How to fix accidental deletion of scattered rings in S1, S2 & S3K

Discussion in 'Tutorials Archive' started by redhotsonic, Jun 3, 2012.

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

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    How to fix accidental deletion of scattered rings


    The problem


    There is a glitch within the scattered rings. Let me explain. In the scattered rings code, there is a check to see if rings have reached to the bottom of the level and if so, to delete themselves. Here is some code from Sonic 2's scattered rings object.



    loc_121B8:
    tst.b (Ring_spill_anim_counter).w


    beq.s BranchTo5_DeleteObject


    move.w (Camera_Max_Y_pos_now).w,d0 ; HERE


    addi.w #$E0,d0 ; HERE


    cmp.w y_pos(a0),d0 ; HERE


    bcs.s BranchTo5_DeleteObject ; HERE


    bra.w DisplaySprite



    It has this code because when rings reach to the bottom of the level, they delete themselves, so they do not spawn at the top of the level (they won't loop). This is a good thing, as we don't want rings looping, right?


    But there is an issue with levels that are y-wrapped enabled. Easiest place to explain it is in Sonic 2's Metropolis act 2.


    [​IMG]


    Debug is enabled to explain easier (glitch will happen with debug mode on or off), but if you go to these co-ordinates in MTZ2, you will see Asteron (starfish badnik) to the right. Go to him and let him hurt you.


    [​IMG]


    I've just got hurt, look at all the rings that are about to scatter. But, the bottom line of the level is right above me.


    [​IMG]


    Look at that! Most of my rings have suddenly vanished! To help, I've drawn a red line. That's the line where if the rings reach, to delete themselves. The rings think that that line is the bottom of the level, but because this level is y-wrapped, technically, there is no "bottom of level". So we still want the rings to be there so we can collect them.


    The bug is NOT fixed in S1 or S3K either, but it is quite hard to pull the glitch off. Generally because the only time you're passing the y-wrap in S1 and S3K, is when you're sliding down the water in LZ, or the ice in ICZ.


    But if you've editing these level layouts to cross the y-wrap quite often, the glitch may become more apparent. And you might want to fix it.


    The fix


    As usual, Sonic 3 and Knuckles' fix is slightly different.


    The fix I have added, I've not equated. That way, the fix is compatible with any disassembly you are using. I've told what disassembly for which game I'm going by, but if you're using any other disassembly, you can still use my fix.


    Sonic 1


    This can be done in SVN disassembly.


    Go to "@chkdel:" and you'll see this:



    @chkdel:
    tst.b (v_ani3_time).w


    beq.s RLoss_Delete


    move.w (v_limitbtm2).w,d0


    addi.w #$E0,d0


    cmp.w obY(a0),d0 ; has object moved below level boundary?


    bcs.s RLoss_Delete ; if yes, branch


    bra.w DisplaySprite



    Right after the 1st branch to "RLoss_Delete" command, insert this:



    cmpi.w #$FF00,($FFFFF72C).w ; is vertical wrapping enabled?
    beq.w DisplaySprite ; if so, branch



    So, you have something like this:



    @chkdel:
    tst.b (v_ani3_time).w


    beq.s RLoss_Delete


    cmpi.w #$FF00,($FFFFF72C).w ; is vertical wrapping enabled?


    beq.w DisplaySprite ; if so, branch


    move.w (v_limitbtm2).w,d0


    addi.w #$E0,d0


    cmp.w obY(a0),d0 ; has object moved below level boundary?


    bcs.s RLoss_Delete ; if yes, branch


    bra.w DisplaySprite



    Done


    Sonic 2


    This can be done in Xenowhirl's 2007 disassembly.


    Go to "loc_121B8:" and you'll see this:



    loc_121B8:
    tst.b (Ring_spill_anim_counter).w


    beq.s BranchTo5_DeleteObject


    move.w (Camera_Max_Y_pos_now).w,d0


    addi.w #$E0,d0


    cmp.w y_pos(a0),d0


    bcs.s BranchTo5_DeleteObject


    bra.w DisplaySprite



    Right after the 1st branch to "BranchTo5_DeleteObject" command, insert this:



    cmpi.w #$FF00,($FFFFEECC).w ; is vertical wrapping enabled?
    beq.w DisplaySprite ; if so, branch



    So, you have something like this:



    loc_121B8:
    tst.b (Ring_spill_anim_counter).w


    beq.s BranchTo5_DeleteObject


    cmpi.w #$FF00,($FFFFEECC).w ; is vertical wrapping enabled?


    beq.w DisplaySprite ; if so, branch


    move.w (Camera_Max_Y_pos_now).w,d0


    addi.w #$E0,d0


    cmp.w y_pos(a0),d0


    bcs.s BranchTo5_DeleteObject


    bra.w DisplaySprite



    Done


    Sonic 3 and Knuckles


    This can be done in SVN disassembly.


    Go to "loc_1A79C" and you'll see this:



    loc_1A79C:
    tst.b (Ring_spill_anim_counter).w


    beq.s loc_1A7E4


    move.w (Camera_max_Y_pos).w,d0


    addi.w #$E0,d0


    cmp.w $14(a0),d0


    bcs.s loc_1A7E4



    Right after the 1st branch to "loc_1A7E4" command, insert this:



    cmpi.w #$FF00,($FFFFEE18).w ; is vertical wrapping enabled?
    beq.w loc_1A7B0 ; if so, branch



    So, you have something like this:



    loc_1A79C:
    tst.b (Ring_spill_anim_counter).w


    beq.s loc_1A7E4


    cmpi.w #$FF00,($FFFFEE18).w ; is vertical wrapping enabled?


    beq.w loc_1A7B0 ; if so, branch


    move.w (Camera_max_Y_pos).w,d0


    addi.w #$E0,d0


    cmp.w $14(a0),d0


    bcs.s loc_1A7E4



    Done


    The bug explained


    Basically, whenever rings fell to the bottom of the level, it deletes itself to stop it looping and coming from the top of the screen (like Sonic does on y-wrapped levels). But with levels with y-wrap enabled, the rings would still delete themselves when it reached those co-ordinates. In the pictures provided as examples, those rings reached them co-ordinates and deleted themselves, which we don't want theoretically, there is no bottom of level and you want your rings back!


    So, all we've done here to all 3 games, is if y-wrap is enabled, do not delete the rings if they've reached them co-ordinates. If y-wrap is disabled, then to delete the rings once they've reached the bottom of the level.


    The rings itself will still delete themselves after a certain amount of time, so, you do not need to worry about them being around forever if y-wrap is enabled.


    That's it. Enjoy!


    redhotsonic
     
    FireRat likes this.
Thread Status:
Not open for further replies.