From ed163203d8da35e39e245fa36f4fbf6e9d25687b Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 15 May 2023 12:04:07 -0700 Subject: [PATCH] Make gEnvironmentRegions safer --- src/engine/surface_collision.c | 2 ++ src/engine/surface_load.c | 8 ++++++-- src/game/behaviors/moat_drainer.inc.c | 4 ++-- src/game/behaviors/thi_top.inc.c | 7 ++++--- src/game/behaviors/treasure_chest.inc.c | 2 +- src/game/behaviors/water_pillar.inc.c | 2 +- src/game/behaviors/wdw_water_level.inc.c | 12 ++++++++---- src/game/moving_texture.c | 9 +++++++-- src/game/obj_behaviors.c | 2 +- src/game/object_list_processor.c | 1 + src/game/object_list_processor.h | 1 + src/pc/lua/utils/smlua_misc_utils.c | 10 ++++++---- src/pc/network/packets/packet_area.c | 2 +- 13 files changed, 41 insertions(+), 21 deletions(-) diff --git a/src/engine/surface_collision.c b/src/engine/surface_collision.c index 4dcb0ad2..6bff4a5c 100644 --- a/src/engine/surface_collision.c +++ b/src/engine/surface_collision.c @@ -889,6 +889,7 @@ f32 find_water_level(f32 x, f32 z) { s16 val; f32 loX, hiX, loZ, hiZ; f32 waterLevel = gLevelValues.floorLowerLimit; + if (!gEnvironmentRegions) { return waterLevel; } s16 *p = gEnvironmentRegions; if (p != NULL) { @@ -925,6 +926,7 @@ f32 find_poison_gas_level(f32 x, f32 z) { s16 val; f32 loX, hiX, loZ, hiZ; f32 gasLevel = gLevelValues.floorLowerLimit; + if (!gEnvironmentRegions) { return gasLevel; } s16 *p = gEnvironmentRegions; if (p != NULL) { diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index b6631e23..037e847e 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -47,8 +47,6 @@ static struct SurfaceNode *alloc_surface_node(void) { struct SurfaceNode *node = &sSurfaceNodePool[gSurfaceNodesAllocated]; gSurfaceNodesAllocated++; - node->next = NULL; - //! A bounds check! If there's more surface nodes than 7000 allowed, // we, um... // Perhaps originally just debug feedback? @@ -59,6 +57,8 @@ static struct SurfaceNode *alloc_surface_node(void) { gSurfacePoolError &= ~NOT_ENOUGH_ROOM_FOR_NODES; } + node->next = NULL; + return node; } @@ -515,8 +515,10 @@ static void load_environmental_regions(s16 **data) { s32 numRegions; s32 i; + gEnvironmentRegionsLength = 0; gEnvironmentRegions = *data; numRegions = *(*data)++; + gEnvironmentRegionsLength++; if (numRegions > 20) { numRegions = 20; @@ -535,6 +537,7 @@ static void load_environmental_regions(s16 **data) { height = *(*data)++; + gEnvironmentRegionsLength += 6; gEnvironmentLevels[i] = height; } } @@ -550,6 +553,7 @@ void alloc_surface_pools(void) { if (!sSurfaceNodePool) { sSurfaceNodePool = calloc(1, SURFACE_NODE_POOL_SIZE * sizeof(struct SurfaceNode)); } if (!sSurfacePool) { sSurfacePool = calloc(1, sSurfacePoolSize * sizeof(struct Surface)); } + gEnvironmentRegions = NULL; gSurfaceNodesAllocated = 0; gSurfacesAllocated = 0; gNumStaticSurfaceNodes = 0; diff --git a/src/game/behaviors/moat_drainer.inc.c b/src/game/behaviors/moat_drainer.inc.c index 8b2353df..199bfed9 100644 --- a/src/game/behaviors/moat_drainer.inc.c +++ b/src/game/behaviors/moat_drainer.inc.c @@ -2,7 +2,7 @@ void bhv_invisible_objects_under_bridge_init(void) { if (save_file_get_flags() & SAVE_FLAG_MOAT_DRAINED) { - if (gEnvironmentRegions) { + if (gEnvironmentRegions && gEnvironmentRegionsLength > 12) { gEnvironmentRegions[6] = -800; gEnvironmentRegions[12] = -800; } @@ -20,7 +20,7 @@ void bhv_invisible_objects_under_bridge_loop(void) { break; case 1: // approach -800 - if (gEnvironmentRegions) { + if (gEnvironmentRegions && gEnvironmentRegionsLength > 12) { gEnvironmentRegions[6] = (s16)approach_f32_symmetric(gEnvironmentRegions[6], -800, 5.0f); gEnvironmentRegions[12] = (s16)approach_f32_symmetric(gEnvironmentRegions[12], -800, 5.0f); if (gEnvironmentRegions[6] <= -795 && gEnvironmentRegions[12] <= -795) { diff --git a/src/game/behaviors/thi_top.inc.c b/src/game/behaviors/thi_top.inc.c index e59164ff..d9280e1e 100644 --- a/src/game/behaviors/thi_top.inc.c +++ b/src/game/behaviors/thi_top.inc.c @@ -8,8 +8,9 @@ UNUSED u8 unused8032F134[] = { 10, 11, 12 }; void bhv_thi_huge_island_top_loop(void) { if (gTHIWaterDrained & 1) { - if (o->oTimer == 0) + if (o->oTimer == 0 && gEnvironmentRegionsLength > 18) { gEnvironmentRegions[18] = 3000; + } cur_obj_hide(); } else load_object_collision_model(); @@ -41,7 +42,7 @@ void bhv_thi_tiny_island_top_loop(void) { } } else { if (o->oTimer < 50) { - if (gEnvironmentRegions) { gEnvironmentRegions[18]--; } + if (gEnvironmentRegions && gEnvironmentRegionsLength > 18) { gEnvironmentRegions[18]--; } cur_obj_play_sound_1(SOUND_ENV_WATER_DRAIN); } else { gTHIWaterDrained |= 1; @@ -51,7 +52,7 @@ void bhv_thi_tiny_island_top_loop(void) { } } else { if (o->oTimer == 0) { - if (gEnvironmentRegions) { gEnvironmentRegions[18] = 700; } + if (gEnvironmentRegions && gEnvironmentRegionsLength > 18) { gEnvironmentRegions[18] = 700; } } cur_obj_hide(); } diff --git a/src/game/behaviors/treasure_chest.inc.c b/src/game/behaviors/treasure_chest.inc.c index fb905a1c..c18bb7ba 100644 --- a/src/game/behaviors/treasure_chest.inc.c +++ b/src/game/behaviors/treasure_chest.inc.c @@ -186,7 +186,7 @@ void bhv_treasure_chest_ship_loop(void) { break; case 1: - if (gEnvironmentRegions != NULL) { + if (gEnvironmentRegions != NULL && gEnvironmentRegionsLength > 6) { gEnvironmentRegions[6] += -5; play_sound(SOUND_ENV_WATER_DRAIN, gGlobalSoundSource); set_environmental_camera_shake(SHAKE_ENV_JRB_SHIP_DRAIN); diff --git a/src/game/behaviors/water_pillar.inc.c b/src/game/behaviors/water_pillar.inc.c index 7e1f2810..aced8cb0 100644 --- a/src/game/behaviors/water_pillar.inc.c +++ b/src/game/behaviors/water_pillar.inc.c @@ -81,7 +81,7 @@ void bhv_water_level_pillar_loop(void) { water_level_pillar_drained(); else water_level_pillar_undrained(); - if (gEnvironmentRegions) { + if (gEnvironmentRegions && gEnvironmentRegionsLength > 18) { gEnvironmentRegions[18] = gEnvironmentLevels[2]; gEnvironmentRegions[6] = gEnvironmentLevels[0]; } diff --git a/src/game/behaviors/wdw_water_level.inc.c b/src/game/behaviors/wdw_water_level.inc.c index 5e96d69e..b4a2e66b 100644 --- a/src/game/behaviors/wdw_water_level.inc.c +++ b/src/game/behaviors/wdw_water_level.inc.c @@ -26,10 +26,14 @@ void bhv_init_changing_water_level_loop(void) { if (gCurrentObject->oAction == 0) { gCurrentObject->oAction++; - } else if (gCurrentObject->oTimer < 10) - *gEnvironmentLevels = gEnvironmentRegions[6]; - else { - gEnvironmentRegions[6] = *gEnvironmentLevels + sins(o->oWaterLevelTriggerUnkF4) * 20.0f; + } else if (gCurrentObject->oTimer < 10) { + if (gEnvironmentRegions && gEnvironmentRegionsLength > 6) { + *gEnvironmentLevels = gEnvironmentRegions[6]; + } + } else { + if (gEnvironmentRegions && gEnvironmentRegionsLength > 6) { + gEnvironmentRegions[6] = *gEnvironmentLevels + sins(o->oWaterLevelTriggerUnkF4) * 20.0f; + } gCurrentObject->oWaterLevelTriggerUnkF4 += 0x200; } } diff --git a/src/game/moving_texture.c b/src/game/moving_texture.c index 47f4cf4d..ceb07ab9 100644 --- a/src/game/moving_texture.c +++ b/src/game/moving_texture.c @@ -321,7 +321,10 @@ Gfx *geo_wdw_set_initial_water_level(s32 callContext, UNUSED struct GraphNode *n } if (gEnvironmentRegions) { for (i = 0; i < *gEnvironmentRegions; i++) { - gEnvironmentRegions[i * 6 + 6] = wdwWaterHeight; + s32 idx = (i + 1) * 6; + if (idx < gEnvironmentRegionsLength) { + gEnvironmentRegions[idx] = wdwWaterHeight; + } } } gWdwWaterLevelSet = TRUE; @@ -627,7 +630,7 @@ Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUS if (callContext == GEO_CONTEXT_RENDER) { gMovtexVtxColor = MOVTEX_VTX_COLOR_DEFAULT; - if (gEnvironmentRegions == NULL) { + if (gEnvironmentRegions == NULL || gEnvironmentRegionsLength <= 0) { return NULL; } s16 numWaterBoxes = gEnvironmentRegions[0]; @@ -666,6 +669,7 @@ Gfx *geo_movtex_draw_water_regions(s32 callContext, struct GraphNode *node, UNUS movtex_change_texture_format(asGenerated->parameter, &gfx); gMovetexLastTextureId = -1; for (s32 i = 0; i < numWaterBoxes; i++) { + if (((i+1)*6) >= gEnvironmentRegionsLength) { break; } s16 waterId = gEnvironmentRegions[i * 6 + 1]; s16 waterY = gEnvironmentRegions[i * 6 + 6]; Gfx *subList = movtex_gen_quads_id(waterId, waterY, quadCollection); @@ -718,6 +722,7 @@ Gfx *geo_movtex_draw_water_regions_ext(s32 callContext, struct GraphNode *node, movtex_change_texture_format(asGenerated->parameter, &gfx); gMovetexLastTextureId = -1; for (s32 i = 0; i < numWaterBoxes; i++) { + if (((i+1)*6) >= gEnvironmentRegionsLength) { break; } s16 waterId = gEnvironmentRegions[i * 6 + 1]; s16 waterY = gEnvironmentRegions[i * 6 + 6]; Gfx *subList = movtex_gen_quads_id(waterId, waterY, quadCollection); diff --git a/src/game/obj_behaviors.c b/src/game/obj_behaviors.c index ebf8c436..581a4638 100644 --- a/src/game/obj_behaviors.c +++ b/src/game/obj_behaviors.c @@ -158,7 +158,7 @@ void turn_obj_away_from_surface(f32 velX, f32 velZ, f32 nX, UNUSED f32 nY, f32 n */ s8 obj_find_wall(f32 objNewX, f32 objY, f32 objNewZ, f32 objVelX, f32 objVelZ) { if (!o) { return 0; } - struct WallCollisionData hitbox; + struct WallCollisionData hitbox = { 0 }; f32 wall_nX, wall_nY, wall_nZ, objVelXCopy, objVelZCopy, objYawX, objYawZ; hitbox.x = objNewX; diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index f1499462..4ffb042c 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -146,6 +146,7 @@ struct Object* gCheckingSurfaceCollisionsForObject = NULL; s16 gCheckingSurfaceCollisionsForCamera; s16 gFindFloorIncludeSurfaceIntangible; s16 *gEnvironmentRegions; +s32 gEnvironmentRegionsLength = 0; s32 gEnvironmentLevels[20]; s8 gDoorAdjacentRooms[60][2]; s16 gMarioCurrentRoom; diff --git a/src/game/object_list_processor.h b/src/game/object_list_processor.h index 0d9c85b4..b4e531e5 100644 --- a/src/game/object_list_processor.h +++ b/src/game/object_list_processor.h @@ -100,6 +100,7 @@ extern struct Object* gCheckingSurfaceCollisionsForObject; extern s16 gCheckingSurfaceCollisionsForCamera; extern s16 gFindFloorIncludeSurfaceIntangible; extern s16 *gEnvironmentRegions; +extern s32 gEnvironmentRegionsLength; extern s32 gEnvironmentLevels[20]; extern s8 gDoorAdjacentRooms[60][2]; extern s16 gMarioCurrentRoom; diff --git a/src/pc/lua/utils/smlua_misc_utils.c b/src/pc/lua/utils/smlua_misc_utils.c index 3e05f020..bda0152e 100644 --- a/src/pc/lua/utils/smlua_misc_utils.c +++ b/src/pc/lua/utils/smlua_misc_utils.c @@ -390,15 +390,17 @@ void movtexqc_register(const char* name, s16 level, s16 area, s16 type) { /// f32 get_environment_region(u8 index) { - if (gEnvironmentRegions != NULL && index > 0 && index <= gEnvironmentRegions[0]) { - return gEnvironmentRegions[6 * (int)index]; + s32 idx = 6 * index; + if (gEnvironmentRegions != NULL && index > 0 && index <= gEnvironmentRegions[0] && gEnvironmentRegionsLength > idx) { + return gEnvironmentRegions[idx]; } return gLevelValues.floorLowerLimit; } void set_environment_region(u8 index, s32 value) { - if (gEnvironmentRegions != NULL && index > 0 && index <= gEnvironmentRegions[0]) { - gEnvironmentRegions[6 * (int)index] = value; + s32 idx = 6 * index; + if (gEnvironmentRegions != NULL && index > 0 && index <= gEnvironmentRegions[0] && gEnvironmentRegionsLength > idx) { + gEnvironmentRegions[idx] = value; } } diff --git a/src/pc/network/packets/packet_area.c b/src/pc/network/packets/packet_area.c index 93789a62..3fa466af 100644 --- a/src/pc/network/packets/packet_area.c +++ b/src/pc/network/packets/packet_area.c @@ -159,7 +159,7 @@ void network_receive_area(struct Packet* p) { packet_read(p, &gNetworkAreaTimer, sizeof(u32)); gNetworkAreaTimerClock = clock_elapsed_ticks() - gNetworkAreaTimer; packet_read(p, gEnvironmentLevels, sizeof(s32)); - if (gCurrLevelNum == LEVEL_WDW && gEnvironmentRegions != NULL) { + if (gCurrLevelNum == LEVEL_WDW && gEnvironmentRegions != NULL && gEnvironmentRegionsLength > 6) { gEnvironmentRegions[6] = *gEnvironmentLevels; }