pokeruby/src/reset_rtc_screen.c
Eduardo Quezada afcbea1f17
Some checks are pending
CI / build (push) Waiting to run
Use JOY_NEW, JOY_HELD and JOY_REPT across the repo (#885)
2026-02-14 02:33:00 -05:00

693 lines
17 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "global.h"
#include "event_data.h"
#include "main.h"
#include "menu.h"
#include "palette.h"
#include "rtc.h"
#include "save.h"
#include "script.h"
#include "sprite.h"
#include "constants/songs.h"
#include "sound.h"
#include "string_util.h"
#include "strings.h"
#include "strings2.h"
#include "task.h"
#include "text.h"
#include "scanline_effect.h"
struct ResetRtcStruct
{
/*0x0*/ u8 dataIndex;
/*0x2*/ u16 minVal;
/*0x4*/ u16 maxVal;
/*0x6*/ u8 left;
/*0x7*/ u8 right;
/*0x8*/ u8 unk8;
};
extern u16 gSaveFileStatus;
void CB2_ResetRtcScreen(void);
void VBlankCB_ResetRtcScreen(void);
void Task_ResetRtcScreen(u8);
static const struct ResetRtcStruct gUnknown_08376420[5] =
{
{
.dataIndex = 3,
.minVal = 1,
.maxVal = 9999,
.left = 0,
.right = 2,
.unk8 = 0,
},
{
.dataIndex = 4,
.minVal = 0,
.maxVal = 23,
.left = 1,
.right = 3,
.unk8 = 0,
},
{
.dataIndex = 5,
.minVal = 0,
.maxVal = 59,
.left = 2,
.right = 4,
.unk8 = 0,
},
{
.dataIndex = 6,
.minVal = 0,
.maxVal = 59,
.left = 3,
.right = 5,
.unk8 = 0,
},
{
.dataIndex = 7,
.minVal = 0,
.maxVal = 0,
.left = 4,
.right = 0,
.unk8 = 6,
},
};
const struct OamData gOamData_837645C =
{
.y = 0,
.affineMode = 0,
.objMode = 0,
.mosaic = 0,
.bpp = 0,
.shape = 0,
.x = 0,
.matrixNum = 0,
.size = 0,
.tileNum = 0,
.priority = 0,
.paletteNum = 0,
.affineParam = 0,
};
const u8 gSpriteImage_8376464[] = INCBIN_U8("graphics/unknown_sprites/83764AC/0.4bpp");
const u8 gSpriteImage_8376484[] = INCBIN_U8("graphics/unknown_sprites/83764AC/1.4bpp");
const u16 Palette_3764A4[] = INCBIN_U16("graphics/unknown/83764A4.gbapal");
const struct SpriteFrameImage gSpriteImageTable_83764AC[] =
{
{ gSpriteImage_8376464, 0x20 },
{ gSpriteImage_8376484, 0x20 },
};
const struct SpritePalette gUnknown_083764BC =
{
.data = Palette_3764A4,
.tag = 0x1000,
};
const union AnimCmd gSpriteAnim_83764C4[] =
{
ANIMCMD_FRAME(0, 30),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSpriteAnim_83764CC[] =
{
ANIMCMD_FRAME(0, 30, .vFlip = TRUE),
ANIMCMD_JUMP(0),
};
const union AnimCmd gSpriteAnim_83764D4[] =
{
ANIMCMD_FRAME(1, 30),
ANIMCMD_JUMP(0),
};
const union AnimCmd *const gSpriteAnimTable_83764DC[] =
{
gSpriteAnim_83764C4,
gSpriteAnim_83764CC,
gSpriteAnim_83764D4,
};
const struct SpriteTemplate gSpriteTemplate_83764E8 =
{
.tileTag = 0xFFFF,
.paletteTag = 0x1000,
.oam = &gOamData_837645C,
.anims = gSpriteAnimTable_83764DC,
.images = gSpriteImageTable_83764AC,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SpriteCallbackDummy,
};
const u8 gUnknown_08376500[] = _(" : ");
void SpriteCB_ResetRtcCusor0(struct Sprite *sprite)
{
int state = gTasks[sprite->data[0]].data[2];
if (state != sprite->data[1])
{
sprite->data[1] = state;
switch (state)
{
case 1:
sprite->invisible = FALSE;
sprite->animNum = 1;
sprite->animDelayCounter = 0;
sprite->x = 53;
sprite->y = 68;
break;
case 2:
sprite->invisible = FALSE;
sprite->animNum = 1;
sprite->animDelayCounter = 0;
sprite->x = 86;
sprite->y = 68;
break;
case 3:
sprite->invisible = FALSE;
sprite->animNum = 1;
sprite->animDelayCounter = 0;
sprite->x = 107;
sprite->y = 68;
break;
case 4:
sprite->invisible = FALSE;
sprite->animNum = 1;
sprite->animDelayCounter = 0;
sprite->x = 128;
sprite->y = 68;
break;
case 5:
sprite->invisible = FALSE;
sprite->animNum = 2;
sprite->animDelayCounter = 0;
sprite->x = 155;
sprite->y = 80;
break;
case 6:
DestroySprite(sprite);
break;
}
}
}
void SpriteCB_ResetRtcCusor1(struct Sprite *sprite)
{
int state = gTasks[sprite->data[0]].data[2];
if (state != sprite->data[1])
{
sprite->data[1] = state;
switch (state)
{
case 1:
sprite->invisible = FALSE;
sprite->animNum = 0;
sprite->animDelayCounter = 0;
sprite->x = 53;
sprite->y = 92;
break;
case 2:
sprite->invisible = FALSE;
sprite->animNum = 0;
sprite->animDelayCounter = 0;
sprite->x = 86;
sprite->y = 92;
break;
case 3:
sprite->invisible = FALSE;
sprite->animNum = 0;
sprite->animDelayCounter = 0;
sprite->x = 107;
sprite->y = 92;
break;
case 4:
sprite->invisible = FALSE;
sprite->animNum = 0;
sprite->animDelayCounter = 0;
sprite->x = 128;
sprite->y = 92;
break;
case 5:
sprite->invisible = TRUE;
break;
case 6:
DestroySprite(sprite);
break;
}
}
}
void ResetRtcScreen_CreateCursor(u8 taskId)
{
int spriteId;
LoadSpritePalette(&gUnknown_083764BC);
spriteId = CreateSpriteAtEnd(&gSpriteTemplate_83764E8, 53, 68, 0);
gSprites[spriteId].callback = SpriteCB_ResetRtcCusor0;
gSprites[spriteId].data[0] = taskId;
gSprites[spriteId].data[1] = -1;
spriteId = CreateSpriteAtEnd(&gSpriteTemplate_83764E8, 53, 68, 0);
gSprites[spriteId].callback = SpriteCB_ResetRtcCusor1;
gSprites[spriteId].data[0] = taskId;
gSprites[spriteId].data[1] = -1;
}
void ResetRtcScreen_FreeCursorPalette(void)
{
FreeSpritePaletteByTag(gUnknown_083764BC.tag);
}
void ResetRtcScreen_HideChooseTimeWindow(void)
{
Menu_EraseWindowRect(3, 8, 25, 11);
}
void ResetRtcScreen_PrintTime(u8 x, u8 y, u16 days, u8 hours, u8 minutes, u8 seconds)
{
u8 *dest = gStringVar4;
days %= 10000;
hours %= 24;
minutes %= 60;
seconds %= 60;
AlignInt2InMenuWindow(gStringVar1, days, 24, 1);
dest = StringCopy(dest, gStringVar1);
dest = StringCopy(dest, gOtherText_Day);
AlignInt2InMenuWindow(gStringVar1, hours, 18, 1);
dest = StringCopy(dest, gStringVar1);
dest = StringCopy(dest, gUnknown_08376500);
dest = ConvertIntToDecimalStringN(dest, minutes, STR_CONV_MODE_LEADING_ZEROS, 2);
dest = StringCopy(dest, gUnknown_08376500);
ConvertIntToDecimalStringN(dest, seconds, STR_CONV_MODE_LEADING_ZEROS, 2);
Menu_PrintText(gStringVar4, x, y);
}
void ResetRtcScreen_ShowChooseTimeWindow(u16 days, u8 hours, u8 minutes, u8 seconds)
{
Menu_DrawStdWindowFrame(3, 8, 25, 11);
Menu_PrintText(gOtherText_OK, 20, 9);
ResetRtcScreen_PrintTime(4, 9, days, hours, minutes, seconds);
}
bool32 ResetRtcScreen_MoveTimeUpDown(s16 *val, int minVal, int maxVal, u16 keys)
{
if (keys & DPAD_DOWN)
{
(*val)--;
if (*val < minVal)
*val = maxVal;
}
else if (keys & DPAD_UP)
{
(*val)++;
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;
}
void Task_ResetRtc_3(u8 taskId)
{
gTasks[taskId].data[0] = 1;
}
void Task_ResetRtc_2(u8 taskId)
{
ResetRtcScreen_HideChooseTimeWindow();
ResetRtcScreen_FreeCursorPalette();
gTasks[taskId].func = Task_ResetRtc_3;
}
void Task_ResetRtc_1(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u8 selection = data[2];
const struct ResetRtcStruct *selectionInfo = &gUnknown_08376420[selection - 1];
if (JOY_NEW(B_BUTTON))
{
gTasks[taskId].func = Task_ResetRtc_2;
data[1] = 0;
data[2] = 6;
PlaySE(SE_SELECT);
return;
}
if (JOY_NEW(DPAD_RIGHT))
{
if (selectionInfo->right)
{
data[2] = selectionInfo->right;
PlaySE(SE_SELECT);
return;
}
}
if (JOY_NEW(DPAD_LEFT))
{
if (selectionInfo->left)
{
data[2] = selectionInfo->left;
PlaySE(SE_SELECT);
return;
}
}
if (selection == 5)
{
if (JOY_NEW(A_BUTTON))
{
gLocalTime.days = data[3];
gLocalTime.hours = data[4];
gLocalTime.minutes = data[5];
gLocalTime.seconds = data[6];
PlaySE(SE_SELECT);
gTasks[taskId].func = Task_ResetRtc_2;
data[1] = 1;
data[2] = 6;
}
}
else if (ResetRtcScreen_MoveTimeUpDown(&data[selectionInfo->dataIndex], selectionInfo->minVal, selectionInfo->maxVal, JOY_REPT(DPAD_UP | DPAD_DOWN)))
{
PlaySE(SE_SELECT);
ResetRtcScreen_PrintTime(4, 9, data[3], data[4], data[5], data[6]);
}
}
void Task_ResetRtc_0(u8 taskId)
{
s16 *data = gTasks[taskId].data;
data[0] = 0;
data[3] = gLocalTime.days;
data[4] = gLocalTime.hours;
data[5] = gLocalTime.minutes;
data[6] = gLocalTime.seconds;
ResetRtcScreen_ShowChooseTimeWindow(data[3], data[4], data[5], data[6]);
ResetRtcScreen_CreateCursor(taskId);
data[2] = 2;
gTasks[taskId].func = Task_ResetRtc_1;
}
void CB2_InitResetRtcScreen(void)
{
REG_DISPCNT = 0;
SetVBlankCallback(NULL);
DmaClear16(3, PLTT, PLTT_SIZE);
DmaFill16Large(3, 0, (u8 *)VRAM, 0x18000, 0x1000);
ResetOamRange(0, 128);
LoadOam();
ScanlineEffect_Stop();
ScanlineEffect_Clear();
ResetSpriteData();
ResetTasks();
ResetPaletteFade();
Text_LoadWindowTemplate(&gMenuTextWindowTemplate);
InitMenuWindow(&gMenuTextWindowTemplate);
REG_DISPCNT = 4352;
SetVBlankCallback(VBlankCB_ResetRtcScreen);
SetMainCallback2(CB2_ResetRtcScreen);
CreateTask(Task_ResetRtcScreen, 80);
}
void CB2_ResetRtcScreen(void)
{
RunTasks();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
void VBlankCB_ResetRtcScreen(void)
{
ProcessSpriteCopyRequests();
LoadOam();
TransferPlttBuffer();
}
void ResetRtcScreen_ShowMessage(const u8 *str)
{
Menu_DisplayDialogueFrame();
Menu_PrintText(str, 2, 15);
}
void Task_ShowResetRtcPrompt(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (data[0])
{
case 0:
Menu_EraseScreen();
Menu_DrawStdWindowFrame(0, 0, 20, 10);
Menu_PrintText(gSystemText_PresentTime, 1, 1);
ResetRtcScreen_PrintTime(
1,
3,
gLocalTime.days,
gLocalTime.hours,
gLocalTime.minutes,
gLocalTime.seconds);
Menu_PrintText(gSystemText_PreviousTime, 1, 5);
ResetRtcScreen_PrintTime(
1,
7,
gSaveBlock2.lastBerryTreeUpdate.days,
gSaveBlock2.lastBerryTreeUpdate.hours,
gSaveBlock2.lastBerryTreeUpdate.minutes,
gSaveBlock2.lastBerryTreeUpdate.seconds);
ResetRtcScreen_ShowMessage(gSystemText_ResetRTCPrompt);
data[0]++;
case 1:
if (JOY_NEW(B_BUTTON))
{
DestroyTask(taskId);
DoSoftReset();
}
else if (JOY_NEW(A_BUTTON))
{
PlaySE(SE_SELECT);
DestroyTask(taskId);
}
break;
}
}
void Task_ResetRtcScreen(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (data[0])
{
case 0:
BeginNormalPaletteFade(0xFFFFFFFF, 1, 16, 0, FADE_COLOR_WHITE);
data[0] = 1;
break;
case 1:
if (!gPaletteFade.active)
{
if (gSaveFileStatus == 0 || gSaveFileStatus == 2)
{
ResetRtcScreen_ShowMessage(gSystemText_NoSaveFileNoTime);
data[0] = 5;
}
else
{
RtcCalcLocalTime();
data[1] = CreateTask(Task_ShowResetRtcPrompt, 80);
data[0] = 2;
}
}
break;
case 2:
if (gTasks[data[1]].isActive != TRUE)
{
Menu_EraseScreen();
ResetRtcScreen_ShowMessage(gSystemText_PleaseResetTime);
gLocalTime = gSaveBlock2.lastBerryTreeUpdate;
data[1] = CreateTask(Task_ResetRtc_0, 80);
data[0] = 3;
}
break;
case 3:
if (gTasks[data[1]].data[0])
{
if (!gTasks[data[1]].data[1])
{
DestroyTask(data[1]);
data[0] = 2;
}
else
{
DestroyTask(data[1]);
RtcReset();
RtcCalcLocalTimeOffset(
gLocalTime.days,
gLocalTime.hours,
gLocalTime.minutes,
gLocalTime.seconds);
gSaveBlock2.lastBerryTreeUpdate = gLocalTime;
VarSet(VAR_DAYS, gLocalTime.days);
DisableResetRTC();
ResetRtcScreen_ShowMessage(gSystemText_ClockResetDataSave);
data[0] = 4;
}
}
break;
case 4:
if (Save_WriteData(0) == SAVE_STATUS_OK)
{
ResetRtcScreen_ShowMessage(gSystemText_SaveCompleted);
PlaySE(SE_DING_DONG);
}
else
{
ResetRtcScreen_ShowMessage(gSystemText_SaveFailed);
PlaySE(SE_BOO);
}
data[0] = 5;
// fall through
case 5:
if (JOY_NEW(A_BUTTON))
{
BeginNormalPaletteFade(0xFFFFFFFF, 1, 0, 16, FADE_COLOR_WHITE);
data[0] = 6;
}
else
{
break;
}
// fall through
case 6:
if (!gPaletteFade.active)
{
DestroyTask(taskId);
DoSoftReset();
}
}
}
#if DEBUG
void debug_sub_806F8F8(void)
{
SetMainCallback2(CB2_InitResetRtcScreen);
}
void debug_sub_806F908(u8 taskId)
{
s16 *data = gTasks[taskId].data;
switch (data[0])
{
case 0:
data[1] = CreateTask(Task_ResetRtc_0, 80);
data[0]++;
break;
case 1:
if (gTasks[data[1]].data[0] != 0)
{
if (gTasks[data[1]].data[1] == 1)
RtcCalcLocalTimeOffset(gLocalTime.days, gLocalTime.hours, gLocalTime.minutes, gLocalTime.seconds);
DestroyTask(data[1]);
Menu_EraseScreen();
ScriptContext2_Disable();
DestroyTask(taskId);
}
break;
}
}
void debug_sub_806F99C(void)
{
RtcCalcLocalTime();
CreateTask(debug_sub_806F908, 80);
ScriptContext2_Enable();
}
void debug_sub_806F9B8(void)
{
gLocalTime = gSaveBlock2.lastBerryTreeUpdate;
CreateTask(debug_sub_806F908, 80);
ScriptContext2_Enable();
}
static const u8 sDebugText_Days[] = DTR("にっすう", "days");
static const u8 sDebugText_Time[] = DTR("じかん", "time");
static const u8 sDebugText_GameTime[] = DTR("ゲームない じかん", "game time");
static const u8 sDebugText_RTCTime[] = DTR("RTC じかん", "RTC time");
void debug_sub_806F9E4(u8 taskId)
{
s16 *data = gTasks[taskId].data;
u8 *str = gStringVar4;
switch (data[0])
{
case 0:
data[0]++;
break;
case 1:
Menu_DrawStdWindowFrame(0, 9, 29, 19);
ConvertIntToHexStringN(str + 80, RtcGetErrorStatus(), 2, 4);
Menu_PrintText(str + 80, 2, 10);
Menu_PrintText(sDebugText_Days, 12, 12);
Menu_PrintText(sDebugText_Time, 20, 12);
Menu_PrintText(sDebugText_RTCTime, 1, 14);
Menu_PrintText(sDebugText_GameTime, 1, 16);
data[0]++;
break;
case 2:
RtcCalcLocalTime();
FormatHexRtcTime(str);
debug_sub_8009894(str + 20);
FormatDecimalTime(str + 40, gLocalTime.hours, gLocalTime.minutes, gLocalTime.seconds);
ConvertIntToDecimalStringN(str + 60, gLocalTime.days, 1, 4);
if (gSaveBlock2.playTimeVBlanks == 0)
{
Menu_PrintText(str, 20, 14);
Menu_PrintText(str + 20, 12, 14);
Menu_PrintText(str + 40, 20, 16);
Menu_PrintText(str + 60, 12, 16);
}
if (data[1] > 19) // Did you mean < 19?
{
data[1]++;
}
else
{
if (JOY_NEW(A_BUTTON))
{
Menu_EraseScreen();
DestroyTask(taskId);
ScriptContext2_Disable();
}
}
break;
}
}
#endif