diff options
Diffstat (limited to 'src/code/cutscene_camera.c')
| -rw-r--r-- | src/code/cutscene_camera.c | 380 |
1 files changed, 380 insertions, 0 deletions
diff --git a/src/code/cutscene_camera.c b/src/code/cutscene_camera.c new file mode 100644 index 000000000..d5f028b94 --- /dev/null +++ b/src/code/cutscene_camera.c @@ -0,0 +1,380 @@ +#include "global.h" + +extern CutsceneCamera* sCurCsCamera; + +typedef s16 (*CsCamInterpolateCallback)(Vec3f*, f32*, s16*, CsCmdCamPoint*, CsCmdCamMisc*, CutsceneCameraInterp*); + +// function declarations +s16 func_80161180(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_8016237C(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_8016253C(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_80162A50(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_801623E4(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_80161C20(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_80161E4C(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_801620CC(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +s16 func_80163334(Vec3f* pos, f32* fov, s16* roll, CsCmdCamPoint* point, CsCmdCamMisc* misc, + CutsceneCameraInterp* interp); +f32 func_80163660(Actor* actor); + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80161180.s") + +/** + * Initializes Cutscene Camera Info + */ +s32 CutsceneCamera_Init(Camera* camera, CutsceneCamera* csCamera) { + csCamera->camera = camera; + + csCamera->nextSplineTimer = csCamera->updateSplineTimer = 0; + csCamera->cmdIndex = 0; + csCamera->splineIndex = 0xFFFF; + csCamera->splineNeedsInit = true; + csCamera->state = CS_CAM_STATE_UPDATE_ALL; + + sCurCsCamera = csCamera; + + __osMemset(&csCamera->eyeInterp, 0, sizeof(CutsceneCameraInterp)); + __osMemset(&csCamera->atInterp, 0, sizeof(CutsceneCameraInterp)); + + csCamera->eyeInterp.unk_2D = csCamera->atInterp.unk_2D = 7; + + return 1; +} + +CsCamInterpolateCallback CutsceneCamera_Interpolate(u8 interpType) { + switch (interpType) { + case CS_CAM_INTERP_7: + default: + return func_80161180; + + case CS_CAM_INTERP_0: + return func_8016237C; + + case CS_CAM_INTERP_5: + return func_8016253C; + + case CS_CAM_INTERP_4: + return func_80162A50; + + case CS_CAM_INTERP_1: + return func_801623E4; + + case CS_CAM_INTERP_2: + return func_80161C20; + + case CS_CAM_INTERP_3: + return func_80161E4C; + + case CS_CAM_INTERP_6: + return func_801620CC; + } +} + +u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { + s32 sp5C; + f32* fov; + s16* roll; + CsCamInterpolateCallback interpHandler; + Player* player; + Actor* target; + s16 numPoints; + + sp5C = true; + if (csCamera->state == CS_CAM_STATE_DONE_SPLINE) { + return false; + } + + player = GET_PLAYER(csCamera->camera->play); + target = csCamera->camera->target; + + if (csCamera->eyeCmd[csCamera->atInterp.curPoint].interpType < + csCamera->atCmd[csCamera->eyeInterp.curPoint].interpType) { + sp5C = false; + } + + csCamera->eyeInterp.unk_00 = csCamera->camera->eye; + csCamera->atInterp.unk_00 = csCamera->camera->at; + + if (sp5C) { + fov = NULL; + } else { + fov = &csCamera->camera->fov; + } + + if (sp5C) { + roll = NULL; + } else { + roll = &csCamera->camera->roll; + } + + interpHandler = CutsceneCamera_Interpolate(csCamera->atCmd[csCamera->eyeInterp.curPoint].interpType); + + switch (csCamera->atCmd[csCamera->eyeInterp.curPoint].relativeTo) { + case CS_CAM_REL_2: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 2); + break; + + case CS_CAM_REL_3: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + break; + + case CS_CAM_REL_1: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + break; + + case CS_CAM_REL_4: + OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, 1); + break; + + case CS_CAM_REL_5: + OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, 2); + break; + + default: // CS_CAM_REL_0 + break; + } + + numPoints = interpHandler(&csCamera->camera->at, fov, roll, &csCamera->atCmd[csCamera->eyeInterp.curPoint], + &csCamera->miscCmd[csCamera->eyeInterp.curPoint], &csCamera->eyeInterp); + + switch (csCamera->atCmd[csCamera->eyeInterp.curPoint].relativeTo) { + case CS_CAM_REL_2: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 2); + break; + + case CS_CAM_REL_3: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + csCamera->camera->at.y += func_80163660(&player->actor); + break; + + case CS_CAM_REL_1: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + break; + + case CS_CAM_REL_4: + OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->at, &csCamera->camera->at, 1); + break; + + case CS_CAM_REL_5: + OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->at, &csCamera->camera->at, 2); + break; + + default: // CS_CAM_REL_0 + break; + } + + csCamera->eyeInterp.curPoint += numPoints; + + if (sp5C) { + fov = &csCamera->camera->fov; + } else { + fov = NULL; + } + + if (sp5C) { + roll = &csCamera->camera->roll; + } else { + roll = NULL; + } + + interpHandler = CutsceneCamera_Interpolate(csCamera->eyeCmd[csCamera->atInterp.curPoint].interpType); + + switch (csCamera->eyeCmd[csCamera->atInterp.curPoint].relativeTo) { + case CS_CAM_REL_2: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + break; + + case CS_CAM_REL_3: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + break; + + case CS_CAM_REL_1: + OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + break; + + case CS_CAM_REL_4: + OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + break; + + case CS_CAM_REL_5: + OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + break; + + default: // CS_CAM_REL_0 + break; + } + + numPoints = interpHandler(&csCamera->camera->eye, fov, roll, &csCamera->eyeCmd[csCamera->atInterp.curPoint], + &csCamera->miscCmd[csCamera->atInterp.curPoint], &csCamera->atInterp); + + switch (csCamera->eyeCmd[csCamera->atInterp.curPoint].relativeTo) { + case CS_CAM_REL_2: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + break; + + case CS_CAM_REL_3: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + csCamera->camera->eye.y += func_80163660(&player->actor); + break; + + case CS_CAM_REL_1: + OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + break; + + case CS_CAM_REL_4: + OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + break; + + case CS_CAM_REL_5: + OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + break; + + default: // CS_CAM_REL_0 + break; + } + + csCamera->atInterp.curPoint += numPoints; + + if ((csCamera->eyeInterp.curPoint >= csCamera->eyeInterp.numEntries) || + (csCamera->atInterp.curPoint >= csCamera->atInterp.numEntries)) { + return false; + } + + return true; +} + +/** + * Processes camera cutscene commands + */ +s32 CutsceneCamera_UpdateSplines(u8* script, CutsceneCamera* csCamera) { + CsCmdCamSpline* spline; + + switch (csCamera->state) { + case CS_CAM_STATE_DONE: + return 0; + + case CS_CAM_STATE_PAUSE: + return csCamera->nextSplineTimer; + + case CS_CAM_STATE_UPDATE_SPLINE: + if (csCamera->updateSplineTimer <= csCamera->duration) { + csCamera->updateSplineTimer++; + if (csCamera->updateSplineTimer <= csCamera->duration) { + // Process Spline + if (!CutsceneCamera_ProcessSpline(csCamera)) { + csCamera->state = CS_CAM_STATE_DONE_SPLINE; + } + } + } + break; + + case CS_CAM_STATE_DONE_SPLINE: + break; + + default: // CS_CAM_STATE_UPDATE_ALL + if (csCamera->splineNeedsInit == true) { + // Spline Header + spline = (CsCmdCamSpline*)&script[csCamera->cmdIndex]; + csCamera->atInterp.numEntries = csCamera->eyeInterp.numEntries = spline->numEntries; + csCamera->duration = spline->duration; + csCamera->cmdIndex += sizeof(CsCmdCamSpline); + + // At Point + csCamera->atCmd = (CsCmdCamPoint*)&script[csCamera->cmdIndex]; + csCamera->cmdIndex += (s16)(csCamera->eyeInterp.numEntries * sizeof(CsCmdCamPoint)); + + // Misc Point + csCamera->eyeCmd = (CsCmdCamPoint*)&script[csCamera->cmdIndex]; + csCamera->cmdIndex += (s16)(csCamera->eyeInterp.numEntries * sizeof(CsCmdCamPoint)); + + // Misc + csCamera->miscCmd = (CsCmdCamMisc*)&script[csCamera->cmdIndex]; + csCamera->cmdIndex += (s16)(csCamera->eyeInterp.numEntries * sizeof(CsCmdCamMisc)); + + // Other Params + csCamera->eyeInterp.curPoint = 0; + csCamera->atInterp.curPoint = 0; + + csCamera->splineNeedsInit = false; + //! FAKE: csCamera->splineIndex++; + csCamera->splineIndex = (csCamera->splineIndex & 0xFFFF) + 1; + csCamera->state = CS_CAM_STATE_UPDATE_ALL; + csCamera->nextSplineTimer = csCamera->updateSplineTimer = 0; + csCamera->eyeInterp.unk_2D = csCamera->atInterp.unk_2D = 7; + } + + csCamera->nextSplineTimer++; + + if (csCamera->updateSplineTimer <= csCamera->duration) { + csCamera->updateSplineTimer++; + if (csCamera->updateSplineTimer <= csCamera->duration) { + // Process SubCommands + if (!CutsceneCamera_ProcessSpline(csCamera)) { + csCamera->state = CS_CAM_STATE_DONE_SPLINE; + } + } + } + break; + } + + if (csCamera->nextSplineTimer > csCamera->duration) { + // Next Spline + csCamera->splineNeedsInit = true; + spline = (CsCmdCamSpline*)&script[csCamera->cmdIndex]; + if (spline->numEntries == -1) { + csCamera->state = CS_CAM_STATE_DONE; + return 0; + } + } + + return csCamera->nextSplineTimer; +} + +// Unused +s16 func_80161BAC(void) { + return (sCurCsCamera->state == CS_CAM_STATE_PAUSE) || (sCurCsCamera->state == CS_CAM_STATE_UPDATE_SPLINE); +} + +void CutsceneCamera_SetState(s16 state) { + if (sCurCsCamera->state == CS_CAM_STATE_UPDATE_ALL) { + sCurCsCamera->state = state; + } +} + +void CutsceneCamera_Reset(void) { + sCurCsCamera->state = CS_CAM_STATE_UPDATE_ALL; +} + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80161C20.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80161E4C.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_801620CC.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_8016237C.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_801623E4.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_801624EC.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_8016253C.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_801629BC.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80162A50.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80162FF8.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_801631DC.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80163334.s") + +#pragma GLOBAL_ASM("asm/non_matchings/code/cutscene_camera/func_80163660.s") |
