Skip to content

Commit

Permalink
Fix crash in the PGZ2 outro.
Browse files Browse the repository at this point in the history
Ohhhhhhh where the hell do I begin with this...

Okay, so, if you complete PGZ2 while playing without Tails or
Knuckles as a sidekick and while you have a Fire Shield, then the
game will crash during the cutscene right when the first 'pulse' of
the Phantom Ruby happens.

This is caused by the shield being loaded into player 2's object
slot. The cutscene tries to update both players, mistaking the shield
for the sidekick character. This causes it to overwrite the shield's
state with player state, causing the shield player pointer to be
replaced with a pointer to a player object function. This would cause
the shield object's update function to crash the game.

The original code was able to tell that the second player slot had a
shield in it by comparing its classID to that of the first player,
but this decompilation got this incorrect and instead merely checked
that the slot wasn't empty. It also redundantly checked if the
pointer to the slot was `NULL`, which is impossible.

Correcting this fixes the crash. Good riddance, too: that bug's been
driving me crazy for over a month! I thought I'd fixed it in this
PR...

Rubberduckycooly/RSDKv5-Decompilation#111

...but it turns out that I'd just fixed a completely unrelated bug
that, at the time, was crashing my MinGW builds.

Because the conditions to trigger this bug were so specific (have a
Fire Shield, and don't have Tails or Knuckles as a companion), I
never figured out how to consistently recreate this crash until now.

Aaaaaaaaaaaaaaaaaaaaa.
  • Loading branch information
Clownacy committed Oct 9, 2022
1 parent 99fd79e commit d9fac7a
Showing 1 changed file with 1 addition and 1 deletion.
2 changes: 1 addition & 1 deletion SonicMania/Objects/PGZ/PSZ2Outro.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,7 +233,7 @@ bool32 PSZ2Outro_Cutscene_RubyWarp(EntityCutsceneSeq *host)
int32 id = 0;
for (int32 angle = 0; angle < 0x80; angle += 0x40) {
EntityPlayer *player = RSDK_GET_ENTITY(id++, Player);
if (!player || player->classID == TYPE_BLANK)
if (player->classID != Player->classID)
break;

RSDK.SetSpriteAnimation(player->aniFrames, ANI_FAN, &player->animator, false, 0);
Expand Down

0 comments on commit d9fac7a

Please sign in to comment.