don't click here

Sonic 1 objects and their memory usage

Discussion in 'Engineering & Reverse Engineering' started by Hivebrain, Aug 15, 2021.

  1. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    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:

    Sonic 1 objects and memory usage - Sheet1.png

    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
     
    Last edited: Nov 17, 2021
    • Like Like x 5
    • Informative Informative x 1
    • List
  2. Sonic Hachelle-Bee

    Sonic Hachelle-Bee

    Taking a Sand Shower Tech Member
    806
    200
    43
    Lyon, France
    Sonic 2 Long Version
    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.
     
  3. Quickman

    Quickman

    be attitude for gains Tech Member
    5,595
    18
    18
    :x
    omg porjcet
    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.
     
  4. Techokami

    Techokami

    For use only on NTSC Genesis systems Researcher
    1,373
    81
    28
    HoleNet!
    Sonic Worlds Next
    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...
     
  5. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    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.
     
  6. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    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.
     
    Last edited: Nov 17, 2021
    • Informative Informative x 4
    • Like Like x 3
    • List
  7. Brainulator

    Brainulator

    Regular garden-variety member Member
    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...
     
  8. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    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):
    1.  
    2. v_ost_all:       equ $FFFFD000 ; object variable space ($40 bytes per object) ($2000 bytes)
    3.    v_ost_player:       equ v_ost_all ; object variable space for Sonic ($40 bytes)
    4.    ; Title screen and intro
    5.    v_ost_titlesonic:   equ v_ost_all+(sizeof_ost*1) ; title screen Sonic
    6.    v_ost_psb:       equ v_ost_all+(sizeof_ost*2) ; title screen "Press Start Button"
    7.    v_ost_tm:       equ v_ost_all+(sizeof_ost*3) ; title screen "TM"
    8.    v_ost_titlemask:   equ v_ost_all+(sizeof_ost*4) ; title screen sprite mask
    9.    ; Intro/credits
    10.    v_ost_credits:       equ v_ost_all+(sizeof_ost*2) ; "Sonic Team Presents" and credits text
    11.    ; Try again
    12.    v_ost_endeggman:   equ v_ost_all+(sizeof_ost*2) ; ending/"Try Again" Eggman
    13.    v_ost_tryagain:       equ v_ost_all+(sizeof_ost*3) ; "Try Again" text
    14.    v_ost_tryag_emeralds:   equ v_ost_all+(sizeof_ost*$20) ; "Try Again" chaos emeralds
    15.    ; Continue
    16.    v_ost_cont_text:   equ v_ost_all+(sizeof_ost*1) ; continue screen text
    17.    v_ost_cont_oval:   equ v_ost_all+(sizeof_ost*2) ; continue screen oval
    18.    v_ost_cont_minisonic:   equ v_ost_all+(sizeof_ost*3) ; continue screen mini Sonics
    19.    ; Level - no interaction with Sonic
    20.    v_ost_hud:       equ v_ost_all+(sizeof_ost*1) ; HUD
    21.    v_ost_titlecard1:   equ v_ost_all+(sizeof_ost*2) ; title card - zone name
    22.    v_ost_titlecard2:   equ v_ost_all+(sizeof_ost*3) ; title card - "zone"
    23.    v_ost_titlecard3:   equ v_ost_all+(sizeof_ost*4) ; title card - "act" 1/2/3
    24.    v_ost_titlecard4:   equ v_ost_all+(sizeof_ost*5) ; title card - oval
    25.    v_ost_shield:       equ v_ost_all+(sizeof_ost*6) ; shield
    26.    v_ost_stars1:       equ v_ost_all+(sizeof_ost*8) ; invincibility stars
    27.    v_ost_stars2:       equ v_ost_all+(sizeof_ost*9) ; invincibility stars
    28.    v_ost_stars3:       equ v_ost_all+(sizeof_ost*$A) ; invincibility stars
    29.    v_ost_stars4:       equ v_ost_all+(sizeof_ost*$B) ; invincibility stars
    30.    v_ost_splash:       equ v_ost_all+(sizeof_ost*$C) ; splash
    31.    v_ost_bubble:       equ v_ost_all+(sizeof_ost*$D) ; bubble from Sonic's mouth
    32.    v_ost_end_emeralds:   equ v_ost_all+(sizeof_ost*$10) ; ending chaos emeralds
    33.    v_ost_gotthrough1:   equ v_ost_all+(sizeof_ost*$17) ; got through act - "Sonic has"
    34.    v_ost_gotthrough2:   equ v_ost_all+(sizeof_ost*$18) ; got through act - "passed"
    35.    v_ost_gotthrough3:   equ v_ost_all+(sizeof_ost*$19) ; got through act - "act" 1/2/3
    36.    v_ost_gotthrough4:   equ v_ost_all+(sizeof_ost*$1A) ; got through act - score
    37.    v_ost_gotthrough5:   equ v_ost_all+(sizeof_ost*$1B) ; got through act - time bonus
    38.    v_ost_gotthrough6:   equ v_ost_all+(sizeof_ost*$1C) ; got through act - ring bonus
    39.    v_ost_gotthrough7:   equ v_ost_all+(sizeof_ost*$1D) ; got through act - oval
    40.    v_ost_watersurface1:   equ v_ost_all+(sizeof_ost*$1E) ; LZ water surface
    41.    v_ost_watersurface2:   equ v_ost_all+(sizeof_ost*$1F) ; LZ water surface
    42.    ; Special stage results
    43.    v_ost_ssresult1:   equ v_ost_all+(sizeof_ost*$17) ; special stage results screen
    44.    v_ost_ssresult2:   equ v_ost_all+(sizeof_ost*$18) ; special stage results screen
    45.    v_ost_ssresult3:   equ v_ost_all+(sizeof_ost*$19) ; special stage results screen
    46.    v_ost_ssresult4:   equ v_ost_all+(sizeof_ost*$1A) ; special stage results screen
    47.    v_ost_ssresult5:   equ v_ost_all+(sizeof_ost*$1B) ; special stage results screen
    48.    v_ost_ssres_emeralds:   equ v_ost_all+(sizeof_ost*$20) ; special stage results screen chaos emeralds
    49.    ; Level - can interact with Sonic
    50.    v_ost_level_obj:   equ v_ost_all+(sizeof_ost*$20) ; level object variable space ($1800 bytes)
    51.  
    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.
     
    Last edited: Nov 3, 2021
    • Informative Informative x 2
    • List
  9. 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.
     
    • Informative Informative x 1
    • List
  10. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    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.
     
    • Informative Informative x 1
    • List
  11. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    Minor correction: slots $C and $D are used for LZ splashes and countdown numbers/bubbles.
     
    • Informative Informative x 1
    • List
  12. Hivebrain

    Hivebrain

    Administrator
    3,047
    154
    43
    53.4N, 1.5W
    Github
    Angles.png
    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.
     
    • Informative Informative x 2
    • List
  13. saxman

    saxman

    Oldbie Tech Member
    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).
     
  14. MarkeyJester

    MarkeyJester

    Original, No substitute Resident Jester
    2,192
    405
    63
    Japan
    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.