Users browsing this thread: 2 Guest(s)
Condensing Spell List in Battle
09-16-2017, 11:12 PM
(This post was last modified: 09-17-2017, 01:46 AM by GrayShadows.)
Hmm. So I tackled the optimisation first, assassin, based on your suggestion about using two indices -- I think I did basically the opposite of what you suggested, but it's definitely working.
Any suggestions on optimising it further? If this looks good, I'll swap it over for Lore sorting, too.
I'm sitting down with C2/4F08 now to figure out what I can do with that.
AHAHAHAHA I DID IT. Optimised the sorting per before (and sorting Lore again, as well), and MP deduction is working properly for Lore, Magic, and Espers, including with MP-cost adjusting relics.
If you're curious about jumping to 16-bit accumulator and back during sorting the Lores, it's because otherwise $F0 increments in 8-bit, which breaks the game, oops. I'm happy to take suggestions on improving that section.
Code:
org !freespace_C2_0
CondenseSpellLists:
PHX ; This is our character ID coming in
LDY #$04 ; the #0 index in our list is the esper; the character's magic list starts at index 4
STY $F0 ; earlier, $F0 stores number of spells a characters knows, but it shoooould be free to use here, let's test it and see if something breaks
; now it's going to be our "last open spot" index for our loop
LDX #$34 ; this is our main loop index; we're checking 53 slots for a total of 54 spells
.checkSpellLoop
LDA ($F2),Y
CMP #$FF
BNE .checkNextSpell
PHX
LDX #$03
.findNextSpell
INY #4
CPY #$DC ; this is the first Lore slot, so if we've gone that far, there are no more spells to copy back
BEQ .noMoreSpells
LDA ($F2),Y
CMP #$FF
BEQ .findNextSpell
PHY ; set aside the starting byte for the spell we found
; 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
.copyNextSpell
LDA ($F2),Y ; Yes, we just did this, but we need to do it within this loop, too
PHY ; this stores our Y location, i.e. the next slot with a spell learned
LDY $F0 ; and loads our index for slot to write to
STA ($F2),Y
PLY ; back to our 'write from' location
INY ; and gets the next byte
INC $F0 ; while getting our next write-to byte, too. on the last loop,
; this will get set to the first byte of the next spell slot (which
DEX
BPL .copyNextSpell ; if we haven't done four bytes, loop back and grab the next
PLY ; this is the first byte of the slot we copied from
LDA #$FF
STA ($F2),Y ; this blanks out the spell we copied from
LDA #$00
STA ($F4),Y ; and zeroes out the MP cost
PLX ; this gets our index for the loop -- how many spell slots we've checked
BRA .weCopiedASpell
.checkNextSpell
INC $F0 ; if we DIDN'T copy a spell, we need to increment our 'current slot' index
INC $F0 ; but if we did, the loop already has it pointing to the next slot
INC $F0
INC $F0
.weCopiedASpell
LDY $F0 ; and then copy it over to Y for our next loop through
DEX
BPL .checkSpellLoop
BRA .earlyExit
.noMoreSpells
PLX ; if we exited early because there were no more spells to check, we need
; to make sure we settle up our stack -- exit early bypasses a PLX
.earlyExit
PLX
JMP $532C
Any suggestions on optimising it further? If this looks good, I'll swap it over for Lore sorting, too.
I'm sitting down with C2/4F08 now to figure out what I can do with that.
AHAHAHAHA I DID IT. Optimised the sorting per before (and sorting Lore again, as well), and MP deduction is working properly for Lore, Magic, and Espers, including with MP-cost adjusting relics.
Code:
hirom
;header
!freespace_C2_0 = $C2A65A
!freespace_C2_1 = $C2FAB0
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 $C24F11
REP #$10
LDA $3A7B ; (get attack #) -- the new code will do this again in a bit, but
CPX #$0008 ; we need it in A now or we'll break monster casting
BCS fka_4F47 ; (branch if it's a monster attacker. they don't have
; menus containing MP data, nor relics that can
; alter MP costs.)
; This was originally in the middle of the code, but
; there shouldn't be any issues doing this check first,
; and it makes the new code MUCH smoother.
JMP calculateMPDeduction
org $C24F47
fka_4F47:
org !freespace_C2_0
condenseSpellLists:
PHX ; This is our character ID coming in
LDY #$04 ; the #0 index in our list is the esper; the character's magic list starts at index 4
STY $F0 ; earlier, $F0 stores number of spells a characters knows, but it shoooould be free to use here, let's test it and see if something breaks
; now it's going to be our "last open spot" index for our loop
LDX #$34 ; this is our main loop index; we're checking 53 slots for a total of 54 spells
.checkSpellLoop
LDA ($F2),Y
CMP #$FF
BNE .checkNextSpell
PHX
LDX #$03
.findNextSpell
INY #4
CPY #$DC ; this is the first Lore slot, so if we've gone that far, there are no more spells to copy back
BEQ .noMoreSpells
LDA ($F2),Y
CMP #$FF
BEQ .findNextSpell
PHY ; set aside the starting byte for the spell we found
; 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
.copyNextSpell
LDA ($F2),Y ; Yes, we just did this, but we need to do it within this loop, too
PHY ; this stores our Y location, i.e. the next slot with a spell learned
LDY $F0 ; and loads our index for slot to write to
STA ($F2),Y
PLY ; back to our 'write from' location
INY ; and gets the next byte
INC $F0 ; while getting our next write-to byte, too. on the last loop,
; this will get set to the first byte of the next spell slot (which
DEX
BPL .copyNextSpell ; if we haven't done four bytes, loop back and grab the next
PLY ; this is the first byte of the slot we copied from
LDA #$FF
STA ($F2),Y ; this blanks out the spell we copied from
LDA #$00
STA ($F4),Y ; and zeroes out the MP cost
PLX ; this gets our index for the loop -- how many spell slots we've checked
BRA .weCopiedASpell
.checkNextSpell
INC $F0 ; if we DIDN'T copy a spell, we need to increment our 'current slot' index
INC $F0 ; but if we did, the loop already has it pointing to the next slot
INC $F0
INC $F0
.weCopiedASpell
LDY $F0 ; and then copy it over to Y for our next loop through
DEX
BPL .checkSpellLoop
BRA .earlyExit
.noMoreSpells
PLX ; if we exited early because there were no more spells to check, we need
; to make sure we settle up our stack -- exit early bypasses a PLX
.earlyExit
PHP
REP #$10
LDY #$00DC ; this is the index of the first Lore slot in the character's spell list
STY $F0 ;
LDX #$0016 ; this is our main loop index; we're checking 53 slots for a total of 54 spells
.checkLoreLoop
LDA ($F2),Y
CMP #$FF
BNE .checkNextLore
PHX
LDX #$0003
.findNextLore
INY #4
CPY #$013C ; this is after the last Lore slot, so if we've gone that far, there are no more spells to copy back
BEQ .noMoreLores
LDA ($F2),Y
CMP #$FF
BEQ .findNextLore
PHY ; set aside the starting byte for the spell we found
; 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
.copyNextLore
LDA ($F2),Y ; Yes, we just did this, but we need to do it within this loop, too
PHY ; this stores our Y location, i.e. the next slot with a spell learned
LDY $F0 ; and loads our index for slot to write to
STA ($F2),Y
PLY ; back to our 'write from' location
INY ; and gets the next byte
REP #$20
INC $F0 ; while getting our next write-to byte, too. on the last loop,
; this will get set to the first byte of the next spell slot (which
SEP #$20
DEX
BPL .copyNextLore ; if we haven't done four bytes, loop back and grab the next
PLY ; this is the first byte of the slot we copied from
LDA #$FF
STA ($F2),Y ; this blanks out the spell we copied from
LDA #$00
STA ($F4),Y ; and zeroes out the MP cost
PLX ; this gets our index for the loop -- how many spell slots we've checked
BRA .weCopiedALore
.checkNextLore
REP #$20
INC $F0 ; if we DIDN'T copy a spell, we need to increment our 'current slot' index
INC $F0 ; but if we did, the loop already has it pointing to the next slot
INC $F0
INC $F0
SEP #$20
.weCopiedALore
LDY $F0 ; and then copy it over to Y for our next loop through
DEX
BPL .checkLoreLoop
BRA .earlyExitLore
.noMoreLores
PLX ; if we exited early because there were no more spells to check, we need
; to make sure we settle up our stack -- exit early bypasses a PLX
.earlyExitLore
PLP
PLX
JMP $532C
org !freespace_C2_1
calculateMPDeduction:
REP #$10 ; (Set 16-bit X and Y)
LDA $3A7A ; (get command #)
CMP #$19
BEQ .calculateSummon ; (branch if it's Summon)
CMP #$0C
BEQ .calculateLore ; (branch if it's Lore)
CMP #$02
BEQ .calculateMagic ; (branch if it's Magic)
CMP #$17
BNE fka_4F53 ; (branch if it's not X-Magic)
.calculateMagic
LDA $3A7B ; (get attack #)
STA $F0 ; save our spell ID in scratch memory
REP #$20
LDA #$0004 ; four bytes per index
.loreEntersHere
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 #$0000
.findSpell
LDA ($F2),Y
CMP $F0
BEQ .getMPCost
CMP #$FF
BEQ fka_4F53
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
REP #$20
LDA #$00DC ; this is our first Lore slot in the character's spell list
BRA .loreEntersHere
.calculateSummon ; rather than looking for the spell ID, I'm operating under
REP #$20 ; the assumption that if someone is using Summon, it's already
LDA $302C,X ; checked for the equipped Esper, so I'm just loading the MP cost
TAX ; from the first entry in the character's list
SEP #$20
LDA $0003,X
BRA fka_4F45
fka_4F45: JMP $4F54 ; (clean up stack and exit)
fka_4F53: JMP $4F53
If you're curious about jumping to 16-bit accumulator and back during sorting the Lores, it's because otherwise $F0 increments in 8-bit, which breaks the game, oops. I'm happy to take suggestions on improving that section.
« Next Oldest | Next Newest »
Users browsing this thread: 2 Guest(s)