diff --git a/Makefile b/Makefile index 5cefd6257a..4b1260b47a 100644 --- a/Makefile +++ b/Makefile @@ -133,7 +133,7 @@ OBJCOPY := $(MIPS_BINUTILS_PREFIX)objcopy OBJDUMP := $(MIPS_BINUTILS_PREFIX)objdump NM := $(MIPS_BINUTILS_PREFIX)nm -N64_EMULATOR ?= +N64_EMULATOR ?= INC := -Iinclude -Iinclude/libc -Isrc -I$(BUILD_DIR) -I. -I$(EXTRACTED_DIR) @@ -243,7 +243,7 @@ $(BUILD_DIR)/src/boot/stackcheck.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/__osMalloc.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/code_800FC620.o: OPTFLAGS := -O2 -$(BUILD_DIR)/src/code/code_800FCE80.o: OPTFLAGS := -O2 +$(BUILD_DIR)/src/code/fp_math.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/rand.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/gfxprint.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/jpegutils.o: OPTFLAGS := -O2 diff --git a/include/fp_math.h b/include/fp_math.h new file mode 100644 index 0000000000..26f9b171b7 --- /dev/null +++ b/include/fp_math.h @@ -0,0 +1,17 @@ +#ifndef FP_MATH_H +#define FP_MATH_H + +#include "ultra64.h" + +f32 Math_FTanF(f32 angle); +f32 Math_FFloorF(f32 x); +f32 Math_FCeilF(f32 x); +f32 Math_FRoundF(f32 x); +f32 Math_FNearbyIntF(f32 x); +f32 Math_FTruncF(f32 x); +f32 Math_FAtanF(f32 x); +f32 Math_FAtan2F(f32 y, f32 x); +f32 Math_FAsinF(f32 x); +f32 Math_FAcosF(f32 x); + +#endif diff --git a/include/functions.h b/include/functions.h index 35b378a7a8..54b57c8ea5 100644 --- a/include/functions.h +++ b/include/functions.h @@ -4,23 +4,6 @@ #include "z64.h" #include "macros.h" -f32 fabsf(f32 f); -#ifdef __sgi -#pragma intrinsic(fabsf) -#else -#define fabsf(f) __builtin_fabsf((f32)(f)) -#endif - -f32 sqrtf(f32 f); -#ifdef __sgi -#pragma intrinsic(sqrtf) -#endif - -f64 sqrt(f64 f); -#ifdef __sgi -#pragma intrinsic(sqrt) -#endif - void cleararena(void); void bootproc(void); void Main_ThreadEntry(void* arg); @@ -839,41 +822,6 @@ s32 Environment_IsForcedSequenceDisabled(void); void Environment_PlayStormNatureAmbience(PlayState* play); void Environment_StopStormNatureAmbience(PlayState* play); void Environment_WarpSongLeave(PlayState* play); -void Lib_MemSet(u8* dest, size_t len, u8 val); -f32 Math_CosS(s16 angle); -f32 Math_SinS(s16 angle); -s32 Math_ScaledStepToS(s16* pValue, s16 target, s16 step); -s32 Math_StepToS(s16* pValue, s16 target, s16 step); -s32 Math_StepToF(f32* pValue, f32 target, f32 step); -s32 Math_StepUntilAngleS(s16* pValue, s16 limit, s16 step); -s32 Math_StepUntilS(s16* pValue, s16 limit, s16 step); -s32 Math_StepToAngleS(s16* pValue, s16 target, s16 step); -s32 Math_StepUntilF(f32* pValue, f32 limit, f32 step); -s32 Math_AsymStepToF(f32* pValue, f32 target, f32 incrStep, f32 decrStep); -void Lib_GetControlStickData(f32* outMagnitude, s16* outAngle, Input* input); -s16 Rand_S16Offset(s16 base, s16 range); -void Math_Vec3f_Copy(Vec3f* dest, Vec3f* src); -void Math_Vec3s_ToVec3f(Vec3f* dest, Vec3s* src); -void Math_Vec3f_Sum(Vec3f* a, Vec3f* b, Vec3f* dest); -void Math_Vec3f_Diff(Vec3f* a, Vec3f* b, Vec3f* dest); -void Math_Vec3s_DiffToVec3f(Vec3f* dest, Vec3s* a, Vec3s* b); -void Math_Vec3f_Scale(Vec3f* vec, f32 scaleF); -f32 Math_Vec3f_DistXYZ(Vec3f* a, Vec3f* b); -f32 Math_Vec3f_DistXYZAndStoreDiff(Vec3f* a, Vec3f* b, Vec3f* dest); -f32 Math_Vec3f_DistXZ(Vec3f* a, Vec3f* b); -s16 Math_Vec3f_Yaw(Vec3f* origin, Vec3f* point); -s16 Math_Vec3f_Pitch(Vec3f* a, Vec3f* b); -void Actor_ProcessInitChain(Actor* actor, InitChainEntry* ichain); -f32 Math_SmoothStepToF(f32* pValue, f32 target, f32 fraction, f32 step, f32 minStep); -void Math_ApproachF(f32* pValue, f32 target, f32 fraction, f32 step); -void Math_ApproachZeroF(f32* pValue, f32 fraction, f32 step); -f32 Math_SmoothStepToDegF(f32* pValue, f32 target, f32 fraction, f32 step, f32 minStep); -s16 Math_SmoothStepToS(s16* pValue, s16 target, s16 scale, s16 step, s16 minStep); -void Math_ApproachS(s16* pValue, s16 target, s16 scale, s16 step); -void Color_RGBA8_Copy(Color_RGBA8* dst, Color_RGBA8* src); -void Sfx_PlaySfxCentered(u16 sfxId); -void Sfx_PlaySfxCentered2(u16 sfxId); -void Sfx_PlaySfxAtPos(Vec3f* projectedPos, u16 sfxId); void Health_InitMeter(PlayState* play); void Health_UpdateMeter(PlayState* play); void Health_DrawMeter(PlayState* play); @@ -1346,80 +1294,9 @@ void Main(void* arg); void SysCfb_Init(s32 n64dd); void* SysCfb_GetFbPtr(s32 idx); void* SysCfb_GetFbEnd(void); -f32 Math_FactorialF(f32 n); -f32 Math_Factorial(s32 n); -f32 Math_PowF(f32 base, s32 exp); -f32 Math_SinF(f32 angle); -f32 Math_CosF(f32 angle); -s32 Math3D_PlaneVsLineSegClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, f32 planeBB, - f32 planeBC, f32 planeBDist, Vec3f* linePointA, Vec3f* linePointB, - Vec3f* closestPoint); -void Math3D_LineClosestToPoint(InfiniteLine* line, Vec3f* pos, Vec3f* closestPoint); -s32 Math3D_PlaneVsPlaneVsLineClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, - f32 planeBB, f32 planeBC, f32 planeBDist, Vec3f* point, Vec3f* closestPoint); -void Math3D_LineSplitRatio(Vec3f* v0, Vec3f* v1, f32 ratio, Vec3f* ret); -f32 Math3D_Cos(Vec3f* a, Vec3f* b); -s32 Math3D_CosOut(Vec3f* a, Vec3f* b, f32* dst); -void Math3D_Vec3fReflect(Vec3f* vec, Vec3f* normal, Vec3f* reflVec); -s32 Math3D_PointInSquare2D(f32 upperLeftX, f32 lowerRightX, f32 upperLeftY, f32 lowerRightY, f32 x, f32 y); -f32 Math3D_Dist1DSq(f32 a, f32 b); -f32 Math3D_Dist2DSq(f32 x0, f32 y0, f32 x1, f32 y1); -f32 Math3D_Vec3fMagnitudeSq(Vec3f* vec); -f32 Math3D_Vec3fMagnitude(Vec3f* vec); -f32 Math3D_Vec3fDistSq(Vec3f* a, Vec3f* b); -void Math3D_Vec3f_Cross(Vec3f* a, Vec3f* b, Vec3f* ret); -void Math3D_SurfaceNorm(Vec3f* va, Vec3f* vb, Vec3f* vc, Vec3f* normal); -f32 Math3D_Vec3f_DistXYZ(Vec3f* a, Vec3f* b); -s32 Math3D_PointRelativeToCubeFaces(Vec3f* point, Vec3f* min, Vec3f* max); -s32 Math3D_PointRelativeToCubeEdges(Vec3f* point, Vec3f* min, Vec3f* max); -s32 Math3D_PointRelativeToCubeVertices(Vec3f* point, Vec3f* min, Vec3f* max); -s32 Math3D_LineVsCube(Vec3f* min, Vec3f* max, Vec3f* a, Vec3f* b); -void Math3D_RotateXZPlane(Vec3f* pointOnPlane, s16 angle, f32* a, f32* c, f32* d); -void Math3D_DefPlane(Vec3f* va, Vec3f* vb, Vec3f* vc, f32* nx, f32* ny, f32* nz, f32* originDist); -f32 Math3D_UDistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p); -f32 Math3D_DistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p); -s32 Math3D_TriChkPointParaYSlopedY(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x); -s32 Math3D_TriChkPointParaYIntersectDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, - f32 x, f32* yIntersect, f32 chkDist); -s32 Math3D_TriChkPointParaYIntersectInsideTri(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, - f32 z, f32 x, f32* yIntersect, f32 chkDist); -s32 Math3D_TriChkLineSegParaYIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, - f32 x, f32* yIntersect, f32 y0, f32 y1); -s32 Math3D_TriChkPointParaYDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 z, f32 x, f32 chkDist); -s32 Math3D_TriChkPointParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, - f32 z, f32* xIntersect); -s32 Math3D_TriChkLineSegParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, - f32 z, f32* xIntersect, f32 x0, f32 x1); -s32 Math3D_TriChkPointParaXDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 y, f32 z, f32 chkDist); -s32 Math3D_TriChkPointParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, - f32 y, f32* zIntersect); -s32 Math3D_TriChkLineSegParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, - f32 y, f32* zIntersect, f32 z0, f32 z1); -s32 Math3D_TriChkLineSegParaZDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 x, f32 y, f32 chkDist); -s32 Math3D_LineSegVsPlane(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec3f* linePointB, - Vec3f* intersect, s32 fromFront); -void Math3D_TriNorm(TriNorm* tri, Vec3f* va, Vec3f* vb, Vec3f* vc); -s32 Math3D_PointDistSqToLine2D(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32* lineLenSq); -s32 Math3D_LineVsSph(Sphere16* sphere, Linef* line); -s32 Math3D_TriVsSphIntersect(Sphere16* sphere, TriNorm* tri, Vec3f* intersectPoint); -s32 Math3D_CylVsLineSeg(Cylinder16* cyl, Vec3f* linePointA, Vec3f* linePointB, Vec3f* intersectA, Vec3f* intersectB); -s32 Math3D_CylVsTri(Cylinder16* cyl, TriNorm* tri); -s32 Math3D_CylTriVsIntersect(Cylinder16* cyl, TriNorm* tri, Vec3f* intersect); -s32 Math3D_SphVsSph(Sphere16* sphereA, Sphere16* sphereB); -s32 Math3D_SphVsSphOverlap(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize); -s32 Math3D_SphVsSphOverlapCenterDist(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize, f32* centerDist); -s32 Math3D_SphVsCylOverlap(Sphere16* sph, Cylinder16* cyl, f32* overlapSize); -s32 Math3D_SphVsCylOverlapCenterDist(Sphere16* sph, Cylinder16* cyl, f32* overlapSize, f32* centerDist); -s32 Math3D_CylVsCylOverlap(Cylinder16* ca, Cylinder16* cb, f32* overlapSize); -s32 Math3D_CylVsCylOverlapCenterDist(Cylinder16* ca, Cylinder16* cb, f32* overlapSize, f32* centerDist); -s32 Math3D_TriVsTriIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect); -s32 Math3D_XZInSphere(Sphere16* sphere, f32 x, f32 z); -s32 Math3D_XYInSphere(Sphere16* sphere, f32 x, f32 y); -s32 Math3D_YZInSphere(Sphere16* sphere, f32 y, f32 z); + void Math3D_DrawSphere(PlayState* play, Sphere16* sph); void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl); -s16 Math_Atan2S(f32 x, f32 y); -f32 Math_Atan2F(f32 x, f32 y); void Matrix_Init(GameState* gameState); void Matrix_Push(void); void Matrix_Pop(void); @@ -1681,24 +1558,7 @@ void Audio_Init(void); void Audio_InitSound(void); void func_800F7170(void); void func_800F71BC(s32 arg0); -void Audio_SetSfxBanksMute(u16 muteMask); -void Audio_QueueSeqCmdMute(u8 channelIndex); -void Audio_ClearBGMMute(u8 channelIndex); -void Audio_PlaySfxGeneral(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* vol, s8* reverbAdd); -void Audio_ProcessSfxRequest(void); -void Audio_ChooseActiveSfx(u8 bankId); -void Audio_PlayActiveSfx(u8 bankId); -void Audio_StopSfxByBank(u8 bankId); -void func_800F8884(u8 bankId, Vec3f* pos); -void Audio_StopSfxByPosAndBank(u8 bankId, Vec3f* pos); -void Audio_StopSfxByPos(Vec3f* pos); -void Audio_StopSfxByPosAndId(Vec3f* pos, u16 sfxId); -void Audio_StopSfxByTokenAndId(u8 token, u16 sfxId); -void Audio_StopSfxById(u32 sfxId); -void Audio_ProcessSfxRequests(void); -void func_800F8F88(void); -u8 Audio_IsSfxPlaying(u32 sfxId); -void Audio_ResetSfx(void); + void Audio_StartSequence(u8 seqPlayerIndex, u8 seqId, u8 seqArgs, u16 fadeInDuration); void Audio_StopSequence(u8 seqPlayerIndex, u16 fadeOutDuration); void Audio_QueueSeqCmd(u32 cmd); @@ -1748,20 +1608,7 @@ s8 PadUtils_GetRelX(Input* input); s8 PadUtils_GetRelY(Input* input); void PadUtils_UpdateRelXY(Input* input); s32 PadSetup_Init(OSMesgQueue* mq, u8* outMask, OSContStatus* status); -f32 Math_FTanF(f32 angle); -f32 Math_FFloorF(f32 x); -f32 Math_FCeilF(f32 x); -f32 Math_FRoundF(f32 x); -f32 Math_FNearbyIntF(f32 x); -f32 Math_FTruncF(f32 x); -f32 Math_FAtanF(f32 x); -f32 Math_FAtan2F(f32 y, f32 x); -f32 Math_FAsinF(f32 x); -f32 Math_FAcosF(f32 x); -f32 ceilf(f32 x); -f32 truncf(f32 x); -f32 roundf(f32 x); -f32 nearbyintf(f32 x); + void* SystemArena_Malloc(u32 size); void* SystemArena_MallocR(u32 size); void* SystemArena_Realloc(void* ptr, u32 newSize); @@ -1779,14 +1626,7 @@ void* SystemArena_ReallocDebug(void* ptr, u32 newSize, const char* file, int lin void SystemArena_FreeDebug(void* ptr, const char* file, int line); void SystemArena_Display(void); #endif -u32 Rand_Next(void); -void Rand_Seed(u32 seed); -f32 Rand_ZeroOne(void); -f32 Rand_Centered(void); -void Rand_Seed_Variable(u32* rndNum, u32 seed); -u32 Rand_Next_Variable(u32* rndNum); -f32 Rand_ZeroOne_Variable(u32* rndNum); -f32 Rand_Centered_Variable(u32* rndNum); + void __osMallocInit(Arena* arena, void* start, u32 size); void __osMallocAddBlock(Arena* arena, void* start, s32 size); void __osMallocCleanup(Arena* arena); @@ -1825,8 +1665,6 @@ s32 JpegDecoder_ParseNextSymbol(JpegHuffmanTable* hTable, s16* outCoeff, s8* out u16 JpegDecoder_ReadBits(u8 len); s32 osPfsFreeBlocks(OSPfs* pfs, s32* leftoverBytes); void guScale(Mtx* m, f32 x, f32 y, f32 z); -f32 sinf(f32 angle); -s16 sins(u16 angle); OSTask* _VirtualToPhysicalTask(OSTask* intp); void osSpTaskLoad(OSTask* intp); void osSpTaskStartGo(OSTask* tp); @@ -1890,8 +1728,6 @@ s32 osPfsDeleteFile(OSPfs* pfs, u16 companyCode, u32 gameCode, u8* gameName, u8* s32 __osPfsReleasePages(OSPfs* pfs, __OSInode* inode, u8 initialPage, u8 bank, __OSInodeUnit* finalPage); void guOrthoF(f32[4][4], f32, f32, f32, f32, f32, f32, f32); void guOrtho(Mtx*, f32, f32, f32, f32, f32, f32, f32); -f32 cosf(f32 angle); -s16 coss(u16 angle); void osViSetEvent(OSMesgQueue* mq, OSMesg msg, u32 retraceCount); s32 osPfsIsPlug(OSMesgQueue* mq, u8* pattern); void __osPfsRequestData(u8 cmd); diff --git a/include/ichain.h b/include/ichain.h index 07bd073133..8334237801 100644 --- a/include/ichain.h +++ b/include/ichain.h @@ -1,7 +1,9 @@ #ifndef ICHAIN_H #define ICHAIN_H -#include "libc/stddef.h" +#include "ultra64.h" + +struct Actor; typedef struct { u32 cont: 1; @@ -55,4 +57,6 @@ typedef enum { #define ICHAIN_CONTINUE 1 #define ICHAIN_STOP 0 +void Actor_ProcessInitChain(struct Actor* actor, InitChainEntry* ichain); + #endif diff --git a/include/libc/math.h b/include/libc/math.h index 831be6de7e..d8031ee1a6 100644 --- a/include/libc/math.h +++ b/include/libc/math.h @@ -34,6 +34,23 @@ double round(double); long lroundf(float); long lround(double); +f32 fabsf(f32 f); +#ifdef __sgi +#pragma intrinsic(fabsf) +#else +#define fabsf(f) __builtin_fabsf((f32)(f)) +#endif + +f32 sqrtf(f32 f); +#ifdef __sgi +#pragma intrinsic(sqrtf) +#endif + +f64 sqrt(f64 f); +#ifdef __sgi +#pragma intrinsic(sqrt) +#endif + extern float qNaN0x3FFFFF; extern float qNaN0x10000; extern float sNaN0x3FFFFF; diff --git a/include/macros.h b/include/macros.h index 97627d9b4c..6315fbe94c 100644 --- a/include/macros.h +++ b/include/macros.h @@ -14,7 +14,6 @@ #define VIRTUAL_TO_PHYSICAL(addr) (uintptr_t)((u8*)(addr) - 0x80000000) #define SEGMENTED_TO_VIRTUAL(addr) PHYSICAL_TO_VIRTUAL(gSegments[SEGMENT_NUMBER(addr)] + SEGMENT_OFFSET(addr)) -#define SQ(x) ((x)*(x)) #define ABS(x) ((x) >= 0 ? (x) : -(x)) #define DECR(x) ((x) == 0 ? 0 : --(x)) #define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x)) diff --git a/include/rand.h b/include/rand.h new file mode 100644 index 0000000000..508c9d6466 --- /dev/null +++ b/include/rand.h @@ -0,0 +1,15 @@ +#ifndef RAND_H +#define RAND_H + +#include "ultra64.h" + +u32 Rand_Next(void); +void Rand_Seed(u32 seed); +f32 Rand_ZeroOne(void); +f32 Rand_Centered(void); +void Rand_Seed_Variable(u32* rndNum, u32 seed); +u32 Rand_Next_Variable(u32* rndNum); +f32 Rand_ZeroOne_Variable(u32* rndNum); +f32 Rand_Centered_Variable(u32* rndNum); + +#endif diff --git a/include/regs.h b/include/regs.h index e1eb9d8b93..4a11f7a557 100644 --- a/include/regs.h +++ b/include/regs.h @@ -109,6 +109,7 @@ #define R_C_UP_ICON_Y YREG(89) #define R_EPONAS_SONG_PLAYED DREG(53) #define R_MAGIC_FILL_COLOR(i) ZREG(0 + (i)) +#define R_PAUSE_PAGE_SWITCH_FRAME_ADVANCE_ON ZREG(13) #define R_C_BTN_COLOR(i) ZREG(39 + (i)) #define R_B_BTN_COLOR(i) ZREG(43 + (i)) #define R_START_LABEL_DD(i) ZREG(48 + (i)) @@ -352,4 +353,15 @@ typedef enum { #define R_VI_CUR_ADDI_SCAN_LINES HREG(83) #define R_VI_CUR_Y_SCALE_MODE HREG(84) +typedef struct { + /* 0x00 */ s32 regPage; // 0: no page selected (reg editor is not active); 1: first page; `REG_PAGES`: last page + /* 0x04 */ s32 regGroup; // Indexed from 0 to `REG_GROUPS`-1. Each group has its own character to identify it. + /* 0x08 */ s32 regCur; // Selected reg, indexed from 0 as the page start + /* 0x0C */ s32 dPadInputPrev; + /* 0x10 */ s32 inputRepeatTimer; + /* 0x14 */ s16 data[REG_GROUPS * REGS_PER_GROUP]; // Accessed through *REG macros, see regs.h +} RegEditor; // size = 0x15D4 + +extern RegEditor* gRegEditor; + #endif diff --git a/include/sfx.h b/include/sfx.h index d5545af8d6..a8ea68dee5 100644 --- a/include/sfx.h +++ b/include/sfx.h @@ -125,4 +125,27 @@ typedef struct { #define SFX_DIST_SCALING 10.0f #endif +void Audio_SetSfxBanksMute(u16 muteMask); +void Audio_QueueSeqCmdMute(u8 channelIndex); +void Audio_ClearBGMMute(u8 channelIndex); +void Audio_PlaySfxGeneral(u16 sfxId, Vec3f* pos, u8 token, f32* freqScale, f32* vol, s8* reverbAdd); +void Audio_ProcessSfxRequest(void); +void Audio_ChooseActiveSfx(u8 bankId); +void Audio_PlayActiveSfx(u8 bankId); +void Audio_StopSfxByBank(u8 bankId); +void func_800F8884(u8 bankId, Vec3f* pos); +void Audio_StopSfxByPosAndBank(u8 bankId, Vec3f* pos); +void Audio_StopSfxByPos(Vec3f* pos); +void Audio_StopSfxByPosAndId(Vec3f* pos, u16 sfxId); +void Audio_StopSfxByTokenAndId(u8 token, u16 sfxId); +void Audio_StopSfxById(u32 sfxId); +void Audio_ProcessSfxRequests(void); +void func_800F8F88(void); +u8 Audio_IsSfxPlaying(u32 sfxId); +void Audio_ResetSfx(void); + +extern Vec3f gSfxDefaultPos; +extern f32 gSfxDefaultFreqAndVolScale; +extern s8 gSfxDefaultReverb; + #endif diff --git a/include/sys_math.h b/include/sys_math.h new file mode 100644 index 0000000000..0da5df8902 --- /dev/null +++ b/include/sys_math.h @@ -0,0 +1,14 @@ +#ifndef SYS_MATH_H +#define SYS_MATH_H + +#include "ultra64.h" + +f32 Math_FactorialF(f32 n); +f32 Math_Factorial(s32 n); +f32 Math_PowF(f32 base, s32 exp); +f32 Math_SinF(f32 angle); +f32 Math_CosF(f32 angle); +s16 Math_Atan2S(f32 x, f32 y); +f32 Math_Atan2F(f32 x, f32 y); + +#endif diff --git a/include/sys_math3d.h b/include/sys_math3d.h new file mode 100644 index 0000000000..b01063a9f0 --- /dev/null +++ b/include/sys_math3d.h @@ -0,0 +1,73 @@ +#ifndef SYS_MATH3D_H +#define SYS_MATH3D_H + +#include "ultra64.h" +#include "z64math.h" + +s32 Math3D_PlaneVsLineSegClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, f32 planeBB, + f32 planeBC, f32 planeBDist, Vec3f* linePointA, Vec3f* linePointB, + Vec3f* closestPoint); +void Math3D_LineClosestToPoint(InfiniteLine* line, Vec3f* pos, Vec3f* closestPoint); +s32 Math3D_PlaneVsPlaneVsLineClosestPoint(f32 planeAA, f32 planeAB, f32 planeAC, f32 planeADist, f32 planeBA, + f32 planeBB, f32 planeBC, f32 planeBDist, Vec3f* point, Vec3f* closestPoint); +void Math3D_LineSplitRatio(Vec3f* v0, Vec3f* v1, f32 ratio, Vec3f* ret); +f32 Math3D_Cos(Vec3f* a, Vec3f* b); +s32 Math3D_CosOut(Vec3f* a, Vec3f* b, f32* dst); +void Math3D_Vec3fReflect(Vec3f* vec, Vec3f* normal, Vec3f* reflVec); +s32 Math3D_PointInSquare2D(f32 upperLeftX, f32 lowerRightX, f32 upperLeftY, f32 lowerRightY, f32 x, f32 y); +f32 Math3D_Dist1DSq(f32 a, f32 b); +f32 Math3D_Dist2DSq(f32 x0, f32 y0, f32 x1, f32 y1); +f32 Math3D_Vec3fMagnitudeSq(Vec3f* vec); +f32 Math3D_Vec3fMagnitude(Vec3f* vec); +f32 Math3D_Vec3fDistSq(Vec3f* a, Vec3f* b); +void Math3D_Vec3f_Cross(Vec3f* a, Vec3f* b, Vec3f* ret); +void Math3D_SurfaceNorm(Vec3f* va, Vec3f* vb, Vec3f* vc, Vec3f* normal); +f32 Math3D_Vec3f_DistXYZ(Vec3f* a, Vec3f* b); +s32 Math3D_PointRelativeToCubeFaces(Vec3f* point, Vec3f* min, Vec3f* max); +s32 Math3D_PointRelativeToCubeEdges(Vec3f* point, Vec3f* min, Vec3f* max); +s32 Math3D_PointRelativeToCubeVertices(Vec3f* point, Vec3f* min, Vec3f* max); +s32 Math3D_LineVsCube(Vec3f* min, Vec3f* max, Vec3f* a, Vec3f* b); +void Math3D_RotateXZPlane(Vec3f* pointOnPlane, s16 angle, f32* a, f32* c, f32* d); +void Math3D_DefPlane(Vec3f* va, Vec3f* vb, Vec3f* vc, f32* nx, f32* ny, f32* nz, f32* originDist); +f32 Math3D_UDistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p); +f32 Math3D_DistPlaneToPos(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* p); +s32 Math3D_TriChkPointParaYSlopedY(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 z, f32 x); +s32 Math3D_TriChkPointParaYIntersectDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, + f32 x, f32* yIntersect, f32 chkDist); +s32 Math3D_TriChkPointParaYIntersectInsideTri(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, + f32 z, f32 x, f32* yIntersect, f32 chkDist); +s32 Math3D_TriChkLineSegParaYIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 z, + f32 x, f32* yIntersect, f32 y0, f32 y1); +s32 Math3D_TriChkPointParaYDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 z, f32 x, f32 chkDist); +s32 Math3D_TriChkPointParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, + f32 z, f32* xIntersect); +s32 Math3D_TriChkLineSegParaXIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 y, + f32 z, f32* xIntersect, f32 x0, f32 x1); +s32 Math3D_TriChkPointParaXDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 y, f32 z, f32 chkDist); +s32 Math3D_TriChkPointParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, + f32 y, f32* zIntersect); +s32 Math3D_TriChkLineSegParaZIntersect(Vec3f* v0, Vec3f* v1, Vec3f* v2, f32 nx, f32 ny, f32 nz, f32 originDist, f32 x, + f32 y, f32* zIntersect, f32 z0, f32 z1); +s32 Math3D_TriChkLineSegParaZDist(Vec3f* v0, Vec3f* v1, Vec3f* v2, Plane* plane, f32 x, f32 y, f32 chkDist); +s32 Math3D_LineSegVsPlane(f32 nx, f32 ny, f32 nz, f32 originDist, Vec3f* linePointA, Vec3f* linePointB, + Vec3f* intersect, s32 fromFront); +void Math3D_TriNorm(TriNorm* tri, Vec3f* va, Vec3f* vb, Vec3f* vc); +s32 Math3D_PointDistSqToLine2D(f32 x0, f32 y0, f32 x1, f32 y1, f32 x2, f32 y2, f32* lineLenSq); +s32 Math3D_LineVsSph(Sphere16* sphere, Linef* line); +s32 Math3D_TriVsSphIntersect(Sphere16* sphere, TriNorm* tri, Vec3f* intersectPoint); +s32 Math3D_CylVsLineSeg(Cylinder16* cyl, Vec3f* linePointA, Vec3f* linePointB, Vec3f* intersectA, Vec3f* intersectB); +s32 Math3D_CylVsTri(Cylinder16* cyl, TriNorm* tri); +s32 Math3D_CylTriVsIntersect(Cylinder16* cyl, TriNorm* tri, Vec3f* intersect); +s32 Math3D_SphVsSph(Sphere16* sphereA, Sphere16* sphereB); +s32 Math3D_SphVsSphOverlap(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize); +s32 Math3D_SphVsSphOverlapCenterDist(Sphere16* sphereA, Sphere16* sphereB, f32* overlapSize, f32* centerDist); +s32 Math3D_SphVsCylOverlap(Sphere16* sph, Cylinder16* cyl, f32* overlapSize); +s32 Math3D_SphVsCylOverlapCenterDist(Sphere16* sph, Cylinder16* cyl, f32* overlapSize, f32* centerDist); +s32 Math3D_CylVsCylOverlap(Cylinder16* ca, Cylinder16* cb, f32* overlapSize); +s32 Math3D_CylVsCylOverlapCenterDist(Cylinder16* ca, Cylinder16* cb, f32* overlapSize, f32* centerDist); +s32 Math3D_TriVsTriIntersect(TriNorm* ta, TriNorm* tb, Vec3f* intersect); +s32 Math3D_XZInSphere(Sphere16* sphere, f32 x, f32 z); +s32 Math3D_XYInSphere(Sphere16* sphere, f32 x, f32 y); +s32 Math3D_YZInSphere(Sphere16* sphere, f32 y, f32 z); + +#endif diff --git a/include/ultra64/gu.h b/include/ultra64/gu.h index 429d12352e..7e2a50d725 100644 --- a/include/ultra64/gu.h +++ b/include/ultra64/gu.h @@ -21,6 +21,12 @@ typedef union { f32 f; } fu; +f32 sinf(f32 angle); +s16 sins(u16 angle); + +f32 cosf(f32 angle); +s16 coss(u16 angle); + extern f32 __libm_qnan_f; #endif diff --git a/include/variables.h b/include/variables.h index a67d99246b..0b3b260bf2 100644 --- a/include/variables.h +++ b/include/variables.h @@ -172,7 +172,6 @@ extern u8 gSequenceTable[]; extern u8 gSampleBankTable[]; extern SaveContext gSaveContext; -extern RegEditor* gRegEditor; extern u8 gUseCutsceneCam; extern u16 D_8015FCCC; diff --git a/include/z64.h b/include/z64.h index 2fcf7b889c..2a556d3f9f 100644 --- a/include/z64.h +++ b/include/z64.h @@ -44,6 +44,7 @@ #include "sfx.h" #include "color.h" #include "gfxprint.h" +#include "z_lib.h" #include "ichain.h" #include "regs.h" #include "irqmgr.h" @@ -58,6 +59,10 @@ #include "gfx.h" #include "jpeg.h" #include "prerender.h" +#include "rand.h" +#include "sys_math.h" +#include "sys_math3d.h" +#include "fp_math.h" #define SCREEN_WIDTH 320 #define SCREEN_HEIGHT 240 @@ -99,15 +104,6 @@ // NOTE: Once we start supporting other builds, this can be changed with an ifdef #define REGION_NATIVE REGION_EU -typedef struct { - /* 0x00 */ s32 regPage; // 0: no page selected (reg editor is not active); 1: first page; `REG_PAGES`: last page - /* 0x04 */ s32 regGroup; // Indexed from 0 to `REG_GROUPS`-1. Each group has its own character to identify it. - /* 0x08 */ s32 regCur; // Selected reg, indexed from 0 as the page start - /* 0x0C */ s32 dPadInputPrev; - /* 0x10 */ s32 inputRepeatTimer; - /* 0x14 */ s16 data[REG_GROUPS * REGS_PER_GROUP]; // Accessed through *REG macros, see regs.h -} RegEditor; // size = 0x15D4 - typedef struct { /* 0x00 */ u8 seqId; /* 0x01 */ u8 natureAmbienceId; @@ -225,8 +221,8 @@ typedef struct { } GameOverContext; // size = 0x2 typedef enum { - /* 0 */ LENS_MODE_HIDE_ACTORS, // lens actors are visible by default, and hidden by using lens (for example, fake walls) - /* 1 */ LENS_MODE_SHOW_ACTORS // lens actors are invisible by default, and shown by using lens (for example, invisible enemies) + /* 0 */ LENS_MODE_SHOW_ACTORS, // lens actors are invisible by default, and shown by using lens (for example, invisible enemies) + /* 1 */ LENS_MODE_HIDE_ACTORS // lens actors are visible by default, and hidden by using lens (for example, fake walls) } LensMode; typedef enum { @@ -396,7 +392,7 @@ typedef struct PlayState { /* 0x10760 */ PauseContext pauseCtx; /* 0x10A20 */ GameOverContext gameOverCtx; /* 0x10A24 */ EnvironmentContext envCtx; - /* 0x10B20 */ AnimationContext animationCtx; + /* 0x10B20 */ AnimTaskQueue animTaskQueue; /* 0x117A4 */ ObjectContext objectCtx; /* 0x11CBC */ RoomContext roomCtx; /* 0x11D34 */ TransitionActorContext transiActorCtx; diff --git a/include/z64animation.h b/include/z64animation.h old mode 100755 new mode 100644 index ca87a69d15..a0b4982b77 --- a/include/z64animation.h +++ b/include/z64animation.h @@ -91,7 +91,7 @@ typedef enum { #define ANIM_FLAG_0 (1 << 0) // (no effect outside of player) Related to scaling an animation from/to child/adult #define ANIM_FLAG_UPDATE_Y (1 << 1) #define ANIM_FLAG_PLAYER_2 (1 << 2) // (player-only) Related to scaling an animation from/to child/adult -#define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) // (player-only) Call AnimationContext_SetMoveActor +#define ANIM_FLAG_PLAYER_SETMOVE (1 << 3) // (player-only) Call AnimTaskQueue_AddActorMove #define ANIM_FLAG_NO_MOVE (1 << 4) #define ANIM_FLAG_PLAYER_7 (1 << 7) // (player-only) @@ -239,95 +239,95 @@ s16 Animation_GetLength(void* animation); s16 Animation_GetLastFrame(void* animation); /* - * Animation requests + * Animation Task Queue */ typedef enum { - /* 0 */ ANIMENTRY_LOADFRAME, - /* 1 */ ANIMENTRY_COPYALL, - /* 2 */ ANIMENTRY_INTERP, - /* 3 */ ANIMENTRY_COPYTRUE, - /* 4 */ ANIMENTRY_COPYFALSE, - /* 5 */ ANIMENTRY_MOVEACTOR -} AnimationType; + /* 0 */ ANIMTASK_LOAD_PLAYER_FRAME, + /* 1 */ ANIMTASK_COPY, + /* 2 */ ANIMTASK_INTERP, + /* 3 */ ANIMTASK_COPY_USING_MAP, + /* 4 */ ANIMTASK_COPY_USING_MAP_INVERTED, + /* 5 */ ANIMTASK_ACTOR_MOVE +} AnimTaskType; typedef struct { - /* 0x000 */ DmaRequest req; - /* 0x020 */ OSMesgQueue msgQueue; - /* 0x038 */ OSMesg msg; -} AnimEntryLoadFrame; // size = 0x3C + /* 0x00 */ DmaRequest req; + /* 0x20 */ OSMesgQueue msgQueue; + /* 0x38 */ OSMesg msg; +} AnimTaskLoadPlayerFrame; // size = 0x3C typedef struct { - /* 0x000 */ u8 queueFlag; - /* 0x001 */ u8 vecCount; - /* 0x004 */ Vec3s* dst; - /* 0x008 */ Vec3s* src; -} AnimEntryCopyAll; // size = 0xC + /* 0x00 */ u8 group; + /* 0x01 */ u8 vecCount; + /* 0x04 */ Vec3s* dest; + /* 0x08 */ Vec3s* src; +} AnimTaskCopy; // size = 0xC typedef struct { - /* 0x000 */ u8 queueFlag; - /* 0x001 */ u8 vecCount; - /* 0x004 */ Vec3s* base; - /* 0x008 */ Vec3s* mod; - /* 0x00C */ f32 weight; -} AnimEntryInterp; // size = 0x10 + /* 0x00 */ u8 group; + /* 0x01 */ u8 vecCount; + /* 0x04 */ Vec3s* base; + /* 0x08 */ Vec3s* mod; + /* 0x0C */ f32 weight; +} AnimTaskInterp; // size = 0x10 typedef struct { - /* 0x000 */ u8 queueFlag; - /* 0x001 */ u8 vecCount; - /* 0x004 */ Vec3s* dst; - /* 0x008 */ Vec3s* src; - /* 0x00C */ u8* copyFlag; -} AnimEntryCopyTrue; // size = 0x10 + /* 0x00 */ u8 group; + /* 0x01 */ u8 vecCount; + /* 0x04 */ Vec3s* dest; + /* 0x08 */ Vec3s* src; + /* 0x0C */ u8* limbCopyMap; +} AnimTaskCopyUsingMap; // size = 0x10 typedef struct { - /* 0x000 */ u8 queueFlag; - /* 0x001 */ u8 vecCount; - /* 0x004 */ Vec3s* dst; - /* 0x008 */ Vec3s* src; - /* 0x00C */ u8* copyFlag; -} AnimEntryCopyFalse; // size = 0x10 + /* 0x00 */ u8 group; + /* 0x01 */ u8 vecCount; + /* 0x04 */ Vec3s* dest; + /* 0x08 */ Vec3s* src; + /* 0x0C */ u8* limbCopyMap; +} AnimTaskCopyUsingMapInverted; // size = 0x10 typedef struct { - /* 0x000 */ struct Actor* actor; - /* 0x004 */ struct SkelAnime* skelAnime; - /* 0x008 */ f32 diffScaleY; -} AnimEntryMoveActor; // size = 0xC + /* 0x00 */ struct Actor* actor; + /* 0x04 */ struct SkelAnime* skelAnime; + /* 0x08 */ f32 diffScaleY; +} AnimTaskActorMove; // size = 0xC typedef union { - AnimEntryLoadFrame load; - AnimEntryCopyAll copy; - AnimEntryInterp interp; - AnimEntryCopyTrue copy1; - AnimEntryCopyFalse copy0; - AnimEntryMoveActor move; -} AnimationEntryData; // size = 0x3C + AnimTaskLoadPlayerFrame loadPlayerFrame; + AnimTaskCopy copy; + AnimTaskInterp interp; + AnimTaskCopyUsingMap copyUsingMap; + AnimTaskCopyUsingMapInverted copyUsingMapInverted; + AnimTaskActorMove actorMove; +} AnimTaskData; // size = 0x3C typedef struct { /* 0x00 */ u8 type; - /* 0x04 */ AnimationEntryData data; -} AnimationEntry; // size = 0x40 + /* 0x04 */ AnimTaskData data; +} AnimTask; // size = 0x40 -#define ANIMATION_ENTRY_MAX 50 +#define ANIM_TASK_QUEUE_MAX 50 -typedef struct AnimationContext { - s16 animationCount; - AnimationEntry entries[ANIMATION_ENTRY_MAX]; -} AnimationContext; // size = 0xC84 +typedef struct AnimTaskQueue { + s16 count; + AnimTask tasks[ANIM_TASK_QUEUE_MAX]; +} AnimTaskQueue; // size = 0xC84 -void AnimationContext_SetLoadFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, - Vec3s* frameTable); -void AnimationContext_SetCopyAll(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src); -void AnimationContext_SetCopyTrue(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); -void AnimationContext_SetCopyFalse(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); -void AnimationContext_SetInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight); -void AnimationContext_SetMoveActor(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY); +void AnimTaskQueue_AddLoadPlayerFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, + Vec3s* frameTable); +void AnimTaskQueue_AddCopy(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src); +void AnimTaskQueue_AddInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight); +void AnimTaskQueue_AddCopyUsingMap(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap); +void AnimTaskQueue_AddCopyUsingMapInverted(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap); +void AnimTaskQueue_AddActorMove(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY); -void AnimationContext_SetNextQueue(struct PlayState* play); -void AnimationContext_DisableQueue(struct PlayState* play); +void AnimTaskQueue_SetNextGroup(struct PlayState* play); +void AnimTaskQueue_DisableTransformTasksForGroup(struct PlayState* play); -void AnimationContext_Reset(AnimationContext* animationCtx); -void AnimationContext_Update(struct PlayState* play, AnimationContext* animationCtx); +void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue); +void AnimTaskQueue_Update(struct PlayState* play, AnimTaskQueue* animTaskQueue); /* * Link animations diff --git a/include/z64camera.h b/include/z64camera.h index 81584c1b68..e3696b4fbb 100644 --- a/include/z64camera.h +++ b/include/z64camera.h @@ -6,10 +6,6 @@ #include "z64math.h" #include "z64save.h" -// these two angle conversion macros are slightly inaccurate -#define CAM_DEG_TO_BINANG(degrees) (s16)TRUNCF_BINANG((degrees) * 182.04167f + .5f) -#define CAM_BINANG_TO_DEG(binang) ((f32)(binang) * (360.0001525f / 65535.0f)) - #define CAM_STAT_CUT 0 #define CAM_STAT_WAIT 1 #define CAM_STAT_UNK3 3 diff --git a/include/z64math.h b/include/z64math.h index 6661a8dc22..16ba1a2039 100644 --- a/include/z64math.h +++ b/include/z64math.h @@ -2,7 +2,9 @@ #define Z64MATH_H #include "ultra64.h" +#include "math.h" +#define SQ(x) ((x)*(x)) #define VEC_SET(V,X,Y,Z) (V).x=(X);(V).y=(Y);(V).z=(Z) typedef struct { @@ -116,6 +118,11 @@ typedef VecSphGeo VecGeo; #define BINANG_TO_RAD_ALT(binang) (((f32)(binang) / (f32)0x8000) * M_PI) #define BINANG_TO_RAD_ALT2(binang) (((f32)(binang) * M_PI) / 0x8000) +// Angle conversion macros (Camera) +// these two angle conversion macros are slightly inaccurate +#define CAM_DEG_TO_BINANG(degrees) (s16)TRUNCF_BINANG((degrees) * 182.04167f + .5f) +#define CAM_BINANG_TO_DEG(binang) ((f32)(binang) * (360.0001525f / 65535.0f)) + // Vector macros #define SQXZ(vec) ((vec).x * (vec).x + (vec).z * (vec).z) #define DOTXZ(vec1, vec2) ((vec1).x * (vec2).x + (vec1).z * (vec2).z) diff --git a/include/z64pause.h b/include/z64pause.h index 1cc810c318..9e19936da0 100644 --- a/include/z64pause.h +++ b/include/z64pause.h @@ -20,6 +20,33 @@ typedef enum { /* 0x04 */ PAUSE_WORLD_MAP } PauseMenuPage; +// The XZ coordinates in which direction each pause page is at +// e.g. the item page is in the -z direction +/* + * < item > + * + * ^ ^ + * x + * equip o--> map + * | + * v z v v + * + * < quest > + */ +#define PAUSE_ITEM_X (0) +#define PAUSE_ITEM_Z (-1) +#define PAUSE_MAP_X (1) +#define PAUSE_MAP_Z (0) +#define PAUSE_QUEST_X (0) +#define PAUSE_QUEST_Z (1) +#define PAUSE_EQUIP_X (-1) +#define PAUSE_EQUIP_Z (0) + +// The pause camera looks at x=0,z=0, +// with the eye being PAUSE_EYE_DIST away in the direction opposite to the active page, +// which results in the camera being pointed (through x=0,z=0) towards the active page. +#define PAUSE_EYE_DIST (64.0f) + #define PAUSE_EQUIP_PLAYER_WIDTH 64 #define PAUSE_EQUIP_PLAYER_HEIGHT 112 @@ -58,7 +85,7 @@ typedef enum { // Sub-states of PAUSE_STATE_MAIN typedef enum { /* 0 */ PAUSE_MAIN_STATE_IDLE, - /* 1 */ PAUSE_MAIN_STATE_1, + /* 1 */ PAUSE_MAIN_STATE_SWITCHING_PAGE, /* 2 */ PAUSE_MAIN_STATE_2, /* 3 */ PAUSE_MAIN_STATE_3, /* 4 */ PAUSE_MAIN_STATE_4, @@ -98,9 +125,9 @@ typedef struct { /* 0x01D6 */ u16 debugState; /* 0x01D8 */ Vec3f eye; /* 0x01E4 */ u16 mainState; - /* 0x01E6 */ u16 mode; + /* 0x01E6 */ u16 nextPageMode; // During a page switch, indicates the page before switching and the direction to scroll in. Value is `(2 * prev pageIndex) + (scroll left ? 1 : 0)` /* 0x01E8 */ u16 pageIndex; // "kscp_pos" - /* 0x01EA */ u16 unk_1EA; + /* 0x01EA */ u16 pageSwitchTimer; /* 0x01EC */ u16 unk_1EC; /* 0x01F0 */ f32 unk_1F0; /* 0x01F4 */ f32 unk_1F4; diff --git a/include/z_lib.h b/include/z_lib.h new file mode 100644 index 0000000000..34581da982 --- /dev/null +++ b/include/z_lib.h @@ -0,0 +1,44 @@ +#ifndef Z_LIB_H +#define Z_LIB_H + +#include "libc/stddef.h" +#include "padmgr.h" +#include "z64math.h" +#include "color.h" + +void Lib_MemSet(u8* dest, size_t len, u8 val); +f32 Math_CosS(s16 angle); +f32 Math_SinS(s16 angle); +s32 Math_ScaledStepToS(s16* pValue, s16 target, s16 step); +s32 Math_StepToS(s16* pValue, s16 target, s16 step); +s32 Math_StepToF(f32* pValue, f32 target, f32 step); +s32 Math_StepUntilAngleS(s16* pValue, s16 limit, s16 step); +s32 Math_StepUntilS(s16* pValue, s16 limit, s16 step); +s32 Math_StepToAngleS(s16* pValue, s16 target, s16 step); +s32 Math_StepUntilF(f32* pValue, f32 limit, f32 step); +s32 Math_AsymStepToF(f32* pValue, f32 target, f32 incrStep, f32 decrStep); +void Lib_GetControlStickData(f32* outMagnitude, s16* outAngle, Input* input); +s16 Rand_S16Offset(s16 base, s16 range); +void Math_Vec3f_Copy(Vec3f* dest, Vec3f* src); +void Math_Vec3s_ToVec3f(Vec3f* dest, Vec3s* src); +void Math_Vec3f_Sum(Vec3f* a, Vec3f* b, Vec3f* dest); +void Math_Vec3f_Diff(Vec3f* a, Vec3f* b, Vec3f* dest); +void Math_Vec3s_DiffToVec3f(Vec3f* dest, Vec3s* a, Vec3s* b); +void Math_Vec3f_Scale(Vec3f* vec, f32 scaleF); +f32 Math_Vec3f_DistXYZ(Vec3f* a, Vec3f* b); +f32 Math_Vec3f_DistXYZAndStoreDiff(Vec3f* a, Vec3f* b, Vec3f* dest); +f32 Math_Vec3f_DistXZ(Vec3f* a, Vec3f* b); +s16 Math_Vec3f_Yaw(Vec3f* origin, Vec3f* point); +s16 Math_Vec3f_Pitch(Vec3f* a, Vec3f* b); +f32 Math_SmoothStepToF(f32* pValue, f32 target, f32 fraction, f32 step, f32 minStep); +void Math_ApproachF(f32* pValue, f32 target, f32 fraction, f32 step); +void Math_ApproachZeroF(f32* pValue, f32 fraction, f32 step); +f32 Math_SmoothStepToDegF(f32* pValue, f32 target, f32 fraction, f32 step, f32 minStep); +s16 Math_SmoothStepToS(s16* pValue, s16 target, s16 scale, s16 step, s16 minStep); +void Math_ApproachS(s16* pValue, s16 target, s16 scale, s16 step); +void Color_RGBA8_Copy(Color_RGBA8* dst, Color_RGBA8* src); +void Sfx_PlaySfxCentered(u16 sfxId); +void Sfx_PlaySfxCentered2(u16 sfxId); +void Sfx_PlaySfxAtPos(Vec3f* projectedPos, u16 sfxId); + +#endif diff --git a/spec b/spec index a0f411d40e..9cc1b8d59b 100644 --- a/spec +++ b/spec @@ -437,6 +437,9 @@ beginseg include "$(BUILD_DIR)/src/code/sys_cfb.o" include "$(BUILD_DIR)/src/code/sys_math.o" include "$(BUILD_DIR)/src/code/sys_math3d.o" +#if OOT_DEBUG + include "$(BUILD_DIR)/src/code/sys_math3d_draw.o" +#endif include "$(BUILD_DIR)/src/code/sys_math_atan.o" include "$(BUILD_DIR)/src/code/sys_matrix.o" include "$(BUILD_DIR)/src/code/sys_ucode.o" @@ -484,7 +487,7 @@ beginseg include "$(BUILD_DIR)/src/code/code_800FC620.o" include "$(BUILD_DIR)/src/code/padutils.o" include "$(BUILD_DIR)/src/code/padsetup.o" - include "$(BUILD_DIR)/src/code/code_800FCE80.o" + include "$(BUILD_DIR)/src/code/fp_math.o" include "$(BUILD_DIR)/src/code/fp.o" include "$(BUILD_DIR)/src/code/system_malloc.o" include "$(BUILD_DIR)/src/code/rand.o" @@ -597,8 +600,12 @@ beginseg include "$(BUILD_DIR)/src/code/fmodf.o" include "$(BUILD_DIR)/src/code/__osMemset.o" include "$(BUILD_DIR)/src/code/__osMemmove.o" - include_data_with_rodata "$(BUILD_DIR)/src/code/z_message_PAL.o" - include "$(BUILD_DIR)/src/code/z_game_over.o" + // For some reason, the data sections of these files are placed here near the + // rodata sections of the other files + include_data_only_within_rodata "$(BUILD_DIR)/src/code/z_message_PAL.o" + include_data_only_within_rodata "$(BUILD_DIR)/src/code/z_game_over.o" + include_no_data "$(BUILD_DIR)/src/code/z_message_PAL.o" + include_no_data "$(BUILD_DIR)/src/code/z_game_over.o" include "$(BUILD_DIR)/src/code/z_construct.o" include "$(BUILD_DIR)/data/audio_tables.rodata.o" include "$(BUILD_DIR)/data/rsp.text.o" diff --git a/src/code/code_80069420.c b/src/code/code_80069420.c index 6dd0a94f42..9a190edcf3 100644 --- a/src/code/code_80069420.c +++ b/src/code/code_80069420.c @@ -1,4 +1,4 @@ -#include "global.h" +#include "ultra64.h" /** * memcpy: copies `len` bytes from memory starting at `src` to memory starting at `dest`. Expects the memory diff --git a/src/code/fault.c b/src/code/fault.c index 662c1a9f1a..7d8e62fef1 100644 --- a/src/code/fault.c +++ b/src/code/fault.c @@ -48,9 +48,9 @@ // just above (the exact upper bound depends on the block numbers assigned to // extern variables declared in headers). #if OOT_DEBUG -#pragma increment_block_number 20 +#pragma increment_block_number 0 #else -#pragma increment_block_number 25 +#pragma increment_block_number 20 #endif void FaultDrawer_Init(void); diff --git a/src/code/fmodf.c b/src/code/fmodf.c index e1e3862231..4ebec43bdc 100644 --- a/src/code/fmodf.c +++ b/src/code/fmodf.c @@ -1,4 +1,4 @@ -#include "global.h" +#include "ultra64.h" /** * Computes one `x` modulo `y` for floats. diff --git a/src/code/code_800FCE80.c b/src/code/fp_math.c similarity index 98% rename from src/code/code_800FCE80.c rename to src/code/fp_math.c index 8ac46833d9..c429b83e23 100644 --- a/src/code/code_800FCE80.c +++ b/src/code/fp_math.c @@ -1,4 +1,5 @@ -#include "global.h" +#include "z64math.h" +#include "macros.h" s32 gUseAtanContFrac; diff --git a/src/code/rand.c b/src/code/rand.c index 4a0c5dc4a3..baf3965421 100644 --- a/src/code/rand.c +++ b/src/code/rand.c @@ -41,7 +41,7 @@ * * @note Original name: qrand.c */ -#include "ultra64.h" +#include "rand.h" #define RAND_MULTIPLIER 1664525 #define RAND_INCREMENT 1013904223 diff --git a/src/code/sys_math.c b/src/code/sys_math.c index f19719bb95..6a7344baad 100644 --- a/src/code/sys_math.c +++ b/src/code/sys_math.c @@ -1,4 +1,4 @@ -#include "global.h" +#include "sys_math.h" f32 sFactorialTbl[] = { 1.0f, 1.0f, 2.0f, 6.0f, 24.0f, 120.0f, 720.0f, 5040.0f, 40320.0f, 362880.0f, 3628800.0f, 39916800.0f, 479001600.0f }; diff --git a/src/code/sys_math3d.c b/src/code/sys_math3d.c index 6525f825da..f0bfb60bc6 100644 --- a/src/code/sys_math3d.c +++ b/src/code/sys_math3d.c @@ -1,9 +1,13 @@ -#include "global.h" +#include "ultra64.h" +#include "z_lib.h" +#include "z64math.h" #include "terminal.h" +#include "macros.h" +#include "sys_math3d.h" // For retail BSS ordering, the block number of cbf in Math3D_CylVsCylOverlapCenterDist // must be 0. -#pragma increment_block_number 187 +#pragma increment_block_number 114 s32 Math3D_LineVsLineClosestTwoPoints(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB, Vec3f* lineAClosestToB, Vec3f* lineBClosestToA); @@ -2147,11 +2151,3 @@ s32 Math3D_YZInSphere(Sphere16* sphere, f32 y, f32 z) { } return false; } - -#if OOT_DEBUG -void Math3D_DrawSphere(PlayState* play, Sphere16* sph) { -} - -void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl) { -} -#endif diff --git a/src/code/sys_math3d_draw.c b/src/code/sys_math3d_draw.c new file mode 100644 index 0000000000..76651c825e --- /dev/null +++ b/src/code/sys_math3d_draw.c @@ -0,0 +1,7 @@ +#include "z64.h" + +void Math3D_DrawSphere(PlayState* play, Sphere16* sph) { +} + +void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl) { +} diff --git a/src/code/sys_math_atan.c b/src/code/sys_math_atan.c index efbe8a2055..0647745b06 100644 --- a/src/code/sys_math_atan.c +++ b/src/code/sys_math_atan.c @@ -1,4 +1,5 @@ -#include "global.h" +#include "z64math.h" +#include "macros.h" static u16 sAtan2Tbl[] = { 0x0000, 0x000A, 0x0014, 0x001F, 0x0029, 0x0033, 0x003D, 0x0047, 0x0051, 0x005C, 0x0066, 0x0070, 0x007A, 0x0084, diff --git a/src/code/z_actor.c b/src/code/z_actor.c index 214fa7138d..6afae4f1fd 100644 --- a/src/code/z_actor.c +++ b/src/code/z_actor.c @@ -2452,7 +2452,7 @@ void Actor_DrawLensActors(PlayState* play, s32 numInvisibleActors, Actor** invis gDPPipeSync(POLY_XLU_DISP++); - if (play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) { + if (play->roomCtx.curRoom.lensMode == LENS_MODE_SHOW_ACTORS) { // Update both the color frame buffer and the z-buffer gDPSetOtherMode(POLY_XLU_DISP++, G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE | @@ -2501,7 +2501,7 @@ void Actor_DrawLensActors(PlayState* play, s32 numInvisibleActors, Actor** invis // "Magic lens invisible Actor display END" gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないActor表示 END", numInvisibleActors); - if (play->roomCtx.curRoom.lensMode != LENS_MODE_HIDE_ACTORS) { + if (play->roomCtx.curRoom.lensMode != LENS_MODE_SHOW_ACTORS) { // Draw the lens overlay to the color frame buffer gDPNoOpString(POLY_OPA_DISP++, "青い眼鏡(外側)", 0); // "Blue spectacles (exterior)" @@ -2596,7 +2596,7 @@ void func_800315AC(PlayState* play, ActorContext* actorCtx) { if (!OOT_DEBUG || (HREG(64) != 1) || ((HREG(65) != -1) && (HREG(65) != HREG(66))) || (HREG(71) == 0)) { if ((actor->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_5 | ACTOR_FLAG_6))) { if ((actor->flags & ACTOR_FLAG_REACT_TO_LENS) && - ((play->roomCtx.curRoom.lensMode == LENS_MODE_HIDE_ACTORS) || play->actorCtx.lensActive || + ((play->roomCtx.curRoom.lensMode == LENS_MODE_SHOW_ACTORS) || play->actorCtx.lensActive || (actor->room != play->roomCtx.curRoom.num))) { ASSERT(invisibleActorCounter < INVISIBLE_ACTOR_MAX, "invisible_actor_counter < INVISIBLE_ACTOR_MAX", "../z_actor.c", 6464); diff --git a/src/code/z_collision_check.c b/src/code/z_collision_check.c index 118a445d7b..bebcac08d7 100644 --- a/src/code/z_collision_check.c +++ b/src/code/z_collision_check.c @@ -2360,9 +2360,6 @@ void CollisionCheck_ATTrisVsACTris(PlayState* play, CollisionCheckContext* colCh #if OOT_DEBUG static s8 sBssDummy7; -static s8 sBssDummy8; -static s8 sBssDummy9; -static s8 sBssDummy10; #endif void CollisionCheck_ATTrisVsACQuad(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol, @@ -3329,12 +3326,10 @@ void Collider_SetTrisDim(PlayState* play, ColliderTris* tris, s32 elemIndex, Col } #if OOT_DEBUG -// Due to an unknown reason, bss ordering changed between the 2 static Vec3f variables in the function below. -// In order to reproduce this behavior, we need a specific number of bss variables in the file before that point. -// For this, we introduce a certain amount of dummy variables throughout the file, which we fit inside padding added -// by the compiler between structs like TriNorm and/or Vec3f, so they don't take space in bss. -static s8 sBssDummy11; -static s8 sBssDummy12; +// The two static Vec3f variables in the function below cross a block index rollover, causing a bss order swap. +//! In order to replicate this behavior, we declare a certain amount of sBssDummy variables throughout the file, which +//! we fit inside padding added by the compiler between structs like TriNorm and/or Vec3f, so they don't take space in +//! bss. #endif /** diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c index 796ce358d2..b282fc9e74 100644 --- a/src/code/z_game_over.c +++ b/src/code/z_game_over.c @@ -13,8 +13,7 @@ void GameOver_FadeInLights(PlayState* play) { } } -// This variable cannot be moved into this file as all of z_message_PAL rodata is in the way -extern s16 gGameOverTimer; +s16 sGameOverTimer = 0; void GameOver_Update(PlayState* play) { GameOverContext* gameOverCtx = &play->gameOverCtx; @@ -74,7 +73,7 @@ void GameOver_Update(PlayState* play) { gSaveContext.hudVisibilityModeTimer = 0; // false, HUD_VISIBILITY_NO_CHANGE Environment_InitGameOverLights(play); - gGameOverTimer = 20; + sGameOverTimer = 20; if (1) {} rumbleStrength = R_GAME_OVER_RUMBLE_STRENGTH; @@ -92,9 +91,9 @@ void GameOver_Update(PlayState* play) { break; case GAMEOVER_DEATH_DELAY_MENU: - gGameOverTimer--; + sGameOverTimer--; - if (gGameOverTimer == 0) { + if (sGameOverTimer == 0) { play->pauseCtx.state = PAUSE_STATE_8; gameOverCtx->state++; Rumble_Reset(); @@ -103,13 +102,13 @@ void GameOver_Update(PlayState* play) { case GAMEOVER_REVIVE_START: gameOverCtx->state++; - gGameOverTimer = 0; + sGameOverTimer = 0; Environment_InitGameOverLights(play); Letterbox_SetSizeTarget(32); return; case GAMEOVER_REVIVE_RUMBLE: - gGameOverTimer = 50; + sGameOverTimer = 50; gameOverCtx->state++; if (1) {} @@ -123,28 +122,28 @@ void GameOver_Update(PlayState* play) { break; case GAMEOVER_REVIVE_WAIT_GROUND: - gGameOverTimer--; + sGameOverTimer--; - if (gGameOverTimer == 0) { - gGameOverTimer = 64; + if (sGameOverTimer == 0) { + sGameOverTimer = 64; gameOverCtx->state++; } break; case GAMEOVER_REVIVE_WAIT_FAIRY: - gGameOverTimer--; + sGameOverTimer--; - if (gGameOverTimer == 0) { - gGameOverTimer = 50; + if (sGameOverTimer == 0) { + sGameOverTimer = 50; gameOverCtx->state++; } break; case GAMEOVER_REVIVE_FADE_OUT: Environment_FadeOutGameOverLights(play); - gGameOverTimer--; + sGameOverTimer--; - if (gGameOverTimer == 0) { + if (sGameOverTimer == 0) { gameOverCtx->state = GAMEOVER_INACTIVE; } break; diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c index 871adabf13..36a01c1239 100644 --- a/src/code/z_kaleido_setup.c +++ b/src/code/z_kaleido_setup.c @@ -1,12 +1,58 @@ #include "global.h" -s16 sKaleidoSetupKscpPos0[] = { PAUSE_QUEST, PAUSE_EQUIP, PAUSE_ITEM, PAUSE_MAP }; -f32 sKaleidoSetupEyeX0[] = { 0.0f, 64.0f, 0.0f, -64.0f }; -f32 sKaleidoSetupEyeZ0[] = { -64.0f, 0.0f, 64.0f, 0.0f }; +/* + * The following three arrays are effectively unused. + * They are partly equivalent to the `sKaleidoSetupRightPage*` arrays below, + * but make each page correspond to the opposite page instead of the page to the right. + */ -s16 sKaleidoSetupKscpPos1[] = { PAUSE_MAP, PAUSE_QUEST, PAUSE_EQUIP, PAUSE_ITEM }; -f32 sKaleidoSetupEyeX1[] = { -64.0f, 0.0f, 64.0f, 0.0f }; -f32 sKaleidoSetupEyeZ1[] = { 0.0f, -64.0f, 0.0f, 64.0f }; +s16 sKaleidoSetupUnusedPageIndex[] = { + PAUSE_QUEST, // PAUSE_ITEM + PAUSE_EQUIP, // PAUSE_MAP + PAUSE_ITEM, // PAUSE_QUEST + PAUSE_MAP, // PAUSE_EQUIP +}; + +f32 sKaleidoSetupUnusedEyeX[] = { + PAUSE_EYE_DIST * -PAUSE_QUEST_X, // PAUSE_ITEM + PAUSE_EYE_DIST * -PAUSE_EQUIP_X, // PAUSE_MAP + PAUSE_EYE_DIST * -PAUSE_ITEM_X, // PAUSE_QUEST + PAUSE_EYE_DIST * -PAUSE_MAP_X, // PAUSE_EQUIP +}; + +f32 sKaleidoSetupUnusedEyeZ[] = { + PAUSE_EYE_DIST * -PAUSE_QUEST_Z, // PAUSE_ITEM + PAUSE_EYE_DIST * -PAUSE_EQUIP_Z, // PAUSE_MAP + PAUSE_EYE_DIST * -PAUSE_ITEM_Z, // PAUSE_QUEST + PAUSE_EYE_DIST * -PAUSE_MAP_Z, // PAUSE_EQUIP +}; + +/* + * The following three arrays are used when opening the pause menu to set up a page switch such that scrolling left + * brings to the initial page. + * For example to open the menu on page PAUSE_ITEM, the menu would open on PAUSE_MAP and scroll left to PAUSE_ITEM. + */ + +s16 sKaleidoSetupRightPageIndex[] = { + PAUSE_MAP, // PAUSE_ITEM + PAUSE_QUEST, // PAUSE_MAP + PAUSE_EQUIP, // PAUSE_QUEST + PAUSE_ITEM, // PAUSE_EQUIP +}; + +f32 sKaleidoSetupRightPageEyeX[] = { + PAUSE_EYE_DIST * -PAUSE_MAP_X, // PAUSE_ITEM + PAUSE_EYE_DIST * -PAUSE_QUEST_X, // PAUSE_MAP + PAUSE_EYE_DIST * -PAUSE_EQUIP_X, // PAUSE_QUEST + PAUSE_EYE_DIST * -PAUSE_ITEM_X, // PAUSE_EQUIP +}; + +f32 sKaleidoSetupRightPageEyeZ[] = { + PAUSE_EYE_DIST * -PAUSE_MAP_Z, // PAUSE_ITEM + PAUSE_EYE_DIST * -PAUSE_QUEST_Z, // PAUSE_MAP + PAUSE_EYE_DIST * -PAUSE_EQUIP_Z, // PAUSE_QUEST + PAUSE_EYE_DIST * -PAUSE_ITEM_Z, // PAUSE_EQUIP +}; void KaleidoSetup_Update(PlayState* play) { PauseContext* pauseCtx = &play->pauseCtx; @@ -30,24 +76,33 @@ void KaleidoSetup_Update(PlayState* play) { WREG(16) = -175; WREG(17) = 155; - pauseCtx->unk_1EA = 0; - pauseCtx->mainState = PAUSE_MAIN_STATE_1; + pauseCtx->pageSwitchTimer = 0; - if (ZREG(48) == 0) { - pauseCtx->eye.x = sKaleidoSetupEyeX0[pauseCtx->pageIndex]; - pauseCtx->eye.z = sKaleidoSetupEyeZ0[pauseCtx->pageIndex]; - pauseCtx->pageIndex = sKaleidoSetupKscpPos0[pauseCtx->pageIndex]; + // Setting mainState here is irrelevant, mainState is only used under PAUSE_STATE_MAIN, + // which isn't involved in the initial pause menu opening page scrolling animation. + // mainState is also overwritten later before being used. + pauseCtx->mainState = PAUSE_MAIN_STATE_SWITCHING_PAGE; + + //! @bug REG collision + if (R_START_LABEL_DD(0) == 0) { + // Never reached, unused, and the data would be wrong anyway + // (scrolling left from this would not bring to the initial page) + pauseCtx->eye.x = sKaleidoSetupUnusedEyeX[pauseCtx->pageIndex]; + pauseCtx->eye.z = sKaleidoSetupUnusedEyeZ[pauseCtx->pageIndex]; + pauseCtx->pageIndex = sKaleidoSetupUnusedPageIndex[pauseCtx->pageIndex]; } else { - pauseCtx->eye.x = sKaleidoSetupEyeX1[pauseCtx->pageIndex]; - pauseCtx->eye.z = sKaleidoSetupEyeZ1[pauseCtx->pageIndex]; - pauseCtx->pageIndex = sKaleidoSetupKscpPos1[pauseCtx->pageIndex]; + // Set eye position and pageIndex such that scrolling left brings to the desired page + pauseCtx->eye.x = sKaleidoSetupRightPageEyeX[pauseCtx->pageIndex]; + pauseCtx->eye.z = sKaleidoSetupRightPageEyeZ[pauseCtx->pageIndex]; + pauseCtx->pageIndex = sKaleidoSetupRightPageIndex[pauseCtx->pageIndex]; } - pauseCtx->mode = (u16)(pauseCtx->pageIndex * 2) + 1; + // Set next page mode to scroll left + pauseCtx->nextPageMode = (u16)(pauseCtx->pageIndex * 2) + 1; pauseCtx->state = PAUSE_STATE_WAIT_LETTERBOX; - PRINTF("Mode=%d eye.x=%f, eye.z=%f kscp_pos=%d\n", pauseCtx->mode, pauseCtx->eye.x, pauseCtx->eye.z, - pauseCtx->pageIndex); + PRINTF("Mode=%d eye.x=%f, eye.z=%f kscp_pos=%d\n", pauseCtx->nextPageMode, pauseCtx->eye.x, + pauseCtx->eye.z, pauseCtx->pageIndex); } if (pauseCtx->state == PAUSE_STATE_WAIT_LETTERBOX) { @@ -77,7 +132,7 @@ void KaleidoSetup_Init(PlayState* play) { pauseCtx->alpha = 0; // mainState = PAUSE_MAIN_STATE_IDLE , pageIndex = PAUSE_ITEM - pauseCtx->unk_1EA = pauseCtx->mainState = pauseCtx->mode = pauseCtx->pageIndex = 0; + pauseCtx->pageSwitchTimer = pauseCtx->mainState = pauseCtx->nextPageMode = pauseCtx->pageIndex = 0; pauseCtx->unk_204 = -314.0f; diff --git a/src/code/z_kankyo.c b/src/code/z_kankyo.c index ce79a7df93..aab4069048 100644 --- a/src/code/z_kankyo.c +++ b/src/code/z_kankyo.c @@ -215,7 +215,7 @@ s16 sSunDepthTestY; // These variables could be moved farther down in the file to reduce the amount // of block number padding here, but currently this causes BSS ordering issues // for debug. -#pragma increment_block_number 230 +#pragma increment_block_number 227 LightNode* sNGameOverLightNode; LightInfo sNGameOverLightInfo; diff --git a/src/code/z_lib.c b/src/code/z_lib.c index 58a2911622..5eba9346f5 100644 --- a/src/code/z_lib.c +++ b/src/code/z_lib.c @@ -1,4 +1,11 @@ -#include "global.h" +#include "ultra64.h" +#include "z_lib.h" +#include "ichain.h" +#include "regs.h" +#include "macros.h" +#include "sys_math.h" +#include "rand.h" +#include "sfx.h" /** * memset: sets `len` bytes to `val` starting at address `dest`. @@ -334,7 +341,7 @@ void (*sInitChainHandlers[])(u8* ptr, InitChainEntry* ichain) = { IChain_Apply_Vec3f, IChain_Apply_Vec3fdiv1000, IChain_Apply_Vec3s, }; -void Actor_ProcessInitChain(Actor* actor, InitChainEntry* ichain) { +void Actor_ProcessInitChain(struct Actor* actor, InitChainEntry* ichain) { do { sInitChainHandlers[ichain->type]((u8*)actor, ichain); } while ((ichain++)->cont); diff --git a/src/code/z_message_PAL.c b/src/code/z_message_PAL.c index 126841cea3..027e66c217 100644 --- a/src/code/z_message_PAL.c +++ b/src/code/z_message_PAL.c @@ -3358,12 +3358,3 @@ void Message_SetTables(void) { sFraMessageEntryTablePtr = sFraMessageEntryTable; sStaffMessageEntryTablePtr = sStaffMessageEntryTable; } - -#if OOT_DEBUG -// Appears to be file padding -UNK_TYPE D_80153D7C = 0x00000000; -#endif - -// This should be part of z_game_over.c, but cannot be moved there as the entire -// late_rodata section of this file is in the way -s16 gGameOverTimer = 0; diff --git a/src/code/z_olib.c b/src/code/z_olib.c index d5056e8f70..c1f93a0522 100644 --- a/src/code/z_olib.c +++ b/src/code/z_olib.c @@ -1,4 +1,6 @@ -#include "global.h" +#include "z64math.h" +#include "fp_math.h" +#include "z_lib.h" /** * Calculates the distances between `a` and `b` diff --git a/src/code/z_play.c b/src/code/z_play.c index f86986839b..589ea596cb 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -284,7 +284,7 @@ void Play_Init(GameState* thisx) { Effect_InitContext(this); EffectSs_InitInfo(this, 0x55); CollisionCheck_InitContext(this, &this->colChkCtx); - AnimationContext_Reset(&this->animationCtx); + AnimTaskQueue_Reset(&this->animTaskQueue); Cutscene_InitContext(this, &this->csCtx); if (gSaveContext.nextCutsceneIndex != 0xFFEF) { @@ -454,7 +454,7 @@ void Play_Init(GameState* thisx) { gSaveContext.seqId = this->sequenceCtx.seqId; gSaveContext.natureAmbienceId = this->sequenceCtx.natureAmbienceId; func_8002DF18(this, GET_PLAYER(this)); - AnimationContext_Update(this, &this->animationCtx); + AnimTaskQueue_Update(this, &this->animTaskQueue); gSaveContext.respawnFlag = 0; #if OOT_DEBUG @@ -883,7 +883,7 @@ void Play_Update(PlayState* this) { isPaused = IS_PAUSED(&this->pauseCtx); PLAY_LOG(3555); - AnimationContext_Reset(&this->animationCtx); + AnimTaskQueue_Reset(&this->animTaskQueue); if (!OOT_DEBUG) {} @@ -1000,7 +1000,7 @@ void Play_Update(PlayState* this) { Interface_Update(this); PLAY_LOG(3765); - AnimationContext_Update(this, &this->animationCtx); + AnimTaskQueue_Update(this, &this->animTaskQueue); PLAY_LOG(3771); SfxSource_UpdateAll(this); diff --git a/src/code/z_skelanime.c b/src/code/z_skelanime.c index 42dfa4e9bc..acc01cb742 100644 --- a/src/code/z_skelanime.c +++ b/src/code/z_skelanime.c @@ -9,9 +9,6 @@ s32 SkelAnime_LoopFull(SkelAnime* skelAnime); s32 SkelAnime_Once(SkelAnime* skelAnime); s32 SkelAnime_LoopPartial(SkelAnime* skelAnime); -static u32 sDisableAnimQueueFlags = 0; -static u32 sAnimQueueFlags; - /** * Draw a limb of type `LodLimb` * Near or far display list is specified via `lod` @@ -798,39 +795,64 @@ void SkelAnime_InterpFrameTable(s32 limbCount, Vec3s* dst, Vec3s* start, Vec3s* } } +static u32 sDisabledTransformTaskGroups = 0; +static u32 sCurAnimTaskGroup; + /** - * zeroes out the current request count + * Clear the current task queue. The discarded tasks will then not be processed. */ -void AnimationContext_Reset(AnimationContext* animationCtx) { - animationCtx->animationCount = 0; +void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue) { + animTaskQueue->count = 0; } /** - * Shifts the queue flag to the next queue + * Changes `sCurAnimTaskGroup` to the next group number. + * + * Task groups allow for disabling "transformative" tasks for a defined group. + * For more information see `AnimTaskQueue_DisableTransformTasksForGroup`. + * + * Note that `sCurAnimTaskGroup` is not a whole number that increments, it is handled at the bit-level. + * Every time the group number changes, a single bit moves 1 position to the left. This is an implementation detail + * that allows for `sDisabledTransformTaskGroups` to compare against a set of bit flags. */ -void AnimationContext_SetNextQueue(PlayState* play) { - sAnimQueueFlags <<= 1; +void AnimTaskQueue_SetNextGroup(PlayState* play) { + sCurAnimTaskGroup <<= 1; } /** - * Disables the current animation queue. Only load and move actor requests will be processed for that queue. + * Marks the current task group as disabled so that "transformative" tasks are skipped. + * A transformative task is one that will alter the appearance of an animation. + * These include Copy, Interp, CopyUsingMap, and CopyUsingMapInverted. + * + * LoadPlayerFrame and ActorMove, which don't alter the appearance of an existing animation, + * will always run even if a group has its transformative tasks disabled. */ -void AnimationContext_DisableQueue(PlayState* play) { - sDisableAnimQueueFlags |= sAnimQueueFlags; +void AnimTaskQueue_DisableTransformTasksForGroup(PlayState* play) { + sDisabledTransformTaskGroups |= sCurAnimTaskGroup; } -AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, AnimationType type) { - AnimationEntry* entry; - s16 index = animationCtx->animationCount; +/** + * Creates a new task and adds it to the queue, if there is room for it. + * + * The `type` value for the task gets set here, but all other + * initialization must be handled by the caller. + * + * @return a pointer to the task, or NULL if it could not be added + */ +AnimTask* AnimTaskQueue_NewTask(AnimTaskQueue* animTaskQueue, s32 type) { + AnimTask* task; + s16 taskNumber = animTaskQueue->count; - if (index >= ANIMATION_ENTRY_MAX) { + if (taskNumber >= ANIM_TASK_QUEUE_MAX) { return NULL; } - animationCtx->animationCount = index + 1; - entry = &animationCtx->entries[index]; - entry->type = type; - return entry; + animTaskQueue->count = taskNumber + 1; + + task = &animTaskQueue->tasks[taskNumber]; + task->type = type; + + return task; } #define LINK_ANIMATION_OFFSET(addr, offset) \ @@ -838,205 +860,230 @@ AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, Animat (offset)) /** - * Requests loading frame data from the Link animation into frameTable + * Creates a task which will load a single frame of animation data from the link_animetion file. + * The asynchronous DMA request to load the data is made as soon as the task is created. + * When the task is processed later in the AnimTaskQueue, it will wait for the DMA to finish. */ -void AnimationContext_SetLoadFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, - Vec3s* frameTable) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_LOADFRAME); +void AnimTaskQueue_AddLoadPlayerFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, + Vec3s* frameTable) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_LOAD_PLAYER_FRAME); - if (entry != NULL) { + if (task != NULL) { LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation); s32 pad; - osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1); - DMA_REQUEST_ASYNC(&entry->data.load.req, frameTable, + osCreateMesgQueue(&task->data.loadPlayerFrame.msgQueue, &task->data.loadPlayerFrame.msg, 1); + DMA_REQUEST_ASYNC(&task->data.loadPlayerFrame.req, frameTable, LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)), - sizeof(Vec3s) * limbCount + 2, 0, &entry->data.load.msgQueue, NULL, "../z_skelanime.c", 2004); + sizeof(Vec3s) * limbCount + 2, 0, &task->data.loadPlayerFrame.msgQueue, NULL, + "../z_skelanime.c", 2004); } } /** - * Requests copying all vectors from src frame table into dst frame table + * Creates a task which will copy all vectors from the `src` frame table to the `dest` frame table. + * + * Note: This task is "transformative", meaning it will alter the appearance of an animation. + * If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame. */ -void AnimationContext_SetCopyAll(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYALL); +void AnimTaskQueue_AddCopy(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY); - if (entry != NULL) { - entry->data.copy.queueFlag = sAnimQueueFlags; - entry->data.copy.vecCount = vecCount; - entry->data.copy.dst = dst; - entry->data.copy.src = src; + if (task != NULL) { + task->data.copy.group = sCurAnimTaskGroup; + task->data.copy.vecCount = vecCount; + task->data.copy.dest = dest; + task->data.copy.src = src; } } /** - * Requests interpolating between base and mod frame tables with the given weight, placing the result in base + * Creates a task which will interpolate between the `base` and `mod` frame tables. + * The result of the interpolation will be placed in the original `base` table. + * + * Note: This task is "transformative", meaning it will alter the appearance of an animation. + * If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame. */ -void AnimationContext_SetInterp(PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_INTERP); +void AnimTaskQueue_AddInterp(PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_INTERP); - if (entry != NULL) { - entry->data.interp.queueFlag = sAnimQueueFlags; - entry->data.interp.vecCount = vecCount; - entry->data.interp.base = base; - entry->data.interp.mod = mod; - entry->data.interp.weight = weight; + if (task != NULL) { + task->data.interp.group = sCurAnimTaskGroup; + task->data.interp.vecCount = vecCount; + task->data.interp.base = base; + task->data.interp.mod = mod; + task->data.interp.weight = weight; } } /** - * Requests copying vectors from src frame table to dst frame table whose copy flag is true + * Creates a task which will copy specified vectors from the `src` frame table to the `dest` frame table. + * Exactly which vectors will be copied is specified by the `limbCopyMap`. + * + * The copy map is an array of true/false flags that specify which limbs should have their data copied. + * Each index of the map corresponds to a limb number in the skeleton. + * Every limb that has `true` listed will have its data copied. + * + * Note: This task is "transformative", meaning it will alter the appearance of an animation. + * If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame. */ -void AnimationContext_SetCopyTrue(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYTRUE); +void AnimTaskQueue_AddCopyUsingMap(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP); - if (entry != NULL) { - entry->data.copy1.queueFlag = sAnimQueueFlags; - entry->data.copy1.vecCount = vecCount; - entry->data.copy1.dst = dst; - entry->data.copy1.src = src; - entry->data.copy1.copyFlag = copyFlag; + if (task != NULL) { + task->data.copyUsingMap.group = sCurAnimTaskGroup; + task->data.copyUsingMap.vecCount = vecCount; + task->data.copyUsingMap.dest = dest; + task->data.copyUsingMap.src = src; + task->data.copyUsingMap.limbCopyMap = limbCopyMap; } } /** - * Requests copying vectors from src frame table to dst frame table whose copy flag is false + * Identical to `AnimTaskQueue_AddCopyUsingMap`, except the meaning of the flags in the `limbCopyMap` are inverted. + * Any entry that specifies `false` will be copied, and any entry that specifies `true` will not. + * + * Note: This task is "transformative", meaning it will alter the appearance of an animation. + * If this task's group is included in `sDisabledTransformTaskGroups`, this task will be skipped for that frame. */ -void AnimationContext_SetCopyFalse(PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYFALSE); +void AnimTaskQueue_AddCopyUsingMapInverted(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP_INVERTED); - if (entry != NULL) { - entry->data.copy0.queueFlag = sAnimQueueFlags; - entry->data.copy0.vecCount = vecCount; - entry->data.copy0.dst = dst; - entry->data.copy0.src = src; - entry->data.copy0.copyFlag = copyFlag; + if (task != NULL) { + task->data.copyUsingMapInverted.group = sCurAnimTaskGroup; + task->data.copyUsingMapInverted.vecCount = vecCount; + task->data.copyUsingMapInverted.dest = dest; + task->data.copyUsingMapInverted.src = src; + task->data.copyUsingMapInverted.limbCopyMap = limbCopyMap; } } /** - * Requests moving an actor according to the translation of its root limb + * Creates a task which will move an actor according to the translation of its root limb for the current frame. */ -void AnimationContext_SetMoveActor(PlayState* play, Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY) { - AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_MOVEACTOR); +void AnimTaskQueue_AddActorMove(PlayState* play, Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY) { + AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_ACTOR_MOVE); - if (entry != NULL) { - entry->data.move.actor = actor; - entry->data.move.skelAnime = skelAnime; - entry->data.move.diffScaleY = moveDiffScaleY; + if (task != NULL) { + task->data.actorMove.actor = actor; + task->data.actorMove.skelAnime = skelAnime; + task->data.actorMove.diffScaleY = moveDiffScaleY; } } /** - * Receives the request for Link's animation frame data + * Wait for the DMA request submitted by `AnimTaskQueue_AddLoadPlayerFrame` to complete. */ -void AnimationContext_LoadFrame(PlayState* play, AnimationEntryData* data) { - AnimEntryLoadFrame* entry = &data->load; +void AnimTask_LoadPlayerFrame(PlayState* play, AnimTaskData* data) { + AnimTaskLoadPlayerFrame* task = &data->loadPlayerFrame; - osRecvMesg(&entry->msgQueue, NULL, OS_MESG_BLOCK); + osRecvMesg(&task->msgQueue, NULL, OS_MESG_BLOCK); } /** - * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table + * Copy all data from the `src` frame table to the `dest` table. */ -void AnimationContext_CopyAll(PlayState* play, AnimationEntryData* data) { - AnimEntryCopyAll* entry = &data->copy; +void AnimTask_Copy(PlayState* play, AnimTaskData* data) { + AnimTaskCopy* task = &data->copy; - if (!(entry->queueFlag & sDisableAnimQueueFlags)) { - Vec3s* dst = entry->dst; - Vec3s* src = entry->src; + if (!(task->group & sDisabledTransformTaskGroups)) { + Vec3s* dest = task->dest; + Vec3s* src = task->src; s32 i; - for (i = 0; i < entry->vecCount; i++) { - *dst++ = *src++; + for (i = 0; i < task->vecCount; i++) { + *dest++ = *src++; } } } /** - * If the entry's queue is enabled, interpolates between the base and mod frame tables, placing the result in base + * Interpolate between the `base` and `mod` frame tables. */ -void AnimationContext_Interp(PlayState* play, AnimationEntryData* data) { - AnimEntryInterp* entry = &data->interp; +void AnimTask_Interp(PlayState* play, AnimTaskData* data) { + AnimTaskInterp* task = &data->interp; - if (!(entry->queueFlag & sDisableAnimQueueFlags)) { - SkelAnime_InterpFrameTable(entry->vecCount, entry->base, entry->base, entry->mod, entry->weight); + if (!(task->group & sDisabledTransformTaskGroups)) { + SkelAnime_InterpFrameTable(task->vecCount, task->base, task->base, task->mod, task->weight); } } /** - * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is true + * Copy all data from the `src` frame table to the `dest` table according to the copy map. */ -void AnimationContext_CopyTrue(PlayState* play, AnimationEntryData* data) { - AnimEntryCopyTrue* entry = &data->copy1; +void AnimTask_CopyUsingMap(PlayState* play, AnimTaskData* data) { + AnimTaskCopyUsingMap* task = &data->copyUsingMap; - if (!(entry->queueFlag & sDisableAnimQueueFlags)) { - Vec3s* dst = entry->dst; - Vec3s* src = entry->src; - u8* copyFlag = entry->copyFlag; + if (!(task->group & sDisabledTransformTaskGroups)) { + Vec3s* dest = task->dest; + Vec3s* src = task->src; + u8* limbCopyMap = task->limbCopyMap; s32 i; - for (i = 0; i < entry->vecCount; i++, dst++, src++) { - if (*copyFlag++) { - *dst = *src; + for (i = 0; i < task->vecCount; i++, dest++, src++) { + if (*limbCopyMap++) { + *dest = *src; } } } } /** - * If the entry's queue is enabled, copies all vectors from src frame table to dst frame table whose copy flag is false + * Copy all data from the `src` frame table to the `dest` table according to the inverted copy map. */ -void AnimationContext_CopyFalse(PlayState* play, AnimationEntryData* data) { - AnimEntryCopyFalse* entry = &data->copy0; +void AnimTask_CopyUsingMapInverted(PlayState* play, AnimTaskData* data) { + AnimTaskCopyUsingMapInverted* task = &data->copyUsingMapInverted; - if (!(entry->queueFlag & sDisableAnimQueueFlags)) { - Vec3s* dst = entry->dst; - Vec3s* src = entry->src; - u8* copyFlag = entry->copyFlag; + if (!(task->group & sDisabledTransformTaskGroups)) { + Vec3s* dest = task->dest; + Vec3s* src = task->src; + u8* limbCopyMap = task->limbCopyMap; s32 i; - for (i = 0; i < entry->vecCount; i++, dst++, src++) { - if (!(*copyFlag++)) { - *dst = *src; + for (i = 0; i < task->vecCount; i++, dest++, src++) { + if (!(*limbCopyMap++)) { + *dest = *src; } } } } /** - * Moves an actor according to the translation of its root limb + * Move an actor according to the translation of its root limb for the current animation frame. */ -void AnimationContext_MoveActor(PlayState* play, AnimationEntryData* data) { - AnimEntryMoveActor* entry = &data->move; - Actor* actor = entry->actor; +void AnimTask_ActorMove(PlayState* play, AnimTaskData* data) { + AnimTaskActorMove* task = &data->actorMove; + Actor* actor = task->actor; Vec3f diff; - SkelAnime_UpdateTranslation(entry->skelAnime, &diff, actor->shape.rot.y); + SkelAnime_UpdateTranslation(task->skelAnime, &diff, actor->shape.rot.y); + actor->world.pos.x += diff.x * actor->scale.x; - actor->world.pos.y += diff.y * actor->scale.y * entry->diffScaleY; + actor->world.pos.y += diff.y * actor->scale.y * task->diffScaleY; actor->world.pos.z += diff.z * actor->scale.z; } -typedef void (*AnimationEntryCallback)(struct PlayState* play, AnimationEntryData* data); +typedef void (*AnimTaskFunc)(struct PlayState* play, AnimTaskData* data); /** - * Performs all requests in the animation queue, then resets the queue flags. + * Update the AnimTaskQueue, processing all tasks in order. + * Variables related to anim task groups are then reset for the next frame. */ -void AnimationContext_Update(PlayState* play, AnimationContext* animationCtx) { - static AnimationEntryCallback animFuncs[] = { - AnimationContext_LoadFrame, AnimationContext_CopyAll, AnimationContext_Interp, - AnimationContext_CopyTrue, AnimationContext_CopyFalse, AnimationContext_MoveActor, +void AnimTaskQueue_Update(PlayState* play, AnimTaskQueue* animTaskQueue) { + static AnimTaskFunc animTaskFuncs[] = { + AnimTask_LoadPlayerFrame, AnimTask_Copy, AnimTask_Interp, AnimTask_CopyUsingMap, + AnimTask_CopyUsingMapInverted, AnimTask_ActorMove, }; - AnimationEntry* entry = animationCtx->entries; + AnimTask* task = animTaskQueue->tasks; - for (; animationCtx->animationCount != 0; animationCtx->animationCount--) { - animFuncs[entry->type](play, &entry->data); - entry++; + while (animTaskQueue->count != 0) { + animTaskFuncs[task->type](play, &task->data); + task++; + animTaskQueue->count--; } - sAnimQueueFlags = 1; - sDisableAnimQueueFlags = 0; + sCurAnimTaskGroup = 1 << 0; + sDisabledTransformTaskGroups = 0; } /** @@ -1125,8 +1172,8 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) { LinkAnimation_SetUpdateFunction(skelAnime); } - AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, - 1.0f - (skelAnime->morphWeight / prevMorphWeight)); + AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, + 1.0f - (skelAnime->morphWeight / prevMorphWeight)); return 0; } @@ -1135,8 +1182,8 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) { * jointTable and morphTable */ void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) { - AnimationContext_SetLoadFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, - skelAnime->jointTable); + AnimTaskQueue_AddLoadPlayerFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, + skelAnime->jointTable); if (skelAnime->morphWeight != 0) { f32 updateRate = R_UPDATE_RATE * 0.5f; @@ -1144,8 +1191,8 @@ void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) { if (skelAnime->morphWeight <= 0.0f) { skelAnime->morphWeight = 0.0f; } else { - AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, - skelAnime->morphWeight); + AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, + skelAnime->morphWeight); } } } @@ -1212,14 +1259,14 @@ void LinkAnimation_Change(PlayState* play, SkelAnime* skelAnime, LinkAnimationHe morphFrames = -morphFrames; } else { skelAnime->update.link = LinkAnimation_Morph; - AnimationContext_SetLoadFrame(play, animation, (s32)startFrame, skelAnime->limbCount, - skelAnime->morphTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)startFrame, skelAnime->limbCount, + skelAnime->morphTable); } skelAnime->morphWeight = 1.0f; skelAnime->morphRate = 1.0f / morphFrames; } else { LinkAnimation_SetUpdateFunction(skelAnime); - AnimationContext_SetLoadFrame(play, animation, (s32)startFrame, skelAnime->limbCount, skelAnime->jointTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)startFrame, skelAnime->limbCount, skelAnime->jointTable); skelAnime->morphWeight = 0.0f; } @@ -1270,7 +1317,7 @@ void LinkAnimation_PlayLoopSetSpeed(PlayState* play, SkelAnime* skelAnime, LinkA * Requests copying jointTable to morphTable */ void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) { - AnimationContext_SetCopyAll(play, skelAnime->limbCount, skelAnime->morphTable, skelAnime->jointTable); + AnimTaskQueue_AddCopy(play, skelAnime->limbCount, skelAnime->morphTable, skelAnime->jointTable); } /** @@ -1278,28 +1325,28 @@ void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) { * unused */ void LinkAnimation_CopyMorphToJoint(PlayState* play, SkelAnime* skelAnime) { - AnimationContext_SetCopyAll(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable); + AnimTaskQueue_AddCopy(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable); } /** * Requests loading frame data from the Link animation into morphTable */ void LinkAnimation_LoadToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { - AnimationContext_SetLoadFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->morphTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->morphTable); } /** * Requests loading frame data from the Link animation into jointTable */ void LinkAnimation_LoadToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { - AnimationContext_SetLoadFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->jointTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)frame, skelAnime->limbCount, skelAnime->jointTable); } /** * Requests interpolating between jointTable and morphTable, placing the result in jointTable */ void LinkAnimation_InterpJointMorph(PlayState* play, SkelAnime* skelAnime, f32 weight) { - AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, weight); + AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, weight); } /** @@ -1309,12 +1356,12 @@ void LinkAnimation_BlendToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnima LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) { Vec3s* alignedBlendTable; - AnimationContext_SetLoadFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->jointTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->jointTable); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable); - AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); - AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight); + AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); + AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight); } /** @@ -1324,12 +1371,12 @@ void LinkAnimation_BlendToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnima LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) { Vec3s* alignedBlendTable; - AnimationContext_SetLoadFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->morphTable); + AnimTaskQueue_AddLoadPlayerFrame(play, animation1, (s32)frame1, skelAnime->limbCount, skelAnime->morphTable); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable); - AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); - AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight); + AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); + AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight); } /** diff --git a/src/libultra/gu/coss.c b/src/libultra/gu/coss.c index 0eb8b5e65d..6a52bd1d40 100644 --- a/src/libultra/gu/coss.c +++ b/src/libultra/gu/coss.c @@ -1,4 +1,4 @@ -#include "global.h" +#include "ultra64.h" /** * @param angle binang diff --git a/src/overlays/actors/ovl_Bg_Haka_Megane/z_bg_haka_megane.c b/src/overlays/actors/ovl_Bg_Haka_Megane/z_bg_haka_megane.c index b7d3248962..39082dcb64 100644 --- a/src/overlays/actors/ovl_Bg_Haka_Megane/z_bg_haka_megane.c +++ b/src/overlays/actors/ovl_Bg_Haka_Megane/z_bg_haka_megane.c @@ -89,7 +89,7 @@ void func_8087DB24(BgHakaMegane* this, PlayState* play) { this->dyna.actor.objectSlot = this->requiredObjectSlot; this->dyna.actor.draw = BgHakaMegane_Draw; Actor_SetObjectDependency(play, &this->dyna.actor); - if (play->roomCtx.curRoom.lensMode != LENS_MODE_HIDE_ACTORS) { + if (play->roomCtx.curRoom.lensMode != LENS_MODE_SHOW_ACTORS) { CollisionHeader* colHeader; CollisionHeader* collision; diff --git a/src/overlays/actors/ovl_Demo_Ec/z_demo_ec.c b/src/overlays/actors/ovl_Demo_Ec/z_demo_ec.c index fa4879e26c..1f4bcf362d 100644 --- a/src/overlays/actors/ovl_Demo_Ec/z_demo_ec.c +++ b/src/overlays/actors/ovl_Demo_Ec/z_demo_ec.c @@ -177,19 +177,19 @@ void DemoEc_UpdateBgFlags(DemoEc* this, PlayState* play) { void func_8096D594(DemoEc* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_8096D5D4(DemoEc* this, PlayState* play) { this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_8096D64C(DemoEc* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void DemoEc_UpdateEyes(DemoEc* this) { diff --git a/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c b/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c index 199fb04f7e..0d2d7b24d2 100644 --- a/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c +++ b/src/overlays/actors/ovl_Demo_Ik/z_demo_ik.c @@ -55,7 +55,7 @@ s32 DemoIk_CheckForCue(PlayState* play, u16 cueId, s32 cueChannel) { void DemoIk_SetMove(DemoIk* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void DemoIk_EndMove(DemoIk* this) { 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 f41fd6fe1d..ff1a9bda7b 100644 --- a/src/overlays/actors/ovl_En_In/z_en_in.c +++ b/src/overlays/actors/ovl_En_In/z_en_in.c @@ -338,7 +338,7 @@ void func_80A795C8(EnIn* this, PlayState* play) { void func_80A79690(SkelAnime* skelAnime, EnIn* this, PlayState* play) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f); } } diff --git a/src/overlays/actors/ovl_En_Nb/z_en_nb.c b/src/overlays/actors/ovl_En_Nb/z_en_nb.c index 336aad8d15..2421276bef 100644 --- a/src/overlays/actors/ovl_En_Nb/z_en_nb.c +++ b/src/overlays/actors/ovl_En_Nb/z_en_nb.c @@ -757,7 +757,7 @@ void EnNb_InitDemo6KInConfrontation(EnNb* this, PlayState* play) { void func_80AB2688(EnNb* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80AB26C8(EnNb* this) { diff --git a/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c b/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c index 792457dc5a..e0549aca4f 100644 --- a/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c +++ b/src/overlays/actors/ovl_En_Ru1/z_en_ru1.c @@ -392,7 +392,7 @@ s32 EnRu1_UpdateSkelAnime(EnRu1* this) { void func_80AEB364(EnRu1* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80AEB3A4(EnRu1* this, PlayState* play) { @@ -463,7 +463,7 @@ void func_80AEB6E0(EnRu1* this, PlayState* play) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f); } } @@ -474,7 +474,7 @@ void func_80AEB738(EnRu1* this, PlayState* play) { skelAnime->prevTransl = skelAnime->jointTable[0]; if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f); } } diff --git a/src/overlays/actors/ovl_En_Test/z_en_test.c b/src/overlays/actors/ovl_En_Test/z_en_test.c index 1371a2adba..96a2a2e87b 100644 --- a/src/overlays/actors/ovl_En_Test/z_en_test.c +++ b/src/overlays/actors/ovl_En_Test/z_en_test.c @@ -61,7 +61,7 @@ void func_80862FA8(EnTest* this, PlayState* play); s32 EnTest_ReactToProjectile(PlayState* play, EnTest* this); -static u8 sJointCopyFlags[] = { +static u8 sUpperBodyLimbCopyMap[] = { false, // STALFOS_LIMB_NONE false, // STALFOS_LIMB_ROOT false, // STALFOS_LIMB_UPPERBODY_ROOT @@ -1742,15 +1742,15 @@ void EnTest_Update(Actor* thisx, PlayState* play) { case 1: Animation_Change(&this->upperSkelanime, &gStalfosBlockWithShieldAnim, 2.0f, 0.0f, Animation_GetLastFrame(&gStalfosBlockWithShieldAnim), 2, 2.0f); - AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelanime.jointTable, sJointCopyFlags); + AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap); this->unk_7DE++; break; case 2: SkelAnime_Update(&this->upperSkelanime); SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, - this->upperSkelanime.jointTable, sJointCopyFlags); + this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap); break; case 3: @@ -1769,7 +1769,7 @@ void EnTest_Update(Actor* thisx, PlayState* play) { this->upperSkelanime.jointTable, this->skelAnime.jointTable, 1.0f - (this->upperSkelanime.morphWeight / oldWeight)); SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, - this->upperSkelanime.jointTable, sJointCopyFlags); + this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap); break; } diff --git a/src/overlays/actors/ovl_En_Xc/z_en_xc.c b/src/overlays/actors/ovl_En_Xc/z_en_xc.c index 17eff561ad..826edcc722 100644 --- a/src/overlays/actors/ovl_En_Xc/z_en_xc.c +++ b/src/overlays/actors/ovl_En_Xc/z_en_xc.c @@ -255,20 +255,20 @@ void func_80B3C8CC(EnXc* this, PlayState* play) { if (skelAnime->jointTable[0].y >= skelAnime->baseTransl.y) { skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f); } } void func_80B3C924(EnXc* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80B3C964(EnXc* this, PlayState* play) { this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80B3C9DC(EnXc* this) { diff --git a/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c b/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c index aed5c9b0fb..2b1c7d3321 100644 --- a/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c +++ b/src/overlays/actors/ovl_En_Zl1/z_en_zl1.c @@ -346,7 +346,7 @@ void func_80B4B834(CsCmdActorCue* cue, Vec3f* dest) { void func_80B4B874(EnZl1* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80B4B8B4(EnZl1* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c b/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c index 00fdde50aa..2cf5b1d2a3 100644 --- a/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c +++ b/src/overlays/actors/ovl_En_Zl4/z_en_zl4.c @@ -299,7 +299,7 @@ void EnZl4_UpdateFace(EnZl4* this) { void EnZl4_SetMove(EnZl4* this, PlayState* play) { this->skelAnime.moveFlags |= ANIM_FLAG_0; - AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f); } void func_80B5BB78(EnZl4* this, PlayState* play) { diff --git a/src/overlays/actors/ovl_Fishing/z_fishing.c b/src/overlays/actors/ovl_Fishing/z_fishing.c index bee978e5bc..76daff7a0e 100644 --- a/src/overlays/actors/ovl_Fishing/z_fishing.c +++ b/src/overlays/actors/ovl_Fishing/z_fishing.c @@ -11,7 +11,7 @@ #include "terminal.h" // For retail BSS ordering, the block number of sStreamSfxProjectedPos must be 0. -#pragma increment_block_number 198 +#pragma increment_block_number 193 #define FLAGS ACTOR_FLAG_4 diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 8946f8f9f4..db42ef755d 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -1989,7 +1989,7 @@ void Player_AnimReplaceApplyFlags(PlayState* play, Player* this, s32 flags) { this->skelAnime.moveFlags = flags & 0xFF; Player_ZeroSpeedXZ(this); - AnimationContext_DisableQueue(play); + AnimTaskQueue_DisableTransformTasksForGroup(play); } void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, @@ -3071,8 +3071,8 @@ s32 func_808358F0(Player* this, PlayState* play) { if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) || (func_808335F4(this) == animSeg)) { - AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, - this->skelAnime.jointTable); + AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, + this->skelAnime.jointTable); } else { LinkAnimation_Update(play, &this->upperSkelAnime); } @@ -3425,22 +3425,22 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) { // The functionality contained within this block of code is never used in practice // because `upperAnimInterpWeight` is always 0. if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { - AnimationContext_SetCopyFalse(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, - this->skelAnime.jointTable, sUpperBodyLimbCopyMap); + AnimTaskQueue_AddCopyUsingMapInverted(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, + this->skelAnime.jointTable, sUpperBodyLimbCopyMap); } Math_StepToF(&this->upperAnimInterpWeight, 0.0f, 0.25f); - AnimationContext_SetInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight); + AnimTaskQueue_AddInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight); } else if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { // Only copy the upper body animation to the upper body limbs in the main skeleton. // Doing so allows the main skeleton to play its own animation for the lower body limbs. - AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); + AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); } else { // Copy all of the upper body animation into the whole main skeleton. // The upper body has full control of all limbs. - AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelAnime.jointTable); + AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelAnime.jointTable); } return true; @@ -4650,7 +4650,7 @@ s32 Player_ActionChange_12(Player* this, PlayState* play) { this->actor.bgCheckFlags |= BGCHECKFLAG_GROUND; LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f); - AnimationContext_DisableQueue(play); + AnimTaskQueue_DisableTransformTasksForGroup(play); this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000; @@ -8105,10 +8105,10 @@ void Player_Action_80841BA8(Player* this, PlayState* play) { LinkAnimation_Update(play, &this->skelAnime); if (Player_HoldsTwoHandedWeapon(this)) { - AnimationContext_SetLoadFrame(play, func_80833338(this), 0, this->skelAnime.limbCount, - this->skelAnime.morphTable); - AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->skelAnime.morphTable, sUpperBodyLimbCopyMap); + AnimTaskQueue_AddLoadPlayerFrame(play, func_80833338(this), 0, this->skelAnime.limbCount, + this->skelAnime.morphTable); + AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->skelAnime.morphTable, sUpperBodyLimbCopyMap); } Player_GetMovementSpeedAndYaw(this, &speedTarget, &yawTarget, SPEED_MODE_CURVED, play); @@ -9033,7 +9033,7 @@ void Player_Action_8084411C(Player* this, PlayState* play) { } else if ((this->ledgeClimbType >= PLAYER_LEDGE_CLIMB_2) && (this->yDistToLedge < 150.0f) && (((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) > (70.0f * this->ageProperties->unk_08))) { - AnimationContext_DisableQueue(play); + AnimTaskQueue_DisableTransformTasksForGroup(play); if (this->stateFlags1 & PLAYER_STATE1_2) { func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG); } else { @@ -11345,9 +11345,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { Player_UpdateCamAndSeqModes(play, this); if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) { - AnimationContext_SetMoveActor( - play, &this->actor, &this->skelAnime, - (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f : this->ageProperties->unk_08); + AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, + (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f + : this->ageProperties->unk_08); } Player_UpdateShapeYaw(this, play); @@ -11417,8 +11417,10 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) { } } } - - AnimationContext_SetNextQueue(play); + // Because Player updates early relative to most actors, his animation tasks will belong to group 0. + // Task group 1 is set here at the end of Player's update, meaning tasks that get added by other + // actors will be in a different group. + AnimTaskQueue_SetNextGroup(play); } Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos); @@ -12635,8 +12637,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) { LinkAnimation_AnimateFrame(play, &this->skelAnime); } - AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.morphTable, - this->skelAnime.jointTable); + AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.morphTable, this->skelAnime.jointTable); if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != PLAYER_CSACTION_NONE)) { if (this->csAction == PLAYER_CSACTION_7) { @@ -12674,16 +12675,16 @@ void Player_Action_8084CC98(Player* this, PlayState* play) { func_80832698(this, NA_SE_VO_LI_LASH); } - AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelAnime.jointTable); + AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelAnime.jointTable); } else { if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) { Player_PlaySfx(this, NA_SE_IT_LASH); func_80832698(this, NA_SE_VO_LI_LASH); } - AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, - this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); + AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable, + this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); } } else { LinkAnimationHeader* anim = NULL; diff --git a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c index 4e612c5578..cf961177a3 100644 --- a/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c +++ b/src/overlays/misc/ovl_kaleido_scope/z_kaleido_scope_PAL.c @@ -135,12 +135,45 @@ s16 D_8082AB2C[] = { 24, 72, 13, 22, 19, 20, 19, 27, 14, 26, 22, 21, 49, 32, 45, 60, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 16, 32, 8, }; -static u8 D_8082AB6C[][5] = { +/** + * Contains the status of buttons for each page. + * + * Indexed by `pageIndex + pt` values, + * where pageIndex is from the `PauseMenuPage` enum + * and pt is 0 or 2 (respectively `PAGE_SWITCH_PT_LEFT` and `PAGE_SWITCH_PT_RIGHT`). + * + * `PauseMenuPage` enum values are ordered clockwise, starting at PAUSE_ITEM. That means adding 1 to a page index + * produces (modulo 4) the index of the page to the right, and similar with subtracting 1 for the left page. + * The indexing of this array relies on this property, but without modulo operations. Instead, the data for the first + * and last pages (PAUSE_ITEM, PAUSE_EQUIP) is duplicated. + * + * For example when scrolling left from the quest page PAUSE_QUEST (so, to PAUSE_MAP), + * the index is `PAUSE_QUEST + PAGE_SWITCH_PT_LEFT` and the data is button status for the map page. + */ +static u8 gPageSwitchNextButtonStatus[][5] = { + // PAUSE_ITEM + PAGE_SWITCH_PT_LEFT + // + // -> PAUSE_EQUIP { BTN_ENABLED, BTN_DISABLED, BTN_DISABLED, BTN_DISABLED, BTN_ENABLED }, + // PAUSE_MAP + PAGE_SWITCH_PT_LEFT + // + // -> PAUSE_ITEM { BTN_ENABLED, BTN_ENABLED, BTN_ENABLED, BTN_ENABLED, BTN_DISABLED }, + // PAUSE_QUEST + PAGE_SWITCH_PT_LEFT + // PAUSE_ITEM + PAGE_SWITCH_PT_RIGHT + // -> PAUSE_MAP { BTN_ENABLED, BTN_DISABLED, BTN_DISABLED, BTN_DISABLED, BTN_DISABLED }, + // PAUSE_EQUIP + PAGE_SWITCH_PT_LEFT + // PAUSE_MAP + PAGE_SWITCH_PT_RIGHT + // -> PAUSE_QUEST { BTN_ENABLED, BTN_DISABLED, BTN_DISABLED, BTN_DISABLED, BTN_ENABLED }, + // + // PAUSE_QUEST + PAGE_SWITCH_PT_RIGHT + // -> PAUSE_EQUIP { BTN_ENABLED, BTN_DISABLED, BTN_DISABLED, BTN_DISABLED, BTN_ENABLED }, + // + // PAUSE_EQUIP + PAGE_SWITCH_PT_RIGHT + // -> PAUSE_ITEM { BTN_ENABLED, BTN_ENABLED, BTN_ENABLED, BTN_ENABLED, BTN_DISABLED }, }; @@ -155,16 +188,49 @@ static s16 D_8082ABA4 = 0; static s16 sInDungeonScene = false; -static f32 D_8082ABAC[] = { - -4.0f, 4.0f, 4.0f, 4.0f, 4.0f, -4.0f, -4.0f, -4.0f, +/* + * The following three `sPageSwitch*` arrays are indexed by nextPageMode values, + * which encode the page to switch from and the scroll direction. + * + * sPageSwitchEyeDx/Dz describe how to move the camera eye so that the pages appear scrolling and the next active page + * is switched into view. + * + * sPageSwitchNextPageIndex contains the page a nextPageMode leads to once scrolling is done. + */ + +#define PAGE_SWITCH_NSTEPS 16 + +static f32 sPageSwitchEyeDx[] = { + -PAUSE_EYE_DIST * (PAUSE_MAP_X - PAUSE_ITEM_X) / PAGE_SWITCH_NSTEPS, // PAUSE_ITEM right + -PAUSE_EYE_DIST*(PAUSE_EQUIP_X - PAUSE_ITEM_X) / PAGE_SWITCH_NSTEPS, // PAUSE_ITEM left + -PAUSE_EYE_DIST*(PAUSE_QUEST_X - PAUSE_MAP_X) / PAGE_SWITCH_NSTEPS, // PAUSE_MAP right + -PAUSE_EYE_DIST*(PAUSE_ITEM_X - PAUSE_MAP_X) / PAGE_SWITCH_NSTEPS, // PAUSE_MAP left + -PAUSE_EYE_DIST*(PAUSE_EQUIP_X - PAUSE_QUEST_X) / PAGE_SWITCH_NSTEPS, // PAUSE_QUEST right + -PAUSE_EYE_DIST*(PAUSE_MAP_X - PAUSE_QUEST_X) / PAGE_SWITCH_NSTEPS, // PAUSE_QUEST left + -PAUSE_EYE_DIST*(PAUSE_ITEM_X - PAUSE_EQUIP_X) / PAGE_SWITCH_NSTEPS, // PAUSE_EQUIP right + -PAUSE_EYE_DIST*(PAUSE_QUEST_X - PAUSE_EQUIP_X) / PAGE_SWITCH_NSTEPS, // PAUSE_EQUIP left }; -static f32 D_8082ABCC[] = { - -4.0f, -4.0f, -4.0f, 4.0f, 4.0f, 4.0f, 4.0f, -4.0f, +static f32 sPageSwitchEyeDz[] = { + -PAUSE_EYE_DIST * (PAUSE_MAP_Z - PAUSE_ITEM_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_ITEM right + -PAUSE_EYE_DIST*(PAUSE_EQUIP_Z - PAUSE_ITEM_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_ITEM left + -PAUSE_EYE_DIST*(PAUSE_QUEST_Z - PAUSE_MAP_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_MAP right + -PAUSE_EYE_DIST*(PAUSE_ITEM_Z - PAUSE_MAP_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_MAP left + -PAUSE_EYE_DIST*(PAUSE_EQUIP_Z - PAUSE_QUEST_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_QUEST right + -PAUSE_EYE_DIST*(PAUSE_MAP_Z - PAUSE_QUEST_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_QUEST left + -PAUSE_EYE_DIST*(PAUSE_ITEM_Z - PAUSE_EQUIP_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_EQUIP right + -PAUSE_EYE_DIST*(PAUSE_QUEST_Z - PAUSE_EQUIP_Z) / PAGE_SWITCH_NSTEPS, // PAUSE_EQUIP left }; -static u16 D_8082ABEC[] = { - PAUSE_MAP, PAUSE_EQUIP, PAUSE_QUEST, PAUSE_ITEM, PAUSE_EQUIP, PAUSE_MAP, PAUSE_ITEM, PAUSE_QUEST, +static u16 sPageSwitchNextPageIndex[] = { + PAUSE_MAP, // PAUSE_ITEM right + PAUSE_EQUIP, // PAUSE_ITEM left + PAUSE_QUEST, // PAUSE_MAP right + PAUSE_ITEM, // PAUSE_MAP left + PAUSE_EQUIP, // PAUSE_QUEST right + PAUSE_MAP, // PAUSE_QUEST left + PAUSE_ITEM, // PAUSE_EQUIP right + PAUSE_QUEST, // PAUSE_EQUIP left }; u8 gSlotAgeReqs[] = { @@ -489,26 +555,29 @@ void KaleidoScope_SetDefaultCursor(PlayState* play) { } } -void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 pt) { - pauseCtx->mainState = PAUSE_MAIN_STATE_1; - pauseCtx->unk_1EA = 0; +#define PAGE_SWITCH_PT_LEFT 0 +#define PAGE_SWITCH_PT_RIGHT 2 - if (!pt) { - pauseCtx->mode = pauseCtx->pageIndex * 2 + 1; +void KaleidoScope_SetupPageSwitch(PauseContext* pauseCtx, u8 pt) { + pauseCtx->mainState = PAUSE_MAIN_STATE_SWITCHING_PAGE; + pauseCtx->pageSwitchTimer = 0; + + if (!pt) { // PAGE_SWITCH_PT_LEFT + pauseCtx->nextPageMode = pauseCtx->pageIndex * 2 + 1; Audio_PlaySfxGeneral(NA_SE_SY_WIN_SCROLL_LEFT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); pauseCtx->cursorSpecialPos = PAUSE_CURSOR_PAGE_RIGHT; - } else { - pauseCtx->mode = pauseCtx->pageIndex * 2; + } else { // PAGE_SWITCH_PT_RIGHT + pauseCtx->nextPageMode = pauseCtx->pageIndex * 2; Audio_PlaySfxGeneral(NA_SE_SY_WIN_SCROLL_RIGHT, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); pauseCtx->cursorSpecialPos = PAUSE_CURSOR_PAGE_LEFT; } - gSaveContext.buttonStatus[1] = D_8082AB6C[pauseCtx->pageIndex + pt][1]; - gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex + pt][2]; - gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex + pt][3]; - gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex + pt][4]; + gSaveContext.buttonStatus[1] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + pt][1]; + gSaveContext.buttonStatus[2] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + pt][2]; + gSaveContext.buttonStatus[3] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + pt][3]; + gSaveContext.buttonStatus[4] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + pt][4]; PRINTF("kscope->kscp_pos+pt = %d\n", pauseCtx->pageIndex + pt); @@ -525,12 +594,12 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { } if (CHECK_BTN_ALL(input->press.button, BTN_R)) { - KaleidoScope_SwitchPage(pauseCtx, 2); + KaleidoScope_SetupPageSwitch(pauseCtx, PAGE_SWITCH_PT_RIGHT); return; } if (CHECK_BTN_ALL(input->press.button, BTN_Z)) { - KaleidoScope_SwitchPage(pauseCtx, 0); + KaleidoScope_SetupPageSwitch(pauseCtx, PAGE_SWITCH_PT_LEFT); return; } @@ -538,7 +607,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { if (pauseCtx->stickAdjX < -30) { pauseCtx->pageSwitchInputTimer++; if ((pauseCtx->pageSwitchInputTimer >= 10) || (pauseCtx->pageSwitchInputTimer == 0)) { - KaleidoScope_SwitchPage(pauseCtx, 0); + KaleidoScope_SetupPageSwitch(pauseCtx, PAGE_SWITCH_PT_LEFT); } } else { pauseCtx->pageSwitchInputTimer = -1; @@ -547,7 +616,7 @@ void KaleidoScope_HandlePageToggles(PauseContext* pauseCtx, Input* input) { if (pauseCtx->stickAdjX > 30) { pauseCtx->pageSwitchInputTimer++; if ((pauseCtx->pageSwitchInputTimer >= 10) || (pauseCtx->pageSwitchInputTimer == 0)) { - KaleidoScope_SwitchPage(pauseCtx, 2); + KaleidoScope_SetupPageSwitch(pauseCtx, PAGE_SWITCH_PT_RIGHT); } } else { pauseCtx->pageSwitchInputTimer = -1; @@ -1533,21 +1602,21 @@ void KaleidoScope_UpdateNamePanel(PlayState* play) { } } -void func_808237B4(PlayState* play, Input* input) { +void KaleidoScope_UpdatePageSwitch(PlayState* play, Input* input) { PauseContext* pauseCtx = &play->pauseCtx; - s32 cond = false; - s32 mode; + s32 frameAdvanceFreeze = false; + s32 nextPageMode; - if (ZREG(13) && !CHECK_BTN_ALL(input->press.button, BTN_L)) { - cond = true; + if (R_PAUSE_PAGE_SWITCH_FRAME_ADVANCE_ON && !CHECK_BTN_ALL(input->press.button, BTN_L)) { + frameAdvanceFreeze = true; } - if (!cond) { - mode = pauseCtx->mode; - pauseCtx->eye.x += D_8082ABAC[mode]; - pauseCtx->eye.z += D_8082ABCC[mode]; + if (!frameAdvanceFreeze) { + nextPageMode = pauseCtx->nextPageMode; + pauseCtx->eye.x += sPageSwitchEyeDx[nextPageMode]; + pauseCtx->eye.z += sPageSwitchEyeDz[nextPageMode]; - if (pauseCtx->unk_1EA < 32) { + if (pauseCtx->pageSwitchTimer < ((4 * PAGE_SWITCH_NSTEPS) / 2)) { WREG(16) -= WREG(25) / WREG(6); WREG(17) -= WREG(26) / WREG(6); } else { @@ -1555,11 +1624,11 @@ void func_808237B4(PlayState* play, Input* input) { WREG(17) += WREG(26) / WREG(6); } - pauseCtx->unk_1EA += 4; + pauseCtx->pageSwitchTimer += 4; - if (pauseCtx->unk_1EA == 64) { - pauseCtx->unk_1EA = 0; - pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode]; + if (pauseCtx->pageSwitchTimer == (4 * PAGE_SWITCH_NSTEPS)) { + pauseCtx->pageSwitchTimer = 0; + pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode]; pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; } } @@ -2471,28 +2540,32 @@ void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) { void KaleidoScope_UpdateOpening(PlayState* play) { PauseContext* pauseCtx = &play->pauseCtx; - pauseCtx->eye.x += D_8082ABAC[pauseCtx->mode] * ZREG(46); - pauseCtx->eye.z += D_8082ABCC[pauseCtx->mode] * ZREG(46); - pauseCtx->unk_1EA += 4 * ZREG(46); + pauseCtx->eye.x += sPageSwitchEyeDx[pauseCtx->nextPageMode] * ZREG(46); + pauseCtx->eye.z += sPageSwitchEyeDz[pauseCtx->nextPageMode] * ZREG(46); + pauseCtx->pageSwitchTimer += 4 * ZREG(46); - if (pauseCtx->unk_1EA == (64 * ZREG(47))) { + if (pauseCtx->pageSwitchTimer == (4 * PAGE_SWITCH_NSTEPS * ZREG(47))) { // Finished opening func_80084BF4(play, 1); - gSaveContext.buttonStatus[0] = D_8082AB6C[pauseCtx->pageIndex][0]; - gSaveContext.buttonStatus[1] = D_8082AB6C[pauseCtx->pageIndex][1]; - gSaveContext.buttonStatus[2] = D_8082AB6C[pauseCtx->pageIndex][2]; - gSaveContext.buttonStatus[3] = D_8082AB6C[pauseCtx->pageIndex][3]; - gSaveContext.buttonStatus[4] = D_8082AB6C[pauseCtx->pageIndex][4]; - pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode]; + + gSaveContext.buttonStatus[0] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][0]; + gSaveContext.buttonStatus[1] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][1]; + gSaveContext.buttonStatus[2] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][2]; + gSaveContext.buttonStatus[3] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][3]; + gSaveContext.buttonStatus[4] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][4]; + + pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode]; + pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; pauseCtx->state++; // PAUSE_STATE_MAIN + pauseCtx->alpha = 255; Interface_LoadActionLabelB(play, DO_ACTION_SAVE); - } else if (pauseCtx->unk_1EA == 64) { + } else if (pauseCtx->pageSwitchTimer == (4 * PAGE_SWITCH_NSTEPS * 1)) { // `ZREG(47)` is always 1 so this normally never happens - pauseCtx->pageIndex = D_8082ABEC[pauseCtx->mode]; - pauseCtx->mode = (u16)(pauseCtx->pageIndex * 2) + 1; + pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode]; + pauseCtx->nextPageMode = (u16)(pauseCtx->pageIndex * 2) + 1; } } @@ -3071,7 +3144,7 @@ void KaleidoScope_Update(PlayState* play) { WREG(2) = -6240; func_800F64E0(0); } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { - pauseCtx->mode = 0; + pauseCtx->nextPageMode = 0; pauseCtx->promptChoice = 0; Audio_PlaySfxGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); @@ -3085,8 +3158,8 @@ void KaleidoScope_Update(PlayState* play) { } break; - case PAUSE_MAIN_STATE_1: - func_808237B4(play, play->state.input); + case PAUSE_MAIN_STATE_SWITCHING_PAGE: + KaleidoScope_UpdatePageSwitch(play, play->state.input); break; case PAUSE_MAIN_STATE_2: @@ -3118,7 +3191,7 @@ void KaleidoScope_Update(PlayState* play) { } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; - pauseCtx->mode = 0; + pauseCtx->nextPageMode = 0; pauseCtx->promptChoice = 0; Audio_PlaySfxGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); @@ -3168,7 +3241,7 @@ void KaleidoScope_Update(PlayState* play) { } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF); pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE; - pauseCtx->mode = 0; + pauseCtx->nextPageMode = 0; pauseCtx->promptChoice = 0; Audio_PlaySfxGeneral(NA_SE_SY_DECIDE, &gSfxDefaultPos, 4, &gSfxDefaultFreqAndVolScale, &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb); diff --git a/tools/Makefile b/tools/Makefile index 4d342e2485..c4688f6646 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -1,5 +1,5 @@ CFLAGS := -Wall -Wextra -pedantic -std=c99 -g -O2 -PROGRAMS := elf2rom makeromfs mkdmadata mkldscript reloc_prereq vtxdis yaz0 +PROGRAMS := elf2rom makeromfs mkdmadata mkldscript reloc_prereq vtxdis ifeq ($(shell command -v clang >/dev/null 2>&1; echo $$?),0) CC := clang @@ -36,7 +36,6 @@ mkdmadata_SOURCES := mkdmadata.c spec.c util.c mkldscript_SOURCES := mkldscript.c spec.c util.c reloc_prereq_SOURCES := reloc_prereq.c spec.c util.c vtxdis_SOURCES := vtxdis.c -yaz0_SOURCES := yaz0tool.c yaz0.c util.c define COMPILE = diff --git a/tools/check_ordering.py b/tools/check_ordering.py index cfd2913780..83eecfacb4 100755 --- a/tools/check_ordering.py +++ b/tools/check_ordering.py @@ -131,6 +131,7 @@ def main(): if not ( mapfile_segment.name.startswith("..boot") or mapfile_segment.name.startswith("..code") + or mapfile_segment.name.startswith("..buffers") or mapfile_segment.name.startswith("..ovl_") ): continue @@ -152,13 +153,15 @@ def main(): base_value = read_u32(base, file.vrom + reloc.offset_32) build_value = read_u32(build, file.vrom + reloc.offset_32) elif reloc.offset_hi16 is not None and reloc.offset_lo16 is not None: - if read_u16(base, file.vrom + reloc.offset_hi16) != read_u16( - build, file.vrom + reloc.offset_hi16 - ) or read_u16(base, file.vrom + reloc.offset_hi16) != read_u16( - build, file.vrom + reloc.offset_hi16 + if ( + read_u16(base, file.vrom + reloc.offset_hi16) + != read_u16(build, file.vrom + reloc.offset_hi16) + ) or ( + read_u16(base, file.vrom + reloc.offset_lo16) + != read_u16(build, file.vrom + reloc.offset_lo16) ): print( - f"Error: Reference to {reloc.name} in {file.filepath} is in a shifted portion of the ROM.\n" + f"Error: Reference to {reloc.name} in {file.filepath} is in a shifted (or non-matching even ignoring relocs) portion of the ROM.\n" "Please ensure that the only differences between the baserom and the current build are due to data ordering.", file=sys.stderr, ) @@ -186,7 +189,9 @@ def main(): for mapfile_segment in source_code_segments: for file in mapfile_segment: pointers_in_section = [ - p for p in pointers if file.vram <= p.build_value < file.vram + file.size + p + for p in pointers + if file.vram <= p.build_value < file.vram + file.size ] if not pointers_in_section: continue diff --git a/tools/mkldscript.c b/tools/mkldscript.c index 9157bc79dc..199c77eb74 100644 --- a/tools/mkldscript.c +++ b/tools/mkldscript.c @@ -42,10 +42,6 @@ static void write_ld_script(FILE *fout) // initialized data (.text, .data, .rodata, .sdata) - // Increment the start of the section - //if (seg->fields & (1 << STMT_increment)) - //fprintf(fout, " . += 0x%08X;\n", seg->increment); - fprintf(fout, " _%sSegmentRomStartTemp = _RomSize;\n" " _%sSegmentRomStart = _%sSegmentRomStartTemp;\n" " ..%s ", seg->name, seg->name, seg->name, seg->name); @@ -68,10 +64,13 @@ static void write_ld_script(FILE *fout) for (j = 0; j < seg->includesCount; j++) { - fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); - if (seg->includes[j].linkerPadding != 0) - fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding); - fprintf(fout, " . = ALIGN(0x10);\n"); + if (!seg->includes[j].dataOnlyWithinRodata) + { + fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); + if (seg->includes[j].linkerPadding != 0) + fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding); + fprintf(fout, " . = ALIGN(0x10);\n"); + } } fprintf(fout, " _%sSegmentTextEnd = .;\n", seg->name); @@ -82,20 +81,11 @@ static void write_ld_script(FILE *fout) for (j = 0; j < seg->includesCount; j++) { - if (!seg->includes[j].dataWithRodata) + if (!seg->includes[j].dataOnlyWithinRodata && !seg->includes[j].noData) fprintf(fout, " %s (.data)\n" " . = ALIGN(0x10);\n", seg->includes[j].fpath); } - /* - for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.rodata)\n", seg->includes[j].fpath); - - for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sdata)\n", seg->includes[j].fpath); - */ - - //fprintf(fout, " . = ALIGN(0x10);\n"); fprintf(fout, " _%sSegmentDataEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, seg->name, seg->name); @@ -104,7 +94,7 @@ static void write_ld_script(FILE *fout) for (j = 0; j < seg->includesCount; j++) { - if (seg->includes[j].dataWithRodata) + if (seg->includes[j].dataOnlyWithinRodata) fprintf(fout, " %s (.data)\n" " . = ALIGN(0x10);\n", seg->includes[j].fpath); @@ -116,11 +106,12 @@ static void write_ld_script(FILE *fout) // the beginning of the entire rodata area in order to remain consistent. // Inconsistencies will lead to various .rodata reloc crashes as a result of // either missing relocs or wrong relocs. - fprintf(fout, " %s (.rodata)\n" - " %s (.rodata.str*)\n" - " %s (.rodata.cst*)\n" - " . = ALIGN(0x10);\n", - seg->includes[j].fpath, seg->includes[j].fpath, seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.rodata)\n" + " %s (.rodata.str*)\n" + " %s (.rodata.cst*)\n" + " . = ALIGN(0x10);\n", + seg->includes[j].fpath, seg->includes[j].fpath, seg->includes[j].fpath); } fprintf(fout, " _%sSegmentRoDataEnd = .;\n", seg->name); @@ -130,15 +121,17 @@ static void write_ld_script(FILE *fout) fprintf(fout, " _%sSegmentSDataStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sdata)\n" - " . = ALIGN(0x10);\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.sdata)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); fprintf(fout, " _%sSegmentSDataEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentOvlStart = .;\n", seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name); @@ -166,20 +159,24 @@ static void write_ld_script(FILE *fout) seg->name, seg->name, seg->name, seg->name); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.sbss)\n" - " . = ALIGN(0x10);\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.sbss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.scommon)\n" - " . = ALIGN(0x10);\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.scommon)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (.bss)\n" - " . = ALIGN(0x10);\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (.bss)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); for (j = 0; j < seg->includesCount; j++) - fprintf(fout, " %s (COMMON)\n" - " . = ALIGN(0x10);\n", seg->includes[j].fpath); + if (!seg->includes[j].dataOnlyWithinRodata) + fprintf(fout, " %s (COMMON)\n" + " . = ALIGN(0x10);\n", seg->includes[j].fpath); fprintf(fout, " . = ALIGN(0x10);\n" " _%sSegmentBssEnd = .;\n" @@ -187,25 +184,6 @@ static void write_ld_script(FILE *fout) " }\n" " _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n", seg->name, seg->name, seg->name, seg->name, seg->name); - - // Increment the end of the segment - //if (seg->fields & (1 << STMT_increment)) - //fprintf(fout, " . += 0x%08X;\n", seg->increment); - - //fprintf(fout, " ..%s.ovl ADDR(..%s) + SIZEOF(..%s) :\n" - // /*" ..%s.bss :\n"*/ - // " {\n", - // seg->name, seg->name, seg->name); - //fprintf(fout, " _%sSegmentOvlStart = .;\n", seg->name); - - //for (j = 0; j < seg->includesCount; j++) - // fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); - - ////fprintf(fout, " . = ALIGN(0x10);\n"); - - //fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name); - - //fprintf(fout, "\n }\n"); } fputs(" _RomEnd = _RomSize;\n\n", fout); diff --git a/tools/spec.c b/tools/spec.c index 39dd088ec8..b13455867c 100644 --- a/tools/spec.c +++ b/tools/spec.c @@ -136,7 +136,8 @@ static const char *const stmtNames[] = [STMT_entry] = "entry", [STMT_flags] = "flags", [STMT_include] = "include", - [STMT_include_data_with_rodata] = "include_data_with_rodata", + [STMT_include_data_only_within_rodata] = "include_data_only_within_rodata", + [STMT_include_no_data] = "include_no_data", [STMT_name] = "name", [STMT_number] = "number", [STMT_romalign] = "romalign", @@ -158,7 +159,8 @@ STMTId get_stmt_id_by_stmt_name(const char *stmtName, int lineNum) { bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, int lineNum) { // ensure no duplicates (except for 'include' or 'pad_text') - if (stmt != STMT_include && stmt != STMT_include_data_with_rodata && stmt != STMT_pad_text && + if (stmt != STMT_include && stmt != STMT_include_data_only_within_rodata && + stmt != STMT_include_no_data && stmt != STMT_pad_text && (currSeg->fields & (1 << stmt))) util_fatal_error("line %i: duplicate '%s' statement", lineNum, stmtNames[stmt]); @@ -211,7 +213,8 @@ bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, i util_fatal_error("line %i: alignment is not a power of two", lineNum); break; case STMT_include: - case STMT_include_data_with_rodata: + case STMT_include_data_only_within_rodata: + case STMT_include_no_data: currSeg->includesCount++; currSeg->includes = realloc(currSeg->includes, currSeg->includesCount * sizeof(*currSeg->includes)); @@ -219,7 +222,8 @@ bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, i util_fatal_error("line %i: invalid filename", lineNum); currSeg->includes[currSeg->includesCount - 1].linkerPadding = 0; - currSeg->includes[currSeg->includesCount - 1].dataWithRodata = (stmt == STMT_include_data_with_rodata); + currSeg->includes[currSeg->includesCount - 1].dataOnlyWithinRodata = (stmt == STMT_include_data_only_within_rodata); + currSeg->includes[currSeg->includesCount - 1].noData = (stmt == STMT_include_no_data); break; case STMT_increment: if (!parse_number(args, &currSeg->increment)) diff --git a/tools/spec.h b/tools/spec.h index f0a16eeb4f..6b01b34755 100644 --- a/tools/spec.h +++ b/tools/spec.h @@ -14,7 +14,8 @@ typedef enum { STMT_entry, STMT_flags, STMT_include, - STMT_include_data_with_rodata, + STMT_include_data_only_within_rodata, + STMT_include_no_data, STMT_name, STMT_number, STMT_romalign, @@ -34,7 +35,8 @@ enum { struct Include { char* fpath; int linkerPadding; - uint8_t dataWithRodata; + bool dataOnlyWithinRodata; + bool noData; }; typedef struct Segment { diff --git a/tools/yaz0.c b/tools/yaz0.c deleted file mode 100644 index 5b3156e443..0000000000 --- a/tools/yaz0.c +++ /dev/null @@ -1,238 +0,0 @@ -#include -#include -#include -#include - -#include "yaz0.h" - -// decoder implementation by thakis of http://www.amnoid.de - -// src points to the yaz0 source data (to the "real" source data, not at the header!) -// dst points to a buffer uncompressedSize bytes large (you get uncompressedSize from -// the second 4 bytes in the Yaz0 header). -void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize) -{ - int srcPlace = 0, dstPlace = 0; // current read/write positions - - unsigned int validBitCount = 0; // number of valid bits left in "code" byte - uint8_t currCodeByte; - while (dstPlace < uncompressedSize) - { - // read new "code" byte if the current one is used up - if (validBitCount == 0) - { - currCodeByte = src[srcPlace]; - ++srcPlace; - validBitCount = 8; - } - - if ((currCodeByte & 0x80) != 0) - { - // straight copy - dst[dstPlace] = src[srcPlace]; - dstPlace++; - srcPlace++; - } - else - { - // RLE part - uint8_t byte1 = src[srcPlace]; - uint8_t byte2 = src[srcPlace + 1]; - srcPlace += 2; - - unsigned int dist = ((byte1 & 0xF) << 8) | byte2; - unsigned int copySource = dstPlace - (dist + 1); - - unsigned int numBytes = byte1 >> 4; - if (numBytes == 0) - { - numBytes = src[srcPlace] + 0x12; - srcPlace++; - } - else - { - numBytes += 2; - } - - // copy run - for (unsigned int i = 0; i < numBytes; ++i) - { - dst[dstPlace] = dst[copySource]; - copySource++; - dstPlace++; - } - } - - // use next bit from "code" byte - currCodeByte <<= 1; - validBitCount -= 1; - } -} - -// encoder implementation by shevious, with bug fixes by notwa - -typedef uint32_t uint32_t; -typedef uint8_t uint8_t; - -#define MAX_RUNLEN (0xFF + 0x12) - -// simple and straight encoding scheme for Yaz0 -static uint32_t simpleEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos) -{ - int numBytes = 1; - int matchPos = 0; - - int startPos = pos - 0x1000; - int end = size - pos; - - if (startPos < 0) - startPos = 0; - - // maximum runlength for 3 byte encoding - if (end > MAX_RUNLEN) - end = MAX_RUNLEN; - - for (int i = startPos; i < pos; i++) - { - int j; - - for (j = 0; j < end; j++) - { - if (src[i + j] != src[j + pos]) - break; - } - if (j > numBytes) - { - numBytes = j; - matchPos = i; - } - } - - *pMatchPos = matchPos; - - if (numBytes == 2) - numBytes = 1; - - return numBytes; -} - -// a lookahead encoding scheme for ngc Yaz0 -static uint32_t nintendoEnc(uint8_t *src, int size, int pos, uint32_t *pMatchPos) -{ - uint32_t numBytes = 1; - static uint32_t numBytes1; - static uint32_t matchPos; - static int prevFlag = 0; - - // if prevFlag is set, it means that the previous position - // was determined by look-ahead try. - // so just use it. this is not the best optimization, - // but nintendo's choice for speed. - if (prevFlag == 1) - { - *pMatchPos = matchPos; - prevFlag = 0; - return numBytes1; - } - - prevFlag = 0; - numBytes = simpleEnc(src, size, pos, &matchPos); - *pMatchPos = matchPos; - - // if this position is RLE encoded, then compare to copying 1 byte and next position(pos+1) encoding - if (numBytes >= 3) - { - numBytes1 = simpleEnc(src, size, pos + 1, &matchPos); - // if the next position encoding is +2 longer than current position, choose it. - // this does not guarantee the best optimization, but fairly good optimization with speed. - if (numBytes1 >= numBytes + 2) - { - numBytes = 1; - prevFlag = 1; - } - } - return numBytes; -} - -int yaz0_encode(uint8_t *src, uint8_t *dst, int srcSize) -{ - int srcPos = 0; - int dstPos = 0; - int bufPos = 0; - - uint8_t buf[24]; // 8 codes * 3 bytes maximum - - uint32_t validBitCount = 0; // number of valid bits left in "code" byte - uint8_t currCodeByte = 0; // a bitfield, set bits meaning copy, unset meaning RLE - - while (srcPos < srcSize) - { - uint32_t numBytes; - uint32_t matchPos; - - numBytes = nintendoEnc(src, srcSize, srcPos, &matchPos); - if (numBytes < 3) - { - // straight copy - buf[bufPos] = src[srcPos]; - bufPos++; - srcPos++; - //set flag for straight copy - currCodeByte |= (0x80 >> validBitCount); - } - else - { - //RLE part - uint32_t dist = srcPos - matchPos - 1; - uint8_t byte1, byte2, byte3; - - if (numBytes >= 0x12) // 3 byte encoding - { - byte1 = 0 | (dist >> 8); - byte2 = dist & 0xFF; - buf[bufPos++] = byte1; - buf[bufPos++] = byte2; - // maximum runlength for 3 byte encoding - if (numBytes > MAX_RUNLEN) - numBytes = MAX_RUNLEN; - byte3 = numBytes - 0x12; - buf[bufPos++] = byte3; - } - else // 2 byte encoding - { - byte1 = ((numBytes - 2) << 4) | (dist >> 8); - byte2 = dist & 0xFF; - buf[bufPos++] = byte1; - buf[bufPos++] = byte2; - } - srcPos += numBytes; - } - - validBitCount++; - - // write eight codes - if (validBitCount == 8) - { - dst[dstPos++] = currCodeByte; - for (int j = 0; j < bufPos; j++) - dst[dstPos++] = buf[j]; - - currCodeByte = 0; - validBitCount = 0; - bufPos = 0; - } - } - - if (validBitCount > 0) - { - dst[dstPos++] = currCodeByte; - for (int j = 0; j < bufPos; j++) - dst[dstPos++] = buf[j]; - - currCodeByte = 0; - validBitCount = 0; - bufPos = 0; - } - - return dstPos; -} diff --git a/tools/yaz0.h b/tools/yaz0.h deleted file mode 100644 index 0cc3703ec9..0000000000 --- a/tools/yaz0.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _YAZ0_H_ -#define _YAZ0_H_ - -int yaz0_encode2(uint8_t *src, uint8_t *dest, int uncompressedSize); - -void yaz0_decode(uint8_t* src, uint8_t* dst, int uncompressedSize); - -int yaz0_encode(uint8_t *src, uint8_t *dest, int srcSize); - -#endif // _YAZ0_H_ diff --git a/tools/yaz0tool.c b/tools/yaz0tool.c deleted file mode 100644 index b21468fa20..0000000000 --- a/tools/yaz0tool.c +++ /dev/null @@ -1,201 +0,0 @@ -#ifdef __linux__ -#define _POSIX_C_SOURCE 199309L -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include "yaz0.h" -#include "util.h" - -// TODO: Windows support -static unsigned long int get_time_milliseconds(void) -{ -#ifdef __linux__ - struct timespec tspec; - - clock_gettime(CLOCK_MONOTONIC, &tspec); - return (tspec.tv_sec * 1000) + tspec.tv_nsec / 1000000; -#else - // dummy - return 0; -#endif -} - -static void print_report(unsigned long int time, size_t compSize, size_t uncompSize) -{ - unsigned int minutes = time / (1000 * 60); - float seconds = (float)(time % (1000 * 60)) / 1000; - - printf("compression ratio: %.2fKiB / %.2fKiB (%.2f%%)\n" - "time: %um %.3fs\n", - (float)compSize / 1024, (float)uncompSize / 1024, - (float)compSize * 100 / (float)uncompSize, - minutes, seconds); -} - -static void compress_file(const char *inputFileName, const char *outputFileName, bool verbose) -{ - size_t uncompSize; - uint8_t *input = util_read_whole_file(inputFileName, &uncompSize); - uint8_t *output = malloc(uncompSize * 2); // TODO: figure out how much space we need - unsigned long int time; - - if (verbose) - { - printf("decompressing %s\n", inputFileName); - time = get_time_milliseconds(); - } - - // compress data - size_t compSize = yaz0_encode(input, output, uncompSize); - - if (verbose) - time = get_time_milliseconds() - time; - - // make Yaz0 header - uint8_t header[16] = {0}; - header[0] = 'Y'; - header[1] = 'a'; - header[2] = 'z'; - header[3] = '0'; - util_write_uint32_be(header + 4, uncompSize); - - // write output file - FILE *outFile = fopen(outputFileName, "wb"); - if (outFile == NULL) - util_fatal_error("failed to open file '%s' for writing", outputFileName); - fwrite(header, sizeof(header), 1, outFile); - fwrite(output, compSize, 1, outFile); - fclose(outFile); - - free(input); - free(output); - - if (verbose) - print_report(time, compSize, uncompSize); -} - -static void decompress_file(const char *inputFileName, const char *outputFileName, bool verbose) -{ - size_t compSize; - uint8_t *input = util_read_whole_file(inputFileName, &compSize); - size_t uncompSize; - uint8_t *output; - unsigned long int time = 0; - - // read header - if (input[0] != 'Y' || input[1] != 'a' || input[2] != 'z' || input[3] != '0') - util_fatal_error("file '%s' does not have a valid Yaz0 header", inputFileName); - uncompSize = util_read_uint32_be(input + 4); - - // decompress data - output = malloc(uncompSize); - - if (verbose) - { - printf("decompressing %s\n", inputFileName); - time = get_time_milliseconds(); - } - - yaz0_decode(input + 16, output, uncompSize); - - if (verbose) - time = get_time_milliseconds() - time; - - // write output file - FILE *outFile = fopen(outputFileName, "wb"); - fwrite(output, uncompSize, 1, outFile); - fclose(outFile); - - free(input); - free(output); - - if (verbose) - print_report(time, compSize, uncompSize); -} - -static void usage(const char *execName) -{ - printf("Yaz0 compressor/decompressor\n" - "usage: %s [-d] [-h] [-v] INPUT_FILE OUTPUT_FILE\n" - "compresses INPUT_FILE using Yaz0 encoding and writes output to OUTPUT_FILE\n" - "Available options:\n" - "-d: decompresses INPUT_FILE, a Yaz0 compressed file, and writes decompressed\n" - " output to OUTPUT_FILE\n" - "-v: prints verbose output (compression ratio and time)\n" - "-h: shows this help message\n", - execName); -} - -int main(int argc, char **argv) -{ - int i; - const char *inputFileName = NULL; - const char *outputFileName = NULL; - bool decompress = false; - bool verbose = false; - - // parse arguments - for (i = 1; i < argc; i++) - { - char *arg = argv[i]; - - if (arg[0] == '-') - { - if (strcmp(arg, "-d") == 0) - decompress = true; - else if (strcmp(arg, "-v") == 0) - verbose = true; - else if (strcmp(arg, "-h") == 0) - { - usage(argv[0]); - return 0; - } - else - { - printf("unknown option %s\n", arg); - usage(argv[0]); - return 1; - } - } - else - { - if (inputFileName == NULL) - inputFileName = arg; - else if (outputFileName == NULL) - outputFileName = arg; - else - { - puts("too many files specified"); - usage(argv[0]); - return 1; - } - } - } - - if (inputFileName == NULL) - { - puts("no input file specified"); - usage(argv[0]); - return 1; - } - if (outputFileName == NULL) - { - puts("no output file specified"); - usage(argv[0]); - return 1; - } - - if (decompress) - decompress_file(inputFileName, outputFileName, verbose); - else - compress_file(inputFileName, outputFileName, verbose); - - return 0; -}