Sonic and Sega Retro Message Board: Streets of Rage 1 Hacking - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
Page 1 of 1
    Locked
    Locked Forum

Streets of Rage 1 Hacking

#1 User is offline Dandaman 

Posted 02 August 2015 - 10:32 PM

  • Also known as Dandaman955
  • Posts: 79
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
X-Posted from SSRG. I remember someone showed an interest when I posted about my disassembly in the GS&M Thread:

Okay, lessons learned. Back up my stuff.

Basically, some of you may know that I have been working on a disassembly of the game 'Streets of Rage' for the past 6 months. Well today, my hard drive decided it didn't want anything else to do with it and decided to pack itself in. So while I'm foaming at the mouth, trying to salvage what I can to see if I haven't wasted 6 months of my life, I thought I might as well post what I've learned about Streets of Rage, while I can still remember some of the specifics.

RAM Addresses:

$FFB800 - Start of object RAM. Each entry is $80 bytes in size, and the space is $1000 bytes in size, which gives you $20 (32) objects to use at a time, excluding collectibles. During regular gameplay, $FFB800 is generally reserved for the first player, while $FFB880 is reserved for the second, meaning that the start of object RAM for everything else is $FFB900. The SSTs that I can remember are 00 (object ID, see below), 04 is the mappings offset, $10 is the X-axis coordinates (word) and $14 is the Y-axis coordinates (word). $18 is an artificial third axis which measures your height. Used when jumping. Setting this too low or high can cause the character to die, except for Round 8. $30 is the object's routine counter, $32 is the object's health, where the object is killed if it goes below 0 ($FFFF), and $34 is the object's attack power (I.e. how much damage it does to you).

$FFC980 - Seperate object RAM space that only seems to store bats and knives.
$FFCD00 - Seperate object RAM space that stores items you can pick up (presumably due to different SST handlers needed), with exception of what was listed above. $400 bytes in size, which means you can only have 8 collectible objects on the screen at the same time.
$FFF00A - Updates the current track playing.
$FFF400 - Normal palette buffer. DMAed to CRAM during VBlank, depending on whether $FFFA01 is set or not. $80 bytes in size.
$FFF480 - Target palette RAM space. Used by fading routines to fade the palettes at $FFF400, until the data matches the target palette. $80 bytes in size.
$FFFA01 - CRAM DMA flag. When set to 1, whatever's stored in the normal palette buffer will be DMAed to CRAM during the next Vint.
$FFFF02 - Level flag.
$FFFF1B - Player 1's continues.
$FFFF1D - Player 2's continues.
$FFFF20 - Player $1's lives.
$FFFF21 - Player 1's police car amount.
$FFFF23 - Player 2's lives.
$FFFF24 - Player 2's police car amount.
$FFFF46 - VDP Register 1 value, enables display.
$FFFF48 - VDP Register 1 value, disables display.
$FFFFC7 - Difficulty
00 - Easy
01 - Normal
02 - Hard
03 - Hardest (No mania options as rumoured ;V)

Music Hacking:

Whatever's written to $FFF00A will play. There is a subroutine that handles playing tracks when the IDs are stored to d7, located at $01069E.

Music IDs:


$00-$7F - Stops the music.
$80 - /
$81 - Round 1
$82 - Game Over
$83 - Title
$84 - Round 3
$85 - Round 5
$86 - Round 7
$87 - Boss
$88 - Round 8
$89 - Round 6
$8A - Select
$8B - Round 2
$8C - Round 4
$8D - Name Entry
$8E - Round Clear
$8F - Bad Ending
$90 - Last Boss
$91 - Good Ending
$92-$9F - Blank
; Start of Sound Effects
$A0 - SE 1
$A1 - SE 2
$A2 - SE 3
$A3 - SE 4
$A4 - SE 5
$A5 - SE 6
$A6 - SE 7
$A7 - SE 8
$A8 - SE 9
$A9 - SE 10
$AA - SE 11
$AB - SE 12
$AC - SE 13
$AD - SE 14
$AE - SE 15
$AF - SE 16
$B0 - SE 17
$B1 - SE 18
$B2 - SE 19
$B3 - SE 20
$B4 - SE 21
$B5 - SE 22
$B6 - SE 23
$B7 - SE 24
$B8 - SE 25
$B9 - SE 26
$BA - SE 27
$BB - SE 28
$BC - SE 29
$BD - Pause Jingle (Not in sound test)
$BE - SE 30
$BF - SE 31
$C0 - SE 32
$C1 - SE 33
$C2 - SE 34
$C3 - SE 35
$C4 - SE 36
$C5 - SE 37
$C6 - SE 38
$C7 - SE 39
$C8 - SE 40
$C9 - SE 41
$CA - SE 42
$CB - SE 43
$CC - SE 44
$CD - SE 45
$CE - SE 46
$CF - 'GO' Buzzing (Not in sound test)
; Start of Voices
$D0 - Adam's voice (Voice 1)
$D1 - Unused, higher pitch variant of Adam's voice (Not in sound test).
$D2 - Voice 3
$D3 - Voice 4
$D4 - Voice 5
$D5 - Voice 6
$D6 - Voice 7
$D7 - Voice 8
$D8 - Voice 9
$D9 - Voice 10
$DA - Boss defeated SE (Not in sound test)
$DB - Axel's voice (Voice 2)
$DC-$DF - Blank
; Special Flags
$E0 - Fade out music.
$E1 - Stop Music
$E2 - Stop Sound Effects
$E3 - Stop sound.
$E4 - ''

Palette Editing:

Streets of Rage uses a different method compared to the usual 0BGR method. It is encoded so that the subroutine it is loaded to knows exactly what palette line to load it to, which entry in that palette line to load it to (to where it is then positioned appropriately in the palette buffer) and the length of the data string. Rather than the typical bitfield:

0000 BBB0 GGG0 RRR0

...It uses:

XXXX BBBN GGGN RRRT

For instance, take the value $6EFE for instance:

XXXX BBBN GGGN RRRT
0110 1110 1111 1110

The XXXX in this case is represented by the number 6. Palette entries are $0-$F, so this one is loaded to palette entry $6 in this case. Next, the first N is 0, while the second N is 1. Group them together, and you get 01. Now look at this chart:

00 - Palette line 0
01 - Palette line 1
10 - Palette line 2
11 - Palette line 3

This shows which palette line the palette will end up in. Since this is 01, it will end up in the "1st" one. You can usually tell if an N bit is checked by it having an odd number in the number it's representing in hex. So for example, the second digit 'E' isn't odd, so the N bit isn't checked, while the third digit is, so the N bit is checked. You can't have odd numbers for palettes, so the game makes use of it before it is written to the palette buffer. In this case, T isn't checked, so the game will treat the following word as a palette, and will try to decode it. If it's the end of the palette data, set T to 1 (or put an odd number into the final digit). Afterwards, the original data is anded by $0EEE (White, as you can't get a higher value than that), and the value is positioned appropriately in the palette buffer. $6EFE anded by $0EEE is $0EEE, so white will be moved to palette line 1, entry 6 during the next CRAM DMA in VBlank (Setting $FFFA01 to 1 activates it, otherwise CRAM DMA is skipped).

SUBROUTINE ADDRESSES:


$010538 - Loads the target palette into a2, sets the CRAM DMA flag and then decodes the palettes into the buffer at $010548.
$01053E - Loads the palette buffer into a2, sets the CRAM DMA flag and then decodes the palettes into the buffer at $010548.
$010548 - Palettes are decoded here into the appropriate position relative to a2.

Objects:

The object list is found at $00B238 and each entry is a word in size. The entries go in the following order:

Object Lists:

01 - Main character
02 -
03 -
04 -
05 - Police car
06 - Character select cursor controller
07 - Main characters on the select screen
08 - Knife
09 - Bottle
0A
0B - Pipe
0C - Pepper
0D -
0E -
0F -
10 -
11 - Phone box
12 -
13 -
14 -
15 - Statue
16 - Can
17 -
18 - Stacks of tyres
19 - Barrel / Oil Drum
1A -
1B -
1C - Luminous Stand
1D - Roadblock
1E -
1F -
20 - Galsia holding knife
21 - Passive Galsia
22 - Galsia
23 - Galsia holding long weapon
24 - Signal
25 - Hakuyo
26 - Nora
27 - Jack
28 - Jack's Axes/Fire sticks
29 -
2A - Group of 3 Hakuyos
2B -
2C -
2D -
2E -
2F -
30 - Abadede
31 -
32 -
33 - Mr X's body sitting down
34 - Mr X's legs sitting down
35 -
36 -
37 - Mr X defeated?
38 -
39 -
3A -
3B -
3C -
3D -
3E -
3F - Money
40 - Gold bars
41 - Wooden crates
42 - Industrial crushers
43 -
44 -
45 - Dinner table
46 -
47 - Meat
48 -
49 -
4A - Baseball bat
4B - Apple
4C - Extra life
4D -
4E - Round 3's trees
4F - Mini police car
50 -
51 - Door and window (Round 7)
52 -
53 -
54 - Garage door
55 - Souther
56 - Antonio
57 - Bongo
58 - Yasha & Onihime (separate objects, 2 are loaded at a time)
; There's more, but this is all I recognise, ATM.


This stuff is pretty bare-bones, but it's all I can remember at the moment. Expect it to be updated should I ever get hold of my source again. I do have a lot of cool stuff that I would like to post (song locations, more on music hacking, screen modes, art locations, etc.), so fingers crossed that my HDD isn't too badly damaged.

#2 User is offline Overlord 

Posted 03 August 2015 - 01:27 PM

  • Substitute Meerkovo IT Chief
  • Posts: 16061
  • Joined: 12-January 03
  • Gender:Male
  • Location:Berkshire, England
  • Project:VGDB
  • Wiki edits:3,204
Best of luck recovering your data - remember kids, keep your backups up to date! Ideally 3 copies of everything, on 3 different physical objects (and if one is at someone you trust's house and you swap it periodically when you go there, even better!)

Any information you do glean back will be of value in some form, though.

#3 User is offline Vangar 

Posted 11 August 2015 - 06:03 PM

  • Posts: 3408
  • Joined: 08-January 04
  • Gender:Male
  • Location:Australia
  • Wiki edits:2
That sucks. If you try again, maybe backup your work on Bitbucket or something.

#4 User is offline Dandaman 

Posted 13 October 2015 - 10:04 AM

  • Also known as Dandaman955
  • Posts: 79
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
Update with some stuff that I missed/need to cover:

It's extremely unlikely that I'm going to be able to recover this. I had a look at the HDD and if you reflect it against the light, it has little ring-shaped bending around it, and what looks to be a dent. Whatever, it can be started again. Anyway, this might be my last update until I start working on this again, since I forgot to post these, but didn't have a computer to do it on.

The following decompression routines (or just routines in general) use the same decompression routines as Sonic 1, word for word, which leads me to believe that they were supplied by a devkit.

$000003BA - Screen mode pointers.
$00008138 - Controller-reading subroutine.
$00008192 - Nemesis decompression subroutine.
$000082D6 - Enigma decompression subroutine.
$00008454 - LoadPLC
$00008484 - LoadPLC2/AddPLC routine from Sonic 1, except ClearPLC is built into it, rather than having it branch out.
$000084BA - RunPLC_RAM (word for word, except with the RAM addresses being different).
$000085A2 - Kosinski decompression subroutine.
$00008642 - RunPLC_ROM (word for word, with the exception of the starting lea being pc-relative).
$00008672 - ArtLoadCues table.
$0000A63A - Nemesis pointer table. Before branching, d0 must contain 4 separate bytes: d0 - ZZYYXXWW, which is a pointer. The subroutine
has a table that has a pre-written VRAM address and a Nemesis-compressed source. The subroutine reads the first byte,
rotates it to the right (XX read next) until they've all been read. If it contains a 00, it is skipped. The byte is used as
an ID for the table, where the VRAM address is loaded to the control port of the VDP and the Nemesis source is ran through
NemDec.
$0000B748 - Similar to the above table, but uses Kosinski pointers, RAM addresses instead of VRAM and doesn't check the other byte entries.
*NOTE* There is a table for Enigma similar to the three above, but I can't remember the address.
$00010502 - WaitforVBlank/DelayProgram routine.
$00010514 - Seperate WaitforVBlank/DelayProgram routine that IIRC, branches to a different mode during VBlank. Bit vague, sorry.
$00010576 - Palette fade out routine.
$000105CC - Palette fade in routine.
$00019D1A - VBlank routine.
$0001A166 - Start of HUGE DMA table (I think it's sprite table data).

$FFDCD0 - PLC address queue.
$FFF600 - Nemesis decompression buffer.
$FFFB0C - Palette-fading variable.
$FFFC04/08 - Controller variables.
$FFFF00 - Screen mode.

It's probably worth mentioning that there are a few variations of PlaneMaptoVRAM/ShowVDPGraphics, but I can't seem to remember their locations. I do remember that some were modified to load the amount of X-tiles and Y-tiles as a header from the mappings, though. Anyway, I think that's all I have now. If I do happen to remember anything, I will post it here.

#5 User is offline Master Emerald 

Posted 03 November 2015 - 08:34 AM

  • Posts: 3029
  • Joined: 14-December 07
  • Gender:Male
  • Location:Rio de Janeiro - Brazil
  • Project:College
  • Wiki edits:22
Interesting, I was kind of expecting this to be burried in the rom but not referenced, as it has an entry in the sound test as 'Name Entry'.

#6 User is offline Dandaman 

Posted 03 November 2015 - 07:19 PM

  • Also known as Dandaman955
  • Posts: 79
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
It's a possibility, although it's worth a note that the Round Clear and Name Entry entries share the same pointer ($7D91C). Didn't really get to working on much of the sound, as I wanted the main code/art/mappings finished first. I'm close to finishing another disassembly, so when that's finished, I'll give SoR another shot.

#7 User is offline Xilla 

Posted 03 November 2015 - 07:47 PM

  • No promotion for you, laddy.
  • Posts: 346
  • Joined: 08-September 05
  • Gender:Male
Speaking of unused tracks. Up and Up is an extended version of the Stage 7 theme Violent Breathing. I was thinking the Name Entry music was possibly an unused portion of another track, but Yuzo also uploaded that one and it's the same as the OST. To me it was probably meant to be used for a seperate Enter Your Initials screen cut from the final game (possibly after a Game Over).
This post has been edited by Xilla: 03 November 2015 - 07:54 PM

#8 User is offline evilhamwizard 

Posted 20 February 2016 - 09:17 PM

  • Posts: 1252
  • Joined: 16-June 04
  • Gender:Male
  • Wiki edits:109
Hijacking this thread because I'm also taking a gander at SoR1 (trying to see how feasible a 3 player hack would be). I found something very cool.

As far as cheats go, the game is a bit bare. However, I found a small cheat that goes unused in the final and can only be accessed by hacking. This is from REV01.

During development, the devs included a cheat that could be accessed depending on the name you put if you get a high score and die. Depending on the name you put in, you can get 0, 1, 7, 9, 73, and 144 lives and based upon where the name you enter appears in the name value array, you receive that amount of cop car calls (+1 I think).

This code is as follows, and is meant to be called when you die:

ROM:00005920 ; ---------------------------------------------------------------------------
ROM:00005920                 lea     (RAM_Player1Name).w,a1 ; unused
ROM:00005924                 cmpa.w  #$B800,a0
ROM:00005928                 beq.s   loc_592E
ROM:0000592A                 lea     (RAM_Player2Name).w,a1
ROM:0000592E
ROM:0000592E loc_592E:                               ; CODE XREF: ROM:00005928j
ROM:0000592E                 move.l  (a1),d0
ROM:00005930                 lea     Array_DevNames,a1 ; mom
ROM:00005934                 moveq   #5,d7
ROM:00005936
ROM:00005936 compare:                                ; CODE XREF: ROM:0000593Aj
ROM:00005936                 cmp.l   (a1)+,d0
ROM:00005938                 beq.s   match
ROM:0000593A                 dbf     d7,compare
ROM:0000593E                 rts
ROM:00005940 ; ---------------------------------------------------------------------------
ROM:00005940
ROM:00005940 match:                                  ; CODE XREF: ROM:00005938j
ROM:00005940                 lea     (RAM_Player1Lives).w,a1
ROM:00005944                 cmpa.w  #$B800,a0
ROM:00005948                 beq.s   loc_594E
ROM:0000594A                 lea     (RAM_Player2Lives).w,a1
ROM:0000594E
ROM:0000594E loc_594E:                               ; CODE XREF: ROM:00005948j
ROM:0000594E                 move.b  d7,(RAM_CopCallAdder).w
ROM:00005952 ; START OF FUNCTION CHUNK FOR sub_565C
ROM:00005952
ROM:00005952 loc_5952:                               ; CODE XREF: sub_565C+1Ej
ROM:00005952                 move.b  byte_5970(pc,d7.w),(a1) ; Predicted (Code-scan)
ROM:00005956                 rts                     ; Predicted (Code-scan)


All the code up to 5952 is unused and can only be touched by hacking. The game does see 5952, but sub_565c will only branch to it when the value at FFFFFF35 in RAM is greater than 0, which is impossible to achieve without hacking as well. What's interesting is that even when FFFFFF35 is set to a number greater than 0, it's still not enough to take advantage of the cheat since it doesn't acknowledge the name you entered and will give you no additional cop car calls (besides the 1+ the game gives you when you die). I have no idea why they left that jump in particular in since it's never called and does nothing when called anyway, but it's clear that the game was originally meant to jump to 5920 instead. My only guess was that it was probably changed late because they didn't want people entering names from the array to get special bonuses (make it more fair, etc).

The list of names the game checks yours against are very interesting. They're all names of the devs!

(note: a = 01, b = 02, etc)
ROM:00005958 Array_DevNames: dc.l $D0F0D             ; DATA XREF: ROM:00005930o
ROM:00005958                                         ; mom - Hiroshi Momota (programmer)
ROM:0000595C                 dc.l $13150E            ; sun - Little Sun (programmer)
ROM:00005960                 dc.l $150409            ; udi - Unknown (designer)
ROM:00005964                 dc.l $20F00             ; ore - Unknown (sound driver)
ROM:00005968                 dc.l $F1205             ; bo - Tokuhiko Uwabo (sound driver)


To unlock the ability to use the cheat, do the following in REV01:

1.) Disable the checksum check and run the game in an emulator that lets you edit ram
2.) Modify your rom at $567a from 660002D6 to 660002a4
3.) Run the game and go to the memory editor in your emulator and go to FFFFFF35, change value from 00 to 01
4.) Play the game and get a high score (you can modify your score at FFFFFF08)
5.) Die, and when the game asks you to enter your name, enter one of the names listed above and use one of your continues.

Depending on the name you use, you will receive a certain number of lives and cop car calls. I believe to net the highest benefit your name has to be "MOM", which should get you 144 lives and 5+1 cop car calls.
This post has been edited by evilhamwizard: 21 February 2016 - 03:42 PM

#9 User is offline Dandaman 

Posted 22 February 2016 - 12:32 PM

  • Also known as Dandaman955
  • Posts: 79
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
Now THAT is interesting! Never even seen that when I was working on it. One note though is that it's better to change it to 6700 (beq.w) instead of 6600 (bne.w), so you don't have to set $FFFFFF35 to 1. Anyone who wants to see this can use the game genie codes ABMA-AR54 and YVMA-AED6, and use a continue with the highest score on game over (100,000).

#10 User is offline Dandaman 

Posted 09 July 2016 - 06:30 PM

  • Also known as Dandaman955
  • Posts: 79
  • Joined: 30-August 09
  • Gender:Male
  • Location:UK
  • Wiki edits:30
Isn't exactly new, but there was never a way stated to access it, so for documentation's sake:

Posted Image

An unused palette for Souther!

To access it, input the game genie code PMBT-DK6A and get to the end of Round 2.
This post has been edited by Dandaman: 09 July 2016 - 06:30 PM

Page 1 of 1
    Locked
    Locked Forum

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users