the cutting room mirror

Thunder Spirits

This article has a talk page!
view on tcrf.net

This page contains notes for the game Thunder Spirits.

Configuration Mode#

Addresses correspond to the North American version.

open configuration menu
$05/91AC AF 90 03 7F LDA $7F0390[$7F:0390]   //check if finished game. FFFF = no 0000 = yes
$05/91B0 D0 03       BNE $03    [$91B5]
$05/91B2 4C BD 92    JMP $92BD  [$05:92BD]   //yes, open expanded config mode.  replace 4C BD 92 with 4C F2 91 (JMP $91F2) for debug mode
$05/91B5 20 1F 89    JSR $891F  [$05:891F]   //no

Pause cheat#

Addresses correspond to the North American version.

while paused...
$00/8D31 20 0D 88    JSR $880D  [$00:880D]
$00/8D34 20 95 AB    JSR $AB95  [$00:AB95]
$00/8D37 20 E1 B5    JSR $B5E1  [$00:B5E1]
$00/8D3A AD 69 1B    LDA $1B69  [$00:1B69]
$00/8D3D 89 00 20    BIT #$2000              //check Select
$00/8D40 F0 03       BEQ $03    [$8D45]

Select button pressed
$00/8D42 EE 6D 1B    INC $1B6D  [$00:1B6D]   //inc counter for times Select pressed

$00/8D45 89 20 00    BIT #$0020              //check L
$00/8D48 F0 08       BEQ $08    [$8D52]

L button pressed
$00/8D4A AD 6D 1B    LDA $1B6D  [$00:1B6D]
$00/8D4D C9 0A 00    CMP #$000A              //check if Select pressed 10x
$00/8D50 F0 09       BEQ $09    [$8D5B]      //if 10x, proceed to next section $8D5B

$00/8D52 AD 69 1B    LDA $1B69  [$00:1B69]
$00/8D55 89 00 10    BIT #$1000              //check Start
$00/8D58 F0 D7       BEQ $D7    [$8D31]

$00/8D5A 60          RTS

second part of cheat entry
$00/8D5B 20 0D 88    JSR $880D  [$00:880D]
$00/8D5E 20 95 AB    JSR $AB95  [$00:AB95]
$00/8D61 20 E1 B5    JSR $B5E1  [$00:B5E1]
$00/8D64 AD 69 1B    LDA $1B69  [$00:1B69]
$00/8D67 89 10 00    BIT #$0010              //check R
$00/8D6A F0 03       BEQ $03    [$8D6F]

R button pressed
$00/8D6C EE 6D 1B    INC $1B6D  [$00:1B6D]   //inc counter for times R pressed

$00/8D6F 89 00 20    BIT #$2000              //check Select
$00/8D72 F0 08       BEQ $08    [$8D7C]

Select button pressed
$00/8D74 AD 6D 1B    LDA $1B6D  [$00:1B6D]
$00/8D77 C9 0C 00    CMP #$000C              //Select pressed 10x + R 2x
$00/8D7A F0 09       BEQ $09    [$8D85]      //if #$0C, code entry successful, proceed to $8D85

$00/8D7C AD 69 1B    LDA $1B69  [$00:1B69]
$00/8D7F 89 00 10    BIT #$1000              //check Start
$00/8D82 F0 D7       BEQ $D7    [$8D5B]

$00/8D84 60          RTS

use cheat features
$00/8D85 20 0D 88    JSR $880D  [$00:880D]
$00/8D88 20 95 AB    JSR $AB95  [$00:AB95]
$00/8D8B 20 E1 B5    JSR $B5E1  [$00:B5E1]
$00/8D8E AD 69 1B    LDA $1B69  [$00:1B69]
$00/8D91 89 80 00    BIT #$0080              //check A
$00/8D94 F0 11       BEQ $11    [$8DA7]

A button pressed - upgrade/add weapons
$00/8D96 20 F1 8D    JSR $8DF1  [$00:8DF1]
$00/8D99 E2 20       SEP #$20
$00/8D9B A9 FF       LDA #$FF
$00/8D9D 99 63 1B    STA $1B63,y[$00:1B63]
$00/8DA0 C2 20       REP #$20
$00/8DA2 20 45 C1    JSR $C145  [$00:C145]
$00/8DA5 80 DE       BRA $DE    [$8D85]

$00/8DA7 89 00 80    BIT #$8000              //check B
$00/8DAA F0 14       BEQ $14    [$8DC0]

B button pressed - downgrade/remove weapons
$00/8DAC 20 F1 8D    JSR $8DF1  [$00:8DF1]
$00/8DAF E2 20       SEP #$20
$00/8DB1 A9 00       LDA #$00
$00/8DB3 99 63 1B    STA $1B63,y[$00:1B64]
$00/8DB6 C2 20       REP #$20
$00/8DB8 9C 61 1B    STZ $1B61  [$00:1B61]
$00/8DBB 20 45 C1    JSR $C145  [$00:C145]
$00/8DBE 80 C5       BRA $C5    [$8D85]

$00/8DC0 89 40 00    BIT #$0040              //check X
$00/8DC3 F0 0B       BEQ $0B    [$8DD0]

X button pressed - add support guns
$00/8DC5 A9 01 00    LDA #$0001
$00/8DC8 8D 12 04    STA $0412  [$00:0412]
$00/8DCB 20 45 C1    JSR $C145  [$00:C145]
$00/8DCE 80 B5       BRA $B5    [$8D85]

$00/8DD0 89 00 40    BIT #$4000              //check Y
$00/8DD3 F0 0B       BEQ $0B    [$8DE0]

Y button pressed - add shield
$00/8DD5 A9 03 00    LDA #$0003
$00/8DD8 8D 14 04    STA $0414  [$00:0414]
$00/8DDB 20 45 C1    JSR $C145  [$00:C145]
$00/8DDE 80 A5       BRA $A5    [$8D85]

$00/8DE0 89 10 00    BIT #$0010              //check R
$00/8DE3 F0 03       BEQ $03    [$8DE8]

R button pressed - self-destruct
$00/8DE5 20 6C AD    JSR $AD6C  [$00:AD6C]

$00/8DE8 89 00 10    BIT #$1000              //check Start
$00/8DEB F0 98       BEQ $98    [$8D85]

Start button pressed
$00/8DED 9C 61 1B    STZ $1B61  [$00:1B61]   //related to collision?
$00/8DF0 60          RTS                     //exit

sub for weapons
$00/8DF1 AD 6F 1B    LDA $1B6F  [$00:1B6F]
$00/8DF4 1A          INC A
$00/8DF5 C9 05 00    CMP #$0005
$00/8DF8 90 03       BCC $03    [$8DFD]
$00/8DFA A9 00 00    LDA #$0000
$00/8DFD 8D 6F 1B    STA $1B6F  [$00:1B6F]
$00/8E00 A8          TAY
$00/8E01 60          RTS

Name entry check#

To do:
Reformat

; format:                         ROM addr | logical addr of memory access
    rep #$20            ; $28FD2
    lda $7F0302,x       ; $28FD4 | $7F0302 - first two initials
    cmp #$4040          ; $28FD8 - "  "
    beq loc_28FE7       ; $28FDB - yes, see if we need to replace
    cmp #$4141          ; $28FDD - "AA"
    beq loc_28FE7       ; $28FE0 - yes, see if we need to replace
    cmp #$4553          ; $28FE2 - "ES" (little-endian)
    bne loc_29010       ; $28FE5 - no, do not replace
loc_28FE7:
    lda $7F0304,x       ; $28FE7 | $7F0304 - last initial
    cmp #$0040          ; $28FEB - " "
    beq loc_28FFA       ; $28FEE - yes, replace
    cmp #$0041          ; $28FF0 - "A"
    beq loc_28FFA       ; $28FF3 - yes, replace
    cmp #$0058          ; $28FF5 - "X"
    bne loc_29010       ; $28FF8 - no, do not replace
loc_28FFA:
    sep #$20            ; $28FFA - switch to byte reads/writes
    lda #$45            ; $28FFC - "E"
    sta $7F0302,x       ; $28FFE |  $7F0302
    lda #$4D            ; $29002 - "M"
    sta $7F0303,x       ; $29004 |  $7F0303
    lda #$49            ; $29008 - "I"
    sta $7F0304,x       ; $2900A |  $7F0304
    rep #$20            ; $2900E - switch to word reads/writes
loc_29010:

andlabs's scattered notes#

$7F0000 - 'Ohda'
used for reset check
does not appear to be used by any other SNES game? no name match with any of the Thunder Force III staff

$7F0004 - $FF if 'Ohda'; $00 otherwise

sub_9CE - Toshiba EMI screen

sub_B8000 - the actual gruntwork

sub_9DF - ending; starts after the fadeout for the final level but before the HUD is removed from the screen as well

sub_30003 -> loc_30107 -> sub_38000 -> loc_38005 - ending cutscene
$381E3 is right after "was eventually extinguished." has been output
$3823F is right after this block of text scrolls offscreen
$3828A is right after this part of the cutscene ends, leading into the slideshow
sub_3897E appears to be the routine that loads the slideshow image, with byte $7FFD80 choosing (zero for first, nonzero for second)
$38391 is right before the THE END screen shows up
verdict: seems to be nothing unused, unless I am missing extra data
00038262 4CD181    jmp loc_381D1  ; normal branch
00038265 A90100    lda #$0001     ; target 1 - NOTHING
00038268 8D901A    sta $1A90
0003826B 4CDA83    jmp loc_383DA
0003826E 9C901A    stz $1A90      ; target 2 - NOTHING, but controller input stops working?
00038271 4CDA83    jmp loc_383DA
00038274 A90200    lda #$0002     ; target 3 - NOTHING, but controller input stops working
00038277 8D901A    sta $1A90
0003827A 4CDA83    jmp loc_383DA
0003827D 20 42 93 9C DB  sub_3827D

if they all do nothing, I'll need to try subroutiune calls...

loc_383DA:
    jsr sub_383DF       ; $383DA
    plb     ; $383DD
    rtl     ; $383DE
sub_383DF:
    ; does stuff

so we want 20DF83 - and the game hangs ok final verdict: got nothing; off to the name entry code

$021A98 - level number (0..7; not sure what higher values would do)

huh? demo recording?

loc_B39:
    sta $ABAD8C,x       ; $B3B |  $ABAD8C -> ROM $55AD8C
loc_B3D:
    beq loc_B4D     ; $B40
    lda $1B69       ; $B42 | $1B69 -> $001B69
    bit #$00        ; $B45
    bpl loc_B39     ; $B47

loc_28BFD - actual start of name entry code (after following some jumps)

sub_2891F - PrintString - looks like I need to add a noreturn feature of sort, since this behaves like the PrintString in tecnosoft's MD games (pulls strings from instruction stream)

actually here the string starts after three bytes and ends on a null byte so maybe I can do a string feature...

loc_28FC7 - start of built in name check

loc_28FFA - loads EMI (replacement name)
verdict - doe not appear to check any other names

00282e0: d0e4 9c14 1c20 2183 a900 00ab 6b4d 5354  ..... !.....kMST
00282f0: 0053 484f 004e 4153 0054 3a4b 0050 4950  .SHO.NAS.T:K.PIP
0028300: 0053 4d49 0045 584f 0059 4f55 0056 3132  .SMI.EXO.YOU.V12
0028310: 004e 414f 0054 4945 004b 5234 0038 3431  .NAO.TIE.KR4.841

are TIE, KR4, 841 names that do not appear?

bugs in the disassembler

   rep #$20        ; $134F
    lda $7F038A     ; $1351 |  $7F038A
    bne loc_1360        ; $1355
    lda #$F3        ; $1357
    brk #$20        ; $1359
    lda ($AC),y     ; $135B | $AC + d=$00 -> $0000AC
    jmp loc_A0D     ; $135D
loc_1360:
    lda #$00F4      ; $1360
    jsr sub_2CB1        ; $1363
    jmp loc_A0D     ; $1367

(need to actually add environment saving/restoring)