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

Notes:Steven Seagal is The Final Option

From The Cutting Room Floor
Jump to navigation Jump to search

This page contains notes for the game Steven Seagal is The Final Option.

RAM Addresses

7E0A71 cheat input upper 16 bits
7E0A73 cheat input lower 16 bits

7E128A Options: Continues range 0-5 ($00-05)
7E128C Options: Lives range 1-5 ($01-05)

7E1290 Options: 2 players: normal = 00, share = 01, team = 02
7E1292 Options: Difficulty: easy = 00, normal = 01, hard = 02
7E2194 Options: P1 Skill range 0-5, 2 is default ($00-05)
7E1296 Options: P2 Skill range 0-5, 2 is default ($00-05)

7E129A P1 continues
7E129C P2 continues

7E12A4 infinite lives cheat enabled 0001 = yes
7E12A6 1 hit kills cheat enabled 0001 = yes
7E12A8 P1 lives
7E12AA P2 lives

7E1CC8 P1 ???
7E1CCA P2 ???
7E1CCC P1 ammo (R button)
7E1CCE P2 ammo (R button)

7E1CD2 P1 knives (L button)
7E1CD4 P2 knives (L button)

7E1CEC collision box enabled 0001 = yes

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 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 SNES titles developed by Riedel: this, Beethoven: The Ultimate Canine Caper, Bobby's World, The Hunt for Red October, and Tom & Jerry.

Cheat Table

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

addr.  value
019194 0000DC00
019198 0000B600
01919C 00008F00
0191A0 00009C00
0191A4 00007900
0191A8 00004700

None of the cheats use the upper 24 bits.

Cheat Input and Comparison

...
$81/9570 BF 94 91 83 LDA $839194,x
$81/9574 1F 96 91 83 ORA $839196,x
$81/9578 F0 5D       BEQ $5D    [$95D7]      //branch to $95D7 if reached the end of the cheat table
$81/957A BF 94 91 83 LDA $839194,x
$81/957E CD 71 0A    CMP $0A71  [$83:0A71]   //compare against upper 16 bits of player input
$81/9581 D0 14       BNE $14    [$9597]      //branch to $9597 if not a match
$81/9583 BF 96 91 83 LDA $839196,x
$81/9587 CD 73 0A    CMP $0A73  [$83:0A73]   //compare against lower 16 bits of player input
$81/958A D0 0B       BNE $0B    [$9597]      //branch to $9597 if not a match
successful cheat entry
$81/958C 9C 71 0A    STZ $0A71  [$83:0A71]   //reset player input upper 16 bits
$81/958F 9C 73 0A    STZ $0A73  [$83:0A73]   //reset player input lower 16 bits
$81/9592 8A          TXA
$81/9593 4A          LSR A
$81/9594 4A          LSR A                   //accumulator now holds index value of cheat to award bonus
$81/9595 80 49       BRA $49    [$95E0]      //exit
player input didn't match the stored value, increment to the next one
$81/9597 E8          INX
$81/9598 E8          INX
$81/9599 E8          INX
$81/959A E8          INX
$81/959B 80 D3       BRA $D3    [$9570]      //loop and check if player input matches the next stored value
check button presses
$81/959D 89 80 00    BIT #$0080              //A button
$81/95A0 F0 05       BEQ $05    [$95A7]      //branch to $95A7 if A not pressed
$81/95A2 A9 00 00    LDA #$0000
$81/95A5 80 1C       BRA $1C    [$95C3]
$81/95A7 89 00 80    BIT #$8000              //B button
$81/95AA F0 05       BEQ $05    [$95B1]      //branch to $95B1 if B not pressed
$81/95AC A9 01 00    LDA #$0001
$81/95AF 80 12       BRA $12    [$95C3]
$81/95B1 89 40 00    BIT #$0040              //X button
$81/95B4 F0 05       BEQ $05    [$95BB]      //branch to $95BB if X not pressed
$81/95B6 A9 02 00    LDA #$0002
$81/95B9 80 08       BRA $08    [$95C3]
$81/95BB 89 00 40    BIT #$4000              //Y button
$81/95BE F0 17       BEQ $17    [$95D7]      //branch to $95D7 if Y not pressed
$81/95C0 A9 03 00    LDA #$0003
calculation
$81/95C3 0E 73 0A    ASL $0A73  [$83:0A73]   //x2
$81/95C6 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95C9 0E 73 0A    ASL $0A73  [$83:0A73]   //x2
$81/95CC 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95CF 0D 73 0A    ORA $0A73  [$83:0A73]   //ORA #$0000 if A pressed, #$0001 for B, #$0002 for X, #$0003 for Y
$81/95D2 8D 73 0A    STA $0A73  [$83:0A73]
$81/95D5 80 06       BRA $06    [$95DD]
failed cheat entry
$81/95D7 9C 71 0A    STZ $0A71  [$83:0A71]   //reset player input upper 16 bits
$81/95DA 9C 73 0A    STZ $0A73  [$83:0A73]   //reset player input lower 16 bits
unfinished cheat entry
$81/95DD A9 FF FF    LDA #$FFFF
exit
$81/95E0 FA          PLX
$81/95E1 C9 00 00    CMP #$0000
$81/95E4 6B          RTL

Example Cheat

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

Y
$81/95C3 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 0000
$81/95C6 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95C9 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 0000
$81/95CC 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95CF 0D 73 0A    ORA $0A73  [$83:0A73]   //accumulator = 0003
$81/95D2 8D 73 0A    STA $0A73  [$83:0A73]   //current total: 7E0A73 = 0003
$81/95D5 80 06       BRA $06    [$95DD]

B
$81/95C3 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 0006
$81/95C6 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95C9 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 000C
$81/95CC 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95CF 0D 73 0A    ORA $0A73  [$83:0A73]   //accumulator = 0001
$81/95D2 8D 73 0A    STA $0A73  [$83:0A73]   //current total: 7E0A73 = 000D 
$81/95D5 80 06       BRA $06    [$95DD]

Y
$81/95C3 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 001A
$81/95C6 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95C9 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 0034
$81/95CC 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95CF 0D 73 0A    ORA $0A73  [$83:0A73]   //accumulator = 0003
$81/95D2 8D 73 0A    STA $0A73  [$83:0A73]   //current total: 7E0A73 = 0037
$81/95D5 80 06       BRA $06    [$95DD]

A
$81/95C3 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 006E
$81/95C6 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95C9 0E 73 0A    ASL $0A73  [$83:0A73]   //7E0A73 = 00DC
$81/95CC 2E 71 0A    ROL $0A71  [$83:0A71]
$81/95CF 0D 73 0A    ORA $0A73  [$83:0A73]   //accumulator = 00DC
$81/95D2 8D 73 0A    STA $0A73  [$83:0A73]   //final total: 7E0A73 = 00DC (matches value stored at ROM offset 019196 - note the byte order is reversed)
$81/95D5 80 06       BRA $06    [$95DD]

R
press R to confirm cheat entry is finished

Alternate Example

An easier way to understand the cheat system is that it takes two 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:

YB=D 
YA=C
R

Award Bonus

$80/BAD7 10 03       BPL $03    [$BADC]      //branch to $BADC if successful cheat entry
...
first cheat
$80/BADC C9 00 00    CMP #$0000              //YBYA cheat
$80/BADF D0 0B       BNE $0B    [$BAEC]      //branch to $BEAC if not a match
$80/BAE1 A9 01 00    LDA #$0001              //stage clear
$80/BAE4 8D 6C 12    STA $126C  [$83:126C]
$80/BAE7 8D 6E 12    STA $126E  [$83:126E]
$80/BAEA 80 6C       BRA $6C    [$BB58]
second cheat
$80/BAEC C9 01 00    CMP #$0001              //XYBX cheat
$80/BAEF D0 08       BNE $08    [$BAF9]      //branch to $BAF9 if not a match
$80/BAF1 A9 01 00    LDA #$0001              //enable 1 hit kills
$80/BAF4 8D A6 12    STA $12A6  [$83:12A6]
$80/BAF7 80 5F       BRA $5F    [$BB58]
third cheat
$80/BAF9 C9 02 00    CMP #$0002              //XAYY cheat
$80/BAFC D0 08       BNE $08    [$BB06]      //branch to $BB06 if not a match
$80/BAFE A9 01 00    LDA #$0001              //enable infinite lives
$80/BB01 8D A4 12    STA $12A4  [$83:12A4]
$80/BB04 80 52       BRA $52    [$BB58]
fourth cheat
$80/BB06 C9 03 00    CMP #$0003              //XBYA cheat
$80/BB09 D0 1D       BNE $1D    [$BB28]      //branch to $BB28 if not a match
$80/BB0B A9 00 01    LDA #$0100              //256
$80/BB0E 8D A8 12    STA $12A8  [$83:12A8]   //P1 lives
$80/BB11 8D AA 12    STA $12AA  [$83:12AA]   //P2 lives
$80/BB14 8D CC 1C    STA $1CCC  [$83:1CCC]   //P1 ammo (R button)
$80/BB17 8D CE 1C    STA $1CCE  [$83:1CCE]   //P2 ammo (R button)
$80/BB1A 8D D2 1C    STA $1CD2  [$83:1CD2]   //P1 knives (L button)
$80/BB1D 8D D4 1C    STA $1CD4  [$83:1CD4]   //P2 knives (L button)
$80/BB20 8D C8 1C    STA $1CC8  [$83:1CC8]   //P1 ???
$80/BB23 8D CA 1C    STA $1CCA  [$83:1CCA]   //P2 ???
$80/BB26 80 30       BRA $30    [$BB58]
fifth cheat
$80/BB28 C9 04 00    CMP #$0004              //BYXB cheat
$80/BB2B D0 0B       BNE $0B    [$BB38]      //branch to $BB38 if not a match
$80/BB2D AD EC 1C    LDA $1CEC  [$83:1CEC]
$80/BB30 49 01 00    EOR #$0001              //toggle collision box
$80/BB33 8D EC 1C    STA $1CEC  [$83:1CEC]
$80/BB36 80 20       BRA $20    [$BB58]
sixth cheat
$80/BB38 C9 05 00    CMP #$0005              //BABY cheat
$80/BB3B D0 18       BNE $18    [$BB55]      //branch to $BB55 if not a match
$80/BB3D A9 01 00    LDA #$0001              //level clear
$80/BB40 8D 6C 12    STA $126C  [$83:126C]
$80/BB43 8D 6E 12    STA $126E  [$83:126E]
$80/BB46 AD 7A 12    LDA $127A  [$83:127A]
$80/BB49 AA          TAX
$80/BB4A BD F7 9F    LDA $9FF7,x
$80/BB4D 29 FF 00    AND #$00FF
$80/BB50 8D 7C 12    STA $127C  [$83:127C]
$80/BB53 80 03       BRA $03    [$BB58]
fail
$80/BB55 18          CLC
$80/BB56 80 01       BRA $01    [$BB59]
success
$80/BB58 38          SEC
$80/BB59 FA          PLX
$80/BB5A 6B          RTL

Infinite Lives Cheat Check

Executes when defeated.

...
$80/D228 AD A4 12    LDA $12A4  [$83:12A4]   //infinite lives cheat flag
$80/D22B D0 07       BNE $07    [$D234]      //branch to $D234 if enabled
$80/D22D B9 A8 12    LDA $12A8,y[$83:12A8]
$80/D230 3A          DEC A                   //lives -1
$80/D231 99 A8 12    STA $12A8,y[$83:12A8]
$80/D234 AD 86 12    LDA $1286  [$83:1286]
...

Start Status

...
initial start status
$80/B499 AD 8C 12    LDA $128C  [$83:128C]   //lives (set in Options)
$80/B49C 8D A8 12    STA $12A8  [$83:12A8]   //P1 lives
$80/B49F 8D AA 12    STA $12AA  [$83:12AA]   //P2 lives
$80/B4A2 AD 8A 12    LDA $128A  [$83:128A]   //continues (set in Options)
$80/B4A5 8D 9A 12    STA $129A  [$83:129A]   //P1 continues
$80/B4A8 8D 9C 12    STA $129C  [$83:129C]   //P2 continues
$80/B4AB 9C C8 1C    STZ $1CC8  [$83:1CC8]   //zero P1 ???
$80/B4AE 9C CC 1C    STZ $1CCC  [$83:1CCC]   //zero P1 ammo (R button)
$80/B4B1 9C D2 1C    STZ $1CD2  [$83:1CD2]   //zero P1 knives (L button)
$80/B4B4 9C CA 1C    STZ $1CCA  [$83:1CCA]   //zero P2 ???
$80/B4B7 9C CE 1C    STZ $1CCE  [$83:1CCE]   //zero P2 ammo (R button)
$80/B4BA 9C D4 1C    STZ $1CD4  [$83:1CD4]   //zero P2 knives (L button)
demo mode start status sets 256 for all stats
$80/B4BD A9 00 01    LDA #$0100              //256
$80/B4C0 8D A8 12    STA $12A8  [$83:12A8]   //P1 lives
$80/B4C3 8D AA 12    STA $12AA  [$83:12AA]   //P2 lives
$80/B4C6 8D CC 1C    STA $1CCC  [$83:1CCC]   //P1 ammo (R button)
$80/B4C9 8D CE 1C    STA $1CCE  [$83:1CCE]   //P2 ammo (R button)
$80/B4CC 8D D2 1C    STA $1CD2  [$83:1CD2]   //P1 knives (L button)
$80/B4CF 8D D4 1C    STA $1CD4  [$83:1CD4]   //P2 knives (L button)
$80/B4D2 8D C8 1C    STA $1CC8  [$83:1CC8]   //P1 ???
$80/B4D5 8D CA 1C    STA $1CCA  [$83:1CCA]   //P2 ???
...