Rotwang |
Life is too short to be little...
|
|
|
Reged: 03/21/17
|
Posts: 109
|
|
|
Send PM
|
|
Re: Secrets of SFII' Rainbow (CPU opponents, in-air moves, title colors)
01/28/21 08:48 PM
|
|
|
I'm back after taking some time off from looking at this hack. I'll be covering several subjects in one post this time.
The next code hijack in this ROM happens at $26E6 which is some code that runs prior to the start of any new round. Here is what SF2RB redirects it to:
Code:
0E5000 move.w #$40, (-$6700,A5) ; $FF1900 0E5006 tst.b ($94c,A5) ; Test 2P active status 0E500A bne $e5028 ; Branch if 2P active 0E500E tst.b ($64c,A5) ; Test 1P active status 0E5012 beq $e5036 ; Return if 1P inactive (both inactive)
0E5016 move.w #$6, (-$6f10,A5) ; write to $FF10F0 0E501C move.w #$6, (-$6c10,A5) ; write to $FF13F0 0E5022 move.b (-$65ff,A5), ($94f,A5) ; ($FF1A01) copied to 2P character ID
0E5028 tst.b ($64c,A5) ; Test 1P active status 0E502C bne $e5036 ; Return if both 1P and 2P active (feature only works VS CPU) 0E5030 move.b (-$65ff,A5), ($64f,A5) ; ($FF1A01) copied to 1P character ID
0E5036 move.b ($1c,A5), D0 ; original hijacked coide 0E503A andi.w #$3, D0 0E503E rts
Before I explain what this does, here is the next hijack which is found at $2BC6, which runs once before any new match begins.
Code:
0E5040 move.w (A1,D0.w), ($9be,A5) ; Original hijacked code (this instruction only) ; Copies the next CPU opponent's character ID to 2P RAM. 0E5046 move.w ($9be,A5), (-$6600,A5) ; $FF1A00 - Preserves CPU opponent's ; character ID so it can be reset ; between rounds. This assumes ; 2P is CPU controlled. 0E504C move.b ($64f,A5), (-$6603,A5) ; 1P character ID, $FF19FD 0E5052 rts
Here's what's happening. When 1P selects a character, the program populates a table in RAM at $FFDD5E with word length player character IDs. This is the order in which the player will fight the rest of the characters.
![](https://i.imgur.com/zUbQ9UN.png)
Code:
0 = Ryu 1 = E.Honda 2 = Blanka 3 = Guile 4 = Ken 5 = Chun Li 6 = Zangief 7 = Dhalsim 8 = Dictator 9 = Sagat A = Boxer B = Claw
When the round ends and your CPU opponent has switched to some other character, that first code hijack forces the CPU's character back to what it originally was. If both players are human controlled they keep their changed character at the next round's start. Whats weird here though is that it does something extra if player 1 is the active player. It writes #6 to two addresses, and doesnt do that if 2P is the human player fighting a CPU. Not sure yet what those addresses do, but hopefully we will find out in another post.
What sub $E0040 does is just copies the CPU opponent's character ID to be retrieved by sub $E0000 before the round starts proper. It assumes 2P is CPU controlled though, possibly because a Human VS CPU game can only be started from 1P's side.
================================
The next change is a fun one. It's not even a proper code hijack either, all the hackers did was change one instruction.
Code:
0032D6 tst.b ($28e,A6) 0032DA beq $3344 0032DE tst.b ($181,A6) ; Test if player is in-air 0032E2 bne $32e6 ; Used to branch to $3344 0032E6 tst.b ($2e3,A5) 0032EA bne $3344 0032EE tst.b ($ac2,A5) 0032F2 bne $3344 0032F6 tst.b ($ace,A5) 0032FA bne $3344 0032FE cmpi.b #$c, ($3,A6) 003304 beq $3344 etc, etc...
What this change does is, you guessed it, allow the player to perform a special move in the air. The conditional branch after the byte test has been changed to simply branch to the instruction that comes right after it. I wonder why the hackers did it this way as opposed to NOP-ing out the whole comparison, but it wouldn't be the first thing I've seen in this hack that made me scratch my head.
================================
The code changes I'll cover in this section are also not hijacks. They are further tweaks to the Player VS CPU experience to account for the CPU being able to switch characters in the middle of a fight. The function these changes appear in are what "clears" a match from the world map. At the conclusion of a fight, this code checks the losing player's character ID and then clears that match from the world map. All the hackers have changed is where it reads that character ID from. Instead of retrieving it from the losing player's RAM region, it reads it from the preserved CPU character ID that was set aside in sub $E5040. So, if you were fighting CPU Guile and he turned into Zangief before you won the match, Guile's stage will be cleared on the map instead of Zangief's.
I'm not going to reverse engineer the entire function as it's long and only a few instructions have been changed. Instead I will only highlight which instructions have been modified. Basically, any instance of reading from ($291,A1) (NOTE: at this point in the code, A1 contains a pointer to the losing player's base RAM region and $291 is the offset to the player's character ID) has been changed to (-$65ff,A5).
Code:
$91DE move.b (-$65ff,A5), D0
$91F0 cmpi.b #$8, (-$65ff,A5) ; tests if defeated opponent is Dictator
$9212 cmpi.b #$8, (-$65ff,A5) ; tests if defeated opponent is Dictator (again)
$9228 move.b (-$65ff,A5), D0
$924A move.b (-$65ff,A5), D1
A side effect of this change is that this also applies to player VS player fights. If 2P has challenged 1P to a PVP game and defeats 1P, it won't clear 1P's character's stage from the map, it will clear whoever 1P's CPU opponent originally was. In the unmodified original game, the defeated opponent's stage would be cleared on the world map whoever it was.
================================
I'll end on a bit of a fluff change. The next change in ROM is only one byte long. $19E07 has been changed from #$1F to #$04. This is what changes the title screen graphic's palette assignment. OBJ palette #$04 is actually Guile's sprite palette. His American flag tattoo, yellow hair and green clothes are what give the title screen the funky colors of this hack's unofficial namesake. (EDIT: this same change appears again soon after at $19E6D, probably the first is for the smaller billboard title graphic and the second is the larger one)
![](https://i.imgur.com/q3ThI8k.png)
![](https://i.imgur.com/4aWC7zY.png)
================================
That's all for now. Hope you've been enjoying these.
Edited by Rotwang (01/28/21 10:50 PM)
|
|