Here's the code:
tst.b (Super_Sonic_Knux_flag).w bne.s loc_215F4 cmpi.b #2,$38(a1) beq.s loc_215F4 btst #4,$2B(a1) bne.s loc_215E0 btst #5,$2A(a0) beq.s loc_2162A loc_215E0: cmpi.b #2,$20(a1) bne.s loc_2162A move.w d1,d0 bpl.s loc_215EE neg.w d0 loc_215EE: cmpi.w #$480,d0 blo.s loc_2162A loc_215F4: bclr #5,$2A(a0) bsr.s sub_2165A ...Alright, let's start from the top.
tst.b (Super_Sonic_Knux_flag).w bne.s loc_215F4Pretty straightforward. If you're Super Sonic or Super Knuckles (or the Hyper version of either character), then you can break the wall. Note that this leaves out Super Tails, as if he wasn't screwed over enough already.
cmpi.b #2,$38(a1) beq.s loc_215F4$38 is the character ID: Sonic is 0, Tails is 1, Knuckles is 2. So if you're playing as Knuckles, then you can break the wall. This effectively means the previous check is only relevant when playing as Sonic.
btst #4,$2B(a1) bne.s loc_215E0$2B is the secondary status bitfield, exclusive to the player objects. Sonic Retro helpfully chimes in:
Bit | Hex | Description |
---|---|---|
4 | $10 | Fire shield flag. |
So if you have a flame barrier, we skip over the next check. Which happens to be...
btst #5,$2A(a0) beq.s loc_2162A$2A is the primary status bitfield, universal to all objects. Note that we're checking the flags of the breakable wall in a0, not the player object loaded in a1. Retro says:
Bit | Hex | Description |
---|---|---|
5 | $20 | Set if Sonic is pushing on this object. |
This is a bit inaccurate. Bit 5 is only set if player 1 is pushing on the object while standing on something. Combined with the previous check, this means if you have a flame barrier, then you can break the wall even if in mid-air.
cmpi.b #2,$20(a1) bne.s loc_2162A$20 is the current animation ID, for objects that use the global animation system. In the case of the player objects, #2 corresponds to the spinning animation, used while either rolling or jumping. So if you aren't in the spinning animation, then you can't break the wall.
move.w d1,d0 bpl.s loc_215EE neg.w d0 loc_215EE: cmpi.w #$480,d0 blo.s loc_2162AFinally, the player's horizontal velocity, which was previously stored in d1, is copied over to d0 and transformed into its absolute value. That value is then compared to $480, and if you're moving at a horizontal speed of less than 4.5 pixels, then you can't break the wall. This also applies to the flame barrier check, which is what allows Sonic to break through walls using his fireball dash move.
Notice anything fishy, though? Nowhere do we check whether the player has performed a double jump move or not, so if you have a flame barrier, just jumping at the wall with the requisite speed will work. In fact, there's no check for Sonic either, which means Tails can break down walls in the exact same way. This surely annoys players who try to avoid the first special ring in Angel Island 2 by jumping -- only to go through the wall due to their speed coming out of the tube.
So there /aren't/ any specific "Knuckles-only" walls, they just put them in midair and restrict your access to fire shields? And Super Sonic can bust through them anyway? That's... not the conclusion I expected.
ReplyDeleteWhere did I say there aren't any Knuckles-only walls? Strap yourself in, we're just getting started.
DeleteI don't get why they wouldn't add a double jump move check. Do you think there's some logic to that, or it's most likely just an oversight?
ReplyDeleteI dunno. I checked Sonic 1/2 and everything up to loc_215E0 is missing, so it was added specifically for Sonic 3. Smells like lousy programming to me.
DeleteActually, the game does have a way to know whether the player is using a double jump move: the double jump flag, which is also used to track Tails and Knuckles' flying/gliding state. Among other things, it prevents you from using your double jump move more than once per jump.
Delete