diff --git a/assets/xml/misc/title_static.xml b/assets/xml/misc/title_static.xml new file mode 100644 index 0000000000..5e6cea55f7 --- /dev/null +++ b/assets/xml/misc/title_static.xml @@ -0,0 +1,126 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/xml/overlays/ovl_file_choose.xml b/assets/xml/overlays/ovl_file_choose.xml new file mode 100644 index 0000000000..cac6f3d9dc --- /dev/null +++ b/assets/xml/overlays/ovl_file_choose.xml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/include/functions.h b/include/functions.h index ccf1877e01..7d64745f69 100644 --- a/include/functions.h +++ b/include/functions.h @@ -2218,7 +2218,8 @@ s32 SysFlashrom_IsBusy(void); s32 SysFlashrom_AwaitResult(void); void SysFlashrom_WriteDataSync(void* addr, u32 pageNum, u32 pageCount); -s32 func_80185F90(u32 param_1); +s32 func_80185F90(u32 arg0); + u32 osFlashGetAddr(u32 pageNum); OSPiHandle* osFlashReInit(u8 latency, u8 pulse, u8 pageSize, u8 relDuration, u32 start); void osFlashChange(u32 flashNum); diff --git a/include/z64.h b/include/z64.h index b5597f58cf..a83001a010 100644 --- a/include/z64.h +++ b/include/z64.h @@ -273,45 +273,45 @@ typedef struct { /* 0x00 */ u16 unk_0; /* 0x02 */ u16 sceneTimeSpeed; /* 0x04 */ Vec3f sunPos; - /* 0x10 */ u8 unk_10; - /* 0x11 */ u8 unk_11; + /* 0x10 */ u8 skybox1Index; + /* 0x11 */ u8 skybox2Index; /* 0x12 */ u8 unk_12; - /* 0x13 */ u8 unk_13; + /* 0x13 */ u8 skyboxBlend; /* 0x14 */ u8 unk_14; /* 0x15 */ u8 skyboxDisabled; /* 0x16 */ u8 sunMoonDisabled; - /* 0x17 */ u8 unk_17; - /* 0x18 */ u8 unk_18; - /* 0x19 */ u8 unk_19; - /* 0x1A */ u16 unk_1A; + /* 0x17 */ u8 skyboxConfig; + /* 0x18 */ u8 changeSkyboxNextConfig; + /* 0x19 */ u8 changeSkyboxState; + /* 0x1A */ u16 changeSkyboxTimer; /* 0x1C */ u16 unk_1C; - /* 0x1E */ u8 unk_1E; - /* 0x1F */ u8 unk_1F; - /* 0x20 */ u8 unk_20; - /* 0x21 */ u8 unk_21; - /* 0x22 */ u16 unk_22; - /* 0x24 */ u16 unk_24; + /* 0x1E */ u8 lightMode; + /* 0x1F */ u8 lightConfig; + /* 0x20 */ u8 changeLightNextConfig; + /* 0x21 */ u8 changeLightEnabled; + /* 0x22 */ u16 changeLightTimer; + /* 0x24 */ u16 changeDuration; /* 0x26 */ u8 unk_26; /* 0x28 */ LightInfo dirLight1; // sun 1 /* 0x36 */ LightInfo unk_36; // sun 2 - /* 0x44 */ s8 unk_44; - /* 0x48 */ DmaRequest unk_48; - /* 0x68 */ OSMesgQueue unk_68; - /* 0x80 */ OSMesg unk_80; - /* 0x84 */ f32 unk_84; - /* 0x88 */ f32 unk_88; + /* 0x44 */ s8 skyboxDmaState; + /* 0x48 */ DmaRequest dmaRequest; + /* 0x68 */ OSMesgQueue loadQueue; + /* 0x80 */ OSMesg loadMsg; + /* 0x84 */ f32 glareAlpha; + /* 0x88 */ f32 lensFlareAlphaScale; /* 0x8C */ EnvLightSettings lightSettings; /* 0xA8 */ f32 unk_A8; /* 0xAC */ Vec3s windDir; /* 0xB4 */ f32 windSpeed; /* 0xB8 */ u8 numLightSettings; /* 0xBC */ LightSettings* lightSettingsList; - /* 0xC0 */ u8 unk_C0; - /* 0xC1 */ u8 unk_C1; - /* 0xC2 */ u8 unk_C2; + /* 0xC0 */ u8 lightBlendEnabled; + /* 0xC1 */ u8 lightSetting; + /* 0xC2 */ u8 prevLightSetting; /* 0xC3 */ u8 lightSettingOverride; /* 0xC4 */ LightSettings unk_C4; - /* 0xDA */ u16 unk_DA; + /* 0xDA */ u16 lightBlendRateOverride; /* 0xDC */ f32 lightBlend; /* 0xE0 */ u8 unk_E0; /* 0xE1 */ u8 unk_E1; diff --git a/include/z64save.h b/include/z64save.h index fdb99fea04..cea6ffa46c 100644 --- a/include/z64save.h +++ b/include/z64save.h @@ -10,6 +10,13 @@ struct GameState; struct PlayState; struct FileSelectState; +typedef enum { + /* 0 */ SAVE_AUDIO_STEREO, + /* 1 */ SAVE_AUDIO_MONO, + /* 2 */ SAVE_AUDIO_HEADSET, + /* 3 */ SAVE_AUDIO_SURROUND +} AudioOption; + // TODO: properly name DOWN, RETURN and TOP typedef enum RespawnMode { /* 0 */ RESPAWN_MODE_DOWN, // "RESTART_MODE_DOWN" @@ -157,13 +164,13 @@ typedef enum { #define PICTO_PHOTO_COMPRESSED_SIZE (PICTO_PHOTO_SIZE * 5 / 8) typedef struct SramContext { - /* 0x00 */ u8* readBuff; - /* 0x04 */ u8 *saveBuf; + /* 0x00 */ u8* noFlashSaveBuf; // Never allocated memory + /* 0x04 */ u8* saveBuf; /* 0x08 */ char unk_08[4]; /* 0x0C */ s16 status; /* 0x10 */ u32 curPage; /* 0x14 */ u32 numPages; - /* 0x18 */ OSTime unk_18; + /* 0x18 */ OSTime startWriteOsTime; /* 0x20 */ s16 unk_20; /* 0x22 */ s16 unk_22; /* 0x24 */ s16 unk_24; @@ -226,14 +233,14 @@ typedef struct CycleSceneFlags { typedef struct SaveOptions { /* 0x0 */ u16 optionId; // "option_id" /* 0x2 */ u8 language; // "j_n" - /* 0x3 */ s8 audioSetting; // "s_sound" + /* 0x3 */ u8 audioSetting; // "s_sound" /* 0x4 */ u8 languageSetting; // "language" /* 0x5 */ u8 zTargetSetting; // "z_attention", 0: Switch; 1: Hold } SaveOptions; // size = 0x6 typedef struct SavePlayerData { /* 0x00 */ char newf[6]; // "newf" Will always be "ZELDA3 for a valid save - /* 0x06 */ u16 deaths; // "savect" + /* 0x06 */ u16 threeDayResetCount; // "savect" /* 0x08 */ char playerName[8]; // "player_name" /* 0x10 */ s16 healthCapacity; // "max_life" /* 0x12 */ s16 health; // "now_life" @@ -337,11 +344,11 @@ typedef struct SaveContext { /* 0x3DB4 */ f32 entranceSpeed; // "player_wipe_speedF" /* 0x3DB8 */ u16 entranceSound; // "player_wipe_door_SE" /* 0x3DBA */ u8 unk_3DBA; // "player_wipe_item" - /* 0x3DBB */ u8 unk_3DBB; // "next_walk" + /* 0x3DBB */ u8 retainWeatherMode; // "next_walk" /* 0x3DBC */ s16 dogParams; // OoT leftover. "dog_flag" /* 0x3DBE */ u8 envHazardTextTriggerFlags; // "guide_status" /* 0x3DBF */ u8 showTitleCard; // "name_display" - /* 0x3DC0 */ s16 unk_3DC0; // "shield_magic_timer" + /* 0x3DC0 */ s16 nayrusLoveTimer; // remnant of OoT, "shield_magic_timer" /* 0x3DC2 */ u8 unk_3DC2; // "pad1" /* 0x3DC8 */ OSTime postmanTimerStopOsTime; // The osTime when the timer stops for the postman minigame. "get_time" /* 0x3DD0 */ u8 timerStates[TIMER_ID_MAX]; // See the `TimerState` enum. "event_fg" @@ -374,13 +381,13 @@ typedef struct SaveContext { /* 0x3F3A */ u16 minigameScore; // "yabusame_total" /* 0x3F3C */ u16 minigameHiddenScore; // "yabusame_out_ct" /* 0x3F3E */ u8 unk_3F3E; // "no_save" - /* 0x3F3F */ u8 unk_3F3F; // "flash_flag" + /* 0x3F3F */ u8 flashSaveAvailable; // "flash_flag" /* 0x3F40 */ SaveOptions options; - /* 0x3F46 */ u16 unk_3F46; // "NottoriBgm" + /* 0x3F46 */ u16 forcedSeqId; // "NottoriBgm" /* 0x3F48 */ u8 cutsceneTransitionControl; // "fade_go" /* 0x3F4A */ u16 nextCutsceneIndex; // "next_daytime" /* 0x3F4C */ u8 cutsceneTrigger; // "doukidemo" - /* 0x3F4D */ u8 unk_3F4D; // "Kenjya_no" + /* 0x3F4D */ u8 chamberCutsceneNum; // remnant of OoT "Kenjya_no" /* 0x3F4E */ u16 nextDayTime; // "next_zelda_time" /* 0x3F50 */ u8 transFadeDuration; // "fade_speed" /* 0x3F51 */ u8 transWipeSpeed; // "wipe_speed" transition related @@ -1575,28 +1582,28 @@ void Sram_InitDebugSave(void); void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx); void Sram_OpenSave(struct FileSelectState* fileSelect, SramContext* sramCtx); void func_8014546C(SramContext* sramCtx); -void func_801457CC(struct FileSelectState* fileSelect, SramContext* sramCtx); -void func_80146580(struct FileSelectState* fileSelect2, SramContext* sramCtx, s32 fileNum); -void func_80146628(struct FileSelectState* fileSelect2, SramContext* sramCtx); +void func_801457CC(struct GameState* gameState, SramContext* sramCtx); +void Sram_EraseSave(struct FileSelectState* fileSelect2, SramContext* sramCtx, s32 fileNum); +void Sram_CopySave(struct FileSelectState* fileSelect2, SramContext* sramCtx); void Sram_InitSave(struct FileSelectState* fileSelect2, SramContext* sramCtx); -void func_80146DF8(SramContext* sramCtx); +void Sram_WriteSaveOptionsToBuffer(SramContext* sramCtx); void Sram_InitSram(struct GameState* gameState, SramContext* sramCtx); void Sram_Alloc(struct GameState* gameState, SramContext* sramCtx); void Sram_SaveSpecialEnterClockTown(struct PlayState* play); void Sram_SaveSpecialNewDay(struct PlayState* play); -void func_80147008(SramContext* sramCtx, u32 curPage, u32 numPages); -void func_80147020(SramContext* sramCtx); -void func_80147068(SramContext* sramCtx); -void func_80147138(SramContext* sramCtx, s32 curPage, s32 numPages); -void func_80147150(SramContext* sramCtx); -void func_80147198(SramContext* sramCtx); +void Sram_SetFlashPagesDefault(SramContext* sramCtx, u32 curPage, u32 numPages); +void Sram_StartWriteToFlashDefault(SramContext* sramCtx); +void Sram_UpdateWriteToFlashDefault(SramContext* sramCtx); +void Sram_SetFlashPagesOwlSave(SramContext* sramCtx, s32 curPage, s32 numPages); +void Sram_StartWriteToFlashOwlSave(SramContext* sramCtx); +void Sram_UpdateWriteToFlashOwlSave(SramContext* sramCtx); -extern s32 D_801C6798[]; +extern u32 gSramSlotOffsets[]; extern u8 gAmmoItems[]; -extern s32 D_801C67C8[]; -extern s32 D_801C67F0[]; -extern s32 D_801C6818[]; -extern s32 D_801C6840[]; -extern s32 D_801C6850[]; +extern s32 gFlashSaveStartPages[]; +extern s32 gFlashSaveNumPages[]; +extern s32 gFlashSpecialSaveNumPages[]; +extern s32 gFlashOwlSaveStartPages[]; +extern s32 gFlashOwlSaveNumPages[]; #endif diff --git a/include/z64scene.h b/include/z64scene.h index 7f48d87402..5505f08e31 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -130,8 +130,8 @@ typedef struct { /* 0x1 */ u8 data1; /* 0x2 */ UNK_TYPE1 pad2[2]; /* 0x4 */ u8 skyboxId; - /* 0x5 */ u8 unk5; - /* 0x6 */ u8 unk6; + /* 0x5 */ u8 skyboxConfig; + /* 0x6 */ u8 envLightMode; } SCmdSkyboxSettings; // size = 0x7 typedef struct { @@ -719,6 +719,8 @@ typedef enum { */ #define ENTRANCE(scene, spawn) ((((ENTR_SCENE_##scene) & 0x7F) << 9) | (((spawn) & 0x1F) << 4)) +#define ENTR_LOAD_OPENING -1 + /* * Entrances used in cutscene destination. Includes scene layer that's immediately applied to `nextCutsceneIndex` and removed. * See `CutsceneScriptEntry.nextEntrance` diff --git a/spec b/spec index 601a46f403..a3cde9e587 100644 --- a/spec +++ b/spec @@ -664,12 +664,15 @@ endseg beginseg name "ovl_file_choose" compress + include "build/src/overlays/gamestates/ovl_file_choose/z_file_nameset_data.o" + include "build/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.o" include "build/src/overlays/gamestates/ovl_file_choose/z_file_nameset_NES.o" - include "build/src/overlays/gamestates/ovl_file_choose/z_file_choose_80807940.o" include "build/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.o" - include "build/data/ovl_file_choose/ovl_file_choose.data.o" - include "build/data/ovl_file_choose/ovl_file_choose.bss.o" - include "build/data/ovl_file_choose/ovl_file_choose.reloc.o" + #ifdef NON_MATCHING + include "build/src/overlays/gamestates/ovl_file_choose/ovl_file_choose_reloc.o" + #else + include "build/data/ovl_file_choose/ovl_file_choose.reloc.o" + #endif endseg beginseg @@ -8824,7 +8827,8 @@ beginseg name "title_static" compress romalign 0x1000 - include "build/baserom/title_static.o" + include "build/assets/misc/title_static/title_static.o" + number 1 endseg beginseg diff --git a/src/code/graph.c b/src/code/graph.c index bf9067b698..2e104234e2 100644 --- a/src/code/graph.c +++ b/src/code/graph.c @@ -2,7 +2,7 @@ #include "buffers.h" #include "system_malloc.h" #include "overlays/gamestates/ovl_daytelop/z_daytelop.h" -#include "overlays/gamestates/ovl_file_choose/z_file_choose.h" +#include "overlays/gamestates/ovl_file_choose/z_file_select.h" #include "overlays/gamestates/ovl_opening/z_opening.h" #include "overlays/gamestates/ovl_select/z_select.h" #include "overlays/gamestates/ovl_title/z_title.h" diff --git a/src/code/z_common_data.c b/src/code/z_common_data.c index 0e682231f4..46dfe189ef 100644 --- a/src/code/z_common_data.c +++ b/src/code/z_common_data.c @@ -8,10 +8,10 @@ void SaveContext_Init(void) { gSaveContext.save.playerForm = 0; gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.ambienceId = AMBIENCE_ID_DISABLED; - gSaveContext.unk_3F46 = NA_BGM_GENERAL_SFX; + gSaveContext.forcedSeqId = NA_BGM_GENERAL_SFX; gSaveContext.nextCutsceneIndex = 0xFFEF; gSaveContext.cutsceneTrigger = 0; - gSaveContext.unk_3F4D = 0; + gSaveContext.chamberCutsceneNum = 0; gSaveContext.nextDayTime = 0xFFFF; gSaveContext.skyboxTime = 0; gSaveContext.dogIsLost = true; @@ -19,6 +19,6 @@ void SaveContext_Init(void) { gSaveContext.prevHudVisibility = HUD_VISIBILITY_ALL; gSaveContext.options.language = 1; - gSaveContext.options.audioSetting = 0; + gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; gSaveContext.options.zTargetSetting = 0; } diff --git a/src/code/z_demo.c b/src/code/z_demo.c index 733ec4bc13..00ee877e93 100644 --- a/src/code/z_demo.c +++ b/src/code/z_demo.c @@ -171,15 +171,15 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { case CS_MISC_CLOUDY_SKY: if (isFirstFrame) { - play->envCtx.unk_19 = 1; - play->envCtx.unk_17 = 1; - play->envCtx.unk_18 = 0; - play->envCtx.unk_1A = 0x3C; - play->envCtx.unk_21 = 1; - play->envCtx.unk_1F = 0; - play->envCtx.unk_20 = 1; - play->envCtx.unk_24 = 0x3C; - play->envCtx.unk_22 = play->envCtx.unk_24; + play->envCtx.changeSkyboxState = 1; + play->envCtx.skyboxConfig = 1; + play->envCtx.changeSkyboxNextConfig = 0; + play->envCtx.changeSkyboxTimer = 60; + play->envCtx.changeLightEnabled = true; + play->envCtx.lightConfig = 0; + play->envCtx.changeLightNextConfig = 1; + play->envCtx.changeDuration = 60; + play->envCtx.changeLightTimer = play->envCtx.changeDuration; } break; @@ -327,8 +327,7 @@ void CutsceneCmd_Misc(PlayState* play, CutsceneContext* csCtx, CsCmdMisc* cmd) { case CS_MISC_MOON_CRASH_SKYBOX: if (isFirstFrame) { - // skyboxConfig - play->envCtx.unk_17 = 0xD; + play->envCtx.skyboxConfig = 0xD; } break; diff --git a/src/code/z_game_dlftbls.c b/src/code/z_game_dlftbls.c index 1b82705f56..7336b01f6f 100644 --- a/src/code/z_game_dlftbls.c +++ b/src/code/z_game_dlftbls.c @@ -1,6 +1,6 @@ #include "global.h" #include "overlays/gamestates/ovl_daytelop/z_daytelop.h" -#include "overlays/gamestates/ovl_file_choose/z_file_choose.h" +#include "overlays/gamestates/ovl_file_choose/z_file_select.h" #include "overlays/gamestates/ovl_opening/z_opening.h" #include "overlays/gamestates/ovl_select/z_select.h" #include "overlays/gamestates/ovl_title/z_title.h" diff --git a/src/code/z_game_over.c b/src/code/z_game_over.c index d0e5e45f22..c3c6819be6 100644 --- a/src/code/z_game_over.c +++ b/src/code/z_game_over.c @@ -49,7 +49,7 @@ void GameOver_Update(PlayState* play) { } } - gSaveContext.unk_3DC0 = 2000; + gSaveContext.nayrusLoveTimer = 2000; gSaveContext.save.saveInfo.playerData.tatlTimer = 0; gSaveContext.seqId = (u8)NA_BGM_DISABLED; gSaveContext.ambienceId = AMBIENCE_ID_DISABLED; diff --git a/src/code/z_lifemeter.c b/src/code/z_lifemeter.c index c9bea16694..7226a6719d 100644 --- a/src/code/z_lifemeter.c +++ b/src/code/z_lifemeter.c @@ -16,14 +16,14 @@ s16 sBeatingHeartsDDEnv[3]; s16 sHeartsDDPrim[2][3]; s16 sHeartsDDEnv[2][3]; -TexturePtr sHeartTextures[] = { +static TexturePtr sHeartTextures[] = { gHeartFullTex, gHeartQuarterTex, gHeartQuarterTex, gHeartQuarterTex, gHeartQuarterTex, gHeartQuarterTex, gHeartHalfTex, gHeartHalfTex, gHeartHalfTex, gHeartHalfTex, gHeartHalfTex, gHeartThreeQuarterTex, gHeartThreeQuarterTex, gHeartThreeQuarterTex, gHeartThreeQuarterTex, gHeartThreeQuarterTex, }; -TexturePtr sHeartDDTextures[] = { +static TexturePtr sHeartDDTextures[] = { gDefenseHeartFullTex, gDefenseHeartQuarterTex, gDefenseHeartQuarterTex, gDefenseHeartQuarterTex, gDefenseHeartQuarterTex, gDefenseHeartQuarterTex, gDefenseHeartHalfTex, gDefenseHeartHalfTex, gDefenseHeartHalfTex, diff --git a/src/code/z_parameter.c b/src/code/z_parameter.c index 9672b8804c..f8f28f4b8d 100644 --- a/src/code/z_parameter.c +++ b/src/code/z_parameter.c @@ -147,7 +147,7 @@ s16 D_801BF97C = 255; f32 D_801BF980 = 1.0f; s32 D_801BF984 = 0; -Gfx sScreenFillSetupDL[] = { +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), diff --git a/src/code/z_play.c b/src/code/z_play.c index dade44cf6f..dd9b6c561c 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -7,7 +7,7 @@ #include "z64view.h" #include "overlays/gamestates/ovl_daytelop/z_daytelop.h" #include "overlays/gamestates/ovl_opening/z_opening.h" -#include "overlays/gamestates/ovl_file_choose/z_file_choose.h" +#include "overlays/gamestates/ovl_file_choose/z_file_select.h" #include "overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope.h" s32 gDbgCamEnabled = false; @@ -1036,9 +1036,9 @@ void Play_UpdateMain(PlayState* this) { if (this->sramCtx.status != 0) { if (gSaveContext.save.isOwlSave) { - func_80147198(&this->sramCtx); + Sram_UpdateWriteToFlashOwlSave(&this->sramCtx); } else { - func_80147068(&this->sramCtx); + Sram_UpdateWriteToFlashDefault(&this->sramCtx); } } } @@ -1272,8 +1272,8 @@ void Play_DrawMain(PlayState* this) { if ((this->skyboxId != SKYBOX_NONE) && !this->envCtx.skyboxDisabled) { if ((this->skyboxId == SKYBOX_NORMAL_SKY) || (this->skyboxId == SKYBOX_3)) { Environment_UpdateSkybox(this->skyboxId, &this->envCtx, &this->skyboxCtx); - Skybox_Draw(&this->skyboxCtx, gfxCtx, this->skyboxId, this->envCtx.unk_13, this->view.eye.x, - this->view.eye.y, this->view.eye.z); + Skybox_Draw(&this->skyboxCtx, gfxCtx, this->skyboxId, this->envCtx.skyboxBlend, + this->view.eye.x, this->view.eye.y, this->view.eye.z); } else if (!this->skyboxCtx.skyboxShouldDraw) { Skybox_Draw(&this->skyboxCtx, gfxCtx, this->skyboxId, 0, this->view.eye.x, this->view.eye.y, this->view.eye.z); @@ -2217,7 +2217,7 @@ void Play_Init(GameState* thisx) { if (((gSaveContext.gameMode != GAMEMODE_NORMAL) && (gSaveContext.gameMode != GAMEMODE_TITLE_SCREEN)) || (gSaveContext.save.cutsceneIndex >= 0xFFF0)) { - gSaveContext.unk_3DC0 = 0; + gSaveContext.nayrusLoveTimer = 0; Magic_Reset(this); gSaveContext.sceneLayer = (gSaveContext.save.cutsceneIndex & 0xF) + 1; diff --git a/src/code/z_scene.c b/src/code/z_scene.c index 623db6b24b..368b4509e2 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -365,8 +365,8 @@ void Scene_LoadAreaTextures(PlayState* play, s32 fileIndex) { // SceneTableEntry Header Command 0x11: Skybox Settings void Scene_CommandSkyboxSettings(PlayState* play, SceneCmd* cmd) { play->skyboxId = cmd->skyboxSettings.skyboxId & 3; - play->envCtx.unk_17 = play->envCtx.unk_18 = cmd->skyboxSettings.unk5; - play->envCtx.unk_1E = cmd->skyboxSettings.unk6; + play->envCtx.skyboxConfig = play->envCtx.changeSkyboxNextConfig = cmd->skyboxSettings.skyboxConfig; + play->envCtx.lightMode = cmd->skyboxSettings.envLightMode; Scene_LoadAreaTextures(play, cmd->skyboxSettings.data1); } diff --git a/src/code/z_sram_NES.c b/src/code/z_sram_NES.c index f47a8e2010..21bfaf7efa 100644 --- a/src/code/z_sram_NES.c +++ b/src/code/z_sram_NES.c @@ -1,9 +1,9 @@ #include "prevent_bss_reordering.h" #include "global.h" #include "z64horse.h" -#include "overlays/gamestates/ovl_file_choose/z_file_choose.h" +#include "overlays/gamestates/ovl_file_choose/z_file_select.h" -void func_80146EBC(SramContext* sramCtx, s32 curPage, s32 numPages); +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); @@ -140,9 +140,21 @@ u16 D_801C66D0[ARRAY_COUNT(gSaveContext.save.saveInfo.weekEventReg)] = { /* 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 -s32 D_801C6798[] = { - 0x00000020, 0x00001470, 0x000028C0, 0x00003D10, 0x00005160, 0x000065B0, +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[] = { @@ -172,28 +184,89 @@ u8 gAmmoItems[] = { ITEM_NONE, // SLOT_BOTTLE_6 }; -s32 D_801C67C8[] = { 0, 0x40, 0x80, 0xC0, 0x100, 0x180, 0x200, 0x280, 0x300, 0x380 }; - -s32 D_801C67F0[] = { 0x40, 0x40, 0x40, 0x40, 0x80, 0x80, 0x80, 0x80, 1, 1 }; - -s32 D_801C6818[] = { 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 1, 1 }; - -s32 D_801C6840[] = { 0x100, 0x180, 0x200, 0x280 }; - -s32 D_801C6850[] = { 0x80, 0x80, 0x80, 0x80, 0x300, 0x380, 1, 1 }; - -s32 D_801C6870[] = { - sizeof(Save), - sizeof(Save), - sizeof(Save), - sizeof(Save), - offsetof(SaveContext, fileNum), - offsetof(SaveContext, fileNum), - offsetof(SaveContext, fileNum), - offsetof(SaveContext, fileNum), +// 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) }; -u8 D_801C6890[8] = { 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80 }; +// 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 +}; + +u8 D_801C6890[8] = { 1 << 0, 1 << 1, 1 << 2, 1 << 3, 1 << 4, 1 << 5, 1 << 6, 1 << 7 }; u16 D_801F6AF0; u8 D_801F6AF2; @@ -245,9 +318,9 @@ void Sram_SaveEndOfCycle(PlayState* play) { gSaveContext.save.day = 0; gSaveContext.save.time = CLOCK_TIME(6, 0) - 1; - gSaveContext.save.saveInfo.playerData.deaths++; - if (gSaveContext.save.saveInfo.playerData.deaths > 999) { - gSaveContext.save.saveInfo.playerData.deaths = 999; + gSaveContext.save.saveInfo.playerData.threeDayResetCount++; + if (gSaveContext.save.saveInfo.playerData.threeDayResetCount > 999) { + gSaveContext.save.saveInfo.playerData.threeDayResetCount = 999; } sceneId = Play_GetOriginalSceneId(play->sceneId); @@ -577,7 +650,7 @@ void Sram_GenerateRandomSaveFields(void) { SavePlayerData sSaveDefaultPlayerData = { { '\0', '\0', '\0', '\0', '\0', '\0' }, // newf - 0, // deaths + 0, // threeDayResetCount { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName " " 0x30, // healthCapacity 0x30, // health @@ -678,7 +751,7 @@ void Sram_InitNewSave(void) { SavePlayerData sSaveDebugPlayerData = { { 'Z', 'E', 'L', 'D', 'A', '3' }, // newf - 0x0000, // deaths + 0, // threeDayResetCount { 0x15, 0x12, 0x17, 0x14, 0x3E, 0x3E, 0x3E, 0x3E }, // playerName "LINK " 0x80, // healthCapacity 0x80, // health @@ -775,7 +848,18 @@ Inventory sSaveDebugInventory = { (1 << QUEST_SONG_SOARING) | (1 << QUEST_SONG_STORMS) | (1 << QUEST_BOMBERS_NOTEBOOK) | (1 << QUEST_SONG_LULLABY_INTRO), // dungeonItems - { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 }, + { + (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 @@ -851,15 +935,15 @@ void Sram_ResetSaveFromMoonCrash(SramContext* sramCtx) { bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2], - D_801C67F0[gSaveContext.fileNum * 2]) != 0) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2 + 1], - D_801C67F0[gSaveContext.fileNum * 2 + 1]); + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2], + gFlashSaveNumPages[gSaveContext.fileNum * 2]) != 0) { + SysFlashrom_ReadData(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_ReadData(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2 + 1], - D_801C67F0[gSaveContext.fileNum * 2 + 1]); + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2 + 1], + gFlashSaveNumPages[gSaveContext.fileNum * 2 + 1]); Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save)); } gSaveContext.save.cutsceneIndex = cutsceneIndex; @@ -907,32 +991,34 @@ void Sram_OpenSave(FileSelectState* fileSelect, SramContext* sramCtx) { s32 pad1; s32 fileNum; - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); if (gSaveContext.fileNum == 0xFF) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[0], D_801C67F0[0]); - } else if (fileSelect->unk_2446A[gSaveContext.fileNum] != 0) { + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[0], gFlashSaveNumPages[0]); + } else if (fileSelect->isOwlSave[gSaveContext.fileNum + 2]) { phi_t1 = gSaveContext.fileNum + 2; phi_t1 *= 2; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[phi_t1], D_801C67F0[phi_t1]) != 0) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]); + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1], gFlashSaveNumPages[phi_t1]) != 0) { + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], + gFlashSaveNumPages[phi_t1 + 1]); } } else { phi_t1 = gSaveContext.fileNum; phi_t1 *= 2; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[phi_t1], D_801C67F0[phi_t1]) != 0) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]); + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1], gFlashSaveNumPages[phi_t1]) != 0) { + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], + gFlashSaveNumPages[phi_t1 + 1]); } } - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[phi_t1]); + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[phi_t1]); if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf)) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[phi_t1 + 1], D_801C67F0[phi_t1 + 1]); - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[phi_t1]); + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[phi_t1 + 1], gFlashSaveNumPages[phi_t1 + 1]); + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[phi_t1]); } } @@ -963,7 +1049,7 @@ void Sram_OpenSave(FileSelectState* fileSelect, SramContext* sramCtx) { if (gSaveContext.save.isFirstCycle) { gSaveContext.save.entrance = ENTRANCE(SOUTH_CLOCK_TOWN, 0); gSaveContext.save.day = 0; - gSaveContext.save.time = 0x3FFF; + gSaveContext.save.time = CLOCK_TIME(6, 0) - 1; } else { gSaveContext.save.entrance = ENTRANCE(CUTSCENE, 0); gSaveContext.nextCutsceneIndex = 0; @@ -1028,7 +1114,7 @@ void func_8014546C(SramContext* sramCtx) { gSaveContext.save.saveInfo.checksum = 0; gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save)); - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save)); Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save)); } @@ -1051,7 +1137,7 @@ void func_80145698(SramContext* sramCtx) { gSaveContext.save.saveInfo.checksum = 0; gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save)); - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, sizeof(Save)); Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save)); } @@ -1059,31 +1145,21 @@ void func_80145698(SramContext* sramCtx) { // Verifies save and use backup if corrupted? #ifdef NON_EQUIVALENT -void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { - FileSelectState* fileSelect = fileSelect2; +void func_801457CC(GameState* gameState, SramContext* sramCtx) { + FileSelectState* fileSelect = (FileSelectState*)gameState; u16 sp7A; - // u16 sp78; + u16 oldCheckSum; // s2 u16 sp76; - // u16 sp74; - u16 sp6E; //! - // s32 sp68; - // u16 sp66; - u16 phi_s2; //! - u16 sp64; - // s32 sp60; - // s32 sp5C; - // s32 sp58; - // u32 new_var; - u16 phi_s2_3; - // s16 fakevar; + u16 sp64; // sp74? + u16 phi_s2; + u16 phi_s7; + u16 sp6E; + u16 newCheckSum; // v0 + u16 phi_a0; // maskCount - u16 temp_s2; - u16 temp_v0_2; - u16 phi_a0; // maskCount - - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { D_801F6AF0 = gSaveContext.save.time; - D_801F6AF2 = gSaveContext.unk_3F3F; + D_801F6AF2 = gSaveContext.flashSaveAvailable; sp64 = 0; for (sp76 = 0; sp76 < 5; sp76++, sp64 += 2) { @@ -1091,40 +1167,65 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { phi_s2 = false; sp6E = 0; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64])) { + // read main save from flash + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]) != 0) { + // main save didn't work sp6E = 1; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) { + // read backup save from flash + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], + gFlashSaveNumPages[sp64 + 1]) != 0) { + // backup save didn't work phi_s2 = true; } } if (sp76 < 2) { - fileSelect->unk_24468[sp76] = 0; + // 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, D_801C6870[sp64]); + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); } else { - // Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - temp_s2 = gSaveContext.save.saveInfo.checksum; + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); + + // test checksum of main save + oldCheckSum = gSaveContext.save.saveInfo.checksum; gSaveContext.save.saveInfo.checksum = 0; - temp_v0_2 = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]); - gSaveContext.save.saveInfo.checksum = temp_s2; + newCheckSum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]); + gSaveContext.save.saveInfo.checksum = oldCheckSum; - if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (temp_s2 != temp_v0_2)) { + if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (oldCheckSum != newCheckSum)) { + // checksum didnt match, try backup save sp6E = 1; - if (CHECK_NEWF2(gSaveContext.save.saveInfo.playerData.newf)) {} - phi_s2 = false; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) { + if ((gSaveContext.save.saveInfo.playerData.newf[0] == 'Z') && + (gSaveContext.save.saveInfo.playerData.newf[1] == 'E')) { + phi_s2 = false; + } + + // phi_s2 = false; + + // read backup save from flash + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], + gFlashSaveNumPages[sp64 + 1]) != 0) { + // backup save didn't work phi_s2 = true; } - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - temp_s2 = gSaveContext.save.saveInfo.checksum; + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); + + // test checksum of backup save + oldCheckSum = gSaveContext.save.saveInfo.checksum; gSaveContext.save.saveInfo.checksum = 0; + + //! FAKE: (s32)sp64 if (phi_s2 || CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || - (temp_s2 != Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]))) { + (oldCheckSum != Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[(s32)sp64]))) { + // backup save didn't work bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save)); sp6E = 999; @@ -1133,29 +1234,30 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { } gSaveContext.save.saveInfo.checksum = 0; + // FAKE: Needed? gSaveContext.save.saveInfo.checksum = - Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64 & 0xFFFFFFFF]); // TODO: Needed? + Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64 & 0xFFFFFFFF]); 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->unk_2440C[sp76] = gSaveContext.save.saveInfo.playerData.deaths; + fileSelect->threeDayResetCount[sp76] = gSaveContext.save.saveInfo.playerData.threeDayResetCount; for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); sp7A++) { - fileSelect->unk_24414[sp76][sp7A] = 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->unk_24454[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts; - fileSelect->unk_24444[sp76] = gSaveContext.save.saveInfo.inventory.questItems; - fileSelect->unk_24458[sp76] = gSaveContext.save.time; - fileSelect->unk_24460[sp76] = gSaveContext.save.day; - fileSelect->unk_24468[sp76] = gSaveContext.save.isOwlSave; + fileSelect->defenseHearts[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts; + fileSelect->questItems[sp76] = gSaveContext.save.saveInfo.inventory.questItems; + fileSelect->time[sp76] = gSaveContext.save.time; + fileSelect->day[sp76] = gSaveContext.save.day; + fileSelect->isOwlSave[sp76] = gSaveContext.save.isOwlSave; fileSelect->rupees[sp76] = gSaveContext.save.saveInfo.playerData.rupees; - fileSelect->unk_24474[sp76] = CUR_UPG_VALUE(4); + fileSelect->walletUpgrades[sp76] = CUR_UPG_VALUE(UPG_WALLET); for (sp7A = 0, phi_a0 = 0; sp7A < 24; sp7A++) { if (gSaveContext.save.saveInfo.inventory.items[sp7A + 24] != 0xFF) { @@ -1168,90 +1270,106 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { } if (sp6E == 1) { + // backup save Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save)); - func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C6818[sp64]); - } else if (sp6E == 0) { // TODO: == 0? - temp_s2 = gSaveContext.save.saveInfo.checksum; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) { - phi_s2_3 = 1; + Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSpecialSaveNumPages[sp64]); + } else if (!sp6E) { + // main save + phi_s7 = gSaveContext.save.saveInfo.checksum; + + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], + gFlashSaveNumPages[sp64 + 1]) != 0) { + oldCheckSum = 1; } else { Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save)); - phi_s2_3 = gSaveContext.save.saveInfo.checksum; + oldCheckSum = gSaveContext.save.saveInfo.checksum; gSaveContext.save.saveInfo.checksum = 0; sp7A = Sram_CalcChecksum(&gSaveContext.save, sizeof(Save)); } - if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (phi_s2_3 != sp7A) || - (phi_s2_3 != temp_s2)) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64]); + if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (oldCheckSum != sp7A) || + (oldCheckSum != phi_s7)) { + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]); Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save)); Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save)); - func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C6818[sp64]); + Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSpecialSaveNumPages[sp64]); } } } else if (sp76 < 4) { - fileSelect->unk_24468[sp76] = 0; + // Owl Save: + // sp76 = 3: main owl save + // sp76 = 4: backup owl save + fileSelect->isOwlSave[sp76] = 0; - if (!CHECK_NEWF(fileSelect->newf2[(s32)sp76])) { // TODO: Needed? + 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, - D_801C6870[sp64]); // TODO: Needed? + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); } else { - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - temp_s2 = gSaveContext.save.saveInfo.checksum; + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); + oldCheckSum = gSaveContext.save.saveInfo.checksum; + // test checksum of main save gSaveContext.save.saveInfo.checksum = 0; - temp_v0_2 = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]); - gSaveContext.save.saveInfo.checksum = temp_s2; - if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (temp_s2 != temp_v0_2)) { + newCheckSum = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]); + gSaveContext.save.saveInfo.checksum = oldCheckSum; + + if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (oldCheckSum != newCheckSum)) { + // checksum didnt match, try backup save sp6E = 1; if ((gSaveContext.save.saveInfo.playerData.newf[0] == 'Z') && (gSaveContext.save.saveInfo.playerData.newf[1] == 'E')) { phi_s2 = false; } - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) { + // read backup save from flash + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], + gFlashSaveNumPages[sp64 + 1])) { + // backup save didn't work phi_s2 = true; } - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - temp_s2 = gSaveContext.save.saveInfo.checksum; + 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) || - (temp_s2 != Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]))) { + (oldCheckSum != Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]))) { bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); sp6E = 999; } } } gSaveContext.save.saveInfo.checksum = 0; + // FAKE: Needed? gSaveContext.save.saveInfo.checksum = - Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64 & 0xFFFFFFFF]); // TODO: Needed? + Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64 & 0xFFFFFFFF]); 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->unk_2440C[sp76] = gSaveContext.save.saveInfo.playerData.deaths; + fileSelect->threeDayResetCount[sp76] = gSaveContext.save.saveInfo.playerData.threeDayResetCount; for (sp7A = 0; sp7A < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); sp7A++) { - phi_s2 += 0; // TODO: Needed? - fileSelect->unk_24414[sp76][sp7A] = 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->unk_24454[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts; - fileSelect->unk_24444[sp76] = gSaveContext.save.saveInfo.inventory.questItems; - fileSelect->unk_24458[sp76] = gSaveContext.save.time; - fileSelect->unk_24460[sp76] = gSaveContext.save.day; - fileSelect->unk_24468[sp76] = gSaveContext.save.isOwlSave; + fileSelect->defenseHearts[sp76] = gSaveContext.save.saveInfo.inventory.defenseHearts; + fileSelect->questItems[sp76] = gSaveContext.save.saveInfo.inventory.questItems; + fileSelect->time[sp76] = gSaveContext.save.time; + fileSelect->day[sp76] = gSaveContext.save.day; + fileSelect->isOwlSave[sp76] = gSaveContext.save.isOwlSave; fileSelect->rupees[sp76] = gSaveContext.save.saveInfo.playerData.rupees; - fileSelect->unk_24474[sp76] = CUR_UPG_VALUE(4); + fileSelect->walletUpgrades[sp76] = CUR_UPG_VALUE(UPG_WALLET); for (sp7A = 0, phi_a0 = 0; sp7A < 24; sp7A++) { if (gSaveContext.save.saveInfo.inventory.items[sp7A + 24] != 0xFF) { @@ -1264,39 +1382,44 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { } if (sp6E == 1) { - func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]); - func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]); - } else if (!sp6E) { // TODO: == 0? - temp_s2 = gSaveContext.save.saveInfo.checksum; - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1])) { - phi_s2_3 = 1; + // backup save + Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64], gFlashSaveNumPages[sp64]); + Sram_SyncWriteToFlash(sramCtx, gFlashSaveStartPages[sp64 + 1], gFlashSaveNumPages[sp64 + 1]); + } else if (!sp6E) { + // main save + phi_s7 = gSaveContext.save.saveInfo.checksum; + + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashSaveStartPages[sp64 + 1], + gFlashSaveNumPages[sp64 + 1])) { + oldCheckSum = 1; } else { - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - phi_s2_3 = gSaveContext.save.saveInfo.checksum; + Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, gFlashSaveSizes[sp64]); + oldCheckSum = gSaveContext.save.saveInfo.checksum; gSaveContext.save.saveInfo.checksum = 0; - // phi_s2_3 = gSaveContext.save.saveInfo.checksum; - sp7A = Sram_CalcChecksum(&gSaveContext, D_801C6870[sp64]); + sp7A = Sram_CalcChecksum(&gSaveContext, gFlashSaveSizes[sp64]); } - if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (phi_s2_3 != sp7A) || - (phi_s2_3 != temp_s2)) { - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[sp64], D_801C67F0[sp64]); - Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, D_801C6870[sp64]); - func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]); - func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]); + if (CHECK_NEWF(gSaveContext.save.saveInfo.playerData.newf) || (oldCheckSum != sp7A) || + (oldCheckSum != phi_s7)) { + SysFlashrom_ReadData(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, D_801C6870[sp64]); - func_80146EBC(sramCtx, D_801C67C8[sp64], D_801C67F0[sp64]); - func_80146EBC(sramCtx, D_801C67C8[sp64 + 1], D_801C67F0[sp64 + 1]); + 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 = 1; - gSaveContext.options.audioSetting = 0; + gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; gSaveContext.options.languageSetting = 0; gSaveContext.options.zTargetSetting = 0; } else { @@ -1304,7 +1427,7 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { if (gSaveContext.options.optionId != 0xA51D) { gSaveContext.options.optionId = 0xA51D; gSaveContext.options.language = 1; - gSaveContext.options.audioSetting = 0; + gSaveContext.options.audioSetting = SAVE_AUDIO_STEREO; gSaveContext.options.languageSetting = 0; gSaveContext.options.zTargetSetting = 0; } @@ -1314,7 +1437,7 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { } gSaveContext.save.time = D_801F6AF0; - gSaveContext.unk_3F3F = D_801F6AF2; + gSaveContext.flashSaveAvailable = D_801F6AF2; } gSaveContext.options.language = 1; @@ -1323,50 +1446,52 @@ void func_801457CC(FileSelectState* fileSelect2, SramContext* sramCtx) { #pragma GLOBAL_ASM("asm/non_matchings/code/z_sram_NES/func_801457CC.s") #endif -void func_80146580(FileSelectState* fileSelect2, SramContext* sramCtx, s32 fileNum) { +void Sram_EraseSave(FileSelectState* fileSelect2, SramContext* sramCtx, s32 fileNum) { FileSelectState* fileSelect = fileSelect2; s32 pad; - if (gSaveContext.unk_3F3F) { - if (fileSelect->unk_2446A[fileNum]) { + if (gSaveContext.flashSaveAvailable) { + if (fileSelect->isOwlSave[fileNum + 2]) { func_80147314(sramCtx, fileNum); - fileSelect->unk_2446A[fileNum] = 0; + fileSelect->isOwlSave[fileNum + 2] = false; } bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, sizeof(Save)); } gSaveContext.save.time = D_801F6AF0; - gSaveContext.unk_3F3F = D_801F6AF2; + gSaveContext.flashSaveAvailable = D_801F6AF2; } #ifdef NON_MATCHING // v0/v1 -void func_80146628(FileSelectState* fileSelect2, SramContext* sramCtx) { +void Sram_CopySave(FileSelectState* fileSelect2, SramContext* sramCtx) { FileSelectState* fileSelect = fileSelect2; u16 i; s16 maskCount; - if (gSaveContext.unk_3F3F) { - if (fileSelect->unk_2446A[fileSelect->unk_2448E]) { - func_80147414(sramCtx, fileSelect->unk_2448E, fileSelect->fileNum); - fileSelect->unk_24410[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.deaths; + 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->unk_24424[fileSelect->fileNum][i] = gSaveContext.save.saveInfo.playerData.playerName[i]; + fileSelect->fileNames[fileSelect->copyDestFileIndex + 2][i] = + gSaveContext.save.saveInfo.playerData.playerName[i]; } - fileSelect->unk_24438[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.healthCapacity; - fileSelect->unk_24440[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.health; - fileSelect->unk_24456[fileSelect->fileNum] = gSaveContext.save.saveInfo.inventory.defenseHearts; - fileSelect->unk_2444C[fileSelect->fileNum] = gSaveContext.save.saveInfo.inventory.questItems; - fileSelect->unk_2445C[fileSelect->fileNum] = gSaveContext.save.time; - fileSelect->unk_24464[fileSelect->fileNum] = gSaveContext.save.day; - fileSelect->unk_2446A[fileSelect->fileNum] = gSaveContext.save.isOwlSave; - fileSelect->unk_24470[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.rupees; - // = CUR_UPG_VALUE(UPG_WALLET); - fileSelect->unk_24476[fileSelect->fileNum] = - (gSaveContext.save.saveInfo.inventory.upgrades & gUpgradeMasks[4]) >> gUpgradeShifts[4]; + 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] = gSaveContext.save.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 < 24; i++) { if (gSaveContext.save.saveInfo.inventory.items[i + 24] != ITEM_NONE) { @@ -1374,42 +1499,42 @@ void func_80146628(FileSelectState* fileSelect2, SramContext* sramCtx) { } } - fileSelect->unk_2447A[fileSelect->fileNum] = maskCount; - fileSelect->unk_2447E[fileSelect->fileNum] = - (gSaveContext.save.saveInfo.inventory.questItems & 0xF0000000) >> 0x1C; + 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 - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C67C8[fileSelect->unk_2448E * 2], - D_801C67F0[fileSelect->unk_2448E * 2]); - + SysFlashrom_ReadData(&sramCtx->saveBuf[0], gFlashSaveStartPages[fileSelect->selectedFileIndex * 2], + gFlashSaveNumPages[fileSelect->selectedFileIndex * 2]); if (1) {} - SysFlashrom_ReadData(&sramCtx->saveBuf[0x2000], D_801C67C8[fileSelect->unk_2448E * 2 + 1], - D_801C67F0[fileSelect->unk_2448E * 2 + 1]); + + SysFlashrom_ReadData(&sramCtx->saveBuf[0x2000], gFlashSaveStartPages[fileSelect->selectedFileIndex * 2 + 1], + gFlashSaveNumPages[fileSelect->selectedFileIndex * 2 + 1]); if (1) {} // copy buffer to save context Lib_MemCpy(&gSaveContext.save, sramCtx->saveBuf, sizeof(Save)); - fileSelect->unk_2440C[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.deaths; + fileSelect->threeDayResetCount[fileSelect->copyDestFileIndex] = + gSaveContext.save.saveInfo.playerData.threeDayResetCount; for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); i++) { - fileSelect->unk_24414[fileSelect->fileNum][i] = gSaveContext.save.saveInfo.playerData.playerName[i]; + fileSelect->fileNames[fileSelect->copyDestFileIndex][i] = + gSaveContext.save.saveInfo.playerData.playerName[i]; } - fileSelect->healthCapacity[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.healthCapacity; - fileSelect->health[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.health; - fileSelect->unk_24454[fileSelect->fileNum] = gSaveContext.save.saveInfo.inventory.defenseHearts; - fileSelect->unk_24444[fileSelect->fileNum] = gSaveContext.save.saveInfo.inventory.questItems; - fileSelect->unk_24458[fileSelect->fileNum] = gSaveContext.save.time; - fileSelect->unk_24460[fileSelect->fileNum] = gSaveContext.save.day; - fileSelect->unk_24468[fileSelect->fileNum] = gSaveContext.save.isOwlSave; - fileSelect->rupees[fileSelect->fileNum] = gSaveContext.save.saveInfo.playerData.rupees; - // = CUR_UPG_VALUE(UPG_WALLET); - fileSelect->unk_24474[fileSelect->fileNum] = - (gSaveContext.save.saveInfo.inventory.upgrades & gUpgradeMasks[4]) >> gUpgradeShifts[4]; + 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] = gSaveContext.save.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 < 24; i++) { if (gSaveContext.save.saveInfo.inventory.items[i + 24] != ITEM_NONE) { @@ -1417,16 +1542,15 @@ void func_80146628(FileSelectState* fileSelect2, SramContext* sramCtx) { } } - fileSelect->maskCount[fileSelect->fileNum] = maskCount; - fileSelect->heartPieceCount[fileSelect->fileNum] = - (gSaveContext.save.saveInfo.inventory.questItems & 0xF0000000) >> 0x1C; + fileSelect->maskCount[fileSelect->copyDestFileIndex] = maskCount; + fileSelect->heartPieceCount[fileSelect->copyDestFileIndex] = GET_QUEST_HEART_PIECE_COUNT; } gSaveContext.save.time = D_801F6AF0; - gSaveContext.unk_3F3F = D_801F6AF2; + gSaveContext.flashSaveAvailable = D_801F6AF2; } #else -#pragma GLOBAL_ASM("asm/non_matchings/code/z_sram_NES/func_80146628.s") +#pragma GLOBAL_ASM("asm/non_matchings/code/z_sram_NES/Sram_CopySave.s") #endif void Sram_InitSave(FileSelectState* fileSelect2, SramContext* sramCtx) { @@ -1435,15 +1559,15 @@ void Sram_InitSave(FileSelectState* fileSelect2, SramContext* sramCtx) { FileSelectState* fileSelect = fileSelect2; s16 maskCount; - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { Sram_InitNewSave(); - if (fileSelect->unk_24480 == 0) { + 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->unk_24414[fileSelect->unk_24480][phi_v0]; + fileSelect->fileNames[fileSelect->buttonIndex][phi_v0]; } gSaveContext.save.saveInfo.playerData.newf[0] = 'Z'; @@ -1459,24 +1583,25 @@ void Sram_InitSave(FileSelectState* fileSelect2, SramContext* sramCtx) { Lib_MemCpy(&sramCtx->saveBuf[0x2000], &gSaveContext.save, sizeof(Save)); for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.newf); i++) { - fileSelect->newf[fileSelect->unk_24480][i] = gSaveContext.save.saveInfo.playerData.newf[i]; + fileSelect->newf[fileSelect->buttonIndex][i] = gSaveContext.save.saveInfo.playerData.newf[i]; } - fileSelect->unk_2440C[fileSelect->unk_24480] = gSaveContext.save.saveInfo.playerData.deaths; + fileSelect->threeDayResetCount[fileSelect->buttonIndex] = + gSaveContext.save.saveInfo.playerData.threeDayResetCount; for (i = 0; i < ARRAY_COUNT(gSaveContext.save.saveInfo.playerData.playerName); i++) { - fileSelect->unk_24414[fileSelect->unk_24480][i] = gSaveContext.save.saveInfo.playerData.playerName[i]; + fileSelect->fileNames[fileSelect->buttonIndex][i] = gSaveContext.save.saveInfo.playerData.playerName[i]; } - fileSelect->healthCapacity[fileSelect->unk_24480] = gSaveContext.save.saveInfo.playerData.healthCapacity; - fileSelect->health[fileSelect->unk_24480] = gSaveContext.save.saveInfo.playerData.health; - fileSelect->unk_24454[fileSelect->unk_24480] = gSaveContext.save.saveInfo.inventory.defenseHearts; - fileSelect->unk_24444[fileSelect->unk_24480] = gSaveContext.save.saveInfo.inventory.questItems; - fileSelect->unk_24458[fileSelect->unk_24480] = gSaveContext.save.time; - fileSelect->unk_24460[fileSelect->unk_24480] = gSaveContext.save.day; - fileSelect->unk_24468[fileSelect->unk_24480] = gSaveContext.save.isOwlSave; - fileSelect->rupees[fileSelect->unk_24480] = gSaveContext.save.saveInfo.playerData.rupees; - fileSelect->unk_24474[fileSelect->unk_24480] = CUR_UPG_VALUE(UPG_WALLET); + 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] = gSaveContext.save.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 < 24; i++) { if (gSaveContext.save.saveInfo.inventory.items[i + 24] != ITEM_NONE) { @@ -1484,17 +1609,19 @@ void Sram_InitSave(FileSelectState* fileSelect2, SramContext* sramCtx) { } } - fileSelect->maskCount[fileSelect->unk_24480] = maskCount; - fileSelect->heartPieceCount[fileSelect->unk_24480] = - (gSaveContext.save.saveInfo.inventory.questItems & 0xF0000000) >> 0x1C; + fileSelect->maskCount[fileSelect->buttonIndex] = maskCount; + fileSelect->heartPieceCount[fileSelect->buttonIndex] = GET_QUEST_HEART_PIECE_COUNT; } gSaveContext.save.time = D_801F6AF0; - gSaveContext.unk_3F3F = D_801F6AF2; + gSaveContext.flashSaveAvailable = D_801F6AF2; } -void func_80146DF8(SramContext* sramCtx) { - if (gSaveContext.unk_3F3F) { +/** + * Write the SaveOptions of SaveContext to the save buffer + */ +void Sram_WriteSaveOptionsToBuffer(SramContext* sramCtx) { + if (gSaveContext.flashSaveAvailable) { // TODO: macros for languages gSaveContext.options.language = 1; Lib_MemCpy(sramCtx->saveBuf, &gSaveContext.options, sizeof(SaveOptions)); @@ -1508,7 +1635,7 @@ void Sram_InitSram(GameState* gameState, SramContext* sramCtx) { } void Sram_Alloc(GameState* gameState, SramContext* sramCtx) { - if (gSaveContext.unk_3F3F) { + if (gSaveContext.flashSaveAvailable) { sramCtx->saveBuf = THA_AllocTailAlign16(&gameState->heap, SAVE_BUFFER_SIZE); sramCtx->status = 0; } @@ -1517,7 +1644,7 @@ void Sram_Alloc(GameState* gameState, SramContext* sramCtx) { /** * Synchronous flash write */ -void func_80146EBC(SramContext* sramCtx, s32 curPage, s32 numPages) { +void Sram_SyncWriteToFlash(SramContext* sramCtx, s32 curPage, s32 numPages) { sramCtx->curPage = curPage; sramCtx->numPages = numPages; SysFlashrom_WriteDataSync(sramCtx->saveBuf, curPage, numPages); @@ -1533,8 +1660,8 @@ void Sram_SaveSpecialEnterClockTown(PlayState* play) { gSaveContext.save.isFirstCycle = true; gSaveContext.save.isOwlSave = false; func_80145698(sramCtx); - SysFlashrom_WriteDataSync(sramCtx->saveBuf, D_801C67C8[gSaveContext.fileNum * 2], - D_801C6818[gSaveContext.fileNum * 2]); + SysFlashrom_WriteDataSync(sramCtx->saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2], + gFlashSpecialSaveNumPages[gSaveContext.fileNum * 2]); } /** @@ -1555,25 +1682,25 @@ void Sram_SaveSpecialNewDay(PlayState* play) { gSaveContext.save.day = day; gSaveContext.save.time = time; gSaveContext.save.cutsceneIndex = cutsceneIndex; - SysFlashrom_WriteDataSync(play->sramCtx.saveBuf, D_801C67C8[gSaveContext.fileNum * 2], - D_801C67F0[gSaveContext.fileNum * 2]); + SysFlashrom_WriteDataSync(play->sramCtx.saveBuf, gFlashSaveStartPages[gSaveContext.fileNum * 2], + gFlashSaveNumPages[gSaveContext.fileNum * 2]); } -void func_80147008(SramContext* sramCtx, u32 curPage, u32 numPages) { +void Sram_SetFlashPagesDefault(SramContext* sramCtx, u32 curPage, u32 numPages) { sramCtx->curPage = curPage; sramCtx->numPages = numPages; sramCtx->status = 1; } -void func_80147020(SramContext* sramCtx) { +void Sram_StartWriteToFlashDefault(SramContext* sramCtx) { // async flash write SysFlashrom_WriteDataAsync(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages); - sramCtx->unk_18 = osGetTime(); + sramCtx->startWriteOsTime = osGetTime(); sramCtx->status = 2; } -void func_80147068(SramContext* sramCtx) { +void Sram_UpdateWriteToFlashDefault(SramContext* sramCtx) { if (sramCtx->status == 2) { if (SysFlashrom_IsBusy() != 0) { // if task running if (SysFlashrom_AwaitResult() == 0) { // wait for task done @@ -1584,25 +1711,26 @@ void func_80147068(SramContext* sramCtx) { sramCtx->status = 4; } } - } else if (OSTIME_TO_TIMER(osGetTime() - sramCtx->unk_18) >= SECONDS_TO_TIMER(2)) { + } 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 func_80147138(SramContext* sramCtx, s32 curPage, s32 numPages) { +void Sram_SetFlashPagesOwlSave(SramContext* sramCtx, s32 curPage, s32 numPages) { sramCtx->curPage = curPage; sramCtx->numPages = numPages; sramCtx->status = 6; } -void func_80147150(SramContext* sramCtx) { +void Sram_StartWriteToFlashOwlSave(SramContext* sramCtx) { SysFlashrom_WriteDataAsync(sramCtx->saveBuf, sramCtx->curPage, sramCtx->numPages); - sramCtx->unk_18 = osGetTime(); + sramCtx->startWriteOsTime = osGetTime(); sramCtx->status = 7; } -void func_80147198(SramContext* sramCtx) { +void Sram_UpdateWriteToFlashOwlSave(SramContext* sramCtx) { if (sramCtx->status == 7) { if (SysFlashrom_IsBusy() != 0) { // Is task running if (SysFlashrom_AwaitResult() == 0) { // Wait for task done @@ -1621,7 +1749,8 @@ void func_80147198(SramContext* sramCtx) { sramCtx->status = 4; } } - } else if (OSTIME_TO_TIMER(osGetTime() - sramCtx->unk_18) >= SECONDS_TO_TIMER(2)) { + } 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; @@ -1648,8 +1777,9 @@ void func_80147314(SramContext* sramCtx, s32 fileNum) { gSaveContext.save.saveInfo.checksum = Sram_CalcChecksum(&gSaveContext, offsetof(SaveContext, fileNum)); Lib_MemCpy(sramCtx->saveBuf, &gSaveContext, offsetof(SaveContext, fileNum)); - func_80146EBC(sramCtx, D_801C6840[fileNum * 2], D_801C6850[fileNum * 2]); - func_80146EBC(sramCtx, D_801C6840[fileNum * 2 + 1], D_801C6850[fileNum * 2]); + 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; @@ -1661,6 +1791,7 @@ void func_80147314(SramContext* sramCtx, s32 fileNum) { 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; @@ -1668,16 +1799,18 @@ void func_80147414(SramContext* sramCtx, s32 fileNum, s32 arg2) { bzero(sramCtx->saveBuf, SAVE_BUFFER_SIZE); // Read save file - if (SysFlashrom_ReadData(sramCtx->saveBuf, D_801C6840[fileNum * 2], D_801C6850[fileNum * 2]) != 0) { + if (SysFlashrom_ReadData(sramCtx->saveBuf, gFlashOwlSaveStartPages[fileNum * 2], + gFlashOwlSaveNumPages[fileNum * 2]) != 0) { // If failed, read backup save file - SysFlashrom_ReadData(sramCtx->saveBuf, D_801C6840[fileNum * 2 + 1], D_801C6850[fileNum * 2 + 1]); + SysFlashrom_ReadData(sramCtx->saveBuf, gFlashOwlSaveStartPages[fileNum * 2 + 1], + gFlashOwlSaveNumPages[fileNum * 2 + 1]); } // Copy buffer to save context Lib_MemCpy(&gSaveContext, sramCtx->saveBuf, offsetof(SaveContext, fileNum)); - func_80146EBC(sramCtx, D_801C6840[arg2 * 2], D_801C6850[arg2 * 2]); - func_80146EBC(sramCtx, D_801C6840[arg2 * 2 + 1], D_801C6850[arg2 * 2]); + 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/code/z_vr_box.c b/src/code/z_vr_box.c index 911e3e7577..dd0785d94a 100644 --- a/src/code/z_vr_box.c +++ b/src/code/z_vr_box.c @@ -239,7 +239,7 @@ void func_80143324(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) { case SKYBOX_NORMAL_SKY: osCreateMesgQueue(&skyboxCtx->loadQueue, &skyboxCtx->loadMsg, 1); - if (play->envCtx.unk_10 == 0) { + if (play->envCtx.skybox1Index == 0) { // Send a DMA request for the clear sky texture size = SEGMENT_ROM_SIZE(d2_fine_static); @@ -256,7 +256,7 @@ void func_80143324(PlayState* play, SkyboxContext* skyboxCtx, s16 skyboxId) { osRecvMesg(&skyboxCtx->loadQueue, NULL, OS_MESG_BLOCK); osCreateMesgQueue(&skyboxCtx->loadQueue, &skyboxCtx->loadMsg, 1); - if (play->envCtx.unk_11 == 0) { + if (play->envCtx.skybox2Index == 0) { // Send a DMA request for the clear sky texture size = SEGMENT_ROM_SIZE(d2_fine_static); diff --git a/src/overlays/actors/ovl_Dm_Char01/z_dm_char01.c b/src/overlays/actors/ovl_Dm_Char01/z_dm_char01.c index 767d4c8274..33c6eed8ff 100644 --- a/src/overlays/actors/ovl_Dm_Char01/z_dm_char01.c +++ b/src/overlays/actors/ovl_Dm_Char01/z_dm_char01.c @@ -74,8 +74,8 @@ void DmChar01_Init(Actor* thisx, PlayState* play) { } if (gSaveContext.sceneLayer == 0) { - play->envCtx.unk_1F = 5; - play->envCtx.unk_20 = 5; + play->envCtx.lightConfig = 5; + play->envCtx.changeLightNextConfig = 5; } this->unk_348 = 255.0f; diff --git a/src/overlays/actors/ovl_Dm_Stk/z_dm_stk.c b/src/overlays/actors/ovl_Dm_Stk/z_dm_stk.c index 36415d7dbc..01a5b8c822 100644 --- a/src/overlays/actors/ovl_Dm_Stk/z_dm_stk.c +++ b/src/overlays/actors/ovl_Dm_Stk/z_dm_stk.c @@ -1129,8 +1129,8 @@ void DmStk_Init(Actor* thisx, PlayState* play) { Actor_SetScale(&this->actor, 0.01f); if ((play->sceneId == SCENE_00KEIKOKU) && (gSaveContext.sceneLayer == 3) && (play->csCtx.scriptIndex > 0)) { - play->envCtx.unk_17 = 15; - play->envCtx.unk_18 = 15; + play->envCtx.skyboxConfig = 15; + play->envCtx.changeSkyboxNextConfig = 15; } } @@ -1826,8 +1826,8 @@ void DmStk_Update(Actor* thisx, PlayState* play) { } if ((play->sceneId == SCENE_00KEIKOKU) && (gSaveContext.sceneLayer == 3) && (play->csCtx.scriptIndex > 0)) { - play->envCtx.unk_17 = 15; - play->envCtx.unk_18 = 15; + play->envCtx.skyboxConfig = 15; + play->envCtx.changeSkyboxNextConfig = 15; } } diff --git a/src/overlays/actors/ovl_En_Holl/z_en_holl.c b/src/overlays/actors/ovl_En_Holl/z_en_holl.c index 9b196c2fcd..ed3fe65b95 100644 --- a/src/overlays/actors/ovl_En_Holl/z_en_holl.c +++ b/src/overlays/actors/ovl_En_Holl/z_en_holl.c @@ -191,7 +191,7 @@ void EnHoll_VisibleIdle(EnHoll* this, PlayState* play) { } } else if (this->type == EN_HOLL_TYPE_SCENE_CHANGER) { play->nextEntrance = play->setupExitList[EN_HOLL_GET_EXIT_LIST_INDEX(&this->actor)]; - gSaveContext.unk_3DBB = 1; + gSaveContext.retainWeatherMode = true; Scene_SetExitFade(play); play->transitionTrigger = TRANS_TRIGGER_START; play->unk_1878C(play); diff --git a/src/overlays/actors/ovl_En_Viewer/z_en_viewer.c b/src/overlays/actors/ovl_En_Viewer/z_en_viewer.c index 34551dac90..79bee615aa 100644 --- a/src/overlays/actors/ovl_En_Viewer/z_en_viewer.c +++ b/src/overlays/actors/ovl_En_Viewer/z_en_viewer.c @@ -78,8 +78,8 @@ void func_8089F014(EnViewer* this, PlayState* play, f32 arg2) { } play->envCtx.lightSettingOverride = 0; play->envCtx.unk_E0 = 2; - play->envCtx.unk_C1 = this->actor.world.rot.x; - play->envCtx.unk_C2 = this->actor.world.rot.z; + play->envCtx.lightSetting = this->actor.world.rot.x; + play->envCtx.prevLightSetting = this->actor.world.rot.z; play->envCtx.lightBlend = arg2; } @@ -94,7 +94,7 @@ void func_8089F0A0(EnViewer* this, PlayState* play) { func_800FAAB4( play, SurfaceType_GetLightSettingIndex(&play->colCtx, player->actor.floorPoly, player->actor.floorBgId)); play->envCtx.lightBlend = 1.0f; - play->envCtx.unk_C2 = play->envCtx.unk_C1; + play->envCtx.prevLightSetting = play->envCtx.lightSetting; } } diff --git a/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c b/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c index 10be4ec3c6..84f6219158 100644 --- a/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c +++ b/src/overlays/actors/ovl_En_Weather_Tag/z_en_weather_tag.c @@ -99,8 +99,8 @@ void EnWeatherTag_Init(Actor* thisx, PlayState* play) { case WEATHERTAG_TYPE_UNK5: func_800BC154(play, &play->actorCtx, &this->actor, 7); play->skyboxId = SKYBOX_3; - play->envCtx.unk_1F = 5; - play->envCtx.unk_20 = 5; + play->envCtx.lightConfig = 5; + play->envCtx.changeLightNextConfig = 5; D_801F4E74 = 1.0f; EnWeatherTag_SetupAction(this, func_80966BF4); break; @@ -124,25 +124,26 @@ void EnWeatherTag_Init(Actor* thisx, PlayState* play) { // matches but unused params is suspicious // called WeatherTag_CheckEnableWeatherEffect in OOT, that's where "weatherMode" came from -u8 func_80966608(EnWeatherTag* this, PlayState* play, UNK_TYPE a3, UNK_TYPE a4, u8 new1F, u8 new20, u16 new24, - u8 weatherMode) { +u8 func_80966608(EnWeatherTag* this, PlayState* play, UNK_TYPE a3, UNK_TYPE a4, u8 lightConfig, + u8 changeLightNextConfig, u16 changeDuration, u8 weatherMode) { Player* player = GET_PLAYER(play); u8 returnVal = 0; if (WEATHER_TAG_RANGE100(&this->actor) > Actor_WorldDistXZToActor(&player->actor, &this->actor)) { - if (play->envCtx.unk_1F == play->envCtx.unk_20) { + if (play->envCtx.lightConfig == play->envCtx.changeLightNextConfig) { D_801BDBB8 = 1; - if (!(play->envCtx.unk_1E == 0) || ((play->envCtx.unk_1F != 1) && (play->envCtx.unk_21 == 0))) { + if (!(play->envCtx.lightMode == 0) || + ((play->envCtx.lightConfig != 1) && !play->envCtx.changeLightEnabled)) { D_801BDBB8 = 0; if (gWeatherMode != weatherMode) { gWeatherMode = weatherMode; - play->envCtx.unk_21 = 1; - play->envCtx.unk_1F = new1F; - play->envCtx.unk_20 = new20; - D_801BDBB4 = new20; - play->envCtx.unk_24 = new24; - play->envCtx.unk_22 = play->envCtx.unk_24; + play->envCtx.changeLightEnabled = true; + play->envCtx.lightConfig = lightConfig; + play->envCtx.changeLightNextConfig = changeLightNextConfig; + D_801BDBB4 = changeLightNextConfig; + play->envCtx.changeDuration = changeDuration; + play->envCtx.changeLightTimer = play->envCtx.changeDuration; } returnVal = 1; } @@ -153,23 +154,25 @@ u8 func_80966608(EnWeatherTag* this, PlayState* play, UNK_TYPE a3, UNK_TYPE a4, // again with the unused parameters // called WeatherTag_CheckRestoreWeather in OOT -u8 func_80966758(EnWeatherTag* this, PlayState* play, UNK_TYPE a3, UNK_TYPE a4, u8 new1F, u8 new20, u16 new24) { +u8 func_80966758(EnWeatherTag* this, PlayState* play, UNK_TYPE a3, UNK_TYPE a4, u8 lightConfig, + u8 changeLightNextConfig, u16 changeDuration) { Player* player = GET_PLAYER(play); u8 returnVal = 0; if (WEATHER_TAG_RANGE100(&this->actor) < Actor_WorldDistXZToActor(&player->actor, &this->actor)) { - if (play->envCtx.unk_1F == play->envCtx.unk_20) { + if (play->envCtx.lightConfig == play->envCtx.changeLightNextConfig) { D_801BDBB8 = 1; - if (!(play->envCtx.unk_1E == 0) || ((play->envCtx.unk_1F != 1) && (play->envCtx.unk_21 == 0))) { + if (!(play->envCtx.lightMode == 0) || + ((play->envCtx.lightConfig != 1) && !play->envCtx.changeLightEnabled)) { D_801BDBB8 = 0; gWeatherMode = 0; - play->envCtx.unk_21 = 1; - play->envCtx.unk_1F = new1F; - play->envCtx.unk_20 = new20; - D_801BDBB4 = new20; - play->envCtx.unk_24 = new24; - play->envCtx.unk_22 = play->envCtx.unk_24; + play->envCtx.changeLightEnabled = true; + play->envCtx.lightConfig = lightConfig; + play->envCtx.changeLightNextConfig = changeLightNextConfig; + D_801BDBB4 = changeLightNextConfig; + play->envCtx.changeDuration = changeDuration; + play->envCtx.changeLightTimer = play->envCtx.changeDuration; returnVal = 1; } } @@ -240,7 +243,7 @@ void EnWeatherTag_Die(EnWeatherTag* this, PlayState* play) { // poisoned swamp: placed behind the water fall from ikana // this tag stops spawning after STT cleared? void func_80966B08(EnWeatherTag* this, PlayState* play) { - if (func_80966608(this, play, 0, 0, play->envCtx.unk_1F, 5, 100, 2) || (gWeatherMode == 2)) { + if (func_80966608(this, play, 0, 0, play->envCtx.lightConfig, 5, 100, 2) || (gWeatherMode == 2)) { play->skyboxId = SKYBOX_3; EnWeatherTag_SetupAction(this, func_80966D20); } else if (D_801F4E74 <= 0.01f) { @@ -253,7 +256,7 @@ void func_80966B08(EnWeatherTag* this, PlayState* play) { // WEATHERTAG_TYPE_UNK5: only one in ikana canyon, corner of cliff right outside of stone tower entrance // because it uses cutsecnes.. is this the clear ikana cutcsene? void func_80966BF4(EnWeatherTag* this, PlayState* play) { - u8 newUnk20; + u8 changeLightNextConfig; CsCmdActorCue* cue; if (Cutscene_IsCueInChannel(play, CS_CMD_ACTOR_CUE_567)) { @@ -263,25 +266,25 @@ void func_80966BF4(EnWeatherTag* this, PlayState* play) { case 0: case 1: default: - - newUnk20 = 0; + changeLightNextConfig = 0; break; + case 2: - newUnk20 = 3; + changeLightNextConfig = 3; break; case 3: - newUnk20 = 4; + changeLightNextConfig = 4; break; } Math_SmoothStepToF(&D_801F4E74, 0.0f, 0.2f, 0.02f, 0.001f); - if (play->envCtx.unk_20 != newUnk20) { - play->envCtx.unk_21 = 1; - play->envCtx.unk_20 = newUnk20; - play->envCtx.unk_24 = 100; - play->envCtx.unk_22 = play->envCtx.unk_24; + if (play->envCtx.changeLightNextConfig != changeLightNextConfig) { + play->envCtx.changeLightEnabled = true; + play->envCtx.changeLightNextConfig = changeLightNextConfig; + play->envCtx.changeDuration = 100; + play->envCtx.changeLightTimer = play->envCtx.changeDuration; } } } diff --git a/src/overlays/actors/ovl_Obj_Grass/z_obj_grass.c b/src/overlays/actors/ovl_Obj_Grass/z_obj_grass.c index 6431a558bb..a17f853df3 100644 --- a/src/overlays/actors/ovl_Obj_Grass/z_obj_grass.c +++ b/src/overlays/actors/ovl_Obj_Grass/z_obj_grass.c @@ -4,6 +4,7 @@ * Description: "Master" instance of grass for unit spawned by Obj_Grass_Unit */ +#include "prevent_bss_reordering.h" #include "z_obj_grass.h" #include "overlays/actors/ovl_Obj_Grass_Carry/z_obj_grass_carry.h" #include "objects/gameplay_keep/gameplay_keep.h" diff --git a/src/overlays/actors/ovl_player_actor/z_player.c b/src/overlays/actors/ovl_player_actor/z_player.c index 5da69099e4..41cf34318f 100644 --- a/src/overlays/actors/ovl_player_actor/z_player.c +++ b/src/overlays/actors/ovl_player_actor/z_player.c @@ -5734,7 +5734,7 @@ void func_808354A4(PlayState* play, s32 arg1, s32 arg2) { gSaveContext.respawnFlag = -2; } - gSaveContext.unk_3DBB = 1; + gSaveContext.retainWeatherMode = 1; Scene_SetExitFade(play); } @@ -16454,7 +16454,7 @@ void func_8085269C(Player* this, PlayState* play) { (play->msgCtx.ocarinaMode == 0x18) || (play->msgCtx.ocarinaMode == 0x19)) { if (play->msgCtx.ocarinaMode == 0x16) { if (!func_8082DA90(play)) { - if (gSaveContext.save.saveInfo.playerData.deaths == 1) { + if (gSaveContext.save.saveInfo.playerData.threeDayResetCount == 1) { play->nextEntrance = ENTRANCE(CUTSCENE, 1); } else { play->nextEntrance = ENTRANCE(CUTSCENE, 0); diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose.h b/src/overlays/gamestates/ovl_file_choose/z_file_choose.h deleted file mode 100644 index f3231ec56b..0000000000 --- a/src/overlays/gamestates/ovl_file_choose/z_file_choose.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef Z64_FILE_CHOOSE_H -#define Z64_FILE_CHOOSE_H - -#include "global.h" - -void FileSelect_Init(GameState* thisx); -void FileSelect_Destroy(GameState* thisx); - -typedef struct FileSelectState { - /* 0x00000 */ GameState state; - /* 0x000A4 */ Vtx* unk_A4; - /* 0x000A8 */ u8* staticSegment; - /* 0x000AC */ u8* parameterSegment; - /* 0x000B0 */ u8* titleSegment; - /* 0x000B8 */ View view; - /* 0x00220 */ SramContext sramCtx; - /* 0x00248 */ SkyboxContext skyboxCtx; - /* 0x00470 */ MessageContext msgCtx; - /* 0x12550 */ Font font; - /* 0x242E0 */ EnvironmentContext envCtx; - /* 0x243E0 */ Vtx* unk_243E0; - /* 0x243E4 */ Vtx* unk_243E4; - /* 0x243E8 */ u8 newf2[2][6]; - /* 0x243F4 */ u8 newf[2][6]; - /* 0x24400 */ UNK_TYPE1 unk_24400[0xC]; - /* 0x2440C */ u16 unk_2440C[2]; - /* 0x24410 */ u16 unk_24410[2]; - /* 0x24414 */ u8 unk_24414[2][8]; // playername - /* 0x24424 */ u8 unk_24424[2][8]; // playername - /* 0x24434 */ s16 healthCapacity[2]; - /* 0x24438 */ u16 unk_24438[2]; - /* 0x2443C */ s16 health[2]; - /* 0x24440 */ u16 unk_24440[2]; - /* 0x24444 */ u32 unk_24444[2]; - /* 0x2444C */ u32 unk_2444C[2]; - /* 0x24454 */ s8 unk_24454[2]; - /* 0x24456 */ u8 unk_24456[2]; - /* 0x24458 */ u16 unk_24458[2]; - /* 0x2445C */ u16 unk_2445C[2]; - /* 0x24460 */ s16 unk_24460[2]; - /* 0x24464 */ s16 unk_24464[2]; - /* 0x24468 */ u8 unk_24468[2]; - /* 0x2446A */ u8 unk_2446A[2]; - /* 0x2446C */ s16 rupees[2]; - /* 0x24470 */ s16 unk_24470[2]; - /* 0x24474 */ s8 unk_24474[2]; - /* 0x24476 */ s8 unk_24476[2]; - /* 0x24478 */ s8 maskCount[2]; - /* 0x2447A */ s8 unk_2447A[2]; - /* 0x2447C */ s8 heartPieceCount[2]; - /* 0x2447E */ s8 unk_2447E[2]; - /* 0x24480 */ s16 unk_24480; - /* 0x24482 */ s16 unk_24482; - /* 0x24484 */ s16 unk_24484; - /* 0x24486 */ s16 unk_24486; - /* 0x24488 */ s16 unk_24488; - /* 0x2448A */ s16 unk_2448A; - /* 0x2448C */ s16 unk_2448C; - /* 0x2448E */ s16 unk_2448E; - /* 0x24490 */ s16 unk_24490; - /* 0x24492 */ s16 unk_24492[3]; - /* 0x24498 */ s16 unk_24498; - /* 0x2449A */ s16 unk_2449A[6]; - /* 0x244A6 */ s16 fileNum; - /* 0x244A8 */ s16 unk_244A8; - /* 0x244AA */ s16 unk_244AA; - /* 0x244AC */ s16 unk_244AC; - /* 0x244AE */ s16 unk_244AE; - /* 0x244B0 */ s16 unk_244B0[3]; - /* 0x244B6 */ s16 unk_244B6[2]; - /* 0x244BA */ s16 unk_244BA; - /* 0x244BC */ s16 unk_244BC[3]; - /* 0x244C2 */ s16 unk_244C2[3]; - /* 0x244C8 */ s16 unk_244C8[3]; - /* 0x244CE */ s16 unk_244CE[3]; - /* 0x244D4 */ s16 unk_244D4[3]; - /* 0x244DA */ s16 unk_244DA[4]; - /* 0x244E2 */ s16 unk_244E2; - /* 0x244E4 */ s16 unk_244E4; - /* 0x244E6 */ s16 unk_244E6; - /* 0x244E8 */ s16 unk_244E8; - /* 0x244EA */ s16 unk_244EA[4]; - /* 0x244F2 */ s16 unk_244F2; - /* 0x244F4 */ s16 unk_244F4; - /* 0x244F6 */ s16 unk_244F6[2]; - /* 0x244FA */ s16 unk_244FA; - /* 0x244FC */ s16 unk_244FC; - /* 0x244FE */ s16 unk_244FE; - /* 0x24500 */ s16 unk_24500; - /* 0x24502 */ s16 unk_24502; - /* 0x24504 */ s16 unk_24504; - /* 0x24506 */ s16 unk_24506; - /* 0x24508 */ s16 unk_24508; - /* 0x2450A */ s16 unk_2450A; - /* 0x2450C */ f32 unk_2450C; - /* 0x24510 */ s16 unk_24510; - /* 0x24512 */ s16 unk_24512; - /* 0x24514 */ s16 unk_24514; - /* 0x24516 */ s16 unk_24516; - /* 0x24518 */ s16 unk_24518; - /* 0x2451A */ s16 unk_2451A; - /* 0x2451C */ s16 unk_2451C; - /* 0x2451E */ s16 unk_2451E[5]; - /* 0x24528 */ s16 unk_24528; - /* 0x2452A */ s16 unk_2452A; - /* 0x2452C */ s16 unk_2452C[4]; - /* 0x24534 */ s16 unk_24534[4]; - /* 0x2453C */ s16 unk_2453C[4]; - /* 0x24544 */ s16 unk_24544[4]; - /* 0x2454C */ s16 unk_2454C; - /* 0x2454E */ s16 unk_2454E; - /* 0x24550 */ s16 unk_24550; -} FileSelectState; // size = 0x24558 - -#endif diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose_80807940.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose_80807940.c deleted file mode 100644 index 2e0e9a0d44..0000000000 --- a/src/overlays/gamestates/ovl_file_choose/z_file_choose_80807940.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * File: z_file_choose_80807940.c - * Overlay: ovl_file_choose - * Description: - */ - -#include "z_file_choose.h" -#include "z64rumble.h" - -extern UNK_TYPE D_01002800; -extern UNK_TYPE D_01007980; -extern UNK_TYPE D_0102A6B0; -extern UNK_TYPE D_0102B170; -extern UNK_TYPE D_010310F0; -extern UNK_TYPE D_010311F0; - -// there are uses of D_0E000000.fillRect (appearing as D_0E0002E0) in this file -extern GfxMasterList D_0E000000; - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80807940.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80807A78.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80807C58.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80808214.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80808D30.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80808F1C.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80809DF0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80809EA0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080A3CC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080A418.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080A4A0.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080A6BC.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080A708.s") - -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080BBFC.s") diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c index da9144e7c6..0cc43ad501 100644 --- a/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c +++ b/src/overlays/gamestates/ovl_file_choose/z_file_choose_NES.c @@ -4,96 +4,2545 @@ * Description: */ -#include "z_file_choose.h" +#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 "interface/parameter_static/parameter_static.h" +#include "misc/title_static/title_static.h" -extern UNK_TYPE D_01002800; -extern UNK_TYPE D_01007980; -extern UNK_TYPE D_0102A6B0; -extern UNK_TYPE D_0102B170; -extern UNK_TYPE D_010310F0; -extern UNK_TYPE D_010311F0; +s32 D_808144F10 = 100; +f32 D_808144F14 = 8.0f; +f32 D_808144F18 = 100.0f; +s32 D_808144F1C = 0; -// there are uses of D_0E000000.fillRect (appearing as D_0E0002E0) in this file -extern GfxMasterList D_0E000000; +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(), +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080BC20.s") +s16 sFileInfoBoxPartWidths[] = { + 36, 36, 36, 36, 24, 28, 28, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_nop8080bc44.s") +s16 sWindowContentColors[] = { 100, 150, 255 }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_nop8080BC4C.s") +s16 sFileSelectSkyboxRotation = 0; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080BC58.s") +s16 sWalletFirstDigit[] = { + 1, // tens (Default Wallet) + 0, // hundreds (Adult Wallet) + 0, // hundreds (Giant Wallet) +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080BDAC.s") +void FileSelect_IncrementConfigMode(FileSelectState* this) { + this->configMode++; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_RenderView.s") +void FileSelect_Noop1(void) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080BE60.s") +void FileSelect_Noop2(FileSelectState* this) { +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080C040.s") +void FileSelect_InitModeUpdate(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080C228.s") + 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; + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080C29C.s") + 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; + } + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080C324.s") +void FileSelect_InitModeDraw(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080C3A8.s") + Gfx_SetupDL39_Opa(this->state.gfxCtx); + FileSelect_Noop2(this); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D164.s") +void FileSelect_SetView(FileSelectState* this, f32 eyeX, f32 eyeY, f32 eyeZ) { + Vec3f eye; + Vec3f lookAt; + Vec3f up; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D170.s") + eye.x = eyeX; + eye.y = eyeY; + eye.z = eyeZ; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D1BC.s") + lookAt.x = lookAt.y = lookAt.z = 0.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D220.s") + up.x = up.z = 0.0f; + up.y = 1.0f; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D284.s") + View_LookAt(&this->view, &eye, &lookAt, &up); + View_Apply(&this->view, VIEW_ALL | VIEW_FORCE_VIEWING | VIEW_FORCE_VIEWPORT | VIEW_FORCE_PROJECTION_PERSPECTIVE); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D2EC.s") +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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D3D0.s") + gSP1Quadrangle(gfx++, point, point + 2, point + 3, point + 1, 0); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D40C.s") + return gfx; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080D6D4.s") +/** + * 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080F25C.s") + this->titleAlpha[FS_TITLE_CUR] += 20; + this->windowAlpha += 16; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808108DC.s") + for (i = 0; i < 3; i++) { + this->fileButtonAlpha[i] = this->windowAlpha; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80811CB8.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812460.s") + if (this->connectorAlpha[i] >= 255) { + this->connectorAlpha[i] = 255; + } + } + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812668.s") + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->optionButtonAlpha = this->windowAlpha; +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812760.s") +/** + * 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812840.s") + do { + if ((*ones - 100) < 0) { + break; + } + (*hundreds)++; + *ones -= 100; + } while (true); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812980.s") + do { + if ((*ones - 10) < 0) { + break; + } + (*tens)++; + *ones -= 10; + } while (true); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812A6C.s") +// Start of Config Mode Update Functions -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812D44.s") +/** + * 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812D94.s") + FileSelect_FadeInMenuElements(this); + this->screenFillAlpha -= 40; + this->windowPosX -= 20; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812E94.s") + if (this->windowPosX <= -94) { + this->windowPosX = -94; + this->configMode = CM_FADE_IN_END; + this->screenFillAlpha = 0; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80812ED0.s") +/** + * 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_UpdateAndDrawSkybox.s") + this->controlsAlpha += 20; + FileSelect_FadeInMenuElements(this); -void FileSelect_Main(GameState* thisx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_Main.s") + if (this->titleAlpha[FS_TITLE_CUR] >= 255) { + this->titleAlpha[FS_TITLE_CUR] = 255; + this->controlsAlpha = 255; + this->windowAlpha = 200; + this->configMode = CM_MAIN_MENU; + } +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80813908.s") +u8 sEmptyName[] = { 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E, 0x3E }; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_Destroy.s") +/** + * 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_Init.s") + 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)) { + play_sound(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 != 0) { + 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 { + play_sound(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)) { + play_sound(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 != 0) { + 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 { + play_sound(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) { + play_sound(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 { + play_sound(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) { + play_sound(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 + */ + +#ifdef NON_MATCHING +// regalloc at the beginning is fixed by removing FAKE: labelled code +void FileSelect_SetWindowContentVtx(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + u16 vtxId; + s16 j; + s16 index; + s16 spAC; + s16 i; // a3 + u16 spA4[3]; + u16* ptr; + s32 posY; // sp9C + s32 relPosY; // sp98 + s32 tempPosY; + s32 posX; // s1 + s32 temp_t5; + + 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; + + //! FAKE: + if (index && index && index) {} + + // 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; + temp_t5 = 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[temp_t5 + 8].v.ob[0] = this->windowContentVtx[temp_t5 + 10].v.ob[0] = + this->windowContentVtx[temp_t5 + 8].v.ob[0] + 3; + + this->windowContentVtx[temp_t5 + 9].v.ob[0] = this->windowContentVtx[temp_t5 + 11].v.ob[0] = + this->windowContentVtx[temp_t5 + 8].v.ob[0] + 0xC; + + this->windowContentVtx[temp_t5 + 0x1C].v.ob[0] = this->windowContentVtx[temp_t5 + 0x1E].v.ob[0] = + this->windowContentVtx[temp_t5 + 8].v.ob[0] + 1; + + this->windowContentVtx[temp_t5 + 0x1D].v.ob[0] = this->windowContentVtx[temp_t5 + 0x1F].v.ob[0] = + this->windowContentVtx[temp_t5 + 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; +} +#else +void FileSelect_SetWindowContentVtx(GameState* thisx); +#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/FileSelect_SetWindowContentVtx.s") +#endif + +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, (s16)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; + + if (1) {} + + 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); + } + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + 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); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + 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); + + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + 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); + play_sound(NA_SE_SY_FSEL_DECIDE_L); + this->selectMode = SM_FADE_OUT; + func_801A4058(0xF); + } else { // FS_BTN_CONFIRM_QUIT + play_sound(NA_SE_SY_FSEL_CLOSE); + this->selectMode++; // SM_FADE_OUT_FILE_INFO + } + } else if (CHECK_BTN_ALL(input->press.button, BTN_B)) { + play_sound(NA_SE_SY_FSEL_CLOSE); + this->selectMode++; // SM_FADE_OUT_FILE_INFO + } else if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(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 = 0xFFFF; + 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); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + + 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->actionButtonAlpha[2] = + this->actionButtonAlpha[3] = 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 = 0; + + Skybox_Init(&this->state, &this->skyboxCtx, 1); + R_TIME_SPEED = 10; + + envCtx->changeSkyboxState = 0; + 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 = 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; + + Game_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.heap, size); + DmaMgr_SendRequest0(this->staticSegment, SEGMENT_ROM_START(title_static), size); + + size = SEGMENT_ROM_SIZE(parameter_static); + this->parameterSegment = THA_AllocTailAlign16(&this->state.heap, size); + DmaMgr_SendRequest0(this->parameterSegment, SEGMENT_ROM_START(parameter_static), size); + + size = gObjectTable[OBJECT_MAG].vromEnd - gObjectTable[OBJECT_MAG].vromStart; + this->titleSegment = THA_AllocTailAlign16(&this->state.heap, size); + DmaMgr_SendRequest0(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_copy_erase.c b/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c new file mode 100644 index 0000000000..7f8e5789c1 --- /dev/null +++ b/src/overlays/gamestates/ovl_file_choose/z_file_copy_erase.c @@ -0,0 +1,1253 @@ +/* + * File: z_file_copy_erase.c + * Overlay: ovl_file_choose + * Description: Copying and Erasing Files + */ + +#include "z_file_select.h" +#include "z64rumble.h" + +// When choosing a file to copy or erase, the 6 main menu buttons are placed at these offsets +s16 sChooseFileYOffsets[] = { -48, -48, -48, -24, -24, 0 }; + +s16 D_8081424C[3][3] = { + { 0, -48, -48 }, + { -64, 16, -48 }, + { -64, -64, 32 }, +}; + +s16 sEraseDelayTimer = 15; + +/** + * Move buttons into place for the select source screen and fade in the proper labels. + * Update function for `CM_SETUP_COPY_SOURCE` + */ +void FileSelect_SetupCopySource(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s32 yStep; + s16 i; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i] - sChooseFileYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= sChooseFileYOffsets[i]) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + this->actionButtonAlpha[FS_BTN_ACTION_COPY] -= 200 / 4; + this->actionButtonAlpha[FS_BTN_ACTION_ERASE] -= 200 / 4; + this->optionButtonAlpha -= 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] += 200 / 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->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->optionButtonAlpha = 0; + + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 200; + this->titleLabel = this->nextTitleLabel; + + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->buttonIndex = FS_BTN_COPY_QUIT; + this->configMode++; // CM_SELECT_COPY_SOURCE + } +} + +/** + * Allow the player to select a file to copy or exit back to the main menu. + * Update function for `CM_SELECT_COPY_SOURCE` + */ +void FileSelect_SelectCopySource(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + Input* input = CONTROLLER1(&this->state); + + if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || + CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->actionTimer = 4; + this->buttonIndex = FS_BTN_MAIN_COPY; + this->nextTitleLabel = FS_TITLE_SELECT_FILE; + this->configMode = CM_COPY_RETURN_MAIN; + this->warningLabel = FS_WARNING_NONE; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) { + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->actionTimer = 4; + this->selectedFileIndex = this->buttonIndex; + this->configMode = CM_SETUP_COPY_DEST_1; + this->nextTitleLabel = FS_TITLE_COPY_TO; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else if (SLOT_OCCUPIED(this, this->buttonIndex)) { + this->actionTimer = 4; + this->selectedFileIndex = this->buttonIndex; + this->configMode = CM_SETUP_COPY_DEST_1; + this->nextTitleLabel = FS_TITLE_COPY_TO; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else { + if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + if (this->stickAdjY >= 30) { + this->buttonIndex--; + // Instead of removing File 3 entirely, the index is manually adjusted to skip it + if (this->buttonIndex == FS_BTN_COPY_FILE_3) { + this->buttonIndex = FS_BTN_COPY_FILE_2; + } + if (this->buttonIndex < FS_BTN_COPY_FILE_1) { + this->buttonIndex = FS_BTN_COPY_QUIT; + } + } else { + this->buttonIndex++; + // Instead of removing File 3 entirely, the index is manually adjusted to skip it + if (this->buttonIndex == FS_BTN_COPY_FILE_3) { + this->buttonIndex = FS_BTN_COPY_QUIT; + } + if (this->buttonIndex > FS_BTN_COPY_QUIT) { + this->buttonIndex = FS_BTN_COPY_FILE_1; + } + } + } + + if (this->buttonIndex != FS_BTN_COPY_QUIT) { + if (!gSaveContext.flashSaveAvailable) { + if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_EMPTY; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } else if (!SLOT_OCCUPIED(this, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_EMPTY; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } + } +} + +/** + * Move the menu buttons into place for the copy destination selection and switch titles. + * Update function for `CM_SETUP_COPY_DEST_1` + */ +void FileSelect_SetupCopyDest1(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s32 yStep; + s16 i; + + for (i = 0; i < 3; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i] - D_8081424C[this->buttonIndex][i]) / this->actionTimer; + + if (D_8081424C[this->buttonIndex][i] >= this->buttonYOffsets[i]) { + this->buttonYOffsets[i] += yStep; + } else { + this->buttonYOffsets[i] -= yStep; + } + } + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->nameBoxAlpha[this->buttonIndex] -= 200 / 4; + + this->actionTimer--; + if (this->actionTimer == 0) { + this->buttonYOffsets[this->buttonIndex] = D_8081424C[this->buttonIndex][this->buttonIndex]; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->actionTimer = 4; + this->configMode++; // CM_SETUP_COPY_DEST_2 + } +} + +/** + * Show the file info of the file selected to copy from. + * Update function for `CM_SETUP_COPY_DEST_2` + */ +void FileSelect_SetupCopyDest2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->nameBoxAlpha[this->buttonIndex] -= 200 / 4; + this->fileInfoAlpha[this->buttonIndex] += 200 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->nameBoxAlpha[this->buttonIndex] = 0; + this->fileInfoAlpha[this->buttonIndex] = 200; + this->buttonIndex = FS_BTN_COPY_QUIT; + this->actionTimer = 4; + this->configMode = CM_SELECT_COPY_DEST; + } +} + +/** + * Allow the player to select a slot to copy to or exit to the copy select screen. + * Update function for `CM_SELECT_COPY_DEST` + */ +void FileSelect_SelectCopyDest(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + Input* input = CONTROLLER1(&this->state); + + if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || + CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->buttonIndex = this->selectedFileIndex; + this->nextTitleLabel = FS_TITLE_COPY_FROM; + this->actionTimer = 4; + this->configMode = CM_EXIT_TO_COPY_SOURCE_1; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) { + if (!gSaveContext.flashSaveAvailable) { + if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->copyDestFileIndex = this->buttonIndex; + this->nextTitleLabel = FS_TITLE_COPY_CONFIRM; + this->actionTimer = 4; + this->configMode = CM_SETUP_COPY_CONFIRM_1; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else if (!SLOT_OCCUPIED(this, this->buttonIndex)) { + this->copyDestFileIndex = this->buttonIndex; + this->nextTitleLabel = FS_TITLE_COPY_CONFIRM; + this->actionTimer = 4; + this->configMode = CM_SETUP_COPY_CONFIRM_1; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else { + if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + if (this->stickAdjY >= 30) { + this->buttonIndex--; + // Instead of removing File 3 entirely, the index is manually adjusted to skip it + if (this->buttonIndex == FS_BTN_COPY_FILE_3) { + this->buttonIndex = FS_BTN_COPY_FILE_2; + } + if (this->buttonIndex == this->selectedFileIndex) { + this->buttonIndex--; + if (this->buttonIndex < FS_BTN_COPY_FILE_1) { + this->buttonIndex = FS_BTN_COPY_QUIT; + } + // Instead of removing File 3 entirely, the index is manually adjusted to skip it + if (this->buttonIndex == FS_BTN_COPY_FILE_3) { + this->buttonIndex = FS_BTN_COPY_FILE_2; + } + } else if (this->buttonIndex < FS_BTN_COPY_FILE_1) { + this->buttonIndex = FS_BTN_COPY_QUIT; + } + } else { + this->buttonIndex++; + if (this->buttonIndex > FS_BTN_COPY_QUIT) { + this->buttonIndex = FS_BTN_COPY_FILE_1; + } + if (this->buttonIndex == this->selectedFileIndex) { + this->buttonIndex++; + } + // Instead of removing File 3 entirely, the index is manually adjusted to skip it + if (this->buttonIndex == FS_BTN_COPY_FILE_3) { + this->buttonIndex = FS_BTN_COPY_QUIT; + } + } + } + if (this->buttonIndex != FS_BTN_COPY_QUIT) { + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_IN_USE; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } else if (SLOT_OCCUPIED(this, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_IN_USE; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } + } +} + +/** + * Fade out file info, bring back the name box, and get ready to return to copy source screen. + * Update function for `CM_EXIT_TO_COPY_SOURCE_1` + */ +void FileSelect_ExitToCopySource1(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->nextTitleLabel = FS_TITLE_COPY_FROM; + this->nameBoxAlpha[this->buttonIndex] = 200; + this->fileInfoAlpha[this->buttonIndex] = 0; + this->actionTimer = 4; + this->configMode++; // CM_EXIT_TO_COPY_SOURCE_2 + } +} + +/** + * Move the buttons back into place and return to copy source select. + * Update function for `CM_EXIT_TO_COPY_SOURCE_2` + */ +void FileSelect_ExitToCopySource2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + for (i = 0; i < 3; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i] - sChooseFileYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= sChooseFileYOffsets[i]) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->buttonIndex = FS_BTN_COPY_QUIT; + this->configMode = CM_SELECT_COPY_SOURCE; + } +} + +s16 D_80814264[] = { -56, -40, -24, 0 }; + +/** + * Rearrange buttons on the screen to prepare for copy confirmation. + * Update function for `CM_SETUP_COPY_CONFIRM_1` + */ +void FileSelect_SetupCopyConfirm1(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + + for (i = 0; i < 3; i++) { + if ((i != this->copyDestFileIndex) && (i != this->selectedFileIndex)) { + this->fileButtonAlpha[i] -= 200 / 4; + + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) { + this->connectorAlpha[i] -= 255 / 4; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + } + } else if (SLOT_OCCUPIED(this, i)) { + this->connectorAlpha[i] -= 255 / 4; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + } + } else if (i == this->copyDestFileIndex) { + yStep = ABS_ALT(this->buttonYOffsets[i] - D_80814264[i]) / this->actionTimer; + this->buttonYOffsets[i] += yStep; + + if (this->buttonYOffsets[i] >= D_80814264[i]) { + this->buttonYOffsets[i] = D_80814264[i]; + } + } + } + + this->actionTimer--; + + if (this->actionTimer == 0) { + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->actionTimer = 4; + this->configMode++; + } +} + +/** + * Fade in the 'Yes' button before allowing the player to decide. + * Update function for `CM_SETUP_COPY_CONFIRM_2` + */ +void FileSelect_SetupCopyConfirm2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] += 200 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->configMode = CM_COPY_CONFIRM; + this->buttonIndex = FS_BTN_CONFIRM_QUIT; + } +} + +/** + * Allow the player to confirm the copy, or quit back to the destination select. + * If yes is selected, the actual copy occurs in this function before moving on to the animation. + * Update function for `CM_COPY_CONFIRM` + */ +void FileSelect_CopyConfirm(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + Input* input = CONTROLLER1(&this->state); + u16 dayTime; + + if (((this->buttonIndex != FS_BTN_CONFIRM_YES) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || + CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->actionTimer = 4; + this->nextTitleLabel = FS_TITLE_COPY_TO; + this->configMode = CM_RETURN_TO_COPY_DEST; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) { + dayTime = gSaveContext.save.time; + gSaveContext.save.time = dayTime; + this->nameAlpha[this->copyDestFileIndex] = 0; + this->fileInfoAlpha[this->copyDestFileIndex] = this->nameAlpha[this->copyDestFileIndex]; + this->nextTitleLabel = FS_TITLE_COPY_COMPLETE; + this->actionTimer = 4; + Sram_CopySave(this, sramCtx); + if (!gSaveContext.flashSaveAvailable) { + this->configMode = CM_COPY_ANIM_1; + } else { + Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[this->copyDestFileIndex * 2], + gFlashSpecialSaveNumPages[this->copyDestFileIndex * 2]); + Sram_StartWriteToFlashDefault(sramCtx); + this->configMode = CM_COPY_WAIT_FOR_FLASH_SAVE; + } + Rumble_Request(300.0f, 180, 20, 100); + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + this->buttonIndex ^= 1; + } +} + +/** + * Update and wait for the save to flash to complete. + * Update function for `CM_COPY_WAIT_FOR_FLASH_SAVE` + */ +void FileSelect_CopyWaitForFlashSave(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + u16 i; + + Sram_UpdateWriteToFlashDefault(sramCtx); + + if (sramCtx->status == 0) { + this->configMode = CM_COPY_ANIM_1; + + for (i = 0; i < 6; i++) { + this->newf[this->copyDestFileIndex][i] = gSaveContext.save.saveInfo.playerData.newf[i]; + } + + this->threeDayResetCount[this->copyDestFileIndex] = gSaveContext.save.saveInfo.playerData.threeDayResetCount; + + for (i = 0; i < 8; i++) { + this->fileNames[this->copyDestFileIndex][i] = gSaveContext.save.saveInfo.playerData.playerName[i]; + } + + this->healthCapacity[this->copyDestFileIndex] = gSaveContext.save.saveInfo.playerData.healthCapacity; + this->health[this->copyDestFileIndex] = gSaveContext.save.saveInfo.playerData.health; + this->defenseHearts[this->copyDestFileIndex] = gSaveContext.save.saveInfo.inventory.defenseHearts; + } +} + +/** + * Move buttons back in place and return to copy destination select. + * Update function for `CM_RETURN_TO_COPY_DEST` + */ +void FileSelect_ReturnToCopyDest(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] -= 200 / 4; + + for (i = 0; i < 3; i++) { + if ((i != this->copyDestFileIndex) && (i != this->selectedFileIndex)) { + this->fileButtonAlpha[i] += 200 / 4; + + 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; + } + } + + yStep = ABS_ALT(this->buttonYOffsets[i] - D_8081424C[this->selectedFileIndex][i]) / this->actionTimer; + + if (D_8081424C[this->selectedFileIndex][i] >= this->buttonYOffsets[i]) { + this->buttonYOffsets[i] += yStep; + } else { + this->buttonYOffsets[i] -= yStep; + } + } + + this->actionTimer--; + + if (this->actionTimer == 0) { + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->actionTimer = 4; + this->buttonIndex = FS_BTN_COPY_QUIT; + this->configMode = CM_SELECT_COPY_DEST; + } +} + +/** + * Hide title + * Update function for `CM_COPY_ANIM_1` + */ +void FileSelect_CopyAnim1(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] -= 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] -= 200 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->titleAlpha[FS_TITLE_CUR] = 0; + this->actionTimer = 4; + this->configMode++; // CM_COPY_ANIM_2 + } +} + +/** + * Move a copy of the file window down and fade in the file info. + * Update function for `CM_COPY_ANIM_2` + */ +void FileSelect_CopyAnim2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s32 yStep; + + this->fileInfoAlpha[this->copyDestFileIndex] += 200 / 4; + this->nameAlpha[this->copyDestFileIndex] += 200 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + yStep = ABS_ALT(this->fileNamesY[this->copyDestFileIndex] + 56) / this->actionTimer; + this->fileNamesY[this->copyDestFileIndex] -= yStep; + + if (this->fileNamesY[this->copyDestFileIndex] <= -56) { + this->fileNamesY[this->copyDestFileIndex] = -56; + } + + this->actionTimer--; + + if (this->actionTimer == 0) { + this->actionTimer = 45; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode++; // CM_COPY_ANIM_3 + } +} + +/** + * Play a sound effect to indicate that the copy has completed. Wait for a timer or for + * the player to press a button before moving on. + * Update function for `CM_COPY_ANIM_3` + */ +void FileSelect_CopyAnim3(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + Input* input = CONTROLLER1(&this->state); + + if (this->actionTimer == 38) { + this->connectorAlpha[this->copyDestFileIndex] = 255; + play_sound(NA_SE_EV_DIAMOND_SWITCH); + } + + this->actionTimer--; + + if (this->actionTimer < 37) { + if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_B | BTN_START) || (this->actionTimer == 0)) { + this->actionTimer = 4; + this->nextTitleLabel = FS_TITLE_SELECT_FILE; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + this->configMode = CM_COPY_ANIM_4; + } + } +} + +/** + * Fade out the info boxes for both files and bring in their name boxes. Fade out title. + * Update function for `CM_COPY_ANIM_4` + */ +void FileSelect_CopyAnim4(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->fileInfoAlpha[this->selectedFileIndex] -= 200 / 4; + this->fileInfoAlpha[this->copyDestFileIndex] -= 200 / 4; + this->nameBoxAlpha[this->selectedFileIndex] += 200 / 4; + this->nameBoxAlpha[this->copyDestFileIndex] += 200 / 4; + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->fileNamesY[this->copyDestFileIndex] = this->buttonYOffsets[3] = 0; + this->actionTimer = 4; + this->titleAlpha[FS_TITLE_CUR] = 0; + this->configMode++; + } +} + +/** + * Restore all buttons and labels back to their original place and go back to the main menu. + * Update function for `CM_COPY_ANIM_5` + */ +void FileSelect_CopyAnim5(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= 0) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + for (i = 0; i < 3; i++) { + if (i != this->buttonIndex) { + this->fileButtonAlpha[i] += 200 / 4; + + 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->actionButtonAlpha[FS_BTN_ACTION_COPY] += 200 / 4; + this->actionButtonAlpha[FS_BTN_ACTION_ERASE] += 200 / 4; + this->optionButtonAlpha += 200 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + for (i = 0; i < 3; i++) { + this->connectorAlpha[i] = 0; + this->fileButtonAlpha[i] = 200; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->connectorAlpha[i]; + + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) { + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + this->connectorAlpha[i] = 255; + } + } else if (SLOT_OCCUPIED(this, i)) { + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + this->connectorAlpha[i] = 255; + } + } + + this->fileNamesY[this->selectedFileIndex] = 0; + this->highlightColor[3] = 70; + this->highlightPulseDir = 1; + this->highlightTimer = 20; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode = CM_MAIN_MENU; + } +} + +/** + * Exit from the copy source screen to the main menu. Return all buttons and labels to their original place. + * Update function for `CM_COPY_RETURN_MAIN` + */ +void FileSelect_ExitCopyToMain(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s16 i; + s32 yStep; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= 0) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + this->actionButtonAlpha[FS_BTN_ACTION_COPY] += 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] -= 200 / 4; + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = 200; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 0; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode = CM_MAIN_MENU; + } + + this->optionButtonAlpha = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->actionButtonAlpha[FS_BTN_ACTION_COPY]; +} + +/** + * Move buttons into place for the erase select screen and fade in the proper labels. + * Update function for `CM_SETUP_ERASE_SELECT` + */ +void FileSelect_SetupEraseSelect(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s16 i; + s32 yStep; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i] - sChooseFileYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= sChooseFileYOffsets[i]) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + this->actionButtonAlpha[FS_BTN_ACTION_COPY] -= 100; + this->actionButtonAlpha[FS_BTN_ACTION_ERASE] -= 100; + this->optionButtonAlpha -= 100; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] += 200 / 4; + + if (this->actionButtonAlpha[FS_BTN_ACTION_COPY] <= 0) { + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->optionButtonAlpha = 0; + } + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->highlightColor[3] = 70; + this->highlightPulseDir = 1; + this->highlightTimer = 20; + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->optionButtonAlpha = 0; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 200; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->buttonIndex = FS_BTN_ERASE_QUIT; + this->configMode++; // CM_ERASE_SELECT + } +} + +/** + * Allow the player to select a file to erase or exit back to the main menu. + * Update function for `CM_ERASE_SELECT` + */ +void FileSelect_EraseSelect(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + Input* input = CONTROLLER1(&this->state); + + if (((this->buttonIndex == FS_BTN_COPY_QUIT) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || + CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->buttonIndex = FS_BTN_MAIN_ERASE; + this->actionTimer = 4; + this->nextTitleLabel = FS_TITLE_SELECT_FILE; + this->configMode = CM_EXIT_ERASE_TO_MAIN; + this->warningLabel = FS_WARNING_NONE; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) { + + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->actionTimer = 4; + this->selectedFileIndex = this->buttonIndex; + this->configMode = CM_SETUP_ERASE_CONFIRM_1; + this->nextTitleLabel = FS_TITLE_ERASE_CONFIRM; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else if (SLOT_OCCUPIED(this, this->buttonIndex)) { + this->actionTimer = 4; + this->selectedFileIndex = this->buttonIndex; + this->configMode = CM_SETUP_ERASE_CONFIRM_1; + this->nextTitleLabel = FS_TITLE_ERASE_CONFIRM; + play_sound(NA_SE_SY_FSEL_DECIDE_L); + } else { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } else { + if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + + if (this->stickAdjY >= 30) { + this->buttonIndex--; + if (this->buttonIndex == FS_BTN_ERASE_FILE_3) { + this->buttonIndex = FS_BTN_ERASE_FILE_2; + } + if (this->buttonIndex < FS_BTN_ERASE_FILE_1) { + this->buttonIndex = FS_BTN_ERASE_QUIT; + } + } else { + this->buttonIndex++; + if (this->buttonIndex == FS_BTN_ERASE_FILE_3) { + this->buttonIndex = FS_BTN_ERASE_QUIT; + } + if (this->buttonIndex > FS_BTN_ERASE_QUIT) { + this->buttonIndex = FS_BTN_ERASE_FILE_1; + } + } + } + + if (this->buttonIndex != FS_BTN_ERASE_QUIT) { + if (!gSaveContext.flashSaveAvailable) { + if (!NO_FLASH_SLOT_OCCUPIED(sramCtx, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_EMPTY; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } else if (!SLOT_OCCUPIED(this, this->buttonIndex)) { + this->warningLabel = FS_WARNING_FILE_EMPTY; + this->warningButtonIndex = this->buttonIndex; + this->emptyFileTextAlpha = 255; + } else { + this->warningLabel = FS_WARNING_NONE; + } + } else { + this->warningLabel = FS_WARNING_NONE; + } + } +} + +s16 D_8081426C[] = { 0, 16, 32 }; + +/** + * Update function for `CM_SETUP_ERASE_CONFIRM_1` + */ +void FileSelect_SetupEraseConfirm1(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + for (i = 0; i < 3; i++) { + if (i != this->buttonIndex) { + this->fileButtonAlpha[i] -= 200 / 4; + + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) { + this->connectorAlpha[i] -= 255 / 4; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + } + } else if (SLOT_OCCUPIED(this, i)) { + this->connectorAlpha[i] -= 255 / 4; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i]; + } + } else { + this->nameBoxAlpha[i] -= 200 / 4; + } + } + this->titleAlpha[FS_TITLE_CUR] -= 255 / 8; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 8; + + yStep = ABS_ALT(this->buttonYOffsets[this->buttonIndex] - D_8081426C[this->buttonIndex]) / this->actionTimer; + + if (this->buttonYOffsets[this->buttonIndex] >= D_8081426C[this->buttonIndex]) { + this->buttonYOffsets[this->buttonIndex] -= yStep; + } else { + this->buttonYOffsets[this->buttonIndex] += yStep; + } + + this->actionTimer--; + + if (this->actionTimer == 0) { + for (i = 0; i < 3; i++) { + if (i != this->buttonIndex) { + this->fileButtonAlpha[i] = 0; + + if (!gSaveContext.flashSaveAvailable) { + if (NO_FLASH_SLOT_OCCUPIED(sramCtx, i)) { + this->connectorAlpha[i] = 0; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i] = 0; + } + } else if (SLOT_OCCUPIED(this, i)) { + this->connectorAlpha[i] = 0; + this->nameBoxAlpha[i] = this->nameAlpha[i] = this->fileButtonAlpha[i] = 0; + } + } else { + this->nameBoxAlpha[i] = 0; + } + } + + this->buttonYOffsets[this->buttonIndex] = D_8081426C[this->buttonIndex]; + this->actionTimer = 4; + this->configMode++; + } +} + +/** + * Show the file info of the file selected to erase. + * Update function for `CM_SETUP_ERASE_CONFIRM_2` + */ +void FileSelect_SetupEraseConfirm2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] += 200 / 4; + this->titleAlpha[FS_TITLE_CUR] -= 255 / 8; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 8; + this->fileInfoAlpha[this->buttonIndex] += 200 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->actionTimer = 4; + this->titleLabel = this->nextTitleLabel; + this->fileInfoAlpha[this->buttonIndex] = this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] = 200; + this->buttonIndex = FS_BTN_CONFIRM_QUIT; + this->configMode = CM_ERASE_CONFIRM; + } +} + +/** + * Allow the player to confirm their choice to erase or return back to erase select. + * Update function for `CM_ERASE_CONFIRM` + */ +void FileSelect_EraseConfirm(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + Input* input = CONTROLLER1(&this->state); + + if (((this->buttonIndex != FS_BTN_CONFIRM_YES) && CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) || + CHECK_BTN_ALL(input->press.button, BTN_B)) { + this->buttonIndex = this->selectedFileIndex; + this->nextTitleLabel = FS_TITLE_ERASE_FILE; + this->configMode = CM_EXIT_TO_ERASE_SELECT_1; + this->actionTimer = 4; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_START)) { + Sram_EraseSave(this, sramCtx, this->selectedFileIndex); + if (!gSaveContext.flashSaveAvailable) { + this->configMode = CM_ERASE_ANIM_1; + } else { + Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[this->selectedFileIndex * 2], + gFlashSpecialSaveNumPages[this->selectedFileIndex * 2]); + Sram_StartWriteToFlashDefault(sramCtx); + this->configMode = CM_ERASE_WAIT_FOR_FLASH_SAVE; + } + this->connectorAlpha[this->selectedFileIndex] = 0; + play_sound(NA_SE_EV_DIAMOND_SWITCH); + this->actionTimer = 4; + this->nextTitleLabel = FS_TITLE_ERASE_COMPLETE; + Rumble_Request(200.0f, 255, 20, 150); + sEraseDelayTimer = 15; + } else if (ABS_ALT(this->stickAdjY) >= 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + this->buttonIndex ^= 1; + } +} + +/** + * Fade out file info, bring back the name box, and get ready to return to erase select screen. + * Update function for `CM_EXIT_TO_ERASE_SELECT_1` + */ +void FileSelect_ExitToEraseSelect1(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + + this->fileInfoAlpha[this->buttonIndex] -= 200 / 4; + this->nameBoxAlpha[this->buttonIndex] += 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] -= 200 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->actionTimer = 4; + this->fileInfoAlpha[this->buttonIndex] = 0; + this->configMode++; // CM_EXIT_TO_ERASE_SELECT_2 + } +} + +/** + * Move the buttons back into place and return to erase select. + * Update function for `CM_EXIT_TO_ERASE_SELECT_2` + */ +void FileSelect_ExitToEraseSelect2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + yStep = + ABS_ALT(this->buttonYOffsets[this->buttonIndex] - sChooseFileYOffsets[this->buttonIndex]) / this->actionTimer; + + if (this->buttonYOffsets[this->buttonIndex] >= sChooseFileYOffsets[this->buttonIndex]) { + this->buttonYOffsets[this->buttonIndex] -= yStep; + } else { + this->buttonYOffsets[this->buttonIndex] += yStep; + } + + for (i = 0; i < 3; i++) { + if (i != this->buttonIndex) { + this->fileButtonAlpha[i] += 200 / 4; + + 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->buttonYOffsets[this->buttonIndex] = sChooseFileYOffsets[this->buttonIndex]; + this->actionTimer = 4; + this->buttonIndex = FS_BTN_ERASE_QUIT; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode = CM_ERASE_SELECT; + } +} + +/** + * Wait for an initial delay, then start fading out the selected file. + * The actual file deletion occurs in this function. + * Update function for `CM_ERASE_ANIM_1` + */ +void FileSelect_EraseAnim1(GameState* thisx) { + static s16 D_80814E80; + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + + if (sEraseDelayTimer == 0) { + if (this->actionTimer == 4) { + D_80814E80 = 1; + } + + if (this->actionTimer != 0) { + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->fileInfoAlpha[this->selectedFileIndex] -= 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] -= 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] -= 200 / 4; + } + + this->fileNamesY[this->selectedFileIndex] -= D_80814E80; + D_80814E80 += 2; + + this->actionTimer--; + if (this->actionTimer == 0) { + this->configMode = CM_ERASE_ANIM_2; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = this->connectorAlpha[this->selectedFileIndex] = 0; + + //! FAKE: there should be a better chained assignment + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] = this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 0; + if (1) {} + if (0) {} + this->fileInfoAlpha[this->selectedFileIndex] = this->nameAlpha[this->selectedFileIndex] = + this->nameBoxAlpha[this->selectedFileIndex] = this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT]; + + this->actionTimer = 45; + } + } else { + sEraseDelayTimer--; + + if (sEraseDelayTimer == 0) { + play_sound(NA_SE_OC_ABYSS); + } + } +} + +/** + * Update and wait for the save to flash to complete. + * Update function for `CM_ERASE_WAIT_FOR_FLASH_SAVE` + */ +void FileSelect_EraseWaitForFlashSave(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + u16 i; + + Sram_UpdateWriteToFlashDefault(sramCtx); + + if (sramCtx->status == 0) { + this->configMode = CM_ERASE_ANIM_1; + for (i = 0; i < 6; i++) { + this->newf[this->selectedFileIndex][i] = gSaveContext.save.saveInfo.playerData.newf[i]; + } + } +} + +/** + * Wait for a delay timer or for the palyer to press a button before returning to the main menu. + * Update function for `CM_ERASE_ANIM_2` + */ +void FileSelect_EraseAnim2(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + Input* input = CONTROLLER1(&this->state); + + if (CHECK_BTN_ANY(input->press.button, BTN_A | BTN_B | BTN_START) || (--this->actionTimer == 0)) { + this->buttonYOffsets[3] = 0; + this->actionTimer = 4; + this->nextTitleLabel = FS_TITLE_SELECT_FILE; + this->configMode++; // CM_ERASE_ANIM_3 + play_sound(NA_SE_SY_FSEL_CLOSE); + } +} + +/** + * Exit from the erase animation to the main menu. Return all buttons and labels to their original place. + * Update function for `CM_ERASE_ANIM_3` + */ +void FileSelect_EraseAnim3(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + SramContext* sramCtx = &this->sramCtx; + s16 i; + s32 yStep; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= 0) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + for (i = 0; i < 3; i++) { + this->fileButtonAlpha[i] += 200 / 4; + + 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; + } + } + + if (this->fileButtonAlpha[this->selectedFileIndex] >= 200) { + this->fileButtonAlpha[this->selectedFileIndex] = 200; + } + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->fileNamesY[this->selectedFileIndex] = 0; + this->highlightColor[3] = 70; + this->highlightPulseDir = 1; + this->highlightTimer = 20; + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = 200; + this->confirmButtonAlpha[FS_BTN_CONFIRM_YES] = this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 0; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode = CM_MAIN_MENU; + } + + this->optionButtonAlpha = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->actionButtonAlpha[FS_BTN_ACTION_COPY]; +} + +/** + * Exit from the erase select screen to the main menu. Return all buttons and labels to their original place. + * Update function for `CM_EXIT_ERASE_TO_MAIN` + */ +void FileSelect_ExitEraseToMain(GameState* thisx) { + FileSelectState* this = (FileSelectState*)thisx; + s16 i; + s32 yStep; + + for (i = 0; i < 5; i++) { + yStep = ABS_ALT(this->buttonYOffsets[i]) / this->actionTimer; + + if (this->buttonYOffsets[i] >= 0) { + this->buttonYOffsets[i] -= yStep; + } else { + this->buttonYOffsets[i] += yStep; + } + } + + this->actionButtonAlpha[FS_BTN_ACTION_COPY] += 200 / 4; + this->actionButtonAlpha[FS_BTN_ACTION_ERASE] += 200 / 4; + this->optionButtonAlpha += 200 / 4; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] -= 200 / 2; + + if (this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] <= 0) { + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 0; + } + + this->titleAlpha[FS_TITLE_CUR] -= 255 / 4; + this->titleAlpha[FS_TITLE_NEXT] += 255 / 4; + this->actionTimer--; + + if (this->actionTimer == 0) { + this->highlightColor[3] = 70; + this->highlightPulseDir = 1; + this->highlightTimer = 20; + this->actionButtonAlpha[FS_BTN_ACTION_COPY] = 200; + this->confirmButtonAlpha[FS_BTN_CONFIRM_QUIT] = 0; + this->titleLabel = this->nextTitleLabel; + this->titleAlpha[FS_TITLE_CUR] = 255; + this->titleAlpha[FS_TITLE_NEXT] = 0; + this->configMode = CM_MAIN_MENU; + } + + this->optionButtonAlpha = this->actionButtonAlpha[FS_BTN_ACTION_ERASE] = + this->actionButtonAlpha[FS_BTN_ACTION_COPY]; +} diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_nameset_NES.c b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_NES.c index c6e3983d8e..02236002a8 100644 --- a/src/overlays/gamestates/ovl_file_choose/z_file_nameset_NES.c +++ b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_NES.c @@ -1,78 +1,1059 @@ /* * File: z_file_nameset_NES.c * Overlay: ovl_file_choose - * Description: + * Description: Entering name on a new file, selecting options from the options menu */ -#include "z_file_choose.h" +#include "prevent_bss_reordering.h" +#include "z_file_select.h" #include "z64rumble.h" +#include "misc/title_static/title_static.h" +#include "overlays/ovl_file_choose/ovl_file_choose.h" -extern UNK_TYPE D_01002800; -extern UNK_TYPE D_01007980; -extern UNK_TYPE D_0102A6B0; -extern UNK_TYPE D_0102B170; -extern UNK_TYPE D_010310F0; -extern UNK_TYPE D_010311F0; +void FileSelect_DrawTexQuadI4(GraphicsContext* gfxCtx, TexturePtr texture, s16 point) { + OPEN_DISPS(gfxCtx); -// there are uses of D_0E000000.fillRect (appearing as D_0E0002E0) in this file -extern GfxMasterList D_0E000000; + 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80804010.s") + CLOSE_DISPS(gfxCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808041A0.s") +void FileSelect_DrawMultiTexQuadI4(GraphicsContext* gfxCtx, TexturePtr texture1, TexturePtr texture2, s16 point) { + OPEN_DISPS(gfxCtx); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80804654.s") + 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); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808047D8.s") + CLOSE_DISPS(gfxCtx); +} -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080489C.s") +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, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80804DAC.s") +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, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80804E74.s") +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, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80804F98.s") +s16 D_80814404[] = { + -94, -96, -48, 0, 32, 64, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080525C.s") +s16 D_80814410[] = { + 56, 44, 44, 28, 28, 44, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808052B0.s") +s16 D_8081441C[] = { + 72, -48, -48, -48, -48, -48, +}; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808054A4.s") +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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808055D0.s") + this->keyboardVtx = GRAPH_ALLOC(this->state.gfxCtx, sizeof(Vtx) * 4 * 5 * 13); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808058A4.s") + phi_s1 = 0x26; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80805918.s") + for (phi_t2 = 0, phi_s2 = 0, phi_t3 = 0; phi_s2 < 5; phi_s2++) { + phi_t0 = -0x60; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80805A58.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80805B30.s") + this->keyboardVtx[phi_t3 + 1].v.ob[0] = this->keyboardVtx[phi_t3 + 3].v.ob[0] = + D_80814304[phi_t2] + phi_t0 + 12; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80805C1C.s") + this->keyboardVtx[phi_t3].v.ob[1] = this->keyboardVtx[phi_t3 + 1].v.ob[1] = phi_s1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806014.s") + this->keyboardVtx[phi_t3 + 2].v.ob[1] = this->keyboardVtx[phi_t3 + 3].v.ob[1] = phi_s1 - 12; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806148.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806310.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808067E0.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806BC8.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806CA0.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806E84.s") + phi_t0 += 0x10; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80806F30.s") + phi_s1 -= 0x10; + } -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808071E4.s") + this->keyboard2Vtx = GRAPH_ALLOC(this->state.gfxCtx, sizeof(Vtx) * 24); -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_80807390.s") + for (phi_t1 = 0, phi_t3 = 0; phi_t3 < 6; phi_t3++, phi_t1 += 4) { -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_8080742C.s") + this->keyboard2Vtx[phi_t1 + 0].v.ob[0] = this->keyboard2Vtx[phi_t1 + 2].v.ob[0] = D_80814404[phi_t3] + 1; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808074B4.s") + 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; -#pragma GLOBAL_ASM("asm/non_matchings/overlays/ovl_file_choose/func_808077AC.s") + 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)) { + play_sound(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; + play_sound(NA_SE_SY_FSEL_CLOSE); + } else { + this->newFileNameCharCount--; + + if (this->newFileNameCharCount < 0) { + this->newFileNameCharCount = 0; + this->configMode = CM_NAME_ENTRY_TO_MAIN; + play_sound(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; + play_sound(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)) { + play_sound(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; + play_sound(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; + play_sound(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) { + play_sound(NA_SE_SY_FSEL_DECIDE_L); + gSaveContext.fileNum = this->buttonIndex; + time = ((void)0, gSaveContext.save.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 { + play_sound(NA_SE_SY_FSEL_ERROR); + } + } + } + } + + if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { + play_sound(NA_SE_SY_FSEL_CURSOR); + this->newFileNameCharCount++; + + if (this->newFileNameCharCount > 7) { + this->newFileNameCharCount = 7; + } + } else if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { + play_sound(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) { + play_sound(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) { + play_sound(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) { + play_sound(NA_SE_SY_FSEL_CURSOR); + this->kbdX--; + if (this->kbdX < 3) { + this->kbdX = 4; + } + } else if (this->stickAdjX > 30) { + play_sound(NA_SE_SY_FSEL_CURSOR); + this->kbdX++; + if (this->kbdX > 4) { + this->kbdX = 3; + } + } + } + + if (this->stickAdjY > 30) { + play_sound(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) { + play_sound(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)) { + play_sound(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; + } + func_801A3D98(gSaveContext.options.audioSetting); + return; + } + + if (this->stickAdjX < -30) { + play_sound(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) { + play_sound(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)) { + play_sound(NA_SE_SY_FSEL_CURSOR); + sSelectedSetting ^= 1; + return; + } + if (CHECK_BTN_ALL(input->press.button, BTN_A)) { + play_sound(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); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + 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); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + 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); + gSPMatrix(POLY_OPA_DISP++, Matrix_NewMtx(this->state.gfxCtx), G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW); + 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); + } + + 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/gamestates/ovl_file_choose/z_file_nameset_data.c b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_data.c new file mode 100644 index 0000000000..47619b66d6 --- /dev/null +++ b/src/overlays/gamestates/ovl_file_choose/z_file_nameset_data.c @@ -0,0 +1,17 @@ +#include "z_file_select.h" + +// Vtx Data +#include "overlays/ovl_file_choose/ovl_file_choose.c" + +u8 D_808141F0[] = { + // 'A' 'B' 'C' 'D' 'E' 'F' 'G' 'H' 'I' 'J' 'K' 'L' 'M' + /* Row 0 */ 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, + // 'N' 'O' 'P' 'Q' 'R' 'S' 'T' 'U' 'V' 'W' 'X' 'Y' 'Z' + /* Row 1 */ 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23, + // 'a' 'b' 'c' 'd' 'e' 'f' 'g' 'h' 'i' 'j' 'k' 'l' 'm' + /* Row 2 */ 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F, 0x30, + // 'n' 'o' 'p' 'q' 'r' 's' 't' 'u' 'v' 'w' 'x' 'y' 'z' + /* Row 3 */ 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, + // '1' '2' '3' '4' '5' '6' '7' '8' '9' '0' '.' '-' ' ' + /* Row 4 */ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x00, 0x40, 0x3F, 0x3E +}; diff --git a/src/overlays/gamestates/ovl_file_choose/z_file_select.h b/src/overlays/gamestates/ovl_file_choose/z_file_select.h new file mode 100644 index 0000000000..7dcc72a9da --- /dev/null +++ b/src/overlays/gamestates/ovl_file_choose/z_file_select.h @@ -0,0 +1,327 @@ +#ifndef FILE_SELECT_H +#define FILE_SELECT_H + +#include "global.h" + +// `sramCtx->noFlashSaveBuf` is never allocated space, so should never be used +// Slot offsets are also based on OoT SaveContext sizes, and contains incorrect sizes from MM +// Macros appear to be remnant from OoT +#define NO_FLASH_GET_NEWF(sramCtx, slotNum, index) \ + (sramCtx->noFlashSaveBuf[gSramSlotOffsets[slotNum] + offsetof(SaveContext, save.saveInfo.playerData.newf[index])]) +#define NO_FLASH_SLOT_OCCUPIED(sramCtx, slotNum) \ + ((NO_FLASH_GET_NEWF(sramCtx, slotNum, 0) == 'Z') || (NO_FLASH_GET_NEWF(sramCtx, slotNum, 1) == 'E') || \ + (NO_FLASH_GET_NEWF(sramCtx, slotNum, 2) == 'L') || (NO_FLASH_GET_NEWF(sramCtx, slotNum, 3) == 'D') || \ + (NO_FLASH_GET_NEWF(sramCtx, slotNum, 4) == 'A') || (NO_FLASH_GET_NEWF(sramCtx, slotNum, 5) == '3')) + +#define GET_NEWF(fileSelect, slotNum, index) (fileSelect->newf[slotNum][index]) +#define SLOT_OCCUPIED(fileSelect, slotNum) \ + ((GET_NEWF(fileSelect, slotNum, 0) == 'Z') && (GET_NEWF(fileSelect, slotNum, 1) == 'E') && \ + (GET_NEWF(fileSelect, slotNum, 2) == 'L') && (GET_NEWF(fileSelect, slotNum, 3) == 'D') && \ + (GET_NEWF(fileSelect, slotNum, 4) == 'A') && (GET_NEWF(fileSelect, slotNum, 5) == '3')) + +// Init mode: Initial setup as the file select is starting up, fades and slides in various menu elements +// Config mode: Handles the bulk of the file select, various configuration tasks like picking a file, copy/erase, and the options menu +// Select mode: Displays the selected file with various details about it, and allows the player to confirm and open it +typedef enum { + /* 0 */ FS_MENU_MODE_INIT, + /* 1 */ FS_MENU_MODE_CONFIG, + /* 2 */ FS_MENU_MODE_SELECT +} MenuMode; + +typedef enum { + /* 0x00 */ CM_FADE_IN_START, + /* 0x01 */ CM_FADE_IN_END, + /* 0x02 */ CM_MAIN_MENU, + /* 0x03 */ CM_SETUP_COPY_SOURCE, + /* 0x04 */ CM_SELECT_COPY_SOURCE, + /* 0x05 */ CM_SETUP_COPY_DEST_1, + /* 0x06 */ CM_SETUP_COPY_DEST_2, + /* 0x07 */ CM_SELECT_COPY_DEST, + /* 0x08 */ CM_EXIT_TO_COPY_SOURCE_1, + /* 0x09 */ CM_EXIT_TO_COPY_SOURCE_2, + /* 0x0A */ CM_SETUP_COPY_CONFIRM_1, + /* 0x0B */ CM_SETUP_COPY_CONFIRM_2, + /* 0x0C */ CM_COPY_CONFIRM, + /* 0x0D */ CM_COPY_WAIT_FOR_FLASH_SAVE, + /* 0x0E */ CM_RETURN_TO_COPY_DEST, + /* 0x0F */ CM_COPY_ANIM_1, + /* 0x10 */ CM_COPY_ANIM_2, + /* 0x11 */ CM_COPY_ANIM_3, + /* 0x12 */ CM_COPY_ANIM_4, + /* 0x13 */ CM_COPY_ANIM_5, + /* 0x14 */ CM_COPY_RETURN_MAIN, + /* 0x15 */ CM_SETUP_ERASE_SELECT, + /* 0x16 */ CM_ERASE_SELECT, + /* 0x17 */ CM_SETUP_ERASE_CONFIRM_1, + /* 0x18 */ CM_SETUP_ERASE_CONFIRM_2, + /* 0x19 */ CM_ERASE_CONFIRM, + /* 0x1A */ CM_EXIT_TO_ERASE_SELECT_1, + /* 0x1B */ CM_EXIT_TO_ERASE_SELECT_2, + /* 0x1C */ CM_ERASE_ANIM_1, + /* 0x1D */ CM_ERASE_WAIT_FOR_FLASH_SAVE, + /* 0x1E */ CM_ERASE_ANIM_2, + /* 0x1F */ CM_ERASE_ANIM_3, + /* 0x20 */ CM_EXIT_ERASE_TO_MAIN, + /* 0x21 */ CM_UNUSED_31, + /* 0x22 */ CM_ROTATE_TO_NAME_ENTRY, + /* 0x23 */ CM_START_NAME_ENTRY, + /* 0x24 */ CM_NAME_ENTRY, + /* 0x25 */ CM_NAME_ENTRY_WAIT_FOR_FLASH_SAVE, + /* 0x26 */ CM_NAME_ENTRY_TO_MAIN, + /* 0x27 */ CM_MAIN_TO_OPTIONS, + /* 0x28 */ CM_START_OPTIONS, + /* 0x29 */ CM_OPTIONS_MENU, + /* 0x2A */ CM_OPTIONS_WAIT_FOR_FLASH_SAVE, + /* 0x2B */ CM_OPTIONS_TO_MAIN, + /* 0x2C */ CM_UNUSED_DELAY +} ConfigMode; + +typedef enum { + /* 0 */ SM_FADE_MAIN_TO_SELECT, + /* 1 */ SM_MOVE_FILE_TO_TOP, + /* 2 */ SM_FADE_IN_FILE_INFO, + /* 3 */ SM_CONFIRM_FILE, + /* 4 */ SM_FADE_OUT_FILE_INFO, + /* 5 */ SM_MOVE_FILE_TO_SLOT, + /* 6 */ SM_FADE_OUT, + /* 7 */ SM_LOAD_GAME +} SelectMode; + +typedef enum { + /* 0 */ FS_TITLE_SELECT_FILE, // "Please select a file." + /* 1 */ FS_TITLE_OPEN_FILE, // "Open this file?" + /* 2 */ FS_TITLE_COPY_FROM, // "Copy which file?" + /* 3 */ FS_TITLE_COPY_TO, // "Copy to which file?" + /* 4 */ FS_TITLE_COPY_CONFIRM, // "Are you sure?" + /* 5 */ FS_TITLE_COPY_COMPLETE, // "File copied." + /* 6 */ FS_TITLE_ERASE_FILE, // "Erase which file?" + /* 7 */ FS_TITLE_ERASE_CONFIRM, // "Are you sure?" + /* 8 */ FS_TITLE_ERASE_COMPLETE // "File erased." +} TitleLabel; + +typedef enum { + /* 0 */ FS_TITLE_CUR, + /* 1 */ FS_TITLE_NEXT +} TitleIndex; + +typedef enum { + /* -1 */ FS_WARNING_NONE = -1, + /* 0 */ FS_WARNING_NO_FILE_COPY, // "No file to copy." + /* 1 */ FS_WARNING_NO_FILE_ERASE, // "No file to erase." + /* 2 */ FS_WARNING_NO_EMPTY_FILES, // "There is no empty file." + /* 3 */ FS_WARNING_FILE_EMPTY, // "This is an empty file." + /* 4 */ FS_WARNING_FILE_IN_USE // "This file is in use." +} WarningLabel; + +typedef enum { + /* 0 */ FS_BTN_MAIN_FILE_1, + /* 1 */ FS_BTN_MAIN_FILE_2, + /* 2 */ FS_BTN_MAIN_FILE_3, + /* 3 */ FS_BTN_MAIN_COPY, + /* 4 */ FS_BTN_MAIN_ERASE, + /* 5 */ FS_BTN_MAIN_OPTIONS +} MainMenuButtonIndex; + +typedef enum { + /* 0 */ FS_BTN_COPY_FILE_1, + /* 1 */ FS_BTN_COPY_FILE_2, + /* 2 */ FS_BTN_COPY_FILE_3, + /* 3 */ FS_BTN_COPY_QUIT +} CopyMenuButtonIndex; + +typedef enum { + /* 0 */ FS_BTN_ERASE_FILE_1, + /* 1 */ FS_BTN_ERASE_FILE_2, + /* 2 */ FS_BTN_ERASE_FILE_3, + /* 3 */ FS_BTN_ERASE_QUIT +} EraseMenuButtonIndex; + +typedef enum { + /* 0 */ FS_BTN_SELECT_FILE_1, + /* 1 */ FS_BTN_SELECT_FILE_2, + /* 2 */ FS_BTN_SELECT_FILE_3, + /* 3 */ FS_BTN_SELECT_YES, + /* 4 */ FS_BTN_SELECT_QUIT +} SelectMenuButtonIndex; + +typedef enum { + /* 0 */ FS_BTN_CONFIRM_YES, + /* 1 */ FS_BTN_CONFIRM_QUIT +} ConfirmButtonIndex; + +typedef enum { + /* 0 */ FS_BTN_ACTION_COPY, + /* 1 */ FS_BTN_ACTION_ERASE +} ActionButtonIndex; + +typedef enum { + /* 0 */ FS_SETTING_AUDIO, + /* 1 */ FS_SETTING_ZTARGET +} SettingIndex; + +typedef enum { + /* 0 */ FS_CHAR_PAGE_HIRA, + /* 1 */ FS_CHAR_PAGE_KATA, + /* 2 */ FS_CHAR_PAGE_ENG +} CharPage; + +typedef enum { + /* 0 */ FS_KBD_BTN_HIRA, + /* 1 */ FS_KBD_BTN_KATA, + /* 2 */ FS_KBD_BTN_ENG, + /* 3 */ FS_KBD_BTN_BACKSPACE, + /* 4 */ FS_KBD_BTN_END, + /* 99 */ FS_KBD_BTN_NONE = 99 +} KeyboardButton; + +typedef struct FileSelectState { + /* 0x00000 */ GameState state; + /* 0x000A4 */ Vtx* windowVtx; + /* 0x000A8 */ u8* staticSegment; + /* 0x000AC */ u8* parameterSegment; + /* 0x000B0 */ u8* titleSegment; + /* 0x000B8 */ View view; + /* 0x00220 */ SramContext sramCtx; + /* 0x00248 */ SkyboxContext skyboxCtx; + /* 0x00470 */ MessageContext msgCtx; + /* 0x12550 */ Font font; + /* 0x242E0 */ EnvironmentContext envCtx; + /* 0x243E0 */ UNK_TYPE1 pad243E0[0x4]; + /* 0x243E4 */ Vtx* windowContentVtx; + /* 0x243E8 */ Vtx* keyboardVtx; + /* 0x243EC */ Vtx* nameEntryVtx; + /* 0x243F0 */ Vtx* keyboard2Vtx; + /* 0x243F4 */ u8 newf[4][6]; + /* 0x2440C */ u16 threeDayResetCount[4]; + /* 0x24414 */ char fileNames[4][8]; + /* 0x24434 */ s16 healthCapacity[4]; + /* 0x2443C */ s16 health[4]; + /* 0x24444 */ u32 questItems[4]; + /* 0x24454 */ s8 defenseHearts[4]; + /* 0x24458 */ u16 time[4]; + /* 0x24460 */ s16 day[4]; + /* 0x24468 */ u8 isOwlSave[4]; + /* 0x2446C */ s16 rupees[4]; + /* 0x24474 */ u8 walletUpgrades[4]; + /* 0x24478 */ u8 maskCount[4]; + /* 0x2447C */ u8 heartPieceCount[4]; + /* 0x24480 */ s16 buttonIndex; // enum will depend on `ConfigMode` + /* 0x24482 */ s16 confirmButtonIndex; // see `ConfirmButtonIndex` enum + /* 0x24484 */ s16 menuMode; // see `MenuMode` enum + /* 0x24486 */ s16 configMode; // see `ConfigMode` enum + /* 0x24488 */ s16 prevConfigMode; // see `ConfigMode` enum + /* 0x2448A */ s16 nextConfigMode; // see `ConfigMode` enum + /* 0x2448C */ s16 selectMode; // see `SelectMode` enum + /* 0x2448E */ s16 selectedFileIndex; + /* 0x24490 */ UNK_TYPE1 pad24490[0x2]; + /* 0x24492 */ s16 fileNamesY[3]; + /* 0x24498 */ s16 actionTimer; + /* 0x2449A */ s16 buttonYOffsets[6]; + /* 0x244A6 */ s16 copyDestFileIndex; + /* 0x244A8 */ s16 warningLabel; + /* 0x244AA */ s16 warningButtonIndex; + /* 0x244AC */ s16 titleLabel; // see `TitleLabel` enum + /* 0x244AE */ s16 nextTitleLabel; // see `TitleLabel` enum + /* 0x244B0 */ s16 windowColor[3]; + /* 0x244B6 */ s16 titleAlpha[2]; // see `TitleIndex` enum + /* 0x244BA */ s16 windowAlpha; + /* 0x244BC */ s16 fileButtonAlpha[3]; + /* 0x244C2 */ s16 nameBoxAlpha[3]; + /* 0x244C8 */ s16 nameAlpha[3]; + /* 0x244CE */ s16 connectorAlpha[3]; + /* 0x244D4 */ s16 fileInfoAlpha[3]; + /* 0x244DA */ s16 actionButtonAlpha[2]; + /* 0x244DA */ s16 confirmButtonAlpha[2]; + /* 0x244E2 */ s16 optionButtonAlpha; + /* 0x244E4 */ s16 nameEntryBoxAlpha; + /* 0x244E6 */ s16 controlsAlpha; + /* 0x244E8 */ s16 emptyFileTextAlpha; + /* 0x244EA */ s16 highlightColor[4]; + /* 0x244F2 */ s16 highlightPulseDir; + /* 0x244F4 */ s16 unk_244F4; + /* 0x244F6 */ s16 confirmButtonTexIndices[2]; + /* 0x244FA */ s16 inputTimerX; + /* 0x244FC */ s16 inputTimerY; + /* 0x244FE */ s16 stickXDir; + /* 0x24500 */ s16 stickYDir; + /* 0x24502 */ s16 stickAdjX; + /* 0x24504 */ s16 stickAdjY; + /* 0x24506 */ s16 nameEntryBoxPosX; + /* 0x24508 */ s16 windowPosX; + /* 0x2450A */ s16 screenFillAlpha; + /* 0x2450C */ f32 windowRot; + /* 0x24510 */ s16 kbdButton; + /* 0x24512 */ s16 charPage; + /* 0x24514 */ s16 charBgAlpha; + /* 0x24516 */ s16 charIndex; + /* 0x24518 */ s16 kbdX; + /* 0x2451A */ s16 kbdY; + /* 0x2451C */ s16 newFileNameCharCount; + /* 0x2451E */ s16 unk_2451E[5]; + /* 0x24528 */ s16 highlightTimer; + /* 0x2452A */ s16 unk_2452A; + /* 0x2452C */ s16 unk_2452C[4]; + /* 0x24534 */ s16 unk_24534[4]; + /* 0x2453C */ s16 unk_2453C[4]; + /* 0x24544 */ s16 unk_24544[4]; + /* 0x2454C */ s16 unk_2454C; + /* 0x2454E */ s16 unk_2454E; + /* 0x24550 */ s16 unk_24550; +} FileSelectState; // size = 0x24558 + +void FileSelect_Init(GameState* thisx); +void FileSelect_Destroy(GameState* thisx); + +void FileSelect_PulsateCursor(GameState* thisx); +void FileSelect_DrawNameEntry(GameState* thisx); +void FileSelect_DrawOptions(GameState* thisx); +void FileSelect_DrawTexQuadI4(GraphicsContext* gfxCtx, TexturePtr texture, s16 point); + +// Copying Files +void FileSelect_SetupCopySource(GameState* thisx); +void FileSelect_SelectCopySource(GameState* thisx); +void FileSelect_SetupCopyDest1(GameState* thisx); +void FileSelect_SetupCopyDest2(GameState* thisx); +void FileSelect_SelectCopyDest(GameState* thisx); +void FileSelect_ExitToCopySource1(GameState* thisx); +void FileSelect_ExitToCopySource2(GameState* thisx); +void FileSelect_SetupCopyConfirm1(GameState* thisx); +void FileSelect_SetupCopyConfirm2(GameState* thisx); +void FileSelect_CopyConfirm(GameState* thisx); +void FileSelect_CopyWaitForFlashSave(GameState* thisx); +void FileSelect_ReturnToCopyDest(GameState* thisx); +void FileSelect_CopyAnim1(GameState* thisx); +void FileSelect_CopyAnim2(GameState* thisx); +void FileSelect_CopyAnim3(GameState* thisx); +void FileSelect_CopyAnim4(GameState* thisx); +void FileSelect_CopyAnim5(GameState* thisx); +void FileSelect_ExitCopyToMain(GameState* thisx); + +// Erasing Files +void FileSelect_SetupEraseSelect(GameState* thisx); +void FileSelect_EraseSelect(GameState* thisx); +void FileSelect_SetupEraseConfirm1(GameState* thisx); +void FileSelect_SetupEraseConfirm2(GameState* thisx); +void FileSelect_EraseConfirm(GameState* thisx); +void FileSelect_ExitToEraseSelect1(GameState* thisx); +void FileSelect_ExitToEraseSelect2(GameState* thisx); +void FileSelect_EraseAnim1(GameState* thisx); +void FileSelect_EraseWaitForFlashSave(GameState* thisx); +void FileSelect_EraseAnim2(GameState* thisx); +void FileSelect_EraseAnim3(GameState* thisx); +void FileSelect_ExitEraseToMain(GameState* thisx); + +// Entering Name +void FileSelect_StartNameEntry(GameState* thisx); +void FileSelect_UpdateKeyboardCursor(GameState* thisx); +void FileSelect_NameEntryWaitForFlashSave(GameState* thisx); + +// Selecting Options +void FileSelect_StartOptions(GameState* thisx); +void FileSelect_UpdateOptionsMenu(GameState* thisx); +void FileSelect_OptionsWaitForFlashSave(GameState* thisx); + +extern u8 D_808141F0[]; +extern s16 D_80814280[]; + +#endif diff --git a/src/overlays/gamestates/ovl_title/z_title.c b/src/overlays/gamestates/ovl_title/z_title.c index 8e270b8367..abde294e5c 100644 --- a/src/overlays/gamestates/ovl_title/z_title.c +++ b/src/overlays/gamestates/ovl_title/z_title.c @@ -171,7 +171,7 @@ void ConsoleLogo_Init(GameState* thisx) { gSaveContext.fileNum = 0xFF; } - gSaveContext.unk_3F3F = true; + gSaveContext.flashSaveAvailable = true; Sram_Alloc(thisx, &this->sramCtx); this->ult = 0; this->timer = 20; diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_debug.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_debug.c index 1eb46728fd..8517fdf209 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_debug.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_debug.c @@ -285,7 +285,7 @@ void KaleidoScope_DrawInventoryEditorText(Gfx** gfxp) { GfxPrint_SetPos(&printer, 23, 22); GfxPrint_Printf(&printer, "%s", "セイ"); - // Life (double defence) + // Life (double defense) GfxPrint_SetPos(&printer, 4, 25); GfxPrint_Printf(&printer, "%s", "イ"); GfxPrint_SetPos(&printer, 4, 26); @@ -601,7 +601,7 @@ void KaleidoScope_DrawInventoryEditor(PlayState* play) { counterDigits[1] += 21; } - // Double Defence + // Double Defense KaleidoScope_DrawDigit(play, gSaveContext.save.saveInfo.playerData.doubleDefense, 44, 202); // Magic @@ -1048,16 +1048,13 @@ void KaleidoScope_UpdateInventoryEditor(PlayState* play) { // Dungeon Items slot = sCurSection - INV_EDITOR_SECTION_DUNGEON_ITEMS; if (CHECK_BTN_ALL(input->press.button, BTN_CLEFT)) { - // Map - gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= 4; + gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= (1 << DUNGEON_MAP); } if (CHECK_BTN_ALL(input->press.button, BTN_CDOWN)) { - // Compass - gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= 2; + gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= (1 << DUNGEON_COMPASS); } if (CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { - // Boss Key - gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= 1; + gSaveContext.save.saveInfo.inventory.dungeonItems[slot] ^= (1 << DUNGEON_BOSS_KEY); } } else if (sCurSection < INV_EDITOR_SECTION_DOUBLE_DEFENSE) { @@ -1077,7 +1074,7 @@ void KaleidoScope_UpdateInventoryEditor(PlayState* play) { } } else { - // Double Defence + // Double Defense if (CHECK_BTN_ALL(input->press.button, BTN_CUP) || CHECK_BTN_ALL(input->press.button, BTN_CLEFT) || CHECK_BTN_ALL(input->press.button, BTN_CDOWN) || CHECK_BTN_ALL(input->press.button, BTN_CRIGHT)) { gSaveContext.save.saveInfo.playerData.doubleDefense ^= 1; diff --git a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c index 9d210a728c..64da25451f 100644 --- a/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c +++ b/src/overlays/kaleido_scope/ovl_kaleido_scope/z_kaleido_scope_NES.c @@ -3060,12 +3060,12 @@ void KaleidoScope_Update(PlayState* play) { Play_SaveCycleSceneFlags(&play->state); gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId; func_8014546C(sramCtx); - if (gSaveContext.unk_3F3F == 0) { + if (!gSaveContext.flashSaveAvailable) { pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_5; } else { - func_80147008(sramCtx, D_801C67C8[gSaveContext.fileNum], - D_801C67F0[gSaveContext.fileNum]); - func_80147020(sramCtx); + Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[gSaveContext.fileNum], + gFlashSaveNumPages[gSaveContext.fileNum]); + Sram_StartWriteToFlashDefault(sramCtx); pauseCtx->savePromptState = PAUSE_SAVEPROMPT_STATE_4; } sDelayTimer = 90; @@ -3327,11 +3327,12 @@ void KaleidoScope_Update(PlayState* play) { gSaveContext.save.saveInfo.playerData.savedSceneId = play->sceneId; gSaveContext.save.saveInfo.playerData.health = 0x30; func_8014546C(sramCtx); - if (gSaveContext.unk_3F3F == 0) { + if (!gSaveContext.flashSaveAvailable) { pauseCtx->state = PAUSE_STATE_GAMEOVER_8; } else { - func_80147008(sramCtx, D_801C67C8[gSaveContext.fileNum], D_801C67F0[gSaveContext.fileNum]); - func_80147020(sramCtx); + Sram_SetFlashPagesDefault(sramCtx, gFlashSaveStartPages[gSaveContext.fileNum], + gFlashSaveNumPages[gSaveContext.fileNum]); + Sram_StartWriteToFlashDefault(sramCtx); pauseCtx->state = PAUSE_STATE_GAMEOVER_7; } sDelayTimer = 90; diff --git a/tools/disasm/functions.txt b/tools/disasm/functions.txt index 4c65de06c4..e4f96e594b 100644 --- a/tools/disasm/functions.txt +++ b/tools/disasm/functions.txt @@ -2802,21 +2802,21 @@ 0x8014546C:("func_8014546C",), 0x80145698:("func_80145698",), 0x801457CC:("func_801457CC",), - 0x80146580:("func_80146580",), - 0x80146628:("func_80146628",), + 0x80146580:("Sram_EraseSave",), + 0x80146628:("Sram_CopySave",), 0x80146AA0:("Sram_InitSave",), - 0x80146DF8:("func_80146DF8",), + 0x80146DF8:("Sram_WriteSaveOptionsToBuffer",), 0x80146E40:("Sram_InitSram",), 0x80146E70:("Sram_Alloc",), - 0x80146EBC:("func_80146EBC",), + 0x80146EBC:("Sram_SyncWriteToFlash",), 0x80146EE8:("Sram_SaveSpecialEnterClockTown",), 0x80146F5C:("Sram_SaveSpecialNewDay",), - 0x80147008:("func_80147008",), - 0x80147020:("func_80147020",), - 0x80147068:("func_80147068",), - 0x80147138:("func_80147138",), - 0x80147150:("func_80147150",), - 0x80147198:("func_80147198",), + 0x80147008:("Sram_SetFlashPagesDefault",), + 0x80147020:("Sram_StartWriteToFlashDefault",), + 0x80147068:("Sram_UpdateWriteToFlashDefault",), + 0x80147138:("Sram_SetFlashPagesOwlSave",), + 0x80147150:("Sram_StartWriteToFlashOwlSave",), + 0x80147198:("Sram_UpdateWriteToFlashOwlSave",), 0x80147314:("func_80147314",), 0x80147414:("func_80147414",), 0x8014750C:("Sram_nop8014750C",), @@ -4107,87 +4107,87 @@ 0x80803EC0:("TitleSetup_Main",), 0x80803F0C:("TitleSetup_Destroy",), 0x80803F30:("TitleSetup_Init",), - 0x80804010:("func_80804010",), - 0x808041A0:("func_808041A0",), - 0x80804654:("func_80804654",), - 0x808047D8:("func_808047D8",), - 0x8080489C:("func_8080489C",), - 0x80804DAC:("func_80804DAC",), - 0x80804E74:("func_80804E74",), - 0x80804F98:("func_80804F98",), - 0x8080525C:("func_8080525C",), - 0x808052B0:("func_808052B0",), - 0x808054A4:("func_808054A4",), - 0x808055D0:("func_808055D0",), - 0x808058A4:("func_808058A4",), - 0x80805918:("func_80805918",), - 0x80805A58:("func_80805A58",), - 0x80805B30:("func_80805B30",), - 0x80805C1C:("func_80805C1C",), - 0x80806014:("func_80806014",), - 0x80806148:("func_80806148",), - 0x80806310:("func_80806310",), - 0x808067E0:("func_808067E0",), - 0x80806BC8:("func_80806BC8",), - 0x80806CA0:("func_80806CA0",), - 0x80806E84:("func_80806E84",), - 0x80806F30:("func_80806F30",), - 0x808071E4:("func_808071E4",), - 0x80807390:("func_80807390",), - 0x8080742C:("func_8080742C",), - 0x808074B4:("func_808074B4",), - 0x808077AC:("func_808077AC",), - 0x80807940:("func_80807940",), - 0x80807A78:("func_80807A78",), - 0x80807C58:("func_80807C58",), - 0x80808214:("func_80808214",), - 0x80808D30:("func_80808D30",), - 0x80808F1C:("func_80808F1C",), - 0x80809DF0:("func_80809DF0",), - 0x80809EA0:("func_80809EA0",), - 0x8080A3CC:("func_8080A3CC",), - 0x8080A418:("func_8080A418",), - 0x8080A4A0:("func_8080A4A0",), - 0x8080A6BC:("func_8080A6BC",), - 0x8080A708:("func_8080A708",), - 0x8080BBFC:("func_8080BBFC",), - 0x8080BC20:("func_8080BC20",), - 0x8080BC44:("FileSelect_nop8080bc44",), - 0x8080BC4C:("FileSelect_nop8080BC4C",), - 0x8080BC58:("func_8080BC58",), - 0x8080BDAC:("func_8080BDAC",), - 0x8080BDDC:("FileSelect_RenderView",), - 0x8080BE60:("func_8080BE60",), - 0x8080C040:("func_8080C040",), - 0x8080C228:("func_8080C228",), - 0x8080C29C:("func_8080C29C",), - 0x8080C324:("func_8080C324",), - 0x8080C3A8:("func_8080C3A8",), - 0x8080D164:("func_8080D164",), - 0x8080D170:("func_8080D170",), - 0x8080D1BC:("func_8080D1BC",), - 0x8080D220:("func_8080D220",), - 0x8080D284:("func_8080D284",), - 0x8080D2EC:("func_8080D2EC",), - 0x8080D3D0:("func_8080D3D0",), - 0x8080D40C:("func_8080D40C",), - 0x8080D6D4:("func_8080D6D4",), - 0x8080F25C:("func_8080F25C",), - 0x808108DC:("func_808108DC",), - 0x80811CB8:("func_80811CB8",), - 0x80812460:("func_80812460",), - 0x80812668:("func_80812668",), - 0x80812760:("func_80812760",), - 0x80812840:("func_80812840",), - 0x80812980:("func_80812980",), - 0x80812A6C:("func_80812A6C",), - 0x80812D44:("func_80812D44",), - 0x80812D94:("func_80812D94",), - 0x80812E94:("func_80812E94",), - 0x80812ED0:("func_80812ED0",), + 0x80804010:("FileSelect_SetupCopySource",), + 0x808041A0:("FileSelect_SelectCopySource",), + 0x80804654:("FileSelect_SetupCopyDest1",), + 0x808047D8:("FileSelect_SetupCopyDest2",), + 0x8080489C:("FileSelect_SelectCopyDest",), + 0x80804DAC:("FileSelect_ExitToCopySource1",), + 0x80804E74:("FileSelect_ExitToCopySource2",), + 0x80804F98:("FileSelect_SetupCopyConfirm1",), + 0x8080525C:("FileSelect_SetupCopyConfirm2",), + 0x808052B0:("FileSelect_CopyConfirm",), + 0x808054A4:("FileSelect_CopyWaitForFlashSave",), + 0x808055D0:("FileSelect_ReturnToCopyDest",), + 0x808058A4:("FileSelect_CopyAnim1",), + 0x80805918:("FileSelect_CopyAnim2",), + 0x80805A58:("FileSelect_CopyAnim3",), + 0x80805B30:("FileSelect_CopyAnim4",), + 0x80805C1C:("FileSelect_CopyAnim5",), + 0x80806014:("FileSelect_ExitCopyToMain",), + 0x80806148:("FileSelect_SetupEraseSelect",), + 0x80806310:("FileSelect_EraseSelect",), + 0x808067E0:("FileSelect_SetupEraseConfirm1",), + 0x80806BC8:("FileSelect_SetupEraseConfirm2",), + 0x80806CA0:("FileSelect_EraseConfirm",), + 0x80806E84:("FileSelect_ExitToEraseSelect1",), + 0x80806F30:("FileSelect_ExitToEraseSelect2",), + 0x808071E4:("FileSelect_EraseAnim1",), + 0x80807390:("FileSelect_EraseWaitForFlashSave",), + 0x8080742C:("FileSelect_EraseAnim2",), + 0x808074B4:("FileSelect_EraseAnim3",), + 0x808077AC:("FileSelect_ExitEraseToMain",), + 0x80807940:("FileSelect_DrawTexQuadI4",), + 0x80807A78:("FileSelect_DrawMultiTexQuadI4",), + 0x80807C58:("FileSelect_SetKeyboardVtx",), + 0x80808214:("FileSelect_SetNameEntryVtx",), + 0x80808D30:("FileSelect_DrawKeyboard",), + 0x80808F1C:("FileSelect_DrawNameEntry",), + 0x80809DF0:("FileSelect_StartNameEntry",), + 0x80809EA0:("FileSelect_UpdateKeyboardCursor",), + 0x8080A3CC:("FileSelect_NameEntryWaitForFlashSave",), + 0x8080A418:("FileSelect_StartOptions",), + 0x8080A4A0:("FileSelect_UpdateOptionsMenu",), + 0x8080A6BC:("FileSelect_OptionsWaitForFlashSave",), + 0x8080A708:("FileSelect_DrawOptionsImpl",), + 0x8080BBFC:("FileSelect_DrawOptions",), + 0x8080BC20:("FileSelect_IncrementConfigMode",), + 0x8080BC44:("FileSelect_Noop1",), + 0x8080BC4C:("FileSelect_Noop2",), + 0x8080BC58:("FileSelect_InitModeUpdate",), + 0x8080BDAC:("FileSelect_InitModeDraw",), + 0x8080BDDC:("FileSelect_SetView",), + 0x8080BE60:("FileSelect_DrawTexQuadIA8",), + 0x8080C040:("FileSelect_FadeInMenuElements",), + 0x8080C228:("FileSelect_SplitNumber",), + 0x8080C29C:("FileSelect_StartFadeIn",), + 0x8080C324:("FileSelect_FinishFadeIn",), + 0x8080C3A8:("FileSelect_UpdateMainMenu",), + 0x8080D164:("FileSelect_UnusedCM31",), + 0x8080D170:("FileSelect_UnusedCMDelay",), + 0x8080D1BC:("FileSelect_RotateToNameEntry",), + 0x8080D220:("FileSelect_RotateToOptions",), + 0x8080D284:("FileSelect_RotateToMain",), + 0x8080D2EC:("FileSelect_PulsateCursor",), + 0x8080D3D0:("FileSelect_ConfigModeUpdate",), + 0x8080D40C:("FileSelect_SetWindowVtx",), + 0x8080D6D4:("FileSelect_SetWindowContentVtx",), + 0x8080F25C:("FileSelect_DrawFileInfo",), + 0x808108DC:("FileSelect_DrawWindowContents",), + 0x80811CB8:("FileSelect_ConfigModeDraw",), + 0x80812460:("FileSelect_FadeMainToSelect",), + 0x80812668:("FileSelect_MoveSelectedFileToTop",), + 0x80812760:("FileSelect_FadeInFileInfo",), + 0x80812840:("FileSelect_ConfirmFile",), + 0x80812980:("FileSelect_FadeOutFileInfo",), + 0x80812A6C:("FileSelect_MoveSelectedFileToSlot",), + 0x80812D44:("FileSelect_FadeOut",), + 0x80812D94:("FileSelect_LoadGame",), + 0x80812E94:("FileSelect_SelectModeUpdate",), + 0x80812ED0:("FileSelect_SelectModeDraw",), 0x8081313C:("FileSelect_UpdateAndDrawSkybox",), 0x80813268:("FileSelect_Main",), - 0x80813908:("func_80813908",), + 0x80813908:("FileSelect_InitContext",), 0x80813C74:("FileSelect_Destroy",), 0x80813C98:("FileSelect_Init",), 0x80814EB0:("DayTelop_Update",), diff --git a/tools/disasm/variables.txt b/tools/disasm/variables.txt index daa6aff8f0..3a14118c56 100644 --- a/tools/disasm/variables.txt +++ b/tools/disasm/variables.txt @@ -1927,14 +1927,14 @@ 0x801C5F44:("D_801C5F44","UNK_TYPE4","",0x4), 0x801C5FC0:("sPersistentCycleFlags","u32","[452]",0x710), 0x801C66D0:("D_801C66D0","UNK_TYPE2","",0x2), - 0x801C6798:("D_801C6798","UNK_TYPE4","",0x4), + 0x801C6798:("gSramSlotOffsets","UNK_TYPE4","",0x4), 0x801C67B0:("gAmmoItems","UNK_TYPE1","",0x1), - 0x801C67C8:("D_801C67C8","s32","[10]",0x28), - 0x801C67F0:("D_801C67F0","s32","[10]",0x28), - 0x801C6818:("D_801C6818","s32","[10]",0x28), - 0x801C6840:("D_801C6840","UNK_TYPE1","",0x1), - 0x801C6850:("D_801C6850","UNK_TYPE1","",0x1), - 0x801C6870:("D_801C6870","UNK_TYPE1","",0x1), + 0x801C67C8:("gFlashSaveStartPages","s32","[10]",0x28), + 0x801C67F0:("gFlashSaveNumPages","s32","[10]",0x28), + 0x801C6818:("gFlashSpecialSaveNumPages","s32","[10]",0x28), + 0x801C6840:("gFlashOwlSaveStartPages","UNK_TYPE1","",0x1), + 0x801C6850:("gFlashOwlSaveNumPages","UNK_TYPE1","",0x1), + 0x801C6870:("gFlashSaveSizes","UNK_TYPE1","",0x1), 0x801C6890:("D_801C6890","UNK_TYPE1","",0x1), 0x801C6898:("sSaveDefaultPlayerData","SavePlayerData","",0x28), 0x801C68C0:("sSaveDefaultItemEquips","ItemEquips","",0x22), @@ -4544,13 +4544,13 @@ 0x80803FC8:("openingCutscenes","u32","[2]",0x8), 0x80813DF0:("D_80813DF0","UNK_TYPE1","",0x1), 0x80813F30:("D_80813F30","UNK_TYPE1","",0x1), - 0x80814130:("D_80814130","UNK_TYPE1","",0x1), - 0x80814170:("D_80814170","UNK_TYPE1","",0x1), - 0x808141B0:("D_808141B0","UNK_TYPE1","",0x1), + 0x80814130:("gOptionsDividerTopVtx","UNK_TYPE1","",0x1), + 0x80814170:("gOptionsDividerMiddleVtx","UNK_TYPE1","",0x1), + 0x808141B0:("gOptionsDividerBottomVtx","UNK_TYPE1","",0x1), 0x808141F0:("D_808141F0","UNK_TYPE1","",0x1), - 0x80814240:("D_80814240","UNK_TYPE2","",0x2), + 0x80814240:("sChooseFileYOffsets","UNK_TYPE2","",0x2), 0x8081424C:("D_8081424C","UNK_TYPE2","",0x2), - 0x80814260:("D_80814260","UNK_TYPE2","",0x2), + 0x80814260:("sEraseDelayTimer","UNK_TYPE2","",0x2), 0x80814264:("D_80814264","UNK_TYPE2","",0x2), 0x8081426C:("D_8081426C","UNK_TYPE1","",0x1), 0x80814280:("D_80814280","UNK_TYPE1","",0x1), @@ -4559,31 +4559,31 @@ 0x80814404:("D_80814404","UNK_TYPE2","",0x2), 0x80814410:("D_80814410","UNK_TYPE2","",0x2), 0x8081441C:("D_8081441C","UNK_TYPE2","",0x2), - 0x80814428:("D_80814428","UNK_TYPE4","",0x4), - 0x80814430:("D_80814430","UNK_TYPE2","",0x2), + 0x80814428:("sBackspaceEndTextures","UNK_TYPE4","",0x4), + 0x80814430:("sBackspaceEndWidths","UNK_TYPE2","",0x2), 0x80814434:("D_80814434","UNK_TYPE2","",0x2), 0x8081444C:("D_8081444C","UNK_TYPE1","",0x1), - 0x80814464:("D_80814464","UNK_TYPE4","",0x4), - 0x8081448C:("D_8081448C","UNK_TYPE4","",0x4), - 0x808144BC:("D_808144BC","UNK_TYPE2","",0x2), - 0x808144C0:("D_808144C0","UNK_TYPE2","",0x2), - 0x808144C4:("D_808144C4","UNK_TYPE2","",0x2), - 0x808144C8:("D_808144C8","UNK_TYPE2","",0x2), - 0x808144CC:("D_808144CC","UNK_TYPE2","",0x2), - 0x808144D0:("D_808144D0","UNK_TYPE2","",0x2), - 0x808144D4:("D_808144D4","UNK_TYPE2","",0x2), - 0x808144D8:("D_808144D8","UNK_TYPE2","",0x2), - 0x808144DC:("D_808144DC","UNK_TYPE1","",0x1), - 0x808144E8:("D_808144E8","UNK_TYPE1","",0x1), - 0x80814510:("D_80814510","Gfx","[5]",0x28), - 0x80814538:("D_80814538","UNK_TYPE2","",0x2), - 0x80814548:("D_80814548","UNK_TYPE2","",0x2), - 0x80814550:("fileChooseSkyboxRotation","s16","",0x2), - 0x80814554:("D_80814554","UNK_TYPE1","",0x1), - 0x8081455C:("D_8081455C","UNK_TYPE1","",0x1), + 0x80814464:("gOptionsMenuHeaders","UNK_TYPE4","",0x4), + 0x8081448C:("gOptionsMenuSettings","UNK_TYPE4","",0x4), + 0x808144BC:("sCursorPrimRed","UNK_TYPE2","",0x2), + 0x808144C0:("sCursorPrimGreen","UNK_TYPE2","",0x2), + 0x808144C4:("sCursorPrimBlue","UNK_TYPE2","",0x2), + 0x808144C8:("sCursorEnvRed","UNK_TYPE2","",0x2), + 0x808144CC:("sCursorEnvGreen","UNK_TYPE2","",0x2), + 0x808144D0:("sCursorEnvBlue","UNK_TYPE2","",0x2), + 0x808144D4:("sCursorPulseDir","UNK_TYPE2","",0x2), + 0x808144D8:("sCursorFlashTimer","UNK_TYPE2","",0x2), + 0x808144DC:("sCursorPrimColors","UNK_TYPE1","",0x1), + 0x808144E8:("sCursorEnvColors","UNK_TYPE1","",0x1), + 0x80814510:("sScreenFillSetupDL","Gfx","[5]",0x28), + 0x80814538:("sFileInfoBoxPartWidths","UNK_TYPE2","",0x2), + 0x80814548:("sWindowContentColors","UNK_TYPE2","",0x2), + 0x80814550:("sFileSelectSkyboxRotation","s16","",0x2), + 0x80814554:("sWalletFirstDigit","UNK_TYPE1","",0x1), + 0x8081455C:("sEmptyName","UNK_TYPE1","",0x1), 0x80814564:("D_80814564","UNK_TYPE2","",0x2), - 0x80814568:("D_80814568","UNK_TYPE","[45]",0xb4), - 0x8081461C:("D_8081461C","s16","[2]",0x4), + 0x80814568:("sConfigModeUpdateFuncs","UNK_TYPE","[45]",0xb4), + 0x8081461C:("sCursorAlphaTargets","s16","[2]",0x4), 0x80814620:("D_80814620","UNK_TYPE2","",0x2), 0x80814628:("D_80814628","UNK_TYPE2","",0x2), 0x80814630:("D_80814630","UNK_TYPE2","",0x2), @@ -4592,24 +4592,24 @@ 0x8081464C:("D_8081464C","UNK_TYPE1","",0x1), 0x80814650:("D_80814650","UNK_TYPE1","",0x1), 0x80814654:("D_80814654","UNK_TYPE1","",0x1), - 0x8081465C:("D_8081465C","UNK_TYPE4","",0x4), - 0x8081466C:("D_8081466C","UNK_TYPE1","",0x1), - 0x8081467C:("D_8081467C","UNK_TYPE1","",0x1), - 0x8081468C:("D_8081468C","UNK_TYPE4","",0x4), - 0x808146B4:("D_808146B4","UNK_TYPE1","",0x1), - 0x808146C4:("D_808146C4","UNK_TYPE1","",0x1), - 0x808146D8:("D_808146D8","UNK_TYPE1","",0x1), - 0x808146EC:("D_808146EC","UNK_TYPE2","",0x2), - 0x808146F8:("D_808146F8","UNK_TYPE2","",0x2), - 0x80814704:("D_80814704","UNK_TYPE4","",0x4), - 0x80814720:("D_80814720","UNK_TYPE1","",0x1), - 0x80814744:("D_80814744","UNK_TYPE1","",0x1), - 0x80814758:("D_80814758","UNK_TYPE4","",0x4), - 0x80814764:("D_80814764","UNK_TYPE4","",0x4), - 0x80814774:("D_80814774","UNK_TYPE1","",0x1), - 0x8081477C:("D_8081477C","UNK_TYPE","[8]",0x20), - 0x8081479C:("D_8081479C","UNK_TYPE","[3]",0xc), - 0x808147A8:("D_808147A8","UNK_TYPE","[3]",0xc), + 0x8081465C:("sFileSelRemainsTextures","UNK_TYPE4","",0x4), + 0x8081466C:("sFileSelDayENGTextures","UNK_TYPE1","",0x1), + 0x8081467C:("sFileSelHeartPieceTextures","UNK_TYPE1","",0x1), + 0x8081468C:("sHeartTextures","UNK_TYPE4","",0x4), + 0x808146B4:("sHealthToQuarterHeartCount","UNK_TYPE1","",0x1), + 0x808146C4:("sFileSelRupeePrimColors","UNK_TYPE1","",0x1), + 0x808146D8:("sFileSelRupeeEnvColors","UNK_TYPE1","",0x1), + 0x808146EC:("sHeartPrimColors","UNK_TYPE2","",0x2), + 0x808146F8:("sHeartEnvColors","UNK_TYPE2","",0x2), + 0x80814704:("sFileInfoBoxTextures","UNK_TYPE4","",0x4), + 0x80814720:("sTitleLabels","UNK_TYPE1","",0x1), + 0x80814744:("sWarningLabels","UNK_TYPE1","",0x1), + 0x80814758:("sFileButtonTextures","UNK_TYPE4","",0x4), + 0x80814764:("sActionButtonTextures","UNK_TYPE4","",0x4), + 0x80814774:("sFileYOffsets","UNK_TYPE1","",0x1), + 0x8081477C:("sSelectModeUpdateFuncs","UNK_TYPE","[8]",0x20), + 0x8081479C:("gFileSelectDrawFuncs","UNK_TYPE","[3]",0xc), + 0x808147A8:("gFileSelectUpdateFuncs","UNK_TYPE","[3]",0xc), 0x808147B4:("D_808147B4","UNK_TYPE4","",0x4), 0x808147C0:("D_808147C0","UNK_TYPE2","",0x2), 0x808147C8:("D_808147C8","UNK_TYPE2","",0x2), @@ -4622,7 +4622,7 @@ 0x808147EC:("D_808147EC","f32","",0x4), 0x808147F0:("D_808147F0","f32","",0x4), 0x80814E80:("D_80814E80","UNK_TYPE1","",0x1), - 0x80814E90:("D_80814E90","UNK_TYPE1","",0x1), + 0x80814E90:("sSelectedSetting","UNK_TYPE1","",0x1), 0x80815FF0:("D_80815FF0","u8","",0x1), 0x80815FF4:("sDayLeftTextures","TexturePtr","[4]",0x10), 0x80816004:("sDayRightTextures","TexturePtr","[4]",0x10), diff --git a/tools/sizes/code_functions.csv b/tools/sizes/code_functions.csv index 6713041f7f..3d5839a69f 100644 --- a/tools/sizes/code_functions.csv +++ b/tools/sizes/code_functions.csv @@ -2316,21 +2316,21 @@ asm/non_matchings/code/z_sram_NES/Sram_OpenSave.s,Sram_OpenSave,0x80144E78,0x17D asm/non_matchings/code/z_sram_NES/func_8014546C.s,func_8014546C,0x8014546C,0x8B asm/non_matchings/code/z_sram_NES/func_80145698.s,func_80145698,0x80145698,0x4D asm/non_matchings/code/z_sram_NES/func_801457CC.s,func_801457CC,0x801457CC,0x36D -asm/non_matchings/code/z_sram_NES/func_80146580.s,func_80146580,0x80146580,0x2A -asm/non_matchings/code/z_sram_NES/func_80146628.s,func_80146628,0x80146628,0x11E +asm/non_matchings/code/z_sram_NES/Sram_EraseSave.s,Sram_EraseSave,0x80146580,0x2A +asm/non_matchings/code/z_sram_NES/Sram_CopySave.s,Sram_CopySave,0x80146628,0x11E asm/non_matchings/code/z_sram_NES/Sram_InitSave.s,Sram_InitSave,0x80146AA0,0xD6 -asm/non_matchings/code/z_sram_NES/func_80146DF8.s,func_80146DF8,0x80146DF8,0x12 +asm/non_matchings/code/z_sram_NES/Sram_WriteSaveOptionsToBuffer.s,Sram_WriteSaveOptionsToBuffer,0x80146DF8,0x12 asm/non_matchings/code/z_sram_NES/Sram_InitSram.s,Sram_InitSram,0x80146E40,0xC asm/non_matchings/code/z_sram_NES/Sram_Alloc.s,Sram_Alloc,0x80146E70,0x13 -asm/non_matchings/code/z_sram_NES/func_80146EBC.s,func_80146EBC,0x80146EBC,0xB +asm/non_matchings/code/z_sram_NES/Sram_SyncWriteToFlash.s,Sram_SyncWriteToFlash,0x80146EBC,0xB asm/non_matchings/code/z_sram_NES/Sram_SaveSpecialEnterClockTown.s,Sram_SaveSpecialEnterClockTown,0x80146EE8,0x1D asm/non_matchings/code/z_sram_NES/Sram_SaveSpecialNewDay.s,Sram_SaveSpecialNewDay,0x80146F5C,0x2B -asm/non_matchings/code/z_sram_NES/func_80147008.s,func_80147008,0x80147008,0x6 -asm/non_matchings/code/z_sram_NES/func_80147020.s,func_80147020,0x80147020,0x12 -asm/non_matchings/code/z_sram_NES/func_80147068.s,func_80147068,0x80147068,0x34 -asm/non_matchings/code/z_sram_NES/func_80147138.s,func_80147138,0x80147138,0x6 -asm/non_matchings/code/z_sram_NES/func_80147150.s,func_80147150,0x80147150,0x12 -asm/non_matchings/code/z_sram_NES/func_80147198.s,func_80147198,0x80147198,0x5F +asm/non_matchings/code/z_sram_NES/Sram_SetFlashPagesDefault.s,Sram_SetFlashPagesDefault,0x80147008,0x6 +asm/non_matchings/code/z_sram_NES/Sram_StartWriteToFlashDefault.s,Sram_StartWriteToFlashDefault,0x80147020,0x12 +asm/non_matchings/code/z_sram_NES/Sram_UpdateWriteToFlashDefault.s,Sram_UpdateWriteToFlashDefault,0x80147068,0x34 +asm/non_matchings/code/z_sram_NES/Sram_SetFlashPagesOwlSave.s,Sram_SetFlashPagesOwlSave,0x80147138,0x6 +asm/non_matchings/code/z_sram_NES/Sram_StartWriteToFlashOwlSave.s,Sram_StartWriteToFlashOwlSave,0x80147150,0x12 +asm/non_matchings/code/z_sram_NES/Sram_UpdateWriteToFlashOwlSave.s,Sram_UpdateWriteToFlashOwlSave,0x80147198,0x5F asm/non_matchings/code/z_sram_NES/func_80147314.s,func_80147314,0x80147314,0x40 asm/non_matchings/code/z_sram_NES/func_80147414.s,func_80147414,0x80147414,0x3E asm/non_matchings/code/z_sram_NES/Sram_nop8014750C.s,Sram_nop8014750C,0x8014750C,0x5