Wednesday, August 9, 2017

You can now play as Failure Cresh

Last time, I mentioned how when you enter object placement mode, the game stores away player 1's mappings and art pointer to some RAM address off in the boonies. But if we take another look, we can see the latter actually isn't backed up all the time.
loc_92A20:
    addq.b  #2,(Debug_placement_mode).w
    move.l  $C(a0),($FFFFFFCA).w        ; save mappings to $FFCA
    cmpi.b  #6,5(a0)
    bhs.s   loc_92A38
    move.w  $A(a0),($FFFFFFCE).w        ; save art tile to $FFCE

loc_92A38:
    ...
Specifically, it checks if the player's routine byte is 6 or higher, and if so, doesn't back up the art tile. These just happen to be the states in which the player is dead; in particular routine 6 indicates that the player is bouncing up in their death frame, but hasn't reached the bottom of the screen yet.

Routine 6 is special because it has an escape hatch. If debug mode is available and the B button is pressed, the player can avoid death by entering object placement mode. Here's the code responsible for killing a player:
loc_1036E:
    clr.b   $2B(a0)
    clr.b   $37(a0)
    move.b  #6,5(a0)                    ; change player to death state
    move.w  d0,-(sp)
    jsr     (Player_TouchFloor).l
    move.w  (sp)+,d0
    bset    #1,$2A(a0)
    move.w  #-$700,$1A(a0)
    move.w  #0,$18(a0)
    move.w  #0,$1C(a0)
    move.b  #$18,$20(a0)
    move.w  $A(a0),($FFFFFFCE).w        ; save art tile to $FFCE
    bset    #7,$A(a0)                   ; set priority flag
    jsr     (Play_Sound_2).l
    
loc_103B6:
    moveq   #-1,d0
    rts
Recall that art tile is a VDP pattern index of the form PCCXYAAAAAAAAAAA, used as the base pattern index for every sprite of an object. Setting the high bit on the art tile effectively sets the player's sprite to high priority, so that it appears to "fall off the level" rather than disappear into the floor.

Due to routine 6's escape hatch, the current art tile is first saved to $FFCE. This ensures that if the player cheats death by entering object placement mode, then upon exiting it the player's priority will be restored to how it was pre-mortem. The normal backup on debug entry is thus skipped to avoid overwriting the one done here.

However, once again we have run into code which is not careful with the pattern bits. The entire pattern index is saved on death, rather than just the priority bit. This means that if the art tile currently has a dirty value, say, due to the player having died while in object placement mode, then it's actually the dirty value that's being saved.


All you have to do is pick your favorite item from the debug reel, and find something that can kill you even when you're in object placement mode, such as Big Arm, the frost cannons in Icecap Zone, or the tilting lava in the Lava Reef Zone boss act. When you die, the saved art tile at $FFCE gets replaced by the art tile of the debug item, which means once you exit debug mode, you can finally play the game as Failure Cresh.


This looks particularly nice when you jump or roll, since all the spinning frames are just single 4x4 mappings. It looks especially nice as Tails, since you'll still have his titular appendages sticking out.

1 comment:

  1. I found this glitch while playing Sonic 3 Complete, lol. In that hack, you can also do this by going into debug mode and then skipping the intro cutscene.

    ReplyDelete