Notes:Final Fight 2
This page contains notes for the game Final Fight 2.
Addresses on this page correspond to the USA version unless noted otherwise.
- 1 Breakpoints
- 2 Enemy List
- 3 Enemy Names
- 4 Player Character Stats
- 5 Enemy Stats
- 6 Display 8 or 16-bit value
- 7 Same Player Cheat
- 8 Stored Button Presses Table
- 9 Palettes
- 10 Palette Offsets
- 11 Continue Screen
80811A, execute - accumulator holds start addresses of palette (+830000) 8180B1, execute - accumulator holds sound effect index to play
These Pro Action Replay codes can be used to change the first two enemies that appear at the beginning of the first stage. Presumably, U.Andore and F.Andore would've used values 0603, 0604, respectively, but no slots are reserved for them.
84C265xx 84C266xx 84C26Dxx 84C26Exx
Alternately, change the following values directly in a hex editor:
00024265 00024266 0002426D 0002426E
Enemy Index, Name 0300 Mic 0301 Schot 0302 Bull 0303 Mark 0304 Jack 0305 Elijah 0400 Elick 0500 Atlas 0501 Jony 0600 Andore Jr. 0601 Andore 0602 G.Andore 0700 Leon 0701 Robert 0800 Eliot 0801 Elias 0900 Joe 0A00 Won Won 0B00 Freddie 0C00 Bratken 0D00 Philippe 0E00 Rolent 0F00 Retu
The enemy names are stored in the chunk of memory beginning at 00016A4B and ending at 00016B9A when viewed in a hex editor. The data for a given enemy is 12 bytes long--the first byte is presumably a pointer to the enemy icon, but this isn't known for sure. Then there's white space, and finally the enemy name. In other words, the enemy names are left-padded with spaces. Note that the first three entries are currently not known as to what they actually are (Possibly encrypted data for displaying the player character names/icons?). "Plaintext" enemy data, therefore, begins at 00016A6F.
For example, to change Mic's name to Michael, you would change the row of data found at 00016A70:
20 20 20 20 20 20 20 20 4D 49 43 04 20 20 20 20 | MIC. |
20 20 20 20 4D 49 43 48 41 45 4C 04 20 20 20 20 | MICHAEL. |
Do not change it to the below. More accurately, while you can change it to the below, you won't get the results you expect--Mic will still be called Mic, while Schot won't have a name and will have gibberish for an icon.
20 20 20 20 20 20 20 20 4D 49 43 48 41 45 4C 04 | MICHAEL.|
Player Character Stats
The following addresses correspond to the statistics for the three playable characters, their starting health, and their attacks. Numbers in parentheses in the comments are the corresponding decimal values.
When viewed in a hex editor, the corresponding beginning address is 00016B9B.
82EB9B 8D 82EB9C 00 //Maki's starting/maximum health. 2 bytes, lower byte first (141) 82EB9D 00 //Padding/unknown byte 82EB9E 2E //Maki's Extra Joy damage (46) 82EB9F 1E //Maki's knife damage (30) 82EBA0 1E //Maki's tonfa damage (30) 82EBA1 14 //Maki's 2X4 damage (20) 82EBA2 08 //Damage of Maki's first knee after grabbing an enemy (8) 82EBA3 0E //Damage of Maki's second knee after grabbing an enemy (14) 82EBA4 18 //Damage of Maki's third knee after grabbing an enemy (24) 82EBA5 1C //Damage of Maki's throw (28) 82EBA6 08 //Damage taken by an enemy "catching" a thrown enemy (8) 82EBA7 06 //Damage of Maki's basic jab (6) 82EBA8 08 //Damage of the third hit in Maki's combo (8) 82EBA9 0C //Damage of the fourth hit in Maki's combo (12) 82EBAA 14 //Damage of the last hit in Maki's combo (20) 82EBAB 0C //Damage of Maki's "standing" jump kick (12) 82EBAC 08 //Damage of Maki's "Down+Attack" in the air (8) 82EBAD 0E //Damage of Maki's "flying" jump kick (14) 82EBAE 8D 82EBAF 00 //Haggar's starting/maximum health. 2 bytes, lower byte first (141) 82EBB0 00 //Padding/unknown byte 82EBB1 24 //Haggar's Extra Joy damage (36) 82EBB2 1E //Haggar's knife damage (30) 82EBB3 1E //Haggar's tonfa damage (30) 82EBB4 14 //Haggar's 2X4 damage (20) 82EBB5 0A //Damage of Haggar's first headbutt after grabbing an enemy (10) 82EBB6 10 //Damage of Haggar's second headbutt after grabbing an enemy (16) 82EBB7 24 //Damage of Haggar's third headbutt after grabbing an enemy (36) 82EBB8 24 //Damage of Haggar's suplex (36) 82EBB9 08 //Damage taken by an enemy "catching" a suplexed/piledriven enemy (8) 82EBBA 28 //Damage of Haggar's spinning piledriver (40) 82EBBB 12 //Damage of Haggar's basic jab (18) 82EBBC 12 //Damage of the last hit in Haggar's combo (18) 82EBBD 14 //Damage of any of Haggar's flying attacks (20) 82EBBE 08 //?? Unknown at this time 82EBBF 8D 82EBC0 00 //Carlos's starting/maximum health. 2 bytes, lower byte first (141) 82EBC1 00 //Padding/unknown byte 82EBC2 24 //Carlos's Extra Joy damage (36) 82EBC3 1E //Carlos's knife damage (30) 82EBC4 1E //Carlos's tonfa damage (30) 82EBC5 14 //Carlos's 2X4 damage (20) 82EBC6 09 //Damage of Carlos's first knee after grabbing an enemy (9) 82EBC7 10 //Damage of Carlos's second knee after grabbing an enemy (16) 82EBC8 1C //Damage of Carlos's third knee after grabbing an enemy (28) 82EBC9 08 //Damage taken by an enemy "catching" a thrown enemy (8) 82EBCA 1C //Damage of Carlos's throw (28) 82EBCB 0A //Damage of Carlos's basic jab (10) 82EBCC 0A //Damage of the third hit in Carlos's combo (10) 82EBCD 10 //Damage of the last hit in Carlos's combo (10) 82EBCE 0C //Damage of Carlos's "standing" jump kick (12) 82EBCF 08 //Damage of Carlos's "Down+Attack" in the air (8) 82EBD0 0E //Damage of Carlos's "flying" jump kick (14)
The enemy statistics begin immediately after the above player statistics (Viewed in a hex editor, beginning at 00016BD1). The format is as follows:
-The life of the "group" of enemies, in two bytes (Smaller byte first), for each of 32 potential "internal" difficulty levels. This takes up a total of 64 bytes.
-The defense of the group, taking up 32 bytes, one for each potential internal difficulty.
-Numerous groups of 32 bytes, presumably attack values for that group's various attacks.
The beginning addresses for each group are the following locations. Group numbers correspond to the first byte in the "Enemy Index" section above:
Group 03 (Mic/Schot/Bull/Mark/Jack/Elijah): 82EBD1 Group 04 (Elick): 82ECD1 Group 05 (Jony/Atlas): 82EDB1 Group 06 (Andore Jr./Andore/G.Andore): 82EEB1 Group 07 (Leon/Robert): 82EFF1 Group 08 (Elias/Eliot): 82F111 (Group 09, the Joes, do not seem to appear in this block. Perhaps their data is all hard-coded elsewhere) Group 0A (Won Won): 82F1D1 Group 0B (Freddie): 82F2F1 Group 0C (Bratken): 82F451 Group 0D (Philippe): 82F5D1 Group 0E (Rolent): 82F6B1 Group 0F (Retu): 82F791
The structure of this enemy data implies at least the potential for an arcade-style "rank" system, despite the fact that there are only 4 selectable difficulties. How much of this is actually used, and how much is "Capcom ported the enemy structure from Arcade Final Fight to SNES Final Fight 1, then kept it rolling for Final Fight 2 instead of cleaning up that structure", is unknown at this time.
The Damage Formula
Determining damage to an enemy is pretty simple:
-Take the value of the attack in the "Player Character Stats" section above.
-Multiply that value by (32 - enemy defense)
-Divide that result by 32
-Round down, if necessary
Display 8 or 16-bit value
The programming to display an 8-bit hex value is used (by the continue countdown timer in 2P mode when one player runs out of lives), but not the 16-bit part. No pattern matches for 22468580 (JSL $808546) were found.
Display 16-bit value $80/8546 E2 20 SEP #$20 $80/8548 48 PHA //Push the upper 8 bits to display later $80/8549 EB XBA $80/854A 22 51 85 80 JSL $808551[$80:8551] //Display 8-bit value $80/854E E2 20 SEP #$20 $80/8550 68 PLA //Pull the upper 8 bits Display 8-bit value $80/8551 48 PHA $80/8552 C2 30 REP #$30 $80/8554 29 F0 00 AND #$00F0 //Keep only upper 4 bits (first digit) $80/8557 4A LSR A $80/8558 4A LSR A $80/8559 4A LSR A $80/855A AA TAX $80/855B BF 7F E4 82 LDA $82E47F,x //Get tile index $80/855F 99 3E 22 STA $223E,y //Store to tilemap $80/8562 C8 INY $80/8563 C8 INY $80/8564 E2 20 SEP #$20 $80/8566 68 PLA $80/8567 C2 20 REP #$20 $80/8569 29 0F 00 AND #$000F //Keep only lower 4 bits (second digit) $80/856C 0A ASL A $80/856D AA TAX // $80/856E BF 7F E4 82 LDA $82E47F,x //Get tile index $80/8572 99 3E 22 STA $223E,y //Store to tilemap $80/8575 C8 INY $80/8576 C8 INY $80/8577 6B RTL
Tile Index Values
82E47F 3028 3128 3228 3328 3428 3528 3628 3728 0(1(2(3(4(5(6(7( 82E48F 3828 3928 4128 4228 4328 4428 4528 4628 8(9(A(B(C(D(E(F(
Same Player Cheat
$80/A886 BD A4 AD LDA $ADA4,x //Load the set of player button presses starting at 7EADA4 $80/A889 DF D6 E4 82 CMP $82E4D6,x //Compare to stored button presses table starting at 82E4D6
Success $80/A895 A9 00 4C LDA #$4C00 //Set background to blue $80/A898 8D 3E 20 STA $203E [$7E:203E] $80/A89B E2 20 SEP #$20 $80/A89D EE CD AD INC $ADCD [$7E:ADCD] //Turn on same player cheat
Stored Button Presses Table
82E4D6 0004 = down 82E4D8 0004 = down 82E4DA 0008 = up 82E4DC 0008 = up 82E4DE 0001 = right 82E4E0 0002 = left 82E4E2 0001 = right 82E4E4 0002 = left 82E4E6 2000 = L 82E4E8 1000 = R
Copy $20 byte palettes from ROM to RAM. The starting ROM address for palettes is $83F560 $80/8117 69 60 F5 ADC #$F560 $80/811A AA TAX $80/811B A9 1F 00 LDA #$001F $80/811E 54 7E 83 MVN 83 7E
Offset, Enemy index, Palette index, Name
83F560 ---- Maki 83F580 ---- Haggar 83F5A0 ---- Carlos 83F5C0 0300 Mic 83F5E0 0301 Schot 83F600 0302 Bull 83F620 0800 Eliot 83F640 0400 Elick 83F660 0500 Atlas 83F680 83F6A0 ---- Drumcan 83F6C0 83F6E0 0600 $0C Andore Jr. 83F700 0601 $0D Andore 83F720 0602 $0E G.Andore 83F740 0801 Elias 83F760 0A00 Won Won 83F780 83F7A0 83F7C0 83F7E0 83F800 ---- (yellow border around character portrait on character select screen) 83F820 0303 Mark 83F840 0304 Jack 83F860 0305 Elijah 83F880 83F8A0 83F8C0 83F8E0 83F900 83F920 0501 Jony 83F940 83F960 83F980 83F9A0 83F9C0 83F9E0 83FA00 83FA20 83FA40 83FA60 83FA80 83FAA0 0E00 Rolent 83FAC0 83FAE0 83FB00 83FB20 83FB40 83FB60 83FB80 83FBA0 ---- Bottle 83FBC0 83FBE0 83FC00 83FC20 83FC40 83FC60 83FC80 83FCA0 83FCC0 83FCE0 83FD00 83FD20 83FD40 83FD60 0900 Joe 83FD80 0700 Leon 83FDA0 0701 Robert 83FDC0 ---- Maki (same player 2P mode, blue) 83FDE0 ---- Haggar (same player 2P mode, blue) 83FE00 ---- Carlos (same player 2P mode, orange) 83FE20 ---- 83FE40 ---- (identical to 83FE20) - A duplicate set is found in the Japanese version (ie, it has 4 copies total of this palette) This may be unused in the USA version. 83FE60-83FFFF unused space ($01A0 bytes)
This is very incomplete.
$80/E710 E2 20 SEP #$20 $80/E712 E6 7E INC $7E $80/E714 A5 7E LDA $7E $80/E716 C9 0A CMP #$0A $80/E718 90 18 BCC $E732 //If incrementer less than 10, DO NOT raise water (incrementer increases every frame) $80/E71A 64 7E STZ $7E //Otherwise, zero out incrementer (Located at 0019CB) and proceed. $80/E71C AD 0E D6 LDA $d60e $80/E71F C9 00 CMP #$00 $80/E721 D0 0F BNE $E732 //Compare 7ED60E to 0 and DO NOT raise water if NOT equal to 0. This seems to get set to something //besides 0 once the "Game Over" begins. $80/E723 C2 20 REP #$20 $80/E725 AD 49 AB LDA $AB49 $80/E728 C9 B0 FF CMP #$FFB0 $80/E72B B0 05 BCS $E732 //Compare current water height (Located at 7EAB49) to 176. If greater than or equal to 176, DO NOT //raise it. $80/E72D EE 49 AB INC $AB49 //Otherwise, we've passed all the checks, so raise the water one pixel and continue. $80/E730 80 00 BRA $E732
Timer Counting Down (One Player)
$80/E381 E2 20 SEP #$20 $80/E383 E6 7F INC $7F $80/E385 A5 7F LDA $7F $80/E387 C9 3C CMP #$3C $80/E389 90 15 BCC $E3A0 //If incrementer less than 60, DO NOT decrement timer (incrementer increases every frame) $80/E38B 64 7F STZ $7F //Otherwise, 0 out incrementer (located at 00107F) and proceed. $80/E38D E2 08 SEP #$08 $80/E38F A5 7E LDA $7E $80/E391 38 SEC $80/E392 E9 01 SBC #$01 $80/E394 85 7E STA $7E //Decrease timer (Located at 7E107E in RAM) $80/E396 C2 08 REP #$08 $80/E398 30 74 BMI $E40E //If negative flag (Countdown at -1), jump to Game Over routine $80/E39A A9 41 LDA #$41 $80/E39C 22 B1 JSL $8180B1 //Otherwise, load 65 to A and jump to 8180B1