summaryrefslogtreecommitdiff
path: root/src/code
diff options
context:
space:
mode:
authorLucas Shaw <49287729+shawlucas@users.noreply.github.com>2021-10-24 10:59:14 -0400
committerGitHub <noreply@github.com>2021-10-24 10:59:14 -0400
commitdcf44596d2c335c1ad82ea50f7e7d934e6bc1e52 (patch)
tree59946691d9d64724244a98332a1350a5dca3f8b7 /src/code
parent961913f18fb677ac6f95f0ab08c30bedaa616ec2 (diff)
Animation system updated, some more boot files decompiled (+6%), z_fcurve_data_skelanime decompiled (1 non-matching), some asm files split, etc (#89)
* Progress on various files * gfxprint stuff * split some rodata, add iconv for rodata string parsing * z_std_dma rodata * 2 nonmatchings in gfxprint * mtxuty-cvt ok * more * match a function in idle.c * progress * Cleanup * Rename BgPolygon to CollisionPoly * progress * some effect stuff * more effect progress * updates * made suggested changes * z_effect_soft_sprite_old_init mostly ok * remove old effects enum * gamealloc.c OK * added more files * motor.c almost done * motor.c OK * updates * migration of two files * listalloc.c oK * z_fcurve_data_skelanime split * z_fcurve_data_skelanime.c decompiled * more files split * z_malloc.c OK * contpfs.c OK * fault.c rodata migrated * migrated fault_drawer rodata * update * update preprocess.py * renamed functions in z_skelanime * started z_skelanime cleanup * like halfway through fixing z_skelanime * animation system updated to meet oot standards * remove unused animation structs * rename matrix structs to fit oot * Add -woff 712 * fix diff_settings.py because i accidentally broke it before * fixed merge conflict, doesn't match though * It matches now * Updates * Fixed warnings...added gcc code syntax checking * Remove gcc check, added in Tharo's PR * warnings fixed (i think) * fixed all warnings i think * ok * not sure what to do * Fix all warnings i think (z_en_a_keep needs some file cleanup thouguh) * it matches if i do this * remove comment * accidentally put osPfsFreeBlocks in epilinkhandle.c * memcmp -> bcmp * change u32 size to size_t size, delete string.h because it caused unnecessary confusion with defining size_t twice * format.sh * MTXMODE_NEW and MTXMODE_APPLY to matrix functions * Made suggested changes * pragma sFaultDrawerFont instead of including in repo * add some functions to functions.h * Bss reordering fixed in z_collision_check...added hack to disasm.py * Updated z_en_a_keep.c * Missed suggestion in EnAObj_Destroy * . * update z_fcurve_Data_skelanime and z_skelanime with suggestions * devmgr.c ok * minor changes * Addressed comments * remove redundant file * gfxp -> dlist in game.c * updated actorfixer.py * fixed warnings in z_malloc * Change void* back to Actor* * format * Add the soft_sprit comments back * Rename SV->Flex * remove .common * run format * Update src/code/z_skelanime.c * u32 channel Co-authored-by: Lucas Shaw <lucas.shaw1123@gmail.com> Co-authored-by: angie <angheloalf95@gmail.com> Co-authored-by: Kenix3 <kenixwhisperwind@gmail.com>
Diffstat (limited to 'src/code')
-rw-r--r--src/code/PreRender.c4
-rw-r--r--src/code/TwoHeadArena.c10
-rw-r--r--src/code/TwoHeadGfxArena.c4
-rw-r--r--src/code/code_800F23E0.c5
-rw-r--r--src/code/code_80122660.c5
-rw-r--r--src/code/game.c181
-rw-r--r--src/code/gamealloc.c58
-rw-r--r--src/code/listalloc.c61
-rw-r--r--src/code/main.c22
-rw-r--r--src/code/padmgr.c2
-rw-r--r--src/code/sys_matrix.c68
-rw-r--r--src/code/z_DLF.c4
-rw-r--r--src/code/z_actor.c6
-rw-r--r--src/code/z_actor_dlftbls.c2
-rw-r--r--src/code/z_collision_check.c14
-rw-r--r--src/code/z_eff_footmark.c4
-rw-r--r--src/code/z_effect_soft_sprite.c4
-rw-r--r--src/code/z_effect_soft_sprite_old_init.c9
-rw-r--r--src/code/z_en_a_keep.c71
-rw-r--r--src/code/z_en_item00.c4
-rw-r--r--src/code/z_fcurve_data.c5
-rw-r--r--src/code/z_fcurve_data_skelanime.c180
-rw-r--r--src/code/z_lights.c2
-rw-r--r--src/code/z_malloc.c53
-rw-r--r--src/code/z_pause.c5
-rw-r--r--src/code/z_room.c2
-rw-r--r--src/code/z_scene.c12
-rw-r--r--src/code/z_skelanime.c2178
-rw-r--r--src/code/z_view.c24
-rw-r--r--src/code/z_vr_box.c18
30 files changed, 1804 insertions, 1213 deletions
diff --git a/src/code/PreRender.c b/src/code/PreRender.c
index bdf4d326c..0afb1df68 100644
--- a/src/code/PreRender.c
+++ b/src/code/PreRender.c
@@ -17,7 +17,7 @@ void PreRender_SetValuesSave(PreRender* this, u32 width, u32 height, void* fbuf,
void PreRender_Init(PreRender* this) {
bzero(this, sizeof(PreRender));
- func_80174AA0(&this->alloc);
+ ListAlloc_Init(&this->alloc);
}
/**
@@ -35,7 +35,7 @@ void PreRender_SetValues(PreRender* this, u32 width, u32 height, void* fbuf, voi
}
void PreRender_Destroy(PreRender* this) {
- func_80174BA0(&this->alloc);
+ ListAlloc_FreeAll(&this->alloc);
}
void func_8016FDB8(PreRender* this, Gfx** gfxp, void* buf, void* bufSave, u32 arg4) {
diff --git a/src/code/TwoHeadArena.c b/src/code/TwoHeadArena.c
index b4262e3c6..83d5be3d1 100644
--- a/src/code/TwoHeadArena.c
+++ b/src/code/TwoHeadArena.c
@@ -12,7 +12,7 @@ void* THA_GetTail(TwoHeadArena* tha) {
return tha->tail;
}
-void* THA_AllocStart(TwoHeadArena* tha, u32 size) {
+void* THA_AllocStart(TwoHeadArena* tha, size_t size) {
void* start = tha->head;
tha->head = (u32)tha->head + size;
@@ -23,7 +23,7 @@ void* THA_AllocStart1(TwoHeadArena* tha) {
return THA_AllocStart(tha, 1);
}
-void* THA_AllocEnd(TwoHeadArena* tha, u32 size) {
+void* THA_AllocEnd(TwoHeadArena* tha, size_t size) {
u32 mask;
if (size >= 0x10) {
@@ -42,14 +42,14 @@ void* THA_AllocEnd(TwoHeadArena* tha, u32 size) {
return tha->tail;
}
-void* THA_AllocEndAlign16(TwoHeadArena* tha, u32 size) {
+void* THA_AllocEndAlign16(TwoHeadArena* tha, size_t size) {
u32 mask = ~0xF;
tha->tail = (((u32)tha->tail & mask) - size) & mask;
return tha->tail;
}
-void* THA_AllocEndAlign(TwoHeadArena* tha, u32 size, u32 mask) {
+void* THA_AllocEndAlign(TwoHeadArena* tha, size_t size, u32 mask) {
tha->tail = (((u32)tha->tail & mask) - size) & mask;
return tha->tail;
}
@@ -67,7 +67,7 @@ void THA_Init(TwoHeadArena* tha) {
tha->tail = (u32)tha->bufp + tha->size;
}
-void THA_Ct(TwoHeadArena* tha, void* ptr, u32 size) {
+void THA_Ct(TwoHeadArena* tha, void* ptr, size_t size) {
bzero(tha, sizeof(TwoHeadArena));
tha->bufp = ptr;
tha->size = size;
diff --git a/src/code/TwoHeadGfxArena.c b/src/code/TwoHeadGfxArena.c
index 81a3a383b..2f1629765 100644
--- a/src/code/TwoHeadGfxArena.c
+++ b/src/code/TwoHeadGfxArena.c
@@ -1,6 +1,6 @@
#include "global.h"
-void THGA_Ct(TwoHeadGfxArena* thga, Gfx* start, u32 size) {
+void THGA_Ct(TwoHeadGfxArena* thga, Gfx* start, size_t size) {
THA_Ct((TwoHeadArena*)thga, start, size);
}
@@ -44,7 +44,7 @@ Gfx* THGA_AllocStart8Wrapper(TwoHeadGfxArena* thga) {
return THGA_AllocStart8(thga);
}
-Gfx* THGA_AllocEnd(TwoHeadGfxArena* thga, u32 size) {
+Gfx* THGA_AllocEnd(TwoHeadGfxArena* thga, size_t size) {
return THA_AllocEnd((TwoHeadArena*)thga, size);
}
diff --git a/src/code/code_800F23E0.c b/src/code/code_800F23E0.c
deleted file mode 100644
index 008a95db3..000000000
--- a/src/code/code_800F23E0.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "global.h"
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_800F23E0/func_800F23E0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_800F23E0/func_800F2478.s")
diff --git a/src/code/code_80122660.c b/src/code/code_80122660.c
deleted file mode 100644
index 7c0da2932..000000000
--- a/src/code/code_80122660.c
+++ /dev/null
@@ -1,5 +0,0 @@
-#include "global.h"
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_80122660/func_80122660.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/code_80122660/func_80122670.s")
diff --git a/src/code/game.c b/src/code/game.c
index eb26dee8a..a90fc7ac2 100644
--- a/src/code/game.c
+++ b/src/code/game.c
@@ -22,7 +22,7 @@ void Game_SetFramerateDivisor(GameState* gameState, s32 divisor) {
}
void GameState_SetFBFilter(Gfx** gfx, u32 arg1) {
- Gfx* _gfx = *gfx;
+ Gfx* dlist = *gfx;
if ((R_FB_FILTER_TYPE > 0) && (R_FB_FILTER_TYPE < 5)) {
D_801F8010.type = R_FB_FILTER_TYPE;
@@ -30,7 +30,7 @@ void GameState_SetFBFilter(Gfx** gfx, u32 arg1) {
D_801F8010.color.g = R_FB_FILTER_PRIM_COLOR(1);
D_801F8010.color.b = R_FB_FILTER_PRIM_COLOR(2);
D_801F8010.color.a = R_FB_FILTER_A;
- func_80140D10(&D_801F8010, &_gfx, arg1);
+ func_80140D10(&D_801F8010, &dlist, arg1);
} else {
if ((R_FB_FILTER_TYPE == 5) || (R_FB_FILTER_TYPE == 6)) {
D_801F8020.useRgba = (R_FB_FILTER_TYPE == 6);
@@ -42,7 +42,7 @@ void GameState_SetFBFilter(Gfx** gfx, u32 arg1) {
D_801F8020.envColor.g = R_FB_FILTER_ENV_COLOR(1);
D_801F8020.envColor.b = R_FB_FILTER_ENV_COLOR(2);
D_801F8020.envColor.a = R_FB_FILTER_A;
- func_80142100(&D_801F8020, &_gfx, arg1);
+ func_80142100(&D_801F8020, &dlist, arg1);
} else {
if (R_FB_FILTER_TYPE == 7) {
sMonoColors.unk_00 = 0;
@@ -54,27 +54,24 @@ void GameState_SetFBFilter(Gfx** gfx, u32 arg1) {
sMonoColors.envColor.g = R_FB_FILTER_ENV_COLOR(1);
sMonoColors.envColor.b = R_FB_FILTER_ENV_COLOR(2);
sMonoColors.envColor.a = R_FB_FILTER_A;
- VisMono_Draw(&sMonoColors, &_gfx, arg1);
+ VisMono_Draw(&sMonoColors, &dlist, arg1);
}
}
}
- *gfx = _gfx;
+ *gfx = dlist;
}
-void Game_Nop80173534(GameState* gamestate) {
- ;
+void Game_Nop80173534(GameState* gameState) {
}
-void GameState_Draw(GameState* gamestate, GraphicsContext* gfxCtx) {
+void GameState_Draw(GameState* gameState, GraphicsContext* gfxCtx) {
Gfx* nextDisplayList;
Gfx* polyOpa;
OPEN_DISPS(gfxCtx);
- polyOpa = POLY_OPA_DISP;
- nextDisplayList = Graph_GfxPlusOne(POLY_OPA_DISP);
-
+ nextDisplayList = Graph_GfxPlusOne(polyOpa = POLY_OPA_DISP);
gSPDisplayList(OVERLAY_DISP++, nextDisplayList);
if (R_FB_FILTER_TYPE && R_FB_FILTER_ENV_COLOR(3) == 0) {
@@ -98,119 +95,123 @@ void GameState_Draw(GameState* gamestate, GraphicsContext* gfxCtx) {
if (R_ENABLE_ARENA_DBG != 0) {
SpeedMeter_DrawTimeEntries(&D_801F7FF0, gfxCtx);
- SpeedMeter_DrawAllocEntries(&D_801F7FF0, gfxCtx, gamestate);
+ SpeedMeter_DrawAllocEntries(&D_801F7FF0, gfxCtx, gameState);
}
CLOSE_DISPS(gfxCtx);
}
-void Game_ResetSegments(GraphicsContext* gfxCtx) {
- gSPSegment(gfxCtx->polyOpa.p++, 0, 0);
- gSPSegment(gfxCtx->polyOpa.p++, 0xF, gfxCtx->framebuffer);
- gSPSegment(gfxCtx->polyXlu.p++, 0, 0);
- gSPSegment(gfxCtx->polyXlu.p++, 0xF, gfxCtx->framebuffer);
- gSPSegment(gfxCtx->overlay.p++, 0, 0);
- gSPSegment(gfxCtx->overlay.p++, 0xF, gfxCtx->framebuffer);
+void GameState_SetFrameBuffer(GraphicsContext* gfxCtx) {
+ OPEN_DISPS(gfxCtx);
+
+ gSPSegment(POLY_OPA_DISP++, 0, NULL);
+ gSPSegment(POLY_OPA_DISP++, 0xF, gfxCtx->framebuffer);
+ gSPSegment(POLY_XLU_DISP++, 0, NULL);
+ gSPSegment(POLY_XLU_DISP++, 0xF, gfxCtx->framebuffer);
+ gSPSegment(OVERLAY_DISP++, 0, NULL);
+ gSPSegment(OVERLAY_DISP++, 0xF, gfxCtx->framebuffer);
+
+ CLOSE_DISPS(gfxCtx);
}
void func_801736DC(GraphicsContext* gfxCtx) {
Gfx* nextDisplayList;
- Gfx* _polyOpa;
+ Gfx* polyOpa;
+
+ OPEN_DISPS(gfxCtx);
- nextDisplayList = Graph_GfxPlusOne(_polyOpa = gfxCtx->polyOpa.p);
- gSPDisplayList(gfxCtx->overlay.p++, nextDisplayList);
+ nextDisplayList = Graph_GfxPlusOne(polyOpa = gfxCtx->polyOpa.p);
+ gSPDisplayList(OVERLAY_DISP++, nextDisplayList);
gSPEndDisplayList(nextDisplayList++);
- Graph_BranchDlist(_polyOpa, nextDisplayList);
+ Graph_BranchDlist(polyOpa, nextDisplayList);
+
+ POLY_OPA_DISP = nextDisplayList;
- gfxCtx->polyOpa.p = nextDisplayList;
+ CLOSE_DISPS(gfxCtx);
}
-void Game_UpdateInput(GameState* gamestate) {
- Padmgr_GetInput(gamestate->input, 1);
+void Game_UpdateInput(GameState* gameState) {
+ Padmgr_GetInput(gameState->input, 1);
}
-void Game_Update(GameState* gamestate) {
- GraphicsContext* _gCtx;
- _gCtx = gamestate->gfxCtx;
+void Game_Update(GameState* gameState) {
+ GraphicsContext* gfxCtx = gameState->gfxCtx;
- Game_ResetSegments(gamestate->gfxCtx);
+ GameState_SetFrameBuffer(gameState->gfxCtx);
- gamestate->main(gamestate);
+ gameState->main(gameState);
if (R_PAUSE_MENU_MODE != 2) {
- GameState_Draw(gamestate, _gCtx);
- func_801736DC(_gCtx);
+ GameState_Draw(gameState, gfxCtx);
+ func_801736DC(gfxCtx);
}
}
-void Game_IncrementFrameCount(GameState* gamestate) {
- Game_Nop80173534(gamestate);
- gamestate->frames++;
+void Game_IncrementFrameCount(GameState* gameState) {
+ Game_Nop80173534(gameState);
+ gameState->frames++;
}
-void Game_InitHeap(GameState* gamestate, u32 size) {
- GameState* _ctx;
- void* buf;
-
- _ctx = gamestate;
- buf = Gamealloc_Alloc(&_ctx->alloc, size);
+void GameState_InitArena(GameState* gameState, size_t size) {
+ GameAlloc* alloc = &gameState->alloc;
+ void* buf = GameAlloc_Malloc(alloc, size);
if (buf) {
- THA_Ct(&gamestate->heap, buf, size);
+ THA_Ct(&gameState->heap, buf, size);
return;
}
- THA_Ct(&gamestate->heap, NULL, 0);
- __assert("../game.c", 0x40B);
+ THA_Ct(&gameState->heap, NULL, 0);
+ __assert("../game.c", 1035);
}
-void Game_ResizeHeap(GameState* gamestate, u32 size) {
+void GameState_Realloc(GameState* gameState, size_t size) {
GameAlloc* alloc;
- void* buf;
- u32 systemMaxFree;
- u32 bytesFree;
- u32 bytesAllocated;
+ void* gameArena;
+ size_t systemMaxFree;
+ size_t bytesFree;
+ size_t bytesAllocated;
void* heapStart;
- heapStart = gamestate->heap.bufp;
- alloc = &gamestate->alloc;
- THA_Dt(&gamestate->heap);
- Gamealloc_Free(alloc, heapStart);
+ heapStart = gameState->heap.bufp;
+ alloc = &gameState->alloc;
+ THA_Dt(&gameState->heap);
+ GameAlloc_Free(alloc, heapStart);
SystemArena_AnalyzeArena(&systemMaxFree, &bytesFree, &bytesAllocated);
size = ((systemMaxFree - (sizeof(ArenaNode))) < size) ? (0) : (size);
- if (!size) {
+ if (size == 0) {
size = systemMaxFree - (sizeof(ArenaNode));
}
- if ((buf = Gamealloc_Alloc(alloc, size)) != NULL) {
- THA_Ct(&gamestate->heap, buf, size);
+ if ((gameArena = GameAlloc_Malloc(alloc, size)) != NULL) {
+ THA_Ct(&gameState->heap, gameArena, size);
} else {
- THA_Ct(&gamestate->heap, 0, 0);
- __assert("../game.c", 0x432);
+ THA_Ct(&gameState->heap, 0, 0);
+ __assert("../game.c", 1074);
}
}
-void Game_StateInit(GameState* gamestate, GameStateFunc gameStateInit, GraphicsContext* gfxCtx) {
- gamestate->gfxCtx = gfxCtx;
- gamestate->frames = 0U;
- gamestate->main = NULL;
- gamestate->destroy = NULL;
- gamestate->running = 1;
- gfxCtx->unk274 = D_801FBB88;
+void GameState_Init(GameState* gameState, GameStateFunc init, GraphicsContext* gfxCtx) {
+ gameState->gfxCtx = gfxCtx;
+ gameState->frames = 0U;
+ gameState->main = NULL;
+ gameState->destroy = NULL;
+ gameState->running = 1;
+ gfxCtx->viMode = D_801FBB88;
gfxCtx->viConfigFeatures = gViConfigFeatures;
gfxCtx->viConfigXScale = gViConfigXScale;
gfxCtx->viConfigYScale = gViConfigYScale;
- gamestate->nextGameStateInit = NULL;
- gamestate->nextGameStateSize = 0U;
+ gameState->nextGameStateInit = NULL;
+ gameState->nextGameStateSize = 0U;
{
s32 requiredScopeTemp;
- Gamealloc_Init(&gamestate->alloc);
- Game_InitHeap(gamestate, 0x100000);
- Game_SetFramerateDivisor(gamestate, 3);
+ GameAlloc_Init(&gameState->alloc);
+ GameState_InitArena(gameState, 0x100000);
+ Game_SetFramerateDivisor(gameState, 3);
- gameStateInit(gamestate);
+ init(gameState);
func_80140CE0(&D_801F8010);
func_801420C0(&D_801F8020);
@@ -219,17 +220,17 @@ void Game_StateInit(GameState* gamestate, GameStateFunc gameStateInit, GraphicsC
func_801773A0(&D_801F7FF0);
func_8013ED9C();
- osSendMesg(&gamestate->gfxCtx->unk5C, NULL, 1);
+ osSendMesg(&gameState->gfxCtx->unk5C, NULL, 1);
}
}
-void Game_StateFini(GameState* gamestate) {
+void GameState_Destroy(GameState* gameState) {
func_80172BC0();
func_8019E014();
- osRecvMesg(&gamestate->gfxCtx->unk5C, 0, 1);
+ osRecvMesg(&gameState->gfxCtx->unk5C, NULL, OS_MESG_BLOCK);
- if (gamestate->destroy != 0) {
- gamestate->destroy(gamestate);
+ if (gameState->destroy != NULL) {
+ gameState->destroy(gameState);
}
func_8013EDD0();
@@ -238,28 +239,28 @@ void Game_StateFini(GameState* gamestate) {
func_801420F4(&D_801F8020);
func_80141900(&sMonoColors);
func_80140900(&D_801F8048);
- THA_Dt(&gamestate->heap);
- Gamealloc_FreeAll(&gamestate->alloc);
+ THA_Dt(&gameState->heap);
+ GameAlloc_Cleanup(&gameState->alloc);
}
-GameStateFunc Game_GetNextStateInit(GameState* gamestate) {
- return gamestate->nextGameStateInit;
+GameStateFunc GameState_GetNextStateInit(GameState* gameState) {
+ return gameState->nextGameStateInit;
}
-u32 Game_GetNextStateSize(GameState* gamestate) {
- return gamestate->nextGameStateSize;
+size_t Game_GetNextStateSize(GameState* gameState) {
+ return gameState->nextGameStateSize;
}
-u32 Game_GetShouldContinue(GameState* gamestate) {
- return gamestate->running;
+u32 GameState_IsRunning(GameState* gameState) {
+ return gameState->running;
}
-s32 Game_GetHeapFreeSize(GameState* gamestate) {
- return THA_GetSize(&gamestate->heap);
+s32 GameState_GetArenaSize(GameState* gameState) {
+ return THA_GetSize(&gameState->heap);
}
-s32 func_80173B48(GameState* gamestate) {
- s32 result;
- result = OS_CYCLES_TO_NSEC(gamestate->framerateDivisor * sIrqMgrRetraceTime) - OS_CYCLES_TO_NSEC(D_801FBAF0);
+s32 func_80173B48(GameState* gameState) {
+ s32 result = OS_CYCLES_TO_NSEC(gameState->framerateDivisor * sIrqMgrRetraceTime) - OS_CYCLES_TO_NSEC(D_801FBAF0);
+
return result;
}
diff --git a/src/code/gamealloc.c b/src/code/gamealloc.c
index 34d595f79..541f9125b 100644
--- a/src/code/gamealloc.c
+++ b/src/code/gamealloc.c
@@ -1,11 +1,59 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/gamealloc/func_80173BF0.s")
+void GameAlloc_Log(GameAlloc* this) {
+ GameAllocEntry* iter;
-#pragma GLOBAL_ASM("asm/non_matchings/code/gamealloc/Gamealloc_Alloc.s")
+ iter = this->base.next;
+ while (iter != &this->base) {
+ iter = iter->next;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/gamealloc/Gamealloc_Free.s")
+void* GameAlloc_Malloc(GameAlloc* this, size_t size) {
+ GameAllocEntry* ptr = SystemArena_Malloc(size + sizeof(GameAllocEntry));
-#pragma GLOBAL_ASM("asm/non_matchings/code/gamealloc/Gamealloc_FreeAll.s")
+ if (ptr != NULL) {
+ ptr->size = size;
+ ptr->prev = this->head;
+ this->head->next = ptr;
+ this->head = ptr;
+ ptr->next = &this->base;
+ this->base.prev = this->head;
+ return ptr + 1;
+ } else {
+ return NULL;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/gamealloc/Gamealloc_Init.s")
+void GameAlloc_Free(GameAlloc* this, void* data) {
+ GameAllocEntry* ptr;
+
+ if (data != NULL) {
+ ptr = &((GameAllocEntry*)data)[-1];
+ ptr->prev->next = ptr->next;
+ ptr->next->prev = ptr->prev;
+ this->head = this->base.prev;
+ SystemArena_Free(ptr);
+ }
+}
+
+void GameAlloc_Cleanup(GameAlloc* this) {
+ GameAllocEntry* next = this->base.next;
+ GameAllocEntry* cur;
+
+ while (&this->base != next) {
+ cur = next;
+ next = next->next;
+ SystemArena_Free(cur);
+ }
+
+ this->head = &this->base;
+ this->base.next = &this->base;
+ this->base.prev = &this->base;
+}
+
+void GameAlloc_Init(GameAlloc* this) {
+ this->head = &this->base;
+ this->base.next = &this->base;
+ this->base.prev = &this->base;
+}
diff --git a/src/code/listalloc.c b/src/code/listalloc.c
index 3880806a1..da294a109 100644
--- a/src/code/listalloc.c
+++ b/src/code/listalloc.c
@@ -1,9 +1,62 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/listalloc/func_80174AA0.s")
+ListAlloc* ListAlloc_Init(ListAlloc* this) {
+ this->prev = NULL;
+ this->next = NULL;
+ return this;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/listalloc/func_80174AB4.s")
+void* ListAlloc_Alloc(ListAlloc* this, size_t size) {
+ ListAlloc* ptr = SystemArena_Malloc(size + sizeof(ListAlloc));
+ ListAlloc* next;
-#pragma GLOBAL_ASM("asm/non_matchings/code/listalloc/func_80174B20.s")
+ if (ptr == NULL) {
+ return NULL;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/listalloc/func_80174BA0.s")
+ next = this->next;
+ if (next != NULL) {
+ next->next = ptr;
+ }
+
+ ptr->prev = next;
+ ptr->next = NULL;
+ this->next = ptr;
+
+ if (this->prev == NULL) {
+ this->prev = ptr;
+ }
+
+ return (u8*)ptr + sizeof(ListAlloc);
+}
+
+void ListAlloc_Free(ListAlloc* this, void* data) {
+ ListAlloc* ptr = &((ListAlloc*)data)[-1];
+
+ if (ptr->prev != NULL) {
+ ptr->prev->next = ptr->next;
+ }
+
+ if (ptr->next != NULL) {
+ ptr->next->prev = ptr->prev;
+ }
+
+ if (this->prev == ptr) {
+ this->prev = ptr->next;
+ }
+
+ if (this->next == ptr) {
+ this->next = ptr->prev;
+ }
+
+ SystemArena_Free(ptr);
+}
+
+void ListAlloc_FreeAll(ListAlloc* this) {
+ ListAlloc* iter = this->prev;
+
+ while (iter != NULL) {
+ ListAlloc_Free(this, (u8*)iter + sizeof(ListAlloc));
+ iter = this->prev;
+ }
+}
diff --git a/src/code/main.c b/src/code/main.c
index a2b859991..59ffb6a32 100644
--- a/src/code/main.c
+++ b/src/code/main.c
@@ -28,36 +28,36 @@ void Main(void* arg) {
R_ENABLE_ARENA_DBG = 0;
- osCreateMesgQueue(&siEventCallbackQueue, siEventCallbackBuffer, ARRAY_COUNT(siEventCallbackBuffer));
- osSetEventMesg(OS_EVENT_SI, &siEventCallbackQueue, NULL);
+ osCreateMesgQueue(&sSiIntMsgQ, sSiIntMsgBuf, ARRAY_COUNT(sSiIntMsgBuf));
+ osSetEventMesg(OS_EVENT_SI, &sSiIntMsgQ, NULL);
- osCreateMesgQueue(&mainIrqmgrCallbackQueue, mainIrqCallbackBuffer, ARRAY_COUNT(mainIrqCallbackBuffer));
+ osCreateMesgQueue(&irqMgrMsgQ, irqMgrMsgBuf, ARRAY_COUNT(irqMgrMsgBuf));
StackCheck_Init(&schedStackEntry, schedStack, schedStack + sizeof(schedStack), 0, 0x100, "sched");
Sched_Init(&gSchedContext, schedStack + sizeof(schedStack), Z_PRIORITY_SCHED, D_8009B290, 1, &gIrqMgr);
CIC6105_AddRomInfoFaultPage();
- IrqMgr_AddClient(&gIrqMgr, &mainIrqmgrCallbackNode, &mainIrqmgrCallbackQueue);
+ IrqMgr_AddClient(&gIrqMgr, &irqClient, &irqMgrMsgQ);
StackCheck_Init(&audioStackEntry, audioStack, audioStack + sizeof(audioStack), 0, 0x100, "audio");
AudioMgr_Init(&audioContext, audioStack + sizeof(audioStack), Z_PRIORITY_AUDIOMGR, 0xA, &gSchedContext, &gIrqMgr);
StackCheck_Init(&padmgrStackEntry, padmgrStack, padmgrStack + sizeof(padmgrStack), 0, 0x100, "padmgr");
- Padmgr_Start(&siEventCallbackQueue, &gIrqMgr, 7, Z_PRIORITY_PADMGR, padmgrStack + sizeof(padmgrStack));
+ PadMgr_Init(&sSiIntMsgQ, &gIrqMgr, 7, Z_PRIORITY_PADMGR, padmgrStack + sizeof(padmgrStack));
AudioMgr_Unlock(&audioContext);
- StackCheck_Init(&graphStackEntry, graphStack, graphStack + sizeof(graphStack), 0, 0x100, "graph");
- osCreateThread(&graphOSThread, Z_THREAD_ID_GRAPH, Graph_ThreadEntry, arg, graphStack + sizeof(graphStack),
+ StackCheck_Init(&sGraphStackInfo, sGraphStack, sGraphStack + sizeof(sGraphStack), 0, 0x100, "graph");
+ osCreateThread(&sGraphThread, Z_THREAD_ID_GRAPH, Graph_ThreadEntry, arg, sGraphStack + sizeof(sGraphStack),
Z_PRIORITY_GRAPH);
- osStartThread(&graphOSThread);
+ osStartThread(&sGraphThread);
exit = false;
while (!exit) {
msg = NULL;
- osRecvMesg(&mainIrqmgrCallbackQueue, (OSMesg)&msg, OS_MESG_BLOCK);
+ osRecvMesg(&irqMgrMsgQ, (OSMesg)&msg, OS_MESG_BLOCK);
if (msg == NULL) {
break;
}
@@ -72,6 +72,6 @@ void Main(void* arg) {
}
}
- IrqMgr_RemoveClient(&gIrqMgr, &mainIrqmgrCallbackNode);
- osDestroyThread(&graphOSThread);
+ IrqMgr_RemoveClient(&gIrqMgr, &irqClient);
+ osDestroyThread(&sGraphThread);
}
diff --git a/src/code/padmgr.c b/src/code/padmgr.c
index 65b9d0ff4..a8ef1db15 100644
--- a/src/code/padmgr.c
+++ b/src/code/padmgr.c
@@ -54,4 +54,4 @@
#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_ThreadEntry.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/Padmgr_Start.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/padmgr/PadMgr_Init.s")
diff --git a/src/code/sys_matrix.c b/src/code/sys_matrix.c
index cab2e563a..a4d5b9379 100644
--- a/src/code/sys_matrix.c
+++ b/src/code/sys_matrix.c
@@ -1,92 +1,92 @@
#include "global.h"
-void SysMatrix_StateAlloc(GameState* gamestate) {
- sMatrixStack = (MtxF*)THA_AllocEndAlign16(&gamestate->heap, 0x500);
+void Matrix_StateAlloc(GameState* gameState) {
+ sMatrixStack = (MtxF*)THA_AllocEndAlign16(&gameState->heap, 0x500);
sCurrentMatrix = sMatrixStack;
}
-void SysMatrix_StatePush(void) {
+void Matrix_StatePush(void) {
MtxF* prev = sCurrentMatrix;
sCurrentMatrix++;
Matrix_MtxFCopy(sCurrentMatrix, prev);
}
-void SysMatrix_StatePop(void) {
+void Matrix_StatePop(void) {
sCurrentMatrix--;
}
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_CopyCurrentState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_CopyCurrentState.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_SetCurrentState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetCurrentState.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetCurrentState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetCurrentState.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertMatrix.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertMatrix.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertTranslation.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertTranslation.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_Scale.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertXRotation_s.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertXRotation_s.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertXRotation_f.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertXRotation_f.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_RotateStateAroundXAxis.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_RotateStateAroundXAxis.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_SetStateXRotation.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetStateXRotation.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_RotateY.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertYRotation_f.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertYRotation_f.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertZRotation_s.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertZRotation_s.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertZRotation_f.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertZRotation_f.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertRotation.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotation.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_RotateAndTranslateState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_JointPosition.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_SetStateRotationAndTranslation.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_SetStateRotationAndTranslation.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_ToRSPMatrix.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_ToRSPMatrix.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetStateAsRSPMatrix.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_ToMtx.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_NewMtx.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_AppendToPolyOpaDisp.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_AppendToPolyOpaDisp.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_MultiplyVector3fByState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fByState.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetStateTranslation.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslation.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetStateTranslationAndScaledX.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledX.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetStateTranslationAndScaledY.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledY.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_GetStateTranslationAndScaledZ.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_GetStateTranslationAndScaledZ.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_MultiplyVector3fXZByCurrentState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fXZByCurrentState.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MtxFCopy.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_FromRSPMatrix.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_FromRSPMatrix.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_MultiplyVector3fByMatrix.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_MultiplyVector3fByMatrix.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_TransposeXYZ.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_TransposeXYZ.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_NormalizeXYZ.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_NormalizeXYZ.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/func_8018219C.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/func_801822C4.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertRotationAroundUnitVector_f.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotationAroundUnitVector_f.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/SysMatrix_InsertRotationAroundUnitVector_s.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/Matrix_InsertRotationAroundUnitVector_s.s")
#pragma GLOBAL_ASM("asm/non_matchings/code/sys_matrix/func_80182C90.s")
diff --git a/src/code/z_DLF.c b/src/code/z_DLF.c
index 1ae43c91d..688a5af15 100644
--- a/src/code/z_DLF.c
+++ b/src/code/z_DLF.c
@@ -1,5 +1,5 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_DLF/DLF_LoadGameState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_DLF/Overlay_LoadGameState.s")
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_DLF/DLF_FreeGameState.s")
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_DLF/Overlay_FreeGameState.s")
diff --git a/src/code/z_actor.c b/src/code/z_actor.c
index 2f1277057..8d87e539b 100644
--- a/src/code/z_actor.c
+++ b/src/code/z_actor.c
@@ -53,7 +53,7 @@ void ActorShadow_Draw(Actor* actor, Lights* lights, GlobalContext* globalCtx, Gf
}
func_800C0094(actor->floorPoly, actor->world.pos.x, actor->floorHeight, actor->world.pos.z, &mtx);
- SysMatrix_SetCurrentState(&mtx);
+ Matrix_SetCurrentState(&mtx);
if (dlist != D_04076BC0) {
Matrix_RotateY((f32)actor->shape.rot.y * (M_PI / 32768), MTXMODE_APPLY);
@@ -117,7 +117,7 @@ void func_800B40E0(GlobalContext* globalCtx, Light* light, MtxF* arg2, s32 arg3,
sp58 = Math_FAtan2F(light->l.dir[0], light->l.dir[2]);
arg6 *= (4.5f - (light->l.dir[1] * 0.035f));
arg6 = (arg6 < 1.0f) ? 1.0f : arg6;
- SysMatrix_SetCurrentState(arg2);
+ Matrix_SetCurrentState(arg2);
Matrix_RotateY(sp58, MTXMODE_APPLY);
Matrix_Scale(arg5, 1.0f, arg5 * arg6, MTXMODE_APPLY);
@@ -744,7 +744,7 @@ void Actor_FreeOverlay(ActorOverlay* entry) {
if ((entry->allocType & 1) != 0) {
entry->loadedRamAddr = NULL;
} else {
- zelda_free(ramAddr);
+ ZeldaArena_Free(ramAddr);
entry->loadedRamAddr = NULL;
}
}
diff --git a/src/code/z_actor_dlftbls.c b/src/code/z_actor_dlftbls.c
index 4165e4c9b..f33fcd538 100644
--- a/src/code/z_actor_dlftbls.c
+++ b/src/code/z_actor_dlftbls.c
@@ -736,7 +736,7 @@ void* ActorOverlayTable_FaultAddrConv(void* arg0, void* arg1) {
s32 i;
u8* ramStart;
u8* ramEnd;
- u32 size;
+ size_t size;
u32 offset;
for (i = 0; i < gMaxActorId; i++, overlayEntry++) {
diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c
index 6ea0b2fcf..059fbce09 100644
--- a/src/code/z_collision_check.c
+++ b/src/code/z_collision_check.c
@@ -327,7 +327,7 @@ s32 Collider_FreeJntSph(GlobalContext* globalCtx, ColliderJntSph* collider) {
collider->count = 0;
if (collider->elements != NULL) {
- zelda_free(collider->elements);
+ ZeldaArena_Free(collider->elements);
}
collider->elements = NULL;
return 1;
@@ -359,7 +359,7 @@ s32 Collider_SetJntSphToActor(GlobalContext* globalCtx, ColliderJntSph* collider
Collider_SetBaseToActor(globalCtx, &collider->base, &src->base);
collider->count = src->count;
- collider->elements = zelda_malloc(src->count * sizeof(ColliderJntSphElement));
+ collider->elements = ZeldaArena_Malloc(src->count * sizeof(ColliderJntSphElement));
if (collider->elements == NULL) {
collider->count = 0;
@@ -385,7 +385,7 @@ s32 Collider_SetJntSphAllocType1(GlobalContext* globalCtx, ColliderJntSph* spher
Collider_SetBaseType1(globalCtx, &sphereGroup->base, actor, &src->base);
sphereGroup->count = src->count;
- sphereGroup->elements = zelda_malloc(src->count * sizeof(ColliderJntSphElement));
+ sphereGroup->elements = ZeldaArena_Malloc(src->count * sizeof(ColliderJntSphElement));
if (sphereGroup->elements == NULL) {
sphereGroup->count = 0;
@@ -681,7 +681,7 @@ s32 Collider_FreeTris(GlobalContext* globalCtx, ColliderTris* tris) {
tris->count = 0;
if (tris->elements != NULL) {
- zelda_free(tris->elements);
+ ZeldaArena_Free(tris->elements);
}
tris->elements = NULL;
@@ -714,7 +714,7 @@ s32 Collider_SetTrisAllocType1(GlobalContext* globalCtx, ColliderTris* tris, Act
Collider_SetBaseType1(globalCtx, &tris->base, actor, &src->base);
tris->count = src->count;
- tris->elements = zelda_malloc(tris->count * sizeof(ColliderTrisElement));
+ tris->elements = ZeldaArena_Malloc(tris->count * sizeof(ColliderTrisElement));
if (tris->elements == NULL) {
tris->count = 0;
@@ -3691,7 +3691,7 @@ void Collider_UpdateSpheres(s32 limb, ColliderJntSph* collider) {
D_801EE1C0.x = collider->elements[i].dim.modelSphere.center.x;
D_801EE1C0.y = collider->elements[i].dim.modelSphere.center.y;
D_801EE1C0.z = collider->elements[i].dim.modelSphere.center.z;
- SysMatrix_MultiplyVector3fByState(&D_801EE1C0, &D_801EE1D0);
+ Matrix_MultiplyVector3fByState(&D_801EE1C0, &D_801EE1D0);
collider->elements[i].dim.worldSphere.center.x = D_801EE1D0.x;
collider->elements[i].dim.worldSphere.center.y = D_801EE1D0.y;
collider->elements[i].dim.worldSphere.center.z = D_801EE1D0.z;
@@ -3733,7 +3733,7 @@ void Collider_UpdateSphere(s32 limb, ColliderSphere* collider) {
D_801EE1E0.x = collider->dim.modelSphere.center.x;
D_801EE1E0.y = collider->dim.modelSphere.center.y;
D_801EE1E0.z = collider->dim.modelSphere.center.z;
- SysMatrix_MultiplyVector3fByState(&D_801EE1E0, &D_801EE1F0);
+ Matrix_MultiplyVector3fByState(&D_801EE1E0, &D_801EE1F0);
collider->dim.worldSphere.center.x = D_801EE1F0.x;
collider->dim.worldSphere.center.y = D_801EE1F0.y;
collider->dim.worldSphere.center.z = D_801EE1F0.z;
diff --git a/src/code/z_eff_footmark.c b/src/code/z_eff_footmark.c
index ba2c79f71..d246aaffa 100644
--- a/src/code/z_eff_footmark.c
+++ b/src/code/z_eff_footmark.c
@@ -106,8 +106,8 @@ void EffFootmark_Draw(GlobalContext* globalCtx) {
for (footmark = globalCtx->footprintInfo, i = 0; i < 100; i++, footmark++) {
if (footmark->actor != NULL) {
- SysMatrix_SetCurrentState(&footmark->displayMatrix);
- Matrix_Scale(footmark->size * 0.00390625f * 0.7f, 1, footmark->size * 0.00390625f, 1);
+ Matrix_SetCurrentState(&footmark->displayMatrix);
+ Matrix_Scale(footmark->size * (1.0f / 0x100) * 0.7f, 1, footmark->size * (1.0f / 0x100), MTXMODE_APPLY);
gSPMatrix(gfxCtx->polyXlu.p++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD);
diff --git a/src/code/z_effect_soft_sprite.c b/src/code/z_effect_soft_sprite.c
index 0ed19c050..47c2202f1 100644
--- a/src/code/z_effect_soft_sprite.c
+++ b/src/code/z_effect_soft_sprite.c
@@ -41,7 +41,7 @@ void EffectSS_Clear(GlobalContext* globalCtx) {
for (i = 0; i < EFFECT_SS_MAX; i++) {
addr = overlay->loadedRamAddr;
if (addr != NULL) {
- zelda_free(addr);
+ ZeldaArena_Free(addr);
}
overlay->loadedRamAddr = 0;
@@ -175,7 +175,7 @@ void EffectSs_Spawn(GlobalContext* globalCtx, s32 type, s32 priority, void* init
initInfo = entry->initInfo;
} else {
if (entry->loadedRamAddr == NULL) {
- entry->loadedRamAddr = zelda_mallocR(overlaySize);
+ entry->loadedRamAddr = ZeldaArena_MallocR(overlaySize);
if (entry->loadedRamAddr == NULL) {
return;
diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c
index aa461153c..cf27d2251 100644
--- a/src/code/z_effect_soft_sprite_old_init.c
+++ b/src/code/z_effect_soft_sprite_old_init.c
@@ -403,7 +403,7 @@ void EffectSsGSpk_SpawnSmall(GlobalContext* globalCtx, Actor* actor, Vec3f* pos,
// EffectSsDFire Spawn Functions
void EffectSsDFire_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16 scaleStep,
- s16 alpha, s16 fadeDelay, s16 life, s32 arg9) {
+ s16 alpha, s16 fadeDelay, s16 arg8, s32 life) {
EffectSsDFireInitParams initParams;
Math_Vec3f_Copy(&initParams.pos, pos);
@@ -413,8 +413,8 @@ void EffectSsDFire_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity,
initParams.scaleStep = scaleStep;
initParams.alpha = alpha;
initParams.fadeDelay = fadeDelay;
+ initParams.unk_2C = arg8;
initParams.life = life;
- initParams.unk_30 = arg9;
EffectSs_Spawn(globalCtx, EFFECT_SS_D_FIRE, 128, &initParams);
}
@@ -535,8 +535,8 @@ void EffectSsDtBubble_SpawnCustomColor(GlobalContext* globalCtx, Vec3f* pos, Vec
/**
* Spawn a single fragment
*
- * Notes:
- * - if a display list is not provided, D_0400C0D0 (wilted deku fragment) will be used as default
+ * * Notes:
+ * - if a display list is not provided, an unknown default will be used as default
* - the unused arg does not do anything, any value can be passed here
* - due to how life is implemented it is capped at 200. Any value over 200 is accepted, but the fragment will
* only live for 200 frames
@@ -960,6 +960,7 @@ void EffectSsExtra_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity,
}
// EffectSsDeadDb Spawn Functions
+
void EffectSsDeadDb_Spawn(GlobalContext* globalCtx, Vec3f* pos, Vec3f* velocity, Vec3f* accel, Color_RGBA8* prim,
Color_RGBA8* env, s16 scale, s16 scaleStep, s32 unk) {
EffectSsDeadDbInitParams initParams;
diff --git a/src/code/z_en_a_keep.c b/src/code/z_en_a_keep.c
index fbd323885..d5125d249 100644
--- a/src/code/z_en_a_keep.c
+++ b/src/code/z_en_a_keep.c
@@ -1,48 +1,57 @@
#include "global.h"
-void EnAObj_Init(ActorEnAObj* this, GlobalContext* globalCtx) {
- ActorEnAObj* s0 = (ActorEnAObj*)this;
- s0->base.textId = ((s0->base.params >> 8) & 0xFF) | 0x300;
- s0->base.params = (s0->base.params & 0xFF) - 9;
- Actor_ProcessInitChain((Actor*)s0, &enAObjInitVar);
- ActorShape_Init(&s0->base.shape, 0, (ActorShadowFunc)func_800B3FC0, 12);
- Collider_InitAndSetCylinder(globalCtx, &s0->collision, (Actor*)s0, &enAObjCylinderInit);
- Collider_UpdateCylinder((Actor*)s0, &s0->collision);
- s0->base.colChkInfo.mass = 255;
- s0->update = (ActorFunc)EnAObj_Update1;
+#define THIS ((EnAObj*)thisx)
+
+void EnAObj_Update1(EnAObj* this, GlobalContext* globalCtx);
+void EnAObj_Update2(EnAObj* this, GlobalContext* globalCtx);
+
+void EnAObj_Init(Actor* thisx, GlobalContext* globalCtx) {
+ EnAObj* this = THIS;
+
+ this->actor.textId = ((this->actor.params >> 8) & 0xFF) | 0x300;
+ this->actor.params = (this->actor.params & 0xFF) - 9;
+ Actor_ProcessInitChain(&this->actor, &enAObjInitVar);
+ ActorShape_Init(&this->actor.shape, 0, func_800B3FC0, 12);
+ Collider_InitAndSetCylinder(globalCtx, &this->collision, &this->actor, &enAObjCylinderInit);
+ Collider_UpdateCylinder(&this->actor, &this->collision);
+ this->actor.colChkInfo.mass = 255;
+ this->actionFunc = EnAObj_Update1;
}
-void EnAObj_Destroy(ActorEnAObj* this, GlobalContext* globalCtx) {
- ColliderCylinder* a2 = &this->collision;
- Collider_DestroyCylinder(globalCtx, a2);
+void EnAObj_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+ EnAObj* this = THIS;
+
+ Collider_DestroyCylinder(globalCtx, &this->collision);
}
-void EnAObj_Update1(ActorEnAObj* this, GlobalContext* globalCtx) {
- s16 v0;
- s32 v1;
- if (func_800B84D0((Actor*)this, globalCtx) != 0) {
- this->update = (ActorFunc)EnAObj_Update2;
+void EnAObj_Update1(EnAObj* this, GlobalContext* globalCtx) {
+ s32 yawDiff;
+
+ if (func_800B84D0(&this->actor, globalCtx)) {
+ this->actionFunc = EnAObj_Update2;
} else {
- v0 = this->base.yawTowardsPlayer - this->base.shape.rot.y;
- v1 = (v0 < 0) ? -v0 : v0;
- if ((v1 < 10240) || ((this->base.params == 1) && (v1 > 22528))) {
- func_800B863C((Actor*)this, globalCtx);
+ yawDiff = ABS_ALT((s16)(this->actor.yawTowardsPlayer - this->actor.shape.rot.y));
+
+ if ((yawDiff < 0x2800) || ((this->actor.params == 1) && (yawDiff > 0x5800))) {
+ func_800B863C(&this->actor, globalCtx);
}
}
}
-void EnAObj_Update2(ActorEnAObj* this, GlobalContext* globalCtx) {
- if (func_800B867C((Actor*)this, globalCtx) != 0) {
- this->update = (ActorFunc)EnAObj_Update1;
+void EnAObj_Update2(EnAObj* this, GlobalContext* globalCtx) {
+ if (func_800B867C(&this->actor, globalCtx)) {
+ this->actionFunc = EnAObj_Update1;
}
}
-void EnAObj_Update(ActorEnAObj* this, GlobalContext* globalCtx) {
- (this->update)((Actor*)this, (GlobalContext*)globalCtx);
- Actor_SetHeight((Actor*)this, 45.0f);
- CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, (Collider*)&this->collision);
+void EnAObj_Update(Actor* thisx, GlobalContext* globalCtx) {
+ EnAObj* this = THIS;
+
+ this->actionFunc(this, globalCtx);
+ Actor_SetHeight(&this->actor, 45.0f);
+ CollisionCheck_SetOC(globalCtx, &globalCtx->colChkCtx, &this->collision.base);
}
-void EnAObj_Draw(ActorEnAObj* this, GlobalContext* globalCtx) {
- func_800BDFC0(globalCtx, enAObjDisplayLists[this->base.params]);
+void EnAObj_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ func_800BDFC0(globalCtx, enAObjDisplayLists[thisx->params]);
}
diff --git a/src/code/z_en_item00.c b/src/code/z_en_item00.c
index 0a412c2da..acae2e0ce 100644
--- a/src/code/z_en_item00.c
+++ b/src/code/z_en_item00.c
@@ -660,7 +660,7 @@ void EnItem00_Draw(Actor* thisx, GlobalContext* globalCtx) {
this->unk152 = -2;
}
} else {
- Matrix_Scale(16.0f, 16.0f, 16.0f, 1);
+ Matrix_Scale(16.0f, 16.0f, 16.0f, MTXMODE_APPLY);
GetItem_Draw(globalCtx, 8);
}
break;
@@ -785,7 +785,7 @@ void EnItem00_DrawHeartContainer(EnItem00* actor, GlobalContext* globalCtx) {
OPEN_DISPS(globalCtx->state.gfxCtx);
func_8012C2DC(globalCtx->state.gfxCtx);
- Matrix_Scale(20.0f, 20.0f, 20.0f, 1);
+ Matrix_Scale(20.0f, 20.0f, 20.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_MODELVIEW | G_MTX_LOAD);
diff --git a/src/code/z_fcurve_data.c b/src/code/z_fcurve_data.c
new file mode 100644
index 000000000..a0bf887e1
--- /dev/null
+++ b/src/code/z_fcurve_data.c
@@ -0,0 +1,5 @@
+#include "global.h"
+
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F23E0.s")
+
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data/func_800F2478.s")
diff --git a/src/code/z_fcurve_data_skelanime.c b/src/code/z_fcurve_data_skelanime.c
index 79439550d..c6ee50d87 100644
--- a/src/code/z_fcurve_data_skelanime.c
+++ b/src/code/z_fcurve_data_skelanime.c
@@ -1,15 +1,181 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F2620.s")
+void SkelCurve_Clear(SkelAnimeCurve* skelCurve) {
+ skelCurve->limbCount = 0;
+ skelCurve->limbList = NULL;
+ skelCurve->transUpdIdx = NULL;
+ skelCurve->animCurFrame = 0.0f;
+ skelCurve->animSpeed = 0.0f;
+ skelCurve->animFinalFrame = 0.0f;
+ skelCurve->unk0C = 0.0f;
+ skelCurve->transforms = NULL;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F2650.s")
+s32 SkelCurve_Init(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve, SkelCurveLimbList* limbListSeg,
+ TransformUpdateIndex* transUpdIdx) {
+ SkelCurveLimb** limbs;
+ SkelCurveLimbList* limbList = (SkelCurveLimbList*)Lib_SegmentedToVirtual(limbListSeg);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F26C0.s")
+ skelCurve->limbCount = limbList->limbCount;
+ skelCurve->limbList = (SkelCurveLimb**)Lib_SegmentedToVirtual(limbList->limbs);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F26F0.s")
+ skelCurve->transforms = ZeldaArena_Malloc(sizeof(*skelCurve->transforms) * skelCurve->limbCount);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F2728.s")
+ do {
+ skelCurve->animCurFrame = 0.0f;
+ } while (0);
+ return 1;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F29A0.s")
+void SkelCurve_Destroy(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
+ if (skelCurve->transforms != NULL) {
+ ZeldaArena_Free(skelCurve->transforms);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/func_800F2CD8.s")
+void SkelCurve_SetAnim(SkelAnimeCurve* skelCurve, TransformUpdateIndex* transUpdIdx, f32 arg2, f32 animFinalFrame,
+ f32 animCurFrame, f32 animSpeed) {
+ skelCurve->unk0C = arg2 - skelCurve->animSpeed;
+ skelCurve->animFinalFrame = animFinalFrame;
+ skelCurve->animCurFrame = animCurFrame;
+ skelCurve->animSpeed = animSpeed;
+ skelCurve->transUpdIdx = transUpdIdx;
+}
+
+#ifdef NON_MATCHING
+/* Should be functionally equivalent, also migrating rodata makes it a lot cleaner */
+s32 SkelCurve_Update(GlobalContext* globalCtx, SkelAnimeCurve* skelCurve) {
+ s16* transforms;
+ u8* transformRefIdx;
+ TransformUpdateIndex* transformIndex;
+ u16* transformCopyValues;
+ s32 i;
+ s32 ret = 0;
+ s32 k;
+ TransformData* transData;
+ f32 transformValue;
+ s32 j;
+
+ transformIndex = Lib_SegmentedToVirtual(skelCurve->transUpdIdx);
+ transformRefIdx = Lib_SegmentedToVirtual(transformIndex->refIndex);
+ transData = Lib_SegmentedToVirtual(transformIndex->transformData);
+ transformCopyValues = Lib_SegmentedToVirtual(transformIndex->copyValues);
+ transforms = (s16*)skelCurve->transforms;
+
+ skelCurve->animCurFrame += skelCurve->animSpeed * (globalCtx->state.framerateDivisor * 0.5f);
+
+ if ((skelCurve->animSpeed >= 0.0f && skelCurve->animCurFrame > skelCurve->animFinalFrame) ||
+ (skelCurve->animSpeed < 0.0f && skelCurve->animCurFrame < skelCurve->animFinalFrame)) {
+ skelCurve->animCurFrame = skelCurve->animFinalFrame;
+ ret = 1;
+ }
+
+ for (i = 0; i < skelCurve->limbCount; i++) {
+ for (j = 0; j < 3; j++) {
+ for (k = 0; k < 3; k++, transformRefIdx++, transforms++) {
+ if (*transformRefIdx == 0) {
+ transformValue = *transformCopyValues;
+ *transforms = transformValue;
+ transformCopyValues++;
+ } else {
+ transformValue = func_800F2478(skelCurve->animCurFrame, transData, *transformRefIdx);
+ transData += *transformRefIdx;
+ if (j == 0) {
+ *transforms = transformValue * 1024.0f;
+ } else if (j == 1) {
+ *transforms = transformValue * (32768.0f / 180.0f);
+ } else {
+ *transforms = transformValue * 100.0f;
+ }
+ }
+ }
+ }
+ }
+
+ return ret;
+}
+#else
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_fcurve_data_skelanime/SkelCurve_Update.s")
+#endif
+
+void SkelCurve_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, SkelAnimeCurve* skelCurve,
+ OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
+ SkelCurveLimb* limb = (SkelCurveLimb*)Lib_SegmentedToVirtual(skelCurve->limbList[limbIndex]);
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+
+ Matrix_StatePush();
+
+ if (overrideLimbDraw == NULL ||
+ (overrideLimbDraw != NULL && overrideLimbDraw(globalCtx, skelCurve, limbIndex, thisx))) {
+ Vec3f scale;
+ Vec3s rot;
+ Vec3f pos;
+ Gfx* dList;
+ Vec3s* transform = (Vec3s*)&skelCurve->transforms[limbIndex];
+
+ scale.x = transform->x / 1024.0f;
+ scale.y = transform->y / 1024.0f;
+ scale.z = transform->z / 1024.0f;
+ transform++;
+ rot.x = transform->x;
+ rot.y = transform->y;
+ rot.z = transform->z;
+ transform++;
+ pos.x = transform->x;
+ pos.y = transform->y;
+ pos.z = transform->z;
+
+ Matrix_JointPosition(&pos, &rot);
+ Matrix_Scale(scale.x, scale.y, scale.z, MTXMODE_APPLY);
+
+ if (lod == 0) {
+ s32 pad1;
+
+ dList = limb->dList[0];
+ if (dList != NULL) {
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
+ G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, dList);
+ }
+ } else if (lod == 1) {
+ s32 pad2;
+
+ dList = limb->dList[0];
+ if (dList != NULL) {
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
+ G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, dList);
+ }
+ dList = limb->dList[1];
+ if (dList != NULL) {
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(globalCtx->state.gfxCtx),
+ G_MTX_LOAD | G_MTX_NOPUSH | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, dList);
+ }
+ }
+ }
+
+ if (postLimbDraw != NULL) {
+ postLimbDraw(globalCtx, skelCurve, limbIndex, thisx);
+ }
+
+ if (limb->firstChildIdx != LIMB_DONE) {
+ SkelCurve_DrawLimb(globalCtx, limb->firstChildIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
+ }
+
+ Matrix_StatePop();
+
+ if (limb->nextLimbIdx != LIMB_DONE) {
+ SkelCurve_DrawLimb(globalCtx, limb->nextLimbIdx, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
+ }
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
+
+void SkelCurve_Draw(Actor* actor, GlobalContext* globalCtx, SkelAnimeCurve* skelCurve,
+ OverrideCurveLimbDraw overrideLimbDraw, PostCurveLimbDraw postLimbDraw, s32 lod, Actor* thisx) {
+ if (skelCurve->transforms != NULL) {
+ SkelCurve_DrawLimb(globalCtx, 0, skelCurve, overrideLimbDraw, postLimbDraw, lod, thisx);
+ }
+}
diff --git a/src/code/z_lights.c b/src/code/z_lights.c
index 3e2e041b3..80d3f7131 100644
--- a/src/code/z_lights.c
+++ b/src/code/z_lights.c
@@ -432,7 +432,7 @@ void Lights_DrawGlow(GlobalContext* globalCtx) {
gDPSetPrimColor(dl++, 0, 0, params->color[0], params->color[1], params->color[2], 50);
- SysMatrix_InsertTranslation(params->x, params->y, params->z, 0);
+ Matrix_InsertTranslation(params->x, params->y, params->z, MTXMODE_NEW);
Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
gSPMatrix(dl++, Matrix_NewMtx(globalCtx->state.gfxCtx),
diff --git a/src/code/z_malloc.c b/src/code/z_malloc.c
index f99519e9b..8d0bba44a 100644
--- a/src/code/z_malloc.c
+++ b/src/code/z_malloc.c
@@ -1,21 +1,54 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/zelda_malloc.s")
+void* ZeldaArena_Malloc(size_t size) {
+ void* ptr = __osMalloc(&sZeldaArena, size);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/zelda_mallocR.s")
+ return ptr;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/zelda_realloc.s")
+void* ZeldaArena_MallocR(size_t size) {
+ void* ptr = __osMallocR(&sZeldaArena, size);
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/zelda_free.s")
+ return ptr;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/zelda_calloc.s")
+void* ZeldaArena_Realloc(void* ptr, size_t newSize) {
+ ptr = __osRealloc(&sZeldaArena, ptr, newSize);
+ return ptr;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/MainHeap_AnalyzeArena.s")
+void ZeldaArena_Free(void* ptr) {
+ __osFree(&sZeldaArena, ptr);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/MainHeap_Check.s")
+void* ZeldaArena_Calloc(u32 num, size_t size) {
+ void* ret;
+ u32 n = num * size;
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/MainHeap_Init.s")
+ ret = __osMalloc(&sZeldaArena, n);
+ if (ret != NULL) {
+ bzero(ret, n);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/MainHeap_Cleanup.s")
+ return ret;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_malloc/MainHeap_IsInitialized.s")
+void ZeldaArena_GetSizes(size_t* outMaxFree, size_t* outFree, size_t* outAlloc) {
+ __osAnalyzeArena(&sZeldaArena, outMaxFree, outFree, outAlloc);
+}
+
+void ZeldaArena_Check() {
+ __osCheckArena(&sZeldaArena);
+}
+
+void ZeldaArena_Init(void* start, size_t size) {
+ __osMallocInit(&sZeldaArena, start, size);
+}
+
+void ZeldaArena_Cleanup() {
+ __osMallocCleanup(&sZeldaArena);
+}
+
+u8 ZeldaArena_IsInitialized() {
+ return __osMallocIsInitalized(&sZeldaArena);
+}
diff --git a/src/code/z_pause.c b/src/code/z_pause.c
new file mode 100644
index 000000000..44be6238a
--- /dev/null
+++ b/src/code/z_pause.c
@@ -0,0 +1,5 @@
+#include "global.h"
+
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_pause/func_80122660.s")
+
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_pause/func_80122670.s")
diff --git a/src/code/z_room.c b/src/code/z_room.c
index 5f900ea87..5163f1f29 100644
--- a/src/code/z_room.c
+++ b/src/code/z_room.c
@@ -77,7 +77,7 @@ void Room_Init(GlobalContext* globalCtx, RoomContext* roomCtx) {
#ifdef NON_MATCHING
s32 Room_StartRoomTransition(GlobalContext* globalCtx, RoomContext* roomCtx, s32 index) {
- u32 size;
+ size_t size;
// XXX: this should use a branch-likely
if (roomCtx->unk31 == 0) {
diff --git a/src/code/z_scene.c b/src/code/z_scene.c
index e77144528..b744af5d0 100644
--- a/src/code/z_scene.c
+++ b/src/code/z_scene.c
@@ -1,7 +1,7 @@
#include "global.h"
s32 Object_Spawn(ObjectContext* objectCtx, s16 id) {
- u32 size;
+ size_t size;
objectCtx->status[objectCtx->num].id = id;
size = objectFileTable[id].vromEnd - objectFileTable[id].vromStart;
@@ -23,8 +23,8 @@ s32 Object_Spawn(ObjectContext* objectCtx, s16 id) {
return objectCtx->num - 1;
}
-void Object_InitBank(GameState* gamestate, ObjectContext* objectCtx) {
- GlobalContext* globalCtx = (GlobalContext*)gamestate;
+void Object_InitBank(GameState* gameState, ObjectContext* objectCtx) {
+ GlobalContext* globalCtx = (GlobalContext*)gameState;
s32 pad;
u32 spaceSize;
s32 i;
@@ -49,7 +49,7 @@ void Object_InitBank(GameState* gamestate, ObjectContext* objectCtx) {
for (i = 0; i < OBJECT_EXCHANGE_BANK_MAX; i++) { objectCtx->status[i].id = 0; }
// clang-format on
- objectCtx->spaceStart = objectCtx->status[0].segment = THA_AllocEndAlign16(&gamestate->heap, spaceSize);
+ objectCtx->spaceStart = objectCtx->status[0].segment = THA_AllocEndAlign16(&gameState->heap, spaceSize);
objectCtx->spaceEnd = (void*)((u32)objectCtx->spaceStart + spaceSize);
objectCtx->mainKeepIndex = Object_Spawn(objectCtx, GAMEPLAY_KEEP);
@@ -60,7 +60,7 @@ void Object_UpdateBank(ObjectContext* objectCtx) {
s32 i;
ObjectStatus* status = &objectCtx->status[0];
RomFile* objectFile;
- u32 size;
+ size_t size;
for (i = 0; i < objectCtx->num; i++) {
if (status->id < 0) {
@@ -354,7 +354,7 @@ s32 Scene_LoadAreaTextures(GlobalContext* globalCtx, s32 fileIndex) {
{ SEGMENT_ROM_START(scene_texture_08), SEGMENT_ROM_END(scene_texture_08) },
};
u32 vromStart = sceneTextureFiles[fileIndex].vromStart;
- u32 size = sceneTextureFiles[fileIndex].vromEnd - vromStart;
+ size_t size = sceneTextureFiles[fileIndex].vromEnd - vromStart;
if (size != 0) {
globalCtx->roomCtx.unk74 = THA_AllocEndAlign16(&globalCtx->state.heap, size);
diff --git a/src/code/z_skelanime.c b/src/code/z_skelanime.c
index 16428023a..4cd9734f6 100644
--- a/src/code/z_skelanime.c
+++ b/src/code/z_skelanime.c
@@ -1,63 +1,57 @@
#include "global.h"
-s32 func_80136288(GlobalContext* globalCtx, SkelAnime* skelAnime);
-s32 func_8013631C(GlobalContext* globalCtx, SkelAnime* skelAnime);
-s32 func_8013702C(SkelAnime* skelAnime);
-s32 func_801370B0(SkelAnime* skelAnime);
-s32 func_8013713C(SkelAnime* skelAnime);
-void SkelAnime_ChangeAnimDefaultRepeat(SkelAnime* skelAnime, AnimationHeader* animationSeg);
-void func_80137748(SkelAnime* skelAnime, Vec3f* pos, s16 angle);
-void SkelAnime_ChangeLinkAnim(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg, f32 playbackSpeed, f32 frame, f32 frameCount,
- u8 animationMode, f32 transitionRate);
-void SkelAnime_CopyVec3s(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src);
-void SkelAnime_LinkAnimetionLoaded(GlobalContext* globalCtx, AnimationEntryType0* entry);
-void SkelAnime_AnimationType1Loaded(GlobalContext* globalCtx, AnimationEntryType1* entry);
-void SkelAnime_AnimationType2Loaded(GlobalContext* globalCtx, AnimationEntryType2* entry);
-void SkelAnime_AnimationType3Loaded(GlobalContext* globalCtx, AnimationEntryType3* entry);
-void SkelAnime_AnimationType4Loaded(GlobalContext* globalCtx, AnimationEntryType4* entry);
-void SkelAnime_AnimationType5Loaded(GlobalContext* globalCtx, AnimationEntryType5* entry);
+#define ANIM_INTERP 1
+
+s32 LinkAnimation_Loop(GlobalContext* globalCtx, SkelAnime* skelAnime);
+s32 LinkAnimation_Once(GlobalContext* globalCtx, SkelAnime* skelAnime);
+s32 SkelAnime_LoopFull(SkelAnime* skelAnime);
+s32 SkelAnime_LoopPartial(SkelAnime* skelAnime);
+s32 SkelAnime_Once(SkelAnime* skelAnime);
+void Animation_PlayLoop(SkelAnime* skelAnime, AnimationHeader* animationSeg);
+void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* pos, s16 angle);
+void LinkAnimation_Change(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* linkAnimetionEntrySeg,
+ f32 playbackSpeed, f32 frame, f32 frameCount, u8 animationMode, f32 transitionRate);
+void SkelAnime_CopyFrameTable(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src);
static AnimationEntryCallback sAnimationLoadDone[] = {
- (AnimationEntryCallback)SkelAnime_LinkAnimetionLoaded, (AnimationEntryCallback)SkelAnime_AnimationType1Loaded,
- (AnimationEntryCallback)SkelAnime_AnimationType2Loaded, (AnimationEntryCallback)SkelAnime_AnimationType3Loaded,
- (AnimationEntryCallback)SkelAnime_AnimationType4Loaded, (AnimationEntryCallback)SkelAnime_AnimationType5Loaded,
+ AnimationContext_LoadFrame, AnimationContext_CopyAll, AnimationContext_Interp,
+ AnimationContext_CopyTrue, AnimationContext_CopyFalse, AnimationContext_MoveActor,
};
-s32 D_801F5AB0;
-s32 D_801F5AB4;
+s32 sAnimQueueFlags;
+s32 sDisableAnimQueueFlags;
/*
* Draws the limb at `limbIndex` with a level of detail display lists index by `dListIndex`
*/
-void SkelAnime_LodDrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, s32 dListIndex) {
- StandardLimb* limbEntry;
+void SkelAnime_DrawLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor, s32 lod) {
+ LodLimb* limb;
Gfx* dList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
- s32 pad;
- SysMatrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+
+ Matrix_StatePush();
+ limb = (LodLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
+ rot = jointTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
- dList = limbEntry->displayLists[dListIndex];
+ dList = limb->dLists[lod];
if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPMatrix(&polyTemp[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPDisplayList(&polyTemp[1], dList);
+ POLY_OPA_DISP = &polyTemp[2];
}
}
@@ -65,58 +59,58 @@ void SkelAnime_LodDrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skele
postLimbDraw(globalCtx, limbIndex, &dList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_LodDrawLimb(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex);
+ if (limb->child != LIMB_DONE) {
+ SkelAnime_DrawLimbLod(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor, lod);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- SkelAnime_LodDrawLimb(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex);
+ if (limb->sibling != LIMB_DONE) {
+ SkelAnime_DrawLimbLod(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ lod);
}
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-/*
- * Draws the Skeleton described by `skeleton` with a level of detail display list indexed by `dListIndex`
+/**
+ * Draw all limbs of type `LodLimb` in a given skeleton
+ * Near or far display list is specified via `lod`
*/
-void SkelAnime_LodDraw(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, s32 dListIndex) {
- StandardLimb* limbEntry;
+void SkelAnime_DrawLod(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor, s32 lod) {
+ LodLimb* rootLimb;
s32 pad;
Gfx* dList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx;
- s32 pad2;
if (skeleton == NULL) {
return;
}
- gfxCtx = globalCtx->state.gfxCtx;
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- SysMatrix_StatePush();
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
+ rootLimb = (LodLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
- rot = limbDrawTable[1];
- dList = limbEntry->displayLists[dListIndex];
+ rot = jointTable[1];
+ dList = rootLimb->dLists[lod];
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPMatrix(&polyTemp[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList);
+ gSPDisplayList(&polyTemp[1], dList);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ POLY_OPA_DISP = &polyTemp[2];
}
}
@@ -124,167 +118,169 @@ void SkelAnime_LodDraw(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDra
postLimbDraw(globalCtx, 1, &dList, &rot, actor);
}
- if (limbEntry->firstChildIndex != 0xFF) {
- SkelAnime_LodDrawLimb(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex);
+ if (rootLimb->child != LIMB_DONE) {
+ SkelAnime_DrawLimbLod(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ lod);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-/*
- * Draws the limb at `limbIndex` with a level of detail display lists index by `dListIndex`, Limb matrices come
- * from a dynamic allocation from the graph arena.
- */
-void SkelAnime_LodDrawLimbSV(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDrawSV overrideLimbDraw, PostLimbDrawSV postLimbDraw, Actor* actor,
- s32 dListIndex, RSPMatrix** mtx) {
- StandardLimb* limbEntry;
- Gfx* dList[2];
+/**
+ * Draw a limb of type `LodLimb` contained within a flexible skeleton
+ * Near or far display list is specified via `lod`
+ */
+void SkelAnime_DrawFlexLimbLod(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawFlex overrideLimbDraw, PostLimbDrawFlex postLimbDraw, Actor* actor,
+ s32 lod, Mtx** mtx) {
+ LodLimb* limb;
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
- s32 pad;
- SysMatrix_StatePush();
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ Matrix_StatePush();
+
+ limb = (LodLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
-
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
- // Double assignment here would not work.
- dList[0] = limbEntry->displayLists[dListIndex];
- dList[1] = dList[0];
-
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList[1] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*mtx);
- gSPMatrix(gfxCtx->polyOpa.p++, *mtx, G_MTX_LOAD);
- gSPDisplayList(gfxCtx->polyOpa.p++, dList[1]);
+ rot = jointTable[limbIndex];
+
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
+
+ newDList = limbDList = limb->dLists[lod];
+
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ Matrix_ToMtx(*mtx);
+ gSPMatrix(POLY_OPA_DISP++, *mtx, G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, newDList);
(*mtx)++;
- } else if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*mtx);
+ } else if (limbDList != NULL) {
+ Matrix_ToMtx(*mtx);
(*mtx)++;
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, limbIndex, &dList[1], &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, limbIndex, &newDList, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_LodDrawLimbSV(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex, mtx);
+ if (limb->child != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbLod(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ lod, mtx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- SkelAnime_LodDrawLimbSV(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex, mtx);
+ if (limb->sibling != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbLod(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ lod, mtx);
}
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-/*
- * Draws the Skeleton described by `skeleton` with a level of detail display list indexed by `dListIndex`
- * Matricies for the limbs are dynamically allocted from the graph arena. The dynamic allocation occurs
- * because the Skeleton is too large to be supported by the normal matrix stack.
- */
-void SkelAnime_LodDrawSV(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable, s32 dListCount,
- OverrideLimbDrawSV overrideLimbDraw, PostLimbDrawSV postLimbDraw, Actor* actor,
- s32 dListIndex) {
- StandardLimb* limbEntry;
+/**
+ * Draws all limbs of type `LodLimb` in a given flexible skeleton
+ * Limbs in a flexible skeleton have meshes that can stretch to line up with other limbs.
+ * An array of matrices is dynamically allocated so each limb can access any transform to ensure its meshes line up.
+ */
+void SkelAnime_DrawFlexLod(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, s32 dListCount,
+ OverrideLimbDrawFlex overrideLimbDraw, PostLimbDrawFlex postLimbDraw, Actor* actor,
+ s32 lod) {
+ LodLimb* rootLimb;
s32 pad;
- Gfx* dList[2];
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- RSPMatrix* mtx;
- GraphicsContext* gfxCtx;
- s32 pad2;
-
- mtx = (RSPMatrix*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(RSPMatrix) * dListCount));
+ Mtx* mtx = (Mtx*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(Mtx) * dListCount));
if (skeleton == NULL) {
return;
}
- gfxCtx = globalCtx->state.gfxCtx;
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- gSPSegment(gfxCtx->polyOpa.p++, 0xD, mtx);
- SysMatrix_StatePush();
+ gSPSegment(POLY_OPA_DISP++, 0xD, mtx);
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
+ rootLimb = (LodLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
- rot = limbDrawTable[1];
+ rot = jointTable[1];
- dList[0] = limbEntry->displayLists[dListIndex];
- dList[1] = dList[0];
+ newDList = limbDList = rootLimb->dLists[lod];
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList[1] != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, SysMatrix_GetStateAsRSPMatrix(mtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList[1]);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPMatrix(&polyTemp[0], Matrix_ToMtx(mtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], newDList);
+ POLY_OPA_DISP = &polyTemp[2];
mtx++;
- } else if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(mtx);
+ } else if (limbDList != NULL) {
+ Matrix_ToMtx(mtx);
mtx++;
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, 1, &dList[1], &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, 1, &newDList, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_LodDrawLimbSV(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, dListIndex, &mtx);
+ if (rootLimb->child != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbLod(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, lod, &mtx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
/*
* Draws the limb of the Skeleton `skeleton` at `limbIndex`
*/
-void SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor) {
- StandardLimb* limbEntry;
+void SkelAnime_DrawLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor) {
+ StandardLimb* limb;
Gfx* dList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
- s32 pad;
- SysMatrix_StatePush();
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
- limbIndex++;
- rot = limbDrawTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
- dList = limbEntry->displayLists[0];
+ Matrix_StatePush();
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ limb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ limbIndex++;
+ rot = jointTable[limbIndex];
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
+ dList = limb->dList;
+
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPMatrix(&polyTemp[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], dList);
+ POLY_OPA_DISP = &polyTemp[2];
}
}
@@ -292,53 +288,54 @@ void SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton
postLimbDraw(globalCtx, limbIndex, &dList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_DrawLimb(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor);
+ if (limb->child != LIMB_DONE) {
+ SkelAnime_DrawLimbOpa(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- SkelAnime_DrawLimb(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw, postLimbDraw,
- actor);
+ if (limb->sibling != LIMB_DONE) {
+ SkelAnime_DrawLimbOpa(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
}
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable, OverrideLimbDraw overrideLimbDraw,
- PostLimbDraw postLimbDraw, Actor* actor) {
+/**
+ * Draw all limbs of type `StandardLimb` in a given skeleton to the polyOpa buffer
+ */
+void SkelAnime_DrawOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor) {
StandardLimb* rootLimb;
s32 pad;
Gfx* dList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx;
- s32 pad2;
if (skeleton == NULL) {
return;
}
- gfxCtx = globalCtx->state.gfxCtx;
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- SysMatrix_StatePush();
- rootLimb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ Matrix_StatePush();
+ rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
- rot = limbDrawTable[1];
- dList = rootLimb->displayLists[0];
+ rot = jointTable[1];
+ dList = rootLimb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPMatrix(&polyTemp[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], dList);
+ POLY_OPA_DISP = &polyTemp[2];
}
}
@@ -346,318 +343,333 @@ void SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTa
postLimbDraw(globalCtx, 1, &dList, &rot, actor);
}
- if (rootLimb->firstChildIndex != LIMB_DONE) {
- SkelAnime_DrawLimb(globalCtx, rootLimb->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor);
+ if (rootLimb->child != LIMB_DONE) {
+ SkelAnime_DrawLimbOpa(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void SkelAnime_DrawLimbSV(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor,
- RSPMatrix** limbMatricies) {
- StandardLimb* limbEntry;
- Gfx* dList[2];
+void SkelAnime_DrawFlexLimbOpa(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor,
+ Mtx** limbMatricies) {
+ StandardLimb* limb;
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
- s32 pad;
- SysMatrix_StatePush();
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ limb = Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
+ rot = jointTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
- dList[0] = limbEntry->displayLists[0];
- dList[1] = dList[0];
+ newDList = limbDList = limb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList[1] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*limbMatricies);
- gSPMatrix(gfxCtx->polyOpa.p++, *limbMatricies, G_MTX_LOAD);
- gSPDisplayList(gfxCtx->polyOpa.p++, dList[1]);
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ Matrix_ToMtx(*limbMatricies);
+ gSPMatrix(POLY_OPA_DISP++, *limbMatricies, G_MTX_LOAD);
+ gSPDisplayList(POLY_OPA_DISP++, newDList);
(*limbMatricies)++;
- } else if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*limbMatricies);
+ } else if (limbDList != NULL) {
+ Matrix_ToMtx(*limbMatricies);
(*limbMatricies)++;
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, limbIndex, &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, limbIndex, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_DrawLimbSV(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, limbMatricies);
+ if (limb->child != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbOpa(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ limbMatricies);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- SkelAnime_DrawLimbSV(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, limbMatricies);
+ if (limb->sibling != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbOpa(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ limbMatricies);
}
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void SkelAnime_DrawSV(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable, s32 dListCount,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor) {
- StandardLimb* limbEntry;
+/**
+ * Draw all limbs of type `StandardLimb` in a given flexible skeleton to the polyOpa buffer
+ * Limbs in a flexible skeleton have meshes that can stretch to line up with other limbs.
+ * An array of matrices is dynamically allocated so each limb can access any transform to ensure its meshes line up.
+ */
+void SkelAnime_DrawFlexOpa(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, s32 dListCount,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, Actor* actor) {
+ StandardLimb* rootLimb;
s32 pad;
- Gfx* dList[2];
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- RSPMatrix* mtx;
- GraphicsContext* gfxCtx;
- s32 pad2;
-
- mtx = (RSPMatrix*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(RSPMatrix) * dListCount));
+ Mtx* mtx = (Mtx*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(Mtx) * dListCount));
if (skeleton == NULL) {
return;
}
- gfxCtx = globalCtx->state.gfxCtx;
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- gSPSegment(gfxCtx->polyOpa.p++, 0xD, mtx);
+ gSPSegment(POLY_OPA_DISP++, 0xD, mtx);
- SysMatrix_StatePush();
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
- rot = limbDrawTable[1];
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
+ rot = jointTable[1];
- dList[0] = limbEntry->displayLists[0];
- dList[1] = dList[0];
+ newDList = limbDList = rootLimb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList[1] != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, SysMatrix_GetStateAsRSPMatrix(mtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList[1]);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPMatrix(&polyTemp[0], Matrix_ToMtx(mtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], newDList);
+ POLY_OPA_DISP = &polyTemp[2];
mtx++;
} else {
- if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(mtx);
+ if (limbDList != NULL) {
+ Matrix_ToMtx(mtx);
mtx++;
}
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, 1, &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, 1, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- SkelAnime_DrawLimbSV(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, &mtx);
+ if (rootLimb->child != LIMB_DONE) {
+ SkelAnime_DrawFlexLimbOpa(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, &mtx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void func_80134148(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, UnkActorDraw unkDraw, Actor* actor,
- RSPMatrix** mtx) {
- StandardLimb* limbEntry;
- Gfx* dList[2];
+void func_80134148(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, UnkActorDraw unkDraw,
+ Actor* actor, Mtx** mtx) {
+ StandardLimb* limb;
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- GraphicsContext* gfxCtx = globalCtx->state.gfxCtx;
- s32 pad2;
- SysMatrix_StatePush();
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ Matrix_StatePush();
+
+ limb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
+ rot = jointTable[limbIndex];
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
+
+ newDList = limbDList = limb->dList;
- dList[0] = limbEntry->displayLists[0];
- dList[1] = dList[0];
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ Matrix_StatePush();
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- SysMatrix_StatePush();
+ //! @bug Does not check unkDraw is not NULL before calling it.
unkDraw(globalCtx, limbIndex, actor);
- if (dList[1] != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
+ if (newDList != NULL) {
+ Gfx* polyTemp = POLY_OPA_DISP;
- gSPMatrix(polyTemp, SysMatrix_GetStateAsRSPMatrix(*mtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList[1]);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ gSPMatrix(&polyTemp[0], Matrix_ToMtx(*mtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], newDList);
+ POLY_OPA_DISP = &polyTemp[2];
(*mtx)++;
} else {
- if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*mtx);
+ if (limbDList != NULL) {
+ Matrix_ToMtx(*mtx);
(*mtx)++;
}
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, limbIndex, &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, limbIndex, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- func_80134148(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw, postLimbDraw,
- unkDraw, actor, mtx);
+ if (limb->child != LIMB_DONE) {
+ func_80134148(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, unkDraw, actor,
+ mtx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- func_80134148(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw, postLimbDraw,
- unkDraw, actor, mtx);
+ if (limb->sibling != LIMB_DONE) {
+ func_80134148(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, unkDraw, actor,
+ mtx);
}
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-void func_801343C0(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable, s32 dListCount,
- OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, UnkActorDraw unkDraw, Actor* actor) {
- StandardLimb* limbEntry;
+void func_801343C0(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, s32 dListCount,
+ OverrideLimbDrawOpa overrideLimbDraw, PostLimbDrawOpa postLimbDraw, UnkActorDraw unkDraw,
+ Actor* actor) {
+ StandardLimb* rootLimb;
s32 pad;
- Gfx* dList[2];
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- RSPMatrix* mtx;
- GraphicsContext* gfxCtx;
- s32 pad2;
+ Mtx* mtx;
if (skeleton == NULL) {
return;
}
- gfxCtx = globalCtx->state.gfxCtx;
+ OPEN_DISPS(globalCtx->state.gfxCtx);
- mtx = (RSPMatrix*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(RSPMatrix) * dListCount));
+ mtx = (Mtx*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(Mtx) * dListCount));
- gSPSegment(gfxCtx->polyOpa.p++, 0xD, mtx);
+ gSPSegment(POLY_OPA_DISP++, 0xD, mtx);
- SysMatrix_StatePush();
+ Matrix_StatePush();
+
+ rootLimb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
+ rot = jointTable[1];
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
- rot = limbDrawTable[1];
+ newDList = limbDList = rootLimb->dList;
- dList[0] = limbEntry->displayLists[0];
- dList[1] = dList[0];
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor)) {
+ Matrix_JointPosition(&pos, &rot);
+ Matrix_StatePush();
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList[1], &pos, &rot, actor) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- SysMatrix_StatePush();
+ //! @bug Does not check unkDraw is not NULL before calling it.
unkDraw(globalCtx, 1, actor);
- if (dList[1] != NULL) {
- Gfx* polyTemp = gfxCtx->polyOpa.p;
- gSPMatrix(polyTemp, SysMatrix_GetStateAsRSPMatrix(mtx), G_MTX_LOAD);
- gSPDisplayList(polyTemp + 1, dList[1]);
- gfxCtx->polyOpa.p = polyTemp + 2;
+ if (newDList != NULL) {
+ Gfx* polyTemp = POLY_OPA_DISP;
+
+ gSPMatrix(&polyTemp[0], Matrix_ToMtx(mtx), G_MTX_LOAD);
+ gSPDisplayList(&polyTemp[1], newDList);
+ POLY_OPA_DISP = &polyTemp[2];
mtx++;
} else {
- if (dList[0] != NULL) {
- SysMatrix_GetStateAsRSPMatrix(mtx++);
+ if (limbDList != NULL) {
+ Matrix_ToMtx(mtx++);
}
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, 1, &dList[0], &rot, actor);
+ postLimbDraw(globalCtx, 1, &limbDList, &rot, actor);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- func_80134148(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw, postLimbDraw,
- unkDraw, actor, &mtx);
+ if (rootLimb->child != LIMB_DONE) {
+ func_80134148(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, unkDraw, actor,
+ &mtx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
}
-/*
- * Copies the rotation values from the rotation value table, indexed by the rotation index table
- * When a rotation index is >= the animation limit, the output rotation value is copied from the frame's
- * rotation value list, otherwise it is copied from the initial rotation value list
- */
-void SkelAnime_AnimateFrame(AnimationHeader* animationSeg, s32 currentFrame, s32 limbCount, Vec3s* dst) {
- AnimationHeader* animationHeader = Lib_SegmentedToVirtual(animationSeg);
- JointIndex* index = Lib_SegmentedToVirtual(animationHeader->jointIndices);
- AnimationRotationValue* rotationValueTable = Lib_SegmentedToVirtual(animationHeader->frameData);
- AnimationRotationValue* frameRotationValueTable = &rotationValueTable[currentFrame];
+/**
+ * Copies frame data from the frame data table, indexed by the joint index table.
+ * Indices below staticIndexMax are copied from that entry in the static frame data table.
+ * Indices above staticIndexMax are offsets to a frame data array indexed by the frame.
+ */
+void SkelAnime_GetFrameData(AnimationHeader* animation, s32 frame, s32 limbCount, Vec3s* frameTable) {
+ AnimationHeader* animHeader = Lib_SegmentedToVirtual(animation);
+ JointIndex* jointIndices = Lib_SegmentedToVirtual(animHeader->jointIndices);
+ s16* frameData = Lib_SegmentedToVirtual(animHeader->frameData);
+ s16* dynamicData = &frameData[frame];
s32 i;
- u16 limit = animationHeader->staticIndexMax;
+ u16 staticIndexMax = animHeader->staticIndexMax;
for (i = 0; i < limbCount; i++) {
// Debug prints here, this is needed to prevent loop unrolling
if (0) {
if (0) {};
}
- dst->x = index->x >= limit ? frameRotationValueTable[index->x] : rotationValueTable[index->x];
- dst->y = index->y >= limit ? frameRotationValueTable[index->y] : rotationValueTable[index->y];
- dst->z = index->z >= limit ? frameRotationValueTable[index->z] : rotationValueTable[index->z];
- index++, dst++;
+ frameTable->x = jointIndices->x >= staticIndexMax ? dynamicData[jointIndices->x] : frameData[jointIndices->x];
+ frameTable->y = jointIndices->y >= staticIndexMax ? dynamicData[jointIndices->y] : frameData[jointIndices->y];
+ frameTable->z = jointIndices->z >= staticIndexMax ? dynamicData[jointIndices->z] : frameData[jointIndices->z];
+ jointIndices++, frameTable++;
}
}
-s16 SkelAnime_GetTotalFrames(AnimationHeaderCommon* animationSeg) {
- AnimationHeaderCommon* animation = Lib_SegmentedToVirtual(animationSeg);
- return animation->frameCount;
+s16 Animation_GetLength(void* animation) {
+ AnimationHeaderCommon* common = Lib_SegmentedToVirtual(animation);
+
+ return common->frameCount;
}
-s16 SkelAnime_GetFrameCount(AnimationHeaderCommon* animationSeg) {
- AnimationHeaderCommon* animation = Lib_SegmentedToVirtual(animationSeg);
+s16 Animation_GetLastFrame(void* animation) {
+ AnimationHeaderCommon* common = Lib_SegmentedToVirtual(animation);
- return (u16)animation->frameCount - 1;
+ return (u16)common->frameCount - 1;
}
/*
* Draws the Skeleton `skeleton`'s limb at index `limbIndex`. Appends all generated graphics commands to
* `gfx`. Returns a pointer to the next gfx to be appended to.
*/
-Gfx* SkelAnime_Draw2Limb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw2 overrideLimbDraw, PostLimbDraw2 postLimbDraw, Actor* actor, Gfx* gfx) {
- StandardLimb* limbEntry;
+Gfx* SkelAnime_DrawLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, Gfx* gfx) {
+ StandardLimb* limb;
Gfx* dList;
Vec3f pos;
Vec3s rot;
- SysMatrix_StatePush();
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ limb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
+ rot = jointTable[limbIndex];
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
- dList = limbEntry->displayLists[0];
+ dList = limb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor, &gfx) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &dList, &pos, &rot, actor, &gfx)) {
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- gSPMatrix(gfx, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(gfx + 1, dList);
- gfx = gfx + 2;
+ gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPDisplayList(&gfx[1], dList);
+ gfx = &gfx[2];
}
}
@@ -665,16 +677,16 @@ Gfx* SkelAnime_Draw2Limb(GlobalContext* globalCtx, s32 limbIndex, void** skeleto
postLimbDraw(globalCtx, limbIndex, &dList, &rot, actor, &gfx);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- gfx = SkelAnime_Draw2Limb(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, gfx);
+ if (limb->child != LIMB_DONE) {
+ gfx = SkelAnime_DrawLimb(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ gfx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- gfx = SkelAnime_Draw2Limb(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, gfx);
+ if (limb->sibling != LIMB_DONE) {
+ gfx = SkelAnime_DrawLimb(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw, actor,
+ gfx);
}
return gfx;
@@ -684,9 +696,9 @@ Gfx* SkelAnime_Draw2Limb(GlobalContext* globalCtx, s32 limbIndex, void** skeleto
* Draws the Skeleton `skeleton` Appends all generated graphics to `gfx`, and returns a pointer to the
* next gfx to be appended to.
*/
-Gfx* SkelAnime_Draw2(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw2 overrideLimbDraw, PostLimbDraw2 postLimbDraw, Actor* actor, Gfx* gfx) {
- StandardLimb* limbEntry;
+Gfx* SkelAnime_Draw(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, OverrideLimbDraw overrideLimbDraw,
+ PostLimbDraw postLimbDraw, Actor* actor, Gfx* gfx) {
+ StandardLimb* rootLimb;
s32 pad;
Gfx* dList;
Vec3f pos;
@@ -696,23 +708,24 @@ Gfx* SkelAnime_Draw2(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawT
return NULL;
}
- SysMatrix_StatePush();
+ Matrix_StatePush();
+
+ rootLimb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
- rot = limbDrawTable[1];
+ rot = jointTable[1];
- dList = limbEntry->displayLists[0];
+ dList = rootLimb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor, &gfx) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &dList, &pos, &rot, actor, &gfx)) {
+ Matrix_JointPosition(&pos, &rot);
if (dList != NULL) {
- gSPMatrix(gfx, Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
- gSPDisplayList(gfx + 1, dList);
- gfx = gfx + 2;
+ gSPMatrix(&gfx[0], Matrix_NewMtx(globalCtx->state.gfxCtx), G_MTX_LOAD);
+ gSPDisplayList(&gfx[1], dList);
+ gfx = &gfx[2];
}
}
@@ -720,202 +733,285 @@ Gfx* SkelAnime_Draw2(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawT
postLimbDraw(globalCtx, 1, &dList, &rot, actor, &gfx);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- gfx = SkelAnime_Draw2Limb(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, gfx);
+ if (rootLimb->child != LIMB_DONE) {
+ gfx = SkelAnime_DrawLimb(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, gfx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
return gfx;
}
-/*
- * Draws the Skeleton `skeleton` Appends all generated graphics to `gfx`, and returns a pointer to the
- * next gfx to be appended to. Allocates matricies for display lists on the graph heap.
- */
-Gfx* SkelAnime_DrawLimbSV2(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* limbDrawTable,
- OverrideLimbDraw2 overrideLimbDraw, PostLimbDraw2 postLimbDraw, Actor* actor,
- RSPMatrix** mtx, Gfx* gfx) {
- StandardLimb* limbEntry;
- Gfx* dList1;
- Gfx* dList2;
+/**
+ * Draw a limb of type `StandardLimb` contained within a flexible skeleton to the specified display buffer
+ */
+Gfx* SkelAnime_DrawFlexLimb(GlobalContext* globalCtx, s32 limbIndex, void** skeleton, Vec3s* jointTable,
+ OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, Mtx** mtx,
+ Gfx* gfx) {
+ StandardLimb* limb;
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- SysMatrix_StatePush();
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
+ limb = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[limbIndex]);
limbIndex++;
- rot = limbDrawTable[limbIndex];
+ rot = jointTable[limbIndex];
- pos.x = limbEntry->translation.x;
- pos.y = limbEntry->translation.y;
- pos.z = limbEntry->translation.z;
+ pos.x = limb->jointPos.x;
+ pos.y = limb->jointPos.y;
+ pos.z = limb->jointPos.z;
- dList1 = dList2 = limbEntry->displayLists[0];
+ newDList = limbDList = limb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, limbIndex, &dList1, &pos, &rot, actor, &gfx) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList1 != NULL) {
- gSPMatrix(gfx, SysMatrix_GetStateAsRSPMatrix(*mtx), G_MTX_LOAD);
- gSPDisplayList(gfx + 1, dList1);
- gfx = gfx + 2;
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, limbIndex, &newDList, &pos, &rot, actor, &gfx)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ gSPMatrix(&gfx[0], Matrix_ToMtx(*mtx), G_MTX_LOAD);
+ gSPDisplayList(&gfx[1], newDList);
+ gfx = &gfx[2];
(*mtx)++;
} else {
- if (dList2 != NULL) {
- SysMatrix_GetStateAsRSPMatrix(*mtx);
+ if (limbDList != NULL) {
+ Matrix_ToMtx(*mtx);
(*mtx)++;
}
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, limbIndex, &dList2, &rot, actor, &gfx);
+ postLimbDraw(globalCtx, limbIndex, &limbDList, &rot, actor, &gfx);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- gfx = SkelAnime_DrawLimbSV2(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, mtx, gfx);
+ if (limb->child != LIMB_DONE) {
+ gfx = SkelAnime_DrawFlexLimb(globalCtx, limb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, mtx, gfx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
- if (limbEntry->nextLimbIndex != LIMB_DONE) {
- gfx = SkelAnime_DrawLimbSV2(globalCtx, limbEntry->nextLimbIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, mtx, gfx);
+ if (limb->sibling != LIMB_DONE) {
+ gfx = SkelAnime_DrawFlexLimb(globalCtx, limb->sibling, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, mtx, gfx);
}
return gfx;
}
-Gfx* SkelAnime_DrawSV2(GlobalContext* globalCtx, void** skeleton, Vec3s* limbDrawTable, s32 dListCount,
- OverrideLimbDraw2 overrideLimbDraw, PostLimbDraw2 postLimbDraw, Actor* actor, Gfx* gfx) {
- StandardLimb* limbEntry;
+/**
+ * Draw all limbs of type `StandardLimb` in a given flexible skeleton to the specified display buffer
+ * Limbs in a flexible skeleton have meshes that can stretch to line up with other limbs.
+ * An array of matrices is dynamically allocated so each limb can access any transform to ensure its meshes line up.
+ */
+Gfx* SkelAnime_DrawFlex(GlobalContext* globalCtx, void** skeleton, Vec3s* jointTable, s32 dListCount,
+ OverrideLimbDraw overrideLimbDraw, PostLimbDraw postLimbDraw, Actor* actor, Gfx* gfx) {
+ StandardLimb* rootLimb;
s32 pad;
- Gfx* dList1;
- Gfx* dList2;
+ Gfx* newDList;
+ Gfx* limbDList;
Vec3f pos;
Vec3s rot;
- RSPMatrix* mtx;
+ Mtx* mtx;
if (skeleton == NULL) {
return NULL;
}
- mtx = (RSPMatrix*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(RSPMatrix) * dListCount));
+ mtx = (Mtx*)GRAPH_ALLOC(globalCtx->state.gfxCtx, ALIGN16(sizeof(Mtx) * dListCount));
gSPSegment(gfx++, 0xD, mtx);
- SysMatrix_StatePush();
+ Matrix_StatePush();
- limbEntry = (StandardLimb*)Lib_SegmentedToVirtual(skeleton[0]);
+ rootLimb = Lib_SegmentedToVirtual(skeleton[0]);
- pos.x = limbDrawTable[0].x;
- pos.y = limbDrawTable[0].y;
- pos.z = limbDrawTable[0].z;
+ pos.x = jointTable[0].x;
+ pos.y = jointTable[0].y;
+ pos.z = jointTable[0].z;
- rot = limbDrawTable[1];
+ rot = jointTable[1];
- dList1 = dList2 = limbEntry->displayLists[0];
+ newDList = limbDList = rootLimb->dList;
- if ((overrideLimbDraw == NULL) || (overrideLimbDraw(globalCtx, 1, &dList1, &pos, &rot, actor, &gfx) == 0)) {
- SysMatrix_RotateAndTranslateState(&pos, &rot);
- if (dList1 != NULL) {
- gSPMatrix(gfx, SysMatrix_GetStateAsRSPMatrix(mtx), G_MTX_LOAD);
- gSPDisplayList(gfx + 1, dList1);
- gfx = gfx + 2;
+ if ((overrideLimbDraw == NULL) || !overrideLimbDraw(globalCtx, 1, &newDList, &pos, &rot, actor, &gfx)) {
+ Matrix_JointPosition(&pos, &rot);
+ if (newDList != NULL) {
+ gSPMatrix(&gfx[0], Matrix_ToMtx(mtx), G_MTX_LOAD);
+ gSPDisplayList(&gfx[1], newDList);
+ gfx = &gfx[2];
mtx++;
} else {
- if (dList2 != NULL) {
- SysMatrix_GetStateAsRSPMatrix(mtx);
+ if (limbDList != NULL) {
+ Matrix_ToMtx(mtx);
mtx++;
}
}
}
if (postLimbDraw != NULL) {
- postLimbDraw(globalCtx, 1, &dList2, &rot, actor, &gfx);
+ postLimbDraw(globalCtx, 1, &limbDList, &rot, actor, &gfx);
}
- if (limbEntry->firstChildIndex != LIMB_DONE) {
- gfx = SkelAnime_DrawLimbSV2(globalCtx, limbEntry->firstChildIndex, skeleton, limbDrawTable, overrideLimbDraw,
- postLimbDraw, actor, &mtx, gfx);
+ if (rootLimb->child != LIMB_DONE) {
+ gfx = SkelAnime_DrawFlexLimb(globalCtx, rootLimb->child, skeleton, jointTable, overrideLimbDraw, postLimbDraw,
+ actor, &mtx, gfx);
}
- SysMatrix_StatePop();
+ Matrix_StatePop();
return gfx;
}
-// Function is unused.
-#pragma GLOBAL_ASM("asm/non_matchings/code/z_skelanime/func_80134FFC.s")
+/**
+ * Unpacks frame data for the animation at the given frame into frameTable
+ * Used by the legacy animation format
+ */
+#ifdef NON_MATCHING
+// equivalent, minor reordering
+s16 SkelAnime_GetFrameDataLegacy(LegacyAnimationHeader* animation, s32 frame, Vec3s* frameTable) {
+ LegacyAnimationHeader* animHeader = Lib_SegmentedToVirtual(animation);
+ s16 limbCount = animHeader->limbCount;
+ JointKey* key = Lib_SegmentedToVirtual(animHeader->jointKey);
+ s16* frameData = Lib_SegmentedToVirtual(animHeader->frameData);
+ s16* staticData = &frameData[0];
+ s16* dynamicData = &frameData[frame];
+ s32 i;
-s16 func_801353D4(AnimationHeaderCommon* animationSeg) {
- AnimationHeaderCommon* animation = Lib_SegmentedToVirtual(animationSeg);
+ /**
+ *Equivalent to the following, but the compiler optimizes the loop in a way I can't replicate
+ */
+ /*
+ for(i = 0, frameTable++, key++; i < limbCount + 1; i++, key++, frameTable++) {
+ frameTable->x = frame < key->xMax ? dynamicData[key->x] : staticData[key->x];
+ frameTable->y = frame < key->yMax ? dynamicData[key->y] : staticData[key->y];
+ frameTable->z = frame < key->zMax ? dynamicData[key->z] : staticData[key->z];
+ }
+ */
+ frameTable->x = frame < key->xMax ? dynamicData[key->x] : staticData[key->x];
+ frameTable->y = frame < key->yMax ? dynamicData[key->y] : staticData[key->y];
+ frameTable->z = frame < key->zMax ? dynamicData[key->z] : staticData[key->z];
+
+ i = 1;
+ frameTable++;
+ key++;
+
+ if (limbCount & 1) {}
+
+ if (limbCount > 0) {
+ if (limbCount & 1) {
+ i++;
+ frameTable->x = frame < key->xMax ? dynamicData[key->x] : staticData[key->x];
+ frameTable->y = frame < key->yMax ? dynamicData[key->y] : staticData[key->y];
+ frameTable->z = frame < key->zMax ? dynamicData[key->z] : staticData[key->z];
+ key++;
+ frameTable++;
+ if (limbCount + 1 == i) {
+ goto ret;
+ }
+ }
+ do {
+ i += 2;
+ frameTable->x = frame < key->xMax ? dynamicData[key->x] : staticData[key->x];
+ frameTable->y = frame < key->yMax ? dynamicData[key->y] : staticData[key->y];
+ frameTable->z = frame < key->zMax ? dynamicData[key->z] : staticData[key->z];
+ key++;
+ frameTable++;
+ frameTable->x = frame < key->xMax ? dynamicData[key->x] : staticData[key->x];
+ frameTable->y = frame < key->yMax ? dynamicData[key->y] : staticData[key->y];
+ frameTable->z = frame < key->zMax ? dynamicData[key->z] : staticData[key->z];
+ key++;
+ frameTable++;
+ } while (i != limbCount + 1);
+ }
+
+ret:
+ return limbCount;
+}
+#else
+#pragma GLOBAL_ASM("asm/non_matchings/code/z_skelanime/SkelAnime_GetFrameData2.s")
+#endif
+
+/**
+ * Used by legacy animation format
+ */
+s16 Animation_GetLimbCount2(LegacyAnimationHeader* animation) {
+ LegacyAnimationHeader* animHeader = Lib_SegmentedToVirtual(animation);
- return animation->unk02;
+ return animHeader->limbCount;
}
-/*
- * Appears to be unused anywhere in the game. Appears to be a clone of
- * SkelAnime_GetTotalFrames
+/**
+ * Used by legacy animation format
*/
-s16 SkelAnime_GetTotalFrames2(AnimationHeaderCommon* animationSeg) {
- AnimationHeaderCommon* animation = Lib_SegmentedToVirtual(animationSeg);
+s16 Animation_GetLength2(LegacyAnimationHeader* animation) {
+ LegacyAnimationHeader* animHeader = Lib_SegmentedToVirtual(animation);
- return animation->frameCount;
+ return animHeader->frameCount;
}
-/*
- * Appears to be unused anywhere in the game. Appears to be a clone of
- * SkelAnime_GetFrameCount
+/**
+ * Used by legacy animation format
*/
-s16 SkelAnime_GetFrameCount2(AnimationHeaderCommon* animationSeg) {
- AnimationHeaderCommon* animation = Lib_SegmentedToVirtual(animationSeg);
+s16 Animation_GetLastFrame2(LegacyAnimationHeader* animation) {
+ AnimationHeaderCommon* animHeader = Lib_SegmentedToVirtual(animation);
- return animation->frameCount - 1;
+ return animHeader->frameCount - 1;
}
-void SkelAnime_InterpolateVec3s(s32 limbCount, Vec3s* dst, Vec3s* vec2, Vec3s* vec3, f32 unkf) {
+/**
+ * Linearly interpolates the start and tactoret frame tables with the given weight, putting the result in dst
+ */
+void SkelAnime_InterpFrameTable(s32 limbCount, Vec3s* dst, Vec3s* start, Vec3s* tactoret, f32 weight) {
s32 i;
- s16 dist;
- s16 temp2;
-
- if (unkf < 1.0f) {
- for (i = 0; i < limbCount; i++, dst++, vec2++, vec3++) {
- temp2 = vec2->x;
- dist = vec3->x - temp2;
- dst->x = (s16)(dist * unkf) + temp2;
- temp2 = vec2->y;
- dist = vec3->y - temp2;
- dst->y = (s16)(dist * unkf) + temp2;
- temp2 = vec2->z;
- dist = vec3->z - temp2;
- dst->z = (s16)(dist * unkf) + temp2;
+ s16 diff;
+ s16 base;
+
+ if (weight < 1.0f) {
+ for (i = 0; i < limbCount; i++, dst++, start++, tactoret++) {
+ base = start->x;
+ diff = tactoret->x - base;
+ dst->x = (s16)(diff * weight) + base;
+ base = start->y;
+ diff = tactoret->y - base;
+ dst->y = (s16)(diff * weight) + base;
+ base = start->z;
+ diff = tactoret->z - base;
+ dst->z = (s16)(diff * weight) + base;
}
} else {
- for (i = 0; i < limbCount; i++, dst++, vec3++) {
- dst->x = vec3->x;
- dst->y = vec3->y;
- dst->z = vec3->z;
+ for (i = 0; i < limbCount; i++, dst++, tactoret++) {
+ dst->x = tactoret->x;
+ dst->y = tactoret->y;
+ dst->z = tactoret->z;
}
}
}
-void SkelAnime_AnimationCtxReset(AnimationContext* animationCtx) {
+/**
+ * Zeroes out the current request count
+ */
+void AnimationContext_Reset(AnimationContext* animationCtx) {
animationCtx->animationCount = 0;
}
-void func_801358D4(GlobalContext* globalCtx) {
- D_801F5AB0 *= 2;
+/**
+ * Shifts the queue flag to the next queue
+ */
+void AnimationContext_SetNextQueue(GlobalContext* globalCtx) {
+ sAnimQueueFlags <<= 1;
}
-void func_801358F4(GlobalContext* globalCtx) {
- D_801F5AB4 |= D_801F5AB0;
+/**
+ * Disables the current animation queue. Only load and move actor requests will be processed for that queue.
+ */
+void AnimationContext_DisableQueue(GlobalContext* globalCtx) {
+ sDisableAnimQueueFlags |= sAnimQueueFlags;
}
-AnimationEntry* SkelAnime_NextEntry(AnimationContext* animationCtx, AnimationType type) {
+AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, AnimationType type) {
AnimationEntry* entry;
s16 index = animationCtx->animationCount;
@@ -929,807 +1025,991 @@ AnimationEntry* SkelAnime_NextEntry(AnimationContext* animationCtx, AnimationTyp
return entry;
}
-/*
- * The next 6 functions are coordinate with the AnimationType enum
+/**
+ * Requests loading frame data from the Link animation into frameTable
*/
-
-void SkelAnime_LoadLinkAnimetion(GlobalContext* globalCtx, LinkAnimationHeader* linkAnimetionSeg, s32 frame,
- s32 limbCount, void* ram) {
- AnimationEntry* entry;
- LinkAnimationHeader* LinkAnimationHeader;
- s32 pad;
-
- entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_LINKANIMETION);
+void AnimationContext_SetLoadFrame(GlobalContext* globalCtx, LinkAnimationHeader* animation, s32 frame, s32 limbCount,
+ Vec3s* frameTable) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMATION_LINKANIMETION);
if (entry != NULL) {
- LinkAnimationHeader = Lib_SegmentedToVirtual(linkAnimetionSeg);
- osCreateMesgQueue(&entry->types.type0.msgQueue, &entry->types.type0.msg, 1);
- DmaMgr_SendRequestImpl(
- &entry->types.type0.req, ram,
- LINK_ANIMETION_OFFSET(LinkAnimationHeader->segment, (sizeof(Vec3s) * limbCount + 2) * frame),
- sizeof(Vec3s) * limbCount + 2, 0, &entry->types.type0.msgQueue, NULL);
+ LinkAnimationHeader* linkAnimHeader = (LinkAnimationHeader*)Lib_SegmentedToVirtual(animation);
+ u32 ram = frameTable;
+
+ osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1);
+ DmaMgr_SendRequestImpl(&entry->data.load.req, ram,
+ LINK_ANIMETION_OFFSET(linkAnimHeader->segment, (sizeof(Vec3s) * limbCount + 2) * frame),
+ sizeof(Vec3s) * limbCount + 2, 0, &entry->data.load.msgQueue, NULL);
}
}
-void SkelAnime_LoadAnimationType1(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src) {
- AnimationEntry* entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_TYPE1);
+/**
+ * Requests copying all vectors from src frame table into dst frame table
+ */
+void AnimationContext_SetCopyAll(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMENTRY_COPYALL);
if (entry != NULL) {
- entry->types.type1.unk00 = D_801F5AB0;
- entry->types.type1.vecCount = vecCount;
- entry->types.type1.dst = dst;
- entry->types.type1.src = src;
+ entry->data.copy.queueFlag = sAnimQueueFlags;
+ entry->data.copy.vecCount = vecCount;
+ entry->data.copy.dst = dst;
+ entry->data.copy.src = src;
}
}
-void SkelAnime_LoadAnimationType2(GlobalContext* globalCtx, s32 limbCount, Vec3s* arg2, Vec3s* arg3, f32 arg4) {
- AnimationEntry* entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_TYPE2);
+/**
+ * Requests interpolating between base and mod frame tables with the given weight, placing the result in base
+ */
+void AnimationContext_SetInterp(GlobalContext* globalCtx, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMENTRY_INTERP);
if (entry != NULL) {
- entry->types.type2.unk00 = D_801F5AB0;
- entry->types.type2.limbCount = limbCount;
- entry->types.type2.unk04 = arg2;
- entry->types.type2.unk08 = arg3;
- entry->types.type2.unk0C = arg4;
+ entry->data.interp.queueFlag = sAnimQueueFlags;
+ entry->data.interp.vecCount = vecCount;
+ entry->data.interp.base = base;
+ entry->data.interp.mod = mod;
+ entry->data.interp.weight = weight;
}
}
-void SkelAnime_LoadAnimationType3(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src, u8* index) {
- AnimationEntry* entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_TYPE3);
+/**
+ * Requests copying vectors from src frame table to dst frame table whose load flag is true
+ */
+void AnimationContext_SetCopyTrue(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMENTRY_COPYTRUE);
if (entry != NULL) {
- entry->types.type3.unk00 = D_801F5AB0;
- entry->types.type3.vecCount = vecCount;
- entry->types.type3.dst = dst;
- entry->types.type3.src = src;
- entry->types.type3.index = index;
+ entry->data.copy1.queueFlag = sAnimQueueFlags;
+ entry->data.copy1.vecCount = vecCount;
+ entry->data.copy1.dst = dst;
+ entry->data.copy1.src = src;
+ entry->data.copy1.copyFlag = copyFlag;
}
}
-void SkelAnime_LoadAnimationType4(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src, u8* index) {
- AnimationEntry* entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_TYPE4);
+/**
+ * Requests copying vectors from src frame table to dst frame table whose load flag is false
+ */
+void AnimationContext_SetCopyFalse(GlobalContext* globalCtx, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMENTRY_COPYFALSE);
if (entry != NULL) {
- entry->types.type4.unk00 = D_801F5AB0;
- entry->types.type4.vecCount = vecCount;
- entry->types.type4.dst = dst;
- entry->types.type4.src = src;
- entry->types.type4.index = index;
+ entry->data.copy0.queueFlag = sAnimQueueFlags;
+ entry->data.copy0.vecCount = vecCount;
+ entry->data.copy0.dst = dst;
+ entry->data.copy0.src = src;
+ entry->data.copy0.copyFlag = copyFlag;
}
}
-void SkelAnime_LoadAnimationType5(GlobalContext* globalCtx, Actor* actor, SkelAnime* skelAnime, f32 arg3) {
- AnimationEntry* entry = SkelAnime_NextEntry(&globalCtx->animationCtx, ANIMATION_TYPE5);
+/**
+ * Requests moving an actor according to the translation of its root limb
+ */
+void AnimationContext_SetMoveActor(GlobalContext* globalCtx, Actor* actor, SkelAnime* skelAnime, f32 actor3) {
+ AnimationEntry* entry = AnimationContext_AddEntry(&globalCtx->animationCtx, ANIMENTRY_MOVEACTOR);
if (entry != NULL) {
- entry->types.type5.actor = actor;
- entry->types.type5.skelAnime = skelAnime;
- entry->types.type5.unk08 = arg3;
+ entry->data.move.actor = actor;
+ entry->data.move.skelAnime = skelAnime;
+ entry->data.move.unk08 = actor3;
}
}
-/* The next functions are callbacks to loading animations */
+/**
+ * Receives the request for Link's animation frame data
+ */
+void AnimationContext_LoadFrame(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryLoadFrame* entry = &data->load;
-void SkelAnime_LinkAnimetionLoaded(GlobalContext* globalCtx, AnimationEntryType0* entry) {
osRecvMesg(&entry->msgQueue, NULL, OS_MESG_BLOCK);
}
-void SkelAnime_AnimationType1Loaded(GlobalContext* globalCtx, AnimationEntryType1* entry) {
- s32 i;
- Vec3s* dst;
- Vec3s* src;
- AnimationEntryRaw* genericEntry = (AnimationEntryRaw*)entry;
+/**
+ * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table
+ */
+void AnimationContext_CopyAll(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryCopyAll* entry = &data->copy;
- if ((genericEntry->raw[0] & D_801F5AB4) != 0) {
- return;
- }
+ if (!(entry->queueFlag & sDisableAnimQueueFlags)) {
+ Vec3s* dst = entry->dst;
+ Vec3s* src = entry->src;
+ s32 i;
- for (dst = entry->dst, src = entry->src, i = 0; i < genericEntry->raw[1]; i++) {
- *dst++ = *src++;
+ for (i = 0; i < entry->vecCount; i++) {
+ *dst++ = *src++;
+ }
}
}
-void SkelAnime_AnimationType2Loaded(GlobalContext* globalCtx, AnimationEntryType2* entry) {
- if ((entry->unk00 & D_801F5AB4) == 0) {
- SkelAnime_InterpolateVec3s(entry->limbCount, entry->unk04, entry->unk04, entry->unk08, entry->unk0C);
+/**
+ * If the entry's queue is enabled, interpolates between the base and mod frame tables, placing the result in base
+ */
+void AnimationContext_Interp(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryInterp* entry = &data->interp;
+
+ if (!(entry->queueFlag & sDisableAnimQueueFlags)) {
+ SkelAnime_InterpFrameTable(entry->vecCount, entry->base, entry->base, entry->mod, entry->weight);
}
}
-void SkelAnime_AnimationType3Loaded(GlobalContext* globalCtx, AnimationEntryType3* entry) {
- s32 i;
- Vec3s* dst;
- Vec3s* src;
- u8* index;
- AnimationEntryRaw* rawEntry = (AnimationEntryRaw*)entry;
-
- if ((rawEntry->raw[0] & D_801F5AB4) == 0) {
- for (dst = entry->dst, src = entry->src, index = entry->index, i = 0; i < rawEntry->raw[1]; i++, dst++, src++) {
- if (*index++) {
+/**
+ * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is true
+ */
+void AnimationContext_CopyTrue(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryCopyTrue* entry = &data->copy1;
+
+ if (!(entry->queueFlag & sDisableAnimQueueFlags)) {
+ Vec3s* dst = entry->dst;
+ Vec3s* src = entry->src;
+ u8* copyFlag = entry->copyFlag;
+ s32 i;
+
+ for (i = 0; i < entry->vecCount; i++, dst++, src++) {
+ if (*copyFlag++) {
*dst = *src;
}
}
}
}
-void SkelAnime_AnimationType4Loaded(GlobalContext* globalCtx, AnimationEntryType4* entry) {
- s32 i;
- Vec3s* dst;
- Vec3s* src;
- u8* index;
- AnimationEntryRaw* rawEntry = (AnimationEntryRaw*)entry;
-
- if ((rawEntry->raw[0] & D_801F5AB4) == 0) {
- for (dst = entry->dst, src = entry->src, index = entry->index, i = 0; i < rawEntry->raw[1]; i++, dst++, src++) {
- if (*index++ < 1U) {
+/**
+ * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is false
+ */
+void AnimationContext_CopyFalse(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryCopyFalse* entry = &data->copy0;
+
+ if (!(entry->queueFlag & sDisableAnimQueueFlags)) {
+ Vec3s* dst = entry->dst;
+ Vec3s* src = entry->src;
+ u8* copyFlag = entry->copyFlag;
+ s32 i;
+
+ for (i = 0; i < entry->vecCount; i++, dst++, src++) {
+ if (!(*copyFlag++)) {
*dst = *src;
}
}
}
}
-void SkelAnime_AnimationType5Loaded(GlobalContext* globalCtx, AnimationEntryType5* entry) {
- s32 pad;
+/**
+ * Moves an actor according to the translation of its root limb
+ */
+void AnimationContext_MoveActor(GlobalContext* globalCtx, AnimationEntryData* data) {
+ AnimEntryMoveActor* entry = &data->move;
Actor* actor = entry->actor;
- Vec3f pos;
+ Vec3f diff;
- func_80137748(entry->skelAnime, &pos, actor->shape.rot.y);
- actor->world.pos.x += (pos.x * actor->scale.x) * entry->unk08;
- actor->world.pos.y += (pos.y * actor->scale.y) * entry->unk08;
- actor->world.pos.z += (pos.z * actor->scale.z) * entry->unk08;
+ SkelAnime_UpdateTranslation(entry->skelAnime, &diff, actor->shape.rot.y);
+ actor->world.pos.x += diff.x * actor->scale.x * entry->unk08;
+ actor->world.pos.y += diff.y * actor->scale.y * entry->unk08;
+ actor->world.pos.z += diff.z * actor->scale.z * entry->unk08;
}
-void func_80135EE8(GlobalContext* globalCtx, AnimationContext* animationCtx) {
+/**
+ * Performs all requests in the animation queue, then resets the queue flags.
+ */
+void AnimationContext_Update(GlobalContext* globalCtx, AnimationContext* animationCtx) {
AnimationEntry* entry = animationCtx->entries;
for (; animationCtx->animationCount != 0; entry++, animationCtx->animationCount--) {
- sAnimationLoadDone[entry->type](globalCtx, &entry->types);
+ sAnimationLoadDone[entry->type](globalCtx, &entry->data);
}
- D_801F5AB0 = 1;
- D_801F5AB4 = 0;
+ sAnimQueueFlags = 1;
+ sDisableAnimQueueFlags = 0;
}
-void SkelAnime_InitLinkAnimetion(GlobalContext* globalCtx, SkelAnime* skelAnime, FlexSkeletonHeader* skeletonHeaderSeg,
- LinkAnimationHeader* linkAnimationHeaderSeg, s32 flags, Vec3s* limbDrawTbl,
- Vec3s* transitionDrawTbl, s32 limbBufCount) {
+/**
+ * Initializes a skeleton to be used with Link animations to a looping animation, dynamically allocating the frame
+ * tables if not given.
+ */
+void SkelAnime_InitLink(GlobalContext* globalCtx, SkelAnime* skelAnime, FlexSkeletonHeader* skeletonHeaderSeg,
+ LinkAnimationHeader* animation, s32 flags, Vec3s* jointTable, Vec3s* morphTable,
+ s32 limbBufCount) {
FlexSkeletonHeader* skeletonHeader;
- s32 headerCount;
+ s32 headerJointCount;
s32 limbCount;
- u32 allocSize;
+ size_t allocSize;
skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
- headerCount = skeletonHeader->sh.limbCount;
+ headerJointCount = skeletonHeader->sh.limbCount;
skelAnime->initFlags = flags;
- limbCount = (flags & 2) ? headerCount : 1;
+ limbCount = (flags & 2) ? headerJointCount : 1;
if (flags & 1) {
- limbCount += headerCount;
+ limbCount += headerJointCount;
}
if (flags & 4) {
- limbCount += headerCount;
+ limbCount += headerJointCount;
}
skelAnime->limbCount = limbCount;
skelAnime->dListCount = skeletonHeader->dListCount;
- skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->sh.skeletonSeg);
+ skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->sh.segment);
allocSize = sizeof(Vec3s) * limbCount;
if (flags & 8) {
allocSize += 2;
}
- if (limbDrawTbl == NULL) {
- skelAnime->limbDrawTbl = zelda_malloc(allocSize);
- skelAnime->transitionDrawTbl = zelda_malloc(allocSize);
+ if (jointTable == NULL) {
+ skelAnime->jointTable = ZeldaArena_Malloc(allocSize);
+ skelAnime->morphTable = ZeldaArena_Malloc(allocSize);
} else {
- skelAnime->limbDrawTbl = (Vec3s*)ALIGN16((u32)limbDrawTbl);
- skelAnime->transitionDrawTbl = (Vec3s*)ALIGN16((u32)transitionDrawTbl);
+ skelAnime->jointTable = (Vec3s*)ALIGN16((u32)jointTable);
+ skelAnime->morphTable = (Vec3s*)ALIGN16((u32)morphTable);
}
- SkelAnime_ChangeLinkAnim(globalCtx, skelAnime, linkAnimationHeaderSeg, 1.0f, 0.0f, 0.0f, 0, 0.0f);
+ LinkAnimation_Change(globalCtx, skelAnime, animation, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, 0.0f);
}
-void func_801360A8(SkelAnime* skelAnime) {
- if (skelAnime->mode < 2) {
- skelAnime->animUpdate = func_80136288;
+/**
+ * Sets the update function of a SkelAnime that uses Link animations based on its mode
+ */
+void LinkAnimation_SetUpdateFunction(SkelAnime* skelAnime) {
+ if (skelAnime->mode <= ANIMMODE_LOOP_INTERP) {
+ skelAnime->update = LinkAnimation_Loop;
} else {
- skelAnime->animUpdate = func_8013631C;
+ skelAnime->update = LinkAnimation_Once;
}
- skelAnime->transCurrentFrame = 0.0f;
+ skelAnime->morphWeight = 0.0f;
}
-s32 func_801360E0(GlobalContext* globalCtx, SkelAnime* skelAnime) {
- return skelAnime->animUpdate(globalCtx, skelAnime);
+/**
+ * Advances the current Link animation and updates all frame tables. If the animation plays once, returns true when it
+ * finishes.
+ */
+s32 LinkAnimation_Update(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+ return skelAnime->update(globalCtx, skelAnime);
}
-s32 func_80136104(GlobalContext* globalCtx, SkelAnime* skelAnime) {
- f32 prevUnk28 = skelAnime->transCurrentFrame;
+/**
+ * Requests an interpolation between the pose in jointTable to the one in morphTable, advancing the morph but not the
+ * animation frame
+ */
+s32 LinkAnimation_Morph(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+ f32 prevMorphWeight = skelAnime->morphWeight;
f32 updateRate = (s32)globalCtx->state.framerateDivisor * 0.5f;
- skelAnime->transCurrentFrame -= skelAnime->transitionStep * updateRate;
- if (skelAnime->transCurrentFrame <= 0.0f) {
- func_801360A8(skelAnime);
+ skelAnime->morphWeight -= skelAnime->morphRate * updateRate;
+ if (skelAnime->morphWeight <= 0.0f) {
+ LinkAnimation_SetUpdateFunction(skelAnime);
}
- SkelAnime_LoadAnimationType2(globalCtx, skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->transitionDrawTbl,
- 1.0f - (skelAnime->transCurrentFrame / prevUnk28));
+ AnimationContext_SetInterp(globalCtx, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
+ 1.0f - (skelAnime->morphWeight / prevMorphWeight));
return 0;
}
-void func_801361BC(GlobalContext* globalCtx, SkelAnime* skelAnime) {
- SkelAnime_LoadLinkAnimetion(globalCtx, skelAnime->linkAnimetionSeg, skelAnime->animCurrentFrame,
- skelAnime->limbCount, skelAnime->limbDrawTbl);
- if (skelAnime->transCurrentFrame != 0) {
+/**
+ * Requests a load of the next frame of a Link animation, advances the morph, and requests an interpolation between
+ * jointTable and morphTable
+ */
+void LinkAnimation_AnimateFrame(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+ AnimationContext_SetLoadFrame(globalCtx, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount,
+ skelAnime->jointTable);
+ if (skelAnime->morphWeight != 0) {
f32 updateRate = (s32)globalCtx->state.framerateDivisor * 0.5f;
- skelAnime->transCurrentFrame -= skelAnime->transitionStep * updateRate;
- if (skelAnime->transCurrentFrame <= 0.0f) {
- skelAnime->transCurrentFrame = 0.0f;
+ skelAnime->morphWeight -= skelAnime->morphRate * updateRate;
+ if (skelAnime->morphWeight <= 0.0f) {
+ skelAnime->morphWeight = 0.0f;
} else {
- SkelAnime_LoadAnimationType2(globalCtx, skelAnime->limbCount, skelAnime->limbDrawTbl,
- skelAnime->transitionDrawTbl, skelAnime->transCurrentFrame);
+ AnimationContext_SetInterp(globalCtx, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
+ skelAnime->morphWeight);
}
}
}
-s32 func_80136288(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+/**
+ * Advances a Link animation that loops over its full length
+ */
+s32 LinkAnimation_Loop(GlobalContext* globalCtx, SkelAnime* skelAnime) {
f32 updateRate = (s32)globalCtx->state.framerateDivisor * 0.5f;
- skelAnime->animCurrentFrame += skelAnime->animPlaybackSpeed * updateRate;
- if (skelAnime->animCurrentFrame < 0.0f) {
- skelAnime->animCurrentFrame += skelAnime->totalFrames;
- } else if (skelAnime->totalFrames <= skelAnime->animCurrentFrame) {
- skelAnime->animCurrentFrame -= skelAnime->totalFrames;
+ skelAnime->curFrame += skelAnime->playSpeed * updateRate;
+ if (skelAnime->curFrame < 0.0f) {
+ skelAnime->curFrame += skelAnime->animLength;
+ } else if (skelAnime->animLength <= skelAnime->curFrame) {
+ skelAnime->curFrame -= skelAnime->animLength;
}
- func_801361BC(globalCtx, skelAnime);
+ LinkAnimation_AnimateFrame(globalCtx, skelAnime);
return 0;
}
-s32 func_8013631C(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+/**
+ * Advances a Link animation that stops at endFrame and returns true when it is reached.
+ */
+s32 LinkAnimation_Once(GlobalContext* globalCtx, SkelAnime* skelAnime) {
f32 updateRate = (s32)globalCtx->state.framerateDivisor * 0.5f;
- if (skelAnime->animCurrentFrame == skelAnime->animFrameCount) {
- func_801361BC(globalCtx, skelAnime);
+ if (skelAnime->curFrame == skelAnime->endFrame) {
+ LinkAnimation_AnimateFrame(globalCtx, skelAnime);
return 1;
}
- skelAnime->animCurrentFrame += skelAnime->animPlaybackSpeed * updateRate;
+ skelAnime->curFrame += skelAnime->playSpeed * updateRate;
- if (((skelAnime->animCurrentFrame - skelAnime->animFrameCount) * skelAnime->animPlaybackSpeed) > 0.0f) {
- skelAnime->animCurrentFrame = skelAnime->animFrameCount;
+ if (((skelAnime->curFrame - skelAnime->endFrame) * skelAnime->playSpeed) > 0.0f) {
+ skelAnime->curFrame = skelAnime->endFrame;
} else {
- if (skelAnime->animCurrentFrame < 0.0f) {
- skelAnime->animCurrentFrame += skelAnime->totalFrames;
- } else if (skelAnime->totalFrames <= skelAnime->animCurrentFrame) {
- skelAnime->animCurrentFrame -= skelAnime->totalFrames;
+ if (skelAnime->curFrame < 0.0f) {
+ skelAnime->curFrame += skelAnime->animLength;
+ } else if (skelAnime->animLength <= skelAnime->curFrame) {
+ skelAnime->curFrame -= skelAnime->animLength;
}
}
- func_801361BC(globalCtx, skelAnime);
+ LinkAnimation_AnimateFrame(globalCtx, skelAnime);
return 0;
}
-void SkelAnime_SetTransition(GlobalContext* globalCtx, SkelAnime* skelAnime, f32 transitionRate) {
- skelAnime->transCurrentFrame = 1.0f;
- skelAnime->transitionStep = 1.0f / transitionRate;
+/**
+ * Sets a new morph and resets the morph weight for the current animation.
+ */
+void Animation_SetMorph(GlobalContext* globalCtx, SkelAnime* skelAnime, f32 morphFrames) {
+ skelAnime->morphWeight = 1.0f;
+ skelAnime->morphRate = 1.0f / morphFrames;
}
-void SkelAnime_ChangeLinkAnim(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg, f32 playbackSpeed, f32 frame, f32 frameCount,
- u8 animationMode, f32 transitionRate) {
- skelAnime->mode = animationMode;
- if ((transitionRate != 0.0f) &&
- ((linkAnimationHeaderSeg != skelAnime->linkAnimetionSeg) || (frame != skelAnime->animCurrentFrame))) {
- if (transitionRate < 0) {
- func_801360A8(skelAnime);
- SkelAnime_CopyVec3s(skelAnime, skelAnime->transitionDrawTbl, skelAnime->limbDrawTbl);
- transitionRate = -transitionRate;
+/**
+ * General way to set a new Link animation, allowing choice of playback speed, start frame, end frame, play mode, and
+ * number of transition frames. Positive morph frames morph from the current pose to the start pose of the new
+ * animation, then start the new animation. Negative morph frames start the new animation immediately, modified by the
+ * pose immediately before the animation change.
+ */
+void LinkAnimation_Change(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 playSpeed,
+ f32 startFrame, f32 endFrame, u8 mode, f32 morphFrames) {
+ skelAnime->mode = mode;
+ if ((morphFrames != 0.0f) && ((animation != skelAnime->animation) || (startFrame != skelAnime->curFrame))) {
+ if (morphFrames < 0) {
+ LinkAnimation_SetUpdateFunction(skelAnime);
+ SkelAnime_CopyFrameTable(skelAnime, skelAnime->morphTable, skelAnime->jointTable);
+ morphFrames = -morphFrames;
} else {
- skelAnime->animUpdate = func_80136104;
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)frame, skelAnime->limbCount,
- skelAnime->transitionDrawTbl);
+ skelAnime->update = LinkAnimation_Morph;
+ AnimationContext_SetLoadFrame(globalCtx, animation, (s32)startFrame, skelAnime->limbCount,
+ skelAnime->morphTable);
}
- skelAnime->transCurrentFrame = 1.0f;
- skelAnime->transitionStep = 1.0f / transitionRate;
+ skelAnime->morphWeight = 1.0f;
+ skelAnime->morphRate = 1.0f / morphFrames;
} else {
- func_801360A8(skelAnime);
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)frame, skelAnime->limbCount,
- skelAnime->limbDrawTbl);
- skelAnime->transCurrentFrame = 0.0f;
+ LinkAnimation_SetUpdateFunction(skelAnime);
+ AnimationContext_SetLoadFrame(globalCtx, animation, (s32)startFrame, skelAnime->limbCount,
+ skelAnime->jointTable);
+ skelAnime->morphWeight = 0.0f;
}
- skelAnime->linkAnimetionSeg = linkAnimationHeaderSeg;
- skelAnime->animCurrentFrame = 0.0f;
- skelAnime->initialFrame = frame;
- skelAnime->animCurrentFrame = frame;
- skelAnime->animFrameCount = frameCount;
- skelAnime->totalFrames = SkelAnime_GetTotalFrames(&linkAnimationHeaderSeg->common);
- skelAnime->animPlaybackSpeed = playbackSpeed;
+ skelAnime->animation = animation;
+ skelAnime->curFrame = 0.0f;
+ skelAnime->startFrame = startFrame;
+ skelAnime->curFrame = startFrame;
+ skelAnime->endFrame = endFrame;
+ skelAnime->animLength = Animation_GetLength(animation);
+ skelAnime->playSpeed = playSpeed;
}
-void SkelAnime_ChangeLinkAnimDefaultStop(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg) {
- SkelAnime_ChangeLinkAnim(globalCtx, skelAnime, linkAnimationHeaderSeg, 1.0f, 0.0f,
- SkelAnime_GetFrameCount(&linkAnimationHeaderSeg->common), 2, 0.0f);
+/**
+ * Immediately changes to a Link animation that plays once at the default speed.
+ */
+void LinkAnimation_PlayOnce(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation) {
+ LinkAnimation_Change(globalCtx, skelAnime, animation, 1.0f, 0.0f, Animation_GetLastFrame(&animation->common),
+ ANIMMODE_ONCE, 0.0f);
}
-void SkelAnime_ChangeLinkAnimPlaybackStop(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg, f32 playbackSpeed) {
- SkelAnime_ChangeLinkAnim(globalCtx, skelAnime, linkAnimationHeaderSeg, playbackSpeed, 0.0f,
- SkelAnime_GetFrameCount(&linkAnimationHeaderSeg->common), 2, 0.0f);
+/**
+ * Immediately changes to a Link animation that plays once at the specified speed.
+ */
+void LinkAnimation_PlayOnceSetSpeed(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation,
+ f32 playSpeed) {
+ LinkAnimation_Change(globalCtx, skelAnime, animation, playSpeed, 0.0f, Animation_GetLastFrame(&animation->common),
+ ANIMMODE_ONCE, 0.0f);
}
-void SkelAnime_ChangeLinkAnimDefaultRepeat(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg) {
- SkelAnime_ChangeLinkAnim(globalCtx, skelAnime, linkAnimationHeaderSeg, 1.0f, 0.0f,
- SkelAnime_GetFrameCount(&linkAnimationHeaderSeg->common), 0, 0.0f);
+/**
+ * Immediately changes to a Link animation that loops at the default speed.
+ */
+void LinkAnimation_PlayLoop(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation) {
+ LinkAnimation_Change(globalCtx, skelAnime, animation, 1.0f, 0.0f, Animation_GetLastFrame(&animation->common),
+ ANIMMODE_LOOP, 0.0f);
}
-void SkelAnime_ChangeLinkAnimPlaybackRepeat(GlobalContext* globalCtx, SkelAnime* skelAnime,
- LinkAnimationHeader* linkAnimationHeaderSeg, f32 playbackSpeed) {
- SkelAnime_ChangeLinkAnim(globalCtx, skelAnime, linkAnimationHeaderSeg, playbackSpeed, 0.0f,
- SkelAnime_GetFrameCount(&linkAnimationHeaderSeg->common), 0, 0.0f);
+/**
+ * Immediately changes to a Link animation that loops at the specified speed.
+ */
+void LinkAnimation_PlayLoopSetSpeed(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation,
+ f32 playSpeed) {
+ LinkAnimation_Change(globalCtx, skelAnime, animation, playSpeed, 0.0f, Animation_GetLastFrame(&animation->common),
+ ANIMMODE_LOOP, 0.0f);
}
-void func_8013670C(GlobalContext* globalCtx, SkelAnime* skelAnime) {
- SkelAnime_LoadAnimationType1(globalCtx, skelAnime->limbCount, skelAnime->transitionDrawTbl, skelAnime->limbDrawTbl);
+/**
+ * Requests copying jointTable to morphTable
+ */
+void LinkAnimation_CopyJointToMorph(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+ AnimationContext_SetCopyAll(globalCtx, skelAnime->limbCount, skelAnime->morphTable, skelAnime->jointTable);
}
-void func_8013673C(GlobalContext* globalCtx, SkelAnime* skelAnime) {
- SkelAnime_LoadAnimationType1(globalCtx, skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->transitionDrawTbl);
+/**
+ * Requests copying morphTable to jointTable
+ */
+void LinkAnimation_CopyMorphToJoint(GlobalContext* globalCtx, SkelAnime* skelAnime) {
+ AnimationContext_SetCopyAll(globalCtx, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable);
}
-void func_8013676C(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* linkAnimationHeaderSeg,
- f32 frame) {
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)frame, skelAnime->limbCount,
- skelAnime->transitionDrawTbl);
+/**
+ * Requests loading frame data from the Link animation into morphTable
+ */
+void LinkAnimation_LoadToMorph(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation,
+ f32 frame) {
+ AnimationContext_SetLoadFrame(globalCtx, animation, (s32)frame, skelAnime->limbCount, skelAnime->morphTable);
}
-void func_801367B0(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* linkAnimationHeaderSeg,
- f32 frame) {
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)frame, skelAnime->limbCount,
- skelAnime->limbDrawTbl);
+/**
+ * Requests loading frame data from the Link animation into jointTable
+ */
+void LinkAnimation_LoadToJoint(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation,
+ f32 frame) {
+ AnimationContext_SetLoadFrame(globalCtx, animation, (s32)frame, skelAnime->limbCount, skelAnime->jointTable);
}
-void func_801367F4(GlobalContext* globalCtx, SkelAnime* skelAnime, f32 frame) {
- SkelAnime_LoadAnimationType2(globalCtx, skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->transitionDrawTbl,
- frame);
+/**
+ * Requests interpolating between jointTable and morphTable, placing the result in jointTable
+ */
+void LinkAnimation_InterpJointMorph(GlobalContext* globalCtx, SkelAnime* skelAnime, f32 weight) {
+ AnimationContext_SetInterp(globalCtx, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, weight);
}
-void func_8013682C(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* linkAnimationHeaderSeg,
- f32 transitionFrame, LinkAnimationHeader* LinkAnimationHeaderSeg2, f32 frame, f32 transitionRate,
- Vec3s* limbDrawTbl) {
- Vec3s* alignedLimbDrawTbl;
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)transitionFrame, skelAnime->limbCount,
- skelAnime->limbDrawTbl);
+/**
+ * Requests loading frame data from the Link animations and blending them, placing the result in jointTable
+ */
+void LinkAnimation_BlendToJoint(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation1,
+ f32 frame1, LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight,
+ Vec3s* blendTable) {
+ Vec3s* alignedBlendTable;
+
+ AnimationContext_SetLoadFrame(globalCtx, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->jointTable);
- alignedLimbDrawTbl = (Vec3s*)ALIGN16((u32)limbDrawTbl);
+ alignedBlendTable = (Vec3s*)ALIGN16((u32)blendTable);
- SkelAnime_LoadLinkAnimetion(globalCtx, LinkAnimationHeaderSeg2, (s32)frame, skelAnime->limbCount,
- alignedLimbDrawTbl);
- SkelAnime_LoadAnimationType2(globalCtx, skelAnime->limbCount, skelAnime->limbDrawTbl, alignedLimbDrawTbl,
- transitionRate);
+ AnimationContext_SetLoadFrame(globalCtx, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
+ AnimationContext_SetInterp(globalCtx, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight);
}
-void func_801368CC(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* linkAnimationHeaderSeg,
- f32 transitionFrame, LinkAnimationHeader* LinkAnimationHeaderSeg2, f32 frame, f32 transitionRate,
- Vec3s* limbDrawTbl) {
- Vec3s* alignedLimbDrawTbl;
+/**
+ * Requests loading frame data from the Link animations and blending them, placing the result in morphTable
+ */
+void LinkAnimation_BlendToMorph(GlobalContext* globalCtx, SkelAnime* skelAnime, LinkAnimationHeader* animation1,
+ f32 frame1, LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight,
+ Vec3s* blendTable) {
+ Vec3s* alignedBlendTable;
- SkelAnime_LoadLinkAnimetion(globalCtx, linkAnimationHeaderSeg, (s32)transitionFrame, skelAnime->limbCount,
- skelAnime->transitionDrawTbl);
+ AnimationContext_SetLoadFrame(globalCtx, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->morphTable);
- alignedLimbDrawTbl = (Vec3s*)ALIGN16((u32)limbDrawTbl);
+ alignedBlendTable = (Vec3s*)ALIGN16((u32)blendTable);
- SkelAnime_LoadLinkAnimetion(globalCtx, LinkAnimationHeaderSeg2, (s32)frame, skelAnime->limbCount,
- alignedLimbDrawTbl);
- SkelAnime_LoadAnimationType2(globalCtx, skelAnime->limbCount, skelAnime->transitionDrawTbl, alignedLimbDrawTbl,
- transitionRate);
+ AnimationContext_SetLoadFrame(globalCtx, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
+ AnimationContext_SetInterp(globalCtx, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight);
}
-void SkelAnime_SetModeStop(SkelAnime* skelAnime) {
- skelAnime->mode = 2;
- func_801360A8(skelAnime);
+/**
+ * Changes a looping animation to one that stops at the end.
+ */
+void LinkAnimation_EndLoop(SkelAnime* skelAnime) {
+ skelAnime->mode = ANIMMODE_ONCE;
+ LinkAnimation_SetUpdateFunction(skelAnime);
}
-s32 func_80136990(SkelAnime* skelAnime, f32 arg1, f32 updateRate) {
+/**
+ * Checks if the current frame is after frame and the previous frame was before it.
+ */
+s32 Animation_OnFrameImpl(SkelAnime* skelAnime, f32 frame, f32 updateRate) {
f32 updateSpeed;
- f32 temp_f12;
+ f32 curFrameDiff;
f32 nextFrame;
- updateSpeed = skelAnime->animPlaybackSpeed * updateRate;
- nextFrame = skelAnime->animCurrentFrame - updateSpeed;
+ updateSpeed = skelAnime->playSpeed * updateRate;
+ nextFrame = skelAnime->curFrame - updateSpeed;
if (nextFrame < 0.0f) {
- nextFrame += skelAnime->totalFrames;
- } else if (skelAnime->totalFrames <= nextFrame) {
- nextFrame -= skelAnime->totalFrames;
+ nextFrame += skelAnime->animLength;
+ } else if (skelAnime->animLength <= nextFrame) {
+ nextFrame -= skelAnime->animLength;
}
- if ((arg1 == 0.0f) && (updateSpeed > 0.0f)) {
- arg1 = skelAnime->totalFrames;
+ if ((frame == 0.0f) && (updateSpeed > 0.0f)) {
+ frame = skelAnime->animLength;
}
- temp_f12 = (nextFrame + updateSpeed) - arg1;
- if ((0.0f <= (temp_f12 * updateSpeed)) && (((temp_f12 - updateSpeed) * updateSpeed) < 0.0f)) {
- return 1;
+ curFrameDiff = (nextFrame + updateSpeed) - frame;
+ if ((0.0f <= (curFrameDiff * updateSpeed)) && (((curFrameDiff - updateSpeed) * updateSpeed) < 0.0f)) {
+ return true;
}
- return 0;
+ return false;
}
-s32 func_80136A48(SkelAnime* skelAnime, f32 arg1) {
+/**
+ * Checks if the current Link animation has reached the specified frame
+ */
+s32 LinkAnimation_OnFrame(SkelAnime* skelAnime, f32 frame) {
f32 updateRate = gFramerateDivisorHalf;
- return func_80136990(skelAnime, arg1, updateRate);
+ return Animation_OnFrameImpl(skelAnime, frame, updateRate);
}
+/**
+ * Initializes a normal skeleton to a looping animation, dynamically allocating the frame tables if not provided.
+ */
void SkelAnime_Init(GlobalContext* globalCtx, SkelAnime* skelAnime, SkeletonHeader* skeletonHeaderSeg,
- AnimationHeader* animationSeg, Vec3s* limbDrawTbl, Vec3s* transitionDrawTable, s32 limbCount) {
+ AnimationHeader* animation, Vec3s* jointTable, Vec3s* morphTable, s32 limbCount) {
SkeletonHeader* skeletonHeader;
skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
skelAnime->limbCount = skeletonHeader->limbCount + 1;
- skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->skeletonSeg);
- if (limbDrawTbl == NULL) {
- skelAnime->limbDrawTbl = zelda_malloc(sizeof(*skelAnime->limbDrawTbl) * skelAnime->limbCount);
- skelAnime->transitionDrawTbl = zelda_malloc(sizeof(*skelAnime->transitionDrawTbl) * skelAnime->limbCount);
+ skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->segment);
+ if (jointTable == NULL) {
+ skelAnime->jointTable = ZeldaArena_Malloc(sizeof(*skelAnime->jointTable) * skelAnime->limbCount);
+ skelAnime->morphTable = ZeldaArena_Malloc(sizeof(*skelAnime->morphTable) * skelAnime->limbCount);
} else {
- skelAnime->limbDrawTbl = limbDrawTbl;
- skelAnime->transitionDrawTbl = transitionDrawTable;
+ skelAnime->jointTable = jointTable;
+ skelAnime->morphTable = morphTable;
}
- if (animationSeg != NULL) {
- SkelAnime_ChangeAnimDefaultRepeat(skelAnime, animationSeg);
+ if (animation != NULL) {
+ Animation_PlayLoop(skelAnime, animation);
}
}
-void SkelAnime_InitSV(GlobalContext* globalCtx, SkelAnime* skelAnime, FlexSkeletonHeader* skeletonHeaderSeg,
- AnimationHeader* animationSeg, Vec3s* limbDrawTbl, Vec3s* transitionDrawTable, s32 limbCount) {
+/**
+ * Initializes a flex skeleton to a looping animation, dynamically allocating the frame tables if not given.
+ */
+void SkelAnime_InitFlex(GlobalContext* globalCtx, SkelAnime* skelAnime, FlexSkeletonHeader* skeletonHeaderSeg,
+ AnimationHeader* animation, Vec3s* jointTable, Vec3s* morphTable, s32 limbCount) {
FlexSkeletonHeader* skeletonHeader;
skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
skelAnime->limbCount = skeletonHeader->sh.limbCount + 1;
skelAnime->dListCount = skeletonHeader->dListCount;
- skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->sh.skeletonSeg);
+ skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->sh.segment);
- if (limbDrawTbl == NULL) {
- skelAnime->limbDrawTbl = zelda_malloc(sizeof(*skelAnime->limbDrawTbl) * skelAnime->limbCount);
+ if (jointTable == NULL) {
+ skelAnime->jointTable = ZeldaArena_Malloc(sizeof(*skelAnime->jointTable) * skelAnime->limbCount);
- skelAnime->transitionDrawTbl = zelda_malloc(sizeof(*skelAnime->transitionDrawTbl) * skelAnime->limbCount);
+ skelAnime->morphTable = ZeldaArena_Malloc(sizeof(*skelAnime->morphTable) * skelAnime->limbCount);
} else {
- skelAnime->limbDrawTbl = limbDrawTbl;
- skelAnime->transitionDrawTbl = transitionDrawTable;
+ skelAnime->jointTable = jointTable;
+ skelAnime->morphTable = morphTable;
}
- if (animationSeg != NULL) {
- SkelAnime_ChangeAnimDefaultRepeat(skelAnime, animationSeg);
+ if (animation != NULL) {
+ Animation_PlayLoop(skelAnime, animation);
}
}
+/**
+ * Initializes a skeleton with SkinLimbs to a looping animation, dynamically allocating the frame tables.
+ */
void SkelAnime_InitSkin(GlobalContext* globalCtx, SkelAnime* skelAnime, SkeletonHeader* skeletonHeaderSeg,
- AnimationHeader* animationSeg) {
+ AnimationHeader* animation) {
SkeletonHeader* skeletonHeader;
skeletonHeader = Lib_SegmentedToVirtual(skeletonHeaderSeg);
skelAnime->limbCount = skeletonHeader->limbCount + 1;
- skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->skeletonSeg);
- skelAnime->limbDrawTbl = zelda_malloc(sizeof(*skelAnime->limbDrawTbl) * skelAnime->limbCount);
- skelAnime->transitionDrawTbl = zelda_malloc(sizeof(*skelAnime->transitionDrawTbl) * skelAnime->limbCount);
+ skelAnime->skeleton = Lib_SegmentedToVirtual(skeletonHeader->segment);
+ skelAnime->jointTable = ZeldaArena_Malloc(sizeof(*skelAnime->jointTable) * skelAnime->limbCount);
+ skelAnime->morphTable = ZeldaArena_Malloc(sizeof(*skelAnime->morphTable) * skelAnime->limbCount);
// Debug prints here, required to match.
if (1) {};
- if (animationSeg != NULL) {
- SkelAnime_ChangeAnimDefaultRepeat(skelAnime, animationSeg);
+ if (animation != NULL) {
+ Animation_PlayLoop(skelAnime, animation);
}
}
-void func_80136C84(SkelAnime* skelAnime) {
- if (skelAnime->mode < 2) {
- skelAnime->animUpdate = func_8013702C;
- } else if (skelAnime->mode < 4) {
- skelAnime->animUpdate = func_8013713C;
+/**
+ * Sets the SkelAnime's update function based on its current mode.
+ */
+void SkelAnime_SetUpdate(SkelAnime* skelAnime) {
+ if (skelAnime->mode <= ANIMMODE_LOOP_INTERP) {
+ skelAnime->update = SkelAnime_LoopFull;
+ } else if (skelAnime->mode <= ANIMMODE_ONCE_INTERP) {
+ skelAnime->update = SkelAnime_Once;
} else {
- skelAnime->animUpdate = func_801370B0;
+ skelAnime->update = SkelAnime_LoopPartial;
}
}
-s32 SkelAnime_FrameUpdateMatrix(SkelAnime* skelAnime) {
- return skelAnime->animUpdate(skelAnime);
+/**
+ * Advances the current animation and updates all frame tables. If the animation plays once, returns true when it
+ * finishes.
+ */
+s32 SkelAnime_Update(SkelAnime* skelAnime) {
+ return skelAnime->update(skelAnime);
}
-s32 func_80136CF4(SkelAnime* skelAnime) {
- f32 prevUnk28 = skelAnime->transCurrentFrame;
+/**
+ * Morphs from the pose in jointTable to the one in morphTable, advancing the morph but not the animation frame
+ */
+s32 SkelAnime_Morph(SkelAnime* skelAnime) {
+ f32 prevMorphWeight = skelAnime->morphWeight;
f32 updateRate = gFramerateDivisorThird;
- skelAnime->transCurrentFrame -= skelAnime->transitionStep * updateRate;
- if (skelAnime->transCurrentFrame <= 0.0f) {
- func_80136C84(skelAnime);
- skelAnime->transCurrentFrame = 0.0f;
+ skelAnime->morphWeight -= skelAnime->morphRate * updateRate;
+ if (skelAnime->morphWeight <= 0.0f) {
+ SkelAnime_SetUpdate(skelAnime);
+ skelAnime->morphWeight = 0.0f;
}
- SkelAnime_InterpolateVec3s(skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->limbDrawTbl,
- skelAnime->transitionDrawTbl, 1.0f - (skelAnime->transCurrentFrame / prevUnk28));
+ SkelAnime_InterpFrameTable(skelAnime->limbCount, skelAnime->jointTable, skelAnime->jointTable,
+ skelAnime->morphTable, 1.0f - (skelAnime->morphWeight / prevMorphWeight));
return 0;
}
-s32 func_80136D98(SkelAnime* skelAnime) {
- s16 temp_a2 = (s16)(skelAnime->transCurrentFrame * 16384.0f);
- s16 temp_a1;
- f32 sp28;
- f32 phi_f2;
+/**
+ * Performs a tapered morph from the pose in jointTable to the one in morphTable, advancing the morph but not the
+ * animation frame
+ */
+s32 SkelAnime_MorphTaper(SkelAnime* skelAnime) {
+ s16 prevPhase = skelAnime->morphWeight * 0x4000;
+ s16 curPhase;
+ f32 prevWeight;
+ f32 curWeight;
f32 updateRate = gFramerateDivisorThird;
- skelAnime->transCurrentFrame -= skelAnime->transitionStep * updateRate;
- if (skelAnime->transCurrentFrame <= 0.0f) {
- func_80136C84(skelAnime);
- skelAnime->transCurrentFrame = 0.0f;
+ skelAnime->morphWeight -= skelAnime->morphRate * updateRate;
+ if (skelAnime->morphWeight <= 0.0f) {
+ SkelAnime_SetUpdate(skelAnime);
+ skelAnime->morphWeight = 0.0f;
}
- temp_a1 = (s16)(skelAnime->transCurrentFrame * 16384.0f);
- if (skelAnime->unk03 < 0) {
- sp28 = 1.0f - Math_CosS(temp_a2);
- phi_f2 = 1.0f - Math_CosS(temp_a1);
+ curPhase = skelAnime->morphWeight * 0x4000;
+ if (skelAnime->taper < 0) {
+ prevWeight = 1.0f - Math_CosS(prevPhase);
+ curWeight = 1.0f - Math_CosS(curPhase);
} else {
- sp28 = Math_SinS(temp_a2);
- phi_f2 = Math_SinS(temp_a1);
+ prevWeight = Math_SinS(prevPhase);
+ curWeight = Math_SinS(curPhase);
}
- if (phi_f2 != 0.0f) {
- phi_f2 /= sp28;
+ if (curWeight != 0.0f) {
+ curWeight /= prevWeight;
} else {
- phi_f2 = 0.0f;
+ curWeight = 0.0f;
}
- SkelAnime_InterpolateVec3s(skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->limbDrawTbl,
- skelAnime->transitionDrawTbl, 1.0f - phi_f2);
+ SkelAnime_InterpFrameTable(skelAnime->limbCount, skelAnime->jointTable, skelAnime->jointTable,
+ skelAnime->morphTable, 1.0f - curWeight);
return 0;
}
-void func_80136F04(SkelAnime* skelAnime) {
- s32 t;
- s32 pad[2];
- Vec3s sp38[98];
- f32 temp_f10;
- f32 temp_f2;
-
- SkelAnime_AnimateFrame(skelAnime->animCurrentSeg, skelAnime->animCurrentFrame, skelAnime->limbCount,
- skelAnime->limbDrawTbl);
- if (skelAnime->mode & 0x1) {
- t = (s32)skelAnime->animCurrentFrame;
- temp_f10 = t;
- temp_f2 = skelAnime->animCurrentFrame - temp_f10;
- t++;
- if (t >= (s32)skelAnime->totalFrames) {
- t = 0;
+/**
+ * Gets frame data for the current frame as modified by morphTable and advances the morph
+ */
+void SkelAnime_AnimateFrame(SkelAnime* skelAnime) {
+ Vec3s nextjointTable[100];
+
+ SkelAnime_GetFrameData(skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, skelAnime->jointTable);
+ if (skelAnime->mode & ANIM_INTERP) {
+ s32 frame = skelAnime->curFrame;
+ f32 partialFrame = skelAnime->curFrame - frame;
+
+ if (++frame >= (s32)skelAnime->animLength) {
+ frame = 0;
}
- SkelAnime_AnimateFrame(skelAnime->animCurrentSeg, t, skelAnime->limbCount, sp38);
- SkelAnime_InterpolateVec3s(skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->limbDrawTbl, sp38, temp_f2);
+ SkelAnime_GetFrameData(skelAnime->animation, frame, skelAnime->limbCount, nextjointTable);
+ SkelAnime_InterpFrameTable(skelAnime->limbCount, skelAnime->jointTable, skelAnime->jointTable, nextjointTable,
+ partialFrame);
}
- if (skelAnime->transCurrentFrame != 0) {
+ if (skelAnime->morphWeight != 0) {
f32 updateRate = gFramerateDivisorThird;
- skelAnime->transCurrentFrame -= skelAnime->transitionStep * updateRate;
- if (skelAnime->transCurrentFrame <= 0.0f) {
- skelAnime->transCurrentFrame = 0.0f;
- return;
+
+ skelAnime->morphWeight -= skelAnime->morphRate * updateRate;
+ if (skelAnime->morphWeight <= 0.0f) {
+ skelAnime->morphWeight = 0.0f;
+ } else {
+ SkelAnime_InterpFrameTable(skelAnime->limbCount, skelAnime->jointTable, skelAnime->jointTable,
+ skelAnime->morphTable, skelAnime->morphWeight);
}
- SkelAnime_InterpolateVec3s(skelAnime->limbCount, skelAnime->limbDrawTbl, skelAnime->limbDrawTbl,
- skelAnime->transitionDrawTbl, skelAnime->transCurrentFrame);
}
}
-
-s32 func_8013702C(SkelAnime* skelAnime) {
+/**
+ * Advances an animation that loops over its full length and updates the frame tables
+ */
+s32 SkelAnime_LoopFull(SkelAnime* skelAnime) {
f32 updateRate = gFramerateDivisorThird;
- skelAnime->animCurrentFrame += skelAnime->animPlaybackSpeed * updateRate;
- if (skelAnime->animCurrentFrame < 0.0f) {
- skelAnime->animCurrentFrame += skelAnime->totalFrames;
- } else if (skelAnime->totalFrames <= skelAnime->animCurrentFrame) {
- skelAnime->animCurrentFrame -= skelAnime->totalFrames;
+ skelAnime->curFrame += skelAnime->playSpeed * updateRate;
+ if (skelAnime->curFrame < 0.0f) {
+ skelAnime->curFrame += skelAnime->animLength;
+ } else if (skelAnime->animLength <= skelAnime->curFrame) {
+ skelAnime->curFrame -= skelAnime->animLength;
}
- func_80136F04(skelAnime);
+ SkelAnime_AnimateFrame(skelAnime);
return 0;
}
-s32 func_801370B0(SkelAnime* skelAnime) {
+/**
+ * Advances an animation that loops over part of its length and updates the frame tables
+ */
+s32 SkelAnime_LoopPartial(SkelAnime* skelAnime) {
f32 updateRate = gFramerateDivisorThird;
- skelAnime->animCurrentFrame += skelAnime->animPlaybackSpeed * updateRate;
- if (skelAnime->animCurrentFrame < skelAnime->initialFrame) {
- skelAnime->animCurrentFrame =
- (skelAnime->animCurrentFrame - skelAnime->initialFrame) + skelAnime->animFrameCount;
- } else if (skelAnime->animFrameCount <= skelAnime->animCurrentFrame) {
- skelAnime->animCurrentFrame =
- (skelAnime->animCurrentFrame - skelAnime->animFrameCount) + skelAnime->initialFrame;
+ skelAnime->curFrame += skelAnime->playSpeed * updateRate;
+ if (skelAnime->curFrame < skelAnime->startFrame) {
+ skelAnime->curFrame = (skelAnime->curFrame - skelAnime->startFrame) + skelAnime->endFrame;
+ } else if (skelAnime->endFrame <= skelAnime->curFrame) {
+ skelAnime->curFrame = (skelAnime->curFrame - skelAnime->endFrame) + skelAnime->startFrame;
}
- func_80136F04(skelAnime);
+ SkelAnime_AnimateFrame(skelAnime);
return 0;
}
-s32 func_8013713C(SkelAnime* skelAnime) {
+/**
+ * Advances an animation that stops at endFrame and returns true when it is reached.
+ */
+s32 SkelAnime_Once(SkelAnime* skelAnime) {
f32 updateRate = gFramerateDivisorThird;
- if (skelAnime->animCurrentFrame == skelAnime->animFrameCount) {
- SkelAnime_AnimateFrame(skelAnime->animCurrentSeg, (s32)skelAnime->animCurrentFrame, skelAnime->limbCount,
- skelAnime->limbDrawTbl);
- func_80136F04(skelAnime);
+ if (skelAnime->curFrame == skelAnime->endFrame) {
+ SkelAnime_GetFrameData(skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, skelAnime->jointTable);
+ SkelAnime_AnimateFrame(skelAnime);
return 1;
}
- skelAnime->animCurrentFrame += skelAnime->animPlaybackSpeed * updateRate;
- if (((skelAnime->animCurrentFrame - skelAnime->animFrameCount) * skelAnime->animPlaybackSpeed) > 0.0f) {
- skelAnime->animCurrentFrame = skelAnime->animFrameCount;
+ skelAnime->curFrame += skelAnime->playSpeed * updateRate;
+ if (((skelAnime->curFrame - skelAnime->endFrame) * skelAnime->playSpeed) > 0.0f) {
+ skelAnime->curFrame = skelAnime->endFrame;
} else {
- if (skelAnime->animCurrentFrame < 0.0f) {
- skelAnime->animCurrentFrame += skelAnime->totalFrames;
+ if (skelAnime->curFrame < 0.0f) {
+ skelAnime->curFrame += skelAnime->animLength;
} else {
- if (skelAnime->totalFrames <= skelAnime->animCurrentFrame) {
- skelAnime->animCurrentFrame -= skelAnime->totalFrames;
+ if (skelAnime->animLength <= skelAnime->curFrame) {
+ skelAnime->curFrame -= skelAnime->animLength;
}
}
}
- func_80136F04(skelAnime);
+ SkelAnime_AnimateFrame(skelAnime);
return 0;
}
-void SkelAnime_ChangeAnimImpl(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 playbackSpeed, f32 frame,
- f32 frameCount, u8 animationType, f32 transitionRate, s8 unk2) {
- skelAnime->mode = animationType;
- if ((transitionRate != 0.0f) &&
- ((animationSeg != skelAnime->animCurrentSeg) || (frame != skelAnime->animCurrentFrame))) {
- if (transitionRate < 0) {
- func_80136C84(skelAnime);
- SkelAnime_CopyVec3s(skelAnime, skelAnime->transitionDrawTbl, skelAnime->limbDrawTbl);
- transitionRate = -transitionRate;
+/**
+ * Fully general way to set a new animation, allowing choice of playback speed, start frame, end frame, play mode,
+ * number of transition frames, and tapering of the transition. Positive morph frames morph from the current pose to the
+ * start pose of the new animation, then start the new animation. Negative morph frames start the new animation
+ * immediately, modified by the pose immediately before the animation change.
+ */
+void Animation_ChangeImpl(SkelAnime* skelAnime, AnimationHeader* animation, f32 playSpeed, f32 startFrame, f32 endFrame,
+ u8 mode, f32 morphFrames, s8 taper) {
+ skelAnime->mode = mode;
+ if ((morphFrames != 0.0f) && ((animation != skelAnime->animation) || (startFrame != skelAnime->curFrame))) {
+ if (morphFrames < 0) {
+ SkelAnime_SetUpdate(skelAnime);
+ SkelAnime_CopyFrameTable(skelAnime, skelAnime->morphTable, skelAnime->jointTable);
+ morphFrames = -morphFrames;
} else {
- if (unk2 != 0) {
- skelAnime->animUpdate = func_80136D98;
- skelAnime->unk03 = unk2;
+ if (taper != ANIMTAPER_NONE) {
+ skelAnime->update = SkelAnime_MorphTaper;
+ skelAnime->taper = taper;
} else {
- skelAnime->animUpdate = func_80136CF4;
+ skelAnime->update = SkelAnime_Morph;
}
- SkelAnime_AnimateFrame(animationSeg, frame, skelAnime->limbCount, skelAnime->transitionDrawTbl);
+ SkelAnime_GetFrameData(animation, startFrame, skelAnime->limbCount, skelAnime->morphTable);
}
- skelAnime->transCurrentFrame = 1.0f;
- skelAnime->transitionStep = 1.0f / transitionRate;
+ skelAnime->morphWeight = 1.0f;
+ skelAnime->morphRate = 1.0f / morphFrames;
} else {
- func_80136C84(skelAnime);
- SkelAnime_AnimateFrame(animationSeg, frame, skelAnime->limbCount, skelAnime->limbDrawTbl);
- skelAnime->transCurrentFrame = 0.0f;
+ SkelAnime_SetUpdate(skelAnime);
+ SkelAnime_GetFrameData(animation, startFrame, skelAnime->limbCount, skelAnime->jointTable);
+ skelAnime->morphWeight = 0.0f;
}
- skelAnime->animCurrentSeg = animationSeg;
- skelAnime->initialFrame = frame;
- skelAnime->animFrameCount = frameCount;
- skelAnime->totalFrames = SkelAnime_GetTotalFrames(&animationSeg->common);
- if (skelAnime->mode >= 4) {
- skelAnime->animCurrentFrame = 0.0f;
+ skelAnime->animation = animation;
+ skelAnime->startFrame = startFrame;
+ skelAnime->endFrame = endFrame;
+ skelAnime->animLength = Animation_GetLength(&animation->common);
+ if (skelAnime->mode >= ANIMMODE_LOOP_PARTIAL) {
+ skelAnime->curFrame = 0.0f;
} else {
- skelAnime->animCurrentFrame = frame;
- if (skelAnime->mode < 2) {
- skelAnime->animFrameCount = skelAnime->totalFrames - 1.0f;
+ skelAnime->curFrame = startFrame;
+ if (skelAnime->mode <= ANIMMODE_LOOP_INTERP) {
+ skelAnime->endFrame = skelAnime->animLength - 1.0f;
}
}
- skelAnime->animPlaybackSpeed = playbackSpeed;
+ skelAnime->playSpeed = playSpeed;
}
-void SkelAnime_ChangeAnim(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 playbackSpeed, f32 frame,
- f32 frameCount, u8 mode, f32 transitionRate) {
- SkelAnime_ChangeAnimImpl(skelAnime, animationSeg, playbackSpeed, frame, frameCount, mode, transitionRate, 0);
+/**
+ * General way to set a new animation, allowing choice of playback speed, start frame, end frame, play mode, and number
+ * of transition frames. Positive morph frames morph from the current pose to the start pose of the new animation, then
+ * start the new animation. Negative morph frames start the new animation immediately, modified by the pose immediately
+ * before the animation change.
+ */
+void Animation_Change(SkelAnime* skelAnime, AnimationHeader* animation, f32 playSpeed, f32 startFrame, f32 endFrame,
+ u8 mode, f32 morphFrames) {
+ Animation_ChangeImpl(skelAnime, animation, playSpeed, startFrame, endFrame, mode, morphFrames, ANIMTAPER_NONE);
}
-void SkelAnime_ChangeAnimDefaultStop(SkelAnime* skelAnime, AnimationHeader* animationSeg) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, 1.0f, 0.0f, SkelAnime_GetFrameCount(&animationSeg->common), 2, 0.0f);
+/**
+ * Immediately changes to an animation that plays once at the default speed.
+ */
+void Animation_PlayOnce(SkelAnime* skelAnime, AnimationHeader* animation) {
+ Animation_Change(skelAnime, animation, 1.0f, 0.0f, Animation_GetLastFrame(&animation->common), ANIMMODE_ONCE, 0.0f);
}
-void SkelAnime_ChangeAnimTransitionStop(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 transitionRate) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, 1.0f, 0, SkelAnime_GetFrameCount(&animationSeg->common), 2,
- transitionRate);
+/**
+ * Smoothly transitions to an animation that plays once at the default speed.
+ * Positive morph frames morph from the current pose to the start pose of the new animation, then start the new
+ * animation. Negative morph frames start the new animation immediately, modified by the pose immediately before the
+ * animation change.
+ */
+void Animation_MorphToPlayOnce(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 morphFrames) {
+ Animation_Change(skelAnime, animationSeg, 1.0f, 0, Animation_GetLastFrame(&animationSeg->common), ANIMMODE_ONCE,
+ morphFrames);
}
-void SkelAnime_ChangeAnimPlaybackStop(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 playbackSpeed) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, playbackSpeed, 0.0f, SkelAnime_GetFrameCount(&animationSeg->common),
- 2, 0.0f);
+/**
+ * Immediately changes to an animation that plays once at the specified speed.
+ */
+void Animation_PlayOnceSetSpeed(SkelAnime* skelAnime, AnimationHeader* animation, f32 playSpeed) {
+ Animation_Change(skelAnime, animation, playSpeed, 0.0f, Animation_GetLastFrame(&animation->common), ANIMMODE_ONCE,
+ 0.0f);
}
-void SkelAnime_ChangeAnimDefaultRepeat(SkelAnime* skelAnime, AnimationHeader* animationSeg) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, 1.0f, 0.0f, SkelAnime_GetFrameCount(&animationSeg->common), 0, 0.0f);
+/**
+ * Immediately changes to an animation that loops at the default.
+ */
+void Animation_PlayLoop(SkelAnime* skelAnime, AnimationHeader* animation) {
+ Animation_Change(skelAnime, animation, 1.0f, 0.0f, Animation_GetLastFrame(&animation->common), ANIMMODE_LOOP, 0.0f);
}
-void SkelAnime_ChangeAnimTransitionRepeat(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 transitionRate) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, 1.0f, 0.0f, 0.0f, 0, transitionRate);
+/**
+ * Smoothly transitions to a looping animation, specifying the number of frames for the transition.
+ * Positive morph frames morph from the current pose to the start pose of the new animation, then start the new
+ * animation. Negative morph frames start the new animation immediately, modified by the pose immediately before the
+ * animation change.
+ */
+void Animation_MorphToLoop(SkelAnime* skelAnime, AnimationHeader* animation, f32 morphFrames) {
+ Animation_Change(skelAnime, animation, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, morphFrames);
}
-void SkelAnime_ChangeAnimPlaybackRepeat(SkelAnime* skelAnime, AnimationHeader* animationSeg, f32 playbackSpeed) {
- SkelAnime_ChangeAnim(skelAnime, animationSeg, playbackSpeed, 0.0f, SkelAnime_GetFrameCount(&animationSeg->common),
- 0, 0.0f);
+/**
+ * Immediately changes to an animation that loops at the specified speed.
+ */
+void Animation_PlayLoopSetSpeed(SkelAnime* skelAnime, AnimationHeader* animation, f32 playbackSpeed) {
+ Animation_Change(skelAnime, animation, playbackSpeed, 0.0f, Animation_GetLastFrame(&animation->common),
+ ANIMMODE_LOOP, 0.0f);
}
-void SkelAnime_AnimSetStop(SkelAnime* skelAnime) {
- skelAnime->mode = 2;
- skelAnime->animFrameCount = skelAnime->totalFrames;
- func_80136C84(skelAnime);
+/**
+ * Changes a looping animation to one that stops at the end. Unused
+ */
+void Animation_EndLoop(SkelAnime* skelAnime) {
+ skelAnime->mode = ANIMMODE_ONCE;
+ skelAnime->endFrame = skelAnime->animLength;
+ SkelAnime_SetUpdate(skelAnime);
}
-void SkelAnime_AnimReverse(SkelAnime* skelAnime) {
- f32 initialFrame = skelAnime->initialFrame;
+/**
+ * Reverses the current animation.
+ */
+void Animation_Reverse(SkelAnime* skelAnime) {
+ f32 startFrame = skelAnime->startFrame;
- skelAnime->initialFrame = skelAnime->animFrameCount;
- skelAnime->animPlaybackSpeed = -skelAnime->animPlaybackSpeed;
- skelAnime->animFrameCount = initialFrame;
+ skelAnime->startFrame = skelAnime->endFrame;
+ skelAnime->playSpeed = -skelAnime->playSpeed;
+ skelAnime->endFrame = startFrame;
}
-void func_80137674(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src, u8* index) {
+/**
+ * Copies the src frame table to the dst frame table if copyFlag for that limb is true.
+ */
+void SkelAnime_CopyFrameTableTrue(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src, u8* copyFlag) {
s32 i;
for (i = 0; i < skelAnime->limbCount; i++, dst++, src++) {
- if (*index++) {
+ if (*copyFlag++) {
*dst = *src;
}
}
}
-void func_801376DC(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src, u8* arg3) {
+/**
+ * Copies the src frame table to the dst frame table if copyFlag for that limb is false.
+ */
+void SkelAnime_CopyFrameTableFalse(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src, u8* copyFlag) {
s32 i;
for (i = 0; i < skelAnime->limbCount; i++, dst++, src++) {
- if (*arg3++ < 1U) {
+ if (!*copyFlag++) {
*dst = *src;
}
}
}
-/*
- * Moves `pos` backwards on the xz plane from `angle`
+/**
+ * Updates translation of the root limb and calculates `pos`, the difference between
+ * the old and new positions of the root limb as rotated by `angle`. Used to allow
+ * animations to change an actor's position.
*/
-void func_80137748(SkelAnime* skelAnime, Vec3f* pos, s16 angle) {
+void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) {
f32 x;
f32 z;
f32 sin;
f32 cos;
- if (skelAnime->flags & 0x10) {
- pos->z = 0.0f;
- pos->x = 0.0f;
+ if (skelAnime->moveFlags & ANIM_FLAG_NOMOVE) {
+ diff->z = 0.0f;
+ diff->x = 0.0f;
} else {
// `angle` rotation around y axis.
- x = skelAnime->limbDrawTbl->x - skelAnime->prevFramePos.x;
- z = skelAnime->limbDrawTbl->z - skelAnime->prevFramePos.z;
+ x = skelAnime->jointTable->x - skelAnime->prevTransl.x;
+ z = skelAnime->jointTable->z - skelAnime->prevTransl.z;
sin = Math_SinS(angle);
cos = Math_CosS(angle);
- pos->x = x * cos + z * sin;
- pos->z = z * cos - x * sin;
+ diff->x = x * cos + z * sin;
+ diff->z = z * cos - x * sin;
}
- skelAnime->prevFramePos.x = skelAnime->limbDrawTbl->x;
- skelAnime->limbDrawTbl->x = skelAnime->unk3E.x;
- skelAnime->prevFramePos.z = skelAnime->limbDrawTbl->z;
- skelAnime->limbDrawTbl->z = skelAnime->unk3E.z;
- if (skelAnime->flags & ANIM_FLAG_UPDATEXZ) {
- if (skelAnime->flags & ANIM_FLAG_UPDATEY) {
- pos->y = 0.0f;
+ skelAnime->prevTransl.x = skelAnime->jointTable->x;
+ skelAnime->jointTable->x = skelAnime->baseTransl.x;
+ skelAnime->prevTransl.z = skelAnime->jointTable->z;
+ skelAnime->jointTable->z = skelAnime->baseTransl.z;
+ if (skelAnime->moveFlags & ANIM_FLAG_UPDATEY) {
+ if (skelAnime->moveFlags & ANIM_FLAG_NOMOVE) {
+ diff->y = 0.0f;
} else {
- pos->y = skelAnime->limbDrawTbl->y - skelAnime->prevFramePos.y;
+ diff->y = skelAnime->jointTable->y - skelAnime->prevTransl.y;
}
- skelAnime->prevFramePos.y = skelAnime->limbDrawTbl->y;
- skelAnime->limbDrawTbl->y = skelAnime->unk3E.y;
+ skelAnime->prevTransl.y = skelAnime->jointTable->y;
+ skelAnime->jointTable->y = skelAnime->baseTransl.y;
} else {
- pos->y = 0.0f;
- skelAnime->prevFramePos.y = skelAnime->limbDrawTbl->y;
+ diff->y = 0.0f;
+ skelAnime->prevTransl.y = skelAnime->jointTable->y;
}
- skelAnime->flags &= ~ANIM_FLAG_UPDATEY;
+ skelAnime->moveFlags &= ~ANIM_FLAG_NOMOVE;
}
-s32 func_801378B8(SkelAnime* skelAnime, f32 arg1) {
- return func_80136990(skelAnime, arg1, 1.0f);
+/**
+ * Checks if the current animation is at the specified frame
+ */
+s32 Animation_OnFrame(SkelAnime* skelAnime, f32 frame) {
+ return Animation_OnFrameImpl(skelAnime, frame, 1.0f);
}
+/**
+ * Frees the frame tables for a skelAnime with dynamically allocated tables.
+ */
void SkelAnime_Free(SkelAnime* skelAnime, GlobalContext* globalCtx) {
- if (skelAnime->limbDrawTbl != NULL) {
- zelda_free(skelAnime->limbDrawTbl);
+ if (skelAnime->jointTable != NULL) {
+ ZeldaArena_Free(skelAnime->jointTable);
}
- if (skelAnime->transitionDrawTbl != NULL) {
- zelda_free(skelAnime->transitionDrawTbl);
+ if (skelAnime->morphTable != NULL) {
+ ZeldaArena_Free(skelAnime->morphTable);
}
}
-void SkelAnime_CopyVec3s(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src) {
+/**
+ * Copies the src frame table to the dst frame table.
+ */
+void SkelAnime_CopyFrameTable(SkelAnime* skelAnime, Vec3s* dst, Vec3s* src) {
bcopy(src, dst, sizeof(Vec3s) * skelAnime->limbCount);
}
diff --git a/src/code/z_view.c b/src/code/z_view.c
index 034f045b1..c325fd563 100644
--- a/src/code/z_view.c
+++ b/src/code/z_view.c
@@ -237,7 +237,7 @@ s32 View_SetQuake(View* view, Vec3f rot, Vec3f scale, f32 speed) {
return 1;
}
-s32 View_StepQuake(View* view, RSPMatrix* matrix) {
+s32 View_StepQuake(View* view, Mtx* matrix) {
MtxF mf;
if (view->quakeSpeed == 0.0f) {
@@ -256,16 +256,16 @@ s32 View_StepQuake(View* view, RSPMatrix* matrix) {
view->currQuakeScale.z += ((view->quakeScale.z - view->currQuakeScale.z) * view->quakeSpeed);
}
- SysMatrix_FromRSPMatrix(matrix, &mf);
- SysMatrix_SetCurrentState(&mf);
- SysMatrix_RotateStateAroundXAxis(view->currQuakeRot.x);
- SysMatrix_InsertYRotation_f(view->currQuakeRot.y, 1);
- SysMatrix_InsertZRotation_f(view->currQuakeRot.z, 1);
- Matrix_Scale(view->currQuakeScale.x, view->currQuakeScale.y, view->currQuakeScale.z, 1);
- SysMatrix_InsertZRotation_f(-view->currQuakeRot.z, 1);
- SysMatrix_InsertYRotation_f(-view->currQuakeRot.y, 1);
- SysMatrix_RotateStateAroundXAxis(-view->currQuakeRot.x);
- SysMatrix_GetStateAsRSPMatrix(matrix);
+ Matrix_FromRSPMatrix(matrix, &mf);
+ Matrix_SetCurrentState(&mf);
+ Matrix_RotateStateAroundXAxis(view->currQuakeRot.x);
+ Matrix_InsertYRotation_f(view->currQuakeRot.y, 1);
+ Matrix_InsertZRotation_f(view->currQuakeRot.z, 1);
+ Matrix_Scale(view->currQuakeScale.x, view->currQuakeScale.y, view->currQuakeScale.z, MTXMODE_APPLY);
+ Matrix_InsertZRotation_f(-view->currQuakeRot.z, 1);
+ Matrix_InsertYRotation_f(-view->currQuakeRot.y, 1);
+ Matrix_RotateStateAroundXAxis(-view->currQuakeRot.x);
+ Matrix_ToMtx(matrix);
return 1;
}
@@ -310,7 +310,7 @@ s32 View_RenderToPerspectiveMatrix(View* view) {
guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale);
view->projection = *projection;
//! @bug: This cast of `projection` is invalid
- View_StepQuake(view, (RSPMatrix*)projection);
+ View_StepQuake(view, (Mtx*)projection);
gSPPerspNormalize(POLY_OPA_DISP++, view->normal);
gSPMatrix(POLY_OPA_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
diff --git a/src/code/z_vr_box.c b/src/code/z_vr_box.c
index 1fca4801d..9e949beac 100644
--- a/src/code/z_vr_box.c
+++ b/src/code/z_vr_box.c
@@ -35,9 +35,9 @@ void func_80143148(SkyboxContext* skyboxCtx, s32 arg1) {
}
}
-void func_801431E8(GameState* gamestate, SkyboxContext* skyboxCtx, s16 skyType) {
- GlobalContext* globalCtx = (GlobalContext*)gamestate;
- u32 size;
+void func_801431E8(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType) {
+ GlobalContext* globalCtx = (GlobalContext*)gameState;
+ size_t size;
void* offset;
s32 pad;
@@ -82,7 +82,7 @@ void func_801431E8(GameState* gamestate, SkyboxContext* skyboxCtx, s16 skyType)
}
void func_80143324(GlobalContext* globalCtx, SkyboxContext* skyboxCtx, s16 skyType) {
- u32 size;
+ size_t size;
if (1) {}
@@ -133,22 +133,22 @@ void func_80143324(GlobalContext* globalCtx, SkyboxContext* skyboxCtx, s16 skyTy
}
}
-void func_801434E4(GameState* gamestate, SkyboxContext* skyboxCtx, s16 skyType) {
+void func_801434E4(GameState* gameState, SkyboxContext* skyboxCtx, s16 skyType) {
skyboxCtx->skyboxShouldDraw = 0;
skyboxCtx->rotX = skyboxCtx->rotY = skyboxCtx->rotZ = 0.0f;
- func_801431E8(gamestate, skyboxCtx, skyType);
+ func_801431E8(gameState, skyboxCtx, skyType);
if (skyType != 0) {
- skyboxCtx->unk17C = THA_AllocEndAlign16(&gamestate->heap, 0x3840);
+ skyboxCtx->unk17C = THA_AllocEndAlign16(&gameState->heap, 0x3840);
if (skyType == 5) {
// Allocate enough space for the vertices for a 6 sided skybox (cube)
- skyboxCtx->roomVtx = THA_AllocEndAlign16(&gamestate->heap, sizeof(Vtx) * 32 * 6);
+ skyboxCtx->roomVtx = THA_AllocEndAlign16(&gameState->heap, sizeof(Vtx) * 32 * 6);
func_80143148(skyboxCtx, 6);
} else {
// Allocate enough space for the vertices for a 5 sided skybox (bottom is missing)
- skyboxCtx->roomVtx = THA_AllocEndAlign16(&gamestate->heap, sizeof(Vtx) * 32 * 5);
+ skyboxCtx->roomVtx = THA_AllocEndAlign16(&gameState->heap, sizeof(Vtx) * 32 * 5);
func_80143148(skyboxCtx, 5);
}
}