diff --git a/src/engine/level_script.c b/src/engine/level_script.c index 08f86f51..1163a413 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -31,6 +31,7 @@ #include "pc/debug_context.h" #include "game/hardcoded.h" #include "menu/intro_geo.h" +#include "game/envfx_snow.h" #define CMD_GET(type, offset) (*(type *) (CMD_PROCESS_OFFSET(offset) + (u8 *) sCurrentCmd)) @@ -51,7 +52,7 @@ LevelScript* gLevelScriptActive = NULL; static uintptr_t sStack[32]; -static struct DynamicPool *sLevelPool = NULL; +struct DynamicPool *gLevelPool = NULL; static u16 sDelayFrames = 0; static u16 sDelayFrames2 = 0; @@ -107,7 +108,7 @@ static s32 eval_script_op(s8 op, s32 arg) { struct ObjectWarpNode *area_create_warp_node(u8 id, u8 destLevel, u8 destArea, u8 destNode, u8 checkpoint, struct Object *o) { if (sCurrAreaIndex != -1) { - struct ObjectWarpNode *warpNode = dynamic_pool_alloc(sLevelPool, sizeof(struct ObjectWarpNode)); + struct ObjectWarpNode *warpNode = dynamic_pool_alloc(gLevelPool, sizeof(struct ObjectWarpNode)); warpNode->node.id = id; warpNode->node.destLevel = destLevel + checkpoint; @@ -384,6 +385,21 @@ static void level_cmd_clear_level(void) { sCurrentCmd = CMD_NEXT; } +static void level_reset_globals(void) { + // free previous level pool + if (gLevelPool != NULL) { + dynamic_pool_free_pool(gLevelPool); + gLevelPool = NULL; + } + + // reset envfx + gEnvFxBuffer = NULL; + gEnvFxMode = ENVFX_MODE_NONE; + + // free models stored in dynos + dynos_model_clear_pool(MODEL_POOL_LEVEL); +} + static void level_cmd_alloc_level_pool(void) { // reset level graph node ownership @@ -394,16 +410,12 @@ static void level_cmd_alloc_level_pool(void) { } } - // free previous level pool - if (sLevelPool != NULL) { - dynamic_pool_free_pool(sLevelPool); - sLevelPool = NULL; - } - dynos_model_clear_pool(MODEL_POOL_LEVEL); + // reset all globals + level_reset_globals(); // allocate new level pool - if (sLevelPool == NULL) { - sLevelPool = dynamic_pool_init(); + if (gLevelPool == NULL) { + gLevelPool = dynamic_pool_init(); } sCurrentCmd = CMD_NEXT; @@ -415,7 +427,7 @@ static void level_cmd_free_level_pool(void) { if (!sFinishedLoadingPerm) { sFinishedLoadingPerm = true; // make sure we don't free the pool with the permanent models - sLevelPool = NULL; + gLevelPool = NULL; } for (i = 0; i < 8; i++) { @@ -500,7 +512,7 @@ static void level_cmd_23(void) { if (model < MAX_LOADED_GRAPH_NODES) { // GraphNodeScale has a GraphNode at the top. This // is being stored to the array, so cast the pointer. - gLoadedGraphNodes[model] = (struct GraphNode *) init_graph_node_scale(sLevelPool, 0, arg0H, arg1, arg2.f); + gLoadedGraphNodes[model] = (struct GraphNode *) init_graph_node_scale(gLevelPool, 0, arg0H, arg1, arg2.f); if (sFinishedLoadingPerm) { sLevelOwnedGraphNodes[model] = true; } smlua_model_util_remember(model, arg0H, arg1, 1); } @@ -547,7 +559,7 @@ static void level_cmd_place_object(void) { if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) { model = CMD_GET(u8, 3); if (model >= MAX_LOADED_GRAPH_NODES) { model = MODEL_NONE; } - spawnInfo = dynamic_pool_alloc(sLevelPool, sizeof(struct SpawnInfo)); + spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); spawnInfo->startPos[0] = CMD_GET(s16, 4); spawnInfo->startPos[1] = CMD_GET(s16, 6); @@ -578,7 +590,7 @@ static void level_cmd_place_object(void) { static void level_cmd_create_warp_node(void) { if (sCurrAreaIndex != -1) { struct ObjectWarpNode *warpNode = - dynamic_pool_alloc(sLevelPool, sizeof(struct ObjectWarpNode)); + dynamic_pool_alloc(gLevelPool, sizeof(struct ObjectWarpNode)); warpNode->node.id = CMD_GET(u8, 2); warpNode->node.destLevel = CMD_GET(u8, 3) + CMD_GET(u8, 6); @@ -601,7 +613,7 @@ static void level_cmd_create_instant_warp(void) { if (sCurrAreaIndex != -1) { if (gAreas[sCurrAreaIndex].instantWarps == NULL) { gAreas[sCurrAreaIndex].instantWarps = - dynamic_pool_alloc(sLevelPool, 4 * sizeof(struct InstantWarp)); + dynamic_pool_alloc(gLevelPool, 4 * sizeof(struct InstantWarp)); for (i = INSTANT_WARP_INDEX_START; i < INSTANT_WARP_INDEX_STOP; i++) { gAreas[sCurrAreaIndex].instantWarps[i].id = 0; @@ -636,7 +648,7 @@ static void level_cmd_create_painting_warp_node(void) { if (sCurrAreaIndex != -1) { if (gAreas[sCurrAreaIndex].paintingWarpNodes == NULL) { gAreas[sCurrAreaIndex].paintingWarpNodes = - dynamic_pool_alloc(sLevelPool, MAX_PAINTING_WARP_NODES * sizeof(struct WarpNode)); + dynamic_pool_alloc(gLevelPool, MAX_PAINTING_WARP_NODES * sizeof(struct WarpNode)); for (i = 0; i < MAX_PAINTING_WARP_NODES; i++) { gAreas[sCurrAreaIndex].paintingWarpNodes[i].id = 0; @@ -660,7 +672,7 @@ static void level_cmd_3A(void) { if (sCurrAreaIndex != -1) { if ((val4 = gAreas[sCurrAreaIndex].unused28) == NULL) { val4 = gAreas[sCurrAreaIndex].unused28 = - dynamic_pool_alloc(sLevelPool, sizeof(struct UnusedArea28)); + dynamic_pool_alloc(gLevelPool, sizeof(struct UnusedArea28)); } val4->unk00 = CMD_GET(s16, 2); @@ -683,7 +695,7 @@ static void level_cmd_create_whirlpool(void) { || (CMD_GET(u8, 3) == 2 && beatBowser2) || (CMD_GET(u8, 3) == 3 && gCurrActNum >= 2)) { if (sCurrAreaIndex != -1 && index < 2) { if ((whirlpool = gAreas[sCurrAreaIndex].whirlpools[index]) == NULL) { - whirlpool = dynamic_pool_alloc(sLevelPool, sizeof(struct Whirlpool)); + whirlpool = dynamic_pool_alloc(gLevelPool, sizeof(struct Whirlpool)); gAreas[sCurrAreaIndex].whirlpools[index] = whirlpool; } @@ -713,7 +725,7 @@ static void level_cmd_set_terrain_data(void) { // The game modifies the terrain data and must be reset upon level reload. data = segmented_to_virtual(CMD_GET(void *, 4)); size = get_area_terrain_size(data) * sizeof(Collision); - gAreas[sCurrAreaIndex].terrainData = dynamic_pool_alloc(sLevelPool, size); + gAreas[sCurrAreaIndex].terrainData = dynamic_pool_alloc(gLevelPool, size); memcpy(gAreas[sCurrAreaIndex].terrainData, data, size); } sCurrentCmd = CMD_NEXT; @@ -736,10 +748,10 @@ static void level_cmd_set_macro_objects(void) { area_check_red_coin_or_secret(&data[len - 1], true); len += 4; } - gAreas[sCurrAreaIndex].macroObjects = dynamic_pool_alloc(sLevelPool, len * sizeof(MacroObject)); + gAreas[sCurrAreaIndex].macroObjects = dynamic_pool_alloc(gLevelPool, len * sizeof(MacroObject)); memcpy(gAreas[sCurrAreaIndex].macroObjects, data, len * sizeof(MacroObject)); - gAreas[sCurrAreaIndex].macroObjectsAltered = dynamic_pool_alloc(sLevelPool, len * sizeof(u8)); + gAreas[sCurrAreaIndex].macroObjectsAltered = dynamic_pool_alloc(gLevelPool, len * sizeof(u8)); memset(gAreas[sCurrAreaIndex].macroObjectsAltered, 0, len); } sCurrentCmd = CMD_NEXT; @@ -946,7 +958,7 @@ static void level_cmd_place_object_ext(void) { if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) { u16 model = CMD_GET(u8, 3); if (model >= MAX_LOADED_GRAPH_NODES) { model = MODEL_NONE; } - spawnInfo = dynamic_pool_alloc(sLevelPool, sizeof(struct SpawnInfo)); + spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); spawnInfo->startPos[0] = CMD_GET(s16, 4); spawnInfo->startPos[1] = CMD_GET(s16, 6); @@ -1016,7 +1028,7 @@ static void level_cmd_place_object_ext2(void) { } if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) { - spawnInfo = dynamic_pool_alloc(sLevelPool, sizeof(struct SpawnInfo)); + spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo)); spawnInfo->startPos[0] = CMD_GET(s16, 4); spawnInfo->startPos[1] = CMD_GET(s16, 6); diff --git a/src/engine/level_script.h b/src/engine/level_script.h index f62c4ceb..2ee8ba89 100644 --- a/src/engine/level_script.h +++ b/src/engine/level_script.h @@ -7,6 +7,8 @@ struct LevelCommand; +extern struct DynamicPool *gLevelPool; + extern s32 gLevelScriptModIndex; extern LevelScript* gLevelScriptActive; diff --git a/src/game/envfx_bubbles.c b/src/game/envfx_bubbles.c index f947bd13..38e13fed 100644 --- a/src/game/envfx_bubbles.c +++ b/src/game/envfx_bubbles.c @@ -13,6 +13,7 @@ #include "game/rendering_graph_node.h" #include "pc/utils/misc.h" #include "game/hardcoded.h" +#include "engine/level_script.h" /** * This file implements environment effects that are not snow: @@ -49,7 +50,7 @@ static Vec3s sBubbleGfxCamTo; void patch_bubble_particles_before(void) { if (sBubbleGfxPos) { for (s32 i = 0; i < sBubbleParticleMaxCount; i++) { - vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos); + vec3s_set(gEnvFxBuffer[i].prevPos, gEnvFxBuffer[i].xPos, gEnvFxBuffer[i].yPos, gEnvFxBuffer[i].zPos); } sBubbleGfxPos = NULL; } @@ -67,8 +68,8 @@ void patch_bubble_particles_interpolated(UNUSED f32 delta) { * kill flower and bubble particles. */ s32 particle_is_laterally_close(s32 index, s32 x, s32 z, s32 distance) { - s32 xPos = (gEnvFxBuffer + index)->xPos; - s32 zPos = (gEnvFxBuffer + index)->zPos; + s32 xPos = gEnvFxBuffer[index].xPos; + s32 zPos = gEnvFxBuffer[index].zPos; if (sqr(xPos - x) + sqr(zPos - z) > sqr(distance)) { return 0; @@ -106,19 +107,19 @@ void envfx_update_flower(Vec3s centerPos) { s16 centerZ = centerPos[2]; for (i = 0; i < sBubbleParticleMaxCount; i++) { - (gEnvFxBuffer + i)->isAlive = particle_is_laterally_close(i, centerX, centerZ, 3000); - if ((gEnvFxBuffer + i)->isAlive == 0) { - (gEnvFxBuffer + i)->xPos = random_flower_offset() + centerX; - (gEnvFxBuffer + i)->zPos = random_flower_offset() + centerZ; - (gEnvFxBuffer + i)->yPos = find_floor_height_and_data((gEnvFxBuffer + i)->xPos, 10000.0f, - (gEnvFxBuffer + i)->zPos, &floorGeo); - (gEnvFxBuffer + i)->isAlive = 1; - (gEnvFxBuffer + i)->animFrame = random_float() * 5.0f; - vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos); + gEnvFxBuffer[i].isAlive = particle_is_laterally_close(i, centerX, centerZ, 3000); + if (gEnvFxBuffer[i].isAlive == 0) { + gEnvFxBuffer[i].xPos = random_flower_offset() + centerX; + gEnvFxBuffer[i].zPos = random_flower_offset() + centerZ; + gEnvFxBuffer[i].yPos = find_floor_height_and_data(gEnvFxBuffer[i].xPos, 10000.0f, + gEnvFxBuffer[i].zPos, &floorGeo); + gEnvFxBuffer[i].isAlive = 1; + gEnvFxBuffer[i].animFrame = random_float() * 5.0f; + vec3s_set(gEnvFxBuffer[i].prevPos, gEnvFxBuffer[i].xPos, gEnvFxBuffer[i].yPos, gEnvFxBuffer[i].zPos); } else if ((timer & 0x03) == 0) { - (gEnvFxBuffer + i)->animFrame += 1; - if ((gEnvFxBuffer + i)->animFrame > 5) { - (gEnvFxBuffer + i)->animFrame = 0; + gEnvFxBuffer[i].animFrame += 1; + if (gEnvFxBuffer[i].animFrame > 5) { + gEnvFxBuffer[i].animFrame = 0; } } } @@ -142,33 +143,33 @@ void envfx_set_lava_bubble_position(s32 index, Vec3s centerPos) { centerY = centerPos[1]; centerZ = centerPos[2]; - (gEnvFxBuffer + index)->xPos = random_float() * 6000.0f - 3000.0f + centerX; - (gEnvFxBuffer + index)->zPos = random_float() * 6000.0f - 3000.0f + centerZ; + gEnvFxBuffer[index].xPos = random_float() * 6000.0f - 3000.0f + centerX; + gEnvFxBuffer[index].zPos = random_float() * 6000.0f - 3000.0f + centerZ; - if ((gEnvFxBuffer + index)->xPos > 8000) { - (gEnvFxBuffer + index)->xPos = 16000 - (gEnvFxBuffer + index)->xPos; + if (gEnvFxBuffer[index].xPos > 8000) { + gEnvFxBuffer[index].xPos = 16000 - gEnvFxBuffer[index].xPos; } - if ((gEnvFxBuffer + index)->xPos < -8000) { - (gEnvFxBuffer + index)->xPos = -16000 - (gEnvFxBuffer + index)->xPos; + if (gEnvFxBuffer[index].xPos < -8000) { + gEnvFxBuffer[index].xPos = -16000 - gEnvFxBuffer[index].xPos; } - if ((gEnvFxBuffer + index)->zPos > 8000) { - (gEnvFxBuffer + index)->zPos = 16000 - (gEnvFxBuffer + index)->zPos; + if (gEnvFxBuffer[index].zPos > 8000) { + gEnvFxBuffer[index].zPos = 16000 - gEnvFxBuffer[index].zPos; } - if ((gEnvFxBuffer + index)->zPos < -8000) { - (gEnvFxBuffer + index)->zPos = -16000 - (gEnvFxBuffer + index)->zPos; + if (gEnvFxBuffer[index].zPos < -8000) { + gEnvFxBuffer[index].zPos = -16000 - gEnvFxBuffer[index].zPos; } - floorY = find_floor((gEnvFxBuffer + index)->xPos, centerY + 500, (gEnvFxBuffer + index)->zPos, &surface); + floorY = find_floor(gEnvFxBuffer[index].xPos, centerY + 500, gEnvFxBuffer[index].zPos, &surface); if (surface == NULL) { - (gEnvFxBuffer + index)->yPos = gLevelValues.floorLowerLimitMisc; + gEnvFxBuffer[index].yPos = gLevelValues.floorLowerLimitMisc; return; } if (surface->type == SURFACE_BURNING) { - (gEnvFxBuffer + index)->yPos = floorY; + gEnvFxBuffer[index].yPos = floorY; } else { - (gEnvFxBuffer + index)->yPos = gLevelValues.floorLowerLimitMisc; + gEnvFxBuffer[index].yPos = gLevelValues.floorLowerLimitMisc; } } @@ -187,15 +188,15 @@ void envfx_update_lava(Vec3s centerPos) { centerZ = centerPos[2]; for (i = 0; i < sBubbleParticleMaxCount; i++) { - if ((gEnvFxBuffer + i)->isAlive == 0) { + if (gEnvFxBuffer[i].isAlive == 0) { envfx_set_lava_bubble_position(i, centerPos); - vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos); - (gEnvFxBuffer + i)->isAlive = 1; + vec3s_set(gEnvFxBuffer[i].prevPos, gEnvFxBuffer[i].xPos, gEnvFxBuffer[i].yPos, gEnvFxBuffer[i].zPos); + gEnvFxBuffer[i].isAlive = 1; } else if ((timer & 0x01) == 0) { - (gEnvFxBuffer + i)->animFrame += 1; - if ((gEnvFxBuffer + i)->animFrame > 8) { - (gEnvFxBuffer + i)->isAlive = 0; - (gEnvFxBuffer + i)->animFrame = 0; + gEnvFxBuffer[i].animFrame += 1; + if (gEnvFxBuffer[i].animFrame > 8) { + gEnvFxBuffer[i].isAlive = 0; + gEnvFxBuffer[i].animFrame = 0; } } } @@ -234,11 +235,11 @@ void envfx_rotate_around_whirlpool(s32 *x, s32 *y, s32 *z) { s32 envfx_is_whirlpool_bubble_alive(s32 index) { s32 UNUSED sp4; - if ((gEnvFxBuffer + index)->bubbleY < gEnvFxBubbleConfig[ENVFX_STATE_DEST_Y] - 100) { + if (gEnvFxBuffer[index].bubbleY < gEnvFxBubbleConfig[ENVFX_STATE_DEST_Y] - 100) { return 0; } - if ((gEnvFxBuffer + index)->angleAndDist[1] < 10) { + if (gEnvFxBuffer[index].angleAndDist[1] < 10) { return 0; } @@ -253,43 +254,43 @@ void envfx_update_whirlpool(void) { s32 i; for (i = 0; i < sBubbleParticleMaxCount; i++) { - (gEnvFxBuffer + i)->isAlive = envfx_is_whirlpool_bubble_alive(i); - if ((gEnvFxBuffer + i)->isAlive == 0) { - (gEnvFxBuffer + i)->angleAndDist[1] = random_float() * 1000.0f; - (gEnvFxBuffer + i)->angleAndDist[0] = random_float() * 65536.0f; - (gEnvFxBuffer + i)->xPos = + gEnvFxBuffer[i].isAlive = envfx_is_whirlpool_bubble_alive(i); + if (gEnvFxBuffer[i].isAlive == 0) { + gEnvFxBuffer[i].angleAndDist[1] = random_float() * 1000.0f; + gEnvFxBuffer[i].angleAndDist[0] = random_float() * 65536.0f; + gEnvFxBuffer[i].xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] - + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->zPos = + + sins(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] - + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->bubbleY = + + coss(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].bubbleY = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 100.0f - 50.0f); - (gEnvFxBuffer + i)->yPos = (i + gEnvFxBuffer)->bubbleY; - (gEnvFxBuffer + i)->unusedBubbleVar = 0; - (gEnvFxBuffer + i)->isAlive = 1; - (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; - vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos); + gEnvFxBuffer[i].yPos = (i + gEnvFxBuffer)->bubbleY; + gEnvFxBuffer[i].unusedBubbleVar = 0; + gEnvFxBuffer[i].isAlive = 1; + gEnvFxBuffer[i].spawnTimestamp = gGlobalTimer; + vec3s_set(gEnvFxBuffer[i].prevPos, gEnvFxBuffer[i].xPos, gEnvFxBuffer[i].yPos, gEnvFxBuffer[i].zPos); - envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, - &(gEnvFxBuffer + i)->zPos); + envfx_rotate_around_whirlpool(&gEnvFxBuffer[i].xPos, &gEnvFxBuffer[i].yPos, + &gEnvFxBuffer[i].zPos); } - if ((gEnvFxBuffer + i)->isAlive != 0) { - (gEnvFxBuffer + i)->angleAndDist[1] -= 40; - (gEnvFxBuffer + i)->angleAndDist[0] += - (s16)(3000 - (gEnvFxBuffer + i)->angleAndDist[1] * 2) + 0x400; - (gEnvFxBuffer + i)->xPos = + if (gEnvFxBuffer[i].isAlive != 0) { + gEnvFxBuffer[i].angleAndDist[1] -= 40; + gEnvFxBuffer[i].angleAndDist[0] += + (s16)(3000 - gEnvFxBuffer[i].angleAndDist[1] * 2) + 0x400; + gEnvFxBuffer[i].xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] - + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->zPos = + + sins(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] - + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->bubbleY -= 40 - ((s16)(gEnvFxBuffer + i)->angleAndDist[1] / 100); - (gEnvFxBuffer + i)->yPos = (i + gEnvFxBuffer)->bubbleY; + + coss(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].bubbleY -= 40 - ((s16)gEnvFxBuffer[i].angleAndDist[1] / 100); + gEnvFxBuffer[i].yPos = (i + gEnvFxBuffer)->bubbleY; - envfx_rotate_around_whirlpool(&(gEnvFxBuffer + i)->xPos, &(gEnvFxBuffer + i)->yPos, - &(gEnvFxBuffer + i)->zPos); + envfx_rotate_around_whirlpool(&gEnvFxBuffer[i].xPos, &gEnvFxBuffer[i].yPos, + &gEnvFxBuffer[i].zPos); } } } @@ -303,7 +304,7 @@ s32 envfx_is_jestream_bubble_alive(s32 index) { if (!particle_is_laterally_close(index, gEnvFxBubbleConfig[ENVFX_STATE_SRC_X], gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z], 1000) - || gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + 1500 < (gEnvFxBuffer + index)->yPos) { + || gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + 1500 < gEnvFxBuffer[index].yPos) { return 0; } @@ -318,20 +319,20 @@ void envfx_update_jetstream(void) { s32 i; for (i = 0; i < sBubbleParticleMaxCount; i++) { - (gEnvFxBuffer + i)->isAlive = envfx_is_jestream_bubble_alive(i); - if ((gEnvFxBuffer + i)->isAlive == 0) { - (gEnvFxBuffer + i)->angleAndDist[1] = random_float() * 300.0f; - (gEnvFxBuffer + i)->angleAndDist[0] = random_u16(); - (gEnvFxBuffer + i)->xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss((gEnvFxBuffer + i)->angleAndDist[0]) * (gEnvFxBuffer + i)->angleAndDist[1]; - (gEnvFxBuffer + i)->yPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f); - (gEnvFxBuffer + i)->spawnTimestamp = gGlobalTimer; - vec3s_set((gEnvFxBuffer + i)->prevPos, (gEnvFxBuffer + i)->xPos, (gEnvFxBuffer + i)->yPos, (gEnvFxBuffer + i)->zPos); + gEnvFxBuffer[i].isAlive = envfx_is_jestream_bubble_alive(i); + if (gEnvFxBuffer[i].isAlive == 0) { + gEnvFxBuffer[i].angleAndDist[1] = random_float() * 300.0f; + gEnvFxBuffer[i].angleAndDist[0] = random_u16(); + gEnvFxBuffer[i].xPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_X] + sins(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].zPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Z] + coss(gEnvFxBuffer[i].angleAndDist[0]) * gEnvFxBuffer[i].angleAndDist[1]; + gEnvFxBuffer[i].yPos = gEnvFxBubbleConfig[ENVFX_STATE_SRC_Y] + (random_float() * 400.0f - 200.0f); + gEnvFxBuffer[i].spawnTimestamp = gGlobalTimer; + vec3s_set(gEnvFxBuffer[i].prevPos, gEnvFxBuffer[i].xPos, gEnvFxBuffer[i].yPos, gEnvFxBuffer[i].zPos); } else { - (gEnvFxBuffer + i)->angleAndDist[1] += 10; - (gEnvFxBuffer + i)->xPos += sins((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f; - (gEnvFxBuffer + i)->zPos += coss((gEnvFxBuffer + i)->angleAndDist[0]) * 10.0f; - (gEnvFxBuffer + i)->yPos -= ((gEnvFxBuffer + i)->angleAndDist[1] / 30) - 50; + gEnvFxBuffer[i].angleAndDist[1] += 10; + gEnvFxBuffer[i].xPos += sins(gEnvFxBuffer[i].angleAndDist[0]) * 10.0f; + gEnvFxBuffer[i].zPos += coss(gEnvFxBuffer[i].angleAndDist[0]) * 10.0f; + gEnvFxBuffer[i].yPos -= (gEnvFxBuffer[i].angleAndDist[1] / 30) - 50; } } } @@ -367,10 +368,8 @@ s32 envfx_init_bubble(s32 mode) { break; } - gEnvFxBuffer = mem_pool_alloc(gEffectsMemoryPool, sBubbleParticleCount * sizeof(struct EnvFxParticle)); - if (!gEnvFxBuffer) { - return 0; - } + gEnvFxBuffer = dynamic_pool_alloc(gLevelPool, sBubbleParticleCount * sizeof(struct EnvFxParticle)); + if (!gEnvFxBuffer) { return 0; } bzero(gEnvFxBuffer, sBubbleParticleCount * sizeof(struct EnvFxParticle)); bzero(gEnvFxBubbleConfig, sizeof(gEnvFxBubbleConfig)); @@ -378,7 +377,7 @@ s32 envfx_init_bubble(s32 mode) { switch (mode) { case ENVFX_LAVA_BUBBLES: for (i = 0; i < sBubbleParticleCount; i++) { - (gEnvFxBuffer + i)->animFrame = random_float() * 7.0f; + gEnvFxBuffer[i].animFrame = random_float() * 7.0f; } break; } @@ -489,17 +488,17 @@ void append_bubble_vertex_buffer(Gfx *gfx, s32 index, Vec3s vertex1, Vec3s verte */ void envfx_set_bubble_texture(s32 mode, s16 index) { void **imageArr; - s16 frame = (gEnvFxBuffer + index)->animFrame; + s16 frame = gEnvFxBuffer[index].animFrame; switch (mode) { case ENVFX_FLOWERS: imageArr = segmented_to_virtual(&flower_bubbles_textures_ptr_0B002008); - frame = (gEnvFxBuffer + index)->animFrame; + frame = gEnvFxBuffer[index].animFrame; break; case ENVFX_LAVA_BUBBLES: imageArr = segmented_to_virtual(&lava_bubble_ptr_0B006020); - frame = (gEnvFxBuffer + index)->animFrame; + frame = gEnvFxBuffer[index].animFrame; break; case ENVFX_WHIRLPOOL_BUBBLES: diff --git a/src/game/envfx_snow.c b/src/game/envfx_snow.c index f48cd90d..d1fb896b 100644 --- a/src/game/envfx_snow.c +++ b/src/game/envfx_snow.c @@ -9,6 +9,7 @@ #include "engine/surface_collision.h" #include "engine/math_util.h" #include "engine/behavior_script.h" +#include "engine/level_script.h" #include "audio/external.h" #include "obj_behaviors.h" #include "pc/utils/misc.h" @@ -104,10 +105,8 @@ s32 envfx_init_snow(s32 mode) { break; } - gEnvFxBuffer = mem_pool_alloc(gEffectsMemoryPool, gSnowParticleMaxCount * sizeof(struct EnvFxParticle)); - if (!gEnvFxBuffer) { - return 0; - } + gEnvFxBuffer = dynamic_pool_alloc(gLevelPool, gSnowParticleMaxCount * sizeof(struct EnvFxParticle)); + if (!gEnvFxBuffer) { return 0; } bzero(gEnvFxBuffer, gSnowParticleMaxCount * sizeof(struct EnvFxParticle)); @@ -161,7 +160,7 @@ void envfx_update_snowflake_count(s32 mode, Vec3s marioPos) { void envfx_cleanup_snow(void *snowParticleArray) { if (gEnvFxMode) { if (snowParticleArray) { - mem_pool_free(gEffectsMemoryPool, snowParticleArray); + dynamic_pool_free(gLevelPool, snowParticleArray); } gEnvFxMode = ENVFX_MODE_NONE; } diff --git a/src/game/memory.c b/src/game/memory.c index 93945380..208c2322 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -54,7 +54,7 @@ extern struct MainPoolBlock *sPoolListHeadR; * Memory pool for small graphical effects that aren't connected to Objects. * Used for colored text, paintings, and environmental snow and bubbles. */ -struct MemoryPool *gEffectsMemoryPool; +struct MemoryPool *gEffectsMemoryPool = NULL; uintptr_t sSegmentTable[32]; u32 sPoolFreeSpace; diff --git a/src/game/memory.h b/src/game/memory.h index 6fbfa07d..b10aa5c2 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -70,6 +70,7 @@ u32 main_pool_pop_state(void); struct DynamicPool* dynamic_pool_init(void); void* dynamic_pool_alloc(struct DynamicPool *pool, u32 size); +void dynamic_pool_free(struct DynamicPool *pool, void* ptr); void dynamic_pool_free_pool(struct DynamicPool *pool); struct GrowingPool* growing_pool_init(struct GrowingPool* pool, u32 nodeSize); diff --git a/src/game/memory_dynamic.c b/src/game/memory_dynamic.c index 406d6374..862b1ff6 100644 --- a/src/game/memory_dynamic.c +++ b/src/game/memory_dynamic.c @@ -28,6 +28,28 @@ void* dynamic_pool_alloc(struct DynamicPool *pool, u32 size) { return node->ptr; } +void dynamic_pool_free(struct DynamicPool *pool, void* ptr) { + if (!pool || !ptr) { return; } + + struct DynamicPoolNode* node = pool->tail; + struct DynamicPoolNode* next = node; + + while (node) { + struct DynamicPoolNode* prev = node->prev; + if (node->ptr == ptr) { + if (pool->tail == node) { + pool->tail = prev; + } else { + next->prev = prev; + } + free(node->ptr); + free(node); + } + next = node; + node = prev; + } +} + void dynamic_pool_free_pool(struct DynamicPool *pool) { if (!pool) { return; } struct DynamicPoolNode* node = pool->tail;