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.
This commit is contained in:
Isaac0-dev 2024-05-21 21:17:30 +10:00 committed by GitHub
parent bb34e9f501
commit 0d71c6c12f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 114 additions and 148 deletions

View File

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

View File

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

View File

@ -1556,6 +1556,7 @@
<br />
- 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)

View File

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

View File

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

View File

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

View File

@ -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);
}
/**

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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