As you know, objects in Sonic 1 are each assigned $40 bytes of memory in the object status table (OST) when they're loaded. Bytes 0-$28 have fixed uses (as described here), although not every object sticks to it. The remaining bytes $29-$3f are free for the object to use in any way. I wanted to rearrange how the OST is used, in particular to expand the number of fixed bytes, so I thought it would be helpful to know exactly which bytes are used by every object. This is a diagram showing that information: Bytes $29-$2f are only used by a handful of objects, so if you want more fixed bytes that's where I'd start. Teal bytes represent child object addresses, which vary in number in some cases (bridges, swinging platforms) but not in others (caterkiller segments). The diagram may not be 100% accurate as I probably made 1 or 2 mistakes. EDIT: Out of date. Use this instead: https://github.com/cvghivebrain/s1disasm/blob/main/Notes/Objects and memory usage.pdf
This is very useful information. It is often hard to tell which object uses which bytes in a safe and fast manner. We should have a diagram like this for S2 and S3K. Thank you Hivebrain.
It seems like the bytes with documented uses are broken down into two groups: those whose purpose is fixed due to being used by the object system itself, and those whose purpose is conveyed by using particular subroutines (e.g. objects which never call the collision routines can use the collision bytes as scratch space; likewise for objects which don't animate and the animation bytes). Documenting which is which would be helpful as an extension of this already impressive work.
If what I am seeing in this chart is correct... there is a word-sized entry ($0E and $0F) that is only used by the SonicPlayer object, which isn't using $2A or $2B. So if that word-sized entry gets moved... that frees up an entire global word-sized entry in the OST, which would be needed for things like porting the Sonic 3K object manager over... HMMMMMM...
I can use a different colour for bytes which are used for something other than their intended purpose. I think there might be a couple of objects that use animation bytes as general timers. That's true, but $e-$f are the y subpixel value, which is probably assumed to be next to the y value. Moving it may require more work than changing a single equ. A better option would be bytes $14-$15 (inertia), which are used by 5 objects, but relocating them would be pretty straightforward. Also I'm thinking animations only really need three bytes: animation number, animation frame and time until next frame. Optimising the code would save another 2 bytes.
I combed through all the objects again, and I'd actually made a lot of mistakes, so here's an up to date chart: https://github.com/cvghivebrain/s1disasm/blob/main/Notes/Objects and memory usage.pdf I added more colours along with a key at the bottom of the page. Again, I can't guarantee this is 100% accurate. The Final Zone boss appears to have variables that aren't functional, meaning when I disabled them it continued to behave normally. It's a rather complicated object that I found somewhat incomprehensible, so I haven't marked any of it as orange yet.
I was actually thinking of working on something like this, only making the actual cell contents list out how each byte is used (which would result in some redundancy with common variables, given their descriptions in a U.S. patent). Interesting how there's no object that makes use of all $40 bytes...
OSTs are located in $D000-$EFFF in RAM, but only those in $D800+ are used by the usual object loading routine and can interact with Sonic. The first $20 OST spots are used by Sonic, shields, the HUD and so on. I wanted to know exactly which ones are used so I can safely add things like spindash dust without worrying about conflicts. Code (Text): v_ost_all: equ $FFFFD000 ; object variable space ($40 bytes per object) ($2000 bytes) v_ost_player: equ v_ost_all ; object variable space for Sonic ($40 bytes) ; Title screen and intro v_ost_titlesonic: equ v_ost_all+(sizeof_ost*1) ; title screen Sonic v_ost_psb: equ v_ost_all+(sizeof_ost*2) ; title screen "Press Start Button" v_ost_tm: equ v_ost_all+(sizeof_ost*3) ; title screen "TM" v_ost_titlemask: equ v_ost_all+(sizeof_ost*4) ; title screen sprite mask ; Intro/credits v_ost_credits: equ v_ost_all+(sizeof_ost*2) ; "Sonic Team Presents" and credits text ; Try again v_ost_endeggman: equ v_ost_all+(sizeof_ost*2) ; ending/"Try Again" Eggman v_ost_tryagain: equ v_ost_all+(sizeof_ost*3) ; "Try Again" text v_ost_tryag_emeralds: equ v_ost_all+(sizeof_ost*$20) ; "Try Again" chaos emeralds ; Continue v_ost_cont_text: equ v_ost_all+(sizeof_ost*1) ; continue screen text v_ost_cont_oval: equ v_ost_all+(sizeof_ost*2) ; continue screen oval v_ost_cont_minisonic: equ v_ost_all+(sizeof_ost*3) ; continue screen mini Sonics ; Level - no interaction with Sonic v_ost_hud: equ v_ost_all+(sizeof_ost*1) ; HUD v_ost_titlecard1: equ v_ost_all+(sizeof_ost*2) ; title card - zone name v_ost_titlecard2: equ v_ost_all+(sizeof_ost*3) ; title card - "zone" v_ost_titlecard3: equ v_ost_all+(sizeof_ost*4) ; title card - "act" 1/2/3 v_ost_titlecard4: equ v_ost_all+(sizeof_ost*5) ; title card - oval v_ost_shield: equ v_ost_all+(sizeof_ost*6) ; shield v_ost_stars1: equ v_ost_all+(sizeof_ost*8) ; invincibility stars v_ost_stars2: equ v_ost_all+(sizeof_ost*9) ; invincibility stars v_ost_stars3: equ v_ost_all+(sizeof_ost*$A) ; invincibility stars v_ost_stars4: equ v_ost_all+(sizeof_ost*$B) ; invincibility stars v_ost_splash: equ v_ost_all+(sizeof_ost*$C) ; splash v_ost_bubble: equ v_ost_all+(sizeof_ost*$D) ; bubble from Sonic's mouth v_ost_end_emeralds: equ v_ost_all+(sizeof_ost*$10) ; ending chaos emeralds v_ost_gotthrough1: equ v_ost_all+(sizeof_ost*$17) ; got through act - "Sonic has" v_ost_gotthrough2: equ v_ost_all+(sizeof_ost*$18) ; got through act - "passed" v_ost_gotthrough3: equ v_ost_all+(sizeof_ost*$19) ; got through act - "act" 1/2/3 v_ost_gotthrough4: equ v_ost_all+(sizeof_ost*$1A) ; got through act - score v_ost_gotthrough5: equ v_ost_all+(sizeof_ost*$1B) ; got through act - time bonus v_ost_gotthrough6: equ v_ost_all+(sizeof_ost*$1C) ; got through act - ring bonus v_ost_gotthrough7: equ v_ost_all+(sizeof_ost*$1D) ; got through act - oval v_ost_watersurface1: equ v_ost_all+(sizeof_ost*$1E) ; LZ water surface v_ost_watersurface2: equ v_ost_all+(sizeof_ost*$1F) ; LZ water surface ; Special stage results v_ost_ssresult1: equ v_ost_all+(sizeof_ost*$17) ; special stage results screen v_ost_ssresult2: equ v_ost_all+(sizeof_ost*$18) ; special stage results screen v_ost_ssresult3: equ v_ost_all+(sizeof_ost*$19) ; special stage results screen v_ost_ssresult4: equ v_ost_all+(sizeof_ost*$1A) ; special stage results screen v_ost_ssresult5: equ v_ost_all+(sizeof_ost*$1B) ; special stage results screen v_ost_ssres_emeralds: equ v_ost_all+(sizeof_ost*$20) ; special stage results screen chaos emeralds ; Level - can interact with Sonic v_ost_level_obj: equ v_ost_all+(sizeof_ost*$20) ; level object variable space ($1800 bytes) The ones that seem to be completely unused are 7, $E-$F and $16. $10-$15 are only used in the ending so those are pretty safe too.
Minor correction: Those "unused" values for the wrecking ball are used; $38-$3B are used for spawning, while $3E-$3F are used for its motion.
They're being written to, but I can't see where $38-$3B are being read. You're right though, I tried disabling those bytes and it did break the object. $3E-$3F is handled by a separate routine which is why I missed that.
Something I haven't seen clarified is how the angle variable, $26(a0), relates to what the floor looks like. So here it is. The angle is the same no matter which direction Sonic is going.
Just to clarify (or confuse), the 00 is actually FF in practice. If someone wants to explain to me why, I would love to hear it. Despite working many times with that code, I never fully understood why (especially since the angle is 7 bits of precision, not 8).
Bit 0 of the angle of a level block is a "snap" angle bit, if set, it causes Sonic's angle to snap to the nearest 90 degree angle (or provided angle which is usually one of the four 90 degree angles). This is often used with $FF to signify a block to be treated as a wall that can only be landed on from the top, attempting to land on it from a side (i.e. jumping at a wall) won't cause Sonic to land on it and start walking. Bit 1 has a reserved purpose, but it's never used so we can't quite work out what it would have been for. But all angles tend to be a multiple of 4, except for $FF for square 90 degree floor/walls.