mirror of https://github.com/zeldaret/mm.git
304 lines
8.4 KiB
C
304 lines
8.4 KiB
C
#include <ultra64.h>
|
|
#include <global.h>
|
|
|
|
void EffectSS_Init(GlobalContext* ctxt, s32 numEntries) {
|
|
u32 i;
|
|
LoadedParticleEntry* iter;
|
|
ParticleOverlay* iter2;
|
|
|
|
EffectSS2Info.data_table = (LoadedParticleEntry*)GameStateHeap_AllocFromEnd(&ctxt->state.heap, numEntries * sizeof(LoadedParticleEntry));
|
|
EffectSS2Info.searchIndex = 0;
|
|
EffectSS2Info.size = numEntries;
|
|
|
|
for (iter = EffectSS2Info.data_table; iter < EffectSS2Info.data_table + EffectSS2Info.size; iter++) {
|
|
EffectSS_ResetEntry(iter);
|
|
}
|
|
|
|
for (i = 0, iter2 = particleOverlayTable; i != EFFECT_SS2_TYPE_LAST_LABEL; i++) {
|
|
(iter2++)->loadedRamAddr = 0;
|
|
}
|
|
}
|
|
|
|
void EffectSS_Clear(GlobalContext* ctxt) {
|
|
u32 i;
|
|
LoadedParticleEntry* iter;
|
|
ParticleOverlay* iter2;
|
|
void* addr;
|
|
|
|
EffectSS2Info.data_table = NULL;
|
|
EffectSS2Info.searchIndex = 0;
|
|
EffectSS2Info.size = 0;
|
|
|
|
// This code is completely useless, as data_table was just set to NULL and size to 0
|
|
for (iter = EffectSS2Info.data_table; iter < EffectSS2Info.data_table + EffectSS2Info.size; iter++) {
|
|
EffectSS_Delete(iter);
|
|
}
|
|
|
|
// Free memory from loaded particle overlays
|
|
for (i = 0, iter2 = particleOverlayTable; i != EFFECT_SS2_TYPE_LAST_LABEL; i++) {
|
|
addr = (void*)iter2->loadedRamAddr;
|
|
if (addr != NULL) {
|
|
zelda_free(addr);
|
|
}
|
|
(iter2++)->loadedRamAddr = 0;
|
|
}
|
|
}
|
|
|
|
LoadedParticleEntry* EffectSS_GetTable() {
|
|
return EffectSS2Info.data_table;
|
|
}
|
|
|
|
void EffectSS_Delete(LoadedParticleEntry* a0) {
|
|
if (a0->flags & 0x2) {
|
|
func_801A72CC((UNK_PTR)&a0->position);
|
|
}
|
|
|
|
if (a0->flags & 0x4) {
|
|
func_801A72CC((UNK_PTR)&a0->unk2C);
|
|
}
|
|
|
|
EffectSS_ResetEntry(a0);
|
|
}
|
|
|
|
void EffectSS_ResetEntry(LoadedParticleEntry* particle) {
|
|
u32 i;
|
|
|
|
particle->type = EFFECT_SS2_TYPE_LAST_LABEL;
|
|
particle->acceleration.z = 0;
|
|
particle->acceleration.y = 0;
|
|
particle->acceleration.x = 0;
|
|
particle->velocity.z = 0;
|
|
particle->velocity.y = 0;
|
|
particle->velocity.x = 0;
|
|
particle->unk2C.z = 0;
|
|
particle->unk2C.y = 0;
|
|
particle->unk2C.x = 0;
|
|
particle->position.z = 0;
|
|
particle->position.y = 0;
|
|
particle->position.x = 0;
|
|
particle->life = -1;
|
|
particle->flags = 0;
|
|
particle->priority = 128;
|
|
particle->draw = NULL;
|
|
particle->update = NULL;
|
|
particle->displayList = 0;
|
|
particle->unk3C = 0;
|
|
|
|
for (i = 0; i != 13; i++) {
|
|
particle->regs[i] = 0;
|
|
}
|
|
}
|
|
|
|
// XXX Some regalloc differences and instruction ordering
|
|
#ifdef NON_MATCHING
|
|
s32 EffectSS_FindFreeSpace(u32 priority, u32* tableEntry) {
|
|
s32 ret = 0;
|
|
s32 i;
|
|
|
|
if (EffectSS2Info.size <= EffectSS2Info.searchIndex) {
|
|
EffectSS2Info.searchIndex = 0;
|
|
}
|
|
|
|
// Search for a unused entry
|
|
for (i = EffectSS2Info.searchIndex;;) {
|
|
if (EffectSS2Info.data_table[i].life == -1) {
|
|
ret = 1;
|
|
break;
|
|
}
|
|
|
|
i += 1;
|
|
|
|
if (EffectSS2Info.size <= i) {
|
|
i = 0;
|
|
}
|
|
|
|
if (i == EffectSS2Info.searchIndex) break;
|
|
}
|
|
|
|
if (ret == 1) {
|
|
ret = 0;
|
|
} else {
|
|
// If the entire table is full, look for a lower priority entry instead
|
|
for (;;) {
|
|
if (priority <= EffectSS2Info.data_table[i].priority &&
|
|
(priority != EffectSS2Info.data_table[i].priority || (EffectSS2Info.data_table[i].flags & 0x1) == 0)) {
|
|
ret = 0;
|
|
break;
|
|
}
|
|
|
|
i += 1;
|
|
|
|
if (EffectSS2Info.size <= i) {
|
|
i = 0;
|
|
}
|
|
|
|
if (i == EffectSS2Info.searchIndex) {
|
|
ret = 1;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
*tableEntry = i;
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("./asm/non_matchings/z_effect_soft_sprite/EffectSS_FindFreeSpace.asm")
|
|
#endif
|
|
|
|
void EffectSS_Copy(GlobalContext* ctxt, LoadedParticleEntry* a1) {
|
|
u32 index;
|
|
if (func_8016A01C(ctxt) != 1) {
|
|
if (EffectSS_FindFreeSpace(a1->priority, &index) == 0) {
|
|
EffectSS2Info.searchIndex = index + 1;
|
|
EffectSS2Info.data_table[index] = *a1;
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
void EffectSS_LoadParticle(GlobalContext* ctxt, u32 type, u32 priority, void* initData) {
|
|
u32 index;
|
|
u32 initRet;
|
|
u32 overlaySize;
|
|
ParticleOverlayInfo* overlayInfo;
|
|
ParticleOverlay* entry = &particleOverlayTable[type];
|
|
|
|
if (EffectSS_FindFreeSpace(priority, &index) != 0) {
|
|
return;
|
|
}
|
|
|
|
EffectSS2Info.searchIndex = index + 1;
|
|
if (entry->vramStart == 0) {
|
|
overlayInfo = entry->overlayInfo;
|
|
} else {
|
|
// XXX this subtraction is done earlier
|
|
overlaySize = entry->vramEnd - entry->vramStart;
|
|
if (entry->loadedRamAddr == 0) {
|
|
entry->loadedRamAddr = (u32)zelda_mallocR(overlaySize);
|
|
|
|
if (entry->loadedRamAddr == 0) {
|
|
return;
|
|
}
|
|
|
|
load_and_relocate_overlay(entry->vromStart, entry->vromEnd, entry->vramStart, entry->vramEnd, entry->loadedRamAddr);
|
|
}
|
|
|
|
// XXX this should use a0, but it doesn't
|
|
if (entry->overlayInfo != NULL) {
|
|
overlayInfo = (ParticleOverlayInfo*)(-(entry->vramStart - entry->loadedRamAddr) + (u32)entry->overlayInfo);
|
|
} else {
|
|
overlayInfo = NULL;
|
|
}
|
|
}
|
|
|
|
if (overlayInfo->init != 0) {
|
|
EffectSS_Delete(&EffectSS2Info.data_table[index]);
|
|
|
|
EffectSS2Info.data_table[index].type = type;
|
|
EffectSS2Info.data_table[index].priority = priority;
|
|
|
|
initRet = (*overlayInfo->init)(ctxt, index, &EffectSS2Info.data_table[index], initData);
|
|
|
|
if (initRet == 0) {
|
|
EffectSS_ResetEntry(&EffectSS2Info.data_table[index]);
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
GLOBAL_ASM("./asm/non_matchings/z_effect_soft_sprite/EffectSS_LoadParticle.asm")
|
|
#endif
|
|
|
|
void EffectSS_UpdateParticle(GlobalContext* ctxt, s32 index) {
|
|
LoadedParticleEntry* particle = &EffectSS2Info.data_table[index];
|
|
|
|
if (particle->update != NULL) {
|
|
particle->velocity.x += particle->acceleration.x;
|
|
particle->velocity.y += particle->acceleration.y;
|
|
particle->velocity.z += particle->acceleration.z;
|
|
|
|
particle->position.x += particle->velocity.x;
|
|
particle->position.y += particle->velocity.y;
|
|
particle->position.z += particle->velocity.z;
|
|
|
|
(*particle->update)(ctxt, index, particle);
|
|
}
|
|
}
|
|
|
|
void EffectSS_UpdateAllParticles(GlobalContext* ctxt) {
|
|
s32 i;
|
|
|
|
for (i = 0; i < EffectSS2Info.size; i++) {
|
|
if (EffectSS2Info.data_table[i].life > -1) {
|
|
EffectSS2Info.data_table[i].life--;
|
|
|
|
if (EffectSS2Info.data_table[i].life < 0) {
|
|
EffectSS_Delete(&EffectSS2Info.data_table[i]);
|
|
}
|
|
}
|
|
|
|
if (EffectSS2Info.data_table[i].life > -1) {
|
|
EffectSS_UpdateParticle(ctxt, i);
|
|
}
|
|
}
|
|
}
|
|
|
|
void EffectSS_DrawParticle(GlobalContext* ctxt, s32 index) {
|
|
LoadedParticleEntry* entry = &EffectSS2Info.data_table[index];
|
|
if (entry->draw != 0) {
|
|
(*entry->draw)(ctxt, index, entry);
|
|
}
|
|
}
|
|
|
|
void EffectSS_DrawAllParticles(GlobalContext* ctxt) {
|
|
LightMapper* s0;
|
|
s32 i;
|
|
|
|
s0 = Lights_CreateMapper(&ctxt->lightCtx, ctxt->state.gfxCtx);
|
|
Lights_MapLights(s0, ctxt->lightCtx.lightsHead, 0, ctxt);
|
|
Lights_UploadLights(s0, ctxt->state.gfxCtx);
|
|
|
|
for (i = 0; i < EffectSS2Info.size; i++) {
|
|
if (EffectSS2Info.data_table[i].life > -1) {
|
|
if (EffectSS2Info.data_table[i].position.x > 32000 ||
|
|
EffectSS2Info.data_table[i].position.x < -32000 ||
|
|
EffectSS2Info.data_table[i].position.y > 32000 ||
|
|
EffectSS2Info.data_table[i].position.y < -32000 ||
|
|
EffectSS2Info.data_table[i].position.z > 32000 ||
|
|
EffectSS2Info.data_table[i].position.z < -32000
|
|
) {
|
|
EffectSS_Delete(&EffectSS2Info.data_table[i]);
|
|
} else {
|
|
EffectSS_DrawParticle(ctxt, i);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#ifdef NON_MATCHING
|
|
s16 func_800B096C(s16 a0, s16 a1, s32 a2) {
|
|
s16 ret;
|
|
|
|
if (a2 == 0) {
|
|
ret = a1;
|
|
} else {
|
|
// XXX result of the division is put in t0 instead of t8
|
|
ret = a0 + (s16)((a1 - a0) / (f32)a2);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#else
|
|
GLOBAL_ASM("./asm/non_matchings/z_effect_soft_sprite/func_800B096C.asm")
|
|
#endif
|
|
|
|
s16 func_800B09D0(s16 a0, s16 a1, f32 a2) {
|
|
return a2 * (a1 - a0) + a0;
|
|
}
|
|
|
|
u8 func_800B0A24(u8 a0, u8 a1, f32 a2) {
|
|
return a2 * ((f32)a1 - (f32)a0) + a0;
|
|
}
|