Nem s1
From Sonic Retro
Revision as of 16:49, 24 March 2020 by Black Squirrel (talk | contribs) (Text replacement - " Block mappings==" to " block mappings==")
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 the Hedgehog. |
Contents
- 1 Introduction
- 2 Address listing
- 3 Offset indexes
- 4 Main level load block
- 5 Pattern load cues
- 6 Collision definitions
- 7 Level layout
- 8 Sprite placement
- 9 Main level block mappings
- 10 Uncompressed art
- 11 Mappings for Sonic
- 12 Sega intro sound
- 13 Art compression format
- 14 Animated pattern load cues
- 15 Palettes
- 16 Character start location array
- 17 Music playlist for levels
- 18 Level order
- 19 Object debug list
- 20 Dynamic screen resizing
- 21 Music/Sound FX pointers
- 22 Sprite programming
- 23 References
Introduction
Here are my hacking notes on the Sonic 1 ROM. If you use these notes I'd appreciate it if you would mention it with your hack or your utility, so that other people can find their way here. For hex editing I recommend you use a hex utility called Hex Workshop, and for emulators I recommend you get both Gens and Genecyst. Genecyst may be old and kinda crap, but it has a whole heap of debug outputs that really help when it comes to seeing exactly what it's doing and when.
First of all it's very important that you understand the basics. All data stored on a computer is in the form of 1s and 0s. 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 doesn’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 1s and 0s, so to make it simpler it deals 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 their 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 for 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 recognisable 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 necessary 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 value, you will in fact end up with 80, because that value you are entering is actually a hex value, but if you use the base converter 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.
Another thing you need to know is that each level in Sonic 1 has a value assigned 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 1:
00 | Green Hill zone |
01 | Labyrinth zone (act 4 is scrap brain zone 3) |
02 | Marble zone |
03 | Star Light zone |
04 | Spring Yard zone |
05 | Scrap Brain zone (act 3 is Final zone) |
One other 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 its colour from. The palette has 4 lines, each with 16 colours 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 make 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 their 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 256x256 block, and these are the things that the actual level info loads. It is made up of 256 16x16 blocks, and each block inside them can use a different palette line. You cannot place anything except a sprite or a 256x256 block directly into a level.
Now that you know all the basics, here's my breakdown:
Address listing
For the most part, there are no breaks in this list. If one address follows on directly from another on this list, it does so in the rom, with the exception of data that comes before 1D000. All the compiled code that is used in the game is stored in this section, and that's a pain in the ass to sort through, so there will be many breaks there. The column on the left lists it's file location, the column in the middle contains it's name and description, and the column on the right will contain any special notes about it, such as compression format used if applicable, and number of blocks an art tile uses. The right column will also contain a link with the text further info, if that particular block requires it. That link will jump to a detailed explanation of that thing. Anything linked like that will also be listed in the contents at the top of the page. Also, any patterns that are not used anywhere in the game will be preceeded by this red dot .
0-FF | Vector table | |
100-200 | Header | |
438-5B8 | Platform error messages (ASCII text) | |
5F0-B0F | Standard numbers/symbols | Uncompressed Further info |
1B66-1CA9 | Unknown palettes | |
1D0A-1DAB | Unknown palettes | |
20C0-20FB | Unknown palette | |
2168-2207 | Palette pointers | Further info |
2208 | SEGA screen palette | Further info |
2288 | Title screen palette | Further info |
2308 | Level select palette | Further info |
2388 | Primary palette line | Further info |
23A8 | GHZ level palette | Further info |
2408 | LZ level palette | Further info |
2468 | LZ underwater level palette | Further info |
24E8 | MZ level palette | Further info |
2548 | SLZ level palette | Further info |
25A8 | SYZ level palette | Further info |
2608 | SBZ level palette | Further info |
2668 | FZ level palette | Further info |
26C8 | Special stage palette | Further info |
2748 | SBZ act 3 level palette | Further info |
27A8 | SBZ act 3 underwater level palette | Further info |
2828 | SBZ act 3 primary palette line | Further info |
2868 | Special stage results palette | Further info |
28E8 | Unknown palette | Further info |
2928 | Ending sequence level palette | Further info |
337A-339F | Level select level order | Further info |
379A-37A0 | Music playlist for levels | Further info |
4100-4117 | 16x16 collision index pointers | Further info |
4E42 | Continue screen (sprite) | |
4F5C | ??????? (sprite) | |
53E2 | ??????? (sprite) | |
553C | ??????? (sprite) | |
5616 | ??????? (sprite) | |
59E2 | ??????? (sprite) | |
5AC2 | ??????? (sprite) | |
6112-6181 | Character start location array | Further info |
6DD0-6DDD | Offset index for dynamic screen resizing | Further info |
6DDE | GHZ dynamic screen resizing | Further info |
6EF2 | LZ dynamic screen resizing | Further info |
6F8E | MZ dynamic screen resizing | Further info |
70F2 | SLZ dynamic screen resizing | Further info |
7168 | SYZ dynamic screen resizing | Further info |
720A | SBZ dynamic screen resizing | Further info |
7326 | Ending sequence dynamic screen resizing (empty) | Further info |
7328 | ??????? (sprite) | |
7952 | ??????? (sprite) | |
7CA2 | ??????? (sprite) | |
7E32 | ??????? (sprite) | |
81A8 | ??????? (sprite) | |
8210 | Collapsable platform (sprite) | |
8320 | Platform in MZ made up of blocks that breaks. (sprite) | |
87CA | ??????? (sprite) | |
885E | ??????? (sprite) | |
8934 | ??????? (sprite) | |
8B4C | Double big red explosion (sprite) | |
8C1C | Big red explosion (sprite) | |
8CF2 | ??????? (sprite) | |
8D62 | Normal explosion (sprite) | |
8DF6 | Large explosion (sprite) | |
8F22 | ??????? (sprite) | |
9412 | ??????? (sprite) | |
94F0 | Crab enemy from GHZ (sprite) | |
97DE | Buzz bomber (sprite) | |
9932 | ??????? (sprite) | |
9B26 | ??????? (sprite) | |
9CB6 | Rings flying out from being hit (sprite) | |
9E06 | Large golden ring (sprite) | |
9ED6 | Special stage entry effect (sprite) | |
A118 | ??????? (sprite) | |
A302 | Contents of monitor flying up frm monitor being busted (sprite) | |
A61C | ??????? (sprite) | |
A69C | ??????? (sprite) | |
AB20 | ??????? (sprite) | |
ABDA | ??????? (sprite) | |
ACA4 | Drill badnick in LZ (sprite) | |
AEB8 | Platfrom in MZ that moves up and down (sprite) | |
B1DC | ??????? (sprite) | |
B39E | ??????? (sprite) | |
B67C | Metal block with spikes on bottom from MZ (sprite) | |
B99A | Sideways spikes that were cut in MZ (sprite) | |
BD2E | Button in MZ (sprite) | |
BED2 | Moveable block in MZ (sprite) | |
C306 | Title card (sprite) | |
C4B8 | "Game over" sprite (sprite) | |
C572 | End of level results screen (sprite) | |
C6F4-C723 | Main game level order | Further info |
C7AE | End of special stage results screen (sprite) | |
C956 | Bubble (sprite) | |
CE28 | Spikes (sprite) | |
D050 | Rock from GHZ (sprite) | |
D0BE | ??????? (sprite) | |
D11C | Breakable barrier from GHZ (sprite) | |
D382-D5B1 | Object pointer list | Further info |
D5B2 | ??????? (sprite) | |
DABE | Red spring (sprite) | |
DD68 | Badnick that appears behind wall and fires projectile from GHZ (sprite) | |
DFFA | ??????? (sprite) | |
E1D4 | Wall barrier from GHZ (sprite) | |
E296 | ??????? (sprite) | |
E304 | ??????? (sprite) | |
E4E0 | ??????? (sprite) | |
E7D0 | ??????? (sprite) | |
E90C | ??????? (sprite) | |
E9D0 | Bumper (sprite) | |
EB28 | ??????? (sprite) | |
ED84 | Lava spurt with lava ripples (sprite) | |
EE70 | Lava spurt (sprite) | |
F05E | Lava wave from MZ (sprite) | |
F1B8 | Sprite for lava hurting you (sprite) | |
F61A | Motobug from GHZ (sprite) | |
F806 | ??????? (sprite) | |
F83A | That ground based badnick with spikes ontop from SYZ (sprite) | |
FC92 | Breakable block in MZ (sprite) | |
FDF8 | ??????? (sprite) | |
100A8 | Bat from MZ (sprite) | |
10286 | ??????? (sprite) | |
10782 | ??????? (sprite) | |
10976 | Same as above, but different image (sprite) | |
10AD2 | Raising platforms from SLZ (sprite) | |
10D5A | Platform moving in circular motion in SLZ (sprite) | |
10E90 | Lowering staircase from SLZ (sprite) | |
11044 | Pylon in foreground frm SLZ (sprite) | |
110C6 | ??????? (sprite) | |
11206 | ??????? (sprite) | |
11346 | ??????? (sprite) | |
1141A | ??????? (sprite) | |
114FC | Fan from SLZ (sprite) | |
1163C | See saw without spikeball (sprite) | |
119F6 | Walking bomb (sprite) | |
11CCE | Badnick surrounded by spikeballs that shoots them at you (sprite) | |
11F04 | ??????? (sprite) | |
11FD4 | ??????? (sprite) | |
121E8 | Stone head that launches projectile in LZ (sprite) | |
1233C | ??????? (sprite) | |
126A4 | Small bubble (sprite) | |
12A9E | ??????? (sprite) | |
12BD8 | Sonic (sprite) | |
13C98 | ??????? (sprite) | |
14158 | ??????? (sprite) | |
14254 | Old special entry effect (sprite) | |
142F0 | ??????? (sprite) | |
1509A | Spinning wheel in SBZ that shoots you off in different directions (sprite) | |
154E2 | ??????? (sprite) | |
1568E | ??????? (sprite) | |
15730 | ??????? (sprite) | |
1597C | ??????? (sprite) | |
15C12 | ??????? (sprite) | |
15FF8 | ??????? (sprite) | |
16146 | ??????? (sprite) | |
1626A | ??????? (sprite) | |
1652A | Big moving rectangle in SBZ (sprite) | |
16668 | ??????? (sprite) | |
16934 | Catakiller (sprite) | |
16E2E | Starpoll (sprite) | |
1715E | ??????? (sprite) | |
17264 | ??????? (sprite) | |
17700 | Robotnic in his primary ship (sprite) | |
17AE4 | Large ball from GHZ that was cut (sprite) | |
17E36 | ??????? (sprite) | |
18230 | Robotnic flying his default ship (sprite) | |
186A4 | ??????? (sprite) | |
188B8 | ??????? (sprite) | |
18CCE | ??????? (sprite) | |
190EE | ??????? (sprite) | |
19692 | ??????? (sprite) | |
19832 | ??????? (sprite) | |
19B60 | ??????? (sprite) | |
19D58 | ??????? (sprite) | |
1A44E | ??????? (sprite) | |
1A7DA | ??????? (sprite) | |
1AB22 | Egg prison (sprite) | |
1B984 | Sonic in special stage (sprite) | |
1C022 | ??????? (sprite) | |
1C046-1C053 | Offset index of animated pattern load cues | Further info |
1C054 | GHZ animated pattern load cue | Further info |
1C112 | MZ animated pattern load cue | Further info |
1C1AE | Unknown animated pattern load cue | Further info |
1C1EC | SBZ animated pattern load cue | Further info |
1C2A2 | End of game sequence animated pattern load cue | Further info |
1C3B6 | LZ/SLZ/SYZ animated pattern load cue (empty) | Further info |
1C548 | ??????? (sprite) | |
1CADA-1CF19 | Big and small numbers used on counters in game | Uncompressed Further info |
1D16E-1D17B | Offset index of object debug lists | Further info |
1D17C | GHZ object debug list | Further info |
1D1FE | LZ object debug list | Further info |
1D2C8 | MZ object debug list | Further info |
1D35A | SLZ object debug list | Further info |
1D3D4 | SYZ object debug list | Further info |
1D44E | SBZ object debug list | Further info |
1D538 | Ending sequence object debug list | Further info |
1D5A2 | Main level load blocks (patterns/16x16/256x256/palette) | Further info |
1D612 | Offset index of pattern load cues | Further info |
1D652 | Pattern load cues | Further info |
1DB12 | Data block acting as seperator | |
1DC00 | "SEGA" Patterns | Art compression 123 blocks |
1E26E | Patterns for foreground in intro | Art compression 254 blocks |
1F27A | Patterns for sonic in intro | Art compression 525 blocks |
20C48 | "TM" | Art compression 00, 2 blocks |
20D3A | Hidden Japanese writing on "Sonic team presents" screen | Art compression 00, 166 blocks |
211E2-21291 | Unknown offset index | |
21292-217FD | Data that offset index is linking to (something to do with mappings for Sonic) | |
217FE-218AD | Unknown offset index | |
218AE-21AFD | Data that offset index is linking to (something to do with mappings for Sonic) | |
21AFE-2BC1D | Patterns for Sonic | Uncompressed Further info |
2BC1E | Smoke/dust trail | Art compression 00, 16 blocks |
2BD22 | Stars | Art compression 00, 3 blocks |
2BD5C | Bubble | Art compression 27 blocks |
2BEF2 | Stars from invincibility | Art compression 00, 36 blocks |
2C03A | Three different sized air bubbles, and a picture of Sonic holding his breath. | Art compression 15 blocks |
2C144 | Projectile that stone head shoots at you in LZ | Art compression 00, 3 blocks |
2C196 | Original special stage entrance effect | Art compression 00, 59 blocks |
2C5E4 | Block in special stage from every angle it rotates to | Art compression 249 blocks |
2D050 | Background of special stage | Art compression 241 blocks |
2DFE0 | Bubbles/clouds in background of special stage | Art compression 00, 81 blocks |
2E4D4 | "Goal" block from special stage | Art compression 18 blocks |
2E5C2 | "R" block from special stage | Art compression 9 blocks |
2E692 | Sonic life block from special stage | Art compression 00, 9 blocks |
2E788 | Stars from getting emerald in special stage | Art compression 00, 9 blocks |
2E7E6 | Closed one way block from special stage | Art compression 9 blocks |
2E878 | "Zone 1" block from special stage | Art compression 9 blocks |
2E93A | "Zone 2" block from special stage | Art compression 9 blocks |
2EA08 | "Zone 3" block from special stage | Art compression 9 blocks |
2EAD4 | "Zone 4" block from special stage | Art compression 9 blocks |
2EB9C | "Zone 5" block from special stage | Art compression 9 blocks |
2EC66 | "Zone 6" block from special stage | Art compression 9 blocks |
23D36 | "Up/Down" block from special stage | Art compression 27 blocks |
2EF2A | 4 emeralds present in special stage | Art compression 16 blocks |
2F092 | One way block from special stage | Art compression 00, 9 blocks |
2F142 | "W" block from special stage | Art compression 9 blocks |
2F21C | Desroyable blocks from special stage | Art compression 9 blocks |
2F2A0 | Different 4 emeralds present in special stage | Art compression 16 blocks |
2F41E | Stalk of flower | Art compression 00, 4 blocks |
2F468 | Swinging platform | Art compression 14 blocks |
2F582 | Rope bridge in EHZ | Art compression 00, 10 blocks |
2F66E | 2x2 block | Art compression 4 blocks |
2F6B6 | Ball that is swung by robotnic in GHZ | Art compression 38 blocks |
2F854 | Vertical and horizontal spike | Art compression 8 blocks |
2F8D0 | Rotating spike log in GHZ | Art compression 44 blocks |
2FAE4 | Rotating spikes off log in GHZ | Art compression 18 blocks |
2FC10 | Rock in EHZ | Art compression 24 blocks |
2FD3E | Destroyable section of wall in GHZ | Art compression 12 blocks |
2FDDC | Normal section of wall in GHZ | Art compression 12 blocks |
2FE3C | Surface of water in LZ | Art compression 00, 16 blocks |
2FF60 | Waterfall and water | Art compression 00, 144 blocks |
30754 | Swinging spikeball | Art compression 00, 24 blocks |
308D4 | Flat and diagonal blocks from SBZ | Art compression 32 blocks |
30A3E | Bubbles and numbers for underwater | Art compression 00, 116 blocks |
31094 | Block from LZ | Art compression 8 blocks |
3114A | Another block from LZ | Art compression 8 blocks |
311EC | Horizontal and vertical spear in LZ that extends and retracts | Art compression 18 blocks |
31348 | Broken bar from LZ | Art compression 8 blocks |
313AC | Block from LZ | Art compression 16 blocks |
314FE | Wheel from LZ | Art compression 72 blocks |
319E0 | Head that launches projectile in LZ | Art compression 17 blocks |
31B50 | Level blocks from LZ | Art compression 104 blocks |
31E08 | More blocks from LZ | Art compression 24 blocks |
31F40 | Cork block from LZ | Art compression 16 blocks |
3206A | A block from LZ | Art compression 16 blocks |
3217A | Metal blocks from MZ | Art compression 69 blocks |
32408 | Button in LZ and MZ | Art compression 8 blocks |
324C6 | Ball that swinging platform attaches to in MZ | Art compression 26 blocks |
3257E | Unknown. Grass... or something | Art compression 6 blocks |
325D2 | Fireballs from MZ | Art compression 44 blocks |
328B0 | Lava stuff from MZ | Art compression 156 blocks |
331C6 | Moveable block from MZ | Art compression 24 blocks |
3332A | Block in background frm MZ | Art compression 00, 16 blocks |
33978 | Metal block from SLZ | Art compression 00, 8 blocks |
333B2 | See-saw from SLZ | Art compression 44 blocks |
335EE | Spikeballs that flash red and explode that robotnic drops in SLZ | Art compression 00, 18 blocks |
33734 | Fan from SLZ | Art compression 44 blocks |
339DA | Pylon from SLZ | Art compression 16 blocks |
33ABC | Spikeball from SLZ | Art compression 32 blocks |
33C9E | Misc blocks for SLZ | Art compression 00, 16 blocks |
33DAA | Fireball launcher from SLZ | Art compression 8 blocks |
33E4E | Bumper from special stage and SYZ | Art compression 22 blocks |
33FB8 | Small spikeball | Art compression 00, 4 blocks |
3401A | Normal button pressed/unpressed, and red button unpressed | Art compression 12 blocks |
340FC | Spikeball and chain | Art compression 36 blocks |
3438A | Indent on spinning wheel in SBZ | Art compression 4 blocks |
343DE | Platforms from SBZ | Art compression 79 blocks |
3467A | Pizza slicer thing from SBZ | Art compression 36 blocks |
3487E | Stomper from SBZ | Art compression 40 blocks |
34A1C | Tilting platform from SBZ | Art compression 00, 48 blocks |
34D4C | Some blocks from SBZ | Art compression 49 blocks |
34F2A | Metal block from collapsing platform in SBZ | Art compression 00, 4 blocks |
34F82 | Zapper thing from SPZ | Art compression 00, 20 blocks |
35102 | Blocks from SBZ | Art compression 28 blocks |
35200 | Flame pipes from SBZ | Art compression 28 blocks |
3538C | One way barrier frm SBZ | Art compression 8 blocks |
353DC | Red and metal platforms from SBZ | Art compression 15 blocks |
35434 | Blocks from SBZ | Art compression 00, 15 blocks |
35530 | Metal blocks from SBZ | Art compression 00, 12 blocks |
35646 | Pig badnick | Art compression 47 blocks |
35A06 | Crab badnick | Art compression 00, 68 blocks |
35EF4 | Buzz bomber | Art compression 55 blocks |
3629A | Fireball | Art compression 36 blocks |
36482 | Drill noze badnick from LZ | Art compression 00, 90 blocks |
36B6C | Fish badnick from GHZ | Art compression 32 blocks |
36DD4 | Fish badnick from LZ | Art compression 32 blocks |
3705E | Enemy that can enter a ball from SYZ | Art compression 80 blocks |
37582 | Driving enemy from GHZ | Art compression 00, 29 blocks |
3780C | Enemy that appears and jets along the ground | Art compression 00, 85 blocks |
37E2A | Enemy with spikes on top | Art compression 61 blocks |
38212 | Bat | Art compression 00, 41 blocks |
3850E | Splats badnick | Art compression 29 blocks |
38756 | Walking bomb | Art compression 41 blocks |
389EE | Enemy with spikeballs around it | Art compression 31 blocks |
38BCC | Caterkiller | Art compression 16 blocks |
38D5A | Level splash screen tiles | Art compression 128 blocks |
39368 | Rings/Score/Time patterns | Art compression 24 blocks |
3945E | Sonic life counter patterns | Art compression 12 blocks |
39564 | Patterns for rings | Art compression 00, 14 blocks |
39658 | Monitor/contents of monitor patterns | Art compression 64 blocks |
39AB8 | Explosion | Art compression 96 blocks |
3A11E | Points popping up onscreen from busting badnick | Art compression 9 blocks |
3A1CE | "Game over" text | Art compression 34 blocks |
3A360 | Horizontal Spring | Art compression 00, 16 blocks |
3A462 | Vertical spring | Art compression 00, 14 blocks |
3A53E | End of level signpost | Art compression 58 blocks |
3A9BA | Starpoll | Art compression 10 blocks |
3AA7A | Flash from entering giant golden ring | Art compression 84 blocks |
3ABEE | Hidden points at end of levels | Art compression 00, 36 blocks |
3AEF0 | Sonic lying down anomation in "Continue?" screen | Art compression 37 blocks |
3B1A0 | "Continue" and mini sonic for it. | Art compression 30 blocks |
3B3DA | Rabbit | Art compression 00, 18 blocks |
3B532 | Chicken | Art compression 14 blocks |
3B68E | Blackbird | Art compression 00, 18 blocks |
3B80A | Seal | Art compression 00, 14 blocks |
3B926 | Pig | Art compression 18 blocks |
3BA5C | Bluebird | Art compression 00, 14 blocks |
3BB96 | Squirrel | Art compression 00, 18 blocks |
3BCF2 | GHZ 16x16 block mappings | Further info |
3C692 | GHZ Primary pattern block | Art compression 461 blocks |
3DCF2 | GHZ secondary pattern block | Art compression 369 blocks |
3F09A | GHZ 256x256 block mappings | Further info |
411AA | LZ 16x16 block mappings | Further info |
414D4 | LZ primary pattern block | Art compression 454 blocks |
4301C | LZ 256x256 block mappings | Further info |
4580C | MZ 16x16 block mappings | Further info |
46016 | MZ primary pattern block | Art compression 663 blocks |
4885A | MZ 256x256 block mappings | Further info |
4A01A | SLZ 16x16 block mappings | Further info |
4A7FE | SLZ primary pattern block | Art compression 874 blocks |
4E352 | SLZ 256x256 block mappings | Further info |
50782 | SYZ 16x16 block mappings | Further info |
510F0 | SYZ primary pattern block | Art compression 882 blocks |
5481C | SYZ 256x256 block mappings | Further info |
56BCC | SBZ 16x16 block mappings | Further info |
57A66 | SBZ primary pattern block | Art compression 681 blocks |
5A212 | SBZ 256x256 block mappings | Further info |
5CC62 | Robotnic's main ship | Art compression 108 blocks |
5D4C6 | GHZ boss | Art compression 00, 42 blocks |
5D7B0 | Egg prison | Art compression 117 blocks |
5E034 | Robotnic | Art compression 144 blocks |
5E860 | Stomper boss from final zone | Art compression 156 blocks |
5EFC8 | Robotnic's ship at end of final zone | Art compression 00, 76 blocks |
5F548 | Rocket thrust from robotnic's ship | Art compression 00, 17 blocks |
5F668 | 7 chaos emeralds | Art compression 28 blocks |
5F866 | Patterns for Sonic in ending sequence | Art compression 323 blocks |
60A44 | Robotnic in Try Again screen | Art compression 139 blocks |
61388 | Robotnic's ship in flames and blowing up in background | Art compression 00, 47 blocks |
61CEE | Grass and flower against both checkered and non checkered background | Art compression 37 blocks |
61F76 | Alphabet | Art compression 96 blocks |
62574 | "Sonic the hedgehog" writing from end of game | Art compression 48 blocks |
627FC-628FF | Data block acting as seperator | |
62900-629FF | Curve and resistance mapping | Further info |
62A00-649FF | Collision array | Further info |
64A00 | GHZ 16x16 collision index | Further info |
64B9A | LZ 16x16 collision index | Further info |
64C62 | MZ 16x16 collision index | Further info |
64DF2 | SLZ 16x16 collision index | Further info |
64FE6 | SYZ 16x16 collision index | Further info |
651DA-65431 | SBZ 16x16 collision index | Further info |
65432-66AD5 | Something to do with special stages | |
66AD6-66CD5 | Waterfall tiles from GHZ | Uncompressed Further info |
66CD6-670D5 | Flower with pointy petals in GHZ | Uncompressed Further info |
670D6-67559 | Flower with curved petals in GHZ | Uncompressed Further info |
6755A-67835 | Lava surface | Uncompressed Further info |
67836-67E55 | Lava | Uncompressed Further info |
67E56-68155 | Flames against stone from MZ | Uncompressed Further info |
68156-68BD5 | Steam in background from SBZ | Uncompressed Further info |
68BD6 | Offset index of level data | Unique offset Further info |
68C7E | GHZ act 1 foreground | Further info |
68D74 | GHZ act 2 foreground | Further info |
68E40 | GHZ act 3 foreground | Further info |
68F62 | GHZ act 1/2/3/ending sequence background | Further info |
68F8C | LZ act 1 foreground | Further info |
6908E | LZ act 1/2/3/SBZ 3 background | Further info |
69194 | LZ act 2 foreground | Further info |
69232 | LZ act 3 foreground | Further info |
69350 | SBZ act 3 foreground | Further info |
6940E | MZ act 1 foreground | Further info |
694AC | MZ act 1 background | Further info |
69526 | MZ act 2 foreground | Further info |
695CA | MZ act 2 background | Further info |
69660 | MZ act 3 foreground | Further info |
69742 | MZ act 3 background | Further info |
697EE | SLZ act 1 foreground | Further info |
69900 | SLZ act 1/2/3 background | Further info |
6997A | SLZ act 2 foreground | Further info |
69A6A | SLZ act 3 foreground | Further info |
69B88 | SYZ act 1 foreground | Further info |
69C44 | SYZ act 1/2 background | Further info |
69C82 | SYZ act 2 foreground | Further info |
69D8A | SYZ act 3 foreground | Further info |
69EEC | SBZ act 1 foreground | Further info |
6A00E | SBZ act 1 background | Further info |
6A04C | SBZ act 2/FZ foreground | Further info |
6A18E | SBZ act 2/FZ background | Further info |
6A300 | Ending sequence foreground | Further info |
6A324-6AF63 | Giant spinning golden ring | Uncompressed Further info |
6AF64-6AFFF | Data block acting as seperator | |
6B000-6B095 | Offset index of sprite locations | Unique offset |
6B096 | GHZ act 1/4 sprite locations | Further info |
6B5A0 | GHZ act 2 sprite locations | Further info |
6BB5E | GHZ act 3 sprite locations | Further info |
6C218 | LZ act 1 sprite locations | Further info |
6C686 | LZ act 2 sprite locations | Further info |
6C9C8 | LZ act 3 sprite locations | Further info |
6CFAA | SBZ act 3 sprite locations | Further info |
6D442 | End of game sequence sprite locations | Further info |
6D592 | MZ act 1/4 sprite locations | Further info |
6D8FE | MZ act 2 sprite locations | Further info |
6DDA8 | MZ act 3 sprite locations | Further info |
6E31E | SLZ act 1/4 sprite locations | Further info |
6E85E | SLZ act 2 sprite locations | Further info |
6ECC6 | SLZ act 3 sprite locations | Further info |
6F2A8 | SYZ act 1/4 sprite locations | Further info |
6F734 | SYZ act 2 sprite locations | Further info |
6FC9E | SYZ act 3 sprite locations | Further info |
702A4 | SBZ act 1/FZ sprite locations | Further info |
709E2 | SBZ act 2 sprite locations | Further info |
710C0 | SBZ act 3 sprite locations | Further info |
710D2 | Title screen sprite locations | Further info |
71204 | Level value 06 act 1/2/3/4 sprite locations | Further info |
71360 | Unknown sprite locations (empty) | Further info |
71366-7198F | Data block acting as seperator | |
71A9C | Midi pointers | Further info |
745DC | Track 00 | |
74D44 | Track 01 | |
75194 | Track 02 | |
755F2 | Track 03 | |
75A60 | Track 04 | |
75EAC | Track 05 | |
763FC | Track 06 | |
765E2 | Track 07 | |
766D0 | Track 08 | |
769FC | Track 09 | |
76BA8 | Track 0A | |
76E42 | Track 0B | |
7705E | Track 0C | |
7727A | Track 0D | |
773D0 | Track 0E | |
77520 | Track 0F | |
7767E | Track 10 | |
7894C | Track 11 | |
78A76 | Track 12 | |
78B44 | Sound FX pointers | Further info |
78C08 | Sound 00 | |
78C1E | Sound 01 | |
78C48 | Sound 02 | |
78C68 | Sound 03 | |
78C9A | Sound 04 | |
78CD0 | Sound 05 | |
78CFC | Sound 06 | |
78D2C | Sound 07 | |
78D5C | Sound 08 | |
78D90 | Sound 09 | |
78DA2 | Sound 0A | |
78DE4 | Sound 0B | |
78E04 | Sound 0C | |
78E38 | Sound 0D | |
78E6E | Sound 0E | |
78EB8 | Sound 0F | |
78EE6 | Sound 10 | |
78F18 | Sound 11 | |
78F44 | Sound 12 | |
78F94 | Sound 13 | |
78FDE | Sound 14 | |
7903A | Sound 15 | |
79068 | Sound 16 | |
79086 | Sound 17 | |
790C2 | Sound 18 | |
790E0 | Sound 19 | |
79144 | Sound 1A | |
7916C | Sound 1B | |
79198 | Sound 1C | |
791DA | Sound 1D | |
7922E | Sound 1E | |
79268 | Sound 1F | |
792DA | Sound 20 | |
79308 | Sound 21 | |
79342 | Sound 22 | |
7936C | Sound 23 | |
793E6 | Sound 24 | |
7940E | Sound 25 | |
79476 | Sound 26 | |
794B8 | Sound 27 | |
794E6 | Sound 28 | |
794F8 | Sound 29 | |
79526 | Sound 2A | |
79554 | Sound 2B | |
795A0 | Sound 2C | |
795DA | Sound 2D | |
795E8 | Sound 2E | |
79616 | Sound 2F | |
7964E | Sound 30 | |
79687-7FFFF | Sega intro sound | 16000Hz mono 8-bit unsigned PCM raw audio Further info |
Offset indexes
An offset index is a handy way of keeping a block of data grouped together, and also replacing a whole heap of pointers. The way it works is there is a list of two byte vaues, and depending on the block of data the game wants to load, it will take one of those values and add it to the starting address of the offset index. The most common usage is for every act of every level value, there is an offset that acts as the pointer to the block of data to use for it. Lets look at an example:
E6800: 004A 037A 5552 5552 5552 5552 5552 5552 0734 0BC0 10EE 10EE 1748 1AFC
Now this is the beginning of the offset index for the sprite locations in the S2 rom. Now, can you see which values are the offset for MTZ act 2? They're 0BC0. All you had to do to get that was to take the level value for MTZ, which is 04, and count across four bytes for every value it is above 00, then across another two because it's the second act. Now we take that value and using a hex calculator, add it to the address of the offset table, which is E6800. That will give us a value of E73C0, which is the address in the rom of the MTZ act 2 sprite locations.
There are other forms of an offset index such as the one where there's just one offset per level value, and another type that actually uses a double offset index. The first is easy enough, but a double offset index will specify two values per level, but that's not for act one and two, but rather two blocks of data to use for both acts.
Main level load block
These are the blocks that tie all the pieces for a level together. Pretty much everything major to do with a level is linked back to this block at some point.
One thing that's very imporant to understand is that the game engine used in S1 was not completed. It looks like some things that Yuji Naka planned to implement were not completed due to lack of time. Some of these things show up in the main level load block. First of all, the pointer to the main level patterns in this block is not used by the game at all. Instead the main level patterns are included on the pattern load cue for that level. In S2 another compression format was made, and the main level patterns were stored in this format, which was less dence to allow the main level patterns to be loaded into the VRAM faster, and for that this pointer was used. Several other things that were only to use one byte were also allowed for in this block, such as the music track to play for that level. Some of these were later moved to seperate sections of the code though, so only the pattern load cue and palette index numbers are used.
Here's the main level load block for MZ:
0804 | 6016 | 0904 | 580C | 0004 | 885A | 0083 | 0606 | ||||||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | 10 |
And here's what each byte does:
1 | Index number of first pattern load cue | Further info |
2-4 | Main level patterns | Unused |
5 | Index number of second pattern load cue | Further info |
6-8 | 16x16 block mappings | Further info |
9 | Blank | Unused |
A-C | 256x256 block mappings | Further info |
D | Blank | Unused |
E | Music track to play for level | Unused |
F | Unknown | Unused |
10 | Index number of palette to use for level | Further info |
Now that you know that, here's a breakdown of the main level load blocks in the S1 rom:
- 1D5A2: Main level load blocks (patterns/16x16/256x256/palette)
- 1D5A2-1D5B1: Green hill zone (00)
- 1D5A2: GHZ main level patterns (3DCF2) [04]
- 1D5A6: GHZ 16x16 block mappings (3BCF2) [05]
- 1D5AA: GHZ 256x256 bock mappings (3F09A) [00]
- 1D5AE: GHZ main level palette (04) [00 81 04]
- 1D5B2-1D5C1: Labyrinth zone (01)
- 1D5B2: LZ main level patterns (414D4) [06]
- 1D5B6: LZ 16x16 block mappings (411AA) [07]
- 1D5BA: LZ 256x256 block mappings (4301C) [00]
- 1D5BE: LZ main level palette (05) [00 82 05]
- 1D5C2-1D5D1: Marble zone (02)
- 1D5C2: MZ main level patterns (46016) [08]
- 1D5C6: MZ 16x16 block mappings (4580C) [09]
- 1D5CA: MZ 256x256 block mappings (4885A) [00]
- 1D5CE: MZ main level palette (06) [00 83 06]
- 1D5D2-1D5E1: Star light zone (03)
- 1D5D2: SLZ main level patterns (4A7FE) [0A]
- 1D5D6: SLZ 16x16 block mappings (50782) [0B]
- 1D5DA: SLZ 256x256 block mappins (5481C) [00]
- 1D5DE: SLZ main level palette (07) [00 84 07]
- 1D5E2-1D5F1: Spring yard zone (04)
- 1D5E2: SYZ main level patterns (510F0) [0C]
- 1D5E6: SYZ 16x16 block mappings (50782) [0D]
- 1D5EA: SYZ 256x256 block mappins (5481C) [00]
- 1D5EE: SYZ main level palette (08) [00 85 08]
- 1D5F2-1D601: Scrap brain zone (05)
- 1D5F2: SBZ main level patterns (57A66) [0E]
- 1D5F6: SBZ 16x16 block mappings (56BCC) [0F]
- 1D5FA: SBZ 256x256 block mappins (5A212) [00]
- 1D5FE: SBZ main level palette (09) [00 86 09]
- 1D602-1D611: End of game (06)
- 1D602: GHZ main level patterns (3DCF2) [00]
- 1D606: GHZ 16x16 block mappings (3BCF2) [00]
- 1D60A: GHZ 256256 block mappins (3F09A) [00]
- 1D60E: GHZ main level palette (13) [00 86 13]
- 1D602-1D611: End of game (06)
I think that pretty much summs it up. Just change the vaue of the thing you want to modify to the appropriate value. If you wanted to give GHZ the MZ palette, just change the main level palette index number from 04 to 06 and it's done.
Pattern load cues
The pattern load cues are what loads all the peices of art into the VRAM that are not in the main level load block. Here's a breakdown of the pattern load cues in the S1 rom:
00 | 1D652 | Standard block 1 (starpoll/rings\score\time/life/ring/points) | (4) |
01 | 1D672 | Standard block 2 (monitor/bubble/stars) | (2) |
02 | 1D686 | Explosion (explosion) | (0) |
03 | 1D68E | Game/Time over (game\time over) | (0) |
04 | 1D696 | GHZ (GHZ primary/GHZ secondary/stalk/rock/crabmeat/buzz bomber/fish/jet badnick/driving badnick/spikes/H spring/V spring) | (B) |
05 | 1D6E0 | GHZ (platform/bridge/wooden spikes/ball/breakable wall/wall block) | (5) |
06 | 1D706 | LZ (LZ patterns/block/blocks/waterfall/water surface/spikeball/blocks/bubbles/block/block/spear/drill badnick) | (B) |
07 | 1D750 | LZ (broken bar/block/wheel/stone head/sonic holding breath/blocks/enemy with spikeballs/fish/button/cork/spikes/H spring/V spring) | (C) |
08 | 1D7A0 | MZ (MZ patterns/metal/fireball/platform/ball/lava/buzz bomber/spikey badnick/bat/caterkiller) | (9) |
09 | 1D7DE | MZ (button/spikes/H spring/V spring/moveable block) | (4) |
0A | 1D7FE | SLZ (SLZ patterns/bomb/enemy with spikeballs/fireballs/blocks/block/spikes/H spring/V spring) | (8) |
0B | 1D836 | SLZ (see-saw/fan/pylon/spikeball/fireball launcher/spikeball) | (5) |
0C | 1D85C | SYZ (SYZ patterns/crabmeat/buzz bomber/spikey badnick/metal sonic) | (4) |
0D | 1D87C | SYZ (bumper/spikeball/spikeball/caterkiller/button/spikes/H spring/V spring) | (7) |
0E | 1D8AE | SBZ (SBZ patterns/stomper/barrier/blocks/pig/indent/platform/spikeball/spikewheel/flamepipe/zapper/blocks) | (B) |
0F | 1D8F8 | SBZ (caterkiller/bomb/badnick with spikeballs/platforms/zapper/blocks/collapsing platform/tilting platform/button/spikes/H spring/V spring) | (C) |
10 | 1D948 | Title card (title card) | (0) |
11 | 1D950 | End of boss level (robotnic's ship/GHZ boss/egg prizon/bomb/spikeball/rocket thrust) | (5) |
12 | 1D976 | End of signpost level (signpost/hidden bonuses/flash) | (2) |
13 | 1D98A | Lost warp effect (original bonus stage entry effect) | (0) |
14 | 1D992 | Special stage (bubbles\clouds/background/block/bumper/"goal"/up\down/"R"/life block/stars/closed one way block/one way block/"W"/destroyable blocks/emeralds/"zone 1"/"zone 2"/"zone 3"/"zone 4"/"zone 5"/"zone 6") | (10) [13] |
15 | 1DA0C | GHZ animals (rabbit/bluebird) | (1) |
16 | 1DA1A | LZ animals (blackbird/seal) | (1) |
17 | 1DA28 | MZ animals (squirrel/seal) | (1) |
18 | 1DA36 | SLZ animals (pig/bluebird) | (1) |
19 | 1DA44 | SYZ animals (pig/chicken) | (1) |
1A | 1DA52 | SBZ animals (rabbit/chicken) | (1) |
1B | 1DA60 | End of special stage (emeralds/continue) | (1) |
1C | 1DA6E | End of game sequence (GHZ primary/GHZ secondary/stalk/weird flowers/emeralds/sonic in ending sequence/robotnic dying/rabbit/chicken/blackbird/seal/pig/bluebird/squirrel/"sonic the hedgehog") | (E) |
1D | 1DACA | End/try again screen (emeralds/robotnic/alphabet) | (2) |
1E | 1DADE | End of SBZ 2 (blocks/robotnic/button) | (2) |
1F | 1DAF2 | FZ (robotnic's ship at end/stomper boss/robotnic's ship/robotnic/rocket thrust) | (4) |
This pointer list has an offset index to locate the correct cue. Go here for an explanation of how this works. Note that the number in parenthesis is the recorded number of requests in the cue. If a number follows it in brackets, it means the actual number that exists differs from the recorded one. This means any load requests past the recorded number were not being loaded, but still exist in the rom. Now, each load cue has a two byte value before it that specifies how many addresses are in the cue, to avoid it reading too far, and going into the next cue. This value is dead simple, just enter the number of patterns on the cue in hex between the first two bytes, but you have to count 00 as 1, so if there was 16 loading addresses in the cue, you'd have 000F preceding it. After that, there are 6 bytes per load request. The first four bytes are a pointer to the art block to use, and the two bytes after that are the location in the VRAM to load them into. To change the pattern load cues being loaded for a level, you need to change the values in the main level load block. For more information on that go here.
Collision definitions
Ok, I’m going to explain how collision works on objects that are not sprites in the sonic games. First of all forget the image that the block contains. The image has absolutely nothing to do with the collision. There's basically in invisible collision box on top of every 16x16 block that sets what's solid and what's not. This collision box has two parts to it. The main part of it is the collision array (an array is basically a table of values). The collision array stores the actual data that says that is a block is solid in certain places. It does that through 16 bytes per collision box. To understand how those 16 bytes set what's solid, imagine a 16x16 block. Now imagine that 16x16 block with the numbers 1-10 (hex) down the side starting from the bottom and going up to the top, and starting from the left and going up as it moves right along the top, so that you can give an exact location of each pixel. (eg, the top left pixel would be 10,00) Now, in this array the first two bytes define what's solid for the row of pixels on the left side of that 16x16 block. Basically the first of those two bytes says where to start making things solid, and the second byte says where to stop making them solid. So if you entered the value 0010, the first row would be solid from the very bottom of the block all the way up to the top. If you were to enter the value 020E, there would be two pixels on either side of the block that are not solid, and everything in the middle would be. The next two bytes after that are for the next row, etc. After 16 bytes the definitions for the next collision box begin.
Now, to specify which blocks use which collision boxes, there are collision indexes, which give an array location for each 16x16 block. If you look at the space used by the collision array, you can divide that by 16 (the number of bytes used by each entry into the array) to give a one byte value, which represents the maximum number of collision boxes that the array can hold in the S2 platform, which is FF. Now, for each level there is at least one 16x16 collision index, and that index consists of a whole heap of array locations, one for each 16x16 block. If for example you wanted the 9th 16x16 block to use the collision box with an array location of 3E, you would give the 9th byte of the collision index for that level a value of 3E.
It is through collision indexes that the loops work in the game. It's commonly believed that there are layers, and that the sprite represented by 4 rings changes between them. This is partly true. For any levels that use multiple layers like that, there is a secondary 16x16 collision index. That object switches the 16x16 collision index in use. The pointers to these 16x16 collision indexes are stored at 4ADC-4B63. The first set of pointers in this group specify the location of the primary collision index to use for each level, and the second set specify the location of the secondary collision index to use for each level.
Now just setting something as solid, doesn't give it the effect of having a slope. There's an index in the rom, which has one byte in it for each collision array location. To understand how this value works, think of two lines running parallel to each other, both with the value 0-F along them. Now, the first value of the byte gives a point on the right line, and the second value gives a point on the left line. Now imagine drawing a line between these to points. If the points are different, the resulting gradient will be taken to create the effect of a slope and the resistance going up it on the box in the corresponding collision array location.
Level layout
The level layout in S1 is broken up into two peices, one for the foreground of the level, and one for the background. When being read into the ram, this data is interleaved to give the entire level layout. The offset index that proceeds the actual level data is a unique offset index. There are three offset values for each act, and four acts for each level value. The first value is the offset to the foreground to use for that act. The value is the offset to the background to use for that act. I have no idea what the third offset was intended to be used for, but it appears that it is not used in the game, so just ignore it.
Sprite placement
Sprites are quite simple to define. It takes six bytes to define one sprite. The first two bytes are the x location of the sprite, and the next two bytes are the y location of the sprite. The 5th byte is the number on the sprite array to lookup to get the location for the function to use for the programming of that sprite, and the 6th byte is an optional declaration to use with the function for that sprite. Go here for more info on what exactly that means, and a list of all the sprites in the S1 rom.
Main level block mappings
In S1 both the 16x16 and 256x256 block mappings are compressed. This means that in order to edit the block mappings, you'd need to be able to decompress, alter, then recompress them. Right now there is no way to do that, so you can only use the block mapings that are in the rom unless you want to do a savestate hack. Note also that becuase S1 uses 256x256 block mappings, you can't just port the block mappings from later sonic games.
Uncompressed art
Any art that needs to be updated on the fly will not be compressed in the rom. This is because the game can't work with compressed data, and needs to extract any data it wants to use to the ram. This decompression process takes a fair bit of computation, and because of that it wouldn't be possible to create the appearance of a smooth animation using compressed data. The same reason is true as to why any data that is not loaded into the ram will always be uncompressed, because otherwise they would have to load it into the ram just to read it.
Now, for example all of the blocks for Sonic are uncompressed, because they of course need to be updated quickly. You can use basically any editing utility to edit them, but you can only change what each block looks like through this. In order to edit what blocks are placed where in each of Sonic's animation frames, you need to edit the mappings for them, and for more information on that go here. Now in their uncompressed form, you can edit them just like you would in the VRAM, so for more information on that check the sonic 1 savestate breakdown.
Mappings for Sonic
What the mappings do is they tell the game what patterns to display, and where to put them for each of the frames that the sprite has. The mappings for most sprites are contained within their function (go here for more details), but with the sprite for Sonic, to allow the programmers to add a new frame easily without having to recompile the function, and hence the whole game because of the size difference, they created a separate array containing the mapping data for each frame. I haven't examined this to see how it works yet, but when I do I’ll explain the format here.
Sega intro sound
The Sega intro sound is just an 16000HZ wav sound. Opening up the rom in any sound editing program that supports raw audio with the settings listed next to the location on the list will enable you to playback the sound effect. You could also insert your own sound in the same place as long as it's at the same bitrate. The bitrate is to do with the quality of the sound. The lower it is the crappier it will sound, because that's to do with how often the output is modified. Just think of the difference between long play and short play on a VCR. Stuff recorded in long play does save space, but the quality of the recording is worse.
Art compression format
The art compression format is a very dense compression format. It's only used for art because the format relies on the data being in blocks of 64 bytes. This format is used for all the compressed art in sonic 1 and sonic 2 beta, and all the compressed art except for the main level pattern blocks in Sonic 2 and S3&K. As I said this format is very dense, and as such it requires a hell of a lot of computation to decompress. Because of this it also requires a hell of a lot of time and effort to crack. I've had a go at it, but the lightning has yet to strike. When I crack it I’ll post the format breakdown here, and create a simple program to decompress it, but until then it is impossible to directly edit any art using this format. The porting of a compressed block of art is simple though, so if you want to transfer beta art to the final, you can just tack it onto the end and enter the pointer into the pattern load cue of the level or event you want it to appear at, along with a VRAM location to load it into. Go Here for more information on that.
Animated pattern load cues
While the function of these cues is identical to the ones in S2 and S2B, these ones are structured entirely differently, and as of yet I haven't figured the entire system of this one out. You can switch the animated pattern load cues between levels easy enough by changing the offset index preceeding them though.
Palettes
All the main palettes used in the game are linked in a pointer table at 2168. In this pointer table there are 8 bytes per palette. The first four simply give a location in the rom for the data to load. The fifth and sixth bytes give the location in the system ram to load the data into, and the seventh and eighth bytes give the number of bytes being loaded. Here's a palette pointer:
0000 2942 FB20 0007
Now in this case the palette is being loaded from 00002942 in the rom into the beginning of the second above water palette row (FB20), and it's loading 4 colours (0007). Here's a listing of the palette pointers in the S1 rom:
00 | 2168 | SEGA screen palette (2208) |
01 | 2170 | Title screen palette (2288) |
02 | 2178 | Level select palette (2308) |
03 | 2180 | Primary palette line (2388) |
04 | 2188 | GHZ level palette (23A8) |
05 | 2190 | LZ level palette (2408) |
06 | 2198 | MZ level palette (24E8) |
07 | 21A0 | SLZ level palette (2548) |
08 | 21A8 | SYZ level palette (25A8) |
09 | 21B0 | SBZ level palette (2608) |
0A | 21B8 | Special stage palette (26C8) |
0B | 21C0 | LZ underwater level palette (2468) |
0C | 21C8 | SBZ act 3 level palette (2748) |
0D | 21D0 | SBZ act 3 underwater level palette (27A8) |
0E | 21D8 | FZ level palette (2668) |
0F | 21E0 | LZ underwater primary palette line (2828) |
10 | 21E8 | SBZ act 3 underwater primary palette line (2848) |
11 | 21F0 | Special stage results palette (2868) |
12 | 21F8 | Unknown palette (28E8) |
13 | 2200 | Ending sequence level palette (2928) |
To change the palette being loaded for each level, you need to change the palette index number in the main level load block. For more information on that go here. The palettes themeslves are very easy to modify as they are all uncompressed in the rom. Refer to the savestate hacking documents for information on how to edit palettes.
Character start location array
The start location for the characters and the camera for each level are stored in this array at address 6112. It couldn't be any simpler to modify, there's just two values per act, the first being the X location, and the second being the Y location.
Music playlist for levels
The music playlist is very simple to modify. There is one byte per level value, and that byte stores the value of the music track you want to play for that level. The values for the music tracks can be obtained from the sound test in the level select screen.
Level order
There are several different sections in the game to do with the order of levels. The first one is the one that determins which level the game loads when someone finishes a level. The second one is the one which determins which level to load when you select a level from the level select menu. The level select one is easy to modify, just enter the level value followed by an act number for each of the levels you want to load, in the order you want them to be loaded. For a list of the level values for all the different stages, look at the beginning of the introduction to this page. Note that if you load the same level into the level order twice, when you link to it via the level select, it will continue the sequence from the last one in the list, not the first.
The second system for which level to load when one ends works slightly differently. There is a list of values, with two bytes allocated to each act of each level. That two byte value is simply the value of the level you wish to load when that level ends. So, if you wanted LZ act 1 to load up when you finish SBZ act 2, you would take the location of the table, which in this case is C6F4, and you would add 42 bytes to that location, and then you would replace the next two bytes from that point with 0100. That's becuase you add 8 bytes to the address for every level that comes before it, and in this case there are 5, and then you would add another 2 bytes becuase you want to alter the level to load when you finish the second act.
Also, note that when you want a level to be the last level in the game, you must enter the value FFFF as the stage to load when it finishes. This tells the game to end and return to the title screen.
Object debug list
This list is what determins what sprites you can place in debug mode, and in what levels. An offset index is used to locate which object debug list to use for which level, so if you want further info on that go here. Now, there is a 2 byte value at the start of each debug list. That 2 byte value is simply the number of sprites in the list. After that there are 8 bytes per sprite. Here's an object that's present in an object debug list from sonic 2:
2601 | 2D36 | 0800 | 0680 | ||||
1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |
And here's a quick referance sheet of what each byte does. For further info on each one, refer to information below.
1 | Object number |
2-4 | Sprite mappings |
5 | Declaration |
6 | Frame to display |
7 and 8 | flip/mirror/palette/VRAM location |
Object number:
This value is what determins which object to use. For a list of all the sprites in the game, check out the sprite programming section of this document here. In the case of the above example the object number is 26, which is a monitor.
Sprite mappings:
This is a pointer to the location in the rom to load the mappings for that sprite. This will be located in the programming for the sprite itself. Do not change this unless porting between levels, or you're absolutely sure you know what you're doing, or the game will most likely hang. This only affects the preview picture, not the placed object itself. In this case, the sprite mappings are being loaded from the address 012D36 in the rom.
Declaration:
This is the declaration for the loading of the sprite. For information on exactly what that is, go here. In this example the declaration is 08, which switches the type of monitor it is in the case of this sprite.
Frame to display:
This is simply the frame of the sprite that will be displayed on the preview picture before you place an object. Right now it's set to 00, which is the first frame.
Flip/mirror/VRAM location:
The first hex value of the 7th byte is to do with flipping and mirroring of the sprite, as well as the palette line to use for it. Refer to the following table for an explination of what responce each value will create.
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 |
In the case of our example, the value of 0 is used, so the preview image will use the first palette line, and will not be flipped or mirrored.
The last hex value of the 7th byte, and all of the 8th byte in this block combine to give a starting location in the VRAM to find the patterns to use for that sprite when displaying the preview. This is not an actual location, but merely the number of blocks after which to load the patterns from. After the value of 800 is passed, the block number resets to zero but the image is mirrored. In this case, that block number is 680.
And that's about it. I've just realised that this is a rediculous amount of detail for such a small thing, but at least you're sure to get it.
Dynamic screen resizing
In S1, the programmers allowed for some very fancy effects to do with the height and width of the sceen. They allowed for the X/Y start, and X/Y ending locations to be changed at any point during the level, based on any event they cared to use. The method they used made the programmers job a little harder though and ate away some performance. They completely redesigned the way this worked for the S2 platform. All the programming for the screen resizing is compiled, so it's very difficult to edit directly.
Music/Sound FX pointers
The music and sound effects in S1 are very easy to change. Note that the midi's in the game start at a sound value of 80, and the sound effects start at a value of A0. If you want to determine the value of the sound or midi you want to work with, just read it staright off the sound test in the level select menu. The pointers to the midi's are at address 71A9C, and the pointers for the sound ffects are at 78B44. Both are simply 4 byte pointers to the address in the rom that the data is located at, so to find the pointer to the sound or midi you want to edit, add 4 bytes to the starting address of the pointer list for every sound or midi that comes before it after it's starting value. To switch a track, just switch thier pointer values.
Sprite programming
The programming for a sprite in the sonic games are stored as a function, and that function can take one declaration. People often confuse this declaration with a subtype value, but it's not really. What that basically means for the non programmers out there is that when the game places a sprite, you can enter a value along with the sprite number that may alter something about that sprite, but what it does varies depending on what sprite you're working with. Now because these functions are now compiled, the only way you can effectively edit them is to find the code for it and decompile it into assembly, alter it as necessary, and then recompile it and enter it back into the rom. This document will contain all the info necessary to enter a new sprite or replace an old one, but when it comes to the ASM you're on your own.
Now, the value assigned to a sprite in the game is done by a pointer index at D382. It’s pretty simple, just one pointer per address value. Here's the pointer list in Sonic 1:
01 | D382 | Sonic [12BD8] |
02 | D386 | ??????? [D5B2] |
03 | D38A | ??????? [D5B2] |
04 | D38E | ??????? [D5B2] |
05 | D392 | ??????? [D5B2] |
06 | D396 | ??????? [D5B2] |
07 | D39A | ??????? [D5B2] |
08 | D39E | ??????? [142F0] |
09 | D3A2 | Sonic in special stage [1B984] |
0A | D3A6 | ??????? [13C98] |
0B | D3AA | Bar you hold onto in LZ [11206] |
0C | D3AE | Opening blocks that open to pasage sonic gets sucked down in LZ [11346] |
0D | D3B2 | Unknown. Warps you to somewhere. [EB28] |
0E | D3B6 | ??????? [A61C] |
0F | D3BA | ??????? [A69C] |
10 | D3BE | ??????? [1C022] |
11 | D3C2 | ??????? [7328] |
12 | D3C6 | Spinning light behind glass from SYZ [E90C] |
13 | D3CA | Fireball from MZ [E296] |
14 | D3CE | Unknown. Dives through the floor. [E304] |
15 | D3D2 | Swinging spikeball on a chain from SBZ [7952] |
16 | D3D6 | Spear from LZ [11F04] |
17 | D3DA | Unknown. Flashes between hitable and not hitable, but you can't hurt it, only the other way around. Frame changes in accordance with this. [7CA2] |
18 | D3DE | Misc standard platforms [7E32] |
19 | D3F2 | ??????? [81A8] |
1A | D3F6 | Collapsable platform [8210] |
1B | D3FA | ??????? [110C6] |
1C | D3FE | Fireball launcher from SLZ [87CA] |
1D | D402 | ??????? [885E] |
1E | D406 | Double big red explosion [8B4C] |
1F | D40A | Crab enemy from GHZ and SYZ [94F0] |
20 | D40E | Big red explosion [8C1C] |
21 | D412 | Unknown. It just sits there. [1C548] |
22 | D416 | Buzz bomber [97DE] |
23 | D41A | Unknown. Sprite sits there and flashes. [9932] |
24 | D41E | Unknown. Sprite changes frame and disappears. [8CF2] |
25 | D422 | Ring [9B26] |
26 | D426 | Monitor [A118] |
27 | D42A | Normal explosion [8D62] |
28 | D42E | Unknown. Edges along grund at a terminal rate. As soon (as in immediately) as it leaves the screen it disappears. [8F22] |
29 | D432 | ??????? [9412] |
2A | D436 | One way barrier from SBZ [8934] |
2B | D43A | Unknown. Sprite moves off bottom of screen. [AB20] |
2C | D43E | Unknown. Sprite changes a few frames, then sits there moving quickly back and forth in a small area. [ABDA] |
2D | D442 | Drill badnick in LZ [ACA4] |
2E | D446 | Contents of monitor flying up frm monitor being busted [A302] |
2F | D44A | Platfrom in MZ that moves up and down [AEB8] |
30 | D44E | Unknown. Big block. [B39E] |
31 | D452 | Metal block with spikes on bottom from MZ [B67C] |
32 | D456 | Button [BD2E] |
33 | D45A | Moveable block in MZ and LZ [BED2] |
34 | D45E | Title card [C306] |
35 | D462 | ??????? [B1DC] |
36 | D466 | Spikes [CE28] |
37 | D46A | Rings flying out from being hit [9CB6] |
38 | D46E | ??????? [14158] |
39 | D472 | "Game over" sprite [C4B8] |
3A | D476 | End of level results screen [C572] |
3B | D47A | Rock from GHZ [D050] |
3C | D47E | Breakable barrier from GHZ [D11C] |
3D | D482 | Robotnic in his primary ship [17700] |
3E | D486 | Egg prison [1AB22] |
3F | D48A | Large explosion [8DF6] |
40 | D48E | Motobug from GHZ [F61A] |
41 | D492 | Red spring [DABE] |
42 | D496 | Badnick that appears behind wall and fires projectile from GHZ [DD68] |
43 | D49A | Metal dude that goes in a ball like sonic from SYZ [DFFA] |
44 | D49E | Wall barrier from GHZ [E1D4] |
45 | D4A2 | Sideways spikes that were cut in MZ [B99A] |
46 | D4A6 | Block from MZ [E7D0] |
47 | D4AA | Bumper [E9D0] |
48 | D4AE | Large ball from GHZ that was cut [17AE4] |
49 | D4B2 | ??????? [D0BE] |
4A | D4B6 | Unknown. Some sort of teleport effect. Most likely belongs to those lost patterns. [14254] |
4B | D4BA | Large golden ring [9E06] |
4C | D4BE | Lava spurt with lava ripples [ED84] |
4D | D4C2 | Lava spurt [EE70] |
4E | D4C6 | Lava wave from MZ [F05E] |
4F | D4CA | ??????? [F806] |
50 | D4CE | That ground based badnick with spikes ontop from SYZ [F83A] |
51 | D4D2 | Breakable block in MZ [FC92] |
52 | D4D6 | Misc platforms [FDF8] |
53 | D4DA | Platform made up of small blocks that collapses [8320] |
54 | D4DE | Sprite for lava hurting you [F1B8] |
55 | D4E2 | Bat from MZ [100A8] |
56 | D4E6 | Block from SYZ [10286] |
57 | D4EA | Unknown. A small sprite with a small collision box that hurts you, but you can't bust it. [10782] |
58 | D4EE | Same as above, but different image [10976] |
59 | D502 | Raising platforms from SLZ [10AD2] |
5A | D506 | Platform moving in circular motion in SLZ [10D5A] |
5B | D50A | Lowering staircase from SLZ [10E90] |
5C | D50E | Pylon in foreground frm SLZ [11044] |
5D | D512 | Fan from SLZ [114FC] |
5E | D516 | See saw [1163C] |
5F | D51A | Walking bomb [119F6] |
60 | D51E | Badnick surrounded by spikeballs that shoots them at you [11CCE] |
61 | D522 | Misc blocks from LZ [11FD4] |
62 | D526 | Stone head that launches projectile in LZ [121E8] |
63 | D52A | Rotating wheel in LZ [1233C] |
64 | D52E | Small bubble [126A4] |
65 | D532 | moving water sprites from LZ [12A9E] |
66 | D536 | Spinning wheel in SBZ that shoots you off in different directions [1509A] |
67 | D53A | Spinning circle on wheel from SBZ [154E2] |
68 | D53E | ??????? [1568E] |
69 | D542 | Various platforms from SBZ [15730] |
6A | D546 | Giant pizza slicer thing from SBZ [1597C] |
6B | D54A | Misc blocks in SBZ [15C12] |
6C | D54E | Spikewheel from SBZ that runs through floor [15FF8] |
6D | D552 | Unknown. Looks like flamepipe frm SBZ [E4E0] |
6E | D556 | Broken pipe that lets out fire from SBZ [16146] |
6F | D55A | ??????? [1626A] |
70 | D55E | Big moving rectangle in SBZ [1652A] |
71 | D562 | Unknown. A collsion box but no image. [1141A] |
72 | D566 | Unknown. A spin tube? [16668] |
73 | D56A | Robotnic flying his default ship. [18230] |
74 | D56E | Unknown. Changes frames back and forth for awhile, and it can hurt you but you can't hurt it, then it diappears. [186A4] |
75 | D572 | ??????? [190EE] |
76 | D576 | ??????? [19692] |
77 | D57A | ??????? [17E36] |
78 | D57E | Catakiller [16934] |
79 | D582 | Starpoll [16E2E] |
7A | D586 | ??????? [188B8] |
7B | D58A | Unknown. Makes flashing stuff appear at top of screen [18CCE] |
7C | D58E | Special stage entry effect [9ED6] |
7D | D592 | ??????? [1715E] |
7E | D596 | End of special stage results screen [C7AE] |
7F | D59A | Bubble [C956] |
80 | D59E | Continue screen [4E42] |
81 | D5A2 | ??????? [4F5C] |
82 | D5A6 | ??????? [19832] |
83 | D5AA | ??????? [19B60] |
84 | D5AE | ??????? [1A44E] |
85 | D5B2 | ??????? [19D58] |
86 | D5B6 | ??????? [1A7DA] |
87 | D5BA | ??????? [53E2] |
88 | D5BE | ??????? [553C] |
89 | D5C2 | ??????? [5616] |
8A | D5C6 | ??????? [17264] |
8B | D5CA | ??????? [59E2] |
8C | D5CE | ??????? [5AC2] |
References