Actions

SCHG How-to

Fix Accidental Deletion of Scattered Rings

From Sonic Retro

Revision as of 03:48, 10 June 2012 by KingofHarts (talk | contribs) (Another Header edit)

(Guide for all 3 games written by redhotsonic.) I am not sure how to repost the images from the original guide here, so in the meantime, for further illustration, check out the OP: [1]

The Problem

Anyway, 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 the bottom of the level and if so, to delete themselves. Here is some code from Sonic 2's scattered rings object.

<asm> 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

</asm>

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. Easy example: Sonic 2's Metropolis Zone, Act 2.

Go to the area with the yellow strips of diagonal springs, a wall to your right, and an Asteron on the lower-right hand corner. (The first screenshot in the OP.) Let Asteron hurt you. You will notice that you will lose your rings, and at first... all will seem normal. However, one thing to note is that the bottom line of the level is right above you. (The 3rd image in the OP shows this, with the red line) When the rings cross this line, they are deleted, making it impossible to collect them! This happens because due to the code, the rings think that it is the bottom of the level! But since Metropolis Zone is "y-looped", that isn't the case... So we still want our rings available so we may collect them.

NOTE: This bug is also present in Sonic's 1 & 3K, 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 in the water slide in LZ Act 3, or in the ice tunnel in ICZ Act 1.

But if you're editing these level layouts to cross the y-wrap quite often, the glitch may become more apparent. And you might want to fix it. Therefore, we will cover fixing this for ALL 3 games! Lets start with Sonic 1, and work our way forward...

The Fix

NOTE: 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 fix

This guide uses the SVN disassembly.

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

       @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

</asm>

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

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

</asm>

So, you have something like this: <asm>

       @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

</asm>

Done

Sonic 2 fix

This guide uses Xenowhirl's 2007 disassembly.

Go to "loc_121B8:" and you'll see this: <asm> 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

</asm>

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

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

</asm>

So, you have something like this: <asm> 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

</asm>

Done

Sonic 3K fix

This guide uses the SVN disassembly.

Go to "loc_1A79C" and you'll see this: <asm> 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

</asm>

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

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

</asm>

So, you have something like this: <asm> 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

</asm>

Done

The bug explained

Basically, whenever rings fall to the bottom of the level, they delete themselves to stop from 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 they reached those same co-ordinates. In the pictures provided as examples (In the OP), those rings reached the 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 the co-ordinates. Only if y-wrap is disabled, will the game 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.