From 2cb1924ab72945d5456c1015dd29869623e25686 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 01:44:58 +0100 Subject: [PATCH 01/13] animated materials --- include/animated_materials.h | 84 +++++ include/config/config_game.h | 5 + include/helpers.h | 2 + include/macros.h | 1 + include/ultra64/ultratypes.h | 2 + include/z64play.h | 10 +- include/z64scene.h | 26 +- src/audio/general.c | 2 - src/code/animated_materials.c | 399 ++++++++++++++++++++ src/code/helpers.c | 54 +++ src/code/z_play.c | 7 + src/code/z_room.c | 6 + src/code/z_scene.c | 11 + src/code/z_scene_table.c | 89 ++--- src/overlays/gamestates/ovl_title/z_title.c | 2 +- 15 files changed, 633 insertions(+), 67 deletions(-) create mode 100644 include/animated_materials.h create mode 100644 src/code/animated_materials.c diff --git a/include/animated_materials.h b/include/animated_materials.h new file mode 100644 index 0000000000..01ceaa60ea --- /dev/null +++ b/include/animated_materials.h @@ -0,0 +1,84 @@ +#ifndef ANIMATED_MATERIALS_H +#define ANIMATED_MATERIALS_H + +#include "ultra64.h" + +typedef enum AnimatedMatType { + /* 0 */ ANIM_MAT_TYPE_TEX_SCROLL, + /* 1 */ ANIM_MAT_TYPE_TWO_TEX_SCROLL, + /* 2 */ ANIM_MAT_TYPE_COLOR, + /* 3 */ ANIM_MAT_TYPE_COLOR_LERP, + /* 4 */ ANIM_MAT_TYPE_COLOR_NON_LINEAR_INTERP, + /* 5 */ ANIM_MAT_TYPE_TEX_CYCLE, + /* 6 */ ANIM_MAT_TYPE_MAX +} AnimatedMatType; + +typedef struct { + /* 0x0 */ u8 r; + /* 0x1 */ u8 g; + /* 0x2 */ u8 b; + /* 0x3 */ u8 a; + /* 0x4 */ u8 lodFrac; +} F3DPrimColor; // size = 0x5 + +typedef struct { + /* 0x0 */ u8 r; + /* 0x1 */ u8 g; + /* 0x2 */ u8 b; + /* 0x3 */ u8 a; +} F3DEnvColor; // size = 0x4 + +typedef struct { + /* 0x0 */ u16 keyFrameLength; + /* 0x2 */ u16 keyFrameCount; + /* 0x4 */ F3DPrimColor* primColors; + /* 0x8 */ F3DEnvColor* envColors; + /* 0xC */ u16* keyFrames; +} AnimatedMatColorParams; // size = 0x10 + +typedef struct { + /* 0x0 */ s8 xStep; + /* 0x1 */ s8 yStep; + /* 0x2 */ u8 width; + /* 0x3 */ u8 height; +} AnimatedMatTexScrollParams; // size = 0x4 + +typedef struct { + /* 0x0 */ u16 keyFrameLength; + /* 0x4 */ TexturePtr* textureList; + /* 0x8 */ u8* textureIndexList; +} AnimatedMatTexCycleParams; // size = 0xC + +typedef struct { + /* 0x0 */ s8 segment; + /* 0x2 */ AnimatedMatType type; + /* 0x4 */ void* params; +} AnimatedMaterial; // size = 0x8 + +struct PlayState; + +Gfx* AnimatedMat_TexScroll(struct PlayState* play, AnimatedMatTexScrollParams* params); +void AnimatedMat_DrawTexScroll(struct PlayState* play, s32 segment, void* params); +Gfx* AnimatedMat_TwoLayerTexScroll(struct PlayState* play, AnimatedMatTexScrollParams* params); +void AnimatedMat_DrawTwoTexScroll(struct PlayState* play, s32 segment, void* params); +void AnimatedMat_SetColor(struct PlayState* play, s32 segment, F3DPrimColor* primColorResult, F3DEnvColor* envColor); +void AnimatedMat_DrawColor(struct PlayState* play, s32 segment, void* params); +s32 AnimatedMat_Lerp(s32 min, s32 max, f32 norm); +void AnimatedMat_DrawColorLerp(struct PlayState* play, s32 segment, void* params); +void AnimatedMat_DrawColorNonLinearInterp(struct PlayState* play, s32 segment, void* params); +void AnimatedMat_DrawTexCycle(struct PlayState* play, s32 segment, void* params); +void AnimatedMat_DrawMain(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step, u32 flags); +void AnimatedMat_Draw(struct PlayState* play, AnimatedMaterial* matAnim); +void AnimatedMat_DrawOpa(struct PlayState* play, AnimatedMaterial* matAnim); +void AnimatedMat_DrawXlu(struct PlayState* play, AnimatedMaterial* matAnim); +void AnimatedMat_DrawAlpha(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio); +void AnimatedMat_DrawAlphaOpa(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio); +void AnimatedMat_DrawAlphaXlu(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio); +void AnimatedMat_DrawStep(struct PlayState* play, AnimatedMaterial* matAnim, u32 step); +void AnimatedMat_DrawStepOpa(struct PlayState* play, AnimatedMaterial* matAnim, u32 step); +void AnimatedMat_DrawStepXlu(struct PlayState* play, AnimatedMaterial* matAnim, u32 step); +void AnimatedMat_DrawAlphaStep(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step); +void AnimatedMat_DrawAlphaStepOpa(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step); +void AnimatedMat_DrawAlphaStepXlu(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step); + +#endif diff --git a/include/config/config_game.h b/include/config/config_game.h index 170c1d2009..9be9c08fd9 100644 --- a/include/config/config_game.h +++ b/include/config/config_game.h @@ -69,4 +69,9 @@ // Make `Camera_KeepOn4`'s `case 9`, mimic how getting an item looks in Majora's Mask (Perspective from above) #define MM_GETITEM_CAM false +/** + * Enable Animated Materials (from Majora's Mask) + */ +#define ENABLE_ANIMATED_MATERIALS true + #endif diff --git a/include/helpers.h b/include/helpers.h index c9f1a52d5a..0c4cbc9e5b 100644 --- a/include/helpers.h +++ b/include/helpers.h @@ -12,5 +12,7 @@ void Helpers_LoadMapSelect(GameState* gameState); void Helpers_SetView(View* view, f32 eyeX, f32 eyeY, f32 eyeZ); void Helpers_InitSkybox(GameState* gameState, EnvironmentContext* envCtx, SkyboxContext* skyboxCtx, s16 skyboxId); void Helpers_DrawSkybox(GameState* gameState, View* view, EnvironmentContext* envCtx, SkyboxContext* skyboxCtx, s16 skyboxId, f32 eyeY, f32 angleIncrement); +f32 Helpers_LagrangeInterp(s32 n, f32 x[], f32 fx[], f32 xp); +u8 Helpers_LagrangeInterpColor(s32 n, f32 x[], f32 fx[], f32 xp); #endif diff --git a/include/macros.h b/include/macros.h index 9bd72bda5f..da78aa7502 100644 --- a/include/macros.h +++ b/include/macros.h @@ -24,6 +24,7 @@ #define VIRTUAL_TO_PHYSICAL(addr) (uintptr_t)((u8*)(addr) - 0x80000000) #define ABS(x) ((x) >= 0 ? (x) : -(x)) +#define ABS_ALT(x) ((x) < 0 ? -(x) : (x)) #define DECR(x) ((x) == 0 ? 0 : --(x)) #define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x)) #define CLAMP_MAX(x, max) ((x) > (max) ? (max) : (x)) diff --git a/include/ultra64/ultratypes.h b/include/ultra64/ultratypes.h index 743e755ae9..180f7dc103 100644 --- a/include/ultra64/ultratypes.h +++ b/include/ultra64/ultratypes.h @@ -38,6 +38,8 @@ typedef union MtxF { }; } MtxF; +typedef void* TexturePtr; + #endif #endif diff --git a/include/z64play.h b/include/z64play.h index 310c4134c2..6a36fa1ed1 100644 --- a/include/z64play.h +++ b/include/z64play.h @@ -24,6 +24,8 @@ #include "z64sram.h" #include "z64transition.h" #include "z64view.h" +#include "animated_materials.h" +#include "config.h" union Color_RGBA8_u32; struct Player; @@ -96,23 +98,21 @@ typedef struct PlayState { /* 0x11E16 */ s16 unk_11E16; /* 0x11E18 */ s16 bgCoverAlpha; /* 0x11E1A */ s16 nextEntranceIndex; - /* 0x11E1C */ char unk_11E1C[0x40]; /* 0x11E5C */ s8 shootingGalleryStatus; /* 0x11E5D */ s8 bombchuBowlingStatus; // "bombchu_game_flag" /* 0x11E5E */ u8 transitionType; /* 0x11E60 */ CollisionCheckContext colChkCtx; /* 0x120FC */ u16 cutsceneFlags[20]; /* 0x12124 */ PreRender pauseBgPreRender; - /* 0x12174 */ char unk_12174[0x53]; /* 0x121C7 */ s8 unk_121C7; /* 0x121C8 */ TransitionContext transitionCtx; - /* 0x12418 */ char unk_12418[0x3]; /* 0x1241B */ u8 transitionMode; // "fbdemo_wipe_modem" /* 0x1241C */ TransitionFade transitionFadeFlash; // Transition fade instance which flashes screen, see R_TRANS_FADE_FLASH_ALPHA_STEP - /* 0x12428 */ char unk_12428[0x3]; /* 0x1242B */ u8 viewpoint; // toggleable camera setting by shops or player. Is also equal to the bgCamIndex + 1 /* 0x1242C */ SceneTableEntry* loadedScene; - /* 0x12430 */ char unk_12430[0xE8]; +#if ENABLE_ANIMATED_MATERIALS + AnimatedMaterial* sceneMaterialAnims; +#endif } PlayState; // size = 0x12518 #define GET_ACTIVE_CAM(play) ((play)->cameraPtrs[(play)->activeCamId]) diff --git a/include/z64scene.h b/include/z64scene.h index e5d3744c9b..6008195407 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -390,6 +390,14 @@ typedef struct SCmdOccPlaneCandList { } SCmdOccPlaneCandList; #endif +#if ENABLE_ANIMATED_MATERIALS +typedef struct { + /* 0x0 */ u8 code; + /* 0x1 */ u8 data1; + /* 0x4 */ void* segment; +} SCmdTextureAnimations; // size = 0x8 +#endif + typedef union SceneCmd { SCmdBase base; SCmdPlayerEntryList playerEntryList; @@ -420,6 +428,9 @@ typedef union SceneCmd { #if ENABLE_F3DEX3 SCmdOccPlaneCandList occPlaneCandList; #endif +#if ENABLE_ANIMATED_MATERIALS + SCmdTextureAnimations textureAnimations; +#endif } SceneCmd; // size = 0x8 typedef BAD_RETURN(s32) (*SceneCmdHandlerFunc)(struct PlayState*, SceneCmd*); @@ -545,7 +556,11 @@ typedef enum SceneDrawConfig { /* 50 */ SDC_FISHING_POND, /* 51 */ SDC_GANONS_TOWER_COLLAPSE_INTERIOR, /* 52 */ SDC_INSIDE_GANONS_CASTLE_COLLAPSE, - /* 53 */ SDC_MAX +#if ENABLE_ANIMATED_MATERIALS + /* 53 */ SDC_MAT_ANIM, + /* 54 */ SDC_MAT_ANIM_MANUAL_STEP, +#endif + /* 55 */ SDC_MAX } SceneDrawConfig; typedef void (*SceneDrawConfigFunc)(struct PlayState*); @@ -596,6 +611,9 @@ typedef enum SceneCommandTypeID { /* 0x19 */ SCENE_CMD_ID_MISC_SETTINGS, #if ENABLE_F3DEX3 SCENE_CMD_ID_OCC_PLANE_CAND_LIST, +#endif +#if ENABLE_ANIMATED_MATERIALS + SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, #endif /* 0x1A */ SCENE_CMD_ID_MAX } SceneCommandTypeID; @@ -684,6 +702,12 @@ typedef enum SceneCommandTypeID { { SCENE_CMD_ID_OCC_PLANE_CAND_LIST, numPlanes, CMD_PTR(planeList) } #endif +#if ENABLE_ANIMATED_MATERIALS +#define SCENE_CMD_ANIMATED_MATERIAL_LIST(matAnimList) \ + { SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, 0, CMD_PTR(matAnimList) } +#endif + + s32 Scene_ExecuteCommands(struct PlayState* play, SceneCmd* sceneCmd); void Scene_ResetTransitionActorList(struct GameState* state, TransitionActorList* transitionActors); void Scene_SetTransitionForNextEntrance(struct PlayState* play); diff --git a/src/audio/general.c b/src/audio/general.c index de0875553f..a95ec453f4 100644 --- a/src/audio/general.c +++ b/src/audio/general.c @@ -2,8 +2,6 @@ #include "global.h" #include "versions.h" -#define ABS_ALT(x) ((x) < 0 ? -(x) : (x)) - #if !PLATFORM_N64 #define AUDIO_PRINTF osSyncPrintf #elif IDO_PRINTF_WORKAROUND diff --git a/src/code/animated_materials.c b/src/code/animated_materials.c new file mode 100644 index 0000000000..fbe802eb5d --- /dev/null +++ b/src/code/animated_materials.c @@ -0,0 +1,399 @@ +#include "animated_materials.h" +#include "global.h" +#include "z64.h" +#include "helpers.h" + +static s32 sMatAnimStep; +static u32 sMatAnimFlags; +static f32 sMatAnimAlphaRatio; + +/** + * Returns a pointer to a single layer texture scroll displaylist. + */ +Gfx* AnimatedMat_TexScroll(PlayState* play, AnimatedMatTexScrollParams* params) { + return Gfx_TexScroll(play->state.gfxCtx, params->xStep * sMatAnimStep, -(params->yStep * sMatAnimStep), + params->width, params->height); +} + +/** + * Animated Material Type 0: + * Scrolls a single layer texture using the provided `AnimatedMatTexScrollParams`. + */ +void AnimatedMat_DrawTexScroll(PlayState* play, s32 segment, void* params) { + AnimatedMatTexScrollParams* texScrollParams = (AnimatedMatTexScrollParams*)params; + Gfx* texScrollDList = AnimatedMat_TexScroll(play, texScrollParams); + + OPEN_DISPS(play->state.gfxCtx); + + if (sMatAnimFlags & 1) { + gSPSegment(POLY_OPA_DISP++, segment, texScrollDList); + } + + if (sMatAnimFlags & 2) { + gSPSegment(POLY_XLU_DISP++, segment, texScrollDList); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +/** + * Returns a pointer to a two layer texture scroll displaylist. + */ +Gfx* AnimatedMat_TwoLayerTexScroll(PlayState* play, AnimatedMatTexScrollParams* params) { + return Gfx_TwoTexScroll(play->state.gfxCtx, 0, params[0].xStep * sMatAnimStep, -(params[0].yStep * sMatAnimStep), + params[0].width, params[0].height, 1, params[1].xStep * sMatAnimStep, + -(params[1].yStep * sMatAnimStep), params[1].width, params[1].height); +} + +/** + * Animated Material Type 1: + * Scrolls a two layer texture using the provided `AnimatedMatTexScrollParams`. + */ +void AnimatedMat_DrawTwoTexScroll(PlayState* play, s32 segment, void* params) { + AnimatedMatTexScrollParams* texScrollParams = (AnimatedMatTexScrollParams*)params; + Gfx* texScrollDList = AnimatedMat_TwoLayerTexScroll(play, texScrollParams); + + OPEN_DISPS(play->state.gfxCtx); + + if (sMatAnimFlags & 1) { + gSPSegment(POLY_OPA_DISP++, segment, texScrollDList); + } + + if (sMatAnimFlags & 2) { + gSPSegment(POLY_XLU_DISP++, segment, texScrollDList); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +/** + * Generates a displaylist that sets the prim and env color, and stores it in the provided segment ID. + */ +void AnimatedMat_SetColor(PlayState* play, s32 segment, F3DPrimColor* primColorResult, F3DEnvColor* envColor) { + Gfx* gfx = GRAPH_ALLOC(play->state.gfxCtx, 3 * sizeof(Gfx)); + + OPEN_DISPS(play->state.gfxCtx); + + // clang-format off + if (sMatAnimFlags & 1) { gSPSegment(POLY_OPA_DISP++, segment, gfx); } + if (sMatAnimFlags & 2) { gSPSegment(POLY_XLU_DISP++, segment, gfx); } + // clang-format on + + gDPSetPrimColor(gfx++, 0, primColorResult->lodFrac, primColorResult->r, primColorResult->g, primColorResult->b, + (u8)(primColorResult->a * sMatAnimAlphaRatio)); + + if (envColor != NULL) { + gDPSetEnvColor(gfx++, envColor->r, envColor->g, envColor->b, envColor->a); + } + + gSPEndDisplayList(gfx++); + + CLOSE_DISPS(play->state.gfxCtx); +} + +/** + * Animated Material Type 2: + * Color key frame animation without linear interpolation. + */ +void AnimatedMat_DrawColor(PlayState* play, s32 segment, void* params) { + AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params; + F3DPrimColor* primColor = SEGMENTED_TO_VIRTUAL(colorAnimParams->primColors); + F3DEnvColor* envColor; + s32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength; + + primColor += curFrame; + envColor = (colorAnimParams->envColors != NULL) + ? (F3DEnvColor*)SEGMENTED_TO_VIRTUAL(colorAnimParams->envColors) + curFrame + : NULL; + + AnimatedMat_SetColor(play, segment, primColor, envColor); +} + +/** + * Linear Interpolation + */ +s32 AnimatedMat_Lerp(s32 min, s32 max, f32 norm) { + return (s32)((max - min) * norm) + min; +} + +/** + * Animated Material Type 3: + * Color key frame animation with linear interpolation. + */ +void AnimatedMat_DrawColorLerp(PlayState* play, s32 segment, void* params) { + AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params; + F3DPrimColor* primColorMax = SEGMENTED_TO_VIRTUAL(colorAnimParams->primColors); + F3DEnvColor* envColorMax; + u16* keyFrames = SEGMENTED_TO_VIRTUAL(colorAnimParams->keyFrames); + s32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength; + s32 endFrame; + s32 relativeFrame; // relative to the start frame + s32 startFrame; + f32 norm; + F3DPrimColor* primColorMin; + F3DPrimColor primColorResult; + F3DEnvColor* envColorMin; + F3DEnvColor envColorResult; + s32 i; + + keyFrames++; + i = 1; + + while (colorAnimParams->keyFrameCount > i) { + if (curFrame < *keyFrames) { + break; + } + i++; + keyFrames++; + } + + startFrame = keyFrames[-1]; + endFrame = keyFrames[0] - startFrame; + relativeFrame = curFrame - startFrame; + norm = (f32)relativeFrame / (f32)endFrame; + + primColorMax += i; + primColorMin = primColorMax - 1; + primColorResult.r = AnimatedMat_Lerp(primColorMin->r, primColorMax->r, norm); + primColorResult.g = AnimatedMat_Lerp(primColorMin->g, primColorMax->g, norm); + primColorResult.b = AnimatedMat_Lerp(primColorMin->b, primColorMax->b, norm); + primColorResult.a = AnimatedMat_Lerp(primColorMin->a, primColorMax->a, norm); + primColorResult.lodFrac = AnimatedMat_Lerp(primColorMin->lodFrac, primColorMax->lodFrac, norm); + + if (colorAnimParams->envColors) { + envColorMax = SEGMENTED_TO_VIRTUAL(colorAnimParams->envColors); + envColorMax += i; + envColorMin = envColorMax - 1; + envColorResult.r = AnimatedMat_Lerp(envColorMin->r, envColorMax->r, norm); + envColorResult.g = AnimatedMat_Lerp(envColorMin->g, envColorMax->g, norm); + envColorResult.b = AnimatedMat_Lerp(envColorMin->b, envColorMax->b, norm); + envColorResult.a = AnimatedMat_Lerp(envColorMin->a, envColorMax->a, norm); + } else { + envColorMax = NULL; + } + + AnimatedMat_SetColor(play, segment, &primColorResult, (envColorMax != NULL) ? &envColorResult : NULL); +} + +/** + * Animated Material Type 4: + * Color key frame animation with non-linear interpolation. + */ +void AnimatedMat_DrawColorNonLinearInterp(PlayState* play, s32 segment, void* params) { + AnimatedMatColorParams* colorAnimParams = (AnimatedMatColorParams*)params; + F3DPrimColor* primColorCur = SEGMENTED_TO_VIRTUAL(colorAnimParams->primColors); + F3DEnvColor* envColorCur = SEGMENTED_TO_VIRTUAL(colorAnimParams->envColors); + u16* keyFrames = SEGMENTED_TO_VIRTUAL(colorAnimParams->keyFrames); + f32 curFrame = sMatAnimStep % colorAnimParams->keyFrameLength; + F3DPrimColor primColorResult; + F3DEnvColor envColorResult; + f32 x[50]; + f32 fxPrimR[50]; + f32 fxPrimG[50]; + f32 fxPrimB[50]; + f32 fxPrimA[50]; + f32 fxPrimLodFrac[50]; + f32 fxEnvR[50]; + f32 fxEnvG[50]; + f32 fxEnvB[50]; + f32 fxEnvA[50]; + f32* xPtr = x; + f32* fxPrimRPtr = fxPrimR; + f32* fxPrimGPtr = fxPrimG; + f32* fxPrimBPtr = fxPrimB; + f32* fxPrimAPtr = fxPrimA; + f32* fxPrimLodFracPtr = fxPrimLodFrac; + f32* fxEnvRPtr = fxEnvR; + f32* fxEnvGPtr = fxEnvG; + f32* fxEnvBPtr = fxEnvB; + f32* fxEnvAPtr = fxEnvA; + s32 i; + + for (i = 0; i < colorAnimParams->keyFrameCount; i++) { + *xPtr = *keyFrames; + *fxPrimRPtr = primColorCur->r; + *fxPrimGPtr = primColorCur->g; + *fxPrimBPtr = primColorCur->b; + *fxPrimAPtr = primColorCur->a; + *fxPrimLodFracPtr = primColorCur->lodFrac; + + primColorCur++; + fxPrimRPtr++; + fxPrimGPtr++; + fxPrimBPtr++; + fxPrimAPtr++; + fxPrimLodFracPtr++; + + if (envColorCur != NULL) { + *fxEnvRPtr = envColorCur->r; + *fxEnvGPtr = envColorCur->g; + *fxEnvBPtr = envColorCur->b; + *fxEnvAPtr = envColorCur->a; + + envColorCur++; + fxEnvRPtr++; + fxEnvGPtr++; + fxEnvBPtr++; + fxEnvAPtr++; + } + + keyFrames++; + xPtr++; + } + + primColorResult.r = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimR, curFrame); + primColorResult.g = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimG, curFrame); + primColorResult.b = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimB, curFrame); + primColorResult.a = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimA, curFrame); + primColorResult.lodFrac = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxPrimLodFrac, curFrame); + + if (colorAnimParams->envColors != NULL) { + envColorCur = SEGMENTED_TO_VIRTUAL(colorAnimParams->envColors); + envColorResult.r = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvR, curFrame); + envColorResult.g = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvG, curFrame); + envColorResult.b = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvB, curFrame); + envColorResult.a = Helpers_LagrangeInterpColor(colorAnimParams->keyFrameCount, x, fxEnvA, curFrame); + } else { + envColorCur = NULL; + } + + AnimatedMat_SetColor(play, segment, &primColorResult, (envColorCur != NULL) ? &envColorResult : NULL); +} + +/** + * Animated Material Type 5: + * Cycles between a list of textures (imagine like a GIF) + */ +void AnimatedMat_DrawTexCycle(PlayState* play, s32 segment, void* params) { + AnimatedMatTexCycleParams* texAnimParams = params; + TexturePtr* texList = SEGMENTED_TO_VIRTUAL(texAnimParams->textureList); + u8* texId = SEGMENTED_TO_VIRTUAL(texAnimParams->textureIndexList); + s32 curFrame = sMatAnimStep % texAnimParams->keyFrameLength; + TexturePtr tex = SEGMENTED_TO_VIRTUAL(texList[texId[curFrame]]); + + OPEN_DISPS(play->state.gfxCtx); + + if (sMatAnimFlags & 1) { + gSPSegment(POLY_OPA_DISP++, segment, tex); + } + + if (sMatAnimFlags & 2) { + gSPSegment(POLY_XLU_DISP++, segment, tex); + } + + CLOSE_DISPS(play->state.gfxCtx); +} + +/** + * This is the main function that handles the animated material system. + * There are six different animated material types, which should be set in the provided `AnimatedMaterial`. + */ +void AnimatedMat_DrawMain(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step, u32 flags) { + static void (*sMatAnimDrawHandlers[ANIM_MAT_TYPE_MAX])(PlayState*, s32 segment, void* params) = { + AnimatedMat_DrawTexScroll, // ANIM_MAT_TYPE_TEX_SCROLL + AnimatedMat_DrawTwoTexScroll, // ANIM_MAT_TYPE_TWO_TEX_SCROLL + AnimatedMat_DrawColor, // ANIM_MAT_TYPE_COLOR + AnimatedMat_DrawColorLerp, // ANIM_MAT_TYPE_COLOR_LERP + AnimatedMat_DrawColorNonLinearInterp, // ANIM_MAT_TYPE_COLOR_NON_LINEAR_INTERP + AnimatedMat_DrawTexCycle, // ANIM_MAT_TYPE_TEX_CYCLE + }; + s32 segmentAbs; + s32 segment; + + sMatAnimAlphaRatio = alphaRatio; + sMatAnimStep = step; + sMatAnimFlags = flags; + + if ((matAnim != NULL) && (matAnim->segment != 0)) { + do { + segment = matAnim->segment; + segmentAbs = ABS_ALT(segment) + 7; + sMatAnimDrawHandlers[matAnim->type](play, segmentAbs, SEGMENTED_TO_VIRTUAL(matAnim->params)); + matAnim++; + } while (segment >= 0); + } +} + +/** + * Draws an animated material to both OPA and XLU buffers. + */ +void AnimatedMat_Draw(PlayState* play, AnimatedMaterial* matAnim) { + AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 3); +} + +/** + * Draws an animated material to only the OPA buffer. + */ +void AnimatedMat_DrawOpa(PlayState* play, AnimatedMaterial* matAnim) { + AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 1); +} + +/** + * Draws an animated material to only the XLU buffer. + */ +void AnimatedMat_DrawXlu(PlayState* play, AnimatedMaterial* matAnim) { + AnimatedMat_DrawMain(play, matAnim, 1, play->gameplayFrames, 2); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) both OPA and XLU buffers. + */ +void AnimatedMat_DrawAlpha(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 3); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) to only the OPA buffer. + */ +void AnimatedMat_DrawAlphaOpa(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 1); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) to only the XLU buffer. + */ +void AnimatedMat_DrawAlphaXlu(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, play->gameplayFrames, 2); +} + +/** + * Draws an animated material with a step to both the OPA and XLU buffers. + */ +void AnimatedMat_DrawStep(PlayState* play, AnimatedMaterial* matAnim, u32 step) { + AnimatedMat_DrawMain(play, matAnim, 1, step, 3); +} + +/** + * Draws an animated material with a step to only the OPA buffer. + */ +void AnimatedMat_DrawStepOpa(PlayState* play, AnimatedMaterial* matAnim, u32 step) { + AnimatedMat_DrawMain(play, matAnim, 1, step, 1); +} + +/** + * Draws an animated material with a step to only the XLU buffer. + */ +void AnimatedMat_DrawStepXlu(PlayState* play, AnimatedMaterial* matAnim, u32 step) { + AnimatedMat_DrawMain(play, matAnim, 1, step, 2); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to both the OPA and XLU buffers. + */ +void AnimatedMat_DrawAlphaStep(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 3); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to only the OPA buffer. + */ +void AnimatedMat_DrawAlphaStepOpa(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 1); +} + +/** + * Draws an animated material with an alpha ratio (0.0 - 1.0) and a step to only the XLU buffer. + */ +void AnimatedMat_DrawAlphaStepXlu(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) { + AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 2); +} diff --git a/src/code/helpers.c b/src/code/helpers.c index 513d63f853..f10dd990fe 100644 --- a/src/code/helpers.c +++ b/src/code/helpers.c @@ -104,3 +104,57 @@ void Helpers_DrawSkybox(GameState* gameState, View* view, EnvironmentContext* en view->eye.z); Environment_UpdateSkybox(skyboxId, envCtx, skyboxCtx); } + +/** + * Lagrange interpolation + */ +f32 Helpers_LagrangeInterp(s32 n, f32 x[], f32 fx[], f32 xp) { + f32 weights[50]; + f32 xVal; + f32 m; + f32 intp; + f32* xPtr1; + f32* fxPtr; + f32* weightsPtr; + f32* xPtr2; + s32 i; + s32 j; + + for (i = 0, xPtr1 = x, fxPtr = fx, weightsPtr = weights; i < n; i++) { + for (xVal = *xPtr1, m = 1.0f, j = 0, xPtr2 = x; j < n; j++) { + if (j != i) { + m *= xVal - (*xPtr2); + } + xPtr2++; + } + + xPtr1++; + *weightsPtr = (*fxPtr) / m; + fxPtr++; + weightsPtr++; + } + + for (intp = 0.0f, i = 0, weightsPtr = weights; i < n; i++) { + for (m = 1.0f, j = 0, xPtr2 = x; j < n; j++) { + if (j != i) { + m *= xp - (*xPtr2); + } + xPtr2++; + } + + intp += (*weightsPtr) * m; + weightsPtr++; + } + + return intp; +} + +/** + * Lagrange interpolation specifically for colors + */ +u8 Helpers_LagrangeInterpColor(s32 n, f32 x[], f32 fx[], f32 xp) { + s32 intp = Helpers_LagrangeInterp(n, x, fx, xp); + + // Clamp between 0 and 255 to ensure the color value does not overflow in either direction + return CLAMP(intp, 0, 255); +} diff --git a/src/code/z_play.c b/src/code/z_play.c index 1f8d3aee10..e6465607de 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -531,6 +531,9 @@ void Play_Init(GameState* thisx) { DmaMgr_DmaRomToRam(0x03FEB000, gDebugCutsceneScript, sizeof(sDebugCutsceneScriptBuf)); } #endif + + //! TODO: investigate issue with this variable set to a random value + this->gameplayFrames = 0; } void Play_Update(PlayState* this) { @@ -1771,6 +1774,10 @@ void Play_InitScene(PlayState* this, s32 spawn) { this->naviQuestHints = NULL; this->pathList = NULL; +#if ENABLE_ANIMATED_MATERIALS + this->sceneMaterialAnims = NULL; +#endif + this->numActorEntries = 0; Object_InitContext(this, &this->objectCtx); diff --git a/src/code/z_room.c b/src/code/z_room.c index 25578a631d..6d523137cc 100644 --- a/src/code/z_room.c +++ b/src/code/z_room.c @@ -562,11 +562,17 @@ void Room_DrawImage(PlayState* play, Room* room, u32 flags) { } void Room_Init(PlayState* play, Room* room) { + u8 i; + room->num = -1; room->segment = NULL; #if ENABLE_F3DEX3 room->occPlaneCount = 0; #endif + + for (i = 0; i < ARRAY_COUNT(play->roomCtx.drawParams); i++) { + play->roomCtx.drawParams[i] = 0; + } } /** diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 949e4c9d7b..0c8c3b4fe7 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -527,6 +527,14 @@ void Scene_SetTransitionForNextEntrance(PlayState* play) { play->transitionType = ENTRANCE_INFO_START_TRANS_TYPE(gEntranceTable[entranceIndex].field); } +#if ENABLE_ANIMATED_MATERIALS + +void Scene_CommandAnimatedMaterials(PlayState* play, SceneCmd* cmd) { + play->sceneMaterialAnims = SEGMENTED_TO_VIRTUAL(cmd->textureAnimations.segment); +} + +#endif + SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX] = { Scene_CommandPlayerEntryList, // SCENE_CMD_ID_SPAWN_LIST Scene_CommandActorEntryList, // SCENE_CMD_ID_ACTOR_LIST @@ -557,6 +565,9 @@ SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX] = { #if ENABLE_F3DEX3 Scene_CommandOccPlaneCandList, // SCENE_CMD_ID_OCC_PLANE_CAND_LIST #endif +#if ENABLE_ANIMATED_MATERIALS + Scene_CommandAnimatedMaterials, // SCENE_CMD_ID_ANIMATED_MATERIAL_LIST +#endif }; RomFile sNaviQuestHintFiles[] = { diff --git a/src/code/z_scene_table.c b/src/code/z_scene_table.c index b10223500a..1d1ce3aabf 100644 --- a/src/code/z_scene_table.c +++ b/src/code/z_scene_table.c @@ -2,6 +2,7 @@ #include "quake.h" #include "versions.h" #include "z64frame_advance.h" +#include "animated_materials.h" #include "config.h" #if PLATFORM_N64 #include "n64dd.h" @@ -85,6 +86,11 @@ void Scene_DrawConfigFishingPond(PlayState* play); void Scene_DrawConfigGanonsTowerCollapseInterior(PlayState* play); void Scene_DrawConfigInsideGanonsCastleCollapse(PlayState* play); +#if ENABLE_ANIMATED_MATERIALS +void Scene_DrawConfigMatAnim(PlayState* play); +void Scene_DrawConfigMatAnimManualStep(PlayState* play); +#endif + // Entrance Table definition #define DEFINE_ENTRANCE(_0, sceneId, spawn, continueBgm, displayTitleCard, endTransType, startTransType) \ { sceneId, spawn, \ @@ -138,8 +144,6 @@ Gfx sDefaultDisplayList[] = { gsSPEndDisplayList(), }; -#if PLATFORM_N64 // Scene_Draw is at end of file in GC/iQue versions - SceneDrawConfigFunc sSceneDrawConfigs[SDC_MAX] = { Scene_DrawConfigDefault, // SDC_DEFAULT Scene_DrawConfigHyruleField, // SDC_HYRULE_FIELD @@ -194,8 +198,14 @@ SceneDrawConfigFunc sSceneDrawConfigs[SDC_MAX] = { Scene_DrawConfigFishingPond, // SDC_FISHING_POND Scene_DrawConfigGanonsTowerCollapseInterior, // SDC_GANONS_TOWER_COLLAPSE_INTERIOR Scene_DrawConfigInsideGanonsCastleCollapse, // SDC_INSIDE_GANONS_CASTLE_COLLAPSE +#if ENABLE_ANIMATED_MATERIALS + Scene_DrawConfigMatAnim, // SDC_MAT_ANIM + Scene_DrawConfigMatAnimManualStep, // SDC_MAT_ANIM_MANUAL_STEP +#endif }; +#if PLATFORM_N64 // Scene_Draw is at end of file in GC/iQue versions + void Scene_Draw(PlayState* play) { if ((B_80121220 != NULL) && (B_80121220->unk_6C != NULL)) { B_80121220->unk_6C(play, sSceneDrawConfigs); @@ -1703,63 +1713,26 @@ void Scene_DrawConfigBesitu(PlayState* play) { CLOSE_DISPS(play->state.gfxCtx, "../z_scene_table.c", 7910); } -#if !PLATFORM_N64 // Scene_Draw is at beginning of file in N64 versions +#if ENABLE_ANIMATED_MATERIALS -SceneDrawConfigFunc sSceneDrawConfigs[SDC_MAX] = { - Scene_DrawConfigDefault, // SDC_DEFAULT - Scene_DrawConfigHyruleField, // SDC_HYRULE_FIELD - Scene_DrawConfigKakarikoVillage, // SDC_KAKARIKO_VILLAGE - Scene_DrawConfigZorasRiver, // SDC_ZORAS_RIVER - Scene_DrawConfigKokiriForest, // SDC_KOKIRI_FOREST - Scene_DrawConfigLakeHylia, // SDC_LAKE_HYLIA - Scene_DrawConfigZorasDomain, // SDC_ZORAS_DOMAIN - Scene_DrawConfigZorasFountain, // SDC_ZORAS_FOUNTAIN - Scene_DrawConfigGerudoValley, // SDC_GERUDO_VALLEY - Scene_DrawConfigLostWoods, // SDC_LOST_WOODS - Scene_DrawConfigDesertColossus, // SDC_DESERT_COLOSSUS - Scene_DrawConfigGerudosFortress, // SDC_GERUDOS_FORTRESS - Scene_DrawConfigHauntedWasteland, // SDC_HAUNTED_WASTELAND - Scene_DrawConfigHyruleCastle, // SDC_HYRULE_CASTLE - Scene_DrawConfigDeathMountainTrail, // SDC_DEATH_MOUNTAIN_TRAIL - Scene_DrawConfigDeathMountainCrater, // SDC_DEATH_MOUNTAIN_CRATER - Scene_DrawConfigGoronCity, // SDC_GORON_CITY - Scene_DrawConfigLonLonRanch, // SDC_LON_LON_RANCH - Scene_DrawConfigFireTemple, // SDC_FIRE_TEMPLE - Scene_DrawConfigDekuTree, // SDC_DEKU_TREE - Scene_DrawConfigDodongosCavern, // SDC_DODONGOS_CAVERN - Scene_DrawConfigJabuJabu, // SDC_JABU_JABU - Scene_DrawConfigForestTemple, // SDC_FOREST_TEMPLE - Scene_DrawConfigWaterTemple, // SDC_WATER_TEMPLE - Scene_DrawConfigShadowTempleAndWell, // SDC_SHADOW_TEMPLE_AND_WELL - Scene_DrawConfigSpiritTemple, // SDC_SPIRIT_TEMPLE - Scene_DrawConfigInsideGanonsCastle, // SDC_INSIDE_GANONS_CASTLE - Scene_DrawConfigGerudoTrainingGround, // SDC_GERUDO_TRAINING_GROUND - Scene_DrawConfigDekuTreeBoss, // SDC_DEKU_TREE_BOSS - Scene_DrawConfigWaterTempleBoss, // SDC_WATER_TEMPLE_BOSS - Scene_DrawConfigTempleOfTime, // SDC_TEMPLE_OF_TIME - Scene_DrawConfigGrottos, // SDC_GROTTOS - Scene_DrawConfigChamberOfTheSages, // SDC_CHAMBER_OF_THE_SAGES - Scene_DrawConfigGreatFairyFountain, // SDC_GREAT_FAIRYS_FOUNTAIN - Scene_DrawConfigShootingGallery, // SDC_SHOOTING_GALLERY - Scene_DrawConfigCastleCourtyardGuards, // SDC_CASTLE_COURTYARD_GUARDS - Scene_DrawConfigOutsideGanonsCastle, // SDC_OUTSIDE_GANONS_CASTLE - Scene_DrawConfigIceCavern, // SDC_ICE_CAVERN - Scene_DrawConfigGanonsTowerCollapseExterior, // SDC_GANONS_TOWER_COLLAPSE_EXTERIOR - Scene_DrawConfigFairysFountain, // SDC_FAIRYS_FOUNTAIN - Scene_DrawConfigThievesHideout, // SDC_THIEVES_HIDEOUT - Scene_DrawConfigBombchuBowlingAlley, // SDC_BOMBCHU_BOWLING_ALLEY - Scene_DrawConfigRoyalFamilysTomb, // SDC_ROYAL_FAMILYS_TOMB - Scene_DrawConfigLakesideLaboratory, // SDC_LAKESIDE_LABORATORY - Scene_DrawConfigLonLonBuildings, // SDC_LON_LON_BUILDINGS - Scene_DrawConfigMarketGuardHouse, // SDC_MARKET_GUARD_HOUSE - Scene_DrawConfigPotionShopGranny, // SDC_POTION_SHOP_GRANNY - Scene_DrawConfigCalmWater, // SDC_CALM_WATER - Scene_DrawConfigGraveExitLightShining, // SDC_GRAVE_EXIT_LIGHT_SHINING - Scene_DrawConfigBesitu, // SDC_BESITU - Scene_DrawConfigFishingPond, // SDC_FISHING_POND - Scene_DrawConfigGanonsTowerCollapseInterior, // SDC_GANONS_TOWER_COLLAPSE_INTERIOR - Scene_DrawConfigInsideGanonsCastleCollapse, // SDC_INSIDE_GANONS_CASTLE_COLLAPSE -}; +/** + * Allows the usage of the animated material system in scenes. + */ +void Scene_DrawConfigMatAnim(PlayState* play) { + AnimatedMat_Draw(play, play->sceneMaterialAnims); +} + +/** + * This is a special draw config for Sakon's Hideout, as well as the Music Box House. Its step value is set manually + * rather than always animating like `Scene_DrawConfigMatAnim`. + */ +void Scene_DrawConfigMatAnimManualStep(PlayState* play) { + AnimatedMat_DrawStep(play, play->sceneMaterialAnims, play->roomCtx.drawParams[0]); +} + +#endif + +#if !PLATFORM_N64 // Scene_Draw is at beginning of file in N64 versions void Scene_Draw(PlayState* play) { #if DEBUG_FEATURES diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c index f792b9e433..6aa88c349f 100644 --- a/src/overlays/gamestates/ovl_title/z_title.c +++ b/src/overlays/gamestates/ovl_title/z_title.c @@ -137,7 +137,7 @@ void ConsoleLogo_Main(GameState* thisx) { if (this->exit) { #if ENABLE_HACKER_DEBUG #if BOOT_TO_SCENE - Helpers_LoadDefinedScene(thisx), + Helpers_LoadDefinedScene(thisx); #elif IS_DEBUG_BOOT_ENABLED && BOOT_TO_DEBUG_OPENING this->state.running = false; SET_NEXT_GAMESTATE(&this->state, DebugOpening_Init, DebugOpeningState); From 0e68aab10cf5e9b260fd1036d4c59e74d636363d Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 01:56:12 +0100 Subject: [PATCH 02/13] fix build errors with CI --- spec | 1 + 1 file changed, 1 insertion(+) diff --git a/spec b/spec index cefd81b5c0..28b254d29a 100644 --- a/spec +++ b/spec @@ -963,6 +963,7 @@ beginseg #endif include "$(BUILD_DIR)/src/code/rainbow.o" include "$(BUILD_DIR)/src/code/helpers.o" + include "$(BUILD_DIR)/src/code/animated_materials.o" endseg #if ENABLE_HACKER_DEBUG From ab64c6503649dc5cf17d32a6e521e7434b0a8954 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:31:18 +0100 Subject: [PATCH 03/13] tests --- include/config/config_debug.h | 4 +- include/config/config_game.h | 12 + include/letterbox.h | 21 + include/z64actor.h | 7 + include/z64camera.h | 9 + include/z64cutscene.h | 296 +++++- include/z64olib.h | 17 + include/z64play.h | 8 + include/z64save.h | 9 + include/z64scene.h | 37 + include/z_lib.h | 4 + spec | 25 + src/code/cutscene_camera.c | 933 ++++++++++++++++++ src/code/cutscene_manager.c | 573 +++++++++++ src/code/shrink_window.c | 154 +++ src/code/z_camera.c | 208 ++++ src/code/z_camera_data.inc.c | 140 +-- src/code/z_demo.c | 24 +- src/code/z_lib.c | 27 + src/code/z_olib.c | 66 ++ src/code/z_parameter.c | 315 ++++++ src/code/z_play.c | 58 ++ src/code/z_player_lib.c | 2 +- src/code/z_scene.c | 15 +- .../ovl_file_choose/z_file_choose.c | 6 + .../gamestates/ovl_opening/z_opening.c | 6 + src/overlays/gamestates/ovl_select/z_select.c | 8 + src/overlays/gamestates/ovl_title/z_title.c | 7 + 28 files changed, 2898 insertions(+), 93 deletions(-) create mode 100644 src/code/cutscene_camera.c create mode 100644 src/code/cutscene_manager.c diff --git a/include/config/config_debug.h b/include/config/config_debug.h index 184652b35d..c8bea9ccad 100644 --- a/include/config/config_debug.h +++ b/include/config/config_debug.h @@ -28,7 +28,7 @@ /** * Options for booting directly into a scene, the debug boot or the file select, instead of the title screen. */ -#define BOOT_TO_SCENE false +#define BOOT_TO_SCENE true #define BOOT_TO_SCENE_NEW_GAME_ONLY false #define BOOT_TO_FILE_SELECT false #define BOOT_TO_DEBUG_OPENING true @@ -40,7 +40,7 @@ #define MAP_SELECT_ON_FILE_1 false // Change these if using `BOOT_TO_SCENE`, `BOOT_TO_SCENE_NEW_GAME_ONLY` or `BOOT_TO_DEBUG_OPENING` -#define BOOT_ENTRANCE ENTR_EXAMPLE_0 +#define BOOT_ENTRANCE ENTR_DEBUG1_0 #define BOOT_AGE LINK_AGE_ADULT #define BOOT_CUTSCENE 0x0000 diff --git a/include/config/config_game.h b/include/config/config_game.h index 9be9c08fd9..8b6d52d850 100644 --- a/include/config/config_game.h +++ b/include/config/config_game.h @@ -74,4 +74,16 @@ */ #define ENABLE_ANIMATED_MATERIALS true +/** + * Enable New Letterbox (from Majora's Mask) + */ +#define ENABLE_NEW_LETTERBOX true + +/** + * Enable Cutscene Improvements (from Majora's Mask) + * + * This includes actor cutscenes + */ +#define ENABLE_CUTSCENE_IMPROVEMENTS true + #endif diff --git a/include/letterbox.h b/include/letterbox.h index 48d6ea7c13..cf54c27195 100644 --- a/include/letterbox.h +++ b/include/letterbox.h @@ -11,4 +11,25 @@ void Letterbox_Init(void); void Letterbox_Destroy(void); void Letterbox_Update(s32 updateRate); +#if ENABLE_NEW_LETTERBOX + +struct GraphicsContext; + +void ShrinkWindow_Letterbox_SetSizeTarget(s32 target); +s32 ShrinkWindow_Letterbox_GetSizeTarget(void); +void ShrinkWindow_Letterbox_SetSize(s32 size); +s32 ShrinkWindow_Letterbox_GetSize(void); + +void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target); +s32 ShrinkWindow_Pillarbox_GetSizeTarget(void); +void ShrinkWindow_Pillarbox_SetSize(s32 size); +s32 ShrinkWindow_Pillarbox_GetSize(void); + +void ShrinkWindow_Init(void); +void ShrinkWindow_Destroy(void); +void ShrinkWindow_Update(s32 framerateDivisor); +void ShrinkWindow_Draw(struct GraphicsContext* gfxCtx); + +#endif + #endif diff --git a/include/z64actor.h b/include/z64actor.h index deac35481c..5f3241e729 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -220,6 +220,13 @@ typedef struct ActorShape { // Flag controlling the use of `Actor.sfx`. Do not use directly. See Actor_PlaySfx_FlaggedTimer #define ACTOR_FLAG_SFX_TIMER (1 << 28) +// Actor can update even if Player is currently in one of the `sCategoryFreezeMasks` states. +// Typically an actor will halt while the player is in one of the `sCategoryFreezeMasks` states (depending on category). +// This flag allows a given actor to be an exception. +// +// Note: Not implemented yet. +#define ACTOR_FLAG_FREEZE_EXCEPTION (1 << 29) + #define COLORFILTER_GET_COLORINTENSITY(colorFilterParams) (((colorFilterParams) & 0x1F00) >> 5) #define COLORFILTER_GET_DURATION(colorFilterParams) ((colorFilterParams) & 0xFF) diff --git a/include/z64camera.h b/include/z64camera.h index 41f22aec7c..d6900925a8 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -1733,4 +1733,13 @@ void Camera_SetCameraData(Camera* camera, s16 setDataFlags, void* data0, void* d s32 func_8005B198(void); s16 Camera_SetFinishedFlag(Camera* camera); +#if ENABLE_CUTSCENE_IMPROVEMENTS +s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId); +Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId); +s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags); +s32 Camera_ChangeSetting(Camera* camera, s16 setting); +s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex); +void Camera_800E0348(Camera* camera); +#endif + #endif diff --git a/include/z64cutscene.h b/include/z64cutscene.h index 8e94406eda..feac14c170 100644 --- a/include/z64cutscene.h +++ b/include/z64cutscene.h @@ -11,7 +11,7 @@ typedef union CutsceneData { s32 i; f32 f; s16 s[2]; - s8 b[4]; + s8 b[4]; } CutsceneData; typedef enum CutsceneState { @@ -198,7 +198,7 @@ typedef enum CutsceneTextType { /* 0x00 */ CS_TEXT_NORMAL, /* 0x01 */ CS_TEXT_CHOICE, /* 0x02 */ CS_TEXT_OCARINA_ACTION, - /* 0x03 */ CS_TEXT_GORON_RUBY, // use `altTextId1` in the ruby cutscene if sapphire is already obtained + /* 0x03 */ CS_TEXT_GORON_RUBY, // use `altTextId1` in the ruby cutscene if sapphire is already obtained /* 0x04 */ CS_TEXT_ZORA_SAPPHIRE // use `altTextId1` in the sapphire cutscene if ruby is already obtained } CutsceneTextType; @@ -240,7 +240,7 @@ typedef enum CutsceneDestination { /* 0x0D */ CS_DEST_ZORAS_FOUNTAIN_FROM_ZORAS_SAPPHIRE, /* 0x0E */ CS_DEST_KOKIRI_FOREST_FROM_KOKIRI_EMERALD, /* 0x0F */ CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED, // unused - /* 0x10 */ CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED, // unused + /* 0x10 */ CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED, // unused /* 0x11 */ CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED, // unused /* 0x12 */ CS_DEST_TEMPLE_OF_TIME_AFTER_LIGHT_MEDALLION, /* 0x13 */ CS_DEST_DEATH_MOUNTAIN_TRAIL, // unused @@ -251,7 +251,7 @@ typedef enum CutsceneDestination { /* 0x18 */ CS_DEST_JABU_JABU, /* 0x19 */ CS_DEST_CHAMBER_OF_SAGES_LIGHT_MEDALLION, /* 0x1A */ CS_DEST_TEMPLE_OF_TIME_KOKIRI_EMERALD_RESTORED_2, // unused - /* 0x1B */ CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2, // unused + /* 0x1B */ CS_DEST_TEMPLE_OF_TIME_GORON_RUBY_RESTORED_2, // unused /* 0x1C */ CS_DEST_TEMPLE_OF_TIME_ZORAS_SAPPHIRE_RESTORED_2, // unused /* 0x1D */ CS_DEST_CHAMBER_OF_SAGES_FOREST_MEDALLION, /* 0x1E */ CS_DEST_CHAMBER_OF_SAGES_FIRE_MEDALLION, @@ -303,15 +303,15 @@ typedef enum CutsceneDestination { /* 0x4C */ CS_DEST_LON_LON_RANCH_CREDITS_PART_4, /* 0x4D */ CS_DEST_LON_LON_RANCH_CREDITS_PART_5, /* 0x4E */ CS_DEST_LON_LON_RANCH_CREDITS_PART_6, - /* 0x4F */ CS_DEST_LON_LON_RANCH_1, // unused - /* 0x50 */ CS_DEST_LON_LON_RANCH_2, // unused - /* 0x51 */ CS_DEST_LON_LON_RANCH_3, // unused - /* 0x52 */ CS_DEST_LON_LON_RANCH_4, // unused - /* 0x53 */ CS_DEST_LON_LON_RANCH_5, // unused - /* 0x54 */ CS_DEST_LON_LON_RANCH_6, // unused - /* 0x55 */ CS_DEST_LON_LON_RANCH_7, // unused - /* 0x56 */ CS_DEST_LON_LON_RANCH_8, // unused - /* 0x57 */ CS_DEST_LON_LON_RANCH_9, // unused + /* 0x4F */ CS_DEST_LON_LON_RANCH_1, // unused + /* 0x50 */ CS_DEST_LON_LON_RANCH_2, // unused + /* 0x51 */ CS_DEST_LON_LON_RANCH_3, // unused + /* 0x52 */ CS_DEST_LON_LON_RANCH_4, // unused + /* 0x53 */ CS_DEST_LON_LON_RANCH_5, // unused + /* 0x54 */ CS_DEST_LON_LON_RANCH_6, // unused + /* 0x55 */ CS_DEST_LON_LON_RANCH_7, // unused + /* 0x56 */ CS_DEST_LON_LON_RANCH_8, // unused + /* 0x57 */ CS_DEST_LON_LON_RANCH_9, // unused /* 0x58 */ CS_DEST_LON_LON_RANCH_10, // unused /* 0x59 */ CS_DEST_LON_LON_RANCH_11, // unused /* 0x5A */ CS_DEST_LON_LON_RANCH_12, // unused @@ -355,7 +355,6 @@ typedef union CsCmdCam { s32 _words[2]; } CsCmdCam; // size = 0x8 - typedef union CsCmdMisc { struct { /* 0x00 */ u16 type; @@ -421,8 +420,8 @@ typedef union CsCmdTime { /* 0x00 */ u16 unused0; /* 0x02 */ u16 startFrame; /* 0x04 */ u16 endFrame; // unused - /* 0x06 */ u8 hour; - /* 0x07 */ u8 minute; + /* 0x06 */ u8 hour; + /* 0x07 */ u8 minute; }; s32 _words[3]; } CsCmdTime; // size = 0xC @@ -500,22 +499,244 @@ typedef struct CutsceneCameraMove { /* 0x8 */ s16 relativeToPlayer; } CutsceneCameraMove; // size = 0xC +#if ENABLE_CUTSCENE_IMPROVEMENTS + +typedef struct CutsceneScriptEntry { + /* 0x0 */ CutsceneData* script; + /* 0x4 */ s16 nextEntrance; + /* 0x6 */ u8 spawn; + /* 0x7 */ u8 spawnFlags; // See `CS_SPAWN_FLAG_` +} CutsceneScriptEntry; // size = 0x8 + +typedef struct CutsceneEntry { + /* 0x0 */ s16 priority; // Lower means higher priority. -1 means it ignores priority + /* 0x2 */ s16 length; + /* 0x4 */ s16 csCamId; // Index of CsCameraEntry to use. Negative indices use sGlobalCamDataSettings. Indices 0 and + // above use CsCameraEntry from a sceneLayer + /* 0x6 */ s16 scriptIndex; + /* 0x8 */ s16 additionalCsId; + /* 0xA */ u8 endSfx; + /* 0xB */ u8 customValue; // 0 - 99: actor-specific custom value. 100+: spawn. 255: none + /* 0xC */ s16 hudVisibility; + /* 0xE */ u8 endCam; + /* 0xF */ u8 letterboxSize; +} CutsceneEntry; // size = 0x10 + +#define CS_SCRIPT_ID_NONE -1 + +typedef enum CutsceneCamId { + // global (see sGlobalCamDataSettings) + /* -66 */ CS_CAM_ID_GLOBAL_NORMAL4 = -66, // CAM_SET_NORMAL4 (set to -CAM_SET_MAX) + /* -65 */ CS_CAM_ID_GLOBAL_PIVOT_FROM_SIDE, // CAM_SET_PIVOT_FROM_SIDE + /* -64 */ CS_CAM_ID_GLOBAL_DIRECTED_YAW, // CAM_SET_DIRECTED_YAW + /* -63 */ CS_CAM_ID_GLOBAL_DUNGEON2, // CAM_SET_DUNGEON2 + /* -62 */ CS_CAM_ID_GLOBAL_JABU_TENTACLE, // CAM_SET_JABU_TENTACLE + /* -61 */ CS_CAM_ID_GLOBAL_CS_C, // CAM_SET_CS_C + /* -60 */ CS_CAM_ID_GLOBAL_FISHING, // CAM_SET_FISHING + /* -59 */ CS_CAM_ID_GLOBAL_NORMAL2, // CAM_SET_NORMAL2 + /* -58 */ CS_CAM_ID_GLOBAL_PIVOT_VERTICAL, // CAM_SET_PIVOT_VERTICAL + /* -57 */ CS_CAM_ID_GLOBAL_TURN_AROUND, // CAM_SET_TURN_AROUND + /* -56 */ CS_CAM_ID_GLOBAL_FIRE_BIRDS_EYE, // CAM_SET_FIRE_BIRDS_EYE + /* -55 */ CS_CAM_ID_GLOBAL_MEADOW_UNUSED, // CAM_SET_MEADOW_UNUSED + /* -54 */ CS_CAM_ID_GLOBAL_MEADOW_BIRDS_EYE, // CAM_SET_MEADOW_BIRDS_EYE + /* -53 */ CS_CAM_ID_GLOBAL_BIG_OCTO, // CAM_SET_BIG_OCTO + /* -52 */ CS_CAM_ID_GLOBAL_FOREST_DEFEAT_POE, // CAM_SET_FOREST_DEFEAT_POE + /* -51 */ CS_CAM_ID_GLOBAL_FOREST_UNUSED, // CAM_SET_FOREST_UNUSED + /* -50 */ CS_CAM_ID_GLOBAL_FIRE_STAIRCASE, // CAM_SET_FIRE_STAIRCASE + /* -49 */ CS_CAM_ID_GLOBAL_ELEVATOR_PLATFORM, // CAM_SET_ELEVATOR_PLATFORM + /* -48 */ CS_CAM_ID_GLOBAL_SCENE_TRANSITION, // CAM_SET_SCENE_TRANSITION + /* -47 */ CS_CAM_ID_GLOBAL_SCENE_UNUSED, // CAM_SET_SCENE_UNUSED + /* -46 */ CS_CAM_ID_GLOBAL_BEAN_LOST_WOODS, // CAM_SET_BEAN_LOST_WOODS + /* -45 */ CS_CAM_ID_GLOBAL_BEAN_GENERIC, // CAM_SET_BEAN_GENERIC + /* -44 */ CS_CAM_ID_GLOBAL_CS_ATTENTION, // CAM_SET_CS_ATTENTION + /* -43 */ CS_CAM_ID_GLOBAL_CS_3, // CAM_SET_CS_3 + /* -42 */ CS_CAM_ID_GLOBAL_ITEM_UNUSED, // CAM_SET_ITEM_UNUSED + /* -41 */ CS_CAM_ID_GLOBAL_SLOW_CHEST_CS, // CAM_SET_SLOW_CHEST_CS + /* -40 */ CS_CAM_ID_GLOBAL_FOREST_BIRDS_EYE, // CAM_SET_FOREST_BIRDS_EYE + /* -39 */ CS_CAM_ID_GLOBAL_CS_TWISTED_HALLWAY, // CAM_SET_CS_TWISTED_HALLWAY + /* -38 */ CS_CAM_ID_GLOBAL_CS_0, // CAM_SET_CS_0 + /* -37 */ CS_CAM_ID_GLOBAL_PIVOT_WATER_SURFACE, // CAM_SET_PIVOT_WATER_SURFACE + /* -36 */ CS_CAM_ID_GLOBAL_PIVOT_CORNER, // CAM_SET_PIVOT_CORNER + /* -35 */ CS_CAM_ID_GLOBAL_FREE2, // CAM_SET_FREE2 + /* -34 */ CS_CAM_ID_GLOBAL_FREE0, // CAM_SET_FREE0 + /* -33 */ CS_CAM_ID_GLOBAL_START1, // CAM_SET_START1 + /* -32 */ CS_CAM_ID_GLOBAL_START0, // CAM_SET_START0 + /* -31 */ CS_CAM_ID_GLOBAL_CRAWLSPACE, // CAM_SET_CRAWLSPACE + /* -30 */ CS_CAM_ID_GLOBAL_DOORC, // CAM_SET_DOORC + /* -29 */ CS_CAM_ID_GLOBAL_DOOR0, // CAM_SET_DOOR0 + /* -28 */ CS_CAM_ID_GLOBAL_PREREND_SIDE_SCROLL, // CAM_SET_PREREND_SIDE_SCROLL + /* -27 */ CS_CAM_ID_GLOBAL_PREREND_PIVOT, // CAM_SET_PREREND_PIVOT + /* -26 */ CS_CAM_ID_GLOBAL_PREREND_FIXED, // CAM_SET_PREREND_FIXED + /* -25 */ CS_CAM_ID_GLOBAL_PIVOT_IN_FRONT, // CAM_SET_PIVOT_IN_FRONT + /* -24 */ CS_CAM_ID_GLOBAL_PIVOT_SHOP_BROWSING, // CAM_SET_PIVOT_SHOP_BROWSING + /* -23 */ CS_CAM_ID_GLOBAL_PIVOT_CRAWLSPACE, // CAM_SET_PIVOT_CRAWLSPACE + /* -22 */ CS_CAM_ID_GLOBAL_CHU_BOWLING, // CAM_SET_CHU_BOWLING + /* -21 */ CS_CAM_ID_GLOBAL_MARKET_BALCONY, // CAM_SET_MARKET_BALCONY + /* -20 */ CS_CAM_ID_GLOBAL_TOWER_UNUSED, // CAM_SET_TOWER_UNUSED + /* -19 */ CS_CAM_ID_GLOBAL_TOWER_CLIMB, // CAM_SET_TOWER_CLIMB + /* -18 */ CS_CAM_ID_GLOBAL_BOSS_GANON, // CAM_SET_BOSS_GANON + /* -17 */ CS_CAM_ID_GLOBAL_BOSS_GANONDORF, // CAM_SET_BOSS_GANONDORF + /* -16 */ CS_CAM_ID_GLOBAL_BOSS_TWINROVA_FLOOR, // CAM_SET_BOSS_TWINROVA_FLOOR + /* -15 */ CS_CAM_ID_GLOBAL_BOSS_TWINROVA_PLATFORM, // CAM_SET_BOSS_TWINROVA_PLATFORM + /* -14 */ CS_CAM_ID_GLOBAL_BOSS_MORPHA, // CAM_SET_BOSS_MORPHA + /* -13 */ CS_CAM_ID_GLOBAL_BOSS_BONGO, // CAM_SET_BOSS_BONGO + /* -12 */ CS_CAM_ID_GLOBAL_BOSS_VOLVAGIA, // CAM_SET_BOSS_VOLVAGIA + /* -11 */ CS_CAM_ID_GLOBAL_BOSS_PHANTOM_GANON, // CAM_SET_BOSS_PHANTOM_GANON + /* -10 */ CS_CAM_ID_GLOBAL_BOSS_BARINADE, // CAM_SET_BOSS_BARINADE + /* -9 */ CS_CAM_ID_GLOBAL_BOSS_DODONGO, // CAM_SET_BOSS_DODONGO + /* -8 */ CS_CAM_ID_GLOBAL_BOSS_GOHMA, // CAM_SET_BOSS_GOHMA + /* -7 */ CS_CAM_ID_GLOBAL_HORSE, // CAM_SET_HORSE + /* -6 */ CS_CAM_ID_GLOBAL_NORMAL3, // CAM_SET_NORMAL3 + /* -5 */ CS_CAM_ID_GLOBAL_DUNGEON1, // CAM_SET_DUNGEON1 + /* -4 */ CS_CAM_ID_GLOBAL_DUNGEON0, // CAM_SET_DUNGEON0 + /* -3 */ CS_CAM_ID_GLOBAL_NORMAL1, // CAM_SET_NORMAL1 + /* -2 */ CS_CAM_ID_GLOBAL_NORMAL0, // CAM_SET_NORMAL0 + /* -1 */ CS_CAM_ID_NONE, + // CamCsId's 0+ are sceneLayer-specific and index `ActorCsCamInfo` +} CutsceneCamId; + +typedef enum CutsceneHudVisibility { + /* -1 */ CS_HUD_VISIBILITY_ALL_ALT = -1, + /* 0 */ CS_HUD_VISIBILITY_NONE, + /* 1 */ CS_HUD_VISIBILITY_ALL, + /* 2 */ CS_HUD_VISIBILITY_A_HEARTS_MAGIC, + /* 3 */ CS_HUD_VISIBILITY_C_HEARTS_MAGIC, + /* 4 */ CS_HUD_VISIBILITY_ALL_NO_MINIMAP, + /* 5 */ CS_HUD_VISIBILITY_A_B_C, + /* 6 */ CS_HUD_VISIBILITY_B_MINIMAP, + /* 7 */ CS_HUD_VISIBILITY_A +} CutsceneHudVisibility; + +typedef enum CutsceneEndSfx { + /* 0 */ CS_END_SFX_NONE, + /* 1 */ CS_END_SFX_TRE_BOX_APPEAR, + /* 2 */ CS_END_SFX_CORRECT_CHIME, + /* 255 */ CS_END_SFX_NONE_ALT = 0xFF +} CutsceneEndSfx; + +typedef enum CutsceneEndCam { + /* 0 */ CS_END_CAM_0, + /* 1 */ CS_END_CAM_1, + /* 2 */ CS_END_CAM_SMOOTH +} CutsceneEndCam; + +typedef enum CutsceneId { + /* -1 */ CS_ID_NONE = -1, + // CsId's 0 - 119 are sceneLayer-specific and index `CutsceneEntry` + /* 0x78 */ CS_ID_GLOBAL_78 = 120, + /* 0x79 */ CS_ID_GLOBAL_79, + /* 0x7A */ CS_ID_GLOBAL_7A, + /* 0x7C */ CS_ID_GLOBAL_TALK, + /* 0x7D */ CS_ID_GLOBAL_DOOR, + /* 0x7F */ CS_ID_GLOBAL_END = 0x7F +} CutsceneId; + +typedef struct { + /* 0x0 */ s16 numEntries; + /* 0x2 */ s16 unk_02; // unused + /* 0x4 */ s16 unk_04; // unused + /* 0x6 */ s16 duration; // total duration +} CsCmdCamSpline; // size = 0x8 + +// Both camAt and camEye +typedef struct { + /* 0x0 */ u8 interpType; // see `CutsceneCamInterpType` + /* 0x1 */ u8 weight; // for certain types of interpTypes, shifts the weight to certain points. Default is 100. + /* 0x2 */ s16 duration; // duration of current point + /* 0x4 */ Vec3s pos; + /* 0xA */ s16 relativeTo; // see `CutsceneCamRelativeTo` +} CsCmdCamPoint; // size = 0xC + +typedef enum CutsceneCamInterpType { + /* 0 */ CS_CAM_INTERP_NONE, // values do not change. + // values 1-3 only uses a single point from the cmd + /* 1 */ CS_CAM_INTERP_SET, // values immediately set to cmd values. + /* 2 */ CS_CAM_INTERP_LINEAR, // Lerp to the target position + /* 3 */ CS_CAM_INTERP_SCALE, // Step to the target position in increments scaled by the remaining distance + // values 4-5 uses multiple points from the cmd + /* 4 */ CS_CAM_INTERP_MP_CUBIC, // cubic multi-point (identical to SM64/OoT) + /* 5 */ CS_CAM_INTERP_MP_QUAD, // quadratic multi-point + // value 6 only uses a single point from the cmd + /* 6 */ CS_CAM_INTERP_GEO, // does VecGeo calculations using fov + /* 7 */ CS_CAM_INTERP_OFF // interpolation is not processed. +} CutsceneCamInterpType; + +typedef enum CutsceneCamRelativeTo { + /* 0 */ CS_CAM_REL_0, + /* 1 */ CS_CAM_REL_1, + /* 2 */ CS_CAM_REL_2, + /* 3 */ CS_CAM_REL_3, + /* 4 */ CS_CAM_REL_4, + /* 5 */ CS_CAM_REL_5 +} CutsceneCamRelativeTo; + +// Roll and Fov Data +typedef struct CsCmdCamMisc { + /* 0x0 */ s16 unused0; // used only in the unused interp function + /* 0x2 */ s16 roll; + /* 0x4 */ s16 fov; + /* 0x6 */ s16 unused1; // unused +} CsCmdCamMisc; // size = 0x8 + +typedef struct CutsceneCameraInterp { + /* 0x00 */ Vec3f curPos; + /* 0x0C */ Vec3f initPos; + /* 0x18 */ f32 initFov; + /* 0x1C */ f32 initRoll; + /* 0x2A */ f32 unk_20; // position adjustment based on fov? + /* 0x24 */ s16 curFrame; + /* 0x26 */ s16 waypoint; + /* 0x28 */ s16 duration; + /* 0x2A */ s16 numEntries; + /* 0x1E */ u8 curPoint; + /* 0x2D */ u8 type; // See `CutsceneCamInterpType` +} CutsceneCameraInterp; // size = 0x30 + +typedef struct CutsceneCamera { + /* 0x00 */ s16 splineIndex; + /* 0x02 */ s16 cmdIndex; + /* 0x04 */ s16 splineNeedsInit; + /* 0x06 */ s16 state; + /* 0x08 */ s16 nextSplineTimer; + /* 0x0A */ s16 updateSplineTimer; + /* 0x0C */ s16 duration; // Duration of the current spline + /* 0x10 */ CutsceneCameraInterp eyeInterp; + /* 0x40 */ CutsceneCameraInterp atInterp; + /* 0x70 */ CsCmdCamPoint* atCmd; + /* 0x74 */ CsCmdCamPoint* eyeCmd; + /* 0x78 */ CsCmdCamMisc* miscCmd; + /* 0x7C */ struct Camera* camera; +} CutsceneCamera; // size = 0x80 + +typedef enum { + /* 0 */ CS_CAM_STATE_UPDATE_ALL, // Update spline and next spline timer + /* 1 */ CS_CAM_STATE_UPDATE_SPLINE, // Update spline, do not advance next spline timer + /* 2 */ CS_CAM_STATE_PAUSE, // No updates + /* 3 */ CS_CAM_STATE_DONE_SPLINE, // Finished the current spline, ready for the next one + /* 999 */ CS_CAM_STATE_DONE = 999 // Finished all the splines. +} CutsceneCameraState; + +#endif + typedef struct CutsceneContext { - /* 0x00 */ char unk_00[0x4]; - /* 0x04 */ void* script; + /* 0x00 */ u8 scriptListCount; + /* 0x04 */ CutsceneData* script; /* 0x08 */ u8 state; /* 0x0C */ f32 timer; /* 0x10 */ u16 curFrame; // current frame of the script that is running - /* 0x12 */ u16 unk_12; // set but never used + /* 0x12 */ u16 scriptIndex; /* 0x14 */ s32 subCamId; /* 0x18 */ u16 camEyeSplinePointsAppliedFrame; // stores the frame the cam eye spline points data was last applied on - /* 0x1A */ u8 camAtReady; // cam `at` data is ready to be applied - /* 0x1B */ u8 camEyeReady; // cam `eye` data is ready to be applied + /* 0x1A */ u8 camAtReady; // cam `at` data is ready to be applied + /* 0x1B */ u8 camEyeReady; // cam `eye` data is ready to be applied /* 0x1C */ CutsceneCameraPoint* camAtPoints; /* 0x20 */ CutsceneCameraPoint* camEyePoints; /* 0x24 */ CsCmdActorCue* playerCue; /* 0x28 */ CsCmdActorCue* actorCues[10]; // "npcdemopnt" /* 0x38 */ u16 originalBlurAlpha; +#if ENABLE_CUTSCENE_IMPROVEMENTS + CutsceneScriptEntry* scriptList; +#endif } CutsceneContext; // size = 0x50 typedef union { @@ -541,5 +762,38 @@ void Cutscene_UpdateScripted(struct PlayState* play, CutsceneContext* csCtx); void Cutscene_HandleEntranceTriggers(struct PlayState* play); void Cutscene_HandleConditionalTriggers(struct PlayState* play); void Cutscene_SetScript(struct PlayState* play, void* script); +void Cutscene_StartScripted(struct PlayState* play, u8 scriptIndex); + +#if ENABLE_CUTSCENE_IMPROVEMENTS +struct Camera; +struct Actor; + +void CutsceneManager_Init(struct PlayState* play, CutsceneEntry* cutsceneList, s16 numEntries); +void CutsceneManager_StoreCamera(struct Camera* camera); +void CutsceneManager_ClearWaiting(void); +s16 CutsceneManager_Update(void); +void CutsceneManager_Queue(s16 csId); +s16 CutsceneManager_IsNext(s16 csId); +s16 CutsceneManager_StartWithPlayerCs(s16 csId, struct Actor* actor); +s16 CutsceneManager_StartWithPlayerCsAndSetFlag(s16 csId, struct Actor* actor); +s16 CutsceneManager_Start(s16 csId, struct Actor* actor); +s16 CutsceneManager_Stop(s16 csId); +s16 CutsceneManager_GetCurrentCsId(void); +CutsceneEntry* CutsceneManager_GetCutsceneEntry(s16 csId); +s16 CutsceneManager_GetAdditionalCsId(s16 csId); +s16 CutsceneManager_GetLength(s16 csId); +s16 CutsceneManager_GetCutsceneScriptIndex(s16 csId); +s16 CutsceneManager_GetCutsceneCustomValue(s16 csId); +s16 CutsceneManager_GetCurrentSubCamId(s16 csId); +s16 CutsceneManager_FindEntranceCsId(void); +s32 CutsceneManager_800F22C4(s16 csId, struct Actor* actor); +void CutsceneManager_SetReturnCamera(s16 camId); +s16 CutsceneManager_MarkNextCutscenes(void); + +s32 CutsceneCamera_Init(struct Camera* camera, CutsceneCamera* csCamera); +s32 CutsceneCamera_UpdateSplines(u8* script, CutsceneCamera* csCamera); +void CutsceneCamera_SetState(s16 state); +void CutsceneCamera_Reset(void); +#endif #endif diff --git a/include/z64olib.h b/include/z64olib.h index 1b704b0e69..8c34199a6c 100644 --- a/include/z64olib.h +++ b/include/z64olib.h @@ -3,6 +3,19 @@ #include "z64math.h" +// To be used with OLib_Vec3fAdd() +typedef enum { + /* 0 */ OLIB_ADD_COPY, // Copy `b` to dest + /* 1 */ OLIB_ADD_OFFSET, // Add `a` and `b` to dest, and also add the yaw of `a` to the dest + /* 2 */ OLIB_ADD // Add `a` and `b` to dest +} OlibVec3fAdd; + +typedef enum { + /* 0 */ OLIB_DIFF_COPY, // Copy `b` to dest + /* 1 */ OLIB_DIFF_OFFSET, // Sub `a` and `b` to dest, and also subs the yaw of `a` to the dest + /* 2 */ OLIB_DIFF // Sub `a` and `b` to dest +} OlibVec3fDiff; + f32 OLib_Vec3fDist(Vec3f* a, Vec3f* b); f32 OLib_Vec3fDistXZ(Vec3f* a, Vec3f* b); f32 OLib_ClampMinDist(f32 val, f32 min); @@ -14,4 +27,8 @@ VecGeo OLib_Vec3fToVecGeo(Vec3f* vec); VecGeo OLib_Vec3fDiffToVecGeo(Vec3f* a, Vec3f* b); Vec3f OLib_Vec3fDiffRad(Vec3f* a, Vec3f* b); +Vec3f OLib_AddVecGeoToVec3f(Vec3f* a, VecGeo* geo); +void OLib_Vec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); +void OLib_Vec3fAdd(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); + #endif diff --git a/include/z64play.h b/include/z64play.h index 6a36fa1ed1..c8d7defe7e 100644 --- a/include/z64play.h +++ b/include/z64play.h @@ -113,6 +113,9 @@ typedef struct PlayState { #if ENABLE_ANIMATED_MATERIALS AnimatedMaterial* sceneMaterialAnims; #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + ActorCsCamInfo* actorCsCamList; +#endif } PlayState; // size = 0x12518 #define GET_ACTIVE_CAM(play) ((play)->cameraPtrs[(play)->activeCamId]) @@ -149,6 +152,11 @@ void Play_TriggerVoidOut(PlayState* this); void Play_TriggerRespawn(PlayState* this); int Play_CamIsNotFixed(PlayState* this); +#if ENABLE_CUTSCENE_IMPROVEMENTS +u16 Play_GetActorCsCamSetting(PlayState* this, s32 csCamDataIndex); +Vec3s* Play_GetActorCsCamFuncData(PlayState* this, s32 csCamDataIndex); +#endif + #if DEBUG_FEATURES extern void* gDebugCutsceneScript; #endif diff --git a/include/z64save.h b/include/z64save.h index c5eac00270..d36a93cd14 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -36,6 +36,15 @@ typedef enum HudVisibilityMode { /* 11 */ HUD_VISIBILITY_HEARTS, /* 12 */ HUD_VISIBILITY_A_B_MINIMAP, /* 13 */ HUD_VISIBILITY_HEARTS_MAGIC_FORCE, // See above + /* 14 */ HUD_VISIBILITY_HEARTS_MAGIC_C, + /* 15 */ HUD_VISIBILITY_ALL_NO_MINIMAP, + /* 16 */ HUD_VISIBILITY_A_B_C, + /* 17 */ HUD_VISIBILITY_B_MINIMAP, + /* 18 */ HUD_VISIBILITY_HEARTS_MAGIC_MINIMAP, + /* 19 */ HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP, + /* 20 */ HUD_VISIBILITY_B_MAGIC, + /* 21 */ HUD_VISIBILITY_A_B, + /* 22 */ HUD_VISIBILITY_A_B_HEARTS_MAGIC_MINIMAP, /* 50 */ HUD_VISIBILITY_ALL = 50, // Only raises button alphas if not disabled /* 52 */ HUD_VISIBILITY_NOTHING_INSTANT = 52 } HudVisibilityMode; diff --git a/include/z64scene.h b/include/z64scene.h index 6008195407..98581a23d2 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -398,6 +398,26 @@ typedef struct { } SCmdTextureAnimations; // size = 0x8 #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS +typedef struct { + /* 0x0 */ u8 code; + /* 0x1 */ u8 data1; + /* 0x4 */ void* segment; +} SCmdCsCameraList; // size = 0x8 + +typedef struct { + /* 0x0 */ u8 code; + /* 0x1 */ u8 num; + /* 0x4 */ void* segment; +} SCmdCutsceneList; // size = 0x8 + +typedef struct { + /* 0x0 */ s16 setting; // camera setting described by CameraSettingType enum + /* 0x2 */ s16 count; + /* 0x4 */ Vec3s* actorCsCamFuncData; // s16 data grouped in threes +} ActorCsCamInfo; // size = 0x8 +#endif + typedef union SceneCmd { SCmdBase base; SCmdPlayerEntryList playerEntryList; @@ -431,6 +451,10 @@ typedef union SceneCmd { #if ENABLE_ANIMATED_MATERIALS SCmdTextureAnimations textureAnimations; #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCmdCsCameraList actorCsCamList; + SCmdCutsceneList cutsceneList; +#endif } SceneCmd; // size = 0x8 typedef BAD_RETURN(s32) (*SceneCmdHandlerFunc)(struct PlayState*, SceneCmd*); @@ -614,6 +638,10 @@ typedef enum SceneCommandTypeID { #endif #if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, +#endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCENE_CMD_ID_ACTOR_CUTSCENE_LIST, + SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST, #endif /* 0x1A */ SCENE_CMD_ID_MAX } SceneCommandTypeID; @@ -707,6 +735,15 @@ typedef enum SceneCommandTypeID { { SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, 0, CMD_PTR(matAnimList) } #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS +#define SCENE_CMD_ACTOR_CUTSCENE_LIST(numEntries, actorCutsceneList) \ + { SCENE_CMD_ID_ACTOR_CUTSCENE_LIST, numEntries, CMD_PTR(actorCutsceneList) } + +#define SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(numCams, camList) \ + { SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST, numCams, CMD_PTR(camList) } + +#endif + s32 Scene_ExecuteCommands(struct PlayState* play, SceneCmd* sceneCmd); void Scene_ResetTransitionActorList(struct GameState* state, TransitionActorList* transitionActors); diff --git a/include/z_lib.h b/include/z_lib.h index 34581da982..a16454293a 100644 --- a/include/z_lib.h +++ b/include/z_lib.h @@ -41,4 +41,8 @@ void Sfx_PlaySfxCentered(u16 sfxId); void Sfx_PlaySfxCentered2(u16 sfxId); void Sfx_PlaySfxAtPos(Vec3f* projectedPos, u16 sfxId); +s32 Math_StepToIImpl(s32 start, s32 target, s32 step); +void Math_StepToIGet(s32* pValue, s32 target, s32 step); +s32 Math_StepToI(s32* pValue, s32 target, s32 step); + #endif diff --git a/spec b/spec index 28b254d29a..b2c1c93071 100644 --- a/spec +++ b/spec @@ -963,7 +963,13 @@ beginseg #endif include "$(BUILD_DIR)/src/code/rainbow.o" include "$(BUILD_DIR)/src/code/helpers.o" +#if ENABLE_ANIMATED_MATERIALS include "$(BUILD_DIR)/src/code/animated_materials.o" +#endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + include "$(BUILD_DIR)/src/code/cutscene_camera.o" + include "$(BUILD_DIR)/src/code/cutscene_manager.o" +#endif endseg #if ENABLE_HACKER_DEBUG @@ -19779,3 +19785,22 @@ beginseg number 3 endseg #endif + +beginseg + name "debug1_scene" + compress + romalign 0x1000 + include "$(BUILD_DIR)/assets/scenes/debug1/debug1_scene_main.o" + include "$(BUILD_DIR)/assets/scenes/debug1/debug1_scene_col.o" + number 2 +endseg + +beginseg + name "debug1_room_0" + compress + romalign 0x1000 + include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_main.o" + include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_model_info.o" + include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_model.o" + number 3 +endseg diff --git a/src/code/cutscene_camera.c b/src/code/cutscene_camera.c new file mode 100644 index 0000000000..30e50d2689 --- /dev/null +++ b/src/code/cutscene_camera.c @@ -0,0 +1,933 @@ +#include "global.h" +#include "string.h" +#include "z64olib.h" +#include "config.h" + +#if ENABLE_CUTSCENE_IMPROVEMENTS + +CutsceneCamera* sCurCsCamera; + +typedef s16 (*CsCamInterpolateCallback)(Vec3f*, f32*, s16*, CsCmdCamPoint*, CsCmdCamMisc*, CutsceneCameraInterp*); + +s16 CutsceneCamera_Interp_Off(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_None(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_MultiPointQuadratic(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_MultiPointCubic(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_Set(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_Linear(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_Scale(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_Geo(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState); +s16 CutsceneCamera_Interp_Unused(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState); + +f32 func_80163660(Actor* actor); + +s16 CutsceneCamera_Interp_Off(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState) { + return 0; +} + +/** + * 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; + + memset(&csCamera->eyeInterp, 0, sizeof(CutsceneCameraInterp)); + memset(&csCamera->atInterp, 0, sizeof(CutsceneCameraInterp)); + + csCamera->eyeInterp.type = csCamera->atInterp.type = CS_CAM_INTERP_OFF; + + return 1; +} + +CsCamInterpolateCallback CutsceneCamera_Interpolate(u8 interpType) { + switch (interpType) { + case CS_CAM_INTERP_OFF: + default: + return CutsceneCamera_Interp_Off; + + case CS_CAM_INTERP_NONE: + return CutsceneCamera_Interp_None; + + case CS_CAM_INTERP_MP_QUAD: + return CutsceneCamera_Interp_MultiPointQuadratic; + + case CS_CAM_INTERP_MP_CUBIC: + return CutsceneCamera_Interp_MultiPointCubic; + + case CS_CAM_INTERP_SET: + return CutsceneCamera_Interp_Set; + + case CS_CAM_INTERP_LINEAR: + return CutsceneCamera_Interp_Linear; + + case CS_CAM_INTERP_SCALE: + return CutsceneCamera_Interp_Scale; + + case CS_CAM_INTERP_GEO: + return CutsceneCamera_Interp_Geo; + } +} + +u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { + s32 sp5C; + f32* camFov; + s16* camRoll; + 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.curPos = csCamera->camera->eye; + csCamera->atInterp.curPos = csCamera->camera->at; + + if (sp5C) { + camFov = NULL; + } else { + camFov = &csCamera->camera->fov; + } + + if (sp5C) { + camRoll = NULL; + } else { + camRoll = &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_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF); + break; + + case CS_CAM_REL_3: + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_1: + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_4: + OLib_Vec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_5: + OLib_Vec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF); + break; + + default: // CS_CAM_REL_0 + break; + } + + numPoints = interpHandler(&csCamera->camera->at, camFov, camRoll, &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_Vec3fAdd(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD); + break; + + case CS_CAM_REL_3: + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD_OFFSET); + csCamera->camera->at.y += func_80163660(&player->actor); + break; + + case CS_CAM_REL_1: + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD_OFFSET); + break; + + case CS_CAM_REL_4: + OLib_Vec3fAdd(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD_OFFSET); + break; + + case CS_CAM_REL_5: + OLib_Vec3fAdd(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD); + break; + + default: // CS_CAM_REL_0 + break; + } + + csCamera->eyeInterp.curPoint += numPoints; + + if (sp5C) { + camFov = &csCamera->camera->fov; + } else { + camFov = NULL; + } + + if (sp5C) { + camRoll = &csCamera->camera->roll; + } else { + camRoll = NULL; + } + + interpHandler = CutsceneCamera_Interpolate(csCamera->eyeCmd[csCamera->atInterp.curPoint].interpType); + + switch (csCamera->eyeCmd[csCamera->atInterp.curPoint].relativeTo) { + case CS_CAM_REL_2: + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF); + break; + + case CS_CAM_REL_3: + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_1: + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_4: + OLib_Vec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); + break; + + case CS_CAM_REL_5: + OLib_Vec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF); + break; + + default: // CS_CAM_REL_0 + break; + } + + numPoints = interpHandler(&csCamera->camera->eye, camFov, camRoll, &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_Vec3fAdd(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD); + break; + + case CS_CAM_REL_3: + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD_OFFSET); + csCamera->camera->eye.y += func_80163660(&player->actor); + break; + + case CS_CAM_REL_1: + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD_OFFSET); + break; + + case CS_CAM_REL_4: + OLib_Vec3fAdd(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD_OFFSET); + break; + + case CS_CAM_REL_5: + OLib_Vec3fAdd(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD); + 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.type = csCamera->atInterp.type = CS_CAM_INTERP_OFF; + } + + 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; +} + +// Linear interpolation from initial values to cmd values. Set weight to 100 to go all the way to the cmd value. +s16 CutsceneCamera_Interp_Linear(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState) { + f32 lerp; + + if (interpState->type != CS_CAM_INTERP_LINEAR) { + // Initialize + interpState->type = CS_CAM_INTERP_LINEAR; + interpState->waypoint = 0; + interpState->curFrame = 0; + interpState->duration = 1; + if (camPos != NULL) { + interpState->initPos.x = camPos->x; + interpState->initPos.y = camPos->y; + interpState->initPos.z = camPos->z; + } + + if (camFov != NULL) { + interpState->initFov = *camFov; + } + + if (camRoll != NULL) { + interpState->initRoll = *camRoll; + } + } + + interpState->curFrame++; + + lerp = ((f32)interpState->curFrame / pointCmd->duration) * (pointCmd->weight / 100.0f); + + if (camPos != NULL) { + VEC3F_LERPIMPDST(camPos, &interpState->initPos, &pointCmd->pos, lerp); + } + + if (camFov != NULL) { + *camFov = F32_LERPIMP(interpState->initFov, miscCmd->fov, lerp); + } + + if (camRoll != NULL) { + s16 targetRoll; + s16 rollDiffToTarget; + + targetRoll = CAM_DEG_TO_BINANG(miscCmd->roll); + + rollDiffToTarget = (s16)(targetRoll - TRUNCF_BINANG(interpState->initRoll)); + + *camRoll = TRUNCF_BINANG(interpState->initRoll) + TRUNCF_BINANG(rollDiffToTarget * lerp); + } + + if (interpState->curFrame >= pointCmd->duration) { + // Finished + interpState->type = CS_CAM_INTERP_OFF; + return 1; + } + + return 0; +} + +s16 CutsceneCamera_Interp_Scale(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState) { + f32 lerp; + f32 tmp1; + f32 tmp2; + + if (interpState->type != CS_CAM_INTERP_SCALE) { + // Initialize + interpState->type = CS_CAM_INTERP_SCALE; + interpState->waypoint = 0; + interpState->curFrame = 0; + interpState->duration = 1; + if (camPos != NULL) { + interpState->initPos.x = camPos->x; + interpState->initPos.y = camPos->y; + interpState->initPos.z = camPos->z; + } + if (camFov != NULL) { + interpState->initFov = *camFov; + } + if (camRoll != NULL) { + interpState->initRoll = *camRoll; + } + } + + tmp2 = (((pointCmd->weight + 100) * (pointCmd->duration / 2)) + + (((pointCmd->weight + 100) / 2) * (pointCmd->duration & 1))); + if (pointCmd->duration < 2) { + lerp = 1.0f; + } else { + tmp1 = (f32)(pointCmd->weight - 100) / (pointCmd->duration - 1); + lerp = ((interpState->curFrame * tmp1) + 100.0f) / tmp2; + } + + interpState->curFrame++; + + if (camPos != NULL) { + camPos->x += (pointCmd->pos.x - interpState->initPos.x) * lerp; + camPos->y += (pointCmd->pos.y - interpState->initPos.y) * lerp; + camPos->z += (pointCmd->pos.z - interpState->initPos.z) * lerp; + } + + if (camFov != NULL) { + *camFov += (miscCmd->fov - interpState->initFov) * lerp; + } + + if (camRoll != NULL) { + s16 targetRoll; + s16 rollDiffToTarget; + + targetRoll = CAM_DEG_TO_BINANG(miscCmd->roll); + + rollDiffToTarget = (s16)(targetRoll - TRUNCF_BINANG(interpState->initRoll)); + + *camRoll += TRUNCF_BINANG(rollDiffToTarget * lerp); + } + + if (interpState->curFrame >= pointCmd->duration) { + // Finished + interpState->type = CS_CAM_INTERP_OFF; + return 1; + } + + return 0; +} + +s16 CutsceneCamera_Interp_Geo(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState) { + VecGeo sp40; + f32 lerp; + f32 tmp1; + f32 tmp2; + + if (interpState->type != CS_CAM_INTERP_GEO) { + // Initialize + interpState->type = CS_CAM_INTERP_GEO; + interpState->waypoint = 0; + interpState->curFrame = 0; + interpState->duration = 1; + if (camPos != NULL) { + interpState->unk_20 = OLib_Vec3fDist(&interpState->curPos, camPos) * Math_FTanF(DEG_TO_RAD(*camFov)); + } + if (camFov != NULL) { + interpState->initFov = *camFov; + } + if (camRoll != NULL) { + interpState->initRoll = *camRoll; + } + } + + tmp2 = (((pointCmd->weight + 100) * (pointCmd->duration / 2)) + + (((pointCmd->weight + 100) / 2) * (pointCmd->duration & 1))); + if (pointCmd->duration < 2) { + lerp = 1.0f; + } else { + tmp1 = (f32)(pointCmd->weight - 100) / (pointCmd->duration - 1); + lerp = ((interpState->curFrame * tmp1) + 100.0f) / tmp2; + } + + interpState->curFrame++; + + if (camPos != NULL) { + sp40 = OLib_Vec3fDiffToVecGeo(&interpState->curPos, camPos); + sp40.r = interpState->unk_20 / Math_FTanF(DEG_TO_RAD(*camFov)); + *camPos = OLib_AddVecGeoToVec3f(&interpState->curPos, &sp40); + } + + if (camFov != NULL) { + *camFov += (miscCmd->fov - interpState->initFov) * lerp; + } + + if (camRoll != NULL) { + s16 targetRoll; + s16 rollDiffToTarget; + + targetRoll = CAM_DEG_TO_BINANG(miscCmd->roll); + + rollDiffToTarget = (s16)(targetRoll - TRUNCF_BINANG(interpState->initRoll)); + + *camRoll += TRUNCF_BINANG(rollDiffToTarget * lerp); + } + + if (interpState->curFrame >= pointCmd->duration) { + // Finished + interpState->type = CS_CAM_INTERP_OFF; + return 1; + } + + return 0; +} + +// Updates the interpolation state but does not change the pos/fov/roll values +s16 CutsceneCamera_Interp_None(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState) { + if (interpState->type != CS_CAM_INTERP_NONE) { + // Initialize + interpState->type = CS_CAM_INTERP_NONE; + interpState->waypoint = 0; + interpState->curFrame = 0; + interpState->duration = 1; + } + + interpState->curFrame++; + + if (interpState->curFrame >= pointCmd->duration) { + // Finishes + interpState->type = CS_CAM_INTERP_OFF; + return 1; + } + + return 0; +} + +// Immediately sets the values +s16 CutsceneCamera_Interp_Set(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, CsCmdCamMisc* miscCmd, + CutsceneCameraInterp* interpState) { + s16 pad; + + if (interpState->type != CS_CAM_INTERP_SET) { + // Initialize + interpState->type = CS_CAM_INTERP_SET; + interpState->waypoint = 0; + interpState->curFrame = 0; + interpState->duration = 1; + if (camFov != NULL) { + *camFov = miscCmd->fov; + } + if (camRoll != NULL) { + *camRoll = CAM_DEG_TO_BINANG(miscCmd->roll); + } + } + + if (camPos != NULL) { + camPos->x = pointCmd->pos.x; + camPos->y = pointCmd->pos.y; + camPos->z = pointCmd->pos.z; + } + + interpState->curFrame++; + + if (interpState->curFrame >= pointCmd->duration) { + // Finished + interpState->type = CS_CAM_INTERP_OFF; + return 1; + } + + return 0; +} + +void func_801624EC(f32 u, f32* coeff) { + f32 u1 = 1.0f - u; + + coeff[0] = u1 * u1 * 0.5f; + coeff[1] = u * u1 + 0.5f; + coeff[2] = u * u * 0.5f; +} + +s16 CutsceneCamera_Interp_MultiPointQuadratic(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState) { + f32 new_var; + f32 coeff[3]; + s32 waypoints[3]; + + if (interpState->type != CS_CAM_INTERP_MP_QUAD) { + // Initialize + interpState->type = CS_CAM_INTERP_MP_QUAD; + interpState->waypoint = 0; + interpState->duration = pointCmd->duration; + interpState->curFrame = 0; + } + + new_var = (f32)interpState->curFrame / pointCmd[interpState->waypoint + 1].duration; + + if (interpState->waypoint < (interpState->duration - 1)) { + waypoints[0] = interpState->waypoint; + } else { + waypoints[0] = interpState->duration - 1; + } + + if ((interpState->waypoint + 1) < (interpState->duration - 1)) { + waypoints[1] = interpState->waypoint + 1; + } else { + waypoints[1] = interpState->duration - 1; + } + + if ((interpState->waypoint + 2) < (interpState->duration - 1)) { + waypoints[2] = interpState->waypoint + 2; + } else { + waypoints[2] = interpState->duration - 1; + } + + func_801624EC(new_var, coeff); + + if (camPos != NULL) { + camPos->x = (coeff[0] * pointCmd[waypoints[0]].pos.x) + (coeff[1] * pointCmd[waypoints[1]].pos.x) + + (coeff[2] * pointCmd[waypoints[2]].pos.x); + camPos->y = (coeff[0] * pointCmd[waypoints[0]].pos.y) + (coeff[1] * pointCmd[waypoints[1]].pos.y) + + (coeff[2] * pointCmd[waypoints[2]].pos.y); + camPos->z = (coeff[0] * pointCmd[waypoints[0]].pos.z) + (coeff[1] * pointCmd[waypoints[1]].pos.z) + + (coeff[2] * pointCmd[waypoints[2]].pos.z); + } + + if (camFov != NULL) { + *camFov = (coeff[0] * miscCmd[waypoints[0]].fov) + (coeff[1] * miscCmd[waypoints[1]].fov) + + (coeff[2] * miscCmd[waypoints[2]].fov); + } + + if (camRoll != NULL) { + s16 targetRolls[3]; + s32 sp28[2]; + s32 rollDiffToTarget; + + targetRolls[0] = CAM_DEG_TO_BINANG(miscCmd[waypoints[0]].roll); + targetRolls[1] = CAM_DEG_TO_BINANG(miscCmd[waypoints[1]].roll); + targetRolls[2] = CAM_DEG_TO_BINANG(miscCmd[waypoints[2]].roll); + + sp28[0] = (s16)(targetRolls[1] - targetRolls[0]); + sp28[1] = sp28[0] + (s16)(targetRolls[2] - targetRolls[1]); + + rollDiffToTarget = ((coeff[1] * sp28[0]) + (coeff[2] * sp28[1])); + *camRoll = targetRolls[0] + rollDiffToTarget; + } + + interpState->curFrame++; + + if (interpState->curFrame == pointCmd[interpState->waypoint + 1].duration) { + interpState->waypoint++; + interpState->curFrame = 0; + if (interpState->waypoint >= (interpState->duration - 2)) { + interpState->type = CS_CAM_INTERP_OFF; + return interpState->duration; + } + } + return 0; +} + +/** + * This code is very similar to the spline system in OoT's func_800BB0A0 + * in that it is based on the Super Mario 64 cutscene camera movement + */ +void func_801629BC(f32 u, f32* coeff) { + coeff[0] = (1.0f - u) * (1.0f - u) * (1.0f - u) * (1.0f / 6.0f); + coeff[1] = ((u * u * u * 0.5f) - u * u) + (2.0f / 3.0f); + coeff[2] = (u * u * u * -0.5f) + (u * u * 0.5f) + (u * 0.5f) + (1.0f / 6.0f); + coeff[3] = u * u * u * (1.0f / 6.0f); +} + +s16 CutsceneCamera_Interp_MultiPointCubic(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState) { + f32 new_var; + f32 coeff[4]; + s32 waypoints[4]; + + if (interpState->type != CS_CAM_INTERP_MP_CUBIC) { + // Initialize + interpState->type = CS_CAM_INTERP_MP_CUBIC; + interpState->waypoint = 0; + interpState->duration = pointCmd->duration; + interpState->curFrame = 0; + } + + new_var = (f32)interpState->curFrame / pointCmd[interpState->waypoint + 1].duration; + + if (interpState->waypoint < (interpState->duration - 1)) { + waypoints[0] = interpState->waypoint; + } else { + waypoints[0] = interpState->duration - 1; + } + + if ((interpState->waypoint + 1) < (interpState->duration - 1)) { + waypoints[1] = interpState->waypoint + 1; + } else { + waypoints[1] = interpState->duration - 1; + } + + if ((interpState->waypoint + 2) < (interpState->duration - 1)) { + waypoints[2] = interpState->waypoint + 2; + } else { + waypoints[2] = interpState->duration - 1; + } + + if ((interpState->waypoint + 3) < (interpState->duration - 1)) { + waypoints[3] = interpState->waypoint + 3; + } else { + waypoints[3] = interpState->duration - 1; + } + + func_801629BC(new_var, coeff); + + if (camPos != NULL) { + camPos->x = (coeff[0] * pointCmd[waypoints[0]].pos.x) + (coeff[1] * pointCmd[waypoints[1]].pos.x) + + (coeff[2] * pointCmd[waypoints[2]].pos.x) + (coeff[3] * pointCmd[waypoints[3]].pos.x); + camPos->y = (coeff[0] * pointCmd[waypoints[0]].pos.y) + (coeff[1] * pointCmd[waypoints[1]].pos.y) + + (coeff[2] * pointCmd[waypoints[2]].pos.y) + (coeff[3] * pointCmd[waypoints[3]].pos.y); + camPos->z = (coeff[0] * pointCmd[waypoints[0]].pos.z) + (coeff[1] * pointCmd[waypoints[1]].pos.z) + + (coeff[2] * pointCmd[waypoints[2]].pos.z) + (coeff[3] * pointCmd[waypoints[3]].pos.z); + } + + if (camFov != NULL) { + *camFov = (coeff[0] * miscCmd[waypoints[0]].fov) + (coeff[1] * miscCmd[waypoints[1]].fov) + + (coeff[2] * miscCmd[waypoints[2]].fov) + (coeff[3] * miscCmd[waypoints[3]].fov); + } + + if (camRoll != NULL) { + s16 targetRolls[4]; + s32 sp2C[3]; + s32 rollDiffToTarget; + + targetRolls[0] = CAM_DEG_TO_BINANG(miscCmd[waypoints[0]].roll); + targetRolls[1] = CAM_DEG_TO_BINANG(miscCmd[waypoints[1]].roll); + targetRolls[2] = CAM_DEG_TO_BINANG(miscCmd[waypoints[2]].roll); + targetRolls[3] = CAM_DEG_TO_BINANG(miscCmd[waypoints[3]].roll); + + sp2C[0] = (s16)(targetRolls[1] - targetRolls[0]); + sp2C[1] = sp2C[0] + (s16)(targetRolls[2] - targetRolls[1]); + sp2C[2] = sp2C[1] + (s16)(targetRolls[3] - targetRolls[2]); + + rollDiffToTarget = ((coeff[1] * sp2C[0]) + (coeff[2] * sp2C[1]) + (coeff[3] * sp2C[2])); + *camRoll = targetRolls[0] + rollDiffToTarget; + } + + interpState->curFrame++; + + if (interpState->curFrame == pointCmd[interpState->waypoint + 1].duration) { + interpState->curFrame = 0; + interpState->waypoint++; + if (interpState->waypoint >= (interpState->duration - 3)) { + interpState->type = CS_CAM_INTERP_OFF; + return interpState->duration; + } + } + return 0; +} + +f32 sCsCamKnots[38]; + +// Only used by unused CutsceneCamera_Interp_Unused +void func_80162FF8(s16 arg0) { + f32 val = 0.0f; + s32 i; + + sCsCamKnots[0] = 0.0f; + sCsCamKnots[1] = 0.0f; + sCsCamKnots[2] = 0.0f; + + for (i = 3; i < arg0; i++) { + if (i == 3) { + val += 0.9f; + } else if ((i == 4) || (i == (arg0 - 1))) { + val += 0.6f; + } else { + val += 0.3f; + } + + sCsCamKnots[i] = val; + } + + val += 0.9f; + sCsCamKnots[i++] = val; + sCsCamKnots[i++] = val; + sCsCamKnots[i++] = val; +} + +#define FUNC_801631DC_ORDER 3 + +// Only used by unused CutsceneCamera_Interp_Unused +void func_801631DC(f32 progress, s32 arg2, f32* coeff) { + f32 coeffTemp[4][4]; + s32 i; + s32 j; + s32 k; + + for (i = 0; i < FUNC_801631DC_ORDER + 1; i++) { + for (j = 0; j < FUNC_801631DC_ORDER + 1; j++) { + coeffTemp[i][j] = 0.0f; + } + } + + coeffTemp[0][FUNC_801631DC_ORDER - 1] = 1.0f; + + for (i = 1; i < FUNC_801631DC_ORDER; i++) { + for (j = arg2 - i, k = (FUNC_801631DC_ORDER - 1) - i; j <= arg2; j++, k++) { + if (sCsCamKnots[j + i] != sCsCamKnots[j]) { + coeffTemp[i][k] = + ((progress - sCsCamKnots[j]) / (sCsCamKnots[j + i] - sCsCamKnots[j])) * coeffTemp[i - 1][k]; + } else { + coeffTemp[i][k] = 0.0f; + } + + if (sCsCamKnots[j + i + 1] != sCsCamKnots[j + 1]) { + coeffTemp[i][k] += + ((sCsCamKnots[j + i + 1] - progress) / (sCsCamKnots[j + i + 1] - sCsCamKnots[j + 1])) * + coeffTemp[i - 1][k + 1]; + } + } + } + for (j = 0; j < FUNC_801631DC_ORDER; j++) { + coeff[j] = coeffTemp[FUNC_801631DC_ORDER - 1][j]; + } +} + +s16 CutsceneCamera_Interp_Unused(Vec3f* camPos, f32* camFov, s16* camRoll, CsCmdCamPoint* pointCmd, + CsCmdCamMisc* miscCmd, CutsceneCameraInterp* interpState) { + s32 index; + f32 coeff[3]; + + if (interpState->type != CS_CAM_INTERP_MP_CUBIC) { + // Initialize + interpState->type = CS_CAM_INTERP_MP_CUBIC; + interpState->waypoint = 0; + interpState->duration = pointCmd->duration; + func_80162FF8(interpState->duration); + interpState->curFrame = 0; + } + + index = interpState->waypoint + 2; + func_801631DC(F32_LERPIMP(sCsCamKnots[index], sCsCamKnots[index + 1], + (f32)interpState->curFrame / miscCmd[interpState->waypoint].unused0), + index, coeff); + + if (camPos != NULL) { + camPos->x = (coeff[0] * pointCmd[interpState->waypoint].pos.x) + + (coeff[1] * pointCmd[interpState->waypoint + 1].pos.x) + + (coeff[2] * pointCmd[interpState->waypoint + 2].pos.x); + camPos->y = (coeff[0] * pointCmd[interpState->waypoint].pos.y) + + (coeff[1] * pointCmd[interpState->waypoint + 1].pos.y) + + (coeff[2] * pointCmd[interpState->waypoint + 2].pos.y); + camPos->z = (coeff[0] * pointCmd[interpState->waypoint].pos.z) + + (coeff[1] * pointCmd[interpState->waypoint + 1].pos.z) + + (coeff[2] * pointCmd[interpState->waypoint + 2].pos.z); + } + + if (camFov != NULL) { + *camFov = (coeff[0] * miscCmd[interpState->waypoint].fov) + + (coeff[1] * miscCmd[interpState->waypoint + 1].fov) + + (coeff[2] * miscCmd[interpState->waypoint + 2].fov); + } + + if (camRoll != NULL) { + *camRoll = CAM_DEG_TO_BINANG((coeff[0] * miscCmd[interpState->waypoint].roll) + + (coeff[1] * miscCmd[interpState->waypoint + 1].roll) + + (coeff[2] * miscCmd[interpState->waypoint + 2].roll)); + } + + interpState->curFrame++; + + if (interpState->curFrame >= miscCmd[interpState->waypoint].unused0) { + interpState->waypoint++; + interpState->curFrame = 0; + if (interpState->waypoint >= (interpState->duration - 2)) { + interpState->type = CS_CAM_INTERP_OFF; + return interpState->duration; + } + } + return 0; +} + +f32 func_80163660(Actor* actor) { + if (actor->category != ACTORCAT_PLAYER) { + return 38.0f - (actor->focus.pos.y - actor->world.pos.y); + } + + switch (gSaveContext.save.linkAge) { + case LINK_AGE_ADULT: + return 17.0f; + + default: + return 0.0f; + } +} + +#endif diff --git a/src/code/cutscene_manager.c b/src/code/cutscene_manager.c new file mode 100644 index 0000000000..9785e428fa --- /dev/null +++ b/src/code/cutscene_manager.c @@ -0,0 +1,573 @@ +/** + * @file z_eventmgr.c + * + * Manages all cutscenes except for manual + */ + +#include "z64cutscene.h" + +#include "string.h" +#include "attributes.h" + +#include "global.h" +#include "z64olib.h" +#include "letterbox.h" +#include "config.h" +#include "z64camera.h" + +#if ENABLE_CUTSCENE_IMPROVEMENTS + +CutsceneEntry sGlobalCutsceneList[] = { + // CS_ID_GLOBAL_78 + { -100, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE_ALT, 255, CS_HUD_VISIBILITY_ALL_ALT, 255, + 255 }, + // CS_ID_GLOBAL_79 + { -100, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE_ALT, 255, CS_HUD_VISIBILITY_ALL_ALT, 255, + 255 }, + // CS_ID_GLOBAL_7A + { -100, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE_ALT, 255, CS_HUD_VISIBILITY_ALL_ALT, 255, + 255 }, + // CS_ID_GLOBAL_TALK + { 32765, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE_ALT, 255, CS_HUD_VISIBILITY_ALL_ALT, + CS_END_CAM_0, 255 }, + // CS_ID_GLOBAL_DOOR + { 32764, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE_ALT, 255, CS_HUD_VISIBILITY_ALL_ALT, + CS_END_CAM_0, 255 }, + // CS_ID_GLOBAL_END + { 0, -1, CS_CAM_ID_NONE, CS_SCRIPT_ID_NONE, CS_ID_NONE, CS_END_SFX_NONE, 255, CS_HUD_VISIBILITY_ALL_ALT, + CS_END_CAM_0, 32 }, +}; + +typedef enum { + /* 0 */ CS_START_0, + /* 1 */ CS_START_1, + /* 2 */ CS_START_2 +} ActorCutsceneStartMethod; + +typedef struct { + /* 0x00 */ s16 csId; + /* 0x02 */ s16 length; + /* 0x04 */ s16 endCsId; + /* 0x06 */ s16 subCamId; + /* 0x08 */ Actor* targetActor; + /* 0x0C */ s32 startMethod; + /* 0x10 */ PlayState* play; + /* 0x14 */ s16 retCamId; + /* 0x16 */ s16 isCameraStored; +} CutsceneManager; // size = 0x18 + +CutsceneManager sCutsceneMgr = { + CS_ID_NONE, 0, CS_ID_NONE, SUB_CAM_ID_DONE, NULL, CS_START_0, NULL, CAM_ID_MAIN, false, +}; + +CutsceneEntry* sSceneCutsceneList; +s16 sSceneCutsceneCount; +u8 sWaitingCutsceneList[16]; +static s32 sBssPad; +u8 sNextCutsceneList[16]; +static s32 sBssPad2; + +s16 CutsceneManager_SetHudVisibility(s16 csHudVisibility) { + u16 hudVisibility; + + switch (csHudVisibility) { + case CS_HUD_VISIBILITY_NONE: + hudVisibility = HUD_VISIBILITY_NOTHING_ALT; + break; + + case CS_HUD_VISIBILITY_ALL: + hudVisibility = HUD_VISIBILITY_ALL; + break; + + case CS_HUD_VISIBILITY_A_HEARTS_MAGIC: + hudVisibility = HUD_VISIBILITY_A_HEARTS_MAGIC_FORCE; + break; + + case CS_HUD_VISIBILITY_C_HEARTS_MAGIC: + hudVisibility = HUD_VISIBILITY_HEARTS_MAGIC_C; + break; + + case CS_HUD_VISIBILITY_ALL_NO_MINIMAP: + hudVisibility = HUD_VISIBILITY_ALL_NO_MINIMAP; + break; + + case CS_HUD_VISIBILITY_A_B_C: + hudVisibility = HUD_VISIBILITY_A_B_C; + break; + + case CS_HUD_VISIBILITY_B_MINIMAP: + hudVisibility = HUD_VISIBILITY_B_MINIMAP; + break; + + case CS_HUD_VISIBILITY_A: + hudVisibility = HUD_VISIBILITY_A; + break; + + default: + hudVisibility = HUD_VISIBILITY_ALL; + break; + } + + Interface_ChangeHudVisibilityMode(hudVisibility); + + return hudVisibility; +} + +CutsceneEntry* CutsceneManager_GetCutsceneEntryImpl(s16 csId) { + if (csId < CS_ID_GLOBAL_78) { + return &sSceneCutsceneList[csId]; + } else { + csId -= CS_ID_GLOBAL_78; + return &sGlobalCutsceneList[csId]; + } +} + +void CutsceneManager_Init(PlayState* play, CutsceneEntry* cutsceneList, s16 numEntries) { + s32 i; + + sSceneCutsceneList = cutsceneList; + sSceneCutsceneCount = numEntries; + + for (i = 0; i < ARRAY_COUNT(sWaitingCutsceneList); i++) { + sWaitingCutsceneList[i] = 0; + sNextCutsceneList[i] = 0; + } + + sCutsceneMgr.endCsId = CS_ID_NONE; + sCutsceneMgr.play = play; + sCutsceneMgr.length = -1; + sCutsceneMgr.targetActor = NULL; + sCutsceneMgr.subCamId = SUB_CAM_ID_DONE; + sCutsceneMgr.isCameraStored = false; + sCutsceneMgr.csId = sCutsceneMgr.endCsId; +} + +/** + * Store camera into subCam 2, and keep subCam 2 INACTIVE to preserve the struct. + */ +void CutsceneManager_StoreCamera(Camera* camera) { + if (camera != NULL) { + memcpy(&sCutsceneMgr.play->subCameras[2], camera, sizeof(Camera)); + sCutsceneMgr.play->subCameras[2].camId = camera->camId; + Camera_ChangeStatus(&sCutsceneMgr.play->subCameras[2], CAM_STAT_UNK100); + sCutsceneMgr.isCameraStored = true; + } +} + +void CutsceneManager_ClearWaiting(void) { + s32 i; + + for (i = 0; i < ARRAY_COUNT(sWaitingCutsceneList); i++) { + sWaitingCutsceneList[i] = 0; + } +} + +void CutsceneManager_ClearNextCutscenes(void) { + s32 i; + + for (i = 0; i < ARRAY_COUNT(sNextCutsceneList); i++) { + sNextCutsceneList[i] = 0; + } +} + +s16 CutsceneManager_MarkNextCutscenes(void) { + s16 bit; + s32 i; + s32 j; + s32 count = 0; + s16 csIdMax = CS_ID_NONE; + s16 priorityMax = SHT_MAX; // lower number means higher priority + s16 csId; + s16 priority; + + for (i = 0; i < ARRAY_COUNT(sNextCutsceneList); i++) { + for (bit = 1, j = 0; j < 8; j++) { + if (sWaitingCutsceneList[i] & bit) { + csId = (i << 3) | j; + priority = CutsceneManager_GetCutsceneEntryImpl(csId)->priority; + + if ((priority ^ 0) == -1) { + sNextCutsceneList[i] |= bit; + } else if ((priority < priorityMax) && (priority > 0)) { + csIdMax = csId; + priorityMax = priority; + } + count++; + } + bit <<= 1; + } + } + if (csIdMax != CS_ID_NONE) { + sNextCutsceneList[csIdMax >> 3] |= 1 << (csIdMax & 7); + } + return count; +} + +#define RET_CAM sCutsceneMgr.play->cameraPtrs[sCutsceneMgr.retCamId] +#define CUR_CAM sCutsceneMgr.play->cameraPtrs[sCutsceneMgr.subCamId] + +void CutsceneManager_End(void) { + CutsceneEntry* csEntry; + s16 oldCamId; + s16 oldStateFlags; + + switch (sCutsceneMgr.startMethod) { + case CS_START_2: + sCutsceneMgr.targetActor->flags &= ~ACTOR_FLAG_FREEZE_EXCEPTION; + FALLTHROUGH; + case CS_START_1: + Player_SetCsActionWithHaltedActors(sCutsceneMgr.play, NULL, PLAYER_CSACTION_7); // PLAYER_CSACTION_END + sCutsceneMgr.startMethod = CS_START_0; + break; + + default: + break; + } + + csEntry = CutsceneManager_GetCutsceneEntryImpl(sCutsceneMgr.csId); + + switch (csEntry->endSfx) { + case CS_END_SFX_TRE_BOX_APPEAR: + Sfx_PlaySfxCentered(NA_SE_SY_TRE_BOX_APPEAR); + break; + + case CS_END_SFX_CORRECT_CHIME: + Sfx_PlaySfxCentered(NA_SE_SY_CORRECT_CHIME); + break; + + default: // CS_END_SFX_NONE + break; + } + + switch (csEntry->endCam) { + // case CS_END_CAM_SMOOTH: + // Play_CopyCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId, sCutsceneMgr.subCamId); + // RET_CAM->stateFlags = + // (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); + // CutsceneManager_Queue(CS_ID_GLOBAL_RETURN_TO_CAM); + // break; + + case CS_END_CAM_0: + default: + Play_CopyCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId, sCutsceneMgr.subCamId); + RET_CAM->stateFlags = + (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); + break; + + case CS_END_CAM_1: + oldCamId = RET_CAM->camId; + oldStateFlags = RET_CAM->stateFlags; + + if (sCutsceneMgr.isCameraStored) { + // Restore the camera that was stored in subCam 2 + memcpy(RET_CAM, &sCutsceneMgr.play->subCameras[2], sizeof(Camera)); + + RET_CAM->stateFlags = + (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); + + RET_CAM->stateFlags = (RET_CAM->stateFlags & ~CAM_STATE_CHECK_BG) | (oldStateFlags & CAM_STATE_CHECK_BG); + sCutsceneMgr.isCameraStored = false; + } + RET_CAM->camId = oldCamId; + break; + } + + if (sCutsceneMgr.subCamId != SUB_CAM_ID_DONE) { + Play_ClearCamera(sCutsceneMgr.play, sCutsceneMgr.subCamId); + Play_ChangeCameraStatus(sCutsceneMgr.play, sCutsceneMgr.retCamId, CAM_STAT_ACTIVE); + } + + sCutsceneMgr.csId = CS_ID_NONE; + sCutsceneMgr.endCsId = CS_ID_NONE; + sCutsceneMgr.length = -1; + sCutsceneMgr.targetActor = NULL; + sCutsceneMgr.subCamId = SUB_CAM_ID_DONE; +} + +s16 CutsceneManager_Update(void) { + s16 sp1E = 0; + + // if (CutsceneManager_IsNext(CS_ID_GLOBAL_RETURN_TO_CAM)) { + // CutsceneManager_StartWithPlayerCs(CS_ID_GLOBAL_RETURN_TO_CAM, &GET_PLAYER(sCutsceneMgr.play)->actor); + // } + + PRINTF("(CutsceneManager_Update) csId: %d, endCsId: %d, length: %d\n", sCutsceneMgr.csId, sCutsceneMgr.endCsId, sCutsceneMgr.length); + + if (sCutsceneMgr.endCsId == CS_ID_NONE) { + if (sCutsceneMgr.csId != CS_ID_NONE) { + if (sCutsceneMgr.length > 0) { + sCutsceneMgr.length--; + } + sp1E = 1; + if (sCutsceneMgr.length == 0) { + CutsceneManager_Stop(sCutsceneMgr.csId); + } + } + } + + if (sCutsceneMgr.endCsId != CS_ID_NONE) { + CutsceneManager_End(); + sp1E = 2; + } + + CutsceneManager_ClearNextCutscenes(); + + if (sCutsceneMgr.csId == CS_ID_NONE) { + if ((CutsceneManager_MarkNextCutscenes() == 0) && (sp1E != 0)) { + ShrinkWindow_Letterbox_SetSizeTarget(0); + } else if (sp1E == 0) { + CutsceneManager_StoreCamera(Play_GetCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId)); + } + } + return sp1E; +} + +void CutsceneManager_Queue(s16 csId) { + if (csId > CS_ID_NONE) { + sWaitingCutsceneList[csId >> 3] |= 1 << (csId & 7); + } +} + +s16 CutsceneManager_IsNext(s16 csId) { + if (csId == CS_ID_GLOBAL_END) { + if (sCutsceneMgr.csId == CS_ID_NONE) { + return 0x7F; + } else { + return 0; + } + } + if (csId <= CS_ID_NONE) { + return -1; + } + return (sNextCutsceneList[csId >> 3] & (1 << (csId & 7))) ? 1 : 0; +} + +/** + * Start an actor cutscene, activate Player Cutscene Action "Wait" + */ +s16 CutsceneManager_StartWithPlayerCs(s16 csId, Actor* actor) { + s16 startCsId = CutsceneManager_Start(csId, actor); + + if (startCsId > CS_ID_NONE) { + Player_SetCsActionWithHaltedActors(sCutsceneMgr.play, NULL, PLAYER_CSACTION_8); // PLAYER_CSACTION_WAIT + if (sCutsceneMgr.length == 0) { + CutsceneManager_Stop(sCutsceneMgr.csId); + } + sCutsceneMgr.startMethod = CS_START_1; + } + return startCsId; +} + +/** + * Start an actor cutscene, activate Player Cutscene Action "Wait", turn on ACTOR_FLAG_FREEZE_EXCEPTION + */ +s16 CutsceneManager_StartWithPlayerCsAndSetFlag(s16 csId, Actor* actor) { + s16 startCsId = CutsceneManager_Start(csId, actor); + + if (startCsId > CS_ID_NONE) { + Player_SetCsActionWithHaltedActors(sCutsceneMgr.play, NULL, PLAYER_CSACTION_8); + if (sCutsceneMgr.length == 0) { + CutsceneManager_Stop(sCutsceneMgr.csId); + } + if (actor != NULL) { + actor->flags |= ACTOR_FLAG_FREEZE_EXCEPTION; + sCutsceneMgr.startMethod = CS_START_2; + } else { + sCutsceneMgr.startMethod = CS_START_1; + } + } + return startCsId; +} + +s16 CutsceneManager_Start(s16 csId, Actor* actor) { + CutsceneEntry* csEntry; + Camera* subCam; + Camera* retCam; + s32 csType = 0; + + if ((csId <= CS_ID_NONE) || (sCutsceneMgr.csId != CS_ID_NONE)) { + return csId; + } + + sCutsceneMgr.startMethod = CS_START_0; + csEntry = CutsceneManager_GetCutsceneEntryImpl(csId); + + ShrinkWindow_Letterbox_SetSizeTarget(csEntry->letterboxSize); + CutsceneManager_SetHudVisibility(csEntry->hudVisibility); + + if (csId == CS_ID_GLOBAL_END) { + csType = 1; + } else if (csEntry->scriptIndex != CS_SCRIPT_ID_NONE) { + // scripted cutscene + csType = 1; + } else if ((csId != CS_ID_GLOBAL_DOOR) && (csId != CS_ID_GLOBAL_TALK)) { + csType = 2; + } + + PRINTF("(CutsceneManager_Start) csType: %d, csEntry->scriptIndex:%d, csEntry->priority: %d\n", + csType, csEntry->scriptIndex, csEntry->priority); + + if (csType != 0) { + sCutsceneMgr.retCamId = Play_GetActiveCamId(sCutsceneMgr.play); + sCutsceneMgr.subCamId = Play_CreateSubCamera(sCutsceneMgr.play); + + subCam = Play_GetCamera(sCutsceneMgr.play, sCutsceneMgr.subCamId); + retCam = Play_GetCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId); + + if ((retCam->setting == CAM_SET_START0) || /* (retCam->setting == CAM_SET_START2) || */ + (retCam->setting == CAM_SET_START1)) { + if (CutsceneManager_FindEntranceCsId() != csId) { + Camera_800E0348(retCam); + } else { + Camera_UnsetStateFlag(retCam, CAM_STATE_CHECK_BG); + } + } + + memcpy(subCam, retCam, sizeof(Camera)); + subCam->camId = sCutsceneMgr.subCamId; + Camera_UnsetStateFlag(subCam, CAM_STATE_DISTORTION | CAM_STATE_CHECK_BG_ALT); + + Play_ChangeCameraStatus(sCutsceneMgr.play, sCutsceneMgr.retCamId, CAM_STAT_WAIT); + Play_ChangeCameraStatus(sCutsceneMgr.play, sCutsceneMgr.subCamId, CAM_STAT_ACTIVE); + + subCam->target = sCutsceneMgr.targetActor = actor; + subCam->behaviorFlags = 0; + + if (csType == 1) { + Camera_ChangeSetting(subCam, CAM_SET_FREE0); + Cutscene_StartScripted(sCutsceneMgr.play, csEntry->scriptIndex); + sCutsceneMgr.length = csEntry->length; + } else { + if (csEntry->csCamId != CS_CAM_ID_NONE) { + Camera_ChangeActorCsCamIndex(subCam, csEntry->csCamId); + } else { + Camera_ChangeSetting(subCam, CAM_SET_FREE0); + } + sCutsceneMgr.length = csEntry->length; + } + } + sCutsceneMgr.csId = csId; + + return csId; +} + +s16 CutsceneManager_Stop(s16 csId) { + CutsceneEntry* csEntry; + + if (csId <= CS_ID_NONE) { + return csId; + } + + csEntry = CutsceneManager_GetCutsceneEntryImpl(sCutsceneMgr.csId); + if ((sCutsceneMgr.length > 0) && (csEntry->scriptIndex == CS_SCRIPT_ID_NONE)) { + return -2; + } + if ((csId != CS_ID_GLOBAL_END) && (csEntry->scriptIndex != CS_SCRIPT_ID_NONE)) { + return -3; + } + + if (csId == CS_ID_GLOBAL_END) { + csId = sCutsceneMgr.csId; + } + if (csId == sCutsceneMgr.csId) { + sCutsceneMgr.endCsId = sCutsceneMgr.csId; + return sCutsceneMgr.endCsId; + } + return -1; +} + +s16 CutsceneManager_GetCurrentCsId(void) { + return sCutsceneMgr.csId; +} + +CutsceneEntry* CutsceneManager_GetCutsceneEntry(s16 csId) { + return CutsceneManager_GetCutsceneEntryImpl(csId); +} + +s16 CutsceneManager_GetAdditionalCsId(s16 csId) { + if (csId <= CS_ID_NONE) { + return CS_ID_NONE; + } + return CutsceneManager_GetCutsceneEntryImpl(csId)->additionalCsId; +} + +s16 CutsceneManager_GetLength(s16 csId) { + if (csId <= CS_ID_NONE) { + return -1; + } + return CutsceneManager_GetCutsceneEntryImpl(csId)->length; +} + +s16 CutsceneManager_GetCutsceneScriptIndex(s16 csId) { + if (csId <= CS_ID_NONE) { + return -1; + } + return CutsceneManager_GetCutsceneEntryImpl(csId)->scriptIndex; +} + +s16 CutsceneManager_GetCutsceneCustomValue(s16 csId) { + if (csId <= CS_ID_NONE) { + return -1; + } + return CutsceneManager_GetCutsceneEntryImpl(csId)->customValue; +} + +s16 CutsceneManager_GetCurrentSubCamId(s16 csId) { + return sCutsceneMgr.subCamId; +} + +s16 CutsceneManager_FindEntranceCsId(void) { + PlayState* play; + s32 csId; + + for (csId = 0; csId < sSceneCutsceneCount; csId++) { + //! FAKE: + if ((sSceneCutsceneList[csId].scriptIndex != CS_SCRIPT_ID_NONE) && + (sSceneCutsceneList[csId].scriptIndex < (play = sCutsceneMgr.play)->csCtx.scriptListCount) && + (sCutsceneMgr.play->spawn == + sCutsceneMgr.play->csCtx.scriptList[sSceneCutsceneList[csId].scriptIndex].spawn)) { + return csId; + } + } + + for (csId = 0; csId < sSceneCutsceneCount; csId++) { + if ((sSceneCutsceneList[csId].customValue >= 100) && + (sSceneCutsceneList[csId].customValue == (sCutsceneMgr.play->spawn + 100))) { + return csId; + } + } + + return -1; +} + +s32 CutsceneManager_800F22C4(s16 csId, Actor* actor) { + f32 dist; + s16 screenPosX; + s16 screenPosY; + + if ((sCutsceneMgr.csId == CS_ID_NONE) || (csId == CS_ID_NONE)) { + return 4; + } + + Actor_GetScreenPos(sCutsceneMgr.play, actor, &screenPosX, &screenPosY); + + dist = OLib_Vec3fDist(&actor->focus.pos, &Play_GetCamera(sCutsceneMgr.play, sCutsceneMgr.subCamId)->eye); + + if ((screenPosX > 40) && (screenPosX < SCREEN_WIDTH - 40) && (screenPosY > 40) && + (screenPosY < SCREEN_HEIGHT - 40) && (dist < 700.0f)) { + return 1; + } + if (sCutsceneMgr.length < 6) { + return 2; + } + if (csId == sCutsceneMgr.csId) { + return 0; + } + return 3; +} + +void CutsceneManager_SetReturnCamera(s16 camId) { + sCutsceneMgr.retCamId = camId; +} + +#endif diff --git a/src/code/shrink_window.c b/src/code/shrink_window.c index ad8da58d35..5969694e8f 100644 --- a/src/code/shrink_window.c +++ b/src/code/shrink_window.c @@ -1,5 +1,135 @@ #include "global.h" +#if ENABLE_NEW_LETTERBOX + +#include "gfx.h" +#include "main.h" +#include "z_lib.h" + +typedef struct { + /* 0x0 */ s8 letterboxTarget; + /* 0x1 */ s8 letterboxSize; + /* 0x2 */ s8 pillarboxTarget; + /* 0x3 */ s8 pillarboxSize; +} ShrinkWindow; // size = 0x4 + +ShrinkWindow sShrinkWindow; +ShrinkWindow* sShrinkWindowPtr; + +void ShrinkWindow_Letterbox_SetSizeTarget(s32 target) { + sShrinkWindowPtr->letterboxTarget = target; +} + +s32 ShrinkWindow_Letterbox_GetSizeTarget(void) { + return sShrinkWindowPtr->letterboxTarget; +} + +void ShrinkWindow_Letterbox_SetSize(s32 size) { + sShrinkWindowPtr->letterboxSize = size; +} + +s32 ShrinkWindow_Letterbox_GetSize(void) { + return sShrinkWindowPtr->letterboxSize; +} + +void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target) { + sShrinkWindowPtr->pillarboxTarget = target; +} + +s32 ShrinkWindow_Pillarbox_GetSizeTarget(void) { + return sShrinkWindowPtr->pillarboxTarget; +} + +void ShrinkWindow_Pillarbox_SetSize(s32 size) { + sShrinkWindowPtr->pillarboxSize = size; +} + +s32 ShrinkWindow_Pillarbox_GetSize(void) { + return sShrinkWindowPtr->pillarboxSize; +} + +void ShrinkWindow_Init(void) { + sShrinkWindowPtr = &sShrinkWindow; + bzero(sShrinkWindowPtr, sizeof(sShrinkWindow)); +} + +void ShrinkWindow_Destroy(void) { + sShrinkWindowPtr = NULL; +} + +void ShrinkWindow_Update(s32 framerateDivisor) { + s32 step = (framerateDivisor == 3) ? 10 : (30 / framerateDivisor); + s32 nextSize; + + nextSize = sShrinkWindowPtr->letterboxSize; + Math_StepToIGet(&nextSize, sShrinkWindowPtr->letterboxTarget, step); + sShrinkWindowPtr->letterboxSize = nextSize; + + nextSize = sShrinkWindowPtr->pillarboxSize; + Math_StepToIGet(&nextSize, sShrinkWindowPtr->pillarboxTarget, step); + sShrinkWindowPtr->pillarboxSize = nextSize; +} + +void ShrinkWindow_Draw(GraphicsContext* gfxCtx) { + Gfx* gfx; + s8 letterboxSize = sShrinkWindowPtr->letterboxSize; + s8 pillarboxSize = sShrinkWindowPtr->pillarboxSize; + + if (letterboxSize > 0) { + OPEN_DISPS(gfxCtx); + + gfx = OVERLAY_DISP; + + gDPPipeSync(gfx++); + gDPSetCycleType(gfx++, G_CYC_FILL); + gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); + gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxSize - 1); + gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1); + + gDPPipeSync(gfx++); + gDPSetCycleType(gfx++, G_CYC_1CYCLE); + gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0); + gDPFillRectangle(gfx++, 0, letterboxSize, gScreenWidth, letterboxSize + 1); + gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize - 1, gScreenWidth, gScreenHeight - letterboxSize); + + gDPPipeSync(gfx++); + OVERLAY_DISP = gfx++; + + CLOSE_DISPS(gfxCtx); + } + + if (pillarboxSize > 0) { + OPEN_DISPS(gfxCtx); + + gfx = OVERLAY_DISP; + + gDPPipeSync(gfx++); + gDPSetCycleType(gfx++, G_CYC_FILL); + gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2); + gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1)); + + gDPFillRectangle(gfx++, 0, 0, pillarboxSize - 1, gScreenHeight - 1); + gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize, 0, gScreenWidth - 1, gScreenHeight - 1); + + gDPPipeSync(gfx++); + gDPSetCycleType(gfx++, G_CYC_1CYCLE); + gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0); + + gDPFillRectangle(gfx++, pillarboxSize, 0, pillarboxSize + 2, gScreenHeight); + gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize - 2, 0, gScreenWidth - pillarboxSize, gScreenHeight); + + gDPPipeSync(gfx++); + OVERLAY_DISP = gfx++; + + CLOSE_DISPS(gfxCtx); + } +} + +#else + typedef enum LetterboxState { /* 0 */ LETTERBOX_STATE_IDLE, /* 1 */ LETTERBOX_STATE_GROWING, @@ -11,31 +141,50 @@ s32 sLetterboxState = LETTERBOX_STATE_IDLE; s32 sLetterboxSizeTarget = 0; s32 sLetterboxSize = 0; +#endif + void Letterbox_SetSizeTarget(s32 target) { +#if ENABLE_NEW_LETTERBOX + return ShrinkWindow_Letterbox_SetSizeTarget(target); +#else if (R_HREG_MODE == HREG_MODE_LETTERBOX && R_LETTERBOX_ENABLE_LOGS == 1) { PRINTF("shrink_window_setval(%d)\n", target); } sLetterboxSizeTarget = target; +#endif } u32 Letterbox_GetSizeTarget(void) { +#if ENABLE_NEW_LETTERBOX + return ShrinkWindow_Letterbox_GetSizeTarget(); +#else return sLetterboxSizeTarget; +#endif } void Letterbox_SetSize(s32 size) { +#if ENABLE_NEW_LETTERBOX + return ShrinkWindow_Letterbox_SetSize(size); +#else if (R_HREG_MODE == HREG_MODE_LETTERBOX && R_LETTERBOX_ENABLE_LOGS == 1) { PRINTF("shrink_window_setnowval(%d)\n", size); } sLetterboxSize = size; +#endif } u32 Letterbox_GetSize(void) { +#if ENABLE_NEW_LETTERBOX + return ShrinkWindow_Letterbox_GetSize(); +#else return sLetterboxSize; +#endif } void Letterbox_Init(void) { +#if !ENABLE_NEW_LETTERBOX if (R_HREG_MODE == HREG_MODE_LETTERBOX && R_LETTERBOX_ENABLE_LOGS == 1) { PRINTF("shrink_window_init()\n"); } @@ -43,17 +192,21 @@ void Letterbox_Init(void) { sLetterboxState = LETTERBOX_STATE_IDLE; sLetterboxSizeTarget = 0; sLetterboxSize = 0; +#endif } void Letterbox_Destroy(void) { +#if !ENABLE_NEW_LETTERBOX if (R_HREG_MODE == HREG_MODE_LETTERBOX && R_LETTERBOX_ENABLE_LOGS == 1) { PRINTF("shrink_window_cleanup()\n"); } sLetterboxSize = 0; +#endif } void Letterbox_Update(s32 updateRate) { +#if !ENABLE_NEW_LETTERBOX s32 step; if (updateRate == 3) { @@ -107,4 +260,5 @@ void Letterbox_Update(s32 updateRate) { R_LETTERBOX_TARGET_SIZE = sLetterboxSizeTarget; R_LETTERBOX_STEP = step; } +#endif } diff --git a/src/code/z_camera.c b/src/code/z_camera.c index 2802a97c8b..4c4d7ae6a0 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -8959,3 +8959,211 @@ s16 Camera_SetFinishedFlag(Camera* camera) { return camera->camId; } + +#if ENABLE_CUTSCENE_IMPROVEMENTS +#define CAM_DATA_IS_BG (1 << 12) // if not set, then cam data is for actor cutscenes + +s16 sGlobalCamDataSettings[] = { + /* -66 */ CAM_SET_NORMAL4, // CS_CAM_ID_GLOBAL_NORMAL4 + /* -65 */ CAM_SET_PIVOT_FROM_SIDE, // CS_CAM_ID_GLOBAL_PIVOT_FROM_SIDE + /* -64 */ CAM_SET_DIRECTED_YAW, // CS_CAM_ID_GLOBAL_DIRECTED_YAW + /* -63 */ CAM_SET_DUNGEON2, // CS_CAM_ID_GLOBAL_DUNGEON2 + /* -62 */ CAM_SET_JABU_TENTACLE, // CS_CAM_ID_GLOBAL_JABU_TENTACLE + /* -61 */ CAM_SET_CS_C, // CS_CAM_ID_GLOBAL_CS_C + /* -60 */ CAM_SET_FISHING, // CS_CAM_ID_GLOBAL_FISHING + /* -59 */ CAM_SET_NORMAL2, // CS_CAM_ID_GLOBAL_NORMAL2 + /* -58 */ CAM_SET_PIVOT_VERTICAL, // CS_CAM_ID_GLOBAL_PIVOT_VERTICAL + /* -57 */ CAM_SET_TURN_AROUND, // CS_CAM_ID_GLOBAL_TURN_AROUND + /* -56 */ CAM_SET_FIRE_BIRDS_EYE, // CS_CAM_ID_GLOBAL_FIRE_BIRDS_EYE + /* -55 */ CAM_SET_MEADOW_UNUSED, // CS_CAM_ID_GLOBAL_MEADOW_UNUSED + /* -54 */ CAM_SET_MEADOW_BIRDS_EYE, // CS_CAM_ID_GLOBAL_MEADOW_BIRDS_EYE + /* -53 */ CAM_SET_BIG_OCTO, // CS_CAM_ID_GLOBAL_BIG_OCTO + /* -52 */ CAM_SET_FOREST_DEFEAT_POE, // CS_CAM_ID_GLOBAL_FOREST_DEFEAT_POE + /* -51 */ CAM_SET_FOREST_UNUSED, // CS_CAM_ID_GLOBAL_FOREST_UNUSED + /* -50 */ CAM_SET_FIRE_STAIRCASE, // CS_CAM_ID_GLOBAL_FIRE_STAIRCASE + /* -49 */ CAM_SET_ELEVATOR_PLATFORM, // CS_CAM_ID_GLOBAL_ELEVATOR_PLATFORM + /* -48 */ CAM_SET_SCENE_TRANSITION, // CS_CAM_ID_GLOBAL_SCENE_TRANSITION + /* -47 */ CAM_SET_SCENE_UNUSED, // CS_CAM_ID_GLOBAL_SCENE_UNUSED + /* -46 */ CAM_SET_BEAN_LOST_WOODS, // CS_CAM_ID_GLOBAL_BEAN_LOST_WOODS + /* -45 */ CAM_SET_BEAN_GENERIC, // CS_CAM_ID_GLOBAL_BEAN_GENERIC + /* -44 */ CAM_SET_CS_ATTENTION, // CS_CAM_ID_GLOBAL_CS_ATTENTION + /* -43 */ CAM_SET_CS_3, // CS_CAM_ID_GLOBAL_CS_3 + /* -42 */ CAM_SET_ITEM_UNUSED, // CS_CAM_ID_GLOBAL_ITEM_UNUSED + /* -41 */ CAM_SET_SLOW_CHEST_CS, // CS_CAM_ID_GLOBAL_SLOW_CHEST_CS + /* -40 */ CAM_SET_FOREST_BIRDS_EYE, // CS_CAM_ID_GLOBAL_FOREST_BIRDS_EYE + /* -39 */ CAM_SET_CS_TWISTED_HALLWAY, // CS_CAM_ID_GLOBAL_CS_TWISTED_HALLWAY + /* -38 */ CAM_SET_CS_0, // CS_CAM_ID_GLOBAL_CS_0 + /* -37 */ CAM_SET_PIVOT_WATER_SURFACE, // CS_CAM_ID_GLOBAL_PIVOT_WATER_SURFACE + /* -36 */ CAM_SET_PIVOT_CORNER, // CS_CAM_ID_GLOBAL_PIVOT_CORNER + /* -35 */ CAM_SET_FREE2, // CS_CAM_ID_GLOBAL_FREE2 + /* -34 */ CAM_SET_FREE0, // CS_CAM_ID_GLOBAL_FREE0 + /* -33 */ CAM_SET_START1, // CS_CAM_ID_GLOBAL_START1 + /* -32 */ CAM_SET_START0, // CS_CAM_ID_GLOBAL_START0 + /* -31 */ CAM_SET_CRAWLSPACE, // CS_CAM_ID_GLOBAL_CRAWLSPACE + /* -30 */ CAM_SET_DOORC, // CS_CAM_ID_GLOBAL_DOORC + /* -29 */ CAM_SET_DOOR0, // CS_CAM_ID_GLOBAL_DOOR0 + /* -28 */ CAM_SET_PREREND_SIDE_SCROLL, // CS_CAM_ID_GLOBAL_PREREND_SIDE_SCROLL + /* -27 */ CAM_SET_PREREND_PIVOT, // CS_CAM_ID_GLOBAL_PREREND_PIVOT + /* -26 */ CAM_SET_PREREND_FIXED, // CS_CAM_ID_GLOBAL_PREREND_FIXED + /* -25 */ CAM_SET_PIVOT_IN_FRONT, // CS_CAM_ID_GLOBAL_PIVOT_IN_FRONT + /* -24 */ CAM_SET_PIVOT_SHOP_BROWSING, // CS_CAM_ID_GLOBAL_PIVOT_SHOP_BROWSING + /* -23 */ CAM_SET_PIVOT_CRAWLSPACE, // CS_CAM_ID_GLOBAL_PIVOT_CRAWLSPACE + /* -22 */ CAM_SET_CHU_BOWLING, // CS_CAM_ID_GLOBAL_CHU_BOWLING + /* -21 */ CAM_SET_MARKET_BALCONY, // CS_CAM_ID_GLOBAL_MARKET_BALCONY + /* -20 */ CAM_SET_TOWER_UNUSED, // CS_CAM_ID_GLOBAL_TOWER_UNUSED + /* -19 */ CAM_SET_TOWER_CLIMB, // CS_CAM_ID_GLOBAL_TOWER_CLIMB + /* -18 */ CAM_SET_BOSS_GANON, // CS_CAM_ID_GLOBAL_BOSS_GANON + /* -17 */ CAM_SET_BOSS_GANONDORF, // CS_CAM_ID_GLOBAL_BOSS_GANONDORF + /* -16 */ CAM_SET_BOSS_TWINROVA_FLOOR, // CS_CAM_ID_GLOBAL_BOSS_TWINROVA_FLOOR + /* -15 */ CAM_SET_BOSS_TWINROVA_PLATFORM, // CS_CAM_ID_GLOBAL_BOSS_TWINROVA_PLATFORM + /* -14 */ CAM_SET_BOSS_MORPHA, // CS_CAM_ID_GLOBAL_BOSS_MORPHA + /* -13 */ CAM_SET_BOSS_BONGO, // CS_CAM_ID_GLOBAL_BOSS_BONGO + /* -12 */ CAM_SET_BOSS_VOLVAGIA, // CS_CAM_ID_GLOBAL_BOSS_VOLVAGIA + /* -11 */ CAM_SET_BOSS_PHANTOM_GANON, // CS_CAM_ID_GLOBAL_BOSS_PHANTOM_GANON + /* -10 */ CAM_SET_BOSS_BARINADE, // CS_CAM_ID_GLOBAL_BOSS_BARINADE + /* -9 */ CAM_SET_BOSS_DODONGO, // CS_CAM_ID_GLOBAL_BOSS_DODONGO + /* -8 */ CAM_SET_BOSS_GOHMA, // CS_CAM_ID_GLOBAL_BOSS_GOHMA + /* -7 */ CAM_SET_HORSE, // CS_CAM_ID_GLOBAL_HORSE + /* -6 */ CAM_SET_NORMAL3, // CS_CAM_ID_GLOBAL_NORMAL3 + /* -5 */ CAM_SET_DUNGEON1, // CS_CAM_ID_GLOBAL_DUNGEON1 + /* -4 */ CAM_SET_DUNGEON0, // CS_CAM_ID_GLOBAL_DUNGEON0 + /* -3 */ CAM_SET_NORMAL1, // CS_CAM_ID_GLOBAL_NORMAL1 + /* -2 */ CAM_SET_NORMAL0, // CS_CAM_ID_GLOBAL_NORMAL0 + /* -1 */ CAM_SET_NONE, // CS_CAM_ID_NONE + /* 0 */ CAM_SET_NONE, +}; + +s16* sGlobalCamDataSettingsPtr = &sGlobalCamDataSettings[ARRAY_COUNT(sGlobalCamDataSettings) - 1]; + +/** + * Returns the CameraSettingType of the camera from either the bgCam or the actorCsCam at index `camDataId` + */ +s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId) { + if (camDataId & CAM_DATA_IS_BG) { + return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); + } else { + return Play_GetActorCsCamSetting(camera->play, camDataId); + } +} + +/** + * Returns either the bgCam data or the actorCsCam data at index `camDataId` + */ +Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId) { + if (camDataId & CAM_DATA_IS_BG) { + return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); + } else { + return Play_GetActorCsCamFuncData(camera->play, camDataId); + } +} + +s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags) { + // Reject settings change based on priority + if ((camera->behaviorFlags & CAM_BEHAVIOR_SETTING_CHECK_PRIORITY) && + ((sCameraSettings[camera->setting].flags & 0xF) >= (sCameraSettings[setting].flags & 0xF))) { + camera->behaviorFlags |= CAM_BEHAVIOR_BG_SUCCESS; + if (!(flags & CAM_REQUEST_SETTING_IGNORE_PRIORITY)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_CHECK_PRIORITY; + } + return -2; + } + + // Reject settings change based on NONE setting + if (setting == CAM_SET_NONE) { + return 0; + } + + // Reject settings change based on an invalid setting + if (setting >= CAM_SET_MAX) { + return -99; + } + + // Reject settings change based on setting already set (and flags) + if ((setting == camera->setting) && !(flags & CAM_REQUEST_SETTING_FORCE_CHANGE)) { + camera->behaviorFlags |= CAM_REQUEST_SETTING_PRESERVE_BG_CAM_INDEX; + if (!(flags & CAM_REQUEST_SETTING_IGNORE_PRIORITY)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_CHECK_PRIORITY; + } + return -1; + } + + camera->behaviorFlags |= CAM_REQUEST_SETTING_PRESERVE_BG_CAM_INDEX; + + if (!(flags & CAM_REQUEST_SETTING_IGNORE_PRIORITY)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_CHECK_PRIORITY; + } + + Camera_SetNewModeStateFlags(camera); + + if (!(sCameraSettings[camera->setting].flags & 0x40000000)) { + camera->prevSetting = camera->setting; + } + + if (flags & CAM_REQUEST_SETTING_RESTORE_PREV_BG_CAM_INDEX) { + camera->bgCamIndex = camera->prevBgCamIndex; + camera->prevBgCamIndex = -1; + } else if (!(flags & CAM_REQUEST_SETTING_PRESERVE_BG_CAM_INDEX)) { + if (!(sCameraSettings[camera->setting].flags & 0x40000000)) { + camera->prevBgCamIndex = camera->bgCamIndex; + } + camera->bgCamIndex = -1; + } + + camera->setting = setting; + + if (Camera_RequestModeImpl(camera, camera->mode, true) >= 0) { + Camera_CopyDataToRegs(camera, camera->mode); + } + + return setting; +} + +s32 Camera_ChangeSetting(Camera* camera, s16 setting) { + s32 settingChangeSuccessful = Camera_ChangeSettingFlags(camera, setting, 0); + + if (settingChangeSuccessful >= 0) { + camera->bgCamIndex = -1; + } + return settingChangeSuccessful; +} + +s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex) { + s16 setting; + + if ((bgCamIndex == -1) || (bgCamIndex == camera->bgCamIndex)) { + camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; + return -1; + } + + if (bgCamIndex < 0) { + setting = sGlobalCamDataSettingsPtr[bgCamIndex]; + } else if (!(camera->behaviorFlags & CAM_BEHAVIOR_BG_PROCESSED)) { + setting = Camera_GetBgCamOrActorCsCamSetting(camera, bgCamIndex); + } else { + return -1; + } + + camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; + + // Sets camera setting based on bg/scene data + if ((Camera_ChangeSettingFlags( + camera, setting, CAM_REQUEST_SETTING_PRESERVE_BG_CAM_INDEX | CAM_REQUEST_SETTING_FORCE_CHANGE) >= 0) || + (sCameraSettings[camera->setting].flags & 0x80000000)) { + camera->bgCamIndex = bgCamIndex; + camera->behaviorFlags |= CAM_BEHAVIOR_BG_SUCCESS; + Camera_CopyDataToRegs(camera, camera->mode); + } + + return bgCamIndex | 0x80000000; +} + +void Camera_800E0348(Camera* camera) { + if (!RELOAD_PARAMS(camera)) { + camera->animState = 999; + Camera_SetStateFlag(camera, CAM_STATE_BLOCK_BG | CAM_STATE_CAM_FUNC_FINISH | CAM_STATE_CHECK_BG | CAM_STATE_CHECK_WATER); + } else { + camera->animState = 666; + } +} + +#endif diff --git a/src/code/z_camera_data.inc.c b/src/code/z_camera_data.inc.c index 0676150c69..7eb12fb352 100644 --- a/src/code/z_camera_data.inc.c +++ b/src/code/z_camera_data.inc.c @@ -12,6 +12,13 @@ typedef struct CameraMode { CameraModeValue* values; } CameraMode; +/** + * Flags: + * (flags & 0xF): Priority (lower value has higher priority) + * (flags & 0x20000000): Ignore flags + * (flags & 0x40000000): Store previous setting and bgCamData, also ignores water checks + * (flags & 0x80000000): Set camera setting based on bg/scene data and reset action function state + */ typedef struct CameraSetting { union { u32 unk_00; @@ -21,6 +28,7 @@ typedef struct CameraSetting { u32 validModes : 30; }; }; + u32 flags; CameraMode* cameraModes; } CameraSetting; @@ -2345,72 +2353,72 @@ CameraMode sCamSetNormal4Modes[] = { }; CameraSetting sCameraSettings[] = { - { { 0x00000000 }, NULL }, // CAM_SET_NONE - { { 0x051FFFFF }, sCamSetNormal0Modes }, // CAM_SET_NORMAL0 - { { 0x051FFFFF }, sCamSetNormal1Modes }, // CAM_SET_NORMAL1 - { { 0x051FFFFF }, sCamSetDungeon0Modes }, // CAM_SET_DUNGEON0 - { { 0x051FFFFF }, sCamSetDungeon1Modes }, // CAM_SET_DUNGEON1 - { { 0x050FF7FF }, sCamSetNormal3Modes }, // CAM_SET_NORMAL3 - { { 0x8500018F }, sCamSetHorseModes }, // CAM_SET_HORSE - { { 0x051FFFFF }, sCamSetBossGohmaModes }, // CAM_SET_BOSS_GOHMA - { { 0x051FFFFF }, sCamSetBossDodongoModes }, // CAM_SET_BOSS_DODONGO - { { 0x051FFFFF }, sCamSetBossBarinadeModes }, // CAM_SET_BOSS_BARINADE - { { 0x051FFFFF }, sCamSetBossPhantomGanonModes }, // CAM_SET_BOSS_PHANTOM_GANON - { { 0x051FFFFF }, sCamSetBossVolvagiaModes }, // CAM_SET_BOSS_VOLVAGIA - { { 0x051FFFFF }, sCamSetBossBongoModes }, // CAM_SET_BOSS_BONGO - { { 0x051FFFFF }, sCamSetBossMorphaModes }, // CAM_SET_BOSS_MORPHA - { { 0x051FFFFF }, sCamSetBossTwinrovaPlatformModes }, // CAM_SET_BOSS_TWINROVA_PLATFORM - { { 0x051FFFFF }, sCamSetBossTwinrovaFloorModes }, // CAM_SET_BOSS_TWINROVA_FLOOR - { { 0x051FFFFF }, sCamSetBossGanondorfModes }, // CAM_SET_BOSS_GANONDORF - { { 0x051FFFFF }, sCamSetBossGanonModes }, // CAM_SET_BOSS_GANON - { { 0x851FFFFF }, sCamSetTowerClimbModes }, // CAM_SET_TOWER_CLIMB - { { 0x851FFFFF }, sCamSetTowerUnusedModes }, // CAM_SET_TOWER_UNUSED - { { 0x8500000D }, sCamSetMarketBalconyModes }, // CAM_SET_MARKET_BALCONY - { { 0x85000001 }, sCamSetChuBowlingModes }, // CAM_SET_CHU_BOWLING - { { 0x85000001 }, sCamSetPivotCrawlspaceModes }, // CAM_SET_PIVOT_CRAWLSPACE - { { 0x85000001 }, sCamSetPivotShopBrowsingModes }, // CAM_SET_PIVOT_SHOP_BROWSING - { { 0x851E1FFF }, sCamSetPivotInFrontModes }, // CAM_SET_PIVOT_IN_FRONT - { { 0x8C00000D }, sCamSetPreRendFixedModes }, // CAM_SET_PREREND_FIXED - { { 0x8C00000D }, sCamSetPreRendPivotModes }, // CAM_SET_PREREND_PIVOT - { { 0x8C000001 }, sCamSetPreRendSideScrollModes }, // CAM_SET_PREREND_SIDE_SCROLL - { { 0xC5000001 }, sCamSetDoor0Modes }, // CAM_SET_DOOR0 - { { 0xC5000003 }, sCamSetDoorCModes }, // CAM_SET_DOORC - { { 0xC5000001 }, sCamSetCrawlspaceModes }, // CAM_SET_CRAWLSPACE - { { 0xC5000001 }, sCamSetStart0Modes }, // CAM_SET_START0 - { { 0xC5000001 }, sCamSetStart1Modes }, // CAM_SET_START1 - { { 0x05000001 }, sCamSetFree0Modes }, // CAM_SET_FREE0 - { { 0x05000001 }, sCamSetFree2Modes }, // CAM_SET_FREE2 - { { 0x85000001 }, sCamSetPivotCornerModes }, // CAM_SET_PIVOT_CORNER - { { 0x05000003 }, sCamSetPivotWaterSurfaceModes }, // CAM_SET_PIVOT_WATER_SURFACE - { { 0xCE000001 }, sCamSetCs0Modes }, // CAM_SET_CS_0 - { { 0x4E000001 }, sCamSetCsTwistedHallwayModes }, // CAM_SET_CS_TWISTED_HALLWAY - { { 0x05000009 }, sCamSetForestBirdsEyeModes }, // CAM_SET_FOREST_BIRDS_EYE - { { 0x45000001 }, sCamSetSlowChestCsModes }, // CAM_SET_SLOW_CHEST_CS - { { 0x45000001 }, sCamSetItemUnusedModes }, // CAM_SET_ITEM_UNUSED - { { 0x45000001 }, sCamSetCs3Modes }, // CAM_SET_CS_3 - { { 0x45000001 }, sCamSetCsAttentionModes }, // CAM_SET_CS_ATTENTION - { { 0x451FFFFF }, sCamSetBeanGenericModes }, // CAM_SET_BEAN_GENERIC - { { 0x451FFFFF }, sCamSetBeanLostWoodsModes }, // CAM_SET_BEAN_LOST_WOODS - { { 0xC5000001 }, sCamSetSceneUnusedModes }, // CAM_SET_SCENE_UNUSED - { { 0x45000001 }, sCamSetSceneTransitionModes }, // CAM_SET_SCENE_TRANSITION - { { 0x05000001 }, sCamSetElevatorPlatformModes }, // CAM_SET_ELEVATOR_PLATFORM - { { 0x45000001 }, sCamSetFireStaircaseModes }, // CAM_SET_FIRE_STAIRCASE - { { 0x45000001 }, sCamSetForestUnusedModes }, // CAM_SET_FOREST_UNUSED - { { 0x45000001 }, sCamSetForestDefeatPoeModes }, // CAM_SET_FOREST_DEFEAT_POE - { { 0x451FFFFF }, sCamSetBigOctoModes }, // CAM_SET_BIG_OCTO - { { 0x05000033 }, sCamSetMeadowBirdsEyeModes }, // CAM_SET_MEADOW_BIRDS_EYE - { { 0x05000033 }, sCamSetMeadowUnusedModes }, // CAM_SET_MEADOW_UNUSED - { { 0x05000033 }, sCamSetFireBirdsEyeModes }, // CAM_SET_FIRE_BIRDS_EYE - { { 0x4A000001 }, sCamSetTurnAroundModes }, // CAM_SET_TURN_AROUND - { { 0x05000001 }, sCamSetPivotVerticalModes }, // CAM_SET_PIVOT_VERTICAL - { { 0x051FFFFF }, sCamSetNorm2Modes }, // CAM_SET_NORMAL2 - { { 0x0501E05F }, sCamSetFishingModes }, // CAM_SET_FISHING - { { 0x45000001 }, sCamSetCsCModes }, // CAM_SET_CS_C - { { 0x051FFFFF }, sCamSetJabuTentacleModes }, // CAM_SET_JABU_TENTACLE - { { 0x051FFFFF }, sCamSetDungeon2Modes }, // CAM_SET_DUNGEON2 - { { 0x051FFFFF }, sCamSetDirectedYawModes }, // CAM_SET_DIRECTED_YAW - { { 0xC5000ECD }, sCamSetPivotFromSideModes }, // CAM_SET_PIVOT_FROM_SIDE - { { 0x051FFFFF }, sCamSetNormal4Modes }, // CAM_SET_NORMAL4 + { { 0x00000000 }, 0x20000000, NULL }, // CAM_SET_NONE + { { 0x051FFFFF }, 0x20000000, sCamSetNormal0Modes }, // CAM_SET_NORMAL0 + { { 0x051FFFFF }, 0x20000000, sCamSetNormal1Modes }, // CAM_SET_NORMAL1 + { { 0x051FFFFF }, 0x20000000, sCamSetDungeon0Modes }, // CAM_SET_DUNGEON0 + { { 0x051FFFFF }, 0x20000000, sCamSetDungeon1Modes }, // CAM_SET_DUNGEON1 + { { 0x050FF7FF }, 0x20000000, sCamSetNormal3Modes }, // CAM_SET_NORMAL3 + { { 0x8500018F }, 0x20000000, sCamSetHorseModes }, // CAM_SET_HORSE + { { 0x051FFFFF }, 0x20000000, sCamSetBossGohmaModes }, // CAM_SET_BOSS_GOHMA + { { 0x051FFFFF }, 0x20000000, sCamSetBossDodongoModes }, // CAM_SET_BOSS_DODONGO + { { 0x051FFFFF }, 0x20000000, sCamSetBossBarinadeModes }, // CAM_SET_BOSS_BARINADE + { { 0x051FFFFF }, 0x20000000, sCamSetBossPhantomGanonModes }, // CAM_SET_BOSS_PHANTOM_GANON + { { 0x051FFFFF }, 0x20000000, sCamSetBossVolvagiaModes }, // CAM_SET_BOSS_VOLVAGIA + { { 0x051FFFFF }, 0x20000000, sCamSetBossBongoModes }, // CAM_SET_BOSS_BONGO + { { 0x051FFFFF }, 0x20000000, sCamSetBossMorphaModes }, // CAM_SET_BOSS_MORPHA + { { 0x051FFFFF }, 0x20000000, sCamSetBossTwinrovaPlatformModes }, // CAM_SET_BOSS_TWINROVA_PLATFORM + { { 0x051FFFFF }, 0x20000000, sCamSetBossTwinrovaFloorModes }, // CAM_SET_BOSS_TWINROVA_FLOOR + { { 0x051FFFFF }, 0x20000000, sCamSetBossGanondorfModes }, // CAM_SET_BOSS_GANONDORF + { { 0x051FFFFF }, 0x20000000, sCamSetBossGanonModes }, // CAM_SET_BOSS_GANON + { { 0x851FFFFF }, 0x20000000, sCamSetTowerClimbModes }, // CAM_SET_TOWER_CLIMB + { { 0x851FFFFF }, 0x20000000, sCamSetTowerUnusedModes }, // CAM_SET_TOWER_UNUSED + { { 0x8500000D }, 0x20000000, sCamSetMarketBalconyModes }, // CAM_SET_MARKET_BALCONY + { { 0x85000001 }, 0x20000000, sCamSetChuBowlingModes }, // CAM_SET_CHU_BOWLING + { { 0x85000001 }, 0x20000000, sCamSetPivotCrawlspaceModes }, // CAM_SET_PIVOT_CRAWLSPACE + { { 0x85000001 }, 0x20000000, sCamSetPivotShopBrowsingModes }, // CAM_SET_PIVOT_SHOP_BROWSING + { { 0x851E1FFF }, 0x20000000, sCamSetPivotInFrontModes }, // CAM_SET_PIVOT_IN_FRONT + { { 0x8C00000D }, 0x20000000, sCamSetPreRendFixedModes }, // CAM_SET_PREREND_FIXED + { { 0x8C00000D }, 0x20000000, sCamSetPreRendPivotModes }, // CAM_SET_PREREND_PIVOT + { { 0x8C000001 }, 0x20000000, sCamSetPreRendSideScrollModes }, // CAM_SET_PREREND_SIDE_SCROLL + { { 0xC5000001 }, 0x20000000, sCamSetDoor0Modes }, // CAM_SET_DOOR0 + { { 0xC5000003 }, 0x20000000, sCamSetDoorCModes }, // CAM_SET_DOORC + { { 0xC5000001 }, 0x20000000, sCamSetCrawlspaceModes }, // CAM_SET_CRAWLSPACE + { { 0xC5000001 }, 0x20000000, sCamSetStart0Modes }, // CAM_SET_START0 + { { 0xC5000001 }, 0x20000000, sCamSetStart1Modes }, // CAM_SET_START1 + { { 0x05000001 }, 0x20000000, sCamSetFree0Modes }, // CAM_SET_FREE0 + { { 0x05000001 }, 0x20000000, sCamSetFree2Modes }, // CAM_SET_FREE2 + { { 0x85000001 }, 0x20000000, sCamSetPivotCornerModes }, // CAM_SET_PIVOT_CORNER + { { 0x05000003 }, 0x20000000, sCamSetPivotWaterSurfaceModes }, // CAM_SET_PIVOT_WATER_SURFACE + { { 0xCE000001 }, 0x20000000, sCamSetCs0Modes }, // CAM_SET_CS_0 + { { 0x4E000001 }, 0x20000000, sCamSetCsTwistedHallwayModes }, // CAM_SET_CS_TWISTED_HALLWAY + { { 0x05000009 }, 0x20000000, sCamSetForestBirdsEyeModes }, // CAM_SET_FOREST_BIRDS_EYE + { { 0x45000001 }, 0x20000000, sCamSetSlowChestCsModes }, // CAM_SET_SLOW_CHEST_CS + { { 0x45000001 }, 0x20000000, sCamSetItemUnusedModes }, // CAM_SET_ITEM_UNUSED + { { 0x45000001 }, 0x20000000, sCamSetCs3Modes }, // CAM_SET_CS_3 + { { 0x45000001 }, 0x20000000, sCamSetCsAttentionModes }, // CAM_SET_CS_ATTENTION + { { 0x451FFFFF }, 0x20000000, sCamSetBeanGenericModes }, // CAM_SET_BEAN_GENERIC + { { 0x451FFFFF }, 0x20000000, sCamSetBeanLostWoodsModes }, // CAM_SET_BEAN_LOST_WOODS + { { 0xC5000001 }, 0x20000000, sCamSetSceneUnusedModes }, // CAM_SET_SCENE_UNUSED + { { 0x45000001 }, 0x20000000, sCamSetSceneTransitionModes }, // CAM_SET_SCENE_TRANSITION + { { 0x05000001 }, 0x20000000, sCamSetElevatorPlatformModes }, // CAM_SET_ELEVATOR_PLATFORM + { { 0x45000001 }, 0x20000000, sCamSetFireStaircaseModes }, // CAM_SET_FIRE_STAIRCASE + { { 0x45000001 }, 0x20000000, sCamSetForestUnusedModes }, // CAM_SET_FOREST_UNUSED + { { 0x45000001 }, 0x20000000, sCamSetForestDefeatPoeModes }, // CAM_SET_FOREST_DEFEAT_POE + { { 0x451FFFFF }, 0x20000000, sCamSetBigOctoModes }, // CAM_SET_BIG_OCTO + { { 0x05000033 }, 0x20000000, sCamSetMeadowBirdsEyeModes }, // CAM_SET_MEADOW_BIRDS_EYE + { { 0x05000033 }, 0x20000000, sCamSetMeadowUnusedModes }, // CAM_SET_MEADOW_UNUSED + { { 0x05000033 }, 0x20000000, sCamSetFireBirdsEyeModes }, // CAM_SET_FIRE_BIRDS_EYE + { { 0x4A000001 }, 0x20000000, sCamSetTurnAroundModes }, // CAM_SET_TURN_AROUND + { { 0x05000001 }, 0x20000000, sCamSetPivotVerticalModes }, // CAM_SET_PIVOT_VERTICAL + { { 0x051FFFFF }, 0x20000000, sCamSetNorm2Modes }, // CAM_SET_NORMAL2 + { { 0x0501E05F }, 0x20000000, sCamSetFishingModes }, // CAM_SET_FISHING + { { 0x45000001 }, 0x20000000, sCamSetCsCModes }, // CAM_SET_CS_C + { { 0x051FFFFF }, 0x20000000, sCamSetJabuTentacleModes }, // CAM_SET_JABU_TENTACLE + { { 0x051FFFFF }, 0x20000000, sCamSetDungeon2Modes }, // CAM_SET_DUNGEON2 + { { 0x051FFFFF }, 0x20000000, sCamSetDirectedYawModes }, // CAM_SET_DIRECTED_YAW + { { 0xC5000ECD }, 0x20000000, sCamSetPivotFromSideModes }, // CAM_SET_PIVOT_FROM_SIDE + { { 0x051FFFFF }, 0x20000000, sCamSetNormal4Modes }, // CAM_SET_NORMAL4 }; s32 Camera_Normal0(Camera* camera); diff --git a/src/code/z_demo.c b/src/code/z_demo.c index e0bc95f07f..4e9e0f1151 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -35,6 +35,10 @@ #include "assets/scenes/misc/hakaana_ouke/hakaana_ouke_scene.h" +#if ENABLE_CUTSCENE_IMPROVEMENTS +struct CutsceneCamera sCutsceneCameraInfo; +#endif + u16 sCurTextId = 0; u16 sCurOcarinaAction = 0; @@ -165,7 +169,11 @@ void Cutscene_DrawDebugInfo(PlayState* play, Gfx** dlist, CutsceneContext* csCtx void Cutscene_InitContext(PlayState* play, CutsceneContext* csCtx) { csCtx->state = CS_STATE_IDLE; + csCtx->curFrame = 0; csCtx->timer = 0.0f; + play->csCtx.scriptListCount = 0; + play->csCtx.scriptIndex = 0; + Audio_SetCutsceneFlag(0); } void Cutscene_StartManual(PlayState* play, CutsceneContext* csCtx) { @@ -1821,7 +1829,7 @@ void CutsceneCmd_MotionBlur(PlayState* play, CutsceneContext* csCtx, CsCmdMotion } } -void Cutscene_ProcessScript(PlayState* play, CutsceneContext* csCtx, u8* script) { +void Cutscene_ProcessScript(PlayState* play, CutsceneContext* csCtx, CutsceneData* script) { s16 i; s32 totalEntries; s32 cmdType; @@ -2351,7 +2359,6 @@ void Cutscene_SetupScripted(PlayState* play, CutsceneContext* csCtx) { sCurTextId = 0; sCurOcarinaAction = 0; - csCtx->unk_12 = 0; csCtx->playerCue = NULL; for (i = 0; i < ARRAY_COUNT(csCtx->actorCues); i++) { @@ -2365,6 +2372,12 @@ void Cutscene_SetupScripted(PlayState* play, CutsceneContext* csCtx) { csCtx->curFrame = 0xFFFF; +#if ENABLE_CUTSCENE_IMPROVEMENTS + csCtx->subCamId = CutsceneManager_GetCurrentSubCamId(CS_ID_GLOBAL_END); + CutsceneCamera_Init(Play_GetCamera(play, csCtx->subCamId), &sCutsceneCameraInfo); + csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; +#else + csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; gCamAtSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; gCamEyePointAppliedFrame = CS_CAM_DATA_NOT_APPLIED; @@ -2378,6 +2391,7 @@ void Cutscene_SetupScripted(PlayState* play, CutsceneContext* csCtx) { if (gUseCutsceneCam) { csCtx->subCamId = Play_CreateSubCamera(play); } +#endif if (gSaveContext.cutsceneTrigger == 0) { Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING); @@ -2488,3 +2502,9 @@ void Cutscene_SetScript(PlayState* play, void* script) { play->csCtx.script = script; } } + +void Cutscene_StartScripted(PlayState* play, u8 scriptIndex) { + PRINTF("(Cutscene_StartScripted) play->csCtx.scriptList: %08X\n", play->csCtx.scriptList); + Cutscene_SetScript(play, play->csCtx.scriptList[scriptIndex].script); + gSaveContext.cutsceneTrigger = 1; +} diff --git a/src/code/z_lib.c b/src/code/z_lib.c index d5f59a2a86..36200f73cf 100644 --- a/src/code/z_lib.c +++ b/src/code/z_lib.c @@ -627,3 +627,30 @@ void Sfx_PlaySfxAtPos(Vec3f* projectedPos, u16 sfxId) { Audio_PlaySfxGeneral(sfxId, projectedPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); } + +s32 Math_StepToIImpl(s32 start, s32 target, s32 step) { + s32 ret; + + if (target >= start) { + ret = start + step; + if (target >= ret) { + return ret; + } + } else { + ret = start - step; + if (ret >= target) { + return ret; + } + } + return target; +} + +void Math_StepToIGet(s32* pValue, s32 target, s32 step) { + *pValue = Math_StepToIImpl(*pValue, target, step); +} + +s32 Math_StepToI(s32* pValue, s32 target, s32 step) { + Math_StepToIGet(pValue, target, step); + + return target == *pValue; +} diff --git a/src/code/z_olib.c b/src/code/z_olib.c index 298f151e2c..9ad837008d 100644 --- a/src/code/z_olib.c +++ b/src/code/z_olib.c @@ -1,6 +1,7 @@ #include "z64math.h" #include "libc64/math64.h" #include "z_lib.h" +#include "z64olib.h" /** * Calculates the distances between `a` and `b` @@ -209,3 +210,68 @@ Vec3s OLib_Vec3fDiffBinAng(Vec3f* a, Vec3f* b) { return anglesBinAng; } + +/** + * Takes the sum of positions `a` (x,y,z coordinates) and `geo` (geographic coordinates), result is in x,y,z position + * Identical to Quake_AddVec from OoT + */ +Vec3f OLib_AddVecGeoToVec3f(Vec3f* a, VecGeo* geo) { + Vec3f sum; + Vec3f b = OLib_VecGeoToVec3f(geo); + + sum.x = a->x + b.x; + sum.y = a->y + b.y; + sum.z = a->z + b.z; + + return sum; +} + +/** + * Gets a x,y,z position diff depending on the mode + */ +void OLib_Vec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { + VecGeo geo; + + switch (mode) { + case OLIB_DIFF_OFFSET: + geo = OLib_Vec3fDiffToVecGeo(&a->pos, b); + geo.yaw -= a->rot.y; + *dest = OLib_VecGeoToVec3f(&geo); + break; + + case OLIB_DIFF: + dest->x = b->x - a->pos.x; + dest->y = b->y - a->pos.y; + dest->z = b->z - a->pos.z; + break; + + default: // OLIB_DIFF_COPY + *dest = *b; + break; + } +} + +/** + * Gets a x,y,z position sum depending on the mode + */ +void OLib_Vec3fAdd(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { + VecGeo geo; + + switch (mode) { + case OLIB_ADD_OFFSET: + geo = OLib_Vec3fToVecGeo(b); + geo.yaw += a->rot.y; + *dest = OLib_AddVecGeoToVec3f(&a->pos, &geo); + break; + + case OLIB_ADD: + dest->x = a->pos.x + b->x; + dest->y = a->pos.y + b->y; + dest->z = a->pos.z + b->z; + break; + + default: // OLIB_ADD_COPY + *dest = *b; + break; + } +} diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 1c8de94e6a..5ed3ecab6a 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -632,6 +632,321 @@ void Interface_UpdateHudAlphas(PlayState* play, s16 dimmingAlpha) { interfaceCtx->magicAlpha = risingAlpha; } + break; + + case HUD_VISIBILITY_HEARTS_MAGIC_C: + if ((interfaceCtx->bAlpha != 0) && (interfaceCtx->bAlpha > dimmingAlpha)) { + interfaceCtx->bAlpha = dimmingAlpha; + } + + if ((interfaceCtx->aAlpha != 0) && (interfaceCtx->aAlpha > dimmingAlpha)) { + interfaceCtx->aAlpha = dimmingAlpha; + } + + if ((interfaceCtx->minimapAlpha != 0) && (interfaceCtx->minimapAlpha > dimmingAlpha)) { + interfaceCtx->minimapAlpha = dimmingAlpha; + } + + if (interfaceCtx->cLeftAlpha != 255) { + interfaceCtx->cLeftAlpha = risingAlpha; + } + + if (interfaceCtx->cDownAlpha != 255) { + interfaceCtx->cDownAlpha = risingAlpha; + } + + if (interfaceCtx->cRightAlpha != 255) { + interfaceCtx->cRightAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + if (interfaceCtx->healthAlpha != 255) { + interfaceCtx->healthAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_ALL_NO_MINIMAP: + if ((interfaceCtx->minimapAlpha != 0) && (interfaceCtx->minimapAlpha > dimmingAlpha)) { + interfaceCtx->minimapAlpha = dimmingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if (interfaceCtx->aAlpha != 255) { + interfaceCtx->aAlpha = risingAlpha; + } + + if (interfaceCtx->cLeftAlpha != 255) { + interfaceCtx->cLeftAlpha = risingAlpha; + } + + if (interfaceCtx->cDownAlpha != 255) { + interfaceCtx->cDownAlpha = risingAlpha; + } + + if (interfaceCtx->cRightAlpha != 255) { + interfaceCtx->cRightAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + if (interfaceCtx->healthAlpha != 255) { + interfaceCtx->healthAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_A_B_C: + if ((interfaceCtx->minimapAlpha != 0) && (interfaceCtx->minimapAlpha > dimmingAlpha)) { + interfaceCtx->minimapAlpha = dimmingAlpha; + } + + if ((interfaceCtx->magicAlpha != 0) && (interfaceCtx->magicAlpha > dimmingAlpha)) { + interfaceCtx->magicAlpha = dimmingAlpha; + } + + if ((interfaceCtx->healthAlpha != 0) && (interfaceCtx->healthAlpha > dimmingAlpha)) { + interfaceCtx->healthAlpha = dimmingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if (interfaceCtx->aAlpha != 255) { + interfaceCtx->aAlpha = risingAlpha; + } + + if (interfaceCtx->cLeftAlpha != 255) { + interfaceCtx->cLeftAlpha = risingAlpha; + } + + if (interfaceCtx->cDownAlpha != 255) { + interfaceCtx->cDownAlpha = risingAlpha; + } + + if (interfaceCtx->cRightAlpha != 255) { + interfaceCtx->cRightAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_B_MINIMAP: + if ((interfaceCtx->aAlpha != 0) && (interfaceCtx->aAlpha > dimmingAlpha)) { + interfaceCtx->aAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if ((interfaceCtx->magicAlpha != 0) && (interfaceCtx->magicAlpha > dimmingAlpha)) { + interfaceCtx->magicAlpha = dimmingAlpha; + } + + if ((interfaceCtx->healthAlpha != 0) && (interfaceCtx->healthAlpha > dimmingAlpha)) { + interfaceCtx->healthAlpha = dimmingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if (interfaceCtx->minimapAlpha != 255) { + interfaceCtx->minimapAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_HEARTS_MAGIC_MINIMAP: + if ((interfaceCtx->bAlpha != 0) && (interfaceCtx->bAlpha > dimmingAlpha)) { + interfaceCtx->bAlpha = dimmingAlpha; + } + + if ((interfaceCtx->aAlpha != 0) && (interfaceCtx->aAlpha > dimmingAlpha)) { + interfaceCtx->aAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if (interfaceCtx->healthAlpha != 255) { + interfaceCtx->healthAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + if (interfaceCtx->minimapAlpha != 255) { + interfaceCtx->minimapAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_A_HEARTS_MAGIC_MINIMAP: + if ((interfaceCtx->bAlpha != 0) && (interfaceCtx->bAlpha > dimmingAlpha)) { + interfaceCtx->bAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if (interfaceCtx->aAlpha != 255) { + interfaceCtx->aAlpha = risingAlpha; + } + + if (interfaceCtx->minimapAlpha != 255) { + interfaceCtx->minimapAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + if (interfaceCtx->healthAlpha != 255) { + interfaceCtx->healthAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_B_MAGIC: + if ((interfaceCtx->aAlpha != 0) && (interfaceCtx->aAlpha > dimmingAlpha)) { + interfaceCtx->aAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if ((interfaceCtx->minimapAlpha != 0) && (interfaceCtx->minimapAlpha > dimmingAlpha)) { + interfaceCtx->minimapAlpha = dimmingAlpha; + } + + if ((interfaceCtx->healthAlpha != 0) && (interfaceCtx->healthAlpha > dimmingAlpha)) { + interfaceCtx->healthAlpha = dimmingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + break; + + case HUD_VISIBILITY_A_B: + if (interfaceCtx->aAlpha != 255) { + interfaceCtx->aAlpha = risingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if ((interfaceCtx->minimapAlpha != 0) && (interfaceCtx->minimapAlpha > dimmingAlpha)) { + interfaceCtx->minimapAlpha = dimmingAlpha; + } + + if ((interfaceCtx->magicAlpha != 0) && (interfaceCtx->magicAlpha > dimmingAlpha)) { + interfaceCtx->magicAlpha = dimmingAlpha; + } + + if ((interfaceCtx->healthAlpha != 0) && (interfaceCtx->healthAlpha > dimmingAlpha)) { + interfaceCtx->healthAlpha = dimmingAlpha; + } + + break; + + case HUD_VISIBILITY_A_B_HEARTS_MAGIC_MINIMAP: + if ((interfaceCtx->cLeftAlpha != 0) && (interfaceCtx->cLeftAlpha > dimmingAlpha)) { + interfaceCtx->cLeftAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cDownAlpha != 0) && (interfaceCtx->cDownAlpha > dimmingAlpha)) { + interfaceCtx->cDownAlpha = dimmingAlpha; + } + + if ((interfaceCtx->cRightAlpha != 0) && (interfaceCtx->cRightAlpha > dimmingAlpha)) { + interfaceCtx->cRightAlpha = dimmingAlpha; + } + + if (interfaceCtx->bAlpha != 255) { + interfaceCtx->bAlpha = risingAlpha; + } + + if (interfaceCtx->aAlpha != 255) { + interfaceCtx->aAlpha = risingAlpha; + } + + if (interfaceCtx->minimapAlpha != 255) { + interfaceCtx->minimapAlpha = risingAlpha; + } + + if (interfaceCtx->magicAlpha != 255) { + interfaceCtx->magicAlpha = risingAlpha; + } + + if (interfaceCtx->healthAlpha != 255) { + interfaceCtx->healthAlpha = risingAlpha; + } + break; } diff --git a/src/code/z_play.c b/src/code/z_play.c index e6465607de..fab5044038 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -9,6 +9,7 @@ #include "n64dd.h" #endif #include "z64frame_advance.h" +#include "z64camera.h" #if INCLUDE_EXAMPLE_SCENE #include "assets/scenes/example/example_scene.h" @@ -247,6 +248,9 @@ void Play_Destroy(GameState* thisx) { } Letterbox_Destroy(); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Destroy(); +#endif TransitionFade_Destroy(&this->transitionFadeFlash); VisMono_Destroy(&gPlayVisMono); @@ -308,6 +312,9 @@ void Play_Init(GameState* thisx) { #endif KaleidoManager_Init(this); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif View_Init(&this->view, gfxCtx); Audio_SetExtraFilter(0); Quake_Init(); @@ -497,6 +504,14 @@ void Play_Init(GameState* thisx) { Camera_InitDataUsingPlayer(&this->mainCamera, player); Camera_RequestMode(&this->mainCamera, CAM_MODE_NORMAL); +#if ENABLE_CUTSCENE_IMPROVEMENTS + if ((player->actor.params & 0xFF) != 0xFF) { + Camera_ChangeActorCsCamIndex(&this->mainCamera, player->actor.params & 0xFF); + } + + CutsceneManager_StoreCamera(&this->mainCamera); +#endif + playerStartBgCamIndex = PARAMS_GET_U(player->actor.params, 0, 8); if (playerStartBgCamIndex != 0xFF) { PRINTF("player has start camera ID (" VT_FGCOL(BLUE) "%d" VT_RST ")\n", playerStartBgCamIndex); @@ -586,6 +601,18 @@ void Play_Update(PlayState* this) { #define FRAMEADVANCE_CAN_UPDATE true #endif + if (CHECK_BTN_ALL(input[0].press.button, BTN_L)) { + if (!CutsceneManager_IsNext(0)) { + CutsceneManager_Queue(0); + } else { + CutsceneManager_Start(0, &GET_PLAYER(this)->actor); + } + + PRINTF("pressed!\n"); + } + + PRINTF("CutsceneManager_IsNext(0):%d\n", CutsceneManager_IsNext(0)); + if (FRAMEADVANCE_CAN_UPDATE) { if ((this->transitionMode == TRANS_MODE_OFF) && (this->transitionTrigger != TRANS_TRIGGER_OFF)) { this->transitionMode = TRANS_MODE_SETUP; @@ -1079,6 +1106,10 @@ void Play_Update(PlayState* this) { PLAY_LOG(3777); Letterbox_Update(R_UPDATE_RATE); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Update(R_UPDATE_RATE); +#endif + PLAY_LOG(3783); TransitionFade_Update(&this->transitionFadeFlash, R_UPDATE_RATE); } else { @@ -1326,6 +1357,10 @@ void Play_Draw(PlayState* this) { #endif if (!DEBUG_FEATURES || (R_HREG_MODE != HREG_MODE_PLAY) || R_PLAY_RUN_DRAW) { +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Draw(gfxCtx); +#endif + POLY_OPA_DISP = Play_SetFog(this, POLY_OPA_DISP); POLY_XLU_DISP = Play_SetFog(this, POLY_XLU_DISP); @@ -1667,6 +1702,11 @@ void Play_Main(GameState* thisx) { Play_Draw(this); PLAY_LOG(4587); + +#if ENABLE_CUTSCENE_IMPROVEMENTS + CutsceneManager_Update(); + // CutsceneManager_ClearWaiting(); +#endif } // original name: "Game_play_demo_mode_check" @@ -1778,6 +1818,10 @@ void Play_InitScene(PlayState* this, s32 spawn) { this->sceneMaterialAnims = NULL; #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + this->actorCsCamList = NULL; +#endif + this->numActorEntries = 0; Object_InitContext(this, &this->objectCtx); @@ -2204,3 +2248,17 @@ s32 func_800C0DB4(PlayState* this, Vec3f* pos) { return false; } } + +#if ENABLE_CUTSCENE_IMPROVEMENTS +u16 Play_GetActorCsCamSetting(PlayState* this, s32 csCamDataIndex) { + ActorCsCamInfo* actorCsCamList = &this->actorCsCamList[csCamDataIndex]; + + return actorCsCamList->setting; +} + +Vec3s* Play_GetActorCsCamFuncData(PlayState* this, s32 csCamDataIndex) { + ActorCsCamInfo* actorCsCamList = &this->actorCsCamList[csCamDataIndex]; + + return SEGMENTED_TO_VIRTUAL(actorCsCamList->actorCsCamFuncData); +} +#endif diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 75275899d6..075736cb41 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -614,7 +614,7 @@ int Player_InBlockingCsMode(PlayState* play, Player* this) { int Player_InCsMode(PlayState* play) { Player* this = GET_PLAYER(play); - return Player_InBlockingCsMode(play, this) || (this->unk_6AD == 4); + return CutsceneManager_GetCurrentCsId() == CS_ID_NONE && (Player_InBlockingCsMode(play, this) || (this->unk_6AD == 4)); } /** diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 0c8c3b4fe7..8cd396d2b1 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -528,11 +528,20 @@ void Scene_SetTransitionForNextEntrance(PlayState* play) { } #if ENABLE_ANIMATED_MATERIALS - void Scene_CommandAnimatedMaterials(PlayState* play, SceneCmd* cmd) { play->sceneMaterialAnims = SEGMENTED_TO_VIRTUAL(cmd->textureAnimations.segment); } +#endif + +#if ENABLE_CUTSCENE_IMPROVEMENTS +void Scene_CommandCutsceneList(PlayState* play, SceneCmd* cmd) { + CutsceneManager_Init(play, SEGMENTED_TO_VIRTUAL(cmd->cutsceneList.segment), cmd->cutsceneList.num); + PRINTF("(Scene_CommandCutsceneList) segment: 0x%08X, num: %d\n", cmd->cutsceneList.segment, cmd->cutsceneList.num); +} +void Scene_CommandActorCutsceneCamList(PlayState* play, SceneCmd* cmd) { + play->actorCsCamList = SEGMENTED_TO_VIRTUAL(cmd->actorCsCamList.segment); +} #endif SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX] = { @@ -568,6 +577,10 @@ SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX] = { #if ENABLE_ANIMATED_MATERIALS Scene_CommandAnimatedMaterials, // SCENE_CMD_ID_ANIMATED_MATERIAL_LIST #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS + Scene_CommandCutsceneList, // SCENE_CMD_ID_ACTOR_CUTSCENE_LIST + Scene_CommandActorCutsceneCamList, // SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST +#endif }; RomFile sNaviQuestHintFiles[] = { diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index d922733344..874da7ac65 100644 --- a/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -2308,6 +2308,9 @@ void FileSelect_InitContext(GameState* thisx) { } void FileSelect_Destroy(GameState* thisx) { +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Destroy(); +#endif } void FileSelect_Init(GameState* thisx) { @@ -2345,6 +2348,9 @@ void FileSelect_Init(GameState* thisx) { #endif Matrix_Init(&this->state); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif View_Init(&this->view, this->state.gfxCtx); this->state.main = FileSelect_Main; this->state.destroy = FileSelect_Destroy; diff --git a/src/overlays/gamestates/ovl_opening/z_opening.c b/src/overlays/gamestates/ovl_opening/z_opening.c index 1ae248381a..4d94951216 100644 --- a/src/overlays/gamestates/ovl_opening/z_opening.c +++ b/src/overlays/gamestates/ovl_opening/z_opening.c @@ -29,6 +29,9 @@ void TitleSetup_Main(GameState* thisx) { } void TitleSetup_Destroy(GameState* thisx) { +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Destroy(); +#endif } void TitleSetup_Init(GameState* thisx) { @@ -36,6 +39,9 @@ void TitleSetup_Init(GameState* thisx) { R_UPDATE_RATE = 1; Matrix_Init(&this->state); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif View_Init(&this->view, this->state.gfxCtx); this->state.main = TitleSetup_Main; this->state.destroy = TitleSetup_Destroy; diff --git a/src/overlays/gamestates/ovl_select/z_select.c b/src/overlays/gamestates/ovl_select/z_select.c index a49261e37b..ddf5b3368a 100644 --- a/src/overlays/gamestates/ovl_select/z_select.c +++ b/src/overlays/gamestates/ovl_select/z_select.c @@ -28,6 +28,10 @@ void MapSelect_Init(GameState* thisx) { this->pageDownStops[6] = 91; // Escaping Ganon's Tower 3 this->pageDownIndex = 0; this->sceneTotal = ARRAY_COUNT(sScenes); + +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif View_Init(&this->view, this->state.gfxCtx); this->view.flags = (VIEW_PROJECTION_ORTHO | VIEW_VIEWPORT); this->verticalInputAccumulator = 0; @@ -106,6 +110,10 @@ void MapSelect_Destroy(GameState* thisx) { PRINTF("%c", BEL); // "view_cleanup will hang, so it won't be called" PRINTF("*** view_cleanupはハングアップするので、呼ばない ***\n"); + +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Destroy(); +#endif } void MapSelect_UpdateMenu(MapSelectState* this) { diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c index 6aa88c349f..2d41440b7e 100644 --- a/src/overlays/gamestates/ovl_title/z_title.c +++ b/src/overlays/gamestates/ovl_title/z_title.c @@ -169,6 +169,10 @@ void ConsoleLogo_Destroy(GameState* thisx) { #if PLATFORM_N64 func_800014E8(); #endif + +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Destroy(); +#endif } void ConsoleLogo_Init(GameState* thisx) { @@ -192,6 +196,9 @@ void ConsoleLogo_Init(GameState* thisx) { DMA_REQUEST_SYNC(this->staticSegment, (uintptr_t)_nintendo_rogo_staticSegmentRomStart, size, "../z_title.c", 615); R_UPDATE_RATE = 1; Matrix_Init(&this->state); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif View_Init(&this->view, this->state.gfxCtx); this->state.main = ConsoleLogo_Main; this->state.destroy = ConsoleLogo_Destroy; From 6b449f03b6170427f629b55114c999f5f94d3fc0 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:38:03 +0100 Subject: [PATCH 04/13] fix issues --- include/z64camera.h | 10 +- include/z64cutscene.h | 2 +- include/z64player.h | 9 +- src/code/cutscene_manager.c | 17 ++- src/code/z_actor.c | 45 ++++--- src/code/z_camera.c | 111 +++++++++++------- src/code/z_camera_data.inc.c | 16 +++ src/code/z_demo.c | 3 + src/code/z_play.c | 23 ++-- src/code/z_player_lib.c | 7 +- src/overlays/actors/ovl_En_Holl/z_en_holl.c | 7 ++ src/overlays/actors/ovl_En_Okuta/z_en_okuta.c | 7 ++ 12 files changed, 177 insertions(+), 80 deletions(-) diff --git a/include/z64camera.h b/include/z64camera.h index d6900925a8..2667aaa676 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -205,7 +205,10 @@ typedef enum CameraSettingType { /* 0x3F */ CAM_SET_DIRECTED_YAW, // Does not auto-update yaw, tends to keep the camera pointed at a certain yaw (used by biggoron and final spirit lowering platform) "TEPPEN" /* 0x40 */ CAM_SET_PIVOT_FROM_SIDE, // Fixed side view, allows rotation of camera (eg. Potion Shop, Meadow at fairy grotto) "CIRCLE7" /* 0x41 */ CAM_SET_NORMAL4, - /* 0x42 */ CAM_SET_MAX +#if ENABLE_CUTSCENE_IMPROVEMENTS + /* 0x42 */ CAM_SET_FIXED1, +#endif + /* 0x43 */ CAM_SET_MAX } CameraSettingType; typedef enum CameraModeType { @@ -305,7 +308,10 @@ typedef enum CameraFuncType { /* 0x44 */ CAM_FUNC_SPEC7, /* 0x45 */ CAM_FUNC_SPEC8, /* 0x46 */ CAM_FUNC_SPEC9, - /* 0x47 */ CAM_FUNC_MAX +#if ENABLE_CUTSCENE_IMPROVEMENTS + /* 0x47 */ CAM_FUNC_FIXED1, +#endif + /* 0x48 */ CAM_FUNC_MAX } CameraFuncType; typedef enum CameraDataType { diff --git a/include/z64cutscene.h b/include/z64cutscene.h index feac14c170..002f363866 100644 --- a/include/z64cutscene.h +++ b/include/z64cutscene.h @@ -526,7 +526,7 @@ typedef struct CutsceneEntry { typedef enum CutsceneCamId { // global (see sGlobalCamDataSettings) - /* -66 */ CS_CAM_ID_GLOBAL_NORMAL4 = -66, // CAM_SET_NORMAL4 (set to -CAM_SET_MAX) + /* -66 */ CS_CAM_ID_GLOBAL_NORMAL4 = -67, // CAM_SET_NORMAL4 (set to -CAM_SET_MAX) /* -65 */ CS_CAM_ID_GLOBAL_PIVOT_FROM_SIDE, // CAM_SET_PIVOT_FROM_SIDE /* -64 */ CS_CAM_ID_GLOBAL_DIRECTED_YAW, // CAM_SET_DIRECTED_YAW /* -63 */ CS_CAM_ID_GLOBAL_DUNGEON2, // CAM_SET_DUNGEON2 diff --git a/include/z64player.h b/include/z64player.h index 19acbeff30..3e1b8df07b 100644 --- a/include/z64player.h +++ b/include/z64player.h @@ -4,6 +4,7 @@ #include "z64actor.h" #include "alignment.h" #include "face_change.h" +#include "config.h" struct Player; @@ -766,6 +767,12 @@ typedef struct WeaponInfo { #define PLAYER_STATE3_RESTORE_NAYRUS_LOVE (1 << 6) // Set by ocarina effects actors when destroyed to signal Nayru's Love may be restored (see `ACTOROVL_ALLOC_ABSOLUTE`) #define PLAYER_STATE3_FLYING_WITH_HOOKSHOT (1 << 7) // Flying in the air with the hookshot as it pulls Player toward its destination +#if ENABLE_CUTSCENE_IMPROVEMENTS +#define PLAYER_STATE3_ACTOR_CS_HALT (1 << 8) // Prevents updating the actor while an actor cutscene is playing +#else +#define PLAYER_STATE3_ACTOR_CS_HALT (0) +#endif + #define PLAYER_ALLOC_GI_MIN 0x2880 // title card maximum file size typedef void (*PlayerActionFunc)(struct Player*, struct PlayState*); @@ -862,7 +869,7 @@ typedef struct Player { /* 0x0688 */ Actor* boomerangActor; /* 0x068C */ Actor* naviActor; /* 0x0690 */ s16 naviTextId; - /* 0x0692 */ u8 stateFlags3; + /* 0x0692 */ u32 stateFlags3; /* 0x0693 */ s8 exchangeItemId; /* 0x0694 */ Actor* talkActor; // Actor offering to talk, or currently talking to, depending on context /* 0x0698 */ f32 talkActorDistance; // xz distance away from `talkActor` diff --git a/src/code/cutscene_manager.c b/src/code/cutscene_manager.c index 9785e428fa..5297126037 100644 --- a/src/code/cutscene_manager.c +++ b/src/code/cutscene_manager.c @@ -291,8 +291,6 @@ s16 CutsceneManager_Update(void) { // CutsceneManager_StartWithPlayerCs(CS_ID_GLOBAL_RETURN_TO_CAM, &GET_PLAYER(sCutsceneMgr.play)->actor); // } - PRINTF("(CutsceneManager_Update) csId: %d, endCsId: %d, length: %d\n", sCutsceneMgr.csId, sCutsceneMgr.endCsId, sCutsceneMgr.length); - if (sCutsceneMgr.endCsId == CS_ID_NONE) { if (sCutsceneMgr.csId != CS_ID_NONE) { if (sCutsceneMgr.length > 0) { @@ -384,6 +382,12 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { Camera* subCam; Camera* retCam; s32 csType = 0; + Player* player = GET_PLAYER(sCutsceneMgr.play); + + // set the cutscene halt flag + if (!(player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT)) { + player->stateFlags3 |= PLAYER_STATE3_ACTOR_CS_HALT; + } if ((csId <= CS_ID_NONE) || (sCutsceneMgr.csId != CS_ID_NONE)) { return csId; @@ -404,9 +408,6 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { csType = 2; } - PRINTF("(CutsceneManager_Start) csType: %d, csEntry->scriptIndex:%d, csEntry->priority: %d\n", - csType, csEntry->scriptIndex, csEntry->priority); - if (csType != 0) { sCutsceneMgr.retCamId = Play_GetActiveCamId(sCutsceneMgr.play); sCutsceneMgr.subCamId = Play_CreateSubCamera(sCutsceneMgr.play); @@ -453,6 +454,12 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { s16 CutsceneManager_Stop(s16 csId) { CutsceneEntry* csEntry; + Player* player = GET_PLAYER(sCutsceneMgr.play); + + // unset the cutscene halt flag + if (player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { + player->stateFlags3 &= ~PLAYER_STATE3_ACTOR_CS_HALT; + } if (csId <= CS_ID_NONE) { return csId; diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 3e80120e93..01c34038cc 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -4,6 +4,7 @@ #include "rand.h" #include "terminal.h" #include "versions.h" +#include "config.h" #include "overlays/actors/ovl_Arms_Hook/z_arms_hook.h" #include "overlays/actors/ovl_En_Part/z_en_part.h" @@ -326,6 +327,12 @@ void Attention_Init(Attention* attention, Actor* actor, PlayState* play) { void Attention_Draw(Attention* attention, PlayState* play) { Actor* actor; // used for both the reticle actor and arrow hover actor +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { + return; + } +#endif + actor = attention->reticleActor; OPEN_DISPS(play->state.gfxCtx, "../z_actor.c", 2029); @@ -2315,38 +2322,44 @@ void Actor_InitContext(PlayState* play, ActorContext* actorCtx, ActorEntry* play func_8002FA60(play); } -u32 sCategoryFreezeMasks[ACTORCAT_MAX] = { +typedef struct ActorFreezeMasks { + u32 mask1; // stateFlags1 + u32 mask2; // stateFlags2 + u32 mask3; // stateFlags3 +} ActorFreezeMasks; + +ActorFreezeMasks sCategoryFreezeMasks[ACTORCAT_MAX] = { // ACTORCAT_SWITCH - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_BG - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_PLAYER - 0, + { 0, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_EXPLOSIVE - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_NPC - PLAYER_STATE1_DEAD, + { PLAYER_STATE1_DEAD, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_ENEMY - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_PROP - PLAYER_STATE1_DEAD | PLAYER_STATE1_28, + { PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_ITEMACTION - 0, + { 0, 0, 0 }, // ACTORCAT_MISC - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_BOSS - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, // ACTORCAT_DOOR - 0, + { 0, 0, 0 }, // ACTORCAT_CHEST - PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, }; void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { s32 i; Actor* actor; Player* player; - u32* categoryFreezeMaskP; + ActorFreezeMasks* categoryFreezeMaskP; u32 freezeExceptionFlag; u32 canFreezeCategory; Actor* sp74; @@ -2395,7 +2408,9 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { } for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++, categoryFreezeMaskP++) { - canFreezeCategory = (*categoryFreezeMaskP & player->stateFlags1); + ActorFreezeMasks curEntry = *categoryFreezeMaskP; + + canFreezeCategory = (curEntry.mask1 & player->stateFlags1) || (curEntry.mask2 & player->stateFlags2) || (curEntry.mask3 & player->stateFlags3); actor = actorCtx->actorLists[i].head; while (actor != NULL) { diff --git a/src/code/z_camera.c b/src/code/z_camera.c index 4c4d7ae6a0..b4ca4929ad 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -3,6 +3,7 @@ #include "quake.h" #include "terminal.h" #include "overlays/actors/ovl_En_Horse/z_en_horse.h" +#include "config.h" #pragma increment_block_number "gc-eu:192 gc-eu-mq:192 gc-jp:192 gc-jp-ce:192 gc-jp-mq:192 gc-us:192 gc-us-mq:192" \ "ntsc-1.0:192 ntsc-1.1:192 ntsc-1.2:192 pal-1.0:192 pal-1.1:192" @@ -39,6 +40,9 @@ s32 Camera_QRegInit(void); #define CAM_DEBUG_RELOAD_PARAMS true #endif +#define CAMERA_CHECK_FLAGS(settings, mask) ((settings.flags & 0x20000000) ? sCameraSettings[camera->setting].unk_00 & (mask) : sCameraSettings[camera->setting].flags & (mask)) +#define CAM_DATA_IS_BG (1 << 12) // if not set, then cam data is for actor cutscenes + /** * Camera data is stored in both read-only data and OREG as s16, and then converted to the appropriate type during * runtime. If a small f32 is being stored as an s16, it is common to store that value 100 times larger than the @@ -1849,7 +1853,7 @@ s32 Camera_Normal2(Camera* camera) { case 10: case 20: case 25: - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); rwData->unk_00 = Camera_Vec3sToVec3f(&bgCamFuncData->pos); rwData->unk_20 = bgCamFuncData->rot.x; rwData->unk_22 = bgCamFuncData->rot.y; @@ -3994,7 +3998,7 @@ s32 Camera_KeepOn0(Camera* camera) { CAM_DEBUG_RELOAD_PREG(camera); - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); *eyeNext = Camera_Vec3sToVec3f(&bgCamFuncData->pos); *eye = *eyeNext; @@ -4059,7 +4063,7 @@ s32 Camera_Fixed1(Camera* camera) { if (RELOAD_PARAMS(camera) || CAM_DEBUG_RELOAD_PARAMS) { CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); rwData->eyePosRotTarget.pos = Camera_Vec3sToVec3f(&bgCamFuncData->pos); rwData->eyePosRotTarget.rot = bgCamFuncData->rot; rwData->fov = bgCamFuncData->fov; @@ -4139,7 +4143,7 @@ s32 Camera_Fixed2(Camera* camera) { roData->interfaceField = GET_NEXT_RO_DATA(values); rwData->fov = roData->fov * 100.0f; - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); if (bgCamFuncData != NULL) { rwData->eye = Camera_Vec3sToVec3f(&bgCamFuncData->pos); if (bgCamFuncData->fov != -1) { @@ -4204,7 +4208,7 @@ s32 Camera_Fixed3(Camera* camera) { Fixed3ReadWriteData* rwData = &camera->paramData.fixd3.rwData; s32 pad; - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); eyeAtOffset = OLib_Vec3fDiffToVecGeo(eye, at); @@ -4291,7 +4295,7 @@ s32 Camera_Fixed4(Camera* camera) { roData->fov = GET_NEXT_RO_DATA(values); roData->interfaceField = GET_NEXT_RO_DATA(values); - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); if (bgCamFuncData != NULL) { rwData->eyeTarget = Camera_Vec3sToVec3f(&bgCamFuncData->pos); } else { @@ -4694,7 +4698,7 @@ s32 Camera_Data4(Camera* camera) { roData->fov = GET_NEXT_RO_DATA(values); roData->interfaceField = GET_NEXT_RO_DATA(values); - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); rwData->eyePosRot.pos = Camera_Vec3sToVec3f(&bgCamFuncData->pos); rwData->eyePosRot.rot = bgCamFuncData->rot; fov = bgCamFuncData->fov; @@ -4953,7 +4957,7 @@ s32 Camera_Unique3(Camera* camera) { break; } - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); camera->eyeNext = Camera_Vec3sToVec3f(&bgCamFuncData->pos); camera->eye = camera->eyeNext; bgCamRot = bgCamFuncData->rot; @@ -5068,7 +5072,7 @@ s32 Camera_Unique0(Camera* camera) { func_80043B60(camera); camera->stateFlags &= ~CAM_STATE_CHECK_BG; - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); rwData->eyeAndDirection.point = Camera_Vec3sToVec3f(&bgCamFuncData->pos); *eye = camera->eyeNext = rwData->eyeAndDirection.point; @@ -5227,7 +5231,7 @@ s32 Camera_Unique7(Camera* camera) { } CAM_DEBUG_RELOAD_PREG(camera); - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); *eyeNext = Camera_Vec3sToVec3f(&bgCamFuncData->pos); *eye = *eyeNext; @@ -7210,7 +7214,7 @@ s32 Camera_Special6(Camera* camera) { eyeAtOffset = OLib_Vec3fDiffToVecGeo(eye, at); - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); bgCamPos = Camera_Vec3sToVec3f(&bgCamFuncData->pos); bgCamRot = bgCamFuncData->rot; fov = bgCamFuncData->fov; @@ -7354,7 +7358,7 @@ s32 Camera_Special9(Camera* camera) { if (doorParams->timer1 <= 0) { camera->animState++; if (roData->interfaceField & SPECIAL9_FLAG_0) { - bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamFuncData(camera); + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); *eyeNext = Camera_Vec3sToVec3f(&bgCamFuncData->pos); spAC = *eye = *eyeNext; } else { @@ -7777,7 +7781,7 @@ s32 Camera_UpdateWater(Camera* camera) { Player* player = camera->player; s16 prevBgId; - if (!(camera->stateFlags & CAM_STATE_CHECK_WATER) || sCameraSettings[camera->setting].unk_00 & 0x40000000) { + if (!(camera->stateFlags & CAM_STATE_CHECK_WATER) || CAMERA_CHECK_FLAGS(sCameraSettings[camera->setting], 0x40000000)) { return 0; } @@ -8032,6 +8036,15 @@ void Camera_UpdateDistortion(Camera* camera) { #define ENABLE_DEBUG_CAM_UPDATE false #endif +// probably useless? +s32 Camera_800CB854(Camera* camera) { +#if ENABLE_CUTSCENE_IMPROVEMENTS + return camera->player->stateFlags1 & PLAYER_STATE1_5; +#else + return 0; +#endif +} + Vec3s Camera_Update(Camera* camera) { static s32 sOOBTimer = 0; Vec3f viewAt; @@ -8114,6 +8127,10 @@ Vec3s Camera_Update(Camera* camera) { camera->nextBgId = bgId; if (bgId == BGCHECK_SCENE) { camera->nextBgCamIndex = bgCamIndex; + +#if ENABLE_CUTSCENE_IMPROVEMENTS + camera->nextBgCamIndex |= CAM_DATA_IS_BG; +#endif } } } @@ -8155,15 +8172,18 @@ Vec3s Camera_Update(Camera* camera) { Camera_CalcAtDefault(camera, &eyeAtAngle, 0.0f, false); } + if (D_8011D3F0 != 0) { + D_8011D3F0--; + } + if (camera->status == CAM_STAT_ACTIVE) { if ((gSaveContext.gameMode != GAMEMODE_NORMAL) && (gSaveContext.gameMode != GAMEMODE_END_CREDITS)) { sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); Camera_UpdateInterface(sCameraInterfaceField); - } else if ((D_8011D3F0 != 0) && (camera->camId == CAM_ID_MAIN)) { - D_8011D3F0--; + } else if (((D_8011D3F0 != 0) || Camera_800CB854(camera)) && (camera->camId == CAM_ID_MAIN)) { sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_LARGE, CAM_HUD_VISIBILITY_NOTHING_ALT, 0); Camera_UpdateInterface(sCameraInterfaceField); - } else if (camera->play->transitionMode != TRANS_MODE_OFF) { + } else if ((camera->play->transitionMode != TRANS_MODE_OFF) && (camera->camId != CAM_ID_MAIN)) { sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_IGNORE, CAM_HUD_VISIBILITY_NOTHING_ALT, 0); Camera_UpdateInterface(sCameraInterfaceField); } else if (camera->play->csCtx.state != CS_STATE_IDLE) { @@ -8617,7 +8637,7 @@ s32 Camera_RequestBgCam(Camera* camera, s32 requestedBgCamIndex) { } if (!(camera->behaviorFlags & CAM_BEHAVIOR_BG_PROCESSED)) { - requestedCamSetting = Camera_GetBgCamSetting(camera, requestedBgCamIndex); + requestedCamSetting = Camera_GetBgCamOrActorCsCamSetting(camera, requestedBgCamIndex); camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; #if DEBUG_FEATURES settingChangeSuccessful = Camera_RequestSettingImpl(camera, requestedCamSetting, @@ -8828,7 +8848,7 @@ s32 Camera_ChangeDoorCam(Camera* camera, Actor* doorActor, s16 bgCamIndex, f32 a Camera_RequestSetting(camera, CAM_SET_DOORC); PRINTF(".... change default door camera (set %d)\n", CAM_SET_DOORC); } else { - s32 setting = Camera_GetBgCamSetting(camera, bgCamIndex); + s32 setting = Camera_GetBgCamOrActorCsCamSetting(camera, bgCamIndex); camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; @@ -8960,8 +8980,37 @@ s16 Camera_SetFinishedFlag(Camera* camera) { return camera->camId; } +/** + * Returns the CameraSettingType of the camera from either the bgCam or the actorCsCam at index `camDataId` + */ +s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId) { +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (camDataId & CAM_DATA_IS_BG) { + return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); + } else { + return Play_GetActorCsCamSetting(camera->play, camDataId); + } +#else + return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, bgCamIndex, BGCHECK_SCENE); +#endif +} + +/** + * Returns either the bgCam data or the actorCsCam data at index `camDataId` + */ +Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId) { +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (camDataId & CAM_DATA_IS_BG) { + return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); + } else { + return Play_GetActorCsCamFuncData(camera->play, camDataId); + } +#else + return return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId, BGCHECK_SCENE); +#endif +} + #if ENABLE_CUTSCENE_IMPROVEMENTS -#define CAM_DATA_IS_BG (1 << 12) // if not set, then cam data is for actor cutscenes s16 sGlobalCamDataSettings[] = { /* -66 */ CAM_SET_NORMAL4, // CS_CAM_ID_GLOBAL_NORMAL4 @@ -9035,28 +9084,6 @@ s16 sGlobalCamDataSettings[] = { s16* sGlobalCamDataSettingsPtr = &sGlobalCamDataSettings[ARRAY_COUNT(sGlobalCamDataSettings) - 1]; -/** - * Returns the CameraSettingType of the camera from either the bgCam or the actorCsCam at index `camDataId` - */ -s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId) { - if (camDataId & CAM_DATA_IS_BG) { - return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); - } else { - return Play_GetActorCsCamSetting(camera->play, camDataId); - } -} - -/** - * Returns either the bgCam data or the actorCsCam data at index `camDataId` - */ -Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId) { - if (camDataId & CAM_DATA_IS_BG) { - return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId & ~CAM_DATA_IS_BG, BGCHECK_SCENE); - } else { - return Play_GetActorCsCamFuncData(camera->play, camDataId); - } -} - s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags) { // Reject settings change based on priority if ((camera->behaviorFlags & CAM_BEHAVIOR_SETTING_CHECK_PRIORITY) && @@ -9130,7 +9157,7 @@ s32 Camera_ChangeSetting(Camera* camera, s16 setting) { s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex) { s16 setting; - if ((bgCamIndex == -1) || (bgCamIndex == camera->bgCamIndex)) { + if ((bgCamIndex == -1) || ((bgCamIndex == camera->bgCamIndex) && !(camera->behaviorFlags & CAM_BEHAVIOR_BG_PROCESSED))) { camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; return -1; } diff --git a/src/code/z_camera_data.inc.c b/src/code/z_camera_data.inc.c index 7eb12fb352..502874e130 100644 --- a/src/code/z_camera_data.inc.c +++ b/src/code/z_camera_data.inc.c @@ -2352,6 +2352,16 @@ CameraMode sCamSetNormal4Modes[] = { CAM_SETTING_MODE_ENTRY(CAM_FUNC_KEEP1, sSetNormal0ModeFollowBoomerangData), // CAM_MODE_FOLLOW_BOOMERANG }; +#if ENABLE_CUTSCENE_IMPROVEMENTS +CameraModeValue D_801B5824[] = { + CAM_FUNCDATA_FIXD1(-40, 100, 60, CAM_INTERFACE_FIELD(CAM_LETTERBOX_IGNORE, CAM_HUD_VISIBILITY_IGNORE, 0)), +}; + +CameraMode sCamSetFixed1Modes[] = { + CAM_SETTING_MODE_ENTRY(CAM_FUNC_FIXED1, D_801B5824), // CAM_MODE_NORMAL +}; +#endif + CameraSetting sCameraSettings[] = { { { 0x00000000 }, 0x20000000, NULL }, // CAM_SET_NONE { { 0x051FFFFF }, 0x20000000, sCamSetNormal0Modes }, // CAM_SET_NORMAL0 @@ -2419,6 +2429,9 @@ CameraSetting sCameraSettings[] = { { { 0x051FFFFF }, 0x20000000, sCamSetDirectedYawModes }, // CAM_SET_DIRECTED_YAW { { 0xC5000ECD }, 0x20000000, sCamSetPivotFromSideModes }, // CAM_SET_PIVOT_FROM_SIDE { { 0x051FFFFF }, 0x20000000, sCamSetNormal4Modes }, // CAM_SET_NORMAL4 +#if ENABLE_CUTSCENE_IMPROVEMENTS + { { 0x00000001 }, 0x80000005, sCamSetFixed1Modes }, // CAM_SET_FIXED1 +#endif }; s32 Camera_Normal0(Camera* camera); @@ -2564,6 +2577,9 @@ s32 (*sCameraFunctions[])(Camera*) = { Camera_Special7, // CAM_FUNC_SPEC7 Camera_Special8, // CAM_FUNC_SPEC8 Camera_Special9, // CAM_FUNC_SPEC9 +#if ENABLE_CUTSCENE_IMPROVEMENTS + Camera_Fixed3, // CAM_FUNC_FIXED1 +#endif }; s32 sInitRegs = 1; diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 4e9e0f1151..0c2a5f3a2d 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -2342,6 +2342,9 @@ void CutsceneHandler_StopScript(PlayState* play, CutsceneContext* csCtx) { Camera_SetFinishedFlag(play->cameraPtrs[sReturnToCamId]); } +#if ENABLE_CUTSCENE_IMPROVEMENTS + CutsceneManager_Stop(CS_ID_GLOBAL_END); +#endif Audio_SetCutsceneFlag(0); csCtx->state = CS_STATE_IDLE; } diff --git a/src/code/z_play.c b/src/code/z_play.c index fab5044038..3521386794 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -601,18 +601,6 @@ void Play_Update(PlayState* this) { #define FRAMEADVANCE_CAN_UPDATE true #endif - if (CHECK_BTN_ALL(input[0].press.button, BTN_L)) { - if (!CutsceneManager_IsNext(0)) { - CutsceneManager_Queue(0); - } else { - CutsceneManager_Start(0, &GET_PLAYER(this)->actor); - } - - PRINTF("pressed!\n"); - } - - PRINTF("CutsceneManager_IsNext(0):%d\n", CutsceneManager_IsNext(0)); - if (FRAMEADVANCE_CAN_UPDATE) { if ((this->transitionMode == TRANS_MODE_OFF) && (this->transitionTrigger != TRANS_TRIGGER_OFF)) { this->transitionMode = TRANS_MODE_SETUP; @@ -1704,8 +1692,17 @@ void Play_Main(GameState* thisx) { PLAY_LOG(4587); #if ENABLE_CUTSCENE_IMPROVEMENTS + s16 optCsId = CutsceneManager_GetAdditionalCsId(0); + s16 csId = optCsId >= 0 ? optCsId : 0; + + if (CutsceneManager_IsNext(csId)) { + CutsceneManager_Start(csId, &GET_PLAYER(this)->actor); + } else if (CHECK_BTN_ALL(this->state.input[0].press.button, BTN_L)) { + CutsceneManager_Queue(csId); + } + CutsceneManager_Update(); - // CutsceneManager_ClearWaiting(); + CutsceneManager_ClearWaiting(); #endif } diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 075736cb41..8cd7db7c6c 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -3,6 +3,7 @@ #include "assets/objects/gameplay_keep/gameplay_keep.h" #include "assets/objects/object_link_boy/object_link_boy.h" #include "assets/objects/object_link_child/object_link_child.h" +#include "config.h" #pragma increment_block_number "gc-eu:0 gc-eu-mq:0 gc-jp:128 gc-jp-ce:128 gc-jp-mq:128 gc-us:128 gc-us-mq:128" @@ -607,14 +608,18 @@ void Player_SetBootData(PlayState* play, Player* this) { int Player_InBlockingCsMode(PlayState* play, Player* this) { return (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_29)) || (this->csAction != PLAYER_CSACTION_NONE) || (play->transitionTrigger == TRANS_TRIGGER_START) || (this->stateFlags1 & PLAYER_STATE1_0) || +#if ENABLE_CUTSCENE_IMPROVEMENTS + (this->stateFlags3 & (PLAYER_STATE3_FLYING_WITH_HOOKSHOT | PLAYER_STATE3_ACTOR_CS_HALT)) || +#else (this->stateFlags3 & PLAYER_STATE3_FLYING_WITH_HOOKSHOT) || +#endif ((gSaveContext.magicState != MAGIC_STATE_IDLE) && (Player_ActionToMagicSpell(this, this->itemAction) >= 0)); } int Player_InCsMode(PlayState* play) { Player* this = GET_PLAYER(play); - return CutsceneManager_GetCurrentCsId() == CS_ID_NONE && (Player_InBlockingCsMode(play, this) || (this->unk_6AD == 4)); + return Player_InBlockingCsMode(play, this) || (this->unk_6AD == 4); } /** diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.c b/src/overlays/actors/ovl_En_Holl/z_en_holl.c index af3defe56d..8f04dac95f 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.c +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.c @@ -1,4 +1,5 @@ #include "z_en_holl.h" +#include "config.h" #define FLAGS ACTOR_FLAG_4 @@ -403,7 +404,13 @@ void EnHoll_WaitRoomLoaded(EnHoll* this, PlayState* play) { void EnHoll_Update(Actor* thisx, PlayState* play) { EnHoll* this = (EnHoll*)thisx; +#if ENABLE_CUTSCENE_IMPROVEMENTS + if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !(GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT)) { + this->actionFunc(this, play); + } +#else this->actionFunc(this, play); +#endif } #include "assets/overlays/ovl_En_Holl/ovl_En_Holl.c" diff --git a/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 0360e73379..6097bf1cba 100644 --- a/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -1,5 +1,6 @@ #include "z_en_okuta.h" #include "assets/objects/object_okuta/object_okuta.h" +#include "config.h" #define FLAGS (ACTOR_FLAG_ATTENTION_ENABLED | ACTOR_FLAG_HOSTILE) @@ -578,6 +579,12 @@ void EnOkuta_Update(Actor* thisx, PlayState* play2) { Vec3f prevPos; s32 canRestorePrevPos; +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { + return; + } +#endif + if (!(player->stateFlags1 & (PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29))) { if (this->actor.params == 0) { EnOkuta_ColliderCheck(this, play); From 615189b1091adc51e9916e271f4a8bcf1776f2e4 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:39:01 +0100 Subject: [PATCH 05/13] renamed cs halt state flag --- include/z64player.h | 4 ++-- src/code/cutscene_manager.c | 8 +++---- src/code/z_actor.c | 22 +++++++++---------- src/code/z_player_lib.c | 2 +- src/overlays/actors/ovl_En_Holl/z_en_holl.c | 2 +- src/overlays/actors/ovl_En_Okuta/z_en_okuta.c | 2 +- 6 files changed, 20 insertions(+), 20 deletions(-) diff --git a/include/z64player.h b/include/z64player.h index 3e1b8df07b..732f02cbcb 100644 --- a/include/z64player.h +++ b/include/z64player.h @@ -768,9 +768,9 @@ typedef struct WeaponInfo { #define PLAYER_STATE3_FLYING_WITH_HOOKSHOT (1 << 7) // Flying in the air with the hookshot as it pulls Player toward its destination #if ENABLE_CUTSCENE_IMPROVEMENTS -#define PLAYER_STATE3_ACTOR_CS_HALT (1 << 8) // Prevents updating the actor while an actor cutscene is playing +#define PLAYER_STATE3_CS_HALT (1 << 8) // Prevents updating the actor while a cutscene is playing #else -#define PLAYER_STATE3_ACTOR_CS_HALT (0) +#define PLAYER_STATE3_CS_HALT (0) #endif #define PLAYER_ALLOC_GI_MIN 0x2880 // title card maximum file size diff --git a/src/code/cutscene_manager.c b/src/code/cutscene_manager.c index 5297126037..3544e4496a 100644 --- a/src/code/cutscene_manager.c +++ b/src/code/cutscene_manager.c @@ -385,8 +385,8 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { Player* player = GET_PLAYER(sCutsceneMgr.play); // set the cutscene halt flag - if (!(player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT)) { - player->stateFlags3 |= PLAYER_STATE3_ACTOR_CS_HALT; + if (!(player->stateFlags3 & PLAYER_STATE3_CS_HALT)) { + player->stateFlags3 |= PLAYER_STATE3_CS_HALT; } if ((csId <= CS_ID_NONE) || (sCutsceneMgr.csId != CS_ID_NONE)) { @@ -457,8 +457,8 @@ s16 CutsceneManager_Stop(s16 csId) { Player* player = GET_PLAYER(sCutsceneMgr.play); // unset the cutscene halt flag - if (player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { - player->stateFlags3 &= ~PLAYER_STATE3_ACTOR_CS_HALT; + if (player->stateFlags3 & PLAYER_STATE3_CS_HALT) { + player->stateFlags3 &= ~PLAYER_STATE3_CS_HALT; } if (csId <= CS_ID_NONE) { diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 01c34038cc..2690bb31f1 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -328,7 +328,7 @@ void Attention_Draw(Attention* attention, PlayState* play) { Actor* actor; // used for both the reticle actor and arrow hover actor #if ENABLE_CUTSCENE_IMPROVEMENTS - if (GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { + if (GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_CS_HALT) { return; } #endif @@ -2330,29 +2330,29 @@ typedef struct ActorFreezeMasks { ActorFreezeMasks sCategoryFreezeMasks[ACTORCAT_MAX] = { // ACTORCAT_SWITCH - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_CS_HALT }, // ACTORCAT_BG - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_CS_HALT }, // ACTORCAT_PLAYER - { 0, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { 0, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_EXPLOSIVE - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_NPC - { PLAYER_STATE1_DEAD, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_DEAD, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_ENEMY - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_PROP - { PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_ITEMACTION { 0, 0, 0 }, // ACTORCAT_MISC - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28 | PLAYER_STATE1_29, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_BOSS - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_10 | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_DOOR { 0, 0, 0 }, // ACTORCAT_CHEST - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_ACTOR_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, }; void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { diff --git a/src/code/z_player_lib.c b/src/code/z_player_lib.c index 8cd7db7c6c..55ffb830c9 100644 --- a/src/code/z_player_lib.c +++ b/src/code/z_player_lib.c @@ -609,7 +609,7 @@ int Player_InBlockingCsMode(PlayState* play, Player* this) { return (this->stateFlags1 & (PLAYER_STATE1_DEAD | PLAYER_STATE1_29)) || (this->csAction != PLAYER_CSACTION_NONE) || (play->transitionTrigger == TRANS_TRIGGER_START) || (this->stateFlags1 & PLAYER_STATE1_0) || #if ENABLE_CUTSCENE_IMPROVEMENTS - (this->stateFlags3 & (PLAYER_STATE3_FLYING_WITH_HOOKSHOT | PLAYER_STATE3_ACTOR_CS_HALT)) || + (this->stateFlags3 & (PLAYER_STATE3_FLYING_WITH_HOOKSHOT | PLAYER_STATE3_CS_HALT)) || #else (this->stateFlags3 & PLAYER_STATE3_FLYING_WITH_HOOKSHOT) || #endif diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.c b/src/overlays/actors/ovl_En_Holl/z_en_holl.c index 8f04dac95f..e4689fc0fc 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.c +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.c @@ -405,7 +405,7 @@ void EnHoll_Update(Actor* thisx, PlayState* play) { EnHoll* this = (EnHoll*)thisx; #if ENABLE_CUTSCENE_IMPROVEMENTS - if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !(GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT)) { + if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !(GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_CS_HALT)) { this->actionFunc(this, play); } #else diff --git a/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c b/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c index 6097bf1cba..5329f4904b 100644 --- a/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c +++ b/src/overlays/actors/ovl_En_Okuta/z_en_okuta.c @@ -580,7 +580,7 @@ void EnOkuta_Update(Actor* thisx, PlayState* play2) { s32 canRestorePrevPos; #if ENABLE_CUTSCENE_IMPROVEMENTS - if (player->stateFlags3 & PLAYER_STATE3_ACTOR_CS_HALT) { + if (player->stateFlags3 & PLAYER_STATE3_CS_HALT) { return; } #endif From 335ab653c5bc611c06bc49b8e3f0e5fdbe73ed7a Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:39:41 +0100 Subject: [PATCH 06/13] format --- include/config/config_game.h | 2 +- src/code/cutscene_manager.c | 20 +++++++++++--------- src/code/z_actor.c | 7 ++++--- src/code/z_camera.c | 13 +++++++++---- src/code/z_camera_data.inc.c | 4 ++-- src/overlays/actors/ovl_En_Holl/z_en_holl.c | 3 ++- 6 files changed, 29 insertions(+), 20 deletions(-) diff --git a/include/config/config_game.h b/include/config/config_game.h index 8b6d52d850..92fd36e3ca 100644 --- a/include/config/config_game.h +++ b/include/config/config_game.h @@ -81,7 +81,7 @@ /** * Enable Cutscene Improvements (from Majora's Mask) - * + * * This includes actor cutscenes */ #define ENABLE_CUTSCENE_IMPROVEMENTS true diff --git a/src/code/cutscene_manager.c b/src/code/cutscene_manager.c index 3544e4496a..a2a6ea7adf 100644 --- a/src/code/cutscene_manager.c +++ b/src/code/cutscene_manager.c @@ -240,12 +240,13 @@ void CutsceneManager_End(void) { } switch (csEntry->endCam) { - // case CS_END_CAM_SMOOTH: - // Play_CopyCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId, sCutsceneMgr.subCamId); - // RET_CAM->stateFlags = - // (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); - // CutsceneManager_Queue(CS_ID_GLOBAL_RETURN_TO_CAM); - // break; + // case CS_END_CAM_SMOOTH: + // Play_CopyCamera(sCutsceneMgr.play, sCutsceneMgr.retCamId, sCutsceneMgr.subCamId); + // RET_CAM->stateFlags = + // (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & + // CAM_STATE_CAMERA_IN_WATER); + // CutsceneManager_Queue(CS_ID_GLOBAL_RETURN_TO_CAM); + // break; case CS_END_CAM_0: default: @@ -262,10 +263,11 @@ void CutsceneManager_End(void) { // Restore the camera that was stored in subCam 2 memcpy(RET_CAM, &sCutsceneMgr.play->subCameras[2], sizeof(Camera)); - RET_CAM->stateFlags = - (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); + RET_CAM->stateFlags = (RET_CAM->stateFlags & ~CAM_STATE_CAMERA_IN_WATER) | + (CUR_CAM->stateFlags & CAM_STATE_CAMERA_IN_WATER); - RET_CAM->stateFlags = (RET_CAM->stateFlags & ~CAM_STATE_CHECK_BG) | (oldStateFlags & CAM_STATE_CHECK_BG); + RET_CAM->stateFlags = + (RET_CAM->stateFlags & ~CAM_STATE_CHECK_BG) | (oldStateFlags & CAM_STATE_CHECK_BG); sCutsceneMgr.isCameraStored = false; } RET_CAM->camId = oldCamId; diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 2690bb31f1..37baa9f23c 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -2330,9 +2330,9 @@ typedef struct ActorFreezeMasks { ActorFreezeMasks sCategoryFreezeMasks[ACTORCAT_MAX] = { // ACTORCAT_SWITCH - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_BG - { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0 , PLAYER_STATE3_CS_HALT }, + { PLAYER_STATE1_TALKING | PLAYER_STATE1_DEAD | PLAYER_STATE1_28, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_PLAYER { 0, 0, PLAYER_STATE3_CS_HALT }, // ACTORCAT_EXPLOSIVE @@ -2410,7 +2410,8 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { for (i = 0; i < ARRAY_COUNT(actorCtx->actorLists); i++, categoryFreezeMaskP++) { ActorFreezeMasks curEntry = *categoryFreezeMaskP; - canFreezeCategory = (curEntry.mask1 & player->stateFlags1) || (curEntry.mask2 & player->stateFlags2) || (curEntry.mask3 & player->stateFlags3); + canFreezeCategory = (curEntry.mask1 & player->stateFlags1) || (curEntry.mask2 & player->stateFlags2) || + (curEntry.mask3 & player->stateFlags3); actor = actorCtx->actorLists[i].head; while (actor != NULL) { diff --git a/src/code/z_camera.c b/src/code/z_camera.c index b4ca4929ad..5e97a737e2 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -40,7 +40,9 @@ s32 Camera_QRegInit(void); #define CAM_DEBUG_RELOAD_PARAMS true #endif -#define CAMERA_CHECK_FLAGS(settings, mask) ((settings.flags & 0x20000000) ? sCameraSettings[camera->setting].unk_00 & (mask) : sCameraSettings[camera->setting].flags & (mask)) +#define CAMERA_CHECK_FLAGS(settings, mask) \ + ((settings.flags & 0x20000000) ? sCameraSettings[camera->setting].unk_00 & (mask) \ + : sCameraSettings[camera->setting].flags & (mask)) #define CAM_DATA_IS_BG (1 << 12) // if not set, then cam data is for actor cutscenes /** @@ -7781,7 +7783,8 @@ s32 Camera_UpdateWater(Camera* camera) { Player* player = camera->player; s16 prevBgId; - if (!(camera->stateFlags & CAM_STATE_CHECK_WATER) || CAMERA_CHECK_FLAGS(sCameraSettings[camera->setting], 0x40000000)) { + if (!(camera->stateFlags & CAM_STATE_CHECK_WATER) || + CAMERA_CHECK_FLAGS(sCameraSettings[camera->setting], 0x40000000)) { return 0; } @@ -9157,7 +9160,8 @@ s32 Camera_ChangeSetting(Camera* camera, s16 setting) { s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex) { s16 setting; - if ((bgCamIndex == -1) || ((bgCamIndex == camera->bgCamIndex) && !(camera->behaviorFlags & CAM_BEHAVIOR_BG_PROCESSED))) { + if ((bgCamIndex == -1) || + ((bgCamIndex == camera->bgCamIndex) && !(camera->behaviorFlags & CAM_BEHAVIOR_BG_PROCESSED))) { camera->behaviorFlags |= CAM_BEHAVIOR_BG_PROCESSED; return -1; } @@ -9187,7 +9191,8 @@ s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex) { void Camera_800E0348(Camera* camera) { if (!RELOAD_PARAMS(camera)) { camera->animState = 999; - Camera_SetStateFlag(camera, CAM_STATE_BLOCK_BG | CAM_STATE_CAM_FUNC_FINISH | CAM_STATE_CHECK_BG | CAM_STATE_CHECK_WATER); + Camera_SetStateFlag(camera, CAM_STATE_BLOCK_BG | CAM_STATE_CAM_FUNC_FINISH | CAM_STATE_CHECK_BG | + CAM_STATE_CHECK_WATER); } else { camera->animState = 666; } diff --git a/src/code/z_camera_data.inc.c b/src/code/z_camera_data.inc.c index 502874e130..2c796631e2 100644 --- a/src/code/z_camera_data.inc.c +++ b/src/code/z_camera_data.inc.c @@ -2430,7 +2430,7 @@ CameraSetting sCameraSettings[] = { { { 0xC5000ECD }, 0x20000000, sCamSetPivotFromSideModes }, // CAM_SET_PIVOT_FROM_SIDE { { 0x051FFFFF }, 0x20000000, sCamSetNormal4Modes }, // CAM_SET_NORMAL4 #if ENABLE_CUTSCENE_IMPROVEMENTS - { { 0x00000001 }, 0x80000005, sCamSetFixed1Modes }, // CAM_SET_FIXED1 + { { 0x00000001 }, 0x80000005, sCamSetFixed1Modes }, // CAM_SET_FIXED1 #endif }; @@ -2578,7 +2578,7 @@ s32 (*sCameraFunctions[])(Camera*) = { Camera_Special8, // CAM_FUNC_SPEC8 Camera_Special9, // CAM_FUNC_SPEC9 #if ENABLE_CUTSCENE_IMPROVEMENTS - Camera_Fixed3, // CAM_FUNC_FIXED1 + Camera_Fixed3, // CAM_FUNC_FIXED1 #endif }; diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.c b/src/overlays/actors/ovl_En_Holl/z_en_holl.c index e4689fc0fc..2dd6b7d810 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.c +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.c @@ -405,7 +405,8 @@ void EnHoll_Update(Actor* thisx, PlayState* play) { EnHoll* this = (EnHoll*)thisx; #if ENABLE_CUTSCENE_IMPROVEMENTS - if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && !(GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_CS_HALT)) { + if ((play->transitionTrigger == TRANS_TRIGGER_OFF) && (play->transitionMode == TRANS_MODE_OFF) && + !(GET_PLAYER(play)->stateFlags3 & PLAYER_STATE3_CS_HALT)) { this->actionFunc(this, play); } #else From a16cf79c2a386e5a5cd86f79be7caabac714341f Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:45:13 +0100 Subject: [PATCH 07/13] remove test scene from spec --- spec | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/spec b/spec index b2c1c93071..8575e33809 100644 --- a/spec +++ b/spec @@ -19785,22 +19785,3 @@ beginseg number 3 endseg #endif - -beginseg - name "debug1_scene" - compress - romalign 0x1000 - include "$(BUILD_DIR)/assets/scenes/debug1/debug1_scene_main.o" - include "$(BUILD_DIR)/assets/scenes/debug1/debug1_scene_col.o" - number 2 -endseg - -beginseg - name "debug1_room_0" - compress - romalign 0x1000 - include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_main.o" - include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_model_info.o" - include "$(BUILD_DIR)/assets/scenes/debug1/debug1_room_0_model.o" - number 3 -endseg From 743ae1826ae0d512aff390ae862d3afd346f3243 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:49:34 +0100 Subject: [PATCH 08/13] remove test code from z_play.c --- src/code/z_play.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/code/z_play.c b/src/code/z_play.c index 3521386794..488a558067 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1692,15 +1692,6 @@ void Play_Main(GameState* thisx) { PLAY_LOG(4587); #if ENABLE_CUTSCENE_IMPROVEMENTS - s16 optCsId = CutsceneManager_GetAdditionalCsId(0); - s16 csId = optCsId >= 0 ? optCsId : 0; - - if (CutsceneManager_IsNext(csId)) { - CutsceneManager_Start(csId, &GET_PLAYER(this)->actor); - } else if (CHECK_BTN_ALL(this->state.input[0].press.button, BTN_L)) { - CutsceneManager_Queue(csId); - } - CutsceneManager_Update(); CutsceneManager_ClearWaiting(); #endif From 371a648af313c2cbb3d5ff3b0babf4aa2c16cf55 Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Fri, 3 Jan 2025 23:54:27 +0100 Subject: [PATCH 09/13] forgot to reset the boot entrance --- include/config/config_debug.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/config/config_debug.h b/include/config/config_debug.h index c8bea9ccad..150c2b713e 100644 --- a/include/config/config_debug.h +++ b/include/config/config_debug.h @@ -40,7 +40,7 @@ #define MAP_SELECT_ON_FILE_1 false // Change these if using `BOOT_TO_SCENE`, `BOOT_TO_SCENE_NEW_GAME_ONLY` or `BOOT_TO_DEBUG_OPENING` -#define BOOT_ENTRANCE ENTR_DEBUG1_0 +#define BOOT_ENTRANCE ENTR_EXAMPLE_0 #define BOOT_AGE LINK_AGE_ADULT #define BOOT_CUTSCENE 0x0000 From 8672bb21a49da14602ec13e8ad28d4be04407a1d Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Sat, 4 Jan 2025 04:21:09 +0100 Subject: [PATCH 10/13] fixed issues --- include/tables/scene_table.h | 2 +- include/z64camera.h | 2 +- include/z64cutscene.h | 6 +- include/z64scene.h | 1 - .../scenes/example/example_room_0_model.c | 2 + mod_assets/scenes/example/example_scene.h | 13 +++ .../scenes/example/example_scene_main.c | 90 +++++++++++++++++++ src/code/cutscene_manager.c | 8 +- src/code/z_camera.c | 15 +--- src/code/z_demo.c | 50 ++++++----- src/code/z_play.c | 35 ++++++-- src/code/z_scene.c | 1 - 12 files changed, 174 insertions(+), 51 deletions(-) diff --git a/include/tables/scene_table.h b/include/tables/scene_table.h index 9d9da91289..bbb17d218e 100644 --- a/include/tables/scene_table.h +++ b/include/tables/scene_table.h @@ -124,5 +124,5 @@ #endif #if CAN_INCLUDE_EXAMPLE_SCENE -/* 0x6C */ DEFINE_SCENE(example_scene, none, SCENE_EXAMPLE, SDC_HAUNTED_WASTELAND, 0, 0) +/* 0x6C */ DEFINE_SCENE(example_scene, none, SCENE_EXAMPLE, SDC_MAT_ANIM, 0, 0) #endif diff --git a/include/z64camera.h b/include/z64camera.h index 2667aaa676..dfa6ad94dd 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -1739,9 +1739,9 @@ void Camera_SetCameraData(Camera* camera, s16 setDataFlags, void* data0, void* d s32 func_8005B198(void); s16 Camera_SetFinishedFlag(Camera* camera); -#if ENABLE_CUTSCENE_IMPROVEMENTS s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId); Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId); +#if ENABLE_CUTSCENE_IMPROVEMENTS s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags); s32 Camera_ChangeSetting(Camera* camera, s16 setting); s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex); diff --git a/include/z64cutscene.h b/include/z64cutscene.h index 002f363866..381c5c58dd 100644 --- a/include/z64cutscene.h +++ b/include/z64cutscene.h @@ -499,8 +499,6 @@ typedef struct CutsceneCameraMove { /* 0x8 */ s16 relativeToPlayer; } CutsceneCameraMove; // size = 0xC -#if ENABLE_CUTSCENE_IMPROVEMENTS - typedef struct CutsceneScriptEntry { /* 0x0 */ CutsceneData* script; /* 0x4 */ s16 nextEntrance; @@ -716,11 +714,9 @@ typedef enum { /* 999 */ CS_CAM_STATE_DONE = 999 // Finished all the splines. } CutsceneCameraState; -#endif - typedef struct CutsceneContext { /* 0x00 */ u8 scriptListCount; - /* 0x04 */ CutsceneData* script; + /* 0x04 */ void* script; /* 0x08 */ u8 state; /* 0x0C */ f32 timer; /* 0x10 */ u16 curFrame; // current frame of the script that is running diff --git a/include/z64scene.h b/include/z64scene.h index 98581a23d2..4f25eea60f 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -741,7 +741,6 @@ typedef enum SceneCommandTypeID { #define SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(numCams, camList) \ { SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST, numCams, CMD_PTR(camList) } - #endif diff --git a/mod_assets/scenes/example/example_room_0_model.c b/mod_assets/scenes/example/example_room_0_model.c index 5d3950e4f4..4d2bc322b2 100644 --- a/mod_assets/scenes/example/example_room_0_model.c +++ b/mod_assets/scenes/example/example_room_0_model.c @@ -1413,6 +1413,7 @@ Gfx mat_example_room_0_dl_wall_layerOpaque[] = { gsDPLoadBlock(7, 0, 0, 511, 512), gsDPSetTile(G_IM_FMT_I, G_IM_SIZ_8b, 4, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 14, G_TX_WRAP | G_TX_NOMIRROR, 5, 14), gsDPSetTileSize(0, 0, 0, 124, 124), + gsSPDisplayList(0xA000000), gsSPEndDisplayList(), }; @@ -1663,6 +1664,7 @@ Gfx mat_example_room_0_dl_water_layerTransparent[] = { gsDPSetTileSize(0, 0, 0, 124, 124), gsDPSetTile(G_IM_FMT_CI, G_IM_SIZ_8b, 4, 0, 1, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 15, G_TX_WRAP | G_TX_NOMIRROR, 5, 15), gsDPSetTileSize(1, 0, 0, 124, 124), + gsSPDisplayList(0x8000000), gsSPDisplayList(0x9000000), gsSPEndDisplayList(), }; diff --git a/mod_assets/scenes/example/example_scene.h b/mod_assets/scenes/example/example_scene.h index ca6b9cb4d3..b8056329c5 100644 --- a/mod_assets/scenes/example/example_scene.h +++ b/mod_assets/scenes/example/example_scene.h @@ -4,6 +4,7 @@ #include "ultra64.h" #include "macros.h" #include "z64.h" +#include "config.h" extern SceneCmd example_scene_header00[]; @@ -15,6 +16,18 @@ extern ActorEntry example_scene_header00_playerEntryList[]; extern Spawn example_scene_header00_entranceList[]; extern TransitionActorEntry example_scene_header00_transitionActors[]; extern EnvLightSettings example_scene_header00_lightSettings[4]; +extern AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_00[]; +extern AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_01[]; +extern F3DPrimColor debug1_scene_header00_AnimatedMaterialColorPrimColor_02[]; +extern F3DEnvColor debug1_scene_header00_AnimatedMaterialColorEnvColor_02[]; +extern u16 debug1_scene_header00_AnimatedMaterialColorKeyFrames_02[]; +extern AnimatedMatColorParams debug1_scene_header00_AnimatedMaterialColorParams_02; +extern AnimatedMaterial debug1_scene_header00_AnimatedMaterial[]; +extern Vec3s debug1_scene_header00_ActorCutsceneCameraData[]; +#if ENABLE_CUTSCENE_IMPROVEMENTS +extern ActorCsCamInfo debug1_scene_header00_ActorCutsceneCameraInfo[]; +extern CutsceneEntry debug1_scene_header00_ActorCutsceneList[]; +#endif extern SceneCmd example_scene_header01[]; extern ActorEntry example_scene_header01_playerEntryList[]; extern Spawn example_scene_header01_entranceList[]; diff --git a/mod_assets/scenes/example/example_scene_main.c b/mod_assets/scenes/example/example_scene_main.c index aabb783b60..f9156861f6 100644 --- a/mod_assets/scenes/example/example_scene_main.c +++ b/mod_assets/scenes/example/example_scene_main.c @@ -19,6 +19,11 @@ SceneCmd example_scene_header00[] = { SCENE_CMD_ENTRANCE_LIST(example_scene_header00_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header00_playerEntryList), SCENE_CMD_CUTSCENE_DATA(gExampleCS), + SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), + SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), +#endif SCENE_CMD_END(), }; @@ -153,6 +158,76 @@ EnvLightSettings example_scene_header00_lightSettings[4] = { }, }; +AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_00[] = { + { 0, -1, 32, 32 }, + { 0, -1, 32, 32 } +}; + +AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_01[] = { + { 0, 1, 32, 32 }, + { 0, -1, 32, 32 } +}; + +F3DPrimColor debug1_scene_header00_AnimatedMaterialColorPrimColor_02[] = { + { 255, 255, 255, 255, 128 }, + { 255, 255, 255, 255, 128 }, + { 128, 0, 0, 255, 128 }, + { 255, 255, 255, 255, 128 }, + { 255, 255, 255, 255, 128 } +}; + +F3DEnvColor debug1_scene_header00_AnimatedMaterialColorEnvColor_02[] = { + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 }, + { 255, 255, 255, 255 } +}; + +u16 debug1_scene_header00_AnimatedMaterialColorKeyFrames_02[] = { + 0, + 5, + 30, + 55, + 59 +}; + +AnimatedMatColorParams debug1_scene_header00_AnimatedMaterialColorParams_02 = { + 60, + 5, + debug1_scene_header00_AnimatedMaterialColorPrimColor_02, + debug1_scene_header00_AnimatedMaterialColorEnvColor_02, + debug1_scene_header00_AnimatedMaterialColorKeyFrames_02, +}; + +AnimatedMaterial debug1_scene_header00_AnimatedMaterial[] = { + { 1 /* 8 */, 1, debug1_scene_header00_AnimatedMaterialTexScrollParams_00 }, + { 2 /* 9 */, 1, debug1_scene_header00_AnimatedMaterialTexScrollParams_01 }, + { -3 /* 10 */, 4, &debug1_scene_header00_AnimatedMaterialColorParams_02 } +}; + +#if ENABLE_CUTSCENE_IMPROVEMENTS +Vec3s debug1_scene_header00_ActorCutsceneCameraData[] = { + { 608, 279, -730 }, + { 0x0C3B, 0xE10A, 0x0000 }, + { 4000, -1, -1 }, + + { -506, 279, -730 }, + { 0x0C3B, 0x2067, 0x0000 }, + { -1, -1, -1 }, +}; + +ActorCsCamInfo debug1_scene_header00_ActorCutsceneCameraInfo[] = { + { CAM_SET_FIXED1, 3, &debug1_scene_header00_ActorCutsceneCameraData[0] }, + { CAM_SET_FIXED1, 3, &debug1_scene_header00_ActorCutsceneCameraData[3] }, +}; + +CutsceneEntry debug1_scene_header00_ActorCutsceneList[] = { + /* 0 */ { 500, 90, 0, -1, 1, CS_END_SFX_NONE, 255, CS_HUD_VISIBILITY_NONE, CS_END_CAM_SMOOTH, 20 }, + /* 1 */ { 501, 90, 1, -1, -1, CS_END_SFX_TRE_BOX_APPEAR, 255, CS_HUD_VISIBILITY_NONE, CS_END_CAM_SMOOTH, 35 }, +}; +#endif + /** * Header Child Night */ @@ -167,6 +242,11 @@ SceneCmd example_scene_header01[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header01_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header01_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header01_playerEntryList), + SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), + SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), +#endif SCENE_CMD_END(), }; @@ -305,6 +385,11 @@ SceneCmd example_scene_header02[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header02_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header02_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header02_playerEntryList), + SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), + SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), +#endif SCENE_CMD_END(), }; @@ -443,6 +528,11 @@ SceneCmd example_scene_header03[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header03_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header03_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header03_playerEntryList), + SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#if ENABLE_CUTSCENE_IMPROVEMENTS + SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), + SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), +#endif SCENE_CMD_END(), }; diff --git a/src/code/cutscene_manager.c b/src/code/cutscene_manager.c index a2a6ea7adf..6b4061226d 100644 --- a/src/code/cutscene_manager.c +++ b/src/code/cutscene_manager.c @@ -125,8 +125,10 @@ CutsceneEntry* CutsceneManager_GetCutsceneEntryImpl(s16 csId) { void CutsceneManager_Init(PlayState* play, CutsceneEntry* cutsceneList, s16 numEntries) { s32 i; - sSceneCutsceneList = cutsceneList; - sSceneCutsceneCount = numEntries; + if (cutsceneList != NULL) { + sSceneCutsceneList = cutsceneList; + sSceneCutsceneCount = numEntries; + } for (i = 0; i < ARRAY_COUNT(sWaitingCutsceneList); i++) { sWaitingCutsceneList[i] = 0; @@ -146,7 +148,7 @@ void CutsceneManager_Init(PlayState* play, CutsceneEntry* cutsceneList, s16 numE * Store camera into subCam 2, and keep subCam 2 INACTIVE to preserve the struct. */ void CutsceneManager_StoreCamera(Camera* camera) { - if (camera != NULL) { + if ((camera != NULL) && (sCutsceneMgr.play != NULL)) { memcpy(&sCutsceneMgr.play->subCameras[2], camera, sizeof(Camera)); sCutsceneMgr.play->subCameras[2].camId = camera->camId; Camera_ChangeStatus(&sCutsceneMgr.play->subCameras[2], CAM_STAT_UNK100); diff --git a/src/code/z_camera.c b/src/code/z_camera.c index 5e97a737e2..3cd1830ce9 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -8039,15 +8039,6 @@ void Camera_UpdateDistortion(Camera* camera) { #define ENABLE_DEBUG_CAM_UPDATE false #endif -// probably useless? -s32 Camera_800CB854(Camera* camera) { -#if ENABLE_CUTSCENE_IMPROVEMENTS - return camera->player->stateFlags1 & PLAYER_STATE1_5; -#else - return 0; -#endif -} - Vec3s Camera_Update(Camera* camera) { static s32 sOOBTimer = 0; Vec3f viewAt; @@ -8183,7 +8174,7 @@ Vec3s Camera_Update(Camera* camera) { if ((gSaveContext.gameMode != GAMEMODE_NORMAL) && (gSaveContext.gameMode != GAMEMODE_END_CREDITS)) { sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); Camera_UpdateInterface(sCameraInterfaceField); - } else if (((D_8011D3F0 != 0) || Camera_800CB854(camera)) && (camera->camId == CAM_ID_MAIN)) { + } else if ((D_8011D3F0 != 0) && (camera->camId == CAM_ID_MAIN)) { sCameraInterfaceField = CAM_INTERFACE_FIELD(CAM_LETTERBOX_LARGE, CAM_HUD_VISIBILITY_NOTHING_ALT, 0); Camera_UpdateInterface(sCameraInterfaceField); } else if ((camera->play->transitionMode != TRANS_MODE_OFF) && (camera->camId != CAM_ID_MAIN)) { @@ -8994,7 +8985,7 @@ s16 Camera_GetBgCamOrActorCsCamSetting(Camera* camera, u32 camDataId) { return Play_GetActorCsCamSetting(camera->play, camDataId); } #else - return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, bgCamIndex, BGCHECK_SCENE); + return BgCheck_GetBgCamSettingImpl(&camera->play->colCtx, camDataId, BGCHECK_SCENE); #endif } @@ -9009,7 +9000,7 @@ Vec3s* Camera_GetBgCamOrActorCsCamFuncData(Camera* camera, u32 camDataId) { return Play_GetActorCsCamFuncData(camera->play, camDataId); } #else - return return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId, BGCHECK_SCENE); + return BgCheck_GetBgCamFuncDataImpl(&camera->play->colCtx, camDataId, BGCHECK_SCENE); #endif } diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 0c2a5f3a2d..16edfa5e3d 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -171,8 +171,11 @@ void Cutscene_InitContext(PlayState* play, CutsceneContext* csCtx) { csCtx->state = CS_STATE_IDLE; csCtx->curFrame = 0; csCtx->timer = 0.0f; - play->csCtx.scriptListCount = 0; - play->csCtx.scriptIndex = 0; + csCtx->scriptListCount = 0; + csCtx->scriptIndex = 0; +#if ENABLE_CUTSCENE_IMPROVEMENTS + csCtx->scriptList = NULL; +#endif Audio_SetCutsceneFlag(0); } @@ -1829,7 +1832,7 @@ void CutsceneCmd_MotionBlur(PlayState* play, CutsceneContext* csCtx, CsCmdMotion } } -void Cutscene_ProcessScript(PlayState* play, CutsceneContext* csCtx, CutsceneData* script) { +void Cutscene_ProcessScript(PlayState* play, CutsceneContext* csCtx, u8* script) { s16 i; s32 totalEntries; s32 cmdType; @@ -2376,25 +2379,27 @@ void Cutscene_SetupScripted(PlayState* play, CutsceneContext* csCtx) { csCtx->curFrame = 0xFFFF; #if ENABLE_CUTSCENE_IMPROVEMENTS - csCtx->subCamId = CutsceneManager_GetCurrentSubCamId(CS_ID_GLOBAL_END); - CutsceneCamera_Init(Play_GetCamera(play, csCtx->subCamId), &sCutsceneCameraInfo); - csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; -#else - - csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; - gCamAtSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; - gCamEyePointAppliedFrame = CS_CAM_DATA_NOT_APPLIED; - gCamAtPointAppliedFrame = CS_CAM_DATA_NOT_APPLIED; + if (csCtx->scriptList != NULL) { + csCtx->subCamId = CutsceneManager_GetCurrentSubCamId(CS_ID_GLOBAL_END); + CutsceneCamera_Init(Play_GetCamera(play, csCtx->subCamId), &sCutsceneCameraInfo); + csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; + } else +#endif + { + csCtx->camEyeSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; + gCamAtSplinePointsAppliedFrame = CS_CAM_DATA_NOT_APPLIED; + gCamEyePointAppliedFrame = CS_CAM_DATA_NOT_APPLIED; + gCamAtPointAppliedFrame = CS_CAM_DATA_NOT_APPLIED; - csCtx->camAtReady = false; - csCtx->camEyeReady = false; + csCtx->camAtReady = false; + csCtx->camEyeReady = false; - sReturnToCamId = play->activeCamId; + sReturnToCamId = play->activeCamId; - if (gUseCutsceneCam) { - csCtx->subCamId = Play_CreateSubCamera(play); + if (gUseCutsceneCam) { + csCtx->subCamId = Play_CreateSubCamera(play); + } } -#endif if (gSaveContext.cutsceneTrigger == 0) { Interface_ChangeHudVisibilityMode(HUD_VISIBILITY_NOTHING); @@ -2507,7 +2512,10 @@ void Cutscene_SetScript(PlayState* play, void* script) { } void Cutscene_StartScripted(PlayState* play, u8 scriptIndex) { - PRINTF("(Cutscene_StartScripted) play->csCtx.scriptList: %08X\n", play->csCtx.scriptList); - Cutscene_SetScript(play, play->csCtx.scriptList[scriptIndex].script); - gSaveContext.cutsceneTrigger = 1; +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (play->csCtx.scriptList != NULL) { + Cutscene_SetScript(play, play->csCtx.scriptList[scriptIndex].script); + gSaveContext.cutsceneTrigger = 1; + } +#endif } diff --git a/src/code/z_play.c b/src/code/z_play.c index 488a558067..1c2bc924ff 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -11,7 +11,7 @@ #include "z64frame_advance.h" #include "z64camera.h" -#if INCLUDE_EXAMPLE_SCENE +#if CAN_INCLUDE_EXAMPLE_SCENE #include "assets/scenes/example/example_scene.h" #endif @@ -400,6 +400,11 @@ void Play_Init(GameState* thisx) { gSaveContext.sceneLayer = GET_EVENTCHKINF(EVENTCHKINF_48) ? 3 : 2; } +#if ENABLE_CUTSCENE_IMPROVEMENTS + // initialize default values to avoid issues + CutsceneManager_Init(this, NULL, 0); +#endif + Play_SpawnScene( this, gEntranceTable[((void)0, gSaveContext.save.entranceIndex) + ((void)0, gSaveContext.sceneLayer)].sceneId, gEntranceTable[((void)0, gSaveContext.save.entranceIndex) + ((void)0, gSaveContext.sceneLayer)].spawn); @@ -1154,11 +1159,29 @@ void Play_Update(PlayState* this) { } } -#if INCLUDE_EXAMPLE_SCENE - if (this->sceneId == SCENE_EXAMPLE && CHECK_BTN_ALL(this->state.input[0].cur.button, BTN_L | BTN_R) && - CHECK_BTN_ALL(this->state.input[0].press.button, BTN_A) && !Play_InCsMode(this)) { - Cutscene_SetScript(this, gExampleCS); - gSaveContext.cutsceneTrigger = 1; +#if CAN_INCLUDE_EXAMPLE_SCENE + if (this->sceneId == SCENE_EXAMPLE) { + if (CHECK_BTN_ALL(this->state.input[0].cur.button, BTN_Z | BTN_R) && + CHECK_BTN_ALL(this->state.input[0].press.button, BTN_A) && !Play_InCsMode(this)) { + Cutscene_SetScript(this, gExampleCS); + gSaveContext.cutsceneTrigger = 1; + } + +#if ENABLE_CUTSCENE_IMPROVEMENTS + if (!Play_InCsMode(this)) { + // get the additional cutscene id and use it if the value is not -1 + s16 optCsId = CutsceneManager_GetAdditionalCsId(0); + s16 csId = optCsId >= 0 ? optCsId : 0; + + // check if the cutscene is the next on the queue, if it is play it, + // otherwise add it to the queue when the button L is pressed + if (CutsceneManager_IsNext(csId)) { + CutsceneManager_Start(csId, &GET_PLAYER(this)->actor); + } else if (CHECK_BTN_ALL(this->state.input[0].press.button, BTN_L)) { + CutsceneManager_Queue(csId); + } + } +#endif } #endif } diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 8cd396d2b1..da2512a566 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -536,7 +536,6 @@ void Scene_CommandAnimatedMaterials(PlayState* play, SceneCmd* cmd) { #if ENABLE_CUTSCENE_IMPROVEMENTS void Scene_CommandCutsceneList(PlayState* play, SceneCmd* cmd) { CutsceneManager_Init(play, SEGMENTED_TO_VIRTUAL(cmd->cutsceneList.segment), cmd->cutsceneList.num); - PRINTF("(Scene_CommandCutsceneList) segment: 0x%08X, num: %d\n", cmd->cutsceneList.segment, cmd->cutsceneList.num); } void Scene_CommandActorCutsceneCamList(PlayState* play, SceneCmd* cmd) { From 67ea1aba54ee8358a1ced456fd1bf59656f15e3f Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Mon, 6 Jan 2025 00:25:31 +0100 Subject: [PATCH 11/13] format --- src/code/z_scene.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/code/z_scene.c b/src/code/z_scene.c index be7202ce1d..9be8ea6318 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -575,7 +575,7 @@ SceneCmdHandlerFunc sSceneCmdHandlers[SCENE_CMD_ID_MAX] = { #if ENABLE_F3DEX3 Scene_CommandOccPlaneCandList, // SCENE_CMD_ID_OCC_PLANE_CAND_LIST #endif - Scene_CommandAnimatedMaterials, // SCENE_CMD_ID_ANIMATED_MATERIAL_LIST + Scene_CommandAnimatedMaterials, // SCENE_CMD_ID_ANIMATED_MATERIAL_LIST Scene_CommandCutsceneList, // SCENE_CMD_ID_ACTOR_CUTSCENE_LIST Scene_CommandActorCutsceneCamList, // SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST }; From 1490d8b4e13db8f9e5a8dc0921bf49450772cb8b Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Mon, 6 Jan 2025 00:27:42 +0100 Subject: [PATCH 12/13] update safeguards --- include/config/config_safeguards.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/config/config_safeguards.h b/include/config/config_safeguards.h index cef95c2777..e8999fe842 100644 --- a/include/config/config_safeguards.h +++ b/include/config/config_safeguards.h @@ -137,6 +137,14 @@ #define USE_WIDESCREEN (ENABLE_WIDESCREEN && gSaveContext.save.useWidescreen == true) #endif +#if ENABLE_CUTSCENE_IMPROVEMENTS && !ENABLE_NEW_LETTERBOX + #undef ENABLE_NEW_LETTERBOX + #define ENABLE_NEW_LETTERBOX true +#endif + +/***************** + * config_graphics.h + */ //! TODO: implement better Wii VC compatibility #ifdef CONSOLE_WIIVC #undef ENABLE_F3DEX3 From 516d074f8b996544f964bd4e7f7d72bbb3a2eb3c Mon Sep 17 00:00:00 2001 From: Yanis002 <35189056+Yanis002@users.noreply.github.com> Date: Mon, 6 Jan 2025 01:25:47 +0100 Subject: [PATCH 13/13] cleanup and fixes --- include/animated_materials.h | 5 +++++ include/config/config_debug.h | 2 +- include/tables/scene_table.h | 4 ++++ include/z64scene.h | 11 ++++++++++- .../scenes/example/example_room_0_model.c | 4 ++++ mod_assets/scenes/example/example_scene.h | 4 +++- mod_assets/scenes/example/example_scene_main.c | 10 ++++++++++ src/code/animated_materials.c | 5 +++++ src/code/z_scene_table.c | 18 ++++++++---------- .../ovl_debug_opening/debug_opening.c | 4 ++++ 10 files changed, 54 insertions(+), 13 deletions(-) diff --git a/include/animated_materials.h b/include/animated_materials.h index 01ceaa60ea..2277528859 100644 --- a/include/animated_materials.h +++ b/include/animated_materials.h @@ -2,6 +2,9 @@ #define ANIMATED_MATERIALS_H #include "ultra64.h" +#include "config.h" + +#if ENABLE_ANIMATED_MATERIALS typedef enum AnimatedMatType { /* 0 */ ANIM_MAT_TYPE_TEX_SCROLL, @@ -82,3 +85,5 @@ void AnimatedMat_DrawAlphaStepOpa(struct PlayState* play, AnimatedMaterial* matA void AnimatedMat_DrawAlphaStepXlu(struct PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step); #endif + +#endif diff --git a/include/config/config_debug.h b/include/config/config_debug.h index 150c2b713e..184652b35d 100644 --- a/include/config/config_debug.h +++ b/include/config/config_debug.h @@ -28,7 +28,7 @@ /** * Options for booting directly into a scene, the debug boot or the file select, instead of the title screen. */ -#define BOOT_TO_SCENE true +#define BOOT_TO_SCENE false #define BOOT_TO_SCENE_NEW_GAME_ONLY false #define BOOT_TO_FILE_SELECT false #define BOOT_TO_DEBUG_OPENING true diff --git a/include/tables/scene_table.h b/include/tables/scene_table.h index bbb17d218e..9efdc4e661 100644 --- a/include/tables/scene_table.h +++ b/include/tables/scene_table.h @@ -124,5 +124,9 @@ #endif #if CAN_INCLUDE_EXAMPLE_SCENE +#if ENABLE_ANIMATED_MATERIALS /* 0x6C */ DEFINE_SCENE(example_scene, none, SCENE_EXAMPLE, SDC_MAT_ANIM, 0, 0) +#else +/* 0x6C */ DEFINE_SCENE(example_scene, none, SCENE_EXAMPLE, SDC_HAUNTED_WASTELAND, 0, 0) +#endif #endif diff --git a/include/z64scene.h b/include/z64scene.h index fd7810903d..4f25eea60f 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -580,8 +580,10 @@ typedef enum SceneDrawConfig { /* 50 */ SDC_FISHING_POND, /* 51 */ SDC_GANONS_TOWER_COLLAPSE_INTERIOR, /* 52 */ SDC_INSIDE_GANONS_CASTLE_COLLAPSE, +#if ENABLE_ANIMATED_MATERIALS /* 53 */ SDC_MAT_ANIM, /* 54 */ SDC_MAT_ANIM_MANUAL_STEP, +#endif /* 55 */ SDC_MAX } SceneDrawConfig; @@ -634,9 +636,13 @@ typedef enum SceneCommandTypeID { #if ENABLE_F3DEX3 SCENE_CMD_ID_OCC_PLANE_CAND_LIST, #endif +#if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, +#endif +#if ENABLE_CUTSCENE_IMPROVEMENTS SCENE_CMD_ID_ACTOR_CUTSCENE_LIST, SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST, +#endif /* 0x1A */ SCENE_CMD_ID_MAX } SceneCommandTypeID; @@ -724,15 +730,18 @@ typedef enum SceneCommandTypeID { { SCENE_CMD_ID_OCC_PLANE_CAND_LIST, numPlanes, CMD_PTR(planeList) } #endif +#if ENABLE_ANIMATED_MATERIALS #define SCENE_CMD_ANIMATED_MATERIAL_LIST(matAnimList) \ { SCENE_CMD_ID_ANIMATED_MATERIAL_LIST, 0, CMD_PTR(matAnimList) } +#endif +#if ENABLE_CUTSCENE_IMPROVEMENTS #define SCENE_CMD_ACTOR_CUTSCENE_LIST(numEntries, actorCutsceneList) \ { SCENE_CMD_ID_ACTOR_CUTSCENE_LIST, numEntries, CMD_PTR(actorCutsceneList) } #define SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(numCams, camList) \ { SCENE_CMD_ID_ACTOR_CUTSCENE_CAM_LIST, numCams, CMD_PTR(camList) } - +#endif s32 Scene_ExecuteCommands(struct PlayState* play, SceneCmd* sceneCmd); diff --git a/mod_assets/scenes/example/example_room_0_model.c b/mod_assets/scenes/example/example_room_0_model.c index 4d2bc322b2..d9e3a7b75c 100644 --- a/mod_assets/scenes/example/example_room_0_model.c +++ b/mod_assets/scenes/example/example_room_0_model.c @@ -1413,7 +1413,9 @@ Gfx mat_example_room_0_dl_wall_layerOpaque[] = { gsDPLoadBlock(7, 0, 0, 511, 512), gsDPSetTile(G_IM_FMT_I, G_IM_SIZ_8b, 4, 0, 0, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 14, G_TX_WRAP | G_TX_NOMIRROR, 5, 14), gsDPSetTileSize(0, 0, 0, 124, 124), +#if ENABLE_ANIMATED_MATERIALS gsSPDisplayList(0xA000000), +#endif gsSPEndDisplayList(), }; @@ -1664,7 +1666,9 @@ Gfx mat_example_room_0_dl_water_layerTransparent[] = { gsDPSetTileSize(0, 0, 0, 124, 124), gsDPSetTile(G_IM_FMT_CI, G_IM_SIZ_8b, 4, 0, 1, 0, G_TX_WRAP | G_TX_NOMIRROR, 5, 15, G_TX_WRAP | G_TX_NOMIRROR, 5, 15), gsDPSetTileSize(1, 0, 0, 124, 124), +#if ENABLE_ANIMATED_MATERIALS gsSPDisplayList(0x8000000), +#endif gsSPDisplayList(0x9000000), gsSPEndDisplayList(), }; diff --git a/mod_assets/scenes/example/example_scene.h b/mod_assets/scenes/example/example_scene.h index b8056329c5..f06d43456c 100644 --- a/mod_assets/scenes/example/example_scene.h +++ b/mod_assets/scenes/example/example_scene.h @@ -16,6 +16,7 @@ extern ActorEntry example_scene_header00_playerEntryList[]; extern Spawn example_scene_header00_entranceList[]; extern TransitionActorEntry example_scene_header00_transitionActors[]; extern EnvLightSettings example_scene_header00_lightSettings[4]; +#if ENABLE_ANIMATED_MATERIALS extern AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_00[]; extern AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_01[]; extern F3DPrimColor debug1_scene_header00_AnimatedMaterialColorPrimColor_02[]; @@ -23,8 +24,9 @@ extern F3DEnvColor debug1_scene_header00_AnimatedMaterialColorEnvColor_02[]; extern u16 debug1_scene_header00_AnimatedMaterialColorKeyFrames_02[]; extern AnimatedMatColorParams debug1_scene_header00_AnimatedMaterialColorParams_02; extern AnimatedMaterial debug1_scene_header00_AnimatedMaterial[]; -extern Vec3s debug1_scene_header00_ActorCutsceneCameraData[]; +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS +extern Vec3s debug1_scene_header00_ActorCutsceneCameraData[]; extern ActorCsCamInfo debug1_scene_header00_ActorCutsceneCameraInfo[]; extern CutsceneEntry debug1_scene_header00_ActorCutsceneList[]; #endif diff --git a/mod_assets/scenes/example/example_scene_main.c b/mod_assets/scenes/example/example_scene_main.c index f9156861f6..45d59d0e54 100644 --- a/mod_assets/scenes/example/example_scene_main.c +++ b/mod_assets/scenes/example/example_scene_main.c @@ -19,7 +19,9 @@ SceneCmd example_scene_header00[] = { SCENE_CMD_ENTRANCE_LIST(example_scene_header00_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header00_playerEntryList), SCENE_CMD_CUTSCENE_DATA(gExampleCS), +#if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), @@ -158,6 +160,7 @@ EnvLightSettings example_scene_header00_lightSettings[4] = { }, }; +#if ENABLE_ANIMATED_MATERIALS AnimatedMatTexScrollParams debug1_scene_header00_AnimatedMaterialTexScrollParams_00[] = { { 0, -1, 32, 32 }, { 0, -1, 32, 32 } @@ -205,6 +208,7 @@ AnimatedMaterial debug1_scene_header00_AnimatedMaterial[] = { { 2 /* 9 */, 1, debug1_scene_header00_AnimatedMaterialTexScrollParams_01 }, { -3 /* 10 */, 4, &debug1_scene_header00_AnimatedMaterialColorParams_02 } }; +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS Vec3s debug1_scene_header00_ActorCutsceneCameraData[] = { @@ -242,7 +246,9 @@ SceneCmd example_scene_header01[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header01_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header01_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header01_playerEntryList), +#if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), @@ -385,7 +391,9 @@ SceneCmd example_scene_header02[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header02_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header02_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header02_playerEntryList), +#if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), @@ -528,7 +536,9 @@ SceneCmd example_scene_header03[] = { SCENE_CMD_TRANSITION_ACTOR_LIST(1, example_scene_header03_transitionActors), SCENE_CMD_ENTRANCE_LIST(example_scene_header03_entranceList), SCENE_CMD_SPAWN_LIST(7, example_scene_header03_playerEntryList), +#if ENABLE_ANIMATED_MATERIALS SCENE_CMD_ANIMATED_MATERIAL_LIST(debug1_scene_header00_AnimatedMaterial), +#endif #if ENABLE_CUTSCENE_IMPROVEMENTS SCENE_CMD_ACTOR_CUTSCENE_LIST(2, debug1_scene_header00_ActorCutsceneList), SCENE_CMD_ACTOR_CUTSCENE_CAM_LIST(2, debug1_scene_header00_ActorCutsceneCameraInfo), diff --git a/src/code/animated_materials.c b/src/code/animated_materials.c index fbe802eb5d..dd4221fe6c 100644 --- a/src/code/animated_materials.c +++ b/src/code/animated_materials.c @@ -2,6 +2,9 @@ #include "global.h" #include "z64.h" #include "helpers.h" +#include "config.h" + +#if ENABLE_ANIMATED_MATERIALS static s32 sMatAnimStep; static u32 sMatAnimFlags; @@ -397,3 +400,5 @@ void AnimatedMat_DrawAlphaStepOpa(PlayState* play, AnimatedMaterial* matAnim, f3 void AnimatedMat_DrawAlphaStepXlu(PlayState* play, AnimatedMaterial* matAnim, f32 alphaRatio, u32 step) { AnimatedMat_DrawMain(play, matAnim, alphaRatio, step, 2); } + +#endif diff --git a/src/code/z_scene_table.c b/src/code/z_scene_table.c index c616926c0d..cf391ab121 100644 --- a/src/code/z_scene_table.c +++ b/src/code/z_scene_table.c @@ -86,8 +86,10 @@ void Scene_DrawConfigFishingPond(PlayState* play); void Scene_DrawConfigGanonsTowerCollapseInterior(PlayState* play); void Scene_DrawConfigInsideGanonsCastleCollapse(PlayState* play); +#if ENABLE_ANIMATED_MATERIALS void Scene_DrawConfigMatAnim(PlayState* play); void Scene_DrawConfigMatAnimManualStep(PlayState* play); +#endif // Entrance Table definition #define DEFINE_ENTRANCE(_0, sceneId, spawn, continueBgm, displayTitleCard, endTransType, startTransType) \ @@ -196,8 +198,10 @@ SceneDrawConfigFunc sSceneDrawConfigs[SDC_MAX] = { Scene_DrawConfigFishingPond, // SDC_FISHING_POND Scene_DrawConfigGanonsTowerCollapseInterior, // SDC_GANONS_TOWER_COLLAPSE_INTERIOR Scene_DrawConfigInsideGanonsCastleCollapse, // SDC_INSIDE_GANONS_CASTLE_COLLAPSE - Scene_DrawConfigMatAnim, // SDC_MAT_ANIM - Scene_DrawConfigMatAnimManualStep, // SDC_MAT_ANIM_MANUAL_STEP +#if ENABLE_ANIMATED_MATERIALS + Scene_DrawConfigMatAnim, // SDC_MAT_ANIM + Scene_DrawConfigMatAnimManualStep, // SDC_MAT_ANIM_MANUAL_STEP +#endif }; #if PLATFORM_N64 // Scene_Draw is at end of file in GC/iQue versions @@ -1709,15 +1713,12 @@ void Scene_DrawConfigBesitu(PlayState* play) { CLOSE_DISPS(play->state.gfxCtx, "../z_scene_table.c", 7910); } +#if ENABLE_ANIMATED_MATERIALS /** * Allows the usage of the animated material system in scenes. */ void Scene_DrawConfigMatAnim(PlayState* play) { -#if ENABLE_ANIMATED_MATERIALS AnimatedMat_Draw(play, play->sceneMaterialAnims); -#else - Scene_DrawConfigDefault(play); -#endif } /** @@ -1725,12 +1726,9 @@ void Scene_DrawConfigMatAnim(PlayState* play) { * rather than always animating like `Scene_DrawConfigMatAnim`. */ void Scene_DrawConfigMatAnimManualStep(PlayState* play) { -#if ENABLE_ANIMATED_MATERIALS AnimatedMat_DrawStep(play, play->sceneMaterialAnims, play->roomCtx.drawParams[0]); -#else - Scene_DrawConfigDefault(play); -#endif } +#endif #if !PLATFORM_N64 // Scene_Draw is at beginning of file in N64 versions diff --git a/src/overlays/gamestates/ovl_debug_opening/debug_opening.c b/src/overlays/gamestates/ovl_debug_opening/debug_opening.c index c6d20066dc..22f2a36f13 100644 --- a/src/overlays/gamestates/ovl_debug_opening/debug_opening.c +++ b/src/overlays/gamestates/ovl_debug_opening/debug_opening.c @@ -254,6 +254,10 @@ void DebugOpening_Init(GameState* thisx) { gSaveContext.save.dayTime = gSaveContext.skyboxTime = CLOCK_TIME(15, 0); Helpers_InitSkybox(&this->state, &this->envCtx, &this->skyboxCtx, DEBUG_OPENING_SKYBOX_ID); +#if ENABLE_NEW_LETTERBOX + ShrinkWindow_Init(); +#endif + this->state.main = DebugOpening_Main; this->state.destroy = DebugOpening_Destroy;