mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-12-22 00:10:25 +00:00
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:
parent
bb34e9f501
commit
0d71c6c12f
13 changed files with 114 additions and 148 deletions
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
160
src/game/mario.c
160
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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 //
|
||||
///////////////////////
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue