Notes:The Hunt for Red October (SNES)
This page contains notes for the game The Hunt for Red October (SNES).
Addresses are for the USA game unless noted.
Contents
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:
- Beethoven: The Ultimate Canine Caper (SNES)
- Bobby's World
- Steven Seagal is the Final Option
- The Hunt for Red October (SNES)
- Tom and Jerry (SNES)
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