From 924fa9aadf99f9efdc3cd19411bb1c834f3ad74c Mon Sep 17 00:00:00 2001
From: EllipticEllipsis <73679967+EllipticEllipsis@users.noreply.github.com>
Date: Sun, 16 Jan 2022 17:55:03 +0000
Subject: [PATCH] EnMag OK and documented (#547)
* Name textures in object_mag
* Corrections
* tabs -> spaces
* OK, data imported
* Remove obsolete comment
* Start documentation
* Defines for most texture sizes
* Name most static variables, add state enum
* Macros, name all the statics
* Couple of minor tweaks to other files
* Name some more effect stuff
* Fix kanfont data
* Name everything else, move macros
* Format
* Review
---
assets/xml/objects/object_mag.xml | 26 +-
include/functions.h | 2 +-
include/macros.h | 15 +
include/z64.h | 4 +-
spec | 3 +-
src/code/sys_math.c | 2 +-
src/code/z_kanfont.c | 14 +-
src/overlays/actors/ovl_En_Mag/z_en_mag.c | 947 +++++++++++++++++++-
src/overlays/actors/ovl_En_Mag/z_en_mag.h | 40 +-
src/overlays/gamestates/ovl_title/z_title.c | 3 +-
tools/disasm/functions.txt | 14 +-
tools/disasm/variables.txt | 42 +-
12 files changed, 1045 insertions(+), 67 deletions(-)
diff --git a/assets/xml/objects/object_mag.xml b/assets/xml/objects/object_mag.xml
index 1feae8057c..6ec4426d8c 100644
--- a/assets/xml/objects/object_mag.xml
+++ b/assets/xml/objects/object_mag.xml
@@ -5,18 +5,20 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/include/functions.h b/include/functions.h
index 3c20bca11c..14744a9dee 100644
--- a/include/functions.h
+++ b/include/functions.h
@@ -3768,7 +3768,7 @@ void func_801A3CD8(s8 param_1);
// void func_801A3D98(void);
// void func_801A3E38(void);
// void func_801A3EC0(void);
-void func_801A3F54(s32 arg0);
+void func_801A3F54(u8 flag);
// void func_801A3F6C(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_801A3FB4(void);
// void func_801A3FFC(UNK_TYPE1 param_1);
diff --git a/include/macros.h b/include/macros.h
index c5fc2c4aeb..4253eb6cd8 100644
--- a/include/macros.h
+++ b/include/macros.h
@@ -127,6 +127,21 @@ extern GraphicsContext* __gfxCtx;
#define GRAPH_ALLOC(gfxCtx, size) ((void*)((gfxCtx)->polyOpa.d = (Gfx*)((u8*)(gfxCtx)->polyOpa.d - (size))))
+// Custom gbi macro
+#define gDPSetTileCustom(pkt, fmt, siz, width, height, pal, cms, cmt, masks, maskt, shifts, shiftt) \
+ { \
+ gDPPipeSync(pkt); \
+ gDPTileSync(pkt); \
+ gDPSetTile(pkt, fmt, siz, (((width)*siz##_TILE_BYTES) + 7) >> 3, 0, G_TX_LOADTILE, 0, cmt, maskt, shiftt, cms, \
+ masks, shifts); \
+ gDPTileSync(pkt); \
+ gDPSetTile(pkt, fmt, siz, (((width)*siz##_TILE_BYTES) + 7) >> 3, 0, G_TX_RENDERTILE, pal, cmt, maskt, shiftt, \
+ cms, masks, shifts); \
+ gDPSetTileSize(pkt, G_TX_RENDERTILE, 0, 0, ((width)-1) << G_TEXTURE_IMAGE_FRAC, \
+ ((height)-1) << G_TEXTURE_IMAGE_FRAC); \
+ } \
+ (void)0
+
#define ALIGN8(val) (((val) + 7) & ~7)
#define ALIGN16(val) (((val) + 0xF) & ~0xF)
#define ALIGN64(val) (((val) + 0x3F) & ~0x3F)
diff --git a/include/z64.h b/include/z64.h
index f468d32aa1..cb41a82496 100644
--- a/include/z64.h
+++ b/include/z64.h
@@ -167,8 +167,10 @@ typedef struct {
/* 0x5 */ Color_RGB8 envColor;
} FireObjLightParams; // size = 0x8
+#define FONT_CHAR_TEX_WIDTH 16
+#define FONT_CHAR_TEX_HEIGHT 16
//! @TODO: Make this use `sizeof(AnyFontTextureSymbol)`
-#define FONT_CHAR_TEX_SIZE ((16 * 16) / 2)
+#define FONT_CHAR_TEX_SIZE ((16 * 16) / 2) // 16x16 I4 texture
// Font textures are loaded into here
typedef struct {
diff --git a/spec b/spec
index 98cd58af9b..de71a0e4f2 100644
--- a/spec
+++ b/spec
@@ -1754,8 +1754,7 @@ beginseg
name "ovl_En_Mag"
compress
include "build/src/overlays/actors/ovl_En_Mag/z_en_mag.o"
- include "build/data/ovl_En_Mag/ovl_En_Mag.data.o"
- include "build/data/ovl_En_Mag/ovl_En_Mag.reloc.o"
+ include "build/src/overlays/actors/ovl_En_Mag/ovl_En_Mag_reloc.o"
endseg
beginseg
diff --git a/src/code/sys_math.c b/src/code/sys_math.c
index 9b274c7e24..da4ccc9d28 100644
--- a/src/code/sys_math.c
+++ b/src/code/sys_math.c
@@ -34,7 +34,7 @@ f32 func_80179400(s32 n) {
//! @bug No check for negative argument. Will read the array out-of-bounds if the argument is negative.
//! (The OoT version does an unsigned check instead, which will return sFactorialTbl[12] for a negative argument.)
- if (n > 12) {
+ if (n >= ARRAY_COUNT(sFactorialTbl)) {
ret = sFactorialTbl[12];
for (i = 13; i <= n; i++) {
ret *= i;
diff --git a/src/code/z_kanfont.c b/src/code/z_kanfont.c
index b678642b18..2a4849ccb0 100644
--- a/src/code/z_kanfont.c
+++ b/src/code/z_kanfont.c
@@ -19,11 +19,13 @@ void Font_LoadMessageBoxEndIcon(Font* font, u16 icon) {
FONT_CHAR_TEX_SIZE);
}
-static u8 sFontOrdering[] = "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19"
- "!\"#$%&\'()*+,-./0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "\x00\x0D\x0E\x1A"
- "afjmosvwxyz{|}~"
- "\x7F\x80\x81\x84\x86\x87\x88\x89\x8A\x8B\x8C";
+static u8 sFontOrdering[] = {
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29,
+ 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x41, 0x42,
+ 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55,
+ 0x56, 0x57, 0x58, 0x59, 0x5A, 0x00, 0x0D, 0x0E, 0x1A, 0x61, 0x66, 0x6A, 0x6D, 0x6F, 0x73, 0x76, 0x77, 0x78, 0x79,
+ 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x84, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C,
+};
void Font_LoadOrderedFont(Font* font) {
u32 loadOffset;
@@ -36,7 +38,7 @@ void Font_LoadOrderedFont(Font* font) {
if (sFontOrdering[codePointIndex] == 0) {
loadOffset = 0;
}
- // UB to convert pointer to u32
+
DmaMgr_SendRequest0(writeLocation, (uintptr_t)SEGMENT_ROM_START(nes_font_static) + loadOffset,
FONT_CHAR_TEX_SIZE);
if (sFontOrdering[codePointIndex] == 0x8C) {
diff --git a/src/overlays/actors/ovl_En_Mag/z_en_mag.c b/src/overlays/actors/ovl_En_Mag/z_en_mag.c
index 6b18d43fd5..6f2591952c 100644
--- a/src/overlays/actors/ovl_En_Mag/z_en_mag.c
+++ b/src/overlays/actors/ovl_En_Mag/z_en_mag.c
@@ -5,6 +5,7 @@
*/
#include "z_en_mag.h"
+#include "objects/object_mag/object_mag.h"
#define FLAGS 0x00000030
@@ -15,7 +16,75 @@ void EnMag_Destroy(Actor* thisx, GlobalContext* globalCtx);
void EnMag_Update(Actor* thisx, GlobalContext* globalCtx);
void EnMag_Draw(Actor* thisx, GlobalContext* globalCtx);
-#if 0
+/**
+ * Steps `var` towards `target` linearly, so that it will arrive in `timeRemaining` seconds. Can be used from either
+ * direction. `timeRemaining` must be decremented separately for this to work properly, and obviously timeRemaining = 0
+ * must be handled separately.
+ *
+ * @param var Variable to step.
+ * @param target Target to step towards.
+ * @param timeRemaining Number of times this function should be run for `var` to reach `target`
+ * @param stepVar Variable to use for the step (required to match).
+ *
+ * The progression is not quite linear because of truncation in the division, but the variable will always reach
+ * `target` at the appropriate time since the last step is always the full difference.
+ */
+#define TIMED_STEP_TO(var, target, timeRemaining, stepVar) \
+ { \
+ stepVar = ABS_ALT(var - target) / timeRemaining; \
+ if (var >= target) { \
+ var -= stepVar; \
+ } else { \
+ var += stepVar; \
+ } \
+ } \
+ (void)0
+
+/**
+ * Similar to `TIMED_STEP_TO`, but will always increase `var`. If var > target, this will eventually increase `var` by
+ * an amount that is at most ( timeRemaining + 1 ) * | var - target |, but which depends on the amount lost to
+ * truncation from the divisions.
+ */
+#define TIMED_STEP_UP_TO(var, target, timeRemaining, stepVar) \
+ { \
+ stepVar = ABS_ALT(var - target) / timeRemaining; \
+ var += stepVar; \
+ } \
+ (void)0
+
+/**
+ * Similar to `TIMED_STEP_TO`, but will always increase `var`. If var < target, this will eventually dncrease `var` by
+ * an amount that is at most ( timeRemaining + 1 ) * | var - target |, but which depends on the amount lost to
+ * truncation from the divisions.
+ */
+#define TIMED_STEP_DOWN_TO(var, target, timeRemaining, stepVar) \
+ { \
+ stepVar = ABS_ALT(var - target) / timeRemaining; \
+ var -= stepVar; \
+ } \
+ (void)0
+
+typedef enum {
+ /* 0 */ MAG_STATE_INITIAL,
+ /* 1 */ MAG_STATE_FADE_IN_MASK_EFFECTS,
+ /* 2 */ MAG_STATE_FADE_IN_MASK,
+ /* 3 */ MAG_STATE_FADE_IN_MAIN_TITLE,
+ /* 5 */ MAG_STATE_FADE_IN_SUBTITLE = 5,
+ /* 6 */ MAG_STATE_FADE_IN_COPYRIGHT, // And PRESS START
+ /* 10 */ MAG_STATE_CALLED = 10, // by a button press
+ /* 13 */ MAG_STATE_DISPLAY = 13, // Buttons will trigger File Select state
+ /* 20 */ MAG_STATE_FADE_OUT = 20,
+ /* 21 */ MAG_STATE_POST_DISPLAY // Go to next scene
+} EnMagState;
+
+static s16 sInputDelayTimer = 0;
+
+static s16 sZeldaEffectColorTimer = 30;
+static s16 sZeldaEffectColorTargetIndex = 0;
+
+static s16 sTextAlphaTargetIndex = 0;
+static s16 sTextAlphaTimer = 20;
+
const ActorInit En_Mag_InitVars = {
ACTOR_EN_MAG,
ACTORCAT_PROP,
@@ -28,28 +97,878 @@ const ActorInit En_Mag_InitVars = {
(ActorFunc)EnMag_Draw,
};
-#endif
+void EnMag_Init(Actor* thisx, GlobalContext* globalCtx) {
+ EnMag* this = THIS;
+ u16 i;
-extern UNK_TYPE D_06011E48;
+ this->unk11F54 = 6;
+ this->unk11F56 = 10;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/EnMag_Init.s")
+ for (i = 0; i < 6; i++) {
+ this->effectScrollSs[i] = 0;
+ this->effectScrollTs[i] = 0;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/EnMag_Destroy.s")
+ this->appearEffectPrimColor[0] = 255;
+ this->appearEffectPrimColor[1] = 155;
+ this->appearEffectPrimColor[2] = 255;
+ this->appearEffectEnvColor[0] = 0;
+ this->appearEffectEnvColor[1] = 255;
+ this->appearEffectEnvColor[2] = 155;
+ this->appearEffectPrimLodFrac = 20;
+ this->appearEffectAlpha = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096B604.s")
+ this->displayEffectPrimColor[0] = 255;
+ this->displayEffectPrimColor[1] = 155;
+ this->displayEffectPrimColor[2] = 255;
+ this->displayEffectEnvColor[0] = 0;
+ this->displayEffectEnvColor[1] = 255;
+ this->displayEffectEnvColor[2] = 155;
+ this->displayEffectPrimLodFrac = 55;
+ this->displayEffectAlpha = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/EnMag_Update.s")
+ this->majorasMaskAlpha = 0;
+ this->majorasMaskEnvColor[0] = this->majorasMaskEnvColor[1] = this->majorasMaskEnvColor[2] = 255;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096C998.s")
+ this->mainTitleAlpha = this->subtitleAlpha = this->unk11F32 = this->copyrightAlpha = 0;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096CBB0.s")
+ this->unk11F02 = 30;
+ this->unk11F00 = this->state = MAG_STATE_INITIAL;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096CDC8.s")
+ if (gSaveContext.unk_3F1E != 0) {
+ this->mainTitleAlpha = 210;
+ this->unk11F32 = 255;
+ this->copyrightAlpha = 255;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096D230.s")
+ this->appearEffectPrimLodFrac = 100;
+ this->appearEffectAlpha = 255;
+ this->appearEffectPrimColor[0] = 255;
+ this->appearEffectPrimColor[1] = 255;
+ this->appearEffectPrimColor[2] = 255;
+ this->appearEffectEnvColor[0] = 0;
+ this->appearEffectEnvColor[1] = 255;
+ this->appearEffectEnvColor[2] = 155;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096D60C.s")
+ this->displayEffectPrimLodFrac = 100;
+ this->displayEffectAlpha = 255;
+ this->displayEffectPrimColor[0] = 255;
+ this->displayEffectPrimColor[1] = 255;
+ this->displayEffectPrimColor[2] = 255;
+ this->displayEffectEnvColor[0] = 0;
+ this->displayEffectEnvColor[1] = 255;
+ this->displayEffectEnvColor[2] = 155;
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/func_8096D74C.s")
+ gSaveContext.unk_3F1E = 0;
+ this->state = MAG_STATE_FADE_IN_MASK;
+ sInputDelayTimer = 20;
+ gSaveContext.fadeDuration = 1;
+ gSaveContext.unk_3F51 = 255;
+ }
-#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_En_Mag/EnMag_Draw.s")
+ Font_LoadOrderedFont(&this->font);
+
+ this->unk11F58 = 0;
+ this->unk11F5A = 0;
+ this->unk11F5C = 0;
+ this->unk11F60 = 0;
+
+ this->majorasMaskEffectsFadeInTimer = 25;
+ this->majorasMaskFadeInTimer = 25;
+ this->mainTitleAlphaFadeInTimer = 20;
+ this->effectAlphaFadeInTimer = 40;
+ this->subtitleFadeInTimer = 10;
+ this->copyrightFadeInTimer = 10;
+ this->fadeOutTimer = 15;
+
+ sZeldaEffectColorTimer = 30;
+ sZeldaEffectColorTargetIndex = 0;
+}
+
+void EnMag_Destroy(Actor* thisx, GlobalContext* globalCtx) {
+}
+
+void EnMag_UpdateDisplayEffectColors(Actor* thisx) {
+ static s16 sDisplayEffectPrimRedTargets[] = { 155, 255 };
+ static s16 sDisplayEffectPrimGreenTargets[] = { 255, 155 };
+ static s16 sDisplayEffectPrimBlueTargets[] = { 55, 255 };
+ static s16 sDisplayEffectEnvRedTargets[] = { 255, 0 };
+ static s16 sDisplayEffectEnvBlueTargets[] = { 255, 155 };
+ EnMag* this = THIS;
+ s16 colorStep;
+
+ TIMED_STEP_TO(this->displayEffectPrimColor[0], sDisplayEffectPrimRedTargets[sZeldaEffectColorTargetIndex],
+ sZeldaEffectColorTimer, colorStep);
+ TIMED_STEP_TO(this->displayEffectPrimColor[1], sDisplayEffectPrimGreenTargets[sZeldaEffectColorTargetIndex],
+ sZeldaEffectColorTimer, colorStep);
+ TIMED_STEP_TO(this->displayEffectPrimColor[2], sDisplayEffectPrimBlueTargets[sZeldaEffectColorTargetIndex],
+ sZeldaEffectColorTimer, colorStep);
+ TIMED_STEP_TO(this->displayEffectEnvColor[0], sDisplayEffectEnvRedTargets[sZeldaEffectColorTargetIndex],
+ sZeldaEffectColorTimer, colorStep);
+ // Skips 1, i.e. green.
+ TIMED_STEP_TO(this->displayEffectEnvColor[2], sDisplayEffectEnvBlueTargets[sZeldaEffectColorTargetIndex],
+ sZeldaEffectColorTimer, colorStep);
+
+ sZeldaEffectColorTimer--;
+ if (sZeldaEffectColorTimer == 0) {
+ this->displayEffectPrimColor[0] = sDisplayEffectPrimRedTargets[sZeldaEffectColorTargetIndex];
+ this->displayEffectPrimColor[1] = sDisplayEffectPrimGreenTargets[sZeldaEffectColorTargetIndex];
+ this->displayEffectPrimColor[2] = sDisplayEffectPrimBlueTargets[sZeldaEffectColorTargetIndex];
+ this->displayEffectEnvColor[0] = sDisplayEffectEnvRedTargets[sZeldaEffectColorTargetIndex];
+ // Skips 1, i.e. green.
+ this->displayEffectEnvColor[2] = sDisplayEffectEnvBlueTargets[sZeldaEffectColorTargetIndex];
+ sZeldaEffectColorTimer = 30;
+ sZeldaEffectColorTargetIndex ^= 1;
+ }
+}
+
+/**
+ * Controls the actions performed using a switch and the `state` struct variable rather than action functions. Most of
+ * these are to do with fading various parts in and out.
+ */
+void EnMag_Update(Actor* thisx, GlobalContext* globalCtx) {
+ static s16 sAppearEffectPrimGreenTargets[] = { 255, 155 };
+ static s16 sAppearEffectEnvRedTargets[] = { 255, 0 };
+ static s16 sAppearEffectEnvBlueTargets[] = { 0, 155 };
+ s16 step;
+ s32 pad[2];
+ EnMag* this = THIS;
+
+ if (gSaveContext.fileNum != 0xFEDC) {
+ if (this->state == MAG_STATE_INITIAL) {
+ if (CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_START) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_A) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_B)) {
+
+ if (!EnvFlags_Get(globalCtx, 4)) {
+ play_sound(NA_SE_SY_PIECE_OF_HEART);
+ this->state = MAG_STATE_CALLED;
+ this->unk11F00 = 0;
+ this->unk11F02 = 30;
+ sInputDelayTimer = 20;
+ gSaveContext.fadeDuration = 1;
+ gSaveContext.unk_3F51 = 255;
+ }
+ }
+ } else {
+ switch (this->state) {
+ case MAG_STATE_FADE_IN_MASK_EFFECTS:
+ TIMED_STEP_TO(this->appearEffectPrimColor[1], sAppearEffectPrimGreenTargets[0],
+ this->majorasMaskEffectsFadeInTimer, step);
+ TIMED_STEP_TO(this->appearEffectEnvColor[0], sAppearEffectEnvRedTargets[0],
+ this->majorasMaskEffectsFadeInTimer, step);
+ TIMED_STEP_TO(this->appearEffectEnvColor[2], sAppearEffectEnvBlueTargets[0],
+ this->majorasMaskEffectsFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->appearEffectAlpha, 255, this->majorasMaskEffectsFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->appearEffectPrimLodFrac, 32, this->majorasMaskEffectsFadeInTimer, step);
+
+ this->majorasMaskEffectsFadeInTimer--;
+ if (this->majorasMaskEffectsFadeInTimer == 0) {
+ this->appearEffectPrimColor[1] = sAppearEffectPrimGreenTargets[0];
+ this->appearEffectEnvColor[0] = sAppearEffectEnvRedTargets[0];
+ this->appearEffectEnvColor[2] = sAppearEffectEnvBlueTargets[0];
+ this->appearEffectAlpha = 255;
+ this->state = MAG_STATE_FADE_IN_MASK;
+ this->delayTimer = 5;
+ }
+ break;
+
+ case MAG_STATE_FADE_IN_MASK:
+ if (this->delayTimer == 0) {
+ TIMED_STEP_TO(this->appearEffectPrimColor[1], sAppearEffectPrimGreenTargets[1],
+ this->majorasMaskFadeInTimer, step);
+ TIMED_STEP_TO(this->appearEffectEnvColor[0], sAppearEffectEnvRedTargets[1],
+ this->majorasMaskFadeInTimer, step);
+ TIMED_STEP_TO(this->appearEffectEnvColor[2], sAppearEffectEnvBlueTargets[1],
+ this->majorasMaskFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->appearEffectPrimLodFrac, 128, this->majorasMaskFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->majorasMaskAlpha, 255, this->majorasMaskFadeInTimer, step);
+
+ this->majorasMaskFadeInTimer--;
+ if (this->majorasMaskFadeInTimer == 0) {
+ this->appearEffectPrimColor[1] = sAppearEffectPrimGreenTargets[1];
+ this->appearEffectEnvColor[0] = sAppearEffectEnvRedTargets[1];
+ this->appearEffectEnvColor[2] = sAppearEffectEnvBlueTargets[1];
+ this->appearEffectPrimLodFrac = 128;
+ this->majorasMaskAlpha = 255;
+ this->state = MAG_STATE_FADE_IN_MAIN_TITLE;
+ this->delayTimer = 5;
+ }
+ } else {
+ this->delayTimer--;
+ }
+ break;
+
+ case MAG_STATE_FADE_IN_MAIN_TITLE:
+ if (this->delayTimer == 0) {
+ TIMED_STEP_UP_TO(this->mainTitleAlpha, 255, this->mainTitleAlphaFadeInTimer, step);
+
+ this->mainTitleAlphaFadeInTimer--;
+ if (this->mainTitleAlphaFadeInTimer == 0) {
+ this->mainTitleAlphaFadeInTimer = 1;
+ this->mainTitleAlpha = 255;
+ }
+
+ TIMED_STEP_DOWN_TO(this->appearEffectAlpha, 60, this->effectAlphaFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->displayEffectAlpha, 255, this->effectAlphaFadeInTimer, step);
+ TIMED_STEP_UP_TO(this->displayEffectPrimLodFrac, 128, this->effectAlphaFadeInTimer, step);
+
+ this->effectAlphaFadeInTimer--;
+
+ if (this->effectAlphaFadeInTimer == 0) {
+ this->appearEffectAlpha = 60;
+ this->displayEffectAlpha = 255;
+ this->displayEffectPrimLodFrac = 128;
+ this->state = MAG_STATE_FADE_IN_SUBTITLE;
+ this->delayTimer = 20;
+ }
+ } else {
+ this->delayTimer--;
+ }
+ break;
+
+ case MAG_STATE_FADE_IN_SUBTITLE:
+ EnMag_UpdateDisplayEffectColors(&this->actor);
+
+ if (this->delayTimer == 0) {
+ TIMED_STEP_UP_TO(this->subtitleAlpha, 255, this->subtitleFadeInTimer, step);
+
+ this->subtitleFadeInTimer--;
+ if (this->subtitleFadeInTimer == 0) {
+ this->displayEffectAlpha = 255;
+ this->state = MAG_STATE_FADE_IN_COPYRIGHT;
+ this->delayTimer = 20;
+ }
+ } else {
+ this->delayTimer--;
+ }
+ break;
+
+ case MAG_STATE_FADE_IN_COPYRIGHT:
+ EnMag_UpdateDisplayEffectColors(&this->actor);
+
+ if (this->delayTimer == 0) {
+ TIMED_STEP_UP_TO(this->copyrightAlpha, 255, this->copyrightFadeInTimer, step);
+
+ this->copyrightFadeInTimer--;
+ if (this->copyrightFadeInTimer == 0) {
+ this->copyrightAlpha = 255;
+ this->state = MAG_STATE_DISPLAY;
+ }
+ } else {
+ this->delayTimer--;
+ }
+ break;
+
+ case MAG_STATE_CALLED:
+ this->appearEffectPrimColor[1] = sAppearEffectPrimGreenTargets[0];
+ this->appearEffectEnvColor[0] = sAppearEffectEnvRedTargets[0];
+ this->appearEffectEnvColor[2] = sAppearEffectEnvBlueTargets[0];
+ this->appearEffectAlpha = 60;
+ this->appearEffectPrimLodFrac = 128;
+ this->majorasMaskAlpha = 255;
+ this->mainTitleAlpha = 255;
+ this->displayEffectAlpha = 255;
+ this->displayEffectPrimLodFrac = 128;
+ this->subtitleAlpha = 255;
+ this->copyrightAlpha = 255;
+ this->state = MAG_STATE_DISPLAY;
+ break;
+
+ case MAG_STATE_DISPLAY:
+ EnMag_UpdateDisplayEffectColors(&this->actor);
+
+ if (sInputDelayTimer == 0) {
+ if (CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_START) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_A) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_B)) {
+ if (globalCtx->sceneLoadFlag != 0x14) {
+ func_801A3F54(false);
+ D_801BB12C++;
+ if (D_801BB12C >= 2) {
+ D_801BB12C = 0;
+ }
+ play_sound(NA_SE_SY_PIECE_OF_HEART);
+ gSaveContext.gameMode = 2; // Go to FileChoose
+ globalCtx->sceneLoadFlag = 0x14;
+ globalCtx->unk_1887F = 2;
+ globalCtx->nextEntranceIndex = 0x1C00;
+ gSaveContext.cutscene = 0;
+ gSaveContext.sceneSetupIndex = 0;
+ }
+ this->unk11F54 = 15;
+ this->unk11F56 = 25;
+ this->state = MAG_STATE_FADE_OUT;
+ }
+ } else {
+ sInputDelayTimer--;
+ }
+ break;
+
+ case MAG_STATE_FADE_OUT:
+ TIMED_STEP_DOWN_TO(this->appearEffectAlpha, 0, this->fadeOutTimer, step);
+ TIMED_STEP_DOWN_TO(this->majorasMaskAlpha, 0, this->fadeOutTimer, step);
+ TIMED_STEP_DOWN_TO(this->displayEffectAlpha, 0, this->fadeOutTimer, step);
+ TIMED_STEP_DOWN_TO(this->mainTitleAlpha, 0, this->fadeOutTimer, step);
+ TIMED_STEP_DOWN_TO(this->subtitleAlpha, 0, this->fadeOutTimer, step);
+ TIMED_STEP_DOWN_TO(this->copyrightAlpha, 0, this->fadeOutTimer, step);
+
+ this->fadeOutTimer--;
+ if (this->fadeOutTimer == 0) {
+ this->appearEffectAlpha = 0;
+ this->majorasMaskAlpha = 0;
+ this->mainTitleAlpha = 0;
+ this->subtitleAlpha = 0;
+ this->displayEffectAlpha = 0;
+ this->copyrightAlpha = 0;
+ this->state = MAG_STATE_POST_DISPLAY;
+ }
+ break;
+ }
+
+ // Appear fully immediately if called during fade-in states.
+ if ((this->state > MAG_STATE_INITIAL) && (this->state < MAG_STATE_CALLED)) {
+ if (CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_START) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_A) ||
+ CHECK_BTN_ALL(CONTROLLER1(globalCtx)->press.button, BTN_B)) {
+ play_sound(NA_SE_SY_PIECE_OF_HEART);
+ this->state = MAG_STATE_CALLED;
+ }
+ }
+ }
+ }
+
+ if (this->state == MAG_STATE_INITIAL) {
+ if (EnvFlags_Get(globalCtx, 3)) {
+ this->unk11F02 = 40;
+ this->state = MAG_STATE_FADE_IN_MASK_EFFECTS;
+ }
+ } else if (this->state < MAG_STATE_FADE_OUT) {
+ if (EnvFlags_Get(globalCtx, 4)) {
+ this->state = MAG_STATE_FADE_OUT;
+ }
+ }
+}
+
+/**
+ * Draws an i8 texture.
+ *
+ * @param[in,out] gfxp Pointer to current displaylist.
+ * @param[in] texture Texture to draw.
+ * @param[in] texWidth Width of the texture.
+ * @param[in] texHeight Height of the texture.
+ * @param[in] rectLeft X coordinate of the top-left of the draw position.
+ * @param[in] rectTop Y coordinate of the top-left of the draw position.
+ */
+void EnMag_DrawTextureI8(Gfx** gfxp, TexturePtr texture, s16 texWidth, s16 texHeight, s16 rectLeft, s16 rectTop) {
+ Gfx* gfx = *gfxp;
+
+ gDPLoadTextureBlock(gfx++, texture, G_IM_FMT_I, G_IM_SIZ_8b, texWidth, texHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ gSPTextureRectangle(gfx++, rectLeft << 2, rectTop << 2, (rectLeft + texWidth) << 2, (rectTop + texHeight) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ *gfxp = gfx;
+}
+
+/**
+ * Draws an ia8 texture.
+ *
+ * @param[in,out] gfxp Pointer to current displaylist.
+ * @param[in] texture Texture to draw.
+ * @param[in] texWidth Width of the texture.
+ * @param[in] texHeight Height of the texture.
+ * @param[in] rectLeft X coordinate of the top-left of the draw position.
+ * @param[in] rectTop Y coordinate of the top-left of the draw position.
+ */
+void EnMag_DrawTextureIA8(Gfx** gfxp, TexturePtr texture, s16 texWidth, s16 texHeight, s16 rectLeft, s16 rectTop) {
+ Gfx* gfx = *gfxp;
+
+ gDPLoadTextureBlock(gfx++, texture, G_IM_FMT_IA, G_IM_SIZ_8b, texWidth, texHeight, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ gSPTextureRectangle(gfx++, rectLeft << 2, rectTop << 2, (rectLeft + texWidth) << 2, (rectTop + texHeight) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ *gfxp = gfx;
+}
+
+/**
+ * Draws an i8 effect texture, masking it with an i4 mask, with shifting
+ *
+ * @param[in,out] gfxp Pointer to current displaylist.
+ * @param[in] maskTex Texture with which to mask, i4.
+ * @param[in] effectTex Effect texture to draw, i8.
+ * @param[in] maskWidth Width of masking texture.
+ * @param[in] maskHeight Height of masking texture.
+ * @param[in] effectWidth Width of effect texture.
+ * @param[in] effectHeight Height of effect texture.
+ * @param[in] rectLeft X coordinate of the top-left of the draw position.
+ * @param[in] rectTop Y coordinate of the top-left of the draw position.
+ * @param[in] shifts Shift to apply to effect texture's S coordinate to control LOD.
+ * @param[in] shiftt Shift to apply to effect texture's T coordinate to control LOD.
+ * @param[in] index Index into the scrolling arrays to use for gDPSetTileSize.
+ * @param[in] this Pointer to EnMag instance.
+ */
+void EnMag_DrawEffectTextures(Gfx** gfxp, TexturePtr maskTex, TexturePtr effectTex, s16 maskWidth, s16 maskHeight,
+ s16 effectWidth, s16 effectHeight, s16 rectLeft, s16 rectTop, u16 shifts, u16 shiftt,
+ u16 index, EnMag* this) {
+ Gfx* gfx = *gfxp;
+
+ gDPLoadMultiBlock_4b(gfx++, maskTex, 0x0000, G_TX_RENDERTILE, G_IM_FMT_I, maskWidth, maskHeight, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+
+ gDPLoadMultiBlock(gfx++, effectTex, 0x0100, 1, G_IM_FMT_I, G_IM_SIZ_8b, effectWidth, effectHeight, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, 5, 5, shifts, shiftt);
+
+ gDPSetTileSize(gfx++, 1, this->effectScrollSs[index] & 0x7F, this->effectScrollTs[index] & 0x7F,
+ (this->effectScrollSs[index] & 0x7F) + 15, (this->effectScrollTs[index] & 0x7F) + 15);
+
+ gSPTextureRectangle(gfx++, rectLeft << 2, rectTop << 2, (rectLeft + maskWidth) << 2, (rectTop + maskHeight) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ *gfxp = gfx;
+}
+
+/**
+ * Draws an rgba32 texture. Because these are so large, this will draw the texture in horizontal stripes, each narrow
+ * enough that that part of the texture will fit into TMEM's 4kB.
+ *
+ * @param[in,out] gfxp Pointer to current displaylist.
+ * @param[in] centerX X coordinate of the center of the draw position.
+ * @param[in] centerY Y coordinate of the center of the draw position.
+ * @param[in] source Texture to draw.
+ * @param[in] width Width of the texture.
+ * @param[in] height Height of the texture.
+ */
+void EnMag_DrawImageRGBA32(Gfx** gfxp, s16 centerX, s16 centerY, TexturePtr source, u32 width, u32 height) {
+ Gfx* gfx = *gfxp;
+ uintptr_t curTexture;
+ s32 textureCount;
+ u32 rectLeft;
+ u32 rectTop;
+ u32 textureHeight;
+ s32 remainingSize;
+ s32 textureSize;
+ s32 pad;
+ s32 i;
+
+ func_8012CA0C(&gfx);
+
+ curTexture = source;
+ rectLeft = centerX - (width / 2);
+ rectTop = centerY - (height / 2);
+ textureHeight = TMEM_SIZE / (width << 2);
+ remainingSize = (width * height) << 2;
+ textureSize = (width * textureHeight) << 2;
+ textureCount = remainingSize / textureSize;
+ if ((remainingSize % textureSize) != 0) {
+ textureCount++;
+ }
+
+ gDPSetTileCustom(gfx++, G_IM_FMT_RGBA, G_IM_SIZ_32b, width, textureHeight, 0, G_TX_NOMIRROR | G_TX_CLAMP,
+ G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ remainingSize -= textureSize;
+
+ for (i = 0; i < textureCount; i++) {
+ gDPSetTextureImage(gfx++, G_IM_FMT_RGBA, G_IM_SIZ_32b, width, curTexture);
+
+ gDPLoadSync(gfx++);
+ gDPLoadTile(gfx++, G_TX_LOADTILE, 0, 0, (width - 1) << 2, (textureHeight - 1) << 2);
+
+ gSPTextureRectangle(gfx++, rectLeft << 2, rectTop << 2, (rectLeft + (s32)width) << 2,
+ (rectTop + textureHeight) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ curTexture += textureSize;
+ rectTop += textureHeight;
+
+ if ((remainingSize - textureSize) < 0) {
+ if (remainingSize > 0) {
+ textureHeight = remainingSize / (s32)(width << 2);
+ remainingSize -= textureSize;
+
+ gDPSetTileCustom(gfx++, G_IM_FMT_RGBA, G_IM_SIZ_32b, width, textureHeight, 0,
+ G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ }
+ } else {
+ remainingSize -= textureSize;
+ }
+ }
+
+ *gfxp = gfx;
+}
+
+/**
+ * Draws one character, expected to be a 16 by 16 i4 texture. It will draw shrunk to 10 by 10.
+ *
+ * @param[in,out] gfxp Pointer to current displaylist.
+ * @param[in] texture Texture to draw.
+ * @param[in] rectLeft X coordinate of the top-left of the draw position.
+ * @param[in] rectTop Y coordinate of the top-left of the draw position.
+ */
+void EnMag_DrawCharTexture(Gfx** gfxp, TexturePtr texture, s32 rectLeft, s32 rectTop) {
+ Gfx* gfx = *gfxp;
+
+ gDPLoadTextureBlock_4b(gfx++, texture, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_CLAMP,
+ G_TX_NOMIRROR | G_TX_CLAMP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ // The dsdx and dtdy are roughly 1.587 * 0x400, to fit the texture into 10 by 10 pixels. It is not the more
+ // obvious 1.6 * 0x400 = 1656.
+ gSPTextureRectangle(gfx++, rectLeft << 2, rectTop << 2, (rectLeft + 10) << 2, (rectTop + 10) << 2, G_TX_RENDERTILE,
+ 0, 0, 1625, 1625);
+
+ *gfxp = gfx;
+}
+
+#define EFFECT_MASK_TEX_WIDTH 64
+#define EFFECT_MASK_TEX_HEIGHT 64
+#define EFFECT_TEX_WIDTH 32
+#define EFFECT_TEX_HEIGHT 32
+#define EFFECT_TEX_LEFT 38
+#define EFFECT_TEX_TOP 57
+
+#define MAJORAS_MASK_TEX_WIDTH 128
+#define MAJORAS_MASK_TEX_HEIGHT 112
+#define MAJORAS_MASK_TEX_CENTER_X 124
+#define MAJORAS_MASK_TEX_CENTER_Y 103
+
+#define ZELDA_TEX_WIDTH 144
+#define ZELDA_TEX_HEIGHT 64
+#define ZELDA_TEX_CENTER_X 177
+#define ZELDA_TEX_CENTER_Y 105
+
+#define SUBTITLE_TEX_WIDTH 104
+#define SUBTITLE_TEX_HEIGHT 16
+#define SUBTITLE_TEX_LEFT 151
+#define SUBTITLE_TEX_TOP 124
+
+#define THE_LEGEND_OF_TEX_WIDTH 72
+#define THE_LEGEND_OF_TEX_HEIGHT 8
+#define THE_LEGEND_OF_TEX_LEFT 158
+#define THE_LEGEND_OF_TEX_TOP 71
+
+#define COPYRIGHT_TEX_WIDTH 128
+#define COPYRIGHT_TEX_HEIGHT 16
+#define COPYRIGHT_TEX_LEFT 94
+#define COPYRIGHT_TEX_TOP 198
+
+#define NO_CONTROLLER_FIRST_TEX_WIDTH 256
+#define NO_CONTROLLER_FIRST_TEX_HEIGHT 9
+#define NO_CONTROLLER_FIRST_TEX_LEFT 35
+#define NO_CONTROLLER_FIRST_TEX_TOP 175
+
+#define NO_CONTROLLER_SECOND_TEX_WIDTH 144
+#define NO_CONTROLLER_SECOND_TEX_HEIGHT 9
+#define NO_CONTROLLER_SECOND_TEX_LEFT 91
+#define NO_CONTROLLER_SECOND_TEX_TOP 188
+
+// Top-left of the text itself, not the shadow
+#define PRESS_START_LEFT 119
+#define PRESS_START_TOP 174
+#define PRESS_START_CHAR_SPACING 7 // Amount of rightward shift before printing next char
+#define PRESS_START_SPACE 5 // Extra space between the words
+
+/**
+ * Loads title, PRESS START text, etc. graphics to gfxp, which is made to live on
+ * POLY_OPA_DISP, but is used by OVERLAY_DISP.
+ */
+void EnMag_DrawInner(Actor* thisx, GlobalContext* globalCtx, Gfx** gfxp) {
+ static u8 pressStartFontIndices[] = {
+ 0x19, 0x1B, 0x0E, 0x1C, 0x1C, 0x1C, 0x1D, 0x0A, 0x1B, 0x1D,
+ }; // Indices into this->font.fontBuf
+ static TexturePtr sAppearEffectMaskTextures[] = {
+ gTitleScreenAppearEffectMask00Tex, gTitleScreenAppearEffectMask01Tex, gTitleScreenAppearEffectMask02Tex,
+ gTitleScreenAppearEffectMask10Tex, gTitleScreenAppearEffectMask11Tex, gTitleScreenAppearEffectMask12Tex,
+ }; // Visible when mask appearing
+ static TexturePtr sDisplayEffectMaskTextures[] = {
+ gTitleScreenDisplayEffectMask00Tex, gTitleScreenDisplayEffectMask01Tex, gTitleScreenDisplayEffectMask02Tex,
+ gTitleScreenDisplayEffectMask10Tex, gTitleScreenDisplayEffectMask11Tex, gTitleScreenDisplayEffectMask12Tex,
+ }; // Visible when full game logo displayed
+ static TexturePtr sEffectTextures[] = {
+ gTitleScreenFlame0Tex, gTitleScreenFlame1Tex, gTitleScreenFlame1Tex,
+ gTitleScreenFlame2Tex, gTitleScreenFlame3Tex, gTitleScreenFlame3Tex,
+ };
+ static s16 sEffectScrollVelocitySs[] = { -1, 1, 1, -1, 1, 1 };
+ static s16 sEffectScrollVelocityTs[] = { -2, -2, -2, 2, 2, 2 };
+ static s16 sTextAlpha = 0; // For drawing both the No Controller message and "PRESS START"
+ static s16 sTextAlphaTargets[] = { 255, 0 };
+ s32 pad;
+ EnMag* this = THIS;
+ Font* font = &this->font;
+ Gfx* gfx = *gfxp;
+ u16 i;
+ u16 j;
+ u16 k;
+ s32 rectLeft;
+ s32 rectTop;
+ s16 step;
+
+ // Set segment 6 to the object, since this will be read by OVERLAY_DISP where it is not set by default.
+ gSPSegment(gfx++, 0x06, globalCtx->objectCtx.status[this->actor.objBankIndex].segment);
+
+ func_8012C680(&gfx);
+
+ // Mask appearing effects
+ gDPPipeSync(gfx++);
+ gDPSetCycleType(gfx++, G_CYC_2CYCLE);
+ gDPSetAlphaCompare(gfx++, G_AC_THRESHOLD);
+ gDPSetRenderMode(gfx++, G_RM_PASS, G_RM_CLD_SURF2);
+ gDPSetCombineLERP(gfx++, TEXEL1, PRIMITIVE, PRIM_LOD_FRAC, TEXEL0, TEXEL1, 1, PRIM_LOD_FRAC, TEXEL0, PRIMITIVE,
+ ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(gfx++, 0, this->appearEffectPrimLodFrac, this->appearEffectPrimColor[0],
+ this->appearEffectPrimColor[1], this->appearEffectPrimColor[2], this->appearEffectAlpha);
+ gDPSetEnvColor(gfx++, this->appearEffectEnvColor[0], this->appearEffectEnvColor[1], this->appearEffectEnvColor[2],
+ 255);
+
+ if (this->appearEffectPrimLodFrac != 0) {
+ for (k = 0, i = 0, rectTop = EFFECT_TEX_LEFT; i < 2; i++, rectTop += EFFECT_MASK_TEX_HEIGHT) {
+ for (j = 0, rectLeft = EFFECT_TEX_TOP; j < 3; j++, k++, rectLeft += EFFECT_MASK_TEX_WIDTH) {
+ this->effectScrollSs[k] += sEffectScrollVelocitySs[k];
+ this->effectScrollTs[k] += sEffectScrollVelocityTs[k];
+ EnMag_DrawEffectTextures(&gfx, sAppearEffectMaskTextures[k], sEffectTextures[k], EFFECT_MASK_TEX_WIDTH,
+ EFFECT_MASK_TEX_HEIGHT, EFFECT_TEX_WIDTH, EFFECT_TEX_HEIGHT, rectLeft, rectTop,
+ 1, 1, k, this);
+ }
+ }
+ }
+
+ func_8012C680(&gfx);
+
+ if (this->majorasMaskAlpha != 0) {
+ gDPSetCombineLERP(gfx++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(gfx++, 0, 0, 255, 255, 255, this->majorasMaskAlpha);
+ gDPSetEnvColor(gfx++, this->majorasMaskEnvColor[0], this->majorasMaskEnvColor[1], this->majorasMaskEnvColor[2],
+ 255);
+
+ EnMag_DrawImageRGBA32(&gfx, MAJORAS_MASK_TEX_CENTER_X, MAJORAS_MASK_TEX_CENTER_Y, gTitleScreenMajorasMaskTex,
+ MAJORAS_MASK_TEX_WIDTH, MAJORAS_MASK_TEX_HEIGHT);
+ }
+
+ // Flame glow effects on full game logo when displayed
+ gDPPipeSync(gfx++);
+ gDPSetCycleType(gfx++, G_CYC_2CYCLE);
+ gDPSetAlphaCompare(gfx++, G_AC_THRESHOLD);
+ gDPSetRenderMode(gfx++, G_RM_PASS, G_RM_CLD_SURF2);
+ gDPSetCombineLERP(gfx++, TEXEL1, PRIMITIVE, PRIM_LOD_FRAC, TEXEL0, TEXEL1, 1, PRIM_LOD_FRAC, TEXEL0, PRIMITIVE,
+ ENVIRONMENT, COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(gfx++, 0, this->displayEffectPrimLodFrac, this->displayEffectPrimColor[0],
+ this->displayEffectPrimColor[1], this->displayEffectPrimColor[2], this->displayEffectAlpha);
+ gDPSetEnvColor(gfx++, this->displayEffectEnvColor[0], this->displayEffectEnvColor[1],
+ this->displayEffectEnvColor[2], 255);
+
+ if (this->displayEffectPrimLodFrac != 0) {
+ for (k = 0, i = 0, rectTop = EFFECT_TEX_LEFT; i < 2; i++, rectTop += EFFECT_MASK_TEX_HEIGHT) {
+ for (j = 0, rectLeft = EFFECT_TEX_TOP; j < 3; j++, k++, rectLeft += EFFECT_MASK_TEX_WIDTH) {
+ EnMag_DrawEffectTextures(&gfx, sDisplayEffectMaskTextures[k], sEffectTextures[k], EFFECT_MASK_TEX_WIDTH,
+ EFFECT_MASK_TEX_HEIGHT, EFFECT_TEX_WIDTH, EFFECT_TEX_HEIGHT, rectLeft, rectTop,
+ 1, 1, k, this);
+ }
+ }
+ }
+
+ if (this->subtitleAlpha != 0) {
+ func_8012C680(&gfx);
+
+ gDPSetAlphaCompare(gfx++, G_AC_NONE);
+ gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ if (this->mainTitleAlpha < 100) {
+ gDPSetRenderMode(gfx++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
+ } else {
+ gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
+ }
+
+ gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, this->subtitleAlpha);
+ gDPSetEnvColor(gfx++, 100, 0, 100, 255);
+
+ EnMag_DrawTextureI8(&gfx, gTitleScreenMajorasMaskSubtitleMaskTex, SUBTITLE_TEX_WIDTH, SUBTITLE_TEX_HEIGHT,
+ SUBTITLE_TEX_LEFT, SUBTITLE_TEX_TOP);
+ }
+
+ func_8012C680(&gfx);
+
+ gDPSetAlphaCompare(gfx++, G_AC_NONE);
+ gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ if (this->mainTitleAlpha < 100) {
+ gDPSetRenderMode(gfx++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
+ } else {
+ gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
+ }
+
+ gDPSetPrimColor(gfx++, 0, 120, 208, 102, 222, this->subtitleAlpha);
+
+ EnMag_DrawTextureI8(&gfx, gTitleScreenMajorasMaskSubtitleTex, SUBTITLE_TEX_WIDTH, SUBTITLE_TEX_HEIGHT,
+ SUBTITLE_TEX_LEFT, SUBTITLE_TEX_TOP);
+
+ func_8012C680(&gfx);
+
+ gDPSetAlphaCompare(gfx++, G_AC_NONE);
+ gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ if (this->mainTitleAlpha != 0) {
+ gDPSetPrimColor(gfx++, 0, 0, 255, 255, 255, this->mainTitleAlpha);
+
+ EnMag_DrawImageRGBA32(&gfx, ZELDA_TEX_CENTER_X, ZELDA_TEX_CENTER_Y, gTitleScreenZeldaLogoTex, ZELDA_TEX_WIDTH,
+ ZELDA_TEX_HEIGHT);
+
+ gDPPipeSync(gfx++);
+
+ if (this->mainTitleAlpha < 100) {
+ gDPSetRenderMode(gfx++, G_RM_CLD_SURF, G_RM_CLD_SURF2);
+ } else {
+ gDPSetRenderMode(gfx++, G_RM_XLU_SURF, G_RM_XLU_SURF2);
+ }
+
+ gDPSetPrimColor(gfx++, 0, 0, 208, 102, 222, this->mainTitleAlpha);
+
+ EnMag_DrawTextureI8(&gfx, gTitleScreenTheLegendOfTextTex, THE_LEGEND_OF_TEX_WIDTH, THE_LEGEND_OF_TEX_HEIGHT,
+ THE_LEGEND_OF_TEX_LEFT, THE_LEGEND_OF_TEX_TOP);
+ }
+
+ func_8012C680(&gfx);
+
+ if (this->copyrightAlpha != 0) {
+ gDPSetAlphaCompare(gfx++, G_AC_NONE);
+ gDPSetCombineMode(gfx++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(gfx++, 0, 0, this->copyrightAlpha, this->copyrightAlpha, this->copyrightAlpha,
+ this->copyrightAlpha);
+
+ EnMag_DrawTextureIA8(&gfx, gTitleScreenCopyright2000NintendoTex, COPYRIGHT_TEX_WIDTH, COPYRIGHT_TEX_HEIGHT,
+ COPYRIGHT_TEX_LEFT, COPYRIGHT_TEX_TOP);
+ }
+
+ if (gSaveContext.fileNum == 0xFEDC) {
+ // Draw No controller message
+
+ TIMED_STEP_TO(sTextAlpha, sTextAlphaTargets[sTextAlphaTargetIndex], sTextAlphaTimer, step);
+
+ gDPPipeSync(gfx++);
+ gDPSetAlphaCompare(gfx++, G_AC_THRESHOLD);
+
+ gDPSetCombineLERP(gfx++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE,
+ 0);
+ gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, sTextAlpha);
+ gDPLoadTextureBlock_4b(gfx++, gTitleScreenControllerNotConnectedTextTex, G_IM_FMT_I,
+ NO_CONTROLLER_FIRST_TEX_WIDTH, NO_CONTROLLER_FIRST_TEX_HEIGHT, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ // Texture shadow
+ gSPTextureRectangle(gfx++, (NO_CONTROLLER_FIRST_TEX_LEFT + 1) << 2, (NO_CONTROLLER_FIRST_TEX_TOP + 1) << 2,
+ (NO_CONTROLLER_FIRST_TEX_LEFT + 1 + NO_CONTROLLER_FIRST_TEX_WIDTH) << 2,
+ (NO_CONTROLLER_FIRST_TEX_TOP + 1 + NO_CONTROLLER_FIRST_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0,
+ 0, 1 << 10, 1 << 10);
+ // Actual texture
+ gDPSetPrimColor(gfx++, 0, 0, 205, 255, 255, sTextAlpha);
+ gSPTextureRectangle(gfx++, NO_CONTROLLER_FIRST_TEX_LEFT << 2, NO_CONTROLLER_FIRST_TEX_TOP << 2,
+ (NO_CONTROLLER_FIRST_TEX_LEFT + NO_CONTROLLER_FIRST_TEX_WIDTH) << 2,
+ (NO_CONTROLLER_FIRST_TEX_TOP + NO_CONTROLLER_FIRST_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0, 0,
+ 1 << 10, 1 << 10);
+
+ gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, sTextAlpha);
+ gDPLoadTextureBlock_4b(gfx++, gTitleScreenInsertControllerTextTex, G_IM_FMT_I, NO_CONTROLLER_SECOND_TEX_WIDTH,
+ NO_CONTROLLER_SECOND_TEX_HEIGHT, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ // Texture shadow
+ gSPTextureRectangle(gfx++, (NO_CONTROLLER_SECOND_TEX_LEFT + 1) << 2, (NO_CONTROLLER_SECOND_TEX_TOP + 1) << 2,
+ (NO_CONTROLLER_SECOND_TEX_LEFT + 1 + NO_CONTROLLER_SECOND_TEX_WIDTH) << 2,
+ (NO_CONTROLLER_SECOND_TEX_TOP + 1 + NO_CONTROLLER_SECOND_TEX_HEIGHT) << 2, G_TX_RENDERTILE,
+ 0, 0, 1 << 10, 1 << 10);
+ // Actual texture
+ gDPSetPrimColor(gfx++, 0, 0, 205, 255, 255, sTextAlpha);
+ gSPTextureRectangle(gfx++, NO_CONTROLLER_SECOND_TEX_LEFT << 2, NO_CONTROLLER_SECOND_TEX_TOP << 2,
+ (NO_CONTROLLER_SECOND_TEX_LEFT + NO_CONTROLLER_SECOND_TEX_WIDTH) << 2,
+ (NO_CONTROLLER_SECOND_TEX_TOP + NO_CONTROLLER_SECOND_TEX_HEIGHT) << 2, G_TX_RENDERTILE, 0,
+ 0, 1 << 10, 1 << 10);
+
+ sTextAlphaTimer--;
+ if (sTextAlphaTimer == 0) {
+ sTextAlpha = sTextAlphaTargets[sTextAlphaTargetIndex];
+ if (gSaveContext.fileNum == 0xFEDC) {
+ sTextAlphaTimer = 40;
+ } else {
+ sTextAlphaTimer = 20;
+ }
+ sTextAlphaTargetIndex ^= 1;
+ }
+ } else if (this->copyrightAlpha != 0) {
+ // Draw "PRESS START" characters
+
+ TIMED_STEP_TO(sTextAlpha, sTextAlphaTargets[sTextAlphaTargetIndex], sTextAlphaTimer, step);
+
+ // Text shadow
+ gDPPipeSync(gfx++);
+ gDPSetCombineLERP(gfx++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE,
+ 0);
+ gDPSetPrimColor(gfx++, 0, 0, 0, 0, 0, sTextAlpha);
+
+ rectLeft = PRESS_START_LEFT + 1;
+ for (i = 0; i < ARRAY_COUNT(pressStartFontIndices); i++) {
+ EnMag_DrawCharTexture(&gfx, font->fontBuf + pressStartFontIndices[i] * FONT_CHAR_TEX_SIZE, rectLeft,
+ PRESS_START_TOP + 1);
+
+ rectLeft += PRESS_START_CHAR_SPACING;
+ if (i == 4) {
+ rectLeft += PRESS_START_SPACE;
+ }
+ }
+
+ // Actual text
+ gDPPipeSync(gfx++);
+ gDPSetPrimColor(gfx++, 0, 0, 255, 30, 30, sTextAlpha);
+
+ rectLeft = PRESS_START_LEFT;
+ for (i = 0; i < ARRAY_COUNT(pressStartFontIndices); i++) {
+ EnMag_DrawCharTexture(&gfx, font->fontBuf + pressStartFontIndices[i] * FONT_CHAR_TEX_SIZE, rectLeft,
+ PRESS_START_TOP);
+ rectLeft += PRESS_START_CHAR_SPACING;
+ if (i == 4) {
+ rectLeft += PRESS_START_SPACE;
+ }
+ }
+
+ sTextAlphaTimer--;
+ if (sTextAlphaTimer == 0) {
+ sTextAlpha = sTextAlphaTargets[sTextAlphaTargetIndex];
+ if (gSaveContext.fileNum == 0xFEDC) {
+ sTextAlphaTimer = 40;
+ } else {
+ sTextAlphaTimer = 20;
+ }
+ sTextAlphaTargetIndex ^= 1;
+ }
+ }
+
+ *gfxp = gfx;
+}
+
+/**
+ * Jumps drawing to POLY_OPA_DISP to take advantage of the extra space available, but jmups back and actually draws
+ * using OVERLAY_DISP.
+ */
+void EnMag_Draw(Actor* thisx, GlobalContext* globalCtx) {
+ s32 pad;
+ Gfx* gfx;
+ Gfx* gfxRef;
+
+ OPEN_DISPS(globalCtx->state.gfxCtx);
+
+ gfxRef = POLY_OPA_DISP;
+ gfx = Graph_GfxPlusOne(gfxRef);
+ gSPDisplayList(OVERLAY_DISP++, gfx);
+
+ EnMag_DrawInner(thisx, globalCtx, &gfx);
+
+ gSPEndDisplayList(gfx++);
+ Graph_BranchDlist(gfxRef, gfx);
+ POLY_OPA_DISP = gfx;
+
+ CLOSE_DISPS(globalCtx->state.gfxCtx);
+}
diff --git a/src/overlays/actors/ovl_En_Mag/z_en_mag.h b/src/overlays/actors/ovl_En_Mag/z_en_mag.h
index 3543b5cea8..c116ae98dd 100644
--- a/src/overlays/actors/ovl_En_Mag/z_en_mag.h
+++ b/src/overlays/actors/ovl_En_Mag/z_en_mag.h
@@ -7,7 +7,45 @@ struct EnMag;
typedef struct EnMag {
/* 0x00000 */ Actor actor;
- /* 0x00144 */ char unk_00144[0x11E34];
+ /* 0x00144 */ UNK_TYPE1 unk144[0x2C];
+ /* 0x00170 */ Font font;
+ /* 0x11EFC */ UNK_TYPE1 unk11EFC[4];
+ /* 0x11F00 */ s16 unk11F00; // Set and not used.
+ /* 0x11F02 */ s16 unk11F02; // Set and not used.
+ /* 0x11F04 */ s16 state; // State of whole actor, uses EnMagState enum
+ /* 0x11F06 */ s16 appearEffectPrimLodFrac;
+ /* 0x11F08 */ s16 appearEffectPrimColor[3];
+ /* 0x11F08 */ s16 appearEffectEnvColor[3];
+ /* 0x11F14 */ s16 appearEffectAlpha;
+ /* 0x11F16 */ s16 displayEffectPrimLodFrac;
+ /* 0x11F18 */ s16 displayEffectPrimColor[3];
+ /* 0x11F18 */ s16 displayEffectEnvColor[3];
+ /* 0x11F24 */ s16 displayEffectAlpha;
+ /* 0x11F26 */ s16 majorasMaskAlpha;
+ /* 0x11F28 */ s16 majorasMaskEnvColor[3];
+ /* 0x11F2E */ s16 mainTitleAlpha;
+ /* 0x11F30 */ s16 subtitleAlpha;
+ /* 0x11F32 */ s16 unk11F32; // Set but not used, likely a spare alpha.
+ /* 0x11F34 */ s16 copyrightAlpha;
+ /* 0x11F36 */ s16 effectScrollSs[6];
+ /* 0x11F42 */ UNK_TYPE1 unk11F42[2];
+ /* 0x11F44 */ s16 effectScrollTs[6];
+ /* 0x11F50 */ UNK_TYPE1 unk11F50[4];
+ /* 0x11F54 */ s16 unk11F54; // Set but not used.
+ /* 0x11F56 */ s16 unk11F56; // Set but not used.
+ /* 0x11F58 */ s16 unk11F58; // Set but not used.
+ /* 0x11F5A */ s16 unk11F5A; // Set but not used.
+ /* 0x11F5C */ s32 unk11F5C; // Set but not used.
+ /* 0x11F60 */ s32 unk11F60; // Set but not used.
+ /* 0x11F64 */ s16 majorasMaskEffectsFadeInTimer;
+ /* 0x11F66 */ s16 majorasMaskFadeInTimer;
+ /* 0x11F68 */ s16 mainTitleAlphaFadeInTimer;
+ /* 0x11F6A */ s16 effectAlphaFadeInTimer;
+ /* 0x11F6C */ s16 subtitleFadeInTimer;
+ /* 0x11F6E */ s16 copyrightFadeInTimer;
+ /* 0x11F70 */ s16 fadeOutTimer;
+ /* 0x11F72 */ s16 delayTimer; // Delays start of next action in Update.
+ /* 0x11F74 */ UNK_TYPE1 unk11F74[4];
} EnMag; // size = 0x11F78
extern const ActorInit En_Mag_InitVars;
diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c
index 9b36a7e148..827c273871 100644
--- a/src/overlays/gamestates/ovl_title/z_title.c
+++ b/src/overlays/gamestates/ovl_title/z_title.c
@@ -105,7 +105,8 @@ void Title_Draw(GameState* thisx) {
G_TX_NOLOD, G_TX_NOLOD);
gDPSetTileSize(POLY_OPA_DISP++, 1, this->uls, (this->ult & 0x7F) - idx * 4, 0, 0);
- gSPTextureRectangle(POLY_OPA_DISP++, 388, y << 2, 1156, (y + 2) << 2, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+ gSPTextureRectangle(POLY_OPA_DISP++, 97 << 2, y << 2, (97 + 192) << 2, (y + 2) << 2, G_TX_RENDERTILE, 0, 0,
+ 1 << 10, 1 << 10);
}
func_800FC444(this->gameState.gfxCtx, 0, 0, 0, this->coverAlpha, 2);
diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt
index 25784be00c..a251e77989 100644
--- a/tools/disasm/functions.txt
+++ b/tools/disasm/functions.txt
@@ -7992,14 +7992,14 @@
0x8096B260:("EnOkarinaEffect_Update",),
0x8096B310:("EnMag_Init",),
0x8096B5F4:("EnMag_Destroy",),
- 0x8096B604:("func_8096B604",),
+ 0x8096B604:("EnMag_UpdateDisplayEffectColors",),
0x8096B94C:("EnMag_Update",),
- 0x8096C998:("func_8096C998",),
- 0x8096CBB0:("func_8096CBB0",),
- 0x8096CDC8:("func_8096CDC8",),
- 0x8096D230:("func_8096D230",),
- 0x8096D60C:("func_8096D60C",),
- 0x8096D74C:("func_8096D74C",),
+ 0x8096C998:("EnMag_DrawTextureI8",),
+ 0x8096CBB0:("EnMag_DrawTextureIA8",),
+ 0x8096CDC8:("EnMag_DrawEffectTextures",),
+ 0x8096D230:("EnMag_DrawImageRGBA32",),
+ 0x8096D60C:("EnMag_DrawCharTexture",),
+ 0x8096D74C:("EnMag_DrawInner",),
0x8096E868:("EnMag_Draw",),
0x8096EC40:("ElfMsg2_SetupAction",),
0x8096EC4C:("func_8096EC4C",),
diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt
index 73afcda755..f1bbbb8d15 100644
--- a/tools/disasm/variables.txt
+++ b/tools/disasm/variables.txt
@@ -8997,28 +8997,28 @@
0x8096AD3C:("jtbl_8096AD3C","UNK_PTR","",0x4),
0x8096B290:("En_Okarina_Effect_InitVars","UNK_TYPE1","",0x1),
0x8096B2B0:("D_8096B2B0","f32","",0x4),
- 0x8096E910:("D_8096E910","UNK_TYPE2","",0x2),
- 0x8096E914:("D_8096E914","UNK_TYPE2","",0x2),
- 0x8096E918:("D_8096E918","UNK_TYPE2","",0x2),
- 0x8096E91C:("D_8096E91C","UNK_TYPE2","",0x2),
- 0x8096E920:("D_8096E920","UNK_TYPE2","",0x2),
+ 0x8096E910:("sInputDelayTimer","s16","",0x2),
+ 0x8096E914:("sZeldaEffectColorTimer","s16","",0x2),
+ 0x8096E918:("sZeldaEffectColorTargetIndex","s16","",0x2),
+ 0x8096E91C:("sTextAlphaTargetIndex","s16","",0x2),
+ 0x8096E920:("sTextAlphaTimer","s16","",0x2),
0x8096E924:("En_Mag_InitVars","UNK_TYPE1","",0x1),
- 0x8096E944:("D_8096E944","UNK_TYPE1","",0x1),
- 0x8096E948:("D_8096E948","UNK_TYPE1","",0x1),
- 0x8096E94C:("D_8096E94C","UNK_TYPE1","",0x1),
- 0x8096E950:("D_8096E950","UNK_TYPE1","",0x1),
- 0x8096E954:("D_8096E954","UNK_TYPE1","",0x1),
- 0x8096E958:("D_8096E958","UNK_TYPE2","",0x2),
- 0x8096E95C:("D_8096E95C","UNK_TYPE2","",0x2),
- 0x8096E960:("D_8096E960","UNK_TYPE2","",0x2),
- 0x8096E964:("D_8096E964","UNK_TYPE1","",0x1),
- 0x8096E970:("D_8096E970","UNK_TYPE4","",0x4),
- 0x8096E988:("D_8096E988","UNK_TYPE4","",0x4),
- 0x8096E9A0:("D_8096E9A0","UNK_TYPE4","",0x4),
- 0x8096E9B8:("D_8096E9B8","UNK_TYPE2","",0x2),
- 0x8096E9C4:("D_8096E9C4","UNK_TYPE2","",0x2),
- 0x8096E9D0:("D_8096E9D0","UNK_TYPE2","",0x2),
- 0x8096E9D4:("D_8096E9D4","UNK_TYPE1","",0x1),
+ 0x8096E944:("sDisplayEffectPrimRedTargets","s16","[2]",0x4),
+ 0x8096E948:("sDisplayEffectPrimGreenTargets","s16","[2]",0x4),
+ 0x8096E94C:("sDisplayEffectPrimBlueTargets","s16","[2]",0x4),
+ 0x8096E950:("sDisplayEffectEnvRedTargets","s16","[2]",0x4),
+ 0x8096E954:("sDisplayEffectEnvBlueTargets","s16","[2]",0x4),
+ 0x8096E958:("sAppearEffectPrimGreenTargets","s16","[2]",0x4),
+ 0x8096E95C:("sAppearEffectEnvRedTargets","s16","[2]",0x4),
+ 0x8096E960:("sAppearEffectEnvBlueTargets","s16","[2]",0x4),
+ 0x8096E964:("pressStartFontIndices","u8","[10]",0x1),
+ 0x8096E970:("sAppearEffectMaskTextures","TexturePtr","[6]",0x18),
+ 0x8096E988:("sDisplayEffectMaskTextures","TexturePtr","[6]",0x18),
+ 0x8096E9A0:("sEffectTextures","TexturePtr","[6]",0x18),
+ 0x8096E9B8:("sEffectScrollVelocitySs","s16","[6]",0xC),
+ 0x8096E9C4:("sEffectScrollVelocityTs","s16","[6]",0xC),
+ 0x8096E9D0:("sTextAlpha","s16","",0x2),
+ 0x8096E9D4:("sTextAlphaTargets","s16","[2]",0x4),
0x8096E9E0:("jtbl_8096E9E0","UNK_PTR","",0x4),
0x8096F090:("Elf_Msg2_InitVars","UNK_TYPE1","",0x1),
0x8096F0B0:("D_8096F0B0","UNK_TYPE1","",0x1),