Thursday, December 14, 2017

Over the threshold

Not far into Sonic's animation routines, we come across the following snippet:
loc_1270A:
    tst.b   (Super_Sonic_Knux_flag).w
    bne.s   loc_12766
    lea     (byte_12AF8).l,a1
    cmpi.w  #$600,d2
    bhs.s   loc_12724
    lea     (byte_12AEE).l,a1
They're a little obfuscated due to a lack of human-readable labels, but byte_12AEE and byte_12AF8 are the scripts for Sonic's walking and running animations, which can be found in the Anim - Sonic.asm file in the current disassembly:
byte_12AEE:     dc.b  $FF,   7,   8,   1,   2,   3,   4,   5,   6, $FF

byte_12AF8:     dc.b  $FF, $21, $22, $23, $24, $FF, $FF, $FF, $FF, $FF
As we can tell from the above code, rather than use the current animation value at byte $20 of its SST, the Sonic object switches between walking and running by loading the appropriate animation script, based on the value of register d2. It does so without resetting its own animation frame value, so the shorter running animation is padded to the length of the walking animation to ensure the value is kept within the bounds of either animation.

Meanwhile, register d2 contains Sonic's current ground velocity, which serves as a threshold for when the running anim should kick in. Ground velocity is measured in increments of 1/256 pixels per frame, and so the above code causes the running anim to kick in when Sonic is traveling at a speed higher or equal to 6 pixels per frame.

Every time the current animation frame changes, ground velocity is also used to inform the initial value of the animation frame timer; the first byte in either animation script is for all purposes unused.

When the Super_Sonic_Knux_flag is set however, the code jumps to loc_12766, which looks like this:
loc_12766:
    lea     (byte_12C84).l,a1
    cmpi.w  #$800,d2
    bhs.s   loc_1277E
    lea     (byte_12C7A).l,a1
Not only does the code now point at Super Sonic's walking and running animations, which have separate definitions for some reason, but the speed threshold is raised from 6 to 8 pixels per frame. The reason for this is obvious: the running animation is meant to kick in when Sonic reaches his maximum speed (on flat ground, anyway), and since Super Sonic has a higher maximum speed, the threshold is moved forward to compensate.

This detail is so fundamental, it pains me that neither the mobile remakes nor Sonic Mania implement it, causing Super Sonic to break into his flying pose much sooner than intended.


Anyway, if we keep scrolling down, we'll eventually find a third spot where a similar speed check is done:
loc_12A4C:
    lea     (byte_12B0C).l,a1
    cmpi.w  #$600,d2
    bhs.s   loc_12A5E
    lea     (byte_12B02).l,a1
So what are the byte_12B02 and byte_12B0C animation scripts? Turns out, they're byte-for-byte identical, and both of them define Sonic's rolling animation:
byte_12B02:     dc.b  $FE, $96, $97, $96, $98, $96, $99, $96, $9A, $FF

byte_12B0C:     dc.b  $FE, $96, $97, $96, $98, $96, $99, $96, $9A, $FF
Rather unintuitively, while Sonic is jumping or spinning, the above code causes his animation to switch between a "slow roll" anim and a "fast roll" anim, according to the same threshold as the running code. It just so happens that since both animations are identical, there is no way to actually observe this change.

5 comments:

  1. What about how the running animation speeds up with increased speed?

    ReplyDelete
    Replies
    1. And of course, I had to wait a couple of hours.

      I know that Super Tails's sprinting animation (the blurred tails, same context as the Sonic figure eight in Sonic CD) can appear via max reachable speed in Sonic 3 & Knuckles, Sonic 1 2013, and Sonic 2 2013, but not in Sonic Mania. It's weird, but not as weird as how in both the Sonic 1 and 2 remakes, Tails can sprint with his running animation if you've played as Sonic or Knuckles before or with Tails!

      Delete
    2. The variable animation speed is achieved by setting the animation frame timer to a different initial value each time the current animation frame changes, based on the player's current ground velocity. I've edited the post to address this detail.

      Delete
  2. Just thought I'd add this here, despite this being an old blog post: not sure about sonic 2 but sonic 1 has a different animation for rolling

    SonAni_Roll: dc.b $FE, fr_Roll1, fr_Roll2, fr_Roll3, fr_Roll4, fr_Roll5, afEnd, afEnd
    even
    SonAni_Roll2: dc.b $FE, fr_Roll1, fr_Roll2, fr_Roll5, fr_Roll3, fr_Roll4, fr_Roll5, afEnd
    even

    the only difference is that it adds an extra frame in the middle, likely to make it seem more "blurry"

    ReplyDelete