diff --git a/assets/xml/misc/link_animetion.xml b/assets/xml/misc/link_animetion.xml
index 788e0a49d..2bb5826dd 100644
--- a/assets/xml/misc/link_animetion.xml
+++ b/assets/xml/misc/link_animetion.xml
@@ -1,699 +1,699 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/xml/objects/gameplay_keep.xml b/assets/xml/objects/gameplay_keep.xml
index 03ed9eef5..ca0aaeb3c 100644
--- a/assets/xml/objects/gameplay_keep.xml
+++ b/assets/xml/objects/gameplay_keep.xml
@@ -39,7 +39,7 @@
-
+
@@ -69,703 +69,722 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -915,18 +934,23 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1353,8 +1377,8 @@
-
-
+
+
diff --git a/assets/xml/objects/object_trt.xml b/assets/xml/objects/object_trt.xml
index 826aa1ef0..9f024f9cb 100644
--- a/assets/xml/objects/object_trt.xml
+++ b/assets/xml/objects/object_trt.xml
@@ -51,10 +51,10 @@
-
+
-
+
->
diff --git a/assets/xml/objects/object_tru.xml b/assets/xml/objects/object_tru.xml
index 138723ceb..db35ec604 100644
--- a/assets/xml/objects/object_tru.xml
+++ b/assets/xml/objects/object_tru.xml
@@ -1,108 +1,117 @@

+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/xml/objects/object_wiz.xml b/assets/xml/objects/object_wiz.xml
index 2928083aa..51fcae3a7 100644
--- a/assets/xml/objects/object_wiz.xml
+++ b/assets/xml/objects/object_wiz.xml
@@ -1,102 +1,148 @@

+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/PR/abi.h b/include/PR/abi.h
index 49d539762..15ae5d911 100644
--- a/include/PR/abi.h
+++ b/include/PR/abi.h
@@ -53,6 +53,7 @@
#define A_INIT 0x01
#define A_CONTINUE 0x00
#define A_LOOP 0x02
+#define A_ADPCM_SHORT 0x04
#define A_OUT 0x02
#define A_LEFT 0x02
#define A_RIGHT 0x00
@@ -331,13 +332,20 @@ typedef short ENVMIX_STATE[40];
_a->words.w1 = (unsigned int)(a2); \
}
-#define aClearBuffer(pkt, d, c) \
-{ \
- Acmd *_a = (Acmd *)pkt; \
- \
- _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(d, 0, 24); \
- _a->words.w1 = (unsigned int)(c); \
-}
+/*
+ * Clears DMEM by writing zeros.
+ *
+ * @param pkt pointer to an Acmd buffer
+ * @param dmem DMEM address to clear
+ * @param size number of bytes to clear (rounded up to the next multiple of 16)
+ */
+#define aClearBuffer(pkt, dmem, size) \
+ { \
+ Acmd* _a = (Acmd*)pkt; \
+ \
+ _a->words.w0 = _SHIFTL(A_CLEARBUFF, 24, 8) | _SHIFTL(dmem, 0, 24); \
+ _a->words.w1 = (uintptr_t)(size); \
+ }
#define aEnvMixer(pkt, dmemi, count, swapLR, x0, x1, x2, x3, m, bits) \
{ \
@@ -368,14 +376,21 @@ typedef short ENVMIX_STATE[40];
_a->words.w1 = _SHIFTL(dmemi, 16, 16) | _SHIFTL(dmemo, 0, 16); \
}
-#define aLoadBuffer(pkt, s, d, c) \
-{ \
- Acmd *_a = (Acmd *)pkt; \
- \
- _a->words.w0 = _SHIFTL(A_LOADBUFF, 24, 8) | \
- _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(d, 0, 16); \
- _a->words.w1 = (unsigned int)(s); \
-}
+/*
+ * Loads a buffer to DMEM from any physical source address, KSEG0, or KSEG1
+ *
+ * @param pkt pointer to an Acmd buffer
+ * @param addrSrc Any physical source address, KSEG0, or KSEG1
+ * @param dmemDest DMEM destination address
+ * @param size number of bytes to copy (rounded down to the next multiple of 16)
+ */
+#define aLoadBuffer(pkt, addrSrc, dmemDest, size) \
+ { \
+ Acmd* _a = (Acmd*)pkt; \
+ \
+ _a->words.w0 = (_SHIFTL(A_LOADBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemDest, 0, 16)); \
+ _a->words.w1 = (uintptr_t)(addrSrc); \
+ }
#define aMix(pkt, f, g, i, o) \
{ \
@@ -404,14 +419,21 @@ typedef short ENVMIX_STATE[40];
_a->words.w1 = (unsigned int)(s); \
}
-#define aSaveBuffer(pkt, s, d, c) \
-{ \
- Acmd *_a = (Acmd *)pkt; \
- \
- _a->words.w0 = _SHIFTL(A_SAVEBUFF, 24, 8) | \
- _SHIFTL((c) >> 4, 16, 8) | _SHIFTL(s, 0, 16); \
- _a->words.w1 = (unsigned int)(d); \
-}
+/*
+ * Stores a buffer from DMEM to any physical source address, KSEG0, or KSEG1
+ *
+ * @param pkt pointer to an Acmd buffer
+ * @param dmemSrc DMEM source address
+ * @param addrDest Any physical source address, KSEG0, or KSEG1
+ * @param size number of bytes to copy (rounded down to the next multiple of 16)
+ */
+#define aSaveBuffer(pkt, dmemSrc, addrDest, size) \
+ { \
+ Acmd* _a = (Acmd*)pkt; \
+ \
+ _a->words.w0 = (_SHIFTL(A_SAVEBUFF, 24, 8) | _SHIFTL((size) >> 4, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \
+ _a->words.w1 = (uintptr_t)(addrDest); \
+ }
#define aSegment(pkt, s, b) \
{ \
@@ -501,14 +523,21 @@ typedef short ENVMIX_STATE[40];
_a->words.w1 = (unsigned int)(addr); \
}
-#define aDuplicate(pkt, count, dmemi, dmemo, a4) \
-{ \
- Acmd *_a = (Acmd *)pkt; \
- \
- _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | \
- _SHIFTL(count, 16, 8) | _SHIFTL(dmemi, 0, 16)); \
- _a->words.w1 = _SHIFTL(dmemo, 16, 16) | _SHIFTL(a4, 0, 16); \
-}
+/*
+ * Duplicates 128 bytes of data a specified number of times.
+ *
+ * @param pkt pointer to an Acmd buffer
+ * @param numCopies number of times to duplicate 128 bytes from src
+ * @param dmemSrc DMEM source address
+ * @param dmemDest DMEM destination address for the duplicates, size 128 * numCopies
+ */
+#define aDuplicate(pkt, numCopies, dmemSrc, dmemDest) \
+ { \
+ Acmd* _a = (Acmd*)pkt; \
+ \
+ _a->words.w0 = (_SHIFTL(A_DUPLICATE, 24, 8) | _SHIFTL(numCopies, 16, 8) | _SHIFTL(dmemSrc, 0, 16)); \
+ _a->words.w1 = _SHIFTL(dmemDest, 16, 16) | _SHIFTL(0x80, 0, 16); \
+ }
#define aAddMixer(pkt, count, dmemi, dmemo, a4) \
{ \
diff --git a/include/functions.h b/include/functions.h
index bbc7471c1..406bdc410 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -558,7 +558,7 @@ void EffectSsHitmark_SpawnFixedScale(PlayState* play, s32 type, Vec3f* pos);
void EffectSsHitmark_SpawnCustomScale(PlayState* play, s32 type, s16 scale, Vec3f* pos);
void EffectSsFhgFlash_SpawnShock(PlayState* play, Actor* actor, Vec3f* pos, s16 scale, u8 params);
// void EffectSsKFire_Spawn(UNK_TYPE4 uParm1, Vec3f* pzParm2, Vec3f* pzParm3, Vec3f* pzParm4, UNK_TYPE2 param_5, UNK_TYPE1 param_6);
-void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 unused, s16* linkDetected, s16 drawFlag);
+void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale, s16* playerDetected, s16 params);
void EffectSsKakera_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* arg3, s16 gravity, s16 arg5, s16 arg6, s16 arg7, s16 arg8, s16 scale, s16 arg10, s16 arg11, s32 life, s16 colorIdx, s16 objId, Gfx* dList);
// void EffectSsIcePiece_Spawn(UNK_TYPE4 uParm1, Vec3f* pzParm2, UNK_TYPE4 uParm3, Vec3f* pzParm4, Vec3f* param_5, UNK_TYPE4 param_6);
// void EffectSsIcePiece_SpawnBurst(void);
@@ -2238,35 +2238,6 @@ void SkinMatrix_SetYRotation(MtxF* mf, s16 a);
void SkinMatrix_MulYRotation(MtxF* mf, s16 a);
void SkinMatrix_SetZRotation(MtxF* mf, s16 a);
-void View_ViewportToVp(Vp* dest, Viewport* src);
-void View_Init(View* view, GraphicsContext* gfxCtx);
-void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up);
-void func_8013F050(View* view, Vec3f* eye, Vec3f* at, Vec3f* up);
-void View_SetScale(View* view, f32 scale);
-void View_GetScale(View* view, f32* scale);
-void func_8013F0D0(View* view, f32 fovy, f32 zNear, f32 zFar);
-void func_8013F100(View* view, f32* fovy, f32* zNear, f32* zFar);
-void func_8013F120(View* view, f32 fovy, f32 zNear, f32 zFar);
-void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar);
-void View_SetViewport(View* view, Viewport* viewport);
-void View_GetViewport(View* view, Viewport* viewport);
-void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry);
-void View_SyncAndWriteScissor(View* view, Gfx** gfx);
-void View_SetScissorForLetterbox(View* view);
-s32 View_SetDistortionDirRot(View* view, f32 dirRotX, f32 dirRotY, f32 dirRotZ);
-s32 View_SetDistortionScale(View* view, f32 scaleX, f32 scaleY, f32 scaleZ);
-s32 View_SetDistortionSpeed(View* view, f32 speed);
-s32 View_InitDistortion(View* view);
-s32 View_ClearDistortion(View* view);
-s32 View_SetDistortion(View* view, Vec3f dirRot, Vec3f scale, f32 speed);
-s32 View_StepDistortion(View* view, Mtx* projectionMtx);
-void View_RenderView(View* view, s32 uParm2);
-s32 View_RenderToPerspectiveMatrix(View* view);
-s32 View_RenderToOrthographicMatrix(View* view);
-s32 func_8013FBC8(View* view);
-s32 func_8013FD74(View* view);
-s32 func_80140024(View* view);
-s32 func_801400CC(View* view, Gfx** gfxp);
void func_80140260(OSViMode* vimode);
// void func_8014026C(OSViMode* param_1, UNK_TYPE1 param_2, s32 param_3, s32 param_4, s32 param_5, s32 param_6, s32 param_7, s32 param_8, UNK_TYPE4 param_9, s32 param_10, s16 param_11, u32 param_12, UNK_TYPE4 param_13);
// void func_80140730(void);
@@ -2376,18 +2347,6 @@ void Message_FindCreditsMessage(PlayState* play, u16 textId);
void func_8015E7EC(PlayState* play, UNK_PTR puParm2);
// void func_8015F8A8(UNK_TYPE4 ctxt);
-void ShrinkWindow_SetLetterboxTarget(s32 target);
-s32 ShrinkWindow_GetLetterboxTarget(void);
-void ShrinkWindow_SetLetterboxMagnitude(s32 magnitude);
-s32 ShrinkWindow_GetLetterboxMagnitude(void);
-void ShrinkWindow_SetPillarboxTarget(s32 target);
-s32 ShrinkWindow_GetPillarboxTarget(void);
-void ShrinkWindow_SetPillarboxMagnitude(s32 magnitude);
-s32 ShrinkWindow_GetPillarboxMagnitude(void);
-void ShrinkWindow_Init(void);
-void ShrinkWindow_Destroy(void);
-void ShrinkWindow_Update(s32 framerateDivisor);
-void ShrinkWindow_Draw(GraphicsContext* gfxCtx);
// void func_80161180(void);
s32 func_8016119C(Camera* camera, DbCameraUnkStruct* arg1);
// void func_8016122C(void);
@@ -2915,48 +2874,7 @@ s32 osFlashWriteBuffer(OSIoMesg* mb, s32 priority, void* dramAddr, OSMesgQueue*
s32 osFlashWriteArray(u32 pageNum);
s32 osFlashReadArray(OSIoMesg* mb, s32 priority, u32 pageNum, void* dramAddr, u32 pageCount, OSMesgQueue* mq);
-// void func_801877D0(void);
-// void func_80187B64(void);
-// void func_80187BEC(void);
-// void func_80187DE8(void);
-// void func_80187E58(void);
-// void func_80187F00(void);
-// void func_80187FB0(void);
-// void func_80187FE8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188034(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188078(void);
-// void func_801880C4(void);
-// void func_801880E8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188124(void);
-// void func_8018814C(void);
-// void func_80188174(void);
-// void func_801881A8(void);
-// void func_801881C4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_801881F8(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188264(void);
-// void func_80188288(void);
-// void func_801882A0(void);
-// void func_80188304(void);
-// void func_801884A0(void);
-// void func_80188698(void);
-// void func_8018883C(void);
-// void func_801888E4(void);
-// void func_801889A4(void);
-// void func_80188A50(void);
-// void func_80188AFC(void);
-// void func_80188C48(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188CB4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5);
-// void func_80188D28(void);
-// void func_80188D68(void);
-// void func_80188DDC(void);
-// void func_80188FBC(void);
-// void func_80189064(void);
-// void func_80189620(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6, UNK_TYPE4 param_7);
-// void func_8018A4B4(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6);
-// void func_8018A768(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6);
-// void func_8018A808(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE2 param_5, UNK_TYPE4 param_6);
-// void func_8018ACC4(void);
-// void func_8018AE34(UNK_TYPE1 param_1, UNK_TYPE1 param_2, UNK_TYPE1 param_3, UNK_TYPE1 param_4, UNK_TYPE4 param_5, UNK_TYPE4 param_6);
+Acmd* AudioSynth_Update(Acmd* cmdStart, s32* numAbiCmds, s16* aiStart, s32 aiBufLen);
void AudioHeap_DiscardFont(s32 fontId);
void* AudioHeap_WritebackDCache(void* addr, size_t size);
@@ -3123,7 +3041,7 @@ void AudioSfx_LowerSfxSettingsReverb(Vec3f* pos, s8 isReverbLowered);
// void func_8019F7D8(void);
// void func_8019F830(void);
void func_8019F88C(Vec3f* arg0, u16 sfxId, UNK_TYPE arg2);
-// void func_8019F900(void);
+void func_8019F900(Vec3f* pos, u8 chargeLevel);
// void func_8019FA18(void);
void func_8019FAD8(Vec3f* param_1, u16 sfxId, f32 param_3);
void func_8019FB0C(Vec3f* arg0, u16 sfxId, f32 arg2, s32 arg3);
diff --git a/include/variables.h b/include/variables.h
index f5644fe5e..70508d72b 100644
--- a/include/variables.h
+++ b/include/variables.h
@@ -1557,11 +1557,11 @@ extern f32 gPitchFrequencies[];
extern u8 gDefaultShortNoteVelocityTable[];
extern u8 gDefaultShortNoteGateTimeTable[];
extern EnvelopePoint gDefaultEnvelope[];
-extern NoteSubEu gZeroNoteSub;
-extern NoteSubEu gDefaultNoteSub;
-extern u16 gHeadsetPanQuantization[];
-extern u16 gHeadsetPanQuantization[];
-extern s16 D_801D58A8[];
+extern NoteSampleState gZeroedSampleState;
+extern NoteSampleState gDefaultSampleState;
+extern u16 gHaasEffectDelaySize[];
+extern u16 gHaasEffectDelaySize[];
+extern s16 gInvalidAdpcmCodeBook[];
extern f32 gHeadsetPanVolume[];
extern f32 gStereoPanVolume[];
extern f32 gDefaultPanVolume[];
@@ -1721,21 +1721,7 @@ extern s8 gSfxDefaultReverb;
extern u8 gAudioSpecId;
// extern UNK_TYPE1 D_801DB4D8;
// extern UNK_TYPE4 D_801DB4DC;
-// extern UNK_TYPE1 D_801DB4E0;
-// extern UNK_TYPE1 D_801DB528;
-// extern UNK_TYPE1 D_801DB570;
-// extern UNK_TYPE1 D_801DB5B8;
-// extern UNK_TYPE1 D_801DB600;
-// extern UNK_TYPE1 D_801DB648;
-// extern UNK_TYPE1 D_801DB690;
-// extern UNK_TYPE1 D_801DB6D8;
-// extern UNK_TYPE1 D_801DB720;
-// extern UNK_TYPE1 D_801DB750;
-// extern UNK_TYPE1 D_801DB798;
-// extern UNK_TYPE1 D_801DB870;
-// extern UNK_TYPE1 D_801DB8B8;
-// extern UNK_TYPE1 D_801DB900;
-extern UNK_PTR D_801DB930;
+extern ReverbSettings* gReverbSettingsTable[];
extern AudioSpec gAudioSpecs[21];
// rodata
@@ -3181,8 +3167,6 @@ extern s16 D_801F4E7A;
// extern UNK_TYPE1 D_801F6B1E;
// extern UNK_TYPE1 D_801F6B20;
// extern UNK_TYPE1 D_801F6B22;
-extern ShrinkWindowContext gShrinkWindowContext;
-extern ShrinkWindowContext* gShrinkWindowContextPtr;
// extern UNK_TYPE4 D_801F6B50;
// extern UNK_TYPE1 D_801F6B58;
extern void (*sKaleidoScopeUpdateFunc)(PlayState* play);
@@ -3485,10 +3469,10 @@ extern ActiveSequence gActiveSeqs[];
// extern UNK_TYPE1 D_80200BCE;
// extern UNK_TYPE1 D_80200BD0;
extern AudioContext gAudioContext; // at 0x80200C70
-extern void (*D_80208E68)(void);
-extern u32 (*D_80208E6C)(s8 value, SequenceChannel* channel);
-extern s32 (*D_80208E70)(Sample*, s32, s8, s32);
-extern Acmd* (*D_80208E74)(Acmd*, s32, s32);
+extern void (*gCustomAudioUpdateFunction)(void);
+extern u32 (*gCustomAudioSeqFunction)(s8 value, SequenceChannel* channel);
+extern s32 (*gCustomAudioReverbFunction)(Sample*, s32, s8, s32);
+extern Acmd* (*gCustomAudioSynthFunction)(Acmd*, s32, s32);
// post-code buffers
extern u8 gGfxSPTaskYieldBuffer[OS_YIELD_DATA_SIZE];
diff --git a/include/z64.h b/include/z64.h
index d5e1207e7..61323e9ae 100644
--- a/include/z64.h
+++ b/include/z64.h
@@ -287,13 +287,6 @@ typedef struct {
/* 0x10 */ OSTime resetTime;
} NmiBuff; // size >= 0x18
-typedef struct {
- /* 0x0 */ s8 letterboxTarget;
- /* 0x1 */ s8 letterboxMagnitude;
- /* 0x2 */ s8 pillarboxTarget;
- /* 0x3 */ s8 pillarboxMagnitude;
-} ShrinkWindowContext; // size = 0x4
-
typedef void(*osCreateThread_func)(void*);
typedef enum {
diff --git a/include/z64audio.h b/include/z64audio.h
index c5045e34f..264e8d9e3 100644
--- a/include/z64audio.h
+++ b/include/z64audio.h
@@ -1,7 +1,7 @@
#ifndef Z64_AUDIO_H
#define Z64_AUDIO_H
-#define MK_AUDIO_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
+#define AUDIO_MK_CMD(b0,b1,b2,b3) ((((b0) & 0xFF) << 0x18) | (((b1) & 0xFF) << 0x10) | (((b2) & 0xFF) << 0x8) | (((b3) & 0xFF) << 0))
#define NO_LAYER ((SequenceLayer*)(-1))
@@ -32,13 +32,45 @@ typedef enum {
#define ADSR_GOTO -2
#define ADSR_RESTART -3
-#define AIBUF_LEN 0x580
+// size of a single sample point
+#define SAMPLE_SIZE sizeof(s16)
+
+// Samples are processed in groups of 16 called a "frame"
+#define SAMPLES_PER_FRAME ADPCMFSIZE
+
+// The length of one left/right channel is 13 frames
+#define DMEM_1CH_SIZE (13 * SAMPLES_PER_FRAME * SAMPLE_SIZE)
+// Both left and right channels
+#define DMEM_2CH_SIZE (2 * DMEM_1CH_SIZE)
+
+#define AIBUF_LEN (88 * SAMPLES_PER_FRAME) // number of samples
+#define AIBUF_SIZE (AIBUF_LEN * SAMPLE_SIZE) // number of bytes
+
+// Filter sizes
+#define FILTER_SIZE (8 * SAMPLE_SIZE)
+#define FILTER_BUF_PART1 (8 * SAMPLE_SIZE)
+#define FILTER_BUF_PART2 (8 * SAMPLE_SIZE)
// Must be the same amount of samples as copied by aDuplicate() (audio microcode)
#define WAVE_SAMPLE_COUNT 64
#define AUDIO_RELOCATED_ADDRESS_START K0BASE
+#define REVERB_INDEX_NONE -1
+
+typedef enum {
+ /* 0 */ REVERB_DATA_TYPE_SETTINGS, // Reverb Settings (Init)
+ /* 1 */ REVERB_DATA_TYPE_DELAY, // Reverb Delay (numSamples)
+ /* 2 */ REVERB_DATA_TYPE_DECAY, // Reverb Decay Ratio
+ /* 3 */ REVERB_DATA_TYPE_SUB_VOLUME, // Reverb Sub-Volume
+ /* 4 */ REVERB_DATA_TYPE_VOLUME, // Reverb Volume
+ /* 5 */ REVERB_DATA_TYPE_LEAK_RIGHT, // Reverb Leak Right Channel
+ /* 6 */ REVERB_DATA_TYPE_LEAK_LEFT, // Reverb Leak Left Channel
+ /* 7 */ REVERB_DATA_TYPE_FILTER_LEFT, // Reverb Left Filter
+ /* 8 */ REVERB_DATA_TYPE_FILTER_RIGHT, // Reverb Right Filter
+ /* 9 */ REVERB_DATA_TYPE_9 // Reverb Unk
+} ReverbDataType;
+
typedef enum {
/* 0x1 */ AUDIO_ERROR_NO_INST = 1,
/* 0x3 */ AUDIO_ERROR_INVALID_INST_ID = 3,
@@ -78,12 +110,14 @@ typedef enum {
} SampleMedium;
typedef enum {
- /* 0 */ CODEC_ADPCM,
- /* 1 */ CODEC_S8,
+ /* 0 */ CODEC_ADPCM, // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte
+ /* 1 */ CODEC_S8, // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes)
/* 2 */ CODEC_S16_INMEMORY,
- /* 3 */ CODEC_SMALL_ADPCM,
+ /* 3 */ CODEC_SMALL_ADPCM, // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte
/* 4 */ CODEC_REVERB,
- /* 5 */ CODEC_S16
+ /* 5 */ CODEC_S16,
+ /* 6 */ CODEC_UNK6,
+ /* 7 */ CODEC_UNK7 // processed as uncompressed samples
} SampleCodec;
typedef enum {
@@ -165,24 +199,28 @@ typedef struct {
typedef struct {
/* 0x00 */ u32 start;
- /* 0x04 */ u32 end;
+ /* 0x04 */ u32 loopEnd; // numSamples into the sample where the loop ends
/* 0x08 */ u32 count;
- /* 0x0C */ u32 unk_0C;
- /* 0x10 */ s16 state[16]; // only exists if count != 0. 8-byte aligned
+ /* 0x0C */ u32 sampleEnd; // total number of s16-samples in the
+ /* 0x10 */ s16 predictorState[16]; // only exists if count != 0. 8-byte aligned
} AdpcmLoop; // size = 0x30 (or 0x10)
+/**
+ * The procedure used to design the codeBook is based on an adaptive clustering algorithm.
+ * The size of the codeBook is (8 * order * numPredictors) and is 8-byte aligned
+ */
typedef struct {
/* 0x00 */ s32 order;
- /* 0x04 */ s32 npredictors;
- /* 0x08 */ s16 book[1]; // size 8 * order * npredictors. 8-byte aligned
+ /* 0x04 */ s32 numPredictors;
+ /* 0x08 */ s16 codeBook[1]; // a table of prediction coefficients that the coder selects from to optimize sound quality.
} AdpcmBook; // size >= 0x8
typedef struct {
/* 0x00 */ u32 unk_0 : 1;
/* 0x00 */ u32 codec : 3; // The state of compression or decompression
/* 0x00 */ u32 medium : 2; // Medium where sample is currently stored
- /* 0x00 */ u32 unk_bit26 : 1; // Has the sample header been relocated (offsets to pointers)
- /* 0x00 */ u32 isRelocated : 1; // Size of the sample
+ /* 0x00 */ u32 unk_bit26 : 1;
+ /* 0x00 */ u32 isRelocated : 1; // Has the sample header been relocated (offsets to pointers)
/* 0x01 */ u32 size : 24; // Size of the sample
/* 0x04 */ u8* sampleAddr; // Raw sample data. Offset from the start of the sample bank or absolute address to either rom or ram
/* 0x08 */ AdpcmLoop* loop; // Adpcm loop parameters used by the sample. Offset from the start of the sound font / pointer to ram
@@ -194,18 +232,23 @@ typedef struct {
/* 0x04 */ f32 tuning; // frequency scale factor
} TunedSample; // size = 0x8
+/**
+ * Stores an entry of decompressed samples in a reverb ring buffer.
+ * By storing the sample in a ring buffer, the time it takes to loop
+ * around back to the same sample acts as a delay, leading to an echo effect.
+ */
typedef struct {
/* 0x00 */ s16 numSamplesAfterDownsampling; // never read
- /* 0x02 */ s16 chunkLen; // never read
+ /* 0x02 */ s16 numSamples; // never read
/* 0x04 */ s16* toDownsampleLeft;
/* 0x08 */ s16* toDownsampleRight; // data pointed to by left and right are adjacent in memory
/* 0x0C */ s32 startPos; // start pos in ring buffer
- /* 0x10 */ s16 lengthA; // first length in ring buffer (from startPos, at most until end)
- /* 0x12 */ s16 lengthB; // second length in ring buffer (from pos 0)
- /* 0x14 */ u16 unk_14;
- /* 0x16 */ u16 unk_16;
- /* 0x18 */ u16 unk_18;
-} ReverbRingBufferItem; // size = 0x1C
+ /* 0x10 */ s16 size; // first length in ring buffer (from startPos, at most until end)
+ /* 0x12 */ s16 wrappedSize; // second length in ring buffer (from pos 0)
+ /* 0x14 */ u16 loadResamplePitch;
+ /* 0x16 */ u16 saveResamplePitch;
+ /* 0x18 */ u16 saveResampleNumSamples;
+} ReverbBufferEntry; // size = 0x1C
typedef struct {
/* 0x000 */ u8 resampleFlags;
@@ -213,35 +256,35 @@ typedef struct {
/* 0x002 */ u8 framesToIgnore;
/* 0x003 */ u8 curFrame;
/* 0x004 */ u8 downsampleRate;
- /* 0x005 */ s8 unk_05;
- /* 0x006 */ u16 windowSize;
- /* 0x008 */ s16 unk_08;
- /* 0x00A */ s16 unk_0A;
- /* 0x00C */ u16 unk_0C;
- /* 0x00E */ u16 unk_0E;
+ /* 0x005 */ s8 mixReverbIndex; // mix in reverb from this index. set to 0xFF to not mix any
+ /* 0x006 */ u16 delayNumSamples; // number of samples between echos
+ /* 0x008 */ s16 mixReverbStrength; // the gain/amount to mix in reverb from mixReverbIndex
+ /* 0x00A */ s16 volume;
+ /* 0x00C */ u16 decayRatio; // determines how fast reverb dissipate
+ /* 0x00E */ u16 downsamplePitch;
/* 0x010 */ s16 leakRtl;
/* 0x012 */ s16 leakLtr;
- /* 0x014 */ u16 unk_14;
- /* 0x016 */ s16 unk_16;
- /* 0x018 */ u8 unk_18;
- /* 0x019 */ s8 unk_19;
- /* 0x01A */ u16 unk_1A;
- /* 0x01C */ u16 unk_1C;
- /* 0x01E */ u8 unk_1E;
- /* 0x020 */ s32 nextRingBufPos;
- /* 0x024 */ s32 unk_24; // May be bufSizePerChan
- /* 0x028 */ s16* leftRingBuf;
- /* 0x02C */ s16* rightRingBuf;
- /* 0x030 */ void* unk_30;
- /* 0x034 */ void* unk_34;
- /* 0x038 */ void* unk_38;
- /* 0x03C */ void* unk_3C;
- /* 0x040 */ ReverbRingBufferItem items[2][5];
- /* 0x158 */ ReverbRingBufferItem items2[2][5];
+ /* 0x014 */ u16 subDelay; // number of samples between sub echos
+ /* 0x016 */ s16 subVolume; // strength of the sub echos
+ /* 0x018 */ u8 resampleEffectOn;
+ /* 0x019 */ s8 resampleEffectExtraSamples;
+ /* 0x01A */ u16 resampleEffectLoadUnk;
+ /* 0x01C */ u16 resampleEffectSaveUnk;
+ /* 0x01E */ u8 delayNumSamplesAfterDownsampling;
+ /* 0x020 */ s32 nextReverbBufPos;
+ /* 0x024 */ s32 delayNumSamplesUnk; // May be bufSizePerChan
+ /* 0x028 */ s16* leftReverbBuf;
+ /* 0x02C */ s16* rightReverbBuf;
+ /* 0x030 */ s16* leftLoadResampleBuf;
+ /* 0x034 */ s16* rightLoadResampleBuf;
+ /* 0x038 */ s16* leftSaveResampleBuf;
+ /* 0x03C */ s16* rightSaveResampleBuf;
+ /* 0x040 */ ReverbBufferEntry bufEntry[2][5];
+ /* 0x158 */ ReverbBufferEntry subBufEntry[2][5];
/* 0x270 */ s16* filterLeft;
/* 0x274 */ s16* filterRight;
- /* 0x278 */ s16* unk_278;
- /* 0x27C */ s16* unk_27C;
+ /* 0x278 */ s16* filterLeftInit;
+ /* 0x27C */ s16* filterRightInit;
/* 0x280 */ s16* filterLeftState;
/* 0x284 */ s16* filterRightState;
/* 0x288 */ TunedSample tunedSample;
@@ -363,28 +406,26 @@ typedef struct {
/* 0x1C */ EnvelopePoint* envelope;
} AdsrState; // size = 0x20
-typedef struct {
- /* 0x0 */ u8 unused : 2;
- /* 0x0 */ u8 bit2 : 2;
- /* 0x0 */ u8 strongRight : 1;
- /* 0x0 */ u8 strongLeft : 1;
- /* 0x0 */ u8 stereoHeadsetEffects : 1;
- /* 0x0 */ u8 usesHeadsetPanEffects : 1;
+typedef union {
+ struct {
+ /* 0x0 */ u8 unused : 2;
+ /* 0x0 */ u8 type : 2;
+ /* 0x0 */ u8 strongRight : 1;
+ /* 0x0 */ u8 strongLeft : 1;
+ /* 0x0 */ u8 strongReverbRight : 1;
+ /* 0x0 */ u8 strongReverbLeft : 1;
+ };
+ /* 0x0 */ u8 asByte;
} StereoData; // size = 0x1
-typedef union {
- /* 0x0 */ StereoData s;
- /* 0x0 */ u8 asByte;
-} Stereo; // size = 0x1
-
typedef struct {
- /* 0x00 */ u8 reverb;
+ /* 0x00 */ u8 targetReverbVol;
/* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x02 */ u8 pan;
- /* 0x03 */ u8 unk_3; // Possibly part of stereo?
- /* 0x04 */ Stereo stereo;
- /* 0x05 */ u8 unk_4;
- /* 0x06 */ u16 unk_6;
+ /* 0x03 */ u8 surroundEffectIndex;
+ /* 0x04 */ StereoData stereoData;
+ /* 0x05 */ u8 combFilterSize;
+ /* 0x06 */ u16 combFilterGain;
/* 0x08 */ f32 freqScale;
/* 0x0C */ f32 velocity;
/* 0x10 */ s16* filter;
@@ -421,7 +462,7 @@ typedef struct SequenceChannel {
} changes;
/* 0x02 */ u8 noteAllocPolicy;
/* 0x03 */ u8 muteFlags;
- /* 0x04 */ u8 reverb; // or dry/wet mix
+ /* 0x04 */ u8 targetReverbVol; // or dry/wet mix
/* 0x05 */ u8 notePriority; // 0-3
/* 0x06 */ u8 someOtherPriority;
/* 0x07 */ u8 fontId;
@@ -432,12 +473,12 @@ typedef struct SequenceChannel {
/* 0x0C */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x0D */ u8 velocityRandomVariance;
/* 0x0E */ u8 gateTimeRandomVariance;
- /* 0x0F */ u8 unk_0F;
- /* 0x10 */ u8 unk_10;
+ /* 0x0F */ u8 combFilterSize;
+ /* 0x10 */ u8 surroundEffectIndex;
/* 0x11 */ u8 unk_11;
/* 0x12 */ VibratoSubStruct vibrato;
/* 0x20 */ u16 delay;
- /* 0x22 */ u16 unk_20;
+ /* 0x22 */ u16 combFilterGain;
/* 0x24 */ u16 unk_22; // Used for indexing data
/* 0x26 */ s16 instOrWave; // either 0 (none), instrument index + 1, or
// 0x80..0x83 for sawtooth/triangle/sine/square waves.
@@ -459,7 +500,7 @@ typedef struct SequenceChannel {
/* 0xC8 */ s8 soundScriptIO[8]; // bridge between sound script and audio lib, "io ports"
/* 0xD0 */ u8* sfxState; // SfxChannelState
/* 0xD4 */ s16* filter;
- /* 0xD8 */ Stereo stereo;
+ /* 0xD8 */ StereoData stereoData;
/* 0xDC */ s32 startSamplePos;
/* 0xE0 */ s32 unk_E0;
} SequenceChannel; // size = 0xE4
@@ -474,15 +515,15 @@ typedef struct SequenceLayer {
/* 0x00 */ u8 ignoreDrumPan : 1;
/* 0x00 */ u8 bit1 : 1; // "has initialized continuous notes"?
/* 0x00 */ u8 notePropertiesNeedInit : 1;
- /* 0x01 */ Stereo stereo;
+ /* 0x01 */ StereoData stereoData;
/* 0x02 */ u8 instOrWave;
/* 0x03 */ u8 gateTime;
/* 0x04 */ u8 semitone;
/* 0x05 */ u8 portamentoTargetNote;
/* 0x06 */ u8 pan; // 0..128
/* 0x07 */ u8 notePan;
- /* 0x08 */ u8 unk_08;
- /* 0x09 */ u8 unk_09;
+ /* 0x08 */ u8 surroundEffectIndex;
+ /* 0x09 */ u8 targetReverbVol;
union {
struct {
/* 0x0A */ u16 bit_0 : 1;
@@ -531,45 +572,37 @@ typedef struct SequenceLayer {
} SequenceLayer; // size = 0x90
typedef struct {
- /* 0x00 */ s16 adpcmdecState[0x10];
- /* 0x20 */ s16 finalResampleState[0x10];
- /* 0x40 */ s16 mixEnvelopeState[0x28];
- /* 0x90 */ s16 panResampleState[0x10];
- /* 0xB0 */ s16 panSamplesBuffer[0x20];
- /* 0xF0 */ s16 dummyResampleState[0x10];
-} NoteSynthesisBuffers; // size = 0x110
+ /* 0x000 */ s16 adpcmState[16];
+ /* 0x020 */ s16 finalResampleState[16];
+ /* 0x040 */ s16 filterState[32];
+ /* 0x080 */ s16 unusedState[16];
+ /* 0x0A0 */ s16 haasEffectDelayState[32];
+ /* 0x0E0 */ s16 combFilterState[128];
+ /* 0x1E0 */ s16 surroundEffectState[128];
+} NoteSynthesisBuffers; // size = 0x2E0
typedef struct {
- /* 0x00 */ u8 restart_bit0 : 1;
- /* 0x00 */ u8 restart_bit1 : 1;
- /* 0x00 */ u8 restart_bit2 : 1;
- /* 0x00 */ u8 restart_bit3 : 1;
- /* 0x00 */ u8 restart_bit4 : 1;
- /* 0x00 */ u8 restart_bit5 : 1;
- /* 0x00 */ u8 restart_bit6 : 1;
- /* 0x00 */ u8 restart_bit7 : 1;
+ /* 0x00 */ u8 atLoopPoint : 1;
+ /* 0x00 */ u8 stopLoop : 1;
/* 0x01 */ u8 sampleDmaIndex;
- /* 0x02 */ u8 prevHeadsetPanRight;
- /* 0x03 */ u8 prevHeadsetPanLeft;
- /* 0x04 */ u8 reverbVol;
+ /* 0x02 */ u8 prevHaasEffectLeftDelaySize;
+ /* 0x03 */ u8 prevHaasEffectRightDelaySize;
+ /* 0x04 */ u8 curReverbVol;
/* 0x05 */ u8 numParts;
- /* 0x06 */ u16 samplePosFrac;
- /* 0x08 */ u16 unk_08;
- /* 0x0C */ s32 samplePosInt;
+ /* 0x06 */ u16 samplePosFrac; // Fractional part of the sample position
+ /* 0x08 */ u16 surroundEffectGain;
+ /* 0x0C */ s32 samplePosInt; // Integer part of the sample position
/* 0x10 */ NoteSynthesisBuffers* synthesisBuffers;
/* 0x14 */ s16 curVolLeft;
/* 0x16 */ s16 curVolRight;
- /* 0x18 */ u16 unk_14;
- /* 0x1A */ u16 unk_16;
- /* 0x1C */ u16 unk_18;
- /* 0x1E */ u8 unk_1A;
+ /* 0x18 */ UNK_TYPE1 unk_14[0x6];
+ /* 0x1E */ u8 combFilterNeedsInit;
/* 0x1F */ u8 unk_1F;
- /* 0x20 */ u16 unk_1C;
- /* 0x22 */ u16 unk_1E;
+ /* 0x20 */ UNK_TYPE1 unk_20[0x4];
} NoteSynthesisState; // size = 0x24
typedef struct {
- /* 0x00 */ struct VibratoSubStruct* vibSubStruct; // MM Something else?
+ /* 0x00 */ struct VibratoSubStruct* vibSubStruct; // Something else?
/* 0x04 */ u32 time;
/* 0x08 */ s16* curve;
/* 0x0C */ f32 extent;
@@ -603,67 +636,68 @@ typedef struct {
/* 0x34 */ AdsrState adsr;
/* 0x54 */ Portamento portamento;
/* 0x60 */ VibratoState vibratoState;
- /* 0x7C */ char unk_7C[0x8];
+ /* 0x7C */ UNK_TYPE1 pad7C[0x4];
+ /* 0x80 */ u8 unk_80;
/* 0x84 */ u32 startSamplePos;
-} NotePlaybackState; // size = 0x88
+ /* 0x88 */ UNK_TYPE1 unk_BC[0x1C];
+} NotePlaybackState; // size = 0xA4
typedef struct {
struct {
/* 0x00 */ volatile u8 enabled : 1;
/* 0x00 */ u8 needsInit : 1;
- /* 0x00 */ u8 finished : 1; // ?
+ /* 0x00 */ u8 finished : 1;
/* 0x00 */ u8 unused : 1;
- /* 0x00 */ u8 stereoStrongRight : 1;
- /* 0x00 */ u8 stereoStrongLeft : 1;
- /* 0x00 */ u8 stereoHeadsetEffects : 1;
- /* 0x00 */ u8 usesHeadsetPanEffects : 1; // ?
+ /* 0x00 */ u8 strongRight : 1;
+ /* 0x00 */ u8 strongLeft : 1;
+ /* 0x00 */ u8 strongReverbRight : 1;
+ /* 0x00 */ u8 strongReverbLeft : 1;
} bitField0;
struct {
/* 0x01 */ u8 reverbIndex : 3;
/* 0x01 */ u8 bookOffset : 2;
/* 0x01 */ u8 isSyntheticWave : 1;
/* 0x01 */ u8 hasTwoParts : 1;
- /* 0x01 */ u8 usesHeadsetPanEffects2 : 1;
+ /* 0x01 */ u8 useHaasEffect : 1;
} bitField1;
/* 0x02 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
- /* 0x03 */ u8 headsetPanRight;
- /* 0x04 */ u8 headsetPanLeft;
- /* 0x05 */ u8 reverbVol;
+ /* 0x03 */ u8 haasEffectLeftDelaySize;
+ /* 0x04 */ u8 haasEffectRightDelaySize;
+ /* 0x05 */ u8 targetReverbVol;
/* 0x06 */ u8 harmonicIndexCurAndPrev; // bits 3..2 store curHarmonicIndex, bits 1..0 store prevHarmonicIndex
- /* 0x07 */ u8 unk_07;
+ /* 0x07 */ u8 combFilterSize;
/* 0x08 */ u16 targetVolLeft;
/* 0x0A */ u16 targetVolRight;
- /* 0x0C */ u16 resamplingRateFixedPoint;
- /* 0x0E */ u16 unk_0E;
+ /* 0x0C */ u16 frequencyFixedPoint;
+ /* 0x0E */ u16 combFilterGain;
union {
/* 0x10 */ TunedSample* tunedSample;
/* 0x10 */ s16* waveSampleAddr; // used for synthetic waves
};
/* 0x14 */ s16* filter;
- /* 0x18 */ u8 unk_18;
- /* 0x19 */ u8 unk_19;
- /* 0x1A */ UNK_TYPE1 pad_1A[0x6];
-} NoteSubEu; // size = 0x20
+ /* 0x18 */ UNK_TYPE1 unk_18;
+ /* 0x19 */ u8 surroundEffectIndex;
+ /* 0x1A */ UNK_TYPE1 unk_1A[0x6];
+} NoteSampleState; // size = 0x20
typedef struct Note {
/* 0x00 */ AudioListItem listItem;
/* 0x10 */ NoteSynthesisState synthesisState;
/* 0x34 */ NotePlaybackState playbackState;
- /* 0xBC */ char unk_BC[0x1C];
- /* 0xD8 */ NoteSubEu noteSubEu;
+ /* 0xD8 */ NoteSampleState sampleState;
} Note; // size = 0xF8
typedef struct {
/* 0x00 */ u8 downsampleRate;
- /* 0x02 */ u16 windowSize;
- /* 0x04 */ u16 unk_4;
- /* 0x06 */ u16 unk_6;
- /* 0x08 */ u16 unk_8;
- /* 0x0A */ u16 unk_A;
+ /* 0x02 */ u16 delayNumSamples;
+ /* 0x04 */ u16 decayRatio; // determines how fast reverb dissipates
+ /* 0x06 */ u16 subDelay;
+ /* 0x08 */ u16 subVolume;
+ /* 0x0A */ u16 volume;
/* 0x0C */ u16 leakRtl;
/* 0x0E */ u16 leakLtr;
- /* 0x10 */ s8 unk_10;
- /* 0x12 */ u16 unk_12;
+ /* 0x10 */ s8 mixReverbIndex;
+ /* 0x12 */ u16 mixReverbStrength;
/* 0x14 */ s16 lowPassFilterCutoffLeft;
/* 0x16 */ s16 lowPassFilterCutoffRight;
} ReverbSettings; // size = 0x18
@@ -704,13 +738,13 @@ typedef struct {
/* 0x00 */ s16 specUnk4;
/* 0x02 */ u16 samplingFreq; // Target sampling rate in Hz
/* 0x04 */ u16 aiSamplingFreq; // True sampling rate set to the audio interface (AI) for the audio digital-analog converter (DAC)
- /* 0x06 */ s16 samplesPerFrameTarget;
- /* 0x08 */ s16 maxAiBufNumSamples;
- /* 0x0A */ s16 minAiBufNumSamples;
+ /* 0x06 */ s16 numSamplesPerFrameTarget;
+ /* 0x08 */ s16 numSamplesPerFrameMax;
+ /* 0x0A */ s16 numSamplesPerFrameMin;
/* 0x0C */ s16 updatesPerFrame; // for each frame of the audio thread (default 60 fps), number of updates to process audio
- /* 0x0E */ s16 samplesPerUpdate;
- /* 0x10 */ s16 samplesPerUpdateMax;
- /* 0x12 */ s16 samplesPerUpdateMin;
+ /* 0x0E */ s16 numSamplesPerUpdate;
+ /* 0x10 */ s16 numSamplesPerUpdateMax;
+ /* 0x12 */ s16 numSamplesPerUpdateMin;
/* 0x14 */ s16 numSequencePlayers;
/* 0x18 */ f32 resampleRate;
/* 0x1C */ f32 updatesPerFrameInv; // inverse (reciprocal) of updatesPerFrame
@@ -899,8 +933,8 @@ typedef struct {
/* 0x0002 */ u16 unk_2; // reads from audio spec unk_14, never used, always set to 0x7FFF
/* 0x0004 */ u16 unk_4;
/* 0x0006 */ char unk_0006[0xA];
- /* 0x0010 */ s16* curLoadedBook;
- /* 0x0014 */ NoteSubEu* noteSubsEu;
+ /* 0x0010 */ s16* adpcmCodeBook;
+ /* 0x0014 */ NoteSampleState* sampleStateList;
/* 0x0018 */ SynthesisReverb synthesisReverbs[4];
/* 0x0B58 */ char unk_0B58[0x30];
/* 0x0B88 */ Sample* usedSamples[128];
@@ -1002,7 +1036,7 @@ typedef struct {
/* 0x4460 */ SequencePlayer seqPlayers[5];
/* 0x4B40 */ SequenceLayer sequenceLayers[80];
/* 0x7840 */ SequenceChannel sequenceChannelNone;
- /* 0x7924 */ s32 noteSubEuOffset;
+ /* 0x7924 */ s32 sampleStateOffset; // Start of the list of sample states for this update. Resets after each audio frame.
/* 0x7928 */ AudioListItem layerFreeList;
/* 0x7938 */ NotePool noteFreeLists;
/* 0x7978 */ u8 cmdWritePos;
@@ -1023,17 +1057,17 @@ typedef struct {
} AudioContext; // size = 0x81F8
typedef struct {
- /* 0x00 */ u8 reverbVol;
+ /* 0x00 */ u8 targetReverbVol;
/* 0x01 */ u8 gain; // Increases volume by a multiplicative scaling factor. Represented as a UQ4.4 number
/* 0x02 */ u8 pan;
- /* 0x03 */ u8 unk_3;
- /* 0x04 */ Stereo stereo;
+ /* 0x03 */ u8 surroundEffectIndex;
+ /* 0x04 */ StereoData stereoData;
/* 0x08 */ f32 frequency;
/* 0x0C */ f32 velocity;
/* 0x10 */ char unk_0C[0x4];
/* 0x14 */ s16* filter;
- /* 0x18 */ u8 unk_14;
- /* 0x1A */ u16 unk_16;
+ /* 0x18 */ u8 combFilterSize;
+ /* 0x1A */ u16 combFilterGain;
} NoteSubAttributes; // size = 0x1A
typedef struct {
diff --git a/include/z64effect.h b/include/z64effect.h
index dde996eb7..b4574592a 100644
--- a/include/z64effect.h
+++ b/include/z64effect.h
@@ -257,7 +257,6 @@ typedef struct {
/* 0x18 */ u8 unk18; // Always 1?
} EffectSsOverlay; // size = 0x1C
-//! TODO: Review reuse of vec/gfx/actor fields across all effects
typedef struct EffectSs {
/* 0x00 */ Vec3f pos;
/* 0x0C */ Vec3f velocity;
diff --git a/include/z64shrink_window.h b/include/z64shrink_window.h
new file mode 100644
index 000000000..2742fb602
--- /dev/null
+++ b/include/z64shrink_window.h
@@ -0,0 +1,23 @@
+#ifndef Z64SHRINK_WINDOW_H
+#define Z64SHRINK_WINDOW_H
+
+#include "PR/ultratypes.h"
+
+struct GraphicsContext;
+
+void ShrinkWindow_Letterbox_SetSizeTarget(s32 target);
+s32 ShrinkWindow_Letterbox_GetSizeTarget(void);
+void ShrinkWindow_Letterbox_SetSize(s32 size);
+s32 ShrinkWindow_Letterbox_GetSize(void);
+
+void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target);
+s32 ShrinkWindow_Pillarbox_GetSizeTarget(void);
+void ShrinkWindow_Pillarbox_SetSize(s32 size);
+s32 ShrinkWindow_Pillarbox_GetSize(void);
+
+void ShrinkWindow_Init(void);
+void ShrinkWindow_Destroy(void);
+void ShrinkWindow_Update(s32 framerateDivisor);
+void ShrinkWindow_Draw(GraphicsContext* gfxCtx);
+
+#endif
diff --git a/include/z64view.h b/include/z64view.h
index 98ca1ab19..f0661d947 100644
--- a/include/z64view.h
+++ b/include/z64view.h
@@ -33,16 +33,27 @@ typedef struct View {
/* 0x0E0 */ Mtx unkE0;
/* 0x120 */ Mtx* projectionPtr;
/* 0x124 */ Mtx* viewingPtr;
- /* 0x128 */ Vec3f distortionDirRot;
+ /* 0x128 */ Vec3f distortionOrientation;
/* 0x134 */ Vec3f distortionScale;
/* 0x140 */ f32 distortionSpeed;
- /* 0x144 */ Vec3f curDistortionDirRot;
+ /* 0x144 */ Vec3f curDistortionOrientation;
/* 0x150 */ Vec3f curDistortionScale;
- /* 0x15C */ u16 normal; // used to normalize the projection matrix
+ /* 0x15C */ u16 perspNorm; // used to normalize the projection matrix
/* 0x160 */ u32 flags; // bit 3: Render to an orthographic perspective
/* 0x164 */ s32 unk164;
} View; // size = 0x168
+#define VIEW_VIEWING (1 << 0)
+#define VIEW_VIEWPORT (1 << 1)
+#define VIEW_PROJECTION_PERSPECTIVE (1 << 2)
+#define VIEW_PROJECTION_ORTHO (1 << 3)
+#define VIEW_ALL (VIEW_VIEWING | VIEW_VIEWPORT | VIEW_PROJECTION_PERSPECTIVE | VIEW_PROJECTION_ORTHO)
+
+#define VIEW_FORCE_VIEWING (VIEW_VIEWING << 4)
+#define VIEW_FORCE_VIEWPORT (VIEW_VIEWPORT << 4)
+#define VIEW_FORCE_PROJECTION_PERSPECTIVE (VIEW_PROJECTION_PERSPECTIVE << 4)
+#define VIEW_FORCE_PROJECTION_ORTHO (VIEW_PROJECTION_ORTHO << 4)
+
#define SET_FULLSCREEN_VIEWPORT(view) \
{ \
Viewport viewport; \
@@ -54,4 +65,28 @@ typedef struct View {
} \
(void)0
+void View_Init(View* view, struct GraphicsContext* gfxCtx);
+void View_LookAt(View* view, Vec3f* eye, Vec3f* at, Vec3f* up);
+void View_SetScale(View* view, f32 scale);
+void View_GetScale(View* view, f32* scale);
+void View_SetPerspective(View* view, f32 fovy, f32 zNear, f32 zFar);
+void View_GetPerspective(View* view, f32* fovy, f32* zNear, f32* zFar);
+void View_SetOrtho(View* view, f32 fovy, f32 zNear, f32 zFar);
+void View_GetOrtho(View* view, f32* fovy, f32* zNear, f32* zFar);
+void View_SetViewport(View* view, Viewport* viewport);
+void View_GetViewport(View* view, Viewport* viewport);
+
+s32 View_SetDistortionOrientation(View* view, f32 rotX, f32 rotY, f32 rotZ);
+s32 View_SetDistortionScale(View* view, f32 scaleX, f32 scaleY, f32 scaleZ);
+s32 View_SetDistortionSpeed(View* view, f32 speed);
+s32 View_InitDistortion(View* view);
+s32 View_ClearDistortion(View* view);
+s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed);
+
+void View_Apply(View* view, s32 mask);
+s32 View_ApplyOrthoToOverlay(View* view);
+s32 View_ApplyPerspectiveToOverlay(View* view);
+s32 View_UpdateViewingMatrix(View* view);
+s32 View_ApplyTo(View* view, Gfx** gfxp);
+
#endif
diff --git a/spec b/spec
index b4a8a6108..100e615cf 100644
--- a/spec
+++ b/spec
@@ -608,7 +608,6 @@ beginseg
pad_text
include "build/src/code/audio/audio_data.o"
include "build/src/code/audio/audio_synthesis.o"
- include "build/data/code/audio_synthesis.data.o"
include "build/src/code/audio/audio_heap.o"
include "build/data/code/audio_heap.bss.o"
include "build/src/code/audio/audio_load.o"
@@ -984,8 +983,7 @@ beginseg
name "ovl_En_M_Thunder"
compress
include "build/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.o"
- include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.data.o"
- include "build/data/ovl_En_M_Thunder/ovl_En_M_Thunder.reloc.o"
+ include "build/src/overlays/actors/ovl_En_M_Thunder/ovl_En_M_Thunder_reloc.o"
endseg
beginseg
@@ -1870,8 +1868,7 @@ beginseg
name "ovl_Effect_Ss_Solder_Srch_Ball"
compress
include "build/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.o"
- include "build/data/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball.data.o"
- include "build/data/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball.reloc.o"
+ include "build/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/ovl_Effect_Ss_Solder_Srch_Ball_reloc.o"
endseg
beginseg
@@ -2715,8 +2712,7 @@ beginseg
name "ovl_En_Wiz"
compress
include "build/src/overlays/actors/ovl_En_Wiz/z_en_wiz.o"
- include "build/data/ovl_En_Wiz/ovl_En_Wiz.data.o"
- include "build/data/ovl_En_Wiz/ovl_En_Wiz.reloc.o"
+ include "build/src/overlays/actors/ovl_En_Wiz/ovl_En_Wiz_reloc.o"
endseg
beginseg
@@ -3200,8 +3196,7 @@ beginseg
name "ovl_En_Door_Etc"
compress
include "build/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.o"
- include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.data.o"
- include "build/data/ovl_En_Door_Etc/ovl_En_Door_Etc.reloc.o"
+ include "build/src/overlays/actors/ovl_En_Door_Etc/ovl_En_Door_Etc_reloc.o"
endseg
beginseg
@@ -5033,8 +5028,7 @@ beginseg
name "ovl_Dm_Tag"
compress
include "build/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.o"
- include "build/data/ovl_Dm_Tag/ovl_Dm_Tag.data.o"
- include "build/data/ovl_Dm_Tag/ovl_Dm_Tag.reloc.o"
+ include "build/src/overlays/actors/ovl_Dm_Tag/ovl_Dm_Tag_reloc.o"
endseg
beginseg
diff --git a/src/code/audio/audio_data.c b/src/code/audio/audio_data.c
index 7238a4bfa..eb931262b 100644
--- a/src/code/audio/audio_data.c
+++ b/src/code/audio/audio_data.c
@@ -857,22 +857,99 @@ EnvelopePoint gDefaultEnvelope[] = {
{ ADSR_DISABLE, 0 },
};
-NoteSubEu gZeroNoteSub = { 0 };
+NoteSampleState gZeroedSampleState = { 0 };
-NoteSubEu gDefaultNoteSub = {
- { 1, 1, 0, 0, 0, 0, 0, 0 }, { 0 }, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+NoteSampleState gDefaultSampleState = {
+ { true, true, false, false, false, false, false, false },
+ { 0 },
+ 0, // gain
+ 0, // haasEffectLeftDelaySize
+ 0, // haasEffectRightDelaySize
+ 0, // targetReverbVol
+ 0, // harmonicIndexCurAndPrev
+ 0, // combFilterSize
+ 0, // targetVolLeft
+ 0, // targetVolRight
+ 0, // frequencyFixedPoint
+ 0, // combFilterGain
+ NULL, // tunedSample
+ NULL, // filter
+ 0, // unk_18
+ 0, // surroundEffectIndex
+ 0, // unk_1A
};
-u16 gHeadsetPanQuantization[64] = {
- 60, 58, 56, 54, 52, 50, 48, 46, 44, 42, 40, 38, 36, 34, 32, 30, 28, 26, 24, 22, 20, 18,
- 16, 14, 12, 10, 8, 6, 4, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+u16 gHaasEffectDelaySize[64] = {
+ 30 * SAMPLE_SIZE,
+ 29 * SAMPLE_SIZE,
+ 28 * SAMPLE_SIZE,
+ 27 * SAMPLE_SIZE,
+ 26 * SAMPLE_SIZE,
+ 25 * SAMPLE_SIZE,
+ 24 * SAMPLE_SIZE,
+ 23 * SAMPLE_SIZE,
+ 22 * SAMPLE_SIZE,
+ 21 * SAMPLE_SIZE,
+ 20 * SAMPLE_SIZE,
+ 19 * SAMPLE_SIZE,
+ 18 * SAMPLE_SIZE,
+ 17 * SAMPLE_SIZE,
+ 16 * SAMPLE_SIZE,
+ 15 * SAMPLE_SIZE,
+ 14 * SAMPLE_SIZE,
+ 13 * SAMPLE_SIZE,
+ 12 * SAMPLE_SIZE,
+ 11 * SAMPLE_SIZE,
+ 10 * SAMPLE_SIZE,
+ 9 * SAMPLE_SIZE,
+ 8 * SAMPLE_SIZE,
+ 7 * SAMPLE_SIZE,
+ 6 * SAMPLE_SIZE,
+ 5 * SAMPLE_SIZE,
+ 4 * SAMPLE_SIZE,
+ 3 * SAMPLE_SIZE,
+ 2 * SAMPLE_SIZE,
+ 1 * SAMPLE_SIZE,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
};
s32 D_801D58A4 = 0;
// clang-format off
-s16 D_801D58A8[] = {
+s16 gInvalidAdpcmCodeBook[] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
diff --git a/src/code/audio/audio_heap.c b/src/code/audio/audio_heap.c
index 667cd1c40..8412220a3 100644
--- a/src/code/audio/audio_heap.c
+++ b/src/code/audio/audio_heap.c
@@ -10,7 +10,7 @@ void AudioHeap_DiscardSampleCaches(void);
void AudioHeap_DiscardSampleBank(s32 sampleBankId);
void AudioHeap_ApplySampleBankCacheInternal(s32 apply, s32 sampleBankId);
void AudioHeap_DiscardSampleBanks(void);
-void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags);
+void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit);
#define gTatumsPerBeat (gAudioTatumInit[1])
@@ -421,7 +421,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry0 == LOAD_STATUS_MAYBE_DISCARDABLE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -435,7 +435,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry1 == LOAD_STATUS_MAYBE_DISCARDABLE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -491,7 +491,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry0 == LOAD_STATUS_COMPLETE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[0].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -504,7 +504,7 @@ void* AudioHeap_AllocCached(s32 tableType, size_t size, s32 cache, s32 id) {
if (loadStatusEntry1 == LOAD_STATUS_COMPLETE) {
for (i = 0; i < gAudioContext.numNotes; i++) {
if ((gAudioContext.notes[i].playbackState.fontId == temporaryCache->entries[1].id) &&
- gAudioContext.notes[i].noteSubEu.bitField0.enabled) {
+ gAudioContext.notes[i].sampleState.bitField0.enabled) {
break;
}
}
@@ -814,7 +814,7 @@ void AudioHeap_UpdateReverb(SynthesisReverb* reverb) {
void AudioHeap_UpdateReverbs(void) {
s32 count;
- s32 i;
+ s32 reverbIndex;
s32 j;
if (gAudioContext.audioBufferParameters.specUnk4 == 2) {
@@ -823,9 +823,9 @@ void AudioHeap_UpdateReverbs(void) {
count = 1;
}
- for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) {
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
for (j = 0; j < count; j++) {
- AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[i]);
+ AudioHeap_UpdateReverb(&gAudioContext.synthesisReverbs[reverbIndex]);
}
}
}
@@ -837,7 +837,7 @@ void AudioHeap_ClearAiBuffers(void) {
s32 curAiBufferIndex = gAudioContext.curAiBufferIndex;
s32 i;
- gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.minAiBufNumSamples;
+ gAudioContext.aiBufNumSamples[curAiBufferIndex] = gAudioContext.audioBufferParameters.numSamplesPerFrameMin;
for (i = 0; i < AIBUF_LEN; i++) {
gAudioContext.aiBuffers[curAiBufferIndex][i] = 0;
@@ -870,7 +870,7 @@ s32 AudioHeap_ResetStep(void) {
AudioHeap_UpdateReverbs();
} else {
for (i = 0; i < gAudioContext.numNotes; i++) {
- if (gAudioContext.notes[i].noteSubEu.bitField0.enabled &&
+ if (gAudioContext.notes[i].sampleState.bitField0.enabled &&
gAudioContext.notes[i].playbackState.adsr.action.s.state != ADSR_STATE_DISABLED) {
gAudioContext.notes[i].playbackState.adsr.fadeOutVel =
gAudioContext.audioBufferParameters.updatesPerFrameInv;
@@ -907,7 +907,7 @@ s32 AudioHeap_ResetStep(void) {
AudioHeap_Init();
gAudioContext.resetStatus = 0;
for (i = 0; i < ARRAY_COUNT(gAudioContext.aiBufNumSamples); i++) {
- gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.maxAiBufNumSamples;
+ gAudioContext.aiBufNumSamples[i] = gAudioContext.audioBufferParameters.numSamplesPerFrameMax;
for (j = 0; j < AIBUF_LEN; j++) {
gAudioContext.aiBuffers[i][j] = 0;
}
@@ -930,8 +930,8 @@ void AudioHeap_Init(void) {
size_t cachePoolSize;
size_t miscPoolSize;
u32 intMask;
+ s32 reverbIndex;
s32 i;
- s32 j;
s32 pad2;
AudioSpec* spec = &gAudioSpecs[gAudioContext.audioResetSpecIdToLoad]; // Audio Specifications
@@ -942,19 +942,22 @@ void AudioHeap_Init(void) {
gAudioContext.audioBufferParameters.aiSamplingFreq =
osAiSetFrequency(gAudioContext.audioBufferParameters.samplingFreq);
- gAudioContext.audioBufferParameters.samplesPerFrameTarget =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget =
ALIGN16(gAudioContext.audioBufferParameters.samplingFreq / gAudioContext.refreshRate);
- gAudioContext.audioBufferParameters.minAiBufNumSamples =
- gAudioContext.audioBufferParameters.samplesPerFrameTarget - 0x10;
- gAudioContext.audioBufferParameters.maxAiBufNumSamples =
- gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMin =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget - 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax =
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10;
gAudioContext.audioBufferParameters.updatesPerFrame =
- ((gAudioContext.audioBufferParameters.samplesPerFrameTarget + 0x10) / 0xD0) + 1;
- gAudioContext.audioBufferParameters.samplesPerUpdate = (gAudioContext.audioBufferParameters.samplesPerFrameTarget /
- gAudioContext.audioBufferParameters.updatesPerFrame) &
- ~7;
- gAudioContext.audioBufferParameters.samplesPerUpdateMax = gAudioContext.audioBufferParameters.samplesPerUpdate + 8;
- gAudioContext.audioBufferParameters.samplesPerUpdateMin = gAudioContext.audioBufferParameters.samplesPerUpdate - 8;
+ ((gAudioContext.audioBufferParameters.numSamplesPerFrameTarget + 0x10) / 0xD0) + 1;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate =
+ (gAudioContext.audioBufferParameters.numSamplesPerFrameTarget /
+ gAudioContext.audioBufferParameters.updatesPerFrame) &
+ ~7;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMax =
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate + 8;
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMin =
+ gAudioContext.audioBufferParameters.numSamplesPerUpdate - 8;
gAudioContext.audioBufferParameters.resampleRate = 32000.0f / (s32)gAudioContext.audioBufferParameters.samplingFreq;
gAudioContext.audioBufferParameters.updatesPerFrameInvScaled =
(1.0f / 256.0f) / gAudioContext.audioBufferParameters.updatesPerFrame;
@@ -984,13 +987,13 @@ void AudioHeap_Init(void) {
gAudioContext.unk_2870 /= gAudioContext.tempoInternalToExternal;
gAudioContext.audioBufferParameters.specUnk4 = spec->unk_04;
- gAudioContext.audioBufferParameters.samplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4;
- gAudioContext.audioBufferParameters.maxAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4;
- gAudioContext.audioBufferParameters.minAiBufNumSamples *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameTarget *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax *= gAudioContext.audioBufferParameters.specUnk4;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMin *= gAudioContext.audioBufferParameters.specUnk4;
gAudioContext.audioBufferParameters.updatesPerFrame *= gAudioContext.audioBufferParameters.specUnk4;
if (gAudioContext.audioBufferParameters.specUnk4 >= 2) {
- gAudioContext.audioBufferParameters.maxAiBufNumSamples -= 0x10;
+ gAudioContext.audioBufferParameters.numSamplesPerFrameMax -= 0x10;
}
// Determine the maximum allowable number of audio command list entries for the rsp microcode
@@ -1037,13 +1040,13 @@ void AudioHeap_Init(void) {
gAudioContext.notes = AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.numNotes * sizeof(Note));
AudioPlayback_NoteInitAll();
AudioPlayback_InitNoteFreeList();
- gAudioContext.noteSubsEu =
+ gAudioContext.sampleStateList =
AudioHeap_AllocZeroed(&gAudioContext.miscPool, gAudioContext.audioBufferParameters.updatesPerFrame *
- gAudioContext.numNotes * sizeof(NoteSubEu));
+ gAudioContext.numNotes * sizeof(NoteSampleState));
// Initialize audio binary interface command list buffer
- for (j = 0; j < ARRAY_COUNT(gAudioContext.abiCmdBufs); j++) {
- gAudioContext.abiCmdBufs[j] =
+ for (i = 0; i < ARRAY_COUNT(gAudioContext.abiCmdBufs); i++) {
+ gAudioContext.abiCmdBufs[i] =
AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, gAudioContext.maxAudioCmds * sizeof(Acmd));
}
@@ -1052,20 +1055,20 @@ void AudioHeap_Init(void) {
AudioHeap_InitAdsrDecayTable();
// Initialize reverbs
- for (i = 0; i < ARRAY_COUNT(gAudioContext.synthesisReverbs); i++) {
- gAudioContext.synthesisReverbs[i].useReverb = 0;
+ for (reverbIndex = 0; reverbIndex < ARRAY_COUNT(gAudioContext.synthesisReverbs); reverbIndex++) {
+ gAudioContext.synthesisReverbs[reverbIndex].useReverb = 0;
}
gAudioContext.numSynthesisReverbs = spec->numReverbs;
- for (i = 0; i < gAudioContext.numSynthesisReverbs; i++) {
- AudioHeap_InitReverb(i, &spec->reverbSettings[i], 1);
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ AudioHeap_InitReverb(reverbIndex, &spec->reverbSettings[reverbIndex], true);
}
// Initialize sequence players
AudioSeq_InitSequencePlayers();
- for (j = 0; j < gAudioContext.audioBufferParameters.numSequencePlayers; j++) {
- AudioSeq_InitSequencePlayerChannels(j);
- AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[j]);
+ for (i = 0; i < gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
+ AudioSeq_InitSequencePlayerChannels(i);
+ AudioSeq_ResetSequencePlayer(&gAudioContext.seqPlayers[i]);
}
// Initialize two additional caches on the audio heap to store individual audio samples
@@ -1529,149 +1532,165 @@ void AudioHeap_DiscardSampleBanks(void) {
}
}
-void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 flags) {
- s32 windowSize;
+void AudioHeap_SetReverbData(s32 reverbIndex, u32 dataType, s32 data, s32 isFirstInit) {
+ s32 delayNumSamples;
SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex];
switch (dataType) {
- case 0:
- AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, 0);
+ case REVERB_DATA_TYPE_SETTINGS:
+ AudioHeap_InitReverb(reverbIndex, (ReverbSettings*)data, false);
break;
- case 1:
+
+ case REVERB_DATA_TYPE_DELAY:
if (data < 4) {
data = 4;
}
- windowSize = data * 64;
- if (windowSize < 0x100) {
- windowSize = 0x100;
+ delayNumSamples = data * 64;
+ if (delayNumSamples < (16 * SAMPLES_PER_FRAME)) {
+ delayNumSamples = 16 * SAMPLES_PER_FRAME;
}
- windowSize /= reverb->downsampleRate;
+ delayNumSamples /= reverb->downsampleRate;
- if (flags == 0) {
- if (reverb->unk_1E >= (data / reverb->downsampleRate)) {
- if ((reverb->nextRingBufPos >= windowSize) || (reverb->unk_24 >= windowSize)) {
- reverb->nextRingBufPos = 0;
- reverb->unk_24 = 0;
- }
- } else {
+ if (!isFirstInit) {
+ if (reverb->delayNumSamplesAfterDownsampling < (data / reverb->downsampleRate)) {
break;
}
+ if ((reverb->nextReverbBufPos >= delayNumSamples) || (reverb->delayNumSamplesUnk >= delayNumSamples)) {
+ reverb->nextReverbBufPos = 0;
+ reverb->delayNumSamplesUnk = 0;
+ }
}
- reverb->windowSize = windowSize;
+ reverb->delayNumSamples = delayNumSamples;
- if ((reverb->downsampleRate != 1) || reverb->unk_18) {
- reverb->unk_0E = 0x8000 / reverb->downsampleRate;
- if (reverb->unk_30 == NULL) {
- reverb->unk_30 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_34 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_38 = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- reverb->unk_3C = AudioHeap_AllocZeroed(&gAudioContext.miscPool, 0x20);
- if (reverb->unk_3C == NULL) {
+ if ((reverb->downsampleRate != 1) || reverb->resampleEffectOn) {
+ reverb->downsamplePitch = 0x8000 / reverb->downsampleRate;
+ if (reverb->leftLoadResampleBuf == NULL) {
+ reverb->leftLoadResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->rightLoadResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->leftSaveResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ reverb->rightSaveResampleBuf =
+ AudioHeap_AllocZeroed(&gAudioContext.miscPool, sizeof(RESAMPLE_STATE));
+ if (reverb->rightSaveResampleBuf == NULL) {
reverb->downsampleRate = 1;
}
}
}
break;
- case 2:
- gAudioContext.synthesisReverbs[reverbIndex].unk_0C = data;
+
+ case REVERB_DATA_TYPE_DECAY:
+ gAudioContext.synthesisReverbs[reverbIndex].decayRatio = data;
break;
- case 3:
- gAudioContext.synthesisReverbs[reverbIndex].unk_16 = data;
+
+ case REVERB_DATA_TYPE_SUB_VOLUME:
+ gAudioContext.synthesisReverbs[reverbIndex].subVolume = data;
break;
- case 4:
- gAudioContext.synthesisReverbs[reverbIndex].unk_0A = data;
+
+ case REVERB_DATA_TYPE_VOLUME:
+ gAudioContext.synthesisReverbs[reverbIndex].volume = data;
break;
- case 5:
+
+ case REVERB_DATA_TYPE_LEAK_RIGHT:
gAudioContext.synthesisReverbs[reverbIndex].leakRtl = data;
break;
- case 6:
+
+ case REVERB_DATA_TYPE_LEAK_LEFT:
gAudioContext.synthesisReverbs[reverbIndex].leakLtr = data;
break;
- case 7:
+
+ case REVERB_DATA_TYPE_FILTER_LEFT:
if (data != 0) {
- if ((flags != 0) || (reverb->unk_278 == 0)) {
- reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40);
- reverb->unk_278 = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ if (isFirstInit || (reverb->filterLeftInit == NULL)) {
+ reverb->filterLeftState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool,
+ 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2));
+ reverb->filterLeftInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
- reverb->filterLeft = reverb->unk_278;
- if (reverb->filterLeft != 0) {
+ reverb->filterLeft = reverb->filterLeftInit;
+ if (reverb->filterLeft != NULL) {
AudioHeap_LoadLowPassFilter(reverb->filterLeft, data);
}
} else {
- reverb->filterLeft = 0;
+ reverb->filterLeft = NULL;
- if (flags != 0) {
- reverb->unk_278 = 0;
+ if (isFirstInit) {
+ reverb->filterLeftInit = NULL;
}
}
-
break;
- case 8:
+
+ case REVERB_DATA_TYPE_FILTER_RIGHT:
if (data != 0) {
- if ((flags != 0) || (reverb->unk_27C == 0)) {
- reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(&gAudioContext.miscPool, 0x40);
- reverb->unk_27C = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ if (isFirstInit || (reverb->filterRightInit == NULL)) {
+ reverb->filterRightState = AudioHeap_AllocDmaMemoryZeroed(
+ &gAudioContext.miscPool, 2 * (FILTER_BUF_PART1 + FILTER_BUF_PART2));
+ reverb->filterRightInit = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
- reverb->filterRight = reverb->unk_27C;
- if (reverb->unk_27C != 0) {
- AudioHeap_LoadLowPassFilter(reverb->unk_27C, data);
+ reverb->filterRight = reverb->filterRightInit;
+ if (reverb->filterRight != NULL) {
+ AudioHeap_LoadLowPassFilter(reverb->filterRight, data);
}
} else {
- reverb->filterRight = 0;
- if (flags != 0) {
- reverb->unk_27C = 0;
+ reverb->filterRight = NULL;
+ if (isFirstInit) {
+ reverb->filterRightInit = NULL;
}
}
break;
- case 9:
- reverb->unk_19 = data;
+
+ case REVERB_DATA_TYPE_9:
+ reverb->resampleEffectExtraSamples = data;
if (data == 0) {
- reverb->unk_18 = false;
+ reverb->resampleEffectOn = false;
} else {
- reverb->unk_18 = true;
+ reverb->resampleEffectOn = true;
}
break;
+
default:
break;
}
}
-void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags) {
+void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 isFirstInit) {
SynthesisReverb* reverb = &gAudioContext.synthesisReverbs[reverbIndex];
- if (flags != 0) {
- reverb->unk_1E = settings->windowSize / settings->downsampleRate;
- reverb->unk_30 = 0;
- } else if (reverb->unk_1E < (settings->windowSize / settings->downsampleRate)) {
+ if (isFirstInit) {
+ reverb->delayNumSamplesAfterDownsampling = settings->delayNumSamples / settings->downsampleRate;
+ reverb->leftLoadResampleBuf = NULL;
+ } else if (reverb->delayNumSamplesAfterDownsampling < (settings->delayNumSamples / settings->downsampleRate)) {
return;
}
reverb->downsampleRate = settings->downsampleRate;
- reverb->unk_18 = false;
- reverb->unk_19 = 0;
- reverb->unk_1A = 0;
- reverb->unk_1C = 0;
- AudioHeap_SetReverbData(reverbIndex, 1, settings->windowSize, flags);
- reverb->unk_0C = settings->unk_4;
- reverb->unk_0A = settings->unk_A;
- reverb->unk_14 = settings->unk_6 << 6;
- reverb->unk_16 = settings->unk_8;
+ reverb->resampleEffectOn = false;
+ reverb->resampleEffectExtraSamples = 0;
+ reverb->resampleEffectLoadUnk = 0;
+ reverb->resampleEffectSaveUnk = 0;
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_DELAY, settings->delayNumSamples, isFirstInit);
+ reverb->decayRatio = settings->decayRatio;
+ reverb->volume = settings->volume;
+ reverb->subDelay = settings->subDelay * 64;
+ reverb->subVolume = settings->subVolume;
reverb->leakRtl = settings->leakRtl;
reverb->leakLtr = settings->leakLtr;
- reverb->unk_05 = settings->unk_10;
- reverb->unk_08 = settings->unk_12;
- reverb->useReverb = 8;
+ reverb->mixReverbIndex = settings->mixReverbIndex;
+ reverb->mixReverbStrength = settings->mixReverbStrength;
+ reverb->useReverb = 8; // used as a boolean
- if (flags != 0) {
- reverb->leftRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2);
- reverb->rightRingBuf = AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->windowSize * 2);
+ if (isFirstInit) {
+ reverb->leftReverbBuf =
+ AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2);
+ reverb->rightReverbBuf =
+ AudioHeap_AllocZeroedAttemptExternal(&gAudioContext.miscPool, reverb->delayNumSamples * 2);
reverb->resampleFlags = 1;
- reverb->nextRingBufPos = 0;
- reverb->unk_24 = 0;
+ reverb->nextReverbBufPos = 0;
+ reverb->delayNumSamplesUnk = 0;
reverb->curFrame = 0;
reverb->framesToIgnore = 2;
}
@@ -1681,12 +1700,13 @@ void AudioHeap_InitReverb(s32 reverbIndex, ReverbSettings* settings, s32 flags)
reverb->tunedSample.tuning = 1.0f;
reverb->sample.codec = CODEC_REVERB;
reverb->sample.medium = MEDIUM_RAM;
- reverb->sample.size = reverb->windowSize * 2;
- reverb->sample.sampleAddr = (u8*)reverb->leftRingBuf;
+ reverb->sample.size = reverb->delayNumSamples * SAMPLE_SIZE;
+ reverb->sample.sampleAddr = (u8*)reverb->leftReverbBuf;
reverb->loop.start = 0;
reverb->loop.count = 1;
- reverb->loop.end = reverb->windowSize;
+ reverb->loop.loopEnd = reverb->delayNumSamples;
- AudioHeap_SetReverbData(reverbIndex, 7, settings->lowPassFilterCutoffLeft, flags);
- AudioHeap_SetReverbData(reverbIndex, 8, settings->lowPassFilterCutoffRight, flags);
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_LEFT, settings->lowPassFilterCutoffLeft, isFirstInit);
+ AudioHeap_SetReverbData(reverbIndex, REVERB_DATA_TYPE_FILTER_RIGHT, settings->lowPassFilterCutoffRight,
+ isFirstInit);
}
diff --git a/src/code/audio/audio_init_params.c b/src/code/audio/audio_init_params.c
index 81c49b30c..59c6658ac 100644
--- a/src/code/audio/audio_init_params.c
+++ b/src/code/audio/audio_init_params.c
@@ -1,12 +1,184 @@
#include "global.h"
const s16 gAudioTatumInit[] = {
- 0x1C00, // unused
- 0x30, // gTatumsPerBeat
+ 0x1C00, // unused
+ TATUMS_PER_BEAT, // gTatumsPerBeat
};
+// TODO: Extract from table?
+#define NUM_SOUNDFONTS 41
+#define SFX_SEQ_SIZE 0xC6A0
+#define AMBIENCE_SEQ_SIZE 0xFC0
+#define SOUNDFONT_0_SIZE 0x81C0
+#define SOUNDFONT_1_SIZE 0x36D0
+#define SOUNDFONT_2_SIZE 0xCE0
+
+// Sizes of everything on the init pool
+#define AI_BUFFERS_SIZE (AIBUF_SIZE * ARRAY_COUNT(gAudioContext.aiBuffers))
+#define SOUNDFONT_LIST_SIZE (NUM_SOUNDFONTS * sizeof(SoundFont))
+
+// 0x19BD0
+#define PERMANENT_POOL_SIZE \
+ (SFX_SEQ_SIZE + AMBIENCE_SEQ_SIZE + SOUNDFONT_0_SIZE + SOUNDFONT_1_SIZE + SOUNDFONT_2_SIZE + 0x430)
+
const AudioHeapInitSizes gAudioHeapInitSizes = {
- 0x137F00, // heapSize
- 0x1C480, // initPoolSize
- 0x1A000, // permanentPoolSize
+ ALIGN16(sizeof(gAudioHeap) - 0x100), // audio heap size
+ ALIGN16(PERMANENT_POOL_SIZE + AI_BUFFERS_SIZE + SOUNDFONT_LIST_SIZE + 0x40), // init pool size
+ ALIGN16(PERMANENT_POOL_SIZE), // permanent pool size
+};
+
+#define REVERB_INDEX_0_SETTINGS \
+ { 1, 0x30, 0x3000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 }
+
+ReverbSettings reverbSettings0[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x20, 0x0800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 },
+};
+
+ReverbSettings reverbSettings1[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings reverbSettings2[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x38, 0x2800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 7, 7 },
+};
+
+ReverbSettings reverbSettings3[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+ { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettings4[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 },
+};
+
+ReverbSettings reverbSettings5[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5C00, 0, 0, 0x7FFF, 0x2000, 0x2000, REVERB_INDEX_NONE, 0x3000, 4, 4 },
+};
+
+ReverbSettings reverbSettings6[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6000, 0, 0, 0x7FFF, 0x1000, 0x1000, REVERB_INDEX_NONE, 0x3000, 10, 10 },
+};
+
+ReverbSettings reverbSettings7[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+};
+
+ReverbSettings reverbSettings8[2] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x50, 0x5000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettings9[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x20, 0x0000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsA[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings reverbSettingsB[3] = {
+ REVERB_INDEX_0_SETTINGS,
+};
+
+ReverbSettings reverbSettingsC[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsD[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x6800, 0, 0, 0x7FFF, 0x1400, 0x1400, REVERB_INDEX_NONE, 0x3000, 6, 6 },
+ { 2, 0x50, 0x6000, 0, 0, 0x7FFF, 0xD000, 0x3000, REVERB_INDEX_NONE, 0x3000, 0, 0 },
+};
+
+ReverbSettings reverbSettingsE[3] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x30, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+ { 1, 0x40, 0x5000, 0, 0, 0x7FFF, 0x1800, 0x1800, REVERB_INDEX_NONE, 0x3000, 7, 7 },
+};
+
+ReverbSettings reverbSettingsF[2] = {
+ REVERB_INDEX_0_SETTINGS,
+ { 1, 0x50, 0x1800, 0, 0, 0x7FFF, 0x0000, 0x0000, REVERB_INDEX_NONE, 0x0000, 11, 11 },
+};
+
+ReverbSettings* gReverbSettingsTable[] = {
+ reverbSettings0, reverbSettings1, reverbSettings2, reverbSettings4, reverbSettings5,
+ reverbSettings6, reverbSettings7, reverbSettings8, reverbSettings9, reverbSettings3,
+};
+
+AudioSpec gAudioSpecs[21] = {
+ /* 0x0 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x1 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x2 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x3 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x4 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x5 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x6 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x7 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x8 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x9 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xA */
+ { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x2800, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xB */
+ { 32000, 1, 28, 3, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xC */
+ { 32000, 1, 28, 5, 0, 0, 2, reverbSettingsA, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xCC800 },
+ /* 0xD */
+ { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsD, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xE */
+ { 32000, 1, 24, 5, 0, 0, 3, reverbSettingsE, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0xF */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettingsF, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4000, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x10 */
+ { 32000, 1, 22, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x11 */
+ { 32000, 1, 22, 5, 0, 0, 2, reverbSettings8, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x12 */
+ { 32000, 1, 16, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x13 */
+ { 22050, 1, 24, 5, 0, 0, 2, reverbSettings0, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x4100, 0x2D00, 0, 0,
+ 0xDC800 },
+ /* 0x14 */
+ { 32000, 1, 24, 5, 0, 0, 2, reverbSettings2, 0x500, 0x200, 0x7FFF, 0xAF0, 0x2D80, 0, 0x3600, 0x2600, 0, 0,
+ 0xDC800 },
};
diff --git a/src/code/audio/audio_load.c b/src/code/audio/audio_load.c
index c8e5ac5d1..ccdc7488d 100644
--- a/src/code/audio/audio_load.c
+++ b/src/code/audio/audio_load.c
@@ -1218,9 +1218,9 @@ void AudioLoad_Init(void* heap, size_t heapSize) {
s32 i;
s32 j;
- D_80208E68 = NULL;
- D_80208E70 = NULL;
- D_80208E74 = NULL;
+ gCustomAudioUpdateFunction = NULL;
+ gCustomAudioReverbFunction = NULL;
+ gCustomAudioSynthFunction = NULL;
for (i = 0; i < ARRAY_COUNT(gAudioContext.unk_29A8); i++) {
gAudioContext.unk_29A8[i] = NULL;
diff --git a/src/code/audio/audio_playback.c b/src/code/audio/audio_playback.c
index e1a42b1ed..a7cc9a588 100644
--- a/src/code/audio/audio_playback.c
+++ b/src/code/audio/audio_playback.c
@@ -1,10 +1,10 @@
#include "global.h"
-void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput);
+void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput);
void AudioPlayback_AudioListPushFront(AudioListItem* list, AudioListItem* item);
void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer);
-void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttributes* subAttrs) {
+void AudioPlayback_InitSampleState(Note* note, NoteSampleState* sampleState, NoteSubAttributes* subAttrs) {
f32 volLeft;
f32 volRight;
s32 halfPanIndex;
@@ -13,45 +13,45 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
u8 strongRight;
f32 vel;
u8 pan;
- u8 reverbVol;
+ u8 targetReverbVol;
StereoData stereoData;
s32 stereoHeadsetEffects = note->playbackState.stereoHeadsetEffects;
vel = subAttrs->velocity;
pan = subAttrs->pan;
- reverbVol = subAttrs->reverbVol;
- stereoData = subAttrs->stereo.s;
+ targetReverbVol = subAttrs->targetReverbVol;
+ stereoData = subAttrs->stereoData;
- noteSubEu->bitField0 = note->noteSubEu.bitField0;
- noteSubEu->bitField1 = note->noteSubEu.bitField1;
- noteSubEu->waveSampleAddr = note->noteSubEu.waveSampleAddr;
- noteSubEu->harmonicIndexCurAndPrev = note->noteSubEu.harmonicIndexCurAndPrev;
+ sampleState->bitField0 = note->sampleState.bitField0;
+ sampleState->bitField1 = note->sampleState.bitField1;
+ sampleState->waveSampleAddr = note->sampleState.waveSampleAddr;
+ sampleState->harmonicIndexCurAndPrev = note->sampleState.harmonicIndexCurAndPrev;
- AudioPlayback_NoteSetResamplingRate(noteSubEu, subAttrs->frequency);
+ AudioPlayback_NoteSetResamplingRate(sampleState, subAttrs->frequency);
pan &= 0x7F;
- noteSubEu->bitField0.stereoStrongRight = false;
- noteSubEu->bitField0.stereoStrongLeft = false;
- noteSubEu->bitField0.stereoHeadsetEffects = stereoData.stereoHeadsetEffects;
- noteSubEu->bitField0.usesHeadsetPanEffects = stereoData.usesHeadsetPanEffects;
+ sampleState->bitField0.strongRight = false;
+ sampleState->bitField0.strongLeft = false;
+ sampleState->bitField0.strongReverbRight = stereoData.strongReverbRight;
+ sampleState->bitField0.strongReverbLeft = stereoData.strongReverbLeft;
if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_HEADSET)) {
halfPanIndex = pan >> 1;
if (halfPanIndex > 0x3F) {
halfPanIndex = 0x3F;
}
- noteSubEu->headsetPanLeft = gHeadsetPanQuantization[halfPanIndex];
- noteSubEu->headsetPanRight = gHeadsetPanQuantization[0x3F - halfPanIndex];
- noteSubEu->bitField1.usesHeadsetPanEffects2 = true;
+ sampleState->haasEffectRightDelaySize = gHaasEffectDelaySize[halfPanIndex];
+ sampleState->haasEffectLeftDelaySize = gHaasEffectDelaySize[0x3F - halfPanIndex];
+ sampleState->bitField1.useHaasEffect = true;
volLeft = gHeadsetPanVolume[pan];
volRight = gHeadsetPanVolume[0x7F - pan];
} else if (stereoHeadsetEffects && (gAudioContext.soundMode == SOUNDMODE_STEREO)) {
strongLeft = strongRight = false;
- noteSubEu->headsetPanRight = 0;
- noteSubEu->headsetPanLeft = 0;
- noteSubEu->bitField1.usesHeadsetPanEffects2 = false;
+ sampleState->haasEffectLeftDelaySize = 0;
+ sampleState->haasEffectRightDelaySize = 0;
+ sampleState->bitField1.useHaasEffect = false;
volLeft = gStereoPanVolume[pan];
volRight = gStereoPanVolume[0x7F - pan];
@@ -62,37 +62,37 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
}
// case 0:
- noteSubEu->bitField0.stereoStrongRight = strongRight;
- noteSubEu->bitField0.stereoStrongLeft = strongLeft;
+ sampleState->bitField0.strongRight = strongRight;
+ sampleState->bitField0.strongLeft = strongLeft;
- switch (stereoData.bit2) {
+ switch (stereoData.type) {
case 0:
break;
case 1:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft;
break;
case 2:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight | strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft | strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight | strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft | strongLeft;
break;
case 3:
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight ^ strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft ^ strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight ^ strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft ^ strongLeft;
break;
}
} else if (gAudioContext.soundMode == SOUNDMODE_MONO) {
- noteSubEu->bitField0.stereoHeadsetEffects = false;
- noteSubEu->bitField0.usesHeadsetPanEffects = false;
+ sampleState->bitField0.strongReverbRight = false;
+ sampleState->bitField0.strongReverbLeft = false;
volLeft = 0.707f; // approx 1/sqrt(2)
volRight = 0.707f;
} else {
- noteSubEu->bitField0.stereoStrongRight = stereoData.strongRight;
- noteSubEu->bitField0.stereoStrongLeft = stereoData.strongLeft;
+ sampleState->bitField0.strongRight = stereoData.strongRight;
+ sampleState->bitField0.strongLeft = stereoData.strongLeft;
volLeft = gDefaultPanVolume[pan];
volRight = gDefaultPanVolume[0x7F - pan];
}
@@ -100,33 +100,33 @@ void AudioPlayback_InitNoteSub(Note* note, NoteSubEu* noteSubEu, NoteSubAttribut
vel = 0.0f > vel ? 0.0f : vel;
vel = 1.0f < vel ? 1.0f : vel;
- noteSubEu->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
- noteSubEu->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
+ sampleState->targetVolLeft = (s32)((vel * volLeft) * (0x1000 - 0.001f));
+ sampleState->targetVolRight = (s32)((vel * volRight) * (0x1000 - 0.001f));
- noteSubEu->gain = subAttrs->gain;
- noteSubEu->filter = subAttrs->filter;
- noteSubEu->unk_07 = subAttrs->unk_14;
- noteSubEu->unk_0E = subAttrs->unk_16;
- noteSubEu->reverbVol = reverbVol;
- noteSubEu->unk_19 = subAttrs->unk_3;
+ sampleState->gain = subAttrs->gain;
+ sampleState->filter = subAttrs->filter;
+ sampleState->combFilterSize = subAttrs->combFilterSize;
+ sampleState->combFilterGain = subAttrs->combFilterGain;
+ sampleState->targetReverbVol = targetReverbVol;
+ sampleState->surroundEffectIndex = subAttrs->surroundEffectIndex;
}
-void AudioPlayback_NoteSetResamplingRate(NoteSubEu* noteSubEu, f32 resamplingRateInput) {
+void AudioPlayback_NoteSetResamplingRate(NoteSampleState* sampleState, f32 resamplingRateInput) {
f32 resamplingRate = 0.0f;
if (resamplingRateInput < 2.0f) {
- noteSubEu->bitField1.hasTwoParts = false;
+ sampleState->bitField1.hasTwoParts = false;
resamplingRate = CLAMP_MAX(resamplingRateInput, 1.99998f);
} else {
- noteSubEu->bitField1.hasTwoParts = true;
+ sampleState->bitField1.hasTwoParts = true;
if (resamplingRateInput > 3.99996f) {
resamplingRate = 1.99998f;
} else {
resamplingRate = resamplingRateInput * 0.5f;
}
}
- noteSubEu->resamplingRateFixedPoint = (s32)(resamplingRate * 32768.0f);
+ sampleState->frequencyFixedPoint = (s32)(resamplingRate * 32768.0f);
}
void AudioPlayback_NoteInit(Note* note) {
@@ -140,17 +140,17 @@ void AudioPlayback_NoteInit(Note* note) {
note->playbackState.status = PLAYBACK_STATUS_0;
note->playbackState.adsr.action.s.state = ADSR_STATE_INITIAL;
- note->noteSubEu = gDefaultNoteSub;
+ note->sampleState = gDefaultSampleState;
}
void AudioPlayback_NoteDisable(Note* note) {
- if (note->noteSubEu.bitField0.needsInit == true) {
- note->noteSubEu.bitField0.needsInit = false;
+ if (note->sampleState.bitField0.needsInit == true) {
+ note->sampleState.bitField0.needsInit = false;
}
note->playbackState.priority = 0;
- note->noteSubEu.bitField0.enabled = false;
+ note->sampleState.bitField0.enabled = false;
note->playbackState.status = PLAYBACK_STATUS_0;
- note->noteSubEu.bitField0.finished = false;
+ note->sampleState.bitField0.finished = false;
note->playbackState.parentLayer = NO_LAYER;
note->playbackState.prevParentLayer = NO_LAYER;
note->playbackState.adsr.action.s.state = ADSR_STATE_DISABLED;
@@ -161,8 +161,8 @@ void AudioPlayback_ProcessNotes(void) {
s32 pad;
s32 playbackStatus;
NoteAttributes* attrs;
- NoteSubEu* noteSubEu2;
- NoteSubEu* noteSubEu;
+ NoteSampleState* sampleState;
+ NoteSampleState* noteSampleState;
Note* note;
NotePlaybackState* playbackState;
NoteSubAttributes subAttrs;
@@ -172,7 +172,7 @@ void AudioPlayback_ProcessNotes(void) {
for (i = 0; i < gAudioContext.numNotes; i++) {
note = &gAudioContext.notes[i];
- noteSubEu2 = &gAudioContext.noteSubsEu[gAudioContext.noteSubEuOffset + i];
+ sampleState = &gAudioContext.sampleStateList[gAudioContext.sampleStateOffset + i];
playbackState = ¬e->playbackState;
if (playbackState->parentLayer != NO_LAYER) {
if ((u32)playbackState->parentLayer < 0x7FFFFFFF) {
@@ -211,10 +211,12 @@ void AudioPlayback_ProcessNotes(void) {
out:
if (playbackState->priority != 0) {
+ //! FAKE:
if (1) {}
- noteSubEu = ¬e->noteSubEu;
- if ((playbackState->status >= 1) || noteSubEu->bitField0.finished) {
- if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) || noteSubEu->bitField0.finished) {
+ noteSampleState = ¬e->sampleState;
+ if ((playbackState->status >= 1) || noteSampleState->bitField0.finished) {
+ if ((playbackState->adsr.action.s.state == ADSR_STATE_DISABLED) ||
+ noteSampleState->bitField0.finished) {
if (playbackState->wantedParentLayer != NO_LAYER) {
AudioPlayback_NoteDisable(note);
if (playbackState->wantedParentLayer->channel != NULL) {
@@ -260,14 +262,14 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.frequency = attrs->freqScale;
subAttrs.velocity = attrs->velocity;
subAttrs.pan = attrs->pan;
- subAttrs.reverbVol = attrs->reverb;
- subAttrs.stereo = attrs->stereo;
+ subAttrs.targetReverbVol = attrs->targetReverbVol;
+ subAttrs.stereoData = attrs->stereoData;
subAttrs.gain = attrs->gain;
subAttrs.filter = attrs->filter;
- subAttrs.unk_14 = attrs->unk_4;
- subAttrs.unk_16 = attrs->unk_6;
- subAttrs.unk_3 = attrs->unk_3;
- bookOffset = noteSubEu->bitField1.bookOffset;
+ subAttrs.combFilterSize = attrs->combFilterSize;
+ subAttrs.combFilterGain = attrs->combFilterGain;
+ subAttrs.surroundEffectIndex = attrs->surroundEffectIndex;
+ bookOffset = noteSampleState->bitField1.bookOffset;
} else {
SequenceLayer* layer = playbackState->parentLayer;
SequenceChannel* channel = playbackState->parentLayer->channel;
@@ -276,34 +278,35 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.velocity = layer->noteVelocity;
subAttrs.pan = layer->notePan;
- if (layer->unk_08 == 0x80) {
- subAttrs.unk_3 = channel->unk_10;
+ if (layer->surroundEffectIndex == 0x80) {
+ subAttrs.surroundEffectIndex = channel->surroundEffectIndex;
} else {
- subAttrs.unk_3 = layer->unk_08;
+ subAttrs.surroundEffectIndex = layer->surroundEffectIndex;
}
- if (layer->stereo.s.bit2 == 0) {
- subAttrs.stereo = channel->stereo;
+ if (layer->stereoData.type == 0) {
+ subAttrs.stereoData = channel->stereoData;
} else {
- subAttrs.stereo = layer->stereo;
+ subAttrs.stereoData = layer->stereoData;
}
if (layer->unk_0A.s.bit_2 == 1) {
- subAttrs.reverbVol = channel->reverb;
+ subAttrs.targetReverbVol = channel->targetReverbVol;
} else {
- subAttrs.reverbVol = layer->unk_09;
+ subAttrs.targetReverbVol = layer->targetReverbVol;
}
if (layer->unk_0A.s.bit_9 == 1) {
subAttrs.gain = channel->gain;
} else {
subAttrs.gain = 0;
+ //! FAKE:
if (1) {}
}
subAttrs.filter = channel->filter;
- subAttrs.unk_14 = channel->unk_0F;
- subAttrs.unk_16 = channel->unk_20;
+ subAttrs.combFilterSize = channel->combFilterSize;
+ subAttrs.combFilterGain = channel->combFilterGain;
bookOffset = channel->bookOffset & 0x7;
if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) {
@@ -315,8 +318,8 @@ void AudioPlayback_ProcessNotes(void) {
subAttrs.frequency *= playbackState->vibratoFreqScale * playbackState->portamentoFreqScale;
subAttrs.frequency *= gAudioContext.audioBufferParameters.resampleRate;
subAttrs.velocity *= scale;
- AudioPlayback_InitNoteSub(note, noteSubEu2, &subAttrs);
- noteSubEu->bitField1.bookOffset = bookOffset;
+ AudioPlayback_InitSampleState(note, sampleState, &subAttrs);
+ noteSampleState->bitField1.bookOffset = bookOffset;
skip:;
}
}
@@ -500,15 +503,15 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
channel = layer->channel;
if (layer->unk_0A.s.bit_2 == 1) {
- attrs->reverb = channel->reverb;
+ attrs->targetReverbVol = channel->targetReverbVol;
} else {
- attrs->reverb = layer->unk_09;
+ attrs->targetReverbVol = layer->targetReverbVol;
}
- if (layer->unk_08 == 0x80) {
- attrs->unk_3 = channel->unk_10;
+ if (layer->surroundEffectIndex == 0x80) {
+ attrs->surroundEffectIndex = channel->surroundEffectIndex;
} else {
- attrs->unk_3 = layer->unk_08;
+ attrs->surroundEffectIndex = layer->surroundEffectIndex;
}
if (layer->unk_0A.s.bit_9 == 1) {
@@ -526,20 +529,20 @@ void AudioPlayback_SeqLayerDecayRelease(SequenceLayer* layer, s32 target) {
attrs->filter = attrs->filterBuf;
}
- attrs->unk_6 = channel->unk_20;
- attrs->unk_4 = channel->unk_0F;
+ attrs->combFilterGain = channel->combFilterGain;
+ attrs->combFilterSize = channel->combFilterSize;
if (channel->seqPlayer->muted && (channel->muteFlags & MUTE_FLAGS_3)) {
- note->noteSubEu.bitField0.finished = true;
+ note->sampleState.bitField0.finished = true;
}
- if (layer->stereo.asByte == 0) {
- attrs->stereo = channel->stereo;
+ if (layer->stereoData.asByte == 0) {
+ attrs->stereoData = channel->stereoData;
} else {
- attrs->stereo = layer->stereo;
+ attrs->stereoData = layer->stereoData;
}
note->playbackState.priority = channel->someOtherPriority;
} else {
- attrs->stereo = layer->stereo;
+ attrs->stereoData = layer->stereoData;
note->playbackState.priority = 1;
}
@@ -620,7 +623,7 @@ s32 AudioPlayback_BuildSyntheticWave(Note* note, SequenceLayer* layer, s32 waveI
// Save the pointer to the synthethic wave
// waveId index starts at 128, there are WAVE_SAMPLE_COUNT samples to read from
- note->noteSubEu.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT];
+ note->sampleState.waveSampleAddr = &gWaveSamples[waveId - 128][harmonicIndex * WAVE_SAMPLE_COUNT];
return harmonicIndex;
}
@@ -638,7 +641,7 @@ void AudioPlayback_InitSyntheticWave(Note* note, SequenceLayer* layer) {
curHarmonicIndex = AudioPlayback_BuildSyntheticWave(note, layer, waveId);
if (curHarmonicIndex != prevHarmonicIndex) {
- note->noteSubEu.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex;
+ note->sampleState.harmonicIndexCurAndPrev = (curHarmonicIndex << 2) + prevHarmonicIndex;
}
}
@@ -808,7 +811,7 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) {
s16 instId;
SequenceChannel* channel = layer->channel;
NotePlaybackState* playbackState = ¬e->playbackState;
- NoteSubEu* noteSubEu = ¬e->noteSubEu;
+ NoteSampleState* noteSampleState = ¬e->sampleState;
playbackState->prevParentLayer = NO_LAYER;
playbackState->parentLayer = layer;
@@ -825,28 +828,28 @@ void AudioPlayback_NoteInitForLayer(Note* note, SequenceLayer* layer) {
if (instId == 0xFF) {
instId = channel->instOrWave;
}
- noteSubEu->tunedSample = layer->tunedSample;
+ noteSampleState->tunedSample = layer->tunedSample;
if (instId >= 0x80 && instId < 0xC0) {
- noteSubEu->bitField1.isSyntheticWave = true;
+ noteSampleState->bitField1.isSyntheticWave = true;
} else {
- noteSubEu->bitField1.isSyntheticWave = false;
+ noteSampleState->bitField1.isSyntheticWave = false;
}
- if (noteSubEu->bitField1.isSyntheticWave) {
+ if (noteSampleState->bitField1.isSyntheticWave) {
AudioPlayback_BuildSyntheticWave(note, layer, instId);
} else if (channel->startSamplePos == 1) {
- playbackState->startSamplePos = noteSubEu->tunedSample->sample->loop->start;
+ playbackState->startSamplePos = noteSampleState->tunedSample->sample->loop->start;
} else {
playbackState->startSamplePos = channel->startSamplePos;
- if (playbackState->startSamplePos >= noteSubEu->tunedSample->sample->loop->end) {
+ if (playbackState->startSamplePos >= noteSampleState->tunedSample->sample->loop->loopEnd) {
playbackState->startSamplePos = 0;
}
}
playbackState->fontId = channel->fontId;
playbackState->stereoHeadsetEffects = channel->stereoHeadsetEffects;
- noteSubEu->bitField1.reverbIndex = channel->reverbIndex & 3;
+ noteSampleState->bitField1.reverbIndex = channel->reverbIndex & 3;
}
void func_801963E8(Note* note, SequenceLayer* layer) {
@@ -987,7 +990,7 @@ void AudioPlayback_NoteInitAll(void) {
for (i = 0; i < gAudioContext.numNotes; i++) {
note = &gAudioContext.notes[i];
- note->noteSubEu = gZeroNoteSub;
+ note->sampleState = gZeroedSampleState;
note->playbackState.priority = 0;
note->playbackState.status = PLAYBACK_STATUS_0;
note->playbackState.parentLayer = NO_LAYER;
@@ -1002,7 +1005,8 @@ void AudioPlayback_NoteInitAll(void) {
note->playbackState.portamento.speed = 0;
note->playbackState.stereoHeadsetEffects = false;
note->playbackState.startSamplePos = 0;
- note->synthesisState.synthesisBuffers = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x2E0);
- note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, 0x10);
+ note->synthesisState.synthesisBuffers =
+ AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, sizeof(NoteSynthesisBuffers));
+ note->playbackState.attributes.filterBuf = AudioHeap_AllocDmaMemory(&gAudioContext.miscPool, FILTER_SIZE);
}
}
diff --git a/src/code/audio/audio_seqplayer.c b/src/code/audio/audio_seqplayer.c
index a8573e33d..bc5115f8f 100644
--- a/src/code/audio/audio_seqplayer.c
+++ b/src/code/audio/audio_seqplayer.c
@@ -282,17 +282,17 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->transposition = 0;
channel->largeNotes = false;
channel->bookOffset = 0;
- channel->stereo.asByte = 0;
+ channel->stereoData.asByte = 0;
channel->changes.asByte = 0xFF;
channel->scriptState.depth = 0;
channel->newPan = 0x40;
channel->panChannelWeight = 0x80;
- channel->unk_10 = 0xFF;
+ channel->surroundEffectIndex = 0xFF;
channel->velocityRandomVariance = 0;
channel->gateTimeRandomVariance = 0;
channel->noteUnused = NULL;
channel->reverbIndex = 0;
- channel->reverb = 0;
+ channel->targetReverbVol = 0;
channel->gain = 0;
channel->notePriority = 3;
channel->someOtherPriority = 1;
@@ -308,8 +308,8 @@ void AudioSeq_InitSequenceChannel(SequenceChannel* channel) {
channel->vibrato.vibratoExtentChangeDelay = 0;
channel->vibrato.vibratoDelay = 0;
channel->filter = NULL;
- channel->unk_20 = 0;
- channel->unk_0F = 0;
+ channel->combFilterGain = 0;
+ channel->combFilterSize = 0;
channel->volume = 1.0f;
channel->volumeScale = 1.0f;
channel->freqScale = 1.0f;
@@ -345,7 +345,7 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) {
layer->channel = channel;
layer->adsr = channel->adsr;
layer->adsr.decayIndex = 0;
- layer->unk_09 = channel->reverb;
+ layer->targetReverbVol = channel->targetReverbVol;
layer->enabled = true;
layer->finished = false;
layer->stopSomething = false;
@@ -355,8 +355,8 @@ s32 AudioSeq_SeqChannelSetLayer(SequenceChannel* channel, s32 layerIndex) {
layer->bit1 = false;
layer->notePropertiesNeedInit = false;
layer->gateTime = 0x80;
- layer->unk_08 = 0x80;
- layer->stereo.asByte = 0;
+ layer->surroundEffectIndex = 0x80;
+ layer->stereoData.asByte = 0;
layer->portamento.mode = PORTAMENTO_MODE_OFF;
layer->scriptState.depth = 0;
layer->pan = 0x40;
@@ -782,7 +782,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
break;
case 0xCD: // layer: stereo effects
- layer->stereo.asByte = AudioSeq_ScriptReadU8(state);
+ layer->stereoData.asByte = AudioSeq_ScriptReadU8(state);
break;
case 0xCE: // layer: bend pitch
@@ -796,7 +796,7 @@ s32 AudioSeq_SeqLayerProcessScriptStep2(SequenceLayer* layer) {
break;
case 0xF1: // layer:
- layer->unk_08 = AudioSeq_ScriptReadU8(state);
+ layer->surroundEffectIndex = AudioSeq_ScriptReadU8(state);
break;
default:
@@ -991,13 +991,14 @@ s32 AudioSeq_SeqLayerProcessScriptStep4(SequenceLayer* layer, s32 cmd) {
if (layer->delay == 0) {
if (layer->tunedSample != NULL) {
- time = layer->tunedSample->sample->loop->end;
+ time = layer->tunedSample->sample->loop->loopEnd;
} else {
time = 0.0f;
}
time *= seqPlayer->tempo;
time *= gAudioContext.unk_2870;
time /= layer->freqScale;
+ //! FAKE:
if (1) {}
if (time > 0x7FFE) {
time = 0x7FFE;
@@ -1416,9 +1417,9 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->vibrato.vibratoDelay = cmd * 16;
break;
- case 0xD4: // channel: set reverb
+ case 0xD4: // channel: set reverb volume
cmd = (u8)cmdArgs[0];
- channel->reverb = cmd;
+ channel->targetReverbVol = cmd;
break;
case 0xC6: // channel: set soundFont
@@ -1491,7 +1492,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
} else {
channel->stereoHeadsetEffects = false;
}
- channel->stereo.asByte = cmd & 0x7F;
+ channel->stereoData.asByte = cmd & 0x7F;
break;
case 0xD1: // channel: set note allocation policy
@@ -1537,7 +1538,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
data += 4;
channel->newPan = data[-3];
channel->panChannelWeight = data[-2];
- channel->reverb = data[-1];
+ channel->targetReverbVol = data[-1];
channel->reverbIndex = data[0];
//! @bug: Not marking reverb state as changed
channel->changes.s.pan = true;
@@ -1551,7 +1552,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->transposition = (s8)AudioSeq_ScriptReadU8(scriptState);
channel->newPan = AudioSeq_ScriptReadU8(scriptState);
channel->panChannelWeight = AudioSeq_ScriptReadU8(scriptState);
- channel->reverb = AudioSeq_ScriptReadU8(scriptState);
+ channel->targetReverbVol = AudioSeq_ScriptReadU8(scriptState);
channel->reverbIndex = AudioSeq_ScriptReadU8(scriptState);
//! @bug: Not marking reverb state as changed
channel->changes.s.pan = true;
@@ -1569,8 +1570,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
channel->adsr.sustain = 0;
channel->velocityRandomVariance = 0;
channel->gateTimeRandomVariance = 0;
- channel->unk_0F = 0;
- channel->unk_20 = 0;
+ channel->combFilterSize = 0;
+ channel->combFilterGain = 0;
channel->bookOffset = 0;
channel->startSamplePos = 0;
channel->unk_E0 = 0;
@@ -1651,8 +1652,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xBB: // channel:
- channel->unk_0F = cmdArgs[0];
- channel->unk_20 = cmdArgs[1];
+ channel->combFilterSize = cmdArgs[0];
+ channel->combFilterGain = cmdArgs[1];
break;
case 0xBC: // channel: add large
@@ -1667,8 +1668,8 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
if (cmdArgs[0] < 5) {
if (1) {}
if (gAudioContext.unk_29A8[cmdArgs[0]] != NULL) {
- D_80208E6C = gAudioContext.unk_29A8[cmdArgs[0]];
- scriptState->value = D_80208E6C(scriptState->value, channel);
+ gCustomAudioSeqFunction = gAudioContext.unk_29A8[cmdArgs[0]];
+ scriptState->value = gCustomAudioSeqFunction(scriptState->value, channel);
}
}
break;
@@ -1693,7 +1694,7 @@ void AudioSeq_SequenceChannelProcessScript(SequenceChannel* channel) {
break;
case 0xA4: // channel:
- channel->unk_10 = cmdArgs[0];
+ channel->surroundEffectIndex = cmdArgs[0];
break;
case 0xA5: // channel:
@@ -2197,7 +2198,7 @@ void AudioSeq_ProcessSequences(s32 arg0) {
SequencePlayer* seqPlayer;
u32 i;
- gAudioContext.noteSubEuOffset =
+ gAudioContext.sampleStateOffset =
(gAudioContext.audioBufferParameters.updatesPerFrame - arg0 - 1) * gAudioContext.numNotes;
for (i = 0; i < (u32)gAudioContext.audioBufferParameters.numSequencePlayers; i++) {
diff --git a/src/code/audio/audio_synthesis.c b/src/code/audio/audio_synthesis.c
index 51842a33f..17b3ff4be 100644
--- a/src/code/audio/audio_synthesis.c
+++ b/src/code/audio/audio_synthesis.c
@@ -1,137 +1,1698 @@
#include "global.h"
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801877D0.s")
+// DMEM Addresses for the RSP
+#define DMEM_TEMP 0x3B0
+#define DMEM_TEMP2 0x3C0
+#define DMEM_SURROUND_TEMP 0x4B0
+#define DMEM_UNCOMPRESSED_NOTE 0x570
+#define DMEM_HAAS_TEMP 0x5B0
+#define DMEM_COMB_TEMP 0x750 // = DMEM_TEMP + DMEM_2CH_SIZE + a bit more
+#define DMEM_COMPRESSED_ADPCM_DATA 0x930 // = DMEM_LEFT_CH
+#define DMEM_LEFT_CH 0x930
+#define DMEM_RIGHT_CH 0xAD0
+#define DMEM_WET_TEMP 0x3D0
+#define DMEM_WET_SCRATCH 0x710 // = DMEM_WET_TEMP + DMEM_2CH_SIZE
+#define DMEM_WET_LEFT_CH 0xC70
+#define DMEM_WET_RIGHT_CH 0xE10 // = DMEM_WET_LEFT_CH + DMEM_1CH_SIZE
+
+typedef enum {
+ /* 0 */ HAAS_EFFECT_DELAY_NONE,
+ /* 1 */ HAAS_EFFECT_DELAY_LEFT, // Delay left channel so that right channel is heard first
+ /* 2 */ HAAS_EFFECT_DELAY_RIGHT // Delay right channel so that left channel is heard first
+} HaasEffectDelaySide;
+
+Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 arg2, uintptr_t arg3);
+Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb);
+Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb);
+Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex);
+Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf,
+ s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex);
+Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 dmem, s32 flags);
+Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem,
+ s32 resampleFlags);
+Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags);
+Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesToLoad);
+Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 flags, s32 haasEffectDelaySide);
+
+s32 D_801D5FB0 = 0;
+
+u32 sEnvMixerOp = _SHIFTL(A_ENVMIXER, 24, 8);
+
+// Store the left dry channel in a temp space to be delayed to produce the haas effect
+u32 sEnvMixerLeftHaasDmemDests =
+ AUDIO_MK_CMD(DMEM_HAAS_TEMP >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+// Store the right dry channel in a temp space to be delayed to produce the haas effect
+u32 sEnvMixerRightHaasDmemDests =
+ AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_HAAS_TEMP >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+u32 sEnvMixerDefaultDmemDests =
+ AUDIO_MK_CMD(DMEM_LEFT_CH >> 4, DMEM_RIGHT_CH >> 4, DMEM_WET_LEFT_CH >> 4, DMEM_WET_RIGHT_CH >> 4);
+
+// Unused Data
+u16 D_801D5FC4[] = {
+ 0x7FFF, 0xD001, 0x3FFF, 0xF001, 0x5FFF, 0x9001, 0x7FFF, 0x8001,
+};
+
+u8 sNumSamplesPerWavePeriod[] = {
+ WAVE_SAMPLE_COUNT / 1, // 1st harmonic
+ WAVE_SAMPLE_COUNT / 2, // 2nd harmonic
+ WAVE_SAMPLE_COUNT / 4, // 4th harmonic
+ WAVE_SAMPLE_COUNT / 8, // 8th harmonic
+};
+
+/**
+ * Add a collection of s16-samples as a single entry to the reverb buffer
+ */
+void AudioSynth_AddReverbBufferEntry(s32 numSamples, s32 updateIndex, s32 reverbIndex) {
+ SynthesisReverb* reverb;
+ ReverbBufferEntry* entry;
+ s32 extraSamples;
+ s32 numSamplesAfterDownsampling;
+ s32 reverbBufPos;
+ s32 temp_t2;
+ s32 temp_t4;
+ s32 count1;
+ s32 count2;
+ s32 nextReverbSubBufPos;
+
+ reverb = &gAudioContext.synthesisReverbs[reverbIndex];
+ entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ numSamplesAfterDownsampling = numSamples / gAudioContext.synthesisReverbs[reverbIndex].downsampleRate;
+
+ // Apply resampling effect
+ if (gAudioContext.synthesisReverbs[reverbIndex].resampleEffectOn) {
+ if (reverb->downsampleRate == 1) {
+ count1 = 0;
+ count2 = 0;
+
+ numSamplesAfterDownsampling += reverb->resampleEffectExtraSamples;
+
+ entry->saveResampleNumSamples = numSamplesAfterDownsampling;
+ entry->loadResamplePitch = ((u16)numSamplesAfterDownsampling << 0xF) / numSamples;
+ entry->saveResamplePitch = (numSamples << 0xF) / (u16)numSamplesAfterDownsampling;
+
+ while (true) {
+ temp_t2 = (entry->loadResamplePitch * numSamples * 2) + reverb->resampleEffectLoadUnk;
+ temp_t4 = temp_t2 >> 0x10;
+
+ if ((temp_t4 != numSamplesAfterDownsampling) && (count1 == 0)) {
+ entry->loadResamplePitch =
+ ((numSamplesAfterDownsampling << 0x10) - reverb->resampleEffectLoadUnk) / (numSamples * 2);
+ count1++;
+ } else {
+ count1++;
+ if (temp_t4 > numSamplesAfterDownsampling) {
+ entry->loadResamplePitch--;
+ } else if (temp_t4 < numSamplesAfterDownsampling) {
+ entry->loadResamplePitch++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ reverb->resampleEffectLoadUnk = temp_t2 & 0xFFFF;
+
+ while (true) {
+ temp_t2 = (entry->saveResamplePitch * numSamplesAfterDownsampling * 2) + reverb->resampleEffectSaveUnk;
+ temp_t4 = temp_t2 >> 0x10;
+
+ if ((temp_t4 != numSamples) && (count2 == 0)) {
+ entry->saveResamplePitch =
+ ((numSamples << 0x10) - reverb->resampleEffectSaveUnk) / (numSamplesAfterDownsampling * 2);
+ count2++;
+ } else {
+ count2++;
+ if (temp_t4 > numSamples) {
+ entry->saveResamplePitch--;
+ } else if (temp_t4 < numSamples) {
+ entry->saveResamplePitch++;
+ } else {
+ break;
+ }
+ }
+ }
+
+ reverb->resampleEffectSaveUnk = temp_t2 & 0xFFFF;
+ }
+ }
+
+ extraSamples = (reverb->nextReverbBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples;
+ reverbBufPos = reverb->nextReverbBufPos;
+
+ // Add a reverb entry
+ if (extraSamples < 0) {
+ entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE;
+ entry->wrappedSize = 0;
+ entry->startPos = reverb->nextReverbBufPos;
+ reverb->nextReverbBufPos += numSamplesAfterDownsampling;
+ } else {
+ // End of the buffer is reached. Loop back around
+ entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE;
+ entry->wrappedSize = extraSamples * SAMPLE_SIZE;
+ entry->startPos = reverb->nextReverbBufPos;
+ reverb->nextReverbBufPos = extraSamples;
+ }
+
+ entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling;
+ entry->numSamples = numSamples;
+
+ // Add a sub-reverb entry
+ if (reverb->subDelay != 0) {
+ nextReverbSubBufPos = reverb->subDelay + reverbBufPos;
+ if (nextReverbSubBufPos >= reverb->delayNumSamples) {
+ nextReverbSubBufPos -= reverb->delayNumSamples;
+ }
+
+ entry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+ numSamplesAfterDownsampling = numSamples / reverb->downsampleRate;
+ extraSamples = (nextReverbSubBufPos + numSamplesAfterDownsampling) - reverb->delayNumSamples;
+
+ if (extraSamples < 0) {
+ entry->size = numSamplesAfterDownsampling * SAMPLE_SIZE;
+ entry->wrappedSize = 0;
+ entry->startPos = nextReverbSubBufPos;
+ } else {
+ // End of the buffer is reached. Loop back around
+ entry->size = (numSamplesAfterDownsampling - extraSamples) * SAMPLE_SIZE;
+ entry->wrappedSize = extraSamples * SAMPLE_SIZE;
+ entry->startPos = nextReverbSubBufPos;
+ }
+
+ entry->numSamplesAfterDownsampling = numSamplesAfterDownsampling;
+ entry->numSamples = numSamples;
+ }
+}
+
+/**
+ * Sync the sample states between the notes and the list
+ */
+void AudioSynth_SyncSampleStates(s32 updateIndex) {
+ NoteSampleState* noteSampleState;
+ NoteSampleState* sampleState;
+ s32 sampleStateBaseIndex;
+ s32 i;
+
+ sampleStateBaseIndex = gAudioContext.numNotes * updateIndex;
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ noteSampleState = &gAudioContext.notes[i].sampleState;
+ sampleState = &gAudioContext.sampleStateList[sampleStateBaseIndex + i];
+ if (noteSampleState->bitField0.enabled) {
+ noteSampleState->bitField0.needsInit = false;
+ } else {
+ sampleState->bitField0.enabled = false;
+ }
+
+ noteSampleState->harmonicIndexCurAndPrev = 0;
+ }
+}
+
+Acmd* AudioSynth_Update(Acmd* abiCmdStart, s32* numAbiCmds, s16* aiBufStart, s32 numSamplesPerFrame) {
+ s32 numSamplesPerUpdate;
+ s16* curAiBufPos;
+ Acmd* curCmd = abiCmdStart;
+ s32 reverseUpdateIndex;
+ s32 reverbIndex;
+ SynthesisReverb* reverb;
+
+ for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0;
+ reverseUpdateIndex--) {
+ AudioSeq_ProcessSequences(reverseUpdateIndex - 1);
+ AudioSynth_SyncSampleStates(gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex);
+ }
+
+ curAiBufPos = aiBufStart;
+ gAudioContext.adpcmCodeBook = NULL;
+
+ // Process/Update all samples multiple times in a single frame
+ for (reverseUpdateIndex = gAudioContext.audioBufferParameters.updatesPerFrame; reverseUpdateIndex > 0;
+ reverseUpdateIndex--) {
+ if (reverseUpdateIndex == 1) {
+ // Final Update
+ numSamplesPerUpdate = numSamplesPerFrame;
+ } else if ((numSamplesPerFrame / reverseUpdateIndex) >=
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMax) {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMax;
+ } else if ((numSamplesPerFrame / reverseUpdateIndex) <=
+ gAudioContext.audioBufferParameters.numSamplesPerUpdateMin) {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdateMin;
+ } else {
+ numSamplesPerUpdate = gAudioContext.audioBufferParameters.numSamplesPerUpdate;
+ }
+
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ if (gAudioContext.synthesisReverbs[reverbIndex].useReverb) {
+ AudioSynth_AddReverbBufferEntry(
+ numSamplesPerUpdate, gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex,
+ reverbIndex);
+ }
+ }
+
+ curCmd = AudioSynth_ProcessSamples(curAiBufPos, numSamplesPerUpdate, curCmd,
+ gAudioContext.audioBufferParameters.updatesPerFrame - reverseUpdateIndex);
+ numSamplesPerFrame -= numSamplesPerUpdate;
+ curAiBufPos += numSamplesPerUpdate * SAMPLE_SIZE;
+ }
+
+ // Update reverb frame info
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ if (gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore != 0) {
+ gAudioContext.synthesisReverbs[reverbIndex].framesToIgnore--;
+ }
+ gAudioContext.synthesisReverbs[reverbIndex].curFrame ^= 1;
+ }
+
+ *numAbiCmds = curCmd - abiCmdStart;
+ return curCmd;
+}
+
+void AudioSynth_DisableSampleStates(s32 updateIndex, s32 noteIndex) {
+ NoteSampleState* sampleState;
+ s32 i;
+
+ for (i = updateIndex + 1; i < gAudioContext.audioBufferParameters.updatesPerFrame; i++) {
+ sampleState = &gAudioContext.sampleStateList[(gAudioContext.numNotes * i) + noteIndex];
+ if (sampleState->bitField0.needsInit) {
+ break;
+ }
+ sampleState->bitField0.enabled = false;
+ }
+}
+
+/**
+ * Load reverb samples from a different reverb index
+ */
+Acmd* AudioSynth_LoadMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb);
+ }
+ return cmd;
+}
+
+/**
+ * Save reverb samples from a different reverb index
+ */
+Acmd* AudioSynth_SaveMixedReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_TEMP + entry->size, 0, entry->wrappedSize, reverb);
+ }
+ return cmd;
+}
+
+void AudioSynth_Noop1(void) {
+}
+
+void AudioSynth_ClearBuffer(Acmd* cmd, s32 dmem, s32 size) {
+ aClearBuffer(cmd, dmem, size);
+}
+
+void AudioSynth_Noop2(void) {
+}
+
+void AudioSynth_Noop3(void) {
+}
+
+void AudioSynth_Noop4(void) {
+}
+
+void AudioSynth_Mix(Acmd* cmd, size_t size, s32 gain, s32 dmemIn, s32 dmemOut) {
+ aMix(cmd, size, gain, dmemIn, dmemOut);
+}
+
+void AudioSynth_Noop5(void) {
+}
+
+void AudioSynth_Noop6(void) {
+}
+
+void AudioSynth_Noop7(void) {
+}
+
+void AudioSynth_SetBuffer(Acmd* cmd, s32 flags, s32 dmemIn, s32 dmemOut, size_t size) {
+ aSetBuffer(cmd, flags, dmemIn, dmemOut, size);
+}
+
+void AudioSynth_Noop8(void) {
+}
+
+void AudioSynth_Noop9(void) {
+}
+
+void AudioSynth_DMemMove(Acmd* cmd, s32 dmemIn, s32 dmemOut, size_t size) {
+ // aDMEMMove(cmd, dmemIn, dmemOut, size);
+ cmd->words.w0 = _SHIFTL(A_DMEMMOVE, 24, 8) | _SHIFTL(dmemIn, 0, 24);
+ cmd->words.w1 = _SHIFTL(dmemOut, 16, 16) | _SHIFTL(size, 0, 16);
+}
+
+void AudioSynth_Noop10(void) {
+}
+
+void AudioSynth_Noop11(void) {
+}
+
+void AudioSynth_Noop12(void) {
+}
+
+void AudioSynth_Noop13(void) {
+}
+
+void AudioSynth_InterL(Acmd* cmd, s32 dmemIn, s32 dmemOut, s32 numSamples) {
+ // aInterl(cmd, dmemIn, dmemOut, numSamples);
+ cmd->words.w0 = _SHIFTL(A_INTERL, 24, 8) | _SHIFTL(numSamples, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
+}
+
+void AudioSynth_EnvSetup1(Acmd* cmd, s32 reverbVol, s32 rampReverb, s32 rampLeft, s32 rampRight) {
+ aEnvSetup1(cmd, reverbVol, rampReverb, rampLeft, rampRight);
+}
+
+void AudioSynth_Noop14(void) {
+}
+
+void AudioSynth_LoadBuffer(Acmd* cmd, s32 dmemDest, s32 size, void* addrSrc) {
+ aLoadBuffer(cmd, addrSrc, dmemDest, size);
+}
+
+void AudioSynth_SaveBuffer(Acmd* cmd, s32 dmemSrc, s32 size, void* addrDest) {
+ aSaveBuffer(cmd, dmemSrc, addrDest, size);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187B64.s")
+void AudioSynth_EnvSetup2(Acmd* cmd, s32 volLeft, s32 volRight) {
+ // aEnvSetup2(cmd, volLeft, volRight);
+ cmd->words.w0 = _SHIFTL(A_ENVSETUP2, 24, 8);
+ cmd->words.w1 = _SHIFTL(volLeft, 16, 16) | _SHIFTL(volRight, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187BEC.s")
+void AudioSynth_Noop15(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187DE8.s")
+void AudioSynth_Noop16(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187E58.s")
+void AudioSynth_Noop17(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187F00.s")
+void AudioSynth_S8Dec(Acmd* cmd, s32 flags, s16* state) {
+ aS8Dec(cmd, flags, state);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FA8.s")
+void AudioSynth_HiLoGain(Acmd* cmd, s32 gain, s32 dmemIn, s32 dmemOut, s32 size) {
+ // aHiLoGain(cmd, gain, size, dmemIn, dmemOut);
+ cmd->words.w0 = _SHIFTL(A_HILOGAIN, 24, 8) | _SHIFTL(gain, 16, 8) | _SHIFTL(size, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmemIn, 16, 16) | _SHIFTL(dmemOut, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FB0.s")
+// Remnant of OoT
+void AudioSynth_UnkCmd19(Acmd* cmd, s32 dmem1, s32 dmem2, s32 size, s32 arg4) {
+ cmd->words.w0 = _SHIFTL(A_SPNOOP, 24, 8) | _SHIFTL(arg4, 16, 8) | _SHIFTL(size, 0, 16);
+ cmd->words.w1 = _SHIFTL(dmem1, 16, 16) | _SHIFTL(dmem2, 0, 16);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD0.s")
+void AudioSynth_Noop18(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FD8.s")
+void AudioSynth_Noop19(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE0.s")
+void AudioSynth_Noop20(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80187FE8.s")
+void AudioSynth_Noop21(void) {
+}
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018801C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188024.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018802C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188034.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188068.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188070.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188078.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880AC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880B4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880BC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801880E8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018811C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188124.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018814C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188174.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188190.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188198.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881A8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881C4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801881F8.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188224.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018822C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188234.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018823C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188244.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018824C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188254.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018825C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188264.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188288.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801882A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188304.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801884A0.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188698.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018883C.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801888E4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_801889A4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188A50.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188AFC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188C48.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188CB4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D20.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D28.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188D68.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188DDC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80188FBC.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189064.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_80189620.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A4B4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A768.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018A808.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018ACC4.s")
-
-#pragma GLOBAL_ASM("asm/non_matchings/code/audio_synthesis/func_8018AE34.s")
+void AudioSynth_Noop22(void) {
+}
+
+void AudioSynth_Noop23(void) {
+}
+
+void AudioSynth_Noop24(void) {
+}
+
+void AudioSynth_Noop25(void) {
+}
+
+void AudioSynth_LoadFilterBuffer(Acmd* cmd, s32 flags, s32 buf, s16* addr) {
+ aFilter(cmd, flags, buf, addr);
+}
+
+void AudioSynth_LoadFilterSize(Acmd* cmd, size_t size, s16* addr) {
+ aFilter(cmd, 2, size, addr);
+}
+
+/**
+ * Leak some audio from the left reverb channel into the right reverb channel and vice versa (pan)
+ */
+Acmd* AudioSynth_LeakReverb(Acmd* cmd, SynthesisReverb* reverb) {
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_SCRATCH, DMEM_1CH_SIZE);
+ aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakRtl, DMEM_WET_RIGHT_CH, DMEM_WET_LEFT_CH);
+ aMix(cmd++, DMEM_1CH_SIZE >> 4, reverb->leakLtr, DMEM_WET_SCRATCH, DMEM_WET_RIGHT_CH);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadDownsampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE;
+ s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size);
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE),
+ DMEM_1CH_SIZE, reverb);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP + wrappedOffsetSize, 0,
+ DMEM_1CH_SIZE - wrappedOffsetSize, reverb);
+ }
+
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->leftLoadResampleBuf);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH,
+ numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, reverb->downsamplePitch, reverb->rightLoadResampleBuf);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveResampledReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 numSamples = entry->numSamples;
+ u32 size = numSamples * SAMPLE_SIZE;
+
+ // Left Resample
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, size);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->leftSaveResampleBuf);
+
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size,
+ &reverb->leftReverbBuf[entry->startPos]);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize,
+ reverb->leftReverbBuf);
+ }
+
+ // Right Resample
+ aDMEMMove(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_TEMP, size);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP, DMEM_WET_SCRATCH, entry->saveResampleNumSamples * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->saveResamplePitch, reverb->rightSaveResampleBuf);
+
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_SCRATCH, entry->size,
+ &reverb->rightReverbBuf[entry->startPos]);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_SCRATCH, entry->wrappedSize,
+ reverb->rightReverbBuf);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadResampledReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s16 offsetSize = (entry->startPos & 7) * SAMPLE_SIZE;
+ s16 wrappedOffsetSize = ALIGN16(offsetSize + entry->size);
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_TEMP, entry->startPos - (offsetSize / (s32)SAMPLE_SIZE),
+ DMEM_1CH_SIZE, reverb);
+
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, wrappedOffsetSize + DMEM_WET_TEMP, 0,
+ DMEM_1CH_SIZE - wrappedOffsetSize, reverb);
+ }
+
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + offsetSize, DMEM_WET_LEFT_CH, numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->leftLoadResampleBuf);
+ aSetBuffer(cmd++, 0, DMEM_WET_TEMP + DMEM_1CH_SIZE + offsetSize, DMEM_WET_RIGHT_CH,
+ numSamplesPerUpdate * SAMPLE_SIZE);
+ aResample(cmd++, reverb->resampleFlags, entry->loadResamplePitch, reverb->rightLoadResampleBuf);
+
+ return cmd;
+}
+
+/**
+ * Apply a filter (convolution) to each reverb channel.
+ */
+Acmd* AudioSynth_FilterReverb(Acmd* cmd, s32 size, SynthesisReverb* reverb) {
+ if (reverb->filterLeft != NULL) {
+ aFilter(cmd++, 2, size, reverb->filterLeft);
+ aFilter(cmd++, reverb->resampleFlags, DMEM_WET_LEFT_CH, reverb->filterLeftState);
+ }
+
+ if (reverb->filterRight != NULL) {
+ aFilter(cmd++, 2, size, reverb->filterRight);
+ aFilter(cmd++, reverb->resampleFlags, DMEM_WET_RIGHT_CH, reverb->filterRightState);
+ }
+
+ return cmd;
+}
+
+/**
+ * Mix in reverb from a different reverb index
+ */
+Acmd* AudioSynth_MixOtherReverbIndex(Acmd* cmd, SynthesisReverb* reverb, s32 updateIndex) {
+ SynthesisReverb* mixReverb;
+
+ if (reverb->mixReverbIndex >= gAudioContext.numSynthesisReverbs) {
+ return cmd;
+ }
+
+ mixReverb = &gAudioContext.synthesisReverbs[reverb->mixReverbIndex];
+ if (mixReverb->downsampleRate == 1) {
+ cmd = AudioSynth_LoadMixedReverbSamples(cmd, mixReverb, updateIndex);
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->mixReverbStrength, DMEM_WET_LEFT_CH, DMEM_WET_TEMP);
+ cmd = AudioSynth_SaveMixedReverbSamples(cmd, mixReverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadDefaultReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadSubReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb);
+ if (subEntry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd =
+ AudioSynth_LoadReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveResampledReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 size, uintptr_t startAddr) {
+ s32 startAddrAlignDropped;
+ u32 endAddr;
+ s32 endAddrAlignDropped;
+
+ endAddr = startAddr + size;
+
+ endAddrAlignDropped = endAddr & 0xF;
+ if (endAddrAlignDropped != 0) {
+ aLoadBuffer(cmd++, (endAddr - endAddrAlignDropped), DMEM_TEMP, 0x10);
+ aDMEMMove(cmd++, dmem, DMEM_TEMP2, size);
+ aDMEMMove(cmd++, DMEM_TEMP + endAddrAlignDropped, size + DMEM_TEMP2, 0x10 - endAddrAlignDropped);
+
+ size += (0x10 - endAddrAlignDropped);
+ dmem = DMEM_TEMP2;
+ }
+
+ startAddrAlignDropped = startAddr & 0xF;
+ if (startAddrAlignDropped != 0) {
+ aLoadBuffer(cmd++, startAddr - startAddrAlignDropped, DMEM_TEMP, 0x10);
+ aDMEMMove(cmd++, dmem, startAddrAlignDropped + DMEM_TEMP, size);
+
+ size += startAddrAlignDropped;
+ dmem = DMEM_TEMP;
+ }
+
+ aSaveBuffer(cmd++, dmem, startAddr - startAddrAlignDropped, size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) {
+ aLoadBuffer(cmd++, &reverb->leftReverbBuf[startPos], dmem, size);
+ aLoadBuffer(cmd++, &reverb->rightReverbBuf[startPos], dmem + DMEM_1CH_SIZE, size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveReverbSamplesImpl(Acmd* cmd, u16 dmem, u16 startPos, s32 size, SynthesisReverb* reverb) {
+ aSaveBuffer(cmd++, dmem, &reverb->leftReverbBuf[startPos], size);
+ aSaveBuffer(cmd++, dmem + DMEM_1CH_SIZE, &reverb->rightReverbBuf[startPos], size);
+
+ return cmd;
+}
+
+void AudioSynth_Noop26(void) {
+}
+
+Acmd* AudioSynth_LoadSubReverbSamplesWithoutDownsample(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb,
+ s16 updateIndex) {
+ if (reverb->downsampleRate == 1) {
+ cmd = AudioSynth_LoadSubReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadReverbSamples(Acmd* cmd, s32 numSamplesPerUpdate, SynthesisReverb* reverb, s16 updateIndex) {
+ if (reverb->downsampleRate == 1) {
+ if (reverb->resampleEffectOn) {
+ cmd = AudioSynth_LoadResampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ } else {
+ cmd = AudioSynth_LoadDefaultReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+ } else {
+ cmd = AudioSynth_LoadDownsampledReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* entry = &reverb->bufEntry[reverb->curFrame][updateIndex];
+ s32 downsampleRate;
+ s32 numSamples;
+
+ if (reverb->downsampleRate == 1) {
+ if (reverb->resampleEffectOn) {
+ cmd = AudioSynth_SaveResampledReverbSamples(cmd, reverb, updateIndex);
+ } else {
+ // Put the oldest samples in the ring buffer into the wet channels
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->startPos, entry->size, reverb);
+ if (entry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + entry->size, 0, entry->wrappedSize,
+ reverb);
+ }
+ }
+ } else {
+ //! FAKE:
+ if (1) {}
+
+ downsampleRate = reverb->downsampleRate;
+ numSamples = 13 * SAMPLES_PER_FRAME;
+
+ while (downsampleRate >= 2) {
+ aInterl(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH, numSamples);
+ aInterl(cmd++, DMEM_WET_RIGHT_CH, DMEM_WET_RIGHT_CH, numSamples);
+ downsampleRate >>= 1;
+ numSamples >>= 1;
+ }
+
+ if (entry->size != 0) {
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, entry->size,
+ &reverb->leftReverbBuf[entry->startPos]);
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, DMEM_WET_RIGHT_CH, entry->size,
+ &reverb->rightReverbBuf[entry->startPos]);
+ }
+
+ if (entry->wrappedSize != 0) {
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_LEFT_CH, entry->wrappedSize,
+ reverb->leftReverbBuf);
+ cmd = AudioSynth_SaveResampledReverbSamplesImpl(cmd, entry->size + DMEM_WET_RIGHT_CH, entry->wrappedSize,
+ reverb->rightReverbBuf);
+ }
+ }
+
+ reverb->resampleFlags = 0;
+
+ return cmd;
+}
+
+Acmd* AudioSynth_SaveSubReverbSamples(Acmd* cmd, SynthesisReverb* reverb, s16 updateIndex) {
+ ReverbBufferEntry* subEntry = &reverb->subBufEntry[reverb->curFrame][updateIndex];
+
+ cmd = AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH, subEntry->startPos, subEntry->size, reverb);
+ if (subEntry->wrappedSize != 0) {
+ // Ring buffer wrapped
+ cmd =
+ AudioSynth_SaveReverbSamplesImpl(cmd, DMEM_WET_LEFT_CH + subEntry->size, 0, subEntry->wrappedSize, reverb);
+ }
+
+ return cmd;
+}
+
+/**
+ * Process all samples embedded in a note. Every sample has numSamplesPerUpdate processed,
+ * and each of those are mixed together into both DMEM_LEFT_CH and DMEM_RIGHT_CH
+ */
+Acmd* AudioSynth_ProcessSamples(s16* aiBuf, s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) {
+ s32 size;
+ u8 noteIndices[0x58];
+ s16 noteCount = 0;
+ s16 reverbIndex;
+ SynthesisReverb* reverb;
+ s32 useReverb;
+ s32 sampleStateOffset = gAudioContext.numNotes * updateIndex;
+ s32 i;
+
+ if (gAudioContext.numSynthesisReverbs == 0) {
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ if (gAudioContext.sampleStateList[sampleStateOffset + i].bitField0.enabled) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ } else {
+ NoteSampleState* sampleState;
+
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i];
+ if (sampleState->bitField0.enabled && (sampleState->bitField1.reverbIndex == reverbIndex)) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ }
+
+ for (i = 0; i < gAudioContext.numNotes; i++) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + i];
+ if (sampleState->bitField0.enabled &&
+ (sampleState->bitField1.reverbIndex >= gAudioContext.numSynthesisReverbs)) {
+ noteIndices[noteCount++] = i;
+ }
+ }
+ }
+
+ aClearBuffer(cmd++, DMEM_LEFT_CH, DMEM_2CH_SIZE);
+
+ i = 0;
+ for (reverbIndex = 0; reverbIndex < gAudioContext.numSynthesisReverbs; reverbIndex++) {
+ s32 subDelay;
+ NoteSampleState* sampleState;
+
+ reverb = &gAudioContext.synthesisReverbs[reverbIndex];
+ useReverb = reverb->useReverb;
+ if (useReverb) {
+
+ // Loads reverb samples from DRAM (ringBuffer) into DMEM (DMEM_WET_LEFT_CH)
+ cmd = AudioSynth_LoadReverbSamples(cmd, numSamplesPerUpdate, reverb, updateIndex);
+
+ // Mixes reverb sample into the main dry channel
+ // reverb->volume is always set to 0x7FFF (audio spec), and DMEM_LEFT_CH is cleared before reverbs.
+ // So this is essentially a DMEMmove from DMEM_WET_LEFT_CH to DMEM_LEFT_CH
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->volume, DMEM_WET_LEFT_CH, DMEM_LEFT_CH);
+
+ subDelay = reverb->subDelay;
+ if (subDelay != 0) {
+ aDMEMMove(cmd++, DMEM_WET_LEFT_CH, DMEM_WET_TEMP, DMEM_2CH_SIZE);
+ }
+
+ // Decays reverb over time. The (+ 0x8000) here is -100%
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->decayRatio + 0x8000, DMEM_WET_LEFT_CH, DMEM_WET_LEFT_CH);
+
+ if (((reverb->leakRtl != 0) || (reverb->leakLtr != 0)) && (gAudioContext.soundMode != SOUNDMODE_MONO)) {
+ cmd = AudioSynth_LeakReverb(cmd, reverb);
+ }
+
+ if (subDelay != 0) {
+ if (reverb->mixReverbIndex != REVERB_INDEX_NONE) {
+ cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex);
+ }
+ cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex);
+ cmd = AudioSynth_LoadSubReverbSamplesWithoutDownsample(cmd, numSamplesPerUpdate, reverb, updateIndex);
+ aMix(cmd++, DMEM_2CH_SIZE >> 4, reverb->subVolume, DMEM_WET_TEMP, DMEM_WET_LEFT_CH);
+ }
+ }
+
+ while (i < noteCount) {
+ sampleState = &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]];
+ if (sampleState->bitField1.reverbIndex != reverbIndex) {
+ break;
+ }
+ cmd = AudioSynth_ProcessSample(noteIndices[i], sampleState,
+ &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf,
+ numSamplesPerUpdate, cmd, updateIndex);
+ i++;
+ }
+
+ if (useReverb) {
+ if ((reverb->filterLeft != NULL) || (reverb->filterRight != NULL)) {
+ cmd = AudioSynth_FilterReverb(cmd, numSamplesPerUpdate * SAMPLE_SIZE, reverb);
+ }
+
+ // Saves the wet channel sample from DMEM (DMEM_WET_LEFT_CH) into (ringBuffer) DRAM for future use
+ if (subDelay != 0) {
+ cmd = AudioSynth_SaveSubReverbSamples(cmd, reverb, updateIndex);
+ } else {
+ if (reverb->mixReverbIndex != REVERB_INDEX_NONE) {
+ cmd = AudioSynth_MixOtherReverbIndex(cmd, reverb, updateIndex);
+ }
+ cmd = AudioSynth_SaveReverbSamples(cmd, reverb, updateIndex);
+ }
+ }
+ }
+
+ while (i < noteCount) {
+ cmd = AudioSynth_ProcessSample(
+ noteIndices[i], &gAudioContext.sampleStateList[sampleStateOffset + noteIndices[i]],
+ &gAudioContext.notes[noteIndices[i]].synthesisState, aiBuf, numSamplesPerUpdate, cmd, updateIndex);
+ i++;
+ }
+
+ size = numSamplesPerUpdate * SAMPLE_SIZE;
+ aInterleave(cmd++, DMEM_TEMP, DMEM_LEFT_CH, DMEM_RIGHT_CH, size);
+
+ if (gCustomAudioSynthFunction != NULL) {
+ cmd = gCustomAudioSynthFunction(cmd, 2 * size, updateIndex);
+ }
+ aSaveBuffer(cmd++, DMEM_TEMP, aiBuf, 2 * size);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ProcessSample(s32 noteIndex, NoteSampleState* sampleState, NoteSynthesisState* synthState, s16* aiBuf,
+ s32 numSamplesPerUpdate, Acmd* cmd, s32 updateIndex) {
+ s32 pad1[2];
+ void* reverbAddrSrc;
+ Sample* sample;
+ AdpcmLoop* loopInfo;
+ s32 numSamplesUntilEnd;
+ s32 numSamplesInThisIteration;
+ s32 sampleFinished;
+ s32 loopToPoint;
+ s32 flags;
+ u16 frequencyFixedPoint;
+ s32 gain;
+ s32 frameIndex;
+ s32 skipBytes;
+ void* combFilterState;
+ s32 numSamplesToDecode;
+ s32 numFirstFrameSamplesToIgnore;
+ u8* sampleAddr;
+ u32 numSamplesToLoadFixedPoint;
+ s32 numSamplesToLoadAdj;
+ s32 numSamplesProcessed;
+ s32 sampleEndPos;
+ s32 numSamplesToProcess;
+ s32 dmemUncompressedAddrOffset2;
+ s32 pad2[3];
+ s32 numSamplesInFirstFrame;
+ s32 numTrailingSamplesToIgnore;
+ s32 pad3[3];
+ s32 frameSize;
+ s32 numFramesToDecode;
+ s32 skipInitialSamples;
+ s32 zeroOffset;
+ u8* samplesToLoadAddr;
+ s32 numParts;
+ s32 curPart;
+ s32 sampleDataChunkAlignPad;
+ s32 haasEffectDelaySide;
+ s32 numSamplesToLoadFirstPart;
+ u16 sampleDmemBeforeResampling;
+ s32 sampleAddrOffset;
+ s32 combFilterDmem;
+ s32 dmemUncompressedAddrOffset1;
+ Note* note;
+ u32 numSamplesToLoad;
+ u16 combFilterSize;
+ u16 combFilterGain;
+ s16* filter;
+ s32 bookOffset = sampleState->bitField1.bookOffset;
+ s32 finished = sampleState->bitField0.finished;
+ s32 sampleDataChunkSize;
+ s16 sampleDataDmemAddr;
+
+ note = &gAudioContext.notes[noteIndex];
+ flags = A_CONTINUE;
+
+ // Initialize the synthesis state
+ if (sampleState->bitField0.needsInit == true) {
+ flags = A_INIT;
+ synthState->atLoopPoint = false;
+ synthState->stopLoop = false;
+ synthState->samplePosInt = note->playbackState.startSamplePos;
+ synthState->samplePosFrac = 0;
+ synthState->curVolLeft = 0;
+ synthState->curVolRight = 0;
+ synthState->prevHaasEffectLeftDelaySize = 0;
+ synthState->prevHaasEffectRightDelaySize = 0;
+ synthState->curReverbVol = sampleState->targetReverbVol;
+ synthState->numParts = 0;
+ synthState->combFilterNeedsInit = true;
+ note->sampleState.bitField0.finished = false;
+ synthState->unk_1F = note->playbackState.unk_80; // Never set, never used
+ finished = false;
+ }
+
+ // Process the sample in either one or two parts
+ numParts = sampleState->bitField1.hasTwoParts + 1;
+
+ // Determine number of samples to load based on numSamplesPerUpdate and relative frequency
+ frequencyFixedPoint = sampleState->frequencyFixedPoint;
+ numSamplesToLoadFixedPoint = (frequencyFixedPoint * numSamplesPerUpdate * 2) + synthState->samplePosFrac;
+ numSamplesToLoad = numSamplesToLoadFixedPoint >> 16;
+
+ if (numSamplesToLoad == 0) {
+ skipBytes = false;
+ }
+
+ synthState->samplePosFrac = numSamplesToLoadFixedPoint & 0xFFFF;
+
+ // Partially-optimized out no-op ifs required for matching. SM64 decomp
+ // makes it clear that this is how it should look.
+ if ((synthState->numParts == 1) && (numParts == 2)) {
+ } else if ((synthState->numParts == 2) && (numParts == 1)) {
+ } else {
+ }
+
+ synthState->numParts = numParts;
+
+ if (sampleState->bitField1.isSyntheticWave) {
+ cmd = AudioSynth_LoadWaveSamples(cmd, sampleState, synthState, numSamplesToLoad);
+ sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + (synthState->samplePosInt * 2);
+ synthState->samplePosInt += numSamplesToLoad;
+ } else {
+ sample = sampleState->tunedSample->sample;
+ loopInfo = sample->loop;
+
+ if (note->playbackState.status != PLAYBACK_STATUS_0) {
+ synthState->stopLoop = true;
+ }
+
+ if ((loopInfo->count == 2) && synthState->stopLoop) {
+ sampleEndPos = loopInfo->sampleEnd;
+ } else {
+ sampleEndPos = loopInfo->loopEnd;
+ }
+
+ sampleAddr = sample->sampleAddr;
+ numSamplesToLoadFirstPart = 0;
+
+ // If the frequency requested is more than double that of the raw sample,
+ // then the sample processing is split into two parts.
+ for (curPart = 0; curPart < numParts; curPart++) {
+ numSamplesProcessed = 0;
+ dmemUncompressedAddrOffset1 = 0;
+
+ // Adjust the number of samples to load only if there are two parts and an odd number of samples
+ if (numParts == 1) {
+ numSamplesToLoadAdj = numSamplesToLoad;
+ } else if (numSamplesToLoad & 1) {
+ // round down for the first part
+ // round up for the second part
+ numSamplesToLoadAdj = (numSamplesToLoad & ~1) + (curPart * 2);
+ } else {
+ numSamplesToLoadAdj = numSamplesToLoad;
+ }
+
+ // Load the ADPCM codeBook
+ if ((sample->codec == CODEC_ADPCM) || (sample->codec == CODEC_SMALL_ADPCM)) {
+ if (gAudioContext.adpcmCodeBook != sample->book->codeBook) {
+ u32 numEntries;
+
+ switch (bookOffset) {
+ case 1:
+ gAudioContext.adpcmCodeBook = &gInvalidAdpcmCodeBook[1];
+ break;
+
+ case 2:
+ case 3:
+ default:
+ gAudioContext.adpcmCodeBook = sample->book->codeBook;
+ break;
+ }
+
+ numEntries = SAMPLES_PER_FRAME * sample->book->order * sample->book->numPredictors;
+ aLoadADPCM(cmd++, numEntries, gAudioContext.adpcmCodeBook);
+ }
+ }
+
+ // Continue processing samples until the number of samples needed to load is reached
+ while (numSamplesProcessed != numSamplesToLoadAdj) {
+ sampleFinished = false;
+ loopToPoint = false;
+ dmemUncompressedAddrOffset2 = 0;
+
+ numFirstFrameSamplesToIgnore = synthState->samplePosInt & 0xF;
+ numSamplesUntilEnd = sampleEndPos - synthState->samplePosInt;
+
+ // Calculate number of samples to process this loop
+ numSamplesToProcess = numSamplesToLoadAdj - numSamplesProcessed;
+
+ if ((numFirstFrameSamplesToIgnore == 0) && !synthState->atLoopPoint) {
+ numFirstFrameSamplesToIgnore = SAMPLES_PER_FRAME;
+ }
+ numSamplesInFirstFrame = SAMPLES_PER_FRAME - numFirstFrameSamplesToIgnore;
+
+ // Determine the number of samples to decode based on whether the end will be reached or not.
+ if (numSamplesToProcess < numSamplesUntilEnd) {
+ // The end will not be reached.
+ numFramesToDecode =
+ (s32)(numSamplesToProcess - numSamplesInFirstFrame + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME;
+ numSamplesToDecode = numFramesToDecode * SAMPLES_PER_FRAME;
+ numTrailingSamplesToIgnore = numSamplesInFirstFrame + numSamplesToDecode - numSamplesToProcess;
+ } else {
+ // The end will be reached.
+ numSamplesToDecode = numSamplesUntilEnd - numSamplesInFirstFrame;
+ numTrailingSamplesToIgnore = 0;
+ if (numSamplesToDecode <= 0) {
+ numSamplesToDecode = 0;
+ numSamplesInFirstFrame = numSamplesUntilEnd;
+ }
+ numFramesToDecode = (numSamplesToDecode + SAMPLES_PER_FRAME - 1) / SAMPLES_PER_FRAME;
+ if (loopInfo->count != 0) {
+ if ((loopInfo->count == 2) && synthState->stopLoop) {
+ sampleFinished = true;
+ } else {
+ // Loop around and restart
+ loopToPoint = true;
+ }
+ } else {
+ sampleFinished = true;
+ }
+ }
+
+ // Set parameters based on compression type
+ switch (sample->codec) {
+ case CODEC_ADPCM:
+ // 16 2-byte samples (32 bytes) compressed into 4-bit samples (8 bytes) + 1 header byte
+ frameSize = 9;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_SMALL_ADPCM:
+ // 16 2-byte samples (32 bytes) compressed into 2-bit samples (4 bytes) + 1 header byte
+ frameSize = 5;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_UNK7:
+ // 2 2-byte samples (4 bytes) processed without decompression
+ frameSize = 4;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_S8:
+ // 16 2-byte samples (32 bytes) compressed into 8-bit samples (16 bytes)
+ frameSize = 16;
+ skipInitialSamples = SAMPLES_PER_FRAME;
+ zeroOffset = 0;
+ break;
+
+ case CODEC_REVERB:
+ reverbAddrSrc = (void*)0xFFFFFFFF;
+ if (gCustomAudioReverbFunction != NULL) {
+ reverbAddrSrc = gCustomAudioReverbFunction(sample, numSamplesToLoadAdj, flags, noteIndex);
+ }
+
+ if (reverbAddrSrc == (void*)0xFFFFFFFF) {
+ sampleFinished = true;
+ } else if (reverbAddrSrc == NULL) {
+ return cmd;
+ } else {
+ AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE,
+ reverbAddrSrc);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ }
+ goto skip;
+
+ case CODEC_S16_INMEMORY:
+ case CODEC_UNK6:
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ goto skip;
+
+ case CODEC_S16:
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE,
+ (numSamplesToLoadAdj + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ flags = A_CONTINUE;
+ skipBytes = 0;
+ numSamplesProcessed = numSamplesToLoadAdj;
+ dmemUncompressedAddrOffset1 = numSamplesToLoadAdj;
+ goto skip;
+
+ default:
+ break;
+ }
+
+ // Move the compressed raw sample data from ram into the rsp (DMEM)
+ if (numFramesToDecode != 0) {
+ // Get the offset from the start of the sample to where the sample is currently playing from
+ frameIndex = (synthState->samplePosInt + skipInitialSamples - numFirstFrameSamplesToIgnore) /
+ SAMPLES_PER_FRAME;
+ sampleAddrOffset = frameIndex * frameSize;
+
+ // Get the ram address of the requested sample chunk
+ if (sample->medium == MEDIUM_RAM) {
+ // Sample is already loaded into ram
+ samplesToLoadAddr = sampleAddr + (zeroOffset + sampleAddrOffset);
+ } else if (gAudioContext.unk_29B8) { // always false
+ return cmd;
+ } else if (sample->medium == MEDIUM_UNK) {
+ // This medium is unsupported so terminate processing this note
+ return cmd;
+ } else {
+ // This medium is not in ram, so dma the requested sample into ram
+ samplesToLoadAddr =
+ AudioLoad_DmaSampleData(sampleAddr + (zeroOffset + sampleAddrOffset),
+ ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME), flags,
+ &synthState->sampleDmaIndex, sample->medium);
+ }
+
+ if (samplesToLoadAddr == NULL) {
+ // The ram address was unsuccessfully allocated
+ return cmd;
+ }
+
+ // Move the raw sample chunk from ram to the rsp
+ // DMEM at the addresses before DMEM_COMPRESSED_ADPCM_DATA
+ sampleDataChunkAlignPad = (u32)samplesToLoadAddr & 0xF;
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aLoadBuffer(cmd++, samplesToLoadAddr - sampleDataChunkAlignPad, sampleDataDmemAddr,
+ sampleDataChunkSize);
+ } else {
+ numSamplesToDecode = 0;
+ sampleDataChunkAlignPad = 0;
+ }
+
+ if (synthState->atLoopPoint) {
+ aSetLoop(cmd++, sample->loop->predictorState);
+ flags = A_LOOP;
+ synthState->atLoopPoint = false;
+ }
+
+ numSamplesInThisIteration = numSamplesToDecode + numSamplesInFirstFrame - numTrailingSamplesToIgnore;
+
+ if (numSamplesProcessed == 0) {
+ //! FAKE:
+ if (1) {}
+ skipBytes = numFirstFrameSamplesToIgnore * SAMPLE_SIZE;
+ } else {
+ dmemUncompressedAddrOffset2 = ALIGN16(dmemUncompressedAddrOffset1 + 8 * SAMPLE_SIZE);
+ }
+
+ // Decompress the raw sample chunks in the rsp
+ // Goes from adpcm (compressed) sample data to pcm (uncompressed) sample data
+ switch (sample->codec) {
+ case CODEC_ADPCM:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ aADPCMdec(cmd++, flags, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_SMALL_ADPCM:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ aSetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ aADPCMdec(cmd++, flags | A_ADPCM_SHORT, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_S8:
+ sampleDataChunkSize = ALIGN16((numFramesToDecode * frameSize) + SAMPLES_PER_FRAME);
+ sampleDataDmemAddr = DMEM_COMPRESSED_ADPCM_DATA - sampleDataChunkSize;
+ AudioSynth_SetBuffer(cmd++, 0, sampleDataDmemAddr + sampleDataChunkAlignPad,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2,
+ numSamplesToDecode * SAMPLE_SIZE);
+ AudioSynth_S8Dec(cmd++, flags, synthState->synthesisBuffers->adpcmState);
+ break;
+
+ case CODEC_UNK7:
+ default:
+ // No decompression
+ break;
+ }
+
+ if (numSamplesProcessed != 0) {
+ aDMEMMove(cmd++,
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset2 +
+ (numFirstFrameSamplesToIgnore * SAMPLE_SIZE),
+ DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1,
+ numSamplesInThisIteration * SAMPLE_SIZE);
+ }
+
+ numSamplesProcessed += numSamplesInThisIteration;
+
+ switch (flags) {
+ case A_INIT:
+ skipBytes = SAMPLES_PER_FRAME * SAMPLE_SIZE;
+ dmemUncompressedAddrOffset1 = (numSamplesToDecode + SAMPLES_PER_FRAME) * SAMPLE_SIZE;
+ break;
+
+ case A_LOOP:
+ dmemUncompressedAddrOffset1 =
+ numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1;
+ break;
+
+ default:
+ if (dmemUncompressedAddrOffset1 != 0) {
+ dmemUncompressedAddrOffset1 =
+ numSamplesInThisIteration * SAMPLE_SIZE + dmemUncompressedAddrOffset1;
+ } else {
+ dmemUncompressedAddrOffset1 =
+ (numFirstFrameSamplesToIgnore + numSamplesInThisIteration) * SAMPLE_SIZE;
+ }
+ break;
+ }
+
+ flags = A_CONTINUE;
+
+ skip:
+
+ // Update what to do with the samples next
+ if (sampleFinished) {
+ if ((numSamplesToLoadAdj - numSamplesProcessed) != 0) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE + dmemUncompressedAddrOffset1,
+ (numSamplesToLoadAdj - numSamplesProcessed) * SAMPLE_SIZE);
+ }
+ finished = true;
+ note->sampleState.bitField0.finished = true;
+ AudioSynth_DisableSampleStates(updateIndex, noteIndex);
+ break; // break out of the for-loop
+ } else if (loopToPoint) {
+ synthState->atLoopPoint = true;
+ synthState->samplePosInt = loopInfo->start;
+ } else {
+ synthState->samplePosInt += numSamplesToProcess;
+ }
+ }
+
+ switch (numParts) {
+ case 1:
+ sampleDmemBeforeResampling = DMEM_UNCOMPRESSED_NOTE + skipBytes;
+ break;
+
+ case 2:
+ switch (curPart) {
+ case 0:
+ AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes,
+ DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE),
+ ALIGN8(numSamplesToLoadAdj / 2));
+ numSamplesToLoadFirstPart = numSamplesToLoadAdj;
+ sampleDmemBeforeResampling = DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE);
+ if (finished) {
+ AudioSynth_ClearBuffer(cmd++, sampleDmemBeforeResampling + numSamplesToLoadFirstPart,
+ numSamplesToLoadAdj + SAMPLES_PER_FRAME);
+ }
+ break;
+
+ case 1:
+ AudioSynth_InterL(cmd++, DMEM_UNCOMPRESSED_NOTE + skipBytes,
+ DMEM_TEMP + (SAMPLES_PER_FRAME * SAMPLE_SIZE) + numSamplesToLoadFirstPart,
+ ALIGN8(numSamplesToLoadAdj / 2));
+ break;
+
+ default:
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ if (finished) {
+ break;
+ }
+ }
+ }
+
+ // Update the flags for the signal processing below
+ flags = A_CONTINUE;
+ if (sampleState->bitField0.needsInit == true) {
+ sampleState->bitField0.needsInit = false;
+ flags = A_INIT;
+ }
+
+ // Resample the decompressed mono-signal to the correct pitch
+ cmd = AudioSynth_FinalResample(cmd, synthState, numSamplesPerUpdate * SAMPLE_SIZE, frequencyFixedPoint,
+ sampleDmemBeforeResampling, flags);
+
+ // UnkCmd19 was removed from the audio microcode
+ // This block performs no operation
+ if (bookOffset == 3) {
+ AudioSynth_UnkCmd19(cmd++, DMEM_TEMP, DMEM_TEMP, numSamplesPerUpdate * (s32)SAMPLE_SIZE, 0);
+ }
+
+ // Apply the gain to the mono-signal to adjust the volume
+ gain = sampleState->gain;
+ if (gain != 0) {
+ // A gain of 0x10 (a UQ4.4 number) is equivalent to 1.0 and represents no volume change
+ if (gain < 0x10) {
+ gain = 0x10;
+ }
+ AudioSynth_HiLoGain(cmd++, gain, DMEM_TEMP, 0, (numSamplesPerUpdate + SAMPLES_PER_FRAME) * SAMPLE_SIZE);
+ }
+
+ // Apply the filter to the mono-signal
+ filter = sampleState->filter;
+ if (filter != 0) {
+ AudioSynth_LoadFilterSize(cmd++, numSamplesPerUpdate * SAMPLE_SIZE, filter);
+ AudioSynth_LoadFilterBuffer(cmd++, flags, DMEM_TEMP, synthState->synthesisBuffers->filterState);
+ }
+
+ // Apply the comb filter to the mono-signal by taking the signal with a small temporal offset,
+ // and adding it back to itself
+ combFilterSize = sampleState->combFilterSize;
+ combFilterGain = sampleState->combFilterGain;
+ combFilterState = synthState->synthesisBuffers->combFilterState;
+ if ((combFilterSize != 0) && (sampleState->combFilterGain != 0)) {
+ AudioSynth_DMemMove(cmd++, DMEM_TEMP, DMEM_COMB_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ combFilterDmem = DMEM_COMB_TEMP - combFilterSize;
+ if (synthState->combFilterNeedsInit) {
+ AudioSynth_ClearBuffer(cmd++, combFilterDmem, combFilterSize);
+ synthState->combFilterNeedsInit = false;
+ } else {
+ AudioSynth_LoadBuffer(cmd++, combFilterDmem, combFilterSize, combFilterState);
+ }
+ AudioSynth_SaveBuffer(cmd++, DMEM_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE) - combFilterSize, combFilterSize,
+ combFilterState);
+ AudioSynth_Mix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, combFilterGain, DMEM_COMB_TEMP,
+ combFilterDmem);
+ AudioSynth_DMemMove(cmd++, combFilterDmem, DMEM_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ } else {
+ synthState->combFilterNeedsInit = true;
+ }
+
+ // Determine the behavior of the audio processing that leads to the haas effect
+ if ((sampleState->haasEffectLeftDelaySize != 0) || (synthState->prevHaasEffectLeftDelaySize != 0)) {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_LEFT;
+ } else if ((sampleState->haasEffectRightDelaySize != 0) || (synthState->prevHaasEffectRightDelaySize != 0)) {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_RIGHT;
+ } else {
+ haasEffectDelaySide = HAAS_EFFECT_DELAY_NONE;
+ }
+
+ // Apply an unknown effect based on the surround sound-mode
+ if (gAudioContext.soundMode == SOUNDMODE_SURROUND) {
+ sampleState->targetVolLeft = sampleState->targetVolLeft >> 1;
+ sampleState->targetVolRight = sampleState->targetVolRight >> 1;
+ if (sampleState->surroundEffectIndex != 0xFF) {
+ cmd = AudioSynth_ApplySurroundEffect(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, flags);
+ }
+ }
+
+ // Split the mono-signal into left and right channels:
+ // Both for dry signal (to go to the speakers now)
+ // and for wet signal (to go to a reverb buffer to be stored, and brought back later to produce an echo)
+ cmd = AudioSynth_ProcessEnvelope(cmd, sampleState, synthState, numSamplesPerUpdate, DMEM_TEMP, haasEffectDelaySide,
+ flags);
+
+ // Apply the haas effect by delaying either the left or the right channel by a small amount
+ if (sampleState->bitField1.useHaasEffect) {
+ if (!(flags & A_INIT)) {
+ flags = A_CONTINUE;
+ }
+ cmd = AudioSynth_ApplyHaasEffect(cmd, sampleState, synthState, numSamplesPerUpdate * (s32)SAMPLE_SIZE, flags,
+ haasEffectDelaySide);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ApplySurroundEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, s32 haasDmem, s32 flags) {
+ s32 wetGain;
+ u16 dryGain;
+ s64 dmem = DMEM_SURROUND_TEMP;
+ f32 decayGain;
+
+ AudioSynth_DMemMove(cmd++, haasDmem, DMEM_HAAS_TEMP, numSamplesPerUpdate * SAMPLE_SIZE);
+ dryGain = synthState->surroundEffectGain;
+
+ if (flags == A_INIT) {
+ aClearBuffer(cmd++, dmem, sizeof(synthState->synthesisBuffers->surroundEffectState));
+ synthState->surroundEffectGain = 0;
+ } else {
+ aLoadBuffer(cmd++, synthState->synthesisBuffers->surroundEffectState, dmem,
+ sizeof(synthState->synthesisBuffers->surroundEffectState));
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, dryGain, dmem, DMEM_LEFT_CH);
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (dryGain ^ 0xFFFF), dmem, DMEM_RIGHT_CH);
+
+ wetGain = (dryGain * synthState->curReverbVol) >> 7;
+
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, wetGain, dmem, DMEM_WET_LEFT_CH);
+ aMix(cmd++, (numSamplesPerUpdate * (s32)SAMPLE_SIZE) >> 4, (wetGain ^ 0xFFFF), dmem, DMEM_WET_RIGHT_CH);
+ }
+
+ aSaveBuffer(cmd++, DMEM_SURROUND_TEMP + (numSamplesPerUpdate * SAMPLE_SIZE),
+ synthState->synthesisBuffers->surroundEffectState,
+ sizeof(synthState->synthesisBuffers->surroundEffectState));
+
+ decayGain = (sampleState->targetVolLeft + sampleState->targetVolRight) * (1.0f / 0x2000);
+
+ if (decayGain > 1.0f) {
+ decayGain = 1.0f;
+ }
+
+ decayGain = decayGain * gDefaultPanVolume[127 - sampleState->surroundEffectIndex];
+ synthState->surroundEffectGain = ((decayGain * 0x7FFF) + synthState->surroundEffectGain) / 2;
+
+ AudioSynth_DMemMove(cmd++, DMEM_HAAS_TEMP, haasDmem, numSamplesPerUpdate * SAMPLE_SIZE);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_FinalResample(Acmd* cmd, NoteSynthesisState* synthState, s32 size, u16 pitch, u16 inpDmem,
+ s32 resampleFlags) {
+ if (pitch == 0) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_TEMP, size);
+ } else {
+ aSetBuffer(cmd++, 0, inpDmem, DMEM_TEMP, size);
+ aResample(cmd++, resampleFlags, pitch, synthState->synthesisBuffers->finalResampleState);
+ }
+
+ return cmd;
+}
+
+Acmd* AudioSynth_ProcessEnvelope(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesPerUpdate, u16 dmemSrc, s32 haasEffectDelaySide, s32 flags) {
+ u32 dmemDests;
+ u16 curVolLeft;
+ u16 targetVolLeft;
+ s32 curReverbVol;
+ u16 curVolRight;
+ s16 targetReverbVol;
+ s16 rampLeft;
+ s16 rampRight;
+ s16 rampReverb;
+ s16 curReverbVolAndFlags;
+ u16 targetVolRight;
+ f32 defaultPanVolume;
+ s32 pad;
+
+ targetReverbVol = sampleState->targetReverbVol;
+
+ curVolLeft = synthState->curVolLeft;
+ curVolRight = synthState->curVolRight;
+
+ targetVolLeft = sampleState->targetVolLeft;
+ targetVolLeft <<= 4;
+ targetVolRight = sampleState->targetVolRight;
+ targetVolRight <<= 4;
+
+ if ((gAudioContext.soundMode == SOUNDMODE_SURROUND) && (sampleState->surroundEffectIndex != 0xFF)) {
+ defaultPanVolume = gDefaultPanVolume[sampleState->surroundEffectIndex];
+ targetVolLeft *= defaultPanVolume;
+ targetVolRight *= defaultPanVolume;
+ }
+
+ if (targetVolLeft != curVolLeft) {
+ rampLeft = (targetVolLeft - curVolLeft) / (numSamplesPerUpdate >> 3);
+ } else {
+ rampLeft = 0;
+ }
+
+ if (targetVolRight != curVolRight) {
+ rampRight = (targetVolRight - curVolRight) / (numSamplesPerUpdate >> 3);
+ } else {
+ rampRight = 0;
+ }
+
+ curReverbVolAndFlags = synthState->curReverbVol;
+ curReverbVol = curReverbVolAndFlags & 0x7F;
+
+ if (curReverbVolAndFlags != targetReverbVol) {
+ rampReverb = (((targetReverbVol & 0x7F) - curReverbVol) << 9) / (numSamplesPerUpdate >> 3);
+ synthState->curReverbVol = targetReverbVol;
+ } else {
+ rampReverb = 0;
+ }
+
+ synthState->curVolLeft = curVolLeft + (rampLeft * (numSamplesPerUpdate >> 3));
+ synthState->curVolRight = curVolRight + (rampRight * (numSamplesPerUpdate >> 3));
+
+ if (sampleState->bitField1.useHaasEffect) {
+ AudioSynth_ClearBuffer(cmd++, DMEM_HAAS_TEMP, DMEM_1CH_SIZE);
+ AudioSynth_EnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
+ AudioSynth_EnvSetup2(cmd++, curVolLeft, curVolRight);
+
+ switch (haasEffectDelaySide) {
+ case HAAS_EFFECT_DELAY_LEFT:
+ // Store the left dry channel in a temp space to be delayed to produce the haas effect
+ dmemDests = sEnvMixerLeftHaasDmemDests;
+ break;
+
+ case HAAS_EFFECT_DELAY_RIGHT:
+ // Store the right dry channel in a temp space to be delayed to produce the haas effect
+ dmemDests = sEnvMixerRightHaasDmemDests;
+ break;
+
+ default: // HAAS_EFFECT_DELAY_NONE
+ dmemDests = sEnvMixerDefaultDmemDests;
+ break;
+ }
+ } else {
+ aEnvSetup1(cmd++, curReverbVol * 2, rampReverb, rampLeft, rampRight);
+ aEnvSetup2(cmd++, curVolLeft, curVolRight);
+ dmemDests = sEnvMixerDefaultDmemDests;
+ }
+
+ aEnvMixer(cmd++, dmemSrc, numSamplesPerUpdate, (curReverbVolAndFlags & 0x80) >> 7,
+ sampleState->bitField0.strongReverbRight, sampleState->bitField0.strongReverbLeft,
+ sampleState->bitField0.strongRight, sampleState->bitField0.strongLeft, dmemDests, sEnvMixerOp);
+
+ return cmd;
+}
+
+Acmd* AudioSynth_LoadWaveSamples(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState,
+ s32 numSamplesToLoad) {
+ s32 numSamplesAvailable;
+ s32 harmonicIndexCurAndPrev = sampleState->harmonicIndexCurAndPrev;
+ s32 samplePosInt = synthState->samplePosInt;
+ s32 numDuplicates;
+
+ if (sampleState->bitField1.bookOffset != 0) {
+ // Move the noise wave (that reads compiled assembly as samples) from ram to dmem
+ AudioSynth_LoadBuffer(cmd++, DMEM_UNCOMPRESSED_NOTE, ALIGN16(numSamplesToLoad * SAMPLE_SIZE), gWaveSamples[8]);
+ // Offset the address for the samples read by gWaveSamples[8] to the next set of samples
+ gWaveSamples[8] += numSamplesToLoad * SAMPLE_SIZE;
+
+ return cmd;
+ } else {
+ // Move the synthetic wave from ram to dmem
+ aLoadBuffer(cmd++, sampleState->waveSampleAddr, DMEM_UNCOMPRESSED_NOTE, WAVE_SAMPLE_COUNT * SAMPLE_SIZE);
+
+ // If the harmonic changes, map the offset in the wave from one harmonic to another for continuity
+ if (harmonicIndexCurAndPrev != 0) {
+ samplePosInt = (samplePosInt * sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev >> 2]) /
+ sNumSamplesPerWavePeriod[harmonicIndexCurAndPrev & 3];
+ }
+
+ // Offset in the WAVE_SAMPLE_COUNT samples of gWaveSamples to start processing the wave for continuity
+ samplePosInt = (u32)samplePosInt % WAVE_SAMPLE_COUNT;
+ // Number of samples in the initial WAVE_SAMPLE_COUNT samples available to be used to process
+ numSamplesAvailable = WAVE_SAMPLE_COUNT - samplePosInt;
+
+ // Require duplicates if there are more samples to load than available
+ if (numSamplesToLoad > numSamplesAvailable) {
+ // Duplicate (copy) the WAVE_SAMPLE_COUNT samples as many times as needed to reach numSamplesToLoad.
+ // (numSamplesToLoad - numSamplesAvailable) is the number of samples missing.
+ // Divide by WAVE_SAMPLE_COUNT, rounding up, to get the amount of duplicates
+ numDuplicates = ((numSamplesToLoad - numSamplesAvailable + WAVE_SAMPLE_COUNT - 1) / WAVE_SAMPLE_COUNT);
+ if (numDuplicates != 0) {
+ aDuplicate(cmd++, numDuplicates, DMEM_UNCOMPRESSED_NOTE,
+ DMEM_UNCOMPRESSED_NOTE + (WAVE_SAMPLE_COUNT * SAMPLE_SIZE));
+ }
+ }
+ synthState->samplePosInt = samplePosInt;
+ }
+
+ return cmd;
+}
+
+/**
+ * The Haas Effect gives directionality to sound by applying a small (< 35ms) delay to either the left or right channel.
+ * The delay is small enough that the sound is still perceived as one sound, but the channel that is not delayed will
+ * reach our ear first and give a sense of directionality. The sound is directed towards the opposite side of the delay.
+ */
+Acmd* AudioSynth_ApplyHaasEffect(Acmd* cmd, NoteSampleState* sampleState, NoteSynthesisState* synthState, s32 size,
+ s32 flags, s32 haasEffectDelaySide) {
+ u16 dmemDest;
+ u16 pitch;
+ u8 prevHaasEffectDelaySize;
+ u8 haasEffectDelaySize;
+
+ switch (haasEffectDelaySide) {
+ case HAAS_EFFECT_DELAY_LEFT:
+ // Delay the sample on the left channel
+ // This allows the right channel to be heard first
+ dmemDest = DMEM_LEFT_CH;
+ haasEffectDelaySize = sampleState->haasEffectLeftDelaySize;
+ prevHaasEffectDelaySize = synthState->prevHaasEffectLeftDelaySize;
+ synthState->prevHaasEffectRightDelaySize = 0;
+ synthState->prevHaasEffectLeftDelaySize = haasEffectDelaySize;
+ break;
+
+ case HAAS_EFFECT_DELAY_RIGHT:
+ // Delay the sample on the right channel
+ // This allows the left channel to be heard first
+ dmemDest = DMEM_RIGHT_CH;
+ haasEffectDelaySize = sampleState->haasEffectRightDelaySize;
+ prevHaasEffectDelaySize = synthState->prevHaasEffectRightDelaySize;
+ synthState->prevHaasEffectRightDelaySize = haasEffectDelaySize;
+ synthState->prevHaasEffectLeftDelaySize = 0;
+ break;
+
+ default: // HAAS_EFFECT_DELAY_NONE
+ return cmd;
+ }
+
+ if (flags != A_INIT) {
+ // Slightly adjust the sample rate in order to fit a change in sample delay
+ if (haasEffectDelaySize != prevHaasEffectDelaySize) {
+ pitch = (((size << 0xF) / 2) - 1) / ((size + haasEffectDelaySize - prevHaasEffectDelaySize - 2) / 2);
+ aSetBuffer(cmd++, 0, DMEM_HAAS_TEMP, DMEM_TEMP, size + haasEffectDelaySize - prevHaasEffectDelaySize);
+ aResampleZoh(cmd++, pitch, 0);
+ } else {
+ aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
+ }
+
+ if (prevHaasEffectDelaySize != 0) {
+ aLoadBuffer(cmd++, synthState->synthesisBuffers->haasEffectDelayState, DMEM_HAAS_TEMP,
+ ALIGN16(prevHaasEffectDelaySize));
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + prevHaasEffectDelaySize,
+ size + haasEffectDelaySize - prevHaasEffectDelaySize);
+ } else {
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP, size + haasEffectDelaySize);
+ }
+ } else {
+ // Just apply a delay directly
+ aDMEMMove(cmd++, DMEM_HAAS_TEMP, DMEM_TEMP, size);
+ if (haasEffectDelaySize) { // != 0
+ aClearBuffer(cmd++, DMEM_HAAS_TEMP, haasEffectDelaySize);
+ }
+ aDMEMMove(cmd++, DMEM_TEMP, DMEM_HAAS_TEMP + haasEffectDelaySize, size);
+ }
+
+ if (haasEffectDelaySize) { // != 0
+ // Save excessive samples for next iteration
+ aSaveBuffer(cmd++, DMEM_HAAS_TEMP + size, synthState->synthesisBuffers->haasEffectDelayState,
+ ALIGN16(haasEffectDelaySize));
+ }
+
+ aAddMixer(cmd++, ALIGN64(size), DMEM_HAAS_TEMP, dmemDest, 0x7FFF);
+
+ return cmd;
+}
diff --git a/src/code/audio/code_8019AF00.c b/src/code/audio/code_8019AF00.c
index 007d7ca85..98be41397 100644
--- a/src/code/audio/code_8019AF00.c
+++ b/src/code/audio/code_8019AF00.c
@@ -4078,7 +4078,7 @@ void AudioSfx_SetProperties(u8 bankId, u8 entryIndex, u8 channelIndex) {
}
u32 AudioSfx_SetFreqAndStereoBits(u8 seqScriptValIn, SequenceChannel* channel) {
- channel->stereo.asByte = sSfxChannelState[seqScriptValIn].stereoBits;
+ channel->stereoData.asByte = sSfxChannelState[seqScriptValIn].stereoBits;
channel->freqScale = sSfxChannelState[seqScriptValIn].freqScale;
channel->changes.s.freqScale = true;
diff --git a/src/code/speed_meter.c b/src/code/speed_meter.c
index 9f04de110..5ad1cdbe0 100644
--- a/src/code/speed_meter.c
+++ b/src/code/speed_meter.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64view.h"
#include "system_malloc.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/speed_meter/func_80177390.s")
diff --git a/src/code/z_camera.c b/src/code/z_camera.c
index c26947b21..da8a5f35a 100644
--- a/src/code/z_camera.c
+++ b/src/code/z_camera.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64quake.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
/**
* Returns the absolute value for floats
diff --git a/src/code/z_demo.c b/src/code/z_demo.c
index ea4a9828a..79d6d05ff 100644
--- a/src/code/z_demo.c
+++ b/src/code/z_demo.c
@@ -1,6 +1,7 @@
#include "global.h"
#include "z64quake.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#include "overlays/gamestates/ovl_daytelop/z_daytelop.h"
void Cutscene_DoNothing(PlayState* play, CutsceneContext* csCtx);
@@ -107,7 +108,7 @@ s32 func_800EA220(PlayState* play, CutsceneContext* csCtx, f32 target) {
void func_800EA258(PlayState* play, CutsceneContext* csCtx) {
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
if (func_800EA220(play, csCtx, 1.0f)) {
Audio_SetCutsceneFlag(true);
csCtx->state++;
@@ -117,7 +118,7 @@ void func_800EA258(PlayState* play, CutsceneContext* csCtx) {
void func_800EA2B8(PlayState* play, CutsceneContext* csCtx) {
func_800ED980(play, csCtx);
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
if (func_800EA220(play, csCtx, 1.0f)) {
Audio_SetCutsceneFlag(true);
csCtx->state++;
@@ -1449,8 +1450,8 @@ void func_800EDA84(PlayState* play, CutsceneContext* csCtx) {
if (gSaveContext.cutsceneTrigger == 0) {
Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
- ShrinkWindow_SetLetterboxTarget(32);
- ShrinkWindow_SetLetterboxMagnitude(0x20);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
+ ShrinkWindow_Letterbox_SetSize(32);
csCtx->state++;
}
diff --git a/src/code/z_effect_soft_sprite_old_init.c b/src/code/z_effect_soft_sprite_old_init.c
index 5fc51b0c3..bbdd528a4 100644
--- a/src/code/z_effect_soft_sprite_old_init.c
+++ b/src/code/z_effect_soft_sprite_old_init.c
@@ -702,16 +702,16 @@ void EffectSsKFire_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* ac
// EffectSsSolderSrchBall Spawn Functions
-void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 unused,
- s16* linkDetected, s16 drawFlag) {
+void EffectSsSolderSrchBall_Spawn(PlayState* play, Vec3f* pos, Vec3f* velocity, Vec3f* accel, s16 scale,
+ s16* playerDetected, s16 flags) {
EffectSsSolderSrchBallInitParams initParams;
Math_Vec3f_Copy(&initParams.pos, pos);
Math_Vec3f_Copy(&initParams.velocity, velocity);
Math_Vec3f_Copy(&initParams.accel, accel);
- initParams.unused = unused;
- initParams.linkDetected = linkDetected;
- initParams.drawFlag = drawFlag;
+ initParams.scale = scale;
+ initParams.playerDetected = playerDetected;
+ initParams.flags = flags;
EffectSs_Spawn(play, EFFECT_SS_SOLDER_SRCH_BALL, 128, &initParams);
}
diff --git a/src/code/z_eventmgr.c b/src/code/z_eventmgr.c
index 7128368ac..5b8b8dce3 100644
--- a/src/code/z_eventmgr.c
+++ b/src/code/z_eventmgr.c
@@ -1,4 +1,5 @@
#include "global.h"
+#include "z64shrink_window.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_eventmgr/func_800F1460.s")
diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c
index 776dc75d7..857250eec 100644
--- a/src/code/z_game_over.c
+++ b/src/code/z_game_over.c
@@ -1,5 +1,6 @@
#include "global.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
void GameOver_Init(PlayState* play) {
play->gameOverCtx.state = GAMEOVER_INACTIVE;
@@ -86,7 +87,7 @@ void GameOver_Update(PlayState* play) {
gameOverCtx->state++;
sGameOverTimer = 0;
Kankyo_InitGameOverLights(play);
- ShrinkWindow_SetLetterboxTarget(32);
+ ShrinkWindow_Letterbox_SetSizeTarget(32);
break;
case GAMEOVER_REVIVE_RUMBLE:
sGameOverTimer = 50;
diff --git a/src/code/z_kaleido_scope_call.c b/src/code/z_kaleido_scope_call.c
index d7905e4dd..9cea42691 100644
--- a/src/code/z_kaleido_scope_call.c
+++ b/src/code/z_kaleido_scope_call.c
@@ -1,5 +1,6 @@
#include "prevent_bss_reordering.h"
#include "global.h"
+#include "z64shrink_window.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
void (*sKaleidoScopeUpdateFunc)(PlayState* play);
@@ -36,7 +37,7 @@ void KaleidoScopeCall_Update(PlayState* play) {
if ((play->pauseCtx.state != 0) || (play->pauseCtx.debugEditor != DEBUG_EDITOR_NONE)) {
if (pauseCtx->state == 1 || pauseCtx->state == 19) {
- if (ShrinkWindow_GetLetterboxMagnitude() == 0) {
+ if (ShrinkWindow_Letterbox_GetSize() == 0) {
R_PAUSE_MENU_MODE = 1;
pauseCtx->unk_200 = 0;
pauseCtx->unk_208 = 0;
diff --git a/src/code/z_kaleido_setup.c b/src/code/z_kaleido_setup.c
index ad24321c7..ec9ae8824 100644
--- a/src/code/z_kaleido_setup.c
+++ b/src/code/z_kaleido_setup.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
s16 D_801BDB00[] = { PAUSE_MAP, PAUSE_QUEST, PAUSE_MASK, PAUSE_ITEM };
@@ -91,8 +93,8 @@ void KaleidoSetup_Update(PlayState* play) {
if (pauseCtx->state == 1) {
Game_SetFramerateDivisor(&play->state, 2);
- if (ShrinkWindow_GetLetterboxTarget() != 0) {
- ShrinkWindow_SetLetterboxTarget(0);
+ if (ShrinkWindow_Letterbox_GetSizeTarget() != 0) {
+ ShrinkWindow_Letterbox_SetSizeTarget(0);
}
func_801A3AEC(1);
}
diff --git a/src/code/z_message.c b/src/code/z_message.c
index df9d160a2..94b0e4b91 100644
--- a/src/code/z_message.c
+++ b/src/code/z_message.c
@@ -1,4 +1,6 @@
#include "global.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "message_data_static.h"
#include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h"
@@ -488,7 +490,7 @@ u8 Message_GetState(MessageContext* msgCtx) {
void func_80152C64(View* view) {
SET_FULLSCREEN_VIEWPORT(view);
- func_8013FBC8(view);
+ View_ApplyOrthoToOverlay(view);
}
#pragma GLOBAL_ASM("asm/non_matchings/code/z_message/func_80152CAC.s")
diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c
index cf7716c9f..5bcd47e15 100644
--- a/src/code/z_parameter.c
+++ b/src/code/z_parameter.c
@@ -1,6 +1,6 @@
#include "global.h"
#include "z64snap.h"
-
+#include "z64view.h"
#include "interface/parameter_static/parameter_static.h"
#include "interface/do_action_static/do_action_static.h"
#include "misc/story_static/story_static.h"
@@ -3825,7 +3825,7 @@ void Interface_SetView1(PlayState* play, s32 topY, s32 bottomY, s32 leftX, s32 r
up.x = up.z = 0.0f;
up.y = 1.0f;
- View_SetViewOrientation(&interfaceCtx->view, &eye, &lookAt, &up);
+ View_LookAt(&interfaceCtx->view, &eye, &lookAt, &up);
interfaceCtx->viewport.topY = topY;
interfaceCtx->viewport.bottomY = bottomY;
@@ -3833,13 +3833,13 @@ void Interface_SetView1(PlayState* play, s32 topY, s32 bottomY, s32 leftX, s32 r
interfaceCtx->viewport.rightX = rightX;
View_SetViewport(&interfaceCtx->view, &interfaceCtx->viewport);
- func_8013F0D0(&interfaceCtx->view, 60.0f, 10.0f, 60.0f);
- func_8013FD74(&interfaceCtx->view);
+ View_SetPerspective(&interfaceCtx->view, 60.0f, 10.0f, 60.0f);
+ View_ApplyPerspectiveToOverlay(&interfaceCtx->view);
}
void Interface_SetView2(InterfaceContext* interfaceCtx) {
SET_FULLSCREEN_VIEWPORT(&interfaceCtx->view);
- func_8013FBC8(&interfaceCtx->view);
+ View_ApplyOrthoToOverlay(&interfaceCtx->view);
}
void Interface_DrawItemButtons(PlayState* play) {
diff --git a/src/code/z_play.c b/src/code/z_play.c
index 06ec9c21e..47bb97a60 100644
--- a/src/code/z_play.c
+++ b/src/code/z_play.c
@@ -1,5 +1,7 @@
#include "global.h"
#include "z64quake.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#pragma GLOBAL_ASM("asm/non_matchings/code/z_play/func_80165460.s")
diff --git a/src/code/z_quake.c b/src/code/z_quake.c
index 2b66a39f8..964935ea1 100644
--- a/src/code/z_quake.c
+++ b/src/code/z_quake.c
@@ -1,5 +1,6 @@
#include "global.h"
#include "z64quake.h"
+#include "z64view.h"
typedef struct {
/* 0x00 */ s16 randIndex;
@@ -823,10 +824,10 @@ void Distortion_Update(void) {
depthPhase += CAM_DEG_TO_BINANG(depthPhaseStep);
screenPlanePhase += CAM_DEG_TO_BINANG(screenPlanePhaseStep);
- View_SetDistortionDirRot(&sDistortionRequest.play->view,
- Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor),
- Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor),
- Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor));
+ View_SetDistortionOrientation(&sDistortionRequest.play->view,
+ Math_CosS(depthPhase) * (DEGF_TO_RADF(rotX) * xyScaleFactor),
+ Math_SinS(depthPhase) * (DEGF_TO_RADF(rotY) * xyScaleFactor),
+ Math_SinS(screenPlanePhase) * (DEGF_TO_RADF(rotZ) * zScaleFactor));
View_SetDistortionScale(&sDistortionRequest.play->view,
(Math_SinS(screenPlanePhase) * (xScale * xyScaleFactor)) + 1.0f,
(Math_CosS(screenPlanePhase) * (yScale * xyScaleFactor)) + 1.0f,
diff --git a/src/code/z_shrink_window.c b/src/code/z_shrink_window.c
index 5bfca86d9..acbdb5c5b 100644
--- a/src/code/z_shrink_window.c
+++ b/src/code/z_shrink_window.c
@@ -4,70 +4,78 @@
*/
#include "prevent_bss_reordering.h"
#include "global.h"
+#include "z64shrink_window.h"
-ShrinkWindowContext gShrinkWindowContext;
-ShrinkWindowContext* gShrinkWindowContextPtr;
+typedef struct {
+ /* 0x0 */ s8 letterboxTarget;
+ /* 0x1 */ s8 letterboxSize;
+ /* 0x2 */ s8 pillarboxTarget;
+ /* 0x3 */ s8 pillarboxSize;
+} ShrinkWindow; // size = 0x4
-void ShrinkWindow_SetLetterboxTarget(s32 target) {
- gShrinkWindowContextPtr->letterboxTarget = target;
+ShrinkWindow sShrinkWindow;
+ShrinkWindow* sShrinkWindowPtr;
+
+void ShrinkWindow_Letterbox_SetSizeTarget(s32 target) {
+ sShrinkWindowPtr->letterboxTarget = target;
}
-s32 ShrinkWindow_GetLetterboxTarget(void) {
- return gShrinkWindowContextPtr->letterboxTarget;
+s32 ShrinkWindow_Letterbox_GetSizeTarget(void) {
+ return sShrinkWindowPtr->letterboxTarget;
}
-void ShrinkWindow_SetLetterboxMagnitude(s32 magnitude) {
- gShrinkWindowContextPtr->letterboxMagnitude = magnitude;
+void ShrinkWindow_Letterbox_SetSize(s32 size) {
+ sShrinkWindowPtr->letterboxSize = size;
}
-s32 ShrinkWindow_GetLetterboxMagnitude(void) {
- return gShrinkWindowContextPtr->letterboxMagnitude;
+s32 ShrinkWindow_Letterbox_GetSize(void) {
+ return sShrinkWindowPtr->letterboxSize;
}
-void ShrinkWindow_SetPillarboxTarget(s32 target) {
- gShrinkWindowContextPtr->pillarboxTarget = target;
+void ShrinkWindow_Pillarbox_SetSizeTarget(s32 target) {
+ sShrinkWindowPtr->pillarboxTarget = target;
}
-s32 ShrinkWindow_GetPillarboxTarget(void) {
- return gShrinkWindowContextPtr->pillarboxTarget;
+s32 ShrinkWindow_Pillarbox_GetSizeTarget(void) {
+ return sShrinkWindowPtr->pillarboxTarget;
}
-void ShrinkWindow_SetPillarboxMagnitude(s32 magnitude) {
- gShrinkWindowContextPtr->pillarboxMagnitude = magnitude;
+void ShrinkWindow_Pillarbox_SetSize(s32 size) {
+ sShrinkWindowPtr->pillarboxSize = size;
}
-s32 ShrinkWindow_GetPillarboxMagnitude(void) {
- return gShrinkWindowContextPtr->pillarboxMagnitude;
+s32 ShrinkWindow_Pillarbox_GetSize(void) {
+ return sShrinkWindowPtr->pillarboxSize;
}
void ShrinkWindow_Init(void) {
- gShrinkWindowContextPtr = &gShrinkWindowContext;
- bzero(gShrinkWindowContextPtr, sizeof(gShrinkWindowContext));
+ sShrinkWindowPtr = &sShrinkWindow;
+ bzero(sShrinkWindowPtr, sizeof(sShrinkWindow));
}
void ShrinkWindow_Destroy(void) {
- gShrinkWindowContextPtr = NULL;
+ sShrinkWindowPtr = NULL;
}
void ShrinkWindow_Update(s32 framerateDivisor) {
- s32 step = ((framerateDivisor == 3) ? 10 : 30 / framerateDivisor);
- s32 nextMagnitude;
+ s32 step = (framerateDivisor == 3) ? 10 : (30 / framerateDivisor);
+ s32 nextSize;
- nextMagnitude = gShrinkWindowContextPtr->letterboxMagnitude;
- Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->letterboxTarget, step);
- gShrinkWindowContextPtr->letterboxMagnitude = nextMagnitude;
+ nextSize = sShrinkWindowPtr->letterboxSize;
+ Math_StepToIGet(&nextSize, sShrinkWindowPtr->letterboxTarget, step);
+ sShrinkWindowPtr->letterboxSize = nextSize;
- nextMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude;
- Math_StepToIGet(&nextMagnitude, gShrinkWindowContextPtr->pillarboxTarget, step);
- gShrinkWindowContextPtr->pillarboxMagnitude = nextMagnitude;
+ nextSize = sShrinkWindowPtr->pillarboxSize;
+ Math_StepToIGet(&nextSize, sShrinkWindowPtr->pillarboxTarget, step);
+ sShrinkWindowPtr->pillarboxSize = nextSize;
}
void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
Gfx* gfx;
- s8 letterboxMagnitude = gShrinkWindowContextPtr->letterboxMagnitude;
- s8 pillarboxMagnitude = gShrinkWindowContextPtr->pillarboxMagnitude;
+ s8 letterboxSize = sShrinkWindowPtr->letterboxSize;
+ s8 pillarboxSize = sShrinkWindowPtr->pillarboxSize;
- if (letterboxMagnitude > 0) {
+ if (letterboxSize > 0) {
OPEN_DISPS(gfxCtx);
gfx = OVERLAY_DISP;
@@ -76,23 +84,23 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
gDPSetCycleType(gfx++, G_CYC_FILL);
gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1));
- gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxMagnitude - 1);
- gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude, gScreenWidth - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, 0, 0, gScreenWidth - 1, letterboxSize - 1);
+ gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize, gScreenWidth - 1, gScreenHeight - 1);
gDPPipeSync(gfx++);
gDPSetCycleType(gfx++, G_CYC_1CYCLE);
gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0);
- gDPFillRectangle(gfx++, 0, letterboxMagnitude, gScreenWidth, letterboxMagnitude + 1);
- gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxMagnitude - 1, gScreenWidth,
- gScreenHeight - letterboxMagnitude);
+ gDPFillRectangle(gfx++, 0, letterboxSize, gScreenWidth, letterboxSize + 1);
+ gDPFillRectangle(gfx++, 0, gScreenHeight - letterboxSize - 1, gScreenWidth, gScreenHeight - letterboxSize);
gDPPipeSync(gfx++);
OVERLAY_DISP = gfx++;
CLOSE_DISPS(gfxCtx);
}
- if (pillarboxMagnitude > 0) {
+
+ if (pillarboxSize > 0) {
OPEN_DISPS(gfxCtx);
gfx = OVERLAY_DISP;
@@ -102,17 +110,16 @@ void ShrinkWindow_Draw(GraphicsContext* gfxCtx) {
gDPSetRenderMode(gfx++, G_RM_NOOP, G_RM_NOOP2);
gDPSetFillColor(gfx++, (GPACK_RGBA5551(0, 0, 0, 1) << 16) | GPACK_RGBA5551(0, 0, 0, 1));
- gDPFillRectangle(gfx++, 0, 0, pillarboxMagnitude - 1, gScreenHeight - 1);
- gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude, 0, gScreenWidth - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, 0, 0, pillarboxSize - 1, gScreenHeight - 1);
+ gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize, 0, gScreenWidth - 1, gScreenHeight - 1);
gDPPipeSync(gfx++);
gDPSetCycleType(gfx++, G_CYC_1CYCLE);
gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, 0);
- gDPFillRectangle(gfx++, pillarboxMagnitude, 0, pillarboxMagnitude + 2, gScreenHeight);
- gDPFillRectangle(gfx++, gScreenWidth - pillarboxMagnitude - 2, 0, gScreenWidth - pillarboxMagnitude,
- gScreenHeight);
+ gDPFillRectangle(gfx++, pillarboxSize, 0, pillarboxSize + 2, gScreenHeight);
+ gDPFillRectangle(gfx++, gScreenWidth - pillarboxSize - 2, 0, gScreenWidth - pillarboxSize, gScreenHeight);
gDPPipeSync(gfx++);
OVERLAY_DISP = gfx++;
diff --git a/src/code/z_view.c b/src/code/z_view.c
index 915c196b7..105e6643a 100644
--- a/src/code/z_view.c
+++ b/src/code/z_view.c
@@ -1,4 +1,9 @@
#include "global.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
+
+s32 View_ApplyPerspective(View* view);
+s32 View_ApplyOrtho(View* view);
void View_ViewportToVp(Vp* dest, Viewport* src) {
s32 width = src->rightX - src->leftX;
@@ -13,41 +18,45 @@ void View_ViewportToVp(Vp* dest, Viewport* src) {
dest->vp.vtrans[2] = 0x01FF;
dest->vp.vtrans[3] = 0;
- if (src->leftX == 0 && src->rightX == 576 && src->topY == 0 && src->bottomY) {}
+ if ((src->leftX == 0) && (src->rightX == SCREEN_WIDTH_HIGH_RES) && (src->topY == 0) &&
+ (src->bottomY == SCREEN_HEIGHT_HIGH_RES)) {}
}
void View_Init(View* view, GraphicsContext* gfxCtx) {
view->gfxCtx = gfxCtx;
+
view->viewport.topY = 0;
- view->viewport.bottomY = 240;
+ view->viewport.bottomY = SCREEN_HEIGHT;
view->viewport.leftX = 0;
- view->viewport.rightX = 320;
+ view->viewport.rightX = SCREEN_WIDTH;
+
view->magic = 0x56494557; // "VIEW"
- view->unk164 = 0;
- view->flags = 1 | 2 | 4;
-
- if (1) {
- ;
- }
+ if (1) {}
view->scale = 1.0f;
- view->up.y = 1.0f;
view->fovy = 60.0f;
- view->eye.x = 0.0f;
- view->eye.y = 0.0f;
- view->at.x = 0.0f;
- view->up.x = 0.0f;
- view->up.z = 0.0f;
view->zNear = 10.0f;
view->zFar = 12800.0f;
+
+ view->eye.x = 0.0f;
+ view->eye.y = 0.0f;
view->eye.z = -1.0f;
+ view->at.x = 0.0f;
+
+ view->up.x = 0.0f;
+ view->up.y = 1.0f;
+ view->up.z = 0.0f;
+
+ view->unk164 = 0;
+ view->flags = VIEW_VIEWING | VIEW_VIEWPORT | VIEW_PROJECTION_PERSPECTIVE;
+
View_InitDistortion(view);
}
-void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
- if (eye->x == at->x && eye->z == at->z) {
+void View_LookAt(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
+ if ((eye->x == at->x) && (eye->z == at->z)) {
eye->z += 0.1f;
up->z = 0.0f;
up->x = 0.0f;
@@ -57,17 +66,21 @@ void View_SetViewOrientation(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
view->eye = *eye;
view->at = *at;
view->up = *up;
- view->flags |= 1;
+ view->flags |= VIEW_VIEWING;
}
-void func_8013F050(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
+/*
+ * Unused. View_LookAt is always used instead. This version is similar but
+ * is missing the input sanitization and the update to the flags.
+ */
+void View_LookAtUnsafe(View* view, Vec3f* eye, Vec3f* at, Vec3f* up) {
view->eye = *eye;
view->at = *at;
view->up = *up;
}
void View_SetScale(View* view, f32 scale) {
- view->flags |= 4;
+ view->flags |= VIEW_PROJECTION_PERSPECTIVE;
view->scale = scale;
}
@@ -75,28 +88,32 @@ void View_GetScale(View* view, f32* scale) {
*scale = view->scale;
}
-void func_8013F0D0(View* view, f32 fovy, f32 zNear, f32 zFar) {
+void View_SetPerspective(View* view, f32 fovy, f32 zNear, f32 zFar) {
view->fovy = fovy;
view->zNear = zNear;
view->zFar = zFar;
- view->flags |= 4;
+ view->flags |= VIEW_PROJECTION_PERSPECTIVE;
}
-void func_8013F100(View* view, f32* fovy, f32* zNear, f32* zFar) {
+void View_GetPerspective(View* view, f32* fovy, f32* zNear, f32* zFar) {
*fovy = view->fovy;
*zNear = view->zNear;
*zFar = view->zFar;
}
-void func_8013F120(View* view, f32 fovy, f32 zNear, f32 zFar) {
+void View_SetOrtho(View* view, f32 fovy, f32 zNear, f32 zFar) {
view->fovy = fovy;
view->zNear = zNear;
view->zFar = zFar;
- view->flags |= 8;
+ view->flags |= VIEW_PROJECTION_ORTHO;
view->scale = 1.0f;
}
-void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) {
+/*
+ * Identical to View_GetPerspective, and never called.
+ * Named as it seems to fit the "set, get" pattern.
+ */
+void View_GetOrtho(View* view, f32* fovy, f32* zNear, f32* zFar) {
*fovy = view->fovy;
*zNear = view->zNear;
*zFar = view->zFar;
@@ -104,14 +121,14 @@ void func_8013F15C(View* view, f32* fovy, f32* zNear, f32* zFar) {
void View_SetViewport(View* view, Viewport* viewport) {
view->viewport = *viewport;
- view->flags |= 2;
+ view->flags |= VIEW_VIEWPORT;
}
void View_GetViewport(View* view, Viewport* viewport) {
*viewport = view->viewport;
}
-void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
+void View_SetScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
Gfx* gfxp = *gfx;
gDPSetScissor(gfxp++, G_SC_NON_INTERLACE, ulx, uly, lrx, lry);
@@ -119,7 +136,7 @@ void View_WriteScissor(Gfx** gfx, s32 ulx, s32 uly, s32 lrx, s32 lry) {
*gfx = gfxp;
}
-void View_SyncAndWriteScissor(View* view, Gfx** gfx) {
+void View_ClearScissor(View* view, Gfx** gfx) {
Gfx* gfxp = *gfx;
s32 ulx = view->viewport.leftX;
s32 uly = view->viewport.topY;
@@ -127,12 +144,12 @@ void View_SyncAndWriteScissor(View* view, Gfx** gfx) {
s32 lry = view->viewport.bottomY;
gDPPipeSync(gfxp++);
- View_WriteScissor(&gfxp, ulx, uly, lrx, lry);
+ View_SetScissor(&gfxp, ulx, uly, lrx, lry);
*gfx = gfxp;
}
-void View_SetScissorForLetterbox(View* view) {
+void View_ApplyLetterbox(View* view) {
s32 letterboxY;
s32 letterboxX;
s32 pad1;
@@ -143,20 +160,21 @@ void View_SetScissorForLetterbox(View* view) {
OPEN_DISPS(view->gfxCtx);
- letterboxY = ShrinkWindow_GetLetterboxMagnitude();
+ letterboxY = ShrinkWindow_Letterbox_GetSize();
+
letterboxX = -1; // The following is optimized to varX = 0 but affects codegen
if (letterboxX < 0) {
letterboxX = 0;
}
- if (letterboxX > 160) {
- letterboxX = 160;
+ if (letterboxX > (SCREEN_WIDTH / 2)) {
+ letterboxX = SCREEN_WIDTH / 2;
}
if (letterboxY < 0) {
letterboxY = 0;
- } else if (letterboxY > 120) {
- letterboxY = 120;
+ } else if (letterboxY > (SCREEN_HEIGHT / 2)) {
+ letterboxY = SCREEN_HEIGHT / 2;
}
ulx = view->viewport.leftX + letterboxX;
@@ -166,31 +184,31 @@ void View_SetScissorForLetterbox(View* view) {
gDPPipeSync(POLY_OPA_DISP++);
{
- s32 pad3;
+ s32 pad2;
Gfx* polyOpa;
polyOpa = POLY_OPA_DISP;
- View_WriteScissor(&polyOpa, ulx, uly, lrx, lry);
+ View_SetScissor(&polyOpa, ulx, uly, lrx, lry);
POLY_OPA_DISP = polyOpa;
}
gDPPipeSync(POLY_XLU_DISP++);
{
Gfx* polyXlu;
- s32 pad4;
+ s32 pad3;
polyXlu = POLY_XLU_DISP;
- View_WriteScissor(&polyXlu, ulx, uly, lrx, lry);
+ View_SetScissor(&polyXlu, ulx, uly, lrx, lry);
POLY_XLU_DISP = polyXlu;
}
CLOSE_DISPS(view->gfxCtx);
}
-s32 View_SetDistortionDirRot(View* view, f32 dirRotX, f32 dirRotY, f32 dirRotZ) {
- view->distortionDirRot.x = dirRotX;
- view->distortionDirRot.y = dirRotY;
- view->distortionDirRot.z = dirRotZ;
+s32 View_SetDistortionOrientation(View* view, f32 rotX, f32 rotY, f32 rotZ) {
+ view->distortionOrientation.x = rotX;
+ view->distortionOrientation.y = rotY;
+ view->distortionOrientation.z = rotZ;
return 1;
}
@@ -207,22 +225,22 @@ s32 View_SetDistortionSpeed(View* view, f32 speed) {
}
s32 View_InitDistortion(View* view) {
- view->distortionDirRot.x = 0.0f;
- view->distortionDirRot.y = 0.0f;
- view->distortionDirRot.z = 0.0f;
+ view->distortionOrientation.x = 0.0f;
+ view->distortionOrientation.y = 0.0f;
+ view->distortionOrientation.z = 0.0f;
view->distortionScale.x = 1.0f;
view->distortionScale.y = 1.0f;
view->distortionScale.z = 1.0f;
- view->curDistortionDirRot = view->distortionDirRot;
+ view->curDistortionOrientation = view->distortionOrientation;
view->curDistortionScale = view->distortionScale;
view->distortionSpeed = 0.0f;
return 1;
}
s32 View_ClearDistortion(View* view) {
- view->distortionDirRot.x = 0.0f;
- view->distortionDirRot.y = 0.0f;
- view->distortionDirRot.z = 0.0f;
+ view->distortionOrientation.x = 0.0f;
+ view->distortionOrientation.y = 0.0f;
+ view->distortionOrientation.z = 0.0f;
view->distortionScale.x = 1.0f;
view->distortionScale.y = 1.0f;
view->distortionScale.z = 1.0f;
@@ -230,8 +248,8 @@ s32 View_ClearDistortion(View* view) {
return 1;
}
-s32 View_SetDistortion(View* view, Vec3f dirRot, Vec3f scale, f32 speed) {
- view->distortionDirRot = dirRot;
+s32 View_SetDistortion(View* view, Vec3f orientation, Vec3f scale, f32 speed) {
+ view->distortionOrientation = orientation;
view->distortionScale = scale;
view->distortionSpeed = speed;
return 1;
@@ -242,17 +260,19 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) {
if (view->distortionSpeed == 0.0f) {
return false;
- } else if (view->distortionSpeed == 1.0f) {
- view->curDistortionDirRot = view->distortionDirRot;
+ }
+
+ if (view->distortionSpeed == 1.0f) {
+ view->curDistortionOrientation = view->distortionOrientation;
view->curDistortionScale = view->distortionScale;
view->distortionSpeed = 0.0f;
} else {
- view->curDistortionDirRot.x =
- F32_LERPIMP(view->curDistortionDirRot.x, view->distortionDirRot.x, view->distortionSpeed);
- view->curDistortionDirRot.y =
- F32_LERPIMP(view->curDistortionDirRot.y, view->distortionDirRot.y, view->distortionSpeed);
- view->curDistortionDirRot.z =
- F32_LERPIMP(view->curDistortionDirRot.z, view->distortionDirRot.z, view->distortionSpeed);
+ view->curDistortionOrientation.x =
+ F32_LERPIMP(view->curDistortionOrientation.x, view->distortionOrientation.x, view->distortionSpeed);
+ view->curDistortionOrientation.y =
+ F32_LERPIMP(view->curDistortionOrientation.y, view->distortionOrientation.y, view->distortionSpeed);
+ view->curDistortionOrientation.z =
+ F32_LERPIMP(view->curDistortionOrientation.z, view->distortionOrientation.z, view->distortionSpeed);
view->curDistortionScale.x =
F32_LERPIMP(view->curDistortionScale.x, view->distortionScale.x, view->distortionSpeed);
@@ -264,29 +284,32 @@ s32 View_StepDistortion(View* view, Mtx* projectionMtx) {
Matrix_MtxToMtxF(projectionMtx, &projectionMtxF);
Matrix_Put(&projectionMtxF);
- Matrix_RotateXFApply(view->curDistortionDirRot.x);
- Matrix_RotateYF(view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_RotateZF(view->curDistortionDirRot.z, MTXMODE_APPLY);
+ Matrix_RotateXFApply(view->curDistortionOrientation.x);
+ Matrix_RotateYF(view->curDistortionOrientation.y, MTXMODE_APPLY);
+ Matrix_RotateZF(view->curDistortionOrientation.z, MTXMODE_APPLY);
Matrix_Scale(view->curDistortionScale.x, view->curDistortionScale.y, view->curDistortionScale.z, MTXMODE_APPLY);
- Matrix_RotateZF(-view->curDistortionDirRot.z, MTXMODE_APPLY);
- Matrix_RotateYF(-view->curDistortionDirRot.y, MTXMODE_APPLY);
- Matrix_RotateXFApply(-view->curDistortionDirRot.x);
+ Matrix_RotateZF(-view->curDistortionOrientation.z, MTXMODE_APPLY);
+ Matrix_RotateYF(-view->curDistortionOrientation.y, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-view->curDistortionOrientation.x);
Matrix_ToMtx(projectionMtx);
return true;
}
-void View_RenderView(View* view, s32 uParm2) {
- uParm2 = (view->flags & uParm2) | uParm2 >> 4;
+/**
+ * Apply view to POLY_OPA_DISP, POLY_XLU_DISP (and OVERLAY_DISP if ortho)
+ */
+void View_Apply(View* view, s32 mask) {
+ mask = (view->flags & mask) | (mask >> 4);
- if (uParm2 & 8) {
- View_RenderToOrthographicMatrix(view);
+ if (mask & VIEW_PROJECTION_ORTHO) {
+ View_ApplyOrtho(view);
} else {
- View_RenderToPerspectiveMatrix(view);
+ View_ApplyPerspective(view);
}
}
-s32 View_RenderToPerspectiveMatrix(View* view) {
+s32 View_ApplyPerspective(View* view) {
f32 aspect;
s32 width;
s32 height;
@@ -297,36 +320,39 @@ s32 View_RenderToPerspectiveMatrix(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ // Viewport
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
- View_SetScissorForLetterbox(view);
+ View_ApplyLetterbox(view);
gSPViewport(POLY_OPA_DISP++, vp);
gSPViewport(POLY_XLU_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ // Perspective projection
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
width = view->viewport.rightX - view->viewport.leftX;
height = view->viewport.bottomY - view->viewport.topY;
aspect = (f32)width / (f32)height;
- guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+ guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale);
view->projection = *projection;
View_StepDistortion(view, projection);
- gSPPerspNormalize(POLY_OPA_DISP++, view->normal);
+ gSPPerspNormalize(POLY_OPA_DISP++, view->perspNorm);
gSPMatrix(POLY_OPA_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- gSPPerspNormalize(POLY_XLU_DISP++, view->normal);
+ gSPPerspNormalize(POLY_XLU_DISP++, view->perspNorm);
gSPMatrix(POLY_XLU_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing));
+ // View matrix (look-at)
+ viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->viewingPtr = viewing;
- if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) {
+ if ((view->eye.x == view->at.x) && (view->eye.y == view->at.y) && (view->eye.z == view->at.z)) {
view->eye.z += 2.0f;
}
@@ -343,24 +369,24 @@ s32 View_RenderToPerspectiveMatrix(View* view) {
return 1;
}
-s32 View_RenderToOrthographicMatrix(View* view) {
+s32 View_ApplyOrtho(View* view) {
Vp* vp;
Mtx* projection;
GraphicsContext* gfxCtx = view->gfxCtx;
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
- View_SetScissorForLetterbox(view);
+ View_ApplyLetterbox(view);
gSPViewport(POLY_OPA_DISP++, vp);
gSPViewport(POLY_XLU_DISP++, vp);
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
@@ -376,7 +402,10 @@ s32 View_RenderToOrthographicMatrix(View* view) {
return 1;
}
-s32 func_8013FBC8(View* view) {
+/**
+ * Apply scissor, viewport and projection (ortho) to OVERLAY_DISP.
+ */
+s32 View_ApplyOrthoToOverlay(View* view) {
Vp* vp;
Mtx* projection;
GraphicsContext* gfxCtx;
@@ -385,7 +414,7 @@ s32 func_8013FBC8(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
@@ -395,26 +424,29 @@ s32 func_8013FBC8(View* view) {
s32 pad;
overlay = OVERLAY_DISP;
- View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
- view->viewport.bottomY);
+ View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
+ view->viewport.bottomY);
OVERLAY_DISP = overlay;
}
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
view->zNear, view->zFar, view->scale);
view->projection = *projection;
- gSPMatrix(OVERLAY_DISP++, projection, G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
CLOSE_DISPS(gfxCtx);
return 1;
}
-s32 func_8013FD74(View* view) {
+/**
+ * Apply scissor, viewport, view and projection (perspective) to OVERLAY_DISP.
+ */
+s32 View_ApplyPerspectiveToOverlay(View* view) {
f32 aspect;
s32 width;
s32 height;
@@ -428,7 +460,7 @@ s32 func_8013FD74(View* view) {
OPEN_DISPS(gfxCtx);
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, &view->viewport);
view->vp = *vp;
@@ -438,28 +470,30 @@ s32 func_8013FD74(View* view) {
Gfx* overlay;
overlay = OVERLAY_DISP;
- View_WriteScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
- view->viewport.bottomY);
+ View_SetScissor(&overlay, view->viewport.leftX, view->viewport.topY, view->viewport.rightX,
+ view->viewport.bottomY);
OVERLAY_DISP = overlay;
}
gSPViewport(OVERLAY_DISP++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
width = view->viewport.rightX - view->viewport.leftX;
height = view->viewport.bottomY - view->viewport.topY;
aspect = (f32)width / (f32)height;
- guPerspective(projection, &view->normal, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+ guPerspective(projection, &view->perspNorm, view->fovy, aspect, view->zNear, view->zFar, view->scale);
+
view->projection = *projection;
- gSPPerspNormalize(OVERLAY_DISP++, view->normal);
+ gSPPerspNormalize(OVERLAY_DISP++, view->perspNorm);
gSPMatrix(OVERLAY_DISP++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
- viewing = GRAPH_ALLOC(gfxCtx, sizeof(*viewing));
+ viewing = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->viewingPtr = viewing;
+ // This check avoids a divide-by-zero in guLookAt if eye == at
if (view->eye.x == view->at.x && view->eye.y == view->at.y && view->eye.z == view->at.z) {
view->eye.z += 2.0f;
}
@@ -476,7 +510,10 @@ s32 func_8013FD74(View* view) {
return 1;
}
-s32 func_80140024(View* view) {
+/**
+ * Just updates view's view matrix from its eye/at/up vectors.
+ */
+s32 View_UpdateViewingMatrix(View* view) {
guLookAt(view->viewingPtr, view->eye.x, view->eye.y, view->eye.z, view->at.x, view->at.y, view->at.z, view->up.x,
view->up.y, view->up.z);
@@ -486,22 +523,22 @@ s32 func_80140024(View* view) {
return 1;
}
-s32 func_801400CC(View* view, Gfx** gfxp) {
+s32 View_ApplyTo(View* view, Gfx** gfxp) {
Gfx* gfx = *gfxp;
GraphicsContext* gfxCtx = view->gfxCtx;
Viewport* viewport = &view->viewport;
Mtx* projection;
Vp* vp;
- vp = GRAPH_ALLOC(gfxCtx, sizeof(*vp));
+ vp = GRAPH_ALLOC(gfxCtx, sizeof(Vp));
View_ViewportToVp(vp, viewport);
view->vp = *vp;
- View_SyncAndWriteScissor(view, &gfx);
+ View_ClearScissor(view, &gfx);
gSPViewport(gfx++, vp);
- projection = GRAPH_ALLOC(gfxCtx, sizeof(*projection));
+ projection = GRAPH_ALLOC(gfxCtx, sizeof(Mtx));
view->projectionPtr = projection;
guOrtho(projection, gScreenWidth * -0.5f, gScreenWidth * 0.5f, gScreenHeight * -0.5f, gScreenHeight * 0.5f,
@@ -509,7 +546,7 @@ s32 func_801400CC(View* view, Gfx** gfxp) {
view->projection = *projection;
- gSPMatrix(gfx++, projection, G_MTX_LOAD | G_MTX_PROJECTION);
+ gSPMatrix(gfx++, projection, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_PROJECTION);
*gfxp = gfx;
return 1;
diff --git a/src/overlays/actors/ovl_Boss_01/z_boss_01.c b/src/overlays/actors/ovl_Boss_01/z_boss_01.c
index 11790f377..40800569f 100644
--- a/src/overlays/actors/ovl_Boss_01/z_boss_01.c
+++ b/src/overlays/actors/ovl_Boss_01/z_boss_01.c
@@ -6,6 +6,7 @@
#include "z_boss_01.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20)
diff --git a/src/overlays/actors/ovl_Boss_02/z_boss_02.c b/src/overlays/actors/ovl_Boss_02/z_boss_02.c
index 9808e68a4..b3ab79b20 100644
--- a/src/overlays/actors/ovl_Boss_02/z_boss_02.c
+++ b/src/overlays/actors/ovl_Boss_02/z_boss_02.c
@@ -6,6 +6,7 @@
#include "z_boss_02.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#include "overlays/actors/ovl_Door_Warp1/z_door_warp1.h"
#include "overlays/actors/ovl_Item_B_Heart/z_item_b_heart.h"
#include "objects/gameplay_keep/gameplay_keep.h"
@@ -2033,7 +2034,7 @@ void func_809DD934(Boss02* this, PlayState* play) {
Matrix_RotateZF(this->unk_1D54, MTXMODE_APPLY);
Matrix_MultVecY(1.0f, &this->subCamUp);
Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &this->subCamEye, &this->subCamUp);
- ShrinkWindow_SetLetterboxTarget(27);
+ ShrinkWindow_Letterbox_SetSizeTarget(27);
}
}
@@ -2241,6 +2242,6 @@ void func_809DEAC4(Boss02* this, PlayState* play) {
Play_SetCameraAtEyeUp(play, this->subCamId, &this->subCamAt, &subCamEye, &this->subCamUp);
this->subCamUp.z = this->subCamUp.x = 0.0f;
this->subCamUp.y = 1.0f;
- ShrinkWindow_SetLetterboxTarget(27);
+ ShrinkWindow_Letterbox_SetSizeTarget(27);
}
}
diff --git a/src/overlays/actors/ovl_Boss_04/z_boss_04.c b/src/overlays/actors/ovl_Boss_04/z_boss_04.c
index f26bc505f..8eb73d84d 100644
--- a/src/overlays/actors/ovl_Boss_04/z_boss_04.c
+++ b/src/overlays/actors/ovl_Boss_04/z_boss_04.c
@@ -5,6 +5,7 @@
*/
#include "z_boss_04.h"
+#include "z64shrink_window.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20)
@@ -399,7 +400,7 @@ void func_809EC568(Boss04* this, PlayState* play) {
if (this->subCamId != SUB_CAM_ID_DONE) {
Vec3f subCamAt;
- ShrinkWindow_SetLetterboxTarget(27);
+ ShrinkWindow_Letterbox_SetSizeTarget(27);
if (this->subCamAtOscillator != 0) {
this->subCamAtOscillator--;
}
diff --git a/src/overlays/actors/ovl_Boss_06/z_boss_06.c b/src/overlays/actors/ovl_Boss_06/z_boss_06.c
index 045a76995..3aadce42c 100644
--- a/src/overlays/actors/ovl_Boss_06/z_boss_06.c
+++ b/src/overlays/actors/ovl_Boss_06/z_boss_06.c
@@ -6,6 +6,7 @@
#include "prevent_bss_reordering.h"
#include "z_boss_06.h"
+#include "z64shrink_window.h"
#include "overlays/actors/ovl_En_Knight/z_en_knight.h"
#include "objects/gameplay_keep/gameplay_keep.h"
#include "objects/object_knight/object_knight.h"
@@ -339,7 +340,7 @@ void func_809F24C8(Boss06* this, PlayState* play) {
}
if (this->subCamId != SUB_CAM_ID_DONE) {
- ShrinkWindow_SetLetterboxTarget(27);
+ ShrinkWindow_Letterbox_SetSizeTarget(27);
Play_SetCameraAtEye(play, this->subCamId, &this->subCamAt, &this->subCamEye);
}
}
diff --git a/src/overlays/actors/ovl_Boss_07/z_boss_07.c b/src/overlays/actors/ovl_Boss_07/z_boss_07.c
index 9b988da18..923c838fc 100644
--- a/src/overlays/actors/ovl_Boss_07/z_boss_07.c
+++ b/src/overlays/actors/ovl_Boss_07/z_boss_07.c
@@ -5,6 +5,7 @@
*/
#include "z_boss_07.h"
+#include "z64shrink_window.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20)
diff --git a/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c b/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c
index 12da39288..10b72634a 100644
--- a/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c
+++ b/src/overlays/actors/ovl_Demo_Kankyo/z_demo_kankyo.c
@@ -508,7 +508,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex));
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);
for (i = 0; i < play->envCtx.unk_F2[3]; i++) {
worldPos.x = this->effects[i].posBase.x + this->effects[i].posOffset.x;
@@ -575,7 +575,7 @@ void DemoKakyo_DrawLostWoodsSparkle(Actor* thisx, PlayState* play2) {
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx),
G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
}
}
diff --git a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c
index b74c43940..2c8bf046f 100644
--- a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c
+++ b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.c
@@ -18,7 +18,6 @@ void func_80C229AC(DmTag* this, PlayState* play);
void func_80C229EC(DmTag* this, PlayState* play);
void func_80C229FC(DmTag* this, PlayState* play);
-#if 0
const ActorInit Dm_Tag_InitVars = {
ACTOR_DM_TAG,
ACTORCAT_ITEMACTION,
@@ -31,30 +30,236 @@ const ActorInit Dm_Tag_InitVars = {
(ActorFunc)NULL,
};
-#endif
+s32 D_80C22BF0[] = {
+ 0x0E28F00C,
+ 0x15090000,
+ 0x10000000,
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22350.s")
+s32 D_80C22BFC[] = {
+ 0x0900000E, 0x28F10C09, 0x00000E28, 0xF20C0900, 0x000E28F3, 0x0C090000, 0x0E28F40C,
+ 0x0900000E, 0x28F50C09, 0x00000E28, 0xF60C1511, 0x55040900, 0x00100000,
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22400.s")
+s32 D_80C22C30[] = {
+ 0x0E28EF0C,
+ 0x10000000,
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C2247C.s")
+Actor* func_80C22350(DmTag* this, PlayState* play, u8 actorCat, s16 actorId) {
+ Actor* foundActor = NULL;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C224D8.s")
+ while (true) {
+ foundActor = SubS_FindActor(play, foundActor, actorCat, actorId);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C227E8.s")
+ if ((foundActor == NULL) || (((this != (DmTag*)foundActor)) && (foundActor->update != NULL))) {
+ break;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C22880.s")
+ if (foundActor->next == NULL) {
+ foundActor = NULL;
+ break;
+ }
+ foundActor = foundActor->next;
+ }
+ return foundActor;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C2291C.s")
+s32 func_80C22400(DmTag* this, s16 arg1) {
+ s32 ret = false;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229AC.s")
+ if (ActorCutscene_GetCurrentIndex() == 0x7C) {
+ ActorCutscene_Stop(0x7C);
+ ActorCutscene_SetIntentToPlay(arg1);
+ } else if (ActorCutscene_GetCanPlayNext(arg1)) {
+ ActorCutscene_StartAndSetUnkLinkFields(arg1, &this->actor);
+ ret = true;
+ } else {
+ ActorCutscene_SetIntentToPlay(arg1);
+ }
+ return ret;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229EC.s")
+s16 func_80C2247C(DmTag* this, s32 arg1) {
+ s32 i;
+ s16 cs = this->actor.cutscene;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/func_80C229FC.s")
+ for (i = 0; i < arg1; i++) {
+ cs = ActorCutscene_GetAdditionalCutscene(cs);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Init.s")
+ return cs;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Destroy.s")
+s32 func_80C224D8(DmTag* this, PlayState* play) {
+ s32 pad;
+ Actor* sp30;
+ Actor* sp2C;
+ s16 sp2A = this->actor.cutscene;
+ s32 ret = false;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Dm_Tag/DmTag_Update.s")
+ sp30 = func_80C22350(this, play, ACTORCAT_NPC, ACTOR_EN_AN);
+ sp2C = func_80C22350(this, play, ACTORCAT_NPC, ACTOR_EN_AH);
+
+ switch (this->unk_1A4) {
+ case 0:
+ if (func_80C22400(this, sp2A)) {
+ if ((sp2C != NULL) && (sp2C->update != NULL)) {
+ Camera_SetTargetActor(Play_GetCamera(play, ActorCutscene_GetCurrentSubCamId(sp2A)), sp2C);
+ }
+ this->unk_1A4++;
+ ret = true;
+ }
+ break;
+
+ case 1:
+ if ((sp30 != NULL) && (sp30->update != NULL)) {
+ Camera_SetTargetActor(Play_GetCamera(play, ActorCutscene_GetCurrentSubCamId(func_80C2247C(this, 0))),
+ sp30);
+ }
+ this->unk_1A4++;
+ ret = true;
+ break;
+
+ case 2:
+ ActorCutscene_Stop(func_80C2247C(this, 0));
+ if (func_80C22400(this, func_80C2247C(this, 1))) {
+ this->unk_1A4++;
+ ret = true;
+ }
+ break;
+
+ case 3:
+ ActorCutscene_Stop(func_80C2247C(this, 1));
+ if (func_80C22400(this, func_80C2247C(this, 2))) {
+ this->unk_1A4++;
+ ret = true;
+ }
+ break;
+
+ case 4:
+ ActorCutscene_Stop(func_80C2247C(this, 2));
+ if (func_80C22400(this, func_80C2247C(this, 3))) {
+ this->unk_1A4++;
+ ret = true;
+ }
+ break;
+
+ case 5:
+ ActorCutscene_Stop(func_80C2247C(this, 3));
+ if (func_80C22400(this, func_80C2247C(this, 4))) {
+ this->unk_1A4++;
+ ret = true;
+ }
+ break;
+
+ case 6:
+ func_800B7298(play, &this->actor, 7);
+ play->nextEntrance = ENTRANCE(STOCK_POT_INN, 5);
+ gSaveContext.nextCutsceneIndex = 0;
+ play->transitionTrigger = TRANS_TRIGGER_START;
+ play->transitionType = TRANS_TYPE_02;
+ gSaveContext.nextTransitionType = TRANS_TYPE_06;
+ this->unk_1A4++;
+ break;
+ }
+ return ret;
+}
+
+s32 func_80C227E8(DmTag* this, PlayState* play) {
+ if (this->unk_1A4 == 0) {
+ func_800B7298(play, &this->actor, 7);
+ play->nextEntrance = ENTRANCE(STOCK_POT_INN, 4);
+ gSaveContext.nextCutsceneIndex = 0;
+ play->transitionTrigger = TRANS_TRIGGER_START;
+ play->transitionType = TRANS_TYPE_02;
+ gSaveContext.nextTransitionType = TRANS_TYPE_06;
+ this->unk_1A4++;
+ }
+ return false;
+}
+
+s32* func_80C22880(DmTag* this, PlayState* play) {
+ s32 time;
+
+ switch (this->unk_18E) {
+ case 1:
+ time = gSaveContext.save.time - 0x3FFC;
+ if ((time >= 0xA54B) && (time < 0xB54A) && (gSaveContext.save.day == 2)) {
+ this->msgEventCallback = func_80C227E8;
+ return D_80C22BF0;
+ }
+ return D_80C22C30;
+ case 2:
+ this->msgEventCallback = func_80C224D8;
+ return D_80C22BFC;
+ }
+ return NULL;
+}
+
+s32 func_80C2291C(DmTag* this, PlayState* play) {
+ s32 ret = false;
+
+ if (this->unk_18C & 7) {
+ if (Actor_ProcessTalkRequest(&this->actor, &play->state)) {
+ this->unk_18C |= 8;
+ SubS_UpdateFlags(&this->unk_18C, 0, 7);
+ this->msgEventScript = func_80C22880(this, play);
+ this->actionFunc = func_80C229FC;
+ ret = true;
+ }
+ }
+ return ret;
+}
+
+void func_80C229AC(DmTag* this, PlayState* play) {
+ SubS_UpdateFlags(&this->unk_18C, 3, 7);
+ this->actor.flags |= ACTOR_FLAG_1;
+}
+
+void func_80C229EC(DmTag* this, PlayState* play) {
+}
+
+void func_80C229FC(DmTag* this, PlayState* play) {
+ if (func_8010BF58(&this->actor, play, this->msgEventScript, this->msgEventCallback, &this->msgEventArg4)) {
+ this->actionFunc = func_80C229AC;
+ }
+}
+
+void DmTag_Init(Actor* thisx, PlayState* play) {
+ DmTag* this = (DmTag*)thisx;
+ Player* player = GET_PLAYER(play);
+
+ if (gSaveContext.save.weekEventReg[85] & 4) {
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
+
+ if ((play->sceneId == SCENE_YADOYA) && (play->curSpawn == 4)) {
+ player->stateFlags1 |= PLAYER_STATE1_20;
+ this->unk_18E = 2;
+ this->unk_18C = 0;
+ SubS_UpdateFlags(&this->unk_18C, 4, 7);
+ this->actor.flags &= ~ACTOR_FLAG_1;
+ this->actionFunc = func_80C229EC;
+ } else if (this->actor.room == 2) {
+ Actor_MarkForDeath(&this->actor);
+ } else {
+ this->actor.targetMode = 1;
+ this->unk_18E = 1;
+ this->unk_18C = 0;
+ this->actionFunc = func_80C229AC;
+ }
+}
+
+void DmTag_Destroy(Actor* thisx, PlayState* play) {
+}
+
+void DmTag_Update(Actor* thisx, PlayState* play) {
+ DmTag* this = THIS;
+
+ func_80C2291C(this, play);
+ this->actionFunc(this, play);
+ func_8013C964(&this->actor, play, 40.0f, fabsf(this->actor.playerHeightRel) + 1.0f, 0, this->unk_18C & 7);
+ Actor_SetFocus(&this->actor, 0.0f);
+}
diff --git a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h
index fda9397c7..d68cd38d4 100644
--- a/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h
+++ b/src/overlays/actors/ovl_Dm_Tag/z_dm_tag.h
@@ -6,12 +6,19 @@
struct DmTag;
typedef void (*DmTagActionFunc)(struct DmTag*, PlayState*);
+typedef s32 (*DmTagMsgEventFunc)(struct DmTag*, PlayState*);
typedef struct DmTag {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x44];
+ /* 0x144 */ UNK_TYPE1 pad144[0x44];
/* 0x188 */ DmTagActionFunc actionFunc;
- /* 0x18C */ char unk_18C[0x20];
+ /* 0x18C */ u16 unk_18C;
+ /* 0x18E */ u8 unk_18E;
+ /* 0x190 */ s32* msgEventScript;
+ /* 0x194 */ s32 msgEventArg4;
+ /* 0x198 */ UNK_TYPE1 pad198[0xC];
+ /* 0x1A4 */ s16 unk_1A4;
+ /* 0x1A8 */ DmTagMsgEventFunc msgEventCallback;
} DmTag; // size = 0x1AC
extern const ActorInit Dm_Tag_InitVars;
diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c
index b2d896a14..c517ad007 100644
--- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c
+++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.c
@@ -71,7 +71,7 @@ void EffDust_Init(Actor* thisx, PlayState* play) {
this->dz = 0.8f;
this->scalingFactor = 0.5f;
break;
- case EFF_DUST_TYPE_2:
+ case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE:
case EFF_DUST_TYPE_3:
this->actionFunc = func_80919230;
this->actor.draw = func_809199FC;
@@ -203,7 +203,7 @@ void func_80919230(EffDust* this, PlayState* play) {
if (this->distanceTraveled[i] >= 1.0f) {
theta = randPlusMinusPoint5Scaled(0x10000);
switch (this->actor.params) {
- case EFF_DUST_TYPE_2:
+ case EFF_DUST_TYPE_SPIN_ATTACK_CHARGE:
this->initialPositions[i].x = (Rand_ZeroOne() * 4500.0f) + 700.0f;
if (this->initialPositions[i].x > 3000.0f) {
this->initialPositions[i].y = (3000.0f * Rand_ZeroOne()) * Math_SinS(theta);
diff --git a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h
index ec864ea4d..d73b5ce0e 100644
--- a/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h
+++ b/src/overlays/actors/ovl_Eff_Dust/z_eff_dust.h
@@ -24,7 +24,7 @@ typedef struct EffDust {
typedef enum {
/* 0x0 */ EFF_DUST_TYPE_0,
/* 0x1 */ EFF_DUST_TYPE_1,
- /* 0x2 */ EFF_DUST_TYPE_2,
+ /* 0x2 */ EFF_DUST_TYPE_SPIN_ATTACK_CHARGE,
/* 0x3 */ EFF_DUST_TYPE_3,
/* 0x4 */ EFF_DUST_TYPE_4,
/* 0x5 */ EFF_DUST_TYPE_5
diff --git a/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c b/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c
index 5a3ce9cf8..4ad558a0a 100644
--- a/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c
+++ b/src/overlays/actors/ovl_En_Bsb/z_en_bsb.c
@@ -6,6 +6,7 @@
#include "z_en_bsb.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_2000000)
diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c
index 0d3612145..98e9d2b8f 100644
--- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c
+++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.c
@@ -5,6 +5,7 @@
*/
#include "z_en_door_etc.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_10)
@@ -14,7 +15,11 @@ void EnDoorEtc_Init(Actor* thisx, PlayState* play);
void EnDoorEtc_Destroy(Actor* thisx, PlayState* play);
void EnDoorEtc_Update(Actor* thisx, PlayState* play);
-#if 0
+void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play);
+void func_80AC21A0(EnDoorEtc* this, PlayState* play);
+void func_80AC2354(EnDoorEtc* this, PlayState* play);
+void EnDoorEtc_Draw(Actor* thisx, PlayState* play);
+
const ActorInit En_Door_Etc_InitVars = {
ACTOR_EN_DOOR_ETC,
ACTORCAT_DOOR,
@@ -27,42 +32,219 @@ const ActorInit En_Door_Etc_InitVars = {
(ActorFunc)NULL,
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_80AC25A0 = {
- { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK0, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK0,
+ { 0x00000000, 0x00, 0x00 },
+ { 0x00000000, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 100, 40, 0, { 0, 0, 0 } },
};
-// static InitChainEntry sInitChain[] = {
-static InitChainEntry D_80AC2634[] = {
+typedef struct {
+ /* 0x0 */ s16 sceneId;
+ /* 0x2 */ u8 dListIndex;
+ /* 0x4 */ s16 objectId;
+} EnDoorEtcInfo; // size = 0x6
+
+EnDoorEtcInfo sObjInfo[] = {
+ { SCENE_MITURIN, 1, OBJECT_NUMA_OBJ },
+ { -1, 0, GAMEPLAY_KEEP },
+ { -1, 13, GAMEPLAY_FIELD_KEEP },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+ { 0, 0, OBJECT_UNSET_0 },
+};
+
+static InitChainEntry sInitChain[] = {
ICHAIN_U8(targetMode, 0, ICHAIN_CONTINUE),
ICHAIN_F32(uncullZoneForward, 4000, ICHAIN_CONTINUE),
ICHAIN_U16(shape.rot.x, 0, ICHAIN_CONTINUE),
ICHAIN_U16(shape.rot.z, 0, ICHAIN_STOP),
};
-#endif
+void EnDoorEtc_Init(Actor* thisx, PlayState* play2) {
+ PlayState* play = play2;
+ s32 objectIndex;
+ EnDoorEtcInfo* objectInfo = sObjInfo;
+ s32 i;
+ EnDoorEtc* this = THIS;
-extern ColliderCylinderInit D_80AC25A0;
-extern InitChainEntry D_80AC2634[];
+ Actor_ProcessInitChain(&this->actor, sInitChain);
+ Actor_SetScale(&this->actor, 0.01f);
+ this->actor.shape.rot.x = -0x4000;
+ this->angle = 0;
+ for (i = 0; i < 15; i++, objectInfo++) {
+ if (play->sceneId == objectInfo->sceneId) {
+ break;
+ }
+ }
+ if ((i >= 15) && (Object_GetIndex(&play->objectCtx, GAMEPLAY_FIELD_KEEP) >= 0)) {
+ objectInfo++;
+ }
+ objectIndex = Object_GetIndex(&play->objectCtx, objectInfo->objectId);
+ if (objectIndex < 0) {
+ Actor_MarkForDeath(&this->actor);
+ } else {
+ this->objectIndex = objectIndex;
+ this->dListIndex = objectInfo->dListIndex;
+ if (this->actor.objBankIndex == this->objectIndex) {
+ EnDoorEtc_WaitForObject(this, play);
+ } else {
+ this->actionFunc = EnDoorEtc_WaitForObject;
+ }
+ }
+ Collider_InitCylinder(play, &this->collider);
+ Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
+ this->actor.colChkInfo.mass = MASS_IMMOVABLE;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Init.s")
+void EnDoorEtc_Destroy(Actor* thisx, PlayState* play) {
+ EnDoorEtc* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Destroy.s")
+ Collider_DestroyCylinder(play, &this->collider);
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2044.s")
+/**
+ * Calculates if the distance between `a` and `b` is greater than distance `c`
+ */
+s32 EnDoorEtc_IsDistanceGreater(Vec3f* a, Vec3f* b, f32 c) {
+ f32 dx = b->x - a->x;
+ f32 dy = b->y - a->y;
+ f32 dz = b->z - a->z;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC20A8.s")
+ return ((SQ(dx) + SQ(dy) + SQ(dz)) < SQ(c));
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2118.s")
+void EnDoorEtc_WaitForObject(EnDoorEtc* this, PlayState* play) {
+ if (Object_IsLoaded(&play->objectCtx, this->objectIndex)) {
+ this->actor.flags &= ~ACTOR_FLAG_10;
+ this->actor.objBankIndex = this->objectIndex;
+ this->actionFunc = func_80AC2354;
+ this->actor.draw = EnDoorEtc_Draw;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2154.s")
+void func_80AC2118(EnDoorEtc* this, PlayState* play) {
+ if (this->angle < 0) {
+ this->angle += 0x100;
+ } else {
+ this->angle = 0;
+ this->actionFunc = func_80AC21A0;
+ this->unk_1F4 &= ~1;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC21A0.s")
+void func_80AC2154(EnDoorEtc* this, PlayState* play) {
+ if (this->timer > 0) {
+ this->timer--;
+ } else if (this->angle > -0x4000) {
+ this->angle -= 0x800;
+ } else {
+ this->angle = -0x4000;
+ this->actionFunc = func_80AC2118;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC2354.s")
+void func_80AC21A0(EnDoorEtc* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+ Vec3f playerOffsetFromDoor;
+ s32 pad;
+ s16 yawDiff;
+ s32 yawDiffAbs;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/EnDoorEtc_Update.s")
+ Actor_OffsetOfPointInActorCoords(&this->actor, &playerOffsetFromDoor, &player->actor.world.pos);
+ if (this->unk_1A1 == 0) {
+ if ((!Player_InCsMode(play)) &&
+ ((fabsf(playerOffsetFromDoor.y) < 20.0f) && fabsf(playerOffsetFromDoor.x) < 20.0f) &&
+ (fabsf(playerOffsetFromDoor.z) < 50.0f)) {
+ yawDiff = player->actor.shape.rot.y - this->actor.shape.rot.y;
+ if (playerOffsetFromDoor.z > 0.0f) {
+ yawDiff = 0x8000 - yawDiff;
+ }
+ yawDiffAbs = ABS_ALT(yawDiff);
+ if (yawDiffAbs < 0x3000) {
+ player->doorDirection = (playerOffsetFromDoor.z >= 0.0f) ? 1.0f : -1.0f;
+ player->doorActor = &this->actor;
+ player->doorType = -1;
+ }
+ }
+ }
+ if ((this->actor.textId == 0x239B) && Flags_GetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor))) {
+ Flags_UnsetSwitch(play, ENDOORETC_GET_SWITCHFLAG(&this->actor));
+ this->actionFunc = func_80AC2154;
+ this->actor.textId = 0x1800; // "It won't budge!"
+ this->unk_1F4 |= 1;
+ this->timer = 0x5A;
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Door_Etc/func_80AC24A8.s")
+void func_80AC2354(EnDoorEtc* this, PlayState* play) {
+ Actor* door = play->actorCtx.actorLists[ACTORCAT_DOOR].first;
+
+ while (door != NULL) {
+ if ((door->id != ACTOR_EN_DOOR) ||
+ !EnDoorEtc_IsDistanceGreater(&door->world.pos, &this->actor.world.pos, 10.0f)) {
+ door = door->next;
+ } else {
+ this->actor.world.pos.x = door->world.pos.x;
+ this->actor.world.pos.y = door->world.pos.y;
+ this->actor.world.pos.z = door->world.pos.z;
+ this->actor.shape.rot.y = door->shape.rot.y;
+ this->actor.world.rot.y = door->world.rot.y;
+ Actor_MarkForDeath(door);
+ this->actionFunc = func_80AC21A0;
+ this->actor.textId = 0x239B;
+ Actor_SetFocus(&this->actor, 70.0f);
+ break;
+ }
+ }
+}
+
+void EnDoorEtc_Update(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnDoorEtc* this = THIS;
+
+ this->actionFunc(this, play);
+ if (this->unk_1F4 & 1) {
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
+ }
+}
+
+void EnDoorEtc_Draw(Actor* thisx, PlayState* play) {
+ EnDoorEtc* this = THIS;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ func_8012C28C(play->state.gfxCtx);
+ Matrix_Translate(-2900.0f, 0.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_RotateZS(this->angle, MTXMODE_APPLY);
+ gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_OPA_DISP++, gDoorLeftDL);
+ gSPDisplayList(POLY_OPA_DISP++, gDoorRightDL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h
index 18d525f44..cbcdf2f54 100644
--- a/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h
+++ b/src/overlays/actors/ovl_En_Door_Etc/z_en_door_etc.h
@@ -5,11 +5,20 @@
struct EnDoorEtc;
+#define ENDOORETC_GET_SWITCHFLAG(thisx) ((thisx)->params & 0x7F)
+
typedef void (*EnDoorEtcActionFunc)(struct EnDoorEtc*, PlayState*);
typedef struct EnDoorEtc {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0xB4];
+ /* 0x144 */ char pad_144[0x5D];
+ /* 0x1A1 */ u8 unk_1A1;
+ /* 0x1A2 */ s8 objectIndex;
+ /* 0x1A3 */ u8 dListIndex; // Never read, inferred from ovl_En_Door
+ /* 0x1A4 */ s16 angle;
+ /* 0x1A6 */ s16 timer;
+ /* 0x1A8 */ ColliderCylinder collider;
+ /* 0x1F4 */ u8 unk_1F4;
/* 0x1F8 */ EnDoorEtcActionFunc actionFunc;
} EnDoorEtc; // size = 0x1FC
diff --git a/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c b/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c
index d771f3511..b7c698376 100644
--- a/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c
+++ b/src/overlays/actors/ovl_En_Encount2/z_en_encount2.c
@@ -279,14 +279,14 @@ void EnEncount2_DrawEffects(EnEncount2* this, PlayState* play) {
Matrix_Scale(sPtr->scale, sPtr->scale, sPtr->scale, MTXMODE_APPLY);
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex));
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255);
gDPSetEnvColor(POLY_XLU_DISP++, 250, 180, 255, sPtr->alpha);
Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
Matrix_RotateZF(DEGF_TO_RADF(play->state.frames * 20.0f), MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
}
}
CLOSE_DISPS(gfxCtx);
diff --git a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c
index 8bd1b7e0e..baa65bfa3 100644
--- a/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c
+++ b/src/overlays/actors/ovl_En_Fishing/z_en_fishing.c
@@ -6,6 +6,7 @@
#include "z_en_fishing.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#include "objects/object_fish/object_fish.h"
#include "overlays/actors/ovl_En_Kanban/z_en_kanban.h"
@@ -5170,7 +5171,7 @@ void EnFishing_UpdateOwner(Actor* thisx, PlayState* play2) {
sSubCamVelFactor = 0.0f;
// fallthrough
case 2:
- ShrinkWindow_SetLetterboxTarget(27);
+ ShrinkWindow_Letterbox_SetSizeTarget(27);
spFC.x = sLurePos.x - player->actor.world.pos.x;
spFC.z = sLurePos.z - player->actor.world.pos.z;
diff --git a/src/overlays/actors/ovl_En_Fz/z_en_fz.c b/src/overlays/actors/ovl_En_Fz/z_en_fz.c
index 198166b00..58d5a6f5f 100644
--- a/src/overlays/actors/ovl_En_Fz/z_en_fz.c
+++ b/src/overlays/actors/ovl_En_Fz/z_en_fz.c
@@ -241,10 +241,10 @@ void EnFz_Destroy(Actor* thisx, PlayState* play) {
Collider_DestroyCylinder(play, &this->collider3);
if ((this->actor.parent != NULL) && (this->unk_BC4 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ) &&
- (this->actor.parent->update != NULL) && (((EnWiz*)this->actor.parent)->unk_448 != 0)) {
+ (this->actor.parent->update != NULL) && (((EnWiz*)this->actor.parent)->freezard != NULL)) {
EnWiz* wiz = (EnWiz*)this->actor.parent;
- wiz->unk_448 = 0;
+ wiz->freezard = NULL;
}
}
diff --git a/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c b/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c
index f9085e825..0f016f300 100644
--- a/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c
+++ b/src/overlays/actors/ovl_En_Hanabi/z_en_hanabi.c
@@ -146,7 +146,7 @@ void func_80B22FA8(EnHanabiStruct* arg0, PlayState* play2) {
POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex));
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB10);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);
sp53 = 0xFF;
if (sp53) {}
@@ -181,7 +181,7 @@ void func_80B22FA8(EnHanabiStruct* arg0, PlayState* play2) {
D_80B23C2C[arg0->unk_02 + 2], 255);
}
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_07AB58);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
}
}
diff --git a/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c b/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c
index fd671c66b..46a1df4f8 100644
--- a/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c
+++ b/src/overlays/actors/ovl_En_Jc_Mato/z_en_jc_mato.c
@@ -145,15 +145,14 @@ void EnJcMato_Update(Actor* thisx, PlayState* play) {
}
}
-static Vec3f movement = { 0.0f, -2500.0f, 0.0f };
-
void EnJcMato_Draw(Actor* thisx, PlayState* play) {
+ static Vec3f sOffset = { 0.0f, -2500.0f, 0.0f };
EnJcMato* this = THIS;
OPEN_DISPS(play->state.gfxCtx);
func_8012C28C(play->state.gfxCtx);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_000390);
- Matrix_MultVec3f(&movement, &this->pos);
+ gSPDisplayList(POLY_OPA_DISP++, gKoumeTargetDL);
+ Matrix_MultVec3f(&sOffset, &this->pos);
CLOSE_DISPS(play->state.gfxCtx);
}
diff --git a/src/overlays/actors/ovl_En_Knight/z_en_knight.c b/src/overlays/actors/ovl_En_Knight/z_en_knight.c
index 095ca5a98..17d0e3752 100644
--- a/src/overlays/actors/ovl_En_Knight/z_en_knight.c
+++ b/src/overlays/actors/ovl_En_Knight/z_en_knight.c
@@ -5,6 +5,7 @@
*/
#include "z_en_knight.h"
+#include "z64shrink_window.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20)
diff --git a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c
index 4ed5b82a0..fdf3cc9ac 100644
--- a/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c
+++ b/src/overlays/actors/ovl_En_Kusa2/z_en_kusa2.c
@@ -4,7 +4,6 @@
* Description: Keaton grass
*/
-#include "prevent_bss_reordering.h"
#include "z_en_kusa2.h"
#include "objects/gameplay_field_keep/gameplay_field_keep.h"
#include "objects/gameplay_keep/gameplay_keep.h"
diff --git a/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c b/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c
index de053c46a..6fd949feb 100644
--- a/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c
+++ b/src/overlays/actors/ovl_En_Look_Nuts/z_en_look_nuts.c
@@ -5,6 +5,7 @@
*/
#include "z_en_look_nuts.h"
+#include "overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h"
#define FLAGS (ACTOR_FLAG_80000000)
@@ -340,13 +341,14 @@ void EnLookNuts_Update(Actor* thisx, PlayState* play) {
Matrix_MultVec3f(&effectVelOffset, &effectVel);
Matrix_Pop();
if (!this->isPlayerDetected) {
- s16 drawFlag = 1;
+ s16 effectFlags = SOLDERSRCHBALL_INVISIBLE;
+
if (gSaveContext.save.isNight) {
- drawFlag = 0;
+ effectFlags = 0;
}
if (Player_GetMask(play) != PLAYER_MASK_STONE) {
EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->isPlayerDetected,
- drawFlag);
+ effectFlags);
}
}
diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
index b509cf789..fbfb17040 100644
--- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
+++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.c
@@ -6,6 +6,8 @@
#include "z_en_m_thunder.h"
#include "z64rumble.h"
+#include "overlays/actors/ovl_Eff_Dust/z_eff_dust.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_10)
@@ -16,7 +18,17 @@ void EnMThunder_Destroy(Actor* thisx, PlayState* play);
void EnMThunder_Update(Actor* thisx, PlayState* play);
void EnMThunder_Draw(Actor* thisx, PlayState* play);
-#if 0
+void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play);
+
+void EnMThunder_AdjustLights(PlayState* play, f32 arg1);
+
+void EnMThunder_Charge(EnMThunder* this, PlayState* play);
+void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play);
+void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play);
+void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play);
+
+#define ENMTHUNDER_TYPE_MAX 4
+
const ActorInit En_M_Thunder_InitVars = {
ACTOR_EN_M_THUNDER,
ACTORCAT_ITEMACTION,
@@ -29,39 +41,533 @@ const ActorInit En_M_Thunder_InitVars = {
(ActorFunc)EnMThunder_Draw,
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_808B7120 = {
- { COLTYPE_NONE, AT_ON | AT_TYPE_PLAYER, AC_NONE, OC1_NONE, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK2, { 0x01000000, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_ON | TOUCH_SFX_NONE, BUMP_ON, OCELEM_ON, },
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_NONE,
+ AT_ON | AT_TYPE_PLAYER,
+ AC_NONE,
+ OC1_NONE,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK2,
+ { 0x01000000, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_ON | TOUCH_SFX_NONE,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 200, 200, 0, { 0, 0, 0 } },
};
-#endif
+static u8 sDamages[] = {
+ 1, 2, 3, 4, // Regular
+ 1, 2, 3, 4, // Great Spin
+};
-extern ColliderCylinderInit D_808B7120;
+static u16 sChargingSfxIds[] = {
+ NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SPIN_GREAT
+ NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SPIN_REGULAR
+ NA_SE_IT_ROLLING_CUT_LV2, // ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT
+ NA_SE_IT_ROLLING_CUT_LV1, // ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B53C0.s")
+static f32 sScales[] = { 0.1f, 0.15f, 0.2f, 0.25f, 0.3f, 0.25f, 0.2f, 0.15f, 0.0f };
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Init.s")
+typedef enum {
+ /* 0 */ ENMTHUNDER_SUBTYPE_SPIN_GREAT,
+ /* 1 */ ENMTHUNDER_SUBTYPE_SPIN_REGULAR,
+ /* 2 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT,
+ /* 3 */ ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR
+} EnMThunderSubType;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Destroy.s")
+void EnMThunder_UnkType_Setup(EnMThunder* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5890.s")
+ this->actor.update = EnMThunder_UnkType_Update;
+ this->isCharging = false;
+ this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR;
+ this->scaleTarget = 2;
+ this->actionFunc = EnMThunder_UnkType_Attack;
+ this->timer = 8;
+ this->lightColorFrac = 1.0f;
+ AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ this->actor.child = NULL;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B58CC.s")
+void EnMThunder_Init(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnMThunder* this = THIS;
+ Player* player = GET_PLAYER(play);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5984.s")
+ Collider_InitCylinder(play, &this->collider);
+ Collider_SetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
+ this->type = ENMTHUNDER_GET_TYPE(&this->actor);
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, 255, 255, 255, 0);
+ this->lightNode = LightContext_InsertLight(play, &play->lightCtx, &this->lightInfo);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5EEC.s")
+ if (this->type == ENMTHUNDER_TYPE_UNK) {
+ EnMThunder_UnkType_Setup(this, play);
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B5F68.s")
+ this->collider.dim.radius = 0;
+ this->collider.dim.height = 40;
+ this->collider.dim.yShift = -20;
+ this->timer = 8;
+ this->scroll = 0.0f;
+ this->actor.world.pos = player->bodyPartsPos[0];
+ this->lightColorFrac = 0.0f;
+ this->adjustLightsArg1 = 0.0f;
+ this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000;
+ this->actor.shape.rot.x = -this->actor.world.rot.x;
+ this->actor.room = -1;
+ Actor_SetScale(&this->actor, 0.1f);
+ this->isCharging = false;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B60D4.s")
+ if (player->stateFlags2 & PLAYER_STATE2_20000) {
+ if (!gSaveContext.save.playerData.isMagicAcquired || (gSaveContext.magicState != MAGIC_STATE_IDLE) ||
+ ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) &&
+ !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_NOW))) {
+ AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B6310.s")
+ player->stateFlags2 &= ~PLAYER_STATE2_20000;
+ this->isCharging = false;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Update.s")
+ if (gSaveContext.save.weekEventReg[23] & 2) {
+ player->unk_B08[0] = 1.0f;
+ this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX];
+ this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT;
+ if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) {
+ this->scaleTarget = 6;
+ } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) {
+ this->scaleTarget = 4;
+ } else {
+ this->scaleTarget = 3;
+ }
+ } else {
+ player->unk_B08[0] = 0.5f;
+ this->collider.info.toucher.damage = sDamages[this->type];
+ this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR;
+ if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) {
+ this->scaleTarget = 4;
+ } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) {
+ this->scaleTarget = 3;
+ } else {
+ this->scaleTarget = 2;
+ }
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/func_808B65BC.s")
+ if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) {
+ this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT;
+ this->actionFunc = EnMThunder_SwordBeam_Attack;
+ this->timer = 1;
+ this->scaleTarget = 12;
+ this->collider.info.toucher.dmgFlags = DMG_SWORD_BEAM;
+ this->collider.info.toucher.damage = 3;
+ } else {
+ this->actionFunc = EnMThunder_Spin_Attack;
+ this->timer = 8;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_M_Thunder/EnMThunder_Draw.s")
+ AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT_LV1, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+
+ this->lightColorFrac = 1.0f;
+ } else {
+ this->actionFunc = EnMThunder_Charge;
+ }
+
+ this->actor.child = NULL;
+}
+
+void EnMThunder_Destroy(Actor* thisx, PlayState* play) {
+ EnMThunder* this = THIS;
+
+ if (this->isCharging) {
+ Magic_Reset(play);
+ }
+
+ Collider_DestroyCylinder(play, &this->collider);
+ EnMThunder_AdjustLights(play, 0.0f);
+ LightContext_RemoveLight(play, &play->lightCtx, this->lightNode);
+}
+
+void EnMThunder_AdjustLights(PlayState* play, f32 arg1) {
+ func_800FD2B4(play, arg1, 850.0f, 0.2f, 0.0f);
+}
+
+void EnMThunder_Spin_AttackNoMagic(EnMThunder* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ if (player->stateFlags2 & PLAYER_STATE2_20000) {
+ if (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H) {
+ AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ }
+ Actor_MarkForDeath(&this->actor);
+ } else if (!(player->stateFlags1 & PLAYER_STATE1_1000)) {
+ Actor_MarkForDeath(&this->actor);
+ }
+}
+
+void EnMThunder_Charge(EnMThunder* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+ Actor* child = this->actor.child;
+
+ this->unk1B0 = player->unk_B08[0];
+ this->actor.world.pos = player->bodyPartsPos[0];
+ this->actor.shape.rot.y = player->actor.shape.rot.y + 0x8000;
+
+ if (!this->isCharging && (player->unk_B08[0] >= 0.1f)) {
+ if ((gSaveContext.magicState != MAGIC_STATE_IDLE) ||
+ ((ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) &&
+ !Magic_Consume(play, ENMTHUNDER_GET_MAGIC_COST(&this->actor), MAGIC_CONSUME_WAIT_PREVIEW))) {
+ EnMThunder_Spin_AttackNoMagic(this, play);
+ this->actionFunc = EnMThunder_Spin_AttackNoMagic;
+ this->chargingAlpha = 0;
+ this->adjustLightsArg1 = 0.0f;
+ this->lightColorFrac = 0.0f;
+ return;
+ }
+ this->isCharging = true;
+ }
+
+ if (player->unk_B08[0] >= 0.1f) {
+ Rumble_Request(0.0f, (s32)(player->unk_B08[0] * 150.0f), 2, (s32)(player->unk_B08[0] * 150.0f));
+ }
+
+ if (player->stateFlags2 & PLAYER_STATE2_20000) {
+ if ((child != NULL) && (child->update != NULL)) {
+ child->parent = NULL;
+ }
+
+ if (player->unk_B08[0] <= 0.15f) {
+ if ((player->unk_B08[0] >= 0.1f) && (player->meleeWeaponAnimation >= PLAYER_MWA_SPIN_ATTACK_1H)) {
+ AudioSfx_PlaySfx(NA_SE_IT_ROLLING_CUT, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ AudioSfx_PlaySfx(NA_SE_IT_SWORD_SWING_HARD, &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+ }
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
+
+ player->stateFlags2 &= ~PLAYER_STATE2_20000;
+
+ if (ENMTHUNDER_GET_MAGIC_COST(&this->actor) != 0) {
+ gSaveContext.magicState = MAGIC_STATE_CONSUME_SETUP;
+ }
+
+ if (player->unk_B08[0] < 0.85f) {
+ this->collider.info.toucher.damage = sDamages[this->type];
+ this->subtype = ENMTHUNDER_SUBTYPE_SPIN_REGULAR;
+ if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) {
+ this->scaleTarget = 4;
+ } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) {
+ this->scaleTarget = 3;
+ } else {
+ this->scaleTarget = 2;
+ }
+ } else {
+ this->collider.info.toucher.damage = sDamages[this->type + ENMTHUNDER_TYPE_MAX];
+ this->subtype = ENMTHUNDER_SUBTYPE_SPIN_GREAT;
+ if (this->type == ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD) {
+ this->scaleTarget = 6;
+ } else if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) {
+ this->scaleTarget = 4;
+ } else {
+ this->scaleTarget = 3;
+ }
+ }
+
+ if (player->meleeWeaponAnimation < PLAYER_MWA_SPIN_ATTACK_1H) {
+ this->subtype += ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT;
+ this->actionFunc = EnMThunder_SwordBeam_Attack;
+ this->timer = 1;
+ } else {
+ this->actionFunc = EnMThunder_Spin_Attack;
+ this->timer = 8;
+ }
+
+ AudioSfx_PlaySfx(sChargingSfxIds[this->subtype], &player->actor.projectedPos, 4, &gSfxDefaultFreqAndVolScale,
+ &gSfxDefaultFreqAndVolScale, &gSfxDefaultReverb);
+
+ this->lightColorFrac = 1.0f;
+
+ return;
+ }
+
+ if (!(player->stateFlags1 & PLAYER_STATE1_1000)) {
+ if (this->actor.child != NULL) {
+ this->actor.child->parent = NULL;
+ }
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
+
+ if (player->unk_B08[0] > 0.15f) {
+ this->chargingAlpha = 255;
+ if (this->actor.child == NULL) {
+ Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EFF_DUST, this->actor.world.pos.x,
+ this->actor.world.pos.y, this->actor.world.pos.z, 0, this->actor.shape.rot.y, 0,
+ EFF_DUST_TYPE_SPIN_ATTACK_CHARGE);
+ }
+ this->adjustLightsArg1 += (((player->unk_B08[0] - 0.15f) * 1.5f) - this->adjustLightsArg1) * 0.5f;
+ } else if (player->unk_B08[0] > .1f) {
+ this->chargingAlpha = (s32)((player->unk_B08[0] - .1f) * 255.0f * 20.0f);
+ this->lightColorFrac = (player->unk_B08[0] - .1f) * 10.0f;
+ } else {
+ this->chargingAlpha = 0;
+ }
+
+ if (player->unk_B08[0] > 0.85f) {
+ func_8019F900(&player->actor.projectedPos, 2);
+ } else if (player->unk_B08[0] > 0.15f) {
+ func_8019F900(&player->actor.projectedPos, 1);
+ } else if (player->unk_B08[0] > 0.1f) {
+ func_8019F900(&player->actor.projectedPos, 0);
+ }
+
+ if (Play_InCsMode(play)) {
+ Actor_MarkForDeath(&this->actor);
+ }
+}
+
+void func_808B5EEC(EnMThunder* this, PlayState* play) {
+ if (this->timer < 2) {
+ if (this->chargingAlpha < 40) {
+ this->chargingAlpha = 0;
+ } else {
+ this->chargingAlpha -= 40;
+ }
+ }
+
+ this->scroll += 2.0f * this->alphaFrac;
+
+ if (this->adjustLightsArg1 < this->lightColorFrac) {
+ this->adjustLightsArg1 = F32_LERPIMP(this->adjustLightsArg1, this->lightColorFrac, 0.1f);
+ } else {
+ this->adjustLightsArg1 = this->lightColorFrac;
+ }
+}
+
+void EnMThunder_Spin_Attack(EnMThunder* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+
+ if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) {
+ Actor_MarkForDeath(&this->actor);
+ } else {
+ Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f);
+ Actor_SetScale(&this->actor, this->actor.scale.x);
+ this->collider.dim.radius = this->actor.scale.x * 30.0f;
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base);
+ }
+
+ if (this->timer > 0) {
+ this->actor.world.pos.x = player->bodyPartsPos[0].x;
+ this->actor.world.pos.z = player->bodyPartsPos[0].z;
+ this->timer--;
+ }
+
+ if (this->lightColorFrac > (6.0f / 10.0f)) {
+ this->alphaFrac = 1.0f;
+ } else {
+ this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f);
+ }
+
+ func_808B5EEC(this, play);
+
+ if (Play_InCsMode(play)) {
+ Actor_MarkForDeath(&this->actor);
+ }
+}
+
+void EnMThunder_SwordBeam_Attack(EnMThunder* this, PlayState* play) {
+ s32 pad[2];
+ f32 sp2C;
+
+ if (this->lightColorFrac > (9.0f / 10.0f)) {
+ this->alphaFrac = 1.0f;
+ } else {
+ this->alphaFrac = this->lightColorFrac * (10.0f / 9.0f);
+ }
+
+ if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.05f)) {
+ Actor_MarkForDeath(&this->actor);
+ } else {
+ sp2C = -80.0f * Math_CosS(this->actor.world.rot.x);
+
+ this->actor.world.pos.x += sp2C * Math_SinS(this->actor.shape.rot.y);
+ this->actor.world.pos.z += sp2C * Math_CosS(this->actor.shape.rot.y);
+ this->actor.world.pos.y += -80.0f * Math_SinS(this->actor.world.rot.x);
+
+ Math_SmoothStepToF(&this->actor.scale.x, this->scaleTarget, 0.6f, 2.0f, 0.0f);
+ Actor_SetScale(&this->actor, this->actor.scale.x);
+
+ this->collider.dim.radius = this->actor.scale.x * 5.0f;
+
+ this->collider.dim.pos.x = this->actor.world.pos.x;
+ this->collider.dim.pos.y = this->actor.world.pos.y;
+ this->collider.dim.pos.z = this->actor.world.pos.z;
+
+ this->collider.dim.pos.x =
+ (Math_SinS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.x) + this->actor.world.pos.x;
+ this->collider.dim.pos.y = this->actor.world.pos.y;
+ this->collider.dim.pos.z =
+ (Math_CosS(this->actor.shape.rot.y) * -5.0f * this->actor.scale.z) + this->actor.world.pos.z;
+
+ CollisionCheck_SetAT(play, &play->colChkCtx, &this->collider.base);
+ }
+
+ if (this->timer > 0) {
+ this->timer--;
+ }
+
+ func_808B5EEC(this, play);
+}
+
+void EnMThunder_UnkType_Attack(EnMThunder* this, PlayState* play) {
+ if (Math_StepToF(&this->lightColorFrac, 0.0f, 0.0625f)) {
+ Actor_MarkForDeath(&this->actor);
+ } else {
+ Math_SmoothStepToF(&this->actor.scale.x, (s32)this->scaleTarget, 0.6f, 0.8f, 0.0f);
+ Actor_SetScale(&this->actor, this->actor.scale.x);
+ }
+
+ if (this->lightColorFrac > (6.0f / 10.0f)) {
+ this->alphaFrac = 1.0f;
+ } else {
+ this->alphaFrac = this->lightColorFrac * (10.0f / 6.0f);
+ }
+
+ func_808B5EEC(this, play);
+}
+
+void EnMThunder_Update(Actor* thisx, PlayState* play) {
+ EnMThunder* this = THIS;
+
+ this->actionFunc(this, play);
+ EnMThunder_AdjustLights(play, this->adjustLightsArg1);
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f,
+ this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f);
+}
+
+void EnMThunder_UnkType_Update(Actor* thisx, PlayState* play) {
+ EnMThunder* this = THIS;
+
+ this->actionFunc(this, play);
+ Lights_PointNoGlowSetInfo(&this->lightInfo, this->actor.world.pos.x, this->actor.world.pos.y,
+ this->actor.world.pos.z, this->lightColorFrac * 255.0f, this->lightColorFrac * 255.0f,
+ this->lightColorFrac * 100.0f, this->lightColorFrac * 800.0f);
+}
+
+void EnMThunder_Draw(Actor* thisx, PlayState* play2) {
+ PlayState* play = play2;
+ EnMThunder* this = THIS;
+ Player* player = GET_PLAYER(play);
+ f32 scale;
+ s32 y2Scroll;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ func_8012C2DC(play->state.gfxCtx);
+ Matrix_Scale(0.02f, 0.02f, 0.02f, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+
+ switch (this->subtype) {
+ case ENMTHUNDER_SUBTYPE_SPIN_GREAT:
+ case ENMTHUNDER_SUBTYPE_SPIN_REGULAR:
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0xFF - ((u16)(s32)(this->scroll * 30.0f) & 0xFF), 0, 64,
+ 32, 1, 0xFF - ((u16)(s32)(this->scroll * 20.0f) & 0xFF), 0, 8, 8));
+ break;
+
+ case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT:
+ case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR:
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 16, 64, 1, 0,
+ 0x1FF - ((u16)(s32)(this->scroll * 10.0f) & 0x1FF), 32, 128));
+ break;
+
+ default:
+ break;
+ }
+
+ switch (this->subtype) {
+ case ENMTHUNDER_SUBTYPE_SPIN_GREAT:
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, (u16)(this->alphaFrac * 255.0f));
+ gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackDiskDL);
+ gSPDisplayList(POLY_XLU_DISP++, gGreatSpinAttackCylinderDL);
+ break;
+
+ case ENMTHUNDER_SUBTYPE_SPIN_REGULAR:
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f));
+ gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL);
+ gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL);
+ break;
+
+ case ENMTHUNDER_SUBTYPE_SWORDBEAM_REGULAR:
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u16)(this->alphaFrac * 255.0f));
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128);
+ gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL);
+ break;
+
+ case ENMTHUNDER_SUBTYPE_SWORDBEAM_GREAT:
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 0, 255, 255, (u16)(this->alphaFrac * 255.0f));
+ gDPSetEnvColor(POLY_XLU_DISP++, 200, 200, 200, 128);
+ gSPDisplayList(POLY_XLU_DISP++, gSwordBeamDL);
+ break;
+
+ default:
+ break;
+ }
+
+ Matrix_Mult(&player->mf_CC4, MTXMODE_NEW);
+
+ if (this->type == ENMTHUNDER_TYPE_GILDED_SWORD) {
+ Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(-1.2f, -0.8f, -0.6f, MTXMODE_APPLY);
+ Matrix_RotateXS(0x4000, MTXMODE_APPLY);
+ } else {
+ Matrix_Translate(0.0f, 220.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_Scale(-0.7f, -0.6f, -0.4f, MTXMODE_APPLY);
+ Matrix_RotateXS(0x4000, MTXMODE_APPLY);
+ }
+
+ if (this->unk1B0 >= 0.85f) {
+ scale = (sScales[play->gameplayFrames & 7] * 6.0f) + 1.0f;
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 170, this->chargingAlpha);
+ gDPSetEnvColor(POLY_XLU_DISP++, 255, 100, 0, 128);
+ y2Scroll = 40;
+ } else {
+ scale = (sScales[play->gameplayFrames & 7] * 2.0f) + 1.0f;
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, this->chargingAlpha);
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 100, 255, 128);
+ y2Scroll = 20;
+ }
+
+ Matrix_Scale(1.0f, scale, scale, MTXMODE_APPLY);
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPSegment(POLY_XLU_DISP++, 0x09,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, (play->gameplayFrames * 5) & 0xFF, 0, 32, 32, 1,
+ (play->gameplayFrames * 20) & 0xFF, (play->gameplayFrames * y2Scroll) & 0xFF, 8, 8));
+ gSPDisplayList(POLY_XLU_DISP++, gSpinAttackChargingDL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h
index 14d022770..7ac851e92 100644
--- a/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h
+++ b/src/overlays/actors/ovl_En_M_Thunder/z_en_m_thunder.h
@@ -5,13 +5,36 @@
struct EnMThunder;
+#define ENMTHUNDER_GET_TYPE(thisx) ((thisx)->params & 0xFF)
+#define ENMTHUNDER_GET_MAGIC_COST(thisx) (((thisx)->params & 0xFF00) >> 8)
+
+typedef enum {
+ /* 0x00 */ ENMTHUNDER_TYPE_KOKIRI_SWORD,
+ /* 0x01 */ ENMTHUNDER_TYPE_RAZOR_SWORD,
+ /* 0x02 */ ENMTHUNDER_TYPE_GILDED_SWORD,
+ /* 0x03 */ ENMTHUNDER_TYPE_GREAT_FAIRY_SWORD,
+ /* 0x80 */ ENMTHUNDER_TYPE_UNK = 0x80
+} EnMThunderType;
+
typedef void (*EnMThunderActionFunc)(struct EnMThunder*, PlayState*);
typedef struct EnMThunder {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x74];
+ /* 0x144 */ ColliderCylinder collider;
+ /* 0x190 */ LightNode* lightNode;
+ /* 0x194 */ LightInfo lightInfo;
+ /* 0x1A4 */ f32 lightColorFrac;
+ /* 0x1A8 */ f32 alphaFrac;
+ /* 0x1AC */ f32 scroll;
+ /* 0x1B0 */ f32 unk1B0;
+ /* 0x1B4 */ f32 adjustLightsArg1;
/* 0x1B8 */ EnMThunderActionFunc actionFunc;
- /* 0x1BC */ char unk_1BC[0x8];
+ /* 0x1BC */ u16 timer;
+ /* 0x1BE */ u8 subtype;
+ /* 0x1BF */ u8 type;
+ /* 0x1C0 */ u8 chargingAlpha;
+ /* 0x1C1 */ u8 scaleTarget;
+ /* 0x1C2 */ u8 isCharging;
} EnMThunder; // size = 0x1C4
extern const ActorInit En_M_Thunder_InitVars;
diff --git a/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c b/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c
index 1e92e1f77..399a8f659 100644
--- a/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c
+++ b/src/overlays/actors/ovl_En_Minifrog/z_en_minifrog.c
@@ -411,7 +411,7 @@ void EnMinifrog_NextFrogReturned(EnMinifrog* this, PlayState* play) {
this->actionFunc = EnMinifrog_ContinueChoirCutscene;
this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE |
0x2 << MINIFROG_WHITE);
- play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00DEA8, 0);
+ play->setPlayerTalkAnim(play, &gPlayerAnim_link_normal_talk_free_wait, 0);
}
}
@@ -442,7 +442,7 @@ void EnMinifrog_SetupNextFrogChoir(EnMinifrog* this, PlayState* play) {
this->flags &= ~0x100;
this->flags &= ~(0x2 << MINIFROG_YELLOW | 0x2 << MINIFROG_CYAN | 0x2 << MINIFROG_PINK | 0x2 << MINIFROG_BLUE |
0x2 << MINIFROG_WHITE);
- play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00DEA8, 0);
+ play->setPlayerTalkAnim(play, &gPlayerAnim_link_normal_talk_free_wait, 0);
} else if (this->timer <= 0) {
this->actionFunc = EnMinifrog_NextFrogReturned;
this->timer = 30;
@@ -462,7 +462,7 @@ void EnMinifrog_BeginChoirCutscene(EnMinifrog* this, PlayState* play) {
this->timer = 5;
func_801A1F00(3, NA_BGM_FROG_SONG);
this->flags |= 0x100;
- play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00E2A8, 0);
+ play->setPlayerTalkAnim(play, &gPlayerAnim_pn_gakkiplay, 0);
} else {
ActorCutscene_SetIntentToPlay(this->actor.cutscene);
}
diff --git a/src/overlays/actors/ovl_En_St/z_en_st.c b/src/overlays/actors/ovl_En_St/z_en_st.c
index 7d0dcbf11..ecc2b85b2 100644
--- a/src/overlays/actors/ovl_En_St/z_en_st.c
+++ b/src/overlays/actors/ovl_En_St/z_en_st.c
@@ -260,8 +260,8 @@ void func_808A54B0(EnSt* this, PlayState* play) {
}
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 170, 255, 255, (u8)(255 * temp_f0));
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025850);
- gSPDisplayList(POLY_XLU_DISP++, gameplay_keep_DL_025970);
+ gSPDisplayList(POLY_XLU_DISP++, gSpinAttackDiskDL);
+ gSPDisplayList(POLY_XLU_DISP++, gSpinAttackCylinderDL);
CLOSE_DISPS(play->state.gfxCtx);
}
diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c
index bbce2ee6c..4f3882aa7 100644
--- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c
+++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.c
@@ -7,6 +7,7 @@
#include "z_en_suttari.h"
#include "overlays/actors/ovl_En_Elf/z_en_elf.h"
#include "overlays/actors/ovl_En_Door/z_en_door.h"
+#include "overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h"
#include "objects/object_boj/object_boj.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10)
@@ -444,12 +445,13 @@ void func_80BAAFDC(EnSuttari* this, PlayState* play) {
effectVelOffset.z = 20.0f;
Matrix_MultVec3f(&effectVelOffset, &effectVel);
Matrix_Pop();
- if (this->unk3F0 == 0) {
- EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->unk3F0, 1);
+ if (!this->playerDetected) {
+ EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->playerDetected,
+ SOLDERSRCHBALL_INVISIBLE);
}
- if (this->unk3F0 == 1) {
+ if (this->playerDetected == true) {
play_sound(NA_SE_SY_FOUND);
- this->unk3F0 = 0;
+ this->playerDetected = false;
this->actor.speedXZ = 0.0f;
if (this->unk1F4[0] != 0) {
this->unk1F4[0]--;
@@ -476,12 +478,13 @@ void func_80BAB1A0(EnSuttari* this, PlayState* play) {
effectVelOffset.z = 20.0f;
Matrix_MultVec3f(&effectVelOffset, &effectVel);
Matrix_Pop();
- if (this->unk3F0 == 0) {
- EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->unk3F0, 1);
+ if (!this->playerDetected) {
+ EffectSsSolderSrchBall_Spawn(play, &effectPos, &effectVel, &gZeroVec3f, 50, &this->playerDetected,
+ SOLDERSRCHBALL_INVISIBLE);
}
- if (this->unk3F0 == 1) {
+ if (this->playerDetected == true) {
play_sound(NA_SE_SY_FOUND);
- this->unk3F0 = 0;
+ this->playerDetected = false;
this->actor.speedXZ = 0.0f;
if (this->unk1F4[0] != 0) {
this->unk1F4[0]--;
diff --git a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h
index 35a9b6e2e..427f74988 100644
--- a/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h
+++ b/src/overlays/actors/ovl_En_Suttari/z_en_suttari.h
@@ -34,7 +34,7 @@ typedef struct EnSuttari {
/* 0x2FA */ s16 unk2FA[16];
/* 0x31A */ s16 unk31A[16];
/* 0x33A */ UNK_TYPE1 unk_33A[0xB6];
- /* 0x3F0 */ s16 unk3F0;
+ /* 0x3F0 */ s16 playerDetected;
/* 0x3F2 */ s16 unk3F2;
/* 0x3F4 */ s16 unk3F4;
/* 0x3F6 */ s16 unk3F6;
diff --git a/src/overlays/actors/ovl_En_Tab/z_en_tab.c b/src/overlays/actors/ovl_En_Tab/z_en_tab.c
index 860ad9d0c..ffa557746 100644
--- a/src/overlays/actors/ovl_En_Tab/z_en_tab.c
+++ b/src/overlays/actors/ovl_En_Tab/z_en_tab.c
@@ -323,7 +323,7 @@ s32 func_80BE0D60(EnTab* this, PlayState* play) {
this->unk_320++;
if (this->unk_320 == 1) {
- play->setPlayerTalkAnim(play, &gameplay_keep_Linkanim_00D568, 2);
+ play->setPlayerTalkAnim(play, &gPlayerAnim_link_demo_bikkuri, 2);
} else if (this->unk_320 > 20) {
play->setPlayerTalkAnim(play, NULL, 0);
this->unk_320 = 0;
diff --git a/src/overlays/actors/ovl_En_Tru/z_en_tru.c b/src/overlays/actors/ovl_En_Tru/z_en_tru.c
index 42cbdc22a..c54d924df 100644
--- a/src/overlays/actors/ovl_En_Tru/z_en_tru.c
+++ b/src/overlays/actors/ovl_En_Tru/z_en_tru.c
@@ -5,7 +5,7 @@
*/
#include "z_en_tru.h"
-#include "objects/object_tru/object_tru.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
#define FLAGS (ACTOR_FLAG_1 | ACTOR_FLAG_8 | ACTOR_FLAG_10 | ACTOR_FLAG_20)
@@ -24,6 +24,26 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play);
void func_80A87FD0(EnTru* this, PlayState* play);
void func_80A881E0(EnTru* this, PlayState* play);
+typedef enum {
+ /* 0x00 */ KOUME_ANIM_INJURED_LYING_DOWN,
+ /* 0x01 */ KOUME_ANIM_INJURED_LYING_DOWN_MORPH,
+ /* 0x02 */ KOUME_ANIM_TRY_GET_UP,
+ /* 0x03 */ KOUME_ANIM_INJURED_RAISE_HEAD,
+ /* 0x04 */ KOUME_ANIM_INJURED_TALK,
+ /* 0x05 */ KOUME_ANIM_INJURED_HEAD_UP,
+ /* 0x06 */ KOUME_ANIM_INJURED_HEAD_UP_MORPH,
+ /* 0x07 */ KOUME_ANIM_TAKE,
+ /* 0x08 */ KOUME_ANIM_SHAKE, // Unused
+ /* 0x09 */ KOUME_ANIM_DRINK,
+ /* 0x0A */ KOUME_ANIM_FINISHED_DRINKING,
+ /* 0x0B */ KOUME_ANIM_HEALED,
+ /* 0x0C */ KOUME_ANIM_HOVER1,
+ /* 0x0D */ KOUME_ANIM_TAKE_OFF,
+ /* 0x0E */ KOUME_ANIM_FLY,
+ /* 0x0F */ KOUME_ANIM_HOVER2,
+ /* 0x10 */ KOUME_ANIM_MAX
+} KoumeAnimation;
+
static UNK_TYPE D_80A88910[] = {
0x0E08520C,
0x16100000,
@@ -69,7 +89,6 @@ const ActorInit En_Tru_InitVars = {
};
#include "overlays/ovl_En_Tru/ovl_En_Tru.c"
-#include "objects/gameplay_keep/gameplay_keep.h"
static Vec3f D_80A8B250 = { 0.0f, 0.02f, 0.0f };
@@ -107,22 +126,22 @@ static ColliderSphereInit sSphereInit = {
static CollisionCheckInfoInit2 sColChkInfoInit = { 1, 20, 0, 0, MASS_IMMOVABLE };
static AnimationInfoS sAnimationInfo[] = {
- { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_0108AC, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_009348, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
- { &object_tru_Anim_00EEDC, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_014728, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
- { &object_tru_Anim_01B5C4, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
- { &object_tru_Anim_007FA0, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_016B4C, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_011F88, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_003698, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_002BD8, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeTryGetUpAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeInjuredRaiseHeadAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gKoumeInjuredTalkAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeTakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gKoumeShakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gKoumeDrinkAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeFinishedDrinkingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeHealedAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeTakeOffAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeFlyAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
};
static Vec3f D_80A8B3D8 = { 0.0f, 24.0f, 16.0f };
@@ -275,12 +294,12 @@ void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) {
for (i = 0; i < 30; i++, arg0++) {
f32 alpha;
- s32 idx;
+ s32 index;
if ((arg0->unk_00 == 3) || (arg0->unk_00 == 4) || (arg0->unk_00 == 5)) {
if (!flag) {
- POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, sizeof(Gfx) * 0);
- gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_01A820);
+ POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 0);
+ gSPDisplayList(POLY_XLU_DISP++, gKoumeDustMaterialDL);
flag = true;
}
@@ -306,9 +325,9 @@ void func_80A85F84(EnTruUnkStruct* arg0, PlayState* play) {
Matrix_ReplaceRotation(&play->billboardMtxF);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- idx = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f;
- gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[idx]));
- gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_01A830);
+ index = ((f32)arg0->unk_02 / arg0->unk_01) * 8.0f;
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(sDustTextures[index]));
+ gSPDisplayList(POLY_XLU_DISP++, gKoumeDustModelDL);
Matrix_Pop();
}
@@ -414,21 +433,21 @@ s32 func_80A86770(EnTru* this) {
return false;
}
-void func_80A868F8(EnTru* this) {
- this->skelAnime.playSpeed = this->unk_358;
+void EnTru_UpdateSkelAnime(EnTru* this) {
+ this->skelAnime.playSpeed = this->playSpeed;
SkelAnime_Update(&this->skelAnime);
}
-s32 func_80A86924(EnTru* this, s32 arg1) {
- s32 ret = false;
+s32 EnTru_ChangeAnim(EnTru* this, s32 animIndex) {
+ s32 didChange = false;
- if (arg1 != this->unk_37C) {
- this->unk_37C = arg1;
- ret = SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, arg1);
- this->unk_358 = this->skelAnime.playSpeed;
+ if (animIndex != this->animIndex) {
+ this->animIndex = animIndex;
+ didChange = SubS_ChangeAnimationByInfoS(&this->skelAnime, sAnimationInfo, animIndex);
+ this->playSpeed = this->skelAnime.playSpeed;
}
- return ret;
+ return didChange;
}
void func_80A8697C(EnTru* this, PlayState* play) {
@@ -497,7 +516,7 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) {
Matrix_RotateXS(-0x4000, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_0020C8);
+ gSPDisplayList(POLY_OPA_DISP++, gKoumePotionDL);
Matrix_Pop();
@@ -515,7 +534,7 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) {
Matrix_RotateXS(-0x4000, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_tru_DL_001F90);
+ gSPDisplayList(POLY_XLU_DISP++, gKoumeBottleDL);
Matrix_Pop();
@@ -527,104 +546,105 @@ s32 func_80A86BAC(EnTru* this, PlayState* play) {
s32 func_80A86DB8(EnTru* this) {
if (this->unk_34E & 0x80) {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
return false;
}
- switch (this->unk_37C) {
- case 0:
- case 1:
- if (DECR(this->unk_36C) == 0) {
+ switch (this->animIndex) {
+ case KOUME_ANIM_INJURED_LYING_DOWN:
+ case KOUME_ANIM_INJURED_LYING_DOWN_MORPH:
+ if (DECR(this->blinkTimer) == 0) {
s16 rand = Rand_S16Offset(40, 20);
- if (this->unk_36E == 2) {
- this->unk_36C = 8;
+
+ if (this->eyeTexIndex == 2) {
+ this->blinkTimer = 8;
} else {
- this->unk_36C = rand;
+ this->blinkTimer = rand;
}
- if (this->unk_36E == 2) {
- this->unk_36E = 1;
+ if (this->eyeTexIndex == 2) {
+ this->eyeTexIndex = 1;
} else {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
}
}
return false;
- case 2:
+ case KOUME_ANIM_TRY_GET_UP:
if (Animation_OnFrame(&this->skelAnime, 10.0f)) {
- this->unk_36E = 1;
+ this->eyeTexIndex = 1;
} else if ((this->skelAnime.curFrame >= 11.0f) && (this->skelAnime.curFrame <= 32.0f)) {
- this->unk_36E = 0;
+ this->eyeTexIndex = 0;
} else {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
}
return false;
- case 3:
+ case KOUME_ANIM_INJURED_RAISE_HEAD:
if (Animation_OnFrame(&this->skelAnime, 31.0f)) {
- this->unk_36E = 1;
+ this->eyeTexIndex = 1;
} else if (this->skelAnime.curFrame <= 32.0f) {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
} else {
- this->unk_36E = 0;
+ this->eyeTexIndex = 0;
}
return false;
- case 9:
+ case KOUME_ANIM_DRINK:
if (Animation_OnFrame(&this->skelAnime, 57.0f)) {
- this->unk_36C = 0;
- this->unk_36E = 0;
+ this->blinkTimer = 0;
+ this->eyeTexIndex = 0;
}
if (this->skelAnime.curFrame < 57.0f) {
- if (DECR(this->unk_36C) == 0) {
- this->unk_36C = Rand_S16Offset(8, 8);
- this->unk_36E = 2;
+ if (DECR(this->blinkTimer) == 0) {
+ this->blinkTimer = Rand_S16Offset(8, 8);
+ this->eyeTexIndex = 2;
} else {
- this->unk_36E = 1;
+ this->eyeTexIndex = 1;
}
- } else if (DECR(this->unk_36C) == 0) {
- this->unk_36E++;
- if (this->unk_36E >= 4) {
- this->unk_36C = Rand_S16Offset(20, 10);
- this->unk_36E = 0;
+ } else if (DECR(this->blinkTimer) == 0) {
+ this->eyeTexIndex++;
+ if (this->eyeTexIndex >= 4) {
+ this->blinkTimer = Rand_S16Offset(20, 10);
+ this->eyeTexIndex = 0;
}
}
return false;
- case 10:
- this->unk_36E = 0;
+ case KOUME_ANIM_FINISHED_DRINKING:
+ this->eyeTexIndex = 0;
return false;
- case 11:
+ case KOUME_ANIM_HEALED:
if (Animation_OnFrame(&this->skelAnime, 19.0f) || Animation_OnFrame(&this->skelAnime, 45.0f)) {
- this->unk_36E = 1;
+ this->eyeTexIndex = 1;
} else if ((this->skelAnime.curFrame >= 19.0f) && (this->skelAnime.curFrame <= 45.0f)) {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
} else {
- this->unk_36E = 3;
+ this->eyeTexIndex = 3;
}
return false;
- case 13:
+ case KOUME_ANIM_TAKE_OFF:
if (Animation_OnFrame(&this->skelAnime, 19.0f)) {
- this->unk_36E = 1;
+ this->eyeTexIndex = 1;
} else if (this->skelAnime.curFrame >= 19.0f) {
- this->unk_36E = 2;
+ this->eyeTexIndex = 2;
} else {
- this->unk_36E = 0;
+ this->eyeTexIndex = 0;
}
return false;
default:
- if (DECR(this->unk_36C) == 0) {
- if ((this->unk_36E != 2) || !(this->unk_34E & 0x80)) {
- this->unk_36E++;
+ if (DECR(this->blinkTimer) == 0) {
+ if ((this->eyeTexIndex != 2) || !(this->unk_34E & 0x80)) {
+ this->eyeTexIndex++;
}
- if (this->unk_36E >= 4) {
- this->unk_36C = Rand_S16Offset(30, 30);
- this->unk_36E = 0;
+ if (this->eyeTexIndex >= 4) {
+ this->blinkTimer = Rand_S16Offset(30, 30);
+ this->eyeTexIndex = 0;
}
}
return false;
@@ -772,11 +792,12 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) {
break;
case 2:
- if ((this->unk_37C != 5) && (this->unk_37C != 6)) {
- func_80A86924(this, 3);
+ if ((this->animIndex != KOUME_ANIM_INJURED_HEAD_UP) &&
+ (this->animIndex != KOUME_ANIM_INJURED_HEAD_UP_MORPH)) {
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_RAISE_HEAD);
this->unk_364++;
} else {
- func_80A86924(this, 4);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_TALK);
ret = true;
}
break;
@@ -784,7 +805,7 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) {
case 3:
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
this->unk_364++;
- func_80A86924(this, 4);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_TALK);
ret = true;
}
break;
@@ -806,7 +827,7 @@ s32 func_80A875AC(Actor* thisx, PlayState* play) {
s32 func_80A8777C(Actor* thisx, PlayState* play) {
EnTru* this = THIS;
s32 ret = 0;
- s32 temp_v0;
+ s32 itemActionParam;
switch (Message_GetState(&play->msgCtx)) {
case TEXT_STATE_CHOICE:
@@ -816,10 +837,10 @@ s32 func_80A8777C(Actor* thisx, PlayState* play) {
}
// Fallthrough
case TEXT_STATE_16:
- temp_v0 = func_80123810(play);
- if ((temp_v0 == 35) || (temp_v0 == 36)) {
+ itemActionParam = func_80123810(play);
+ if ((itemActionParam == PLAYER_AP_BOTTLE_POTION_RED) || (itemActionParam == PLAYER_AP_BOTTLE_POTION_BLUE)) {
this->unk_34E |= 8;
- if (temp_v0 == 35) {
+ if (itemActionParam == PLAYER_AP_BOTTLE_POTION_RED) {
this->unk_390 = 1;
} else {
this->unk_390 = 2;
@@ -827,9 +848,9 @@ s32 func_80A8777C(Actor* thisx, PlayState* play) {
this->unk_378 = func_80A87880;
this->unk_364 = 0;
ret = 1;
- } else if (temp_v0 < 0) {
+ } else if (itemActionParam < PLAYER_AP_NONE) {
ret = 3;
- } else if (temp_v0 != 0) {
+ } else if (itemActionParam != PLAYER_AP_NONE) {
ret = 2;
}
break;
@@ -866,14 +887,14 @@ s32 func_80A87880(Actor* thisx, PlayState* play) {
this->unk_34E &= ~0x8;
this->actor.shape.rot.y = this->actor.yawTowardsPlayer;
this->actor.world.rot.y = this->actor.yawTowardsPlayer;
- func_80A86924(this, 7);
+ EnTru_ChangeAnim(this, KOUME_ANIM_TAKE);
this->unk_364++;
break;
case 3:
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
this->unk_364++;
- func_80A86924(this, 9);
+ EnTru_ChangeAnim(this, KOUME_ANIM_DRINK);
this->actor.world.rot.y += 0x4000;
} else if (Animation_OnFrame(&this->skelAnime, 12.0f) && !(this->unk_34E & 0x800)) {
this->unk_34E |= 0x400;
@@ -885,7 +906,7 @@ s32 func_80A87880(Actor* thisx, PlayState* play) {
case 4:
if (Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
this->unk_364++;
- func_80A86924(this, 10);
+ EnTru_ChangeAnim(this, KOUME_ANIM_FINISHED_DRINKING);
ret = true;
} else if (Animation_OnFrame(&this->skelAnime, 18.0f) || Animation_OnFrame(&this->skelAnime, 32.0f) ||
Animation_OnFrame(&this->skelAnime, 52.0f)) {
@@ -923,7 +944,7 @@ s32 func_80A87B48(Actor* thisx, PlayState* play) {
switch (this->unk_364) {
case 0:
- func_80A86924(this, 11);
+ EnTru_ChangeAnim(this, KOUME_ANIM_HEALED);
this->unk_364++;
break;
@@ -954,7 +975,7 @@ s32 func_80A87B48(Actor* thisx, PlayState* play) {
if (player->exchangeItemId != 0) {
player->exchangeItemId = 0;
}
- func_80A86924(this, 12);
+ EnTru_ChangeAnim(this, KOUME_ANIM_HOVER1);
}
} else {
MREG(64) = 0;
@@ -997,7 +1018,7 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play) {
AudioSfx_StopById(NA_SE_EN_KOUME_MAGIC);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KOUME_AWAY);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_KOUME_LAUGH);
- func_80A86924(this, 13);
+ EnTru_ChangeAnim(this, KOUME_ANIM_TAKE_OFF);
this->skelAnime.baseTransl.y = 0;
this->skelAnime.moveFlags = 2;
this->unk_34E &= ~0x8;
@@ -1010,7 +1031,7 @@ s32 func_80A87DC0(Actor* thisx, PlayState* play) {
AnimationContext_SetMoveActor(play, &this->actor, &this->skelAnime, 1.0f);
break;
} else {
- func_80A86924(this, 14);
+ EnTru_ChangeAnim(this, KOUME_ANIM_FLY);
this->actor.shape.rot.y = this->actor.world.rot.y;
this->unk_362 = 20;
this->unk_364++;
@@ -1049,13 +1070,14 @@ void func_80A87FD0(EnTru* this, PlayState* play) {
SubS_UpdateFlags(&this->unk_34E, 0, 7);
}
- if ((this->unk_37C == 2) && Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
+ if ((this->animIndex == KOUME_ANIM_TRY_GET_UP) &&
+ Animation_OnFrame(&this->skelAnime, this->skelAnime.endFrame)) {
this->unk_362 = Rand_S16Offset(40, 20);
- func_80A86924(this, 1);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN_MORPH);
func_80A86460(this);
- } else if (this->unk_37C != 2) {
+ } else if (this->animIndex != KOUME_ANIM_TRY_GET_UP) {
if (DECR(this->unk_362) == 0) {
- func_80A86924(this, 2);
+ EnTru_ChangeAnim(this, KOUME_ANIM_TRY_GET_UP);
}
}
} else if (!(gSaveContext.save.weekEventReg[16] & 0x10) && (fabsf(this->actor.playerHeightRel) < 10.0f) &&
@@ -1084,12 +1106,12 @@ void func_80A881E0(EnTru* this, PlayState* play) {
}
if (!(this->unk_34E & 0x40) && !(gSaveContext.save.weekEventReg[16] & 0x10)) {
- func_80A86924(this, 0);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN);
} else if (this->unk_34E & 0x80) {
- func_80A86924(this, 0);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN);
func_80A86460(this);
} else if (gSaveContext.save.weekEventReg[16] & 0x10) {
- func_80A86924(this, 6);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_HEAD_UP_MORPH);
}
SubS_UpdateFlags(&this->unk_34E, 0, 7);
@@ -1111,11 +1133,11 @@ void EnTru_Init(Actor* thisx, PlayState* play) {
}
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 24.0f);
- SkelAnime_InitFlex(play, &this->skelAnime, &object_tru_Skel_01AA60, NULL, this->jointTable, this->morphTable, 27);
+ SkelAnime_InitFlex(play, &this->skelAnime, &gKoumeSkel, NULL, this->jointTable, this->morphTable, KOUME_LIMB_MAX);
Collider_InitAndSetSphere(play, &this->collider, &this->actor, &sSphereInit);
CollisionCheck_SetInfo2(&this->actor.colChkInfo, DamageTable_Get(0x16), &sColChkInfoInit);
- this->unk_37C = -1;
- func_80A86924(this, 0);
+ this->animIndex = -1;
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_LYING_DOWN);
this->path = SubS_GetDayDependentPath(play, ENTRU_GET_PATH(&this->actor), 255, &this->unk_384);
if (this->path != NULL) {
this->unk_384 = 1;
@@ -1126,7 +1148,7 @@ void EnTru_Init(Actor* thisx, PlayState* play) {
this->unk_34E = 0;
if (gSaveContext.save.weekEventReg[16] & 0x10) {
- func_80A86924(this, 5);
+ EnTru_ChangeAnim(this, KOUME_ANIM_INJURED_HEAD_UP);
} else {
this->unk_388 = PLAYER_AP_NONE;
}
@@ -1149,7 +1171,7 @@ void EnTru_Update(Actor* thisx, PlayState* play) {
this->actionFunc(this, play);
- func_80A868F8(this);
+ EnTru_UpdateSkelAnime(this);
func_80A86B0C(this, play);
func_80A86DB8(this);
@@ -1165,7 +1187,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
s32 pad;
EnTru* this = THIS;
- if (limbIndex == 21) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
Matrix_MultZero(&this->actor.focus.pos);
Math_Vec3f_ToVec3s(&this->collider.dim.worldSphere.center, &this->actor.focus.pos);
this->actor.focus.pos.x = (this->actor.focus.pos.x / 10.0f) * 10.0f;
@@ -1175,7 +1197,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
Matrix_MultVec3f(&D_80A8B3FC, &this->unk_1F8);
}
- if (!(this->unk_34E & 0x200) && (limbIndex == 14)) {
+ if (!(this->unk_34E & 0x200) && (limbIndex == KOUME_LIMB_BROOM)) {
*dList = NULL;
}
@@ -1185,7 +1207,7 @@ s32 EnTru_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* p
void EnTru_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
EnTru* this = THIS;
- if (limbIndex == 19) {
+ if (limbIndex == KOUME_LIMB_RIGHT_HAND) {
func_80A86BAC(this, play);
}
}
@@ -1212,7 +1234,7 @@ void EnTru_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) {
overrideRot = false;
}
- if (limbIndex == 21) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
SubS_UpdateLimb(this->unk_366, this->unk_368 + this->actor.shape.rot.y, &this->unk_1EC, &this->unk_204, stepRot,
overrideRot);
Matrix_Pop();
@@ -1232,11 +1254,11 @@ void EnTru_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) {
}
void EnTru_Draw(Actor* thisx, PlayState* play) {
- static TexturePtr D_80A8B408[] = {
- object_tru_Tex_018FA0,
- object_tru_Tex_0197A0,
- object_tru_Tex_019FA0,
- object_tru_Tex_0197A0,
+ static TexturePtr sEyeTextures[] = {
+ gKoumeEyeOpenTex,
+ gKoumeEyeHalfTex,
+ gKoumeEyeClosedTex,
+ gKoumeEyeHalfTex,
};
s32 pad;
EnTru* this = THIS;
@@ -1245,8 +1267,8 @@ void EnTru_Draw(Actor* thisx, PlayState* play) {
func_8012C28C(play->state.gfxCtx);
- gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(D_80A8B408[this->unk_36E]));
- gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(D_80A8B408[this->unk_36E]));
+ gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex]));
+ gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sEyeTextures[this->eyeTexIndex]));
SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, EnTru_OverrideLimbDraw, EnTru_PostLimbDraw,
diff --git a/src/overlays/actors/ovl_En_Tru/z_en_tru.h b/src/overlays/actors/ovl_En_Tru/z_en_tru.h
index 7e1c23380..711d5aeb6 100644
--- a/src/overlays/actors/ovl_En_Tru/z_en_tru.h
+++ b/src/overlays/actors/ovl_En_Tru/z_en_tru.h
@@ -2,6 +2,7 @@
#define Z_EN_TRU_H
#include "global.h"
+#include "objects/object_tru/object_tru.h"
struct EnTru;
@@ -31,12 +32,12 @@ typedef struct EnTru {
/* 0x1EC */ Vec3f unk_1EC;
/* 0x1F8 */ Vec3f unk_1F8;
/* 0x204 */ Vec3s unk_204;
- /* 0x20A */ Vec3s jointTable[27];
- /* 0x2AC */ Vec3s morphTable[27];
+ /* 0x20A */ Vec3s jointTable[KOUME_LIMB_MAX];
+ /* 0x2AC */ Vec3s morphTable[KOUME_LIMB_MAX];
/* 0x34E */ u16 unk_34E;
/* 0x350 */ UNK_TYPE1 unk350[0x4];
/* 0x354 */ s32* unk_354;
- /* 0x358 */ f32 unk_358;
+ /* 0x358 */ f32 playSpeed;
/* 0x35C */ f32 unk_35C;
/* 0x360 */ s16 unk_360;
/* 0x362 */ s16 unk_362;
@@ -44,13 +45,13 @@ typedef struct EnTru {
/* 0x366 */ s16 unk_366;
/* 0x368 */ s16 unk_368;
/* 0x36A */ s16 unk_36A;
- /* 0x36C */ s16 unk_36C;
- /* 0x36E */ s16 unk_36E;
+ /* 0x36C */ s16 blinkTimer;
+ /* 0x36E */ s16 eyeTexIndex;
/* 0x370 */ s16 unk_370;
/* 0x372 */ s16 unk_372;
/* 0x374 */ s16 unk_374;
/* 0x378 */ EnTruUnkFunc unk_378;
- /* 0x37C */ s32 unk_37C;
+ /* 0x37C */ s32 animIndex;
/* 0x380 */ UNK_TYPE1 unk380[0x4];
/* 0x384 */ s32 unk_384;
/* 0x388 */ s32 unk_388;
diff --git a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c
index aab26a226..be1556f13 100644
--- a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c
+++ b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.c
@@ -20,6 +20,26 @@ void func_80B76A64(EnTruMt* this, PlayState* play);
void func_80B76BB8(EnTruMt* this, PlayState* play);
void func_80B76C38(EnTruMt* this, PlayState* play);
+typedef enum {
+ /* 0x00 */ KOUME_MT_ANIM_INJURED_LYING_DOWN,
+ /* 0x01 */ KOUME_MT_ANIM_INJURED_LYING_DOWN_MORPH,
+ /* 0x02 */ KOUME_MT_ANIM_TRY_GET_UP,
+ /* 0x03 */ KOUME_MT_ANIM_INJURED_RAISE_HEAD,
+ /* 0x04 */ KOUME_MT_ANIM_INJURED_TALK,
+ /* 0x05 */ KOUME_MT_ANIM_INJURED_HEAD_UP,
+ /* 0x06 */ KOUME_MT_ANIM_INJURED_HEAD_UP_MORPH,
+ /* 0x07 */ KOUME_MT_ANIM_TAKE,
+ /* 0x08 */ KOUME_MT_ANIM_SHAKE, // Unused
+ /* 0x09 */ KOUME_MT_ANIM_DRINK,
+ /* 0x0A */ KOUME_MT_ANIM_FINISHED_DRINKING,
+ /* 0x0B */ KOUME_MT_ANIM_HEALED,
+ /* 0x0C */ KOUME_MT_ANIM_HOVER1,
+ /* 0x0D */ KOUME_MT_ANIM_TAKE_OFF,
+ /* 0x0E */ KOUME_MT_ANIM_FLY,
+ /* 0x0F */ KOUME_MT_ANIM_HOVER2,
+ /* 0x10 */ KOUME_MT_ANIM_MAX
+} KoumeMtAnimation;
+
const ActorInit En_Tru_Mt_InitVars = {
ACTOR_EN_TRU_MT,
ACTORCAT_NPC,
@@ -88,57 +108,57 @@ static DamageTable sDamageTable = {
};
static AnimationInfoS sAnimationInfo[] = {
- { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_00F9A0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_0108AC, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_009348, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_00EEDC, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_015CA0, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_014728, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
- { &object_tru_Anim_01B5C4, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
- { &object_tru_Anim_007FA0, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_016B4C, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
- { &object_tru_Anim_011F88, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_003698, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
- { &object_tru_Anim_002BD8, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
- { &object_tru_Anim_00446C, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredLyingDownAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeTryGetUpAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeInjuredRaiseHeadAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeInjuredTalkAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeInjuredHeadUpAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeTakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gKoumeShakeAnim, 1.0f, 0, -1, ANIMMODE_ONCE, 0 },
+ { &gKoumeDrinkAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeFinishedDrinkingAnim, 1.0f, 0, -1, ANIMMODE_LOOP, -4 },
+ { &gKoumeHealedAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeTakeOffAnim, 1.0f, 0, -1, ANIMMODE_ONCE, -4 },
+ { &gKoumeFlyAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
+ { &gKoumeHoverAnim, 1.0f, 0, -1, ANIMMODE_LOOP, 0 },
};
Vec3f D_80B7765C = { 3000.0f, -800.0f, 0.0f };
Vec3f D_80B77668 = { 0.0f, 0.0f, -3000.0f };
-s32 func_80B76030(SkelAnime* skelAnime, s16 arg1) {
+s32 EnTruMt_ChangeAnim(SkelAnime* skelAnime, s16 animIndex) {
s16 endFrame;
s16 startFrame;
- s32 ret = false;
+ s32 didChange = false;
- if ((arg1 >= 0) && (arg1 < ARRAY_COUNT(sAnimationInfo))) {
- endFrame = sAnimationInfo[arg1].frameCount;
+ if ((animIndex >= KOUME_MT_ANIM_INJURED_LYING_DOWN) && (animIndex < KOUME_MT_ANIM_MAX)) {
+ endFrame = sAnimationInfo[animIndex].frameCount;
if (endFrame < 0) {
- endFrame = Animation_GetLastFrame(sAnimationInfo[arg1].animation);
+ endFrame = Animation_GetLastFrame(sAnimationInfo[animIndex].animation);
}
- startFrame = sAnimationInfo[arg1].startFrame;
+ startFrame = sAnimationInfo[animIndex].startFrame;
if (startFrame < 0) {
- startFrame = Animation_GetLastFrame(sAnimationInfo[arg1].animation);
+ startFrame = Animation_GetLastFrame(sAnimationInfo[animIndex].animation);
}
- Animation_Change(skelAnime, sAnimationInfo[arg1].animation, sAnimationInfo[arg1].playSpeed, startFrame,
- endFrame, sAnimationInfo[arg1].mode, sAnimationInfo[arg1].morphFrames);
- ret = true;
+ Animation_Change(skelAnime, sAnimationInfo[animIndex].animation, sAnimationInfo[animIndex].playSpeed,
+ startFrame, endFrame, sAnimationInfo[animIndex].mode, sAnimationInfo[animIndex].morphFrames);
+ didChange = true;
}
- return ret;
+ return didChange;
}
void func_80B76110(EnTruMt* this) {
- if (DECR(this->unk_34E) == 0) {
- this->unk_34C++;
- if (this->unk_34C >= 3) {
- this->unk_34E = Rand_S16Offset(30, 30);
- this->unk_34C = 0;
+ if (DECR(this->blinkTimer) == 0) {
+ this->eyeTexIndex++;
+ if (this->eyeTexIndex >= 3) {
+ this->blinkTimer = Rand_S16Offset(30, 30);
+ this->eyeTexIndex = 0;
}
}
}
@@ -404,8 +424,7 @@ void EnTruMt_Init(Actor* thisx, PlayState* play) {
}
ActorShape_Init(&this->actor.shape, 0.0f, ActorShadow_DrawCircle, 24.0f);
- SkelAnime_InitFlex(play, &this->skelAnime, &object_tru_Skel_01AA60, NULL, this->jointTable, this->morphTable,
- OBJECT_TRU_LIMB_MAX);
+ SkelAnime_InitFlex(play, &this->skelAnime, &gKoumeSkel, NULL, this->jointTable, this->morphTable, KOUME_LIMB_MAX);
Collider_InitSphere(play, &this->collider);
Collider_SetSphere(play, &this->collider, &this->actor, &sSphereInit);
@@ -421,7 +440,7 @@ void EnTruMt_Init(Actor* thisx, PlayState* play) {
this->unk_328 = 0;
this->actor.room = -1;
this->path = SubS_GetPathByIndex(play, ENTRUMT_GET_FC00(&this->actor), 0x3F);
- func_80B76030(&this->skelAnime, 14);
+ EnTruMt_ChangeAnim(&this->skelAnime, KOUME_MT_ANIM_FLY);
this->actionFunc = func_80B76A64;
}
@@ -477,11 +496,11 @@ void func_80B76ED4(s16 arg0, s16 arg1, Vec3f* arg2, Vec3s* arg3, s32 arg4) {
s32 EnTruMt_OverrideLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3f* pos, Vec3s* rot, Actor* thisx) {
EnTruMt* this = THIS;
- if (limbIndex == OBJECT_TRU_LIMB_15) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
Matrix_MultVec3f(&gZeroVec3f, &this->unk_35C);
}
- if (limbIndex == OBJECT_TRU_LIMB_15) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
Matrix_MultVec3f(&D_80B7765C, &this->unk_350);
}
return false;
@@ -493,7 +512,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro
MtxF* sp54;
s32 phi_v0;
- if (limbIndex == OBJECT_TRU_LIMB_15) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
if (this->unk_328 & 0x10) {
phi_v0 = 1;
} else {
@@ -507,7 +526,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro
Matrix_RotateZS(this->unk_336.z, MTXMODE_APPLY);
}
- if (limbIndex == OBJECT_TRU_LIMB_0E) {
+ if (limbIndex == KOUME_LIMB_BROOM) {
func_8012C28C(play->state.gfxCtx);
OPEN_DISPS(play->state.gfxCtx);
@@ -520,7 +539,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro
Matrix_Scale(0.008f, 0.008f, 0.008f, MTXMODE_APPLY);
gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_OPA_DISP++, object_tru_DL_0004C8);
+ gSPDisplayList(POLY_OPA_DISP++, gKoumeChainDL);
CLOSE_DISPS(play->state.gfxCtx);
@@ -545,7 +564,7 @@ void EnTruMt_PostLimbDraw(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* ro
void EnTruMt_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) {
EnTruMt* this = THIS;
- if (limbIndex == OBJECT_TRU_LIMB_15) {
+ if (limbIndex == KOUME_LIMB_HEAD) {
Matrix_Translate(this->unk_33C.x, this->unk_33C.y, this->unk_33C.z, MTXMODE_NEW);
Matrix_Scale(this->actor.scale.x, this->actor.scale.y, this->actor.scale.z, MTXMODE_APPLY);
Matrix_RotateYS(this->unk_336.y, MTXMODE_APPLY);
@@ -556,18 +575,18 @@ void EnTruMt_TransformLimbDraw(PlayState* play, s32 limbIndex, Actor* thisx) {
void EnTruMt_Draw(Actor* thisx, PlayState* play) {
EnTruMt* this = THIS;
- TexturePtr sp48[] = {
- object_tru_Tex_018FA0,
- object_tru_Tex_0197A0,
- object_tru_Tex_019FA0,
+ TexturePtr eyeTextures[] = {
+ gKoumeEyeOpenTex,
+ gKoumeEyeHalfTex,
+ gKoumeEyeClosedTex,
};
OPEN_DISPS(play->state.gfxCtx);
func_8012C28C(play->state.gfxCtx);
- gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(sp48[this->unk_34C]));
- gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(sp48[this->unk_34C]));
+ gSPSegment(POLY_OPA_DISP++, 0x08, Lib_SegmentedToVirtual(eyeTextures[this->eyeTexIndex]));
+ gSPSegment(POLY_OPA_DISP++, 0x09, Lib_SegmentedToVirtual(eyeTextures[this->eyeTexIndex]));
SkelAnime_DrawTransformFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable,
this->skelAnime.dListCount, EnTruMt_OverrideLimbDraw, EnTruMt_PostLimbDraw,
diff --git a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h
index 670d0d728..54d58326e 100644
--- a/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h
+++ b/src/overlays/actors/ovl_En_Tru_Mt/z_en_tru_mt.h
@@ -16,16 +16,16 @@ typedef struct EnTruMt {
/* 0x144 */ EnTruMtActionFunc actionFunc;
/* 0x148 */ SkelAnime skelAnime;
/* 0x18C */ ColliderSphere collider;
- /* 0x1E4 */ Vec3s jointTable[OBJECT_TRU_LIMB_MAX];
- /* 0x286 */ Vec3s morphTable[OBJECT_TRU_LIMB_MAX];
+ /* 0x1E4 */ Vec3s jointTable[KOUME_LIMB_MAX];
+ /* 0x286 */ Vec3s morphTable[KOUME_LIMB_MAX];
/* 0x328 */ u16 unk_328;
/* 0x32A */ UNK_TYPE1 unk32A[0xC];
/* 0x336 */ Vec3s unk_336;
/* 0x33C */ Vec3f unk_33C;
/* 0x348 */ s16 unk_348;
/* 0x34A */ s16 unk_34A;
- /* 0x34C */ s16 unk_34C;
- /* 0x34E */ s16 unk_34E;
+ /* 0x34C */ s16 eyeTexIndex;
+ /* 0x34E */ s16 blinkTimer;
/* 0x350 */ Vec3f unk_350;
/* 0x35C */ Vec3f unk_35C;
/* 0x368 */ Path* path;
diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c
index 82cc5f2e2..0abf1fe56 100644
--- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c
+++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.c
@@ -1,10 +1,12 @@
/*
* File: z_en_wiz.c
* Overlay: ovl_En_Wiz
- * Description: Wizzrobe
+ * Description: Wizrobe
*/
#include "z_en_wiz.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
+#include "overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h"
#define FLAGS \
(ACTOR_FLAG_1 | ACTOR_FLAG_4 | ACTOR_FLAG_10 | ACTOR_FLAG_20 | ACTOR_FLAG_1000 | ACTOR_FLAG_100000 | \
@@ -17,7 +19,67 @@ void EnWiz_Destroy(Actor* thisx, PlayState* play);
void EnWiz_Update(Actor* thisx, PlayState* play);
void EnWiz_Draw(Actor* thisx, PlayState* play);
-#if 0
+void EnWiz_StartIntroCutscene(EnWiz* this, PlayState* play);
+void EnWiz_SetupAppear(EnWiz* this, PlayState* play);
+void EnWiz_Appear(EnWiz* this, PlayState* play);
+void EnWiz_SetupDance(EnWiz* this);
+void EnWiz_Dance(EnWiz* this, PlayState* play);
+void EnWiz_SetupSecondPhaseCutscene(EnWiz* this, PlayState* play);
+void EnWiz_SecondPhaseCutscene(EnWiz* this, PlayState* play);
+void EnWiz_SetupWindUp(EnWiz* this);
+void EnWiz_WindUp(EnWiz* this, PlayState* play);
+void EnWiz_SetupAttack(EnWiz* this);
+void EnWiz_Attack(EnWiz* this, PlayState* play);
+void EnWiz_SetupDisappear(EnWiz* this);
+void EnWiz_Disappear(EnWiz* this, PlayState* play);
+void EnWiz_Damaged(EnWiz* this, PlayState* play);
+void EnWiz_SetupDead(EnWiz* this);
+void EnWiz_Dead(EnWiz* this, PlayState* play);
+
+// This number is almost-entirely arbirary, with the only requirement being
+// that cannot be a valid curPlatformIndex. Any negative number, or any number
+// larger than 10, would work just as well.
+#define INITIAL_PLATFORM_INDEX 777
+
+typedef enum {
+ /* 1 */ EN_WIZ_ACTION_APPEAR = 1,
+ /* 2 */ EN_WIZ_ACTION_RUN_BETWEEN_PLATFORMS,
+ /* 3 */ EN_WIZ_ACTION_DISAPPEAR,
+ /* 4 */ EN_WIZ_ACTION_DAMAGED,
+ /* 5 */ EN_WIZ_ACTION_DEAD,
+ /* 6 */ EN_WIZ_ACTION_BURST_INTO_FLAMES,
+ /* 7 */ EN_WIZ_ACTION_RUN_IN_CIRCLES,
+ /* 8 */ EN_WIZ_ACTION_ATTACK,
+ /* 9 */ EN_WIZ_ACTION_DANCE,
+} EnWizAction;
+
+typedef enum {
+ /* 0 */ EN_WIZ_INTRO_CS_NOT_STARTED,
+ /* 1 */ EN_WIZ_INTRO_CS_CAMERA_MOVE_TO_PLATFORM,
+ /* 2 */ EN_WIZ_INTRO_CS_APPEAR,
+ /* 3 */ EN_WIZ_INTRO_CS_CAMERA_SPIN_TO_FACE_WIZROBE,
+ /* 4 */ EN_WIZ_INTRO_CS_WAIT_BEFORE_RUN,
+ /* 5 */ EN_WIZ_INTRO_CS_RUN_IN_CIRCLES,
+ /* 6 */ EN_WIZ_INTRO_CS_DISAPPEAR,
+ /* 7 */ EN_WIZ_INTRO_CS_END
+} EnWizIntroCutsceneState;
+
+typedef enum {
+ /* 0 */ EN_WIZ_FIGHT_STATE_FIRST_PHASE,
+ /* 1 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE,
+ /* 2 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE,
+ /* 3 */ EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND,
+} EnWizFightState;
+
+typedef enum {
+ /* 0 */ EN_WIZ_ANIM_IDLE,
+ /* 1 */ EN_WIZ_ANIM_RUN,
+ /* 2 */ EN_WIZ_ANIM_DANCE,
+ /* 3 */ EN_WIZ_ANIM_WIND_UP,
+ /* 4 */ EN_WIZ_ANIM_ATTACK,
+ /* 5 */ EN_WIZ_ANIM_DAMAGE,
+} EnWizAnimation;
+
const ActorInit En_Wiz_InitVars = {
ACTOR_EN_WIZ,
ACTORCAT_ENEMY,
@@ -30,199 +92,1470 @@ const ActorInit En_Wiz_InitVars = {
(ActorFunc)EnWiz_Draw,
};
-// static ColliderJntSphElementInit sJntSphElementsInit[10] = {
-static ColliderJntSphElementInit D_80A48B50[10] = {
+static ColliderJntSphElementInit sJntSphElementsInit[10] = {
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0x01000202, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_NONE, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 1 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0x01000202, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_NONE,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 1 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
{
- { ELEMTYPE_UNK0, { 0xF7CFFFFF, 0x00, 0x00 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_NONE, },
- { 1, { { 0, 0, 0 }, 0 }, 0 },
+ {
+ ELEMTYPE_UNK0,
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_NONE,
+ },
+ { WIZROBE_LIMB_PELVIS, { { 0, 0, 0 }, 0 }, 0 },
},
};
-// static ColliderJntSphInit sJntSphInit = {
-static ColliderJntSphInit D_80A48CB8 = {
- { COLTYPE_HIT2, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_NONE, OC2_TYPE_1, COLSHAPE_JNTSPH, },
- ARRAY_COUNT(sJntSphElementsInit), D_80A48B50, // sJntSphElementsInit,
+static ColliderJntSphInit sJntSphInit = {
+ {
+ COLTYPE_HIT2,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_NONE,
+ OC2_TYPE_1,
+ COLSHAPE_JNTSPH,
+ },
+ ARRAY_COUNT(sJntSphElementsInit),
+ sJntSphElementsInit,
};
-// static ColliderCylinderInit sCylinderInit = {
-static ColliderCylinderInit D_80A48CC8 = {
- { COLTYPE_NONE, AT_NONE, AC_ON | AC_TYPE_PLAYER, OC1_ON | OC1_TYPE_ALL, OC2_TYPE_1, COLSHAPE_CYLINDER, },
- { ELEMTYPE_UNK1, { 0xF7CFFFFF, 0x08, 0x04 }, { 0xF7CFFFFF, 0x00, 0x00 }, TOUCH_NONE | TOUCH_SFX_NORMAL, BUMP_ON, OCELEM_ON, },
+static ColliderCylinderInit sCylinderInit = {
+ {
+ COLTYPE_NONE,
+ AT_NONE,
+ AC_ON | AC_TYPE_PLAYER,
+ OC1_ON | OC1_TYPE_ALL,
+ OC2_TYPE_1,
+ COLSHAPE_CYLINDER,
+ },
+ {
+ ELEMTYPE_UNK1,
+ { 0xF7CFFFFF, 0x08, 0x04 },
+ { 0xF7CFFFFF, 0x00, 0x00 },
+ TOUCH_NONE | TOUCH_SFX_NORMAL,
+ BUMP_ON,
+ OCELEM_ON,
+ },
{ 35, 130, 0, { 0, 0, 0 } },
};
-// static DamageTable sDamageTable = {
-static DamageTable D_80A48CF4 = {
- /* Deku Nut */ DMG_ENTRY(0, 0x1),
- /* Deku Stick */ DMG_ENTRY(1, 0xF),
- /* Horse trample */ DMG_ENTRY(0, 0x0),
- /* Explosives */ DMG_ENTRY(1, 0xF),
- /* Zora boomerang */ DMG_ENTRY(1, 0xF),
- /* Normal arrow */ DMG_ENTRY(1, 0xF),
- /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
- /* Hookshot */ DMG_ENTRY(1, 0xF),
- /* Goron punch */ DMG_ENTRY(1, 0xF),
- /* Sword */ DMG_ENTRY(1, 0xF),
- /* Goron pound */ DMG_ENTRY(3, 0xF),
- /* Fire arrow */ DMG_ENTRY(1, 0x2),
- /* Ice arrow */ DMG_ENTRY(2, 0x3),
- /* Light arrow */ DMG_ENTRY(2, 0x4),
- /* Goron spikes */ DMG_ENTRY(0, 0x0),
- /* Deku spin */ DMG_ENTRY(1, 0xF),
- /* Deku bubble */ DMG_ENTRY(1, 0xF),
- /* Deku launch */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1),
- /* Zora barrier */ DMG_ENTRY(0, 0x0),
- /* Normal shield */ DMG_ENTRY(0, 0x0),
- /* Light ray */ DMG_ENTRY(0, 0x0),
- /* Thrown object */ DMG_ENTRY(1, 0xF),
- /* Zora punch */ DMG_ENTRY(1, 0xF),
- /* Spin attack */ DMG_ENTRY(1, 0xF),
- /* Sword beam */ DMG_ENTRY(0, 0x0),
- /* Normal Roll */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0),
- /* Unblockable */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0),
- /* Powder Keg */ DMG_ENTRY(1, 0xF),
+typedef enum {
+ /* 0x0 */ EN_WIZ_DMGEFF_IMMUNE, // Deals no damage
+ /* 0x1 */ EN_WIZ_DMGEFF_UNK1, // Deals no damage. Was probably originally intended for destroying ghosts.
+ /* 0x2 */ EN_WIZ_DMGEFF_FIRE, // Damages and sets Ice Wizrobes on fire
+ /* 0x3 */ EN_WIZ_DMGEFF_FREEZE, // Damages and surrounds Fire Wizrobes with ice
+ /* 0x4 */ EN_WIZ_DMGEFF_LIGHT_ORB, // Damages and surrounds the Wizrobe with light orbs
+ /* 0xF */ EN_WIZ_DMGEFF_NONE = 0xF, // Deals regular damage and has no special effect
+} EnWizDamageEffect;
+
+static DamageTable sFireWizrobeDamageTable = {
+ /* Deku Nut */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1),
+ /* Deku Stick */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Horse trample */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Explosives */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Zora boomerang */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Normal arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* UNK_DMG_D_06 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Hookshot */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Goron punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Sword */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Goron pound */ DMG_ENTRY(3, EN_WIZ_DMGEFF_NONE),
+ /* Fire arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_FIRE),
+ /* Ice arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_FREEZE),
+ /* Light arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_LIGHT_ORB),
+ /* Goron spikes */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Deku spin */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Deku bubble */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Deku launch */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1),
+ /* Zora barrier */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Normal shield */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Light ray */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Thrown object */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Zora punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Spin attack */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Sword beam */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Normal Roll */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Unblockable */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Powder Keg */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
};
-// static DamageTable sDamageTable = {
-static DamageTable D_80A48D14 = {
- /* Deku Nut */ DMG_ENTRY(0, 0x1),
- /* Deku Stick */ DMG_ENTRY(1, 0xF),
- /* Horse trample */ DMG_ENTRY(0, 0x0),
- /* Explosives */ DMG_ENTRY(1, 0xF),
- /* Zora boomerang */ DMG_ENTRY(1, 0xF),
- /* Normal arrow */ DMG_ENTRY(1, 0xF),
- /* UNK_DMG_0x06 */ DMG_ENTRY(0, 0x0),
- /* Hookshot */ DMG_ENTRY(1, 0xF),
- /* Goron punch */ DMG_ENTRY(2, 0xF),
- /* Sword */ DMG_ENTRY(1, 0xF),
- /* Goron pound */ DMG_ENTRY(3, 0xF),
- /* Fire arrow */ DMG_ENTRY(2, 0x2),
- /* Ice arrow */ DMG_ENTRY(1, 0x3),
- /* Light arrow */ DMG_ENTRY(2, 0x4),
- /* Goron spikes */ DMG_ENTRY(0, 0x0),
- /* Deku spin */ DMG_ENTRY(1, 0xF),
- /* Deku bubble */ DMG_ENTRY(1, 0xF),
- /* Deku launch */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x12 */ DMG_ENTRY(0, 0x1),
- /* Zora barrier */ DMG_ENTRY(0, 0x0),
- /* Normal shield */ DMG_ENTRY(0, 0x0),
- /* Light ray */ DMG_ENTRY(0, 0x0),
- /* Thrown object */ DMG_ENTRY(1, 0xF),
- /* Zora punch */ DMG_ENTRY(1, 0xF),
- /* Spin attack */ DMG_ENTRY(1, 0xF),
- /* Sword beam */ DMG_ENTRY(0, 0x0),
- /* Normal Roll */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1B */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1C */ DMG_ENTRY(0, 0x0),
- /* Unblockable */ DMG_ENTRY(0, 0x0),
- /* UNK_DMG_0x1E */ DMG_ENTRY(0, 0x0),
- /* Powder Keg */ DMG_ENTRY(1, 0xF),
+static DamageTable sIceWizrobeDamageTable = {
+ /* Deku Nut */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1),
+ /* Deku Stick */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Horse trample */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Explosives */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Zora boomerang */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Normal arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* UNK_DMG_D_06 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Hookshot */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Goron punch */ DMG_ENTRY(2, EN_WIZ_DMGEFF_NONE),
+ /* Sword */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Goron pound */ DMG_ENTRY(3, EN_WIZ_DMGEFF_NONE),
+ /* Fire arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_FIRE),
+ /* Ice arrow */ DMG_ENTRY(1, EN_WIZ_DMGEFF_FREEZE),
+ /* Light arrow */ DMG_ENTRY(2, EN_WIZ_DMGEFF_LIGHT_ORB),
+ /* Goron spikes */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Deku spin */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Deku bubble */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Deku launch */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x12 */ DMG_ENTRY(0, EN_WIZ_DMGEFF_UNK1),
+ /* Zora barrier */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Normal shield */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Light ray */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Thrown object */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Zora punch */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Spin attack */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
+ /* Sword beam */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Normal Roll */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1B */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1C */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Unblockable */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* UNK_DMG_0x1E */ DMG_ENTRY(0, EN_WIZ_DMGEFF_IMMUNE),
+ /* Powder Keg */ DMG_ENTRY(1, EN_WIZ_DMGEFF_NONE),
};
-#endif
+void EnWiz_Init(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnWiz* this = THIS;
-extern ColliderJntSphElementInit D_80A48B50[10];
-extern ColliderJntSphInit D_80A48CB8;
-extern ColliderCylinderInit D_80A48CC8;
-extern DamageTable D_80A48CF4;
-extern DamageTable D_80A48D14;
+ SkelAnime_InitFlex(play, &this->skelAnime, &gWizrobeSkel, &gWizrobeIdleAnim, this->jointTable, this->morphTable,
+ WIZROBE_LIMB_MAX);
+ SkelAnime_InitFlex(play, &this->ghostSkelAnime, &gWizrobeSkel, &gWizrobeIdleAnim, this->ghostBaseJointTable,
+ this->ghostMorphTable, WIZROBE_LIMB_MAX);
+ Actor_SetScale(&this->actor, 0.0f);
+ this->platformLightAlpha = 0;
+ this->alpha = 255;
+ this->actor.colChkInfo.mass = MASS_IMMOVABLE;
+ this->actor.targetMode = 3;
+ this->unk_450 = 1.0f;
+ this->actor.shape.yOffset = 700.0f;
+ Collider_InitAndSetJntSph(play, &this->ghostColliders, &this->actor, &sJntSphInit, this->ghostColliderElements);
+ Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
+ this->staffFlameScroll = Rand_S16Offset(0, 7);
+ this->switchFlag = EN_WIZ_GET_SWITCHFLAG(&this->actor);
+ this->type = EN_WIZ_GET_TYPE(&this->actor);
-extern UNK_TYPE D_0600211C;
-extern UNK_TYPE D_060025F0;
-extern UNK_TYPE D_060066C0;
+ if (this->switchFlag == 0x7F) {
+ this->switchFlag = -1;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Init.s")
+ if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ this->actor.colChkInfo.damageTable = &sFireWizrobeDamageTable;
+ this->actor.colChkInfo.health = 8;
+ this->actor.flags &= ~ACTOR_FLAG_100000;
+ } else {
+ this->actor.colChkInfo.damageTable = &sIceWizrobeDamageTable;
+ this->actor.colChkInfo.health = 6;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Destroy.s")
+ if ((this->switchFlag >= 0) && (Flags_GetSwitch(play, this->switchFlag))) {
+ Actor_MarkForDeath(&this->actor);
+ return;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A455C4.s")
+ this->actor.hintId = TATL_HINT_ID_WIZROBE;
+ this->curPlatformIndex = INITIAL_PLATFORM_INDEX;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A456A0.s")
+ // Setting the radius and scale to zero here effectively disables all of the ghost colliders.
+ this->ghostColliders.elements[0].dim.modelSphere.radius = 0;
+ this->ghostColliders.elements[0].dim.scale = 0.0f;
+ this->ghostColliders.elements[0].dim.modelSphere.center.x = 0;
+ this->ghostColliders.elements[0].dim.modelSphere.center.y = 0;
+ this->ghostColliders.elements[0].dim.modelSphere.center.z = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A45CD8.s")
+ this->actionFunc = EnWiz_StartIntroCutscene;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A460A4.s")
+void EnWiz_Destroy(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnWiz* this = THIS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46280.s")
+ Collider_DestroyCylinder(play, &this->collider);
+ Collider_DestroyJntSph(play, &this->ghostColliders);
+ if (this->type != EN_WIZ_TYPE_FIRE_NO_BGM) {
+ Audio_RestorePrevBgm();
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A462F8.s")
+static AnimationHeader* sAnimations[] = {
+ &gWizrobeIdleAnim, // EN_WIZ_ANIM_IDLE
+ &gWizrobeRunAnim, // EN_WIZ_ANIM_RUN
+ &gWizrobeDanceAnim, // EN_WIZ_ANIM_DANCE
+ &gWizrobeWindUpAnim, // EN_WIZ_ANIM_WIND_UP
+ &gWizrobeAttackAnim, // EN_WIZ_ANIM_ATTACK
+ &gWizrobeDamageAnim, // EN_WIZ_ANIM_DAMAGE
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46414.s")
+static u8 sAnimationModes[] = {
+ ANIMMODE_LOOP, // EN_WIZ_ANIM_IDLE
+ ANIMMODE_LOOP, // EN_WIZ_ANIM_RUN
+ ANIMMODE_LOOP, // EN_WIZ_ANIM_DANCE
+ ANIMMODE_LOOP, // EN_WIZ_ANIM_WIND_UP
+ ANIMMODE_LOOP, // EN_WIZ_ANIM_ATTACK
+ ANIMMODE_ONCE, // EN_WIZ_ANIM_DAMAGE
+};
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A4668C.s")
+void EnWiz_ChangeAnim(EnWiz* this, s32 animIndex, s32 updateGhostAnim) {
+ this->endFrame = Animation_GetLastFrame(sAnimations[animIndex]);
+ Animation_Change(&this->skelAnime, sAnimations[animIndex], 1.0f, 0.0f, this->endFrame, sAnimationModes[animIndex],
+ -2.0f);
+ if (updateGhostAnim) {
+ Animation_Change(&this->ghostSkelAnime, sAnimations[animIndex], 1.0f, 0.0f, this->endFrame,
+ sAnimationModes[animIndex], -2.0f);
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46764.s")
+/**
+ * Responsible for moving the camera around and making the Wizrobe run in circles during the intro cutscene.
+ */
+void EnWiz_HandleIntroCutscene(EnWiz* this, PlayState* play) {
+ Camera* subCam;
+ Vec3f eyeNext;
+ Vec3f atNext;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A468CC.s")
+ if (this->introCutsceneState < EN_WIZ_INTRO_CS_DISAPPEAR) {
+ subCam = Play_GetCamera(play, this->subCamId);
+ switch (this->introCutsceneState) {
+ case EN_WIZ_INTRO_CS_NOT_STARTED:
+ this->introCutsceneTimer = 100;
+ this->introCutsceneCameraAngle = this->actor.world.rot.y;
+ this->introCutsceneState++;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46990.s")
+ case EN_WIZ_INTRO_CS_CAMERA_MOVE_TO_PLATFORM:
+ Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos);
+ Math_Vec3f_Copy(&atNext, &this->actor.world.pos);
+ eyeNext.x += Math_SinS(this->introCutsceneCameraAngle) * 200.0f;
+ eyeNext.y += 100.0f;
+ eyeNext.z += Math_CosS(this->introCutsceneCameraAngle) * 200.0f;
+ atNext.y += 80.0f;
+ Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f);
+ subCam->eye.y = eyeNext.y;
+ subCam->at.y = atNext.y;
+ if ((fabsf(subCam->eye.x - eyeNext.x) < 2.0f) && (fabsf(subCam->eye.y - eyeNext.y) < 2.0f) &&
+ (fabsf(subCam->eye.z - eyeNext.z) < 2.0f) && (fabsf(subCam->at.x - atNext.x) < 2.0f) &&
+ (fabsf(subCam->at.y - atNext.y) < 2.0f) && (fabsf(subCam->at.z - atNext.z) < 2.0f)) {
+ Player* player = GET_PLAYER(play);
+ s32 i;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46C88.s")
+ this->actor.world.rot.y = this->actor.shape.rot.y =
+ Math_Vec3f_Yaw(&this->actor.world.pos, &player->actor.world.pos);
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46CC4.s")
+ for (i = 0; i < this->platformCount; i++) {
+ this->ghostRot[i].y = Math_Vec3f_Yaw(&this->ghostPos[i], &player->actor.world.pos);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46DDC.s")
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, true);
+ this->shouldStartTimer = false;
+ this->targetPlatformLightAlpha = 255;
+ Math_Vec3f_Copy(&this->platformLightPos, &this->actor.world.pos);
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_UNARI);
+ } else {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG);
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A46E24.s")
+ this->introCutsceneTimer = 40;
+ this->introCutsceneState++;
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47000.s")
+ case EN_WIZ_INTRO_CS_APPEAR:
+ if (this->introCutsceneTimer == 0) {
+ this->introCutsceneTimer = 20;
+ this->introCutsceneState++;
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A470D8.s")
+ case EN_WIZ_INTRO_CS_CAMERA_SPIN_TO_FACE_WIZROBE:
+ Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos);
+ Math_Vec3f_Copy(&atNext, &this->actor.world.pos);
+ eyeNext.x += Math_SinS(this->actor.world.rot.y) * 160.0f;
+ eyeNext.y += 70.0f;
+ eyeNext.z += Math_CosS(this->actor.world.rot.y) * 140.0f;
+ atNext.x += -10.0f;
+ atNext.y += 100.0f;
+ Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f);
+ subCam->eye.y = eyeNext.y;
+ subCam->at.y = atNext.y;
+ if (this->introCutsceneTimer == 0) {
+ this->introCutsceneTimer = 10;
+ this->introCutsceneState++;
+ this->introCutsceneCameraAngle = this->actor.world.rot.y;
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47298.s")
+ case EN_WIZ_INTRO_CS_WAIT_BEFORE_RUN:
+ if (this->introCutsceneTimer == 0) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_RUN, false);
+ this->rotationalVelocity = 0;
+ this->introCutsceneTimer = 34;
+ this->introCutsceneState++;
+ }
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A473B8.s")
+ case EN_WIZ_INTRO_CS_RUN_IN_CIRCLES:
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG);
+ if (this->introCutsceneTimer == 0) {
+ this->animLoopCounter = this->introCutsceneCameraAngle = 0;
+ this->introCutsceneState = EN_WIZ_INTRO_CS_DISAPPEAR;
+ } else {
+ Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8);
+ this->actor.world.rot.y += this->rotationalVelocity;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A4767C.s")
+ Math_Vec3f_Copy(&eyeNext, &this->actor.world.pos);
+ Math_Vec3f_Copy(&atNext, &this->actor.world.pos);
+ eyeNext.x += Math_SinS(this->introCutsceneCameraAngle) * 200.0f;
+ eyeNext.y += 100.0f;
+ eyeNext.z += Math_CosS(this->introCutsceneCameraAngle) * 200.0f;
+ atNext.y += 80.0f;
+ Math_ApproachF(&subCam->eye.x, eyeNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->eye.z, eyeNext.z, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.x, atNext.x, 0.3f, 30.0f);
+ Math_ApproachF(&subCam->at.z, atNext.z, 0.3f, 30.0f);
+ subCam->eye.y = eyeNext.y;
+ subCam->at.y = atNext.y;
+ break;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A476C8.s")
+ default:
+ break;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A477E8.s")
+ if (this->musicStartTimer < 11) {
+ this->musicStartTimer++;
+ if ((this->type != EN_WIZ_TYPE_FIRE_NO_BGM) && (this->musicStartTimer == 11)) {
+ Audio_PlayBgm_StorePrevBgm(NA_BGM_MINI_BOSS);
+ }
+ }
+ }
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Update.s")
+/**
+ * Chooses which platform the Wizrobe should appear at, and updates its position accordingly.
+ * It also updates the position and alpha of all the ghosts.
+ */
+void EnWiz_SelectPlatform(EnWiz* this, PlayState* play) {
+ Actor* prop;
+ s32 i;
+ s32 j;
+ s16 ghostAlpha;
+ s16 type;
+ s16 curPlatformIndex;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A47FCC.s")
+ for (i = 0; i < ARRAY_COUNT(this->platforms); i++) {
+ this->platforms[i] = NULL;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/func_80A48138.s")
+ prop = play->actorCtx.actorLists[ACTORCAT_PROP].first;
+ i = 0;
+ while (prop != NULL) {
+ if (prop->id != ACTOR_EN_WIZ_BROCK) {
+ prop = prop->next;
+ continue;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Wiz/EnWiz_Draw.s")
+ this->platforms[i] = prop;
+ i++;
+ if (this->action != EN_WIZ_ACTION_BURST_INTO_FLAMES) {
+ type = this->type;
+ if (type == EN_WIZ_TYPE_FIRE_NO_BGM) {
+ type = EN_WIZ_TYPE_FIRE;
+ }
+
+ prop->colChkInfo.health = type + EN_WIZ_BROCK_PLATFORM_TYPE_FIRE;
+ prop = prop->next;
+ } else {
+ prop->colChkInfo.health = EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE;
+ prop = prop->next;
+ }
+ }
+
+ if (this->action != EN_WIZ_ACTION_DEAD) {
+ this->platformCount = i;
+ if (i < 0) {
+ i = 0;
+ } else if (this->platformCount > 10) {
+ this->platformCount = 10;
+ }
+
+ curPlatformIndex = Rand_ZeroFloat(i);
+ while ((this->curPlatformIndex == curPlatformIndex) || ((s16)i == curPlatformIndex)) {
+ curPlatformIndex = Rand_ZeroFloat(i);
+ if (1) {}
+ }
+
+ this->curPlatformIndex = curPlatformIndex;
+ switch (this->fightState) {
+ case EN_WIZ_FIGHT_STATE_FIRST_PHASE:
+ Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[curPlatformIndex]->world.pos);
+ break;
+
+ case EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE:
+ Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[0]->world.pos);
+ for (i = 0, ghostAlpha = 128; i < this->platformCount; i++, ghostAlpha -= 10) {
+ Math_Vec3f_Copy(&this->ghostPos[i], &this->actor.world.pos);
+ this->ghostAlpha[i] = ghostAlpha;
+ }
+ break;
+
+ default:
+ Math_Vec3f_Copy(&this->actor.world.pos, &this->platforms[curPlatformIndex]->world.pos);
+ for (i--; i >= 0; i--) {
+ if (curPlatformIndex != i) {
+ Math_Vec3f_Copy(&this->ghostPos[i], &this->platforms[i]->world.pos);
+ this->ghostRot[i] = this->actor.world.rot;
+ this->ghostAlpha[i] = 100;
+ this->ghostNextPlatformIndex[i] = i;
+ for (j = 0; j < ARRAY_COUNT(this->jointTable); j++) {
+ this->ghostJointTables[i][j] = this->jointTable[j];
+ }
+ } else {
+ Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f);
+ }
+ }
+ break;
+ }
+ }
+}
+
+/**
+ * Makes the ghosts run around the room from platform to platform.
+ */
+void EnWiz_MoveGhosts(EnWiz* this) {
+ s32 i;
+ s32 ghostNextPlatformIndex;
+ s32 playSfx = false;
+
+ for (i = 0; i < this->platformCount; i++) {
+ if (this->ghostPos[i].x != 0.0f && this->ghostPos[i].z != 0.0f) {
+ f32 diffX;
+ f32 diffZ;
+
+ ghostNextPlatformIndex = this->ghostNextPlatformIndex[i];
+ diffX = this->platforms[ghostNextPlatformIndex]->world.pos.x - this->ghostPos[i].x;
+ diffZ = this->platforms[ghostNextPlatformIndex]->world.pos.z - this->ghostPos[i].z;
+ playSfx++;
+
+ if (sqrtf(SQ(diffX) + SQ(diffZ)) < 30.0f) {
+ this->ghostNextPlatformIndex[i]--;
+ if (this->ghostNextPlatformIndex[i] < 0) {
+ this->ghostNextPlatformIndex[i] = this->platformCount - 1;
+ }
+ }
+
+ ghostNextPlatformIndex = this->ghostNextPlatformIndex[i];
+ Math_ApproachF(&this->ghostPos[i].x, this->platforms[ghostNextPlatformIndex]->world.pos.x, 0.3f, 30.0f);
+ Math_ApproachF(&this->ghostPos[i].y, this->platforms[ghostNextPlatformIndex]->world.pos.y, 0.3f, 30.0f);
+ Math_ApproachF(&this->ghostPos[i].z, this->platforms[ghostNextPlatformIndex]->world.pos.z, 0.3f, 30.0f);
+ this->ghostRot[i].y =
+ Math_Vec3f_Yaw(&this->ghostPos[i], &this->platforms[ghostNextPlatformIndex]->world.pos);
+ }
+ }
+
+ if (playSfx) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG);
+ }
+}
+
+void EnWiz_StartIntroCutscene(EnWiz* this, PlayState* play) {
+ if (ActorCutscene_GetCanPlayNext(this->actor.cutscene)) {
+ ActorCutscene_StartAndSetFlag(this->actor.cutscene, &this->actor);
+ this->subCamId = ActorCutscene_GetCurrentSubCamId(this->actor.cutscene);
+ this->actor.flags |= ACTOR_FLAG_100000;
+ EnWiz_SetupAppear(this, play);
+ } else {
+ ActorCutscene_SetIntentToPlay(this->actor.cutscene);
+ }
+}
+
+void EnWiz_SetupAppear(EnWiz* this, PlayState* play) {
+ Player* player = GET_PLAYER(play);
+ s32 i;
+ s16 angle;
+
+ this->action = EN_WIZ_ACTION_APPEAR;
+
+ if (this->timer == 0) {
+ EnWiz_SelectPlatform(this, play);
+
+ if (this->introCutsceneState != EN_WIZ_INTRO_CS_NOT_STARTED) {
+ angle = Math_Vec3f_Yaw(&this->actor.world.pos, &player->actor.world.pos);
+ this->actor.shape.rot.y = angle;
+ this->actor.world.rot.y = angle;
+ for (i = 0; i < this->platformCount; i++) {
+ this->ghostRot[i].y = Math_Vec3f_Yaw(&this->ghostPos[i], &player->actor.world.pos);
+ }
+
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, true);
+ this->shouldStartTimer = false;
+ this->targetPlatformLightAlpha = 255;
+ Math_Vec3f_Copy(&this->platformLightPos, &this->actor.world.pos);
+
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_UNARI);
+ } else {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG);
+ }
+ }
+
+ this->actionFunc = EnWiz_Appear;
+ }
+}
+
+/**
+ * Makes the Wizrobe grow in scale and become more opaque.
+ * During the first phase, it also increases the alpha for the platform's light.
+ * If the player gets too close during the first phase, this will set up the Wizrobe to disappear.
+ */
+void EnWiz_Appear(EnWiz* this, PlayState* play) {
+ Vec3f staffTargetFlameScale = { 0.006f, 0.006f, 0.006f };
+ Player* player = GET_PLAYER(play);
+
+ EnWiz_HandleIntroCutscene(this, play);
+
+ if (this->introCutsceneState >= EN_WIZ_INTRO_CS_APPEAR) {
+ SkelAnime_Update(&this->skelAnime);
+
+ if ((this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) &&
+ (this->introCutsceneState >= EN_WIZ_INTRO_CS_DISAPPEAR) &&
+ ((this->actor.xzDistToPlayer < 200.0f) ||
+ ((player->unk_D57 != 0) &&
+ ((ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, this->actor.shape.rot.y)) < 0x7D0)) &&
+ (ABS_ALT(BINANG_SUB(this->actor.yawTowardsPlayer, BINANG_ADD(player->actor.shape.rot.y, 0x8000))) <
+ 0x7D0)))) {
+ EnWiz_SetupDisappear(this);
+ } else {
+ Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xA, 0xBB8, 0);
+
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 10, 10);
+ if (!this->shouldStartTimer) {
+ this->timer = 20;
+ this->shouldStartTimer = true;
+ }
+ } else {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_VOICE - SFX_FLAG);
+ }
+
+ if (this->timer == 0) {
+ Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.01f);
+ Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0);
+ }
+
+ if (this->scale < 0.0138f) {
+ return;
+ } else {
+ this->action = EN_WIZ_ACTION_RUN_IN_CIRCLES;
+ this->actor.flags &= ~ACTOR_FLAG_8000000;
+ this->ghostColliders.elements[0].info.bumper.dmgFlags = 0x1013A22;
+ Math_Vec3f_Copy(&this->staffTargetFlameScale, &staffTargetFlameScale);
+ this->targetPlatformLightAlpha = 0;
+
+ if (this->introCutsceneState == EN_WIZ_INTRO_CS_DISAPPEAR) {
+ this->timer = 0;
+ this->introCutsceneTimer = 20;
+ EnWiz_SetupDisappear(this);
+ } else if (this->introCutsceneState >= EN_WIZ_INTRO_CS_END) {
+ if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE) {
+ this->actionFunc = EnWiz_SetupSecondPhaseCutscene;
+ } else {
+ EnWiz_SetupDance(this);
+ }
+ }
+ }
+ }
+ }
+}
+
+void EnWiz_SetupDance(EnWiz* this) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DANCE, false);
+ Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.001f);
+ this->rotationalVelocity = 0;
+ this->animLoopCounter = 0;
+ this->action = EN_WIZ_ACTION_DANCE;
+ if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE) {
+ Animation_Change(&this->ghostSkelAnime, &gWizrobeRunAnim, 1.0f, 0.0f, Animation_GetLastFrame(&gWizrobeRunAnim),
+ ANIMMODE_LOOP, 0.0f);
+ this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND;
+ }
+
+ Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0);
+ this->actionFunc = EnWiz_Dance;
+}
+
+/**
+ * Makes the Wizrobe spin around and dance until there are no active projectiles
+ * and it completes at least three loops of its dancing animation.
+ */
+void EnWiz_Dance(EnWiz* this, PlayState* play) {
+ f32 curFrame = this->skelAnime.curFrame;
+ s32 i;
+
+ Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0);
+ Math_ApproachF(&this->scale, 0.015f, 0.05f, 0.001f);
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG);
+ this->actor.world.rot.y += this->rotationalVelocity;
+ if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) {
+ EnWiz_MoveGhosts(this);
+ } else {
+ for (i = 0; i < this->platformCount; i++) {
+ this->ghostRot[i].y += this->rotationalVelocity;
+ }
+ }
+
+ Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8);
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 20, 50, 10);
+ if (this->endFrame <= curFrame) {
+ if (this->animLoopCounter < 10) {
+ this->animLoopCounter++;
+ }
+ }
+
+ if ((this->animLoopCounter >= 3) && (!this->hasActiveProjectile)) {
+ this->targetPlatformLightAlpha = 0;
+ EnWiz_SetupWindUp(this);
+ }
+}
+
+void EnWiz_SetupSecondPhaseCutscene(EnWiz* this, PlayState* play) {
+ s16 secondPhaseCutscene = ActorCutscene_GetAdditionalCutscene(this->actor.cutscene);
+
+ if (!ActorCutscene_GetCanPlayNext(secondPhaseCutscene)) {
+ ActorCutscene_SetIntentToPlay(secondPhaseCutscene);
+ } else {
+ ActorCutscene_StartAndSetFlag(secondPhaseCutscene, &this->actor);
+ this->subCamId = ActorCutscene_GetCurrentSubCamId(secondPhaseCutscene);
+ this->actor.flags |= ACTOR_FLAG_100000;
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DANCE, false);
+ this->action = EN_WIZ_ACTION_RUN_BETWEEN_PLATFORMS;
+ this->nextPlatformIndex = 1;
+ this->hasRunToEveryPlatform = false;
+ Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0);
+ this->actionFunc = EnWiz_SecondPhaseCutscene;
+ }
+}
+
+/**
+ * Makes the Wizrobe run between every platform in the room once before returning to its
+ * original platform and disappearing. Ghosts trail behind the Wizrobe as it runs.
+ */
+void EnWiz_SecondPhaseCutscene(EnWiz* this, PlayState* play) {
+ Camera* subCam;
+ s32 i;
+
+ Math_SmoothStepToS(&this->alpha, 255, 1, 5, 0);
+ subCam = Play_GetCamera(play, this->subCamId);
+ Math_Vec3f_Copy(&subCam->at, &this->actor.focus.pos);
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_RUN - SFX_FLAG);
+ if (this->platforms[this->nextPlatformIndex] != NULL) {
+ f32 diffX = this->actor.world.pos.x - this->platforms[this->nextPlatformIndex]->world.pos.x;
+ f32 diffZ = this->actor.world.pos.z - this->platforms[this->nextPlatformIndex]->world.pos.z;
+ s32 pad;
+
+ if (sqrtf(SQ(diffX) + SQ(diffZ)) < 30.0f) {
+ if (!this->hasRunToEveryPlatform) {
+ this->nextPlatformIndex++;
+ if (this->nextPlatformIndex >= this->platformCount) {
+ this->hasRunToEveryPlatform = true;
+ this->nextPlatformIndex = 0;
+ }
+ } else {
+ f32 diffX = this->actor.world.pos.x - this->ghostPos[this->platformCount].x;
+ f32 diffZ = this->actor.world.pos.z - this->ghostPos[this->platformCount].z;
+ s32 pad;
+ s32 i;
+
+ this->actor.flags |= ACTOR_FLAG_8000000;
+ if (sqrtf(SQ(diffX) + SQ(diffZ)) < 20.0f) {
+ for (i = 0; i < this->platformCount; i++) {
+ Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f);
+ }
+
+ this->nextPlatformIndex = 0;
+ this->platformCount = 0;
+ this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE;
+ this->timer = 0;
+ ActorCutscene_Stop(ActorCutscene_GetAdditionalCutscene(this->actor.cutscene));
+ this->actor.flags &= ~ACTOR_FLAG_100000;
+ EnWiz_SetupDisappear(this);
+ return;
+ }
+ }
+ }
+ }
+
+ Math_Vec3f_Copy(this->ghostPos, &this->actor.world.pos);
+ this->ghostRot[0].y = this->actor.world.rot.y;
+ Math_ApproachF(&this->actor.world.pos.x, this->platforms[this->nextPlatformIndex]->world.pos.x, 0.3f, 30.0f);
+ Math_ApproachF(&this->actor.world.pos.y, this->platforms[this->nextPlatformIndex]->world.pos.y, 0.3f, 30.0f);
+ Math_ApproachF(&this->actor.world.pos.z, this->platforms[this->nextPlatformIndex]->world.pos.z, 0.3f, 30.0f);
+ for (i = this->platformCount; i > 0; i--) {
+ Math_Vec3f_Copy(&this->ghostPos[i], &this->ghostPos[i - 1]);
+ this->ghostRot[i].y = this->ghostRot[i - 1].y;
+ }
+
+ this->actor.world.rot.y =
+ Math_Vec3f_Yaw(&this->actor.world.pos, &this->platforms[this->nextPlatformIndex]->world.pos);
+}
+
+void EnWiz_SetupWindUp(EnWiz* this) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_WIND_UP, false);
+ this->animLoopCounter = 0;
+ this->actionFunc = EnWiz_WindUp;
+}
+
+/**
+ * Plays the wind up animation for at least two animation loops before attacking.
+ */
+void EnWiz_WindUp(EnWiz* this, PlayState* play) {
+ f32 curFrame = this->skelAnime.curFrame;
+ s32 i;
+
+ Math_SmoothStepToS(&this->actor.world.rot.y, this->actor.yawTowardsPlayer, 0xC8, 0x1F40, 0x1388);
+ if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) {
+ EnWiz_MoveGhosts(this);
+ } else {
+ for (i = 0; i < this->platformCount; i++) {
+ Math_SmoothStepToS(&this->ghostRot[i].y, this->actor.yawTowardsPlayer, 0xC8, 0x1F40, 0x1388);
+ }
+ }
+
+ if (this->endFrame <= curFrame) {
+ this->animLoopCounter++;
+ if (this->animLoopCounter >= 2) {
+ EnWiz_SetupAttack(this);
+ }
+ }
+
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 10, 10);
+}
+
+void EnWiz_SetupAttack(EnWiz* this) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_ATTACK, false);
+ this->timer = 0;
+ this->shouldStartTimer = false;
+ this->action = EN_WIZ_ACTION_ATTACK;
+ this->actionFunc = EnWiz_Attack;
+}
+
+/**
+ * Spawns an EnWizFire projectile that is pointed at the player, then disappears.
+ */
+void EnWiz_Attack(EnWiz* this, PlayState* play) {
+ f32 curFrame = this->skelAnime.curFrame;
+
+ if (this->fightState >= EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) {
+ EnWiz_MoveGhosts(this);
+ }
+
+ if (this->timer == 0) {
+ if ((Animation_OnFrame(&this->skelAnime, 6.0f)) && (!this->hasActiveProjectile)) {
+ Player* player = GET_PLAYER(play);
+ Vec3f pos;
+ s32 type = this->type;
+
+ Math_Vec3f_Copy(&pos, &this->actor.world.pos);
+ pos.x += Math_SinS(this->actor.world.rot.y) * 40.0f;
+ pos.y += 60.0f;
+ pos.z += Math_CosS(this->actor.world.rot.y) * 40.0f;
+ if (type == EN_WIZ_TYPE_FIRE_NO_BGM) {
+ type = EN_WIZ_TYPE_FIRE;
+ }
+
+ Actor_SpawnAsChild(&play->actorCtx, &this->actor, play, ACTOR_EN_WIZ_FIRE, pos.x, pos.y, pos.z,
+ Math_Vec3f_Pitch(&pos, &player->actor.world.pos),
+ Math_Vec3f_Yaw(&pos, &player->actor.world.pos), 0, type * 4);
+ this->hasActiveProjectile = true;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_ATTACK);
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_PL_MAGIC_FIRE);
+ }
+
+ if ((curFrame >= 8.0f) && !this->shouldStartTimer) {
+ this->timer = 3;
+ this->shouldStartTimer = true;
+ }
+
+ if (this->endFrame <= curFrame) {
+ EnWiz_SetupDisappear(this);
+ }
+ }
+}
+
+void EnWiz_SetupDisappear(EnWiz* this) {
+ if (this->action != EN_WIZ_ACTION_DAMAGED) {
+ this->rotationalVelocity = 0x2710;
+ this->timer = 0;
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_IDLE, false);
+ this->action = EN_WIZ_ACTION_DISAPPEAR;
+ } else {
+ this->rotationalVelocity = 0x2710;
+ this->actor.world.rot.y += this->rotationalVelocity;
+ }
+
+ this->targetPlatformLightAlpha = 0;
+ this->actor.flags |= ACTOR_FLAG_8000000;
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DISAPPEAR);
+ Math_SmoothStepToS(&this->rotationalVelocity, 0x1388, 0x64, 0x3E8, 0x3E8);
+ this->actor.world.rot.y += this->rotationalVelocity;
+ this->actor.flags &= ~ACTOR_FLAG_1;
+ this->actionFunc = EnWiz_Disappear;
+}
+
+/**
+ * Spin the Wizrobe around and shrink it so that it disappears into its platform.
+ * Afterwards, set it up to appear again.
+ */
+void EnWiz_Disappear(EnWiz* this, PlayState* play) {
+ s32 i;
+
+ Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14);
+ this->actor.world.rot.y += this->rotationalVelocity;
+ if ((this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) || (this->action == EN_WIZ_ACTION_DAMAGED)) {
+ Math_ApproachZeroF(&this->scale, 0.3f, 0.01f);
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 5, 50, 0);
+ } else {
+ Math_ApproachZeroF(&this->scale, 0.3f, 0.001f);
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 10, 50, 0);
+ for (i = 0; i < this->platformCount; i++) {
+ this->ghostRot[i].y += this->rotationalVelocity;
+ }
+ }
+
+ Math_Vec3f_Copy(&this->staffTargetFlameScale, &gZeroVec3f);
+ if (this->scale < 0.001f) {
+ this->scale = 0.0f;
+
+ if ((this->introCutsceneState == EN_WIZ_INTRO_CS_DISAPPEAR) && (this->introCutsceneTimer == 0)) {
+ this->introCutsceneState = EN_WIZ_INTRO_CS_END;
+ ActorCutscene_Stop(this->actor.cutscene);
+ this->actor.flags &= ~ACTOR_FLAG_100000;
+ }
+
+ if (this->introCutsceneState != EN_WIZ_INTRO_CS_DISAPPEAR) {
+ this->alpha = 0;
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ this->ghostColliders.elements[0].info.bumper.dmgFlags = 0x1000202;
+ }
+
+ this->actor.flags |= ACTOR_FLAG_1;
+ this->actionFunc = EnWiz_SetupAppear;
+ }
+ }
+}
+
+void EnWiz_SetupDamaged(EnWiz* this, PlayState* play) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DAMAGE, false);
+ Actor_SetColorFilter(&this->actor, 0x4000, 255, 0, 8);
+ this->timer = 20;
+
+ if ((this->fightState != EN_WIZ_FIGHT_STATE_FIRST_PHASE) && (this->actor.colChkInfo.health <= 0)) {
+ Enemy_StartFinishingBlow(play, &this->actor);
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DEAD);
+ this->timer = 0;
+ this->actor.flags &= ~ACTOR_FLAG_1;
+ } else {
+ Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_DAMAGE);
+ }
+
+ this->scale = 0.015f;
+ this->platformCount = 0;
+ this->targetPlatformLightAlpha = 0;
+ if ((this->drawDmgEffTimer != 0) &&
+ ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FIRE) || (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_LIGHT_ORBS))) {
+ this->timer = 0;
+ }
+
+ this->rotationalVelocity = 0x4E20;
+ if ((this->drawDmgEffTimer != 0) && (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX)) {
+ this->rotationalVelocity = 0;
+ this->timer = 0;
+ }
+
+ this->action = EN_WIZ_ACTION_DAMAGED;
+ this->actionFunc = EnWiz_Damaged;
+}
+
+/**
+ * Spins the Wizrobe around quickly and makes it jump in the air if it was defeated or if
+ * it was damaged in a certain way. Afterwards, the Wizrobe either disappears or dies.
+ */
+void EnWiz_Damaged(EnWiz* this, PlayState* play) {
+ s32 i;
+
+ if ((this->drawDmgEffTimer < 50) && (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX)) {
+ Actor_SpawnIceEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos), 2, 1.0f, 0.7f);
+ this->drawDmgEffTimer = 0;
+ this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE;
+ this->rotationalVelocity = 0x4E20;
+ this->actor.velocity.y = 30.0f;
+ this->actor.gravity = -3.0f;
+ }
+
+ if ((this->drawDmgEffTimer != 0) && (this->drawDmgEffTimer < 30) &&
+ ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FIRE) || (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_LIGHT_ORBS))) {
+ this->actor.velocity.y = 30.0f;
+ this->actor.gravity = -3.0f;
+ this->drawDmgEffTimer = 0;
+ this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE;
+ } else if (!this->isDead && (this->fightState != EN_WIZ_FIGHT_STATE_FIRST_PHASE) &&
+ (this->actor.colChkInfo.health <= 0)) {
+ this->actor.velocity.y = 30.0f;
+ this->actor.gravity = -3.0f;
+ this->isDead = true;
+ }
+
+ this->actor.world.rot.y += this->rotationalVelocity;
+ Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14);
+ for (i = 0; i < this->platformCount; i++) {
+ this->ghostRot[i].y += this->rotationalVelocity;
+ }
+
+ if ((this->timer == 1) ||
+ ((this->actor.velocity.y < 0.0f) &&
+ (this->actor.world.pos.y < (this->platforms[this->curPlatformIndex]->world.pos.y + 11.0f)))) {
+ this->timer = 0;
+ this->actor.velocity.y = 0.0f;
+ this->actor.gravity = 0.0f;
+ this->drawDmgEffTimer = this->timer;
+ this->drawDmgEffType = this->timer;
+
+ if (this->actor.colChkInfo.health <= 0) {
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE;
+ if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ this->actor.colChkInfo.health = 8;
+ } else {
+ this->actor.colChkInfo.health = 6;
+ }
+
+ EnWiz_SetupDisappear(this);
+ } else {
+ EnWiz_SetupDead(this);
+ }
+ } else {
+ EnWiz_SetupDisappear(this);
+ }
+
+ this->actor.flags |= ACTOR_FLAG_8000000;
+ }
+
+ Math_SmoothStepToS(&this->platformLightAlpha, this->targetPlatformLightAlpha, 20, 50, 10);
+ Actor_MoveWithGravity(&this->actor);
+ Actor_UpdateBgCheckInfo(play, &this->actor, 35.0f, 40.0f, 40.0f, 0x1F);
+}
+
+void EnWiz_SetupDead(EnWiz* this) {
+ EnWiz_ChangeAnim(this, EN_WIZ_ANIM_DAMAGE, false);
+ this->rotationalVelocity = 0x2710;
+ this->action = EN_WIZ_ACTION_DEAD;
+ this->timer = 0;
+ this->actionFunc = EnWiz_Dead;
+}
+
+/**
+ * Slows the Wizrobe's rotation to a stop, then makes it burst into flames.
+ * If the Wizrobe has a switch flag, it will set that switch flag when it dies.
+ */
+void EnWiz_Dead(EnWiz* this, PlayState* play) {
+ s32 i;
+
+ this->actor.world.rot.y += this->rotationalVelocity;
+ Math_SmoothStepToS(&this->rotationalVelocity, 0, 0xA, 0xBB8, 0x14);
+ if (this->rotationalVelocity < 0x1E) {
+ Math_SmoothStepToS(&this->alpha, 0, 10, 30, 20);
+ for (i = 0; i < this->platformCount; i++) {
+ Math_SmoothStepToS(&this->ghostAlpha[i], 0, 10, 30, 20);
+ }
+
+ this->action = EN_WIZ_ACTION_BURST_INTO_FLAMES;
+ }
+
+ if (this->alpha < 30) {
+ EnWiz_SelectPlatform(this, play);
+ SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EN_EXTINCT);
+ Actor_MarkForDeath(&this->actor);
+ if (this->switchFlag >= 0) {
+ Flags_SetSwitch(play, this->switchFlag);
+ }
+ }
+}
+
+static Color_RGBA8 sDustPrimColor = { 250, 250, 250, 255 };
+static Color_RGBA8 sDustEnvTimer = { 180, 180, 180, 255 };
+
+void EnWiz_UpdateDamage(EnWiz* this, PlayState* play) {
+ s32 i;
+ s32 attackDealsDamage = false;
+
+ if (this->collider.base.acFlags & AC_HIT) {
+ this->ghostColliders.base.acFlags &= ~AC_HIT;
+ if (this->action < EN_WIZ_ACTION_RUN_IN_CIRCLES) {
+ return;
+ }
+
+ switch (this->actor.colChkInfo.damageEffect) {
+ case EN_WIZ_DMGEFF_NONE:
+ attackDealsDamage = true;
+ break;
+
+ case EN_WIZ_DMGEFF_FIRE:
+ if (this->type == EN_WIZ_TYPE_ICE) {
+ this->drawDmgEffTimer = 40;
+ this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FIRE;
+ }
+
+ attackDealsDamage = true;
+ break;
+
+ case EN_WIZ_DMGEFF_FREEZE:
+ if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ this->drawDmgEffTimer = 80;
+ this->drawDmgEffType = ACTOR_DRAW_DMGEFF_FROZEN_SFX;
+ this->drawDmgEffScale = 0.0f;
+ this->drawDmgEffFrozenSteamScale = 1.5f;
+ }
+
+ Actor_ApplyDamage(&this->actor);
+ EnWiz_SetupDamaged(this, play);
+ break;
+
+ case EN_WIZ_DMGEFF_LIGHT_ORB:
+ if (((this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_SFX) &&
+ (this->drawDmgEffType != ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) ||
+ (this->drawDmgEffTimer == 0)) {
+ Actor_Spawn(&play->actorCtx, play, ACTOR_EN_CLEAR_TAG, this->actor.focus.pos.x,
+ this->actor.focus.pos.y, this->actor.focus.pos.z, 0, 0, 0, CLEAR_TAG_LARGE_LIGHT_RAYS);
+ this->drawDmgEffTimer = 40;
+ this->drawDmgEffType = ACTOR_DRAW_DMGEFF_LIGHT_ORBS;
+ attackDealsDamage = true;
+ }
+ break;
+ }
+
+ this->alpha = 255;
+ if (attackDealsDamage) {
+ Actor_ApplyDamage(&this->actor);
+ EnWiz_SetupDamaged(this, play);
+ return;
+ }
+ }
+
+ if ((this->platformCount != 0) && (this->fightState != EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE)) {
+ for (i = 0; i < this->platformCount; i++) {
+ Vec3f accel;
+ Vec3f velocity;
+ Vec3f pos;
+ f32 scaleStep;
+ s32 j;
+
+ // If the player throws a Deku Nut or hits a ghost's collider (something that is impossible
+ // in the final game, since EnWiz_Init effectively disables them), then the below code will
+ // "destroy" the ghost by turning into a cloud of smoke.
+ if ((iREG(50) != 0) || (this->ghostColliders.elements[i + 1].info.bumperFlags & BUMP_HIT)) {
+ //! @bug: If a single ghost is destroyed, then changing the fight state here will cause
+ //! strange behavior; the ghosts will stand still and pretend to attack the player like
+ //! the real Wizrobe. Since Deku Nuts destroy all ghosts at once, and since the ghost
+ //! colliders are effectively disabled, this doesn't cause any problems in the final
+ //! game, but it becomes an issue if the ghost colliders are enabled.
+ this->fightState = EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_COPY_WIZROBE;
+ this->ghostColliders.base.acFlags &= ~BUMP_HIT;
+ if (this->ghostPos[i].x != .0f || this->ghostPos[i].z != .0f) {
+ for (j = 0; j < 9; j++) {
+ accel.x = 0.0f;
+ accel.y = 1.0f;
+ accel.z = 0.0f;
+ velocity.x = 0.0f;
+ velocity.y = 1.0f;
+ velocity.z = 0.0f;
+ scaleStep = Rand_S16Offset(20, 10);
+ Math_Vec3f_Copy(&pos, &this->ghostPos[i]);
+ pos.x += (f32)Rand_S16Offset(20, 20) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1);
+ pos.y += 70.0f + randPlusMinusPoint5Scaled(30.0f);
+ pos.z += (f32)Rand_S16Offset(20, 20) * ((Rand_ZeroOne() < 0.5f) ? -1 : 1);
+ func_800B0DE0(play, &pos, &velocity, &accel, &sDustPrimColor, &sDustEnvTimer,
+ Rand_S16Offset(350, 100), scaleStep);
+ }
+
+ SoundSource_PlaySfxAtFixedWorldPos(play, &this->ghostPos[i], 50, NA_SE_EN_WIZ_LAUGH);
+ Math_Vec3f_Copy(&this->ghostPos[i], &gZeroVec3f);
+ }
+ }
+ }
+ }
+}
+
+void EnWiz_Update(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnWiz* this = THIS;
+ s32 i;
+ s32 j;
+
+ if (this->action != EN_WIZ_ACTION_APPEAR) {
+ SkelAnime_Update(&this->skelAnime);
+ SkelAnime_Update(&this->ghostSkelAnime);
+ }
+
+ Actor_SetFocus(&this->actor, 60.0f);
+ Actor_SetScale(&this->actor, this->scale);
+ EnWiz_UpdateDamage(this, play);
+ this->actionFunc(this, play);
+
+ this->actor.shape.rot.y = this->actor.world.rot.y;
+
+ DECR(this->timer);
+ DECR(this->introCutsceneTimer);
+ DECR(this->drawDmgEffTimer);
+
+ this->collider.dim.radius = 35;
+ this->collider.dim.height = 130;
+ this->collider.dim.yShift = 0;
+ if (this->action >= EN_WIZ_ACTION_RUN_IN_CIRCLES) {
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->ghostColliders.base);
+ Collider_UpdateCylinder(&this->actor, &this->collider);
+ CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
+ CollisionCheck_SetOC(play, &play->colChkCtx, &this->collider.base);
+ }
+
+ Math_ApproachF(&this->staffFlameScale.x, this->staffTargetFlameScale.x, 0.3f, 0.002f);
+ Math_ApproachF(&this->staffFlameScale.y, this->staffTargetFlameScale.y, 0.3f, 0.002f);
+ Math_ApproachF(&this->staffFlameScale.z, this->staffTargetFlameScale.z, 0.3f, 0.002f);
+
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ this->platformCount = 0;
+ } else if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_GHOSTS_RUN_AROUND) {
+ for (i = 0; i < this->platformCount; i++) {
+ for (j = 0; j < ARRAY_COUNT(this->ghostBaseJointTable); j++) {
+ this->ghostJointTables[i][j] = this->ghostBaseJointTable[j];
+ }
+ }
+ } else {
+ for (i = 0; i < this->platformCount; i++) {
+ for (j = 0; j < ARRAY_COUNT(this->jointTable); j++) {
+ this->ghostJointTables[i][j] = this->jointTable[j];
+ }
+ }
+ }
+}
+
+void EnWiz_PostLimbDrawOpa(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx) {
+ Vec3f staffFlamePos = { 0.0f, 0.0f, 0.0f };
+ EnWiz* this = THIS;
+
+ if (limbIndex == WIZROBE_LIMB_STAFF) {
+ staffFlamePos.x = 7300.0f;
+ staffFlamePos.y = -1500.0f;
+ if (this->action != EN_WIZ_ACTION_DANCE) {
+ staffFlamePos.y = 0.0f;
+ staffFlamePos.x = 5300.0f;
+ }
+
+ Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_MultVec3f(&staffFlamePos, &this->staffFlamePos);
+ }
+
+ Collider_UpdateSpheres(limbIndex, &this->ghostColliders);
+
+ if ((limbIndex == WIZROBE_LIMB_PELVIS) || (limbIndex == WIZROBE_LIMB_TORSO) ||
+ (limbIndex == WIZROBE_LIMB_LEFT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_LEFT_FOREARM) ||
+ (limbIndex == WIZROBE_LIMB_RIGHT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_RIGHT_FOREARM) ||
+ (limbIndex == WIZROBE_LIMB_NECK) || (limbIndex == WIZROBE_LIMB_HEAD) || (limbIndex == WIZROBE_LIMB_JAW) ||
+ (limbIndex == WIZROBE_LIMB_LEFT_SHIN) || (limbIndex == WIZROBE_LIMB_RIGHT_SHIN) ||
+ (limbIndex == WIZROBE_LIMB_LOINCLOTH)) {
+ Matrix_MultZero(&this->bodyPartsPos[this->bodyPartsPosIndex]);
+ this->bodyPartsPosIndex++;
+ if (this->bodyPartsPosIndex >= ARRAY_COUNT(this->bodyPartsPos)) {
+ this->bodyPartsPosIndex = 0;
+ }
+ }
+}
+
+void EnWiz_PostLimbDrawXlu(PlayState* play, s32 limbIndex, Gfx** dList, Vec3s* rot, Actor* thisx, Gfx** gfx) {
+ Vec3f staffFlamePos = { 0.0f, 0.0f, 0.0f };
+ s32 pad;
+ EnWiz* this = THIS;
+
+ if (this->action != EN_WIZ_ACTION_BURST_INTO_FLAMES) {
+ if (limbIndex == WIZROBE_LIMB_STAFF) {
+ staffFlamePos.x = 7300.0f;
+ staffFlamePos.y = -1500.0f;
+ if (this->action != EN_WIZ_ACTION_DANCE) {
+ staffFlamePos.y = 0.0f;
+ staffFlamePos.x = 5300.0f;
+ }
+
+ Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_MultVec3f(&staffFlamePos, &this->staffFlamePos);
+ }
+ } else {
+ if (this->timer == 0) {
+ Vec3f flamePos;
+
+ Matrix_Translate(0.0f, 0.0f, 0.0f, MTXMODE_APPLY);
+ Matrix_MultVec3f(&staffFlamePos, &flamePos);
+ flamePos.x += randPlusMinusPoint5Scaled(4.0f);
+ flamePos.y += randPlusMinusPoint5Scaled(7.0f);
+ flamePos.z += randPlusMinusPoint5Scaled(5.0f);
+ func_800B3030(play, &flamePos, &gZeroVec3f, &gZeroVec3f, ((Rand_ZeroFloat(1.0f) * 50.0f) + 70.0f), 10, 1);
+ SoundSource_PlaySfxAtFixedWorldPos(play, &flamePos, 10, NA_SE_EN_EXTINCT);
+ }
+
+ if ((limbIndex >= WIZROBE_LIMB_RIGHT_FOOT) && (this->timer == 0)) {
+ this->timer = 4;
+ }
+ }
+
+ if ((limbIndex == WIZROBE_LIMB_PELVIS) || (limbIndex == WIZROBE_LIMB_TORSO) ||
+ (limbIndex == WIZROBE_LIMB_LEFT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_LEFT_FOREARM) ||
+ (limbIndex == WIZROBE_LIMB_RIGHT_UPPER_ARM) || (limbIndex == WIZROBE_LIMB_RIGHT_FOREARM) ||
+ (limbIndex == WIZROBE_LIMB_NECK) || (limbIndex == WIZROBE_LIMB_HEAD) || (limbIndex == WIZROBE_LIMB_JAW) ||
+ (limbIndex == WIZROBE_LIMB_LEFT_SHIN) || (limbIndex == WIZROBE_LIMB_RIGHT_SHIN) ||
+ (limbIndex == WIZROBE_LIMB_LOINCLOTH)) {
+ Matrix_MultZero(&this->bodyPartsPos[this->bodyPartsPosIndex]);
+ this->bodyPartsPosIndex++;
+ if (this->bodyPartsPosIndex >= ARRAY_COUNT(this->bodyPartsPos)) {
+ this->bodyPartsPosIndex = 0;
+ }
+ }
+}
+
+void EnWiz_Draw(Actor* thisx, PlayState* play) {
+ s32 pad;
+ EnWiz* this = THIS;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ func_8012C28C(play->state.gfxCtx);
+ func_8012C2DC(play->state.gfxCtx);
+
+ if ((this->action == EN_WIZ_ACTION_BURST_INTO_FLAMES) || (this->alpha != 255)) {
+ Scene_SetRenderModeXlu(play, 1, 2);
+ gDPPipeSync(POLY_XLU_DISP++);
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->alpha);
+ POLY_XLU_DISP =
+ SkelAnime_DrawFlex(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
+ NULL, EnWiz_PostLimbDrawXlu, &this->actor, POLY_XLU_DISP);
+ } else {
+ Scene_SetRenderModeXlu(play, 0, 1);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, this->alpha);
+ SkelAnime_DrawFlexOpa(play, this->skelAnime.skeleton, this->skelAnime.jointTable, this->skelAnime.dListCount,
+ NULL, EnWiz_PostLimbDrawOpa, &this->actor);
+ }
+
+ if (this->drawDmgEffTimer != 0) {
+ f32 drawDmgEffAlpha = this->drawDmgEffTimer * 0.05f;
+
+ if ((this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_SFX) ||
+ (this->drawDmgEffType == ACTOR_DRAW_DMGEFF_FROZEN_NO_SFX)) {
+ this->drawDmgEffScale += 0.3f;
+ if (this->drawDmgEffScale > 0.5f) {
+ this->drawDmgEffScale = 0.5f;
+ }
+
+ Math_ApproachF(&this->drawDmgEffFrozenSteamScale, this->drawDmgEffScale, 0.1f, 0.04f);
+ } else {
+ this->drawDmgEffScale = 0.8f;
+ this->drawDmgEffFrozenSteamScale = 0.8f;
+ }
+
+ Actor_DrawDamageEffects(play, &this->actor, this->bodyPartsPos, ARRAY_COUNT(this->bodyPartsPos),
+ this->drawDmgEffScale, this->drawDmgEffFrozenSteamScale, drawDmgEffAlpha,
+ this->drawDmgEffType);
+ }
+
+ if (this->platformCount > 0) {
+ s32 i;
+ s16 platformCount;
+
+ Matrix_Push();
+
+ platformCount = this->platformCount;
+ if (this->fightState == EN_WIZ_FIGHT_STATE_SECOND_PHASE_CUTSCENE) {
+ platformCount = 10;
+ }
+
+ for (i = 0; i < platformCount; i++) {
+ func_8012C28C(play->state.gfxCtx);
+ func_8012C2DC(play->state.gfxCtx);
+
+ if ((this->ghostPos[i].x != 0.0f) && (this->ghostPos[i].z != 0.0f)) {
+ Matrix_Translate(this->ghostPos[i].x, this->ghostPos[i].y + 10.0f, this->ghostPos[i].z, MTXMODE_NEW);
+ Matrix_Scale(this->scale, this->scale, this->scale, MTXMODE_APPLY);
+ Matrix_RotateYS(this->ghostRot[i].y, MTXMODE_APPLY);
+ Matrix_RotateXS(this->ghostRot[i].x, MTXMODE_APPLY);
+ Matrix_RotateZS(this->ghostRot[i].z, MTXMODE_APPLY);
+ Scene_SetRenderModeXlu(play, 1, 2);
+ gDPPipeSync(POLY_XLU_DISP++);
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, this->ghostAlpha[i]);
+ POLY_XLU_DISP =
+ SkelAnime_DrawFlex(play, this->ghostSkelAnime.skeleton, this->ghostJointTables[i],
+ this->ghostSkelAnime.dListCount, NULL, NULL, &this->actor, POLY_XLU_DISP);
+ this->ghostColliders.elements[i + 1].dim.worldSphere.center.x = this->ghostPos[i].x;
+ this->ghostColliders.elements[i + 1].dim.worldSphere.center.y = this->ghostPos[i].y + 50.0f;
+ this->ghostColliders.elements[i + 1].dim.worldSphere.center.z = this->ghostPos[i].z;
+ this->ghostColliders.elements[i + 1].dim.worldSphere.radius =
+ this->ghostColliders.elements[0].dim.modelSphere.radius;
+ this->ghostColliders.elements[i + 1].dim.scale = this->ghostColliders.elements[0].dim.scale;
+ }
+ }
+
+ Matrix_Pop();
+ }
+
+ func_8012C2DC(play->state.gfxCtx);
+ func_8012C28C(play->state.gfxCtx);
+
+ // Draw the light emanating from the Wizrobe's platform
+ if (this->fightState == EN_WIZ_FIGHT_STATE_FIRST_PHASE) {
+ Matrix_Push();
+
+ AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizrobePlatformLightTexAnim));
+ Matrix_Translate(this->platformLightPos.x, this->platformLightPos.y, this->platformLightPos.z, MTXMODE_NEW);
+ Matrix_Scale(0.01f, 0.01f, 0.01f, MTXMODE_APPLY);
+ gDPPipeSync(POLY_XLU_DISP++);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 255, 255, 255, this->platformLightAlpha);
+
+ if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ gDPSetEnvColor(POLY_XLU_DISP++, 255, 0, 100, 255);
+ } else {
+ gDPSetEnvColor(POLY_XLU_DISP++, 50, 0, 255, 255);
+ }
+
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobePlatformLightDL);
+
+ Matrix_Pop();
+ }
+
+ // Draw the flame at the tip of the Wizrobe's staff
+ Matrix_Translate(this->staffFlamePos.x, this->staffFlamePos.y, this->staffFlamePos.z, MTXMODE_NEW);
+ Matrix_Scale(this->staffFlameScale.x, this->staffFlameScale.y, this->staffFlameScale.z, MTXMODE_APPLY);
+ gSPSegment(POLY_XLU_DISP++, 0x08,
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 64, 1, 0,
+ ((this->staffFlameScroll * 10) - (play->state.frames * 20)) % 512, 32, 128));
+ gDPPipeSync(POLY_XLU_DISP++);
+
+ if ((this->type == EN_WIZ_TYPE_FIRE) || (this->type == EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 170, 255);
+ gDPSetEnvColor(POLY_XLU_DISP++, 255, 50, 0, 255);
+ } else {
+ gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 170, 255, 255, 255);
+ gDPSetEnvColor(POLY_XLU_DISP++, 0, 50, 255, 255);
+ }
+
+ Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gEffFire1DL);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h
index a1ae32032..3d18abab2 100644
--- a/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h
+++ b/src/overlays/actors/ovl_En_Wiz/z_en_wiz.h
@@ -2,6 +2,16 @@
#define Z_EN_WIZ_H
#include "global.h"
+#include "objects/object_wiz/object_wiz.h"
+
+#define EN_WIZ_GET_SWITCHFLAG(thisx) ((thisx)->params & 0x7F)
+#define EN_WIZ_GET_TYPE(thisx) (((thisx)->params >> 8) & 0xFF)
+
+typedef enum {
+ /* 0 */ EN_WIZ_TYPE_FIRE,
+ /* 1 */ EN_WIZ_TYPE_ICE,
+ /* 2 */ EN_WIZ_TYPE_FIRE_NO_BGM, // does not request the mini-boss BGM
+} EnWizType;
struct EnWiz;
@@ -9,15 +19,62 @@ typedef void (*EnWizActionFunc)(struct EnWiz*, PlayState*);
typedef struct EnWiz {
/* 0x000 */ Actor actor;
- /* 0x144 */ char unk_144[0x268];
+ /* 0x144 */ SkelAnime skelAnime;
+ /* 0x188 */ Vec3s jointTable[WIZROBE_LIMB_MAX];
+ /* 0x200 */ Vec3s morphTable[WIZROBE_LIMB_MAX];
+ /* 0x278 */ SkelAnime ghostSkelAnime;
+ /* 0x2BC */ Vec3s ghostBaseJointTable[WIZROBE_LIMB_MAX];
+ /* 0x334 */ Vec3s ghostMorphTable[WIZROBE_LIMB_MAX];
/* 0x3AC */ EnWizActionFunc actionFunc;
- /* 0x3B0 */ char unk_3B0[0xA];
- /* 0x3BA */ s16 unk_3BA;
- /* 0x3BC */ char unk_3BC[0x8C];
- /* 0x448 */ s32 unk_448;
- /* 0x44C */ char unk_44C[0x2FE];
- /* 0x74A */ s16 unk_74A;
- /* 0x74C */ char unk_74C[0x634];
+ /* 0x3B0 */ s16 action;
+ /* 0x3B2 */ s16 timer;
+ /* 0x3B4 */ s16 introCutsceneTimer;
+ /* 0x3B6 */ s16 fightState;
+ /* 0x3B8 */ s16 staffFlameScroll;
+ /* 0x3BA */ s16 hasActiveProjectile;
+ /* 0x3BC */ s16 hasRunToEveryPlatform; // used for the second phase cutscene to make sure the Wizrobe visits every platform
+ /* 0x3BE */ s16 unk_3BE; // unused, inferred from surrounding members
+ /* 0x3C0 */ s16 rotationalVelocity;
+ /* 0x3C2 */ s16 alpha;
+ /* 0x3C4 */ s16 platformLightAlpha;
+ /* 0x3C6 */ s16 targetPlatformLightAlpha;
+ /* 0x3C8 */ s16 introCutsceneCameraAngle;
+ /* 0x3CA */ u8 shouldStartTimer;
+ /* 0x3CB */ u8 introCutsceneState;
+ /* 0x3CC */ s32 musicStartTimer;
+ /* 0x3D0 */ f32 endFrame;
+ /* 0x3D4 */ f32 scale;
+ /* 0x3D8 */ Vec3f staffFlamePos;
+ /* 0x3E4 */ Vec3f staffFlameScale;
+ /* 0x3F0 */ Vec3f staffTargetFlameScale;
+ /* 0x3FC */ Vec3f unk_3FC; // unused, inferred from surrounding members
+ /* 0x408 */ Vec3f unk_408; // unused, inferred from surrounding members
+ /* 0x414 */ Vec3f platformLightPos;
+ /* 0x420 */ Actor* platforms[10];
+ /* 0x448 */ Actor* freezard;
+ /* 0x44C */ s16 animLoopCounter;
+ /* 0x450 */ f32 unk_450; // set to 1.0f, but never used
+ /* 0x454 */ ColliderJntSph ghostColliders;
+ /* 0x474 */ ColliderJntSphElement ghostColliderElements[10];
+ /* 0x6F4 */ ColliderCylinder collider;
+ /* 0x740 */ s32 platformCount;
+ /* 0x744 */ s32 nextPlatformIndex; // used for the second phase cutscene to dictate where the Wizrobe should run to next
+ /* 0x748 */ s16 curPlatformIndex;
+ /* 0x74A */ s16 type;
+ /* 0x74C */ s16 switchFlag;
+ /* 0x74E */ s16 subCamId;
+ /* 0x750 */ s16 isDead;
+ /* 0x752 */ s16 drawDmgEffTimer;
+ /* 0x754 */ s16 drawDmgEffType;
+ /* 0x758 */ f32 drawDmgEffScale;
+ /* 0x75C */ f32 drawDmgEffFrozenSteamScale;
+ /* 0x760 */ Vec3f bodyPartsPos[12];
+ /* 0x7F0 */ s16 bodyPartsPosIndex;
+ /* 0x7F2 */ s16 ghostAlpha[10];
+ /* 0x806 */ s16 ghostNextPlatformIndex[10];
+ /* 0x81C */ Vec3f ghostPos[10];
+ /* 0x894 */ Vec3s ghostRot[10];
+ /* 0x8D0 */ Vec3s ghostJointTables[10][WIZROBE_LIMB_MAX];
} EnWiz; // size = 0xD80
extern const ActorInit En_Wiz_InitVars;
diff --git a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c
index d49e71c08..ce13687a7 100644
--- a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c
+++ b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.c
@@ -1,7 +1,7 @@
/*
* File: z_en_wiz_brock.c
* Overlay: ovl_En_Wiz_Brock
- * Description: Wizzrobe Warp Platform
+ * Description: Wizrobe Warp Platform
*/
#include "z_en_wiz_brock.h"
@@ -11,13 +11,6 @@
#define THIS ((EnWizBrock*)thisx)
-typedef enum {
- PLATFORM_TYPE_INACTIVE,
- PLATFORM_TYPE_FIRE,
- PLATFORM_TYPE_ICE,
- PLATFORM_TYPE_MAX,
-} PlatformType;
-
void EnWizBrock_Init(Actor* thisx, PlayState* play);
void EnWizBrock_Destroy(Actor* thisx, PlayState* play);
void EnWizBrock_Update(Actor* thisx, PlayState* play);
@@ -26,7 +19,7 @@ void EnWizBrock_Draw(Actor* thisx, PlayState* play);
void EnWizBrock_SetupUpdateStatus(EnWizBrock* this, PlayState* play);
void EnWizBrock_UpdateStatus(EnWizBrock* this, PlayState* play);
-s16 platformCount = 0;
+s16 sPlatformIndex = 0;
const ActorInit En_Wiz_Brock_InitVars = {
ACTOR_EN_WIZ_BROCK,
@@ -45,13 +38,13 @@ void EnWizBrock_Init(Actor* thisx, PlayState* play) {
CollisionHeader* colHeader = NULL;
DynaPolyActor_Init(&this->dyna, 0);
- CollisionHeader_GetVirtual(&object_wiz_Colheader_001690, &colHeader);
+ CollisionHeader_GetVirtual(&gWizrobePlatformCol, &colHeader);
this->dyna.bgId = DynaPoly_SetBgActor(play, &play->colCtx.dyna, &this->dyna.actor, colHeader);
this->dyna.actor.colChkInfo.mass = MASS_IMMOVABLE;
this->dyna.actor.colChkInfo.health = 3;
this->unk_1A6 = 0;
Actor_SetScale(&this->dyna.actor, 0.01f);
- this->platformNum = platformCount++;
+ this->platformIndex = sPlatformIndex++;
this->actionFunc = EnWizBrock_SetupUpdateStatus;
this->dyna.actor.scale.x = this->dyna.actor.scale.y = this->dyna.actor.scale.z = 0.01f;
this->alpha = 255.0f;
@@ -68,12 +61,12 @@ void EnWizBrock_SetupUpdateStatus(EnWizBrock* this, PlayState* play) {
}
/**
- * @brief Checks the platform status, when the Wizzrobe is defeated, which triggers timer to
+ * @brief Checks the platform status, when the Wizrobe is defeated, which triggers timer to
* count up to 30 at which point the platforms are despawned.
*/
void EnWizBrock_UpdateStatus(EnWizBrock* this, PlayState* play) {
- if (this->platformType == PLATFORM_TYPE_INACTIVE) {
- if (this->dyna.actor.colChkInfo.health != PLATFORM_TYPE_MAX) {
+ if (this->platformType == EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE) {
+ if (this->dyna.actor.colChkInfo.health != EN_WIZ_BROCK_PLATFORM_TYPE_MAX) {
this->platformType = this->dyna.actor.colChkInfo.health;
}
}
@@ -115,30 +108,30 @@ void EnWizBrock_Draw(Actor* thisx, PlayState* play) {
Scene_SetRenderModeXlu(play, 0, 1);
gDPPipeSync(POLY_OPA_DISP++);
gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
- Gfx_DrawDListOpa(play, gWizzrobePlatform);
+ Gfx_DrawDListOpa(play, gWizrobePlatformDL);
} else {
Scene_SetRenderModeXlu(play, 1, 2);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, (s16)this->alpha);
- Gfx_DrawDListXlu(play, gWizzrobePlatform);
+ Gfx_DrawDListXlu(play, gWizrobePlatformDL);
}
CLOSE_DISPS(play->state.gfxCtx);
- if (this->platformType != PLATFORM_TYPE_INACTIVE) {
+ if (this->platformType != EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE) {
OPEN_DISPS(play->state.gfxCtx);
- AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizzrobePlatformTexAnim));
+ AnimatedMat_Draw(play, Lib_SegmentedToVirtual(&gWizrobePlatformCenterTexAnim));
gDPPipeSync(POLY_XLU_DISP++);
gDPSetPrimColor(POLY_XLU_DISP++, 0x80, 0x80, 255, 255, 255, 255);
- if (this->platformType == PLATFORM_TYPE_FIRE) {
+ if (this->platformType == EN_WIZ_BROCK_PLATFORM_TYPE_FIRE) {
gDPSetEnvColor(POLY_XLU_DISP++, 255, 00, 100, (s16)this->alpha);
} else {
gDPSetEnvColor(POLY_XLU_DISP++, 50, 00, 255, (s16)this->alpha);
}
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, &gWizzrobePlatformCenter);
+ gSPDisplayList(POLY_XLU_DISP++, &gWizrobePlatformCenterDL);
CLOSE_DISPS(play->state.gfxCtx);
}
diff --git a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h
index 0f0150697..3b23d08b0 100644
--- a/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h
+++ b/src/overlays/actors/ovl_En_Wiz_Brock/z_en_wiz_brock.h
@@ -3,6 +3,13 @@
#include "global.h"
+typedef enum {
+ /* 0 */ EN_WIZ_BROCK_PLATFORM_TYPE_INACTIVE,
+ /* 1 */ EN_WIZ_BROCK_PLATFORM_TYPE_FIRE,
+ /* 2 */ EN_WIZ_BROCK_PLATFORM_TYPE_ICE,
+ /* 3 */ EN_WIZ_BROCK_PLATFORM_TYPE_MAX,
+} EnWizBrockPlatformType;
+
struct EnWizBrock;
typedef void (*EnWizBrockActionFunc)(struct EnWizBrock*, PlayState*);
@@ -12,8 +19,8 @@ typedef struct EnWizBrock {
/* 0x15C */ UNK_TYPE1 unk_15C[0x44];
/* 0x1A0 */ EnWizBrockActionFunc actionFunc;
/* 0x1A4 */ s16 timer; // Counter for despawing blocks (Max of 37)
- /* 0x1A6 */ s16 unk_1A6; // TODO: set but not used maybe used in wizzrobe?
- /* 0x1A8 */ s16 platformNum; // Numeric identifier for platform
+ /* 0x1A6 */ s16 unk_1A6; // set to 0, but never used
+ /* 0x1A8 */ s16 platformIndex; // Numeric identifier for platform
/* 0x1AA */ s16 platformType; // Determines element type for platform (ice/fire)
/* 0x1AC */ f32 alpha;
} EnWizBrock; // size = 0x1B0
diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c
index 666a5156b..eea112f89 100644
--- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c
+++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.c
@@ -1,7 +1,7 @@
/*
* File: z_en_wiz_fire.c
* Overlay: ovl_En_Wiz_Fire
- * Description: Wizzrobe Fire/Ice Attack
+ * Description: Wizrobe Fire/Ice Attack
*/
#include "z_en_wiz_fire.h"
@@ -17,18 +17,25 @@ void EnWizFire_Destroy(Actor* thisx, PlayState* play);
void EnWizFire_Update(Actor* thisx, PlayState* play);
void EnWizFire_Draw(Actor* thisx, PlayState* play);
-void func_80A4984C(EnWizFire* this, PlayState* play);
-void func_80A49A44(EnWizFire* this, PlayState* play);
-void func_80A49F38(EnWizFire* this, PlayState* play);
-void func_80A49FD8(EnWizFire* this, PlayState* play);
-void func_80A4A11C(EnWizFire* this, PlayState* play);
-void func_80A4A608(EnWizFire* this, PlayState* play);
-void func_80A4BAB4(Actor* thisx, PlayState* play);
-void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2);
-void func_80A4BDDC(EnWizFire* this, PlayState* play);
-void func_80A4BF78(EnWizFire* this, PlayState* play);
+void EnWiz_SetupMoveMagicProjectile(EnWizFire* this, PlayState* play);
+void EnWiz_MoveMagicProjectile(EnWizFire* this, PlayState* play);
+void EnWiz_SetupSmallFlame(EnWizFire* this, PlayState* play);
+void EnWiz_SmallFlame(EnWizFire* this, PlayState* play);
+void EnWiz_Pool(EnWizFire* this, PlayState* play);
+void EnWiz_KillMagicProjectile(EnWizFire* this, PlayState* play);
+void EnWizFire_DrawSmallFlame(Actor* thisx, PlayState* play);
+void EnWizFire_InitializeEffect(EnWizFire* this, Vec3f* pos, Vec3f* accel);
+void EnWizFire_UpdateEffects(EnWizFire* this, PlayState* play);
+void EnWizFire_DrawEffects(EnWizFire* this, PlayState* play);
-static s32 D_80A4C1C0 = 0;
+typedef enum {
+ /* 0 */ EN_WIZ_FIRE_ACTION_MOVE_MAGIC_PROJECTILE,
+ /* 1 */ EN_WIZ_FIRE_ACTION_SMALL_FLAME,
+ /* 2 */ EN_WIZ_FIRE_ACTION_POOL,
+ /* 3 */ EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE,
+} EnWizFireAction;
+
+static s32 sPoolHitByIceArrow = false;
const ActorInit En_Wiz_Fire_InitVars = {
ACTOR_EN_WIZ_FIRE,
@@ -66,48 +73,52 @@ void EnWizFire_Init(Actor* thisx, PlayState* play) {
EnWizFire* this = THIS;
Collider_InitAndSetCylinder(play, &this->collider, &this->actor, &sCylinderInit);
- this->unk_162 = this->actor.params;
+ this->type = EN_WIZ_FIRE_GET_TYPE(&this->actor);
this->actor.targetMode = 3;
- this->unk_172 = 10;
- this->unk_1FC = 255.0f;
+ this->wallCheckTimer = 10;
+ this->alpha = 255.0f;
this->actor.flags &= ~ACTOR_FLAG_1;
if (!Player_HasMirrorShieldEquipped(play)) {
this->collider.info.toucher.dmgFlags = 0x20000000;
}
- switch (this->unk_162) {
- case 4:
- this->unk_166 = 1;
+ switch (this->type) {
+ case EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE:
+ this->isIceType = true;
this->collider.info.toucher.damage = 8;
this->collider.info.toucher.effect = 2;
this->collider.info.bumper.dmgFlags = (0x1000000 | 0x800 | 0x200 | 0x2);
- this->unk_162 = 0;
-
- case 0:
- if (this->unk_162 == 4) {
- this->unk_162 = 0;
+ this->type = EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE;
+ // fallthrough
+ case EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE:
+ if (this->type == EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE) {
+ this->type = EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE;
this->collider.info.toucher.damage = 8;
}
-
- case 1:
- case 3:
- this->actionFunc = func_80A4984C;
+ // fallthrough
+ case EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE:
+ case EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE:
+ this->actionFunc = EnWiz_SetupMoveMagicProjectile;
break;
- case 2:
- this->actor.draw = func_80A4BAB4;
- this->unk_170 = Rand_S16Offset(0, 10000);
- this->unk_160 = 1;
+ case EN_WIZ_FIRE_TYPE_SMALL_FLAME:
+ this->actor.draw = EnWizFire_DrawSmallFlame;
+ this->smallFlameScroll = Rand_S16Offset(0, 10000);
+ this->action = EN_WIZ_FIRE_ACTION_SMALL_FLAME;
this->collider.info.toucher.damage = 2;
- this->actionFunc = func_80A49F38;
+ this->actionFunc = EnWiz_SetupSmallFlame;
+ break;
+
+ default:
+ break;
}
}
void EnWizFire_Destroy(Actor* thisx, PlayState* play) {
EnWizFire* this = THIS;
- if (this->unk_162 == 0) {
+ if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
play->envCtx.lightSettings.fogColor[2] = 0;
play->envCtx.lightSettings.fogColor[1] = play->envCtx.lightSettings.fogColor[2];
play->envCtx.lightSettings.fogColor[0] = play->envCtx.lightSettings.fogColor[2];
@@ -122,146 +133,159 @@ void EnWizFire_Destroy(Actor* thisx, PlayState* play) {
play->envCtx.lightSettings.ambientColor[0] = play->envCtx.lightSettings.fogColor[2];
play->envCtx.lightSettings.fogNear = play->envCtx.lightSettings.fogColor[2];
}
+
Collider_DestroyCylinder(play, &this->collider);
}
-void func_80A4984C(EnWizFire* this, PlayState* play) {
- Vec3f sp44 = { 0.0f, 0.0f, 0.0f };
+void EnWiz_SetupMoveMagicProjectile(EnWizFire* this, PlayState* play) {
+ Vec3f velocity = { 0.0f, 0.0f, 0.0f };
s32 i;
- for (i = 0; i < ARRAY_COUNT(this->unk_178); i++) {
- this->unk_178[i] = this->actor.world.pos;
+ for (i = 0; i < ARRAY_COUNT(this->magicProjectilePos); i++) {
+ this->magicProjectilePos[i] = this->actor.world.pos;
}
- this->unk_16E = 0;
+ this->lowestUsedIndex = 0;
+
Matrix_Push();
Matrix_RotateYS(this->actor.world.rot.y, MTXMODE_NEW);
Matrix_RotateXS(this->actor.world.rot.x, MTXMODE_APPLY);
- if (this->unk_162 != 0) {
- sp44.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f;
+ if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
+ velocity.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f;
} else {
- sp44.z = 12.0f;
+ velocity.z = 12.0f;
}
- Matrix_MultVec3f(&sp44, &this->actor.velocity);
+ Matrix_MultVec3f(&velocity, &this->actor.velocity);
Matrix_Pop();
+
this->actor.world.rot.x = this->actor.world.rot.y = this->actor.world.rot.z = 0;
- this->unk_168 = 50;
- if (this->unk_162 != 0) {
+ this->timer = 50;
+
+ if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
this->actor.velocity.y = 10.0f;
this->actor.gravity = -1.0f;
- this->unk_150 = 0.01f;
+ this->targetScale = 0.01f;
} else {
- this->unk_150 = 0.02f;
- this->unk_168 = 100;
+ this->targetScale = 0.02f;
+ this->timer = 100;
}
- this->unk_160 = 0;
- this->actionFunc = func_80A49A44;
+
+ this->action = EN_WIZ_FIRE_ACTION_MOVE_MAGIC_PROJECTILE;
+ this->actionFunc = EnWiz_MoveMagicProjectile;
}
-void func_80A49A44(EnWizFire* this, PlayState* play) {
- Vec3f sp54 = { 0.0f, 0.0f, 0.0f };
+/**
+ * Moves all types of magic projectiles around, including arcing ones created by the
+ * Fire Wizrobe's attack or ones reflected by the Mirror Shield.
+ */
+void EnWiz_MoveMagicProjectile(EnWizFire* this, PlayState* play) {
+ Vec3f velocity = { 0.0f, 0.0f, 0.0f };
this->actor.world.rot.z += 5000;
- if (this->unk_162 != 0) {
- this->unk_150 = 0.01f;
+ if (this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
+ this->targetScale = 0.01f;
} else {
- this->unk_150 = 0.02f;
+ this->targetScale = 0.02f;
}
- if ((this->unk_168 == 0) && (this->unk_14C < 0.001f)) {
+ if ((this->timer == 0) && (this->scale < 0.001f)) {
Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f);
- this->unk_160 = 3;
- this->unk_16A = 0;
- this->actionFunc = func_80A4A608;
+ this->action = EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE;
+ this->increaseLowestUsedIndexTimer = 0;
+ this->actionFunc = EnWiz_KillMagicProjectile;
return;
}
- if (this->unk_168 == 0) {
- this->unk_150 = 0.0f;
+ if (this->timer == 0) {
+ this->targetScale = 0.0f;
}
- Math_ApproachF(&this->unk_14C, this->unk_150, 0.2f, 0.01f);
+ Math_ApproachF(&this->scale, this->targetScale, 0.2f, 0.01f);
- if (this->unk_172 == 0) {
- if ((this->actor.bgCheckFlags & 8) && (this->unk_162 == 0) && (this->unk_168 != 0) &&
+ if (this->wallCheckTimer == 0) {
+ if ((this->actor.bgCheckFlags & 8) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->timer != 0) &&
(this->actor.bgCheckFlags & 8)) {
- D_80A4C1C0 = 0;
- this->unk_168 = 0;
- this->unk_150 = 0.0f;
+ sPoolHitByIceArrow = false;
+ this->timer = 0;
+ this->targetScale = 0.0f;
}
}
- if ((this->actor.bgCheckFlags & 1) && (this->unk_16A == 0)) {
+ if ((this->actor.bgCheckFlags & 1) && (this->poolTimer == 0)) {
s32 i;
- s16 phi_s0;
- s32 temp;
+ s16 arcingProjectileRotY;
+ s32 pad;
- if (this->unk_162 == 1) {
- this->unk_16A = 10;
+ if (this->type == EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE) {
+ this->increaseLowestUsedIndexTimer = 10;
Matrix_Push();
Matrix_RotateYS((s16)randPlusMinusPoint5Scaled(0x100) + this->actor.world.rot.y, MTXMODE_NEW);
- sp54.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f;
- Matrix_MultVec3f(&sp54, &this->actor.velocity);
+ velocity.z = randPlusMinusPoint5Scaled(2.0f) + 8.0f;
+ Matrix_MultVec3f(&velocity, &this->actor.velocity);
Matrix_Pop();
this->actor.velocity.y = 6.0f;
this->actor.gravity = -0.7f;
- if (this->unk_164 == 0) {
+ if (!this->hasSpawnedSmallFlame) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x,
- this->actor.world.pos.y - 10.0f, this->actor.world.pos.z, 0, 0, 0, 2);
- this->unk_164 = 1;
+ this->actor.world.pos.y - 10.0f, this->actor.world.pos.z, 0, 0, 0,
+ EN_WIZ_FIRE_TYPE_SMALL_FLAME);
+ this->hasSpawnedSmallFlame = true;
}
- this->unk_168 = 0;
- this->unk_14C = 0.0f;
+ this->timer = 0;
+ this->scale = 0.0f;
Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f);
- this->unk_160 = 3;
- this->unk_16A = 0;
- this->actionFunc = func_80A4A608;
+ this->action = EN_WIZ_FIRE_ACTION_KILL_MAGIC_PROJECTILE;
+ this->increaseLowestUsedIndexTimer = 0;
+ this->actionFunc = EnWiz_KillMagicProjectile;
return;
}
- if ((this->unk_162 == 0) && (this->unk_168 != 0)) {
+ if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->timer != 0)) {
if (this->actor.floorBgId == BGCHECK_SCENE) {
- this->unk_16A = 100;
- if (this->unk_166 == 0) {
- phi_s0 = 0;
+ this->poolTimer = 100;
+ if (!this->isIceType) {
+ arcingProjectileRotY = 0;
for (i = 0; i < 5; i++) {
Actor_Spawn(&play->actorCtx, play, ACTOR_EN_WIZ_FIRE, this->actor.world.pos.x,
- this->actor.world.pos.y, this->actor.world.pos.z, 0, phi_s0, 0, 1);
- phi_s0 += BINANG_ADD((s32)randPlusMinusPoint5Scaled(0x1000), 0x3333);
+ this->actor.world.pos.y, this->actor.world.pos.z, 0, arcingProjectileRotY, 0,
+ EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE);
+ arcingProjectileRotY += BINANG_ADD((s32)randPlusMinusPoint5Scaled(0x1000), 0x3333);
}
Actor_PlaySfxAtPos(&this->actor, NA_SE_IT_BOMB_EXPLOSION);
- this->unk_16A = Rand_S16Offset(70, 30);
- if (this->unk_16A != 0) {
+ this->poolTimer = Rand_S16Offset(70, 30);
+ if (this->poolTimer != 0) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_EXP - SFX_FLAG);
}
- } else if (this->unk_16A != 0) {
+ } else if (this->poolTimer != 0) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
}
+
Math_Vec3f_Copy(&this->actor.velocity, &gZeroVec3f);
- this->unk_168 = 0;
- this->unk_160 = 2;
- this->unk_14C = 0.0f;
- this->actionFunc = func_80A4A11C;
+ this->timer = 0;
+ this->action = EN_WIZ_FIRE_ACTION_POOL;
+ this->scale = 0.0f;
+ this->actionFunc = EnWiz_Pool;
}
+
return;
}
}
- if ((this->unk_162 != 3) && (this->unk_168 != 0)) {
+ if ((this->type != EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE) && (this->timer != 0)) {
if (this->collider.base.acFlags & AC_HIT) {
this->collider.base.acFlags &= ~AC_HIT;
if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) {
- this->unk_168 = 0;
- this->unk_148 = 1;
+ this->timer = 0;
+ this->hitByIceArrow = true;
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT);
}
}
@@ -272,104 +296,111 @@ void func_80A49A44(EnWizFire* this, PlayState* play) {
this->collider.base.atFlags |= AT_TYPE_PLAYER;
this->collider.info.toucher.dmgFlags = 0x20;
this->collider.info.toucher.damage = 2;
- this->unk_168 = 100;
- this->unk_162 = 3;
+ this->timer = 100;
+ this->type = EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE;
this->actor.velocity.x *= -1.0f;
this->actor.velocity.y *= -0.5f;
this->actor.velocity.z *= -1.0f;
if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) &&
(this->actor.parent->update != NULL)) {
- ((EnWiz*)this->actor.parent)->unk_3BA = 0;
+ ((EnWiz*)this->actor.parent)->hasActiveProjectile = false;
}
}
}
}
-void func_80A49F38(EnWizFire* this, PlayState* play) {
- this->unk_150 = 0.02f;
- this->unk_168 = Rand_S16Offset(50, 50);
- this->unk_154 = randPlusMinusPoint5Scaled(1.0f) * 0.007f;
- this->unk_158 = randPlusMinusPoint5Scaled(1.0f) * 0.005f;
- this->unk_15C = randPlusMinusPoint5Scaled(1.0f) * 0.007f;
- this->actionFunc = func_80A49FD8;
+void EnWiz_SetupSmallFlame(EnWizFire* this, PlayState* play) {
+ this->targetScale = 0.02f;
+ this->timer = Rand_S16Offset(50, 50);
+ this->scaleMod.x = randPlusMinusPoint5Scaled(1.0f) * 0.007f;
+ this->scaleMod.y = randPlusMinusPoint5Scaled(1.0f) * 0.005f;
+ this->scaleMod.z = randPlusMinusPoint5Scaled(1.0f) * 0.007f;
+ this->actionFunc = EnWiz_SmallFlame;
}
-void func_80A49FD8(EnWizFire* this, PlayState* play) {
- if (this->unk_168 > 10) {
- Math_ApproachF(&this->unk_14C, this->unk_150, 0.3f, 0.01f);
+/**
+ * Manages the small flame that is created when the arcing projectiles from the Fire Wizrobe's
+ * attack hit the floor.
+ */
+void EnWiz_SmallFlame(EnWizFire* this, PlayState* play) {
+ if (this->timer > 10) {
+ Math_ApproachF(&this->scale, this->targetScale, 0.3f, 0.01f);
} else {
- Math_ApproachF(&this->unk_14C, 2.0f * this->unk_150, 0.2f, 0.002f);
- Math_ApproachZeroF(&this->unk_1FC, 1.0f, 35.0f);
- if ((this->unk_168 == 0) && (this->unk_1FC < 2.0f)) {
+ Math_ApproachF(&this->scale, 2.0f * this->targetScale, 0.2f, 0.002f);
+ Math_ApproachZeroF(&this->alpha, 1.0f, 35.0f);
+ if ((this->timer == 0) && (this->alpha < 2.0f)) {
Actor_MarkForDeath(&this->actor);
}
return;
}
if (this->collider.base.acFlags & AC_HIT) {
- if (this->unk_168 != 0) {
+ if (this->timer != 0) {
this->collider.base.acFlags &= ~AC_HIT;
- if (this->unk_168 > 10) {
- this->unk_168 -= 10;
+ if (this->timer > 10) {
+ this->timer -= 10;
}
if (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000) {
- this->unk_168 = 0;
- this->unk_148 = 1;
+ this->timer = 0;
+ this->hitByIceArrow = true;
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT);
}
}
}
- if (this->unk_168 != 0) {
+ if (this->timer != 0) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_BURN_OUT - SFX_FLAG);
}
}
-void func_80A4A11C(EnWizFire* this, PlayState* play) {
+/**
+ * Manages the pool of fire or ice that is created when a magic projectile hits the floor.
+ */
+void EnWiz_Pool(EnWizFire* this, PlayState* play) {
s32 pad;
if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) &&
(this->actor.parent->update != NULL) && (this->actor.parent->colChkInfo.health == 0)) {
- this->unk_16A = 0;
- this->unk_174 = 1;
+ this->poolTimer = 0;
+ this->playerHitByIceProjectile = true;
}
- this->unk_16E++;
+ this->lowestUsedIndex++;
- if (this->unk_16E > 10) {
- this->unk_16E = 10;
+ if (this->lowestUsedIndex > 10) {
+ this->lowestUsedIndex = 10;
}
- if (this->unk_16A != 0) {
- Math_ApproachF(&this->unk_200, 60.0f, 0.5f, 10.0f);
- if (this->unk_166 == 1) {
- Vec3f sp40 = { 0.0f, 0.0f, 0.0f };
- Vec3f sp34;
+ if (this->poolTimer != 0) {
+ Math_ApproachF(&this->blendScale, 60.0f, 0.5f, 10.0f);
+ if (this->isIceType == true) {
+ Vec3f accel = { 0.0f, 0.0f, 0.0f };
+ Vec3f pos;
- sp40.x = randPlusMinusPoint5Scaled(3.0f) / 10.0f;
- sp40.y = 0.23f;
- sp40.z = randPlusMinusPoint5Scaled(3.0f) / 10.0f;
+ accel.x = randPlusMinusPoint5Scaled(3.0f) / 10.0f;
+ accel.y = 0.23f;
+ accel.z = randPlusMinusPoint5Scaled(3.0f) / 10.0f;
- Math_Vec3f_Copy(&sp34, &this->actor.world.pos);
- sp34.x += randPlusMinusPoint5Scaled(150.0f);
- sp34.z += randPlusMinusPoint5Scaled(150.0f);
+ Math_Vec3f_Copy(&pos, &this->actor.world.pos);
+ pos.x += randPlusMinusPoint5Scaled(150.0f);
+ pos.z += randPlusMinusPoint5Scaled(150.0f);
- Math_ApproachF(&this->unk_1F0, 0.022f, 0.3f, 0.01f);
- this->collider.dim.radius = this->unk_1F0 * 4300.0f;
+ Math_ApproachF(&this->poolScale, 0.022f, 0.3f, 0.01f);
+ this->collider.dim.radius = this->poolScale * 4300.0f;
this->collider.dim.height = 30;
this->collider.dim.yShift = 15;
- func_80A4BC74(this, &sp34, &sp40);
+ EnWizFire_InitializeEffect(this, &pos, &accel);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
return;
}
- Math_ApproachF(&this->unk_1F0, 0.02f, 0.3f, 0.002f);
- Math_ApproachF(&this->unk_1F8, 0.02f, 0.3f, 0.002f);
- Math_ApproachF(&this->unk_1F4, 0.02f, 0.3f, 0.2f);
- this->collider.dim.radius = this->unk_1F0 * 4000.0f;
- this->collider.dim.height = this->unk_1F4 * 1850.0f;
+ Math_ApproachF(&this->poolScale, 0.02f, 0.3f, 0.002f);
+ Math_ApproachF(&this->fireSmokeScale, 0.02f, 0.3f, 0.002f);
+ Math_ApproachF(&this->bigFlameScale, 0.02f, 0.3f, 0.2f);
+ this->collider.dim.radius = this->poolScale * 4000.0f;
+ this->collider.dim.height = this->bigFlameScale * 1850.0f;
this->collider.dim.yShift = -15;
if (this->collider.dim.height < 2) {
@@ -378,231 +409,228 @@ void func_80A4A11C(EnWizFire* this, PlayState* play) {
if (this->collider.base.acFlags & AC_HIT) {
this->collider.base.acFlags &= ~AC_HIT;
- if ((D_80A4C1C0 == 0) && (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000)) {
- D_80A4C1C0 = 1;
- this->unk_148 = 1;
- this->unk_16A = 0;
+ if (!sPoolHitByIceArrow && (this->collider.info.acHitInfo->toucher.dmgFlags == 0x1000)) {
+ sPoolHitByIceArrow = true;
+ this->hitByIceArrow = true;
+ this->poolTimer = 0;
SoundSource_PlaySfxAtFixedWorldPos(play, &this->actor.world.pos, 50, NA_SE_EV_ICE_MELT);
}
}
+
this->actor.world.pos.y = this->actor.floorHeight + 10.0f;
Actor_SetFocus(&this->actor, 0.0f);
return;
}
- Math_ApproachZeroF(&this->unk_200, 0.2f, 3.0f);
+ Math_ApproachZeroF(&this->blendScale, 0.2f, 3.0f);
- if (this->unk_166 == 1) {
- Math_ApproachZeroF(&this->unk_1F0, 0.046f, 0.001f);
+ if (this->isIceType == true) {
+ Math_ApproachZeroF(&this->poolScale, 0.046f, 0.001f);
Actor_PlaySfxAtPos(&this->actor, NA_SE_EV_ICE_FREEZE - SFX_FLAG);
- if (this->unk_164 == 0) {
- if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->unk_1F0 < 0.05f)) {
+ if (!this->shouldPoolFadeOut) {
+ if ((this->actor.parent != NULL) && (this->actor.parent->id == ACTOR_EN_WIZ) && (this->poolScale < 0.05f)) {
EnWiz* wiz = (EnWiz*)this->actor.parent;
this->collider.dim.yShift = -15;
- this->unk_164 = 1;
- wiz->unk_3BA = 0;
+ this->shouldPoolFadeOut = true;
+ wiz->hasActiveProjectile = false;
}
}
- if ((this->unk_164 != 0) && (this->unk_1F0 < 0.05f)) {
- Math_ApproachZeroF(&this->unk_1FC, 1.0f, 5.0f);
+ if (this->shouldPoolFadeOut && (this->poolScale < 0.05f)) {
+ Math_ApproachZeroF(&this->alpha, 1.0f, 5.0f);
}
- if ((this->unk_1F0 < 0.001f) && (this->unk_204 < 0.001f)) {
- D_80A4C1C0 = 0;
+ if ((this->poolScale < 0.001f) && (this->blendScaleFrac < 0.001f)) {
+ sPoolHitByIceArrow = false;
Actor_MarkForDeath(&this->actor);
}
+
return;
}
- Math_ApproachZeroF(&this->unk_1F4, 0.1f, 0.01f);
+ Math_ApproachZeroF(&this->bigFlameScale, 0.1f, 0.01f);
- if (this->unk_1F4 < 0.01f) {
- Math_ApproachZeroF(&this->unk_1FC, 1.0f, 10.0f);
- if ((this->unk_1FC < 10.0f) && (this->unk_204 < 0.001f)) {
- D_80A4C1C0 = 0;
- if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ) &&
- (this->actor.parent->update != NULL)) {
+ if (this->bigFlameScale < 0.01f) {
+ Math_ApproachZeroF(&this->alpha, 1.0f, 10.0f);
+ if ((this->alpha < 10.0f) && (this->blendScaleFrac < 0.001f)) {
+ sPoolHitByIceArrow = false;
+ if ((this->actor.parent != NULL) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) &&
+ (this->actor.parent->id == ACTOR_EN_WIZ) && (this->actor.parent->update != NULL)) {
EnWiz* wiz = (EnWiz*)this->actor.parent;
- wiz->unk_3BA = 0;
+ wiz->hasActiveProjectile = false;
}
+
Actor_MarkForDeath(&this->actor);
}
}
}
-void func_80A4A608(EnWizFire* this, PlayState* play) {
- if (this->unk_16A == 0) {
- this->unk_16A = 2;
- this->unk_16E++;
- if (this->unk_16E >= 6) {
- if ((this->actor.parent != NULL) && (this->unk_162 == 0) && (this->actor.parent->id == ACTOR_EN_WIZ)) {
+void EnWiz_KillMagicProjectile(EnWizFire* this, PlayState* play) {
+ if (this->increaseLowestUsedIndexTimer == 0) {
+ this->increaseLowestUsedIndexTimer = 2;
+ this->lowestUsedIndex++;
+ if (this->lowestUsedIndex >= 6) {
+ if ((this->actor.parent != NULL) && (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) &&
+ (this->actor.parent->id == ACTOR_EN_WIZ)) {
EnWiz* wiz = (EnWiz*)this->actor.parent;
- D_80A4C1C0 = 0;
+ sPoolHitByIceArrow = false;
if (wiz->actor.update != NULL) {
- wiz->unk_3BA = 0;
+ wiz->hasActiveProjectile = false;
}
}
+
Actor_MarkForDeath(&this->actor);
}
}
}
void EnWizFire_Update(Actor* thisx, PlayState* play2) {
- static Color_RGB8 D_80A4C234[] = {
- { 100, 40, 40 }, { 180, 0x78, 80 }, { 155, 80, 80 }, { 125, 20, 0 },
- { 0, 0, 0 }, { 200, 250, 250 }, { 100, 250, 250 }, { 225, 255, 235 },
+ // These are AmbientColor, DiffuseColor1, DiffuseColor2, and fogColor
+ static Color_RGB8 lightSettingsColors[] = {
+ { 100, 40, 40 }, { 180, 120, 80 }, { 155, 80, 80 }, { 125, 20, 0 }, // Fire
+ { 0, 0, 0 }, { 200, 250, 250 }, { 100, 250, 250 }, { 225, 255, 235 }, // Ice
};
- static Color_RGBA8 D_80A4C24C = { 250, 250, 250, 255 };
- static Color_RGBA8 D_80A4C250 = { 180, 180, 180, 255 };
PlayState* play = play2;
EnWizFire* this = THIS;
Player* player = GET_PLAYER(play);
s32 j;
- s16 temp_s0;
- s16 idx;
+ s16 randomScale;
+ s16 index;
- Actor_SetScale(&this->actor, this->unk_14C);
- func_80A4BDDC(this, play);
- this->unk_204 = this->unk_200 / 60.0f;
+ Actor_SetScale(&this->actor, this->scale);
+ EnWizFire_UpdateEffects(this, play);
+ this->blendScaleFrac = this->blendScale / 60.0f;
- if (this->unk_162 == 0) {
+ if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
Actor* wiz = this->actor.parent;
- if ((wiz != NULL) && (wiz->id == ACTOR_EN_WIZ) && (wiz->update != NULL) && (((EnWiz*)wiz)->unk_74A != 2)) {
- f32 phi_f0;
+ if ((wiz != NULL) && (wiz->id == ACTOR_EN_WIZ) && (wiz->update != NULL) &&
+ (((EnWiz*)wiz)->type != EN_WIZ_TYPE_FIRE_NO_BGM)) {
+ f32 fogNear;
- idx = this->unk_166 * 4;
-
- phi_f0 = 970.0f;
- if (this->unk_166 == 0) {
- phi_f0 = 968.0f;
+ index = this->isIceType * 4;
+ fogNear = 970.0f;
+ if (!this->isIceType) {
+ fogNear = 968.0f;
}
- play->envCtx.lightSettings.fogNear = (phi_f0 - (s16)play->envCtx.unk_C4.fogNear) * this->unk_204;
+ play->envCtx.lightSettings.fogNear = (fogNear - (s16)play->envCtx.unk_C4.fogNear) * this->blendScaleFrac;
play->envCtx.lightSettings.ambientColor[0] =
- ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.ambientColor[0]) * this->unk_204;
+ ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.ambientColor[0]) * this->blendScaleFrac;
play->envCtx.lightSettings.ambientColor[1] =
- ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.ambientColor[1]) * this->unk_204;
+ ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.ambientColor[1]) * this->blendScaleFrac;
play->envCtx.lightSettings.ambientColor[2] =
- ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.ambientColor[2]) * this->unk_204;
+ ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.ambientColor[2]) * this->blendScaleFrac;
- idx++;
+ index++;
play->envCtx.lightSettings.diffuseColor1[0] =
- ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.diffuseColor1[0]) * this->unk_204;
+ ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.diffuseColor1[0]) * this->blendScaleFrac;
play->envCtx.lightSettings.diffuseColor1[1] =
- ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.diffuseColor1[1]) * this->unk_204;
+ ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.diffuseColor1[1]) * this->blendScaleFrac;
play->envCtx.lightSettings.diffuseColor1[2] =
- ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.diffuseColor1[2]) * this->unk_204;
+ ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.diffuseColor1[2]) * this->blendScaleFrac;
- idx++;
+ index++;
play->envCtx.lightSettings.diffuseColor2[0] =
- ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.diffuseColor[0]) * this->unk_204;
+ ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.diffuseColor[0]) * this->blendScaleFrac;
play->envCtx.lightSettings.diffuseColor2[1] =
- ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.diffuseColor[1]) * this->unk_204;
+ ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.diffuseColor[1]) * this->blendScaleFrac;
play->envCtx.lightSettings.diffuseColor2[2] =
- ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.diffuseColor[2]) * this->unk_204;
+ ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.diffuseColor[2]) * this->blendScaleFrac;
- idx++;
+ index++;
play->envCtx.lightSettings.fogColor[0] =
- ((f32)D_80A4C234[idx].r - play->envCtx.unk_C4.fogColor[0]) * this->unk_204;
+ ((f32)lightSettingsColors[index].r - play->envCtx.unk_C4.fogColor[0]) * this->blendScaleFrac;
play->envCtx.lightSettings.fogColor[1] =
- ((f32)D_80A4C234[idx].g - play->envCtx.unk_C4.fogColor[1]) * this->unk_204;
+ ((f32)lightSettingsColors[index].g - play->envCtx.unk_C4.fogColor[1]) * this->blendScaleFrac;
play->envCtx.lightSettings.fogColor[2] =
- ((f32)D_80A4C234[idx].b - play->envCtx.unk_C4.fogColor[2]) * this->unk_204;
+ ((f32)lightSettingsColors[index].b - play->envCtx.unk_C4.fogColor[2]) * this->blendScaleFrac;
}
}
- this->unk_170++;
+ this->smallFlameScroll++;
this->actionFunc(this, play);
this->actor.shape.yOffset = 10.0f;
Actor_UpdatePos(&this->actor);
- this->unk_178[0] = this->actor.world.pos;
+ this->magicProjectilePos[0] = this->actor.world.pos;
- for (j = 8; j >= 0; j--) {
- this->unk_178[j + 1] = this->unk_178[j];
+ for (j = ARRAY_COUNT(this->magicProjectilePos) - 2; j >= 0; j--) {
+ this->magicProjectilePos[j + 1] = this->magicProjectilePos[j];
}
this->actor.velocity.y += this->actor.gravity;
- if (this->unk_172 != 0) {
- this->unk_172--;
- }
-
- if (this->unk_168 != 0) {
- this->unk_168--;
- }
-
- if (this->unk_16C != 0) {
- this->unk_16C--;
- }
-
- if (this->unk_16A != 0) {
- this->unk_16A--;
- }
+ DECR(this->wallCheckTimer);
+ DECR(this->timer);
+ DECR(this->steamSpawnTimer);
+ DECR(this->poolTimer);
Actor_UpdateBgCheckInfo(play, &this->actor, 20.0f, 5.0f, 10, 0x1D);
- if (((this->unk_148 != 0) || (D_80A4C1C0 != 0)) && (this->unk_16C == 0)) {
- Vec3f sp70;
- Vec3f sp64;
- Vec3f sp58;
- f32 sp54;
+ if ((this->hitByIceArrow || sPoolHitByIceArrow) && (this->steamSpawnTimer == 0)) {
+ Vec3f accel;
+ Vec3f velocity;
+ Vec3f pos;
+ f32 scaleStep;
s32 i;
- sp70.x = 0.0f;
- sp70.y = 1.0f;
- sp70.z = 0.0f;
- sp64.x = 0.0f;
- sp64.y = 1.0f;
- sp64.z = 0.0f;
+ accel.x = 0.0f;
+ accel.y = 1.0f;
+ accel.z = 0.0f;
+ velocity.x = 0.0f;
+ velocity.y = 1.0f;
+ velocity.z = 0.0f;
- sp54 = Rand_S16Offset(20, 10);
- if (this->unk_162 == 0) {
- sp54 = Rand_S16Offset(40, 20);
+ scaleStep = Rand_S16Offset(20, 10);
+ if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
+ scaleStep = Rand_S16Offset(40, 20);
}
- this->unk_16C = Rand_S16Offset(2, 2);
+ this->steamSpawnTimer = Rand_S16Offset(2, 2);
for (i = 0; i < 2; i++) {
- temp_s0 = Rand_S16Offset(20, 20);
- sp58.x = ((f32)((Rand_ZeroOne() < 0.5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.x;
- sp58.y = (Rand_ZeroOne() * 20.0f) + this->actor.floorHeight;
- temp_s0 = Rand_S16Offset(20, 20);
- sp58.z = ((f32)((Rand_ZeroOne() < .5f) ? -1 : 1) * temp_s0) + this->actor.world.pos.z;
- func_800B0DE0(play, &sp58, &sp64, &sp70, &D_80A4C24C, &D_80A4C250, Rand_S16Offset(350, 100), sp54);
+ static Color_RGBA8 sSteamPrimColor = { 250, 250, 250, 255 };
+ static Color_RGBA8 sSteamEnvColor = { 180, 180, 180, 255 };
+
+ randomScale = Rand_S16Offset(20, 20);
+ pos.x = ((f32)((Rand_ZeroOne() < 0.5f) ? -1 : 1) * randomScale) + this->actor.world.pos.x;
+ pos.y = (Rand_ZeroOne() * 20.0f) + this->actor.floorHeight;
+ randomScale = Rand_S16Offset(20, 20);
+ pos.z = ((f32)((Rand_ZeroOne() < .5f) ? -1 : 1) * randomScale) + this->actor.world.pos.z;
+ func_800B0DE0(play, &pos, &velocity, &accel, &sSteamPrimColor, &sSteamEnvColor, Rand_S16Offset(350, 100),
+ scaleStep);
}
}
- if (this->unk_160 < 2) {
- this->collider.dim.radius = (this->unk_14C * 15.0f) + 25.0f;
- this->collider.dim.height = (this->unk_14C * 15.0f) + 25.0f;
- this->collider.dim.yShift = (this->unk_14C * -0.75f) - 5.0f;
+ if (this->action < EN_WIZ_FIRE_ACTION_POOL) {
+ this->collider.dim.radius = (this->scale * 15.0f) + 25.0f;
+ this->collider.dim.height = (this->scale * 15.0f) + 25.0f;
+ this->collider.dim.yShift = (this->scale * -0.75f) - 5.0f;
}
- if (this->unk_162 == 2) {
+ if (this->type == EN_WIZ_FIRE_TYPE_SMALL_FLAME) {
this->collider.dim.radius = 10;
- this->collider.dim.height = this->unk_14C * 5000.0f;
+ this->collider.dim.height = this->scale * 5000.0f;
this->collider.dim.yShift = 0;
}
if (this->collider.base.atFlags & AT_HIT) {
this->collider.base.atFlags &= ~AT_HIT;
- if (this->unk_162 == 0) {
+ if (this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) {
Actor_PlaySfxAtPos(&this->actor, NA_SE_EN_WIZ_LAUGH2);
if (player->invincibilityTimer > 0) {
player->invincibilityTimer += 40;
- if (this->unk_166 != 0) {
+ if (this->isIceType) {
player->invincibilityTimer += 50;
- this->unk_174 = 1;
+ this->playerHitByIceProjectile = true;
}
}
}
@@ -612,7 +640,8 @@ void EnWizFire_Update(Actor* thisx, PlayState* play2) {
player->unk_AE8 = 90;
}
- if ((this->unk_148 == 0) && (D_80A4C1C0 == 0) && ((this->unk_162 != 0) || (this->unk_1FC > 200.0f))) {
+ if (!this->hitByIceArrow && !sPoolHitByIceArrow &&
+ ((this->type != EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) || (this->alpha > 200.0f))) {
Collider_UpdateCylinder(&this->actor, &this->collider);
CollisionCheck_SetAC(play, &play->colChkCtx, &this->collider.base);
if (player->invincibilityTimer == 0) {
@@ -621,61 +650,63 @@ void EnWizFire_Update(Actor* thisx, PlayState* play2) {
}
}
-void func_80A4B0C8(EnWizFire* this, PlayState* play) {
+void EnWizFire_DrawIcePool(EnWizFire* this, PlayState* play) {
s32 pad;
OPEN_DISPS(play->state.gfxCtx);
- if ((this->unk_162 == 0) && (this->unk_160 == 2)) {
+ if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->action == EN_WIZ_FIRE_ACTION_POOL)) {
func_8012C28C(play->state.gfxCtx);
func_8012C2DC(play->state.gfxCtx);
Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW);
- Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY);
+ Matrix_Scale(this->poolScale, this->poolScale, this->poolScale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPPipeSync(POLY_XLU_DISP++);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->unk_1FC);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, (s8)this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 40, 30, 80);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005190);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 215, 215, 215, (s8)this->unk_1FC);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeIcePoolDL);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 215, 215, 215, (s8)this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 255, 255, 128);
gSPSegment(POLY_XLU_DISP++, 0x08,
- Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames & 0x7F, -play->state.frames & 0x7F, 0x20,
- 0x40, 1, play->state.frames & 0xFF, play->state.frames & 0xFF, 0x10, 0x10));
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames & 0x7F, -play->state.frames & 0x7F, 32,
+ 64, 1, play->state.frames & 0xFF, play->state.frames & 0xFF, 16, 16));
Matrix_RotateYS(0, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_005750);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeIcePoolShineDL);
}
- func_80A4BF78(this, play);
+ EnWizFire_DrawEffects(this, play);
CLOSE_DISPS(play->state.gfxCtx);
}
-void func_80A4B33C(EnWizFire* this, PlayState* play2) {
+void EnWizFire_DrawFirePoolAndFlame(EnWizFire* this, PlayState* play2) {
PlayState* play = play2;
OPEN_DISPS(play->state.gfxCtx);
- if ((this->unk_162 == 0) && (this->unk_160 == 2)) {
+ if ((this->type == EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE) && (this->action == EN_WIZ_FIRE_ACTION_POOL)) {
func_8012C28C(play->state.gfxCtx);
func_8012C2DC(play->state.gfxCtx);
+
Matrix_Push();
Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW);
- Matrix_Scale(this->unk_1F0, this->unk_1F0, this->unk_1F0, MTXMODE_APPLY);
+ Matrix_Scale(this->poolScale, this->poolScale, this->poolScale, MTXMODE_APPLY);
gSPSegment(POLY_XLU_DISP++, 0x08,
Gfx_TwoTexScroll(play->state.gfxCtx, 0, -play->state.frames % 128, 0, 0x20, 0x20, 1,
(play->state.frames * 2) % 128, 0, 0x20, 0x20));
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPPipeSync(POLY_XLU_DISP++);
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 40, 0, (s8)this->unk_1FC);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 100, 40, 0, (s8)this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 255, 245, 255, 128);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003120);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeFirePoolDL);
Matrix_Pop();
+
Matrix_Push();
Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
@@ -684,16 +715,17 @@ void func_80A4B33C(EnWizFire* this, PlayState* play2) {
Gfx_TwoTexScroll(play->state.gfxCtx, 0, play->state.frames % 128, (-play->state.frames * 6) % 256,
0x20, 0x40, 1, (play->state.frames * 2) % 128, (-play->state.frames * 6) % 256,
0x20, 0x40));
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 0, 0, (s8)this->unk_1FC);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 80, 0, 0, (s8)this->alpha);
gDPPipeSync(POLY_XLU_DISP++);
gDPSetEnvColor(POLY_XLU_DISP++, 0, 0, 0, 100);
- Matrix_Scale(this->unk_1F8, this->unk_1F8, this->unk_1F8, MTXMODE_APPLY);
+ Matrix_Scale(this->fireSmokeScale, this->fireSmokeScale, this->fireSmokeScale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003640);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeFireSmokeDL);
Matrix_Pop();
+
Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight, this->actor.world.pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
@@ -704,10 +736,10 @@ void func_80A4B33C(EnWizFire* this, PlayState* play2) {
gDPPipeSync(POLY_XLU_DISP++);
gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 240, 128);
- Matrix_Scale(this->unk_1F4, this->unk_1F4, this->unk_1F4, MTXMODE_APPLY);
+ Matrix_Scale(this->bigFlameScale, this->bigFlameScale, this->bigFlameScale, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_003FC0);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeBigFlameDL);
}
CLOSE_DISPS(play->state.gfxCtx);
@@ -724,11 +756,11 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) {
func_8012C2DC(play->state.gfxCtx);
Matrix_Push();
- for (i = 9; i >= this->unk_16E; i--) {
- f32 temp_f20 = this->actor.scale.x - (i * -0.0019f);
+ for (i = ARRAY_COUNT(this->magicProjectilePos) - 1; i >= this->lowestUsedIndex; i--) {
+ f32 scale = this->actor.scale.x - (i * -0.0019f);
- if (temp_f20 > 0.0f) {
- if (this->unk_166 == 0) {
+ if (scale > 0.0f) {
+ if (!this->isIceType) {
gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255 - (i * 25), 0, 255 - (i * 25));
gDPSetEnvColor(POLY_XLU_DISP++, 255 - (i * 25), 0, 0, 0);
} else {
@@ -736,14 +768,14 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) {
gDPSetEnvColor(POLY_XLU_DISP++, 220, 255, 235, 0);
}
- Matrix_Translate(this->unk_178[i].x, this->unk_178[i].y + this->actor.shape.yOffset, this->unk_178[i].z,
- MTXMODE_NEW);
- Matrix_Scale(temp_f20, temp_f20, temp_f20, MTXMODE_APPLY);
+ Matrix_Translate(this->magicProjectilePos[i].x, this->magicProjectilePos[i].y + this->actor.shape.yOffset,
+ this->magicProjectilePos[i].z, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
Matrix_ReplaceRotation(&play->billboardMtxF);
Matrix_RotateZS(this->actor.world.rot.z, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002B40);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeMagicProjectileDL);
}
}
@@ -751,92 +783,92 @@ void EnWizFire_Draw(Actor* thisx, PlayState* play2) {
CLOSE_DISPS(play->state.gfxCtx);
- if (this->unk_166 == 0) {
- func_80A4B33C(this, play);
+ if (!this->isIceType) {
+ EnWizFire_DrawFirePoolAndFlame(this, play);
} else {
- func_80A4B0C8(this, play);
+ EnWizFire_DrawIcePool(this, play);
}
}
-void func_80A4BAB4(Actor* thisx, PlayState* play) {
+void EnWizFire_DrawSmallFlame(Actor* thisx, PlayState* play) {
s32 pad;
EnWizFire* this = THIS;
OPEN_DISPS(play->state.gfxCtx);
Matrix_Translate(this->actor.world.pos.x, this->actor.floorHeight + 20.0f, this->actor.world.pos.z, MTXMODE_NEW);
- Matrix_Scale(this->unk_14C + this->unk_154, this->unk_14C + this->unk_158, this->unk_14C + this->unk_15C,
+ Matrix_Scale(this->scale + this->scaleMod.x, this->scale + this->scaleMod.y, this->scale + this->scaleMod.z,
MTXMODE_APPLY);
gSPSegment(POLY_XLU_DISP++, 0x08,
- Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 0x20, 0x20, 1, this->unk_170 & 0x7F,
- (-this->unk_170 * 10) & 0x7F, 0x20, 0x20));
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 100, 50, 0, (s8)this->unk_1FC);
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, 0, 0, 32, 32, 1, this->smallFlameScroll & 0x7F,
+ (-this->smallFlameScroll * 10) & 0x7F, 32, 32));
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0x80, 100, 50, 0, (s8)this->alpha);
gDPSetEnvColor(POLY_XLU_DISP++, 200, 235, 245, 255);
Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_002630);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeSmallFlameDL);
CLOSE_DISPS(play->state.gfxCtx);
}
-void func_80A4BC74(EnWizFire* this, Vec3f* arg1, Vec3f* arg2) {
+void EnWizFire_InitializeEffect(EnWizFire* this, Vec3f* pos, Vec3f* accel) {
s16 i;
- EnWizFireStruct* ptr = this->unk_254;
+ EnWizFireEffect* effect = &this->effects[0];
- for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) {
- if (ptr->unk_00 == 0) {
- ptr->unk_00 = 1;
- Math_Vec3f_Copy(&ptr->unk_1C, &gZeroVec3f);
- ptr->unk_01 = Rand_ZeroFloat(100.0f);
- ptr->unk_10 = *arg1;
- ptr->unk_28 = *arg2;
- ptr->unk_0C = (Rand_ZeroFloat(5.0f) + 20.0f) * 0.001f;
- ptr->unk_08 = 0;
- ptr->unk_06 = 0;
+ for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) {
+ if (!effect->isEnabled) {
+ effect->isEnabled = true;
+ Math_Vec3f_Copy(&effect->velocity, &gZeroVec3f);
+ effect->smokeScroll = Rand_ZeroFloat(100.0f);
+ effect->pos = *pos;
+ effect->accel = *accel;
+ effect->scale = (Rand_ZeroFloat(5.0f) + 20.0f) * 0.001f;
+ effect->shouldDecreaseAlpha = 0;
+ effect->alpha = 0;
break;
}
}
}
-void func_80A4BDDC(EnWizFire* this, PlayState* play) {
+void EnWizFire_UpdateEffects(EnWizFire* this, PlayState* play) {
s32 i;
- EnWizFireStruct* ptr = &this->unk_254[0];
+ EnWizFireEffect* effect = &this->effects[0];
- for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) {
- if (ptr->unk_00 != 0) {
- ptr->unk_01++;
+ for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) {
+ if (effect->isEnabled) {
+ effect->smokeScroll++;
- ptr->unk_10.x += ptr->unk_1C.x;
- ptr->unk_10.y += ptr->unk_1C.y;
- ptr->unk_10.z += ptr->unk_1C.z;
+ effect->pos.x += effect->velocity.x;
+ effect->pos.y += effect->velocity.y;
+ effect->pos.z += effect->velocity.z;
- ptr->unk_1C.x += ptr->unk_28.x;
- ptr->unk_1C.y += ptr->unk_28.y;
- ptr->unk_1C.z += ptr->unk_28.z;
+ effect->velocity.x += effect->accel.x;
+ effect->velocity.y += effect->accel.y;
+ effect->velocity.z += effect->accel.z;
- if (ptr->unk_08 == 0) {
- ptr->unk_06 += 10;
- if (ptr->unk_06 >= 100) {
- ptr->unk_08 = 1;
+ if (!effect->shouldDecreaseAlpha) {
+ effect->alpha += 10;
+ if (effect->alpha >= 100) {
+ effect->shouldDecreaseAlpha = true;
}
} else {
- ptr->unk_06 -= 8;
- if (ptr->unk_06 <= 0) {
- ptr->unk_06 = 0;
- ptr->unk_00 = 0;
+ effect->alpha -= 8;
+ if (effect->alpha <= 0) {
+ effect->alpha = 0;
+ effect->isEnabled = false;
}
}
}
}
}
-void func_80A4BF78(EnWizFire* this, PlayState* play) {
+void EnWizFire_DrawEffects(EnWizFire* this, PlayState* play) {
s16 i;
- u8 flag;
- EnWizFireStruct* ptr = &this->unk_254[0];
+ u8 materialFlag;
+ EnWizFireEffect* effect = &this->effects[0];
GraphicsContext* gfxCtx = play->state.gfxCtx;
OPEN_DISPS(gfxCtx);
@@ -844,27 +876,27 @@ void func_80A4BF78(EnWizFire* this, PlayState* play) {
func_8012C28C(play->state.gfxCtx);
func_8012C2DC(play->state.gfxCtx);
- flag = false;
- for (i = 0; i < ARRAY_COUNT(this->unk_254); i++, ptr++) {
- if (ptr->unk_00 != 0) {
- if (!flag) {
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000E70);
- flag++;
+ materialFlag = false;
+ for (i = 0; i < ARRAY_COUNT(this->effects); i++, effect++) {
+ if (effect->isEnabled) {
+ if (!materialFlag) {
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeIceSmokeMaterialDL);
+ materialFlag++;
}
- gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, ptr->unk_06);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 195, 225, 235, effect->alpha);
gSPSegment(POLY_XLU_DISP++, 0x08,
- Gfx_TwoTexScroll(play->state.gfxCtx, 0, (ptr->unk_01 * 3) & 0x7F, (ptr->unk_01 * 0xF) & 0xFF,
- 0x20, 0x40, 1, 0, 0, 0x20, 0x20));
+ Gfx_TwoTexScroll(play->state.gfxCtx, 0, (effect->smokeScroll * 3) & 0x7F,
+ (effect->smokeScroll * 0xF) & 0xFF, 32, 64, 1, 0, 0, 32, 32));
- Matrix_Translate(ptr->unk_10.x, ptr->unk_10.y, ptr->unk_10.z, MTXMODE_NEW);
+ Matrix_Translate(effect->pos.x, effect->pos.y, effect->pos.z, MTXMODE_NEW);
Matrix_ReplaceRotation(&play->billboardMtxF);
- Matrix_Scale(ptr->unk_0C, ptr->unk_0C, 1.0f, MTXMODE_APPLY);
+ Matrix_Scale(effect->scale, effect->scale, 1.0f, MTXMODE_APPLY);
gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
gDPSetRenderMode(POLY_XLU_DISP++, G_RM_PASS, G_RM_AA_ZB_XLU_SURF2);
gSPClearGeometryMode(POLY_XLU_DISP++, G_CULL_BACK | G_FOG);
- gSPDisplayList(POLY_XLU_DISP++, object_wiz_DL_000FD8);
+ gSPDisplayList(POLY_XLU_DISP++, gWizrobeIceSmokeModelDL);
}
}
diff --git a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h
index b628404bb..180192d4c 100644
--- a/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h
+++ b/src/overlays/actors/ovl_En_Wiz_Fire/z_en_wiz_fire.h
@@ -3,52 +3,65 @@
#include "global.h"
+typedef enum {
+ /* 0 */ EN_WIZ_FIRE_TYPE_MAGIC_PROJECTILE,
+ /* 1 */ EN_WIZ_FIRE_TYPE_ARCING_MAGIC_PROJECTILE,
+ /* 2 */ EN_WIZ_FIRE_TYPE_SMALL_FLAME,
+ /* 3 */ EN_WIZ_FIRE_TYPE_REFLECTED_MAGIC_PROJECTILE,
+ /* 4 */ EN_WIZ_FIRE_TYPE_ICE_MAGIC_PROJECTILE
+} EnWizFireType;
+
+#define EN_WIZ_FIRE_GET_TYPE(thisx) ((thisx)->params)
+
struct EnWizFire;
typedef void (*EnWizFireActionFunc)(struct EnWizFire*, PlayState*);
typedef struct {
- /* 0x00 */ u8 unk_00;
- /* 0x01 */ u8 unk_01;
+ /* 0x00 */ u8 isEnabled;
+ /* 0x01 */ u8 smokeScroll;
/* 0x02 */ UNK_TYPE1 unk02[0x4];
- /* 0x06 */ s16 unk_06;
- /* 0x08 */ s16 unk_08;
- /* 0x0A */ UNK_TYPE1 unk0A[0x2];
- /* 0x0C */ f32 unk_0C;
- /* 0x10 */ Vec3f unk_10;
- /* 0x1C */ Vec3f unk_1C;
- /* 0x28 */ Vec3f unk_28;
-} EnWizFireStruct; // size = 0x34
+ /* 0x06 */ s16 alpha;
+ /* 0x08 */ s16 shouldDecreaseAlpha;
+ /* 0x0C */ f32 scale;
+ /* 0x10 */ Vec3f pos;
+ /* 0x1C */ Vec3f velocity;
+ /* 0x28 */ Vec3f accel;
+} EnWizFireEffect; // size = 0x34
typedef struct EnWizFire {
/* 0x0000 */ Actor actor;
/* 0x0144 */ EnWizFireActionFunc actionFunc;
- /* 0x0148 */ u8 unk_148;
- /* 0x014C */ f32 unk_14C;
- /* 0x0150 */ f32 unk_150;
- /* 0x0154 */ f32 unk_154;
- /* 0x0158 */ f32 unk_158;
- /* 0x015C */ f32 unk_15C;
- /* 0x0160 */ s16 unk_160;
- /* 0x0162 */ s16 unk_162;
- /* 0x0164 */ u8 unk_164;
- /* 0x0166 */ s16 unk_166;
- /* 0x0168 */ s16 unk_168;
- /* 0x016A */ s16 unk_16A;
- /* 0x016C */ s16 unk_16C;
- /* 0x016E */ s16 unk_16E;
- /* 0x0170 */ s16 unk_170;
- /* 0x0172 */ s16 unk_172;
- /* 0x0174 */ s8 unk_174;
- /* 0x0178 */ Vec3f unk_178[10];
- /* 0x01F0 */ f32 unk_1F0;
- /* 0x01F4 */ f32 unk_1F4;
- /* 0x01F8 */ f32 unk_1F8;
- /* 0x01FC */ f32 unk_1FC;
- /* 0x0200 */ f32 unk_200;
- /* 0x0204 */ f32 unk_204;
+ /* 0x0148 */ u8 hitByIceArrow;
+ /* 0x014C */ f32 scale;
+ /* 0x0150 */ f32 targetScale;
+ /* 0x0154 */ Vec3f scaleMod;
+ /* 0x0160 */ s16 action;
+ /* 0x0162 */ s16 type;
+ /* 0x0164 */ union {
+ u8 shouldPoolFadeOut;
+ u8 hasSpawnedSmallFlame;
+ };
+ /* 0x0166 */ s16 isIceType;
+ /* 0x0168 */ s16 timer;
+ /* 0x016A */ union {
+ s16 poolTimer;
+ s16 increaseLowestUsedIndexTimer;
+ };
+ /* 0x016C */ s16 steamSpawnTimer;
+ /* 0x016E */ s16 lowestUsedIndex;
+ /* 0x0170 */ s16 smallFlameScroll;
+ /* 0x0172 */ s16 wallCheckTimer; // The projectile won't check for impacts with walls until this is zero
+ /* 0x0174 */ s8 playerHitByIceProjectile; // Set, but never used
+ /* 0x0178 */ Vec3f magicProjectilePos[10];
+ /* 0x01F0 */ f32 poolScale;
+ /* 0x01F4 */ f32 bigFlameScale;
+ /* 0x01F8 */ f32 fireSmokeScale;
+ /* 0x01FC */ f32 alpha;
+ /* 0x0200 */ f32 blendScale;
+ /* 0x0204 */ f32 blendScaleFrac;
/* 0x0208 */ ColliderCylinder collider;
- /* 0x0254 */ EnWizFireStruct unk_254[200];
+ /* 0x0254 */ EnWizFireEffect effects[200];
} EnWizFire; // size = 0x2AF4
extern const ActorInit En_Wiz_Fire_InitVars;
diff --git a/src/overlays/actors/ovl_En_Yb/z_en_yb.c b/src/overlays/actors/ovl_En_Yb/z_en_yb.c
index d28a06fa0..11474f01e 100644
--- a/src/overlays/actors/ovl_En_Yb/z_en_yb.c
+++ b/src/overlays/actors/ovl_En_Yb/z_en_yb.c
@@ -68,7 +68,7 @@ static ColliderCylinderInit sCylinderInit = {
// assumption: draw uses two different skeleton functions, might be incompatible
static AnimationHeader* gYbUnusedAnimations[] = { &object_yb_Anim_000200 };
-static LinkAnimationHeader* gLinkAnimations[] = { &gameplay_keep_Linkanim_00DF28, &gameplay_keep_Linkanim_00CF98 };
+static LinkAnimationHeader* gLinkAnimations[] = { &gPlayerAnim_link_normal_wait_free, &gPlayerAnim_alink_dance_loop };
static Vec3f D_80BFB2E8 = { 0.0f, 0.5f, 0.0f };
diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c
index 681438463..1f92e8825 100644
--- a/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/src/overlays/actors/ovl_player_actor/z_player.c
@@ -7,6 +7,7 @@
#include "global.h"
#include "z64quake.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
#define THIS ((Player*)thisx)
diff --git a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c
index 04afcba3f..01224dd32 100644
--- a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c
+++ b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.c
@@ -1,27 +1,93 @@
/*
* File: z_eff_ss_solder_srch_ball.c
* Overlay: ovl_Effect_Ss_Solder_Srch_Ball
- * Description:
+ * Description: Vision sphere
*/
#include "z_eff_ss_solder_srch_ball.h"
+#include "objects/gameplay_keep/gameplay_keep.h"
+
+#define rFlags regs[0]
#define PARAMS ((EffectSsSolderSrchBallInitParams*)initParamsx)
-s32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx);
+u32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx);
void EffectSsSolderSrchBall_Update(PlayState* play, u32 index, EffectSs* this);
void EffectSsSolderSrchBall_Draw(PlayState* play, u32 index, EffectSs* this);
-#if 0
const EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars = {
EFFECT_SS_SOLDER_SRCH_BALL,
EffectSsSolderSrchBall_Init,
};
-#endif
+u32 EffectSsSolderSrchBall_Init(PlayState* play, u32 index, EffectSs* this, void* initParamsx) {
+ EffectSsSolderSrchBallInitParams* initParams = PARAMS;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Init.s")
+ this->pos = initParams->pos;
+ this->velocity = initParams->velocity;
+ this->accel = initParams->accel;
+ this->update = EffectSsSolderSrchBall_Update;
+ if (!(initParams->flags & SOLDERSRCHBALL_INVISIBLE)) {
+ this->draw = EffectSsSolderSrchBall_Draw;
+ }
+ this->life = 10;
+ this->rgScale = initParams->scale;
+ this->rFlags = initParams->flags;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Draw.s")
+ //! @bug actor field used to store an s16*
+ // This bug is purely cosmetic. Nothing external will ever read this as an Actor, so there are no unintended
+ // side-effects.
+ this->actor = (Actor*)initParams->playerDetected;
+ return 1;
+}
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_Effect_Ss_Solder_Srch_Ball/EffectSsSolderSrchBall_Update.s")
+void EffectSsSolderSrchBall_Draw(PlayState* play, u32 index, EffectSs* this) {
+ s32 pad;
+ GraphicsContext* gfxCtx = play->state.gfxCtx;
+ f32 scale = this->rgScale / 100.0f;
+
+ func_8012C28C(gfxCtx);
+ func_8012C2DC(play->state.gfxCtx);
+
+ OPEN_DISPS(gfxCtx);
+
+ Matrix_Translate(this->pos.x, this->pos.y, this->pos.z, MTXMODE_NEW);
+ Matrix_Scale(scale, scale, scale, MTXMODE_APPLY);
+ POLY_XLU_DISP = Gfx_CallSetupDL(POLY_XLU_DISP, 20);
+ gSPSegment(POLY_XLU_DISP++, 0x08, Lib_SegmentedToVirtual(gSun1Tex));
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleMaterialDL);
+ gDPPipeSync(POLY_XLU_DISP++);
+ gDPSetPrimColor(POLY_XLU_DISP++, 0, 0, 255, 255, 255, 255);
+ gDPSetEnvColor(POLY_XLU_DISP++, 250, 180, 255, 255);
+ Matrix_Mult(&play->billboardMtxF, MTXMODE_APPLY);
+ Matrix_RotateZF(DEGF_TO_RADF(20.0f * play->state.frames), MTXMODE_APPLY);
+ gSPMatrix(POLY_XLU_DISP++, Matrix_NewMtx(play->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW);
+ gSPDisplayList(POLY_XLU_DISP++, gSunSparkleModelDL);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+void EffectSsSolderSrchBall_Update(PlayState* play, u32 index, EffectSs* this) {
+ s32 pad;
+ f32 diffX;
+ f32 diffY;
+ f32 diffZ;
+ s16* playerDetected = (s16*)this->actor;
+ Player* player = GET_PLAYER(play);
+
+ diffX = player->actor.world.pos.x - this->pos.x;
+ diffY = player->actor.world.pos.y - this->pos.y;
+ diffZ = player->actor.world.pos.z - this->pos.z;
+
+ if (this->rFlags >= SOLDERSRCHBALL_SMALL_DETECT_RADIUS) {
+ if ((sqrtf(SQ(diffX) + SQ(diffZ)) < 10.0f) && (sqrtf(SQ(diffY)) < 10.0f)) {
+ *playerDetected = true;
+ }
+ } else if (!BgCheck_SphVsFirstWall(&play->colCtx, &this->pos, 30.0f)) {
+ if ((sqrtf(SQ(diffX) + SQ(diffZ)) < 40.0f) && (sqrtf(SQ(diffY)) < 80.0f)) {
+ *playerDetected = true;
+ }
+ } else if (this->life > 1) {
+ this->life = 1;
+ }
+}
diff --git a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h
index 24b9f47fc..fb4fb4159 100644
--- a/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h
+++ b/src/overlays/effects/ovl_Effect_Ss_Solder_Srch_Ball/z_eff_ss_solder_srch_ball.h
@@ -3,13 +3,16 @@
#include "global.h"
+#define SOLDERSRCHBALL_INVISIBLE (1 << 0)
+#define SOLDERSRCHBALL_SMALL_DETECT_RADIUS (1 << 1)
+
typedef struct {
/* 0x00 */ Vec3f pos;
/* 0x0C */ Vec3f velocity;
/* 0x18 */ Vec3f accel;
- /* 0x24 */ s16 unused;
- /* 0x28 */ s16* linkDetected;
- /* 0x2C */ s16 drawFlag;
+ /* 0x24 */ s16 scale;
+ /* 0x28 */ s16* playerDetected;
+ /* 0x2C */ s16 flags;
} EffectSsSolderSrchBallInitParams; // size = 0x30
extern const EffectSsInit Effect_Ss_Solder_Srch_Ball_InitVars;
diff --git a/src/overlays/gamestates/ovl_daytelop/z_daytelop.c b/src/overlays/gamestates/ovl_daytelop/z_daytelop.c
index ad5230253..201030862 100644
--- a/src/overlays/gamestates/ovl_daytelop/z_daytelop.c
+++ b/src/overlays/gamestates/ovl_daytelop/z_daytelop.c
@@ -5,6 +5,8 @@
*/
#include "z_daytelop.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "misc/daytelop_static/daytelop_static.h"
#include "interface/icon_item_gameover_static/icon_item_gameover_static.h"
diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c
index 657a2530f..da9144e7c 100644
--- a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c
+++ b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c
@@ -6,6 +6,8 @@
#include "z_file_choose.h"
#include "z64rumble.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
extern UNK_TYPE D_01002800;
extern UNK_TYPE D_01007980;
diff --git a/src/overlays/gamestates/ovl_opening/z_opening.c b/src/overlays/gamestates/ovl_opening/z_opening.c
index 42336b9bc..fc5d05be2 100644
--- a/src/overlays/gamestates/ovl_opening/z_opening.c
+++ b/src/overlays/gamestates/ovl_opening/z_opening.c
@@ -5,6 +5,8 @@
*/
#include "z_opening.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
void TitleSetup_SetupTitleScreen(TitleSetupState* this) {
static s32 sOpeningEntrances[] = { ENTRANCE(CUTSCENE, 0), ENTRANCE(CUTSCENE, 1) };
diff --git a/src/overlays/gamestates/ovl_select/z_select.c b/src/overlays/gamestates/ovl_select/z_select.c
index 5ec343e7f..b7b21167e 100644
--- a/src/overlays/gamestates/ovl_select/z_select.c
+++ b/src/overlays/gamestates/ovl_select/z_select.c
@@ -5,6 +5,8 @@
*/
#include "z_select.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "libc/alloca.h"
#include "overlays/gamestates/ovl_title/z_title.h"
@@ -1026,7 +1028,7 @@ void MapSelect_Draw(MapSelectState* this) {
func_8012CF0C(gfxCtx, true, true, 0, 0, 0);
SET_FULLSCREEN_VIEWPORT(&this->view);
- View_RenderView(&this->view, 0xF);
+ View_Apply(&this->view, VIEW_ALL);
if (!this->state.running) {
MapSelect_DrawLoadingScreen(this);
} else {
diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c
index 62d2a36d0..2b23bf565 100644
--- a/src/overlays/gamestates/ovl_title/z_title.c
+++ b/src/overlays/gamestates/ovl_title/z_title.c
@@ -5,6 +5,8 @@
*/
#include "z_title.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
#include "overlays/gamestates/ovl_opening/z_opening.h"
#include "misc/nintendo_rogo_static/nintendo_rogo_static.h"
@@ -44,9 +46,9 @@ void ConsoleLogo_RenderView(ConsoleLogoState* this, f32 x, f32 y, f32 z) {
up.x = up.z = 0.0f;
at.x = at.y = at.z = 0.0f;
up.y = 1.0f;
- func_8013F0D0(view, 30.0f, 10.0f, 12800.0f);
- View_SetViewOrientation(view, &eye, &at, &up);
- View_RenderView(view, 0xF);
+ View_SetPerspective(view, 30.0f, 10.0f, 12800.0f);
+ View_LookAt(view, &eye, &at, &up);
+ View_Apply(view, VIEW_ALL);
}
void ConsoleLogo_Draw(GameState* thisx) {
diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c
index c02ebcad2..3b3de5937 100644
--- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c
+++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c
@@ -5,6 +5,7 @@
*/
#include "z_kaleido_scope.h"
+#include "z64view.h"
extern UNK_TYPE D_02001360;
extern UNK_TYPE D_020044A0;
diff --git a/tools/disasm/files.txt b/tools/disasm/files.txt
index ffa305cdd..c546c1f69 100644
--- a/tools/disasm/files.txt
+++ b/tools/disasm/files.txt
@@ -597,6 +597,7 @@
0x801D9090 : "audio_sound_params",
0x801DB470 : "code_801A5BD0",
0x801DB4C0 : "code_801A7B10",
+ 0x801DB4E0 : "audio_init_params",
# .rodata section
0x801DBDF0 : "z_en_item00",
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index 887c94afd..cf2f9676b 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -2721,33 +2721,33 @@
0x8013EE48:("Rumble_SetUpdateEnabled",),
0x8013EE60:("View_ViewportToVp",),
0x8013EEF4:("View_Init",),
- 0x8013EF9C:("View_SetViewOrientation",),
- 0x8013F050:("func_8013F050",),
+ 0x8013EF9C:("View_LookAt",),
+ 0x8013F050:("View_LookAtUnsafe",),
0x8013F0A0:("View_SetScale",),
0x8013F0C0:("View_GetScale",),
- 0x8013F0D0:("func_8013F0D0",),
- 0x8013F100:("func_8013F100",),
- 0x8013F120:("func_8013F120",),
- 0x8013F15C:("func_8013F15C",),
+ 0x8013F0D0:("View_SetPerspective",),
+ 0x8013F100:("View_GetPerspective",),
+ 0x8013F120:("View_SetOrtho",),
+ 0x8013F15C:("View_GetOrtho",),
0x8013F17C:("View_SetViewport",),
0x8013F1B0:("View_GetViewport",),
- 0x8013F1D8:("View_WriteScissor",),
- 0x8013F28C:("View_SyncAndWriteScissor",),
- 0x8013F2F8:("View_SetScissorForLetterbox",),
- 0x8013F3F8:("View_SetDistortionDirRot",),
+ 0x8013F1D8:("View_SetScissor",),
+ 0x8013F28C:("View_ClearScissor",),
+ 0x8013F2F8:("View_ApplyLetterbox",),
+ 0x8013F3F8:("View_SetDistortionOrientation",),
0x8013F420:("View_SetDistortionScale",),
0x8013F448:("View_SetDistortionSpeed",),
0x8013F45C:("View_InitDistortion",),
0x8013F4C0:("View_ClearDistortion",),
0x8013F4F4:("View_SetDistortion",),
0x8013F54C:("View_StepDistortion",),
- 0x8013F6FC:("View_RenderView",),
- 0x8013F748:("View_RenderToPerspectiveMatrix",),
- 0x8013FA1C:("View_RenderToOrthographicMatrix",),
- 0x8013FBC8:("func_8013FBC8",),
- 0x8013FD74:("func_8013FD74",),
- 0x80140024:("func_80140024",),
- 0x801400CC:("func_801400CC",),
+ 0x8013F6FC:("View_Apply",),
+ 0x8013F748:("View_ApplyPerspective",),
+ 0x8013FA1C:("View_ApplyOrtho",),
+ 0x8013FBC8:("View_ApplyOrthoToOverlay",),
+ 0x8013FD74:("View_ApplyPerspectiveToOverlay",),
+ 0x80140024:("View_UpdateViewingMatrix",),
+ 0x801400CC:("View_ApplyTo",),
0x80140260:("func_80140260",),
0x8014026C:("func_8014026C",),
0x80140730:("func_80140730",),
@@ -2892,14 +2892,14 @@
0x80160B40:("PlayerCall_Destroy",),
0x80160B80:("PlayerCall_Update",),
0x80160BC0:("PlayerCall_Draw",),
- 0x80160C00:("ShrinkWindow_SetLetterboxTarget",),
- 0x80160C14:("ShrinkWindow_GetLetterboxTarget",),
- 0x80160C28:("ShrinkWindow_SetLetterboxMagnitude",),
- 0x80160C3C:("ShrinkWindow_GetLetterboxMagnitude",),
- 0x80160C50:("ShrinkWindow_SetPillarboxTarget",),
- 0x80160C64:("ShrinkWindow_GetPillarboxTarget",),
- 0x80160C78:("ShrinkWindow_SetPillarboxMagnitude",),
- 0x80160C8C:("ShrinkWindow_GetPillarboxMagnitude",),
+ 0x80160C00:("ShrinkWindow_Letterbox_SetSizeTarget",),
+ 0x80160C14:("ShrinkWindow_Letterbox_GetSizeTarget",),
+ 0x80160C28:("ShrinkWindow_Letterbox_SetSize",),
+ 0x80160C3C:("ShrinkWindow_Letterbox_GetSize",),
+ 0x80160C50:("ShrinkWindow_Pillarbox_SetSizeTarget",),
+ 0x80160C64:("ShrinkWindow_Pillarbox_GetSizeTarget",),
+ 0x80160C78:("ShrinkWindow_Pillarbox_SetSize",),
+ 0x80160C8C:("ShrinkWindow_Pillarbox_GetSize",),
0x80160CA0:("ShrinkWindow_Init",),
0x80160CD4:("ShrinkWindow_Destroy",),
0x80160CE4:("ShrinkWindow_Update",),
@@ -3478,74 +3478,74 @@
0x801872FC:("osFlashWriteBuffer",),
0x801873BC:("osFlashWriteArray",),
0x8018752C:("osFlashReadArray",),
- 0x801877D0:("func_801877D0",),
- 0x80187B64:("func_80187B64",),
- 0x80187BEC:("func_80187BEC",),
- 0x80187DE8:("func_80187DE8",),
- 0x80187E58:("func_80187E58",),
- 0x80187F00:("func_80187F00",),
- 0x80187FA8:("func_80187FA8",),
- 0x80187FB0:("func_80187FB0",),
- 0x80187FD0:("func_80187FD0",),
- 0x80187FD8:("func_80187FD8",),
- 0x80187FE0:("func_80187FE0",),
- 0x80187FE8:("func_80187FE8",),
- 0x8018801C:("func_8018801C",),
- 0x80188024:("func_80188024",),
- 0x8018802C:("func_8018802C",),
- 0x80188034:("func_80188034",),
- 0x80188068:("func_80188068",),
- 0x80188070:("func_80188070",),
- 0x80188078:("func_80188078",),
- 0x801880A4:("func_801880A4",),
- 0x801880AC:("func_801880AC",),
- 0x801880B4:("func_801880B4",),
- 0x801880BC:("func_801880BC",),
- 0x801880C4:("func_801880C4",),
- 0x801880E8:("func_801880E8",),
- 0x8018811C:("func_8018811C",),
- 0x80188124:("func_80188124",),
- 0x8018814C:("func_8018814C",),
- 0x80188174:("func_80188174",),
- 0x80188190:("func_80188190",),
- 0x80188198:("func_80188198",),
- 0x801881A0:("func_801881A0",),
- 0x801881A8:("func_801881A8",),
- 0x801881C4:("func_801881C4",),
- 0x801881F8:("func_801881F8",),
- 0x80188224:("func_80188224",),
- 0x8018822C:("func_8018822C",),
- 0x80188234:("func_80188234",),
- 0x8018823C:("func_8018823C",),
- 0x80188244:("func_80188244",),
- 0x8018824C:("func_8018824C",),
- 0x80188254:("func_80188254",),
- 0x8018825C:("func_8018825C",),
- 0x80188264:("func_80188264",),
- 0x80188288:("func_80188288",),
- 0x801882A0:("func_801882A0",),
- 0x80188304:("func_80188304",),
- 0x801884A0:("func_801884A0",),
- 0x80188698:("func_80188698",),
- 0x8018883C:("func_8018883C",),
- 0x801888E4:("func_801888E4",),
- 0x801889A4:("func_801889A4",),
- 0x80188A50:("func_80188A50",),
- 0x80188AFC:("func_80188AFC",),
- 0x80188C48:("func_80188C48",),
- 0x80188CB4:("func_80188CB4",),
- 0x80188D20:("func_80188D20",),
- 0x80188D28:("func_80188D28",),
- 0x80188D68:("func_80188D68",),
- 0x80188DDC:("func_80188DDC",),
- 0x80188FBC:("func_80188FBC",),
- 0x80189064:("func_80189064",),
- 0x80189620:("func_80189620",),
- 0x8018A4B4:("func_8018A4B4",),
- 0x8018A768:("func_8018A768",),
- 0x8018A808:("func_8018A808",),
- 0x8018ACC4:("func_8018ACC4",),
- 0x8018AE34:("func_8018AE34",),
+ 0x801877D0:("AudioSynth_AddReverbBufferEntry",),
+ 0x80187B64:("AudioSynth_SyncSampleStates",),
+ 0x80187BEC:("AudioSynth_Update",),
+ 0x80187DE8:("AudioSynth_DisableSampleStates",),
+ 0x80187E58:("AudioSynth_LoadMixedReverbSamples",),
+ 0x80187F00:("AudioSynth_SaveMixedReverbSamples",),
+ 0x80187FA8:("AudioSynth_Noop1",),
+ 0x80187FB0:("AudioSynth_ClearBuffer",),
+ 0x80187FD0:("AudioSynth_Noop2",),
+ 0x80187FD8:("AudioSynth_Noop3",),
+ 0x80187FE0:("AudioSynth_Noop4",),
+ 0x80187FE8:("AudioSynth_Mix",),
+ 0x8018801C:("AudioSynth_Noop5",),
+ 0x80188024:("AudioSynth_Noop6",),
+ 0x8018802C:("AudioSynth_Noop7",),
+ 0x80188034:("AudioSynth_SetBuffer",),
+ 0x80188068:("AudioSynth_Noop8",),
+ 0x80188070:("AudioSynth_Noop9",),
+ 0x80188078:("AudioSynth_DMemMove",),
+ 0x801880A4:("AudioSynth_Noop10",),
+ 0x801880AC:("AudioSynth_Noop11",),
+ 0x801880B4:("AudioSynth_Noop12",),
+ 0x801880BC:("AudioSynth_Noop13",),
+ 0x801880C4:("AudioSynth_InterL",),
+ 0x801880E8:("AudioSynth_EnvSetup1",),
+ 0x8018811C:("AudioSynth_Noop14",),
+ 0x80188124:("AudioSynth_LoadBuffer",),
+ 0x8018814C:("AudioSynth_SaveBuffer",),
+ 0x80188174:("AudioSynth_EnvSetup2",),
+ 0x80188190:("AudioSynth_Noop15",),
+ 0x80188198:("AudioSynth_Noop16",),
+ 0x801881A0:("AudioSynth_Noop17",),
+ 0x801881A8:("AudioSynth_S8Dec",),
+ 0x801881C4:("AudioSynth_HiLoGain",),
+ 0x801881F8:("AudioSynth_UnkCmd19",),
+ 0x80188224:("AudioSynth_Noop18",),
+ 0x8018822C:("AudioSynth_Noop19",),
+ 0x80188234:("AudioSynth_Noop20",),
+ 0x8018823C:("AudioSynth_Noop21",),
+ 0x80188244:("AudioSynth_Noop22",),
+ 0x8018824C:("AudioSynth_Noop23",),
+ 0x80188254:("AudioSynth_Noop24",),
+ 0x8018825C:("AudioSynth_Noop25",),
+ 0x80188264:("AudioSynth_LoadFilterBuffer",),
+ 0x80188288:("AudioSynth_LoadFilterSize",),
+ 0x801882A0:("AudioSynth_LeakReverb",),
+ 0x80188304:("AudioSynth_LoadDownsampledReverbSamples",),
+ 0x801884A0:("AudioSynth_SaveResampledReverbSamples",),
+ 0x80188698:("AudioSynth_LoadResampledReverbSamples",),
+ 0x8018883C:("AudioSynth_FilterReverb",),
+ 0x801888E4:("AudioSynth_MixOtherReverbIndex",),
+ 0x801889A4:("AudioSynth_LoadDefaultReverbSamples",),
+ 0x80188A50:("AudioSynth_LoadSubReverbSamples",),
+ 0x80188AFC:("AudioSynth_SaveResampledReverbSamplesImpl",),
+ 0x80188C48:("AudioSynth_LoadReverbSamplesImpl",),
+ 0x80188CB4:("AudioSynth_SaveReverbSamplesImpl",),
+ 0x80188D20:("AudioSynth_Noop26",),
+ 0x80188D28:("AudioSynth_LoadSubReverbSamplesWithoutDownsample",),
+ 0x80188D68:("AudioSynth_LoadReverbSamples",),
+ 0x80188DDC:("AudioSynth_SaveReverbSamples",),
+ 0x80188FBC:("AudioSynth_SaveSubReverbSamples",),
+ 0x80189064:("AudioSynth_ProcessSamples",),
+ 0x80189620:("AudioSynth_ProcessSample",),
+ 0x8018A4B4:("AudioSynth_ApplySurroundEffect",),
+ 0x8018A768:("AudioSynth_FinalResample",),
+ 0x8018A808:("AudioSynth_ProcessEnvelope",),
+ 0x8018ACC4:("AudioSynth_LoadWaveSamples",),
+ 0x8018AE34:("AudioSynth_ApplyHaasEffect",),
0x8018B0F0:("AudioHeap_CalculateAdsrDecay",),
0x8018B10C:("AudioHeap_InitAdsrDecayTable",),
0x8018B250:("AudioHeap_ResetLoadStatus",),
@@ -3726,7 +3726,7 @@
0x80194804:("func_80194804",),
0x80194840:("func_80194840",),
0x801948B0:("func_801948B0",),
- 0x80194930:("AudioPlayback_InitNoteSub",),
+ 0x80194930:("AudioPlayback_InitSampleState",),
0x80194DB0:("AudioPlayback_NoteSetResamplingRate",),
0x80194E60:("AudioPlayback_NoteInit",),
0x80194F20:("AudioPlayback_NoteDisable",),
@@ -5947,18 +5947,18 @@
0x808B5230:("EnMFire1_Init",),
0x808B5294:("EnMFire1_Destroy",),
0x808B52C0:("EnMFire1_Update",),
- 0x808B53C0:("func_808B53C0",),
+ 0x808B53C0:("EnMThunder_UnkType_Setup",),
0x808B545C:("EnMThunder_Init",),
0x808B5820:("EnMThunder_Destroy",),
- 0x808B5890:("func_808B5890",),
- 0x808B58CC:("func_808B58CC",),
- 0x808B5984:("func_808B5984",),
+ 0x808B5890:("EnMThunder_AdjustLights",),
+ 0x808B58CC:("EnMThunder_Spin_AttackNoMagic",),
+ 0x808B5984:("EnMThunder_Charge",),
0x808B5EEC:("func_808B5EEC",),
- 0x808B5F68:("func_808B5F68",),
- 0x808B60D4:("func_808B60D4",),
- 0x808B6310:("func_808B6310",),
+ 0x808B5F68:("EnMThunder_Spin_Attack",),
+ 0x808B60D4:("EnMThunder_SwordBeam_Attack",),
+ 0x808B6310:("EnMThunder_UnkType_Attack",),
0x808B63E8:("EnMThunder_Update",),
- 0x808B65BC:("func_808B65BC",),
+ 0x808B65BC:("EnMThunder_UnkType_Update",),
0x808B677C:("EnMThunder_Draw",),
0x808B7360:("BgBreakwall_SetupAction",),
0x808B736C:("func_808B736C",),
@@ -10441,31 +10441,31 @@
0x80A45164:("EnSekihi_Draw",),
0x80A45360:("EnWiz_Init",),
0x80A45568:("EnWiz_Destroy",),
- 0x80A455C4:("func_80A455C4",),
- 0x80A456A0:("func_80A456A0",),
- 0x80A45CD8:("func_80A45CD8",),
- 0x80A460A4:("func_80A460A4",),
- 0x80A46280:("func_80A46280",),
- 0x80A462F8:("func_80A462F8",),
- 0x80A46414:("func_80A46414",),
- 0x80A4668C:("func_80A4668C",),
- 0x80A46764:("func_80A46764",),
- 0x80A468CC:("func_80A468CC",),
- 0x80A46990:("func_80A46990",),
- 0x80A46C88:("func_80A46C88",),
- 0x80A46CC4:("func_80A46CC4",),
- 0x80A46DDC:("func_80A46DDC",),
- 0x80A46E24:("func_80A46E24",),
- 0x80A47000:("func_80A47000",),
- 0x80A470D8:("func_80A470D8",),
- 0x80A47298:("func_80A47298",),
- 0x80A473B8:("func_80A473B8",),
- 0x80A4767C:("func_80A4767C",),
- 0x80A476C8:("func_80A476C8",),
- 0x80A477E8:("func_80A477E8",),
+ 0x80A455C4:("EnWiz_ChangeAnim",),
+ 0x80A456A0:("EnWiz_HandleIntroCutscene",),
+ 0x80A45CD8:("EnWiz_SelectPlatform",),
+ 0x80A460A4:("EnWiz_MoveGhosts",),
+ 0x80A46280:("EnWiz_StartIntroCutscene",),
+ 0x80A462F8:("EnWiz_SetupAppear",),
+ 0x80A46414:("EnWiz_Appear",),
+ 0x80A4668C:("EnWiz_SetupDance",),
+ 0x80A46764:("EnWiz_Dance",),
+ 0x80A468CC:("EnWiz_SetupSecondPhaseCutscene",),
+ 0x80A46990:("EnWiz_SecondPhaseCutscene",),
+ 0x80A46C88:("EnWiz_SetupWindUp",),
+ 0x80A46CC4:("EnWiz_WindUp",),
+ 0x80A46DDC:("EnWiz_SetupAttack",),
+ 0x80A46E24:("EnWiz_Attack",),
+ 0x80A47000:("EnWiz_SetupDisappear",),
+ 0x80A470D8:("EnWiz_Disappear",),
+ 0x80A47298:("EnWiz_SetupDamaged",),
+ 0x80A473B8:("EnWiz_Damaged",),
+ 0x80A4767C:("EnWiz_SetupDead",),
+ 0x80A476C8:("EnWiz_Dead",),
+ 0x80A477E8:("EnWiz_UpdateDamage",),
0x80A47C6C:("EnWiz_Update",),
- 0x80A47FCC:("func_80A47FCC",),
- 0x80A48138:("func_80A48138",),
+ 0x80A47FCC:("EnWiz_PostLimbDrawOpa",),
+ 0x80A48138:("EnWiz_PostLimbDrawXlu",),
0x80A483B4:("EnWiz_Draw",),
0x80A48FE0:("EnWizBrock_Init",),
0x80A490B0:("EnWizBrock_Destroy",),
@@ -10475,20 +10475,20 @@
0x80A49308:("EnWizBrock_Draw",),
0x80A496A0:("EnWizFire_Init",),
0x80A497D4:("EnWizFire_Destroy",),
- 0x80A4984C:("func_80A4984C",),
- 0x80A49A44:("func_80A49A44",),
- 0x80A49F38:("func_80A49F38",),
- 0x80A49FD8:("func_80A49FD8",),
- 0x80A4A11C:("func_80A4A11C",),
- 0x80A4A608:("func_80A4A608",),
+ 0x80A4984C:("EnWiz_SetupMoveMagicProjectile",),
+ 0x80A49A44:("EnWiz_MoveMagicProjectile",),
+ 0x80A49F38:("EnWiz_SetupSmallFlame",),
+ 0x80A49FD8:("EnWiz_SmallFlame",),
+ 0x80A4A11C:("EnWiz_Pool",),
+ 0x80A4A608:("EnWiz_KillMagicProjectile",),
0x80A4A698:("EnWizFire_Update",),
- 0x80A4B0C8:("func_80A4B0C8",),
- 0x80A4B33C:("func_80A4B33C",),
+ 0x80A4B0C8:("EnWizFire_DrawIcePool",),
+ 0x80A4B33C:("EnWizFire_DrawFirePoolAndFlame",),
0x80A4B804:("EnWizFire_Draw",),
- 0x80A4BAB4:("func_80A4BAB4",),
- 0x80A4BC74:("func_80A4BC74",),
- 0x80A4BDDC:("func_80A4BDDC",),
- 0x80A4BF78:("func_80A4BF78",),
+ 0x80A4BAB4:("EnWizFire_DrawSmallFlame",),
+ 0x80A4BC74:("EnWizFire_InitializeEffect",),
+ 0x80A4BDDC:("EnWizFire_UpdateEffects",),
+ 0x80A4BF78:("EnWizFire_DrawEffects",),
0x80A4C490:("EffChange_Init",),
0x80A4C54C:("EffChange_Destroy",),
0x80A4C578:("EffChange_SetColors",),
@@ -11226,8 +11226,8 @@
0x80A86460:("func_80A86460",),
0x80A86674:("func_80A86674",),
0x80A86770:("func_80A86770",),
- 0x80A868F8:("func_80A868F8",),
- 0x80A86924:("func_80A86924",),
+ 0x80A868F8:("EnTru_UpdateSkelAnime",),
+ 0x80A86924:("EnTru_ChangeAnim",),
0x80A8697C:("func_80A8697C",),
0x80A869DC:("func_80A869DC",),
0x80A86B0C:("func_80A86B0C",),
@@ -11902,14 +11902,14 @@
0x80AC1D14:("EnPoFusen_Draw",),
0x80AC1ED0:("EnDoorEtc_Init",),
0x80AC2018:("EnDoorEtc_Destroy",),
- 0x80AC2044:("func_80AC2044",),
- 0x80AC20A8:("func_80AC20A8",),
+ 0x80AC2044:("EnDoorEtc_IsDistanceGreater",),
+ 0x80AC20A8:("EnDoorEtc_WaitForObject",),
0x80AC2118:("func_80AC2118",),
0x80AC2154:("func_80AC2154",),
0x80AC21A0:("func_80AC21A0",),
0x80AC2354:("func_80AC2354",),
0x80AC2430:("EnDoorEtc_Update",),
- 0x80AC24A8:("func_80AC24A8",),
+ 0x80AC24A8:("EnDoorEtc_Draw",),
0x80AC26F0:("EnBigokuta_Init",),
0x80AC2874:("EnBigokuta_Destroy",),
0x80AC28B4:("EnBigokuta_SetupCutsceneCamera",),
@@ -14437,7 +14437,7 @@
0x80B75658:("EnJg_OverrideLimbDraw",),
0x80B75708:("EnJg_PostLimbDraw",),
0x80B757AC:("EnJg_Draw",),
- 0x80B76030:("func_80B76030",),
+ 0x80B76030:("EnTruMt_ChangeAnim",),
0x80B76110:("func_80B76110",),
0x80B76188:("func_80B76188",),
0x80B761FC:("func_80B761FC",),
diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt
index adc4a9c08..c48de3cc9 100644
--- a/tools/disasm/variables.txt
+++ b/tools/disasm/variables.txt
@@ -2220,11 +2220,11 @@
0x801D57B4:("gDefaultShortNoteVelocityTable","UNK_TYPE1","",0x1),
0x801D57C4:("gDefaultShortNoteGateTimeTable","UNK_TYPE1","",0x1),
0x801D57D4:("gDefaultEnvelope","UNK_TYPE1","",0x1),
- 0x801D57E4:("gZeroNoteSub","UNK_TYPE4","",0x4),
- 0x801D5804:("gDefaultNoteSub","UNK_TYPE4","",0x4),
- 0x801D5824:("gHeadsetPanQuantization","u16","[64]",0x80),
+ 0x801D57E4:("gZeroedSampleState","UNK_TYPE4","",0x4),
+ 0x801D5804:("gDefaultSampleState","UNK_TYPE4","",0x4),
+ 0x801D5824:("gHaasEffectDelaySize","u16","[64]",0x80),
0x801D58A4:("D_801D58A4","s32","",0x4),
- 0x801D58A8:("D_801D58A8","s16","[64]",0x80),
+ 0x801D58A8:("gInvalidAdpcmCodeBook","s16","[64]",0x80),
0x801D5928:("gHeadsetPanVolume","f32","[128]",0x200),
0x801D5B28:("gStereoPanVolume","f32","[128]",0x200),
0x801D5D28:("gDefaultPanVolume","f32","[128]",0x200),
@@ -2411,7 +2411,7 @@
0x801DB870:("D_801DB870","UNK_TYPE1","",0x1),
0x801DB8B8:("D_801DB8B8","UNK_TYPE1","",0x1),
0x801DB900:("D_801DB900","UNK_TYPE1","",0x1),
- 0x801DB930:("D_801DB930","UNK_PTR","",0x4),
+ 0x801DB930:("gReverbSettingsTable","UNK_PTR","",0x4),
0x801DB958:("gAudioSpecs","AudioSpec","[21]",0x498),
0x801DBDF0:("D_801DBDF0","f32","",0x4),
0x801DBDF4:("jtbl_801DBDF4","UNK_PTR","",0x4),
@@ -4046,8 +4046,8 @@
0x801F6B34:("sPlayerCallDestroyFunc","UNK_TYPE1","",0x1),
0x801F6B38:("sPlayerCallUpdateFunc","UNK_TYPE1","",0x1),
0x801F6B3C:("sPlayerCallDrawFunc","UNK_TYPE1","",0x1),
- 0x801F6B40:("gShrinkWindowContext","ShrinkWindowContext","",0x4),
- 0x801F6B44:("gShrinkWindowContextPtr","ShrinkWindowContext*","",0x4),
+ 0x801F6B40:("sShrinkWindow","ShrinkWindow","",0x4),
+ 0x801F6B44:("sShrinkWindowPtr","ShrinkWindow*","",0x4),
0x801F6B50:("D_801F6B50","UNK_TYPE4","",0x4),
0x801F6B58:("D_801F6B58","UNK_TYPE1","",0x1),
0x801F6BF0:("sKaleidoAreaFaultClient","FaultAddrConvClient","",0xC),
@@ -4354,10 +4354,10 @@
0x80200BCE:("D_80200BCE","UNK_TYPE1","",0x1),
0x80200BD0:("D_80200BD0","UNK_TYPE1","",0x1),
0x80200C70:("gAudioContext","AudioContext","",0x81F8),
- 0x80208E68:("D_80208E68","UNK_TYPE4","",0x4),
- 0x80208E6C:("D_80208E6C","UNK_TYPE4","",0x4),
- 0x80208E70:("D_80208E70","UNK_TYPE4","",0x4),
- 0x80208E74:("D_80208E74","UNK_TYPE4","",0x4),
+ 0x80208E68:("gCustomAudioUpdateFunction","UNK_TYPE4","",0x4),
+ 0x80208E6C:("gCustomAudioSeqFunction","UNK_TYPE4","",0x4),
+ 0x80208E70:("gCustomAudioReverbFunction","UNK_TYPE4","",0x4),
+ 0x80208E74:("gCustomAudioSynthFunction","UNK_TYPE4","",0x4),
0x80208E90:("sJpegBitStreamPtr","UNK_TYPE1","",0x1),
0x80208E94:("sJpegBitStreamByteIdx","UNK_TYPE1","",0x1),
0x80208E98:("sJpegBitStreamBitIdx","UNK_TYPE1","",0x1),
@@ -11517,18 +11517,18 @@
0x80A452A4:("D_80A452A4","UNK_TYPE1","",0x1),
0x80A452B0:("D_80A452B0","UNK_TYPE4","",0x4),
0x80A48B30:("En_Wiz_InitVars","UNK_TYPE1","",0x1),
- 0x80A48B50:("D_80A48B50","UNK_TYPE1","",0x1),
- 0x80A48CB8:("D_80A48CB8","UNK_PTR","",0x4),
- 0x80A48CC8:("D_80A48CC8","UNK_TYPE1","",0x1),
- 0x80A48CF4:("D_80A48CF4","UNK_TYPE1","",0x1),
- 0x80A48D14:("D_80A48D14","UNK_TYPE1","",0x1),
- 0x80A48D34:("D_80A48D34","UNK_TYPE1","",0x1),
- 0x80A48D4C:("D_80A48D4C","UNK_TYPE1","",0x1),
- 0x80A48D54:("D_80A48D54","UNK_TYPE4","",0x4),
- 0x80A48D60:("D_80A48D60","UNK_TYPE1","",0x1),
- 0x80A48D64:("D_80A48D64","UNK_TYPE1","",0x1),
- 0x80A48D68:("D_80A48D68","UNK_TYPE4","",0x4),
- 0x80A48D74:("D_80A48D74","UNK_TYPE4","",0x4),
+ 0x80A48B50:("sJntSphElementsInit","UNK_TYPE1","",0x1),
+ 0x80A48CB8:("sJntSphInit","UNK_PTR","",0x4),
+ 0x80A48CC8:("sCylinderInit","UNK_TYPE1","",0x1),
+ 0x80A48CF4:("sFireWizrobeDamageTable","UNK_TYPE1","",0x1),
+ 0x80A48D14:("sIceWizrobeDamageTable","UNK_TYPE1","",0x1),
+ 0x80A48D34:("sAnimations","UNK_TYPE1","",0x1),
+ 0x80A48D4C:("sAnimationModes","UNK_TYPE1","",0x1),
+ 0x80A48D54:("staffTargetFlameScale","UNK_TYPE4","",0x4),
+ 0x80A48D60:("sDustPrimColor","UNK_TYPE1","",0x1),
+ 0x80A48D64:("sDustEnvTimer","UNK_TYPE1","",0x1),
+ 0x80A48D68:("staffFlamePos","UNK_TYPE4","",0x4),
+ 0x80A48D74:("staffFlamePos","UNK_TYPE4","",0x4),
0x80A48D80:("jtbl_80A48D80","UNK_PTR","",0x4),
0x80A48D98:("D_80A48D98","f32","",0x4),
0x80A48D9C:("D_80A48D9C","f32","",0x4),
@@ -11556,15 +11556,15 @@
0x80A495F8:("D_80A495F8","f32","",0x4),
0x80A495FC:("D_80A495FC","f32","",0x4),
0x80A49600:("D_80A49600","f32","",0x4),
- 0x80A4C1C0:("D_80A4C1C0","UNK_TYPE4","",0x4),
+ 0x80A4C1C0:("sPoolHitByIceArrow","UNK_TYPE4","",0x4),
0x80A4C1C4:("En_Wiz_Fire_InitVars","UNK_TYPE1","",0x1),
0x80A4C1E4:("D_80A4C1E4","UNK_TYPE1","",0x1),
0x80A4C210:("D_80A4C210","UNK_TYPE4","",0x4),
0x80A4C21C:("D_80A4C21C","UNK_TYPE4","",0x4),
0x80A4C228:("D_80A4C228","UNK_TYPE4","",0x4),
- 0x80A4C234:("D_80A4C234","UNK_TYPE1","",0x1),
- 0x80A4C24C:("D_80A4C24C","UNK_TYPE1","",0x1),
- 0x80A4C250:("D_80A4C250","UNK_TYPE1","",0x1),
+ 0x80A4C234:("lightSettingsColors","UNK_TYPE1","",0x1),
+ 0x80A4C24C:("sSteamPrimColor","UNK_TYPE1","",0x1),
+ 0x80A4C250:("sSteamEnvColor","UNK_TYPE1","",0x1),
0x80A4C260:("jtbl_80A4C260","UNK_PTR","",0x4),
0x80A4C274:("D_80A4C274","f32","",0x4),
0x80A4C278:("D_80A4C278","f32","",0x4),
@@ -12869,9 +12869,9 @@
0x80AC1E00:("D_80AC1E00","f32","",0x4),
0x80AC1E04:("D_80AC1E04","f32","",0x4),
0x80AC2580:("En_Door_Etc_InitVars","UNK_TYPE1","",0x1),
- 0x80AC25A0:("D_80AC25A0","UNK_TYPE1","",0x1),
- 0x80AC25CC:("D_80AC25CC","UNK_TYPE2","",0x2),
- 0x80AC2634:("D_80AC2634","UNK_TYPE1","",0x1),
+ 0x80AC25A0:("sCylinderInit","UNK_TYPE1","",0x1),
+ 0x80AC25CC:("sObjInfo","UNK_TYPE2","",0x2),
+ 0x80AC2634:("sInitChain","UNK_TYPE1","",0x1),
0x80AC2650:("D_80AC2650","f32","",0x4),
0x80AC4510:("En_Bigokuta_InitVars","UNK_TYPE1","",0x1),
0x80AC4530:("D_80AC4530","UNK_TYPE1","",0x1),
diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv
index be788a794..b807a0e24 100644
--- a/tools/sizes/code_functions.csv
+++ b/tools/sizes/code_functions.csv
@@ -2235,33 +2235,33 @@ asm/non_matchings/code/code_8013EC10/Rumble_StateWipeRequests.s,Rumble_StateWipe
asm/non_matchings/code/code_8013EC10/Rumble_SetUpdateEnabled.s,Rumble_SetUpdateEnabled,0x8013EE48,0x6
asm/non_matchings/code/z_view/View_ViewportToVp.s,View_ViewportToVp,0x8013EE60,0x25
asm/non_matchings/code/z_view/View_Init.s,View_Init,0x8013EEF4,0x2A
-asm/non_matchings/code/z_view/View_SetViewOrientation.s,View_SetViewOrientation,0x8013EF9C,0x2D
-asm/non_matchings/code/z_view/func_8013F050.s,func_8013F050,0x8013F050,0x14
+asm/non_matchings/code/z_view/View_LookAt.s,View_LookAt,0x8013EF9C,0x2D
+asm/non_matchings/code/z_view/View_LookAtUnsafe.s,View_LookAtUnsafe,0x8013F050,0x14
asm/non_matchings/code/z_view/View_SetScale.s,View_SetScale,0x8013F0A0,0x8
asm/non_matchings/code/z_view/View_GetScale.s,View_GetScale,0x8013F0C0,0x4
-asm/non_matchings/code/z_view/func_8013F0D0.s,func_8013F0D0,0x8013F0D0,0xC
-asm/non_matchings/code/z_view/func_8013F100.s,func_8013F100,0x8013F100,0x8
-asm/non_matchings/code/z_view/func_8013F120.s,func_8013F120,0x8013F120,0xF
-asm/non_matchings/code/z_view/func_8013F15C.s,func_8013F15C,0x8013F15C,0x8
+asm/non_matchings/code/z_view/View_SetPerspective.s,View_SetPerspective,0x8013F0D0,0xC
+asm/non_matchings/code/z_view/View_GetPerspective.s,View_GetPerspective,0x8013F100,0x8
+asm/non_matchings/code/z_view/View_SetOrtho.s,View_SetOrtho,0x8013F120,0xF
+asm/non_matchings/code/z_view/View_GetOrtho.s,View_GetOrtho,0x8013F15C,0x8
asm/non_matchings/code/z_view/View_SetViewport.s,View_SetViewport,0x8013F17C,0xD
asm/non_matchings/code/z_view/View_GetViewport.s,View_GetViewport,0x8013F1B0,0xA
-asm/non_matchings/code/z_view/View_WriteScissor.s,View_WriteScissor,0x8013F1D8,0x2D
-asm/non_matchings/code/z_view/View_SyncAndWriteScissor.s,View_SyncAndWriteScissor,0x8013F28C,0x1B
-asm/non_matchings/code/z_view/View_SetScissorForLetterbox.s,View_SetScissorForLetterbox,0x8013F2F8,0x40
-asm/non_matchings/code/z_view/View_SetDistortionDirRot.s,View_SetDistortionDirRot,0x8013F3F8,0xA
+asm/non_matchings/code/z_view/View_SetScissor.s,View_SetScissor,0x8013F1D8,0x2D
+asm/non_matchings/code/z_view/View_ClearScissor.s,View_ClearScissor,0x8013F28C,0x1B
+asm/non_matchings/code/z_view/View_ApplyLetterbox.s,View_ApplyLetterbox,0x8013F2F8,0x40
+asm/non_matchings/code/z_view/View_SetDistortionOrientation.s,View_SetDistortionOrientation,0x8013F3F8,0xA
asm/non_matchings/code/z_view/View_SetDistortionScale.s,View_SetDistortionScale,0x8013F420,0xA
asm/non_matchings/code/z_view/View_SetDistortionSpeed.s,View_SetDistortionSpeed,0x8013F448,0x5
asm/non_matchings/code/z_view/View_InitDistortion.s,View_InitDistortion,0x8013F45C,0x19
asm/non_matchings/code/z_view/View_ClearDistortion.s,View_ClearDistortion,0x8013F4C0,0xD
asm/non_matchings/code/z_view/View_SetDistortion.s,View_SetDistortion,0x8013F4F4,0x16
asm/non_matchings/code/z_view/View_StepDistortion.s,View_StepDistortion,0x8013F54C,0x6C
-asm/non_matchings/code/z_view/View_RenderView.s,View_RenderView,0x8013F6FC,0x13
-asm/non_matchings/code/z_view/View_RenderToPerspectiveMatrix.s,View_RenderToPerspectiveMatrix,0x8013F748,0xB5
-asm/non_matchings/code/z_view/View_RenderToOrthographicMatrix.s,View_RenderToOrthographicMatrix,0x8013FA1C,0x6B
-asm/non_matchings/code/z_view/func_8013FBC8.s,func_8013FBC8,0x8013FBC8,0x6B
-asm/non_matchings/code/z_view/func_8013FD74.s,func_8013FD74,0x8013FD74,0xAC
-asm/non_matchings/code/z_view/func_80140024.s,func_80140024,0x80140024,0x2A
-asm/non_matchings/code/z_view/func_801400CC.s,func_801400CC,0x801400CC,0x65
+asm/non_matchings/code/z_view/View_Apply.s,View_Apply,0x8013F6FC,0x13
+asm/non_matchings/code/z_view/View_ApplyPerspective.s,View_ApplyPerspective,0x8013F748,0xB5
+asm/non_matchings/code/z_view/View_ApplyOrtho.s,View_ApplyOrtho,0x8013FA1C,0x6B
+asm/non_matchings/code/z_view/View_ApplyOrthoToOverlay.s,View_ApplyOrthoToOverlay,0x8013FBC8,0x6B
+asm/non_matchings/code/z_view/View_ApplyPerspectiveToOverlay.s,View_ApplyPerspectiveToOverlay,0x8013FD74,0xAC
+asm/non_matchings/code/z_view/View_UpdateViewingMatrix.s,View_UpdateViewingMatrix,0x80140024,0x2A
+asm/non_matchings/code/z_view/View_ApplyTo.s,View_ApplyTo,0x801400CC,0x65
asm/non_matchings/code/z_vimode/func_80140260.s,func_80140260,0x80140260,0x3
asm/non_matchings/code/z_vimode/func_8014026C.s,func_8014026C,0x8014026C,0x131
asm/non_matchings/code/z_vimode/func_80140730.s,func_80140730,0x80140730,0x38
@@ -2406,14 +2406,14 @@ asm/non_matchings/code/z_player_call/PlayerCall_Init.s,PlayerCall_Init,0x80160AF
asm/non_matchings/code/z_player_call/PlayerCall_Destroy.s,PlayerCall_Destroy,0x80160B40,0x10
asm/non_matchings/code/z_player_call/PlayerCall_Update.s,PlayerCall_Update,0x80160B80,0x10
asm/non_matchings/code/z_player_call/PlayerCall_Draw.s,PlayerCall_Draw,0x80160BC0,0x10
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetLetterboxTarget.s,ShrinkWindow_SetLetterboxTarget,0x80160C00,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetLetterboxTarget.s,ShrinkWindow_GetLetterboxTarget,0x80160C14,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetLetterboxMagnitude.s,ShrinkWindow_SetLetterboxMagnitude,0x80160C28,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetLetterboxMagnitude.s,ShrinkWindow_GetLetterboxMagnitude,0x80160C3C,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetPillarboxTarget.s,ShrinkWindow_SetPillarboxTarget,0x80160C50,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetPillarboxTarget.s,ShrinkWindow_GetPillarboxTarget,0x80160C64,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_SetPillarboxMagnitude.s,ShrinkWindow_SetPillarboxMagnitude,0x80160C78,0x5
-asm/non_matchings/code/z_shrink_window/ShrinkWindow_GetPillarboxMagnitude.s,ShrinkWindow_GetPillarboxMagnitude,0x80160C8C,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_SetSizeTarget.s,ShrinkWindow_Letterbox_SetSizeTarget,0x80160C00,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_GetSizeTarget.s,ShrinkWindow_Letterbox_GetSizeTarget,0x80160C14,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_SetSize.s,ShrinkWindow_Letterbox_SetSize,0x80160C28,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Letterbox_GetSize.s,ShrinkWindow_Letterbox_GetSize,0x80160C3C,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_SetSizeTarget.s,ShrinkWindow_Pillarbox_SetSizeTarget,0x80160C50,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_GetSizeTarget.s,ShrinkWindow_Pillarbox_GetSizeTarget,0x80160C64,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_SetSize.s,ShrinkWindow_Pillarbox_SetSize,0x80160C78,0x5
+asm/non_matchings/code/z_shrink_window/ShrinkWindow_Pillarbox_GetSize.s,ShrinkWindow_Pillarbox_GetSize,0x80160C8C,0x5
asm/non_matchings/code/z_shrink_window/ShrinkWindow_Init.s,ShrinkWindow_Init,0x80160CA0,0xD
asm/non_matchings/code/z_shrink_window/ShrinkWindow_Destroy.s,ShrinkWindow_Destroy,0x80160CD4,0x4
asm/non_matchings/code/z_shrink_window/ShrinkWindow_Update.s,ShrinkWindow_Update,0x80160CE4,0x2D
@@ -2996,74 +2996,74 @@ asm/non_matchings/code/osFlash/func_80187284.s,func_80187284,0x80187284,0x1E
asm/non_matchings/code/osFlash/func_801872FC.s,func_801872FC,0x801872FC,0x30
asm/non_matchings/code/osFlash/func_801873BC.s,func_801873BC,0x801873BC,0x5C
asm/non_matchings/code/osFlash/func_8018752C.s,func_8018752C,0x8018752C,0x9D
-asm/non_matchings/code/audio_synthesis/func_801877D0.s,func_801877D0,0x801877D0,0xE5
-asm/non_matchings/code/audio_synthesis/func_80187B64.s,func_80187B64,0x80187B64,0x22
-asm/non_matchings/code/audio_synthesis/func_80187BEC.s,func_80187BEC,0x80187BEC,0x7F
-asm/non_matchings/code/audio_synthesis/func_80187DE8.s,func_80187DE8,0x80187DE8,0x1C
-asm/non_matchings/code/audio_synthesis/func_80187E58.s,func_80187E58,0x80187E58,0x2A
-asm/non_matchings/code/audio_synthesis/func_80187F00.s,func_80187F00,0x80187F00,0x2A
-asm/non_matchings/code/audio_synthesis/func_80187FA8.s,func_80187FA8,0x80187FA8,0x2
-asm/non_matchings/code/audio_synthesis/func_80187FB0.s,func_80187FB0,0x80187FB0,0x8
-asm/non_matchings/code/audio_synthesis/func_80187FD0.s,func_80187FD0,0x80187FD0,0x2
-asm/non_matchings/code/audio_synthesis/func_80187FD8.s,func_80187FD8,0x80187FD8,0x2
-asm/non_matchings/code/audio_synthesis/func_80187FE0.s,func_80187FE0,0x80187FE0,0x2
-asm/non_matchings/code/audio_synthesis/func_80187FE8.s,func_80187FE8,0x80187FE8,0xD
-asm/non_matchings/code/audio_synthesis/func_8018801C.s,func_8018801C,0x8018801C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188024.s,func_80188024,0x80188024,0x2
-asm/non_matchings/code/audio_synthesis/func_8018802C.s,func_8018802C,0x8018802C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188034.s,func_80188034,0x80188034,0xD
-asm/non_matchings/code/audio_synthesis/func_80188068.s,func_80188068,0x80188068,0x2
-asm/non_matchings/code/audio_synthesis/func_80188070.s,func_80188070,0x80188070,0x2
-asm/non_matchings/code/audio_synthesis/func_80188078.s,func_80188078,0x80188078,0xB
-asm/non_matchings/code/audio_synthesis/func_801880A4.s,func_801880A4,0x801880A4,0x2
-asm/non_matchings/code/audio_synthesis/func_801880AC.s,func_801880AC,0x801880AC,0x2
-asm/non_matchings/code/audio_synthesis/func_801880B4.s,func_801880B4,0x801880B4,0x2
-asm/non_matchings/code/audio_synthesis/func_801880BC.s,func_801880BC,0x801880BC,0x2
-asm/non_matchings/code/audio_synthesis/func_801880C4.s,func_801880C4,0x801880C4,0x9
-asm/non_matchings/code/audio_synthesis/func_801880E8.s,func_801880E8,0x801880E8,0xD
-asm/non_matchings/code/audio_synthesis/func_8018811C.s,func_8018811C,0x8018811C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188124.s,func_80188124,0x80188124,0xA
-asm/non_matchings/code/audio_synthesis/func_8018814C.s,func_8018814C,0x8018814C,0xA
-asm/non_matchings/code/audio_synthesis/func_80188174.s,func_80188174,0x80188174,0x7
-asm/non_matchings/code/audio_synthesis/func_80188190.s,func_80188190,0x80188190,0x2
-asm/non_matchings/code/audio_synthesis/func_80188198.s,func_80188198,0x80188198,0x2
-asm/non_matchings/code/audio_synthesis/func_801881A0.s,func_801881A0,0x801881A0,0x2
-asm/non_matchings/code/audio_synthesis/func_801881A8.s,func_801881A8,0x801881A8,0x7
-asm/non_matchings/code/audio_synthesis/func_801881C4.s,func_801881C4,0x801881C4,0xD
-asm/non_matchings/code/audio_synthesis/func_801881F8.s,func_801881F8,0x801881F8,0xB
-asm/non_matchings/code/audio_synthesis/func_80188224.s,func_80188224,0x80188224,0x2
-asm/non_matchings/code/audio_synthesis/func_8018822C.s,func_8018822C,0x8018822C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188234.s,func_80188234,0x80188234,0x2
-asm/non_matchings/code/audio_synthesis/func_8018823C.s,func_8018823C,0x8018823C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188244.s,func_80188244,0x80188244,0x2
-asm/non_matchings/code/audio_synthesis/func_8018824C.s,func_8018824C,0x8018824C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188254.s,func_80188254,0x80188254,0x2
-asm/non_matchings/code/audio_synthesis/func_8018825C.s,func_8018825C,0x8018825C,0x2
-asm/non_matchings/code/audio_synthesis/func_80188264.s,func_80188264,0x80188264,0x9
-asm/non_matchings/code/audio_synthesis/func_80188288.s,func_80188288,0x80188288,0x6
-asm/non_matchings/code/audio_synthesis/func_801882A0.s,func_801882A0,0x801882A0,0x19
-asm/non_matchings/code/audio_synthesis/func_80188304.s,func_80188304,0x80188304,0x67
-asm/non_matchings/code/audio_synthesis/func_801884A0.s,func_801884A0,0x801884A0,0x7E
-asm/non_matchings/code/audio_synthesis/func_80188698.s,func_80188698,0x80188698,0x69
-asm/non_matchings/code/audio_synthesis/func_8018883C.s,func_8018883C,0x8018883C,0x2A
-asm/non_matchings/code/audio_synthesis/func_801888E4.s,func_801888E4,0x801888E4,0x30
-asm/non_matchings/code/audio_synthesis/func_801889A4.s,func_801889A4,0x801889A4,0x2B
-asm/non_matchings/code/audio_synthesis/func_80188A50.s,func_80188A50,0x80188A50,0x2B
-asm/non_matchings/code/audio_synthesis/func_80188AFC.s,func_80188AFC,0x80188AFC,0x53
-asm/non_matchings/code/audio_synthesis/func_80188C48.s,func_80188C48,0x80188C48,0x1B
-asm/non_matchings/code/audio_synthesis/func_80188CB4.s,func_80188CB4,0x80188CB4,0x1B
-asm/non_matchings/code/audio_synthesis/func_80188D20.s,func_80188D20,0x80188D20,0x2
-asm/non_matchings/code/audio_synthesis/func_80188D28.s,func_80188D28,0x80188D28,0x10
-asm/non_matchings/code/audio_synthesis/func_80188D68.s,func_80188D68,0x80188D68,0x1D
-asm/non_matchings/code/audio_synthesis/func_80188DDC.s,func_80188DDC,0x80188DDC,0x78
-asm/non_matchings/code/audio_synthesis/func_80188FBC.s,func_80188FBC,0x80188FBC,0x2A
-asm/non_matchings/code/audio_synthesis/func_80189064.s,func_80189064,0x80189064,0x16F
-asm/non_matchings/code/audio_synthesis/func_80189620.s,func_80189620,0x80189620,0x3A5
-asm/non_matchings/code/audio_synthesis/func_8018A4B4.s,func_8018A4B4,0x8018A4B4,0xAD
-asm/non_matchings/code/audio_synthesis/func_8018A768.s,func_8018A768,0x8018A768,0x28
-asm/non_matchings/code/audio_synthesis/func_8018A808.s,func_8018A808,0x8018A808,0x12F
-asm/non_matchings/code/audio_synthesis/func_8018ACC4.s,func_8018ACC4,0x8018ACC4,0x5C
-asm/non_matchings/code/audio_synthesis/func_8018AE34.s,func_8018AE34,0x8018AE34,0xAF
+asm/non_matchings/code/audio_synthesis/AudioSynth_AddReverbBufferEntry.s,AudioSynth_AddReverbBufferEntry,0x801877D0,0xE5
+asm/non_matchings/code/audio_synthesis/AudioSynth_SyncSampleStates.s,AudioSynth_SyncSampleStates,0x80187B64,0x22
+asm/non_matchings/code/audio_synthesis/AudioSynth_Update.s,AudioSynth_Update,0x80187BEC,0x7F
+asm/non_matchings/code/audio_synthesis/AudioSynth_DisableSampleStates.s,AudioSynth_DisableSampleStates,0x80187DE8,0x1C
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadMixedReverbSamples.s,AudioSynth_LoadMixedReverbSamples,0x80187E58,0x2A
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveMixedReverbSamples.s,AudioSynth_SaveMixedReverbSamples,0x80187F00,0x2A
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop1.s,AudioSynth_Noop1,0x80187FA8,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_ClearBuffer.s,AudioSynth_ClearBuffer,0x80187FB0,0x8
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop2.s,AudioSynth_Noop2,0x80187FD0,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop3.s,AudioSynth_Noop3,0x80187FD8,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop4.s,AudioSynth_Noop4,0x80187FE0,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Mix.s,AudioSynth_Mix,0x80187FE8,0xD
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop5.s,AudioSynth_Noop5,0x8018801C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop6.s,AudioSynth_Noop6,0x80188024,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop7.s,AudioSynth_Noop7,0x8018802C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_SetBuffer.s,AudioSynth_SetBuffer,0x80188034,0xD
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop8.s,AudioSynth_Noop8,0x80188068,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop9.s,AudioSynth_Noop9,0x80188070,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_DMemMove.s,AudioSynth_DMemMove,0x80188078,0xB
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop10.s,AudioSynth_Noop10,0x801880A4,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop11.s,AudioSynth_Noop11,0x801880AC,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop12.s,AudioSynth_Noop12,0x801880B4,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop13.s,AudioSynth_Noop13,0x801880BC,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_InterL.s,AudioSynth_InterL,0x801880C4,0x9
+asm/non_matchings/code/audio_synthesis/AudioSynth_EnvSetup1.s,AudioSynth_EnvSetup1,0x801880E8,0xD
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop14.s,AudioSynth_Noop14,0x8018811C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadBuffer.s,AudioSynth_LoadBuffer,0x80188124,0xA
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveBuffer.s,AudioSynth_SaveBuffer,0x8018814C,0xA
+asm/non_matchings/code/audio_synthesis/AudioSynth_EnvSetup2.s,AudioSynth_EnvSetup2,0x80188174,0x7
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop15.s,AudioSynth_Noop15,0x80188190,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop16.s,AudioSynth_Noop16,0x80188198,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop17.s,AudioSynth_Noop17,0x801881A0,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_S8Dec.s,AudioSynth_S8Dec,0x801881A8,0x7
+asm/non_matchings/code/audio_synthesis/AudioSynth_HiLoGain.s,AudioSynth_HiLoGain,0x801881C4,0xD
+asm/non_matchings/code/audio_synthesis/AudioSynth_UnkCmd19.s,AudioSynth_UnkCmd19,0x801881F8,0xB
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop18.s,AudioSynth_Noop18,0x80188224,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop19.s,AudioSynth_Noop19,0x8018822C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop20.s,AudioSynth_Noop20,0x80188234,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop21.s,AudioSynth_Noop21,0x8018823C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop22.s,AudioSynth_Noop22,0x80188244,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop23.s,AudioSynth_Noop23,0x8018824C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop24.s,AudioSynth_Noop24,0x80188254,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop25.s,AudioSynth_Noop25,0x8018825C,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadFilterBuffer.s,AudioSynth_LoadFilterBuffer,0x80188264,0x9
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadFilterSize.s,AudioSynth_LoadFilterSize,0x80188288,0x6
+asm/non_matchings/code/audio_synthesis/AudioSynth_LeakReverb.s,AudioSynth_LeakReverb,0x801882A0,0x19
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadDownsampledReverbSamples.s,AudioSynth_LoadDownsampledReverbSamples,0x80188304,0x67
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveResampledReverbSamples.s,AudioSynth_SaveResampledReverbSamples,0x801884A0,0x7E
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadResampledReverbSamples.s,AudioSynth_LoadResampledReverbSamples,0x80188698,0x69
+asm/non_matchings/code/audio_synthesis/AudioSynth_FilterReverb.s,AudioSynth_FilterReverb,0x8018883C,0x2A
+asm/non_matchings/code/audio_synthesis/AudioSynth_MixOtherReverbIndex.s,AudioSynth_MixOtherReverbIndex,0x801888E4,0x30
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadDefaultReverbSamples.s,AudioSynth_LoadDefaultReverbSamples,0x801889A4,0x2B
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadSubReverbSamples.s,AudioSynth_LoadSubReverbSamples,0x80188A50,0x2B
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveResampledReverbSamplesImpl.s,AudioSynth_SaveResampledReverbSamplesImpl,0x80188AFC,0x53
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadReverbSamplesImpl.s,AudioSynth_LoadReverbSamplesImpl,0x80188C48,0x1B
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveReverbSamplesImpl.s,AudioSynth_SaveReverbSamplesImpl,0x80188CB4,0x1B
+asm/non_matchings/code/audio_synthesis/AudioSynth_Noop26.s,AudioSynth_Noop26,0x80188D20,0x2
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadSubReverbSamplesWithoutDownsample.s,AudioSynth_LoadSubReverbSamplesWithoutDownsample,0x80188D28,0x10
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadReverbSamples.s,AudioSynth_LoadReverbSamples,0x80188D68,0x1D
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveReverbSamples.s,AudioSynth_SaveReverbSamples,0x80188DDC,0x78
+asm/non_matchings/code/audio_synthesis/AudioSynth_SaveSubReverbSamples.s,AudioSynth_SaveSubReverbSamples,0x80188FBC,0x2A
+asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessSamples.s,AudioSynth_ProcessSamples,0x80189064,0x16F
+asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessSample.s,AudioSynth_ProcessSample,0x80189620,0x3A5
+asm/non_matchings/code/audio_synthesis/AudioSynth_ApplySurroundEffect.s,AudioSynth_ApplySurroundEffect,0x8018A4B4,0xAD
+asm/non_matchings/code/audio_synthesis/AudioSynth_FinalResample.s,AudioSynth_FinalResample,0x8018A768,0x28
+asm/non_matchings/code/audio_synthesis/AudioSynth_ProcessEnvelope.s,AudioSynth_ProcessEnvelope,0x8018A808,0x12F
+asm/non_matchings/code/audio_synthesis/AudioSynth_LoadWaveSamples.s,AudioSynth_LoadWaveSamples,0x8018ACC4,0x5C
+asm/non_matchings/code/audio_synthesis/AudioSynth_ApplyHaasEffect.s,AudioSynth_ApplyHaasEffect,0x8018AE34,0xAF
asm/non_matchings/code/audio_heap/AudioHeap_ResetLoadStatus.s,AudioHeap_ResetLoadStatus,0x8018B250,0x32
asm/non_matchings/code/audio_heap/AudioHeap_DiscardFont.s,AudioHeap_DiscardFont,0x8018B318,0x39
asm/non_matchings/code/audio_heap/AudioHeap_ReleaseNotesForFont.s,AudioHeap_ReleaseNotesForFont,0x8018B3FC,0x1E
@@ -3242,7 +3242,7 @@ asm/non_matchings/code/code_80194710/osAiSetNextBuffer.s,osAiSetNextBuffer,0x801
asm/non_matchings/code/code_80194710/func_80194804.s,func_80194804,0x80194804,0xF
asm/non_matchings/code/code_80194710/func_80194840.s,func_80194840,0x80194840,0x1C
asm/non_matchings/code/code_80194710/func_801948B0.s,func_801948B0,0x801948B0,0x20
-asm/non_matchings/code/audio_playback/AudioPlayback_InitNoteSub.s,AudioPlayback_InitNoteSub,0x80194930,0x120
+asm/non_matchings/code/audio_playback/AudioPlayback_InitSampleState.s,AudioPlayback_InitSampleState,0x80194930,0x120
asm/non_matchings/code/audio_playback/AudioPlayback_NoteSetResamplingRate.s,AudioPlayback_NoteSetResamplingRate,0x80194DB0,0x2C
asm/non_matchings/code/audio_playback/AudioPlayback_NoteInit.s,AudioPlayback_NoteInit,0x80194E60,0x30
asm/non_matchings/code/audio_playback/AudioPlayback_NoteDisable.s,AudioPlayback_NoteDisable,0x80194F20,0x19
diff --git a/undefined_syms.txt b/undefined_syms.txt
index aae06790f..073840341 100644
--- a/undefined_syms.txt
+++ b/undefined_syms.txt
@@ -1375,14 +1375,6 @@ D_060014C0 = 0x060014C0;
D_060015B0 = 0x060015B0;
D_06001E20 = 0x06001E20;
-// ovl_En_Wiz
-
-D_06001860 = 0x06001860;
-D_0600211C = 0x0600211C;
-D_060025F0 = 0x060025F0;
-D_060066C0 = 0x060066C0;
-D_0600B320 = 0x0600B320;
-
// ovl_En_Zl4
D_06013328 = 0x06013328;