Sonic the Hedgehog 2 (Master System)
From Sonic Retro
SONIC 2 MASTER SYSTEM ROM HACKING |
Written by Leon "Hivebrain" White.
Sections:
[#rom ROM contents]
[#headers Level headers]
[#levsel Level select pointers]
[#tcard Title card mappings]
[#palletes Palletes]
[#32x32 32x32 mappings]
[#level Level layout & compression]
[#sprite Sprite layout]
[#loop Loop X/Y motion data]
[#littleendian Little endian things]
ROM Contents
A4C-DEA Level select text (plain ASCII format) E1C-E4B Level select level pointers 28F0 Pointers for title card mappings (16-bit, little endian) 2904-2FA7 Mappings for title cards & act results screens 55E5 Pointers for level headers (16-bit, little endian) 5635-585A Level headers 10000 Uncompressed art - Sonic 13800 Compressed Art - bubble (ALZ) 13930 Compressed Art - jumping pig enemy (GMZ) 13BD0 Compressed Art - small yellow numbers (unused) 13CF8 Compressed Art - spinning turtle enemy (SHZ/SEZ/CEZ) 14000 Uncompressed art - Sonic gliding (SHZ) 15E00 Uncompressed art - Sonic riding a minecart (UGZ/GMZ) 18000 Uncompressed art - Sonic runnning round a loop (ALZ/GHZ) 1BC00 Compressed Art - spinning wheel (CEZ) 1BE60 Compressed Art - block (CEZ) 1C000 Compressed Art - numbers, lives icon 1C2CA Compressed Art - collected ring sparkles 1C306 Compressed Art - invincibility sparkles 1C332 Compressed Art - explosion 1C462 Compressed Art - monitor (generic) 1C608 Uncompressed art - monitors (specific) 1CCC8 Compressed Art - rings (dropped when Sonic gets hit) 1CE98 Compressed Art - moving platform (GHZ) 1CF92 Compressed Art - glider (SHZ) 1D20E Uncompressed art - prison capsule 1DACE Uncompressed art - animals 1E0CE Compressed Art - cloud & tree from scrolling text on title cards 1E124 Uncompressed art - end of act signpost 1EDA4 Compressed Art - minecart (UGZ/GMZ) 1EE48 Uncompressed art - minecart wheel (UGZ/GMZ) 1EEC8 Compressed Art - minecart wheel (UGZ/GMZ) 1F040 Compressed Art - broken minecart (UGZ/GMZ) 1F0EA Uncompressed art - Silver Sonic (SEZ) 1F96A Compressed Art - log (SHZ) 1F9B4 Compressed Art - moving platform (SHZ) 1FAB4 Empty 20000 Compressed Art - circle & floor from intro sequence 206A0 Compressed Art - beta title screen (unused) 213B0 32x32 mappings - intro sequence 216E0 32x32 mappings - title screen 21A32 Level layout - intro sequence (uncompressed) 21AB2 Level layout - title screen (uncompressed) 21B32 Uncompressed art - mini Sonic from intro sequence 22832 Compressed Art - scenery from intro sequence 229A2 Compressed Art - Sonic's hand from title screen 22C32 Compressed Art - Tails' face from title screen 22DA2 Mappings for title screen 2307C Unknown 23C72 Empty 24000 Code 2411F Pallete - unknown (4 shades of grey) 2412F Pallete - unknown 2413F Pallete - unknown 2414F Pallete - title cards 2415F Pallete - Sonic (GHZ) 2416F Pallete - Sonic (SHZ1/3) 2417F Pallete - Sonic (SHZ2) 2418F Pallete - Sonic (ALZ1/3) 2419F Pallete - Sonic (ALZ2) 241AF Pallete - Sonic (UGZ) 241BF Pallete - Sonic (GMZ) 241CF Pallete - Sonic (SEZ) 241DF Pallete - Sonic (CEZ1/2) 241EF Pallete - Sonic (CEZ3) 241FF Pallete - UGZ 2420F Pallete - SHZ1/3 2421F Pallete - SHZ2 2422F Pallete - ALZ1/3 2423F Pallete - ALZ2 2424F Pallete - GHZ 2425F Pallete - GMZ 2426F Pallete - SEZ 2427F Pallete - CEZ1/2 2428F Pallete - CEZ3 2429F Pallete - intro sequence 242AF Pallete - title screen 242BF Pallete - intro sequence 242CF Pallete - title screen 242DF Pallete - unknown 242EF Palletes (7) - title cards (UGZ, SHZ, ALZ, GHZ, GMZ, SEZ, CEZ) 2435F Pallete - unknown 2436F Pallete - Sonic (ending) 2437F Pallete - unknown 2438F Palletes (8) - ending (gradually changes from day to night) 2440F Pallete - blank 2441F Loop XY motion data (ALZ/GHZ) 24D1E Compressed Art - level select text 2511E Compressed Art - text from title cards 260A4 Compressed Art - UGZ level tiles 270DC Compressed Art - yellow bird (SHZ) 2715C Compressed Art - spears (ALZ) 2724E Compressed Art - moving platform (GMZ) 2724E Compressed Art - moving platform (SEZ) 273E8 Compressed Art - newtron (UGZ/SHZ/GHZ) 27654 Compressed Art - bomb enemy (GMZ/SEZ) 27782 Compressed Art - moving platform (UGZ) 27870 Compressed Art - crab (UGZ/ALZ/GHZ/SEZ/CEZ) 27B90 Compressed Art - splash (ALZ) 27BE0 Compressed Art - water (ALZ) 27C10 Compressed Art - falling spike (UGZ) 27CB0 Compressed Art - falling spike (GMZ) 27D50 Compressed Art - bubble (ALZ) 27E51 Empty 28000 Compressed Art - SHZ1/3 level tiles 291DC Compressed Art - SHZ2 level tiles 2A2AC Compressed Art - GMZ level tiles 2B2E2 Compressed Art - text from ending sequence 2B812 Empty 2C000 32x32 mappings - SHZ1/3 2D8C0 32x32 mappings - SHZ2 2F080 Level layout - CEZ1 (compressed) 2FA48 Empty 30000 32x32 mappings - GHZ 316C0 32x32 mappings - ALZ 32F80 Level layout - SHZ3 (compressed) 33716 Level layout - GMZ3 (compressed) 34000 Level layout - GHZ1 (compressed) 34C6B Level layout - GHZ2 (compressed) 35884 Level layout - GHZ3 (compressed) 36429 Level layout - SHZ1 (compressed) 370D8 Level layout - SHZ2 (compressed) 38000 Level layout - ALZ1 (compressed) 38F68 Level layout - ALZ2 (compressed) 39DFF Level layout - ALZ3 (compressed) 3ADBB Level layout - UGZ1 (compressed) 3C000 32x32 mappings - ALZ2 3DD80 32x32 mappings - UGZ 3F380 Compressed Art - "Game Over" text 3F75A Compressed Art - numbers 0 to 9 in scrolling GHZ style 3FB7E Mappings for Game Over screen 3FC5E Empty 40000 Uncompressed art - Sonic (mirrored) 43680 Compressed Art - little wavy lines (?) 436C0 Compressed Art - fireball (UGZ) 43722 Compressed Art - mini flame (UGZ) 43740 Compressed Art - lobster enemy (ALZ) 439A0 Compressed Art - burrobot (GMZ) 43C82 Compressed Art - moto bug (UGZ/GHZ) 43E28 Compressed Art - fish enemy (CEZ) 43EDA Empty 44000 Uncompressed art - Sonic gliding (mirrored) 45E00 Uncompressed art - Sonic riding a minecart (mirrored) 48000 Uncompressed art - Sonic running round a loop (mirrored) 4BC00 Compressed Art - block (SEZ) 4BC80 Compressed Art - moving platform (CEZ) 4BD46 Compressed Art - levitating spiked rock (CEZ) 4C000 Level layout - GMZ1 (compressed) 4CC68 Level layout - GMZ2 (compressed) 4DA91 Level layout - SEZ1 (compressed) 4E9C9 Level layout - SEZ2 (compressed) 4F76E Compressed Art - Tails & Eggman from intro sequence 4FC2A Empty 50000 Compressed Art - SEZ1/3 level tiles 5102A Compressed Art - SEZ2 level tiles 52102 Uncompressed art - UGZ boss 52E42 Compressed Art - "END" from ending sequence 53002 Compressed Art - Tails running in ending sequence 53850 Compressed Art - Tails looking up in ending sequence 53960 Uncompressed art - chaos emeralds 54000 Compressed Art - ALZ1/3 level tiles 550F0 Compressed Art - ALZ2 level tiles 56116 Compressed Art - CEZ1/2 level tiles 56E7E Compressed Art - CEZ3 level tiles 58000 32x32 mappings - GMZ 59960 32x32 mappings - SEZ1/3 5AF20 32x32 mappings - ending sequence / original GHZ 5B900 Empty 5C000 32x32 mappings - SEZ2 5D760 32x32 mappings - CEZ3 5E000 Compressed Art - GHZ level tiles 5F11B Level layout - UGZ2 (compressed) 60000 32x32 mappings - CEZ1/2 61600 Compressed Art - title screen 6299A Compressed Art - Eggman final boss (CEZ3) 6339C Compressed Art - cloud (CEZ3) 633CC Empty 64000 Compressed Art - UGZ title card pic 649A0 Compressed Art - SHZ title card pic 65410 Compressed Art - ALZ title card pic 65DC0 Compressed Art - GHZ title card pic 66446 Compressed Art - GMZ title card pic 66C26 Compressed Art - SEZ title card pic 670A6 Compressed Art - CEZ title card pic 67806 Mappings for title card pics 67F06 Empty 68000 Uncompressed art - GMZ boss 68980 Uncompressed art - SHZ boss 69740 Uncompressed art - ALZ boss 6A0C0 Uncompressed art - GHZ boss 6B340 Compressed Art - rock (SHZ) 6B460 Compressed Art - fragment of a smashed block (all zones) 6B4EA Uncompressed art - Tails (CEZ3) 6C000 Level layout - UGZ3 (compressed) 6C6D3 Level layout - SEZ3 (compressed) 6D1F5 Level layout - CEZ2 (compressed) 6DE81 Level layout - CEZ3 (compressed) 6DFD7 Level layout - good ending sequence (compressed) 6E151 Level layout - bad ending sequence (compressed) 6E2C2 Compressed Art - original GHZ level tiles from ending sequence 6F719 Empty 70000 Unknown 75C00 Uncompressed art - rings (UGZ) 75F00 Uncompressed art - rings (SHZ1/3) 76200 Uncompressed art - rings (SHZ2) 76500 Uncompressed art - rings (ALZ) 76800 Uncompressed art - rings (GHZ) 76B00 Uncompressed art - rings (GMZ) 76E00 Uncompressed art - rings (SEZ) 77100 Uncompressed art - rings (CEZ) 77400 Unknown 77552 Credits (plain ASCII format) 77732 Empty 78000 Unknown 78135 Pointers for sprite layouts (16-bit, little endian) 78173 Sprite layout - UGZ1 782C1 Sprite layout - UGZ2 7840F Sprite layout - UGZ3 7848E Sprite layout - SHZ1 784E9 Sprite layout - SHZ2 78568 Sprite layout - SHZ3 78584 Sprite layout - ALZ1 78666 Sprite layout - ALZ2 787BD Sprite layout - ALZ3 787F4 Sprite layout - GHZ1 788C4 Sprite layout - GHZ2 78970 Sprite layout - GHZ3 78983 Sprite layout - GMZ1 78A4A Sprite layout - GMZ2 78AFF Sprite layout - GMZ3 78B24 Sprite layout - SEZ1 78BE2 Sprite layout - SEZ2 78C7C Sprite layout - SEZ3 78C8F Sprite layout - CEZ1 78D20 Sprite layout - CEZ2 78D8D Sprite layout - CEZ3 78D97 Unknown 7AF41-7AF49 Cycling pallete - UGZ lava 7AF4A-7AF52 Cycling pallete - SHZ2 rain 7AF53-7AF5B Cycling pallete - ALZ water 7AF5C-7AF64 Cycling pallete - GMZ wheels and conveyor belts 7AF9F-7AFCE Cycling pallete - CEZ3 lightning Level headers:
Each level header consists of 22 bytes:
MM MM MM LL LL LL ?? ?? CC CC ?? ?? ?? ?? ?? ?? ?? XX ?? YY ?? ??
MM MM MM = 32x32 mappings pointer
LL LL LL = level layout pointer
CC CC = collision data pointer
XX = level width
YY = level heightThe mappings and level layout pointers use the following format:
MM = bank number, where the data is located. The ROM is divided up into "banks", each of which is 0x4000 bytes large. Bank number 00 starts at address 0x0, bank 01 starts at address 0x4000, bank 0F starts at 0x3C000, and so on.
MM MM = location of the data within the bank (16-bit, little endian). This pointer has 0080 added to it, for some reason.The collision pointer lacks a bank number, presumeably because all the data is in the same bank, which makes the bank number unnecessary.
ROM addresses for the level headers:
5635, 564B, 5661 GHZ1/2/3 5677, 568D, 56A3 SHZ1/2/3 56B9, 56CF, 56E5 ALZ1/2/3 56FB, 5711, 5727 UGZ1/2/3 573D, 5753, 5769 GMZ1/2/3 577F, 5795, 57AB SEZ1/2/3 57C1, 57D7, 57ED CEZ1/2/3 5803 Bad Ending 5819 Good Ending 582F Intro 5845 Title Screen Level select pointers:
The pointers define which level the game goes to for each item on the level select. Each pointer consists of two bytes: one for the zone number, and one for the act number. The level numbers are as follows:
Value Zone 00?? Underground 01?? Sky High 02?? Aqua Lake 03?? Green Hills 04?? Gimmick Mt. 05?? Scrambled Egg 06?? Crystal Egg 0700 Bad Ending Sequence 0701 Good Ending Sequence 0900 Intro Sequence 0901 Title Screen The act numbers are just 00, 01 and 02. There are a total of 18 entries in the pointer array.
Title card mappings:
The title cards are built up with rows of 8x8 tiles. Mappings define which tiles are pulled from the VRAM and displayed on the screen. Each 8x8 tile is given a 2-byte, little endian value based on where it appears in the VRAM:
So, the letter A would mapped like so:
0111 0211 0C11 0D11 Spaces not containing any letters are 7011. Here are the ROM addresses for each title card:
2904 GREEN HILLS 298C ZONE 29C4 AQUA LAKE 2A34 UNDERGROUND 2AA4 SKY HIGH 2B14 GIMMICK MT. 2B84 MOUNTAIN 2BF4 SCRAMBLED EGG 2C64 CRYSTAL EGG 2CE4 SONIC HAS 2D54 PASSED 2D98 RING 2DAC TIME 2DC0 SCORE 2DD6 100X 2DE5 00 2DF6 00 2E04 ACT 1 2E90 ACT 2 2F1C ACT 3 Palletes:
Master System palletes contain 16 colours, and each colour is defined by a single byte. Although you might think this means the colour format is 8-bit, it's actually only 6-bit, which gives a total of 64 possible colours. The colours are stored in the ROM as a value between 00 and 3F:
32x32 Mappings:
First of all, the mappings begin with an offset index containing 256 16-bit, little endian pointers. The pointers are relative to a fixed position in the ROM, which varies depending on which set of mappings you're looking at. Immediately after the offset index is the mappings data itself. Each 32x32 tile is composed of 16 8x8 tiles. A 16-bit, little endian value is used to define which 8x8 tile is pulled from the VRAM, and also how that 8x8 tile is displayed. Adding certain amounts to the value cause the 8x8 tile to be flipped/mirrored:
Value added Effect +0000 None +0002 Flip horizontally +0004 Flip vertically +0006 Flip both ways Level layout and compression:
Each byte in the level layout represents a 32x32 tile. The level is composed of many 32x32 tiles. In a savestate, the level is easy to edit because it's simple and uncompressed. However, in the ROM it's usually compressed.
Uncompressed:
2020 2020 2020---> Compressed:
FD06 20FD means compression has occurred. 06 is the number of times a byte has been repeated. 20 is the byte which has been repeated.
Strangely, 1515 (for example) appears in the ROM as FD02 15, which wastes space. Repeated strings of bytes can be used in the ROM, and will appear correctly in the game. Compression is entirely optional, given that there is enough space in the ROM for the data.
Sprite Layout:
The properties of each sprite is determined by 9 bytes, which follow this format:
TT XXXX YYYY ??SS VVWW (FF)
TT = object type
XXXX = horizontal position
YYYY = vertical position
SS = object subtype
VV = tiles to read from the VRAM
WW = tiles to read from the VRAM when the object is reversed
FF = end of sprite list (only appears once)Object types and subtypes:
TT SS Description 00 Nothing 01 Sonic 04 Fragment of a smashed block 0A Bubbles (ALZ) 0B Splash of water (ALZ) 0D-0E Fireball (UGZ) 0F Explosion 10 Monitors: 00 Blank 01 Blank 02 Rings 03 Extra life 04 Speed shoes 05 Invincibility 06 Running Sonic (does nothing) 07 Question mark (does nothing) 08 Lead shoes (does nothing) 09 Arrow (does nothing) 11-14 Chaos emerald 15-18 End level signpost 19 Falling spike with wrong mappings 1A Unknown 1B Falling spike (UGZ) 1C Clouds (intro sequence) 1D Clouds & cycling pallete (intro sequence) 1E Tree (intro sequence) 1F Unknown 20 Platforms: 00 Moves side-to-side 01 Falls when you stand on it 02 Swinging 21 Platforms: 00 Rises when you stand on it 01 Rises when you stand on it, then reappears in its original position 02 Moves side-to-side 03 Moves right when you stand on it 04 Doesn't move 22 XX Platform: moves side-to-side, XX = distance moved 23 Crab enemy 24 Fireballs that the crab enemy spits out 25 Yellow bird (SHZ) 26 Spears (ALZ): 00 Moves upwards 01 Moves upwards 02 Moves downwards 03 Moves left 04 Moves right 27 Glider (SHZ) 28 Flywheel (GMZ) 29 Minecart: 00 Doesn't move 01 Doesn't move 02 Moves right 03 Moves left 04 Explodes when you touch it 2A XX Flywheel: moves side-to-side, XX = distance moved (CEZ) 2B Spiked crystal (CEZ) 2C Falling block (CEZ) 2D Falling log (SHZ) 2E Unknown 2F Unknown 30 Makes Sonic flash 31 Makes Sonic flash 32 Spinning turtle enemy (SHZ) 33 Lobster enemy (ALZ) 34 Moto bug enemy 35 Newtron enemy 36 SHZ boss - mini robot birds 37 Fish enemy (CEZ) 38 Burrobot enemy (GMZ) 39 Bomb enemy 3A Pig enemy (GMZ) 3B-3F Unknown 40 Prison capsule 41 Animals 42 GHZ boss - sumo robot 43 Unknown 44 GMZ boss - pig robot 45 GMZ boss - falling rocks 46 SHZ boss - mini robot birds 47 SHZ boss - eggs 48 SHZ boss - big bird robot 49 Unknown 4A ALZ boss - seal robot 4B UGZ boss - Eggman 4C UGZ boss - cannonball 4D UGZ boss - pincers thing 4E SEZ boss - Silver Sonic 4F ALZ boss - orange bouncing ball 50 Sonic's hand (title screen) 51 Tails' face (title screen) 52 Unknown 53 CEZ boss - floating cluster of yellow balls 54 CEZ boss - zigzag thing that crawls across the floor 55 CEZ boss - Eggman 56-5C Unknown 5D Tails (CEZ) 5E Unknown 5F Tails & Eggman (intro sequence) Loop XY motion data:
When Sonic hits a loop in either Aqua Lake or Green Hills Zone, you're momentarily unable to control him. The loop motion data determines how Sonic moves vertically and horizontally when he reaches a loop. By default, he moves in a large circle. Modifying the loop data could allow Sonic to move around virtually any shape.
Little endian things:
This means 1234 becomes 3412, and 5500 becomes 0055. It's a feature of Master System ROMs which makes hacking them slightly more confusing. Pointers have to be read backwards.