From 3cf0d063ce0caa1de7c81cdc22a378789b8b723d Mon Sep 17 00:00:00 2001 From: MegaMech Date: Sat, 25 Jan 2025 11:34:40 -0700 Subject: [PATCH] Fix overflow with tyreSpeed (#170) * Fix tyreSpeed overflow and avoid ub --- include/common_structs.h | 2 +- src/player_controller.c | 2 +- src/render_player.c | 43 +++++++++++++++++++++++----------------- 3 files changed, 27 insertions(+), 20 deletions(-) diff --git a/include/common_structs.h b/include/common_structs.h index db8e189c9..8ae06ea1e 100644 --- a/include/common_structs.h +++ b/include/common_structs.h @@ -361,7 +361,7 @@ typedef struct { /* 0x0238 */ s16 unk_238; /* 0x023A */ s16 unk_23A; /* 0x023C */ f32 unk_23C; - /* 0x0240 */ s32 unk_240; + /* 0x0240 */ s32 tyreSpeed; /* 0x0244 */ u16 animFrameSelector[4]; // [0] Active texture group /* 0x024C */ u16 animGroupSelector[4]; // Based on screen /* 0x0254 */ u16 characterId; diff --git a/src/player_controller.c b/src/player_controller.c index fa0d53c13..f5a269527 100644 --- a/src/player_controller.c +++ b/src/player_controller.c @@ -2027,7 +2027,7 @@ void func_8002D028(Player* player, s8 arg1) { player->unk_08C = 0; player->unk_094 = 0; player->unk_104 = 0; - player->unk_240 = 0; + player->tyreSpeed = 0; player->unk_07C = 0; player->velocity[0] = 0; player->velocity[1] = 0; diff --git a/src/render_player.c b/src/render_player.c index 4aa6e01b8..1c4d78a7e 100644 --- a/src/render_player.c +++ b/src/render_player.c @@ -1956,23 +1956,30 @@ void render_player(Player* player, s8 playerId, s8 screenId) { void func_80026A48(Player* player, s8 arg1) { f32 temp_f0; - if (((player->effects & 0x4000) == 0x4000) && ((player->type & PLAYER_START_SEQUENCE) == 0)) { - player->unk_240 += D_800DDE74[8]; - if (player->unk_240 >= 0x400) { - player->unk_240 = 0; + player->tyreSpeed += D_800DDE74[8]; + if (player->tyreSpeed >= 0x400) { + player->tyreSpeed = 0; } return; } - temp_f0 = ((player->unk_094 * (1.0f + player->unk_104)) / 18.0f) * 216.0f; + if ((temp_f0 <= 1.0f) || (gIsPlayerTripleBButtonCombo[arg1] == true)) { - player->unk_240 = 0; + player->tyreSpeed = 0; } else { - player->unk_240 += D_800DDE74[(s32) (temp_f0 / 12.0f)]; + s32 temp = (s32) (temp_f0 / 12.0f); + //! @warning This condition prevents an array overflow. + // It's possible on hardware the tyres stop spinning despite that the player is still moving. + // This prevents that overflow/bug + // The ARRAY_COUNT is so if D_800DDE74 is changed, this fix automatically adjusts to the new size. + if (temp >= ARRAY_COUNT(D_800DDE74)) { + temp = ARRAY_COUNT(D_800DDE74) - 1; + } + player->tyreSpeed += D_800DDE74[temp]; } - if (player->unk_240 >= 0x400) { - player->unk_240 = 0; + if (player->tyreSpeed >= 0x400) { + player->tyreSpeed = 0; } } @@ -1986,7 +1993,7 @@ void func_80026A48(Player* player, s8 arg1) { void update_wheel_palette(Player* player, s8 playerId, s8 screenId, s8 arg3) { s16 frameId = gLastAnimFrameSelector[screenId][playerId]; s16 groupId = gLastAnimGroupSelector[screenId][playerId]; - s16 temp_t2 = player->unk_240; + s16 tyreSpeed = player->tyreSpeed; s16 temp_num = 0x40; // setting this as a variable gets rid of regalloc u8 character = player->characterId; @@ -1999,21 +2006,21 @@ void update_wheel_palette(Player* player, s8 playerId, s8 screenId, s8 arg3) { ((player->effects & 0x800000) != 0x800000) && ((player->unk_044 & 0x800) == 0)) { if (frameId <= 20) { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel0 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } else { - int32_t offset = (((((frameId - 21) * (temp_num * 4) + ((temp_t2 >> 8) * 0x40)) + 0x600)) * 2) / 0x80; + int32_t offset = (((((frameId - 21) * (temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) + 0x600)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel1 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } } else { if (frameId == 0) { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel0 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } else { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel1 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } @@ -2024,22 +2031,22 @@ void update_wheel_palette(Player* player, s8 playerId, s8 screenId, s8 arg3) { ((player->effects & 0x20000) != 0x20000) && ((player->unk_044 & 0x800) == 0)) { if (frameId <= 20) { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel0 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } else { - int32_t offset = (((((frameId - 21) * (temp_num * 4) + ((temp_t2 >> 8) * 0x40)) + 0x600)) * 2) / 0x80; + int32_t offset = (((((frameId - 21) * (temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) + 0x600)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel1 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } } else { if (frameId == 0) { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel0 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); } else { - int32_t offset = (((frameId * temp_num * 4) + ((temp_t2 >> 8) * 0x40)) * 2) / 0x80; + int32_t offset = (((frameId * temp_num * 4) + ((tyreSpeed >> 8) * 0x40)) * 2) / 0x80; load_wheel_palette_non_blocking(player, wheelPtr[character][wheel1 + offset], D_802F1F80_WHEEL(arg3, screenId, playerId), 0x80); }