How to fix level transition issues in Sonic 1

Discussion in 'Approved' started by vladikcomper, Mar 23, 2012.

Thread Status:
Not open for further replies.
  1. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    421
    In Sonic 1, when level switches to the next one, the few bugs can occur during the fade out sequence.

    1) If next level is a new zone, the BG may get deformed wrongly. The example is when GHZ3 switches to MZ1, just compare screenshots before fading and during it:
    [​IMG][​IMG]

    However this can be ok in other zones, as it depends on how BG deformation works in the next level.


    2) If the end position of current level matches the boss arena position in the next act, the boss will be loaded, and boss music will start to play, but stop quickly as all sounds fade out.

    This didn't happen in the original game though, as acts 2 were shorter than acts 3. But if you widen them, you may meet this bug easily.


    3) On zone transition, palette cycles of new zone will apply as soon as fading starts, so few colors may spoil. This is noticeable during MZ3 to SYZ1 transition.

    All these bugs are caused because level restart conditions sits in a wrong place. When 'SONIC HAS PASSED' card object switches level, many routines, like BG deformation and palette cycling, will work before restart level condition is met. As the level is switched, all these routines will deform BG, load objects and do palette cycles for the new level, which causes bugs described above.


    Go to Level_MainLoop, you will see:

    Code:
    Level_MainLoop:
            bsr.w    PauseGame
            move.b    #8,($FFFFF62A).w
            bsr.w    DelayProgram
            addq.w    #1,($FFFFFE04).w    ; add 1 to level timer
            bsr.w    MoveSonicInDemo
            bsr.w    LZWaterEffects
            jsr    ObjectsLoad
            tst.w    ($FFFFFE08).w
            bne.s    loc_3B10
            cmpi.b    #6,($FFFFD024).w    ; is Sonic dying?
            bcc.s    loc_3B14        ; if yes, branch
    
    loc_3B10:
            bsr.w    DeformBgLayer
    
    loc_3B14:
            jsr    BuildSprites
            jsr    ObjPosLoad
            bsr.w    PalCycle_Load
            bsr.w    RunPLC_RAM
            bsr.w    OscillateNumDo
            bsr.w    ChangeRingFrame
            bsr.w    SignpostArtLoad
            tst.w    ($FFFFFE02).w    ; is the level set to restart?
            bne.w    Level        ; if yes, branch
            cmpi.b    #8,($FFFFF600).w
            beq.s    Level_ChkDemo    ; if screen mode is 08 (demo), branch
            cmpi.b    #$C,($FFFFF600).w
            beq.w    Level_MainLoop    ; if screen mode is $0C    (level), branch
            rts            ; quit
    
    Here is level restart condition among the lines:
    Code:
            tst.w    ($FFFFFE02).w    ; is the level set to restart?
            bne.w    Level        ; if yes, branch
    
    It branches to 'Level' routine, to fade out and reload the whole level. The condition is ok, but see how many unnecessary routines work after level id is switched (during ObjectsLoad, as switched by object) and before this condition is met.

    To fix this, simply move the condition few lines up, under the 'jsr ObjectsLoad' line.

    You will get:

    Code:
    Level_MainLoop:
            bsr.w    PauseGame
            move.b    #8,($FFFFF62A).w
            bsr.w    DelayProgram
            addq.w    #1,($FFFFFE04).w    ; add 1 to level timer
            bsr.w    MoveSonicInDemo
            bsr.w    LZWaterEffects
            jsr    ObjectsLoad
            tst.w    ($FFFFFE02).w    ; is the level set to restart?
            bne.w    Level        ; if yes, branch
            tst.w    ($FFFFFE08).w
            bne.s    loc_3B10
            cmpi.b    #6,($FFFFD024).w    ; is Sonic dying?
            bcc.s    loc_3B14        ; if yes, branch
    
    loc_3B10:
            bsr.w    DeformBgLayer
    
    loc_3B14:
            jsr    BuildSprites
            jsr    ObjPosLoad
            bsr.w    PalCycle_Load
            bsr.w    RunPLC_RAM
            bsr.w    OscillateNumDo
            bsr.w    ChangeRingFrame
            bsr.w    SignpostArtLoad
            cmpi.b    #8,($FFFFF600).w
            beq.s    Level_ChkDemo    ; if screen mode is 08 (demo), branch
            cmpi.b    #$C,($FFFFF600).w
            beq.w    Level_MainLoop    ; if screen mode is $0C    (level), branch
            rts            ; quit
    
    That's it. The big bug fixed in one shot =)

    EDIT [31/07/2017]: Fixed formatting that broke after numerous forum updates.
     
    Last edited: Jul 31, 2017
    Naoto likes this.
  2. SpirituInsanum

    SpirituInsanum Well-Known Member Member

    Joined:
    Feb 11, 2010
    Messages:
    642
    I never took time to look into it, but this is definitely a very welcome fix. With this fixed, the game engine looks much more solid as those visual glitches were showing a disagreeable technical side the player should never see.


    Thanks :)
     
  3. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    Very cool stuffs indeed, soon we'll have every possible bug in the game fixed, and this is one step closer.
     
  4. Psycho RFG

    Psycho RFG Well-Known Member Member

    Joined:
    Feb 22, 2011
    Messages:
    234
    Nice fix! I remember ask for this long ago. I have tested the code and it works fine. It's cool to have it finally fixed! Great job Vladikcomper!
     
  5. vladikcomper

    vladikcomper Well-Known Member Member

    Joined:
    Dec 2, 2009
    Messages:
    421
    Thank for your replies =)

    Yes, we're getting closer and closer. There are still many bugs to discover though.


    Soon I plan to make another guide fixing noticeable bug with PLC queue processing (we already have an awesome guide fixing PLC 'race condition', but another serious bug remains uncovered).
     
  6. Selbi

    Selbi The Euphonic Mess Member

    Joined:
    Jul 20, 2008
    Messages:
    2,435
    Location:
    Northern Germany
    Ok, this is amazing. It was in fact so amazing that this bug fix made me dig out ERaZor again after over a month of complete nothingness.
     
  7. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    Am I the only one who's never noticed this bug? =P
     
  8. SpirituInsanum

    SpirituInsanum Well-Known Member Member

    Joined:
    Feb 11, 2010
    Messages:
    642
    Such bugs are usually completely ignored. Personally, I often noticed it and always forgot it immediately after entering the next level. If I had to list the bugs in S1, I'm totally sure I would have forgotten it.


    Now that it's fixed, I do noticed the transition looks *much* better though, especially when the big ring remains on screen during the fade out.
     
  9. MaDSkull

    MaDSkull Lycanthrope Member

    Joined:
    Apr 3, 2013
    Messages:
    25
    Location:
    Baku
    I was never notice that bug until I saw this topic. Nice fix !
     
  10. nineko

    nineko I am the Holy Cat Member

    Joined:
    Mar 24, 2008
    Messages:
    1,902
    Location:
    italy
    I noticed it a lot of times, basically every time I played, in fact I even thought it was unavoidable, I always assumed it happened because something was loaded too soon, or something.


    Now, did YOU notice that you bumped a topic which was just a few days short from being 2 years old, right?
     
  11. MarkeyJester

    MarkeyJester ♡ ! Member

    Joined:
    Jun 27, 2009
    Messages:
    2,867
    [​IMG]

    You didn't want to be staff... >=(
     
  12. KingofHarts

    KingofHarts Well-Known Member Member

    Joined:
    Sep 30, 2012
    Messages:
    53
    Location:
    Chi-Town
    Looked into this in Sonic 1... This is already fixed in the Revision JP01 version. Looking into the clean Git disasm, you can see it.

    Either way, it's a good look into WHY this was fixed.
     
Thread Status:
Not open for further replies.