Users browsing this thread: 2 Guest(s)
Condensing Spell List in Battle
10-05-2017, 01:15 AM
Hah, I like that. I may sit down with it and see if I can work out my own solution for it, too, just as an exercise.
Barring any further optimisations, this should be the definitive version of the patch; the first function is down to 77 bytes, and the second is down to 79.
Barring any further optimisations, this should be the definitive version of the patch; the first function is down to 77 bytes, and the second is down to 79.
Code:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Condensed Spell Lists v1.5
; Author: Gray Shadows (in.the.afterlight@gmail.com
; Applies to Final Fantasy 3/6us v1.0
;
; Urgency: Low - QoL enhancement
;
; Contributors: assassin (code support and optimisation)
; seibaby (testing and problem solving)
; Warrax (testing and bug identification)
;
; In vanilla FF6, because of the way the game builds spell lists in
; battle, if one character in battle knows a lot of spells and another
; character doesn't, that second character will have a lot of blank
; space in their Magic menu. Condensed Spell Lists adds some additional
; code to battle initialisation that takes a character's spell list
; and 'shuffles' it up, so that all of the blank spots are at the end.
; It also resorts the Lore list in the same manner.
;
; Version 1.5 update includes: bugfixes, including an error introduced
; wherein monster abilities were incorrectly costing MP, as well as a
; fatal crashing error caused by Interceptor counter-attacks. The hack
; should now properly account for all abilities that use the Magic
; command but do not cast from a character's spell list. (This should
; only be Interceptor counter-attacks, and possibly Desperation Attacks.)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
hirom
;header
!freespace_C2_0 = $C2A65A ; 77 bytes needed
!freespace_C2_1 = $C2FAB0 ; 79 bytes needed
org $C2256D
JSR condenseSpellLists
; This was originally a JSR to modify available commands; we'll be JMPing to
; that at the end of the modified code so that RTS comes back to the right spot.
org $C24F2E
JMP calculateMPDeduction
; This jumps in the middle of a function at C2/4F08 that grabs the MP cost for
; a spell. A character's individual spell list in battle stores a modified MP
; cost based on modifying relics, and as we're reshuffling the list, we need to
; add additional code to make sure that the game looks for MP costs in the right
; location.
;
;
org !freespace_C2_0
print " "
print "New function CondenseSpellLists starts at: ",pc
reset bytes
condenseSpellLists:
PHX ;
PHP
LDY #$04 ; The 0 index in the list holds the equipped esper, which we're not touching.
; Each entry is four bytes long, so the spell list starts at Y = 4.
.noMoreSpells ; We'll be branching back here to execute our Lore list
TYX ; X is going to be our 'write-space' index, whereas Y is our 'read-space' index.
REP #$10
.checkSpellLoop
LDA ($F2),Y
INC
BNE .checkNextSpell
.findNextSpell
INY #4
CPY #$00DC ; If we've hit the first Lore slot, there are no more spells to copy back,
BEQ .noMoreSpells ; so jump out, reset X to start sorting the Lore list instead.
CPY #$013C ; This is after the last Lore slot, so if we've gone that far, there are
BEQ .noMoreLores ; no more spells to copy back and we can exit the function entirely.
LDA ($F2),Y
INC
BEQ .findNextSpell
PHY ; we'll be pushing and pulling within the loop, but we need to know
; where it started so we can blank out the slot we copied from
CLC
REP #$20
.copyNextSpell
LDA ($F2),Y
PHY ; This stores our Y location, i.e. the next slot with a spell learned
TXY ; and pulls our X, or the blank slot we're writing to.
STA ($F2),Y
PLY ; back to our 'write from' location
INY #2 ; and gets the next bytes
INX #2
BCS .doneCopy
SEC
BPL .copyNextSpell ; if we haven't done four bytes, loop back and grab the next
.doneCopy
SEP #$20
PLY ; this is the first byte of the slot we copied from
TDC
STA ($F4),Y ; this zeroes out the MP cost
DEC
STA ($F2),Y ; and blanks out the spell we copied from
BRA .weCopiedASpell
.checkNextSpell
INX #4
.weCopiedASpell
TXY ; and then copy it over to Y for our next loop through
CPY #$0138
BNE .checkSpellLoop
.noMoreLores
PLP
PLX
JMP $532C
print "CondenseSpellLists ends at: ",pc," and used ",bytes," bytes of space."
print " "
org !freespace_C2_1
calculateMPDeduction:
print "New function CalculateMPDeduction starts at: ",pc
reset bytes
LDA $3A7A ; (get command #)
CMP #$19
BEQ .calculateSummon ; (branch if it's Summon)
CMP #$0C
BEQ .calculateLore ; (branch if it's Lore)
.calculateMagic
LDA $3A7B ; (get attack #)
CMP #$F0 ; is it a Desperation Attack or an Interceptor counter?
BCS fka_4F53 ; if so, exit
STA $F0 ; save our spell ID in scratch memory
LDA #$04 ; four bytes per index, and we're starting at the second index in
; the list (i.e. the first Magic spell)
.loreEntersHere
REP #$20
CLC
ADC $302C,X ; get the start of our character's magic list (index #0 is esper)
STA $F2 ; this points out our first Magic slot
INC #3
STA $F4 ; and this points at our first MP cost slot
SEP #$20
PHY
LDY $00
.findSpell
LDA ($F2),Y
CMP $F0
BEQ .getMPCost
INY #4
BRA .findSpell
.getMPCost
LDA ($F4),Y
PLY
BRA fka_4F45
.calculateLore
LDA $3A7B ; (get attack #)
SEC
SBC #$8B ; turn our raw spell ID into a 0-23 Lore ID
STA $F0
LDA #$DC ; this is our first Lore slot in the character's spell list
BRA .loreEntersHere
.calculateSummon
TDC ; By zeroing A, we can just jump back into the vanilla code
JMP $4F38 ; and it will load the MP cost from the first index in the list,
; i.e. the equipped esper, which SHOULD be the only ability being
; cast with the Summon command.
fka_4F45: JMP $4F54 ; (clean up stack and exit)
fka_4F53: JMP $4F53
print "CalculateMPDeduction ends at: ",pc," and used ",bytes," bytes of space."
print " "
« Next Oldest | Next Newest »
Users browsing this thread: 2 Guest(s)