Thursday, January 25, 2018

Why do the S monitors in S3A turn Tails into a block of mush?

Several weird things happen when Tails breaks open an S monitor in S3A. First off, he takes on this ungodly scrambled appearance, all while not receiving the customary 50 rings.


Then, although he does become invincible, his speed isn't increased, nor are rings ever drained from his count. He also doesn't glow at all, though by defeating some enemies, we can verify that Flickies still become yellow.


So what's going on here? Well, the short version is that Super Tails simply doesn't exist yet. To get into the nitty-gritty of it however, we need to take a look at the Monitor_Give_SuperSonic function in S3A.

As we previously saw, in S&K this function is broken up into three distinct code paths, and which path is taken depends on the player's current character. In S3A though, the same function is completely linear, which creates some interesting differences in its behavior when playing as Tails. S3A to the left, S&K to the right:
Monitor_Give_SuperSonic:                                Monitor_Give_SuperSonic:
    addq.w  #1,(a2)                                         addq.w  #1,(a2)
    addi.w  #50,(Ring_count).w                              addi.w  #50,(Ring_count).w
    move.b  #1,(Super_Hyper_palette_status).w               move.b  #1,(Super_Hyper_palette_status).w
    move.b  #$F,(Palette_timer).w                           move.b  #$F,(Palette_timer).w
    move.b  #1,(Super_Sonic_Knux_flag).w                    move.b  #1,(Super_Sonic_Knux_flag).w
    move.w  #60,(Super_Hyper_frame_count).w                 move.w  #60,(Super_Hyper_frame_count).w
    move.l  #Map_SuperSonic,(Player_1+mappings).w           ...
    move.b  #$81,(Player_1+object_control).w                move.b  #1,(Super_Tails_flag).w
    move.b  #$1F,(Player_1+anim).w                          move.b  #$29,(Player_1+anim).w
    move.l  #Obj_SuperSonic_Stars,(Super_stars).w
    move.w  #$A00,(Sonic_Knux_top_speed).w                  move.w  #$800,(Tails_top_speed).w
    move.w  #$30,(Sonic_Knux_acceleration).w                move.w  #$18,(Tails_acceleration).w
    move.w  #$100,(Sonic_Knux_deceleration).w               move.w  #$C0,(Tails_deceleration).w
                                                            move.l  #Obj_HyperTails_Birds,(Hyper_Sonic_stars).w
                                                            ...
                                                            move.b  #$81,(Player_1+object_control).w
    move.b  #0,(Player_1+invincibility_timer).w             move.b  #0,(Player_1+invincibility_timer).w
    bset    #Status_Invincible,status_secondary(a1)         bset    #Status_Invincible,status_secondary(a1)
    moveq   #$46,d0                                         moveq   #$9F,d0
    jsr     (Play_Sound_2).l                                jsr     (Play_Sound_2).l
    moveq   #$2C,d0                                         moveq   #$2C,d0
    jmp     (Play_Sound).l                                  jmp     (Play_Sound).l

First off, both versions of the function add 50 rings to the Ring_count RAM variable, no change there. In S3A however, Tails actually uses the Ring_count_P2 variable, a holdover from Sonic 2's 2P mode in which each character kept track of their own ring count. This accounts for Tails' unchanging ring count.

Next, S3A replaces player 1's mappings with the mappings for Super Sonic. In S&K, Sonic is the only character whose sprites change for his super form; S3A assumes that only Sonic will ever turn super, therefore the player should always receive the new mappings. This results in Tails' corrupted appearance.

Only S&K sets what would become the Super_Tails_flag, enabling Super Tails' rotating palette. However, both games set the Super_Sonic_Knux_flag, which enables Super Sonic's rotating palette and makes Flickies turn yellow.

S3A only writes Super Sonic's speed values to Sonic's speed variables, leaving Tails' values unaffected. And finally, as we've seen before, rather than play the regular transformation sound, S3A monitors play a whistling sound instead.


The sprite corruption can be avoided with debug mode. When the player enters debug mode, their mappings are saved to RAM address $FFCA, so they can be restored upon exiting the mode. By waiting out the transformation sequence in debug mode, Tails' old mappings are kept safe at $FFCA and will undo the damage done by the S monitor.

1 comment:

  1. He does turn golden in the end if you break an S monitor during the game, it seems.

    ReplyDelete