summaryrefslogtreecommitdiff
path: root/src/save_failed_screen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/save_failed_screen.c')
-rw-r--r--src/save_failed_screen.c301
1 files changed, 301 insertions, 0 deletions
diff --git a/src/save_failed_screen.c b/src/save_failed_screen.c
new file mode 100644
index 000000000..41e61eadb
--- /dev/null
+++ b/src/save_failed_screen.c
@@ -0,0 +1,301 @@
+#include "global.h"
+#include "main.h"
+#include "sprite.h"
+#include "palette.h"
+#include "task.h"
+#include "text.h"
+#include "menu.h"
+#include "save.h"
+#include "m4a.h"
+#include "gba/flash_internal.h"
+#include "asm.h"
+
+// In English 1.0, the text window is too small, causing text to overflow.
+
+#ifdef BUGFIX_SAVEFAILEDSCREEN1
+#define MSG_WIN_TOP 10
+#else
+#define MSG_WIN_TOP 12
+#endif
+
+#define CLOCK_WIN_TOP (MSG_WIN_TOP - 4)
+
+struct SaveFailedStruct
+{
+ u16 unk0;
+ u16 unk2;
+};
+
+extern u8 unk_2000000[];
+
+extern u16 gUnknown_0203933C;
+extern struct SaveFailedStruct gUnknown_0203933E;
+extern u32 gUnknown_03005EA8;
+extern u32 gUnknown_03005EBC;
+
+extern struct OamData gUnknown_08411940;
+extern u8 gUnknown_08411948[][3];
+
+extern u8 gBirchHelpGfx[];
+
+extern u8 gSystemText_SaveFailedBackupCheck[];
+extern u8 gSystemText_CheckCompleteSaveAttempt[];
+extern u8 gSystemText_BackupDamagedGameContinue[];
+extern u8 gSystemText_SaveCompletedPressA[];
+extern u8 gSystemText_SaveCompletedGameEnd[];
+extern u8 gSystemText_GameplayEnded[];
+
+extern u8 gBirchGrassTilemap[];
+extern u8 gBirchBagTilemap[];
+
+extern const u8 gSaveFailedClockGfx[];
+extern const u8 gSaveFailedClockPal[];
+extern u8 gBirchBagGrassPal[];
+
+static void VBlankCB(void);
+static void CB2_SaveFailedScreen(void);
+static void CB2_WipeSave(void);
+static void CB2_GameplayCannotBeContinued(void);
+static void CB2_FadeAndReturnToTitleScreen(void);
+static void CB2_ReturnToTitleScreen(void);
+static void VBlankCB_UpdateClockGraphics(void);
+static bool8 VerifySectorWipe(u16 sector);
+static bool8 WipeSector(u16 sector);
+static bool8 WipeSectors(u32 sectorBits);
+
+void DoSaveFailedScreen(u8 var)
+{
+ SetMainCallback2(CB2_SaveFailedScreen);
+ gUnknown_0203933C = var;
+ gUnknown_0203933E.unk0 = 0;
+}
+
+static void VBlankCB(void)
+{
+ LoadOam();
+ ProcessSpriteCopyRequests();
+ TransferPlttBuffer();
+}
+
+static void CB2_SaveFailedScreen(void)
+{
+ u16 ime;
+
+ switch(gMain.state)
+ {
+ case 0:
+ default:
+ SetVBlankCallback(0);
+ REG_DISPCNT = 0;
+ REG_BG3CNT = 0;
+ REG_BG2CNT = 0;
+ REG_BG1CNT = 0;
+ REG_BG0CNT = 0;
+ REG_BG3HOFS = 0;
+ REG_BG3VOFS = 0;
+ REG_BG2HOFS = 0;
+ REG_BG2VOFS = 0;
+ REG_BG1HOFS = 0;
+ REG_BG1VOFS = 0;
+ REG_BG0HOFS = 0;
+ REG_BG0VOFS = 0;
+ DmaFill16(3, 0, VRAM, VRAM_SIZE);
+ DmaFill32(3, 0, OAM, OAM_SIZE);
+ DmaFill16(3, 0, PLTT, PLTT_SIZE);
+ LZ77UnCompVram(&gBirchHelpGfx, (void *)VRAM);
+ LZ77UnCompVram(&gBirchBagTilemap, (void *)(VRAM + 0x3000));
+ LZ77UnCompVram(&gBirchGrassTilemap, (void *)(VRAM + 0x3800));
+ LZ77UnCompVram(&gSaveFailedClockGfx, (void *)(VRAM + 0x10020));
+ ResetSpriteData();
+ ResetTasks();
+ ResetPaletteFade();
+ LoadPalette(&gBirchBagGrassPal, 0, 0x40);
+ LoadPalette(&gSaveFailedClockPal, 0x100, 0x20);
+ SetUpWindowConfig(&gWindowConfig_81E6C3C);
+ InitMenuWindow(&gWindowConfig_81E6CE4);
+ MenuDrawTextWindow(13, CLOCK_WIN_TOP, 16, CLOCK_WIN_TOP + 3); // clock window
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19); // message window
+ MenuPrint(gSystemText_SaveFailedBackupCheck, 2, MSG_WIN_TOP + 1);
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0);
+ ime = REG_IME;
+ REG_IME = 0;
+ REG_IE |= INTR_FLAG_VBLANK;
+ REG_IME = ime;
+ REG_DISPSTAT |= DISPSTAT_VBLANK_INTR;
+ SetVBlankCallback(VBlankCB);
+ REG_BG3CNT = 0x703;
+ REG_BG2CNT = 0x602;
+ REG_BG0CNT = 0x1f08;
+ REG_DISPCNT = DISPCNT_OBJ_ON | DISPCNT_BG3_ON | DISPCNT_BG2_ON | DISPCNT_BG0_ON | DISPCNT_OBJ_1D_MAP | DISPCNT_MODE_0;
+ gMain.state++;
+ break;
+ case 1:
+ if (!UpdatePaletteFade())
+ {
+ SetMainCallback2(CB2_WipeSave);
+ SetVBlankCallback(VBlankCB_UpdateClockGraphics);
+ }
+ break;
+ }
+}
+
+static void CB2_WipeSave(void)
+{
+ u8 wipeTries = 0;
+
+ gUnknown_0203933E.unk0 = 1;
+
+ while (gUnknown_03005EA8 && wipeTries < 3)
+ {
+ if (WipeSectors(gUnknown_03005EA8))
+ {
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+ MenuPrint(gSystemText_BackupDamagedGameContinue, 2, MSG_WIN_TOP + 1);
+ SetMainCallback2(CB2_GameplayCannotBeContinued);
+ return;
+ }
+
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+ MenuPrint(gSystemText_CheckCompleteSaveAttempt, 2, MSG_WIN_TOP + 1);
+ sub_8125C3C(gUnknown_0203933C);
+
+ if (gUnknown_03005EA8)
+ {
+#ifdef BUGFIX_SAVEFAILEDSCREEN2
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+#endif
+ MenuPrint(gSystemText_SaveFailedBackupCheck, 2, MSG_WIN_TOP + 1);
+ }
+
+ wipeTries++;
+ }
+
+ if (wipeTries == 3)
+ {
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+ MenuPrint(gSystemText_BackupDamagedGameContinue, 2, MSG_WIN_TOP + 1);
+ SetMainCallback2(CB2_FadeAndReturnToTitleScreen); // called again below
+ }
+ else
+ {
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+
+ if (!gUnknown_03005EBC) // cant continue game.
+ MenuPrint(gSystemText_SaveCompletedGameEnd, 2, MSG_WIN_TOP + 1);
+ else // can continue game.
+ MenuPrint(gSystemText_SaveCompletedPressA, 2, MSG_WIN_TOP + 1);
+ }
+
+ SetMainCallback2(CB2_FadeAndReturnToTitleScreen);
+}
+
+static void CB2_GameplayCannotBeContinued(void)
+{
+ gUnknown_0203933E.unk0 = 0;
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ MenuDrawTextWindow(1, MSG_WIN_TOP, 28, 19);
+ MenuPrint(gSystemText_GameplayEnded, 2, MSG_WIN_TOP + 1);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_FadeAndReturnToTitleScreen);
+ }
+}
+
+static void CB2_FadeAndReturnToTitleScreen(void)
+{
+ u8 zero;
+
+ gUnknown_0203933E.unk0 = zero = 0;
+
+ if (gMain.newKeys & A_BUTTON)
+ {
+ BeginNormalPaletteFade(0xFFFFFFFF, 0, zero, 16, 0);
+ SetVBlankCallback(VBlankCB);
+ SetMainCallback2(CB2_ReturnToTitleScreen);
+ }
+}
+
+static void CB2_ReturnToTitleScreen(void)
+{
+ if (!UpdatePaletteFade())
+ {
+ if (!gUnknown_03005EBC)
+ {
+ DoSoftReset();
+ }
+ else
+ {
+ SetMainCallback2((MainCallback)gUnknown_03005EBC);
+ gUnknown_03005EBC = 0;
+ }
+ }
+}
+
+static void VBlankCB_UpdateClockGraphics(void)
+{
+ unsigned int n = (gMain.vblankCounter2 >> 3) & 7;
+
+ gMain.oamBuffer[0] = gUnknown_08411940;
+ gMain.oamBuffer[0].x = 112;
+ gMain.oamBuffer[0].y = (CLOCK_WIN_TOP + 1) * 8;
+
+ if (gUnknown_0203933E.unk0)
+ {
+ gMain.oamBuffer[0].tileNum = gUnknown_08411948[n][0];
+ gMain.oamBuffer[0].matrixNum = (gUnknown_08411948[n][2] << 4) | (gUnknown_08411948[n][1] << 3);
+ }
+ else
+ {
+ gMain.oamBuffer[0].tileNum = 1;
+ }
+
+ CpuFastCopy(gMain.oamBuffer, (void *)OAM, 4);
+
+ if (gUnknown_0203933E.unk2)
+ gUnknown_0203933E.unk2--;
+}
+
+static bool8 VerifySectorWipe(u16 sector)
+{
+ u32 *ptr = (u32 *)unk_2000000;
+ u16 i;
+
+ ReadFlash(sector, 0, (u8 *)ptr, 4096);
+
+ for (i = 0; i < 0x400; i++, ptr++)
+ if (*ptr)
+ return TRUE;
+
+ return FALSE;
+}
+
+static bool8 WipeSector(u16 sector)
+{
+ u16 i, j;
+ bool8 failed = TRUE;
+
+ for (i = 0; failed && i < 130; i++)
+ {
+ for (j = 0; j < 0x1000; j++)
+ ProgramFlashByte(sector, j, 0);
+
+ failed = VerifySectorWipe(sector);
+ }
+
+ return failed;
+}
+
+static bool8 WipeSectors(u32 sectorBits)
+{
+ u16 i;
+
+ for (i = 0; i < 0x20; i++)
+ if ((sectorBits & (1 << i)) && !WipeSector(i))
+ sectorBits &= ~(1 << i);
+
+ if (sectorBits == 0)
+ return FALSE;
+ else
+ return TRUE;
+}