Sonic the Hedgehog 2 (16-bit)
From Sonic Retro
Revision as of 15:40, 28 August 2006 by Ss is testing (talk | contribs) (→Pattern Load Requests: and also uses the correct operator for assignment)
This is the Sonic Community Hacking Guide for Sonic the Hedgehog 2. Originally based on Nemesis's guide, this document has grown to outclass it in most ways, and is now preferred over the original Nemesis guides (which were written three or four years ago with limited knowledge of the game's code).
Contents
ROM Hacking
Art Editing
There are several different tools that can be used to edit art besides the hex editor. SonED is probably the best tool to use for editing level art, and can also be used on palettes. HivePal is also a great tool for editing palettes. Sonik Sprite is useful for editing uncompressed art; it gets its name from its ability to edit Sonic's sprites. LOst Library is most likely the best choice for editing compressed art in the Nemesis format.
If, however, you still want to do it yourself, your best bet is to download the Sonic 2 Split disassembly here. Decompress the archive into a new folder, and place your S2 ROM, in binary format and named "S2.bin", in that folder. Run the batch file "split.bat". This will split up all the art into its own binary files, which you can then decompress and edit. When you're done, run "combine.bat".
Uncompressed Art Locations
Most of this information was taken from Nemesis's guide. Please excuse any mistakes or misunderstandings, as that guide wasn't exactly well-written. A description is written in parentheses after the original name if I deem it necessary; if I don't know what it is, "Unknown" appears in that place. Please correct this if you know. It doesn't list the number of blocks taken up, so if you know, put it in. Otherwise, I'll find out eventually.
Offset | Description | # of blocks |
---|---|---|
Zone Independent | ||
$50000 | Sonic | ? |
$64180 | Tails | ? |
$71FFC | Splash | ? |
$7287C | Spindash smoke | ? |
$7A1A0 | Signpost | ? |
$7AF82 | Drowning countdown | ? |
$7CD30 | Option and level select menu background | ? |
Emerald Hill Zone | ||
$49714 | Animated flowers | ? |
$49914 | Pulsing orb on walls | ? |
Chemical Plant Zone | ||
$4FAFE | Part of background | ? |
Aquatic Ruin Zone | ||
$4FCFE | Waterfall | ? |
Casino Night Zone | ||
$4D4FE | Flipping square in foreground | ? |
$4EEFE | Slot machine pictures | ? |
Hill Top Zone | ||
$49714 | Animated flowers | ? |
$4A33E | Clouds from background | ? |
$4B73E | Lava | ? |
Mystic Cave Zone | ||
$894E4 | Rocks that fall from ceiling during boss fight | ? |
Oil Ocean Zone | ||
$49914 | Pulsing orb on walls | ? |
$4BF7E | Pulsing ball | ? |
$4C0FE | Square rotating around ball (Unknown) | ? |
$4C4FE | Oil | ? |
Metropolis Zone | ||
$4A73E | Rotating net | ? |
$4B73E | Lava | ? |
$4BD3E | Parts of background | ? |
Death Egg Zone | ||
$4FAFE | Part of background | ? |
Compressed Art Locations - Nemesis format
See SCHG:Sonic 2/Nemesis Compressed Art.
Compressed Art Locations - Kosinski format
- $95C24 - EHZ/HTZ main level patterns
- $9DB64 - MTZ main level patterns
- $A4204 - OOZ main level patterns
- $A9D74 - MCZ main level patterns
- $B0894 - CNZ main level patterns
- $B6174 - CPZ/DEZ main level patterns
- $BCC24 - ARZ main level patterns
- $C5004 - SCZ/WFZ main level patterns
- $DCA38 - Special stage floor patterns
Palette Editing
Usually, it's not really necessary to edit a palette in hex. Palette editors give you instant feedback for each RGB value, and the palette can be easily saved as a separate binary and reimported into the ROM. However, it is sometimes desireable or necessary to do it in hex, and it can't hurt to know how it's done.
These are the ROM offsets of the palettes in Sonic 2, as listed by HivePal:
Name | Offset |
---|---|
Sega Sonic | $2902 |
Title Screen (Sonic) | $133EC |
Title Screen (Tails) | $2942 |
Title Screen (Main) | $1340C |
Title Screen Water | $1E5A |
Sonic and Tails | $29E2 |
Sonic to Super Sonic | $2246 |
Super Sonic | $2276 |
Title Cards | $2A02 |
Emerald Hill | $2A22 |
Emerald Hill/Aquatic Ruin Rotating Water | $1E7A |
Wood | $2A82 |
Wood Conveyor Belts | $1F1A |
Metropolis | $2AE2 |
Metropolis Cycle #1 | $1F2A |
Metropolis Cycle #2 | $1F36 |
Metropolis Cycle #3 | $1F42 |
Wing Fortress | $2B42 |
Wing Fortress Fire Cycle | $20A2 |
Hill Top | $2BA2 |
Hill Top Lava | $1E9A |
Hidden Palace | $2C02 |
Hidden Palace (Sonic & Tails Under Water) | $2C62 |
Hidden Palace Underwater Tiles Pallete | $2C82 |
Hidden Palace Water Cycle | $1F56 |
Hidden Palace Underwater Cycle | $1F66 |
Oil Ocean (Do not edit or you'll get a huge mess unless you know how to fix it!) | $2CE2 |
Oil Ocean Oil | $1F76 |
Mystic Cave | $2D42 |
Mystic Cave Lanterns | $1F86 |
Casino Night | $2DA2 |
Casino Night Cycle 1 | $1F8E |
Casino Night Cycle 2 | $1FA0 |
Casino Night Cycle 3 | $1FB2 |
Casino Night Cycle 4 | $1FC4 |
Chemical Plant | $2E02 |
Chemical Plant Sonic & Tails Underwater | $2E62 |
Chemical Plant Underwater | $2E82 |
Chemical Plant Underwater Sonic to Super Sonic | $22C6 |
Chemical Plant Underwater Super Sonic | $22F6 |
Chemical Plant Cycle 1 | $2022 |
Chemical Plant Cycle 2 | $2058 |
Chemical Plant Cycle 3 | $2082 |
Chemical Plant Cycle 4 | $20E2 |
Death Egg | $2EE2 |
Aquatic Ruin | $2F42 |
Sonic & Tails Underwater (Aquatic Ruin) | $2FA2 |
Aquatic Ruin Underwater | $2FC2 |
Sonic to Super Sonic Underwater (Aquatic Ruin) | $2346 |
Aquatic Ruin Underwater Super Sonic | $2376 |
Sky Chase | $3022 |
Menus | $30E2 |
Special Stage Main | $3162 |
Special Stage Sonic | $3182 |
Special Stage Tails | $31A2 |
Special Stage 1 | $31C2 |
Special Stage 2 | $31E2 |
Special Stage 3 | $3202 |
Special Stage 4 | $3222 |
Special Stage 5 | $3242 |
Special Stage 6 | $3262 |
Special Stage 7 | $3282 |
Special Stag 1 2p | $32A2 |
Special Stage 2 2p | $32C2 |
Special Stage 3 2p | $32E2 |
Special Stage Chaos Emerald | $35F92 |
Special Stage Results Screen | $3302 |
Emerald Hill Icon | $9880 |
Metropolis Icon | $98A0 |
Hill Top Icon | $98C0 |
Hidden Palace Icon | $98E0 |
Oil Ocean Icon | $9900 |
Mystic Cave Icon | $9920 |
Casino Night Icon | $9940 |
Chemical Plant Icon | $9960 |
Aquatic Ruin Icon | $9980 |
Sky Chase Icon | $99A0 |
Wing Fortress Icon | $99C0 |
Death Egg Icon | $99E0 |
Special Stage Icon | $9A00 |
X 2 Player Versus Icon | $9A20 |
Sound Test Icon | $9A40 |
Ending Grey Cutscenes | $AD1E |
Ending Main | $ACBE |
Ending Sonic | $AC7E |
Ending Tails | $AC9E |
Ending Super Sonic | $AD3E |
Unknown 1 | $3082 |
Unknown 2 | $30A2 |
Oil Ocean Zone Boss (Pallete line 1) | $30C2 |
For details of the palette data format, see Megadrive Palettes.
Pattern Load Requests
Nemesis named this structure the "pattern load queue". However, this name tends to confuse the RAM structure (which is actually a queue) with the ROM structure (which is a set of data to be loaded into the queue).
PLRs tell the game engine where to get Nemesis-compressed art data and where to put it. The format is rather simple, and can be described with this pseudocode:
struct plr{ long *compPattern; word vramStartLoc; }; struct plrList03{ const word plrCount = 3; plr plrArray[3] } plr000;
plrCount is the length of plrArray. compPattern is a pointer to Nemesis-compressed patterns, and vramStartLoc is the VRAM address where the patterns are to be decompressed to.
The RAM queue has space for 20 PLRs. Note that the routines that load PLRs into the queue do not do any bounds checking, and it is quite easy to create a buffer overrun condition. Further, both lists seem to be moved into the queue at the same time, so even if neither one is longer than 20 requests, they can still overrun the queue and destroy the variables that are stored just beyond it. 'Make sure that the primary and secondary PLR lists are no more than 20 requests long.'
Object Editing
Sounds
If you change the "ring" sound effect, all objects using that sound will have the new sound. This may not be desired, however - you may have only wanted the Super Ring powerup to play the new sound. With this list, you can edit the sound effect that an object plays. If you change the sound for the Super Ring power-up, only the Super Ring will have the new sound. Note that you are not changing any sound effects - you are only changing which effect will play.
These notes are for those who don't want see the programming stuff of the objects to change its sounds.
To change the sound, first, take a value from the sound test (Ex: 1-up sound is $18) , add $80 to it and you get $98. This is the way you have to replace sounds (take a value from sound test, add $80 to it, and after that, insert the byte in the offset where you wish change the sound.)
Offset List
The following list is the offset where you will place the new sound. I not will make a list with the values and its respective sounds. Use the trick (explained above) and Sound Test. Of course you can place the objects in any level you want (see Object Placement below), I'm just saying the level the object is used in for a better description.
Level | Description | Offset |
---|---|---|
ALL | Invincibility power-up | $12A81 |
ALL | Shield power-up | $12A37 |
ALL | Super Ring | $129CD |
ALL | Lamp Post: | $1F191 |
Casino Night | Bumper | $1F7F5 |
ALL | Red and Yellow Springs Facing Up | $18A69 |
ALL | Red and Yellow Springs Facing Right | $18BBF |
ALL | Red Spring Facing Down | $18D63 |
Chemical Plant | Speed booster | $223DB |
Chemical Plant | Blue worm (The sound is repeated 3 Times.) | $224EA |
Aquatic Ruin | Arrow launcher | $257B7 |
Casino Night | Slot machine cage | $2BE1F |
Casino Night | Point cage | $2BE6B |
Hill Top | Zip line | $21E75 |
Casino Night | Blue Bumper | $2C577 |
Casino Night | Green flipper | $2B30B |
Casino Night | Orange flipper | $2B3BF |
Casino Night | Impulse spring facing up | $2AE4F |
Wing Fortress | Propellor (repeat infinitely) | $3B3A3 |
Object Pointer List
See SCHG:Sonic 2/Object Pointers.
Sprite table (aka mappings)
Reference
The sprite table data can be expressed with this pseudocode:
struct spriteTablePiece{ byte yPosition; byte shape; byte attributes1P; byte artOffset1P; byte attributes2P; byte artOffset2P; word xPosition; }; struct spriteTableLenghth03{ const word length == 3; spriteTablePiece table[3]; } spriteTable01;
- The value of shape can range from $00 (1x1) to $0F (4x4). $01 is a 1x2 sprite, $02 is a 1x3 sprite, $04 is a 2x1 sprite, and so on.
- attributes1P and attributes2P are bitfields that controls various sprite attributes:
Bit Attribute 3 Flip sprite horizontally 4 Flip sprite vertically 5 Palette line +1 6 Palette line +2 7 Keep sprite in forground
- artOffset1P and artOffset2P control the offset from the object's base tile that the sprite should start reading from. For example, if the object's art started a tile $3F0, and artOffset1P was $06, then the sprite would start reading its art at $3F6.
Question: Are xPosition and yPosition offsets from the object's current position?
Object Placement
There are six bites in one object definition. The first two bytes are the X position of the object, and the next two bytes are the Y position. The 5th byte is the reference number on the object pointer list (see above), and the 6th byte is an optional declaration to use for defining that object's behavior and/or animation. This will depend on the object. See the level specific hacking info for the locations of the object lists.
The 6th byte, the object subtype, is loaded in the 28th byte of the SST of that object (see below).
Ring Placement
There are four bytes for every ring object. The first 2 bytes are X coordinates, after that there is one nibble to determine how many rings, then three nibbles (or one nibble and one byte) for the Y coordinates. After you are done adding all your rings for the level, "FF FF" will end the ring data. A format would look like this:
XX XX TY YY
Where X represents X position, Y represents Y position, and T represents type, as per the table below.
Example: 03 46 10 2B
If you see this, then you will get two horizontal rings at X = 0346 Y = 02B. The "1" determines how many rings there are, and what direction they go. (horizontal or vertical) Here is what you get for each value:
Value | Rings |
---|---|
0 | 1 Horizontal |
1 | 2 Horizontal |
2 | 3 Horizontal |
3 | 4 Horizontal |
4 | 5 Horizontal |
5 | 6 Horizontal |
6 | 7 Horizontal |
7 | 8 Horizontal |
8 | 1 Vertical |
9 | 2 Vertical |
A | 3 Vertical |
B | 4 Vertical |
C | 5 Vertical |
D | 6 Vertical |
E | 7 Vertical |
F | 8 Vertical |
See the level specific hacking info for the locations of the ring data.
Level Layout
Level layouts are compressed in Kosinski format, so to edit them you will need to decompress them first. (I recommend using TSDC for this)
Level layouts are pretty simple. There is one byte per 128x128 tile to place on the map. The blocks are put together from left to right, top to bottom. Each horizontal row is 60 bytes long. The rows are interlaced between the foreground and the background, so that there are 60 bytes for the first row of the foreground, then 60 bytes for the first row of the background, then 60 bytes for the second row of the foreground, etc.
See the level specific hacking info for the locations of level layout data.
Block mappings
These are compressed in Kosinski format, so to edit them you will need to decompress them first.
struct blockElement { int cellProperties : 5; // c int vramCellIndex : 11; }; // i // cccc ciii iiii iiii blockElement (*blockMap)[0x100][4] = 0xFFFF0000; struct metaBlockElement { int : 4; // x int blockIndex : 12; }; // I // xxxx IIII IIII IIII metaBlockElement (*metaBlockMap)[0x300][8] = 0xFFFF9000;
A block is an array of four blockElements. blockElement->cellProperties describes the palette line and orientation of the cell. The actual mapping of block elements is like this:
0 1 2 3
Metablocks are basically arrays of indeces into blockMap. metaBlockElement->blockIndex provides the first index into blockMap; the upper four bits of the element appear to be unused.
Nemesis provides this chart of values for the upper four bits of cellProperties. The LSB mirrors the cell.
Value | Pallet 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 |
See the level specific hacking info for the locations of 16x16 data.
Text Editing
[to be filled later]
Level event scripts
Also known as "dynamic screen resizing" or "dynamic level events", this code is used to create effects unique to a certain Zone or Act. I have no further information to contribute on the subject, as I know absolutely nothing about it.
RAM Hacking
Main System Memory Locations
These are significant locations in the system memory. Note that any numbers entered (for example, score or number of rings) will have to be converted to hex before putting them in.
These are the offsets in RAM. To convert them to Genecyst savestate offsets, add $2478.
RAM offset | Description |
---|---|
$EE00-$EE01 | Camera's X position, as measured from the top left corner of the Act. |
$EE04-$EE05 | Camera's Y position from the same point. |
$EE06-$EE0B | Unknown |
$EE0C-$EE0D | Variable used by the software scroll managers. Its exact purpose is not known. |
$EE0E-$EEC5 | Unknown |
$EEC6-$EEC7 | Screen Y end location; the maximum value for camera Y position. |
$EEC8-$EEC9 | Screen X start location; minimum value for camera X position. Should be 0. |
$EECA-$EECB | Screen X end location; should be at least $30 less than the end of the level, otherwise, Sonic will fall off the screen. |
$EECC-$EECD | Screen Y start location. Note that if $FF00 is placed in both the start and the end, the screen will be Y wrapped. Y wrapping should not be used on levels with water - note what happened in the beta's Hidden Palace Zone. |
$EECE-$EECF | Maximum camera scroll speed |
$F600 | Master level trigger. Tells the game what it should be doing. Values:
The MSB is a loading routine flag. It only matters for some game modes. It won't have any effect when changing modes because it's filtered out, but the corresponding routine does pay attention to it... |
$F604 | This bitfield tells which button(s) on Controller 1, if any, are being pressed. Format is:
This is updated every frame. |
$F605 | Same as $F604, but tells which buttons are being held down. |
$F606 | Same as $F604, but for Controller 2. |
$F607 | Same as $F606, but tells which buttons are being held down. |
$F648-$F649 | Current water level. Should be a valid Y-axis value. Remember, the top of the level is $0000. |
$F650-$F651 | The level that the water should be at. If this is different than the value above, the water will move until they are the same. |
$F652 | Water level change speed. If set to $00, the water level won't change. |
$F65E | Super Sonic palette counter. Decremented with every frame. How it works, exactly, is not known. |
$F65F | Sets the rotating palette for Super Sonic. |
$F670 | Super Sonic ring drain counter. This is updated each frame, so the counter is set to 60 ($3C) on consoles operating in 60Hz mode, or 50 ($32) in consoles operating in 50Hz mode. After each frame, the code subtracts 1. One ring is removed when this counter reaches zero; in other words, each second. |
$F730 | Water flag. Must be set for any of the other water variables to have any effect. Note that levels without water don't have an underwater palette; you must set one or everything below the water level will be black. |
$F760-$F761 | Sonic's top speed |
$F762-$F763 | Sonic's acceleration |
$F764-$F765 | Sonic's deceleration |
$F76C | Routine counter for the object placement engine? |
$F76E-$F76F | Unknown |
$F770-$F773 $F774-$F777 $F778-$F77B $F77C-$F77F |
Sprite loading addresses. Tells the game where in the ROM to get sprite info. |
$F78C-$F78D | Unknown |
$F7AA | Seems to be clear during normal play, but set to some value during a boss fight. That value may be the current Zone number. |
$F7DA | Seems to be a count of the number of screens since the start point (which is set at FF = 0) What? Explain please. |
$F7DB | Unknown (may be unused) |
$FE00 | Start of the system stack. Note that the stack grows up rather than down. This means that when something is pushed onto the stack, the SP is decremented, and when something is popped from it, the SP is incermented. |
$FE06 | Object currently selected in debug mode. |
$FE09 | Object placement mode flag. |
$FE10 | The current Zone. This is the value assigned to the Zone, not its position in the level list. |
$FE11 | Act number |
$FE12 | Number of lives. |
$FE16 | Current special stage. |
$FE18 | Number of continues. |
$FE19 | Super Sonic flag. Setting this will load the Super Sonic tiles, adjust Sonic's jump height, and start draining rings, but it will not load the rotating palette, change acceleration, max speed, or deceleration, or make him invincible. |
$FE1D | Flag determines if the rings counter needs to be updated |
$FE1E | Flag determines if the timer needs to be updated |
$FE1F | Flag determines if the score counter needs to be updated |
$FE20-$FE21 | Ring count |
$FE23 | Minutes on clock. Should not go above $09, or the clock will look like shit. |
$FE24 | Seconds. This one shouldn't go above $3B, for the same reason. |
$FE25 | Milliseconds. I don't know what'll happen if this goes out of range, but it's probably not good. |
$FE26-$FE29 | Score |
$FE30 | Greatest reference number of passed star poles |
$FEC0-$FEC1 | Tails's max speed |
$FEC2-$FEC3 | Tails's acceleration |
$FEC4-$FEC5 | Tails's deceleration |
$FEC6 | Tails's lives |
$FF40-$FF41 | Number of rings to collect before a perfect is scored |
$FF70-$FF71 | "Player in special stage"; variable tested by a lot of other routines, so it may have other meanings |
$FF72-$FF73 | Player option (Sonic and Tails - 0, Sonic alone - 1, Tails alone - 2) |
$FF74-$FF75 | 2P mode items (teleport only, all kinds items - which is which?) |
$FF82-$FF83 | Item in level select menu that's selected (set to 16 to see the HPZ picture) |
$FF85 | Sound currently selected in sound test; value retained when options menu is exited |
$FF86 | Selection on Title Screen |
$FF88 | Selection on 2 Player Level Select Menu |
$FF90-$FF91 | Zone music currently playing. Used for quick access when switching music. |
$FF8C | Box slected in options menu |
$FFB0 | Special stage completed flag |
$FFB1 | Number of emeralds collected so far |
$FFB2-$FFB8 | Array of finished special stages. Each byte represents one stage. |
$FFD0 | Level select flag |
$FFD1 | Slow motion flag |
$FFD8-$FFD9 | 2P mode flag |
$FFE1 | Play specified sound effect. Not sure how it works. |
$FFE4 | Play specified music. These are the actual playlist values, NOT the sound test values. To convert from sound test to playlist, add $80 to the sound test value. For example, putting in $96 here will play the Super Sonic music; putting in $97 will play the invincibility music. |
$FFF0-$FFF1 | Demo mode flag |
$FFD4 | Unknown cheat value |
$FFFA | Debug mode flag |
Object Status Table Format
The starting offset in RAM for this list is $B000. The first object is always Sonic; the second is always Tails. After this, there is a gap, and the list picks up again at $B400. Each object is alloted a block of $40 bytes. I will use the beginning of a block as a reference point. Note that many of these variables are object-specific - for example, some of them only make sense for Sonic, and some only work on badniks.
Offset | Description | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$00 | Object number. See object list above. | |||||||||||||||||||||||||||
$01 | Action flags. The bitfield looks like this:
| |||||||||||||||||||||||||||
$02-$03 | Starting art block. This is an index into an array of cells; to get the actual address, multiply by $20. | |||||||||||||||||||||||||||
$04-$07 | Object's mappings offset | |||||||||||||||||||||||||||
$08-$09 | If the object is Sonic or Tails, this is the X playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0A-$0B | If the object is Sonic or Tails, this is the X screen coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0C-$0D | If the object is Sonic or Tails, this is the Y playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0E-$0F | If the object is Sonic or Tails, this is the Y screen coordinate. Otherwise:
| |||||||||||||||||||||||||||
$10-$11 | X speed | |||||||||||||||||||||||||||
$12-$13 | Y speed | |||||||||||||||||||||||||||
$14-$15 | Potential speed (inertia). | |||||||||||||||||||||||||||
$16 | Height/2 | |||||||||||||||||||||||||||
$17 | Width/2 | |||||||||||||||||||||||||||
$18 | Sprite priority (00 = front). | |||||||||||||||||||||||||||
$19 | Width of the object, in pixels | |||||||||||||||||||||||||||
$1A | Current animation frame to display. | |||||||||||||||||||||||||||
$1B | Current frame in animation script. | |||||||||||||||||||||||||||
$1C | Animation number. | |||||||||||||||||||||||||||
$1D | Restart animation flag (when $1D is not equal to $1C, animation restarts) | |||||||||||||||||||||||||||
$1E | Animation frame duration (time until next frame). | |||||||||||||||||||||||||||
$20 | Collision response bitfield. Tells what the object will do if hit by the character. The bitfield is in the format TTSS SSSS. TT is the type of collision - 00 is enemy, 01 is some event, 10 is harm, and 11 seems to be a special thing for the starpole. SS SSSS is the size, but the format is unknown. | |||||||||||||||||||||||||||
$21 | Custom collision property, for special interaction with Sonic. This is used by bosses, badniks, bumpers and other objects. The way in which this byte is used is different for each object. Bosses use this byte as a hit counter. | |||||||||||||||||||||||||||
$22 | Object's orientation. $00 is normal, $01 is X flipped, $02 is Y flipped, and $03 is X-Y flipped. These values repeat until $FF. Note that this byte has a different meaning for Sonic and Tails (see below). | |||||||||||||||||||||||||||
$23 | Respawn index reference number, used by badniks, rings and monitors. Each destroyable object is assigned an index number (01, 02, 03 etc.) which refers to a list at $FC00 in the RAM. | |||||||||||||||||||||||||||
$24 | Routine counter. | |||||||||||||||||||||||||||
$25 | Second routine counter. This is used for some of the more complicated objects. | |||||||||||||||||||||||||||
$26-$27 | Angle. | |||||||||||||||||||||||||||
$28 | Object subtype. For example, the current monitor selected. See the Object List above for values. Has a different meaning for Sonic and Tails. | |||||||||||||||||||||||||||
Object-specific variables | ||||||||||||||||||||||||||||
Offset | Description | |||||||||||||||||||||||||||
$22 | Sonic and Tails: Special bitfield. Counting from the least significant bit:
You can add the hex values together to use multiple settings at once. Also notice that the first 3 bits (0-2) are used in the character object as a second routine counter. | |||||||||||||||||||||||||||
$28 | Sonic and Tails: Seconds of air left. Usually $1E; it decrements every second while the player is underwater. Beeps on $18, $13, and $0E. Countdown starts on $0B. | |||||||||||||||||||||||||||
$2B | Sonic and Tails: Another bitfield.
| |||||||||||||||||||||||||||
$30-$31 | Sonic and Tails: Remaining invunerability time. Starts at $0078 after Sonic is hit, and seems to decrement every frame until it reaches $0000. | |||||||||||||||||||||||||||
$32-$33 | Sonic and Tails: Remaining time of invincibility. | |||||||||||||||||||||||||||
$34-$35 | Sonic and Tails: Remaining time of Speed Shoes. | |||||||||||||||||||||||||||
$36 | Sonic and Tails: Seems to be related with the collision block boundaries (this isn't a flag) | |||||||||||||||||||||||||||
$37 | Sonic and Tails: Seems to be related with the collision block boundaries (the opposite side of $36) (this isn't a flag) | |||||||||||||||||||||||||||
$39 | Sonic and Tails: Set if charging a spindash. | |||||||||||||||||||||||||||
$3A-$3B | Sonic and Tails: Spindash counter. Cleared when the spindash is started. After each subsequent "rev", $200 is added to the counter, which then rapidly decreases (the algorithm is to logically shift the value right by five bits and subtract the results from the original). It maxes out at $800. The game looks at the high-order byte to determine how fast the character should move after the dash is released. | |||||||||||||||||||||||||||
$3C | Sonic and Tails: Set if jumping. |