Make envfx use dynamic memory

This commit is contained in:
MysterD 2023-05-12 21:30:16 -07:00
parent 1e67809cd8
commit 4aa4386319
7 changed files with 152 additions and 117 deletions

View file

@ -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);

View file

@ -7,6 +7,8 @@
struct LevelCommand;
extern struct DynamicPool *gLevelPool;
extern s32 gLevelScriptModIndex;
extern LevelScript* gLevelScriptActive;

View file

@ -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:

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;