SCHG

Nem s2ss

From Sonic Retro

This historical hacking document is preserved here for archival purposes.
It has not been revised since its original writing and may be outdated. For an SCHG-equivalent document, see SCHG:Sonic 2/RAM Editing.

Introduction

Here are my notes on the S2 savestate files. In order to edit these files I recommend a hex utility called Hex Workshop, and I recommend getting the emulators gens and genecyst. Gens is the one I use most of the time, but genecyst has a lot of features that are extremely useful that gens dosen't have.

First of all it's very important that you understand the basics. All data stored on a computer is in the form of 1's and 0's. On a CD for example, a laser hits the surface, and if the laser bounces back and hits the lens it's a 1, and if it dosen't it's a zero. Each 1 or 0 is called a bit, and a bit cannot have any other characters in it other that a 1 or a 0. Now the computer deals with bits in groups of 4. There are 16 possible combinations for a group of four 1's and 0's, so to make it simpler to deal with it as one value, rather than 4 (Eg. 0110 becomes 6). Now as there are 16 possible combinations for a group of 4 bits, this value to represent thier values must have 16 values itself, so rather than a simple 0-9, this value is 0-F (0123456789ABCDEF). This value is called a hexadecimal value (hex value fo short). Each hex value is dealt with in groups of 2, called a byte, each byte having 128 possible combinations. Now on a final output level the byte may be looked up on an ASCII table, which will convert that value into a recogniseable character (Eg. a byte value of 73 becomes a lowercase s on an english ASCII table). You will practically never touch the ASCII version of the code in hacking though.

Now one important thing to realise is that as one character of hex has 16 values and a decimal (real) value only has 10, it may be nessicary to convert the numbers between them from time to time. This is done with the use of a base converter (included in hex workshop). Let's say you wanted to give Sonic 50 rings. If you enter 50 as the vaue, you will in fact end up with 80, becuase that value you are entering is actually a hex value, but if you use the base converer to convert it first, you merely enter the value of 50 into the decimal box, and it will spit out a hex value of 32, which will in fact give you 50 rings in the game. Another useful utility that you will need is a hex calculator (also included in hex workshop). A hex calculator is the same as a normal calculator, but it deals with hex values rather than decimal values.

Now onto exactly what a savestate consists of. A savestate is a dump of all the ram that is allocated to the system, but that's not just main system ram, it's sound ram, CPU cache, etc. In a savestate all of this is mashed together in one file. Here's what's where in a genecyst savestate:

0-111

Unknown

112-191

C ram (byteswapped)

192-1E1

VS ram

1E2 and 1E3

A 2 byte break.

1E4-3E3

YM2612 registers

3E4-473

Some kind of sound ram (Z80 regs?)(93)

474-2473

Z80 ram (sound ram)

2474-2477

A 4 byte break

2478-12477

System ram

12478-22477

Video ram

And here's what's where in a Kgen savestate:

0-97

File header

98-2097

Z80 ram

2098-12097

System ram

12098-22097

Video ram

22098-22117

C ram

22118-223A5

Unknown (D72)

223A6-225A5

YM2612 registers

225A6-2275B

Unknown (1B6)

All the address values listed here are based on a genecyst savestate file, so if you wish to edit one of another type you'll have to convert them yourself. Now any single value that is stored in the system ram can be altered in game by use of a pro action replay code. First of all, here's an example of a Pro action replay code: FFFE10:0800 Now, the first byte in this code is FF, and a value of FF in the first two characters indicates that the code is altering data in the system ram. The next four character after it are the actual memory location in the ram, and the last four are the two byte value to write into that memory address. The pro action replay will always alter two memory addreses at a time by the way, because the Mega Drive (Genesis) is a 16 bit system. It dosen't matter though because you will find that a value will have two bytes assigned to it anyway, or the second byte will be related. In the case of the example, the first byte being altered is the current level, and the second is the current act within that level. The actual address of these values in the savestate are 12288 and 12289. An explination of why lies in the locations of the ram data that is stored in the savestate. If you look at the above table, there are 2478 lines worth of data before the system ram in the savestate, so for any action replay code you want to convert into a file location, you will need to add 2478 to the line number, and for any line number you want to convert into a pro action replay code you will need to minus 2478. Remember that these line numbers are hex values though, so you will need to do this in a hex calculator. (NOTE: Genecyst dosen't do pro action replay codes properly, use gens instead for that function).

Another thing you need to know is that each level in Sonic 2 has a value asigned to it, but this value does not correspond with each level's final position in the game. Here is a list of the level values in Sonic 2:

00

Emerald Hill zone

04

Metropolis zone

05

Metropolis zone act 3 (you should realise why later)

06

Wing fortress zone

07

Hill Top zone

08

Hidden Palace zone

0A

Oil Ocean zone

0B

Mystic Cave zone

0C

Casino Night zone

0D

Chemical Plant zone

0E

Death Egg zone

0F

Aquatic Ruin zone

10

Sky Chase zone

And here's the list for the beta:

00

Emerald Hill zone

02

Wood zone

04

Metropolis zone

05

Metropolis zone act 3 (you should realise why later)

07

Hill Top zone

08

Hidden Palace zone

0A

Oil Ocean zone

0B

Dust Hill zone

0C

Casino Night zone

0D

Chemical Plant zone

0E

Genocide City zone

0F

Neo Green Hill zone

10

Death Egg zone

And one last thing you need to know is the way that the Mega Drive stores all the art. All the art that is used in the game is stored in the form of 8x8 pixel blocks. These blocks do not actually store colours at all, they actually only have one hex value per pixel. That value specifies what point on the palette line the pixel will get it's colour from. The palette has 4 lines, each with 16 colurs on them. Now the colours on the palette can be changed at any point during play, and some palette colours may even automatically change colour each couple of frames to make it look like the colour is flashing.

Now these 8x8 blocks are not what makes up the level directly. 4 8x8 blocks are grouped together to form a 16x16 block, and it is at this point that the palette line to use for that 16x16 block is specified. The 8x8 patterns can also have thier x, y, or x and y values reversed when placing them in a 16x16 block. Also it's at the 16x16 level that the collision definitions are specified. Now finally we get to a 128x128 block, and these are the things that the actual level info loads. It is made up of 64 16x16 blocks,and each block inside them can use a different palette line. You cannot place anything except a sprite or a 128x128 block directly into a level.

Now that you know all the basics, here's my breakdown:

Internal Groups

System ram

2478-A477

128x128 block mappings

A478-B477

Level layout

B478-CE77

16x16 block mappings

CE78-????

Pattern decompression buffer

D478-FA77

Buffered sprites

FA78-FD77

Primary collision index

FD78-10078

Secondary collision index

10C78-11277

Ring positions

11478-114F7

Below water palette

114F8-11577

Unknown palette

11AF8-?????

Pattern load cue

11F78-11FF7

Above water palette

11FF8-12077

Unknown palette

Video ram

12478-1E477

Main Pattern info

1E478-1F477

Makeup of buffered foreground

1F478-20477

Patterns for text/computers/rings

20478-21477

Makeup of buffered background

21478-21C77

Patterns for sonic and tails

21C78-21EF7

Makeup of buffered active objects?

21EF8-22077

Lives counter patterns

22078-223F7

Current state of background tiles

223F8-22477

4 empty blocks

Single Variables

11278 and 11279

Camera x position

1127C and 1127D

Camera y position

1133E and 1133F

Screen y end location

11344 and 11345

Screen y start location (if a value of FF00 is specified for both start and end, the level will be y wrapped. This should not be used when water is present though or, yeah, you get the picture.

11340 and 11341

Screen x start location

11342 and 11343

Screen x end location (Set (30) back from end of level or else sonic will be able to fall off end platform.)

11346 and 11347

Camera scroll speed (speed at which camera moves to catch up to character)

11A78

Master level trigger (This trigger tells the game what you're in, be it a level, special stage, or a menu. View breakdown for table of values.)

11AC0 and 11AC1

Current Water level (specify a y axis value. Note, use bottom value as referance when in debug mode, as top value is y axis screen position with the value being taken from the top left of the screen. Also note that the y axis values work as 0 being the top of the level and increase as the character moves further down the level.)

11AC2 and 11AC3

Set water level (same as above. If the values in this variable and the one above differ, water level will automatically raise/lower as is neccisary in order for the water level to return to this point.)

11AC4

The speed at which the water moves (If this is set to 00 the water will not move if the set water level changes)

11BA8

Water on/off (must be set to 01 or above for any of the other values to be of any use at all. NOTE: Below water palette is empty on levels that don't have water, hence one will need to be entered, or everything underneath the water level will appear as black.

11BD8 and 11BD9

Sonic's Top speed

11BDA and 11BDB

Sonic's Acceleration

11BDC and 11BDD

Sonic's Deceleration

11BE8-11BEF

Sprites (includes map triggers. NOTE: this is not the actual data on the sprite locations. Read breakdown for details).

1227E

Sprite currently selected in debug mode

12281

Sprite placement mode (00=off 01 up=on)

12288

Level (hex vaue assigned to level, not level position on list. NOTE: Changing this value in level will also switch info for background movement, animated sprites, and animated palette sections.)

12289

Act

1228A

Lives (convert from decimal to hex for desired number)

12290

Continues (convert from decimal to hex for desired number)

12291

Supersonic mode (00=no 01 up=yes. This will make Sonic's tiles that of supersonic and will adjust his movement speed when in a ball, but will not shift the palette or change his acceleration, top speed or decelleration. It will also make Sonic's rings drain, but sonic will not be able to kill enemies on contact.)

Number of star polls that have been hit (based thier positions on the x axis)

12338 and 12339

Tails' max speed

1233A and 1233B

Tails' acceleration

1233C and 1233D

Tails' decelleration

123B8 and 123B9

Rings remaining to get perfect (set to 0000 for a perfect)

123E8 and 123E9

Player in special stage

123EA and 123EB

Player in game (sonic and tails, sonic alone, tails alone)

123EC and 123ED

VS mode items (teleport only, all kinds items)

123FA and 123FB

Item in level select menu that is selected (set to 16 to see the HPZ picture in the window).

123FD

Sound that is selected in options menu (value retained even out of menu)

12404

Box that is selected in options menu

12429

Number of emeralds you have

12448

Level select (set to 01 to enable)

12449

Slow motion

12468 and 12469

Demo mode (00=off 01 up=on)

12472

Debug mode (00=off 01 up=on)

Pattern breakdown

8x8 blocks (12478-1C477)
All 8x8 patterns are stored sequentially, each one taking up 32(20) bytes. One pixel takes up one hex value, not one byte. The value of this hex value being 0-16 represents the colour that pixel is on the palette, 0 being the start, and F being the end (NOTE: specifying a value of 0 will not load up the first colour on the palette line, but instead make that pixel transparent).

16x16 block mappings: (B478-CE77)
Each 16x16 block is made up of four 8x8 blocks. Delt with in blocks of 8 bytes, 2 bytes per pattern to be used in block. First value determins which palette line to use, and which orientation the pattern is at. Refer to table for explination:

Value

palette line

flipped horizntally

flipped vertically

0

1

n

n

1

1

n

y

2

2

n

n

3

2

n

y

4

3

n

n

5

3

n

y

6

4

n

n

7

4

n

y

8

1

n

n

9

1

y

n

A

2

n

n

B

2

y

n

C

3

n

n

D

3

y

n

E

4

n

n

F

4

y

n

The next three values represent the pattern number to use. Specify the number that the pattern is in the list. Past the value of 800, the block number restarts back at block 0, but the block is mirrored. The block mappings use the standard method of layout, start at x0 y0 and move across x values until end of line is reached, then repeating on next y value. If a space is blank in the 16x16 mappings, it will have the values 4000 in every box.

128x128 block mappings: (2478-A477)
Dealt with in blocks of 128 (80) bytes. Each 128 block is made up of 64 16x16 blocks, hence two bytes per 16x16 block are used. I don't know what the first value does, but the next three give the number of the 16x16 block to use.

Collision info breakdown

Final: (FA78-FD77) Based on 16x16 blocks, not 8x8 blocks. One byte per block in sequencial order. Each value creates a different responce, so a full listing will need to be compiled (FF=solid, 00=not solid).

Beta: (F478-FA77)
Based on 16x16 blocks. Two bytes per block in sequencial order. First byte seems to be some sort of special flag to do with character animation/movement when you hit the block. Most of this can be done with the second flag anyway, so that's probably why it was cut in the final version. The second byte is exactly the same variable as is present in the final version.

Sprite loading addresses (11BE8-11BEF)

The sprite information is discarded when screen moves too far away, and information is then reloaded from rom when character reenters area. These values specify a location in the rom to load the information from. The first four bytes are the address to load the sprites from when approaching from the left. The four bytes after that is the address to load the sprite info when approaching from the right. There is also another block of 8 bytes after this one that appears to be the same, but it dosen't seem to do anything. And no, it's not where to load the sprites from when approaching from the top and bottom. By transferring these values between levels, you can do some interesting things such as fighting the Death Egg in Aquatic Ruin zone.

NOTE: Altering these values to those of another level will transfer the information for the location of sprites, and the key files (definitions about movement/reactions) for the sprites, but unless the correct patterns for them are loaded into the ram, it will look like a jumbled piece of crap.

Buffered sprite breakdown

Final: (D878-F477)
Stored in blocks of 64 bytes (40) per sprite. The sprites are listed in the order that they appear starting from the top left and scrolling across x values, then beginning on next line. The following example uses address locations for the first sprite on the list as a referance. You will need to increase the line values on this list by 40(hex) for every sprite that comes before the one you want to modify.

D878

Key file to use for defining the actions/movements of sprite. 94 is lava snake, 26 is monitor, A4 is exploding star, just to name a few. Check the S2 rom breakdown section for a full list of sprites.

D87A and D87B

Patterns to use for sprite. Specify number of 8x8 block to start from, not address value.

D87C-D87F

A loading address from the rom. For what I have no idea.

D880 and D881

x position of sprite

D884 and D885

y position of sprite

D888 and D889

x speed when monitor is knocked down. (7FFF max right, 8000 max left and working back accordingly. This will make the monitor move at the specified speed either lef tor right when you knock it down.)

D892

Current animation frame of sprite

D898

Collision response (this value determines what happens when your character's sprite hits this one. A long list of different values so one will have to be compiled).

D899

Special flag for collision (Setting this value to 01 or above will set a special thing about the sprite for the collision group it belongs to. If it's set as an enemy this trigger will make you bounce off the sprite like

the enemy in Casino night. If it's a computer it will turn off collision responces all together. The other two do nothing.)

D89A

orientation of sprite (00 is normal, 01 x is reversed, 02 y is reversed, 03 y and x are both reversed. This pattern repeats all the way up to FF).

D8A0

current monitor selected (only toggle on monitors). With a monitor, the values for the desired monitor are as follows:

00: Static (Does the same thing as a robotnic monitor, but with static image instead)

01: Sonic 1UP

02: Tails 1UP

03: Robotnic (Hits character, like in later sonic games)

04: Ring

05: Fastfoot

06: Bubble

07: Invincibility

08: Teleport

09: Questionmark

0A: Broken monitor

Beyond these values you get serious screwups/lockups.

Beta: (DC78-F477)
Same as final for the most part. The definitions for the monitor are different though.

D894

current monitor selected (only toggle on monitors). With a monitor, the values for the desired monitor are as follows:

08: Weirdness (Very interesting. Appears to be the original idea for supersonic. When you bust this computer which has the picture of a questionmark monitor, the palette shifts and Sonic looks golden like supersonic. None of the other effects are done, the palette merely shifts, but it does seem to be the original idea for supersonic.)

Ring placement breakdown (10C78-11277)

One ring is defined by 6 bytes. The first byte has something to do with the ring's current status. 00 you can get the ring, but 01-7F you can't, and 80-FF the ring disappears completely. The second byte is to do with the animation of the sprite. 00 is animated, 01 up is the frame of the animation to display if the sprite is not animated (07 is the last frame for the ring animation). The second two bytes are the x location of the sprite, and the last two bytes are the y location of the sprite. All the rings are listed in a large group, and the end of this group is signalled by the 4 byte value FFFF FFFF.

Pallette breakdown

Final: (Below water: 114F8-11577, Above water: 11F78-11FF7)
A simple 12 bit RGB value. One colour on palette is represented by two bytes, and working back from the last value forward an RGB value is specified like this: 0BGR. So if you wanted that colour on the palette to be completely red, you would enter a value of 000F. The first colour on the palette is the default colour of the stage. If you had a value of 0 in one of the background tiles, this colour will be substituted in instead of making it transparent.

Pattern load cue (11AF8-?????)

Requests are processed in the order they are listed. If you try to load multiple patterns to the same area, the last one will overwrite the first. A six byte value per request. First four bytes are the address to load the patterns from the rom (eg, 0008 30D2). The last two bytes are the address to load the patterns into in the video ram. The pattern view window in genecyst is the easiest way to determine this. Note that whenever clearing out the pattern cue you must also set 11B71 to 00, or else some crap will be written over the first few patterns in the video ram. I have yet to narrow down the exact relationship this variable has with the load cue.

Master level trigger (11A78)

This trigger is the main trigger that specifies the current "mode" if you will that the game is in. Changing this will make the game switch to the mode you specify once it finishes it's current process.

00

SEGA logo

04

Title screen

08

Demo (will make the screen fade out and return to title when time reaches 27 seconds)

0C

Normal level

10

Special stage

14

Continue screen

18

2 player vs result screen

1C

2 player vs level select screen

20

End of game sequence

24

Options screen

28

Level select screen

These values repeat every (40). Values above 28 have not been used, so you get the red screen of death. If you change this value in level the screen will fade out and the data for the thing you have selected will be loaded instead. If you specify a value betwen the values I have listed, you will get some strange results.

Level design breakdown (A478-B477)

Level is delt with as a grid, starting with first tile in top left and working across to the right doing one x value at a time. One byte represents one tile in one grid location. A value of 00 is the first large tile in the database, 01 is the second, etc. The maximum possible number of large tiles on the x-axis is 127 (7F). One x line is stored in the form of 127 lines for foreground tiles, then another 127 lines for background tiles per y value. That totals an increase of 0100 per line, so if level data started at 0300 (not possible), 0300-03FF would be all the data for the top row of 128x128 tiles, 0400-04FF would be all the data for the second row of 128x128 tiles, etc.