Skip to content

Commit

Permalink
n64: fix dd rtc skipping december + validity checks to avoid glitchy …
Browse files Browse the repository at this point in the history
…rtc (#1290)

- add more details to the dd time.rtc format as comments for readability
- fix dd rtc skipping december entirely (wrong comparison)
  - I feel really dumb for this one.
- add validity checks on every rtc second tick to avoid glitchy rtc time
& date
- This also avoids the user to be able to skip the time & date error
into a glitchy rtc by simply restarting.
- add validity check on load if the time is valid or not, if not valid,
destroy the rtc info to get the user to input new rtc info
  • Loading branch information
LuigiBlood authored Nov 15, 2023
1 parent 4537145 commit 8a4bf9d
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 1 deletion.
1 change: 1 addition & 0 deletions ares/n64/dd/dd.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ struct DD : Memory::PI<DD> {
auto tick(u32 offset) -> void;
auto tickClock() -> void;
auto tickSecond() -> void;
auto valid() -> bool;
} rtc;

auto title() const -> string { return information.title; }
Expand Down
40 changes: 39 additions & 1 deletion ares/n64/dd/rtc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,23 @@ auto DD::RTC::load() -> void {
ram.load(fp);
}

//byte 0 to 7 = raw rtc time (last updated, only 6 bytes are used)
n64 check = 0;
for(auto n : range(8)) check.byte(n) = ram.read<Byte>(n);
if(!~check) return; //new save file

//check for invalid time info, if invalid, set time info to something invalid and ignore the rest
if (!valid()) {
for(auto n : range(8)) ram.write<Byte>(n, 0xff);
return;
}

//byte 8 to 15 = timestamp of when the last save was made
n64 timestamp = 0;
for(auto n : range(8)) timestamp.byte(n) = ram.read<Byte>(8 + n);
if(!~timestamp) return; //new save file

//update based on the amount of time that has passed since the last save
timestamp = time(0) - timestamp;
while(timestamp--) tickSecond();
}
Expand Down Expand Up @@ -47,6 +56,8 @@ auto DD::RTC::tickClock() -> void {
}

auto DD::RTC::tickSecond() -> void {
if (!valid()) return;

//second
tick(5);
if(ram.read<Byte>(5) < 0x60) return;
Expand All @@ -72,9 +83,36 @@ auto DD::RTC::tickSecond() -> void {

//month
tick(1);
if(ram.read<Byte>(1) < 0x12) return;
if(ram.read<Byte>(1) <= 0x12) return;
ram.write<Byte>(1, 1);

//year
tick(0);
}

auto DD::RTC::valid() -> bool {
//check validity of ram rtc data (if it's BCD valid or not)
for(auto n : range(6)) {
if ((ram.read<Byte>(n) & 0x0f) >= 0x0a) return false;
if (ram.read<Byte>(n) >= 0xa0) return false;
}

//check for valid values of each byte
//second
if(ram.read<Byte>(5) >= 0x60) return false;
//minute
if(ram.read<Byte>(4) >= 0x60) return false;
//hour
if(ram.read<Byte>(3) >= 0x24) return false;
//month
if(ram.read<Byte>(1) > 0x12) return false;
if(ram.read<Byte>(1) < 1) return false;
//day
if(ram.read<Byte>(2) < 1) return false;
u32 daysInMonth[12] = {0x31, 0x28, 0x31, 0x30, 0x31, 0x30, 0x31, 0x31, 0x30, 0x31, 0x30, 0x31};
if(ram.read<Byte>(0) && !(BCD::decode(ram.read<Byte>(0)) % 4)) daysInMonth[1]++;
if(ram.read<Byte>(2) > daysInMonth[BCD::decode(ram.read<Byte>(1))-1]) return false;

//everything is valid
return true;
}

0 comments on commit 8a4bf9d

Please sign in to comment.