diff --git a/assets/xml/objects/object_and.xml b/assets/xml/objects/object_and.xml index a076a1c07..69ffebc7b 100644 --- a/assets/xml/objects/object_and.xml +++ b/assets/xml/objects/object_and.xml @@ -1,79 +1,80 @@  + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/include/functions.h b/include/functions.h index 09cdd2de0..459c28e23 100644 --- a/include/functions.h +++ b/include/functions.h @@ -133,7 +133,7 @@ void SystemArena_FreeNullCheck(void* ptr); void SystemArena_RunInits(void); void SystemArena_Init(void* start, size_t size); s32 func_80086620(OSMesgQueue* param_1, PadMgr* param_2, OSContStatus* param_3); -// void func_80086760(void); +f32 func_80086760(f32 x); // void func_80086794(void); // void func_800867B4(void); // void func_800867D4(void); @@ -609,8 +609,8 @@ void Flags_SetCollectible(PlayState* play, s32 flag); void TitleCard_InitBossName(GameState* gameState, TitleCardContext* titleCtx, TexturePtr texture, s16 x, s16 y, u8 width, u8 height); -s32 func_800B648C(PlayState* play, s32 arg1, s32 timer, f32 arg3, Vec3f* arg4); -f32 func_800B64FC(PlayState* play, f32 arg1, Vec3f* arg2, u32* arg3); +s32 Actor_SetPlayerImpact(PlayState* play, PlayerImpactType type, s32 timer, f32 dist, Vec3f* pos); +f32 Actor_GetPlayerImpact(PlayState* play, f32 range, Vec3f* pos, PlayerImpactType* type); void* func_800B6584(PlayState* play, s16 id, void* arg2, size_t size); void* func_800B6608(PlayState* play, s16 id); void* func_800B6680(PlayState* play, s16 id); @@ -739,9 +739,9 @@ s16 Actor_TestFloorInDirection(Actor* actor, PlayState* play, f32 distance, s16 s32 Actor_IsTargeted(PlayState* play, Actor* actor); s32 Actor_OtherIsTargeted(PlayState* play, Actor* actor); void func_800BC620(Vec3f* pos, Vec3f* scale, u8 alpha, PlayState* play); -void Actor_AddQuake(PlayState* play, s16 verticalMag, s16 countdown); -void Actor_AddQuakeWithSpeed(PlayState* play, s16 verticalMag, s16 countdown, s16 speed); -void func_800BC848(Actor* actor, PlayState* play, s16 y, s16 countdown); +void Actor_RequestQuake(PlayState* play, s16 y, s16 duration); +void Actor_RequestQuakeWithSpeed(PlayState* play, s16 y, s16 duration, s16 speed); +void Actor_RequestQuakeAndRumble(Actor* actor, PlayState* play, s16 quakeY, s16 quakeDuration); void Actor_DrawDoorLock(PlayState* play, s32 frame, s32 type); void Actor_SetColorFilter(Actor* actor, u16 colorFlag, u16 colorIntensityMax, u16 bufFlag, u16 duration); Hilite* func_800BCBF4(Vec3f* arg0, PlayState* play); @@ -797,47 +797,45 @@ s32 DynaPolyActor_IsSwitchPressed(DynaPolyActor* dynaActor); s32 DynaPolyActor_IsHeavySwitchPressed(DynaPolyActor* dynaActor); s32 DynaPolyActor_ValidateMove(PlayState* play, DynaPolyActor* dynaActor, s16 startRadius, s16 endRadius, s16 startHeight); -Camera* Camera_Alloc(View* view, CollisionContext* bg, PlayState* play); -void Camera_Free(Camera* camera); -void Camera_Init(Camera* camera, View* view, CollisionContext* bg, PlayState* play); -// void func_800DDFE0(void); -void Camera_InitPlayerSettings(Camera* camera, Player* player); +Camera* Camera_Create(View* view, CollisionContext* colCtx, PlayState* play); +void Camera_Destroy(Camera* camera); +void Camera_Init(Camera* camera, View* view, CollisionContext* colCtx, PlayState* play); +void func_800DDFE0(Camera* camera); +void Camera_InitFocalActorSettings(Camera* camera, Actor* focalActor); s32 Camera_ChangeStatus(Camera* camera, s16 status); -// void func_800DE324(void); -// void func_800DE62C(void); -// void func_800DE840(void); -// void func_800DE890(void); -// UNK_TYPE4 func_800DE954(Camera* camera); -Vec3s* Camera_Update(Vec3s* param_1, Camera* camera); -// void func_800DF498(void); -u32 Camera_SetMode(Camera* camera, s16 mode, s8 param_3); +s32 Camera_UpdateWater(Camera* camera); +void Camera_EarthquakeDay3(Camera* camera); +s32 Camera_UpdateHotRoom(Camera* camera); +s32 Camera_SetSwordDistortion(Camera* camera); +s32 Camera_RequestGiantsMaskSetting(Camera* camera); +Vec3s* Camera_Update(Vec3s* inputDir, Camera* camera); +s32 func_800DF498(Camera* camera); +s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 forceChange); s32 Camera_ChangeMode(Camera* camera, s16 mode); -s32 func_800DF86C(Camera* camera, s16 arg1); -// void func_800DF8EC(void); +s32 Camera_CheckValidMode(Camera* camera, s16 mode); +s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags); s32 Camera_ChangeSetting(Camera* camera, s16 setting); -s32 Camera_ChangeDataIdx(Camera* camera, s32 camDataIdx); -// void func_800DFC1C(void); -// void func_800DFC40(void); -s32 Camera_GetInputDirYaw(Camera* camera); -void Camera_GetCamDir(Vec3s* dst, Camera* camera); +s32 Camera_ChangeActorCsCamIndex(Camera* camera, s32 bgCamIndex); +Vec3s* Camera_GetInputDir(Vec3s* dst, Camera* camera); +s16 Camera_GetInputDirPitch(Camera* camera); +s16 Camera_GetInputDirYaw(Camera* camera); +Vec3s* Camera_GetCamDir(Vec3s* dst, Camera* camera); s16 Camera_GetCamDirPitch(Camera* camera); s16 Camera_GetCamDirYaw(Camera* camera); -void Camera_AddQuake(Camera* camera, s32 arg1, s16 y, s32 countdown); +s32 Camera_AddQuake(Camera* camera, s32 arg1, s16 y, s32 countdown); s32 Camera_SetViewParam(Camera* camera, s32 viewFlag, void* param); -// UNK_TYPE4 func_800DFEF0(s32 param_1, u16 param_2); -void func_800DFF18(Camera* camera, s32 arg1); -// UNK_TYPE4 func_800DFF34(s32 param_1); -// UNK_TYPE4 func_800DFF44(void); -s16 Camera_SetFlags(Camera* iParm1, s16 flags); -s16 Camera_ClearFlags(Camera* camera, s16 flags); +s32 Camera_UnsetViewFlag(Camera* camera, s16 viewFlag); +s32 Camera_OverwriteStateFlags(Camera* camera, s16 stateFlags); +s16 Camera_SetStateFlag(Camera* camera, s16 flags); +s16 Camera_UnsetStateFlag(Camera* camera, s16 flags); s32 Camera_ChangeDoorCam(Camera* camera, Actor* doorActor, s16 bgCamIndex, f32 arg3, s16 timer1, s16 timer2, s16 timer3); -s32 Camera_Copy(Camera* dstCamera, Camera* srcCamera); -// UNK_TYPE4 func_800E01AC(void); -Vec3f* Camera_GetQuakeOffset(Vec3f* dst, Camera* camera); -// void func_800E01DC(s32 param_1, u32 param_2, UNK_TYPE4 param_3, UNK_TYPE4 param_4, UNK_TYPE2 param_5, UNK_TYPE2 param_6); -// UNK_TYPE4 func_800E0228(void); -void func_800E0238(Camera* camera); -void Camera_SetToTrackActor(Camera* camera, Actor* actor); +s32 Camera_Copy(Camera* dstCam, Camera* srcCam); +s32 Camera_IsDbgCamEnabled(void); +Vec3f* Camera_GetQuakeOffset(Vec3f* quakeOffset, Camera* camera); +void Camera_SetCameraData(Camera* camera, s16 setDataFlags, void* data0, void* data1, s16 data2, s16 data3); +s32 Camera_GetNegOne(void); +s16 func_800E0238(Camera* camera); +void Camera_SetFocalActor(Camera* camera, Actor* actor); void Camera_SetTargetActor(Camera* camera, Actor* actor); f32 Camera_GetWaterYPos(Camera* camera); void func_800E0348(Camera* camera); @@ -1292,7 +1290,7 @@ void* func_801068FC(PlayState* play, void* arg1, size_t size); void func_80108AF8(PlayState* play); s32 func_801090B0(s32 arg0); s32 func_80109124(s16 arg0); -// void func_801091F0(void); +void func_801091F0(PlayState* play); void func_80109428(PlayState* play); // void func_801094A0(void); // void func_801094C8(void); @@ -1411,17 +1409,17 @@ f32 OLib_ClampMinDist(f32 val, f32 min); f32 OLib_ClampMaxDist(f32 val, f32 max); Vec3f* OLib_Vec3fDistNormalize(Vec3f* dest, Vec3f* a, Vec3f* b); Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph); -Vec3f* OLib_VecSphGeoToVec3f(Vec3f* dest, VecSph* sph); +Vec3f* OLib_VecGeoToVec3f(Vec3f* dest, VecGeo* geo); VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec); -VecSph* OLib_Vec3fToVecSphGeo(VecSph* dest, Vec3f* vec); +VecGeo* OLib_Vec3fToVecGeo(VecGeo* dest, Vec3f* vec); VecSph* OLib_Vec3fDiffToVecSph(VecSph* dest, Vec3f* a, Vec3f* b); -VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* dest, Vec3f* a, Vec3f* b); -Vec3f* OLib_VecSphAddToVec3f(Vec3f* dest, Vec3f* a, VecSph* sph); +VecGeo* OLib_Vec3fDiffToVecGeo(VecGeo* dest, Vec3f* a, Vec3f* b); +Vec3f* OLib_AddVecGeoToVec3f(Vec3f* dest, Vec3f* a, VecGeo* geo); Vec3f* OLib_Vec3fDiffRad(Vec3f* dest, Vec3f* a, Vec3f* b); Vec3f* OLib_Vec3fDiffDegF(Vec3f* dest, Vec3f* a, Vec3f* b); Vec3s* OLib_Vec3fDiffBinAng(Vec3s* dest, Vec3f* a, Vec3f* b); -void OLib_DbCameraVec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); -void OLib_DbCameraVec3fSum(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); +void OLib_Vec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); +void OLib_Vec3fAdd(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode); Gfx* Gfx_DrawTexRectRGBA16(Gfx* gfx, TexturePtr texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop, s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy); Gfx* Gfx_DrawTexRectIA8(Gfx* gfx, TexturePtr texture, s16 textureWidth, s16 textureHeight, s16 rectLeft, s16 rectTop, s16 rectWidth, s16 rectHeight, u16 dsdx, u16 dtdy); diff --git a/include/initvars.h b/include/initvars.h deleted file mode 100644 index 554b0ff5d..000000000 --- a/include/initvars.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef _INITVARS_H_ -#define _INITVARS_H_ - -extern TransitionInit TransitionFade_InitVars; -extern TransitionInit TransitionTriforce_InitVars; -extern TransitionInit TransitionWipe1_InitVars; -extern TransitionInit TransitionWipe3_InitVars; -extern TransitionInit TransitionWipe4_InitVars; -extern TransitionInit TransitionCircle_InitVars; -extern TransitionInit TransitionWipe5_InitVars; - -#endif diff --git a/include/segment_symbols.h b/include/segment_symbols.h index 79601bc93..9fc49a6cb 100644 --- a/include/segment_symbols.h +++ b/include/segment_symbols.h @@ -88,12 +88,6 @@ DECLARE_OVERLAY_SEGMENT(player_actor) #undef DEFINE_ACTOR_INTERNAL #undef DEFINE_ACTOR_UNSET -DECLARE_OVERLAY_SEGMENT(fbdemo_triforce) -DECLARE_OVERLAY_SEGMENT(fbdemo_wipe1) -DECLARE_OVERLAY_SEGMENT(fbdemo_wipe3) -DECLARE_OVERLAY_SEGMENT(fbdemo_wipe4) -DECLARE_OVERLAY_SEGMENT(fbdemo_wipe5) - #define DEFINE_OBJECT(name, _enumValue) DECLARE_ROM_SEGMENT(name) #define DEFINE_OBJECT_UNSET(_enumValue) #define DEFINE_OBJECT_SIZE_ZERO(_name, _enumValue) diff --git a/include/tables/transition_table.h b/include/tables/transition_table.h new file mode 100644 index 000000000..d623d76bb --- /dev/null +++ b/include/tables/transition_table.h @@ -0,0 +1,21 @@ +/** + * Transition Table + * + * DEFINE_TRANSITION should be used for normal transitions + * - Argument 0: Enum value for this transition + * - Argument 1: Name of the effect struct + * - Argument 2: Instance name + * - Argument 3: Name of the effect (without the ovl_ part) + * + * DEFINE_TRANSITION_INTERNAL should be used for transitions that aren't an overlay + * - Argument 0: Enum value for this transition + * - Argument 1: Name of the effect struct + * - Argument 2: Instance name + */ +/* 0 */ DEFINE_TRANSITION_INTERNAL(FBDEMO_FADE, TransitionFade, fade) +/* 1 */ DEFINE_TRANSITION(FBDEMO_TRIFORCE, TransitionTriforce, triforce, fbdemo_triforce) +/* 2 */ DEFINE_TRANSITION(FBDEMO_WIPE1, TransitionWipe1, wipe1, fbdemo_wipe1) +/* 3 */ DEFINE_TRANSITION(FBDEMO_WIPE3, TransitionWipe3, wipe3, fbdemo_wipe3) +/* 4 */ DEFINE_TRANSITION(FBDEMO_WIPE4, TransitionWipe4, wipe4, fbdemo_wipe4) +/* 5 */ DEFINE_TRANSITION_INTERNAL(FBDEMO_CIRCLE, TransitionCircle, circle) +/* 6 */ DEFINE_TRANSITION(FBDEMO_WIPE5, TransitionWipe5, wipe5, fbdemo_wipe5) diff --git a/include/variables.h b/include/variables.h index 9ced17a09..935a96076 100644 --- a/include/variables.h +++ b/include/variables.h @@ -384,23 +384,6 @@ extern BgCheckSceneSubdivisionEntry sSceneSubdivisionList[]; extern BgSpecialSceneMaxObjects sCustomDynapolyMem[]; // extern UNK_TYPE1 D_801B4708; -// extern UNK_TYPE4 D_801B9E0C; -// extern UNK_TYPE4 D_801B9E10; -// extern UNK_TYPE4 D_801B9E14; -// extern UNK_TYPE2 D_801B9E18; -// extern UNK_TYPE2 D_801B9E34; -// extern UNK_TYPE4 D_801B9E50; -// extern UNK_TYPE4 D_801B9E54; -// extern UNK_TYPE4 D_801B9E58; -// extern UNK_TYPE4 D_801B9E5C; -// extern UNK_TYPE4 D_801B9E60; -// extern UNK_TYPE1 D_801B9E64; -// extern UNK_TYPE1 D_801B9E84; -// extern UNK_TYPE4 D_801B9EB4; -// extern UNK_TYPE4 D_801B9ED4; -// extern UNK_TYPE4 sEarthquakeFreq; -// extern UNK_TYPE2 sEarthquakeTimer; -extern UNK_TYPE4 D_801B9F10; extern DamageTable sDamageTablePresets[23]; extern f32 damageMultipliers[16]; extern Collider defaultCollider; @@ -746,7 +729,6 @@ extern char D_801D039C[]; extern KaleidoMgrOverlay gKaleidoMgrOverlayTable[2]; // extern UNK_TYPE1 D_801D0B8C; extern KaleidoMgrOverlay* gKaleidoMgrCurOvl; -// extern UNK_TYPE4 D_801D0BB0; // extern UNK_TYPE1 D_801D0C80; // extern UNK_TYPE1 D_801D0CB0; extern s32 gDbgCamEnabled; @@ -2241,7 +2223,7 @@ extern f32 D_801ED8D0; // extern UNK_TYPE1 D_801ED8D8; // extern UNK_TYPE1 D_801ED8DC; extern Mtx D_801ED8E0; -// extern UNK_TYPE1 D_801ED920; +extern Actor* D_801ED920; extern FaultClient sActorOverlayTableFaultClient; extern FaultAddrConvClient sActorOverlayTableFaultAddrConvClient; extern char D_801ED950[80]; @@ -2257,20 +2239,6 @@ extern Vec3f D_801EDB70[3]; extern Plane D_801EDB98; extern Sphere16 D_801EDBA8; extern TriNorm D_801EDBB0; -// extern UNK_TYPE1 D_801EDBD4; -// extern UNK_TYPE1 D_801EDBD8; -// extern UNK_TYPE1 D_801EDBDC; -// extern UNK_TYPE1 D_801EDBE0; - -// extern s16 D_801EDBF0; -// extern f32 D_801EDBF4; -// extern f32 D_801EDBF8; -// extern CameraCollision D_801EDC00; -// extern PlayState* sCamPlayState; -// extern SwingAnimation D_801EDC30[4]; -// extern Vec3f D_801EDDD0; -// extern Vec3f D_801EDDE0; -// extern Vec3f D_801EDDF0; extern Vec3f D_801EDE00; extern Vec3f D_801EDE10; diff --git a/include/z64.h b/include/z64.h index 50405690f..95af2c157 100644 --- a/include/z64.h +++ b/include/z64.h @@ -261,11 +261,11 @@ typedef struct { /* 0x188 */ Vtx* questPageVtx; /* 0x18C */ Vtx* maskPageVtx; /* 0x190 */ Vtx* itemVtx; - /* 0x194 */ Vtx* mapVtx; + /* 0x194 */ Vtx* mapVtx; // inferred /* 0x198 */ Vtx* questVtx; /* 0x19C */ Vtx* maskVtx; - /* 0x1A0 */ Vtx* unk_1A0; - /* 0x1A4 */ Vtx* unk_1A4; + /* 0x1A0 */ Vtx* promptPageVtx; + /* 0x1A4 */ Vtx* infoPanelVtx; /* 0x1A8 */ Vtx* cursorVtx; /* 0x1AC */ OcarinaStaff* ocarinaStaff; /* 0x1B0 */ UNK_TYPE1 unk_1B0[0x20]; @@ -281,10 +281,10 @@ typedef struct { /* 0x206 */ u16 switchPageTimer; /* 0x208 */ u16 savePromptState; /* 0x20C */ f32 unk_20C; - /* 0x210 */ f32 itemPageRoll; // rotation (-z) of the item page into the screen - /* 0x214 */ f32 mapPageRoll; // rotation (+x) of the map page into the screen - /* 0x218 */ f32 questPageRoll; // rotation (+z) of the quest page into the screen - /* 0x21C */ f32 maskPageRoll; // rotation (-z) of the mask page into the screen + /* 0x210 */ f32 itemPageRoll; // rotation (-z) of the item page into the screen + /* 0x214 */ f32 mapPageRoll; // rotation (+x) of the map page into the screen + /* 0x218 */ f32 questPageRoll; // rotation (+z) of the quest page into the screen + /* 0x21C */ f32 maskPageRoll; // rotation (-z) of the mask page into the screen /* 0x220 */ f32 roll; /* 0x224 */ u16 alpha; /* 0x226 */ s16 offsetY; diff --git a/include/z64actor.h b/include/z64actor.h index 7cc4275ac..3a646fe8f 100644 --- a/include/z64actor.h +++ b/include/z64actor.h @@ -389,12 +389,18 @@ typedef struct { /* 0xE */ s16 intensity; } TitleCardContext; // size = 0x10 -typedef struct ActorContext_unk_1F4 { - /* 0x00 */ u8 unk_00; +typedef enum { + /* 0 */ PLAYER_IMPACT_GORON_GROUND_POUND, + /* 1 */ PLAYER_IMPACT_ZORA_BARRIER, + /* 2 */ PLAYER_IMPACT_BONK // also activated by goron attack +} PlayerImpactType; + +typedef struct PlayerImpact { + /* 0x00 */ u8 type; /* 0x01 */ u8 timer; - /* 0x04 */ f32 unk_04; - /* 0x08 */ Vec3f unk_08; -} ActorContext_unk_1F4; // size = 0x14 + /* 0x04 */ f32 dist; + /* 0x08 */ Vec3f pos; +} PlayerImpact; // size = 0x14 typedef struct ActorContext_unk_20C { /* 0x0 */ s16 id; @@ -458,7 +464,7 @@ typedef struct ActorContext { /* 0x120 */ TargetContext targetContext; /* 0x1B8 */ ActorContextSceneFlags sceneFlags; /* 0x1E4 */ TitleCardContext titleCtxt; - /* 0x1F4 */ ActorContext_unk_1F4 unk_1F4; + /* 0x1F4 */ PlayerImpact playerImpact; /* 0x208 */ UNK_TYPE1 unk_208[0x4]; /* 0x20C */ ActorContext_unk_20C unk_20C[8]; /* 0x24C */ UNK_TYPE1 unk_24C[0x4]; @@ -526,8 +532,8 @@ typedef enum { #define ACTOR_FLAG_400 (1 << 10) // #define ACTOR_FLAG_800 (1 << 11) -// -#define ACTOR_FLAG_1000 (1 << 12) +// Actor will not shake when a quake occurs +#define ACTOR_FLAG_IGNORE_QUAKE (1 << 12) // #define ACTOR_FLAG_2000 (1 << 13) // diff --git a/include/z64bgcheck.h b/include/z64bgcheck.h index a5effefca..91a892e03 100644 --- a/include/z64bgcheck.h +++ b/include/z64bgcheck.h @@ -255,7 +255,7 @@ typedef struct { /* 0x14 */ u16 numPolygons; /* 0x18 */ CollisionPoly* polyList; /* 0x1C */ SurfaceType* surfaceTypeList; - /* 0x20 */ CamData* bgCamList; + /* 0x20 */ BgCamInfo* bgCamList; /* 0x24 */ u16 numWaterBoxes; /* 0x28 */ WaterBox* waterBoxes; } CollisionHeader; // size = 0x2C diff --git a/include/z64camera.h b/include/z64camera.h index 3205496e7..54cf748ac 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -90,18 +90,18 @@ #define CAM_BEHAVIOR_SETTING_2 (1 << 4) // Mode (0x2, 0x20) #define CAM_BEHAVIOR_MODE_1 (1 << 1) -#define CAM_BEHAVIOR_MODE_2 (1 << 5) +#define CAM_BEHAVIOR_MODE_VALID (1 << 5) // bgCam (0x4, 0x40) #define CAM_BEHAVIOR_BGCAM_1 (1 << 2) #define CAM_BEHAVIOR_BGCAM_2 (1 << 6) // Camera stateFlags. Variety of generic flags #define CAM_STATE_0 (1 << 0) // Must be set for the camera from changing settings based on the bg surface -#define CAM_STATE_1 (1 << 1) +#define CAM_STATE_CHECK_WATER (1 << 1) #define CAM_STATE_2 (1 << 2) #define CAM_STATE_3 (1 << 3) #define CAM_STATE_4 (1 << 4) -#define CAM_STATE_5 (1 << 5) +#define CAM_STATE_DISABLE_MODE_CHANGE (1 << 5) #define CAM_STATE_6 (1 << 6) #define CAM_STATE_7 (1 << 7) #define CAM_STATE_UNDERWATER (1 << 8) @@ -110,7 +110,7 @@ #define CAM_STATE_11 (1 << 11) #define CAM_STATE_12 (1 << 12) #define CAM_STATE_13 (1 << 13) -#define CAM_STATE_14 (1 << 14) +#define CAM_STATE_INITIALIZED (1 << 14) #define CAM_STATE_15 ((s16)(1 << 15)) // Camera viewFlags. Set params related to view @@ -340,13 +340,13 @@ typedef enum { } CameraFuncType; typedef enum { - /* 0x00 */ CAM_DATA_00, + /* 0x00 */ CAM_DATA_Y_OFFSET, /* 0x01 */ CAM_DATA_01, /* 0x02 */ CAM_DATA_02, - /* 0x03 */ CAM_DATA_03, + /* 0x03 */ CAM_DATA_PITCH_TARGET, /* 0x04 */ CAM_DATA_04, /* 0x05 */ CAM_DATA_05, - /* 0x06 */ CAM_DATA_06, + /* 0x06 */ CAM_DATA_YAW_DIFF_RANGE, /* 0x07 */ CAM_DATA_FOV, /* 0x08 */ CAM_DATA_08, /* 0x09 */ CAM_DATA_INTERFACE_FLAGS, @@ -374,7 +374,7 @@ typedef struct { /* 0x00 */ Vec3f pos; /* 0x0C */ Vec3f norm; /* 0x18 */ CollisionPoly* poly; - /* 0x1C */ VecSph sphNorm; + /* 0x1C */ VecGeo geoNorm; /* 0x24 */ s32 bgId; } CameraCollision; // size = 0x28 @@ -405,13 +405,13 @@ typedef struct { */ #define CAM_FUNCDATA_NORM1(yOffset, data01, data02, pitchTarget, eyeStepScale, posStepScale, yawDiffRange, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { eyeStepScale, CAM_DATA_04 }, \ { posStepScale, CAM_DATA_05 }, \ - { yawDiffRange, CAM_DATA_06 }, \ + { yawDiffRange, CAM_DATA_YAW_DIFF_RANGE }, \ { fov, CAM_DATA_FOV }, \ { data08, CAM_DATA_08 }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -462,10 +462,10 @@ typedef struct { // Unused Camera RemoteBomb Setting #define CAM_FUNCDATA_NORM2(yOffset, data01, data02, pitchTarget, data04, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data04, CAM_DATA_04 }, \ { fov, CAM_DATA_FOV }, \ { data08, CAM_DATA_08 }, \ @@ -480,10 +480,10 @@ typedef struct { */ #define CAM_FUNCDATA_NORM3(yOffset, data01, data02, pitchTarget, eyeStepScale, posStepScale, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { eyeStepScale, CAM_DATA_04 }, \ { posStepScale, CAM_DATA_05 }, \ { fov, CAM_DATA_FOV }, \ @@ -530,12 +530,12 @@ typedef struct { */ #define CAM_FUNCDATA_NORM0(yOffset, data01, data02, data21, data04, yawDiffRange, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data21, CAM_DATA_21 }, \ { data04, CAM_DATA_04 }, \ - { yawDiffRange, CAM_DATA_06 }, \ + { yawDiffRange, CAM_DATA_YAW_DIFF_RANGE }, \ { fov, CAM_DATA_FOV }, \ { data08, CAM_DATA_08 }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -581,10 +581,10 @@ typedef struct { */ #define CAM_FUNCDATA_PARA1(yOffset, data01, data02, pitchTarget, data10, data04, data05, fov, data08, interfaceFlags, data11, data12) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data10, CAM_DATA_10 }, \ { data04, CAM_DATA_04 }, \ { data05, CAM_DATA_05 }, \ @@ -596,10 +596,10 @@ typedef struct { // Same as above but with extra unused entry #define CAM_FUNCDATA_PARA1_ALT(yOffset, data01, data02, pitchTarget, data10, data04, data05, fov, data08, interfaceFlags, data11, data12, data18) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data10, CAM_DATA_10 }, \ { data04, CAM_DATA_04 }, \ { data05, CAM_DATA_05 }, \ @@ -662,10 +662,10 @@ typedef struct { // Unused Camera Maze Setting #define CAM_FUNCDATA_PARA2(yOffset, data02, data01, pitchTarget, data04, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data02, CAM_DATA_02 }, \ { data01, CAM_DATA_01 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data04, CAM_DATA_04 }, \ { fov, CAM_DATA_FOV }, \ { data08, CAM_DATA_08 }, \ @@ -680,7 +680,7 @@ typedef struct { */ #define CAM_FUNCDATA_JUMP2(yOffset, data01, data02, data20, data04, data05, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data20, CAM_DATA_20 }, \ @@ -729,13 +729,13 @@ typedef struct { */ #define CAM_FUNCDATA_JUMP3(yOffset, data01, data02, pitchTarget, data04, data05, yawDiffRange, fov, data08, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data04, CAM_DATA_04 }, \ { data05, CAM_DATA_05 }, \ - { yawDiffRange, CAM_DATA_06 }, \ + { yawDiffRange, CAM_DATA_YAW_DIFF_RANGE }, \ { fov, CAM_DATA_FOV }, \ { data08, CAM_DATA_08 }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -785,7 +785,7 @@ typedef struct { */ #define CAM_FUNCDATA_BATT1(yOffset, data01, data02, data13, data14, data15, data16, data17, fov, data08, interfaceFlags, data11, data18) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data13, CAM_DATA_13 }, \ @@ -845,7 +845,7 @@ typedef struct { */ #define CAM_FUNCDATA_KEEP1(yOffset, data01, data02, data13, data14, data15, data16, data17, fov, data08, interfaceFlags, data11) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data13, CAM_DATA_13 }, \ @@ -902,7 +902,7 @@ typedef struct { */ #define CAM_FUNCDATA_KEEP3(yOffset, data01, data02, data13, data14, data15, data16, data17, fov, data08, timer, interfaceFlags, data18) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data13, CAM_DATA_13 }, \ @@ -957,9 +957,9 @@ typedef struct { */ #define CAM_FUNCDATA_KEEP4(yOffset, data01, pitchTarget, data10, data18, fov, interfaceFlags, data04, timer) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ - { pitchTarget, CAM_DATA_03 }, \ + { pitchTarget, CAM_DATA_PITCH_TARGET }, \ { data10, CAM_DATA_10 }, \ { data18, CAM_DATA_18 }, \ { fov, CAM_DATA_FOV }, \ @@ -1008,7 +1008,7 @@ typedef struct { */ #define CAM_FUNCDATA_FIXD1(yOffset, data04, fov, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data04, CAM_DATA_04 }, \ { fov, CAM_DATA_FOV }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -1040,7 +1040,7 @@ typedef struct { */ #define CAM_FUNCDATA_FIXD2(yOffset, data01, data02, data04, data05, fov, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data04, CAM_DATA_04 }, \ @@ -1097,7 +1097,7 @@ typedef struct { */ #define CAM_FUNCDATA_SUBJ1(yOffset, data01, data02, data04, data19, data17, data18, fov, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { data02, CAM_DATA_02 }, \ { data04, CAM_DATA_04 }, \ @@ -1140,7 +1140,7 @@ typedef struct { */ #define CAM_FUNCDATA_UNIQ2(yOffset, data01, fov, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data01, CAM_DATA_01 }, \ { fov, CAM_DATA_FOV }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -1175,7 +1175,7 @@ typedef struct { */ #define CAM_FUNCDATA_UNIQ0(yOffset, data04, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { data04, CAM_DATA_04 }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -1244,8 +1244,8 @@ typedef struct { typedef struct { /* 0x00 */ Vec3f unk_00; - /* 0x0C */ VecSph unk_0C; - /* 0x14 */ VecSph unk_14; + /* 0x0C */ VecGeo unk_0C; + /* 0x14 */ VecGeo unk_14; /* 0x1C */ s16 unk_1C; } Demo1ReadWriteData; // size = 0x20 @@ -1319,7 +1319,7 @@ typedef struct { /* 0x0C */ f32 unk_0C; /* 0x10 */ f32 unk_10; /* 0x14 */ f32 unk_14; - /* 0x18 */ VecSph unk_18; + /* 0x18 */ VecGeo unk_18; /* 0x20 */ s16 unk_20; /* 0x22 */ s16 timer; } Demo4ReadWriteData; // size = 0x24 @@ -1345,7 +1345,7 @@ typedef struct { /* 0x10 */ f32 unk_10; /* 0x14 */ f32 unk_14; /* 0x18 */ f32 unk_18; - /* 0x1C */ VecSph unk_1C; + /* 0x1C */ VecGeo unk_1C; /* 0x24 */ s16 unk_24; /* 0x26 */ s16 timer; } Demo5ReadWriteData; // size = 0x28 @@ -1367,8 +1367,8 @@ typedef struct { typedef struct { /* 0x00 */ f32 unk_00; - /* 0x04 */ VecSph subAtToEye; - /* 0x0C */ VecSph atToEye; + /* 0x04 */ VecGeo subAtToEye; + /* 0x0C */ VecGeo atToEye; /* 0x14 */ s16 unk_14; /* 0x16 */ s16 unk_16; /* 0x18 */ s16 unk_18; @@ -1387,10 +1387,10 @@ typedef struct { */ #define CAM_FUNCDATA_SPEC5(yOffset, eyeDist, minDistForRot, fov, atMaxLERPScale, timerInit, pitch, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { eyeDist, CAM_DATA_01 }, \ { minDistForRot, CAM_DATA_02 }, \ - { fov, CAM_DATA_03 }, \ + { fov, CAM_DATA_PITCH_TARGET }, \ { atMaxLERPScale, CAM_DATA_FOV }, \ { timerInit, CAM_DATA_08 }, \ { pitch, CAM_DATA_12 }, \ @@ -1446,7 +1446,7 @@ typedef struct { */ #define CAM_FUNCDATA_SPEC8(yOffset, eyeStepScale, posStepScale, fov, spiralDoorCsLength, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { eyeStepScale, CAM_DATA_04 }, \ { posStepScale, CAM_DATA_05 }, \ { fov, CAM_DATA_FOV }, \ @@ -1483,7 +1483,7 @@ typedef struct { */ #define CAM_FUNCDATA_SPEC9(yOffset, fov, interfaceFlags) \ - { yOffset, CAM_DATA_00 }, \ + { yOffset, CAM_DATA_Y_OFFSET }, \ { fov, CAM_DATA_FOV }, \ { interfaceFlags, CAM_DATA_INTERFACE_FLAGS } @@ -1565,11 +1565,11 @@ typedef struct Camera { /* 0x0D8 */ f32 xzSpeed; /* 0x0DC */ f32 dist; /* 0x0E0 */ f32 speedRatio; - /* 0x0E4 */ Vec3f atActorOffset; - /* 0x0F0 */ Vec3f focalActorOffset; + /* 0x0E4 */ Vec3f focalActorAtOffset; // Offset between the camera's at Pos and the focalActor's Pos + /* 0x0F0 */ Vec3f unk_0F0; // Offset between the focalActor's Pos and the camera's focalActor's Pos from the previous frame /* 0x0FC */ f32 fov; /* 0x100 */ f32 atLerpStepScale; - /* 0x104 */ f32 playerFloorHeight; + /* 0x104 */ f32 focalActorFloorHeight; /* 0x108 */ Vec3f floorNorm; /* 0x114 */ f32 waterYPos; /* 0x118 */ s32 waterPrevBgCamDataId; @@ -1588,11 +1588,11 @@ typedef struct Camera { /* 0x142 */ s16 setting; /* 0x144 */ s16 mode; /* 0x146 */ s16 bgId; - /* 0x148 */ s16 bgCamDataId; + /* 0x148 */ s16 bgCamIndex; /* 0x14A */ s16 behaviorFlags; /* 0x14C */ s16 stateFlags; /* 0x14E */ s16 childCamId; - /* 0x150 */ s16 doorTimer1; // a door timer used when door cam is indexed from bgCamDataId + /* 0x150 */ s16 doorTimer1; // a door timer used when door cam is indexed from bgCamIndex /* 0x152 */ s16 unk152; /* 0x154 */ s16 prevSetting; /* 0x156 */ s16 nextCamSceneDataId; @@ -1600,8 +1600,8 @@ typedef struct Camera { /* 0x15A */ s16 roll; /* 0x15C */ s16 viewFlags; /* 0x15E */ s16 animState; // Determines the current state of the current camera behavior function - /* 0x160 */ s16 unk160; - /* 0x162 */ s16 doorTimer2; // a door timer used when door cam is indexed from bgCamDataId + /* 0x160 */ s16 timer; // Unused remnant of OoT: originally destoryed subCamera when timer ran out + /* 0x162 */ s16 doorTimer2; // a door timer used when door cam is indexed from bgCamIndex /* 0x164 */ s16 camId; /* 0x166 */ s16 prevBgCamDataId; /* 0x168 */ s16 unk168; diff --git a/include/z64math.h b/include/z64math.h index 0b89ff772..5bf72296f 100644 --- a/include/z64math.h +++ b/include/z64math.h @@ -87,12 +87,32 @@ typedef struct { /* 0x0C */ Vec3f b; } Linef; // size = 0x18 -// Defines a point in the spherical coordinate system typedef struct { - /* 0x0 */ f32 r; // radius - /* 0x4 */ s16 pitch; // polar (zenith) angle - /* 0x6 */ s16 yaw; // azimuthal angle -} VecSph; // size = 0x8 + /* 0x0 */ f32 r; // radius + /* 0x4 */ s16 pitch; // depends on coordinate system. See below. + /* 0x6 */ s16 yaw; // azimuthal angle +} VecSphGeo; // size = 0x8 + +// Defines a point in the spherical coordinate system. +// Pitch is 0 along the positive y-axis (up) +typedef VecSphGeo VecSph; + +// Defines a point in the geographic coordinate system. +// Pitch is 0 along the xz-plane (horizon) +typedef VecSphGeo VecGeo; + +// 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; #define LERPIMP(v0, v1, t) ((v0) + (((v1) - (v0)) * (t))) #define F32_LERP(v0, v1, t) ((1.0f - (t)) * (f32)(v0) + (t) * (f32)(v1)) diff --git a/include/z64player.h b/include/z64player.h index 54894893f..3bcc53fde 100644 --- a/include/z64player.h +++ b/include/z64player.h @@ -677,7 +677,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE1_1 (1 << 0) // #define PLAYER_STATE1_2 (1 << 1) -// +// Climbing ledge #define PLAYER_STATE1_4 (1 << 2) // #define PLAYER_STATE1_8 (1 << 3) @@ -697,7 +697,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE1_400 (1 << 10) // #define PLAYER_STATE1_800 (1 << 11) -// +// charging spin attack #define PLAYER_STATE1_1000 (1 << 12) // #define PLAYER_STATE1_2000 (1 << 13) @@ -731,7 +731,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE1_8000000 (1 << 27) // #define PLAYER_STATE1_10000000 (1 << 28) -// +// Time is stopped but Link & NPC animations continue #define PLAYER_STATE1_20000000 (1 << 29) // #define PLAYER_STATE1_40000000 (1 << 30) @@ -761,7 +761,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE2_200 (1 << 9) // #define PLAYER_STATE2_400 (1 << 10) -// +// Diving #define PLAYER_STATE2_800 (1 << 11) // #define PLAYER_STATE2_1000 (1 << 12) @@ -773,7 +773,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE2_8000 (1 << 15) // #define PLAYER_STATE2_10000 (1 << 16) -// +// A non-magic spin attack #define PLAYER_STATE2_20000 (1 << 17) // #define PLAYER_STATE2_40000 (1 << 18) @@ -821,7 +821,7 @@ typedef enum PlayerCsMode { #define PLAYER_STATE3_40 (1 << 6) // #define PLAYER_STATE3_80 (1 << 7) -// Related to form Deku +// Deku flower dive #define PLAYER_STATE3_100 (1 << 8) // #define PLAYER_STATE3_200 (1 << 9) diff --git a/include/z64quake.h b/include/z64quake.h index f0bd401fc..0150b5404 100644 --- a/include/z64quake.h +++ b/include/z64quake.h @@ -1,68 +1,64 @@ #ifndef Z64QUAKE_H #define Z64QUAKE_H +#include "z64camera.h" #include "z64math.h" struct PlayState; -struct Camera; typedef struct { /* 0x00 */ Vec3f atOffset; /* 0x0C */ Vec3f eyeOffset; - /* 0x18 */ s16 rollOffset; - /* 0x1A */ s16 zoom; - /* 0x1C */ f32 max; // Set to scaled max data of struct (mag for Vec3f), never used -} QuakeCamCalc; // size = 0x20 - -#define QUAKE_SPEED (1 << 0) -#define QUAKE_VERTICAL_MAG (1 << 1) -#define QUAKE_HORIZONTAL_MAG (1 << 2) -#define QUAKE_ZOOM (1 << 3) -#define QUAKE_ROLL_OFFSET (1 << 4) -#define QUAKE_SHAKE_PLANE_OFFSET_X (1 << 5) -#define QUAKE_SHAKE_PLANE_OFFSET_Y (1 << 6) -#define QUAKE_SHAKE_PLANE_OFFSET_Z (1 << 7) -#define QUAKE_COUNTDOWN (1 << 8) -#define QUAKE_IS_SHAKE_PERPENDICULAR (1 << 9) + /* 0x18 */ s16 upRollOffset; + /* 0x1A */ s16 fovOffset; + /* 0x1C */ f32 maxOffset; // Set to scaled max data of struct (mag for Vec3f), never used +} ShakeInfo; // size = 0x20 typedef enum { - /* 1 */ QUAKE_TYPE_1 = 1, - /* 2 */ QUAKE_TYPE_2, - /* 3 */ QUAKE_TYPE_3, - /* 4 */ QUAKE_TYPE_4, - /* 5 */ QUAKE_TYPE_5, - /* 6 */ QUAKE_TYPE_6 + /* 0 */ QUAKE_TYPE_NONE, + /* 1 */ QUAKE_TYPE_1, // Periodic, sustaining, random X perturbations + /* 2 */ QUAKE_TYPE_2, // Aperiodic, sustaining, random X perturbations + /* 3 */ QUAKE_TYPE_3, // Periodic, decaying + /* 4 */ QUAKE_TYPE_4, // Aperiodic, decaying, random X perturbations + /* 5 */ QUAKE_TYPE_5, // Periodic, sustaining + /* 6 */ QUAKE_TYPE_6 // See below } QuakeType; -u32 Quake_SetValue(s16 quakeIndex, s16 valueType, s16 value); -u32 Quake_SetSpeed(s16 quakeIndex, s16 speed); -u32 Quake_SetCountdown(s16 quakeIndex, s16 countdown); -s16 Quake_GetCountdown(s16 quakeIndex); -u32 Quake_SetQuakeValues(s16 quakeIndex, s16 verticalMag, s16 horizontalMag, s16 zoom, s16 rollOffset); -u32 Quake_SetQuakeValues2(s16 quakeIndex, s16 isShakePerpendicular, Vec3s shakePlaneOffset); -s16 Quake_Add(Camera* camera, u32 type); -s16 Quake_Calc(Camera* camera, QuakeCamCalc* camData); -u32 Quake_Remove(s16 index); -s32 Quake_NumActiveQuakes(void); +s16 Quake_Request(Camera* camera, u32 type); + +u32 Quake_SetSpeed(s16 index, s16 speed); +u32 Quake_SetPerturbations(s16 index, s16 y, s16 x, s16 fov, s16 roll); +u32 Quake_SetDuration(s16 index, s16 duration); +u32 Quake_SetOrientation(s16 index, s16 isRelativeToScreen, Vec3s orientation); + +s16 Quake_GetTimeLeft(s16 index); +s32 Quake_GetNumActiveQuakes(void); +u32 Quake_RemoveRequest(s16 index); + void Quake_Init(void); +s16 Quake_Update(Camera* camera, ShakeInfo* camShake); -#define DISTORTION_TYPE_0 (1 << 0) -#define DISTORTION_TYPE_NON_ZORA_SWIMMING (1 << 2) -#define DISTORTION_TYPE_ZORA_SWIMMING (1 << 3) -#define DISTORTION_TYPE_UNDERWATER_ENTRY (1 << 4) -#define DISTORTION_TYPE_5 (1 << 5) -#define DISTORTION_TYPE_6 (1 << 6) -#define DISTORTION_TYPE_7 (1 << 7) -#define DISTORTION_TYPE_8 (1 << 8) -#define DISTORTION_TYPE_9 (1 << 9) -#define DISTORTION_TYPE_A (1 << 10) -#define DISTORTION_TYPE_B (1 << 11) +#define DISTORTION_TYPE_HOT_ROOM (1 << 0) // Hot Room +#define DISTORTION_TYPE_NON_ZORA_SWIMMING (1 << 2) // Non-Zora swimming +#define DISTORTION_TYPE_ZORA_SWIMMING (1 << 3) // Zora swimming, also used for boss warp pad part 1 -void Distortion_SetCountdown(s16 countdown); -s16 Distortion_GetCountdown(void); +#define DISTORTION_TYPE_UNDERWATER_ENTRY (1 << 4) // Entering water, also used for boss warp pad part 2 +#define DISTORTION_TYPE_SONG_OF_TIME (1 << 5) // Song of Time effects +#define DISTORTION_TYPE_ZORA_KICK (1 << 6) // PLAYER_MWA_ZORA_PUNCH_KICK +#define DISTORTION_TYPE_UNK_ATTACK (1 << 7) // Impossible to achieve, inferred to be another `PLAYER_MWA_`, + +#define DISTORTION_TYPE_GORON_BUTT (1 << 8) // PLAYER_MWA_GORON_PUNCH_BUTT +#define DISTORTION_TYPE_MASK_TRANSFORM_1 (1 << 9) // Mask transformation part 1 +#define DISTORTION_TYPE_BOSS_WARP (1 << 10) // Boss warp pad part 3 +#define DISTORTION_TYPE_MASK_TRANSFORM_2 (1 << 11) // Mask transformation part 2 + +void Distortion_Request(s32 type); +void Distortion_SetDuration(s16 duration); + +s16 Distortion_GetTimeLeft(void); s16 Distortion_GetType(void); -void Distortion_SetType(s32 type); -void Distortion_ClearType(s32 type); +void Distortion_RemoveRequest(s32 type); + void Distortion_Init(PlayState* play); void Distortion_Update(void); diff --git a/include/z64save.h b/include/z64save.h index 1f59fea01..9d580803f 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -594,7 +594,7 @@ typedef enum { #define WEEKEVENTREG_08_04 PACK_WEEKEVENTREG_FLAG(8, 0x04) #define WEEKEVENTREG_08_08 PACK_WEEKEVENTREG_FLAG(8, 0x08) #define WEEKEVENTREG_08_10 PACK_WEEKEVENTREG_FLAG(8, 0x10) -#define WEEKEVENTREG_08_20 PACK_WEEKEVENTREG_FLAG(8, 0x20) +#define WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE PACK_WEEKEVENTREG_FLAG(8, 0x20) // Related to final hours #define WEEKEVENTREG_08_40 PACK_WEEKEVENTREG_FLAG(8, 0x40) @@ -857,7 +857,7 @@ typedef enum { #define WEEKEVENTREG_34_02 PACK_WEEKEVENTREG_FLAG(34, 0x02) #define WEEKEVENTREG_34_04 PACK_WEEKEVENTREG_FLAG(34, 0x04) -#define WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED PACK_WEEKEVENTREG_FLAG(34, 0x08) +#define WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN PACK_WEEKEVENTREG_FLAG(34, 0x08) #define WEEKEVENTREG_34_10 PACK_WEEKEVENTREG_FLAG(34, 0x10) #define WEEKEVENTREG_34_20 PACK_WEEKEVENTREG_FLAG(34, 0x20) #define WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH PACK_WEEKEVENTREG_FLAG(34, 0x40) @@ -924,62 +924,11 @@ typedef enum { #define WEEKEVENTREG_41_20 PACK_WEEKEVENTREG_FLAG(41, 0x20) #define WEEKEVENTREG_41_40 PACK_WEEKEVENTREG_FLAG(41, 0x40) #define WEEKEVENTREG_41_80 PACK_WEEKEVENTREG_FLAG(41, 0x80) -#define WEEKEVENTREG_42_01 PACK_WEEKEVENTREG_FLAG(42, 0x01) -#define WEEKEVENTREG_42_02 PACK_WEEKEVENTREG_FLAG(42, 0x02) -#define WEEKEVENTREG_42_04 PACK_WEEKEVENTREG_FLAG(42, 0x04) -#define WEEKEVENTREG_42_08 PACK_WEEKEVENTREG_FLAG(42, 0x08) -#define WEEKEVENTREG_42_10 PACK_WEEKEVENTREG_FLAG(42, 0x10) -#define WEEKEVENTREG_42_20 PACK_WEEKEVENTREG_FLAG(42, 0x20) -#define WEEKEVENTREG_42_40 PACK_WEEKEVENTREG_FLAG(42, 0x40) -#define WEEKEVENTREG_42_80 PACK_WEEKEVENTREG_FLAG(42, 0x80) -#define WEEKEVENTREG_43_01 PACK_WEEKEVENTREG_FLAG(43, 0x01) -#define WEEKEVENTREG_43_02 PACK_WEEKEVENTREG_FLAG(43, 0x02) -#define WEEKEVENTREG_43_04 PACK_WEEKEVENTREG_FLAG(43, 0x04) -#define WEEKEVENTREG_43_08 PACK_WEEKEVENTREG_FLAG(43, 0x08) -#define WEEKEVENTREG_43_10 PACK_WEEKEVENTREG_FLAG(43, 0x10) -#define WEEKEVENTREG_43_20 PACK_WEEKEVENTREG_FLAG(43, 0x20) -#define WEEKEVENTREG_43_40 PACK_WEEKEVENTREG_FLAG(43, 0x40) -#define WEEKEVENTREG_43_80 PACK_WEEKEVENTREG_FLAG(43, 0x80) -#define WEEKEVENTREG_44_01 PACK_WEEKEVENTREG_FLAG(44, 0x01) -#define WEEKEVENTREG_44_02 PACK_WEEKEVENTREG_FLAG(44, 0x02) -#define WEEKEVENTREG_44_04 PACK_WEEKEVENTREG_FLAG(44, 0x04) -#define WEEKEVENTREG_44_08 PACK_WEEKEVENTREG_FLAG(44, 0x08) -#define WEEKEVENTREG_44_10 PACK_WEEKEVENTREG_FLAG(44, 0x10) -#define WEEKEVENTREG_44_20 PACK_WEEKEVENTREG_FLAG(44, 0x20) -#define WEEKEVENTREG_44_40 PACK_WEEKEVENTREG_FLAG(44, 0x40) -#define WEEKEVENTREG_44_80 PACK_WEEKEVENTREG_FLAG(44, 0x80) -#define WEEKEVENTREG_45_01 PACK_WEEKEVENTREG_FLAG(45, 0x01) -#define WEEKEVENTREG_45_02 PACK_WEEKEVENTREG_FLAG(45, 0x02) -#define WEEKEVENTREG_45_04 PACK_WEEKEVENTREG_FLAG(45, 0x04) -#define WEEKEVENTREG_45_08 PACK_WEEKEVENTREG_FLAG(45, 0x08) -#define WEEKEVENTREG_45_10 PACK_WEEKEVENTREG_FLAG(45, 0x10) -#define WEEKEVENTREG_45_20 PACK_WEEKEVENTREG_FLAG(45, 0x20) -#define WEEKEVENTREG_45_40 PACK_WEEKEVENTREG_FLAG(45, 0x40) -#define WEEKEVENTREG_45_80 PACK_WEEKEVENTREG_FLAG(45, 0x80) -#define WEEKEVENTREG_46_01 PACK_WEEKEVENTREG_FLAG(46, 0x01) -#define WEEKEVENTREG_46_02 PACK_WEEKEVENTREG_FLAG(46, 0x02) -#define WEEKEVENTREG_46_04 PACK_WEEKEVENTREG_FLAG(46, 0x04) -#define WEEKEVENTREG_46_08 PACK_WEEKEVENTREG_FLAG(46, 0x08) -#define WEEKEVENTREG_46_10 PACK_WEEKEVENTREG_FLAG(46, 0x10) -#define WEEKEVENTREG_46_20 PACK_WEEKEVENTREG_FLAG(46, 0x20) -#define WEEKEVENTREG_46_40 PACK_WEEKEVENTREG_FLAG(46, 0x40) -#define WEEKEVENTREG_46_80 PACK_WEEKEVENTREG_FLAG(46, 0x80) -#define WEEKEVENTREG_47_01 PACK_WEEKEVENTREG_FLAG(47, 0x01) -#define WEEKEVENTREG_47_02 PACK_WEEKEVENTREG_FLAG(47, 0x02) -#define WEEKEVENTREG_47_04 PACK_WEEKEVENTREG_FLAG(47, 0x04) -#define WEEKEVENTREG_47_08 PACK_WEEKEVENTREG_FLAG(47, 0x08) -#define WEEKEVENTREG_47_10 PACK_WEEKEVENTREG_FLAG(47, 0x10) -#define WEEKEVENTREG_47_20 PACK_WEEKEVENTREG_FLAG(47, 0x20) -#define WEEKEVENTREG_47_40 PACK_WEEKEVENTREG_FLAG(47, 0x40) -#define WEEKEVENTREG_47_80 PACK_WEEKEVENTREG_FLAG(47, 0x80) -#define WEEKEVENTREG_48_01 PACK_WEEKEVENTREG_FLAG(48, 0x01) -#define WEEKEVENTREG_48_02 PACK_WEEKEVENTREG_FLAG(48, 0x02) -#define WEEKEVENTREG_48_04 PACK_WEEKEVENTREG_FLAG(48, 0x04) -#define WEEKEVENTREG_48_08 PACK_WEEKEVENTREG_FLAG(48, 0x08) -#define WEEKEVENTREG_48_10 PACK_WEEKEVENTREG_FLAG(48, 0x10) -#define WEEKEVENTREG_48_20 PACK_WEEKEVENTREG_FLAG(48, 0x20) -#define WEEKEVENTREG_48_40 PACK_WEEKEVENTREG_FLAG(48, 0x40) -#define WEEKEVENTREG_48_80 PACK_WEEKEVENTREG_FLAG(48, 0x80) + +// Used for storing the text ID offsets for the dogs in the Doggy Racetrack (56 entries) +// The number of weekEventRegs used needs to be kept in sync with RACEDOG_COUNT in z_en_aob_01.h +// PACK_WEEKEVENTREG_FLAG(42, 0x01) to PACK_WEEKEVENTREG_FLAG(48, 0x80) + #define WEEKEVENTREG_49_01 PACK_WEEKEVENTREG_FLAG(49, 0x01) #define WEEKEVENTREG_49_02 PACK_WEEKEVENTREG_FLAG(49, 0x02) #define WEEKEVENTREG_49_04 PACK_WEEKEVENTREG_FLAG(49, 0x04) @@ -1013,10 +962,7 @@ typedef enum { #define WEEKEVENTREG_52_04 PACK_WEEKEVENTREG_FLAG(52, 0x04) #define WEEKEVENTREG_52_08 PACK_WEEKEVENTREG_FLAG(52, 0x08) #define WEEKEVENTREG_52_10 PACK_WEEKEVENTREG_FLAG(52, 0x10) - -// cleared Stone Tower Temple #define WEEKEVENTREG_CLEARED_STONE_TOWER_TEMPLE PACK_WEEKEVENTREG_FLAG(52, 0x20) - #define WEEKEVENTREG_52_40 PACK_WEEKEVENTREG_FLAG(52, 0x40) #define WEEKEVENTREG_52_80 PACK_WEEKEVENTREG_FLAG(52, 0x80) #define WEEKEVENTREG_53_01 PACK_WEEKEVENTREG_FLAG(53, 0x01) @@ -1130,12 +1076,12 @@ typedef enum { #define WEEKEVENTREG_64_10 PACK_WEEKEVENTREG_FLAG(64, 0x10) #define WEEKEVENTREG_64_20 PACK_WEEKEVENTREG_FLAG(64, 0x20) #define WEEKEVENTREG_64_40 PACK_WEEKEVENTREG_FLAG(64, 0x40) -#define WEEKEVENTREG_64_80 PACK_WEEKEVENTREG_FLAG(64, 0x80) -#define WEEKEVENTREG_65_01 PACK_WEEKEVENTREG_FLAG(65, 0x01) -#define WEEKEVENTREG_65_02 PACK_WEEKEVENTREG_FLAG(65, 0x02) -#define WEEKEVENTREG_65_04 PACK_WEEKEVENTREG_FLAG(65, 0x04) -#define WEEKEVENTREG_65_08 PACK_WEEKEVENTREG_FLAG(65, 0x08) -#define WEEKEVENTREG_65_10 PACK_WEEKEVENTREG_FLAG(65, 0x10) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_1 PACK_WEEKEVENTREG_FLAG(64, 0x80) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_1 PACK_WEEKEVENTREG_FLAG(65, 0x01) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_2 PACK_WEEKEVENTREG_FLAG(65, 0x02) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_2 PACK_WEEKEVENTREG_FLAG(65, 0x04) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_3 PACK_WEEKEVENTREG_FLAG(65, 0x08) +#define WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_3 PACK_WEEKEVENTREG_FLAG(65, 0x10) #define WEEKEVENTREG_65_20 PACK_WEEKEVENTREG_FLAG(65, 0x20) #define WEEKEVENTREG_65_40 PACK_WEEKEVENTREG_FLAG(65, 0x40) #define WEEKEVENTREG_65_80 PACK_WEEKEVENTREG_FLAG(65, 0x80) @@ -1385,10 +1331,8 @@ typedef enum { #define WEEKEVENTREG_91_40 PACK_WEEKEVENTREG_FLAG(91, 0x40) #define WEEKEVENTREG_91_80 PACK_WEEKEVENTREG_FLAG(91, 0x80) -// RACE_FLAGS -//#define WEEKEVENTREG_92_01 PACK_WEEKEVENTREG_FLAG(92, 0x01) -//#define WEEKEVENTREG_92_02 PACK_WEEKEVENTREG_FLAG(92, 0x02) -//#define WEEKEVENTREG_92_04 PACK_WEEKEVENTREG_FLAG(92, 0x04) +// HORSE_RACE_STATE (3 entries) +// WEEKEVENTREG_92_01 to WEEKEVENTREG_92_04 #define WEEKEVENTREG_92_08 PACK_WEEKEVENTREG_FLAG(92, 0x08) #define WEEKEVENTREG_92_10 PACK_WEEKEVENTREG_FLAG(92, 0x10) @@ -1460,34 +1404,52 @@ typedef enum { #define SET_WEEKEVENTREG(flag) (WEEKEVENTREG((flag) >> 8) = GET_WEEKEVENTREG((flag) >> 8) | ((flag) & 0xFF)) #define CLEAR_WEEKEVENTREG(flag) (WEEKEVENTREG((flag) >> 8) = GET_WEEKEVENTREG((flag) >> 8) & (u8)~((flag) & 0xFF)) -#define WEEKEVENTREG_RACE_FLAG_END 0 -#define WEEKEVENTREG_RACE_FLAG_START 1 -#define WEEKEVENTREG_RACE_FLAG_2 2 -#define WEEKEVENTREG_RACE_FLAG_3 3 -#define WEEKEVENTREG_RACE_FLAG_4 4 -#define WEEKEVENTREG_RACE_FLAGS 7 +typedef enum { + /* 0 */ WEEKEVENTREG_HORSE_RACE_STATE_END, + /* 1 */ WEEKEVENTREG_HORSE_RACE_STATE_START, + /* 2 */ WEEKEVENTREG_HORSE_RACE_STATE_2, + /* 3 */ WEEKEVENTREG_HORSE_RACE_STATE_3, + /* 4 */ WEEKEVENTREG_HORSE_RACE_STATE_4, + /* 7 */ WEEKEVENTREG_HORSE_RACE_STATE_MAX = 7 +} WeekEventRegHorseRaceState; -#define GET_WEEKEVENTREG_RACE_FLAGS (WEEKEVENTREG(92) & WEEKEVENTREG_RACE_FLAGS) +#define GET_WEEKEVENTREG_HORSE_RACE_STATE (WEEKEVENTREG(92) & WEEKEVENTREG_HORSE_RACE_STATE_MAX) -#define SET_WEEKEVENTREG_RACE_FLAGS(flag) \ - { \ - WEEKEVENTREG(92) &= (u8)~WEEKEVENTREG_RACE_FLAGS; \ - WEEKEVENTREG(92) = WEEKEVENTREG(92) | (u8)((WEEKEVENTREG(92) & ~WEEKEVENTREG_RACE_FLAGS) | (flag)); \ - } \ +#define SET_WEEKEVENTREG_HORSE_RACE_STATE(state) \ + { \ + WEEKEVENTREG(92) &= (u8)~WEEKEVENTREG_HORSE_RACE_STATE_MAX; \ + WEEKEVENTREG(92) = WEEKEVENTREG(92) | (u8)((WEEKEVENTREG(92) & ~WEEKEVENTREG_HORSE_RACE_STATE_MAX) | (state)); \ + } \ (void)0 +#define GET_WEEKEVENTREG_DOG_RACE_TEXT(index, baseTextId) \ + (index % 2) ? (baseTextId + (((WEEKEVENTREG(42 + (index / 2))) & 0xF0) >> 4)) \ + : (baseTextId + ((WEEKEVENTREG(42 + (index / 2))) & 0x0F)); + +#define SET_WEEKEVENTREG_DOG_RACE_TEXT_OFFSETS(index, packedOffsets) \ + { \ + WEEKEVENTREG(42 + index) = ((void)0, WEEKEVENTREG(42 + index)) | packedOffsets; \ + } + +#define CLEAR_WEEKEVENTREG_DOG_RACE_TEXT_OFFSETS(index) \ + { \ + WEEKEVENTREG(42 + index) = 0; \ + } + /** * gSaveContext.eventInf */ -#define EVENTINF_00 0x00 -#define EVENTINF_01 0x01 -#define EVENTINF_02 0x02 -#define EVENTINF_03 0x03 -#define EVENTINF_04 0x04 -#define EVENTINF_05 0x05 -#define EVENTINF_06 0x06 -#define EVENTINF_07 0x07 +// gSaveContext.eventInf[0] is used to dog race information +// #define EVENTINF_00 0x00 +// #define EVENTINF_01 0x01 +// #define EVENTINF_02 0x02 +// #define EVENTINF_03 0x03 +// #define EVENTINF_04 0x04 +// #define EVENTINF_05 0x05 +// #define EVENTINF_06 0x06 +// #define EVENTINF_07 0x07 + #define EVENTINF_10 0x10 #define EVENTINF_11 0x11 #define EVENTINF_12 0x12 @@ -1561,6 +1523,25 @@ typedef enum { #define CLEAR_EVENTINF(flag) (gSaveContext.eventInf[(flag) >> 4] &= (u8)~(1 << ((flag) & 0xF))) #define CLEAR_EVENTINF_ALT(flag) (gSaveContext.eventInf[(flag) >> 4] &= ~(1 << ((flag) & 0xF))) +typedef enum { + /* 0 */ EVENTINF_DOG_RACE_STATE_NOT_STARTED, + /* 2 */ EVENTINF_DOG_RACE_STATE_STARTED = 2, + /* 3 */ EVENTINF_DOG_RACE_STATE_ENDED, + /* 7 */ EVENTINF_DOG_RACE_STATE_MAX = 7 +} EventInfDogRaceState; + +#define GET_EVENTINF_DOG_RACE_STATE (gSaveContext.eventInf[0] & EVENTINF_DOG_RACE_STATE_MAX) +#define SET_EVENTINF_DOG_RACE_STATE(state) \ + (gSaveContext.eventInf[0] = ((gSaveContext.eventInf[0] & (u8)~EVENTINF_DOG_RACE_STATE_MAX) | (state))) + +#define GET_EVENTINF_DOG_RACE_SELECTED_DOG_INDEX ((gSaveContext.eventInf[0] & (u8)~EVENTINF_DOG_RACE_STATE_MAX) >> 3) +#define SET_EVENTINF_DOG_RACE_SELECTED_DOG_INDEX(selectedDogIndex) \ + (gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & EVENTINF_DOG_RACE_STATE_MAX) | (selectedDogIndex << 3)) + +// This is exactly the same as the selected dog index; they never need both of them at the same time. +#define GET_EVENTINF_DOG_RACE_RACE_STANDING ((gSaveContext.eventInf[0] & (u8)~EVENTINF_DOG_RACE_STATE_MAX) >> 3) +#define SET_EVENTINF_DOG_RACE_RACE_STANDING(raceStanding) \ + (gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & EVENTINF_DOG_RACE_STATE_MAX) | (raceStanding << 3)) typedef enum { /* 0 */ DUNGEON_INDEX_WOODFALL_TEMPLE, diff --git a/include/z64transition.h b/include/z64transition.h index 741f344d7..e223d9b58 100644 --- a/include/z64transition.h +++ b/include/z64transition.h @@ -2,6 +2,7 @@ #define Z64TRANSITION_H #include "ultra64.h" +#include "libc/stdint.h" #include "overlays/fbdemos/ovl_fbdemo_triforce/z_fbdemo_triforce.h" #include "overlays/fbdemos/ovl_fbdemo_wipe1/z_fbdemo_wipe1.h" #include "overlays/fbdemos/ovl_fbdemo_wipe3/z_fbdemo_wipe3.h" @@ -164,31 +165,34 @@ typedef enum { /* 86 */ TRANS_TYPE_86 = 86 } TransitionType; -typedef enum { - /* 0 */ FBDEMO_FADE, - /* 1 */ FBDEMO_TRIFORCE, - /* 2 */ FBDEMO_WIPE1, - /* 3 */ FBDEMO_WIPE3, - /* 4 */ FBDEMO_WIPE4, - /* 5 */ FBDEMO_CIRCLE, - /* 6 */ FBDEMO_WIPE5 +#define DEFINE_TRANSITION(enumValue, _structName, _instanceName, _name) enumValue, +#define DEFINE_TRANSITION_INTERNAL(enumValue, _structName, _instanceName) enumValue, + +typedef enum FbDemoType { + #include "tables/transition_table.h" + /* 7 */ FBDEMO_MAX } FbDemoType; +#undef DEFINE_TRANSITION +#undef DEFINE_TRANSITION_INTERNAL + #define TRANS_NEXT_TYPE_DEFAULT 0xFF +#define DEFINE_TRANSITION(_enumValue, structName, instanceName, _name) structName instanceName; +#define DEFINE_TRANSITION_INTERNAL(_enumValue, structName, instanceName) structName instanceName; + +typedef union TransitionInstance { + #include "tables/transition_table.h" +} TransitionInstance; // size = 0x218 + +#undef DEFINE_TRANSITION +#undef DEFINE_TRANSITION_INTERNAL + typedef struct { /* 0x000 */ s16 transitionType; /* 0x002 */ s8 fbdemoType; /* 0x003 */ char unk_003[0x5]; - /* 0x008 */ union { - TransitionFade fade; - TransitionCircle circle; - TransitionTriforce triforce; - TransitionWipe1 wipe1; - TransitionWipe3 wipe3; - TransitionWipe4 wipe4; - TransitionWipe5 wipe5; - } instanceData; + /* 0x008 */ TransitionInstance instanceData; /* 0x220 */ char unk_220[0x10]; /* 0x230 */ void* (*init)(void* transition); /* 0x234 */ void (*destroy)(void* transition); diff --git a/spec b/spec index 481fd099d..57fca6cda 100644 --- a/spec +++ b/spec @@ -2962,11 +2962,7 @@ beginseg name "ovl_En_Tru" compress include "build/src/overlays/actors/ovl_En_Tru/z_en_tru.o" - #ifdef NON_MATCHING - include "build/src/overlays/actors/ovl_En_Tru/ovl_En_Tru_reloc.o" - #else - include "build/data/ovl_En_Tru/ovl_En_Tru.reloc.o" - #endif + include "build/src/overlays/actors/ovl_En_Tru/ovl_En_Tru_reloc.o" endseg beginseg @@ -4888,8 +4884,7 @@ beginseg name "ovl_En_And" compress include "build/src/overlays/actors/ovl_En_And/z_en_and.o" - include "build/data/ovl_En_And/ovl_En_And.data.o" - include "build/data/ovl_En_And/ovl_En_And.reloc.o" + include "build/src/overlays/actors/ovl_En_And/ovl_En_And_reloc.o" endseg beginseg diff --git a/src/boot_O2_g3/boot_main.c b/src/boot_O2_g3/boot_main.c index 6a561992b..7b8d7126b 100644 --- a/src/boot_O2_g3/boot_main.c +++ b/src/boot_O2_g3/boot_main.c @@ -1,4 +1,3 @@ -#include "prevent_bss_reordering.h" #include "global.h" #include "stack.h" #include "stackcheck.h" diff --git a/src/boot_O2_g3/z_std_dma.c b/src/boot_O2_g3/z_std_dma.c index bbf8e4bed..00d894f74 100644 --- a/src/boot_O2_g3/z_std_dma.c +++ b/src/boot_O2_g3/z_std_dma.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "stack.h" #include "stackcheck.h" diff --git a/src/code/cutscene_camera.c b/src/code/cutscene_camera.c index d5f028b94..d92d119dd 100644 --- a/src/code/cutscene_camera.c +++ b/src/code/cutscene_camera.c @@ -119,23 +119,23 @@ u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { switch (csCamera->atCmd[csCamera->eyeInterp.curPoint].relativeTo) { case CS_CAM_REL_2: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 2); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF); break; case CS_CAM_REL_3: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_1: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_4: - OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, 1); + OLib_Vec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_5: - OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, 2); + OLib_Vec3fDiff(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_DIFF); break; default: // CS_CAM_REL_0 @@ -147,24 +147,24 @@ u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { switch (csCamera->atCmd[csCamera->eyeInterp.curPoint].relativeTo) { case CS_CAM_REL_2: - OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 2); + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD); break; case CS_CAM_REL_3: - OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + 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_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, 1); + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD_OFFSET); break; case CS_CAM_REL_4: - OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->at, &csCamera->camera->at, 1); + OLib_Vec3fAdd(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD_OFFSET); break; case CS_CAM_REL_5: - OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->at, &csCamera->camera->at, 2); + OLib_Vec3fAdd(&target->world, &csCamera->camera->at, &csCamera->camera->at, OLIB_ADD); break; default: // CS_CAM_REL_0 @@ -189,23 +189,23 @@ u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { switch (csCamera->eyeCmd[csCamera->atInterp.curPoint].relativeTo) { case CS_CAM_REL_2: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF); break; case CS_CAM_REL_3: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_1: - OLib_DbCameraVec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + OLib_Vec3fDiff(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_4: - OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + OLib_Vec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF_OFFSET); break; case CS_CAM_REL_5: - OLib_DbCameraVec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + OLib_Vec3fDiff(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_DIFF); break; default: // CS_CAM_REL_0 @@ -217,24 +217,24 @@ u8 CutsceneCamera_ProcessSpline(CutsceneCamera* csCamera) { switch (csCamera->eyeCmd[csCamera->atInterp.curPoint].relativeTo) { case CS_CAM_REL_2: - OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD); break; case CS_CAM_REL_3: - OLib_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + 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_DbCameraVec3fSum(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + OLib_Vec3fAdd(&player->actor.world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD_OFFSET); break; case CS_CAM_REL_4: - OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 1); + OLib_Vec3fAdd(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD_OFFSET); break; case CS_CAM_REL_5: - OLib_DbCameraVec3fSum(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, 2); + OLib_Vec3fAdd(&target->world, &csCamera->camera->eye, &csCamera->camera->eye, OLIB_ADD); break; default: // CS_CAM_REL_0 diff --git a/src/code/sched.c b/src/code/sched.c index 98b005ba1..c2630677c 100644 --- a/src/code/sched.c +++ b/src/code/sched.c @@ -1,3 +1,4 @@ +#include "prevent_bss_reordering.h" #include "global.h" #include "stackcheck.h" diff --git a/src/code/z_actor.c b/src/code/z_actor.c index cfe29f893..a719bd9d6 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -908,41 +908,38 @@ s32 func_800B6434(PlayState* play, TitleCardContext* titleCtx) { return true; } -// ActorContext_1F4 Init -void func_800B6468(PlayState* play) { - play->actorCtx.unk_1F4.timer = 0; +void Actor_InitPlayerImpact(PlayState* play) { + play->actorCtx.playerImpact.timer = 0; } -// ActorContext_1F4 Update -void func_800B6474(PlayState* play) { - DECR(play->actorCtx.unk_1F4.timer); +void Actor_UpdatePlayerImpact(PlayState* play) { + DECR(play->actorCtx.playerImpact.timer); } -// ActorContext_1F4 setter something -s32 func_800B648C(PlayState* play, s32 arg1, s32 timer, f32 arg3, Vec3f* arg4) { - if ((play->actorCtx.unk_1F4.timer != 0) && (arg3 < play->actorCtx.unk_1F4.unk_04)) { +s32 Actor_SetPlayerImpact(PlayState* play, PlayerImpactType type, s32 timer, f32 dist, Vec3f* pos) { + if ((play->actorCtx.playerImpact.timer != 0) && (dist < play->actorCtx.playerImpact.dist)) { return false; } - play->actorCtx.unk_1F4.unk_00 = arg1; - play->actorCtx.unk_1F4.timer = timer; - play->actorCtx.unk_1F4.unk_04 = arg3; - Math_Vec3f_Copy(&play->actorCtx.unk_1F4.unk_08, arg4); + play->actorCtx.playerImpact.type = type; + play->actorCtx.playerImpact.timer = timer; + play->actorCtx.playerImpact.dist = dist; + Math_Vec3f_Copy(&play->actorCtx.playerImpact.pos, pos); return true; } -// ActorContext_1F4 getter something -f32 func_800B64FC(PlayState* play, f32 arg1, Vec3f* arg2, u32* arg3) { - f32 temp_f8; +f32 Actor_GetPlayerImpact(PlayState* play, f32 range, Vec3f* pos, PlayerImpactType* type) { + f32 dist; - if ((play->actorCtx.unk_1F4.timer == 0) || (arg1 == 0.0f)) { + if ((play->actorCtx.playerImpact.timer == 0) || (range == 0.0f)) { return -1.0f; } - temp_f8 = Math_Vec3f_DistXYZ(&play->actorCtx.unk_1F4.unk_08, arg2) / arg1; - *arg3 = play->actorCtx.unk_1F4.unk_00; - return play->actorCtx.unk_1F4.unk_04 - temp_f8; + dist = Math_Vec3f_DistXYZ(&play->actorCtx.playerImpact.pos, pos) / range; + *type = play->actorCtx.playerImpact.type; + + return play->actorCtx.playerImpact.dist - dist; } /** @@ -2303,7 +2300,7 @@ void Actor_InitContext(PlayState* play, ActorContext* actorCtx, ActorEntry* acto actorCtx->sceneFlags.clearedRoom = cycleFlags->clearedRoom; TitleCard_ContextInit(&play->state, &actorCtx->titleCtxt); - func_800B6468(play); + Actor_InitPlayerImpact(play); actorCtx->absoluteSpace = NULL; @@ -2559,7 +2556,7 @@ void Actor_UpdateAll(PlayState* play, ActorContext* actorCtx) { } TitleCard_Update(&play->state, &actorCtx->titleCtxt); - func_800B6474(play); + Actor_UpdatePlayerImpact(play); DynaPoly_UpdateBgActorTransforms(play, &play->colCtx.dyna); } @@ -2577,7 +2574,7 @@ void Actor_Draw(PlayState* play, Actor* actor) { (actor->flags & (ACTOR_FLAG_10000000 | ACTOR_FLAG_400000)) ? NULL : &actor->world.pos, play); Lights_Draw(light, play->state.gfxCtx); - if (actor->flags & ACTOR_FLAG_1000) { + if (actor->flags & ACTOR_FLAG_IGNORE_QUAKE) { Matrix_SetTranslateRotateYXZ(actor->world.pos.x + play->mainCamera.quakeOffset.x, actor->world.pos.y + ((actor->shape.yOffset * actor->scale.y) + play->mainCamera.quakeOffset.y), @@ -2656,11 +2653,11 @@ void func_800B9D1C(Actor* actor) { if (sfxId) {} if (actor->audioFlags & 0x40) { - func_801A1FB4(3, &actor->projectedPos, NA_BGM_MUSIC_BOX_HOUSE, 1500.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &actor->projectedPos, NA_BGM_MUSIC_BOX_HOUSE, 1500.0f); } if (actor->audioFlags & 0x20) { - func_801A1FB4(0, &actor->projectedPos, NA_BGM_KAMARO_DANCE, 900.0f); + func_801A1FB4(SEQ_PLAYER_BGM_MAIN, &actor->projectedPos, NA_BGM_KAMARO_DANCE, 900.0f); } } @@ -3794,30 +3791,29 @@ void func_800BC620(Vec3f* pos, Vec3f* scale, u8 alpha, PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); } -void Actor_AddQuake(PlayState* play, s16 verticalMag, s16 countdown) { - s16 quakeIndex = Quake_Add(&play->mainCamera, QUAKE_TYPE_3); +void Actor_RequestQuake(PlayState* play, s16 y, s16 duration) { + s16 quakeIndex = Quake_Request(&play->mainCamera, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, verticalMag, 0, 0, 0); - Quake_SetCountdown(quakeIndex, countdown); + Quake_SetPerturbations(quakeIndex, y, 0, 0, 0); + Quake_SetDuration(quakeIndex, duration); } -void Actor_AddQuakeWithSpeed(PlayState* play, s16 verticalMag, s16 countdown, s16 speed) { - s16 quakeIndex = Quake_Add(&play->mainCamera, QUAKE_TYPE_3); +void Actor_RequestQuakeWithSpeed(PlayState* play, s16 y, s16 duration, s16 speed) { + s16 quakeIndex = Quake_Request(&play->mainCamera, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, speed); - Quake_SetQuakeValues(quakeIndex, verticalMag, 0, 0, 0); - Quake_SetCountdown(quakeIndex, countdown); + Quake_SetPerturbations(quakeIndex, y, 0, 0, 0); + Quake_SetDuration(quakeIndex, duration); } -// Actor_RequestRumble? -void func_800BC848(Actor* actor, PlayState* play, s16 y, s16 countdown) { - if (y >= 5) { +void Actor_RequestQuakeAndRumble(Actor* actor, PlayState* play, s16 quakeY, s16 quakeDuration) { + if (quakeY >= 5) { Rumble_Request(actor->xyzDistToPlayerSq, 255, 20, 150); } else { Rumble_Request(actor->xyzDistToPlayerSq, 180, 20, 100); } - Actor_AddQuake(play, y, countdown); + Actor_RequestQuake(play, quakeY, quakeDuration); } typedef struct { diff --git a/src/code/z_camera.c b/src/code/z_camera.c index f54fc93da..ea600b30e 100644 --- a/src/code/z_camera.c +++ b/src/code/z_camera.c @@ -1,22 +1,96 @@ +/** + * @file camera.c + * Implements the camera system. Camera functionality depends on the current combination of + * setting and mode. + * + * When working with the camera, you should be familiar with MM's coordinate system. + * Relative to the camera, the coordinate system follows the right hand rule: + * +X points right. + * +Y points up. + * +Z points out of the screen. + * + * You should also be familiar with Euler angles: 'pitch', 'yaw', and 'roll'. + * pitch: rotation about the X-axis, measured from +Y. + * Unlike yaw and roll, pitch is bounded in +-0x4000 (90 degrees). + * Pitch is 0 when the camera points parallel to the xz-plane (+Y points straight up). + * + * yaw: rotation about the Y-axis, measured from (absolute) +Z. + * Positive yaw rotates clockwise, towards +X. + * + * roll: rotation about the Z-axis, measured from the camera's right direction. + * Unfortunately, it's weird: For some reason, roll is flipped. Positive roll makes the camera + * rotate counterclockwise, which means the WORLD rotates clockwise. Luckily roll is rarely + * used. + * + * Remember the right hand rule: make a thumbs-up with your right hand, stick your thumb in the + * +direction (except for roll), and the angle follows the rotation of your curled fingers. + * + * Illustrations: + * Following the right hand rule, each hidden axis's positive direction points out of the screen. + * + * YZ-Plane (pitch) XZ-Plane (yaw) XY-Plane (roll -- Note flipped) + * +Y -Z +Y + * ^ ^ (into the ^ + * --|-- | screen) |<- + * +pitch / | \ -pitch | | \ -roll + * v | v | | | + * +Z <------O------> -Z -X <------O------> +X -X <------O------> +X + * | ^ | ^ | | + * | \ | / | / +roll + * | -yaw --|-- +yaw |<- + * v v v + * -Y +Z -Y + * + */ #include "global.h" #include "z64quake.h" #include "z64shrink_window.h" #include "z64view.h" +#include "overlays/actors/ovl_En_Horse/z_en_horse.h" + +void func_800DDFE0(Camera* camera); +s32 Camera_ChangeMode(Camera* camera, s16 mode); +s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags); +s16 Camera_UnsetStateFlag(Camera* camera, s16 flags); #include "z_camera_data.inc.c" -// BSS -s16 D_801EDBF0; -f32 D_801EDBF4; -f32 D_801EDBF8; -CameraCollision D_801EDC00; - PlayState* sCamPlayState; SwingAnimation D_801EDC30[4]; Vec3f D_801EDDD0; Vec3f D_801EDDE0; Vec3f D_801EDDF0; +// Camera will reload its paramData. Usually that means setting the read-only data from what is stored in +// CameraModeValue arrays. Although sometimes some read-write data is reset as well +#define RELOAD_PARAMS(camera) ((camera->animState == 0) || (camera->animState == 10) || (camera->animState == 20)) + +/** + * 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 + * original value. This is then scaled back down during runtime with the CAM_RODATA_UNSCALE macro. + */ +#define CAM_RODATA_SCALE(x) ((x)*100.0f) +#define CAM_RODATA_UNSCALE(x) ((x)*0.01f) + +// Load the next value from camera read-only data stored in CameraModeValue +#define GET_NEXT_RO_DATA(values) ((values++)->val) +// Load the next value and scale down from camera read-only data stored in CameraModeValue +#define GET_NEXT_SCALED_RO_DATA(values) CAM_RODATA_UNSCALE(GET_NEXT_RO_DATA(values)) + +// Camera bg surface flags +#define FLG_ADJSLOPE (1 << 0) +#define FLG_OFFGROUND (1 << 7) + +#define CAM_CHANGE_SETTING_0 (1 << 0) +#define CAM_CHANGE_SETTING_1 (1 << 1) +#define CAM_CHANGE_SETTING_2 (1 << 2) +#define CAM_CHANGE_SETTING_3 (1 << 3) + +/*===============================================================*/ +/* Camera Internal Functions */ +/*===============================================================*/ + /** * Returns the absolute value for floats */ @@ -81,47 +155,63 @@ f32 Camera_QuadraticAttenuation(f32 xRange, f32 x) { return y; } -/* - * Performs linear interpoloation between `cur` and `target`. If `cur` is within - * `minDiff` units, the result is rounded up to `target` +/** + * @param[in] target target value + * @param[in] cur current value + * @param[in] stepScale fraction of (target - cur) to step towards target + * @param[in] minDiff minimum value of (target - cur) perform a step. Otherwise, return `target` + * + * @return new current value */ -f32 Camera_LerpCeilF(f32 target, f32 cur, f32 stepScale, f32 minDiff) { +f32 Camera_ScaledStepToCeilF(f32 target, f32 cur, f32 stepScale, f32 minDiff) { f32 diff = target - cur; f32 step = diff * stepScale; return (Camera_fabsf(diff) >= minDiff) ? cur + step : target; } -/* - * Performs linear interpoloation between `cur` and `target`. If `cur` is within - * `minDiff` units, the result is rounded up to `target` +/** + * @param[in] target target value + * @param[in] cur current value + * @param[in] stepScale fraction of (target - cur) to step towards target + * @param[in] minDiff minimum value of (target - cur) perform a step. Otherwise, return `target` + * + * @return new current value */ -s16 Camera_LerpCeilS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { +s16 Camera_ScaledStepToCeilS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { s16 diff = target - cur; s16 step = diff * stepScale + 0.5f; return (ABS(diff) >= minDiff) ? cur + step : target; } -/* - * Performs linear interpoloation between `cur` and `target`. If `cur` is within - * `minDiff` units, the result is rounded down to `cur` +/** + * @param[in] target target value + * @param[in] cur current value + * @param[in] stepScale fraction of (target - cur) to step towards target + * @param[in] minDiff minimum value of (target - cur) perform a step. Otherwise, return `current` + * + * @return new current value */ -s16 Camera_LerpFloorS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { +s16 Camera_ScaledStepToFloorS(s16 target, s16 cur, f32 stepScale, s16 minDiff) { s16 diff = target - cur; s16 step = diff * stepScale + 0.5f; return (ABS(diff) >= minDiff) ? cur + step : cur; } -/* - * Performs linear interpoloation between `cur` and `target`. If `cur` is within - * `minDiff` units, the result is rounded up to `target`. Output is written to `cur` +/** + * @param[in] target target value + * @param[in] cur current value + * @param[in] stepScale fraction of (target - cur) to step towards target + * @param[in] minDiff minimum value of (target - cur) perform a step. Otherwise, return `target` + * + * @return new current value */ -void Camera_LerpCeilVec3f(Vec3f* target, Vec3f* cur, f32 xzStepScale, f32 yStepScale, f32 minDiff) { - cur->x = Camera_LerpCeilF(target->x, cur->x, xzStepScale, minDiff); - cur->y = Camera_LerpCeilF(target->y, cur->y, yStepScale, minDiff); - cur->z = Camera_LerpCeilF(target->z, cur->z, xzStepScale, minDiff); +void Camera_ScaledStepToCeilVec3f(Vec3f* target, Vec3f* cur, f32 xzStepScale, f32 yStepScale, f32 minDiff) { + cur->x = Camera_ScaledStepToCeilF(target->x, cur->x, xzStepScale, minDiff); + cur->y = Camera_ScaledStepToCeilF(target->y, cur->y, yStepScale, minDiff); + cur->z = Camera_ScaledStepToCeilF(target->z, cur->z, xzStepScale, minDiff); } void Camera_SetUpdateRatesFastPitch(Camera* camera) { @@ -149,14 +239,11 @@ void Camera_SetUpdateRatesSlow(Camera* camera) { camera->rUpdateRateInv = 1800.0f; camera->yawUpdateRateInv = 1800.0f; camera->pitchUpdateRateInv = 1800.0f; - camera->yOffsetUpdateRate = 0.01; - camera->xzOffsetUpdateRate = 0.01; - camera->fovUpdateRate = 0.01; + camera->yOffsetUpdateRate = 0.01f; + camera->xzOffsetUpdateRate = 0.01f; + camera->fovUpdateRate = 0.01f; } -/** - * Converts a 3D s16 vector into a 3D f32 vector - */ Vec3f* Camera_Vec3sToVec3f(Vec3f* dest, Vec3s* src) { Vec3f copy; @@ -176,29 +263,29 @@ s16 Camera_AngleDiffAndScale(s16 angle1, s16 angle2, f32 scale) { } /** - * Calculates the current offset between the camera's at-coordinates and the centered actor's coordinates + * Calculates the current offset between the camera's at-coordinates and the focal actors coordinates */ -void Camera_UpdateAtActorOffset(Camera* camera, Vec3f* actorOffset) { - camera->atActorOffset.x = camera->at.x - actorOffset->x; - camera->atActorOffset.y = camera->at.y - actorOffset->y; - camera->atActorOffset.z = camera->at.z - actorOffset->z; +void Camera_SetFocalActorAtOffset(Camera* camera, Vec3f* focalActorPos) { + camera->focalActorAtOffset.x = camera->at.x - focalActorPos->x; + camera->focalActorAtOffset.y = camera->at.y - focalActorPos->y; + camera->focalActorAtOffset.z = camera->at.z - focalActorPos->z; } f32 Camera_GetFocalActorHeight(Camera* camera) { - PosRot actorFocus; + PosRot focalActorFocus; Actor* focalActor = camera->focalActor; - f32 focalHeight; + f32 focalActorHeight; if (focalActor == &GET_PLAYER(camera->play)->actor) { - focalHeight = Player_GetHeight((Player*)focalActor); + focalActorHeight = Player_GetHeight((Player*)focalActor); } else { - Actor_GetFocus(&actorFocus, focalActor); - focalHeight = actorFocus.pos.y - camera->focalActorPosRot.pos.y; - if (focalHeight == 0.0f) { - focalHeight = 10.0f; + Actor_GetFocus(&focalActorFocus, focalActor); + focalActorHeight = focalActorFocus.pos.y - camera->focalActorPosRot.pos.y; + if (focalActorHeight == 0.0f) { + focalActorHeight = 10.0f; } } - return focalHeight; + return focalActorHeight; } f32 Camera_GetRunSpeedLimit(Camera* camera) { @@ -223,6 +310,7 @@ s32 func_800CB7CC(Camera* camera) { return 0; } } + s32 Camera_IsMountedOnHorse(Camera* camera) { Actor* focalActor = camera->focalActor; @@ -310,7 +398,7 @@ s32 func_800CB950(Camera* camera) { f32 yDiff; if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { - yDiff = Camera_fabsf(camera->focalActorPosRot.pos.y - camera->playerFloorHeight); + yDiff = Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight); phi_v0 = false; if (yDiff < 11.0f) { @@ -444,7 +532,7 @@ s32 Camera_IsUsingZoraFins(Camera* camera) { } s32 func_800CBC30(Camera* camera, f32 waterYMax, f32 waterYMin) { - if ((camera->playerFloorHeight != camera->waterYPos) && (camera->waterYPos < waterYMax) && + if ((camera->focalActorFloorHeight != camera->waterYPos) && (camera->waterYPos < waterYMax) && (camera->waterYPos > waterYMin)) { return true; } else { @@ -452,23 +540,258 @@ s32 func_800CBC30(Camera* camera, f32 waterYMax, f32 waterYMin) { } } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBC84.s") +s32 func_800CBC84(Camera* camera, Vec3f* from, CameraCollision* to, s32 arg3) { + CollisionContext* colCtx = &camera->play->colCtx; + Vec3f toNewPos; + Vec3f toPoint; + Vec3f fromToNorm; + f32 floorPolyY; + CollisionPoly** floorPoly; + s32 floorBgId; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CBFA4.s") + OLib_Vec3fDistNormalize(&fromToNorm, from, &to->pos); + toPoint.x = to->pos.x + fromToNorm.x; + toPoint.y = to->pos.y + fromToNorm.y; + toPoint.z = to->pos.z + fromToNorm.z; + floorPoly = &to->poly; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC000.s") + if (!BgCheck_CameraLineTest1(colCtx, from, &toPoint, &toNewPos, floorPoly, (arg3 & 1) ? 0 : 1, 1, + (arg3 & 2) ? 0 : 1, -1, &floorBgId)) { + toNewPos = to->pos; + //! FAKE + if (1) {} + if (1) {} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC128.s") + toNewPos.y += 5.0f; + if ((arg3 != 0) && func_800CB7CC(camera)) { + to->poly = camera->focalActor->floorPoly; + floorBgId = camera->focalActor->floorBgId; + to->norm.x = COLPOLY_GET_NORMAL(to->poly->normal.x); + to->norm.y = COLPOLY_GET_NORMAL(to->poly->normal.y); + to->norm.z = COLPOLY_GET_NORMAL(to->poly->normal.z); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC1C4.s") + if (!Math3D_LineSegVsPlane(to->norm.x, to->norm.y, to->norm.z, to->poly->dist, from, &toPoint, &toNewPos, + 1)) { + floorPolyY = to->pos.y - 20.0f; + } else { + toNewPos.y += 5.0f; + floorPolyY = to->pos.y; + } + } else { + floorPolyY = BgCheck_CameraRaycastFloor2(colCtx, floorPoly, &floorBgId, &toNewPos); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC260.s") + if ((to->pos.y - floorPolyY) > 5.0f) { + to->norm.x = -fromToNorm.x; + to->norm.y = -fromToNorm.y; + to->norm.z = -fromToNorm.z; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC488.s") + return 0; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC56C.s") + to->bgId = floorBgId; + to->norm.x = COLPOLY_GET_NORMAL(to->poly->normal.x); + to->norm.y = COLPOLY_GET_NORMAL(to->poly->normal.y); + to->norm.z = COLPOLY_GET_NORMAL(to->poly->normal.z); + to->pos.x = to->norm.x + toNewPos.x; + to->pos.y = to->norm.y + toNewPos.y; + to->pos.z = to->norm.z + toNewPos.z; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC5C8.s") + return floorBgId + 1; +} + +void func_800CBFA4(Camera* camera, Vec3f* arg1, Vec3f* arg2, s32 arg3) { + CameraCollision sp20; + s32 pad; + + sp20.pos = *arg2; + func_800CBC84(camera, arg1, &sp20, arg3); + *arg2 = sp20.pos; +} + +/** + * Detects the collision poly between `from` and `to`, places collision info in `to` + */ +s32 Camera_BgCheckInfo(Camera* camera, Vec3f* from, CameraCollision* to) { + CollisionPoly* floorPoly; + Vec3f toNewPos; + Vec3f fromToNorm; + + if (BgCheck_CameraLineTest1(&camera->play->colCtx, from, &to->pos, &toNewPos, &to->poly, 1, 1, 1, -1, &to->bgId)) { + floorPoly = to->poly; + to->norm.x = COLPOLY_GET_NORMAL(floorPoly->normal.x); + to->norm.y = COLPOLY_GET_NORMAL(floorPoly->normal.y); + to->norm.z = COLPOLY_GET_NORMAL(floorPoly->normal.z); + to->pos = toNewPos; + + return to->bgId + 1; + } + + OLib_Vec3fDistNormalize(&fromToNorm, from, &to->pos); + to->norm.x = -fromToNorm.x; + to->norm.y = -fromToNorm.y; + to->norm.z = -fromToNorm.z; + + return 0; +} + +/** + * Detects if there is collision between `from` and `to` + */ +s32 Camera_BgCheck(Camera* camera, Vec3f* from, Vec3f* to) { + CollisionContext* colCtx = &camera->play->colCtx; + Vec3f intersect; + s32 bgId; + CollisionPoly* poly = NULL; + + if (BgCheck_CameraLineTest1(colCtx, from, to, &intersect, &poly, 1, 1, 1, -1, &bgId)) { + *to = intersect; + return true; + } + + return false; +} + +/** + * Checks if `from` to `to` is looking from the outside of a poly towards the front + */ +s32 Camera_CheckOOB(Camera* camera, Vec3f* from, Vec3f* to) { + s32 pad; + Vec3f intersect; + s32 pad2; + s32 bgId; + CollisionPoly* poly; + CollisionContext* colCtx = &camera->play->colCtx; + + poly = NULL; + if ((BgCheck_CameraLineTest1(colCtx, from, to, &intersect, &poly, 1, 1, 1, 0, &bgId)) && + (CollisionPoly_GetPointDistanceFromPlane(poly, from) < 0.0f)) { + return true; + } + + return false; +} + +s16 func_800CC260(Camera* camera, Vec3f* arg1, Vec3f* arg2, VecGeo* arg3, Actor** exclusions, s16 numExclusions) { + VecGeo sp90; + s32 ret; + s32 angleCount; + f32 rand; + PosRot playerFocus; + Vec3f sp64; + Player* player = GET_PLAYER(camera->play); + s32 i; + + sp64 = *arg2; + Actor_GetFocus(&playerFocus, &player->actor); // playerFocus unused + sp90 = *arg3; + + angleCount = ARRAY_COUNT(D_801B9E18); + + for (i = 0; i < angleCount; i++) { + OLib_AddVecGeoToVec3f(arg1, arg2, &sp90); + + if (!Camera_CheckOOB(camera, arg1, &sp64) && !func_800CBC30(camera, arg2->y, arg1->y) && + !CollisionCheck_LineOCCheck(camera->play, &camera->play->colChkCtx, arg2, arg1, exclusions, + numExclusions)) { + break; + } + + sp90.yaw = D_801B9E18[i] + arg3->yaw; + rand = Rand_ZeroOne(); + sp90.pitch = D_801B9E34[i] + (s16)(arg3->pitch * rand); + + if (sp90.pitch > 0x36B0) { // 76.9 degrees + sp90.pitch -= 0x3E80; // -87.9 degrees + } + if (sp90.pitch < -0x36B0) { // -76.9 degrees + sp90.pitch += 0x3A98; // 82.4 degrees + } + + sp90.r *= 0.9f; + sp64 = *arg2; + } + + *arg3 = sp90; + + if (i == angleCount) { + ret = -1; + } else { + ret = i; + } + + return ret; +} + +/** + * Gets the floor position underneath `chkPos`, and returns the normal of the floor to `floorNorm`, + * and bgId to `bgId`. If no floor is found, then the normal is a flat surface pointing upwards. + */ +f32 Camera_GetFloorYNorm(Camera* camera, Vec3f* floorNorm, Vec3f* chkPos, s32* bgId) { + CollisionContext* colCtx = &camera->play->colCtx; + CollisionPoly* floorPoly; + f32 floorY = BgCheck_EntityRaycastFloor3(colCtx, &floorPoly, bgId, chkPos); + + if (floorY == BGCHECK_Y_MIN) { + // no floor + floorNorm->x = 0.0f; + floorNorm->y = 1.0f; + floorNorm->z = 0.0f; + } else { + floorNorm->x = COLPOLY_GET_NORMAL(floorPoly->normal.x); + floorNorm->y = COLPOLY_GET_NORMAL(floorPoly->normal.y); + floorNorm->z = COLPOLY_GET_NORMAL(floorPoly->normal.z); + } + + return floorY; +} + +/** + * Gets the position of the floor from `pos` + */ +f32 Camera_GetFloorY(Camera* camera, Vec3f* pos) { + Vec3f posCheck; + Vec3f floorNorm; + s32 bgId; + + posCheck = *pos; + posCheck.y += 80.0f; + + return Camera_GetFloorYNorm(camera, &floorNorm, &posCheck, &bgId); +} + +/** + * Gets the position of the floor from `pos`, and if the floor is considered not solid, + * it checks the next floor below that. Returns the normal of the floor into `norm` + */ +f32 Camera_GetFloorYLayer(Camera* camera, Vec3f* norm, Vec3f* pos, s32* bgId) { + CollisionPoly* floorPoly; + CollisionContext* colCtx = &camera->play->colCtx; + f32 floorY; + + if (camera->focalActor != NULL) { + floorY = BgCheck_EntityRaycastFloor5_3(camera->play, &camera->play->colCtx, &floorPoly, bgId, + camera->focalActor, pos); + } else { + floorY = BgCheck_CameraRaycastFloor2(colCtx, &floorPoly, bgId, pos); + } + + if ((floorY == BGCHECK_Y_MIN) || + ((camera->focalActorFloorHeight < floorY) && !(COLPOLY_GET_NORMAL(floorPoly->normal.y) > 0.5f))) { + // no floor, or player is below the floor and floor is not considered steep + norm->x = 0.0f; + norm->y = 1.0f; + norm->z = 0.0f; + floorY = BGCHECK_Y_MIN; + } else { + norm->x = COLPOLY_GET_NORMAL(floorPoly->normal.x); + norm->y = COLPOLY_GET_NORMAL(floorPoly->normal.y); + norm->z = COLPOLY_GET_NORMAL(floorPoly->normal.z); + } + + return floorY; +} #define CAM_DATA_IS_BG (1 << 12) // if not set, then cam data is for actor cutscenes @@ -543,163 +866,5087 @@ s32 Camera_GetWaterBoxBgCamSetting(Camera* camera, f32* waterY) { return (camSetting == CAM_SET_NONE) ? -2 : camSetting; } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC938.s") +void func_800CC938(Camera* camera) { + func_800DDFE0(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC958.s") +/** + * Calculates the angle between points `from` and `to` + */ +s16 Camera_CalcXZAngle(Vec3f* to, Vec3f* from) { + return CAM_DEG_TO_BINANG(RAD_TO_DEG(func_80086B30(from->x - to->x, from->z - to->z))); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CC9C0.s") +// BSS +s16 D_801EDBF0; -s32 D_801B9E5C = 0; -f32 D_801B9E60 = 0.0f; +/** + * Calculates a pitch adjustment by sampling a position in front of the focal actor and testing the floor height. + * Used to detect if the focal actor is near a slope, edge, or cliff. + * + * @param camera + * @param viewYaw The yaw the camera is facing, gives a direction to sample a position + * @param shouldInit + * + * @return pitchOffset resulting pitch adjustment + */ +s16 Camera_GetPitchAdjFromFloorHeightDiffs(Camera* camera, s16 viewYaw, s16 shouldInit) { + static f32 sFloorYNear; + static f32 sFloorYFar; + static CameraCollision sFarColChk; + Vec3f focalActorPos; + Vec3f nearPos; + Vec3f floorNorm; + f32 checkOffsetY; + s16 pitchNear; + s16 pitchFar; + f32 floorYDiffFar; + f32 viewForwardsUnitX; + f32 viewForwardsUnitZ; + s32 bgId; + f32 nearDist; + f32 farDist; + f32 floorYDiffNear; + f32 focalActorHeight; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CCCEC.s") + viewForwardsUnitX = Math_SinS(viewYaw); + viewForwardsUnitZ = Math_CosS(viewYaw); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD04C.s") + focalActorHeight = Camera_GetFocalActorHeight(camera); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD288.s") + checkOffsetY = focalActorHeight * 1.2f; + nearDist = focalActorHeight * 1.0f; + farDist = focalActorHeight * 2.5f; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD2E0.s") + focalActorPos.x = camera->focalActorPosRot.pos.x; + focalActorPos.y = camera->focalActorFloorHeight + checkOffsetY; + focalActorPos.z = camera->focalActorPosRot.pos.z; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD2F0.s") + nearPos.x = focalActorPos.x + (nearDist * viewForwardsUnitX); + nearPos.y = focalActorPos.y; + nearPos.z = focalActorPos.z + (nearDist * viewForwardsUnitZ); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD3E4.s") + if (shouldInit || ((camera->play->state.frames % 2) == 0)) { + sFarColChk.pos.x = focalActorPos.x + (farDist * viewForwardsUnitX); + sFarColChk.pos.y = focalActorPos.y; + sFarColChk.pos.z = focalActorPos.z + (farDist * viewForwardsUnitZ); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD44C.s") + Camera_BgCheckInfo(camera, &focalActorPos, &sFarColChk); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD634.s") + if (shouldInit) { + sFloorYNear = sFloorYFar = camera->focalActorFloorHeight; + } + } else { + farDist = OLib_Vec3fDistXZ(&focalActorPos, &sFarColChk.pos); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD6CC.s") + sFarColChk.pos.x += sFarColChk.norm.x * 5.0f; + sFarColChk.pos.y += sFarColChk.norm.y * 5.0f; + sFarColChk.pos.z += sFarColChk.norm.z * 5.0f; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD6F8.s") + if (nearDist > farDist) { + nearDist = farDist; + sFloorYNear = sFloorYFar = Camera_GetFloorYLayer(camera, &floorNorm, &sFarColChk.pos, &bgId); + } else { + sFloorYNear = Camera_GetFloorYLayer(camera, &floorNorm, &nearPos, &bgId); + sFloorYFar = Camera_GetFloorYLayer(camera, &floorNorm, &sFarColChk.pos, &bgId); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CD834.s") + if (sFloorYNear == BGCHECK_Y_MIN) { + sFloorYNear = camera->focalActorFloorHeight; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CDA14.s") + if (sFloorYFar == BGCHECK_Y_MIN) { + sFloorYFar = sFloorYNear; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CDB6C.s") + floorYDiffNear = (sFloorYNear - camera->focalActorFloorHeight) * 0.8f; + floorYDiffFar = (sFloorYFar - camera->focalActorFloorHeight) * (20.0f * 0.01f); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CDE6C.s") + pitchNear = CAM_DEG_TO_BINANG(RAD_TO_DEG(func_80086B30(floorYDiffNear, nearDist))); + pitchFar = CAM_DEG_TO_BINANG(RAD_TO_DEG(func_80086B30(floorYDiffFar, farDist))); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CE2B8.s") + return pitchNear + pitchFar; +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CE5E0.s") +f32 func_800CCCEC(Camera* camera, s16 reset) { + static s32 D_801B9E5C = 0; + static f32 D_801B9E60 = 0.0f; + Vec3f offsetForwards; + Vec3f angledOffsetForwards; + PosRot focalActorPosRot; + CameraCollision camCollision; + f32 forwardsUnitZ; + f32 focalActorHeight; + f32 forwardsUnitX; + f32 distResult; + s16 yawForwardsOffset; + f32 distResultAdj; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CE79C.s") + focalActorHeight = Camera_GetFocalActorHeight(camera); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CE930.s") + if (reset) { + D_801B9E5C = 0; + D_801B9E60 = 0.0f; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CEAD8.s") + focalActorPosRot = camera->focalActorPosRot; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CEC38.s") + forwardsUnitX = Math_SinS(focalActorPosRot.rot.y); + forwardsUnitZ = Math_CosS(focalActorPosRot.rot.y); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800CED90.s") + offsetForwards.x = focalActorPosRot.pos.x + (30.0f * forwardsUnitX); + offsetForwards.y = focalActorPosRot.pos.y + focalActorHeight; + offsetForwards.z = focalActorPosRot.pos.z + (30.0f * forwardsUnitZ); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Noop.s") + camCollision.pos.x = focalActorPosRot.pos.x + (12.0f * forwardsUnitX); + camCollision.pos.y = offsetForwards.y; + camCollision.pos.z = focalActorPosRot.pos.z + (12.0f * forwardsUnitZ); + if ((camera->play->state.frames % 2) != 0) { + // Turn and project 65.92 degrees left + yawForwardsOffset = focalActorPosRot.rot.y + DEG_TO_BINANG(65.92f); + + angledOffsetForwards.x = (Math_SinS(yawForwardsOffset) * 50.0f) + offsetForwards.x; + angledOffsetForwards.y = offsetForwards.y; + angledOffsetForwards.z = (Math_CosS(yawForwardsOffset) * 50.0f) + offsetForwards.z; + + if ((Camera_BgCheckInfo(camera, &angledOffsetForwards, &camCollision) != 0) && + Camera_CheckOOB(camera, &offsetForwards, &angledOffsetForwards)) { + // Always going to result in 28.0f? + distResult = OLib_Vec3fDistXZ(&offsetForwards, &camCollision.pos); + + // (-D_801B9E60 < (50.0f - distResult)) + if (!((D_801B9E5C == 2) && (-D_801B9E60 >= (50.0f - distResult)))) { + D_801B9E5C = 1; + distResult = 50.0f - distResult; // 22.0f + D_801B9E60 = distResult; + + // if (distResult == 0.0f) + if (distResult == -distResult) { + distResultAdj = 0.0f; + } else { + distResultAdj = distResult; + } + + return distResultAdj; + } + } + } else { + // Turn and project 90 degrees right + yawForwardsOffset = focalActorPosRot.rot.y - DEG_TO_BINANG(90); + + angledOffsetForwards.x = (Math_SinS(yawForwardsOffset) * 50.0f) + offsetForwards.x; + angledOffsetForwards.y = offsetForwards.y; + angledOffsetForwards.z = (Math_CosS(yawForwardsOffset) * 50.0f) + offsetForwards.z; + + if ((Camera_BgCheckInfo(camera, &angledOffsetForwards, &camCollision) != 0) && + Camera_CheckOOB(camera, &offsetForwards, &angledOffsetForwards)) { + // Always going to result in 28.0f? + distResult = OLib_Vec3fDistXZ(&offsetForwards, &camCollision.pos); + + if (!((D_801B9E5C == 1) && (D_801B9E60 >= -(distResult - 50.0f)))) { + D_801B9E5C = 2; + distResult = distResult - 50.0f; + D_801B9E60 = distResult; + if (distResult == -distResult) { + distResultAdj = 0.0f; + } else { + distResultAdj = distResult; + } + return distResultAdj; + } + } + } + + if (D_801B9E5C != 0) { + distResult = D_801B9E60; + } else { + distResult = 0.0f; + } + + D_801B9E5C = 0; + D_801B9E60 = 0.0f; + + return distResult; +} + +/** + * Calculates a new Up vector from the pitch, yaw, roll + */ +Vec3f* Camera_CalcUpVec(Vec3f* viewUp, s16 pitch, s16 yaw, s16 roll) { + f32 sinP = Math_SinS(pitch); + f32 cosP = Math_CosS(pitch); + f32 sinY = Math_SinS(yaw); + f32 cosY = Math_CosS(yaw); + f32 sinR = Math_SinS(-roll); + f32 cosR = Math_CosS(-roll); + Vec3f up; + Vec3f baseUp; + Vec3f u; + Vec3f rollMtxRow1; + Vec3f rollMtxRow2; + Vec3f rollMtxRow3; + f32 pad; + + // Axis to roll around + u.x = cosP * sinY; + u.y = sinP; + u.z = cosP * cosY; + + // Matrix to apply the roll to the Up vector without roll + rollMtxRow1.x = ((1.0f - SQ(u.x)) * cosR) + SQ(u.x); + rollMtxRow1.y = ((u.x * u.y) * (1.0f - cosR)) - (u.z * sinR); + rollMtxRow1.z = ((u.z * u.x) * (1.0f - cosR)) + (u.y * sinR); + + rollMtxRow2.x = ((u.x * u.y) * (1.0f - cosR)) + (u.z * sinR); + rollMtxRow2.y = ((1.0f - SQ(u.y)) * cosR) + SQ(u.y); + rollMtxRow2.z = ((u.y * u.z) * (1.0f - cosR)) - (u.x * sinR); + + rollMtxRow3.x = ((u.z * u.x) * (1.0f - cosR)) - (u.y * sinR); + rollMtxRow3.y = ((u.y * u.z) * (1.0f - cosR)) + (u.x * sinR); + rollMtxRow3.z = ((1.0f - SQ(u.z)) * cosR) + SQ(u.z); + + // Up without roll + baseUp.x = -sinP * sinY; + baseUp.y = cosP; + baseUp.z = -sinP * cosY; + + // rollMtx * baseUp + up.x = DOTXYZ(baseUp, rollMtxRow1); + up.y = DOTXYZ(baseUp, rollMtxRow2); + up.z = DOTXYZ(baseUp, rollMtxRow3); + + *viewUp = up; + + return viewUp; +} + +f32 Camera_ClampLerpScale(Camera* camera, f32 maxLerpScale) { + f32 ret; + + if (camera->atLerpStepScale < 0.12f) { + ret = 0.12f; + } else if (camera->atLerpStepScale >= maxLerpScale) { + ret = maxLerpScale; + } else { + ret = 1.1f * camera->atLerpStepScale; + } + + return ret; +} + +void Camera_ResetActionFuncState(Camera* camera, s32 mode) { + camera->animState = 0; +} + +void Camera_UpdateInterface(s32 interfaceFlags) { + s32 hudVisibility; + + if ((interfaceFlags & CAM_LETTERBOX_MASK) != CAM_LETTERBOX_IGNORE) { + switch (interfaceFlags & CAM_LETTERBOX_SIZE_MASK) { + case CAM_LETTERBOX_SMALL: + sCameraLetterboxSize = 26; + break; + + case CAM_LETTERBOX_MEDIUM: + sCameraLetterboxSize = 27; + break; + + case CAM_LETTERBOX_LARGE: + sCameraLetterboxSize = 32; + break; + + default: + sCameraLetterboxSize = 0; + break; + } + + if (interfaceFlags & CAM_LETTERBOX_INSTANT) { + ShrinkWindow_Letterbox_SetSize(sCameraLetterboxSize); + } else { + ShrinkWindow_Letterbox_SetSizeTarget(sCameraLetterboxSize); + } + } + + if ((interfaceFlags & CAM_HUD_VISIBILITY_MASK) != CAM_HUD_VISIBILITY_IGNORE) { + hudVisibility = (interfaceFlags & CAM_HUD_VISIBILITY_MASK) >> CAM_HUD_VISIBILITY_SHIFT; + if (hudVisibility == (CAM_HUD_VISIBILITY_ALL >> CAM_HUD_VISIBILITY_SHIFT)) { + hudVisibility = 50; + } + if (hudVisibility != sCameraHudVisibility) { + sCameraHudVisibility = hudVisibility; + Interface_SetHudVisibility(sCameraHudVisibility); + } + } +} + +Vec3f* Camera_BgCheckCorner(Vec3f* dst, Vec3f* linePointA, Vec3f* linePointB, CameraCollision* pointAColChk, + CameraCollision* pointBColChk) { + Vec3f closestPoint; + + func_800CAA14(pointAColChk->poly, pointBColChk->poly, linePointA, linePointB, &closestPoint); + *dst = closestPoint; + + return dst; +} + +/** + * Checks collision between at and eyeNext, if `checkEye` is set, if there is no collsion between + * eyeNext->at, then eye->at is also checked. + * Returns: + * 0 if no collsion is found between at->eyeNext + * 1 if the angle between the polys is between 60 degrees and 120 degrees + * 3 ? + * 6 if the angle between the polys is greater than 120 degrees + */ +s32 func_800CD44C(Camera* camera, VecGeo* diffGeo, CameraCollision* camEyeCollision, CameraCollision* camAtCollision, + s16 checkEye) { + Vec3f* at = &camera->at; + s32 pad[2]; + s32 atEyeBgId; + s32 eyeAtBgId; + s32 ret; + f32 cosEyeAt; + CameraCollision camCollision; + + camEyeCollision->pos = camera->eyeNext; + + ret = 0; + + atEyeBgId = func_800CBC84(camera, at, camEyeCollision, 0); + if (atEyeBgId != 0) { + // collision found between at->ey + camAtCollision->pos = *at; + + OLib_Vec3fToVecGeo(&camEyeCollision->geoNorm, &camEyeCollision->norm); + + if (camEyeCollision->geoNorm.pitch > 0x2EE0) { // 65.9 degrees + camEyeCollision->geoNorm.yaw = diffGeo->yaw; + } + + if (checkEye & 1) { + memcpy(&camCollision, camAtCollision, sizeof(CameraCollision)); + } + + eyeAtBgId = Camera_BgCheckInfo(camera, &camera->eye, camAtCollision); + + if (eyeAtBgId == 0) { + // no collision from eyeNext->at + if (checkEye & 1) { + memcpy(camAtCollision, &camCollision, sizeof(CameraCollision)); + } else { + return 3; + } + } + + if (camEyeCollision->poly == camAtCollision->poly) { + // at->eyeNext and eyeNext->at is the same poly + return 3; + } + + OLib_Vec3fToVecGeo(&camAtCollision->geoNorm, &camAtCollision->norm); + + if (camAtCollision->geoNorm.pitch > 0x2EE0) { // 65.9 degrees + camAtCollision->geoNorm.yaw = BINANG_ROT180(diffGeo->yaw); + } + + if (atEyeBgId != eyeAtBgId) { + // different bgIds for at->eye[Next] and eye[Next]->at + ret = 3; + } else { + cosEyeAt = Math3D_Parallel(&camEyeCollision->norm, &camAtCollision->norm); + if (cosEyeAt < -0.5f) { + ret = 6; + } else if ((cosEyeAt > 0.5f) || (checkEye & 2)) { + ret = 3; + } else { + ret = 1; + } + } + } + return ret; +} + +/** + * Calculates how much to adjust the camera at's y value when on a slope. + */ +f32 Camera_CalcSlopeYAdj(Vec3f* floorNorm, s16 playerYRot, s16 eyeAtYaw, f32 adjAmt) { + f32 tmp; + VecGeo floorNormGeo; + + OLib_Vec3fToVecGeo(&floorNormGeo, floorNorm); + + tmp = Math_CosS(floorNormGeo.pitch) * Math_CosS(playerYRot - floorNormGeo.yaw); + + return (Camera_fabsf(tmp) * adjAmt) * Math_CosS(playerYRot - eyeAtYaw); +} + +f32 func_800CD6CC(Actor* actor) { + return sqrtf(gTargetRanges[actor->targetMode].rangeSq / gTargetRanges[actor->targetMode].leashScale); +} + +/** + * Calculates new at vector for the camera pointing in `eyeAtDir` + */ +s32 Camera_CalcAtDefault(Camera* camera, VecGeo* eyeAtDir, f32 yOffset, s16 calcSlope) { + Vec3f* at = &camera->at; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + s32 pad; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + + focalActorAtOffsetTarget.y = focalActorHeight + yOffset; + focalActorAtOffsetTarget.x = 0.0f; + focalActorAtOffsetTarget.z = 0.0f; + + if (calcSlope) { + focalActorAtOffsetTarget.y -= OLib_ClampMaxDist( + Camera_CalcSlopeYAdj(&camera->floorNorm, focalActorPosRot->rot.y, eyeAtDir->yaw, 25.0f), focalActorHeight); + } + + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + + if (atTarget.y < (camera->focalActorFloorHeight + 10.0f)) { + atTarget.y = camera->focalActorFloorHeight + 10.0f; + } + + Camera_ScaledStepToCeilVec3f(&atTarget, at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return 1; +} + +s32 Camera_CalcAtForScreen(Camera* camera, VecGeo* eyeAtDir, f32 yOffset, f32* focalActorPosY, f32 deltaYMax) { + f32 deltaY; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + s32 pad; + f32 clampedDeltaY; + f32 clampedAbsScreenY; + s16 absScreenY; + s16 screenY; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + + focalActorAtOffsetTarget.y = focalActorHeight + yOffset; + focalActorAtOffsetTarget.x = 0.0f; + focalActorAtOffsetTarget.z = 0.0f; + + Actor_GetScreenPos(camera->play, camera->focalActor, &absScreenY, &screenY); + screenY -= SCREEN_HEIGHT / 2; + absScreenY = ABS(screenY); + + // result unused + clampedAbsScreenY = OLib_ClampMaxDist(absScreenY / (f32)(SCREEN_HEIGHT / 2), 1.0f); + + deltaY = focalActorPosRot->pos.y - *focalActorPosY; + clampedDeltaY = OLib_ClampMaxDist(deltaY, deltaYMax); + + if (absScreenY > (SCREEN_HEIGHT / 4)) { + absScreenY = SCREEN_HEIGHT / 4; + } + + clampedAbsScreenY = OLib_ClampMaxDist(absScreenY / (f32)(SCREEN_HEIGHT / 4), 1.0f); + + focalActorAtOffsetTarget.y -= clampedDeltaY * clampedAbsScreenY * clampedAbsScreenY; + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + atTarget.y = CLAMP_MIN(atTarget.y, camera->focalActorFloorHeight + 10.0f); + + Camera_ScaledStepToCeilVec3f(&atTarget, &camera->at, camera->atLerpStepScale, camera->atLerpStepScale, 0.1f); + + return 1; +} + +s32 Camera_CalcAtForNormal1(Camera* camera, VecGeo* arg1, f32 yOffset, f32 forwardDist) { + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + Vec3f collisionFromPos; + s32 pad; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + + focalActorAtOffsetTarget.x = Math_SinS(focalActorPosRot->rot.y) * forwardDist; + focalActorAtOffsetTarget.z = Math_CosS(focalActorPosRot->rot.y) * forwardDist; + focalActorAtOffsetTarget.y = focalActorHeight + yOffset; + + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + + collisionFromPos.x = focalActorPosRot->pos.x; + collisionFromPos.y = atTarget.y; + collisionFromPos.z = focalActorPosRot->pos.z; + + if (Camera_BgCheck(camera, &collisionFromPos, &atTarget)) { + atTarget.x -= camera->focalActorAtOffset.x - (atTarget.x - collisionFromPos.x); + atTarget.z -= camera->focalActorAtOffset.z - (atTarget.z - collisionFromPos.z); + } + + Camera_ScaledStepToCeilVec3f(&atTarget, &camera->at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return 1; +} + +/** + * Adjusts the camera's at position for Camera_Parallel1 + */ +s32 Camera_CalcAtForParallel(Camera* camera, VecGeo* arg1, f32 yOffset, f32 xzOffsetMax, f32* focalActorPosY, + s16 flags) { + f32 pad; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + f32 fovHeight; + Vec3f* at = &camera->at; + f32 deltaY; + f32 eyeAtDistXZ; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + VecGeo focalActorAtOffsetTargetGeo; + + // Calculate the `focalActorAtOffsetTarget` + // @TODO: Only uses `PARALLEL1_FLAG_` flags, but may need separate flags for `CalcAt` system + if (flags & 0x40) { + focalActorAtOffsetTargetGeo.r = func_800CCCEC(camera, flags & 0x10); + focalActorAtOffsetTargetGeo.yaw = focalActorPosRot->rot.y + 0x4000; + focalActorAtOffsetTargetGeo.pitch = 0; + OLib_VecGeoToVec3f(&focalActorAtOffsetTarget, &focalActorAtOffsetTargetGeo); + } else { + f32 xOffset = camera->focalActorAtOffset.x + camera->unk_0F0.x; + f32 zOffset = camera->focalActorAtOffset.z + camera->unk_0F0.z; + + if (sqrtf(SQ(xOffset) + SQ(zOffset)) < xzOffsetMax) { + focalActorAtOffsetTarget.x = xOffset; + focalActorAtOffsetTarget.z = zOffset; + } else { + focalActorAtOffsetTarget.x = camera->focalActorAtOffset.x; + focalActorAtOffsetTarget.z = camera->focalActorAtOffset.z; + } + } + + focalActorAtOffsetTarget.y = focalActorHeight + yOffset; + + // focalActorAtOffsetTarget.y based on slope + if (PREG(76) && flags) { + focalActorAtOffsetTarget.y -= + Camera_CalcSlopeYAdj(&camera->floorNorm, focalActorPosRot->rot.y, arg1->yaw, 25.0f); + } + + // Adjust posOffsetTarget.y based on something + if (func_800CB950(camera)) { + *focalActorPosY = Camera_ScaledStepToCeilF(focalActorPosRot->pos.y, *focalActorPosY, 0.4f, 0.1f); + deltaY = focalActorPosRot->pos.y - *focalActorPosY; + focalActorAtOffsetTarget.y -= deltaY; + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + } else { + deltaY = focalActorPosRot->pos.y - *focalActorPosY; + eyeAtDistXZ = OLib_Vec3fDistXZ(at, &camera->eye); + + // Math_FTanF + // Get the height based on 80% of the fov + fovHeight = func_80086760(DEG_TO_RAD(camera->fov * (0.8f * 0.5f))) * eyeAtDistXZ; + + if (deltaY > fovHeight) { + //! FAKE + if (1) {} + *focalActorPosY += deltaY - fovHeight; + deltaY = fovHeight; + } else if (deltaY < -fovHeight) { + *focalActorPosY += deltaY + fovHeight; + deltaY = -fovHeight; + } + + focalActorAtOffsetTarget.y -= deltaY; + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, 0.3f, 0.2f, 0.1f); + camera->xzOffsetUpdateRate = 0.3f; + camera->yOffsetUpdateRate = 0.2f; + } + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + Camera_ScaledStepToCeilVec3f(&atTarget, at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return 1; +} + +s32 Camera_CalcAtForFriendlyLockOn(Camera* camera, VecGeo* eyeAtDir, Vec3f* targetPos, f32 yOffset, f32 distance, + f32* yPosOffset, VecGeo* outPlayerToTargetDir, s16 flags) { + Vec3f* at = &camera->at; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + Vec3f sp68; + f32 temp_f0_6; + VecGeo sp5C; + f32 deltaY; + f32 fovHeight; + f32 phi_f16; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + f32 sp50; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + + focalActorAtOffsetTarget.y = focalActorHeight + yOffset; + focalActorAtOffsetTarget.x = 0.0f; + focalActorAtOffsetTarget.z = 0.0f; + + if (PREG(76) && (flags & FLG_ADJSLOPE)) { + focalActorAtOffsetTarget.y -= + Camera_CalcSlopeYAdj(&camera->floorNorm, camera->focalActorPosRot.rot.y, eyeAtDir->yaw, 25.0f); + } + + atTarget = focalActorPosRot->pos; + atTarget.y += focalActorHeight; + + OLib_Vec3fDiffToVecGeo(outPlayerToTargetDir, &atTarget, targetPos); + + sp5C = *outPlayerToTargetDir; + sp5C.r = (distance < sp5C.r) ? (sp5C.r * 0.2f) : ((sp5C.r * 0.9f) - (sp5C.r * 0.7f * (sp5C.r / distance))); + + if (flags & FLG_OFFGROUND) { + sp5C.r *= 0.2f; + camera->yOffsetUpdateRate = camera->xzOffsetUpdateRate = 0.01f; + } + + OLib_VecGeoToVec3f(&sp68, &sp5C); + + focalActorAtOffsetTarget.x += sp68.x; + focalActorAtOffsetTarget.y += sp68.y; + focalActorAtOffsetTarget.z += sp68.z; + + if (func_800CB950(camera)) { + *yPosOffset = Camera_ScaledStepToCeilF(focalActorPosRot->pos.y, *yPosOffset, 0.4f, 0.1f); + deltaY = focalActorPosRot->pos.y - *yPosOffset; + focalActorAtOffsetTarget.y -= deltaY; + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + } else { + if (!(flags & 0x80)) { + deltaY = focalActorPosRot->pos.y - *yPosOffset; + sp50 = OLib_Vec3fDistXZ(at, &camera->eye); + phi_f16 = sp50; + func_80086B30(deltaY, sp50); + fovHeight = func_80086760(DEG_TO_RAD(camera->fov * 0.4f)) * phi_f16; + + if (fovHeight < deltaY) { + *yPosOffset += deltaY - fovHeight; + deltaY = fovHeight; + } else if (deltaY < -fovHeight) { + *yPosOffset += deltaY + fovHeight; + deltaY = -fovHeight; + } + focalActorAtOffsetTarget.y -= deltaY; + } else { + deltaY = focalActorPosRot->pos.y - *yPosOffset; + temp_f0_6 = func_80086B30(deltaY, OLib_Vec3fDistXZ(at, &camera->eye)); + + if (temp_f0_6 > 0.34906584f) { // (M_PI / 9) + phi_f16 = 1.0f - sin_rad(temp_f0_6 - 0.34906584f); + } else if (temp_f0_6 < -0.17453292f) { // (M_PI / 18) + phi_f16 = 1.0f - sin_rad(-0.17453292f - temp_f0_6); + } else { + phi_f16 = 1.0f; + } + + focalActorAtOffsetTarget.y -= deltaY * phi_f16; + } + + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, 0.5f, 0.5f, 0.1f); + camera->xzOffsetUpdateRate = 0.5f; + camera->yOffsetUpdateRate = 0.5f; + } + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + Camera_ScaledStepToCeilVec3f(&atTarget, at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return 1; +} + +s32 Camera_CalcAtForEnemyLockOn(Camera* camera, f32* arg1, s32 arg2, f32 yOffset, f32 arg4, f32 arg5, f32* arg6, + VecGeo* arg7, s16 flags) { + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Vec3f focalActorAtOffsetTarget; + Vec3f atTarget; + Vec3f sp60; + VecGeo sp58; + f32 temp_f0_3; + f32 deltaY; + f32 new_var2; + f32 sp4C; + f32 phi_f14; + f32 fovHeight; + + focalActorAtOffsetTarget.y = Camera_GetFocalActorHeight(camera) + yOffset; + focalActorAtOffsetTarget.x = 0.0f; + focalActorAtOffsetTarget.z = 0.0f; + + sp58 = *arg7; + sp58.r = arg7->r * (arg5 * arg4); + + if (flags & 0x80) { + camera->yOffsetUpdateRate = 0.01f; + camera->xzOffsetUpdateRate = 0.01f; + } + + OLib_VecGeoToVec3f(&sp60, &sp58); + + focalActorAtOffsetTarget.x += sp60.x; + focalActorAtOffsetTarget.y += sp60.y; + focalActorAtOffsetTarget.z += sp60.z; + + if (func_800CB950(camera)) { + phi_f14 = *arg6; + *arg6 = Camera_ScaledStepToCeilF(focalActorPosRot->pos.y, phi_f14, 0.4f, 0.1f); + deltaY = focalActorPosRot->pos.y - *arg6; + focalActorAtOffsetTarget.y -= deltaY; + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + } else { + //! FAKE: + if (focalActorPosRot->pos.x) {} + + //! FAKE: unnecessary temp? + new_var2 = *arg1; + sp4C = new_var2; + deltaY = focalActorPosRot->pos.y - *arg6; + temp_f0_3 = func_80086B30(deltaY, sp4C); + + if (!(flags & 0x80)) { + fovHeight = func_80086760(DEG_TO_RAD(camera->fov * 0.4f)) * sp4C; + + if (fovHeight < deltaY) { + *arg6 += deltaY - fovHeight; + deltaY = fovHeight; + } else if (deltaY < -fovHeight) { + *arg6 += deltaY + fovHeight; + deltaY = -fovHeight; + } + + focalActorAtOffsetTarget.y -= deltaY; + } else { + if (temp_f0_3 > 0.34906584f) { // (M_PI / 9) + phi_f14 = 1.0f - sin_rad(temp_f0_3 - 0.34906584f); + } else if (temp_f0_3 < -0.17453292f) { // (M_PI / 18) + phi_f14 = 1.0f - sin_rad(-0.17453292f - temp_f0_3); + } else { + phi_f14 = 1.0f; + } + + focalActorAtOffsetTarget.y -= deltaY * phi_f14; + } + Camera_ScaledStepToCeilVec3f(&focalActorAtOffsetTarget, &camera->focalActorAtOffset, 0.5f, 0.5f, 0.1f); + camera->xzOffsetUpdateRate = 0.5f; + camera->yOffsetUpdateRate = 0.5f; + } + + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + Camera_ScaledStepToCeilVec3f(&atTarget, &camera->at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return true; +} + +s32 Camera_CalcAtForHorse(Camera* camera, VecGeo* eyeAtDir, f32 yOffset, f32* yPosOffset, s16 calcSlope) { + Vec3f* at = &camera->at; + Vec3f posOffsetTarget; + Vec3f atTarget; + s32 pad[2]; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + Player* player = (Player*)camera->focalActor; + PosRot horsePosRot; + + Actor_GetWorld(&horsePosRot, player->rideActor); + + if (EN_HORSE_CHECK_JUMPING((EnHorse*)player->rideActor)) { + horsePosRot.pos.y -= 49.0f; + *yPosOffset = Camera_ScaledStepToCeilF(horsePosRot.pos.y, *yPosOffset, 0.1f, 0.1f); + camera->atLerpStepScale = Camera_ScaledStepToCeilF(0.4f, camera->atLerpStepScale, 0.2f, 0.02f); + } else { + *yPosOffset = Camera_ScaledStepToCeilF(horsePosRot.pos.y, *yPosOffset, 0.5f, 0.1f); + } + + posOffsetTarget.x = 0.0f; + posOffsetTarget.y = focalActorHeight + yOffset; + posOffsetTarget.z = 0.0f; + + if (calcSlope) { + posOffsetTarget.y -= + Camera_CalcSlopeYAdj(&camera->floorNorm, camera->focalActorPosRot.rot.y, eyeAtDir->yaw, 25.0f); + } + + Camera_ScaledStepToCeilVec3f(&posOffsetTarget, &camera->focalActorAtOffset, camera->xzOffsetUpdateRate, + camera->yOffsetUpdateRate, 0.1f); + + atTarget.x = camera->focalActorAtOffset.x + horsePosRot.pos.x; + atTarget.y = camera->focalActorAtOffset.y + horsePosRot.pos.y; + atTarget.z = camera->focalActorAtOffset.z + horsePosRot.pos.z; + Camera_ScaledStepToCeilVec3f(&atTarget, at, camera->atLerpStepScale, camera->atLerpStepScale, 0.2f); + + return true; +} + +f32 Camera_ClampDist1(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 timer) { + f32 distTarget; + + if ((dist / maxDist) > 1.2f) { + distTarget = maxDist; + + camera->rUpdateRateInv = 20.0f / (dist / maxDist); + if ((20.0f / (dist / maxDist)) < 10) { + camera->rUpdateRateInv = 10; + } + } else if (dist < minDist) { + distTarget = minDist; + + camera->rUpdateRateInv = + Camera_ScaledStepToCeilF((timer != 0) ? 10.0f : 20.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } else if (maxDist < dist) { + distTarget = maxDist; + + camera->rUpdateRateInv = + Camera_ScaledStepToCeilF((timer != 0) ? 10.0f : 20.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } else { + distTarget = dist; + + camera->rUpdateRateInv = + Camera_ScaledStepToCeilF((timer != 0) ? 20.0f : 1.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } + + return Camera_ScaledStepToCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f); +} + +f32 Camera_ClampDist2(Camera* camera, f32 dist, f32 minDist, f32 maxDist, s16 timer) { + f32 distTarget; + + if (timer == 0) { + distTarget = ((maxDist * 0.25f) > 80.0f) ? maxDist * 0.25f : 80.0f; + + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(1000.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } else if ((dist / maxDist) > 1.2f) { + distTarget = maxDist; + + camera->rUpdateRateInv = 20.0f / (dist / maxDist); + if ((20.0f / (dist / maxDist)) < 10.0f) { + camera->rUpdateRateInv = 10.0f; + } + } else if (dist < minDist) { + distTarget = minDist; + + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } else if (maxDist < dist) { + distTarget = maxDist; + + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } else { + distTarget = dist; + + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(1.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + } + + return Camera_ScaledStepToCeilF(distTarget, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f); +} + +/** + * Calculates the camera pitch to update to as player moves around + * The pitch target starts with a default value on a flat surface, then standing on a sloped surface will create an + * offset in default pitch Camera "AI" for pitch + */ +s16 Camera_CalcDefaultPitch(Camera* camera, s16 pitch, s16 flatSurfacePitchTarget, s16 slopePitchAdj) { + f32 attenuation; + f32 pitchStepScale; + f32 t; + s16 slopePitchAdjAttenuated; + s16 pitchMag = ABS(pitch); + s16 pitchTarget; + + // if slopePitchAdj is positive, then it is attenuated by a factor of Math_CosS(slopePitchAdj) + slopePitchAdjAttenuated = (slopePitchAdj > 0) ? (s16)(Math_CosS(slopePitchAdj) * slopePitchAdj) : slopePitchAdj; + pitchTarget = flatSurfacePitchTarget - slopePitchAdjAttenuated; + + if (ABS(pitchTarget) < pitchMag) { + // pitch is decreasing + pitchStepScale = (1.0f / camera->pitchUpdateRateInv) * 3.0f; + } else { + // pitch is increasing + t = pitchMag * (1.0f / DEG_TO_BINANG(79.655f)); + attenuation = + Camera_QuadraticAttenuation(0.8f, 1.0f - t); // attenuation starts above pitch = 0xB54 (16 degrees) + pitchStepScale = (1.0f / camera->pitchUpdateRateInv) * attenuation; + } + + return Camera_ScaledStepToCeilS(pitchTarget, pitch, pitchStepScale, 5); +} + +/** + * Calculates the camera pitch to update to as player moves around + * The yaw target starts with a default value, but will only update to that target yaw in proportion to players velocity + * No velocity means yaw does not update + * Camera "AI" for yaw + */ +s16 Camera_CalcDefaultYaw(Camera* camera, s16 yaw, s16 target, f32 attenuationYawDiffRange, + f32 attenuationYawDiffInterpParam) { + f32 attenuationYawDiffAdj; + f32 attenuationYawDiff; + f32 attenuationYawDiffParam; + f32 attenuationSpeedRatio; + f32 yawUpdRate; + s16 yawDiffToTarget; + + if (camera->xzSpeed > 0.001f) { + yawDiffToTarget = target - BINANG_ROT180(yaw); + attenuationYawDiffParam = BINANG_ROT180(yawDiffToTarget) / (f32)0x8000; + } else { + yawDiffToTarget = target - BINANG_ROT180(yaw); + attenuationYawDiffParam = 0.3f; + } + + // Attenuation 1 based on YawDiffToTarget. + attenuationYawDiff = Camera_QuadraticAttenuation(attenuationYawDiffRange, attenuationYawDiffParam); + attenuationYawDiffAdj = LERPIMP(attenuationYawDiff, 1.0f, attenuationYawDiffInterpParam); + attenuationYawDiffAdj = CLAMP_MIN(attenuationYawDiffAdj, 0.0f); + + // attenuation 2 based on SpeedRatio + attenuationSpeedRatio = Camera_QuadraticAttenuation(0.5f, camera->speedRatio); + + yawUpdRate = 1.0f / camera->yawUpdateRateInv; + return yaw + (s16)(yawDiffToTarget * attenuationYawDiffAdj * attenuationSpeedRatio * yawUpdRate); +} + +void Camera_CalcDefaultSwing(Camera* camera, VecGeo* arg1, VecGeo* arg2, f32 arg3, f32 arg4, SwingAnimation* swing2, + s16* flags) { + SwingAnimation* swing = swing2; + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f peekAroundPoint; + s32 sp8C = 0; + f32 sp88; + s32 checkEyeBit1; + s32 checkEyeBit2; + CameraCollision sp58; + VecGeo sp50; + Vec3f* sp30; + + if (swing->unk_64 == 1) { + if (arg3 < (sp88 = OLib_Vec3fDist(at, &swing->collisionClosePoint))) { + //! FAKE: + dummy:; + swing->unk_64 = 0; + } else if ((sp88 = Math3D_SignedDistanceFromPlane(swing->eyeAtColChk.norm.x, swing->eyeAtColChk.norm.y, + swing->eyeAtColChk.norm.z, swing->eyeAtColChk.poly->dist, + at)) > 0.0f) { + swing->unk_64 = 0; + } else if ((sp88 = OLib_Vec3fDist(eye, &swing->eyeAtColChk.pos)) < 10.0f) { + swing->unk_64 = 0; + } else if ((sp88 = Math3D_SignedDistanceFromPlane(swing->atEyeColChk.norm.x, swing->atEyeColChk.norm.y, + swing->atEyeColChk.norm.z, swing->atEyeColChk.poly->dist, + eye)) > 0.0f) { + swing->unk_64 = 0; + } else if (swing->atEyeColChk.norm.y > 0.50f) { + swing->unk_64 = 0; + } else { + Math3D_AngleBetweenVectors(&camera->unk_0F0, &swing->eyeAtColChk.norm, &sp88); + if (sp88 > 0.0f) { + swing->unk_64 = 0; + } + } + + if (swing->unk_64 == 1) { + sp8C = 2; + } + } else if (swing->unk_64 == 2) { + swing->unk_64 = 0; + } + + if (sp8C == 0) { + if (*flags & 2) { + checkEyeBit1 = 1 << 1; + } else { + checkEyeBit1 = 0; + } + + if (swing->unk_64 != 1) { + checkEyeBit2 = 1 << 0; + } else { + checkEyeBit2 = 0; + } + + sp8C = + func_800CD44C(camera, arg1, &swing->atEyeColChk, &swing->eyeAtColChk, ((s16)checkEyeBit2 | checkEyeBit1)); + } + + switch (sp8C) { + case 1: + Camera_BgCheckCorner(&swing->collisionClosePoint, &camera->at, &camera->eyeNext, &swing->atEyeColChk, + &swing->eyeAtColChk); + // fallthrough + case 2: + peekAroundPoint.x = swing->collisionClosePoint.x + (swing->atEyeColChk.norm.x + swing->eyeAtColChk.norm.x); + peekAroundPoint.y = swing->collisionClosePoint.y + (swing->atEyeColChk.norm.y + swing->eyeAtColChk.norm.y); + peekAroundPoint.z = swing->collisionClosePoint.z + (swing->atEyeColChk.norm.z + swing->eyeAtColChk.norm.z); + + sp30 = &camera->eyeNext; + OLib_Vec3fDiffToVecGeo(&sp50, at, &peekAroundPoint); + sp50.r = arg1->r; + swing->unk_64 = 1; + swing->swingUpdateRate = 1.5f; + OLib_AddVecGeoToVec3f(&sp58.pos, at, &sp50); + + if (func_800CBC84(camera, &swing->eyeAtColChk.pos, &sp58, 0) == 0) { + sp50.yaw = + Camera_AngleDiffAndScale(arg1->yaw, arg2->yaw, (camera->speedRatio * 0.5f) + 0.5f) + arg2->yaw; + sp50.pitch = Camera_AngleDiffAndScale(arg1->pitch, arg2->pitch, (camera->speedRatio * 0.5f) + 0.5f) + + arg2->pitch; + if (swing->atEyeColChk.geoNorm.pitch < 0x2AA8) { // 60 degrees + swing->yaw = sp50.yaw; + swing->pitch = sp50.pitch; + } else { + swing->yaw = arg1->yaw; + swing->pitch = arg1->pitch; + } + } + *eye = *sp30 = sp58.pos; + break; + + case 3: + case 6: + sp30 = &swing->atEyeColChk.pos; + sp88 = OLib_Vec3fDist(at, sp30); + if (sp88 < 60.0f) { + sp50.yaw = Camera_AngleDiffAndScale(arg1->yaw, arg2->yaw, camera->speedRatio) + arg2->yaw; + if (*flags & 0x1000) { + sp50.pitch = arg2->pitch; + } else { + sp50.pitch = Math_CosS(swing->atEyeColChk.geoNorm.pitch) * 0x3FFC; + } + sp50.r = 60.0f - sp88; + OLib_AddVecGeoToVec3f(&sp58.pos, sp30, &sp50); + } else { + sp50.yaw = Camera_AngleDiffAndScale(arg1->yaw, arg2->yaw, camera->speedRatio) + arg2->yaw; + sp50.pitch = Camera_AngleDiffAndScale(arg1->pitch, arg2->pitch, camera->speedRatio) + arg2->pitch; + sp50.r = arg1->r; + OLib_AddVecGeoToVec3f(&sp58.pos, at, &sp50); + } + func_800CBC84(camera, at, &sp58, 0); + *eye = sp58.pos; + break; + + default: + sp30 = &swing->atEyeColChk.pos; + *flags &= ~0x1000; + swing->swingUpdateRate = arg4; + *eye = *sp30; + break; + } +} + +/*===============================================================*/ +/* Camera Update Functions (Chosen by Settings & Modes) */ +/*===============================================================*/ + +s32 Camera_Noop(Camera* camera) { + return 1; +} + +// SP, FLOATS - Many temps reused to get the stack pointer down, even though it doesn't seem logical +// https://decomp.me/scratch/zVOSG +#ifdef NON_EQUIVALENT +s32 Camera_Normal1(Camera* camera) { + CameraModeValue* values; + f32 phi_f16_2; + Vec3f spD8; // D8-DC-E0 + f32 spD4; + f32 spD0; + f32 spC8; + f32 spC4; + f32 spC0; + VecGeo spB4; // B4-B8-BA + VecGeo spAC; // AC-B0-B2 + VecGeo spA4; // A4-A8-AA + VecGeo sp9C; // 9C-A0-A2 + VecGeo sp74; // 74-78-7A + s16 sp72; + f32 sp6C; + VecGeo sp64; // 64-68-6A + CollisionPoly* sp60; + f32 sp88 = Camera_GetFocalActorHeight(camera); + s32 sp5C; // BgID + f32 sp58; + f32 phi_f2; + // Vec3f *sp48; + // Vec3f *sp44; + + // f32 phi_f0; + f32 phi_f2_2; + f32 phi_f0_4; + s32 phi_v1_2; + Vec3f* sp4C = &camera->eye; + PosRot* sp40 = &camera->focalActorPosRot; + // f32 phi_f16_5; + + s16 phi_a0; + s16 temp_a0_3; // May be fake + Vec3f* new_var3; + + Normal1ReadOnlyData* roData = &camera->paramData.norm1.roData; + Normal1ReadWriteData* rwData = &camera->paramData.norm1.rwData; + + // sp48 = &camera->at; + // sp4C;/ + // sp44 = &camera->eyeNext; + // sp40; + // sp88; + + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = GET_NEXT_RO_DATA(values) * (sp88 * 0.01f * (0.8f - ((68.0f / sp88) * -0.2f))); + roData->unk_04 = GET_NEXT_RO_DATA(values) * (sp88 * 0.01f * (0.8f - ((68.0f / sp88) * -0.2f))); + roData->unk_08 = GET_NEXT_RO_DATA(values) * (sp88 * 0.01f * (0.8f - ((68.0f / sp88) * -0.2f))); + roData->unk_04 = roData->unk_08 - (roData->unk_08 - roData->unk_04); + + if (RELOAD_PARAMS(camera)) { + roData->unk_20 = (s16)((GET_NEXT_RO_DATA(values) * 182.04167f) + .5f); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_0C = 40.0f - (40.0f - roData->unk_0C); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values) * 0.01f; + roData->unk_14 = 1.0f - (1.0f - roData->unk_14); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_1C = GET_NEXT_RO_DATA(values) * 0.01f; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + sCameraInterfaceFlags = roData->interfaceFlags; + OLib_Vec3fDiffToVecGeo(&spA4, &camera->at, sp4C); + OLib_Vec3fDiffToVecGeo(&sp9C, &camera->at, &camera->eyeNext); + + switch (camera->animState) { + case 20: + Camera_SetUpdateRatesFastYaw(camera); + // fallthrough? + case 0: + rwData->unk_0C = 1; + if (!(roData->interfaceFlags & NORMAL1_FLAG_3) && (camera->animState != 20)) { + rwData->unk_0C |= 0x1000; + } + // fallthrough? + case 10: + if (camera->animState == 10) { + rwData->unk_0C = 0; + } + rwData->unk_08 = 0; + D_801EDC30[camera->camId].yaw = D_801EDC30[camera->camId].pitch = D_801EDC30[camera->camId].unk_64 = 0; + rwData->unk_0A = 0x514; + D_801EDC30[camera->camId].swingUpdateRate = roData->unk_0C; + rwData->unk_00 = camera->focalActorPosRot.pos.y; + rwData->unk_04 = camera->xzSpeed; + D_801EDC30[camera->camId].timer = 0; + sUpdateCameraDirection = false; + rwData->unk_10 = 120.0f; + break; + } + + camera->animState = 1; + sUpdateCameraDirection = true; + + if ((camera->speedRatio < 0.01f) || (rwData->unk_0A > 0x4B0)) { + if (rwData->unk_0A > -0x4B0) { + rwData->unk_0A--; + } + } else { + rwData->unk_0A = 0x4B0; + } + + if (func_800CB950(camera)) { + rwData->unk_00 = camera->focalActorPosRot.pos.y; + } + + if (rwData->unk_0C & 0x1000) { + spC8 = camera->speedRatio; + } else { + spC8 = ((camera->speedRatio * 3.0f) + 1.0f) * 0.25f; + } + + spD8 = camera->focalActorAtOffset; + spD8.y -= sp88 + roData->unk_00; + spC4 = Camera_Vec3fMagnitude(&spD8); + + if ((roData->unk_04 + roData->unk_08) < spC4) { + spC4 = 1.0f; + } else { + spC4 = spC4 / (roData->unk_04 + roData->unk_08); + } + + // Everything above matches except stack pointers + // PERM_RANDOMIZE( + + phi_f16_2 = 0.2f; + + phi_f2 = (camera->xzSpeed - rwData->unk_04) * 0.2f; + phi_f0_4 = phi_f2; + if (phi_f2 < 0.0f) { + phi_f0_4 = 0.0f; + } + + spC0 = OLib_ClampMaxDist(SQ(phi_f0_4), 1.0f); + camera->yOffsetUpdateRate = + Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, (0.5f * spC8) + (0.5f * spC4), 0.0001f); + camera->xzOffsetUpdateRate = + Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, (0.5f * spC8) + (0.5f * spC4), 0.0001f); + camera->fovUpdateRate = + Camera_ScaledStepToCeilF(0.05f, camera->fovUpdateRate, (0.5f * spC8) + (0.5f * spC4), 0.0001f); + + if (D_801EDC30[camera->camId].unk_64 == 1) { + phi_f2 = 0.5f; + } else { + phi_f2 = (0.5f * spC8) + (0.5f * spC4); + } + + rwData->unk_04 = camera->xzSpeed; + + if (D_801EDC30[camera->camId].timer != 0) { + camera->yawUpdateRateInv = + Camera_ScaledStepToCeilF((D_801EDC30[camera->camId].timer * 2) + D_801EDC30[camera->camId].swingUpdateRate, + camera->yawUpdateRateInv, phi_f2, 0.1f); + if (roData->interfaceFlags & NORMAL1_FLAG_3) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(100.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + } else { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF((D_801EDC30[camera->camId].timer * 2) + 16.0f, + camera->pitchUpdateRateInv, 0.2f, 0.1f); + } + D_801EDC30[camera->camId].timer--; + } else { + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF( + D_801EDC30[camera->camId].swingUpdateRate - (D_801EDC30[camera->camId].swingUpdateRate * 0.7f * spC0), + camera->yawUpdateRateInv, phi_f2, 0.1f); + if ((roData->interfaceFlags & NORMAL1_FLAG_3) && (camera->speedRatio > 0.01f)) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(100.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + } else if (D_801ED920 != NULL) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(32.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + } else { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(16.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f); + } + } + + if (roData->interfaceFlags & NORMAL1_FLAG_0) { + //! FAKE + if (!spC8) {} + temp_a0_3 = Camera_GetPitchAdjFromFloorHeightDiffs(camera, spA4.yaw + 0x8000, rwData->unk_0C & 1); + phi_f2 = (1.0f / roData->unk_10) * 0.7f; + phi_f16_2 = (1.0f / roData->unk_10) * 0.3f * (1.0f - camera->speedRatio); + spD0 = phi_f16_2; + rwData->unk_08 = Camera_ScaledStepToCeilS(temp_a0_3, rwData->unk_08, phi_f2 + phi_f16_2, 5); + } else { + rwData->unk_08 = 0; + } + + if ((D_801EDC30[camera->camId].unk_64 == 1) && (roData->unk_00 > -40.0f)) { + phi_f0_4 = Math_SinS(D_801EDC30[camera->camId].pitch); + phi_f2 = roData->unk_00; + phi_f2 = phi_f2 * (1.0f - phi_f0_4); // TODO: phi_f2 should not be on the LHS and RHS + // phi_f2 = roData->unk_00 * (1.0f - phi_f0_4); + camera->yawUpdateRateInv = 80.0f; + camera->pitchUpdateRateInv = 80.0f; + phi_f2_2 = ((-40.0f) * phi_f0_4) + phi_f2; + phi_f16_2 = phi_f0_4; + } else { + phi_f2_2 = roData->unk_00; + } + + if (roData->interfaceFlags & (NORMAL1_FLAG_6 | NORMAL1_FLAG_5)) { + if (camera->dist < roData->unk_04) { + phi_f16_2 = 0.0f; + } else if (roData->unk_08 < camera->dist) { + phi_f16_2 = 1.0f; + } else if (roData->unk_08 == roData->unk_04) { + phi_f16_2 = 1.0f; + } else { + // phi_f16_2 = camera->dist - roData->unk_04; + spD4 = (camera->dist - roData->unk_04) / (roData->unk_08 - roData->unk_04); + phi_f16_2 = spD4; + } + + Camera_CalcAtForNormal1(camera, &sp9C, phi_f2_2, 25.0f * phi_f16_2 * camera->speedRatio); + rwData->unk_10 = 120.0f; + spD0 = phi_f16_2; + } else if ((roData->interfaceFlags & NORMAL1_FLAG_7) && (rwData->unk_0A < 0)) { + phi_f0_4 = rwData->unk_0A / -1200.0f; // May be used to swap $f registers + Camera_CalcAtForNormal1( + camera, &sp9C, + phi_f2_2 - ((phi_f2_2 - ((0.8f - ((68.0f / sp88) * -0.2f)) * sp88 * -0.45f)) * phi_f0_4 * 0.75f), + 10.0f * phi_f0_4); + rwData->unk_10 = 120.0f; + spD0 = phi_f16_2; + //! FAKE + if (0) {} + } else if (roData->interfaceFlags & NORMAL1_FLAG_3) { + spD0 = phi_f16_2; + Camera_CalcAtForScreen(camera, &sp9C, roData->unk_00, &rwData->unk_00, rwData->unk_10); + if (rwData->unk_10 > 20.0f) { + rwData->unk_10 -= 0.2f; + } + } else { + spD0 = phi_f16_2; + Camera_CalcAtDefault(camera, &sp9C, phi_f2_2, roData->interfaceFlags & NORMAL1_FLAG_0); + rwData->unk_10 = 120.0f; + } + + phi_f16_2 = spD0; + OLib_Vec3fDiffToVecGeo(&spB4, &camera->at, &camera->eyeNext); + if ((roData->interfaceFlags & NORMAL1_FLAG_7) && (rwData->unk_0A < 0)) { + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + switch (((Player*)camera->focalActor)->transformation) { + case PLAYER_FORM_HUMAN: + phi_f16_2 = 66.0f; + break; + + case PLAYER_FORM_DEKU: + phi_f16_2 = 66.0f; + break; + + case PLAYER_FORM_ZORA: + phi_f16_2 = 115.0f; + break; + + case PLAYER_FORM_GORON: + phi_f16_2 = 115.0f; + break; + + case PLAYER_FORM_FIERCE_DEITY: + phi_f16_2 = roData->unk_04; + break; + + default: + phi_f16_2 = roData->unk_04; + break; + } + } + phi_f0_4 = Camera_ClampDist2(camera, spB4.r, phi_f16_2, phi_f16_2, 0); + } else if (roData->interfaceFlags & NORMAL1_FLAG_7) { + phi_f0_4 = Camera_ClampDist2(camera, spB4.r, roData->unk_04, roData->unk_08, 1); + } else { + phi_f0_4 = Camera_ClampDist1(camera, spB4.r, roData->unk_04, roData->unk_08, rwData->unk_0A > 0); + } + + camera->dist = spB4.r = phi_f0_4; + + if (D_801EDC30[camera->camId].unk_64 != 0) { + //! FAKE + if (phi_v1_2) {} + spB4.pitch = + Camera_ScaledStepToCeilS(D_801EDC30[camera->camId].pitch, sp9C.pitch, 1.0f / camera->yawUpdateRateInv, 5); + spB4.yaw = + Camera_ScaledStepToCeilS(D_801EDC30[camera->camId].yaw, sp9C.yaw, 1.0f / camera->yawUpdateRateInv, 5); + } else { + if (roData->interfaceFlags & NORMAL1_FLAG_5) { + spB4.yaw = sp9C.yaw; + spB4.pitch = sp9C.pitch; + camera->animState = 20; + } else { + if (D_801ED920 != NULL) { + //! FAKE + if (sp40) {} + new_var3 = &D_801ED920->world.pos; + OLib_Vec3fDiffToVecGeo(&sp74, &sp40->pos, new_var3); // TODO: arg0 & arg1 swapped + sp72 = sp40->rot.y - sp74.yaw; + // Interface and shrink-window flags + if ((roData->interfaceFlags & 0xFF00) == 0xFF00) { + sp6C = 1.0f; + } else { + sp6C = 1.0f - (ABS(sp72) / 10922.0f); + } + + if (ABS((s16)(sp9C.yaw - sp74.yaw)) < 0x4000) { + sp74.yaw += 0x8000; + } + + if (!(roData->interfaceFlags & NORMAL1_FLAG_3) || !func_800CB924(camera)) { + spB4.yaw = Camera_CalcDefaultYaw(camera, sp9C.yaw, (s16)(sp40->rot.y - (s16)(sp72 * sp6C)), + roData->unk_14, spC0); + } + + if (!(roData->interfaceFlags & NORMAL1_FLAG_3) || (camera->speedRatio < 0.01f)) { + spB4.pitch = Camera_CalcDefaultPitch( + camera, sp9C.pitch, roData->unk_20 + (s16)((roData->unk_20 - sp74.pitch) * sp6C * 0.75f), + rwData->unk_08); + } + dummy:; // TODO: Will this be needed? + } else if (roData->interfaceFlags & NORMAL1_FLAG_1) { + if ((camera->speedRatio > 0.1f) || (rwData->unk_0A > 0x4B0)) { + OLib_Vec3fToVecGeo(&sp64, &camera->unk_0F0); + if (!(roData->interfaceFlags & NORMAL1_FLAG_3) || !func_800CB924(camera)) { + spB4.yaw = Camera_CalcDefaultYaw(camera, sp9C.yaw, sp64.yaw, roData->unk_14, spC0); + } + if (!(roData->interfaceFlags & NORMAL1_FLAG_3)) { + spB4.pitch = Camera_CalcDefaultPitch(camera, sp9C.pitch, roData->unk_20, rwData->unk_08); + } else if ((camera->unk_0F0.y > 0.0f) && func_800CB924(camera)) { + spB4.pitch = Camera_CalcDefaultPitch(camera, sp9C.pitch, roData->unk_20, rwData->unk_08); + } + } else { + spB4.yaw = sp9C.yaw; + spB4.pitch = sp9C.pitch; + dummy4:; // TODO: Will this be needed? + } + } else { + spB4.yaw = Camera_CalcDefaultYaw(camera, sp9C.yaw, sp40->rot.y, roData->unk_14, spC0); + if (!(roData->interfaceFlags & NORMAL1_FLAG_3) || (camera->speedRatio < 0.1f)) { + spB4.pitch = Camera_CalcDefaultPitch(camera, sp9C.pitch, roData->unk_20, rwData->unk_08); + } + } + } + } + + // 76.9 degrees + if (spB4.pitch > 0x36B0) { + spB4.pitch = 0x36B0; + } + + // -76.9 degrees + if (spB4.pitch < -0x36B0) { + spB4.pitch = -0x36B0; + } + + OLib_AddVecGeoToVec3f(&camera->eyeNext, &camera->at, &spB4); + if ((camera->status == CAM_STATUS_ACTIVE) && !(roData->interfaceFlags & NORMAL1_FLAG_4) && (spC4 <= 0.9f)) { + + if (func_800CBA7C(camera) == 0) { + Camera_CalcDefaultSwing(camera, &spB4, &sp9C, roData->unk_04, roData->unk_0C, &D_801EDC30[camera->camId], + &rwData->unk_0C); + sp58 = BgCheck_CameraRaycastFloor2(&camera->play->colCtx, &sp60, &sp5C, sp4C); + if ((roData->interfaceFlags & NORMAL1_FLAG_3) && func_800CB924(camera)) { + phi_f16_2 = 25.0f; + } else { + phi_f16_2 = 5.0f; + } + spD0 = sp4C->y; // TODO: another fake reuse of temp + phi_f0_4 = sp4C->y; + phi_f0_4 -= sp58; + // new_var2 = sp4C->y; + if ((sp58 != BGCHECK_Y_MIN) && (phi_f0_4 < phi_f16_2)) { + sp4C->y = sp58 + phi_f16_2; + } else if ((camera->waterYPos != camera->focalActorFloorHeight) && ((spD0 - camera->waterYPos) < 5.0f) && + ((spD0 - camera->waterYPos) > -5.0f)) { + sp4C->y = camera->waterYPos + 5.0f; + } + } + + OLib_Vec3fDiffToVecGeo(&spAC, sp4C, &camera->at); + camera->inputDir.x = spAC.pitch; + camera->inputDir.y = spAC.yaw; + camera->inputDir.z = 0; + if (gSaveContext.save.saveInfo.playerData.health < 17) { + phi_v1_2 = (camera->play->state.frames << 0x18); + phi_v1_2 = (s16)((phi_v1_2 >> 0x15) & 0xFD68); + camera->inputDir.y += phi_v1_2; + } + } else { + D_801EDC30[camera->camId].swingUpdateRate = roData->unk_0C; + D_801EDC30[camera->camId].unk_64 = 0; + sUpdateCameraDirection = false; + *sp4C = camera->eyeNext; + } + + // Everything below OLib_Vec3fDiffToVecGeo matches except stack pointers + // ) + + phi_f2 = (gSaveContext.save.saveInfo.playerData.health <= 16) ? 0.8f : 1.0f; + camera->fov = Camera_ScaledStepToCeilF(roData->unk_18 * phi_f2, camera->fov, camera->fovUpdateRate, 0.1f); + + if (roData->interfaceFlags & NORMAL1_FLAG_2) { + spD4 = Math_SinS((s16)(spA4.yaw - spB4.yaw)); + camera->roll = Camera_ScaledStepToCeilS(((Rand_ZeroOne() - 0.5f) * 500.0f * camera->speedRatio) + + (spD4 * spD4 * spD4 * 10000.0f), + camera->roll, 0.1f, 5); + } else { + if (gSaveContext.save.saveInfo.playerData.health <= 16) { + phi_a0 = (Rand_ZeroOne() - 0.5f) * 100.0f * camera->speedRatio; + } else { + phi_a0 = 0.0f; + } + camera->roll = Camera_ScaledStepToCeilS(phi_a0, camera->roll, 0.2f, 5); + } + + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->unk_1C); + rwData->unk_0C &= ~1; + + return true; +} +#else #pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Normal1.s") +#endif -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Normal2.s") +/** + * Unused Camera RemoteBomb Setting + */ +s32 Camera_Normal2(Camera* camera) { + return Camera_Noop(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Normal3.s") +#define NORMAL3_RW_FLAG (1 << 0) -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Normal4.s") +/** + * Riding Epona and Zora + */ +s32 Camera_Normal3(Camera* camera) { + Normal3ReadOnlyData* roData = &camera->paramData.norm3.roData; + Normal3ReadWriteData* rwData = &camera->paramData.norm3.rwData; + f32 sp8C; + f32 sp90; + f32 temp_f2; // multi-use temp + f32 sp88; + VecGeo sp80; + VecGeo sp78; + VecGeo sp70; + VecGeo sp68; + f32 phi_f2; + s16 sp62; + s16 phi_v1_2; + Player* player = (Player*)camera->focalActor; + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Normal0.s") + temp_f2 = Camera_GetFocalActorHeight(camera); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Parallel1.s") + if ((camera->setting == CAM_SET_HORSE) && (player->rideActor == NULL)) { + Camera_ChangeSettingFlags(camera, camera->prevSetting, CAM_CHANGE_SETTING_1); + return 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Parallel2.s") + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Parallel3.s") + temp_f2 = CAM_RODATA_UNSCALE(temp_f2); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Parallel4.s") + roData->yOffset = GET_NEXT_RO_DATA(values) * temp_f2; + roData->distMin = GET_NEXT_RO_DATA(values) * temp_f2; + roData->distMax = GET_NEXT_RO_DATA(values) * temp_f2; + roData->pitchTarget = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->yawUpdateRateInv = GET_NEXT_RO_DATA(values); + roData->pitchUpdateRateInv = GET_NEXT_RO_DATA(values); + roData->fovTarget = GET_NEXT_RO_DATA(values); + roData->maxAtLERPScale = GET_NEXT_SCALED_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Parallel0.s") + OLib_Vec3fDiffToVecGeo(&sp70, at, eye); + OLib_Vec3fDiffToVecGeo(&sp68, at, eyeNext); + sUpdateCameraDirection = true; + sCameraInterfaceFlags = roData->interfaceFlags; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Jump1.s") + //! FAKE: fake temp + phi_v1_2 = camera->animState; + if (!(((phi_v1_2 == 0) || (phi_v1_2 == 10)) || (phi_v1_2 == 20))) { + } else { + rwData->isZero = 0; + rwData->curPitch = 0; + rwData->yPosOffset = camera->focalActorFloorHeight; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Jump2.s") + D_801EDC30[camera->camId].yaw = D_801EDC30[camera->camId].pitch = D_801EDC30[camera->camId].unk_64 = 0; + D_801EDC30[camera->camId].swingUpdateRate = roData->yawUpdateRateInv; + rwData->yawUpdateRate = BINANG_SUB(BINANG_ROT180(camera->focalActorPosRot.rot.y), sp70.yaw) * (1.0f / 6.0f); + rwData->distTimer = 0; + rwData->is1200 = 1200; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Jump3.s") + if (roData->interfaceFlags & NORMAL3_FLAG_1) { + rwData->yawTimer = 6; + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + } else { + rwData->yawTimer = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Jump4.s") + camera->animState = 1; + D_801EDC30[camera->camId].timer = 0; + rwData->flag = NORMAL3_RW_FLAG; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Jump0.s") + if (rwData->distTimer != 0) { + rwData->distTimer--; + } + sp90 = ((camera->speedRatio * 3.0f) + 1.0f) * 0.25f * 0.5f; + sp8C = temp_f2 = camera->speedRatio * 0.2f; + + if (D_801EDC30[camera->camId].timer != 0) { + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF( + (D_801EDC30[camera->camId].timer * 2) + roData->yawUpdateRateInv, camera->yawUpdateRateInv, sp90, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF((D_801EDC30[camera->camId].timer * 2) + 16.0f, + camera->pitchUpdateRateInv, sp8C, 0.1f); + D_801EDC30[camera->camId].timer--; + } else { + camera->yawUpdateRateInv = + Camera_ScaledStepToCeilF(roData->yawUpdateRateInv, camera->yawUpdateRateInv, sp90, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(16.0f, camera->pitchUpdateRateInv, sp8C, 0.1f); + } + + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, sp90, 0.001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, sp8C, 0.0001f); + camera->fovUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->fovUpdateRate, sp8C, 0.0001f); + + phi_v1_2 = Camera_GetPitchAdjFromFloorHeightDiffs(camera, BINANG_ROT180(sp70.yaw), rwData->flag & NORMAL3_RW_FLAG); + temp_f2 = ((1.0f / roData->pitchUpdateRateInv) * 0.5f) * (1.0f - camera->speedRatio); + rwData->curPitch = + Camera_ScaledStepToCeilS(phi_v1_2, rwData->curPitch, ((1.0f / roData->pitchUpdateRateInv) * 0.5f) + temp_f2, 5); + + if ((roData->interfaceFlags & NORMAL3_FLAG_6) || (player->rideActor == NULL)) { + Camera_CalcAtDefault(camera, &sp68, roData->yOffset, 1); + } else { + Camera_CalcAtForHorse(camera, &sp68, roData->yOffset, &rwData->yPosOffset, 1); + } + + sp88 = (roData->distMax + roData->distMin) * 0.5f; + OLib_Vec3fDiffToVecGeo(&sp80, at, eyeNext); + temp_f2 = Camera_ClampDist1(camera, sp80.r, roData->distMin, roData->distMax, rwData->distTimer); + + phi_f2 = sp88 - temp_f2; + phi_f2 *= 0.002f; + camera->dist = sp80.r = temp_f2 + phi_f2; + + if (roData->interfaceFlags & NORMAL3_FLAG_7) { + sp80.pitch = Camera_ScaledStepToCeilS(camera->focalActor->focus.rot.x - rwData->curPitch, sp68.pitch, 0.25f, 5); + } else { + sp62 = roData->pitchTarget - rwData->curPitch; + sp80.pitch = Camera_ScaledStepToCeilS(sp62, sp68.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + } + + sp80.pitch = CLAMP_MAX(sp80.pitch, DEG_TO_BINANG(79.655f)); + + if (sp80.pitch < -DEG_TO_BINANG(29.995f)) { + sp80.pitch = -DEG_TO_BINANG(29.995f); + } + + if (roData->interfaceFlags & NORMAL3_FLAG_7) { + sp62 = BINANG_SUB(camera->focalActor->focus.rot.y, BINANG_ROT180(sp68.yaw)); + temp_f2 = 1.0f; + } else { + sp62 = BINANG_SUB(focalActorPosRot->rot.y, BINANG_ROT180(sp68.yaw)); + OLib_Vec3fToVecGeo(&sp78, &camera->unk_0F0); + phi_v1_2 = focalActorPosRot->rot.y - sp78.yaw; + if (phi_v1_2 < 0) { + phi_v1_2 *= -1; + } + + if (phi_v1_2 < 0x555A) { + temp_f2 = 1.0f; + } else { + temp_f2 = ((f32)0x8000 - phi_v1_2) / (f32)0x2AA6; + } + } + + sp90 = (sp62 * ((SQ(camera->speedRatio) * 0.8f) + 0.2f) * temp_f2) / camera->yawUpdateRateInv; + if ((Camera_fabsf(sp90) > 150.0f) && (camera->speedRatio > 0.05f)) { + sp80.yaw = sp68.yaw + sp90; + } + + if (rwData->yawTimer > 0) { + sp80.yaw += rwData->yawUpdateRate; + rwData->yawTimer--; + if (rwData->yawTimer == 0) { + Camera_UnsetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + } + } + + OLib_AddVecGeoToVec3f(eyeNext, at, &sp80); + + if (camera->status == CAM_STATUS_ACTIVE) { + *eye = *eyeNext; + func_800CBFA4(camera, at, eye, 0); + } else { + *eye = *eyeNext; + } + + camera->fov = Camera_ScaledStepToCeilF(roData->fovTarget, camera->fov, camera->fovUpdateRate, 0.1f); + + if (roData->interfaceFlags & NORMAL3_FLAG_5) { + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.05f, 5); + } else { + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.1f, 5); + } + + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->maxAtLERPScale); + rwData->flag &= ~NORMAL3_RW_FLAG; + + return 1; +} + +/** + * Used for the unknown Naname setting. + * Identical to Normal1 except reads camera scene data to apply a camera roll + */ +s32 Camera_Normal4(Camera* camera) { + BgCamFuncData* bgCamFuncData; + s16 roll; + + if (RELOAD_PARAMS(camera)) { + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + D_801EDBF0 = bgCamFuncData->rot.z; + } + + roll = camera->roll; + Camera_Normal1(camera); + camera->roll = Camera_ScaledStepToCeilS(D_801EDBF0, roll, 0.05f, 5); + + return 1; +} + +s32 Camera_Normal0(Camera* camera) { + f32 phi_f0; + f32 yNormal; + s32 pad; + f32 playerHeight; + f32 spA4; + f32 spA0; + VecGeo sp98; + VecGeo sp90; + VecGeo sp88; + VecGeo sp80; + VecGeo sp78; + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + s16 temp_v1_2; + s16 phi_a1; + s16 phi_a0; + BgCamFuncData* bgCamFuncData; + f32 new_var; + Normal0ReadOnlyData* roData = &camera->paramData.norm0.roData; + Normal0ReadWriteData* rwData = &camera->paramData.norm0.rwData; + + playerHeight = Player_GetHeight((Player*)camera->focalActor); + yNormal = 0.8f - ((68.0f / playerHeight) * -0.2f); + + if (!RELOAD_PARAMS(camera)) { + } else { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->unk_00 = GET_NEXT_SCALED_RO_DATA(values) * playerHeight * yNormal; + roData->unk_04 = GET_NEXT_SCALED_RO_DATA(values) * playerHeight * yNormal; + roData->unk_08 = GET_NEXT_SCALED_RO_DATA(values) * playerHeight * yNormal; + roData->unk_1C = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->unk_18 = GET_NEXT_SCALED_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + if (RELOAD_PARAMS(camera)) { + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + Camera_Vec3sToVec3f(&rwData->unk_00, &bgCamFuncData->pos); + rwData->unk_20 = bgCamFuncData->rot.x; + rwData->unk_22 = bgCamFuncData->rot.y; + rwData->unk_24 = focalActorPosRot->pos.y; + if (bgCamFuncData->fov == -1) { + rwData->unk_1C = roData->unk_14; + } else { + if (bgCamFuncData->fov > 360) { + phi_f0 = CAM_RODATA_UNSCALE(bgCamFuncData->fov); + } else { + phi_f0 = bgCamFuncData->fov; + } + rwData->unk_1C = phi_f0; + } + + if (bgCamFuncData->unk_0E == -1) { + rwData->unk_2C = 0; + } else { + rwData->unk_2C = bgCamFuncData->unk_0E; + } + + rwData->unk_18 = 0.0f; + rwData->unk_28 = 120.0f; + + if (roData->interfaceFlags & NORMAL0_FLAG_2) { + sp88.pitch = rwData->unk_20; + sp88.yaw = rwData->unk_22; + sp88.r = 100.0f; + OLib_VecGeoToVec3f(&rwData->unk_0C, &sp88); + } + camera->animState = 1; + camera->yawUpdateRateInv = 50.0f; + } else { + if (func_800CB950(camera)) { + rwData->unk_24 = focalActorPosRot->pos.y; + } + //! FAKE: + if (1) {} + } + + OLib_Vec3fDiffToVecGeo(&sp80, at, eye); + OLib_Vec3fDiffToVecGeo(&sp78, at, eyeNext); + + camera->speedRatio *= 0.50f; + spA4 = camera->speedRatio * 0.5f; + spA0 = camera->speedRatio * 0.2f; + + camera->yawUpdateRateInv = + Camera_ScaledStepToCeilF(roData->unk_0C, camera->yawUpdateRateInv * camera->speedRatio, 0.5f, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(16.0f, camera->pitchUpdateRateInv, spA0, 0.1f); + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, spA4, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, spA0, 0.0001f); + camera->fovUpdateRate = Camera_ScaledStepToCeilF(0.05, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f); + + if (!(roData->interfaceFlags & NORMAL0_FLAG_7)) { + Camera_CalcAtDefault(camera, &sp78, roData->unk_00, roData->interfaceFlags & NORMAL0_FLAG_0); + rwData->unk_28 = 120.0f; + } else { + Camera_CalcAtForScreen(camera, &sp78, roData->unk_00, &rwData->unk_24, rwData->unk_28); + if (rwData->unk_28 > 20.0f) { + rwData->unk_28 -= 0.2f; + } + } + + if (roData->interfaceFlags & NORMAL0_FLAG_2) { + rwData->unk_00.x = focalActorPosRot->pos.x + rwData->unk_0C.x; + rwData->unk_00.z = focalActorPosRot->pos.z + rwData->unk_0C.z; + } + + rwData->unk_00.y = focalActorPosRot->pos.y; + OLib_Vec3fDiffToVecGeo(&sp88, &rwData->unk_00, at); + OLib_Vec3fDiffToVecGeo(&sp90, at, eyeNext); + + if (rwData->unk_2C & 2) { + phi_a1 = rwData->unk_22; + } else { + phi_a1 = roData->unk_1C; + } + + temp_v1_2 = sp90.yaw - sp88.yaw; + if (((phi_a1 <= 0x4000) && (phi_a1 < ABS(temp_v1_2))) || ((phi_a1 > 0x4000) && (ABS(temp_v1_2) < phi_a1))) { + //! FAKE: Needed to swap v0/v1 + if (1) {} + if (1) {} + if (1) {} + if (1) {} + + //! FAKE: Needed because the *1.0f isn't being multiplied + new_var = 1.0f; + + if (temp_v1_2 < 0) { + phi_a0 = -phi_a1; + } else { + phi_a0 = phi_a1; + } + + phi_a0 += sp88.yaw; + sp98.yaw = Camera_ScaledStepToCeilS(phi_a0, sp80.yaw, + (1.0f / camera->yawUpdateRateInv) * new_var * camera->speedRatio, 5); + if (rwData->unk_2C & 1) { + sp98.pitch = Camera_CalcDefaultPitch(camera, sp78.pitch, rwData->unk_20, 0); + } else { + sp98.pitch = sp80.pitch; + } + } else { + sp98 = sp90; + } + + camera->dist = sp98.r = Camera_ClampDist1(camera, sp90.r, roData->unk_04, roData->unk_08, 0); + if (!(rwData->unk_2C & 1)) { + if (sp98.pitch > 0xE38) { // 20 degrees + sp98.pitch += ((s16)(0xE38 - sp98.pitch) >> 2); + } + if (sp98.pitch < 0) { + sp98.pitch += ((s16)(-0x38E - sp98.pitch) >> 2); + } + } + OLib_AddVecGeoToVec3f(eyeNext, at, &sp98); + + *eye = *eyeNext; + + if (camera->status == CAM_STATUS_ACTIVE) { + if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & NORMAL0_FLAG_4)) { + Camera_BgCheck(camera, at, eye); + } else { + func_800CBFA4(camera, at, eye, 3); + OLib_Vec3fDiffToVecGeo(&sp98, eye, at); + camera->inputDir.x = sp98.pitch; + camera->inputDir.y = sp98.yaw; + camera->inputDir.z = 0; + } + } + + camera->fov = Camera_ScaledStepToCeilF(rwData->unk_1C, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->unk_18); + + return 1; +} + +/** + * Used for targeting + */ +s32 Camera_Parallel1(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Vec3f spB0; + Vec3f spA4; + f32 spA0; + f32 sp9C; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + VecGeo sp90; + VecGeo sp88; + VecGeo sp80; + VecGeo sp78; + BgCamFuncData* bgCamFuncData; + s16 sp72; + s16 tangle; + Parallel1ReadOnlyData* roData = &camera->paramData.para1.roData; + Parallel1ReadWriteData* rwData = &camera->paramData.para1.rwData; + s32 parallelFlagCond; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + s16 new_var2; + s16 phi_a0; + s32 phi_a0_2; + CameraModeValue* values; + f32 yNormal; + + if (!RELOAD_PARAMS(camera)) { + } else { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_04 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_08 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_20 = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->unk_22 = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->unk_18 = GET_NEXT_SCALED_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_24 = GET_NEXT_RO_DATA(values); + rwData->unk_00 = roData->unk_04; + } + + OLib_Vec3fDiffToVecGeo(&sp80, at, eye); + OLib_Vec3fDiffToVecGeo(&sp78, at, eyeNext); + Camera_GetFocalActorPos(&spA4, camera); + + switch (camera->animState) { + case 20: + if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == 0) { + Camera_SetUpdateRatesFastYaw(camera); + } + // fallthrough + case 0: + case 10: + if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) { + rwData->unk_10 = focalActorPosRot->pos; + } else { + camera->xzOffsetUpdateRate = 0.5f; + camera->yOffsetUpdateRate = 0.5f; + } + + if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + PARALLEL1_FLAG_3) { + rwData->unk_10 = camera->focalActorPosRot.pos; + } + + rwData->timer1 = 200.0f; + + if ((2.0f * roData->unk_04) < camera->dist) { + camera->dist = 2.0f * roData->unk_04; + sp78.r = camera->dist; + sp80.r = sp78.r; + OLib_AddVecGeoToVec3f(eye, at, &sp80); + *eyeNext = *eye; + } + + rwData->unk_1C = 0; + + if (roData->interfaceFlags & PARALLEL1_FLAG_2) { + rwData->timer2 = 20; + } else { + rwData->timer2 = 6; + } + + if ((camera->focalActor == &GET_PLAYER(camera->play)->actor) && (camera->mode == CAM_MODE_CHARGE)) { + rwData->timer2 = 30; + if (((Player*)camera->focalActor)->transformation == PLAYER_FORM_DEKU) { + roData->unk_24 = -1; + } + } + + if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_1)) { + rwData->timer2 = 1; + yNormal = 0.8f - ((68.0f / focalActorHeight) * -0.2f); + + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + + rwData->unk_20 = bgCamFuncData->rot.x; + rwData->unk_1E = bgCamFuncData->rot.y; + rwData->unk_08 = (bgCamFuncData->fov == -1) ? roData->unk_14 + : (bgCamFuncData->fov > 360) ? CAM_RODATA_UNSCALE(bgCamFuncData->fov) + : bgCamFuncData->fov; + rwData->unk_00 = (bgCamFuncData->unk_0E == -1) + ? roData->unk_04 + : CAM_RODATA_UNSCALE(bgCamFuncData->unk_0E) * focalActorHeight * yNormal; + //! FAKE + dummy:; + } else { + rwData->unk_08 = roData->unk_14; + rwData->unk_00 = roData->unk_04; + } + + rwData->timer3 = roData->unk_24; + rwData->unk_04 = focalActorPosRot->pos.y - camera->unk_0F0.y; + rwData->unk_26 = 1; + camera->animState = 1; + sCameraInterfaceFlags = roData->interfaceFlags; + break; + } + + if (rwData->timer2 != 0) { + switch (roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) { + case PARALLEL1_FLAG_1: + case (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1): + rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22; + rwData->unk_20 = roData->unk_20; + break; + + case PARALLEL1_FLAG_2: + rwData->unk_1E = roData->unk_22; + rwData->unk_20 = roData->unk_20; + break; + + case (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1): + if (rwData->timer3 == 1) { + OLib_Vec3fDiffToVecGeo(&sp88, &rwData->unk_10, &spA4); + rwData->unk_1E = ((ABS(BINANG_SUB(sp88.yaw, sp80.yaw)) < 0x3A98) || Camera_IsClimbingLedge(camera)) + ? sp80.yaw + : sp80.yaw + (s16)((BINANG_SUB(sp88.yaw, sp80.yaw) >> 2) * 3); + } + rwData->unk_20 = roData->unk_20; + break; + + case PARALLEL1_FLAG_3: + rwData->unk_1E = sp80.yaw; + rwData->unk_20 = roData->unk_20; + break; + + case (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_1): + break; + + default: + rwData->unk_1E = sp78.yaw + roData->unk_22; + rwData->unk_20 = roData->unk_20; + break; + } + } else if (roData->interfaceFlags & PARALLEL1_FLAG_5) { + rwData->unk_1E = BINANG_ROT180(camera->focalActorPosRot.rot.y) + roData->unk_22; + } + + if (camera->animState == 21) { + camera->animState = 1; + } else if (camera->animState == 11) { + camera->animState = 1; + } + + spA0 = camera->speedRatio * 0.5f; + sp9C = camera->speedRatio * 0.2f; + + if (((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) || + ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == PARALLEL1_FLAG_3) || + (roData->interfaceFlags & PARALLEL1_FLAG_5)) { + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.5f, 0.1f); + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_0C, camera->yawUpdateRateInv, 0.5f, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + } else { + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, spA0, 0.1f); + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_0C, camera->yawUpdateRateInv, spA0, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(2.0f, camera->pitchUpdateRateInv, sp9C, 0.1f); + } + + if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) { + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.1f, camera->yOffsetUpdateRate, spA0, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.1f, camera->xzOffsetUpdateRate, sp9C, 0.0001f); + } else if (roData->interfaceFlags & PARALLEL1_FLAG_7) { + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.5f, camera->yOffsetUpdateRate, spA0, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.5f, camera->xzOffsetUpdateRate, sp9C, 0.0001f); + } else { + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, spA0, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, sp9C, 0.0001f); + } + + // TODO: Extra trailing 0 in 0.050f needed? + camera->fovUpdateRate = + Camera_ScaledStepToCeilF(0.050f, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f); + + if (roData->interfaceFlags & PARALLEL1_FLAG_0) { + tangle = Camera_GetPitchAdjFromFloorHeightDiffs(camera, BINANG_ROT180(sp80.yaw), rwData->unk_26 = 1); + spA0 = ((1.0f / roData->unk_10)); + spA0 *= 0.6f; + sp9C = ((1.0f / roData->unk_10) * 0.4f) * (1.0f - camera->speedRatio); + rwData->unk_1C = Camera_ScaledStepToCeilS(tangle, rwData->unk_1C, spA0 + sp9C, 5); + } else { + rwData->unk_1C = 0; + } + + if (func_800CB950(camera) || (((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_1000) || + (((Player*)camera->focalActor)->stateFlags3 & PLAYER_STATE3_100)) { + rwData->unk_04 = camera->focalActorPosRot.pos.y; + sp72 = false; + } else { + sp72 = true; + } + + if ((((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4000) || + (((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4) || + ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1))) { + spB0 = spA4; + spB0.y += ((focalActorHeight * 0.6f) + roData->unk_00); + Camera_ScaledStepToCeilVec3f(&spB0, at, camera->xzOffsetUpdateRate, camera->yOffsetUpdateRate, 0.0001f); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } else if ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) { + spB0 = focalActorPosRot->pos; + spB0.y += focalActorHeight + roData->unk_00; + Camera_ScaledStepToCeilVec3f(&spB0, at, camera->xzOffsetUpdateRate, camera->yOffsetUpdateRate, 0.0001f); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } else if (rwData->timer2 != 0) { + Camera_CalcAtDefault(camera, &sp78, roData->unk_00, 0); + rwData->timer1 = 200.0f; + } else if (!(roData->interfaceFlags & PARALLEL1_FLAG_7) && !sp72) { + Camera_CalcAtForParallel(camera, &sp78, roData->unk_00, roData->unk_08, &rwData->unk_04, + roData->interfaceFlags & (PARALLEL1_FLAG_6 | PARALLEL1_FLAG_0)); + rwData->timer1 = 200.0f; + } else { + Camera_CalcAtForScreen(camera, &sp78, roData->unk_00, &rwData->unk_04, rwData->timer1); + if (rwData->timer1 > 10.0f) { + rwData->timer1--; + } + } + + camera->dist = Camera_ScaledStepToCeilF(rwData->unk_00, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f); + + if (rwData->timer2 != 0) { + if (rwData->timer3 <= 0) { + if (rwData->timer3 == 0) { + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + } + + tangle = ((rwData->timer2 + 1) * rwData->timer2) >> 1; + sp90.yaw = sp80.yaw + ((BINANG_SUB(rwData->unk_1E, sp80.yaw) / tangle) * rwData->timer2); + phi_a0 = ((roData->interfaceFlags & PARALLEL1_FLAG_0) ? BINANG_SUB(rwData->unk_20, rwData->unk_1C) + : rwData->unk_20); + new_var2 = BINANG_SUB(phi_a0, sp80.pitch); + sp90.pitch = sp80.pitch + ((new_var2 / tangle) * rwData->timer2); + sp90.r = camera->dist; + rwData->timer2--; + } else { + sp90 = sp80; + sp90.r = camera->dist; + } + } else { + OLib_Vec3fDiffToVecGeo(&sp90, at, eyeNext); + sp90.r = camera->dist; + + if (roData->interfaceFlags & PARALLEL1_FLAG_1) { + sp90.yaw = Camera_ScaledStepToCeilS(rwData->unk_1E, sp78.yaw, 1.0f / camera->yawUpdateRateInv, 0xC8); + } + + parallelFlagCond = (roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)); + + if (roData->interfaceFlags & PARALLEL1_FLAG_0) { + phi_a0 = (rwData->unk_20 - rwData->unk_1C); + } else { + phi_a0 = rwData->unk_20; + } + + if (parallelFlagCond == (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) { + spA0 = CLAMP_MAX(camera->speedRatio, 1.0f); + phi_a0 = (sp90.pitch * spA0) + (phi_a0 * (1.0f - spA0)); + sp90.pitch = Camera_ScaledStepToCeilS(phi_a0, sp78.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + } else if (parallelFlagCond != PARALLEL1_FLAG_3) { + sp90.pitch = Camera_ScaledStepToCeilS(phi_a0, sp78.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + } + + if (sp90.pitch > DEG_TO_BINANG(79.655f)) { + sp90.pitch = DEG_TO_BINANG(79.655f); + } + + if (sp90.pitch < -DEG_TO_BINANG(29.995f)) { + sp90.pitch = -DEG_TO_BINANG(29.995f); + } + } + + if (rwData->timer3 > 0) { + rwData->timer3--; + } + + OLib_AddVecGeoToVec3f(eyeNext, at, &sp90); + + if (camera->status == CAM_STATUS_ACTIVE) { + if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & PARALLEL1_FLAG_4)) { + spB0 = *at; + if ((((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4000) || + (((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4) || + ((roData->interfaceFlags & (PARALLEL1_FLAG_3 | PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1)) == + (PARALLEL1_FLAG_2 | PARALLEL1_FLAG_1))) { + spB0.y += focalActorHeight; + } + *eye = *eyeNext; + func_800CBFA4(camera, &spB0, eye, 0); + } else { + *eye = *eyeNext; + func_800CBFA4(camera, at, eye, 3); + } + + if (rwData->timer2 != 0) { + sUpdateCameraDirection = true; + } else { + sUpdateCameraDirection = false; + } + } + + camera->fov = Camera_ScaledStepToCeilF(rwData->unk_08, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, sp72 ? roData->unk_1C : roData->unk_18); + rwData->unk_26 &= ~1; + + return 1; +} + +/** + * Unused Camera Maze Setting + */ +s32 Camera_Parallel2(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Parallel3(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Parallel4(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Parallel0(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Jump1(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Camera for climbing structures + */ +s32 Camera_Jump2(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Vec3f spC8; + Vec3f spBC; + VecGeo spB4; + VecGeo spAC; + VecGeo spA4; + VecGeo sp9C; + s16 temp_t2; + s16 yawDiff; + s32 pad; + f32 sp90; + f32 sp8C; + s32 sp88; + CameraCollision sp60; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Jump2ReadOnlyData* roData = &camera->paramData.jump2.roData; + Jump2ReadWriteData* rwData = &camera->paramData.jump2.rwData; + f32 phi_f2; + f32 yNormal; // used twice + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + f32 temp_f16; + + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + yNormal = 0.8f - (-0.2f * (68.0f / focalActorHeight)); + + if (camera->unk_0F0.y > 0.0f) { + phi_f2 = -10.0f; + } else { + phi_f2 = 10.0f; + } + + roData->unk_00 = CAM_RODATA_UNSCALE(phi_f2 + GET_NEXT_RO_DATA(values)) * focalActorHeight * yNormal; + roData->unk_04 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal; + roData->unk_08 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal; + roData->unk_0C = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + OLib_Vec3fDiffToVecGeo(&sp9C, at, eye); + OLib_Vec3fDiffToVecGeo(&spA4, at, eyeNext); + + sCameraInterfaceFlags = roData->interfaceFlags; + + if (RELOAD_PARAMS(camera)) { + spC8 = focalActorPosRot->pos; + rwData->unk_00 = Camera_GetFloorY(camera, &spC8); + rwData->unk_04 = spA4.yaw; + rwData->unk_06 = 0; + + if (rwData->unk_00 == BGCHECK_Y_MIN) { + rwData->unk_0A = -1; + rwData->unk_00 = focalActorPosRot->pos.y - 1000.0f; + } else if ((focalActorPosRot->pos.y - rwData->unk_00) < focalActorHeight) { + rwData->unk_0A = 1; + } else { + rwData->unk_0A = -1; + } + + yawDiff = BINANG_SUB(BINANG_ROT180(focalActorPosRot->rot.y), spA4.yaw); + rwData->unk_06 = ((yawDiff / 6) / 4) * 3; + + if (roData->interfaceFlags & JUMP2_FLAG_1) { + rwData->unk_08 = 10; + } else { + rwData->unk_08 = 10000; + } + + focalActorPosRot->pos.x -= camera->unk_0F0.x; + focalActorPosRot->pos.y -= camera->unk_0F0.y; + focalActorPosRot->pos.z -= camera->unk_0F0.z; + + rwData->timer = 6; + camera->animState++; + camera->atLerpStepScale = roData->unk_1C; + } + + sp90 = camera->speedRatio * 0.5f; + sp8C = camera->speedRatio * 0.2f; + + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(roData->unk_10, camera->yawUpdateRateInv, sp90, 0.1f); + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(roData->unk_14, camera->yOffsetUpdateRate, sp90, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, sp8C, 0.0001f); + camera->fovUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->fovUpdateRate, camera->speedRatio * .05f, 0.0001f); + camera->rUpdateRateInv = 1800.0f; + + Camera_CalcAtDefault(camera, &spA4, roData->unk_00, 0); + OLib_Vec3fDiffToVecGeo(&spB4, at, eye); + + //! FAKE: Unused + yNormal = roData->unk_04; + + phi_f2 = roData->unk_08 + (roData->unk_08 * roData->unk_0C); + temp_f16 = roData->unk_04 - (roData->unk_04 * roData->unk_0C); + + if (spB4.r > phi_f2) { + spB4.r = phi_f2; + } else if (spB4.r < temp_f16) { + spB4.r = temp_f16; + } + + yawDiff = BINANG_SUB(BINANG_ROT180(focalActorPosRot->rot.y), spB4.yaw); + if (rwData->timer != 0) { + rwData->unk_04 = BINANG_ROT180(focalActorPosRot->rot.y); + rwData->timer--; + spB4.yaw = Camera_ScaledStepToCeilS(rwData->unk_04, spA4.yaw, 0.5f, 5); + } else if (rwData->unk_08 < ABS(yawDiff)) { + temp_t2 = BINANG_ROT180(focalActorPosRot->rot.y); + spB4.yaw = Camera_ScaledStepToFloorS((yawDiff < 0) ? (temp_t2 + rwData->unk_08) : (temp_t2 - rwData->unk_08), + spA4.yaw, 0.1f, 1); + } else { + spB4.yaw = Camera_ScaledStepToCeilS(spB4.yaw, spA4.yaw, 0.25f, 5); + } + + spC8.x = focalActorPosRot->pos.x + (Math_SinS(focalActorPosRot->rot.y) * 25.0f); + spC8.y = focalActorPosRot->pos.y + (focalActorHeight * 2.2f); + spC8.z = focalActorPosRot->pos.z + (Math_CosS(focalActorPosRot->rot.y) * 25.0f); + + yNormal = Camera_GetFloorYNorm(camera, &spBC, &spC8, &sp88); + if (camera->focalActor->bgCheckFlags & 0x10) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f); + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f); + spB4.pitch = Camera_ScaledStepToCeilS(-DEG_TO_BINANG(27.47f), spA4.pitch, 0.2f, 5); + } else if ((yNormal != BGCHECK_Y_MIN) && (focalActorPosRot->pos.y < yNormal)) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f); + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f); + if (camera->unk_0F0.y > 1.0f) { + spB4.pitch = Camera_ScaledStepToCeilS(0x1F4, spA4.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + } + } else if ((focalActorPosRot->pos.y - rwData->unk_00) < focalActorHeight) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->pitchUpdateRateInv, 0.2f, 0.1f); + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(20.0f, camera->rUpdateRateInv, 0.2f, 0.1f); + if (camera->unk_0F0.y > 1.0f) { + spB4.pitch = Camera_ScaledStepToCeilS(0x1F4, spA4.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + } + } else { + camera->pitchUpdateRateInv = 100.0f; + camera->rUpdateRateInv = 100.0f; + } + + spB4.pitch = CLAMP_MAX(spB4.pitch, DEG_TO_BINANG(60.43f)); + spB4.pitch = CLAMP_MIN(spB4.pitch, -DEG_TO_BINANG(60.43f)); + + OLib_AddVecGeoToVec3f(eyeNext, at, &spB4); + sp60.pos = *eyeNext; + + if (func_800CBC84(camera, at, &sp60, 0) != 0) { + spC8 = sp60.pos; + spAC.pitch = 0; + spAC.r = spB4.r; + spAC.yaw = spB4.yaw; + OLib_AddVecGeoToVec3f(&sp60.pos, at, &spAC); + if (func_800CBC84(camera, at, &sp60, 0) != 0) { + *eye = spC8; + } else { + spB4.pitch = Camera_ScaledStepToCeilS(0, spB4.pitch, 0.2f, 5); + OLib_AddVecGeoToVec3f(eye, at, &spB4); + func_800CBFA4(camera, at, eye, 0); + } + } else { + *eye = *eyeNext; + } + + camera->dist = spB4.r; + camera->fov = Camera_ScaledStepToCeilF(roData->unk_18, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + + return true; +} + +/** + * Used for water-based camera settings + * e.g. Gyorg, Pinnacle Rock, whirlpool, water + */ +s32 Camera_Jump3(Camera* camera) { + Vec3f* sp48 = &camera->eye; + Vec3f* sp44 = &camera->at; + Vec3f* sp40 = &camera->eyeNext; + f32 spD0; + f32 spCC; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 phi_f0; + f32 spC0; + Vec3f spB4; + VecGeo spAC; + CameraModeValue* values; + f32 phi_f14; + VecGeo sp9C; + VecGeo sp94; + f32 phi_f2_2; + f32 temp_f0; + f32 temp1; + f32 pad; + Jump3ReadOnlyData* roData = &camera->paramData.jump3.roData; + Jump3ReadWriteData* rwData = &camera->paramData.jump3.rwData; + f32 focalActorHeight; + PosRot focalActorFocus; + f32 sp60; + f32 sp5C; + s32 sp58; + + focalActorHeight = Camera_GetFocalActorHeight(camera); + Actor_GetFocus(&focalActorFocus, camera->focalActor); + sp60 = camera->waterYPos - sp48->y; + + sp58 = false; + + if (RELOAD_PARAMS(camera)) { + rwData->unk_0A = camera->mode; + rwData->timer2 = 0; + } + + if (camera->mode == CAM_MODE_NORMAL) { + if ((camera->focalActor->bgCheckFlags & 0x10) || (rwData->timer2 != 0)) { + if (rwData->unk_0A != 0xF) { + rwData->unk_0A = 0xF; + sp58 = true; + rwData->timer2 = 10; + } + } else if (sp60 < 50.0f) { + if (rwData->unk_0A != 0) { + rwData->unk_0A = 0; + sp58 = true; + } + } else if (Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight) < 11.0f) { + if (rwData->unk_0A != 5) { + rwData->unk_0A = 5; + sp58 = true; + } + } else if ((sp60 > 250.0f) && (rwData->unk_0A != 0x1A)) { + rwData->unk_0A = 0x1A; + sp58 = true; + } + } + + if (rwData->timer2 != 0) { + rwData->timer2--; + } + + OLib_Vec3fDiffToVecGeo(&sp9C, sp44, sp48); + OLib_Vec3fDiffToVecGeo(&sp94, sp44, sp40); + + if (!RELOAD_PARAMS(camera) && !sp58) { + } else { + values = sCameraSettings[camera->setting].cameraModes[rwData->unk_0A].values; + + sp5C = 0.8f - (-0.2f * (68.0f / focalActorHeight)); + spD0 = focalActorHeight * 0.01f * sp5C; + + roData->unk_00 = GET_NEXT_RO_DATA(values) * spD0; + roData->unk_04 = GET_NEXT_RO_DATA(values) * spD0; + roData->unk_08 = GET_NEXT_RO_DATA(values) * spD0; + roData->unk_20 = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + rwData->unk_10 = 0x1000; + // fallthrough + case 10: + case 20: + rwData->unk_00 = camera->focalActorFloorHeight; + D_801EDC30[camera->camId].yaw = D_801EDC30[camera->camId].pitch = D_801EDC30[camera->camId].unk_64 = 0; + rwData->timer1 = 10; + D_801EDC30[camera->camId].swingUpdateRate = roData->unk_0C; + camera->animState++; + D_801EDC30[camera->camId].timer = 0; + break; + + default: + if (rwData->timer1 != 0) { + rwData->timer1--; + } + break; + } + + spC0 = focalActorFocus.pos.y - focalActorPosRot->pos.y; + spB4 = *sp48; + + spD0 = camera->speedRatio * 0.5f; + spCC = camera->speedRatio * 0.2f; + + temp_f0 = (D_801EDC30[camera->camId].unk_64 == 1) ? 0.5f : spD0; + + if (D_801EDC30[camera->camId].timer != 0) { + camera->yawUpdateRateInv = + Camera_ScaledStepToCeilF((D_801EDC30[camera->camId].swingUpdateRate + D_801EDC30[camera->camId].timer * 2), + camera->yawUpdateRateInv, spD0, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF((40.0f + D_801EDC30[camera->camId].timer * 2), + camera->pitchUpdateRateInv, spCC, 0.1f); + D_801EDC30[camera->camId].timer--; + } else { + camera->yawUpdateRateInv = Camera_ScaledStepToCeilF(D_801EDC30[camera->camId].swingUpdateRate, + camera->yawUpdateRateInv, temp_f0, 0.1f); + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(40.0f, camera->pitchUpdateRateInv, spCC, 0.1f); + } + + if (roData->interfaceFlags & JUMP3_FLAG_7) { + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.01f, camera->yOffsetUpdateRate, spD0, 0.0001f); + sp5C = sqrtf((camera->unk_0F0.x * camera->unk_0F0.x) + (camera->unk_0F0.z * camera->unk_0F0.z)) / + Camera_GetRunSpeedLimit(camera); + camera->speedRatio = OLib_ClampMaxDist(sp5C / Camera_GetRunSpeedLimit(camera), 1.8f); + spCC = camera->speedRatio * 0.2f; + } else { + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->yOffsetUpdateRate, spD0, 0.0001f); + } + + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.05f, camera->xzOffsetUpdateRate, spCC, 0.0001f); + camera->fovUpdateRate = + Camera_ScaledStepToCeilF(0.050f, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f); + + if (sp60 < 50.0f) { + sp5C = camera->waterYPos - spC0; + + Camera_CalcAtForScreen(camera, &sp94, roData->unk_00, &sp5C, + ((sp60 < 0.0f) ? 1.0f : 1.0f - (sp60 / 50.0f)) * 50.0f); + } else { + Camera_CalcAtDefault(camera, &sp94, roData->unk_00, roData->interfaceFlags); + } + + OLib_Vec3fDiffToVecGeo(&spAC, sp44, sp40); + spAC.r = Camera_ClampDist1(camera, spAC.r, roData->unk_04, roData->unk_08, rwData->timer1); + camera->dist = spAC.r; + + if (!(Camera_fabsf(focalActorPosRot->pos.y - camera->focalActorFloorHeight) < 10.0f) && + !(Camera_fabsf(focalActorFocus.pos.y - camera->waterYPos) < 50.f)) { + camera->pitchUpdateRateInv = 100.0f; + } + + if (roData->interfaceFlags & JUMP3_FLAG_5) { + spD0 = CLAMP_MAX(camera->speedRatio * 1.3f, 0.6f); + + //! FAKE: spCC = + spAC.pitch = Camera_ScaledStepToCeilS( + (spAC.pitch * spD0) + (roData->unk_20 * (1.0f - spD0)), sp94.pitch, + 1.0f / (spCC = ((camera->pitchUpdateRateInv + 1.0f) - (camera->pitchUpdateRateInv * spD0))), 5); + } else if (D_801EDC30[camera->camId].unk_64 == 1) { + spAC.yaw = + Camera_ScaledStepToCeilS(D_801EDC30[camera->camId].yaw, sp94.yaw, 1.0f / camera->yawUpdateRateInv, 5); + + // Bug? Should be pitchUpdateRateInv + spAC.pitch = + Camera_ScaledStepToCeilS(D_801EDC30[camera->camId].pitch, sp94.pitch, 1.0f / camera->yawUpdateRateInv, 5); + } else if (roData->interfaceFlags & (JUMP3_FLAG_7 | JUMP3_FLAG_3)) { + spAC.yaw = Camera_CalcDefaultYaw(camera, sp94.yaw, focalActorPosRot->rot.y, roData->unk_14, 0.0f); + + spD0 = CLAMP_MAX(camera->speedRatio * 1.3f, 1.0f); + + //! FAKE: spCC = + spAC.pitch = Camera_ScaledStepToCeilS( + (spAC.pitch * spD0) + (roData->unk_20 * (1.0f - spD0)), sp94.pitch, + 1.0f / (spCC = (camera->pitchUpdateRateInv + 1.0f) - (camera->pitchUpdateRateInv * spD0)), 5); + } else { + spAC.yaw = Camera_CalcDefaultYaw(camera, sp94.yaw, focalActorPosRot->rot.y, roData->unk_14, 0.0f); + spAC.pitch = Camera_CalcDefaultPitch(camera, sp94.pitch, roData->unk_20, 0); + } + + if (spAC.pitch > DEG_TO_BINANG(79.655f)) { + spAC.pitch = DEG_TO_BINANG(79.655f); + } + + if (spAC.pitch < -DEG_TO_BINANG(29.995f)) { + spAC.pitch = -DEG_TO_BINANG(29.995f); + } + + OLib_AddVecGeoToVec3f(sp40, sp44, &spAC); + + if ((camera->status == CAM_STATUS_ACTIVE) && !(roData->interfaceFlags & JUMP3_FLAG_6)) { + if (func_800CBA7C(camera) == 0) { + Camera_CalcDefaultSwing(camera, &spAC, &sp9C, roData->unk_04, roData->unk_0C, &D_801EDC30[camera->camId], + &rwData->unk_10); + } + + if (roData->interfaceFlags & JUMP3_FLAG_2) { + camera->inputDir.x = -sp9C.pitch; + camera->inputDir.y = sp9C.yaw + 0x8000; + camera->inputDir.z = 0; + } else { + OLib_Vec3fDiffToVecGeo(&spAC, sp48, sp44); + camera->inputDir.x = spAC.pitch; + camera->inputDir.y = spAC.yaw; + camera->inputDir.z = 0; + } + } else { + D_801EDC30[camera->camId].swingUpdateRate = roData->unk_0C; + D_801EDC30[camera->camId].unk_64 = 0; + sUpdateCameraDirection = false; + *sp48 = *sp40; + } + + camera->fov = Camera_ScaledStepToCeilF(roData->unk_18, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, .5f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->unk_1C); + + return 1; +} + +s32 Camera_Jump4(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Jump0(Camera* camera) { + return Camera_Noop(camera); +} + +#ifdef NON_EQUIVALENT +s32 Camera_Battle1(Camera* camera) { + Battle1ReadOnlyData* roData = &camera->paramData.batt1.roData; + Battle1ReadWriteData* rwData = &camera->paramData.batt1.rwData; + Vec3f sp120; + Vec3f sp114; + f32 sp104; + f32 spFC; + f32 spF8; + f32 spF8_2; + f32 spF4; + s32 spF0; // bool + f32 spEC; + Vec3f spC4; + VecGeo spBC; + VecGeo spB4; + VecGeo spAC; + VecGeo spA4; + VecGeo sp9C; + VecGeo sp94; + PosRot* sp8C; + s16 sp8A; + s16 sp88; + s16 sp86; + s16 sp84; + f32 sp80; + f32 sp7C; + f32 sp78; + f32 sp68; + s16 sp5E; + s16 sp5C; + Vec3f* sp50; + Vec3f* sp4C; + Vec3f* sp48; + PosRot* sp40; + + f32 temp_f12; + f32 temp_f14; + f32 temp_f2_3; + s16 temp_v0_5; + s16 temp_v0_6; + s32 temp_f4; + f32 phi_f0_3; + f32 phi_f12; + + f32 new_var; + f32 new_var2; + f32 new_var3; + f32 new_var5; + f32 new_var4; + + sp50 = &camera->eye; + sp4C = &camera->at; + sp48 = &camera->eyeNext; + sp40 = &camera->targetPosRot; + + spF0 = false; + sp8C = &camera->focalActor->focus; + sp68 = Camera_GetFocalActorHeight(camera); + + if ((camera->animState != 0) && (camera->animState != 0xA) && (camera->animState != 0x14)) { + } else { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->unk_00 = GET_NEXT_RO_DATA(values) * 0.01f * sp68 * (0.8f - ((68.0f / sp68) * -0.2f)); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_0C = 80.0f - (80.0f - roData->unk_0C); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_10 = 0.0f - (0.0f - roData->unk_10); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->unk_14 = 40.0f - (40.0f - roData->unk_14); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_18 = 20.0f - (20.0f - roData->unk_18); + roData->unk_1C = GET_NEXT_RO_DATA(values) * 0.01f; + roData->unk_1C = 1.0f - (1.0f - roData->unk_1C); + roData->unk_20 = GET_NEXT_RO_DATA(values); + roData->unk_24 = GET_NEXT_RO_DATA(values) * 0.01f; + roData->unk_24 = 1.0f - (1.0f - roData->unk_24); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + roData->unk_28 = GET_NEXT_RO_DATA(values) * 0.01f; + roData->unk_28 = 0.2f - (0.2f - roData->unk_28); + roData->unk_2C = GET_NEXT_RO_DATA(values) * 0.01f; + if ((camera->animState != 0) && (camera->animState != 0xA) && (camera->animState != 0x14)) { + } else { + rwData->unk_18 = 0x28; + camera->pitchUpdateRateInv = 9.0f; + } + } + + sp80 = roData->unk_14; + sp7C = roData->unk_18; + sp78 = roData->unk_20; + + if (Camera_IsChargingSwordOrDekuFlowerDive(camera)) { + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(18.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + camera->yOffsetUpdateRate = Camera_ScaledStepToCeilF(0.2f, camera->yOffsetUpdateRate, 0.5f, 0.0001f); + camera->xzOffsetUpdateRate = Camera_ScaledStepToCeilF(0.2f, camera->xzOffsetUpdateRate, 0.5f, 0.0001f); + if (rwData->unk_18 >= -0x13) { + rwData->unk_18--; + } else { + sp80 = 50.0f; + sp7C = 40.0f; + sp78 = 60.0f; + } + } else { + if (rwData->unk_18 < 0) { + sp80 = 50.0f; + sp7C = 40.0f; + sp78 = 60.0f; + rwData->unk_18++; + } else { + rwData->unk_18 = 0x28; + camera->pitchUpdateRateInv = Camera_ScaledStepToCeilF(9.0f, camera->pitchUpdateRateInv, 0.5f, 0.1f); + camera->yOffsetUpdateRate = + Camera_ScaledStepToCeilF(0.6f, camera->yOffsetUpdateRate, camera->speedRatio * 0.5f, 0.0001f); + camera->xzOffsetUpdateRate = + Camera_ScaledStepToCeilF(0.6f, camera->xzOffsetUpdateRate, camera->speedRatio * 0.2f, 0.0001f); + } + } + + camera->fovUpdateRate = + Camera_ScaledStepToCeilF(0.050f, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f); + sp68 += roData->unk_00; + OLib_Vec3fDiffToVecGeo(&sp9C, sp4C, sp50); + OLib_Vec3fDiffToVecGeo(&sp94, sp4C, sp48); + if ((camera->target == NULL) || (camera->target->update == NULL)) { + camera->target = NULL; + Camera_ChangeMode(camera, CAM_MODE_TARGET); + return true; + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + if ((camera->animState == 0) || (camera->animState == 0xA) || (camera->animState == 0x14)) { + rwData->unk_10 = 0; + rwData->unk_1A = 0; + rwData->unk_08 = camera->target; + camera->animState++; + rwData->unk_16 = 7; + rwData->unk_12 = sp9C.yaw; + rwData->unk_14 = sp9C.pitch; + rwData->unk_00 = sp9C.r; + rwData->unk_04 = camera->focalActorPosRot.pos.y - camera->unk_0F0.y; + if ((2.0f * roData->unk_04) < camera->dist) { + camera->dist = 2.0f * roData->unk_04; + sp94.r = camera->dist; + sp9C.r = sp94.r; + OLib_AddVecGeoToVec3f(sp50, sp4C, &sp9C); + *sp48 = *sp50; + } + } + + if (camera->status == CAM_STATUS_ACTIVE) { + sUpdateCameraDirection = true; + camera->inputDir.x = -sp9C.pitch; + camera->inputDir.y = sp9C.yaw + 0x8000; + camera->inputDir.z = 0; + } + + if (func_800CB950(camera)) { + rwData->unk_04 = camera->focalActorPosRot.pos.y; + sp84 = 0; + } else { + sp84 = 1; + } + + if (rwData->unk_16 == 0) { + camera->atLerpStepScale = Camera_ClampLerpScale(camera, sp84 ? roData->unk_28 : roData->unk_24); + } + + Actor_GetFocus(&sp40->pos, camera->target); + + if (rwData->unk_08 != camera->target) { + camera->animState = 0; + return true; + } + + sp120 = camera->focalActorPosRot.pos; + sp120.y += sp68; + OLib_Vec3fDiffToVecGeo(&spA4, &sp120, &sp40->pos); + sp104 = func_800CD6CC(camera->target); + if (PREG(86) + 800.0f < sp104) { + sp104 = PREG(86) + 800.0f; + } + + // new_var5 = sp104; // TODO: Fake temp but helps when used? + // sp104 = new_var5; + + // Above is down to SP and Floats + + if ((sp104 < spA4.r) || Camera_IsChargingSwordOrDekuFlowerDive(camera)) { + spEC = 1.0f; + spF8 = 10.0f; + // dummy:; // Helps? + // sp80 = roData->unk_14; // Fake & Non-equivalent but helps? + } else { + spEC = spA4.r / sp104; + spF8 = 2.0f; + } + // spF8 should be set with swc1 twice, not once + + // sp94 is loading in too early + Camera_CalcAtForEnemyLockOn(camera, &sp94.r, sp40, roData->unk_00, roData->unk_2C, 1.0f - spEC, &rwData->unk_04, + &spA4, + (sp84 ? (BATTLE1_FLAG_7 | BATTLE1_FLAG_0) : BATTLE1_FLAG_0) | roData->interfaceFlags); + + sp88 = spA4.yaw; + OLib_Vec3fDiffToVecGeo(&spBC, sp4C, sp48); + spF4 = roData->unk_04 + ((roData->unk_08 - roData->unk_04) * spEC); + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(spF8, camera->rUpdateRateInv, 0.5f, 0.1f); + spBC.r = camera->dist = Camera_ScaledStepToCeilF(spF4, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f); + OLib_Vec3fDiffToVecGeo(&spAC, sp4C, &sp40->pos); + + spAC.r = spBC.r - (((spAC.r >= spBC.r) ? spBC.r : spAC.r) * 0.5f); + + if (rwData->unk_1A & 0x1000) { + spFC = 15.0f; + } else { + spFC = roData->unk_0C + ((roData->unk_10 - roData->unk_0C) * (1.1f - spEC)); + } + spBC.yaw = sp94.yaw; + temp_v0_5 = (sp94.yaw + 0x8000); + temp_v0_5 = spAC.yaw - temp_v0_5; + if (rwData->unk_16 != 0) { + if (rwData->unk_16 > 0) { + sp86 = rwData->unk_16 - 1; + OLib_Vec3fDiffToVecGeo(&spB4, sp4C, sp50); + spB4.yaw = sp88 + 0x8000; + new_var = (rwData->unk_00 - spB4.r) * 0.16666667f; + sp8A = (s16)(rwData->unk_12 - spB4.yaw) * 0.16666667f; + sp88 = (s16)(rwData->unk_14 - spB4.pitch) * 0.16666667f; + spBC.r = Camera_ScaledStepToCeilF((sp86 * new_var) + spB4.r, sp9C.r, 0.5f, + 1.0f); // TODO: extra float calcs going on here + spBC.yaw = Camera_ScaledStepToCeilS(spB4.yaw + (sp8A * sp86), sp9C.yaw, 0.5f, 5); + spBC.pitch = Camera_ScaledStepToCeilS(spB4.pitch + (sp88 * sp86), sp9C.pitch, 0.5f, 5); + } else { + spF0 = true; + } + rwData->unk_16--; + } else { + // s32 phi_v0_2 = ABS(temp_v0_5); + temp_f4 = (s16)((spFC * 182.04167f) + .5f); + if ((temp_f4 < ABS(temp_v0_5)) && (sp84 == 0)) { + + sp8A = temp_v0_5; + sp104 = temp_v0_5 * 0.00549325f; + + temp_f2_3 = ((OLib_ClampMaxDist(spAC.r, spBC.r) / spBC.r) * ((spFC + 10.0f) - spFC)) + spFC; + temp_f12 = (SQ(temp_f2_3) - 2.0f) / (temp_f2_3 - 360.0f); + new_var3 = temp_f12 * sp104; + temp_f14 = SQ(sp104) / (new_var3 + (2.0f - (360.0f * temp_f12))); + + if (sp8A >= 0) { + sp88 = CAM_DEG_TO_BINANG(temp_f14); + } else { + sp88 = -CAM_DEG_TO_BINANG(temp_f14); + } + + spBC.yaw = (s16)(sp94.yaw + 0x8000) + (s16)(sp88 + 0x8000); + } else { + new_var2 = (1.0f - camera->speedRatio) * 0.05f; + if (temp_v0_5 >= 0) { + sp88 = temp_f4 & 0xFFFFu; // TODO: Is this needed? + } else { + sp88 = -temp_f4; + } + spBC.yaw = sp94.yaw - (s16)((sp88 - temp_v0_5) * new_var2); + } + } + + if (spF0 == false) { + new_var4 = spAC.pitch * roData->unk_1C; + temp_v0_6 = ((s16)(((((sp7C - sp80) * spEC) + sp80) * 182.04167f) + .5f) - + (s16)((spA4.pitch * (0.5f + (spEC * 0.5f))) + 0.5f)); + temp_v0_6 += (s16)new_var4; + + if (temp_v0_6 < -0x2AA8) { + temp_v0_6 = -0x2AA8; + } else if (temp_v0_6 > 0x2AA8) { + temp_v0_6 = 0x2AA8; + } + + spBC.pitch = Camera_ScaledStepToCeilS(temp_v0_6, sp94.pitch, 1.0f / camera->pitchUpdateRateInv, 5); + OLib_AddVecGeoToVec3f(sp48, sp4C, &spBC); + spC4 = *sp48; + if (camera->status == CAM_STATUS_ACTIVE) { + if (!(roData->interfaceFlags & BATTLE1_FLAG_4)) { + if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & BATTLE1_FLAG_0)) { + if (func_800CBC84(camera, sp4C, &spC4, 0) != 0) { + rwData->unk_1A |= 0x1000; + } else { + rwData->unk_1A &= ~0x1000; + } + } else if (roData->interfaceFlags & BATTLE1_FLAG_1) { + func_800CBC84(camera, sp4C, &spC4, 3); + } else { + OLib_Vec3fDistNormalize(&sp114, sp4C, &spC4); + spC4.x -= sp114.x; + spC4.y -= sp114.y; + spC4.z -= sp114.z; + } + *sp50 = spC4; + ; + rwData->unk_1A &= ~0x10; + } else if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & BATTLE1_FLAG_0)) { + if (func_800CBC84(camera, sp4C, &spC4, 0) != 0) { + rwData->unk_1A |= 0x1000; + spF8 = OLib_Vec3fDist(sp4C, sp8C); + spF4 = OLib_Vec3fDist(sp4C, &spC4); + phi_f0_3 = (rwData->unk_1A & 0x10) ? 40.0f : 0.0f; + spF8 = spF8 + phi_f0_3; + Actor_GetScreenPos(camera->play, camera->focalActor, &sp5E, &sp5C); + if ((spF4 < spF8) || ((sp5E >= 0) && (sp5E < 0x141) && (sp5C >= 0) && (sp5C < 0xF1))) { + rwData->unk_1A |= 0x10; + spB4.yaw = spA4.yaw + 0x8000; + spB4.pitch = -spA4.pitch; + spB4.r = 40.0f; + sp114 = sp8C->pos; + sp114.y += 40.0f; + OLib_AddVecGeoToVec3f(&sp120, &sp114, &spB4); + Camera_ScaledStepToCeilVec3f(&sp120, sp50, 0.15f, 0.15f, 0.2f); + } else if (rwData->unk_1A & 0x10) { + if (OLib_Vec3fDist(&spC4, sp50) < 20.0f) { + rwData->unk_1A &= ~0x10; + *sp50 = spC4; + } else { + Camera_ScaledStepToCeilVec3f(&spC4, sp50, 0.15f, 0.15f, 0.2f); + } + } else { + rwData->unk_1A &= ~0x10; + *sp50 = spC4; + } + dummy:; // TODO: Is Needed? + } else { + if (rwData->unk_1A & 0x10) { + if (OLib_Vec3fDist(&spC4, sp50) < 20.0f) { + rwData->unk_1A &= ~0x10; + *sp50 = spC4; + } else { + Camera_ScaledStepToCeilVec3f(&spC4, sp50, 0.15f, 0.15f, 0.2f); + } + } else { + rwData->unk_1A &= ~0x10; + *sp50 = spC4; + } + rwData->unk_1A &= ~0x1000; + } + } else if (roData->interfaceFlags & BATTLE1_FLAG_1) { + rwData->unk_1A &= ~0x10; + if (func_800CBC84(camera, sp4C, &spC4, 3) != 0) { + *sp50 = spC4; + } else { + *sp50 = spC4; + } + } else { + rwData->unk_1A &= ~0x10; + OLib_Vec3fDistNormalize(&sp114, sp4C, &spC4); + spC4.x -= sp114.x; + spC4.y -= sp114.y; + spC4.z -= sp114.z; + *sp50 = spC4; + } + } else { + rwData->unk_1A &= ~0x10; + *sp50 = *sp48; + } + } + + if (rwData->unk_16 != 0) { + sp88 = 0; + } else { + sp88 = (s16)(sp94.yaw - spBC.yaw) * 0.50f; + } + + camera->roll = Camera_ScaledStepToCeilS(sp88, camera->roll, 0.06f, 5); + if (func_800CBAAC(camera) != 0) { + phi_f12 = ((camera->play->state.frames & 8) != 0) ? roData->unk_20 - (roData->unk_20 * 0.5f) : roData->unk_20; + } else { + phi_f12 = ((gSaveContext.save.saveInfo.playerData.health <= 16) ? 0.8f : 1.0f) * (sp78 - (sp78 * 0.05f * spEC)); + } + camera->fov = Camera_ScaledStepToCeilF(phi_f12, camera->fov, camera->fovUpdateRate, 0.1f); + + return true; +} +#else #pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Battle1.s") +#endif -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Battle2.s") +s32 Camera_Battle2(Camera* camera) { + return Camera_Noop(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Battle3.s") +s32 Camera_Battle3(Camera* camera) { + return Camera_Noop(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Battle4.s") +s32 Camera_Battle4(Camera* camera) { + return Camera_Noop(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Battle0.s") +s32 Camera_Battle0(Camera* camera) { + return Camera_Noop(camera); +} +/** + * Used for following a secondary target such as zora fins or a z-target + */ +// Very non-equivalent, many fakes. May need to restart from scratch (mips2c) +#ifdef NON_EQUIVALENT +s32 Camera_KeepOn1(Camera* camera) { + f32 pad1; + f32* pad2; + Vec3f* sp48 = &camera->eye; + Vec3f* sp44 = &camera->at; + Vec3f* sp40 = &camera->eyeNext; + Vec3f sp130; + Vec3f sp124; + Vec3f sp118; + f32 sp114; + PosRot* sp3C = &camera->focalActorPosRot; + PosRot* sp30 = &camera->targetPosRot; + f32 sp104; + f32 temp_f2_3; + f32 new_var; + f32 spFC; + f32 spF8; + f32 spF4; + s16 spF2; + s16 spF0; + VecGeo spE8; + VecGeo spE0; + VecGeo spD8; + VecGeo spD0; + VecGeo spC8; + VecGeo spC0; + f32 new_var2; + s32 new_var3; + f32 temp_f0; + Vec3f spA8; + PosRot* spA4; + CameraCollision sp7C; + + s32 sp78; + f32 sp74; + s16 sp72; + s16 sp70; + f32 sp60; + s16 sp56; + s16 sp54; + + s16 phi_v1_3; + s16 phi_a0; + KeepOn1ReadOnlyData* roData = &camera->paramData.keep1.roData; + KeepOn1ReadWriteData* rwData = &camera->paramData.keep1.rwData; + s16 temp_v0_3; + s16 new_var4; + + spA4 = &camera->focalActor->focus; + //! FAKE + if (temp_v0_3) {} + sp78 = 0; + temp_f0 = Camera_GetFocalActorHeight(camera); + // temp_a1 = camera->target; + + if ((camera->target == NULL) || (camera->target->update == NULL)) { + camera->target = NULL; + Camera_ChangeMode(camera, CAM_MODE_TARGET); + return 1; + } + + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->unk_00 = GET_NEXT_SCALED_RO_DATA(values) * temp_f0 * (0.8f - ((68.0f / temp_f0) * -0.2f)); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->unk_14 = 40.0f - (40.0f - roData->unk_14); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_18 = 20.0f - (20.0f - roData->unk_18); + // roData->unk_18 = roData->unk_18; // TODO: Fake + // if (!roData->unk_08) {} + roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_1C = 1.000f - (1.00f - roData->unk_1C); // TODO: Necessary? + roData->unk_20 = GET_NEXT_RO_DATA(values); + roData->unk_24 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_24 = 1.0f - (1.0f - roData->unk_24); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + roData->unk_28 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_28 = 0.2f - (0.2f - roData->unk_28); + } + + sp60 = temp_f0; + sp114 = roData->unk_00; // TODO: likely fake temp + sp60 += sp114; + OLib_Vec3fDiffToVecGeo(&spC8, sp44, sp48); + OLib_Vec3fDiffToVecGeo(&spC0, sp44, sp40); + sCameraInterfaceFlags = roData->interfaceFlags; + + if (RELOAD_PARAMS(camera)) { + camera->animState++; + rwData->unk_18 = 0; + rwData->unk_10 = 0; + rwData->unk_04 = 0.0f; + rwData->unk_0C = camera->target; + rwData->unk_16 = 7; + rwData->unk_12 = spC8.yaw; + rwData->unk_14 = spC8.pitch; + rwData->unk_00 = spC8.r; + rwData->unk_08 = sp3C->pos.y - camera->unk_0F0.y; + if ((2.0f * roData->unk_04) < camera->dist) { + camera->dist = 2.0f * roData->unk_04; + spC0.r = camera->dist; + spC8.r = spC0.r; + OLib_AddVecGeoToVec3f(sp48, sp44, &spC8); + *sp40 = *sp48; + } + } + + if (camera->status == CAM_STATUS_ACTIVE) { + sUpdateCameraDirection = true; + camera->inputDir.x = -spC8.pitch; + camera->inputDir.y = spC8.yaw + 0x8000; + camera->inputDir.z = 0; + } + + if (func_800CB950(camera)) { + rwData->unk_08 = sp3C->pos.y; + } + + sp114 = roData->unk_04; + + if (camera->target->id != ACTOR_EN_BOOM) { + Actor_GetWorldPosShapeRot(sp30, camera->target); + Actor_GetFocus(&spA8, camera->target); + camera->targetPosRot.pos.y = spA8.y; + } else { + Actor_GetFocus(sp30, camera->target); + } + if (rwData->unk_0C != camera->target) { + rwData->unk_0C = camera->target; + camera->atLerpStepScale = 0.0f; + } + + camera->yOffsetUpdateRate = + Camera_ScaledStepToCeilF(1.0f, camera->yOffsetUpdateRate, camera->speedRatio * 0.5f, 0.0001f); + camera->xzOffsetUpdateRate = + Camera_ScaledStepToCeilF(1.0f, camera->xzOffsetUpdateRate, camera->speedRatio * 0.2f, 0.0001f); + // TODO: No f on 0.05? + camera->fovUpdateRate = Camera_ScaledStepToCeilF(0.05, camera->fovUpdateRate, camera->speedRatio * 0.05f, 0.0001f); + + if (func_800CB950(camera)) { + rwData->unk_08 = sp3C->pos.y; + sp70 = false; + } else { + sp70 = true; + } + + Camera_CalcAtForFriendlyLockOn(camera, &spC0, sp30, roData->unk_00, roData->unk_08, &rwData->unk_08, &spD0, + roData->interfaceFlags | (sp70 ? KEEPON1_FLAG_7 : 0)); + sp124 = sp3C->pos; + sp124.y += sp60; + OLib_Vec3fDiffToVecGeo(&spD0, &sp124, sp30); + + if (sp114 < spD0.r) { + sp74 = 1.0f; + } else { + sp74 = spD0.r / sp114; + } + + OLib_Vec3fDiffToVecGeo(&spE8, sp44, sp40); + + if (spE8.r < roData->unk_04) { + sp114 = roData->unk_04; + spF8 = 20.0f; + } else if (roData->unk_08 < spE8.r) { + sp114 = roData->unk_08; + spF8 = 20.0f; + } else { + sp114 = spE8.r; + spF8 = 1.0f; + } + + camera->rUpdateRateInv = Camera_ScaledStepToCeilF(spF8, camera->rUpdateRateInv, 0.5f, 0.1f); + camera->dist = Camera_ScaledStepToCeilF(sp114, camera->dist, 1.0f / camera->rUpdateRateInv, 0.1f); + spF8 = camera->dist; + spE8.r = camera->dist; + sp118 = sp30->pos; + OLib_Vec3fDiffToVecGeo(&spD8, sp44, &sp118); + //! FAKE + if (1) {} + if (1) {} + if (1) {} // TODO: Is needed? + pad1 = spD8.r; // TODO: Fake temp? + spD8.r = spF8 - (((pad1 <= spF8) ? spD8.r : spF8) * .5f); + camera->dist = Camera_ScaledStepToCeilF(pad1, camera->dist, 0.06f, 0.1f); + spE8.r = camera->dist; + spFC = roData->unk_0C + ((roData->unk_10 - roData->unk_0C) * (1.1f - sp74)); + spE8.yaw = spC0.yaw; + temp_v0_3 = (s16)(spD8.yaw - (s16)(spC0.yaw + 0x8000)); + if (rwData->unk_16 != 0) { + if (rwData->unk_16 > 0) { + sp72 = rwData->unk_16 - 1; + spF2 = spD0.yaw; + OLib_Vec3fDiffToVecGeo(&spD0, sp44, sp48); + spD0.yaw = (s16)(spF2 + 0x8000); + sp60 = (rwData->unk_00 - spD0.r) * 0.16666667f; + spF2 = (s16)(rwData->unk_12 - (s16)(spF2 + 0x8000)) * 0.16666667f; + spF0 = ((s16)(rwData->unk_14 - (s64)spD0.pitch)); // TODO: s16 cast on F0 + spF0 = (s16)(spF0 * 0.16666667f); + spE8.r = Camera_ScaledStepToCeilF(spD0.r + (sp60 * sp72), spC8.r, .5f, 0.1f); + spE8.yaw = Camera_ScaledStepToCeilS(spD0.yaw + (spF2 * sp72), spC8.yaw, .5f, 5); + spE8.pitch = Camera_ScaledStepToCeilS(spD0.pitch + (spF0 * sp72), spC8.pitch, .5f, 5); + } + sp78 = 1; + rwData->unk_16--; + } else { + new_var3 = ABS(temp_v0_3); // TODO: Fake temp? + if ((s16)((spFC * 182.04167f) + .5f) < new_var3) { + spF2 = temp_v0_3; + sp104 = temp_v0_3 * 0.00549325f; + temp_f2_3 = ((OLib_ClampMaxDist(spD8.r, spE8.r) / spE8.r) * ((spFC + 10.0f) - spFC)) + spFC; + pad2 = &sp104; // TODO: Fake temp + temp_f2_3 = ((temp_f2_3 * temp_f2_3) - 2.0f) / (temp_f2_3 - 360.0f); + temp_f2_3 = (sp104 * (*pad2)) / ((temp_f2_3 * (*pad2)) + (2.0f - (360.0f * temp_f2_3))); + + if (spF2 >= 0) { + phi_v1_3 = (s16)((temp_f2_3 * 182.04167f) + .5f); + } else { + phi_v1_3 = -(s16)((temp_f2_3 * 182.04167f) + .5f); + } + spE8.yaw = (s16)(spC0.yaw + 0x8000) + (s16)(phi_v1_3 + 0x8000); + } else { + new_var = (1.0f - camera->speedRatio) * 0.05f; // TODO: Fake temp? + phi_v1_3 = (temp_v0_3 >= 0) ? CAM_DEG_TO_BINANG(spFC) : -CAM_DEG_TO_BINANG(spFC); + //! FAKE + if (phi_a0) {} // TODO: Fake to shaft a registers + spE8.yaw = (s16)(spC0.yaw - (s16)((phi_v1_3 - temp_v0_3) * new_var)); + } + } + + //! FAKE + if (!spF0) {} // TODO: Is needed? + if (sp78 == 0) { + // TODO: extra 0 on 0.050f needed? + phi_a0 = (s16)(((roData->unk_14 + ((roData->unk_18 - roData->unk_14) * sp74)) * 182.04167f) + .5f); + phi_a0 -= (s16)((spD0.pitch * (0.5f + (sp74 * 0.5f))) + 0.5f); + //! FAKE + if (1) {} // TODO: Needed? + sp60 = spD8.pitch * roData->unk_1C; // TODO: Fake sp60 temp? + phi_a0 += (s16)sp60; + + if (phi_a0 < -0x3200) { + phi_a0 = -0x3200; + } else if (phi_a0 > 0x3200) { + phi_a0 = 0x3200; + } + + spE8.pitch = Camera_ScaledStepToCeilS(phi_a0, spC0.pitch, 0.11111111f, 5); + OLib_AddVecGeoToVec3f(sp40, sp44, &spE8); + sp7C.pos = *sp40; + if (camera->status == CAM_STATUS_ACTIVE) { + if (!(roData->interfaceFlags & KEEPON1_FLAG_4)) { + if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & KEEPON1_FLAG_0)) { + if (func_800CBC84(camera, sp44, &sp7C, 0) != 0) { + rwData->unk_18 |= 0x1000; + } else { + rwData->unk_18 &= ~0x1000; + } + } else if (roData->interfaceFlags & KEEPON1_FLAG_1) { + func_800CBC84(camera, sp44, &sp7C, 3); + } else { + OLib_Vec3fDistNormalize(&sp130, sp44, &sp7C.pos); + sp7C.pos.x -= sp130.x; + sp7C.pos.y -= sp130.y; + sp7C.pos.z -= sp130.z; + } + *sp48 = sp7C.pos; + rwData->unk_18 &= ~0x10; + } else if ((camera->play->envCtx.skyboxDisabled == 0) || (roData->interfaceFlags & KEEPON1_FLAG_0)) { + if (func_800CBC84(camera, sp44, &sp7C, 0) != 0) { + rwData->unk_18 |= 0x1000; + spF8 = OLib_Vec3fDist(sp44, spA4); + spF4 = OLib_Vec3fDist(sp44, &sp7C.pos); + spF8 += (rwData->unk_18 & 0x10) ? 40 : 0.0f; // TODO: 40.0f? + Actor_GetScreenPos(camera->play, camera->focalActor, &sp56, &sp54); + if ((spF4 < spF8) || ((sp56 >= 0) && (sp56 <= 320) && (sp54 >= 0) && (sp54 <= 240))) { + rwData->unk_18 |= 0x10; + spE0.yaw = (s16)(spD0.yaw + 0x8000); + spE0.pitch = -spD0.pitch; + spE0.r = 40.0f; + sp130 = spA4->pos; + sp130.y += 40.0f; + OLib_AddVecGeoToVec3f(&sp124, &sp130, &spE0); + Camera_ScaledStepToCeilVec3f(&sp124, sp48, 0.15f, 0.15f, 0.2f); + } else if (rwData->unk_18 & 0x10) { + if (OLib_Vec3fDist(&sp7C.pos, sp48) < 20.0f) { + rwData->unk_18 &= ~0x10; + *sp48 = sp7C.pos; + } else { + Camera_ScaledStepToCeilVec3f(&sp7C.pos, sp48, 0.15f, 0.15f, 0.2f); + } + } else { + rwData->unk_18 &= ~0x10; + *sp48 = sp7C.pos; + } + dummy:; // TODO: Is this needed? + } else { + if (rwData->unk_18 & 0x10) { + if (OLib_Vec3fDist(&sp7C.pos, sp48) < 20.0f) { + rwData->unk_18 &= ~0x10; + *sp48 = sp7C.pos; + } else { + Camera_ScaledStepToCeilVec3f(&sp7C.pos, sp48, 0.15f, 0.15f, 0.2f); + } + } else { + rwData->unk_18 &= ~0x10; + *sp48 = sp7C.pos; + // if (sp104) {} // TODO: Is this needed? + } + rwData->unk_18 &= ~0x1000; + } + } else if (roData->interfaceFlags & KEEPON1_FLAG_1) { + rwData->unk_18 &= ~0x10; + if (func_800CBC84(camera, sp44, &sp7C, 3) != 0) { + *sp48 = sp7C.pos; + } else { + *sp48 = sp7C.pos; + ; + } + } else { + rwData->unk_18 &= ~0x10; + OLib_Vec3fDistNormalize(&sp130, sp44, &sp7C.pos); + sp7C.pos.x -= sp130.x; + sp7C.pos.y -= sp130.y; + sp7C.pos.z -= sp130.z; + *sp48 = sp7C.pos; + } + } else { + rwData->unk_18 &= ~0x10; + *sp48 = *sp40; + } + } + + // TODO: spF8 temp needed? + camera->fov = Camera_ScaledStepToCeilF(spF8 = roData->unk_20, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.2f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, sp70 ? roData->unk_28 : roData->unk_24); + + return true; +} +#else #pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_KeepOn1.s") +#endif -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_KeepOn2.s") +s32 Camera_KeepOn2(Camera* camera) { + return Camera_Noop(camera); +} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_KeepOn3.s") +/** + * Talking to an NPC + */ +s32 Camera_KeepOn3(Camera* camera) { + Vec3f* eye = &camera->eye; + s32 temp_f0; + Vec3f* eyeNext = &camera->eyeNext; + Vec3f spD8; + Vec3f spCC; + Vec3f spC0; + f32 timer; + f32 spB8; + f32 spB4; + f32 swingAngle; + Actor* spA8[2]; + VecGeo spA0; + VecGeo sp98; + VecGeo sp90; + VecGeo sp88; + VecGeo sp80; + Vec3f* at = &camera->at; + s32 sp78; + f32 phi_f14; + PosRot* sp70; + s16 sp6E; + s16 sp6C; + s16 sp6A; + s16 phi_a3; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + KeepOn3ReadOnlyData* roData = &camera->paramData.keep3.roData; + KeepOn3ReadWriteData* rwData = &camera->paramData.keep3.rwData; + f32 focalActorHeight; + s32 i; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_KeepOn4.s") + sp70 = &camera->focalActor->focus; // TODO: Move above? + sp6A = 0; + focalActorHeight = Camera_GetFocalActorHeight(camera); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_KeepOn0.s") + if ((camera->target == NULL) || (camera->target->update == NULL)) { + camera->target = NULL; + Camera_ChangeMode(camera, CAM_MODE_TARGET); + return 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Fixed1.s") + if (RELOAD_PARAMS(camera)) { + if (camera->play->view.unk164 == 0) { + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + camera->play->view.unk164 = camera->camId | 0x50; + return 1; + } + Camera_UnsetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Fixed2.s") + Camera_UnsetStateFlag(camera, CAM_STATE_4); + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Fixed3.s") + roData->unk_00 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->unk_1C = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_20 = GET_NEXT_RO_DATA(values); + roData->unk_24 = GET_NEXT_SCALED_RO_DATA(values); + roData->timer = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + roData->unk_28 = GET_NEXT_SCALED_RO_DATA(values); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Fixed4.s") + if (camera->animState == 10) { + roData->timer >>= 1; + if (roData->timer < 20) { + roData->timer = 20; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Fixed0.s") + OLib_Vec3fDiffToVecGeo(&sp88, at, eye); + OLib_Vec3fDiffToVecGeo(&sp80, at, eyeNext); + Actor_GetFocus(&camera->targetPosRot, camera->target); + spD8 = focalActorPosRot->pos; + spD8.y += focalActorHeight; + OLib_Vec3fDiffToVecGeo(&spA0, &spD8, &camera->targetPosRot.pos); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Subject1.s") + if (RELOAD_PARAMS(camera)) { + camera->animState++; + spA8[0] = camera->target; + spA8[1] = camera->focalActor; + rwData->unk_0C = camera->target; + phi_f14 = (roData->unk_08 < spA0.r) ? 1.0f : (spA0.r / roData->unk_08); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Subject2.s") + rwData->timer = roData->timer; + spB8 = ((1.0f - phi_f14) * spA0.r) / rwData->timer; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Subject3.s") + if (roData->interfaceFlags & KEEPON3_FLAG_6) { + spA0.pitch = 0; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Subject4.s") + swingAngle = LERPIMP(roData->unk_14, roData->unk_18, phi_f14); + sp98.pitch = CAM_DEG_TO_BINANG(swingAngle) + ((s16) - (spA0.pitch * roData->unk_1C)); + swingAngle = LERPIMP(roData->unk_0C, roData->unk_10, phi_f14); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Subject0.s") + phi_a3 = CAM_DEG_TO_BINANG(swingAngle); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Data0.s") + sp78 = 1; + if ((camera->target->category == ACTORCAT_DOOR) || (camera->target->id == ACTOR_EN_TALK)) { + if ((s16)(camera->targetPosRot.rot.y - sp80.yaw) > 0) { + phi_a3 = -phi_a3; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Data1.s") + if (ABS(spA0.pitch) < 0x157C) { // 30.2 degrees + sp98.yaw = BINANG_ROT180(spA0.yaw) + phi_a3; + sp6A = (s16)(BINANG_ROT180(spA0.yaw) - phi_a3); + } else { + sp78 = 0; + sp90.r = 30.0f; + sp90.yaw = BINANG_ROT180(spA0.yaw) + (phi_a3 >> 2); + sp90.pitch = -spA0.pitch; + spCC = sp70->pos; + spCC.y += 30.0f; + OLib_AddVecGeoToVec3f(&spC0, &spCC, &sp90); + spCC.x = (camera->targetPosRot.pos.x + spD8.x) * 0.5f; + spCC.y = (camera->targetPosRot.pos.y + spD8.y) * 0.5f; + spCC.z = (camera->targetPosRot.pos.z + spD8.z) * 0.5f; + OLib_Vec3fDiffToVecGeo(&sp98, &spCC, &spC0); + if (sp98.pitch < -0x2328) { // 49.4 degrees + sp98.pitch = -0x2328; + } + } + } else if (!(roData->interfaceFlags & KEEPON3_FLAG_5) && (ABS((s16)(spA0.yaw - sp80.yaw)) < 0x4000)) { + if ((s16)(spA0.yaw - sp80.yaw) > 0) { + phi_a3 = -phi_a3; + } + sp98.yaw = (s16)(spA0.yaw + phi_a3); + sp6A = (s16)(spA0.yaw - phi_a3); + } else { + if ((s16)(BINANG_ROT180(spA0.yaw) - sp80.yaw) < 0) { + phi_a3 = -phi_a3; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Data2.s") + sp98.yaw = BINANG_ROT180(spA0.yaw) + phi_a3; + sp6A = BINANG_ROT180(spA0.yaw) - phi_a3; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Data3.s") + sp6C = sp98.yaw; + sp6E = sp98.pitch; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Data4.s") + //! FAKE + if (roData->unk_28) {} -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique1.s") + spB4 = spA0.r; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique2.s") + phi_f14 = roData->unk_28; + spA0.r = spB8 * phi_f14 + (spB4 * (1.0f - phi_f14)); + spD8 = focalActorPosRot->pos; + spD8.y += focalActorHeight; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique3.s") + OLib_AddVecGeoToVec3f(&rwData->unk_10, &spD8, &spA0); + rwData->unk_10.y += roData->unk_00; + spA0.r = spB4; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique4.s") + if (sp78 != 0) { + sp98.r = ((roData->unk_04 + (spA0.r * 0.5f)) - sp80.r) + sp80.r; + i = 0; + sp78 = 14; + OLib_AddVecGeoToVec3f(&spCC, &rwData->unk_10, &sp98); + if (!(roData->interfaceFlags & KEEPON3_FLAG_7)) { + if (CollisionCheck_LineOCCheck(camera->play, &camera->play->colChkCtx, &rwData->unk_10, &spCC, spA8, + 2) || + Camera_BgCheck(camera, &rwData->unk_10, &spCC)) { + sp98.yaw = sp6A; + OLib_AddVecGeoToVec3f(&spCC, &rwData->unk_10, &sp98); + } + while (i < sp78) { + if (!CollisionCheck_LineOCCheck(camera->play, &camera->play->colChkCtx, &rwData->unk_10, &spCC, + spA8, 2) && + !Camera_BgCheck(camera, &rwData->unk_10, &spCC)) { + break; + } + sp98.yaw = sp6C + D_801B9E18[i]; + sp98.pitch = sp6E + D_801B9E34[i]; + OLib_AddVecGeoToVec3f(&spCC, &rwData->unk_10, &sp98); + i++; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique5.s") + Camera_UnsetStateFlag(camera, CAM_STATE_3 | CAM_STATE_2); + temp_f0 = ((rwData->timer + 1) * rwData->timer) >> 1; + rwData->unk_04 = (f32)(s16)(sp98.yaw - sp80.yaw) / temp_f0; + rwData->unk_08 = (f32)(s16)(sp98.pitch - sp80.pitch) / temp_f0; + rwData->unk_00 = (sp98.r - sp80.r) / temp_f0; + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_IGNORE, CAM_HUD_VISIBILITY_IGNORE, 0); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique0.s") + return 1; + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique6.s") + sCameraInterfaceFlags = roData->interfaceFlags; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique7.s") + if (rwData->timer != 0) { + timer = rwData->timer; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique8.s") + at->x += (rwData->unk_10.x - at->x) / timer; + at->y += (rwData->unk_10.y - at->y) / timer; + at->z += (rwData->unk_10.z - at->z) / timer; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Unique9.s") + sp98.r = (rwData->unk_00 * timer) + sp80.r + 1.0f; + sp98.yaw = sp80.yaw + (s16)(rwData->unk_04 * timer); + sp98.pitch = sp80.pitch + (s16)(rwData->unk_08 * timer); + OLib_AddVecGeoToVec3f(eyeNext, at, &sp98); + *eye = *eyeNext; + camera->fov = Camera_ScaledStepToCeilF(roData->unk_20, camera->fov, 0.5f, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->unk_24); + func_800CBFA4(camera, at, eye, 3); + rwData->timer--; + } else { + Camera_SetStateFlag(camera, CAM_STATE_10 | CAM_STATE_4); + } -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo1.s") + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + camera->dist = OLib_Vec3fDist(at, eye); + if (camera->stateFlags & CAM_STATE_3) { + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); + Camera_SetUpdateRatesSlow(camera); + camera->atLerpStepScale = 0.0f; + + if ((camera->xzSpeed > 0.001f) || CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R)) { + Camera_SetStateFlag(camera, CAM_STATE_2); + Camera_UnsetStateFlag(camera, CAM_STATE_3); + } + } + + if (rwData->unk_0C != camera->target) { + rwData->unk_0C = camera->target; + camera->animState = 10; + } + + return 1; +} + +/** + * Used for settings where camera turns around and faces player + * eg. all item-based settings, elegy shell cutscene, death cutscene, ... + */ +s32 Camera_KeepOn4(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Actor* spCC[2]; + f32 temp_f0_2; + f32 new_var; + CollisionPoly* spC0; + VecGeo spB8; + VecGeo spB0; + VecGeo spA8; + s16* sp44 = &camera->data2; + s16 spA2; + s16 spA0; + s16 sp9E; + s16 sp9C; + s16 pad1; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + KeepOn4ReadOnlyData* roData = &camera->paramData.keep4.roData; + KeepOn4ReadWriteData* rwData = &camera->paramData.keep4.rwData; + f32 focalActorHeight; + s32 bgId; + s16 camMode; + Player* player; + Vec3f* data; + CameraModeValue* values; + PosRot sp60; + PosRot sp4C; + + if (RELOAD_PARAMS(camera)) { + if (camera->play->view.unk164 == 0) { + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + Camera_UnsetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + camera->play->view.unk164 = camera->camId | 0x50; + return true; + } + rwData->unk_18 = *sp44; + Camera_UnsetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + } + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + player = (Player*)camera->focalActor; + + switch (((Player*)camera->focalActor)->transformation) { + case PLAYER_FORM_DEKU: + camMode = CAM_MODE_DEKUSHOOT; + break; + + case PLAYER_FORM_GORON: + camMode = CAM_MODE_GORONDASH; + break; + + case PLAYER_FORM_ZORA: + camMode = CAM_MODE_DEKUFLY; + break; + + case PLAYER_FORM_FIERCE_DEITY: + camMode = CAM_MODE_JUMP; + break; + + default: + camMode = CAM_MODE_NORMAL; + break; + } + + focalActorHeight = Camera_GetFocalActorHeight(camera) - (player->unk_AB8 * camera->focalActor->scale.y); + } else { + camMode = CAM_MODE_NORMAL; + focalActorHeight = Camera_GetFocalActorHeight(camera); + } + + if (rwData->unk_18 != *sp44) { + camera->animState = 20; + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + Camera_UnsetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + camera->play->view.unk164 = camera->camId | 0x50; + return true; + } + + Camera_UnsetStateFlag(camera, CAM_STATE_4); + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camMode].values; + new_var = -0.5f; + roData->unk_00 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * + ((1.0f + new_var) - ((68.0f / focalActorHeight) * new_var)); + roData->unk_04 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * + ((1.0f + new_var) - ((68.0f / focalActorHeight) * new_var)); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values); + roData->unk_18 = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + roData->unk_14 = GET_NEXT_SCALED_RO_DATA(values); + roData->timer = GET_NEXT_RO_DATA(values); + } + + sUpdateCameraDirection = true; + sCameraInterfaceFlags = roData->interfaceFlags; + + OLib_Vec3fDiffToVecGeo(&spB0, at, eye); + data = &D_801EDDD0; + OLib_Vec3fDiffToVecGeo(&spA8, at, eyeNext); + D_801EDDD0 = focalActorPosRot->pos; + D_801EDDD0.y = data->y + focalActorHeight; + temp_f0_2 = BgCheck_CameraRaycastFloor2(&camera->play->colCtx, &spC0, &bgId, &D_801EDDD0); + + if ((roData->unk_00 + data->y) < temp_f0_2) { + D_801EDDD0.y = temp_f0_2 + 10.0f; + } else { + D_801EDDD0.y = roData->unk_00 + data->y; + } + + if (roData->unk_10 != 0.0f) { + D_801EDDE0 = (*data); + spB8.r = roData->unk_10; + spB8.pitch = 0; + spB8.yaw = focalActorPosRot->rot.y; + OLib_AddVecGeoToVec3f(&D_801EDDD0, &D_801EDDD0, &spB8); + } + + sp9C = 0; + + switch (camera->animState) { + case 0: + case 20: + spCC[sp9C] = camera->focalActor; + sp9C++; + Camera_SetUpdateRatesFastPitch(camera); + Camera_UnsetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + rwData->timer = roData->timer; + rwData->unk_08 = focalActorPosRot->pos.y - camera->unk_0F0.y; + + switch (roData->interfaceFlags & (KEEPON4_FLAG_3 | KEEPON4_FLAG_2 | KEEPON4_FLAG_1)) { + case KEEPON4_FLAG_1: + spA2 = CAM_DEG_TO_BINANG(roData->unk_08); + spA0 = BINANG_SUB(BINANG_ROT180(focalActorPosRot->rot.y), spA8.yaw) < 0 + ? BINANG_ROT180(focalActorPosRot->rot.y) + CAM_DEG_TO_BINANG(roData->unk_0C) + : BINANG_ROT180(focalActorPosRot->rot.y) - CAM_DEG_TO_BINANG(roData->unk_0C); + break; + + case (KEEPON4_FLAG_3 | KEEPON4_FLAG_2): + spA2 = CAM_DEG_TO_BINANG(roData->unk_08); + pad1 = BINANG_ROT180(focalActorPosRot->rot.y); + spA0 = pad1 + CAM_DEG_TO_BINANG(roData->unk_0C); + break; + + case KEEPON4_FLAG_2: + spA2 = CAM_DEG_TO_BINANG(roData->unk_08); + spA0 = CAM_DEG_TO_BINANG(roData->unk_0C); + break; + + case (KEEPON4_FLAG_2 | KEEPON4_FLAG_1): + spA2 = spA8.pitch + CAM_DEG_TO_BINANG(roData->unk_08); + spA0 = spA8.yaw + CAM_DEG_TO_BINANG(roData->unk_0C); + break; + + case KEEPON4_FLAG_3: + if (camera->target != NULL) { + Actor_GetWorldPosShapeRot(&sp60, camera->target); + spA2 = CAM_DEG_TO_BINANG(roData->unk_08) - sp60.rot.x; + spA0 = (BINANG_SUB(BINANG_ROT180(sp60.rot.y), spA8.yaw) > 0) + ? BINANG_ROT180(sp60.rot.y) + CAM_DEG_TO_BINANG(roData->unk_0C) + : BINANG_ROT180(sp60.rot.y) - CAM_DEG_TO_BINANG(roData->unk_0C); + + spCC[1] = camera->target; + sp9C++; + break; + } + // fallthrough + case (KEEPON4_FLAG_3 | KEEPON4_FLAG_1): + if (camera->target != 0) { + Actor_GetWorld(&sp4C, camera->target); + spA2 = CAM_DEG_TO_BINANG(roData->unk_08); + sp9E = Camera_CalcXZAngle(&sp4C.pos, &focalActorPosRot->pos); + spA0 = (BINANG_SUB(sp9E, spA8.yaw) > 0) ? sp9E + CAM_DEG_TO_BINANG(roData->unk_0C) + : sp9E - CAM_DEG_TO_BINANG(roData->unk_0C); + spCC[1] = camera->target; + sp9C++; + break; + } + // fallthrough + case (KEEPON4_FLAG_3 | KEEPON4_FLAG_2 | KEEPON4_FLAG_1): + spA2 = CAM_DEG_TO_BINANG(roData->unk_08); + spA0 = spA8.yaw; + break; + + default: + spA2 = spA8.pitch; + spA0 = spA8.yaw; + break; + } + + spB8.pitch = spA2; + spB8.yaw = spA0; + spB8.r = roData->unk_04; + // Odd that the return is set to bgId and remains unused + bgId = func_800CC260(camera, &D_801EDDF0, &D_801EDDD0, &spB8, spCC, sp9C); + rwData->unk_04 = (f32)(s16)(spB8.pitch - spA8.pitch) / rwData->timer; + rwData->unk_00 = (f32)(s16)(spB8.yaw - spA8.yaw) / rwData->timer; + rwData->unk_10 = spA8.yaw; + rwData->unk_12 = spA8.pitch; + camera->animState++; + rwData->unk_16 = 1; + break; + + case 10: + rwData->unk_08 = focalActorPosRot->pos.y - camera->unk_0F0.y; + break; + } + + if (roData->interfaceFlags & KEEPON4_FLAG_6) { + if (rwData->timer != 0) { + at->x += ((data->x - at->x) / rwData->timer); + at->y += ((data->y - at->y) / rwData->timer); + at->z += ((data->z - at->z) / rwData->timer); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } + camera->yOffsetUpdateRate = 0.25f; + camera->xzOffsetUpdateRate = 0.25f; + camera->atLerpStepScale = 0.0f; + } else { + camera->yOffsetUpdateRate = 0.25f; + camera->xzOffsetUpdateRate = 0.25f; + camera->atLerpStepScale = 0.75f; + Camera_ScaledStepToCeilVec3f(data, at, 0.2f, 0.2f, 0.2f); + camera->atLerpStepScale = 0.0f; + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } + + camera->dist = Camera_ScaledStepToCeilF(roData->unk_04, camera->dist, 0.25f, 1.0f); + spB8.r = camera->dist; + + if (rwData->timer != 0) { + Camera_SetStateFlag(camera, CAM_STATE_DISABLE_MODE_CHANGE); + rwData->unk_10 += (s16)rwData->unk_00; + rwData->unk_12 += (s16)rwData->unk_04; + rwData->timer--; + } else { + Camera_SetStateFlag(camera, CAM_STATE_10 | CAM_STATE_4); + } + + spB8.yaw = Camera_ScaledStepToCeilS(rwData->unk_10, spA8.yaw, roData->unk_14, 5); + spB8.pitch = Camera_ScaledStepToCeilS(rwData->unk_12, spA8.pitch, roData->unk_14, 5); + OLib_AddVecGeoToVec3f(eyeNext, at, &spB8); + *eye = *eyeNext; + func_800CBFA4(camera, at, eye, 3); + + camera->fov = Camera_ScaledStepToCeilF(roData->unk_18, camera->fov, camera->fovUpdateRate, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + + return 1; +} + +s32 Camera_KeepOn0(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Used for many fixed-based camera settings i.e. camera is fixed in rotation, and often position (but not always) + */ +s32 Camera_Fixed1(Camera* camera) { + s32 pad[2]; + s32 yawDiff; + VecGeo eyeOffset; + VecGeo eyeAtOffset; + VecGeo sp7C; + u32 negOne; + Vec3f adjustedPos; + BgCamFuncData* bgCamFuncData; + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + CameraModeValue* values; + PosRot* targetHome; + PosRot* targetWorld; + VecGeo sp44; + Fixed1ReadOnlyData* roData = &camera->paramData.fixd1.roData; + Fixed1ReadWriteData* rwData = &camera->paramData.fixd1.rwData; + + OLib_Vec3fDiffToVecGeo(&sp7C, at, eye); + + if (!RELOAD_PARAMS(camera)) { + } else { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + Camera_Vec3sToVec3f(&rwData->eyePosRotTarget.pos, &bgCamFuncData->pos); + + rwData->eyePosRotTarget.rot = bgCamFuncData->rot; + rwData->fov = bgCamFuncData->fov; + rwData->focalActor = camera->focalActor; + + roData->unk_00 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight; + roData->unk_04 = GET_NEXT_SCALED_RO_DATA(values); + roData->fov = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + + if (roData->interfaceFlags & FIXED1_FLAG_4) { + if (camera->target == NULL) { + return false; + } + + targetHome = &camera->target->home; + targetWorld = &camera->target->world; + + OLib_Vec3fDiffToVecGeo(&sp44, &targetHome->pos, &rwData->eyePosRotTarget.pos); + sp44.yaw = targetWorld->rot.y + (s16)(sp44.yaw - targetHome->rot.y); + OLib_AddVecGeoToVec3f(&rwData->eyePosRotTarget.pos, &targetWorld->pos, &sp44); + yawDiff = (s16)(rwData->eyePosRotTarget.rot.y - targetHome->rot.y); + rwData->eyePosRotTarget.rot.y = targetWorld->rot.y + yawDiff; + } + } + + negOne = -1; + + if (rwData->focalActor != camera->focalActor) { + camera->animState = 20; + } + + if (rwData->fov == (s32)negOne) { + rwData->fov = roData->fov * 100; + } else if (rwData->fov <= 360) { + rwData->fov *= 100; + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + if (camera->animState == 0) { + camera->animState++; + Camera_SetUpdateRatesSlow(camera); + if (rwData->fov != (s32)negOne) { + roData->fov = CAM_RODATA_UNSCALE(rwData->fov); + } + + if (bgCamFuncData->unk_0E != (s32)negOne) { + roData->unk_04 = CAM_RODATA_UNSCALE(bgCamFuncData->unk_0E); + } + } + + OLib_Vec3fDiffToVecGeo(&eyeAtOffset, eye, at); + Camera_ScaledStepToCeilVec3f(&rwData->eyePosRotTarget.pos, eye, roData->unk_04, roData->unk_04, 0.2f); + adjustedPos = focalActorPosRot->pos; + adjustedPos.y += focalActorHeight; + camera->dist = OLib_Vec3fDist(&adjustedPos, eye); + eyeOffset.r = camera->dist; + eyeOffset.pitch = + Camera_ScaledStepToCeilS(rwData->eyePosRotTarget.rot.x * -1, eyeAtOffset.pitch, roData->unk_04, 5); + eyeOffset.yaw = Camera_ScaledStepToCeilS(rwData->eyePosRotTarget.rot.y, eyeAtOffset.yaw, roData->unk_04, 5); + OLib_AddVecGeoToVec3f(at, eye, &eyeOffset); + camera->eyeNext = *eye; + Camera_BgCheck(camera, eye, at); + + camera->fov = Camera_ScaledStepToCeilF(roData->fov, camera->fov, roData->unk_04, 0.1f); + camera->roll = 0; + camera->atLerpStepScale = 0.0f; + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + camera->roll = Camera_ScaledStepToCeilS(rwData->eyePosRotTarget.rot.z, camera->roll, roData->unk_04, 5); + + return 1; +} + +/** + * Used for many pivot-based camera settings i.e. camera fixed in position but free to rotate + */ +s32 Camera_Fixed2(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Vec3f spB0; + Vec3f spA4; + Vec3f sp98; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + f32 temp_f0_3; + f32 new_var; + BgCamFuncData* bgCamFuncData; + VecGeo sp80; + PosRot* sp7C; + PosRot* sp78; + VecGeo sp70; + Vec3f* new_var1; + Vec3f* new_var2; + Player* player; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + Actor* actor; + Fixed2ReadOnlyData* roData = &camera->paramData.fixd2.roData; + Fixed2ReadWriteData* rwData = &camera->paramData.fixd2.rwData; + CameraModeValue* values; + Vec3f sp44; + + if (!RELOAD_PARAMS(camera)) { + } else { + //! FAKE + if (new_var2) {} + + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_10 = GET_NEXT_SCALED_RO_DATA(values); + roData->unk_14 = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + rwData->unk_1C = roData->unk_14 * 100.0f; + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + if (bgCamFuncData != NULL) { + if (!(roData->interfaceFlags & FIXED2_FLAG_1)) { + Camera_Vec3sToVec3f(&rwData->unk_00, &bgCamFuncData->pos); + } else { + if (camera->focalActor != &GET_PLAYER(camera->play)->actor) { + player = GET_PLAYER(camera->play); + OLib_Vec3fDiffToVecGeo(&sp70, &player->actor.focus.pos, eye); + if (sp70.r < roData->unk_04) { + sp70.r = roData->unk_04; + if (sp70.pitch < 0xBB8) { // 16.5 degrees + sp70.pitch = 0xBB8; + } + + new_var1 = &player->actor.focus.pos; + + OLib_AddVecGeoToVec3f(&rwData->unk_00, new_var1, &sp70); + } else { + rwData->unk_00 = *eye; + //! FAKE: + dummy:; + } + } else { + rwData->unk_00 = camera->eye; + } + } + + if (bgCamFuncData->fov != -1) { + if (roData->interfaceFlags & FIXED2_FLAG_7) { + rwData->unk_1C = (bgCamFuncData->fov >> 1) + (bgCamFuncData->fov >> 2); + if (rwData->unk_1C < 0x1E) { + rwData->unk_1C = 0x1E; + } + } else { + rwData->unk_1C = bgCamFuncData->fov; + } + } + + if (bgCamFuncData->unk_0E != -1) { + rwData->unk_0C = bgCamFuncData->unk_0E; + } else { + rwData->unk_0C = roData->unk_08; + } + + if (bgCamFuncData->unk_10 != -1) { + if (roData->interfaceFlags & FIXED2_FLAG_2) { + rwData->unk_14 = bgCamFuncData->unk_10 * 0.01f; + rwData->unk_18 = roData->unk_0C; + } else { + temp_f0_3 = bgCamFuncData->unk_10 * 0.01f; + rwData->unk_18 = temp_f0_3; + rwData->unk_14 = temp_f0_3; + } + } else { + rwData->unk_14 = roData->unk_10; + rwData->unk_18 = roData->unk_0C; + } + if (roData->interfaceFlags & FIXED2_FLAG_4) { + if (camera->target == 0) { + return 0; + } + sp7C = &camera->target->home; + sp78 = &camera->target->world; + OLib_Vec3fDiffToVecGeo(&sp70, &sp7C->pos, &rwData->unk_00); + sp70.yaw = sp78->rot.y + (s16)(sp70.yaw - sp7C->rot.y); + OLib_AddVecGeoToVec3f(&rwData->unk_00, &sp78->pos, &sp70); + } + } else { + rwData->unk_00 = camera->eye; + rwData->unk_0C = roData->unk_08; + rwData->unk_14 = roData->unk_10; + rwData->unk_18 = roData->unk_0C; + } + if (rwData->unk_1C <= 360) { + rwData->unk_1C *= 100; + } + if (camera->animState == 20) { + rwData->unk_14 = 0.2f; + } + //! FAKE: + if (1) {} + } + + sCameraInterfaceFlags = roData->interfaceFlags; + //! FAKE: + new_var = 0.0f; + + if (roData->interfaceFlags & FIXED2_FLAG_3) { + if (camera->target == NULL) { + return false; + } + + spB0.x = camera->target->focus.pos.x; + spB0.y = camera->target->focus.pos.y; + spB0.z = camera->target->focus.pos.z; + + camera->focalActorAtOffset.x = spB0.x - focalActorPosRot->pos.x; + camera->focalActorAtOffset.y = spB0.y - focalActorPosRot->pos.y; + camera->focalActorAtOffset.z = spB0.z - focalActorPosRot->pos.z; + } else if (roData->interfaceFlags & FIXED2_FLAG_6) { + sp98.x = new_var; + sp98.y = roData->unk_00 + focalActorHeight; + sp98.z = new_var; + + if (camera->target != NULL) { + new_var1 = &camera->focalActor->focus.pos; + new_var2 = &camera->target->focus.pos; + //! FAKE: + sp98.x = ((void)0, new_var) + ((new_var2->x - new_var1->x) * 0.4f); + sp98.y += (new_var2->y - new_var1->y) * 0.4f; + sp98.z = ((void)0, new_var) + ((new_var2->z - new_var1->z) * 0.4f); + } + + Camera_ScaledStepToCeilVec3f(&sp98, &camera->focalActorAtOffset, 0.25f, 0.25f, 0.1f); + spB0.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + spB0.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + spB0.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + } else if (roData->interfaceFlags & FIXED2_FLAG_7) { + sp98.x = new_var; + sp98.y = roData->unk_00 + focalActorHeight; + sp98.z = new_var; + + if (camera->target != NULL) { + new_var1 = &camera->focalActor->focus.pos; + new_var2 = &camera->target->focus.pos; + //! FAKE: + sp98.x = ((void)0, new_var) + ((new_var2->x - new_var1->x) * 0.7f); + sp98.y += (new_var2->y - new_var1->y) * 0.7f; + sp98.z = ((void)0, new_var) + ((new_var2->z - new_var1->z) * 0.7f); + } + + Camera_ScaledStepToCeilVec3f(&sp98, &camera->focalActorAtOffset, 0.25f, 0.25f, 0.1f); + spB0.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + spB0.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + spB0.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + } else { + sp98.x = new_var; + sp98.z = new_var; + + if ((((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4000) || + (((Player*)camera->focalActor)->stateFlags1 & PLAYER_STATE1_4)) { + sp98.y = roData->unk_00; + } else { + sp98.y = roData->unk_00 + focalActorHeight; + } + + Camera_ScaledStepToCeilVec3f(&sp98, &camera->focalActorAtOffset, rwData->unk_14, rwData->unk_14, 0.1f); + spB0.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + spB0.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + spB0.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + } + + if (camera->animState == 0) { + Camera_SetUpdateRatesSlow(camera); + if (!(roData->interfaceFlags & FIXED2_FLAG_0)) { + *at = spB0; + OLib_Vec3fDiffToVecGeo(&sp80, at, &rwData->unk_00); + if ((rwData->unk_0C < sp80.r) || (roData->interfaceFlags & FIXED2_FLAG_5)) { + sp80.r = rwData->unk_0C; + OLib_AddVecGeoToVec3f(&spA4, at, &sp80); + } else { + if (sp80.r < roData->unk_04) { + sp80.r = roData->unk_04; + OLib_AddVecGeoToVec3f(&spA4, at, &sp80); + } else { + spA4 = rwData->unk_00; + } + } + sp44 = spA4; + camera->eyeNext = sp44; + *eye = sp44; + camera->fov = rwData->unk_1C * 0.01f; + } + } + + Camera_ScaledStepToCeilVec3f(&spB0, at, rwData->unk_14, rwData->unk_14, 1.0f); + OLib_Vec3fDiffToVecGeo(&sp80, at, &rwData->unk_00); + if ((rwData->unk_0C < sp80.r) || (roData->interfaceFlags & FIXED2_FLAG_5)) { + sp80.r = rwData->unk_0C; + OLib_AddVecGeoToVec3f(&spA4, at, &sp80); + } else if (sp80.r < roData->unk_04) { + sp80.r = roData->unk_04; + OLib_AddVecGeoToVec3f(&spA4, at, &sp80); + } else { + spA4 = rwData->unk_00; + } + + Camera_ScaledStepToCeilVec3f(&spA4, eyeNext, rwData->unk_18, rwData->unk_18, 0.1f); + *eye = *eyeNext; + camera->dist = OLib_Vec3fDist(at, eye); + camera->roll = 0; + camera->xzSpeed = 0; + rwData->unk_10 = rwData->unk_1C * 0.01f; + camera->fov = Camera_ScaledStepToCeilF(rwData->unk_10, camera->fov, rwData->unk_14, 0.1f); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, 1.0f); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + camera->animState = 1; + + return true; +} + +/** + * Used by the unused PREREND_FIXED Camera Setting. Remnant of OoT + */ +s32 Camera_Fixed3(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Fixed4(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Fixed0(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * First person view + */ +s32 Camera_Subject1(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Vec3f sp90; + Vec3f sp84; + VecGeo sp7C; + VecGeo sp74; + VecGeo tgeo; + PosRot sp58; + f32 sp54; + f32 temp_f0_2; + s16 sp4E; + s16 sp4C; + Subject1ReadOnlyData* roData = &camera->paramData.subj1.roData; + Subject1ReadWriteData* rwData = &camera->paramData.subj1.rwData; + CameraModeValue* values; + f32 temp_f0; + f32 focalActorHeight; + + Actor_GetFocus(&sp58, camera->focalActor); + focalActorHeight = Camera_GetFocalActorHeight(camera); + Camera_SetUpdateRatesFastPitch(camera); + + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight; + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = GET_NEXT_RO_DATA(values); + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->unk_10 = GET_NEXT_RO_DATA(values) * 0.1f; + roData->unk_14 = GET_NEXT_RO_DATA(values) * 0.1f; + roData->unk_18 = GET_NEXT_RO_DATA(values) * 0.1f; + roData->unk_1C = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + + sp7C.r = roData->unk_08; + sp7C.yaw = BINANG_ROT180(sp58.rot.y); + sp7C.pitch = sp58.rot.x; + sp90 = sp58.pos; + sp90.y += roData->unk_00; + + OLib_AddVecGeoToVec3f(&sp84, &sp90, &sp7C); + OLib_Vec3fDiffToVecGeo(&sp74, &camera->at, eye); + sCameraInterfaceFlags = roData->interfaceFlags; + + if (camera->play->view.unk164 == 0) { + camera->play->view.unk164 = camera->camId | 0x50; + return true; + } + + if (RELOAD_PARAMS(camera)) { + rwData->unk_00 = sp74.r; + rwData->unk_04 = sp74.yaw; + rwData->unk_06 = sp74.pitch; + + if (roData->interfaceFlags & SUBJECT1_FLAG_4) { + camera->fov = roData->unk_1C; + rwData->timer = 0; + } else { + rwData->timer = 6; + } + camera->dist = roData->unk_08; + camera->rUpdateRateInv = 1.0f; + camera->animState++; + camera->dist = roData->unk_08; + } + + tgeo.r = rwData->unk_00; + tgeo.pitch = rwData->unk_04; + tgeo.yaw = rwData->unk_06; + + if (rwData->timer != 0) { + temp_f0 = (1.0f / rwData->timer); + + VEC3F_LERPIMPDST(at, at, &sp90, temp_f0); + + sp54 = ((tgeo.r - sp7C.r) * (1.0f / 6.0f)); + sp4E = BINANG_SUB(tgeo.pitch, sp7C.yaw) * (1.0f / 6.0f); + sp4C = BINANG_SUB(tgeo.yaw, sp7C.pitch) * (1.0f / 6.0f); + + sp74.r = Camera_ScaledStepToCeilF((rwData->timer * sp54) + sp7C.r, sp74.r, 0.5f, 1.0f); + sp74.yaw = Camera_ScaledStepToCeilS(sp7C.yaw + (sp4E * rwData->timer), sp74.yaw, 0.5f, 5); + sp74.pitch = Camera_ScaledStepToCeilS(sp7C.pitch + (sp4C * rwData->timer), sp74.pitch, 0.5f, 5); + + OLib_AddVecGeoToVec3f(eyeNext, at, &sp74); + *eye = *eyeNext; + rwData->timer--; + } else { + sp54 = Math_SinS(-sp58.rot.x); + temp_f0_2 = Math_CosS(-sp58.rot.x); + + sp90.x = roData->unk_10; + sp90.y = (roData->unk_14 * temp_f0_2) - (roData->unk_18 * sp54); + sp90.z = (roData->unk_14 * sp54) + (roData->unk_18 * temp_f0_2); + + sp54 = Math_SinS(BINANG_ROT180(sp58.rot.y)); + temp_f0_2 = Math_CosS(BINANG_ROT180(sp58.rot.y)); + + roData->unk_10 = (sp90.z * sp54) + (sp90.x * temp_f0_2); + roData->unk_14 = sp90.y; + roData->unk_18 = (sp90.z * temp_f0_2) - (sp90.x * sp54); + + at->x = roData->unk_10 + sp58.pos.x; + at->y = roData->unk_14 + sp58.pos.y; + at->z = roData->unk_18 + sp58.pos.z; + + sp74.r = roData->unk_08; + sp74.yaw = BINANG_ROT180(sp58.rot.y); + sp74.pitch = sp58.rot.x; + + OLib_AddVecGeoToVec3f(&camera->eyeNext, at, &sp74); + sp74.r = roData->unk_04; + OLib_AddVecGeoToVec3f(eye, at, &sp74); + } + + // TODO: is skyboxDisabled accurate here? + if (camera->play->envCtx.skyboxDisabled == 0) { + Camera_BgCheck(camera, at, eye); + } else { + func_800CBFA4(camera, at, eye, 3); + } + + camera->fov = Camera_ScaledStepToCeilF(roData->unk_1C, camera->fov, 0.25f, 0.1f); + camera->roll = 0; + camera->atLerpStepScale = 0.0f; + + return true; +} + +s32 Camera_Subject2(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Subject3(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Subject4(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Subject0(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Data0(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Data1(Camera* camera) { + return Camera_Normal1(camera); +} + +s32 Camera_Data2(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Data3(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Data4(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Unique1(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Player diving from the surface of the water to underwater not as zora + * Also used when using a door to leave a scene + */ +s32 Camera_Unique2(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + f32 phi_f16; + Vec3f sp70; + VecGeo sp68; + VecGeo sp60; + s32 pad[3]; + Unique2ReadOnlyData* roData = &camera->paramData.uniq2.roData; + Unique2ReadWriteData* rwData = &camera->paramData.uniq2.rwData; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + Vec3f* eyeNext = &camera->eyeNext; + CameraModeValue* values; + + OLib_Vec3fDiffToVecGeo(&sp60, at, eye); + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = + GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->unk_08 = 0.25f; + roData->unk_0C = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + if ((camera->animState == 0) || (rwData->unk_04 != roData->interfaceFlags)) { + rwData->unk_04 = roData->interfaceFlags; + } + + if (camera->animState == 0) { + camera->animState = 1; + Camera_SetUpdateRatesSlow(camera); + rwData->unk_00 = 200.0f; + } + + if (roData->interfaceFlags & UNIQUE2_FLAG_4) { + *eyeNext = *eye; + Camera_UnsetStateFlag(camera, CAM_STATE_2); + } + + sp70 = camera->focalActorPosRot.pos; + + if (roData->interfaceFlags & UNIQUE2_FLAG_0) { + phi_f16 = 1.0f; + } else { + phi_f16 = camera->speedRatio; + } + + at->x += (sp70.x - at->x) * phi_f16 * 0.3f; + at->y += ((sp70.y + focalActorHeight + roData->unk_00) - at->y) * 0.2f; + at->z += (sp70.z - at->z) * phi_f16 * 0.3f; + + rwData->unk_00 = rwData->unk_00 + ((2.0f - rwData->unk_00) * 0.05f); + + if (roData->interfaceFlags & UNIQUE2_FLAG_0) { + OLib_Vec3fDiffToVecGeo(&sp68, at, eyeNext); + sp68.r = roData->unk_04; + OLib_AddVecGeoToVec3f(&sp70, at, &sp68); + Camera_ScaledStepToCeilVec3f(&sp70, eye, roData->unk_08, roData->unk_08, 0.2f); + } else if (roData->interfaceFlags & UNIQUE2_FLAG_1) { + if (OLib_Vec3fDistXZ(at, eyeNext) < roData->unk_04) { + OLib_Vec3fDiffToVecGeo(&sp68, at, eyeNext); + sp68.yaw = Camera_ScaledStepToCeilS(sp68.yaw, sp60.yaw, 0.1f, 5); + sp68.r = roData->unk_04; + sp68.pitch = 0; + OLib_AddVecGeoToVec3f(eye, at, &sp68); + eye->y = eyeNext->y; + } else { + Camera_ScaledStepToCeilVec3f(eyeNext, eye, roData->unk_08, roData->unk_08, 0.2f); + } + } + + if (!(roData->interfaceFlags & UNIQUE2_FLAG_5)) { + Camera_BgCheck(camera, at, eye); + } + + camera->dist = OLib_Vec3fDist(at, eye); + camera->roll = 0; + camera->fov = Camera_ScaledStepToCeilF(roData->unk_0C, camera->fov, 0.2f, 0.1f); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, 1.0f); + + return true; +} + +/** + * Woodfall inside the Swamp, used for normal camModes and derivative modes + */ +s32 Camera_Unique3(Camera* camera) { + s32 ret = Camera_Normal1(camera); + + if ((camera->play->sceneId == SCENE_21MITURINMAE) && (camera->eye.y < 5.0f)) { + camera->eye.y = 5.0f; + } + return ret; +} + +/** + * Woodfall inside the Swamp, used for parallel camModes and derivative modes + */ +s32 Camera_Unique4(Camera* camera) { + s32 ret = Camera_Parallel1(camera); + + if ((camera->play->sceneId == SCENE_21MITURINMAE) && (camera->eye.y < 5.0f)) { + camera->eye.y = 5.0f; + } + return ret; +} + +/** + * Woodfall inside the Swamp, used for battle camMode + */ +s32 Camera_Unique5(Camera* camera) { + s32 ret = Camera_Battle1(camera); + + if ((camera->play->sceneId == SCENE_21MITURINMAE) && (camera->eye.y < 5.0f)) { + camera->eye.y = 5.0f; + } + return ret; +} + +/** + * Entering a room or scene (camera settings START0/START1/START2) + */ +s32 Camera_Unique0(Camera* camera) { + f32 playerHeight; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + PosRot sp9C; + Player* player; + Vec3f sp8C; + VecGeo sp84; + VecGeo sp7C; + BgCamFuncData* bgCamFuncData; + f32 sp74; + s32 pad; + s16 temp_v1; + Unique0ReadOnlyData* roData = &camera->paramData.uniq0.roData; + Unique0ReadWriteData* rwData = &camera->paramData.uniq0.rwData; + CameraModeValue* values; + Vec3f sp54; + + playerHeight = Player_GetHeight((Player*)camera->focalActor); + player = (Player*)camera->focalActor; + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->unk_00 = GET_NEXT_RO_DATA(values); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + OLib_Vec3fDiffToVecGeo(&sp7C, &camera->at, &camera->eye); + + if (player->rideActor != NULL) { + Actor_GetWorld(&sp9C, player->rideActor); + sp8C = sp9C.pos; + sp8C.y += playerHeight + 20.0f; + } else { + sp8C = camera->focalActorPosRot.pos; + sp8C.y += playerHeight; + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + Camera_Vec3sToVec3f(&rwData->unk_1C, &bgCamFuncData->pos); + camera->eye = camera->eyeNext = rwData->unk_1C; + rwData->unk_34 = bgCamFuncData->rot; + + temp_v1 = bgCamFuncData->fov; + if (temp_v1 != -1) { + if (temp_v1 <= 360) { + camera->fov = temp_v1; + } else { + camera->fov = temp_v1 * 0.01f; + } + } + + rwData->timer = bgCamFuncData->unk_0E; + if (rwData->timer == -1) { + rwData->timer = 60; + } + + if (bgCamFuncData->unk_10 != -1) { + rwData->unk_18 = bgCamFuncData->unk_10 * 0.01f; + } else { + rwData->unk_18 = roData->unk_04 * 0.01f; + } + + rwData->unk_00 = focalActorPosRot->pos; + if (roData->interfaceFlags & UNIQUE0_FLAG_4) { + rwData->unk_0C.x = focalActorPosRot->pos.x; + rwData->unk_0C.y = focalActorPosRot->pos.y + playerHeight + roData->unk_00; + rwData->unk_0C.z = focalActorPosRot->pos.z; + } + rwData->unk_3A = camera->focalActor->world.rot.y; + rwData->unk_3E = 0; + camera->eye = camera->eyeNext = rwData->unk_1C; + Camera_UnsetStateFlag(camera, CAM_STATE_2); + camera->animState++; + // fallthrough + case 1: + sp84.r = OLib_Vec3fDist(&sp8C, &camera->eye); + sp84.yaw = rwData->unk_34.y; + sp84.pitch = -rwData->unk_34.x; + OLib_VecGeoToVec3f(&rwData->unk_28, &sp84); + func_80179A44(&rwData->unk_1C, focalActorPosRot, &rwData->unk_0C); + camera->at = rwData->unk_0C; + + if (player->stateFlags1 & PLAYER_STATE1_20000000) { + rwData->unk_00 = focalActorPosRot->pos; + } + + if (roData->interfaceFlags & UNIQUE0_FLAG_4) { + sp54.x = focalActorPosRot->pos.x; + sp54.y = focalActorPosRot->pos.y + playerHeight + roData->unk_00; + sp54.z = focalActorPosRot->pos.z; + Camera_ScaledStepToCeilVec3f(&sp54, &camera->at, camera->xzOffsetUpdateRate, camera->yOffsetUpdateRate, + 0.1f); + camera->yOffsetUpdateRate = + Camera_ScaledStepToCeilF(rwData->unk_18, camera->yOffsetUpdateRate, 0.1f, 0.0001f); + camera->xzOffsetUpdateRate = + Camera_ScaledStepToCeilF(rwData->unk_18, camera->xzOffsetUpdateRate, 0.1f, 0.0001f); + } + + if ((camera->animState == 999) || (camera->animState == 666)) { + rwData->unk_3E = 2; + } + + if (roData->interfaceFlags & UNIQUE0_FLAG_0) { + if (rwData->timer > 0) { + rwData->timer--; + rwData->unk_00 = focalActorPosRot->pos; + } else if (!(player->stateFlags1 & PLAYER_STATE1_20000000) && + ((OLib_Vec3fDistXZ(&focalActorPosRot->pos, &rwData->unk_00) >= 10.0f) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R) || + (roData->interfaceFlags & UNIQUE0_FLAG_1))) { + rwData->unk_3E = 1; + } + } else { + if (rwData->timer > 0) { + rwData->timer--; + if (rwData->timer == 0) { + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); + } + } else { + rwData->unk_00 = focalActorPosRot->pos; + } + + if (!(player->stateFlags1 & PLAYER_STATE1_20000000)) { // TODO: Merge into 1 if-statement + if ((rwData->unk_3A != camera->focalActor->world.rot.y) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R) || + (roData->interfaceFlags & UNIQUE0_FLAG_1)) { + rwData->unk_3E = 1; + } + } + } + break; + + case 3: + sp74 = 1.0f / rwData->timer; + sp8C.y -= playerHeight * 0.2f; + + Camera_ScaledStepToCeilVec3f(&sp8C, &camera->at, sp74, sp74, 0.001f); + + sp84.r = OLib_Vec3fDist(&camera->at, &camera->eye); + sp84.pitch = sp7C.pitch; + sp84.yaw = sp7C.yaw; + sp84.r = Camera_ScaledStepToCeilF(100.0f, sp84.r, sp74, 1.0f); + + OLib_AddVecGeoToVec3f(&sp8C, &camera->at, &sp84); + + sp74 = (QREG(64) * 0.01f) + 0.2f; + + Camera_ScaledStepToCeilVec3f(&sp8C, &camera->eye, sp74, sp74, 0.001f); + + rwData->timer--; + if (rwData->timer == 0) { + rwData->unk_3E = 9; + } + break; + } + + if ((rwData->unk_3E == 1) || (rwData->unk_3E == 2) || (rwData->unk_3E == 9)) { + camera->dist = OLib_Vec3fDist(&camera->at, &camera->eye); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, 1.0f); + + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + + camera->atLerpStepScale = 0.0f; + + Camera_ChangeSettingFlags(camera, camera->prevSetting, CAM_CHANGE_SETTING_1); + Camera_SetStateFlag(camera, CAM_STATE_2); + + camera->yawUpdateRateInv = 1200.0f; + camera->pitchUpdateRateInv = 1200.0f; + camera->yOffsetUpdateRate = 0.001f; + camera->xzOffsetUpdateRate = 0.001f; + camera->fovUpdateRate = 0.01f; + } + + return true; +} + +/** + * Does the minimal amount of camera update. + * Allows for manual control of camera parameters without interference from update + */ +s32 Camera_Unique6(Camera* camera) { + f32 focalActorHeight; + CameraModeValue* values; + Vec3f playerPosDisp; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Unique6ReadOnlyData* roData = &camera->paramData.uniq6.roData; + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + if (camera->animState == 0) { + camera->animState++; + Camera_SetUpdateRatesFastPitch(camera); + } + + if (camera->focalActor != NULL) { + focalActorHeight = Camera_GetFocalActorHeight(camera); + playerPosDisp = focalActorPosRot->pos; + playerPosDisp.y += focalActorHeight; + camera->dist = OLib_Vec3fDist(&playerPosDisp, &camera->eye); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } else { + camera->dist = OLib_Vec3fDist(&camera->at, &camera->eye); + } + + if (roData->interfaceFlags & UNIQUE6_FLAG_0) { + if (camera->timer > 0) { + camera->timer--; + } + } + + return true; +} + +/** + * Used by the unused PREREND_PIVOT Camera Setting. Remnant of OoT + */ +s32 Camera_Unique7(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Unique8(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Unique9(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Used by unknown settings DEMO0 and ATTENTION + */ +s32 Camera_Demo1(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* targetPosRot = &camera->targetPosRot; + f32 temp_f0; + Actor* sp98[1]; + s16 screenX; + s16 screenY; + s32 phi_v0; + VecGeo sp88; + PosRot sp74; + PosRot targetHead; + Demo1ReadOnlyData* roData = &camera->paramData.demo1.roData; + Demo1ReadWriteData* rwData = &camera->paramData.demo1.rwData; + s32 pad; + + if (camera->animState == 0) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + if (camera->animState == 0) { + rwData->unk_1C = 0; + OLib_Vec3fDiffToVecGeo(&rwData->unk_0C, &camera->targetPosRot.pos, eye); + OLib_Vec3fDiffToVecGeo(&rwData->unk_14, &camera->at, eye); + Actor_GetFocus(&targetHead, camera->target); + Actor_GetWorld(&sp74, camera->target); + camera->targetPosRot.pos.x = (sp74.pos.x + targetHead.pos.x) * 0.5f; + camera->targetPosRot.pos.y = (sp74.pos.y + targetHead.pos.y) * 0.5f; + camera->targetPosRot.pos.z = (sp74.pos.z + targetHead.pos.z) * 0.5f; + camera->targetPosRot.rot = targetHead.rot; + camera->animState++; + } + + Actor_GetScreenPos(camera->play, camera->target, &screenX, &screenY); + + temp_f0 = rwData->unk_0C.r; + if ((screenX > 20) && (screenX < (SCREEN_WIDTH - 20)) && (screenY > 40) && (screenY < (SCREEN_HEIGHT - 40))) { + if (temp_f0 < 700.0f) { + phi_v0 = 0; + } else { + phi_v0 = 1; + } + } else if (temp_f0 < 50.0f) { + phi_v0 = 2; + } else if (temp_f0 < 300.0f) { + phi_v0 = 3; + } else if (temp_f0 < 700.0f) { + phi_v0 = 4; + } else { + phi_v0 = 5; + } + + if (camera->target->category == ACTORCAT_DOOR) { + if ((phi_v0 > 0) && (phi_v0 < 5)) { + phi_v0 = 6; + } else if (phi_v0 >= 5) { + phi_v0 = 7; + } + } + + if (camera->target->category == ACTORCAT_CHEST) { + if ((phi_v0 > 1) && (phi_v0 < 5)) { + phi_v0 = 8; + } + } + + switch (phi_v0) { + Vec3f sp44; + + case 1: + Camera_ScaledStepToCeilVec3f(&camera->targetPosRot.pos, at, 0.1f, 0.1f, 0.1f); + OLib_Vec3fDiffToVecGeo(&sp88, at, eye); + sp88.r = rwData->unk_0C.r; + OLib_AddVecGeoToVec3f(eyeNext, at, &sp88); + *eye = *eyeNext; + Camera_BgCheck(camera, at, eye); + break; + + case 2: + Camera_ScaledStepToCeilVec3f(&camera->targetPosRot.pos, &camera->at, 0.1f, 0.1f, 0.1f); + break; + + case 3: + eyeNext = &targetPosRot->pos; + if (rwData->unk_1C == 0) { + sp98[0] = camera->target; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_14, sp98, 1); + } + Camera_ScaledStepToCeilVec3f(eyeNext, at, 0.1f, 0.1f, 0.1f); + eyeNext = &camera->eyeNext; + Camera_ScaledStepToCeilVec3f(&rwData->unk_00, eyeNext, 0.1f, 0.1f, 0.1f); + *eye = *eyeNext; + Camera_BgCheck(camera, at, eye); + break; + + case 4: + if (rwData->unk_1C == 0) { + sp98[0] = camera->target; + rwData->unk_14.r = rwData->unk_0C.r; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_14, sp98, 1); + } + Camera_ScaledStepToCeilVec3f(&targetPosRot->pos, at, 0.1f, 0.1f, 0.1f); + Camera_ScaledStepToCeilVec3f(&rwData->unk_00, eyeNext, 0.1f, 0.1f, 0.1f); + *eye = *eyeNext; + Camera_BgCheck(camera, at, eye); + break; + + case 5: + eyeNext = &targetPosRot->pos; + if (rwData->unk_1C == 0) { + sp98[0] = camera->target; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_0C, sp98, 1); + } + *at = *eyeNext; + sp44 = rwData->unk_00; + camera->eyeNext = sp44; + *eye = sp44; + break; + + case 6: + if (rwData->unk_1C == 0) { + rwData->unk_0C.yaw = camera->target->shape.rot.y; + sp98[0] = camera->target; + rwData->unk_0C.r = rwData->unk_14.r; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_0C, sp98, 1); + } + Camera_ScaledStepToCeilVec3f(&targetPosRot->pos, at, 0.1f, 0.1f, 0.1f); + Camera_ScaledStepToCeilVec3f(&rwData->unk_00, eyeNext, 0.1f, 0.1f, 0.1f); + *eye = *eyeNext; + Camera_BgCheck(camera, at, eye); + break; + + case 7: + if (rwData->unk_1C == 0) { + rwData->unk_0C.yaw = camera->target->shape.rot.y; + sp98[0] = camera->target; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_0C, sp98, 1); + } + *at = targetPosRot->pos; + sp44 = rwData->unk_00; + camera->eyeNext = sp44; + *eye = sp44; + break; + + case 8: + if (rwData->unk_1C == 0) { + rwData->unk_0C.yaw = camera->target->shape.rot.y; + sp98[0] = camera->target; + func_800CC260(camera, &rwData->unk_00, &targetPosRot->pos, &rwData->unk_0C, sp98, 1); + } + Camera_ScaledStepToCeilVec3f(&targetPosRot->pos, at, 0.1f, 0.1f, 0.1f); + Camera_ScaledStepToCeilVec3f(&rwData->unk_00, eyeNext, 0.1f, 0.1f, 0.1f); + *eye = *eyeNext; + Camera_BgCheck(camera, at, eye); + break; + } + + rwData->unk_1C++; + + return true; +} // Data for opening chests (default) -VecSph D_801B9E64[] = { +VecGeo D_801B9E64[] = { { 50.0f, 0xEE3A, 0xD558 }, { 75.0f, 0x0000, 0x8008 }, { 80.0f, 0xEE3A, 0x8008 }, @@ -713,7 +5960,7 @@ Vec3f D_801B9E84[] = { }; // Data for opening chests (goron) -VecSph D_801B9EB4[] = { +VecGeo D_801B9EB4[] = { { 60.0f, 0xEE3A, 0xD558 }, { 95.0f, 0x0000, 0x8008 }, { 90.0f, 0xEE3A, 0x8008 }, @@ -726,140 +5973,2308 @@ Vec3f D_801B9ED4[] = { { 0.0f, 3.0f, -3.0f }, }; -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo2.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo3.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo5.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo6.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo7.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo9.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Demo0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special1.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special2.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special3.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special4.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special5.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special6.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special7.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special8.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Special9.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Alloc.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Free.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Init.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DDFE0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE0E0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_InitPlayerSettings.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ChangeStatus.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE324.s") - -s16 sEarthquakeFreq[] = { - 0xFFC, // 1 Large Earthquake between CLOCK_TIME(0, 00) to CLOCK_TIME(1, 30) - 0x7FC, // 2 Large Earthquakes between CLOCK_TIME(1, 30) to CLOCK_TIME(3, 00) - 0x3FC, // 4 Large Earthquakes between CLOCK_TIME(3, 00) to CLOCK_TIME(4, 30) - 0x1FC, // 8 Large Earthquakes between CLOCK_TIME(4, 30) to CLOCK_TIME(6, 00) -}; -s16 sEarthquakeTimer = 0; - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE62C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE840.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE890.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DE954.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Update.s") - -s32 sModeChangeFlags = 0; - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DF498.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_SetMode.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ChangeMode.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DF86C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DF8EC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ChangeSetting.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ChangeDataIdx.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFC1C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFC40.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetInputDirYaw.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetCamDir.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetCamDirPitch.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetCamDirYaw.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_AddQuake.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_SetViewParam.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFEF0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFF18.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFF34.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800DFF44.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_SetFlags.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ClearFlags.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_ChangeDoorCam.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_Copy.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800E01AC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetQuakeOffset.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800E01DC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800E0228.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800E0238.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_SetToTrackActor.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_SetTargetActor.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/Camera_GetWaterYPos.s") - -#pragma GLOBAL_ASM("asm/non_matchings/code/z_camera/func_800E0348.s") +/** + * Opening large chests. + * The camera position will be at a fixed point, and rotate around at different intervals. + * The direction, and initial position is dependent on when the camera was started. + */ +s32 Camera_Demo2(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + VecGeo atToEye; + VecGeo eyeOffset; + VecGeo atOffset; + Vec3f sp7C; + Vec3f sp70; + Vec3f sp64; + f32 sp60; + s32 pad; + u8 skipUpdateEye = false; + f32 playerHeight = Player_GetHeight((Player*)camera->focalActor); + s16 angle; + VecGeo* sp4C = D_801B9E64; + Vec3f* sp48 = D_801B9E84; + Actor* focalActor = camera->focalActor; + Demo2ReadOnlyData* roData = &camera->paramData.demo2.roData; + Demo2ReadWriteData* rwData = &camera->paramData.demo2.rwData; + + if (((focalActor == &GET_PLAYER(camera->play)->actor) && + (((Player*)focalActor)->transformation == PLAYER_FORM_GORON))) { + sp4C = D_801B9EB4; + sp48 = D_801B9ED4; + } + + Camera_UnsetStateFlag(camera, CAM_STATE_4); + + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->fov = GET_NEXT_RO_DATA(values); + roData->unk_04 = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + OLib_Vec3fDiffToVecGeo(&atToEye, at, eye); + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + Camera_UnsetStateFlag(camera, CAM_STATE_3 | CAM_STATE_2); + Camera_SetUpdateRatesSlow(camera); + camera->fov = roData->fov; + camera->roll = rwData->animFrame = 0; + rwData->initialAt = focalActorPosRot->pos; + if (camera->focalActorFloorHeight != BGCHECK_Y_MIN) { + rwData->initialAt.y = camera->focalActorFloorHeight; + } + angle = focalActorPosRot->rot.y; + sp70.x = rwData->initialAt.x + (Math_SinS(angle) * 40.0f); + sp70.y = rwData->initialAt.y + 40.0f; + sp70.z = rwData->initialAt.z + (Math_CosS(angle) * 40.0f); + if (camera->play->state.frames & 2) { + angle -= 0x4000; + rwData->yawDir = 1; + } else { + angle += 0x4000; + rwData->yawDir = -1; + } + + sp7C.x = sp70.x + (sp4C[1].r * Math_SinS(angle)); + sp7C.y = rwData->initialAt.y + 5.0f; + sp7C.z = sp70.z + (sp4C[1].r * Math_CosS(angle)); + if (Camera_BgCheck(camera, &sp70, &sp7C)) { + rwData->yawDir = -rwData->yawDir; + } + + OLib_Vec3fToVecGeo(&atOffset, &sp48[0]); + atOffset.yaw += focalActorPosRot->rot.y; + OLib_AddVecGeoToVec3f(at, &rwData->initialAt, &atOffset); + + eyeOffset.r = sp4C[0].r; + eyeOffset.pitch = sp4C[0].pitch; + eyeOffset.yaw = (sp4C[0].yaw * rwData->yawDir) + focalActorPosRot->rot.y; + + rwData->unk_0C = 1.0f; + break; + + case 1: + // This is the case taken for nearly the entire cutscene + sp60 = (rwData->animFrame - 2) * (1.0f / 146.0f); + + VEC3F_LERPIMPDST(&sp64, &sp48[0], &sp48[1], sp60); + + OLib_Vec3fToVecGeo(&atOffset, &sp64); + atOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + OLib_AddVecGeoToVec3f(at, &rwData->initialAt, &atOffset); + + atOffset.r = LERPIMP(sp4C[0].r, sp4C[1].r, sp60); + atOffset.pitch = BINANG_LERPIMP(sp4C[0].pitch, sp4C[1].pitch, sp60); + atOffset.yaw = BINANG_LERPIMP(sp4C[0].yaw, sp4C[1].yaw, sp60); + + eyeOffset.r = atOffset.r; + eyeOffset.pitch = atOffset.pitch; + eyeOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + + rwData->unk_0C -= (1.0f / 365.0f); + break; + + case 2: + sp60 = (rwData->animFrame - 148) * 0.1f; + + sp64.x = LERPIMP(sp48[1].x, sp48[2].x, sp60); + sp64.y = LERPIMP((sp48[1].y - playerHeight), sp48[2].y, sp60); + sp64.y += playerHeight; + sp64.z = LERPIMP(sp48[1].z, sp48[2].z, sp60); + + OLib_Vec3fToVecGeo(&atOffset, &sp64); + atOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + OLib_AddVecGeoToVec3f(at, &rwData->initialAt, &atOffset); + + atOffset.r = LERPIMP(sp4C[1].r, sp4C[2].r, sp60); + atOffset.pitch = BINANG_LERPIMP(sp4C[1].pitch, sp4C[2].pitch, sp60); + atOffset.yaw = BINANG_LERPIMP(sp4C[1].yaw, sp4C[2].yaw, sp60); + + eyeOffset.r = atOffset.r; + eyeOffset.pitch = atOffset.pitch; + eyeOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + + rwData->unk_0C -= 0.04f; + break; + + case 3: + sp60 = (rwData->animFrame - 159) * (1.0f / 9.0f); + + sp64.x = LERPIMP(sp48[2].x, sp48[3].x, sp60); + sp64.y = LERPIMP(sp48[2].y, sp48[3].y, sp60); + sp64.y += playerHeight; + sp64.z = LERPIMP(sp48[2].z, sp48[3].z, sp60); + + OLib_Vec3fToVecGeo(&atOffset, &sp64); + atOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + OLib_AddVecGeoToVec3f(at, &rwData->initialAt, &atOffset); + + atOffset.r = LERPIMP(sp4C[2].r, sp4C[3].r, sp60); + atOffset.pitch = BINANG_LERPIMP(sp4C[2].pitch, sp4C[3].pitch, sp60); + atOffset.yaw = BINANG_LERPIMP(sp4C[2].yaw, sp4C[3].yaw, sp60); + + eyeOffset.r = atOffset.r; + eyeOffset.pitch = atOffset.pitch; + eyeOffset.yaw = (atOffset.yaw * rwData->yawDir) + focalActorPosRot->rot.y; + + rwData->unk_0C += (4.0f / 45.0f); + break; + + case 30: + Camera_SetStateFlag(camera, CAM_STATE_10); + if (camera->stateFlags & CAM_STATE_3) { + camera->animState = 4; + } + // fallthrough + case 10: + case 20: + // Taken on the 1st and 158th animation frame + skipUpdateEye = true; + break; + case 4: + eyeOffset.r = 80.0f; + eyeOffset.pitch = 0; + eyeOffset.yaw = atToEye.yaw; + rwData->unk_0C = 0.1f; + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_LARGE, CAM_HUD_VISIBILITY_A, 0); + + if (!(((rwData->animFrame < 0) || (camera->xzSpeed > 0.001f) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R)) && + (camera->stateFlags & CAM_STATE_3))) { + goto skipeyeUpdate; + } + // fallthrough + default: + Camera_SetStateFlag(camera, CAM_STATE_4 | CAM_STATE_2); + Camera_UnsetStateFlag(camera, CAM_STATE_3); + func_800CC938(camera); + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); + skipeyeUpdate: + skipUpdateEye = true; + break; + } + + rwData->animFrame++; + + /** + * Opening a large chest only lasts 135 frames + * + * So for one frame, the animState is set to 10, + * allowing the static data to be loaded into the subCamera mini-heap + * + * For the remainder of the cutscene, animState is set to 1 + */ + if (rwData->animFrame == 1) { + camera->animState = 10; + } else if (rwData->animFrame == 2) { + camera->animState = 1; + } else if (rwData->animFrame == 148) { + camera->animState = 2; + } else if (rwData->animFrame == 158) { + camera->animState = 20; + } else if (rwData->animFrame == 159) { + camera->animState = 3; + } else if (rwData->animFrame == 168) { + camera->animState = 30; + } else if (rwData->animFrame == 228) { + camera->animState = 4; + } + + if (!skipUpdateEye) { + eyeOffset.r = Camera_ScaledStepToCeilF(eyeOffset.r, atToEye.r, rwData->unk_0C, 1.0f); + eyeOffset.pitch = Camera_ScaledStepToCeilS(eyeOffset.pitch, atToEye.pitch, rwData->unk_0C, 5); + eyeOffset.yaw = Camera_ScaledStepToCeilS(eyeOffset.yaw, atToEye.yaw, rwData->unk_0C, 5); + OLib_AddVecGeoToVec3f(eyeNext, at, &eyeOffset); + *eye = *eyeNext; + } + + camera->dist = OLib_Vec3fDist(at, eye); + camera->atLerpStepScale = 0.1f; + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + + return true; +} + +/** + * Taking the warp pad from the start of a dungeon to the boss-room + */ +s32 Camera_Demo3(Camera* camera) { + s32 pad2; + f32 temp; + CameraModeValue* values; + VecGeo atToEye; + PosRot focalActorFocus; + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + Demo3ReadOnlyData* roData = &camera->paramData.demo3.roData; + Demo3ReadWriteData* rwData = &camera->paramData.demo3.rwData; + + OLib_Vec3fDiffToVecGeo(&atToEye, at, eye); + Actor_GetFocus(&focalActorFocus, camera->focalActor); + focalActorFocus.pos.x = camera->focalActorPosRot.pos.x; + focalActorFocus.pos.z = camera->focalActorPosRot.pos.z; + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.4f; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.1f, 0.1f, 0.1f); + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + camera->animState = 0; + } + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + // Init Data + camera->animState++; + rwData->timer = 125; + Distortion_Request(DISTORTION_TYPE_ZORA_SWIMMING); + Distortion_SetDuration(60); + break; + + case 1: + // Zoom into player, start to rise + temp = 1.0f / rwData->timer; + atToEye.r = Camera_ScaledStepToCeilF(140.0f, atToEye.r, temp, 0.1f); + rwData->timer--; + camera->fov = Camera_ScaledStepToCeilF(50.0f, camera->fov, 0.1f, 0.1f); + if (rwData->timer <= 0) { + rwData->timer = 20; + camera->animState++; + Distortion_Request(DISTORTION_TYPE_UNDERWATER_ENTRY); + Distortion_SetDuration(80); + } + break; + + case 2: + // continue rising + rwData->timer--; + if (rwData->timer <= 0) { + rwData->unk_04 = 120; + rwData->timer = 0; + rwData->unk_00 = (175.0f - camera->fov) / rwData->unk_04; + camera->animState++; + Distortion_Request(DISTORTION_TYPE_BOSS_WARP); + Distortion_SetDuration(15); + } + break; + + case 3: + rwData->timer++; + camera->fov += rwData->unk_00 * rwData->timer; + if (rwData->timer >= 15) { + Distortion_RemoveRequest(DISTORTION_TYPE_BOSS_WARP); + Distortion_RemoveRequest(DISTORTION_TYPE_UNDERWATER_ENTRY); + Distortion_RemoveRequest(DISTORTION_TYPE_ZORA_SWIMMING); + camera->animState++; + } + break; + } + + OLib_AddVecGeoToVec3f(eyeNext, at, &atToEye); + *eye = *eyeNext; + return true; +} + +/** + * Mask Transformation Cutscene 0: + * starting as a human and transforming into anything else + */ +s32 Camera_Demo4(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + VecGeo atToEye; + CameraModeValue* values; + PosRot focalActorFocus; + f32 sp58; + f32 sin; + Demo4ReadOnlyData* roData = &camera->paramData.demo4.roData; + Demo4ReadWriteData* rwData = &camera->paramData.demo4.rwData; + s32 pad[2]; + + OLib_Vec3fDiffToVecGeo(&atToEye, at, eye); + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + camera->animState = 0; + rwData->unk_00 = *at; + rwData->unk_18 = atToEye; + rwData->unk_14 = camera->fov; + } + + Actor_GetFocus(&focalActorFocus, camera->focalActor); + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + //! FAKE: + if (1) {} + case 0: + camera->animState++; + rwData->timer = 0; + + if (!(atToEye.r < 40.0f)) { + atToEye.r = 40.0f; + } + + camera->fov = 80.0f; + rwData->unk_10 = (Rand_ZeroOne() - 0.5f) * 40.0f; + // fallthrough + case 1: + // Camera fixed on human player as the mask moves from the pocket to the face + // Camera rolls left and right + if (rwData->timer >= 12) { + rwData->unk_0C = (rwData->timer - 12) * 10.384615f; + sin = sin_rad(DEG_TO_RAD(rwData->unk_0C)); + rwData->unk_0C = ((rwData->unk_10 < 0.0f) ? -1.0f : 1.0f) * sin; + if (rwData->timer == 12) { + Distortion_Request(DISTORTION_TYPE_MASK_TRANSFORM_1); + Distortion_SetDuration(26); + } + } else { + rwData->unk_0C = 0.0f; + } + + sp58 = rwData->timer * (6.0f / 19.0f); + rwData->unk_20 = focalActorPosRot->rot.y + 0x4000; + focalActorFocus.pos.x = (Math_SinS(rwData->unk_20) * sp58 * rwData->unk_0C) + focalActorPosRot->pos.x; + focalActorFocus.pos.z = (Math_CosS(rwData->unk_20) * sp58 * rwData->unk_0C) + focalActorPosRot->pos.z; + focalActorFocus.pos.y -= (focalActorFocus.pos.y - focalActorPosRot->pos.y) * 0.099999994f; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.2f, 0.2f, 0.1f); + + sp58 = (rwData->timer * (30.0f / 19.0f)); + camera->roll = CAM_DEG_TO_BINANG(sp58 * rwData->unk_0C); + + sp58 = 1.0f / (38 - rwData->timer); + rwData->timer++; + atToEye.r = Camera_ScaledStepToCeilF(30.0f, atToEye.r, sp58, 0.1f); + atToEye.pitch = 0; + + if (rwData->timer >= 38) { + rwData->timer = 24; + camera->animState++; + rwData->unk_0C = (32.0f - camera->fov) / 24.0f; + Distortion_Request(DISTORTION_TYPE_MASK_TRANSFORM_2); + } + break; + + case 2: + // Camera steadies as human player is fully croutched down and hiding face + if (rwData->timer == 24) { + at->x = (Math_SinS(focalActorPosRot->rot.y) * -7.0f) + focalActorPosRot->pos.x; + at->y = focalActorFocus.pos.y - ((focalActorFocus.pos.y - focalActorPosRot->pos.y) * 0.1f); + at->z = (Math_CosS(focalActorPosRot->rot.y) * -7.0f) + focalActorPosRot->pos.z; + } else { + focalActorFocus.pos.x = (Math_SinS(focalActorPosRot->rot.y) * -7.0f) + focalActorPosRot->pos.x; + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.1f; + focalActorFocus.pos.z = (Math_CosS(focalActorPosRot->rot.y) * -7.0f) + focalActorPosRot->pos.z; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.25f, 0.25f, 0.1f); + } + + if (rwData->timer > 0) { + camera->fov += rwData->unk_0C; + } + + rwData->timer--; + + atToEye.r = 35.0f; + atToEye.pitch = 0x2000; + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.1f, 5); + + if (rwData->timer <= 0) { + rwData->unk_20 = 630; + rwData->timer = 0; + rwData->unk_0C = (60.0f - camera->fov) / rwData->unk_20; + camera->animState = 3; + } + break; + + case 3: + // Camera zooms into human players face with bulging eyes + focalActorFocus.pos.x = focalActorPosRot->pos.x; + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.1f; + focalActorFocus.pos.z = focalActorPosRot->pos.z; + + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.25f, 0.25f, 0.1f); + + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.1f, 5); + rwData->timer++; + camera->fov += rwData->unk_0C * rwData->timer; + atToEye.pitch = 0x2000; + atToEye.r = 35.0f; + + if (rwData->timer >= 35) { + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_1); + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_2); + camera->animState = 4; + } + break; + + case 999: + Actor_GetFocus(&focalActorFocus, camera->focalActor); + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_1); + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_2); + camera->animState = 4; + break; + + case 4: + // Camera backs up as player is now in a transformed state + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.1f; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.1f, 0.1f, 0.1f); + atToEye = rwData->unk_18; + camera->fov = rwData->unk_14; + camera->roll = 0; + break; + } + + OLib_AddVecGeoToVec3f(&camera->eyeNext, at, &atToEye); + *eye = camera->eyeNext; + + return true; +} + +/** + * Mask Transformation Cutscene 1: + * starting as non-human/fierce diety and transforming into anything else + */ +s32 Camera_Demo5(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + VecGeo atToEye; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + PosRot focalActorFocus; + f32 new_var; + f32 sp58; + f32 sin; + Demo5ReadOnlyData* roData = &camera->paramData.demo5.roData; + Demo5ReadWriteData* rwData = &camera->paramData.demo5.rwData; + CameraModeValue* values; + + OLib_Vec3fDiffToVecGeo(&atToEye, at, eye); + + if (RELOAD_PARAMS(camera)) { + values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + camera->animState = 0; + rwData->unk_00 = *at; + rwData->unk_1C = atToEye; + rwData->unk_18 = camera->fov; + } + + Actor_GetFocus(&focalActorFocus, camera->focalActor); + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + camera->animState++; + atToEye.pitch = 0; + rwData->timer = 0x12; + rwData->unk_14 = 80.0f; + atToEye.r = 30.0f; + camera->fov = 80.0f; + rwData->unk_10 = (Rand_ZeroOne() - 0.5f) * 40.0f; + camera->roll = 0; + focalActorFocus.pos.x = focalActorPosRot->pos.x; + focalActorFocus.pos.z = focalActorPosRot->pos.z; + *at = focalActorFocus.pos; + // fallthrough + case 1: + // Camera remains still as player moves hands to face + rwData->timer--; + if (rwData->timer <= 0) { + rwData->timer = 0; + camera->animState = 2; + rwData->unk_24 = camera->focalActorPosRot.rot.y + 0x4000; + rwData->timer = 46; + Distortion_Request(DISTORTION_TYPE_MASK_TRANSFORM_1); + Distortion_SetDuration(46); + } + break; + + case 2: + // Camera zooms out while rolling back and forth + rwData->unk_0C = rwData->timer * (180.0f / 23.0f); + sp58 = DEG_TO_RAD(rwData->unk_0C); + sin = sin_rad(sp58); + rwData->unk_0C = ((rwData->unk_10 < 0.0f) ? -1.0f : 1.0f) * sin; + new_var = (46 - rwData->timer) * (5.0f / 46.0f); + focalActorFocus.pos.x = (Math_SinS(rwData->unk_24) * new_var * rwData->unk_0C) + focalActorPosRot->pos.x; + focalActorFocus.pos.z = (Math_CosS(rwData->unk_24) * new_var * rwData->unk_0C) + focalActorPosRot->pos.z; + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.2f; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.1f, 0.1f, 0.1f); + new_var = rwData->timer * (10.0f / 23.0f); + camera->roll = CAM_DEG_TO_BINANG(rwData->unk_0C * new_var); + new_var = 1.0f / rwData->timer; + atToEye.r = Camera_ScaledStepToCeilF(rwData->unk_14, atToEye.r, new_var, 0.1f); + rwData->timer--; + atToEye.pitch = 0; + if (rwData->timer <= 0) { + camera->animState = 3; + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_1); + } + break; + + case 999: + Actor_GetFocus(&focalActorFocus, camera->focalActor); + camera->animState = 3; + Distortion_RemoveRequest(DISTORTION_TYPE_MASK_TRANSFORM_1); + break; + + case 3: + // Player is in new form + focalActorFocus.pos.y -= (focalActorFocus.pos.y - camera->focalActorPosRot.pos.y) * 0.1f; + Camera_ScaledStepToCeilVec3f(&focalActorFocus.pos, at, 0.1f, 0.1f, 0.1f); + camera->roll = 0; + atToEye = rwData->unk_1C; + camera->fov = rwData->unk_18; + break; + } + + OLib_AddVecGeoToVec3f(eyeNext, at, &atToEye); + *eye = *eyeNext; + + return true; +} + +s32 Camera_Demo6(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Demo7(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Demo8(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Demo9(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Smoothly and gradually return camera to Player after a cutscene + * Used for global actorCsId = 0x7E (Connect Camera Setting) + */ +s32 Camera_Demo0(Camera* camera) { + s32 pad; + f32 timer; + s16 phi_v1; + Camera* subCam = &camera->play->subCameras[2]; + Vec3f* eye = &camera->eye; + Vec3f* subEye = &subCam->eye; + Vec3f* at = &camera->at; + Demo0ReadOnlyData* roData = &camera->paramData.demo0.roData; + Demo0ReadWriteData* rwData = &camera->paramData.demo0.rwData; + + // Initialize + if (camera->animState == 0) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + // Initialize + if (camera->animState == 0) { + OLib_Vec3fDiffToVecGeo(&rwData->subAtToEye, &subCam->at, subEye); + OLib_Vec3fDiffToVecGeo(&rwData->atToEye, &camera->at, eye); + if (rwData->subAtToEye.r < 50.0f) { + rwData->subAtToEye.r = 50.0f; + if (rwData->subAtToEye.pitch < 0x7D0) { // 11 degrees + rwData->subAtToEye.pitch = 0x7D0; + } + } + + rwData->unk_00 = OLib_Vec3fDist(eye, subEye); + if (rwData->unk_00 < 300.0f) { + rwData->timer = 0; + } else { + rwData->timer = sqrtf(rwData->unk_00 - 200.0f); + } + + rwData->unk_14 = subCam->inputDir.x - camera->inputDir.x; + if (rwData->unk_14 >= 0) { + phi_v1 = rwData->unk_14; + } else { + phi_v1 = -rwData->unk_14; + } + + if (phi_v1 > 10000) { + phi_v1 /= 1000; + if (rwData->timer < phi_v1) { + rwData->timer = phi_v1; + } + } + + rwData->unk_16 = subCam->inputDir.y - camera->inputDir.y; + if (rwData->unk_16 >= 0) { + phi_v1 = rwData->unk_16; + } else { + phi_v1 = -rwData->unk_16; + } + + if (phi_v1 > 10000) { + phi_v1 /= 1000; + if (rwData->timer < phi_v1) { + rwData->timer = phi_v1; + } + } + + rwData->unk_18 = subCam->inputDir.z - camera->inputDir.z; + if (rwData->unk_18 >= 0) { + phi_v1 = rwData->unk_18; + } else { + phi_v1 = -rwData->unk_18; + } + + if (phi_v1 > 10000) { + phi_v1 /= 1000; + if (rwData->timer < phi_v1) { + rwData->timer = phi_v1; + } + } + + if (rwData->timer != 0) { + rwData->unk_00 = (rwData->subAtToEye.r - rwData->atToEye.r) / rwData->timer; + rwData->unk_14 = (s16)(rwData->subAtToEye.pitch - rwData->atToEye.pitch) / rwData->timer; + rwData->unk_16 = (s16)(rwData->subAtToEye.yaw - rwData->atToEye.yaw) / rwData->timer; + rwData->unk_18 = (s16)(subCam->roll - camera->roll) / rwData->timer; + } + camera->animState++; + } + + if (rwData->timer != 0) { + timer = rwData->timer; + + // Update At (Inverse Interpolation) + at->x += (subCam->at.x - camera->at.x) / timer; + at->y += (subCam->at.y - camera->at.y) / timer; + at->z += (subCam->at.z - camera->at.z) / timer; + + rwData->atToEye.r += rwData->unk_00; + rwData->atToEye.pitch += rwData->unk_14; + rwData->atToEye.yaw += rwData->unk_16; + + camera->roll += rwData->unk_18; + + // Update Eye + OLib_AddVecGeoToVec3f(eye, at, &rwData->atToEye); + camera->eyeNext = *eye; + + rwData->timer--; + } + + if (rwData->timer == 0) { + CutsceneManager_Stop(0x7E); + } + + return true; +} + +s32 Camera_Special0(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Special1(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Special2(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Special3(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Special4(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Flying with hookshot + */ +s32 Camera_Special5(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot spA8; + s16 pad1; + s16 spA4; + CameraCollision sp7C; + VecGeo sp74; + VecGeo sp6C; + VecGeo atToEye; + VecGeo atToEyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Special5ReadOnlyData* roData = &camera->paramData.spec5.roData; + Special5ReadWriteData* rwData = &camera->paramData.spec5.rwData; + f32 rand; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + + if (RELOAD_PARAMS(camera)) { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + f32 yNormal = (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + + roData->yOffset = (GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight) * yNormal; + roData->eyeDist = GET_NEXT_RO_DATA(values); + roData->minDistForRot = GET_NEXT_RO_DATA(values); + roData->pitch = CAM_DEG_TO_BINANG(GET_NEXT_RO_DATA(values)); + roData->fovTarget = GET_NEXT_RO_DATA(values); + roData->atMaxLERPScale = GET_NEXT_SCALED_RO_DATA(values); + roData->timerInit = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + OLib_Vec3fDiffToVecGeo(&atToEye, at, eye); + OLib_Vec3fDiffToVecGeo(&atToEyeNext, at, eyeNext); + Actor_GetWorld(&spA8, camera->target); + + sCameraInterfaceFlags = roData->interfaceFlags; + + if (camera->animState == 0) { + camera->animState++; + rwData->animTimer = roData->timerInit; + } + + if (rwData->animTimer > 0) { + rwData->animTimer--; + } else if (rwData->animTimer == 0) { + if ((camera->target == NULL) || (camera->target->update == NULL)) { + camera->target = NULL; + return true; + } + + rwData->animTimer--; + if (roData->minDistForRot < OLib_Vec3fDist(&spA8.pos, &focalActorPosRot->pos)) { + sp6C.yaw = focalActorPosRot->rot.y; + sp6C.pitch = -focalActorPosRot->rot.x; + sp6C.r = 20.0f; + OLib_AddVecGeoToVec3f(&sp7C.pos, &spA8.pos, &sp6C); + func_800CBC84(camera, at, &sp7C, 0); + OLib_Vec3fToVecGeo(&sp6C, &sp7C.norm); + spA4 = BINANG_SUB(focalActorPosRot->rot.y, sp6C.yaw); + sp74.r = roData->eyeDist; + rand = Rand_ZeroOne(); + sp74.yaw = BINANG_ROT180(focalActorPosRot->rot.y) + + (s16)(spA4 < 0 ? -(s16)(0x1553 + (s16)(rand * 2730.0f)) : (s16)(0x1553 + (s16)(rand * 2730.0f))); + sp74.pitch = roData->pitch; + OLib_AddVecGeoToVec3f(eyeNext, &spA8.pos, &sp74); + *eye = *eyeNext; + Camera_BgCheck(camera, &spA8.pos, eye); + } + } + + Camera_CalcAtDefault(camera, &atToEyeNext, roData->yOffset, 0); + camera->fov = Camera_ScaledStepToCeilF(roData->fovTarget, camera->fov, camera->atLerpStepScale * 0.05f, 0.1f); + camera->roll = Camera_ScaledStepToCeilS(0, camera->roll, 0.5f, 5); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, roData->atMaxLERPScale); + + return true; +} + +s32 Camera_Special6(Camera* camera) { + return Camera_Noop(camera); +} + +s32 Camera_Special7(Camera* camera) { + return Camera_Noop(camera); +} + +/** + * Exiting a spiral staircase cutscene. + * Camera remains fixed at given position, and tracks player for the duration of the cutscene + */ +s32 Camera_Special8(Camera* camera) { + Vec3f* at = &camera->at; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + Vec3f atTarget; + Vec3f posOffsetTarget; + f32 yNormal; + f32 focalActorHeight = Camera_GetFocalActorHeight(camera); + DoorParams* doorParams = &camera->paramData.doorParams; + Special8ReadOnlyData* roData = &camera->paramData.spec8.roData; + Special8ReadWriteData* rwData = &camera->paramData.spec8.rwData; + s32 pad[2]; + + Camera_UnsetStateFlag(camera, CAM_STATE_4); + yNormal = (0.8f - ((68.0f / focalActorHeight) * -0.2f)); + + if (!RELOAD_PARAMS(camera)) { + } else { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + // Initialize data + roData->yOffset = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal; + roData->eyeStepScale = GET_NEXT_SCALED_RO_DATA(values); + roData->posStepScale = GET_NEXT_SCALED_RO_DATA(values); + roData->fov = GET_NEXT_RO_DATA(values); + roData->spiralDoorCsLength = GET_NEXT_RO_DATA(values) * 5; + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + rwData->fov = roData->fov * 100.0f; + rwData->spiralDoorCsFrame = 0; + Camera_UnsetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + rwData->eye.x = doorParams->eye.x; + rwData->eye.y = doorParams->eye.y; + rwData->eye.z = doorParams->eye.z; + } + + // Check if cutscene is still playing + if (rwData->spiralDoorCsFrame < roData->spiralDoorCsLength) { + rwData->spiralDoorCsFrame++; + sCameraInterfaceFlags = roData->interfaceFlags; + posOffsetTarget.x = 0.0f; + posOffsetTarget.y = roData->yOffset + focalActorHeight; + posOffsetTarget.z = 0.0f; + Camera_ScaledStepToCeilVec3f(&posOffsetTarget, &camera->focalActorAtOffset, roData->posStepScale, + roData->posStepScale, 0.1f); + + // Camera follows player as they exit the stairwell + atTarget.x = focalActorPosRot->pos.x + camera->focalActorAtOffset.x; + atTarget.y = focalActorPosRot->pos.y + camera->focalActorAtOffset.y; + atTarget.z = focalActorPosRot->pos.z + camera->focalActorAtOffset.z; + if (camera->animState == 0) { + camera->animState++; + if (!(roData->interfaceFlags & SPECIAL8_FLAG_0)) { + camera->eyeNext = rwData->eye; + camera->at = atTarget; + } + } + + // Update at to look at player + Camera_ScaledStepToCeilVec3f(&atTarget, at, roData->posStepScale, roData->posStepScale, 10.0f); + + // Move camera position &rwData->eye and remain there for the entire cutscen + Camera_ScaledStepToCeilVec3f(&rwData->eye, eyeNext, roData->eyeStepScale, roData->eyeStepScale, 0.1f); + camera->eye = *eyeNext; + camera->dist = OLib_Vec3fDist(at, &camera->eye); + camera->roll = 0; + camera->xzSpeed = 0.0f; + camera->fov = CAM_RODATA_UNSCALE(rwData->fov); + camera->atLerpStepScale = Camera_ClampLerpScale(camera, 1.0f); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + } else { + // Cutscene is finished + Camera_SetStateFlag(camera, CAM_STATE_10 | CAM_STATE_4); + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); + + // Wait for user input to move to the next camera update function + if ((camera->xzSpeed > 0.001f) || CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R) || + (roData->interfaceFlags & SPECIAL8_FLAG_3)) { + func_800CC938(camera); + Camera_SetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + Camera_UnsetStateFlag(camera, CAM_STATE_10); + } + } + return true; +} + +/** + * Entering and exiting a door between rooms (eg. sliding doors) + * Camera closely follows player on both the front and the back room + */ +s32 Camera_Special9(Camera* camera) { + Vec3f* eye = &camera->eye; + Vec3f* at = &camera->at; + s32 rand1; + Vec3f spB8; + VecGeo spB0; + VecGeo spA8; + f32 focalActorHeight; + s32 phi_v1_2; + s16 actorCsId; + f32 yNormal; + PosRot sp84; + Vec3f* eyeNext = &camera->eyeNext; + PosRot* focalActorPosRot = &camera->focalActorPosRot; + DoorParams* doorParams = &camera->paramData.doorParams; + Special9ReadOnlyData* roData = &camera->paramData.spec9.roData; + Special9ReadWriteData* rwData = &camera->paramData.spec9.rwData; + s32 sp50[1]; + BgCamFuncData* bgCamFuncData; + + focalActorHeight = Camera_GetFocalActorHeight(camera); + actorCsId = CutsceneManager_GetCurrentCsId(); + + if ((actorCsId != -1) && (actorCsId != 0x7D)) { + func_800E0348(camera); + } + + Camera_UnsetStateFlag(camera, CAM_STATE_4); + yNormal = 0.8f - ((68.0f / focalActorHeight) * -0.2f); + + if (!RELOAD_PARAMS(camera)) { + } else { + CameraModeValue* values = sCameraSettings[camera->setting].cameraModes[camera->mode].values; + + roData->yOffset = GET_NEXT_SCALED_RO_DATA(values) * focalActorHeight * yNormal; + roData->fov = GET_NEXT_RO_DATA(values); + roData->interfaceFlags = GET_NEXT_RO_DATA(values); + } + + if (doorParams->doorActor != NULL) { + Actor_GetWorldPosShapeRot(&sp84, doorParams->doorActor); + } else { + sp84 = *focalActorPosRot; + sp84.pos.y += focalActorHeight + roData->yOffset; + sp84.rot.x = 0; + } + + OLib_Vec3fDiffToVecGeo(&spA8, at, eye); + + sCameraInterfaceFlags = roData->interfaceFlags; + + switch (camera->animState) { + case 0: + // Init + Camera_UnsetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + camera->animState++; + if (ABS((s16)(focalActorPosRot->rot.y - sp84.rot.y)) > 0x4000) { + rwData->unk_00 = BINANG_ROT180(sp84.rot.y); + } else { + rwData->unk_00 = sp84.rot.y; + } + // fallthrough + case 1: + // Camera is fixed in front of the door + doorParams->timer1--; + if (doorParams->timer1 > 0) { + break; + } + + camera->animState++; + + // Setup for the camera moving behind the door + if (roData->interfaceFlags & SPECIAL9_FLAG_0) { + bgCamFuncData = (BgCamFuncData*)Camera_GetBgCamOrActorCsCamFuncData(camera, camera->bgCamIndex); + Camera_Vec3sToVec3f(eyeNext, &bgCamFuncData->pos); + spB8 = *eye = *eyeNext; + } else { + s16 camEyeSide; + s16 randFloat; + + spB0.pitch = ((s16)(Rand_ZeroOne() * 0x280) + 0xBB8); + randFloat = ((s16)(Rand_ZeroOne() * 0x4CE) + 0x5DC); + + // The camera will either position itself either to the left or to the right + // of the door when it jumps behind it. It's effectively 50/50 percent chance + camEyeSide = (s16)(randFloat * ((camera->play->state.frames % 2) ? 1 : -1)); + + spB0.yaw = rwData->unk_00 + camEyeSide; + spB0.r = 200.0f * yNormal; + OLib_AddVecGeoToVec3f(eyeNext, at, &spB0); + spB8 = *eye = *eyeNext; + + // If the side chosen moves the camera out-of-bounds, move to the other side + if (Camera_CheckOOB(camera, &spB8, &focalActorPosRot->pos)) { + camEyeSide = (s16)-camEyeSide; + spB0.yaw = rwData->unk_00 + camEyeSide; + OLib_AddVecGeoToVec3f(eyeNext, at, &spB0); + *eye = *eyeNext; + } + } + // fallthrough + case 2: + // Camera is behind the door looking at player + spB8 = focalActorPosRot->pos; + spB8.y += focalActorHeight + roData->yOffset; + // Update camera at to follow the player + Camera_ScaledStepToCeilVec3f(&spB8, at, 0.25f, 0.25f, 0.1f); + + doorParams->timer2--; + if (doorParams->timer2 > 0) { + break; + } + + // Setup for the camera turning around to look in front of player + camera->animState++; + rwData->unk_00 = BINANG_ROT180(rwData->unk_00); + // fallthrough + case 3: + // Camera turns around to look in front of player + spB8 = focalActorPosRot->pos; + spB8.y += focalActorHeight + roData->yOffset; + Camera_ScaledStepToCeilVec3f(&spB8, at, 0.5f, 0.5f, 0.1f); + spB0.pitch = Camera_ScaledStepToCeilS(0xAAA, spA8.pitch, 0.3f, 5); + spB0.yaw = Camera_ScaledStepToCeilS(rwData->unk_00, spA8.yaw, 0.3f, 5); + spB0.r = Camera_ScaledStepToCeilF(60.0f, spA8.r, 0.3f, 1.0f); + OLib_AddVecGeoToVec3f(eyeNext, at, &spB0); + + *eye = *eyeNext; + + doorParams->timer3--; + if (doorParams->timer3 > 0) { + break; + } + + camera->animState++; + // fallthrough + case 4: + camera->animState++; + // fallthrough + case 999: + default: + // Door is closed and is waiting for user input to toggle to a new setting + Camera_SetStateFlag(camera, CAM_STATE_10 | CAM_STATE_4); + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_NONE, CAM_HUD_VISIBILITY_ALL, 0); + + if ((camera->xzSpeed > 0.001f) || CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_A) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_B) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CUP) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CDOWN) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CLEFT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_CRIGHT) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_Z) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_L) || + CHECK_BTN_ALL(CONTROLLER1(&camera->play->state)->press.button, BTN_R) || + (roData->interfaceFlags & SPECIAL9_FLAG_3)) { + + func_800CC938(camera); + Camera_SetStateFlag(camera, CAM_STATE_2 | CAM_STATE_CHECK_WATER); + Camera_UnsetStateFlag(camera, CAM_STATE_10); + } + break; + } + + spB8 = focalActorPosRot->pos; + spB8.y += focalActorHeight; + camera->dist = OLib_Vec3fDist(&spB8, eye); + Camera_SetFocalActorAtOffset(camera, &focalActorPosRot->pos); + + return true; +} + +/*===============================================================*/ +/* Camera Public Functions */ +/*===============================================================*/ + +Camera* Camera_Create(View* view, CollisionContext* colCtx, PlayState* play) { + Camera* newCamera = ZeldaArena_Malloc(sizeof(Camera)); + + if (newCamera != NULL) { + Camera_Init(newCamera, view, colCtx, play); + } + return newCamera; +} + +void Camera_Destroy(Camera* camera) { + if (camera != NULL) { + ZeldaArena_Free(camera); + } +} + +void Camera_Init(Camera* camera, View* view, CollisionContext* colCtx, PlayState* play) { + Camera* cameraPtr; + s32 i; + s16 curUID; + s16 j; + + __osMemset(camera, 0, sizeof(Camera)); + + camera->play = sCamPlayState = play; + curUID = sCameraNextUID; + sCameraNextUID++; + while (curUID != 0) { + if (curUID == 0) { + sCameraNextUID++; + } + + for (j = 0; j < NUM_CAMS; j++) { + cameraPtr = camera->play->cameraPtrs[j]; + if ((cameraPtr != NULL) && (curUID == cameraPtr->uid)) { + break; + } + } + + if (j == NUM_CAMS) { + break; + } + + curUID = sCameraNextUID++; + } + + camera->inputDir.y = 0x4000; + camera->uid = curUID; + camera->camDir = camera->inputDir; + camera->nextCamSceneDataId = -1; + camera->up.z = camera->up.x = 0.0f; + camera->up.y = 1.0f; + camera->fov = 60.0f; + camera->yOffsetUpdateRate = 0.05f; + camera->xzOffsetUpdateRate = 0.05f; + camera->fovUpdateRate = 0.05f; + camera->rUpdateRateInv = 10.0f; + camera->yawUpdateRateInv = 10.0f; + camera->pitchUpdateRateInv = 16.0f; + + sCameraLetterboxSize = 32; + sCameraHudVisibility = 0; + + camera->setting = camera->prevSetting = CAM_SET_FREE0; + camera->bgCamIndex = camera->prevBgCamDataId = -1; + camera->stateFlags = 0; + camera->mode = CAM_MODE_NORMAL; + camera->bgId = BGCHECK_SCENE; + camera->unk168 = 0xF; + camera->timer = -1; + camera->focalActor = NULL; + camera->target = NULL; + Camera_SetStateFlag(camera, CAM_STATE_INITIALIZED); + camera->quakeOffset.z = camera->quakeOffset.y = camera->quakeOffset.x = 0; + camera->up.z = camera->up.x = 0.0f; + camera->atLerpStepScale = 1; + camera->up.y = 1.0f; + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_IGNORE, CAM_HUD_VISIBILITY_IGNORE, 0); + sCameraInitSceneTimer = 3; +} + +void func_800DDFE0(Camera* camera) { + if (camera != &camera->play->mainCamera) { + camera->prevSetting = camera->setting = CAM_SET_FREE0; + Camera_UnsetStateFlag(camera, CAM_STATE_2); + } else { + switch (camera->play->roomCtx.curRoom.behaviorType1) { + case ROOM_BEHAVIOR_TYPE1_1: + camera->prevSetting = CAM_SET_DUNGEON0; + Camera_ChangeSettingFlags(camera, CAM_SET_DUNGEON0, CAM_CHANGE_SETTING_1); + break; + + case ROOM_BEHAVIOR_TYPE1_0: + camera->prevSetting = CAM_SET_NORMAL0; + Camera_ChangeSettingFlags(camera, CAM_SET_NORMAL0, CAM_CHANGE_SETTING_1); + break; + + case ROOM_BEHAVIOR_TYPE1_2: + camera->prevSetting = CAM_SET_ROOM0; + Camera_ChangeSettingFlags(camera, CAM_SET_ROOM0, CAM_CHANGE_SETTING_1); + break; + + default: + camera->prevSetting = CAM_SET_NORMAL0; + Camera_ChangeSettingFlags(camera, CAM_SET_NORMAL0, CAM_CHANGE_SETTING_1); + break; + } + Camera_SetStateFlag(camera, CAM_STATE_2); + } +} + +/** + * Unused empty function + */ +void Camera_Stub800DE0E0(Camera* camera) { +} + +void Camera_InitFocalActorSettings(Camera* camera, Actor* focalActor) { + PosRot focalActorPosRot; + VecGeo eyeNextAtOffset; + s32 bgId; + Vec3f floorPos; + s32 upXZ; + f32 focalActorHeight; + Vec3f* eye = &camera->eye; + + Actor_GetWorldPosShapeRot(&focalActorPosRot, focalActor); + + camera->focalActor = focalActor; + focalActorHeight = Camera_GetFocalActorHeight(camera); + camera->focalActorPosRot = focalActorPosRot; + camera->dist = eyeNextAtOffset.r = 180.0f; + camera->inputDir.y = focalActorPosRot.rot.y; + eyeNextAtOffset.yaw = BINANG_ROT180(camera->inputDir.y); + camera->inputDir.x = eyeNextAtOffset.pitch = 0x71C; + camera->inputDir.z = 0; + camera->camDir = camera->inputDir; + camera->xzSpeed = 0.0f; + camera->unk_0F0.y = 0.0f; + camera->at = focalActorPosRot.pos; + camera->at.y += focalActorHeight; + + camera->focalActorAtOffset.x = 0; + camera->focalActorAtOffset.y = focalActorHeight; + camera->focalActorAtOffset.z = 0; + + OLib_AddVecGeoToVec3f(&camera->eyeNext, &camera->at, &eyeNextAtOffset); + *eye = camera->eyeNext; + camera->roll = 0; + + upXZ = 0; + camera->up.z = upXZ; + camera->up.y = 1.0f; + camera->up.x = upXZ; + + { + s32 pad; + + if (Camera_GetFloorYNorm(camera, &floorPos, &camera->at, &bgId) != BGCHECK_Y_MIN) { + camera->bgId = bgId; + } + } + + camera->waterPrevBgCamDataId = -1; + camera->waterPrevCamSetting = -1; + camera->waterQuakeId = -1; + + { + s32 pad; + + func_800DDFE0(camera); + } + + Camera_SetStateFlag(camera, CAM_STATE_2); + + camera->viewFlags = 0; + camera->nextCamSceneDataId = -1; + camera->yOffsetUpdateRate = 0.01f; + camera->xzOffsetUpdateRate = 0.01f; + camera->fovUpdateRate = 0.01f; + camera->atLerpStepScale = 1; + Camera_ResetActionFuncState(camera, camera->mode); + + if (camera == &camera->play->mainCamera) { + sCameraInterfaceFlags = + CAM_INTERFACE_FLAGS(CAM_LETTERBOX_LARGE | CAM_LETTERBOX_INSTANT, CAM_HUD_VISIBILITY_NONE_ALT, 0); + CutsceneManager_StoreCamera(camera); + } else { + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_LARGE, CAM_HUD_VISIBILITY_NONE_ALT, 0); + } + Camera_UpdateWater(camera); +} + +/** + * Updates the camera status + */ +s32 Camera_ChangeStatus(Camera* camera, s16 status) { + camera->status = status; + return camera->status; +} + +s32 Camera_UpdateWater(Camera* camera) { + f32 waterY; + s16 camSetting; + s32 pad[2]; + s32* waterPrevCamSetting = &camera->waterPrevCamSetting; + s16 prevBgId; + + if (!(camera->stateFlags & CAM_STATE_CHECK_WATER) || (sCameraSettings[camera->setting].flags & 0x40000000)) { + return false; + } + + if (camera->stateFlags & CAM_STATE_9) { + if (Camera_IsDiving(camera)) { + if (!Camera_IsPlayerFormZora(camera)) { + Camera_ChangeSettingFlags(camera, CAM_SET_PIVOT_DIVING, CAM_CHANGE_SETTING_2 | CAM_CHANGE_SETTING_1); + } else { + Camera_ChangeSettingFlags(camera, CAM_SET_ZORA_DIVING, CAM_CHANGE_SETTING_2 | CAM_CHANGE_SETTING_1); + } + Camera_SetStateFlag(camera, CAM_STATE_15); + } else if (camera->stateFlags & CAM_STATE_15) { + Camera_ChangeSettingFlags(camera, *waterPrevCamSetting, CAM_CHANGE_SETTING_2 | CAM_CHANGE_SETTING_1); + Camera_UnsetStateFlag(camera, CAM_STATE_15); + } + } + + if (!(camera->stateFlags & CAM_STATE_15)) { + camSetting = Camera_GetWaterBoxBgCamSetting(camera, &waterY); + if (camSetting == -2) { + // CAM_SET_NONE + if (!(camera->stateFlags & CAM_STATE_9)) { + Camera_SetStateFlag(camera, CAM_STATE_9); + camera->waterPrevBgCamDataId = camera->bgCamIndex; + camera->waterQuakeId = -1; + } + + if (!(Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight) < 11.0f) || + (Camera_IsSwimming(camera) && !Camera_IsUnderwaterAsZora(camera))) { + prevBgId = camera->bgId; + camera->bgId = BGCHECK_SCENE; + waterPrevCamSetting = &camera->waterPrevCamSetting; + Camera_ChangeSettingFlags(camera, CAM_SET_NORMAL3, CAM_CHANGE_SETTING_1); + *waterPrevCamSetting = camera->setting; + camera->bgId = prevBgId; + camera->bgCamIndex = -2; + } + + } else if (camSetting != -1) { + // player is in a water box + if (!(camera->stateFlags & CAM_STATE_9)) { + Camera_SetStateFlag(camera, CAM_STATE_9); + camera->waterPrevBgCamDataId = camera->bgCamIndex; + camera->waterQuakeId = -1; + } + + if (!(Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight) < 11.0f) || + (Camera_IsSwimming(camera) && !Camera_IsUnderwaterAsZora(camera))) { + prevBgId = camera->bgId; + camera->bgId = BGCHECK_SCENE; + waterPrevCamSetting = &camera->waterPrevCamSetting; + Camera_ChangeSettingFlags(camera, camSetting, CAM_CHANGE_SETTING_1); + *waterPrevCamSetting = camera->setting; + camera->bgId = prevBgId; + } + + } else if (camera->stateFlags & CAM_STATE_9) { + // player is out of a water box. + Camera_UnsetStateFlag(camera, CAM_STATE_9); + prevBgId = camera->bgId; + camera->bgId = BGCHECK_SCENE; + if (camera->waterPrevBgCamDataId < 0) { + func_800DDFE0(camera); + camera->bgCamIndex = -1; + } else { + Camera_ChangeActorCsCamIndex(camera, camera->waterPrevBgCamDataId); + } + camera->bgId = prevBgId; + } + camera->waterYPos = waterY; + } + return true; +} + +void Camera_EarthquakeDay3(Camera* camera) { + static s16 sEarthquakeTimer = 0; + u16 time; + s16 quakeIndex; + s32 timeSpeedOffset; + s16 sEarthquakeFreq[] = { + 0xFFC, // 1 Large Earthquake between CLOCK_TIME(0, 00) to CLOCK_TIME(1, 30) + 0x7FC, // 2 Large Earthquakes between CLOCK_TIME(1, 30) to CLOCK_TIME(3, 00) + 0x3FC, // 4 Large Earthquakes between CLOCK_TIME(3, 00) to CLOCK_TIME(4, 30) + 0x1FC, // 8 Large Earthquakes between CLOCK_TIME(4, 30) to CLOCK_TIME(6, 00) + }; + + if ((CURRENT_DAY == 3) && (CutsceneManager_GetCurrentCsId() == -1)) { + time = gSaveContext.save.time; + timeSpeedOffset = gSaveContext.save.timeSpeedOffset; + + // Large earthquake created + // Times based on sEarthquakeFreq + if ((time > CLOCK_TIME(0, 0)) && (time < CLOCK_TIME(6, 0)) && ((sEarthquakeFreq[time >> 12] & time) == 0) && + (Quake_GetNumActiveQuakes() < 2)) { + quakeIndex = Quake_Request(camera, QUAKE_TYPE_4); + if (quakeIndex != 0) { + Quake_SetSpeed(quakeIndex, 30000); + Quake_SetPerturbations(quakeIndex, (time >> 12) + 2, 1, 5, 60); + sEarthquakeTimer = ((time >> 10) - timeSpeedOffset) + 80; + Quake_SetDuration(quakeIndex, sEarthquakeTimer); + } + } + + // Small earthquake created + // Around CLOCK_TIME(17, 33) || Around CLOCK_TIME(20, 33) || Every 1024 frames (around every 51s) + if (((((time + 0x4D2) & 0xDFFC) == 0xC000) || ((camera->play->state.frames % 1024) == 0)) && + (Quake_GetNumActiveQuakes() < 2)) { + quakeIndex = Quake_Request(camera, QUAKE_TYPE_3); + if (quakeIndex != 0) { + Quake_SetSpeed(quakeIndex, 16000); + Quake_SetPerturbations(quakeIndex, 1, 0, 0, time & 0x3F); // %64 + sEarthquakeTimer = 120 - timeSpeedOffset; + Quake_SetDuration(quakeIndex, sEarthquakeTimer); + } + } + + if (sEarthquakeTimer != 0) { + sEarthquakeTimer--; + func_8019F128(NA_SE_SY_EARTHQUAKE_OUTDOOR - SFX_FLAG); + } + } +} + +/** + * Sets the distortion to type 1 for a hot room + * Remnant of OoT as no room in any MM scene is set to a hot-room + */ +s32 Camera_UpdateHotRoom(Camera* camera) { + Distortion_RemoveRequest(DISTORTION_TYPE_HOT_ROOM); + if (camera->play->roomCtx.curRoom.behaviorType2 == ROOM_BEHAVIOR_TYPE2_HOT) { + Distortion_Request(DISTORTION_TYPE_HOT_ROOM); + } + return true; +} + +s32 Camera_SetSwordDistortion(Camera* camera) { + switch (func_800CBB88(camera)) { + case 1: + // non-magic spin attack + if (Distortion_GetType() != DISTORTION_TYPE_ZORA_KICK) { + Distortion_Request(DISTORTION_TYPE_ZORA_KICK); + Distortion_SetDuration(12); + } + break; + + case 2: + // Unused: case 2 is impossible to achieve + if (Distortion_GetType() != DISTORTION_TYPE_UNK_ATTACK) { + Distortion_Request(DISTORTION_TYPE_UNK_ATTACK); + Distortion_SetDuration(5); + } + break; + + case 3: + if (Distortion_GetType() != DISTORTION_TYPE_GORON_BUTT) { + Distortion_Request(DISTORTION_TYPE_GORON_BUTT); + Distortion_SetDuration(15); + } + break; + } + return true; +} + +s32 Camera_RequestGiantsMaskSetting(Camera* camera) { + Player* player = GET_PLAYER(camera->play); + + if ((camera->camId == CAM_ID_MAIN) && (camera->focalActor == &GET_PLAYER(camera->play)->actor) && + (player->currentMask == PLAYER_MASK_GIANT)) { + Camera_ChangeSettingFlags(camera, CAM_SET_GIANT, CAM_CHANGE_SETTING_1); + return true; + } else { + return false; + } +} + +Vec3s* Camera_Update(Vec3s* inputDir, Camera* camera) { + Vec3f viewAt; + Vec3f viewEye; + Vec3f viewUp; + Vec3f focalActorPos; + s32 bgId; + s32 sp98; + s32 changeCamSceneDataType; + CollisionPoly* sp90; + CollisionPoly* sp8C; + f32 runSpeedLimit; + f32 speed; + f32 viewFov; + DynaPolyActor* meshActor; + PosRot focalActorPosRot; + ShakeInfo camShake; + Actor* focalActor = camera->focalActor; + VecGeo sp3C; + s16 bgCamIndex; + s16 numQuakesApplied; + f32 focalActorFloorHeight; + + // Camera of status CUT only updates to this point + if (camera->status == CAM_STATUS_CUT) { + *inputDir = camera->inputDir; + return inputDir; + } + + sUpdateCameraDirection = false; + sIsFalse = false; + + if (camera->play->view.unk164 == 0) { + if (camera->focalActor != NULL) { + // Updates camera info on the actor it's tracking + + if (camera->focalActor == &GET_PLAYER(camera->play)->actor) { + Actor_GetWorldPosShapeRot(&focalActorPosRot, camera->focalActor); + } else { + Actor_GetWorld(&focalActorPosRot, camera->focalActor); + } + camera->unk_0F0.x = focalActorPosRot.pos.x - camera->focalActorPosRot.pos.x; + camera->unk_0F0.y = focalActorPosRot.pos.y - camera->focalActorPosRot.pos.y; + camera->unk_0F0.z = focalActorPosRot.pos.z - camera->focalActorPosRot.pos.z; + + // bg related to tracked actor + sp98 = 0; + if (Camera_IsMountedOnHorse(camera)) { + if (((Player*)focalActor)->rideActor->floorPoly != NULL) { + sp90 = ((Player*)focalActor)->rideActor->floorPoly; + camera->bgId = ((Player*)focalActor)->rideActor->floorBgId; + camera->focalActorFloorHeight = ((Player*)focalActor)->rideActor->floorHeight; + sp98 = 3; + } + } else if (func_800CB7CC(camera)) { + if (camera->focalActor->floorPoly != NULL) { + sp90 = camera->focalActor->floorPoly; + camera->bgId = camera->focalActor->floorBgId; + camera->focalActorFloorHeight = camera->focalActor->floorHeight; + sp98 = 1; + } + } else { + focalActorPos = focalActorPosRot.pos; + focalActorPos.y += Camera_GetFocalActorHeight(camera); + focalActorFloorHeight = BgCheck_EntityRaycastFloor5_3(camera->play, &camera->play->colCtx, &sp90, &bgId, + camera->focalActor, &focalActorPos); + if (focalActorFloorHeight != BGCHECK_Y_MIN) { + camera->bgId = bgId; + camera->focalActorFloorHeight = focalActorFloorHeight; + sp98 = 2; + } + } + + if ((sp98 != 0) && (Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight) < 11.0f)) { + meshActor = DynaPoly_GetActor(&camera->play->colCtx, camera->bgId); + if (meshActor != NULL) { + camera->floorNorm.x = COLPOLY_GET_NORMAL(sp90->normal.x); + camera->floorNorm.y = COLPOLY_GET_NORMAL(sp90->normal.y); + camera->floorNorm.z = COLPOLY_GET_NORMAL(sp90->normal.z); + camera->unk_0F0.x -= meshActor->actor.world.pos.x - camera->meshActorPos.x; + camera->unk_0F0.y -= meshActor->actor.world.pos.y - camera->meshActorPos.y; + camera->unk_0F0.z -= meshActor->actor.world.pos.z - camera->meshActorPos.z; + camera->meshActorPos = meshActor->actor.world.pos; + } + } + + // Set camera speed + runSpeedLimit = Camera_GetRunSpeedLimit(camera) * 1.5f; + speed = Camera_Vec3fMagnitude(&camera->unk_0F0); + camera->xzSpeed = OLib_ClampMaxDist(speed, runSpeedLimit); + camera->speedRatio = OLib_ClampMaxDist(speed / runSpeedLimit, 1.8f); + camera->focalActorPosRot = focalActorPosRot; + + if (camera->camId == CAM_ID_MAIN) { + Camera_UpdateWater(camera); + Camera_UpdateHotRoom(camera); + Camera_EarthquakeDay3(camera); + Camera_SetSwordDistortion(camera); + } + + /** + * This section is about updating the camera setting based on the camera scene data + * + */ + + // If doorTimer1 is active, set CAM_STATE_10 which suppresses bg camera scene data from being read + if (camera->doorTimer1 != 0) { + Camera_SetStateFlag(camera, CAM_STATE_10); + } else if (!(camera->stateFlags & CAM_STATE_2)) { + camera->nextCamSceneDataId = -1; + } + + changeCamSceneDataType = 0; // default to no change in the cam scene data + bgId = camera->bgId; + + // Sets the next cam scene data Index based on the bg surface + if ((camera->stateFlags & CAM_STATE_0) && (camera->stateFlags & CAM_STATE_2) && + !(camera->stateFlags & CAM_STATE_10) && + (!(camera->stateFlags & CAM_STATE_9) || Camera_IsUnderwaterAsZora(camera)) && + !(camera->stateFlags & CAM_STATE_15) && !Camera_IsMountedOnHorse(camera) && + !Camera_RequestGiantsMaskSetting(camera) && !Camera_IsDekuHovering(camera) && (sp98 != 0)) { + + bgCamIndex = Camera_GetBgCamIndex(camera, &bgId, sp90); + if ((bgCamIndex != -1) && (camera->bgId == BGCHECK_SCENE)) { + if (Camera_IsUsingZoraFins(camera) == 0) { + camera->nextCamSceneDataId = bgCamIndex | CAM_DATA_IS_BG; + } + } + + focalActorPos = focalActorPosRot.pos; + focalActorPos.y += Camera_GetFocalActorHeight(camera); + focalActorFloorHeight = + BgCheck_CameraRaycastFloor2(&camera->play->colCtx, &sp8C, &bgId, &focalActorPos); + + if ((focalActorFloorHeight != BGCHECK_Y_MIN) && (sp8C != sp90) && (bgId == BGCHECK_SCENE) && + ((camera->focalActorFloorHeight - 2.0f) < focalActorFloorHeight)) { + bgCamIndex = Camera_GetBgCamIndex(camera, &bgId, sp8C); + if ((bgCamIndex != -1) && (bgId == BGCHECK_SCENE)) { + camera->nextCamSceneDataId = bgCamIndex | CAM_DATA_IS_BG; + changeCamSceneDataType = 1; // change cam scene data based on the bg cam data + } + } + } + + if (camera->doorTimer1 != 0) { + camera->doorTimer1--; + if (camera->doorTimer1 == 0) { + Camera_UnsetStateFlag(camera, CAM_STATE_10); + changeCamSceneDataType = 5; // change cam scene data based on the cutscene cam data + } + } + + if (((camera->camId == CAM_ID_MAIN) || (camera->stateFlags & CAM_STATE_6)) && + ((camera->bgId == BGCHECK_SCENE) || ((bgId == BGCHECK_SCENE) && (changeCamSceneDataType != 0))) && + (camera->nextCamSceneDataId != -1) && (camera->doorTimer1 == 0) && + ((Camera_fabsf(camera->focalActorPosRot.pos.y - camera->focalActorFloorHeight) < 11.0f) || + (changeCamSceneDataType != 0)) && + (!(camera->stateFlags & CAM_STATE_9) || Camera_IsUnderwaterAsZora(camera))) { + + Camera_ChangeActorCsCamIndex(camera, camera->nextCamSceneDataId); + camera->nextCamSceneDataId = -1; + if (camera->doorTimer2 != 0) { + camera->doorTimer1 = camera->doorTimer2; + camera->doorTimer2 = 0; + } + } + } + + // Camera of status WAIT only updates to this point + if (camera->status == CAM_STATUS_WAIT) { + *inputDir = camera->inputDir; + return inputDir; + } + + camera->behaviorFlags = 0; + Camera_UnsetStateFlag(camera, CAM_STATE_10 | CAM_STATE_DISABLE_MODE_CHANGE); + Camera_SetStateFlag(camera, CAM_STATE_4); + } + + // Call the camera update function + sCameraUpdateHandlers[sCameraSettings[camera->setting].cameraModes[camera->mode].funcId](camera); + + // Update the interface + if (sCameraInitSceneTimer != 0) { + sCameraInitSceneTimer--; + } + if (camera->status == CAM_STATUS_ACTIVE) { + if (((sCameraInitSceneTimer != 0) || func_800CB854(camera)) && (camera->camId == CAM_ID_MAIN)) { + // Surpresses the interface for the first few frames of a scene + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_LARGE, CAM_HUD_VISIBILITY_NONE_ALT, 0); + Camera_UpdateInterface(sCameraInterfaceFlags); + } else if ((camera->play->transitionMode != TRANS_MODE_OFF) && (camera->camId != CAM_ID_MAIN)) { + sCameraInterfaceFlags = CAM_INTERFACE_FLAGS(CAM_LETTERBOX_IGNORE, CAM_HUD_VISIBILITY_IGNORE, 0); + Camera_UpdateInterface(sCameraInterfaceFlags); + } else { + Camera_UpdateInterface(sCameraInterfaceFlags); + } + } + + // Camera of status UNK3 only updates to this point + if (camera->status == CAM_STATUS_UNK3) { + *inputDir = camera->inputDir; + return inputDir; + } + + /** + * This section is about updating view structs from the active camera, + * which view uses to calculate the viewing/projection matrices + */ + numQuakesApplied = Quake_Update(camera, &camShake); + + bgId = numQuakesApplied; // required to match + + if (numQuakesApplied != 0) { + viewAt.x = camera->at.x + camShake.atOffset.x; + viewAt.y = camera->at.y + camShake.atOffset.y; + viewAt.z = camera->at.z + camShake.atOffset.z; + viewEye.x = camera->eye.x + camShake.eyeOffset.x; + viewEye.y = camera->eye.y + camShake.eyeOffset.y; + viewEye.z = camera->eye.z + camShake.eyeOffset.z; + OLib_Vec3fDiffToVecGeo(&sp3C, &viewEye, &viewAt); + Camera_CalcUpVec(&viewUp, sp3C.pitch, sp3C.yaw, camera->roll + camShake.upRollOffset); + viewFov = camera->fov + CAM_BINANG_TO_DEG(camShake.fovOffset); + } else if (sIsFalse) { + //! condition is impossible to achieve + viewAt = camera->at; + viewEye = camera->eye; + OLib_Vec3fDiffToVecGeo(&sp3C, &viewEye, &viewAt); + viewUp = camera->up; + viewFov = camera->fov; + } else { + viewAt = camera->at; + viewEye = camera->eye; + OLib_Vec3fDiffToVecGeo(&sp3C, &viewEye, &viewAt); + Camera_CalcUpVec(&viewUp, sp3C.pitch, sp3C.yaw, camera->roll); + viewFov = camera->fov; + } + + // set view up + if (camera->viewFlags & CAM_VIEW_UP) { + camera->viewFlags &= ~CAM_VIEW_UP; + viewUp = camera->up; + } else { + camera->up = viewUp; + } + + camera->quakeOffset = camShake.eyeOffset; + View_SetScale(&camera->play->view, (OREG(67) * 0.01f) + 1.0f); + camera->play->view.fovy = viewFov; + View_LookAt(&camera->play->view, &viewEye, &viewAt, &viewUp); + camera->camDir.x = sp3C.pitch; + camera->camDir.y = sp3C.yaw; + camera->camDir.z = 0; + + if (!sUpdateCameraDirection) { + camera->inputDir.x = sp3C.pitch; + camera->inputDir.y = sp3C.yaw; + camera->inputDir.z = 0; + } + + *inputDir = camera->inputDir; + + return inputDir; +} + +s32 func_800DF498(Camera* camera) { + Camera_SetStateFlag(camera, CAM_STATE_3 | CAM_STATE_2); // CAM_STATE_3 is set only immediately to be unset + Camera_UnsetStateFlag(camera, CAM_STATE_12 | CAM_STATE_3); + return true; +} + +#define CAM_CHANGE_MODE_0 (1 << 0) +#define CAM_CHANGE_MODE_1 (1 << 1) +#define CAM_CHANGE_MODE_BATTLE (1 << 2) +#define CAM_CHANGE_MODE_FOLLOW_TARGET (1 << 3) +#define CAM_CHANGE_MODE_4 (1 << 4) +#define CAM_CHANGE_MODE_FIRST_PERSON (1 << 5) + +s32 Camera_ChangeModeFlags(Camera* camera, s16 mode, u8 forceChange) { + static s32 sModeChangeFlags = 0; + + if ((camera->setting == CAM_SET_TELESCOPE) && ((mode == CAM_MODE_FIRSTPERSON) || (mode == CAM_MODE_DEKUHIDE))) { + forceChange = true; + } + + // Mode change rejected by flag + if ((camera->stateFlags & CAM_STATE_DISABLE_MODE_CHANGE) && !forceChange) { + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_VALID; + return -1; + } + + // Mode change rejected by validModes + if (!(sCameraSettings[camera->setting].validModes & (1 << mode))) { + if (camera->mode != CAM_MODE_NORMAL) { + camera->mode = CAM_MODE_NORMAL; + Camera_ResetActionFuncState(camera, camera->mode); + func_800DF498(camera); + return mode | 0xC0000000; + } else { + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_VALID; + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_1; + return 0; + } + } + + // Mode change rejected due to mode already being set. (otherwise, reset mode) + if ((mode == camera->mode) && !forceChange) { + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_VALID; + return -1; + } + + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_VALID; + camera->behaviorFlags |= CAM_BEHAVIOR_MODE_1; + + Camera_ResetActionFuncState(camera, mode); + + sModeChangeFlags = 0; + + // Process Requested Camera Mode + switch (mode) { + case CAM_MODE_FIRSTPERSON: + sModeChangeFlags = CAM_CHANGE_MODE_FIRST_PERSON; + break; + + case CAM_MODE_BATTLE: + sModeChangeFlags = CAM_CHANGE_MODE_BATTLE; + break; + + case CAM_MODE_FOLLOWTARGET: + if (camera->target != NULL && camera->target->id != ACTOR_EN_BOOM) { + sModeChangeFlags = CAM_CHANGE_MODE_FOLLOW_TARGET; + } + break; + + case CAM_MODE_BOWARROWZ: + case CAM_MODE_TARGET: + case CAM_MODE_TALK: + case CAM_MODE_HANGZ: + case CAM_MODE_PUSHPULL: + sModeChangeFlags = CAM_CHANGE_MODE_1; + break; + + case CAM_MODE_NORMAL: + case CAM_MODE_HANG: + sModeChangeFlags = CAM_CHANGE_MODE_4; + break; + } + + // Process Current Camera Mode + switch (camera->mode) { + case CAM_MODE_FIRSTPERSON: + if (sModeChangeFlags & CAM_CHANGE_MODE_FIRST_PERSON) { + camera->animState = 10; + } + break; + + case CAM_MODE_JUMP: + case CAM_MODE_HANG: + if (sModeChangeFlags & CAM_CHANGE_MODE_4) { + camera->animState = 20; + } + sModeChangeFlags |= CAM_CHANGE_MODE_0; + break; + + case CAM_MODE_CHARGE: + if (sModeChangeFlags & CAM_CHANGE_MODE_4) { + camera->animState = 20; + } + sModeChangeFlags |= CAM_CHANGE_MODE_0; + break; + + case CAM_MODE_FOLLOWTARGET: + if (sModeChangeFlags & CAM_CHANGE_MODE_FOLLOW_TARGET) { + camera->animState = 10; + } + sModeChangeFlags |= CAM_CHANGE_MODE_0; + break; + + case CAM_MODE_BATTLE: + if (sModeChangeFlags & CAM_CHANGE_MODE_BATTLE) { + camera->animState = 10; + } + sModeChangeFlags |= 1; + break; + + case CAM_MODE_BOWARROWZ: + case CAM_MODE_HANGZ: + case CAM_MODE_PUSHPULL: + sModeChangeFlags |= CAM_CHANGE_MODE_0; + break; + + case CAM_MODE_NORMAL: + if (sModeChangeFlags & CAM_CHANGE_MODE_4) { + camera->animState = 20; + } + break; + + default: + break; + } + + sModeChangeFlags &= ~CAM_CHANGE_MODE_4; + + // Z-Pressing Sfx + if (camera->status == CAM_STATUS_ACTIVE) { + switch (sModeChangeFlags) { + case CAM_CHANGE_MODE_0: + play_sound(0); + break; + + case CAM_CHANGE_MODE_1: + if (camera->play->roomCtx.curRoom.behaviorType1 == ROOM_BEHAVIOR_TYPE1_1) { + play_sound(NA_SE_SY_ATTENTION_URGENCY); + } else { + + play_sound(NA_SE_SY_ATTENTION_ON); + } + break; + + case CAM_CHANGE_MODE_BATTLE: + play_sound(NA_SE_SY_ATTENTION_URGENCY); + break; + + case CAM_CHANGE_MODE_FOLLOW_TARGET: + play_sound(NA_SE_SY_ATTENTION_ON); + break; + + default: + break; + } + } + + func_800DF498(camera); + camera->mode = mode; + + return mode | 0x80000000; +} + +s32 Camera_ChangeMode(Camera* camera, s16 mode) { + return Camera_ChangeModeFlags(camera, mode, false); +} + +s32 Camera_CheckValidMode(Camera* camera, s16 mode) { + if (camera->stateFlags & CAM_STATE_DISABLE_MODE_CHANGE) { + return 0; + } else if (!(sCameraSettings[camera->setting].validModes & (1 << mode))) { + return 0; + } else if (mode == camera->mode) { + return -1; + } else { + return mode | 0x80000000; + } +} + +s16 Camera_ChangeSettingFlags(Camera* camera, s16 setting, s16 flags) { + // Reject settings change based on priority + if ((camera->behaviorFlags & CAM_BEHAVIOR_SETTING_USE_PRIORITY) && + ((sCameraSettings[camera->setting].flags & 0xF) >= (sCameraSettings[setting].flags & 0xF))) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_2; + if (!(flags & CAM_CHANGE_SETTING_1)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_USE_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_CHANGE_SETTING_0)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_2; + if (!(flags & CAM_CHANGE_SETTING_1)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_USE_PRIORITY; + } + return -1; + } + + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_2; + + if (!(flags & CAM_CHANGE_SETTING_1)) { + camera->behaviorFlags |= CAM_BEHAVIOR_SETTING_USE_PRIORITY; + } + + func_800DF498(camera); + + if (!(sCameraSettings[camera->setting].flags & 0x40000000)) { + camera->prevSetting = camera->setting; + } + + if (flags & CAM_CHANGE_SETTING_3) { + camera->bgCamIndex = camera->prevBgCamDataId; + camera->prevBgCamDataId = -1; + } else if (!(flags & CAM_CHANGE_SETTING_2)) { + if (!(sCameraSettings[camera->setting].flags & 0x40000000)) { + camera->prevBgCamDataId = camera->bgCamIndex; + } + camera->bgCamIndex = -1; + } + + camera->setting = setting; + + if (Camera_ChangeModeFlags(camera, camera->mode, true) >= 0) { + Camera_ResetActionFuncState(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_BGCAM_2; + return -1; + } + + if (bgCamIndex < 0) { + setting = sGlobalCamDataSettingsPtr[bgCamIndex]; + } else if (!(camera->behaviorFlags & CAM_BEHAVIOR_BGCAM_2)) { + setting = Camera_GetBgCamOrActorCsCamSetting(camera, bgCamIndex); + } else { + return -1; + } + + camera->behaviorFlags |= CAM_BEHAVIOR_BGCAM_2; + + // Sets camera setting based on bg/scene data + if ((Camera_ChangeSettingFlags(camera, setting, CAM_CHANGE_SETTING_2 | CAM_CHANGE_SETTING_0) >= 0) || + (sCameraSettings[camera->setting].flags & 0x80000000)) { + camera->bgCamIndex = bgCamIndex; + camera->behaviorFlags |= CAM_BEHAVIOR_BGCAM_1; + Camera_ResetActionFuncState(camera, camera->mode); + } + + return bgCamIndex | 0x80000000; +} + +Vec3s* Camera_GetInputDir(Vec3s* dst, Camera* camera) { + *dst = camera->inputDir; + return dst; +} + +s16 Camera_GetInputDirPitch(Camera* camera) { + Vec3s dir; + + Camera_GetInputDir(&dir, camera); + return dir.x; +} + +s16 Camera_GetInputDirYaw(Camera* camera) { + Vec3s dir; + + Camera_GetInputDir(&dir, camera); + return dir.y; +} + +Vec3s* Camera_GetCamDir(Vec3s* dst, Camera* camera) { + *dst = camera->camDir; + return dst; +} + +s16 Camera_GetCamDirPitch(Camera* camera) { + Vec3s camDir; + + Camera_GetCamDir(&camDir, camera); + return camDir.x; +} + +s16 Camera_GetCamDirYaw(Camera* camera) { + Vec3s camDir; + + Camera_GetCamDir(&camDir, camera); + return camDir.y; +} + +s32 Camera_AddQuake(Camera* camera, s32 arg1, s16 y, s32 countdown) { + s16 quakeIndex = Quake_Request(camera, QUAKE_TYPE_3); + + if (quakeIndex == 0) { + return false; + } + + Quake_SetSpeed(quakeIndex, 25000); + Quake_SetPerturbations(quakeIndex, y, 0, 0, 0); + Quake_SetDuration(quakeIndex, countdown); + return true; +} + +s32 Camera_SetViewParam(Camera* camera, s32 viewFlag, void* param) { + s32 pad[3]; + + if (param != NULL) { + switch (viewFlag) { + case CAM_VIEW_AT: + camera->viewFlags &= ~(CAM_VIEW_TARGET_POS | CAM_VIEW_TARGET | CAM_VIEW_AT); + camera->at = *(Vec3f*)param; + break; + + case CAM_VIEW_TARGET_POS: + camera->viewFlags &= ~(CAM_VIEW_TARGET_POS | CAM_VIEW_TARGET | CAM_VIEW_AT); + camera->targetPosRot.pos = *(Vec3f*)param; + break; + + case CAM_VIEW_TARGET: + camera->target = (Actor*)param; + camera->viewFlags &= ~(CAM_VIEW_TARGET_POS | CAM_VIEW_TARGET | CAM_VIEW_AT); + break; + + case CAM_VIEW_EYE: + camera->eye = camera->eyeNext = *(Vec3f*)param; + break; + + case CAM_VIEW_UP: + camera->up = *(Vec3f*)param; + break; + + case CAM_VIEW_ROLL: + camera->roll = CAM_DEG_TO_BINANG(*(f32*)param); + break; + + case CAM_VIEW_FOV: + camera->fov = *(f32*)param; + break; + + default: + return false; + } + camera->viewFlags |= viewFlag; + } else { + return false; + } + return true; +} + +s32 Camera_UnsetViewFlag(Camera* camera, s16 viewFlag) { + camera->viewFlags &= ~viewFlag; + return true; +} + +s32 Camera_OverwriteStateFlags(Camera* camera, s16 stateFlags) { + camera->stateFlags = stateFlags; + return true; +} + +s32 Camera_ResetActionFuncStateUnused(Camera* camera) { + camera->animState = 0; + return true; +} + +/** + * Unused Remnant of OoT. `CutsceneCameraPoint` struct no longer exists. + */ +s32 Camera_SetCsParams(Camera* camera, void* atPoints, void* eyePoints, Player* player, s16 relativeToPlayer) { + return true; +} + +s16 Camera_SetStateFlag(Camera* camera, s16 flags) { + camera->stateFlags |= flags; + return camera->stateFlags; +} + +s16 Camera_UnsetStateFlag(Camera* camera, s16 flags) { + camera->stateFlags &= ~flags; + return camera->stateFlags; +} + +s32 Camera_ChangeDoorCam(Camera* camera, Actor* doorActor, s16 bgCamIndex, f32 arg3, s16 timer1, s16 timer2, + s16 timer3) { + DoorParams* doorParams = &camera->paramData.doorParams; + + if (camera->setting == CAM_SET_DOORC) { + return 0; + } + + doorParams->doorActor = doorActor; + doorParams->timer1 = timer1; + doorParams->timer2 = timer2; + doorParams->timer3 = timer3; + doorParams->bgCamIndex = bgCamIndex; + + if (bgCamIndex == -99) { + Camera_ResetActionFuncState(camera, camera->mode); + return -99; + } + + if (bgCamIndex == -1) { + Camera_ChangeSettingFlags(camera, CAM_SET_DOORC, 0); + } else if (bgCamIndex == -2) { + Camera_ChangeSettingFlags(camera, CAM_SET_SPIRAL_DOOR, 0); + } else { + camera->nextCamSceneDataId = bgCamIndex; + camera->doorTimer1 = timer1; + camera->doorTimer2 = timer2 + timer3; + } + + Camera_ResetActionFuncState(camera, camera->mode); + return -1; +} + +s32 Camera_Copy(Camera* dstCam, Camera* srcCam) { + s32 pad; + + dstCam->focalActorAtOffset.z = 0.0f; + dstCam->focalActorAtOffset.y = 0.0f; + dstCam->focalActorAtOffset.x = 0.0f; + dstCam->atLerpStepScale = 0.1f; + dstCam->at = srcCam->at; + + dstCam->eye = dstCam->eyeNext = srcCam->eye; + + dstCam->dist = OLib_Vec3fDist(&dstCam->at, &dstCam->eye); + dstCam->fov = srcCam->fov; + dstCam->roll = srcCam->roll; + Camera_SetUpdateRatesSlow(dstCam); + + if (dstCam->focalActor != NULL) { + if (dstCam->focalActor == &GET_PLAYER(dstCam->play)->actor) { + Actor_GetWorldPosShapeRot(&dstCam->focalActorPosRot, dstCam->focalActor); + } else { + Actor_GetWorld(&dstCam->focalActorPosRot, dstCam->focalActor); + } + Camera_SetFocalActorAtOffset(dstCam, &dstCam->focalActorPosRot.pos); + } + return true; +} + +/** + * Unused Remnant of OoT/Debug + */ +s32 Camera_IsDbgCamEnabled(void) { + return false; +} + +Vec3f* Camera_GetQuakeOffset(Vec3f* quakeOffset, Camera* camera) { + *quakeOffset = camera->quakeOffset; + + return quakeOffset; +} + +void Camera_SetCameraData(Camera* camera, s16 setDataFlags, void* data0, void* data1, s16 data2, s16 data3) { + if (setDataFlags & 1) { + camera->data0 = data0; + } + + if (setDataFlags & 2) { + camera->data1 = data1; + } + + if (setDataFlags & 4) { + camera->data2 = data2; + } + + if (setDataFlags & 8) { + camera->data3 = data3; + } +} + +s32 Camera_GetNegOne(void) { + return sCameraNegOne; +} + +s16 func_800E0238(Camera* camera) { + Camera_SetStateFlag(camera, CAM_STATE_3); + if ((camera->camId == CAM_ID_MAIN) && (camera->play->activeCamId != CAM_ID_MAIN)) { + Camera_SetStateFlag(GET_ACTIVE_CAM(camera->play), CAM_STATE_3); + return camera->play->activeCamId; + } else { + return camera->camId; + } +} + +void Camera_SetFocalActor(Camera* camera, Actor* actor) { + camera->focalActor = actor; + if (actor == &GET_PLAYER(camera->play)->actor) { + Actor_GetWorldPosShapeRot(&camera->focalActorPosRot, actor); + } else { + Actor_GetWorld(&camera->focalActorPosRot, camera->focalActor); + } + + camera->animState = 0; +} + +void Camera_SetTargetActor(Camera* camera, Actor* actor) { + camera->target = actor; + camera->animState = 20; +} + +f32 Camera_GetWaterYPos(Camera* camera) { + if (camera->stateFlags & CAM_STATE_UNDERWATER) { + return camera->waterYPos; + } else { + return BGCHECK_Y_MIN; + } +} + +void func_800E0348(Camera* camera) { + if (!RELOAD_PARAMS(camera)) { + camera->animState = 999; + Camera_SetStateFlag(camera, CAM_STATE_10 | CAM_STATE_4 | CAM_STATE_2 | 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 3df77c0c4..6e1501fd8 100644 --- a/src/code/z_camera_data.inc.c +++ b/src/code/z_camera_data.inc.c @@ -3795,12 +3795,12 @@ s32 sCameraHudVisibility = 2; s32 sCameraLetterboxSize = 32; s32 sCameraNegOne = -1; -// VecSph yaw data +// VecGeo yaw data s16 D_801B9E18[] = { 0x0AAA, 0xF556, 0x1555, 0xEAAB, 0x2AAA, 0xD556, 0x3FFF, 0xC001, 0x5555, 0xAAAB, 0x6AAA, 0x9556, 0x7FFF, 0x0000, }; -// VecSph pitch data +// VecGeo pitch data s16 D_801B9E34[] = { 0x0000, 0x02C6, 0x058C, 0x0000, 0x0000, 0xFD3A, 0x0000, 0x0852, 0x0000, 0x0000, 0x0B18, 0x02C6, 0xFA74, 0x0000, }; diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c index 3f6b9a481..50045a278 100644 --- a/src/code/z_collision_check.c +++ b/src/code/z_collision_check.c @@ -23,16 +23,24 @@ Vec3f D_801EE0D8; TriNorm D_801EE0E8[2]; TriNorm D_801EE150; TriNorm D_801EE188; + +#ifndef NON_MATCHING Vec3f D_801EE1C0; Vec3f D_801EE1D0; Vec3f D_801EE1E0; Vec3f D_801EE1F0; EffectSparkInit D_801EE200; +#endif + TriNorm D_801EE6C8; TriNorm D_801EE700; + +#ifndef NON_MATCHING EffectSparkInit D_801EE738; EffectSparkInit D_801EEC00; EffectSparkInit D_801EF0C8; +#endif + TriNorm D_801EF590; TriNorm D_801EF5C8; TriNorm D_801EF600; diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 79270adce..da965969f 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -202,10 +202,10 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { case CS_MISC_EARTHQUAKE_MEDIUM: func_8019F128(NA_SE_EV_EARTHQUAKE_LAST - SFX_FLAG); if (isFirstFrame) { - sCutsceneQuakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); + sCutsceneQuakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); Quake_SetSpeed(sCutsceneQuakeIndex, 22000); - Quake_SetQuakeValues(sCutsceneQuakeIndex, 6, 4, 0, 0); - Quake_SetCountdown(sCutsceneQuakeIndex, 800); + Quake_SetPerturbations(sCutsceneQuakeIndex, 6, 4, 0, 0); + Quake_SetDuration(sCutsceneQuakeIndex, 800); } break; @@ -310,10 +310,10 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { case CS_MISC_EARTHQUAKE_STRONG: func_8019F128(NA_SE_EV_EARTHQUAKE_LAST2 - SFX_FLAG); if (isFirstFrame) { - sCutsceneQuakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); + sCutsceneQuakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); Quake_SetSpeed(sCutsceneQuakeIndex, 30000); - Quake_SetQuakeValues(sCutsceneQuakeIndex, 20, 10, 0, 0); - Quake_SetCountdown(sCutsceneQuakeIndex, 800); + Quake_SetPerturbations(sCutsceneQuakeIndex, 20, 10, 0, 0); + Quake_SetDuration(sCutsceneQuakeIndex, 800); } break; @@ -372,10 +372,10 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { case CS_MISC_EARTHQUAKE_WEAK: func_8019F128(NA_SE_EV_EARTHQUAKE_LAST - SFX_FLAG); if (isFirstFrame) { - sCutsceneQuakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); + sCutsceneQuakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); Quake_SetSpeed(sCutsceneQuakeIndex, 22000); - Quake_SetQuakeValues(sCutsceneQuakeIndex, 2, 1, 0, 0); - Quake_SetCountdown(sCutsceneQuakeIndex, 800); + Quake_SetPerturbations(sCutsceneQuakeIndex, 2, 1, 0, 0); + Quake_SetDuration(sCutsceneQuakeIndex, 800); } break; diff --git a/src/code/z_eventmgr.c b/src/code/z_eventmgr.c index 2575899ca..aec6fdbb0 100644 --- a/src/code/z_eventmgr.c +++ b/src/code/z_eventmgr.c @@ -402,13 +402,13 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { if (CutsceneManager_FindEntranceCsId() != csId) { func_800E0348(retCam); } else { - Camera_ClearFlags(retCam, CAM_STATE_2); + Camera_UnsetStateFlag(retCam, CAM_STATE_2); } } memcpy(subCam, retCam, sizeof(Camera)); subCam->camId = sCutsceneMgr.subCamId; - Camera_ClearFlags(subCam, CAM_STATE_6 | CAM_STATE_0); + Camera_UnsetStateFlag(subCam, CAM_STATE_6 | CAM_STATE_0); Play_ChangeCameraStatus(sCutsceneMgr.play, sCutsceneMgr.retCamId, CAM_STATUS_WAIT); Play_ChangeCameraStatus(sCutsceneMgr.play, sCutsceneMgr.subCamId, CAM_STATUS_ACTIVE); @@ -422,7 +422,7 @@ s16 CutsceneManager_Start(s16 csId, Actor* actor) { sCutsceneMgr.length = csEntry->length; } else { if (csEntry->csCamId != CS_CAM_ID_NONE) { - Camera_ChangeDataIdx(subCam, csEntry->csCamId); + Camera_ChangeActorCsCamIndex(subCam, csEntry->csCamId); } else { Camera_ChangeSetting(subCam, CAM_SET_FREE0); } diff --git a/src/code/z_fbdemo_dlftbls.c b/src/code/z_fbdemo_dlftbls.c index 9d3685a45..48d424813 100644 --- a/src/code/z_fbdemo_dlftbls.c +++ b/src/code/z_fbdemo_dlftbls.c @@ -1,30 +1,38 @@ #include "global.h" -#include "initvars.h" -#include "overlays/fbdemos/ovl_fbdemo_triforce/z_fbdemo_triforce.h" -#include "overlays/fbdemos/ovl_fbdemo_wipe1/z_fbdemo_wipe1.h" -#include "overlays/fbdemos/ovl_fbdemo_wipe3/z_fbdemo_wipe3.h" -#include "overlays/fbdemos/ovl_fbdemo_wipe4/z_fbdemo_wipe4.h" -#include "overlays/fbdemos/ovl_fbdemo_wipe5/z_fbdemo_wipe5.h" -#define TRANSITION_OVERLAY(name, filename) \ - { \ - { 0, 0 }, SEGMENT_START(ovl_##filename), SEGMENT_END(ovl_##filename), SEGMENT_ROM_START(ovl_##filename), \ - SEGMENT_ROM_END(ovl_##filename), &name##_InitVars, sizeof(name) \ - } +// InitVars and Linker symbol declarations (used in the table below) +#define DEFINE_TRANSITION(_enumValue, structName, _instanceName, name) \ + extern TransitionInit structName##_InitVars; \ + DECLARE_OVERLAY_SEGMENT(name) -#define TRANSITION_OVERLAY_INTERNAL(name) \ - { { 0, 0 }, NULL, NULL, 0, 0, &name##_InitVars, sizeof(name) } +#define DEFINE_TRANSITION_INTERNAL(_enumValue, structName, _instanceName) extern TransitionInit structName##_InitVars; -#define TRANSITION_OVERLAY_UNSET \ - { 0 } +#include "tables/transition_table.h" + +#undef DEFINE_TRANSITION +#undef DEFINE_TRANSITION_INTERNAL + +#define DEFINE_TRANSITION(_enumValue, structName, _instanceName, name) \ + { \ + { 0, 0 }, \ + SEGMENT_START(ovl_##name), \ + SEGMENT_END(ovl_##name), \ + SEGMENT_ROM_START(ovl_##name), \ + SEGMENT_ROM_END(ovl_##name), \ + &structName##_InitVars, \ + sizeof(structName), \ + }, + +#define DEFINE_TRANSITION_INTERNAL(_enumValue, structName, _instanceName) \ + { { 0, 0 }, NULL, NULL, 0, 0, &structName##_InitVars, sizeof(structName) }, TransitionOverlay gTransitionOverlayTable[] = { - TRANSITION_OVERLAY_INTERNAL(TransitionFade), TRANSITION_OVERLAY(TransitionTriforce, fbdemo_triforce), - TRANSITION_OVERLAY(TransitionWipe1, fbdemo_wipe1), TRANSITION_OVERLAY(TransitionWipe3, fbdemo_wipe3), - TRANSITION_OVERLAY(TransitionWipe4, fbdemo_wipe4), TRANSITION_OVERLAY_INTERNAL(TransitionCircle), - TRANSITION_OVERLAY(TransitionWipe5, fbdemo_wipe5), +#include "tables/transition_table.h" }; +#undef DEFINE_TRANSITION +#undef DEFINE_TRANSITION_INTERNAL + void Transition_Init(TransitionContext* transitionCtx) { TransitionOverlay* overlayEntry; ptrdiff_t relocOffset; diff --git a/src/code/z_olib.c b/src/code/z_olib.c index ad0c2b35c..754857014 100644 --- a/src/code/z_olib.c +++ b/src/code/z_olib.c @@ -100,16 +100,16 @@ Vec3f* OLib_VecSphToVec3f(Vec3f* dest, VecSph* sph) { } /** - * Takes the geographic point `sph` and converts it into a x,y,z position + * Takes the geographic point `geo` and converts it into a x,y,z position */ -Vec3f* OLib_VecSphGeoToVec3f(Vec3f* dest, VecSph* sph) { - VecSph geo; +Vec3f* OLib_VecGeoToVec3f(Vec3f* dest, VecGeo* geo) { + VecSph sph; - geo.r = sph->r; - geo.pitch = 0x4000 - sph->pitch; - geo.yaw = sph->yaw; + sph.r = geo->r; + sph.pitch = 0x4000 - geo->pitch; + sph.yaw = geo->yaw; - return OLib_VecSphToVec3f(dest, &geo); + return OLib_VecSphToVec3f(dest, &sph); } /** @@ -117,16 +117,16 @@ Vec3f* OLib_VecSphGeoToVec3f(Vec3f* dest, VecSph* sph) { */ VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec) { VecSph sph; - f32 distSquared = SQ(vec->x) + SQ(vec->z); - f32 dist = sqrtf(distSquared); + f32 distXZSq = SQ(vec->x) + SQ(vec->z); + f32 distXZ = sqrtf(distXZSq); - if ((dist == 0.0f) && (vec->y == 0.0f)) { + if ((distXZ == 0.0f) && (vec->y == 0.0f)) { sph.pitch = 0; } else { - sph.pitch = CAM_DEG_TO_BINANG(RAD_TO_DEG(func_80086B30(dist, vec->y))); + sph.pitch = CAM_DEG_TO_BINANG(RAD_TO_DEG(func_80086B30(distXZ, vec->y))); } - sph.r = sqrtf(SQ(vec->y) + distSquared); + sph.r = sqrtf(SQ(vec->y) + distXZSq); if ((vec->x == 0.0f) && (vec->z == 0.0f)) { sph.yaw = 0; } else { @@ -141,7 +141,7 @@ VecSph* OLib_Vec3fToVecSph(VecSph* dest, Vec3f* vec) { /** * Takes the point `vec`, and converts it to a geographic coordinate */ -VecSph* OLib_Vec3fToVecSphGeo(VecSph* dest, Vec3f* vec) { +VecGeo* OLib_Vec3fToVecGeo(VecGeo* dest, Vec3f* vec) { VecSph sph; OLib_Vec3fToVecSph(&sph, vec); @@ -156,42 +156,42 @@ VecSph* OLib_Vec3fToVecSphGeo(VecSph* dest, Vec3f* vec) { * Takes the differences of positions `a` and `b`, and converts them to spherical coordinates */ VecSph* OLib_Vec3fDiffToVecSph(VecSph* dest, Vec3f* a, Vec3f* b) { - Vec3f sph; + Vec3f diff; - sph.x = b->x - a->x; - sph.y = b->y - a->y; - sph.z = b->z - a->z; + diff.x = b->x - a->x; + diff.y = b->y - a->y; + diff.z = b->z - a->z; - return OLib_Vec3fToVecSph(dest, &sph); + return OLib_Vec3fToVecSph(dest, &diff); } /** * Takes the difference of positions `a` and `b`, and converts them to geographic coordinates */ -VecSph* OLib_Vec3fDiffToVecSphGeo(VecSph* dest, Vec3f* a, Vec3f* b) { - Vec3f sph; +VecGeo* OLib_Vec3fDiffToVecGeo(VecGeo* dest, Vec3f* a, Vec3f* b) { + Vec3f diff; - sph.x = b->x - a->x; - sph.y = b->y - a->y; - sph.z = b->z - a->z; + diff.x = b->x - a->x; + diff.y = b->y - a->y; + diff.z = b->z - a->z; - return OLib_Vec3fToVecSphGeo(dest, &sph); + return OLib_Vec3fToVecGeo(dest, &diff); } /** - * Takes the sum of positions `a` (x,y,z coordinates) and `sph` (geographic coordinates), result is in x,y,z position + * 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_VecSphAddToVec3f(Vec3f* dest, Vec3f* a, VecSph* sph) { - Vec3f vec; +Vec3f* OLib_AddVecGeoToVec3f(Vec3f* dest, Vec3f* a, VecGeo* geo) { + Vec3f sum; Vec3f b; - OLib_VecSphGeoToVec3f(&b, sph); - vec.x = a->x + b.x; - vec.y = a->y + b.y; - vec.z = a->z + b.z; + OLib_VecGeoToVec3f(&b, geo); + sum.x = a->x + b.x; + sum.y = a->y + b.y; + sum.z = a->z + b.z; - *dest = vec; + *dest = sum; return dest; } @@ -248,46 +248,50 @@ Vec3s* OLib_Vec3fDiffBinAng(Vec3s* dest, Vec3f* a, Vec3f* b) { } /** - * Gets a x,y,z position diff depending on the dbCamera mode + * Gets a x,y,z position diff depending on the mode */ -void OLib_DbCameraVec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { - VecSph sph; +void OLib_Vec3fDiff(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { + VecGeo geo; switch (mode) { - case 1: - OLib_Vec3fDiffToVecSphGeo(&sph, &a->pos, b); - sph.yaw -= a->rot.y; - OLib_VecSphGeoToVec3f(dest, &sph); + case OLIB_DIFF_OFFSET: + OLib_Vec3fDiffToVecGeo(&geo, &a->pos, b); + geo.yaw -= a->rot.y; + OLib_VecGeoToVec3f(dest, &geo); break; - case 2: + + 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: + + default: // OLIB_DIFF_COPY *dest = *b; break; } } /** - * Gets a x,y,z position sum depending on the dbCamera mode + * Gets a x,y,z position sum depending on the mode */ -void OLib_DbCameraVec3fSum(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { - VecSph sph; +void OLib_Vec3fAdd(PosRot* a, Vec3f* b, Vec3f* dest, s16 mode) { + VecGeo geo; switch (mode) { - case 1: - OLib_Vec3fToVecSphGeo(&sph, b); - sph.yaw += a->rot.y; - OLib_VecSphAddToVec3f(dest, &a->pos, &sph); + case OLIB_ADD_OFFSET: + OLib_Vec3fToVecGeo(&geo, b); + geo.yaw += a->rot.y; + OLib_AddVecGeoToVec3f(dest, &a->pos, &geo); break; - case 2: + + 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: + + default: // OLIB_ADD_COPY *dest = *b; break; } diff --git a/src/code/z_play.c b/src/code/z_play.c index 9956b44cc..8a39542dd 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1,4 +1,3 @@ -#include "prevent_bss_reordering.h" #include "global.h" #include "buffers.h" #include "z64debug_display.h" @@ -506,41 +505,41 @@ void Play_UpdateWaterCamera(PlayState* this, Camera* camera) { sIsCameraUnderwater = camera->stateFlags & CAM_STATE_UNDERWATER; if (Play_GetWaterSurface(this, &camera->eye, &lightIndex) != BGCHECK_Y_MIN) { if (!sIsCameraUnderwater) { - Camera_SetFlags(camera, CAM_STATE_UNDERWATER); + Camera_SetStateFlag(camera, CAM_STATE_UNDERWATER); sQuakeIndex = -1; - Distortion_SetType(DISTORTION_TYPE_UNDERWATER_ENTRY); - Distortion_SetCountdown(80); + Distortion_Request(DISTORTION_TYPE_UNDERWATER_ENTRY); + Distortion_SetDuration(80); } func_801A3EC0(0x20); func_800F6834(this, lightIndex); - if ((sQuakeIndex == -1) || (Quake_GetCountdown(sQuakeIndex) == 10)) { - s16 quakeIndex = Quake_Add(camera, QUAKE_TYPE_5); + if ((sQuakeIndex == -1) || (Quake_GetTimeLeft(sQuakeIndex) == 10)) { + s16 quakeIndex = Quake_Request(camera, QUAKE_TYPE_5); sQuakeIndex = quakeIndex; if (quakeIndex != 0) { Quake_SetSpeed(sQuakeIndex, 550); - Quake_SetQuakeValues(sQuakeIndex, 1, 1, 180, 0); - Quake_SetCountdown(sQuakeIndex, 1000); + Quake_SetPerturbations(sQuakeIndex, 1, 1, 180, 0); + Quake_SetDuration(sQuakeIndex, 1000); } } if (player->stateFlags3 & PLAYER_STATE3_8000) { - Distortion_SetType(DISTORTION_TYPE_ZORA_SWIMMING); - Distortion_ClearType(DISTORTION_TYPE_NON_ZORA_SWIMMING); + Distortion_Request(DISTORTION_TYPE_ZORA_SWIMMING); + Distortion_RemoveRequest(DISTORTION_TYPE_NON_ZORA_SWIMMING); } else { - Distortion_SetType(DISTORTION_TYPE_NON_ZORA_SWIMMING); - Distortion_ClearType(DISTORTION_TYPE_ZORA_SWIMMING); + Distortion_Request(DISTORTION_TYPE_NON_ZORA_SWIMMING); + Distortion_RemoveRequest(DISTORTION_TYPE_ZORA_SWIMMING); } } else { if (sIsCameraUnderwater) { - Camera_ClearFlags(camera, CAM_STATE_UNDERWATER); + Camera_UnsetStateFlag(camera, CAM_STATE_UNDERWATER); } - Distortion_ClearType(DISTORTION_TYPE_NON_ZORA_SWIMMING); - Distortion_ClearType(DISTORTION_TYPE_UNDERWATER_ENTRY); - Distortion_ClearType(DISTORTION_TYPE_ZORA_SWIMMING); + Distortion_RemoveRequest(DISTORTION_TYPE_NON_ZORA_SWIMMING); + Distortion_RemoveRequest(DISTORTION_TYPE_UNDERWATER_ENTRY); + Distortion_RemoveRequest(DISTORTION_TYPE_ZORA_SWIMMING); if (sQuakeIndex != 0) { - Quake_Remove(sQuakeIndex); + Quake_RemoveRequest(sQuakeIndex); } func_800F694C(this); func_801A3EC0(0); @@ -1682,11 +1681,11 @@ s32 Play_SetCameraAtEye(PlayState* this, s16 camId, Vec3f* at, Vec3f* eye) { camera->dist = Math3D_Vec3f_DistXYZ(at, eye); if (camera->focalActor != NULL) { - camera->atActorOffset.x = at->x - camera->focalActor->world.pos.x; - camera->atActorOffset.y = at->y - camera->focalActor->world.pos.y; - camera->atActorOffset.z = at->z - camera->focalActor->world.pos.z; + camera->focalActorAtOffset.x = at->x - camera->focalActor->world.pos.x; + camera->focalActorAtOffset.y = at->y - camera->focalActor->world.pos.y; + camera->focalActorAtOffset.z = at->z - camera->focalActor->world.pos.z; } else { - camera->atActorOffset.x = camera->atActorOffset.y = camera->atActorOffset.z = 0.0f; + camera->focalActorAtOffset.x = camera->focalActorAtOffset.y = camera->focalActorAtOffset.z = 0.0f; } camera->atLerpStepScale = 0.01f; @@ -1711,11 +1710,11 @@ s32 Play_SetCameraAtEyeUp(PlayState* this, s16 camId, Vec3f* at, Vec3f* eye, Vec camera->dist = Math3D_Vec3f_DistXYZ(at, eye); if (camera->focalActor != NULL) { - camera->atActorOffset.x = at->x - camera->focalActor->world.pos.x; - camera->atActorOffset.y = at->y - camera->focalActor->world.pos.y; - camera->atActorOffset.z = at->z - camera->focalActor->world.pos.z; + camera->focalActorAtOffset.x = at->x - camera->focalActor->world.pos.x; + camera->focalActorAtOffset.y = at->y - camera->focalActor->world.pos.y; + camera->focalActorAtOffset.z = at->z - camera->focalActor->world.pos.z; } else { - camera->atActorOffset.x = camera->atActorOffset.y = camera->atActorOffset.z = 0.0f; + camera->focalActorAtOffset.x = camera->focalActorAtOffset.y = camera->focalActorAtOffset.z = 0.0f; } camera->atLerpStepScale = 0.01f; @@ -1749,13 +1748,13 @@ void Play_CopyCamera(PlayState* this, s16 destCamId, s16 srcCamId) { Camera_Copy(this->cameraPtrs[destCamId1], this->cameraPtrs[srcCamId2]); } -// Same as Play_ChangeCameraSetting but also calls Camera_InitPlayerSettings +// Same as Play_ChangeCameraSetting but also calls Camera_InitFocalActorSettings s32 func_80169A50(PlayState* this, s16 camId, Player* player, s16 setting) { Camera* camera; s16 camIdx = (camId == CAM_ID_NONE) ? this->activeCamId : camId; camera = this->cameraPtrs[camIdx]; - Camera_InitPlayerSettings(camera, player); + Camera_InitFocalActorSettings(camera, &player->actor); return Camera_ChangeSetting(camera, setting); } @@ -2180,7 +2179,8 @@ void Play_Init(GameState* thisx) { this->cameraPtrs[CAM_ID_MAIN]->uid = CAM_ID_MAIN; this->activeCamId = CAM_ID_MAIN; - func_800DFF18(&this->mainCamera, 0x7F); + Camera_OverwriteStateFlags(&this->mainCamera, CAM_STATE_0 | CAM_STATE_CHECK_WATER | CAM_STATE_2 | CAM_STATE_3 | + CAM_STATE_4 | CAM_STATE_DISABLE_MODE_CHANGE | CAM_STATE_6); Sram_Alloc(&this->state, &this->sramCtx); Regs_InitData(this); Message_Init(this); @@ -2324,11 +2324,11 @@ void Play_Init(GameState* thisx) { player = GET_PLAYER(this); - Camera_InitPlayerSettings(&this->mainCamera, player); + Camera_InitFocalActorSettings(&this->mainCamera, &player->actor); gDbgCamEnabled = false; if ((player->actor.params & 0xFF) != 0xFF) { - Camera_ChangeDataIdx(&this->mainCamera, player->actor.params & 0xFF); + Camera_ChangeActorCsCamIndex(&this->mainCamera, player->actor.params & 0xFF); } CutsceneManager_StoreCamera(&this->mainCamera); @@ -2342,6 +2342,3 @@ void Play_Init(GameState* thisx) { sBombersNotebookOpen = false; BombersNotebook_Init(&sBombersNotebook); } - -//! TODO: fake symbol, remove when BombersNotebook_Update is matching -u16 D_801D0D78[] = { 0, 0, 0, 0 }; diff --git a/src/code/z_quake.c b/src/code/z_quake.c index d8d526ca3..c5115375c 100644 --- a/src/code/z_quake.c +++ b/src/code/z_quake.c @@ -3,35 +3,28 @@ #include "z64view.h" typedef struct { - /* 0x00 */ s16 randIndex; - /* 0x02 */ s16 countdownMax; + /* 0x00 */ s16 index; + /* 0x02 */ s16 duration; /* 0x04 */ Camera* camera; /* 0x08 */ u32 type; - /* 0x0C */ s16 verticalMag; - /* 0x0E */ s16 horizontalMag; - /* 0x10 */ s16 zoom; - /* 0x12 */ s16 rollOffset; - /* 0x14 */ Vec3s shakePlaneOffset; // angle deviations from shaking in the perpendicular plane + /* 0x0C */ s16 y; + /* 0x0E */ s16 x; + /* 0x10 */ s16 fov; + /* 0x12 */ s16 upRollOffset; + /* 0x14 */ Vec3s orientation; // alters the orientation of the xy perturbation. Only x (pitch) and y (yaw) are used /* 0x1A */ s16 speed; - /* 0x1C */ s16 isShakePerpendicular; - /* 0x1E */ s16 countdown; + /* 0x1C */ s16 isRelativeToScreen; // is the quake relative to the screen or on world coordinates + /* 0x1E */ s16 timer; /* 0x20 */ s16 camId; } QuakeRequest; // size = 0x24 typedef struct { /* 0x0 */ PlayState* play; /* 0x4 */ s32 type; // bitfield, highest set bit determines type - /* 0x8 */ s16 countdown; + /* 0x8 */ s16 timer; /* 0xA */ s16 state; } DistortionRequest; // size = 0xC -typedef struct { - /* 0x00 */ Vec3f atOffset; - /* 0x0C */ Vec3f eyeOffset; - /* 0x18 */ s16 rollOffset; - /* 0x1A */ s16 zoom; -} ShakeInfo; // size = 0x1C - typedef s16 (*QuakeCallbackFunc)(QuakeRequest*, ShakeInfo*); typedef enum { @@ -40,230 +33,257 @@ typedef enum { /* 2 */ DISTORTION_SETUP } DistortionState; -QuakeRequest sQuakeRequest[4]; +QuakeRequest sQuakeRequests[4]; DistortionRequest sDistortionRequest; -static s16 sIsQuakeInitialized = true; +static s16 sQuakeUnused = 1; static s16 sQuakeRequestCount = 0; f32 Quake_Random(void) { return 2.0f * (Rand_ZeroOne() - 0.5f); } -void Quake_UpdateShakeInfo(QuakeRequest* req, ShakeInfo* shake, f32 verticalPertubation, f32 horizontalPertubation) { +void Quake_UpdateShakeInfo(QuakeRequest* req, ShakeInfo* shake, f32 yOffset, f32 xOffset) { Vec3f* at = &req->camera->at; Vec3f* eye = &req->camera->eye; Vec3f atEyeOffset; - VecSph atEyeOffsetSph2; - VecSph eyeAtAngle; + VecSph geo; + VecSph eyeToAtGeo; - // isShakePerpendicular is always set to 1 before reaching this conditional - // alternative is an unused fixed vertical shake - if (req->isShakePerpendicular) { + if (req->isRelativeToScreen) { atEyeOffset.x = 0; atEyeOffset.y = 0; atEyeOffset.z = 0; - OLib_Vec3fDiffToVecSphGeo(&eyeAtAngle, eye, at); + OLib_Vec3fDiffToVecGeo(&eyeToAtGeo, eye, at); - atEyeOffsetSph2.r = req->verticalMag * verticalPertubation; - atEyeOffsetSph2.pitch = eyeAtAngle.pitch + req->shakePlaneOffset.x + 0x4000; - atEyeOffsetSph2.yaw = eyeAtAngle.yaw + req->shakePlaneOffset.y; - OLib_VecSphAddToVec3f(&atEyeOffset, &atEyeOffset, &atEyeOffsetSph2); + // y shake + geo.r = req->y * yOffset; + // point unit vector up, then add on `req->orientation` + geo.pitch = eyeToAtGeo.pitch + req->orientation.x + 0x4000; + geo.yaw = eyeToAtGeo.yaw + req->orientation.y; + // apply y shake + OLib_AddVecGeoToVec3f(&atEyeOffset, &atEyeOffset, &geo); - atEyeOffsetSph2.r = req->horizontalMag * horizontalPertubation; - atEyeOffsetSph2.pitch = eyeAtAngle.pitch + req->shakePlaneOffset.x; - atEyeOffsetSph2.yaw = eyeAtAngle.yaw + req->shakePlaneOffset.y + 0x4000; - OLib_VecSphAddToVec3f(&atEyeOffset, &atEyeOffset, &atEyeOffsetSph2); + // x shake + geo.r = req->x * xOffset; + // point unit vector left, then add on `req->orientation` + geo.pitch = eyeToAtGeo.pitch + req->orientation.x; + geo.yaw = eyeToAtGeo.yaw + req->orientation.y + 0x4000; + // apply x shake + OLib_AddVecGeoToVec3f(&atEyeOffset, &atEyeOffset, &geo); } else { atEyeOffset.x = 0; - atEyeOffset.y = req->verticalMag * verticalPertubation; + atEyeOffset.y = req->y * yOffset; atEyeOffset.z = 0; - atEyeOffsetSph2.r = req->horizontalMag * horizontalPertubation; - atEyeOffsetSph2.pitch = req->shakePlaneOffset.x; - atEyeOffsetSph2.yaw = req->shakePlaneOffset.y; + geo.r = req->x * xOffset; + geo.pitch = req->orientation.x; + geo.yaw = req->orientation.y; - OLib_VecSphAddToVec3f(&atEyeOffset, &atEyeOffset, &atEyeOffsetSph2); + OLib_AddVecGeoToVec3f(&atEyeOffset, &atEyeOffset, &geo); } shake->atOffset = shake->eyeOffset = atEyeOffset; - shake->rollOffset = req->rollOffset * verticalPertubation; - shake->zoom = req->zoom * verticalPertubation; + shake->upRollOffset = req->upRollOffset * yOffset; + shake->fovOffset = req->fov * yOffset; } s16 Quake_CallbackType1(QuakeRequest* req, ShakeInfo* shake) { - if (req->countdown > 0) { - f32 perpendicularPertubation = Math_SinS(req->speed * req->countdown); + if (req->timer > 0) { + f32 xyOffset = Math_SinS(req->speed * req->timer); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, Rand_ZeroOne() * perpendicularPertubation); - req->countdown--; + Quake_UpdateShakeInfo(req, shake, xyOffset, Rand_ZeroOne() * xyOffset); + req->timer--; } - return req->countdown; + return req->timer; } s16 Quake_CallbackType5(QuakeRequest* req, ShakeInfo* shake) { - if (req->countdown > 0) { - f32 perpendicularPertubation = Math_SinS(req->speed * req->countdown); + if (req->timer > 0) { + f32 xyOffset = Math_SinS(req->speed * req->timer); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, perpendicularPertubation); - req->countdown--; + Quake_UpdateShakeInfo(req, shake, xyOffset, xyOffset); + req->timer--; } - return req->countdown; + return req->timer; } s16 Quake_CallbackType6(QuakeRequest* req, ShakeInfo* shake) { - f32 perpendicularPertubation; + f32 xyOffset; - req->countdown--; - perpendicularPertubation = Math_SinS(req->speed * ((req->countdown & 0xF) + 500)); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, Rand_ZeroOne() * perpendicularPertubation); + req->timer--; + xyOffset = Math_SinS(req->speed * ((req->timer & 0xF) + 500)); + Quake_UpdateShakeInfo(req, shake, xyOffset, Rand_ZeroOne() * xyOffset); + + // Not returning the timer ensures quake type 6 continues indefinitely until manually removed return 1; } s16 Quake_CallbackType3(QuakeRequest* req, ShakeInfo* shake) { - if (req->countdown > 0) { - f32 perpendicularPertubation = - Math_SinS(req->speed * req->countdown) * ((f32)req->countdown / (f32)req->countdownMax); + if (req->timer > 0) { + f32 xyOffset = Math_SinS(req->speed * req->timer) * ((f32)req->timer / req->duration); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, perpendicularPertubation); - req->countdown--; + Quake_UpdateShakeInfo(req, shake, xyOffset, xyOffset); + req->timer--; } - return req->countdown; + return req->timer; } s16 Quake_CallbackType2(QuakeRequest* req, ShakeInfo* shake) { - if (req->countdown > 0) { - f32 perpendicularPertubation = Quake_Random(); + if (req->timer > 0) { + f32 xyOffset = Quake_Random(); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, Rand_ZeroOne() * perpendicularPertubation); - req->countdown--; + Quake_UpdateShakeInfo(req, shake, xyOffset, Rand_ZeroOne() * xyOffset); + req->timer--; } - return req->countdown; + return req->timer; } s16 Quake_CallbackType4(QuakeRequest* req, ShakeInfo* shake) { - if (req->countdown > 0) { - f32 perpendicularPertubation = Quake_Random() * ((f32)req->countdown / (f32)req->countdownMax); + if (req->timer > 0) { + f32 xyOffset = Quake_Random() * ((f32)req->timer / req->duration); - Quake_UpdateShakeInfo(req, shake, perpendicularPertubation, Rand_ZeroOne() * perpendicularPertubation); - req->countdown--; + Quake_UpdateShakeInfo(req, shake, xyOffset, Rand_ZeroOne() * xyOffset); + req->timer--; } - return req->countdown; + return req->timer; } s16 Quake_GetFreeIndex(void) { s32 i; - s32 ret = 0; - s32 min = 0x10000; + s32 index = 0; + s32 timerMin = UINT16_MAX + 1; // timer is a short, so start with a value beyond its range - for (i = 0; i < ARRAY_COUNT(sQuakeRequest); i++) { - if (sQuakeRequest[i].type == 0) { - ret = i; + for (i = 0; i < ARRAY_COUNT(sQuakeRequests); i++) { + if (sQuakeRequests[i].type == QUAKE_TYPE_NONE) { + index = i; break; } - if (sQuakeRequest[i].countdown < min) { - min = sQuakeRequest[i].countdown; - ret = i; + if (timerMin > sQuakeRequests[i].timer) { + timerMin = sQuakeRequests[i].timer; + index = i; } } - return ret; + return index; } -QuakeRequest* Quake_AddImpl(Camera* camera, u32 type) { +QuakeRequest* Quake_RequestImpl(Camera* camera, u32 type) { s16 index = Quake_GetFreeIndex(); - QuakeRequest* req = &sQuakeRequest[index]; + QuakeRequest* req = &sQuakeRequests[index]; __osMemset(req, 0, sizeof(QuakeRequest)); + req->camera = camera; req->camId = camera->camId; req->type = type; - req->isShakePerpendicular = true; - req->randIndex = ((s16)(Rand_ZeroOne() * 0x10000) & ~3) + index; + req->isRelativeToScreen = true; + + // Add a unique random identifier to the upper bits of the index + // The `~3` assumes there are only 4 requests + req->index = index + ((s16)(Rand_ZeroOne() * 0x10000) & ~3); + sQuakeRequestCount++; return req; } -void Quake_RemoveRequest(QuakeRequest* req) { - req->type = 0; - req->countdown = -1; +void Quake_Remove(QuakeRequest* req) { + req->type = QUAKE_TYPE_NONE; + req->timer = -1; sQuakeRequestCount--; } -QuakeRequest* Quake_GetRequest(s16 quakeIndex) { - QuakeRequest* req = &sQuakeRequest[quakeIndex & 3]; +QuakeRequest* Quake_GetRequest(s16 index) { + QuakeRequest* req = &sQuakeRequests[index & 3]; - if (req->type == 0) { + if (req->type == QUAKE_TYPE_NONE) { return NULL; } - if (quakeIndex != req->randIndex) { + if (index != req->index) { return NULL; } return req; } -u32 Quake_SetValue(s16 quakeIndex, s16 valueType, s16 value) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +// valueType for Quake_SetValue() +#define QUAKE_SPEED (1 << 0) +#define QUAKE_Y_OFFSET (1 << 1) +#define QUAKE_X_OFFSET (1 << 2) +#define QUAKE_FOV (1 << 3) +#define QUAKE_ROLL (1 << 4) +#define QUAKE_ORIENTATION_PITCH (1 << 5) +#define QUAKE_ORIENTATION_YAW (1 << 6) +#define QUAKE_ORIENTATION_ROLL (1 << 7) +#define QUAKE_DURATION (1 << 8) +#define QUAKE_IS_RELATIVE_TO_SCREEN (1 << 9) + +u32 Quake_SetValue(s16 index, s16 valueType, s16 value) { + QuakeRequest* req = Quake_GetRequest(index); if (req == NULL) { return false; - } else { - switch (valueType) { - case QUAKE_SPEED: - req->speed = value; - break; - - case QUAKE_VERTICAL_MAG: - req->verticalMag = value; - break; - - case QUAKE_HORIZONTAL_MAG: - req->horizontalMag = value; - break; - - case QUAKE_ZOOM: - req->zoom = value; - break; - - case QUAKE_ROLL_OFFSET: - req->rollOffset = value; - break; - - case QUAKE_SHAKE_PLANE_OFFSET_X: - req->shakePlaneOffset.x = value; - break; - - case QUAKE_SHAKE_PLANE_OFFSET_Y: - req->shakePlaneOffset.y = value; - break; - - case QUAKE_SHAKE_PLANE_OFFSET_Z: - req->shakePlaneOffset.z = value; - break; - - case QUAKE_COUNTDOWN: - req->countdown = value; - req->countdownMax = req->countdown; - break; - - case QUAKE_IS_SHAKE_PERPENDICULAR: - req->isShakePerpendicular = value; - break; - - default: - break; - } - - return true; } + + switch (valueType) { + case QUAKE_SPEED: + req->speed = value; + break; + + case QUAKE_Y_OFFSET: + req->y = value; + break; + + case QUAKE_X_OFFSET: + req->x = value; + break; + + case QUAKE_FOV: + req->fov = value; + break; + + case QUAKE_ROLL: + req->upRollOffset = value; + break; + + case QUAKE_ORIENTATION_PITCH: + req->orientation.x = value; + break; + + case QUAKE_ORIENTATION_YAW: + req->orientation.y = value; + break; + + case QUAKE_ORIENTATION_ROLL: + req->orientation.z = value; + break; + + case QUAKE_DURATION: + req->timer = value; + req->duration = req->timer; + break; + + case QUAKE_IS_RELATIVE_TO_SCREEN: + req->isRelativeToScreen = value; + break; + + default: + break; + } + + return true; } -u32 Quake_SetSpeed(s16 quakeIndex, s16 speed) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +/** + * @param index + * @param speed for periodic types only, the angular frequency of the sine wave (binang / frame) + * @return true if successfully applied, false if the request does not exist + */ +u32 Quake_SetSpeed(s16 index, s16 speed) { + QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { req->speed = speed; @@ -272,45 +292,67 @@ u32 Quake_SetSpeed(s16 quakeIndex, s16 speed) { return false; } -u32 Quake_SetCountdown(s16 quakeIndex, s16 countdown) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +/** + * @param index quake request index to apply + * @param duration number of frames to apply the quake + * @return true if successfully applied, false if the request does not exist + */ +u32 Quake_SetDuration(s16 index, s16 duration) { + QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { - req->countdown = countdown; - req->countdownMax = req->countdown; + req->duration = req->timer = duration; return true; } return false; } -s16 Quake_GetCountdown(s16 quakeIndex) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +/** + * @param index quake request index to get + * @return number of frames until the quake is finished + */ +s16 Quake_GetTimeLeft(s16 index) { + QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { - return req->countdown; + return req->timer; } return 0; } -u32 Quake_SetQuakeValues(s16 quakeIndex, s16 verticalMag, s16 horizontalMag, s16 zoom, s16 rollOffset) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +/** + * @param index quake request index to apply + * @param y apply up/down shake + * @param x apply left/right shake + * @param fov apply zooming in/out shake (binang) + * @param roll apply rolling shake (binang) + * @return true if successfully applied, false if the request does not exist + */ +u32 Quake_SetPerturbations(s16 index, s16 y, s16 x, s16 fov, s16 roll) { + QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { - req->verticalMag = verticalMag; - req->horizontalMag = horizontalMag; - req->zoom = zoom; - req->rollOffset = rollOffset; + req->y = y; + req->x = x; + req->fov = fov; + req->upRollOffset = roll; return true; } return false; } -u32 Quake_SetQuakeValues2(s16 quakeIndex, s16 isShakePerpendicular, Vec3s shakePlaneOffset) { - QuakeRequest* req = Quake_GetRequest(quakeIndex); +/** + * @param index quake request index to apply + * @param isRelativeToScreen is the quake applied relative to the screen or in absolute world coordinates + * @param orientation orient the x/y shake to a different direction + * @return true if successfully applied, false if the request does not exist + */ +u32 Quake_SetOrientation(s16 index, s16 isRelativeToScreen, Vec3s orientation) { + QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { - req->isShakePerpendicular = isShakePerpendicular; - req->shakePlaneOffset = shakePlaneOffset; + req->isRelativeToScreen = isRelativeToScreen; + req->orientation = orientation; return true; } return false; @@ -319,156 +361,167 @@ u32 Quake_SetQuakeValues2(s16 quakeIndex, s16 isShakePerpendicular, Vec3s shakeP void Quake_Init(void) { s16 i; - for (i = 0; i < ARRAY_COUNT(sQuakeRequest); i++) { - sQuakeRequest[i].type = 0; - sQuakeRequest[i].countdown = 0; + for (i = 0; i < ARRAY_COUNT(sQuakeRequests); i++) { + sQuakeRequests[i].type = QUAKE_TYPE_NONE; + sQuakeRequests[i].timer = 0; } - sIsQuakeInitialized = true; + sQuakeUnused = 1; sQuakeRequestCount = 0; } -s16 Quake_Add(Camera* camera, u32 type) { - return Quake_AddImpl(camera, type)->randIndex; +s16 Quake_Request(Camera* camera, u32 type) { + return Quake_RequestImpl(camera, type)->index; } -u32 Quake_Remove(s16 index) { +u32 Quake_RemoveRequest(s16 index) { QuakeRequest* req = Quake_GetRequest(index); if (req != NULL) { - Quake_RemoveRequest(req); + Quake_Remove(req); return true; } return false; } static QuakeCallbackFunc sQuakeCallbacks[] = { - NULL, - Quake_CallbackType1, - Quake_CallbackType2, - Quake_CallbackType3, - Quake_CallbackType4, - Quake_CallbackType5, - Quake_CallbackType6, + NULL, // QUAKE_TYPE_NONE + Quake_CallbackType1, // QUAKE_TYPE_1 + Quake_CallbackType2, // QUAKE_TYPE_2 + Quake_CallbackType3, // QUAKE_TYPE_3 + Quake_CallbackType4, // QUAKE_TYPE_4 + Quake_CallbackType5, // QUAKE_TYPE_5 + Quake_CallbackType6, // QUAKE_TYPE_6 }; -s16 Quake_Calc(Camera* camera, QuakeCamCalc* camData) { - s32 pad; - QuakeRequest* req; - ShakeInfo shake; +s16 Quake_Update(Camera* camera, ShakeInfo* camShake) { f32 absSpeedDiv; + ShakeInfo shake; + QuakeRequest* req; f32 maxCurr; f32 maxNext; s32 index; - s32 ret; - u32 eq; - Vec3f originVec; + s32 numQuakesApplied; + u32 isDifferentCamId; + Vec3f zeroVec; PlayState* play = camera->play; - originVec.x = 0.0f; - originVec.y = 0.0f; - originVec.z = 0.0f; - camData->atOffset.x = 0.0f; - camData->atOffset.y = 0.0f; - camData->atOffset.z = 0.0f; - camData->eyeOffset.x = 0.0f; - camData->eyeOffset.y = 0.0f; - camData->eyeOffset.z = 0.0f; - camData->rollOffset = 0; - camData->zoom = 0; - camData->max = 0.0f; + zeroVec.x = 0.0f; + zeroVec.y = 0.0f; + zeroVec.z = 0.0f; + + camShake->atOffset.x = 0.0f; + camShake->atOffset.y = 0.0f; + camShake->atOffset.z = 0.0f; + + camShake->eyeOffset.x = 0.0f; + camShake->eyeOffset.y = 0.0f; + camShake->eyeOffset.z = 0.0f; + + camShake->upRollOffset = 0; + camShake->fovOffset = 0; + camShake->maxOffset = 0.0f; if (sQuakeRequestCount == 0) { return 0; } - ret = 0; - for (index = 0; index < ARRAY_COUNT(sQuakeRequest); index++) { - req = &sQuakeRequest[index]; - if (req->type != 0) { - if (play->cameraPtrs[req->camId] == NULL) { - Quake_RemoveRequest(req); - } else { - eq = (camera->camId != req->camera->camId); - absSpeedDiv = ABS(req->speed) / (f32)0x8000; - if (sQuakeCallbacks[req->type](req, &shake) == 0) { - Quake_RemoveRequest(req); - } else if (eq == 0) { - if (fabsf(camData->atOffset.x) < fabsf(shake.atOffset.x)) { - camData->atOffset.x = shake.atOffset.x; - } - if (fabsf(camData->atOffset.y) < fabsf(shake.atOffset.y)) { - camData->atOffset.y = shake.atOffset.y; - } - if (fabsf(camData->atOffset.z) < fabsf(shake.atOffset.z)) { - camData->atOffset.z = shake.atOffset.z; - } - if (fabsf(camData->eyeOffset.x) < fabsf(shake.eyeOffset.x)) { - camData->eyeOffset.x = shake.eyeOffset.x; - } - if (fabsf(camData->eyeOffset.y) < fabsf(shake.eyeOffset.y)) { - camData->eyeOffset.y = shake.eyeOffset.y; - } - if (fabsf(camData->eyeOffset.z) < fabsf(shake.eyeOffset.z)) { - camData->eyeOffset.z = shake.eyeOffset.z; - } - if (camData->rollOffset < shake.rollOffset) { - camData->rollOffset = shake.rollOffset; - } - if (camData->zoom < shake.zoom) { - camData->zoom = shake.zoom; - } - - maxCurr = OLib_Vec3fDist(&shake.atOffset, &originVec) * absSpeedDiv; - - maxNext = OLib_Vec3fDist(&shake.eyeOffset, &originVec) * absSpeedDiv; - maxCurr = CLAMP_MIN(maxCurr, maxNext); - - maxNext = (camData->rollOffset * (7.0f / 2500.0f)) * absSpeedDiv; - maxCurr = CLAMP_MIN(maxCurr, maxNext); - - maxNext = (camData->zoom * (7.0f / 2500.0f)) * absSpeedDiv; - maxCurr = CLAMP_MIN(maxCurr, maxNext); - - if (camData->max < maxCurr) { - camData->max = maxCurr; - } - - ret++; - } - } + numQuakesApplied = 0; + for (index = 0; index < ARRAY_COUNT(sQuakeRequests); index++) { + req = &sQuakeRequests[index]; + if (req->type == QUAKE_TYPE_NONE) { + continue; } + + if (play->cameraPtrs[req->camId] == NULL) { + Quake_Remove(req); + continue; + } + + isDifferentCamId = (camera->camId != req->camera->camId); + absSpeedDiv = (f32)ABS(req->speed) / 0x8000; + if (sQuakeCallbacks[req->type](req, &shake) == 0) { + // Quake has reached the end of its timer. + Quake_Remove(req); + continue; + } + + if (isDifferentCamId) { + // Quake is attached to a different camId + continue; + } + + if (fabsf(camShake->atOffset.x) < fabsf(shake.atOffset.x)) { + camShake->atOffset.x = shake.atOffset.x; + } + if (fabsf(camShake->atOffset.y) < fabsf(shake.atOffset.y)) { + camShake->atOffset.y = shake.atOffset.y; + } + if (fabsf(camShake->atOffset.z) < fabsf(shake.atOffset.z)) { + camShake->atOffset.z = shake.atOffset.z; + } + if (fabsf(camShake->eyeOffset.x) < fabsf(shake.eyeOffset.x)) { + camShake->eyeOffset.x = shake.eyeOffset.x; + } + if (fabsf(camShake->eyeOffset.y) < fabsf(shake.eyeOffset.y)) { + camShake->eyeOffset.y = shake.eyeOffset.y; + } + if (fabsf(camShake->eyeOffset.z) < fabsf(shake.eyeOffset.z)) { + camShake->eyeOffset.z = shake.eyeOffset.z; + } + if (camShake->upRollOffset < shake.upRollOffset) { + camShake->upRollOffset = shake.upRollOffset; + } + if (camShake->fovOffset < shake.fovOffset) { + camShake->fovOffset = shake.fovOffset; + } + + maxCurr = OLib_Vec3fDist(&shake.atOffset, &zeroVec) * absSpeedDiv; + maxNext = OLib_Vec3fDist(&shake.eyeOffset, &zeroVec) * absSpeedDiv; + maxCurr = CLAMP_MIN(maxCurr, maxNext); + + maxNext = (camShake->upRollOffset * (7.0f / 2500.0f)) * absSpeedDiv; + maxCurr = CLAMP_MIN(maxCurr, maxNext); + + maxNext = (camShake->fovOffset * (7.0f / 2500.0f)) * absSpeedDiv; + maxCurr = CLAMP_MIN(maxCurr, maxNext); + + if (camShake->maxOffset < maxCurr) { + camShake->maxOffset = maxCurr; + } + + numQuakesApplied++; } - return ret; + return numQuakesApplied; } void Distortion_Init(PlayState* play) { sDistortionRequest.play = play; View_ClearDistortion(&play->view); sDistortionRequest.type = 0; - sDistortionRequest.countdown = 0; + sDistortionRequest.timer = 0; sDistortionRequest.state = DISTORTION_INACTIVE; } -void Distortion_SetCountdown(s16 countdown) { - sDistortionRequest.countdown = countdown; +void Distortion_SetDuration(s16 duration) { + sDistortionRequest.timer = duration; sDistortionRequest.state = DISTORTION_SETUP; } -s16 Distortion_GetCountdown(void) { - return sDistortionRequest.countdown; +s16 Distortion_GetTimeLeft(void) { + return sDistortionRequest.timer; } s16 Distortion_GetType(void) { return sDistortionRequest.type; } -void Distortion_SetType(s32 type) { +void Distortion_Request(s32 type) { if (sDistortionRequest.type < type) { sDistortionRequest.type = type; } } -void Distortion_ClearType(s32 type) { +void Distortion_RemoveRequest(s32 type) { if (sDistortionRequest.type == type) { sDistortionRequest.type = 0; } @@ -489,7 +542,7 @@ ConveyorSpeed Distortion_GetUnderwaterCurrentSpeed(Player* player) { void Distortion_Update(void) { static s16 depthPhase = 0x3F0; static s16 screenPlanePhase = 0x156; - static s16 countdownMax = 1; + static s16 duration = 1; f32 xyScaleFactor; f32 zScaleFactor; f32 speedScaleFactor; @@ -511,8 +564,8 @@ void Distortion_Update(void) { f32 speedRatio = CLAMP_MAX(camera->speedRatio, 1.0f); if (sDistortionRequest.type != 0) { - if (sDistortionRequest.type & DISTORTION_TYPE_B) { - sDistortionRequest.countdown = 2; + if (sDistortionRequest.type & DISTORTION_TYPE_MASK_TRANSFORM_2) { + sDistortionRequest.timer = 2; depthPhase = 0x3F0; screenPlanePhase = 0x156; @@ -528,17 +581,17 @@ void Distortion_Update(void) { zScale = 0.0f; speed = 0.6f; - xyScaleFactor = zScaleFactor = sDistortionRequest.countdown / 60.0f; + xyScaleFactor = zScaleFactor = sDistortionRequest.timer / 60.0f; speedScaleFactor = 1.0f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_A) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_BOSS_WARP) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x3F0; screenPlanePhase = 0x156; } depthPhaseStep = 0.0f; - screenPlanePhaseStep = 50.0f / countdownMax; + screenPlanePhaseStep = 50.0f / duration; rotX = 0.0f; rotY = 0.0f; @@ -549,11 +602,11 @@ void Distortion_Update(void) { zScale = 0.0f; speed = 0.4f; - xyScaleFactor = zScaleFactor = ((f32)countdownMax - sDistortionRequest.countdown) / (f32)countdownMax; + xyScaleFactor = zScaleFactor = ((f32)duration - sDistortionRequest.timer) / (f32)duration; speedScaleFactor = 0.5f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_9) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_MASK_TRANSFORM_1) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x1FC; screenPlanePhase = 0x156; } @@ -570,11 +623,11 @@ void Distortion_Update(void) { zScale = 0.0f; speed = 0.1f; - xyScaleFactor = zScaleFactor = ((f32)countdownMax - sDistortionRequest.countdown) / (f32)countdownMax; + xyScaleFactor = zScaleFactor = ((f32)duration - sDistortionRequest.timer) / (f32)duration; speedScaleFactor = 1.0f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_8) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_GORON_BUTT) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x2710; screenPlanePhase = 0x3E8; } @@ -591,15 +644,15 @@ void Distortion_Update(void) { zScale = 0.01f; speed = 1.5f; - if (sDistortionRequest.countdown < 5) { - xyScaleFactor = zScaleFactor = ((f32)countdownMax - sDistortionRequest.countdown) / (f32)countdownMax; + if (sDistortionRequest.timer < 5) { + xyScaleFactor = zScaleFactor = ((f32)duration - sDistortionRequest.timer) / (f32)duration; } else { xyScaleFactor = zScaleFactor = 0.0f; } speedScaleFactor = 1.0f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_7) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_UNK_ATTACK) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x4B0; screenPlanePhase = 0x7D0; } @@ -616,11 +669,11 @@ void Distortion_Update(void) { zScale = 0.01f; speed = 1.5f; - xyScaleFactor = zScaleFactor = sDistortionRequest.countdown / (f32)countdownMax; + xyScaleFactor = zScaleFactor = sDistortionRequest.timer / (f32)duration; speedScaleFactor = 1.0f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_6) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_ZORA_KICK) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x9C4; screenPlanePhase = 0xBB8; } @@ -637,14 +690,14 @@ void Distortion_Update(void) { zScale = 0.01f; speed = 1.3f; - if (sDistortionRequest.countdown < 4) { - xyScaleFactor = zScaleFactor = sDistortionRequest.countdown / (f32)countdownMax; + if (sDistortionRequest.timer < 4) { + xyScaleFactor = zScaleFactor = sDistortionRequest.timer / (f32)duration; } else { xyScaleFactor = zScaleFactor = 0.0f; } speedScaleFactor = 1.0f; - } else if (sDistortionRequest.type & DISTORTION_TYPE_5) { - sDistortionRequest.countdown = 2; + } else if (sDistortionRequest.type & DISTORTION_TYPE_SONG_OF_TIME) { + sDistortionRequest.timer = 2; if (sDistortionRequest.state == DISTORTION_SETUP) { depthPhase = 0x9C4; screenPlanePhase = 0xBB8; @@ -670,7 +723,7 @@ void Distortion_Update(void) { speedScaleFactor = 1.0f; } else if (sDistortionRequest.type & DISTORTION_TYPE_UNDERWATER_ENTRY) { if (sDistortionRequest.state == DISTORTION_SETUP) { - countdownMax = sDistortionRequest.countdown; + duration = sDistortionRequest.timer; depthPhase = 0x760; screenPlanePhase = 0x1BC; } @@ -687,14 +740,14 @@ void Distortion_Update(void) { zScale = 0.2f; speed = 0.25f; - countdownRatio = sDistortionRequest.countdown / (f32)countdownMax; + countdownRatio = sDistortionRequest.timer / (f32)duration; zScaleFactor = xyScaleFactor = countdownRatio; speedScaleFactor = 1.0f; } else if (sDistortionRequest.type & DISTORTION_TYPE_ZORA_SWIMMING) { depthPhase = 0x3F0; screenPlanePhase = 0x156; - sDistortionRequest.countdown = 2; + sDistortionRequest.timer = 2; player = GET_PLAYER(play); if (player != NULL) { @@ -749,7 +802,7 @@ void Distortion_Update(void) { depthPhase = 0x3F0; screenPlanePhase = 0x156; - sDistortionRequest.countdown = 2; + sDistortionRequest.timer = 2; player = GET_PLAYER(play); depthPhaseStep = 359.2f; @@ -796,12 +849,12 @@ void Distortion_Update(void) { xyScaleFactor = speedScaleFactor = (waterYScaleFactor * 0.15f) + 0.35f + (speedRatio * 0.4f); zScaleFactor = 0.9f - xyScaleFactor; - } else if (sDistortionRequest.type & DISTORTION_TYPE_0) { + } else if (sDistortionRequest.type & DISTORTION_TYPE_HOT_ROOM) { // Gives a small mirage-like appearance depthPhase = 0x3F0; screenPlanePhase = 0x156; - sDistortionRequest.countdown = 2; + sDistortionRequest.timer = 2; depthPhaseStep = 0.0f; screenPlanePhaseStep = 150.0f; @@ -840,32 +893,25 @@ void Distortion_Update(void) { View_ClearDistortion(&play->view); sDistortionRequest.state = DISTORTION_INACTIVE; - sDistortionRequest.countdown = 0; + sDistortionRequest.timer = 0; } - if (sDistortionRequest.countdown != 0) { - sDistortionRequest.countdown--; - if (sDistortionRequest.countdown == 0) { + if (sDistortionRequest.timer != 0) { + sDistortionRequest.timer--; + if (sDistortionRequest.timer == 0) { sDistortionRequest.type = 0; } } } -s32 Quake_NumActiveQuakes(void) { - QuakeRequest* req = sQuakeRequest; +s32 Quake_GetNumActiveQuakes(void) { s32 numActiveQuakes = 0; + s32 i; - if (req[0].type != 0) { - numActiveQuakes++; - } - if (req[1].type != 0) { - numActiveQuakes++; - } - if (req[2].type != 0) { - numActiveQuakes++; - } - if (req[3].type != 0) { - numActiveQuakes++; + for (i = 0; i < ARRAY_COUNT(sQuakeRequests); i++) { + if (sQuakeRequests[i].type != QUAKE_TYPE_NONE) { + numActiveQuakes++; + } } return numActiveQuakes; diff --git a/src/code/z_room.c b/src/code/z_room.c index 369b2b0e5..da221ccd4 100644 --- a/src/code/z_room.c +++ b/src/code/z_room.c @@ -59,40 +59,28 @@ typedef struct RoomShapeCullableEntryLinked { /* 0x0C */ struct RoomShapeCullableEntryLinked* next; } RoomShapeCullableEntryLinked; // size = 0x10 -// TODO: 127 is an arbitrarily chosen number to make the stack sorta work -#define ROOM_SHAPE_CULLABLE_MAX_ENTRIES 127 +#define ROOM_SHAPE_CULLABLE_MAX_ENTRIES 128 -#ifdef NON_MATCHING -// Small regalloc, likely related to temp usage and scoping void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { RoomShapeCullable* roomShape; RoomShapeCullableEntry* roomShapeCullableEntry; - RoomShapeCullableEntry* roomShapeCullableEntries; - RoomShapeCullableEntry* roomShapeCullableEntryIter; - Gfx* displayList; - f32 entryBoundsNearZ; RoomShapeCullableEntryLinked linkedEntriesBuffer[ROOM_SHAPE_CULLABLE_MAX_ENTRIES]; RoomShapeCullableEntryLinked* head = NULL; RoomShapeCullableEntryLinked* tail = NULL; - s32 var_a1; RoomShapeCullableEntryLinked* iter; + Gfx* displayList; RoomShapeCullableEntryLinked* insert; - f32 var_fv1; + f32 entryBoundsNearZ; s32 i; Vec3f pos; Vec3f projectedPos; - s32 pad2; + RoomShapeCullableEntry* roomShapeCullableEntries; OPEN_DISPS(play->state.gfxCtx); if (flags & ROOM_DRAW_OPA) { func_800BCBF4(&sZeroVec, play); - //! TODO: Fake - if (1) {} - if (1) {} - if (1) {} - gSPSegment(POLY_OPA_DISP++, 0x03, room->segment); if (play->roomCtx.unk74 != NULL) { gSPSegment(POLY_OPA_DISP++, 0x06, play->roomCtx.unk74); @@ -159,8 +147,9 @@ void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { } } } else { - f32 var_fa1 = 1.0f / play->projectionMtxFDiagonal.z; // sp54 - s32 pad5; + f32 var_fa1 = 1.0f / play->projectionMtxFDiagonal.z; + f32 var_fv1; + s32 var_a1; // Pick and sort entries by depth for (i = 0; i < roomShape->numEntries; i++, roomShapeCullableEntry++) { @@ -237,8 +226,7 @@ void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { if (flags & ROOM_DRAW_OPA) { for (; head != NULL; head = head->next, i++) { - s32 pad3; - RoomShapeCullableEntry* roomShapeCullableEntry; + s32 pad; roomShapeCullableEntry = head->entry; @@ -265,17 +253,17 @@ void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { } if (flags & ROOM_DRAW_XLU) { - for (; head != NULL; head = head->prev) { + for (; tail != NULL; tail = tail->prev) { f32 temp_fv0; f32 temp_fv1; - roomShapeCullableEntry = head->entry; + roomShapeCullableEntry = tail->entry; displayList = roomShapeCullableEntry->xlu; if (displayList != NULL) { if (roomShapeCullableEntry->boundsSphereRadius & 1) { - temp_fv0 = head->boundsNearZ - (f32)(iREG(93) + 0xBB8); + temp_fv0 = tail->boundsNearZ - (f32)(iREG(93) + 0xBB8); temp_fv1 = iREG(94) + 0x7D0; if (temp_fv0 < temp_fv1) { @@ -299,10 +287,6 @@ void Room_DrawCullable(PlayState* play, Room* room, u32 flags) { CLOSE_DISPS(play->state.gfxCtx); } -#else -void Room_DrawCullable(PlayState* play, Room* room, u32 flags); -#pragma GLOBAL_ASM("asm/non_matchings/code/z_room/Room_DrawCullable.s") -#endif #define ROOM_IMAGE_NODRAW_BACKGROUND (1 << 0) #define ROOM_IMAGE_NODRAW_OPA (1 << 1) @@ -373,7 +357,7 @@ void Room_DrawImageSingle(PlayState* play, Room* room, u32 flags) { RoomShapeImageMultiBgEntry* Room_GetImageMultiBgEntry(RoomShapeImageMulti* roomShapeImageMulti, PlayState* play) { Camera* activeCam = GET_ACTIVE_CAM(play); - s32 bgCamIndex = activeCam->bgCamDataId; + s32 bgCamIndex = activeCam->bgCamIndex; s16 overrideBgCamIndex; Player* player; RoomShapeImageMultiBgEntry* bgEntry; diff --git a/src/overlays/actors/ovl_Bg_Hakugin_Post/z_bg_hakugin_post.c b/src/overlays/actors/ovl_Bg_Hakugin_Post/z_bg_hakugin_post.c index be0f01601..d334cf779 100644 --- a/src/overlays/actors/ovl_Bg_Hakugin_Post/z_bg_hakugin_post.c +++ b/src/overlays/actors/ovl_Bg_Hakugin_Post/z_bg_hakugin_post.c @@ -522,10 +522,10 @@ void func_80A9C058(BgHakuginPost* this, PlayState* play, BgHakuginPostUnkStruct* sp44.z = this->dyna.actor.home.pos.z + unkStruct1->unk_14.z; Rumble_Request(Math3D_Vec3fDistSq(&sp44, &GET_PLAYER(play)->actor.world.pos), 255, 20, 150); - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 7, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 12); + Quake_SetPerturbations(quakeIndex, 7, 0, 0, 0); + Quake_SetDuration(quakeIndex, 12); if (this->unk_179 <= 0) { func_8019F128(NA_SE_EV_STONEDOOR_STOP); @@ -537,7 +537,7 @@ void func_80A9C058(BgHakuginPost* this, PlayState* play, BgHakuginPostUnkStruct* } } -void func_80A9C18C(BgHakuginPost* this, PlayState* play) { +void BgHakuginPost_RequestQuakeAndRumble(BgHakuginPost* this, PlayState* play) { s32 pad; Player* player = GET_PLAYER(play); Camera* activeCam = GET_ACTIVE_CAM(play); @@ -547,10 +547,10 @@ void func_80A9C18C(BgHakuginPost* this, PlayState* play) { this->dyna.actor.home.pos.z), 255, 20, 150); - quakeIndex = Quake_Add(activeCam, QUAKE_TYPE_3); + quakeIndex = Quake_Request(activeCam, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 17232); - Quake_SetQuakeValues(quakeIndex, 6, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 20); + Quake_SetPerturbations(quakeIndex, 6, 0, 0, 0); + Quake_SetDuration(quakeIndex, 20); } void func_80A9C228(BgHakuginPost* this, PlayState* play, BgHakuginPostUnkStruct* unkStruct) { @@ -798,7 +798,7 @@ void func_80A9CD14(BgHakuginPost* this, PlayState* play) { temp_f12 = CLAMP_MAX(temp_f12, 40.0f); this->unk_16C += temp_f12; if (this->unk_168 <= this->unk_16C) { - func_80A9C18C(this, play); + BgHakuginPost_RequestQuakeAndRumble(this, play); func_8019F128(NA_SE_EV_STONEDOOR_STOP); func_80A9CE00(this); } else { @@ -876,7 +876,7 @@ void func_80A9D0B4(BgHakuginPost* this, PlayState* play) { func_80A9C634(this, play); func_80A9B160(&D_80A9E028, play); this->unk_16C = this->unk_164; - func_80A9C18C(this, play); + BgHakuginPost_RequestQuakeAndRumble(this, play); func_8019F128(NA_SE_EV_STONEDOOR_STOP); func_80A9CC84(this); } else { diff --git a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c index 44f81da9c..f853fdfc5 100644 --- a/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c +++ b/src/overlays/actors/ovl_Bg_Ikana_Dharma/z_bg_ikana_dharma.c @@ -228,11 +228,11 @@ void BgIkanaDharma_Update(Actor* thisx, PlayState* play) { Actor_MoveWithGravity(&this->dyna.actor); Actor_UpdateBgCheckInfo(play, &this->dyna.actor, 0.0f, 0.0f, 0.0f, UPDBGCHECKINFO_FLAG_4); if (this->dyna.actor.bgCheckFlags & BGCHECKFLAG_GROUND_TOUCH) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 21536); - Quake_SetQuakeValues(quakeIndex, 4, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 12); + Quake_SetPerturbations(quakeIndex, 4, 0, 0, 0); + Quake_SetDuration(quakeIndex, 12); Actor_PlaySfx(&this->dyna.actor, NA_SE_EV_BLOCK_BOUND); } diff --git a/src/overlays/actors/ovl_Bg_Ikana_Rotaryroom/z_bg_ikana_rotaryroom.c b/src/overlays/actors/ovl_Bg_Ikana_Rotaryroom/z_bg_ikana_rotaryroom.c index 7398dbfd9..8a90a6809 100644 --- a/src/overlays/actors/ovl_Bg_Ikana_Rotaryroom/z_bg_ikana_rotaryroom.c +++ b/src/overlays/actors/ovl_Bg_Ikana_Rotaryroom/z_bg_ikana_rotaryroom.c @@ -832,11 +832,11 @@ void func_80B81A80(Actor* thisx, PlayState* play) { func_80B81B84(this); } else if (this->unk_584 == 15) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 31536); - Quake_SetQuakeValues(quakeIndex, 6, 0, 100, 0); - Quake_SetCountdown(quakeIndex, 22); + Quake_SetPerturbations(quakeIndex, 6, 0, 100, 0); + Quake_SetDuration(quakeIndex, 22); } } @@ -859,11 +859,11 @@ void func_80B81BA0(Actor* thisx, PlayState* play) { thisx->shape.rot.x += 0x1F4; if (!(this->unk_584 & 7)) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 31536); - Quake_SetQuakeValues(quakeIndex, (s32)(Rand_ZeroOne() * 2.5f) + 3, 0, 10, 0); - Quake_SetCountdown(quakeIndex, 15); + Quake_SetPerturbations(quakeIndex, (s32)(Rand_ZeroOne() * 2.5f) + 3, 0, 10, 0); + Quake_SetDuration(quakeIndex, 15); } if (Flags_GetSwitch(play, BGIKANAROTARYROOM_GET_FE(&this->dyna.actor))) { @@ -929,11 +929,11 @@ void func_80B81DC8(Actor* thisx, PlayState* play) { CutsceneManager_Stop(this->dyna.actor.csId); func_80B818B4(this); } else if (this->unk_584 == 19) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 5, 0, 40, 60); - Quake_SetCountdown(quakeIndex, 17); + Quake_SetPerturbations(quakeIndex, 5, 0, 40, 60); + Quake_SetDuration(quakeIndex, 17); } } diff --git a/src/overlays/actors/ovl_Bg_Ikana_Shutter/z_bg_ikana_shutter.c b/src/overlays/actors/ovl_Bg_Ikana_Shutter/z_bg_ikana_shutter.c index f39ca3b8c..4a0abb472 100644 --- a/src/overlays/actors/ovl_Bg_Ikana_Shutter/z_bg_ikana_shutter.c +++ b/src/overlays/actors/ovl_Bg_Ikana_Shutter/z_bg_ikana_shutter.c @@ -151,10 +151,10 @@ void func_80BD5A18(BgIkanaShutter* this, PlayState* play) { this->dyna.actor.velocity.y *= 0.978f; this->dyna.actor.world.pos.y += this->dyna.actor.velocity.y; if (this->dyna.actor.world.pos.y <= this->dyna.actor.home.pos.y) { - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 21536); - Quake_SetQuakeValues(quakeIndex, 4, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 12); + Quake_SetPerturbations(quakeIndex, 4, 0, 0, 0); + Quake_SetDuration(quakeIndex, 12); func_80BD5828(this); } diff --git a/src/overlays/actors/ovl_Bg_Iknin_Susceil/z_bg_iknin_susceil.c b/src/overlays/actors/ovl_Bg_Iknin_Susceil/z_bg_iknin_susceil.c index 5a69e3ca7..48045527f 100644 --- a/src/overlays/actors/ovl_Bg_Iknin_Susceil/z_bg_iknin_susceil.c +++ b/src/overlays/actors/ovl_Bg_Iknin_Susceil/z_bg_iknin_susceil.c @@ -69,19 +69,20 @@ void func_80C0A838(BgIkninSusceil* this, PlayState* play) { DynaPoly_DisableCollision(play, &play->colCtx.dyna, this->dyna.bgId); } -void func_80C0A86C(BgIkninSusceil* this, PlayState* play, s16 verticalMag, s16 countdown, s32 arg4) { +void BgIkninSusceil_RequestQuakeAndRumble(BgIkninSusceil* this, PlayState* play, s16 quakeY, s16 quakeDuration, + s32 rumbleType) { s32 pad; - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 31536); - Quake_SetQuakeValues(quakeIndex, verticalMag, 0, 0, 0); - Quake_SetCountdown(quakeIndex, countdown); + Quake_SetPerturbations(quakeIndex, quakeY, 0, 0, 0); + Quake_SetDuration(quakeIndex, quakeDuration); - if (arg4 == 1) { + if (rumbleType == 1) { Rumble_Request(SQ(100.0f), 255, 20, 150); - } else if (arg4 == 2) { + } else if (rumbleType == 2) { Rumble_Request(SQ(100.0f), 180, 20, 100); - } else if (arg4 == 3) { + } else if (rumbleType == 3) { Rumble_Request(SQ(100.0f), 120, 20, 10); } } @@ -154,7 +155,7 @@ void func_80C0ABA8(BgIkninSusceil* this, PlayState* play) { this->dyna.actor.velocity.y *= 0.93f; this->dyna.actor.world.pos.y += this->dyna.actor.velocity.y; if (this->dyna.actor.world.pos.y <= this->dyna.actor.home.pos.y) { - func_80C0A86C(this, play, 4, 14, 1); + BgIkninSusceil_RequestQuakeAndRumble(this, play, 4, 14, 1); Flags_UnsetSwitch(play, SUSCEIL_GET_SWITCHFLAG(&this->dyna.actor)); Actor_PlaySfx(&this->dyna.actor, NA_SE_EV_BIGWALL_BOUND); func_80C0AC74(this); @@ -197,7 +198,7 @@ void func_80C0AD64(BgIkninSusceil* this, PlayState* play) { this->dyna.actor.velocity.y *= 0.98f; if (Math_SmoothStepToF(&this->dyna.actor.world.pos.y, this->dyna.actor.home.pos.y + 365.0f, 0.5f, this->dyna.actor.velocity.y, 1.0f) < 0.1f) { - func_80C0A86C(this, play, 1, 14, 3); + BgIkninSusceil_RequestQuakeAndRumble(this, play, 1, 14, 3); CutsceneManager_Stop(this->dyna.actor.csId); func_80C0AB14(this); } else { @@ -216,7 +217,7 @@ void func_80C0AE5C(BgIkninSusceil* this, PlayState* play) { this->dyna.actor.velocity.y = CLAMP_MIN(this->dyna.actor.velocity.y, 1.0f); this->dyna.actor.world.pos.y = this->dyna.actor.world.pos.y + this->dyna.actor.velocity.y; if ((this->dyna.actor.home.pos.y + 365.0f) < this->dyna.actor.world.pos.y) { - func_80C0A86C(this, play, 3, 14, 2); + BgIkninSusceil_RequestQuakeAndRumble(this, play, 3, 14, 2); func_80C0AB14(this); } } diff --git a/src/overlays/actors/ovl_Bg_Open_Shutter/z_bg_open_shutter.c b/src/overlays/actors/ovl_Bg_Open_Shutter/z_bg_open_shutter.c index 6acbc8aa8..9a3bbabdf 100644 --- a/src/overlays/actors/ovl_Bg_Open_Shutter/z_bg_open_shutter.c +++ b/src/overlays/actors/ovl_Bg_Open_Shutter/z_bg_open_shutter.c @@ -151,10 +151,10 @@ void func_80ACAEF0(BgOpenShutter* this, PlayState* play) { Actor_SpawnFloorDustRing(play, &this->dyna.actor, &this->dyna.actor.world.pos, 60.0f, 10, 8.0f, 500, 10, true); Actor_PlaySfx(&this->dyna.actor, NA_SE_EV_BIGWALL_BOUND); - quakeIndex = Quake_Add(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); + quakeIndex = Quake_Request(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, -32536); - Quake_SetQuakeValues(quakeIndex, 2, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 10); + Quake_SetPerturbations(quakeIndex, 2, 0, 0, 0); + Quake_SetDuration(quakeIndex, 10); Rumble_Request(this->dyna.actor.xyzDistToPlayerSq, 180, 20, 100); diff --git a/src/overlays/actors/ovl_Boss_03/z_boss_03.c b/src/overlays/actors/ovl_Boss_03/z_boss_03.c index c4c38982e..054b612bc 100644 --- a/src/overlays/actors/ovl_Boss_03/z_boss_03.c +++ b/src/overlays/actors/ovl_Boss_03/z_boss_03.c @@ -1050,7 +1050,7 @@ void Boss03_Charge(Boss03* this, PlayState* play) { // Attack platform if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { play_sound(NA_SE_IT_BIG_BOMB_EXPLOSION); - func_800BC848(&this->actor, play, 20, 15); + Actor_RequestQuakeAndRumble(&this->actor, play, 20, 15); Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WATER_EFFECT, 0.0f, this->waterHeight, 0.0f, 0, 0, 0x96, ENWATEREFFECT_TYPE_GYORG_SHOCKWAVE); @@ -1773,7 +1773,7 @@ void Boss03_Stunned(Boss03* this, PlayState* play) { Actor_MoveWithGravity(&this->actor); if (this->actor.bgCheckFlags & BGCHECKFLAG_GROUND_TOUCH) { play_sound(NA_SE_IT_WALL_HIT_HARD); - func_800BC848(&this->actor, play, 10, 10); + Actor_RequestQuakeAndRumble(&this->actor, play, 10, 10); } } else { Math_ApproachS(&this->actor.shape.rot.z, -0x6000, 0xA, 0x900); diff --git a/src/overlays/actors/ovl_Boss_04/z_boss_04.c b/src/overlays/actors/ovl_Boss_04/z_boss_04.c index a39b10143..80fc52a22 100644 --- a/src/overlays/actors/ovl_Boss_04/z_boss_04.c +++ b/src/overlays/actors/ovl_Boss_04/z_boss_04.c @@ -481,7 +481,7 @@ void func_809ECF58(Boss04* this, PlayState* play) { if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { play_sound(NA_SE_IT_BIG_BOMB_EXPLOSION); - func_800BC848(&this->actor, play, 15, 10); + Actor_RequestQuakeAndRumble(&this->actor, play, 15, 10); this->unk_6F4 = 15; sp3C.x = this->actor.focus.pos.x; sp3C.y = this->actor.focus.pos.y; diff --git a/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c b/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c index f8fef514d..fcc183ef9 100644 --- a/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c +++ b/src/overlays/actors/ovl_Door_Shutter/z_door_shutter.c @@ -610,10 +610,10 @@ void func_808A1B48(DoorShutter* this, PlayState* play) { } Actor_PlaySfx(&this->actor, NA_SE_EV_BIGWALL_BOUND); - quakeIndex = Quake_Add(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); + quakeIndex = Quake_Request(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, -32536); - Quake_SetQuakeValues(quakeIndex, 2, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 10); + Quake_SetPerturbations(quakeIndex, 2, 0, 0, 0); + Quake_SetDuration(quakeIndex, 10); Rumble_Request(this->actor.xyzDistToPlayerSq, 180, 20, 100); diff --git a/src/overlays/actors/ovl_En_And/z_en_and.c b/src/overlays/actors/ovl_En_And/z_en_and.c index 5c888ba45..c1f229751 100644 --- a/src/overlays/actors/ovl_En_And/z_en_and.c +++ b/src/overlays/actors/ovl_En_And/z_en_and.c @@ -10,14 +10,13 @@ #define THIS ((EnAnd*)thisx) +#define EYE_TEXTURES_COUNT 4 + void EnAnd_Init(Actor* thisx, PlayState* play); void EnAnd_Destroy(Actor* thisx, PlayState* play); void EnAnd_Update(Actor* thisx, PlayState* play); void EnAnd_Draw(Actor* thisx, PlayState* play); -void func_80C18C50(EnAnd* this, PlayState* play); - -#if 0 ActorInit En_And_InitVars = { ACTOR_EN_AND, ACTORCAT_NPC, @@ -30,22 +29,163 @@ ActorInit En_And_InitVars = { (ActorFunc)EnAnd_Draw, }; -#endif +static AnimationInfoS sAnimationInfo[] = { + { &gAndStaticAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gAndIdleAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gAndWalkAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gAndRaiseHeadAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gAndRaisedHeadLoopAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gAndRaiseHandAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, + { &gAndRaisedHandLoopAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 }, + { &gAndRaisedHandWalkAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 }, +}; -extern UNK_TYPE D_0600B380; +s32 EnAnd_ChangeAnim(EnAnd* this, s32 animIndex) { + s32 ret = false; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/func_80C18B90.s") + if (this->animIndex != animIndex) { + this->animIndex = animIndex; + ret = SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, animIndex); + } + return ret; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/func_80C18BD8.s") +void EnAnd_Blink(EnAnd* this) { + if (DECR(this->blinkTimer) == 0) { + this->eyeTexIndex++; + if (this->eyeTexIndex >= EYE_TEXTURES_COUNT) { + this->blinkTimer = Rand_S16Offset(30, 30); + this->eyeTexIndex = 0; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/func_80C18C50.s") +void EnAnd_HandleCutscene(EnAnd* this, PlayState* play) { + s32 csAnimations[] = { 0, 1, 2, 3, 5, 7 }; + u16 cueType; + s32 cueChannel; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/EnAnd_Init.s") + if (play->csCtx.state != CS_STATE_IDLE) { + if (!this->isCutscenePlaying) { + // Cutscene is starting + this->cueId = 255; + this->isCutscenePlaying = true; + this->prevAnimIndex = this->animIndex; + } + if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_565)) { + cueChannel = Cutscene_GetCueChannel(play, CS_CMD_ACTOR_CUE_565); + cueType = play->csCtx.actorCues[cueChannel]->id; + if (this->cueId != (u8)cueType) { + this->cueId = cueType; + EnAnd_ChangeAnim(this, csAnimations[cueType]); + } + switch (this->cueId) { + case 3: + case 4: + if ((this->animIndex == 3) || (this->animIndex == 5)) { + if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) { + EnAnd_ChangeAnim(this, this->animIndex + 1); + } + } + break; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/EnAnd_Destroy.s") + default: + break; + } + Cutscene_ActorTranslateAndYaw(&this->actor, play, cueChannel); + } + } else if (this->isCutscenePlaying) { + this->isCutscenePlaying = false; + EnAnd_ChangeAnim(this, this->prevAnimIndex); + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/EnAnd_Update.s") +void EnAnd_Init(Actor* thisx, PlayState* play) { + EnAnd* this = THIS; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/func_80C18ED0.s") + ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 14.0f); + SkelAnime_InitFlex(play, &this->skelAnime, &gAndSkel, NULL, this->jointTable, this->morphTable, + OBJECT_AND_LIMB_MAX); + this->animIndex = -1; + EnAnd_ChangeAnim(this, 0); + Actor_SetScale(&this->actor, 0.01f); + this->actor.flags &= ~ACTOR_FLAG_1; + this->flags |= 8; + this->actionFunc = EnAnd_HandleCutscene; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_And/EnAnd_Draw.s") +void EnAnd_Destroy(Actor* thisx, PlayState* play) { +} + +void EnAnd_Update(Actor* thisx, PlayState* play) { + EnAnd* this = THIS; + + this->actionFunc(this, play); + SkelAnime_Update(&this->skelAnime); + EnAnd_Blink(this); +} + +void EnAnd_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) { + EnAnd* this = THIS; + s32 stepRot; + s32 overrideRot; + + stepRot = this->flags & 8 ? false : true; + overrideRot = this->flags & 2 ? true : false; + if (!stepRot) { + overrideRot = false; + } + + switch (limbIndex) { + case OBJECT_AND_LIMB_HEAD: + SubS_UpdateLimb(this->headRotZ + this->torsoRotZ + 0x4000, + this->headRotY + this->torsoRotY + this->actor.shape.rot.y + 0x4000, &this->headComputedPos, + &this->headComputedRot, stepRot, overrideRot); + Matrix_Pop(); + Matrix_Translate(this->headComputedPos.x, this->headComputedPos.y, this->headComputedPos.z, MTXMODE_NEW); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_RotateYS(this->headComputedRot.y, MTXMODE_APPLY); + Matrix_RotateXS(this->headComputedRot.x, MTXMODE_APPLY); + Matrix_RotateZS(this->headComputedRot.z, MTXMODE_APPLY); + Matrix_Push(); + break; + + case OBJECT_AND_LIMB_TORSO: + SubS_UpdateLimb(this->torsoRotZ + 0x4000, this->torsoRotY + this->actor.shape.rot.y + 0x4000, + &this->torsoComputedPos, &this->torsoComputedRot, stepRot, overrideRot); + Matrix_Pop(); + Matrix_Translate(this->torsoComputedPos.x, this->torsoComputedPos.y, this->torsoComputedPos.z, MTXMODE_NEW); + Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY); + Matrix_RotateYS(this->torsoComputedRot.y, MTXMODE_APPLY); + Matrix_RotateXS(this->torsoComputedRot.x, MTXMODE_APPLY); + Matrix_RotateZS(this->torsoComputedRot.z, MTXMODE_APPLY); + Matrix_Push(); + break; + + default: + break; + } +} + +void EnAnd_Draw(Actor* thisx, PlayState* play) { + static TexturePtr sMouthTextures[] = { gAndMouthNeutralTex, gAndMouthSmileTex }; + static TexturePtr sEyeTextures[EYE_TEXTURES_COUNT] = { + gAndEyeOpenTex, + gAndEyeClosingTex, + gAndEyeClosedTex, + gAndEyeOpeningTex, + }; + EnAnd* this = THIS; + + OPEN_DISPS(play->state.gfxCtx); + + func_8012C28C(play->state.gfxCtx); + + gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex])); + gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sMouthTextures[0])); + + SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, + this->skelAnime.dListCount, NULL, NULL, EnAnd_TransformLimbDraw, &this->actor); + + CLOSE_DISPS(play->state.gfxCtx); +} diff --git a/src/overlays/actors/ovl_En_And/z_en_and.h b/src/overlays/actors/ovl_En_And/z_en_and.h index a0610a408..6b5a0bb7d 100644 --- a/src/overlays/actors/ovl_En_And/z_en_and.h +++ b/src/overlays/actors/ovl_En_And/z_en_and.h @@ -2,6 +2,7 @@ #define Z_EN_AND_H #include "global.h" +#include "objects/object_and/object_and.h" struct EnAnd; @@ -9,9 +10,29 @@ typedef void (*EnAndActionFunc)(struct EnAnd*, PlayState*); typedef struct EnAnd { /* 0x000 */ Actor actor; - /* 0x144 */ char unk_144[0x44]; + /* 0x144 */ SkelAnime skelAnime; /* 0x188 */ EnAndActionFunc actionFunc; - /* 0x18C */ char unk_18C[0x188]; + /* 0x18C */ u8 cueId; + /* 0x18D */ UNK_TYPE1 pad18D[0x7]; + /* 0x194 */ Vec3f headComputedPos; + /* 0x1A0 */ Vec3f torsoComputedPos; + /* 0x1AC */ Vec3s headComputedRot; + /* 0x1B2 */ Vec3s torsoComputedRot; + /* 0x1B8 */ Vec3s jointTable[OBJECT_AND_LIMB_MAX]; + /* 0x254 */ Vec3s morphTable[OBJECT_AND_LIMB_MAX]; + /* 0x2F0 */ u16 flags; + /* 0x2F2 */ UNK_TYPE1 pad2F2[0x4]; + /* 0x2F6 */ s16 headRotZ; + /* 0x2F8 */ s16 headRotY; + /* 0x2FA */ s16 torsoRotZ; + /* 0x2FC */ s16 torsoRotY; + /* 0x2FE */ UNK_TYPE1 pad2FE[0x2]; + /* 0x300 */ s16 blinkTimer; + /* 0x302 */ s16 eyeTexIndex; + /* 0x304 */ s32 animIndex; + /* 0x308 */ s32 prevAnimIndex; + /* 0x30C */ s32 isCutscenePlaying; + /* 0x310 */ UNK_TYPE1 pad310[4]; } EnAnd; // size = 0x314 #endif // Z_EN_AND_H diff --git a/src/overlays/actors/ovl_En_Ani/z_en_ani.c b/src/overlays/actors/ovl_En_Ani/z_en_ani.c index d4c980055..d978d8380 100644 --- a/src/overlays/actors/ovl_En_Ani/z_en_ani.c +++ b/src/overlays/actors/ovl_En_Ani/z_en_ani.c @@ -220,10 +220,10 @@ void EnAni_FallToGround(EnAni* this, PlayState* play) { Animation_Change(&this->skelAnime, &gAniLandingThenStandingUpAnim, 1.0f, 0.0f, 16.0f, ANIMMODE_ONCE, 0.0f); this->stateFlags |= ANI_STATE_WRITHING; - quakeIndex = Quake_Add(play->cameraPtrs[CAM_ID_MAIN], QUAKE_TYPE_3); + quakeIndex = Quake_Request(play->cameraPtrs[CAM_ID_MAIN], QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 27000); - Quake_SetQuakeValues(quakeIndex, 7, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 20); + Quake_SetPerturbations(quakeIndex, 7, 0, 0, 0); + Quake_SetDuration(quakeIndex, 20); Actor_PlaySfx(&this->actor, NA_SE_IT_HAMMER_HIT); } @@ -310,8 +310,8 @@ void EnAni_Update(Actor* thisx, PlayState* play) { } else if (CutsceneManager_IsNext(this->actor.csId)) { CutsceneManager_StartWithPlayerCs(this->actor.csId, &this->actor); this->actor.csId = CutsceneManager_GetAdditionalCsId(this->actor.csId); - Camera_SetToTrackActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->actor.csId)), - &this->actor); + Camera_SetFocalActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->actor.csId)), + &this->actor); } else { CutsceneManager_Queue(this->actor.csId); } diff --git a/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.c b/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.c index 5aa746298..45a413c26 100644 --- a/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.c +++ b/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.c @@ -12,27 +12,25 @@ #define THIS ((EnAob01*)thisx) -//! TODO: this file require macros for its uses of weekEventReg - void EnAob01_Init(Actor* thisx, PlayState* play); void EnAob01_Destroy(Actor* thisx, PlayState* play); void EnAob01_Update(Actor* thisx, PlayState* play); void EnAob01_Draw(Actor* thisx, PlayState* play); -void func_809C1C9C(EnAob01* this, PlayState* play); -void func_809C1D64(EnAob01* this, PlayState* play); -void func_809C2060(EnAob01* this, PlayState* play); -void func_809C21E0(EnAob01* this, PlayState* play); -void func_809C26E4(EnAob01* this, PlayState* play); -void func_809C2730(EnAob01* this, PlayState* play); -void func_809C2788(EnAob01* this, PlayState* play); -void func_809C2824(EnAob01* this, PlayState* play); -void func_809C28B8(EnAob01* this, PlayState* play); -void func_809C2A64(EnAob01* this, PlayState* play); -void func_809C2BE4(EnAob01* this, PlayState* play); -void func_809C2C9C(EnAob01* this, PlayState* play); -void func_809C2D0C(EnAob01* this, PlayState* play); -s32 func_809C2EC4(EnAob01* this, PlayState* play); +void EnAob01_BeforeRace_StartRace(EnAob01* this, PlayState* play); +void EnAob01_BeforeRace_RespondToPlayAgainQuestion(EnAob01* this, PlayState* play); +void EnAob01_BeforeRace_Idle(EnAob01* this, PlayState* play); +void EnAob01_BeforeRace_Talk(EnAob01* this, PlayState* play); +void EnAob01_Race_SkipNonRaceCutscene(EnAob01* this, PlayState* play); +void EnAob01_Race_HandleRaceCutscene(EnAob01* this, PlayState* play); +void EnAob01_Race_HandleRaceEndCutscene(EnAob01* this, PlayState* play); +void EnAob01_Race_StartCutscene(EnAob01* this, PlayState* play); +void EnAob01_AfterRace_GiveRaceResult(EnAob01* this, PlayState* play); +void EnAob01_AfterRace_GiveReward(EnAob01* this, PlayState* play); +void EnAob01_AfterRace_AfterGivingReward(EnAob01* this, PlayState* play); +void EnAob01_AfterRace_AskToPlayAgain(EnAob01* this, PlayState* play); +void EnAob01_AfterRace_Talk(EnAob01* this, PlayState* play); +s32 EnAob01_PlayerIsHoldingDog(EnAob01* this, PlayState* play); ActorInit En_Aob_01_InitVars = { ACTOR_EN_AOB_01, @@ -46,6 +44,22 @@ ActorInit En_Aob_01_InitVars = { (ActorFunc)EnAob01_Draw, }; +typedef enum { + /* 0 */ EN_AOB01_ANIM_IDLE_1, + /* 1 */ EN_AOB01_ANIM_LAUGH_START, + /* 2 */ EN_AOB01_ANIM_LAUGH_LOOP, + /* 3 */ EN_AOB01_ANIM_SURPRISE_START, + /* 4 */ EN_AOB01_ANIM_SURPRISE_LOOP, + /* 5 */ EN_AOB01_ANIM_IDLE_2, +} EnAob01Animation; + +typedef enum { + /* 0 */ EN_AOB01_EYE_OPEN, + /* 1 */ EN_AOB01_EYE_HALF, + /* 2 */ EN_AOB01_EYE_CLOSED, + /* 3 */ EN_AOB01_EYE_MAX, +} EnAob01EyeTexture; + static AnimationInfo sAnimationInfo[] = { { &gMamamuYanIdleAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_LOOP, 0.0f }, { &gMamamuYanLaughStartAnim, 1.0f, 0.0f, 0.0f, ANIMMODE_ONCE, 0.0f }, @@ -76,12 +90,16 @@ static ColliderCylinderInit sCylinderInit = { }; typedef struct { - Vec3f unk_00; - s16 unk_04; - s16 unk_06; -} EnAobStruct; + /* 0x0 */ Vec3f pos; + /* 0xC */ s16 rotY; + /* 0xE */ s16 pathIndex; +} DogInfo; // size = 0x10 -static EnAobStruct D_809C384C[] = { +/** + * Stores the starting position, y-rotation, and path index for all 14 dogs in the racetrack. + * This actor is responsible for spawning these dogs; they are not spawned as part of the scene. + */ +static DogInfo sDogInfo[RACEDOG_COUNT] = { { { -4130.0f, 150.0f, 1367.0f }, 84, 0 }, { { -4861.0f, 172.0f, 1606.0f }, 94, 4 }, { { -4139.0f, 155.0f, 2133.0f }, 73, 6 }, { { -4406.0f, 144.0f, 1416.0f }, 88, 2 }, { { -4156.0f, 155.0f, 1731.0f }, 42, 0 }, { { -4033.0f, 157.0f, 1994.0f }, -65, 1 }, @@ -91,105 +109,137 @@ static EnAobStruct D_809C384C[] = { { { -4827.0f, 168.0f, 1328.0f }, 115, 4 }, { { -4130.0f, 150.0f, 1367.0f }, 112, 0 }, }; -void func_809C10B0(EnAob01* this, s32 arg1) { +void EnAob01_Blink(EnAob01* this, s32 maxEyeIndex) { if (DECR(this->blinkTimer) == 0) { this->eyeIndex++; - if (this->eyeIndex >= arg1) { - this->eyeIndex = 0; + if (this->eyeIndex >= maxEyeIndex) { + this->eyeIndex = EN_AOB01_EYE_OPEN; this->blinkTimer = Rand_S16Offset(30, 30); } } } -void func_809C1124(void) { +/** + * Called every frame during the race in order to make in-game time pass. + */ +void EnAob01_AdvanceTime(void) { gSaveContext.save.time = ((void)0, gSaveContext.save.time) + (u16)R_TIME_SPEED; gSaveContext.save.time = ((void)0, gSaveContext.save.time) + (u16)((void)0, gSaveContext.save.timeSpeedOffset); } -void func_809C1158(EnAob01* this, PlayState* play) { - s32 temp_s0 = ENAOB01_GET_7E00_2(&this->actor); +/** + * Initializes all the paths that the dogs follow. + */ +void EnAob01_InitializeDogPaths(EnAob01* this, PlayState* play) { + s32 pathIndex = ENAOB01_GET_STARTING_DOG_PATH_INDEX(&this->actor); s16 i = 0; - if (temp_s0 != 0x3F) { + if (pathIndex != 0x3F) { do { - this->unk_1D8[i] = SubS_GetPathByIndex(play, temp_s0, 0x3F); - temp_s0 = this->unk_1D8[i]->unk1; + this->dogPaths[i] = SubS_GetPathByIndex(play, pathIndex, 0x3F); + pathIndex = this->dogPaths[i]->unk1; i++; - } while (temp_s0 != 0xFF); + } while (pathIndex != 0xFF); } } -void func_809C11EC(EnAob01* this, PlayState* play) { +/** + * Spawns the dogs that mill about the racetrack before and after each race. + */ +void EnAob01_SpawnDogs(EnAob01* this, PlayState* play) { s32 enDgParams; s16 i; - func_809C1158(this, play); + EnAob01_InitializeDogPaths(this, play); - for (i = 0; i < ARRAY_COUNT(D_809C384C); i++) { - enDgParams = ENDG_PARAMS(this->unk_1D8[D_809C384C[i].unk_06]->unk1, i); + for (i = 0; i < RACEDOG_COUNT; i++) { + enDgParams = ENDG_PARAMS(this->dogPaths[sDogInfo[i].pathIndex]->unk1, i); - this->unk_3F8[i] = Actor_SpawnAsChildAndCutscene( - &play->actorCtx, play, ACTOR_EN_DG, D_809C384C[i].unk_00.x, D_809C384C[i].unk_00.y, D_809C384C[i].unk_00.z, - 0, DEG_TO_BINANG(D_809C384C[i].unk_04), 0, enDgParams, (u16)CS_ID_NONE, this->actor.halfDaysBits, NULL); + this->dogs[i] = Actor_SpawnAsChildAndCutscene( + &play->actorCtx, play, ACTOR_EN_DG, sDogInfo[i].pos.x, sDogInfo[i].pos.y, sDogInfo[i].pos.z, 0, + DEG_TO_BINANG(sDogInfo[i].rotY), 0, enDgParams, (u16)CS_ID_NONE, this->actor.halfDaysBits, NULL); } } -void func_809C1304(EnAob01* this, PlayState* play) { +/** + * Spawns the dogs that run around the track during each race. + */ +void EnAob01_SpawnRacedogs(EnAob01* this, PlayState* play) { s16 i; - for (i = 0; i < ARRAY_COUNT(this->unk_3F8); i++) { - this->unk_3F8[i] = Actor_SpawnAsChildAndCutscene( - &play->actorCtx, play, ACTOR_EN_RACEDOG, (i * 15.0f) + -3897.0f, 130.0f, 1290.0f - (i * 10.0f), 0, 0x1555, - 0, (i << 5) | ENAOB01_GET_7E00_1(&this->actor), (u16)CS_ID_NONE, this->actor.halfDaysBits, NULL); + for (i = 0; i < RACEDOG_COUNT; i++) { + this->dogs[i] = Actor_SpawnAsChildAndCutscene(&play->actorCtx, play, ACTOR_EN_RACEDOG, (i * 15.0f) + -3897.0f, + 130.0f, 1290.0f - (i * 10.0f), 0, 0x1555, 0, + ENRACEDOG_PARAMS(i, ENAOB01_GET_RACEDOG_PATH_INDEX(&this->actor)), + (u16)CS_ID_NONE, this->actor.halfDaysBits, NULL); } } -s32 func_809C1424(EnAob01* this) { +/** + * If the racetrack owner is at the end of her laugh start animation, this function will + * transition her to her laugh loop animation. This function will return true if she is + * *either* in her laugh start or laugh loop animation, false otherwise. + */ +s32 EnAob01_ProcessLaughAnim(EnAob01* this) { s16 curFrame = this->skelAnime.curFrame; - s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->unk_43C].animation); + s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animIndex].animation); - if (this->unk_43C == 1) { + if (this->animIndex == EN_AOB01_ANIM_LAUGH_START) { if (curFrame == lastFrame) { - this->unk_43C = 2; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 2); + this->animIndex = EN_AOB01_ANIM_LAUGH_LOOP; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_LOOP); return true; } - } else if (this->unk_43C == 2) { + } else if (this->animIndex == EN_AOB01_ANIM_LAUGH_LOOP) { return true; } + return false; } -s32 func_809C14D0(EnAob01* this) { +/** + * If the racetrack owner is at the end of her idle animation, this function will + * transition her to her surprise start animation. If the racetrack owner is at the + * end of her surprise start animation, this function will transition her to her + * surprise loop animation. This function will return true if she is *either* in + * her surprise start or surprise loop animation, false otherwise. + */ +s32 EnAob01_ProcessSurpriseAnim(EnAob01* this) { s16 curFrame = this->skelAnime.curFrame; - s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->unk_43C].animation); + s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animIndex].animation); - if ((this->unk_43C == 0) || (this->unk_43C == 5)) { + if ((this->animIndex == EN_AOB01_ANIM_IDLE_1) || (this->animIndex == EN_AOB01_ANIM_IDLE_2)) { if (curFrame == lastFrame) { - this->unk_43C = 3; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 3); + this->animIndex = EN_AOB01_ANIM_SURPRISE_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_SURPRISE_START); return true; } - } else if (this->unk_43C == 3) { + } else if (this->animIndex == EN_AOB01_ANIM_SURPRISE_START) { if (curFrame == lastFrame) { - this->unk_43C = 4; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 4); + this->animIndex = EN_AOB01_ANIM_SURPRISE_LOOP; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_SURPRISE_LOOP); return true; } - } else if (this->unk_43C == 4) { + } else if (this->animIndex == EN_AOB01_ANIM_SURPRISE_LOOP) { return true; } + return false; } -s32 func_809C15BC(EnAob01* this) { +/** + * If the racetrack owner is at the end of her current animation, this function will + * transition her to her the idle animation. This function will return true if she is + * in her idle animation, false otherwise. + */ +s32 EnAob01_ProcessIdleAnim(EnAob01* this) { s16 curFrame = this->skelAnime.curFrame; - s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->unk_43C].animation); + s16 lastFrame = Animation_GetLastFrame(sAnimationInfo[this->animIndex].animation); - if ((this->unk_43C != 0) && (this->unk_43C != 5)) { + if ((this->animIndex != EN_AOB01_ANIM_IDLE_1) && (this->animIndex != EN_AOB01_ANIM_IDLE_2)) { if (curFrame == lastFrame) { - this->unk_43C = 5; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 5); + this->animIndex = EN_AOB01_ANIM_IDLE_2; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_IDLE_2); return true; } } else { @@ -199,7 +249,7 @@ s32 func_809C15BC(EnAob01* this) { return false; } -void func_809C165C(EnAob01* this, PlayState* play) { +void EnAob01_UpdateCollision(EnAob01* this, PlayState* play) { this->collider.dim.pos.x = this->actor.world.pos.x; this->collider.dim.pos.y = this->actor.world.pos.y; this->collider.dim.pos.z = this->actor.world.pos.z; @@ -207,227 +257,238 @@ void func_809C165C(EnAob01* this, PlayState* play) { CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base); } -void func_809C16DC(EnAob01* this, PlayState* play) { +/** + * Handles all parts of the conversation with the racetrack owner before the race begins. + */ +void EnAob01_BeforeRace_HandleConversation(EnAob01* this, PlayState* play) { Player* player = GET_PLAYER(play); - switch (this->unk_210) { + switch (this->textId) { case 0: - case 0x3524: - case 0x3535: - case 0x3548: - case 0x3549: - case 0x354A: + case 0x3524: // You can't play if you can't pay! + case 0x3535: // Really? + case 0x3548: // I can't let you play. (Goron) + case 0x3549: // I can't let you play. (Zora) + case 0x354A: // I can't let you play. (Deku) switch (gSaveContext.save.day) { case 1: if (!gSaveContext.save.isNight) { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_64_80)) { - SET_WEEKEVENTREG(WEEKEVENTREG_64_80); - this->unk_210 = 0x3520; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_1)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_1); + this->textId = 0x3520; // This is the Doggy Racetrack. (Day 1) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } else { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_65_01)) { - SET_WEEKEVENTREG(WEEKEVENTREG_65_01); - this->unk_210 = 0x3530; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_1)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_1); + this->textId = 0x3530; // This is the Doggy Racetrack. (Night 1) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } break; case 2: if (!gSaveContext.save.isNight) { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_65_02)) { - SET_WEEKEVENTREG(WEEKEVENTREG_65_02); - this->unk_210 = 0x3531; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_2)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_2); + this->textId = 0x3531; // This is the Doggy Racetrack. (Day 2) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } else { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_65_04)) { - SET_WEEKEVENTREG(WEEKEVENTREG_65_04); - this->unk_210 = 0x3532; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_2)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_2); + this->textId = 0x3532; // This is the Doggy Racetrack. (Night 2) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } break; case 3: if (!gSaveContext.save.isNight) { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_65_08)) { - SET_WEEKEVENTREG(WEEKEVENTREG_65_08); - this->unk_210 = 0x3533; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_3)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_3); + this->textId = 0x3533; // This is the Doggy Racetrack. (Day 3) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } else { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_65_10)) { - SET_WEEKEVENTREG(WEEKEVENTREG_65_10); - this->unk_210 = 0x3534; + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_3)) { + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_3); + this->textId = 0x3534; // This is the Doggy Racetrack. (Night 3) } else { - this->unk_210 = 0x352F; + this->textId = 0x352F; // What do you want? } } break; } break; - case 0x3520: - case 0x352F: - case 0x3530: - case 0x3531: - case 0x3532: - case 0x3533: - case 0x3534: - this->unk_210 = 0x3521; + case 0x3520: // This is the Doggy Racetrack. (Day 1) + case 0x352F: // What do you want? + case 0x3530: // This is the Doggy Racetrack. (Night 1) + case 0x3531: // This is the Doggy Racetrack. (Day 2) + case 0x3532: // This is the Doggy Racetrack. (Night 2) + case 0x3533: // This is the Doggy Racetrack. (Day 3) + case 0x3534: // This is the Doggy Racetrack. (Night 3) + this->textId = 0x3521; // Do you want to try the dog race? break; - case 0x3521: - if (this->unk_2D2 & 2) { - this->unk_2D2 &= ~2; + case 0x3521: // Do you want to try the dog race? + if (this->stateFlags & ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE) { + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE; switch (player->transformation) { case PLAYER_FORM_GORON: - this->unk_210 = 0x3548; - this->unk_2D2 |= 0x10; + this->textId = 0x3548; // I can't let you play. (Goron) + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; break; case PLAYER_FORM_ZORA: - this->unk_210 = 0x3549; - this->unk_2D2 |= 0x10; + this->textId = 0x3549; // I can't let you play. (Zora) + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; break; case PLAYER_FORM_DEKU: - this->unk_210 = 0x354A; - this->unk_2D2 |= 0x10; + this->textId = 0x354A; // I can't let you play. (Deku) + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; break; case PLAYER_FORM_HUMAN: if (gSaveContext.save.saveInfo.playerData.rupees < 10) { - this->unk_210 = 0x3524; - this->unk_2D2 |= 0x10; + this->textId = 0x3524; // You can't play if you can't pay! + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; } else { - this->unk_210 = 0x3522; - this->unk_2D2 |= 4; - this->unk_2D2 |= 0x10; + this->textId = 0x3522; // Bring me the fastest dog! + this->stateFlags |= ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; } } } else { - this->unk_2D2 |= 0x10; - this->unk_210 = 0x3535; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->textId = 0x3535; // Is that dog fine? } break; - case 0x3522: - case 0x3523: - if (this->unk_2D2 & 8) { - this->unk_210 = 0x3525; + case 0x3522: // Bring me the fastest dog! + case 0x3523: // Hurry up and bring me a dog! + if (this->stateFlags & ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG) { + this->textId = 0x3525; // Is that dog okay? break; } - this->unk_210 = 0x3523; - this->unk_2D2 |= 0x40; - this->unk_2D2 |= 0x10; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + this->textId = 0x3523; // Hurry up and bring me a dog! + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; - case 0x3525: - case 0x3526: - if (this->unk_2D2 & 4) { - if (this->unk_2D2 & 8) { - this->unk_210 = 0x3525; + case 0x3525: // Is that dog okay? + case 0x3526: // Don't wait! Hurry up and choose! + if (this->stateFlags & ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG) { + if (this->stateFlags & ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG) { + this->textId = 0x3525; // Is that dog okay? break; } - this->unk_210 = 0x3523; - this->unk_2D2 |= 0x40; - this->unk_2D2 |= 0x10; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + this->textId = 0x3523; // Hurry up and bring me a dog! + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; } - if (this->unk_2D2 & 2) { - this->unk_2D2 &= ~2; - this->unk_210 = 0x3527; + if (this->stateFlags & ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE) { + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE; + this->textId = 0x3527; // If you win, you'll get more than you bet. break; } - this->unk_210 = 0x3526; - this->unk_2D2 |= 0x40; - this->unk_2D2 |= 4; - this->unk_2D2 |= 0x10; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + this->textId = 0x3526; // Don't wait! Hurry up and choose! + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->stateFlags |= ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; - case 0x3527: - this->unk_210 = 0x3528; + case 0x3527: // If you win, you'll get more than you bet. + this->textId = 0x3528; // How much will you bet? break; - case 0x3528: - if (gSaveContext.save.saveInfo.playerData.rupees < this->unk_434) { - this->unk_210 = 0x3536; - this->unk_2D2 |= 0x40; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + case 0x3528: // How much will you bet? + if (gSaveContext.save.saveInfo.playerData.rupees < this->rupeesBet) { + this->textId = 0x3536; // You don't have enough rupees for that bet. + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; } - if (this->unk_434 == 0) { - this->unk_210 = 0x3537; - this->unk_2D2 |= 0x40; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + if (this->rupeesBet == 0) { + this->textId = 0x3537; // You can't race if you don't bet. + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; } - gSaveContext.unk_3F5C = this->unk_434; - play->msgCtx.bankRupees = this->unk_434; - this->unk_210 = 0x3529; + gSaveContext.unk_3F5C = this->rupeesBet; + play->msgCtx.bankRupees = this->rupeesBet; + this->textId = 0x3529; // Is that bet okay? break; - case 0x3529: - if (this->unk_2D2 & 2) { - this->unk_2D2 &= ~2; - Rupees_ChangeBy(-this->unk_434); + case 0x3529: // Is that bet okay? + if (this->stateFlags & ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE) { + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE; + Rupees_ChangeBy(-this->rupeesBet); func_800B7298(play, NULL, PLAYER_CSMODE_WAIT); play->msgCtx.msgMode = 0x43; play->msgCtx.stateTimer = 4; - this->actionFunc = func_809C1C9C; + this->actionFunc = EnAob01_BeforeRace_StartRace; return; } - this->unk_210 = 0x3528; + this->textId = 0x3528; // How much will you bet? break; - case 0x3536: - case 0x3537: - this->unk_210 = 0x3528; + case 0x3536: // You don't have enough rupees for that bet. + case 0x3537: // You can't race if you don't bet. + this->textId = 0x3528; // How much will you bet? break; } - Message_StartTextbox(play, this->unk_210, &this->actor); + Message_StartTextbox(play, this->textId, &this->actor); } -void func_809C1C9C(EnAob01* this, PlayState* play) { +/** + * Once the player's rupees are done counting down, this function will + * reload the racetrack to start the race. + */ +void EnAob01_BeforeRace_StartRace(EnAob01* this, PlayState* play) { if (gSaveContext.rupeeAccumulator == 0) { SET_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_WAIT); CLEAR_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_TIME_PASSED); - this->unk_2D2 |= 0x20; - func_800FD750(0x40); + this->stateFlags |= ENAOB01_FLAG_STARTED_RACE; + func_800FD750(NA_BGM_HORSE); play->nextEntrance = ENTRANCE(DOGGY_RACETRACK, 1); play->transitionType = TRANS_TYPE_64; gSaveContext.nextTransitionType = TRANS_TYPE_64; - gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & (u8)~7) | 2; - gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & 7) | (this->unk_432 * 8); + SET_EVENTINF_DOG_RACE_STATE(EVENTINF_DOG_RACE_STATE_STARTED); + SET_EVENTINF_DOG_RACE_SELECTED_DOG_INDEX(this->selectedDogIndex); play->transitionTrigger = TRANS_TRIGGER_START; } } -void func_809C1D64(EnAob01* this, PlayState* play) { +/** + * Handles the player's response to the question of whether or not they want to play again. + * Once the textbox closes, the racetrack owner will go back to being idle. + */ +void EnAob01_BeforeRace_RespondToPlayAgainQuestion(EnAob01* this, PlayState* play) { u8 talkState = Message_GetState(&play->msgCtx); if (talkState == TEXT_STATE_CHOICE) { @@ -436,34 +497,38 @@ void func_809C1D64(EnAob01* this, PlayState* play) { case 0: if (gSaveContext.save.saveInfo.playerData.rupees < 10) { play_sound(NA_SE_SY_ERROR); - this->unk_210 = 0x3524; - Message_StartTextbox(play, this->unk_210, &this->actor); + this->textId = 0x3524; // You can't play if you can't pay! + Message_StartTextbox(play, this->textId, &this->actor); } else { func_8019F208(); - this->unk_2D2 |= 4; - this->unk_2D2 |= 0x10; - this->unk_210 = 0x3522; - Message_StartTextbox(play, this->unk_210, &this->actor); - this->actionFunc = func_809C21E0; + this->stateFlags |= ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG; + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->textId = 0x3522; // Bring me the fastest dog! + Message_StartTextbox(play, this->textId, &this->actor); + this->actionFunc = EnAob01_BeforeRace_Talk; } break; case 1: func_8019F230(); - this->unk_210 = 0x3535; - Message_StartTextbox(play, this->unk_210, &this->actor); + this->textId = 0x3535; // Really? + Message_StartTextbox(play, this->textId, &this->actor); break; } } } else if ((talkState == TEXT_STATE_5) && Message_ShouldAdvance(play)) { play->msgCtx.msgMode = 0x43; play->msgCtx.stateTimer = 4; - this->unk_210 = 0; - this->actionFunc = func_809C2060; + this->textId = 0; + this->actionFunc = EnAob01_BeforeRace_Idle; } } -void func_809C1EC8(EnAob01* this, PlayState* play) { +/** + * Handles various things that are common to all action functions, like tracking the + * player, blinking, handling collision, etc. + */ +void EnAob01_UpdateCommon(EnAob01* this, PlayState* play) { static TrackOptionsSet sTrackOptions = { { 0xFA0, 4, 1, 3 }, { 0x1770, 4, 1, 6 }, @@ -474,6 +539,7 @@ void func_809C1EC8(EnAob01* this, PlayState* play) { Vec3f point; SkelAnime_Update(&this->skelAnime); + if (SubS_AngleDiffLessEqual(this->actor.shape.rot.y, 0x36B0, this->actor.yawTowardsPlayer)) { point.x = player->actor.world.pos.x; point.y = player->bodyPartsPos[PLAYER_BODYPART_HEAD].y + 3.0f; @@ -488,124 +554,152 @@ void func_809C1EC8(EnAob01* this, PlayState* play) { Math_SmoothStepToS(&this->torsoRot.x, 0, 4, 0x3E8, 1); Math_SmoothStepToS(&this->torsoRot.y, 0, 4, 0x3E8, 1); } - func_809C10B0(this, 3); - SubS_FillLimbRotTables(play, this->unk_2F8, this->unk_318, ARRAY_COUNT(this->unk_2F8)); - func_809C165C(this, play); + + EnAob01_Blink(this, EN_AOB01_EYE_MAX); + SubS_FillLimbRotTables(play, this->limbRotTableY, this->limbRotTableZ, ARRAY_COUNT(this->limbRotTableY)); + EnAob01_UpdateCollision(this, play); + + // This specific code ensures that in-game time passes during the race. if (player->stateFlags1 & PLAYER_STATE1_20) { - func_809C1124(); + EnAob01_AdvanceTime(); } } -void func_809C2060(EnAob01* this, PlayState* play) { - if (func_809C15BC(this)) { - if (func_809C2EC4(this, play) && !(this->unk_2D2 & 0x100)) { +/** + * Stand around and wait until either the player talks to the racetrack owner or until + * the player bumps into them while holding a dog. In either case, the racetrack owner + * will then start talking with the player. + */ +void EnAob01_BeforeRace_Idle(EnAob01* this, PlayState* play) { + if (EnAob01_ProcessIdleAnim(this)) { + if (EnAob01_PlayerIsHoldingDog(this, play) && !(this->stateFlags & ENAOB01_FLAG_PLAYER_CAN_TALK)) { if (this->collider.base.ocFlags2 & OC2_HIT_PLAYER) { this->actor.flags |= ACTOR_FLAG_10000; func_800B8614(&this->actor, play, 100.0f); - this->unk_2D2 |= 8; - this->actionFunc = func_809C21E0; + this->stateFlags |= ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG; + this->actionFunc = EnAob01_BeforeRace_Talk; } - } else if (Actor_ProcessTalkRequest(&this->actor, &play->state) && (this->unk_2D2 & 0x100)) { - this->unk_2D2 &= ~0x100; - this->unk_2E6 = this->trackTarget; - this->unk_2EC = this->headRot; - this->unk_2F2 = this->torsoRot; - func_809C16DC(this, play); - this->actionFunc = func_809C21E0; + } else if (Actor_ProcessTalkRequest(&this->actor, &play->state) && + (this->stateFlags & ENAOB01_FLAG_PLAYER_CAN_TALK)) { + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_CAN_TALK; + this->prevTrackTarget = this->trackTarget; + this->prevHeadRot = this->headRot; + this->prevTorsoRot = this->torsoRot; + EnAob01_BeforeRace_HandleConversation(this, play); + this->actionFunc = EnAob01_BeforeRace_Talk; } else { - this->unk_2D2 &= ~0x100; + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_CAN_TALK; if ((this->actor.xzDistToPlayer < 100.0f) && !(this->collider.base.ocFlags2 & OC2_HIT_PLAYER)) { - this->unk_2D2 |= 0x100; + this->stateFlags |= ENAOB01_FLAG_PLAYER_CAN_TALK; func_800B8614(&this->actor, play, 100.0f); } } } } -void func_809C21E0(EnAob01* this, PlayState* play) { +/** + * Handles the actual action of talking with the player before the race begins. + */ +void EnAob01_BeforeRace_Talk(EnAob01* this, PlayState* play) { u8 talkState = Message_GetState(&play->msgCtx); Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 4, 4000, 1); - if ((this->unk_2D2 & 8) && !func_809C2EC4(this, play)) { - if ((this->unk_210 != 0) && (this->unk_210 != 0x3535) && (this->unk_210 != 0x3524) && - (this->unk_210 != 0x3548) && (this->unk_210 != 0x3549) && (this->unk_210 != 0x354A)) { - this->unk_210 = 0x3523; + //! @bug: This block of code acts as a failsafe for when the player triggered this conversation by + //! bumping into the racetrack owner while holding the dog and, at the same time, threw or dropped + //! the dog frame-perfectly by pressing A. In this case, the code successfully returns the racetrack + //! owner to her idle state. Unfortunately, the player can also drop the dog by shielding. If this + //! shield drop is done frame-perfectly, then the below code will not function properly and will + //! instead softlock the game. + if ((this->stateFlags & ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG) && !EnAob01_PlayerIsHoldingDog(this, play)) { + if ((this->textId != 0) && (this->textId != 0x3535) && (this->textId != 0x3524) && (this->textId != 0x3548) && + (this->textId != 0x3549) && (this->textId != 0x354A)) { + this->textId = 0x3523; // Hurry up and bring me a dog! } + this->actor.textId = 0; - this->unk_2D2 &= ~8; + this->stateFlags &= ~ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG; this->actor.flags &= ~ACTOR_FLAG_10000; - this->actionFunc = func_809C2060; + this->actionFunc = EnAob01_BeforeRace_Idle; return; } - if (this->unk_2D2 & 0x40) { - if (!func_809C1424(this)) { + if (this->stateFlags & ENAOB01_FLAG_LAUGH) { + if (!EnAob01_ProcessLaughAnim(this)) { return; } - } else if (!func_809C15BC(this)) { + } else if (!EnAob01_ProcessIdleAnim(this)) { return; } - if (this->unk_2D2 & 8) { + if (this->stateFlags & ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG) { if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { this->actor.flags &= ~ACTOR_FLAG_10000; func_80123E90(play, &this->actor); - if (this->unk_2D2 & 4) { - func_809C16DC(this, play); - this->unk_2D2 &= ~4; + if (this->stateFlags & ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG) { + EnAob01_BeforeRace_HandleConversation(this, play); + this->stateFlags &= ~ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG; } else { - this->unk_2D2 |= 0x10; - this->unk_2D2 |= 0x40; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + this->stateFlags |= ENAOB01_FLAG_CONVERSATION_OVER; + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); + // Put my dog down! Message_StartTextbox(play, 0x354B, &this->actor); } - this->unk_2D2 &= ~8; + + this->stateFlags &= ~ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG; } } else if (talkState == TEXT_STATE_CHOICE) { if (Message_ShouldAdvance(play)) { - this->unk_2D2 &= ~0x40; + this->stateFlags &= ~ENAOB01_FLAG_LAUGH; switch (play->msgCtx.choiceIndex) { case 0: func_8019F208(); - this->unk_2D2 |= 2; - func_809C16DC(this, play); + this->stateFlags |= ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE; + EnAob01_BeforeRace_HandleConversation(this, play); break; case 1: func_8019F230(); - func_809C16DC(this, play); + EnAob01_BeforeRace_HandleConversation(this, play); break; } } } else if (talkState == TEXT_STATE_5) { if (Message_ShouldAdvance(play)) { - this->unk_2D2 &= ~0x40; - if (this->unk_2D2 & 0x10) { - this->unk_2D2 &= ~0x10; + this->stateFlags &= ~ENAOB01_FLAG_LAUGH; + if (this->stateFlags & ENAOB01_FLAG_CONVERSATION_OVER) { + this->stateFlags &= ~ENAOB01_FLAG_CONVERSATION_OVER; play->msgCtx.msgMode = 0x43; play->msgCtx.stateTimer = 4; - this->actionFunc = func_809C2060; + this->actionFunc = EnAob01_BeforeRace_Idle; } else { - func_809C16DC(this, play); + EnAob01_BeforeRace_HandleConversation(this, play); } } } else if ((talkState == TEXT_STATE_14) && Message_ShouldAdvance(play)) { - this->unk_2D2 &= ~0x40; - this->unk_434 = play->msgCtx.bankRupeesSelected; - func_809C16DC(this, play); + this->stateFlags &= ~ENAOB01_FLAG_LAUGH; + this->rupeesBet = play->msgCtx.bankRupeesSelected; + EnAob01_BeforeRace_HandleConversation(this, play); } } -s32 func_809C2504(EnAob01* this, PlayState* play) { +/** + * Checks all dog instances to see if any of them have reached a certain point along the racetrack, + * as specified by the cutscene's custom value. Once one of them has reached that point, this function + * will switch to following that dog and set the csId to correspond to the next cutscene in the race + * sequence; this usually appears to the user as a cut to a different camera angle. Returns true if any + * dog has reached the specified point, false otherwise. + */ +s32 EnAob01_Race_DogHasReachedNextCutsceneTrigger(EnAob01* this, PlayState* play) { Actor* npc = play->actorCtx.actorLists[ACTORCAT_NPC].first; while (npc != NULL) { if ((npc->id == ACTOR_EN_RACEDOG) && (CutsceneManager_GetCutsceneCustomValue(this->csId) == ((EnRacedog*)npc)->currentPoint)) { CutsceneManager_Stop(this->csId); - this->unk_3F4 = npc; + this->dogToFollow = npc; this->csId = CutsceneManager_GetAdditionalCsId(this->csId); return true; } @@ -615,12 +709,17 @@ s32 func_809C2504(EnAob01* this, PlayState* play) { return false; } -s32 func_809C2594(EnAob01* this, PlayState* play) { +/** + * Finds the dog that the player selected and starts following it. Returns true if it finds the player's + * selected dog and false otherwise, though nothing actually cares about this return value, and it should + * always be true in normal function (it is impossible to start a race without selecting a dog). + */ +s32 EnAob01_Race_FollowSelectedDog(EnAob01* this, PlayState* play) { Actor* npc = play->actorCtx.actorLists[ACTORCAT_NPC].first; while (npc != NULL) { if ((npc->id == ACTOR_EN_RACEDOG) && (((EnRacedog*)npc)->index == ((EnRacedog*)npc)->selectedDogIndex)) { - this->unk_3F4 = npc; + this->dogToFollow = npc; return true; } npc = npc->next; @@ -629,28 +728,41 @@ s32 func_809C2594(EnAob01* this, PlayState* play) { return false; } -s32 func_809C25E4(EnAob01* this, PlayState* play) { +/** + * Returns true if the race should be ended, which can happen in either of the following circumstances: + * - All `RACEDOG_COUNT` dogs have finished the race. + * - At least 10 dogs have finished the race, and at least 500 frames have passed since the 10th place + * dog finished. This is controlled by the forceRaceEndTimer, which is set in EnAob01_Init. + */ +s32 EnAob01_Race_IsRaceOver(EnAob01* this, PlayState* play) { Actor* npc = play->actorCtx.actorLists[ACTORCAT_NPC].first; - s16 count = 0; + s16 finishedCount = 0; while (npc != NULL) { if ((npc->id == ACTOR_EN_RACEDOG) && (((EnRacedog*)npc)->raceStatus == RACEDOG_RACE_STATUS_FINISHED)) { - count++; + finishedCount++; } npc = npc->next; } - if (count >= 14) { + if (finishedCount >= RACEDOG_COUNT) { return true; } - if ((count >= 10) && (DECR(this->unk_440) == 0)) { + if ((finishedCount >= 10) && (DECR(this->forceRaceEndTimer) == 0)) { return true; } + return false; } -s32 func_809C2680(EnAob01* this) { +/** + * If the current cutscene has a positive length, and if the current cutscene is over (in other words, + * if the length has elapsed), this function will set the csId to the next cutscene in the race sequence + * and return true. In all other cases, it will return false. Note that *all* of the race cutscenes have + * a length of -1, so in practice, this function never does anything and always returns false. + */ +s32 EnAob01_Race_CurrentCutsceneHasEnded(EnAob01* this) { if ((CutsceneManager_GetLength(this->csId) > 0) && (CutsceneManager_GetCurrentCsId() != this->csId)) { this->csId = CutsceneManager_GetAdditionalCsId(this->csId); return true; @@ -658,25 +770,40 @@ s32 func_809C2680(EnAob01* this) { return false; } -void func_809C26E4(EnAob01* this, PlayState* play) { +/** + * The only way we end up inside this function is if we tried to start a cutscene with a custom + * value of 255. This does not correspond to a point on the racetrack, nor is it the special value + * of 99, which is used to signal the race ending cutscene. Thus, whatever cutscene we're trying + * to play here is almost certainly not a race cutscene, so this function just skips it and tries + * to play the next cutscene. + */ +void EnAob01_Race_SkipNonRaceCutscene(EnAob01* this, PlayState* play) { CutsceneManager_Stop(this->csId); this->csId = CutsceneManager_GetAdditionalCsId(this->csId); - this->actionFunc = func_809C2824; + this->actionFunc = EnAob01_Race_StartCutscene; } -void func_809C2730(EnAob01* this, PlayState* play) { - if (func_809C2504(this, play) || func_809C2680(this)) { +/** + * Wait around doing nothing until the next cutscene is triggered (in practice, this only happens + * when a dog reaches the next cutscene trigger), at which point we queue up the next cutscene. + */ +void EnAob01_Race_HandleRaceCutscene(EnAob01* this, PlayState* play) { + if (EnAob01_Race_DogHasReachedNextCutsceneTrigger(this, play) || EnAob01_Race_CurrentCutsceneHasEnded(this)) { CutsceneManager_Queue(this->csId); - this->actionFunc = func_809C2824; + this->actionFunc = EnAob01_Race_StartCutscene; } } -void func_809C2788(EnAob01* this, PlayState* play) { - this->unk_2D2 |= 0x20; - if (func_809C25E4(this, play)) { +/** + * Waits until the race is over, then reloads the racetrack to return it + * to its regular playable state. + */ +void EnAob01_Race_HandleRaceEndCutscene(EnAob01* this, PlayState* play) { + this->stateFlags |= ENAOB01_FLAG_STARTED_RACE; + if (EnAob01_Race_IsRaceOver(this, play)) { if (AudioSeq_GetActiveSeqId(SEQ_PLAYER_BGM_MAIN) != NA_BGM_HORSE_GOAL) { play->nextEntrance = ENTRANCE(DOGGY_RACETRACK, 1); - gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & (u8)~7) | 3; + SET_EVENTINF_DOG_RACE_STATE(EVENTINF_DOG_RACE_STATE_ENDED); play->transitionType = TRANS_TYPE_64; gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; play->transitionTrigger = TRANS_TRIGGER_START; @@ -684,93 +811,109 @@ void func_809C2788(EnAob01* this, PlayState* play) { } } -void func_809C2824(EnAob01* this, PlayState* play) { +/** + * Starts the cutscene specified by the csId and switches to an appropriate + * action function based on the cutscene's custom value. + */ +void EnAob01_Race_StartCutscene(EnAob01* this, PlayState* play) { if (CutsceneManager_IsNext(this->csId)) { - CutsceneManager_Start(this->csId, this->unk_3F4); + CutsceneManager_Start(this->csId, this->dogToFollow); switch (CutsceneManager_GetCutsceneCustomValue(this->csId)) { case 255: - this->actionFunc = func_809C26E4; + this->actionFunc = EnAob01_Race_SkipNonRaceCutscene; break; case 99: - this->actionFunc = func_809C2788; + this->actionFunc = EnAob01_Race_HandleRaceEndCutscene; break; default: - this->actionFunc = func_809C2730; + this->actionFunc = EnAob01_Race_HandleRaceCutscene; } } else { CutsceneManager_Queue(this->csId); } } -void func_809C28B8(EnAob01* this, PlayState* play) { +/** + * Tells the player how their selected dog did in the race and gives the player + * rupees depending on their performance. If their dog placed 1st, they will + * receive triple the rupees they bet. If their dog places 2nd, they will receive + * double the rupees they bet. If their dog places 3rd through 5th, they will + * receive the same number of rupees they bet. + */ +void EnAob01_AfterRace_GiveRaceResult(EnAob01* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { this->actor.flags &= ~ACTOR_FLAG_10000; func_80123E90(play, &this->actor); - this->unk_434 = gSaveContext.unk_3F5C; - switch ((gSaveContext.eventInf[0] & 0xF8) >> 3) { + this->rupeesBet = gSaveContext.unk_3F5C; + switch (GET_EVENTINF_DOG_RACE_RACE_STANDING) { case 1: - this->unk_210 = 0x352A; - this->unk_2D2 |= 0x80; - this->unk_434 *= 3; - Rupees_ChangeBy(this->unk_434); - play->msgCtx.bankRupees = this->unk_434; + this->textId = 0x352A; // You took 1st place! + this->stateFlags |= ENAOB01_FLAG_SURPRISE; + this->rupeesBet *= 3; + Rupees_ChangeBy(this->rupeesBet); + play->msgCtx.bankRupees = this->rupeesBet; break; case 2: - this->unk_210 = 0x352B; - this->unk_2D2 |= 0x80; - this->unk_434 *= 2; - Rupees_ChangeBy(this->unk_434); - play->msgCtx.bankRupees = this->unk_434; + this->textId = 0x352B; // You took 2nd place! + this->stateFlags |= ENAOB01_FLAG_SURPRISE; + this->rupeesBet *= 2; + Rupees_ChangeBy(this->rupeesBet); + play->msgCtx.bankRupees = this->rupeesBet; break; case 3: case 4: case 5: - this->unk_210 = 0x352C; - Rupees_ChangeBy(this->unk_434); + this->textId = 0x352C; // I'll give you back what you bet. + Rupees_ChangeBy(this->rupeesBet); break; default: - this->unk_210 = 0x352D; - this->unk_2D2 |= 0x40; - this->unk_43C = 1; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); + this->textId = 0x352D; // Bad choice! + this->stateFlags |= ENAOB01_FLAG_LAUGH; + this->animIndex = EN_AOB01_ANIM_LAUGH_START; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_LAUGH_START); break; } - Message_StartTextbox(play, this->unk_210, &this->actor); - this->actionFunc = func_809C2D0C; + Message_StartTextbox(play, this->textId, &this->actor); + this->actionFunc = EnAob01_AfterRace_Talk; } else if (this->actor.xzDistToPlayer < 100.0f) { func_800B8614(&this->actor, play, 100.0f); } } -void func_809C2A64(EnAob01* this, PlayState* play) { +/** + * Gives the player the reward for winning 150 or more rupees from the dog race. The first + * time this happens, the player will receive a Heart Piece; any other time, they will + * instead receive a Red Rupee. + */ +void EnAob01_AfterRace_GiveReward(EnAob01* this, PlayState* play) { u8 talkState = Message_GetState(&play->msgCtx); - if (func_809C15BC(this)) { + if (EnAob01_ProcessIdleAnim(this)) { if ((talkState == TEXT_STATE_5) && Message_ShouldAdvance(play)) { - this->unk_434 = 0; + this->rupeesBet = 0; play->msgCtx.msgMode = 0x43; play->msgCtx.stateTimer = 4; } if (Actor_HasParent(&this->actor, play)) { - this->trackTarget = this->unk_2E6; - this->headRot = this->unk_2EC; - this->torsoRot = this->unk_2F2; + this->trackTarget = this->prevTrackTarget; + this->headRot = this->prevHeadRot; + this->torsoRot = this->prevTorsoRot; this->actor.parent = NULL; this->actor.shape.rot.y = this->actor.world.rot.y; - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_08_20)) { - this->actionFunc = func_809C2BE4; + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE)) { + this->actionFunc = EnAob01_AfterRace_AfterGivingReward; } else { - SET_WEEKEVENTREG(WEEKEVENTREG_08_20); - this->actionFunc = func_809C2BE4; + SET_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE); + this->actionFunc = EnAob01_AfterRace_AfterGivingReward; } - } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_08_20)) { + } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE)) { Actor_OfferGetItem(&this->actor, play, GI_RUPEE_RED, 300.0f, 300.0f); } else { Actor_OfferGetItem(&this->actor, play, GI_HEART_PIECE, 300.0f, 300.0f); @@ -778,7 +921,12 @@ void func_809C2A64(EnAob01* this, PlayState* play) { } } -void func_809C2BE4(EnAob01* this, PlayState* play) { +/** + * If the current time is after the racetrack closes, kick the player out. + * Otherwise, ask the player if they want to play again. This function is + * only used when the player has won the 150 rupee reward. + */ +void EnAob01_AfterRace_AfterGivingReward(EnAob01* this, PlayState* play) { u8 talkState = Message_GetState(&play->msgCtx); if (((talkState == TEXT_STATE_5) || (talkState == TEXT_STATE_DONE)) && Message_ShouldAdvance(play)) { @@ -790,51 +938,63 @@ void func_809C2BE4(EnAob01* this, PlayState* play) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_WAIT); } - this->unk_210 = 0; + this->textId = 0; func_800B85E0(&this->actor, play, 400.0f, PLAYER_IA_MINUS1); - gSaveContext.eventInf[0] &= (u8)~7; - this->actionFunc = func_809C2C9C; + SET_EVENTINF_DOG_RACE_STATE(EVENTINF_DOG_RACE_STATE_NOT_STARTED); + this->actionFunc = EnAob01_AfterRace_AskToPlayAgain; } } -void func_809C2C9C(EnAob01* this, PlayState* play) { +/** + * Ask if the player wants to play again. This function is only used when + * the player has won the 150 rupee reward. + */ +void EnAob01_AfterRace_AskToPlayAgain(EnAob01* this, PlayState* play) { if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { - this->unk_210 = 0x354C; - Message_ContinueTextbox(play, this->unk_210); - this->actionFunc = func_809C1D64; + this->textId = 0x354C; // Want to play again? + Message_ContinueTextbox(play, this->textId); + this->actionFunc = EnAob01_BeforeRace_RespondToPlayAgainQuestion; } else { func_800B85E0(&this->actor, play, 400.0f, PLAYER_IA_MINUS1); } } -void func_809C2D0C(EnAob01* this, PlayState* play) { +/** + * Handles the conversation the racetrack owner has with the player after the race + * is over. If the player won 150 or more rupees, this function will transition to + * the action function that gives them the reward. If the player did *not* win 150 + * or more rupees, then if the current time is after the racetrack closes, this + * kicks the player out. Otherwise, this asks the player if they want to play again. + * Much of the logic here is duplicated in the above two functions. + */ +void EnAob01_AfterRace_Talk(EnAob01* this, PlayState* play) { u8 talkState = Message_GetState(&play->msgCtx); Math_SmoothStepToS(&this->actor.shape.rot.y, this->actor.yawTowardsPlayer, 4, 4000, 1); - if (this->unk_2D2 & 0x40) { - if (!func_809C1424(this)) { + if (this->stateFlags & ENAOB01_FLAG_LAUGH) { + if (!EnAob01_ProcessLaughAnim(this)) { return; } - } else if (this->unk_2D2 & 0x80) { - if (!func_809C14D0(this)) { + } else if (this->stateFlags & ENAOB01_FLAG_SURPRISE) { + if (!EnAob01_ProcessSurpriseAnim(this)) { return; } } if ((talkState == TEXT_STATE_5) && Message_ShouldAdvance(play)) { - this->unk_2D2 &= ~0x40; - this->unk_2D2 &= ~0x80; - if (this->unk_434 >= 150) { - this->unk_210 = 0x352E; - Message_StartTextbox(play, this->unk_210, &this->actor); - this->actionFunc = func_809C2A64; + this->stateFlags &= ~ENAOB01_FLAG_LAUGH; + this->stateFlags &= ~ENAOB01_FLAG_SURPRISE; + if (this->rupeesBet >= 150) { + this->textId = 0x352E; // You won over 150 rupees! + Message_StartTextbox(play, this->textId, &this->actor); + this->actionFunc = EnAob01_AfterRace_GiveReward; } else { - this->trackTarget = this->unk_2E6; - this->headRot = this->unk_2EC; - this->torsoRot = this->unk_2F2; + this->trackTarget = this->prevTrackTarget; + this->headRot = this->prevHeadRot; + this->torsoRot = this->prevTorsoRot; - this->unk_434 = 0; + this->rupeesBet = 0; this->actor.shape.rot.y = this->actor.world.rot.y; if (CHECK_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_TIME_PASSED)) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_TIME_PASSED); @@ -844,35 +1004,40 @@ void func_809C2D0C(EnAob01* this, PlayState* play) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_WAIT); } - this->unk_210 = 0x354C; - Message_StartTextbox(play, this->unk_210, &this->actor); - this->actionFunc = func_809C1D64; - gSaveContext.eventInf[0] &= (u8)~7; + this->textId = 0x354C; // Want to play again? + Message_StartTextbox(play, this->textId, &this->actor); + this->actionFunc = EnAob01_BeforeRace_RespondToPlayAgainQuestion; + SET_EVENTINF_DOG_RACE_STATE(EVENTINF_DOG_RACE_STATE_NOT_STARTED); } } } -s32 func_809C2EC4(EnAob01* this, PlayState* play) { +s32 EnAob01_PlayerIsHoldingDog(EnAob01* this, PlayState* play) { Actor* dog = play->actorCtx.actorLists[ACTORCAT_ENEMY].first; while (dog != NULL) { if (dog->id == ACTOR_EN_DG) { - this->unk_432 = ((EnDg*)dog)->selectedDogIndex; - if (this->unk_432 == -1) { + this->selectedDogIndex = ((EnDg*)dog)->selectedDogIndex; + if (this->selectedDogIndex == -1) { return false; } - if (this->unk_432 == ENDG_GET_INDEX(dog)) { + if (this->selectedDogIndex == ENDG_GET_INDEX(dog)) { return true; } } + dog = dog->next; } return false; } -void func_809C2F34(EnAob01* this, PlayState* play) { +/** + * Moves the player and racetrack owner to the center of the racetrack + * (out of the way of the dogs) and stops drawing the player. + */ +void EnAob01_Race_HidePlayer(EnAob01* this, PlayState* play) { Player* player = GET_PLAYER(play); player->actor.world.pos.x = -4134.0f; @@ -885,40 +1050,48 @@ void func_809C2F34(EnAob01* this, PlayState* play) { this->actor.prevPos = this->actor.world.pos; } -void func_809C2FA0(void) { +/** + * Generates a randomized list of dog text offsets and stores them in weekEventRegs. + * EnDg uses these text offsets to determine what text to show when the player picks + * the dog up while equipped with the Mask of Truth, and EnRacedog uses them to + * determine what condition the dog is in. + */ +void EnAob01_InitializeDogTextOffsets(void) { u8 i; u8 rand; - u8 index; - u8 orig; - u8 orig2; - u8 sp44[7]; - u8 sp34[] = { + u8 dogTextOffsetsTemp; + u8 packedDogTextOffsets[(RACEDOG_COUNT + 1) / 2]; + u8 dogTextOffsets[RACEDOG_COUNT] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, }; - for (i = 0; i < ARRAY_COUNT(sp34); i++) { - rand = Rand_ZeroFloat(14.0f); - orig = sp34[i]; + // Swap around the dog text offsets randomly 14 times. + for (i = 0; i < RACEDOG_COUNT; i++) { + rand = Rand_ZeroFloat(RACEDOG_COUNT); - sp34[i] = sp34[rand]; - sp34[rand] = orig; + dogTextOffsetsTemp = dogTextOffsets[i]; + dogTextOffsets[i] = dogTextOffsets[rand]; + dogTextOffsets[rand] = dogTextOffsetsTemp; } - for (i = 0; i < ARRAY_COUNT(sp44); i++) { - gSaveContext.save.saveInfo.weekEventReg[42 + i] = 0; - sp44[i] = 0; + // Clear out all weekEventRegs related to the dog text offsets. + for (i = 0; i < ARRAY_COUNT(packedDogTextOffsets); i++) { + CLEAR_WEEKEVENTREG_DOG_RACE_TEXT_OFFSETS(i); + packedDogTextOffsets[i] = 0; } - for (i = 0; i < ARRAY_COUNT(sp34); i++) { - orig2 = sp34[i]; - index = i / 2; + // Go through all the dog text offsets and pack them into weekEventRegs. + for (i = 0; i < RACEDOG_COUNT; i++) { + u8 dogTextOffsetsTemp = dogTextOffsets[i]; + u8 j = i / 2; if (i % 2) { - sp44[index] |= orig2 << 0x4; - gSaveContext.save.saveInfo.weekEventReg[42 + index] = - ((void)0, gSaveContext.save.saveInfo.weekEventReg[42 + index]) | sp44[index]; + //! @note sets text offsets for both even and odd entry. + //! Requires `RACEDOG_COUNT` to be even to work properly. + packedDogTextOffsets[j] |= dogTextOffsetsTemp << 4; + SET_WEEKEVENTREG_DOG_RACE_TEXT_OFFSETS(j, packedDogTextOffsets[j]); } else { - sp44[index] |= orig2; + packedDogTextOffsets[j] |= dogTextOffsetsTemp; } } } @@ -932,36 +1105,36 @@ void EnAob01_Init(Actor* thisx, PlayState* play) { MAMAMU_YAN_LIMB_MAX); Collider_InitCylinder(play, &this->collider); Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit); - this->unk_43C = 0; - Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 0); + this->animIndex = EN_AOB01_ANIM_IDLE_1; + Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, EN_AOB01_ANIM_IDLE_1); Actor_SetScale(&this->actor, 0.01f); - switch (gSaveContext.eventInf[0] & 7) { - case 0: - func_809C2FA0(); - func_809C11EC(this, play); + switch (GET_EVENTINF_DOG_RACE_STATE) { + case EVENTINF_DOG_RACE_STATE_NOT_STARTED: + EnAob01_InitializeDogTextOffsets(); + EnAob01_SpawnDogs(this, play); this->actor.flags |= ACTOR_FLAG_1; - this->actionFunc = func_809C2060; + this->actionFunc = EnAob01_BeforeRace_Idle; break; - case 2: - this->unk_440 = 500; - func_809C1304(this, play); + case EVENTINF_DOG_RACE_STATE_STARTED: + this->forceRaceEndTimer = 500; + EnAob01_SpawnRacedogs(this, play); this->actor.draw = NULL; this->csId = this->actor.csId; - func_809C2594(this, play); + EnAob01_Race_FollowSelectedDog(this, play); CutsceneManager_Queue(this->csId); this->actor.flags &= ~ACTOR_FLAG_1; - func_809C2F34(this, play); - this->actionFunc = func_809C2824; + EnAob01_Race_HidePlayer(this, play); + this->actionFunc = EnAob01_Race_StartCutscene; break; - case 3: - func_809C2FA0(); - func_809C11EC(this, play); + case EVENTINF_DOG_RACE_STATE_ENDED: + EnAob01_InitializeDogTextOffsets(); + EnAob01_SpawnDogs(this, play); this->actor.flags |= ACTOR_FLAG_1; this->actor.flags |= ACTOR_FLAG_10000; - this->actionFunc = func_809C28B8; + this->actionFunc = EnAob01_AfterRace_GiveRaceResult; break; } } @@ -969,9 +1142,10 @@ void EnAob01_Init(Actor* thisx, PlayState* play) { void EnAob01_Destroy(Actor* thisx, PlayState* play) { EnAob01* this = THIS; - if (!(this->unk_2D2 & 0x20)) { + if (!(this->stateFlags & ENAOB01_FLAG_STARTED_RACE)) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_KICKOUT_WAIT); } + Collider_DestroyCylinder(play, &this->collider); } @@ -979,7 +1153,7 @@ void EnAob01_Update(Actor* thisx, PlayState* play) { EnAob01* this = THIS; this->actionFunc(this, play); - func_809C1EC8(this, play); + EnAob01_UpdateCommon(this, play); } s32 EnAob01_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) { @@ -1014,18 +1188,19 @@ s32 EnAob01_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* if ((limbIndex == MAMAMU_YAN_LIMB_TORSO) || (limbIndex == MAMAMU_YAN_LIMB_LEFT_UPPER_ARM) || (limbIndex == MAMAMU_YAN_LIMB_RIGHT_UPPER_ARM)) { - rot->y += (s16)Math_SinS(this->unk_2F8[limbIndex]) * 200; - rot->z += (s16)Math_CosS(this->unk_318[limbIndex]) * 200; + rot->y += (s16)Math_SinS(this->limbRotTableY[limbIndex]) * 200; + rot->z += (s16)Math_CosS(this->limbRotTableZ[limbIndex]) * 200; } + return false; } void EnAob01_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) { - static Vec3f D_809C3968 = { 0.0f, 0.0f, 0.0f }; + static Vec3f sFocusOffset = { 0.0f, 0.0f, 0.0f }; EnAob01* this = THIS; if (limbIndex == MAMAMU_YAN_LIMB_HEAD) { - Matrix_MultVec3f(&D_809C3968, &this->actor.focus.pos); + Matrix_MultVec3f(&sFocusOffset, &this->actor.focus.pos); } } diff --git a/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.h b/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.h index 5432f74ae..a550fd0d3 100644 --- a/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.h +++ b/src/overlays/actors/ovl_En_Aob_01/z_en_aob_01.h @@ -8,38 +8,56 @@ struct EnAob01; typedef void (*EnAob01ActionFunc)(struct EnAob01*, PlayState*); -#define ENAOB01_GET_7E00_1(thisx) ((thisx)->params & 0x7E00) -#define ENAOB01_GET_7E00_2(thisx) (((thisx)->params & 0x7E00) >> 9) +// This needs to be kept in sync with the number of weekEventRegs used to store the text ID offsets for +// the race dogs. In particular, there needs to be one weekEventReg for every two dogs. This needs to be +// an even number to ensure that all text ID offsets are created (see EnAob01_InitializeDogTextOffsets). +#define RACEDOG_COUNT 14 + +#define ENAOB01_GET_STARTING_DOG_PATH_INDEX(thisx) (((thisx)->params & 0x7E00) >> 9) + +//! @bug This should be shifted up by 1 to match how EnRacedog expects the path index to be supplied. +//! It doesn't cause any problems in the final game because every time EnAob01 is spawned, all the +//! bits here are zero. +#define ENAOB01_GET_RACEDOG_PATH_INDEX(thisx) ((thisx)->params & 0x7E00) + +#define ENAOB01_FLAG_PLAYER_CONFIRMED_CHOICE (1 << 1) +#define ENAOB01_FLAG_PLAYER_TOLD_TO_PICK_A_DOG (1 << 2) +#define ENAOB01_FLAG_TALKING_TO_PLAYER_HOLDING_DOG (1 << 3) +#define ENAOB01_FLAG_CONVERSATION_OVER (1 << 4) +#define ENAOB01_FLAG_STARTED_RACE (1 << 5) +#define ENAOB01_FLAG_LAUGH (1 << 6) +#define ENAOB01_FLAG_SURPRISE (1 << 7) +#define ENAOB01_FLAG_PLAYER_CAN_TALK (1 << 8) typedef struct EnAob01 { /* 0x000 */ Actor actor; /* 0x144 */ EnAob01ActionFunc actionFunc; /* 0x148 */ SkelAnime skelAnime; /* 0x18C */ ColliderCylinder collider; - /* 0x1D8 */ Path* unk_1D8[14]; - /* 0x210 */ u16 unk_210; + /* 0x1D8 */ Path* dogPaths[RACEDOG_COUNT]; + /* 0x210 */ u16 textId; /* 0x212 */ Vec3s jointTable[MAMAMU_YAN_LIMB_MAX]; /* 0x272 */ Vec3s morphTable[MAMAMU_YAN_LIMB_MAX]; - /* 0x2D2 */ u16 unk_2D2; + /* 0x2D2 */ u16 stateFlags; /* 0x2D4 */ Vec3s trackTarget; /* 0x2DA */ Vec3s headRot; /* 0x2E0 */ Vec3s torsoRot; - /* 0x2E6 */ Vec3s unk_2E6; - /* 0x2EC */ Vec3s unk_2EC; - /* 0x2F2 */ Vec3s unk_2F2; - /* 0x2F8 */ s16 unk_2F8[MAMAMU_YAN_LIMB_MAX]; - /* 0x318 */ s16 unk_318[MAMAMU_YAN_LIMB_MAX]; + /* 0x2E6 */ Vec3s prevTrackTarget; + /* 0x2EC */ Vec3s prevHeadRot; + /* 0x2F2 */ Vec3s prevTorsoRot; + /* 0x2F8 */ s16 limbRotTableY[MAMAMU_YAN_LIMB_MAX]; + /* 0x318 */ s16 limbRotTableZ[MAMAMU_YAN_LIMB_MAX]; /* 0x338 */ UNK_TYPE1 unk338[0xB6]; /* 0x3EE */ s16 eyeIndex; /* 0x3F0 */ s16 blinkTimer; - /* 0x3F4 */ Actor* unk_3F4; - /* 0x3F8 */ Actor* unk_3F8[14]; + /* 0x3F4 */ Actor* dogToFollow; + /* 0x3F8 */ Actor* dogs[RACEDOG_COUNT]; /* 0x430 */ s16 csId; - /* 0x432 */ s16 unk_432; - /* 0x434 */ s32 unk_434; + /* 0x432 */ s16 selectedDogIndex; + /* 0x434 */ s32 rupeesBet; // Also used for determining how many rupees to give to the player if they place 1st-5th in the race. /* 0x438 */ UNK_TYPE1 unk438[4]; - /* 0x43C */ s32 unk_43C; - /* 0x440 */ s16 unk_440; + /* 0x43C */ s32 animIndex; + /* 0x440 */ s16 forceRaceEndTimer; } EnAob01; // size = 0x444 #endif // Z_EN_AOB_01_H diff --git a/src/overlays/actors/ovl_En_Bat/z_en_bat.c b/src/overlays/actors/ovl_En_Bat/z_en_bat.c index 0ee1d086b..b60d0bcd3 100644 --- a/src/overlays/actors/ovl_En_Bat/z_en_bat.c +++ b/src/overlays/actors/ovl_En_Bat/z_en_bat.c @@ -4,11 +4,10 @@ * Description: Bad Bat */ -#include "prevent_bss_reordering.h" #include "z_en_bat.h" #include "objects/object_bat/object_bat.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_4000) #define THIS ((EnBat*)thisx) diff --git a/src/overlays/actors/ovl_En_Bigpamet/z_en_bigpamet.c b/src/overlays/actors/ovl_En_Bigpamet/z_en_bigpamet.c index a78731e29..915bf85ba 100644 --- a/src/overlays/actors/ovl_En_Bigpamet/z_en_bigpamet.c +++ b/src/overlays/actors/ovl_En_Bigpamet/z_en_bigpamet.c @@ -540,13 +540,13 @@ void func_80A287E8(EnBigpamet* this, PlayState* play) { } if (this->actor.bgCheckFlags & BGCHECKFLAG_WALL) { - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); this->actor.velocity.y = this->unk_29E * 0.375f; Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 15, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 10); + Quake_SetPerturbations(quakeIndex, 15, 0, 0, 0); + Quake_SetDuration(quakeIndex, 10); Rumble_Request(this->actor.xyzDistToPlayerSq, 180, 20, 100); diff --git a/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c b/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c index c360681e8..f6061d096 100644 --- a/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c +++ b/src/overlays/actors/ovl_En_Bigpo/z_en_bigpo.c @@ -8,7 +8,7 @@ #include "objects/object_bigpo/object_bigpo.h" #include "objects/gameplay_keep/gameplay_keep.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_200 | ACTOR_FLAG_1000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_200 | ACTOR_FLAG_IGNORE_QUAKE) #define THIS ((EnBigpo*)thisx) diff --git a/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c b/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c index 0b61f9e28..5f2071318 100644 --- a/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c +++ b/src/overlays/actors/ovl_En_Bigslime/z_en_bigslime.c @@ -742,11 +742,11 @@ void EnBigslime_EndThrowMinislime(EnBigslime* this) { void EnBigslime_BreakIntoMinislime(EnBigslime* this, PlayState* play) { s32 i; - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 15, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 15); + Quake_SetPerturbations(quakeIndex, 15, 0, 0, 0); + Quake_SetDuration(quakeIndex, 15); Rumble_Request(this->actor.xyzDistToPlayerSq, 180, 20, 100); diff --git a/src/overlays/actors/ovl_En_Bom/z_en_bom.c b/src/overlays/actors/ovl_En_Bom/z_en_bom.c index 4ebdbe916..17ebe10f7 100644 --- a/src/overlays/actors/ovl_En_Bom/z_en_bom.c +++ b/src/overlays/actors/ovl_En_Bom/z_en_bom.c @@ -423,8 +423,8 @@ void EnBom_Explode(EnBom* this, PlayState* play) { } } -static s16 D_80872E98[] = { 3, 5 }; -static s16 D_80872E9C[] = { 10, 15 }; +static s16 sQuakeY[] = { 3, 5 }; +static s16 sQuakeDurations[] = { 10, 15 }; void EnBom_Update(Actor* thisx, PlayState* play) { Vec3f effVelocity = { 0.0f, 0.0f, 0.0f }; @@ -545,7 +545,8 @@ void EnBom_Update(Actor* thisx, PlayState* play) { } Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, effPos.x, effPos.y - 10.0f, effPos.z, 0, 0, 0, this->isPowderKeg); - func_800BC848(thisx, play, D_80872E98[this->isPowderKeg], D_80872E9C[this->isPowderKeg]); + Actor_RequestQuakeAndRumble(thisx, play, sQuakeY[this->isPowderKeg], + sQuakeDurations[this->isPowderKeg]); play->envCtx.lightSettings.diffuseColor1[0] = play->envCtx.lightSettings.diffuseColor1[1] = play->envCtx.lightSettings.diffuseColor1[2] = 250; play->envCtx.lightSettings.ambientColor[0] = play->envCtx.lightSettings.ambientColor[1] = diff --git a/src/overlays/actors/ovl_En_Crow/z_en_crow.c b/src/overlays/actors/ovl_En_Crow/z_en_crow.c index 623d12f0e..3238069cc 100644 --- a/src/overlays/actors/ovl_En_Crow/z_en_crow.c +++ b/src/overlays/actors/ovl_En_Crow/z_en_crow.c @@ -6,7 +6,7 @@ #include "z_en_crow.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_4000) #define THIS ((EnCrow*)thisx) diff --git a/src/overlays/actors/ovl_En_Death/z_en_death.c b/src/overlays/actors/ovl_En_Death/z_en_death.c index dd05c2d48..de02f44ad 100644 --- a/src/overlays/actors/ovl_En_Death/z_en_death.c +++ b/src/overlays/actors/ovl_En_Death/z_en_death.c @@ -7,7 +7,7 @@ #include "z_en_death.h" #include "z64rumble.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_1000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE) #define THIS ((EnDeath*)thisx) diff --git a/src/overlays/actors/ovl_En_Dg/z_en_dg.c b/src/overlays/actors/ovl_En_Dg/z_en_dg.c index 360cf2c49..8a6ae63e8 100644 --- a/src/overlays/actors/ovl_En_Dg/z_en_dg.c +++ b/src/overlays/actors/ovl_En_Dg/z_en_dg.c @@ -5,13 +5,12 @@ */ #include "z_en_dg.h" +#include "overlays/actors/ovl_En_Aob_01/z_en_aob_01.h" #define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10 | ACTOR_FLAG_800000) #define THIS ((EnDg*)thisx) -//! TODO: this file require macros for its uses of weekEventReg - void EnDg_Init(Actor* thisx, PlayState* play); void EnDg_Destroy(Actor* thisx, PlayState* play); void EnDg_Update(Actor* thisx, PlayState* play); @@ -417,20 +416,13 @@ void EnDg_SetupIdleMove(EnDg* this, PlayState* play) { /** * Updates the text ID in sRacetrackDogInfo based on what was set in the weekEventRegs by - * En_Aob_01. This makes it sp the proper message can be displayed when the player picks up + * En_Aob_01. This makes it so the proper message can be displayed when the player picks up * the dog with the Mask of Truth equipped. */ void EnDg_UpdateTextId(EnDg* this) { - if (this->index < 14) { - // Assuming that the weekEventRegs haven't been tampered with, then this will produce a text ID in - // the range of 0x3538 to 0x3545. - if (this->index % 2) { - sRacetrackDogInfo[this->index].textId = - 0x3538 + ((gSaveContext.save.saveInfo.weekEventReg[42 + (this->index / 2)] & 0xF0) >> 4); - } else { - sRacetrackDogInfo[this->index].textId = - 0x3538 + (gSaveContext.save.saveInfo.weekEventReg[42 + (this->index / 2)] & 0x0F); - } + if (this->index < RACEDOG_COUNT) { + // This will produce a text ID in the range of 0x3538 to 0x3545. + sRacetrackDogInfo[this->index].textId = GET_WEEKEVENTREG_DOG_RACE_TEXT(this->index, 0x3538); } else { Actor_Kill(&this->actor); } diff --git a/src/overlays/actors/ovl_En_Dragon/z_en_dragon.c b/src/overlays/actors/ovl_En_Dragon/z_en_dragon.c index 605d0d807..9efb11474 100644 --- a/src/overlays/actors/ovl_En_Dragon/z_en_dragon.c +++ b/src/overlays/actors/ovl_En_Dragon/z_en_dragon.c @@ -725,7 +725,7 @@ void EnDragon_Dead(EnDragon* this, PlayState* play) { void EnDragon_UpdateDamage(EnDragon* this, PlayState* play) { Player* player = GET_PLAYER(play); - u32 sp30; + PlayerImpactType playerImpactType; if (this->action == DEEP_PYTHON_ACTION_EXTEND) { if ((this->collider.elements[2].info.bumperFlags & BUMP_HIT) || @@ -753,7 +753,8 @@ void EnDragon_UpdateDamage(EnDragon* this, PlayState* play) { if ((this->action == DEEP_PYTHON_ACTION_EXTEND) && (this->grabWaitTimer == 0) && (player->invincibilityTimer == 0) && (this->collider.elements[0].info.ocElemFlags & OCELEM_HIT) && - (!(func_800B64FC(play, 1000.0f, &this->actor.world.pos, &sp30) >= 0.0f) || (sp30 != 1))) { + !((Actor_GetPlayerImpact(play, 1000.0f, &this->actor.world.pos, &playerImpactType) >= 0.0f) && + (playerImpactType == PLAYER_IMPACT_ZORA_BARRIER))) { this->actor.speed = 0.0f; this->action = DEEP_PYTHON_ACTION_GRAB; this->actor.flags |= ACTOR_FLAG_100000; diff --git a/src/overlays/actors/ovl_En_Egol/z_en_egol.c b/src/overlays/actors/ovl_En_Egol/z_en_egol.c index 6f9c0e73a..2c7fdc030 100644 --- a/src/overlays/actors/ovl_En_Egol/z_en_egol.c +++ b/src/overlays/actors/ovl_En_Egol/z_en_egol.c @@ -328,19 +328,19 @@ void EnEgol_FootstepEffects(EnEgol* this, PlayState* play, f32 leftFootFrame, f3 if (Animation_OnFrame(&this->skelAnime, leftFootFrame) || Animation_OnFrame(&this->skelAnime, rightFootFrame)) { Vec3f spawnPos; Player* player = GET_PLAYER(play); - s32 quakeSize; + s32 quakeYOffset; s32 pad; Actor_PlaySfx(&this->actor, NA_SE_EN_EYEGOLE_WALK); - quakeSize = 4 - (s32)(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) * 0.02f); - if (quakeSize > 4) { - quakeSize = 4; - } else if (quakeSize < 1) { - quakeSize = 1; + quakeYOffset = 4 - (s32)(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) * 0.02f); + if (quakeYOffset > 4) { + quakeYOffset = 4; + } else if (quakeYOffset < 1) { + quakeYOffset = 1; } if (player->stateFlags3 != PLAYER_STATE3_1000000) { - func_800BC848(&this->actor, play, quakeSize, 2); + Actor_RequestQuakeAndRumble(&this->actor, play, quakeYOffset, 2); } if (Animation_OnFrame(&this->skelAnime, leftFootFrame)) { Math_Vec3f_Copy(&spawnPos, &this->leftFootPos); @@ -755,7 +755,7 @@ void EnEgol_Laser(EnEgol* this, PlayState* play) { f32 nz; s32 pad3; s32 i; - s32 quakeSize; + s32 quakeYOffset; Player* player = GET_PLAYER(play); nx = COLPOLY_GET_NORMAL(colPoly->normal.x); @@ -773,14 +773,14 @@ void EnEgol_Laser(EnEgol* this, PlayState* play) { if ((this->actor.world.pos.y - 50.0f) <= player->actor.world.pos.y) { EnEgol_SpawnEffect(this, &hitPos, &rotToNorm, 100, 0.02f, EYEGORE_EFFECT_IMPACT); } - quakeSize = 4 - (s32)(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) * 0.02f); - if (quakeSize > 4) { - quakeSize = 4; - } else if (quakeSize < 1) { - quakeSize = 1; + quakeYOffset = 4 - (s32)(fabsf(player->actor.world.pos.y - this->actor.world.pos.y) * 0.02f); + if (quakeYOffset > 4) { + quakeYOffset = 4; + } else if (quakeYOffset < 1) { + quakeYOffset = 1; } if (player->stateFlags3 != PLAYER_STATE3_1000000) { - func_800BC848(&this->actor, play, quakeSize, 2); + Actor_RequestQuakeAndRumble(&this->actor, play, quakeYOffset, 2); } Actor_PlaySfx(&this->actor, NA_SE_EV_EXPLOSION); func_800B31BC(play, &hitPos, 40, -2, 255, 20); @@ -880,16 +880,16 @@ void EnEgol_Slam(EnEgol* this, PlayState* play) { Player* player = GET_PLAYER(play); Vec3f spawnPos; f32 dyToPlayer = fabsf(player->actor.world.pos.y - this->actor.world.pos.y); - s32 quakeSize; + s32 quakeYOffset; Actor_PlaySfx(&this->actor, NA_SE_EV_EXPLOSION); - quakeSize = 4 - (s32)(dyToPlayer * 0.02f); - if (quakeSize > 4) { - quakeSize = 4; - } else if (quakeSize < 1) { - quakeSize = 1; + quakeYOffset = 4 - (s32)(dyToPlayer * 0.02f); + if (quakeYOffset > 4) { + quakeYOffset = 4; + } else if (quakeYOffset < 1) { + quakeYOffset = 1; } - func_800BC848(&this->actor, play, quakeSize, 2); + Actor_RequestQuakeAndRumble(&this->actor, play, quakeYOffset, 2); if (this->actor.floorBgId == BGCHECK_SCENE) { Math_Vec3f_Copy(&spawnPos, &this->actor.world.pos); spawnPos.x += Math_SinS(this->actor.world.rot.y) * 60.0f; @@ -1064,7 +1064,7 @@ void EnEgol_Death(EnEgol* this, PlayState* play) { this->subCamAt.y = 60.0f; this->subCamAt.z = 260.0f; Math_Vec3f_Copy(&atOffset, &this->subCamAt); - OLib_DbCameraVec3fSum(&this->actor.world, &atOffset, &this->subCamAt, 1); + OLib_Vec3fAdd(&this->actor.world, &atOffset, &this->subCamAt, OLIB_ADD_OFFSET); this->subCamEye.x = this->actor.world.pos.x; this->subCamEye.y = this->actor.world.pos.y + 70.0f; this->subCamEye.z = this->actor.world.pos.z; @@ -1080,7 +1080,7 @@ void EnEgol_Death(EnEgol* this, PlayState* play) { } else { if (Animation_OnFrame(&this->skelAnime, 46.0f)) { Actor_PlaySfx(&this->actor, NA_SE_EV_EXPLOSION); - func_800BC848(&this->actor, play, 10, 5); + Actor_RequestQuakeAndRumble(&this->actor, play, 10, 5); } if ((curFrame >= this->animEndFrame) && (this->action != EYEGORE_ACTION_DEAD)) { s32 i; diff --git a/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c b/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c index a39a03567..834a6449f 100644 --- a/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c +++ b/src/overlays/actors/ovl_En_Encount1/z_en_encount1.c @@ -5,6 +5,9 @@ */ #include "z_en_encount1.h" +#include "overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h" +#include "overlays/actors/ovl_En_Wallmas/z_en_wallmas.h" +#include "overlays/actors/ovl_En_Pr2/z_en_pr2.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_100000 | ACTOR_FLAG_CANT_LOCK_ON) @@ -13,7 +16,7 @@ void EnEncount1_Init(Actor* thisx, PlayState* play); void EnEncount1_Update(Actor* thisx, PlayState* play); -void func_808E0954(EnEncount1* this, PlayState* play); +void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play); ActorInit En_Encount1_InitVars = { ACTOR_EN_ENCOUNT1, @@ -27,14 +30,19 @@ ActorInit En_Encount1_InitVars = { (ActorFunc)NULL, }; -static s16 sActorList[] = { - ACTOR_EN_GRASSHOPPER, - ACTOR_EN_WALLMAS, - ACTOR_EN_PR2, - ACTOR_EN_PR2, +static s16 sActorIds[] = { + ACTOR_EN_GRASSHOPPER, // EN_ENCOUNT1_GRASSHOPPER + ACTOR_EN_WALLMAS, // EN_ENCOUNT1_WALLMASTER + ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH + ACTOR_EN_PR2, // EN_ENCOUNT1_SKULLFISH_2 }; -static s16 sActorParams[] = { 1, 0, 1, 3 }; +static s16 sActorParams[] = { + EN_GRASSHOPPER_PARAMS(EN_GRASSHOPPER_TYPE_GROWS_WHEN_SPAWNED), // EN_ENCOUNT1_GRASSHOPPER + WALLMASTER_PARAMS(WALLMASTER_TYPE_TIMER_ONLY, 0, false), // EN_ENCOUNT1_WALLMASTER + ENPR2_PARAMS(1, 0), // EN_ENCOUNT1_SKULLFISH + ENPR2_PARAMS(3, 0) // EN_ENCOUNT1_SKULLFISH_2 +}; void EnEncount1_Init(Actor* thisx, PlayState* play) { EnEncount1* this = THIS; @@ -44,69 +52,72 @@ void EnEncount1_Init(Actor* thisx, PlayState* play) { return; } - this->actorType = ENENCOUNT1_GET_TYPE(&this->actor); - this->unk_14C = ENENCOUNT1_GET_7C0(&this->actor); - this->unk_154 = ENENCOUNT1_GET_PATH(&this->actor); - this->unk_158 = this->actor.world.rot.x; - this->unk_15C = this->actor.world.rot.y; - this->unk_160 = (this->actor.world.rot.z * 40.0f) + 120.0f; + this->type = ENENCOUNT1_GET_TYPE(&this->actor); + this->spawnActiveMax = ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(&this->actor); + this->spawnTotalMax = ENENCOUNT1_GET_SPAWN_TOTAL_MAX(&this->actor); + this->spawnTimeMin = ENENCOUNT1_GET_SPAWN_TIME_MIN(&this->actor); + this->spawnUnusedProp = ENENCOUNT1_GET_SPAWN_UNUSED_PROP(&this->actor); + this->spawnDistanceMax = (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) * 40.0f) + 120.0f; - if (this->unk_154 >= 0x3F) { - this->unk_154 = -1; + if (this->spawnTotalMax >= ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE) { + this->spawnTotalMax = -1; } - if (this->actor.world.rot.z < 0) { - this->unk_160 = -1.0f; + if (ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(&this->actor) < 0) { + this->spawnDistanceMax = -1.0f; } - if (this->actorType == EN_ENCOUNT1_SKULLFISH_2) { - this->unk_15A = ENENCOUNT1_GET_PATH(&this->actor); - this->path = SubS_GetPathByIndex(play, this->unk_15A, 0x3F); - this->unk_154 = -1; - this->unk_160 = -1.0f; + if (this->type == EN_ENCOUNT1_SKULLFISH_2) { + this->pathIndex = ENENCOUNT1_GET_PATH_INDEX(&this->actor); + this->path = SubS_GetPathByIndex(play, this->pathIndex, 0x3F); + this->spawnTotalMax = -1; + this->spawnDistanceMax = -1.0f; } this->actor.flags &= ~ACTOR_FLAG_1; - this->actionFunc = func_808E0954; + this->actionFunc = EnEncount1_SpawnActor; } -void func_808E0954(EnEncount1* this, PlayState* play) { +void EnEncount1_SpawnActor(EnEncount1* this, PlayState* play) { Player* player = GET_PLAYER(play); Vec3f spawnPos; - f32 sp64; - f32 temp_fv0_2; - s16 sp5E; - s16 actorList; + f32 scale; + f32 floorHeight; + s16 rotY; + s16 actorId; s32 actorParams; - CollisionPoly* sp54; - s32 sp50; + CollisionPoly* floorPoly; + s32 bgId; - if (((this->unk_14E >= this->unk_14C) || ((this->unk_160 > 0.0f) && (this->unk_160 < this->actor.xzDistToPlayer)) || - ((this->unk_154 > 0) && (this->unk_154 <= this->unk_152)))) { + if (((this->spawnActiveCount >= this->spawnActiveMax) || + ((this->spawnDistanceMax > 0.0f) && (this->spawnDistanceMax < this->actor.xzDistToPlayer)) || + ((this->spawnTotalMax > 0) && (this->spawnTotalMax <= this->spawnTotalCount)))) { return; - } else if (this->unk_156 != 0) { - this->unk_156++; - if (this->unk_156 < this->unk_158) { + } + + if (this->timer != 0) { + this->timer++; + if (this->timer < this->spawnTimeMin) { return; } } - this->unk_156 = 0; - switch (this->actorType) { + this->timer = 0; + switch (this->type) { case EN_ENCOUNT1_GRASSHOPPER: - sp64 = randPlusMinusPoint5Scaled(40.0f) + 200.0f; - sp5E = player->actor.shape.rot.y; - if (this->unk_14E & 1) { - sp5E = -sp5E; - sp64 = randPlusMinusPoint5Scaled(20.0f) + 100.0f; + scale = randPlusMinusPoint5Scaled(40.0f) + 200.0f; + rotY = player->actor.shape.rot.y; + if (this->spawnActiveCount & 1) { + rotY = -rotY; + scale = randPlusMinusPoint5Scaled(20.0f) + 100.0f; } - spawnPos.x = player->actor.world.pos.x + (Math_SinS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); + spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f); spawnPos.y = player->actor.floorHeight + 120.0f; - spawnPos.z = player->actor.world.pos.z + (Math_CosS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); - temp_fv0_2 = BgCheck_EntityRaycastFloor5(&play->colCtx, &sp54, &sp50, &this->actor, &spawnPos); - if ((temp_fv0_2 <= BGCHECK_Y_MIN) || + spawnPos.z = player->actor.world.pos.z + (Math_CosS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f); + floorHeight = BgCheck_EntityRaycastFloor5(&play->colCtx, &floorPoly, &bgId, &this->actor, &spawnPos); + if ((floorHeight <= BGCHECK_Y_MIN) || ((player->actor.depthInWater != BGCHECK_Y_MIN) && - (temp_fv0_2 < (player->actor.world.pos.y - player->actor.depthInWater)))) { + (floorHeight < (player->actor.world.pos.y - player->actor.depthInWater)))) { return; } - spawnPos.y = temp_fv0_2; + spawnPos.y = floorHeight; break; case EN_ENCOUNT1_WALLMASTER: @@ -114,36 +125,36 @@ void func_808E0954(EnEncount1* this, PlayState* play) { break; case EN_ENCOUNT1_SKULLFISH: - sp64 = randPlusMinusPoint5Scaled(250.0f) + 500.0f; - sp5E = player->actor.shape.rot.y; - spawnPos.x = player->actor.world.pos.x + Math_SinS(sp5E) * sp64 + randPlusMinusPoint5Scaled(40.0f); + scale = randPlusMinusPoint5Scaled(250.0f) + 500.0f; + rotY = player->actor.shape.rot.y; + spawnPos.x = player->actor.world.pos.x + (Math_SinS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f); spawnPos.y = player->actor.world.pos.y - Rand_ZeroFloat(20.0f); - spawnPos.z = player->actor.world.pos.z + (Math_CosS(sp5E) * sp64) + randPlusMinusPoint5Scaled(40.0f); - temp_fv0_2 = BgCheck_EntityRaycastFloor5(&play->colCtx, &sp54, &sp50, &this->actor, &spawnPos); - if ((!(player->stateFlags1 & 0x8000000) || (temp_fv0_2 <= (BGCHECK_Y_MIN)) || - (player->actor.depthInWater < temp_fv0_2))) { + spawnPos.z = player->actor.world.pos.z + (Math_CosS(rotY) * scale) + randPlusMinusPoint5Scaled(40.0f); + floorHeight = BgCheck_EntityRaycastFloor5(&play->colCtx, &floorPoly, &bgId, &this->actor, &spawnPos); + if (!(player->stateFlags1 & PLAYER_STATE1_8000000) || (floorHeight <= BGCHECK_Y_MIN) || + (player->actor.depthInWater < floorHeight)) { return; } break; case EN_ENCOUNT1_SKULLFISH_2: - if ((this->path != NULL) && (!SubS_CopyPointFromPath(this->path, 0, &spawnPos))) { + if ((this->path != NULL) && !SubS_CopyPointFromPath(this->path, 0, &spawnPos)) { Actor_Kill(&this->actor); } break; } - actorList = sActorList[this->actorType]; - actorParams = sActorParams[this->actorType]; - if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, actorList, spawnPos.x, spawnPos.y, spawnPos.z, 0, 0, 0, + actorId = sActorIds[this->type]; + actorParams = sActorParams[this->type]; + if (Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, actorId, spawnPos.x, spawnPos.y, spawnPos.z, 0, 0, 0, actorParams) != NULL) { - this->unk_14E++; - if (this->unk_154 > 0) { - this->unk_152++; + this->spawnActiveCount++; + if (this->spawnTotalMax > 0) { + this->spawnTotalCount++; } - if ((this->unk_14E >= this->unk_14C) && (this->unk_158 != 0)) { - this->unk_156 = 1; + if ((this->spawnActiveCount >= this->spawnActiveMax) && (this->spawnTimeMin != 0)) { + this->timer = 1; } } } diff --git a/src/overlays/actors/ovl_En_Encount1/z_en_encount1.h b/src/overlays/actors/ovl_En_Encount1/z_en_encount1.h index 52e0fb30c..5c8e6db83 100644 --- a/src/overlays/actors/ovl_En_Encount1/z_en_encount1.h +++ b/src/overlays/actors/ovl_En_Encount1/z_en_encount1.h @@ -3,15 +3,22 @@ #include "global.h" +#define ENENCOUNT1_SPAWNS_TOTAL_MAX_INFINITE 63 // aka 0x3F, All bits set + #define ENENCOUNT1_GET_TYPE(thisx) (((thisx)->params >> 11) & 0x1F) -#define ENENCOUNT1_GET_7C0(thisx) (((thisx)->params >> 6) & 0x1F) -#define ENENCOUNT1_GET_PATH(thisx) ((thisx)->params & 0x3F) +#define ENENCOUNT1_GET_SPAWN_ACTIVE_MAX(thisx) (((thisx)->params >> 6) & 0x1F) +#define ENENCOUNT1_GET_SPAWN_TOTAL_MAX(thisx) ((thisx)->params & 0x3F) +#define ENENCOUNT1_GET_PATH_INDEX(thisx) ((thisx)->params & 0x3F) // Used only by EN_ENCOUNT1_SKULLFISH_2 which doesn't use SpawnTotalMax + +#define ENENCOUNT1_GET_SPAWN_TIME_MIN(thisx) ((thisx)->world.rot.x) // Time to wait between spawning +#define ENENCOUNT1_GET_SPAWN_UNUSED_PROP(thisx) ((thisx)->world.rot.y) // Unused spawn property +#define ENENCOUNT1_GET_SPAWN_DISTANCE_MAX(thisx) ((thisx)->world.rot.z) // Negative means infinite distance typedef enum EnEncount1Enemy { - /* 0x0 */ EN_ENCOUNT1_GRASSHOPPER, - /* 0x1 */ EN_ENCOUNT1_WALLMASTER, - /* 0x2 */ EN_ENCOUNT1_SKULLFISH, - /* 0x3 */ EN_ENCOUNT1_SKULLFISH_2, + /* 0 */ EN_ENCOUNT1_GRASSHOPPER, + /* 1 */ EN_ENCOUNT1_WALLMASTER, + /* 2 */ EN_ENCOUNT1_SKULLFISH, + /* 3 */ EN_ENCOUNT1_SKULLFISH_2, } EnEncount1Enemy; struct EnEncount1; @@ -22,16 +29,16 @@ typedef struct EnEncount1 { /* 0x000 */ Actor actor; /* 0x144 */ EnEncount1ActionFunc actionFunc; /* 0x148 */ Path* path; - /* 0x14C */ s16 unk_14C; - /* 0x14E */ s16 unk_14E; - /* 0x150 */ s16 actorType; - /* 0x152 */ s16 unk_152; - /* 0x154 */ s16 unk_154; - /* 0x156 */ s16 unk_156; - /* 0x158 */ s16 unk_158; - /* 0x15A */ s16 unk_15A; - /* 0x15C */ s32 unk_15C; - /* 0x160 */ f32 unk_160; + /* 0x14C */ s16 spawnActiveMax; + /* 0x14E */ s16 spawnActiveCount; + /* 0x150 */ s16 type; + /* 0x152 */ s16 spawnTotalCount; + /* 0x154 */ s16 spawnTotalMax; + /* 0x156 */ s16 timer; + /* 0x158 */ s16 spawnTimeMin; + /* 0x15A */ s16 pathIndex; + /* 0x15C */ s32 spawnUnusedProp; + /* 0x160 */ f32 spawnDistanceMax; } EnEncount1; // size = 0x164 #endif // Z_EN_ENCOUNT1_H diff --git a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c index bc4e3d743..434ee1b86 100644 --- a/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c +++ b/src/overlays/actors/ovl_En_Firefly/z_en_firefly.c @@ -8,7 +8,7 @@ #include "overlays/actors/ovl_Obj_Syokudai/z_obj_syokudai.h" #include "objects/object_firefly/object_firefly.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_4000) #define THIS ((EnFirefly*)thisx) diff --git a/src/overlays/actors/ovl_En_Firefly2/z_en_firefly2.c b/src/overlays/actors/ovl_En_Firefly2/z_en_firefly2.c index 6c105caa2..00a0d4d9d 100644 --- a/src/overlays/actors/ovl_En_Firefly2/z_en_firefly2.c +++ b/src/overlays/actors/ovl_En_Firefly2/z_en_firefly2.c @@ -6,7 +6,7 @@ #include "z_en_firefly2.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_4000) #define THIS ((EnFirefly2*)thisx) diff --git a/src/overlays/actors/ovl_En_Fu/z_en_fu.c b/src/overlays/actors/ovl_En_Fu/z_en_fu.c index 7435d0ddc..97f996ff1 100644 --- a/src/overlays/actors/ovl_En_Fu/z_en_fu.c +++ b/src/overlays/actors/ovl_En_Fu/z_en_fu.c @@ -728,8 +728,8 @@ void func_80962D60(EnFu* this, PlayState* play) { void func_80962EBC(EnFu* this, PlayState* play) { if (this->unk_542 != 0) { if (this->actor.csId != CS_ID_NONE) { - Camera_ChangeDataIdx(play->cameraPtrs[CAM_ID_MAIN], - CutsceneManager_GetCutsceneEntry(this->actor.csId)->csCamId); + Camera_ChangeActorCsCamIndex(play->cameraPtrs[CAM_ID_MAIN], + CutsceneManager_GetCutsceneEntry(this->actor.csId)->csCamId); } } } diff --git a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c index 14afe3270..9c2d7fe37 100644 --- a/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c +++ b/src/overlays/actors/ovl_En_Gb2/z_en_gb2.c @@ -355,7 +355,7 @@ void func_80B0FD8C(EnGb2* this, PlayState* play) { } void func_80B0FE18(PlayState* play) { - func_800FD750(0x38); + func_800FD750(NA_BGM_MINI_BOSS); play->nextEntrance = ENTRANCE(GHOST_HUT, 1); play->transitionType = TRANS_TYPE_64; gSaveContext.nextTransitionType = TRANS_TYPE_64; diff --git a/src/overlays/actors/ovl_En_Go/z_en_go.c b/src/overlays/actors/ovl_En_Go/z_en_go.c index a0c7e3180..3f993ae3a 100644 --- a/src/overlays/actors/ovl_En_Go/z_en_go.c +++ b/src/overlays/actors/ovl_En_Go/z_en_go.c @@ -1046,16 +1046,16 @@ s32 func_80A13564(EnGo* this, f32 arg1, f32 arg2, s32 arg3) { return ret; } -void func_80A136B8(PlayState* play, s16 speed, s16 verticalMag, s16 countdown) { - s16 quakeIndex = Quake_Add(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); +void EnGo_RequestQuake(PlayState* play, s16 speed, s16 y, s16 duration) { + s16 quakeIndex = Quake_Request(Play_GetCamera(play, CAM_ID_MAIN), QUAKE_TYPE_3); - Quake_SetCountdown(quakeIndex, countdown); + Quake_SetDuration(quakeIndex, duration); Quake_SetSpeed(quakeIndex, speed); - Quake_SetQuakeValues(quakeIndex, verticalMag, 0, 0, 0); + Quake_SetPerturbations(quakeIndex, y, 0, 0, 0); } void func_80A13728(EnGo* this, PlayState* play) { - func_80A136B8(play, 27767, 7, 20); + EnGo_RequestQuake(play, 27767, 7, 20); play->actorCtx.unk2 = 4; Actor_Spawn(&play->actorCtx, play, ACTOR_EN_TEST, this->actor.world.pos.x, this->actor.world.pos.y, this->actor.world.pos.z, 0, 0, 0, 0); diff --git a/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c b/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c index 6e4c31ab3..0a513e450 100644 --- a/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c +++ b/src/overlays/actors/ovl_En_Goroiwa/z_en_goroiwa.c @@ -451,11 +451,11 @@ s32 func_8093F6F8(EnGoroiwa* this, PlayState* play) { if ((this->actor.velocity.y < 0.0f) && (this->actor.world.pos.y <= sp7C)) { if (this->unk_1CA == 0) { if (this->actor.xzDistToPlayer < 400.0f) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 17232); - Quake_SetQuakeValues(quakeIndex, 3, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 7); + Quake_SetPerturbations(quakeIndex, 3, 0, 0, 0); + Quake_SetDuration(quakeIndex, 7); } this->unk_1C4 = 0.0f; diff --git a/src/overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h b/src/overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h index 8056253f6..11ed8a130 100644 --- a/src/overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h +++ b/src/overlays/actors/ovl_En_Grasshopper/z_en_grasshopper.h @@ -6,6 +6,8 @@ #define EN_GRASSHOPPER_GET_TYPE(thisx) ((thisx)->params) +#define EN_GRASSHOPPER_PARAMS(type) (type) + struct EnGrasshopper; typedef void (*EnGrasshopperActionFunc)(struct EnGrasshopper*, PlayState*); diff --git a/src/overlays/actors/ovl_En_Gs/z_en_gs.c b/src/overlays/actors/ovl_En_Gs/z_en_gs.c index 2f4257347..6d8e64931 100644 --- a/src/overlays/actors/ovl_En_Gs/z_en_gs.c +++ b/src/overlays/actors/ovl_En_Gs/z_en_gs.c @@ -523,8 +523,8 @@ s32 func_80998A48(EnGs* this, PlayState* play) { this->unk_1D4 = 0; this->unk_19A |= 1; - this->unk_21C = 5; - this->unk_21E = 40; + this->quakeY = 5; + this->quakeDuration = 40; this->unk_197++; this->unk_197 &= 0xF; this->unk_19D = 1; @@ -558,8 +558,8 @@ s32 func_80998BBC(EnGs* this, PlayState* play) { this->unk_1D4 = 0; this->unk_19A |= 1; - this->unk_21C = 5; - this->unk_21E = 40; + this->quakeY = 5; + this->quakeDuration = 40; this->unk_197--; this->unk_197 &= 0xF; this->unk_19D = 1; @@ -585,8 +585,8 @@ s32 func_80998D44(EnGs* this, PlayState* play) { this->unk_1E0 = -0.8f; Actor_PlaySfx(&this->actor, NA_SE_EV_G_STONE_CRUSH); this->unk_19A |= 1; - this->unk_21C = 40; - this->unk_21E = 11; + this->quakeY = 40; + this->quakeDuration = 11; this->unk_19D++; } else if (this->unk_19D == 1) { step = Math_SmoothStepToF(&this->unk_1DC, this->unk_1E0, 1.0f, 0.4f, 0.001f); @@ -611,8 +611,8 @@ s32 func_80998D44(EnGs* this, PlayState* play) { this->unk_216 = 0; this->unk_1E0 = 0.0f; this->unk_1D4 = 0; - this->unk_21C = 10; - this->unk_21E = 10; + this->quakeY = 10; + this->quakeDuration = 10; this->unk_1DC = 0.5f; Actor_PlaySfx(&this->actor, NA_SE_EN_STALKID_ATTACK); this->unk_19D += 1; @@ -641,8 +641,8 @@ s32 func_80998F9C(EnGs* this, PlayState* play) { this->unk_1EC = 0.0f; this->unk_19D = 1; - this->unk_21C = 2; - this->unk_21E = 40; + this->quakeY = 2; + this->quakeDuration = 40; this->unk_216 = 200; } @@ -714,8 +714,8 @@ s32 func_80998F9C(EnGs* this, PlayState* play) { this->unk_1F0 = 0.0f; this->unk_1EC = 0.5f; Actor_PlaySfx(&this->actor, NA_SE_EN_STALKID_ATTACK); - this->unk_21C = 20; - this->unk_21E = 2; + this->quakeY = 20; + this->quakeDuration = 2; this->unk_19D = 6; } } @@ -800,8 +800,8 @@ s32 func_809995A4(EnGs* this, PlayState* play) { if (this->unk_1D4 <= 0) { this->unk_19A &= ~4; - this->unk_21C = 3; - this->unk_21E = 40; + this->quakeY = 3; + this->quakeDuration = 40; this->unk_1D4 = 0; this->unk_19D++; } @@ -834,8 +834,8 @@ s32 func_809995A4(EnGs* this, PlayState* play) { this->unk_1DC = 0.0f; this->unk_19D++; - this->unk_21C = 5; - this->unk_21E = 20; + this->quakeY = 5; + this->quakeDuration = 20; this->unk_19A |= 1; this->unk_216 = 200; this->unk_1E0 = (this->unk_197 >> 2) * 0x444; @@ -1028,8 +1028,8 @@ void EnGs_Update(Actor* thisx, PlayState* play) { if ((this->actor.xyzDistToPlayerSq > SQ(400.0f)) || (sp2E < 0) || (sp2E > SCREEN_WIDTH) || (sp2C < 0) || (sp2C > SCREEN_HEIGHT)) { this->unk_216 = 0; - } else if (this->unk_21C > 0) { - func_800BC848(&this->actor, play, this->unk_21C, this->unk_21E); + } else if (this->quakeY > 0) { + Actor_RequestQuakeAndRumble(&this->actor, play, this->quakeY, this->quakeDuration); } } else { this->unk_216 = 0; @@ -1048,8 +1048,8 @@ void EnGs_Update(Actor* thisx, PlayState* play) { } } - if (this->unk_21C > 0) { - this->unk_21C = 0; + if (this->quakeY > 0) { + this->quakeY = 0; } func_80999B34(this); diff --git a/src/overlays/actors/ovl_En_Gs/z_en_gs.h b/src/overlays/actors/ovl_En_Gs/z_en_gs.h index fb2d62816..abb4a5b86 100644 --- a/src/overlays/actors/ovl_En_Gs/z_en_gs.h +++ b/src/overlays/actors/ovl_En_Gs/z_en_gs.h @@ -53,8 +53,8 @@ typedef struct EnGs { /* 0x216 */ s16 unk_216; /* 0x218 */ s16 unk_218; /* 0x21A */ s16 unk_21A; - /* 0x21C */ s16 unk_21C; - /* 0x21E */ s16 unk_21E; + /* 0x21C */ s16 quakeY; + /* 0x21E */ s16 quakeDuration; } EnGs; // size = 0x220 #endif // Z_EN_GS_H diff --git a/src/overlays/actors/ovl_En_Horse/z_en_horse.c b/src/overlays/actors/ovl_En_Horse/z_en_horse.c index 644559c94..6ca711a2b 100644 --- a/src/overlays/actors/ovl_En_Horse/z_en_horse.c +++ b/src/overlays/actors/ovl_En_Horse/z_en_horse.c @@ -792,7 +792,8 @@ void EnHorse_Init(Actor* thisx, PlayState* play2) { this->stateFlags = 0; } - if (((play->sceneId == SCENE_KOEPONARACE) && (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_START)) || + if (((play->sceneId == SCENE_KOEPONARACE) && + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_START)) || ((gSaveContext.save.entrance == ENTRANCE(ROMANI_RANCH, 0)) && (Cutscene_GetSceneLayer(play) != 0))) { this->stateFlags |= ENHORSE_FLAG_25; } @@ -2471,7 +2472,7 @@ void func_808819D8(EnHorse* this, PlayState* play) { func_8088168C(this); } - if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_3) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_3) { this->rider->unk488 = 7; } else { EnHorse_SetIngoAnimation(this->animIndex, this->skin.skelAnime.curFrame, this->unk_394 & 1, diff --git a/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c b/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c index 5e7619cd2..d37fb8f23 100644 --- a/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c +++ b/src/overlays/actors/ovl_En_Horse_Game_Check/z_en_horse_game_check.c @@ -59,7 +59,7 @@ s32 func_808F8AA0(EnHorseGameCheck* this, PlayState* play) { DynaPolyActor_Init(&this->dyna, 0); - if (GET_WEEKEVENTREG_RACE_FLAGS != WEEKEVENTREG_RACE_FLAG_START) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE != WEEKEVENTREG_HORSE_RACE_STATE_START) { Actor_Kill(&this->dyna.actor); return false; } @@ -116,7 +116,7 @@ s32 func_808F8CCC(EnHorseGameCheck* this, PlayState* play2) { this->unk_168 = 0; this->unk_174 = 0; - if (GET_WEEKEVENTREG_RACE_FLAGS != WEEKEVENTREG_RACE_FLAG_START) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE != WEEKEVENTREG_HORSE_RACE_STATE_START) { Actor_Kill(&this->dyna.actor); return false; } @@ -156,14 +156,14 @@ s32 func_808F8EB0(EnHorseGameCheck* this, PlayState* play) { return false; } - if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_3) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_3) { play->transitionType = TRANS_TYPE_64; gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK; - } else if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_2) { + } else if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2) { play->transitionType = TRANS_TYPE_80; gSaveContext.nextTransitionType = TRANS_TYPE_FADE_WHITE; - } else if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_4) { - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_3); + } else if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_4) { + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_3); play->transitionType = TRANS_TYPE_FADE_BLACK; gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK; } @@ -252,7 +252,7 @@ s32 func_808F8FAC(EnHorseGameCheck* this, PlayState* play) { play_sound(NA_SE_SY_START_SHOT); this->unk_164 |= 0x40000; gSaveContext.timerStates[TIMER_ID_MINIGAME_2] = TIMER_STATE_6; - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_4); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_4); this->unk_174 = 60; } @@ -285,7 +285,7 @@ s32 func_808F8FAC(EnHorseGameCheck* this, PlayState* play) { play_sound(NA_SE_SY_START_SHOT); this->unk_164 |= 0x40000; gSaveContext.timerStates[TIMER_ID_MINIGAME_2] = TIMER_STATE_6; - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_3); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_3); this->unk_174 = 60; } @@ -318,7 +318,7 @@ s32 func_808F8FAC(EnHorseGameCheck* this, PlayState* play) { play_sound(NA_SE_SY_START_SHOT); this->unk_164 |= 0x02000000; gSaveContext.timerStates[TIMER_ID_MINIGAME_2] = TIMER_STATE_6; - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_3); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_3); this->unk_174 = 60; } @@ -347,7 +347,7 @@ s32 func_808F8FAC(EnHorseGameCheck* this, PlayState* play) { play_sound(NA_SE_SY_START_SHOT); this->unk_164 |= 0x800; gSaveContext.timerStates[TIMER_ID_MINIGAME_2] = TIMER_STATE_6; - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_2); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_2); this->unk_174 = 60; } return true; diff --git a/src/overlays/actors/ovl_En_In/z_en_in.c b/src/overlays/actors/ovl_En_In/z_en_in.c index 8bedd48cf..71c512418 100644 --- a/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/src/overlays/actors/ovl_En_In/z_en_in.c @@ -336,7 +336,7 @@ void func_808F38F8(EnIn* this, PlayState* play) { } void func_808F395C(EnIn* this, PlayState* play) { - if (this->unk4B0 == WEEKEVENTREG_RACE_FLAG_END) { + if (this->unk4B0 == WEEKEVENTREG_HORSE_RACE_STATE_END) { this->actionFunc = func_808F5A94; } if (Actor_ProcessTalkRequest(&this->actor, &play->state)) { @@ -352,30 +352,30 @@ void func_808F39DC(EnIn* this, PlayState* play) { u16 textId = 0; if (gSaveContext.save.day != 3) { - switch (GET_WEEKEVENTREG_RACE_FLAGS) { - case WEEKEVENTREG_RACE_FLAG_2: + switch (GET_WEEKEVENTREG_HORSE_RACE_STATE) { + case WEEKEVENTREG_HORSE_RACE_STATE_2: textId = 0x347A; break; - case WEEKEVENTREG_RACE_FLAG_3: + case WEEKEVENTREG_HORSE_RACE_STATE_3: textId = 0x3476; break; } - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_END); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_END); } else { - switch (GET_WEEKEVENTREG_RACE_FLAGS) { - case WEEKEVENTREG_RACE_FLAG_2: + switch (GET_WEEKEVENTREG_HORSE_RACE_STATE) { + case WEEKEVENTREG_HORSE_RACE_STATE_2: textId = 0x349D; break; - case WEEKEVENTREG_RACE_FLAG_3: + case WEEKEVENTREG_HORSE_RACE_STATE_3: textId = 0x3499; break; } - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_END); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_END); } this->actor.flags |= ACTOR_FLAG_10000; this->actor.textId = textId; this->actionFunc = func_808F395C; - if (this->unk4B0 == WEEKEVENTREG_RACE_FLAG_2) { + if (this->unk4B0 == WEEKEVENTREG_HORSE_RACE_STATE_2) { Actor_PlaySfx(&this->actor, NA_SE_VO_IN_LOST); } else { Actor_PlaySfx(&this->actor, NA_SE_VO_IN_JOY0); @@ -635,7 +635,7 @@ s32 func_808F4270(PlayState* play, EnIn* this, s32 arg2, MessageContext* msgCtx, s32 func_808F43E0(EnIn* this) { this->unk48C = 0; this->actor.textId = 0; - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_END); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_END); return 0; } @@ -817,7 +817,7 @@ s32 func_808F4414(PlayState* play, EnIn* this, s32 arg2) { func_80151BB4(play, 0x11); break; case 0x3475: - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_START); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_START); func_800FD750(NA_BGM_HORSE); play->nextEntrance = ENTRANCE(GORMAN_TRACK, 5); play->transitionType = TRANS_TYPE_FADE_WHITE_FAST; @@ -1064,7 +1064,7 @@ s32 func_808F4414(PlayState* play, EnIn* this, s32 arg2) { ret = false; break; case 0x3475: - SET_WEEKEVENTREG_RACE_FLAGS(WEEKEVENTREG_RACE_FLAG_START); + SET_WEEKEVENTREG_HORSE_RACE_STATE(WEEKEVENTREG_HORSE_RACE_STATE_START); func_800FD750(NA_BGM_HORSE); play->nextEntrance = ENTRANCE(GORMAN_TRACK, 5); play->transitionType = TRANS_TYPE_FADE_WHITE_FAST; @@ -1322,7 +1322,7 @@ void func_808F5B58(EnIn* this, PlayState* play) { } void func_808F5C98(EnIn* this, PlayState* play) { - if (this->unk4B0 == WEEKEVENTREG_RACE_FLAG_END) { + if (this->unk4B0 == WEEKEVENTREG_HORSE_RACE_STATE_END) { this->actionFunc = func_808F5B58; } if ((Player_GetMask(play) == PLAYER_MASK_CIRCUS_LEADER && CHECK_WEEKEVENTREG(WEEKEVENTREG_63_40)) || @@ -1334,7 +1334,7 @@ void func_808F5C98(EnIn* this, PlayState* play) { } } if (this->unk4A8 == 2) { - if (this->unk4B0 == WEEKEVENTREG_RACE_FLAG_2) { + if (this->unk4B0 == WEEKEVENTREG_HORSE_RACE_STATE_2) { Actor_PlaySfx(&this->actor, NA_SE_VO_IN_LOST); } else { Actor_PlaySfx(&this->actor, NA_SE_VO_IN_JOY0); @@ -1366,7 +1366,7 @@ void EnIn_Init(Actor* thisx, PlayState* play) { this->unk48C = 0; this->unk4AC = 0; type = ENIN_GET_TYPE(thisx); - this->unk4B0 = GET_WEEKEVENTREG_RACE_FLAGS; + this->unk4B0 = GET_WEEKEVENTREG_HORSE_RACE_STATE; if (type == ENIN_HORSE_RIDER_BLUE_SHIRT || type == ENIN_BLUE_SHIRT) { this->unk4AC |= 8; } @@ -1387,8 +1387,8 @@ void EnIn_Init(Actor* thisx, PlayState* play) { this->path = SubS_GetPathByIndex(play, ENIN_GET_PATH(&this->actor), 0x3F); this->unk23D = 0; if (type == ENIN_YELLOW_SHIRT || type == ENIN_BLUE_SHIRT) { - if ((GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_2) || - (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_3)) { + if ((GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2) || + (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_3)) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_56_08); this->unk4A8 = 0; this->unk4AC |= 2; @@ -1396,12 +1396,12 @@ void EnIn_Init(Actor* thisx, PlayState* play) { this->unk23C = 0; D_801BDAA0 = 0; - if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_2) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2) { EnIn_ChangeAnim(&this->skelAnime, ENIN_ANIM_6); } else { EnIn_ChangeAnim(&this->skelAnime, ENIN_ANIM_4); } - if (GET_WEEKEVENTREG_RACE_FLAGS == WEEKEVENTREG_RACE_FLAG_2) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE == WEEKEVENTREG_HORSE_RACE_STATE_2) { this->skelAnime.curFrame = ((Rand_ZeroOne() * 0.6f) + 0.2f) * this->skelAnime.endFrame; } if (this->unk4AC & 8) { @@ -1410,7 +1410,7 @@ void EnIn_Init(Actor* thisx, PlayState* play) { this->actionFunc = func_808F5C98; } } else { - if (GET_WEEKEVENTREG_RACE_FLAGS != WEEKEVENTREG_RACE_FLAG_START) { + if (GET_WEEKEVENTREG_HORSE_RACE_STATE != WEEKEVENTREG_HORSE_RACE_STATE_START) { CLEAR_WEEKEVENTREG(WEEKEVENTREG_56_08); this->unk23C = 0; this->unk4AC |= 2; diff --git a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c index 800cfd291..7bc9878f1 100644 --- a/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c +++ b/src/overlays/actors/ovl_En_Ishi/z_en_ishi.c @@ -597,11 +597,11 @@ void func_8095EBDC(EnIshi* this, PlayState* play) { } if (sp70 == 1) { - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 17232); - Quake_SetQuakeValues(quakeIndex, 3, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 7); + Quake_SetPerturbations(quakeIndex, 3, 0, 0, 0); + Quake_SetDuration(quakeIndex, 7); Rumble_Request(this->actor.xyzDistToPlayerSq, 255, 20, 150); } diff --git a/src/overlays/actors/ovl_En_Jgame_Tsn/z_en_jgame_tsn.c b/src/overlays/actors/ovl_En_Jgame_Tsn/z_en_jgame_tsn.c index 5efca1bcd..2985409dc 100644 --- a/src/overlays/actors/ovl_En_Jgame_Tsn/z_en_jgame_tsn.c +++ b/src/overlays/actors/ovl_En_Jgame_Tsn/z_en_jgame_tsn.c @@ -284,7 +284,7 @@ void func_80C1410C(EnJgameTsn* this, PlayState* play) { Player* player = GET_PLAYER(play); player->stateFlags1 |= PLAYER_STATE1_20; - Audio_PlaySubBgm(0x25); + Audio_PlaySubBgm(NA_BGM_TIMED_MINI_GAME); play->interfaceCtx.minigameState = MINIGAME_STATE_COUNTDOWN_SETUP_3; Interface_InitMinigame(play); SET_WEEKEVENTREG(WEEKEVENTREG_90_20); diff --git a/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c b/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c index 19fd2c19f..2cec5d9b8 100644 --- a/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c +++ b/src/overlays/actors/ovl_En_Kakasi/z_en_kakasi.c @@ -609,7 +609,7 @@ void EnKakasi_TeachingSong(EnKakasi* this, PlayState* play) { this->subCamEyeNext.z = D_80971DCC[this->unk190].z; Math_Vec3f_Copy(&tempVec, &this->subCamEyeNext); - OLib_DbCameraVec3fSum(&this->picto.actor.home, &tempVec, &this->subCamEyeNext, 1); + OLib_Vec3fAdd(&this->picto.actor.home, &tempVec, &this->subCamEyeNext, OLIB_ADD_OFFSET); Math_Vec3f_Copy(&this->subCamAtNext, &this->unk22C); Math_Vec3f_Copy(&this->subCamEye, &this->subCamEyeNext); Math_Vec3f_Copy(&this->subCamAt, &this->subCamAtNext); @@ -722,7 +722,7 @@ void EnKakasi_PostSongLearnDialogue(EnKakasi* this, PlayState* play) { this->subCamEyeNext.y = D_80971FA0[this->unk190].y; this->subCamEyeNext.z = D_80971FA0[this->unk190].z; Math_Vec3f_Copy(&vec3fCopy, &this->subCamEyeNext); - OLib_DbCameraVec3fSum(&this->picto.actor.home, &vec3fCopy, &this->subCamEyeNext, 1); + OLib_Vec3fAdd(&this->picto.actor.home, &vec3fCopy, &this->subCamEyeNext, OLIB_ADD_OFFSET); this->subCamAtNext.x = D_80971FE8[this->unk190].x + this->unk22C.x; this->subCamAtNext.y = D_80971FE8[this->unk190].y + this->unk22C.y; this->subCamAtNext.z = D_80971FE8[this->unk190].z + this->unk22C.z; @@ -831,7 +831,7 @@ void EnKakasi_DancingNightAway(EnKakasi* this, PlayState* play) { this->subCamEyeNext.y = D_80971E38[this->unk190].y; this->subCamEyeNext.z = D_80971E38[this->unk190].z; Math_Vec3f_Copy(&localVec3f, &this->subCamEyeNext); - OLib_DbCameraVec3fSum(&this->picto.actor.home, &localVec3f, &this->subCamEyeNext, 1); + OLib_Vec3fAdd(&this->picto.actor.home, &localVec3f, &this->subCamEyeNext, OLIB_ADD_OFFSET); if (1) {} this->subCamAtNext.x = D_80971EEC[this->unk190].x + this->unk22C.x; @@ -978,7 +978,7 @@ void EnKakasi_DiggingAway(EnKakasi* this, PlayState* play) { this->subCamEyeNext.z = D_80972030.z; Math_Vec3f_Copy(&tempunk238, &this->subCamEyeNext); - OLib_DbCameraVec3fSum(&this->picto.actor.home, &tempunk238, &this->subCamEyeNext, 1); + OLib_Vec3fAdd(&this->picto.actor.home, &tempunk238, &this->subCamEyeNext, OLIB_ADD_OFFSET); this->subCamAtNext.x = ((f32)D_8097203C.x) + this->unk22C.x; // cast req this->subCamAtNext.y = ((f32)D_8097203C.y) + this->unk22C.y; this->subCamAtNext.z = ((f32)D_8097203C.z) + this->unk22C.z; @@ -1122,7 +1122,7 @@ void EnKakasi_Update(Actor* thisx, PlayState* play) { if (this->unk1BC.x != 0.0f || this->unk1BC.z != 0.0f) { Math_Vec3f_Copy(&this->picto.actor.focus.pos, &this->unk1BC); this->picto.actor.focus.pos.y += 10.0f; - if (this->subCamId == CAM_ID_MAIN) { + if (this->subCamId == SUB_CAM_ID_DONE) { Math_Vec3s_Copy(&this->picto.actor.focus.rot, &this->picto.actor.world.rot); } else { Math_Vec3s_Copy(&this->picto.actor.focus.rot, &this->picto.actor.home.rot); diff --git a/src/overlays/actors/ovl_En_Kendo_Js/z_en_kendo_js.c b/src/overlays/actors/ovl_En_Kendo_Js/z_en_kendo_js.c index c72aa9f5f..c3cdeae33 100644 --- a/src/overlays/actors/ovl_En_Kendo_Js/z_en_kendo_js.c +++ b/src/overlays/actors/ovl_En_Kendo_Js/z_en_kendo_js.c @@ -681,8 +681,8 @@ void func_80B27774(EnKendoJs* this, PlayState* play) { void func_80B2783C(EnKendoJs* this, PlayState* play) { if (this->actor.csId != CS_ID_NONE) { - Camera_ChangeDataIdx(play->cameraPtrs[CAM_ID_MAIN], - CutsceneManager_GetCutsceneEntry(this->actor.csId)->csCamId); + Camera_ChangeActorCsCamIndex(play->cameraPtrs[CAM_ID_MAIN], + CutsceneManager_GetCutsceneEntry(this->actor.csId)->csCamId); } } diff --git a/src/overlays/actors/ovl_En_Minislime/z_en_minislime.c b/src/overlays/actors/ovl_En_Minislime/z_en_minislime.c index 4aa052549..3b6cbaf86 100644 --- a/src/overlays/actors/ovl_En_Minislime/z_en_minislime.c +++ b/src/overlays/actors/ovl_En_Minislime/z_en_minislime.c @@ -174,20 +174,20 @@ void EnMinislime_CheckBackgroundCollision(EnMinislime* this) { } void EnMinislime_AddIceShardEffect(EnMinislime* this) { + s32 pad; EnBigslime* bigslime = (EnBigslime*)this->actor.parent; EnBigslimeIceShardEffect* iceShardEffect; s32 i = 10 * this->id + BIGSLIME_NUM_VTX; s32 i_end = i + 10; - VecSph vecSph; - - vecSph.yaw = 0; + s16 pitch; + s16 yaw = 0; for (; i < i_end; i++) { iceShardEffect = &bigslime->iceShardEffect[i]; - vecSph.pitch = Rand_S16Offset(0x1000, 0x3000); - iceShardEffect->velocity.x = Math_CosS(vecSph.pitch) * Math_SinS(vecSph.yaw); - iceShardEffect->velocity.y = Math_SinS(vecSph.pitch); - iceShardEffect->velocity.z = Math_CosS(vecSph.pitch) * Math_CosS(vecSph.yaw); + pitch = Rand_S16Offset(0x1000, 0x3000); + iceShardEffect->velocity.x = Math_CosS(pitch) * Math_SinS(yaw); + iceShardEffect->velocity.y = Math_SinS(pitch); + iceShardEffect->velocity.z = Math_CosS(pitch) * Math_CosS(yaw); iceShardEffect->pos.x = this->actor.world.pos.x + (400.0f * this->actor.scale.x) * iceShardEffect->velocity.x; iceShardEffect->pos.y = this->actor.world.pos.y + (((iceShardEffect->velocity.y * 2.0f) - 1.0f) * 400.0f * this->actor.scale.y); @@ -198,7 +198,7 @@ void EnMinislime_AddIceShardEffect(EnMinislime* this) { iceShardEffect->isEnabled = true; Math_Vec3f_ScaleAndStore(&iceShardEffect->velocity, Rand_ZeroFloat(3.0f) + 7.0f, &iceShardEffect->velocity); iceShardEffect->scale = (Rand_ZeroFloat(6.0f) + 2.0f) * 0.001f; - vecSph.yaw += 0x1999; + yaw += 0x1999; } this->frozenAlpha = 0; diff --git a/src/overlays/actors/ovl_En_Pamera/z_en_pamera.c b/src/overlays/actors/ovl_En_Pamera/z_en_pamera.c index dab8f591e..b4e7c29e3 100644 --- a/src/overlays/actors/ovl_En_Pamera/z_en_pamera.c +++ b/src/overlays/actors/ovl_En_Pamera/z_en_pamera.c @@ -244,8 +244,8 @@ void func_80BD8758(EnPamera* this, PlayState* play) { if (this->hideInisdeTimer++ > 1800) { if (CutsceneManager_IsNext(this->csIdList[0]) && (this->csIdList[0] != -1)) { CutsceneManager_StartWithPlayerCs(this->csIdList[0], &this->actor); - Camera_SetToTrackActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->csIdList[0])), - &this->actor); + Camera_SetFocalActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->csIdList[0])), + &this->actor); this->actor.speed = 1.5f; Actor_ChangeAnimationByInfo(&this->skelAnime, sAnimationInfo, 1); this->actor.shape.rot.y = this->actor.home.rot.y; @@ -431,8 +431,8 @@ void func_80BD90AC(EnPamera* this, PlayState* play) { (Math_Vec3f_DistXZ(&this->actor.home.pos, &player->actor.world.pos) < 200.0f)))) { if ((CutsceneManager_IsNext(this->csIdList[1])) && ((this->csIdList[1] != -1))) { CutsceneManager_StartWithPlayerCs(this->csIdList[1], &this->actor); - Camera_SetToTrackActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->csIdList[1])), - &this->actor); + Camera_SetFocalActor(Play_GetCamera(play, CutsceneManager_GetCurrentSubCamId(this->csIdList[1])), + &this->actor); EnPamera_LookDownWell(this); } else if (this->csIdList[1] != -1) { CutsceneManager_Queue(this->csIdList[1]); diff --git a/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c b/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c index e38574481..c103d9cc7 100644 --- a/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c +++ b/src/overlays/actors/ovl_En_Pametfrog/z_en_pametfrog.c @@ -1224,10 +1224,10 @@ void EnPametfrog_SetupSnapperSpawn(EnPametfrog* this, PlayState* play) { // Zooms in on Snapper spawn point Play_SetCameraAtEye(play, this->subCamId, &subCamAt, &subCamEye); - this->quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); + this->quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_6); Quake_SetSpeed(this->quakeIndex, 18000); - Quake_SetQuakeValues(this->quakeIndex, 2, 0, 0, 0); - Quake_SetCountdown(this->quakeIndex, 15); + Quake_SetPerturbations(this->quakeIndex, 2, 0, 0, 0); + Quake_SetDuration(this->quakeIndex, 15); Rumble_Request(this->actor.xyzDistToPlayerSq, 120, 20, 10); @@ -1249,12 +1249,12 @@ void EnPametfrog_SnapperSpawn(EnPametfrog* this, PlayState* play) { void EnPametfrog_SetupTransitionGekkoSnapper(EnPametfrog* this, PlayState* play) { this->actor.params = GEKKO_GET_SNAPPER; - Quake_Remove(this->quakeIndex); + Quake_RemoveRequest(this->quakeIndex); - this->quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + this->quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(this->quakeIndex, 20000); - Quake_SetQuakeValues(this->quakeIndex, 17, 0, 0, 0); - Quake_SetCountdown(this->quakeIndex, 12); + Quake_SetPerturbations(this->quakeIndex, 17, 0, 0, 0); + Quake_SetDuration(this->quakeIndex, 12); Rumble_Request(this->actor.xyzDistToPlayerSq, 255, 20, 150); diff --git a/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c b/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c index 35a972dfc..53ae73479 100644 --- a/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c +++ b/src/overlays/actors/ovl_En_Po_Sisters/z_en_po_sisters.c @@ -7,7 +7,7 @@ #include "z_en_po_sisters.h" #include "objects/gameplay_keep/gameplay_keep.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_1000 | ACTOR_FLAG_4000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_4000) #define THIS ((EnPoSisters*)thisx) diff --git a/src/overlays/actors/ovl_En_Poh/z_en_poh.c b/src/overlays/actors/ovl_En_Poh/z_en_poh.c index 95bd2d474..c8da2f1ee 100644 --- a/src/overlays/actors/ovl_En_Poh/z_en_poh.c +++ b/src/overlays/actors/ovl_En_Poh/z_en_poh.c @@ -4,10 +4,11 @@ * Description: Poe */ +#include "prevent_bss_reordering.h" #include "z_en_poh.h" #include "objects/object_po/object_po.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_200 | ACTOR_FLAG_1000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_200 | ACTOR_FLAG_IGNORE_QUAKE) #define THIS ((EnPoh*)thisx) diff --git a/src/overlays/actors/ovl_En_Pr2/z_en_pr2.c b/src/overlays/actors/ovl_En_Pr2/z_en_pr2.c index a1c2f3f4d..1c76d5985 100644 --- a/src/overlays/actors/ovl_En_Pr2/z_en_pr2.c +++ b/src/overlays/actors/ovl_En_Pr2/z_en_pr2.c @@ -151,7 +151,7 @@ void EnPr2_Init(Actor* thisx, PlayState* play) { Actor* parent = this->actor.parent; if (parent->update != NULL) { - this->unk_1C8 = ((EnEncount1*)parent)->unk_15A; + this->unk_1C8 = ((EnEncount1*)parent)->pathIndex; this->path = SubS_GetPathByIndex(play, this->unk_1C8, 0x3F); this->unk_208 = parent->world.rot.z * 20.0f; if (this->unk_208 < 20.0f) { @@ -190,8 +190,8 @@ void EnPr2_Destroy(Actor* thisx, PlayState* play) { if (this->actor.parent != NULL) { EnEncount1* encount1 = (EnEncount1*)this->actor.parent; - if ((encount1->actor.update != NULL) && (encount1->unk_14E > 0)) { - encount1->unk_14E--; + if ((encount1->actor.update != NULL) && (encount1->spawnActiveCount > 0)) { + encount1->spawnActiveCount--; } } } diff --git a/src/overlays/actors/ovl_En_Pr2/z_en_pr2.h b/src/overlays/actors/ovl_En_Pr2/z_en_pr2.h index 617a5cc73..bbcd28afd 100644 --- a/src/overlays/actors/ovl_En_Pr2/z_en_pr2.h +++ b/src/overlays/actors/ovl_En_Pr2/z_en_pr2.h @@ -10,6 +10,8 @@ typedef void (*EnPr2ActionFunc)(struct EnPr2*, PlayState*); #define ENPR2_GET_F(thisx) ((thisx)->params & 0xF) #define ENPR2_GET_FF0(thisx) (((thisx)->params >> 4) & 0xFF) +#define ENPR2_PARAMS(paramF, paramFF0) (((paramF) & 0xF) | (((paramFF0) << 4) & 0xFF0)) + typedef struct EnPr2 { /* 0x000 */ Actor actor; /* 0x144 */ SkelAnime skelAnime; diff --git a/src/overlays/actors/ovl_En_Racedog/z_en_racedog.c b/src/overlays/actors/ovl_En_Racedog/z_en_racedog.c index 3ffde38cd..a8e222bec 100644 --- a/src/overlays/actors/ovl_En_Racedog/z_en_racedog.c +++ b/src/overlays/actors/ovl_En_Racedog/z_en_racedog.c @@ -9,14 +9,13 @@ */ #include "z_en_racedog.h" +#include "overlays/actors/ovl_En_Aob_01/z_en_aob_01.h" #include "overlays/actors/ovl_En_Dg/z_en_dg.h" #define FLAGS (ACTOR_FLAG_10 | ACTOR_FLAG_80000000) #define THIS ((EnRacedog*)thisx) -//! TODO: this file require macros for its uses of weekEventReg - void EnRacedog_Init(Actor* thisx, PlayState* play); void EnRacedog_Destroy(Actor* thisx, PlayState* play); void EnRacedog_Update(Actor* thisx, PlayState* play); @@ -317,7 +316,7 @@ void EnRacedog_Init(Actor* thisx, PlayState* play) { this->path = SubS_GetPathByIndex(play, ENRACEDOG_GET_PATH(&this->actor), 0x3F); Actor_SetScale(&this->actor, 0.0075f); this->actor.gravity = -3.0f; - if (ENRACEDOG_GET_INDEX(&this->actor) < 14) { + if (ENRACEDOG_GET_INDEX(&this->actor) < RACEDOG_COUNT) { this->index = ENRACEDOG_GET_INDEX(&this->actor); } else { Actor_Kill(&this->actor); @@ -353,7 +352,7 @@ void EnRacedog_Init(Actor* thisx, PlayState* play) { this->actor.flags |= ACTOR_FLAG_10; this->actor.flags |= ACTOR_FLAG_20; - sSelectedDogInfo = sDogInfo[(s16)((gSaveContext.eventInf[0] & 0xF8) >> 3)]; + sSelectedDogInfo = sDogInfo[(s16)GET_EVENTINF_DOG_RACE_SELECTED_DOG_INDEX]; this->selectedDogIndex = sSelectedDogInfo.index; EnRacedog_ChangeAnim(&this->skelAnime, sAnimationInfo, RACEDOG_ANIM_IDLE); @@ -439,15 +438,8 @@ void EnRacedog_Race(EnRacedog* this, PlayState* play) { * or an intentional choice to introduce a bit of extra variance to the race. */ void EnRacedog_UpdateTextId(EnRacedog* this) { - // Assuming that the weekEventRegs haven't been tampered with, then this will produce a text ID in the - // range of 0x3539 to 0x3546. - if (this->index % 2) { - sDogInfo[this->index].textId = - (((gSaveContext.save.saveInfo.weekEventReg[42 + (this->index / 2)]) & 0xF0) >> 4) + 0x3539; - } else { - sDogInfo[this->index].textId = - ((gSaveContext.save.saveInfo.weekEventReg[42 + (this->index / 2)]) & 0x0F) + 0x3539; - } + // This will produce a text ID in the range of 0x3539 to 0x3546. + sDogInfo[this->index].textId = GET_WEEKEVENTREG_DOG_RACE_TEXT(this->index, 0x3539); // As a sanity check, this makes sure the text ID is something in the expected range of 0x3539 to 0x3546. if ((sDogInfo[this->index].textId > 0x3546) || (sDogInfo[this->index].textId < 0x3539)) { @@ -593,7 +585,7 @@ void EnRacedog_CheckForFinish(EnRacedog* this) { this->raceStatus = RACEDOG_RACE_STATUS_FINISHED; if (this->index == this->selectedDogIndex) { - gSaveContext.eventInf[0] = (gSaveContext.eventInf[0] & 7) | (sNumberOfDogsFinished * 8); + SET_EVENTINF_DOG_RACE_RACE_STANDING(sNumberOfDogsFinished); } } } diff --git a/src/overlays/actors/ovl_En_Racedog/z_en_racedog.h b/src/overlays/actors/ovl_En_Racedog/z_en_racedog.h index 9d49ea4c2..a8cf2a9f9 100644 --- a/src/overlays/actors/ovl_En_Racedog/z_en_racedog.h +++ b/src/overlays/actors/ovl_En_Racedog/z_en_racedog.h @@ -6,6 +6,7 @@ #define ENRACEDOG_GET_INDEX(thisx) (((thisx)->params & 0x3E0) >> 5) #define ENRACEDOG_GET_PATH(thisx) (((thisx)->params & 0xFC00) >> 10) +#define ENRACEDOG_PARAMS(index, path) ((index << 5) | (path)) /** * The main point of this seems to be some very light anti-cheat detection. The dog diff --git a/src/overlays/actors/ovl_En_Rz/z_en_rz.c b/src/overlays/actors/ovl_En_Rz/z_en_rz.c index c870027bb..a223fe900 100644 --- a/src/overlays/actors/ovl_En_Rz/z_en_rz.c +++ b/src/overlays/actors/ovl_En_Rz/z_en_rz.c @@ -446,7 +446,7 @@ void func_80BFC078(EnRz* this, PlayState* play) { sp28.x = this->actor.projectedPos.x; sp28.y = this->actor.projectedPos.y; sp28.z = this->actor.projectedPos.z; - func_801A1FB4(3, &sp28, NA_BGM_ROSA_SISTERS, 900.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &sp28, NA_BGM_ROSA_SISTERS, 900.0f); } } @@ -547,7 +547,7 @@ void func_80BFC3F8(EnRz* this, PlayState* play) { bgmPos.x = this->actor.projectedPos.x; bgmPos.y = this->actor.projectedPos.y; bgmPos.z = this->actor.projectedPos.z; - func_801A1FB4(3, &bgmPos, NA_BGM_ROSA_SISTERS, 900.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &bgmPos, NA_BGM_ROSA_SISTERS, 900.0f); } } } diff --git a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c index 71eade542..60846fda8 100644 --- a/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c +++ b/src/overlays/actors/ovl_En_Ssh/z_en_ssh.c @@ -708,11 +708,11 @@ void EnSsh_Talk(EnSsh* this, PlayState* play) { void func_809756D0(EnSsh* this, PlayState* play) { u16 nextTextId; - if (CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + if (CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN)) { nextTextId = 0x914; // In here, cursed spiders, defeat them to make me normal } else { nextTextId = 0x910; // Help me! I am not a monster, I was cursed this way - SET_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN); } Message_StartTextbox(play, nextTextId, &this->actor); } diff --git a/src/overlays/actors/ovl_En_Sth/z_en_sth.c b/src/overlays/actors/ovl_En_Sth/z_en_sth.c index f10d387d1..215845341 100644 --- a/src/overlays/actors/ovl_En_Sth/z_en_sth.c +++ b/src/overlays/actors/ovl_En_Sth/z_en_sth.c @@ -148,7 +148,7 @@ void EnSth_Init(Actor* thisx, PlayState* play) { } this->actor.textId = 0; if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH) || - !CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + !CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN)) { this->sthFlags |= STH_FLAG_DRAW_MASK_OF_TRUTH; } break; @@ -479,7 +479,7 @@ void EnSth_GetInitialSwampSpiderHouseText(EnSth* this, PlayState* play) { nextTextId = 0x90F; // (does not exist) EnSth_ChangeAnim(this, STH_ANIM_TALK); } else if (CHECK_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH)) { - if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED)) { + if (!CHECK_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN)) { nextTextId = 0x91B; // As soon as I calm down, getting rid of it } else { nextTextId = 0x918; // I've had enough of this, going home @@ -525,7 +525,7 @@ void EnSth_SwampSpiderHouseGiveMask(EnSth* this, PlayState* play) { } else { this->sthFlags &= ~STH_FLAG_DRAW_MASK_OF_TRUTH; // This flag is used to keep track if the player has already spoken to the actor, triggering secondary dialogue. - SET_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); + SET_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN); Actor_OfferGetItem(&this->actor, play, GI_MASK_TRUTH, 10000.0f, 50.0f); } } @@ -566,7 +566,7 @@ void EnSth_HandleSwampSpiderHouseConversation(EnSth* this, PlayState* play) { case 0x91A: // Someone gave me this mask and said it would make me rich, getting rid of it SET_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH); - CLEAR_WEEKEVENTREG(WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED); + CLEAR_WEEKEVENTREG(WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN); case 0x902: // (does not exist) case 0x903: // (does not exist) diff --git a/src/overlays/actors/ovl_En_Stop_heishi/z_en_stop_heishi.c b/src/overlays/actors/ovl_En_Stop_heishi/z_en_stop_heishi.c index 3716f18d0..dd82ef682 100644 --- a/src/overlays/actors/ovl_En_Stop_heishi/z_en_stop_heishi.c +++ b/src/overlays/actors/ovl_En_Stop_heishi/z_en_stop_heishi.c @@ -195,7 +195,7 @@ void EnStopHeishi_UpdateHeadThirdDay(EnStopheishi* this) { this->headTurnTimer1 = 50; } } - } else if ((this->headTurnTimer1 == 0) && (Quake_NumActiveQuakes() != 0) && (this->headTurnTimer2 >= 6)) { + } else if ((this->headTurnTimer1 == 0) && (Quake_GetNumActiveQuakes() != 0) && (this->headTurnTimer2 >= 6)) { this->headTurnTimer2 = 0; } } diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c index a7cd6617a..196b29263 100644 --- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c +++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c @@ -230,7 +230,7 @@ void EnSuttari_TriggerTransition(PlayState* play, u16 entrance) { play->transitionTrigger = TRANS_TRIGGER_START; } -void EnSuttari_UpdateTime(void) { +void EnSuttari_AdvanceTime(void) { gSaveContext.save.time = ((void)0, gSaveContext.save.time) + (u16)R_TIME_SPEED; gSaveContext.save.time = ((void)0, gSaveContext.save.time) + (u16)((void)0, gSaveContext.save.timeSpeedOffset); } @@ -1483,7 +1483,7 @@ void EnSuttari_Update(Actor* thisx, PlayState* play) { func_80BAB4F0(this, play); } if (this->flags2 & 2) { - EnSuttari_UpdateTime(); + EnSuttari_AdvanceTime(); } if (this->unk428 != 0) { if (this->animIndex == 2 || this->animIndex == 6) { diff --git a/src/overlays/actors/ovl_En_Sw/z_en_sw.c b/src/overlays/actors/ovl_En_Sw/z_en_sw.c index 2662e04fe..8ce0918a1 100644 --- a/src/overlays/actors/ovl_En_Sw/z_en_sw.c +++ b/src/overlays/actors/ovl_En_Sw/z_en_sw.c @@ -504,8 +504,8 @@ s32 func_808D99C8(EnSw* this, PlayState* play) { return false; } - if ((this->actor.xyzDistToPlayerSq < ((sREG(16) * 10) + 60000)) && (play->actorCtx.unk_1F4.timer != 0) && - (play->actorCtx.unk_1F4.unk_00 == 0)) { + if ((this->actor.xyzDistToPlayerSq < ((sREG(16) * 10) + 60000)) && (play->actorCtx.playerImpact.timer != 0) && + (play->actorCtx.playerImpact.type == PLAYER_IMPACT_GORON_GROUND_POUND)) { this->actor.colChkInfo.damage = 4; phi_v1 = true; } diff --git a/src/overlays/actors/ovl_En_Tanron5/z_en_tanron5.c b/src/overlays/actors/ovl_En_Tanron5/z_en_tanron5.c index 0e5b8a0f5..24d036bee 100644 --- a/src/overlays/actors/ovl_En_Tanron5/z_en_tanron5.c +++ b/src/overlays/actors/ovl_En_Tanron5/z_en_tanron5.c @@ -350,7 +350,7 @@ void EnTanron5_Update(Actor* thisx, PlayState* play2) { this->actor.shape.rot.y += phi_v0; Actor_PlaySfx(&this->actor, NA_SE_IT_BIG_BOMB_EXPLOSION); - func_800BC848(&this->actor, play, 4, 4); + Actor_RequestQuakeAndRumble(&this->actor, play, 4, 4); this->unk_1A0++; } else { Vec3f sp90; diff --git a/src/overlays/actors/ovl_En_Test3/z_en_test3.c b/src/overlays/actors/ovl_En_Test3/z_en_test3.c index d5ea5f9df..83d3ce8e1 100644 --- a/src/overlays/actors/ovl_En_Test3/z_en_test3.c +++ b/src/overlays/actors/ovl_En_Test3/z_en_test3.c @@ -478,8 +478,8 @@ void EnTest3_Init(Actor* thisx, PlayState* play2) { if (play->sceneId == SCENE_SECOM) { this->subCamId = Play_CreateSubCamera(play); subCam = Play_GetCamera(play, this->subCamId); - Camera_InitPlayerSettings(subCam, &this->player); - Camera_SetFlags(subCam, CAM_STATE_0 | CAM_STATE_6); + Camera_InitFocalActorSettings(subCam, &this->player.actor); + Camera_SetStateFlag(subCam, CAM_STATE_0 | CAM_STATE_6); Play_ChangeCameraStatus(play, this->subCamId, CAM_STATUS_WAIT); } diff --git a/src/overlays/actors/ovl_En_Test6/z_en_test6.c b/src/overlays/actors/ovl_En_Test6/z_en_test6.c index 42ff16ccf..70ab37232 100644 --- a/src/overlays/actors/ovl_En_Test6/z_en_test6.c +++ b/src/overlays/actors/ovl_En_Test6/z_en_test6.c @@ -425,7 +425,7 @@ void func_80A916F0(EnTest6* this, PlayState* play) { CutsceneManager_Stop(play->playerCsIds[PLAYER_CS_ID_SONG_WARP]); func_800B7298(play, NULL, PLAYER_CSMODE_END); EnTest6_DisableMotionBlur(); - Distortion_ClearType(DISTORTION_TYPE_5); + Distortion_RemoveRequest(DISTORTION_TYPE_SONG_OF_TIME); Actor_Kill(&this->actor); } @@ -491,8 +491,8 @@ void func_80A91760(EnTest6* this, PlayState* play) { } } EnTest6_EnableMotionBlur(120); - Distortion_SetType(DISTORTION_TYPE_5); - Distortion_SetCountdown(80); + Distortion_Request(DISTORTION_TYPE_SONG_OF_TIME); + Distortion_SetDuration(80); play->unk_18844 = true; this->cueId = 95; } @@ -546,7 +546,7 @@ void func_80A91760(EnTest6* this, PlayState* play) { if (this->unk_27A == 10) { this->unk_14C = 0.1f; EnTest6_DisableMotionBlur(); - Distortion_ClearType(DISTORTION_TYPE_5); + Distortion_RemoveRequest(DISTORTION_TYPE_SONG_OF_TIME); play->unk_18844 = false; if (this->unk_254 != NULL) { ZeldaArena_Free(this->unk_254); @@ -646,7 +646,7 @@ void func_80A92118(EnTest6* this, PlayState* play) { CutsceneManager_Stop(play->playerCsIds[PLAYER_CS_ID_SONG_WARP]); func_800B7298(play, NULL, PLAYER_CSMODE_END); EnTest6_DisableMotionBlur(); - Distortion_ClearType(DISTORTION_TYPE_5); + Distortion_RemoveRequest(DISTORTION_TYPE_SONG_OF_TIME); Actor_Kill(&this->actor); } @@ -713,8 +713,8 @@ void func_80A92188(EnTest6* this, PlayState* play) { case 115: EnTest6_EnableMotionBlur(20); - Distortion_SetType(DISTORTION_TYPE_5); - Distortion_SetCountdown(90); + Distortion_Request(DISTORTION_TYPE_SONG_OF_TIME); + Distortion_SetDuration(90); this->cueId = 2; break; @@ -744,7 +744,7 @@ void func_80A92188(EnTest6* this, PlayState* play) { case 14: case 15: EnTest6_EnableMotionBlur(50); - Distortion_ClearType(DISTORTION_TYPE_5); + Distortion_RemoveRequest(DISTORTION_TYPE_SONG_OF_TIME); this->cueId = 0; break; diff --git a/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c b/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c index d472077ec..a26095bc7 100644 --- a/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c +++ b/src/overlays/actors/ovl_En_Thiefbird/z_en_thiefbird.c @@ -7,7 +7,7 @@ #include "prevent_bss_reordering.h" #include "z_en_thiefbird.h" -#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_200 | ACTOR_FLAG_1000 | ACTOR_FLAG_80000000) +#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_200 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_80000000) #define THIS ((EnThiefbird*)thisx) diff --git a/src/overlays/actors/ovl_En_Tru/z_en_tru.c b/src/overlays/actors/ovl_En_Tru/z_en_tru.c index bb146784d..2ba130869 100644 --- a/src/overlays/actors/ovl_En_Tru/z_en_tru.c +++ b/src/overlays/actors/ovl_En_Tru/z_en_tru.c @@ -93,8 +93,14 @@ ActorInit En_Tru_InitVars = { static Vec3f D_80A8B250 = { 0.0f, 0.02f, 0.0f }; static Color_RGBA8 D_80A8B25C[] = { - { 255, 20, 60, 0 }, { 255, 235, 160, 0 }, { 20, 60, 255, 0 }, - { 100, 100, 100, 0 }, { 255, 255, 200, 0 }, { 100, 100, 100, 0 }, + { 255, 20, 60, 0 }, + { 255, 235, 160, 0 }, + { 20, 60, 255, 0 }, +}; +static Color_RGBA8 D_80A8B268[] = { + { 100, 100, 100, 0 }, + { 255, 255, 200, 0 }, + { 100, 100, 100, 0 }, }; static f32 D_80A8B274[] = { 60.0f, 255.0f, 60.0f }; @@ -176,33 +182,33 @@ void func_80A85788(EnTruUnkStruct* arg0, PlayState* play) { func_8012C2DC(play->state.gfxCtx); for (i = 0; i < 30; i++, arg0++) { - if (arg0->unk_00 == 1) { - f32 alpha; + f32 alpha; - if (!flag) { - gSPDisplayList(POLY_XLU_DISP++, D_80A89000); - flag = true; - } - - do { - alpha = (f32)arg0->unk_02 / arg0->unk_01; - alpha *= 255.0f; - } while (0); - - gDPPipeSync(POLY_XLU_DISP++); - gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)alpha); - gSPSegment(POLY_XLU_DISP++, 0x08, - Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, -arg0->unk_02 * 5, 32, 64, 1, 0, 0, 32, 32)); - - Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); - Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); - Matrix_Translate(0.0f, 14.0f, 0.0f, MTXMODE_APPLY); - - gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, D_80A890A8); + if (arg0->unk_00 != 1) { + continue; } + + if (!flag) { + gSPDisplayList(POLY_XLU_DISP++, D_80A89000); + flag = true; + } + + alpha = (f32)arg0->unk_02 / arg0->unk_01; + alpha *= 255.0f; + + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (u8)alpha); + gSPSegment(POLY_XLU_DISP++, 0x08, + Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, -arg0->unk_02 * 5, 32, 64, 1, 0, 0, 32, 32)); + + Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); + Matrix_Translate(0.0f, 14.0f, 0.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, D_80A890A8); } CLOSE_DISPS(play->state.gfxCtx); @@ -227,38 +233,38 @@ void func_80A85AA4(EnTruUnkStruct* arg0, Vec3f* arg1, f32 arg2, f32 arg3, f32 ar } void func_80A85BCC(EnTruUnkStruct* arg0, PlayState* play) { + GraphicsContext* gfxCtx = play->state.gfxCtx; s32 i; s32 flag = false; OPEN_DISPS(play->state.gfxCtx); - if (play) {} func_8012C2DC(play->state.gfxCtx); for (i = 0; i < 30; i++, arg0++) { - if (arg0->unk_00 == 2) { - f32 alpha; + f32 alpha; - if (!flag) { - gDPPipeSync(POLY_XLU_DISP++); - gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 200, 0); - flag = true; - } - - do { - alpha = (f32)arg0->unk_02 / arg0->unk_01; - alpha *= 255.0f; - } while (0); - - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 200, (u8)alpha); - - Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); - Matrix_ReplaceRotation(&play->billboardMtxF); - Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); - - gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - gSPDisplayList(POLY_XLU_DISP++, D_80A8A108); + if (arg0->unk_00 != 2) { + continue; } + + if (!flag) { + gDPPipeSync(POLY_XLU_DISP++); + gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 200, 0); + flag = true; + } + + alpha = (f32)arg0->unk_02 / arg0->unk_01; + alpha *= 255.0f; + + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 200, (u8)alpha); + + Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); + Matrix_ReplaceRotation(&play->billboardMtxF); + Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + gSPDisplayList(POLY_XLU_DISP++, D_80A8A108); } CLOSE_DISPS(play->state.gfxCtx); @@ -282,11 +288,10 @@ void func_80A85E2C(EnTruUnkStruct* arg0, Vec3f* arg1, Vec3f* arg2, Vec3f* arg3, } } -#ifdef NON_MATCHING -// s8/s6 flipped, same deal as above functions but the same fixes don't work void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) { - u8 flag = false; + GraphicsContext* gfxCtx = play->state.gfxCtx; s32 i; + s32 flag = false; OPEN_DISPS(play->state.gfxCtx); @@ -295,50 +300,44 @@ void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) { for (i = 0; i < 30; i++, arg0++) { f32 alpha; s32 index; - - if ((arg0->unk_00 == 3) || (arg0->unk_00 == 4) || (arg0->unk_00 == 5)) { - if (!flag) { - POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); - gSPDisplayList(POLY_XLU_DISP++, gKoumeDustMaterialDL); - flag = true; - } - - Matrix_Push(); - - do { - alpha = (f32)arg0->unk_02 / arg0->unk_01; - alpha *= D_80A8B274[arg0->unk_00 - 3]; - } while (0); - - gDPSetCombineLERP(POLY_XLU_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, 0, TEXEL0, 0, - COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED); - gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_CLD_SURF2); - gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); - gDPPipeSync(POLY_XLU_DISP++); - gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, D_80A8B25C[arg0->unk_00 - 3].r, D_80A8B25C[arg0->unk_00 - 3].g, - D_80A8B25C[arg0->unk_00 - 3].b, (u8)alpha); - gDPSetEnvColor(POLY_XLU_DISP++, D_80A8B25C[arg0->unk_00 - 3].r, D_80A8B25C[arg0->unk_00 - 3].g, - D_80A8B25C[arg0->unk_00 - 3].b, 0); - - Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); - Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); - Matrix_ReplaceRotation(&play->billboardMtxF); - - gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); - index = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f; - gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[index])); - gSPDisplayList(POLY_XLU_DISP++, gKoumeDustModelDL); - - Matrix_Pop(); + if ((arg0->unk_00 != 3) && (arg0->unk_00 != 4) && (arg0->unk_00 != 5)) { + continue; } + + if (!flag) { + POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0); + gSPDisplayList(POLY_XLU_DISP++, gKoumeDustMaterialDL); + flag = true; + } + + Matrix_Push(); + + alpha = (f32)arg0->unk_02 / arg0->unk_01; + alpha *= D_80A8B274[arg0->unk_00 - 3]; + + gDPSetCombineLERP(POLY_XLU_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, PRIMITIVE, 0, TEXEL0, 0, + COMBINED, 0, SHADE, 0, 0, 0, 0, COMBINED); + gDPSetRenderMode(POLY_XLU_DISP++, G_RM_FOG_SHADE_A, G_RM_ZB_CLD_SURF2); + gSPSetGeometryMode(POLY_XLU_DISP++, G_FOG | G_LIGHTING); + gDPPipeSync(POLY_XLU_DISP++); + gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, D_80A8B25C[arg0->unk_00 - 3].r, D_80A8B25C[arg0->unk_00 - 3].g, + D_80A8B25C[arg0->unk_00 - 3].b, (u8)alpha); + gDPSetEnvColor(POLY_XLU_DISP++, D_80A8B268[arg0->unk_00 - 3].r, D_80A8B268[arg0->unk_00 - 3].g, + D_80A8B268[arg0->unk_00 - 3].b, 0); + + Matrix_Translate(arg0->unk_04.x, arg0->unk_04.y, arg0->unk_04.z, MTXMODE_NEW); + Matrix_Scale(arg0->unk_28, arg0->unk_28, 1.0f, MTXMODE_APPLY); + Matrix_ReplaceRotation(&play->billboardMtxF); + + gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + index = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f; + gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[index])); + gSPDisplayList(POLY_XLU_DISP++, gKoumeDustModelDL); + Matrix_Pop(); } CLOSE_DISPS(play->state.gfxCtx); } -#else -void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Tru/func_80A85F84.s") -#endif s32 func_80A86384(EnTruUnkStruct* arg0, Vec3f* arg1) { s32 i; diff --git a/src/overlays/actors/ovl_En_Twig/z_en_twig.c b/src/overlays/actors/ovl_En_Twig/z_en_twig.c index a86359610..b756d0f92 100644 --- a/src/overlays/actors/ovl_En_Twig/z_en_twig.c +++ b/src/overlays/actors/ovl_En_Twig/z_en_twig.c @@ -4,6 +4,7 @@ * Description: Beaver Race Ring */ +#include "prevent_bss_reordering.h" #include "z_en_twig.h" #include "objects/object_twig/object_twig.h" diff --git a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c index 11860c20d..a4b3f7cc6 100644 --- a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c +++ b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.c @@ -191,8 +191,8 @@ void EnWallmas_Destroy(Actor* thisx, PlayState* play) { if (this->actor.parent != NULL) { EnEncount1* encount1 = (EnEncount1*)this->actor.parent; - if ((encount1->actor.update != NULL) && (encount1->unk_14E > 0)) { - encount1->unk_14E--; + if ((encount1->actor.update != NULL) && (encount1->spawnActiveCount > 0)) { + encount1->spawnActiveCount--; } } } diff --git a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.h b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.h index ceb1d1823..93dd63245 100644 --- a/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.h +++ b/src/overlays/actors/ovl_En_Wallmas/z_en_wallmas.h @@ -8,6 +8,8 @@ #define WALLMASTER_GET_SWITCH_FLAG(thisx) (((thisx)->params >> 8) & 0xFF) #define WALLMASTER_IS_FROZEN(thisx) ((thisx)->params & 0x80) +#define WALLMASTER_PARAMS(type, switchFlag, isFrozen) ((type) | (((switchFlag) << 8) & 0xFF) | (((isFrozen) << 7) & 0x80)) + /** * This type determines under what conditions the Wallmaster will drop from the ceiling. * - WALLMASTER_TYPE_TIMER_ONLY: These Wallmasters don't check for anything to determine diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c index 125be5056..209218163 100644 --- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c +++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c @@ -8,8 +8,8 @@ #include "objects/gameplay_keep/gameplay_keep.h" #include "overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h" -#define FLAGS \ - (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_1000 | ACTOR_FLAG_100000 | \ +#define FLAGS \ + (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_IGNORE_QUAKE | ACTOR_FLAG_100000 | \ ACTOR_FLAG_CANT_LOCK_ON | ACTOR_FLAG_80000000) #define THIS ((EnWiz*)thisx) @@ -37,8 +37,8 @@ void EnWiz_SetupDead(EnWiz* this); void EnWiz_Dead(EnWiz* this, PlayState* play); // This number is almost-entirely arbirary, with the only requirement being -// that cannot be a valid curPlatformIndex. Any negative number, or any number -// larger than 10, would work just as well. +// that it cannot be a valid curPlatformIndex. Any negative number, or any +// number larger than 10, would work just as well. #define INITIAL_PLATFORM_INDEX 777 typedef enum { @@ -601,6 +601,9 @@ void EnWiz_SelectPlatform(EnWiz* this, PlayState* play) { break; case EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE: + //! @bug: Setting the Wizrobe's position to the first platform *without* updating + //! this->curPlatformIndex can cause a bug later in EnWiz_Damaged. One way to fix + //! this is to set this->curPlatformIndex to 0 here. Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[0]->world.pos); for (i = 0, ghostAlpha = 128; i < this->platformCount; i++, ghostAlpha -= 10) { Math_Vec3f_Copy(&this->ghostPos[i], &this->actor.world.pos); @@ -1120,6 +1123,17 @@ void EnWiz_Damaged(EnWiz* this, PlayState* play) { this->ghostRot[i].y += this->rotationalVelocity; } + //! @bug: When the Wizrobe is defeated, it is launched into the air by the code above, and the + //! last check in this conditional is intended to check that the Wizrobe is standing on its + //! platform before transitioning to a different state. However, when the fight is in the + //! EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE state, the Wizrobe will always appear on top of + //! the first platform, while its curPlatformIndex is allowed to randomly choose any other + //! platform in the room. If the Wizrobe is defeated in this state (which is possible with a + //! well-timed attack before the cutscene starts), and if the first platform is elevated above + //! other platforms in the room (as it is in the Secret Shrine), then it is possible for + //! this->platforms[this->curPlatformIndex]->world.pos.y to be under the floor compared to the + //! Wizrobe's current position, causing it to get stuck here and never actually die. This can + //! be fixed by addressing the bug in EnWiz_SelectPlatform. if ((this->timer == 1) || ((this->actor.velocity.y < 0.0f) && (this->actor.world.pos.y < (this->platforms[this->curPlatformIndex]->world.pos.y + 11.0f)))) { diff --git a/src/overlays/actors/ovl_En_Zob/z_en_zob.c b/src/overlays/actors/ovl_En_Zob/z_en_zob.c index 5f1b16e35..998c2b186 100644 --- a/src/overlays/actors/ovl_En_Zob/z_en_zob.c +++ b/src/overlays/actors/ovl_En_Zob/z_en_zob.c @@ -588,7 +588,7 @@ void func_80BA0728(EnZob* this, PlayState* play) { sp28.x = this->actor.projectedPos.x; sp28.y = this->actor.projectedPos.y; sp28.z = this->actor.projectedPos.z; - func_801A1FB4(3, &sp28, 0x6C, 1000.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &sp28, NA_BGM_BASS_PLAY, 1000.0f); } void func_80BA08E8(EnZob* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_En_Zod/z_en_zod.c b/src/overlays/actors/ovl_En_Zod/z_en_zod.c index aaf3b85f0..826664a9a 100644 --- a/src/overlays/actors/ovl_En_Zod/z_en_zod.c +++ b/src/overlays/actors/ovl_En_Zod/z_en_zod.c @@ -387,7 +387,7 @@ void EnZod_PlayDrumsSequence(EnZod* this, PlayState* play) { seqPos.y = this->actor.projectedPos.y; seqPos.z = this->actor.projectedPos.z; - func_801A1FB4(3, &seqPos, NA_BGM_DRUMS_PLAY, 700.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &seqPos, NA_BGM_DRUMS_PLAY, 700.0f); } void func_80BAFA44(EnZod* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_En_Zos/z_en_zos.c b/src/overlays/actors/ovl_En_Zos/z_en_zos.c index 3c11d1bce..039c2a3e6 100644 --- a/src/overlays/actors/ovl_En_Zos/z_en_zos.c +++ b/src/overlays/actors/ovl_En_Zos/z_en_zos.c @@ -582,7 +582,7 @@ void func_80BBBDE0(EnZos* this, PlayState* play) { sp28.x = this->actor.projectedPos.x; sp28.y = this->actor.projectedPos.y; sp28.z = this->actor.projectedPos.z; - func_801A1FB4(3, &sp28, 110, 1000.0f); + func_801A1FB4(SEQ_PLAYER_BGM_SUB, &sp28, NA_BGM_PIANO_PLAY, 1000.0f); } void func_80BBBFBC(EnZos* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_Obj_Chan/z_obj_chan.c b/src/overlays/actors/ovl_Obj_Chan/z_obj_chan.c index 66c927f1d..facd8de41 100644 --- a/src/overlays/actors/ovl_Obj_Chan/z_obj_chan.c +++ b/src/overlays/actors/ovl_Obj_Chan/z_obj_chan.c @@ -117,16 +117,16 @@ u32 func_80BB9A1C(ObjChan* this, f32 arg1) { f32 sp20; sp20 = Math_SinS(this->unk1D4) * this->unk1D0; - temp_f6 = (Math_CosS(this->unk1D4) * 0.03834952f * this->unk1D0) + arg1; + temp_f6 = (Math_CosS(this->unk1D4) * (400 * M_PI / 0x8000) * this->unk1D0) + arg1; if (temp_f6 != 0.0f) { - this->unk1D4 = RAD_TO_BINANG(func_80086B30(sp20 * 0.03834952f, temp_f6)); + this->unk1D4 = RAD_TO_BINANG(func_80086B30(sp20 * (400 * M_PI / 0x8000), temp_f6)); } else if (sp20 >= 0.0f) { this->unk1D4 = 0x4000; } else { this->unk1D4 = -0x4000; } if (Math_CosS(this->unk1D4) != 0.0f) { - this->unk1D0 = (temp_f6 / (Math_CosS(this->unk1D4) * 0.03834952f)); + this->unk1D0 = (temp_f6 / (Math_CosS(this->unk1D4) * (400 * M_PI / 0x8000))); } else { this->unk1D0 = sp20; } diff --git a/src/overlays/actors/ovl_Obj_Chikuwa/z_obj_chikuwa.c b/src/overlays/actors/ovl_Obj_Chikuwa/z_obj_chikuwa.c index b4b27784e..79007175d 100644 --- a/src/overlays/actors/ovl_Obj_Chikuwa/z_obj_chikuwa.c +++ b/src/overlays/actors/ovl_Obj_Chikuwa/z_obj_chikuwa.c @@ -174,7 +174,7 @@ void ObjChikuwa_Update(Actor* thisx, PlayState* play) { func_809B17D0(play, this, &temp->unk_00); temp_fs0 = Math3D_Vec3fDistSq(&temp->unk_00, &GET_PLAYER(play)->actor.world.pos); if (temp_fs0 < SQ(240.0f)) { - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); if (temp_fs0 < SQ(120.0f)) { quakeVerticalMag = 4; } else { @@ -182,8 +182,8 @@ void ObjChikuwa_Update(Actor* thisx, PlayState* play) { } Quake_SetSpeed(quakeIndex, 17232); - Quake_SetQuakeValues(quakeIndex, quakeVerticalMag, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 7); + Quake_SetPerturbations(quakeIndex, quakeVerticalMag, 0, 0, 0); + Quake_SetDuration(quakeIndex, 7); } } } diff --git a/src/overlays/actors/ovl_Obj_Dhouse/z_obj_dhouse.c b/src/overlays/actors/ovl_Obj_Dhouse/z_obj_dhouse.c index c942f622b..0dba9a21f 100644 --- a/src/overlays/actors/ovl_Obj_Dhouse/z_obj_dhouse.c +++ b/src/overlays/actors/ovl_Obj_Dhouse/z_obj_dhouse.c @@ -458,20 +458,20 @@ void func_80B139F4(ObjDhouse* this, PlayState* play) { s16 quakeIndex; if (this->unk_1370 == 117) { - quakeIndex = Quake_Add(camera, QUAKE_TYPE_3); + quakeIndex = Quake_Request(camera, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 8, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 17); + Quake_SetPerturbations(quakeIndex, 8, 0, 0, 0); + Quake_SetDuration(quakeIndex, 17); } else if (this->unk_1370 == 105) { - quakeIndex = Quake_Add(camera, QUAKE_TYPE_3); + quakeIndex = Quake_Request(camera, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 7, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 20); + Quake_SetPerturbations(quakeIndex, 7, 0, 0, 0); + Quake_SetDuration(quakeIndex, 20); } else if (this->unk_1370 == 90) { - quakeIndex = Quake_Add(camera, QUAKE_TYPE_3); + quakeIndex = Quake_Request(camera, QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 5, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 62); + Quake_SetPerturbations(quakeIndex, 5, 0, 0, 0); + Quake_SetDuration(quakeIndex, 62); } this->unk_1370--; diff --git a/src/overlays/actors/ovl_Obj_Dora/z_obj_dora.c b/src/overlays/actors/ovl_Obj_Dora/z_obj_dora.c index 836a70ba9..f3c271c69 100644 --- a/src/overlays/actors/ovl_Obj_Dora/z_obj_dora.c +++ b/src/overlays/actors/ovl_Obj_Dora/z_obj_dora.c @@ -281,7 +281,7 @@ void ObjDora_UpdateCollision(ObjDora* this, PlayState* play) { this->lastGongHitType = DORA_HIT_STRONG; } - func_800BC848(&this->actor, play, 5, 10); + Actor_RequestQuakeAndRumble(&this->actor, play, 5, 10); ObjDora_SetupMoveGong(this); if ((ObjDora_IsHalfHour(time) == true) && (this->rupeeDropTimer == 0)) { diff --git a/src/overlays/actors/ovl_Obj_Hariko/z_obj_hariko.c b/src/overlays/actors/ovl_Obj_Hariko/z_obj_hariko.c index 1c33af7fe..a2007ad9b 100644 --- a/src/overlays/actors/ovl_Obj_Hariko/z_obj_hariko.c +++ b/src/overlays/actors/ovl_Obj_Hariko/z_obj_hariko.c @@ -74,7 +74,7 @@ void ObjHariko_BobHead(ObjHariko* this, PlayState* play) { } void ObjHariko_CheckForQuakes(ObjHariko* this) { - if (Quake_NumActiveQuakes() != 0) { + if (Quake_GetNumActiveQuakes() != 0) { ObjHariko_SetupBobHead(this); } } diff --git a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c index e69729b92..692fa8448 100644 --- a/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c +++ b/src/overlays/actors/ovl_Obj_Hugebombiwa/z_obj_hugebombiwa.c @@ -293,13 +293,13 @@ void func_80A54600(PlayState* play, Vec3f* arg1, f32 arg2, f32 arg3) { } } -void ObjHugebombiwa_AddQuake(ObjHugebombiwa* this, PlayState* play, s32 quakeVerticalMag) { +void ObjHugebombiwa_RequestQuakeAndRumble(ObjHugebombiwa* this, PlayState* play, s32 quakeVerticalMag) { s32 pad[2]; - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, quakeVerticalMag, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 7); + Quake_SetPerturbations(quakeIndex, quakeVerticalMag, 0, 0, 0); + Quake_SetDuration(quakeIndex, 7); Rumble_Request(this->actor.xyzDistToPlayerSq, 255, 20, 150); } @@ -516,7 +516,7 @@ void func_80A55064(ObjHugebombiwa* this, PlayState* play) { ptr->unk_24 = 1; func_80A53E60(play, &ptr->unk_0C, ptr->unk_18, ptr->unk_00.y * 9.8f); if ((play->gameplayFrames % 4) == 0) { - ObjHugebombiwa_AddQuake(this, play, (s32)(Rand_ZeroOne() * 5.5f) + 1); + ObjHugebombiwa_RequestQuakeAndRumble(this, play, (s32)(Rand_ZeroOne() * 5.5f) + 1); } } } @@ -612,7 +612,7 @@ void func_80A55564(ObjHugebombiwa* this, PlayState* play) { ptr->unk_24 = 1; func_80A54600(play, &ptr->unk_0C, ptr->unk_18, ptr->unk_00.y * 10.1f); if ((play->gameplayFrames % 4) == 0) { - ObjHugebombiwa_AddQuake(this, play, (s32)(Rand_ZeroOne() * 5.5f) + 1); + ObjHugebombiwa_RequestQuakeAndRumble(this, play, (s32)(Rand_ZeroOne() * 5.5f) + 1); } } } diff --git a/src/overlays/actors/ovl_Obj_Lift/z_obj_lift.c b/src/overlays/actors/ovl_Obj_Lift/z_obj_lift.c index a82c9ceea..88d04b780 100644 --- a/src/overlays/actors/ovl_Obj_Lift/z_obj_lift.c +++ b/src/overlays/actors/ovl_Obj_Lift/z_obj_lift.c @@ -134,10 +134,10 @@ void func_8093D7A0(ObjLift* this, PlayState* play) { if (OBJLIFT_GET_7(&this->dyna.actor) == 7) { func_8093D9C0(this); } else { - quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_1); + quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_1); Quake_SetSpeed(quakeIndex, 10000); - Quake_SetQuakeValues(quakeIndex, 2, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 20); + Quake_SetPerturbations(quakeIndex, 2, 0, 0, 0); + Quake_SetDuration(quakeIndex, 20); func_8093D88C(this); } diff --git a/src/overlays/actors/ovl_Obj_Nozoki/z_obj_nozoki.c b/src/overlays/actors/ovl_Obj_Nozoki/z_obj_nozoki.c index 7f7f9550a..d5dfed84d 100644 --- a/src/overlays/actors/ovl_Obj_Nozoki/z_obj_nozoki.c +++ b/src/overlays/actors/ovl_Obj_Nozoki/z_obj_nozoki.c @@ -4,6 +4,7 @@ * Description: Sakon's Hideout Objects (Sun's Mask, doors, etc) */ +#include "prevent_bss_reordering.h" #include "z_obj_nozoki.h" #include "objects/object_secom_obj/object_secom_obj.h" diff --git a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c index 6cdada70b..d5aeffd8f 100644 --- a/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c +++ b/src/overlays/actors/ovl_Obj_Tokei_Step/z_obj_tokei_step.c @@ -61,13 +61,13 @@ void ObjTokeiStep_SetSysMatrix(ObjTokeiStepPanel* panel) { mtx->zw = panel->pos.z; } -void ObjTokeiStep_AddQuake(ObjTokeiStep* this, PlayState* play) { +void ObjTokeiStep_RequestQuakeAndRumble(ObjTokeiStep* this, PlayState* play) { s32 pad[2]; - s16 quakeIndex = Quake_Add(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); + s16 quakeIndex = Quake_Request(GET_ACTIVE_CAM(play), QUAKE_TYPE_3); Quake_SetSpeed(quakeIndex, 20000); - Quake_SetQuakeValues(quakeIndex, 1, 0, 0, 0); - Quake_SetCountdown(quakeIndex, 7); + Quake_SetPerturbations(quakeIndex, 1, 0, 0, 0); + Quake_SetDuration(quakeIndex, 7); Rumble_Request(this->dyna.actor.xyzDistToPlayerSq, 120, 20, 10); } @@ -180,7 +180,7 @@ s32 ObjTokeiStep_OpenProcess(ObjTokeiStep* this, PlayState* play) { } if (panel->numBounces == 1) { ObjTokeiStep_SpawnDust(this2, panel, play); - ObjTokeiStep_AddQuake(this2, play); + ObjTokeiStep_RequestQuakeAndRumble(this2, play); } } } diff --git a/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c b/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c index 93caeb33d..f869b95ac 100644 --- a/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c +++ b/src/overlays/actors/ovl_Oceff_Wipe5/z_oceff_wipe5.c @@ -72,7 +72,7 @@ void OceffWipe5_Draw(Actor* thisx, PlayState* play) { s32 i; s32 pad2; Vec3f activeCamEye = GET_ACTIVE_CAM(play)->eye; - Camera* cam = GET_ACTIVE_CAM(play); + Camera* activeCam = GET_ACTIVE_CAM(play); Vec3f quakeOffset; u8 alpha; s32 colorIndex = OCEFF_WIPE5_GET_SONG_TYPE(thisx) * 3; @@ -88,7 +88,7 @@ void OceffWipe5_Draw(Actor* thisx, PlayState* play) { colorIndex = 0; } - Camera_GetQuakeOffset(&quakeOffset, cam); + Camera_GetQuakeOffset(&quakeOffset, activeCam); if (this->counter < 32) { z = Math_SinS(this->counter << 9) * phi_fv1; diff --git a/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c b/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c index 5523ded78..6279c367e 100644 --- a/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c +++ b/src/overlays/actors/ovl_TG_Sw/z_tg_sw.c @@ -34,18 +34,17 @@ ActorInit TG_Sw_InitVars = { void TGSw_ActionDecider(TGSw* this, PlayState* play) { f32 scaledAbsoluteRotZ; f32 scaledAbsoluteRotY; - u8 unk1F4; + PlayerImpactType playerImpactType; - // Maybe actorCtx Debug Flag? - if (play->actorCtx.unk_1F4.timer != 0) { + if (play->actorCtx.playerImpact.timer != 0) { scaledAbsoluteRotY = ABS_ALT(this->actor.world.rot.y) * 4.0f; scaledAbsoluteRotZ = ABS_ALT(this->actor.world.rot.z) * 4.0f; if ((scaledAbsoluteRotZ < this->actor.xzDistToPlayer) || (scaledAbsoluteRotY < this->actor.playerHeightRel)) { return; } - unk1F4 = play->actorCtx.unk_1F4.unk_00; - if (unk1F4 == 2 || unk1F4 == 0) { + playerImpactType = play->actorCtx.playerImpact.type; + if ((playerImpactType == PLAYER_IMPACT_BONK) || (playerImpactType == PLAYER_IMPACT_GORON_GROUND_POUND)) { this->actionFunc = TGSw_ActionExecuteOneShot; } } diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_collect.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_collect.c index fe72ee840..75c031c0a 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_collect.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_collect.c @@ -62,9 +62,6 @@ s16 sQuestRemainsEnvBlue[] = { 150, // Unused }; -#ifdef NON_EQUIVALENT -// TODO: is actually NON_MATCHING, update once `z_kaleido_scope_NES.c` is decompiled -// A single small regalloc at the first `Gfx_DrawTexQuadIA8` for the heart piece count (see `gItemIcons`) void KaleidoScope_DrawQuestStatus(PlayState* play) { static s16 sQuestRemainsColorTimer = 20; static s16 sQuestRemainsColorTimerIndex = 0; @@ -135,10 +132,11 @@ void KaleidoScope_DrawQuestStatus(PlayState* play) { s16 k; s16 skullTokenDigits[3]; u16 isDigitDrawn; + u32* questItemsPtr; OPEN_DISPS(play->state.gfxCtx); - KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_QUEST] * 4, pauseCtx->questVtx); + KaleidoScope_SetCursorVtxPos(pauseCtx, pauseCtx->cursorSlot[PAUSE_QUEST] * 4, pauseCtx->questVtx); gDPPipeSync(POLY_OPA_DISP++); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); @@ -321,7 +319,12 @@ void KaleidoScope_DrawQuestStatus(PlayState* play) { } } - if ((GET_SAVE_INVENTORY_QUEST_ITEMS >> QUEST_HEART_PIECE_COUNT) != 0) { + //! FAKE: Used to load `0xF0000000` early + if ((GET_SAVE_INVENTORY_QUEST_ITEMS & 0xF0000000) != 0) {} + questItemsPtr = &gSaveContext.save.saveInfo.inventory.questItems; + if (1) {} + + if ((*questItemsPtr >> QUEST_HEART_PIECE_COUNT) != 0) { gDPPipeSync(POLY_OPA_DISP++); gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0); @@ -391,7 +394,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play) { POLY_OPA_DISP, sOcarinaButtonTextures[sQuestSongPlayedOcarinaButtons[i]], 16, 16, 0); } } - } else if (IS_PAUSE_MAIN_STATE_SAVE_PROMPT || (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) { + } else if (IS_PAUSE_MAIN_STATE_SONG_PROMPT || (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) { // Draw the buttons for playing a song sp1C8 = pauseCtx->ocarinaSongIndex; sp1CA = gOcarinaSongButtons[sp1C8].numButtons; @@ -548,34 +551,6 @@ void KaleidoScope_DrawQuestStatus(PlayState* play) { CLOSE_DISPS(play->state.gfxCtx); } -#else -s16 sQuestRemainsColorTimer = 20; -s16 sQuestRemainsColorTimerIndex = 0; -s16 sQuestHpPrimRed = 0; -s16 sQuestHpPrimGreen = 0; -s16 sQuestHpPrimBlue = 0; -s16 sQuestHpPrimAlpha = 0; -s16 sQuestHpColorTimer = 20; -s16 sQuestHpPrimColorTargetIndex = 0; -TexturePtr sOcarinaButtonTextures[] = { - gOcarinaATex, gOcarinaCDownTex, gOcarinaCRightTex, gOcarinaCLeftTex, gOcarinaCUpTex, -}; -s16 sQuestSongsPrimRed[] = { - 150, 255, 100, 255, 255, 255, 255, 255, 255, 255, 255, 255, -}; -s16 sQuestSongsPrimGreen[] = { - 255, 80, 150, 160, 100, 240, 255, 255, 255, 255, 255, 255, -}; -s16 sQuestSongsPrimBlue[] = { - 100, 40, 255, 0, 255, 100, 255, 255, 255, 255, 255, 255, -}; -TexturePtr sQuestUpgradeTextures[][3] = { - { 0x08053000, 0x08054000, 0x08055000 }, - { 0x08056000, 0x08057000, 0x08058000 }, -}; -u8 sQuestUpgrades[] = { UPG_QUIVER, UPG_BOMB_BAG }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_DrawQuestStatus.s") -#endif typedef enum { /* -3 */ CURSOR_TO_LEFT = -3, // Cursor on the "scroll to left page" position diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_item.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_item.c index 149b72444..cfcaf20ea 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_item.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_item.c @@ -15,7 +15,7 @@ s16 sEquipMagicArrowSlotHoldTimer = 0; // Number of frames to move icon from slot to target position when equipping. s16 sEquipAnimTimer = 10; -u8 gPlayerFormSlotRestrictions[PLAYER_FORM_MAX][NUM_ITEM_SLOTS] = { +u8 gPlayerFormSlotRestrictions[PLAYER_FORM_MAX][ITEM_NUM_SLOTS] = { // Fierce Deity { false, // SLOT_OCARINA @@ -236,9 +236,9 @@ void KaleidoScope_DrawAmmoCount(PauseContext* pauseCtx, GraphicsContext* gfxCtx, CLOSE_DISPS(gfxCtx); } -void KaleidoScope_SetCursorVtx(PauseContext* pauseCtx, u16 index, Vtx* vtx) { - pauseCtx->cursorVtx[0].v.ob[0] = vtx[index].v.ob[0]; - pauseCtx->cursorVtx[0].v.ob[1] = vtx[index].v.ob[1]; +void KaleidoScope_SetCursorVtxPos(PauseContext* pauseCtx, u16 vtxIndex, Vtx* vtx) { + pauseCtx->cursorVtx[0].v.ob[0] = vtx[vtxIndex].v.ob[0]; + pauseCtx->cursorVtx[0].v.ob[1] = vtx[vtxIndex].v.ob[1]; } static s16 sMagicArrowEffectsR[] = { 255, 100, 255 }; @@ -258,9 +258,9 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { // Loop over c-buttons (i) and vtx offset (j) gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - for (i = 0, j = NUM_ITEM_SLOTS * 4; i < 3; i++, j += 4) { + for (i = 0, j = ITEM_NUM_SLOTS * 4; i < 3; i++, j += 4) { if (GET_CUR_FORM_BTN_ITEM(i + 1) != ITEM_NONE) { - if (GET_CUR_FORM_BTN_SLOT(i + 1) < NUM_ITEM_SLOTS) { + if (GET_CUR_FORM_BTN_SLOT(i + 1) < ITEM_NUM_SLOTS) { gSPVertex(POLY_OPA_DISP++, &pauseCtx->itemVtx[j], 4, 0); POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); } @@ -272,7 +272,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { // Draw the item icons // Loop over slots (i) and vtx offset (j) gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - for (j = 0, i = 0; i < NUM_ITEM_SLOTS; i++, j += 4) { + for (j = 0, i = 0; i < ITEM_NUM_SLOTS; i++, j += 4) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); if (((void)0, gSaveContext.save.saveInfo.inventory.items[i]) != ITEM_NONE) { @@ -323,7 +323,7 @@ void KaleidoScope_DrawItemSelect(PlayState* play) { gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); // Loop over slots (i) and ammoIndex (j) - for (j = 0, i = 0; i < NUM_ITEM_SLOTS; i++) { + for (j = 0, i = 0; i < ITEM_NUM_SLOTS; i++) { if (gAmmoItems[i] != ITEM_NONE) { if (((void)0, gSaveContext.save.saveInfo.inventory.items[i]) != ITEM_NONE) { KaleidoScope_DrawAmmoCount(pauseCtx, play->state.gfxCtx, @@ -398,7 +398,7 @@ void KaleidoScope_UpdateItemCursor(PlayState* play) { pauseCtx->cursorPoint[PAUSE_ITEM] = pauseCtx->cursorXIndex[PAUSE_ITEM] + (pauseCtx->cursorYIndex[PAUSE_ITEM] * 6); - if (pauseCtx->cursorPoint[PAUSE_ITEM] >= NUM_ITEM_SLOTS) { + if (pauseCtx->cursorPoint[PAUSE_ITEM] >= ITEM_NUM_SLOTS) { pauseCtx->cursorPoint[PAUSE_ITEM] = pauseCtx->cursorXIndex[PAUSE_ITEM]; } @@ -429,7 +429,7 @@ void KaleidoScope_UpdateItemCursor(PlayState* play) { pauseCtx->cursorPoint[PAUSE_ITEM] = pauseCtx->cursorXIndex[PAUSE_ITEM] + (pauseCtx->cursorYIndex[PAUSE_ITEM] * 6); - if (pauseCtx->cursorPoint[PAUSE_ITEM] >= NUM_ITEM_SLOTS) { + if (pauseCtx->cursorPoint[PAUSE_ITEM] >= ITEM_NUM_SLOTS) { pauseCtx->cursorPoint[PAUSE_ITEM] = pauseCtx->cursorXIndex[PAUSE_ITEM]; } @@ -737,7 +737,7 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { } if (sEquipState == EQUIP_STATE_MAGIC_ARROW_MOVE_TO_BOW_SLOT) { - bowItemVtx = &pauseCtx->itemVtx[4]; + bowItemVtx = &pauseCtx->itemVtx[SLOT_BOW * 4]; offsetX = ABS_ALT(pauseCtx->equipAnimX - bowItemVtx->v.ob[0] * 10) / sEquipAnimTimer; offsetY = ABS_ALT(pauseCtx->equipAnimY - bowItemVtx->v.ob[1] * 10) / sEquipAnimTimer; } else { @@ -761,13 +761,13 @@ void KaleidoScope_UpdateItemEquip(PlayState* play) { // Update coordinates of item icon while being equipped if (sEquipState == EQUIP_STATE_MAGIC_ARROW_MOVE_TO_BOW_SLOT) { // target is the bow slot - if (pauseCtx->equipAnimX >= (pauseCtx->itemVtx[4].v.ob[0] * 10)) { + if (pauseCtx->equipAnimX >= (pauseCtx->itemVtx[SLOT_BOW * 4].v.ob[0] * 10)) { pauseCtx->equipAnimX -= offsetX; } else { pauseCtx->equipAnimX += offsetX; } - if (pauseCtx->equipAnimY >= (pauseCtx->itemVtx[4].v.ob[1] * 10)) { + if (pauseCtx->equipAnimY >= (pauseCtx->itemVtx[SLOT_BOW * 4].v.ob[1] * 10)) { pauseCtx->equipAnimY -= offsetY; } else { pauseCtx->equipAnimY += offsetY; diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c index ab598723f..af12f2d5d 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_map.c @@ -10,14 +10,8 @@ #include "interface/icon_item_dungeon_static/icon_item_dungeon_static.h" #include "interface/icon_item_jpn_static/icon_item_jpn_static.h" -extern s16 D_8082B7F0[]; -extern s16 D_8082B838[]; - extern TexturePtr D_09007500; // gPlayerFaceIcon -#define WORLD_MAP_IMAGE_TEX_WIDTH 216 -#define WORLD_MAP_IMAGE_TEX_HEIGHT 128 - void KaleidoScope_DrawDungeonStrayFairyCount(PlayState* play) { s16 counterDigits[2]; s16 rectLeft; @@ -142,8 +136,8 @@ void KaleidoScope_DrawDungeonMap(PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - j = 72 + (pauseCtx->cursorSlot[PAUSE_MAP] * 4); - KaleidoScope_SetCursorVtx(pauseCtx, j, pauseCtx->mapPageVtx); + j = (QUAD_MAP_PAGE_DUNGEON_MAP + pauseCtx->cursorSlot[PAUSE_MAP]) * 4; + KaleidoScope_SetCursorVtxPos(pauseCtx, j, pauseCtx->mapPageVtx); pauseCtx->cursorItem[PAUSE_MAP] = PAUSE_ITEM_NONE; if (pauseCtx->cursorSpecialPos == 0) { @@ -153,11 +147,19 @@ void KaleidoScope_DrawDungeonMap(PlayState* play) { pauseCtx->cursorSlot[PAUSE_MAP] = pauseCtx->cursorPoint[PAUSE_MAP]; } + // Set vertices for: + // QUAD_MAP_PAGE_DUNGEON_TITLE, + // QUAD_MAP_PAGE_DUNGEON_BOSS_KEY, + // QUAD_MAP_PAGE_DUNGEON_COMPASS, + // QUAD_MAP_PAGE_DUNGEON_MAP gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[60], 16, 0); + + // Dungeon Title gDPPipeSync(POLY_OPA_DISP++); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA, G_CC_MODULATEIA); + // QUAD_MAP_PAGE_DUNGEON_TITLE POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, sDungeonTitleTextures[((void)0, gSaveContext.dungeonIndex)], 128, 16, 0); @@ -211,6 +213,7 @@ void KaleidoScope_DrawDungeonMap(PlayState* play) { gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + // QUAD_MAP_PAGE_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE pauseCtx->mapPageVtx[76].v.ob[0] = pauseCtx->mapPageVtx[78].v.ob[0] = -16; pauseCtx->mapPageVtx[77].v.ob[0] = pauseCtx->mapPageVtx[79].v.ob[0] = @@ -221,7 +224,8 @@ void KaleidoScope_DrawDungeonMap(PlayState* play) { pauseCtx->mapPageVtx[78].v.ob[1] = pauseCtx->mapPageVtx[79].v.ob[1] = pauseCtx->mapPageVtx[76].v.ob[1] - 24; - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[76], 4, 0); + gSPVertex(POLY_OPA_DISP++, + &pauseCtx->mapPageVtx[QUAD_MAP_PAGE_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE * 4], 4, 0); POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, gStrayFairyGlowingCircleIconTex, G_IM_FMT_I, 32, 24, 0); @@ -258,6 +262,9 @@ void KaleidoScope_DrawDungeonMap(PlayState* play) { G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + // QUAD_MAP_PAGE_DUNGEON_BOSS_KEY + // QUAD_MAP_PAGE_DUNGEON_COMPASS + // QUAD_MAP_PAGE_DUNGEON_MAP gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } } @@ -486,6 +493,7 @@ s16 sWorldMapDotPrimColors[][3] = { { 0, 0, 255 }, { 255, 255, 0 }, }; + s16 sWorldMapDotEnvColors[][3] = { { 255, 255, 0 }, { 0, 0, 255 }, @@ -537,7 +545,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_MAP] * 4, pauseCtx->mapPageVtx); + KaleidoScope_SetCursorVtxPos(pauseCtx, pauseCtx->cursorSlot[PAUSE_MAP] * 4, pauseCtx->mapPageVtx); // Draw the world map image if ((pauseCtx->pageIndex == PAUSE_MAP) && (pauseCtx->state == PAUSE_STATE_MAIN) && @@ -561,12 +569,12 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { // Process the 128 rows of pixels for gWorldMapImageTex, 8 rows at a time over 16 iterations // Loop over yPos (t), textureIndex (j) for (t = 62, j = 0; j < 16; j++, t += 8) { - gDPLoadTextureBlock(POLY_OPA_DISP++, (u8*)gWorldMapImageTex + j * (WORLD_MAP_IMAGE_TEX_WIDTH * 8), - G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_TEX_WIDTH, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, + gDPLoadTextureBlock(POLY_OPA_DISP++, (u8*)gWorldMapImageTex + j * (WORLD_MAP_IMAGE_WIDTH * 8), G_IM_FMT_CI, + G_IM_SIZ_8b, WORLD_MAP_IMAGE_WIDTH, 8, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); rectLeft = 51 << 2; - rectRight = rectLeft + (WORLD_MAP_IMAGE_TEX_WIDTH << 2); + rectRight = rectLeft + (WORLD_MAP_IMAGE_WIDTH << 2); gSPTextureRectangle(POLY_OPA_DISP++, rectLeft, t << 2, rectRight, (t << 2) + (8 << 2), G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10); } @@ -593,36 +601,39 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); // Set the vertices for the first 8 quads attached to the world map texture. - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[204], 8 * 4, 0); + gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[QUAD_MAP_PAGE_WORLD_IMAGE_FIRST * 4], 8 * 4, 0); // Process the first 72 rows of pixels for gWorldMapImageTex, 9 rows at a time over 8 iterations // Loop over quadIndex of this loop (i), quadIndex of the entire texture (k), vtxIndex (j) for (i = 0, k = 0, j = 0; i < 8; i++, k++, j += 4) { - gDPLoadTextureBlock(POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_TEX_WIDTH * 9), - G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_TEX_WIDTH, 9, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlock( + POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_WIDTH * WORLD_MAP_IMAGE_FRAG_HEIGHT), + G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_WIDTH, WORLD_MAP_IMAGE_FRAG_HEIGHT, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } // Set the vertices for the last 7 quads attached to the world map texture: // 6 quads with a height of 9, 1 quad with a height of 2 - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[236], (6 + 1) * 4, 0); + gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[(QUAD_MAP_PAGE_WORLD_IMAGE_FIRST + 8) * 4], (6 + 1) * 4, 0); // Process the next 54 rows of pixels for gWorldMapImageTex, 9 rows at a time over 6 iterations // Loop over quadIndex of this loop (i), quadIndex of the entire texture (k), vtxIndex (j) for (i = 0, j = 0; i < 6; i++, k++, j += 4) { - gDPLoadTextureBlock(POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_TEX_WIDTH * 9), - G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_TEX_WIDTH, 9, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlock( + POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_WIDTH * WORLD_MAP_IMAGE_FRAG_HEIGHT), + G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_WIDTH, WORLD_MAP_IMAGE_FRAG_HEIGHT, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } // Process the last 2 rows of pixels for gWorldMapImageTex - gDPLoadTextureBlock(POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_TEX_WIDTH * 9), G_IM_FMT_CI, - G_IM_SIZ_8b, WORLD_MAP_IMAGE_TEX_WIDTH, 2, 0, G_TX_NOMIRROR | G_TX_WRAP, - G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gDPLoadTextureBlock( + POLY_OPA_DISP++, (u8*)gWorldMapImageTex + k * (WORLD_MAP_IMAGE_WIDTH * WORLD_MAP_IMAGE_FRAG_HEIGHT), + G_IM_FMT_CI, G_IM_SIZ_8b, WORLD_MAP_IMAGE_WIDTH, WORLD_MAP_IMAGE_HEIGHT % WORLD_MAP_IMAGE_FRAG_HEIGHT, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); gSP1Quadrangle(POLY_OPA_DISP++, j, j + 2, j + 3, j + 1, 0); } @@ -641,12 +652,13 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { // Draw clouds over the world map // Iterate over cloud bits (n) - for (n = 0; n < 15; n++) { + for (n = 0; n < WORLD_MAP_NUM_CLOUDS; n++) { if (!(((void)0, gSaveContext.save.saveInfo.worldMapCloudVisibility) & gBitFlags[n])) { - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[60 + n * 4], 4, 0); + gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[(QUAD_MAP_PAGE_WORLD_CLOUDS_FIRST + n) * 4], 4, 0); - POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, sCloudTextures[n], D_8082B7F0[n], D_8082B838[n], 0); + POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, sCloudTextures[n], gVtxPageMapWorldQuadsWidth[n], + gVtxPageMapWorldQuadsHeight[n], 0); } } @@ -676,6 +688,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { if (R_PAUSE_DBG_MAP_CLOUD_ON) { gSaveContext.save.saveInfo.worldMapCloudVisibility |= (u16)~0x8000; + // QUAD_MAP_PAGE_WORLD_REGION_FIRST pauseCtx->mapPageVtx[120].v.ob[0] = pauseCtx->mapPageVtx[122].v.ob[0] = R_PAUSE_DBG_MAP_CLOUD_X; pauseCtx->mapPageVtx[121].v.ob[0] = pauseCtx->mapPageVtx[123].v.ob[0] = @@ -690,7 +703,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { // Loop over RegionId (i), unused vtxIndex (j), unused (k) for (i = 0, j = 0; i < REGION_MAX; i++, k++, j += 4) { if (pauseCtx->worldMapPoints[i]) { - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[120 + i * 4], 4, 0); + gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[(QUAD_MAP_PAGE_WORLD_REGION_FIRST + i) * 4], 4, 0); gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); } } @@ -708,6 +721,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { if (R_PAUSE_DBG_MAP_CLOUD_ON) { gSaveContext.save.saveInfo.worldMapCloudVisibility |= (u16)~0x8000; + // QUAD_MAP_PAGE_WORLD_WARP_FIRST pauseCtx->mapPageVtx[164].v.ob[0] = pauseCtx->mapPageVtx[166].v.ob[0] = R_PAUSE_DBG_MAP_CLOUD_X; pauseCtx->mapPageVtx[165].v.ob[0] = pauseCtx->mapPageVtx[167].v.ob[0] = @@ -722,7 +736,7 @@ void KaleidoScope_DrawWorldMap(PlayState* play) { // Loop over OwlWarpId (i), unused vtxIndex (j), unused (k) for (i = 0, j = 0; i < OWL_WARP_ENTRANCE; i++, k++, j += 4) { if (pauseCtx->worldMapPoints[i]) { - gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[164 + i * 4], 4, 0); + gSPVertex(POLY_OPA_DISP++, &pauseCtx->mapPageVtx[(QUAD_MAP_PAGE_WORLD_WARP_FIRST + i) * 4], 4, 0); gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0); } } diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c index 61157ffce..950e10788 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_mask.c @@ -15,7 +15,7 @@ s16 sMaskEquipMagicArrowSlotHoldTimer = 0; // Number of frames to move icon from slot to target position when equipping. s16 sMaskEquipAnimTimer = 10; -u8 gMaskPlayerFormSlotRestrictions[PLAYER_FORM_MAX][NUM_MASK_SLOTS] = { +u8 gMaskPlayerFormSlotRestrictions[PLAYER_FORM_MAX][MASK_NUM_SLOTS] = { // Fierce Deity { false, // SLOT_MASK_POSTMAN @@ -196,7 +196,7 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { OPEN_DISPS(play->state.gfxCtx); - KaleidoScope_SetCursorVtx(pauseCtx, pauseCtx->cursorSlot[PAUSE_MASK] * 4, pauseCtx->maskVtx); + KaleidoScope_SetCursorVtxPos(pauseCtx, pauseCtx->cursorSlot[PAUSE_MASK] * 4, pauseCtx->maskVtx); func_8012C8AC(play->state.gfxCtx); @@ -204,9 +204,9 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { // Loop over c-buttons (i) and vtx offset (j) gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - for (i = 0, j = NUM_MASK_SLOTS * 4; i < 3; i++, j += 4) { + for (i = 0, j = MASK_NUM_SLOTS * 4; i < 3; i++, j += 4) { if (GET_CUR_FORM_BTN_ITEM(i + 1) != ITEM_NONE) { - if (GET_CUR_FORM_BTN_SLOT(i + 1) >= NUM_ITEM_SLOTS) { + if (GET_CUR_FORM_BTN_SLOT(i + 1) >= ITEM_NUM_SLOTS) { gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j], 4, 0); POLY_OPA_DISP = Gfx_DrawTexQuadIA8(POLY_OPA_DISP, gEquippedItemOutlineTex, 32, 32, 0); } @@ -218,10 +218,10 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { // Draw the item icons // Loop over slots (i) and vtx offset (j) gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); - for (j = 0, i = 0; i < NUM_MASK_SLOTS; i++, j += 4) { + for (j = 0, i = 0; i < MASK_NUM_SLOTS; i++, j += 4) { gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, pauseCtx->alpha); - if (((void)0, gSaveContext.save.saveInfo.inventory.items[i + NUM_ITEM_SLOTS]) != ITEM_NONE) { + if (((void)0, gSaveContext.save.saveInfo.inventory.items[i + ITEM_NUM_SLOTS]) != ITEM_NONE) { if (!CHECK_GIVEN_MASK_ON_MOON(i)) { if ((pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) && (pauseCtx->pageIndex == PAUSE_MASK) && (pauseCtx->cursorSpecialPos == 0) && @@ -259,7 +259,7 @@ void KaleidoScope_DrawMaskSelect(PlayState* play) { gSPVertex(POLY_OPA_DISP++, &pauseCtx->maskVtx[j + 0], 4, 0); KaleidoScope_DrawTexQuadRGBA32( play->state.gfxCtx, - gItemIcons[((void)0, gSaveContext.save.saveInfo.inventory.items[i + NUM_ITEM_SLOTS])], 32, 32, 0); + gItemIcons[((void)0, gSaveContext.save.saveInfo.inventory.items[i + ITEM_NUM_SLOTS])], 32, 32, 0); } } } @@ -324,7 +324,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { pauseCtx->cursorPoint[PAUSE_MASK] = pauseCtx->cursorXIndex[PAUSE_MASK] + (pauseCtx->cursorYIndex[PAUSE_MASK] * 6); - if (pauseCtx->cursorPoint[PAUSE_MASK] >= NUM_MASK_SLOTS) { + if (pauseCtx->cursorPoint[PAUSE_MASK] >= MASK_NUM_SLOTS) { pauseCtx->cursorPoint[PAUSE_MASK] = pauseCtx->cursorXIndex[PAUSE_MASK]; } @@ -354,7 +354,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { pauseCtx->cursorPoint[PAUSE_MASK] = pauseCtx->cursorXIndex[PAUSE_MASK] + (pauseCtx->cursorYIndex[PAUSE_MASK] * 6); - if (pauseCtx->cursorPoint[PAUSE_MASK] >= NUM_MASK_SLOTS) { + if (pauseCtx->cursorPoint[PAUSE_MASK] >= MASK_NUM_SLOTS) { pauseCtx->cursorPoint[PAUSE_MASK] = pauseCtx->cursorXIndex[PAUSE_MASK]; } @@ -372,7 +372,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { if (moveCursorResult == PAUSE_CURSOR_RESULT_SLOT) { cursorItem = - gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + NUM_ITEM_SLOTS]; + gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + ITEM_NUM_SLOTS]; if (CHECK_GIVEN_MASK_ON_MOON(pauseCtx->cursorPoint[PAUSE_MASK])) { cursorItem = ITEM_NONE; } @@ -388,7 +388,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { // Search for slot to move to while (true) { // Check if current cursor has an item in its slot - if ((gSaveContext.save.saveInfo.inventory.items[cursorPoint + NUM_ITEM_SLOTS] != ITEM_NONE) && + if ((gSaveContext.save.saveInfo.inventory.items[cursorPoint + ITEM_NUM_SLOTS] != ITEM_NONE) && !CHECK_GIVEN_MASK_ON_MOON(cursorPoint)) { pauseCtx->cursorPoint[PAUSE_MASK] = cursorPoint; pauseCtx->cursorXIndex[PAUSE_MASK] = cursorXIndex; @@ -429,7 +429,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { // Search for slot to move to while (true) { // Check if current cursor has an item in its slot - if ((gSaveContext.save.saveInfo.inventory.items[cursorPoint + NUM_ITEM_SLOTS] != ITEM_NONE) && + if ((gSaveContext.save.saveInfo.inventory.items[cursorPoint + ITEM_NUM_SLOTS] != ITEM_NONE) && !CHECK_GIVEN_MASK_ON_MOON(cursorPoint)) { pauseCtx->cursorPoint[PAUSE_MASK] = cursorPoint; pauseCtx->cursorXIndex[PAUSE_MASK] = cursorXIndex; @@ -502,13 +502,13 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { if (moveCursorResult == PAUSE_CURSOR_RESULT_SLOT) { cursorItem = - gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + NUM_ITEM_SLOTS]; + gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + ITEM_NUM_SLOTS]; if (CHECK_GIVEN_MASK_ON_MOON(pauseCtx->cursorPoint[PAUSE_MASK])) { cursorItem = ITEM_NONE; } } else if (moveCursorResult != PAUSE_CURSOR_RESULT_SPECIAL_POS) { cursorItem = - gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + NUM_ITEM_SLOTS]; + gSaveContext.save.saveInfo.inventory.items[pauseCtx->cursorPoint[PAUSE_MASK] + ITEM_NUM_SLOTS]; if (CHECK_GIVEN_MASK_ON_MOON(pauseCtx->cursorPoint[PAUSE_MASK])) { cursorItem = ITEM_NONE; } @@ -571,8 +571,8 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { if ((Player_GetEnvironmentalHazard(play) >= PLAYER_ENV_HAZARD_UNDERWATER_FLOOR) && (Player_GetEnvironmentalHazard(play) <= PLAYER_ENV_HAZARD_UNDERWATER_FREE) && - ((cursorSlot == (SLOT_MASK_DEKU - NUM_ITEM_SLOTS)) || - (cursorSlot == (SLOT_MASK_GORON - NUM_ITEM_SLOTS)))) { + ((cursorSlot == (SLOT_MASK_DEKU - ITEM_NUM_SLOTS)) || + (cursorSlot == (SLOT_MASK_GORON - ITEM_NUM_SLOTS)))) { play_sound(NA_SE_SY_ERROR); return; } @@ -587,7 +587,7 @@ void KaleidoScope_UpdateMaskCursor(PlayState* play) { // Equip item to the C buttons pauseCtx->equipTargetItem = cursorItem; - pauseCtx->equipTargetSlot = cursorSlot + NUM_ITEM_SLOTS; + pauseCtx->equipTargetSlot = cursorSlot + ITEM_NUM_SLOTS; pauseCtx->mainState = PAUSE_MAIN_STATE_EQUIP_MASK; vtxIndex = cursorSlot * 4; pauseCtx->equipAnimX = pauseCtx->maskVtx[vtxIndex].v.ob[0] * 10; @@ -659,7 +659,10 @@ void KaleidoScope_UpdateMaskEquip(PlayState* play) { } if (sMaskEquipState == EQUIP_STATE_MAGIC_ARROW_MOVE_TO_BOW_SLOT) { - bowItemVtx = &pauseCtx->itemVtx[12]; + //! Note: Copied from OoT when `SLOT_BOW` was still valued at 3. + // Due to a shift, `SLOT_ARROW_ICE` now occupies slot 3 but this value was not updated + // Block is never reached as you can not equip magic arrows from the mask page + bowItemVtx = &pauseCtx->itemVtx[SLOT_ARROW_ICE * 4]; offsetX = ABS_ALT(pauseCtx->equipAnimX - bowItemVtx->v.ob[0] * 10) / sMaskEquipAnimTimer; offsetY = ABS_ALT(pauseCtx->equipAnimY - bowItemVtx->v.ob[1] * 10) / sMaskEquipAnimTimer; } else { diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_prompt.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_prompt.c index 13e233b58..9bf89cdd2 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_prompt.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_prompt.c @@ -14,7 +14,7 @@ void KaleidoScope_UpdatePrompt(PlayState* play) { static s16 sPromptAlphaTimer = 10; PauseContext* pauseCtx = &play->pauseCtx; Input* input = CONTROLLER1(&play->state); - s8 relStickX = input->rel.stick_x; + s8 stickAdjX = input->rel.stick_x; s16 alphaStep; if (((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_1)) || @@ -22,11 +22,11 @@ void KaleidoScope_UpdatePrompt(PlayState* play) { (pauseCtx->state == PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT)) { // Move the prompt - if ((pauseCtx->promptChoice == PAUSE_PROMPT_YES) && (relStickX >= 30)) { + if ((pauseCtx->promptChoice == PAUSE_PROMPT_YES) && (stickAdjX >= 30)) { // Move right to the no prompt play_sound(NA_SE_SY_CURSOR); pauseCtx->promptChoice = PAUSE_PROMPT_NO; - } else if ((pauseCtx->promptChoice != PAUSE_PROMPT_YES) && (relStickX <= -30)) { + } else if ((pauseCtx->promptChoice != PAUSE_PROMPT_YES) && (stickAdjX <= -30)) { // Move left to the yes prompt play_sound(NA_SE_SY_CURSOR); pauseCtx->promptChoice = PAUSE_PROMPT_YES; diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h index 849c7020e..a9aeed70f 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h @@ -92,7 +92,7 @@ typedef enum { #define IS_PAUSE_STATE_OWLWARP \ ((pauseCtx->state >= PAUSE_STATE_OWLWARP_2) && (pauseCtx->state <= PAUSE_STATE_OWLWARP_6)) -#define IS_PAUSE_MAIN_STATE_SAVE_PROMPT \ +#define IS_PAUSE_MAIN_STATE_SONG_PROMPT \ ((pauseCtx->mainState >= PAUSE_MAIN_STATE_SONG_PROMPT_INIT) && \ (pauseCtx->mainState <= PAUSE_MAIN_STATE_SONG_PROMPT_DONE)) @@ -125,6 +125,184 @@ typedef enum { /* 5 */ PAUSE_BG_PRERENDER_MAX } PauseBgPreRenderState; +typedef enum { + /* 0 */ VTX_PAGE_MASK, + /* 1 */ VTX_PAGE_ITEM, + /* 2 */ VTX_PAGE_MAP_DUNGEON, + /* 3 */ VTX_PAGE_QUEST, + /* 4 */ VTX_PAGE_MAP_WORLD, + /* 5 */ VTX_PAGE_PROMPT, + /* 6 */ VTX_PAGE_MAX +} VtxPage; + +#define VTX_PAGE_MASK_QUADS 0 // VTX_PAGE_MASK +#define VTX_PAGE_ITEM_QUADS 0 // VTX_PAGE_ITEM +#define VTX_PAGE_MAP_DUNGEON_QUADS 6 // VTX_PAGE_MAP_DUNGEON +#define VTX_PAGE_QUEST_QUADS 0 // VTX_PAGE_QUEST +#define VTX_PAGE_MAP_WORLD_QUADS 36 // VTX_PAGE_MAP_WORLD +#define VTX_PAGE_SAVE_QUADS 5 // VTX_PAGE_PROMPT + +#define PAGE_BG_COLS 3 +#define PAGE_BG_ROWS 5 +#define PAGE_BG_QUADS (PAGE_BG_COLS * PAGE_BG_ROWS) +#define PAGE_BG_QUAD_WIDTH 80 +#define PAGE_BG_QUAD_HEIGHT 32 +#define PAGE_BG_QUAD_TEX_WIDTH 80 +#define PAGE_BG_QUAD_TEX_HEIGHT 32 + +// === ITEM === // + +#define ITEM_GRID_ROWS 4 +#define ITEM_GRID_COLS 6 +#define ITEM_GRID_CELL_WIDTH 32 +#define ITEM_GRID_CELL_HEIGHT 32 +#define ITEM_GRID_QUAD_MARGIN 2 +#define ITEM_GRID_QUAD_WIDTH (ITEM_GRID_CELL_WIDTH - (2 * ITEM_GRID_QUAD_MARGIN)) +#define ITEM_GRID_QUAD_HEIGHT (ITEM_GRID_CELL_HEIGHT - (2 * ITEM_GRID_QUAD_MARGIN)) +#define ITEM_GRID_QUAD_TEX_SIZE 32 // both width and height +#define ITEM_GRID_QUAD_ENLARGE_OFFSET 2 + +#define ITEM_GRID_SELECTED_QUAD_MARGIN (-2) +#define ITEM_GRID_SELECTED_QUAD_WIDTH (ITEM_GRID_QUAD_WIDTH - (2 * ITEM_GRID_SELECTED_QUAD_MARGIN)) +#define ITEM_GRID_SELECTED_QUAD_HEIGHT (ITEM_GRID_QUAD_HEIGHT - (2 * ITEM_GRID_SELECTED_QUAD_MARGIN)) +#define ITEM_GRID_SELECTED_QUAD_TEX_SIZE 32 // both width and height + +#define ITEM_NUM_SLOTS (ITEM_GRID_ROWS * ITEM_GRID_COLS) + +typedef enum { + // 0..59 are the 15 background textures + /* 0 */ QUAD_ITEM_PAGE_BG_FIRST, + /* 14 */ QUAD_ITEM_PAGE_BG_LAST = PAGE_BG_QUADS - 1, + // VTX_PAGE_ITEM_QUADS is 0 + /* 15 */ QUAD_ITEM_PAGE_MAX +} ItemPageQuad; + +typedef enum { + // 0..23 are the ITEM_GRID_ROWS*ITEM_GRID_COLS item grid + // The values follow the `InventorySlot` enum + /* 0 */ QUAD_ITEM_GRID_FIRST, + /* 23 */ QUAD_ITEM_GRID_LAST = ITEM_GRID_ROWS * ITEM_GRID_COLS - 1, + // White-box Markers indicating the currently equipped items + /* 24 */ QUAD_ITEM_GRID_SELECTED_C_LEFT, + /* 25 */ QUAD_ITEM_GRID_SELECTED_C_DOWN, + /* 26 */ QUAD_ITEM_GRID_SELECTED_C_RIGHT, + /* 27 */ QUAD_ITEM_MAX +} ItemQuad; + +// === MASK === // + +#define MASK_GRID_ROWS 4 +#define MASK_GRID_COLS 6 +#define MASK_GRID_CELL_WIDTH 32 +#define MASK_GRID_CELL_HEIGHT 32 +#define MASK_GRID_QUAD_MARGIN 2 +#define MASK_GRID_QUAD_WIDTH (MASK_GRID_CELL_WIDTH - (2 * MASK_GRID_QUAD_MARGIN)) +#define MASK_GRID_QUAD_HEIGHT (MASK_GRID_CELL_HEIGHT - (2 * MASK_GRID_QUAD_MARGIN)) +#define MASK_GRID_QUAD_TEX_SIZE 32 // both width and height +#define MASK_GRID_QUAD_ENLARGE_OFFSET 2 + +#define MASK_GRID_SELECTED_QUAD_MARGIN (-2) +#define MASK_GRID_SELECTED_QUAD_WIDTH (MASK_GRID_QUAD_WIDTH - (2 * MASK_GRID_SELECTED_QUAD_MARGIN)) +#define MASK_GRID_SELECTED_QUAD_HEIGHT (MASK_GRID_QUAD_HEIGHT - (2 * MASK_GRID_SELECTED_QUAD_MARGIN)) +#define MASK_GRID_SELECTED_QUAD_TEX_SIZE 32 // both width and height + +#define MASK_NUM_SLOTS (MASK_GRID_ROWS * MASK_GRID_COLS) + +typedef enum { + // 0..59 are the 15 background textures + /* 0 */ QUAD_MASK_PAGE_BG_FIRST, + /* 14 */ QUAD_MASK_PAGE_BG_LAST = PAGE_BG_QUADS - 1, + // VTX_PAGE_MASK_QUADS is 0 + /* 15 */ QUAD_MASK_PAGE_MAX +} MaskPageQuad; + +typedef enum { + // 0..23 are the MASK_GRID_ROWS*MASK_GRID_COLS item grid + // The values follow the `InventorySlot` enum offset by ITEM_NUM_SLOTS + /* 0 */ QUAD_MASK_GRID_FIRST, + /* 23 */ QUAD_MASK_GRID_LAST = MASK_GRID_ROWS * MASK_GRID_COLS - 1, + // Markers indicating the currently equipped items + /* 24 */ QUAD_MASK_GRID_SELECTED_C_LEFT, + /* 25 */ QUAD_MASK_GRID_SELECTED_C_DOWN, + /* 26 */ QUAD_MASK_GRID_SELECTED_C_RIGHT, + /* 27 */ QUAD_MASK_MAX +} MaskQuad; + +// === QUEST === // + +typedef enum { + // 0..59 are the 15 background textures + /* 0 */ QUAD_QUEST_PAGE_BG_FIRST, + /* 14 */ QUAD_QUEST_PAGE_BG_LAST = PAGE_BG_QUADS - 1, + // VTX_PAGE_QUEST_QUADS is 0 + /* 15 */ QUAD_QUEST_PAGE_MAX +} QuestPageQuad; + +typedef enum { + // 0 to 24 matches the `QuestItem` enum + // Notes showing the correct song + /* 25 */ QUAD_QUEST_SONG_NOTE_A1 = QUEST_HEART_PIECE + 1, + /* 26 */ QUAD_QUEST_SONG_NOTE_A2, + /* 27 */ QUAD_QUEST_SONG_NOTE_A3, + /* 28 */ QUAD_QUEST_SONG_NOTE_A4, + /* 29 */ QUAD_QUEST_SONG_NOTE_A5, + /* 30 */ QUAD_QUEST_SONG_NOTE_A6, + /* 31 */ QUAD_QUEST_SONG_NOTE_A7, + /* 32 */ QUAD_QUEST_SONG_NOTE_A8, + // Notes appearing when playing + /* 33 */ QUAD_QUEST_SONG_NOTE_B1, + /* 34 */ QUAD_QUEST_SONG_NOTE_B2, + /* 35 */ QUAD_QUEST_SONG_NOTE_B3, + /* 36 */ QUAD_QUEST_SONG_NOTE_B4, + /* 37 */ QUAD_QUEST_SONG_NOTE_B5, + /* 38 */ QUAD_QUEST_SONG_NOTE_B6, + /* 39 */ QUAD_QUEST_SONG_NOTE_B7, + /* 40 */ QUAD_QUEST_SONG_NOTE_B8, + /* 41 */ QUAD_QUEST_MAX +} QuestQuad; + +// === DUNGEON MAP === // + +typedef enum { + // 0..59 are the 15 background textures + /* 0 */ QUAD_MAP_PAGE_DUNGEON_BG_FIRST, + /* 14 */ QUAD_MAP_PAGE_DUNGEON_BG_LAST = PAGE_BG_QUADS - 1, + /* 15 */ QUAD_MAP_PAGE_DUNGEON_TITLE, + /* 16 */ QUAD_MAP_PAGE_DUNGEON_BOSS_KEY, + /* 17 */ QUAD_MAP_PAGE_DUNGEON_COMPASS, + /* 18 */ QUAD_MAP_PAGE_DUNGEON_MAP, + /* 19 */ QUAD_MAP_PAGE_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE, + /* 20 */ QUAD_MAP_PAGE_DUNGEON_UNUSED, + /* 21 */ QUAD_MAP_PAGE_DUNGEON_MAX +} DungeonMapPageQuad; + +// === WORLD MAP === // + +#define WORLD_MAP_IMAGE_WIDTH 216 +#define WORLD_MAP_IMAGE_HEIGHT 128 +#define WORLD_MAP_IMAGE_FRAG_HEIGHT ((TMEM_SIZE / 2) / (WORLD_MAP_IMAGE_WIDTH * G_IM_SIZ_8b_BYTES)) +#define WORLD_MAP_IMAGE_FRAG_NUM (((WORLD_MAP_IMAGE_HEIGHT - 1) / WORLD_MAP_IMAGE_FRAG_HEIGHT) + 1) +#define WORLD_MAP_NUM_CLOUDS 15 + +typedef enum { + // 0..59 are the 15 background textures + /* 0 */ QUAD_MAP_PAGE_WORLD_BG_FIRST, + /* 14 */ QUAD_MAP_PAGE_WORLD_BG_LAST = PAGE_BG_QUADS - 1, + // Clouds covering the world map + /* 15 */ QUAD_MAP_PAGE_WORLD_CLOUDS_FIRST, + /* 29 */ QUAD_MAP_PAGE_WORLD_CLOUDS_LAST = QUAD_MAP_PAGE_WORLD_CLOUDS_FIRST + WORLD_MAP_NUM_CLOUDS - 1, + // Markers for regions + /* 30 */ QUAD_MAP_PAGE_WORLD_REGION_FIRST, + /* 40 */ QUAD_MAP_PAGE_WORLD_REGION_LAST = QUAD_MAP_PAGE_WORLD_REGION_FIRST + REGION_MAX - 1, + // Markers for owl warps + /* 41 */ QUAD_MAP_PAGE_WORLD_WARP_FIRST, + /* 50 */ QUAD_MAP_PAGE_WORLD_WARP_LAST = QUAD_MAP_PAGE_WORLD_WARP_FIRST + OWL_WARP_ENTRANCE - 1, + // Fragments of the world map + /* 51 */ QUAD_MAP_PAGE_WORLD_IMAGE_FIRST, + /* 65 */ QUAD_MAP_PAGE_WORLD_IMAGE_LAST = QUAD_MAP_PAGE_WORLD_IMAGE_FIRST + WORLD_MAP_IMAGE_FRAG_NUM - 1, + /* 66 */ QUAD_MAP_PAGE_WORLD_MAX +} WorldMapPageQuad; + #define PAUSE_NAME_COLOR_SET_WHITE 0 #define PAUSE_NAME_COLOR_SET_GREY 1 @@ -139,12 +317,27 @@ typedef enum { /* 2 */ PAUSE_CURSOR_RESULT_SPECIAL_POS } PauseMoveCursorResult; -#define NUM_ITEM_SLOTS 24 -#define NUM_MASK_SLOTS 24 +typedef enum { + /* 0 */ PAUSE_QUAD_CURSOR_0, + /* 1 */ PAUSE_QUAD_CURSOR_1, + /* 2 */ PAUSE_QUAD_CURSOR_2, + /* 3 */ PAUSE_QUAD_CURSOR_3, + /* 4 */ PAUSE_QUAD_CURSOR_4, + /* 5 */ PAUSE_QUAD_CURSOR_MAX +} PauseCursorQuad; #define PAUSE_PROMPT_YES 0 #define PAUSE_PROMPT_NO 4 +typedef enum { + /* 0 */ QUAD_PROMPT_MESSAGE, + /* 1 */ QUAD_PROMPT_CURSOR_LEFT, + /* 2 */ QUAD_PROMPT_CURSOR_RIGHT, + /* 3 */ QUAD_PROMPT_CHOICE_YES, + /* 4 */ QUAD_PROMPT_CHOICE_NO, + /* 5 */ QUAD_PROMPT_MAX +} PromptQuad; + // NES void KaleidoScope_MoveCursorToSpecialPos(PlayState* play, s16 cursorSpecialPos); void KaleidoScope_DrawTexQuadRGBA32(GraphicsContext* gfxCtx, TexturePtr texture, u16 width, u16 height, u16 point); @@ -162,7 +355,7 @@ void KaleidoScope_DrawQuestStatus(PlayState* play); void KaleidoScope_UpdateQuestCursor(PlayState* play); // Item -void KaleidoScope_SetCursorVtx(PauseContext* pauseCtx, u16 index, Vtx* vtx); +void KaleidoScope_SetCursorVtxPos(PauseContext* pauseCtx, u16 vtxIndex, Vtx* vtx); void KaleidoScope_DrawItemSelect(PlayState* play); void KaleidoScope_UpdateItemCursor(PlayState* play); void KaleidoScope_UpdateItemEquip(PlayState* play); @@ -179,4 +372,7 @@ void KaleidoScope_UpdatePrompt(PlayState* play); void KaleidoScope_DrawInventoryEditor(PlayState* play); void KaleidoScope_UpdateInventoryEditor(PlayState* play); +extern s16 gVtxPageMapWorldQuadsWidth[]; +extern s16 gVtxPageMapWorldQuadsHeight[]; + #endif diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 1377f287f..ba9076b05 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -6,6 +6,8 @@ #include "z_kaleido_scope.h" #include "overlays/gamestates/ovl_opening/z_opening.h" +#include "interface/icon_item_gameover_static/icon_item_gameover_static.h" +#include "interface/icon_item_jpn_static/icon_item_jpn_static.h" #include "z64view.h" extern UNK_TYPE D_02001360; @@ -20,32 +22,165 @@ extern UNK_TYPE D_0C006C00; extern u8 sUnpausedButtonStatus[5]; -void* D_8082B700[] = { - 0x08064440, 0x0806E440, 0x08077A40, 0x08081040, 0x0808A640, 0x0D003A00, 0x0806EE40, 0x08078440, - 0x08081A40, 0x0808B040, 0x08065840, 0x0806F840, 0x08078E40, 0x08082440, 0x0808BA40, +// Page Textures (Background of Page): +// Broken up into multiple textures. +// Numbered by column/row. +TexturePtr sMaskPageBgTextures[] = { + // Column 0 + 0x08064440, // gPauseMasks00Tex + 0x0806E440, // gPauseMasks01Tex + 0x08077A40, // gPauseMasks02Tex + 0x08081040, // gPauseMasks03Tex + 0x0808A640, // gPauseMasks04Tex + // Column 1 + gPauseMasks10ENGTex, + 0x0806EE40, // gPauseMasks11Tex + 0x08078440, // gPauseMasks12Tex + 0x08081A40, // gPauseMasks13Tex + 0x0808B040, // gPauseMasks14Tex + // Column 2 + 0x08065840, // gPauseMasks20Tex + 0x0806F840, // gPauseMasks21Tex + 0x08078E40, // gPauseMasks22Tex + 0x08082440, // gPauseMasks23Tex + 0x0808BA40, // gPauseMasks24Tex }; -void* D_8082B73C[] = { - 0x0D004400, 0x08070240, 0x08079840, 0x08082E40, 0x0808C440, 0x0D004E00, 0x08070C40, 0x0807A240, - 0x08083840, 0x0808CE40, 0x0D005800, 0x08071640, 0x0807AC40, 0x08084240, 0x0808D840, +TexturePtr sItemPageBgTextures[] = { + // Column 0 + gPauseSelectItem00ENGTex, + 0x08070240, // gPauseSelectItem01Tex + 0x08079840, // gPauseSelectItem02Tex + 0x08082E40, // gPauseSelectItem03Tex + 0x0808C440, // gPauseSelectItem04Tex + // Column 1 + gPauseSelectItem10ENGTex, + 0x08070C40, // gPauseSelectItem11Tex + 0x0807A240, // gPauseSelectItem12Tex + 0x08083840, // gPauseSelectItem13Tex + 0x0808CE40, // gPauseSelectItem14Tex + // Column 2 + gPauseSelectItem20ENGTex, + 0x08071640, // gPauseSelectItem21Tex + 0x0807AC40, // gPauseSelectItem22Tex + 0x08084240, // gPauseSelectItem23Tex + 0x0808D840, // gPauseSelectItem24Tex }; -void* D_8082B778[] = { - 0x08068040, 0x08072040, 0x0807B640, 0x08084C40, 0x0808E240, 0x0D006200, 0x08072A40, 0x0807C040, - 0x08085640, 0x0808EC40, 0x08069440, 0x08073440, 0x0807CA40, 0x08086040, 0x0808F640, +TexturePtr sMapPageBgTextures[] = { + // Column 0 + 0x08068040, // gPauseMap00Tex + 0x08072040, // gPauseMap01Tex + 0x0807B640, // gPauseMap02Tex + 0x08084C40, // gPauseMap03Tex + 0x0808E240, // gPauseMap04Tex + // Column 1 + gPauseMap10ENGTex, + 0x08072A40, // gPauseMap11Tex + 0x0807C040, // gPauseMap12Tex + 0x08085640, // gPauseMap13Tex + 0x0808EC40, // gPauseMap14Tex + // Column 2 + 0x08069440, // gPauseMap20Tex + 0x08073440, // gPauseMap21Tex + 0x0807CA40, // gPauseMap22Tex + 0x08086040, // gPauseMap23Tex + 0x0808F640, // gPauseMap24Tex }; -void* D_8082B7B4[] = { - 0x0D006C00, 0x08073E40, 0x0807D440, 0x08086A40, 0x08090040, 0x0D007600, 0x08074840, 0x0807DE40, - 0x08087440, 0x08090A40, 0x0D008000, 0x08075240, 0x0807E840, 0x08087E40, 0x08091440, +TexturePtr sQuestPageBgTextures[] = { + // Column 0 + gPauseQuestStatus00ENGTex, + 0x08073E40, // gPauseQuestStatus01Tex + 0x0807D440, // gPauseQuestStatus02Tex + 0x08086A40, // gPauseQuestStatus03Tex + 0x08090040, // gPauseQuestStatus04Tex + // Column 1 + gPauseQuestStatus10ENGTex, + 0x08074840, // gPauseQuestStatus11Tex + 0x0807DE40, // gPauseQuestStatus12Tex + 0x08087440, // gPauseQuestStatus13Tex + 0x08090A40, // gPauseQuestStatus14Tex + // Column 2 + gPauseQuestStatus20ENGTex, + 0x08075240, // gPauseQuestStatus21Tex + 0x0807E840, // gPauseQuestStatus22Tex + 0x08087E40, // gPauseQuestStatus23Tex + 0x08091440, // gPauseQuestStatus24Tex }; -s16 D_8082B7F0[] = { - 0x0050, 0x0040, 0x0040, 0x0040, 0x0010, 0x0040, 0x0070, 0x0070, 0x0030, 0x0040, 0x0040, 0x0040, - 0x0040, 0x0030, 0x0040, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, - 0x0008, 0x0008, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, +s16 gVtxPageMapWorldQuadsWidth[VTX_PAGE_MAP_WORLD_QUADS] = { + 80, // mapPageVtx[60] clouds Clock Town 1 + 64, // mapPageVtx[64] clouds Clock Town 2 + 64, // mapPageVtx[68] clouds Woodfall 1 + 64, // mapPageVtx[72] clouds Woodfall 2 + 16, // mapPageVtx[76] clouds Woodfall 3 + 64, // mapPageVtx[80] clouds Snowhead 1 + 112, // mapPageVtx[84] clouds Snowhead 2 + 112, // mapPageVtx[88] clouds Snowhead 3 + 48, // mapPageVtx[92] clouds Romani Ranch + 64, // mapPageVtx[96] clouds Great Bay 1 + 64, // mapPageVtx[100] clouds Great Bay 2 + 64, // mapPageVtx[104] clouds Great Bay 3 + 64, // mapPageVtx[108] clouds Great Bay 4 + 48, // mapPageVtx[112] clouds Stone Tower 1 + 64, // mapPageVtx[116] clouds Stone Tower 2 + 8, // mapPageVtx[120] region Great Bay + 8, // mapPageVtx[124] region Zora Hall + 8, // mapPageVtx[128] region Romani Ranch + 8, // mapPageVtx[132] region Deku Palace + 8, // mapPageVtx[136] region Woodfall + 8, // mapPageVtx[140] region Clock Town + 8, // mapPageVtx[144] region Snowhead + 8, // mapPageVtx[148] region Ikana Graveyard + 8, // mapPageVtx[152] region Ikana Canyon + 8, // mapPageVtx[156] region Goron Village + 8, // mapPageVtx[160] region Stone Tower + 24, // mapPageVtx[164] owl warp Great Bay Coast + 24, // mapPageVtx[168] owl warp Zora Cape + 24, // mapPageVtx[172] owl warp Snowhead + 24, // mapPageVtx[176] owl warp Mountain Village + 24, // mapPageVtx[180] owl warp Clock Town + 24, // mapPageVtx[184] owl warp Milk Road + 24, // mapPageVtx[188] owl warp Woodfall + 24, // mapPageVtx[192] owl warp Southern Swamp + 24, // mapPageVtx[196] owl warp Ikana Canyon + 24, // mapPageVtx[200] owl warp Stone Tower }; -s16 D_8082B838[] = { - 0x0028, 0x001F, 0x0035, 0x0035, 0x0035, 0x0034, 0x0023, 0x0023, 0x0020, 0x0040, 0x0040, 0x0040, - 0x0040, 0x0052, 0x003D, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, 0x0008, - 0x0008, 0x0008, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, 0x000C, +s16 gVtxPageMapWorldQuadsHeight[VTX_PAGE_MAP_WORLD_QUADS] = { + 40, // mapPageVtx[60] clouds Clock Town 1 + 31, // mapPageVtx[64] clouds Clock Town 2 + 53, // mapPageVtx[68] clouds Woodfall 1 + 53, // mapPageVtx[72] clouds Woodfall 2 + 53, // mapPageVtx[76] clouds Woodfall 3 + 52, // mapPageVtx[80] clouds Snowhead 1 + 35, // mapPageVtx[84] clouds Snowhead 2 + 35, // mapPageVtx[88] clouds Snowhead 3 + 32, // mapPageVtx[92] clouds Romani Ranch + 64, // mapPageVtx[96] clouds Great Bay 1 + 64, // mapPageVtx[100] clouds Great Bay 2 + 64, // mapPageVtx[104] clouds Great Bay 3 + 64, // mapPageVtx[108] clouds Great Bay 4 + 82, // mapPageVtx[112] clouds Stone Tower 1 + 61, // mapPageVtx[116] clouds Stone Tower 2 + 8, // mapPageVtx[120] region Great Bay + 8, // mapPageVtx[124] region Zora Hall + 8, // mapPageVtx[128] region Romani Ranch + 8, // mapPageVtx[132] region Deku Palace + 8, // mapPageVtx[136] region Woodfall + 8, // mapPageVtx[140] region Clock Town + 8, // mapPageVtx[144] region Snowhead + 8, // mapPageVtx[148] region Ikana Graveyard + 8, // mapPageVtx[152] region Ikana Canyon + 8, // mapPageVtx[156] region Goron Village + 8, // mapPageVtx[160] region Stone Tower + 12, // mapPageVtx[164] owl warp Great Bay Coast + 12, // mapPageVtx[168] owl warp Zora Cape + 12, // mapPageVtx[172] owl warp Snowhead + 12, // mapPageVtx[176] owl warp Mountain Village + 12, // mapPageVtx[180] owl warp Clock Town + 12, // mapPageVtx[184] owl warp Milk Road + 12, // mapPageVtx[188] owl warp Woodfall + 12, // mapPageVtx[192] owl warp Southern Swamp + 12, // mapPageVtx[196] owl warp Ikana Canyon + 12, // mapPageVtx[200] owl warp Stone Tower }; s16 sGameOverPrimR = 0; @@ -115,136 +250,768 @@ u8 D_8082B924[] = { // TODO: Also applies to owl warps s16 sGameOverRectPosY = 66; -s16 D_8082B948[][3] = { - { 0x00FF, 0x00FF, 0x00FF }, { 0x00FF, 0x00FF, 0x00FF }, { 0x00FF, 0x00FF, 0x0000 }, - { 0x00FF, 0x00FF, 0x0000 }, { 0x0064, 0x0096, 0x00FF }, { 0x0064, 0x00FF, 0x00FF }, +void func_80821900(void* segment, u32 texIndex) { + CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0x400); +} + +void func_8082192C(void* segment, u32 texIndex) { + CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0xA00); +} + +void func_80821958(void* segment, u32 texIndex) { + CmpDma_LoadFile(SEGMENT_ROM_START(item_name_static), texIndex, segment, 0x400); +} + +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_MoveCursorToSpecialPos.s") + +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80821A04.s") + +void KaleidoScope_DrawTexQuadRGBA32(GraphicsContext* gfxCtx, TexturePtr texture, u16 width, u16 height, u16 point) { + OPEN_DISPS(gfxCtx); + + gDPLoadTextureBlock(POLY_OPA_DISP++, texture, G_IM_FMT_RGBA, G_IM_SIZ_32b, width, height, 0, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, + G_TX_NOLOD); + gSP1Quadrangle(POLY_OPA_DISP++, point, point + 2, point + 3, point + 1, 0); + + CLOSE_DISPS(gfxCtx); +} + +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80821CC4.s") + +void KaleidoScope_HandlePageToggles(PlayState* play, Input* input); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_HandlePageToggles.s") + +// Draw 15 (PAGE_BG_QUADS) quads with IA8 80x32 textures +Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, TexturePtr* textures) { + s32 i; + s32 j; + + gSPVertex(gfx++, vertices, 8 * 4, 0); + + i = 0; + j = 0; + // Draw first 8/15 background textures + while (j < 32) { + gDPPipeSync(gfx++); + gDPLoadTextureBlock(gfx++, textures[i], G_IM_FMT_IA, G_IM_SIZ_8b, 80, 32, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(gfx++, j, j + 2, j + 3, j + 1, 0); + + j += 4; + i++; + } + + gSPVertex(gfx++, vertices + (8 * 4), 7 * 4, 0); + + j = 0; + // Draw last 7/15 background textures + while (j < 28) { + gDPPipeSync(gfx++); + gDPLoadTextureBlock(gfx++, textures[i], G_IM_FMT_IA, G_IM_SIZ_8b, 80, 32, 0, G_TX_NOMIRROR | G_TX_WRAP, + G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD); + gSP1Quadrangle(gfx++, j, j + 2, j + 3, j + 1, 0); + + j += 4; + i++; + } + + return gfx; +} + +s16 sCursorPrimColorTarget[][3] = { + { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 0 }, { 255, 255, 0 }, { 100, 150, 255 }, { 100, 255, 255 }, }; -s16 D_8082B96C[][3] = { - { 0x0000, 0x0000, 0x0000 }, { 0x00AA, 0x00AA, 0x00AA }, { 0x0000, 0x0000, 0x0000 }, - { 0x00FF, 0x00A0, 0x0000 }, { 0x0000, 0x0000, 0x0064 }, { 0x0000, 0x0096, 0x00FF }, +s16 sCursorEnvColorTarget[][3] = { + { 0, 0, 0 }, { 170, 170, 170 }, { 0, 0, 0 }, { 255, 160, 0 }, { 0, 0, 100 }, { 0, 150, 255 }, }; -s16 D_8082B990 = 10; -s16 D_8082B994 = 0; +void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) { + static s16 sCursorColorTimer = 10; + static s16 sCursorColorTargetIndex = 0; + PauseContext* pauseCtx = &play->pauseCtx; + s16 stepR; + s16 stepG; + s16 stepB; -s32 D_8082B998[] = { - 0x0D003300, - 0x0D002700, - 0x0D002B00, - 0x0D002F00, + OPEN_DISPS(gfxCtx); + + if (!IS_PAUSE_STATE_GAMEOVER) { + if (pauseCtx->state != PAUSE_STATE_SAVEPROMPT) { + + stepR = + ABS_ALT(sCursorPrimR - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) / + sCursorColorTimer; + stepG = + ABS_ALT(sCursorPrimG - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) / + sCursorColorTimer; + stepB = + ABS_ALT(sCursorPrimB - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) / + sCursorColorTimer; + + if (sCursorPrimR >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) { + sCursorPrimR -= stepR; + } else { + sCursorPrimR += stepR; + } + + if (sCursorPrimG >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) { + sCursorPrimG -= stepG; + } else { + sCursorPrimG += stepG; + } + + if (sCursorPrimB >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) { + sCursorPrimB -= stepB; + } else { + sCursorPrimB += stepB; + } + + stepR = + ABS_ALT(sCursorEnvR - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) / + sCursorColorTimer; + stepG = + ABS_ALT(sCursorEnvG - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) / + sCursorColorTimer; + stepB = + ABS_ALT(sCursorEnvB - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) / + sCursorColorTimer; + + if (sCursorEnvR >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) { + sCursorEnvR -= stepR; + } else { + sCursorEnvR += stepR; + } + + if (sCursorEnvG >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) { + sCursorEnvG -= stepG; + } else { + sCursorEnvG += stepG; + } + + if (sCursorEnvB >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) { + sCursorEnvB -= stepB; + } else { + sCursorEnvB += stepB; + } + + sCursorColorTimer--; + if (sCursorColorTimer == 0) { + sCursorPrimR = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]; + sCursorPrimG = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]; + sCursorPrimB = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]; + sCursorEnvR = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]; + sCursorEnvG = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]; + sCursorEnvB = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]; + sCursorColorTargetIndex ^= 1; + sCursorColorTimer = 10; + } + } + + if ((pauseCtx->pageIndex != PAUSE_ITEM) && (pauseCtx->pageIndex != PAUSE_QUEST)) { + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, + TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(0.0f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->itemPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->itemPageVtx, sItemPageBgTextures); + + KaleidoScope_DrawItemSelect(play); + } + + if ((pauseCtx->pageIndex != PAUSE_MAP) && (pauseCtx->pageIndex != PAUSE_MASK)) { + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, + TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(-1.57f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures); + + if (sInDungeonScene) { + KaleidoScope_DrawDungeonMap(play); + func_8012C8AC(gfxCtx); + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + func_801091F0(play); + } else { + KaleidoScope_DrawWorldMap(play); + } + } + + if ((pauseCtx->pageIndex != PAUSE_QUEST) && (pauseCtx->pageIndex != PAUSE_ITEM)) { + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, + TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(-3.14f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->questPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->questPageVtx, sQuestPageBgTextures); + + KaleidoScope_DrawQuestStatus(play); + } + + if ((pauseCtx->pageIndex != PAUSE_MASK) && (pauseCtx->pageIndex != PAUSE_MAP)) { + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, + TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(1.57f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->maskPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->maskPageVtx, sMaskPageBgTextures); + + KaleidoScope_DrawMaskSelect(play); + } + + switch (pauseCtx->pageIndex) { + case PAUSE_ITEM: + if (pauseCtx->mainState <= PAUSE_MAIN_STATE_EQUIP_MASK) { + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, + PRIMITIVE, 0, TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(0.0f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->itemPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = + KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->itemPageVtx, sItemPageBgTextures); + + KaleidoScope_DrawItemSelect(play); + } + break; + + case PAUSE_MAP: + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, + 0, TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(-1.57f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures); + + if (sInDungeonScene) { + KaleidoScope_DrawDungeonMap(play); + func_8012C8AC(gfxCtx); + + gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM); + + func_801091F0(play); + } else { + Matrix_RotateYF(R_PAUSE_WORLD_MAP_YAW / 1000.0f, MTXMODE_NEW); + + if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWLWARP_3) || + (pauseCtx->state >= PAUSE_STATE_OWLWARP_6) || + ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && + ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) || + (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) { + Matrix_Translate(0.0f, (R_PAUSE_WORLD_MAP_Y_OFFSET - 8000) / 100.0f, + R_PAUSE_WORLD_MAP_DEPTH / 100.0f, MTXMODE_APPLY); + } else { + Matrix_Translate(0.0f, R_PAUSE_WORLD_MAP_Y_OFFSET / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f, + MTXMODE_APPLY); + } + + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + KaleidoScope_DrawWorldMap(play); + } + break; + + case PAUSE_QUEST: + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, + 0, TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP); + + Matrix_RotateYF(-3.14f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->questPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = + KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->questPageVtx, sQuestPageBgTextures); + + KaleidoScope_DrawQuestStatus(play); + break; + + case PAUSE_MASK: + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, + 0, TEXEL0, 0, SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(1.57f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->maskPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = + KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->maskPageVtx, sMaskPageBgTextures); + + KaleidoScope_DrawMaskSelect(play); + break; + } + } + + CLOSE_DISPS(gfxCtx); +} + +TexturePtr D_8082B998[] = { + gPauseToMasksENGTex, + gPauseToSelectItemENGTex, + gPauseToMapENGTex, + gPauseToQuestStatusENGTex, +}; +TexturePtr D_8082B9A8[] = { + gPauseToMapENGTex, + gPauseToQuestStatusENGTex, + gPauseToMasksENGTex, + gPauseToSelectItemENGTex, }; -s32 D_8082B9A8[] = { - 0x0D002B00, - 0x0D002F00, - 0x0D003300, - 0x0D002700, -}; - -s16 D_8082B9B8[] = { - 0x00B4, 0x00D2, 0x00FF, 0x00DC, 0x0064, 0x0064, 0x0096, 0x00DC, +s16 D_8082B9B8[][4] = { + { 180, 210, 255, 220 }, + { 100, 100, 150, 220 }, }; s16 D_8082B9C8 = 20; +s16 D_8082B9CC = 0; -s32 D_8082B9CC = 0; +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80823350.s") -s16 D_8082B9D0[] = { - 0x00B4, 0x00D2, 0x00FF, 0x00DC, 0x0064, 0x0064, 0x0096, 0x00DC, +void KaleidoScope_UpdateNamePanel(PlayState* play); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateNamePanel.s") + +void KaleidoScope_DrawOwlWarpMapPage(PlayState* play) { + PauseContext* pauseCtx = &play->pauseCtx; + + OPEN_DISPS(play->state.gfxCtx); + + gDPPipeSync(POLY_OPA_DISP++); + + gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, + SHADE, 0); + + gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255); + + Matrix_RotateYF(-1.57f, MTXMODE_NEW); + Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY); + Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures); + + Matrix_RotateYF(R_PAUSE_WORLD_MAP_YAW / 1000.0f, MTXMODE_NEW); + + if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWLWARP_3) || + (pauseCtx->state >= PAUSE_STATE_OWLWARP_6) || + ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) || + (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) { + Matrix_Translate(0.0f, (R_PAUSE_WORLD_MAP_Y_OFFSET - 8000) / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f, + MTXMODE_APPLY); + } else { + Matrix_Translate(0.0f, R_PAUSE_WORLD_MAP_Y_OFFSET / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f, MTXMODE_APPLY); + } + + Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY); + Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + KaleidoScope_DrawWorldMap(play); + + CLOSE_DISPS(play->state.gfxCtx); +} + +s16 D_8082B9D0[][4] = { + { 180, 210, 255, 220 }, + { 100, 100, 150, 220 }, }; s16 D_8082B9E0 = 20; +s16 D_8082B9E4 = 0; -s32 D_8082B9E4 = 0; +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80824B90.s") -s32 D_8082B9E8 = 0; +void KaleidoScope_UpdateOwlWarpNamePanel(PlayState* play); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateOwlWarpNamePanel.s") -s32 D_8082B9EC = 0; +void KaleidoScope_UpdateSwitchPage(PlayState* play, Input* input); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateSwitchPage.s") -s16 D_8082B9F0[] = { - 0xFFEB, 0xFF98, 0xFFB4, 0xFFD0, 0xFF98, 0xFFD8, +void KaleidoScope_SetView(PauseContext* pauseCtx, f32 eyeX, f32 eyeY, f32 eyeZ) { + Vec3f eye; + Vec3f at; + Vec3f up; + + eye.x = eyeX; + eye.y = eyeY; + eye.z = eyeZ; + at.x = at.y = at.z = 0.0f; + up.x = up.z = 0.0f; + up.y = 1.0f; + + View_LookAt(&pauseCtx->view, &eye, &at, &up); + View_Apply(&pauseCtx->view, + VIEW_ALL | VIEW_FORCE_VIEWING | VIEW_FORCE_VIEWPORT | VIEW_FORCE_PROJECTION_PERSPECTIVE); +} + +// CLAMP_MIN(*, 1) because C arrays can't have 0 length +s16 sVtxPageMaskQuadsX[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 }; +s16 sVtxPageItemQuadsX[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 }; +s16 sVtxPageMapDungeonQuadsX[VTX_PAGE_MAP_DUNGEON_QUADS] = { + -21, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE + -104, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY + -76, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS + -48, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP + -104, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE + -40 // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED +}; +s16 sVtxPageQuestQuadsX[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 }; +s16 sVtxPageMapWorldQuadsX[VTX_PAGE_MAP_WORLD_QUADS] = { + -41, // mapPageVtx[60] world map clouds Clock Town 1 + 9, // mapPageVtx[64] world map clouds Clock Town 2 + 43, // mapPageVtx[68] world map clouds Woodfall 1 + -21, // mapPageVtx[72] world map clouds Woodfall 2 + -37, // mapPageVtx[76] world map clouds Woodfall 3 + 43, // mapPageVtx[80] world map clouds Snowhead 1 + -69, // mapPageVtx[84] world map clouds Snowhead 2 + -69, // mapPageVtx[88] world map clouds Snowhead 3 + -32, // mapPageVtx[92] world map clouds Romani Ranch + -109, // mapPageVtx[96] world map clouds Great Bay 1 + -45, // mapPageVtx[100] world map clouds Great Bay 2 + -109, // mapPageVtx[104] world map clouds Great Bay 3 + -45, // mapPageVtx[108] world map clouds Great Bay 4 + 59, // mapPageVtx[112] world map clouds Stone Tower 1 + -5, // mapPageVtx[116] world map clouds Stone Tower 2 + -70, // mapPageVtx[120] world map region Great Bay + -52, // mapPageVtx[124] world map region Zora Hall + -11, // mapPageVtx[128] world map region Romani Ranch + -2, // mapPageVtx[132] world map region Deku Palace + 8, // mapPageVtx[136] world map region Woodfall + 2, // mapPageVtx[140] world map region Clock Town + 1, // mapPageVtx[144] world map region Snowhead + 43, // mapPageVtx[148] world map region Ikana Graveyard + 52, // mapPageVtx[152] world map region Ikana Canyon + 54, // mapPageVtx[156] world map region Goron Village + 62, // mapPageVtx[160] world map region Stone Tower + -80, // mapPageVtx[164] world map owl warp Great Bay Coast + -64, // mapPageVtx[168] world map owl warp Zora Cape + -9, // mapPageVtx[172] world map owl warp Snowhead + -3, // mapPageVtx[176] world map owl warp Mountain Village + -7, // mapPageVtx[180] world map owl warp Clock Town + -16, // mapPageVtx[184] world map owl warp Milk Road + -1, // mapPageVtx[188] world map owl warp Woodfall + 23, // mapPageVtx[192] world map owl warp Southern Swamp + 44, // mapPageVtx[196] world map owl warp Ikana Canyon + 54, // mapPageVtx[200] world map owl warp Stone Tower +}; +s16 sVtxPageSaveQuadsX[VTX_PAGE_SAVE_QUADS] = { + -76, // promptPageVtx[60] QUAD_PROMPT_MESSAGE + -58, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT + 10, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT + -58, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES + 10, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO }; -s32 D_8082B9FC = 0; - -s16 D_8082BA00[] = { - 0xFFD7, 0x0009, 0x002B, 0xFFEB, 0xFFDB, 0x002B, 0xFFBB, 0xFFBB, 0xFFE0, 0xFF93, 0xFFD3, 0xFF93, - 0xFFD3, 0x003B, 0xFFFB, 0xFFBA, 0xFFCC, 0xFFF5, 0xFFFE, 0x0008, 0x0002, 0x0001, 0x002B, 0x0034, - 0x0036, 0x003E, 0xFFB0, 0xFFC0, 0xFFF7, 0xFFFD, 0xFFF9, 0xFFF0, 0xFFFF, 0x0017, 0x002C, 0x0036, +// CLAMP_MIN(*, 1) because C arrays can't have 0 length +s16 sVtxPageMaskQuadsWidth[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 }; +s16 sVtxPageItemQuadsWidth[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 }; +s16 sVtxPageMapDungeonQuadsWidth[VTX_PAGE_MAP_DUNGEON_QUADS] = { + 128, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE + 24, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY + 24, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS + 24, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP + 32, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE + 24, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED +}; +s16 sVtxPageQuestQuadsWidth[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 }; +s16 sVtxPageSaveQuadsWidth[VTX_PAGE_SAVE_QUADS] = { + 152, // promptPageVtx[60] QUAD_PROMPT_MESSAGE + 48, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT + 48, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT + 48, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES + 48, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO }; -s16 D_8082BA48[] = { - 0xFFB4, 0xFFC6, 0x000A, 0xFFC6, 0x000A, 0x0000, +// CLAMP_MIN(*, 1) because C arrays can't have 0 length +s16 sVtxPageMaskQuadsY[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 }; +s16 sVtxPageItemQuadsY[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 }; + +s16 sVtxPageMapDungeonQuadsY[VTX_PAGE_MAP_DUNGEON_QUADS] = { + 54, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE + -42, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY + -42, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS + -42, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP + -24, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE + 50, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED +}; +s16 sVtxPageQuestQuadsY[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 }; +s16 sVtxPageMapWorldQuadsY[VTX_PAGE_MAP_WORLD_QUADS] = { + 11, // mapPageVtx[60] world map clouds Clock Town 1 + 22, // mapPageVtx[64] world map clouds Clock Town 2 + -16, // mapPageVtx[68] world map clouds Woodfall 1 + -16, // mapPageVtx[72] world map clouds Woodfall 2 + -16, // mapPageVtx[76] world map clouds Woodfall 3 + 59, // mapPageVtx[80] world map clouds Snowhead 1 + 24, // mapPageVtx[84] world map clouds Snowhead 2 + 59, // mapPageVtx[88] world map clouds Snowhead 3 + -11, // mapPageVtx[92] world map clouds Romani Ranch + -5, // mapPageVtx[96] world map clouds Great Bay 1 + -5, // mapPageVtx[100] world map clouds Great Bay 2 + 59, // mapPageVtx[104] world map clouds Great Bay 3 + 59, // mapPageVtx[108] world map clouds Great Bay 4 + 39, // mapPageVtx[112] world map clouds Stone Tower 1 + 31, // mapPageVtx[116] world map clouds Stone Tower 2 + -10, // mapPageVtx[120] world map region Great Bay + -36, // mapPageVtx[124] world map region Zora Hall + -19, // mapPageVtx[128] world map region Romani Ranch + -53, // mapPageVtx[132] world map region Deku Palace + -27, // mapPageVtx[136] world map region Woodfall + -2, // mapPageVtx[140] world map region Clock Town + 41, // mapPageVtx[144] world map region Snowhead + 11, // mapPageVtx[148] world map region Ikana Graveyard + -3, // mapPageVtx[152] world map region Ikana Canyon + 45, // mapPageVtx[156] world map region Goron Village + 18, // mapPageVtx[160] world map region Stone Tower + -8, // mapPageVtx[164] world map owl warp Great Bay Coast + -38, // mapPageVtx[168] world map owl warp Zora Cape + 39, // mapPageVtx[172] world map owl warp Snowhead + 26, // mapPageVtx[176] world map owl warp Mountain Village + 1, // mapPageVtx[180] world map owl warp Clock Town + -7, // mapPageVtx[184] world map owl warp Milk Road + -28, // mapPageVtx[188] world map owl warp Woodfall + -27, // mapPageVtx[192] world map owl warp Southern Swamp + -1, // mapPageVtx[196] world map owl warp Ikana Canyon + 24, // mapPageVtx[200] world map owl warp Stone Tower +}; +s16 sVtxPageSaveQuadsY[VTX_PAGE_SAVE_QUADS] = { + 36, // promptPageVtx[60] QUAD_PROMPT_MESSAGE + 10, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT + 10, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT + -6, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES + -6, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO }; -s32 D_8082BA54 = 0; - -s32 D_8082BA58 = 0; - -s16 D_8082BA5C[] = { - 0x0080, 0x0018, 0x0018, 0x0018, 0x0020, 0x0018, +// CLAMP_MIN(*, 1) because C arrays can't have 0 length +s16 sVtxPageMaskQuadsHeight[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 }; +s16 sVtxPageItemQuadsHeight[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 }; +s16 sVtxPageMapDungeonQuadsHeight[] = { + 16, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE + 24, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY + 24, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS + 24, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP + 24, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE + 24, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED +}; +s16 sVtxPageQuestQuadsHeight[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 }; +s16 sVtxPageSaveQuadsHeight[VTX_PAGE_SAVE_QUADS] = { + 16, // promptPageVtx[60] QUAD_PROMPT_MESSAGE + 48, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT + 48, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT + 16, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES + 16, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO }; -s32 D_8082BA68 = 0; - -s16 D_8082BA6C[] = { - 0x0098, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, +s16* sVtxPageQuadsX[VTX_PAGE_MAX] = { + sVtxPageMaskQuadsX, // VTX_PAGE_MASK + sVtxPageItemQuadsX, // VTX_PAGE_ITEM + sVtxPageMapDungeonQuadsX, // VTX_PAGE_MAP_DUNGEON + sVtxPageQuestQuadsX, // VTX_PAGE_QUEST + sVtxPageMapWorldQuadsX, // VTX_PAGE_MAP_WORLD + sVtxPageSaveQuadsX, // VTX_PAGE_PROMPT }; -s32 D_8082BA78 = 0; - -s32 D_8082BA7C = 0; - -s16 D_8082BA80[] = { - 0x0036, 0xFFD6, 0xFFD6, 0xFFD6, 0xFFE8, 0x0032, +s16* sVtxPageQuadsWidth[VTX_PAGE_MAX] = { + sVtxPageMaskQuadsWidth, // VTX_PAGE_MASK + sVtxPageItemQuadsWidth, // VTX_PAGE_ITEM + sVtxPageMapDungeonQuadsWidth, // VTX_PAGE_MAP_DUNGEON + sVtxPageQuestQuadsWidth, // VTX_PAGE_QUEST + gVtxPageMapWorldQuadsWidth, // VTX_PAGE_MAP_WORLD + sVtxPageSaveQuadsWidth, // VTX_PAGE_PROMPT }; -s32 D_8082BA8C = 0; - -s16 D_8082BA90[] = { - 0x000B, 0x0016, 0xFFF0, 0xFFF0, 0xFFF0, 0x003B, 0x0018, 0x003B, 0xFFF5, 0xFFFB, 0xFFFB, 0x003B, - 0x003B, 0x0027, 0x001F, 0xFFF6, 0xFFDC, 0xFFED, 0xFFCB, 0xFFE5, 0xFFFE, 0x0029, 0x000B, 0xFFFD, - 0x002D, 0x0012, 0xFFF8, 0xFFDA, 0x0027, 0x001A, 0x0001, 0xFFF9, 0xFFE4, 0xFFE5, 0xFFFF, 0x0018, +s16* sVtxPageQuadsY[VTX_PAGE_MAX] = { + sVtxPageMaskQuadsY, // VTX_PAGE_MASK + sVtxPageItemQuadsY, // VTX_PAGE_ITEM + sVtxPageMapDungeonQuadsY, // VTX_PAGE_MAP_DUNGEON + sVtxPageQuestQuadsY, // VTX_PAGE_QUEST + sVtxPageMapWorldQuadsY, // VTX_PAGE_MAP_WORLD + sVtxPageSaveQuadsY, // VTX_PAGE_PROMPT }; -s16 D_8082BAD8[] = { - 0x0024, 0x000A, 0x000A, 0xFFFA, 0xFFFA, 0x0000, +s16* sVtxPageQuadsHeight[VTX_PAGE_MAX] = { + sVtxPageMaskQuadsHeight, // VTX_PAGE_MASK + sVtxPageItemQuadsHeight, // VTX_PAGE_ITEM + sVtxPageMapDungeonQuadsHeight, // VTX_PAGE_MAP_DUNGEON + sVtxPageQuestQuadsHeight, // VTX_PAGE_QUEST + gVtxPageMapWorldQuadsHeight, // VTX_PAGE_MAP_WORLD + sVtxPageSaveQuadsHeight, // VTX_PAGE_PROMPT }; -s32 D_8082BAE4 = 0; - -s32 D_8082BAE8 = 0; - -s16 D_8082BAEC[] = { - 0x0010, 0x0018, 0x0018, 0x0018, 0x0018, 0x0018, +s16 sVtxPageGameOverSaveQuadsY[VTX_PAGE_SAVE_QUADS] = { + 14, // promptPageVtx[60] QUAD_PROMPT_MESSAGE + -2, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT + -2, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT + -18, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES + -18, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO }; -s32 D_8082BAF8 = 0; +s16 KaleidoScope_SetPageVertices(PlayState* play, Vtx* vtx, s16 vtxPage, s16 numQuads) { + PauseContext* pauseCtx = &play->pauseCtx; + GameOverContext* gameOverCtx = &play->gameOverCtx; + s16* quadsX; + s16* quadsWidth; + s16* quadsY; + s16* quadsHeight; + s16 pageBgQuadX; + s16 pageBgQuadY; + s16 i; + s16 j; + s16 k; -s16 D_8082BAFC[] = { - 0x0010, 0x0030, 0x0030, 0x0010, 0x0010, 0x0000, -}; + // Vertices for KaleidoScope_DrawPageSections -void* D_8082BB08[] = { - &D_8082B9E8, &D_8082B9EC, &D_8082B9F0, &D_8082B9FC, &D_8082BA00, &D_8082BA48, -}; + pageBgQuadX = 0 - (PAGE_BG_COLS * PAGE_BG_QUAD_WIDTH) / 2 - PAGE_BG_QUAD_WIDTH; -void* D_8082BB20[] = { - &D_8082BA54, &D_8082BA58, &D_8082BA5C, &D_8082BA68, &D_8082B7F0, &D_8082BA6C, -}; + // For each column + for (k = 0, i = 0; i < 3; i++) { + pageBgQuadX += PAGE_BG_QUAD_WIDTH; -void* D_8082BB38[] = { - &D_8082BA78, &D_8082BA7C, &D_8082BA80, &D_8082BA8C, &D_8082BA90, &D_8082BAD8, -}; + // For each row + for (pageBgQuadY = (PAGE_BG_ROWS * PAGE_BG_QUAD_HEIGHT) / 2, j = 0; j < 5; j++, k += 4, pageBgQuadY -= 32) { + vtx[k + 0].v.ob[0] = vtx[k + 2].v.ob[0] = pageBgQuadX; + vtx[k + 1].v.ob[0] = vtx[k + 3].v.ob[0] = vtx[k + 0].v.ob[0] + PAGE_BG_QUAD_WIDTH; -void* D_8082BB50[] = { - &D_8082BAE4, &D_8082BAE8, &D_8082BAEC, &D_8082BAF8, &D_8082B838, &D_8082BAFC, -}; + vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = pageBgQuadY + pauseCtx->offsetY; + vtx[k + 2].v.ob[1] = vtx[k + 3].v.ob[1] = vtx[k + 0].v.ob[1] - PAGE_BG_QUAD_HEIGHT; -s16 D_8082BB68[] = { - 0x000E, 0xFFFE, 0xFFFE, 0xFFEE, 0xFFEE, 0x0000, -}; + vtx[k + 0].v.ob[2] = vtx[k + 1].v.ob[2] = vtx[k + 2].v.ob[2] = vtx[k + 3].v.ob[2] = 0; + + vtx[k + 0].v.flag = vtx[k + 1].v.flag = vtx[k + 2].v.flag = vtx[k + 3].v.flag = 0; + + vtx[k + 0].v.tc[0] = vtx[k + 0].v.tc[1] = 0; + vtx[k + 1].v.tc[1] = vtx[k + 2].v.tc[0] = 0; + vtx[k + 1].v.tc[0] = vtx[k + 3].v.tc[0] = PAGE_BG_QUAD_TEX_WIDTH * (1 << 5); + vtx[k + 2].v.tc[1] = vtx[k + 3].v.tc[1] = PAGE_BG_QUAD_TEX_HEIGHT * (1 << 5); + + vtx[k + 0].v.cn[0] = vtx[k + 2].v.cn[0] = vtx[k + 0].v.cn[1] = vtx[k + 2].v.cn[1] = vtx[k + 0].v.cn[2] = + vtx[k + 2].v.cn[2] = 0; + + vtx[k + 1].v.cn[0] = vtx[k + 3].v.cn[0] = vtx[k + 1].v.cn[1] = vtx[k + 3].v.cn[1] = vtx[k + 1].v.cn[2] = + vtx[k + 3].v.cn[2] = 0; + + vtx[k + 0].v.cn[3] = vtx[k + 2].v.cn[3] = vtx[k + 1].v.cn[3] = vtx[k + 3].v.cn[3] = pauseCtx->alpha; + } + } + + if (numQuads != 0) { + quadsX = sVtxPageQuadsX[vtxPage]; + quadsWidth = sVtxPageQuadsWidth[vtxPage]; + quadsY = sVtxPageQuadsY[vtxPage]; + quadsHeight = sVtxPageQuadsHeight[vtxPage]; + + for (i = 0; i < numQuads; i++, k += 4) { + vtx[k + 2].v.ob[0] = vtx[k + 0].v.ob[0] = quadsX[i]; + + vtx[k + 1].v.ob[0] = vtx[k + 3].v.ob[0] = vtx[k + 0].v.ob[0] + quadsWidth[i]; + + if (!IS_PAUSE_STATE_GAMEOVER) { + vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = quadsY[i] + pauseCtx->offsetY; + } else if (gameOverCtx->state == GAMEOVER_INACTIVE) { + vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = quadsY[i] + pauseCtx->offsetY; + } else { + vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = sVtxPageGameOverSaveQuadsY[i] + pauseCtx->offsetY; + } + + vtx[k + 2].v.ob[1] = vtx[k + 3].v.ob[1] = vtx[k + 0].v.ob[1] - quadsHeight[i]; + + vtx[k + 0].v.ob[2] = vtx[k + 1].v.ob[2] = vtx[k + 2].v.ob[2] = vtx[k + 3].v.ob[2] = 0; + + vtx[k + 0].v.flag = vtx[k + 1].v.flag = vtx[k + 2].v.flag = vtx[k + 3].v.flag = 0; + + vtx[k + 0].v.tc[0] = vtx[k + 0].v.tc[1] = vtx[k + 1].v.tc[1] = vtx[k + 2].v.tc[0] = 0; + vtx[k + 1].v.tc[0] = vtx[k + 3].v.tc[0] = quadsWidth[i] << 5; + vtx[k + 2].v.tc[1] = vtx[k + 3].v.tc[1] = quadsHeight[i] << 5; + + vtx[k + 0].v.cn[0] = vtx[k + 2].v.cn[0] = vtx[k + 0].v.cn[1] = vtx[k + 2].v.cn[1] = vtx[k + 0].v.cn[2] = + vtx[k + 2].v.cn[2] = 255; + + vtx[k + 1].v.cn[0] = vtx[k + 3].v.cn[0] = vtx[k + 1].v.cn[1] = vtx[k + 3].v.cn[1] = vtx[k + 1].v.cn[2] = + vtx[k + 3].v.cn[2] = 255; + + vtx[k + 0].v.cn[3] = vtx[k + 2].v.cn[3] = vtx[k + 1].v.cn[3] = vtx[k + 3].v.cn[3] = pauseCtx->alpha; + } + } + return k; +} s16 sQuestVtxRectLeft[] = { 45, // QUEST_REMAINS_ODOLWA @@ -413,6 +1180,373 @@ s16 sQuestVtxHeights[] = { 16, // ocarina input button index 6 16, // ocarina input button index 7 }; + +void KaleidoScope_SetVertices(PlayState* play, GraphicsContext* gfxCtx) { + PauseContext* pauseCtx = &play->pauseCtx; + s16 i; + s16 j; + s16 k; + s16 vtx_x; + s16 vtx_y; + + pauseCtx->offsetY = 0; + + if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWLWARP_3) || + (pauseCtx->state >= PAUSE_STATE_OWLWARP_6) || + ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) || + (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) { + pauseCtx->offsetY = 80; + } + + if (pauseCtx->pageIndex != PAUSE_QUEST) { + pauseCtx->itemPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_ITEM_QUADS) * 4) * sizeof(Vtx)); + KaleidoScope_SetPageVertices(play, pauseCtx->itemPageVtx, VTX_PAGE_ITEM, VTX_PAGE_ITEM_QUADS); + + pauseCtx->itemVtx = GRAPH_ALLOC(gfxCtx, (QUAD_ITEM_MAX * 4) * sizeof(Vtx)); + + // QUAD_ITEM_GRID_FIRST..QUAD_ITEM_GRID_LAST + + // Loop over grid rows + for (k = 0, i = 0, vtx_y = (ITEM_GRID_ROWS * ITEM_GRID_CELL_HEIGHT) / 2 - 6; k < ITEM_GRID_ROWS; + k++, vtx_y -= ITEM_GRID_CELL_HEIGHT) { + // Loop over grid columns + for (vtx_x = 0 - (ITEM_GRID_COLS * ITEM_GRID_CELL_WIDTH) / 2, j = 0; j < ITEM_GRID_COLS; + j++, i += 4, vtx_x += ITEM_GRID_CELL_WIDTH) { + pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0] = vtx_x + ITEM_GRID_QUAD_MARGIN; + pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] = + pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_QUAD_WIDTH; + + pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] = + vtx_y + pauseCtx->offsetY - ITEM_GRID_QUAD_MARGIN; + pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] = + pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_QUAD_WIDTH; + + pauseCtx->itemVtx[i + 0].v.ob[2] = pauseCtx->itemVtx[i + 1].v.ob[2] = pauseCtx->itemVtx[i + 2].v.ob[2] = + pauseCtx->itemVtx[i + 3].v.ob[2] = 0; + + pauseCtx->itemVtx[i + 0].v.flag = pauseCtx->itemVtx[i + 1].v.flag = pauseCtx->itemVtx[i + 2].v.flag = + pauseCtx->itemVtx[i + 3].v.flag = 0; + + pauseCtx->itemVtx[i + 0].v.tc[0] = pauseCtx->itemVtx[i + 0].v.tc[1] = pauseCtx->itemVtx[i + 1].v.tc[1] = + pauseCtx->itemVtx[i + 2].v.tc[0] = 0; + + pauseCtx->itemVtx[i + 1].v.tc[0] = pauseCtx->itemVtx[i + 2].v.tc[1] = pauseCtx->itemVtx[i + 3].v.tc[0] = + pauseCtx->itemVtx[i + 3].v.tc[1] = ITEM_GRID_QUAD_TEX_SIZE * (1 << 5); + + pauseCtx->itemVtx[i + 0].v.cn[0] = pauseCtx->itemVtx[i + 1].v.cn[0] = pauseCtx->itemVtx[i + 2].v.cn[0] = + pauseCtx->itemVtx[i + 3].v.cn[0] = pauseCtx->itemVtx[i + 0].v.cn[1] = + pauseCtx->itemVtx[i + 1].v.cn[1] = pauseCtx->itemVtx[i + 2].v.cn[1] = + pauseCtx->itemVtx[i + 3].v.cn[1] = pauseCtx->itemVtx[i + 0].v.cn[2] = + pauseCtx->itemVtx[i + 1].v.cn[2] = pauseCtx->itemVtx[i + 2].v.cn[2] = + pauseCtx->itemVtx[i + 3].v.cn[2] = 255; + + pauseCtx->itemVtx[i + 0].v.cn[3] = pauseCtx->itemVtx[i + 1].v.cn[3] = pauseCtx->itemVtx[i + 2].v.cn[3] = + pauseCtx->itemVtx[i + 3].v.cn[3] = 255; + } + } + + // QUAD_ITEM_GRID_SELECTED_C_LEFT, QUAD_ITEM_GRID_SELECTED_C_DOWN, QUAD_ITEM_GRID_SELECTED_C_RIGHT + + for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++, i += 4) { + if (GET_CUR_FORM_BTN_SLOT(j) != ITEM_NONE) { + k = GET_CUR_FORM_BTN_SLOT(j) * 4; + + pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0] = + pauseCtx->itemVtx[k].v.ob[0] + ITEM_GRID_SELECTED_QUAD_MARGIN; + + pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] = + pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_SELECTED_QUAD_WIDTH; + + pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] = + pauseCtx->itemVtx[k].v.ob[1] - ITEM_GRID_SELECTED_QUAD_MARGIN; + + pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] = + pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_SELECTED_QUAD_WIDTH; + + pauseCtx->itemVtx[i + 0].v.ob[2] = pauseCtx->itemVtx[i + 1].v.ob[2] = pauseCtx->itemVtx[i + 2].v.ob[2] = + pauseCtx->itemVtx[i + 3].v.ob[2] = 0; + + pauseCtx->itemVtx[i + 0].v.flag = pauseCtx->itemVtx[i + 1].v.flag = pauseCtx->itemVtx[i + 2].v.flag = + pauseCtx->itemVtx[i + 3].v.flag = 0; + + pauseCtx->itemVtx[i + 0].v.tc[0] = pauseCtx->itemVtx[i + 0].v.tc[1] = pauseCtx->itemVtx[i + 1].v.tc[1] = + pauseCtx->itemVtx[i + 2].v.tc[0] = 0; + + pauseCtx->itemVtx[i + 1].v.tc[0] = pauseCtx->itemVtx[i + 2].v.tc[1] = pauseCtx->itemVtx[i + 3].v.tc[0] = + pauseCtx->itemVtx[i + 3].v.tc[1] = ITEM_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5); + + pauseCtx->itemVtx[i + 0].v.cn[0] = pauseCtx->itemVtx[i + 1].v.cn[0] = pauseCtx->itemVtx[i + 2].v.cn[0] = + pauseCtx->itemVtx[i + 3].v.cn[0] = pauseCtx->itemVtx[i + 0].v.cn[1] = + pauseCtx->itemVtx[i + 1].v.cn[1] = pauseCtx->itemVtx[i + 2].v.cn[1] = + pauseCtx->itemVtx[i + 3].v.cn[1] = pauseCtx->itemVtx[i + 0].v.cn[2] = + pauseCtx->itemVtx[i + 1].v.cn[2] = pauseCtx->itemVtx[i + 2].v.cn[2] = + pauseCtx->itemVtx[i + 3].v.cn[2] = 255; + + pauseCtx->itemVtx[i + 0].v.cn[3] = pauseCtx->itemVtx[i + 1].v.cn[3] = pauseCtx->itemVtx[i + 2].v.cn[3] = + pauseCtx->itemVtx[i + 3].v.cn[3] = pauseCtx->alpha; + } else { + // No item equipped on the C button, put the quad out of view + + pauseCtx->itemVtx[i + 2].v.ob[0] = -300; + pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0]; + + pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] = + pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_SELECTED_QUAD_WIDTH; + + pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] = 300; + pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] = + pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_SELECTED_QUAD_HEIGHT; + } + } + } + + if (pauseCtx->pageIndex != PAUSE_MASK) { + if (!sInDungeonScene) { + pauseCtx->mapPageVtx = GRAPH_ALLOC( + gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MAP_WORLD_QUADS + WORLD_MAP_IMAGE_FRAG_NUM) * 4) * sizeof(Vtx)); + j = KaleidoScope_SetPageVertices(play, pauseCtx->mapPageVtx, VTX_PAGE_MAP_WORLD, VTX_PAGE_MAP_WORLD_QUADS); + + for (i = 0, vtx_y = 59; i < WORLD_MAP_IMAGE_FRAG_NUM; i++, j += 4, vtx_y -= WORLD_MAP_IMAGE_FRAG_HEIGHT) { + pauseCtx->mapPageVtx[j + 2].v.ob[0] = 0 - (WORLD_MAP_IMAGE_WIDTH / 2) - 1; + pauseCtx->mapPageVtx[j + 0].v.ob[0] = pauseCtx->mapPageVtx[j + 2].v.ob[0]; + + pauseCtx->mapPageVtx[j + 1].v.ob[0] = pauseCtx->mapPageVtx[j + 3].v.ob[0] = + pauseCtx->mapPageVtx[j + 0].v.ob[0] + WORLD_MAP_IMAGE_WIDTH; + + pauseCtx->mapPageVtx[j + 0].v.ob[1] = pauseCtx->mapPageVtx[j + 1].v.ob[1] = vtx_y + pauseCtx->offsetY; + + pauseCtx->mapPageVtx[j + 2].v.ob[1] = pauseCtx->mapPageVtx[j + 3].v.ob[1] = + pauseCtx->mapPageVtx[j + 0].v.ob[1] - WORLD_MAP_IMAGE_FRAG_HEIGHT; + + pauseCtx->mapPageVtx[j + 0].v.ob[2] = pauseCtx->mapPageVtx[j + 1].v.ob[2] = + pauseCtx->mapPageVtx[j + 2].v.ob[2] = pauseCtx->mapPageVtx[j + 3].v.ob[2] = 0; + + pauseCtx->mapPageVtx[j + 0].v.flag = pauseCtx->mapPageVtx[j + 1].v.flag = + pauseCtx->mapPageVtx[j + 2].v.flag = pauseCtx->mapPageVtx[j + 3].v.flag = 0; + + pauseCtx->mapPageVtx[j + 0].v.tc[0] = pauseCtx->mapPageVtx[j + 0].v.tc[1] = + pauseCtx->mapPageVtx[j + 1].v.tc[1] = pauseCtx->mapPageVtx[j + 2].v.tc[0] = 0; + + pauseCtx->mapPageVtx[j + 1].v.tc[0] = pauseCtx->mapPageVtx[j + 3].v.tc[0] = + WORLD_MAP_IMAGE_WIDTH * (1 << 5); + pauseCtx->mapPageVtx[j + 2].v.tc[1] = pauseCtx->mapPageVtx[j + 3].v.tc[1] = + WORLD_MAP_IMAGE_FRAG_HEIGHT * (1 << 5); + + pauseCtx->mapPageVtx[j + 0].v.cn[0] = pauseCtx->mapPageVtx[j + 2].v.cn[0] = + pauseCtx->mapPageVtx[j + 0].v.cn[1] = pauseCtx->mapPageVtx[j + 2].v.cn[1] = + pauseCtx->mapPageVtx[j + 0].v.cn[2] = pauseCtx->mapPageVtx[j + 2].v.cn[2] = + pauseCtx->mapPageVtx[j + 1].v.cn[0] = pauseCtx->mapPageVtx[j + 3].v.cn[0] = + pauseCtx->mapPageVtx[j + 1].v.cn[1] = pauseCtx->mapPageVtx[j + 3].v.cn[1] = + pauseCtx->mapPageVtx[j + 1].v.cn[2] = pauseCtx->mapPageVtx[j + 3].v.cn[2] = + pauseCtx->mapPageVtx[j + 0].v.cn[3] = pauseCtx->mapPageVtx[j + 2].v.cn[3] = + pauseCtx->mapPageVtx[j + 1].v.cn[3] = pauseCtx->mapPageVtx[j + 3].v.cn[3] = + pauseCtx->alpha; + } + + pauseCtx->mapPageVtx[j - 2].v.ob[1] = pauseCtx->mapPageVtx[j - 1].v.ob[1] = + pauseCtx->mapPageVtx[j - 4].v.ob[1] - (WORLD_MAP_IMAGE_HEIGHT % WORLD_MAP_IMAGE_FRAG_HEIGHT); + + pauseCtx->mapPageVtx[j - 2].v.tc[1] = pauseCtx->mapPageVtx[j - 1].v.tc[1] = + (WORLD_MAP_IMAGE_HEIGHT % WORLD_MAP_IMAGE_FRAG_HEIGHT) * (1 << 5); + + } else { + pauseCtx->mapPageVtx = + GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MAP_DUNGEON_QUADS) * 4) * sizeof(Vtx)); + KaleidoScope_SetPageVertices(play, pauseCtx->mapPageVtx, VTX_PAGE_MAP_DUNGEON, VTX_PAGE_MAP_DUNGEON_QUADS); + } + } + + if (pauseCtx->pageIndex != PAUSE_ITEM) { + pauseCtx->questPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_QUEST_QUADS) * 4) * sizeof(Vtx)); + KaleidoScope_SetPageVertices(play, pauseCtx->questPageVtx, VTX_PAGE_QUEST, VTX_PAGE_QUEST_QUADS); + + pauseCtx->questVtx = GRAPH_ALLOC(gfxCtx, (39 * 4) * sizeof(Vtx)); + + for (k = 0, j = 0; j < 39; j++, k += 4) { + if (j <= QUEST_SWORD) { + pauseCtx->questVtx[k + 0].v.ob[0] = pauseCtx->questVtx[k + 2].v.ob[0] = sQuestVtxRectLeft[j]; + + pauseCtx->questVtx[k + 1].v.ob[0] = pauseCtx->questVtx[k + 3].v.ob[0] = + pauseCtx->questVtx[k + 0].v.ob[0] + sQuestVtxWidths[j]; + + pauseCtx->questVtx[k + 0].v.ob[1] = pauseCtx->questVtx[k + 1].v.ob[1] = + sQuestVtxRectTop[j] + pauseCtx->offsetY; + + pauseCtx->questVtx[k + 2].v.ob[1] = pauseCtx->questVtx[k + 3].v.ob[1] = + pauseCtx->questVtx[k + 0].v.ob[1] - sQuestVtxHeights[j]; + } else { + pauseCtx->questVtx[k + 0].v.ob[0] = pauseCtx->questVtx[k + 2].v.ob[0] = sQuestVtxRectLeft[j] + 2; + + pauseCtx->questVtx[k + 1].v.ob[0] = pauseCtx->questVtx[k + 3].v.ob[0] = + pauseCtx->questVtx[k + 0].v.ob[0] + sQuestVtxWidths[j] - 4; + + pauseCtx->questVtx[k + 0].v.ob[1] = pauseCtx->questVtx[k + 1].v.ob[1] = + sQuestVtxRectTop[j] + pauseCtx->offsetY - 2; + + pauseCtx->questVtx[k + 2].v.ob[1] = pauseCtx->questVtx[k + 3].v.ob[1] = + pauseCtx->questVtx[k + 0].v.ob[1] - sQuestVtxHeights[j] + 4; + } + + pauseCtx->questVtx[k + 0].v.ob[2] = pauseCtx->questVtx[k + 1].v.ob[2] = pauseCtx->questVtx[k + 2].v.ob[2] = + pauseCtx->questVtx[k + 3].v.ob[2] = 0; + + pauseCtx->questVtx[k + 0].v.flag = pauseCtx->questVtx[k + 1].v.flag = pauseCtx->questVtx[k + 2].v.flag = + pauseCtx->questVtx[k + 3].v.flag = 0; + + pauseCtx->questVtx[k + 0].v.tc[0] = pauseCtx->questVtx[k + 0].v.tc[1] = pauseCtx->questVtx[k + 1].v.tc[1] = + pauseCtx->questVtx[k + 2].v.tc[0] = 0; + + pauseCtx->questVtx[k + 1].v.tc[0] = pauseCtx->questVtx[k + 3].v.tc[0] = sQuestVtxWidths[j] << 5; + pauseCtx->questVtx[k + 2].v.tc[1] = pauseCtx->questVtx[k + 3].v.tc[1] = sQuestVtxHeights[j] << 5; + + pauseCtx->questVtx[k + 0].v.cn[0] = pauseCtx->questVtx[k + 1].v.cn[0] = pauseCtx->questVtx[k + 2].v.cn[0] = + pauseCtx->questVtx[k + 3].v.cn[0] = pauseCtx->questVtx[k + 0].v.cn[1] = + pauseCtx->questVtx[k + 1].v.cn[1] = pauseCtx->questVtx[k + 2].v.cn[1] = + pauseCtx->questVtx[k + 3].v.cn[1] = pauseCtx->questVtx[k + 0].v.cn[2] = + pauseCtx->questVtx[k + 1].v.cn[2] = pauseCtx->questVtx[k + 2].v.cn[2] = + pauseCtx->questVtx[k + 3].v.cn[2] = 255; + + pauseCtx->questVtx[k + 0].v.cn[3] = pauseCtx->questVtx[k + 1].v.cn[3] = pauseCtx->questVtx[k + 2].v.cn[3] = + pauseCtx->questVtx[k + 3].v.cn[3] = pauseCtx->alpha; + } + } + + if (pauseCtx->pageIndex != PAUSE_MAP) { + pauseCtx->maskPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MASK_QUADS) * 4) * sizeof(Vtx)); + KaleidoScope_SetPageVertices(play, pauseCtx->maskPageVtx, VTX_PAGE_MASK, VTX_PAGE_MASK_QUADS); + + pauseCtx->maskVtx = GRAPH_ALLOC(gfxCtx, (QUAD_MASK_MAX * 4) * sizeof(Vtx)); + + // Loop over grid rows + for (k = 0, i = 0, vtx_y = (MASK_GRID_ROWS * MASK_GRID_CELL_HEIGHT) / 2 - 6; k < MASK_GRID_ROWS; + k++, vtx_y -= MASK_GRID_CELL_HEIGHT) { + // Loop over grid columns + for (vtx_x = 0 - (MASK_GRID_COLS * MASK_GRID_CELL_WIDTH) / 2, j = 0; j < MASK_GRID_COLS; + j++, i += 4, vtx_x += MASK_GRID_CELL_WIDTH) { + pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0] = vtx_x + MASK_GRID_QUAD_MARGIN; + pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] = + pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_QUAD_WIDTH; + + pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] = + vtx_y + pauseCtx->offsetY - MASK_GRID_QUAD_MARGIN; + pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] = + pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_QUAD_HEIGHT; + + pauseCtx->maskVtx[i + 0].v.ob[2] = pauseCtx->maskVtx[i + 1].v.ob[2] = pauseCtx->maskVtx[i + 2].v.ob[2] = + pauseCtx->maskVtx[i + 3].v.ob[2] = 0; + + pauseCtx->maskVtx[i + 0].v.flag = pauseCtx->maskVtx[i + 1].v.flag = pauseCtx->maskVtx[i + 2].v.flag = + pauseCtx->maskVtx[i + 3].v.flag = 0; + + pauseCtx->maskVtx[i + 0].v.tc[0] = pauseCtx->maskVtx[i + 0].v.tc[1] = pauseCtx->maskVtx[i + 1].v.tc[1] = + pauseCtx->maskVtx[i + 2].v.tc[0] = 0; + + pauseCtx->maskVtx[i + 1].v.tc[0] = pauseCtx->maskVtx[i + 2].v.tc[1] = pauseCtx->maskVtx[i + 3].v.tc[0] = + pauseCtx->maskVtx[i + 3].v.tc[1] = MASK_GRID_QUAD_TEX_SIZE * (1 << 5); + + pauseCtx->maskVtx[i + 0].v.cn[0] = pauseCtx->maskVtx[i + 1].v.cn[0] = pauseCtx->maskVtx[i + 2].v.cn[0] = + pauseCtx->maskVtx[i + 3].v.cn[0] = pauseCtx->maskVtx[i + 0].v.cn[1] = + pauseCtx->maskVtx[i + 1].v.cn[1] = pauseCtx->maskVtx[i + 2].v.cn[1] = + pauseCtx->maskVtx[i + 3].v.cn[1] = pauseCtx->maskVtx[i + 0].v.cn[2] = + pauseCtx->maskVtx[i + 1].v.cn[2] = pauseCtx->maskVtx[i + 2].v.cn[2] = + pauseCtx->maskVtx[i + 3].v.cn[2] = 255; + + pauseCtx->maskVtx[i + 0].v.cn[3] = pauseCtx->maskVtx[i + 1].v.cn[3] = pauseCtx->maskVtx[i + 2].v.cn[3] = + pauseCtx->maskVtx[i + 3].v.cn[3] = 255; + } + } + + // QUAD_MASK_GRID_SELECTED_C_LEFT, QUAD_MASK_GRID_SELECTED_C_DOWN, QUAD_MASK_GRID_SELECTED_C_RIGHT + + for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++, i += 4) { + if (GET_CUR_FORM_BTN_SLOT(j) != ITEM_NONE) { + k = (GET_CUR_FORM_BTN_SLOT(j) - ITEM_NUM_SLOTS) * 4; + + pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0] = + pauseCtx->maskVtx[k].v.ob[0] + MASK_GRID_SELECTED_QUAD_MARGIN; + + pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] = + pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH; + + pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] = + pauseCtx->maskVtx[k].v.ob[1] - MASK_GRID_SELECTED_QUAD_MARGIN; + + pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] = + pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT; + + pauseCtx->maskVtx[i + 0].v.ob[2] = pauseCtx->maskVtx[i + 1].v.ob[2] = pauseCtx->maskVtx[i + 2].v.ob[2] = + pauseCtx->maskVtx[i + 3].v.ob[2] = 0; + + pauseCtx->maskVtx[i + 0].v.flag = pauseCtx->maskVtx[i + 1].v.flag = pauseCtx->maskVtx[i + 2].v.flag = + pauseCtx->maskVtx[i + 3].v.flag = 0; + + pauseCtx->maskVtx[i + 0].v.tc[0] = pauseCtx->maskVtx[i + 0].v.tc[1] = pauseCtx->maskVtx[i + 1].v.tc[1] = + pauseCtx->maskVtx[i + 2].v.tc[0] = 0; + + pauseCtx->maskVtx[i + 1].v.tc[0] = pauseCtx->maskVtx[i + 2].v.tc[1] = pauseCtx->maskVtx[i + 3].v.tc[0] = + pauseCtx->maskVtx[i + 3].v.tc[1] = MASK_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5); + + pauseCtx->maskVtx[i + 0].v.cn[0] = pauseCtx->maskVtx[i + 1].v.cn[0] = pauseCtx->maskVtx[i + 2].v.cn[0] = + pauseCtx->maskVtx[i + 3].v.cn[0] = pauseCtx->maskVtx[i + 0].v.cn[1] = + pauseCtx->maskVtx[i + 1].v.cn[1] = pauseCtx->maskVtx[i + 2].v.cn[1] = + pauseCtx->maskVtx[i + 3].v.cn[1] = pauseCtx->maskVtx[i + 0].v.cn[2] = + pauseCtx->maskVtx[i + 1].v.cn[2] = pauseCtx->maskVtx[i + 2].v.cn[2] = + pauseCtx->maskVtx[i + 3].v.cn[2] = 255; + + pauseCtx->maskVtx[i + 0].v.cn[3] = pauseCtx->maskVtx[i + 1].v.cn[3] = pauseCtx->maskVtx[i + 2].v.cn[3] = + pauseCtx->maskVtx[i + 3].v.cn[3] = pauseCtx->alpha; + } else { + pauseCtx->maskVtx[i + 2].v.ob[0] = -300; + pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0]; + + pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] = + pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH; + + pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] = 300; + pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] = + pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT; + } + } + } + + pauseCtx->cursorVtx = GRAPH_ALLOC(play->state.gfxCtx, (PAUSE_QUAD_CURSOR_MAX * 4) * sizeof(Vtx)); + + for (i = 0; i < (PAUSE_QUAD_CURSOR_MAX * 4); i++) { + pauseCtx->cursorVtx[i].v.ob[0] = pauseCtx->cursorVtx[i].v.ob[1] = pauseCtx->cursorVtx[i].v.ob[2] = 0; + + pauseCtx->cursorVtx[i].v.flag = 0; + + pauseCtx->cursorVtx[i].v.tc[0] = pauseCtx->cursorVtx[i].v.tc[1] = 0; + + pauseCtx->cursorVtx[i].v.cn[0] = pauseCtx->cursorVtx[i].v.cn[1] = pauseCtx->cursorVtx[i].v.cn[2] = + pauseCtx->cursorVtx[i].v.cn[3] = 255; + } + + // PAUSE_QUAD_CURSOR_0 + pauseCtx->cursorVtx[1].v.tc[0] = pauseCtx->cursorVtx[2].v.tc[1] = pauseCtx->cursorVtx[3].v.tc[0] = + pauseCtx->cursorVtx[3].v.tc[1] + // PAUSE_QUAD_CURSOR_1 + = pauseCtx->cursorVtx[5].v.tc[0] = pauseCtx->cursorVtx[6].v.tc[1] = pauseCtx->cursorVtx[7].v.tc[0] = + pauseCtx->cursorVtx[7].v.tc[1] + // PAUSE_QUAD_CURSOR_2 + = pauseCtx->cursorVtx[9].v.tc[0] = pauseCtx->cursorVtx[10].v.tc[1] = pauseCtx->cursorVtx[11].v.tc[0] = + pauseCtx->cursorVtx[11].v.tc[1] + // PAUSE_QUAD_CURSOR_3 + = pauseCtx->cursorVtx[13].v.tc[0] = pauseCtx->cursorVtx[14].v.tc[1] = pauseCtx->cursorVtx[15].v.tc[0] = + pauseCtx->cursorVtx[15].v.tc[1] = 16 * (1 << 5); + + // PAUSE_QUAD_CURSOR_4 + pauseCtx->cursorVtx[17].v.tc[0] = pauseCtx->cursorVtx[18].v.tc[1] = pauseCtx->cursorVtx[19].v.tc[0] = + pauseCtx->cursorVtx[19].v.tc[1] = 32 * (1 << 5); + + pauseCtx->infoPanelVtx = GRAPH_ALLOC(gfxCtx, 28 * sizeof(Vtx)); + + if ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) || IS_PAUSE_STATE_GAMEOVER) { + pauseCtx->promptPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_SAVE_QUADS) * 4) * sizeof(Vtx)); + KaleidoScope_SetPageVertices(play, pauseCtx->promptPageVtx, VTX_PAGE_PROMPT, VTX_PAGE_SAVE_QUADS); + } +} + f32 D_8082BCB4[] = { -62.0f, -36.0f, -10.0f, 16.0f, 42.0f, 68.0f, }; @@ -458,66 +1592,42 @@ f32 D_8082BE28[] = { -11.0f, -11.0f, -11.0f, -11.0f, -11.0f, -11.0f, 27.0f, -53.0f, -53.0f, 14.0f, 26.0f, }; -s16 D_8082BE84 = 0; - -void func_80821900(void* segment, u32 texIndex) { - CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0x400); -} - -void func_8082192C(void* segment, u32 texIndex) { - CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0xA00); -} - -void func_80821958(void* segment, u32 texIndex) { - CmpDma_LoadFile(SEGMENT_ROM_START(item_name_static), texIndex, segment, 0x400); -} - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_MoveCursorToSpecialPos.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80821A04.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_DrawTexQuadRGBA32.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80821CC4.s") - -void KaleidoScope_HandlePageToggles(PlayState* play, Input* input); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_HandlePageToggles.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80821F30.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_808221DC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80823350.s") - -void KaleidoScope_UpdateNamePanel(PlayState* play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateNamePanel.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_808248D0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80824B90.s") - -void KaleidoScope_UpdateOwlWarpNamePanel(PlayState* play); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateOwlWarpNamePanel.s") - -void KaleidoScope_UpdateSwitchPage(PlayState* play, Input* input); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_UpdateSwitchPage.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_SetView.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80825A50.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80825E28.s") - #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_808274DC.s") #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80827A8C.s") +s16 D_8082BE84 = 0; + #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/func_80827E08.s") #pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_Draw.s") -void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_kaleido_scope/KaleidoScope_GrayOutTextureRGBA32.s") +void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) { + u32 rgb; + u32 gray; + u16 i; + s32 j; + + //! FAKE + if (texture == NULL) {} + + for (i = 0; i < pixelCount; i++) { + //! FAKE + j = i; + if ((texture[j] & 0xFFFFFF00) != 0) { + rgb = texture[j] >> 8; + gray = ((((rgb & 0xFF0000) >> 16) + ((rgb & 0xFF00) >> 7) + (rgb & 0xFF)) / 7) & 0xFF; + + rgb = gray; + rgb <<= 8; + rgb |= gray; + rgb <<= 8; + rgb |= gray; + + texture[j] = (rgb << 8) | (texture[j] & 0xFF); + } + } +} void KaleidoScope_UpdateOpening(PlayState* play) { PauseContext* pauseCtx = &play->pauseCtx; diff --git a/tools/disasm/disasm.py b/tools/disasm/disasm.py index 0f5e16464..e7b0f4d81 100755 --- a/tools/disasm/disasm.py +++ b/tools/disasm/disasm.py @@ -177,6 +177,10 @@ def proper_name(symbol, in_data=False, is_symbol=True): return variables_ast[0x809C46DC][0] + " + 0x14" elif symbol == 0x801EF66D: # z_message_nes constant-folding stray fairy array return variables_ast[0x801EF670][0] + f" - 0x{0x801EF670 - 0x801EF66D:X}" + elif symbol == 0x801EF51D: # z_message constant-folding stray fairy array + return variables_ast[0x801EF670][0] + f" - 0x{0x801EF670 - 0x801EF51D:X}" + elif symbol == 0x801D0D7A: # play_hireso constant-folding D_801D0D80 array + return variables_ast[0x801D0D80][0] + f" - 0x{0x801D0D80 - 0x801D0D7A:X}" elif symbol == 0x80A09740: # boss_07 symbol with large addend folded into %lo return variables_ast[0x80A09A60][0] + f" - 0x{0x80A09A60 - 0x80A09740:X}" # bg_ikana_mirror symbol with large addend folded into %lo diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index a410b60da..5041005a1 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -696,10 +696,10 @@ 0x800B5E68:("TitleCard_Update",), 0x800B5F24:("TitleCard_Draw",), 0x800B6434:("func_800B6434",), - 0x800B6468:("func_800B6468",), - 0x800B6474:("func_800B6474",), - 0x800B648C:("func_800B648C",), - 0x800B64FC:("func_800B64FC",), + 0x800B6468:("Actor_InitPlayerImpact",), + 0x800B6474:("Actor_UpdatePlayerImpact",), + 0x800B648C:("Actor_SetPlayerImpact",), + 0x800B64FC:("Actor_GetPlayerImpact",), 0x800B6584:("func_800B6584",), 0x800B6608:("func_800B6608",), 0x800B6680:("func_800B6680",), @@ -859,9 +859,9 @@ 0x800BC5B8:("Actor_IsTargeted",), 0x800BC5EC:("Actor_OtherIsTargeted",), 0x800BC620:("func_800BC620",), - 0x800BC770:("Actor_AddQuake",), - 0x800BC7D8:("Actor_AddQuakeWithSpeed",), - 0x800BC848:("func_800BC848",), + 0x800BC770:("Actor_RequestQuake",), + 0x800BC7D8:("Actor_RequestQuakeWithSpeed",), + 0x800BC848:("Actor_RequestQuakeAndRumble",), 0x800BC8B8:("Actor_DrawDoorLock",), 0x800BCB50:("Actor_SpawnShieldParticlesMetal",), 0x800BCB70:("Actor_SetColorFilter",), @@ -1115,16 +1115,16 @@ 0x800CB210:("Camera_fabsf",), 0x800CB240:("Camera_Vec3fMagnitude",), 0x800CB270:("Camera_QuadraticAttenuation",), - 0x800CB330:("Camera_LerpCeilF",), - 0x800CB398:("Camera_LerpCeilS",), - 0x800CB42C:("Camera_LerpFloorS",), - 0x800CB4C0:("Camera_LerpCeilVec3f",), + 0x800CB330:("Camera_ScaledStepToCeilF",), + 0x800CB398:("Camera_ScaledStepToCeilS",), + 0x800CB42C:("Camera_ScaledStepToFloorS",), + 0x800CB4C0:("Camera_ScaledStepToCeilVec3f",), 0x800CB544:("Camera_SetUpdateRatesFastPitch",), 0x800CB584:("Camera_SetUpdateRatesFastYaw",), 0x800CB5DC:("Camera_SetUpdateRatesSlow",), 0x800CB60C:("Camera_Vec3sToVec3f",), 0x800CB674:("Camera_AngleDiffAndScale",), - 0x800CB6C8:("Camera_UpdateAtActorOffset",), + 0x800CB6C8:("Camera_SetFocalActorAtOffset",), 0x800CB700:("Camera_GetFocalActorHeight",), 0x800CB780:("Camera_GetRunSpeedLimit",), 0x800CB7CC:("func_800CB7CC",), @@ -1147,41 +1147,41 @@ 0x800CBC30:("func_800CBC30",), 0x800CBC84:("func_800CBC84",), 0x800CBFA4:("func_800CBFA4",), - 0x800CC000:("func_800CC000",), - 0x800CC128:("func_800CC128",), - 0x800CC1C4:("func_800CC1C4",), + 0x800CC000:("Camera_BgCheckInfo",), + 0x800CC128:("Camera_BgCheck",), + 0x800CC1C4:("Camera_CheckOOB",), 0x800CC260:("func_800CC260",), - 0x800CC488:("func_800CC488",), - 0x800CC56C:("func_800CC56C",), - 0x800CC5C8:("func_800CC5C8",), + 0x800CC488:("Camera_GetFloorYNorm",), + 0x800CC56C:("Camera_GetFloorY",), + 0x800CC5C8:("Camera_GetFloorYLayer",), 0x800CC740:("Camera_GetBgCamOrActorCsCamSetting",), 0x800CC7A8:("Camera_GetBgCamOrActorCsCamFuncData",), 0x800CC804:("Camera_GetBgCamIndex",), 0x800CC874:("Camera_GetWaterBoxBgCamSetting",), 0x800CC938:("func_800CC938",), - 0x800CC958:("func_800CC958",), - 0x800CC9C0:("func_800CC9C0",), + 0x800CC958:("Camera_CalcXZAngle",), + 0x800CC9C0:("Camera_GetPitchAdjFromFloorHeightDiffs",), 0x800CCCEC:("func_800CCCEC",), - 0x800CD04C:("func_800CD04C",), - 0x800CD288:("func_800CD288",), - 0x800CD2E0:("func_800CD2E0",), - 0x800CD2F0:("func_800CD2F0",), - 0x800CD3E4:("func_800CD3E4",), + 0x800CD04C:("Camera_CalcUpVec",), + 0x800CD288:("Camera_ClampLerpScale",), + 0x800CD2E0:("Camera_ResetActionFuncState",), + 0x800CD2F0:("Camera_UpdateInterface",), + 0x800CD3E4:("Camera_BgCheckCorner",), 0x800CD44C:("func_800CD44C",), - 0x800CD634:("func_800CD634",), + 0x800CD634:("Camera_CalcSlopeYAdj",), 0x800CD6CC:("func_800CD6CC",), - 0x800CD6F8:("func_800CD6F8",), - 0x800CD834:("func_800CD834",), - 0x800CDA14:("func_800CDA14",), - 0x800CDB6C:("func_800CDB6C",), - 0x800CDE6C:("func_800CDE6C",), - 0x800CE2B8:("func_800CE2B8",), - 0x800CE5E0:("func_800CE5E0",), - 0x800CE79C:("func_800CE79C",), - 0x800CE930:("func_800CE930",), - 0x800CEAD8:("func_800CEAD8",), - 0x800CEC38:("func_800CEC38",), - 0x800CED90:("func_800CED90",), + 0x800CD6F8:("Camera_CalcAtDefault",), + 0x800CD834:("Camera_CalcAtForScreen",), + 0x800CDA14:("Camera_CalcAtForNormal1",), + 0x800CDB6C:("Camera_CalcAtForParallel",), + 0x800CDE6C:("Camera_CalcAtForFriendlyLockOn",), + 0x800CE2B8:("Camera_CalcAtForEnemyLockOn",), + 0x800CE5E0:("Camera_CalcAtForHorse",), + 0x800CE79C:("Camera_ClampDist1",), + 0x800CE930:("Camera_ClampDist2",), + 0x800CEAD8:("Camera_CalcDefaultPitch",), + 0x800CEC38:("Camera_CalcDefaultYaw",), + 0x800CED90:("Camera_CalcDefaultSwing",), 0x800CF3A4:("Camera_Noop",), 0x800CF3B4:("Camera_Normal1",), 0x800D0874:("Camera_Normal2",), @@ -1253,48 +1253,48 @@ 0x800DD11C:("Camera_Special7",), 0x800DD13C:("Camera_Special8",), 0x800DD5B8:("Camera_Special9",), - 0x800DDD58:("Camera_Alloc",), - 0x800DDDA8:("Camera_Free",), + 0x800DDD58:("Camera_Create",), + 0x800DDDA8:("Camera_Destroy",), 0x800DDDD0:("Camera_Init",), 0x800DDFE0:("func_800DDFE0",), - 0x800DE0E0:("func_800DE0E0",), - 0x800DE0EC:("Camera_InitPlayerSettings",), + 0x800DE0E0:("Camera_Stub800DE0E0",), + 0x800DE0EC:("Camera_InitFocalActorSettings",), 0x800DE308:("Camera_ChangeStatus",), - 0x800DE324:("func_800DE324",), - 0x800DE62C:("func_800DE62C",), - 0x800DE840:("func_800DE840",), - 0x800DE890:("func_800DE890",), - 0x800DE954:("func_800DE954",), + 0x800DE324:("Camera_UpdateWater",), + 0x800DE62C:("Camera_EarthquakeDay3",), + 0x800DE840:("Camera_UpdateHotRoom",), + 0x800DE890:("Camera_SetSwordDistortion",), + 0x800DE954:("Camera_RequestGiantsMaskSetting",), 0x800DE9B0:("Camera_Update",), 0x800DF498:("func_800DF498",), - 0x800DF4D0:("Camera_SetMode",), + 0x800DF4D0:("Camera_ChangeModeFlags",), 0x800DF840:("Camera_ChangeMode",), - 0x800DF86C:("func_800DF86C",), - 0x800DF8EC:("func_800DF8EC",), + 0x800DF86C:("Camera_CheckValidMode",), + 0x800DF8EC:("Camera_ChangeSettingFlags",), 0x800DFAC8:("Camera_ChangeSetting",), - 0x800DFB14:("Camera_ChangeDataIdx",), - 0x800DFC1C:("func_800DFC1C",), - 0x800DFC40:("func_800DFC40",), + 0x800DFB14:("Camera_ChangeActorCsCamIndex",), + 0x800DFC1C:("Camera_GetInputDir",), + 0x800DFC40:("Camera_GetInputDirPitch",), 0x800DFC68:("Camera_GetInputDirYaw",), 0x800DFC90:("Camera_GetCamDir",), 0x800DFCB4:("Camera_GetCamDirPitch",), 0x800DFCDC:("Camera_GetCamDirYaw",), 0x800DFD04:("Camera_AddQuake",), 0x800DFD78:("Camera_SetViewParam",), - 0x800DFEF0:("func_800DFEF0",), - 0x800DFF18:("func_800DFF18",), - 0x800DFF34:("func_800DFF34",), - 0x800DFF44:("func_800DFF44",), - 0x800DFF60:("Camera_SetFlags",), - 0x800DFF84:("Camera_ClearFlags",), + 0x800DFEF0:("Camera_UnsetViewFlag",), + 0x800DFF18:("Camera_OverwriteStateFlags",), + 0x800DFF34:("Camera_ResetActionFuncStateUnused",), + 0x800DFF44:("Camera_SetCsParams",), + 0x800DFF60:("Camera_SetStateFlag",), + 0x800DFF84:("Camera_UnsetStateFlag",), 0x800DFFAC:("Camera_ChangeDoorCam",), 0x800E007C:("Camera_Copy",), - 0x800E01AC:("func_800E01AC",), + 0x800E01AC:("Camera_IsDbgCamEnabled",), 0x800E01B8:("Camera_GetQuakeOffset",), - 0x800E01DC:("func_800E01DC",), - 0x800E0228:("func_800E0228",), + 0x800E01DC:("Camera_SetCameraData",), + 0x800E0228:("Camera_GetNegOne",), 0x800E0238:("func_800E0238",), - 0x800E02AC:("Camera_SetToTrackActor",), + 0x800E02AC:("Camera_SetFocalActor",), 0x800E0308:("Camera_SetTargetActor",), 0x800E031C:("Camera_GetWaterYPos",), 0x800E0348:("func_800E0348",), @@ -2072,17 +2072,17 @@ 0x8010C36C:("OLib_ClampMaxDist",), 0x8010C3D4:("OLib_Vec3fDistNormalize",), 0x8010C484:("OLib_VecSphToVec3f",), - 0x8010C530:("OLib_VecSphGeoToVec3f",), + 0x8010C530:("OLib_VecGeoToVec3f",), 0x8010C574:("OLib_Vec3fToVecSph",), - 0x8010C6C8:("OLib_Vec3fToVecSphGeo",), + 0x8010C6C8:("OLib_Vec3fToVecGeo",), 0x8010C710:("OLib_Vec3fDiffToVecSph",), - 0x8010C764:("OLib_Vec3fDiffToVecSphGeo",), - 0x8010C7B8:("OLib_VecSphAddToVec3f",), + 0x8010C764:("OLib_Vec3fDiffToVecGeo",), + 0x8010C7B8:("OLib_AddVecGeoToVec3f",), 0x8010C838:("OLib_Vec3fDiffRad",), 0x8010C8C8:("OLib_Vec3fDiffDegF",), 0x8010C930:("OLib_Vec3fDiffBinAng",), - 0x8010C9C8:("OLib_DbCameraVec3fDiff",), - 0x8010CAA0:("OLib_DbCameraVec3fSum",), + 0x8010C9C8:("OLib_Vec3fDiff",), + 0x8010CAA0:("OLib_Vec3fAdd",), 0x8010CB80:("Gfx_DrawTexRectRGBA16",), 0x8010CD98:("Gfx_DrawTexRectIA8",), 0x8010CFBC:("Gfx_DrawTexRectIA8_DropShadow",), @@ -2289,28 +2289,28 @@ 0x8012A4D0:("Quake_CallbackType2",), 0x8012A540:("Quake_CallbackType4",), 0x8012A5D8:("Quake_GetFreeIndex",), - 0x8012A638:("Quake_AddImpl",), - 0x8012A6F0:("Quake_RemoveRequest",), + 0x8012A638:("Quake_RequestImpl",), + 0x8012A6F0:("Quake_Remove",), 0x8012A718:("Quake_GetRequest",), 0x8012A774:("Quake_SetValue",), 0x8012A8A8:("Quake_SetSpeed",), - 0x8012A8F0:("Quake_SetCountdown",), - 0x8012A940:("Quake_GetCountdown",), - 0x8012A978:("Quake_SetQuakeValues",), - 0x8012A9E0:("Quake_SetQuakeValues2",), + 0x8012A8F0:("Quake_SetDuration",), + 0x8012A940:("Quake_GetTimeLeft",), + 0x8012A978:("Quake_SetPerturbations",), + 0x8012A9E0:("Quake_SetOrientation",), 0x8012AA48:("Quake_Init",), - 0x8012AA9C:("Quake_Add",), - 0x8012AAC0:("Quake_Remove",), - 0x8012AB08:("Quake_Calc",), + 0x8012AA9C:("Quake_Request",), + 0x8012AAC0:("Quake_RemoveRequest",), + 0x8012AB08:("Quake_Update",), 0x8012AE68:("Distortion_Init",), - 0x8012AEAC:("Distortion_SetCountdown",), - 0x8012AED4:("Distortion_GetCountdown",), + 0x8012AEAC:("Distortion_SetDuration",), + 0x8012AED4:("Distortion_GetTimeLeft",), 0x8012AEE4:("Distortion_GetType",), - 0x8012AEF4:("Distortion_SetType",), - 0x8012AF18:("Distortion_ClearType",), + 0x8012AEF4:("Distortion_Request",), + 0x8012AF18:("Distortion_RemoveRequest",), 0x8012AF38:("Distortion_GetUnderwaterCurrentSpeed",), 0x8012AF9C:("Distortion_Update",), - 0x8012BBE8:("Quake_NumActiveQuakes",), + 0x8012BBE8:("Quake_GetNumActiveQuakes",), 0x8012BC50:("Gfx_SetFog",), 0x8012BD8C:("Gfx_SetFogWithSync",), 0x8012BF08:("Gfx_SetFog2",), @@ -4205,7 +4205,7 @@ 0x80819238:("KaleidoScope_DrawInventoryEditor",), 0x80819F04:("KaleidoScope_UpdateInventoryEditor",), 0x8081B240:("KaleidoScope_DrawAmmoCount",), - 0x8081B6BC:("KaleidoScope_SetCursorVtx",), + 0x8081B6BC:("KaleidoScope_SetCursorVtxPos",), 0x8081B6EC:("KaleidoScope_DrawItemSelect",), 0x8081BCA8:("KaleidoScope_UpdateItemCursor",), 0x8081C684:("KaleidoScope_UpdateItemEquip",), @@ -4226,17 +4226,17 @@ 0x80821AD4:("KaleidoScope_DrawTexQuadRGBA32",), 0x80821CC4:("func_80821CC4",), 0x80821D84:("KaleidoScope_HandlePageToggles",), - 0x80821F30:("func_80821F30",), - 0x808221DC:("func_808221DC",), + 0x80821F30:("KaleidoScope_DrawPageSections",), + 0x808221DC:("KaleidoScope_DrawPages",), 0x80823350:("func_80823350",), 0x80824738:("KaleidoScope_UpdateNamePanel",), - 0x808248D0:("func_808248D0",), + 0x808248D0:("KaleidoScope_DrawOwlWarpMapPage",), 0x80824B90:("func_80824B90",), 0x808256E4:("KaleidoScope_UpdateOwlWarpNamePanel",), 0x8082585C:("KaleidoScope_UpdateSwitchPage",), 0x808259D4:("KaleidoScope_SetView",), - 0x80825A50:("func_80825A50",), - 0x80825E28:("func_80825E28",), + 0x80825A50:("KaleidoScope_SetPageVertices",), + 0x80825E28:("KaleidoScope_SetVertices",), 0x808274DC:("func_808274DC",), 0x80827A8C:("func_80827A8C",), 0x80827E08:("func_80827E08",), @@ -6504,7 +6504,7 @@ 0x808E06B0:("DoorAna_Update",), 0x808E0704:("DoorAna_Draw",), 0x808E0830:("EnEncount1_Init",), - 0x808E0954:("func_808E0954",), + 0x808E0954:("EnEncount1_SpawnActor",), 0x808E0DA8:("EnEncount1_Update",), 0x808E0E40:("DemoTreLgt_Init",), 0x808E0EBC:("DemoTreLgt_Destroy",), @@ -8997,37 +8997,37 @@ 0x809C0E30:("EnWarpTag_GrottoReturn",), 0x809C0F18:("EnWarptag_Update",), 0x809C0F3C:("EnWarpTag_Draw",), - 0x809C10B0:("func_809C10B0",), - 0x809C1124:("func_809C1124",), - 0x809C1158:("func_809C1158",), - 0x809C11EC:("func_809C11EC",), - 0x809C1304:("func_809C1304",), - 0x809C1424:("func_809C1424",), - 0x809C14D0:("func_809C14D0",), - 0x809C15BC:("func_809C15BC",), - 0x809C165C:("func_809C165C",), - 0x809C16DC:("func_809C16DC",), - 0x809C1C9C:("func_809C1C9C",), - 0x809C1D64:("func_809C1D64",), - 0x809C1EC8:("func_809C1EC8",), - 0x809C2060:("func_809C2060",), - 0x809C21E0:("func_809C21E0",), - 0x809C2504:("func_809C2504",), - 0x809C2594:("func_809C2594",), - 0x809C25E4:("func_809C25E4",), - 0x809C2680:("func_809C2680",), - 0x809C26E4:("func_809C26E4",), - 0x809C2730:("func_809C2730",), - 0x809C2788:("func_809C2788",), - 0x809C2824:("func_809C2824",), - 0x809C28B8:("func_809C28B8",), - 0x809C2A64:("func_809C2A64",), - 0x809C2BE4:("func_809C2BE4",), - 0x809C2C9C:("func_809C2C9C",), - 0x809C2D0C:("func_809C2D0C",), - 0x809C2EC4:("func_809C2EC4",), - 0x809C2F34:("func_809C2F34",), - 0x809C2FA0:("func_809C2FA0",), + 0x809C10B0:("EnAob01_Blink",), + 0x809C1124:("EnAob01_AdvanceTime",), + 0x809C1158:("EnAob01_InitializeDogPaths",), + 0x809C11EC:("EnAob01_SpawnDogs",), + 0x809C1304:("EnAob01_SpawnRacedogs",), + 0x809C1424:("EnAob01_ProcessLaughAnim",), + 0x809C14D0:("EnAob01_ProcessSurpriseAnim",), + 0x809C15BC:("EnAob01_ProcessIdleAnim",), + 0x809C165C:("EnAob01_UpdateCollision",), + 0x809C16DC:("EnAob01_BeforeRace_HandleConversation",), + 0x809C1C9C:("EnAob01_BeforeRace_StartRace",), + 0x809C1D64:("EnAob01_BeforeRace_RespondToPlayAgainQuestion",), + 0x809C1EC8:("EnAob01_UpdateCommon",), + 0x809C2060:("EnAob01_BeforeRace_Idle",), + 0x809C21E0:("EnAob01_BeforeRace_Talk",), + 0x809C2504:("EnAob01_Race_DogHasReachedNextCutsceneTrigger",), + 0x809C2594:("EnAob01_Race_FollowSelectedDog",), + 0x809C25E4:("EnAob01_Race_IsRaceOver",), + 0x809C2680:("EnAob01_Race_CurrentCutsceneHasEnded",), + 0x809C26E4:("EnAob01_Race_SkipNonRaceCutscene",), + 0x809C2730:("EnAob01_Race_HandleRaceCutscene",), + 0x809C2788:("EnAob01_Race_HandleRaceEndCutscene",), + 0x809C2824:("EnAob01_Race_StartCutscene",), + 0x809C28B8:("EnAob01_AfterRace_GiveRaceResult",), + 0x809C2A64:("EnAob01_AfterRace_GiveReward",), + 0x809C2BE4:("EnAob01_AfterRace_AfterGivingReward",), + 0x809C2C9C:("EnAob01_AfterRace_AskToPlayAgain",), + 0x809C2D0C:("EnAob01_AfterRace_Talk",), + 0x809C2EC4:("EnAob01_PlayerIsHoldingDog",), + 0x809C2F34:("EnAob01_Race_HidePlayer",), + 0x809C2FA0:("EnAob01_InitializeDogTextOffsets",), 0x809C3190:("EnAob01_Init",), 0x809C3350:("EnAob01_Destroy",), 0x809C339C:("EnAob01_Update",), @@ -9710,7 +9710,7 @@ 0x80A134B0:("func_80A134B0",), 0x80A134F4:("func_80A134F4",), 0x80A13564:("func_80A13564",), - 0x80A136B8:("func_80A136B8",), + 0x80A136B8:("EnGo_RequestQuake",), 0x80A13728:("func_80A13728",), 0x80A137C0:("func_80A137C0",), 0x80A139E4:("func_80A139E4",), @@ -10620,7 +10620,7 @@ 0x80A53E60:("func_80A53E60",), 0x80A541F4:("func_80A541F4",), 0x80A54600:("func_80A54600",), - 0x80A54980:("ObjHugebombiwa_AddQuake",), + 0x80A54980:("ObjHugebombiwa_RequestQuakeAndRumble",), 0x80A54A0C:("func_80A54A0C",), 0x80A54AC0:("ObjHugebombiwa_Init",), 0x80A54BC4:("ObjHugebombiwa_Destroy",), @@ -11433,7 +11433,7 @@ 0x80A9BC0C:("func_80A9BC0C",), 0x80A9BD24:("func_80A9BD24",), 0x80A9C058:("func_80A9C058",), - 0x80A9C18C:("func_80A9C18C",), + 0x80A9C18C:("BgHakuginPost_RequestQuakeAndRumble",), 0x80A9C228:("func_80A9C228",), 0x80A9C634:("func_80A9C634",), 0x80A9C854:("func_80A9C854",), @@ -12211,7 +12211,7 @@ 0x80AD566C:("EnTrt2_TransformLimbDraw",), 0x80AD56E8:("func_80AD56E8",), 0x80AD5BB0:("ObjTokeiStep_SetSysMatrix",), - 0x80AD5BE8:("ObjTokeiStep_AddQuake",), + 0x80AD5BE8:("ObjTokeiStep_RequestQuakeAndRumble",), 0x80AD5C70:("ObjTokeiStep_SpawnDust",), 0x80AD5DFC:("ObjTokeiStep_InitSteps",), 0x80AD5EB8:("ObjTokeiStep_InitStepsOpen",), @@ -15199,7 +15199,7 @@ 0x80BAA6D0:("EnSuttari_UpdateCollider",), 0x80BAA848:("EnSuttari_GetActorById",), 0x80BAA88C:("EnSuttari_TriggerTransition",), - 0x80BAA8D0:("EnSuttari_UpdateTime",), + 0x80BAA8D0:("EnSuttari_AdvanceTime",), 0x80BAA904:("func_80BAA904",), 0x80BAA9B4:("func_80BAA9B4",), 0x80BAAA94:("func_80BAAA94",), @@ -16662,7 +16662,7 @@ 0x80C0A740:("func_80C0A740",), 0x80C0A804:("func_80C0A804",), 0x80C0A838:("func_80C0A838",), - 0x80C0A86C:("func_80C0A86C",), + 0x80C0A86C:("BgIkninSusceil_RequestQuakeAndRumble",), 0x80C0A95C:("func_80C0A95C",), 0x80C0AA70:("BgIkninSusceil_Init",), 0x80C0AAE0:("BgIkninSusceil_Destroy",), @@ -16868,13 +16868,13 @@ 0x80C18928:("BgLastBwall_DoNothing",), 0x80C18938:("BgLastBwall_Update",), 0x80C1895C:("BgLastBwall_Draw",), - 0x80C18B90:("func_80C18B90",), - 0x80C18BD8:("func_80C18BD8",), - 0x80C18C50:("func_80C18C50",), + 0x80C18B90:("EnAnd_ChangeAnimation",), + 0x80C18BD8:("EnAnd_Blink",), + 0x80C18C50:("EnAnd_HandleCsAction",), 0x80C18DC8:("EnAnd_Init",), 0x80C18E84:("EnAnd_Destroy",), 0x80C18E94:("EnAnd_Update",), - 0x80C18ED0:("func_80C18ED0",), + 0x80C18ED0:("EnAnd_TransformLimbDraw",), 0x80C19084:("EnAnd_Draw",), 0x80C192A0:("func_80C192A0",), 0x80C192B0:("func_80C192B0",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index e1b86526e..f26cabc06 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -472,19 +472,6 @@ 0x801B48B0:("sSetNormal0ModeBoomerangData","UNK_TYPE1","",0x1), 0x801B48D4:("sSetNormal0ModeSlingshotData","UNK_TYPE1","",0x1), 0x801B48F8:("sSetNormal0ModeClimbZData","UNK_TYPE1","",0x1), - 0x801B4710:("sSetNormal0ModeNormalData","UNK_TYPE1","",0x1), - 0x801B4738:("sSetNormal0ModeTargetData","UNK_TYPE1","",0x1), - 0x801B4768:("sSetNormal0ModeFollowTargetData","UNK_TYPE1","",0x1), - 0x801B4798:("sSetNormal0ModeBattleData","UNK_TYPE1","",0x1), - 0x801B47CC:("sSetNormal0ModeFirstPersonData","UNK_TYPE1","",0x1), - 0x801B47F0:("sSetNormal0ModeTalkData","UNK_TYPE1","",0x1), - 0x801B4824:("sSetNormal0ModeClimbData","UNK_TYPE1","",0x1), - 0x801B4848:("sSetNormal0ModeBowArrowData","UNK_TYPE1","",0x1), - 0x801B486C:("sSetNormal0ModeBowArrowZData","UNK_TYPE1","",0x1), - 0x801B4890:("sSetNormal0ModeHookshotData","UNK_TYPE1","",0x1), - 0x801B48B0:("sSetNormal0ModeBoomerangData","UNK_TYPE1","",0x1), - 0x801B48D4:("sSetNormal0ModeSlingshotData","UNK_TYPE1","",0x1), - 0x801B48F8:("sSetNormal0ModeClimbZData","UNK_TYPE1","",0x1), 0x801B491C:("sSetNormal0ModeJumpData","UNK_TYPE1","",0x1), 0x801B4944:("sSetNormal0ModeHangData","UNK_TYPE1","",0x1), 0x801B4974:("sSetNormal0ModeHangZData","UNK_TYPE1","",0x1), @@ -1326,7 +1313,7 @@ 0x801C0EA0:("D_801C0EA0","UNK_TYPE1","",0x1), 0x801C0EAC:("sSheathLimbModelShieldOnBackPos","Vec3f","",0xC), 0x801C0EB8:("sSheathLimbModelShieldOnBackZyxRot","Vec3s","",0x6), - 0x801C0EC0:("sIsQuakeInitialized","UNK_TYPE2","",0x2), + 0x801C0EC0:("sQuakeUnused","UNK_TYPE2","",0x2), 0x801C0EC4:("sQuakeRequestCount","s16","",0x2), 0x801C0EC8:("sQuakeCallbacks","quake_callback_func","[7]",0x1c), 0x801C0EE4:("D_801C0EE4","s16","",0x2), @@ -2126,7 +2113,7 @@ 0x801D0B70:("gKaleidoMgrOverlayTable","KaleidoMgrOverlay","",0x38), 0x801D0BA8:("sKaleidoAreaPtr","void*","",0x4), 0x801D0BAC:("gKaleidoMgrCurOvl","KaleidoMgrOverlay*","",0x4), - 0x801D0BB0:("D_801D0BB0","UNK_TYPE4","",0x4), + 0x801D0BB0:("gTransitionOverlayTable","UNK_TYPE4","",0x4), 0x801D0C80:("D_801D0C80","UNK_TYPE1","",0x1), 0x801D0CB0:("D_801D0CB0","UNK_TYPE1","",0x1), 0x801D0CD8:("TransitionFade_InitVars","UNK_PTR","",0x4), @@ -2138,7 +2125,6 @@ 0x801D0D5C:("sIsCameraUnderwater","UNK_TYPE2","",0x2), 0x801D0D60:("D_801D0D60","Input*","",0x4), 0x801D0D64:("sPlayerCsIdToCsCamId","s16","[10]",0x14), - 0x801D0D78:("D_801D0D78","u16","[4]",0x4), 0x801D0D80:("D_801D0D80","UNK_TYPE1","",0x1), 0x801D11F4:("D_801D11F4","UNK_TYPE1","",0x1), 0x801D1230:("D_801D1230","UNK_TYPE1","",0x1), @@ -3851,7 +3837,7 @@ 0x801ED8D8:("D_801ED8D8","UNK_TYPE1","",0x1), 0x801ED8DC:("D_801ED8DC","UNK_TYPE1","",0x1), 0x801ED8E0:("D_801ED8E0","Mtx","",0x40), - 0x801ED920:("D_801ED920","UNK_TYPE1","",0x1), + 0x801ED920:("D_801ED920","Actor*","",0x1), 0x801ED930:("D_801ED930","FaultClient","",0x10), 0x801ED940:("sActorOverlayTableFaultAddrConvClient","FaultAddrConvClient","",0xC), 0x801ED950:("D_801ED950","char","[80]",0x50), @@ -3868,9 +3854,9 @@ 0x801EDBA8:("D_801EDBA8","Sphere16","",0x8), 0x801EDBB0:("D_801EDBB0","TriNorm","",0x34), 0x801EDBF0:("D_801EDBF0","s16","",0x2), - 0x801EDBF4:("D_801EDBF4","f32","",0x4), - 0x801EDBF8:("D_801EDBF8","f32","",0x4), - 0x801EDC00:("D_801EDC00","CameraCollision","",0x28), + 0x801EDBF4:("sFloorYNear","f32","",0x4), + 0x801EDBF8:("sFloorYFar","f32","",0x4), + 0x801EDC00:("sFarColChk","CameraCollision","",0x28), 0x801EDC28:("sCamPlayState","PlayState*","",0x4), 0x801EDC30:("D_801EDC30","SwingAnimation","[4]",0x1A0), 0x801EDDD0:("D_801EDDD0","Vec3f","",0xc), @@ -4007,7 +3993,7 @@ 0x801F59E8:("sPlayerGetItemRefPos","Vec3f","",0xC), 0x801F59F4:("sPlayerLeftHandType","s32","",0x4), 0x801F59F8:("sPlayerRightHandType","s32","",0x4), - 0x801F5A00:("sQuakeRequest","QuakeRequest","[4]",0x90), + 0x801F5A00:("sQuakeRequests","QuakeRequest","[4]",0x90), 0x801F5A90:("sDistortionRequest","DistortionRequest","",0xc), 0x801F5AA0:("sMatAnimStep","s32","",0x4), 0x801F5AA4:("sMatAnimFlags","u32","",0x4), @@ -4728,12 +4714,12 @@ 0x8082B6F0:("sPromptAlphaTargets","UNK_TYPE1","",0x1), 0x8082B6F4:("sPromptAlphaTargetIndex","UNK_TYPE2","",0x2), 0x8082B6F8:("sPromptAlphaTimer","UNK_TYPE2","",0x2), - 0x8082B700:("D_8082B700","UNK_TYPE1","",0x1), - 0x8082B73C:("D_8082B73C","UNK_TYPE1","",0x1), - 0x8082B778:("D_8082B778","UNK_TYPE1","",0x1), - 0x8082B7B4:("D_8082B7B4","UNK_TYPE1","",0x1), - 0x8082B7F0:("D_8082B7F0","UNK_TYPE2","",0x2), - 0x8082B838:("D_8082B838","UNK_TYPE2","",0x2), + 0x8082B700:("sMaskPageBgTextures","UNK_TYPE1","",0x1), + 0x8082B73C:("sItemPageBgTextures","UNK_TYPE1","",0x1), + 0x8082B778:("sMapPageBgTextures","UNK_TYPE1","",0x1), + 0x8082B7B4:("sQuestPageBgTextures","UNK_TYPE1","",0x1), + 0x8082B7F0:("gVtxPageMapWorldQuadsWidth","UNK_TYPE2","",0x2), + 0x8082B838:("gVtxPageMapWorldQuadsHeight","UNK_TYPE2","",0x2), 0x8082B880:("sGameOverPrimR","UNK_TYPE2","",0x2), 0x8082B884:("sGameOverPrimG","UNK_TYPE2","",0x2), 0x8082B888:("sGameOverPrimB","UNK_TYPE2","",0x2), @@ -4760,10 +4746,10 @@ 0x8082B920:("D_8082B920","UNK_TYPE2","",0x2), 0x8082B924:("D_8082B924","UNK_TYPE2","",0x2), 0x8082B944:("sGameOverRectPosY","UNK_TYPE2","",0x2), - 0x8082B948:("D_8082B948","UNK_TYPE2","",0x2), - 0x8082B96C:("D_8082B96C","UNK_TYPE2","",0x2), - 0x8082B990:("D_8082B990","UNK_TYPE2","",0x2), - 0x8082B994:("D_8082B994","UNK_TYPE2","",0x2), + 0x8082B948:("sCursorPrimColorTarget","UNK_TYPE2","",0x2), + 0x8082B96C:("sCursorEnvColorTarget","UNK_TYPE2","",0x2), + 0x8082B990:("sCursorColorTimer","UNK_TYPE2","",0x2), + 0x8082B994:("sCursorColorTargetIndex","UNK_TYPE2","",0x2), 0x8082B998:("D_8082B998","UNK_TYPE1","",0x1), 0x8082B9A8:("D_8082B9A8","UNK_TYPE1","",0x1), 0x8082B9B8:("D_8082B9B8","UNK_TYPE1","",0x1), @@ -4772,33 +4758,33 @@ 0x8082B9D0:("D_8082B9D0","UNK_TYPE1","",0x1), 0x8082B9E0:("D_8082B9E0","UNK_TYPE2","",0x2), 0x8082B9E4:("D_8082B9E4","UNK_TYPE2","",0x2), - 0x8082B9E8:("D_8082B9E8","UNK_TYPE1","",0x1), - 0x8082B9EC:("D_8082B9EC","UNK_TYPE1","",0x1), - 0x8082B9F0:("D_8082B9F0","UNK_TYPE1","",0x1), - 0x8082B9FC:("D_8082B9FC","UNK_TYPE1","",0x1), - 0x8082BA00:("D_8082BA00","UNK_TYPE1","",0x1), - 0x8082BA48:("D_8082BA48","UNK_TYPE1","",0x1), - 0x8082BA54:("D_8082BA54","UNK_TYPE1","",0x1), - 0x8082BA58:("D_8082BA58","UNK_TYPE1","",0x1), - 0x8082BA5C:("D_8082BA5C","UNK_TYPE1","",0x1), - 0x8082BA68:("D_8082BA68","UNK_TYPE1","",0x1), - 0x8082BA6C:("D_8082BA6C","UNK_TYPE1","",0x1), - 0x8082BA78:("D_8082BA78","UNK_TYPE1","",0x1), - 0x8082BA7C:("D_8082BA7C","UNK_TYPE1","",0x1), - 0x8082BA80:("D_8082BA80","UNK_TYPE1","",0x1), - 0x8082BA8C:("D_8082BA8C","UNK_TYPE1","",0x1), - 0x8082BA90:("D_8082BA90","UNK_TYPE1","",0x1), - 0x8082BAD8:("D_8082BAD8","UNK_TYPE1","",0x1), - 0x8082BAE4:("D_8082BAE4","UNK_TYPE1","",0x1), - 0x8082BAE8:("D_8082BAE8","UNK_TYPE1","",0x1), - 0x8082BAEC:("D_8082BAEC","UNK_TYPE1","",0x1), - 0x8082BAF8:("D_8082BAF8","UNK_TYPE1","",0x1), - 0x8082BAFC:("D_8082BAFC","UNK_TYPE1","",0x1), - 0x8082BB08:("D_8082BB08","UNK_PTR","",0x4), - 0x8082BB20:("D_8082BB20","UNK_PTR","",0x4), - 0x8082BB38:("D_8082BB38","UNK_PTR","",0x4), - 0x8082BB50:("D_8082BB50","UNK_PTR","",0x4), - 0x8082BB68:("D_8082BB68","UNK_TYPE2","",0x2), + 0x8082B9E8:("sVtxPageMaskQuadsX","UNK_TYPE1","",0x1), + 0x8082B9EC:("sVtxPageItemQuadsX","UNK_TYPE1","",0x1), + 0x8082B9F0:("sVtxPageMapDungeonQuadsX","UNK_TYPE1","",0x1), + 0x8082B9FC:("sVtxPageQuestQuadsX","UNK_TYPE1","",0x1), + 0x8082BA00:("sVtxPageMapWorldQuadsX","UNK_TYPE1","",0x1), + 0x8082BA48:("sVtxPagePromptQuadsX","UNK_TYPE1","",0x1), + 0x8082BA54:("sVtxPageMaskQuadsWidth","UNK_TYPE1","",0x1), + 0x8082BA58:("sVtxPageItemQuadsWidth","UNK_TYPE1","",0x1), + 0x8082BA5C:("sVtxPageMapDungeonQuadsWidth","UNK_TYPE1","",0x1), + 0x8082BA68:("sVtxPageQuestQuadsWidth","UNK_TYPE1","",0x1), + 0x8082BA6C:("sVtxPagePromptQuadsWidth","UNK_TYPE1","",0x1), + 0x8082BA78:("sVtxPageMaskQuadsY","UNK_TYPE1","",0x1), + 0x8082BA7C:("sVtxPageItemQuadsY","UNK_TYPE1","",0x1), + 0x8082BA80:("sVtxPageMapDungeonQuadsY","UNK_TYPE1","",0x1), + 0x8082BA8C:("sVtxPageQuestQuadsY","UNK_TYPE1","",0x1), + 0x8082BA90:("sVtxPageMapWorldQuadsY","UNK_TYPE1","",0x1), + 0x8082BAD8:("sVtxPagePromptQuadsY","UNK_TYPE1","",0x1), + 0x8082BAE4:("sVtxPageMaskQuadsHeight","UNK_TYPE1","",0x1), + 0x8082BAE8:("sVtxPageItemQuadsHeight","UNK_TYPE1","",0x1), + 0x8082BAEC:("sVtxPageMapDungeonQuadsHeight","UNK_TYPE1","",0x1), + 0x8082BAF8:("sVtxPageQuestQuadsHeight","UNK_TYPE1","",0x1), + 0x8082BAFC:("sVtxPagePromptQuadsHeight","UNK_TYPE1","",0x1), + 0x8082BB08:("sVtxPageQuadsX","UNK_PTR","",0x4), + 0x8082BB20:("sVtxPageQuadsWidth","UNK_PTR","",0x4), + 0x8082BB38:("sVtxPageQuadsY","UNK_PTR","",0x4), + 0x8082BB50:("sVtxPageQuadsHeight","UNK_PTR","",0x4), + 0x8082BB68:("sVtxPageGameOverSaveQuadsY","UNK_TYPE2","",0x2), 0x8082BB74:("sQuestVtxRectLeft","UNK_TYPE2","",0x2), 0x8082BBC4:("sQuestVtxRectTop","UNK_TYPE2","",0x2), 0x8082BC14:("sQuestVtxWidths","UNK_TYPE2","",0x2), @@ -5680,8 +5666,8 @@ 0x80872E8C:("D_80872E8C","UNK_TYPE1","",0x1), 0x80872E90:("D_80872E90","UNK_TYPE4","",0x4), 0x80872E94:("D_80872E94","UNK_TYPE4","",0x4), - 0x80872E98:("D_80872E98","UNK_TYPE1","",0x1), - 0x80872E9C:("D_80872E9C","UNK_TYPE1","",0x1), + 0x80872E98:("sQuakeY","UNK_TYPE1","",0x1), + 0x80872E9C:("sQuakeDurations","UNK_TYPE1","",0x1), 0x80872EA0:("D_80872EA0","UNK_TYPE4","",0x4), 0x80872EAC:("D_80872EAC","UNK_TYPE4","",0x4), 0x80872EB8:("D_80872EB8","UNK_TYPE4","",0x4), @@ -7668,11 +7654,11 @@ 0x80911E30:("sSinkingLurePos","Vec3f","[20]",0xF0), 0x80911F20:("D_80911F20","UNK_TYPE1","",0x1), 0x80911F24:("sProjectedW","f32","",0x4), - 0x80911F28:("sCameraEye","Vec3f","",0xC), - 0x80911F38:("sCameraAt","Vec3f","",0xC), - 0x80911F44:("sCameraId","s32","",0x4), + 0x80911F28:("sSubCamEye","Vec3f","",0xC), + 0x80911F38:("sSubCamAt","Vec3f","",0xC), + 0x80911F44:("sSubCamId","s32","",0x4), 0x80911F48:("D_80911F48","f32","",0x4), - 0x80911F4C:("D_80911F4C","f32","",0x4), + 0x80911F4C:("sSubCamVelFactor","f32","",0x4), 0x80911F50:("D_80911F50","UNK_TYPE1","",0x1), 0x80911F58:("sSinkingLureBasePos","Vec3f","",0xC), 0x80911F64:("D_80911F64","f32","",0x4), @@ -9861,11 +9847,11 @@ 0x809C3770:("En_Aob_01_InitVars","UNK_TYPE1","",0x1), 0x809C3790:("sAnimationInfo","UNK_TYPE4","",0x4), 0x809C3820:("D_809C3820","UNK_TYPE1","",0x1), - 0x809C384C:("D_809C384C","UNK_TYPE4","",0x4), + 0x809C384C:("sDogInfo","UNK_TYPE4","",0x4), 0x809C392C:("D_809C392C","UNK_TYPE1","",0x1), 0x809C394C:("D_809C394C","UNK_TYPE4","",0x4), 0x809C395C:("D_809C395C","UNK_PTR","",0x4), - 0x809C3968:("D_809C3968","UNK_TYPE1","",0x1), + 0x809C3968:("sFocusOffset","UNK_TYPE1","",0x1), 0x809C3980:("D_809C3980","f32","",0x4), 0x809C3984:("D_809C3984","f32","",0x4), 0x809C3988:("D_809C3988","f32","",0x4), diff --git a/tools/fixbaserom.py b/tools/fixbaserom.py index 2c3942160..3966c3533 100755 --- a/tools/fixbaserom.py +++ b/tools/fixbaserom.py @@ -122,6 +122,7 @@ def decompress_rom(dmadata_addr, dmadata): # re-calculate crc return update_crc(decompressed) +correct_compressed_str_hash = "2a0a8acb61538235bc1094d297fb6556" correct_str_hash = "f46493eaa0628827dbd6ad3ecd8d65d6" def get_str_hash(byte_array): @@ -179,6 +180,13 @@ elif fileContent[0] == 0x37: print("Byte swapping done.") +# Check to see if the ROM is a compressed "vanilla" ROM +compressed_str_hash = get_str_hash(bytearray(fileContent)) +if compressed_str_hash != correct_compressed_str_hash: + print("Error: Expected a hash of " + correct_compressed_str_hash + " but got " + compressed_str_hash + ". " + + "The baserom has probably been tampered, find a new one") + sys.exit(1) + # Decompress FILE_TABLE_OFFSET = 0x1A500 # 0x1C110 for JP1.0, 0x1C050 for JP1.1, 0x24F60 for debug if any([b != 0 for b in fileContent[FILE_TABLE_OFFSET + 0x9C:FILE_TABLE_OFFSET + 0x9C + 0x4]]): diff --git a/tools/m2ctx.py b/tools/m2ctx.py index 0824899f1..23875eef0 100755 --- a/tools/m2ctx.py +++ b/tools/m2ctx.py @@ -1,14 +1,39 @@ #!/usr/bin/env python3 -import argparse, os, subprocess, sys +import argparse +import os +import sys +import subprocess +import tempfile from pathlib import Path -script_dir = os.path.dirname(os.path.realpath(__file__)) -root_dir = script_dir + "/../" -src_dir = root_dir + "src/" +script_dir = Path(os.path.dirname(os.path.realpath(__file__))) +root_dir = script_dir / ".." +src_dir = root_dir / "src" + +# Project-specific +CPP_FLAGS = [ + "-Iinclude", + "-Isrc", + "-Iassets", + "-Ibuild", + "-I.", + + "-D__sgi", + "-D_LANGUAGE_C", + "-DNON_MATCHING", + "-D_Static_assert(x, y)=", + "-D__attribute__(x)=" + "-D_MIPS_SZLONG=32", + "-ffreestanding", + "-DM2CTX", + + "-std=gnu89", +] # Read through the processes context and replace whatever def custom_replacements(output): + actorList = [] output = output.splitlines() i = 0 @@ -36,7 +61,6 @@ def custom_replacements(output): "door", "chest", ] - actorList = [] for x in range(12): actorList.append(actorListText.replace("first;", f"{actorCats[x]};") + "\n") if x == 2: @@ -48,63 +72,55 @@ def custom_replacements(output): i += 1 return "\n".join(output) -def get_c_dir(dirname): - for root, dirs, files in os.walk(src_dir): - for directory in dirs: - if directory == dirname: - return os.path.join(root, directory) - - -def get_c_file(directory): - for root, dirs, files in os.walk(directory): - for file in files: - if file.endswith(".c") and "data" not in file: - return file - - -def import_c_file(in_file): +def import_c_file(in_file) -> str: in_file = os.path.relpath(in_file, root_dir) - cpp_command = ["gcc", "-E", "-P", "-Iinclude", "-Iassets", "-Isrc", "-undef", "-D__sgi", "-D_LANGUAGE_C", - "-DNON_MATCHING", "-D_Static_assert(x, y)=", "-D__attribute__(x)=", in_file] + + cpp_command = ["gcc", "-E", "-P", "-undef", "-dM", *CPP_FLAGS, in_file] + cpp_command2 = ["gcc", "-E", "-P", "-undef", *CPP_FLAGS, in_file] + + with tempfile.NamedTemporaryFile(suffix=".c") as tmp: + stock_macros = subprocess.check_output(["gcc", "-E", "-P", "-undef", "-dM", tmp.name], cwd=root_dir, encoding="utf-8") + + out_text = "" try: - return subprocess.check_output(cpp_command, cwd=root_dir, encoding="utf-8") + out_text += subprocess.check_output(cpp_command, cwd=root_dir, encoding="utf-8") + out_text += subprocess.check_output(cpp_command2, cwd=root_dir, encoding="utf-8") except subprocess.CalledProcessError: print( "Failed to preprocess input file, when running command:\n" - + cpp_command, + + " ".join(cpp_command), file=sys.stderr, - ) + ) sys.exit(1) + if not out_text: + print("Output is empty - aborting") + sys.exit(1) + + for line in stock_macros.strip().splitlines(): + out_text = out_text.replace(line + "\n", "") + return out_text + def main(): parser = argparse.ArgumentParser(usage="./m2ctx.py path/to/file.c or ./m2ctx.py (from an actor or gamestate's asm dir)", - description="Creates a ctx.c file for mips2c. " - "Output will be saved as oot/ctx.c") + description="Creates a ctx.c file for m2c or decomp.me. " + "Output will be saved as ctx.c") parser.add_argument('filepath', help="path of c file to be processed") - parser.add_argument("--custom", "-c", dest="custom", action="store_true", default=False, - help="Apply custom replacements to the output to help aid m2c output") + parser.add_argument("--custom", "-c", dest="custom", action="store_true", default=False, + help="Apply custom replacements to the output to help aid m2c output") args = parser.parse_args() - if args.filepath: - c_file_path = args.filepath - print("Using file: {}".format(c_file_path)) - else: - this_dir = Path.cwd() - c_dir_path = get_c_dir(this_dir.name) - if c_dir_path is None: - sys.exit( - "Cannot find appropriate c file dir. In argumentless mode, run this script from the c file's corresponding asm dir.") - c_file = get_c_file(c_dir_path) - c_file_path = os.path.join(c_dir_path, c_file) - print("Using file: {}".format(c_file_path)) + c_file_path = args.filepath + print("Using file: {}".format(c_file_path)) output = import_c_file(c_file_path) if args.custom: output = custom_replacements(output) - with open(os.path.join(root_dir, "ctx.c"), "w", encoding="UTF-8") as f: + ctxPath = root_dir / "ctx.c" + with ctxPath.open("w", encoding="UTF-8") as f: f.write(output) diff --git a/tools/namefixer.py b/tools/namefixer.py index 6ddccb519..eefefac57 100755 --- a/tools/namefixer.py +++ b/tools/namefixer.py @@ -164,6 +164,10 @@ wordReplace = { "Actor_DistanceToPoint": "Actor_WorldDistXYZToPoint", "Actor_XZDistanceBetweenActors": "Actor_WorldDistXZToActor", "Actor_XZDistanceToPoint": "Actor_WorldDistXZToPoint", + "func_800B6468": "Actor_InitPlayerImpact", + "func_800B6474": "Actor_UpdatePlayerImpact", + "func_800B648C": "Actor_SetPlayerImpact", + "func_800B64FC": "Actor_GetPlayerImpact", "Audio_PlaySoundAtPosition": "SoundSource_PlaySfxAtFixedWorldPos", "func_800F0590": "SoundSource_PlaySfxEachFrameAtFixedWorldPos", "func_8016970C": "Play_SetCameraAtEye", @@ -317,8 +321,12 @@ wordReplace = { "func_800B86C8": "Actor_ChangeFocus", "func_800DF840": "Camera_ChangeMode", "func_800B90F4": "Actor_DeactivateLens", - "func_800BC770": "Actor_AddQuake", + "Actor_AddQuake": "Actor_RequestQuake", + "func_800BC770": "Actor_RequestQuake", + "Actor_AddQuakeWithSpeed": "Actor_RequestQuakeWithSpeed", + "func_800BC848": "Actor_RequestQuakeAndRumble", "func_800DF840": "Camera_ChangeMode", + "Camera_SetToTrackActor": "Camera_SetFocalActor", "zelda_malloc": "ZeldaArena_Malloc", "zelda_mallocR": "ZeldaArena_MallocR", "zelda_realloc": "ZeldaArena_Realloc", @@ -524,13 +532,13 @@ wordReplace = { "func_8017F9C0": "Math3D_XZInSphere", "func_8017FA34": "Math3D_XYInSphere", "func_8017FAA8": "Math3D_YZInSphere", - "func_800DFB14": "Camera_ChangeDataIdx", + "func_800DFB14": "Camera_ChangeActorCsCamIndex", "func_800DFC68": "Camera_GetInputDirYaw", "func_800DFCB4": "Camera_GetCamDirPitch", "func_800DFCDC": "Camera_GetCamDirYaw", "func_800E0308": "Camera_SetTargetActor", "func_800E031C": "Camera_GetWaterYPos", - "func_800E02AC": "Camera_SetToTrackActor", + "func_800E02AC": "Camera_SetFocalActor", "func_800DFAC8": "Camera_ChangeSetting", "func_800DFC90": "Camera_GetCamDir", "func_800DFD04": "Camera_AddQuake", @@ -645,12 +653,22 @@ wordReplace = { "func_80114E90": "Inventory_HasEmptyBottle", "func_80114F2C": "Inventory_HasItemInBottle", "func_80123C90": "Player_SetEquipmentData", - "Quake2_ClearType": "Distortion_ClearType", - "Quake2_SetType": "Distortion_SetType", - "Quake2_SetCountdown": "Distortion_SetCountdown", + "Quake2_SetType": "Distortion_Request", + "Distortion_SetType": "Distortion_Request", + "Quake2_SetCountdown": "Distortion_SetDuration", + "Distortion_SetCountdown": "Distortion_SetDuration", + "Distortion_GetCountdown": "Distortion_GetTimeLeft", + "Quake2_ClearType": "Distortion_RemoveRequest", + "Distortion_ClearType": "Distortion_RemoveRequest", "func_800BE680": "Actor_DrawDamageEffects", "func_8012F22C": "Inventory_GetSkullTokenCount", - "Quake_RemoveFromIdx": "Quake_Remove", + "Quake_Add": "Quake_Request", + "Quake_SetQuakeValues": "Quake_SetPerturbations", + "Quake_SetCountdown": "Quake_SetDuration", + "Quake_GetCountdown": "Quake_GetTimeLeft", + "Quake_NumActiveQuakes": "Quake_GetNumActiveQuakes", + "Quake_RemoveFromIdx": "Quake_RemoveRequest", + "OLib_DbCameraVec3fSum":"OLib_Vec3fAdd", "func_8013AB00": "SubS_DrawTransformFlex", "func_8013A860": "SubS_DrawTransformFlexLimb", @@ -945,10 +963,14 @@ wordReplace = { "play->roomCtx.unk31": "play->roomCtx.status", "actorCtx.unkC": "actorCtx.halfDaysBit", - "actorCtx.unk1F4": "actorCtx.unk_1F4.unk_00", - "actorCtx.unk1F5": "actorCtx.unk_1F4.timer", - "actorCtx.unk1F8": "actorCtx.unk_1F4.unk_04", - "actorCtx.unk1FC": "actorCtx.unk_1F4.unk_08", + "actorCtx.unk1F4": "actorCtx.playerImpact.type", + "actorCtx.unk1F5": "actorCtx.playerImpact.timer", + "actorCtx.unk1F8": "actorCtx.playerImpact.dist", + "actorCtx.unk1FC": "actorCtx.playerImpact.pos", + "actorCtx.unk_1F4.unk_00": "actorCtx.playerImpact.type", + "actorCtx.unk_1F4.timer": "actorCtx.playerImpact.timer", + "actorCtx.unk_1F4.unk_04": "actorCtx.playerImpact.dist", + "actorCtx.unk_1F4.unk_08": "actorCtx.playerImpact.pos", "gSaveContext.unk_3DC8": "gSaveContext.timerOsTime", "gSaveContext.unk_3DD0": "gSaveContext.timerStates", diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index ac7afd6c8..144678765 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -210,10 +210,10 @@ asm/non_matchings/code/z_actor/TitleCard_InitPlaceName.s,TitleCard_InitPlaceName asm/non_matchings/code/z_actor/TitleCard_Update.s,TitleCard_Update,0x800B5E68,0x2F asm/non_matchings/code/z_actor/TitleCard_Draw.s,TitleCard_Draw,0x800B5F24,0x144 asm/non_matchings/code/z_actor/func_800B6434.s,func_800B6434,0x800B6434,0xD -asm/non_matchings/code/z_actor/func_800B6468.s,func_800B6468,0x800B6468,0x3 -asm/non_matchings/code/z_actor/func_800B6474.s,func_800B6474,0x800B6474,0x6 -asm/non_matchings/code/z_actor/func_800B648C.s,func_800B648C,0x800B648C,0x1C -asm/non_matchings/code/z_actor/func_800B64FC.s,func_800B64FC,0x800B64FC,0x22 +asm/non_matchings/code/z_actor/Actor_InitPlayerImpact.s,Actor_InitPlayerImpact,0x800B6468,0x3 +asm/non_matchings/code/z_actor/Actor_UpdatePlayerImpact.s,Actor_UpdatePlayerImpact,0x800B6474,0x6 +asm/non_matchings/code/z_actor/Actor_SetPlayerImpact.s,Actor_SetPlayerImpact,0x800B648C,0x1C +asm/non_matchings/code/z_actor/Actor_GetPlayerImpact.s,Actor_GetPlayerImpact,0x800B64FC,0x22 asm/non_matchings/code/z_actor/func_800B6584.s,func_800B6584,0x800B6584,0x21 asm/non_matchings/code/z_actor/func_800B6608.s,func_800B6608,0x800B6608,0x1E asm/non_matchings/code/z_actor/func_800B6680.s,func_800B6680,0x800B6680,0x23 @@ -373,9 +373,9 @@ asm/non_matchings/code/z_actor/Actor_TestFloorInDirection.s,Actor_TestFloorInDir asm/non_matchings/code/z_actor/Actor_IsTargeted.s,Actor_IsTargeted,0x800BC5B8,0xD asm/non_matchings/code/z_actor/Actor_OtherIsTargeted.s,Actor_OtherIsTargeted,0x800BC5EC,0xD asm/non_matchings/code/z_actor/func_800BC620.s,func_800BC620,0x800BC620,0x54 -asm/non_matchings/code/z_actor/Actor_AddQuake.s,Actor_AddQuake,0x800BC770,0x1A -asm/non_matchings/code/z_actor/Actor_AddQuakeWithSpeed.s,Actor_AddQuakeWithSpeed,0x800BC7D8,0x1C -asm/non_matchings/code/z_actor/func_800BC848.s,func_800BC848,0x800BC848,0x1C +asm/non_matchings/code/z_actor/Actor_RequestQuake.s,Actor_RequestQuake,0x800BC770,0x1A +asm/non_matchings/code/z_actor/Actor_RequestQuakeWithSpeed.s,Actor_RequestQuakeWithSpeed,0x800BC7D8,0x1C +asm/non_matchings/code/z_actor/Actor_RequestQuakeAndRumble.s,Actor_RequestQuakeAndRumble,0x800BC848,0x1C asm/non_matchings/code/z_actor/Actor_DrawDoorLock.s,Actor_DrawDoorLock,0x800BC8B8,0xA6 asm/non_matchings/code/z_actor/Actor_SpawnShieldParticlesMetal.s,Actor_SpawnShieldParticlesMetal,0x800BCB50,0x8 asm/non_matchings/code/z_actor/Actor_SetColorFilter.s,Actor_SetColorFilter,0x800BCB70,0x21 @@ -629,16 +629,16 @@ asm/non_matchings/code/z_bg_item/DynaPoly_ValidateMove.s,DynaPoly_ValidateMove,0 asm/non_matchings/code/z_camera/Camera_fabsf.s,Camera_fabsf,0x800CB210,0xC asm/non_matchings/code/z_camera/Camera_Vec3fMagnitude.s,Camera_Vec3fMagnitude,0x800CB240,0xC asm/non_matchings/code/z_camera/Camera_QuadraticAttenuation.s,Camera_QuadraticAttenuation,0x800CB270,0x30 -asm/non_matchings/code/z_camera/Camera_LerpCeilF.s,Camera_LerpCeilF,0x800CB330,0x1A -asm/non_matchings/code/z_camera/Camera_LerpCeilS.s,Camera_LerpCeilS,0x800CB398,0x25 -asm/non_matchings/code/z_camera/Camera_LerpFloorS.s,Camera_LerpFloorS,0x800CB42C,0x25 -asm/non_matchings/code/z_camera/Camera_LerpCeilVec3f.s,Camera_LerpCeilVec3f,0x800CB4C0,0x21 +asm/non_matchings/code/z_camera/Camera_ScaledStepToCeilF.s,Camera_ScaledStepToCeilF,0x800CB330,0x1A +asm/non_matchings/code/z_camera/Camera_ScaledStepToCeilS.s,Camera_ScaledStepToCeilS,0x800CB398,0x25 +asm/non_matchings/code/z_camera/Camera_ScaledStepToFloorS.s,Camera_ScaledStepToFloorS,0x800CB42C,0x25 +asm/non_matchings/code/z_camera/Camera_ScaledStepToCeilVec3f.s,Camera_ScaledStepToCeilVec3f,0x800CB4C0,0x21 asm/non_matchings/code/z_camera/Camera_SetUpdateRatesFastPitch.s,Camera_SetUpdateRatesFastPitch,0x800CB544,0x10 asm/non_matchings/code/z_camera/Camera_SetUpdateRatesFastYaw.s,Camera_SetUpdateRatesFastYaw,0x800CB584,0x16 asm/non_matchings/code/z_camera/Camera_SetUpdateRatesSlow.s,Camera_SetUpdateRatesSlow,0x800CB5DC,0xC asm/non_matchings/code/z_camera/Camera_Vec3sToVec3f.s,Camera_Vec3sToVec3f,0x800CB60C,0x1A asm/non_matchings/code/z_camera/Camera_AngleDiffAndScale.s,Camera_AngleDiffAndScale,0x800CB674,0x15 -asm/non_matchings/code/z_camera/Camera_UpdateAtActorOffset.s,Camera_UpdateAtActorOffset,0x800CB6C8,0xE +asm/non_matchings/code/z_camera/Camera_SetFocalActorAtOffset.s,Camera_SetFocalActorAtOffset,0x800CB6C8,0xE asm/non_matchings/code/z_camera/Camera_GetFocalActorHeight.s,Camera_GetFocalActorHeight,0x800CB700,0x20 asm/non_matchings/code/z_camera/Camera_GetRunSpeedLimit.s,Camera_GetRunSpeedLimit,0x800CB780,0x13 asm/non_matchings/code/z_camera/func_800CB7CC.s,func_800CB7CC,0x800CB7CC,0xB @@ -661,41 +661,41 @@ asm/non_matchings/code/z_camera/Camera_IsUsingZoraFins.s,Camera_IsUsingZoraFins, asm/non_matchings/code/z_camera/func_800CBC30.s,func_800CBC30,0x800CBC30,0x15 asm/non_matchings/code/z_camera/func_800CBC84.s,func_800CBC84,0x800CBC84,0xC8 asm/non_matchings/code/z_camera/func_800CBFA4.s,func_800CBFA4,0x800CBFA4,0x17 -asm/non_matchings/code/z_camera/func_800CC000.s,func_800CC000,0x800CC000,0x4A -asm/non_matchings/code/z_camera/func_800CC128.s,func_800CC128,0x800CC128,0x27 -asm/non_matchings/code/z_camera/func_800CC1C4.s,func_800CC1C4,0x800CC1C4,0x27 +asm/non_matchings/code/z_camera/Camera_BgCheckInfo.s,Camera_BgCheckInfo,0x800CC000,0x4A +asm/non_matchings/code/z_camera/Camera_BgCheck.s,Camera_BgCheck,0x800CC128,0x27 +asm/non_matchings/code/z_camera/Camera_CheckOOB.s,Camera_CheckOOB,0x800CC1C4,0x27 asm/non_matchings/code/z_camera/func_800CC260.s,func_800CC260,0x800CC260,0x8A -asm/non_matchings/code/z_camera/func_800CC488.s,func_800CC488,0x800CC488,0x39 -asm/non_matchings/code/z_camera/func_800CC56C.s,func_800CC56C,0x800CC56C,0x17 -asm/non_matchings/code/z_camera/func_800CC5C8.s,func_800CC5C8,0x800CC5C8,0x5E +asm/non_matchings/code/z_camera/Camera_GetFloorYNorm.s,Camera_GetFloorYNorm,0x800CC488,0x39 +asm/non_matchings/code/z_camera/Camera_GetFloorY.s,Camera_GetFloorY,0x800CC56C,0x17 +asm/non_matchings/code/z_camera/Camera_GetFloorYLayer.s,Camera_GetFloorYLayer,0x800CC5C8,0x5E asm/non_matchings/code/z_camera/Camera_GetBgCamOrActorCsCamSetting.s,Camera_GetBgCamOrActorCsCamSetting,0x800CC740,0x1A asm/non_matchings/code/z_camera/Camera_GetBgCamOrActorCsCamFuncData.s,Camera_GetBgCamOrActorCsCamFuncData,0x800CC7A8,0x17 asm/non_matchings/code/z_camera/Camera_GetBgCamIndex.s,Camera_GetBgCamIndex,0x800CC804,0x1C asm/non_matchings/code/z_camera/Camera_GetWaterBoxBgCamSetting.s,Camera_GetWaterBoxBgCamSetting,0x800CC874,0x31 asm/non_matchings/code/z_camera/func_800CC938.s,func_800CC938,0x800CC938,0x8 -asm/non_matchings/code/z_camera/func_800CC958.s,func_800CC958,0x800CC958,0x1A -asm/non_matchings/code/z_camera/func_800CC9C0.s,func_800CC9C0,0x800CC9C0,0xCB +asm/non_matchings/code/z_camera/Camera_CalcXZAngle.s,Camera_CalcXZAngle,0x800CC958,0x1A +asm/non_matchings/code/z_camera/Camera_GetPitchAdjFromFloorHeightDiffs.s,Camera_GetPitchAdjFromFloorHeightDiffs,0x800CC9C0,0xCB asm/non_matchings/code/z_camera/func_800CCCEC.s,func_800CCCEC,0x800CCCEC,0xD8 -asm/non_matchings/code/z_camera/func_800CD04C.s,func_800CD04C,0x800CD04C,0x8F -asm/non_matchings/code/z_camera/func_800CD288.s,func_800CD288,0x800CD288,0x16 -asm/non_matchings/code/z_camera/func_800CD2E0.s,func_800CD2E0,0x800CD2E0,0x4 -asm/non_matchings/code/z_camera/func_800CD2F0.s,func_800CD2F0,0x800CD2F0,0x3D -asm/non_matchings/code/z_camera/func_800CD3E4.s,func_800CD3E4,0x800CD3E4,0x1A +asm/non_matchings/code/z_camera/Camera_CalcUpVec.s,Camera_CalcUpVec,0x800CD04C,0x8F +asm/non_matchings/code/z_camera/Camera_ClampLerpScale.s,Camera_ClampLerpScale,0x800CD288,0x16 +asm/non_matchings/code/z_camera/Camera_ResetActionFuncState.s,Camera_ResetActionFuncState,0x800CD2E0,0x4 +asm/non_matchings/code/z_camera/Camera_UpdateInterface.s,Camera_UpdateInterface,0x800CD2F0,0x3D +asm/non_matchings/code/z_camera/Camera_BgCheckCorner.s,Camera_BgCheckCorner,0x800CD3E4,0x1A asm/non_matchings/code/z_camera/func_800CD44C.s,func_800CD44C,0x800CD44C,0x7A -asm/non_matchings/code/z_camera/func_800CD634.s,func_800CD634,0x800CD634,0x26 +asm/non_matchings/code/z_camera/Camera_CalcSlopeYAdj.s,Camera_CalcSlopeYAdj,0x800CD634,0x26 asm/non_matchings/code/z_camera/func_800CD6CC.s,func_800CD6CC,0x800CD6CC,0xB -asm/non_matchings/code/z_camera/func_800CD6F8.s,func_800CD6F8,0x800CD6F8,0x4F -asm/non_matchings/code/z_camera/func_800CD834.s,func_800CD834,0x800CD834,0x78 -asm/non_matchings/code/z_camera/func_800CDA14.s,func_800CDA14,0x800CDA14,0x56 -asm/non_matchings/code/z_camera/func_800CDB6C.s,func_800CDB6C,0x800CDB6C,0xC0 -asm/non_matchings/code/z_camera/func_800CDE6C.s,func_800CDE6C,0x800CDE6C,0x113 -asm/non_matchings/code/z_camera/func_800CE2B8.s,func_800CE2B8,0x800CE2B8,0xCA -asm/non_matchings/code/z_camera/func_800CE5E0.s,func_800CE5E0,0x800CE5E0,0x6F -asm/non_matchings/code/z_camera/func_800CE79C.s,func_800CE79C,0x800CE79C,0x65 -asm/non_matchings/code/z_camera/func_800CE930.s,func_800CE930,0x800CE930,0x6A -asm/non_matchings/code/z_camera/func_800CEAD8.s,func_800CEAD8,0x800CEAD8,0x58 -asm/non_matchings/code/z_camera/func_800CEC38.s,func_800CEC38,0x800CEC38,0x56 -asm/non_matchings/code/z_camera/func_800CED90.s,func_800CED90,0x800CED90,0x185 +asm/non_matchings/code/z_camera/Camera_CalcAtDefault.s,Camera_CalcAtDefault,0x800CD6F8,0x4F +asm/non_matchings/code/z_camera/Camera_CalcAtForScreen.s,Camera_CalcAtForScreen,0x800CD834,0x78 +asm/non_matchings/code/z_camera/Camera_CalcAtForNormal1.s,Camera_CalcAtForNormal1,0x800CDA14,0x56 +asm/non_matchings/code/z_camera/Camera_CalcAtForParallel.s,Camera_CalcAtForParallel,0x800CDB6C,0xC0 +asm/non_matchings/code/z_camera/Camera_CalcAtForFriendlyLockOn.s,Camera_CalcAtForFriendlyLockOn,0x800CDE6C,0x113 +asm/non_matchings/code/z_camera/Camera_CalcAtForEnemyLockOn.s,Camera_CalcAtForEnemyLockOn,0x800CE2B8,0xCA +asm/non_matchings/code/z_camera/Camera_CalcAtForHorse.s,Camera_CalcAtForHorse,0x800CE5E0,0x6F +asm/non_matchings/code/z_camera/Camera_ClampDist1.s,Camera_ClampDist1,0x800CE79C,0x65 +asm/non_matchings/code/z_camera/Camera_ClampDist2.s,Camera_ClampDist2,0x800CE930,0x6A +asm/non_matchings/code/z_camera/Camera_CalcDefaultPitch.s,Camera_CalcDefaultPitch,0x800CEAD8,0x58 +asm/non_matchings/code/z_camera/Camera_CalcDefaultYaw.s,Camera_CalcDefaultYaw,0x800CEC38,0x56 +asm/non_matchings/code/z_camera/Camera_CalcDefaultSwing.s,Camera_CalcDefaultSwing,0x800CED90,0x185 asm/non_matchings/code/z_camera/Camera_Noop.s,Camera_Noop,0x800CF3A4,0x4 asm/non_matchings/code/z_camera/Camera_Normal1.s,Camera_Normal1,0x800CF3B4,0x530 asm/non_matchings/code/z_camera/Camera_Normal2.s,Camera_Normal2,0x800D0874,0x8 @@ -767,48 +767,48 @@ asm/non_matchings/code/z_camera/Camera_Special6.s,Camera_Special6,0x800DD0FC,0x8 asm/non_matchings/code/z_camera/Camera_Special7.s,Camera_Special7,0x800DD11C,0x8 asm/non_matchings/code/z_camera/Camera_Special8.s,Camera_Special8,0x800DD13C,0x11F asm/non_matchings/code/z_camera/Camera_Special9.s,Camera_Special9,0x800DD5B8,0x1E8 -asm/non_matchings/code/z_camera/Camera_Alloc.s,Camera_Alloc,0x800DDD58,0x14 -asm/non_matchings/code/z_camera/Camera_Free.s,Camera_Free,0x800DDDA8,0xA +asm/non_matchings/code/z_camera/Camera_Create.s,Camera_Create,0x800DDD58,0x14 +asm/non_matchings/code/z_camera/Camera_Destroy.s,Camera_Destroy,0x800DDDA8,0xA asm/non_matchings/code/z_camera/Camera_Init.s,Camera_Init,0x800DDDD0,0x84 asm/non_matchings/code/z_camera/func_800DDFE0.s,func_800DDFE0,0x800DDFE0,0x40 -asm/non_matchings/code/z_camera/func_800DE0E0.s,func_800DE0E0,0x800DE0E0,0x3 -asm/non_matchings/code/z_camera/Camera_InitPlayerSettings.s,Camera_InitPlayerSettings,0x800DE0EC,0x87 +asm/non_matchings/code/z_camera/Camera_Stub800DE0E0.s,Camera_Stub800DE0E0,0x800DE0E0,0x3 +asm/non_matchings/code/z_camera/Camera_InitFocalActorSettings.s,Camera_InitFocalActorSettings,0x800DE0EC,0x87 asm/non_matchings/code/z_camera/Camera_ChangeStatus.s,Camera_ChangeStatus,0x800DE308,0x7 -asm/non_matchings/code/z_camera/func_800DE324.s,func_800DE324,0x800DE324,0xC2 -asm/non_matchings/code/z_camera/func_800DE62C.s,func_800DE62C,0x800DE62C,0x85 -asm/non_matchings/code/z_camera/func_800DE840.s,func_800DE840,0x800DE840,0x14 -asm/non_matchings/code/z_camera/func_800DE890.s,func_800DE890,0x800DE890,0x31 -asm/non_matchings/code/z_camera/func_800DE954.s,func_800DE954,0x800DE954,0x17 +asm/non_matchings/code/z_camera/Camera_UpdateWater.s,Camera_UpdateWater,0x800DE324,0xC2 +asm/non_matchings/code/z_camera/Camera_EarthquakeDay3.s,Camera_EarthquakeDay3,0x800DE62C,0x85 +asm/non_matchings/code/z_camera/Camera_UpdateHotRoom.s,Camera_UpdateHotRoom,0x800DE840,0x14 +asm/non_matchings/code/z_camera/Camera_SetSwordDistortion.s,Camera_SetSwordDistortion,0x800DE890,0x31 +asm/non_matchings/code/z_camera/Camera_RequestGiantsMaskSetting.s,Camera_RequestGiantsMaskSetting,0x800DE954,0x17 asm/non_matchings/code/z_camera/Camera_Update.s,Camera_Update,0x800DE9B0,0x2BA asm/non_matchings/code/z_camera/func_800DF498.s,func_800DF498,0x800DF498,0xE -asm/non_matchings/code/z_camera/Camera_SetMode.s,Camera_SetMode,0x800DF4D0,0xDC +asm/non_matchings/code/z_camera/Camera_ChangeModeFlags.s,Camera_ChangeModeFlags,0x800DF4D0,0xDC asm/non_matchings/code/z_camera/Camera_ChangeMode.s,Camera_ChangeMode,0x800DF840,0xB -asm/non_matchings/code/z_camera/func_800DF86C.s,func_800DF86C,0x800DF86C,0x20 -asm/non_matchings/code/z_camera/func_800DF8EC.s,func_800DF8EC,0x800DF8EC,0x77 +asm/non_matchings/code/z_camera/Camera_CheckValidMode.s,Camera_CheckValidMode,0x800DF86C,0x20 +asm/non_matchings/code/z_camera/Camera_ChangeSettingFlags.s,Camera_ChangeSettingFlags,0x800DF8EC,0x77 asm/non_matchings/code/z_camera/Camera_ChangeSetting.s,Camera_ChangeSetting,0x800DFAC8,0x13 -asm/non_matchings/code/z_camera/Camera_ChangeDataIdx.s,Camera_ChangeDataIdx,0x800DFB14,0x42 -asm/non_matchings/code/z_camera/func_800DFC1C.s,func_800DFC1C,0x800DFC1C,0x9 -asm/non_matchings/code/z_camera/func_800DFC40.s,func_800DFC40,0x800DFC40,0xA +asm/non_matchings/code/z_camera/Camera_ChangeActorCsCamIndex.s,Camera_ChangeActorCsCamIndex,0x800DFB14,0x42 +asm/non_matchings/code/z_camera/Camera_GetInputDir.s,Camera_GetInputDir,0x800DFC1C,0x9 +asm/non_matchings/code/z_camera/Camera_GetInputDirPitch.s,Camera_GetInputDirPitch,0x800DFC40,0xA asm/non_matchings/code/z_camera/Camera_GetInputDirYaw.s,Camera_GetInputDirYaw,0x800DFC68,0xA asm/non_matchings/code/z_camera/Camera_GetCamDir.s,Camera_GetCamDir,0x800DFC90,0x9 asm/non_matchings/code/z_camera/Camera_GetCamDirPitch.s,Camera_GetCamDirPitch,0x800DFCB4,0xA asm/non_matchings/code/z_camera/Camera_GetCamDirYaw.s,Camera_GetCamDirYaw,0x800DFCDC,0xA asm/non_matchings/code/z_camera/Camera_AddQuake.s,Camera_AddQuake,0x800DFD04,0x1D asm/non_matchings/code/z_camera/Camera_SetViewParam.s,Camera_SetViewParam,0x800DFD78,0x5E -asm/non_matchings/code/z_camera/func_800DFEF0.s,func_800DFEF0,0x800DFEF0,0xA -asm/non_matchings/code/z_camera/func_800DFF18.s,func_800DFF18,0x800DFF18,0x7 -asm/non_matchings/code/z_camera/func_800DFF34.s,func_800DFF34,0x800DFF34,0x4 -asm/non_matchings/code/z_camera/func_800DFF44.s,func_800DFF44,0x800DFF44,0x7 -asm/non_matchings/code/z_camera/Camera_SetFlags.s,Camera_SetFlags,0x800DFF60,0x9 -asm/non_matchings/code/z_camera/Camera_ClearFlags.s,Camera_ClearFlags,0x800DFF84,0xA +asm/non_matchings/code/z_camera/Camera_UnsetViewFlag.s,Camera_UnsetViewFlag,0x800DFEF0,0xA +asm/non_matchings/code/z_camera/Camera_OverwriteStateFlags.s,Camera_OverwriteStateFlags,0x800DFF18,0x7 +asm/non_matchings/code/z_camera/Camera_ResetActionFuncStateUnused.s,Camera_ResetActionFuncStateUnused,0x800DFF34,0x4 +asm/non_matchings/code/z_camera/Camera_SetCsParams.s,Camera_SetCsParams,0x800DFF44,0x7 +asm/non_matchings/code/z_camera/Camera_SetStateFlag.s,Camera_SetStateFlag,0x800DFF60,0x9 +asm/non_matchings/code/z_camera/Camera_UnsetStateFlag.s,Camera_UnsetStateFlag,0x800DFF84,0xA asm/non_matchings/code/z_camera/Camera_ChangeDoorCam.s,Camera_ChangeDoorCam,0x800DFFAC,0x34 asm/non_matchings/code/z_camera/Camera_Copy.s,Camera_Copy,0x800E007C,0x4C -asm/non_matchings/code/z_camera/func_800E01AC.s,func_800E01AC,0x800E01AC,0x3 +asm/non_matchings/code/z_camera/Camera_IsDbgCamEnabled.s,Camera_IsDbgCamEnabled,0x800E01AC,0x3 asm/non_matchings/code/z_camera/Camera_GetQuakeOffset.s,Camera_GetQuakeOffset,0x800E01B8,0x9 -asm/non_matchings/code/z_camera/func_800E01DC.s,func_800E01DC,0x800E01DC,0x13 -asm/non_matchings/code/z_camera/func_800E0228.s,func_800E0228,0x800E0228,0x4 +asm/non_matchings/code/z_camera/Camera_SetCameraData.s,Camera_SetCameraData,0x800E01DC,0x13 +asm/non_matchings/code/z_camera/Camera_GetNegOne.s,Camera_GetNegOne,0x800E0228,0x4 asm/non_matchings/code/z_camera/func_800E0238.s,func_800E0238,0x800E0238,0x1D -asm/non_matchings/code/z_camera/Camera_SetToTrackActor.s,Camera_SetToTrackActor,0x800E02AC,0x17 +asm/non_matchings/code/z_camera/Camera_SetFocalActor.s,Camera_SetFocalActor,0x800E02AC,0x17 asm/non_matchings/code/z_camera/Camera_SetTargetActor.s,Camera_SetTargetActor,0x800E0308,0x5 asm/non_matchings/code/z_camera/Camera_GetWaterYPos.s,Camera_GetWaterYPos,0x800E031C,0xB asm/non_matchings/code/z_camera/func_800E0348.s,func_800E0348,0x800E0348,0x16 @@ -1586,17 +1586,17 @@ asm/non_matchings/code/z_olib/OLib_ClampMinDist.s,OLib_ClampMinDist,0x8010C304,0 asm/non_matchings/code/z_olib/OLib_ClampMaxDist.s,OLib_ClampMaxDist,0x8010C36C,0x1A asm/non_matchings/code/z_olib/OLib_Vec3fDistNormalize.s,OLib_Vec3fDistNormalize,0x8010C3D4,0x2C asm/non_matchings/code/z_olib/OLib_VecSphToVec3f.s,OLib_VecSphToVec3f,0x8010C484,0x2B -asm/non_matchings/code/z_olib/OLib_VecSphGeoToVec3f.s,OLib_VecSphGeoToVec3f,0x8010C530,0x11 +asm/non_matchings/code/z_olib/OLib_VecGeoToVec3f.s,OLib_VecGeoToVec3f,0x8010C530,0x11 asm/non_matchings/code/z_olib/OLib_Vec3fToVecSph.s,OLib_Vec3fToVecSph,0x8010C574,0x55 -asm/non_matchings/code/z_olib/OLib_Vec3fToVecSphGeo.s,OLib_Vec3fToVecSphGeo,0x8010C6C8,0x12 +asm/non_matchings/code/z_olib/OLib_Vec3fToVecGeo.s,OLib_Vec3fToVecGeo,0x8010C6C8,0x12 asm/non_matchings/code/z_olib/OLib_Vec3fDiffToVecSph.s,OLib_Vec3fDiffToVecSph,0x8010C710,0x15 -asm/non_matchings/code/z_olib/OLib_Vec3fDiffToVecSphGeo.s,OLib_Vec3fDiffToVecSphGeo,0x8010C764,0x15 -asm/non_matchings/code/z_olib/OLib_VecSphAddToVec3f.s,OLib_VecSphAddToVec3f,0x8010C7B8,0x20 +asm/non_matchings/code/z_olib/OLib_Vec3fDiffToVecGeo.s,OLib_Vec3fDiffToVecGeo,0x8010C764,0x15 +asm/non_matchings/code/z_olib/OLib_AddVecGeoToVec3f.s,OLib_AddVecGeoToVec3f,0x8010C7B8,0x20 asm/non_matchings/code/z_olib/OLib_Vec3fDiffRad.s,OLib_Vec3fDiffRad,0x8010C838,0x24 asm/non_matchings/code/z_olib/OLib_Vec3fDiffDegF.s,OLib_Vec3fDiffDegF,0x8010C8C8,0x1A asm/non_matchings/code/z_olib/OLib_Vec3fDiffBinAng.s,OLib_Vec3fDiffBinAng,0x8010C930,0x26 -asm/non_matchings/code/z_olib/OLib_DbCameraVec3fDiff.s,OLib_DbCameraVec3fDiff,0x8010C9C8,0x36 -asm/non_matchings/code/z_olib/OLib_DbCameraVec3fSum.s,OLib_DbCameraVec3fSum,0x8010CAA0,0x34 +asm/non_matchings/code/z_olib/OLib_Vec3fDiff.s,OLib_Vec3fDiff,0x8010C9C8,0x36 +asm/non_matchings/code/z_olib/OLib_Vec3fAdd.s,OLib_Vec3fAdd,0x8010CAA0,0x34 asm/non_matchings/code/z_parameter/Gfx_DrawTexRectRGBA16.s,Gfx_DrawTexRectRGBA16,0x8010CB80,0x86 asm/non_matchings/code/z_parameter/Gfx_DrawTexRectIA8.s,Gfx_DrawTexRectIA8,0x8010CD98,0x89 asm/non_matchings/code/z_parameter/Gfx_DrawTexRectIA8_DropShadow.s,Gfx_DrawTexRectIA8_DropShadow,0x8010CFBC,0xC6 @@ -1803,28 +1803,28 @@ asm/non_matchings/code/z_quake/Quake_CallbackType3.s,Quake_CallbackType3,0x8012A asm/non_matchings/code/z_quake/Quake_CallbackType2.s,Quake_CallbackType2,0x8012A4D0,0x1C asm/non_matchings/code/z_quake/Quake_CallbackType4.s,Quake_CallbackType4,0x8012A540,0x26 asm/non_matchings/code/z_quake/Quake_GetFreeIndex.s,Quake_GetFreeIndex,0x8012A5D8,0x18 -asm/non_matchings/code/z_quake/Quake_AddImpl.s,Quake_AddImpl,0x8012A638,0x2E -asm/non_matchings/code/z_quake/Quake_RemoveRequest.s,Quake_RemoveRequest,0x8012A6F0,0xA +asm/non_matchings/code/z_quake/Quake_RequestImpl.s,Quake_RequestImpl,0x8012A638,0x2E +asm/non_matchings/code/z_quake/Quake_Remove.s,Quake_Remove,0x8012A6F0,0xA asm/non_matchings/code/z_quake/Quake_GetRequest.s,Quake_GetRequest,0x8012A718,0x17 asm/non_matchings/code/z_quake/Quake_SetValue.s,Quake_SetValue,0x8012A774,0x4D asm/non_matchings/code/z_quake/Quake_SetSpeed.s,Quake_SetSpeed,0x8012A8A8,0x12 -asm/non_matchings/code/z_quake/Quake_SetCountdown.s,Quake_SetCountdown,0x8012A8F0,0x14 -asm/non_matchings/code/z_quake/Quake_GetCountdown.s,Quake_GetCountdown,0x8012A940,0xE -asm/non_matchings/code/z_quake/Quake_SetQuakeValues.s,Quake_SetQuakeValues,0x8012A978,0x1A -asm/non_matchings/code/z_quake/Quake_SetQuakeValues2.s,Quake_SetQuakeValues2,0x8012A9E0,0x1A +asm/non_matchings/code/z_quake/Quake_SetDuration.s,Quake_SetDuration,0x8012A8F0,0x14 +asm/non_matchings/code/z_quake/Quake_GetTimeLeft.s,Quake_GetTimeLeft,0x8012A940,0xE +asm/non_matchings/code/z_quake/Quake_SetPerturbations.s,Quake_SetPerturbations,0x8012A978,0x1A +asm/non_matchings/code/z_quake/Quake_SetOrientation.s,Quake_SetOrientation,0x8012A9E0,0x1A asm/non_matchings/code/z_quake/Quake_Init.s,Quake_Init,0x8012AA48,0x15 -asm/non_matchings/code/z_quake/Quake_Add.s,Quake_Add,0x8012AA9C,0x9 -asm/non_matchings/code/z_quake/Quake_Remove.s,Quake_Remove,0x8012AAC0,0x12 -asm/non_matchings/code/z_quake/Quake_Calc.s,Quake_Calc,0x8012AB08,0xD8 +asm/non_matchings/code/z_quake/Quake_Request.s,Quake_Request,0x8012AA9C,0x9 +asm/non_matchings/code/z_quake/Quake_RemoveRequest.s,Quake_RemoveRequest,0x8012AAC0,0x12 +asm/non_matchings/code/z_quake/Quake_Update.s,Quake_Update,0x8012AB08,0xD8 asm/non_matchings/code/z_quake/Distortion_Init.s,Distortion_Init,0x8012AE68,0x11 -asm/non_matchings/code/z_quake/Distortion_SetCountdown.s,Distortion_SetCountdown,0x8012AEAC,0xA -asm/non_matchings/code/z_quake/Distortion_GetCountdown.s,Distortion_GetCountdown,0x8012AED4,0x4 +asm/non_matchings/code/z_quake/Distortion_SetDuration.s,Distortion_SetDuration,0x8012AEAC,0xA +asm/non_matchings/code/z_quake/Distortion_GetTimeLeft.s,Distortion_GetTimeLeft,0x8012AED4,0x4 asm/non_matchings/code/z_quake/Distortion_GetType.s,Distortion_GetType,0x8012AEE4,0x4 -asm/non_matchings/code/z_quake/Distortion_SetType.s,Distortion_SetType,0x8012AEF4,0x9 -asm/non_matchings/code/z_quake/Distortion_ClearType.s,Distortion_ClearType,0x8012AF18,0x8 +asm/non_matchings/code/z_quake/Distortion_Request.s,Distortion_Request,0x8012AEF4,0x9 +asm/non_matchings/code/z_quake/Distortion_RemoveRequest.s,Distortion_RemoveRequest,0x8012AF18,0x8 asm/non_matchings/code/z_quake/Distortion_GetUnderwaterCurrentSpeed.s,Distortion_GetUnderwaterCurrentSpeed,0x8012AF38,0x19 asm/non_matchings/code/z_quake/Distortion_Update.s,Distortion_Update,0x8012AF9C,0x313 -asm/non_matchings/code/z_quake/Quake_NumActiveQuakes.s,Quake_NumActiveQuakes,0x8012BBE8,0x1A +asm/non_matchings/code/z_quake/Quake_GetNumActiveQuakes.s,Quake_GetNumActiveQuakes,0x8012BBE8,0x1A asm/non_matchings/code/z_rcp/Gfx_SetFog.s,Gfx_SetFog,0x8012BC50,0x4F asm/non_matchings/code/z_rcp/Gfx_SetFogWithSync.s,Gfx_SetFogWithSync,0x8012BD8C,0x5F asm/non_matchings/code/z_rcp/Gfx_SetFog2.s,Gfx_SetFog2,0x8012BF08,0xD diff --git a/tools/weekeventregconvert.py b/tools/weekeventregconvert.py index 34b3ddc46..b96696b46 100755 --- a/tools/weekeventregconvert.py +++ b/tools/weekeventregconvert.py @@ -73,7 +73,7 @@ weekEventReg = { ( 8 << 8) | 0x04: "WEEKEVENTREG_08_04", ( 8 << 8) | 0x08: "WEEKEVENTREG_08_08", ( 8 << 8) | 0x10: "WEEKEVENTREG_08_10", - ( 8 << 8) | 0x20: "WEEKEVENTREG_08_20", + ( 8 << 8) | 0x20: "WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE", ( 8 << 8) | 0x40: "WEEKEVENTREG_08_40", ( 8 << 8) | 0x80: "WEEKEVENTREG_08_80", ( 9 << 8) | 0x01: "WEEKEVENTREG_09_01", @@ -279,7 +279,7 @@ weekEventReg = { (34 << 8) | 0x01: "WEEKEVENTREG_34_01", (34 << 8) | 0x02: "WEEKEVENTREG_34_02", (34 << 8) | 0x04: "WEEKEVENTREG_34_04", - (34 << 8) | 0x08: "WEEKEVENTREG_SWAMP_SPIDER_HOUSE_TALKED", + (34 << 8) | 0x08: "WEEKEVENTREG_TALKED_SWAMP_SPIDER_HOUSE_MAN", (34 << 8) | 0x10: "WEEKEVENTREG_34_10", (34 << 8) | 0x20: "WEEKEVENTREG_34_20", (34 << 8) | 0x40: "WEEKEVENTREG_RECEIVED_MASK_OF_TRUTH", @@ -523,12 +523,12 @@ weekEventReg = { (64 << 8) | 0x10: "WEEKEVENTREG_64_10", (64 << 8) | 0x20: "WEEKEVENTREG_64_20", (64 << 8) | 0x40: "WEEKEVENTREG_64_40", - (64 << 8) | 0x80: "WEEKEVENTREG_64_80", - (65 << 8) | 0x01: "WEEKEVENTREG_65_01", - (65 << 8) | 0x02: "WEEKEVENTREG_65_02", - (65 << 8) | 0x04: "WEEKEVENTREG_65_04", - (65 << 8) | 0x08: "WEEKEVENTREG_65_08", - (65 << 8) | 0x10: "WEEKEVENTREG_65_10", + (64 << 8) | 0x80: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_1", + (65 << 8) | 0x01: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_1", + (65 << 8) | 0x02: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_2", + (65 << 8) | 0x04: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_2", + (65 << 8) | 0x08: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_DAY_3", + (65 << 8) | 0x10: "WEEKEVENTREG_TALKED_DOGGY_RACETRACK_OWNER_NIGHT_3", (65 << 8) | 0x20: "WEEKEVENTREG_65_20", (65 << 8) | 0x40: "WEEKEVENTREG_65_40", (65 << 8) | 0x80: "WEEKEVENTREG_65_80", diff --git a/undefined_syms.txt b/undefined_syms.txt index f0578ff16..1e09ceaab 100644 --- a/undefined_syms.txt +++ b/undefined_syms.txt @@ -770,10 +770,6 @@ D_060111E8 = 0x060111E8; D_06012478 = 0x06012478; D_06012618 = 0x06012618; -// ovl_En_And - -D_0600B380 = 0x0600B380; - // ovl_En_Bal D_060005FC = 0x060005FC;