1
0
Fork 0
mirror of https://github.com/zeldaret/oot.git synced 2025-07-16 12:54:40 +00:00

Merge commit 'b2d80568b9' into doc_pause_menu

This commit is contained in:
Dragorn421 2024-08-01 21:29:29 +02:00
commit dc599911db
No known key found for this signature in database
GPG key ID: 381AEBAF3D429335
78 changed files with 5742 additions and 5952 deletions

View file

@ -27,6 +27,7 @@ RUN_CC_CHECK := 1
CFLAGS ?= CFLAGS ?=
CPPFLAGS ?= CPPFLAGS ?=
CPP_DEFINES ?=
# ORIG_COMPILER cannot be combined with a non-IDO compiler. Check for this case and error out if found. # ORIG_COMPILER cannot be combined with a non-IDO compiler. Check for this case and error out if found.
ifneq ($(COMPILER),ido) ifneq ($(COMPILER),ido)
@ -36,8 +37,7 @@ ifneq ($(COMPILER),ido)
endif endif
ifeq ($(COMPILER),gcc) ifeq ($(COMPILER),gcc)
CFLAGS += -DCOMPILER_GCC CPP_DEFINES += -DCOMPILER_GCC
CPPFLAGS += -DCOMPILER_GCC
NON_MATCHING := 1 NON_MATCHING := 1
endif endif
@ -46,8 +46,7 @@ endif
MIPS_BINUTILS_PREFIX := mips-linux-gnu- MIPS_BINUTILS_PREFIX := mips-linux-gnu-
ifeq ($(NON_MATCHING),1) ifeq ($(NON_MATCHING),1)
CFLAGS += -DNON_MATCHING -DAVOID_UB CPP_DEFINES += -DNON_MATCHING -DAVOID_UB
CPPFLAGS += -DNON_MATCHING -DAVOID_UB
COMPARE := 0 COMPARE := 0
endif endif
@ -57,12 +56,10 @@ ifeq ($(VERSION),gc-eu)
COMPARE := 0 COMPARE := 0
else ifeq ($(VERSION),gc-eu-mq) else ifeq ($(VERSION),gc-eu-mq)
DEBUG := 0 DEBUG := 0
CFLAGS += -DOOT_MQ CPP_DEFINES += -DOOT_MQ
CPPFLAGS += -DOOT_MQ
else ifeq ($(VERSION),gc-eu-mq-dbg) else ifeq ($(VERSION),gc-eu-mq-dbg)
DEBUG := 1 DEBUG := 1
CFLAGS += -DOOT_MQ CPP_DEFINES += -DOOT_MQ
CPPFLAGS += -DOOT_MQ
else else
$(error Unsupported version $(VERSION)) $(error Unsupported version $(VERSION))
endif endif
@ -78,12 +75,10 @@ MAKE = make
CPPFLAGS += -P -xc -fno-dollars-in-identifiers CPPFLAGS += -P -xc -fno-dollars-in-identifiers
ifeq ($(DEBUG),1) ifeq ($(DEBUG),1)
CFLAGS += -DOOT_DEBUG=1 CPP_DEFINES += -DOOT_DEBUG=1
CPPFLAGS += -DOOT_DEBUG=1
OPTFLAGS := -O2 OPTFLAGS := -O2
else else
CFLAGS += -DNDEBUG -DOOT_DEBUG=0 CPP_DEFINES += -DNDEBUG -DOOT_DEBUG=0
CPPFLAGS += -DNDEBUG -DOOT_DEBUG=0
OPTFLAGS := -O2 -g3 OPTFLAGS := -O2 -g3
endif endif
@ -154,10 +149,21 @@ PYTHON ?= $(VENV)/bin/python3
# preprocessor for this because it won't substitute inside string literals. # preprocessor for this because it won't substitute inside string literals.
SPEC_REPLACE_VARS := sed -e 's|$$(BUILD_DIR)|$(BUILD_DIR)|g' SPEC_REPLACE_VARS := sed -e 's|$$(BUILD_DIR)|$(BUILD_DIR)|g'
CFLAGS += $(CPP_DEFINES)
CPPFLAGS += $(CPP_DEFINES)
ifeq ($(COMPILER),gcc) ifeq ($(COMPILER),gcc)
OPTFLAGS := -Os -ffast-math -fno-unsafe-math-optimizations OPTFLAGS := -Os -ffast-math -fno-unsafe-math-optimizations
endif endif
# TODO PL and DOWHILE should be disabled for non-gamecube
GBI_DEFINES := -DF3DEX_GBI_2 -DF3DEX_GBI_PL -DGBI_DOWHILE
ifeq ($(DEBUG),1)
GBI_DEFINES += -DGBI_DEBUG
endif
CFLAGS += $(GBI_DEFINES)
ASFLAGS := -march=vr4300 -32 -no-pad-sections -Iinclude ASFLAGS := -march=vr4300 -32 -no-pad-sections -Iinclude
ifeq ($(COMPILER),gcc) ifeq ($(COMPILER),gcc)
@ -174,7 +180,7 @@ endif
ifeq ($(COMPILER),ido) ifeq ($(COMPILER),ido)
# Have CC_CHECK pretend to be a MIPS compiler # Have CC_CHECK pretend to be a MIPS compiler
MIPS_BUILTIN_DEFS := -D_MIPS_ISA_MIPS2=2 -D_MIPS_ISA=_MIPS_ISA_MIPS2 -D_ABIO32=1 -D_MIPS_SIM=_ABIO32 -D_MIPS_SZINT=32 -D_MIPS_SZLONG=32 -D_MIPS_SZPTR=32 MIPS_BUILTIN_DEFS := -D_MIPS_ISA_MIPS2=2 -D_MIPS_ISA=_MIPS_ISA_MIPS2 -D_ABIO32=1 -D_MIPS_SIM=_ABIO32 -D_MIPS_SZINT=32 -D_MIPS_SZLONG=32 -D_MIPS_SZPTR=32
CC_CHECK = gcc -fno-builtin -fsyntax-only -funsigned-char -std=gnu90 -D_LANGUAGE_C -DNON_MATCHING -DOOT_DEBUG=1 $(MIPS_BUILTIN_DEFS) $(INC) $(CHECK_WARNINGS) CC_CHECK = gcc -fno-builtin -fsyntax-only -funsigned-char -std=gnu90 -D_LANGUAGE_C $(CPP_DEFINES) $(MIPS_BUILTIN_DEFS) $(GBI_DEFINES) $(INC) $(CHECK_WARNINGS)
ifeq ($(shell getconf LONG_BIT), 32) ifeq ($(shell getconf LONG_BIT), 32)
# Work around memory allocation bug in QEMU # Work around memory allocation bug in QEMU
export QEMU_GUEST_BASE := 1 export QEMU_GUEST_BASE := 1
@ -243,7 +249,7 @@ $(BUILD_DIR)/src/boot/stackcheck.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/code/__osMalloc.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_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/rand.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/code/gfxprint.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/gfxprint.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/code/jpegutils.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/code/jpegutils.o: OPTFLAGS := -O2
@ -303,7 +309,7 @@ $(BUILD_DIR)/src/libultra/libc/%.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/libultra/rmon/%.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/libultra/rmon/%.o: OPTFLAGS := -O2
$(BUILD_DIR)/src/libultra/gu/%.o: OPTFLAGS := -O2 $(BUILD_DIR)/src/libultra/gu/%.o: OPTFLAGS := -O2
$(BUILD_DIR)/assets/misc/z_select_static/%.o: CFLAGS += -DF3DEX_GBI $(BUILD_DIR)/assets/misc/z_select_static/%.o: GBI_DEFINES := -DF3DEX_GBI
$(BUILD_DIR)/src/libultra/gu/%.o: CC := $(CC_OLD) $(BUILD_DIR)/src/libultra/gu/%.o: CC := $(CC_OLD)
$(BUILD_DIR)/src/libultra/io/%.o: CC := $(CC_OLD) $(BUILD_DIR)/src/libultra/io/%.o: CC := $(CC_OLD)
@ -370,7 +376,7 @@ venv:
setup: venv setup: venv
$(MAKE) -C tools $(MAKE) -C tools
$(PYTHON) tools/decompress_baserom.py $(VERSION) $(PYTHON) tools/decompress_baserom.py $(VERSION)
$(PYTHON) tools/extract_baserom.py $(BASEROM_DIR)/baserom-decompressed.z64 -o $(EXTRACTED_DIR)/baserom --dmadata-start `cat $(BASEROM_DIR)/dmadata_start.txt` --dmadata-names $(BASEROM_DIR)/dmadata_names.txt $(PYTHON) tools/extract_baserom.py $(BASEROM_DIR)/baserom-decompressed.z64 --oot-version $(VERSION) -o $(EXTRACTED_DIR)/baserom
$(PYTHON) tools/msgdis.py --oot-version $(VERSION) --text-out $(EXTRACTED_DIR)/text/message_data.h --staff-text-out $(EXTRACTED_DIR)/text/message_data_staff.h $(PYTHON) tools/msgdis.py --oot-version $(VERSION) --text-out $(EXTRACTED_DIR)/text/message_data.h --staff-text-out $(EXTRACTED_DIR)/text/message_data_staff.h
# TODO: for now, we only extract assets from the Debug ROM # TODO: for now, we only extract assets from the Debug ROM
ifeq ($(VERSION),gc-eu-mq-dbg) ifeq ($(VERSION),gc-eu-mq-dbg)

View file

@ -0,0 +1,7 @@
dmadata_start: 0x12F70
variables:
gMtxClear: 0x8012DB20
sNesMessageEntryTable: 0x8014B320
sGerMessageEntryTable: 0x8014F548
sFraMessageEntryTable: 0x80151658
sStaffMessageEntryTable: 0x80153768

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
0x12f70

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
dmadata_start: 0x7170
variables:
gMtxClear: 0x800FBC00
sNesMessageEntryTable: 0x801077F0
sGerMessageEntryTable: 0x8010BA18
sFraMessageEntryTable: 0x8010DB28
sStaffMessageEntryTable: 0x8010FC38

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
0x07170

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,7 @@
dmadata_start: 0x7170
variables:
gMtxClear: 0x800FBC20
sNesMessageEntryTable: 0x80107810
sGerMessageEntryTable: 0x8010BA38
sFraMessageEntryTable: 0x8010DB48
sStaffMessageEntryTable: 0x8010FC58

File diff suppressed because it is too large Load diff

View file

@ -1 +0,0 @@
0x07170

1511
baseroms/gc-eu/segments.csv Normal file

File diff suppressed because it is too large Load diff

17
include/fp_math.h Normal file
View file

@ -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

View file

@ -4,23 +4,6 @@
#include "z64.h" #include "z64.h"
#include "macros.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 cleararena(void);
void bootproc(void); void bootproc(void);
void Main_ThreadEntry(void* arg); void Main_ThreadEntry(void* arg);
@ -839,41 +822,6 @@ s32 Environment_IsForcedSequenceDisabled(void);
void Environment_PlayStormNatureAmbience(PlayState* play); void Environment_PlayStormNatureAmbience(PlayState* play);
void Environment_StopStormNatureAmbience(PlayState* play); void Environment_StopStormNatureAmbience(PlayState* play);
void Environment_WarpSongLeave(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_InitMeter(PlayState* play);
void Health_UpdateMeter(PlayState* play); void Health_UpdateMeter(PlayState* play);
void Health_DrawMeter(PlayState* play); void Health_DrawMeter(PlayState* play);
@ -1346,80 +1294,9 @@ void Main(void* arg);
void SysCfb_Init(s32 n64dd); void SysCfb_Init(s32 n64dd);
void* SysCfb_GetFbPtr(s32 idx); void* SysCfb_GetFbPtr(s32 idx);
void* SysCfb_GetFbEnd(void); 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_DrawSphere(PlayState* play, Sphere16* sph);
void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl); 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_Init(GameState* gameState);
void Matrix_Push(void); void Matrix_Push(void);
void Matrix_Pop(void); void Matrix_Pop(void);
@ -1681,24 +1558,7 @@ void Audio_Init(void);
void Audio_InitSound(void); void Audio_InitSound(void);
void func_800F7170(void); void func_800F7170(void);
void func_800F71BC(s32 arg0); 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_StartSequence(u8 seqPlayerIndex, u8 seqId, u8 seqArgs, u16 fadeInDuration);
void Audio_StopSequence(u8 seqPlayerIndex, u16 fadeOutDuration); void Audio_StopSequence(u8 seqPlayerIndex, u16 fadeOutDuration);
void Audio_QueueSeqCmd(u32 cmd); void Audio_QueueSeqCmd(u32 cmd);
@ -1748,20 +1608,7 @@ s8 PadUtils_GetRelX(Input* input);
s8 PadUtils_GetRelY(Input* input); s8 PadUtils_GetRelY(Input* input);
void PadUtils_UpdateRelXY(Input* input); void PadUtils_UpdateRelXY(Input* input);
s32 PadSetup_Init(OSMesgQueue* mq, u8* outMask, OSContStatus* status); 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_Malloc(u32 size);
void* SystemArena_MallocR(u32 size); void* SystemArena_MallocR(u32 size);
void* SystemArena_Realloc(void* ptr, u32 newSize); 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_FreeDebug(void* ptr, const char* file, int line);
void SystemArena_Display(void); void SystemArena_Display(void);
#endif #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 __osMallocInit(Arena* arena, void* start, u32 size);
void __osMallocAddBlock(Arena* arena, void* start, s32 size); void __osMallocAddBlock(Arena* arena, void* start, s32 size);
void __osMallocCleanup(Arena* arena); void __osMallocCleanup(Arena* arena);
@ -1825,8 +1665,6 @@ s32 JpegDecoder_ParseNextSymbol(JpegHuffmanTable* hTable, s16* outCoeff, s8* out
u16 JpegDecoder_ReadBits(u8 len); u16 JpegDecoder_ReadBits(u8 len);
s32 osPfsFreeBlocks(OSPfs* pfs, s32* leftoverBytes); s32 osPfsFreeBlocks(OSPfs* pfs, s32* leftoverBytes);
void guScale(Mtx* m, f32 x, f32 y, f32 z); void guScale(Mtx* m, f32 x, f32 y, f32 z);
f32 sinf(f32 angle);
s16 sins(u16 angle);
OSTask* _VirtualToPhysicalTask(OSTask* intp); OSTask* _VirtualToPhysicalTask(OSTask* intp);
void osSpTaskLoad(OSTask* intp); void osSpTaskLoad(OSTask* intp);
void osSpTaskStartGo(OSTask* tp); 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); 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 guOrthoF(f32[4][4], f32, f32, f32, f32, f32, f32, f32);
void guOrtho(Mtx*, 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); void osViSetEvent(OSMesgQueue* mq, OSMesg msg, u32 retraceCount);
s32 osPfsIsPlug(OSMesgQueue* mq, u8* pattern); s32 osPfsIsPlug(OSMesgQueue* mq, u8* pattern);
void __osPfsRequestData(u8 cmd); void __osPfsRequestData(u8 cmd);

View file

@ -1,7 +1,9 @@
#ifndef ICHAIN_H #ifndef ICHAIN_H
#define ICHAIN_H #define ICHAIN_H
#include "libc/stddef.h" #include "ultra64.h"
struct Actor;
typedef struct { typedef struct {
u32 cont: 1; u32 cont: 1;
@ -55,4 +57,6 @@ typedef enum {
#define ICHAIN_CONTINUE 1 #define ICHAIN_CONTINUE 1
#define ICHAIN_STOP 0 #define ICHAIN_STOP 0
void Actor_ProcessInitChain(struct Actor* actor, InitChainEntry* ichain);
#endif #endif

View file

@ -34,6 +34,23 @@ double round(double);
long lroundf(float); long lroundf(float);
long lround(double); 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 qNaN0x3FFFFF;
extern float qNaN0x10000; extern float qNaN0x10000;
extern float sNaN0x3FFFFF; extern float sNaN0x3FFFFF;

View file

@ -14,7 +14,6 @@
#define VIRTUAL_TO_PHYSICAL(addr) (uintptr_t)((u8*)(addr) - 0x80000000) #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 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 ABS(x) ((x) >= 0 ? (x) : -(x))
#define DECR(x) ((x) == 0 ? 0 : --(x)) #define DECR(x) ((x) == 0 ? 0 : --(x))
#define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x)) #define CLAMP(x, min, max) ((x) < (min) ? (min) : (x) > (max) ? (max) : (x))

15
include/rand.h Normal file
View file

@ -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

View file

@ -372,4 +372,15 @@ typedef enum {
#define R_VI_CUR_ADDI_SCAN_LINES HREG(83) #define R_VI_CUR_ADDI_SCAN_LINES HREG(83)
#define R_VI_CUR_Y_SCALE_MODE HREG(84) #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 #endif

View file

@ -125,4 +125,27 @@ typedef struct {
#define SFX_DIST_SCALING 10.0f #define SFX_DIST_SCALING 10.0f
#endif #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 #endif

14
include/sys_math.h Normal file
View file

@ -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

73
include/sys_math3d.h Normal file
View file

@ -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

View file

@ -3,17 +3,17 @@
#ifndef ULTRA64_GBI_H #ifndef ULTRA64_GBI_H
#define ULTRA64_GBI_H #define ULTRA64_GBI_H
#ifdef GBI_DOWHILE
/* Private macro to wrap other macros in do {...} while (0) */
#define _DW(macro) do { macro } while (0)
#else
#define _DW(macro) { macro } (void)0
#endif
/* To enable Fast3DEX grucode support, define F3DEX_GBI. */ /* To enable Fast3DEX grucode support, define F3DEX_GBI. */
/* Types */ /* Types */
/* Private macro to wrap other macros in do {...} while (0) */
#define _DW(macro) do {macro} while (0)
#ifndef F3DEX_GBI
#define F3DEX_GBI_2
#endif
#ifdef F3DEX_GBI_2 #ifdef F3DEX_GBI_2
# ifndef F3DEX_GBI # ifndef F3DEX_GBI
# define F3DEX_GBI # define F3DEX_GBI
@ -290,6 +290,9 @@
#define G_TEXTURE_GEN 0x00040000 #define G_TEXTURE_GEN 0x00040000
#define G_TEXTURE_GEN_LINEAR 0x00080000 #define G_TEXTURE_GEN_LINEAR 0x00080000
#define G_LOD 0x00100000 /* NOT IMPLEMENTED */ #define G_LOD 0x00100000 /* NOT IMPLEMENTED */
#ifdef F3DEX_GBI_PL
# define G_LIGHTING_POSITIONAL 0x00400000
#endif
#if (defined(F3DEX_GBI) || defined(F3DLP_GBI)) #if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
# define G_CLIPPING 0x00800000 # define G_CLIPPING 0x00800000
#else #else
@ -302,6 +305,9 @@
# define G_TEXTURE_GEN_H (G_TEXTURE_GEN/0x10000) # define G_TEXTURE_GEN_H (G_TEXTURE_GEN/0x10000)
# define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR/0x10000) # define G_TEXTURE_GEN_LINEAR_H (G_TEXTURE_GEN_LINEAR/0x10000)
# define G_LOD_H (G_LOD/0x10000) /* NOT IMPLEMENTED */ # define G_LOD_H (G_LOD/0x10000) /* NOT IMPLEMENTED */
# ifdef F3DEX_GBI_PL
# define G_LIGHTING_POSITIONAL_H (G_LIGHTING_POSITIONAL/0x10000)
# endif
# if (defined(F3DEX_GBI) || defined(F3DLP_GBI)) # if (defined(F3DEX_GBI) || defined(F3DLP_GBI))
# define G_CLIPPING_H (G_CLIPPING/0x10000) # define G_CLIPPING_H (G_CLIPPING/0x10000)
# endif # endif
@ -1309,6 +1315,17 @@ typedef struct {
char pad3; char pad3;
} Light_t; } Light_t;
#ifdef F3DEX_GBI_PL
typedef struct {
unsigned char col[3]; /* point light value (rgba) */
unsigned char kc; /* constant attenuation (> 0 indicates point light) */
unsigned char colc[3]; /* copy of point light value (rgba) */
unsigned char kl; /* linear attenuation */
short pos[3]; /* world-space position of light */
unsigned char kq; /* quadratic attenuation */
} PointLight_t;
#endif
typedef struct { typedef struct {
unsigned char col[3]; /* ambient light value (rgba) */ unsigned char col[3]; /* ambient light value (rgba) */
char pad1; char pad1;
@ -1326,6 +1343,9 @@ typedef struct {
typedef union { typedef union {
Light_t l; Light_t l;
#ifdef F3DEX_GBI_PL
PointLight_t p;
#endif
long long int force_structure_alignment[2]; long long int force_structure_alignment[2];
} Light; } Light;
@ -1388,34 +1408,33 @@ typedef union {
long int force_structure_alignment; long int force_structure_alignment;
} Hilite; } Hilite;
#define gDefAmbient(r, g, b) \
{{ \
{ (r), (g), (b) }, 0, \
{ (r), (g), (b) }, 0, \
}}
#define gDefLight(r, g, b, x, y, z) \
{{ \
{ (r), (g), (b) }, 0, \
{ (r), (g), (b) }, 0, \
{ (x), (y), (z) }, 0, \
}}
#define gdSPDefLights0(ar, ag, ab) \ #define gdSPDefLights0(ar, ag, ab) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(0, 0, 0, 0, 0, 0), \
{ 0, 0, 0 }, 0, \
{ 0, 0, 0 }, 0, \
{ 0, 0, 0 }, 0, \
}} \
} \ } \
} }
#define gdSPDefLights1(ar, ag, ab, \ #define gdSPDefLights1(ar, ag, ab, \
r1, g1, b1, x1, y1, z1) \ r1, g1, b1, x1, y1, z1) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \
{ r1, g1, b1 }, 0, \
{ x1, y1, z1 }, 0, \
}} \
} \ } \
} }
@ -1423,49 +1442,23 @@ typedef union {
r1, g1, b1, x1, y1, z1, \ r1, g1, b1, x1, y1, z1, \
r2, g2, b2, x2, y2, z2) \ r2, g2, b2, x2, y2, z2) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ r1, g1, b1 }, 0, \
{ x1, y1, z1 }, 0, \
}}, \
{{ \
{ r2, g2, b2 }, 0, \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}} \
} \ } \
} }
#define gdSPDefLights3(ar, ag, ab, \ #define gdSPDefLights3(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, \ r1, g1, b1, x1, y1, z1, \
r2, g2, b2, x2, y2, z2, \ r2, g2, b2, x2, y2, z2) \
r3, g3, b3, x3, y3, z3) \ r3, g3, b3, x3, y3, z3) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ r1, g1, b1 }, 0, \ gDefLight(r3, g3, b3, x3, y3, z3), \
{ x1, y1, z1 }, 0, \
}}, \
{{ \
{ r2, g2, b2 }, 0, \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}}, \
{{ \
{ r3, g3, b3 }, 0, \
{ r3, g3, b3 }, 0, \
{ x3, y3, z3 }, 0, \
}} \
} \ } \
} }
@ -1475,31 +1468,12 @@ typedef union {
r3, g3, b3, x3, y3, z3, \ r3, g3, b3, x3, y3, z3, \
r4, g4, b4, x4, y4, z4) \ r4, g4, b4, x4, y4, z4) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ r1, g1, b1 }, 0, \ gDefLight(r3, g3, b3, x3, y3, z3), \
{ x1, y1, z1 }, 0, \ gDefLight(r4, g4, b4, x4, y4, z4), \
}}, \
{{ \
{ r2, g2, b2 }, 0, \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}}, \
{{ \
{ r3, g3, b3 }, 0, \
{ r3, g3, b3 }, 0, \
{ x3, y3, z3 }, 0, \
}}, \
{{ \
{ r4, g4, b4 }, 0, \
{ r4, g4, b4 }, 0, \
{ x4, y4, z4 }, 0, \
}} \
} \ } \
} }
@ -1507,39 +1481,16 @@ typedef union {
r1, g1, b1, x1, y1, z1, \ r1, g1, b1, x1, y1, z1, \
r2, g2, b2, x2, y2, z2, \ r2, g2, b2, x2, y2, z2, \
r3, g3, b3, x3, y3, z3, \ r3, g3, b3, x3, y3, z3, \
r4, g4, b4, x4, y4, z4, \ r4, g4, b4, x4, y4, z4) \
r5, g5, b5, x5, y5, z5) \ r5, g5, b5, x5, y5, z5) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ r1, g1, b1 }, 0, \ gDefLight(r3, g3, b3, x3, y3, z3), \
{ x1, y1, z1 }, 0, \ gDefLight(r4, g4, b4, x4, y4, z4), \
}}, \ gDefLight(r5, g5, b5, x5, y5, z5), \
{{ \
{ r2, g2, b2 }, 0, \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}}, \
{{ \
{ r3, g3, b3 }, 0, \
{ r3, g3, b3 }, 0, \
{ x3, y3, z3 }, 0, \
}}, \
{{ \
{ r4, g4, b4 }, 0, \
{ r4, g4, b4 }, 0, \
{ x4, y4, z4 }, 0, \
}}, \
{{ \
{ r5, g5, b5 }, 0, \
{ r5, g5, b5 }, 0, \
{ x5, y5, z5 }, 0, \
}} \
} \ } \
} }
@ -1551,41 +1502,14 @@ typedef union {
r5, g5, b5, x5, y5, z5, \ r5, g5, b5, x5, y5, z5, \
r6, g6, b6, x6, y6, z6) \ r6, g6, b6, x6, y6, z6) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab }, 0, \
{ ar, ag, ab }, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ x1, y1, z1 }, 0, \ gDefLight(r3, g3, b3, x3, y3, z3), \
{ r1, g1, b1 }, 0, \ gDefLight(r4, g4, b4, x4, y4, z4), \
}}, \ gDefLight(r5, g5, b5, x5, y5, z5), \
{{ \ gDefLight(r6, g6, b6, x6, y6, z6), \
{ r2, g2, b2 }, 0, \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}}, \
{{ \
{ r3, g3, b3 }, 0, \
{ r3, g3, b3 }, 0, \
{ x3, y3, z3 }, 0, \
}}, \
{{ \
{ r4, g4, b4 }, 0, \
{ r4, g4, b4 }, 0, \
{ x4, y4, z4 }, 0, \
}}, \
{{ \
{ r5, g5, b5 }, 0, \
{ r5, g5, b5 }, 0, \
{ x5, y5, z5 }, 0, \
}}, \
{{ \
{ r6, g6, b6 }, 0, \
{ r6, g6, b6 }, 0, \
{ x6, y6, z6 }, 0, \
}} \
} \ } \
} }
@ -1595,52 +1519,144 @@ typedef union {
r3, g3, b3, x3, y3, z3, \ r3, g3, b3, x3, y3, z3, \
r4, g4, b4, x4, y4, z4, \ r4, g4, b4, x4, y4, z4, \
r5, g5, b5, x5, y5, z5, \ r5, g5, b5, x5, y5, z5, \
r6, g6, b6, x6, y6, z6, \ r6, g6, b6, x6, y6, z6) \
r7, g7, b7, x7, y7, z7) \ r7, g7, b7, x7, y7, z7) \
{ \ { \
{{ \ gDefAmbient(ar, ag, ab), \
{ ar, ag, ab}, 0, \
{ ar, ag, ab}, 0, \
}}, \
{ \ { \
{{ \ gDefLight(r1, g1, b1, x1, y1, z1), \
{ r1, g1, b1 }, 0, \ gDefLight(r2, g2, b2, x2, y2, z2), \
{ r1, g1, b1 }, 0, \ gDefLight(r3, g3, b3, x3, y3, z3), \
{ x1, y1, z1 }, 0, \ gDefLight(r4, g4, b4, x4, y4, z4), \
}}, \ gDefLight(r5, g5, b5, x5, y5, z5), \
{{ \ gDefLight(r6, g6, b6, x6, y6, z6), \
{ r2, g2, b2 }, 0, \ gDefLight(r7, g7, b7, x7, y7, z7), \
{ r2, g2, b2 }, 0, \
{ x2, y2, z2 }, 0, \
}}, \
{{ \
{ r3, g3, b3 }, 0, \
{ r3, g3, b3 }, 0, \
{ x3, y3, z3 }, 0, \
}}, \
{{ \
{ r4, g4, b4 }, 0, \
{ r4, g4, b4 }, 0, \
{ x4, y4, z4 }, 0, \
}}, \
{{ \
{ r5, g5, b5 }, 0, \
{ r5, g5, b5 }, 0, \
{ x5, y5, z5 }, 0, \
}}, \
{{ \
{ r6, g6, b6 }, 0, \
{ r6, g6, b6 }, 0, \
{ x6, y6, z6 }, 0, \
}}, \
{{ \
{ r7, g7, b7 }, 0, \
{ r7, g7, b7 }, 0, \
{ x7, y7, z7 }, 0, \
}} \
} \ } \
} }
#ifdef F3DEX_GBI_PL
#define gDefPointLight(r, g, b, x, y, z, kc, kl, kq) \
{{ \
{ (r1), (g1), (b1) }, (kc), \
{ (r1), (g1), (b1) }, (kl), \
{ (x1), (y1), (z1) }, (kq), \
}}
#define gdSPDefPointLights0(ar, ag, ab) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(0, 0, 0, 0, 0, 0, 0, 0, 0), \
} \
}
#define gdSPDefPointLights1(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
} \
}
#define gdSPDefPointLights2(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
} \
}
#define gdSPDefPointLights3(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2) \
r3, g3, b3, x3, y3, z3, c3, l3, q3) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
gDefPointLight(r3, g3, b3, x3, y3, z3, c3, l3, q3), \
} \
}
#define gdSPDefPointLights4(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2, \
r3, g3, b3, x3, y3, z3, c3, l3, q3, \
r4, g4, b4, x4, y4, z4, c4, l4, q4) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
gDefPointLight(r3, g3, b3, x3, y3, z3, c3, l3, q3), \
gDefPointLight(r4, g4, b4, x4, y4, z4, c4, l4, q4), \
} \
}
#define gdSPDefPointLights5(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2, \
r3, g3, b3, x3, y3, z3, c3, l3, q3, \
r4, g4, b4, x4, y4, z4, c4, l4, q4) \
r5, g5, b5, x5, y5, z5, c5, l5, q5) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
gDefPointLight(r3, g3, b3, x3, y3, z3, c3, l3, q3), \
gDefPointLight(r4, g4, b4, x4, y4, z4, c4, l4, q4), \
gDefPointLight(r5, g5, b5, x5, y5, z5, c5, l5, q5), \
} \
}
#define gdSPDefPointLights6(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2, \
r3, g3, b3, x3, y3, z3, c3, l3, q3, \
r4, g4, b4, x4, y4, z4, c4, l4, q4) \
r5, g5, b5, x5, y5, z5, c5, l5, q5) \
r6, g6, b6, x6, y6, z6, c6, l6, q6) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
gDefPointLight(r3, g3, b3, x3, y3, z3, c3, l3, q3), \
gDefPointLight(r4, g4, b4, x4, y4, z4, c4, l4, q4), \
gDefPointLight(r5, g5, b5, x5, y5, z5, c5, l5, q5), \
gDefPointLight(r6, g6, b6, x6, y6, z6, c6, l6, q6), \
} \
}
#define gdSPDefPointLights7(ar, ag, ab, \
r1, g1, b1, x1, y1, z1, c1, l1, q1, \
r2, g2, b2, x2, y2, z2, c2, l2, q2, \
r3, g3, b3, x3, y3, z3, c3, l3, q3, \
r4, g4, b4, x4, y4, z4, c4, l4, q4, \
r5, g5, b5, x5, y5, z5, c5, l5, q5, \
r6, g6, b6, x6, y6, z6, c6, l6, q6) \
r7, g7, b7, x7, y7, z7, c7, l7, q7) \
{ \
gDefAmbient(ar, ag, ab), \
{ \
gDefPointLight(r1, g1, b1, x1, y1, z1, c1, l1, q1), \
gDefPointLight(r2, g2, b2, x2, y2, z2, c2, l2, q2), \
gDefPointLight(r3, g3, b3, x3, y3, z3, c3, l3, q3), \
gDefPointLight(r4, g4, b4, x4, y4, z4, c4, l4, q4), \
gDefPointLight(r5, g5, b5, x5, y5, z5, c5, l5, q5), \
gDefPointLight(r6, g6, b6, x6, y6, z6, c6, l6, q6), \
gDefPointLight(r7, g7, b7, x7, y7, z7, c7, l7, q7), \
} \
}
#endif
#define gdSPDefLookAt(rightx, righty, rightz, upx, upy, upz) \ #define gdSPDefLookAt(rightx, righty, rightz, upx, upy, upz) \
{{ \ {{ \
@ -1995,7 +2011,9 @@ typedef union {
Gquad quad; Gquad quad;
#endif #endif
Gline3D line; Gline3D line;
#if (defined(F3DLP_GBI) || defined(F3DEX_GBI))
Gcull cull; Gcull cull;
#endif
Gmovewd movewd; Gmovewd movewd;
Gmovemem movemem; Gmovemem movemem;
Gpopmtx popmtx; Gpopmtx popmtx;
@ -3435,6 +3453,15 @@ _DW({ \
gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode) gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 2, mode)
#endif #endif
/*
* Majora's Mask Extension, sets both RGB and Alpha dither modes in the same
* macro. `mode` should use both G_CD_* and G_AD_* constants.
*/
#define gDPSetDither(pkt, mode) \
gSPSetOtherMode(pkt, G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 4, mode)
#define gsDPSetDither(mode) \
gsSPSetOtherMode( G_SETOTHERMODE_H, G_MDSFT_ALPHADITHER, 4, mode)
/* 'blendmask' is not supported anymore. /* 'blendmask' is not supported anymore.
* The bits are reserved for future use. * The bits are reserved for future use.
* Fri May 26 13:45:55 PDT 1995 * Fri May 26 13:45:55 PDT 1995
@ -5123,7 +5150,7 @@ _DW({ \
#define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag) #define gDPNoOpTag(pkt, tag) gDPParam(pkt, G_NOOP, tag)
#define gsDPNoOpTag(tag) gsDPParam( G_NOOP, tag) #define gsDPNoOpTag(tag) gsDPParam( G_NOOP, tag)
#if OOT_DEBUG #ifdef GBI_DEBUG
#define gDPNoOpHere(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 1) #define gDPNoOpHere(pkt, file, line) gDma1p(pkt, G_NOOP, file, line, 1)
#define gDPNoOpString(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 2) #define gDPNoOpString(pkt, data, n) gDma1p(pkt, G_NOOP, data, n, 2)
@ -5149,7 +5176,7 @@ _DW({ \
#define gDPNoOpCloseDisp(pkt, file, line) #define gDPNoOpCloseDisp(pkt, file, line)
#define gDPNoOpTag3(pkt, type, data, n) #define gDPNoOpTag3(pkt, type, data, n)
#endif /* OOT_DEBUG */ #endif /* GBI_DEBUG */
#endif #endif

View file

@ -21,6 +21,12 @@ typedef union {
f32 f; f32 f;
} fu; } fu;
f32 sinf(f32 angle);
s16 sins(u16 angle);
f32 cosf(f32 angle);
s16 coss(u16 angle);
extern f32 __libm_qnan_f; extern f32 __libm_qnan_f;
#endif #endif

View file

@ -172,7 +172,6 @@ extern u8 gSequenceTable[];
extern u8 gSampleBankTable[]; extern u8 gSampleBankTable[];
extern SaveContext gSaveContext; extern SaveContext gSaveContext;
extern RegEditor* gRegEditor;
extern u8 gUseCutsceneCam; extern u8 gUseCutsceneCam;
extern u16 D_8015FCCC; extern u16 D_8015FCCC;

View file

@ -44,6 +44,7 @@
#include "sfx.h" #include "sfx.h"
#include "color.h" #include "color.h"
#include "gfxprint.h" #include "gfxprint.h"
#include "z_lib.h"
#include "ichain.h" #include "ichain.h"
#include "regs.h" #include "regs.h"
#include "irqmgr.h" #include "irqmgr.h"
@ -58,6 +59,10 @@
#include "gfx.h" #include "gfx.h"
#include "jpeg.h" #include "jpeg.h"
#include "prerender.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_WIDTH 320
#define SCREEN_HEIGHT 240 #define SCREEN_HEIGHT 240
@ -99,15 +104,6 @@
// NOTE: Once we start supporting other builds, this can be changed with an ifdef // NOTE: Once we start supporting other builds, this can be changed with an ifdef
#define REGION_NATIVE REGION_EU #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 { typedef struct {
/* 0x00 */ u8 seqId; /* 0x00 */ u8 seqId;
/* 0x01 */ u8 natureAmbienceId; /* 0x01 */ u8 natureAmbienceId;
@ -225,8 +221,8 @@ typedef struct {
} GameOverContext; // size = 0x2 } GameOverContext; // size = 0x2
typedef enum { typedef enum {
/* 0 */ LENS_MODE_HIDE_ACTORS, // lens actors are visible by default, and hidden by using lens (for example, fake walls) /* 0 */ LENS_MODE_SHOW_ACTORS, // lens actors are invisible by default, and shown by using lens (for example, invisible enemies)
/* 1 */ 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; } LensMode;
typedef enum { typedef enum {
@ -396,7 +392,7 @@ typedef struct PlayState {
/* 0x10760 */ PauseContext pauseCtx; /* 0x10760 */ PauseContext pauseCtx;
/* 0x10A20 */ GameOverContext gameOverCtx; /* 0x10A20 */ GameOverContext gameOverCtx;
/* 0x10A24 */ EnvironmentContext envCtx; /* 0x10A24 */ EnvironmentContext envCtx;
/* 0x10B20 */ AnimationContext animationCtx; /* 0x10B20 */ AnimTaskQueue animTaskQueue;
/* 0x117A4 */ ObjectContext objectCtx; /* 0x117A4 */ ObjectContext objectCtx;
/* 0x11CBC */ RoomContext roomCtx; /* 0x11CBC */ RoomContext roomCtx;
/* 0x11D34 */ TransitionActorContext transiActorCtx; /* 0x11D34 */ TransitionActorContext transiActorCtx;

152
include/z64animation.h Executable file → Normal file
View file

@ -88,12 +88,30 @@ typedef enum {
/* 1 */ ANIMTAPER_ACCEL /* 1 */ ANIMTAPER_ACCEL
} AnimationTapers; } AnimationTapers;
#define ANIM_FLAG_0 (1 << 0) // (no effect outside of player) Related to scaling an animation from/to child/adult // This flag seems like it was intended to be paired with `ANIM_FLAG_UPDATE_Y` to control
// XZ movement based on the current animation.
// However, this flag is not checked by the Skelanime system. XZ movement will always occur
// regardless of the current state of this flag, as long as the "Actor Move" Anim Task is in use.
// The name of this flag is speculative based on its usage in Player and in other actors.
//
// In practice, this flag only affects the scaling of Player's XZ position based on age.
#define ANIM_FLAG_UPDATE_XZ (1 << 0)
// Enables the movement of an actor in the Y-axis based on the current animation.
// This only has an effect if the "Actor Move" Anim Task is in use.
#define ANIM_FLAG_UPDATE_Y (1 << 1) #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 // (player-only) Related to scaling an animation from/to child/adult
#define ANIM_FLAG_PLAYER_2 (1 << 2)
// (player-only) Call AnimTaskQueue_AddActorMove
#define ANIM_FLAG_PLAYER_SETMOVE (1 << 3)
//
#define ANIM_FLAG_NO_MOVE (1 << 4) #define ANIM_FLAG_NO_MOVE (1 << 4)
#define ANIM_FLAG_PLAYER_7 (1 << 7) // (player-only)
// (player-only)
#define ANIM_FLAG_PLAYER_7 (1 << 7)
typedef struct SkelAnime { typedef struct SkelAnime {
/* 0x00 */ u8 limbCount; // Number of limbs in the skeleton /* 0x00 */ u8 limbCount; // Number of limbs in the skeleton
@ -239,95 +257,95 @@ s16 Animation_GetLength(void* animation);
s16 Animation_GetLastFrame(void* animation); s16 Animation_GetLastFrame(void* animation);
/* /*
* Animation requests * Animation Task Queue
*/ */
typedef enum { typedef enum {
/* 0 */ ANIMENTRY_LOADFRAME, /* 0 */ ANIMTASK_LOAD_PLAYER_FRAME,
/* 1 */ ANIMENTRY_COPYALL, /* 1 */ ANIMTASK_COPY,
/* 2 */ ANIMENTRY_INTERP, /* 2 */ ANIMTASK_INTERP,
/* 3 */ ANIMENTRY_COPYTRUE, /* 3 */ ANIMTASK_COPY_USING_MAP,
/* 4 */ ANIMENTRY_COPYFALSE, /* 4 */ ANIMTASK_COPY_USING_MAP_INVERTED,
/* 5 */ ANIMENTRY_MOVEACTOR /* 5 */ ANIMTASK_ACTOR_MOVE
} AnimationType; } AnimTaskType;
typedef struct { typedef struct {
/* 0x000 */ DmaRequest req; /* 0x00 */ DmaRequest req;
/* 0x020 */ OSMesgQueue msgQueue; /* 0x20 */ OSMesgQueue msgQueue;
/* 0x038 */ OSMesg msg; /* 0x38 */ OSMesg msg;
} AnimEntryLoadFrame; // size = 0x3C } AnimTaskLoadPlayerFrame; // size = 0x3C
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
} AnimEntryCopyAll; // size = 0xC } AnimTaskCopy; // size = 0xC
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* base; /* 0x04 */ Vec3s* base;
/* 0x008 */ Vec3s* mod; /* 0x08 */ Vec3s* mod;
/* 0x00C */ f32 weight; /* 0x0C */ f32 weight;
} AnimEntryInterp; // size = 0x10 } AnimTaskInterp; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
/* 0x00C */ u8* copyFlag; /* 0x0C */ u8* limbCopyMap;
} AnimEntryCopyTrue; // size = 0x10 } AnimTaskCopyUsingMap; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ u8 queueFlag; /* 0x00 */ u8 group;
/* 0x001 */ u8 vecCount; /* 0x01 */ u8 vecCount;
/* 0x004 */ Vec3s* dst; /* 0x04 */ Vec3s* dest;
/* 0x008 */ Vec3s* src; /* 0x08 */ Vec3s* src;
/* 0x00C */ u8* copyFlag; /* 0x0C */ u8* limbCopyMap;
} AnimEntryCopyFalse; // size = 0x10 } AnimTaskCopyUsingMapInverted; // size = 0x10
typedef struct { typedef struct {
/* 0x000 */ struct Actor* actor; /* 0x00 */ struct Actor* actor;
/* 0x004 */ struct SkelAnime* skelAnime; /* 0x04 */ struct SkelAnime* skelAnime;
/* 0x008 */ f32 diffScaleY; /* 0x08 */ f32 diffScaleY;
} AnimEntryMoveActor; // size = 0xC } AnimTaskActorMove; // size = 0xC
typedef union { typedef union {
AnimEntryLoadFrame load; AnimTaskLoadPlayerFrame loadPlayerFrame;
AnimEntryCopyAll copy; AnimTaskCopy copy;
AnimEntryInterp interp; AnimTaskInterp interp;
AnimEntryCopyTrue copy1; AnimTaskCopyUsingMap copyUsingMap;
AnimEntryCopyFalse copy0; AnimTaskCopyUsingMapInverted copyUsingMapInverted;
AnimEntryMoveActor move; AnimTaskActorMove actorMove;
} AnimationEntryData; // size = 0x3C } AnimTaskData; // size = 0x3C
typedef struct { typedef struct {
/* 0x00 */ u8 type; /* 0x00 */ u8 type;
/* 0x04 */ AnimationEntryData data; /* 0x04 */ AnimTaskData data;
} AnimationEntry; // size = 0x40 } AnimTask; // size = 0x40
#define ANIMATION_ENTRY_MAX 50 #define ANIM_TASK_QUEUE_MAX 50
typedef struct AnimationContext { typedef struct AnimTaskQueue {
s16 animationCount; s16 count;
AnimationEntry entries[ANIMATION_ENTRY_MAX]; AnimTask tasks[ANIM_TASK_QUEUE_MAX];
} AnimationContext; // size = 0xC84 } AnimTaskQueue; // size = 0xC84
void AnimationContext_SetLoadFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount, void AnimTaskQueue_AddLoadPlayerFrame(struct PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount,
Vec3s* frameTable); Vec3s* frameTable);
void AnimationContext_SetCopyAll(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src); void AnimTaskQueue_AddCopy(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src);
void AnimationContext_SetCopyTrue(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); void AnimTaskQueue_AddInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight);
void AnimationContext_SetCopyFalse(struct PlayState* play, s32 vecCount, Vec3s* dst, Vec3s* src, u8* copyFlag); void AnimTaskQueue_AddCopyUsingMap(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap);
void AnimationContext_SetInterp(struct PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight); void AnimTaskQueue_AddCopyUsingMapInverted(struct PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap);
void AnimationContext_SetMoveActor(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY); void AnimTaskQueue_AddActorMove(struct PlayState* play, struct Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY);
void AnimationContext_SetNextQueue(struct PlayState* play); void AnimTaskQueue_SetNextGroup(struct PlayState* play);
void AnimationContext_DisableQueue(struct PlayState* play); void AnimTaskQueue_DisableTransformTasksForGroup(struct PlayState* play);
void AnimationContext_Reset(AnimationContext* animationCtx); void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue);
void AnimationContext_Update(struct PlayState* play, AnimationContext* animationCtx); void AnimTaskQueue_Update(struct PlayState* play, AnimTaskQueue* animTaskQueue);
/* /*
* Link animations * Link animations

View file

@ -6,10 +6,6 @@
#include "z64math.h" #include "z64math.h"
#include "z64save.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_CUT 0
#define CAM_STAT_WAIT 1 #define CAM_STAT_WAIT 1
#define CAM_STAT_UNK3 3 #define CAM_STAT_UNK3 3

View file

@ -2,7 +2,9 @@
#define Z64MATH_H #define Z64MATH_H
#include "ultra64.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) #define VEC_SET(V,X,Y,Z) (V).x=(X);(V).y=(Y);(V).z=(Z)
typedef struct { 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_ALT(binang) (((f32)(binang) / (f32)0x8000) * M_PI)
#define BINANG_TO_RAD_ALT2(binang) (((f32)(binang) * M_PI) / 0x8000) #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 // Vector macros
#define SQXZ(vec) ((vec).x * (vec).x + (vec).z * (vec).z) #define SQXZ(vec) ((vec).x * (vec).x + (vec).z * (vec).z)
#define DOTXZ(vec1, vec2) ((vec1).x * (vec2).x + (vec1).z * (vec2).z) #define DOTXZ(vec1, vec2) ((vec1).x * (vec2).x + (vec1).z * (vec2).z)

44
include/z_lib.h Normal file
View file

@ -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

View file

@ -1,6 +1,7 @@
# Setup and compression # Setup and compression
crunch64>=0.3.1,<1.0.0 crunch64>=0.3.1,<1.0.0
ipl3checksum>=1.2.0,<2.0.0 ipl3checksum>=1.2.0,<2.0.0
pyyaml>=6.0.1,<7.0.0
# asm-differ # asm-differ
argcomplete argcomplete

13
spec
View file

@ -437,6 +437,9 @@ beginseg
include "$(BUILD_DIR)/src/code/sys_cfb.o" include "$(BUILD_DIR)/src/code/sys_cfb.o"
include "$(BUILD_DIR)/src/code/sys_math.o" include "$(BUILD_DIR)/src/code/sys_math.o"
include "$(BUILD_DIR)/src/code/sys_math3d.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_math_atan.o"
include "$(BUILD_DIR)/src/code/sys_matrix.o" include "$(BUILD_DIR)/src/code/sys_matrix.o"
include "$(BUILD_DIR)/src/code/sys_ucode.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/code_800FC620.o"
include "$(BUILD_DIR)/src/code/padutils.o" include "$(BUILD_DIR)/src/code/padutils.o"
include "$(BUILD_DIR)/src/code/padsetup.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/fp.o"
include "$(BUILD_DIR)/src/code/system_malloc.o" include "$(BUILD_DIR)/src/code/system_malloc.o"
include "$(BUILD_DIR)/src/code/rand.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/fmodf.o"
include "$(BUILD_DIR)/src/code/__osMemset.o" include "$(BUILD_DIR)/src/code/__osMemset.o"
include "$(BUILD_DIR)/src/code/__osMemmove.o" include "$(BUILD_DIR)/src/code/__osMemmove.o"
include_data_with_rodata "$(BUILD_DIR)/src/code/z_message_PAL.o" // For some reason, the data sections of these files are placed here near the
include "$(BUILD_DIR)/src/code/z_game_over.o" // 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)/src/code/z_construct.o"
include "$(BUILD_DIR)/data/audio_tables.rodata.o" include "$(BUILD_DIR)/data/audio_tables.rodata.o"
include "$(BUILD_DIR)/data/rsp.text.o" include "$(BUILD_DIR)/data/rsp.text.o"

View file

@ -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 * memcpy: copies `len` bytes from memory starting at `src` to memory starting at `dest`. Expects the memory

View file

@ -48,9 +48,9 @@
// just above (the exact upper bound depends on the block numbers assigned to // just above (the exact upper bound depends on the block numbers assigned to
// extern variables declared in headers). // extern variables declared in headers).
#if OOT_DEBUG #if OOT_DEBUG
#pragma increment_block_number 20 #pragma increment_block_number 0
#else #else
#pragma increment_block_number 25 #pragma increment_block_number 20
#endif #endif
void FaultDrawer_Init(void); void FaultDrawer_Init(void);

View file

@ -1,4 +1,4 @@
#include "global.h" #include "ultra64.h"
/** /**
* Computes one `x` modulo `y` for floats. * Computes one `x` modulo `y` for floats.

View file

@ -1,4 +1,5 @@
#include "global.h" #include "z64math.h"
#include "macros.h"
s32 gUseAtanContFrac; s32 gUseAtanContFrac;

View file

@ -41,7 +41,7 @@
* *
* @note Original name: qrand.c * @note Original name: qrand.c
*/ */
#include "ultra64.h" #include "rand.h"
#define RAND_MULTIPLIER 1664525 #define RAND_MULTIPLIER 1664525
#define RAND_INCREMENT 1013904223 #define RAND_INCREMENT 1013904223

View file

@ -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, 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 }; 5040.0f, 40320.0f, 362880.0f, 3628800.0f, 39916800.0f, 479001600.0f };

View file

@ -1,9 +1,13 @@
#include "global.h" #include "ultra64.h"
#include "z_lib.h"
#include "z64math.h"
#include "terminal.h" #include "terminal.h"
#include "macros.h"
#include "sys_math3d.h"
// For retail BSS ordering, the block number of cbf in Math3D_CylVsCylOverlapCenterDist // For retail BSS ordering, the block number of cbf in Math3D_CylVsCylOverlapCenterDist
// must be 0. // must be 0.
#pragma increment_block_number 187 #pragma increment_block_number 111
s32 Math3D_LineVsLineClosestTwoPoints(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB, s32 Math3D_LineVsLineClosestTwoPoints(Vec3f* lineAPointA, Vec3f* lineAPointB, Vec3f* lineBPointA, Vec3f* lineBPointB,
Vec3f* lineAClosestToB, Vec3f* lineBClosestToA); Vec3f* lineAClosestToB, Vec3f* lineBClosestToA);
@ -2147,11 +2151,3 @@ s32 Math3D_YZInSphere(Sphere16* sphere, f32 y, f32 z) {
} }
return false; return false;
} }
#if OOT_DEBUG
void Math3D_DrawSphere(PlayState* play, Sphere16* sph) {
}
void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl) {
}
#endif

View file

@ -0,0 +1,7 @@
#include "z64.h"
void Math3D_DrawSphere(PlayState* play, Sphere16* sph) {
}
void Math3D_DrawCylinder(PlayState* play, Cylinder16* cyl) {
}

View file

@ -1,4 +1,5 @@
#include "global.h" #include "z64math.h"
#include "macros.h"
static u16 sAtan2Tbl[] = { static u16 sAtan2Tbl[] = {
0x0000, 0x000A, 0x0014, 0x001F, 0x0029, 0x0033, 0x003D, 0x0047, 0x0051, 0x005C, 0x0066, 0x0070, 0x007A, 0x0084, 0x0000, 0x000A, 0x0014, 0x001F, 0x0029, 0x0033, 0x003D, 0x0047, 0x0051, 0x005C, 0x0066, 0x0070, 0x007A, 0x0084,

View file

@ -2452,7 +2452,7 @@ void Actor_DrawLensActors(PlayState* play, s32 numInvisibleActors, Actor** invis
gDPPipeSync(POLY_XLU_DISP++); 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 // Update both the color frame buffer and the z-buffer
gDPSetOtherMode(POLY_XLU_DISP++, 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 | 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" // "Magic lens invisible Actor display END"
gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないc表示 END", numInvisibleActors); gDPNoOpString(POLY_OPA_DISP++, "魔法のメガネ 見えないc表示 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 // Draw the lens overlay to the color frame buffer
gDPNoOpString(POLY_OPA_DISP++, "青い眼鏡(外側)", 0); // "Blue spectacles (exterior)" 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 (!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->init == NULL) && (actor->draw != NULL) && (actor->flags & (ACTOR_FLAG_5 | ACTOR_FLAG_6))) {
if ((actor->flags & ACTOR_FLAG_REACT_TO_LENS) && 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))) { (actor->room != play->roomCtx.curRoom.num))) {
ASSERT(invisibleActorCounter < INVISIBLE_ACTOR_MAX, ASSERT(invisibleActorCounter < INVISIBLE_ACTOR_MAX,
"invisible_actor_counter < INVISIBLE_ACTOR_MAX", "../z_actor.c", 6464); "invisible_actor_counter < INVISIBLE_ACTOR_MAX", "../z_actor.c", 6464);

View file

@ -2360,9 +2360,6 @@ void CollisionCheck_ATTrisVsACTris(PlayState* play, CollisionCheckContext* colCh
#if OOT_DEBUG #if OOT_DEBUG
static s8 sBssDummy7; static s8 sBssDummy7;
static s8 sBssDummy8;
static s8 sBssDummy9;
static s8 sBssDummy10;
#endif #endif
void CollisionCheck_ATTrisVsACQuad(PlayState* play, CollisionCheckContext* colChkCtx, Collider* atCol, 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 #if OOT_DEBUG
// Due to an unknown reason, bss ordering changed between the 2 static Vec3f variables in the function below. // The two static Vec3f variables in the function below cross a block index rollover, causing a bss order swap.
// In order to reproduce this behavior, we need a specific number of bss variables in the file before that point. //! In order to replicate this behavior, we declare a certain amount of sBssDummy variables throughout the file, which
// For this, we introduce a certain amount of dummy variables throughout the file, which we fit inside padding added //! we fit inside padding added by the compiler between structs like TriNorm and/or Vec3f, so they don't take space in
// by the compiler between structs like TriNorm and/or Vec3f, so they don't take space in bss. //! bss.
static s8 sBssDummy11;
static s8 sBssDummy12;
#endif #endif
/** /**

View file

@ -115,6 +115,8 @@ void* sUnusedEntranceCsList[] = {
gDekuTreeIntroCs, gJabuJabuIntroCs, gDcOpeningCs, gMinuetCs, gIceCavernSerenadeCs, gTowerBarrierCs, gDekuTreeIntroCs, gJabuJabuIntroCs, gDcOpeningCs, gMinuetCs, gIceCavernSerenadeCs, gTowerBarrierCs,
}; };
#pragma increment_block_number 254
// Stores the frame the relevant cam data was last applied on // Stores the frame the relevant cam data was last applied on
u16 gCamAtSplinePointsAppliedFrame; u16 gCamAtSplinePointsAppliedFrame;
u16 gCamEyePointAppliedFrame; u16 gCamEyePointAppliedFrame;

View file

@ -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 s16 sGameOverTimer = 0;
extern s16 gGameOverTimer;
void GameOver_Update(PlayState* play) { void GameOver_Update(PlayState* play) {
GameOverContext* gameOverCtx = &play->gameOverCtx; GameOverContext* gameOverCtx = &play->gameOverCtx;
@ -74,7 +73,7 @@ void GameOver_Update(PlayState* play) {
gSaveContext.hudVisibilityModeTimer = 0; // false, HUD_VISIBILITY_NO_CHANGE gSaveContext.hudVisibilityModeTimer = 0; // false, HUD_VISIBILITY_NO_CHANGE
Environment_InitGameOverLights(play); Environment_InitGameOverLights(play);
gGameOverTimer = 20; sGameOverTimer = 20;
if (1) {} if (1) {}
rumbleStrength = R_GAME_OVER_RUMBLE_STRENGTH; rumbleStrength = R_GAME_OVER_RUMBLE_STRENGTH;
@ -92,9 +91,9 @@ void GameOver_Update(PlayState* play) {
break; break;
case GAMEOVER_DEATH_DELAY_MENU: case GAMEOVER_DEATH_DELAY_MENU:
gGameOverTimer--; sGameOverTimer--;
if (gGameOverTimer == 0) { if (sGameOverTimer == 0) {
play->pauseCtx.state = PAUSE_STATE_8; play->pauseCtx.state = PAUSE_STATE_8;
gameOverCtx->state++; gameOverCtx->state++;
Rumble_Reset(); Rumble_Reset();
@ -103,13 +102,13 @@ void GameOver_Update(PlayState* play) {
case GAMEOVER_REVIVE_START: case GAMEOVER_REVIVE_START:
gameOverCtx->state++; gameOverCtx->state++;
gGameOverTimer = 0; sGameOverTimer = 0;
Environment_InitGameOverLights(play); Environment_InitGameOverLights(play);
Letterbox_SetSizeTarget(32); Letterbox_SetSizeTarget(32);
return; return;
case GAMEOVER_REVIVE_RUMBLE: case GAMEOVER_REVIVE_RUMBLE:
gGameOverTimer = 50; sGameOverTimer = 50;
gameOverCtx->state++; gameOverCtx->state++;
if (1) {} if (1) {}
@ -123,28 +122,28 @@ void GameOver_Update(PlayState* play) {
break; break;
case GAMEOVER_REVIVE_WAIT_GROUND: case GAMEOVER_REVIVE_WAIT_GROUND:
gGameOverTimer--; sGameOverTimer--;
if (gGameOverTimer == 0) { if (sGameOverTimer == 0) {
gGameOverTimer = 64; sGameOverTimer = 64;
gameOverCtx->state++; gameOverCtx->state++;
} }
break; break;
case GAMEOVER_REVIVE_WAIT_FAIRY: case GAMEOVER_REVIVE_WAIT_FAIRY:
gGameOverTimer--; sGameOverTimer--;
if (gGameOverTimer == 0) { if (sGameOverTimer == 0) {
gGameOverTimer = 50; sGameOverTimer = 50;
gameOverCtx->state++; gameOverCtx->state++;
} }
break; break;
case GAMEOVER_REVIVE_FADE_OUT: case GAMEOVER_REVIVE_FADE_OUT:
Environment_FadeOutGameOverLights(play); Environment_FadeOutGameOverLights(play);
gGameOverTimer--; sGameOverTimer--;
if (gGameOverTimer == 0) { if (sGameOverTimer == 0) {
gameOverCtx->state = GAMEOVER_INACTIVE; gameOverCtx->state = GAMEOVER_INACTIVE;
} }
break; break;

View file

@ -7,7 +7,7 @@
// For retail BSS ordering, the block number of sLensFlareUnused must be lower // For retail BSS ordering, the block number of sLensFlareUnused must be lower
// than the extern variables declared in the header (e.g. gLightningStrike) // than the extern variables declared in the header (e.g. gLightningStrike)
// while the block number of sNGameOverLightNode must be higher. // while the block number of sNGameOverLightNode must be higher.
#pragma increment_block_number 80 #pragma increment_block_number 78
typedef enum { typedef enum {
/* 0x00 */ LIGHTNING_BOLT_START, /* 0x00 */ LIGHTNING_BOLT_START,
@ -215,7 +215,7 @@ s16 sSunDepthTestY;
// These variables could be moved farther down in the file to reduce the amount // 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 // of block number padding here, but currently this causes BSS ordering issues
// for debug. // for debug.
#pragma increment_block_number 230 #pragma increment_block_number 227
LightNode* sNGameOverLightNode; LightNode* sNGameOverLightNode;
LightInfo sNGameOverLightInfo; LightInfo sNGameOverLightInfo;

View file

@ -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`. * 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, 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 { do {
sInitChainHandlers[ichain->type]((u8*)actor, ichain); sInitChainHandlers[ichain->type]((u8*)actor, ichain);
} while ((ichain++)->cont); } while ((ichain++)->cont);

View file

@ -3358,12 +3358,3 @@ void Message_SetTables(void) {
sFraMessageEntryTablePtr = sFraMessageEntryTable; sFraMessageEntryTablePtr = sFraMessageEntryTable;
sStaffMessageEntryTablePtr = sStaffMessageEntryTable; 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;

View file

@ -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` * Calculates the distances between `a` and `b`

View file

@ -284,7 +284,7 @@ void Play_Init(GameState* thisx) {
Effect_InitContext(this); Effect_InitContext(this);
EffectSs_InitInfo(this, 0x55); EffectSs_InitInfo(this, 0x55);
CollisionCheck_InitContext(this, &this->colChkCtx); CollisionCheck_InitContext(this, &this->colChkCtx);
AnimationContext_Reset(&this->animationCtx); AnimTaskQueue_Reset(&this->animTaskQueue);
Cutscene_InitContext(this, &this->csCtx); Cutscene_InitContext(this, &this->csCtx);
if (gSaveContext.nextCutsceneIndex != 0xFFEF) { if (gSaveContext.nextCutsceneIndex != 0xFFEF) {
@ -454,7 +454,7 @@ void Play_Init(GameState* thisx) {
gSaveContext.seqId = this->sequenceCtx.seqId; gSaveContext.seqId = this->sequenceCtx.seqId;
gSaveContext.natureAmbienceId = this->sequenceCtx.natureAmbienceId; gSaveContext.natureAmbienceId = this->sequenceCtx.natureAmbienceId;
func_8002DF18(this, GET_PLAYER(this)); func_8002DF18(this, GET_PLAYER(this));
AnimationContext_Update(this, &this->animationCtx); AnimTaskQueue_Update(this, &this->animTaskQueue);
gSaveContext.respawnFlag = 0; gSaveContext.respawnFlag = 0;
#if OOT_DEBUG #if OOT_DEBUG
@ -883,7 +883,7 @@ void Play_Update(PlayState* this) {
isPaused = IS_PAUSED(&this->pauseCtx); isPaused = IS_PAUSED(&this->pauseCtx);
PLAY_LOG(3555); PLAY_LOG(3555);
AnimationContext_Reset(&this->animationCtx); AnimTaskQueue_Reset(&this->animTaskQueue);
if (!OOT_DEBUG) {} if (!OOT_DEBUG) {}
@ -1000,7 +1000,7 @@ void Play_Update(PlayState* this) {
Interface_Update(this); Interface_Update(this);
PLAY_LOG(3765); PLAY_LOG(3765);
AnimationContext_Update(this, &this->animationCtx); AnimTaskQueue_Update(this, &this->animTaskQueue);
PLAY_LOG(3771); PLAY_LOG(3771);
SfxSource_UpdateAll(this); SfxSource_UpdateAll(this);

View file

@ -1125,7 +1125,8 @@ s32 Player_OverrideLimbDrawGameplayCommon(PlayState* play, s32 limbIndex, Gfx**
sCurBodyPartPos = &this->bodyPartsPos[0] - 1; sCurBodyPartPos = &this->bodyPartsPos[0] - 1;
if (!LINK_IS_ADULT) { if (!LINK_IS_ADULT) {
if (!(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) || (this->skelAnime.moveFlags & ANIM_FLAG_0)) { if (!(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ||
(this->skelAnime.moveFlags & ANIM_FLAG_UPDATE_XZ)) {
pos->x *= 0.64f; pos->x *= 0.64f;
pos->z *= 0.64f; pos->z *= 0.64f;
} }

View file

@ -9,9 +9,6 @@ s32 SkelAnime_LoopFull(SkelAnime* skelAnime);
s32 SkelAnime_Once(SkelAnime* skelAnime); s32 SkelAnime_Once(SkelAnime* skelAnime);
s32 SkelAnime_LoopPartial(SkelAnime* skelAnime); s32 SkelAnime_LoopPartial(SkelAnime* skelAnime);
static u32 sDisableAnimQueueFlags = 0;
static u32 sAnimQueueFlags;
/** /**
* Draw a limb of type `LodLimb` * Draw a limb of type `LodLimb`
* Near or far display list is specified via `lod` * 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) { void AnimTaskQueue_Reset(AnimTaskQueue* animTaskQueue) {
animationCtx->animationCount = 0; 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) { void AnimTaskQueue_SetNextGroup(PlayState* play) {
sAnimQueueFlags <<= 1; 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) { void AnimTaskQueue_DisableTransformTasksForGroup(PlayState* play) {
sDisableAnimQueueFlags |= sAnimQueueFlags; sDisabledTransformTaskGroups |= sCurAnimTaskGroup;
} }
AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, AnimationType type) { /**
AnimationEntry* entry; * Creates a new task and adds it to the queue, if there is room for it.
s16 index = animationCtx->animationCount; *
* 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; return NULL;
} }
animationCtx->animationCount = index + 1; animTaskQueue->count = taskNumber + 1;
entry = &animationCtx->entries[index];
entry->type = type; task = &animTaskQueue->tasks[taskNumber];
return entry; task->type = type;
return task;
} }
#define LINK_ANIMATION_OFFSET(addr, offset) \ #define LINK_ANIMATION_OFFSET(addr, offset) \
@ -838,205 +860,230 @@ AnimationEntry* AnimationContext_AddEntry(AnimationContext* animationCtx, Animat
(offset)) (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, void AnimTaskQueue_AddLoadPlayerFrame(PlayState* play, LinkAnimationHeader* animation, s32 frame, s32 limbCount,
Vec3s* frameTable) { Vec3s* frameTable) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_LOADFRAME); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_LOAD_PLAYER_FRAME);
if (entry != NULL) { if (task != NULL) {
LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation); LinkAnimationHeader* linkAnimHeader = SEGMENTED_TO_VIRTUAL(animation);
s32 pad; s32 pad;
osCreateMesgQueue(&entry->data.load.msgQueue, &entry->data.load.msg, 1); osCreateMesgQueue(&task->data.loadPlayerFrame.msgQueue, &task->data.loadPlayerFrame.msg, 1);
DMA_REQUEST_ASYNC(&entry->data.load.req, frameTable, DMA_REQUEST_ASYNC(&task->data.loadPlayerFrame.req, frameTable,
LINK_ANIMATION_OFFSET(linkAnimHeader->segment, ((sizeof(Vec3s) * limbCount + 2) * frame)), 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) { void AnimTaskQueue_AddCopy(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYALL); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY);
if (entry != NULL) { if (task != NULL) {
entry->data.copy.queueFlag = sAnimQueueFlags; task->data.copy.group = sCurAnimTaskGroup;
entry->data.copy.vecCount = vecCount; task->data.copy.vecCount = vecCount;
entry->data.copy.dst = dst; task->data.copy.dest = dest;
entry->data.copy.src = src; 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) { void AnimTaskQueue_AddInterp(PlayState* play, s32 vecCount, Vec3s* base, Vec3s* mod, f32 weight) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_INTERP); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_INTERP);
if (entry != NULL) { if (task != NULL) {
entry->data.interp.queueFlag = sAnimQueueFlags; task->data.interp.group = sCurAnimTaskGroup;
entry->data.interp.vecCount = vecCount; task->data.interp.vecCount = vecCount;
entry->data.interp.base = base; task->data.interp.base = base;
entry->data.interp.mod = mod; task->data.interp.mod = mod;
entry->data.interp.weight = weight; 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) { void AnimTaskQueue_AddCopyUsingMap(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYTRUE); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP);
if (entry != NULL) { if (task != NULL) {
entry->data.copy1.queueFlag = sAnimQueueFlags; task->data.copyUsingMap.group = sCurAnimTaskGroup;
entry->data.copy1.vecCount = vecCount; task->data.copyUsingMap.vecCount = vecCount;
entry->data.copy1.dst = dst; task->data.copyUsingMap.dest = dest;
entry->data.copy1.src = src; task->data.copyUsingMap.src = src;
entry->data.copy1.copyFlag = copyFlag; 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) { void AnimTaskQueue_AddCopyUsingMapInverted(PlayState* play, s32 vecCount, Vec3s* dest, Vec3s* src, u8* limbCopyMap) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_COPYFALSE); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_COPY_USING_MAP_INVERTED);
if (entry != NULL) { if (task != NULL) {
entry->data.copy0.queueFlag = sAnimQueueFlags; task->data.copyUsingMapInverted.group = sCurAnimTaskGroup;
entry->data.copy0.vecCount = vecCount; task->data.copyUsingMapInverted.vecCount = vecCount;
entry->data.copy0.dst = dst; task->data.copyUsingMapInverted.dest = dest;
entry->data.copy0.src = src; task->data.copyUsingMapInverted.src = src;
entry->data.copy0.copyFlag = copyFlag; 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) { void AnimTaskQueue_AddActorMove(PlayState* play, Actor* actor, SkelAnime* skelAnime, f32 moveDiffScaleY) {
AnimationEntry* entry = AnimationContext_AddEntry(&play->animationCtx, ANIMENTRY_MOVEACTOR); AnimTask* task = AnimTaskQueue_NewTask(&play->animTaskQueue, ANIMTASK_ACTOR_MOVE);
if (entry != NULL) { if (task != NULL) {
entry->data.move.actor = actor; task->data.actorMove.actor = actor;
entry->data.move.skelAnime = skelAnime; task->data.actorMove.skelAnime = skelAnime;
entry->data.move.diffScaleY = moveDiffScaleY; 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) { void AnimTask_LoadPlayerFrame(PlayState* play, AnimTaskData* data) {
AnimEntryLoadFrame* entry = &data->load; 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) { void AnimTask_Copy(PlayState* play, AnimTaskData* data) {
AnimEntryCopyAll* entry = &data->copy; AnimTaskCopy* task = &data->copy;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++) { for (i = 0; i < task->vecCount; i++) {
*dst++ = *src++; *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) { void AnimTask_Interp(PlayState* play, AnimTaskData* data) {
AnimEntryInterp* entry = &data->interp; AnimTaskInterp* task = &data->interp;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
SkelAnime_InterpFrameTable(entry->vecCount, entry->base, entry->base, entry->mod, entry->weight); 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) { void AnimTask_CopyUsingMap(PlayState* play, AnimTaskData* data) {
AnimEntryCopyTrue* entry = &data->copy1; AnimTaskCopyUsingMap* task = &data->copyUsingMap;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
u8* copyFlag = entry->copyFlag; u8* limbCopyMap = task->limbCopyMap;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++, dst++, src++) { for (i = 0; i < task->vecCount; i++, dest++, src++) {
if (*copyFlag++) { if (*limbCopyMap++) {
*dst = *src; *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) { void AnimTask_CopyUsingMapInverted(PlayState* play, AnimTaskData* data) {
AnimEntryCopyFalse* entry = &data->copy0; AnimTaskCopyUsingMapInverted* task = &data->copyUsingMapInverted;
if (!(entry->queueFlag & sDisableAnimQueueFlags)) { if (!(task->group & sDisabledTransformTaskGroups)) {
Vec3s* dst = entry->dst; Vec3s* dest = task->dest;
Vec3s* src = entry->src; Vec3s* src = task->src;
u8* copyFlag = entry->copyFlag; u8* limbCopyMap = task->limbCopyMap;
s32 i; s32 i;
for (i = 0; i < entry->vecCount; i++, dst++, src++) { for (i = 0; i < task->vecCount; i++, dest++, src++) {
if (!(*copyFlag++)) { if (!(*limbCopyMap++)) {
*dst = *src; *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) { void AnimTask_ActorMove(PlayState* play, AnimTaskData* data) {
AnimEntryMoveActor* entry = &data->move; AnimTaskActorMove* task = &data->actorMove;
Actor* actor = entry->actor; Actor* actor = task->actor;
Vec3f diff; 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.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; 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) { void AnimTaskQueue_Update(PlayState* play, AnimTaskQueue* animTaskQueue) {
static AnimationEntryCallback animFuncs[] = { static AnimTaskFunc animTaskFuncs[] = {
AnimationContext_LoadFrame, AnimationContext_CopyAll, AnimationContext_Interp, AnimTask_LoadPlayerFrame, AnimTask_Copy, AnimTask_Interp, AnimTask_CopyUsingMap,
AnimationContext_CopyTrue, AnimationContext_CopyFalse, AnimationContext_MoveActor, AnimTask_CopyUsingMapInverted, AnimTask_ActorMove,
}; };
AnimationEntry* entry = animationCtx->entries; AnimTask* task = animTaskQueue->tasks;
for (; animationCtx->animationCount != 0; animationCtx->animationCount--) { while (animTaskQueue->count != 0) {
animFuncs[entry->type](play, &entry->data); animTaskFuncs[task->type](play, &task->data);
entry++; task++;
animTaskQueue->count--;
} }
sAnimQueueFlags = 1; sCurAnimTaskGroup = 1 << 0;
sDisableAnimQueueFlags = 0; sDisabledTransformTaskGroups = 0;
} }
/** /**
@ -1125,7 +1172,7 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) {
LinkAnimation_SetUpdateFunction(skelAnime); LinkAnimation_SetUpdateFunction(skelAnime);
} }
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
1.0f - (skelAnime->morphWeight / prevMorphWeight)); 1.0f - (skelAnime->morphWeight / prevMorphWeight));
return 0; return 0;
} }
@ -1135,7 +1182,7 @@ s32 LinkAnimation_Morph(PlayState* play, SkelAnime* skelAnime) {
* jointTable and morphTable * jointTable and morphTable
*/ */
void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) { void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) {
AnimationContext_SetLoadFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, skelAnime->animation, skelAnime->curFrame, skelAnime->limbCount,
skelAnime->jointTable); skelAnime->jointTable);
if (skelAnime->morphWeight != 0) { if (skelAnime->morphWeight != 0) {
f32 updateRate = R_UPDATE_RATE * 0.5f; f32 updateRate = R_UPDATE_RATE * 0.5f;
@ -1144,7 +1191,7 @@ void LinkAnimation_AnimateFrame(PlayState* play, SkelAnime* skelAnime) {
if (skelAnime->morphWeight <= 0.0f) { if (skelAnime->morphWeight <= 0.0f) {
skelAnime->morphWeight = 0.0f; skelAnime->morphWeight = 0.0f;
} else { } else {
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable, AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->jointTable, skelAnime->morphTable,
skelAnime->morphWeight); skelAnime->morphWeight);
} }
} }
@ -1212,14 +1259,14 @@ void LinkAnimation_Change(PlayState* play, SkelAnime* skelAnime, LinkAnimationHe
morphFrames = -morphFrames; morphFrames = -morphFrames;
} else { } else {
skelAnime->update.link = LinkAnimation_Morph; skelAnime->update.link = LinkAnimation_Morph;
AnimationContext_SetLoadFrame(play, animation, (s32)startFrame, skelAnime->limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, animation, (s32)startFrame, skelAnime->limbCount,
skelAnime->morphTable); skelAnime->morphTable);
} }
skelAnime->morphWeight = 1.0f; skelAnime->morphWeight = 1.0f;
skelAnime->morphRate = 1.0f / morphFrames; skelAnime->morphRate = 1.0f / morphFrames;
} else { } else {
LinkAnimation_SetUpdateFunction(skelAnime); 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; skelAnime->morphWeight = 0.0f;
} }
@ -1270,7 +1317,7 @@ void LinkAnimation_PlayLoopSetSpeed(PlayState* play, SkelAnime* skelAnime, LinkA
* Requests copying jointTable to morphTable * Requests copying jointTable to morphTable
*/ */
void LinkAnimation_CopyJointToMorph(PlayState* play, SkelAnime* skelAnime) { 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 * unused
*/ */
void LinkAnimation_CopyMorphToJoint(PlayState* play, SkelAnime* skelAnime) { 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 * Requests loading frame data from the Link animation into morphTable
*/ */
void LinkAnimation_LoadToMorph(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { 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 * Requests loading frame data from the Link animation into jointTable
*/ */
void LinkAnimation_LoadToJoint(PlayState* play, SkelAnime* skelAnime, LinkAnimationHeader* animation, f32 frame) { 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 * Requests interpolating between jointTable and morphTable, placing the result in jointTable
*/ */
void LinkAnimation_InterpJointMorph(PlayState* play, SkelAnime* skelAnime, f32 weight) { 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) { LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) {
Vec3s* alignedBlendTable; 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); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable);
AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->jointTable, alignedBlendTable, blendWeight); 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) { LinkAnimationHeader* animation2, f32 frame2, f32 blendWeight, Vec3s* blendTable) {
Vec3s* alignedBlendTable; 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); alignedBlendTable = (Vec3s*)ALIGN16((uintptr_t)blendTable);
AnimationContext_SetLoadFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable); AnimTaskQueue_AddLoadPlayerFrame(play, animation2, (s32)frame2, skelAnime->limbCount, alignedBlendTable);
AnimationContext_SetInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight); AnimTaskQueue_AddInterp(play, skelAnime->limbCount, skelAnime->morphTable, alignedBlendTable, blendWeight);
} }
/** /**
@ -1791,6 +1838,7 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) {
f32 sin; f32 sin;
f32 cos; f32 cos;
// If `ANIM_FLAG_UPDATE_XZ` behaved as expected, it would also be checked here
if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) { if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) {
diff->x = diff->z = 0.0f; diff->x = diff->z = 0.0f;
} else { } else {
@ -1800,6 +1848,7 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) {
cos = Math_CosS(angle); cos = Math_CosS(angle);
diff->x = x * cos + z * sin; diff->x = x * cos + z * sin;
diff->z = z * cos - x * sin; diff->z = z * cos - x * sin;
x = skelAnime->prevTransl.x; x = skelAnime->prevTransl.x;
z = skelAnime->prevTransl.z; z = skelAnime->prevTransl.z;
sin = Math_SinS(skelAnime->prevRot); sin = Math_SinS(skelAnime->prevRot);
@ -1809,22 +1858,27 @@ void SkelAnime_UpdateTranslation(SkelAnime* skelAnime, Vec3f* diff, s16 angle) {
} }
skelAnime->prevRot = angle; skelAnime->prevRot = angle;
skelAnime->prevTransl.x = skelAnime->jointTable[0].x; skelAnime->prevTransl.x = skelAnime->jointTable[0].x;
skelAnime->jointTable[0].x = skelAnime->baseTransl.x; skelAnime->jointTable[0].x = skelAnime->baseTransl.x;
skelAnime->prevTransl.z = skelAnime->jointTable[0].z; skelAnime->prevTransl.z = skelAnime->jointTable[0].z;
skelAnime->jointTable[0].z = skelAnime->baseTransl.z; skelAnime->jointTable[0].z = skelAnime->baseTransl.z;
if (skelAnime->moveFlags & ANIM_FLAG_UPDATE_Y) { if (skelAnime->moveFlags & ANIM_FLAG_UPDATE_Y) {
if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) { if (skelAnime->moveFlags & ANIM_FLAG_NO_MOVE) {
diff->y = 0.0f; diff->y = 0.0f;
} else { } else {
diff->y = skelAnime->jointTable[0].y - skelAnime->prevTransl.y; diff->y = skelAnime->jointTable[0].y - skelAnime->prevTransl.y;
} }
skelAnime->prevTransl.y = skelAnime->jointTable[0].y; skelAnime->prevTransl.y = skelAnime->jointTable[0].y;
skelAnime->jointTable[0].y = skelAnime->baseTransl.y; skelAnime->jointTable[0].y = skelAnime->baseTransl.y;
} else { } else {
diff->y = 0.0f; diff->y = 0.0f;
skelAnime->prevTransl.y = skelAnime->jointTable[0].y; skelAnime->prevTransl.y = skelAnime->jointTable[0].y;
} }
skelAnime->moveFlags &= ~ANIM_FLAG_NO_MOVE; skelAnime->moveFlags &= ~ANIM_FLAG_NO_MOVE;
} }

View file

@ -1,4 +1,4 @@
#include "global.h" #include "ultra64.h"
/** /**
* @param angle binang * @param angle binang

View file

@ -89,7 +89,7 @@ void func_8087DB24(BgHakaMegane* this, PlayState* play) {
this->dyna.actor.objectSlot = this->requiredObjectSlot; this->dyna.actor.objectSlot = this->requiredObjectSlot;
this->dyna.actor.draw = BgHakaMegane_Draw; this->dyna.actor.draw = BgHakaMegane_Draw;
Actor_SetObjectDependency(play, &this->dyna.actor); 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* colHeader;
CollisionHeader* collision; CollisionHeader* collision;

View file

@ -176,20 +176,20 @@ void DemoEc_UpdateBgFlags(DemoEc* this, PlayState* play) {
} }
void func_8096D594(DemoEc* this, PlayState* play) { void func_8096D594(DemoEc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void func_8096D5D4(DemoEc* this, PlayState* play) {
this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.baseTransl = this->skelAnime.jointTable[0];
this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void func_8096D64C(DemoEc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void DemoEc_UpdateEyes(DemoEc* this) {

View file

@ -54,12 +54,12 @@ s32 DemoIk_CheckForCue(PlayState* play, u16 cueId, s32 cueChannel) {
} }
void DemoIk_SetMove(DemoIk* this, PlayState* play) { void DemoIk_SetMove(DemoIk* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void DemoIk_EndMove(DemoIk* this) { void DemoIk_EndMove(DemoIk* this) {
this->skelAnime.moveFlags &= ~ANIM_FLAG_0; this->skelAnime.moveFlags &= ~ANIM_FLAG_UPDATE_XZ;
} }
f32 DemoIk_GetCurFrame(DemoIk* this) { f32 DemoIk_GetCurFrame(DemoIk* this) {

View file

@ -337,8 +337,8 @@ void func_80A795C8(EnIn* this, PlayState* play) {
void func_80A79690(SkelAnime* skelAnime, EnIn* this, PlayState* play) { void func_80A79690(SkelAnime* skelAnime, EnIn* this, PlayState* play) {
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }

View file

@ -756,8 +756,8 @@ void EnNb_InitDemo6KInConfrontation(EnNb* this, PlayState* play) {
} }
void func_80AB2688(EnNb* this, PlayState* play) { void func_80AB2688(EnNb* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime, 1.0f);
} }
void func_80AB26C8(EnNb* this) { void func_80AB26C8(EnNb* this) {

View file

@ -391,17 +391,17 @@ s32 EnRu1_UpdateSkelAnime(EnRu1* this) {
} }
void func_80AEB364(EnRu1* this, PlayState* play) { void func_80AEB364(EnRu1* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
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) { void func_80AEB3A4(EnRu1* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
func_80AEB364(this, play); func_80AEB364(this, play);
} }
void func_80AEB3CC(EnRu1* this) { void func_80AEB3CC(EnRu1* this) {
this->skelAnime.moveFlags &= ~ANIM_FLAG_0; this->skelAnime.moveFlags &= ~ANIM_FLAG_UPDATE_XZ;
} }
void func_80AEB3DC(EnRu1* this, PlayState* play) { void func_80AEB3DC(EnRu1* this, PlayState* play) {
@ -462,8 +462,8 @@ void func_80AEB6E0(EnRu1* this, PlayState* play) {
SkelAnime* skelAnime = &this->skelAnime; SkelAnime* skelAnime = &this->skelAnime;
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }
@ -473,13 +473,13 @@ void func_80AEB738(EnRu1* this, PlayState* play) {
skelAnime->baseTransl = skelAnime->jointTable[0]; skelAnime->baseTransl = skelAnime->jointTable[0];
skelAnime->prevTransl = skelAnime->jointTable[0]; skelAnime->prevTransl = skelAnime->jointTable[0];
if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) { if (skelAnime->baseTransl.y < skelAnime->jointTable[0].y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y;
AnimationContext_SetMoveActor(play, &this->actor, skelAnime, 1.0f); AnimTaskQueue_AddActorMove(play, &this->actor, skelAnime, 1.0f);
} }
} }
void func_80AEB7D0(EnRu1* this) { void func_80AEB7D0(EnRu1* this) {
this->skelAnime.moveFlags &= ~(ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y); this->skelAnime.moveFlags &= ~(ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y);
} }
f32 func_80AEB7E0(CsCmdActorCue* cue, PlayState* play) { f32 func_80AEB7E0(CsCmdActorCue* cue, PlayState* play) {

View file

@ -61,7 +61,7 @@ void func_80862FA8(EnTest* this, PlayState* play);
s32 EnTest_ReactToProjectile(PlayState* play, EnTest* this); s32 EnTest_ReactToProjectile(PlayState* play, EnTest* this);
static u8 sJointCopyFlags[] = { static u8 sUpperBodyLimbCopyMap[] = {
false, // STALFOS_LIMB_NONE false, // STALFOS_LIMB_NONE
false, // STALFOS_LIMB_ROOT false, // STALFOS_LIMB_ROOT
false, // STALFOS_LIMB_UPPERBODY_ROOT false, // STALFOS_LIMB_UPPERBODY_ROOT
@ -1742,15 +1742,15 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
case 1: case 1:
Animation_Change(&this->upperSkelanime, &gStalfosBlockWithShieldAnim, 2.0f, 0.0f, Animation_Change(&this->upperSkelanime, &gStalfosBlockWithShieldAnim, 2.0f, 0.0f,
Animation_GetLastFrame(&gStalfosBlockWithShieldAnim), 2, 2.0f); Animation_GetLastFrame(&gStalfosBlockWithShieldAnim), 2, 2.0f);
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
this->unk_7DE++; this->unk_7DE++;
break; break;
case 2: case 2:
SkelAnime_Update(&this->upperSkelanime); SkelAnime_Update(&this->upperSkelanime);
SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
break; break;
case 3: case 3:
@ -1769,7 +1769,7 @@ void EnTest_Update(Actor* thisx, PlayState* play) {
this->upperSkelanime.jointTable, this->skelAnime.jointTable, this->upperSkelanime.jointTable, this->skelAnime.jointTable,
1.0f - (this->upperSkelanime.morphWeight / oldWeight)); 1.0f - (this->upperSkelanime.morphWeight / oldWeight));
SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable, SkelAnime_CopyFrameTableTrue(&this->skelAnime, this->skelAnime.jointTable,
this->upperSkelanime.jointTable, sJointCopyFlags); this->upperSkelanime.jointTable, sUpperBodyLimbCopyMap);
break; break;
} }

View file

@ -254,25 +254,25 @@ void func_80B3C8CC(EnXc* this, PlayState* play) {
SkelAnime* skelAnime = &this->skelAnime; SkelAnime* skelAnime = &this->skelAnime;
if (skelAnime->jointTable[0].y >= skelAnime->baseTransl.y) { if (skelAnime->jointTable[0].y >= skelAnime->baseTransl.y) {
skelAnime->moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; skelAnime->moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void func_80B3C924(EnXc* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void func_80B3C964(EnXc* this, PlayState* play) {
this->skelAnime.baseTransl = this->skelAnime.jointTable[0]; this->skelAnime.baseTransl = this->skelAnime.jointTable[0];
this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
this->skelAnime.moveFlags |= ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ | 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) { void func_80B3C9DC(EnXc* this) {
this->skelAnime.moveFlags &= ~(ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y); this->skelAnime.moveFlags &= ~(ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y);
} }
void func_80B3C9EC(EnXc* this) { void func_80B3C9EC(EnXc* this) {

View file

@ -345,8 +345,8 @@ void func_80B4B834(CsCmdActorCue* cue, Vec3f* dest) {
} }
void func_80B4B874(EnZl1* this, PlayState* play) { void func_80B4B874(EnZl1* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
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) { void func_80B4B8B4(EnZl1* this, PlayState* play) {

View file

@ -298,8 +298,8 @@ void EnZl4_UpdateFace(EnZl4* this) {
} }
void EnZl4_SetMove(EnZl4* this, PlayState* play) { void EnZl4_SetMove(EnZl4* this, PlayState* play) {
this->skelAnime.moveFlags |= ANIM_FLAG_0; this->skelAnime.moveFlags |= ANIM_FLAG_UPDATE_XZ;
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) { void func_80B5BB78(EnZl4* this, PlayState* play) {

View file

@ -11,7 +11,7 @@
#include "terminal.h" #include "terminal.h"
// For retail BSS ordering, the block number of sStreamSfxProjectedPos must be 0. // For retail BSS ordering, the block number of sStreamSfxProjectedPos must be 0.
#pragma increment_block_number 198 #pragma increment_block_number 190
#define FLAGS ACTOR_FLAG_4 #define FLAGS ACTOR_FLAG_4

View file

@ -1989,7 +1989,7 @@ void Player_AnimReplaceApplyFlags(PlayState* play, Player* this, s32 flags) {
this->skelAnime.moveFlags = flags & 0xFF; this->skelAnime.moveFlags = flags & 0xFF;
Player_ZeroSpeedXZ(this); Player_ZeroSpeedXZ(this);
AnimationContext_DisableQueue(play); AnimTaskQueue_DisableTransformTasksForGroup(play);
} }
void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags, void Player_AnimReplacePlayOnceSetSpeed(PlayState* play, Player* this, LinkAnimationHeader* anim, s32 flags,
@ -3071,7 +3071,7 @@ s32 func_808358F0(Player* this, PlayState* play) {
if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) || if ((func_808334E4(this) == animSeg) || (func_80833528(this) == animSeg) || (func_808335B0(this) == animSeg) ||
(func_808335F4(this) == animSeg)) { (func_808335F4(this) == animSeg)) {
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable); this->skelAnime.jointTable);
} else { } else {
LinkAnimation_Update(play, &this->upperSkelAnime); LinkAnimation_Update(play, &this->upperSkelAnime);
@ -3399,8 +3399,8 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) {
this->stateFlags3 |= PLAYER_STATE3_7; this->stateFlags3 |= PLAYER_STATE3_7;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_hook_fly_start); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_hook_fly_start);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
func_80832224(this); func_80832224(this);
this->yaw = this->actor.shape.rot.y; this->yaw = this->actor.shape.rot.y;
this->actor.bgCheckFlags &= ~BGCHECKFLAG_GROUND; this->actor.bgCheckFlags &= ~BGCHECKFLAG_GROUND;
@ -3425,21 +3425,21 @@ s32 Player_UpdateUpperBody(Player* this, PlayState* play) {
// The functionality contained within this block of code is never used in practice // The functionality contained within this block of code is never used in practice
// because `upperAnimInterpWeight` is always 0. // because `upperAnimInterpWeight` is always 0.
if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) {
AnimationContext_SetCopyFalse(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable, AnimTaskQueue_AddCopyUsingMapInverted(play, this->skelAnime.limbCount, this->upperSkelAnime.jointTable,
this->skelAnime.jointTable, sUpperBodyLimbCopyMap); this->skelAnime.jointTable, sUpperBodyLimbCopyMap);
} }
Math_StepToF(&this->upperAnimInterpWeight, 0.0f, 0.25f); Math_StepToF(&this->upperAnimInterpWeight, 0.0f, 0.25f);
AnimationContext_SetInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddInterp(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight); this->upperSkelAnime.jointTable, 1.0f - this->upperAnimInterpWeight);
} else if ((func_80833350(this) == 0) || (this->speedXZ != 0.0f)) { } 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. // 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. // 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, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
} else { } else {
// Copy all of the upper body animation into the whole main skeleton. // Copy all of the upper body animation into the whole main skeleton.
// The upper body has full control of all limbs. // The upper body has full control of all limbs.
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable); this->upperSkelAnime.jointTable);
} }
@ -4144,7 +4144,8 @@ void func_80837948(PlayState* play, Player* this, s32 arg2) {
Player_AnimPlayOnceAdjusted(play, this, D_80854190[arg2].unk_00); Player_AnimPlayOnceAdjusted(play, this, D_80854190[arg2].unk_00);
if ((arg2 != PLAYER_MWA_FLIPSLASH_START) && (arg2 != PLAYER_MWA_JUMPSLASH_START)) { if ((arg2 != PLAYER_MWA_FLIPSLASH_START) && (arg2 != PLAYER_MWA_JUMPSLASH_START)) {
Player_AnimReplaceApplyFlags(play, this, ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_0 | ANIM_FLAG_PLAYER_SETMOVE); Player_AnimReplaceApplyFlags(play, this,
ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_SETMOVE);
} }
this->yaw = this->actor.shape.rot.y; this->yaw = this->actor.shape.rot.y;
@ -4189,7 +4190,7 @@ s32 func_80837B18(PlayState* play, Player* this, s32 damage) {
void func_80837B60(Player* this) { void func_80837B60(Player* this) {
this->skelAnime.prevTransl = this->skelAnime.jointTable[0]; this->skelAnime.prevTransl = this->skelAnime.jointTable[0];
func_80832E48(this, ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y); func_80832E48(this, ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y);
} }
void func_80837B9C(Player* this, PlayState* play) { void func_80837B9C(Player* this, PlayState* play) {
@ -4650,7 +4651,7 @@ s32 Player_ActionChange_12(Player* this, PlayState* play) {
this->actor.bgCheckFlags |= BGCHECKFLAG_GROUND; this->actor.bgCheckFlags |= BGCHECKFLAG_GROUND;
LinkAnimation_PlayOnceSetSpeed(play, &this->skelAnime, anim, 1.3f); 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; this->actor.shape.rot.y = this->yaw = this->actor.wallYaw + 0x8000;
@ -5054,7 +5055,7 @@ s32 Player_ActionChange_1(Player* this, PlayState* play) {
func_80832224(this); func_80832224(this);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y |
ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7);
// If this door is the second half of a double door (spawned as child) // If this door is the second half of a double door (spawned as child)
@ -5365,7 +5366,7 @@ s32 func_8083A6AC(Player* this, PlayState* play) {
this->stateFlags1 |= PLAYER_STATE1_21; this->stateFlags1 |= PLAYER_STATE1_21;
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 |
ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
this->av2.actionVar2 = -1; this->av2.actionVar2 = -1;
@ -6720,8 +6721,8 @@ s32 Player_ActionChange_3(Player* this, PlayState* play) {
Actor_MountHorse(play, this, &rideActor->actor); Actor_MountHorse(play, this, &rideActor->actor);
Player_AnimPlayOnce(play, this, D_80854578[temp].anim); Player_AnimPlayOnce(play, this, D_80854578[temp].anim);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
this->actor.parent = this->rideActor; this->actor.parent = this->rideActor;
func_80832224(this); func_80832224(this);
@ -6888,7 +6889,7 @@ s32 Player_ActionChange_2(Player* this, PlayState* play) {
(Item_CheckObtainability(giEntry->itemId) == ITEM_NONE)) { (Item_CheckObtainability(giEntry->itemId) == ITEM_NONE)) {
Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98); Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_98);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y |
ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_7);
chest->unk_1F4 = 1; chest->unk_1F4 = 1;
@ -7067,7 +7068,7 @@ s32 func_8083EC18(Player* this, PlayState* play, u32 wallFlags) {
Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.world.pos); Math_Vec3f_Copy(&this->actor.prevPos, &this->actor.world.pos);
Player_AnimPlayOnce(play, this, anim); Player_AnimPlayOnce(play, this, anim);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 |
ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
return true; return true;
@ -7148,7 +7149,7 @@ s32 Player_TryEnteringCrawlspace(Player* this, PlayState* play, u32 interactWall
this->actor.prevPos = this->actor.world.pos; this->actor.prevPos = this->actor.world.pos;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_start);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
return true; return true;
@ -7238,7 +7239,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) {
this->actor.shape.rot.y = this->actor.wallYaw + 0x8000; this->actor.shape.rot.y = this->actor.wallYaw + 0x8000;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_child_tunnel_end);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
OnePointCutscene_Init(play, 9601, 999, NULL, CAM_ID_MAIN); OnePointCutscene_Init(play, 9601, 999, NULL, CAM_ID_MAIN);
} else { } else {
@ -7248,7 +7249,7 @@ s32 Player_TryLeavingCrawlspace(Player* this, PlayState* play) {
Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE, Animation_GetLastFrame(&gPlayerAnim_link_child_tunnel_start), 0.0f, ANIMMODE_ONCE,
0.0f); 0.0f);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
OnePointCutscene_Init(play, 9602, 999, NULL, CAM_ID_MAIN); OnePointCutscene_Init(play, 9602, 999, NULL, CAM_ID_MAIN);
} }
@ -8105,9 +8106,9 @@ void Player_Action_80841BA8(Player* this, PlayState* play) {
LinkAnimation_Update(play, &this->skelAnime); LinkAnimation_Update(play, &this->skelAnime);
if (Player_HoldsTwoHandedWeapon(this)) { if (Player_HoldsTwoHandedWeapon(this)) {
AnimationContext_SetLoadFrame(play, func_80833338(this), 0, this->skelAnime.limbCount, AnimTaskQueue_AddLoadPlayerFrame(play, func_80833338(this), 0, this->skelAnime.limbCount,
this->skelAnime.morphTable); this->skelAnime.morphTable);
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->skelAnime.morphTable, sUpperBodyLimbCopyMap); this->skelAnime.morphTable, sUpperBodyLimbCopyMap);
} }
@ -9033,7 +9034,7 @@ void Player_Action_8084411C(Player* this, PlayState* play) {
} else if ((this->ledgeClimbType >= PLAYER_LEDGE_CLIMB_2) && (this->yDistToLedge < 150.0f) && } else if ((this->ledgeClimbType >= PLAYER_LEDGE_CLIMB_2) && (this->yDistToLedge < 150.0f) &&
(((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) > (((this->actor.world.pos.y - this->actor.floorHeight) + this->yDistToLedge) >
(70.0f * this->ageProperties->unk_08))) { (70.0f * this->ageProperties->unk_08))) {
AnimationContext_DisableQueue(play); AnimTaskQueue_DisableTransformTasksForGroup(play);
if (this->stateFlags1 & PLAYER_STATE1_2) { if (this->stateFlags1 & PLAYER_STATE1_2) {
func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG); func_80832698(this, NA_SE_VO_LI_HOOKSHOT_HANG);
} else { } else {
@ -9967,8 +9968,8 @@ void func_808467D4(PlayState* play, Player* this) {
LinkAnimation_Change(play, &this->skelAnime, this->ageProperties->unk_A0, 2.0f / 3.0f, 0.0f, 0.0f, ANIMMODE_ONCE, LinkAnimation_Change(play, &this->skelAnime, this->ageProperties->unk_A0, 2.0f / 3.0f, 0.0f, 0.0f, ANIMMODE_ONCE,
0.0f); 0.0f);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y |
ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7);
if (LINK_IS_ADULT) { if (LINK_IS_ADULT) {
func_80846720(play, this, 0); func_80846720(play, this, 0);
} }
@ -9978,8 +9979,8 @@ void func_808467D4(PlayState* play, Player* this) {
void func_808468A8(PlayState* play, Player* this) { void func_808468A8(PlayState* play, Player* this) {
Player_SetupAction(play, this, Player_Action_8084F9A0, 0); Player_SetupAction(play, this, Player_Action_8084F9A0, 0);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
} }
void func_808468E8(PlayState* play, Player* this) { void func_808468E8(PlayState* play, Player* this) {
@ -11134,7 +11135,7 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
this->stateFlags1 |= PLAYER_STATE1_23; this->stateFlags1 |= PLAYER_STATE1_23;
Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_1); Player_AnimPlayOnce(play, this, &gPlayerAnim_link_uma_wait_1);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
this->av2.actionVar2 = 99; this->av2.actionVar2 = 99;
} }
@ -11345,9 +11346,9 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
Player_UpdateCamAndSeqModes(play, this); Player_UpdateCamAndSeqModes(play, this);
if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) { if (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_SETMOVE) {
AnimationContext_SetMoveActor( AnimTaskQueue_AddActorMove(play, &this->actor, &this->skelAnime,
play, &this->actor, &this->skelAnime, (this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f
(this->skelAnime.moveFlags & ANIM_FLAG_PLAYER_2) ? 1.0f : this->ageProperties->unk_08); : this->ageProperties->unk_08);
} }
Player_UpdateShapeYaw(this, play); Player_UpdateShapeYaw(this, play);
@ -11417,8 +11418,10 @@ void Player_UpdateCommon(Player* this, PlayState* play, Input* input) {
} }
} }
} }
// Because Player updates early relative to most actors, his animation tasks will belong to group 0.
AnimationContext_SetNextQueue(play); // 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); Math_Vec3f_Copy(&this->actor.home.pos, &this->actor.world.pos);
@ -12152,7 +12155,7 @@ void Player_Action_8084BDFC(Player* this, PlayState* play) {
this->stateFlags2 |= PLAYER_STATE2_6; this->stateFlags2 |= PLAYER_STATE2_6;
if (LinkAnimation_Update(play, &this->skelAnime)) { if (LinkAnimation_Update(play, &this->skelAnime)) {
func_80832E48(this, ANIM_FLAG_0); func_80832E48(this, ANIM_FLAG_UPDATE_XZ);
func_8083C0E8(this, play); func_8083C0E8(this, play);
return; return;
} }
@ -12635,8 +12638,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
LinkAnimation_AnimateFrame(play, &this->skelAnime); LinkAnimation_AnimateFrame(play, &this->skelAnime);
} }
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.morphTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.morphTable, this->skelAnime.jointTable);
this->skelAnime.jointTable);
if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != PLAYER_CSACTION_NONE)) { if ((play->csCtx.state != CS_STATE_IDLE) || (this->csAction != PLAYER_CSACTION_NONE)) {
if (this->csAction == PLAYER_CSACTION_7) { if (this->csAction == PLAYER_CSACTION_7) {
@ -12674,7 +12676,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
func_80832698(this, NA_SE_VO_LI_LASH); func_80832698(this, NA_SE_VO_LI_LASH);
} }
AnimationContext_SetCopyAll(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopy(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable); this->upperSkelAnime.jointTable);
} else { } else {
if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) { if (LinkAnimation_OnFrame(&this->upperSkelAnime, 10.0f)) {
@ -12682,7 +12684,7 @@ void Player_Action_8084CC98(Player* this, PlayState* play) {
func_80832698(this, NA_SE_VO_LI_LASH); func_80832698(this, NA_SE_VO_LI_LASH);
} }
AnimationContext_SetCopyTrue(play, this->skelAnime.limbCount, this->skelAnime.jointTable, AnimTaskQueue_AddCopyUsingMap(play, this->skelAnime.limbCount, this->skelAnime.jointTable,
this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap); this->upperSkelAnime.jointTable, sUpperBodyLimbCopyMap);
} }
} else { } else {
@ -14799,8 +14801,8 @@ void func_808519EC(PlayState* play, Player* this, CsCmdActorCue* cue) {
this->actor.shape.rot.y = -0x8000; this->actor.shape.rot.y = -0x8000;
Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_9C); Player_AnimPlayOnceAdjusted(play, this, this->ageProperties->unk_9C);
Player_AnimReplaceApplyFlags(play, this, Player_AnimReplaceApplyFlags(play, this,
ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_0 | ANIM_FLAG_UPDATE_Y | ANIM_FLAG_PLAYER_2 | ANIM_REPLACE_APPLY_FLAG_9 | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_UPDATE_Y |
ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7); ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_PLAYER_7);
} }
static struct_808551A4 D_808551A4[] = { static struct_808551A4 D_808551A4[] = {
@ -14976,8 +14978,8 @@ void func_80852048(PlayState* play, Player* this, CsCmdActorCue* cue) {
void func_80852080(PlayState* play, Player* this, CsCmdActorCue* cue) { void func_80852080(PlayState* play, Player* this, CsCmdActorCue* cue) {
Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_clink_demo_futtobi, Player_AnimReplacePlayOnceAdjusted(play, this, &gPlayerAnim_clink_demo_futtobi,
ANIM_FLAG_0 | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE | ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_2 | ANIM_FLAG_PLAYER_SETMOVE |
ANIM_FLAG_PLAYER_7); ANIM_FLAG_NO_MOVE | ANIM_FLAG_PLAYER_7);
func_80832698(this, NA_SE_VO_LI_FALL_L); func_80832698(this, NA_SE_VO_LI_FALL_L);
} }
@ -15457,7 +15459,8 @@ void func_80853148(PlayState* play, Actor* actor) {
} }
if (this->skelAnime.animation == &gPlayerAnim_link_normal_backspace) { if (this->skelAnime.animation == &gPlayerAnim_link_normal_backspace) {
Player_AnimReplaceApplyFlags(play, this, ANIM_FLAG_0 | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE); Player_AnimReplaceApplyFlags(play, this,
ANIM_FLAG_UPDATE_XZ | ANIM_FLAG_PLAYER_SETMOVE | ANIM_FLAG_NO_MOVE);
} }
func_80832224(this); func_80832224(this);

View file

@ -1,5 +1,5 @@
CFLAGS := -Wall -Wextra -pedantic -std=c99 -g -O2 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) ifeq ($(shell command -v clang >/dev/null 2>&1; echo $$?),0)
CC := clang CC := clang
@ -36,7 +36,6 @@ mkdmadata_SOURCES := mkdmadata.c spec.c util.c
mkldscript_SOURCES := mkldscript.c spec.c util.c mkldscript_SOURCES := mkldscript.c spec.c util.c
reloc_prereq_SOURCES := reloc_prereq.c spec.c util.c reloc_prereq_SOURCES := reloc_prereq.c spec.c util.c
vtxdis_SOURCES := vtxdis.c vtxdis_SOURCES := vtxdis.c
yaz0_SOURCES := yaz0tool.c yaz0.c util.c
define COMPILE = define COMPILE =

View file

@ -131,6 +131,7 @@ def main():
if not ( if not (
mapfile_segment.name.startswith("..boot") mapfile_segment.name.startswith("..boot")
or mapfile_segment.name.startswith("..code") or mapfile_segment.name.startswith("..code")
or mapfile_segment.name.startswith("..buffers")
or mapfile_segment.name.startswith("..ovl_") or mapfile_segment.name.startswith("..ovl_")
): ):
continue continue
@ -152,13 +153,15 @@ def main():
base_value = read_u32(base, file.vrom + reloc.offset_32) base_value = read_u32(base, file.vrom + reloc.offset_32)
build_value = read_u32(build, 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: 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( if (
build, file.vrom + reloc.offset_hi16 read_u16(base, file.vrom + reloc.offset_hi16)
) or read_u16(base, file.vrom + reloc.offset_hi16) != read_u16( != read_u16(build, file.vrom + reloc.offset_hi16)
build, file.vrom + reloc.offset_hi16 ) or (
read_u16(base, file.vrom + reloc.offset_lo16)
!= read_u16(build, file.vrom + reloc.offset_lo16)
): ):
print( 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.", "Please ensure that the only differences between the baserom and the current build are due to data ordering.",
file=sys.stderr, file=sys.stderr,
) )
@ -186,7 +189,9 @@ def main():
for mapfile_segment in source_code_segments: for mapfile_segment in source_code_segments:
for file in mapfile_segment: for file in mapfile_segment:
pointers_in_section = [ 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: if not pointers_in_section:
continue continue

View file

@ -16,6 +16,7 @@ import ipl3checksum
import zlib import zlib
import dmadata import dmadata
import version_config
def decompress_zlib(data: bytes) -> bytes: def decompress_zlib(data: bytes) -> bytes:
@ -172,8 +173,12 @@ def main():
uncompressed_path = baserom_dir / "baserom-decompressed.z64" uncompressed_path = baserom_dir / "baserom-decompressed.z64"
dmadata_start = int((baserom_dir / "dmadata_start.txt").read_text(), 16) config = version_config.load_version_config(version)
compressed_str_hash = (baserom_dir / "checksum-compressed.md5").read_text().split()[0] dmadata_start = config.dmadata_start
compressed_str_hash = (
(baserom_dir / "checksum-compressed.md5").read_text().split()[0]
)
decompressed_str_hash = (baserom_dir / "checksum.md5").read_text().split()[0] decompressed_str_hash = (baserom_dir / "checksum.md5").read_text().split()[0]
if check_existing_rom(uncompressed_path, decompressed_str_hash): if check_existing_rom(uncompressed_path, decompressed_str_hash):

View file

@ -10,6 +10,7 @@ from pathlib import Path
import sys import sys
import dmadata import dmadata
import version_config
def main(): def main():
@ -19,6 +20,12 @@ def main():
parser.add_argument( parser.add_argument(
"rom", metavar="ROM", type=Path, help="Path to uncompressed ROM" "rom", metavar="ROM", type=Path, help="Path to uncompressed ROM"
) )
parser.add_argument(
"-v",
"--oot-version",
required=True,
help="OOT version",
)
parser.add_argument( parser.add_argument(
"-o", "-o",
"--output-dir", "--output-dir",
@ -29,24 +36,20 @@ def main():
parser.add_argument( parser.add_argument(
"--dmadata-start", "--dmadata-start",
type=lambda s: int(s, 16), type=lambda s: int(s, 16),
required=True,
help=( help=(
"The dmadata location in the rom, as a hexadecimal offset (e.g. 0x12f70)" "Override dmadata location for non-matching ROMs, as a hexadecimal offset (e.g. 0x12F70)"
), ),
) )
parser.add_argument(
"--dmadata-names",
type=Path,
required=True,
help="Path to file containing segment names",
)
args = parser.parse_args() args = parser.parse_args()
rom_data = memoryview(args.rom.read_bytes()) rom_data = memoryview(args.rom.read_bytes())
dma_names = args.dmadata_names.read_text().splitlines() config = version_config.load_version_config(args.oot_version)
dma_entries = dmadata.read_dmadata(rom_data, args.dmadata_start) dmadata_start = args.dmadata_start or config.dmadata_start
dma_names = config.dmadata_segments.keys()
dma_entries = dmadata.read_dmadata(rom_data, dmadata_start)
if len(dma_names) != len(dma_entries): if len(dma_names) != len(dma_entries):
print( print(
f"Error: expected {len(dma_names)} DMA entries but found {len(dma_entries)} in ROM", f"Error: expected {len(dma_names)} DMA entries but found {len(dma_entries)} in ROM",

View file

@ -42,10 +42,6 @@ static void write_ld_script(FILE *fout)
// initialized data (.text, .data, .rodata, .sdata) // 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" fprintf(fout, " _%sSegmentRomStartTemp = _RomSize;\n"
" _%sSegmentRomStart = _%sSegmentRomStartTemp;\n" " _%sSegmentRomStart = _%sSegmentRomStartTemp;\n"
" ..%s ", seg->name, seg->name, seg->name, seg->name); " ..%s ", seg->name, seg->name, seg->name, seg->name);
@ -67,12 +63,15 @@ static void write_ld_script(FILE *fout)
seg->name, seg->name); seg->name, seg->name);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
{
if (!seg->includes[j].dataOnlyWithinRodata)
{ {
fprintf(fout, " %s (.text)\n", seg->includes[j].fpath); fprintf(fout, " %s (.text)\n", seg->includes[j].fpath);
if (seg->includes[j].linkerPadding != 0) if (seg->includes[j].linkerPadding != 0)
fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding); fprintf(fout, " . += 0x%X;\n", seg->includes[j].linkerPadding);
fprintf(fout, " . = ALIGN(0x10);\n"); fprintf(fout, " . = ALIGN(0x10);\n");
} }
}
fprintf(fout, " _%sSegmentTextEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentTextEnd = .;\n", seg->name);
@ -82,20 +81,11 @@ static void write_ld_script(FILE *fout)
for (j = 0; j < seg->includesCount; j++) 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" fprintf(fout, " %s (.data)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = 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, " _%sSegmentDataEnd = .;\n", seg->name);
fprintf(fout, " _%sSegmentDataSize = ABSOLUTE( _%sSegmentDataEnd - _%sSegmentDataStart );\n", seg->name, seg->name, 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++) for (j = 0; j < seg->includesCount; j++)
{ {
if (seg->includes[j].dataWithRodata) if (seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.data)\n" fprintf(fout, " %s (.data)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
@ -116,6 +106,7 @@ static void write_ld_script(FILE *fout)
// the beginning of the entire rodata area in order to remain consistent. // the beginning of the entire rodata area in order to remain consistent.
// Inconsistencies will lead to various .rodata reloc crashes as a result of // Inconsistencies will lead to various .rodata reloc crashes as a result of
// either missing relocs or wrong relocs. // either missing relocs or wrong relocs.
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.rodata)\n" fprintf(fout, " %s (.rodata)\n"
" %s (.rodata.str*)\n" " %s (.rodata.str*)\n"
" %s (.rodata.cst*)\n" " %s (.rodata.cst*)\n"
@ -130,6 +121,7 @@ static void write_ld_script(FILE *fout)
fprintf(fout, " _%sSegmentSDataStart = .;\n", seg->name); fprintf(fout, " _%sSegmentSDataStart = .;\n", seg->name);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.sdata)\n" fprintf(fout, " %s (.sdata)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
@ -138,6 +130,7 @@ static void write_ld_script(FILE *fout)
fprintf(fout, " _%sSegmentOvlStart = .;\n", seg->name); fprintf(fout, " _%sSegmentOvlStart = .;\n", seg->name);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath); fprintf(fout, " %s (.ovl)\n", seg->includes[j].fpath);
fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name); fprintf(fout, " _%sSegmentOvlEnd = .;\n", seg->name);
@ -166,18 +159,22 @@ static void write_ld_script(FILE *fout)
seg->name, seg->name, seg->name, seg->name); seg->name, seg->name, seg->name, seg->name);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.sbss)\n" fprintf(fout, " %s (.sbss)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.scommon)\n" fprintf(fout, " %s (.scommon)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (.bss)\n" fprintf(fout, " %s (.bss)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
for (j = 0; j < seg->includesCount; j++) for (j = 0; j < seg->includesCount; j++)
if (!seg->includes[j].dataOnlyWithinRodata)
fprintf(fout, " %s (COMMON)\n" fprintf(fout, " %s (COMMON)\n"
" . = ALIGN(0x10);\n", seg->includes[j].fpath); " . = ALIGN(0x10);\n", seg->includes[j].fpath);
@ -187,25 +184,6 @@ static void write_ld_script(FILE *fout)
" }\n" " }\n"
" _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n", " _%sSegmentBssSize = ABSOLUTE( _%sSegmentBssEnd - _%sSegmentBssStart );\n\n",
seg->name, seg->name, seg->name, seg->name, seg->name); 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); fputs(" _RomEnd = _RomSize;\n\n", fout);

View file

@ -7,6 +7,8 @@ import re, struct
from os import path from os import path
import argparse import argparse
import version_config
# =================================================== # ===================================================
# Util # Util
# =================================================== # ===================================================
@ -21,10 +23,16 @@ def as_word_list(b):
return None return None
return [i[0] for i in struct.iter_unpack(">I", b)] return [i[0] for i in struct.iter_unpack(">I", b)]
def as_message_table_entry(b): def read_message_table(b, offset):
if len(b) % 8 != 0: table = []
return None while True:
return [(e[0], e[1]>>0x4&0xF, e[1]&0xF, e[2]) for e in [i for i in struct.iter_unpack(">HBxI", b)]] e = struct.unpack(">HBxI", b[offset:offset+8])
entry = (e[0], e[1]>>0x4&0xF, e[1]&0xF, e[2])
table.append(entry)
offset += 8
if entry[0] == 0xFFFF:
break
return table
def segmented_to_physical(address): def segmented_to_physical(address):
return address & ~0x07000000 return address & ~0x07000000
@ -266,7 +274,6 @@ nes_message_entry_table_addr = None
ger_message_entry_table_addr = None ger_message_entry_table_addr = None
fra_message_entry_table_addr = None fra_message_entry_table_addr = None
staff_message_entry_table_addr = None staff_message_entry_table_addr = None
staff_message_entry_table_addr_end = None
nes_message_entry_table = [] nes_message_entry_table = []
ger_message_entry_table = [] ger_message_entry_table = []
@ -285,10 +292,10 @@ def read_tables():
global staff_message_entry_table global staff_message_entry_table
baserom = None baserom = None
with open(f"baseroms/{version}/baserom-decompressed.z64","rb") as infile: with open(f"extracted/{version}/baserom/code","rb") as infile:
baserom = infile.read() baserom = infile.read()
nes_message_entry_table = as_message_table_entry(baserom[nes_message_entry_table_addr:ger_message_entry_table_addr]) nes_message_entry_table = read_message_table(baserom, nes_message_entry_table_addr)
ids = [entry[0] for entry in nes_message_entry_table if entry[0] != 0xFFFC] ids = [entry[0] for entry in nes_message_entry_table if entry[0] != 0xFFFC]
ger_message_entry_table = list(zip(ids,as_word_list(baserom[ger_message_entry_table_addr: fra_message_entry_table_addr]))) ger_message_entry_table = list(zip(ids,as_word_list(baserom[ger_message_entry_table_addr: fra_message_entry_table_addr])))
@ -300,7 +307,7 @@ def read_tables():
else: else:
combined_message_entry_table.append((*entry, None, None)) combined_message_entry_table.append((*entry, None, None))
staff_message_entry_table = as_message_table_entry(baserom[staff_message_entry_table_addr:staff_message_entry_table_addr_end]) staff_message_entry_table = read_message_table(baserom, staff_message_entry_table_addr)
# =================================================== # ===================================================
# Run # Run
@ -421,7 +428,6 @@ def main():
global ger_message_entry_table_addr global ger_message_entry_table_addr
global fra_message_entry_table_addr global fra_message_entry_table_addr
global staff_message_entry_table_addr global staff_message_entry_table_addr
global staff_message_entry_table_addr_end
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description="Extract text from the baserom into .h files" description="Extract text from the baserom into .h files"
@ -437,26 +443,14 @@ def main():
parser.error("No output file requested") parser.error("No output file requested")
version = args.oot_version version = args.oot_version
if version == "gc-eu-mq-dbg":
nes_message_entry_table_addr = 0x00BC24C0 config = version_config.load_version_config(version)
ger_message_entry_table_addr = 0x00BC66E8 code_vram = config.dmadata_segments["code"].vram
fra_message_entry_table_addr = 0x00BC87F8
staff_message_entry_table_addr = 0x00BCA908 nes_message_entry_table_addr = config.variables["sNesMessageEntryTable"] - code_vram
staff_message_entry_table_addr_end = 0x00BCAA90 ger_message_entry_table_addr = config.variables["sGerMessageEntryTable"] - code_vram
elif version == "gc-eu-mq": fra_message_entry_table_addr = config.variables["sFraMessageEntryTable"] - code_vram
nes_message_entry_table_addr = 0x00B7E8F0 staff_message_entry_table_addr = config.variables["sStaffMessageEntryTable"] - code_vram
ger_message_entry_table_addr = 0x00B82B18
fra_message_entry_table_addr = 0x00B84C28
staff_message_entry_table_addr = 0x00B86D38
staff_message_entry_table_addr_end = 0x00B86EC0
elif version == "gc-eu":
nes_message_entry_table_addr = 0x00B7E910
ger_message_entry_table_addr = 0x00B82B38
fra_message_entry_table_addr = 0x00B84C48
staff_message_entry_table_addr = 0x00B86D58
staff_message_entry_table_addr_end = 0x00B86EE0
else:
parser.error("Unsupported OOT version")
extract_all_text(args.text_out, args.staff_text_out) extract_all_text(args.text_out, args.staff_text_out)

View file

@ -136,7 +136,8 @@ static const char *const stmtNames[] =
[STMT_entry] = "entry", [STMT_entry] = "entry",
[STMT_flags] = "flags", [STMT_flags] = "flags",
[STMT_include] = "include", [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_name] = "name",
[STMT_number] = "number", [STMT_number] = "number",
[STMT_romalign] = "romalign", [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) { bool parse_segment_statement(struct Segment *currSeg, STMTId stmt, char* args, int lineNum) {
// ensure no duplicates (except for 'include' or 'pad_text') // 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))) (currSeg->fields & (1 << stmt)))
util_fatal_error("line %i: duplicate '%s' statement", lineNum, stmtNames[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); util_fatal_error("line %i: alignment is not a power of two", lineNum);
break; break;
case STMT_include: case STMT_include:
case STMT_include_data_with_rodata: case STMT_include_data_only_within_rodata:
case STMT_include_no_data:
currSeg->includesCount++; currSeg->includesCount++;
currSeg->includes = realloc(currSeg->includes, currSeg->includesCount * sizeof(*currSeg->includes)); 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); util_fatal_error("line %i: invalid filename", lineNum);
currSeg->includes[currSeg->includesCount - 1].linkerPadding = 0; 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; break;
case STMT_increment: case STMT_increment:
if (!parse_number(args, &currSeg->increment)) if (!parse_number(args, &currSeg->increment))

View file

@ -14,7 +14,8 @@ typedef enum {
STMT_entry, STMT_entry,
STMT_flags, STMT_flags,
STMT_include, STMT_include,
STMT_include_data_with_rodata, STMT_include_data_only_within_rodata,
STMT_include_no_data,
STMT_name, STMT_name,
STMT_number, STMT_number,
STMT_romalign, STMT_romalign,
@ -34,7 +35,8 @@ enum {
struct Include { struct Include {
char* fpath; char* fpath;
int linkerPadding; int linkerPadding;
uint8_t dataWithRodata; bool dataOnlyWithinRodata;
bool noData;
}; };
typedef struct Segment { typedef struct Segment {

53
tools/version_config.py Normal file
View file

@ -0,0 +1,53 @@
# Version-specific configuration for setup and assets extraction
# SPDX-FileCopyrightText: © 2024 ZeldaRET
# SPDX-License-Identifier: CC0-1.0
from __future__ import annotations
from collections import OrderedDict
import csv
import dataclasses
from pathlib import Path
from typing import Optional
import yaml
PROJECT_ROOT = Path(__file__).parent.parent
@dataclasses.dataclass
class VersionConfig:
# ROM offset to start of DMA table
dmadata_start: int
# DMA segment information, in ROM order
dmadata_segments: OrderedDict[str, SegmentInfo]
# Addresses of important variables needed for asset extraction
variables: Dict[str, int]
@dataclasses.dataclass
class SegmentInfo:
name: str
vram: int | None
def load_dmadata_segments(version: str) -> OrderedDict[str, SegmentInfo]:
segments = OrderedDict()
with open(PROJECT_ROOT / f"baseroms/{version}/segments.csv", "r") as f:
reader = csv.DictReader(f)
for row in reader:
name = row["Name"]
vram = int(row["VRAM start"], 16) if row["VRAM start"] else None
segments[name] = SegmentInfo(name, vram)
return segments
def load_version_config(version: str) -> VersionConfig:
with open(PROJECT_ROOT / f"baseroms/{version}/config.yml", "r") as f:
config = yaml.load(f, Loader=yaml.Loader)
return VersionConfig(
dmadata_start=config["dmadata_start"],
dmadata_segments=load_dmadata_segments(version),
variables=config["variables"],
)

View file

@ -1,238 +0,0 @@
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#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;
}

View file

@ -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_

View file

@ -1,201 +0,0 @@
#ifdef __linux__
#define _POSIX_C_SOURCE 199309L
#endif
#include <stdarg.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#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;
}