Alright, so I just have to try to wrap my brain around what I'm looking at. Again have a tendency to think in high-level, so looking at each instruction and trying to imagine it in the context of a (comparatively simple) instruction, I'm trying to figure out how I might rearrange instructions as needed, but first I need to know what each thing is doing. Thus my need for a disassembly. Since there are 4 JSRs to AA3A (which does the comparison to 100 and if so, sets back to 99), I'm referencing those sections of code below.
CLC ; A874 $18
LDA $47 ; A875 $A5 $47
ADC #$10 ; A877 $69 $10
STA $48 ; A879 $85 $48
CLC ; A87B $18
LDA $4A ; A87C $A5 $4A
ADC #$10 ; A87E $69 $10
STA $4B ; A880 $85 $4B
LDX #$00 ; A882 $A2 $00
LDA $46 ; A884 $A5 $46
JSR $FD11 ; A886 $20 $11 $FD
STA $46 ; A889 $85 $46
LDY $9E ; A88B $A4 $9E
SEC ; A88D $38
LDA ($44),Y ; A88E $B1 $44
BEQ L16903 ; A890 $F0 $71
SBC $46 ; A892 $E5 $46
BCC L16903 ; A894 $90 $6D
LDY $47 ; A896 $A4 $47
LDA ($7A),Y ; A898 $B1 $7A
TAX ; A89A $AA
INX ; A89B $E8
TXA ; A89C $8A
JSR $AA3A ; A89D $20 $3A $AA
STA ($7A),Y ; A8A0 $91 $7A
LDY $48 ; A8A2 $A4 $48
LDA ($7A),Y ; A8A4 $B1 $7A
TAX ; A8A6 $AA
INX ; A8A7 $E8
TXA ; A8A8 $8A
JSR $AA3A ; A8A9 $20 $3A $AA
STA ($7A),Y ; A8AC $91 $7A
LDX $AD ; A8AE $A6 $AD
LDA $47 ; A8B0 $A5 $47
SEC ; A8B2 $38
SBC #$13 ; A8B3 $E9 $13
BEQ L168BD ; A8B5 $F0 $06
BCS L168C1 ; A8B7 $B0 $08
LDA #$5F ; A8B9 $A9 $5F
BNE L168C3 ; A8BB $D0 $06
L168BD:
LDA #$60 ; A8BD $A9 $60
BNE L168C3 ; A8BF $D0 $02
L168C1:
LDA #$61 ; A8C1 $A9 $61
L168C3:
STA $7FBA,X ; A8C3 $9D $BA $7F
INC $AD ; A8C6 $E6 $AD
LDX #$00 ; A8C8 $A2 $00
LDA $49 ; A8CA $A5 $49
JSR $FD11 ; A8CC $20 $11 $FD
BNE L16903 ; A8CF $D0 $32
LDY $4A ; A8D1 $A4 $4A
LDA ($7A),Y ; A8D3 $B1 $7A
CMP #$01 ; A8D5 $C9 $01
BEQ L16903 ; A8D7 $F0 $2A
TAX ; A8D9 $AA
DEX ; A8DA $CA
TXA ; A8DB $8A
STA ($7A),Y ; A8DC $91 $7A
LDY $4B ; A8DE $A4 $4B
LDA ($7A),Y ; A8E0 $B1 $7A
TAX ; A8E2 $AA
DEX ; A8E3 $CA
TXA ; A8E4 $8A
STA ($7A),Y ; A8E5 $91 $7A
LDX $AD ; A8E7 $A6 $AD
LDA $4A ; A8E9 $A5 $4A
SEC ; A8EB $38
SBC #$12 ; A8EC $E9 $12
BEQ A8F6 ; A8EE $F0 $06
BCS A8FA ; A8F0 $B0 $08
LDA #$5F ; A8F2 $A9 $5F
BNE A8FC ; A8F4 $D0 $06
A8F6:
LDA #$63 ; A8F6 $A9 $63
BNE A8FC ; A8F8 $D0 $02
A8FA:
LDA #$60 ; A8FA $A9 $60
A8FC:
ORA #$80 ; A8FC $09 $80
STA $7FBA,X ; A8FE $9D $BA $7F
INC $AD ; A901 $E6 $AD
L16903:
RTS ; A903 $60
;; sub start ;;
CLC ; A904 $18
LDA $46 ; A905 $A5 $46
ADC #$10 ; A907 $69 $10
STA $47 ; A909 $85 $47
LDX #$00 ; A90B $A2 $00
LDA $44 ; A90D $A5 $44
JSR $FD11 ; A90F $20 $11 $FD
STA $48 ; A912 $85 $48
SEC ; A914 $38
LDA $45 ; A915 $A5 $45
BEQ L16955 ; A917 $F0 $3C
SBC $48 ; A919 $E5 $48
BCS L16955 ; A91B $B0 $38
LDY $46 ; A91D $A4 $46
CPY #$11 ; A91F $C0 $11
BEQ L1695B ; A921 $F0 $38
L16923:
LDA ($7A),Y ; A923 $B1 $7A
TAX ; A925 $AA
INX ; A926 $E8
TXA ; A927 $8A
JSR $AA3A ; A928 $20 $3A $AA
STA ($7A),Y ; A92B $91 $7A
LDY $47 ; A92D $A4 $47
LDA ($7A),Y ; A92F $B1 $7A
TAX ; A931 $AA
INX ; A932 $E8
TXA ; A933 $8A
JSR $AA3A ; A934 $20 $3A $AA
STA ($7A),Y ; A937 $91 $7A
LDX $AD ; A939 $A6 $AD
LDA $46 ; A93B $A5 $46
SEC ; A93D $38
SBC #$12 ; A93E $E9 $12
BEQ A948 ; A940 $F0 $06
BCS A94C ; A942 $B0 $08
LDA #$62 ; A944 $A9 $62
BNE A94E ; A946 $D0 $06
A948:
LDA #$63 ; A948 $A9 $63
BNE A94E ; A94A $D0 $02
A94C:
LDA #$64 ; A94C $A9 $64
A94E:
STA $7FBA,X ; A94E $9D $BA $7F
INC $AD ; A951 $E6 $AD
BNE L1695B ; A953 $D0 $06
L16955:
LDY $46 ; A955 $A4 $46
CPY #$11 ; A957 $C0 $11
BEQ L16923 ; A959 $F0 $C8
L1695B:
RTS ; A95B $60
I'm assuming, probably incorrectly, that this entire section is the end-of-battle tallying of the "commands issued" counters, using that to determine if a stat is going up, and then increasing it and decrementing the opposing stat. As for the context of what the game is trying to do, that's where I get lost. Like I can refer to opcodes and figure out what each instruction are doing in a vacuum, but correlating that to the actual outcome in the game's parameters confuses me. You stated before that at A896, Memory @ $47 holds Strength, and then the next line loads that value into the accumulator @ $7A, and then the next line Transfers A into X, then Increments X, then Transfers X to A. So in these 4 lines, data is simply being moved around before the JSR is done to the comparison. In essence, the ideal is for the comparison to be done, I'm assuming, directly after A898?
I'm going to wrack my brain a bit and try to read up on opcodes some more to see if I can't build an image of what's happening here in what order alongside the disassembly you've provided. Bear with me while I spitball. After A898, I would want to compare the stat to 99. IF TRUE THEN jump to a point that skips the increment and decrement code entirely. Which looks to be jumping to... somewhere past A8E9? I still have to figure out what the other instructions are doing before I can make a more educated guess.
Actually, you can see more or less that the code is already doing this to avoid going below 1, so it would just need to be repurposed and applied on the opposite end of the spectrum.
LDA ($7A),Y ; A8D3 $B1 $7A
CMP #$01 ; A8D5 $C9 $01
BEQ L16903 ; A8D7 $F0 $2A
So I would want to have the line directly after A898 be CMP #$63 (A898 $C9 $63), and a BEQ to... somewhere. The side effect to doing these comparisons on the fly and avoiding the increment altogether is that AA3A could be cannibalized, since if code branches on = 99, there'd be no reason to have those several bytes in place to ensure that a stat doesn't go up to 100. That's at least 19 bytes by my count (removing the 4 JSR lines @ 3 bytes apiece, and then the AA3A section itself which is 7 more bytes), so that's a nice chunk of space. If I figure out where the BEQ is pointing (I'd assume Line 16903, but that doesn't correlate to the current format of the disassembly), then I can use that as a guide for how I would fill in the repurposed BEQ and possibly rewrite the Strength Up / Intellect down section. If I can figure that out and test it, then I can start working on the other 2 see-saw stats (Spirit+ / Strength- & Intellect+ / Stamina-).
EDIT: Alright, well I think I see where those branches are pointing to, but...
L16903:
RTS ; A903 $60
The 4 BNE, BEQ, BCC pointing to that address have different values after the opcode. My limited work with branches suggested to me that the address after the opcode should be a pointer which... again, forgive me for being so fresh, points to a specific address? But then those values should be the same for all 4 branch instructions, shouldn't they? Basically I just need to know what hex address to put after the $F0 in my above-mentioned test fix.Never mind, I'm an idiot. Basic deduction (though I probably could have gone and read the manual) led me to find that it's the number of bytes skipped ahead by the branch. So assuming nothing else moves currently (which won't be the case)... 105 bytes between the new BEQ and the RTS we want to skip to. That's $69 so...
Test fix:
...
LDY $47 ; A896 $A4 $47
LDA ($7A),Y ; A898 $B1 $7A
CMP #$63 ; A89A $C9 $63
BEQ L16903 ; A89C $F0 $69
...
Obviously this alone can't be plugged in or the whole thing breaks. I may need to analyze how to nudge this in or put it in some blank space and add a JSR to test it before worrying about moving data around. The issue right now in the way of testing this is offsets. The new instructions require inserting 4 bytes in a place that isn't an issue at first, because the JSR 3 bytes can be removed... But then there's still 1 extra byte offset. Even considering that the 4 JSRs are removed (12 bytes), we're adding 16 bytes, and the longer we wait to fix that offset, the more problems pile up. AA3A is another 7 bytes that can be removed which puts us at -3 bytes (which can be padded easily), but that's quite a ways away. I suppose it's feasible to go through the instructions and make sure there's no bad pointers to test this, which for those 4 I'm guessing it's just... Strength and... actually upon searching through that bank_05 disassembly, there's not enough CMP #$64s or JSR AA3As to suggest there's a routine for each stat. I think it's safe to assume that this section handles all stat increases, and there's surely something that checks a table or such to see if it even needs to decrement another stat.
EDIT: Actually upon further analyzing the comparison that prevents a stat from going below 1, I may be able to save more space, as it only does the comparison once on account of the Branch. I would assume this means the two copies of a stat, despite being separate, will always be identical, because the existing CMP-BEQ only compares once, and if it clears, it does the DEX on each without a second CMP. I may be able to utilize this to save even more space, though that also mandates even more padding. To move as little data as possible, I am now operating under the idea that I will leave AA3A alone (though it will never be used), and to replace the two JSRs per section, (3 + 3) I will simply replace the first one with the new CMP-BEQ (4) and the second one with 2 NOPs (2). This will have a minimal impact on pointers and addresses, and should fix the issue. Going to try and mock up a patch and test it now.
Test Fix:
0x168AA: C9 63 F0 65 AA E8 8A 91 7A A4 48 B1 7A AA E8 8A EA EA
0x16935: C9 63 F0 32 AA E8 8A 91 7A A4 47 B1 7A AA E8 8A EA EA
EDIT: HUZZAH! The above fix appears to work! 16 white magic casts, 46 attacks, and Firion gained neither Spirit nor Strength, which means 99 Spirit = no chance of Strength loss, and 99 Strength = no chance of Intellect loss (and though untested this should also mean 99 Int = no Stamina loss)! I'll make a quick IPS and set it aside to be uploaded later separately or used as part of a bug fix omnibus. With this patch, any stat that reaches 99 will no longer try to increase after a battle if criteria are met. This should apply to Strength, Agility, Stamina, Intellect, Spirit, and M.Power. I don't think this affects Magic Defense or Evasion since they are capped at 16 rather than 99.
FFII Maxed Stat Increase Fix.ips