pokeemerald/src/reset_rtc_screen.c

736 lines
19 KiB
C
Raw Normal View History

2018-02-02 19:00:01 +01:00
#include "global.h"
#include "reset_rtc_screen.h"
#include "event_data.h"
#include "main.h"
#include "menu.h"
#include "palette.h"
#include "rtc.h"
#include "save.h"
#include "sprite.h"
#include "constants/songs.h"
#include "sound.h"
#include "string_util.h"
#include "strings.h"
#include "task.h"
#include "text.h"
#include "scanline_effect.h"
#include "bg.h"
#include "window.h"
#include "gpu_regs.h"
2019-04-04 23:05:46 +02:00
#include "constants/rgb.h"
2018-02-02 19:00:01 +01:00
2021-02-24 20:29:33 +01:00
#define PALTAG_ARROW 0x1000
// Task data for the Task_ResetRtc_* series of tasks, when setting the time on the clock
// Data from these tasks is also used by the cursors and the main task (Task_ResetRtcScreen)
enum {
DATAIDX_DAYS = 3,
DATAIDX_HOURS,
DATAIDX_MINS,
DATAIDX_SECS,
DATAIDX_CONFIRM,
};
#define tFinished data[0]
#define tSetTime data[1]
#define tSelection data[2]
#define tDays data[DATAIDX_DAYS]
#define tHours data[DATAIDX_HOURS]
#define tMinutes data[DATAIDX_MINS]
#define tSeconds data[DATAIDX_SECS]
#define tConfirm data[DATAIDX_CONFIRM]
#define tWindowId data[8]
enum {
SELECTION_DAYS = 1,
SELECTION_HOURS,
SELECTION_MINS,
SELECTION_SECS,
SELECTION_CONFIRM,
SELECTION_NONE
};
struct ResetRtcInputMap
2018-02-02 19:00:01 +01:00
{
/*0x0*/ u8 dataIndex;
/*0x2*/ u16 minVal;
/*0x4*/ u16 maxVal;
/*0x6*/ u8 left;
/*0x7*/ u8 right;
2021-02-24 20:29:33 +01:00
/*0x8*/ u8 unk; // never read
2018-02-02 19:00:01 +01:00
};
static void CB2_ResetRtcScreen(void);
static void VBlankCB(void);
static void Task_ResetRtcScreen(u8 taskId);
2021-02-24 20:29:33 +01:00
static void InitResetRtcScreenBgAndWindows(void);
2018-02-02 19:00:01 +01:00
2021-02-24 20:29:33 +01:00
static const struct BgTemplate sBgTemplates[] =
2018-02-02 19:00:01 +01:00
{
{
.bg = 0,
.charBaseIndex = 0,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
}
};
2021-02-24 20:29:33 +01:00
static const struct WindowTemplate sWindowTemplates[] =
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
{
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 1,
.width = 19,
.height = 9,
.paletteNum = 15,
2021-02-24 20:29:33 +01:00
.baseBlock = 0x155
},
{
.bg = 0,
.tilemapLeft = 2,
.tilemapTop = 15,
.width = 27,
.height = 4,
.paletteNum = 15,
2021-02-24 20:29:33 +01:00
.baseBlock = 0xE9
},
2018-02-02 19:00:01 +01:00
DUMMY_WIN_TEMPLATE
};
2021-02-24 20:29:33 +01:00
static const struct WindowTemplate sInputTimeWindow = {
.bg = 0,
.tilemapLeft = 4,
.tilemapTop = 9,
.width = 21,
.height = 2,
.paletteNum = 15,
2021-02-24 20:29:33 +01:00
.baseBlock = 0xBF
};
2018-02-02 19:00:01 +01:00
2021-02-24 20:29:33 +01:00
static const struct ResetRtcInputMap sInputMap[] =
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
[SELECTION_DAYS - 1] = {
.dataIndex = DATAIDX_DAYS,
2018-02-02 19:00:01 +01:00
.minVal = 1,
.maxVal = 9999,
.left = 0,
.right = 2,
2021-02-24 20:29:33 +01:00
.unk = 0,
2018-02-02 19:00:01 +01:00
},
2021-02-24 20:29:33 +01:00
[SELECTION_HOURS - 1] = {
.dataIndex = DATAIDX_HOURS,
2018-02-02 19:00:01 +01:00
.minVal = 0,
.maxVal = 23,
.left = 1,
.right = 3,
2021-02-24 20:29:33 +01:00
.unk = 0,
2018-02-02 19:00:01 +01:00
},
2021-02-24 20:29:33 +01:00
[SELECTION_MINS - 1] = {
.dataIndex = DATAIDX_MINS,
2018-02-02 19:00:01 +01:00
.minVal = 0,
.maxVal = 59,
.left = 2,
.right = 4,
2021-02-24 20:29:33 +01:00
.unk = 0,
2018-02-02 19:00:01 +01:00
},
2021-02-24 20:29:33 +01:00
[SELECTION_SECS - 1] = {
.dataIndex = DATAIDX_SECS,
2018-02-02 19:00:01 +01:00
.minVal = 0,
.maxVal = 59,
.left = 3,
.right = 5,
2021-02-24 20:29:33 +01:00
.unk = 0,
2018-02-02 19:00:01 +01:00
},
2021-02-24 20:29:33 +01:00
[SELECTION_CONFIRM - 1] = {
.dataIndex = DATAIDX_CONFIRM,
2018-02-02 19:00:01 +01:00
.minVal = 0,
.maxVal = 0,
.left = 4,
.right = 0,
2021-02-24 20:29:33 +01:00
.unk = 6,
2018-02-02 19:00:01 +01:00
},
};
2021-02-24 20:29:33 +01:00
static const struct OamData sOamData_Arrow =
2018-02-02 19:00:01 +01:00
{
.y = 0,
.affineMode = ST_OAM_AFFINE_OFF,
.objMode = ST_OAM_OBJ_NORMAL,
2018-02-02 19:00:01 +01:00
.mosaic = 0,
.bpp = ST_OAM_4BPP,
.shape = SPRITE_SHAPE(8x8),
2018-02-02 19:00:01 +01:00
.x = 0,
.matrixNum = 0,
.size = SPRITE_SIZE(8x8),
2018-02-02 19:00:01 +01:00
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
2021-02-24 20:29:33 +01:00
static const u8 sArrowDown_Gfx[] = INCBIN_U8("graphics/reset_rtc_screen/arrow_down.4bpp");
static const u8 sArrowRight_Gfx[] = INCBIN_U8("graphics/reset_rtc_screen/arrow_right.4bpp");
static const u16 sArrow_Pal[] = INCBIN_U16("graphics/reset_rtc_screen/arrow.gbapal");
2018-02-02 19:00:01 +01:00
2021-02-24 20:29:33 +01:00
static const struct SpriteFrameImage sPicTable_Arrow[] =
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
obj_frame_tiles(sArrowDown_Gfx),
obj_frame_tiles(sArrowRight_Gfx)
2018-02-02 19:00:01 +01:00
};
static const struct SpritePalette sSpritePalette_Arrow =
{
2021-02-24 20:29:33 +01:00
sArrow_Pal, PALTAG_ARROW
2018-02-02 19:00:01 +01:00
};
2021-02-24 20:29:33 +01:00
static const union AnimCmd sAnim_Arrow_Down[] =
2018-02-02 19:00:01 +01:00
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_JUMP(0),
};
2021-02-24 20:29:33 +01:00
static const union AnimCmd sAnim_Arrow_Up[] =
2018-02-02 19:00:01 +01:00
{
ANIMCMD_FRAME(0, 30, .vFlip = TRUE),
2018-02-02 19:00:01 +01:00
ANIMCMD_JUMP(0),
};
2021-02-24 20:29:33 +01:00
static const union AnimCmd sAnim_Arrow_Right[] =
2018-02-02 19:00:01 +01:00
{
ANIMCMD_FRAME(1, 30),
ANIMCMD_JUMP(0),
};
2021-02-24 20:29:33 +01:00
enum {
ARROW_DOWN,
ARROW_UP,
ARROW_RIGHT,
};
static const union AnimCmd *const sAnims_Arrow[] =
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
[ARROW_DOWN] = sAnim_Arrow_Down,
[ARROW_UP] = sAnim_Arrow_Up,
[ARROW_RIGHT] = sAnim_Arrow_Right,
2018-02-02 19:00:01 +01:00
};
2021-02-24 20:29:33 +01:00
static const struct SpriteTemplate sSpriteTemplate_Arrow =
2018-02-02 19:00:01 +01:00
{
2021-09-14 19:14:14 +02:00
.tileTag = TAG_NONE,
2021-02-24 20:29:33 +01:00
.paletteTag = PALTAG_ARROW,
.oam = &sOamData_Arrow,
.anims = sAnims_Arrow,
.images = sPicTable_Arrow,
2018-02-02 19:00:01 +01:00
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
};
2021-02-24 20:29:33 +01:00
#define sTaskId data[0]
#define sState data[1]
static void SpriteCB_Cursor_UpOrRight(struct Sprite *sprite)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
int state = gTasks[sprite->sTaskId].tSelection;
if (state != sprite->sState)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
sprite->sState = state;
2018-02-02 19:00:01 +01:00
switch (state)
{
2021-02-24 20:29:33 +01:00
case SELECTION_DAYS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_UP;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 53;
sprite->y = 68;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_HOURS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_UP;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 86;
sprite->y = 68;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_MINS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_UP;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 101;
sprite->y = 68;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_SECS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_UP;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 116;
sprite->y = 68;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_CONFIRM:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_RIGHT;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 153;
sprite->y = 80;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_NONE:
2018-02-02 19:00:01 +01:00
DestroySprite(sprite);
break;
}
}
}
2021-02-24 20:29:33 +01:00
static void SpriteCB_Cursor_Down(struct Sprite *sprite)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
int state = gTasks[sprite->sTaskId].tSelection;
if (state != sprite->sState)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
sprite->sState = state;
2018-02-02 19:00:01 +01:00
switch (state)
{
2021-02-24 20:29:33 +01:00
case SELECTION_DAYS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_DOWN;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 53;
sprite->y = 92;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_HOURS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_DOWN;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 86;
sprite->y = 92;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_MINS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_DOWN;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 101;
sprite->y = 92;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_SECS:
2018-02-02 19:00:01 +01:00
sprite->invisible = FALSE;
2021-02-24 20:29:33 +01:00
sprite->animNum = ARROW_DOWN;
2018-02-02 19:00:01 +01:00
sprite->animDelayCounter = 0;
2021-07-07 15:11:52 +02:00
sprite->x = 116;
sprite->y = 92;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case SELECTION_CONFIRM:
// The up arrow is used as a right arrow when Confirm is selected
// Hide the down arrow
2018-02-02 19:00:01 +01:00
sprite->invisible = TRUE;
break;
2021-02-24 20:29:33 +01:00
case SELECTION_NONE:
2018-02-02 19:00:01 +01:00
DestroySprite(sprite);
break;
}
}
}
static void CreateCursor(u8 taskId)
{
u32 spriteId;
LoadSpritePalette(&sSpritePalette_Arrow);
2021-02-24 20:29:33 +01:00
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_Arrow, 53, 68, 0);
gSprites[spriteId].callback = SpriteCB_Cursor_UpOrRight;
gSprites[spriteId].sTaskId = taskId;
gSprites[spriteId].sState = -1;
2018-02-02 19:00:01 +01:00
2021-02-24 20:29:33 +01:00
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_Arrow, 53, 68, 0);
gSprites[spriteId].callback = SpriteCB_Cursor_Down;
gSprites[spriteId].sTaskId = taskId;
gSprites[spriteId].sState = -1;
2018-02-02 19:00:01 +01:00
}
static void FreeCursorPalette(void)
{
FreeSpritePaletteByTag(sSpritePalette_Arrow.tag);
}
static void HideChooseTimeWindow(u8 windowId)
{
ClearStdWindowAndFrameToTransparent(windowId, FALSE);
2018-02-02 19:00:01 +01:00
RemoveWindow(windowId);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-02-02 19:00:01 +01:00
}
static void PrintTime(u8 windowId, u8 x, u8 y, u16 days, u8 hours, u8 minutes, u8 seconds)
{
u8 *dest = gStringVar4;
// Print days
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, days, STR_CONV_MODE_RIGHT_ALIGN, 4);
2018-02-02 19:00:01 +01:00
dest = StringCopy(dest, gStringVar1);
dest = StringCopy(dest, gText_Day);
2021-02-24 20:29:33 +01:00
// Print hours
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, hours, STR_CONV_MODE_RIGHT_ALIGN, 3);
2018-02-02 19:00:01 +01:00
dest = StringCopy(dest, gStringVar1);
dest = StringCopy(dest, gText_Colon3);
2021-02-24 20:29:33 +01:00
// Print minutes
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, minutes, STR_CONV_MODE_LEADING_ZEROS, 2);
2018-02-02 19:00:01 +01:00
dest = StringCopy(dest, gStringVar1);
dest = StringCopy(dest, gText_Colon3);
2021-02-24 20:29:33 +01:00
// Print seconds
2019-09-30 21:43:44 +02:00
ConvertIntToDecimalStringN(gStringVar1, seconds, STR_CONV_MODE_LEADING_ZEROS, 2);
2018-02-02 19:00:01 +01:00
dest = StringCopy(dest, gStringVar1);
AddTextPrinterParameterized(windowId, FONT_NORMAL, gStringVar4, x, y, TEXT_SKIP_DRAW, NULL);
2018-02-02 19:00:01 +01:00
}
static void ShowChooseTimeWindow(u8 windowId, u16 days, u8 hours, u8 minutes, u8 seconds)
{
DrawStdFrameWithCustomTileAndPalette(windowId, FALSE, 0x214, 0xE);
2018-02-02 19:00:01 +01:00
PrintTime(windowId, 0, 1, days, hours, minutes, seconds);
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized(windowId, FONT_NORMAL, gText_Confirm2, 126, 1, 0, NULL);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-02-02 19:00:01 +01:00
}
static bool32 MoveTimeUpDown(s16 *val, int minVal, int maxVal, u16 keys)
{
if (keys & DPAD_DOWN)
{
2018-02-07 19:59:02 +01:00
*val -= 1;
2018-02-02 19:00:01 +01:00
if (*val < minVal)
*val = maxVal;
}
else if (keys & DPAD_UP)
{
2018-02-07 19:59:02 +01:00
*val += 1;
2018-02-02 19:00:01 +01:00
if (*val > maxVal)
*val = minVal;
}
else if (keys & DPAD_LEFT)
{
*val -= 10;
if (*val < minVal)
*val = maxVal;
}
else if (keys & DPAD_RIGHT)
{
*val += 10;
if (*val > maxVal)
*val = minVal;
}
else
{
return FALSE;
}
return TRUE;
}
2021-02-24 20:29:33 +01:00
static void Task_ResetRtc_SetFinished(u8 taskId)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
gTasks[taskId].tFinished = TRUE;
2018-02-02 19:00:01 +01:00
}
2021-02-24 20:29:33 +01:00
static void Task_ResetRtc_Exit(u8 taskId)
2018-02-02 19:00:01 +01:00
{
s16 *data = gTasks[taskId].data;
2021-02-24 20:29:33 +01:00
HideChooseTimeWindow(tWindowId);
2018-02-02 19:00:01 +01:00
FreeCursorPalette();
2021-02-24 20:29:33 +01:00
gTasks[taskId].func = Task_ResetRtc_SetFinished;
2018-02-02 19:00:01 +01:00
}
2021-02-24 20:29:33 +01:00
static void Task_ResetRtc_HandleInput(u8 taskId)
2018-02-02 19:00:01 +01:00
{
s16 *data = gTasks[taskId].data;
2021-02-24 20:29:33 +01:00
u8 selection = tSelection;
const struct ResetRtcInputMap *selectionInfo = &sInputMap[selection - 1];
2018-02-02 19:00:01 +01:00
2020-09-05 03:11:55 +02:00
if (JOY_NEW(B_BUTTON))
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
gTasks[taskId].func = Task_ResetRtc_Exit;
tSetTime = FALSE;
tSelection = SELECTION_NONE;
2018-02-02 19:00:01 +01:00
PlaySE(SE_SELECT);
return;
}
2020-09-05 03:11:55 +02:00
if (JOY_NEW(DPAD_RIGHT))
2018-02-02 19:00:01 +01:00
{
if (selectionInfo->right)
{
2021-02-24 20:29:33 +01:00
tSelection = selectionInfo->right;
2018-02-02 19:00:01 +01:00
PlaySE(SE_SELECT);
return;
}
}
2020-09-05 03:11:55 +02:00
if (JOY_NEW(DPAD_LEFT))
2018-02-02 19:00:01 +01:00
{
if (selectionInfo->left)
{
2021-02-24 20:29:33 +01:00
tSelection = selectionInfo->left;
2018-02-02 19:00:01 +01:00
PlaySE(SE_SELECT);
return;
}
}
2021-02-24 20:29:33 +01:00
if (selection == SELECTION_CONFIRM)
2018-02-02 19:00:01 +01:00
{
2020-09-05 03:11:55 +02:00
if (JOY_NEW(A_BUTTON))
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
gLocalTime.days = tDays;
gLocalTime.hours = tHours;
gLocalTime.minutes = tMinutes;
gLocalTime.seconds = tSeconds;
2018-02-02 19:00:01 +01:00
PlaySE(SE_SELECT);
2021-02-24 20:29:33 +01:00
gTasks[taskId].func = Task_ResetRtc_Exit;
tSetTime = TRUE;
tSelection = SELECTION_NONE;
2018-02-02 19:00:01 +01:00
}
}
2020-09-05 03:11:55 +02:00
else if (MoveTimeUpDown(&data[selectionInfo->dataIndex], selectionInfo->minVal, selectionInfo->maxVal, JOY_REPEAT(DPAD_UP | DPAD_DOWN)))
2018-02-02 19:00:01 +01:00
{
PlaySE(SE_SELECT);
2021-02-24 20:29:33 +01:00
PrintTime(tWindowId, 0, 1, tDays, tHours, tMinutes, tSeconds);
2021-11-03 20:29:18 +01:00
CopyWindowToVram(tWindowId, COPYWIN_GFX);
2018-02-02 19:00:01 +01:00
}
}
2021-02-24 20:29:33 +01:00
static void Task_ResetRtc_Init(u8 taskId)
2018-02-02 19:00:01 +01:00
{
s16 *data = gTasks[taskId].data;
2021-02-24 20:29:33 +01:00
tFinished = FALSE;
tDays = gLocalTime.days;
tHours = gLocalTime.hours;
tMinutes = gLocalTime.minutes;
tSeconds = gLocalTime.seconds;
tWindowId = AddWindow(&sInputTimeWindow);
ShowChooseTimeWindow(tWindowId, tDays, tHours, tMinutes, tSeconds);
2018-02-02 19:00:01 +01:00
CreateCursor(taskId);
2021-02-24 20:29:33 +01:00
tSelection = SELECTION_HOURS;
gTasks[taskId].func = Task_ResetRtc_HandleInput;
2018-02-02 19:00:01 +01:00
}
void CB2_InitResetRtcScreen(void)
{
SetGpuReg(REG_OFFSET_DISPCNT, 0);
SetVBlankCallback(NULL);
DmaClear16(3, PLTT, PLTT_SIZE);
2021-02-24 20:29:33 +01:00
DmaFillLarge16(3, 0, (u8 *)VRAM, VRAM_SIZE, 0x1000);
2018-02-02 19:00:01 +01:00
ResetOamRange(0, 128);
LoadOam();
ScanlineEffect_Stop();
ScanlineEffect_Clear();
ResetSpriteData();
ResetTasks();
ResetPaletteFade();
2021-02-24 20:29:33 +01:00
InitResetRtcScreenBgAndWindows();
2018-02-02 19:00:01 +01:00
SetVBlankCallback(VBlankCB);
SetMainCallback2(CB2_ResetRtcScreen);
CreateTask(Task_ResetRtcScreen, 80);
}
2021-02-24 20:29:33 +01:00
static void InitResetRtcScreenBgAndWindows(void)
2018-02-02 19:00:01 +01:00
{
ClearScheduledBgCopiesToVram();
2018-02-02 19:00:01 +01:00
ResetBgsAndClearDma3BusyFlags(0);
2021-02-24 20:29:33 +01:00
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-02-02 19:00:01 +01:00
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
ShowBg(0);
2021-02-24 20:29:33 +01:00
InitWindows(sWindowTemplates);
2018-02-02 19:00:01 +01:00
DeactivateAllTextPrinters();
2020-02-07 18:48:47 +01:00
LoadMessageBoxAndBorderGfx();
2018-02-02 19:00:01 +01:00
}
static void CB2_ResetRtcScreen(void)
{
RunTasks();
AnimateSprites();
BuildOamBuffer();
DoScheduledBgTilemapCopiesToVram();
2018-02-02 19:00:01 +01:00
UpdatePaletteFade();
}
static void VBlankCB(void)
{
ProcessSpriteCopyRequests();
LoadOam();
TransferPlttBuffer();
}
static void ShowMessage(const u8 *str)
{
DrawDialogFrameWithCustomTileAndPalette(1, FALSE, 0x200, 0xF);
2021-10-30 22:47:37 +02:00
AddTextPrinterParameterized(1, FONT_NORMAL, str, 0, 1, 0, NULL);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2018-02-02 19:00:01 +01:00
}
2021-02-24 20:29:33 +01:00
#define tState data[0]
2018-02-02 19:00:01 +01:00
static void Task_ShowResetRtcPrompt(u8 taskId)
{
s16 *data = gTasks[taskId].data;
2021-02-24 20:29:33 +01:00
switch (tState)
2018-02-02 19:00:01 +01:00
{
case 0:
DrawStdFrameWithCustomTileAndPalette(0, FALSE, 0x214, 0xE);
2021-02-24 20:29:33 +01:00
AddTextPrinterParameterized(0, FONT_NORMAL, gText_PresentTime, 0, 1, TEXT_SKIP_DRAW, 0);
2018-02-02 19:00:01 +01:00
PrintTime(
0,
0,
17,
gLocalTime.days,
gLocalTime.hours,
gLocalTime.minutes,
gLocalTime.seconds);
2021-02-24 20:29:33 +01:00
AddTextPrinterParameterized(0, FONT_NORMAL, gText_PreviousTime, 0, 33, TEXT_SKIP_DRAW, 0);
2018-02-02 19:00:01 +01:00
PrintTime(
0,
0,
49,
gSaveBlock2Ptr->lastBerryTreeUpdate.days,
gSaveBlock2Ptr->lastBerryTreeUpdate.hours,
gSaveBlock2Ptr->lastBerryTreeUpdate.minutes,
gSaveBlock2Ptr->lastBerryTreeUpdate.seconds);
2021-02-24 20:29:33 +01:00
2018-02-02 19:00:01 +01:00
ShowMessage(gText_ResetRTCConfirmCancel);
2021-11-03 20:29:18 +01:00
CopyWindowToVram(0, COPYWIN_GFX);
2020-05-14 10:37:09 +02:00
ScheduleBgCopyTilemapToVram(0);
2021-02-24 20:29:33 +01:00
tState++;
2018-02-02 19:00:01 +01:00
case 1:
2020-09-05 03:11:55 +02:00
if (JOY_NEW(B_BUTTON))
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
// Cancel, exit without resetting RTC
2018-02-02 19:00:01 +01:00
DestroyTask(taskId);
DoSoftReset();
}
2020-09-05 03:11:55 +02:00
else if (JOY_NEW(A_BUTTON))
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
// Confirm
2018-02-02 19:00:01 +01:00
PlaySE(SE_SELECT);
DestroyTask(taskId);
}
break;
}
}
2021-02-24 20:29:33 +01:00
#undef tState
// Task states for Task_ResetRtcScreen
enum {
MAINSTATE_FADE_IN,
MAINSTATE_CHECK_SAVE,
MAINSTATE_START_SET_TIME,
MAINSTATE_WAIT_SET_TIME,
MAINSTATE_SAVE,
MAINSTATE_WAIT_EXIT,
MAINSTATE_EXIT,
};
#define tState data[0]
#define tSubTaskId data[1]
2018-02-02 19:00:01 +01:00
static void Task_ResetRtcScreen(u8 taskId)
{
s16 *data = gTasks[taskId].data;
2021-02-24 20:29:33 +01:00
switch (tState)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
case MAINSTATE_FADE_IN:
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 1, 0x10, 0, RGB_WHITEALPHA);
2021-02-24 20:29:33 +01:00
tState = MAINSTATE_CHECK_SAVE;
2018-02-02 19:00:01 +01:00
break;
2021-02-24 20:29:33 +01:00
case MAINSTATE_CHECK_SAVE:
2018-02-02 19:00:01 +01:00
if (!gPaletteFade.active)
{
if (gSaveFileStatus == SAVE_STATUS_EMPTY
2021-02-24 20:29:33 +01:00
|| gSaveFileStatus == SAVE_STATUS_CORRUPT)
2018-02-02 19:00:01 +01:00
{
ShowMessage(gText_NoSaveFileCantSetTime);
2021-02-24 20:29:33 +01:00
tState = MAINSTATE_WAIT_EXIT;
2018-02-02 19:00:01 +01:00
}
else
{
RtcCalcLocalTime();
2021-02-24 20:29:33 +01:00
tSubTaskId = CreateTask(Task_ShowResetRtcPrompt, 80);
tState = MAINSTATE_START_SET_TIME;
2018-02-02 19:00:01 +01:00
}
}
break;
2021-02-24 20:29:33 +01:00
case MAINSTATE_START_SET_TIME:
// Wait for A or B press on prompt first
if (gTasks[tSubTaskId].isActive != TRUE)
2018-02-02 19:00:01 +01:00
{
ClearStdWindowAndFrameToTransparent(0, FALSE);
2018-02-02 19:00:01 +01:00
ShowMessage(gText_PleaseResetTime);
gLocalTime = gSaveBlock2Ptr->lastBerryTreeUpdate;
2021-02-24 20:29:33 +01:00
tSubTaskId = CreateTask(Task_ResetRtc_Init, 80);
tState = MAINSTATE_WAIT_SET_TIME;
2018-02-02 19:00:01 +01:00
}
break;
2021-02-24 20:29:33 +01:00
case MAINSTATE_WAIT_SET_TIME:
if (gTasks[tSubTaskId].tFinished)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
if (!gTasks[tSubTaskId].tSetTime)
2018-02-02 19:00:01 +01:00
{
2021-02-24 20:29:33 +01:00
// Exited without setting time, return to "Please reset time"
DestroyTask(tSubTaskId);
tState = MAINSTATE_START_SET_TIME;
2018-02-02 19:00:01 +01:00
}
else
{
2021-02-24 20:29:33 +01:00
// Time has been chosen, reset rtc and save
DestroyTask(tSubTaskId);
2018-02-02 19:00:01 +01:00
RtcReset();
RtcCalcLocalTimeOffset(
gLocalTime.days,
gLocalTime.hours,
gLocalTime.minutes,
gLocalTime.seconds);
gSaveBlock2Ptr->lastBerryTreeUpdate = gLocalTime;
VarSet(VAR_DAYS, gLocalTime.days);
DisableResetRTC();
ShowMessage(gText_ClockHasBeenReset);
2021-02-24 20:29:33 +01:00
tState = MAINSTATE_SAVE;
2018-02-02 19:00:01 +01:00
}
}
break;
2021-02-24 20:29:33 +01:00
case MAINSTATE_SAVE:
2020-01-12 21:27:37 +01:00
if (TrySavingData(SAVE_NORMAL) == SAVE_STATUS_OK)
2018-02-02 19:00:01 +01:00
{
ShowMessage(gText_SaveCompleted);
2020-08-21 00:02:00 +02:00
PlaySE(SE_DING_DONG);
2018-02-02 19:00:01 +01:00
}
else
{
ShowMessage(gText_SaveFailed);
PlaySE(SE_BOO);
}
2021-02-24 20:29:33 +01:00
tState = MAINSTATE_WAIT_EXIT;
// fallthrough
case MAINSTATE_WAIT_EXIT:
2020-09-05 03:11:55 +02:00
if (JOY_NEW(A_BUTTON))
2018-02-02 19:00:01 +01:00
{
2021-02-24 17:01:02 +01:00
BeginNormalPaletteFade(PALETTES_ALL, 1, 0, 0x10, RGB_WHITEALPHA);
2021-02-24 20:29:33 +01:00
tState = MAINSTATE_EXIT;
// fallthrough
2018-02-02 19:00:01 +01:00
}
else
{
break;
}
2021-02-24 20:29:33 +01:00
case MAINSTATE_EXIT:
2018-02-02 19:00:01 +01:00
if (!gPaletteFade.active)
{
DestroyTask(taskId);
FreeAllWindowBuffers();
DoSoftReset();
}
}
}