Wednesday, November 8, 2017

Unsafe cylinder DPLC, part 3: flipping the tables

Okay, this is a good one. While writing yesterday's post, I had to look at the code for the RideObject_SetRide function, and I came across this gem, right at the start:
RideObject_SetRide:
    btst    #3,$2A(a1)
    beq.s   loc_1E4A0
    movea.w $42(a1),a3
    bclr    d6,$2A(a3)

loc_1E4A0:
    move.w  a0,$42(a1)
    ...
We've seen this before. Bit 3 of the player's status bitfield is the "standing on object" flag. When the player lands on an object that's using the SolidObjectFull function, the object sets this bit and copies the address of its own SST to offset $42 of the player's SST. It also sets bit 3 or 4 of its own SST, depending on which player landed on it.

The code at loc_1E4A0 above wants to do the same, but before it can do so, it needs to check whether the player was already standing on another object, and if so, clear bit 3 or 4 of its SST. Which bit it clears is indicated by register d6.

You can already tell where this is going.

If both players are riding the same vertical cylinder object, and the object changes player 1's mapping frame, player 2's handler runs with d6 erroneously set to 1, which corresponds to the vertical flip flag in the object's status bitfield.

Time to put the pieces together. If player 2 is standing on a solid object, player 1 is riding a cylinder, and player 2 starts riding the cylinder at the exact same time that the cylinder object changes player 1's mapping frame, player 2's handler will call RideObject_SetRide with d6 set to 1, clearing the vertical flip flag of the object player 2 was standing on.

At least that was the theory. If the object player 2 was standing on just happened to be upside down...


I love this game so damn much.

3 comments:

  1. At first, I only saw that the platform flipped right-side-up, but eventually it clicked that Tails entering the cylinder kicked Sonic out.

    Is there any location that this can be seen without Debug Mode?

    ReplyDelete
    Replies
    1. Tails didn't "kick Sonic out", I just jumped out to show the platform.

      I just found the bug two days ago, so I don't know of any place you can do it without debug. Would be really cool, though.

      Delete
    2. Oh, okay. There's sleuthing to be done...

      Delete