diff --git a/include/config/overworld.h b/include/config/overworld.h index 6f6aa5cc67d1..ad812710f887 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -6,7 +6,6 @@ // Other settings #define OW_POISON_DAMAGE GEN_LATEST // In Gen4, Pokémon no longer faint from Poison in the overworld. In Gen5+, they no longer take damage at all. -#define OW_TIMES_OF_DAY GEN_LATEST // Different generations have the times of day change at different times. #define OW_DOUBLE_APPROACH_WITH_ONE_MON FALSE // If enabled, you can be spotted by two trainers at the same time even if you only have one eligible Pokémon in your party. #define OW_HIDE_REPEAT_MAP_POPUP FALSE // If enabled, map popups will not appear if entering a map with the same Map Section Id as the last. @@ -86,6 +85,14 @@ #define OW_POPUP_BW_TIME_MODE OW_POPUP_BW_TIME_NONE // Determines what type of time is shown. #define OW_POPUP_BW_ALPHA_BLEND FALSE // Enables alpha blending/transparency for the pop-ups. Mainly intended to be used with the black color option. +// These generational defines only make a distinction for OW_ALTERED_TIME_RATIO +#define GEN_8_PLA GEN_LATEST + 2 + +//Time +#define OW_TIMES_OF_DAY GEN_LATEST // Different generations have the times of day change at different times. +#define OW_USE_FAKE_RTC FALSE // When TRUE, seconds on the in-clock will only advance once every 60 playTimeVBlanks (every 60 frames). +#define OW_ALTERED_TIME_RATIO GEN_LATEST // In GEN_8_PLA, the time in game moves forward 60 seconds for every second in the RTC. In GEN_9, it is 20 seconds. This has no effect if OW_USE_FAKE_RTC is FALSE. + // Pokémon Center #define OW_IGNORE_EGGS_ON_HEAL GEN_LATEST // In Gen 4+, the nurse in the Pokémon Center does not heal Eggs on healing machine. diff --git a/include/fake_rtc.h b/include/fake_rtc.h new file mode 100644 index 000000000000..d74849614e9f --- /dev/null +++ b/include/fake_rtc.h @@ -0,0 +1,13 @@ +#ifndef GUARD_FAKE_RTC_UTIL_H +#define GUARD_FAKE_RTC_UTIL_H + +#include "siirtc.h" + +struct Time* FakeRtc_GetCurrentTime(void); +void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc); +void FakeRtc_AdvanceTimeBy(u32 hours, u32 minutes, u32 seconds); +void FakeRtc_ManuallySetTime(u32 hour, u32 minute, u32 second); +void FakeRtc_TickTimeForward(void); +u32 FakeRtc_GetSecondsRatio(void); + +#endif // GUARD_FAKE_RTC_UTIL_H diff --git a/include/global.h b/include/global.h index a378f15a1d9a..f5ada78360d8 100644 --- a/include/global.h +++ b/include/global.h @@ -167,12 +167,6 @@ struct UCoords32 u32 y; }; -struct SaveBlock3 -{ -}; - -extern struct SaveBlock3 *gSaveBlock3Ptr; - struct Time { /*0x00*/ s16 days; @@ -181,6 +175,16 @@ struct Time /*0x04*/ s8 seconds; }; + +struct SaveBlock3 +{ +#if OW_USE_FAKE_RTC + struct Time fakeRTC; +#endif +}; + +extern struct SaveBlock3 *gSaveBlock3Ptr; + struct Pokedex { /*0x00*/ u8 order; diff --git a/src/fake_rtc.c b/src/fake_rtc.c new file mode 100644 index 000000000000..413a6a4e4ea8 --- /dev/null +++ b/src/fake_rtc.c @@ -0,0 +1,84 @@ +#include "global.h" +#include "string_util.h" +#include "strings.h" +#include "text.h" +#include "rtc.h" +#include "fake_rtc.h" + +struct Time *FakeRtc_GetCurrentTime(void) +{ +#if OW_USE_FAKE_RTC + return &gSaveBlock3Ptr->fakeRTC; +#else + return NULL; +#endif +} + +void FakeRtc_GetRawInfo(struct SiiRtcInfo *rtc) +{ + struct Time* time = FakeRtc_GetCurrentTime(); + rtc->second = time->seconds; + rtc->minute = time->minutes; + rtc->hour = time->hours; + rtc->day = time->days; +} + +void FakeRtc_TickTimeForward(void) +{ + if (!OW_USE_FAKE_RTC) + return; + + FakeRtc_AdvanceTimeBy(0, 0, FakeRtc_GetSecondsRatio()); +} + +void FakeRtc_AdvanceTimeBy(u32 hours, u32 minutes, u32 seconds) +{ + struct Time* time = FakeRtc_GetCurrentTime(); + seconds += time->seconds; + minutes += time->minutes; + hours += time->hours; + + 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) + { + time->days++; + hours -= HOURS_PER_DAY; + } + + time->seconds = seconds; + time->minutes = minutes; + time->hours = hours; +} + +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; + + CalcTimeDifference(&diff, &gLocalTime, &target); + FakeRtc_AdvanceTimeBy(diff.hours, diff.minutes, diff.seconds); +} + +u32 FakeRtc_GetSecondsRatio(void) +{ + return (OW_ALTERED_TIME_RATIO == GEN_8_PLA) ? 60 : + (OW_ALTERED_TIME_RATIO == GEN_9) ? 20 : + 1; +} + diff --git a/src/play_time.c b/src/play_time.c index 97f4ac22f962..197b1fbac9a6 100644 --- a/src/play_time.c +++ b/src/play_time.c @@ -1,5 +1,6 @@ #include "global.h" #include "play_time.h" +#include "fake_rtc.h" enum { @@ -45,6 +46,7 @@ void PlayTimeCounter_Update(void) gSaveBlock2Ptr->playTimeVBlanks = 0; gSaveBlock2Ptr->playTimeSeconds++; + FakeRtc_TickTimeForward(); if (gSaveBlock2Ptr->playTimeSeconds < 60) return; diff --git a/src/rtc.c b/src/rtc.c index a53d5e1fd8ba..5ccafec621bd 100644 --- a/src/rtc.c +++ b/src/rtc.c @@ -3,6 +3,7 @@ #include "string_util.h" #include "strings.h" #include "text.h" +#include "fake_rtc.h" // iwram bss static u16 sErrorStatus; @@ -46,6 +47,9 @@ void RtcRestoreInterrupts(void) u32 ConvertBcdToBinary(u8 bcd) { + if (OW_USE_FAKE_RTC) + return bcd; + if (bcd > 0x9F) return 0xFF; @@ -89,14 +93,22 @@ u16 ConvertDateToDayCount(u8 year, u8 month, u8 day) u16 RtcGetDayCount(struct SiiRtcInfo *rtc) { - u8 year = ConvertBcdToBinary(rtc->year); - u8 month = ConvertBcdToBinary(rtc->month); - u8 day = ConvertBcdToBinary(rtc->day); + u8 year, month, day; + + if (OW_USE_FAKE_RTC) + return rtc->day; + + year = ConvertBcdToBinary(rtc->year); + month = ConvertBcdToBinary(rtc->month); + day = ConvertBcdToBinary(rtc->day); return ConvertDateToDayCount(year, month, day); } void RtcInit(void) { + if (OW_USE_FAKE_RTC) + return; + sErrorStatus = 0; RtcDisableInterrupts(); @@ -121,12 +133,14 @@ void RtcInit(void) u16 RtcGetErrorStatus(void) { - return sErrorStatus; + return (OW_USE_FAKE_RTC) ? 0 : sErrorStatus; } void RtcGetInfo(struct SiiRtcInfo *rtc) { - if (sErrorStatus & RTC_ERR_FLAG_MASK) + if (OW_USE_FAKE_RTC) + FakeRtc_GetRawInfo(rtc); + else if (sErrorStatus & RTC_ERR_FLAG_MASK) *rtc = sRtcDummy; else RtcGetRawInfo(rtc); @@ -159,6 +173,9 @@ u16 RtcCheckInfo(struct SiiRtcInfo *rtc) s32 month; s32 value; + if (OW_USE_FAKE_RTC) + return 0; + if (rtc->status & SIIRTCINFO_POWER) errorFlags |= RTC_ERR_POWER_FAILURE; @@ -211,6 +228,12 @@ u16 RtcCheckInfo(struct SiiRtcInfo *rtc) void RtcReset(void) { + if (OW_USE_FAKE_RTC) + { + memset(FakeRtc_GetCurrentTime(), 0, sizeof(struct Time)); + return; + } + RtcDisableInterrupts(); SiiRtcReset(); RtcRestoreInterrupts();