don't click here

Everything That I Know About Sonic the Hedgehog's Source Code

Discussion in 'General Sonic Discussion' started by Clownacy, Mar 30, 2022.

  1. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    It's entirely possible that the original code used labels like scorewk and bariawk as constants to address actwk slots, but constants don't make their way into DWARF debug information. :(

    I've been wanting to propose labels for actflg bits, just like we did for cddat, but after looking at the information we have it looks like not a single one was 'leaked'.
     
    • Agree Agree x 2
    • Like Like x 1
    • List
  2. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    Checking Sonic CD's source code and the wiki, I think editmode is the value at $FE08-$FE09, which is described as "Object placement flag (Set if debug mode is being used)".

    Sonic 3 seems to have it at the exact same spot, but there it contains two values:
    • Object placement mode routine counter.
    • Object placement mode flag (0 - normal, 1 - object placement, 2 - frame cycling)
    What trips me up is that, according to Sonic CD, the high byte is set when debug/edit mode is activated. As the Mega Drive is big endian, that means the byte at $FE08. But it's the byte at $FE09 that seems to match that description in Sonic 3. It's possible they changed it, but I wanted to point it out just to be sure.
     
    • Informative Informative x 2
    • List
  3. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    We should probably start thinking about files here as I start working on my source code recreation... There's a bit of conflicting info to deal with. While Sonic 2 Simon Wai has a large chunk of LZEXE data left over as a huge dc.b array, that just seems... Impractical. It's one thing with mapping data, it's another with huge tilesets, level data, and collision arrays. And J2ME seems to align with that, as chunks are files with .bmd extensions (At least when uncompressed), and collision arrays are files with .scd and .blt extensions. But on the other hand in the Feb90 footage, there's very little in the directory we see, with it consisting largely of assembly files and output files, while in fcol3.asm we see a reference to scdtblwk, which is a separate file in J2ME. I'm not sure what to think or do really. Do we dc.b everything? Only make arrays for compressed data since the Simon Wai data is LZEXE compressed and the J2ME data is uncompressed? Take a disasm route and assume most graphical data is in it's own file anyways??? I'd like to hear thoughts.

    On a side note I've settled on object ID $48 being btama. I was kind of torn on this since I had also seen bball and bossball thrown around thanks to S2NA's symbols (Granted bball is bballcg, and GHZ's boss just uses ballcg, since it's the rolling ball's graphics originally) and S1J2ME's graphics. But while browsing S2NA's symbols I found a label called btamakusari which, kusari means chain which is absolutely GHZ1's boss' wrecking ball.
     
    Last edited: Sep 7, 2024
    • Informative Informative x 1
    • List
  4. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    I've read the post multiple times in the past few days, but I don't have many useful thoughts to add.

    Small data chunks like mappings were almost definitely placed in the files themselves. I say this because of the debug data found in Sonic & Knuckles Collection. It seems to mark routines and pieces of data as private to the current translation unit. This parallels Sonic CD PC marking methods and data private using the static keyword. Of course, this same port also stores mappings in separate files.

    I wouldn't put too much stock in the February 1990 footage, because they were in the middle of development and things could have changed several times before they settled on a final structure.

    But then there's the LZEXE chunk found in Simon Wai. Maybe they preferred to store the data that way for inclusion or linking with other assembly files? I have no knowledge of how assembly projects are structured, so I can't even begin to make an educated guess.
     
    • Informative Informative x 2
    • List
  5. Brainulator

    Brainulator

    Regular garden-variety member Member
    I've hypothesized that all (or at least most) data was input as dc.b's, on the basis of that file you mentioned as well as the sound driver source code doing this too for things like the drum samples. However, I have nothing really to concretely back this up.

    As for btama... (checks Sonic 2 Nick Arcade) yup, that checks out!
     
  6. Devon

    Devon

    Please do not contact me, overwhelmed with stuff Tech Member
    1,526
    1,883
    93
    your mom
    So, I looked into LZEXE, and I managed to retrieve the unpacked decompressor and compressor binaries. They were both compressed in LZEXE/Kosinski and decompressed just fine with FW-KENSC. The binary loader decompresses to the start of the first memory segment it chooses to loaded to, so when reverse engineering, you should just be able to leave the origin address as 0. The entry point for LZEXE is 0x1668 and the entry point for UPACKEXE is 0xFEF. Upon entry, DS and ES will be the same, but different from CS.

    What I want to note is that the decompressor/compressor binary loaders, of course, take into account memory segmentation, where 1 segment is 0x10000 bytes. Interestingly, the length of the compressed binary for the loader is divided by 0x10, and the compressed binaries are also padded out to the nearest 0x10 byte boundary... curious, eh?
     
    Last edited: Sep 12, 2024
  7. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    So my signature continues to hold up. I was doing my own transcription of the Feb90 fcol routine, just in case the earlier attempts were off. And yeah. If I had actually read it, then I would have realized that cd_right is in fact the horizontal flip flag, and not the push flag:
    Code (Text):
    1.         moveq    #0,d0                    ; Clear d0 for work.
    2.         move.b    sprhs(a0),d0            ; Get sprite's horizontal size.
    3.         tst.w    xspeed(a0)                ; Is the sprite moving right?
    4.         bpl.b    ?jump                    ; If so, branch.
    5. *        btst.b    #cd_right,cddat(a0)        ; Is the sprite facing right? Commented out because they only needed to check if it's moving right
    6. *        beq.b    ?jump                    ; If so, branch.
    7.         neg.w    d0                        ; Otherwise invert horizontal size.
    Boowomp.

    So I conclude it's usage was such:
    Code (Text):
    1. cd_right        equ 0
    2. cd_left            equ 0
    3.  
    4. cd_up            equ 1
    5. cd_down            equ 1
    6.  
    7. * Right check
    8.         btst.b    #cd_right,cddat(a0)        * Is sprite facing right?
    9.         beq.b    ?jump                    * If so, branch
    10.  
    11. * Left check
    12.         btst.b    #cd_left,cddat(a0)        * Is sprite facing left?
    13.         bne.b    ?jump                    * If so, branch
    14.  
    15. * Upright check
    16.         btst.b    #cd_up,cddat(a0)        * Is sprite upright?
    17.         beq.b    ?jump                    * If so, branch
    18.  
    19. * Flipped check
    20.         btst.b    #cd_down,cddat(a0)        * Is sprite flipped upside down?
    21.         bne.b    ?jump                    * If so, branch
     
    Last edited: Sep 12, 2024
    • Informative Informative x 1
    • List
  8. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    That seems counter-intuitive, because you'd have to remember which condition (beq, bne) to use with which constant, as you'd have multiple of them pointing to the same bit.
     
  9. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    Counter-intuitive yes. But it checks out and we actually see that exact usage at ?down2 in the Feb90 code.
     
  10. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    While I took a sick day off from work, I decided to be productive and started work on refactoring the wiki's page on the source code. I hope this is a bit more organized and pleasant to look at. It still needs work to be done, but I hope what I laid out gives an idea of what I'm going for for any other contributors.
     
  11. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    The refactored page has no references. :(
     
  12. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    Like I said, I'm still working on it!
    I do want to find a better way to do references though. The old page ended up having 100 little markers or whatever you call em, cluttering the references section and I don't want that to happen again.

    Edit, well until I figure out a more appealing way to do references, I have gone and done it the standard way. And added some more info.
     
    Last edited: Sep 19, 2024
  13. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    Did a lot of work on the wiki page and my recreation today.
    Here's some of the findings
    • Object 4A, the beta special stage warp effect, seems to be called "warp" sourced from S2NA's symbols with a label called "warppat". Seems to be nulled out with some other mapping addresses that originate from Sonic 1. Such as zone (Title cards, removed in S2NA), sprev the Special Stage R block, sp1uppat the Special Stage 1 Up block.
    • Object 34, title cards, as mentioned above is zone. This one I was bit skeptical on for the longest time because while I had seen zonecg, it's placement in the symbols list didn't really line up with where it was in Sonic 1. And it happened to be near zone00cg, zone08cg, zone1cg, so I couldn't trust it to not be level graphics. But having zonepat, a mappings address to confirm it's an object, I'm confident in saying it's the title cards.
    • Object 3F. Boss explosions, This one I was far too quick to write off as "billbomb", not realizing this is Sonic 2's naming scheme, along with bbat and bfish. These are named after Bill Willis, an assistant programmer. I had gotten the name from Sonic 2 J2ME. So I'll have to go back to the drawing board in finding a name for this object.
    That's a net gain of 1 object name.

    Next has to do with the sound driver. This has been a bit odd for me to work with since I'm already not familiar with the Mega Drive's sound hardware, and the Sound Source code we do have is version 1.1 from September 1990, well after Sonic 1 had started development. So the driver is already different from what Sonic is using, but then Sonic also modified the sound driver to add features like music speed up. Regardless, what I wanted to talk about is not important to that aspect. Sound D0 is kind of stands out in the driver, it's the sound effect used for rushing water, i.e waterfalls and wind tunnels. A lot of disassemblies either just refer to it as "D0 type" or "Special type", but sound source's code seems to have a particular use in mind for these IDs of D0 and above, and that's "back" sound effects. I assume background, or rather, ambient sound effects, and is why they support screen-space panning. It just so happened to look strange in the context of Sonic 1 because it only had 1 of these sound effects, while the sample disks have multiple.
     
    • Informative Informative x 1
    • List
  14. Devon

    Devon

    Please do not contact me, overwhelmed with stuff Tech Member
    1,526
    1,883
    93
    your mom
    I do wanna mention that in Sonic CD, the source file that contains the title card code is called "ZONE" (the object itself is called "title" though), with the zone specific data files being called "ZONETBL[n]".
     
    • Like Like x 2
    • Informative Informative x 1
    • List
  15. BenoitRen

    BenoitRen

    Tech Member
    936
    573
    93
    I'd like to know how they organised data for Sonic J2ME. Do they have separate files for graphics? What about mapping data?

    Sonic CD seems to have all graphics packed together in one file per zone. For mapping data, they're in the same file as the code most of the time.
     
  16. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    J2ME has separate files for most graphics yes. Sometimes multiple objects get grouped together depending on context, i.e fire.png contains the graphics for both fire (0x14), and kazari (0x62)'s fireball. Or hashi.png having both the sprites for hashi (0x11) and bgspr (0x1C) because they compose Green Hill's bridge.
    As for mapping, J2ME isn't tile based so you just draw a sprite by cropping a rectangle from a sheet. And unfortunately it seems said cropping values are hard coded per actor, which is a massive pain for modding purposes, especially since it's all obfuscated.
     
    • Informative Informative x 1
    • List
  17. Devon

    Devon

    Please do not contact me, overwhelmed with stuff Tech Member
    1,526
    1,883
    93
    your mom
    Okay, so this is my guess for what "div" means here. Maybe it means "divide", since the main function is to effectively split graphics data into chunks that are loaded gradually as the game plays, as to avoid freezing the entire game just to load new graphics.
     
    Last edited: Dec 31, 2024
  18. Devon

    Devon

    Please do not contact me, overwhelmed with stuff Tech Member
    1,526
    1,883
    93
    your mom
    So, those unused variables related to camera scrolling in Sonic 1 and Sonic CD. I have their official names right here, taken from Sonic Gems Collection:
    • scrar_no = 0xFFF730 / v_unused1
      • Set to first word in stage's boundary data, which is always 4, but could be changed on a per stage basis
    • scra_h_keep = 0xFFF732 / v_limitleft3
      • Set to the initial stage's left boundary + 0x240
    • scrh_flag = 0xFFF740 / v_unused
      • Cleared on initialization
    • scrv_flag = 0xFFF741 / v_unused
      • Cleared on initialization
    • scr_die = 0xFFF746 / v_unused
      • Cleared on initialization
    • scr_timer = 0xFFF748 / v_unused1
      • Cleared on initialization
    I think it's also worth reminding that scra_v_line (0xFFF73E / v_lookshift), the variable that tracks the camera's vertical focal point (for looking up and down), is set to the last word in the stage's boundary data, which is always 0x60, but could be changed on a per stage basis. Makes me wonder what they were planning...
     
    Last edited: Jan 1, 2025
  19. Kilo

    Kilo

    The Scatterbrained Hacker Tech Member
    1,296
    1,217
    93
    Canada
    Sonic 1 Source Code Recration
    Based on the patterns we've seen so far, scrar_no would seem to be short for scroll A routine number. Which would likely mean it's incremented in words. Weird that every stage starts at 4. Perhaps from an early implementation of level events?
     
  20. Devon

    Devon

    Please do not contact me, overwhelmed with stuff Tech Member
    1,526
    1,883
    93
    your mom
    I took a look at the prototype Sonic 1 code, and these 2 do have some functionality. scrh_flag is set if the left and right stage boundaries are the same, and scrv_flag is set if the top and bottom stage boundaries are the same.

    [​IMG]

    While the stage is running, they get checked each frame. If scrh_flag is set, it jumps to loc_4258, and then comes back around to check scrv_flag, which jumps to loc_4276 if set, and then comes back around again to continue the scrolling function.

    [​IMG]

    loc_4258 simply just slowly scrolls the camera towards the left boundary's position.

    [​IMG]

    loc_4276 does the same thing, but vertically, and with the top boundary (plus 0x20, I assume this is might have been related to old HUD code that displayed on the top 32 pixels of the screen? There is unused code that draws a chain of life icons on the window plane, but it does it on the bottom 32 pixels of the screen instead...).

    [​IMG]

    Perhaps this is some sort of auto-scroll functionality that ended up getting removed in the final game? Interesting how it can basically do that for each individual axis, and not just none or both at the same time. And no, this code was not reused for later games that do have auto-scrolling.
     
    Last edited: Jan 2, 2025
    • Like Like x 3
    • Informative Informative x 1
    • List