Users browsing this thread: 1 Guest(s)
Good Lord Send Us An Esper Level Up Bonus Patch

#1
Posts: 61
Threads: 18
Thanks Received: 1
Thanks Given: 47
Joined: May 2014
Status
None
So one of the things I've been trying to do for years now is figure out how to make the esper level up bonuses better.  Does anyone know how?

I've tried to trace another person's mod to no avail.  Here's what I focus on from the C2:


Code:
C2/60E8: 7B           TDC            (Clear 16-bit A)
C2/60E9: BF 0A 6E D8  LDA $D86E0A,X  (end of data block for Esper..  probably
                                     has level-up bonus)
C2/60ED: 30 05        BMI $60F4      (if null, don't try to calculate bonus)
C2/60EF: 0A           ASL
C2/60F0: AA           TAX            (multiply bonus index by 2)
C2/60F1: FC 4E 61     JSR ($614E,X)  (calculate bonus.  note that [Stat]+1 jumps to the
                                     same place as [Stat]+2.  what distinguishes them?
                                     Bit 1 of X.  if X is 20, 24, 28, 32, you'll get +1
                                     to a stat.. if it's 18, 22, 26, 30, you get +2.

                                     for HP/MP boosts, X of 0/2/4 means HP, and
                                     6/8/10 means MP)
                      
C2/60F4: FA           PLX
C2/60F5: 7A           PLY
I think this is the only part that initiates the sequence.

And then there is the calculation:

Code:
(Code Pointers)

C2/614E: 70 61  (~10% HP bonus)  (HP due to X)
C2/6150: 74 61  (~30% HP bonus)  (HP due to X)
C2/6152: 78 61  (50% HP bonus)   (HP due to X)
C2/6154: 70 61  (~10% MP bonus)  (MP due to X)
C2/6156: 74 61  (~30% MP bonus)  (MP due to X)
C2/6158: 78 61  (50% MP bonus)   (MP due to X)  
C2/615A: B0 61  (Double natural HP gain for level.  Curious...)
C2/615C: 97 61  (No bonus)
C2/615E: 97 61  (No bonus)
C2/6160: 9B 61  (Vigor bonus)    (+1 due to X value in caller)
C2/6162: 9B 61  (Vigor bonus)    (+2 due to X)
C2/6164: 9A 61  (Speed bonus)    (+1 due to X)
C2/6166: 9A 61  (Speed bonus)    (+2 due to X.  No Esper currently uses)
C2/6168: 99 61  (Stamina bonus)  (+1 due to X)
C2/616A: 99 61  (Stamina bonus)  (+2 due to X)
C2/616C: 98 61  (MagPwr bonus)   (+1 due to X)
C2/616E: 98 61  (MagPwr bonus)   (+2 due to X)
As you can see, these are pointers to the real calculation.  Espers look here which points to a bonus.

The real calculation is:

Code:
(Esper HP or MP bonus at level-up)

C2/6170: A9 1A        LDA #$1A     (26 => 10.12625% bonus)  
C2/6172: 80 06        BRA $617A
C2/6174: A9 4E        LDA #$4E     (78 => 30.46875% bonus)    
C2/6176: 80 02        BRA $617A
C2/6178: A9 80        LDA #$80     (128 ==> 50% bonus)
C2/617A: E0 06 00     CPX #$0006   (are we boosting MP rather than HP?)
C2/617D: A2 00 00     LDX #$0000   (start pointing to $FC, which holds normal HP to raise)
C2/6180: 90 02        BCC $6184    (if X was less than 6, we're just boosting HP,
                                   so branch)
C2/6182: E8           INX
C2/6183: E8           INX          (point to $FE, which holds normal MP to raise)
C2/6184: EB           XBA          (put boost numerator in top of A)
C2/6185: B5 FC        LDA $FC,X    (get current HP or MP to add)
C2/6187: 20 81 47     JSR $4781    
C2/618A: EB           XBA          (get (boost number * current HP or MP) / 256.
                                   after all, the boost IS a percentage..)
C2/618B: D0 01        BNE $618E    (if the HP/MP bonus is nonzero, branch)
C2/618D: 1A           INC          (if it was zero, be nice and give the chump one..)
C2/618E: 18           CLC
C2/618F: 75 FC        ADC $FC,X
C2/6191: 95 FC        STA $FC,X    (add boost to natural HP/MP gain)
C2/6193: 90 02        BCC $6197    
C2/6195: F6 FD        INC $FD,X    (if bottom byte overflowed from add, boost top byte)
C2/6197: 60           RTS


(Esper stat bonus at level-up.  Vigor, Speed, Stamina, or MagPwr.
If Bit 1 of X is set, give +1 bonus.  If not, give +2.)

C2/6198: C8           INY          (enter here = 3 INYs = point to MagPwr)
C2/6199: C8           INY          (enter here = 2 INYs = point to Stamina)
C2/619A: C8           INY          (enter here = 1 INY  = point to Speed)
C2/619B: 8A           TXA          (enter here = 0 INYs = point to Vigor)

C2/619C: 4A           LSR
C2/619D: 4A           LSR          (Carry holds bit 1 of X)

C2/619E: BB           TYX          (0 to 3 value.  determines which stat will be altered)
C2/619F: BD 1A 16     LDA $161A,X  (at $161A,X we have Vigor, Speed, Stamina, and MagPwr,
                                   respectively)
C2/61A2: 1A           INC
C2/61A3: B0 01        BCS $61A6    (If carry set, just give +1)
C2/61A5: 1A           INC
C2/61A6: C9 81        CMP #$81     (is stat >= 129?)
C2/61A8: 90 02        BCC $61AC
C2/61AA: A9 80        LDA #$80     (if so, make it 128)
C2/61AC: 9D 1A 16     STA $161A,X  (save updated stat)
C2/61AF: 60           RTS
Why....does it increase Y, copy X to A, then maybe make it carry, then copy Y to X, which I think is then used to determine which stat is changed based on what's in X, which is then increased based on the carry?  This seems like an awfully weird way of doing it, and a perfect way from preventing me to change it to what I want.

Ideally, I'm trying to make a version that allows:
Stamina +6
Speed+6
Vigor/Magic +1/+2/+1/+2

And then the HP/MP.....way too complicated. Right? If anyone's figured this out, please show us all the ninja that is inside of you.
  Find
Quote  

#2
Posts: 290
Threads: 3
Thanks Received: 40
Thanks Given: 1
Joined: Apr 2012
Reputation: 9
Status
None
(01-31-2016, 02:49 AM)ReturnerScum Wrote: Why....does it increase Y, copy X to A, then maybe make it carry, then copy Y to X, which I think is then used to determine which stat is changed based on what's in X, which is then increased based on the carry?  This seems like an awfully weird way of doing it, and a perfect way from preventing me to change it to what I want.

Y is simply used as an index here. The game will jump to that series of INYs at a certain spot depending on what stat you're boosting (check the jump table at C2/614E - or more specifically, the part starting at C2/6160).

See the disassembler comments at C2/60F1 for why bit 1 of X is moved into the carry. It's simply so the game knows whether to boost the stat by 1 or 2.

Y is transferred to X after that simply for indexing purposes again. Y was set above with the series of INY instructions - it's going to be a number zero through three, used for determing which stat at $161A in the SRAM to raise.

HP/MP is actually quite a bit simpler as it's written in vanilla (using percentages). The tricky thing to understand here is how it knows to boost HP or MP - it does this by checking the jump index (C2/60F1). X will be equal to 0, 2, or 4 if it's boosting HP, so a check is run to see if X is greater than or equal to six. If it is, then MP is boosted. Otherwise, HP is.

What you want to do isn't difficult, but you will need to re-write the esper bonus function in order to fit it all in efficiently.

I suppose the key to all of this is understanding how indexed (or indirect) jumping and jump tables work.


GET A SILK BAG FROM THE GRAVEYARD DUCK TO LIVE LONGER.

Brave New World
  Find
Quote  
[-] The following 1 user says Thank You to Synchysi for this post:
  • ReturnerScum (01-31-2016)

#3
Posts: 61
Threads: 18
Thanks Received: 1
Thanks Given: 47
Joined: May 2014
Status
None
I think what's really confusing to me is that I can't follow everything from the beginning.  I understand that it's using Y then transferring to X, but why not just increment X?  My biggest roadblock was not being able to track what happens to X throughout the whole code.  Here is the very beginning code again, which starts before my original post:

Code:
C2/60DD: BD 1E 16     LDA $161E,X    (get equipped Esper)
C2/60E0: 30 14        BMI $60F6      (if it's null, don't try to calculate bonuses)
C2/60E2: 5A           PHY
C2/60E3: DA           PHX
C2/60E4: 9B           TXY            (Y will be used to index stats that are boosted
                                     by the $614E call.  i believe it currently points
                                     to offset of character block from $1600)

C2/60E5: 20 93 62     JSR $6293      (X = A * 11d)
C2/60E8: 7B           TDC            (Clear 16-bit A)
C2/60E9: BF 0A 6E D8  LDA $D86E0A,X  (end of data block for Esper..  probably
                                     has level-up bonus)
C2/60ED: 30 05        BMI $60F4      (if null, don't try to calculate bonus)
C2/60EF: 0A           ASL
C2/60F0: AA           TAX            (multiply bonus index by 2)
C2/60F1: FC 4E 61     JSR ($614E,X)  (calculate bonus.  note that [Stat]+1 jumps to the
                                     same place as [Stat]+2.  what distinguishes them?
                                     Bit 1 of X.  if X is 20, 24, 28, 32, you'll get +1
                                     to a stat.. if it's 18, 22, 26, 30, you get +2.

                                     for HP/MP boosts, X of 0/2/4 means HP, and
                                     6/8/10 means MP)
                      
C2/60F4: FA           PLX
C2/60F5: 7A           PLY

The TDC is what signals to me that the A register is cleared so the new esper function is probably starting.  However, note that the new function starts by loading data at $D86E0A,X which is some esper information that most likely has our esper bonus.  What is in X already, and how did it get there?  I surely don't know.  We take whatever was loaded into A and multiply it by 2 via ASL, which is then copied in X via TAX.  We multiplied by two because of the next jump (JSR) which is indexed by X so the jump lands farther based on the X value.  We want it to land on a string of code pointers that each have 2 bytes, so any jump must land on the first byte of each pair in order to land on the correct section of each pointer.  The jump takes us to the range of 614E plus the X and will return when the subroutine is done.

The Code Pointers
Code:
(Code Pointers)

C2/614E: 70 61  (~10% HP bonus)  (HP due to X)
C2/6150: 74 61  (~30% HP bonus)  (HP due to X)
C2/6152: 78 61  (50% HP bonus)   (HP due to X)
C2/6154: 70 61  (~10% MP bonus)  (MP due to X)
C2/6156: 74 61  (~30% MP bonus)  (MP due to X)
C2/6158: 78 61  (50% MP bonus)   (MP due to X)  
C2/615A: B0 61  (Double natural HP gain for level.  Curious...)
C2/615C: 97 61  (No bonus)
C2/615E: 97 61  (No bonus)
C2/6160: 9B 61  (Vigor bonus)    (+1 due to X value in caller)
C2/6162: 9B 61  (Vigor bonus)    (+2 due to X)
C2/6164: 9A 61  (Speed bonus)    (+1 due to X)
C2/6166: 9A 61  (Speed bonus)    (+2 due to X.  No Esper currently uses)
C2/6168: 99 61  (Stamina bonus)  (+1 due to X)
C2/616A: 99 61  (Stamina bonus)  (+2 due to X)
C2/616C: 98 61  (MagPwr bonus)   (+1 due to X)
C2/616E: 98 61  (MagPwr bonus)   (+2 due to X)
These are pointers, but I'm not sure how the computer knows they're pointers.  The only thing we have here are a string of byte pairs that represent addresses to immediately use.  We landed here based on the X value, so whichever esper we had was copied into X and then that value influenced our jump value to bring us to these new pointers which tell us to immediately look at new addresses, based on these byte pairs.


Now for the real calculations:

First is the HP/MP
Code:
(Esper HP or MP bonus at level-up)

C2/6170: A9 1A        LDA #$1A     (26 => 10.12625% bonus)  
C2/6172: 80 06        BRA $617A
C2/6174: A9 4E        LDA #$4E     (78 => 30.46875% bonus)    
C2/6176: 80 02        BRA $617A
C2/6178: A9 80        LDA #$80     (128 ==> 50% bonus)
C2/617A: E0 06 00     CPX #$0006   (are we boosting MP rather than HP?)
C2/617D: A2 00 00     LDX #$0000   (start pointing to $FC, which holds normal HP to raise)
C2/6180: 90 02        BCC $6184    (if X was less than 6, we're just boosting HP,
                                   so branch)
C2/6182: E8           INX
C2/6183: E8           INX          (point to $FE, which holds normal MP to raise)
C2/6184: EB           XBA          (put boost numerator in top of A)
C2/6185: B5 FC        LDA $FC,X    (get current HP or MP to add)
C2/6187: 20 81 47     JSR $4781    
C2/618A: EB           XBA          (get (boost number * current HP or MP) / 256.
                                   after all, the boost IS a percentage..)
C2/618B: D0 01        BNE $618E    (if the HP/MP bonus is nonzero, branch)
C2/618D: 1A           INC          (if it was zero, be nice and give the chump one..)
C2/618E: 18           CLC
C2/618F: 75 FC        ADC $FC,X
C2/6191: 95 FC        STA $FC,X    (add boost to natural HP/MP gain)
C2/6193: 90 02        BCC $6197    
C2/6195: F6 FD        INC $FD,X    (if bottom byte overflowed from add, boost top byte)
C2/6197: 60           RTS
These are percentages and branches and some maneuvering which I haven't fully cared to figure out.  It's easy enough to change the percentages by changing the LDA values.

Now we have the stat bonuses:
Code:
(Esper stat bonus at level-up.  Vigor, Speed, Stamina, or MagPwr.
If Bit 1 of X is set, give +1 bonus.  If not, give +2.)

C2/6198: C8           INY          (enter here = 3 INYs = point to MagPwr)
C2/6199: C8           INY          (enter here = 2 INYs = point to Stamina)
C2/619A: C8           INY          (enter here = 1 INY  = point to Speed)
C2/619B: 8A           TXA          (enter here = 0 INYs = point to Vigor)

C2/619C: 4A           LSR
C2/619D: 4A           LSR          (Carry holds bit 1 of X)

C2/619E: BB           TYX          (0 to 3 value.  determines which stat will be altered)
C2/619F: BD 1A 16     LDA $161A,X  (at $161A,X we have Vigor, Speed, Stamina, and MagPwr,
                                   respectively)
C2/61A2: 1A           INC
C2/61A3: B0 01        BCS $61A6    (If carry set, just give +1)
C2/61A5: 1A           INC
C2/61A6: C9 81        CMP #$81     (is stat >= 129?)
C2/61A8: 90 02        BCC $61AC
C2/61AA: A9 80        LDA #$80     (if so, make it 128)
C2/61AC: 9D 1A 16     STA $161A,X  (save updated stat)
C2/61AF: 60           RTS
We're going to load $161A,X into A.  Apparently $161A = Vigor, $161B = Speed, $161C = Stamina, and $161D = Magic Power, because we load these indexed by X which will be from 0 to 3.  First we increment Y by 1 via INY and do this as many times (based on where our code pointers take us) as we need until we have the value 0 to 3 desired for X.  We copy X to A then shift A to the right twice, which, I believe, pushes the entire value out of the accumulator.  This puts the value of bit 1 of X into the Carry (which I don't know anything about), or at least sets the carry flag.  Then we copy Y to X, so we now have that 0 to 3 value finally in X.  C2/619F is where we load $161A,X to get our vigor, speed, stamina, or magic power statistic.  The INC increases A by 1, so we're increasing the stat.  Then we branch if the carry flag was set, which hops over another increase of the stat.  So the carry flag is set by a double logical shift right (LSR) of whatever was in bit 1 of X (which I still don't know what it is) and that is what determines if you get +1 or +2 to the stat.

After that we just have some comparison to 129 which leads to the stat being turned into 128, and the stat is then stored back into $161A,X, which is probably where the stats for all heroes are stored.

And with this knowledge, we have enough to change those measly Stamina and Vigor bonuses into +6.....

Now we're going to add an extra equation that's just like the last one for boosting stats, but instead it only boosts vigor and speed by +6.
To do this, we need free space.  This means space that is probably FFFF all over.  I checked the handy Izmogelmo's "Patch Allocation Free Space Usage" document that locates the code spaces used by other author's patches, and notes where free space still resides.

I found 110 bytes free at C2/6760, so I started the journey there.

But first! We change the pointers to point to our new code:

Code:
C2/6164: 61 67  (Speed bonus)    (+6 due to X)
C2/6166: 61 67  (Speed bonus)    (+6 due to X.  No Esper currently uses)
C2/6168: 60 67  (Stamina bonus)  (+6 due to X)
C2/616A: 60 67  (Stamina bonus)  (+6 due to X)

So the speed and stamina bonus pointers are now at the first and second spots of the new code.

Code:
C2/6760: C8           INY          (enter here = 2 INYs = point to Stamina)
C2/6161: C8           INY          (enter here = 1 INY  = point to Speed)
C2/6162: 8A           TXA          (enter here = 0 INYs = point to Vigor)

C2/6163: BB           TYX          (0 to 3 value.  determines which stat will be altered)
C2/6164: BD 1A 16     LDA $161A,X  (at $161A,X we have Vigor, Speed, Stamina, and MagPwr,
                                    respectively)
C2/6167: 1A           INC
C2/6168: 1A           INC
C2/6169: 1A           INC
C2/616A: 1A           INC
C2/616B: 1A           INC
C2/616C: 1A           INC
C2/616D: C9 81        CMP #$E7     (is stat >= 231?)
C2/616F: 90 02        BCC $6172
C2/6170: A9 80        LDA #$E6     (if so, make it 230)
C2/6172: 9D 1A 16     STA $161A,X  (save updated stat)
C2/6175: 60           RTS

So this is our new code, where we have the same process but instead of worrying about the carry flag, we just increase A six times.  Because Speed has problems around 231 and more (I believe it's actually 236), we've changed the ceilings for the stamina and speed stats to be 230.

Now changing esper bonuses is finally within our grasp. All you have to do is go into FF3USME and give espers any of the speed+ or stamina+ bonuses, and our heroes will get 6 points at level up!  The speed and stamina statistics can now grow at a rate that makes them a bit more worthwhile, reducing their stature as a deadweight stat.
  Find
Quote  

#4
Posts: 259
Threads: 3
Thanks Received: 5
Thanks Given: 1
Joined: Jun 2013
Reputation: 6
Status
None
I should point out that earlier versions of Brave New World did pretty much exactly what you're doing right here - we had obscene gains for Stamina because it was dead weight otherwise. What we eventually ended up doing was re-writing the formulas that use them so that each stat actually *is* useful.


"You don't have to be a vampire to die like one... b*t*h." -Simon Belmont
Quote  

#5
Posts: 61
Threads: 18
Thanks Received: 1
Thanks Given: 47
Joined: May 2014
Status
None
Yes the most important question is about game design and not values.  While I'm sure we all would love to have stamina and speed affect other parts of the game, that takes a considerable amount of skill and knowledge.  I do think it is possible for an inexperienced hacker to make stamina and speed useful with much more ease, although less scope.  Stamina can be used to resist magic and ailments, and increase regen.  Speed is much harder.  My doubling of the effects of Slow and Haste make speed much more useful, but changing the speed formula, which is already quite elegant, into something more practical isn't intuitive to me.  Speed has a very logarithmic scale and I believe some technicalities exist which make the hero's battle gauge less reliable than it should be.
  Find
Quote  

#6
Posts: 110
Threads: 4
Thanks Received: 4
Thanks Given: 1
Joined: Jan 2012
Reputation: 4
Status
None
Speed is fixed by making the ATB system work as it did in FFIV. Animations not locking down the ATB bar was a poor design decision.
  Find
Quote  
[-] The following 1 user says Thank You to dn for this post:
  • Robo Jesus (07-24-2019)

#7
Posts: 259
Threads: 3
Thanks Received: 5
Thanks Given: 1
Joined: Jun 2013
Reputation: 6
Status
None
Yeah, stamina has a greatly expanded role in Brave New World. I imagine quite a few of the things we've done with it would do well as standalone hacks (Synchysi hasn't released much in the way of that since, as you can imagine, not a lot of what we've done really does well as a standalone hack).


"You don't have to be a vampire to die like one... b*t*h." -Simon Belmont
Quote  

#8
Posts: 290
Threads: 3
Thanks Received: 40
Thanks Given: 1
Joined: Apr 2012
Reputation: 9
Status
None
(02-11-2016, 06:09 PM)ReturnerScum Wrote: I think what's really confusing to me is that I can't follow everything from the beginning.  I understand that it's using Y then transferring to X, but why not just increment X?  My biggest roadblock was not being able to track what happens to X throughout the whole code.

There's typically a reason they use X instead of Y or vice versa, generally related to common functions - in this case the JSR $6293. This subroutine Multiplies A * 11 and stores the result in X. It's used in multiple places, which forces the calling functions to use X as the resulting index.

So X starts out as the pointer to the equipped esper of the character in question, then has its value transferred to Y. X then becomes the esper bonus index of the esper in question.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: The TDC is what signals to me that the A register is cleared so the new esper function is probably starting.  However, note that the new function starts by loading data at $D86E0A,X which is some esper information that most likely has our esper bonus.  What is in X already, and how did it get there?  I surely don't know.

The commentary two lines before that (JSR $6293) tells you what's in X, as I mentioned above.

Esper data in the ROM starts at D8/6E00, and is eleven bytes. That's eleven bytes of data per esper sorted thusly:

Code:
$0000                               Spell 1 learn rate
$0001                               Spell 1
$0002                               Spell 2 learn rate
$0003                               Spell 2
$0004                               Spell 3 learn rate
$0005                               Spell 3
$0006                               Spell 4 learn rate
$0007                               Spell 4
$0008                               Spell 5 learn rate
$0009                               Spell 5
$000A                               Bonus at level up

So that's why we get the esper ID and multiply it by eleven - because every eleventh byte starting at D8/6E0A will be the bonus for whatever esper we're looking at.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: These are pointers, but I'm not sure how the computer knows they're pointers.

Because of the way we access them. This block never gets executed directly - it's only access via indexed jump, which will always treat whatever it jumps to as a pointer.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: These are percentages and branches and some maneuvering which I haven't fully cared to figure out.  It's easy enough to change the percentages by changing the LDA values.

The maneuvering here is simply for the sake of efficiency. We can go over this later if you want.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: We're going to load $161A,X into A.  Apparently $161A = Vigor, $161B = Speed, $161C = Stamina, and $161D = Magic Power, because we load these indexed by X which will be from 0 to 3.

This is... almost true. This is another case of an info block, just like the eleven-byte block for espers we discussed above. Take a look at the RAM map here: https://www.ff6hacking.com/forums/showth...p?tid=1408

Character data starts at $1600 and is 37 bytes long per character. The first 37 bytes are for Terra, then the next 37 are for Locke, then Cyan, then Shadow, etc. So we can assume that some time ago, X was loaded with (character ID * 37) for the sake of accessing this character info block. It's true that $161A = vigor, but only for Terra. The easier way to read it would be:

$161A + (character ID * 37) = vigor

(02-11-2016, 06:09 PM)ReturnerScum Wrote: We copy X to A then shift A to the right twice, which, I believe, pushes the entire value out of the accumulator.  This puts the value of bit 1 of X into the Carry (which I don't know anything about), or at least sets the carry flag.  Then we copy Y to X, so we now have that 0 to 3 value finally in X.  C2/619F is where we load $161A,X to get our vigor, speed, stamina, or magic power statistic.  The INC increases A by 1, so we're increasing the stat.  Then we branch if the carry flag was set, which hops over another increase of the stat.

The accumulator and index registers carry with them several flags that change depending on multiple factors. One of those flags is the carry flag. It has a multitude of uses, from overflow identification to conditional branching (such as here).

It may be easiest to consider the carry flag as an extra bit that sets off to the right of your working register (typically the accumulator). LSR will discard the carry and move the lowest bit of A into the carry, while ASL will move the carry into the lowest bit of A and discards the highest bit of A (more information on these instructions and others here. In this case, two LSRs actually move bit 1 of A into the carry (note the TXA at C2/619B), and then branches depending on whether or not the carry was set.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: So the carry flag is set by a double logical shift right (LSR) of whatever was in bit 1 of X (which I still don't know what it is) and that is what determines if you get +1 or +2 to the stat.

I'm not too sure what you're confused about here, since you went over it in one of the tutorial threads you made. Note the commentary at C2/60F1:

Code:
C2/60F1: FC 4E 61     JSR ($614E,X)  (calculate bonus.  note that [Stat]+1 jumps to the
                                     same place as [Stat]+2.  what distinguishes them?
                                     Bit 1 of X.  if X is 20, 24, 28, 32, you'll get +1
                                     to a stat.. if it's 18, 22, 26, 30, you get +2.

                                     for HP/MP boosts, X of 0/2/4 means HP, and
                                     6/8/10 means MP)

Just translate X into binary, then shift all the bits to the right twice (two LSRs). X at this point contains the esper bonus index * 2, and the values work out this way due to the way they're laid out in the jump table.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: But first! We change the pointers to point to our new code:

There's no sense in having two speed and stamina pointers here with the same bonus, so you can free up two of those for future expansion if you really wanted to.

(02-11-2016, 06:09 PM)ReturnerScum Wrote: So this is our new code, where we have the same process but instead of worrying about the carry flag, we just increase A six times.  Because Speed has problems around 231 and more (I believe it's actually 236), we've changed the ceilings for the stamina and speed stats to be 230.

It would be more efficient to clear the carry, then add 6 rather than using INC six times:

Code:
C2/6164: BD 1A 16     LDA $161A,X  (at $161A,X we have Vigor, Speed, Stamina, and MagPwr,
                                   respectively)
C2/6167: 18           CLC
C2/6168: 69 06        ADC #$06
C2/616A: C9 81        CMP #$E7     (is stat >= 231?)
C2/616C: 90 02        BCC $6172
C2/616E: A9 80        LDA #$E6     (if so, make it 230)
C2/6170: 9D 1A 16     STA $161A,X  (save updated stat)
C2/6173: 60           RTS

CLC = clear carry
ADC = add with carry

The reason we CLC before the ADC is because if the carry is set, it'll add an additional 1 to your value. So we clear it beforehand to prevent that from happening.


GET A SILK BAG FROM THE GRAVEYARD DUCK TO LIVE LONGER.

Brave New World
  Find
Quote  
[-] The following 1 user says Thank You to Synchysi for this post:
  • ReturnerScum (02-12-2016)

#9
Posts: 281
Threads: 18
Thanks Received: 13
Thanks Given: 8
Joined: Mar 2014
Reputation: 8
Status
None
(02-12-2016, 04:06 AM)BTB Wrote: Yeah, stamina has a greatly expanded role in Brave New World. I imagine quite a few of the things we've done with it would do well as standalone hacks (Synchysi hasn't released much in the way of that since, as you can imagine, not a lot of what we've done really does well as a standalone hack).

I strongly disagree! Smile There are a ton of little fixes in BNW that would work great in an otherwise vanilla game, and that I'd really like to see released as standalone patches. Things like the Heal Rod targeting, Sketch using the Sketcher's stats, Poison not resetting it's incrementor with removal of the status, Earrings not affecting Healing spells and many many other things that I've forgotten. I would love to see notes and code, even if Synchysi's notes are a mess and his code is uncommented it would be so helpful.

BNW is a goldmine of nifty little fixes and tweaks that should've been in the original game. Pandora's Box is the same, only much worse because the developers seem to have dropped the project. So much great work undocumented and unreleased. :/
  Find
Quote  
[-] The following 1 user says Thank You to seibaby for this post:
  • Robo Jesus (01-01-2018)

#10
Posts: 81
Threads: 4
Thanks Received: 6
Thanks Given: 6
Joined: Nov 2009
Reputation: 14
Status
Weakness
(03-07-2016, 06:14 AM)seibaby Wrote: BNW is a goldmine of nifty little fixes and tweaks that should've been in the original game. Pandora's Box is the same, only much worse because the developers seem to have dropped the project. So much great work undocumented and unreleased. :/

It's funny you should say that. While we worked on PB, we made several little fixes, tweaks, and engine extensions that we thought "hey, this would make a great standalone patch". A few of those did ultimately get released, although many did not, partly because we have relocated entire banks of code and data to make room for our planned changes, such as a whole new bank for just battle code, and a whole new bank for events, and an entire bank for monster AI. (note to those who have moved the monster AI: without some code changes your scripts won't work beyond 8000h in a bank, due to the way that it merely reads the top byte to know if a counter should fire... my solution was to have it look for FFh in the top byte instead, so you can go all the way to FEFF with no problems (and hey, just use the last 256 bytes for your pointer table or something).

Another reason is that, eventually you've made so many changes, it get hard to disentangle them from one another. For instance, making every spell, attack, and other check compatible with 24-bit monster HP gets your code into a lot of otherwise unrelated spots. Then you have code that can access a whole 2nd set of 256 types of items, which hooks into even more code. You're also fixing bugs and making those play nicely while trying not to step all over other code. Some of the code is in assembly files; other code is just old hand-edits from antiquity... it gets hard to maintain. Oh, and then real life....


I appreciate the prayers and good wishes. Those who don't know, I was diagnosed with stage 4 melanoma in 2019, and I have done well with the treatment, but eventually treatments stop working and you change.  I recently had a seizure at work, now I am healing but not able to work or really do much at all. The focus is just to get better. Again, thanks for the support and if I can help you I will.  I've forgotten more about this game than most people should ever learn, lol.
  Find
Quote  



Forum Jump:

Users browsing this thread: 1 Guest(s)


Theme by Madsiur2017Custom Graphics by JamesWhite