From 0d71c6c12f7fbffd32cdba0d8556be29e6ec77bf Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Tue, 21 May 2024 21:17:30 +1000 Subject: [PATCH] remove animation dma tables, and provide mods more access to mario animations (#47) This removes the old animation system which would create 16 copies of the animation table, so this should use less memory. Made m->animation->targetAnim always be a pointer to the actual animation in gMarioAnims, so mods can grab the pointer and reuse it. added get_mario_vanilla_animation to Lua, which lets a mod get any of mario's built in animations from its index. --- autogen/lua_definitions/functions.lua | 6 + data/dynos_mgr_anim.cpp | 6 +- docs/lua/functions.md | 1 + src/game/game_init.c | 6 - src/game/game_init.h | 1 - src/game/level_update.c | 4 +- src/game/mario.c | 160 ++++++-------------------- src/game/memory.c | 36 ++++-- src/game/memory.h | 2 +- src/menu/level_select_menu.c | 4 +- src/pc/lua/smlua_functions_autogen.c | 18 +++ src/pc/lua/utils/smlua_anim_utils.c | 16 +++ src/pc/lua/utils/smlua_anim_utils.h | 2 + 13 files changed, 114 insertions(+), 148 deletions(-) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index b9acd8cd..5c1cd580 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -8397,6 +8397,12 @@ function touch_coin_score_age(fileIndex, courseIndex) -- ... end +--- @param index integer +--- @return Animation +function get_mario_vanilla_animation(index) + -- ... +end + --- @param obj Object --- @return string function smlua_anim_util_get_current_animation_name(obj) diff --git a/data/dynos_mgr_anim.cpp b/data/dynos_mgr_anim.cpp index bbec9b7c..f409eba3 100644 --- a/data/dynos_mgr_anim.cpp +++ b/data/dynos_mgr_anim.cpp @@ -13,9 +13,9 @@ extern "C" { // Retrieve the current Mario's animation index static s32 RetrieveCurrentMarioAnimationIndex(u32 aPlayerIndex) { - struct MarioAnimDmaRelatedThing *_AnimDmaTable = gMarioStates[aPlayerIndex].animation->animDmaTable; - for (s32 i = 0; i != (s32) _AnimDmaTable->count; ++i) { - void *_AnimAddr = _AnimDmaTable->srcAddr + _AnimDmaTable->anim[i].offset; + static struct MarioAnimDmaRelatedThing *_MarioAnims = (struct MarioAnimDmaRelatedThing *) gMarioAnims; + for (s32 i = 0; i != (s32) _MarioAnims->count; ++i) { + void *_AnimAddr = gMarioAnims + _MarioAnims->anim[i].offset; if (_AnimAddr == gMarioStates[aPlayerIndex].animation->currentAnimAddr) { return i; } diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 75955e61..4728db8d 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1556,6 +1556,7 @@
- smlua_anim_utils.h + - [get_mario_vanilla_animation](functions-4.md#get_mario_vanilla_animation) - [smlua_anim_util_get_current_animation_name](functions-4.md#smlua_anim_util_get_current_animation_name) - [smlua_anim_util_set_animation](functions-4.md#smlua_anim_util_set_animation) diff --git a/src/game/game_init.c b/src/game/game_init.c index abc62de7..70b44f38 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -46,7 +46,6 @@ OSMesg D_80339CD4 = NULL; struct VblankHandler gGameVblankHandler = { 0 }; uintptr_t gPhysicalFrameBuffers[3] = { 0 }; uintptr_t gPhysicalZBuffer = 0; -void *D_80339CF0[MAX_PLAYERS] = { 0 }; void *gDemoTargetAnim = NULL; struct MarioAnimation D_80339D10[MAX_PLAYERS] = { 0 }; struct MarioAnimation gDemo = { 0 }; @@ -555,11 +554,6 @@ void setup_game_memory(void) { gPhysicalFrameBuffers[0] = VIRTUAL_TO_PHYSICAL(gFrameBuffer0); gPhysicalFrameBuffers[1] = VIRTUAL_TO_PHYSICAL(gFrameBuffer1); gPhysicalFrameBuffers[2] = VIRTUAL_TO_PHYSICAL(gFrameBuffer2); - for (s32 i = 0; i < MAX_PLAYERS; i++) { - D_80339CF0[i] = calloc(1, 0x4000); - set_segment_base_addr(17, (void *)D_80339CF0[i]); - alloc_anim_dma_table(&D_80339D10[i], gMarioAnims, D_80339CF0[i]); - } gDemoTargetAnim = calloc(1, 2048); set_segment_base_addr(24, (void *) gDemoTargetAnim); alloc_anim_dma_table(&gDemo, gDemoInputs, gDemoTargetAnim); diff --git a/src/game/game_init.h b/src/game/game_init.h index 63f3e65f..86710b1e 100644 --- a/src/game/game_init.h +++ b/src/game/game_init.h @@ -32,7 +32,6 @@ extern OSMesg D_80339CD4; extern struct VblankHandler gGameVblankHandler; extern uintptr_t gPhysicalFrameBuffers[3]; extern uintptr_t gPhysicalZBuffer; -extern void *D_80339CF0[MAX_PLAYERS]; extern void *gDemoTargetAnim; extern struct SPTask *gGfxSPTask; extern Gfx *gDisplayListHead; diff --git a/src/game/level_update.c b/src/game/level_update.c index 25815080..3a326401 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -842,7 +842,7 @@ void verify_warp(struct MarioState *m, bool killMario) { dynos_warp_to_start_level(); return; } - + if (!killMario) { sSourceWarpNodeId = WARP_NODE_DEATH; return; @@ -1223,7 +1223,7 @@ static void start_demo(void) { if (sDemoNumber <= 6 && sDemoNumber > -1) { gCurrDemoInput = NULL; alloc_anim_dma_table(&gDemo, gDemoInputs, gDemoTargetAnim); - load_patchable_table(&gDemo, sDemoNumber); + load_patchable_table(&gDemo, sDemoNumber, false); gCurrDemoInput = ((struct DemoInput *) gDemo.targetAnim); } else { gIsDemoActive = false; diff --git a/src/game/mario.c b/src/game/mario.c index b1d7cbb0..2e49f535 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -78,75 +78,50 @@ s32 is_anim_past_end(struct MarioState *m) { return o->header.gfx.animInfo.animFrame >= (o->header.gfx.animInfo.curAnim->loopEnd - 2); } +static s16 mario_set_animation_internal(struct MarioState *m, s32 targetAnimID, s32 accel) { + if (!m) { return 0; } + struct Object *o = m->marioObj; + if (!o || !m->animation) { return 0; } + + load_patchable_table(m->animation, targetAnimID, true); + if (!m->animation->targetAnim) { return 0; } + + if (o->header.gfx.animInfo.animID != targetAnimID) { + struct Animation *targetAnim = m->animation->targetAnim; + o->header.gfx.animInfo.animID = targetAnimID; + o->header.gfx.animInfo.curAnim = targetAnim; + o->header.gfx.animInfo.animYTrans = m->unkB0; + + if (targetAnim->flags & ANIM_FLAG_2) { + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10); + } else { + if (targetAnim->flags & ANIM_FLAG_FORWARD) { + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) + accel; + } else { + o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) - accel; + } + } + + o->header.gfx.animInfo.animFrame = (o->header.gfx.animInfo.animFrameAccelAssist >> 0x10); + } + + o->header.gfx.animInfo.animAccel = accel; + + return o->header.gfx.animInfo.animFrame; +} + /** * Sets Mario's animation without any acceleration, running at its default rate. */ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) { - if (!m) { return 0; } - struct Object *o = m->marioObj; - if (!o || !m->animation) { return 0; } - struct Animation *targetAnim = m->animation->targetAnim; - if (!targetAnim) { return 0; } - - if (load_patchable_table(m->animation, targetAnimID)) { - targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); - targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); - } - - if (o->header.gfx.animInfo.animID != targetAnimID) { - o->header.gfx.animInfo.animID = targetAnimID; - o->header.gfx.animInfo.curAnim = targetAnim; - o->header.gfx.animInfo.animAccel = 0; - o->header.gfx.animInfo.animYTrans = m->unkB0; - - if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame; - } else { - if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame + 1; - } else { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame - 1; - } - } - } - - return o->header.gfx.animInfo.animFrame; + return mario_set_animation_internal(m, targetAnimID, 0x10000); } /** * Sets the character specific animation without any acceleration, running at its default rate. */ s16 set_character_animation(struct MarioState *m, s32 targetAnimID) { - if (!m) { return 0; } - struct Object *o = m->marioObj; - if (!o || !m->animation) { return 0; } - struct Animation *targetAnim = m->animation->targetAnim; - s32 charAnimID = get_character_anim(m, targetAnimID); - if (!targetAnim) { return 0; } - - if (load_patchable_table(m->animation, charAnimID)) { - targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); - targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); - } - - if (o->header.gfx.animInfo.animID != charAnimID) { - o->header.gfx.animInfo.animID = charAnimID; - o->header.gfx.animInfo.curAnim = targetAnim; - o->header.gfx.animInfo.animAccel = 0; - o->header.gfx.animInfo.animYTrans = m->unkB0; - - if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame; - } else { - if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame + 1; - } else { - o->header.gfx.animInfo.animFrame = targetAnim->startFrame - 1; - } - } - } - - return o->header.gfx.animInfo.animFrame; + return mario_set_animation_internal(m, get_character_anim(m, targetAnimID), 0x10000); } /** @@ -154,38 +129,7 @@ s16 set_character_animation(struct MarioState *m, s32 targetAnimID) { * slowed down via acceleration. */ s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) { - if (!m) { return 0; } - struct Object *o = m->marioObj; - if (!o || !m->animation) { return 0; } - struct Animation *targetAnim = m->animation->targetAnim; - if (!targetAnim) { return 0; } - - if (load_patchable_table(m->animation, targetAnimID)) { - targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); - targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); - } - - if (o->header.gfx.animInfo.animID != targetAnimID) { - o->header.gfx.animInfo.animID = targetAnimID; - o->header.gfx.animInfo.curAnim = targetAnim; - o->header.gfx.animInfo.animYTrans = m->unkB0; - - if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10); - } else { - if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) + accel; - } else { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) - accel; - } - } - - o->header.gfx.animInfo.animFrame = (o->header.gfx.animInfo.animFrameAccelAssist >> 0x10); - } - - o->header.gfx.animInfo.animAccel = accel; - - return o->header.gfx.animInfo.animFrame; + return mario_set_animation_internal(m, targetAnimID, accel); } /** @@ -193,39 +137,7 @@ s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) * slowed down via acceleration. */ s16 set_character_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) { - if (!m) { return 0; } - struct Object *o = m->marioObj; - if (!o || !m->animation) { return 0; } - struct Animation *targetAnim = m->animation->targetAnim; - if (!targetAnim) { return 0; } - s32 charAnimID = get_character_anim(m, targetAnimID); - - if (load_patchable_table(m->animation, charAnimID)) { - targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); - targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->index); - } - - if (o->header.gfx.animInfo.animID != charAnimID) { - o->header.gfx.animInfo.animID = charAnimID; - o->header.gfx.animInfo.curAnim = targetAnim; - o->header.gfx.animInfo.animYTrans = m->unkB0; - - if (targetAnim->flags & ANIM_FLAG_2) { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10); - } else { - if (targetAnim->flags & ANIM_FLAG_FORWARD) { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) + accel; - } else { - o->header.gfx.animInfo.animFrameAccelAssist = (targetAnim->startFrame << 0x10) - accel; - } - } - - o->header.gfx.animInfo.animFrame = (o->header.gfx.animInfo.animFrameAccelAssist >> 0x10); - } - - o->header.gfx.animInfo.animAccel = accel; - - return o->header.gfx.animInfo.animFrame; + return mario_set_animation_internal(m, get_character_anim(m, targetAnimID), accel); } /** diff --git a/src/game/memory.c b/src/game/memory.c index 0d4bec3f..a4da7b70 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -298,19 +298,37 @@ void alloc_anim_dma_table(struct MarioAnimation* marioAnim, void* srcAddr, struc marioAnim->targetAnim = targetAnim; } -s32 load_patchable_table(struct MarioAnimation *a, u32 index) { - struct MarioAnimDmaRelatedThing *sp20 = a->animDmaTable; +s32 load_patchable_table(struct MarioAnimation *a, u32 index, bool isAnim) { + if (isAnim) { + static struct MarioAnimDmaRelatedThing *marioAnims = (struct MarioAnimDmaRelatedThing *) gMarioAnims; + if (index < marioAnims->count) { + u8* addr = gMarioAnims + marioAnims->anim[index].offset; - if (index < sp20->count) { - u8* addr = sp20->srcAddr + sp20->anim[index].offset; - u32 size = sp20->anim[index].size; + if (a->currentAnimAddr != addr) { + a->targetAnim = (struct Animation *) addr; + a->currentAnimAddr = addr; - if (a->targetAnim && a->currentAnimAddr != addr) { - memcpy(a->targetAnim, addr, size); - a->currentAnimAddr = addr; - return TRUE; + if ((uintptr_t) a->targetAnim->values < (uintptr_t) a->targetAnim) { + a->targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) a->targetAnim + (uintptr_t) a->targetAnim->values); + } + if ((uintptr_t) a->targetAnim->index < (uintptr_t) a->targetAnim) { + a->targetAnim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) a->targetAnim + (uintptr_t) a->targetAnim->index); + } + } } + } else { + struct MarioAnimDmaRelatedThing *sp20 = a->animDmaTable; + if (index < sp20->count) { + u8* addr = sp20->srcAddr + sp20->anim[index].offset; + u32 size = sp20->anim[index].size; + if (a->targetAnim && a->currentAnimAddr != addr) { + memcpy(a->targetAnim, addr, size); + a->currentAnimAddr = addr; + return TRUE; + } + } } + return FALSE; } diff --git a/src/game/memory.h b/src/game/memory.h index 8c964c82..ceec091f 100644 --- a/src/game/memory.h +++ b/src/game/memory.h @@ -79,6 +79,6 @@ void alloc_display_list_reset(void); void *alloc_display_list(u32 size); void alloc_anim_dma_table(struct MarioAnimation* marioAnim, void *b, struct Animation *targetAnim); -s32 load_patchable_table(struct MarioAnimation *a, u32 b); +s32 load_patchable_table(struct MarioAnimation *a, u32 b, bool isAnim); #endif // MEMORY_H diff --git a/src/menu/level_select_menu.c b/src/menu/level_select_menu.c index c4182e96..ef26e091 100644 --- a/src/menu/level_select_menu.c +++ b/src/menu/level_select_menu.c @@ -62,7 +62,7 @@ s32 run_press_start_demo_timer(s32 timer) { // player is idle on PRESS START screen. // start the Mario demo animation for the demo list. - load_patchable_table(&gDemo, gDemoInputListID); + load_patchable_table(&gDemo, gDemoInputListID, false); // if the next demo sequence ID is the count limit, reset it back to // the first sequence. @@ -193,7 +193,7 @@ s32 intro_default(void) { func_sh_8024C89C(1); #endif sp1C = 100 + gDebugLevelSelect; -#ifndef VERSION_JP +#ifndef VERSION_JP D_U_801A7C34 = 1; #endif } diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 611697ad..93e6d265 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -27843,6 +27843,23 @@ int smlua_func_touch_coin_score_age(lua_State* L) { // smlua_anim_utils.h // //////////////////////// +int smlua_func_get_mario_vanilla_animation(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "get_mario_vanilla_animation", 1, top); + return 0; + } + + u16 index = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "get_mario_vanilla_animation"); return 0; } + + smlua_push_object(L, LOT_ANIMATION, get_mario_vanilla_animation(index)); + + return 1; +} + int smlua_func_smlua_anim_util_get_current_animation_name(lua_State* L) { if (L == NULL) { return 0; } @@ -33801,6 +33818,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "touch_coin_score_age", smlua_func_touch_coin_score_age); // smlua_anim_utils.h + smlua_bind_function(L, "get_mario_vanilla_animation", smlua_func_get_mario_vanilla_animation); smlua_bind_function(L, "smlua_anim_util_get_current_animation_name", smlua_func_smlua_anim_util_get_current_animation_name); smlua_bind_function(L, "smlua_anim_util_set_animation", smlua_func_smlua_anim_util_set_animation); diff --git a/src/pc/lua/utils/smlua_anim_utils.c b/src/pc/lua/utils/smlua_anim_utils.c index 34b6711a..84a09fbc 100644 --- a/src/pc/lua/utils/smlua_anim_utils.c +++ b/src/pc/lua/utils/smlua_anim_utils.c @@ -88,6 +88,22 @@ struct GlobalObjectAnimations gGlobalObjectAnimations = { .yoshi_seg5_anims_05024100 = (struct AnimationTable*) &yoshi_seg5_anims_05024100, }; +struct Animation *get_mario_vanilla_animation(u16 index) { + static struct MarioAnimDmaRelatedThing *marioAnims = (struct MarioAnimDmaRelatedThing *) gMarioAnims; + + if (index < marioAnims->count) { + struct Animation* anim = (struct Animation*) (gMarioAnims + marioAnims->anim[index].offset); + if ((uintptr_t) anim->values < (uintptr_t) anim) { + anim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) anim + (uintptr_t) anim->values); + } + if ((uintptr_t) anim->index < (uintptr_t) anim) { + anim->index = (void *) VIRTUAL_TO_PHYSICAL((u8 *) anim + (uintptr_t) anim->index); + } + return anim; + } + return NULL; +} + /////////////////////// // custom animations // /////////////////////// diff --git a/src/pc/lua/utils/smlua_anim_utils.h b/src/pc/lua/utils/smlua_anim_utils.h index 3d668675..9d757e55 100644 --- a/src/pc/lua/utils/smlua_anim_utils.h +++ b/src/pc/lua/utils/smlua_anim_utils.h @@ -66,6 +66,8 @@ struct GlobalObjectAnimations { extern struct GlobalObjectAnimations gGlobalObjectAnimations; +struct Animation *get_mario_vanilla_animation(u16 index); + void smlua_anim_util_reset(); void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, u16 *values, u32 valuesLength, u16 *index, u32 indexLength); void smlua_anim_util_set_animation(struct Object *obj, const char *name);