Friday, July 14, 2017

S monitor blues

Brainulator9 commented on my previous post regarding S monitors:
Does this also work with Tails and Knuckles? In fact, how come Knuckles doesn't shockwave when using an S monitor.
It can also happens with Tails because the monitor loads the super birds object, and like the hyper stars object, the first thing it does is load the super bird art which, you guessed it, is in KosM format.
Obj_HyperTails_Birds:
    lea     (ArtKosM_SuperTailsBirds).l,a1
    move.w  #$D000,d2
    jsr     (Queue_Kos_Module).l
    ...
Knuckles doesn't make shockwaves when you turn Hyper from an S box because he's not really Hyper, he's just Super. Try jumping in water: he'll still blow bubbles and drown if you leave him there long enough. But how can that be, he has the afterimages and everything!

Turns out the S monitor has its own super transformation code, cobbled up from the code that runs when you transform normally. It is also hastily edited from the original Sonic 3 monitor code, which only turned you Super. And to show how slapped together the code is, here it is in its unabridged form. Relevant bits highlighted by me.
Monitor_Give_SuperSonic:
    addq.w  #1,(a2)
    addi.w  #50,(Ring_count).w
    move.b  #1,(Super_Hyper_palette_status).w
    move.b  #$F,(Palette_timer).w
    move.b  #1,(Super_Sonic_Knux_flag).w
    move.w  #60,(Super_Hyper_frame_count).w
    move.w  #$800,(Sonic_Knux_top_speed).w
    move.w  #$18,(Sonic_Knux_acceleration).w
    move.w  #$C0,(Sonic_Knux_deceleration).w
    move.b  #$1F,(Player_1+anim).w
    cmpi.w  #2,(Player_mode).w
    bne.s   loc_1DACE
    move.b  #0,(Super_Sonic_Knux_flag).w
    move.b  #1,(Super_Tails_flag).w
    move.b  #$29,(Player_1+anim).w
    move.w  #$800,(Tails_top_speed).w
    move.w  #$18,(Tails_acceleration).w
    move.w  #$C0,(Tails_deceleration).w
    move.l  #Obj_HyperTails_Birds,(Hyper_Sonic_stars).w
    bra.s   loc_1DB0A
; ---------------------------------------------------------------------------

loc_1DACE:
    bhs.s   loc_1DB02
    move.l  #Map_SuperSonic,(Player_1+mappings).w
    move.b  #-1,(Super_Sonic_Knux_flag).w
    move.w  #$A00,(Sonic_Knux_top_speed).w
    move.w  #$30,(Sonic_Knux_acceleration).w
    move.w  #$100,(Sonic_Knux_deceleration).w
    move.l  #Obj_HyperSonic_Stars,(Hyper_Sonic_stars).w
    move.l  #Obj_HyperSonicKnux_Trail,(Super_stars).w
    bra.s   loc_1DB0A
; ---------------------------------------------------------------------------

loc_1DB02:
    move.l  #Obj_HyperSonicKnux_Trail,(Super_stars).w

loc_1DB0A:
    move.b  #$81,(Player_1+object_control).w
    move.b  #0,(Player_1+invincibility_timer).w
    bset    #Status_Invincible,status_secondary(a1)
    moveq   #$9F,d0
    jsr     (Play_Sound_2).l
    moveq   #$2C,d0
    jmp     (Play_Sound).l
First, notice the Super Sonic flag is set to 1, signaling a super transformation, which is leftover code from Sonic 3. After it sets up Knuckles' speed values for some reason, notice Tails' code sets the Super Sonic flag back to 0, and then sets the actual Super Tails flag to 1. It also loads up the super birds object, and leaves Knuckles' values lying around for the non-existent second player.

Sonic's code then sets the Super Sonic flag to -1 signaling a hyper transformation, and proceeds to overwrite Knuckles' speed values with Sonic's. It also replaces the super birds with the hyper stars object, and then loads up the afterimage object to a separate slot.

Knuckles' code only sets up the afterimage object, inheriting everything else from the code at the very top. This means he does eventually receive the correct speed values, but notice the Super Sonic flag was never changed from 1, which causes him to turn Super as in Sonic 3, while still keeping his afterimages.

In the developers' defense, it's not immediately apparent that anything is wrong. After all, the question was why Hyper Knuckles doesn't make shockwaves, not why Super Knuckles has afterimages. It would be far easier to notice a yellow Hyper Sonic, or Super Tails without any birds.

Finally, the S monitor is just a cheat. It's okay for it to be buggy and cheaply made. Copy-pasting code is easy and fast, whereas wiring it to the game's core routines would've been needlessly risky and time-consuming.

And hey, they did fix the whistling sound.

5 comments:

  1. That actually makes a lot of sense. The interesting thing about Hyper Knuckles is that he does a shockwave in the 0517 prototype when hitting an S monitor.

    ReplyDelete
  2. The monitor code is no different in the 0517 proto, so if Knuckles causes quakes there it's because Super Knuckles in general causes quakes in that prototype.

    ReplyDelete
    Replies
    1. I checked the 0517 prototype, and the Chaos Emeralds seem to give a broken form of hyper transformations, including Super Knuckles with shockwaves and Hyper Sonic without underwater breathing (oh, and Super Tails without birds). The actual hyper forms were behind the S monitor as they are in the final version. My phrasing of the situation actually comes from the Sonic Retro wiki pages on the 0517 proto and Sonic 3 Complete. I would fix them, but I cannot edit the wiki for some reason...

      Delete
  3. so what happens if you hack the game so you play as knuckles and tails or something? does tails get anything when knuckles hits the monitor or am i just misinterpreting?

    ReplyDelete
    Replies
    1. You're close, but it's actually the other way around. If Tails broke the monitor and there was somehow a Sonic or Knuckles object running around, then it would start using Super Knuckles' speed values.

      But the simplest way to test it would be to start a game as either Sonic or Knuckles, and then force the Player_mode RAM variable to 2. Upon breaking an S monitor, you should receive Super Knuckles' speed values, but fail to actually transform because the Super_Sonic_Knux_flag RAM variable remains cleared.

      Delete