don't click here

Some changes and fixes for Sonic 2

Discussion in 'Engineering & Reverse Engineering' started by Esrael, Jun 7, 2012.

  1. PKstarship

    PKstarship

    Super-Sonic Racer
    I'm no hacker, but I've always hated this glitch, and wondered if this could be fixed: In Hill Top Zone act 2, after the room that fills with lava, there is a large room that you normally use the blue platforms to slowly descend. But jumping down straight to the bottom (usually as Super Sonic) will result in falling out of the level and dying instead of landing in the lava at the bottom. If someone can fix this, I will be pretty happy :)
     
  2. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    Isn't that just a case of the character moving so fast the collision engine can't handle it, with the character appearing on the other side of the level solidity within a frame? A lot of the level solidity, on the floor at least, is 2 8x8's thick. In that room, that lava is only 1 8x8 thick.
     
  3. PKstarship

    PKstarship

    Super-Sonic Racer
    I think it has do do with the collision. Another glitch involves landing on the green platform at the bottom-right of that same room, then defeating that purple badnik in the lava to the right, which soft-locks the game. And one thing I noticed is that when Sonic moves really fast, the camera sometimes falls behind. Is there a way to fix these things?
     
  4. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    The purple thing, we fixed. As for the camera, it's intentional. S1/S2 can't load the offscreen visuals fast enough, so they keep the camera at a reasonable speed. See more on the topic here.
     
  5. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    It's a collision error. I have hackishly fixed it in my Sonic 2 Time Attack, and it works perfectly for normal Sonic, but for Super Sonic, he can still get stuck and them zoom out of the lava, but shouldn't die. I haven't shared a fixed because the code for it is a bit hackish and until I can be arsed to figure it out properly, it'll stay that way.

    I can't remember if the lava is 1 8x8 thick or not, but adding more won't make a difference (because like Clownacy has mentioned, the collision can't keep up with [Super] Sonic).


    EDIT: Spellings.
     
  6. PKstarship

    PKstarship

    Super-Sonic Racer
    I've been playing a lot of Sonic Classic Heroes lately, and have found two glitches that apply in vanilla Sonic 2 also, both in Metropolis Zone act two. First off, if you get hit and land on the floating platforms in the lava at the beginning of the level, you will fall through the lava and end up a bit further into the stage. This glitch can also get you stuck under a lava pit in Hill Top Zone until time runs out. Also, spin-dashing while on the gears and falling off will sometimes make Sonic walk slowly in place with dust trails beneath his feet until you let go of down, which releases the spin-dash. Have these things been fixed? I play a lot of Sonic 2, and while I don't know how to fix these things, I hope I can help by putting these glitches here :)
     
  7. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    I did said:
    The next (unreleased) version of SCH has been like this for several months now:
     
  8. PKstarship

    PKstarship

    Super-Sonic Racer
    Wow, awesome! I hate that Hill Top Zone glitch to this day, so it's nice to see it finally fixed :D
     
  9. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    Are you sure about that? I doubled the collision, and now I can't trigger the bug. My point was that Super Sonic, at that speed, is above the single row of 16x16s in one frame, and below them in the other, bypassing the collision entirely. Doubling the thickness makes Super Sonic more likely to appear inside a 16x16 with collision, which will push him up and out of both rows, colliding properly.

    EDIT: Derp, it's 16x16; not 8x8.

    EDIT2: Well, while I'm here... there's an S1 leftover in the debug mode code. Check out loc_41C82. There's a check for special stage mode, and some additional code for it. You can't use debug mode in S2's debug mode, and the code there was meant for S1's debug mode anyway, so it's useless.
     
    Last edited: Apr 21, 2022
  10. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    I thought I'd released a fix for that? If not, I will look over my notes and post the fix sometime, because I have also fixed that in my S2TA game. I've been really busy recently though so watch this space (unless someone beats me to it).


    We knew what you meant, as I made the same mistake of clling it 8x8 =P


    Anyway, I was going by memory. Thickening it helped for when Sonic went down there (pretty much got stuck inside the collision then being pushed out), but with Super Sonic, it made little difference (he still managed to be push through). The badnik being placed right at the dying point probably pushed him further down and killed him. Anyway, I added a hackish code on fixing it entirely. What I might do (again, when I find the time), is clean it up and release the fix.
     
  11. PKstarship

    PKstarship

    Super-Sonic Racer
    I was messing arould in Sonic 2, Aquatic Ruin Zone, and encountered the glitch where Sonic can't be damaged while behind leaves. I just wanted to ask if is this really a glitch, and if there is a fix for it.
     
  12. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    This has been discussed before. I'm starting to notice a trend, here. Anyway, if I'm remembering it right, the collision manager can only collide Sonic/Tails with one thing at a time. A workaround for that would be to modify the leaves object to not rely on the collision manager, and handle collision with the player by itself. This would free up the collision manager to handle any other objects Sonic/Tails could collide with.

    EDIT: Again, while I'm here: PlrList_Wfz1 lists ArtNem_Tornado and ArtNem_Clouds twice. This is pointless, and only serves to make the loading times longer.

    EDIT2: Here's what I was talking about.
     
  13. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    I keep pointing people to this, so I might as well put it here.

    After Sprite_Table, there's $80 bytes of unused RAM. There are all kinds of things you might want to use it for, but you'll soon find that section being flooded with random rubbish. Even worse, the stuff directly after that unused RAM, Normal_palette, can be overwritten too.

    The cause of this is yet another bug in BuildSprites. Basically, BuildSprites checks if Sprite_Table is full and, if not, it renders a sprite. The problem is, it doesn't compare how empty Sprite_Table is to how much of it this new sprite will take. This means, if there's only room for one sprite piece in Sprite_Table, BuildSprites will happily write the four that make up the entire sprite it just accepted.

    Oddly, this is something S1 handled just fine: it checks, after every sprite piece, if Sprite_Table is full, avoiding this entirely. For whatever reason, S2 removed those checks.

    As for fixing this, place the following check after these labels:

    Code (ASM):
    1.     cmpi.b  #80,d5
    2.     beq LOCRET
    • DrawSprite_Loop
    • The '-' label after DrawSprite_FlipX
    • DrawSprite_FlipY
    • DrawSprite_FlipXY
    • DrawSprite_2P_Loop
    • The '-' label after DrawSprite_2P_FlipX
    • DrawSprite_2P_FlipY
    • DrawSprite_2P_FlipXY

    Just change the 'LOCRET' to the nearest 'rts' label.

    It's worth noting that the similar checks under ChkDrawSprite, DrawSprite, ChkDrawSprite_2P, and DrawSprite_2P can be stripped out. ChkDrawSprite and ChkDrawSprite_2P can be removed entirely, if you know what you're doing.

    On a slightly related note, the current Git disasm gives Sprite_Table a size of $280, with that "unused" $80 bytes after it, but Sprite_Table_2, used for 2 player mode, is listed as having a size of $300, with no $80 after it, despite suffering from the same bug. Hmm...
     
  14. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    So, remember how, in that one guide, the collapsing platforms stop respawning when you destroy them? I recently got around to tackling it, and the cause seems to be some kind of bug. Basically, the main platform object turns itself into a falling fragment, along with creating several others, when you step on it. These fragments are designed as simple objects intended to be created by a parent object, with no ties to any higher object management. Problem is, by turning itself into one, the parent-object-turned-fragment still has to perform the MarkObjGone function, so the parent can be marked as unloaded, so it can be reloaded when you go offscreen and return. Really, I'm not too clear on this, it's been giving me headaches for the best part of an hour, so I could be talking out of my ass, for all I know.

    Anyway, fixing this is simple. Instead of modifying the fragment object to use MarkObjGone, I'll just make the parent object mark itself as unloaded when it transforms itself into a fragment. Go to loc_10B68, and, under the 'movea.l a0,a1' insert this:

    Code (ASM):
    1.     move.w  respawn_index(a0),d0
    2.     beq.s   +
    3.     movea.w d0,a2
    4.     bclr    #7,(a2)
    This is assuming you're using S3K's object manager, which is likely the reason you're following this guide. Alternatively, you can use the markObj_gone macro from Module's guide, if you have it.
     
  15. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    Part 2 to the above guide, hopefully justifies the double post. This time we're focussing on Obj18, the floating platforms from ARZ and EHZ (and HTZ. Thanks, inaccurate disasm comment). In HTZ, there's a room with rising magma. You have to climb out of this room with the help of some floating platforms. Some of these fall and leave the screen, but running around a bit will make them respawn. Again, thanks to S3K's object manager giving everything a respawn table entry, these have bugged, and won't respawn.

    The cause is similar to the above post: the object stops handing its respawn data when it falls and deletes itself, meaning it never marks itself as unloaded, so it can be reloaded. Fixing this is even more of a joke than the first fix: go to BranchTo3_DeleteObject and insert the markObj_gone macro before the bra.w. Now the object will respawn properly.

    Also, for anyone reading, the above post got rewritten not long after it was posted. The original fix was way more complicated, and had a pretty obvious bug, so double check you're using the new one.
     
  16. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    Two more frame-perfect crashes when battling bosses:

    Fixing Oil Ocean boss crash
    If you defeat the boss on the exact frame when he finishes sinking below the screen, the game will crash. Fixing the issue is easy: find this code:
    [68k]; loc_33174:
    Obj55_HandleHits:
    bsr.w Boss_HandleHits
    cmpi.b #$1F,boss_invulnerable_time(a0)
    bne.s return_33192
    lea (Boss_AnimationArray).w,a1
    andi.b #$F0,(a1)
    ori.b #3,(a1)
    ori.b #$80,Obj55_status(a0) ; set boss hit bit

    return_33192:
    rts[/68k]
    and change it to this:
    [68k]; loc_33174:
    Obj55_HandleHits:
    bsr.w Boss_HandleHits
    cmpi.b #$1F,boss_invulnerable_time(a0)
    bne.s .chk_killed
    lea (Boss_AnimationArray).w,a1
    andi.b #$F0,(a1)
    ori.b #3,(a1)
    ori.b #$80,Obj55_status(a0) ; set boss hit bit

    .chk_killed:
    cmpi.b #8,boss_routine(a0) ; is boss exploding or retreating?
    blo.s return_33192 ; if yes, branch
    move.b #2,boss_subtype(a0) ; => Obj55_Main


    return_33192:
    rts[/68k]
    What is the issue?
    When the boss is defeated, boss_routine(a0) is set to 8. ; and on the frame when the boss sinks below the bottom of the screen, boss_subtype(a0) is set to 6 — the spiked chain. The spiked chain does not have enough entries for boss_routine(a0) = 8, so the game ends up executing invalid code. The fix forces boss_subtype(a0) back to Eggman in his submarine.

    Fixing Metropolis boss' clone crash
    If Tails hits a clone two frame frames after it hits Sonic, the game will crash:

    This is a special case of the crash you get when Tails hits any clone two frames after Sonic has been hit by any clone. Fixing this one is rather easy: find this code:
    [68k];loc_32BB0
    Obj53_Animate:
    bsr.w +
    lea (Ani_obj53).l,a1
    jsrto (AnimateSprite).l, JmpTo21_AnimateSprite
    jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
    ; ===========================================================================
    +
    cmpi.b #-2,collision_property(a0)
    bgt.s + ; rts
    move.b #$14,mapping_frame(a0)
    move.b #6,anim(a0)
    addq.b #2,routine(a0)
    +
    rts
    ; ===========================================================================
    ;loc_32BDC
    Obj53_BounceAround:
    tst.b objoff_32(a0)
    bmi.s +
    subq.b #1,objoff_32(a0)
    bpl.s +
    move.b #$DA,collision_flags(a0)
    +
    bsr.w Obj53_CheckPlayerHit
    cmpi.b #$B,mapping_frame(a0)
    bne.s Obj53_Animate[/68k]
    (or the equivalent in your disassembly) and change it to look like this:
    [68k];loc_32BB0
    Obj53_Animate:
    bsr.w +

    Obj53_Animate_Part2:
    lea (Ani_obj53).l,a1
    jsrto (AnimateSprite).l, JmpTo21_AnimateSprite
    jmpto (DisplaySprite).l, JmpTo40_DisplaySprite
    ; ===========================================================================
    +
    cmpi.b #-1,collision_property(a0)
    bgt.s + ; rts
    move.b #$14,mapping_frame(a0)
    move.b #6,anim(a0)
    addq.b #2,routine(a0)
    +
    rts
    ; ===========================================================================
    ;loc_32BDC
    Obj53_BounceAround:
    tst.b objoff_32(a0)
    bmi.s +
    subq.b #1,objoff_32(a0)
    bpl.s +
    move.b #$DA,collision_flags(a0)
    +
    bsr.w Obj53_CheckPlayerHit
    cmpi.b #$B,mapping_frame(a0)
    bne.s Obj53_Animate_Part2[/68k]
    What is the issue?
    When Sonic is hit by a clone, this clone and all others are set to animation 6; this animation ends with a $FC command, which adds 2 to routine(a0) after it is done. This happens in two frames; at this point, getting hit by Tails will further increment routine(a0) by 2 due to the above code, and routine(a0) will end up jumping to invalid code. Adding the 'Obj53_Animate_Part2' label and changing the last branch of the code to jump to it fixes this. Changing the Obj53_BounceAround code just fixes an issue where a clone will not pop when hitting a character until it lands at least once.
     
  17. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Where were you two weeks ago? =P djohe and DAGarden (thanks) showed me this bug. It didn't freeze, and instead caused this glitch, and Eggman just stayed above without moving. Is this the same issue? Apparently, they hit the orb at the exact same time.

    http://rhs.sonicresearch.org/SonicBash_BUG_metro.PNG



    It seems a lot of bosses suffer this sort of error, like the ARZ and DEZ silver Sonic, etc.


    EDIT: Changed link source. It's still the same picture though.
     
  18. flamewing

    flamewing

    Emerald Hunter Tech Member
    1,161
    65
    28
    France
    Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
    By the way, I fixed the fix above; the fix is mostly because of another tiny bug, in that the boss clones only actually pop after they hit the floor at least once. The new fix is better in every way, and I have to thank djohe for pointing out this other issue (which also happens in S2 anyway).

    Edit: And yes, it could be the same bug; it crashes on real hardware, Regen and Gens. I know that Fusion handles reading unaligned words differently than Gens does (both equally incorrect), so it may not crash in Fusion in this one instance.

    Visually, it looks like a double-hit, because I doubt you could tell the difference of 2 frames between the hits in real time.
     
  19. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    10
    18
    United Kingdom
    YouTuber
    Yeah, they were playing Kega so it could explain the no-crash. I will apply your fixes, but whether it will fix my issue or not I do not know. Especially when I can't recreate what djohe and DAGarden did =P


    EDIT: Actually, flamewing, djohe and DAGarden said that Eggman just hanged up the top when this happened. My guess is because the counter was at 1, waiting for 1 orb to be destroyed. Hitting it both at the same time will make the counter got to $FF, making Eggman just wait.

    Assuming your fix fixes the crash issue, will this till make the counter go down by 1, or by 2? If 2, this "new" bug may occur. There was a few times where I had to edit the MTZ boss to make sure the counter did not accidentally go to $FF, otherwise he will wait for you to destroy $FF orbs before coming down again. Obviously this may be a case where it could go to $FF. Just a thought.
     
  20. Clownacy

    Clownacy

    Tech Member
    1,060
    607
    93
    More of a head's up than a bugfix, if you plan on using a palette cycle outside of levels, be sure to clear PalCycle_Frame, and stuff like that before doing anything. Normally, it's only cleared during level initialisation. In my case, my title screen palette cycle caused a crash because PalCycle_EHZ set PalCycle_Frame to an odd value.

    EDIT: Also, the second half of Obj0A_WobbleData is an unused leftover from S1.