If you appreciate the work done within the wiki, please consider supporting The Cutting Room Floor on Patreon. Thanks for all your support!

Notes:The Hunt for Red October (SNES)

From The Cutting Room Floor
Jump to navigation Jump to search

This page contains notes for the game The Hunt for Red October (SNES).

Addresses are for the USA game unless noted.

Button Codes

Instead of having stored patterns of controller button presses to compare player input against, this game looks for specific 32-bit values. Pressing A, B, X, or Y buttons on the controller loads different numbers, and with the correct combination the player input will match the stored value. This cheat system is used in five Riedel Software Productions (RSP) developed SNES titles:

Cheat Table

The stored 32-bit cheat values are located starting at ROM offset $009490 / SNES address $819490:

addr.  value
009490 00003F03
009494 0000BC94 
009498 00009C9C
00949C 0000EEBB
0094A0 000087A5

None of the cheats use the upper 16 bits.

Cheat Input and Comparison

$81/DE54 89 10 00    BIT #$0010              //R button
$81/DE57 F0 30       BEQ $30    [$DE89]      //branch to to $DE89 if R not pressed
cheat comparison mode
$81/DE59 A2 00 00    LDX #$0000              //start of cheat table
$81/DE5C BF 90 94 81 LDA $819490,x
$81/DE60 1F 92 94 81 ORA $819492,x
$81/DE64 F0 5D       BEQ $5D    [$DEC3]      //branch to $DEC3 if reached the end of the cheat table
$81/DE66 BF 90 94 81 LDA $819490,x
$81/DE6A CD 58 09    CMP $0958  [$81:0958]   //compare against upper 16 bits of player input
$81/DE6D D0 14       BNE $14    [$DE83]      //branch to $DE83 if not a match
$81/DE6F BF 92 94 81 LDA $819492,x
$81/DE73 CD 5A 09    CMP $095A  [$81:095A]   //compare against lower 16 bits of player input
$81/DE76 D0 0B       BNE $0B    [$DE83]      //branch to $DE83 if not a match
successful cheat entry
$81/DE78 9C 58 09    STZ $0958  [$81:0958]   //reset player input upper 16 bits
$81/DE7B 9C 5A 09    STZ $095A  [$81:095A]   //reset player input lower 16 bits
$81/DE7E 8A          TXA                     
$81/DE7F 4A          LSR A
$81/DE80 4A          LSR A                   //accumulator now holds index value of cheat to award bonus
$81/DE81 80 49       BRA $49    [$DECC]      //exit
player input didn't match the stored value, increment to the next one
$81/DE83 E8          INX
$81/DE84 E8          INX
$81/DE85 E8          INX
$81/DE86 E8          INX
$81/DE87 80 D3       BRA $D3    [$DE5C]      //loop and check if player input matches the next stored value
check button presses
$81/DE89 89 80 00    BIT #$0080              //A button
$81/DE8C F0 05       BEQ $05    [$DE93]      //branch to $DE93 if A not pressed
$81/DE8E A9 00 00    LDA #$0000
$81/DE91 80 1C       BRA $1C    [$DEAF]      //branch to calculation
$81/DE93 89 00 80    BIT #$8000              //B button
$81/DE96 F0 05       BEQ $05    [$DE9D]      //branch to $DE9D if B not pressed
$81/DE98 A9 01 00    LDA #$0001
$81/DE9B 80 12       BRA $12    [$DEAF]      //branch to calculation
$81/DE9D 89 40 00    BIT #$0040              //X button
$81/DEA0 F0 05       BEQ $05    [$DEA7]      //branch to $DEA7 if X not pressed
$81/DEA2 A9 02 00    LDA #$0002
$81/DEA5 80 08       BRA $08    [$DEAF]      //branch to calculation
$81/DEA7 89 00 40    BIT #$4000              //Y button
$81/DEAA F0 17       BEQ $17    [$DEC3]      //branch to $DEC3 if Y not pressed
$81/DEAC A9 03 00    LDA #$0003
calculation
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //x2
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //x2
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //ORA #$0000 if A pressed, #$0001 for B, #$0002 for X, #$0003 for Y
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]
$81/DEC1 80 06       BRA $06    [$DEC9]
failed cheat entry
$81/DEC3 9C 58 09    STZ $0958  [$81:0958]   //reset player input upper 16 bits
$81/DEC6 9C 5A 09    STZ $095A  [$81:095A]   //reset player input lower 16 bits
unfinished cheat entry
$81/DEC9 A9 FF FF    LDA #$FFFF
exit
$81/DECC FA          PLX
$81/DECC FA          PLX
$81/DECD C9 00 00    CMP #$0000
$81/DED0 6B          RTL

Example Cheat

Here is an example of the first cheat: Y, A, Y, Y, Y, R. As this cheat doesn't use the upper 16-bits, the operations involving 7E0958 can be ignored.

Y
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0000
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0000
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //accumulator = 0003
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]   //current total: 7E095A = 0003
$81/DEC1 80 06       BRA $06    [$DEC9]

A
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0006
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 000C
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //accumulator = 0000
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]   //current total: 7E095A = 000C
$81/DEC1 80 06       BRA $06    [$DEC9]

Y
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0018
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0030
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //accumulator = 0003
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]   //current total: 7E095A = 0033
$81/DEC1 80 06       BRA $06    [$DEC9]

Y
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 0066
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 00CC
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //accumulator = 0003
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]   //current total: 7E095A = 00CF
$81/DEC1 80 06       BRA $06    [$DEC9]

Y
$81/DEAF 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 019E
$81/DEB2 2E 58 09    ROL $0958  [$81:0958]
$81/DEB5 0E 5A 09    ASL $095A  [$81:095A]   //7E095A = 033C
$81/DEB8 2E 58 09    ROL $0958  [$81:0958]
$81/DEBB 0D 5A 09    ORA $095A  [$81:095A]   //accumulator = 0003
$81/DEBE 8D 5A 09    STA $095A  [$81:095A]   //final total: 7E095A = 033F (matches value stored at ROM offset 009492 - note the byte order is reversed)
$81/DEC1 80 06       BRA $06    [$DEC9]

R
press R to confirm cheat entry is finished

Alternate Example

An easier way to understand the cheat system is that it takes 2 button presses to produce the 16 combinations necessary to represent a single hex digit:

AA=0
AB=1
AX=2
AY=3
BA=4
BB=5
BX=6
BY=7
XA=8
XB=9
XX=A
XY=B
YA=C
YB=D
YX=E
YY=F

Using the same cheat as the previous example, it would appear as follows:

AA=0 
AY=3
AY=3
YY=F
R

The 6 most significant bits are zero, meaning the three A button presses at the beginning aren't required and allows the cheat to be shortened from A, A, A, Y, A, Y, Y, Y, R to Y, A, Y, Y, Y, R.

Award Bonus

$80/C334 30 4C       BMI $4C    [$C382]      //branch to $C382 if no cheat successfully entered
first cheat
$80/C336 C9 00 00    CMP #$0000              //YAYYYR cheat
$80/C339 D0 0B       BNE $0B    [$C346]      //branch to $C346 if not a match
$80/C33B A9 01 00    LDA #$0001              //Mission Complete
$80/C33E 8D 2D 15    STA $152D  [$81:152D]
$80/C341 8D 2F 15    STA $152F  [$81:152F]
$80/C344 80 3F       BRA $3F    [$C385]
second cheat
$80/C346 C9 01 00    CMP #$0001              //XBBAXYYA cheat
$80/C349 D0 08       BNE $08    [$C353]      //branch to $C353 if not a match
$80/C34B A9 01 00    LDA #$0001
$80/C34E 8D 45 15    STA $1545  [$81:1545]   //infinite energy
$80/C351 80 32       BRA $32    [$C385]
third cheat
$80/C353 C9 02 00    CMP #$0002              //XBYAXBYA cheat
$80/C356 D0 06       BNE $06    [$C35E]      //branch to $C35E if not a match
$80/C358 22 6C EB 81 JSL $81EB6C[$81:EB6C]   //maximum power-ups
$80/C35C 80 27       BRA $27    [$C385]
fourth cheat
$80/C35E C9 03 00    CMP #$0003              //XYXYYXYX cheat
$80/C361 D0 08       BNE $08    [$C36B]      //branch to $C36B if not a match
$80/C363 A9 01 00    LDA #$0001
$80/C366 8D 3A 0A    STA $0A3A  [$81:0A3A]   //mission select
$80/C369 80 1A       BRA $1A    [$C385]
fifth cheat (YABBXABY)
$80/C36B C9 04 00    CMP #$0004              //XXBBXABY cheat
$80/C36E D0 12       BNE $12    [$C382]      //branch to $C382 if not a match
$80/C370 A9 01 00    LDA #$0001
$80/C373 8D 45 15    STA $1545  [$81:1545]   //infinite energy
$80/C376 22 6C EB 81 JSL $81EB6C[$81:EB6C]   //maximum power-ups
$80/C37A A9 01 00    LDA #$0001
$80/C37D 8D 3A 0A    STA $0A3A  [$81:0A3A]   //mission select
$80/C380 80 03       BRA $03    [$C385]
fail
$80/C382 18          CLC
$80/C383 80 01       BRA $01    [$C386]
success
$80/C385 38          SEC
$80/C386 6B          RTL

Maximum Power-ups Bonus

maximum power-ups
$81/EB6C DA          PHX
$81/EB6D 5A          PHY
$81/EB6E A9 63 00    LDA #$0063              //99
$81/EB71 A2 63 00    LDX #$0063              //99
$81/EB74 A0 D5 14    LDY #$14D5              //ECMs (Select button)
$81/EB77 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EB7B A9 63 00    LDA #$0063              //99
$81/EB7E A2 63 00    LDX #$0063              //99
$81/EB81 A0 D7 14    LDY #$14D7              //Torpedoes (Y button)
$81/EB84 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EB88 A9 63 00    LDA #$0063              //99
$81/EB8B A2 63 00    LDX #$0063              //99
$81/EB8E A0 D9 14    LDY #$14D9              //SSMs (A button)
$81/EB91 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EB95 A9 63 00    LDA #$0063              //99
$81/EB98 A2 63 00    LDX #$0063              //99
$81/EB9B A0 DB 14    LDY #$14DB              //SAMs (X button)
$81/EB9E 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EBA2 A9 63 00    LDA #$0063              //99
$81/EBA5 A2 63 00    LDX #$0063              //99
$81/EBA8 A0 DD 14    LDY #$14DD              //Bombs (B button)
$81/EBAB 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EBAF A9 84 03    LDA #$0384              //900
$81/EBB2 A2 84 03    LDX #$0384              //900
$81/EBB5 A0 DF 14    LDY #$14DF              //Cavitation Drive (R button)
$81/EBB8 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EBBC A9 B0 04    LDA #$04B0              //1200
$81/EBBF A2 B0 04    LDX #$04B0              //1200
$81/EBC2 A0 E1 14    LDY #$14E1              //ship damage 
$81/EBC5 22 D3 EB 81 JSL $81EBD3[$81:EBD3]
$81/EBC9 7A          PLY
$81/EBCA FA          PLX
$81/EBCB 6B          RTL

Options Screen

Only the European version has a jump to the Start Options subroutine:

  • JPN
...
$80/98EA A9 02 00    LDA #$0002
$80/98ED 8D 40 02    STA $0240
$80/98F0 22 9D CD 81 JSL $81CD9D[$81:CD9D]   //title screen
$80/98F4 9C 40 02    STZ $0240
...
  • USA
...
$80/98EC A9 02 00    LDA #$0002
$80/98EF 8D 40 02    STA $0240
$80/98F2 22 9D CD 81 JSL $81CD9D[$81:CD9D]   //title screen
$80/98F6 9C 40 02    STZ $0240
...
  • EUR
...
$80/98EC A9 02 00    LDA #$0002
$80/98EF 8D 40 02    STA $0240
$80/98F2 22 9D CD 81 JSL $81CD9D[$81:CD9D]   //title screen
$80/98F6 22 10 D4 80 JSL $80D410[$80:D410]   //Start Options
$80/98FA 9C 40 02    STZ $0240
...

The JSL $80D410 in EUR would be JSL $80D437 in JPN or JSL $80D417 in USA.

Super Scope

  • EUR
$81/DC15 AD 12 09    LDA $0912  [$81:0912]
$81/DC18 29 0F 00    AND #$000F
$81/DC1B C9 0F 00    CMP #$000F              //Super Scope device ID
$81/DC1E 18          CLC
$81/DC1F F0 01       BEQ $01    [$DC22]      //branch to $DC22 if Super Scope is detected, the ENABLE DISABLE will appear in Options
$81/DC21 38          SEC                     //use PAR code 81DC21EA to NOP the SEC and force Super Scope option to display in Options
$81/DC22 6B          RTL