Sonic the Hedgehog 2 (16-bit)/RAM Editing
From Sonic Retro
Sonic Community Hacking Guide Sonic the Hedgehog 2 (16-bit) |
---|
Art |
Objects |
Levels |
Text |
Music |
RAM |
Miscellaneous |
Main System Memory locations
This is a map of 68k memory as used by the main gameplay engine. Note that any numbers entered (for example, score or number of rings) will have to be converted to hex first.
These are the offsets in RAM. To convert them to Genecyst savestate offsets, add $2478.
RAM offset | Git label | Description |
---|---|---|
$0000 - $7FFF | Chunk_Table | Metablock table |
$8000 - $8FFF | Level_Layout | Level layout |
$9000 - $A9FF | Block_Table | Block table |
$AA00 - $A?FF | Decomp_Buffer | Decompression buffer |
$AC00 - $AFFF | Sprite_Table_Input | Sprite table input. Intermediate storage for sprite attribute table data destined for $DD00 or $F800. |
$B000 - $D5FF | Object_RAM | Object attribute table |
$D600 - $D8FF | Primary_Collision | Primary collision index |
$D900 - $DBFF | Secondary_Collision | Secondary collision index |
$DC00 - $DCFB | VDP_Command_Buffer | VDP command buffer. Stores up to 18 sets of queued up VDP commands to be issued later. |
$DCFC - $DCFF | VDP_Command_Buffer_Slot | VDP command buffer free slot. Stores the address of the first available empty place in the VDP command buffer. |
$DD00 - $DF7F | Sprite_Table_2 | Sprite attribute table buffer for the bottom split screen in 2-player mode. |
$E000 - $E3FF | Horiz_Scroll_Buf | Horizontal scroll buffer |
$E400 - $E4FF | Sonic_Stat_Record_Buf | Sonic's statistic recording buffer, used by Tails' AI. |
$E500 - $E5FF | Sonic_Pos_Record_Buf | Sonic's invincibility star position table |
$E600 - $E6FF | Tails_Pos_Record_Buf | Tails' invincibility star position table |
$E800 - $EDFF | Ring_Positions | Ring Layout |
$EE00-$EE01 | Camera_X_pos | Camera's X position, as measured from the top left corner of the Act. |
$EE04-$EE05 | Camera_Y_pos | Camera's Y position from the same point. |
$EE06-$EE0B | Unknown | |
$EE0C-$EE0D | Camera_BG_Y_pos | Variable used by the software scroll managers. Its exact purpose is not known. |
$EE0E-$EEC5 | Unknown | |
$EE20-$EE21 | Camera_X_pos_P2 | Camera's X position, as measured from the top left corner of the Act, for player 2. |
$EE24-$EE25 | Camera_Y_pos_P2 | Camera's Y position from the same point, for player 2. |
$EEC6-$EEC7 | Camera_Max_Y_pos | Screen Y end location for Sonic; the maximum value for camera Y position. |
$EEC8-$EEC9 | Camera_Min_X_pos | Screen X start location for Sonic; minimum value for camera X position. Should be 0. |
$EECA-$EECB | Camera_Max_X_pos | Screen X end location for Sonic; should be at least $30 less than the end of the level, otherwise, Sonic will fall off the screen. |
$EECC-$EECD | Camera_Min_Y_pos | 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 | Camera_Max_Y_pos_now | Screen Y end location for Sonic; the maximum value for camera Y position. Like $EEC6, but changes slowly instead of instantly when the level Y boundary changes. |
$EED2-$EED3 | Sonic_Pos_Record_Index | Index into Sonic's statistics recording buffer and invincibility star position table. |
$EED6-$EED7 | Tails_Pos_Record_Index | Index into Tails' invincibility star position table. |
$EED8 | Camera_Y_pos_bias | Camera Y position bias. |
$EEDA | Camera_Y_pos_bias_P2 | Camera Y position bias for Tails. |
$EEDF | Dynamic_Resize_Routine | Routine counter for Dynamic Screen Resizing. (Dynamic Level Events) |
$EEF8-$EEF9 | Tails_Min_X_pos | Screen X start location for Tails; minimum value for camera X position. Should be 0. |
$EEFA-$EEFB | Tails_Max_X_pos | Screen X end location for Tails; should be at least $30 less than the end of the level, otherwise, Tails will fall off the screen. |
$EEFE-$EEFF | Tails_Max_Y_pos | Screen Y end location for Tails; the maximum value for camera Y position. |
$F000-$F07F | Underwater_target_palette | Underwater target palette. |
$F080-$F0FF | Underwater_palette | Underwater palette. |
$F100-$F5FF | Unused | |
$F600 | Game_Mode | 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... |
$F602 | Ctrl_1_Held_Logical | In-game Controller 1 held state. Same as F604, but it only updates during the main game loop, and not while paused, or a cutscene is running. |
$F603 | Ctrl_1_Press_Logical | In-game Controller 1 pressed state. Same as F602, but only tells which buttons are being pressed newly this frame. |
$F604 | Ctrl_1_Held | This bitfield tells which button(s) on Controller 1, if any, are currently pressed. Format is:
This is updated every frame. |
$F605 | Ctrl_1_Press | Same as $F604, but only tells which buttons are being pressed newly this frame. |
$F606 | Ctrl_2_Held | Same as $F604, but for Controller 2. |
$F607 | Ctrl_2_Press | Same as $F606, but only tells which buttons are being pressed newly this frame for Controller 2. |
$F614 | Demo_Time_left | Demo time left & Time until demo starts from title screen. |
$F624-$F625 | Hint_counter_reserve | Always contains a VDP command consisting of a write to register $0A (H-Int register). This controls which line H-Int occurs on, and is executed every V-Int. |
$F62A | Vint_routine | V-Int routine to run. Goes in units of 2, like most other routine counters. |
$F636 | RNG_seed | RNG seed (used for pseudo-random number generation). |
$F63A-$F63B | Game_paused | Game paused flag. |
$F640 | DMA_data_thunk | DMA data thunk: every final DMA command word gets written here and copied back out, as required by the Megadrive hardware. |
$F648-$F649 | Water_Level_2 | Current water level. Should be a valid Y-axis value. Remember, the top of the level is $0000. |
$F64C | Water_on | Water on: seems to be a copy of $F730. |
$F64D | Water_routine | Water routine counter |
$F64E | Water_fullscreen_flag | Flag which is set when Sonic is fully submerged in water and the underwater palette has to be displayed throughout the entire screen |
$F64F | Do_Updates_in_H_int | Flag which is set when H-Int is set to occur at a line above line $5C. The only effect this has is that DemoTime is called from inside H-Int instead of from inside V-Int |
$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 | Palette_timer | Super Sonic palette counter. Decremented with every frame. How it works, exactly, is not known. |
$F65F | Super_Sonic_palette | Sets the rotating palette for Super Sonic. |
$F66A | Ctrl_2_Held_Logical | In-game Controller 2 held state. Same as $F602, but for controller 2 |
$F66B | Ctrl_2_Press_Logical | In-game Controller 2 pressed state. Same as $F66A, but only tells which buttons are being pressed newly this frame. |
$F66C-$F66D | Sonic_Look_delay_counter | Sonic looking up/ducking counter. Starts off at 0 and is incremented each frame Sonic is looking up/ducking. When this reaches $78, the camera starts to scroll. Reset to 0 upon release of the up/down button. |
$F66E-$F66F | Tails_Look_delay_counter | Same as above, only for player 2. |
$F670-$F671 | Super_Sonic_frame_count | Super Sonic ring drain counter. This is set to 60 ($3C). After each frame, the code subtracts 1. One ring is removed when this counter reaches zero; in other words, each second. |
$F680-$F6DF | Plc_Buffer | A buffer for pattern loading cues (requests). Each entry in this consists of one longword followed by one word, the longword being the location in ROM of the compressed art, and the word being the VRAM location to decompress to. Can store a maximum of 16 entries, but a coding error in the clearing routine means that storing a PLC in the last slot screws everything up, so effectively only 15 requests can be stored at one time. |
$F6E0-$F6E3 | Plc_Buffer_Only_End | The address in ROM of the decompression routine to be used for the art |
$F6E4-$F6F7 | Plc_Buffer_Reg4 | Used by the PLC routines using decompression. No idea what their function is, although it seems they get passed in as parameters to the decompression routine, and are stored updated when the routine returns. |
$F6F8-$F6F9 | Plc_Buffer_Reg18 | The total number of tiles left to be decompressed for the current piece of art |
$F6FA-$F6FB | Plc_Buffer_Reg1A | The number of tiles left to be decompressed in the current frame |
$F700-$F701 | Seems to be set to $0001 when in a Sonic & Tails game. Set to $0000 when not a Sonic & Tails game. | |
$F702-$F703 | Tails_control_counter | Tails control counter. Counts how long until the CPU takes control. |
$F704-$F705 | Tails_respawn_counter | Tails respawn counter. |
$F708-$F709 | Tails_CPU_routine | Tails CPU routine. |
$F70A-$F70B | Tails_CPU_target_x | Tails CPU target X position. Tells Tails where Sonic's X position is so he can fly back to him. |
$F70C-$F70D | Tails_CPU_target_y | Tails CPU target Y position. Tells Tails where Sonic's Y position is so he can fly back to him. |
$F70E-$F70F | Tails_interact_ID | Tails interact ID. Object ID of last object Tails stood on. |
$F710 | Rings_manager_routine | Routine counter for the rings manager. |
$F711 | Level_started_flag | Level started flag. Set to 1 as soon as the player first gets control in the level. |
$F712 | Ring_start_addr | Address (inside the ring layout table) of the first ring whose X position is greater than or equal to the current camera X value. |
$F714 | Ring_end_addr | Address (inside the ring layout table) of the first ring whose X position is greater than or equal to the current camera X value + $150 |
$F716 | Ring_start_addr_P2 | $F712 for Player 2. |
$F718 | Ring_end_addr_P2 | $F714 for Player 2. |
$F72C | Dirty_flag | Dirty flag. Setting this causes the whole screen to redraw (once) instead of only the part that's scrolling into the screen. |
$F730 | Water_flag | 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. |
$F732-$F733 | Demo_button_index_2P | Demo button index for Player 2. |
$F734 | Demo_press_counter_2P | Frames remaining until next button press in a demo for Player 2. |
$F760-$F761 | Sonic_top_speed | Sonic's top speed |
$F762-$F763 | Sonic_acceleration | Sonic's acceleration |
$F764-$F765 | Sonic_deceleration | Sonic's deceleration |
$F766 | Sonic_LastLoadedDPLC | Sonic's current mapping frame number. |
$F76C | Obj_placement_routine | Object placement function's subroutine counter |
$F76E-$F76F | Camera_X_pos_last | Unknown |
$F770-$F773 $F774-$F777 $F778-$F77B $F77C-$F77F |
Obj_load_addr_right | Sprite loading addresses. Tells the game where in the ROM to get sprite info. |
$F780-??? | unk_F780 | Something |
$F78C-$F78D | Camera_X_pos_last_P2 | Unknown |
$F790-$F791 | Demo_button_index | Demo button index for Player 1. |
$F792 | Demo_press_counter | Frames remaining until next button press in a demo for Player 1. |
$F796-$F799 | Collision_addr | Pointer to primary collision data in RAM. |
$F7A7 | Boss_defeated_flag | Boss defeated flag. Set to $1 once boss is defeated. |
$F7AA | Current_Boss_ID | Seems to be clear during normal play, but set to some value during a boss fight. |
$F7CC | Control_Locked | Controller lock. Normally the player object overwrites $F602 with the actual controller state, but setting this flag will prevent that. Used when the game will supply its own movement script. |
$F7D0-$F7D1 | Chain_Bonus_counter | Bonus counter. Increments upon destruction of a destroyable object, and is used to determine how many points the destruction should give. Resets when the player touches the ground. |
$F7D2-$F7D3 | Bonus_Countdown_1 | Time bonus counter at the end of level result screen/Player 1 ring bonus counter at the end of special stage result screen |
$F7D4-$F7D5 | Bonus_Countdown_2 | Ring bonus counter at the end of level result screen/Player 2 ring bonus counter at the end of special stage result screen |
$F7D6 | Update_Bonus_score | Flag determines if the bonus counters need to be updated. |
$F7DA-$F7DB | Camera_X_pos_coarse | Counts the number of times the camera has scrolled to the right by one full screen width from its previous position - initial value is $FF80 and then counts up like: $FF80,$0000,$0080,$0100,$0180,etc. |
$F800-$FA7F | Sprite_Table | Sprite attribute table buffer. |
$FA80-$FAFF | Unused (although due to the way Sonic 2's BuildSprites is designed, it is possible for the sprite attribute table buffer to spill over into this area) | |
$FB00-$FB7F | Normal_palette | Palette. |
$FB80-$FBFF | Target_palette | Target palette. |
$FC00 - $FCFF | Object_Respawn_Table | Object respawn table |
$FE00 | System_Stack | 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 incremented. |
$FE02-$FE03 | Level_Inactive_flag | Level restart flag. |
$FE04-$FE05 | Timer_frames | Level frame timer. |
$FE06 | Debug_object | Object currently selected in debug mode. |
$FE08-$FE09 | Debug_placement_mode | Object placement mode flag. |
$FE10 | Current_Zone | The current Zone. This is the value assigned to the Zone, not its position in the level list. |
$FE11 | Current_Act | Act number |
$FE12 | Life_count | Number of lives. |
$FE16 | Current_Special_Stage | Current special stage. |
$FE17 | Current_Special_Act | Current segment in special stage. |
$FE18 | Continue_count | Number of continues. |
$FE19 | Super_Sonic_flag | 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. |
$FE1A | Time_Over_flag | Flag which is set when Player 1 has a time over |
$FE1B | Extra_life_flags | This bitfield tells the game if the player has collected extra lives from rings.
|
$FE1C | Update_HUD_lives | Flag determines if the lives counter needs to be updated |
$FE1D | Update_HUD_rings | Flag determines if the rings counter needs to be updated |
$FE1E | Update_HUD_timer | Flag determines if the timer needs to be updated |
$FE1F | Update_HUD_score | Flag determines if the score counter needs to be updated |
$FE20-$FE21 | Ring_count | Ring count. This is also applied in Special Stages. |
$FE23 | Timer_minute | Minutes on clock. Should not go above $09, or the clock will look like shit. |
$FE24 | Timer_second | Seconds. This one shouldn't go above $3B, for the same reason. |
$FE25 | Timer_frame | Frames. I don't know what'll happen if this goes out of range, but it's probably not good. |
$FE26-$FE29 | Score | Score (divided by 10) |
$FE30 | Last_star_pole_hit | Greatest reference number of passed star poles |
$FEA0 | Logspike_anim_counter | Log-spike animation counter. |
$FEA1 | Logspike_anim_frame | Log-spike animation frame. |
$FEA2 | Rings_anim_counter | Rings animation counter. |
$FEA3 | Rings_anim_frame | Rings animation frame. |
$FEA6 | Ring_spill_anim_counter | Spilling rings animation counter. |
$FEA7 | Ring_spill_anim_frame | Spilling rings animation frame. |
$FEC0-$FEC1 | Tails_top_speed | Tails' max speed |
$FEC2-$FEC3 | Tails_acceleration | Tails' acceleration |
$FEC4-$FEC5 | Tails_deceleration | Tails' deceleration |
$FEC6 | Life_count_2P | Tails' lives in 2P mode |
$FEC7 | Extra_life_flags_2P | This bitfield tells the game if the player has collected extra lives from rings. Used for Tails in 2P mode.
|
$FEC8 | Update_HUD_lives_2P | Flag determines if the lives counter needs to be updated. Used for Tails in 2P mode. |
$FEC9 | Update_HUD_rings_2P | Flag determines if the rings counter needs to be updated. Used for Tails in 2P mode. |
$FECA | Update_HUD_timer_2P | Flag determines if the timer needs to be updated. Used for Tails in 2P mode. |
$FECC | Time_Over_flag_2P | Flag which is set when Player 2 has a time over. |
$FED0 | Ring_count_2P | Tails' rings in 2P mode. |
$FED3 | Timer_minute_2P | Minutes on clock for Player 2. Should not go above $09, or the clock will look like shit. |
$FED4 | Timer_second_2P | Seconds for Player 2. This one shouldn't go above $3B, for the same reason. |
$FED5 | Timer_frame_2P | Frames for Player 2. I don't know what'll happen if this goes out of range, but it's probably not good. |
$FED6-$FED9 | Score_2P | Score for Player 2 (divided by 10). |
$FEF0-$FEF1 | Rings_Collected | Rings collected since level load. Resets if you enter a Special stage. Starts recounting from 0 when level is reentered. Unknown use. |
$FEF8 | Loser_Time_Left | Seconds remaining for level completion in 2P versus mode. |
$FEF9 | Centiseconds remaining for level completion in 2P versus mode. | |
$FF10 | Results_Screen_2P | The type of 2P versus results screen being displayed:
|
$FF20-$FF39 | Results_Data_2P | 2P results array. The format is 6 bytes per zone (2 per act, the 3rd act is the special stage). The first byte for each act is the number of "wins" for Player 1, while the second byte is the number of "wins" for Player 2. The special stage uses 2 extra bytes: the first is the number of special stages won by Player 1, the second is the number of special stages won by Player 2. |
$FF40-$FF41 | Perfect_rings_left | Number of rings to collect before a perfect is scored |
$FF70-$FF71 | Player_mode | Player in game (at the start of the game, $FF72 is copied over to $FF70, so they're mostly identical) |
$FF72-$FF73 | Player_option | Player option (Sonic and Tails - 0, Sonic alone - 1, Tails alone - 2) |
$FF74-$FF75 | Two_player_items | 2P mode items (all kinds items - 0, teleport only - 1) |
$FF80-$FF81 | LevSel_HoldTimer | Timer which regulates the speed at which the level select selection changes if up or down is held down. The timer is initialized to $B, and 1 is subtracted from it every frame. If the timer is positive, and the up or down button is being held down, the level select screen selection will not be changed. Only when the timer reaches $FFFF (i.e. -1) is the selection changed. The timer is reset to $B in case of it becoming negative or if up/down is released and pressed again. |
$FF82-$FF83 | Level_select_zone | Item in level select menu that's selected (set to 16 to see the HPZ picture) |
$FF84-$FF85 | Sound_test_sound | Sound currently selected in sound test; value retained when options menu is exited |
$FF86 | Title_screen_option | Selection on Title Screen |
$FF88 | Current_Zone_2P | Selection on 2 Player Level Select Menu |
$FF89 | Current_Act_2P | Act number in 2P versus mode |
$FF8A-$FF8B | Two_player_mode_copy | Copy of $FFD8 (no idea why there are 2 copies) |
$FF8C | Options_menu_box | Box slected in options menu |
$FF8E-$FF8F | Total_Bonus_Countdown | Total bonus counter at the end of level result screen/emerald bonus counter at the end of special stage result screen |
$FF90-$FF91 | Level_Music | Zone music currently playing. Used for quick access when switching music. |
$FF92-$FF93 | Bonus_Countdown_3 | Perfect bonus counter at the end of level result screen |
$FF98-$FF99 | Game_Over_2P | 2P versus mode restart game flag. Set when a game over occurs in 2P versus mode, causes 2P versus results for the current session (from $FF20 to $FF37, last two bytes of result data are skipped) to be wiped, resetting the entire session. |
$FFB0 | Got_Emerald | Special stage completed flag |
$FFB1 | Emerald_count | Number of emeralds collected so far |
$FFB2-$FFB8 | Got_Emeralds_array | Array of finished special stages. Each byte represents one stage. |
$FFC0-$FFC3 | Next_Extra_life_score | Next score at which an extra life will be awarded to Player 1. |
$FFC4-$FFC7 | Next_Extra_life_score_2P | Next score at which an extra life will be awarded to Player 2. |
$FFC8-$FFC9 | Level_Has_Signpost | Level signpost flag. |
$FFD0 | Level_select_flag | Level select flag |
$FFD1 | Slow_motion_flag | Slow motion flag |
$FFD4-$FFD5 | Correct_cheat_entries | Number of correct sounds that have been played for the level select or debug codes |
$FFD6-$FFD7 | Correct_cheat_entries_2 | Same as $FFD4, except it's for the 14 continues or 7 emeralds codes |
$FFD8-$FFD9 | Two_player_mode | 2P mode flag |
$FFE1 | SFX_to_play | Play specified sound effect. Not sure how it works. |
$FFE4 | Music_to_play_2 | 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 | Demo mode flag |
$FFFA | Debug_mode_flag | Debug mode flag |
$FFFC-$FFFF | Checksum_fourcc | Set to 'init' (69 6E 69 74) once the checksum routine has run. |
Object Status Table format
The starting offset in RAM for this list is $B000. The first object is always player 1, the second is always player 2. The next few slots are reserved for certain special objects (e.g. title cards), and the slots available for general use start from $B400. Each object is allocated a block of $40 bytes. The beginning of a block is used 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 | Git label | Description | |||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
$00 | id | Object number. See the IDs at the object pointer list. Writing an ID over an empty object's memory requests that object to be loaded. | |||||||||||||||||||||||||||
$01 | render_flags | Render flags. The bitfield looks like this:
| |||||||||||||||||||||||||||
$02-$03 | art_tile | The lower 11 bits of this represent the starting art block. This is an index into an array of cells; to get the actual address, multiply by $20. Bits 14 and 13 are used to specify the default palette line the sprite uses, and bit 15 is the priority flag - if this is set, the sprite will be given high priority. | |||||||||||||||||||||||||||
$04-$07 | mappings | Object's mappings offset | |||||||||||||||||||||||||||
$08-$09 | x_pos, x_pixel | If the object is Sonic or Tails, this is the X playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0A-$0B | x_sub, y_pixel | If the object is Sonic or Tails, this is the X subpixel playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0C-$0D | y_pos | If the object is Sonic or Tails, this is the Y playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$0E-$0F | y_pixel | If the object is Sonic or Tails, this is the Y subpixel playfield coordinate. Otherwise:
| |||||||||||||||||||||||||||
$10-$11 | x_vel | X speed | |||||||||||||||||||||||||||
$12-$13 | y_vel | Y speed | |||||||||||||||||||||||||||
$14-$15 | inertia | Potential speed (inertia). | |||||||||||||||||||||||||||
$16 | y_radius | Height/2 | |||||||||||||||||||||||||||
$17 | x_radius | Width/2 | |||||||||||||||||||||||||||
$18 | priority | Sprite priority (00 = front). | |||||||||||||||||||||||||||
$19 | width_pixels | Width of the object, in pixels | |||||||||||||||||||||||||||
$1A | mapping_frame | Current animation frame to display. | |||||||||||||||||||||||||||
$1B | anim_frame | Current frame in animation script. | |||||||||||||||||||||||||||
$1C | anim | Animation number. | |||||||||||||||||||||||||||
$1D | next_anim | Restart animation flag (when $1D is not equal to $1C, animation restarts) | |||||||||||||||||||||||||||
$1E | anim_frame_duration | Animation frame duration (time until next frame). | |||||||||||||||||||||||||||
$20 | collision_flags | 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 sets the routine counter to $4, 10 is harm, and 11 seems to be a special thing for the starpole. SSSSSS is the size, lifted from a lookup table in the collision response routine. | |||||||||||||||||||||||||||
$21 | collision_property | 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 | status | Status bitfield.
Counting from the least significant bit:
| |||||||||||||||||||||||||||
$23 | respawn_index | 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 | Routine counter. | |||||||||||||||||||||||||||
$25 | routine_secondary | Second routine counter. This is used for some of the more complicated objects. | |||||||||||||||||||||||||||
$26 | angle | Angle. | |||||||||||||||||||||||||||
$27 | flip_angle | Second angle (different axis). | |||||||||||||||||||||||||||
$28 | subtype | Object subtype. For example, the current monitor selected. See the Object List above for values. Has a different meaning for Sonic and Tails. | |||||||||||||||||||||||||||
$3E-$3F | parent | Parent. Address of the object that spawned this one. Has a different meaning for orphans like Sonic and Tails. | |||||||||||||||||||||||||||
Sonic and Tails-specific variables | |||||||||||||||||||||||||||||
Offset | Hg label | Description | |||||||||||||||||||||||||||
$22 | status | Special bitfield. Counting from the least significant bit:
You can add the hex values together to use multiple settings at once. Also notice that bits 1 and 2 are used in the character object as a second routine counter. | |||||||||||||||||||||||||||
$28 | air_left | 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. | |||||||||||||||||||||||||||
$29 | flip_turned | Invert flipping flag. | |||||||||||||||||||||||||||
$2A | obj_control | Object control flag. Set to 1 if Sonic is under control of another object but can jump out (e.g. flippers), and set to $81 if Sonic is under control of another object and cannot jump out (e.g. CPZ tubes). | |||||||||||||||||||||||||||
$2B | status_secondary | Another bitfield.
| |||||||||||||||||||||||||||
$2C | flips_remaining | Number of flip revolutions remaining. | |||||||||||||||||||||||||||
$2D | flip_speed | Number of flip revolutions per frame divided by 256. | |||||||||||||||||||||||||||
$2E-$2F | move_lock | Horizontal control lock. Counts down to 0, left and right control on the ground is locked unless it's 0. Used for springs and bumpers and falling down slopes. | |||||||||||||||||||||||||||
$30-$31 | invulnerable_time | Remaining invunerability time. Starts at $0078 after Sonic is hit, and seems to decrement every frame until it reaches $0000. | |||||||||||||||||||||||||||
$32-$33 | invincibility_time | Remaining time of invincibility. | |||||||||||||||||||||||||||
$34-$35 | speedshoes_time | Remaining time of Speed Shoes. | |||||||||||||||||||||||||||
$36 | next_tilt | Angle on ground in front of sprite. | |||||||||||||||||||||||||||
$37 | tilt | Angle on ground under sprite. | |||||||||||||||||||||||||||
$38 | stick_to_convex | Stick to convex surfaces flag (unused in Sonic 2 but fully functional). | |||||||||||||||||||||||||||
$39 | spindash_flag | Set if charging a Spin Dash. | |||||||||||||||||||||||||||
$3A-$3B | spindash_counter | Spin Dash counter. Cleared when the Spin Dash 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 | jumping | Set if jumping. | |||||||||||||||||||||||||||
$3D | interact | RAM address of the last object Sonic stood on, minus $B000 and divided by $40. | |||||||||||||||||||||||||||
$3E | top_solid_bit | The bit in the 16x16 entries in the 128x128 block mappings to check for top solidity. Is either $C (for the default collision layer), or $E (for the alternate collision layer). | |||||||||||||||||||||||||||
$3F | lrb_solid_bit | The bit in the 16x16 entries in the 128x128 block mappings to check for left/right/bottom solidity. Is either $D (for the default collision layer), or $F (for the alternate collision layer). |
References