Mail has been fixed; you should now be able to confirm your e-mail address, watch pages, and the like.
Please report any issues on Discord.

Notes:Final Fight 2

From The Cutting Room Floor
Jump to navigation Jump to search

This page contains notes for the game Final Fight 2.


Addresses on this page correspond to the USA version unless noted otherwise.

Breakpoints

80811A, execute - accumulator holds start addresses of palette (+830000)
8180B1, execute - accumulator holds sound effect index to play

Enemy List

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 

Enemy Names

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.    |

to:

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)

Enemy Stats

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

Palettes

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

Palette Offsets

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)

Continue Screen

This is very incomplete.

Water Rising

$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