Vampire spell in FFV is busted. It allows more HP to be drained than the target holds! 😔 I would like to fix this behaviour, as it makes at least 2 bosses very OP in FF5r Clean.

image.png

Some comparison w the target’s current HP will need to occur: will need to JMP out to a new subroutine to capture the target’s HP and then drain no more than this value.

ASM Reference

Initial Analysis of Vampire

; [ attack effect $6D: vampire ]

C2/78FA: 20 F6 7E     JSR $7EF6  ; <= chance to hit with magic
C2/78FD: A5 56        LDA $56
C2/78FF: D0 19        BNE $791A
C2/7901: C2 20        REP #$20
C2/7903: A6 32        LDX $32
C2/7905: 38           SEC 
C2/7906: BD 08 20     LDA $2008,X
C2/7909: FD 06 20     SBC $2006,X
C2/790C: 4A           LSR 
C2/790D: 85 50        STA $50
C2/790F: 7B           TDC 
C2/7910: 85 54        STA $54
C2/7912: 1A           INC 
C2/7913: 85 52        STA $52
C2/7915: E2 20        SEP #$20
C2/7917: 20 26 89     JSR $8926  ; <= "calculate damage"
C2/791A: 60           RTS 

C2/8926

; [  ]

C2/8926: 20 F8 93     JSR $93F8       ; <= calculate damage
C2/8929: A6 49        LDX $49
C2/892B: BD 65 20     LDA $2065,X
C2/892E: 29 01        AND #$01
C2/8930: D0 07        BNE $8939
C2/8932: BD 39 20     LDA $2039,X
C2/8935: 29 02        AND #$02
C2/8937: F0 0A        BEQ $8943
C2/8939: AE 69 7B     LDX $7B69
C2/893C: 8E 6B 7B     STX $7B6B
C2/893F: 8E 71 7B     STX $7B71
C2/8942: 60           RTS 
C2/8943: AE 69 7B     LDX $7B69
C2/8946: 8E 6D 7B     STX $7B6D
C2/8949: 8E 6F 7B     STX $7B6F
C2/894C: 60           RTS 

Another subroutine is immediatey referenced by this one…

C2/93F8

This is the one that allows for more damage than the target has current HP.

Fixing this spell’s behavior means using another code block!

; [ calculate damage ]

; damage = (attack - defense) * multiplier, max 9999

C2/93F8: C2 20        REP #$20
C2/93FA: 38           SEC 
C2/93FB: A5 50        LDA $50         ; attack - defense
C2/93FD: E5 54        SBC $54
C2/93FF: F0 02        BEQ $9403
C2/9401: B0 07        BCS $940A
C2/9403: 7B           TDC 
C2/9404: 8D 69 7B     STA $7B69
C2/9407: E2 20        SEP #$20
C2/9409: 60           RTS 
C2/940A: 85 2A        STA $2A
C2/940C: A5 52        LDA $52         ; damage multiplier
C2/940E: D0 01        BNE $9411
C2/9410: 1A           INC             ; min 1
C2/9411: 85 2C        STA $2C
C2/9413: 7B           TDC 
C2/9414: E2 20        SEP #$20
C2/9416: 20 D2 00     JSR $00D2       ; +++$2E = +$2A * +$2C
C2/9419: A6 2E        LDX $2E
C2/941B: E0 0F 27     CPX #$270F      ; max damage is 9999 ! This is the issue
C2/941E: 90 03        BCC $9423
C2/9420: A2 0F 27     LDX #$270F
C2/9423: 8E 69 7B     STX $7B69
C2/9426: 60           RTS 

OK, so this looks very usable with a specific modification: the max damage needs to change to reflect the current HP!

So the exact ASM at C2/941B is assigning a value of 9999, by comparing X register’s number to the value $270F. Yet seeing that ā€œ#ā€ in this disassembly notation means that it’s a literal value, it’s not looking at somewhere else in the ROM.

Is $270F the same as 9999 in decimal?

image.png

Hell yeah, I’m really getting somewhere with this analysis!

So an exact copy of this ā€œcalculate damageā€ code block that caps the max damage differently is my solution at this time. When I have more skill I can attempt to reuse this code block and do an IF → THEN determination about if the ability wants to have a 9999 damage cap or a current HP damage cap.

But for now, as I’m still building competency with writing logic in ASM, I’m going to literally copy this entire code block somewhere else in the rom, and then have the Vampire routine point to this new version instead!