summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDerek Hensley <hensley.derek58@gmail.com>2025-12-08 21:11:07 -0800
committerGitHub <noreply@github.com>2025-12-08 21:11:07 -0800
commit7b96e58622a3b8130b19c25d8633defd0beaeca1 (patch)
treee36a32bde24b3662f5bf3e272c9ba3e598416263 /src
parentf6b17e23584c17fd2d6ec0d1867b8e395a0ed747 (diff)
Multiversion code support (n64-jp-1.1) (#1826)
* setup n64-jp-1.1 disasm * Add versions * New microcode * Bootstrap z_sram * Bootstrap ovl_file_choose * Bootstrap kaleido scope * Bootstrap BgHeavyBlock * MessageContext shift * SaveContext shift * ItemId shift * Fix `PLAYER_CSACTION` shift * format * Add JP only to Heavy Block Description * Makefile multi version comment --------- Co-authored-by: Tom Overton <tom.overton@outlook.com>
Diffstat (limited to 'src')
-rw-r--r--src/code/z_message.c381
-rw-r--r--src/code/z_sram_JPN.c2042
-rw-r--r--src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c40
-rw-r--r--src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.h16
-rw-r--r--src/overlays/actors/ovl_Obj_Warpstone/z_obj_warpstone.c22
-rw-r--r--src/overlays/actors/ovl_player_actor/z_player.c8
-rw-r--r--src/overlays/gamestates/ovl_file_choose/z_file_choose_JPN.c2536
-rw-r--r--src/overlays/gamestates/ovl_file_choose/z_file_nameset_JPN.c1060
-rw-r--r--src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_JPN.c3746
9 files changed, 9685 insertions, 166 deletions
diff --git a/src/code/z_message.c b/src/code/z_message.c
index 5a5c5a910..d188627b6 100644
--- a/src/code/z_message.c
+++ b/src/code/z_message.c
@@ -15,10 +15,55 @@
#include "assets/interface/parameter_static/parameter_static.h"
+#if MM_VERSION >= N64_US
+#define MESSAGE_DECODE(play) Message_DecodeNES(play)
+#define MESSAGE_DRAW_TEXT(play, gfxP, drawPos) Message_DrawTextNES(play, gfxP, drawPos)
+#else
+#define MESSAGE_DECODE(play) Message_Decode(play)
+#define MESSAGE_DRAW_TEXT(play, gfxP, drawPos) Message_DrawTextDefault(play, gfxP)
+#endif
+
u8 D_801C6A70 = 0;
s16 sOcarinaButtonIndexBufPos = 0;
s16 sOcarinaButtonIndexBufLen = 0;
s16 sLastPlayedSong = 0xFF;
+
+#if MM_VERSION >= N64_US
+#define MSGCTX_UNK120BE msgCtx->unk120BE
+#define MSGCTX_UNK120C0 msgCtx->unk120C0
+#define MSGCTX_UNK120C2 msgCtx->unk120C2
+#define MSGCTX_UNK120C4 msgCtx->unk120C4
+#define MSGCTX_UNK120C8 msgCtx->unk120C8
+#define MSGCTX_UNK120CA msgCtx->unk120CA
+#define MSGCTX_UNK120CC msgCtx->unk120CC
+#define MSGCTX_UNK120CE msgCtx->unk120CE
+#define MSGCTX_UNK120D0 msgCtx->unk120D0
+#define MSGCTX_UNK120D2 msgCtx->unk120D2
+#else
+
+s16 D_801C1B00_unknown = 0;
+s16 D_801C1B04_unknown = 0;
+s16 D_801C1B08_unknown = 0;
+s32 D_801C1B0C_unknown = 0;
+s16 D_801C1B10_unknown = 0;
+s16 D_801C1B14_unknown = 0;
+s16 D_801C1B18_unknown = 0;
+s16 D_801C1B1C_unknown = 0;
+s16 D_801C1B20_unknown = 0;
+s16 D_801C1B24_unknown = 0;
+
+#define MSGCTX_UNK120BE D_801C1B00_unknown
+#define MSGCTX_UNK120C0 D_801C1B04_unknown
+#define MSGCTX_UNK120C2 D_801C1B08_unknown
+#define MSGCTX_UNK120C4 D_801C1B0C_unknown
+#define MSGCTX_UNK120C8 D_801C1B10_unknown
+#define MSGCTX_UNK120CA D_801C1B14_unknown
+#define MSGCTX_UNK120CC D_801C1B18_unknown
+#define MSGCTX_UNK120CE D_801C1B1C_unknown
+#define MSGCTX_UNK120D0 D_801C1B20_unknown
+#define MSGCTX_UNK120D2 D_801C1B24_unknown
+#endif
+
s16 sOcarinaButtonStepR = 0;
s16 sOcarinaButtonStepG = 0;
s16 sOcarinaButtonStepB = 0;
@@ -26,6 +71,19 @@ s16 sOcarinaButtonFlashTimer = 12;
s16 sOcarinaButtonFlashColorIndex = 1;
s16 D_801C6A94 = 0;
+#if MM_VERSION >= N64_US
+#define MSGCTX_UNK120D4 msgCtx->unk120D4
+#define MSGCTX_UNK120D6 msgCtx->unk120D6
+#else
+
+s16 D_801C1B40_unknown = 0;
+s16 D_801C1B44_unknown = 0;
+
+#define MSGCTX_UNK120D4 D_801C1B40_unknown
+#define MSGCTX_UNK120D6 D_801C1B44_unknown
+
+#endif
+
u8 gPageSwitchNextButtonStatus[][5] = {
{ BTN_ENABLED, BTN_ENABLED, BTN_DISABLED, BTN_ENABLED, BTN_ENABLED },
{ BTN_ENABLED, BTN_ENABLED, BTN_DISABLED, BTN_ENABLED, BTN_ENABLED },
@@ -544,34 +602,34 @@ void func_80148D64(PlayState* play) {
MessageContext* msgCtx = &play->msgCtx;
if (play->msgCtx.stickAdjY <= -30) {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2]--;
- if (msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] < '0') {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = '9';
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2]--;
+ if (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] < '0') {
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = '9';
}
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if (msgCtx->stickAdjY >= 30) {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2]++;
- if (msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] > '9') {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = '0';
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2]++;
+ if (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] > '9') {
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = '0';
}
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if ((msgCtx->stickAdjX >= 30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2++;
- if (msgCtx->unk120C2 > 2) {
- msgCtx->unk120C2 = 2;
+ MSGCTX_UNK120C2++;
+ if (MSGCTX_UNK120C2 > 2) {
+ MSGCTX_UNK120C2 = 2;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else if ((msgCtx->stickAdjX <= -30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2--;
- if (msgCtx->unk120C2 < 0) {
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120C2--;
+ if (MSGCTX_UNK120C2 < 0) {
+ MSGCTX_UNK120C2 = 0;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
@@ -579,33 +637,33 @@ void func_80148D64(PlayState* play) {
sAnalogStickHeld = false;
}
- msgCtx->rupeesSelected = (msgCtx->decodedBuffer.schar[msgCtx->unk120C0] - '0') * 100;
- msgCtx->rupeesSelected += (msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + 1] - '0') * 10;
- msgCtx->rupeesSelected += msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + 2] - '0';
+ msgCtx->rupeesSelected = (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0] - '0') * 100;
+ msgCtx->rupeesSelected += (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + 1] - '0') * 10;
+ msgCtx->rupeesSelected += msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + 2] - '0';
}
void func_80149048(PlayState* play) {
MessageContext* msgCtx = &play->msgCtx;
if (msgCtx->stickAdjY <= -30) {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2]--;
- if (msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] < '0') {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = '9';
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2]--;
+ if (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] < '0') {
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = '9';
}
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if (msgCtx->stickAdjY >= 30) {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2]++;
- if (msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] > '9') {
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = '0';
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2]++;
+ if (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] > '9') {
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = '0';
}
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
}
- msgCtx->rupeesSelected = (msgCtx->decodedBuffer.schar[msgCtx->unk120C0] - '0') * 10;
+ msgCtx->rupeesSelected = (msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0] - '0') * 10;
}
void func_801491DC(PlayState* play) {
@@ -613,36 +671,36 @@ void func_801491DC(PlayState* play) {
MessageContext* msgCtx = &play->msgCtx;
if (msgCtx->stickAdjY <= -30) {
- msgCtx->unk12054[msgCtx->unk120C2]--;
- if (msgCtx->unk12054[msgCtx->unk120C2] <= 0) {
- msgCtx->unk12054[msgCtx->unk120C2] = 5;
+ msgCtx->unk12054[MSGCTX_UNK120C2]--;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] <= 0) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 5;
}
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if (msgCtx->stickAdjY >= 30) {
- msgCtx->unk12054[msgCtx->unk120C2]++;
- if (msgCtx->unk12054[msgCtx->unk120C2] > 5) {
- msgCtx->unk12054[msgCtx->unk120C2] = 1;
+ msgCtx->unk12054[MSGCTX_UNK120C2]++;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] > 5) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 1;
}
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if ((msgCtx->stickAdjX >= 30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2++;
- if (msgCtx->unk120C2 > 4) {
- msgCtx->unk120C2 = 4;
+ MSGCTX_UNK120C2++;
+ if (MSGCTX_UNK120C2 > 4) {
+ MSGCTX_UNK120C2 = 4;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else if ((msgCtx->stickAdjX <= -30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2--;
- if (msgCtx->unk120C2 < 0) {
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120C2--;
+ if (MSGCTX_UNK120C2 < 0) {
+ MSGCTX_UNK120C2 = 0;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
@@ -656,36 +714,36 @@ void func_80149454(PlayState* play) {
MessageContext* msgCtx = &play->msgCtx;
if (msgCtx->stickAdjY <= -30) {
- msgCtx->unk12054[msgCtx->unk120C2]--;
- if (msgCtx->unk12054[msgCtx->unk120C2] < 0) {
- msgCtx->unk12054[msgCtx->unk120C2] = 9;
+ msgCtx->unk12054[MSGCTX_UNK120C2]--;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] < 0) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 9;
}
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if (msgCtx->stickAdjY >= 30) {
- msgCtx->unk12054[msgCtx->unk120C2]++;
- if (msgCtx->unk12054[msgCtx->unk120C2] > 9) {
- msgCtx->unk12054[msgCtx->unk120C2] = 0;
+ msgCtx->unk12054[MSGCTX_UNK120C2]++;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] > 9) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 0;
}
- msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadCharNES(play, msgCtx->decodedBuffer.schar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if ((msgCtx->stickAdjX >= 30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2++;
- if (msgCtx->unk120C2 > 2) {
- msgCtx->unk120C2 = 2;
+ MSGCTX_UNK120C2++;
+ if (MSGCTX_UNK120C2 > 2) {
+ MSGCTX_UNK120C2 = 2;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else if ((msgCtx->stickAdjX <= -30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2--;
- if (msgCtx->unk120C2 < 0) {
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120C2--;
+ if (MSGCTX_UNK120C2 < 0) {
+ MSGCTX_UNK120C2 = 0;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
@@ -699,36 +757,36 @@ void func_801496C8(PlayState* play) {
MessageContext* msgCtx = &play->msgCtx;
if (play->msgCtx.stickAdjY <= -30) {
- msgCtx->unk12054[msgCtx->unk120C2]--;
- if (msgCtx->unk12054[msgCtx->unk120C2] < 0) {
- msgCtx->unk12054[msgCtx->unk120C2] = 3;
+ msgCtx->unk12054[MSGCTX_UNK120C2]--;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] < 0) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 3;
}
- msgCtx->decodedBuffer.wchar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadChar(play, msgCtx->decodedBuffer.wchar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.wchar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadChar(play, msgCtx->decodedBuffer.wchar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if (msgCtx->stickAdjY >= 30) {
- msgCtx->unk12054[msgCtx->unk120C2]++;
- if (msgCtx->unk12054[msgCtx->unk120C2] >= 4) {
- msgCtx->unk12054[msgCtx->unk120C2] = 0;
+ msgCtx->unk12054[MSGCTX_UNK120C2]++;
+ if (msgCtx->unk12054[MSGCTX_UNK120C2] >= 4) {
+ msgCtx->unk12054[MSGCTX_UNK120C2] = 0;
}
- msgCtx->decodedBuffer.wchar[msgCtx->unk120C0 + msgCtx->unk120C2] = msgCtx->unk12054[msgCtx->unk120C2] + '0';
- Font_LoadChar(play, msgCtx->decodedBuffer.wchar[msgCtx->unk120C0 + msgCtx->unk120C2],
- msgCtx->unk120C4 + (msgCtx->unk120C2 << 7));
+ msgCtx->decodedBuffer.wchar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2] = msgCtx->unk12054[MSGCTX_UNK120C2] + '0';
+ Font_LoadChar(play, msgCtx->decodedBuffer.wchar[MSGCTX_UNK120C0 + MSGCTX_UNK120C2],
+ MSGCTX_UNK120C4 + (MSGCTX_UNK120C2 << 7));
Audio_PlaySfx(NA_SE_SY_RUPY_COUNT);
} else if ((msgCtx->stickAdjX >= 30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2++;
- if (msgCtx->unk120C2 > 5) {
- msgCtx->unk120C2 = 5;
+ MSGCTX_UNK120C2++;
+ if (MSGCTX_UNK120C2 > 5) {
+ MSGCTX_UNK120C2 = 5;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
} else if ((msgCtx->stickAdjX <= -30) && !sAnalogStickHeld) {
sAnalogStickHeld = true;
- msgCtx->unk120C2--;
- if (msgCtx->unk120C2 < 0) {
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120C2--;
+ if (MSGCTX_UNK120C2 < 0) {
+ MSGCTX_UNK120C2 = 0;
} else {
Audio_PlaySfx(NA_SE_SY_CURSOR);
}
@@ -1101,9 +1159,9 @@ void Message_DrawTextDefault(PlayState* play, Gfx** gfxP) {
if (play->msgCtx.itemId != MESSAGE_ITEM_NONE) {
Message_DrawItemIcon(play, &gfx);
}
- msgCtx->textColorR = msgCtx->unk120C8;
- msgCtx->textColorG = msgCtx->unk120CA;
- msgCtx->textColorB = msgCtx->unk120CC;
+ msgCtx->textColorR = MSGCTX_UNK120C8;
+ msgCtx->textColorG = MSGCTX_UNK120CA;
+ msgCtx->textColorB = MSGCTX_UNK120CC;
charTexIndex = 0;
@@ -1135,32 +1193,32 @@ void Message_DrawTextDefault(PlayState* play, Gfx** gfxP) {
if ((msgCtx->msgMode >= MSGMODE_NEW_CYCLE_0) && (msgCtx->msgMode <= MSGMODE_NEW_CYCLE_2) &&
(character == 0x2002)) {
msgCtx->textDrawPos = msgCtx->decodedTextLen;
- if (msgCtx->unk120D6) {
- msgCtx->unk120D4 += 25;
- if (msgCtx->unk120D4 >= 100) {
- msgCtx->unk120D6 = false;
+ if (MSGCTX_UNK120D6) {
+ MSGCTX_UNK120D4 += 25;
+ if (MSGCTX_UNK120D4 >= 100) {
+ MSGCTX_UNK120D6 = false;
}
} else {
- msgCtx->unk120D4 -= 25;
- if (msgCtx->unk120D4 <= -100) {
- msgCtx->unk120D6 = true;
+ MSGCTX_UNK120D4 -= 25;
+ if (MSGCTX_UNK120D4 <= -100) {
+ MSGCTX_UNK120D6 = true;
}
}
- if (D_801CFE74[(s16)(character - 0x2001)].r + msgCtx->unk120D4 < 0) {
+ if (D_801CFE74[(s16)(character - 0x2001)].r + MSGCTX_UNK120D4 < 0) {
msgCtx->textColorR = 0;
} else {
- msgCtx->textColorR = D_801CFE74[(s16)(character - 0x2001)].r + msgCtx->unk120D4;
+ msgCtx->textColorR = D_801CFE74[(s16)(character - 0x2001)].r + MSGCTX_UNK120D4;
}
- if (D_801CFE74[(s16)(character - 0x2001)].g + msgCtx->unk120D4 >= 255) {
+ if (D_801CFE74[(s16)(character - 0x2001)].g + MSGCTX_UNK120D4 >= 255) {
msgCtx->textColorG = D_801CFE74[(s16)(character - 0x2001)].g;
} else {
- msgCtx->textColorG = D_801CFE74[(s16)(character - 0x2001)].g + msgCtx->unk120D4;
+ msgCtx->textColorG = D_801CFE74[(s16)(character - 0x2001)].g + MSGCTX_UNK120D4;
}
- if (D_801CFE74[(s16)(character - 0x2001)].b + msgCtx->unk120D4 < 0) {
+ if (D_801CFE74[(s16)(character - 0x2001)].b + MSGCTX_UNK120D4 < 0) {
msgCtx->textColorB = 0;
} else {
- msgCtx->textColorB = D_801CFE74[(s16)(character - 0x2001)].b + msgCtx->unk120D4;
+ msgCtx->textColorB = D_801CFE74[(s16)(character - 0x2001)].b + MSGCTX_UNK120D4;
}
} else if (play->pauseCtx.bombersNotebookOpen) {
msgCtx->textColorR = sColorsBombersNotebookJPN[(s16)(character - 0x2001)].r;
@@ -1222,9 +1280,9 @@ void Message_DrawTextDefault(PlayState* play, Gfx** gfxP) {
msgCtx->textUnskippable = false;
msgCtx->msgBufPos++;
}
- msgCtx->unk120CE = msgCtx->textColorR;
- msgCtx->unk120D0 = msgCtx->textColorG;
- msgCtx->unk120D2 = msgCtx->textColorB;
+ MSGCTX_UNK120CE = msgCtx->textColorR;
+ MSGCTX_UNK120D0 = msgCtx->textColorG;
+ MSGCTX_UNK120D2 = msgCtx->textColorB;
}
*gfxP = gfx;
return;
@@ -2259,9 +2317,9 @@ void Message_Decode(PlayState* play) {
msgCtx->textDrawPos = msgCtx->decodedTextLen;
}
- msgCtx->unk120C8 = msgCtx->unk120CE;
- msgCtx->unk120CA = msgCtx->unk120D0;
- msgCtx->unk120CC = msgCtx->unk120D2;
+ MSGCTX_UNK120C8 = MSGCTX_UNK120CE;
+ MSGCTX_UNK120CA = MSGCTX_UNK120D0;
+ MSGCTX_UNK120CC = MSGCTX_UNK120D2;
break;
}
@@ -2403,11 +2461,11 @@ void Message_Decode(PlayState* play) {
Message_LoadChar(play, 0x9543, &charTexIndex, &spC0, decodedBufPos);
} else if (curChar == 0x20C) {
decodedBufPos++;
- msgCtx->unk120BE = spD2;
- msgCtx->unk120C0 = decodedBufPos;
- msgCtx->unk120C2 = 2;
+ MSGCTX_UNK120BE = spD2;
+ MSGCTX_UNK120C0 = decodedBufPos;
+ MSGCTX_UNK120C2 = 2;
msgCtx->rupeesSelected = 0;
- msgCtx->unk120C4 = charTexIndex;
+ MSGCTX_UNK120C4 = charTexIndex;
digits[0] = digits[1] = digits[2] = 0;
for (i = 0; i < 3; i++) {
@@ -2567,11 +2625,11 @@ void Message_Decode(PlayState* play) {
decodedBufPos--;
} else if (curChar == 0x220) {
decodedBufPos++;
- msgCtx->unk120BE = spD2;
- msgCtx->unk120C0 = decodedBufPos;
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120BE = spD2;
+ MSGCTX_UNK120C0 = decodedBufPos;
+ MSGCTX_UNK120C2 = 0;
msgCtx->rupeesSelected = 0;
- msgCtx->unk120C4 = charTexIndex;
+ MSGCTX_UNK120C4 = charTexIndex;
digits[0] = digits[1] = digits[2] = 0;
for (i = 0; i < 2; i++) {
Message_LoadChar(play, digits[i] + '0', &charTexIndex, &spC0, decodedBufPos);
@@ -2580,11 +2638,11 @@ void Message_Decode(PlayState* play) {
Message_LoadRupeesJPN(play, &decodedBufPos, &charTexIndex, &spC0);
} else if (curChar == 0x221) {
decodedBufPos++;
- msgCtx->unk120BE = spD2;
- msgCtx->unk120C0 = decodedBufPos;
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120BE = spD2;
+ MSGCTX_UNK120C0 = decodedBufPos;
+ MSGCTX_UNK120C2 = 0;
msgCtx->rupeesSelected = 0;
- msgCtx->unk120C4 = charTexIndex;
+ MSGCTX_UNK120C4 = charTexIndex;
for (i = 0; i < 5; i++) {
msgCtx->unk12054[i] = 1;
@@ -2613,11 +2671,11 @@ void Message_Decode(PlayState* play) {
Message_LoadOwlWarpText(play, &charTexIndex, &spC0, &decodedBufPos);
} else if (curChar == 0x225) {
decodedBufPos++;
- msgCtx->unk120BE = spD2;
- msgCtx->unk120C0 = decodedBufPos;
- msgCtx->unk120C2 = 0;
+ MSGCTX_UNK120BE = spD2;
+ MSGCTX_UNK120C0 = decodedBufPos;
+ MSGCTX_UNK120C2 = 0;
msgCtx->rupeesSelected = 0;
- msgCtx->unk120C4 = charTexIndex;
+ MSGCTX_UNK120C4 = charTexIndex;
for (i = 0; i < 3; i++) {
msgCtx->unk12054[i] = 1;
@@ -3054,7 +3112,9 @@ void Message_Decode(PlayState* play) {
} else if (msgCtx->textIsCredits) {
Message_DecodeCredits(play);
} else {
+#if MM_VERSION >= N64_US
Message_DecodeNES(play);
+#endif
}
}
@@ -3199,10 +3259,12 @@ void Message_OpenText(PlayState* play, u16 textId) {
DmaMgr_RequestSync(&font->msgBuf, SEGMENT_ROM_START(message_data_static) + font->messageStart,
font->messageEnd);
} else {
+#if MM_VERSION >= N64_US
Message_FindMessageNES(play, textId);
msgCtx->msgLength = font->messageEnd;
DmaMgr_RequestSync(&font->msgBuf, SEGMENT_ROM_START(message_data_static) + font->messageStart,
font->messageEnd);
+#endif
}
msgCtx->choiceNum = 0;
@@ -3227,9 +3289,9 @@ void Message_OpenText(PlayState* play, u16 textId) {
if ((msgCtx->textBoxType == TEXTBOX_TYPE_CLEAR) || (msgCtx->textBoxType == TEXTBOX_TYPE_NOTEBOOK_NOTIFICATION) ||
(play->pauseCtx.bombersNotebookOpen)) {
- msgCtx->unk120CE = msgCtx->unk120D0 = msgCtx->unk120D2 = 0;
+ MSGCTX_UNK120CE = MSGCTX_UNK120D0 = MSGCTX_UNK120D2 = 0;
} else {
- msgCtx->unk120CE = msgCtx->unk120D0 = msgCtx->unk120D2 = 0xFF;
+ MSGCTX_UNK120CE = MSGCTX_UNK120D0 = MSGCTX_UNK120D2 = 0xFF;
}
msgCtx->choiceIndex = 0;
@@ -3293,10 +3355,12 @@ void Message_PauseMenu_ShowDescription(PlayState* play, u16 textId, u8 textBoxPo
DmaMgr_RequestSync(&font->msgBuf, SEGMENT_ROM_START(message_data_static) + font->messageStart,
font->messageEnd);
} else {
+#if MM_VERSION >= N64_US
Message_FindMessageNES(play, textId);
msgCtx->msgLength = font->messageEnd;
DmaMgr_RequestSync(&font->msgBuf, SEGMENT_ROM_START(message_data_static) + font->messageStart,
font->messageEnd);
+#endif
}
msgCtx->choiceNum = 0;
msgCtx->textUnskippable = false;
@@ -3323,8 +3387,8 @@ void Message_PauseMenu_ShowDescription(PlayState* play, u16 textId, u8 textBoxPo
msgCtx->stateTimer = 0;
msgCtx->textDelayTimer = 0;
play->msgCtx.ocarinaMode = OCARINA_MODE_NONE;
- msgCtx->unk120D2 = 0xFF;
- msgCtx->unk120CE = msgCtx->unk120D0 = msgCtx->unk120D2;
+ MSGCTX_UNK120D2 = 0xFF;
+ MSGCTX_UNK120CE = MSGCTX_UNK120D0 = MSGCTX_UNK120D2;
}
void Message_StartTextbox(PlayState* play, u16 textId, Actor* actor) {
@@ -3373,7 +3437,7 @@ void Message_DisplaySceneTitleCard(PlayState* play, u16 textId) {
msgCtx->msgLength = 0;
Message_OpenText(play, textId);
Message_SetTextboxColor(play);
- Message_DecodeNES(play);
+ MESSAGE_DECODE(play);
msgCtx->msgMode = MSGMODE_SCENE_TITLE_CARD_FADE_IN_BACKGROUND;
msgCtx->textDelayTimer = 0;
msgCtx->textboxColorAlphaCurrent = msgCtx->textboxColorAlphaTarget = msgCtx->textColorAlpha = 0;
@@ -4086,7 +4150,9 @@ void Message_DrawText(PlayState* play, Gfx** gfxP) {
} else if (play->msgCtx.textIsCredits) {
Message_DrawTextCredits(play, gfxP);
} else {
+#if MM_VERSION >= N64_US
Message_DrawTextNES(play, gfxP, 0);
+#endif
}
}
@@ -4115,7 +4181,7 @@ void Message_DrawSceneTitleCard(PlayState* play, Gfx** gfxP) {
msgCtx->unk11FF8 = XREG(75);
}
msgCtx->unk11FFA = XREG(74);
- Message_DrawTextNES(play, &gfx, 0);
+ MESSAGE_DRAW_TEXT(play, &gfx, 0);
*gfxP = gfx++;
}
@@ -4243,9 +4309,9 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) {
if (msgCtx->textDelay != 0) {
msgCtx->textDrawPos += msgCtx->textDelay;
}
- Message_DrawTextNES(play, &gfx, 0);
+ MESSAGE_DRAW_TEXT(play, &gfx, 0);
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
- Message_DrawTextNES(play, &gfx, (s32)msgCtx->textDrawPos);
+ MESSAGE_DRAW_TEXT(play, &gfx, (s32)msgCtx->textDrawPos);
}
} else if (msgCtx->textIsCredits) {
Message_DrawTextCredits(play, &gfx);
@@ -4253,9 +4319,9 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) {
if (msgCtx->textDelay != 0) {
msgCtx->textDrawPos += msgCtx->textDelay;
}
- Message_DrawTextNES(play, &gfx, 0);
+ MESSAGE_DRAW_TEXT(play, &gfx, 0);
if (msgCtx->msgMode == MSGMODE_TEXT_DISPLAYING) {
- Message_DrawTextNES(play, &gfx, (s32)msgCtx->textDrawPos);
+ MESSAGE_DRAW_TEXT(play, &gfx, (s32)msgCtx->textDrawPos);
}
}
break;
@@ -4266,7 +4332,7 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) {
case MSGMODE_OWL_SAVE_0:
case MSGMODE_OWL_SAVE_1:
case MSGMODE_OWL_SAVE_2:
- Message_DrawTextNES(play, &gfx, 0);
+ MESSAGE_DRAW_TEXT(play, &gfx, 0);
break;
case MSGMODE_TEXT_AWAIT_INPUT:
@@ -4997,17 +5063,17 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) {
case MSGMODE_TEXT_DONE:
switch (msgCtx->textboxEndType) {
case TEXTBOX_ENDTYPE_INPUT_BANK:
- temp_v0_33 = msgCtx->unk120BE;
+ temp_v0_33 = MSGCTX_UNK120BE;
temp = msgCtx->unk11FFA + (msgCtx->unk11FFC * temp_v0_33);
func_80147F18(play, &gfx,
msgCtx->unk11F1A[temp_v0_33] +
- (s32)(16.0f * msgCtx->textCharScale * (msgCtx->unk120C2 + 5)) - 1,
+ (s32)(16.0f * msgCtx->textCharScale * (MSGCTX_UNK120C2 + 5)) - 1,
temp);
func_80148D64(play);
break;
case TEXTBOX_ENDTYPE_INPUT_DOGGY_RACETRACK_BET:
- temp_v0_33 = msgCtx->unk120BE;
+ temp_v0_33 = MSGCTX_UNK120BE;
temp = msgCtx->unk11FFA + (msgCtx->unk11FFC * temp_v0_33);
func_80148558(play, &gfx,
msgCtx->unk11F1A[temp_v0_33] + (s32)(16.0f * msgCtx->textCharScale * 5.0f) - 1,
@@ -5016,31 +5082,31 @@ void Message_DrawMain(PlayState* play, Gfx** gfxP) {
break;
case TEXTBOX_ENDTYPE_INPUT_BOMBER_CODE:
- temp_v0_33 = msgCtx->unk120BE;
+ temp_v0_33 = MSGCTX_UNK120BE;
temp = msgCtx->unk11FFA + (msgCtx->unk11FFC * temp_v0_33);
func_80147F18(play, &gfx,
msgCtx->unk11F1A[temp_v0_33] +
- (s32)(16.0f * msgCtx->textCharScale * (msgCtx->unk120C2 + 5)) - 1,
+ (s32)(16.0f * msgCtx->textCharScale * (MSGCTX_UNK120C2 + 5)) - 1,
temp);
func_801491DC(play);
break;
case TEXTBOX_ENDTYPE_INPUT_LOTTERY_CODE:
- temp_v0_33 = msgCtx->unk120BE;
+ temp_v0_33 = MSGCTX_UNK120BE;
temp = msgCtx->unk11FFA + (msgCtx->unk11FFC * temp_v0_33);
func_80147F18(play, &gfx,
msgCtx->unk11F1A[temp_v0_33] +
- (s32)(16.0f * msgCtx->textCharScale * (msgCtx->unk120C2 + 5)) - 1,
+ (s32)(16.0f * msgCtx->textCharScale * (MSGCTX_UNK120C2 + 5)) - 1,
temp);
func_80149454(play);
break;
case TEXTBOX_ENDTYPE_64:
- temp_v0_33 = msgCtx->unk120BE;
+ temp_v0_33 = MSGCTX_UNK120BE;
temp = msgCtx->unk11FFA + (msgCtx->unk11FFC * temp_v0_33);
func_80147F18(play, &gfx,
msgCtx->unk11F1A[temp_v0_33] +
- (s32)(16.0f * msgCtx->textCharScale * (msgCtx->unk120C2 + 4)) - 6,
+ (s32)(16.0f * msgCtx->textCharScale * (MSGCTX_UNK120C2 + 4)) - 6,
temp);
func_801496C8(play);
break;
@@ -5595,8 +5661,8 @@ void Message_Update(PlayState* play) {
Audio_PlaySfx_MessageDecide();
msgCtx->msgMode = MSGMODE_NEW_CYCLE_0;
msgCtx->decodedTextLen -= 3;
- msgCtx->unk120D6 = 0;
- msgCtx->unk120D4 = 0;
+ MSGCTX_UNK120D6 = 0;
+ MSGCTX_UNK120D4 = 0;
} else {
Audio_PlaySfx_MessageCancel();
play->msgCtx.ocarinaMode = OCARINA_MODE_END;
@@ -6061,16 +6127,19 @@ void Message_Init(PlayState* play) {
msgCtx->textboxX = 52;
msgCtx->textboxY = 36;
msgCtx->ocarinaSongEffectActive = false;
- msgCtx->unk120BE = 0;
- msgCtx->unk120C0 = 0;
- msgCtx->unk120C2 = 0;
- msgCtx->unk120C4 = 0;
- msgCtx->unk120C8 = 0;
- msgCtx->unk120CA = 0;
- msgCtx->unk120CC = 0;
- msgCtx->unk120CE = 0;
- msgCtx->unk120D0 = 0;
- msgCtx->unk120D2 = 0;
- msgCtx->unk120D4 = 0;
- msgCtx->unk120D6 = 0;
+
+#if MM_VERSION >= N64_US
+ MSGCTX_UNK120BE = 0;
+ MSGCTX_UNK120C0 = 0;
+ MSGCTX_UNK120C2 = 0;
+ MSGCTX_UNK120C4 = 0;
+ MSGCTX_UNK120C8 = 0;
+ MSGCTX_UNK120CA = 0;
+ MSGCTX_UNK120CC = 0;
+ MSGCTX_UNK120CE = 0;
+ MSGCTX_UNK120D0 = 0;
+ MSGCTX_UNK120D2 = 0;
+ MSGCTX_UNK120D4 = 0;
+ MSGCTX_UNK120D6 = 0;
+#endif
}
diff --git a/src/code/z_sram_JPN.c b/src/code/z_sram_JPN.c
new file mode 100644
index 000000000..c6790a1a5
--- /dev/null
+++ b/src/code/z_sram_JPN.c
@@ -0,0 +1,2042 @@
+#include "z64save.h"
+#include "global.h"
+
+#include "sys_flashrom.h"
+#include "z64horse.h"
+#include "overlays/gamestates/ovl_file_choose/z_file_select.h"
+
+void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages);
+void func_80147314(SramContext* sramCtx, s32 fileNum);
+void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2);
+
+#define CHECK_NEWF(newf) \
+ ((newf)[0] != 'Z' || (newf)[1] != 'E' || (newf)[2] != 'L' || (newf)[3] != 'D' || (newf)[4] != 'A' || \
+ (newf)[5] != '3')
+
+typedef struct PersistentCycleSceneFlags {
+ /* 0x0 */ u32 switch0;
+ /* 0x4 */ u32 switch1;
+ /* 0x8 */ u32 chest;
+ /* 0xC */ u32 collectible;
+} PersistentCycleSceneFlags; // size = 0x10
+
+#define PERSISTENT_CYCLE_FLAGS_SET(switch0, switch1, chest, collectible) { switch0, switch1, chest, collectible },
+#define PERSISTENT_CYCLE_FLAGS_NONE PERSISTENT_CYCLE_FLAGS_SET(0, 0, 0, 0)
+
+#define DEFINE_SCENE(_name, _enumValue, _textId, _drawConfig, _restrictionFlags, persistentCycleFlags) \
+ persistentCycleFlags
+#define DEFINE_SCENE_UNSET(_enumValue) PERSISTENT_CYCLE_FLAGS_NONE
+
+/**
+ * Array of bitwise flags which won't be turned off on a cycle reset (will persist between cycles)
+ */
+PersistentCycleSceneFlags sPersistentCycleSceneFlags[SCENE_MAX] = {
+#include "tables/scene_table.h"
+};
+
+#undef DEFINE_SCENE
+#undef DEFINE_SCENE_UNSET
+
+// Each flag has 2 bits to store persistence over the three-day reset cycle
+// Only 1 of these bits need to be set to persist (Values 1, 2, 3).
+// Therefore, the final game does not distinguish between these two macros in use
+#define PERSISTENT_WEEKEVENTREG(flag) (3 << (2 * BIT_FLAG_TO_SHIFT(flag)))
+#define PERSISTENT_WEEKEVENTREG_ALT(flag) (2 << (2 * BIT_FLAG_TO_SHIFT(flag)))
+
+// weekEventReg flags which will be not be cleared on a cycle reset
+//! @note The index of the flag in this array must be the same to its index in the WeekeventReg array
+//! Only the mask is read from the `PERSISTENT_` macros.
+u16 sPersistentCycleWeekEventRegs[ARRAY_COUNT(gSaveContext.save.saveInfo.weekEventReg)] = {
+ /* 0 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_TERMINA_FIELD) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_IKANA_GRAVEYARD) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_ROMANI_RANCH) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_GORMAN_TRACK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_MOUNTAIN_VILLAGE_WINTER) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_GORON_SHRINE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_SNOWHEAD),
+ /* 1 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_SOUTHERN_SWAMP_POISONED) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_WOODFALL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_DEKU_PALACE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_GREAT_BAY_COAST) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_PIRATES_FORTRESS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_ZORA_HALL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_WATERFALL_RAPIDS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_IKANA_CANYON),
+ /* 2 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_IKANA_CASTLE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_STONE_TOWER) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_STONE_TOWER_INVERTED) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_EAST_CLOCK_TOWN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_WEST_CLOCK_TOWN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_NORTH_CLOCK_TOWN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_WOODFALL_TEMPLE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_SNOWHEAD_TEMPLE),
+ /* 3 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_PIRATES_FORTRESS_EXTERIOR) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_STONE_TOWER_TEMPLE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_STONE_TOWER_TEMPLE_INVERTED) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_THE_MOON) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_MOON_DEKU_TRIAL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_MOON_GORON_TRIAL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_MOON_ZORA_TRIAL) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_03_80),
+ /* 4 */ 0,
+ /* 5 */ 0,
+ /* 6 */ 0,
+ /* 7 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_ENTERED_WOODFALL_TEMPLE_PRISON),
+ /* 8 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_DOGGY_RACETRACK_HEART_PIECE),
+ /* 9 */ 0,
+ /* 10 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_BANK_WALLET_UPGRADE),
+ /* 11 */ 0,
+ /* 12 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_KOTAKE_BOTTLE),
+ /* 13 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_OCEANSIDE_WALLET_UPGRADE),
+ /* 14 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_DEKU_PLAYGROUND_HEART_PIECE),
+ /* 15 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_15_20),
+ /* 16 */ 0,
+ /* 17 */ 0,
+ /* 18 */ 0,
+ /* 19 */ 0,
+ /* 20 */ 0,
+ /* 21 */ 0,
+ /* 22 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_ALIENS_BOTTLE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_HONEY_AND_DARLING_HEART_PIECE),
+ /* 23 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_GREAT_SPIN_ATTACK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_BEAVER_RACE_BOTTLE),
+ /* 24 */ PERSISTENT_WEEKEVENTREG_ALT(WEEKEVENTREG_24_02) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_24_80),
+ /* 25 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_BEAVER_BROS_HEART_PIECE),
+ /* 26 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_26_40),
+ /* 27 */ 0,
+ /* 28 */ 0,
+ /* 29 */ 0,
+ /* 30 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_30_10) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_30_20) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_30_40) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_30_80),
+ /* 31 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_31_01) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_31_02) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_31_04) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_31_20),
+ /* 32 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_SEAHORSE_HEART_PIECE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_SWAMP_SHOOTING_GALLERY_HEART_PIECE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_TOWN_SHOOTING_GALLERY_HEART_PIECE),
+ /* 33 */ 0,
+ /* 34 */ 0,
+ /* 35 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_CLOCK_TOWN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_WOODFALL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_SNOWHEAD) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_ROMANI_RANCH) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_GREAT_BAY) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_TINGLE_MAP_BOUGHT_STONE_TOWER) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_FROG_CHOIR_HEART_PIECE),
+ /* 36 */ 0,
+ /* 37 */ 0,
+ /* 38 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_38_20),
+ /* 39 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_EVAN_HEART_PIECE),
+ /* 40 */ 0,
+ /* 41 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_GORON_RACE_BOTTLE),
+ /* 42 */ 0,
+ /* 43 */ 0,
+ /* 44 */ 0,
+ /* 45 */ 0,
+ /* 46 */ 0,
+ /* 47 */ 0,
+ /* 48 */ 0,
+ /* 49 */ 0,
+ /* 50 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_50_02) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_50_04),
+ /* 51 */ PERSISTENT_WEEKEVENTREG_ALT(WEEKEVENTREG_51_04),
+ /* 52 */ 0,
+ /* 53 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_BUSINESS_SCRUB_HEART_PIECE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_53_40),
+ /* 54 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_SPIRIT_HOUSE_HEART_PIECE),
+ /* 55 */ 0,
+ /* 56 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MARINE_RESEARCH_LAB_FISH_HEART_PIECE),
+ /* 57 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_57_08),
+ /* 58 */ 0,
+ /* 59 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_59_04) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_BANK_HEART_PIECE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_SWAMP_SHOOTING_GALLERY_QUIVER_UPGRADE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_TOWN_SHOOTING_GALLERY_QUIVER_UPGRADE),
+ /* 60 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_MAYOR_HEART_PIECE),
+ /* 61 */ 0,
+ /* 62 */ 0,
+ /* 63 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_SWORDSMANS_SCHOOL_HEART_PIECE),
+ /* 64 */ 0,
+ /* 65 */ 0,
+ /* 66 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_ANJU) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_KAFEI) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_CURIOSITY_SHOP_MAN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_BOMB_SHOP_LADY) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_ROMANI) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_CREMIA) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_MAYOR_DOTOUR) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_MADAME_AROMA),
+ /* 67 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_TOTO) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_GORMAN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_POSTMAN) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_ROSA_SISTERS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_TOILET_HAND) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_ANJUS_GRANDMOTHER) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_KAMARO) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_GROG),
+ /* 68 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_GORMAN_BROTHERS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_SHIRO) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_GURU_GURU) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_MET_BOMBERS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_ROOM_KEY) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_PROMISED_MIDNIGHT_MEETING) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_PROMISED_TO_MEET_KAFEI) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_LETTER_TO_KAFEI),
+ /* 69 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_DEPOSITED_LETTER_TO_KAFEI) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_PENDANT_OF_MEMORIES) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_DELIVERED_PENDANT_OF_MEMORIES) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_ESCAPED_SAKONS_HIDEOUT) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_PROMISED_TO_HELP_WITH_ALIENS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_DEFENDED_AGAINST_ALIENS) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_ALIENS_BOTTLE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_ESCORTED_CREMIA),
+ /* 70 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_ROMANIS_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_KEATON_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_PRIORITY_MAIL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_DELIVERED_PRIORITY_MAIL) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_LEARNED_SECRET_CODE) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_BOMBERS_NOTEBOOK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_MAYOR_HP) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_ROSA_SISTERS_HP),
+ /* 71 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_TOILET_HAND_HP) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_GRANDMA_SHORT_STORY_HP) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_GRANDMA_LONG_STORY_HP) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_POSTMAN_HP) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_KAFEIS_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_ALL_NIGHT_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_BUNNY_HOOD) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_GAROS_MASK),
+ /* 72 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_CIRCUS_LEADERS_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_POSTMANS_HAT) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_COUPLES_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_BLAST_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_KAMAROS_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_STONE_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_BOMBERS_NOTEBOOK_EVENT_RECEIVED_BREMEN_MASK) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_72_80),
+ /* 73 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_73_08),
+ /* 74 */ 0,
+ /* 75 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_ROSA_SISTERS_HEART_PIECE),
+ /* 76 */ 0,
+ /* 77 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_POSTMAN_COUNTING_GAME_HEART_PIECE),
+ /* 78 */ 0,
+ /* 79 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_KEATON_HEART_PIECE),
+ /* 80 */ 0,
+ /* 81 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_81_08),
+ /* 82 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_FISHERMANS_JUMPING_GAME_HEART_PIECE),
+ /* 83 */ 0,
+ /* 84 */ 0,
+ /* 85 */ 0,
+ /* 86 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_86_80),
+ /* 87 */
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_04) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_08) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_10) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_20) |
+ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_40) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_87_80),
+ /* 88 */ 0,
+ /* 89 */ 0,
+ /* 90 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_RECEIVED_GOSSIP_STONE_GROTTO_HEART_PIECE),
+ /* 91 */ 0,
+ /* 92 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_92_80),
+ /* 93 */ PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_93_04) | PERSISTENT_WEEKEVENTREG(WEEKEVENTREG_93_08),
+ /* 94 */ 0,
+ /* 95 */ 0,
+ /* 96 */ 0,
+ /* 97 */ 0,
+ /* 98 */ 0,
+ /* 99 */ 0,
+};
+
+// Unused remnant values from OoT. Not the correct sizes in MM.
+#define OOT_SAVECONTEXT_SIZE 0x1428
+#define OOT_SLOT_SIZE (OOT_SAVECONTEXT_SIZE + 0x28)
+#define OOT_SRAM_HEADER_SIZE 0x10
+#define OOT_SLOT_OFFSET(index) (OOT_SRAM_HEADER_SIZE + 0x10 + (index * OOT_SLOT_SIZE))
+
+// used in other files
+u32 gSramSlotOffsets[] = {
+ OOT_SLOT_OFFSET(0),
+ OOT_SLOT_OFFSET(1),
+ OOT_SLOT_OFFSET(2),
+ // the latter three saves are backup saves for the former saves (in OoT)
+ OOT_SLOT_OFFSET(3),
+ OOT_SLOT_OFFSET(4),
+ OOT_SLOT_OFFSET(5),
+};
+
+u8 gAmmoItems[ITEM_NUM_SLOTS] = {
+ ITEM_NONE, // SLOT_OCARINA
+ ITEM_BOW, // SLOT_BOW
+ ITEM_NONE, // SLOT_ARROW_FIRE
+ ITEM_NONE, // SLOT_ARROW_ICE
+ ITEM_NONE, // SLOT_ARROW_LIGHT
+ ITEM_NONE, // SLOT_TRADE_DEED
+ ITEM_BOMB, // SLOT_BOMB
+ ITEM_BOMBCHU, // SLOT_BOMBCHU
+ ITEM_DEKU_STICK, // SLOT_DEKU_STICK
+ ITEM_DEKU_NUT, // SLOT_DEKU_NUT
+ ITEM_MAGIC_BEANS, // SLOT_MAGIC_BEANS
+ ITEM_NONE, // SLOT_TRADE_KEY_MAMA
+ ITEM_POWDER_KEG, // SLOT_POWDER_KEG
+ ITEM_PICTOGRAPH_BOX, // SLOT_PICTOGRAPH_BOX
+ ITEM_NONE, // SLOT_LENS_OF_TRUTH
+ ITEM_NONE, // SLOT_HOOKSHOT
+ ITEM_NONE, // SLOT_SWORD_GREAT_FAIRY
+ ITEM_NONE, // SLOT_TRADE_COUPLE
+ ITEM_NONE, // SLOT_BOTTLE_1
+ ITEM_NONE, // SLOT_BOTTLE_2
+ ITEM_NONE, // SLOT_BOTTLE_3
+ ITEM_NONE, // SLOT_BOTTLE_4
+ ITEM_NONE, // SLOT_BOTTLE_5
+ ITEM_NONE, // SLOT_BOTTLE_6
+};
+
+// Stores flash start page number
+s32 gFlashSaveStartPages[] = {
+ 0, // File 1 New Cycle Save
+ 0x40, // File 1 New Cycle Save Backup
+ 0x80, // File 2 New Cycle Save
+ 0xC0, // File 2 New Cycle Save Backup
+ 0x100, // File 1 Owl Save
+ 0x180, // File 1 Owl Save Backup
+ 0x200, // File 2 Owl Save
+ 0x280, // File 2 Owl Save Backup
+ 0x300, // Sram Header (SaveOptions)
+ 0x380, // Sram Header Backup (SaveOptions)
+};
+
+// Flash rom number of pages
+s32 gFlashSaveNumPages[] = {
+ 0x40, // File 1 New Cycle Save
+ 0x40, // File 1 New Cycle Save Backup
+ 0x40, // File 2 New Cycle Save
+ 0x40, // File 2 New Cycle Save Backup
+ 0x80, // File 1 Owl Save
+ 0x80, // File 1 Owl Save Backup
+ 0x80, // File 2 Owl Save
+ 0x80, // File 2 Owl Save Backup
+ 1, // Sram Header (SaveOptions)
+ 1, // Sram Header Backup (SaveOptions)
+};
+
+// Flash rom number of pages on very first time Player enters South Clock Town from the Clock Tower
+s32 gFlashSpecialSaveNumPages[] = {
+ 0x80, // File 1 New Cycle Save
+ 0x80, // File 1 New Cycle Save Backup
+ 0x80, // File 2 New Cycle Save
+ 0x80, // File 2 New Cycle Save Backup
+ 0x80, // File 1 Owl Save
+ 0x80, // File 1 Owl Save Backup
+ 0x80, // File 2 Owl Save
+ 0x80, // File 2 Owl Save Backup
+ 1, // Sram Header (SaveOptions)
+ 1, // Sram Header Backup (SaveOptions)
+};
+
+// Owl Save flash rom start page number
+s32 gFlashOwlSaveStartPages[] = {
+ 0x100, // File 1 Owl Save
+ 0x180, // File 1 Owl Save Backup
+ 0x200, // File 2 Owl Save
+ 0x280, // File 2 Owl Save Backup
+};
+
+// Owl Save flash rom number of pages
+s32 gFlashOwlSaveNumPages[] = {
+ 0x80, // File 1 Owl Save
+ 0x80, // File 1 Owl Save Backup
+ 0x80, // File 2 Owl Save
+ 0x80, // File 2 Owl Save Backup
+};
+
+// Save Options Sram Header flash rom start page number
+s32 gFlashOptionsSaveStartPages[] = {
+ 0x300, // Sram Header (SaveOptions)
+ 0x380, // Sram Header Backup (SaveOptions)
+};
+
+// Save Options Sram Header flash rom number of pages
+s32 gFlashOptionsSaveNumPages[] = {
+ 1, // Sram Header (SaveOptions)
+ 1, // Sram Header Backup (SaveOptions)
+};
+
+// Flash rom actual size needed
+s32 gFlashSaveSizes[] = {
+ sizeof(Save), // size = 0x100C - File 1 New Cycle Save
+ sizeof(Save), // size = 0x100C - File 1 New Cycle Save Backup
+ sizeof(Save), // size = 0x100C - File 2 New Cycle Save
+ sizeof(Save), // size = 0x100C - File 2 New Cycle Save Backup
+ offsetof(SaveContext, fileNum), // size = 0x3CA0 - File 1 Owl Save
+ offsetof(SaveContext, fileNum), // size = 0x3CA0 - File 1 Owl Save Backup
+ offsetof(SaveContext, fileNum), // size = 0x3CA0 - File 2 Owl Save
+ offsetof(SaveContext, fileNum), // size = 0x3CA0 - File 2 Owl Save Backup
+};
+
+// Bit Flag array in which sBitFlags8[n] is (1 << n)
+u8 sBitFlags8[] = {
+ (1 << 0), (1 << 1), (1 << 2), (1 << 3), (1 << 4), (1 << 5), (1 << 6), (1 << 7),
+};
+
+u16 D_801F6AF0;
+u8 D_801F6AF2;
+
+void Sram_ActivateOwl(u8 owlWarpId) {
+ SET_OWL_STATUE_ACTIVATED(owlWarpId);
+
+ if (gSaveContext.save.saveInfo.playerData.owlWarpId == OWL_WARP_NONE) {
+ gSaveContext.save.saveInfo.playerData.owlWarpId = owlWarpId;
+ }
+}
+
+void Sram_ClearHighscores(void) {
+ HS_SET_BOAT_ARCHERY_HIGH_SCORE(19);
+ HS_SET_HIGH_SCORE_3_LOWER(10);
+ HS_SET_HORSE_BACK_BALLOON_TIME(SECONDS_TO_TIMER(60));
+ HS_SET_TOWN_SHOOTING_GALLERY_HIGH_SCORE(39);
+ HS_SET_SWAMP_SHOOTING_GALLERY_HIGH_SCORE(10);
+
+ gSaveContext.save.saveInfo.dekuPlaygroundHighScores[0] = SECONDS_TO_TIMER(75);
+ gSaveContext.save.saveInfo.dekuPlaygroundHighScores[1] = SECONDS_TO_TIMER(75);
+ gSaveContext.save.saveInfo.dekuPlaygroundHighScores[2] = SECONDS_TO_TIMER(76);
+}
+
+/**
+ * Clears specific weekEventReg flags. Used by the "Dawn of the First Day" message
+ */
+void Sram_ClearFlagsAtDawnOfTheFirstDay(void) {
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_55_02);
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_90_01);
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_89_40);
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_89_08);
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_85_80);
+}
+
+/**
+ * Used by Song of Time (when clicking "Yes") and (indirectly) by the "Dawn of the New Day" cutscene
+ */
+void Sram_SaveEndOfCycle(PlayState* play) {
+ s16 sceneId;
+ s32 j;
+ s32 i;
+ u8 slot;
+ u8 item;
+
+ gSaveContext.save.timeSpeedOffset = 0;
+ gSaveContext.save.eventDayCount = 0;
+ gSaveContext.save.day = 0;
+ gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;
+
+ gSaveContext.save.saveInfo.playerData.threeDayResetCount++;
+ if (gSaveContext.save.saveInfo.playerData.threeDayResetCount > 999) {
+ gSaveContext.save.saveInfo.playerData.threeDayResetCount = 999;
+ }
+
+ sceneId = Play_GetOriginalSceneId(play->sceneId);
+ Play_SaveCycleSceneFlags(play);
+
+ play->actorCtx.sceneFlags.chest &= sPersistentCycleSceneFlags[sceneId].chest;
+ play->actorCtx.sceneFlags.switches[0] &= sPersistentCycleSceneFlags[sceneId].switch0;
+ play->actorCtx.sceneFlags.switches[1] &= sPersistentCycleSceneFlags[sceneId].switch1;
+ play->actorCtx.sceneFlags.collectible[0] &= sPersistentCycleSceneFlags[sceneId].collectible;
+ play->actorCtx.sceneFlags.clearedRoom = 0;
+
+ for (i = 0; i < SCENE_MAX; i++) {
+ gSaveContext.cycleSceneFlags[i].switch0 =
+ ((void)0, gSaveContext.cycleSceneFlags[i].switch0) & sPersistentCycleSceneFlags[i].switch0;
+ gSaveContext.cycleSceneFlags[i].switch1 =
+ ((void)0, gSaveContext.cycleSceneFlags[i].switch1) & sPersistentCycleSceneFlags[i].switch1;
+ gSaveContext.cycleSceneFlags[i].chest =
+ ((void)0, gSaveContext.cycleSceneFlags[i].chest) & sPersistentCycleSceneFlags[i].chest;
+ gSaveContext.cycleSceneFlags[i].collectible =
+ ((void)0, gSaveContext.cycleSceneFlags[i].collectible) & sPersistentCycleSceneFlags[i].collectible;
+ gSaveContext.cycleSceneFlags[i].clearedRoom = 0;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].unk_14 = 0;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].rooms = 0;
+ }
+
+ for (; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.cycleSceneFlags[i].chest = 0;
+ gSaveContext.cycleSceneFlags[i].switch0 = 0;
+ gSaveContext.cycleSceneFlags[i].switch1 = 0;
+ gSaveContext.cycleSceneFlags[i].clearedRoom = 0;
+ gSaveContext.cycleSceneFlags[i].collectible = 0;
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.masksGivenOnMoon); i++) {
+ gSaveContext.masksGivenOnMoon[i] = 0;
+ }
+
+ if (CHECK_WEEKEVENTREG(WEEKEVENTREG_84_20)) {
+ Inventory_DeleteItem(ITEM_MASK_FIERCE_DEITY, SLOT(ITEM_MASK_FIERCE_DEITY));
+ }
+
+ for (i = 0; i < ARRAY_COUNT(sPersistentCycleWeekEventRegs); i++) {
+ u16 isPersistentBits = sPersistentCycleWeekEventRegs[i];
+
+ for (j = 0; j < ARRAY_COUNT(sBitFlags8); j++) {
+ if (!(isPersistentBits & 3)) {
+ gSaveContext.save.saveInfo.weekEventReg[i] =
+ ((void)0, gSaveContext.save.saveInfo.weekEventReg[i]) & (0xFF ^ sBitFlags8[j]);
+ }
+ isPersistentBits >>= 2;
+ }
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
+ gSaveContext.eventInf[i] = 0;
+ }
+
+ CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_RUPEES);
+ CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_BOMB_AMMO);
+ CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_NUT_AMMO);
+ CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_STICK_AMMO);
+ CLEAR_EVENTINF(EVENTINF_THREEDAYRESET_LOST_ARROW_AMMO);
+
+ if (gSaveContext.save.saveInfo.playerData.rupees != 0) {
+ SET_EVENTINF(EVENTINF_THREEDAYRESET_LOST_RUPEES);
+ }
+
+ if (INV_CONTENT(ITEM_BOMB) == ITEM_BOMB) {
+ item = INV_CONTENT(ITEM_BOMB);
+ if (AMMO(item) != 0) {
+ SET_EVENTINF(EVENTINF_THREEDAYRESET_LOST_BOMB_AMMO);
+ }
+ }
+ if (INV_CONTENT(ITEM_DEKU_NUT) == ITEM_DEKU_NUT) {
+ item = INV_CONTENT(ITEM_DEKU_NUT);
+ if (AMMO(item) != 0) {
+ SET_EVENTINF(EVENTINF_THREEDAYRESET_LOST_NUT_AMMO);
+ }
+ }
+ if (INV_CONTENT(ITEM_DEKU_STICK) == ITEM_DEKU_STICK) {
+ item = INV_CONTENT(ITEM_DEKU_STICK);
+ if (AMMO(item) != 0) {
+ SET_EVENTINF(EVENTINF_THREEDAYRESET_LOST_STICK_AMMO);
+ }
+ }
+ if (INV_CONTENT(ITEM_BOW) == ITEM_BOW) {
+ item = INV_CONTENT(ITEM_BOW);
+ if (AMMO(item) != 0) {
+ SET_EVENTINF(EVENTINF_THREEDAYRESET_LOST_ARROW_AMMO);
+ }
+ }
+
+ for (i = 0; i < ITEM_NUM_SLOTS; i++) {
+ if (gAmmoItems[i] != ITEM_NONE) {
+ if ((gSaveContext.save.saveInfo.inventory.items[i] != ITEM_NONE) && (i != SLOT_PICTOGRAPH_BOX)) {
+ item = gSaveContext.save.saveInfo.inventory.items[i];
+ AMMO(item) = 0;
+ }
+ }
+ }
+
+ for (i = SLOT_BOTTLE_1; i <= SLOT_BOTTLE_6; i++) {
+ // Check for all bottled items
+ if (gSaveContext.save.saveInfo.inventory.items[i] >= ITEM_POTION_RED) {
+ if (gSaveContext.save.saveInfo.inventory.items[i] <= ITEM_OBABA_DRINK) {
+ for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++) {
+ if (GET_CUR_FORM_BTN_ITEM(j) == gSaveContext.save.saveInfo.inventory.items[i]) {
+ SET_CUR_FORM_BTN_ITEM(j, ITEM_BOTTLE);
+ Interface_LoadItemIconImpl(play, j);
+ }
+ }
+ gSaveContext.save.saveInfo.inventory.items[i] = ITEM_BOTTLE;
+ }
+ }
+ }
+
+ REMOVE_QUEST_ITEM(QUEST_PICTOGRAPH);
+
+ if (gSaveContext.save.saveInfo.playerData.health < 0x30) {
+ gSaveContext.save.saveInfo.playerData.health = 0x30;
+ }
+
+ if (GET_CUR_EQUIP_VALUE(EQUIP_TYPE_SWORD) <= EQUIP_VALUE_SWORD_RAZOR) {
+ SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_KOKIRI);
+
+ if (CUR_FORM == 0) {
+ if ((STOLEN_ITEM_1 >= ITEM_SWORD_GILDED) || (STOLEN_ITEM_2 >= ITEM_SWORD_GILDED)) {
+ CUR_FORM_EQUIP(EQUIP_SLOT_B) = ITEM_SWORD_GILDED;
+ SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_GILDED);
+ } else {
+ CUR_FORM_EQUIP(EQUIP_SLOT_B) = ITEM_SWORD_KOKIRI;
+ }
+ } else {
+ if ((STOLEN_ITEM_1 >= ITEM_SWORD_GILDED) || (STOLEN_ITEM_2 >= ITEM_SWORD_GILDED)) {
+ BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_GILDED;
+ SET_EQUIP_VALUE(EQUIP_TYPE_SWORD, EQUIP_VALUE_SWORD_GILDED);
+ } else {
+ BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_B) = ITEM_SWORD_KOKIRI;
+ }
+ }
+ }
+
+ if ((STOLEN_ITEM_1 == ITEM_SWORD_GREAT_FAIRY) || (STOLEN_ITEM_2 == ITEM_SWORD_GREAT_FAIRY)) {
+ INV_CONTENT(ITEM_SWORD_GREAT_FAIRY) = ITEM_SWORD_GREAT_FAIRY;
+ }
+
+ if (STOLEN_ITEM_1 == ITEM_BOTTLE) {
+ slot = SLOT(ITEM_BOTTLE);
+ for (i = BOTTLE_FIRST; i < BOTTLE_MAX; i++) {
+ if (gSaveContext.save.saveInfo.inventory.items[slot + i] == ITEM_NONE) {
+ gSaveContext.save.saveInfo.inventory.items[slot + i] = ITEM_BOTTLE;
+ break;
+ }
+ }
+ }
+
+ if (STOLEN_ITEM_2 == ITEM_BOTTLE) {
+ slot = SLOT(ITEM_BOTTLE);
+ for (i = BOTTLE_FIRST; i < BOTTLE_MAX; i++) {
+ if (gSaveContext.save.saveInfo.inventory.items[slot + i] == ITEM_NONE) {
+ gSaveContext.save.saveInfo.inventory.items[slot + i] = ITEM_BOTTLE;
+ break;
+ }
+ }
+ }
+
+ SET_STOLEN_ITEM_1(STOLEN_ITEM_NONE);
+ SET_STOLEN_ITEM_2(STOLEN_ITEM_NONE);
+
+ Inventory_DeleteItem(ITEM_OCARINA_FAIRY, SLOT_TRADE_DEED);
+ Inventory_DeleteItem(ITEM_SLINGSHOT, SLOT_TRADE_KEY_MAMA);
+ Inventory_DeleteItem(ITEM_LONGSHOT, SLOT_TRADE_COUPLE);
+
+ for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++) {
+ if ((GET_CUR_FORM_BTN_ITEM(j) >= ITEM_MOONS_TEAR) && (GET_CUR_FORM_BTN_ITEM(j) <= ITEM_PENDANT_OF_MEMORIES)) {
+ SET_CUR_FORM_BTN_ITEM(j, ITEM_NONE);
+ Interface_LoadItemIconImpl(play, j);
+ }
+ }
+
+ gSaveContext.save.saveInfo.skullTokenCount &= ~0xFFFF0000;
+ gSaveContext.save.saveInfo.skullTokenCount &= ~0x0000FFFF;
+ gSaveContext.save.saveInfo.unk_EA0 = 0;
+
+ gSaveContext.save.saveInfo.alienInfo[0] = 0;
+ gSaveContext.save.saveInfo.alienInfo[1] = 0;
+ gSaveContext.save.saveInfo.alienInfo[2] = 0;
+ gSaveContext.save.saveInfo.alienInfo[3] = 0;
+ gSaveContext.save.saveInfo.alienInfo[4] = 0;
+ gSaveContext.save.saveInfo.alienInfo[5] = 0;
+ gSaveContext.save.saveInfo.alienInfo[6] = 0;
+
+ Sram_ClearHighscores();
+
+ for (i = 0; i < 8; i++) {
+ gSaveContext.save.saveInfo.inventory.dungeonItems[i] &= (u8)~1; // remove boss key
+ DUNGEON_KEY_COUNT(i) = 0;
+ gSaveContext.save.saveInfo.inventory.strayFairies[i] = 0;
+ }
+
+ gSaveContext.save.saveInfo.playerData.rupees = 0;
+ gSaveContext.save.saveInfo.scarecrowSpawnSongSet = false;
+ gSaveContext.powderKegTimer = 0;
+ gSaveContext.unk_1014 = 0;
+ gSaveContext.jinxTimer = 0;
+ gSaveContext.rupeeAccumulator = 0;
+
+ Horse_ResetHorseData(play);
+}
+
+void Sram_IncrementDay(void) {
+ if (CURRENT_DAY <= 3) {
+ gSaveContext.save.day++;
+ gSaveContext.save.eventDayCount++;
+ }
+
+ gSaveContext.save.saveInfo.bombersCaughtNum = 0;
+ gSaveContext.save.saveInfo.bombersCaughtOrder[0] = 0;
+ gSaveContext.save.saveInfo.bombersCaughtOrder[1] = 0;
+ gSaveContext.save.saveInfo.bombersCaughtOrder[2] = 0;
+ gSaveContext.save.saveInfo.bombersCaughtOrder[3] = 0;
+ gSaveContext.save.saveInfo.bombersCaughtOrder[4] = 0;
+
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_73_10);
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_85_02);
+}
+
+u16 Sram_CalcChecksum(void* data, size_t count) {
+ u8* dataPtr = data;
+ u16 chkSum = 0;
+
+ while (count-- > 0) {
+ chkSum += *dataPtr;
+ dataPtr++;
+ }
+ return chkSum;
+}
+
+// Resets `Save` substruct
+void Sram_ResetSave(void) {
+ gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
+ gSaveContext.save.equippedMask = 0;
+ gSaveContext.save.isFirstCycle = false;
+ gSaveContext.save.unk_06 = 0;
+ gSaveContext.save.linkAge = 0;
+ gSaveContext.save.isNight = false;
+ gSaveContext.save.timeSpeedOffset = 0;
+ gSaveContext.save.snowheadCleared = 0;
+ gSaveContext.save.hasTatl = false;
+ gSaveContext.save.isOwlSave = false;
+
+ bzero(&gSaveContext.save.saveInfo, sizeof(SaveInfo));
+}
+
+/**
+ * Initializes with random values the following fields:
+ * - lotteryCodes
+ * - spiderHouseMaskOrder
+ * - bomberCode
+ */
+void Sram_GenerateRandomSaveFields(void) {
+ s32 randBombers;
+ s16 sp2A;
+ s16 pad;
+ s16 i;
+ s16 j;
+ s32 k;
+ s16 randSpiderHouse;
+
+ Sram_ClearHighscores();
+
+ gSaveContext.save.saveInfo.lotteryCodes[0][0] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[0][1] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[0][2] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[1][0] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[1][1] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[1][2] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[2][0] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[2][1] = Rand_S16Offset(0, 10);
+ gSaveContext.save.saveInfo.lotteryCodes[2][2] = Rand_S16Offset(0, 10);
+
+ // Needed to match...
+ for (i = 0; i < 3; i++) {
+ for (j = 0; j < 3; j++) {}
+ }
+
+ i = 0;
+ sp2A = Rand_S16Offset(0, 16) & 3;
+ k = 6;
+ while (i != k) {
+ randSpiderHouse = Rand_S16Offset(0, 16) & 3;
+ if (sp2A != randSpiderHouse) {
+ gSaveContext.save.saveInfo.spiderHouseMaskOrder[i] = randSpiderHouse;
+ i++;
+ sp2A = randSpiderHouse;
+ }
+ }
+
+ do {
+ randBombers = Rand_S16Offset(0, 6);
+ } while ((randBombers <= 0) || (randBombers >= 6));
+
+ gSaveContext.save.saveInfo.bomberCode[0] = randBombers;
+
+ i = 1;
+ while (i != 5) {
+ k = false;
+
+ do {
+ randBombers = Rand_S16Offset(0, 6);
+ } while ((randBombers <= 0) || (randBombers >= 6));
+
+ sp2A = 0;
+ do {
+ if (randBombers == gSaveContext.save.saveInfo.bomberCode[sp2A]) {
+ k = true;
+ }
+ sp2A++;
+ } while (sp2A < i);
+
+ if (k == false) {
+ gSaveContext.save.saveInfo.bomberCode[i] = randBombers;
+ i++;
+ }
+ }
+}
+
+SavePlayerData sSaveDefaultPlayerData = {
+ { '\0', '\0', '\0', '\0', '\0', '\0' }, // newf
+ 0, // threeDayResetCount
+ { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName " "
+ 0x30, // healthCapacity
+ 0x30, // health
+ 0, // magicLevel
+ MAGIC_NORMAL_METER, // magic
+ 0, // rupees
+ 0, // swordHealth
+ 0, // tatlTimer
+ false, // isMagicAcquired
+ false, // isDoubleMagicAcquired
+ 0, // doubleDefense
+ 0, // unk_1F
+ OWL_WARP_NONE, // owlWarpId
+ 0, // owlActivationFlags
+ 0xFF, // unk_24
+ SCENE_SPOT00, // savedSceneId
+};
+
+ItemEquips sSaveDefaultItemEquips = {
+ {
+ { ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
+ { ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
+ { ITEM_SWORD_KOKIRI, ITEM_NONE, ITEM_NONE, ITEM_NONE },
+ { ITEM_FD, ITEM_NONE, ITEM_NONE, ITEM_NONE },
+ },
+ {
+ { SLOT_OCARINA, SLOT_NONE, SLOT_NONE, SLOT_NONE },
+ { SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
+ { SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
+ { SLOT_NONE, SLOT_NONE, SLOT_NONE, SLOT_NONE },
+ },
+ 0x11,
+};
+
+Inventory sSaveDefaultInventory = {
+ // items
+ {
+ ITEM_NONE, // SLOT_OCARINA
+ ITEM_NONE, // SLOT_BOW
+ ITEM_NONE, // SLOT_ARROW_FIRE
+ ITEM_NONE, // SLOT_ARROW_ICE
+ ITEM_NONE, // SLOT_ARROW_LIGHT
+ ITEM_NONE, // SLOT_TRADE_DEED
+ ITEM_NONE, // SLOT_BOMB
+ ITEM_NONE, // SLOT_BOMBCHU
+ ITEM_NONE, // SLOT_DEKU_STICK
+ ITEM_NONE, // SLOT_DEKU_NUT
+ ITEM_NONE, // SLOT_MAGIC_BEANS
+ ITEM_NONE, // SLOT_TRADE_KEY_MAMA
+ ITEM_NONE, // SLOT_POWDER_KEG
+ ITEM_NONE, // SLOT_PICTOGRAPH_BOX
+ ITEM_NONE, // SLOT_LENS_OF_TRUTH
+ ITEM_NONE, // SLOT_HOOKSHOT
+ ITEM_NONE, // SLOT_SWORD_GREAT_FAIRY
+ ITEM_NONE, // SLOT_TRADE_COUPLE
+ ITEM_NONE, // SLOT_BOTTLE_1
+ ITEM_NONE, // SLOT_BOTTLE_2
+ ITEM_NONE, // SLOT_BOTTLE_3
+ ITEM_NONE, // SLOT_BOTTLE_4
+ ITEM_NONE, // SLOT_BOTTLE_5
+ ITEM_NONE, // SLOT_BOTTLE_6
+ ITEM_NONE, // SLOT_MASK_POSTMAN
+ ITEM_NONE, // SLOT_MASK_ALL_NIGHT
+ ITEM_NONE, // SLOT_MASK_BLAST
+ ITEM_NONE, // SLOT_MASK_STONE
+ ITEM_NONE, // SLOT_MASK_GREAT_FAIRY
+ ITEM_NONE, // SLOT_MASK_DEKU
+ ITEM_NONE, // SLOT_MASK_KEATON
+ ITEM_NONE, // SLOT_MASK_BREMEN
+ ITEM_NONE, // SLOT_MASK_BUNNY
+ ITEM_NONE, // SLOT_MASK_DON_GERO
+ ITEM_NONE, // SLOT_MASK_SCENTS
+ ITEM_NONE, // SLOT_MASK_GORON
+ ITEM_NONE, // SLOT_MASK_ROMANI
+ ITEM_NONE, // SLOT_MASK_CIRCUS_LEADER
+ ITEM_NONE, // SLOT_MASK_KAFEIS_MASK
+ ITEM_NONE, // SLOT_MASK_COUPLE
+ ITEM_NONE, // SLOT_MASK_TRUTH
+ ITEM_NONE, // SLOT_MASK_ZORA
+ ITEM_NONE, // SLOT_MASK_KAMARO
+ ITEM_NONE, // SLOT_MASK_GIBDO
+ ITEM_NONE, // SLOT_MASK_GARO
+ ITEM_NONE, // SLOT_MASK_CAPTAIN
+ ITEM_NONE, // SLOT_MASK_GIANT
+ ITEM_NONE, // SLOT_MASK_FIERCE_DEITY
+ },
+ // ammo
+ {
+ 0, // SLOT_OCARINA
+ 0, // SLOT_BOW
+ 0, // SLOT_ARROW_FIRE
+ 0, // SLOT_ARROW_ICE
+ 0, // SLOT_ARROW_LIGHT
+ 0, // SLOT_TRADE_DEED
+ 0, // SLOT_BOMB
+ 0, // SLOT_BOMBCHU
+ 0, // SLOT_DEKU_STICK
+ 0, // SLOT_DEKU_NUT
+ 0, // SLOT_MAGIC_BEANS
+ 0, // SLOT_TRADE_KEY_MAMA
+ 0, // SLOT_POWDER_KEG
+ 0, // SLOT_PICTOGRAPH_BOX
+ 0, // SLOT_LENS_OF_TRUTH
+ 0, // SLOT_HOOKSHOT
+ 0, // SLOT_SWORD_GREAT_FAIRY
+ 0, // SLOT_TRADE_COUPLE
+ 0, // SLOT_BOTTLE_1
+ 0, // SLOT_BOTTLE_2
+ 0, // SLOT_BOTTLE_3
+ 0, // SLOT_BOTTLE_4
+ 0, // SLOT_BOTTLE_5
+ 0, // SLOT_BOTTLE_6
+ },
+ // upgrades
+ (0 << 0) | // UPG_QUIVER
+ (0 << 3) | // UPG_BOMB_BAG
+ (0 << 6) | // UPG_STRENGTH
+ (0 << 9) | // UPG_SCALE
+ (0 << 12) | // UPG_WALLET
+ (0 << 14) | // UPG_BULLET_BAG
+ (1 << 17) | // UPG_DEKU_STICKS
+ (1 << 20), // UPG_DEKU_NUTS
+ // questItems
+ 0,
+ // dungeonItems
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ // dungeonKeys
+ { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF },
+ // defenseHearts
+ 0,
+ // strayFairies
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ // dekuPlaygroundPlayerName
+ {
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ },
+};
+
+u16 sSaveDefaultChecksum = 0;
+
+/**
+ * Initialize new save.
+ * This save has an empty inventory with 3 hearts, sword and shield.
+ */
+void Sram_InitNewSave(void) {
+ gSaveContext.save.playerForm = PLAYER_FORM_HUMAN;
+ gSaveContext.save.eventDayCount = 0;
+ gSaveContext.save.day = 0;
+ gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;
+ Sram_ResetSave();
+
+ Lib_MemCpy(&gSaveContext.save.saveInfo.playerData, &sSaveDefaultPlayerData, sizeof(SavePlayerData));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.equips, &sSaveDefaultItemEquips, sizeof(ItemEquips));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.inventory, &sSaveDefaultInventory, sizeof(Inventory));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.checksum, &sSaveDefaultChecksum,
+ sizeof(gSaveContext.save.saveInfo.checksum));
+
+ gSaveContext.save.saveInfo.horseData.sceneId = SCENE_F01;
+ gSaveContext.save.saveInfo.horseData.pos.x = -1420;
+ gSaveContext.save.saveInfo.horseData.pos.y = 257;
+ gSaveContext.save.saveInfo.horseData.pos.z = -1285;
+ gSaveContext.save.saveInfo.horseData.yaw = -0x7554;
+
+ gSaveContext.nextCutsceneIndex = 0;
+ gSaveContext.save.saveInfo.playerData.magicLevel = 0;
+ Sram_GenerateRandomSaveFields();
+}
+
+SavePlayerData sSaveDebugPlayerData = {
+ { 'Z', 'E', 'L', 'D', 'A', '3' }, // newf
+ 0, // threeDayResetCount
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName "LINK "
+ 0x80, // healthCapacity
+ 0x80, // health
+ 0, // magicLevel
+ MAGIC_NORMAL_METER, // magic
+ 50, // rupees
+ 100, // swordHealth
+ 0, // tatlTimer
+ true, // isMagicAcquired
+ false, // isDoubleMagicAcquired
+ 0, // doubleDefense
+ 0, // unk_1F
+ OWL_WARP_NONE, // owlWarpId
+ 0, // owlActivationFlags
+ 0xFF, // unk_24
+ SCENE_SPOT00, // savedSceneId
+};
+
+ItemEquips sSaveDebugItemEquips = {
+ {
+ { ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_POTION_RED, ITEM_OCARINA_OF_TIME },
+ { ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_MASK_GORON, ITEM_OCARINA_OF_TIME },
+ { ITEM_SWORD_KOKIRI, ITEM_BOW, ITEM_MASK_ZORA, ITEM_OCARINA_OF_TIME },
+ { ITEM_DEKU_NUT, ITEM_DEKU_NUT, ITEM_MASK_DEKU, ITEM_OCARINA_OF_TIME },
+ },
+ {
+ { SLOT_OCARINA, SLOT_BOW, SLOT_BOTTLE_2, SLOT_OCARINA },
+ { SLOT_OCARINA, SLOT_MAGIC_BEANS, SLOT_MASK_GORON, SLOT_BOMBCHU },
+ { SLOT_OCARINA, SLOT_POWDER_KEG, SLOT_MASK_ZORA, SLOT_BOMBCHU },
+ { SLOT_OCARINA, SLOT_BOW, SLOT_MASK_DEKU, SLOT_BOMBCHU },
+ },
+ 0x11,
+};
+
+Inventory sSaveDebugInventory = {
+ // items
+ {
+ ITEM_OCARINA_OF_TIME, // SLOT_OCARINA
+ ITEM_BOW, // SLOT_BOW
+ ITEM_ARROW_FIRE, // SLOT_ARROW_FIRE
+ ITEM_ARROW_ICE, // SLOT_ARROW_ICE
+ ITEM_ARROW_LIGHT, // SLOT_ARROW_LIGHT
+ ITEM_MOONS_TEAR, // SLOT_TRADE_DEED
+ ITEM_BOMB, // SLOT_BOMB
+ ITEM_BOMBCHU, // SLOT_BOMBCHU
+ ITEM_DEKU_STICK, // SLOT_DEKU_STICK
+ ITEM_DEKU_NUT, // SLOT_DEKU_NUT
+ ITEM_MAGIC_BEANS, // SLOT_MAGIC_BEANS
+ ITEM_ROOM_KEY, // SLOT_TRADE_KEY_MAMA
+ ITEM_POWDER_KEG, // SLOT_POWDER_KEG
+ ITEM_PICTOGRAPH_BOX, // SLOT_PICTOGRAPH_BOX
+ ITEM_LENS_OF_TRUTH, // SLOT_LENS_OF_TRUTH
+ ITEM_HOOKSHOT, // SLOT_HOOKSHOT
+ ITEM_SWORD_GREAT_FAIRY, // SLOT_SWORD_GREAT_FAIRY
+ ITEM_LETTER_TO_KAFEI, // SLOT_TRADE_COUPLE
+ ITEM_BOTTLE, // SLOT_BOTTLE_1
+ ITEM_POTION_RED, // SLOT_BOTTLE_2
+ ITEM_POTION_GREEN, // SLOT_BOTTLE_3
+ ITEM_POTION_BLUE, // SLOT_BOTTLE_4
+ ITEM_NONE, // SLOT_BOTTLE_5
+ ITEM_NONE, // SLOT_BOTTLE_6
+ ITEM_MASK_POSTMAN, // SLOT_MASK_POSTMAN
+ ITEM_MASK_ALL_NIGHT, // SLOT_MASK_ALL_NIGHT
+ ITEM_MASK_BLAST, // SLOT_MASK_BLAST
+ ITEM_MASK_STONE, // SLOT_MASK_STONE
+ ITEM_MASK_GREAT_FAIRY, // SLOT_MASK_GREAT_FAIRY
+ ITEM_MASK_DEKU, // SLOT_MASK_DEKU
+ ITEM_MASK_KEATON, // SLOT_MASK_KEATON
+ ITEM_MASK_BREMEN, // SLOT_MASK_BREMEN
+ ITEM_MASK_BUNNY, // SLOT_MASK_BUNNY
+ ITEM_MASK_DON_GERO, // SLOT_MASK_DON_GERO
+ ITEM_MASK_SCENTS, // SLOT_MASK_SCENTS
+ ITEM_MASK_GORON, // SLOT_MASK_GORON
+ ITEM_MASK_ROMANI, // SLOT_MASK_ROMANI
+ ITEM_MASK_CIRCUS_LEADER, // SLOT_MASK_CIRCUS_LEADER
+ ITEM_MASK_KAFEIS_MASK, // SLOT_MASK_KAFEIS_MASK
+ ITEM_MASK_COUPLE, // SLOT_MASK_COUPLE
+ ITEM_MASK_TRUTH, // SLOT_MASK_TRUTH
+ ITEM_MASK_ZORA, // SLOT_MASK_ZORA
+ ITEM_MASK_KAMARO, // SLOT_MASK_KAMARO
+ ITEM_MASK_GIBDO, // SLOT_MASK_GIBDO
+ ITEM_MASK_GARO, // SLOT_MASK_GARO
+ ITEM_MASK_CAPTAIN, // SLOT_MASK_CAPTAIN
+ ITEM_MASK_GIANT, // SLOT_MASK_GIANT
+ ITEM_MASK_FIERCE_DEITY, // SLOT_MASK_FIERCE_DEITY
+ },
+ // ammo
+ {
+ 1, // SLOT_OCARINA
+ 30, // SLOT_BOW
+ 1, // SLOT_ARROW_FIRE
+ 1, // SLOT_ARROW_ICE
+ 1, // SLOT_ARROW_LIGHT
+ 1, // SLOT_TRADE_DEED
+ 30, // SLOT_BOMB
+ 30, // SLOT_BOMBCHU
+ 30, // SLOT_DEKU_STICK
+ 30, // SLOT_DEKU_NUT
+ 1, // SLOT_MAGIC_BEANS
+ 1, // SLOT_TRADE_KEY_MAMA
+ 1, // SLOT_POWDER_KEG
+ 1, // SLOT_PICTOGRAPH_BOX
+ 30, // SLOT_LENS_OF_TRUTH
+ 1, // SLOT_HOOKSHOT
+ 1, // SLOT_SWORD_GREAT_FAIRY
+ 1, // SLOT_TRADE_COUPLE
+ 1, // SLOT_BOTTLE_1
+ 1, // SLOT_BOTTLE_2
+ 1, // SLOT_BOTTLE_3
+ 1, // SLOT_BOTTLE_4
+ 0, // SLOT_BOTTLE_5
+ 0, // SLOT_BOTTLE_6
+ },
+ // upgrades
+ (1 << 0) | // UPG_QUIVER
+ (1 << 3) | // UPG_BOMB_BAG
+ (0 << 6) | // UPG_STRENGTH
+ (0 << 9) | // UPG_SCALE
+ (0 << 12) | // UPG_WALLET
+ (0 << 14) | // UPG_BULLET_BAG
+ (1 << 17) | // UPG_DEKU_STICKS
+ (1 << 20), // UPG_DEKU_NUTS
+ // questItems
+ (1 << QUEST_SONG_SONATA) | (1 << QUEST_SONG_LULLABY) | (1 << QUEST_SONG_BOSSA_NOVA) | (1 << QUEST_SONG_ELEGY) |
+ (1 << QUEST_SONG_OATH) | (1 << QUEST_SONG_TIME) | (1 << QUEST_SONG_HEALING) | (1 << QUEST_SONG_EPONA) |
+ (1 << QUEST_SONG_SOARING) | (1 << QUEST_SONG_STORMS) | (1 << QUEST_BOMBERS_NOTEBOOK) |
+ (1 << QUEST_SONG_LULLABY_INTRO),
+ // dungeonItems
+ {
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ (1 << DUNGEON_BOSS_KEY) | (1 << DUNGEON_COMPASS) | (1 << DUNGEON_MAP),
+ },
+ // dungeonKeys
+ { 8, 8, 8, 8, 8, 8, 8, 8, 8 },
+ // defenseHearts
+ 0,
+ // strayFairies
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
+ // dekuPlaygroundPlayerName
+ {
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ // "LINK "
+ { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E },
+ },
+};
+
+u16 sSaveDebugChecksum = 0;
+
+u8 D_801C6A48[PLAYER_FORM_MAX] = {
+ ITEM_MASK_FIERCE_DEITY, // PLAYER_FORM_FIERCE_DEITY
+ ITEM_MASK_GORON, // PLAYER_FORM_GORON
+ ITEM_MASK_ZORA, // PLAYER_FORM_ZORA
+ ITEM_MASK_DEKU, // PLAYER_FORM_DEKU
+ ITEM_MASK_FIERCE_DEITY, // PLAYER_FORM_HUMAN
+};
+
+u8 D_801C6A50[PLAYER_FORM_MAX] = {
+ SLOT_MASK_FIERCE_DEITY, // PLAYER_FORM_FIERCE_DEITY
+ SLOT_MASK_GORON, // PLAYER_FORM_GORON
+ SLOT_MASK_ZORA, // PLAYER_FORM_ZORA
+ SLOT_MASK_DEKU, // PLAYER_FORM_DEKU
+ SLOT_MASK_FIERCE_DEITY, // PLAYER_FORM_HUMAN
+};
+
+/**
+ * Initialize debug save. This is also used on the Title Screen
+ * This save has a mostly full inventory, every mask and 10 hearts.
+ *
+ * Some noteable flags that are set:
+ * TODO: Investigate the flags
+ */
+void Sram_InitDebugSave(void) {
+ Sram_ResetSave();
+
+ Lib_MemCpy(&gSaveContext.save.saveInfo.playerData, &sSaveDebugPlayerData, sizeof(SavePlayerData));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.equips, &sSaveDebugItemEquips, sizeof(ItemEquips));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.inventory, &sSaveDebugInventory, sizeof(Inventory));
+ Lib_MemCpy(&gSaveContext.save.saveInfo.checksum, &sSaveDebugChecksum, sizeof(gSaveContext.save.saveInfo.checksum));
+
+ if (GET_PLAYER_FORM != PLAYER_FORM_HUMAN) {
+ BUTTON_ITEM_EQUIP(0, EQUIP_SLOT_C_DOWN) = D_801C6A48[GET_PLAYER_FORM];
+ C_SLOT_EQUIP(0, EQUIP_SLOT_C_DOWN) = D_801C6A50[GET_PLAYER_FORM];
+ }
+
+ gSaveContext.save.hasTatl = true;
+
+ gSaveContext.save.saveInfo.horseData.sceneId = SCENE_F01;
+ gSaveContext.save.saveInfo.horseData.pos.x = -1420;
+ gSaveContext.save.saveInfo.horseData.pos.y = 257;
+ gSaveContext.save.saveInfo.horseData.pos.z = -1285;
+ gSaveContext.save.saveInfo.horseData.yaw = -0x7554;
+
+ gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
+ gSaveContext.save.isFirstCycle = true;
+
+ SET_WEEKEVENTREG(WEEKEVENTREG_15_20);
+ SET_WEEKEVENTREG(WEEKEVENTREG_59_04);
+ SET_WEEKEVENTREG(WEEKEVENTREG_31_04);
+
+ gSaveContext.cycleSceneFlags[SCENE_INSIDETOWER].switch0 = 1;
+ gSaveContext.save.saveInfo.permanentSceneFlags[SCENE_INSIDETOWER].switch0 = 1;
+ gSaveContext.save.saveInfo.playerData.magicLevel = 0;
+
+ Sram_GenerateRandomSaveFields();
+}
+
+void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx) {
+ s32 i;
+ s32 cutsceneIndex = gSaveContext.save.cutsceneIndex;
+
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2],
+ gFlashSaveNumPages[gSaveContext.fileNum * 2]) != 0) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2 + 1],
+ gFlashSaveNumPages[gSaveContext.fileNum * 2 + 1]);
+ }
+ Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf)) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2 + 1],
+ gFlashSaveNumPages[gSaveContext.fileNum * 2 + 1]);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save));
+ }
+ gSaveContext.save.cutsceneIndex = cutsceneIndex;
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
+ gSaveContext.eventInf[i] = 0;
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.saveInfo.permanentSceneFlags[i].chest;
+ gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0;
+ gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1;
+ gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom;
+ gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible;
+ }
+
+ for (i = 0; i < TIMER_ID_MAX; i++) {
+ gSaveContext.timerStates[i] = TIMER_STATE_OFF;
+ gSaveContext.timerCurTimes[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerTimeLimits[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerStartOsTimes[i] = 0;
+ gSaveContext.timerStopTimes[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerPausedOsTimes[i] = 0;
+ }
+
+ D_801BDAA0 = true;
+ gHorseIsMounted = false;
+ gSaveContext.powderKegTimer = 0;
+ gSaveContext.unk_1014 = 0;
+ gSaveContext.jinxTimer = 0;
+}
+
+static u16 sOwlWarpEntrances[OWL_WARP_MAX - 1] = {
+ ENTRANCE(GREAT_BAY_COAST, 11), // OWL_WARP_GREAT_BAY_COAST
+ ENTRANCE(ZORA_CAPE, 6), // OWL_WARP_ZORA_CAPE
+ ENTRANCE(SNOWHEAD, 3), // OWL_WARP_SNOWHEAD
+ ENTRANCE(MOUNTAIN_VILLAGE_WINTER, 8), // OWL_WARP_MOUNTAIN_VILLAGE
+ ENTRANCE(SOUTH_CLOCK_TOWN, 9), // OWL_WARP_CLOCK_TOWN
+ ENTRANCE(MILK_ROAD, 4), // OWL_WARP_MILK_ROAD
+ ENTRANCE(WOODFALL, 4), // OWL_WARP_WOODFALL
+ ENTRANCE(SOUTHERN_SWAMP_POISONED, 10), // OWL_WARP_SOUTHERN_SWAMP
+ ENTRANCE(IKANA_CANYON, 4), // OWL_WARP_IKANA_CANYON
+ ENTRANCE(STONE_TOWER, 3), // OWL_WARP_STONE_TOWER
+};
+
+void Sram_OpenSave(FileSelectState* fileSelect, SramContext* sramCtx) {
+ s32 i;
+ s32 pad;
+ s32 phi_t1;
+ s32 pad1;
+ s32 fileNum;
+
+ if (gSaveContext.flashSaveAvailable) {
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+
+ if (gSaveContext.fileNum == 0xFF) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[0], gFlashSaveNumPages[0]);
+ } else if (fileSelect->isOwlSave[gSaveContext.fileNum + 2]) {
+ phi_t1 = gSaveContext.fileNum + 2;
+ phi_t1 *= 2;
+
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1], gFlashSaveNumPages[phi_t1]) != 0) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], gFlashSaveNumPages[phi_t1 + 1]);
+ }
+ } else {
+ phi_t1 = gSaveContext.fileNum;
+ phi_t1 *= 2;
+
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1], gFlashSaveNumPages[phi_t1]) != 0) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], gFlashSaveNumPages[phi_t1 + 1]);
+ }
+ }
+
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[phi_t1]);
+
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf)) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], gFlashSaveNumPages[phi_t1 + 1]);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[phi_t1]);
+ }
+ }
+
+ gSaveContext.save.saveInfo.playerData.magicLevel = 0;
+
+ if (!gSaveContext.save.isOwlSave) {
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.eventInf); i++) {
+ gSaveContext.eventInf[i] = 0;
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.saveInfo.permanentSceneFlags[i].chest;
+ gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0;
+ gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1;
+ gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom;
+ gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible;
+ }
+
+ for (i = 0; i < TIMER_ID_MAX; i++) {
+ gSaveContext.timerStates[i] = TIMER_STATE_OFF;
+ gSaveContext.timerCurTimes[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerTimeLimits[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerStartOsTimes[i] = 0;
+ gSaveContext.timerStopTimes[i] = SECONDS_TO_TIMER(0);
+ gSaveContext.timerPausedOsTimes[i] = 0;
+ }
+
+ if (gSaveContext.save.isFirstCycle) {
+ gSaveContext.save.entrance = ENTRANCE(SOUTH_CLOCK_TOWN, 0);
+ gSaveContext.save.day = 0;
+ gSaveContext.save.time = CLOCK_TIME(6, 0) - 1;
+ } else {
+ gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0);
+ gSaveContext.nextCutsceneIndex = 0;
+ gSaveContext.save.playerForm = PLAYER_FORM_HUMAN;
+ }
+ } else {
+ gSaveContext.save.entrance = sOwlWarpEntrances[(void)0, gSaveContext.save.owlWarpId];
+ if ((gSaveContext.save.entrance == ENTRANCE(SOUTHERN_SWAMP_POISONED, 10)) &&
+ CHECK_WEEKEVENTREG(WEEKEVENTREG_CLEARED_WOODFALL_TEMPLE)) {
+ gSaveContext.save.entrance = ENTRANCE(SOUTHERN_SWAMP_CLEARED, 10);
+ } else if ((gSaveContext.save.entrance == ENTRANCE(MOUNTAIN_VILLAGE_WINTER, 8)) &&
+ CHECK_WEEKEVENTREG(WEEKEVENTREG_CLEARED_SNOWHEAD_TEMPLE)) {
+ gSaveContext.save.entrance = ENTRANCE(MOUNTAIN_VILLAGE_SPRING, 8);
+ }
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.cycleSceneFlags[i].chest = gSaveContext.save.saveInfo.permanentSceneFlags[i].chest;
+ gSaveContext.cycleSceneFlags[i].switch0 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0;
+ gSaveContext.cycleSceneFlags[i].switch1 = gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1;
+ gSaveContext.cycleSceneFlags[i].clearedRoom = gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom;
+ gSaveContext.cycleSceneFlags[i].collectible = gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible;
+ }
+
+ if (gSaveContext.save.saveInfo.scarecrowSpawnSongSet) {
+ Lib_MemCpy(gScarecrowSpawnSongPtr, gSaveContext.save.saveInfo.scarecrowSpawnSong,
+ sizeof(gSaveContext.save.saveInfo.scarecrowSpawnSong));
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.scarecrowSpawnSong); i++) {}
+ }
+
+ fileNum = gSaveContext.fileNum;
+ func_80147314(sramCtx, fileNum);
+ }
+}
+
+// Similar to func_80145698, but accounts for owl saves?
+void func_8014546C(SramContext* sramCtx) {
+ s32 i;
+
+ if (gSaveContext.save.isOwlSave) {
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
+ }
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
+
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
+ } else {
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
+ }
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
+
+ if (gSaveContext.flashSaveAvailable) {
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save));
+ Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
+ }
+ }
+}
+
+/**
+ * Save permanent scene flags, calculate checksum, copy save context to the save buffer
+ */
+void func_80145698(SramContext* sramCtx) {
+ s32 i;
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.cycleSceneFlags); i++) {
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].chest = gSaveContext.cycleSceneFlags[i].chest;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch0 = gSaveContext.cycleSceneFlags[i].switch0;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].switch1 = gSaveContext.cycleSceneFlags[i].switch1;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].clearedRoom = gSaveContext.cycleSceneFlags[i].clearedRoom;
+ gSaveContext.save.saveInfo.permanentSceneFlags[i].collectible = gSaveContext.cycleSceneFlags[i].collectible;
+ }
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
+ if (gSaveContext.flashSaveAvailable) {
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save));
+ Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
+ }
+}
+
+// Verifies save and use backup if corrupted?
+void func_801457CC(GameState* gameState, SramContext* sramCtx) {
+ FileSelectState* fileSelect = (FileSelectState*)gameState;
+ u16 sp7A;
+ u16 oldCheckSum;
+ u16 sp76;
+ u16 sp64;
+ u16 phi_s2;
+ u16 pad;
+ u16 sp6E;
+ u16 newCheckSum;
+ u16 maskCount;
+
+ if (gSaveContext.flashSaveAvailable) {
+ D_801F6AF0 = CURRENT_TIME;
+ D_801F6AF2 = gSaveContext.flashSaveAvailable;
+ sp64 = 0;
+
+ for (sp76 = 0; sp76 < 5; sp76++, sp64 += 2) {
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+
+ phi_s2 = false;
+ sp6E = 0;
+ // read main save from flash
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]) != 0) {
+ // main save didn't work
+ sp6E = 1;
+ // read backup save from flash
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], gFlashSaveNumPages[sp64 + 1]) !=
+ 0) {
+ // backup save didn't work
+ phi_s2 = true;
+ }
+ }
+
+ if (sp76 < 2) {
+ // Non-owl save
+ // sp76 = 0: main save
+ // sp76 = 1: backup save
+
+ fileSelect->isOwlSave[sp76] = 0;
+ if (phi_s2) {
+ // both main save and backup save failed
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ } else {
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+
+ // test checksum of main save
+ phi_s2 = gSaveContext.save.saveInfo.checksum;
+ gSaveContext.save.saveInfo.checksum = 0;
+ newCheckSum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]);
+ gSaveContext.save.saveInfo.checksum = phi_s2;
+
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (newCheckSum != phi_s2)) {
+ // checksum didnt match, try backup save
+ sp6E = 1;
+
+ if ((gSaveContext.save.saveInfo.playerData.newf[0] == 'Z') &&
+ (gSaveContext.save.saveInfo.playerData.newf[1] == 'E') &&
+ (gSaveContext.save.saveInfo.playerData.newf[2] == 'L') &&
+ (gSaveContext.save.saveInfo.playerData.newf[3] == 'D') &&
+ (gSaveContext.save.saveInfo.playerData.newf[4] == 'A')) {}
+
+ // read backup save from flash
+ phi_s2 = false;
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1],
+ gFlashSaveNumPages[sp64 + 1]) != 0) {
+ // backup save didn't work
+ phi_s2 = true;
+ }
+
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+
+ // test checksum of backup save
+ oldCheckSum = gSaveContext.save.saveInfo.checksum;
+ gSaveContext.save.saveInfo.checksum = 0;
+
+ if (phi_s2 || CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) ||
+ (oldCheckSum != Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]))) {
+ // backup save didn't work
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
+ sp6E = 999;
+ }
+ }
+ }
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ //! FAKE: [sp64 + 0]?
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64 + 0]);
+
+ for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.newf); sp7A++) {
+ fileSelect->newf[sp76][sp7A] = gSaveContext.save.saveInfo.playerData.newf[sp7A];
+ }
+
+ if (!CHECK_NEWF(fileSelect->newf[sp76])) {
+ fileSelect->threeDayResetCount[sp76] = gSaveContext.save.saveInfo.playerData.threeDayResetCount;
+
+ for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); sp7A++) {
+ fileSelect->fileNames[sp76][sp7A] = gSaveContext.save.saveInfo.playerData.playerName[sp7A];
+ }
+
+ fileSelect->healthCapacity[sp76] = gSaveContext.save.saveInfo.playerData.healthCapacity;
+ fileSelect->health[sp76] = gSaveContext.save.saveInfo.playerData.health;
+ fileSelect->defenseHearts[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts;
+ fileSelect->questItems[sp76] = gSaveContext.save.saveInfo.inventory.questItems;
+ fileSelect->time[sp76] = CURRENT_TIME;
+ fileSelect->day[sp76] = gSaveContext.save.day;
+ fileSelect->isOwlSave[sp76] = gSaveContext.save.isOwlSave;
+ fileSelect->rupees[sp76] = gSaveContext.save.saveInfo.playerData.rupees;
+ fileSelect->walletUpgrades[sp76] = CUR_UPG_VALUE(UPG_WALLET);
+
+ for (sp7A = 0, maskCount = 0; sp7A < MASK_NUM_SLOTS; sp7A++) {
+ if (gSaveContext.save.saveInfo.inventory.items[sp7A + ITEM_NUM_SLOTS] == ITEM_NONE) {
+ continue;
+ }
+ maskCount++;
+ }
+ fileSelect->maskCount[sp76] = maskCount;
+ fileSelect->heartPieceCount[sp76] = GET_QUEST_HEART_PIECE_COUNT;
+ }
+
+ if (sp6E == 1) {
+ // backup save
+ Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSpecialSaveNumPages[sp64]);
+ } else if (!sp6E) {
+ // main save
+ oldCheckSum = gSaveContext.save.saveInfo.checksum;
+
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1],
+ gFlashSaveNumPages[sp64 + 1]) != 0) {
+ phi_s2 = 1;
+ } else {
+ Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
+ phi_s2 = gSaveContext.save.saveInfo.checksum;
+ gSaveContext.save.saveInfo.checksum = 0;
+ sp7A = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
+ }
+
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (sp7A != phi_s2) ||
+ (oldCheckSum != phi_s2)) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]);
+ Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
+ Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSpecialSaveNumPages[sp64]);
+ }
+ }
+ } else if (sp76 < 4) {
+ // Owl Save:
+ // sp76 = 3: main owl save
+ // sp76 = 4: backup owl save
+ fileSelect->isOwlSave[sp76] = 0;
+
+ if (!CHECK_NEWF(fileSelect->newf[sp76 - 2])) {
+ if (phi_s2) {
+ // both main save and backup save failed
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ } else {
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ phi_s2 = gSaveContext.save.saveInfo.checksum;
+
+ // test checksum of main save
+ gSaveContext.save.saveInfo.checksum = 0;
+ newCheckSum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]);
+ gSaveContext.save.saveInfo.checksum = phi_s2;
+
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (newCheckSum != phi_s2)) {
+ // checksum didnt match, try backup save
+ sp6E = 1;
+ if ((gSaveContext.save.saveInfo.playerData.newf[0] == 'Z') &&
+ (gSaveContext.save.saveInfo.playerData.newf[1] == 'E') &&
+ (gSaveContext.save.saveInfo.playerData.newf[2] == 'L') &&
+ (gSaveContext.save.saveInfo.playerData.newf[3] == 'D') &&
+ (gSaveContext.save.saveInfo.playerData.newf[4] == 'A')) {}
+
+ phi_s2 = false;
+ // read backup save from flash
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1],
+ gFlashSaveNumPages[sp64 + 1]) != 0) {
+ // backup save didn't work
+ phi_s2 = true;
+ }
+
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+
+ // test checksum of backup save
+ oldCheckSum = gSaveContext.save.saveInfo.checksum;
+ gSaveContext.save.saveInfo.checksum = 0;
+
+ if (phi_s2 || CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) ||
+ (oldCheckSum != Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]))) {
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ sp6E = 999;
+ }
+ }
+ }
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ //! FAKE: [sp64 + 0]?
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64 + 0]);
+
+ for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.newf); sp7A++) {
+ fileSelect->newf[sp76][sp7A] = gSaveContext.save.saveInfo.playerData.newf[sp7A];
+ }
+
+ if (!CHECK_NEWF(fileSelect->newf[sp76])) {
+ fileSelect->threeDayResetCount[sp76] = gSaveContext.save.saveInfo.playerData.threeDayResetCount;
+
+ for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); sp7A++) {
+ fileSelect->fileNames[sp76][sp7A] =
+ (u32)gSaveContext.save.saveInfo.playerData.playerName[sp7A];
+ }
+
+ fileSelect->healthCapacity[sp76] = gSaveContext.save.saveInfo.playerData.healthCapacity;
+ fileSelect->health[sp76] = gSaveContext.save.saveInfo.playerData.health;
+ fileSelect->defenseHearts[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts;
+ fileSelect->questItems[sp76] = gSaveContext.save.saveInfo.inventory.questItems;
+ fileSelect->time[sp76] = CURRENT_TIME;
+ fileSelect->day[sp76] = gSaveContext.save.day;
+ fileSelect->isOwlSave[sp76] = gSaveContext.save.isOwlSave;
+ fileSelect->rupees[sp76] = gSaveContext.save.saveInfo.playerData.rupees;
+ fileSelect->walletUpgrades[sp76] = CUR_UPG_VALUE(UPG_WALLET);
+
+ for (sp7A = 0, maskCount = 0; sp7A < MASK_NUM_SLOTS; sp7A++) {
+ if (gSaveContext.save.saveInfo.inventory.items[sp7A + ITEM_NUM_SLOTS] == ITEM_NONE) {
+ continue;
+ }
+ maskCount++;
+ }
+ fileSelect->maskCount[sp76] = maskCount;
+ fileSelect->heartPieceCount[sp76] = GET_QUEST_HEART_PIECE_COUNT;
+ }
+
+ if (sp6E == 1) {
+ // backup save
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64 + 1], gFlashSaveNumPages[sp64 + 1]);
+ } else if (!sp6E) {
+ // main save
+ oldCheckSum = gSaveContext.save.saveInfo.checksum;
+
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1],
+ gFlashSaveNumPages[sp64 + 1]) != 0) {
+ phi_s2 = 1;
+ } else {
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ phi_s2 = gSaveContext.save.saveInfo.checksum;
+ gSaveContext.save.saveInfo.checksum = 0;
+ sp7A = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]);
+ }
+
+ if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (sp7A != phi_s2) ||
+ (oldCheckSum != phi_s2)) {
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64 + 1],
+ gFlashSaveNumPages[sp64 + 1]);
+ }
+ }
+ } else {
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64 + 1], gFlashSaveNumPages[sp64 + 1]);
+ }
+ } else {
+ if (phi_s2) {
+ gSaveContext.options.optionId = 0xA51D;
+ gSaveContext.options.language = LANGUAGE_ENG;
+ gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO;
+ gSaveContext.options.languageSetting = 0;
+ gSaveContext.options.zTargetSetting = 0;
+ } else {
+ Lib_MemCpy(&gSaveContext.options, sramCtx->saveBuf, sizeof(SaveOptions));
+ if (gSaveContext.options.optionId != 0xA51D) {
+ gSaveContext.options.optionId = 0xA51D;
+ gSaveContext.options.language = LANGUAGE_ENG;
+ gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO;
+ gSaveContext.options.languageSetting = 0;
+ gSaveContext.options.zTargetSetting = 0;
+ }
+ }
+ Audio_SetFileSelectSettings(gSaveContext.options.audioSetting);
+ }
+ }
+
+ gSaveContext.save.time = D_801F6AF0;
+ gSaveContext.flashSaveAvailable = D_801F6AF2;
+ }
+
+ gSaveContext.options.language = LANGUAGE_ENG;
+}
+
+void Sram_EraseSave(FileSelectState* fileSelect2, SramContext* sramCtx, s32 fileNum) {
+ FileSelectState* fileSelect = fileSelect2;
+ s32 pad;
+
+ if (gSaveContext.flashSaveAvailable) {
+ if (fileSelect->isOwlSave[fileNum + 2]) {
+ func_80147314(sramCtx, fileNum);
+ fileSelect->isOwlSave[fileNum + 2] = false;
+ }
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save));
+ }
+
+ gSaveContext.save.time = D_801F6AF0;
+ gSaveContext.flashSaveAvailable = D_801F6AF2;
+}
+
+void Sram_CopySave(FileSelectState* fileSelect2, SramContext* sramCtx) {
+ FileSelectState* fileSelect = fileSelect2;
+ u16 i;
+ s16 maskCount;
+
+ if (gSaveContext.flashSaveAvailable) {
+ if (fileSelect->isOwlSave[fileSelect->selectedFileIndex + 2]) {
+ func_80147414(sramCtx, fileSelect->selectedFileIndex, fileSelect->copyDestFileIndex);
+ fileSelect->threeDayResetCount[fileSelect->copyDestFileIndex + 2] =
+ gSaveContext.save.saveInfo.playerData.threeDayResetCount;
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); i++) {
+ fileSelect->fileNames[fileSelect->copyDestFileIndex + 2][i] =
+ gSaveContext.save.saveInfo.playerData.playerName[i];
+ }
+
+ fileSelect->healthCapacity[fileSelect->copyDestFileIndex + 2] =
+ gSaveContext.save.saveInfo.playerData.healthCapacity;
+ fileSelect->health[fileSelect->copyDestFileIndex + 2] = gSaveContext.save.saveInfo.playerData.health;
+ fileSelect->defenseHearts[fileSelect->copyDestFileIndex + 2] =
+ gSaveContext.save.saveInfo.inventory.defenseHearts;
+ fileSelect->questItems[fileSelect->copyDestFileIndex + 2] = gSaveContext.save.saveInfo.inventory.questItems;
+ fileSelect->time[fileSelect->copyDestFileIndex + 2] = CURRENT_TIME;
+ fileSelect->day[fileSelect->copyDestFileIndex + 2] = gSaveContext.save.day;
+ fileSelect->isOwlSave[fileSelect->copyDestFileIndex + 2] = gSaveContext.save.isOwlSave;
+ fileSelect->rupees[fileSelect->copyDestFileIndex + 2] = gSaveContext.save.saveInfo.playerData.rupees;
+ fileSelect->walletUpgrades[fileSelect->copyDestFileIndex + 2] = CUR_UPG_VALUE(UPG_WALLET);
+
+ for (i = 0, maskCount = 0; i < MASK_NUM_SLOTS; i++) {
+ if (gSaveContext.save.saveInfo.inventory.items[i + ITEM_NUM_SLOTS] != ITEM_NONE) {
+ maskCount++;
+ }
+ }
+
+ fileSelect->maskCount[fileSelect->copyDestFileIndex + 2] = maskCount;
+ fileSelect->heartPieceCount[fileSelect->copyDestFileIndex + 2] = GET_QUEST_HEART_PIECE_COUNT;
+ }
+
+ // clear buffer
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ // read to buffer
+ if (SysFlashrom_Read(&sramCtx->saveBuf[0], gFlashSaveStartPages[fileSelect->selectedFileIndex * 2],
+ gFlashSaveNumPages[fileSelect->selectedFileIndex * 2])) {}
+
+ if (SysFlashrom_Read(&sramCtx->saveBuf[0x2000], gFlashSaveStartPages[fileSelect->selectedFileIndex * 2 + 1],
+ gFlashSaveNumPages[fileSelect->selectedFileIndex * 2 + 1])) {}
+
+ // copy buffer to save context
+ Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save));
+
+ fileSelect->threeDayResetCount[fileSelect->copyDestFileIndex] =
+ gSaveContext.save.saveInfo.playerData.threeDayResetCount;
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); i++) {
+ fileSelect->fileNames[fileSelect->copyDestFileIndex][i] =
+ gSaveContext.save.saveInfo.playerData.playerName[i];
+ }
+
+ fileSelect->healthCapacity[fileSelect->copyDestFileIndex] =
+ gSaveContext.save.saveInfo.playerData.healthCapacity;
+ fileSelect->health[fileSelect->copyDestFileIndex] = gSaveContext.save.saveInfo.playerData.health;
+ fileSelect->defenseHearts[fileSelect->copyDestFileIndex] = gSaveContext.save.saveInfo.inventory.defenseHearts;
+ fileSelect->questItems[fileSelect->copyDestFileIndex] = gSaveContext.save.saveInfo.inventory.questItems;
+ fileSelect->time[fileSelect->copyDestFileIndex] = CURRENT_TIME;
+ fileSelect->day[fileSelect->copyDestFileIndex] = gSaveContext.save.day;
+ fileSelect->isOwlSave[fileSelect->copyDestFileIndex] = gSaveContext.save.isOwlSave;
+ fileSelect->rupees[fileSelect->copyDestFileIndex] = gSaveContext.save.saveInfo.playerData.rupees;
+ fileSelect->walletUpgrades[fileSelect->copyDestFileIndex] = CUR_UPG_VALUE(UPG_WALLET);
+
+ for (i = 0, maskCount = 0; i < MASK_NUM_SLOTS; i++) {
+ if (gSaveContext.save.saveInfo.inventory.items[i + ITEM_NUM_SLOTS] != ITEM_NONE) {
+ maskCount++;
+ }
+ }
+
+ fileSelect->maskCount[fileSelect->copyDestFileIndex] = maskCount;
+ fileSelect->heartPieceCount[fileSelect->copyDestFileIndex] = GET_QUEST_HEART_PIECE_COUNT;
+ }
+
+ gSaveContext.save.time = D_801F6AF0;
+ gSaveContext.flashSaveAvailable = D_801F6AF2;
+}
+
+void Sram_InitSave(FileSelectState* fileSelect2, SramContext* sramCtx) {
+ s32 phi_v0;
+ u16 i;
+ FileSelectState* fileSelect = fileSelect2;
+ s16 maskCount;
+
+ if (gSaveContext.flashSaveAvailable) {
+ Sram_InitNewSave();
+ if (fileSelect->buttonIndex == 0) {
+ gSaveContext.save.cutsceneIndex = 0xFFF0;
+ }
+
+ for (phi_v0 = 0; phi_v0 < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); phi_v0++) {
+ gSaveContext.save.saveInfo.playerData.playerName[phi_v0] =
+ fileSelect->fileNames[fileSelect->buttonIndex][phi_v0];
+ }
+
+ gSaveContext.save.saveInfo.playerData.newf[0] = 'Z';
+ gSaveContext.save.saveInfo.playerData.newf[1] = 'E';
+ gSaveContext.save.saveInfo.playerData.newf[2] = 'L';
+ gSaveContext.save.saveInfo.playerData.newf[3] = 'D';
+ gSaveContext.save.saveInfo.playerData.newf[4] = 'A';
+ gSaveContext.save.saveInfo.playerData.newf[5] = '3';
+
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save));
+
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext.save, sizeof(Save));
+ Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save));
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.newf); i++) {
+ fileSelect->newf[fileSelect->buttonIndex][i] = gSaveContext.save.saveInfo.playerData.newf[i];
+ }
+
+ fileSelect->threeDayResetCount[fileSelect->buttonIndex] =
+ gSaveContext.save.saveInfo.playerData.threeDayResetCount;
+
+ for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); i++) {
+ fileSelect->fileNames[fileSelect->buttonIndex][i] = gSaveContext.save.saveInfo.playerData.playerName[i];
+ }
+
+ fileSelect->healthCapacity[fileSelect->buttonIndex] = gSaveContext.save.saveInfo.playerData.healthCapacity;
+ fileSelect->health[fileSelect->buttonIndex] = gSaveContext.save.saveInfo.playerData.health;
+ fileSelect->defenseHearts[fileSelect->buttonIndex] = gSaveContext.save.saveInfo.inventory.defenseHearts;
+ fileSelect->questItems[fileSelect->buttonIndex] = gSaveContext.save.saveInfo.inventory.questItems;
+ fileSelect->time[fileSelect->buttonIndex] = CURRENT_TIME;
+ fileSelect->day[fileSelect->buttonIndex] = gSaveContext.save.day;
+ fileSelect->isOwlSave[fileSelect->buttonIndex] = gSaveContext.save.isOwlSave;
+ fileSelect->rupees[fileSelect->buttonIndex] = gSaveContext.save.saveInfo.playerData.rupees;
+ fileSelect->walletUpgrades[fileSelect->buttonIndex] = CUR_UPG_VALUE(UPG_WALLET);
+
+ for (i = 0, maskCount = 0; i < MASK_NUM_SLOTS; i++) {
+ if (gSaveContext.save.saveInfo.inventory.items[i + ITEM_NUM_SLOTS] != ITEM_NONE) {
+ maskCount++;
+ }
+ }
+
+ fileSelect->maskCount[fileSelect->buttonIndex] = maskCount;
+ fileSelect->heartPieceCount[fileSelect->buttonIndex] = GET_QUEST_HEART_PIECE_COUNT;
+ }
+
+ gSaveContext.save.time = D_801F6AF0;
+ gSaveContext.flashSaveAvailable = D_801F6AF2;
+}
+
+/**
+ * Write the SaveOptions of SaveContext to the save buffer
+ */
+void Sram_WriteSaveOptionsToBuffer(SramContext* sramCtx) {
+ if (gSaveContext.flashSaveAvailable) {
+ gSaveContext.options.language = LANGUAGE_ENG;
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext.options, sizeof(SaveOptions));
+ }
+}
+
+void Sram_InitSram(GameState* gameState, SramContext* sramCtx) {
+ if (gSaveContext.save.entrance) {} // Required to match
+
+ Audio_SetFileSelectSettings(gSaveContext.options.audioSetting);
+}
+
+void Sram_Alloc(GameState* gameState, SramContext* sramCtx) {
+ if (gSaveContext.flashSaveAvailable) {
+ sramCtx->saveBuf = THA_AllocTailAlign16(&gameState->tha, SAVE_BUFFER_SIZE);
+ sramCtx->status = 0;
+ }
+}
+
+/**
+ * Synchronous flash write
+ */
+void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages) {
+ sramCtx->curPage = curPage;
+ sramCtx->numPages = numPages;
+ SysFlashrom_WriteSync(sramCtx->saveBuf, curPage, numPages);
+}
+
+/**
+ * Saves the game on the very first time Player enters South Clock Town from the Clock Tower
+ */
+void Sram_SaveSpecialEnterClockTown(PlayState* play) {
+ s32 pad[2];
+ SramContext* sramCtx = &play->sramCtx;
+
+ gSaveContext.save.isFirstCycle = true;
+ gSaveContext.save.isOwlSave = false;
+ func_80145698(sramCtx);
+ SysFlashrom_WriteSync(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2],
+ gFlashSpecialSaveNumPages[gSaveContext.fileNum * 2]);
+}
+
+/**
+ * Saves when beating the game, after showing the "Dawn of the New Day" message
+ */
+void Sram_SaveSpecialNewDay(PlayState* play) {
+ s32 cutsceneIndex = gSaveContext.save.cutsceneIndex;
+ s32 day;
+ u16 time = CURRENT_TIME;
+
+ day = gSaveContext.save.day;
+
+ CLEAR_WEEKEVENTREG(WEEKEVENTREG_84_20);
+
+ Sram_SaveEndOfCycle(play);
+ func_8014546C(&play->sramCtx);
+
+ gSaveContext.save.day = day;
+ gSaveContext.save.time = time;
+ gSaveContext.save.cutsceneIndex = cutsceneIndex;
+ SysFlashrom_WriteSync(play->sramCtx.saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2],
+ gFlashSaveNumPages[gSaveContext.fileNum * 2]);
+}
+
+void Sram_SetFlashPagesDefault(SramContext* sramCtx, u32 curPage, u32 numPages) {
+ sramCtx->curPage = curPage;
+ sramCtx->numPages = numPages;
+ sramCtx->status = 1;
+}
+
+void Sram_StartWriteToFlashDefault(SramContext* sramCtx) {
+ // async flash write
+ SysFlashrom_WriteAsync(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
+
+ sramCtx->startWriteOsTime = osGetTime();
+ sramCtx->status = 2;
+}
+
+void Sram_UpdateWriteToFlashDefault(SramContext* sramCtx) {
+ if (sramCtx->status == 2) {
+ if (SysFlashrom_IsBusy() != 0) { // if task running
+ if (SysFlashrom_AwaitResult() == 0) { // wait for task done
+ // task success
+ sramCtx->status = 4;
+ } else {
+ // task failure
+ sramCtx->status = 4;
+ }
+ }
+ } else if (OSTIME_TO_TIMER(osGetTime() - sramCtx->startWriteOsTime) >= SECONDS_TO_TIMER(2)) {
+ // Finished status is hardcoded to 2 seconds instead of when the task finishes
+ sramCtx->status = 0;
+ }
+}
+
+void Sram_SetFlashPagesOwlSave(SramContext* sramCtx, s32 curPage, s32 numPages) {
+ sramCtx->curPage = curPage;
+ sramCtx->numPages = numPages;
+ sramCtx->status = 6;
+}
+
+void Sram_StartWriteToFlashOwlSave(SramContext* sramCtx) {
+ SysFlashrom_WriteAsync(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
+
+ sramCtx->startWriteOsTime = osGetTime();
+ sramCtx->status = 7;
+}
+
+void Sram_UpdateWriteToFlashOwlSave(SramContext* sramCtx) {
+ if (sramCtx->status == 7) {
+ if (SysFlashrom_IsBusy() != 0) { // Is task running
+ if (SysFlashrom_AwaitResult() == 0) { // Wait for task done
+ SysFlashrom_WriteAsync(sramCtx->saveBuf, sramCtx->curPage + 0x80, sramCtx->numPages);
+ sramCtx->status = 8;
+ } else {
+ SysFlashrom_WriteAsync(sramCtx->saveBuf, sramCtx->curPage + 0x80, sramCtx->numPages);
+ sramCtx->status = 8;
+ }
+ }
+ } else if (sramCtx->status == 8) {
+ if (SysFlashrom_IsBusy() != 0) { // Is task running
+ if (SysFlashrom_AwaitResult() == 0) { // Wait for task done
+ sramCtx->status = 4;
+ } else {
+ sramCtx->status = 4;
+ }
+ }
+ } else if (OSTIME_TO_TIMER(osGetTime() - sramCtx->startWriteOsTime) >= SECONDS_TO_TIMER(2)) {
+ // Finished status is hardcoded to 2 seconds instead of when the task finishes
+ sramCtx->status = 0;
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+ gSaveContext.save.isOwlSave = false;
+ gSaveContext.save.saveInfo.checksum = 0;
+ // flash read to buffer then copy to save context
+ SysFlashrom_Read(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages);
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, offsetof(SaveContext, fileNum));
+ }
+}
+
+void func_80147314(SramContext* sramCtx, s32 fileNum) {
+ s32 pad;
+
+ gSaveContext.save.isOwlSave = false;
+
+ gSaveContext.save.saveInfo.playerData.newf[0] = '\0';
+ gSaveContext.save.saveInfo.playerData.newf[1] = '\0';
+ gSaveContext.save.saveInfo.playerData.newf[2] = '\0';
+ gSaveContext.save.saveInfo.playerData.newf[3] = '\0';
+ gSaveContext.save.saveInfo.playerData.newf[4] = '\0';
+ gSaveContext.save.saveInfo.playerData.newf[5] = '\0';
+
+ gSaveContext.save.saveInfo.checksum = 0;
+ gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum));
+
+ Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum));
+ Sram_SyncWriteToFlash(sramCtx, gFlashOwlSaveStartPages[fileNum * 2], gFlashOwlSaveNumPages[fileNum * 2]);
+ //! Note: should be `gFlashOwlSaveNumPages[fileNum * 2 + 1]`?
+ Sram_SyncWriteToFlash(sramCtx, gFlashOwlSaveStartPages[fileNum * 2 + 1], gFlashOwlSaveNumPages[fileNum * 2]);
+
+ gSaveContext.save.isOwlSave = true;
+
+ gSaveContext.save.saveInfo.playerData.newf[0] = 'Z';
+ gSaveContext.save.saveInfo.playerData.newf[1] = 'E';
+ gSaveContext.save.saveInfo.playerData.newf[2] = 'L';
+ gSaveContext.save.saveInfo.playerData.newf[3] = 'D';
+ gSaveContext.save.saveInfo.playerData.newf[4] = 'A';
+ gSaveContext.save.saveInfo.playerData.newf[5] = '3';
+}
+
+// Used by `Sram_CopySave` with `isOwlSave` set
+void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2) {
+ s32 pad;
+
+ // Clear save buffer
+ bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE);
+
+ // Read save file
+ if (SysFlashrom_Read(sramCtx->saveBuf, gFlashOwlSaveStartPages[fileNum * 2], gFlashOwlSaveNumPages[fileNum * 2]) !=
+ 0) {
+ // If failed, read backup save file
+ SysFlashrom_Read(sramCtx->saveBuf, gFlashOwlSaveStartPages[fileNum * 2 + 1],
+ gFlashOwlSaveNumPages[fileNum * 2 + 1]);
+ }
+
+ // Copy buffer to save context
+ Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, offsetof(SaveContext, fileNum));
+
+ Sram_SyncWriteToFlash(sramCtx, gFlashOwlSaveStartPages[arg2 * 2], gFlashOwlSaveNumPages[arg2 * 2]);
+ Sram_SyncWriteToFlash(sramCtx, gFlashOwlSaveStartPages[arg2 * 2 + 1], gFlashOwlSaveNumPages[arg2 * 2]);
+}
+
+void Sram_nop8014750C(UNK_TYPE4 arg0) {
+}
diff --git a/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c b/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c
new file mode 100644
index 000000000..5b723f45f
--- /dev/null
+++ b/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.c
@@ -0,0 +1,40 @@
+/*
+ * File: z_bg_heavy_block.c
+ * Overlay: ovl_Bg_Heavy_Block
+ * Description: Large block that can only be lifted with Golden Gauntlets (JP only)
+ */
+
+#include "z_bg_heavy_block.h"
+
+#include "versions.h"
+
+#define FLAGS 0
+
+void BgHeavyBlock_Init(Actor* thisx, PlayState* play);
+void BgHeavyBlock_Destroy(Actor* thisx, PlayState* play);
+void BgHeavyBlock_Update(Actor* thisx, PlayState* play);
+void BgHeavyBlock_Draw(Actor* thisx, PlayState* play);
+
+ActorProfile Bg_Heavy_Block_Profile = {
+ /**/ ACTOR_BG_HEAVY_BLOCK,
+ /**/ ACTORCAT_BG,
+ /**/ FLAGS,
+ /**/ OBJECT_HEAVY_OBJECT,
+ /**/ sizeof(BgHeavyBlock),
+ /**/ BgHeavyBlock_Init,
+ /**/ BgHeavyBlock_Destroy,
+ /**/ BgHeavyBlock_Update,
+ /**/ BgHeavyBlock_Draw,
+};
+
+void BgHeavyBlock_Init(Actor* thisx, PlayState* play) {
+}
+
+void BgHeavyBlock_Destroy(Actor* thisx, PlayState* play) {
+}
+
+void BgHeavyBlock_Update(Actor* thisx, PlayState* play) {
+}
+
+void BgHeavyBlock_Draw(Actor* thisx, PlayState* play) {
+}
diff --git a/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.h b/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.h
new file mode 100644
index 000000000..9870296e4
--- /dev/null
+++ b/src/overlays/actors/ovl_Bg_Heavy_Block/z_bg_heavy_block.h
@@ -0,0 +1,16 @@
+#ifndef Z_BG_HEAVY_BLOCK_H
+#define Z_BG_HEAVY_BLOCK_H
+
+#include "global.h"
+
+struct BgHeavyBlock;
+
+typedef void (*BgHeavyBlockActionFunc)(struct BgHeavyBlock*, PlayState*);
+
+typedef struct BgHeavyBlock {
+ /* 0x000 */ DynaPolyActor dyna;
+ /* 0x15C */ char unk_15C[0x16C - 0x15C];
+ /* 0x16C */ BgHeavyBlockActionFunc actionFunc;
+} BgHeavyBlock; // size = 0x170
+
+#endif // Z_BG_HEAVY_BLOCK_H
diff --git a/src/overlays/actors/ovl_Obj_Warpstone/z_obj_warpstone.c b/src/overlays/actors/ovl_Obj_Warpstone/z_obj_warpstone.c
index 35d7b16ec..d0e38a258 100644
--- a/src/overlays/actors/ovl_Obj_Warpstone/z_obj_warpstone.c
+++ b/src/overlays/actors/ovl_Obj_Warpstone/z_obj_warpstone.c
@@ -136,16 +136,20 @@ void ObjWarpstone_Update(Actor* thisx, PlayState* play) {
if (this->isTalking) {
if (Actor_TextboxIsClosing(&this->dyna.actor, play)) {
this->isTalking = false;
- } else if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
- if (play->msgCtx.choiceIndex != 0) {
- Audio_PlaySfx_MessageDecide();
- play->msgCtx.msgMode = MSGMODE_OWL_SAVE_0;
- play->msgCtx.unk120D6 = 0;
- play->msgCtx.unk120D4 = 0;
- gSaveContext.save.owlWarpId = OBJ_WARPSTONE_GET_OWL_WARP_ID(&this->dyna.actor);
- } else {
- Message_CloseTextbox(play);
+ } else {
+#if MM_VERSION >= N64_US
+ if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) {
+ if (play->msgCtx.choiceIndex != 0) {
+ Audio_PlaySfx_MessageDecide();
+ play->msgCtx.msgMode = MSGMODE_OWL_SAVE_0;
+ play->msgCtx.unk120D6 = 0;
+ play->msgCtx.unk120D4 = 0;
+ gSaveContext.save.owlWarpId = OBJ_WARPSTONE_GET_OWL_WARP_ID(&this->dyna.actor);
+ } else {
+ Message_CloseTextbox(play);
+ }
}
+#endif
}
} else if (Actor_TalkOfferAccepted(&this->dyna.actor, &play->state)) {
this->isTalking = true;
diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c
index e4ba3d02f..349689191 100644
--- a/src/overlays/actors/ovl_player_actor/z_player.c
+++ b/src/overlays/actors/ovl_player_actor/z_player.c
@@ -12225,7 +12225,9 @@ s8 sPlayerCueToCsActionMap[PLAYER_CUEID_MAX] = {
PLAYER_CSACTION_120, // PLAYER_CUEID_88
PLAYER_CSACTION_114, // PLAYER_CUEID_89
PLAYER_CSACTION_111, // PLAYER_CUEID_90
- PLAYER_CSACTION_122, // PLAYER_CUEID_91
+#if MM_VERSION >= N64_US
+ PLAYER_CSACTION_122, // PLAYER_CUEID_91
+#endif
};
f32 D_8085D3E0[PLAYER_FORM_MAX] = {
@@ -20204,7 +20206,9 @@ PlayerCsActionEntry sPlayerCsActionInitFuncs[PLAYER_CSACTION_MAX] = {
/* PLAYER_CSACTION_119 */ { PLAYER_CSTYPE_ANIM_7, { &gPlayerAnim_demo_suwari2 } },
/* PLAYER_CSACTION_120 */ { PLAYER_CSTYPE_ANIM_7, { &gPlayerAnim_demo_suwari3 } },
/* PLAYER_CSACTION_121 */ { PLAYER_CSTYPE_ACTION, { Player_CsAction_7 } },
+#if MM_VERSION >= N64_US
/* PLAYER_CSACTION_122 */ { PLAYER_CSTYPE_NONE, { NULL } },
+#endif
/* PLAYER_CSACTION_123 */ { PLAYER_CSTYPE_ACTION, { Player_CsAction_9 } },
/* PLAYER_CSACTION_124 */ { PLAYER_CSTYPE_ANIM_7, { &gPlayerAnim_clink_demo_get1 } },
/* PLAYER_CSACTION_125 */ { PLAYER_CSTYPE_ANIM_5, { &gPlayerAnim_clink_demo_get2 } },
@@ -20347,7 +20351,9 @@ PlayerCsActionEntry sPlayerCsActionUpdateFuncs[PLAYER_CSACTION_MAX] = {
/* PLAYER_CSACTION_119 */ { PLAYER_CSTYPE_ANIM_11, { NULL } },
/* PLAYER_CSACTION_120 */ { PLAYER_CSTYPE_ANIM_11, { NULL } },
/* PLAYER_CSACTION_121 */ { PLAYER_CSTYPE_ACTION, { Player_CsAction_8 } },
+#if MM_VERSION >= N64_US
/* PLAYER_CSACTION_122 */ { PLAYER_CSTYPE_ACTION, { Player_CsAction_12 } },
+#endif
/* PLAYER_CSACTION_123 */ { PLAYER_CSTYPE_ACTION, { Player_CsAction_10 } },
/* PLAYER_CSACTION_125 */ { PLAYER_CSTYPE_ANIM_11, { NULL } },
/* PLAYER_CSACTION_124 */ { PLAYER_CSTYPE_ANIM_11, { NULL } },
diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose_JPN.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose_JPN.c
new file mode 100644
index 000000000..f7355f72b
--- /dev/null
+++ b/src/overlays/gamestates/ovl_file_choose/z_file_choose_JPN.c
@@ -0,0 +1,2536 @@
+/*
+ * File: z_file_choose_NES.c
+ * Overlay: ovl_file_choose
+ * Description:
+ */
+
+#include "z_file_select.h"
+#include "overlays/gamestates/ovl_opening/z_opening.h"
+#include "z64rumble.h"
+#include "z64save.h"
+#include "z64shrink_window.h"
+#include "z64view.h"
+#include "assets/interface/parameter_static/parameter_static.h"
+#include "assets/misc/title_static/title_static.h"
+
+s32 D_808144F10 = 100;
+f32 D_808144F14 = 8.0f;
+f32 D_808144F18 = 100.0f;
+s32 D_808144F1C = 0;
+
+static Gfx sScreenFillSetupDL[] = {
+ gsDPPipeSync(),
+ gsSPClearGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BOTH | G_FOG | G_LIGHTING | G_TEXTURE_GEN |
+ G_TEXTURE_GEN_LINEAR | G_LOD | G_SHADING_SMOOTH),
+ gsDPSetOtherMode(G_AD_DISABLE | G_CD_MAGICSQ | G_CK_NONE | G_TC_FILT | G_TF_BILERP | G_TT_NONE | G_TL_TILE |
+ G_TD_CLAMP | G_TP_NONE | G_CYC_1CYCLE | G_PM_1PRIMITIVE,
+ G_AC_NONE | G_ZS_PIXEL | G_RM_CLD_SURF | G_RM_CLD_SURF2),
+ gsDPSetCombineMode(G_CC_PRIMITIVE, G_CC_PRIMITIVE),
+ gsSPEndDisplayList(),
+};
+
+s16 sFileInfoBoxPartWidths[] = {
+ 36, 36, 36, 36, 24, 28, 28,
+};
+
+s16 sWindowContentColors[] = { 100, 150, 255 };
+
+s16 sFileSelectSkyboxRotation = 0;
+
+s16 sWalletFirstDigit[] = {
+ 1, // tens (Default Wallet)
+ 0, // hundreds (Adult Wallet)
+ 0, // hundreds (Giant Wallet)
+};
+
+void FileSelect_IncrementConfigMode(FileSelectState* this) {
+ this->configMode++;
+}
+
+void FileSelect_Noop1(void) {
+}
+
+void FileSelect_Noop2(FileSelectState* this) {
+}
+
+void FileSelect_InitModeUpdate(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ if (this->configMode == CM_FADE_IN_START) {
+ if (gSaveContext.options.optionId != 0xA51D) { // Magic number?
+ this->configMode++;
+ } else {
+ this->menuMode = FS_MENU_MODE_CONFIG;
+ this->configMode = CM_FADE_IN_START;
+ this->titleLabel = FS_TITLE_SELECT_FILE;
+ this->nextTitleLabel = FS_TITLE_OPEN_FILE;
+ }
+ }
+
+ if (this->configMode == CM_FADE_IN_END) {
+ this->screenFillAlpha -= 40;
+ if (this->screenFillAlpha <= 0) {
+ this->screenFillAlpha = 0;
+ this->configMode++; // CM_MAIN_MENU
+ }
+ } else if (this->configMode == CM_MAIN_MENU) {
+ FileSelect_IncrementConfigMode(this); // CM_SETUP_COPY_SOURCE
+ } else {
+ this->screenFillAlpha += 40;
+ if (this->screenFillAlpha >= 255) {
+ this->screenFillAlpha = 255;
+ this->menuMode = FS_MENU_MODE_CONFIG;
+ this->configMode = CM_FADE_IN_START;
+ this->titleLabel = FS_TITLE_SELECT_FILE;
+ this->nextTitleLabel = FS_TITLE_OPEN_FILE;
+ }
+ }
+}
+
+void FileSelect_InitModeDraw(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ Gfx_SetupDL39_Opa(this->state.gfxCtx);
+ FileSelect_Noop2(this);
+}
+
+void FileSelect_SetView(FileSelectState* this, f32 eyeX, f32 eyeY, f32 eyeZ) {
+ Vec3f eye;
+ Vec3f lookAt;
+ Vec3f up;
+
+ eye.x = eyeX;
+ eye.y = eyeY;
+ eye.z = eyeZ;
+
+ lookAt.x = lookAt.y = lookAt.z = 0.0f;
+
+ up.x = up.z = 0.0f;
+ up.y = 1.0f;
+
+ View_LookAt(&this->view, &eye, &lookAt, &up);
+ View_Apply(&this->view, VIEW_ALL | VIEW_FORCE_VIEWING | VIEW_FORCE_VIEWPORT | VIEW_FORCE_PROJECTION_PERSPECTIVE);
+}
+
+Gfx* FileSelect_DrawTexQuadIA8(Gfx* gfx, TexturePtr texture, s16 width, s16 height, s16 point) {
+ gDPLoadTextureBlock(gfx++, texture, G_IM_FMT_IA, G_IM_SIZ_8b, width, height, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ gSP1Quadrangle(gfx++, point, point + 2, point + 3, point + 1, 0);
+
+ return gfx;
+}
+
+/**
+ * Fade in the menu window and title label.
+ * If a file is occupied fade in the name, name box, and connector.
+ * Fade in the copy erase and options button according to the window alpha.
+ */
+void FileSelect_FadeInMenuElements(FileSelectState* this) {
+ SramContext* sramCtx = &this->sramCtx;
+ s16 i;
+
+ this->titleAlpha[FS_TITLE_CUR] += 20;
+ this->windowAlpha += 16;
+
+ for (i = 0; i < 3; i++) {
+ this->fileButtonAlpha[i] = this->windowAlpha;
+
+ if (!gSaveContext.flashSaveAvailable) {
+ if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) {
+ this->nameBoxAlpha[i] = this->nameAlpha[i] = this->windowAlpha;
+ this->connectorAlpha[i] += 20;
+ if (this->connectorAlpha[i] >= 255) {
+ this->connectorAlpha[i] = 255;
+ }
+ }
+ } else if (SLOT_OCCUPIED(this, i)) {
+ this->nameBoxAlpha[i] = this->nameAlpha[i] = this->windowAlpha;
+ this->connectorAlpha[i] += 20;
+
+ if (this->connectorAlpha[i] >= 255) {
+ this->connectorAlpha[i] = 255;
+ }
+ }
+ }
+
+ this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] =
+ this->optionButtonAlpha = this->windowAlpha;
+}
+
+/**
+ * Converts a numerical value to hundreds-tens-ones digits
+ */
+void FileSelect_SplitNumber(u16 value, u16* hundreds, u16* tens, u16* ones) {
+ *hundreds = 0;
+ *tens = 0;
+ *ones = value;
+
+ do {
+ if ((*ones - 100) < 0) {
+ break;
+ }
+ (*hundreds)++;
+ *ones -= 100;
+ } while (true);
+
+ do {
+ if ((*ones - 10) < 0) {
+ break;
+ }
+ (*tens)++;
+ *ones -= 10;
+ } while (true);
+}
+
+// Start of Config Mode Update Functions
+
+/**
+ * Reduce the alpha of the black screen fill to create a fade in effect.
+ * Additionally, slide the window from the right to the center of the screen.
+ * Update function for `CM_FADE_IN_START`
+ */
+void FileSelect_StartFadeIn(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ FileSelect_FadeInMenuElements(this);
+ this->screenFillAlpha -= 40;
+ this->windowPosX -= 20;
+
+ if (this->windowPosX <= -94) {
+ this->windowPosX = -94;
+ this->configMode = CM_FADE_IN_END;
+ this->screenFillAlpha = 0;
+ }
+}
+
+/**
+ * Finish fading in the remaining menu elements.
+ * Fade in the controls text at the bottom of the screen.
+ * Update function for `CM_FADE_IN_END`
+ */
+void FileSelect_FinishFadeIn(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->controlsAlpha += 20;
+ FileSelect_FadeInMenuElements(this);
+
+ if (this->titleAlpha[FS_TITLE_CUR] >= 255) {
+ this->titleAlpha[FS_TITLE_CUR] = 255;
+ this->controlsAlpha = 255;
+ this->windowAlpha = 200;
+ this->configMode = CM_MAIN_MENU;
+ }
+}
+
+u8 sEmptyName[] = { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E };
+
+/**
+ * Update the cursor and wait for the player to select a button to change menus accordingly.
+ * If an empty file is selected, enter the name entry config mode.
+ * If an occupied file is selected, enter the `Select` menu mode.
+ * If copy, erase, or options is selected, set config mode accordingly.
+ * Lastly, set any warning labels if appropriate.
+ * Update function for `CM_MAIN_MENU`
+ */
+void FileSelect_UpdateMainMenu(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+ Input* input = CONTROLLER1(&this->state);
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ if (this->buttonIndex <= FS_BTN_MAIN_FILE_3) {
+ if (!gSaveContext.flashSaveAvailable) {
+ if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->configMode = CM_ROTATE_TO_NAME_ENTRY;
+ this->kbdButton = FS_KBD_BTN_NONE;
+ this->charPage = FS_CHAR_PAGE_HIRA;
+ if (gSaveContext.options.language != LANGUAGE_JPN) {
+ this->charPage = FS_CHAR_PAGE_ENG;
+ }
+ this->kbdX = 0;
+ this->kbdY = 0;
+ this->charIndex = 0;
+ this->charBgAlpha = 0;
+ this->newFileNameCharCount = 0;
+ this->nameEntryBoxPosX = 120;
+ this->nameEntryBoxAlpha = 0;
+ Lib_MemCpy(&this->fileNames[this->buttonIndex], &sEmptyName, ARRAY_COUNT(sEmptyName));
+ } else {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->actionTimer = 4;
+ this->selectMode = SM_FADE_MAIN_TO_SELECT;
+ this->selectedFileIndex = this->buttonIndex;
+ this->menuMode = FS_MENU_MODE_SELECT;
+ this->nextTitleLabel = FS_TITLE_OPEN_FILE;
+ }
+ } else if (!SLOT_OCCUPIED(this, this->buttonIndex)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->configMode = CM_ROTATE_TO_NAME_ENTRY;
+ this->kbdButton = FS_KBD_BTN_NONE;
+ this->charPage = FS_CHAR_PAGE_HIRA;
+ if (gSaveContext.options.language != LANGUAGE_JPN) {
+ this->charPage = FS_CHAR_PAGE_ENG;
+ }
+ this->kbdX = 0;
+ this->kbdY = 0;
+ this->charIndex = 0;
+ this->charBgAlpha = 0;
+ this->newFileNameCharCount = 0;
+ this->nameEntryBoxPosX = 120;
+ this->nameEntryBoxAlpha = 0;
+ Lib_MemCpy(&this->fileNames[this->buttonIndex], &sEmptyName, ARRAY_COUNT(sEmptyName));
+ } else {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->actionTimer = 4;
+ this->selectMode = SM_FADE_MAIN_TO_SELECT;
+ this->selectedFileIndex = this->buttonIndex;
+ this->menuMode = FS_MENU_MODE_SELECT;
+ this->nextTitleLabel = FS_TITLE_OPEN_FILE;
+ }
+ } else if (this->warningLabel == FS_WARNING_NONE) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->prevConfigMode = this->configMode;
+
+ if (this->buttonIndex == FS_BTN_MAIN_COPY) {
+ this->configMode = CM_SETUP_COPY_SOURCE;
+ this->nextTitleLabel = FS_TITLE_COPY_FROM;
+ } else if (this->buttonIndex == FS_BTN_MAIN_ERASE) {
+ this->configMode = CM_SETUP_ERASE_SELECT;
+ this->nextTitleLabel = FS_TITLE_ERASE_FILE;
+ } else {
+ this->configMode = CM_MAIN_TO_OPTIONS;
+ this->kbdButton = FS_KBD_BTN_HIRA;
+ this->kbdX = 0;
+ this->kbdY = 0;
+ this->charBgAlpha = 0;
+ this->newFileNameCharCount = 0;
+ this->nameEntryBoxPosX = 120;
+ }
+ this->actionTimer = 4;
+ } else {
+ Audio_PlaySfx(NA_SE_SY_FSEL_ERROR);
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ gSaveContext.gameMode = GAMEMODE_TITLE_SCREEN;
+ STOP_GAMESTATE(&this->state);
+ SET_NEXT_GAMESTATE(&this->state, TitleSetup_Init, sizeof(TitleSetupState));
+ } else {
+ if (ABS_ALT(this->stickAdjY) > 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ if (this->stickAdjY > 30) {
+ this->buttonIndex--;
+ if (this->buttonIndex == FS_BTN_MAIN_FILE_3) {
+ this->buttonIndex = FS_BTN_MAIN_FILE_2;
+ }
+ if (this->buttonIndex < FS_BTN_MAIN_FILE_1) {
+ this->buttonIndex = FS_BTN_MAIN_OPTIONS;
+ }
+ } else {
+ this->buttonIndex++;
+ if (this->buttonIndex == FS_BTN_MAIN_FILE_3) {
+ this->buttonIndex = FS_BTN_MAIN_COPY;
+ }
+ if (this->buttonIndex > FS_BTN_MAIN_OPTIONS) {
+ this->buttonIndex = FS_BTN_MAIN_FILE_1;
+ }
+ }
+ }
+
+ if (this->buttonIndex == FS_BTN_MAIN_COPY) {
+ if (!gSaveContext.flashSaveAvailable) {
+ if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, 0) && !NO_FLASH_SLOT_OCCUPIED(sramCtx, 1) &&
+ !NO_FLASH_SLOT_OCCUPIED(sramCtx, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_FILE_COPY;
+ this->emptyFileTextAlpha = 255;
+ } else if (NO_FLASH_SLOT_OCCUPIED(sramCtx, 0) && NO_FLASH_SLOT_OCCUPIED(sramCtx, 1) &&
+ NO_FLASH_SLOT_OCCUPIED(sramCtx, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_EMPTY_FILES;
+ this->emptyFileTextAlpha = 255;
+ } else {
+ this->warningLabel = FS_WARNING_NONE;
+ }
+ } else {
+ if (!SLOT_OCCUPIED(this, 0) && !SLOT_OCCUPIED(this, 1) && !SLOT_OCCUPIED(this, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_FILE_COPY;
+ this->emptyFileTextAlpha = 255;
+ } else if (SLOT_OCCUPIED(this, 0) && SLOT_OCCUPIED(this, 1) && SLOT_OCCUPIED(this, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_EMPTY_FILES;
+ this->emptyFileTextAlpha = 255;
+ } else {
+ this->warningLabel = FS_WARNING_NONE;
+ }
+ }
+ } else if (this->buttonIndex == FS_BTN_MAIN_ERASE) {
+ if (!gSaveContext.flashSaveAvailable) {
+ if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, 0) && !NO_FLASH_SLOT_OCCUPIED(sramCtx, 1) &&
+ !NO_FLASH_SLOT_OCCUPIED(sramCtx, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_FILE_ERASE;
+ this->emptyFileTextAlpha = 255;
+ } else {
+ this->warningLabel = FS_WARNING_NONE;
+ }
+ } else {
+ if (!SLOT_OCCUPIED(this, 0) && !SLOT_OCCUPIED(this, 1) && !SLOT_OCCUPIED(this, 2)) {
+ this->warningButtonIndex = this->buttonIndex;
+ this->warningLabel = FS_WARNING_NO_FILE_ERASE;
+ this->emptyFileTextAlpha = 255;
+ } else {
+ this->warningLabel = FS_WARNING_NONE;
+ }
+ }
+ } else {
+ this->warningLabel = FS_WARNING_NONE;
+ }
+ }
+}
+
+/**
+ * Update function for `CM_UNUSED_31`
+ */
+void FileSelect_UnusedCM31(GameState* thisx) {
+}
+
+/**
+ * Delay the next config mode from running until `D_80814564` reaches 254.
+ * Because the timer increments by 2, the delay is 127 frames (assuming the value was not changed by reg editor).
+ * Unused in the final game, was possibly used for debugging.
+ * Update function for `CM_UNUSED_DELAY`
+ */
+void FileSelect_UnusedCMDelay(GameState* thisx) {
+ static s16 D_80814564 = 0;
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ D_80814564 += 2;
+
+ if (D_80814564 == 254) {
+ this->configMode = this->nextConfigMode;
+ D_80814564 = 0;
+ }
+}
+
+/**
+ * Rotate the window from the main menu to the name entry menu.
+ * Update function for `CM_ROTATE_TO_NAME_ENTRY`
+ */
+void FileSelect_RotateToNameEntry(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->windowRot += 50.0f;
+
+ if (this->windowRot >= 314.0f) {
+ this->windowRot = 314.0f;
+ this->configMode = CM_START_NAME_ENTRY;
+ }
+}
+
+/**
+ * Rotate the window from the main menu to the options menu.
+ * Update function for `CM_MAIN_TO_OPTIONS`
+ */
+void FileSelect_RotateToOptions(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->windowRot += 50.0f;
+
+ if (this->windowRot >= 314.0f) {
+ this->windowRot = 314.0f;
+ this->configMode = CM_START_OPTIONS;
+ }
+}
+
+/**
+ * Rotate the window from the options menu to the main menu.
+ * Update function for `CM_NAME_ENTRY_TO_MAIN` and `CM_OPTIONS_TO_MAIN`
+ */
+void FileSelect_RotateToMain(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->windowRot += 50.0f;
+
+ if (this->windowRot >= 628.0f) {
+ this->windowRot = 0.0f;
+ this->configMode = CM_MAIN_MENU;
+ }
+}
+
+void (*sConfigModeUpdateFuncs[])(GameState*) = {
+ // Main Menu
+ FileSelect_StartFadeIn, // CM_FADE_IN_START
+ FileSelect_FinishFadeIn, // CM_FADE_IN_END
+ FileSelect_UpdateMainMenu, // CM_MAIN_MENU
+ // Copy File
+ FileSelect_SetupCopySource, // CM_SETUP_COPY_SOURCE
+ FileSelect_SelectCopySource, // CM_SELECT_COPY_SOURCE
+ FileSelect_SetupCopyDest1, // CM_SETUP_COPY_DEST_1
+ FileSelect_SetupCopyDest2, // CM_SETUP_COPY_DEST_2
+ FileSelect_SelectCopyDest, // CM_SELECT_COPY_DEST
+ FileSelect_ExitToCopySource1, // CM_EXIT_TO_COPY_SOURCE_1
+ FileSelect_ExitToCopySource2, // CM_EXIT_TO_COPY_SOURCE_2
+ FileSelect_SetupCopyConfirm1, // CM_SETUP_COPY_CONFIRM_1
+ FileSelect_SetupCopyConfirm2, // CM_SETUP_COPY_CONFIRM_2
+ FileSelect_CopyConfirm, // CM_COPY_CONFIRM
+ FileSelect_CopyWaitForFlashSave, // CM_COPY_WAIT_FOR_FLASH_SAVE
+ FileSelect_ReturnToCopyDest, // CM_RETURN_TO_COPY_DEST
+ FileSelect_CopyAnim1, // CM_COPY_ANIM_1
+ FileSelect_CopyAnim2, // CM_COPY_ANIM_2
+ FileSelect_CopyAnim3, // CM_COPY_ANIM_3
+ FileSelect_CopyAnim4, // CM_COPY_ANIM_4
+ FileSelect_CopyAnim5, // CM_COPY_ANIM_5
+ FileSelect_ExitCopyToMain, // CM_COPY_RETURN_MAIN
+ // Erase File
+ FileSelect_SetupEraseSelect, // CM_SETUP_ERASE_SELECT
+ FileSelect_EraseSelect, // CM_ERASE_SELECT
+ FileSelect_SetupEraseConfirm1, // CM_SETUP_ERASE_CONFIRM_1
+ FileSelect_SetupEraseConfirm2, // CM_SETUP_ERASE_CONFIRM_2
+ FileSelect_EraseConfirm, // CM_ERASE_CONFIRM
+ FileSelect_ExitToEraseSelect1, // CM_EXIT_TO_ERASE_SELECT_1
+ FileSelect_ExitToEraseSelect2, // CM_EXIT_TO_ERASE_SELECT_2
+ FileSelect_EraseAnim1, // CM_ERASE_ANIM_1
+ FileSelect_EraseWaitForFlashSave, // CM_ERASE_WAIT_FOR_FLASH_SAVE
+ FileSelect_EraseAnim2, // CM_ERASE_ANIM_2
+ FileSelect_EraseAnim3, // CM_ERASE_ANIM_3
+ FileSelect_ExitEraseToMain, // CM_EXIT_ERASE_TO_MAIN
+ FileSelect_UnusedCM31, // CM_UNUSED_31
+ // New File Name Entry
+ FileSelect_RotateToNameEntry, // CM_ROTATE_TO_NAME_ENTRY
+ FileSelect_StartNameEntry, // CM_START_NAME_ENTRY
+ FileSelect_UpdateKeyboardCursor, // CM_NAME_ENTRY
+ FileSelect_NameEntryWaitForFlashSave, // CM_NAME_ENTRY_WAIT_FOR_FLASH_SAVE
+ FileSelect_RotateToMain, // CM_NAME_ENTRY_TO_MAIN
+ // Options
+ FileSelect_RotateToOptions, // CM_MAIN_TO_OPTIONS
+ FileSelect_StartOptions, // CM_START_OPTIONS
+ FileSelect_UpdateOptionsMenu, // CM_OPTIONS_MENU
+ FileSelect_OptionsWaitForFlashSave, // CM_OPTIONS_WAIT_FOR_FLASH_SAVE
+ FileSelect_RotateToMain, // CM_OPTIONS_TO_MAIN
+ // Possible Debug
+ FileSelect_UnusedCMDelay, // CM_UNUSED_DELAY
+};
+
+s16 sCursorAlphaTargets[] = { 70, 200 };
+
+/**
+ * Updates the alpha of the cursor to make it pulsate.
+ */
+void FileSelect_PulsateCursor(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s32 alphaStep =
+ ABS_ALT(this->highlightColor[3] - sCursorAlphaTargets[this->highlightPulseDir]) / this->highlightTimer;
+
+ if (this->highlightColor[3] >= sCursorAlphaTargets[this->highlightPulseDir]) {
+ this->highlightColor[3] -= alphaStep;
+ } else {
+ this->highlightColor[3] += alphaStep;
+ }
+
+ this->highlightTimer--;
+
+ if (this->highlightTimer == 0) {
+ this->highlightColor[3] = sCursorAlphaTargets[this->highlightPulseDir];
+ this->highlightTimer = 20;
+ this->highlightPulseDir ^= 1;
+ }
+}
+
+void FileSelect_ConfigModeUpdate(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ sConfigModeUpdateFuncs[this->configMode](&this->state);
+}
+
+void FileSelect_SetWindowVtx(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s16 i;
+ s16 j;
+ s16 x;
+ s32 tmp;
+ s32 tmp2;
+ s32 tmp3;
+
+ this->windowVtx = GRAPH_ALLOC(this->state.gfxCtx, 80 * sizeof(Vtx));
+ tmp = this->windowPosX - 90;
+
+ for (x = 0, i = 0; i < 4; i++) {
+ tmp += 0x40;
+ tmp2 = (i == 3) ? 0x30 : 0x40;
+
+ for (j = 0, tmp3 = 0x50; j < 5; j++, x += 4, tmp3 -= 0x20) {
+ this->windowVtx[x].v.ob[0] = this->windowVtx[x + 2].v.ob[0] = tmp;
+
+ this->windowVtx[x + 1].v.ob[0] = this->windowVtx[x + 3].v.ob[0] = tmp2 + tmp;
+
+ this->windowVtx[x].v.ob[1] = this->windowVtx[x + 1].v.ob[1] = tmp3;
+
+ this->windowVtx[x + 2].v.ob[1] = this->windowVtx[x + 3].v.ob[1] = tmp3 - 0x20;
+
+ this->windowVtx[x].v.ob[2] = this->windowVtx[x + 1].v.ob[2] = this->windowVtx[x + 2].v.ob[2] =
+ this->windowVtx[x + 3].v.ob[2] = 0;
+
+ this->windowVtx[x].v.flag = this->windowVtx[x + 1].v.flag = this->windowVtx[x + 2].v.flag =
+ this->windowVtx[x + 3].v.flag = 0;
+
+ this->windowVtx[x].v.tc[0] = this->windowVtx[x].v.tc[1] = this->windowVtx[x + 1].v.tc[1] =
+ this->windowVtx[x + 2].v.tc[0] = 0;
+
+ this->windowVtx[x + 1].v.tc[0] = this->windowVtx[x + 3].v.tc[0] = tmp2 << 5;
+
+ this->windowVtx[x + 2].v.tc[1] = this->windowVtx[x + 3].v.tc[1] = 32 << 5;
+
+ this->windowVtx[x].v.cn[0] = this->windowVtx[x + 2].v.cn[0] = this->windowVtx[x].v.cn[1] =
+ this->windowVtx[x + 2].v.cn[1] = this->windowVtx[x].v.cn[2] = this->windowVtx[x + 2].v.cn[2] =
+ this->windowVtx[x + 1].v.cn[0] = this->windowVtx[x + 3].v.cn[0] = this->windowVtx[x + 1].v.cn[1] =
+ this->windowVtx[x + 3].v.cn[1] = this->windowVtx[x + 1].v.cn[2] =
+ this->windowVtx[x + 3].v.cn[2] = this->windowVtx[x].v.cn[3] =
+ this->windowVtx[x + 2].v.cn[3] = this->windowVtx[x + 1].v.cn[3] =
+ this->windowVtx[x + 3].v.cn[3] = 255;
+ }
+ }
+}
+
+s16 D_80814620[] = { 8, 8, 8, 0 };
+s16 D_80814628[] = { 12, 12, 12, 0 };
+s16 D_80814630[] = { 12, 12, 12, 0 };
+s16 D_80814638[] = {
+ 88, 104, 120, 940, 944, 948,
+};
+s16 D_80814644[] = { 88, 104, 120, 944 };
+s16 D_8081464C[] = { 940, 944 };
+s16 D_80814650[] = { 940, 944 };
+
+/*
+ * fileSelect->windowContentVtx[0] -> Title Label (4)
+ *
+ * fileSelect->windowContentVtx[4] -> File 1 InfoBox (28)
+ * fileSelect->windowContentVtx[32] -> File 2 InfoBox (28)
+ * fileSelect->windowContentVtx[60] -> File 3 InfoBox (28)
+ *
+ * ** FILE 1 **
+ *
+ * fileSelect->windowContentVtx[88] -> File Button
+ * fileSelect->windowContentVtx[92] -> File Name Box
+ * fileSelect->windowContentVtx[96] -> Connectors
+ * fileSelect->windowContentVtx[100] -> Blank Button (Owl Save)
+ *
+ * ** FILE 2 **
+ *
+ * fileSelect->windowContentVtx[104] -> Repeat of File 1 above
+ *
+ * ** FILE 3 **
+ *
+ * fileSelect->windowContentVtx[120] -> Repeat of File 1 above
+ *
+ * ** FILE 1 Info **
+ *
+ * fileSelect->windowContentVtx[136] -> File Name (32)
+ * fileSelect->windowContentVtx[168] -> File Name Shadow (32)
+ * fileSelect->windowContentVtx[200] -> Rupee Digits (12)
+ * fileSelect->windowContentVtx[212] -> Rupee Digits Shadow (12)
+ * fileSelect->windowContentVtx[224] -> Mask Count (8)
+ * fileSelect->windowContentVtx[232] -> Mask Count Shadow (8)
+ * fileSelect->windowContentVtx[240] -> Hearts (80)
+ * fileSelect->windowContentVtx[320] -> Remains (16)
+ * fileSelect->windowContentVtx[336] -> Rupee Icon (4)
+ * fileSelect->windowContentVtx[340] -> Heart Piece Count (4)
+ * fileSelect->windowContentVtx[344] -> Mask Text (8)
+ * fileSelect->windowContentVtx[352] -> Owl Save Icon (4)
+ * fileSelect->windowContentVtx[356] -> Day Text (8)
+ * fileSelect->windowContentVtx[364] -> Time Digits (20)
+ * fileSelect->windowContentVtx[384] -> Time Digits Shadow (20)
+ *
+ * ** FILE 2 Info **
+ *
+ * fileSelect->windowContentVtx[404] -> Repeat of File 1 above
+ *
+ * ** FILE 3 Info **
+ *
+ * fileSelect->windowContentVtx[672] -> Repeat of File 1 above
+ *
+ * fileSelect->windowContentVtx[940] -> Action buttons (copy/erase/yes/quit)
+ * fileSelect->windowContentVtx[944] -> Action buttons (copy/erase/yes/quit)
+ * fileSelect->windowContentVtx[948] -> Option Button
+ * fileSelect->windowContentVtx[952] -> Highlight over currently selected button
+ * fileSelect->windowContentVtx[956] -> Warning labels
+ */
+
+void FileSelect_SetWindowContentVtx(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ u16 vtxId;
+ s16 j;
+ s16 i;
+ s16 spAC;
+ u16 spA4[3];
+ u16* ptr;
+ s32 posY;
+ s32 relPosY;
+ s32 tempPosY;
+ s32 posX;
+ s32 index;
+
+ this->windowContentVtx = GRAPH_ALLOC(this->state.gfxCtx, 960 * sizeof(Vtx));
+
+ // Initialize all windowContentVtx
+ for (vtxId = 0; vtxId < 960; vtxId += 4) {
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = 0x12C;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 16;
+
+ // y-coord (top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = 0;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 16;
+
+ // z-coordinate
+ this->windowContentVtx[vtxId + 0].v.ob[2] = this->windowContentVtx[vtxId + 1].v.ob[2] =
+ this->windowContentVtx[vtxId + 2].v.ob[2] = this->windowContentVtx[vtxId + 3].v.ob[2] = 0;
+
+ // flag
+ this->windowContentVtx[vtxId + 0].v.flag = this->windowContentVtx[vtxId + 1].v.flag =
+ this->windowContentVtx[vtxId + 2].v.flag = this->windowContentVtx[vtxId + 3].v.flag = 0;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 0].v.tc[0] = this->windowContentVtx[vtxId + 0].v.tc[1] =
+ this->windowContentVtx[vtxId + 1].v.tc[1] = this->windowContentVtx[vtxId + 2].v.tc[0] = 0;
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 2].v.tc[1] =
+ this->windowContentVtx[vtxId + 3].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x200;
+
+ // alpha
+ this->windowContentVtx[vtxId + 0].v.cn[0] = this->windowContentVtx[vtxId + 1].v.cn[0] =
+ this->windowContentVtx[vtxId + 2].v.cn[0] = this->windowContentVtx[vtxId + 3].v.cn[0] =
+ this->windowContentVtx[vtxId + 0].v.cn[1] = this->windowContentVtx[vtxId + 1].v.cn[1] =
+ this->windowContentVtx[vtxId + 2].v.cn[1] = this->windowContentVtx[vtxId + 3].v.cn[1] =
+ this->windowContentVtx[vtxId + 0].v.cn[2] = this->windowContentVtx[vtxId + 1].v.cn[2] =
+ this->windowContentVtx[vtxId + 2].v.cn[2] = this->windowContentVtx[vtxId + 3].v.cn[2] =
+ this->windowContentVtx[vtxId + 0].v.cn[3] = this->windowContentVtx[vtxId + 1].v.cn[3] =
+ this->windowContentVtx[vtxId + 2].v.cn[3] =
+ this->windowContentVtx[vtxId + 3].v.cn[3] = 255;
+ }
+
+ /** Title Label **/
+
+ // x-coord (left)
+ this->windowContentVtx[0].v.ob[0] = this->windowContentVtx[2].v.ob[0] = this->windowPosX;
+ // x-coord (right)
+ this->windowContentVtx[1].v.ob[0] = this->windowContentVtx[3].v.ob[0] = this->windowContentVtx[0].v.ob[0] + 0x80;
+ // y-coord (top)
+ this->windowContentVtx[0].v.ob[1] = this->windowContentVtx[1].v.ob[1] = 0x48;
+ // y-coord (bottom)
+ this->windowContentVtx[2].v.ob[1] = this->windowContentVtx[3].v.ob[1] = this->windowContentVtx[0].v.ob[1] - 0x10;
+ // texture coordinates
+ this->windowContentVtx[1].v.tc[0] = this->windowContentVtx[3].v.tc[0] = 0x1000;
+
+ /** File InfoBox **/
+
+ // Loop through 3 files
+ for (vtxId = 4, i = 0; i < 3; i++) {
+ posX = this->windowPosX - 6;
+
+ // Loop through 7 textures
+ for (j = 0; j < 7; j++, vtxId += 4) {
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + sFileInfoBoxPartWidths[j];
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] =
+ this->fileNamesY[i] + 0x2C;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x38;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] =
+ sFileInfoBoxPartWidths[j] << 5;
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x700;
+
+ // Update X position
+ posX += sFileInfoBoxPartWidths[j];
+ }
+ }
+
+ // File Buttons
+
+ posX = this->windowPosX - 6;
+ posY = 44;
+
+ // Loop through 3 files
+ for (j = 0; j < 3; j++, vtxId += 16, posY -= 0x10) {
+
+ /* File Button */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x40;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] =
+ this->buttonYOffsets[j] + posY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x800;
+
+ /* File Name Box */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 4].v.ob[0] = this->windowContentVtx[vtxId + 6].v.ob[0] = posX + 0x40;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 5].v.ob[0] = this->windowContentVtx[vtxId + 7].v.ob[0] =
+ this->windowContentVtx[vtxId + 4].v.ob[0] + 0x6C;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 4].v.ob[1] = this->windowContentVtx[vtxId + 5].v.ob[1] =
+ this->buttonYOffsets[j] + posY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 6].v.ob[1] = this->windowContentVtx[vtxId + 7].v.ob[1] =
+ this->windowContentVtx[vtxId + 4].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 5].v.tc[0] = this->windowContentVtx[vtxId + 7].v.tc[0] = 0xD80;
+
+ /* Connectors */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 8].v.ob[0] = this->windowContentVtx[vtxId + 10].v.ob[0] = posX + 0x34;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 9].v.ob[0] = this->windowContentVtx[vtxId + 11].v.ob[0] =
+ this->windowContentVtx[vtxId + 8].v.ob[0] + 0x18;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 8].v.ob[1] = this->windowContentVtx[vtxId + 9].v.ob[1] =
+ this->buttonYOffsets[j] + posY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 10].v.ob[1] = this->windowContentVtx[vtxId + 11].v.ob[1] =
+ this->windowContentVtx[vtxId + 8].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 9].v.tc[0] = this->windowContentVtx[vtxId + 11].v.tc[0] = 0x300;
+
+ /* Blank Button (Owl Save) */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 12].v.ob[0] = this->windowContentVtx[vtxId + 14].v.ob[0] = posX + 0xA9;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 13].v.ob[0] = this->windowContentVtx[vtxId + 15].v.ob[0] =
+ this->windowContentVtx[vtxId + 12].v.ob[0] + 0x34;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 12].v.ob[1] = this->windowContentVtx[vtxId + 13].v.ob[1] =
+ this->buttonYOffsets[j] + posY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 14].v.ob[1] = this->windowContentVtx[vtxId + 15].v.ob[1] =
+ this->windowContentVtx[vtxId + 12].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 13].v.tc[0] = this->windowContentVtx[vtxId + 15].v.tc[0] = 0x680;
+ }
+
+ posY = 44;
+
+ // Loop through 3 files
+ for (j = 0; j < 3; j++, posY -= 16) {
+ if (!gSaveContext.flashSaveAvailable) {
+ // Should skip vtxId
+ // vtxId += 268;
+ continue;
+ }
+
+ // Account for owl-save offset
+
+ spAC = j;
+ if (this->isOwlSave[j + 2]) {
+ spAC = j + 2;
+ }
+
+ /* File name */
+
+ posX = this->windowPosX - 6;
+
+ if ((this->configMode == 0x10) && (j == this->copyDestFileIndex)) {
+ relPosY = this->fileNamesY[j] + 0x2C;
+ } else if (((this->configMode == 0x11) || (this->configMode == 0x12)) && (j == this->copyDestFileIndex)) {
+ relPosY = this->buttonYOffsets[j] + posY;
+ } else {
+ relPosY = posY + this->buttonYOffsets[j] + this->fileNamesY[j];
+ }
+
+ tempPosY = relPosY - 2;
+
+ // Loop through 8 characters of file name
+ for (i = 0; i < 8; i++, vtxId += 4) {
+
+ index = this->fileNames[j][i];
+
+ /* File Name */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] =
+ D_80814280[index] + posX + 0x4E;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0xB;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0xC;
+
+ /* File Name Shadow */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 32].v.ob[0] = this->windowContentVtx[vtxId + 34].v.ob[0] =
+ D_80814280[index] + posX + 0x4F;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 33].v.ob[0] = this->windowContentVtx[vtxId + 35].v.ob[0] =
+ this->windowContentVtx[vtxId + 32].v.ob[0] + 0xB;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 32].v.ob[1] = this->windowContentVtx[vtxId + 33].v.ob[1] = tempPosY - 1;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 34].v.ob[1] = this->windowContentVtx[vtxId + 35].v.ob[1] =
+ this->windowContentVtx[vtxId + 32].v.ob[1] - 0xC;
+
+ // Update X position
+ posX += 10;
+ }
+ // Account for the shadow
+ vtxId += 32;
+
+ /* Rupee Digits */
+
+ posX = this->windowPosX + 14;
+ tempPosY = relPosY - 0x18;
+
+ FileSelect_SplitNumber(this->rupees[spAC], &spA4[0], &spA4[1], &spA4[2]);
+
+ index = sWalletFirstDigit[this->walletUpgrades[spAC]];
+
+ ptr = &spA4[index];
+
+ for (i = 0; i < 3; i++, vtxId += 4, ptr++) {
+
+ /* Rupee Digits */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] =
+ D_80814280[*ptr] + posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + D_80814628[i];
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - D_80814630[i];
+
+ /* Rupee Digits Shadow */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 12].v.ob[0] = this->windowContentVtx[vtxId + 14].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 1;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 13].v.ob[0] = this->windowContentVtx[vtxId + 15].v.ob[0] =
+ this->windowContentVtx[vtxId + 12].v.ob[0] + D_80814628[i];
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 12].v.ob[1] = this->windowContentVtx[vtxId + 13].v.ob[1] = tempPosY - 1;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 14].v.ob[1] = this->windowContentVtx[vtxId + 15].v.ob[1] =
+ this->windowContentVtx[vtxId + 12].v.ob[1] - D_80814630[i];
+
+ // Update X position
+ posX += D_80814620[i];
+ }
+
+ // Account for the shadow
+ vtxId += 12;
+
+ /* Mask Count */
+
+ posX = this->windowPosX + 42;
+ tempPosY = relPosY - 0x2A;
+
+ FileSelect_SplitNumber(this->maskCount[spAC], &spA4[0], &spA4[1], &spA4[2]);
+
+ for (i = 1; i < 3; i++, vtxId += 4) {
+
+ /* Mask Count */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] =
+ D_80814280[spA4[i]] + posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + D_80814628[i];
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - D_80814630[i];
+
+ /* Mask Count Shadow */
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 8].v.ob[0] = this->windowContentVtx[vtxId + 10].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 1;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 9].v.ob[0] = this->windowContentVtx[vtxId + 11].v.ob[0] =
+ this->windowContentVtx[vtxId + 8].v.ob[0] + D_80814628[i];
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 8].v.ob[1] = this->windowContentVtx[vtxId + 9].v.ob[1] = tempPosY - 1;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 10].v.ob[1] = this->windowContentVtx[vtxId + 11].v.ob[1] =
+ this->windowContentVtx[vtxId + 8].v.ob[1] - D_80814630[i];
+
+ // Update X position
+ posX += D_80814620[i];
+ }
+
+ // Account for the shadow
+ vtxId += 8;
+
+ /* Hearts */
+
+ posX = this->windowPosX + 63;
+ tempPosY = relPosY - 0x10;
+
+ // Loop through 20 hearts
+ for (i = 0; i < 20; i++, vtxId += 4, posX += 9) {
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0xA;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0xA;
+
+ // New row of hearts next iteration
+ if (i == 9) {
+ posX = this->windowPosX + (63 - 9);
+ tempPosY -= 8;
+ }
+ }
+
+ /* Quest Remains */
+
+ posX = this->windowPosX + 64;
+ tempPosY = relPosY - 0x20;
+
+ // Loop through 4 Remains
+ for (i = 0; i < 4; i++, vtxId += 4, posX += 0x18) {
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x14;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x14;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 2].v.tc[1] =
+ this->windowContentVtx[vtxId + 3].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x400;
+ }
+
+ /* Rupee Icon */
+
+ // posX = this->windowPosX - 1;
+ tempPosY = relPosY - 0x15;
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = this->windowPosX - 1;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x10;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x200;
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x200;
+
+ vtxId += 4;
+
+ /* Heart Piece Count */
+
+ // posX = this->windowPosX + 0x27;
+ tempPosY = relPosY - 0x15;
+
+ // x-coord (left)
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = this->windowPosX + 0x27;
+ // x-coord (right)
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x18;
+
+ // y-coord(top)
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+ // y-coord (bottom)
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ // texture coordinates
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x300;
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x200;
+
+ vtxId += 4;
+
+ /* Mask Text */
+
+ // posX = this->windowPosX - 10;
+ tempPosY = relPosY - 0x27;
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = this->windowPosX - 10;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x40;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x800;
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x200;
+
+ this->windowContentVtx[vtxId + 4].v.ob[0] = this->windowContentVtx[vtxId + 6].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 1;
+
+ this->windowContentVtx[vtxId + 5].v.ob[0] = this->windowContentVtx[vtxId + 7].v.ob[0] =
+ this->windowContentVtx[vtxId + 4].v.ob[0] + 0x40;
+
+ this->windowContentVtx[vtxId + 4].v.ob[1] = this->windowContentVtx[vtxId + 5].v.ob[1] = tempPosY - 1;
+
+ this->windowContentVtx[vtxId + 6].v.ob[1] = this->windowContentVtx[vtxId + 7].v.ob[1] =
+ this->windowContentVtx[vtxId + 4].v.ob[1] - 0x10;
+
+ this->windowContentVtx[vtxId + 5].v.tc[0] = this->windowContentVtx[vtxId + 7].v.tc[0] = 0x800;
+ this->windowContentVtx[vtxId + 6].v.tc[1] = this->windowContentVtx[vtxId + 7].v.tc[1] = 0x200;
+
+ vtxId += 8;
+
+ /* Owl Save Icon */
+
+ posX = this->windowPosX + 0xA3;
+
+ if ((this->configMode == 0x10) && (j == this->copyDestFileIndex)) {
+ tempPosY = this->fileNamesY[j] + 0x2C;
+ } else if (((this->configMode == 0x11) || (this->configMode == 0x12)) && (j == this->copyDestFileIndex)) {
+ tempPosY = this->buttonYOffsets[j] + posY;
+ } else {
+ tempPosY = posY + this->buttonYOffsets[j] + this->fileNamesY[j];
+ }
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX + 0xE;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x18;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY - 2;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0xC;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x300;
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x180;
+
+ vtxId += 4;
+
+ /* Day Text */
+
+ for (i = 0; i < 2; i++, vtxId += 4) {
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = 2 + posX + i;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x30;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY - i - 0x12;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x18;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x600;
+
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x300;
+ }
+
+ /* Time Digits */
+
+ posX += 6;
+ index = vtxId;
+
+ for (i = 0; i < 5; i++, vtxId += 4, posX += 8) {
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0xC;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] = tempPosY - 0x2A;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0xC;
+
+ this->windowContentVtx[vtxId + 0x14].v.ob[0] = this->windowContentVtx[vtxId + 0x16].v.ob[0] = posX + 1;
+
+ this->windowContentVtx[vtxId + 0x15].v.ob[0] = this->windowContentVtx[vtxId + 0x17].v.ob[0] =
+ this->windowContentVtx[vtxId + 0x14].v.ob[0] + 0xC;
+
+ this->windowContentVtx[vtxId + 0x14].v.ob[1] = this->windowContentVtx[vtxId + 0x15].v.ob[1] =
+ tempPosY - 0x2B;
+
+ this->windowContentVtx[vtxId + 0x16].v.ob[1] = this->windowContentVtx[vtxId + 0x17].v.ob[1] =
+ this->windowContentVtx[vtxId + 0x14].v.ob[1] - 0xC;
+ }
+
+ // Adjust the colon to the right
+ this->windowContentVtx[index + 8].v.ob[0] = this->windowContentVtx[index + 10].v.ob[0] =
+ this->windowContentVtx[index + 8].v.ob[0] + 3;
+
+ this->windowContentVtx[index + 9].v.ob[0] = this->windowContentVtx[index + 11].v.ob[0] =
+ this->windowContentVtx[index + 8].v.ob[0] + 0xC;
+
+ this->windowContentVtx[index + 0x1C].v.ob[0] = this->windowContentVtx[index + 0x1E].v.ob[0] =
+ this->windowContentVtx[index + 8].v.ob[0] + 1;
+
+ this->windowContentVtx[index + 0x1D].v.ob[0] = this->windowContentVtx[index + 0x1F].v.ob[0] =
+ this->windowContentVtx[index + 0x1C].v.ob[0] + 0xC;
+
+ vtxId += 20;
+ }
+
+ posX = this->windowPosX - 6;
+ posY = -0xC;
+
+ for (j = 0; j < 2; j++, vtxId += 4, posY -= 0x10) {
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x40;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] =
+ this->buttonYOffsets[j + 3] + posY;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x800;
+ }
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = posX;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x40;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] =
+ this->buttonYOffsets[5] - 0x34;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x10;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x800;
+
+ vtxId += 4;
+
+ if (((this->menuMode == FS_MENU_MODE_CONFIG) && (this->configMode >= 2)) ||
+ ((this->menuMode == FS_MENU_MODE_SELECT) && (this->selectMode == 3))) {
+ if (this->menuMode == FS_MENU_MODE_CONFIG) {
+ if ((this->configMode == 4) || (this->configMode == 7) || (this->configMode == 0x16)) {
+ j = D_80814644[this->buttonIndex];
+ } else if ((this->configMode == 0x19) || (this->configMode == 0xC)) {
+ j = D_8081464C[this->buttonIndex];
+ } else {
+ j = D_80814638[this->buttonIndex];
+ }
+ } else {
+ j = D_80814650[this->confirmButtonIndex];
+ }
+
+ this->windowContentVtx[vtxId + 0].v.ob[0] = this->windowContentVtx[vtxId + 2].v.ob[0] = this->windowPosX - 0xA;
+
+ this->windowContentVtx[vtxId + 1].v.ob[0] = this->windowContentVtx[vtxId + 3].v.ob[0] =
+ this->windowContentVtx[vtxId + 0].v.ob[0] + 0x48;
+
+ this->windowContentVtx[vtxId + 0].v.ob[1] = this->windowContentVtx[vtxId + 1].v.ob[1] =
+ this->windowContentVtx[j].v.ob[1] + 4;
+
+ this->windowContentVtx[vtxId + 2].v.ob[1] = this->windowContentVtx[vtxId + 3].v.ob[1] =
+ this->windowContentVtx[vtxId + 0].v.ob[1] - 0x18;
+
+ this->windowContentVtx[vtxId + 1].v.tc[0] = this->windowContentVtx[vtxId + 3].v.tc[0] = 0x900;
+
+ this->windowContentVtx[vtxId + 2].v.tc[1] = this->windowContentVtx[vtxId + 3].v.tc[1] = 0x300;
+ }
+
+ this->windowContentVtx[vtxId + 4].v.ob[0] = this->windowContentVtx[vtxId + 6].v.ob[0] = this->windowPosX + 0x3A;
+
+ this->windowContentVtx[vtxId + 5].v.ob[0] = this->windowContentVtx[vtxId + 7].v.ob[0] =
+ this->windowContentVtx[vtxId + 4].v.ob[0] + 0x80;
+
+ this->windowContentVtx[vtxId + 4].v.ob[1] = this->windowContentVtx[vtxId + 5].v.ob[1] =
+ this->windowContentVtx[D_80814638[this->warningButtonIndex]].v.ob[1];
+
+ this->windowContentVtx[vtxId + 6].v.ob[1] = this->windowContentVtx[vtxId + 7].v.ob[1] =
+ this->windowContentVtx[vtxId + 4].v.ob[1] - 0x10;
+
+ this->windowContentVtx[vtxId + 5].v.tc[0] = this->windowContentVtx[vtxId + 7].v.tc[0] = 0x1000;
+}
+
+u16 D_80814654[] = {
+ 0x88,
+ 0x194,
+ 0x2A0,
+};
+TexturePtr sFileSelRemainsTextures[] = {
+ gFileSelOdolwasRemainsTex,
+ gFileSelGohtsRemainsTex,
+ gFileSelGyorgsRemainsTex,
+ gFileSelTwinmoldsRemainsTex,
+};
+TexturePtr sFileSelDayENGTextures[] = {
+ gFileSelFirstDayENGTex,
+ gFileSelFirstDayENGTex,
+ gFileSelSecondDayENGTex,
+ gFileSelFinalDayENGTex,
+};
+TexturePtr sFileSelHeartPieceTextures[] = {
+ gFileSel0QuarterHeartENGTex,
+ gFileSel1QuarterHeartENGTex,
+ gFileSel2QuarterHeartENGTex,
+ gFileSel3QuarterHeartENGTex,
+};
+static TexturePtr sHeartTextures[2][5] = {
+ {
+ gHeartEmptyTex,
+ gHeartQuarterTex,
+ gHeartHalfTex,
+ gHeartThreeQuarterTex,
+ gHeartFullTex,
+ },
+ {
+ gDefenseHeartEmptyTex,
+ gDefenseHeartQuarterTex,
+ gDefenseHeartHalfTex,
+ gDefenseHeartThreeQuarterTex,
+ gDefenseHeartFullTex,
+ },
+};
+u8 sHealthToQuarterHeartCount[] = {
+ 0, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3,
+};
+s16 sFileSelRupeePrimColors[3][3] = {
+ { 200, 255, 100 }, // Default Wallet
+ { 170, 170, 255 }, // Adult Wallet
+ { 255, 105, 105 }, // Giant Wallet
+};
+s16 sFileSelRupeeEnvColors[3][3] = {
+ { 0, 80, 0 }, // Default Wallet
+ { 10, 10, 80 }, // Adult Wallet
+ { 40, 10, 0 }, // Giant Wallet
+};
+static s16 sHeartPrimColors[2][3] = {
+ { 255, 70, 50 },
+ { 200, 0, 0 },
+};
+static s16 sHeartEnvColors[2][3] = {
+ { 50, 40, 60 },
+ { 255, 255, 255 },
+};
+
+void FileSelect_DrawFileInfo(GameState* thisx, s16 fileIndex) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ Font* font = &this->font;
+ s16 j;
+ s16 vtxOffset;
+ s32 heartType;
+ s16 i;
+ s16 sp20C;
+ s16 health;
+ s16 timeDigits[5];
+ u16 digits[3]; // rupees and mask count
+ u8 quarterHeartCount;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0,
+ PRIMITIVE, 0);
+
+ sp20C = fileIndex;
+
+ // draw file name
+ if (this->nameAlpha[fileIndex] != 0) {
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + (4 * 8)], 32, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->nameAlpha[fileIndex]);
+
+ for (vtxOffset = 0, i = 0; vtxOffset < (4 * 8); i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx,
+ font->fontBuf + this->fileNames[fileIndex][i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex]], 32, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->nameAlpha[fileIndex]);
+
+ for (vtxOffset = 0, i = 0; vtxOffset < (4 * 8); i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx,
+ font->fontBuf + this->fileNames[fileIndex][i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+ }
+
+ if ((fileIndex == this->selectedFileIndex) || (fileIndex == this->copyDestFileIndex)) {
+ if (this->isOwlSave[fileIndex + 2]) {
+ sp20C = fileIndex + 2;
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, sFileSelRupeePrimColors[this->walletUpgrades[sp20C]][0],
+ sFileSelRupeePrimColors[this->walletUpgrades[sp20C]][1],
+ sFileSelRupeePrimColors[this->walletUpgrades[sp20C]][2], this->fileInfoAlpha[fileIndex]);
+ gDPSetEnvColor(POLY_OPA_DISP++, sFileSelRupeeEnvColors[this->walletUpgrades[sp20C]][0],
+ sFileSelRupeeEnvColors[this->walletUpgrades[sp20C]][1],
+ sFileSelRupeeEnvColors[this->walletUpgrades[sp20C]][2], 255);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xC8], 4, 0);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelRupeeTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
+ PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0x4C], 12, 0);
+
+ FileSelect_SplitNumber((u16)this->rupees[sp20C], &digits[0], &digits[1], &digits[2]);
+
+ for (vtxOffset = 0, i = sWalletFirstDigit[this->walletUpgrades[sp20C]]; i < 3; i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + digits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+
+ if (this->rupees[sp20C] == gUpgradeCapacities[4][this->walletUpgrades[sp20C]]) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 120, 255, 0, this->fileInfoAlpha[fileIndex]);
+ } else if (this->rupees[sp20C] != 0) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 100, 100, 100, this->fileInfoAlpha[fileIndex]);
+ }
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0x40], 12, 0);
+
+ for (vtxOffset = 0, i = sWalletFirstDigit[this->walletUpgrades[sp20C]]; i < 3; i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + digits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
+ PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 0, 0, this->fileInfoAlpha[fileIndex]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xCC], 4, 0);
+
+ POLY_OPA_DISP = FileSelect_DrawTexQuadIA8(
+ POLY_OPA_DISP, sFileSelHeartPieceTextures[this->heartPieceCount[sp20C]], 0x18, 0x10, 0);
+
+ if (this->defenseHearts[sp20C] == 0) {
+ heartType = 0;
+ } else {
+ heartType = 1;
+ }
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, sHeartPrimColors[heartType][0], sHeartPrimColors[heartType][1],
+ sHeartPrimColors[heartType][2], this->fileInfoAlpha[fileIndex]);
+ gDPSetEnvColor(POLY_OPA_DISP++, sHeartEnvColors[heartType][0], sHeartEnvColors[heartType][1],
+ sHeartEnvColors[heartType][2], 255);
+
+ i = this->healthCapacity[sp20C] / 0x10;
+
+ health = this->health[sp20C];
+ if (health <= 0x30) {
+ health = 0x30;
+ }
+
+ quarterHeartCount = 4;
+ for (vtxOffset = 0, j = 0; j < i; j++, vtxOffset += 4) {
+ if (health < 0x10) {
+ if (health != 0) {
+ quarterHeartCount = sHealthToQuarterHeartCount[health];
+ health = 0;
+ } else {
+ quarterHeartCount = 0;
+ }
+ } else {
+ health -= 0x10;
+ }
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0x68 + vtxOffset], 4, 0);
+ POLY_OPA_DISP =
+ FileSelect_DrawTexQuadIA8(POLY_OPA_DISP, sHeartTextures[heartType][quarterHeartCount], 0x10, 0x10, 0);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+
+ for (vtxOffset = 0, j = 0; j < 4; j++, vtxOffset += 4) {
+ if (this->questItems[sp20C] & gBitFlags[j]) {
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xB8 + vtxOffset], 4, 0);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sFileSelRemainsTextures[j], G_IM_FMT_RGBA, G_IM_SIZ_32b, 32, 32, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ }
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
+ PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xD0], 8, 0);
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, gFileSelMASKSENGTex, G_IM_FMT_I, 64, 16, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 4, 6, 7, 5, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0x60], 8, 0);
+
+ FileSelect_SplitNumber(this->maskCount[sp20C], &digits[0], &digits[1], &digits[2]);
+
+ for (vtxOffset = 0, i = 1; i < 3; i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + digits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0x58], 8, 0);
+
+ for (vtxOffset = 0, i = 1; i < 3; i++, vtxOffset += 4) {
+
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + digits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+ }
+
+ if (this->isOwlSave[fileIndex + 2]) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->nameAlpha[fileIndex]);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xD8], 4, 0);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelOwlSaveIconTex, G_IM_FMT_RGBA, G_IM_SIZ_32b, 24, 12, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xDC], 8, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->fileInfoAlpha[fileIndex]);
+
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, sFileSelDayENGTextures[this->day[sp20C]], G_IM_FMT_I, 48, 24, 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);
+ gSP1Quadrangle(POLY_OPA_DISP++, 4, 6, 7, 5, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ timeDigits[0] = 0;
+ timeDigits[1] = TIME_TO_MINUTES_F(this->time[sp20C]) / 60.0f;
+
+ while (timeDigits[1] >= 10) {
+ timeDigits[0]++;
+ timeDigits[1] -= 10;
+ }
+
+ timeDigits[3] = 0;
+ timeDigits[4] = (s32)TIME_TO_MINUTES_F(this->time[sp20C]) % 60;
+
+ while (timeDigits[4] >= 10) {
+ timeDigits[3]++;
+ timeDigits[4] -= 10;
+ }
+ timeDigits[2] = 0x41;
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
+ PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 0, 0, 0, this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xF8], 20, 0);
+
+ for (i = 0, vtxOffset = 0; i < 5; i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + timeDigits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0x00, 0x00, 255, 255, 255, this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[D_80814654[fileIndex] + 0xE4], 20, 0);
+
+ for (i = 0, vtxOffset = 0; i < 5; i++, vtxOffset += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + timeDigits[i] * FONT_CHAR_TEX_SIZE, vtxOffset);
+ }
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+TexturePtr sFileInfoBoxTextures[] = {
+ gFileSelFileInfoBox0Tex, gFileSelFileInfoBox1Tex, gFileSelFileInfoBox2Tex, gFileSelFileInfoBox3Tex,
+ gFileSelFileInfoBox4Tex, gFileSelFileExtraInfoBox0Tex, gFileSelFileExtraInfoBox1Tex,
+};
+
+TexturePtr sTitleLabels[] = {
+ gFileSelPleaseSelectAFileENGTex, gFileSelOpenThisFileENGTex, gFileSelCopyWhichFileENGTex,
+ gFileSelCopyToWhichFileENGTex, gFileSelAreYouSureCopyENGTex, gFileSelFileCopiedENGTex,
+ gFileSelEraseWhichFileENGTex, gFileSelAreYouSureEraseENGTex, gFileSelFileErasedENGTex,
+};
+
+TexturePtr sWarningLabels[] = {
+ gFileSelNoFileToCopyENGTex, gFileSelNoFileToEraseENGTex, gFileSelNoEmptyFileENGTex,
+ gFileSelFileEmptyENGTex, gFileSelFileInUseENGTex,
+};
+
+TexturePtr sFileButtonTextures[] = {
+ gFileSelFile1ButtonENGTex,
+ gFileSelFile2ButtonENGTex,
+ gFileSelFile3ButtonENGTex,
+};
+
+TexturePtr sActionButtonTextures[] = {
+ gFileSelCopyButtonENGTex,
+ gFileSelEraseButtonENGTex,
+ gFileSelYesButtonENGTex,
+ gFileSelQuitButtonENGTex,
+};
+
+/**
+ * Draw most window contents including buttons, labels, and icons.
+ * Does not include anything from the keyboard and settings windows.
+ */
+void FileSelect_DrawWindowContents(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s16 fileIndex;
+ s16 temp;
+ s16 i;
+ s16 quadVtxIndex;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ // draw title label
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[0], 4, 0);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sTitleLabels[this->titleLabel], G_IM_FMT_IA, G_IM_SIZ_8b, 128, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ // draw next title label
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_NEXT]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sTitleLabels[this->nextTitleLabel], G_IM_FMT_IA, G_IM_SIZ_8b, 128, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ temp = 4;
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ // draw file info box (large box when a file is selected)
+ for (fileIndex = 0; fileIndex < 3; fileIndex++, temp += 28) {
+ if (fileIndex < 2) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->fileInfoAlpha[fileIndex]);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 28, 0);
+
+ for (quadVtxIndex = 0, i = 0; i < 7; i++, quadVtxIndex += 4) {
+ if ((i < 5) || (this->isOwlSave[fileIndex + 2] && (i >= 5))) {
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sFileInfoBoxTextures[i], G_IM_FMT_IA, G_IM_SIZ_16b,
+ sFileInfoBoxPartWidths[i], 56, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, quadVtxIndex, quadVtxIndex + 2, quadVtxIndex + 3, quadVtxIndex + 1,
+ 0);
+ }
+ }
+ }
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ for (i = 0; i < 3; i++, temp += 16) {
+ if (i < 2) {
+ // draw file button
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[temp], 16, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[0], sWindowContentColors[1],
+ sWindowContentColors[2], this->fileButtonAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sFileButtonTextures[i], G_IM_FMT_IA, G_IM_SIZ_16b, 64, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ // draw file name box
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[0], sWindowContentColors[1],
+ sWindowContentColors[2], this->nameBoxAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelFileNameBoxTex, G_IM_FMT_IA, G_IM_SIZ_16b, 108, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 4, 6, 7, 5, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[0], sWindowContentColors[1],
+ sWindowContentColors[2], this->connectorAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelConnectorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 24, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 8, 10, 11, 9, 0);
+
+ if (this->isOwlSave[i + 2]) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sWindowContentColors[0], sWindowContentColors[1],
+ sWindowContentColors[2], this->nameBoxAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelBlankButtonTex, G_IM_FMT_IA, G_IM_SIZ_16b, 52, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK,
+ G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 12, 14, 15, 13, 0);
+ }
+ }
+ }
+
+ // draw file info
+ for (fileIndex = 0; fileIndex < 2; fileIndex++) {
+ FileSelect_DrawFileInfo(&this->state, fileIndex);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+ gSPVertex(POLY_OPA_DISP++, &this->windowContentVtx[0x3AC], 20, 0);
+
+ // draw primary action buttons (copy/erase)
+ for (quadVtxIndex = 0, i = 0; i < 2; i++, quadVtxIndex += 4) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->actionButtonAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sActionButtonTextures[i], G_IM_FMT_IA, G_IM_SIZ_16b, 64, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, quadVtxIndex, quadVtxIndex + 2, quadVtxIndex + 3, quadVtxIndex + 1, 0);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ // draw confirm buttons (yes/quit)
+ for (quadVtxIndex = 0, i = FS_BTN_CONFIRM_YES; i <= FS_BTN_CONFIRM_QUIT; i++, quadVtxIndex += 4) {
+ temp = this->confirmButtonTexIndices[i];
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->confirmButtonAlpha[i]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sActionButtonTextures[temp], G_IM_FMT_IA, G_IM_SIZ_16b, 64, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, quadVtxIndex, quadVtxIndex + 2, quadVtxIndex + 3, quadVtxIndex + 1, 0);
+ }
+
+ // draw options button
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->optionButtonAlpha);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelOptionsButtonENGTex, G_IM_FMT_IA, G_IM_SIZ_16b, 64, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 8, 10, 11, 9, 0);
+
+ // draw highlight over currently selected button
+ if (((this->menuMode == FS_MENU_MODE_CONFIG) &&
+ ((this->configMode == CM_MAIN_MENU) || (this->configMode == CM_SELECT_COPY_SOURCE) ||
+ (this->configMode == CM_SELECT_COPY_DEST) || (this->configMode == CM_COPY_CONFIRM) ||
+ (this->configMode == CM_ERASE_SELECT) || (this->configMode == CM_ERASE_CONFIRM))) ||
+ ((this->menuMode == FS_MENU_MODE_SELECT) && (this->selectMode == SM_CONFIRM_FILE))) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
+ PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1],
+ this->highlightColor[2], this->highlightColor[3]);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelBigButtonHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 72, 24, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 12, 14, 15, 13, 0);
+ }
+
+ // draw warning labels
+ if (this->warningLabel > FS_WARNING_NONE) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
+ PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->emptyFileTextAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sWarningLabels[this->warningLabel], G_IM_FMT_IA, G_IM_SIZ_8b, 128, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 16, 18, 19, 17, 0);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_ConfigModeDraw(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ Gfx_SetupDL42_Opa(this->state.gfxCtx);
+ FileSelect_SetView(this, 0.0f, 0.0f, 64.0f);
+ FileSelect_SetWindowVtx(&this->state);
+ FileSelect_SetWindowContentVtx(&this->state);
+
+ if ((this->configMode != CM_NAME_ENTRY) && (this->configMode != CM_START_NAME_ENTRY)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->windowAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+
+ if (this->windowRot != 0) {
+ Matrix_RotateXFApply(this->windowRot / 100.0f);
+ }
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[0], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow1DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[32], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow2DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[64], 16, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow3DL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ FileSelect_DrawWindowContents(&this->state);
+ }
+
+ // draw name entry menu
+ if ((this->configMode >= CM_ROTATE_TO_NAME_ENTRY) && (this->configMode <= CM_NAME_ENTRY_TO_MAIN)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->windowAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply((this->windowRot - 314.0f) / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[0], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow1DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[32], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow2DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[64], 16, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow3DL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ FileSelect_DrawNameEntry(&this->state);
+ }
+
+ // draw options menu
+ if ((this->configMode >= CM_MAIN_TO_OPTIONS) && (this->configMode <= CM_OPTIONS_TO_MAIN)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->windowAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply((this->windowRot - 314.0f) / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[0], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow1DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[32], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow2DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[64], 16, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow3DL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ FileSelect_DrawOptions(&this->state);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ FileSelect_SetView(this, 0.0f, 0.0f, 64.0f);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+/**
+ * Fade out the main menu elements to transition to select mode.
+ * Update function for `SM_FADE_MAIN_TO_SELECT`
+ */
+void FileSelect_FadeMainToSelect(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+ s16 i;
+
+ for (i = 0; i < 3; i++) {
+ if (i != this->buttonIndex) {
+ this->fileButtonAlpha[i] -= 50;
+ this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] =
+ this->optionButtonAlpha = this->fileButtonAlpha[i];
+
+ if (!gSaveContext.flashSaveAvailable) {
+ if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) {
+ this->nameAlpha[i] = this->nameBoxAlpha[i] = this->fileButtonAlpha[i];
+ this->connectorAlpha[i] -= 255 / 4;
+ }
+ } else {
+ if (SLOT_OCCUPIED(this, i)) {
+ this->nameAlpha[i] = this->nameBoxAlpha[i] = this->fileButtonAlpha[i];
+ this->connectorAlpha[i] -= 255 / 4;
+ }
+ }
+ }
+ }
+
+ this->titleAlpha[FS_TITLE_CUR] -= 255 / 4;
+ this->titleAlpha[FS_TITLE_NEXT] += 255 / 4;
+ this->actionTimer--;
+
+ if (this->actionTimer == 0) {
+ this->actionTimer = 4;
+ this->selectMode++; // SM_MOVE_FILE_TO_TOP
+ this->confirmButtonIndex = FS_BTN_CONFIRM_YES;
+ }
+}
+
+// Amount to move by to reach the top of the screen
+s16 sFileYOffsets[] = { 0, 16, 32 };
+
+/**
+ * Moves the selected file to the top of the window.
+ * Update function for `SM_MOVE_FILE_TO_TOP`
+ */
+void FileSelect_MoveSelectedFileToTop(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s32 yStep;
+
+ yStep = ABS_ALT(this->buttonYOffsets[this->buttonIndex] - sFileYOffsets[this->buttonIndex]) / this->actionTimer;
+ this->buttonYOffsets[this->buttonIndex] += yStep;
+ this->actionTimer--;
+
+ if ((this->actionTimer == 0) || (this->buttonYOffsets[this->buttonIndex] == sFileYOffsets[this->buttonIndex])) {
+ this->buttonYOffsets[FS_BTN_SELECT_YES] = this->buttonYOffsets[FS_BTN_SELECT_QUIT] = -24;
+ this->actionTimer = 4;
+ this->selectMode++; // SM_FADE_IN_FILE_INFO
+ }
+}
+
+/**
+ * Fade in the file info for the selected file.
+ * Update function for `SM_FADE_IN_FILE_INFO`
+ */
+void FileSelect_FadeInFileInfo(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->fileInfoAlpha[this->buttonIndex] += 50;
+ this->nameBoxAlpha[this->buttonIndex] -= 100;
+
+ if (this->nameBoxAlpha[this->buttonIndex] <= 0) {
+ this->nameBoxAlpha[this->buttonIndex] = 0;
+ }
+
+ this->actionTimer--;
+
+ if (this->actionTimer == 0) {
+ this->fileInfoAlpha[this->buttonIndex] = 200;
+ this->actionTimer = 4;
+ this->selectMode++; // SM_CONFIRM_FILE
+ }
+
+ this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] = this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] =
+ this->fileInfoAlpha[this->buttonIndex];
+}
+
+/**
+ * Update the cursor and handle the option that the player picks for confirming the selected file.
+ * Update function for `SM_CONFIRM_FILE`
+ */
+void FileSelect_ConfirmFile(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ Input* input = CONTROLLER1(&this->state);
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_START) || (CHECK_BTN_ALL(input->press.button, BTN_A))) {
+ if (this->confirmButtonIndex == FS_BTN_CONFIRM_YES) {
+ Rumble_Request(300.0f, 180, 20, 100);
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ this->selectMode = SM_FADE_OUT;
+ Audio_MuteAllSeqExceptSystemAndOcarina(15);
+ } else { // FS_BTN_CONFIRM_QUIT
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ this->selectMode++; // SM_FADE_OUT_FILE_INFO
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ this->selectMode++; // SM_FADE_OUT_FILE_INFO
+ } else if (ABS_ALT(this->stickAdjY) >= 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->confirmButtonIndex ^= 1;
+ }
+}
+
+/**
+ * Fade out the file info for the selected file before returning to the main menu.
+ * Update function for `SM_FADE_OUT_FILE_INFO`
+ */
+void FileSelect_FadeOutFileInfo(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->fileInfoAlpha[this->buttonIndex] -= 200 / 4;
+ this->nameBoxAlpha[this->buttonIndex] += 200 / 4;
+ this->actionTimer--;
+
+ if (this->actionTimer == 0) {
+ this->buttonYOffsets[FS_BTN_SELECT_YES] = this->buttonYOffsets[FS_BTN_SELECT_QUIT] = 0;
+ this->nameBoxAlpha[this->buttonIndex] = 200;
+ this->fileInfoAlpha[this->buttonIndex] = 0;
+ this->nextTitleLabel = FS_TITLE_SELECT_FILE;
+ this->actionTimer = 4;
+ this->selectMode++;
+ }
+
+ this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] = this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] =
+ this->fileInfoAlpha[this->buttonIndex];
+}
+
+/**
+ * Move the selected file back to the slot position then go to config mode for the main menu.
+ * Update function for `SM_MOVE_FILE_TO_SLOT`
+ */
+void FileSelect_MoveSelectedFileToSlot(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+ s32 yStep;
+ s16 i;
+
+ yStep = ABS_ALT(this->buttonYOffsets[this->buttonIndex]) / this->actionTimer;
+ this->buttonYOffsets[this->buttonIndex] -= yStep;
+
+ if (this->buttonYOffsets[this->buttonIndex] <= 0) {
+ this->buttonYOffsets[this->buttonIndex] = 0;
+ }
+
+ for (i = 0; i < 3; i++) {
+ if (i != this->buttonIndex) {
+ this->fileButtonAlpha[i] += 200 / 4;
+
+ if (this->fileButtonAlpha[i] >= 200) {
+ this->fileButtonAlpha[i] = 200;
+ }
+
+ this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] =
+ this->optionButtonAlpha = this->fileButtonAlpha[i];
+
+ if (!gSaveContext.flashSaveAvailable) {
+ if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) {
+ this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
+ this->connectorAlpha[i] += 255 / 4;
+ }
+ } else {
+ if (SLOT_OCCUPIED(this, i)) {
+ this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i];
+ this->connectorAlpha[i] += 255 / 4;
+ }
+ }
+ }
+ }
+
+ this->titleAlpha[FS_TITLE_CUR] -= 255 / 4;
+ this->titleAlpha[FS_TITLE_NEXT] += 255 / 4;
+ this->actionTimer--;
+
+ if (this->actionTimer == 0) {
+ this->titleAlpha[FS_TITLE_CUR] = 255;
+ this->titleAlpha[FS_TITLE_NEXT] = 0;
+ this->titleLabel = this->nextTitleLabel;
+ this->actionTimer = 4;
+ this->menuMode = FS_MENU_MODE_CONFIG;
+ this->configMode = CM_MAIN_MENU;
+ this->nextConfigMode = CM_MAIN_MENU;
+ this->selectMode = SM_FADE_MAIN_TO_SELECT;
+ }
+}
+
+/**
+ * Fill the screen with black to fade out.
+ * Update function for `SM_FADE_OUT`
+ */
+void FileSelect_FadeOut(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->screenFillAlpha += 40;
+
+ if (this->screenFillAlpha >= 255) {
+ this->screenFillAlpha = 255;
+ this->selectMode++; // SM_LOAD_GAME
+ }
+}
+
+/**
+ * Load the save for the appropriate file and start the game.
+ * Update function for `SM_LOAD_GAME`
+ */
+void FileSelect_LoadGame(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ u16 i;
+
+ gSaveContext.fileNum = this->buttonIndex;
+ Sram_OpenSave(this, &this->sramCtx);
+
+ gSaveContext.gameMode = GAMEMODE_NORMAL;
+
+ STOP_GAMESTATE(&this->state);
+ SET_NEXT_GAMESTATE(&this->state, Play_Init, sizeof(PlayState));
+
+ gSaveContext.respawnFlag = 0;
+ gSaveContext.respawn[RESPAWN_MODE_DOWN].entrance = ENTR_LOAD_OPENING;
+ gSaveContext.seqId = (u8)NA_BGM_DISABLED;
+ gSaveContext.ambienceId = AMBIENCE_ID_DISABLED;
+ gSaveContext.showTitleCard = true;
+ gSaveContext.dogParams = 0;
+
+ for (i = 0; i < TIMER_ID_MAX; i++) {
+ gSaveContext.timerStates[i] = TIMER_STATE_OFF;
+ }
+
+ gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL;
+ gSaveContext.nayrusLoveTimer = 0;
+ gSaveContext.healthAccumulator = 0;
+ gSaveContext.magicFlag = 0;
+ gSaveContext.forcedSeqId = 0;
+ gSaveContext.skyboxTime = CLOCK_TIME(0, 0);
+ gSaveContext.nextTransitionType = TRANS_NEXT_TYPE_DEFAULT;
+ gSaveContext.cutsceneTrigger = 0;
+ gSaveContext.chamberCutsceneNum = 0;
+ gSaveContext.nextDayTime = NEXT_TIME_NONE;
+ gSaveContext.retainWeatherMode = false;
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_ENABLED;
+
+ gSaveContext.hudVisibilityForceButtonAlphasByStatus = false;
+ gSaveContext.nextHudVisibility = HUD_VISIBILITY_IDLE;
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+ gSaveContext.hudVisibilityTimer = 0;
+
+ gSaveContext.save.saveInfo.playerData.tatlTimer = 0;
+}
+
+void (*sSelectModeUpdateFuncs[])(GameState*) = {
+ FileSelect_FadeMainToSelect, // SM_FADE_MAIN_TO_SELECT
+ FileSelect_MoveSelectedFileToTop, // SM_MOVE_FILE_TO_TOP
+ FileSelect_FadeInFileInfo, // SM_FADE_IN_FILE_INFO
+ FileSelect_ConfirmFile, // SM_CONFIRM_FILE
+ FileSelect_FadeOutFileInfo, // SM_FADE_OUT_FILE_INFO
+ FileSelect_MoveSelectedFileToSlot, // SM_MOVE_FILE_TO_SLOT
+ FileSelect_FadeOut, // SM_FADE_OUT
+ FileSelect_LoadGame, // SM_LOAD_GAME
+};
+
+void FileSelect_SelectModeUpdate(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ sSelectModeUpdateFuncs[this->selectMode](&this->state);
+}
+
+void FileSelect_SelectModeDraw(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ Gfx_SetupDL42_Opa(this->state.gfxCtx);
+ FileSelect_SetView(this, 0.0f, 0.0f, 64.0f);
+ FileSelect_SetWindowVtx(&this->state);
+ FileSelect_SetWindowContentVtx(&this->state);
+
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->windowAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ Matrix_Translate(0.0f, 0.0f, -93.6f, MTXMODE_NEW);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(this->windowRot / 100.0f);
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[0], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow1DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[32], 32, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow2DL);
+
+ gSPVertex(POLY_OPA_DISP++, &this->windowVtx[64], 16, 0);
+ gSPDisplayList(POLY_OPA_DISP++, gFileSelWindow3DL);
+
+ FileSelect_DrawWindowContents(&this->state);
+ gDPPipeSync(POLY_OPA_DISP++);
+ FileSelect_SetView(this, 0.0f, 0.0f, 64.0f);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_UpdateAndDrawSkybox(FileSelectState* this) {
+ s32 pad;
+ f32 eyeX;
+ f32 eyeY;
+ f32 eyeZ;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ eyeX = 1000.0f * Math_CosS(sFileSelectSkyboxRotation) - 1000.0f * Math_SinS(sFileSelectSkyboxRotation);
+ eyeY = -700.0f;
+ eyeZ = 1000.0f * Math_SinS(sFileSelectSkyboxRotation) + 1000.0f * Math_CosS(sFileSelectSkyboxRotation);
+
+ FileSelect_SetView(this, eyeX, eyeY, eyeZ);
+ Skybox_Draw(&this->skyboxCtx, this->state.gfxCtx, SKYBOX_NORMAL_SKY, this->envCtx.skyboxBlend, eyeX, eyeY, eyeZ);
+
+ gDPSetTextureLUT(POLY_OPA_DISP++, G_TT_NONE);
+
+ sFileSelectSkyboxRotation += -0xA;
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void (*gFileSelectDrawFuncs[])(GameState*) = {
+ FileSelect_InitModeDraw, // FS_MENU_MODE_INIT
+ FileSelect_ConfigModeDraw, // FS_MENU_MODE_CONFIG
+ FileSelect_SelectModeDraw, // FS_MENU_MODE_SELECT
+};
+void (*gFileSelectUpdateFuncs[])(GameState*) = {
+ FileSelect_InitModeUpdate, // FS_MENU_MODE_INIT
+ FileSelect_ConfigModeUpdate, // FS_MENU_MODE_CONFIG
+ FileSelect_SelectModeUpdate, // FS_MENU_MODE_SELECT
+};
+
+TexturePtr D_808147B4[] = { gFileSelPleaseWaitENGTex, gFileSelDecideCancelENGTex, gFileSelDecideSaveENGTex };
+s16 D_808147C0[] = { 144, 144, 152 };
+s16 D_808147C8[] = { 90, 90, 86 };
+
+void FileSelect_Main(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ Input* input = CONTROLLER1(&this->state);
+ s32 texIndex;
+ s32 pad;
+
+ func_8012CF0C(this->state.gfxCtx, 0, 1, 0, 0, 0);
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gSPSegment(POLY_OPA_DISP++, 0x01, this->staticSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x02, this->parameterSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x06, this->titleSegment);
+
+ this->stickAdjX = input->rel.stick_x;
+ this->stickAdjY = input->rel.stick_y;
+
+ if (this->stickAdjX < -30) {
+ if (this->stickXDir == -1) {
+ this->inputTimerX--;
+ if (this->inputTimerX < 0) {
+ this->inputTimerX = 2;
+ } else {
+ this->stickAdjX = 0;
+ }
+ } else {
+ this->inputTimerX = 10;
+ this->stickXDir = -1;
+ }
+ } else if (this->stickAdjX > 30) {
+ if (this->stickXDir == 1) {
+ this->inputTimerX--;
+ if (this->inputTimerX < 0) {
+ this->inputTimerX = 2;
+ } else {
+ this->stickAdjX = 0;
+ }
+ } else {
+ this->inputTimerX = 10;
+ this->stickXDir = 1;
+ }
+ } else {
+ this->stickXDir = 0;
+ }
+
+ if (this->stickAdjY < -30) {
+ if (this->stickYDir == -1) {
+ this->inputTimerY--;
+ if (this->inputTimerY < 0) {
+ this->inputTimerY = 2;
+ } else {
+ this->stickAdjY = 0;
+ }
+ } else {
+ this->inputTimerY = 10;
+ this->stickYDir = -1;
+ }
+ } else if (this->stickAdjY > 30) {
+ if (this->stickYDir == 1) {
+ this->inputTimerY--;
+ if (this->inputTimerY < 0) {
+ this->inputTimerY = 2;
+ } else {
+ this->stickAdjY = 0;
+ }
+ } else {
+ this->inputTimerY = 10;
+ this->stickYDir = 1;
+ }
+ } else {
+ this->stickYDir = 0;
+ }
+
+ this->emptyFileTextAlpha = 0;
+
+ FileSelect_PulsateCursor(&this->state);
+ gFileSelectUpdateFuncs[this->menuMode](&this->state);
+ FileSelect_UpdateAndDrawSkybox(this);
+ gFileSelectDrawFuncs[this->menuMode](&this->state);
+
+ Gfx_SetupDL39_Opa(this->state.gfxCtx);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 100, 255, 255, this->controlsAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ if (this->sramCtx.status > 0) {
+ texIndex = 0;
+ } else if ((this->configMode >= CM_MAIN_TO_OPTIONS) && (this->configMode <= CM_OPTIONS_TO_MAIN)) {
+ texIndex = 2;
+ } else {
+ texIndex = 1;
+ }
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, D_808147B4[texIndex], G_IM_FMT_IA, G_IM_SIZ_8b, D_808147C0[texIndex], 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK,
+ G_TX_NOLOD);
+
+ gSPTextureRectangle(POLY_OPA_DISP++, D_808147C8[texIndex] << 2, 204 << 2,
+ (D_808147C8[texIndex] + D_808147C0[texIndex]) << 2, (204 + 16) << 2, G_TX_RENDERTILE, 0, 0,
+ 1 << 10, 1 << 10);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gSPDisplayList(POLY_OPA_DISP++, sScreenFillSetupDL);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, this->screenFillAlpha);
+ gSPDisplayList(POLY_OPA_DISP++, D_0E000000.fillRect);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_InitContext(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ EnvironmentContext* envCtx = &this->envCtx;
+
+ Sram_Alloc(&this->state, &this->sramCtx);
+ func_801457CC(&this->state, &this->sramCtx);
+
+ this->menuMode = FS_MENU_MODE_INIT;
+
+ this->buttonIndex = this->selectMode = this->selectedFileIndex = this->copyDestFileIndex =
+ this->confirmButtonIndex = 0;
+
+ this->confirmButtonTexIndices[0] = 2;
+ this->confirmButtonTexIndices[1] = 3;
+ this->titleLabel = FS_TITLE_SELECT_FILE;
+ this->nextTitleLabel = FS_TITLE_OPEN_FILE;
+
+ this->screenFillAlpha = 255;
+ this->highlightPulseDir = 1;
+ this->unk_244F4 = 0xC;
+ this->highlightColor[0] = 155;
+ this->highlightColor[1] = 255;
+ this->highlightColor[2] = 255;
+ this->highlightColor[3] = 70;
+ this->configMode = CM_FADE_IN_START;
+ this->windowRot = 0.0f;
+
+ this->stickXDir = this->inputTimerX = 0;
+ this->stickYDir = this->inputTimerY = 0;
+
+ this->kbdX = this->kbdY = this->charIndex = 0;
+
+ this->kbdButton = FS_KBD_BTN_NONE;
+
+ this->windowColor[0] = 100;
+ this->windowColor[1] = 150;
+ this->windowColor[2] = 255;
+
+ this->windowAlpha = this->titleAlpha[FS_TITLE_CUR] = this->titleAlpha[FS_TITLE_NEXT] = this->fileButtonAlpha[0] =
+ this->fileButtonAlpha[1] = this->fileButtonAlpha[2] = this->nameBoxAlpha[0] = this->nameBoxAlpha[1] =
+ this->nameBoxAlpha[2] = this->nameAlpha[0] = this->nameAlpha[1] = this->nameAlpha[2] =
+ this->connectorAlpha[0] = this->connectorAlpha[1] = this->connectorAlpha[2] = this->fileInfoAlpha[0] =
+ this->fileInfoAlpha[1] = this->fileInfoAlpha[2] = this->actionButtonAlpha[FS_BTN_ACTION_COPY] =
+ this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] =
+ this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = this->optionButtonAlpha =
+ this->nameEntryBoxAlpha = this->controlsAlpha = this->emptyFileTextAlpha = 0;
+
+ this->windowPosX = 6;
+ this->actionTimer = 4;
+ this->warningLabel = FS_WARNING_NONE;
+
+ this->warningButtonIndex = this->buttonYOffsets[0] = this->buttonYOffsets[1] = this->buttonYOffsets[2] =
+ this->buttonYOffsets[3] = this->buttonYOffsets[4] = this->buttonYOffsets[5] = this->fileNamesY[0] =
+ this->fileNamesY[1] = this->fileNamesY[2] = 0;
+
+ this->unk_2451E[0] = 0;
+ this->unk_2451E[1] = 3;
+ this->unk_2451E[2] = 6;
+ this->unk_2451E[3] = 8;
+ this->unk_2451E[4] = 10;
+ this->highlightTimer = 20;
+
+ ShrinkWindow_Letterbox_SetSizeTarget(0);
+
+ gSaveContext.skyboxTime = 0;
+ gSaveContext.save.time = CLOCK_TIME(0, 0);
+
+ Skybox_Init(&this->state, &this->skyboxCtx, 1);
+ R_TIME_SPEED = 10;
+
+ envCtx->changeSkyboxState = CHANGE_SKYBOX_INACTIVE;
+ envCtx->changeSkyboxTimer = 0;
+ envCtx->changeLightEnabled = false;
+ envCtx->changeLightTimer = 0;
+ envCtx->skyboxDmaState = 0;
+ envCtx->skybox1Index = 99;
+ envCtx->skybox2Index = 99;
+ envCtx->lightConfig = 0;
+ envCtx->changeLightNextConfig = 0;
+ envCtx->lightSetting = 0;
+ envCtx->skyboxConfig = SKYBOX_CONFIG_2;
+ envCtx->skyboxDisabled = 0;
+ envCtx->skyboxBlend = 0;
+ envCtx->glareAlpha = 0.0f;
+ envCtx->lensFlareAlphaScale = 0.0f;
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_ENABLED;
+}
+
+void FileSelect_Destroy(GameState* this) {
+ ShrinkWindow_Destroy();
+}
+
+void FileSelect_Init(GameState* thisx) {
+ s32 pad;
+ FileSelectState* this = (FileSelectState*)thisx;
+ size_t size;
+
+ GameState_SetFramerateDivisor(&this->state, 1);
+ Matrix_Init(&this->state);
+ ShrinkWindow_Init();
+ View_Init(&this->view, this->state.gfxCtx);
+ this->state.main = FileSelect_Main;
+ this->state.destroy = FileSelect_Destroy;
+ FileSelect_InitContext(&this->state);
+ Font_LoadOrderedFont(&this->font);
+
+ size = SEGMENT_ROM_SIZE(title_static);
+ this->staticSegment = THA_AllocTailAlign16(&this->state.tha, size);
+ DmaMgr_RequestSync(this->staticSegment, SEGMENT_ROM_START(title_static), size);
+
+ size = SEGMENT_ROM_SIZE(parameter_static);
+ this->parameterSegment = THA_AllocTailAlign16(&this->state.tha, size);
+ DmaMgr_RequestSync(this->parameterSegment, SEGMENT_ROM_START(parameter_static), size);
+
+ size = gObjectTable[OBJECT_MAG].vromEnd - gObjectTable[OBJECT_MAG].vromStart;
+ this->titleSegment = THA_AllocTailAlign16(&this->state.tha, size);
+ DmaMgr_RequestSync(this->titleSegment, gObjectTable[OBJECT_MAG].vromStart, size);
+
+ Audio_SetSpec(0xA);
+ // Setting ioData to 1 and writing it to ioPort 7 will skip the harp intro
+ Audio_PlaySequenceWithSeqPlayerIO(SEQ_PLAYER_BGM_MAIN, NA_BGM_FILE_SELECT, 0, 7, 1);
+}
diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_nameset_JPN.c b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_JPN.c
new file mode 100644
index 000000000..870efe2c8
--- /dev/null
+++ b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_JPN.c
@@ -0,0 +1,1060 @@
+/*
+ * File: z_file_nameset_NES.c
+ * Overlay: ovl_file_choose
+ * Description: Entering name on a new file, selecting options from the options menu
+ */
+
+#include "z_file_select.h"
+#include "z64rumble.h"
+#include "assets/misc/title_static/title_static.h"
+#include "assets/overlays/ovl_file_choose/ovl_file_choose.h"
+
+void FileSelect_DrawTexQuadI4(GraphicsContext* gfxCtx, TexturePtr texture, s16 point) {
+ OPEN_DISPS(gfxCtx);
+
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, 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);
+ gSP1Quadrangle(POLY_OPA_DISP++, point, point + 2, point + 3, point + 1, 0);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+void FileSelect_DrawMultiTexQuadI4(GraphicsContext* gfxCtx, TexturePtr texture1, TexturePtr texture2, s16 point) {
+ OPEN_DISPS(gfxCtx);
+
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, texture1, G_IM_FMT_I, 16, 16, 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_4b(POLY_OPA_DISP++, texture2, 0x0080, 1, G_IM_FMT_I, 16, 16, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, point, point + 2, point + 3, point + 1, 0);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+s16 D_80814280[] = {
+ 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 0, 1, 1, 2, 1, 1, 4, 2, 2, 2, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1, 0,
+ 1, 1, 1, 2, 2, 2, 2, 2, 3, 2, 2, 4, 3, 2, 4, 1, 2, 2, 1, 1, 2, 2, 3, 2, 2, 0, 2, 2, 2, 0, 3, 1, 0,
+};
+
+s16 D_80814304[] = {
+ 1, 2, 0, 1, 1, 2, 1, 1, 4, 2, 2, 2, 1, 1, 0, 2, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 2, 2, 2, 2, 2, 3,
+ 2, 2, 4, 3, 2, 4, 1, 2, 2, 1, 1, 2, 2, 3, 2, 2, 0, 2, 2, 2, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 3,
+};
+
+s16 D_80814384[] = {
+ 0, 1, 0, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 2, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+};
+
+s16 D_80814404[] = {
+ -94, -96, -48, 0, 32, 64,
+};
+
+s16 D_80814410[] = {
+ 56, 44, 44, 28, 28, 44,
+};
+
+s16 D_8081441C[] = {
+ 72, -48, -48, -48, -48, -48,
+};
+
+void FileSelect_SetKeyboardVtx(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s16 phi_t2;
+ s16 phi_t0;
+ s16 phi_t3;
+ s16 phi_s1;
+ s16 phi_t1;
+ s16 phi_s2;
+
+ this->keyboardVtx = GRAPH_ALLOC(this->state.gfxCtx, sizeof(Vtx) * 4 * 5 * 13);
+
+ phi_s1 = 0x26;
+
+ for (phi_t2 = 0, phi_s2 = 0, phi_t3 = 0; phi_s2 < 5; phi_s2++) {
+ phi_t0 = -0x60;
+
+ for (phi_t1 = 0; phi_t1 < 13; phi_t1++, phi_t3 += 4, phi_t2++) {
+ //! @bug D_80814304 is accessed out of bounds when drawing the empty space character (value of 64). Under
+ //! normal circumstances it reads a halfword from D_80814384.
+ this->keyboardVtx[phi_t3].v.ob[0] = this->keyboardVtx[phi_t3 + 2].v.ob[0] = D_80814304[phi_t2] + phi_t0;
+
+ this->keyboardVtx[phi_t3 + 1].v.ob[0] = this->keyboardVtx[phi_t3 + 3].v.ob[0] =
+ D_80814304[phi_t2] + phi_t0 + 12;
+
+ this->keyboardVtx[phi_t3].v.ob[1] = this->keyboardVtx[phi_t3 + 1].v.ob[1] = phi_s1;
+
+ this->keyboardVtx[phi_t3 + 2].v.ob[1] = this->keyboardVtx[phi_t3 + 3].v.ob[1] = phi_s1 - 12;
+
+ this->keyboardVtx[phi_t3].v.ob[2] = this->keyboardVtx[phi_t3 + 1].v.ob[2] =
+ this->keyboardVtx[phi_t3 + 2].v.ob[2] = this->keyboardVtx[phi_t3 + 3].v.ob[2] = 0;
+
+ this->keyboardVtx[phi_t3].v.flag = this->keyboardVtx[phi_t3 + 1].v.flag =
+ this->keyboardVtx[phi_t3 + 2].v.flag = this->keyboardVtx[phi_t3 + 3].v.flag = 0;
+
+ this->keyboardVtx[phi_t3].v.tc[0] = this->keyboardVtx[phi_t3].v.tc[1] =
+ this->keyboardVtx[phi_t3 + 1].v.tc[1] = this->keyboardVtx[phi_t3 + 2].v.tc[0] = 0;
+
+ this->keyboardVtx[phi_t3 + 1].v.tc[0] = this->keyboardVtx[phi_t3 + 2].v.tc[1] =
+ this->keyboardVtx[phi_t3 + 3].v.tc[0] = this->keyboardVtx[phi_t3 + 3].v.tc[1] = 16 << 5;
+
+ this->keyboardVtx[phi_t3].v.cn[0] = this->keyboardVtx[phi_t3 + 1].v.cn[0] =
+ this->keyboardVtx[phi_t3 + 2].v.cn[0] = this->keyboardVtx[phi_t3 + 3].v.cn[0] =
+ this->keyboardVtx[phi_t3].v.cn[1] = this->keyboardVtx[phi_t3 + 1].v.cn[1] =
+ this->keyboardVtx[phi_t3 + 2].v.cn[1] = this->keyboardVtx[phi_t3 + 3].v.cn[1] =
+ this->keyboardVtx[phi_t3].v.cn[2] = this->keyboardVtx[phi_t3 + 1].v.cn[2] =
+ this->keyboardVtx[phi_t3 + 2].v.cn[2] = this->keyboardVtx[phi_t3 + 3].v.cn[2] =
+ this->keyboardVtx[phi_t3].v.cn[3] = this->keyboardVtx[phi_t3 + 1].v.cn[3] =
+ this->keyboardVtx[phi_t3 + 2].v.cn[3] = this->keyboardVtx[phi_t3 + 3].v.cn[3] =
+ 255;
+
+ phi_t0 += 0x10;
+ }
+
+ phi_s1 -= 0x10;
+ }
+
+ this->keyboard2Vtx = GRAPH_ALLOC(this->state.gfxCtx, sizeof(Vtx) * 24);
+
+ for (phi_t1 = 0, phi_t3 = 0; phi_t3 < 6; phi_t3++, phi_t1 += 4) {
+
+ this->keyboard2Vtx[phi_t1 + 0].v.ob[0] = this->keyboard2Vtx[phi_t1 + 2].v.ob[0] = D_80814404[phi_t3] + 1;
+
+ this->keyboard2Vtx[phi_t1 + 1].v.ob[0] = this->keyboard2Vtx[phi_t1 + 3].v.ob[0] =
+ this->keyboard2Vtx[phi_t1 + 0].v.ob[0] + D_80814410[phi_t3] - 2;
+
+ this->keyboard2Vtx[phi_t1 + 0].v.ob[1] = this->keyboard2Vtx[phi_t1 + 1].v.ob[1] = D_8081441C[phi_t3] - 1;
+
+ this->keyboard2Vtx[phi_t1 + 2].v.ob[1] = this->keyboard2Vtx[phi_t1 + 3].v.ob[1] =
+ this->keyboard2Vtx[phi_t1 + 0].v.ob[1] - 0xE;
+
+ this->keyboard2Vtx[phi_t1 + 0].v.ob[2] = this->keyboard2Vtx[phi_t1 + 1].v.ob[2] =
+ this->keyboard2Vtx[phi_t1 + 2].v.ob[2] = this->keyboard2Vtx[phi_t1 + 3].v.ob[2] = 0;
+
+ this->keyboard2Vtx[phi_t1 + 0].v.flag = this->keyboard2Vtx[phi_t1 + 1].v.flag =
+ this->keyboard2Vtx[phi_t1 + 2].v.flag = this->keyboard2Vtx[phi_t1 + 3].v.flag = 0;
+
+ this->keyboard2Vtx[phi_t1 + 0].v.tc[0] = this->keyboard2Vtx[phi_t1 + 0].v.tc[1] =
+ this->keyboard2Vtx[phi_t1 + 1].v.tc[1] = this->keyboard2Vtx[phi_t1 + 2].v.tc[0] = 0;
+
+ this->keyboard2Vtx[phi_t1 + 1].v.tc[0] = this->keyboard2Vtx[phi_t1 + 3].v.tc[0] = D_80814410[phi_t3] << 5;
+
+ this->keyboard2Vtx[phi_t1 + 2].v.tc[1] = this->keyboard2Vtx[phi_t1 + 3].v.tc[1] = 16 << 5;
+
+ this->keyboard2Vtx[phi_t1 + 0].v.cn[0] = this->keyboard2Vtx[phi_t1 + 1].v.cn[0] =
+ this->keyboard2Vtx[phi_t1 + 2].v.cn[0] = this->keyboard2Vtx[phi_t1 + 3].v.cn[0] =
+ this->keyboard2Vtx[phi_t1 + 0].v.cn[1] = this->keyboard2Vtx[phi_t1 + 1].v.cn[1] =
+ this->keyboard2Vtx[phi_t1 + 2].v.cn[1] = this->keyboard2Vtx[phi_t1 + 3].v.cn[1] =
+ this->keyboard2Vtx[phi_t1 + 0].v.cn[2] = this->keyboard2Vtx[phi_t1 + 1].v.cn[2] =
+ this->keyboard2Vtx[phi_t1 + 2].v.cn[2] = this->keyboard2Vtx[phi_t1 + 3].v.cn[2] =
+ this->keyboard2Vtx[phi_t1 + 0].v.cn[3] = this->keyboard2Vtx[phi_t1 + 1].v.cn[3] =
+ this->keyboard2Vtx[phi_t1 + 2].v.cn[3] = this->keyboard2Vtx[phi_t1 + 3].v.cn[3] =
+ 255;
+ }
+}
+
+TexturePtr sBackspaceEndTextures[] = {
+ gFileSelBackspaceButtonTex,
+ gFileSelENDButtonENGTex,
+};
+
+u16 sBackspaceEndWidths[] = { 28, 44 };
+
+s16 D_80814434[] = {
+ -30, -16, -6, 4, 14, 24, 34, 44, 54, -16, -16, 0,
+};
+
+s16 D_8081444C[] = {
+ 72, 69, 69, 69, 69, 69, 69, 69, 69, 69, 69, 0,
+};
+
+/**
+ * Set vertices used by all elements of the name entry screen that are NOT the keyboard.
+ * This includes the cursor highlight, the name entry plate and characters, and the buttons.
+ */
+void FileSelect_SetNameEntryVtx(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ Font* font = &this->font;
+ u8 temp;
+ s16 var_s0;
+ s16 var_t1;
+ s16 sp108;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+ gSPVertex(POLY_OPA_DISP++, this->keyboard2Vtx, 24, 0);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelNameENGTex, G_IM_FMT_IA, G_IM_SIZ_8b, 56, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ for (var_t1 = 0, var_s0 = 0x10; var_t1 < 2; var_t1++, var_s0 += 4) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2], 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, sBackspaceEndTextures[var_t1], G_IM_FMT_IA, G_IM_SIZ_16b,
+ sBackspaceEndWidths[var_t1], 16, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, var_s0, var_s0 + 2, var_s0 + 3, var_s0 + 1, 0);
+ }
+
+ this->nameEntryVtx = GRAPH_ALLOC(this->state.gfxCtx, 44 * sizeof(Vtx));
+
+ for (var_s0 = 0, var_t1 = 0; var_t1 < 44; var_t1 += 4, var_s0++) {
+ if ((var_s0 > 0) && (var_s0 < 9)) {
+ temp = this->fileNames[this->buttonIndex][var_s0 - 1];
+
+ this->nameEntryVtx[var_t1 + 0].v.ob[0] = this->nameEntryVtx[var_t1 + 2].v.ob[0] =
+ D_80814434[var_s0] + this->nameEntryBoxPosX + D_80814280[temp];
+
+ this->nameEntryVtx[var_t1 + 1].v.ob[0] = this->nameEntryVtx[var_t1 + 3].v.ob[0] =
+ this->nameEntryVtx[var_t1 + 0].v.ob[0] + 10;
+ } else {
+ this->nameEntryVtx[var_t1 + 0].v.ob[0] = this->nameEntryVtx[var_t1 + 2].v.ob[0] =
+ D_80814434[var_s0] + this->nameEntryBoxPosX;
+
+ this->nameEntryVtx[var_t1 + 1].v.ob[0] = this->nameEntryVtx[var_t1 + 3].v.ob[0] =
+ this->nameEntryVtx[var_t1 + 0].v.ob[0] + 10;
+ }
+
+ this->nameEntryVtx[var_t1 + 0].v.ob[1] = this->nameEntryVtx[var_t1 + 1].v.ob[1] = D_8081444C[var_s0];
+
+ this->nameEntryVtx[var_t1 + 2].v.ob[1] = this->nameEntryVtx[var_t1 + 3].v.ob[1] =
+ this->nameEntryVtx[var_t1 + 0].v.ob[1] - 10;
+
+ this->nameEntryVtx[var_t1 + 0].v.ob[2] = this->nameEntryVtx[var_t1 + 1].v.ob[2] =
+ this->nameEntryVtx[var_t1 + 2].v.ob[2] = this->nameEntryVtx[var_t1 + 3].v.ob[2] = 0;
+
+ this->nameEntryVtx[var_t1 + 0].v.flag = this->nameEntryVtx[var_t1 + 1].v.flag =
+ this->nameEntryVtx[var_t1 + 2].v.flag = this->nameEntryVtx[var_t1 + 3].v.flag = 0;
+
+ this->nameEntryVtx[var_t1 + 0].v.tc[0] = this->nameEntryVtx[var_t1 + 0].v.tc[1] =
+ this->nameEntryVtx[var_t1 + 1].v.tc[1] = this->nameEntryVtx[var_t1 + 2].v.tc[0] = 0;
+
+ this->nameEntryVtx[var_t1 + 1].v.tc[0] = this->nameEntryVtx[var_t1 + 2].v.tc[1] =
+ this->nameEntryVtx[var_t1 + 3].v.tc[0] = this->nameEntryVtx[var_t1 + 3].v.tc[1] = 16 << 5;
+
+ this->nameEntryVtx[var_t1 + 0].v.cn[0] = this->nameEntryVtx[var_t1 + 1].v.cn[0] =
+ this->nameEntryVtx[var_t1 + 2].v.cn[0] = this->nameEntryVtx[var_t1 + 3].v.cn[0] =
+ this->nameEntryVtx[var_t1 + 0].v.cn[1] = this->nameEntryVtx[var_t1 + 1].v.cn[1] =
+ this->nameEntryVtx[var_t1 + 2].v.cn[1] = this->nameEntryVtx[var_t1 + 3].v.cn[1] =
+ this->nameEntryVtx[var_t1 + 0].v.cn[2] = this->nameEntryVtx[var_t1 + 1].v.cn[2] =
+ this->nameEntryVtx[var_t1 + 2].v.cn[2] = this->nameEntryVtx[var_t1 + 3].v.cn[2] =
+ this->nameEntryVtx[var_t1 + 0].v.cn[3] = this->nameEntryVtx[var_t1 + 1].v.cn[3] =
+ this->nameEntryVtx[var_t1 + 2].v.cn[3] = this->nameEntryVtx[var_t1 + 3].v.cn[3] =
+ 255;
+ }
+
+ this->nameEntryVtx[1].v.ob[0] = this->nameEntryVtx[3].v.ob[0] = this->nameEntryVtx[0].v.ob[0] + 0x6C;
+ this->nameEntryVtx[2].v.ob[1] = this->nameEntryVtx[3].v.ob[1] = this->nameEntryVtx[0].v.ob[1] - 0x10;
+ this->nameEntryVtx[1].v.tc[0] = this->nameEntryVtx[3].v.tc[0] = 108 << 5;
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->windowColor[0], this->windowColor[1], this->windowColor[2],
+ this->nameEntryBoxAlpha);
+ gSPVertex(POLY_OPA_DISP++, this->nameEntryVtx, 4, 0);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelFileNameBoxTex, G_IM_FMT_IA, G_IM_SIZ_16b, 108, 16, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0,
+ PRIMITIVE, 0);
+ gSPVertex(POLY_OPA_DISP++, this->nameEntryVtx + 4, 32, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->nameEntryBoxAlpha);
+
+ for (sp108 = 0, var_s0 = 0; var_s0 < 0x20; var_s0 += 4, sp108++) {
+ FileSelect_DrawTexQuadI4(
+ this->state.gfxCtx, font->fontBuf + this->fileNames[this->buttonIndex][sp108] * FONT_CHAR_TEX_SIZE, var_s0);
+ }
+
+ this->nameEntryVtx[37].v.tc[0] = this->nameEntryVtx[38].v.tc[1] = this->nameEntryVtx[39].v.tc[0] =
+ this->nameEntryVtx[39].v.tc[1] = this->nameEntryVtx[41].v.tc[0] = this->nameEntryVtx[42].v.tc[1] =
+ this->nameEntryVtx[43].v.tc[0] = this->nameEntryVtx[43].v.tc[1] = 24 << 5;
+
+ if ((this->kbdButton == FS_KBD_BTN_HIRA) || (this->kbdButton == FS_KBD_BTN_KATA) ||
+ (this->kbdButton == FS_KBD_BTN_END)) {
+ this->nameEntryVtx[41].v.tc[0] = this->nameEntryVtx[43].v.tc[0] = 56 << 5;
+ } else if ((this->kbdButton == FS_KBD_BTN_ENG) || (this->kbdButton == FS_KBD_BTN_BACKSPACE)) {
+ this->nameEntryVtx[41].v.tc[0] = this->nameEntryVtx[43].v.tc[0] = 40 << 5;
+ }
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_DrawKeyboard(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ Font* font = &this->font;
+ s16 i;
+ s16 tmp;
+ s16 vtx;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ Gfx_SetupDL42_Opa(this->state.gfxCtx);
+ gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE);
+ gDPSetRenderMode(POLY_OPA_DISP++, G_RM_PASS, G_RM_XLU_SURF2);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, PRIMITIVE, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, 0, 0, 0, COMBINED, 0,
+ 0, 0, COMBINED);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, this->charBgAlpha, 255, 255, 255, 255);
+
+ for (i = 0, vtx = 0; vtx < 0x100; vtx += 32) {
+ gSPVertex(POLY_OPA_DISP++, &this->keyboardVtx[vtx], 32, 0);
+
+ for (tmp = 0; tmp < 32; i++, tmp += 4) {
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + D_808141F0[i] * FONT_CHAR_TEX_SIZE, tmp);
+ }
+ }
+
+ gSPVertex(POLY_OPA_DISP++, &this->keyboardVtx[0x100], 4, 0);
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx, font->fontBuf + D_808141F0[i] * FONT_CHAR_TEX_SIZE, 0);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_DrawNameEntry(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+ Font* font = &this->font;
+ Input* input = CONTROLLER1(&this->state);
+ s16 i;
+ s16 tmp;
+ u16 time;
+ s16 validName;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ FileSelect_SetKeyboardVtx(&this->state);
+ FileSelect_SetNameEntryVtx(&this->state);
+ FileSelect_PulsateCursor(&this->state);
+
+ tmp = (this->newFileNameCharCount * 4) + 4;
+ this->nameEntryVtx[36].v.ob[0] = this->nameEntryVtx[38].v.ob[0] = this->nameEntryVtx[tmp].v.ob[0] - 6;
+ this->nameEntryVtx[37].v.ob[0] = this->nameEntryVtx[39].v.ob[0] = this->nameEntryVtx[36].v.ob[0] + 24;
+ this->nameEntryVtx[36].v.ob[1] = this->nameEntryVtx[37].v.ob[1] = this->nameEntryVtx[tmp].v.ob[1] + 7;
+ this->nameEntryVtx[38].v.ob[1] = this->nameEntryVtx[39].v.ob[1] = this->nameEntryVtx[36].v.ob[1] - 24;
+
+ if ((this->kbdButton == FS_KBD_BTN_HIRA) || (this->kbdButton == FS_KBD_BTN_KATA) ||
+ (this->kbdButton == FS_KBD_BTN_END)) {
+ this->nameEntryVtx[40].v.ob[0] = this->nameEntryVtx[42].v.ob[0] =
+ this->keyboard2Vtx[(this->kbdX + 1) * 4].v.ob[0] - 4;
+ this->nameEntryVtx[41].v.ob[0] = this->nameEntryVtx[43].v.ob[0] = this->nameEntryVtx[40].v.ob[0] + 52;
+ this->nameEntryVtx[40].v.ob[1] = this->nameEntryVtx[41].v.ob[1] =
+ this->keyboard2Vtx[(this->kbdX + 1) * 4].v.ob[1] + 4;
+ } else if ((this->kbdButton == FS_KBD_BTN_ENG) || (this->kbdButton == FS_KBD_BTN_BACKSPACE)) {
+ this->nameEntryVtx[40].v.ob[0] = this->nameEntryVtx[42].v.ob[0] =
+ this->keyboard2Vtx[(this->kbdX + 1) * 4].v.ob[0] - 4;
+ this->nameEntryVtx[41].v.ob[0] = this->nameEntryVtx[43].v.ob[0] = this->nameEntryVtx[40].v.ob[0] + 40;
+ this->nameEntryVtx[40].v.ob[1] = this->nameEntryVtx[41].v.ob[1] =
+ this->keyboard2Vtx[(this->kbdX + 1) * 4].v.ob[1] + 4;
+ } else {
+ this->nameEntryVtx[40].v.ob[0] = this->nameEntryVtx[42].v.ob[0] =
+ this->keyboardVtx[this->charIndex * 4].v.ob[0] - D_80814304[this->charIndex] - 6;
+ this->nameEntryVtx[41].v.ob[0] = this->nameEntryVtx[43].v.ob[0] = this->nameEntryVtx[40].v.ob[0] + 24;
+ this->nameEntryVtx[40].v.ob[1] = this->nameEntryVtx[41].v.ob[1] =
+ this->keyboardVtx[this->charIndex * 4].v.ob[1] + 6;
+ }
+
+ this->nameEntryVtx[42].v.ob[1] = this->nameEntryVtx[43].v.ob[1] = this->nameEntryVtx[40].v.ob[1] - 24;
+
+ gSPVertex(POLY_OPA_DISP++, &this->nameEntryVtx[36], 8, 0);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, 1, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0, TEXEL0, 0,
+ PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, this->highlightColor[0], this->highlightColor[1], this->highlightColor[2],
+ this->highlightColor[3]);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelCharHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 24, 24, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+
+ if ((this->kbdButton == FS_KBD_BTN_HIRA) || (this->kbdButton == FS_KBD_BTN_KATA) ||
+ (this->kbdButton == FS_KBD_BTN_END)) {
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelMediumButtonHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 56, 24, 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);
+ } else if ((this->kbdButton == FS_KBD_BTN_ENG) || (this->kbdButton == FS_KBD_BTN_BACKSPACE)) {
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gFileSelSmallButtonHighlightTex, G_IM_FMT_I, G_IM_SIZ_8b, 40, 24, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ }
+
+ gSP1Quadrangle(POLY_OPA_DISP++, 4, 6, 7, 5, 0);
+
+ FileSelect_DrawKeyboard(&this->state);
+ gDPPipeSync(POLY_OPA_DISP++);
+ Gfx_SetupDL42_Opa(this->state.gfxCtx);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, 0, 0, 0, PRIMITIVE, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, PRIMITIVE, TEXEL0, 0,
+ PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+
+ if (this->configMode == CM_NAME_ENTRY) {
+ if (CHECK_BTN_ALL(input->press.button, BTN_START)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ // place cursor on END button
+ this->kbdY = 5;
+ this->kbdX = 4;
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ if ((this->newFileNameCharCount == 7) && (this->fileNames[this->buttonIndex][7] != 0x3E)) {
+
+ for (i = this->newFileNameCharCount; i < 7; i++) {
+ this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
+ }
+
+ this->fileNames[this->buttonIndex][i] = 0x3E;
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ } else {
+ this->newFileNameCharCount--;
+
+ if (this->newFileNameCharCount < 0) {
+ this->newFileNameCharCount = 0;
+ this->configMode = CM_NAME_ENTRY_TO_MAIN;
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ } else {
+ for (i = this->newFileNameCharCount; i < 7; i++) {
+ this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
+ }
+
+ this->fileNames[this->buttonIndex][i] = 0x3E;
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ }
+ }
+ } else {
+ if (this->charPage <= FS_CHAR_PAGE_ENG) {
+ if (this->kbdY != 5) {
+ // draw the character the cursor is hovering over in yellow
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 0, 255);
+
+ //! @bug D_80814384 is accessed out of bounds when drawing the empty space character (value of 64).
+ //! Under normal circumstances it reads a halfword from D_80814404.
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[0] =
+ this->keyboardVtx[(this->charIndex * 4) + 2].v.ob[0] =
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[0] + D_80814384[this->charIndex] - 2;
+
+ this->keyboardVtx[(this->charIndex * 4) + 1].v.ob[0] =
+ this->keyboardVtx[(this->charIndex * 4) + 3].v.ob[0] =
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[0] + 0x10;
+
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[1] =
+ this->keyboardVtx[(this->charIndex * 4) + 1].v.ob[1] =
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[1] + 2;
+
+ this->keyboardVtx[(this->charIndex * 4) + 2].v.ob[1] =
+ this->keyboardVtx[(this->charIndex * 4) + 3].v.ob[1] =
+ this->keyboardVtx[(this->charIndex * 4) + 0].v.ob[1] - 0x10;
+
+ gSPVertex(POLY_OPA_DISP++, &this->keyboardVtx[this->charIndex * 4], 4, 0);
+
+ FileSelect_DrawTexQuadI4(this->state.gfxCtx,
+ font->fontBuf + D_808141F0[this->charIndex] * FONT_CHAR_TEX_SIZE, 0);
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_S);
+ this->fileNames[this->buttonIndex][this->newFileNameCharCount] = D_808141F0[this->charIndex];
+
+ this->newFileNameCharCount++;
+
+ if (this->newFileNameCharCount > 7) {
+ this->newFileNameCharCount = 7;
+ }
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ if (this->charPage != this->kbdButton) {
+ if (this->kbdButton == FS_KBD_BTN_BACKSPACE) {
+ if ((this->newFileNameCharCount == 7) && (this->fileNames[this->buttonIndex][7] != 0x3E)) {
+
+ for (i = this->newFileNameCharCount; i < 7; i++) {
+ this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
+ }
+
+ this->fileNames[this->buttonIndex][i] = 0x3E;
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ } else {
+ this->newFileNameCharCount--;
+
+ if (this->newFileNameCharCount < 0) {
+ this->newFileNameCharCount = 0;
+ }
+
+ for (i = this->newFileNameCharCount; i < 7; i++) {
+ this->fileNames[this->buttonIndex][i] = this->fileNames[this->buttonIndex][i + 1];
+ }
+
+ this->fileNames[this->buttonIndex][i] = 0x3E;
+ Audio_PlaySfx(NA_SE_SY_FSEL_CLOSE);
+ }
+ } else if (this->kbdButton == FS_KBD_BTN_END) {
+ validName = false;
+
+ for (i = 0; i < 8; i++) {
+ if (this->fileNames[this->buttonIndex][i] != 0x3E) {
+ validName = true;
+ break;
+ }
+ }
+
+ if (validName) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ gSaveContext.fileNum = this->buttonIndex;
+ time = CURRENT_TIME;
+ Sram_InitSave(this, sramCtx);
+ gSaveContext.save.time = time;
+
+ if (!gSaveContext.flashSaveAvailable) {
+ this->configMode = CM_NAME_ENTRY_TO_MAIN;
+ } else {
+ Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[this->buttonIndex * 2],
+ gFlashSpecialSaveNumPages[this->buttonIndex * 2]);
+ Sram_StartWriteToFlashDefault(sramCtx);
+ this->configMode = CM_NAME_ENTRY_WAIT_FOR_FLASH_SAVE;
+ }
+
+ this->nameBoxAlpha[this->buttonIndex] = this->nameAlpha[this->buttonIndex] = 200;
+ this->connectorAlpha[this->buttonIndex] = 255;
+ Rumble_Request(300.0f, 180, 20, 100);
+ } else {
+ Audio_PlaySfx(NA_SE_SY_FSEL_ERROR);
+ }
+ }
+ }
+ }
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->newFileNameCharCount++;
+
+ if (this->newFileNameCharCount > 7) {
+ this->newFileNameCharCount = 7;
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->newFileNameCharCount--;
+
+ if (this->newFileNameCharCount < 0) {
+ this->newFileNameCharCount = 0;
+ }
+ }
+ }
+ }
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIDECALA, G_CC_MODULATEIDECALA);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+/**
+ * Fade in the name entry box and slide it to the center of the screen from the right side.
+ * After the name entry box is in place, init the keyboard/cursor and change modes.
+ * Update function for `CM_START_NAME_ENTRY`
+ */
+void FileSelect_StartNameEntry(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->nameEntryBoxAlpha += 25;
+
+ if (this->nameEntryBoxAlpha >= 255) {
+ this->nameEntryBoxAlpha = 255;
+ }
+
+ this->nameEntryBoxPosX -= 30;
+
+ if (this->nameEntryBoxPosX <= 0) {
+ this->nameEntryBoxPosX = 0;
+ this->nameEntryBoxAlpha = 255;
+ this->kbdX = 0;
+ this->kbdY = 0;
+ this->kbdButton = FS_KBD_BTN_NONE;
+ this->configMode = CM_NAME_ENTRY;
+ }
+}
+
+/**
+ * Update the keyboard cursor and play sound effects at the appropriate times.
+ * There are many special cases for warping the cursor depending on where
+ * the cursor currently is.
+ * Update function for `CM_NAME_ENTRY`
+ */
+void FileSelect_UpdateKeyboardCursor(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ s16 prevKbdX;
+
+ this->kbdButton = FS_KBD_BTN_NONE;
+
+ if (this->kbdY != 5) {
+ if (this->stickAdjX < -30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->charIndex--;
+ this->kbdX--;
+ if (this->kbdX < 0) {
+ this->kbdX = 12;
+ this->charIndex = (this->kbdY * 13) + this->kbdX;
+ }
+ } else if (this->stickAdjX > 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->charIndex++;
+ this->kbdX++;
+ if (this->kbdX > 12) {
+ this->kbdX = 0;
+ this->charIndex = (this->kbdY * 13) + this->kbdX;
+ }
+ }
+ } else {
+ if (this->stickAdjX < -30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->kbdX--;
+ if (this->kbdX < 3) {
+ this->kbdX = 4;
+ }
+ } else if (this->stickAdjX > 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->kbdX++;
+ if (this->kbdX > 4) {
+ this->kbdX = 3;
+ }
+ }
+ }
+
+ if (this->stickAdjY > 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+
+ this->kbdY--;
+
+ if (this->kbdY < 0) {
+ // Don't go to bottom row
+ if (this->kbdX < 8) {
+ this->kbdY = 4;
+ this->charIndex = (s32)(this->kbdX + 52);
+ } else {
+ this->kbdY = 5;
+ this->charIndex += 52;
+ prevKbdX = this->kbdX;
+
+ if (this->kbdX < 10) {
+ this->kbdX = 3;
+ } else if (this->kbdX < 13) {
+ this->kbdX = 4;
+ }
+ this->unk_2451E[this->kbdX] = prevKbdX;
+ }
+ } else {
+ this->charIndex -= 13;
+
+ if (this->kbdY == 4) {
+ this->charIndex = 52;
+ this->kbdX = this->unk_2451E[this->kbdX];
+ this->charIndex += this->kbdX;
+ }
+ }
+ } else if (this->stickAdjY < -30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ this->kbdY++;
+
+ if (this->kbdY > 5) {
+ this->kbdY = 0;
+ this->kbdX = this->unk_2451E[this->kbdX];
+ this->charIndex = this->kbdX;
+ } else {
+ this->charIndex += 13;
+
+ if (this->kbdY == 5) {
+ if (this->kbdX < 8) {
+ this->kbdY = 0;
+ this->charIndex = this->kbdX;
+ } else {
+ prevKbdX = this->kbdX;
+
+ if (this->kbdX < 3) {
+ this->kbdX = 0;
+ } else if (this->kbdX < 6) {
+ this->kbdX = 1;
+ } else if (this->kbdX < 8) {
+ this->kbdX = 2;
+ } else if (this->kbdX < 10) {
+ this->kbdX = 3;
+ } else if (this->kbdX < 13) {
+ this->kbdX = 4;
+ }
+ this->unk_2451E[this->kbdX] = prevKbdX;
+ }
+ }
+ }
+ }
+ if (this->kbdY == 5) {
+ this->kbdButton = this->kbdX;
+ }
+}
+
+/**
+ * Update and wait for the save to flash to complete.
+ * Update function for `CM_NAME_ENTRY_WAIT_FOR_FLASH_SAVE`
+ */
+void FileSelect_NameEntryWaitForFlashSave(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+
+ Sram_UpdateWriteToFlashDefault(sramCtx);
+
+ if (sramCtx->status == 0) {
+ this->configMode = CM_NAME_ENTRY_TO_MAIN;
+ }
+}
+
+/**
+ * This function is mostly a copy paste of `FileSelect_StartNameEntry`.
+ * The name entry box fades and slides in even though it is not visible.
+ * After this is complete, change to the options config mode.
+ * Update function for `CM_START_OPTIONS`
+ */
+void FileSelect_StartOptions(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+
+ this->nameEntryBoxAlpha += 25;
+
+ if (this->nameEntryBoxAlpha >= 255) {
+ this->nameEntryBoxAlpha = 255;
+ }
+
+ this->nameEntryBoxPosX -= 30;
+
+ if (this->nameEntryBoxPosX <= 0) {
+ this->nameEntryBoxPosX = 0;
+ this->nameEntryBoxAlpha = 255;
+ this->configMode = CM_OPTIONS_MENU;
+ }
+}
+
+u8 sSelectedSetting;
+// bss padding
+s32 D_80814E94;
+s32 D_80814E98;
+s32 D_80814E9C;
+s32 D_80814EA0;
+
+/**
+ * Update the cursor and appropriate settings for the options menu.
+ * If the player presses B, write the selected options to the SRAM header
+ * and set config mode to rotate back to the main menu.
+ * Update function for `CM_OPTIONS_MENU`
+ */
+void FileSelect_UpdateOptionsMenu(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+ Input* input = CONTROLLER1(&this->state);
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ Sram_WriteSaveOptionsToBuffer(sramCtx);
+
+ if (!gSaveContext.flashSaveAvailable) {
+ this->configMode = CM_OPTIONS_TO_MAIN;
+ } else {
+ Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[8], gFlashSpecialSaveNumPages[8]);
+ Sram_StartWriteToFlashDefault(sramCtx);
+ this->configMode = CM_OPTIONS_WAIT_FOR_FLASH_SAVE;
+ }
+ Audio_SetFileSelectSettings(gSaveContext.options.audioSetting);
+ return;
+ }
+
+ if (this->stickAdjX < -30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+
+ if (sSelectedSetting == FS_SETTING_AUDIO) {
+ gSaveContext.options.audioSetting--;
+
+ // because audio setting is unsigned, can't check for < 0
+ if (gSaveContext.options.audioSetting > 0xF0) {
+ gSaveContext.options.audioSetting = SAVE_AUDIO_SURROUND;
+ }
+ } else {
+ gSaveContext.options.zTargetSetting ^= 1;
+ }
+ } else if (this->stickAdjX > 30) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+
+ if (sSelectedSetting == FS_SETTING_AUDIO) {
+ gSaveContext.options.audioSetting++;
+ if (gSaveContext.options.audioSetting > SAVE_AUDIO_SURROUND) {
+ gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO;
+ }
+ } else {
+ gSaveContext.options.zTargetSetting ^= 1;
+ }
+ }
+
+ if ((this->stickAdjY < -30) || (this->stickAdjY > 30)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_CURSOR);
+ sSelectedSetting ^= 1;
+ return;
+ }
+ if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ Audio_PlaySfx(NA_SE_SY_FSEL_DECIDE_L);
+ sSelectedSetting ^= 1;
+ }
+}
+
+/**
+ * Update and wait for the save to flash to complete.
+ * Update function for `CM_OPTIONS_WAIT_FOR_FLASH_SAVE`
+ */
+void FileSelect_OptionsWaitForFlashSave(GameState* thisx) {
+ FileSelectState* this = (FileSelectState*)thisx;
+ SramContext* sramCtx = &this->sramCtx;
+
+ Sram_UpdateWriteToFlashDefault(sramCtx);
+
+ if (sramCtx->status == 0) {
+ this->configMode = CM_OPTIONS_TO_MAIN;
+ }
+}
+
+typedef struct {
+ /* 0x0 */ TexturePtr texture;
+ /* 0x4 */ u16 width;
+ /* 0x6 */ u16 height;
+} OptionsMenuTextureInfo; // size = 0x8
+
+OptionsMenuTextureInfo gOptionsMenuHeaders[] = {
+ { gFileSelOptionsENGTex, 128, 16 }, { gFileSelSoundENGTex, 64, 16 },
+ { gFileSelTargetingENGTex, 64, 16 }, { gFileSelCheckBrightnessENGTex, 96, 16 },
+ { gFileSelDolbySurroundLogoENGTex, 48, 17 },
+};
+
+OptionsMenuTextureInfo gOptionsMenuSettings[] = {
+ { gFileSelStereoENGTex, 48, 16 }, { gFileSelMonoENGTex, 48, 16 }, { gFileSelHeadsetENGTex, 48, 16 },
+ { gFileSelSurroundENGTex, 48, 16 }, { gFileSelSwitchENGTex, 48, 16 }, { gFileSelHoldENGTex, 48, 16 },
+};
+
+void FileSelect_DrawOptionsImpl(GameState* thisx) {
+ static s16 sCursorPrimRed = 255;
+ static s16 sCursorPrimGreen = 255;
+ static s16 sCursorPrimBlue = 255;
+ static s16 sCursorEnvRed = 0;
+ static s16 sCursorEnvGreen = 0;
+ static s16 sCursorEnvBlue = 0;
+ static s16 sCursorPulseDir = 1;
+ static s16 sCursorFlashTimer = 20;
+ static s16 sCursorPrimColors[][3] = {
+ { 255, 255, 255 },
+ { 0, 255, 255 },
+ };
+ static s16 sCursorEnvColors[][3] = {
+ { 0, 0, 0 },
+ { 0, 150, 150 },
+ };
+ FileSelectState* this = (FileSelectState*)thisx;
+ s16 cursorRedStep;
+ s16 cursorGreenStep;
+ s16 cursorBlueStep;
+ s16 i;
+ s16 j;
+ s16 vtx;
+
+ OPEN_DISPS(this->state.gfxCtx);
+
+ cursorRedStep = ABS_ALT(sCursorPrimRed - sCursorPrimColors[sCursorPulseDir][0]) / sCursorFlashTimer;
+ cursorGreenStep = ABS_ALT(sCursorPrimGreen - sCursorPrimColors[sCursorPulseDir][1]) / sCursorFlashTimer;
+ cursorBlueStep = ABS_ALT(sCursorPrimBlue - sCursorPrimColors[sCursorPulseDir][2]) / sCursorFlashTimer;
+
+ if (sCursorPrimRed >= sCursorPrimColors[sCursorPulseDir][0]) {
+ sCursorPrimRed -= cursorRedStep;
+ } else {
+ sCursorPrimRed += cursorRedStep;
+ }
+
+ if (sCursorPrimGreen >= sCursorPrimColors[sCursorPulseDir][1]) {
+ sCursorPrimGreen -= cursorGreenStep;
+ } else {
+ sCursorPrimGreen += cursorGreenStep;
+ }
+
+ if (sCursorPrimBlue >= sCursorPrimColors[sCursorPulseDir][2]) {
+ sCursorPrimBlue -= cursorBlueStep;
+ } else {
+ sCursorPrimBlue += cursorBlueStep;
+ }
+
+ cursorRedStep = ABS_ALT(sCursorEnvRed - sCursorEnvColors[sCursorPulseDir][0]) / sCursorFlashTimer;
+ cursorGreenStep = ABS_ALT(sCursorEnvGreen - sCursorEnvColors[sCursorPulseDir][1]) / sCursorFlashTimer;
+ cursorBlueStep = ABS_ALT(sCursorEnvBlue - sCursorEnvColors[sCursorPulseDir][2]) / sCursorFlashTimer;
+
+ if (sCursorEnvRed >= sCursorEnvColors[sCursorPulseDir][0]) {
+ sCursorEnvRed -= cursorRedStep;
+ } else {
+ sCursorEnvRed += cursorRedStep;
+ }
+
+ if (sCursorEnvGreen >= sCursorEnvColors[sCursorPulseDir][1]) {
+ sCursorEnvGreen -= cursorGreenStep;
+ } else {
+ sCursorEnvGreen += cursorGreenStep;
+ }
+
+ if (sCursorEnvBlue >= sCursorEnvColors[sCursorPulseDir][2]) {
+ sCursorEnvBlue -= cursorBlueStep;
+ } else {
+ sCursorEnvBlue += cursorBlueStep;
+ }
+
+ if (--sCursorFlashTimer == 0) {
+ sCursorPrimRed = sCursorPrimColors[sCursorPulseDir][0];
+ sCursorPrimGreen = sCursorPrimColors[sCursorPulseDir][1];
+ sCursorPrimBlue = sCursorPrimColors[sCursorPulseDir][2];
+
+ sCursorEnvRed = sCursorEnvColors[sCursorPulseDir][0];
+ sCursorEnvGreen = sCursorEnvColors[sCursorPulseDir][1];
+ sCursorEnvBlue = sCursorEnvColors[sCursorPulseDir][2];
+
+ sCursorFlashTimer = 20;
+
+ if (++sCursorPulseDir > 1) {
+ sCursorPulseDir = 0;
+ }
+ }
+
+ // blue divider lines
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 0);
+
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, gFileSelOptionsDividerTex, G_IM_FMT_IA, 256, 2, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+
+ Matrix_Push();
+ Matrix_Translate(0.0f, 0.1f, 0.0f, MTXMODE_APPLY);
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+ gSPVertex(POLY_OPA_DISP++, gOptionsDividerTopVtx, 4, 0);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ Matrix_Pop();
+
+ Matrix_Push();
+ Matrix_Translate(0.0f, 0.2f, 0.0f, MTXMODE_APPLY);
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+ gSPVertex(POLY_OPA_DISP++, gOptionsDividerMiddleVtx, 4, 0);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ Matrix_Pop();
+
+ Matrix_Push();
+ Matrix_Translate(0.0f, 0.4f, 0.0f, MTXMODE_APPLY);
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, this->state.gfxCtx);
+ gSPVertex(POLY_OPA_DISP++, gOptionsDividerBottomVtx, 4, 0);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ Matrix_Pop();
+
+ gSPVertex(POLY_OPA_DISP++, D_80813DF0, 32, 0);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+
+ for (i = 0, vtx = 0; i < 5; i++, vtx += 4) {
+ if (i == 4) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ if (gSaveContext.options.audioSetting == SAVE_AUDIO_SURROUND) {
+ gDPSetEnvColor(POLY_OPA_DISP++, 255, 255, 255, 255);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 0, 0, 0, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+ }
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gOptionsMenuHeaders[i].texture, G_IM_FMT_IA, G_IM_SIZ_8b,
+ gOptionsMenuHeaders[i].width, gOptionsMenuHeaders[i].height, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ gSPVertex(POLY_OPA_DISP++, D_80813F30, 32, 0);
+
+ for (i = 0, vtx = 0; i < 4; i++, vtx += 4) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ if (i == gSaveContext.options.audioSetting) {
+ if (sSelectedSetting == FS_SETTING_AUDIO) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sCursorPrimRed, sCursorPrimGreen, sCursorPrimBlue,
+ this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, sCursorEnvRed, sCursorEnvGreen, sCursorEnvBlue, 255);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 120, 120, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gOptionsMenuSettings[i].texture, G_IM_FMT_IA, G_IM_SIZ_8b,
+ gOptionsMenuSettings[i].width, gOptionsMenuHeaders[i].height, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0);
+ }
+
+ for (; i < 6; i++, vtx += 4) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ if (i == (gSaveContext.options.zTargetSetting + 4)) {
+ if (sSelectedSetting == FS_SETTING_ZTARGET) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sCursorPrimRed, sCursorPrimGreen, sCursorPrimBlue,
+ this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, sCursorEnvRed, sCursorEnvGreen, sCursorEnvBlue, 255);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 120, 120, 120, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+
+ //! @bug the gOptionsMenuHeaders usage here will produce an OoB read for i == 5. It reads the first element of
+ //! `gOptionsMenuSettings`
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gOptionsMenuSettings[i].texture, G_IM_FMT_IA, G_IM_SIZ_8b,
+ gOptionsMenuSettings[i].width, gOptionsMenuHeaders[i].height, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0);
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ // check brightness bars
+ gDPLoadTextureBlock_4b(POLY_OPA_DISP++, gFileSelBrightnessCheckTex, G_IM_FMT_IA, 96, 16, 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);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 55, 55, 55, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 40, 40, 40, 255);
+ gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0);
+
+ vtx += 4;
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 30, 30, 30, this->titleAlpha[FS_TITLE_CUR]);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ gSP1Quadrangle(POLY_OPA_DISP++, vtx, vtx + 2, vtx + 3, vtx + 1, 0);
+
+ CLOSE_DISPS(this->state.gfxCtx);
+}
+
+void FileSelect_DrawOptions(GameState* thisx) {
+ FileSelect_DrawOptionsImpl(thisx);
+}
diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_JPN.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_JPN.c
new file mode 100644
index 000000000..e629ceeb6
--- /dev/null
+++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_JPN.c
@@ -0,0 +1,3746 @@
+/*
+ * File: z_kaleido_scope_NES.c
+ * Overlay: ovl_kaleido_scope
+ * Description: Pause Menu
+ */
+
+#include "z_kaleido_scope.h"
+
+#include "sys_cmpdma.h"
+#include "z64map.h"
+#include "z64skybox.h"
+#include "z64view.h"
+
+#include "overlays/gamestates/ovl_opening/z_opening.h"
+
+#include "assets/archives/icon_item_static/icon_item_static_yar.h"
+#include "assets/interface/icon_item_gameover_static/icon_item_gameover_static.h"
+#include "assets/interface/icon_item_jpn_static/icon_item_jpn_static.h"
+#include "assets/interface/icon_item_vtx_static/icon_item_vtx_static.h"
+
+// Page Textures (Background of Page):
+// Broken up into multiple textures.
+// Numbered by column/row.
+TexturePtr sMaskPageBgTextures[] = {
+ // Column 0
+ gPauseMasks00Tex,
+ gPauseMasks01Tex,
+ gPauseMasks02Tex,
+ gPauseMasks03Tex,
+ gPauseMasks04Tex,
+ // Column 1
+ gPauseMasks10ENGTex,
+ gPauseMasks11Tex,
+ gPauseMasks12Tex,
+ gPauseMasks13Tex,
+ gPauseMasks14Tex,
+ // Column 2
+ gPauseMasks20Tex,
+ gPauseMasks21Tex,
+ gPauseMasks22Tex,
+ gPauseMasks23Tex,
+ gPauseMasks24Tex,
+};
+TexturePtr sItemPageBgTextures[] = {
+ // Column 0
+ gPauseSelectItem00ENGTex,
+ gPauseSelectItem01Tex,
+ gPauseSelectItem02Tex,
+ gPauseSelectItem03Tex,
+ gPauseSelectItem04Tex,
+ // Column 1
+ gPauseSelectItem10ENGTex,
+ gPauseSelectItem11Tex,
+ gPauseSelectItem12Tex,
+ gPauseSelectItem13Tex,
+ gPauseSelectItem14Tex,
+ // Column 2
+ gPauseSelectItem20ENGTex,
+ gPauseSelectItem21Tex,
+ gPauseSelectItem22Tex,
+ gPauseSelectItem23Tex,
+ gPauseSelectItem24Tex,
+};
+TexturePtr sMapPageBgTextures[] = {
+ // Column 0
+ gPauseMap00Tex,
+ gPauseMap01Tex,
+ gPauseMap02Tex,
+ gPauseMap03Tex,
+ gPauseMap04Tex,
+ // Column 1
+ gPauseMap10ENGTex,
+ gPauseMap11Tex,
+ gPauseMap12Tex,
+ gPauseMap13Tex,
+ gPauseMap14Tex,
+ // Column 2
+ gPauseMap20Tex,
+ gPauseMap21Tex,
+ gPauseMap22Tex,
+ gPauseMap23Tex,
+ gPauseMap24Tex,
+};
+TexturePtr sQuestPageBgTextures[] = {
+ // Column 0
+ gPauseQuestStatus00ENGTex,
+ gPauseQuestStatus01Tex,
+ gPauseQuestStatus02Tex,
+ gPauseQuestStatus03Tex,
+ gPauseQuestStatus04Tex,
+ // Column 1
+ gPauseQuestStatus10ENGTex,
+ gPauseQuestStatus11Tex,
+ gPauseQuestStatus12Tex,
+ gPauseQuestStatus13Tex,
+ gPauseQuestStatus14Tex,
+ // Column 2
+ gPauseQuestStatus20ENGTex,
+ gPauseQuestStatus21Tex,
+ gPauseQuestStatus22Tex,
+ gPauseQuestStatus23Tex,
+ gPauseQuestStatus24Tex,
+};
+
+s16 gVtxPageMapWorldQuadsWidth[VTX_PAGE_MAP_WORLD_QUADS] = {
+ 80, // mapPageVtx[60] clouds Clock Town 1
+ 64, // mapPageVtx[64] clouds Clock Town 2
+ 64, // mapPageVtx[68] clouds Woodfall 1
+ 64, // mapPageVtx[72] clouds Woodfall 2
+ 16, // mapPageVtx[76] clouds Woodfall 3
+ 64, // mapPageVtx[80] clouds Snowhead 1
+ 112, // mapPageVtx[84] clouds Snowhead 2
+ 112, // mapPageVtx[88] clouds Snowhead 3
+ 48, // mapPageVtx[92] clouds Romani Ranch
+ 64, // mapPageVtx[96] clouds Great Bay 1
+ 64, // mapPageVtx[100] clouds Great Bay 2
+ 64, // mapPageVtx[104] clouds Great Bay 3
+ 64, // mapPageVtx[108] clouds Great Bay 4
+ 48, // mapPageVtx[112] clouds Stone Tower 1
+ 64, // mapPageVtx[116] clouds Stone Tower 2
+ 8, // mapPageVtx[120] region Great Bay
+ 8, // mapPageVtx[124] region Zora Hall
+ 8, // mapPageVtx[128] region Romani Ranch
+ 8, // mapPageVtx[132] region Deku Palace
+ 8, // mapPageVtx[136] region Woodfall
+ 8, // mapPageVtx[140] region Clock Town
+ 8, // mapPageVtx[144] region Snowhead
+ 8, // mapPageVtx[148] region Ikana Graveyard
+ 8, // mapPageVtx[152] region Ikana Canyon
+ 8, // mapPageVtx[156] region Goron Village
+ 8, // mapPageVtx[160] region Stone Tower
+ 24, // mapPageVtx[164] owl warp Great Bay Coast
+ 24, // mapPageVtx[168] owl warp Zora Cape
+ 24, // mapPageVtx[172] owl warp Snowhead
+ 24, // mapPageVtx[176] owl warp Mountain Village
+ 24, // mapPageVtx[180] owl warp Clock Town
+ 24, // mapPageVtx[184] owl warp Milk Road
+ 24, // mapPageVtx[188] owl warp Woodfall
+ 24, // mapPageVtx[192] owl warp Southern Swamp
+ 24, // mapPageVtx[196] owl warp Ikana Canyon
+ 24, // mapPageVtx[200] owl warp Stone Tower
+};
+s16 gVtxPageMapWorldQuadsHeight[VTX_PAGE_MAP_WORLD_QUADS] = {
+ 40, // mapPageVtx[60] clouds Clock Town 1
+ 31, // mapPageVtx[64] clouds Clock Town 2
+ 53, // mapPageVtx[68] clouds Woodfall 1
+ 53, // mapPageVtx[72] clouds Woodfall 2
+ 53, // mapPageVtx[76] clouds Woodfall 3
+ 52, // mapPageVtx[80] clouds Snowhead 1
+ 35, // mapPageVtx[84] clouds Snowhead 2
+ 35, // mapPageVtx[88] clouds Snowhead 3
+ 32, // mapPageVtx[92] clouds Romani Ranch
+ 64, // mapPageVtx[96] clouds Great Bay 1
+ 64, // mapPageVtx[100] clouds Great Bay 2
+ 64, // mapPageVtx[104] clouds Great Bay 3
+ 64, // mapPageVtx[108] clouds Great Bay 4
+ 82, // mapPageVtx[112] clouds Stone Tower 1
+ 61, // mapPageVtx[116] clouds Stone Tower 2
+ 8, // mapPageVtx[120] region Great Bay
+ 8, // mapPageVtx[124] region Zora Hall
+ 8, // mapPageVtx[128] region Romani Ranch
+ 8, // mapPageVtx[132] region Deku Palace
+ 8, // mapPageVtx[136] region Woodfall
+ 8, // mapPageVtx[140] region Clock Town
+ 8, // mapPageVtx[144] region Snowhead
+ 8, // mapPageVtx[148] region Ikana Graveyard
+ 8, // mapPageVtx[152] region Ikana Canyon
+ 8, // mapPageVtx[156] region Goron Village
+ 8, // mapPageVtx[160] region Stone Tower
+ 12, // mapPageVtx[164] owl warp Great Bay Coast
+ 12, // mapPageVtx[168] owl warp Zora Cape
+ 12, // mapPageVtx[172] owl warp Snowhead
+ 12, // mapPageVtx[176] owl warp Mountain Village
+ 12, // mapPageVtx[180] owl warp Clock Town
+ 12, // mapPageVtx[184] owl warp Milk Road
+ 12, // mapPageVtx[188] owl warp Woodfall
+ 12, // mapPageVtx[192] owl warp Southern Swamp
+ 12, // mapPageVtx[196] owl warp Ikana Canyon
+ 12, // mapPageVtx[200] owl warp Stone Tower
+};
+
+s16 sGameOverPrimR = 0;
+s16 sGameOverPrimG = 0;
+s16 sGameOverPrimB = 0;
+s16 sGameOverPrimAlpha = 255;
+s16 sCursorPrimR = 0;
+s16 sCursorPrimG = 0;
+s16 sCursorPrimB = 0;
+s16 sCursorEnvR = 0;
+s16 sCursorEnvG = 0;
+s16 sCursorEnvB = 0;
+s16 sGameOverEnvR = 255;
+s16 sGameOverEnvG = 0;
+s16 sGameOverEnvB = 0;
+
+s16 sInDungeonScene = false;
+
+f32 sPageSwitchEyeDx[] = {
+ -PAUSE_EYE_DIST * (PAUSE_MAP_X - PAUSE_ITEM_X) / 16, // From PAUSE_ITEM to PAUSE_MAP (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_MASK_X - PAUSE_ITEM_X) / 16, // From PAUSE_ITEM to PAUSE_MASK (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_QUEST_X - PAUSE_MAP_X) / 16, // From PAUSE_MAP to PAUSE_QUEST (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_ITEM_X - PAUSE_MAP_X) / 16, // From PAUSE_MAP to PAUSE_ITEM (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_MASK_X - PAUSE_QUEST_X) / 16, // From PAUSE_QUEST to PAUSE_MASK (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_MAP_X - PAUSE_QUEST_X) / 16, // From PAUSE_QUEST to PAUSE_MAP (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_ITEM_X - PAUSE_MASK_X) / 16, // From PAUSE_MASK to PAUSE_ITEM (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_QUEST_X - PAUSE_MASK_X) / 16, // From PAUSE_MASK to PAUSE_QUEST (switching left)
+};
+
+f32 sPageSwitchEyeDz[] = {
+ -PAUSE_EYE_DIST * (PAUSE_MAP_Z - PAUSE_ITEM_Z) / 16, // From PAUSE_ITEM to PAUSE_MAP (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_MASK_Z - PAUSE_ITEM_Z) / 16, // From PAUSE_ITEM to PAUSE_MASK (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_QUEST_Z - PAUSE_MAP_Z) / 16, // From PAUSE_MAP to PAUSE_QUEST (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_ITEM_Z - PAUSE_MAP_Z) / 16, // From PAUSE_MAP to PAUSE_ITEM (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_MASK_Z - PAUSE_QUEST_Z) / 16, // From PAUSE_QUEST to PAUSE_MASK (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_MAP_Z - PAUSE_QUEST_Z) / 16, // From PAUSE_QUEST to PAUSE_MAP (switching left)
+ -PAUSE_EYE_DIST*(PAUSE_ITEM_Z - PAUSE_MASK_Z) / 16, // From PAUSE_MASK to PAUSE_ITEM (switching right)
+ -PAUSE_EYE_DIST*(PAUSE_QUEST_Z - PAUSE_MASK_Z) / 16, // From PAUSE_MASK to PAUSE_QUEST (switching left)
+};
+
+u16 sPageSwitchNextPageIndex[] = {
+ PAUSE_MAP, // From PAUSE_ITEM (switching right)
+ PAUSE_MASK, // From PAUSE_ITEM (switching left)
+ PAUSE_QUEST, // From PAUSE_MAP (switching right)
+ PAUSE_ITEM, // From PAUSE_MAP (switching left)
+ PAUSE_MASK, // From PAUSE_QUEST (switching right)
+ PAUSE_MAP, // From PAUSE_QUEST (switching left)
+ PAUSE_ITEM, // From PAUSE_MASK (switching right)
+ PAUSE_QUEST, // From PAUSE_MASK (switching left)
+};
+
+f32 sPauseMenuVerticalOffset = 0.0f;
+f32 D_8082B90C = 0.0f;
+f32 sPauseCursorLeftMoveOffsetX = 40.0f;
+f32 sPauseCursorRightMoveOffsetX = -40.0f;
+
+s16 sPauseCursorLeftX = 0;
+s16 sPauseCursorRightX = 0;
+
+s16 D_8082B920 = 10;
+
+s16 sPauseZRCursorColorTimerInits[] = { 20, 4, 20, 10 };
+
+// Unused remnant of OoT
+u8 gAreaGsFlags[] = {
+ 0x0F, 0x1F, 0x0F, 0x1F, 0x1F, 0x1F, 0x1F, 0x1F, 0x07, 0x07, 0x03, 0x0F,
+ 0x07, 0x0F, 0x0F, 0xFF, 0xFF, 0xFF, 0x1F, 0x0F, 0x03, 0x0F, 0x00, 0x00,
+};
+
+// TODO: Also applies to owl warps
+s16 sGameOverRectPosY = 66;
+
+void Kaleido_LoadMapNameStatic(void* segment, u32 texIndex) {
+ CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0x400);
+}
+
+//! note: nothing from `map_name_static` is of size `0xA00` in US 1.0
+void Kaleido_LoadMapNameStaticLarge(void* segment, u32 texIndex) {
+ CmpDma_LoadFile(SEGMENT_ROM_START(map_name_static), texIndex, segment, 0xA00);
+}
+
+void Kaleido_LoadItemNameStatic(void* segment, u32 texIndex) {
+ CmpDma_LoadFile(SEGMENT_ROM_START(item_name_static), texIndex, segment, 0x400);
+}
+
+void KaleidoScope_MoveCursorToSpecialPos(PlayState* play, s16 cursorSpecialPos) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+
+ pauseCtx->cursorSlot[pauseCtx->pageIndex] = 0;
+ pauseCtx->cursorSpecialPos = cursorSpecialPos;
+ pauseCtx->pageSwitchInputTimer = 0;
+
+ Audio_PlaySfx(NA_SE_SY_DECIDE);
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_DISABLED;
+
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+ Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
+}
+
+void KaleidoScope_MoveCursorFromSpecialPos(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+
+ pauseCtx->nameDisplayTimer = 0;
+ pauseCtx->cursorSpecialPos = 0;
+
+ Audio_PlaySfx(NA_SE_SY_CURSOR);
+
+ pauseCtx->cursorShrinkRate = 4.0f;
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_ENABLED;
+
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+
+ Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
+}
+
+void KaleidoScope_DrawTexQuadRGBA32(GraphicsContext* gfxCtx, TexturePtr texture, u16 width, u16 height, u16 point) {
+ OPEN_DISPS(gfxCtx);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, texture, G_IM_FMT_RGBA, G_IM_SIZ_32b, width, height, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD,
+ G_TX_NOLOD);
+ gSP1Quadrangle(POLY_OPA_DISP++, point, point + 2, point + 3, point + 1, 0);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+#define SWITCH_PAGE_LEFT 0
+#define SWITCH_PAGE_RIGHT 2
+
+void KaleidoScope_SwitchPage(PauseContext* pauseCtx, u8 direction) {
+ pauseCtx->cursorSlot[pauseCtx->pageIndex] = 0;
+ pauseCtx->mainState = PAUSE_MAIN_STATE_SWITCHING_PAGE;
+ pauseCtx->switchPageTimer = 0;
+
+ if (direction == SWITCH_PAGE_LEFT) {
+ pauseCtx->nextPageMode = (pauseCtx->pageIndex * 2) + 1;
+ Audio_PlaySfx(NA_SE_SY_WIN_SCROLL_LEFT);
+ pauseCtx->cursorSpecialPos = PAUSE_CURSOR_PAGE_RIGHT;
+ } else { // SWITCH_PAGE_RIGHT
+ pauseCtx->nextPageMode = pauseCtx->pageIndex * 2;
+ Audio_PlaySfx(NA_SE_SY_WIN_SCROLL_RIGHT);
+ pauseCtx->cursorSpecialPos = PAUSE_CURSOR_PAGE_LEFT;
+ }
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_DISABLED;
+
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+ Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
+}
+
+/**
+ * Process inputs to decide whether to switch pages
+ */
+void KaleidoScope_HandlePageToggles(PlayState* play, Input* input) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ InterfaceContext* interfaceCtx = &play->interfaceCtx;
+
+ //! FAKE
+ if (1) {}
+
+ if ((pauseCtx->debugEditor != DEBUG_EDITOR_NONE) || pauseCtx->itemDescriptionOn) {
+ return;
+ }
+
+ if (CHECK_BTN_ALL(input->cur.button, BTN_DRIGHT) || CHECK_BTN_ALL(input->press.button, BTN_R)) {
+ // Switch the page to the right regardless of where the cursor is
+ if (interfaceCtx->aButtonDoActionDelayed == DO_ACTION_DECIDE) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_INFO);
+ }
+ KaleidoScope_SwitchPage(pauseCtx, SWITCH_PAGE_RIGHT);
+ return;
+ }
+
+ if (CHECK_BTN_ALL(input->cur.button, BTN_DLEFT) || CHECK_BTN_ALL(input->press.button, BTN_Z)) {
+ // Switch the page to the left regardless of where the cursor is
+ if (interfaceCtx->aButtonDoActionDelayed == DO_ACTION_DECIDE) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_INFO);
+ }
+ KaleidoScope_SwitchPage(pauseCtx, SWITCH_PAGE_LEFT);
+ return;
+ }
+
+ if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
+ if (pauseCtx->stickAdjX < -30) {
+ pauseCtx->pageSwitchInputTimer++;
+ // Switch the page to the left after a certain number of frames with held input or after a second press
+ if ((pauseCtx->pageSwitchInputTimer >= 10) || (pauseCtx->pageSwitchInputTimer == 0)) {
+ KaleidoScope_SwitchPage(pauseCtx, SWITCH_PAGE_LEFT);
+ }
+ } else {
+ // stickAdjX is no longer held, so that the next input to the left will immediately switch pages
+ pauseCtx->pageSwitchInputTimer = -1;
+ }
+ } else if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) {
+ if (pauseCtx->stickAdjX > 30) {
+ pauseCtx->pageSwitchInputTimer++;
+ // Switch the page to the right after a certain number of frames with held input or after a second press
+ if ((pauseCtx->pageSwitchInputTimer >= 10) || (pauseCtx->pageSwitchInputTimer == 0)) {
+ KaleidoScope_SwitchPage(pauseCtx, SWITCH_PAGE_RIGHT);
+ }
+ } else {
+ // stickAdjY is no longer held, so that the next input to the right will immediately switch pages
+ pauseCtx->pageSwitchInputTimer = -1;
+ }
+ }
+}
+
+// Draw 15 (PAGE_BG_QUADS) quads with IA8 80x32 textures
+Gfx* KaleidoScope_DrawPageSections(Gfx* gfx, Vtx* vertices, TexturePtr* textures) {
+ s32 i;
+ s32 j;
+
+ gSPVertex(gfx++, vertices, 8 * 4, 0);
+
+ i = 0;
+ j = 0;
+ // Draw first 8/15 background textures
+ while (j < 32) {
+ gDPPipeSync(gfx++);
+ gDPLoadTextureBlock(gfx++, textures[i], G_IM_FMT_IA, G_IM_SIZ_8b, 80, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(gfx++, j, j + 2, j + 3, j + 1, 0);
+
+ j += 4;
+ i++;
+ }
+
+ gSPVertex(gfx++, vertices + (8 * 4), 7 * 4, 0);
+
+ j = 0;
+ // Draw last 7/15 background textures
+ while (j < 28) {
+ gDPPipeSync(gfx++);
+ gDPLoadTextureBlock(gfx++, textures[i], G_IM_FMT_IA, G_IM_SIZ_8b, 80, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+ gSP1Quadrangle(gfx++, j, j + 2, j + 3, j + 1, 0);
+
+ j += 4;
+ i++;
+ }
+
+ return gfx;
+}
+
+s16 sCursorPrimColorTarget[][3] = {
+ { 255, 255, 255 }, { 255, 255, 255 }, { 255, 255, 0 }, { 255, 255, 0 }, { 100, 150, 255 }, { 100, 255, 255 },
+};
+
+s16 sCursorEnvColorTarget[][3] = {
+ { 0, 0, 0 }, { 170, 170, 170 }, { 0, 0, 0 }, { 255, 160, 0 }, { 0, 0, 100 }, { 0, 150, 255 },
+};
+
+void KaleidoScope_DrawPages(PlayState* play, GraphicsContext* gfxCtx) {
+ static s16 sCursorColorTimer = 10;
+ static s16 sCursorColorTargetIndex = 0;
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 stepR;
+ s16 stepG;
+ s16 stepB;
+
+ OPEN_DISPS(gfxCtx);
+
+ if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
+ if (pauseCtx->state != PAUSE_STATE_SAVEPROMPT) {
+
+ stepR =
+ ABS_ALT(sCursorPrimR - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) /
+ sCursorColorTimer;
+ stepG =
+ ABS_ALT(sCursorPrimG - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) /
+ sCursorColorTimer;
+ stepB =
+ ABS_ALT(sCursorPrimB - sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) /
+ sCursorColorTimer;
+
+ if (sCursorPrimR >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) {
+ sCursorPrimR -= stepR;
+ } else {
+ sCursorPrimR += stepR;
+ }
+
+ if (sCursorPrimG >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) {
+ sCursorPrimG -= stepG;
+ } else {
+ sCursorPrimG += stepG;
+ }
+
+ if (sCursorPrimB >= sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) {
+ sCursorPrimB -= stepB;
+ } else {
+ sCursorPrimB += stepB;
+ }
+
+ stepR =
+ ABS_ALT(sCursorEnvR - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) /
+ sCursorColorTimer;
+ stepG =
+ ABS_ALT(sCursorEnvG - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) /
+ sCursorColorTimer;
+ stepB =
+ ABS_ALT(sCursorEnvB - sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) /
+ sCursorColorTimer;
+
+ if (sCursorEnvR >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0]) {
+ sCursorEnvR -= stepR;
+ } else {
+ sCursorEnvR += stepR;
+ }
+
+ if (sCursorEnvG >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1]) {
+ sCursorEnvG -= stepG;
+ } else {
+ sCursorEnvG += stepG;
+ }
+
+ if (sCursorEnvB >= sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2]) {
+ sCursorEnvB -= stepB;
+ } else {
+ sCursorEnvB += stepB;
+ }
+
+ sCursorColorTimer--;
+ if (sCursorColorTimer == 0) {
+ sCursorPrimR = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0];
+ sCursorPrimG = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1];
+ sCursorPrimB = sCursorPrimColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2];
+ sCursorEnvR = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][0];
+ sCursorEnvG = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][1];
+ sCursorEnvB = sCursorEnvColorTarget[pauseCtx->cursorColorSet + sCursorColorTargetIndex][2];
+ sCursorColorTargetIndex ^= 1;
+ sCursorColorTimer = 10;
+ }
+ }
+
+ if ((pauseCtx->pageIndex != PAUSE_ITEM) && (pauseCtx->pageIndex != PAUSE_QUEST)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0,
+ TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(0.0f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->itemPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->itemPageVtx, sItemPageBgTextures);
+
+ KaleidoScope_DrawItemSelect(play);
+ }
+
+ if ((pauseCtx->pageIndex != PAUSE_MAP) && (pauseCtx->pageIndex != PAUSE_MASK)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0,
+ TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(-1.57f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures);
+
+ if (sInDungeonScene) {
+ KaleidoScope_DrawDungeonMap(play);
+ Gfx_SetupDL42_Opa(gfxCtx);
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+ MapDisp_DrawDungeonMap(play);
+ } else {
+ KaleidoScope_DrawWorldMap(play);
+ }
+ }
+
+ if ((pauseCtx->pageIndex != PAUSE_QUEST) && (pauseCtx->pageIndex != PAUSE_ITEM)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0,
+ TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(-3.14f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->questPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->questPageVtx, sQuestPageBgTextures);
+
+ KaleidoScope_DrawQuestStatus(play);
+ }
+
+ if ((pauseCtx->pageIndex != PAUSE_MASK) && (pauseCtx->pageIndex != PAUSE_MAP)) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0,
+ TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(1.57f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->maskPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->maskPageVtx, sMaskPageBgTextures);
+
+ KaleidoScope_DrawMaskSelect(play);
+ }
+
+ switch (pauseCtx->pageIndex) {
+ case PAUSE_ITEM:
+ if (pauseCtx->mainState <= PAUSE_MAIN_STATE_EQUIP_MASK) {
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0,
+ PRIMITIVE, 0, TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(0.0f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->itemPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP =
+ KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->itemPageVtx, sItemPageBgTextures);
+
+ KaleidoScope_DrawItemSelect(play);
+ }
+ break;
+
+ case PAUSE_MAP:
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE,
+ 0, TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(-1.57f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures);
+
+ if (sInDungeonScene) {
+ KaleidoScope_DrawDungeonMap(play);
+ Gfx_SetupDL42_Opa(gfxCtx);
+
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ MapDisp_DrawDungeonMap(play);
+ } else {
+ Matrix_RotateYF(R_PAUSE_WORLD_MAP_YAW / 1000.0f, MTXMODE_NEW);
+
+ if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWL_WARP_3) ||
+ (pauseCtx->state >= PAUSE_STATE_OWL_WARP_6) ||
+ ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) &&
+ ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) ||
+ (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) {
+ Matrix_Translate(0.0f, (R_PAUSE_WORLD_MAP_Y_OFFSET - 8000) / 100.0f,
+ R_PAUSE_WORLD_MAP_DEPTH / 100.0f, MTXMODE_APPLY);
+ } else {
+ Matrix_Translate(0.0f, R_PAUSE_WORLD_MAP_Y_OFFSET / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f,
+ MTXMODE_APPLY);
+ }
+
+ Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ KaleidoScope_DrawWorldMap(play);
+ }
+ break;
+
+ case PAUSE_QUEST:
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE,
+ 0, TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ gDPSetTextureFilter(POLY_OPA_DISP++, G_TF_BILERP);
+
+ Matrix_RotateYF(-3.14f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->questPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP =
+ KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->questPageVtx, sQuestPageBgTextures);
+
+ KaleidoScope_DrawQuestStatus(play);
+ break;
+
+ case PAUSE_MASK:
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE,
+ 0, TEXEL0, 0, SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(1.57f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->maskPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, gfxCtx);
+
+ POLY_OPA_DISP =
+ KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->maskPageVtx, sMaskPageBgTextures);
+
+ KaleidoScope_DrawMaskSelect(play);
+ break;
+ }
+ }
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+TexturePtr D_8082B998[] = {
+ gPauseToMasksENGTex,
+ gPauseToSelectItemENGTex,
+ gPauseToMapENGTex,
+ gPauseToQuestStatusENGTex,
+};
+TexturePtr D_8082B9A8[] = {
+ gPauseToMapENGTex,
+ gPauseToQuestStatusENGTex,
+ gPauseToMasksENGTex,
+ gPauseToSelectItemENGTex,
+};
+void KaleidoScope_DrawInfoPanel(PlayState* play) {
+ static s16 sPauseZRCursorColorTargets[][4] = {
+ { 180, 210, 255, 220 },
+ { 100, 100, 150, 220 },
+ };
+ static s16 sPauseZRCursorColorTimer = 20;
+ static s16 sPauseZRCursorColorIndex = 0;
+ static s16 sPauseZRCursorRed;
+ static s16 sPauseZRCursorGreen;
+ static s16 sPauseZRCursorBlue;
+ static s16 sPauseZRCursorAlpha;
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 stepR;
+ s16 stepG;
+ s16 stepB;
+ s16 stepA;
+ s16 y;
+ s16 i;
+ s16 j;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ stepR =
+ ABS_ALT(sPauseZRCursorRed - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0]) / sPauseZRCursorColorTimer;
+ stepG = ABS_ALT(sPauseZRCursorGreen - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1]) /
+ sPauseZRCursorColorTimer;
+ stepB = ABS_ALT(sPauseZRCursorBlue - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2]) /
+ sPauseZRCursorColorTimer;
+ stepA = ABS_ALT(sPauseZRCursorAlpha - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3]) /
+ sPauseZRCursorColorTimer;
+
+ if (sPauseZRCursorRed >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0]) {
+ sPauseZRCursorRed -= stepR;
+ } else {
+ sPauseZRCursorRed += stepR;
+ }
+
+ if (sPauseZRCursorGreen >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1]) {
+ sPauseZRCursorGreen -= stepG;
+ } else {
+ sPauseZRCursorGreen += stepG;
+ }
+
+ if (sPauseZRCursorBlue >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2]) {
+ sPauseZRCursorBlue -= stepB;
+ } else {
+ sPauseZRCursorBlue += stepB;
+ }
+
+ if (sPauseZRCursorAlpha >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3]) {
+ sPauseZRCursorAlpha -= stepA;
+ } else {
+ sPauseZRCursorAlpha += stepA;
+ }
+
+ sPauseZRCursorColorTimer--;
+ if (sPauseZRCursorColorTimer == 0) {
+ sPauseZRCursorRed = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0];
+ sPauseZRCursorGreen = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1];
+ sPauseZRCursorBlue = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2];
+ sPauseZRCursorAlpha = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3];
+ sPauseZRCursorColorTimer = sPauseZRCursorColorTimerInits[0];
+ sPauseZRCursorColorIndex ^= 1;
+ }
+
+ y = pauseCtx->infoPanelOffsetY - 76;
+ for (j = 0, i = 0; i < 7; i++, j += 4) {
+ pauseCtx->infoPanelVtx[j + 0].v.ob[0] = pauseCtx->infoPanelVtx[j + 2].v.ob[0] = -72;
+
+ pauseCtx->infoPanelVtx[j + 1].v.ob[0] = pauseCtx->infoPanelVtx[j + 3].v.ob[0] = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.ob[1] = pauseCtx->infoPanelVtx[j + 1].v.ob[1] = y;
+
+ pauseCtx->infoPanelVtx[j + 2].v.ob[1] = pauseCtx->infoPanelVtx[j + 3].v.ob[1] = y - 24;
+
+ pauseCtx->infoPanelVtx[j + 0].v.ob[2] = pauseCtx->infoPanelVtx[j + 1].v.ob[2] =
+ pauseCtx->infoPanelVtx[j + 2].v.ob[2] = pauseCtx->infoPanelVtx[j + 3].v.ob[2] = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.flag = pauseCtx->infoPanelVtx[j + 1].v.flag =
+ pauseCtx->infoPanelVtx[j + 2].v.flag = pauseCtx->infoPanelVtx[j + 3].v.flag = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.tc[0] = pauseCtx->infoPanelVtx[j + 0].v.tc[1] =
+ pauseCtx->infoPanelVtx[j + 1].v.tc[1] = pauseCtx->infoPanelVtx[j + 2].v.tc[0] = 0;
+
+ pauseCtx->infoPanelVtx[j + 1].v.tc[0] = pauseCtx->infoPanelVtx[j + 3].v.tc[0] = 72 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[j + 2].v.tc[1] = pauseCtx->infoPanelVtx[j + 3].v.tc[1] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[j + 0].v.cn[0] = pauseCtx->infoPanelVtx[j + 2].v.cn[0] =
+ pauseCtx->infoPanelVtx[j + 0].v.cn[1] = pauseCtx->infoPanelVtx[j + 2].v.cn[1] =
+ pauseCtx->infoPanelVtx[j + 0].v.cn[2] = pauseCtx->infoPanelVtx[j + 2].v.cn[2] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[0] = pauseCtx->infoPanelVtx[j + 3].v.cn[0] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[1] = pauseCtx->infoPanelVtx[j + 3].v.cn[1] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[2] = pauseCtx->infoPanelVtx[j + 3].v.cn[2] = 200;
+
+ pauseCtx->infoPanelVtx[j + 0].v.cn[3] = pauseCtx->infoPanelVtx[j + 2].v.cn[3] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[3] = pauseCtx->infoPanelVtx[j + 3].v.cn[3] = pauseCtx->alpha;
+ }
+
+ pauseCtx->infoPanelVtx[4].v.ob[0] = pauseCtx->infoPanelVtx[6].v.ob[0] = pauseCtx->infoPanelVtx[0].v.ob[0] + 72;
+
+ pauseCtx->infoPanelVtx[5].v.ob[0] = pauseCtx->infoPanelVtx[7].v.ob[0] = pauseCtx->infoPanelVtx[4].v.ob[0] + 72;
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) {
+ pauseCtx->infoPanelVtx[8].v.ob[0] = pauseCtx->infoPanelVtx[10].v.ob[0] = sPauseCursorLeftX;
+
+ pauseCtx->infoPanelVtx[9].v.ob[0] = pauseCtx->infoPanelVtx[11].v.ob[0] = pauseCtx->infoPanelVtx[8].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[8].v.ob[1] = pauseCtx->infoPanelVtx[9].v.ob[1] = D_8082B920;
+
+ pauseCtx->infoPanelVtx[10].v.ob[1] = pauseCtx->infoPanelVtx[11].v.ob[1] =
+ pauseCtx->infoPanelVtx[8].v.ob[1] - 32;
+ } else {
+ pauseCtx->infoPanelVtx[8].v.ob[0] = pauseCtx->infoPanelVtx[10].v.ob[0] = sPauseCursorLeftX + 3;
+
+ pauseCtx->infoPanelVtx[9].v.ob[0] = pauseCtx->infoPanelVtx[11].v.ob[0] = pauseCtx->infoPanelVtx[8].v.ob[0] + 18;
+
+ pauseCtx->infoPanelVtx[8].v.ob[1] = pauseCtx->infoPanelVtx[9].v.ob[1] = D_8082B920 - 3;
+
+ pauseCtx->infoPanelVtx[10].v.ob[1] = pauseCtx->infoPanelVtx[11].v.ob[1] =
+ pauseCtx->infoPanelVtx[8].v.ob[1] - 26;
+ }
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) {
+ pauseCtx->infoPanelVtx[12].v.ob[0] = pauseCtx->infoPanelVtx[14].v.ob[0] = sPauseCursorRightX;
+
+ pauseCtx->infoPanelVtx[13].v.ob[0] = pauseCtx->infoPanelVtx[15].v.ob[0] =
+ pauseCtx->infoPanelVtx[12].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[12].v.ob[1] = pauseCtx->infoPanelVtx[13].v.ob[1] = D_8082B920;
+
+ pauseCtx->infoPanelVtx[14].v.ob[1] = pauseCtx->infoPanelVtx[15].v.ob[1] =
+ pauseCtx->infoPanelVtx[12].v.ob[1] - 32;
+ } else {
+ pauseCtx->infoPanelVtx[12].v.ob[0] = pauseCtx->infoPanelVtx[14].v.ob[0] = sPauseCursorRightX + 3;
+
+ pauseCtx->infoPanelVtx[13].v.ob[0] = pauseCtx->infoPanelVtx[15].v.ob[0] =
+ pauseCtx->infoPanelVtx[12].v.ob[0] + 18;
+
+ pauseCtx->infoPanelVtx[12].v.ob[1] = pauseCtx->infoPanelVtx[13].v.ob[1] = D_8082B920 - 3;
+
+ pauseCtx->infoPanelVtx[14].v.ob[1] = pauseCtx->infoPanelVtx[15].v.ob[1] =
+ pauseCtx->infoPanelVtx[12].v.ob[1] - 26;
+ }
+
+ pauseCtx->infoPanelVtx[9].v.tc[0] = pauseCtx->infoPanelVtx[11].v.tc[0] = pauseCtx->infoPanelVtx[13].v.tc[0] =
+ pauseCtx->infoPanelVtx[15].v.tc[0] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[10].v.tc[1] = pauseCtx->infoPanelVtx[11].v.tc[1] = pauseCtx->infoPanelVtx[14].v.tc[1] =
+ pauseCtx->infoPanelVtx[15].v.tc[1] = 32 * (1 << 5);
+
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ Matrix_Translate(0.0f, 0.0f, -144.0f, MTXMODE_NEW);
+ Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 140, 90, 255);
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0);
+
+ gSPDisplayList(POLY_OPA_DISP++, gItemNamePanelDL);
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) &&
+ (!pauseCtx->mainState || (pauseCtx->mainState == PAUSE_MAIN_STATE_UNK))) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 140, 90, sPauseZRCursorAlpha);
+ }
+
+ gSPDisplayList(POLY_OPA_DISP++, gZButtonIconDL);
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) &&
+ (!pauseCtx->mainState || (pauseCtx->mainState == PAUSE_MAIN_STATE_UNK))) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 140, 90, sPauseZRCursorAlpha);
+ }
+
+ gSPDisplayList(POLY_OPA_DISP++, gRButtonIconDL);
+
+ if (pauseCtx->cursorSpecialPos != 0) {
+ j = (pauseCtx->cursorSpecialPos * 4) - 32;
+ pauseCtx->cursorVtx[0].v.ob[0] = pauseCtx->infoPanelVtx[j].v.ob[0];
+ pauseCtx->cursorVtx[0].v.ob[1] = pauseCtx->infoPanelVtx[j].v.ob[1];
+ }
+
+ y = pauseCtx->infoPanelOffsetY - 80;
+ pauseCtx->infoPanelVtx[16].v.ob[1] = pauseCtx->infoPanelVtx[17].v.ob[1] = y;
+
+ pauseCtx->infoPanelVtx[18].v.ob[1] = pauseCtx->infoPanelVtx[19].v.ob[1] = pauseCtx->infoPanelVtx[16].v.ob[1] - 16;
+
+ pauseCtx->infoPanelVtx[18].v.tc[1] = pauseCtx->infoPanelVtx[19].v.tc[1] = 16 * (1 << 5);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetEnvColor(POLY_OPA_DISP++, 20, 30, 40, 0);
+
+ if (pauseCtx->itemDescriptionOn ||
+ ((pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->namedItem != PAUSE_ITEM_NONE) &&
+ (pauseCtx->nameDisplayTimer < 40) &&
+ (!pauseCtx->mainState || (pauseCtx->mainState == PAUSE_MAIN_STATE_SONG_PLAYBACK) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_UNK) ||
+ ((pauseCtx->mainState >= PAUSE_MAIN_STATE_SONG_PROMPT_INIT) &&
+ (pauseCtx->mainState <= PAUSE_MAIN_STATE_SONG_PROMPT_UNUSED)) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) &&
+ (pauseCtx->cursorSpecialPos == 0))) {
+ if (!pauseCtx->mainState || (pauseCtx->mainState == PAUSE_MAIN_STATE_SONG_PLAYBACK) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_UNK) ||
+ ((pauseCtx->mainState >= PAUSE_MAIN_STATE_SONG_PROMPT_INIT) &&
+ (pauseCtx->mainState <= PAUSE_MAIN_STATE_SONG_PROMPT_UNUSED)) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) {
+
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -63;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 128;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 128 * (1 << 5);
+
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->infoPanelVtx[16], 4, 0);
+
+ if (pauseCtx->nameColorSet == PAUSE_NAME_COLOR_SET_GREY) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 70, 70, 70, 255);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ }
+
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, pauseCtx->nameSegment, G_IM_FMT_IA, 128, 16, 0);
+ }
+ } else if ((pauseCtx->mainState <= PAUSE_MAIN_STATE_SONG_PLAYBACK) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_SONG_PROMPT_UNUSED) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_UNK)) {
+ pauseCtx->infoPanelVtx[20].v.ob[1] = pauseCtx->infoPanelVtx[21].v.ob[1] = y;
+
+ pauseCtx->infoPanelVtx[22].v.ob[1] = pauseCtx->infoPanelVtx[23].v.ob[1] =
+ pauseCtx->infoPanelVtx[20].v.ob[1] - 16;
+
+ pauseCtx->infoPanelVtx[22].v.tc[1] = pauseCtx->infoPanelVtx[23].v.tc[1] = 16 * (1 << 5);
+
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->infoPanelVtx[16], 8, 0);
+
+ if (pauseCtx->state == PAUSE_STATE_SAVEPROMPT) {
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -33;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[20].v.ob[0] = pauseCtx->infoPanelVtx[22].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 0x10;
+
+ pauseCtx->infoPanelVtx[21].v.ob[0] = pauseCtx->infoPanelVtx[23].v.ob[0] =
+ pauseCtx->infoPanelVtx[20].v.ob[0] + 0x30;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = 48 * (1 << 5);
+
+ gSPDisplayList(POLY_OPA_DISP++, gAButtonIconDL);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+
+ //! @bug: Incorrect dimensions. Should be 64x16
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, gPauseToDecideENGTex, G_IM_FMT_IA, 48, 16, 4);
+
+ } else if (pauseCtx->cursorSpecialPos != 0) {
+ if ((pauseCtx->state == PAUSE_STATE_MAIN) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) {
+
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -63;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 128;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 128 * (1 << 5);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 200, 0, 255);
+
+ if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
+ POLY_OPA_DISP =
+ Gfx_DrawTexQuad4b(POLY_OPA_DISP, D_8082B998[pauseCtx->pageIndex], G_IM_FMT_IA, 128, 16, 0);
+ } else {
+ POLY_OPA_DISP =
+ Gfx_DrawTexQuad4b(POLY_OPA_DISP, D_8082B9A8[pauseCtx->pageIndex], G_IM_FMT_IA, 128, 16, 0);
+ }
+ }
+ } else if ((!pauseCtx->pageIndex || (pauseCtx->pageIndex == PAUSE_MASK)) &&
+ (pauseCtx->namedItem != PAUSE_ITEM_NONE)) {
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -49;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 48;
+
+ pauseCtx->infoPanelVtx[20].v.ob[0] = pauseCtx->infoPanelVtx[22].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 47;
+
+ pauseCtx->infoPanelVtx[21].v.ob[0] = pauseCtx->infoPanelVtx[23].v.ob[0] =
+ pauseCtx->infoPanelVtx[20].v.ob[0] + 64;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 48 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = 64 * (1 << 5);
+
+ gSPDisplayList(POLY_OPA_DISP++, gCButtonIconsDL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, gPauseToEquipENGTex, G_IM_FMT_IA, 64, 16, 4);
+ } else if ((pauseCtx->pageIndex == PAUSE_MAP) && sInDungeonScene) {
+ // No code in this case
+ } else if ((pauseCtx->pageIndex == PAUSE_QUEST) &&
+ (pauseCtx->cursorSlot[PAUSE_QUEST] == QUEST_BOMBERS_NOTEBOOK)) {
+ if (pauseCtx->namedItem != PAUSE_ITEM_NONE) {
+ // The cursor is on the bombers notebook
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -58;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[20].v.ob[0] = pauseCtx->infoPanelVtx[22].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 0x14;
+
+ pauseCtx->infoPanelVtx[21].v.ob[0] = pauseCtx->infoPanelVtx[23].v.ob[0] =
+ pauseCtx->infoPanelVtx[20].v.ob[0] + 0x60;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = 96 * (1 << 5);
+
+ gSPDisplayList(POLY_OPA_DISP++, gAButtonIconDL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, gPauseToViewNotebookENGTex, G_IM_FMT_IA, 96, 16, 4);
+ }
+ } else if ((pauseCtx->pageIndex == PAUSE_QUEST) && (pauseCtx->cursorSlot[PAUSE_QUEST] >= QUEST_SONG_SONATA) &&
+ (pauseCtx->cursorSlot[PAUSE_QUEST] <= QUEST_SONG_SUN) && (pauseCtx->namedItem != PAUSE_ITEM_NONE)) {
+ // The cursor is on a learned song
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -55;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[20].v.ob[0] = pauseCtx->infoPanelVtx[22].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 20;
+
+ pauseCtx->infoPanelVtx[21].v.ob[0] = pauseCtx->infoPanelVtx[23].v.ob[0] =
+ pauseCtx->infoPanelVtx[20].v.ob[0] + 96;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[21].v.tc[0] = pauseCtx->infoPanelVtx[23].v.tc[0] = 96 * (1 << 5);
+
+ gSPDisplayList(POLY_OPA_DISP++, gAButtonIconDL);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, gPauseToPlayMelodyENGTex, G_IM_FMT_IA, 96, 16, 4);
+ }
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+u8 sUnpausedButtonStatus[5];
+f32 sCursorCirclesX[4];
+f32 sCursorCirclesY[4];
+
+void KaleidoScope_UpdateNamePanel(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ u16 namedItem;
+
+ if ((pauseCtx->namedItem != pauseCtx->cursorItem[pauseCtx->pageIndex]) ||
+ ((pauseCtx->pageIndex == PAUSE_MAP) && (pauseCtx->cursorSpecialPos != 0))) {
+
+ pauseCtx->namedItem = pauseCtx->cursorItem[pauseCtx->pageIndex];
+ namedItem = pauseCtx->namedItem;
+
+ osCreateMesgQueue(&pauseCtx->loadQueue, &pauseCtx->loadMsg, 1);
+
+ if (pauseCtx->namedItem != PAUSE_ITEM_NONE) {
+ if ((pauseCtx->pageIndex == PAUSE_MAP) && !sInDungeonScene) {
+ Kaleido_LoadMapNameStatic(pauseCtx->nameSegment, namedItem);
+ } else {
+ Kaleido_LoadItemNameStatic(pauseCtx->nameSegment, namedItem);
+ }
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else if (pauseCtx->nameColorSet == PAUSE_NAME_COLOR_SET_WHITE) {
+ if (((pauseCtx->pageIndex == PAUSE_QUEST) && (pauseCtx->cursorSlot[PAUSE_QUEST] >= QUEST_SONG_SONATA) &&
+ (pauseCtx->cursorSlot[PAUSE_QUEST] <= QUEST_SONG_SUN) &&
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) ||
+ ((pauseCtx->pageIndex == PAUSE_QUEST) && (pauseCtx->cursorSlot[PAUSE_QUEST] == QUEST_BOMBERS_NOTEBOOK)) ||
+ (pauseCtx->pageIndex == PAUSE_ITEM) || (pauseCtx->pageIndex == PAUSE_MASK)) {
+
+ pauseCtx->nameDisplayTimer++;
+ if (pauseCtx->nameDisplayTimer > 70) {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+}
+
+void KaleidoScope_DrawOwlWarpMapPage(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0,
+ SHADE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 180, 180, 120, 255);
+
+ Matrix_RotateYF(-1.57f, MTXMODE_NEW);
+ Matrix_Translate(0.0f, sPauseMenuVerticalOffset / 100.0f, -93.0f, MTXMODE_APPLY);
+ Matrix_Scale(0.78f, 0.78f, 0.78f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
+
+ POLY_OPA_DISP = KaleidoScope_DrawPageSections(POLY_OPA_DISP, pauseCtx->mapPageVtx, sMapPageBgTextures);
+
+ Matrix_RotateYF(R_PAUSE_WORLD_MAP_YAW / 1000.0f, MTXMODE_NEW);
+
+ if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWL_WARP_3) ||
+ (pauseCtx->state >= PAUSE_STATE_OWL_WARP_6) ||
+ ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) ||
+ (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) {
+ Matrix_Translate(0.0f, (R_PAUSE_WORLD_MAP_Y_OFFSET - 8000) / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f,
+ MTXMODE_APPLY);
+ } else {
+ Matrix_Translate(0.0f, R_PAUSE_WORLD_MAP_Y_OFFSET / 100.0f, R_PAUSE_WORLD_MAP_DEPTH / 100.0f, MTXMODE_APPLY);
+ }
+
+ Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
+ Matrix_RotateXFApply(-pauseCtx->mapPageRoll / 100.0f);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
+
+ KaleidoScope_DrawWorldMap(play);
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void KaleidoScope_DrawOwlWarpInfoPanel(PlayState* play) {
+ static s16 sPauseZRCursorColorTargets[][4] = {
+ { 180, 210, 255, 220 },
+ { 100, 100, 150, 220 },
+ };
+ static s16 sPauseZRCursorColorTimer = 20;
+ static s16 sPauseZRCursorColorIndex = 0;
+ static s16 sPauseZRCursorRed;
+ static s16 sPauseZRCursorGreen;
+ static s16 sPauseZRCursorBlue;
+ static s16 sPauseZRCursorAlpha;
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 stepR;
+ s16 stepG;
+ s16 stepB;
+ s16 stepA;
+ s16 y;
+ s16 i;
+ s16 j;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ stepR =
+ ABS_ALT(sPauseZRCursorRed - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0]) / sPauseZRCursorColorTimer;
+ stepG = ABS_ALT(sPauseZRCursorGreen - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1]) /
+ sPauseZRCursorColorTimer;
+ stepB = ABS_ALT(sPauseZRCursorBlue - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2]) /
+ sPauseZRCursorColorTimer;
+ stepA = ABS_ALT(sPauseZRCursorAlpha - sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3]) /
+ sPauseZRCursorColorTimer;
+
+ if (sPauseZRCursorRed >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0]) {
+ sPauseZRCursorRed -= stepR;
+ } else {
+ sPauseZRCursorRed += stepR;
+ }
+
+ if (sPauseZRCursorGreen >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1]) {
+ sPauseZRCursorGreen -= stepG;
+ } else {
+ sPauseZRCursorGreen += stepG;
+ }
+
+ if (sPauseZRCursorBlue >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2]) {
+ sPauseZRCursorBlue -= stepB;
+ } else {
+ sPauseZRCursorBlue += stepB;
+ }
+
+ if (sPauseZRCursorAlpha >= sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3]) {
+ sPauseZRCursorAlpha -= stepA;
+ } else {
+ sPauseZRCursorAlpha += stepA;
+ }
+
+ sPauseZRCursorColorTimer--;
+ if (sPauseZRCursorColorTimer == 0) {
+ sPauseZRCursorRed = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][0];
+ sPauseZRCursorGreen = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][1];
+ sPauseZRCursorBlue = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][2];
+ sPauseZRCursorAlpha = sPauseZRCursorColorTargets[sPauseZRCursorColorIndex][3];
+ sPauseZRCursorColorTimer = sPauseZRCursorColorTimerInits[0];
+ sPauseZRCursorColorIndex ^= 1;
+ }
+
+ y = pauseCtx->infoPanelOffsetY - 76;
+ for (j = 0, i = 0; i < 7; i++, j += 4) {
+ pauseCtx->infoPanelVtx[j + 0].v.ob[0] = pauseCtx->infoPanelVtx[j + 2].v.ob[0] = -72;
+
+ pauseCtx->infoPanelVtx[j + 1].v.ob[0] = pauseCtx->infoPanelVtx[j + 3].v.ob[0] = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.ob[1] = pauseCtx->infoPanelVtx[j + 1].v.ob[1] = y;
+
+ pauseCtx->infoPanelVtx[j + 2].v.ob[1] = pauseCtx->infoPanelVtx[j + 3].v.ob[1] = y - 24;
+
+ pauseCtx->infoPanelVtx[j + 0].v.ob[2] = pauseCtx->infoPanelVtx[j + 1].v.ob[2] =
+ pauseCtx->infoPanelVtx[j + 2].v.ob[2] = pauseCtx->infoPanelVtx[j + 3].v.ob[2] = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.flag = pauseCtx->infoPanelVtx[j + 1].v.flag =
+ pauseCtx->infoPanelVtx[j + 2].v.flag = pauseCtx->infoPanelVtx[j + 3].v.flag = 0;
+
+ pauseCtx->infoPanelVtx[j + 0].v.tc[0] = pauseCtx->infoPanelVtx[j + 0].v.tc[1] =
+ pauseCtx->infoPanelVtx[j + 1].v.tc[1] = pauseCtx->infoPanelVtx[j + 2].v.tc[0] = 0;
+
+ pauseCtx->infoPanelVtx[j + 1].v.tc[0] = pauseCtx->infoPanelVtx[j + 3].v.tc[0] = 72 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[j + 2].v.tc[1] = pauseCtx->infoPanelVtx[j + 3].v.tc[1] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[j + 0].v.cn[0] = pauseCtx->infoPanelVtx[j + 2].v.cn[0] =
+ pauseCtx->infoPanelVtx[j + 0].v.cn[1] = pauseCtx->infoPanelVtx[j + 2].v.cn[1] =
+ pauseCtx->infoPanelVtx[j + 0].v.cn[2] = pauseCtx->infoPanelVtx[j + 2].v.cn[2] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[0] = pauseCtx->infoPanelVtx[j + 3].v.cn[0] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[1] = pauseCtx->infoPanelVtx[j + 3].v.cn[1] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[2] = pauseCtx->infoPanelVtx[j + 3].v.cn[2] = 200;
+
+ pauseCtx->infoPanelVtx[j + 0].v.cn[3] = pauseCtx->infoPanelVtx[j + 2].v.cn[3] =
+ pauseCtx->infoPanelVtx[j + 1].v.cn[3] = pauseCtx->infoPanelVtx[j + 3].v.cn[3] = pauseCtx->alpha;
+ }
+
+ pauseCtx->infoPanelVtx[4].v.ob[0] = pauseCtx->infoPanelVtx[6].v.ob[0] = pauseCtx->infoPanelVtx[0].v.ob[0] + 72;
+
+ pauseCtx->infoPanelVtx[5].v.ob[0] = pauseCtx->infoPanelVtx[7].v.ob[0] = pauseCtx->infoPanelVtx[4].v.ob[0] + 72;
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) {
+ pauseCtx->infoPanelVtx[8].v.ob[0] = pauseCtx->infoPanelVtx[10].v.ob[0] = sPauseCursorLeftX;
+
+ pauseCtx->infoPanelVtx[9].v.ob[0] = pauseCtx->infoPanelVtx[11].v.ob[0] = pauseCtx->infoPanelVtx[8].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[8].v.ob[1] = pauseCtx->infoPanelVtx[9].v.ob[1] = D_8082B920;
+
+ pauseCtx->infoPanelVtx[10].v.ob[1] = pauseCtx->infoPanelVtx[11].v.ob[1] =
+ pauseCtx->infoPanelVtx[8].v.ob[1] - 32;
+ } else {
+ pauseCtx->infoPanelVtx[8].v.ob[0] = pauseCtx->infoPanelVtx[10].v.ob[0] = sPauseCursorLeftX + 3;
+
+ pauseCtx->infoPanelVtx[9].v.ob[0] = pauseCtx->infoPanelVtx[11].v.ob[0] = pauseCtx->infoPanelVtx[8].v.ob[0] + 18;
+
+ pauseCtx->infoPanelVtx[8].v.ob[1] = pauseCtx->infoPanelVtx[9].v.ob[1] = D_8082B920 - 3;
+
+ pauseCtx->infoPanelVtx[10].v.ob[1] = pauseCtx->infoPanelVtx[11].v.ob[1] =
+ pauseCtx->infoPanelVtx[8].v.ob[1] - 26;
+ }
+
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT) && (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE)) {
+ pauseCtx->infoPanelVtx[12].v.ob[0] = pauseCtx->infoPanelVtx[14].v.ob[0] = sPauseCursorRightX;
+
+ pauseCtx->infoPanelVtx[13].v.ob[0] = pauseCtx->infoPanelVtx[15].v.ob[0] =
+ pauseCtx->infoPanelVtx[12].v.ob[0] + 24;
+
+ pauseCtx->infoPanelVtx[12].v.ob[1] = pauseCtx->infoPanelVtx[13].v.ob[1] = D_8082B920;
+
+ pauseCtx->infoPanelVtx[14].v.ob[1] = pauseCtx->infoPanelVtx[15].v.ob[1] =
+ pauseCtx->infoPanelVtx[12].v.ob[1] - 32;
+ } else {
+ pauseCtx->infoPanelVtx[12].v.ob[0] = pauseCtx->infoPanelVtx[14].v.ob[0] = sPauseCursorRightX + 3;
+
+ pauseCtx->infoPanelVtx[13].v.ob[0] = pauseCtx->infoPanelVtx[15].v.ob[0] =
+ pauseCtx->infoPanelVtx[12].v.ob[0] + 18;
+
+ pauseCtx->infoPanelVtx[12].v.ob[1] = pauseCtx->infoPanelVtx[13].v.ob[1] = D_8082B920 - 3;
+
+ pauseCtx->infoPanelVtx[14].v.ob[1] = pauseCtx->infoPanelVtx[15].v.ob[1] =
+ pauseCtx->infoPanelVtx[12].v.ob[1] - 26;
+ }
+
+ pauseCtx->infoPanelVtx[9].v.tc[0] = pauseCtx->infoPanelVtx[11].v.tc[0] = pauseCtx->infoPanelVtx[13].v.tc[0] =
+ pauseCtx->infoPanelVtx[15].v.tc[0] = 24 * (1 << 5);
+
+ pauseCtx->infoPanelVtx[10].v.tc[1] = pauseCtx->infoPanelVtx[11].v.tc[1] = pauseCtx->infoPanelVtx[14].v.tc[1] =
+ pauseCtx->infoPanelVtx[15].v.tc[1] = 32 * (1 << 5);
+
+ gDPSetCombineMode(POLY_OPA_DISP++, G_CC_MODULATEIA_PRIM, G_CC_MODULATEIA_PRIM);
+
+ Matrix_Translate(0.0f, 0.0f, -144.0f, MTXMODE_NEW);
+ Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 150, 140, 90, 255);
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->infoPanelVtx[0], 16, 0);
+
+ gSPDisplayList(POLY_OPA_DISP++, gItemNamePanelDL);
+
+ if (pauseCtx->cursorSpecialPos != 0) {
+ j = (pauseCtx->cursorSpecialPos * 4) - 32;
+ pauseCtx->cursorVtx[0].v.ob[0] = pauseCtx->infoPanelVtx[j].v.ob[0];
+ pauseCtx->cursorVtx[0].v.ob[1] = pauseCtx->infoPanelVtx[j].v.ob[1];
+ }
+
+ y = pauseCtx->infoPanelOffsetY - 80;
+ pauseCtx->infoPanelVtx[16].v.ob[1] = pauseCtx->infoPanelVtx[17].v.ob[1] = y;
+
+ pauseCtx->infoPanelVtx[18].v.ob[1] = pauseCtx->infoPanelVtx[19].v.ob[1] = pauseCtx->infoPanelVtx[16].v.ob[1] - 16;
+
+ pauseCtx->infoPanelVtx[18].v.tc[1] = pauseCtx->infoPanelVtx[19].v.tc[1] = 16 * (1 << 5);
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0, PRIMITIVE,
+ ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetEnvColor(POLY_OPA_DISP++, 20, 30, 40, 0);
+
+ if ((pauseCtx->state == PAUSE_STATE_OWL_WARP_SELECT) && (pauseCtx->namedItem != PAUSE_ITEM_NONE) &&
+ (pauseCtx->nameDisplayTimer < 40)) {
+ pauseCtx->infoPanelVtx[16].v.ob[0] = pauseCtx->infoPanelVtx[18].v.ob[0] = -63;
+
+ pauseCtx->infoPanelVtx[17].v.ob[0] = pauseCtx->infoPanelVtx[19].v.ob[0] =
+ pauseCtx->infoPanelVtx[16].v.ob[0] + 128;
+
+ pauseCtx->infoPanelVtx[17].v.tc[0] = pauseCtx->infoPanelVtx[19].v.tc[0] = 128 * (1 << 5);
+
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->infoPanelVtx[16], 4, 0);
+
+ if (pauseCtx->nameColorSet == PAUSE_NAME_COLOR_SET_GREY) {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 70, 70, 70, 255);
+ } else {
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, 255, 255, 255, 255);
+ }
+
+ POLY_OPA_DISP = Gfx_DrawTexQuad4b(POLY_OPA_DISP, pauseCtx->nameSegment, G_IM_FMT_IA, 128, 16, 0);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void KaleidoScope_UpdateOwlWarpNamePanel(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ u16 texIndex;
+
+ if ((pauseCtx->namedItem != pauseCtx->cursorItem[pauseCtx->pageIndex]) ||
+ ((pauseCtx->pageIndex == PAUSE_MAP) && (pauseCtx->cursorSpecialPos != 0))) {
+
+ pauseCtx->namedItem = pauseCtx->cursorItem[pauseCtx->pageIndex];
+ texIndex = pauseCtx->namedItem;
+
+ osCreateMesgQueue(&pauseCtx->loadQueue, &pauseCtx->loadMsg, 1);
+
+ if (pauseCtx->namedItem != PAUSE_ITEM_NONE) {
+ if ((pauseCtx->pageIndex == PAUSE_MAP) && !sInDungeonScene) {
+ Kaleido_LoadMapNameStatic(pauseCtx->nameSegment, texIndex);
+ } else {
+ Kaleido_LoadItemNameStatic(pauseCtx->nameSegment, texIndex);
+ }
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else if (pauseCtx->nameColorSet == PAUSE_NAME_COLOR_SET_WHITE) {
+ if (((pauseCtx->pageIndex == PAUSE_QUEST) && (pauseCtx->cursorSlot[PAUSE_QUEST] >= QUEST_SONG_SONATA) &&
+ (pauseCtx->cursorSlot[PAUSE_QUEST] <= QUEST_SONG_SUN) &&
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)) ||
+ (pauseCtx->pageIndex == PAUSE_ITEM)) {
+
+ pauseCtx->nameDisplayTimer++;
+ if (pauseCtx->nameDisplayTimer > 70) {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+ } else {
+ pauseCtx->nameDisplayTimer = 0;
+ }
+}
+
+void KaleidoScope_UpdateSwitchPage(PlayState* play, Input* input) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+
+ //! FAKE
+ if (1) {
+ pauseCtx->eye.x += sPageSwitchEyeDx[pauseCtx->nextPageMode] * 2.0f;
+ pauseCtx->eye.z += sPageSwitchEyeDz[pauseCtx->nextPageMode] * 2.0f;
+
+ if (pauseCtx->switchPageTimer < 32) {
+ sPauseCursorLeftX -= TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX -= TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ } else {
+ sPauseCursorLeftX += TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX += TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ }
+
+ pauseCtx->switchPageTimer += 8;
+
+ if (pauseCtx->switchPageTimer == 64) {
+ pauseCtx->switchPageTimer = 0;
+ pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode];
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+
+ KaleidoScope_HandlePageToggles(play, input);
+ }
+ }
+}
+
+void KaleidoScope_SetView(PauseContext* pauseCtx, f32 eyeX, f32 eyeY, f32 eyeZ) {
+ Vec3f eye;
+ Vec3f at;
+ Vec3f up;
+
+ eye.x = eyeX;
+ eye.y = eyeY;
+ eye.z = eyeZ;
+ at.x = at.y = at.z = 0.0f;
+ up.x = up.z = 0.0f;
+ up.y = 1.0f;
+
+ View_LookAt(&pauseCtx->view, &eye, &at, &up);
+ View_Apply(&pauseCtx->view,
+ VIEW_ALL | VIEW_FORCE_VIEWING | VIEW_FORCE_VIEWPORT | VIEW_FORCE_PROJECTION_PERSPECTIVE);
+}
+
+// CLAMP_MIN(*, 1) because C arrays can't have 0 length
+s16 sVtxPageMaskQuadsX[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 };
+s16 sVtxPageItemQuadsX[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 };
+s16 sVtxPageMapDungeonQuadsX[VTX_PAGE_MAP_DUNGEON_QUADS] = {
+ -21, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE
+ -104, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY
+ -76, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS
+ -48, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP
+ -104, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE
+ -40 // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED
+};
+s16 sVtxPageQuestQuadsX[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 };
+s16 sVtxPageMapWorldQuadsX[VTX_PAGE_MAP_WORLD_QUADS] = {
+ -41, // mapPageVtx[60] world map clouds Clock Town 1
+ 9, // mapPageVtx[64] world map clouds Clock Town 2
+ 43, // mapPageVtx[68] world map clouds Woodfall 1
+ -21, // mapPageVtx[72] world map clouds Woodfall 2
+ -37, // mapPageVtx[76] world map clouds Woodfall 3
+ 43, // mapPageVtx[80] world map clouds Snowhead 1
+ -69, // mapPageVtx[84] world map clouds Snowhead 2
+ -69, // mapPageVtx[88] world map clouds Snowhead 3
+ -32, // mapPageVtx[92] world map clouds Romani Ranch
+ -109, // mapPageVtx[96] world map clouds Great Bay 1
+ -45, // mapPageVtx[100] world map clouds Great Bay 2
+ -109, // mapPageVtx[104] world map clouds Great Bay 3
+ -45, // mapPageVtx[108] world map clouds Great Bay 4
+ 59, // mapPageVtx[112] world map clouds Stone Tower 1
+ -5, // mapPageVtx[116] world map clouds Stone Tower 2
+ -70, // mapPageVtx[120] world map region Great Bay
+ -52, // mapPageVtx[124] world map region Zora Hall
+ -11, // mapPageVtx[128] world map region Romani Ranch
+ -2, // mapPageVtx[132] world map region Deku Palace
+ 8, // mapPageVtx[136] world map region Woodfall
+ 2, // mapPageVtx[140] world map region Clock Town
+ 1, // mapPageVtx[144] world map region Snowhead
+ 43, // mapPageVtx[148] world map region Ikana Graveyard
+ 52, // mapPageVtx[152] world map region Ikana Canyon
+ 54, // mapPageVtx[156] world map region Goron Village
+ 62, // mapPageVtx[160] world map region Stone Tower
+ -80, // mapPageVtx[164] world map owl warp Great Bay Coast
+ -64, // mapPageVtx[168] world map owl warp Zora Cape
+ -9, // mapPageVtx[172] world map owl warp Snowhead
+ -3, // mapPageVtx[176] world map owl warp Mountain Village
+ -7, // mapPageVtx[180] world map owl warp Clock Town
+ -16, // mapPageVtx[184] world map owl warp Milk Road
+ -1, // mapPageVtx[188] world map owl warp Woodfall
+ 23, // mapPageVtx[192] world map owl warp Southern Swamp
+ 44, // mapPageVtx[196] world map owl warp Ikana Canyon
+ 54, // mapPageVtx[200] world map owl warp Stone Tower
+};
+s16 sVtxPagePromptQuadsX[VTX_PAGE_SAVE_QUADS] = {
+ -76, // promptPageVtx[60] QUAD_PROMPT_MESSAGE
+ -58, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT
+ 10, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT
+ -58, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES
+ 10, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO
+};
+
+// CLAMP_MIN(*, 1) because C arrays can't have 0 length
+s16 sVtxPageMaskQuadsWidth[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 };
+s16 sVtxPageItemQuadsWidth[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 };
+s16 sVtxPageMapDungeonQuadsWidth[VTX_PAGE_MAP_DUNGEON_QUADS] = {
+ 128, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE
+ 24, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY
+ 24, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS
+ 24, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP
+ 32, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE
+ 24, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED
+};
+s16 sVtxPageQuestQuadsWidth[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 };
+s16 sVtxPagePromptQuadsWidth[VTX_PAGE_SAVE_QUADS] = {
+ 152, // promptPageVtx[60] QUAD_PROMPT_MESSAGE
+ 48, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT
+ 48, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT
+ 48, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES
+ 48, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO
+};
+
+// CLAMP_MIN(*, 1) because C arrays can't have 0 length
+s16 sVtxPageMaskQuadsY[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 };
+s16 sVtxPageItemQuadsY[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 };
+
+s16 sVtxPageMapDungeonQuadsY[VTX_PAGE_MAP_DUNGEON_QUADS] = {
+ 54, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE
+ -42, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY
+ -42, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS
+ -42, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP
+ -24, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE
+ 50, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED
+};
+s16 sVtxPageQuestQuadsY[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 };
+s16 sVtxPageMapWorldQuadsY[VTX_PAGE_MAP_WORLD_QUADS] = {
+ 11, // mapPageVtx[60] world map clouds Clock Town 1
+ 22, // mapPageVtx[64] world map clouds Clock Town 2
+ -16, // mapPageVtx[68] world map clouds Woodfall 1
+ -16, // mapPageVtx[72] world map clouds Woodfall 2
+ -16, // mapPageVtx[76] world map clouds Woodfall 3
+ 59, // mapPageVtx[80] world map clouds Snowhead 1
+ 24, // mapPageVtx[84] world map clouds Snowhead 2
+ 59, // mapPageVtx[88] world map clouds Snowhead 3
+ -11, // mapPageVtx[92] world map clouds Romani Ranch
+ -5, // mapPageVtx[96] world map clouds Great Bay 1
+ -5, // mapPageVtx[100] world map clouds Great Bay 2
+ 59, // mapPageVtx[104] world map clouds Great Bay 3
+ 59, // mapPageVtx[108] world map clouds Great Bay 4
+ 39, // mapPageVtx[112] world map clouds Stone Tower 1
+ 31, // mapPageVtx[116] world map clouds Stone Tower 2
+ -10, // mapPageVtx[120] world map region Great Bay
+ -36, // mapPageVtx[124] world map region Zora Hall
+ -19, // mapPageVtx[128] world map region Romani Ranch
+ -53, // mapPageVtx[132] world map region Deku Palace
+ -27, // mapPageVtx[136] world map region Woodfall
+ -2, // mapPageVtx[140] world map region Clock Town
+ 41, // mapPageVtx[144] world map region Snowhead
+ 11, // mapPageVtx[148] world map region Ikana Graveyard
+ -3, // mapPageVtx[152] world map region Ikana Canyon
+ 45, // mapPageVtx[156] world map region Goron Village
+ 18, // mapPageVtx[160] world map region Stone Tower
+ -8, // mapPageVtx[164] world map owl warp Great Bay Coast
+ -38, // mapPageVtx[168] world map owl warp Zora Cape
+ 39, // mapPageVtx[172] world map owl warp Snowhead
+ 26, // mapPageVtx[176] world map owl warp Mountain Village
+ 1, // mapPageVtx[180] world map owl warp Clock Town
+ -7, // mapPageVtx[184] world map owl warp Milk Road
+ -28, // mapPageVtx[188] world map owl warp Woodfall
+ -27, // mapPageVtx[192] world map owl warp Southern Swamp
+ -1, // mapPageVtx[196] world map owl warp Ikana Canyon
+ 24, // mapPageVtx[200] world map owl warp Stone Tower
+};
+s16 sVtxPagePromptQuadsY[VTX_PAGE_SAVE_QUADS] = {
+ 36, // promptPageVtx[60] QUAD_PROMPT_MESSAGE
+ 10, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT
+ 10, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT
+ -6, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES
+ -6, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO
+};
+
+// CLAMP_MIN(*, 1) because C arrays can't have 0 length
+s16 sVtxPageMaskQuadsHeight[CLAMP_MIN(VTX_PAGE_MASK_QUADS, 1)] = { 0 };
+s16 sVtxPageItemQuadsHeight[CLAMP_MIN(VTX_PAGE_ITEM_QUADS, 1)] = { 0 };
+s16 sVtxPageMapDungeonQuadsHeight[] = {
+ 16, // mapPageVtx[60] QUAD_MAP_DUNGEON_TITLE
+ 24, // mapPageVtx[64] QUAD_MAP_DUNGEON_BOSS_KEY
+ 24, // mapPageVtx[68] QUAD_MAP_DUNGEON_COMPASS
+ 24, // mapPageVtx[72] QUAD_MAP_DUNGEON_MAP
+ 24, // mapPageVtx[76] QUAD_MAP_DUNGEON_STRAY_FAIRY_GLOWING_CIRCLE
+ 24, // mapPageVtx[80] QUAD_MAP_DUNGEON_UNUSED
+};
+s16 sVtxPageQuestQuadsHeight[CLAMP_MIN(VTX_PAGE_QUEST_QUADS, 1)] = { 0 };
+s16 sVtxPagePromptQuadsHeight[VTX_PAGE_SAVE_QUADS] = {
+ 16, // promptPageVtx[60] QUAD_PROMPT_MESSAGE
+ 48, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT
+ 48, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT
+ 16, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES
+ 16, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO
+};
+
+s16* sVtxPageQuadsX[VTX_PAGE_MAX] = {
+ sVtxPageMaskQuadsX, // VTX_PAGE_MASK
+ sVtxPageItemQuadsX, // VTX_PAGE_ITEM
+ sVtxPageMapDungeonQuadsX, // VTX_PAGE_MAP_DUNGEON
+ sVtxPageQuestQuadsX, // VTX_PAGE_QUEST
+ sVtxPageMapWorldQuadsX, // VTX_PAGE_MAP_WORLD
+ sVtxPagePromptQuadsX, // VTX_PAGE_PROMPT
+};
+
+s16* sVtxPageQuadsWidth[VTX_PAGE_MAX] = {
+ sVtxPageMaskQuadsWidth, // VTX_PAGE_MASK
+ sVtxPageItemQuadsWidth, // VTX_PAGE_ITEM
+ sVtxPageMapDungeonQuadsWidth, // VTX_PAGE_MAP_DUNGEON
+ sVtxPageQuestQuadsWidth, // VTX_PAGE_QUEST
+ gVtxPageMapWorldQuadsWidth, // VTX_PAGE_MAP_WORLD
+ sVtxPagePromptQuadsWidth, // VTX_PAGE_PROMPT
+};
+
+s16* sVtxPageQuadsY[VTX_PAGE_MAX] = {
+ sVtxPageMaskQuadsY, // VTX_PAGE_MASK
+ sVtxPageItemQuadsY, // VTX_PAGE_ITEM
+ sVtxPageMapDungeonQuadsY, // VTX_PAGE_MAP_DUNGEON
+ sVtxPageQuestQuadsY, // VTX_PAGE_QUEST
+ sVtxPageMapWorldQuadsY, // VTX_PAGE_MAP_WORLD
+ sVtxPagePromptQuadsY, // VTX_PAGE_PROMPT
+};
+
+s16* sVtxPageQuadsHeight[VTX_PAGE_MAX] = {
+ sVtxPageMaskQuadsHeight, // VTX_PAGE_MASK
+ sVtxPageItemQuadsHeight, // VTX_PAGE_ITEM
+ sVtxPageMapDungeonQuadsHeight, // VTX_PAGE_MAP_DUNGEON
+ sVtxPageQuestQuadsHeight, // VTX_PAGE_QUEST
+ gVtxPageMapWorldQuadsHeight, // VTX_PAGE_MAP_WORLD
+ sVtxPagePromptQuadsHeight, // VTX_PAGE_PROMPT
+};
+
+s16 sVtxPageGameOverSaveQuadsY[VTX_PAGE_SAVE_QUADS] = {
+ 14, // promptPageVtx[60] QUAD_PROMPT_MESSAGE
+ -2, // promptPageVtx[64] QUAD_PROMPT_CURSOR_LEFT
+ -2, // promptPageVtx[68] QUAD_PROMPT_CURSOR_RIGHT
+ -18, // promptPageVtx[72] QUAD_PROMPT_CHOICE_YES
+ -18, // promptPageVtx[76] QUAD_PROMPT_CHOICE_NO
+};
+
+s16 KaleidoScope_SetPageVertices(PlayState* play, Vtx* vtx, s16 vtxPage, s16 numQuads) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ GameOverContext* gameOverCtx = &play->gameOverCtx;
+ s16* quadsX;
+ s16* quadsWidth;
+ s16* quadsY;
+ s16* quadsHeight;
+ s16 pageBgQuadX;
+ s16 pageBgQuadY;
+ s16 i;
+ s16 j;
+ s16 k;
+
+ // Vertices for KaleidoScope_DrawPageSections
+
+ pageBgQuadX = 0 - (PAGE_BG_COLS * PAGE_BG_QUAD_WIDTH) / 2 - PAGE_BG_QUAD_WIDTH;
+
+ // For each column
+ for (k = 0, i = 0; i < 3; i++) {
+ pageBgQuadX += PAGE_BG_QUAD_WIDTH;
+
+ // For each row
+ for (pageBgQuadY = (PAGE_BG_ROWS * PAGE_BG_QUAD_HEIGHT) / 2, j = 0; j < 5; j++, k += 4, pageBgQuadY -= 32) {
+ vtx[k + 0].v.ob[0] = vtx[k + 2].v.ob[0] = pageBgQuadX;
+ vtx[k + 1].v.ob[0] = vtx[k + 3].v.ob[0] = vtx[k + 0].v.ob[0] + PAGE_BG_QUAD_WIDTH;
+
+ vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = pageBgQuadY + pauseCtx->offsetY;
+ vtx[k + 2].v.ob[1] = vtx[k + 3].v.ob[1] = vtx[k + 0].v.ob[1] - PAGE_BG_QUAD_HEIGHT;
+
+ vtx[k + 0].v.ob[2] = vtx[k + 1].v.ob[2] = vtx[k + 2].v.ob[2] = vtx[k + 3].v.ob[2] = 0;
+
+ vtx[k + 0].v.flag = vtx[k + 1].v.flag = vtx[k + 2].v.flag = vtx[k + 3].v.flag = 0;
+
+ vtx[k + 0].v.tc[0] = vtx[k + 0].v.tc[1] = 0;
+ vtx[k + 1].v.tc[1] = vtx[k + 2].v.tc[0] = 0;
+ vtx[k + 1].v.tc[0] = vtx[k + 3].v.tc[0] = PAGE_BG_QUAD_TEX_WIDTH * (1 << 5);
+ vtx[k + 2].v.tc[1] = vtx[k + 3].v.tc[1] = PAGE_BG_QUAD_TEX_HEIGHT * (1 << 5);
+
+ vtx[k + 0].v.cn[0] = vtx[k + 2].v.cn[0] = vtx[k + 0].v.cn[1] = vtx[k + 2].v.cn[1] = vtx[k + 0].v.cn[2] =
+ vtx[k + 2].v.cn[2] = 0;
+
+ vtx[k + 1].v.cn[0] = vtx[k + 3].v.cn[0] = vtx[k + 1].v.cn[1] = vtx[k + 3].v.cn[1] = vtx[k + 1].v.cn[2] =
+ vtx[k + 3].v.cn[2] = 0;
+
+ vtx[k + 0].v.cn[3] = vtx[k + 2].v.cn[3] = vtx[k + 1].v.cn[3] = vtx[k + 3].v.cn[3] = pauseCtx->alpha;
+ }
+ }
+
+ if (numQuads != 0) {
+ quadsX = sVtxPageQuadsX[vtxPage];
+ quadsWidth = sVtxPageQuadsWidth[vtxPage];
+ quadsY = sVtxPageQuadsY[vtxPage];
+ quadsHeight = sVtxPageQuadsHeight[vtxPage];
+
+ for (i = 0; i < numQuads; i++, k += 4) {
+ vtx[k + 2].v.ob[0] = vtx[k + 0].v.ob[0] = quadsX[i];
+
+ vtx[k + 1].v.ob[0] = vtx[k + 3].v.ob[0] = vtx[k + 0].v.ob[0] + quadsWidth[i];
+
+ if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
+ vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = quadsY[i] + pauseCtx->offsetY;
+ } else if (gameOverCtx->state == GAMEOVER_INACTIVE) {
+ vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = quadsY[i] + pauseCtx->offsetY;
+ } else {
+ vtx[k + 0].v.ob[1] = vtx[k + 1].v.ob[1] = sVtxPageGameOverSaveQuadsY[i] + pauseCtx->offsetY;
+ }
+
+ vtx[k + 2].v.ob[1] = vtx[k + 3].v.ob[1] = vtx[k + 0].v.ob[1] - quadsHeight[i];
+
+ vtx[k + 0].v.ob[2] = vtx[k + 1].v.ob[2] = vtx[k + 2].v.ob[2] = vtx[k + 3].v.ob[2] = 0;
+
+ vtx[k + 0].v.flag = vtx[k + 1].v.flag = vtx[k + 2].v.flag = vtx[k + 3].v.flag = 0;
+
+ vtx[k + 0].v.tc[0] = vtx[k + 0].v.tc[1] = vtx[k + 1].v.tc[1] = vtx[k + 2].v.tc[0] = 0;
+ vtx[k + 1].v.tc[0] = vtx[k + 3].v.tc[0] = quadsWidth[i] << 5;
+ vtx[k + 2].v.tc[1] = vtx[k + 3].v.tc[1] = quadsHeight[i] << 5;
+
+ vtx[k + 0].v.cn[0] = vtx[k + 2].v.cn[0] = vtx[k + 0].v.cn[1] = vtx[k + 2].v.cn[1] = vtx[k + 0].v.cn[2] =
+ vtx[k + 2].v.cn[2] = 255;
+
+ vtx[k + 1].v.cn[0] = vtx[k + 3].v.cn[0] = vtx[k + 1].v.cn[1] = vtx[k + 3].v.cn[1] = vtx[k + 1].v.cn[2] =
+ vtx[k + 3].v.cn[2] = 255;
+
+ vtx[k + 0].v.cn[3] = vtx[k + 2].v.cn[3] = vtx[k + 1].v.cn[3] = vtx[k + 3].v.cn[3] = pauseCtx->alpha;
+ }
+ }
+ return k;
+}
+
+s16 sQuestVtxRectLeft[] = {
+ 45, // QUEST_REMAINS_ODOLWA
+ 78, // QUEST_REMAINS_GOHT
+ 10, // QUEST_REMAINS_GYORG
+ 45, // QUEST_REMAINS_TWINMOLD
+ 80, // QUEST_SHIELD
+ 11, // QUEST_SWORD
+ -109, // QUEST_SONG_SONATA
+ -87, // QUEST_SONG_LULLABY
+ -65, // QUEST_SONG_BOSSA_NOVA
+ -41, // QUEST_SONG_ELEGY
+ -19, // QUEST_SONG_OATH
+ -18, // QUEST_SONG_SARIA
+ -109, // QUEST_SONG_TIME
+ -87, // QUEST_SONG_HEALING
+ -65, // QUEST_SONG_EPONA
+ -41, // QUEST_SONG_SOARING
+ -19, // QUEST_SONG_STORMS
+ -18, // QUEST_SONG_SUN
+ -103, // QUEST_BOMBERS_NOTEBOOK
+ 7, // QUEST_QUIVER
+ 82, // QUEST_BOMB_BAG
+ -110, // QUEST_SKULL_TOKEN (unused)
+ -54, // QUEST_HEART_PIECE
+ -98, // ocarina song button index 0
+ -86, // ocarina song button index 1
+ -74, // ocarina song button index 2
+ -62, // ocarina song button index 3
+ -50, // ocarina song button index 4
+ -38, // ocarina song button index 5
+ -26, // ocarina song button index 6
+ -14, // ocarina song button index 7
+ -98, // ocarina input button index 0
+ -86, // ocarina input button index 1
+ -74, // ocarina input button index 2
+ -62, // ocarina input button index 3
+ -50, // ocarina input button index 4
+ -38, // ocarina input button index 5
+ -26, // ocarina input button index 6
+ -14, // ocarina input button index 7
+};
+
+s16 sQuestVtxRectTop[] = {
+ 62, // QUEST_REMAINS_ODOLWA
+ 42, // QUEST_REMAINS_GOHT
+ 42, // QUEST_REMAINS_GYORG
+ 20, // QUEST_REMAINS_TWINMOLD
+ -9, // QUEST_SHIELD
+ -9, // QUEST_SWORD
+ -20, // QUEST_SONG_SONATA
+ -20, // QUEST_SONG_LULLABY
+ -20, // QUEST_SONG_BOSSA_NOVA
+ -20, // QUEST_SONG_ELEGY
+ -20, // QUEST_SONG_OATH
+ -20, // QUEST_SONG_SARIA
+ 2, // QUEST_SONG_TIME
+ 2, // QUEST_SONG_HEALING
+ 2, // QUEST_SONG_EPONA
+ 2, // QUEST_SONG_SOARING
+ 2, // QUEST_SONG_STORMS
+ 2, // QUEST_SONG_SUN
+ 54, // QUEST_BOMBERS_NOTEBOOK
+ -44, // QUEST_QUIVER
+ -44, // QUEST_BOMB_BAG
+ 34, // QUEST_SKULL_TOKEN (unused)
+ 58, // QUEST_HEART_PIECE
+ -52, // ocarina song button index 0
+ -52, // ocarina song button index 1
+ -52, // ocarina song button index 2
+ -52, // ocarina song button index 3
+ -52, // ocarina song button index 4
+ -52, // ocarina song button index 5
+ -52, // ocarina song button index 6
+ -52, // ocarina song button index 7
+ -52, // ocarina input button index 0
+ -52, // ocarina input button index 1
+ -52, // ocarina input button index 2
+ -52, // ocarina input button index 3
+ -52, // ocarina input button index 4
+ -52, // ocarina input button index 5
+ -52, // ocarina input button index 6
+ -52, // ocarina input button index 7
+};
+
+s16 sQuestVtxWidths[] = {
+ 32, // QUEST_REMAINS_ODOLWA
+ 32, // QUEST_REMAINS_GOHT
+ 32, // QUEST_REMAINS_GYORG
+ 32, // QUEST_REMAINS_TWINMOLD
+ 32, // QUEST_SHIELD
+ 32, // QUEST_SWORD
+ 16, // QUEST_SONG_SONATA
+ 16, // QUEST_SONG_LULLABY
+ 16, // QUEST_SONG_BOSSA_NOVA
+ 16, // QUEST_SONG_ELEGY
+ 16, // QUEST_SONG_OATH
+ 16, // QUEST_SONG_SARIA
+ 16, // QUEST_SONG_TIME
+ 16, // QUEST_SONG_HEALING
+ 16, // QUEST_SONG_EPONA
+ 16, // QUEST_SONG_SOARING
+ 16, // QUEST_SONG_STORMS
+ 16, // QUEST_SONG_SUN
+ 32, // QUEST_BOMBERS_NOTEBOOK
+ 32, // QUEST_QUIVER
+ 32, // QUEST_BOMB_BAG
+ 24, // QUEST_SKULL_TOKEN (unused)
+ 48, // QUEST_HEART_PIECE
+ 16, // ocarina song button index 0
+ 16, // ocarina song button index 1
+ 16, // ocarina song button index 2
+ 16, // ocarina song button index 3
+ 16, // ocarina song button index 4
+ 16, // ocarina song button index 5
+ 16, // ocarina song button index 6
+ 16, // ocarina song button index 7
+ 16, // ocarina input button index 0
+ 16, // ocarina input button index 1
+ 16, // ocarina input button index 2
+ 16, // ocarina input button index 3
+ 16, // ocarina input button index 4
+ 16, // ocarina input button index 5
+ 16, // ocarina input button index 6
+ 16, // ocarina input button index 7
+};
+
+s16 sQuestVtxHeights[] = {
+ 32, // QUEST_REMAINS_ODOLWA
+ 32, // QUEST_REMAINS_GOHT
+ 32, // QUEST_REMAINS_GYORG
+ 32, // QUEST_REMAINS_TWINMOLD
+ 32, // QUEST_SHIELD
+ 32, // QUEST_SWORD
+ 24, // QUEST_SONG_SONATA
+ 24, // QUEST_SONG_LULLABY
+ 24, // QUEST_SONG_BOSSA_NOVA
+ 24, // QUEST_SONG_ELEGY
+ 24, // QUEST_SONG_OATH
+ 24, // QUEST_SONG_SARIA
+ 24, // QUEST_SONG_TIME
+ 24, // QUEST_SONG_HEALING
+ 24, // QUEST_SONG_EPONA
+ 24, // QUEST_SONG_SOARING
+ 24, // QUEST_SONG_STORMS
+ 24, // QUEST_SONG_SUN
+ 32, // QUEST_BOMBERS_NOTEBOOK
+ 32, // QUEST_QUIVER
+ 32, // QUEST_BOMB_BAG
+ 24, // QUEST_SKULL_TOKEN (unused)
+ 48, // QUEST_HEART_PIECE
+ 16, // ocarina song button index 0
+ 16, // ocarina song button index 1
+ 16, // ocarina song button index 2
+ 16, // ocarina song button index 3
+ 16, // ocarina song button index 4
+ 16, // ocarina song button index 5
+ 16, // ocarina song button index 6
+ 16, // ocarina song button index 7
+ 16, // ocarina input button index 0
+ 16, // ocarina input button index 1
+ 16, // ocarina input button index 2
+ 16, // ocarina input button index 3
+ 16, // ocarina input button index 4
+ 16, // ocarina input button index 5
+ 16, // ocarina input button index 6
+ 16, // ocarina input button index 7
+};
+
+void KaleidoScope_SetVertices(PlayState* play, GraphicsContext* gfxCtx) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 i;
+ s16 j;
+ s16 k;
+ s16 vtx_x;
+ s16 vtx_y;
+
+ pauseCtx->offsetY = 0;
+
+ if ((pauseCtx->state == PAUSE_STATE_OPENING_3) || (pauseCtx->state == PAUSE_STATE_OWL_WARP_3) ||
+ (pauseCtx->state >= PAUSE_STATE_OWL_WARP_6) ||
+ ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) && ((pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_3) ||
+ (pauseCtx->savePromptState == PAUSE_SAVEPROMPT_STATE_7)))) {
+ pauseCtx->offsetY = 80;
+ }
+
+ if (pauseCtx->pageIndex != PAUSE_QUEST) {
+ pauseCtx->itemPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_ITEM_QUADS) * 4) * sizeof(Vtx));
+ KaleidoScope_SetPageVertices(play, pauseCtx->itemPageVtx, VTX_PAGE_ITEM, VTX_PAGE_ITEM_QUADS);
+
+ pauseCtx->itemVtx = GRAPH_ALLOC(gfxCtx, (QUAD_ITEM_MAX * 4) * sizeof(Vtx));
+
+ // QUAD_ITEM_GRID_FIRST..QUAD_ITEM_GRID_LAST
+
+ // Loop over grid rows
+ for (k = 0, i = 0, vtx_y = (ITEM_GRID_ROWS * ITEM_GRID_CELL_HEIGHT) / 2 - 6; k < ITEM_GRID_ROWS;
+ k++, vtx_y -= ITEM_GRID_CELL_HEIGHT) {
+ // Loop over grid columns
+ for (vtx_x = 0 - (ITEM_GRID_COLS * ITEM_GRID_CELL_WIDTH) / 2, j = 0; j < ITEM_GRID_COLS;
+ j++, i += 4, vtx_x += ITEM_GRID_CELL_WIDTH) {
+ pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0] = vtx_x + ITEM_GRID_QUAD_MARGIN;
+ pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] =
+ pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_QUAD_WIDTH;
+
+ pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] =
+ vtx_y + pauseCtx->offsetY - ITEM_GRID_QUAD_MARGIN;
+ pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] =
+ pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_QUAD_WIDTH;
+
+ pauseCtx->itemVtx[i + 0].v.ob[2] = pauseCtx->itemVtx[i + 1].v.ob[2] = pauseCtx->itemVtx[i + 2].v.ob[2] =
+ pauseCtx->itemVtx[i + 3].v.ob[2] = 0;
+
+ pauseCtx->itemVtx[i + 0].v.flag = pauseCtx->itemVtx[i + 1].v.flag = pauseCtx->itemVtx[i + 2].v.flag =
+ pauseCtx->itemVtx[i + 3].v.flag = 0;
+
+ pauseCtx->itemVtx[i + 0].v.tc[0] = pauseCtx->itemVtx[i + 0].v.tc[1] = pauseCtx->itemVtx[i + 1].v.tc[1] =
+ pauseCtx->itemVtx[i + 2].v.tc[0] = 0;
+
+ pauseCtx->itemVtx[i + 1].v.tc[0] = pauseCtx->itemVtx[i + 2].v.tc[1] = pauseCtx->itemVtx[i + 3].v.tc[0] =
+ pauseCtx->itemVtx[i + 3].v.tc[1] = ITEM_GRID_QUAD_TEX_SIZE * (1 << 5);
+
+ pauseCtx->itemVtx[i + 0].v.cn[0] = pauseCtx->itemVtx[i + 1].v.cn[0] = pauseCtx->itemVtx[i + 2].v.cn[0] =
+ pauseCtx->itemVtx[i + 3].v.cn[0] = pauseCtx->itemVtx[i + 0].v.cn[1] =
+ pauseCtx->itemVtx[i + 1].v.cn[1] = pauseCtx->itemVtx[i + 2].v.cn[1] =
+ pauseCtx->itemVtx[i + 3].v.cn[1] = pauseCtx->itemVtx[i + 0].v.cn[2] =
+ pauseCtx->itemVtx[i + 1].v.cn[2] = pauseCtx->itemVtx[i + 2].v.cn[2] =
+ pauseCtx->itemVtx[i + 3].v.cn[2] = 255;
+
+ pauseCtx->itemVtx[i + 0].v.cn[3] = pauseCtx->itemVtx[i + 1].v.cn[3] = pauseCtx->itemVtx[i + 2].v.cn[3] =
+ pauseCtx->itemVtx[i + 3].v.cn[3] = 255;
+ }
+ }
+
+ // QUAD_ITEM_GRID_SELECTED_C_LEFT, QUAD_ITEM_GRID_SELECTED_C_DOWN, QUAD_ITEM_GRID_SELECTED_C_RIGHT
+
+ for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++, i += 4) {
+ if (GET_CUR_FORM_BTN_SLOT(j) != ITEM_NONE) {
+ k = GET_CUR_FORM_BTN_SLOT(j) * 4;
+
+ pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0] =
+ pauseCtx->itemVtx[k].v.ob[0] + ITEM_GRID_SELECTED_QUAD_MARGIN;
+
+ pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] =
+ pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_SELECTED_QUAD_WIDTH;
+
+ pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] =
+ pauseCtx->itemVtx[k].v.ob[1] - ITEM_GRID_SELECTED_QUAD_MARGIN;
+
+ pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] =
+ pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_SELECTED_QUAD_WIDTH;
+
+ pauseCtx->itemVtx[i + 0].v.ob[2] = pauseCtx->itemVtx[i + 1].v.ob[2] = pauseCtx->itemVtx[i + 2].v.ob[2] =
+ pauseCtx->itemVtx[i + 3].v.ob[2] = 0;
+
+ pauseCtx->itemVtx[i + 0].v.flag = pauseCtx->itemVtx[i + 1].v.flag = pauseCtx->itemVtx[i + 2].v.flag =
+ pauseCtx->itemVtx[i + 3].v.flag = 0;
+
+ pauseCtx->itemVtx[i + 0].v.tc[0] = pauseCtx->itemVtx[i + 0].v.tc[1] = pauseCtx->itemVtx[i + 1].v.tc[1] =
+ pauseCtx->itemVtx[i + 2].v.tc[0] = 0;
+
+ pauseCtx->itemVtx[i + 1].v.tc[0] = pauseCtx->itemVtx[i + 2].v.tc[1] = pauseCtx->itemVtx[i + 3].v.tc[0] =
+ pauseCtx->itemVtx[i + 3].v.tc[1] = ITEM_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5);
+
+ pauseCtx->itemVtx[i + 0].v.cn[0] = pauseCtx->itemVtx[i + 1].v.cn[0] = pauseCtx->itemVtx[i + 2].v.cn[0] =
+ pauseCtx->itemVtx[i + 3].v.cn[0] = pauseCtx->itemVtx[i + 0].v.cn[1] =
+ pauseCtx->itemVtx[i + 1].v.cn[1] = pauseCtx->itemVtx[i + 2].v.cn[1] =
+ pauseCtx->itemVtx[i + 3].v.cn[1] = pauseCtx->itemVtx[i + 0].v.cn[2] =
+ pauseCtx->itemVtx[i + 1].v.cn[2] = pauseCtx->itemVtx[i + 2].v.cn[2] =
+ pauseCtx->itemVtx[i + 3].v.cn[2] = 255;
+
+ pauseCtx->itemVtx[i + 0].v.cn[3] = pauseCtx->itemVtx[i + 1].v.cn[3] = pauseCtx->itemVtx[i + 2].v.cn[3] =
+ pauseCtx->itemVtx[i + 3].v.cn[3] = pauseCtx->alpha;
+ } else {
+ // No item equipped on the C button, put the quad out of view
+
+ pauseCtx->itemVtx[i + 2].v.ob[0] = -300;
+ pauseCtx->itemVtx[i + 0].v.ob[0] = pauseCtx->itemVtx[i + 2].v.ob[0];
+
+ pauseCtx->itemVtx[i + 1].v.ob[0] = pauseCtx->itemVtx[i + 3].v.ob[0] =
+ pauseCtx->itemVtx[i + 0].v.ob[0] + ITEM_GRID_SELECTED_QUAD_WIDTH;
+
+ pauseCtx->itemVtx[i + 0].v.ob[1] = pauseCtx->itemVtx[i + 1].v.ob[1] = 300;
+ pauseCtx->itemVtx[i + 2].v.ob[1] = pauseCtx->itemVtx[i + 3].v.ob[1] =
+ pauseCtx->itemVtx[i + 0].v.ob[1] - ITEM_GRID_SELECTED_QUAD_HEIGHT;
+ }
+ }
+ }
+
+ if (pauseCtx->pageIndex != PAUSE_MASK) {
+ if (!sInDungeonScene) {
+ pauseCtx->mapPageVtx = GRAPH_ALLOC(
+ gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MAP_WORLD_QUADS + WORLD_MAP_IMAGE_FRAG_NUM) * 4) * sizeof(Vtx));
+ j = KaleidoScope_SetPageVertices(play, pauseCtx->mapPageVtx, VTX_PAGE_MAP_WORLD, VTX_PAGE_MAP_WORLD_QUADS);
+
+ for (i = 0, vtx_y = 59; i < WORLD_MAP_IMAGE_FRAG_NUM; i++, j += 4, vtx_y -= WORLD_MAP_IMAGE_FRAG_HEIGHT) {
+ pauseCtx->mapPageVtx[j + 2].v.ob[0] = 0 - (WORLD_MAP_IMAGE_WIDTH / 2) - 1;
+ pauseCtx->mapPageVtx[j + 0].v.ob[0] = pauseCtx->mapPageVtx[j + 2].v.ob[0];
+
+ pauseCtx->mapPageVtx[j + 1].v.ob[0] = pauseCtx->mapPageVtx[j + 3].v.ob[0] =
+ pauseCtx->mapPageVtx[j + 0].v.ob[0] + WORLD_MAP_IMAGE_WIDTH;
+
+ pauseCtx->mapPageVtx[j + 0].v.ob[1] = pauseCtx->mapPageVtx[j + 1].v.ob[1] = vtx_y + pauseCtx->offsetY;
+
+ pauseCtx->mapPageVtx[j + 2].v.ob[1] = pauseCtx->mapPageVtx[j + 3].v.ob[1] =
+ pauseCtx->mapPageVtx[j + 0].v.ob[1] - WORLD_MAP_IMAGE_FRAG_HEIGHT;
+
+ pauseCtx->mapPageVtx[j + 0].v.ob[2] = pauseCtx->mapPageVtx[j + 1].v.ob[2] =
+ pauseCtx->mapPageVtx[j + 2].v.ob[2] = pauseCtx->mapPageVtx[j + 3].v.ob[2] = 0;
+
+ pauseCtx->mapPageVtx[j + 0].v.flag = pauseCtx->mapPageVtx[j + 1].v.flag =
+ pauseCtx->mapPageVtx[j + 2].v.flag = pauseCtx->mapPageVtx[j + 3].v.flag = 0;
+
+ pauseCtx->mapPageVtx[j + 0].v.tc[0] = pauseCtx->mapPageVtx[j + 0].v.tc[1] =
+ pauseCtx->mapPageVtx[j + 1].v.tc[1] = pauseCtx->mapPageVtx[j + 2].v.tc[0] = 0;
+
+ pauseCtx->mapPageVtx[j + 1].v.tc[0] = pauseCtx->mapPageVtx[j + 3].v.tc[0] =
+ WORLD_MAP_IMAGE_WIDTH * (1 << 5);
+ pauseCtx->mapPageVtx[j + 2].v.tc[1] = pauseCtx->mapPageVtx[j + 3].v.tc[1] =
+ WORLD_MAP_IMAGE_FRAG_HEIGHT * (1 << 5);
+
+ pauseCtx->mapPageVtx[j + 0].v.cn[0] = pauseCtx->mapPageVtx[j + 2].v.cn[0] =
+ pauseCtx->mapPageVtx[j + 0].v.cn[1] = pauseCtx->mapPageVtx[j + 2].v.cn[1] =
+ pauseCtx->mapPageVtx[j + 0].v.cn[2] = pauseCtx->mapPageVtx[j + 2].v.cn[2] =
+ pauseCtx->mapPageVtx[j + 1].v.cn[0] = pauseCtx->mapPageVtx[j + 3].v.cn[0] =
+ pauseCtx->mapPageVtx[j + 1].v.cn[1] = pauseCtx->mapPageVtx[j + 3].v.cn[1] =
+ pauseCtx->mapPageVtx[j + 1].v.cn[2] = pauseCtx->mapPageVtx[j + 3].v.cn[2] =
+ pauseCtx->mapPageVtx[j + 0].v.cn[3] = pauseCtx->mapPageVtx[j + 2].v.cn[3] =
+ pauseCtx->mapPageVtx[j + 1].v.cn[3] = pauseCtx->mapPageVtx[j + 3].v.cn[3] =
+ pauseCtx->alpha;
+ }
+
+ pauseCtx->mapPageVtx[j - 2].v.ob[1] = pauseCtx->mapPageVtx[j - 1].v.ob[1] =
+ pauseCtx->mapPageVtx[j - 4].v.ob[1] - (WORLD_MAP_IMAGE_HEIGHT % WORLD_MAP_IMAGE_FRAG_HEIGHT);
+
+ pauseCtx->mapPageVtx[j - 2].v.tc[1] = pauseCtx->mapPageVtx[j - 1].v.tc[1] =
+ (WORLD_MAP_IMAGE_HEIGHT % WORLD_MAP_IMAGE_FRAG_HEIGHT) * (1 << 5);
+
+ } else {
+ pauseCtx->mapPageVtx =
+ GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MAP_DUNGEON_QUADS) * 4) * sizeof(Vtx));
+ KaleidoScope_SetPageVertices(play, pauseCtx->mapPageVtx, VTX_PAGE_MAP_DUNGEON, VTX_PAGE_MAP_DUNGEON_QUADS);
+ }
+ }
+
+ if (pauseCtx->pageIndex != PAUSE_ITEM) {
+ pauseCtx->questPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_QUEST_QUADS) * 4) * sizeof(Vtx));
+ KaleidoScope_SetPageVertices(play, pauseCtx->questPageVtx, VTX_PAGE_QUEST, VTX_PAGE_QUEST_QUADS);
+
+ pauseCtx->questVtx = GRAPH_ALLOC(gfxCtx, (39 * 4) * sizeof(Vtx));
+
+ for (k = 0, j = 0; j < 39; j++, k += 4) {
+ if (j <= QUEST_SWORD) {
+ pauseCtx->questVtx[k + 0].v.ob[0] = pauseCtx->questVtx[k + 2].v.ob[0] = sQuestVtxRectLeft[j];
+
+ pauseCtx->questVtx[k + 1].v.ob[0] = pauseCtx->questVtx[k + 3].v.ob[0] =
+ pauseCtx->questVtx[k + 0].v.ob[0] + sQuestVtxWidths[j];
+
+ pauseCtx->questVtx[k + 0].v.ob[1] = pauseCtx->questVtx[k + 1].v.ob[1] =
+ sQuestVtxRectTop[j] + pauseCtx->offsetY;
+
+ pauseCtx->questVtx[k + 2].v.ob[1] = pauseCtx->questVtx[k + 3].v.ob[1] =
+ pauseCtx->questVtx[k + 0].v.ob[1] - sQuestVtxHeights[j];
+ } else {
+ pauseCtx->questVtx[k + 0].v.ob[0] = pauseCtx->questVtx[k + 2].v.ob[0] = sQuestVtxRectLeft[j] + 2;
+
+ pauseCtx->questVtx[k + 1].v.ob[0] = pauseCtx->questVtx[k + 3].v.ob[0] =
+ pauseCtx->questVtx[k + 0].v.ob[0] + sQuestVtxWidths[j] - 4;
+
+ pauseCtx->questVtx[k + 0].v.ob[1] = pauseCtx->questVtx[k + 1].v.ob[1] =
+ sQuestVtxRectTop[j] + pauseCtx->offsetY - 2;
+
+ pauseCtx->questVtx[k + 2].v.ob[1] = pauseCtx->questVtx[k + 3].v.ob[1] =
+ pauseCtx->questVtx[k + 0].v.ob[1] - sQuestVtxHeights[j] + 4;
+ }
+
+ pauseCtx->questVtx[k + 0].v.ob[2] = pauseCtx->questVtx[k + 1].v.ob[2] = pauseCtx->questVtx[k + 2].v.ob[2] =
+ pauseCtx->questVtx[k + 3].v.ob[2] = 0;
+
+ pauseCtx->questVtx[k + 0].v.flag = pauseCtx->questVtx[k + 1].v.flag = pauseCtx->questVtx[k + 2].v.flag =
+ pauseCtx->questVtx[k + 3].v.flag = 0;
+
+ pauseCtx->questVtx[k + 0].v.tc[0] = pauseCtx->questVtx[k + 0].v.tc[1] = pauseCtx->questVtx[k + 1].v.tc[1] =
+ pauseCtx->questVtx[k + 2].v.tc[0] = 0;
+
+ pauseCtx->questVtx[k + 1].v.tc[0] = pauseCtx->questVtx[k + 3].v.tc[0] = sQuestVtxWidths[j] << 5;
+ pauseCtx->questVtx[k + 2].v.tc[1] = pauseCtx->questVtx[k + 3].v.tc[1] = sQuestVtxHeights[j] << 5;
+
+ pauseCtx->questVtx[k + 0].v.cn[0] = pauseCtx->questVtx[k + 1].v.cn[0] = pauseCtx->questVtx[k + 2].v.cn[0] =
+ pauseCtx->questVtx[k + 3].v.cn[0] = pauseCtx->questVtx[k + 0].v.cn[1] =
+ pauseCtx->questVtx[k + 1].v.cn[1] = pauseCtx->questVtx[k + 2].v.cn[1] =
+ pauseCtx->questVtx[k + 3].v.cn[1] = pauseCtx->questVtx[k + 0].v.cn[2] =
+ pauseCtx->questVtx[k + 1].v.cn[2] = pauseCtx->questVtx[k + 2].v.cn[2] =
+ pauseCtx->questVtx[k + 3].v.cn[2] = 255;
+
+ pauseCtx->questVtx[k + 0].v.cn[3] = pauseCtx->questVtx[k + 1].v.cn[3] = pauseCtx->questVtx[k + 2].v.cn[3] =
+ pauseCtx->questVtx[k + 3].v.cn[3] = pauseCtx->alpha;
+ }
+ }
+
+ if (pauseCtx->pageIndex != PAUSE_MAP) {
+ pauseCtx->maskPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_MASK_QUADS) * 4) * sizeof(Vtx));
+ KaleidoScope_SetPageVertices(play, pauseCtx->maskPageVtx, VTX_PAGE_MASK, VTX_PAGE_MASK_QUADS);
+
+ pauseCtx->maskVtx = GRAPH_ALLOC(gfxCtx, (QUAD_MASK_MAX * 4) * sizeof(Vtx));
+
+ // Loop over grid rows
+ for (k = 0, i = 0, vtx_y = (MASK_GRID_ROWS * MASK_GRID_CELL_HEIGHT) / 2 - 6; k < MASK_GRID_ROWS;
+ k++, vtx_y -= MASK_GRID_CELL_HEIGHT) {
+ // Loop over grid columns
+ for (vtx_x = 0 - (MASK_GRID_COLS * MASK_GRID_CELL_WIDTH) / 2, j = 0; j < MASK_GRID_COLS;
+ j++, i += 4, vtx_x += MASK_GRID_CELL_WIDTH) {
+ pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0] = vtx_x + MASK_GRID_QUAD_MARGIN;
+ pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] =
+ pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_QUAD_WIDTH;
+
+ pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] =
+ vtx_y + pauseCtx->offsetY - MASK_GRID_QUAD_MARGIN;
+ pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] =
+ pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_QUAD_HEIGHT;
+
+ pauseCtx->maskVtx[i + 0].v.ob[2] = pauseCtx->maskVtx[i + 1].v.ob[2] = pauseCtx->maskVtx[i + 2].v.ob[2] =
+ pauseCtx->maskVtx[i + 3].v.ob[2] = 0;
+
+ pauseCtx->maskVtx[i + 0].v.flag = pauseCtx->maskVtx[i + 1].v.flag = pauseCtx->maskVtx[i + 2].v.flag =
+ pauseCtx->maskVtx[i + 3].v.flag = 0;
+
+ pauseCtx->maskVtx[i + 0].v.tc[0] = pauseCtx->maskVtx[i + 0].v.tc[1] = pauseCtx->maskVtx[i + 1].v.tc[1] =
+ pauseCtx->maskVtx[i + 2].v.tc[0] = 0;
+
+ pauseCtx->maskVtx[i + 1].v.tc[0] = pauseCtx->maskVtx[i + 2].v.tc[1] = pauseCtx->maskVtx[i + 3].v.tc[0] =
+ pauseCtx->maskVtx[i + 3].v.tc[1] = MASK_GRID_QUAD_TEX_SIZE * (1 << 5);
+
+ pauseCtx->maskVtx[i + 0].v.cn[0] = pauseCtx->maskVtx[i + 1].v.cn[0] = pauseCtx->maskVtx[i + 2].v.cn[0] =
+ pauseCtx->maskVtx[i + 3].v.cn[0] = pauseCtx->maskVtx[i + 0].v.cn[1] =
+ pauseCtx->maskVtx[i + 1].v.cn[1] = pauseCtx->maskVtx[i + 2].v.cn[1] =
+ pauseCtx->maskVtx[i + 3].v.cn[1] = pauseCtx->maskVtx[i + 0].v.cn[2] =
+ pauseCtx->maskVtx[i + 1].v.cn[2] = pauseCtx->maskVtx[i + 2].v.cn[2] =
+ pauseCtx->maskVtx[i + 3].v.cn[2] = 255;
+
+ pauseCtx->maskVtx[i + 0].v.cn[3] = pauseCtx->maskVtx[i + 1].v.cn[3] = pauseCtx->maskVtx[i + 2].v.cn[3] =
+ pauseCtx->maskVtx[i + 3].v.cn[3] = 255;
+ }
+ }
+
+ // QUAD_MASK_GRID_SELECTED_C_LEFT, QUAD_MASK_GRID_SELECTED_C_DOWN, QUAD_MASK_GRID_SELECTED_C_RIGHT
+
+ for (j = EQUIP_SLOT_C_LEFT; j <= EQUIP_SLOT_C_RIGHT; j++, i += 4) {
+ if (GET_CUR_FORM_BTN_SLOT(j) != ITEM_NONE) {
+ k = (GET_CUR_FORM_BTN_SLOT(j) - ITEM_NUM_SLOTS) * 4;
+
+ pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0] =
+ pauseCtx->maskVtx[k].v.ob[0] + MASK_GRID_SELECTED_QUAD_MARGIN;
+
+ pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] =
+ pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH;
+
+ pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] =
+ pauseCtx->maskVtx[k].v.ob[1] - MASK_GRID_SELECTED_QUAD_MARGIN;
+
+ pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] =
+ pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT;
+
+ pauseCtx->maskVtx[i + 0].v.ob[2] = pauseCtx->maskVtx[i + 1].v.ob[2] = pauseCtx->maskVtx[i + 2].v.ob[2] =
+ pauseCtx->maskVtx[i + 3].v.ob[2] = 0;
+
+ pauseCtx->maskVtx[i + 0].v.flag = pauseCtx->maskVtx[i + 1].v.flag = pauseCtx->maskVtx[i + 2].v.flag =
+ pauseCtx->maskVtx[i + 3].v.flag = 0;
+
+ pauseCtx->maskVtx[i + 0].v.tc[0] = pauseCtx->maskVtx[i + 0].v.tc[1] = pauseCtx->maskVtx[i + 1].v.tc[1] =
+ pauseCtx->maskVtx[i + 2].v.tc[0] = 0;
+
+ pauseCtx->maskVtx[i + 1].v.tc[0] = pauseCtx->maskVtx[i + 2].v.tc[1] = pauseCtx->maskVtx[i + 3].v.tc[0] =
+ pauseCtx->maskVtx[i + 3].v.tc[1] = MASK_GRID_SELECTED_QUAD_TEX_SIZE * (1 << 5);
+
+ pauseCtx->maskVtx[i + 0].v.cn[0] = pauseCtx->maskVtx[i + 1].v.cn[0] = pauseCtx->maskVtx[i + 2].v.cn[0] =
+ pauseCtx->maskVtx[i + 3].v.cn[0] = pauseCtx->maskVtx[i + 0].v.cn[1] =
+ pauseCtx->maskVtx[i + 1].v.cn[1] = pauseCtx->maskVtx[i + 2].v.cn[1] =
+ pauseCtx->maskVtx[i + 3].v.cn[1] = pauseCtx->maskVtx[i + 0].v.cn[2] =
+ pauseCtx->maskVtx[i + 1].v.cn[2] = pauseCtx->maskVtx[i + 2].v.cn[2] =
+ pauseCtx->maskVtx[i + 3].v.cn[2] = 255;
+
+ pauseCtx->maskVtx[i + 0].v.cn[3] = pauseCtx->maskVtx[i + 1].v.cn[3] = pauseCtx->maskVtx[i + 2].v.cn[3] =
+ pauseCtx->maskVtx[i + 3].v.cn[3] = pauseCtx->alpha;
+ } else {
+ pauseCtx->maskVtx[i + 2].v.ob[0] = -300;
+ pauseCtx->maskVtx[i + 0].v.ob[0] = pauseCtx->maskVtx[i + 2].v.ob[0];
+
+ pauseCtx->maskVtx[i + 1].v.ob[0] = pauseCtx->maskVtx[i + 3].v.ob[0] =
+ pauseCtx->maskVtx[i + 0].v.ob[0] + MASK_GRID_SELECTED_QUAD_WIDTH;
+
+ pauseCtx->maskVtx[i + 0].v.ob[1] = pauseCtx->maskVtx[i + 1].v.ob[1] = 300;
+ pauseCtx->maskVtx[i + 2].v.ob[1] = pauseCtx->maskVtx[i + 3].v.ob[1] =
+ pauseCtx->maskVtx[i + 0].v.ob[1] - MASK_GRID_SELECTED_QUAD_HEIGHT;
+ }
+ }
+ }
+
+ pauseCtx->cursorVtx = GRAPH_ALLOC(play->state.gfxCtx, (PAUSE_QUAD_CURSOR_MAX * 4) * sizeof(Vtx));
+
+ for (i = 0; i < (PAUSE_QUAD_CURSOR_MAX * 4); i++) {
+ pauseCtx->cursorVtx[i].v.ob[0] = pauseCtx->cursorVtx[i].v.ob[1] = pauseCtx->cursorVtx[i].v.ob[2] = 0;
+
+ pauseCtx->cursorVtx[i].v.flag = 0;
+
+ pauseCtx->cursorVtx[i].v.tc[0] = pauseCtx->cursorVtx[i].v.tc[1] = 0;
+
+ pauseCtx->cursorVtx[i].v.cn[0] = pauseCtx->cursorVtx[i].v.cn[1] = pauseCtx->cursorVtx[i].v.cn[2] =
+ pauseCtx->cursorVtx[i].v.cn[3] = 255;
+ }
+
+ // PAUSE_QUAD_CURSOR_0
+ pauseCtx->cursorVtx[1].v.tc[0] = pauseCtx->cursorVtx[2].v.tc[1] = pauseCtx->cursorVtx[3].v.tc[0] =
+ pauseCtx->cursorVtx[3].v.tc[1]
+ // PAUSE_QUAD_CURSOR_1
+ = pauseCtx->cursorVtx[5].v.tc[0] = pauseCtx->cursorVtx[6].v.tc[1] = pauseCtx->cursorVtx[7].v.tc[0] =
+ pauseCtx->cursorVtx[7].v.tc[1]
+ // PAUSE_QUAD_CURSOR_2
+ = pauseCtx->cursorVtx[9].v.tc[0] = pauseCtx->cursorVtx[10].v.tc[1] = pauseCtx->cursorVtx[11].v.tc[0] =
+ pauseCtx->cursorVtx[11].v.tc[1]
+ // PAUSE_QUAD_CURSOR_3
+ = pauseCtx->cursorVtx[13].v.tc[0] = pauseCtx->cursorVtx[14].v.tc[1] = pauseCtx->cursorVtx[15].v.tc[0] =
+ pauseCtx->cursorVtx[15].v.tc[1] = 16 * (1 << 5);
+
+ // PAUSE_QUAD_CURSOR_4
+ pauseCtx->cursorVtx[17].v.tc[0] = pauseCtx->cursorVtx[18].v.tc[1] = pauseCtx->cursorVtx[19].v.tc[0] =
+ pauseCtx->cursorVtx[19].v.tc[1] = 32 * (1 << 5);
+
+ pauseCtx->infoPanelVtx = GRAPH_ALLOC(gfxCtx, 28 * sizeof(Vtx));
+
+ if ((pauseCtx->state == PAUSE_STATE_SAVEPROMPT) || IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
+ pauseCtx->promptPageVtx = GRAPH_ALLOC(gfxCtx, ((PAGE_BG_QUADS + VTX_PAGE_SAVE_QUADS) * 4) * sizeof(Vtx));
+ KaleidoScope_SetPageVertices(play, pauseCtx->promptPageVtx, VTX_PAGE_PROMPT, VTX_PAGE_SAVE_QUADS);
+ }
+}
+
+f32 sItemMaskCursorsX[] = {
+ -62.0f, // Column 1
+ -36.0f, // Column 2
+ -10.0f, // Column 3
+ 16.0f, // Column 4
+ 42.0f, // Column 5
+ 68.0f, // Column 6
+};
+
+f32 sItemMaskCursorsY[] = {
+ 31.0f, // Row 1
+ 5.0f, // Row 2
+ -21.0f, // Row 3
+ -47.0f, // Row 4
+};
+
+f32 sWorldMapCursorsX[REGION_MAX] = {
+ -49.0f, // REGION_GREAT_BAY
+ -35.0f, // REGION_ZORA_HALL
+ -3.0f, // REGION_ROMANI_RANCH
+ 4.0f, // REGION_DEKU_PALACE
+ 12.0f, // REGION_WOODFALL
+ 8.0f, // REGION_CLOCK_TOWN
+ 7.0f, // REGION_SNOWHEAD
+ 40.0f, // REGION_IKANA_GRAVEYARD
+ 47.0f, // REGION_IKANA_CANYON
+ 49.0f, // REGION_GORON_VILLAGE
+ 55.0f, // REGION_STONE_TOWER
+};
+
+f32 sWorldMapCursorsY[REGION_MAX] = {
+ -15.0f, // REGION_GREAT_BAY
+ -36.0f, // REGION_ZORA_HALL
+ -23.0f, // REGION_ROMANI_RANCH
+ -49.0f, // REGION_DEKU_PALACE
+ -29.0f, // REGION_WOODFALL
+ -8.0f, // REGION_CLOCK_TOWN
+ 25.0f, // REGION_SNOWHEAD
+ 2.0f, // REGION_IKANA_GRAVEYARD
+ -9.0f, // REGION_IKANA_CANYON
+ 28.0f, // REGION_GORON_VILLAGE
+ 7.0f, // REGION_STONE_TOWER
+};
+
+f32 sOwlWarpWorldMapCursorsX[OWL_WARP_MAX - 1] = {
+ -50.0f, // OWL_WARP_GREAT_BAY_COAST
+ -38.0f, // OWL_WARP_ZORA_CAPE
+ 6.0f, // OWL_WARP_SNOWHEAD
+ 11.0f, // OWL_WARP_MOUNTAIN_VILLAGE
+ 8.0f, // OWL_WARP_CLOCK_TOWN
+ 0.0f, // OWL_WARP_MILK_ROAD
+ 12.0f, // OWL_WARP_WOODFALL
+ 31.0f, // OWL_WARP_SOUTHERN_SWAMP
+ 48.0f, // OWL_WARP_IKANA_CANYON
+ 56.0f, // OWL_WARP_STONE_TOWER
+};
+
+f32 sOwlWarpWorldMapCursorsY[OWL_WARP_MAX - 1] = {
+ -14.0f, // OWL_WARP_GREAT_BAY_COAST
+ -39.0f, // OWL_WARP_ZORA_CAPE
+ 23.0f, // OWL_WARP_SNOWHEAD
+ 11.0f, // OWL_WARP_MOUNTAIN_VILLAGE
+ -8.0f, // OWL_WARP_CLOCK_TOWN
+ -15.0f, // OWL_WARP_MILK_ROAD
+ -31.0f, // OWL_WARP_WOODFALL
+ -30.0f, // OWL_WARP_SOUTHERN_SWAMP
+ -10.0f, // OWL_WARP_IKANA_CANYON
+ 11.0f, // OWL_WARP_STONE_TOWER
+};
+
+f32 sDungeonMapCursorsX[] = {
+ -72.0f, // DUNGEON_BOSS_KEY
+ -47.0f, // DUNGEON_COMPASS
+ -26.0f, // DUNGEON_MAP
+ -50.0f, // DUNGEON_STRAY_FAIRIES
+ -48.0f, // DUNGEON_FLOOR_INDEX_4 (top floor)
+ -48.0f, // DUNGEON_FLOOR_INDEX_3
+ -48.0f, // DUNGEON_FLOOR_INDEX_2
+ -48.0f, // DUNGEON_FLOOR_INDEX_1
+ -48.0f, // DUNGEON_FLOOR_INDEX_0 (bottom floor)
+};
+
+f32 sDungeonMapCursorsY[] = {
+ -47.0f, // DUNGEON_BOSS_KEY
+ -47.0f, // DUNGEON_COMPASS
+ -47.0f, // DUNGEON_MAP
+ -30.0f, // DUNGEON_STRAY_FAIRIES
+ 33.0f, // DUNGEON_FLOOR_INDEX_4 (top floor)
+ 22.0f, // DUNGEON_FLOOR_INDEX_3
+ 11.0f, // DUNGEON_FLOOR_INDEX_2
+ -2.0f, // DUNGEON_FLOOR_INDEX_1
+ -13.0f, // DUNGEON_FLOOR_INDEX_0 (bottom floor)
+};
+
+f32 sQuestStatusCursorsX[] = {
+ 52.0f, // QUEST_REMAINS_ODOLWA
+ 80.0f, // QUEST_REMAINS_GOHT
+ 24.0f, // QUEST_REMAINS_GYORG
+ 52.0f, // QUEST_REMAINS_TWINMOLD
+ 81.0f, // QUEST_SHIELD
+ 24.0f, // QUEST_SWORD
+ -78.0f, // QUEST_SONG_SONATA
+ -61.0f, // QUEST_SONG_LULLABY
+ -44.0f, // QUEST_SONG_BOSSA_NOVA
+ -24.0f, // QUEST_SONG_ELEGY
+ -6.0f, // QUEST_SONG_OATH
+ -3.0f, // QUEST_SONG_SARIA
+ -78.0f, // QUEST_SONG_TIME
+ -61.0f, // QUEST_SONG_HEALING
+ -44.0f, // QUEST_SONG_EPONA
+ -24.0f, // QUEST_SONG_SOARING
+ -6.0f, // QUEST_SONG_STORMS
+ -3.0f, // QUEST_SONG_SUN
+ -68.0f, // QUEST_BOMBERS_NOTEBOOK
+ 22.0f, // QUEST_QUIVER
+ 83.0f, // QUEST_BOMB_BAG
+ -67.0f, // QUEST_SKULL_TOKEN
+ -21.0f, // QUEST_HEART_PIECE
+};
+
+f32 sQuestStatusCursorsY[] = {
+ 33.0f, // QUEST_REMAINS_ODOLWA
+ 18.0f, // QUEST_REMAINS_GOHT
+ 18.0f, // QUEST_REMAINS_GYORG
+ 0.0f, // QUEST_REMAINS_TWINMOLD
+ -23.0f, // QUEST_SHIELD
+ -23.0f, // QUEST_SWORD
+ -29.0f, // QUEST_SONG_SONATA
+ -29.0f, // QUEST_SONG_LULLABY
+ -29.0f, // QUEST_SONG_BOSSA_NOVA
+ -29.0f, // QUEST_SONG_ELEGY
+ -29.0f, // QUEST_SONG_OATH
+ -29.0f, // QUEST_SONG_SARIA
+ -11.0f, // QUEST_SONG_TIME
+ -11.0f, // QUEST_SONG_HEALING
+ -11.0f, // QUEST_SONG_EPONA
+ -11.0f, // QUEST_SONG_SOARING
+ -11.0f, // QUEST_SONG_STORMS
+ -11.0f, // QUEST_SONG_SUN
+ 27.0f, // QUEST_BOMBERS_NOTEBOOK
+ -53.0f, // QUEST_QUIVER
+ -53.0f, // QUEST_BOMB_BAG
+ 14.0f, // QUEST_SKULL_TOKEN
+ 26.0f, // QUEST_HEART_PIECE
+};
+
+void KaleidoScope_UpdateCursorSize(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 index;
+
+ pauseCtx->cursorVtx[0].v.ob[0] = pauseCtx->cursorVtx[2].v.ob[0] = -8;
+ pauseCtx->cursorVtx[1].v.ob[0] = pauseCtx->cursorVtx[3].v.ob[0] = pauseCtx->cursorVtx[0].v.ob[0] + 16;
+
+ pauseCtx->cursorVtx[0].v.ob[1] = pauseCtx->cursorVtx[1].v.ob[1] = 8;
+ pauseCtx->cursorVtx[2].v.ob[1] = pauseCtx->cursorVtx[3].v.ob[1] = pauseCtx->cursorVtx[0].v.ob[1] - 16;
+
+ if (pauseCtx->cursorSpecialPos == 0) {
+ switch (pauseCtx->pageIndex) {
+ case PAUSE_ITEM:
+ pauseCtx->cursorX = sItemMaskCursorsX[pauseCtx->cursorXIndex[PAUSE_ITEM]];
+ pauseCtx->cursorY = sItemMaskCursorsY[pauseCtx->cursorYIndex[PAUSE_ITEM]];
+ pauseCtx->cursorWidth = 15.0f;
+ pauseCtx->cursorHeight = 15.0f;
+ break;
+
+ case PAUSE_MAP:
+ if (!sInDungeonScene) {
+ if (IS_PAUSE_STATE_OWL_WARP(pauseCtx)) {
+ pauseCtx->cursorX = sOwlWarpWorldMapCursorsX[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
+ pauseCtx->cursorY = sOwlWarpWorldMapCursorsY[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
+ } else {
+ pauseCtx->cursorX = sWorldMapCursorsX[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
+ pauseCtx->cursorY = sWorldMapCursorsY[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
+ }
+ if (!IS_PAUSE_STATE_OWL_WARP(pauseCtx)) {
+ pauseCtx->cursorHeight = 10.0f;
+ pauseCtx->cursorWidth = 10.0f;
+ } else {
+ pauseCtx->cursorHeight = 15.0f;
+ pauseCtx->cursorWidth = 15.0f;
+ }
+ } else {
+ pauseCtx->cursorX = sDungeonMapCursorsX[pauseCtx->cursorPoint[PAUSE_MAP]];
+ pauseCtx->cursorY = sDungeonMapCursorsY[pauseCtx->cursorPoint[PAUSE_MAP]];
+ if (pauseCtx->cursorSlot[pauseCtx->pageIndex] >= DUNGEON_FLOOR_INDEX_4) {
+ // Floors
+ pauseCtx->cursorWidth = 18.0f;
+ pauseCtx->cursorHeight = 12.0f;
+ } else if (pauseCtx->cursorSlot[pauseCtx->pageIndex] == DUNGEON_STRAY_FAIRIES) {
+ // Stray Fairies
+ pauseCtx->cursorHeight = 12.0f;
+ pauseCtx->cursorWidth = 40.0f;
+ } else {
+ // Map, Compass, Boss Key
+ pauseCtx->cursorHeight = 15.0f;
+ pauseCtx->cursorWidth = 15.0f;
+ }
+ }
+ break;
+
+ case PAUSE_QUEST:
+ if (!R_PAUSE_DBG_QUEST_CURSOR_ON) {
+ pauseCtx->cursorX = sQuestStatusCursorsX[pauseCtx->cursorPoint[PAUSE_QUEST]];
+ pauseCtx->cursorY = sQuestStatusCursorsY[pauseCtx->cursorPoint[PAUSE_QUEST]];
+ } else {
+ pauseCtx->cursorX = R_PAUSE_DBG_QUEST_CURSOR_X;
+ pauseCtx->cursorY = R_PAUSE_DBG_QUEST_CURSOR_Y;
+ }
+ pauseCtx->cursorHeight = 17.0f;
+ pauseCtx->cursorWidth = 17.0f;
+ if (pauseCtx->cursorSlot[pauseCtx->pageIndex] == QUEST_17) {
+ pauseCtx->cursorHeight = 25.0f;
+ pauseCtx->cursorWidth = 25.0f;
+ } else if (pauseCtx->cursorSlot[pauseCtx->pageIndex] <= QUEST_SWORD) {
+ pauseCtx->cursorHeight = 18.0f;
+ pauseCtx->cursorWidth = 18.0f;
+ } else if ((pauseCtx->cursorSlot[pauseCtx->pageIndex] >= QUEST_SONG_SONATA) &&
+ (pauseCtx->cursorSlot[pauseCtx->pageIndex] <= QUEST_SONG_SUN)) {
+ pauseCtx->cursorHeight = 12.0f;
+ pauseCtx->cursorWidth = 12.0f;
+ }
+ break;
+
+ case PAUSE_MASK:
+ pauseCtx->cursorX = sItemMaskCursorsX[pauseCtx->cursorXIndex[PAUSE_MASK]];
+ pauseCtx->cursorY = sItemMaskCursorsY[pauseCtx->cursorYIndex[PAUSE_MASK]];
+ pauseCtx->cursorWidth = 15.0f;
+ pauseCtx->cursorHeight = 15.0f;
+ break;
+
+ default:
+ break;
+ }
+
+ pauseCtx->cursorSpinPhase += 0x300;
+ } else {
+ if (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) {
+ pauseCtx->cursorX = -93.0f;
+ } else { // PAUSE_CURSOR_PAGE_RIGHT
+ pauseCtx->cursorX = 101.0f;
+ }
+ pauseCtx->cursorSpinPhase += 0x300;
+ pauseCtx->cursorHeight = 16.0f;
+ pauseCtx->cursorWidth = 16.0f;
+ pauseCtx->cursorY = -4.0f;
+ }
+
+ if (pauseCtx->cursorWidth < pauseCtx->cursorShrinkRate) {
+ pauseCtx->cursorWidth = 0;
+ } else {
+ pauseCtx->cursorWidth -= pauseCtx->cursorShrinkRate;
+ }
+
+ if (pauseCtx->cursorHeight < pauseCtx->cursorShrinkRate) {
+ pauseCtx->cursorHeight = 0.0f;
+ } else {
+ pauseCtx->cursorHeight -= pauseCtx->cursorShrinkRate;
+ }
+
+ if (pauseCtx->cursorShrinkRate != 0.0f) {
+ pauseCtx->cursorShrinkRate -= 1.0f;
+ }
+
+ sCursorCirclesX[0] = Math_SinS(pauseCtx->cursorSpinPhase) * pauseCtx->cursorWidth;
+ sCursorCirclesX[1] = Math_SinS(pauseCtx->cursorSpinPhase + 0x4000) * pauseCtx->cursorWidth;
+ sCursorCirclesX[2] = Math_SinS(pauseCtx->cursorSpinPhase + 0x8000) * pauseCtx->cursorWidth;
+ sCursorCirclesX[3] = Math_SinS(pauseCtx->cursorSpinPhase + 0xC000) * pauseCtx->cursorWidth;
+ sCursorCirclesY[0] = Math_CosS(pauseCtx->cursorSpinPhase) * pauseCtx->cursorHeight;
+ sCursorCirclesY[1] = Math_CosS(pauseCtx->cursorSpinPhase + 0x4000) * pauseCtx->cursorHeight;
+ sCursorCirclesY[2] = Math_CosS(pauseCtx->cursorSpinPhase + 0x8000) * pauseCtx->cursorHeight;
+ sCursorCirclesY[3] = Math_CosS(pauseCtx->cursorSpinPhase + 0xC000) * pauseCtx->cursorHeight;
+}
+
+void KaleidoScope_DrawCursor(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+ s16 i;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ if ((pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG) ||
+ ((pauseCtx->pageIndex == PAUSE_QUEST) && ((pauseCtx->mainState <= PAUSE_MAIN_STATE_SONG_PLAYBACK) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_SONG_PROMPT) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG)))) {
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
+ PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 0, sCursorPrimR, sCursorPrimG, sCursorPrimB, 255);
+ gDPSetEnvColor(POLY_OPA_DISP++, sCursorEnvR, sCursorEnvG, sCursorEnvB, 255);
+
+ Matrix_Translate(pauseCtx->cursorX, pauseCtx->cursorY, -50.0f, MTXMODE_NEW);
+ Matrix_Scale(1.0f, 1.0f, 1.0f, MTXMODE_APPLY);
+
+ for (i = 0; i < 4; i++) {
+ Matrix_Push();
+ Matrix_Translate(sCursorCirclesX[i], sCursorCirclesY[i], -50.0f, MTXMODE_APPLY);
+ MATRIX_FINALIZE_AND_LOAD(POLY_OPA_DISP++, play->state.gfxCtx);
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gPauseMenuCursorTex, G_IM_FMT_IA, G_IM_SIZ_8b, 16, 16, 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);
+ gSPVertex(POLY_OPA_DISP++, &pauseCtx->cursorVtx[0], 4, 0);
+ gSP1Quadrangle(POLY_OPA_DISP++, 0, 2, 3, 1, 0);
+ Matrix_Pop();
+ }
+
+ gDPPipeSync(POLY_OPA_DISP++);
+ gDPSetEnvColor(POLY_OPA_DISP++, 0, 0, 0, 255);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void KaleidoScope_DrawGameOver(PlayState* play) {
+ static s16 sGameOverUlt = 0;
+ GraphicsContext* gfxCtx = play->state.gfxCtx;
+
+ OPEN_DISPS(gfxCtx);
+
+ Gfx_SetupDL39_Opa(gfxCtx);
+
+ gDPSetCycleType(POLY_OPA_DISP++, G_CYC_2CYCLE);
+ gDPSetRenderMode(POLY_OPA_DISP++, G_RM_PASS, G_RM_XLU_SURF2);
+ gDPSetCombineLERP(POLY_OPA_DISP++, TEXEL1, TEXEL0, PRIM_LOD_FRAC, TEXEL0, 0, 0, 0, TEXEL0, PRIMITIVE, ENVIRONMENT,
+ COMBINED, ENVIRONMENT, COMBINED, 0, PRIMITIVE, 0);
+
+ gDPSetPrimColor(POLY_OPA_DISP++, 0, 80, sGameOverPrimR, sGameOverPrimG, sGameOverPrimB, sGameOverPrimAlpha);
+ gDPSetEnvColor(POLY_OPA_DISP++, sGameOverEnvR, sGameOverEnvG, sGameOverEnvB, 255);
+
+ sGameOverUlt -= 2;
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gGameOverP1Tex, G_IM_FMT_IA, G_IM_SIZ_8b, 64, 32, 0, G_TX_NOMIRROR | G_TX_WRAP,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
+
+ gDPLoadMultiBlock(POLY_OPA_DISP++, gGameOverMaskTex, 256, 1, G_IM_FMT_IA, G_IM_SIZ_8b, 64, 32, 0,
+ G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, 5, G_TX_NOLOD, G_TX_NOLOD);
+
+ gDPSetTileSize(POLY_OPA_DISP++, 1, 0, sGameOverUlt & 0x7F, 252, (sGameOverUlt & 0x7F) + 124);
+
+ gSPTextureRectangle(POLY_OPA_DISP++, 0x100, sGameOverRectPosY << 2, 0x200, (sGameOverRectPosY + 32) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gGameOverP2Tex, G_IM_FMT_IA, G_IM_SIZ_8b, 64, 32, 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);
+
+ gSPTextureRectangle(POLY_OPA_DISP++, 0x200, sGameOverRectPosY << 2, 0x300, (sGameOverRectPosY + 32) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ gDPLoadTextureBlock(POLY_OPA_DISP++, gGameOverP3Tex, G_IM_FMT_IA, G_IM_SIZ_8b, 64, 32, 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);
+
+ gSPTextureRectangle(POLY_OPA_DISP++, 0x300, sGameOverRectPosY << 2, 0x400, (sGameOverRectPosY + 32) << 2,
+ G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
+
+ CLOSE_DISPS(gfxCtx);
+}
+
+void KaleidoScope_Draw(PlayState* play) {
+ s32 pad;
+ PauseContext* pauseCtx = &play->pauseCtx;
+ InterfaceContext* interfaceCtx = &play->interfaceCtx;
+
+ OPEN_DISPS(play->state.gfxCtx);
+
+ gSPSegment(POLY_OPA_DISP++, 0x02, interfaceCtx->parameterSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x08, pauseCtx->iconItemSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x09, pauseCtx->iconItem24Segment);
+ gSPSegment(POLY_OPA_DISP++, 0x0A, pauseCtx->nameSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x0C, pauseCtx->iconItemAltSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x0D, pauseCtx->iconItemLangSegment);
+ gSPSegment(POLY_OPA_DISP++, 0x0B, pauseCtx->iconItemVtxSegment);
+
+ if (pauseCtx->debugEditor == DEBUG_EDITOR_NONE) {
+ KaleidoScope_SetView(pauseCtx, pauseCtx->eye.x, pauseCtx->eye.y, pauseCtx->eye.z);
+ Gfx_SetupDL42_Opa(play->state.gfxCtx);
+
+ if (!IS_PAUSE_STATE_OWL_WARP(pauseCtx)) {
+ // Draw Default or Game Over Menus
+ KaleidoScope_SetVertices(play, play->state.gfxCtx);
+ KaleidoScope_DrawPages(play, play->state.gfxCtx);
+
+ Gfx_SetupDL42_Opa(play->state.gfxCtx);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
+ PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+
+ KaleidoScope_SetView(pauseCtx, 0.0f, 0.0f, 64.0f);
+
+ if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
+ KaleidoScope_DrawInfoPanel(play);
+ }
+
+ KaleidoScope_UpdateCursorSize(play);
+
+ if (pauseCtx->state == PAUSE_STATE_MAIN) {
+ KaleidoScope_DrawCursor(play);
+ }
+
+ if ((pauseCtx->state >= PAUSE_STATE_GAMEOVER_3) && (pauseCtx->state <= PAUSE_STATE_GAMEOVER_10) &&
+ (play->gameOverCtx.state != GAMEOVER_INACTIVE)) {
+ KaleidoScope_DrawGameOver(play);
+ }
+ } else {
+ // Draw Owl Warp Menu
+ KaleidoScope_SetVertices(play, play->state.gfxCtx);
+ KaleidoScope_DrawPages(play, play->state.gfxCtx);
+ KaleidoScope_DrawOwlWarpMapPage(play);
+
+ Gfx_SetupDL42_Opa(play->state.gfxCtx);
+ gDPSetCombineLERP(POLY_OPA_DISP++, PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0,
+ PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, TEXEL0, 0, PRIMITIVE, 0);
+
+ KaleidoScope_SetView(pauseCtx, 0.0f, 0.0f, 64.0f);
+ KaleidoScope_DrawOwlWarpInfoPanel(play);
+ KaleidoScope_UpdateCursorSize(play);
+
+ if (pauseCtx->state == PAUSE_STATE_OWL_WARP_SELECT) {
+ KaleidoScope_DrawCursor(play);
+ }
+ }
+ }
+
+ if ((pauseCtx->debugEditor == DEBUG_EDITOR_INVENTORY_INIT) || (pauseCtx->debugEditor == DEBUG_EDITOR_INVENTORY)) {
+ KaleidoScope_DrawInventoryEditor(play);
+ }
+
+ CLOSE_DISPS(play->state.gfxCtx);
+}
+
+void KaleidoScope_GrayOutTextureRGBA32(u32* texture, u16 pixelCount) {
+ u32 rgb;
+ u32 gray;
+ u16 i;
+ s32 j;
+
+ //! FAKE
+ if (texture == NULL) {}
+
+ for (i = 0; i < pixelCount; i++) {
+ //! FAKE
+ j = i;
+ if ((texture[j] & 0xFFFFFF00) != 0) {
+ rgb = texture[j] >> 8;
+ gray = ((((rgb & 0xFF0000) >> 16) + ((rgb & 0xFF00) >> 7) + (rgb & 0xFF)) / 7) & 0xFF;
+
+ rgb = gray;
+ rgb <<= 8;
+ rgb |= gray;
+ rgb <<= 8;
+ rgb |= gray;
+
+ texture[j] = (rgb << 8) | (texture[j] & 0xFF);
+ }
+ }
+}
+
+void KaleidoScope_UpdateOpening(PlayState* play) {
+ PauseContext* pauseCtx = &play->pauseCtx;
+
+ pauseCtx->eye.x += sPageSwitchEyeDx[pauseCtx->nextPageMode] * 2.0f;
+ pauseCtx->eye.z += sPageSwitchEyeDz[pauseCtx->nextPageMode] * 2.0f;
+ pauseCtx->switchPageTimer += 8;
+
+ if (pauseCtx->switchPageTimer == 64) {
+ // Finished opening
+ Interface_UpdateButtonsAlt(play, 1);
+
+ if (pauseCtx->cursorSpecialPos == 0) {
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][0];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = gPageSwitchNextButtonStatus[pauseCtx->pageIndex][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_ENABLED;
+ } else {
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = BTN_ENABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = BTN_DISABLED;
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = BTN_DISABLED;
+ }
+
+ pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode];
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ pauseCtx->state++; // PAUSE_STATE_MAIN
+ pauseCtx->alpha = 255;
+ Interface_SetBButtonInterfaceDoAction(play, DO_ACTION_RETURN);
+ } else if (pauseCtx->switchPageTimer == 64) {
+ pauseCtx->pageIndex = sPageSwitchNextPageIndex[pauseCtx->nextPageMode];
+ pauseCtx->nextPageMode = (pauseCtx->pageIndex * 2) + 1;
+ }
+}
+
+u16 sCursorPointsToOcarinaModes[] = {
+ OCARINA_MODE_WARP_TO_GREAT_BAY_COAST, OCARINA_MODE_WARP_TO_ZORA_CAPE, OCARINA_MODE_WARP_TO_SNOWHEAD,
+ OCARINA_MODE_WARP_TO_MOUNTAIN_VILLAGE, OCARINA_MODE_WARP_TO_SOUTH_CLOCK_TOWN, OCARINA_MODE_WARP_TO_MILK_ROAD,
+ OCARINA_MODE_WARP_TO_WOODFALL, OCARINA_MODE_WARP_TO_SOUTHERN_SWAMP, OCARINA_MODE_WARP_TO_IKANA_CANYON,
+ OCARINA_MODE_WARP_TO_STONE_TOWER,
+};
+
+void KaleidoScope_Update(PlayState* play) {
+ static s16 sUnpausedHudVisibility = HUD_VISIBILITY_IDLE;
+ static s16 sNextMainState = PAUSE_MAIN_STATE_IDLE;
+ static s16 sDelayTimer = 10;
+ static s16 sGameOverColorTimer = 0;
+ static s16 sStickXRepeatTimer = 0;
+ static s16 sStickYRepeatTimer = 0;
+ static s16 sStickXRepeatState = 0;
+ static s16 sStickYRepeatState = 0;
+ PauseContext* pauseCtx = &play->pauseCtx;
+ InterfaceContext* interfaceCtx = &play->interfaceCtx;
+ MessageContext* msgCtx = &play->msgCtx;
+ GameOverContext* gameOverCtx = &play->gameOverCtx;
+ SramContext* sramCtx = &play->sramCtx;
+ Input* input = CONTROLLER1(&play->state);
+ size_t size0;
+ size_t size1;
+ size_t size2;
+ u16 itemId;
+ u16 worldMapCursorPoint;
+ void* iconItemLangSegment;
+ s16 stepR;
+ s16 stepG;
+ s16 stepB;
+ s16 stepA;
+ s16 stickAdjX = input->rel.stick_x;
+
+ MapDisp_UpdateDungeonMap(play);
+
+ pauseCtx->stickAdjX = input->rel.stick_x;
+ pauseCtx->stickAdjY = input->rel.stick_y;
+
+ switch (pauseCtx->state) {
+ case PAUSE_STATE_OPENING_2:
+ sUnpausedHudVisibility = gSaveContext.hudVisibility;
+ sPauseMenuVerticalOffset = -6240.0f;
+
+ sUnpausedButtonStatus[EQUIP_SLOT_B] = gSaveContext.buttonStatus[EQUIP_SLOT_B];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_LEFT] = gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_DOWN] = gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_RIGHT] = gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT];
+ sUnpausedButtonStatus[EQUIP_SLOT_A] = gSaveContext.buttonStatus[EQUIP_SLOT_A];
+
+ pauseCtx->cursorXIndex[PAUSE_MAP] = 0;
+ pauseCtx->cursorSlot[PAUSE_MAP] = R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+ pauseCtx->cursorPoint[PAUSE_MAP] = pauseCtx->cursorMapDungeonItem =
+ R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+
+ sPauseCursorLeftX = -175;
+ sPauseCursorRightX = 155;
+ pauseCtx->roll = -314.0f;
+
+ pauseCtx->iconItemSegment = (void*)ALIGN16((uintptr_t)play->objectCtx.spaceStart);
+ size0 = SEGMENT_ROM_SIZE(icon_item_static_syms);
+ CmpDma_LoadAllFiles(SEGMENT_ROM_START(icon_item_static_yar), pauseCtx->iconItemSegment, size0);
+
+ gSegments[0x08] = OS_K0_TO_PHYSICAL(pauseCtx->iconItemSegment);
+
+ for (itemId = 0; itemId <= ITEM_BOW_FIRE; itemId++) {
+ if (!gPlayerFormItemRestrictions[GET_PLAYER_FORM][(s32)itemId]) {
+ KaleidoScope_GrayOutTextureRGBA32(Lib_SegmentedToVirtual(gItemIcons[(s32)itemId]),
+ ICON_ITEM_TEX_WIDTH * ICON_ITEM_TEX_HEIGHT);
+ }
+ }
+
+ pauseCtx->iconItem24Segment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemSegment + size0);
+ size1 = SEGMENT_ROM_SIZE(icon_item_24_static_syms);
+ CmpDma_LoadAllFiles(SEGMENT_ROM_START(icon_item_24_static_yar), pauseCtx->iconItem24Segment, size1);
+
+ pauseCtx->iconItemAltSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItem24Segment + size1);
+ if (Map_CurRoomHasMapI(play)) {
+ size_t size = SEGMENT_ROM_SIZE(icon_item_dungeon_static);
+
+ DmaMgr_RequestSync(pauseCtx->iconItemAltSegment, SEGMENT_ROM_START(icon_item_dungeon_static), size);
+ iconItemLangSegment =
+ MapDisp_AllocDungeonMap(play, (void*)ALIGN16((uintptr_t)pauseCtx->iconItemAltSegment + size));
+ sInDungeonScene = true;
+ } else {
+ size_t size;
+
+ sInDungeonScene = false;
+ size = SEGMENT_ROM_SIZE(icon_item_field_static);
+ DmaMgr_RequestSync(pauseCtx->iconItemAltSegment, SEGMENT_ROM_START(icon_item_field_static), size);
+ iconItemLangSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemAltSegment + size);
+ }
+
+ pauseCtx->iconItemLangSegment = iconItemLangSegment;
+ size2 = SEGMENT_ROM_SIZE(icon_item_jpn_static);
+ DmaMgr_RequestSync(pauseCtx->iconItemLangSegment, SEGMENT_ROM_START(icon_item_jpn_static), size2);
+
+ pauseCtx->nameSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemLangSegment + size2);
+ Interface_SetAButtonDoAction(play, DO_ACTION_INFO);
+
+ //! note: `worldMapArea` never set to a value other than 0
+ if (((void)0, gSaveContext.worldMapArea) < 22) {
+ Kaleido_LoadMapNameStaticLarge(pauseCtx->nameSegment + 0x400, ((void)0, gSaveContext.worldMapArea));
+ }
+
+ pauseCtx->iconItemVtxSegment = (void*)ALIGN16((uintptr_t)pauseCtx->nameSegment + 0xA00);
+ DmaMgr_RequestSync(pauseCtx->iconItemVtxSegment, SEGMENT_ROM_START(icon_item_vtx_static),
+ SEGMENT_ROM_SIZE(icon_item_vtx_static));
+
+ pauseCtx->unk_2B6 = 255;
+ pauseCtx->unk_2B7 = 255;
+ pauseCtx->unk_2B8 = 255;
+ pauseCtx->state = PAUSE_STATE_OPENING_3;
+ break;
+
+ case PAUSE_STATE_OPENING_3:
+ pauseCtx->infoPanelOffsetY += 10;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll = pauseCtx->maskPageRoll -= 40.0f;
+
+ interfaceCtx->startAlpha += 63;
+ sPauseCursorLeftX += TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX += TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha += 31;
+ if (pauseCtx->itemPageRoll == 0) {
+ interfaceCtx->startAlpha = 255;
+ sPauseMenuVerticalOffset = 0.0f;
+ pauseCtx->state = PAUSE_STATE_OPENING_4;
+ }
+
+ KaleidoScope_UpdateOpening(play);
+ break;
+
+ case PAUSE_STATE_OPENING_4:
+ pauseCtx->alpha += 31;
+ KaleidoScope_UpdateOpening(play);
+
+ if (pauseCtx->state == PAUSE_STATE_MAIN) {
+ KaleidoScope_UpdateNamePanel(play);
+ }
+ break;
+
+ case PAUSE_STATE_MAIN:
+ switch (pauseCtx->mainState) {
+ case PAUSE_MAIN_STATE_IDLE:
+ if (!pauseCtx->itemDescriptionOn &&
+ (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B))) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_SETUP;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ }
+ break;
+
+ case PAUSE_MAIN_STATE_SWITCHING_PAGE:
+ KaleidoScope_UpdateSwitchPage(play, input);
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PLAYBACK:
+ // Song is in playback
+ pauseCtx->ocarinaStaff = AudioOcarina_GetPlaybackStaff();
+ if (pauseCtx->ocarinaStaff->state == 0) {
+ // Song playback is finished, give song prompt to player
+ pauseCtx->mainState = PAUSE_MAIN_STATE_SONG_PROMPT_INIT;
+ AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
+ }
+ break;
+
+ case PAUSE_MAIN_STATE_EQUIP_ITEM:
+ KaleidoScope_UpdateItemEquip(play);
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PROMPT_INIT:
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PROMPT:
+ pauseCtx->ocarinaStaff = AudioOcarina_GetPlayingStaff();
+
+ if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ // Abort having the player play the song and close the pause menu
+ AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_SETUP;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ } else if (pauseCtx->ocarinaStaff->state == pauseCtx->ocarinaSongIndex) {
+ // The player successfully played the song
+ Audio_PlaySfx(NA_SE_SY_TRE_BOX_APPEAR);
+ sNextMainState = PAUSE_MAIN_STATE_IDLE;
+ sDelayTimer = 30;
+ pauseCtx->mainState = PAUSE_MAIN_STATE_SONG_PROMPT_DONE;
+ } else if (pauseCtx->ocarinaStaff->state == 0xFF) {
+ // The player failed to play the song
+ Audio_PlaySfx(NA_SE_SY_OCARINA_ERROR);
+ sNextMainState = PAUSE_MAIN_STATE_SONG_PROMPT_INIT;
+ sDelayTimer = 20;
+ pauseCtx->mainState = PAUSE_MAIN_STATE_SONG_PROMPT_DONE;
+ }
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PROMPT_DONE:
+ sDelayTimer--;
+ if (sDelayTimer == 0) {
+ pauseCtx->mainState = sNextMainState;
+ if (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) {
+ AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
+ }
+ }
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PROMPT_UNUSED:
+ break;
+
+ case PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG:
+ if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ AudioOcarina_SetInstrument(OCARINA_INSTRUMENT_OFF);
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_SETUP;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ }
+ break;
+
+ case PAUSE_MAIN_STATE_SONG_PLAYBACK_INIT:
+ break;
+
+ case PAUSE_MAIN_STATE_EQUIP_MASK:
+ KaleidoScope_UpdateMaskEquip(play);
+ break;
+
+ case PAUSE_MAIN_STATE_BOMBERS_NOTEBOOK_OPEN:
+ if (!play->pauseCtx.bombersNotebookOpen) {
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ }
+ break;
+
+ default:
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ break;
+ }
+ break;
+
+ case PAUSE_STATE_SAVEPROMPT:
+ switch (pauseCtx->savePromptState) {
+ case PAUSE_SAVEPROMPT_STATE_APPEARING:
+ pauseCtx->roll -= 78.5f;
+ sPauseCursorLeftX -= TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX -= TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ if (pauseCtx->roll <= -628.0f) {
+ pauseCtx->roll = -628.0f;
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_1;
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_1:
+ if (CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_CUP)) {
+ if (pauseCtx->promptChoice != PAUSE_PROMPT_YES) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_RETURN_TO_MENU;
+ } else {
+ Audio_PlaySfx(NA_SE_SY_PIECE_OF_HEART);
+ Play_SaveCycleSceneFlags(play);
+ gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId;
+ func_8014546C(sramCtx);
+ if (!gSaveContext.flashSaveAvailable) {
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_5;
+ } else {
+ Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[gSaveContext.fileNum],
+ gFlashSaveNumPages[gSaveContext.fileNum]);
+ Sram_StartWriteToFlashDefault(sramCtx);
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_4;
+ }
+ sDelayTimer = 90;
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_START)) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_3;
+ sPauseMenuVerticalOffset = -6240.0f;
+ D_8082B90C = pauseCtx->roll;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_RETURN_TO_MENU;
+ D_8082B90C = pauseCtx->roll;
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_4:
+ if (sramCtx->status == 0) {
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_5;
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_5:
+ if (CHECK_BTN_ALL(input->press.button, BTN_B) || CHECK_BTN_ALL(input->press.button, BTN_A) ||
+ CHECK_BTN_ALL(input->press.button, BTN_START) || (--sDelayTimer == 0)) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_3;
+ sPauseMenuVerticalOffset = -6240.0f;
+ D_8082B90C = pauseCtx->roll;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_3:
+ case PAUSE_SAVEPROMPT_STATE_7:
+ if (pauseCtx->roll != (D_8082B90C + 160.0f)) {
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll =
+ pauseCtx->maskPageRoll += 40.0f;
+ pauseCtx->roll += 40.0f;
+ pauseCtx->infoPanelOffsetY -= 10;
+ sPauseCursorLeftX -= TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX -= TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha -= 63;
+ if (pauseCtx->roll == (D_8082B90C + 160.0f)) {
+ pauseCtx->alpha = 0;
+ }
+ } else {
+ pauseCtx->debugEditor = DEBUG_EDITOR_NONE;
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_CLOSE;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll =
+ pauseCtx->maskPageRoll = 160.0f;
+ pauseCtx->roll = -434.0f;
+ pauseCtx->namedItem = PAUSE_ITEM_NONE;
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_RETURN_TO_MENU:
+ pauseCtx->roll += 78.5f;
+ sPauseCursorLeftX += TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX += TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+
+ if (pauseCtx->roll >= -314.0f) {
+ pauseCtx->state = PAUSE_STATE_MAIN;
+ pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_APPEARING;
+ pauseCtx->roll = -314.0f;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll =
+ pauseCtx->maskPageRoll = 0.0f;
+ Interface_SetAButtonDoAction(play, DO_ACTION_INFO);
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] =
+ gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][0];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] =
+ gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] =
+ gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] =
+ gPageSwitchNextButtonStatus[pauseCtx->pageIndex + 1][1];
+ if ((pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_LEFT) ||
+ (pauseCtx->cursorSpecialPos == PAUSE_CURSOR_PAGE_RIGHT)) {
+ KaleidoScope_MoveCursorToSpecialPos(play, pauseCtx->cursorSpecialPos);
+ } else {
+ KaleidoScope_MoveCursorFromSpecialPos(play);
+ }
+ }
+ break;
+
+ case PAUSE_SAVEPROMPT_STATE_6:
+ if (interfaceCtx->screenFillAlpha != 255) {
+ interfaceCtx->screenFillAlpha += 10;
+ if (interfaceCtx->screenFillAlpha >= 255) {
+ interfaceCtx->screenFillAlpha = 255;
+ pauseCtx->state = PAUSE_STATE_OFF;
+ GameState_SetFramerateDivisor(&play->state, 3);
+ R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_UNK4;
+ Object_LoadAll(&play->objectCtx);
+ BgCheck_InitCollisionHeaders(&play->colCtx, play);
+ STOP_GAMESTATE(&play->state);
+ SET_NEXT_GAMESTATE(&play->state, TitleSetup_Init, sizeof(TitleSetupState));
+ Audio_MuteAllSeqExceptSystemAndOcarina(20);
+ gSaveContext.seqId = (u8)NA_BGM_DISABLED;
+ gSaveContext.ambienceId = AMBIENCE_ID_DISABLED;
+ }
+ }
+ break;
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_2:
+ pauseCtx->cursorSlot[PAUSE_MAP] = R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+ pauseCtx->cursorPoint[PAUSE_MAP] = R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+ sPauseCursorLeftX = -175;
+ sPauseCursorRightX = 155;
+ pauseCtx->roll = -434.0f;
+ Interface_SetHudVisibility(HUD_VISIBILITY_NONE);
+
+ pauseCtx->iconItemSegment =
+ (void*)(((uintptr_t)play->objectCtx.spaceStart + 0x30) & ~0x3F); // Messed up ALIGN64
+ size0 = SEGMENT_ROM_SIZE(icon_item_static_syms);
+ CmpDma_LoadAllFiles(SEGMENT_ROM_START(icon_item_static_yar), pauseCtx->iconItemSegment, size0);
+
+ pauseCtx->iconItem24Segment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemSegment + size0);
+ size1 = SEGMENT_ROM_SIZE(icon_item_24_static_syms);
+ CmpDma_LoadAllFiles(SEGMENT_ROM_START(icon_item_24_static_yar), pauseCtx->iconItem24Segment, size1);
+
+ pauseCtx->iconItemAltSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItem24Segment + size1);
+ size2 = SEGMENT_ROM_SIZE(icon_item_gameover_static);
+ DmaMgr_RequestSync(pauseCtx->iconItemAltSegment, SEGMENT_ROM_START(icon_item_gameover_static), size2);
+
+ pauseCtx->iconItemLangSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemAltSegment + size2);
+ DmaMgr_RequestSync(pauseCtx->iconItemLangSegment, SEGMENT_ROM_START(icon_item_jpn_static),
+ SEGMENT_ROM_SIZE(icon_item_jpn_static));
+
+ gSaveContext.timerStates[TIMER_ID_MOON_CRASH] = TIMER_STATE_OFF;
+
+ sGameOverPrimR = 255;
+ sGameOverPrimG = 130;
+ sGameOverPrimB = 0;
+ sGameOverPrimAlpha = 0;
+ sGameOverEnvR = 30;
+ sGameOverEnvG = 0;
+ sGameOverEnvB = 0;
+ sGameOverRectPosY = 98;
+ sGameOverColorTimer = 30;
+
+ pauseCtx->promptChoice = PAUSE_PROMPT_YES;
+ pauseCtx->state++;
+ if (gameOverCtx->state == GAMEOVER_INACTIVE) {
+ pauseCtx->state++; // GAMEOVER_DEATH_START
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_3:
+ stepR = ABS_ALT(sGameOverPrimR - 30) / sGameOverColorTimer;
+ stepG = ABS_ALT(sGameOverPrimG - 0) / sGameOverColorTimer;
+ stepB = ABS_ALT(sGameOverPrimB - 0) / sGameOverColorTimer;
+ stepA = ABS_ALT(sGameOverPrimAlpha - 255) / sGameOverColorTimer;
+ if (sGameOverPrimR >= 30) {
+ sGameOverPrimR -= stepR;
+ } else {
+ sGameOverPrimR += stepR;
+ }
+ if (sGameOverPrimG >= 0) {
+ sGameOverPrimG -= stepG;
+ } else {
+ sGameOverPrimG += stepG;
+ }
+ if (sGameOverPrimB >= 0) {
+ sGameOverPrimB -= stepB;
+ } else {
+ sGameOverPrimB += stepB;
+ }
+ if (sGameOverPrimAlpha >= 255) {
+ sGameOverPrimAlpha -= stepA;
+ } else {
+ sGameOverPrimAlpha += stepA;
+ }
+
+ stepR = ABS_ALT(sGameOverEnvR - 255) / sGameOverColorTimer;
+ stepG = ABS_ALT(sGameOverEnvG - 130) / sGameOverColorTimer;
+ stepB = ABS_ALT(sGameOverEnvB - 0) / sGameOverColorTimer;
+ if (sGameOverEnvR >= 255) {
+ sGameOverEnvR -= stepR;
+ } else {
+ sGameOverEnvR += stepR;
+ }
+ if (sGameOverEnvG >= 130) {
+ sGameOverEnvG -= stepG;
+ } else {
+ sGameOverEnvG += stepG;
+ }
+ if (sGameOverEnvB >= 0) {
+ sGameOverEnvB -= stepB;
+ } else {
+ sGameOverEnvB += stepB;
+ }
+
+ sGameOverColorTimer--;
+ if (sGameOverColorTimer == 0) {
+ sGameOverPrimR = 30;
+ sGameOverPrimG = 0;
+ sGameOverPrimB = 0;
+ sGameOverPrimAlpha = 255;
+
+ sGameOverEnvR = 255;
+ sGameOverEnvG = 130;
+ sGameOverEnvB = 0;
+
+ sGameOverColorTimer = 40;
+ pauseCtx->state++;
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_4:
+ sGameOverColorTimer--;
+ if (sGameOverColorTimer == 0) {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_5;
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_5:
+ pauseCtx->infoPanelOffsetY += 10;
+ pauseCtx->roll -= 40.0f;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll = pauseCtx->maskPageRoll =
+ pauseCtx->roll;
+ interfaceCtx->startAlpha += 63;
+ sGameOverRectPosY -= 3;
+ sPauseCursorLeftX += TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX += TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha += 31;
+ if (pauseCtx->roll < -628.0f) {
+ pauseCtx->roll = -628.0f;
+ interfaceCtx->startAlpha = 255;
+ sGameOverRectPosY = 66;
+ sPauseMenuVerticalOffset = 0.0f;
+ pauseCtx->alpha = 255;
+ if (gameOverCtx->state == GAMEOVER_INACTIVE) {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_SAVE_PROMPT;
+ } else {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT;
+ }
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_SAVE_PROMPT:
+ if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ if (pauseCtx->promptChoice != PAUSE_PROMPT_YES) {
+ pauseCtx->promptChoice = PAUSE_PROMPT_YES;
+ Audio_PlaySfx(NA_SE_SY_DECIDE);
+ pauseCtx->state = PAUSE_STATE_OFF;
+ GameState_SetFramerateDivisor(&play->state, 3);
+ R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_UNK4;
+ Object_LoadAll(&play->objectCtx);
+ BgCheck_InitCollisionHeaders(&play->colCtx, play);
+ } else {
+ Audio_PlaySfx(NA_SE_SY_PIECE_OF_HEART);
+ pauseCtx->promptChoice = PAUSE_PROMPT_YES;
+ Play_SaveCycleSceneFlags(play);
+ gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId;
+ gSaveContext.save.saveInfo.playerData.health = 0x30;
+ func_8014546C(sramCtx);
+ if (!gSaveContext.flashSaveAvailable) {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_8;
+ } else {
+ Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[gSaveContext.fileNum],
+ gFlashSaveNumPages[gSaveContext.fileNum]);
+ Sram_StartWriteToFlashDefault(sramCtx);
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_7;
+ }
+ sDelayTimer = 90;
+ }
+ } else if ((pauseCtx->promptChoice == PAUSE_PROMPT_YES) && (stickAdjX >= 30)) {
+ Audio_PlaySfx(NA_SE_SY_CURSOR);
+ pauseCtx->promptChoice = PAUSE_PROMPT_NO;
+ } else if ((pauseCtx->promptChoice != PAUSE_PROMPT_YES) && (stickAdjX <= -30)) {
+ Audio_PlaySfx(NA_SE_SY_CURSOR);
+ pauseCtx->promptChoice = PAUSE_PROMPT_YES;
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_7:
+ if (sramCtx->status == 0) {
+ pauseCtx->state = PAUSE_STATE_OFF;
+ GameState_SetFramerateDivisor(&play->state, 3);
+ R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_UNK4;
+ Object_LoadAll(&play->objectCtx);
+ BgCheck_InitCollisionHeaders(&play->colCtx, play);
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_8:
+ sDelayTimer--;
+ if (sDelayTimer == 0) {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT;
+ gameOverCtx->state++;
+ } else if ((sDelayTimer <= 80) &&
+ (CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_START))) {
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT;
+ gameOverCtx->state++;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_CONTINUE_PROMPT:
+ if (CHECK_BTN_ALL(input->press.button, BTN_A) || CHECK_BTN_ALL(input->press.button, BTN_START)) {
+ if (pauseCtx->promptChoice == PAUSE_PROMPT_YES) {
+ Audio_PlaySfx(NA_SE_SY_PIECE_OF_HEART);
+ Play_SaveCycleSceneFlags(play);
+ if (gSaveContext.save.entrance == ENTRANCE(UNSET_0D, 0)) {}
+ } else { // PAUSE_PROMPT_NO
+ Audio_PlaySfx(NA_SE_SY_DECIDE);
+ }
+ pauseCtx->state = PAUSE_STATE_GAMEOVER_10;
+ }
+ break;
+
+ case PAUSE_STATE_GAMEOVER_10:
+ if (interfaceCtx->screenFillAlpha != 255) {
+ interfaceCtx->screenFillAlpha += 10;
+ if (interfaceCtx->screenFillAlpha >= 255) {
+ interfaceCtx->screenFillAlpha = 255;
+
+ pauseCtx->state = PAUSE_STATE_OFF;
+ GameState_SetFramerateDivisor(&play->state, 3);
+ R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_UNK4;
+ Object_LoadAll(&play->objectCtx);
+ BgCheck_InitCollisionHeaders(&play->colCtx, play);
+
+ if (pauseCtx->promptChoice == PAUSE_PROMPT_YES) {
+ func_80169FDC(play);
+ gSaveContext.respawnFlag = -2;
+ gSaveContext.nextTransitionType = TRANS_TYPE_FADE_BLACK;
+ gSaveContext.save.saveInfo.playerData.health = 0x30;
+ Audio_SetSpec(0xA);
+ gSaveContext.healthAccumulator = 0;
+ gSaveContext.magicState = MAGIC_STATE_IDLE;
+ gSaveContext.magicFlag = 0;
+ gSaveContext.magicCapacity = 0;
+ gSaveContext.magicFillTarget = gSaveContext.save.saveInfo.playerData.magic;
+ gSaveContext.save.saveInfo.playerData.magicLevel = 0;
+ gSaveContext.save.saveInfo.playerData.magic = 0;
+ } else { // PAUSE_PROMPT_NO
+ STOP_GAMESTATE(&play->state);
+ SET_NEXT_GAMESTATE(&play->state, TitleSetup_Init, sizeof(TitleSetupState));
+ }
+ }
+ }
+ break;
+
+ case PAUSE_STATE_OWL_WARP_2:
+ sPauseMenuVerticalOffset = -6240.0f;
+
+ sUnpausedButtonStatus[EQUIP_SLOT_B] = gSaveContext.buttonStatus[EQUIP_SLOT_B];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_LEFT] = gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_DOWN] = gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN];
+ sUnpausedButtonStatus[EQUIP_SLOT_C_RIGHT] = gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT];
+ sUnpausedButtonStatus[EQUIP_SLOT_A] = gSaveContext.buttonStatus[EQUIP_SLOT_A];
+
+ pauseCtx->cursorXIndex[PAUSE_MAP] = 0;
+ pauseCtx->cursorSlot[PAUSE_MAP] = R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+ pauseCtx->cursorPoint[PAUSE_MAP] = pauseCtx->cursorMapDungeonItem =
+ R_PLAYER_FLOOR_REVERSE_INDEX + DUNGEON_FLOOR_INDEX_4;
+
+ sPauseCursorLeftX = -175;
+ sPauseCursorRightX = 155;
+
+ pauseCtx->iconItemSegment = (void*)ALIGN16((uintptr_t)play->objectCtx.spaceStart);
+ size0 = SEGMENT_ROM_SIZE(icon_item_static_syms);
+ CmpDma_LoadAllFiles(SEGMENT_ROM_START(icon_item_static_yar), pauseCtx->iconItemSegment, size0);
+
+ pauseCtx->iconItemAltSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemSegment + size0);
+ sInDungeonScene = false;
+ size1 = SEGMENT_ROM_SIZE(icon_item_field_static);
+ DmaMgr_RequestSync(pauseCtx->iconItemAltSegment, SEGMENT_ROM_START(icon_item_field_static), size1);
+
+ pauseCtx->iconItemLangSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemAltSegment + size1);
+ size2 = SEGMENT_ROM_SIZE(icon_item_jpn_static);
+ DmaMgr_RequestSync(pauseCtx->iconItemLangSegment, SEGMENT_ROM_START(icon_item_jpn_static), size2);
+
+ pauseCtx->nameSegment = (void*)ALIGN16((uintptr_t)pauseCtx->iconItemLangSegment + size2);
+ Interface_SetAButtonDoAction(play, DO_ACTION_WARP);
+ worldMapCursorPoint = pauseCtx->cursorPoint[PAUSE_WORLD_MAP];
+ Kaleido_LoadMapNameStatic(pauseCtx->nameSegment, worldMapCursorPoint);
+
+ pauseCtx->iconItemVtxSegment = (void*)ALIGN16((uintptr_t)pauseCtx->nameSegment + 0xA00);
+ DmaMgr_RequestSync(pauseCtx->iconItemVtxSegment, SEGMENT_ROM_START(icon_item_vtx_static),
+ SEGMENT_ROM_SIZE(icon_item_vtx_static));
+
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_3;
+ sGameOverRectPosY = 98;
+ pauseCtx->promptChoice = PAUSE_PROMPT_YES;
+ break;
+
+ case PAUSE_STATE_OWL_WARP_3:
+ R_PAUSE_OWL_WARP_ALPHA += 20;
+ pauseCtx->infoPanelOffsetY += 10;
+ pauseCtx->mapPageRoll -= 40.0f;
+ interfaceCtx->startAlpha += 63;
+ sGameOverRectPosY -= 3;
+ sPauseCursorLeftX += TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX += TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha += 31;
+
+ if (pauseCtx->mapPageRoll == 0) {
+ interfaceCtx->startAlpha = 255;
+ sPauseMenuVerticalOffset = 0.0f;
+ pauseCtx->alpha = 255;
+ pauseCtx->mainState = PAUSE_MAIN_STATE_IDLE;
+ pauseCtx->cursorSpecialPos = 0;
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_SELECT;
+ R_PAUSE_OWL_WARP_ALPHA = 120;
+ }
+ break;
+
+ case PAUSE_STATE_OWL_WARP_SELECT:
+ if (CHECK_BTN_ALL(input->press.button, BTN_START) || CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_6;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ play->msgCtx.ocarinaMode = OCARINA_MODE_END;
+ gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL;
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ Audio_PlaySfx(NA_SE_SY_DECIDE);
+ Message_StartTextbox(play, 0x1B93, NULL);
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_CONFIRM;
+ } else {
+ KaleidoScope_UpdateOwlWarpNamePanel(play);
+ }
+ break;
+
+ case PAUSE_STATE_OWL_WARP_CONFIRM:
+ if (CHECK_BTN_ALL(input->press.button, BTN_A)) {
+ msgCtx->msgLength = 0;
+ msgCtx->msgMode = MSGMODE_NONE;
+ if (msgCtx->choiceIndex == 0) {
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_6;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ play->msgCtx.ocarinaMode = sCursorPointsToOcarinaModes[pauseCtx->cursorPoint[PAUSE_WORLD_MAP]];
+ Audio_PlaySfx(NA_SE_SY_DECIDE);
+ } else {
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_SELECT;
+ Interface_SetAButtonDoAction(play, DO_ACTION_WARP);
+ Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
+ }
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) {
+ msgCtx->msgLength = 0;
+ msgCtx->msgMode = MSGMODE_NONE;
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_SELECT;
+ Audio_PlaySfx(NA_SE_SY_MESSAGE_PASS);
+ } else if (CHECK_BTN_ALL(input->press.button, BTN_START)) {
+ msgCtx->msgLength = 0;
+ msgCtx->msgMode = MSGMODE_NONE;
+ Interface_SetAButtonDoAction(play, DO_ACTION_NONE);
+ pauseCtx->state = PAUSE_STATE_OWL_WARP_6;
+ sPauseMenuVerticalOffset = -6240.0f;
+ Audio_PlaySfx_PauseMenuOpenOrClose(SFX_PAUSE_MENU_CLOSE);
+ play->msgCtx.ocarinaMode = OCARINA_MODE_END;
+ gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL;
+ }
+ break;
+
+ case PAUSE_STATE_OWL_WARP_6:
+ if (pauseCtx->mapPageRoll != 160.0f) {
+ R_PAUSE_OWL_WARP_ALPHA -= 60;
+ if (R_PAUSE_OWL_WARP_ALPHA <= 0) {
+ R_PAUSE_OWL_WARP_ALPHA = 0;
+ }
+ pauseCtx->infoPanelOffsetY -= 10;
+ pauseCtx->mapPageRoll += 40.0f;
+ interfaceCtx->startAlpha -= 63;
+ sPauseCursorLeftX -= TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX -= TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha -= 63;
+ if (pauseCtx->mapPageRoll == 160.0f) {
+ pauseCtx->alpha = 0;
+ }
+ } else {
+ pauseCtx->debugEditor = DEBUG_EDITOR_NONE;
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_CLOSE;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll = pauseCtx->maskPageRoll =
+ 160.0f;
+ pauseCtx->namedItem = PAUSE_ITEM_NONE;
+ interfaceCtx->startAlpha = 0;
+ pauseCtx->pageIndex = pauseCtx->unk_2C8;
+ pauseCtx->cursorPoint[PAUSE_WORLD_MAP] = pauseCtx->unk_2CA;
+ }
+ break;
+
+ case PAUSE_STATE_UNPAUSE_SETUP:
+ if (pauseCtx->itemPageRoll != 160.0f) {
+ pauseCtx->infoPanelOffsetY -= 10;
+ pauseCtx->itemPageRoll = pauseCtx->mapPageRoll = pauseCtx->questPageRoll = pauseCtx->maskPageRoll +=
+ 40.0f;
+ interfaceCtx->startAlpha -= 63;
+ sPauseCursorLeftX -= TRUNCF_BINANG(sPauseCursorLeftMoveOffsetX / 4);
+ sPauseCursorRightX -= TRUNCF_BINANG(sPauseCursorRightMoveOffsetX / 4);
+ pauseCtx->alpha -= 63;
+ if (pauseCtx->itemPageRoll == 160.0f) {
+ pauseCtx->alpha = 0;
+ }
+ } else {
+ pauseCtx->debugEditor = DEBUG_EDITOR_NONE;
+ pauseCtx->state = PAUSE_STATE_UNPAUSE_CLOSE;
+ pauseCtx->maskPageRoll = 160.0f;
+ pauseCtx->questPageRoll = 160.0f;
+ pauseCtx->mapPageRoll = 160.0f;
+ pauseCtx->itemPageRoll = 160.0f;
+ pauseCtx->namedItem = PAUSE_ITEM_NONE;
+ interfaceCtx->startAlpha = 0;
+ }
+ break;
+
+ case PAUSE_STATE_UNPAUSE_CLOSE:
+ pauseCtx->state = PAUSE_STATE_OFF;
+ GameState_SetFramerateDivisor(&play->state, 3);
+ R_PAUSE_BG_PRERENDER_STATE = PAUSE_BG_PRERENDER_UNK4;
+ Object_LoadAll(&play->objectCtx);
+ BgCheck_InitCollisionHeaders(&play->colCtx, play);
+
+ gSaveContext.buttonStatus[EQUIP_SLOT_B] = sUnpausedButtonStatus[EQUIP_SLOT_B];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_LEFT] = sUnpausedButtonStatus[EQUIP_SLOT_C_LEFT];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_DOWN] = sUnpausedButtonStatus[EQUIP_SLOT_C_DOWN];
+ gSaveContext.buttonStatus[EQUIP_SLOT_C_RIGHT] = sUnpausedButtonStatus[EQUIP_SLOT_C_RIGHT];
+ gSaveContext.buttonStatus[EQUIP_SLOT_A] = sUnpausedButtonStatus[EQUIP_SLOT_A];
+
+ Interface_UpdateButtonsPart2(play);
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+ Interface_SetHudVisibility(HUD_VISIBILITY_ALL);
+ Sched_FlushTaskQueue();
+ Skybox_Reload(play, &play->skyboxCtx, play->skyboxId);
+
+ if ((msgCtx->msgMode != MSGMODE_NONE) && (msgCtx->currentTextId == 0xFF)) {
+ Interface_SetBButtonInterfaceDoAction(play, DO_ACTION_STOP);
+ Interface_SetAButtonDoAction(play, DO_ACTION_STOP);
+ Interface_SetHudVisibility(HUD_VISIBILITY_A_B_C);
+ } else {
+ interfaceCtx->bButtonInterfaceDoActionActive = interfaceCtx->bButtonInterfaceDoAction = 0;
+ }
+ gSaveContext.hudVisibility = HUD_VISIBILITY_IDLE;
+ Interface_SetHudVisibility(sUnpausedHudVisibility);
+ Audio_SetPauseState(false);
+ break;
+
+ default:
+ break;
+ }
+
+ // If stickAdj is held, set a delay to allow the cursor to read the next input.
+ // The first delay is given a longer time than all subsequent delays.
+ if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx) && (pauseCtx->state != PAUSE_STATE_SAVEPROMPT)) {
+ if (pauseCtx->stickAdjX < -30) {
+ if (sStickXRepeatState == -1) {
+ sStickXRepeatTimer--;
+ if (sStickXRepeatTimer < 0) {
+ // Allow the input to register and apply the delay for all subsequent repeated inputs
+ sStickXRepeatTimer = 2;
+ } else {
+ // Cancel the current input
+ pauseCtx->stickAdjX = 0;
+ }
+ } else {
+ // Allow the input to register and apply the delay for the first repeated input
+ sStickXRepeatTimer = 10;
+ sStickXRepeatState = -1;
+ }
+ } else if (pauseCtx->stickAdjX > 30) {
+ if (sStickXRepeatState == 1) {
+ sStickXRepeatTimer--;
+ if (sStickXRepeatTimer < 0) {
+ // Allow the input to register and apply the delay for all subsequent repeated inputs
+ sStickXRepeatTimer = 2;
+ } else {
+ // Cancel the current input
+ pauseCtx->stickAdjX = 0;
+ }
+ } else {
+ // Allow the input to register and apply the delay for the first repeated input
+ sStickXRepeatTimer = 10;
+ sStickXRepeatState = 1;
+ }
+ } else {
+ sStickXRepeatState = 0;
+ }
+
+ if (pauseCtx->stickAdjY < -30) {
+ if (sStickYRepeatState == -1) {
+ sStickYRepeatTimer--;
+ if (sStickYRepeatTimer < 0) {
+ // Allow the input to register and apply the delay for all subsequent repeated inputs
+ sStickYRepeatTimer = 2;
+ } else {
+ // Cancel the current input
+ pauseCtx->stickAdjY = 0;
+ }
+ } else {
+ // Allow the input to register and apply the delay for the first repeated input
+ sStickYRepeatTimer = 10;
+ sStickYRepeatState = -1;
+ }
+ } else if (pauseCtx->stickAdjY > 30) {
+ if (sStickYRepeatState == 1) {
+ sStickYRepeatTimer--;
+ if (sStickYRepeatTimer < 0) {
+ // Allow the input to register and apply the delay for all subsequent repeated inputs
+ sStickYRepeatTimer = 2;
+ } else {
+ // Cancel the current input
+ pauseCtx->stickAdjY = 0;
+ }
+ } else {
+ // Allow the input to register and apply the delay for the first repeated input
+ sStickYRepeatTimer = 10;
+ sStickYRepeatState = 1;
+ }
+ } else {
+ sStickYRepeatState = 0;
+ }
+ }
+
+ // Process the Cursor input
+ if ((R_PAUSE_BG_PRERENDER_STATE == PAUSE_BG_PRERENDER_READY) && (pauseCtx->debugEditor == DEBUG_EDITOR_NONE) &&
+ !IS_PAUSE_STATE_OWL_WARP(pauseCtx) &&
+ (((pauseCtx->state >= PAUSE_STATE_OPENING_3) && (pauseCtx->state <= PAUSE_STATE_SAVEPROMPT)) ||
+ ((pauseCtx->state >= PAUSE_STATE_GAMEOVER_2) && (pauseCtx->state <= PAUSE_STATE_UNPAUSE_SETUP)))) {
+ if (!IS_PAUSE_STATE_GAMEOVER(pauseCtx)) {
+ switch (pauseCtx->pageIndex) {
+ case PAUSE_ITEM:
+ KaleidoScope_UpdateItemCursor(play);
+ break;
+
+ case PAUSE_MAP:
+ if (sInDungeonScene) {
+ KaleidoScope_UpdateDungeonCursor(play);
+ } else {
+ KaleidoScope_UpdateWorldMapCursor(play);
+ }
+ break;
+
+ case PAUSE_QUEST:
+ KaleidoScope_UpdateQuestCursor(play);
+ break;
+
+ case PAUSE_MASK:
+ KaleidoScope_UpdateMaskCursor(play);
+ break;
+ }
+
+ if ((pauseCtx->state == PAUSE_STATE_MAIN) &&
+ ((pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE) ||
+ (pauseCtx->mainState == PAUSE_MAIN_STATE_IDLE_CURSOR_ON_SONG))) {
+ KaleidoScope_HandlePageToggles(play, input);
+ }
+ }
+ if (pauseCtx->state == PAUSE_STATE_MAIN) {
+ KaleidoScope_UpdateNamePanel(play);
+ }
+ } else if (pauseCtx->state == PAUSE_STATE_OWL_WARP_SELECT) {
+ KaleidoScope_UpdateWorldMapCursor(play);
+ KaleidoScope_UpdateNamePanel(play);
+ }
+
+ // Update the inventory editor
+ if ((pauseCtx->debugEditor == DEBUG_EDITOR_INVENTORY_INIT) || (pauseCtx->debugEditor == DEBUG_EDITOR_INVENTORY)) {
+ KaleidoScope_UpdateInventoryEditor(play);
+ }
+}