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. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,743
    93
    your mom
    So, there is this document that is found in the Sega CD documentation that lists some memory addresses in RAM for the BIOS.

    [​IMG]

    What I want to point out is "bitdevwk". That is the name of the buffer that is used by the Nemesis decompression algorithm in the BIOS. It is confirmed that the name of the Enigma decompression function is called "mapdevr", so perhaps the Nemesis decompression function might be called "bitdevr" or something like that? Just a thought. I've also seen "divdev" thrown around for PLC lists.
     
    • Like Like x 4
    • Informative Informative x 3
    • Useful Useful x 2
    • Agree Agree x 1
    • List
  2. Brainulator

    Brainulator

    Regular garden-variety member Member
    bitdev_d6 exists in Sonic Jam, so that definitely sounds right.
     
  3. Clownacy

    Clownacy

    Tech Member
    1,100
    689
    93
    It is interesting to have these names. Putting the 'dev' bit aside (whatever that means) - Nemesis is 'bit' and Enigma is 'map'. Given that Enigma is designed for plane maps, the name is appropriate. Likewise, what makes Nemesis distinct from Kosinski is that it uses a bit-stream (while Kosinski uses whole bytes), so naming it 'bit' also makes sense.
     
    • Informative Informative x 3
    • Agree Agree x 1
    • List
  4. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    Is there any more research available on Sonic 3 & Knuckles's RAM values, or is everything on the wiki page? Because both F7C3 and FAAD are unknown, and I'd like to know whey are.
     
  5. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    Anyone have an idea as to what "wrt" means? It's related to scrolling and what the community calls "DPLC".
     
  6. Brainulator

    Brainulator

    Regular garden-variety member Member
    I've taken it to be a truncation of "write".
     
  7. Kilo

    Kilo

    Deathly afraid of the YM2612 Tech Member
    1,056
    1,044
    93
    Canada
    Sonic 1 Source Code Recreation + Source Code Wiki Page
    Got more object names pulled. This time sourced from Sonic 2 J2ME.
    Drown bubbles are called dekisi_suzi (Probably just dekisi in the original source? They don't really use underscores) I tried to see if this matched with CD's Tidal Tempest symbols but nothin there. Sonic CD's Tidal Tempest ELF files have an object called plawa this is way more likely to be the drown bubbles.
    upload_2024-3-13_21-6-24.png
    And title cards are potentially haikei?
    upload_2024-3-13_21-7-21.png
    I kind of doubt it because that translates to background, and probably stems from Sonic 2's title cards utilizing the background planes, but Sonic 1 only uses sprites... Maybe? It could also be called font0 for title cards and font1 for results as these files indicate. Edit, 2NA symbols for the graphics data could also call it zone.
    upload_2024-3-13_21-16-53.png
    And finally boss explosions are called billbomb... Which I kind of also doubt was the original name. Edit, it is definitely billbomb, according to this post. That's strange... Wouldn't you expect it to be bossbomb?
    upload_2024-3-13_21-11-56.png
    While J2ME is a good source on object and file names, there are some instances of files being renamed, such as toge suddenly becoming spikes, and save becoming checkpoint in Sonic 2. So it's not a guarantee that these were in fact the original names without confirmation from 2NA's and CD's symbols.

    Also interestingly, some files in S2 J2ME have either the prefix of st_ or y_, with a lot of Metropolis files having the st_ prefix, and enemies and Wing Fortress the y_ prefix. I believe these to stand for Stitt and Yamaguchi!

    And I've started a project to try and recreate Sonic 1's source code. It's still very early on, but it's something. The HUD object (SCORE.ASM) is done for the most part.

    Final edit maybe probably not lol, I've also updated my objects sheet. Has object names from Sonic CD. And some more notes on translations.
     

    Attached Files:

    Last edited: Mar 15, 2024
    • Like Like x 4
    • Informative Informative x 1
    • List
  8. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    I've been working on compiling everything we know about labels and names used in the original source code, and putting it on the wiki: https://info.sonicretro.org/Source_code/Technical_information

    The glossary currently has no references, because most of it comes from my mind that's tainted by decompiling Sonic CD is original research. So I'm posting about it so I can use this post as a reference!

    • emie: As Devon already said earlier in the thread, this refers to Amy.
    • emy: This is short for "enemy".
    • act: The full term is "action object".
    • bye: This refers to the 'feature' of Sonic committing suicide if you leave him waiting for three minutes in Sonic CD. In other words: "I'm outta here!".
    • coli: Short for "collision".
    • marker: What we call a "lamp post" or "star post".
    • pat: Short for "pattern", the original term for a tilesheet, if I remember correctly.
    • pl: Short for "player".
    • pri: Short for "priority".
     
  9. Kilo

    Kilo

    Deathly afraid of the YM2612 Tech Member
    1,056
    1,044
    93
    Canada
    Sonic 1 Source Code Recreation + Source Code Wiki Page
    This is a good start but I have a lot of suggestions to improve this page, or rather I just need to log into my wiki account and spend a good few hours cleaning it.

    My biggest issue right now is that we know that marker isn't what the checkpoint is called, at least not in Sonic 1. From my time routing around CD's ELF files, marker is only the name for the current checkpoint count. The object itself is called save, this has been known from both Sonic 2 Nick Arcade's debug mode code:
    Code (Text):
    1. edit1tbl:
    2.     dc.w    14
    3.     dcblw    ring_act,ringpat,$26bc,0,$00        ;1:
    4.     dcblw    item_act,itempat,$0680,0,$00        ;2:
    5.     dcblw    kani_act,kanipat,$0400,0,$00        ;3:
    6.     dcblw    hachi_act,hachipat,$0444,0,$00        ;4:
    7.     dcblw    fish_act,fishpat,$0470,0,$00        ;5:
    8.     dcblw    toge_act,togepat,$04a0,0,$00        ;6:
    9.     dcblw    shima_act,shimapat2,$4000,0,$00        ;7:
    10.     dcblw    jyama_act,jyamapat,$66c0,0,$00        ;8:
    11.     dcblw    musi_act,musipat,$04e0,0,$00        ;9:
    12.     dcblw    sjump_act,sjumppat,$04a8,0,$00        ;10:
    13.     dcblw    kamere_act,kamerepat,$249b,0,$00    ;11:
    14.     dcblw    kageb_act,kagebpat,$434c,0,$00        ;12:
    15.     dcblw    save_act,savepat,$26bc,0,$01        ;13: <-- HERE
    16.     dcblw    colichg_act,colichgpat,$26bc,0,$00    ;14:
    And S1 J2ME's graphic files.
    upload_2024-3-15_12-27-56.png
    While any variables related to the checkpoint have the suffix of _s.
    Excerpt from the playsave routine, the function to save current variables into the checkpoint vars.
    Code (Text):
    1.     lui          v1,hi(plring+260)
    2.     lh           a0,lo(plring)(v1)
    3.     lui          v1,hi(plring_s+260)    ; <-- Checkpoint's saved rings
    4.     sh           a0,lo(plring_s)(v1)
    5.     lui          v1,hi(plring_f2+260)
    6.     lbu          a0,lo(plring_f2)(v1)
    7.     lui          v1,hi(lpKeepWork+260)
    8.     lw           v1,lo(lpKeepWork)(v1)
    9.     sb           a0,74(v1)
    10.     lui          v1,hi(plring_f2+260)    ; <-- Checkpoint's saved ring 1-up flags.
    11.     lbu          a0,lo(plring_f2)(v1)
    12.     lui          v1,hi(plring_f2_s+260)
    13.     sb           a0,lo(plring_f2_s)(v1)
     
  10. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    The Sonic CD source code disagrees with you. Check out PLAYSUB.C.

    The pattern variable for the checkpoint is called markerpat, all methods related to the checkpoints are prefixed with marker, and the object variable itself is called markerwk.
     
  11. Kilo

    Kilo

    Deathly afraid of the YM2612 Tech Member
    1,056
    1,044
    93
    Canada
    Sonic 1 Source Code Recreation + Source Code Wiki Page
    The conclusion I'm going to personally derive from this is that CD renamed it to marker, while it was save in S1. Perhaps it was to avoid any conflict or confusion with save data related functions?

    Edits as I continue to work on recreating the source so I don't double post:
    - I have confirmed that the GHZ rolling ball (object ID $19) is named ball. I was initially unsure as it's entry in S2NA's source code was removed, but at the top it xrefs it's mappings. Who would've known xrefs would be useful (Everyone, everyone would, I'm just dumb).
    - I got Sonic's rolling code recreated, albeit without comments of course and sound ID constants (Assuming they did use names for sound IDs)
    Code (Text):
    1. ballchk:
    2.         tst.b   mizuflag
    3.         bne.b   ?jump1
    4.         move.w  mspeed(a0),d0
    5.         bpl.b   ?jump
    6.         neg.w   d0
    7. ?jump:
    8.         cmpi.w  #$80,d0
    9.         bcs.b   ?jump1
    10.         move.b  swdata+0,d0
    11.         andi.b  #$C,d0
    12.         bne.b   ?jump1
    13.         btst.b  #1,swdata+0
    14.         bne.b   ballset
    15. ?jump1:
    16.         rts
    17.  
    18. ballset:
    19.         btst.b  #cd_ball,cddat(a0)
    20.         beq.b   ?jump
    21.         rts
    22. ?jump:
    23.         bset.b  #cd_ball,cddat(a0)
    24.         move.b  #14,sprhsize(a0)
    25.         move.b  #7,sprvsize(a0)
    26.         move.b  #2,mstno(a0)
    27.         addq.w  #5,yposi(a0)
    28.         move.w  #$BE,d0
    29.         jsr     soundset
    30.         tst.w   mspeed(a0)
    31.         bne.b   ?jump2
    32.         move.w  #$200,mspeed(a0)
    33. ?jump2:
    34.         rts
    I'm kind of considering making a new thread for my source code recreation? Perhaps when it's more substantial. But I'm pretty excited with how this is coming along!
     
    Last edited: Mar 16, 2024
    • Like Like x 2
    • Agree Agree x 1
    • List
  12. Chimes

    Chimes

    The One SSG-EG Maniac Member
    936
    644
    93
    Since I can't find any other time to mention this, here's a important tip. From time to time, Sega often mixes up which way to write Japanese in English by flipflopping whether to use Kunrei-shiki (what they usually use) or Hepburn (what we Americans use). So whenever you see something like "si", "tyan", or "zyou", it's actually pronounced "shi", "chan", and "jou".
     
    • Informative Informative x 7
    • List
  13. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    Searching for the decimal value of 0xFF80 in Sonic CD's source code, the most likely candidate for the global variable that matches this description is scra_h_posit. Could this be correct?

    (By the way, isn't it kind of awesome that we can consult (a part of) Sonic CD's source code now? :D)

    EDIT: No, scra_h_posit is plane A horizontal (x) position. The variable I'm thinking of might only exist in Sonic 3 onwards.
     
    Last edited: Mar 16, 2024
  14. Kilo

    Kilo

    Deathly afraid of the YM2612 Tech Member
    1,056
    1,044
    93
    Canada
    Sonic 1 Source Code Recreation + Source Code Wiki Page
    Correct. In fact we know all of the scroll position variables in Sonic 1's source code from CD as well as S2NA.
    scra_h_posit = v_screenposx ($FFFFF700)
    scra_v_posit = v_screenposy ($FFFFF704)
    scrb_h_posit = v_bgscreenposx ($FFFFF708)
    scrb_v_posit = v_bgscreenposy ($FFFFF70C)
    scrc_h_posit = v_bg2screenposx ($FFFFF710)
    scrc_v_posit = v_bg2screenposy ($FFFFF714)
    scrz_h_posit = v_bg3screenposx ($FFFFF718)
    scrz_v_posit = v_bg3screenposy ($FFFFF71C)
    Kind of strange that they went from c to z for the 3rd background strip, perhaps they meant z as in z axis because uber cool 3D backgrounds? I dunno.

    Edit- Saw Benoit's quoted post and that variable doesn't exist in Sonic 1, it was introduced into Sonic 2 as Camera_X_pos_coarse. To optimize off screen deletion checks.
     
    • Like Like x 1
    • Agree Agree x 1
    • List
  15. Brainulator

    Brainulator

    Regular garden-variety member Member
    I've gotten the impression sound constants were not used, given things like the 1-up sound being wrong in Sonic 2's Simon Wai and August 21 prototypes under certain conditions. At least until Sonic 3.
     
    • Informative Informative x 1
    • List
  16. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    Even better, make a Git repository!

    It'd be great if disassemblies switched to using official labels. Or at least at least added them next to their own. Because the different names means that guides for modifying them are always tailored to one.
     
  17. Kilo

    Kilo

    Deathly afraid of the YM2612 Tech Member
    1,056
    1,044
    93
    Canada
    Sonic 1 Source Code Recreation + Source Code Wiki Page
    I already have, I linked it in one of my many edits on my reply on S2 J2ME, but it seems to have gone unnoticed.
    Note that this is an attempt to actually recreate the source code, and not a reskinned disassembly, even if that is what I am using as a base. My goal's not really meant to make it buildable or have it serve as a disassembly replacement, but more of an art piece to show what it would've been like. If it can build with X68K, well then that's a nice bonus.
     
    Last edited: Mar 16, 2024
  18. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,743
    93
    your mom
    For the record, I've seen this same padding applied to the compressed Sub CPU BIOS in the Sega CD boot ROM.
     
  19. BenoitRen

    BenoitRen

    Tech Member
    795
    392
    63
    I've just ported the random function from S&KC, and now I'm wondering: is ranum (random number) supposed to be signed? It's signed in Sonic CD, but at the same time it seems to have some hacks to prevent it from being signed. This is the Sonic CD version of the function:
    Code (Text):
    1. int random() {
    2.   int_union lD0, lD1;
    3.   unsigned short w;
    4.  
    5.   lD1.l = ranum;
    6.   if (ranum == 0) lD1.l = 711800410;
    7.   lD0.l = lD1.l;
    8.   if (lD1.l < 0) {
    9.     lD1.l *= 4;
    10.     lD1.l |= -2147483648;
    11.   }
    12.   else {
    13.     lD1.l *= 4;
    14.   }
    15.   lD1.l += lD0.l;
    16.   if (lD1.l < 0) {
    17.     lD1.l *= 8;
    18.     lD1.l |= -2147483648;
    19.   }
    20.   else {
    21.     lD1.l *= 8;
    22.   }
    23.   lD1.l += lD0.l;
    24.   lD0.w.l += lD1.w.l;
    25.  
    26.   w = lD1.w.h;
    27.   lD1.w.h = lD1.w.l;
    28.   lD1.w.l = w;
    29.  
    30.   lD0.w.l += lD1.w.l;
    31.   lD1.w.l = lD0.w.l;
    32.  
    33.   w = lD1.w.h;
    34.   lD1.w.h = lD1.w.l;
    35.   lD1.w.l = w;
    36.  
    37.   ranum = lD1.l;
    38.   return lD0.l;
    39. }
    The S&KC version is more concise, but in order to be portable I couldn't use shifting and bit-masking (the macros hide the multiplications and divisions):
    Code (Text):
    1. long random() {
    2.   long d1 = ranum;
    3.   if (d1 == 0) {
    4.     d1 = 711800411;
    5.   }
    6.   long d0 = d1;
    7.   d1 *= 4;
    8.   d1 += d0;
    9.   d1 *= 8;
    10.   d1 += d0;
    11.   d0 = LONG_HIGH(d0) + LONG_LOW(d1);
    12.   d1 = SHORT_TO_LONG_HIGH(LONG_LOW(d1)) + LONG_HIGH_TO_SHORT(d1); // rotate
    13.   // % 65536 is necessary to ensure there is no overflow to the upper 16 bits.
    14.   d0 = LONG_HIGH(d0) + (LONG_LOW(d0) + LONG_LOW(d1)) % 65536;
    15.   d1 = LONG_HIGH(d1) + LONG_LOW(d0);
    16.   d1 = SHORT_TO_LONG_HIGH(LONG_LOW(d1)) + LONG_HIGH_TO_SHORT(d1); // rotate
    17.   ranum = d1;
    18.   return d0;
    19. }
    It'd simplify things if I could make ranum unsigned.
     
  20. Devon

    Devon

    La mer va embrassé moi et délivré moi lakay. Tech Member
    1,425
    1,743
    93
    your mom
    The original function doesn't really treat it as either signed or unsigned. It just takes whatever is in the seed value and mangles it around and returns the result of that. It's up to the programmer to work with the return value however they need it.

    Code (ASM):
    1. RandomNumber:
    2.         move.l    (v_random).w,d1
    3.         bne.s     .scramble        ; If the seed is initialized, branch
    4.         move.l    #$2A6D365A,d1    ; If it's not, initialize it
    5.  
    6. .scramble:
    7.         move.l    d1,d0
    8.         asl.l     #2,d1
    9.         add.l     d0,d1
    10.         asl.l     #3,d1
    11.         add.l     d0,d1
    12.         move.w    d1,d0
    13.         swap      d1
    14.         add.w     d1,d0
    15.         move.w    d0,d1
    16.         swap      d1
    17.         move.l    d1,(v_random).w
    18.         rts