From e718f0c03ac2b2b3ff0cbf32938a8ffc37b60308 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:24:37 +0100 Subject: [PATCH 1/4] add datetime conversion for fakeRTC --- include/fake_rtc.h | 2 +- include/rtc.h | 1 + src/fake_rtc.c | 52 ++++++++++++++++++++++++++++++++++++------ src/reset_rtc_screen.c | 6 +++++ src/rtc.c | 5 +--- 5 files changed, 54 insertions(+), 12 deletions(-) diff --git a/include/fake_rtc.h b/include/fake_rtc.h index d74849614e9f..0b3df8b8dc10 100644 --- a/include/fake_rtc.h +++ b/include/fake_rtc.h @@ -5,7 +5,7 @@ struct Time* FakeRtc_GetCurrentTime(void); void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc); -void FakeRtc_AdvanceTimeBy(u32 hours, u32 minutes, u32 seconds); +void FakeRtc_AdvanceTimeBy(s16 days, u32 hours, u32 minutes, u32 seconds); void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second); void FakeRtc_TickTimeForward(void); u32 FakeRtc_GetSecondsRatio(void); diff --git a/include/rtc.h b/include/rtc.h index bf8ff9aa936d..b7d6f5f0cff9 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -89,6 +89,7 @@ #define TIME_NIGHT 3 extern struct Time gLocalTime; +extern const s32 sNumDaysInMonths[12]; void RtcDisableInterrupts(void); void RtcRestoreInterrupts(void); diff --git a/src/fake_rtc.c b/src/fake_rtc.c index f3f3b74c3960..771a98da4e0b 100644 --- a/src/fake_rtc.c +++ b/src/fake_rtc.c @@ -15,13 +15,47 @@ struct Time *FakeRtc_GetCurrentTime(void) #endif } -void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc) +static void FakeRtc_ConvertTimeToRtc(struct SiiRtcInfo* rtc, struct Time *time) { - struct Time* time = FakeRtc_GetCurrentTime(); + u8 day = 1; + u8 month = MONTH_JAN; + u16 year = 2000; + u16 days = time->days - 1; + rtc->second = time->seconds; rtc->minute = time->minutes; rtc->hour = time->hours; - rtc->day = time->days; + + while (days > (365 + ((month > MONTH_FEB && IsLeapYear(year + 1)) || (month <= MONTH_FEB && IsLeapYear(year))))) + { + days -= (365 + ((month > MONTH_FEB && IsLeapYear(year + 1)) || (month <= MONTH_FEB && IsLeapYear(year)))); + year++; + } + + while (days > ((sNumDaysInMonths[month - 1] + (month == MONTH_FEB && IsLeapYear(year))) - day)) + { + days -= (sNumDaysInMonths[month - 1] + (month == MONTH_FEB && IsLeapYear(year))); + day = 1; + month++; + } + + while (month > 12) + { + year++; + month -= 12; + } + + year -= 2000; + + rtc->day = day + days; + rtc->month = month; + rtc->year = year; +} + +void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc) +{ + struct Time* time = FakeRtc_GetCurrentTime(); + FakeRtc_ConvertTimeToRtc(rtc, time); } void FakeRtc_TickTimeForward(void) @@ -32,15 +66,18 @@ void FakeRtc_TickTimeForward(void) if (FlagGet(OW_FLAG_PAUSE_TIME)) return; - FakeRtc_AdvanceTimeBy(0, 0, FakeRtc_GetSecondsRatio()); + FakeRtc_AdvanceTimeBy(0, 0, 0, FakeRtc_GetSecondsRatio()); } -void FakeRtc_AdvanceTimeBy(u32 hours, u32 minutes, u32 seconds) +void FakeRtc_AdvanceTimeBy(s16 days, u32 hours, u32 minutes, u32 seconds) { struct Time* time = FakeRtc_GetCurrentTime(); + if (time == NULL) + return; seconds += time->seconds; minutes += time->minutes; hours += time->hours; + days += time->days; while(seconds >= SECONDS_PER_MINUTE) { @@ -56,13 +93,14 @@ void FakeRtc_AdvanceTimeBy(u32 hours, u32 minutes, u32 seconds) while(hours >= HOURS_PER_DAY) { - time->days++; + days++; hours -= HOURS_PER_DAY; } time->seconds = seconds; time->minutes = minutes; time->hours = hours; + time->days = days; } void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second) @@ -76,7 +114,7 @@ void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second) target.days = gLocalTime.days; CalcTimeDifference(&diff, &gLocalTime, &target); - FakeRtc_AdvanceTimeBy(diff.hours, diff.minutes, diff.seconds); + FakeRtc_AdvanceTimeBy(diff.days, diff.hours, diff.minutes, diff.seconds); } u32 FakeRtc_GetSecondsRatio(void) diff --git a/src/reset_rtc_screen.c b/src/reset_rtc_screen.c index 98ccb71b640d..dc3b7ab57ebd 100644 --- a/src/reset_rtc_screen.c +++ b/src/reset_rtc_screen.c @@ -1,6 +1,7 @@ #include "global.h" #include "reset_rtc_screen.h" #include "event_data.h" +#include "fake_rtc.h" #include "main.h" #include "menu.h" #include "palette.h" @@ -692,6 +693,11 @@ static void Task_ResetRtcScreen(u8 taskId) // Time has been chosen, reset rtc and save DestroyTask(tSubTaskId); RtcReset(); + FakeRtc_AdvanceTimeBy( + gLocalTime.days, + gLocalTime.hours, + gLocalTime.minutes, + gLocalTime.seconds); RtcCalcLocalTimeOffset( gLocalTime.days, gLocalTime.hours, diff --git a/src/rtc.c b/src/rtc.c index e5a8b2d1df38..009c6b765f32 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -18,7 +18,7 @@ COMMON_DATA struct Time gLocalTime = {0}; static const struct SiiRtcInfo sRtcDummy = {0, MONTH_JAN, 1}; // 2000 Jan 1 -static const s32 sNumDaysInMonths[MONTH_COUNT] = +const s32 sNumDaysInMonths[MONTH_COUNT] = { [MONTH_JAN - 1] = 31, [MONTH_FEB - 1] = 28, @@ -95,9 +95,6 @@ u16 RtcGetDayCount(struct SiiRtcInfo *rtc) { u8 year, month, day; - if (OW_USE_FAKE_RTC) - return rtc->day; - year = ConvertBcdToBinary(rtc->year); month = ConvertBcdToBinary(rtc->month); day = ConvertBcdToBinary(rtc->day); From 41e26ef1d73383ea6b9dac7092ce99df032ce764 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Wed, 20 Nov 2024 13:30:39 +0100 Subject: [PATCH 2/4] add different day increments to reset_rtc_screen --- src/reset_rtc_screen.c | 108 +++++++++++++++++++++++++++++++++++------ 1 file changed, 93 insertions(+), 15 deletions(-) diff --git a/src/reset_rtc_screen.c b/src/reset_rtc_screen.c index dc3b7ab57ebd..419ead4415bd 100644 --- a/src/reset_rtc_screen.c +++ b/src/reset_rtc_screen.c @@ -42,7 +42,10 @@ enum { #define tWindowId data[8] enum { - SELECTION_DAYS = 1, + SELECTION_DAYS_1000 = 1, + SELECTION_DAYS_100, + SELECTION_DAYS_10, + SELECTION_DAYS_1, SELECTION_HOURS, SELECTION_MINS, SELECTION_SECS, @@ -60,6 +63,7 @@ struct ResetRtcInputMap /*0x0*/ u8 dataIndex; /*0x2*/ u16 minVal; /*0x4*/ u16 maxVal; + u16 increment; /*0x6*/ u8 left; /*0x7*/ u8 right; /*0x8*/ u8 unk; // never read @@ -118,43 +122,75 @@ static const struct WindowTemplate sInputTimeWindow = { static const struct ResetRtcInputMap sInputMap[] = { - [SELECTION_DAYS - 1] = { + [SELECTION_DAYS_1000 - 1] = { .dataIndex = DATAIDX_DAYS, .minVal = 1, .maxVal = 9999, + .increment = 1000, .left = 0, .right = 2, .unk = 0, }, + [SELECTION_DAYS_100 - 1] = { + .dataIndex = DATAIDX_DAYS, + .minVal = 1, + .maxVal = 9999, + .increment = 100, + .left = 1, + .right = 3, + .unk = 0, + }, + [SELECTION_DAYS_10 - 1] = { + .dataIndex = DATAIDX_DAYS, + .minVal = 1, + .maxVal = 9999, + .increment = 10, + .left = 2, + .right = 4, + .unk = 0, + }, + [SELECTION_DAYS_1 - 1] = { + .dataIndex = DATAIDX_DAYS, + .minVal = 1, + .maxVal = 9999, + .increment = 1, + .left = 3, + .right = 5, + .unk = 0, + }, [SELECTION_HOURS - 1] = { .dataIndex = DATAIDX_HOURS, .minVal = 0, .maxVal = 23, - .left = 1, - .right = 3, + .increment = 1, + .left = 4, + .right = 6, .unk = 0, }, [SELECTION_MINS - 1] = { .dataIndex = DATAIDX_MINS, .minVal = 0, .maxVal = 59, - .left = 2, - .right = 4, + .increment = 1, + .left = 5, + .right = 7, .unk = 0, }, [SELECTION_SECS - 1] = { .dataIndex = DATAIDX_SECS, .minVal = 0, .maxVal = 59, - .left = 3, - .right = 5, + .increment = 1, + .left = 6, + .right = 8, .unk = 0, }, [SELECTION_CONFIRM - 1] = { .dataIndex = DATAIDX_CONFIRM, .minVal = 0, .maxVal = 0, - .left = 4, + .increment = 1, + .left = 7, .right = 0, .unk = 6, }, @@ -245,7 +281,28 @@ static void SpriteCB_Cursor_UpOrRight(struct Sprite *sprite) sprite->sState = state; switch (state) { - case SELECTION_DAYS: + case SELECTION_DAYS_1000: + sprite->invisible = FALSE; + sprite->animNum = ARROW_UP; + sprite->animDelayCounter = 0; + sprite->x = 35; + sprite->y = 68; + break; + case SELECTION_DAYS_100: + sprite->invisible = FALSE; + sprite->animNum = ARROW_UP; + sprite->animDelayCounter = 0; + sprite->x = 41; + sprite->y = 68; + break; + case SELECTION_DAYS_10: + sprite->invisible = FALSE; + sprite->animNum = ARROW_UP; + sprite->animDelayCounter = 0; + sprite->x = 47; + sprite->y = 68; + break; + case SELECTION_DAYS_1: sprite->invisible = FALSE; sprite->animNum = ARROW_UP; sprite->animDelayCounter = 0; @@ -295,7 +352,28 @@ static void SpriteCB_Cursor_Down(struct Sprite *sprite) sprite->sState = state; switch (state) { - case SELECTION_DAYS: + case SELECTION_DAYS_1000: + sprite->invisible = FALSE; + sprite->animNum = ARROW_DOWN; + sprite->animDelayCounter = 0; + sprite->x = 35; + sprite->y = 92; + break; + case SELECTION_DAYS_100: + sprite->invisible = FALSE; + sprite->animNum = ARROW_DOWN; + sprite->animDelayCounter = 0; + sprite->x = 41; + sprite->y = 92; + break; + case SELECTION_DAYS_10: + sprite->invisible = FALSE; + sprite->animNum = ARROW_DOWN; + sprite->animDelayCounter = 0; + sprite->x = 47; + sprite->y = 92; + break; + case SELECTION_DAYS_1: sprite->invisible = FALSE; sprite->animNum = ARROW_DOWN; sprite->animDelayCounter = 0; @@ -398,17 +476,17 @@ static void ShowChooseTimeWindow(u8 windowId, u16 days, u8 hours, u8 minutes, u8 ScheduleBgCopyTilemapToVram(0); } -static bool32 MoveTimeUpDown(s16 *val, int minVal, int maxVal, u16 keys) +static bool32 MoveTimeUpDown(s16 *val, int minVal, int maxVal, int increment, u16 keys) { if (keys & DPAD_DOWN) { - *val -= 1; + *val -= increment; if (*val < minVal) *val = maxVal; } else if (keys & DPAD_UP) { - *val += 1; + *val += increment; if (*val > maxVal) *val = minVal; } @@ -495,7 +573,7 @@ static void Task_ResetRtc_HandleInput(u8 taskId) tSelection = SELECTION_NONE; } } - else if (MoveTimeUpDown(&data[selectionInfo->dataIndex], selectionInfo->minVal, selectionInfo->maxVal, JOY_REPEAT(DPAD_UP | DPAD_DOWN))) + else if (MoveTimeUpDown(&data[selectionInfo->dataIndex], selectionInfo->minVal, selectionInfo->maxVal, selectionInfo->increment, JOY_REPEAT(DPAD_UP | DPAD_DOWN))) { PlaySE(SE_SELECT); PrintTime(tWindowId, 0, 1, tDays, tHours, tMinutes, tSeconds); From 65d2f8beb26e236da212c4c39e7f6a36f2d738a1 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Fri, 22 Nov 2024 00:44:27 +0100 Subject: [PATCH 3/4] rtc info in saveblock --- include/fake_rtc.h | 7 +-- include/global.h | 3 +- include/siirtc.h | 12 +++++ src/fake_rtc.c | 117 +++++++++++++++++++---------------------- src/load_save.c | 2 + src/reset_rtc_screen.c | 5 -- src/rtc.c | 2 +- 7 files changed, 76 insertions(+), 72 deletions(-) diff --git a/include/fake_rtc.h b/include/fake_rtc.h index 0b3df8b8dc10..92599b987add 100644 --- a/include/fake_rtc.h +++ b/include/fake_rtc.h @@ -3,10 +3,11 @@ #include "siirtc.h" -struct Time* FakeRtc_GetCurrentTime(void); +void FakeRtc_Reset(void); +struct SiiRtcInfo* FakeRtc_GetCurrentTime(void); void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc); -void FakeRtc_AdvanceTimeBy(s16 days, u32 hours, u32 minutes, u32 seconds); -void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second); +void FakeRtc_AdvanceTimeBy(u32 days, u32 hours, u32 minutes, u32 seconds); +void FakeRtc_ManuallySetTime(u32 day, u32 hour, u32 minute, u32 second); void FakeRtc_TickTimeForward(void); u32 FakeRtc_GetSecondsRatio(void); diff --git a/include/global.h b/include/global.h index 5846f09359d0..da0f7480b34a 100644 --- a/include/global.h +++ b/include/global.h @@ -5,6 +5,7 @@ #include #include "config/general.h" // we need to define config before gba headers as print stuff needs the functions nulled before defines. #include "gba/gba.h" +#include "siirtc.h" #include "fpmath.h" #include "metaprogram.h" #include "constants/global.h" @@ -206,7 +207,7 @@ struct Time struct SaveBlock3 { #if OW_USE_FAKE_RTC - struct Time fakeRTC; + struct SiiRtcInfo fakeRTC; #endif #if OW_SHOW_ITEM_DESCRIPTIONS == OW_ITEM_DESCRIPTIONS_FIRST_TIME u8 itemFlags[ITEM_FLAGS_COUNT]; diff --git a/include/siirtc.h b/include/siirtc.h index ad13fc62f37b..52a365cfcce6 100644 --- a/include/siirtc.h +++ b/include/siirtc.h @@ -13,6 +13,18 @@ #define MINUTES_PER_HOUR 60 #define SECONDS_PER_MINUTE 60 +enum +{ + WEEKDAY_SUN, + WEEKDAY_MON, + WEEKDAY_TUE, + WEEKDAY_WED, + WEEKDAY_THU, + WEEKDAY_FRI, + WEEKDAY_SAT, + WEEKDAY_COUNT, +}; + enum { MONTH_JAN = 1, diff --git a/src/fake_rtc.c b/src/fake_rtc.c index 771a98da4e0b..4647a1124038 100644 --- a/src/fake_rtc.c +++ b/src/fake_rtc.c @@ -6,56 +6,30 @@ #include "fake_rtc.h" #include "event_data.h" -struct Time *FakeRtc_GetCurrentTime(void) +void FakeRtc_Reset(void) { #if OW_USE_FAKE_RTC - return &gSaveBlock3Ptr->fakeRTC; -#else - return NULL; + memset(&gSaveBlock3Ptr->fakeRTC, 0, sizeof(gSaveBlock3Ptr->fakeRTC)); + gSaveBlock3Ptr->fakeRTC.month = MONTH_JAN; + gSaveBlock3Ptr->fakeRTC.day = 1; + gSaveBlock3Ptr->fakeRTC.dayOfWeek = WEEKDAY_SAT; #endif } -static void FakeRtc_ConvertTimeToRtc(struct SiiRtcInfo* rtc, struct Time *time) +struct SiiRtcInfo *FakeRtc_GetCurrentTime(void) { - u8 day = 1; - u8 month = MONTH_JAN; - u16 year = 2000; - u16 days = time->days - 1; - - rtc->second = time->seconds; - rtc->minute = time->minutes; - rtc->hour = time->hours; - - while (days > (365 + ((month > MONTH_FEB && IsLeapYear(year + 1)) || (month <= MONTH_FEB && IsLeapYear(year))))) - { - days -= (365 + ((month > MONTH_FEB && IsLeapYear(year + 1)) || (month <= MONTH_FEB && IsLeapYear(year)))); - year++; - } - - while (days > ((sNumDaysInMonths[month - 1] + (month == MONTH_FEB && IsLeapYear(year))) - day)) - { - days -= (sNumDaysInMonths[month - 1] + (month == MONTH_FEB && IsLeapYear(year))); - day = 1; - month++; - } - - while (month > 12) - { - year++; - month -= 12; - } - - year -= 2000; - - rtc->day = day + days; - rtc->month = month; - rtc->year = year; +#if OW_USE_FAKE_RTC + return &gSaveBlock3Ptr->fakeRTC; +#else + return NULL; +#endif } void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc) { - struct Time* time = FakeRtc_GetCurrentTime(); - FakeRtc_ConvertTimeToRtc(rtc, time); + struct SiiRtcInfo *fakeRtc = FakeRtc_GetCurrentTime(); + if (fakeRtc != NULL) + memcpy(rtc, fakeRtc, sizeof(struct SiiRtcInfo)); } void FakeRtc_TickTimeForward(void) @@ -69,15 +43,13 @@ void FakeRtc_TickTimeForward(void) FakeRtc_AdvanceTimeBy(0, 0, 0, FakeRtc_GetSecondsRatio()); } -void FakeRtc_AdvanceTimeBy(s16 days, u32 hours, u32 minutes, u32 seconds) +void FakeRtc_AdvanceTimeBy(u32 days, u32 hours, u32 minutes, u32 seconds) { - struct Time* time = FakeRtc_GetCurrentTime(); - if (time == NULL) - return; - seconds += time->seconds; - minutes += time->minutes; - hours += time->hours; - days += time->days; + struct SiiRtcInfo *rtc = FakeRtc_GetCurrentTime(); + + seconds += rtc->second; + minutes += rtc->minute; + hours += rtc->hour; while(seconds >= SECONDS_PER_MINUTE) { @@ -97,24 +69,45 @@ void FakeRtc_AdvanceTimeBy(s16 days, u32 hours, u32 minutes, u32 seconds) hours -= HOURS_PER_DAY; } - time->seconds = seconds; - time->minutes = minutes; - time->hours = hours; - time->days = days; + rtc->second = seconds; + rtc->minute = minutes; + rtc->hour = hours; + + while (days > 0) + { + u32 remainingDaysInMonth = (sNumDaysInMonths[rtc->month - 1] + (rtc->month == MONTH_FEB && IsLeapYear(rtc->year)) - rtc->day); + + if (days > remainingDaysInMonth) + { + rtc->day = 1; + rtc->month++; + if (rtc->month > MONTH_DEC) + { + rtc->month = MONTH_JAN; + rtc->year++; + } + days -= (remainingDaysInMonth + 1); + rtc->dayOfWeek = (rtc->dayOfWeek + remainingDaysInMonth + 1) % WEEKDAY_COUNT; + } + else + { + rtc->day += days; + rtc->dayOfWeek = (rtc->dayOfWeek + days) % WEEKDAY_COUNT; + days = 0; + } + } } -void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second) -{ - struct Time diff, target; - RtcCalcLocalTime(); - target.hours = hour; - target.minutes = minute; - target.seconds = second; - target.days = gLocalTime.days; +void FakeRtc_ManuallySetTime(u32 day, u32 hour, u32 minute, u32 second) +{ + FakeRtc_Reset(); + FakeRtc_AdvanceTimeBy(day, hour, minute, second); +} - CalcTimeDifference(&diff, &gLocalTime, &target); - FakeRtc_AdvanceTimeBy(diff.days, diff.hours, diff.minutes, diff.seconds); +void AdvanceScript(void) +{ + FakeRtc_AdvanceTimeBy(300, 0, 0, 0); } u32 FakeRtc_GetSecondsRatio(void) diff --git a/src/load_save.c b/src/load_save.c index 6fde540b8c4e..d4ea39f39de9 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -1,6 +1,7 @@ #include "global.h" #include "malloc.h" #include "berry_powder.h" +#include "fake_rtc.h" #include "item.h" #include "load_save.h" #include "main.h" @@ -63,6 +64,7 @@ void CheckForFlashMemory(void) void ClearSav3(void) { CpuFill16(0, &gSaveblock3, sizeof(struct SaveBlock3)); + FakeRtc_Reset(); } void ClearSav2(void) diff --git a/src/reset_rtc_screen.c b/src/reset_rtc_screen.c index 419ead4415bd..4d3015fa1958 100644 --- a/src/reset_rtc_screen.c +++ b/src/reset_rtc_screen.c @@ -771,11 +771,6 @@ static void Task_ResetRtcScreen(u8 taskId) // Time has been chosen, reset rtc and save DestroyTask(tSubTaskId); RtcReset(); - FakeRtc_AdvanceTimeBy( - gLocalTime.days, - gLocalTime.hours, - gLocalTime.minutes, - gLocalTime.seconds); RtcCalcLocalTimeOffset( gLocalTime.days, gLocalTime.hours, diff --git a/src/rtc.c b/src/rtc.c index 009c6b765f32..5f47e35c66fa 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -227,7 +227,7 @@ void RtcReset(void) { if (OW_USE_FAKE_RTC) { - memset(FakeRtc_GetCurrentTime(), 0, sizeof(struct Time)); + FakeRtc_Reset(); return; } From 7daeb738ace8f328196974e2c687139947a3d3d8 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Sun, 19 Jan 2025 13:11:25 +0100 Subject: [PATCH 4/4] added datetime and functionality to extract datetime from local time --- include/datetime.h | 28 +++++++++++ include/rtc.h | 4 ++ include/siirtc.h | 4 +- src/datetime.c | 115 +++++++++++++++++++++++++++++++++++++++++++++ src/fake_rtc.c | 67 +++++--------------------- src/rtc.c | 37 +++++++++++++++ 6 files changed, 199 insertions(+), 56 deletions(-) create mode 100644 include/datetime.h create mode 100644 src/datetime.c diff --git a/include/datetime.h b/include/datetime.h new file mode 100644 index 000000000000..979fc47f6fa5 --- /dev/null +++ b/include/datetime.h @@ -0,0 +1,28 @@ +#ifndef GUARD_DATETIME_H +#define GUARD_DATETIME_H + +#include "global.h" +#include "siirtc.h" + +struct DateTime +{ + u16 year; + enum Month month; + u8 day; + enum Weekday dayOfWeek; + u8 hour; + u8 minute; + u8 second; +}; + +extern const struct DateTime gGen3Epoch; + +void ConvertTimeToDateTime(struct DateTime *result, struct Time *timeSinceEpoch); +void DateTime_AddDays(struct DateTime *dateTime, u32 days); +void DateTime_AddHours(struct DateTime *dateTime, u32 hours); +void DateTime_AddMinutes(struct DateTime *dateTime, u32 minutes); +void DateTime_AddSeconds(struct DateTime *dateTime, u32 seconds); +void ConvertDateTimeToRtc(struct SiiRtcInfo *result, struct DateTime *dateTime); +void ConvertRtcToDateTime(struct DateTime *result, struct SiiRtcInfo *rtc); + +#endif // GUARD_DATETIME_H diff --git a/include/rtc.h b/include/rtc.h index b7d6f5f0cff9..9351222c4736 100644 --- a/include/rtc.h +++ b/include/rtc.h @@ -120,5 +120,9 @@ void CalcTimeDifference(struct Time *result, struct Time *t1, struct Time *t2); u32 RtcGetMinuteCount(void); u32 RtcGetLocalDayCount(void); void FormatDecimalTimeWithoutSeconds(u8 *dest, s8 hour, s8 minute, bool32 is24Hour); +u16 GetFullYear(void); +enum Month GetMonth(void); +u8 GetDay(void); +enum Weekday GetDayOfWeek(void); #endif // GUARD_RTC_UTIL_H diff --git a/include/siirtc.h b/include/siirtc.h index 52a365cfcce6..8e6958ca08fe 100644 --- a/include/siirtc.h +++ b/include/siirtc.h @@ -13,7 +13,7 @@ #define MINUTES_PER_HOUR 60 #define SECONDS_PER_MINUTE 60 -enum +enum Weekday { WEEKDAY_SUN, WEEKDAY_MON, @@ -25,7 +25,7 @@ enum WEEKDAY_COUNT, }; -enum +enum Month { MONTH_JAN = 1, MONTH_FEB, diff --git a/src/datetime.c b/src/datetime.c new file mode 100644 index 000000000000..1f02813b69b4 --- /dev/null +++ b/src/datetime.c @@ -0,0 +1,115 @@ +#include "global.h" +#include "datetime.h" +#include "rtc.h" + + +const struct DateTime gGen3Epoch = +{ + .year = 2000, + .month = MONTH_JAN, + .day = 1, + .dayOfWeek = WEEKDAY_SAT, + .hour = 0, + .minute = 0, + .second = 0, +}; + +void DateTime_AddDays(struct DateTime *dateTime, u32 days) +{ + while (days > 0) + { + u32 remainingDaysInMonth = (sNumDaysInMonths[dateTime->month - 1] + (dateTime->month == MONTH_FEB && IsLeapYear(dateTime->year)) - dateTime->day); + + if (days > remainingDaysInMonth) + { + dateTime->day = 1; + dateTime->month++; + if (dateTime->month > MONTH_DEC) + { + dateTime->month = MONTH_JAN; + dateTime->year++; + } + days -= (remainingDaysInMonth + 1); + dateTime->dayOfWeek = (dateTime->dayOfWeek + remainingDaysInMonth + 1) % WEEKDAY_COUNT; + } + else + { + dateTime->day += days; + dateTime->dayOfWeek = (dateTime->dayOfWeek + days) % WEEKDAY_COUNT; + days = 0; + } + } +} + +void DateTime_AddHours(struct DateTime *dateTime, u32 hours) +{ + u32 days = 0; + + dateTime->hour += hours; + while (dateTime->hour >= HOURS_PER_DAY) + { + days++; + dateTime->hour -= HOURS_PER_DAY; + } + + DateTime_AddDays(dateTime, days); +} + +void DateTime_AddMinutes(struct DateTime *dateTime, u32 minutes) +{ + u32 hours = 0; + + dateTime->minute += minutes; + while(dateTime->minute >= MINUTES_PER_HOUR) + { + hours++; + dateTime->minute -= MINUTES_PER_HOUR; + } + + DateTime_AddHours(dateTime, hours); +} + +void DateTime_AddSeconds(struct DateTime *dateTime, u32 seconds) +{ + u32 minutes = 0; + + dateTime->second += seconds; + while(dateTime->second >= SECONDS_PER_MINUTE) + { + minutes++; + dateTime->second -= SECONDS_PER_MINUTE; + } + + DateTime_AddMinutes(dateTime, minutes); +} + +void ConvertDateTimeToRtc(struct SiiRtcInfo *result, struct DateTime *dateTime) +{ + result->second = dateTime->second; + result->minute = dateTime->minute; + result->hour = dateTime->hour; + result->day = dateTime->day; + result->dayOfWeek = dateTime->dayOfWeek; + result->month = dateTime->month; + result->year = dateTime->year - gGen3Epoch.year; +} + +void ConvertRtcToDateTime(struct DateTime *result, struct SiiRtcInfo *rtc) +{ + result->second = rtc->second; + result->minute = rtc->minute; + result->hour = rtc->hour; + result->day = rtc->day; + result->dayOfWeek = rtc->dayOfWeek; + result->month = rtc->month; + result->year = gGen3Epoch.year + rtc->year; +} + +void ConvertTimeToDateTime(struct DateTime *result, struct Time *timeSinceEpoch) +{ + result = memcpy(result, &gGen3Epoch, sizeof(struct DateTime)); + DateTime_AddSeconds(result, timeSinceEpoch->seconds); + DateTime_AddMinutes(result, timeSinceEpoch->minutes); + DateTime_AddHours(result, timeSinceEpoch->hours); + DateTime_AddDays(result, timeSinceEpoch->days); +} diff --git a/src/fake_rtc.c b/src/fake_rtc.c index 389356fd2517..e5c745bf1d99 100644 --- a/src/fake_rtc.c +++ b/src/fake_rtc.c @@ -2,6 +2,7 @@ #include "string_util.h" #include "strings.h" #include "text.h" +#include "datetime.h" #include "rtc.h" #include "fake_rtc.h" #include "event_data.h" @@ -11,9 +12,10 @@ void FakeRtc_Reset(void) { #if OW_USE_FAKE_RTC memset(&gSaveBlock3Ptr->fakeRTC, 0, sizeof(gSaveBlock3Ptr->fakeRTC)); - gSaveBlock3Ptr->fakeRTC.month = MONTH_JAN; - gSaveBlock3Ptr->fakeRTC.day = 1; - gSaveBlock3Ptr->fakeRTC.dayOfWeek = WEEKDAY_SAT; + gSaveBlock3Ptr->fakeRTC.year = 0; // offset by gGen3Epoch.year + gSaveBlock3Ptr->fakeRTC.month = gGen3Epoch.month; + gSaveBlock3Ptr->fakeRTC.day = gGen3Epoch.day; + gSaveBlock3Ptr->fakeRTC.dayOfWeek = gGen3Epoch.dayOfWeek; #endif } @@ -46,59 +48,16 @@ void FakeRtc_TickTimeForward(void) void FakeRtc_AdvanceTimeBy(u32 days, u32 hours, u32 minutes, u32 seconds) { + struct DateTime dateTime; struct SiiRtcInfo *rtc = FakeRtc_GetCurrentTime(); - - seconds += rtc->second; - minutes += rtc->minute; - hours += rtc->hour; - - while(seconds >= SECONDS_PER_MINUTE) - { - minutes++; - seconds -= SECONDS_PER_MINUTE; - } - - while(minutes >= MINUTES_PER_HOUR) - { - hours++; - minutes -= MINUTES_PER_HOUR; - } - - while(hours >= HOURS_PER_DAY) - { - days++; - hours -= HOURS_PER_DAY; - } - - rtc->second = seconds; - rtc->minute = minutes; - rtc->hour = hours; - - while (days > 0) - { - u32 remainingDaysInMonth = (sNumDaysInMonths[rtc->month - 1] + (rtc->month == MONTH_FEB && IsLeapYear(rtc->year)) - rtc->day); - - if (days > remainingDaysInMonth) - { - rtc->day = 1; - rtc->month++; - if (rtc->month > MONTH_DEC) - { - rtc->month = MONTH_JAN; - rtc->year++; - } - days -= (remainingDaysInMonth + 1); - rtc->dayOfWeek = (rtc->dayOfWeek + remainingDaysInMonth + 1) % WEEKDAY_COUNT; - } - else - { - rtc->day += days; - rtc->dayOfWeek = (rtc->dayOfWeek + days) % WEEKDAY_COUNT; - days = 0; - } - } -} + ConvertRtcToDateTime(&dateTime, rtc); + DateTime_AddSeconds(&dateTime, seconds); + DateTime_AddMinutes(&dateTime, minutes); + DateTime_AddHours(&dateTime, hours); + DateTime_AddDays(&dateTime, days); + ConvertDateTimeToRtc(rtc, &dateTime); +} void FakeRtc_ManuallySetTime(u32 day, u32 hour, u32 minute, u32 second) { diff --git a/src/rtc.c b/src/rtc.c index 5f47e35c66fa..d60836630356 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -1,4 +1,5 @@ #include "global.h" +#include "datetime.h" #include "rtc.h" #include "string_util.h" #include "strings.h" @@ -415,3 +416,39 @@ void FormatDecimalTimeWithoutSeconds(u8 *txtPtr, s8 hour, s8 minute, bool32 is24 *txtPtr++ = EOS; *txtPtr = EOS; } + +u16 GetFullYear(void) +{ + struct DateTime dateTime; + RtcCalcLocalTime(); + ConvertTimeToDateTime(&dateTime, &gLocalTime); + + return dateTime.year; +} + +enum Month GetMonth(void) +{ + struct DateTime dateTime; + RtcCalcLocalTime(); + ConvertTimeToDateTime(&dateTime, &gLocalTime); + + return dateTime.month; +} + +u8 GetDay(void) +{ + struct DateTime dateTime; + RtcCalcLocalTime(); + ConvertTimeToDateTime(&dateTime, &gLocalTime); + + return dateTime.day; +} + +enum Weekday GetDayOfWeek(void) +{ + struct DateTime dateTime; + RtcCalcLocalTime(); + ConvertTimeToDateTime(&dateTime, &gLocalTime); + + return dateTime.dayOfWeek; +}