don't click here

Some changes/fixes for Sonic 1

Discussion in 'Engineering & Reverse Engineering' started by RetroKoH, Sep 4, 2012.

  1. Brainulator


    Regular garden-variety member Member
  2. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    Specified that both shouldn't be too hard.

    Of note, you could also remove the checks between music/sfx and sfx/specsfx by changing sfx__First to bgm__Last+1, and spec__First to sfx__Last+1. I do plan on updating other guides (Different Songs in Sonic 1) with other, less hackish implementations.
    Last edited: Oct 18, 2021
  3. nineko


    I am the Holy Cat Tech Member
  4. LuigiXHero


    Sonic 1 Character Pak
    Sonic 1 has a bug where if you pause the game on a certain frame the water is shifted over unintentionally causing a gap at the left side, this is in all revision since it's also in all revisions of Sonic 2 (to fix it there go here):

    So in Git Sonic 1 or in Hivebrain 2021 the code is as follows in _incOBJ/1B Water Surface.asm
    Code (Text):
    1. Surf_Action:    ; Routine 2
    2.         move.w    (v_screenposx).w,d1
    3.         andi.w    #$FFE0,d1
    4.         add.w    surf_origX(a0),d1
    5.         btst    #0,(v_framebyte).w
    6.         beq.s    @even        ; branch on even frames
    7.         addi.w    #$20,d1
    9.     @even:
    What we need to do is add a press start check between "add.w surf_origX(a0),d1" and btst #0,(v_framebyte).w like so:
    Code (Text):
    1. Surf_Action:    ; Routine 2
    2.         move.w    (v_screenposx).w,d1
    3.         andi.w    #$FFE0,d1
    4.         add.w    surf_origX(a0),d1
    5.         btst    #bitStart,(v_jpadpress1).w ; is Start button pressed?
    6.         bne.s    @even    ; if yes, branch
    7.         btst    #0,(v_framebyte).w
    8.         beq.s    @even        ; branch on even frames
    9.         addi.w    #$20,d1
    11.     @even:
    This will fix the gap.
    For the old hivebrain disasm go to Obj1B_Action and do the same thing but worse:
    Code (Text):
    1. Obj1B_Action:                ; XREF: Obj1B_Index
    2.         move.w    ($FFFFF700).w,d1
    3.         andi.w    #$FFE0,d1
    4.         add.w    $30(a0),d1
    5.         btst    #7,($FFFFF605).w ; is Start button pressed?
    6.         bne.s    loc_11114    ; if yes, branch
    7.         btst    #0,($FFFFFE05).w
    8.         beq.s    loc_11114
    9.         addi.w    #$20,d1
    11. loc_11114:
    and there you go. Enjoy the finer water surfaces in life.
  5. EpsilionDubwool


    Be a boss-man and come to my big and tall man shop Member
    Fix some graphical bubble glitch when drowning in Sonic 1

    I want you to take a look at this image:


    Now see where I circled the issue in pink, you may believe it's intentional, but that little graphic hangs there when you drown, which is quite unlogical. Looking at the code in a standard Hivebrain disassembly appals me:

    Code (Text):
    1. Obj0A_ChkWater:                ; XREF: Obj0A_Index
    2.         move.w    ($FFFFF646).w,d0
    3.         cmp.w    $C(a0),d0    ; has bubble reached the water surface?
    4.         bcs.s    Obj0A_Wobble    ; if not, branch
    5.         move.b    #6,$24(a0)
    6.         addq.b    #7,$1C(a0)
    7.         cmpi.b    #$D,$1C(a0) ; DW: look here
    8.         beq.s    Obj0A_Display ; DW: here
    9.         bra.s    Obj0A_Display; DW: and here

    The issue is they set a check to animation ID D for it to branch instantly to Obj0A_Display, but at the same time, you'll still be branching there, nevertheless making the code pretty redundant if you ask me. So if we check out what animation ID D does in obj0A:

    Code (Text):
    1. byte_14148:    dc.b $E, $FC

    It sets a frame that blanks out the art from loading when you drown to 0. To fix it, we would need to set a check, so the animation ID loads in so in Obj0A_ChkWater (or Drown_ChkWater for GitHub/Hivebrain 2021 users), replace:

    Code (Text):
    1.         beq.s    Obj0A_Display ; that would be "bcs.s    Drown_Display" for Git/Hive2021 users

    with this:

    Code (Text):
    1.         bcs.s    Obj0A_Display ; that would be "bcs.s    Drown_Display" for Git/Hive2021 users
    2.         move.b    #$D,$1C(a0)      ; change $1C to obAnim if you using the disassembly I mentioned above

    This makes sure it loads animation ID D well, so the art will be blank the next time you drown. From there, save, build and test it, and you should get this:


    Well done! You have done and dusted another bug in Sonic 1.
    Last edited: Jun 27, 2022
  6. EpsilionDubwool


    Be a boss-man and come to my big and tall man shop Member
    Earlier last month, I've had a conversation with vladikcomper to find the best methods to optimize Sonic 1. He came across how it is possible to optimize the BossMove subroutine, which moves the bosses. And after doing my quick analysis by playing GHZ3, I've noticed that the platforms tend to glitch for about a frame or two every time the boss moves. However, upon looking at the code, I saw how quick and easy it was to optimize the code as it shares similar footsteps to two other subroutines: SpeedToPos and ObjectMove.

    So this mini-tutorial will show you how to optimize the BossMove code in vein to S3K. It won't look fast, but it takes less processing time which matters if you intend to have custom bosses with different objects. This will work under any Sonic 1 disassembly. (Sonic 1 Git will be referenced, but it shouldn't be challenging to cross-port the code).

    For Sonic 2 users, I've made a guide for you, so please check it out here.

    Firstly, let's go and check it out:

    Code (Text):
    1. BossMove:
    2.         move.l    $30(a0),d2
    3.         move.l    $38(a0),d3
    4.         move.w    obVelX(a0),d0
    5.         ext.l    d0
    6.         asl.l    #8,d0
    7.         add.l    d0,d2
    8.         move.w    obVelY(a0),d0
    9.         ext.l    d0
    10.         asl.l    #8,d0
    11.         add.l    d0,d3
    12.         move.l    d2,$30(a0)
    13.         move.l    d3,$38(a0)
    14.         rts
    15. ; End of function BossMove
    The way I optimized it was I compared how redhotsonic shortened the subroutine and applied it here. The result you should get is this:

    Code (Text):
    1. BossMove:
    2.         move.w    obVelX(a0),d0        
    3.         ext.l    d0
    4.         lsl.l    #8,d0                
    5.         add.l    d0,$30(a0)  
    6.         move.w    obVelY(a0),d0          
    7.         ext.l    d0
    8.         lsl.l    #8,d0                
    9.         add.l    d0,$38(a0)
    10.         rts  
    11. ; End of function BossMove
    And that's it. Every time the boss moves, it will do the coding quicker in each frame.
  7. A simple fix that I came up with for a silly oversight in Sonic 1. In debug mode, the fans in Star Light Zone will blow around whatever object you're trying to place making it somewhat difficult to navigate. Thankfully, this is a ridiculously easy fix.

    In the GitHub disassembly, open _incObj/5D Fan.asm, and look for the label @blow:

    Code (Text):
    2. @blow:
    3.        tst.b   fan_switch(a0)   ; is fan switched on?
    4.        bne.w   @chkdel       ; if not, branch
    5.        lea   (v_player).w,a1
    6.        move.w   obX(a1),d0
    7.        ...
    In between the bne.w and lea, insert this:
    Code (Text):
    2.        tst.w   (v_debuguse).w       ; is debug mode active?
    3.        bne.s   @animate               ; if yes, branch so fan physics aren't applied
    This will skip the code that applies the fan physics to Sonic if debug placement is active, eliminating this little issue.
  8. Devon


    I am lost in you Tech Member
    I haven't seen anyone else bring this up, but I thought this was a tad interesting.

    So, you might know of the change to make special stages rotate smoother, which is done by removing the "andi.b #$FC,d0" line in SS_ShowLayout that limits the rotation value. Did you know that angle value limitation is also found in Sonic's special stage object and subtley affects his physics for jumping and gravity?

    In Obj09_Jump, you can find:
    Code (Text):
    1.         move.b    (v_ssangle).w,d0
    2.         andi.b    #$FC,d0
    3.         neg.b    d0
    4.         subi.b    #$40,d0
    5.         jsr    (CalcSine).l

    Which calculates the angle to jump at. Note the "andi" instruction, that same line that limits the sprite rotation.

    You can also find a similar line here in Obj09_Fall:
    Code (Text):
    1.         move.b    (v_ssangle).w,d0
    2.         andi.b    #$FC,d0
    3.         jsr    (CalcSine).l

    Which affects how gravity is calculated. Again, that "andi" instruction is there.

    So, if you wanna enable slightly smoother jumping and gravity, comment out those "andi" lines.

    Also, if you followed this guide, then there's 2 additional instances in Obj09_JumpHeight.
    Last edited: Jun 24, 2022
  9. Does the "bcs.s Drown _Display" replace the "beq.s Drown _Display" in the original code? Your post isn't very clear on that.
  10. EpsilionDubwool


    Be a boss-man and come to my big and tall man shop Member
    I said to insert those lines below the second last line below to ensure the correct animation is set correctly, which worked, but after what you said, that also works. Thank you for the update.

    I updated my post to fix that little issue.