Updates:
9/3/2000 Header added, a few new spell/item effect subroutines added,
elemental damage subroutines added.
The most recent copy of this document can be obtained from the Tower of Bab-Il
(http://minitrue.weyland-yutani.net/tower/index.html).
The disassembled code reproduced here is only the code that I believe I fully
understand at the moment. Other disassembled code will be added later once I
can fully comment it.
The subroutine to look up a spell effect subroutine address in a table and
jump to it is disassembled here:
03:D297 ASL A ;A register holds the subroutine #
03:D298 TAX
03:D299 LDA $03E07C,X
03:D29D STA D,$80
03:D29F LDA $03E07D,X
03:D2A3 STA D,$81
03:D2A5 LDA #$03
03:D2A7 STA D,$82
03:D2A9 JML ($0080)
So this tells us that the table of spell effect subroutines is located at
1E27C (in the ROM with header).
The table is reproduced here with commentary:
E# CPUa Used by (not a complete list)
-- ---- -----------------------------
00 D378
01 D3B2
02 D40C Cure1, Cure2, Cure3, Cure4, Asura
03 D443 Storm, Weak
04 D466 Drain
05 D488 Psych
06 D505
07 D5A6 Hold, Sleep, Pin, Tongue, Entangle, Gas
08 D613 Blink, Image
09 D61C Wall
0A D64B Life1, Life2
0B D6E8 Heal
0C D81A Piggy, Size, Toad
0D D83F Armor
0E D863 Shell
0F D887 Slow, Fast, DullSong
10 D8A0
11 D8DE
12 D917 Peep
13 D972
14 D990
15 D9EC Ether1, Ether2
16 DA0C Elixir
17 DA1E
18 DA66
19 DA7F
1A DAA1
1B DB52
1C DBA8
1D DBA8
1E DBD8
1F DC1E
20 DC83
21 DCA3
22 DCBE
23 DCE3
24 DCEE
25 DD05
26 DD1A
27 DD39
28 DD7D
29 DD83
2A DD99
2B DDB1
2C DD4D
2D DDC4
2E DDC1
2F DDC5
30 DDC9
31 DE1C
32 DFBA
33 DFC0
34 DFD3
35 DFE8
At the time this subroutine is called, the target's data has been copied to
2700-277F in RAM. The caster's data has been copied to 2680-26FF. The
subroutines modify this data. The relevant spell/item table entry has been
copied to 289C-28A1. 28A2-28A4 contain the elemental/status table entry for
the spell/item. Locations CD and CE in the zero page designate the caster and
target; if the MSB is set, it is the number of a monster slot, otherwise it is
a character slot. After the subroutine returns, A2-A3 is damage done to the
caster (MSB/bit 0 set for HP recovery, bit 1 set for MP damage which should
only be displayed by following code as the actual damage is handled by the
effect subroutine) and A4-A5 is damage done to the target (ditto).
Here is the spell effect subroutine 00 (used by Fire/Ice/Lit 1-3 and too many
other spells to list):
03:D378 JSR $E0E8 ;adjust elemental damage for elemental defenses
03:D37B LDA $38FE
03:D37E BPL $D388 ;if the elemental damage is positive, go on to check
;for weaknesses
03:D380 AND #$7F
03:D382 STA $38FE ;otherwise, make it positive
03:D385 JMP $D416 ;and treat it as a cure spell (but skipping the undead
;check)
03:D388 JSR $E11B ;adjust elemental damage for elemental weaknesses
03:D38B LDA $2704
03:D38E AND #$40 ;check to see if the target is floating
03:D390 BEQ $D3AE ;if not, skip the checks for earthquake attacks
03:D392 LDA $352A
03:D395 BNE $D3A7 ;if an item is being used, go and check to see if it
;is the Earth Drum
03:D397 LDA $26D2
03:D39A CMP #$28 ;check to see if the spell is the black magic Quake
03:D39C BEQ $D3B1 ;if it is, return
03:D39E CMP #$55 ;check to see if the spell is the call magic Titan
03:D3A0 BEQ $D3B1 ;if it is, return
03:D3A2 CMP #$A1 ;check to see if the spell is the enemy spell Quake
03:D3A4 BNE $D3AE ;if it isn't, go ahead and determine damage
03:D3A6 RTS ;otherwise, return
03:D3A7 LDA $26D2
03:D3AA CMP #$C7 ;check to see if the item is the Earth Drum
03:D3AC BEQ $D3B1 ;if it is, return
03:D3AE JSR $C99F ;call damage determination subroutine
03:D3B1 RTS
Here is the spell effect subroutine 02 (used by all Cure spells and potions):
03:D40C LDA $2740
03:D40F AND #$80 ;check to see if target is undead
03:D411 BEQ $D416
03:D413 JMP $D3AE ;if so, do a straightforward damage determination
03:D416 LDA $352A
03:D419 BNE $D439 ;if an item is being used, do a normal cure
03:D41B LDA $26D2
03:D41E CMP #$11 ;check to see if the spell is the white magic Cure4
03:D420 BNE $D439 ;if it isn't, do a normal cure
03:D422 LDA $3906
03:D425 CMP #$01
03:D427 BNE $D439 ;if the number of targets isn't one, do a normal cure
;otherwise, restore all lost HP...
03:D429 REP #$20 ;16 bit A register
03:D42B SEC
03:D42C LDA $2709
03:D42F SBC $2707
03:D432 STA D,$A4 ;damage done to target = target's max HP - target's
;current HP
03:D434 TDC
03:D435 SEP #$20 ;8 bit A register
03:D437 BRA $D43C ;and skip normal damage determination
;for normal cures, use normal damage determination
03:D439 JSR $C99F ;call damage determination subroutine
03:D43C LDA D,$A5
03:D43E ORA #$80
03:D440 STA D,$A5 ;set cure bit in damage
03:D442 RTS
Here is the spell effect subroutine 04 (used by Drain):
03:D466 LDA D,$CD
03:D468 CMP D,$CE
03:D46A BEQ $D487 ;check to see if user is the target, if so do nothing
03:D46C JSR $C99F ;determine damage
03:D46F LDX D,$A4
03:D471 STX D,$A2 ;assign damage to caster equal to damage to target
03:D473 LDA $2740
03:D476 AND #$80 ;check to see if target is undead
03:D478 BEQ $D481
03:D47A LDA D,$A5
03:D47C ORA #$80
03:D47E STA D,$A5 ;if undead, set highest bit in target damage (cure)
03:D480 RTS
03:D481 LDA D,$A3
03:D483 ORA #$80
03:D485 STA D,$A3 ;if not undead, set highest bit in caster damage
;(cure)
03:D487 RTS
Here is the spell effect subroutine 05 (used by Psych):
03:D488 LDA D,$CD
03:D48A CMP D,$CE
03:D48C BNE $D48F ;check to see that user is not the target target
03:D48E RTS
03:D48F JSR $C99F ;determine damage
03:D492 LDX D,$A4
03:D494 STX D,$A2 ;assign damage to caster equal to damage to target
03:D496 LDA $2740
03:D499 AND #$80 ;check to see if target is undead
03:D49B BEQ $D49F
03:D49D BRA $D4DC
03:D49F REP #$20 ;16 bit A register
03:D4A1 SEC
03:D4A2 LDA $270B
03:D4A5 SBC D,$A4 ;if target is not undead subtract damage from target's
;MP
03:D4A7 BCS $D4B5
03:D4A9 LDA $270B
03:D4AC STA D,$A4
03:D4AE STA D,$A2 ;if the damage was greater than target's MP, lower
;damage to target's MP
03:D4B0 STZ $270B ;target's MP = 0
03:D4B3 BRA $D4B8
03:D4B5 STA $270B ;if it wasn't greater than target's MP, store the
;result
03:D4B8 CLC
03:D4B9 LDA $268B
03:D4BC ADC D,$A4
03:D4BE STA $268B ;add damage to caster's MP
03:D4C1 LDA $268D
03:D4C4 CMP $268B
03:D4C7 BCS $D4CC
03:D4C9 STA $268B ;if MP is greater than maximum, set it to maximum
03:D4CC TDC ;A register = 0
03:D4CD SEP #$20 ;8 bit A register
03:D4CF LDA D,$A5
03:D4D1 ORA #$40
03:D4D3 STA D,$A5 ;set MP damage bit in target's damage
03:D4D5 LDA D,$A3
03:D4D7 ORA #$C0
03:D4D9 STA D,$A3 ;set cure and MP damage bit in caster's damage
03:D4DB RTS
03:D4DC REP #$20 ;16 bit A register
03:D4DE SEC
03:D4DF LDA $268B
03:D4E2 SBC D,$A4 ;if target is undead subtract damage from caster's MP
03:D4E4 BCS $D4F2
03:D4E6 LDA $268B
03:D4E9 STA D,$A4
03:D4EB STA D,$A2 ;if damage was greater than caster's MP lower damage
;to caster's MP
03:D4ED STZ $268B ;caster's MP = 0
03:D4F0 BRA $D4F5
03:D4F2 STA $268B ;if it wasn't greater than caster's MP, store result
03:D4F5 TDC ;A register = 0
03:D4F6 SEP #$20 ;8 bit A register
03:D4F8 LDA D,$A3
03:D4FA ORA #$40
03:D4FC STA D,$A3 ;set MP damage bit in caster's damage
03:D4FE LDA D,$A5
03:D500 ORA #$C0
03:D502 STA D,$A5 ;set cure and MP damage bit in target's damage
03:D504 RTS
Here is the spell effect subroutine 08 (used by Blink and Image):
03:D613 LDA $2706
03:D616 ORA #$0C
03:D618 STA $2706 ;set the image bits in the target status to both 1
;(three images)
03:D61B RTS
Here is the spell effect subroutine 0F (used by Fast, Slow, and DullSong):
03:D887 CLC
03:D888 LDA $273B
03:D88B ADC $289D ;add byte 01 of spell data to target speed modifier
03:D88E CMP #$20
03:D890 BCS $D89A ;if speed modifier >= #20, set it to #20 and return
03:D892 CMP #$0C
03:D894 BCS $D89C ;else if speed modifier < #0C set it and return
03:D896 LDA #$0C
03:D898 BRA $D89C ;if it's less than #0C, set it to #0C and return
03:D89A LDA #$20
03:D89C STA $273B
03:D89F RTS
Here is the spell effect subroutine 15 (used by Ether1 and Ether2):
03:D9EC JSR $C99F ;call damage determination subroutine
03:D9EF REP #$20 ;16 bit A register
03:D9F1 CLC
03:D9F2 LDA D,$A4
03:D9F4 ADC $270B ;add the "damage" to the target's mp
03:D9F7 CMP $270D
03:D9FA BCC $D9FF
03:D9FC LDA $270D
03:D9FF STA $270B ;if mp is greater than maximum, set it to maximum
03:DA02 TDC ;A register = 0
03:DA03 SEP #$20 ;8 bit A register
03:DA05 LDA D,$A5
03:DA07 ORA #$C0
03:DA09 STA D,$A5 ;set cure, mp bits in damage value
03:DA0B RTS
Here is the spell effect subroutine 16 (used by Elixir):
03:DA0C REP #$20 ;16 bit A register
03:DA0E LDA $2709
03:DA11 STA $2707 ;target's hp = target's max hp
03:DA14 LDA $270D
03:DA17 STA $270B ;target's mp = target's max mp
03:DA1A TDC ;A register = 0
03:DA1B SEP #$20 ;8 bit A register
03:DA1D RTS
This subroutine adjusts the elemental damage modifier for elemental defenses:
03:E0E8 LDA $2726 ;get target elemental immunities
03:E0EB AND $28A2 ;check to see if target is immune to any elements used
;in the attack
03:E0EE BEQ $E101
03:E0F0 TDC ;A register = 0
03:E0F1 STA $38FE ;if target was immune to any attack elements, set
;elemental damage multiplier to 0
03:E0F4 LDA $2726
03:E0F7 AND #$40 ;test to see if target is both immune and absorbs
03:E0F9 BEQ $E11A ;if not, return
03:E0FB LDA #$84
03:E0FD STA $38FE
03:E100 RTS ;otherwise, elemental damage is negative (healing)
;and twice normal!
03:E101 LDA $2725
03:E104 AND $28A2 ;check to see if target resists/absorbs any elements
;used in the attack
03:E107 BEQ $E11A ;if not return with elemental damage multiplier intact
03:E109 LDA #$01
03:E10B STA $38FE ;set elemental damage multiplier to 1 (half damage)
03:E10E LDA $2725
03:E111 AND #$40 ;check to see if blocked elements are absorbed
03:E113 BEQ $E11A ;if not, return (with half elemental damage)
03:E115 LDA #$82
03:E117 STA $38FE ;otherwise, elemental damage is negative (healing)
03:E11A RTS
This subroutine adjusts the elemental damage modifier for weaknesses:
03:E11B LDA $38FE ;check the elemental damage multiplier
03:E11E CMP #$02
03:E120 BNE $E13D ;if it isn't normal damage (there was an elemental
;defense involved), return
03:E122 LDA $2721
03:E125 AND $28A2 ;check to see if target is very weak vs. any of the
;attack elements
03:E128 BEQ $E130 ;if not, go check for normal weakness
03:E12A LDA #$08
03:E12C STA $38FE ;if so, set elemental damage to four times normal
03:E12F RTS
03:E130 LDA $2720
03:E133 AND $28A2 ;check to see if target is weak vs. any of the attack
;elements
03:E136 BEQ $E13D ;if not, return
03:E138 LDA #$04
03:E13A STA $38FE ;if so, set elemental damage to twice normal
03:E13D RTS