From 460d1aafb48c5c8f198f9010e71a5262c1d6692f Mon Sep 17 00:00:00 2001 From: Mr-Wiseguy Date: Sat, 6 Apr 2024 00:34:10 -0400 Subject: [PATCH] Added patches for skipping interpolation when actors get teleported in cutscenes --- CMakeLists.txt | 2 + patches/actor_transform_tagging.c | 15 +- patches/cutscene_patches.c | 137 +++++++++++ .../objects/gameplay_keep/gameplay_keep.h | 0 .../objects/object_ha/object_ha.h | 221 ++++++++++++++++++ patches/save_patches.c | 1 - patches/specific_actor_transform_tagging.c | 45 +++- patches/syms.ld | 2 + patches/transform_ids.h | 15 +- 9 files changed, 432 insertions(+), 6 deletions(-) create mode 100644 patches/cutscene_patches.c create mode 100644 patches/dummy_headers/objects/gameplay_keep/gameplay_keep.h create mode 100644 patches/dummy_headers/objects/object_ha/object_ha.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 04972c3..c298cf4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_CXX_EXTENSIONS OFF) # set(CMAKE_CXX_VISIBILITY_PRESET hidden) +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-everything -Wall -Wextra") + # Avoid warning about DOWNLOAD_EXTRACT_TIMESTAMP in CMake 3.24: if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.24.0") cmake_policy(SET CMP0135 NEW) diff --git a/patches/actor_transform_tagging.c b/patches/actor_transform_tagging.c index 81b42d4..d379f53 100644 --- a/patches/actor_transform_tagging.c +++ b/patches/actor_transform_tagging.c @@ -1164,6 +1164,7 @@ void tag_actor_displaylists(Actor* actor, PlayState* play, Gfx* opa_start, Gfx* // Scan the commands written by the actor to see how many matrices were added. s32 opa_matrices = scan_for_matrices(opa_start, POLY_OPA_DISP); s32 xlu_matrices = scan_for_matrices(xlu_start, POLY_XLU_DISP); + bool skipped = actor_get_interpolation_skipped(actor); // If the actor wrote at least one matrix in total and at most one matrix to each list, tag that matrix with the actor's id. if ((opa_matrices == 1 || xlu_matrices == 1) && opa_matrices <= 1 && xlu_matrices <= 1) { @@ -1171,7 +1172,12 @@ void tag_actor_displaylists(Actor* actor, PlayState* play, Gfx* opa_start, Gfx* if (opa_matrices == 1) { // Fill in the slot that was reserved for a transform id. - gEXMatrixGroupDecomposedNormal(opa_start, cur_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + if (skipped) { + gEXMatrixGroupDecomposedSkipPosRot(opa_start, cur_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } + else { + gEXMatrixGroupDecomposedNormal(opa_start, cur_transform_id, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } // Pop the matrix group. gEXPopMatrixGroup(POLY_OPA_DISP++, G_MTX_MODELVIEW); @@ -1179,7 +1185,12 @@ void tag_actor_displaylists(Actor* actor, PlayState* play, Gfx* opa_start, Gfx* if (xlu_matrices == 1) { // Fill in the slot that was reserved for a transform id. - gEXMatrixGroupDecomposedNormal(xlu_start, cur_transform_id + 1, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + if (skipped) { + gEXMatrixGroupDecomposedSkipPosRot(xlu_start, cur_transform_id + 1, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } + else { + gEXMatrixGroupDecomposedNormal(xlu_start, cur_transform_id + 1, G_EX_PUSH, G_MTX_MODELVIEW, G_EX_EDIT_ALLOW); + } // Pop the matrix groups. gEXPopMatrixGroup(POLY_XLU_DISP++, G_MTX_MODELVIEW); diff --git a/patches/cutscene_patches.c b/patches/cutscene_patches.c new file mode 100644 index 0000000..2bbefaa --- /dev/null +++ b/patches/cutscene_patches.c @@ -0,0 +1,137 @@ +#include "patches.h" +#include "transform_ids.h" +#include "overlays/actors/ovl_En_Horse/z_en_horse.h" + +#define CUE_DIST_THRESHOLD 10.0f + +CsCmdActorCue* prev_cues_checked[ARRAY_COUNT(((CutsceneContext*)0)->actorCues)] = {0}; + +void Cutscene_ActorTranslate(Actor* actor, PlayState* play, s32 cueChannel) { + Vec3f startPos; + Vec3f endPos; + CsCmdActorCue* cue = play->csCtx.actorCues[cueChannel]; + f32 lerp; + + startPos.x = cue->startPos.x; + startPos.y = cue->startPos.y; + startPos.z = cue->startPos.z; + endPos.x = cue->endPos.x; + endPos.y = cue->endPos.y; + endPos.z = cue->endPos.z; + + lerp = Environment_LerpWeight(cue->endFrame, cue->startFrame, play->csCtx.curFrame); + + // @recomp Check if this is a new cue for a given channel. + if (prev_cues_checked[cueChannel] != cue) { + // New cue, so check if the start position of this cue is significantly different than the actor's current position. + if (Math3D_Distance(&startPos, &actor->world.pos) > CUE_DIST_THRESHOLD) { + // The actor is probably being teleported, so skip interpolation for them this frame. + actor_set_interpolation_skipped(actor); + } + } + // @recomp Update tracking for this channel's most recent cue. + prev_cues_checked[cueChannel] = cue; + + VEC3F_LERPIMPDST(&actor->world.pos, &startPos, &endPos, lerp); +} + +extern EnHorseCsFunc D_808890F0[]; +extern EnHorseCsFunc D_8088911C[]; + +// @recomp Patched to skip interpolation on Epona when she's teleported by a cutscene. +void func_80884718(EnHorse* this, PlayState* play) { + CsCmdActorCue* cue; + + if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_112)) { + this->cueChannel = Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_112); + cue = play->csCtx.actorCues[this->cueChannel]; + + this->unk_1EC |= 0x20; + if (this->cueId != cue->id) { + if (this->cueId == -1) { + // @recomp Being teleported by a new cue, so skip interpolation. + actor_set_interpolation_skipped(&this->actor); + + this->actor.world.pos.x = cue->startPos.x; + this->actor.world.pos.y = cue->startPos.y; + this->actor.world.pos.z = cue->startPos.z; + + this->actor.world.rot.y = cue->rot.y; + this->actor.shape.rot = this->actor.world.rot; + + this->actor.prevPos = this->actor.world.pos; + } + + this->cueId = cue->id; + // @recomp Manual relocation, TODO remove when automated. + EnHorseCsFunc* D_808890F0_reloc = actor_relocate(&this->actor, D_808890F0); + if (D_808890F0_reloc[this->cueId] != NULL) { + D_808890F0_reloc[this->cueId](this, play, cue); + } + } + + // @recomp Manual relocation, TODO remove when automated. + EnHorseCsFunc* D_8088911C_reloc = actor_relocate(&this->actor, D_8088911C); + if (D_8088911C_reloc[this->cueId] != NULL) { + D_8088911C_reloc[this->cueId](this, play, cue); + } + } +} + +// @recomp Patched to skip interpolation on Epona when she's teleported by a cutscene. +void func_80883B70(EnHorse* this, CsCmdActorCue* cue) { + // @recomp Being teleported by a new cue, so skip interpolation. + actor_set_interpolation_skipped(&this->actor); + + this->actor.world.pos.x = cue->startPos.x; + this->actor.world.pos.y = cue->startPos.y; + this->actor.world.pos.z = cue->startPos.z; + + this->actor.world.rot.y = cue->rot.y; + this->actor.shape.rot = this->actor.world.rot; + + this->actor.prevPos = this->actor.world.pos; +} + +// @recomp Patched to skip interpolation on Link when he's teleported to a new cue. +void Player_Cutscene_SetPosAndYawToStart(Player* this, CsCmdActorCue* cue) { + // @recomp Being teleported by a new cue, so skip interpolation. + actor_set_interpolation_skipped(&this->actor); + + this->actor.world.pos.x = cue->startPos.x; + this->actor.world.pos.y = cue->startPos.y; + this->actor.world.pos.z = cue->startPos.z; + + this->currentYaw = this->actor.shape.rot.y = cue->rot.y; +} + +CsCmdActorCue* prev_link_cue = NULL; + +// @recomp Patched to skip interpolation on Link when he's teleported to a new cue. +void Player_Cutscene_Translate(PlayState* play, Player* this, CsCmdActorCue* cue) { + f32 startX = cue->startPos.x; + f32 startY = cue->startPos.y; + f32 startZ = cue->startPos.z; + f32 diffX = cue->endPos.x - startX; + f32 diffY = cue->endPos.y - startY; + f32 diffZ = cue->endPos.z - startZ; + f32 progress = (((f32)(play->csCtx.curFrame - cue->startFrame)) / ((f32)(cue->endFrame - cue->startFrame))); + + // @recomp Check if this is a new cue for a given channel. + if (prev_link_cue != cue) { + // New cue, so check if the start position of this cue is significantly different than the actor's current position. + Vec3f start_pos; + start_pos.x = startX; + start_pos.y = startY; + start_pos.z = startZ; + if (Math3D_Distance(&start_pos, &this->actor.world.pos) > CUE_DIST_THRESHOLD) { + // The actor is probably being teleported, so skip interpolation for them this frame. + actor_set_interpolation_skipped(&this->actor); + } + } + prev_link_cue = cue; + + this->actor.world.pos.x = (diffX * progress) + startX; + this->actor.world.pos.y = (diffY * progress) + startY; + this->actor.world.pos.z = (diffZ * progress) + startZ; +} diff --git a/patches/dummy_headers/objects/gameplay_keep/gameplay_keep.h b/patches/dummy_headers/objects/gameplay_keep/gameplay_keep.h new file mode 100644 index 0000000..e69de29 diff --git a/patches/dummy_headers/objects/object_ha/object_ha.h b/patches/dummy_headers/objects/object_ha/object_ha.h new file mode 100644 index 0000000..37a1ec3 --- /dev/null +++ b/patches/dummy_headers/objects/object_ha/object_ha.h @@ -0,0 +1,221 @@ +// Required to include MM decomp headers without having built the repo + +#ifndef OBJECT_HA_H +#define OBJECT_HA_H 1 + +typedef enum DonkeyBanditLimb { + /* 0x00 */ HORSE_BANDIT_LIMB_NONE, + /* 0x01 */ HORSE_BANDIT_LIMB_ROOT, + /* 0x02 */ HORSE_BANDIT_LIMB_PELVIS, + /* 0x03 */ HORSE_BANDIT_LIMB_TORSO, + /* 0x04 */ HORSE_BANDIT_LIMB_LEFT_FRONT_LEG_ROOT, + /* 0x05 */ HORSE_BANDIT_LIMB_LEFT_FRONT_FOREARM, + /* 0x06 */ HORSE_BANDIT_LIMB_LEFT_FRONT_CANNON, + /* 0x07 */ HORSE_BANDIT_LIMB_LEFT_FRONT_FOOT, + /* 0x08 */ HORSE_BANDIT_LIMB_LOWER_NECK, + /* 0x09 */ HORSE_BANDIT_LIMB_UPPER_NECK, + /* 0x0A */ HORSE_BANDIT_LIMB_HEAD, + /* 0x0B */ HORSE_BANDIT_LIMB_RIGHT_FRONT_LEG_ROOT, + /* 0x0C */ HORSE_BANDIT_LIMB_RIGHT_FRONT_FOREARM, + /* 0x0D */ HORSE_BANDIT_LIMB_RIGHT_FRONT_CANNON, + /* 0x0E */ HORSE_BANDIT_LIMB_RIGHT_FRONT_FOOT, + /* 0x0F */ HORSE_BANDIT_LIMB_TAIL_DOCK, + /* 0x10 */ HORSE_BANDIT_LIMB_TAIL_MIDDLE, + /* 0x11 */ HORSE_BANDIT_LIMB_TAIL_END, + /* 0x12 */ HORSE_BANDIT_LIMB_LEFT_HIND_THIGH, + /* 0x13 */ HORSE_BANDIT_LIMB_LEFT_HIND_STIFLE, + /* 0x14 */ HORSE_BANDIT_LIMB_LEFT_HIND_CANNON, + /* 0x15 */ HORSE_BANDIT_LIMB_LEFT_HIND_FOOT, + /* 0x16 */ HORSE_BANDIT_LIMB_RIGHT_HIND_THIGH, + /* 0x17 */ HORSE_BANDIT_LIMB_RIGHT_HIND_STIFLE, + /* 0x18 */ HORSE_BANDIT_LIMB_RIGHT_HIND_CANNON, + /* 0x19 */ HORSE_BANDIT_LIMB_RIGHT_HIND_FOOT, + /* 0x1A */ HORSE_BANDIT_LIMB_MAX +} DonkeyBanditLimb; + +typedef enum DonkeyLimb { + /* 0x00 */ DONKEY_LIMB_NONE, + /* 0x01 */ DONKEY_LIMB_ROOT, + /* 0x02 */ DONKEY_LIMB_PELVIS, + /* 0x03 */ DONKEY_LIMB_TORSO, + /* 0x04 */ DONKEY_LIMB_LEFT_FRONT_LEG_ROOT, + /* 0x05 */ DONKEY_LIMB_LEFT_FRONT_FOREARM, + /* 0x06 */ DONKEY_LIMB_LEFT_FRONT_CANNON, + /* 0x07 */ DONKEY_LIMB_LEFT_FRONT_FOOT, + /* 0x08 */ DONKEY_LIMB_LOWER_NECK, + /* 0x09 */ DONKEY_LIMB_UPPER_NECK, + /* 0x0A */ DONKEY_LIMB_HEAD, + /* 0x0B */ DONKEY_LIMB_RIGHT_FRONT_LEG_ROOT, + /* 0x0C */ DONKEY_LIMB_RIGHT_FRONT_FOREARM, + /* 0x0D */ DONKEY_LIMB_RIGHT_FRONT_CANNON, + /* 0x0E */ DONKEY_LIMB_RIGHT_FRONT_FOOT, + /* 0x0F */ DONKEY_LIMB_TAIL_DOCK, + /* 0x10 */ DONKEY_LIMB_TAIL_MIDDLE, + /* 0x11 */ DONKEY_LIMB_TAIL_END, + /* 0x12 */ DONKEY_LIMB_LEFT_HIND_THIGH, + /* 0x13 */ DONKEY_LIMB_LEFT_HIND_STIFLE, + /* 0x14 */ DONKEY_LIMB_LEFT_HIND_CANNON, + /* 0x15 */ DONKEY_LIMB_LEFT_HIND_FOOT, + /* 0x16 */ DONKEY_LIMB_RIGHT_HIND_THIGH, + /* 0x17 */ DONKEY_LIMB_RIGHT_HIND_STIFLE, + /* 0x18 */ DONKEY_LIMB_RIGHT_HIND_CANNON, + /* 0x19 */ DONKEY_LIMB_RIGHT_HIND_FOOT, + /* 0x1A */ DONKEY_LIMB_MAX +} DonkeyLimb; + +extern s16 sHorseUnusedAnimFrameData[]; +extern JointIndex sHorseUnusedAnimJointIndices[]; +extern AnimationHeader gHorseUnusedAnim; +extern Vtx object_haVtx_0000E0[]; +extern Gfx gHorseBanditRightHindFootDL[]; +extern Gfx gHorseBanditRightHindCannonDL[]; +extern Gfx gHorseBanditRightHindStifleDL[]; +extern Gfx gHorseBanditRightHindThighDL[]; +extern Gfx gHorseBanditLeftHindFootDL[]; +extern Gfx gHorseBanditLeftHindCannonDL[]; +extern Gfx gHorseBanditLeftHindStifleDL[]; +extern Gfx gHorseBanditLeftHindThighDL[]; +extern Gfx gHorseBanditTailEndDL[]; +extern Gfx gHorseBanditTailMiddleDL[]; +extern Gfx gHorseBanditTailDockDL[]; +extern Gfx gHorseBanditPelvisDL[]; +extern Gfx gHorseBanditRightFrontFootDL[]; +extern Gfx gHorseBanditRightFrontCannonDL[]; +extern Gfx gHorseBanditRightFrontForearmDL[]; +extern Gfx gHorseBanditRightFrontLegRootDL[]; +extern Gfx gHorseBanditHeadDL[]; +extern Gfx gHorseBanditUpperNeckDL[]; +extern Gfx gHorseBanditLowerNeckDL[]; +extern Gfx gHorseBanditLeftFrontFootDL[]; +extern Gfx gHorseBanditLeftFrontCannonDL[]; +extern Gfx gHorseBanditLeftFrontForearmDL[]; +extern Gfx gHorseBanditLeftFrontLegRootDL[]; +extern Gfx gHorseBanditTorsoDL[]; +extern u64 gHorseBanditTLUT[]; +extern u64 gHorseBanditMaskTex[]; +extern u64 gHorseBanditSpottedDetailTex[]; +extern u64 gHorseBanditEyebrowTex[]; +extern u64 gHorseBanditTeethTex[]; +extern u64 gHorseBanditTailAndFeetTex[]; +extern u64 gHorseBanditEyeTex[]; +extern u64 gHorseBanditMouthTex[]; +extern u64 gHorseBanditSpottedSkinTex[]; +extern u64 gHorseBanditTasselTex[]; +extern u64 gHorseBanditSaddleSideTex[]; +extern u64 gHorseBanditSaddleTopTex[]; +extern u64 gHorseBanditSaddleBackTex[]; +extern StandardLimb gHorseBanditRootLimb; +extern StandardLimb gHorseBanditPelvisLimb; +extern StandardLimb gHorseBanditTorsoLimb; +extern StandardLimb gHorseBanditLeftFrontLegRootLimb; +extern StandardLimb gHorseBanditLeftFrontForearmLimb; +extern StandardLimb gHorseBanditLeftFrontCannonLimb; +extern StandardLimb gHorseBanditLeftFrontFootLimb; +extern StandardLimb gHorseBanditLowerNeckLimb; +extern StandardLimb gHorseBanditUpperNeckLimb; +extern StandardLimb gHorseBanditHeadLimb; +extern StandardLimb gHorseBanditRightFrontLegRootLimb; +extern StandardLimb gHorseBanditRightFrontForearmLimb; +extern StandardLimb gHorseBanditRightFrontCannonLimb; +extern StandardLimb gHorseBanditRightFrontFootLimb; +extern StandardLimb gHorseBanditTailDockLimb; +extern StandardLimb gHorseBanditTailMiddleLimb; +extern StandardLimb gHorseBanditTailEndLimb; +extern StandardLimb gHorseBanditLeftHindThighLimb; +extern StandardLimb gHorseBanditLeftHindStifleLimb; +extern StandardLimb gHorseBanditLeftHindCannonLimb; +extern StandardLimb gHorseBanditLeftHindFootLimb; +extern StandardLimb gHorseBanditRightHindThighLimb; +extern StandardLimb gHorseBanditRightHindStifleLimb; +extern StandardLimb gHorseBanditRightHindCannonLimb; +extern StandardLimb gHorseBanditRightHindFootLimb; +extern void* gHorseBanditSkelLimbs[]; +extern FlexSkeletonHeader gHorseBanditSkel; +extern s16 sHorseGallopAnimFrameData[]; +extern JointIndex sHorseGallopAnimJointIndices[]; +extern AnimationHeader gHorseGallopAnim; +extern s16 sHorseJumpLowAnimFrameData[]; +extern JointIndex sHorseJumpLowAnimJointIndices[]; +extern AnimationHeader gHorseJumpLowAnim; +extern s16 sHorseJumpHighAnimFrameData[]; +extern JointIndex sHorseJumpHighAnimJointIndices[]; +extern AnimationHeader gHorseJumpHighAnim; +extern s16 sHorseTrotAnimFrameData[]; +extern JointIndex sHorseTrotAnimJointIndices[]; +extern AnimationHeader gHorseTrotAnim; +extern s16 sHorseWhinnyAnimFrameData[]; +extern JointIndex sHorseWhinnyAnimJointIndices[]; +extern AnimationHeader gHorseWhinnyAnim; +extern s16 sHorseStopAnimFrameData[]; +extern JointIndex sHorseStopAnimJointIndices[]; +extern AnimationHeader gHorseStopAnim; +extern s16 sHorseIdleAnimFrameData[]; +extern JointIndex sHorseIdleAnimJointIndices[]; +extern AnimationHeader gHorseIdleAnim; +extern s16 sHorseShakeHeadAnimFrameData[]; +extern JointIndex sHorseShakeHeadAnimJointIndices[]; +extern AnimationHeader gHorseShakeHeadAnim; +extern s16 sHorseWalkAnimFrameData[]; +extern JointIndex sHorseWalkAnimJointIndices[]; +extern AnimationHeader gHorseWalkAnim; +extern Vtx object_haVtx_00D660[]; +extern Gfx gDonkeyRightHindFootDL[]; +extern Gfx gDonkeyRightHindCannonDL[]; +extern Gfx gDonkeyRightHindStifleDL[]; +extern Gfx gDonkeyRightHindThighDL[]; +extern Gfx gDonkeyLeftHindFootDL[]; +extern Gfx gDonkeyLeftHindCannonDL[]; +extern Gfx gDonkeyLeftHindStifleDL[]; +extern Gfx gDonkeyLeftHindThighDL[]; +extern Gfx gDonkeyTailEndDL[]; +extern Gfx gDonkeyTailMiddleDL[]; +extern Gfx gDonkeyTailDockDL[]; +extern Gfx gDonkeyPelvisDL[]; +extern Gfx gDonkeyRightFrontFootDL[]; +extern Gfx gDonkeyRightFrontCannonDL[]; +extern Gfx gDonkeyRightFrontForearmDL[]; +extern Gfx gDonkeyRightFrontLegRootDL[]; +extern Gfx gDonkeyHeadDL[]; +extern Gfx gDonkeyUpperNeckDL[]; +extern Gfx gDonkeyLowerNeckDL[]; +extern Gfx gDonkeyLeftFrontFootDL[]; +extern Gfx gDonkeyLeftFrontCannonDL[]; +extern Gfx gDonkeyLeftFrontForearmDL[]; +extern Gfx gDonkeyLeftFrontLegRootDL[]; +extern Gfx gDonkeyTorsoDL[]; +extern u64 gDonkeyTLUT[]; +extern u64 gDonkeyMouthTex[]; +extern u64 gDonkeyHeadTex[]; +extern u64 gDonkeyEyeTex[]; +extern u64 gDonkeyManeTex[]; +extern u64 gDonkeySkinTex[]; +extern u64 gDonkeyHarnessTex[]; +extern u64 gDonkeyTailAndFeetTex[]; +extern StandardLimb gDonkeyRootLimb; +extern StandardLimb gDonkeyPelvisLimb; +extern StandardLimb gDonkeyTorsoLimb; +extern StandardLimb gDonkeyLeftFrontLegRootLimb; +extern StandardLimb gDonkeyLeftFrontForearmLimb; +extern StandardLimb gDonkeyLeftFrontCannonLimb; +extern StandardLimb gDonkeyLeftFrontFootLimb; +extern StandardLimb gDonkeyLowerNeckLimb; +extern StandardLimb gDonkeyUpperNeckLimb; +extern StandardLimb gDonkeyHeadLimb; +extern StandardLimb gDonkeyRightFrontLegRootLimb; +extern StandardLimb gDonkeyRightFrontForearmLimb; +extern StandardLimb gDonkeyRightFrontCannonLimb; +extern StandardLimb gDonkeyRightFrontFootLimb; +extern StandardLimb gDonkeyTailDockLimb; +extern StandardLimb gDonkeyTailMiddleLimb; +extern StandardLimb gDonkeyTailEndLimb; +extern StandardLimb gDonkeyLeftHindThighLimb; +extern StandardLimb gDonkeyLeftHindStifleLimb; +extern StandardLimb gDonkeyLeftHindCannonLimb; +extern StandardLimb gDonkeyLeftHindFootLimb; +extern StandardLimb gDonkeyRightHindThighLimb; +extern StandardLimb gDonkeyRightHindStifleLimb; +extern StandardLimb gDonkeyRightHindCannonLimb; +extern StandardLimb gDonkeyRightHindFootLimb; +extern void* gDonkeySkelLimbs[]; +extern FlexSkeletonHeader gDonkeySkel; +#endif diff --git a/patches/save_patches.c b/patches/save_patches.c index fac569f..5575bf3 100644 --- a/patches/save_patches.c +++ b/patches/save_patches.c @@ -21,7 +21,6 @@ void Sram_UpdateWriteToFlashDefault(SramContext* sramCtx) { } } else if (sramCtx->status == 4) { // @recomp Patched to check status instead of using a hardcoded wait. - recomp_printf("Status 4\n"); sramCtx->status = 0; } } diff --git a/patches/specific_actor_transform_tagging.c b/patches/specific_actor_transform_tagging.c index 0a7392e..aaf412c 100644 --- a/patches/specific_actor_transform_tagging.c +++ b/patches/specific_actor_transform_tagging.c @@ -733,8 +733,8 @@ void EnOsn_ChooseAction(EnOsn* this, PlayState* play) { Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, OSN_ANIM_IDLE); if (!isSwitchFlagSet) { - // @recomp Manual relocation, TODO remove when automated by the recompiler. - this->actionFunc = (EnOsnActionFunc)actor_relocate(&this->actor, EnOsn_HandleCsAction); + // @recomp No need to relocate as this function is replaced, so the patch compilation will pick the new address. + this->actionFunc = EnOsn_HandleCsAction; } else { // @recomp Manual relocation, TODO remove when automated by the recompiler. this->actionFunc = (EnOsnActionFunc)actor_relocate(&this->actor, EnOsn_Idle); @@ -916,3 +916,44 @@ void EnFall2_Draw(Actor* thisx, PlayState* play) { } } } + +// @recomp Skip interpolation on item pickups the frame they're collected. +void func_800A6A40(EnItem00* this, PlayState* play) { + Player* player = GET_PLAYER(play); + + if (this->getItemId != GI_NONE) { + if (!Actor_HasParent(&this->actor, play)) { + Actor_OfferGetItem(&this->actor, play, this->getItemId, 50.0f, 80.0f); + this->unk152++; + } else { + this->getItemId = GI_NONE; + } + } + + if (this->unk152 == 0) { + Actor_Kill(&this->actor); + return; + } + + this->actor.world.pos = player->actor.world.pos; + + if (this->actor.params <= ITEM00_RUPEE_RED) { + this->actor.shape.rot.y += 0x3C0; + } else if (this->actor.params == ITEM00_RECOVERY_HEART) { + this->actor.shape.rot.y = 0; + } + + this->actor.world.pos.y += (40.0f + (Math_SinS(this->unk152 * 15000) * (this->unk152 * 0.3f))); + + if (LINK_IS_ADULT) { + this->actor.world.pos.y += 20.0f; + } + + // @recomp Use custom flag 1 to check if this actor has been in this state before. + if (!actor_get_custom_flag_1(&this->actor)) { + recomp_printf("First frame picked up\n"); + // It hasn't, so skip interpolation this frame and set custom flag 1. + actor_set_interpolation_skipped(&this->actor); + actor_set_custom_flag_1(&this->actor); + } +} diff --git a/patches/syms.ld b/patches/syms.ld index 33652e0..5a629fd 100644 --- a/patches/syms.ld +++ b/patches/syms.ld @@ -12,6 +12,8 @@ _ovl_daytelopSegmentBssEnd = 0x0; sSceneEntranceTable = 0x801C5720; D_808DE5B0 = 0x808DE5B0; sHappyMaskSalesmanAnimationInfo = 0x80AD22C0; +D_808890F0 = 0x808890F0; +D_8088911C = 0x8088911C; /* Dummy addresses that get recompiled into function calls */ recomp_puts = 0x8F000000; diff --git a/patches/transform_ids.h b/patches/transform_ids.h index f3ec826..4688b57 100644 --- a/patches/transform_ids.h +++ b/patches/transform_ids.h @@ -58,7 +58,8 @@ static inline u32 actor_transform_id(Actor* actor) { typedef enum { ACTOR_TRANSFORM_FLAG_INTERPOLATION_SKIPPED = 1 << 0, -} ActorTransformFlags; + ACTOR_CUSTOM_FLAG_1 = 1 << 1, +} CustomActorFlags; static inline u32 actor_get_interpolation_skipped(Actor* actor) { return (actorIdByte2(actor) & ACTOR_TRANSFORM_FLAG_INTERPOLATION_SKIPPED) != 0; @@ -72,6 +73,18 @@ static inline void actor_clear_interpolation_skipped(Actor* actor) { actorIdByte2(actor) &= ~ACTOR_TRANSFORM_FLAG_INTERPOLATION_SKIPPED; } +static inline void actor_set_custom_flag_1(Actor* actor) { + actorIdByte2(actor) |= ACTOR_CUSTOM_FLAG_1; +} + +static inline void actor_clear_custom_flag_1(Actor* actor) { + actorIdByte2(actor) &= ~ACTOR_CUSTOM_FLAG_1; +} + +static inline bool actor_get_custom_flag_1(Actor* actor) { + return (actorIdByte2(actor) & ACTOR_CUSTOM_FLAG_1) != 0; +} + void force_camera_interpolation(); void force_camera_skip_interpolation();