Hacking the ST rom


Here is my to do list in priority. And they’re not on the same level either.

High (Won’t be another release until fixed one of these is fixed)
KO Slow Down Removed(On everything)
Fix Throws to behave properly at low health (No standing)

Player 2 character is the stage*

Select AI*
Any Debug features(If I find them, might have to remove sprites either background to prevent flickering and more slowdown)*

Really Low
Remove timer graphics
Allows Supers to be done any time
Add Free Play on non-phoenixed sets

  • If it requires 10th rom won’t bother with it for awhile. When I’ll attempt a more proper training mode.


I love you jed.


Freeplay only on US board.

Also thanks jed, doing great work.


Slow down fix would make it very usable for training!
Thanks for the Amazing hack


If anyone is interested, I’ve published the first post of a series that will explain how to debug the Super Street Fighter II Turbo ROM in MAME. The first post explains how to create a “change difficulty” cheat: http://pof.eslack.org/2014/03/25/hacking-super-street-fighter-ii-turbo-part-1/


Nice, You could of looked at or talked about the memory map of the cps2 to help decide what needed to be changed instead of guessing.

0x000000 - 0x3FFFFF Main Program

0x400000 - 0x40000A - Encryption(aka the battery memory on pheonixed roms it's 0xFFFFF0 - 0xFFFFFA)

0x618000 - 0x619FFF Shared ram for the Z80 aka tells what sfx or music to play.

0x660000 - 0x663FFF Network Memory

0x900000 Start of Graphic memory can change with each game.

0x900000 - 0x903FFF Palette
0x904000 - 0x907FFF 16x16
0x908000 - 0x90BFFF 32x32
0x90C000 - 0x90FFFF 8x8
0x910000 - 0x913FFF 16x16 mainly hud and character names on select screen

0xFF0000 - 0xFFFFFF - Main Memory


Thanks jedpossum, I updated the post and added your information. Btw, I’ve published part two here: http://pof.eslack.org/2014/04/08/hacking-super-street-fighter-ii-turbo-part-2/ it explains some very basic concepts of m68k assembly needed to do ROM patching, and includes a couple of new MAME cheats. Hopefully someone will find it useful :slight_smile: Again, I appreciate any comments :smiley:


Playing as CPU in GGPO might be fun. You pick Guile, people spectate and wonder how the fuck you walk up Boom or Flash Kick. But, I suppose, people would need the hacked ROM to see matches.


You don’t have to do a rom hack it’s a simple flag in the memory.

Got bored and decided to do some projectile hacking.

For St I’ve only started found the projectile speed table.

Every one uses the same table and just reads at different places.

Start 0x2F8800



Would it be possible to edit ST to allow characters to move before and after the round? That’s my favorite feature in some CE hacks


awesome hack jedpossum, n ken needs that fb buff!


Well the table is shared with most characters I haven’t tested all the characters even old characters.

So, if I edit speed 300 and 400 it would apply to both N.Ryu’s and N.Ken’s Light and Medium Fireball speed.

Fireballs work differently in this engine compared to alpha engine. In the alpha engine each projectile was separately programmed with it’s own table in the later games that even change how it moves. Like Lilith’s Soul Spark has amount of hits, X speed, and a timer. While Lei lei’s item projectile is just four jump parabolas. And Anak’s curse only has x speed and y speed.


New post on my blog, presenting a new training mode using MAME cheats.


You know, you could of easily asked for the addresses instead of comparing the roms.

My notes for the hack


Mid Match
Adr - FE8E
Hex - 1B40 0DD0

Character Select
Adr - ECDA
Hex - 637C

Doesn't drain
Adr - 27FA8
Hex - 422E 02C4

377C 0090 

Throw 1
Ko Slow Down
Adr - 4A96
Hex - 4EB9 0007F2B2

---Throw 3---
Adr - 49C2
Hex - 377C 0090 

Remove KO knock down
Adr - 49E6 
Hex - 177C 0002

Character Select
Adr - E2FC | ECBE | ECCA
Hex - 303C 0034

Hex - 357C 0090

Ko Slow Down
Adr - 
Hex - 

Regular Hits
Life Refill
ADR - BE64C (3E64C)
Hex - 357C 0090

Ko Slow Down

Random Notes
P1 -- p2 + 400 
ADR = FF844E

How long push box is gone after a throw
Original ASM
move.b #$1C,($DE0, A5)
1B7C 001C 0DE0


Thanks jedpossum! Updated the cheat file with your notes.


Vampire Savior Stage Selection

A5 = 0xFF8000 -- Settings,various timers you know global data.

jsr     $ae7c.l
	lea     ($400,A5), A0 --Loading p1 slot
	lea     ($800,A5), A1 --Loading p2 slot

--If versus
tst.b   ($131,A5)
bne     $aea8

lea     ($15be,PC), A2; ($c468) --Stage table pointer being loaded

jsr     $14e8a.l -- This sub routine is everywhere but here it aids in the randomization of stages.
	move.w  ($d4,A5), D0 
	move.w  D0, D1
	add.w   D0, D0
	add.w   D1, D0
	lsr.w   #8, D0
	add.b   D0, ($d5,A5)
	move.b  D0, ($d4,A5)
	move.b  ($d5,A5), D0

andi.w  #$f, D0
moveq   #$0, D1
move.b  ($382,A1), D1
lsl.w   #4, D1
add.w   D0, D1

move.b  (A2,D1.w), D0 --Stage has been selected

move.w  D0, ($100,A5) --and now part of the main memory

I know this isn’t ST, but some one could potentially add a weighted randomization to stages. It needs some reworking as stage values in Vsav are always even. Also, finding a nice place in the code to add this routine.


I haven’t been following this thread so i don’t know if anyone has gone over this yet and if so im sorry but im wondering how hard it would be to normalize the speed of all the stages and if so to release a rom with only that change ?

Edit: Actually as an addition to that if such a change were to be made what would be considered the baseline stage that all the others would be changed to follow ?


As a way to normalize speed would be getting rid of the sprites in the background like I did in Birdie’s A2 stage a long time ago.

A true base line would be absolutely nothing no bg layers, no bg sprites, no raster effects, no palettes, even getting rid of the slowdown mechanic from fireballs on the stage were the cpu is just processing the characters and maybe the hud.


A step closer to random stages.

It’s not much so far since the character select timer doesn’t move in my training mode hack.

Address 39A6 
jsr $ccc10.l

Address CCC10 
move.w($61d2,A5), D0
andi.w #$f, D0
move.w d0 ($c4e,A5)
add.w d0,d0

Address 39A6 (rom 3)
4EB9 000CCC10

Address CCC10 (4CC10 rom 4 )
302D 61D2
0240 000F
3B40 0C4E

I found a place to add the code in the roms.

Now with the code added in full with the character select timer enabled.

edit 2
GGPO test and jsr change 2
Look at that Battle Number



Nothing to do with stages,but I seen this branch when trying to edit ryu’s jab dp.

A5 = FF8000

077FE2: bsr     $78132 
078132: lea     ($44e,A5), A6		;Setting player Player 1
078136: bsr     $7813e			;Branch so it A6 doesn't become player 2's address yet
	07813E: move.l  ($6,A6), D0		;Loading the actual X Position
	078142: sub.l   ($1cc,A6), D0	;Subtracting old position with new
	078146: move.l  D0, ($1c4,A6)	;Supposed X Movement
	07814A: move.l  ($a,A6), D0		;Loading the actual Y position
	07814E: sub.l   ($1d0,A6), D0	;Subtracting old position with new
	078152: move.l  D0, ($1c8,A6)	;Supposed Y Movement
	078156: rts						;Return

07813A: lea     ($84e,A5), A6		;Setting player Player 2
07813E: move.l  ($6,A6), D0			;Loading the actual X Position
078142: sub.l   ($1cc,A6), D0		;Subtracting old position with new
078146: move.l  D0, ($1c4,A6)		;Supposed X Movement
07814A: move.l  ($a,A6), D0			;Loading the actual Y position
07814E: sub.l   ($1d0,A6), D0		;Subtracting old position with new
078152: move.l  D0, ($1c8,A6)		;Supposed Y Movement
078156: rts							;Return

The thing is there is nothing reading those movement values which what this branch is making. So in normal play this branch useless and just a left over of a debug display.

The reason I note this is that it’s a nice place to hook into since this isn’t really used.

Added the all of it.

Also looking into it more this branch does have it’s use does have a use in normal play sorta. Only when players push boxes are touching each other does it get read but it’s not used to calculate which one moves either. Removing the above to not write a value seems to do nothing.


As always A5 = FF8000

0BF6E2: bpl     $bf6e8
0BF6E8: move.l  ($612,A5), D2 ;Reading P1 "X Speed" and putting it on D2
0BF6EC: lsr.l   #8, D2
0BF6EE: tst.w   D2
0BF6F0: bpl     $bf6f4 ;Yes, there is a neg.w command after this branch if value negative.
0BF6F4: move.l  ($a12,A5), D3 ;Reading P2 "X Speed" and putting it on D3
0BF6F8: lsr.l   #8, D3
0BF6FA: tst.w   D3
0BF6FC: bpl     $bf700 ;Same as above
0BF700: cmp.w   D2, D3
0BF702: beq     $bf75a ;Branch past the rts if D2 and D3 are equal
0BF704: bcs     $bf730
0BF730: sub.w   D6, ($454,A5) ;Where did D6 get written? Why is it needed? What the fuck?
0BF734: sub.w   D0, ($454,A5)
0BF738: add.w   D6, ($854,A5) ;Where did D6 get written? Why is it needed? What the fuck?
0BF73C: move.b  #$1, ($5ae,A5)
0BF742: move.b  #$0, ($9ae,A5)
0BF748: tst.b   D6
0BF74A: bmi     $bf72e
0BF74C: move.b  #$0, ($5ae,A5)
0BF752: move.b  #$1, ($9ae,A5)
0BF758: rts

the if equal part
BF75A: sub.w   D6, ($454,A5) ;Where did D6 get written? Why is it needed? What the fuck?
BF75E: add.w   D6, ($854,A5) ;Where did D6 get written? Why is it needed? What the fuck?
BF762: move.b  #$1, ($5ae,A5)
BF768: move.b  #$0, ($9ae,A5)