From 60d70d0d38288e69c7f0def6694ae81eb9a0546f Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 15 May 2023 15:55:16 -0700 Subject: [PATCH] Fix several more possible crashes from the Lua API --- Makefile | 14 +++++++++++--- autogen/convert_structs.py | 2 +- data/dynos_mgr_anim.cpp | 3 +++ data/dynos_mgr_models.cpp | 9 +++++---- docs/lua/structs.md | 6 +++--- src/audio/playback.c | 1 + src/game/behaviors/bbh_merry_go_round.inc.c | 4 +++- src/game/behaviors/beta_boo_key.inc.c | 2 +- src/game/behaviors/beta_trampoline.inc.c | 2 +- src/game/behaviors/blue_coin.inc.c | 6 ++++-- src/game/behaviors/boo.inc.c | 2 +- src/game/behaviors/cannon.inc.c | 4 ++-- src/game/behaviors/chain_chomp.inc.c | 1 - src/game/behaviors/coin.inc.c | 2 +- src/game/behaviors/hidden_star.inc.c | 12 ++++++++---- src/game/behaviors/jrb_ship.inc.c | 16 +++++++++++----- src/game/behaviors/pole_base.inc.c | 10 ++++++---- src/game/behaviors/purple_switch.inc.c | 2 +- src/game/behaviors/red_coin.inc.c | 4 +++- src/game/behaviors/spawn_star.inc.c | 6 ++++-- src/game/behaviors/tower_platform.inc.c | 2 +- src/game/behaviors/ttc_treadmill.inc.c | 8 +++++++- src/game/camera.c | 2 +- src/game/mario.c | 3 ++- src/game/mario_actions_cutscene.c | 3 +-- src/game/mario_actions_moving.c | 1 + src/game/mario_actions_submerged.c | 1 + src/pc/lua/smlua_cobject_autogen.c | 6 +++--- 28 files changed, 87 insertions(+), 47 deletions(-) diff --git a/Makefile b/Makefile index 09352e6a..4a383184 100644 --- a/Makefile +++ b/Makefile @@ -952,9 +952,17 @@ ifeq ($(WINDOWS_BUILD),999) endif ifeq ($(ASAN),1) - EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb - EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb - LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan + + ifeq ($(COMPILER),gcc) + EXTRA_CFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb + EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -ggdb + LDFLAGS += -fsanitize=address -fsanitize=bounds-strict -fsanitize=undefined -static-libasan + else ifeq ($(COMPILER),clang) + EXTRA_CFLAGS += -fsanitize=address -fsanitize=undefined -ggdb + EXTRA_CPP_FLAGS += -fsanitize=address -fsanitize=undefined -ggdb + LDFLAGS += -fsanitize=address -fsanitize=undefined + endif + endif # Coop specific libraries diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index b5ba9af5..b87fbc85 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -93,7 +93,7 @@ override_field_immutable = { "GlobalObjectAnimations": [ "*"], "SpawnParticlesInfo": [ "model" ], "MarioBodyState": [ "updateTorsoTime" ], - "Area": [ "localAreaTimer", "nextSyncID", "unk04" ], + "Area": [ "localAreaTimer", "nextSyncID", "unk04", "objectSpawnInfos", "paintingWarpNodes", "warpNodes" ], "Mod": [ "*" ], "ModFile": [ "*" ], "BassAudio": [ "*" ], diff --git a/data/dynos_mgr_anim.cpp b/data/dynos_mgr_anim.cpp index 6e9fb54c..82840378 100644 --- a/data/dynos_mgr_anim.cpp +++ b/data/dynos_mgr_anim.cpp @@ -84,6 +84,9 @@ void DynOS_Anim_Swap(void *aPtr) { if (_AnimIndex == -1) { return; } + if (_AnimIndex >= _GfxData->mAnimationTable.Count()) { + return; + } // Animation data const AnimData *_AnimData = (const AnimData *) _GfxData->mAnimationTable[_AnimIndex].second; diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp index 1a9db6ac..afba8951 100644 --- a/data/dynos_mgr_models.cpp +++ b/data/dynos_mgr_models.cpp @@ -13,7 +13,8 @@ struct ScheduledFreePool { }; static struct DynamicPool* sModelPools[MODEL_POOL_MAX] = { 0 }; -static std::map sModelMap[MODEL_POOL_MAX]; +static std::map sGraphNodeMap[MODEL_POOL_MAX]; +static std::map sModelIdMap; static std::vector sPoolsToFree; struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) { @@ -26,7 +27,7 @@ struct GraphNode* DynOS_Model_LoadGeo(enum ModelPool aModelPool, void* aAsset) { } // check map - auto& map = sModelMap[aModelPool]; + auto& map = sGraphNodeMap[aModelPool]; if (map.count(aAsset)) { return map[aAsset]; } @@ -49,7 +50,7 @@ struct GraphNode* DynOS_Model_LoadDl(enum ModelPool aModelPool, u8 aLayer, void* } // check map - auto& map = sModelMap[aModelPool]; + auto& map = sGraphNodeMap[aModelPool]; if (map.count(aAsset)) { return map[aAsset]; } @@ -75,7 +76,7 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) { sModelPools[aModelPool] = NULL; // clear map - auto& map = sModelMap[aModelPool]; + auto& map = sGraphNodeMap[aModelPool]; map.clear(); } diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 7c285c27..caaa0e52 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -145,12 +145,12 @@ | nextSyncID | `integer` | read-only | | numRedCoins | `integer` | | | numSecrets | `integer` | | -| objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | | -| paintingWarpNodes | [WarpNode](structs.md#WarpNode) | | +| objectSpawnInfos | [SpawnInfo](structs.md#SpawnInfo) | read-only | +| paintingWarpNodes | [WarpNode](structs.md#WarpNode) | read-only | | surfaceRooms | `Pointer` <`integer`> | read-only | | terrainData | `Pointer` <`integer`> | read-only | | terrainType | `integer` | | -| warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | | +| warpNodes | [ObjectWarpNode](structs.md#ObjectWarpNode) | read-only | [:arrow_up_small:](#) diff --git a/src/audio/playback.c b/src/audio/playback.c index 1c2498fb..17703bed 100644 --- a/src/audio/playback.c +++ b/src/audio/playback.c @@ -1064,6 +1064,7 @@ void audio_list_push_front(struct AudioListItem *list, struct AudioListItem *ite } void audio_list_remove(struct AudioListItem *item) { + if (!item) { return; } // remove 'item' from the list it's in, if any if (item->prev == NULL) { eu_stubbed_printf_0("Already Cut\n"); diff --git a/src/game/behaviors/bbh_merry_go_round.inc.c b/src/game/behaviors/bbh_merry_go_round.inc.c index 628b6a3d..3f38561c 100644 --- a/src/game/behaviors/bbh_merry_go_round.inc.c +++ b/src/game/behaviors/bbh_merry_go_round.inc.c @@ -25,7 +25,9 @@ static void handle_merry_go_round_music(void) { struct Object *marioObject = gMarioObjects[0]; u16 marioFloorType = 0; - find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor); + if (marioObject) { + find_floor(marioObject->oPosX, marioObject->oPosY, marioObject->oPosZ, &marioFloor); + } if (marioFloor != NULL) { marioFloorType = marioFloor->type; diff --git a/src/game/behaviors/beta_boo_key.inc.c b/src/game/behaviors/beta_boo_key.inc.c index bdf33ac1..b8ab00f7 100644 --- a/src/game/behaviors/beta_boo_key.inc.c +++ b/src/game/behaviors/beta_boo_key.inc.c @@ -130,7 +130,7 @@ static void beta_boo_key_drop(void) { // Make the key move laterally away from Mario at 3 units/frame // (as if he transferred kinetic energy to it) - velocityDirection = gMarioObject->oMoveAngleYaw; + velocityDirection = gMarioObject ? gMarioObject->oMoveAngleYaw : 0; velocityMagnitude = 3.0f; o->oVelX = sins(velocityDirection) * velocityMagnitude; diff --git a/src/game/behaviors/beta_trampoline.inc.c b/src/game/behaviors/beta_trampoline.inc.c index 81013a21..ea206cc6 100644 --- a/src/game/behaviors/beta_trampoline.inc.c +++ b/src/game/behaviors/beta_trampoline.inc.c @@ -75,7 +75,7 @@ void bhv_beta_trampoline_top_loop(void) { // Since the trampoline never moves, this doesn't do anything. // Maybe they intended to decrease the trampoline's position // when Mario's on it in this if statement? - if (gMarioObject->platform == o) { + if (gMarioObject && gMarioObject->platform == o) { o->oBetaTrampolineMarioOnTrampoline = TRUE; } else { o->oBetaTrampolineMarioOnTrampoline = FALSE; diff --git a/src/game/behaviors/blue_coin.inc.c b/src/game/behaviors/blue_coin.inc.c index 4479e132..d826f638 100644 --- a/src/game/behaviors/blue_coin.inc.c +++ b/src/game/behaviors/blue_coin.inc.c @@ -135,7 +135,7 @@ void bhv_blue_coin_switch_loop(void) { case BLUE_COIN_SWITCH_ACT_IDLE: // If Mario is on the switch and has ground-pounded, // recede and get ready to start ticking. - if (gMarioObject->platform == o) { + if (gMarioObject && gMarioObject->platform == o) { if (determine_interaction(&gMarioStates[0], o) & INT_GROUND_POUND) { // Set to BLUE_COIN_SWITCH_ACT_RECEDING o->oAction++; @@ -164,7 +164,9 @@ void bhv_blue_coin_switch_loop(void) { // Set to BLUE_COIN_SWITCH_ACT_TICKING o->oAction++; // ??? - o->oPosY = gMarioObject->oPosY - 40.0f; + if (gMarioObject) { + o->oPosY = gMarioObject->oPosY - 40.0f; + } // Spawn particles. There's a function that calls this same function // with the same arguments, spawn_mist_particles, why didn't they just call that? diff --git a/src/game/behaviors/boo.inc.c b/src/game/behaviors/boo.inc.c index 45e4a960..d0a41a08 100644 --- a/src/game/behaviors/boo.inc.c +++ b/src/game/behaviors/boo.inc.c @@ -1029,7 +1029,7 @@ void bhv_boo_in_castle_loop(void) { } void bhv_boo_boss_spawned_bridge_loop(void) { - f32 targetY; + f32 targetY = 0; switch (o->oBehParams2ndByte) { case 1: diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index 8fa3887c..1f147c50 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -75,7 +75,7 @@ void opened_cannon_act_6(void) { o->oMoveAngleYaw = sins(o->oCannonUnkF4) * 0x4000 + ((s16)(o->oBehParams2ndByte << 8)); o->oCannonUnkF4 += 0x400; } else if (o->oTimer < 26) { - } else if (o->oCannonPlayerIndex < MAX_PLAYERS) { + } else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) { struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; if (controlledBy && controlledBy->marioObj != NULL) { controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; @@ -110,7 +110,7 @@ void opened_cannon_act_1(void) { if (o->oCannonPlayerIndex == 0) { cur_obj_become_intangible(); cur_obj_disable_rendering(); - } else if (o->oCannonPlayerIndex < MAX_PLAYERS) { + } else if (o->oCannonPlayerIndex >= 0 && o->oCannonPlayerIndex < MAX_PLAYERS) { struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; o->oMoveAnglePitch = 14563 + controlledBy->faceAngle[0] * -0.5f; if (controlledBy->marioObj != NULL) { diff --git a/src/game/behaviors/chain_chomp.inc.c b/src/game/behaviors/chain_chomp.inc.c index 9d7e990f..36821515 100644 --- a/src/game/behaviors/chain_chomp.inc.c +++ b/src/game/behaviors/chain_chomp.inc.c @@ -450,7 +450,6 @@ static void chain_chomp_act_move(void) { */ static void chain_chomp_act_unload_chain(void) { cur_obj_hide(); - dynamic_pool_free(gLevelPool, o->oChainChompSegments); o->oAction = CHAIN_CHOMP_ACT_UNINITIALIZED; diff --git a/src/game/behaviors/coin.inc.c b/src/game/behaviors/coin.inc.c index aa3f40ce..3f93a3cd 100644 --- a/src/game/behaviors/coin.inc.c +++ b/src/game/behaviors/coin.inc.c @@ -244,7 +244,7 @@ void coin_inside_boo_act_0(void) { obj_copy_pos(o, parent); if (parent->oBooDeathStatus == BOO_DEATH_STATUS_DYING) { o->oAction = 1; - s16 sp26 = gMarioObject->oMoveAngleYaw; + s16 sp26 = gMarioObject ? gMarioObject->oMoveAngleYaw : 0; f32 sp20 = 3.0f; o->oVelX = sins(sp26) * sp20; o->oVelZ = coss(sp26) * sp20; diff --git a/src/game/behaviors/hidden_star.inc.c b/src/game/behaviors/hidden_star.inc.c index 2d4a269a..eaad5afc 100644 --- a/src/game/behaviors/hidden_star.inc.c +++ b/src/game/behaviors/hidden_star.inc.c @@ -8,7 +8,9 @@ void bhv_hidden_star_init(void) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } - o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; + if (gCurrentArea) { + o->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; + } // We haven't interacted with a player yet. // We also don't sync this as not only is it not required @@ -34,7 +36,7 @@ void bhv_hidden_star_init(void) { void bhv_hidden_star_loop(void) { switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) { + if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numSecrets) { o->oAction = 1; } break; @@ -63,7 +65,9 @@ void bhv_hidden_star_trigger_loop(void) { if (hiddenStar != NULL) { s16 count = (count_objects_with_behavior(bhvHiddenStarTrigger) - 1); - hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; + if (gCurrentArea) { + hiddenStar->oHiddenStarTriggerCounter = gCurrentArea->numSecrets - count; + } spawn_orange_number(hiddenStar->oHiddenStarTriggerCounter, 0, 0, 0); // Set the last person who interacted with a secret to the @@ -98,7 +102,7 @@ void bhv_hidden_star_trigger_loop(void) { void bhv_bowser_course_red_coin_star_loop(void) { switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { + if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { o->oAction = 1; } break; diff --git a/src/game/behaviors/jrb_ship.inc.c b/src/game/behaviors/jrb_ship.inc.c index 4936a6a7..7db56849 100644 --- a/src/game/behaviors/jrb_ship.inc.c +++ b/src/game/behaviors/jrb_ship.inc.c @@ -39,8 +39,9 @@ void bhv_ship_part_3_loop(void) { o->oFaceAngleRoll = sins(o->oShipPart3UnkF8) * 1024.0f; o->oAngleVelPitch = o->oFaceAnglePitch - sp1E; o->oAngleVelRoll = o->oFaceAngleRoll - sp1C; - if (gMarioObject->oPosY > 1000.0f) + if (gMarioObject && gMarioObject->oPosY > 1000.0f) { cur_obj_play_sound_1(SOUND_ENV_BOAT_ROCKING1); + } } void bhv_jrb_sliding_box_loop(void) { @@ -103,13 +104,18 @@ void bhv_jrb_sliding_box_loop(void) { o->oJrbSlidingBoxUnkFC = sins(o->oJrbSlidingBoxUnkF8) * 20.0f; o->oJrbSlidingBoxUnkF8 += 0x100; o->oParentRelativePosZ += o->oJrbSlidingBoxUnkFC; - if (gMarioObject->oPosY > 1000.0f) - if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f) + if (gMarioObject && gMarioObject->oPosY > 1000.0f) { + if (absf(o->oJrbSlidingBoxUnkFC) > 3.0f) { cur_obj_play_sound_1(SOUND_AIR_ROUGH_SLIDE); + } + } + obj_set_hitbox(o, &sSkullSlidingBoxHitbox); - if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF)) + if (!(o->oJrbSlidingBoxUnkF8 & 0x7FFF)) { cur_obj_become_tangible(); - if (obj_check_if_collided_with_object(o, gMarioObject)) { + } + + if (gMarioObject && obj_check_if_collided_with_object(o, gMarioObject)) { o->oInteractStatus = 0; cur_obj_become_intangible(); } diff --git a/src/game/behaviors/pole_base.inc.c b/src/game/behaviors/pole_base.inc.c index 0929d4e5..7c3e0c28 100644 --- a/src/game/behaviors/pole_base.inc.c +++ b/src/game/behaviors/pole_base.inc.c @@ -2,9 +2,11 @@ void bhv_pole_base_loop(void) { if (!gMarioObject) { return; } - if (o->oPosY - 10.0f < gMarioObject->oPosY - && gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) - if (o->oTimer > 10) - if (!(gMarioStates[0].action & MARIO_PUNCHING)) + if (o->oPosY - 10.0f < gMarioObject->oPosY && gMarioObject->oPosY < o->oPosY + o->hitboxHeight + 30.0f) { + if (o->oTimer > 10) { + if (!(gMarioStates[0].action & MARIO_PUNCHING)) { cur_obj_push_mario_away(70.0f); + } + } + } } diff --git a/src/game/behaviors/purple_switch.inc.c b/src/game/behaviors/purple_switch.inc.c index 662df4a7..c0b58cef 100644 --- a/src/game/behaviors/purple_switch.inc.c +++ b/src/game/behaviors/purple_switch.inc.c @@ -31,7 +31,7 @@ void bhv_purple_switch_loop(void) { case PURPLE_SWITCH_IDLE: cur_obj_set_model(smlua_model_util_load(E_MODEL_PURPLE_SWITCH)); cur_obj_scale(1.5f); - if (gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) { + if (gMarioObject && gMarioObject->platform == o && !(gMarioStates[0].action & MARIO_UNKNOWN_13)) { if (lateral_dist_between_objects(o, gMarioObject) < 127.5) { o->oAction = PURPLE_SWITCH_PRESSED; network_send_object(o); diff --git a/src/game/behaviors/red_coin.inc.c b/src/game/behaviors/red_coin.inc.c index 7ffa8080..1650cd9b 100644 --- a/src/game/behaviors/red_coin.inc.c +++ b/src/game/behaviors/red_coin.inc.c @@ -50,7 +50,9 @@ void bhv_red_coin_loop(void) { // ...and there is a red coin star in the level... if (o->parentObj != NULL) { s16 redCoins = count_objects_with_behavior(bhvRedCoin) - 1; - o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; + if (gCurrentArea) { + o->parentObj->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; + } // Set the last person who interacted with a red coin to the // parent so only they get the star cutscene. diff --git a/src/game/behaviors/spawn_star.inc.c b/src/game/behaviors/spawn_star.inc.c index 38940d98..9bda024d 100644 --- a/src/game/behaviors/spawn_star.inc.c +++ b/src/game/behaviors/spawn_star.inc.c @@ -288,7 +288,9 @@ void bhv_hidden_red_coin_star_init(void) { o->activeFlags = ACTIVE_FLAG_DEACTIVATED; } - o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; + if (gCurrentArea) { + o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; + } // We haven't interacted with a player yet. // We also don't sync this as not only is it not required @@ -313,7 +315,7 @@ void bhv_hidden_red_coin_star_init(void) { void bhv_hidden_red_coin_star_loop(void) { switch (o->oAction) { case 0: - if (o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { + if (gCurrentArea && o->oHiddenStarTriggerCounter >= gCurrentArea->numRedCoins) { o->oAction = 1; } break; diff --git a/src/game/behaviors/tower_platform.inc.c b/src/game/behaviors/tower_platform.inc.c index 592a7461..5856e1f7 100644 --- a/src/game/behaviors/tower_platform.inc.c +++ b/src/game/behaviors/tower_platform.inc.c @@ -21,7 +21,7 @@ void bhv_wf_elevator_tower_platform_loop(void) { switch (o->oAction) { case 0: - if (gMarioObject->platform == o) { + if (gMarioObject && gMarioObject->platform == o) { o->oAction++; network_send_object(o); } diff --git a/src/game/behaviors/ttc_treadmill.inc.c b/src/game/behaviors/ttc_treadmill.inc.c index bf269014..9394e7da 100644 --- a/src/game/behaviors/ttc_treadmill.inc.c +++ b/src/game/behaviors/ttc_treadmill.inc.c @@ -66,7 +66,13 @@ void bhv_ttc_treadmill_update(void) { approach_f32_ptr(&o->oTTCTreadmillSpeed, o->oTTCTreadmillTargetSpeed, 10.0f); } - *o->oTTCTreadmillBigSurface = *o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed; + if (o->oTTCTreadmillSmallSurface) { + *o->oTTCTreadmillSmallSurface = o->oTTCTreadmillSpeed; + } + + if (o->oTTCTreadmillBigSurface) { + *o->oTTCTreadmillBigSurface = o->oTTCTreadmillSpeed; + } } } diff --git a/src/game/camera.c b/src/game/camera.c index a88d7ce1..944de05b 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -5429,7 +5429,7 @@ void warp_camera(f32 displacementX, f32 displacementY, f32 displacementZ) { struct LinearTransitionPoint *start = &sModeInfo.transitionStart; struct LinearTransitionPoint *end = &sModeInfo.transitionEnd; - gCurrLevelArea = gCurrLevelNum * 16 + gCurrentArea->index; + gCurrLevelArea = gCurrLevelNum * 16 + (gCurrentArea ? gCurrentArea->index : 0); displacement[0] = displacementX; displacement[1] = displacementY; displacement[2] = displacementZ; diff --git a/src/game/mario.c b/src/game/mario.c index 49b01421..e6e38481 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -865,6 +865,7 @@ void update_mario_sound_and_camera(struct MarioState *m) { // only update for local player if (m != &gMarioStates[0]) { return; } + if (!m->area || !m->area->camera) { return; } u32 action = m->action; s32 camPreset = m->area->camera->mode; @@ -1332,7 +1333,7 @@ s32 check_common_hold_action_exits(struct MarioState *m) { */ s32 transition_submerged_to_walking(struct MarioState *m) { if (!m) { return FALSE; } - if (m->playerIndex == 0) { + if (m->playerIndex == 0 && m->area && m->area->camera) { set_camera_mode(m->area->camera, m->area->camera->defMode, 1); } diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 8e001ebd..66e409be 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -3049,8 +3049,7 @@ static s32 check_for_instant_quicksand(struct MarioState *m) { } if (m->action == ACT_BUBBLED) { return FALSE; } - if (m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE - && m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) { + if (m->floor && m->floor->type == SURFACE_INSTANT_QUICKSAND && m->action & ACT_FLAG_INVULNERABLE && m->action != ACT_QUICKSAND_DEATH && m->action != ACT_SHOCKED) { update_mario_sound_and_camera(m); return drop_and_set_mario_action(m, ACT_QUICKSAND_DEATH, 0); } diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index daa70000..5139c506 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -696,6 +696,7 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) { break; default: + val08 = FALSE; break; } } diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index 139eed82..e7dd1df4 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -147,6 +147,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) { step[2] += currentSpeed * coss(currentAngle); } + if (!gCurrentArea) { return; } for (i = 0; i < 2; i++) { struct Whirlpool *whirlpool = gCurrentArea->whirlpools[i]; if (whirlpool != NULL) { diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index a0df0c44..fb3e18b2 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -72,14 +72,14 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { { "nextSyncID", LVT_U32, offsetof(struct Area, nextSyncID), true, LOT_NONE }, { "numRedCoins", LVT_U8, offsetof(struct Area, numRedCoins), false, LOT_NONE }, { "numSecrets", LVT_U8, offsetof(struct Area, numSecrets), false, LOT_NONE }, - { "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), false, LOT_SPAWNINFO }, - { "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), false, LOT_WARPNODE }, + { "objectSpawnInfos", LVT_COBJECT_P, offsetof(struct Area, objectSpawnInfos), true, LOT_SPAWNINFO }, + { "paintingWarpNodes", LVT_COBJECT_P, offsetof(struct Area, paintingWarpNodes), true, LOT_WARPNODE }, { "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER }, { "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER }, { "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE }, // { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED // { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED - { "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE }, + { "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), true, LOT_OBJECTWARPNODE }, // { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED };