Thursday, January 18, 2018

Keep your arms inside at all times

One version difference that a lot of people latch onto is Launch Base Zone's final boss, Big Arm, and the behavior of its grabbing attack when the player is Super. In Sonic & Knuckles, this just bounces the player off the ground with a spring sound, but in Sonic 3, it causes Super Sonic to drop all of his rings and thus revert back to normal Sonic.


The reason for this is boring: in Sonic 3, regardless of whether the player is Super or not, the HurtCharacter function is called, which uh, hurts the character. Meanwhile, Sonic & Knuckles added a check for invincibility (not Super!) that calls up a separate code path if the appropriate bit is set. This suggests the original behavior was just an oversight.
loc_510AE:                          loc_74664:
    move.w  d0,$18(a0)                  move.w  d0,$18(a0)
    move.w  #-$600,$1A(a0)              move.w  #-$600,$1A(a0)
    move.w  #$3F,$2E(a0)                move.w  #$3F,$2E(a0)
                                        btst    #Status_Invincible,(Player_1+status_secondary).w
                                        bne.s   loc_7468C
    movea.l a0,a2                       movea.l a0,a2
    lea     (Player_1).w,a0             lea     (Player_1).w,a0
    jsr     (HurtCharacter).l           jsr     (HurtCharacter).l
    movea.l a2,a0                       movea.l a2,a0
    rts                                 rts
                                    
                                    loc_7468C:
                                        lea     (Player_1).w,a1
                                        clr.b   $2E(a1)
                                        neg.w   d0
                                        move.w  d0,$18(a1)
                                        move.w  #-$400,$1A(a1)
                                        bset    #1,$2A(a1)
                                        bclr    #3,$2A(a1)
                                        clr.b   $40(a1)
                                        clr.b   $3D(a1)
                                        move.b  #2,$20(a1)
                                        move.b  #2,5(a1)
                                        moveq   #-$4F,d0
                                        jmp     (Play_Sound_2).l
There's another, more interesting oversight with the Big Arm boss, which wasn't fixed in Sonic & Knuckles. It requires a second player, however in Sonic 3, the Tails object is deleted during the Egg Mobile ride, and in Sonic & Knuckles, only Knuckles fights the boss!

We can force the bug to occur in Sonic 3 by using the PAR code 05A8CC:6010, which prevents Tails from despawning at the end of Launch Base 2. Get the boss down to 1 HP, then let it grab you while having Tails deal the final hit.


When this happens, Sonic gets stuck in mid-air, at least until the ending sequence starts. The effects are more heinous in Sonic & Knuckles because a regular stage clear sequence was added to the level, which can't start because Sonic is not touching the floor.

What's interesting about this oversight is that both Sonic 3 and Sonic & Knuckles have code in place to prevent it. If the byte at offset $30 of Big Arm's SST is clear, then it calls the Restore_PlayerControl function, which clears the player's object_control flag and resets their animation:
loc_51D78:                                  loc_7506E:
    tst.b   $30(a0)                             tst.b   $30(a0)
    bne.s   loc_51D82                           bne.s   loc_7507A
    jsr     Restore_PlayerControl(pc)           jsr     (Restore_PlayerControl).l
                                            
loc_51D82:                                  loc_7507A:
    jmp     (SaveGame).l                        lea     ChildObjDat_75186(pc),a2
                                                jmp     (CreateChild1_Normal).l
Problem is, the byte at offset $30 is set when the boss is holding the player, which means the Restore_PlayerControl function is only called in the exact wrong situation: when the boss isn't holding the player.


This can be seen in both Sonic 3 and Sonic & Knuckles: upon dealing the final hit to the boss, the player's animation is reset, which results in them falling to the ground in their standing frame.

3 comments:

  1. I see people think the first quirk is intentional because it's the final boss in S3A and not in S3K. I'm convinced it's an error because the spike balls in Icecap Zone - Act 1 hurt you in S3A but not S3K, likely because Knuckles has to face them in S3K. I imagine this is similar to the Sonic 1 spike bug, since the ICZ spike balls also hurt you when flashing, so now I want to extend the post-hit invulnerability timeframe to a minute or so and replace the debug mode S monitor with invincibility to test my hypotheses.

    ReplyDelete
  2. Considering the above quote by Brainulator9, is there a reason why Big Arms can only be fought as Knuckles in S3K and skipped entirely by Sonic and Tails, compared to S3A where Sonic and Tails has to fight it? I can imagine some coding reasons are behind it, since the S3C hack patcher includes the ability to fight it in S3K, but what sort of coding is behind it?

    ReplyDelete
  3. Despite it being an oversight, i quite like how the Big Arm boss can knock you out of your Super form with the slam attack. Since it's the final boss for S3A, it oddly makes sense that it can knock you out of your most powerful form. Though fixing it for Knuckles in S3K was probably the right choice.

    ReplyDelete