Align semantic of all RTC implementations:

* Initialize using the PC localtime
* Handle backward time warp by ignoring it
This commit is contained in:
Giovanni Bajo
2026-09-06 12:34:34 +01:00
committed by Luke Usher
parent dee49f55ae
commit af4cbb04f0
7 changed files with 115 additions and 30 deletions
+19 -4
View File
@@ -10,7 +10,21 @@ namespace ares {
auto S3511A::load() -> void {
n64 timestamp = 0;
for(auto n : range(8)) timestamp.byte(n) = data[8 + n];
if(!timestamp || !(timestamp + 1)) return initRegs(false); //new save file
if(!timestamp || !(timestamp + 1)) { //new save file
time_t t = time(0);
struct tm tmm = *localtime(&t);
year() = BCD::encode(tmm.tm_year % 100);
month() = BCD::encode(tmm.tm_mon + 1);
day() = BCD::encode(tmm.tm_mday);
weekday() = tmm.tm_wday;
hour() = BCD::encode(tmm.tm_hour);
minute() = BCD::encode(tmm.tm_min);
second() = BCD::encode(tmm.tm_sec);
status() = 0x82;
alarmHour() = 0x00;
alarmMinute() = 0x80;
return;
}
if(status() & 0x15) {
//these status bits are always 0; reset state on invalid status.
@@ -18,9 +32,10 @@ auto S3511A::load() -> void {
return;
}
timestamp = time(0) - timestamp;
//prevent insurmountable slowdown by limiting skips to 5 years
if(timestamp < 60*60*24*365*5) {
time_t now = time(0);
time_t saved = (time_t)timestamp;
if(now > saved) {
timestamp = now - saved;
while(timestamp--) tickSecond();
}
}
+18 -6
View File
@@ -26,13 +26,25 @@ struct MBC3 : Interface {
for(u32 index : range(8)) {
timestamp.byte(index) = rtc[5 + index];
}
n64 diff = chrono::timestamp() - timestamp;
if(diff < 32 * 365 * 24 * 60 * 60) {
while(diff >= 24 * 60 * 60) { tickDay(); diff -= 24 * 60 * 60; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
while(diff) { tickSecond(); diff -= 1; }
if(!timestamp || !(timestamp + 1)) {
time_t t = time(0);
struct tm tmm = *localtime(&t);
io.rtc.second = tmm.tm_sec;
io.rtc.minute = tmm.tm_min;
io.rtc.hour = tmm.tm_hour;
io.rtc.day = (n9)((t / 86400) % 512);
io.rtc.halt = 0;
io.rtc.dayCarry = 0;
return;
}
time_t now = chrono::timestamp();
time_t saved = (time_t)timestamp;
if(now <= saved) return;
n64 diff = now - saved;
while(diff >= 24 * 60 * 60) { tickDay(); diff -= 24 * 60 * 60; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
while(diff) { tickSecond(); diff -= 1; }
}
}
+19 -6
View File
@@ -33,13 +33,26 @@ struct TAMA : Interface {
for(u32 index : range(8)) {
timestamp.byte(index) = rtc[7 + index];
}
n64 diff = chrono::timestamp() - timestamp;
if(diff < 32 * 365 * 24 * 60 * 60) {
while(diff >= 24 * 60 * 60) { tickDay(); diff -= 24 * 60 * 60; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
while(diff) { tickSecond(); diff -= 1; }
if(!timestamp || !(timestamp + 1)) {
time_t t = time(0);
struct tm tmm = *localtime(&t);
io.rtc.year = tmm.tm_year % 100;
io.rtc.month = tmm.tm_mon + 1;
io.rtc.day = tmm.tm_mday;
io.rtc.hour = tmm.tm_hour;
io.rtc.minute = tmm.tm_min;
io.rtc.second = tmm.tm_sec;
io.rtc.meridian = tmm.tm_hour >= 12;
return;
}
time_t now = chrono::timestamp();
time_t saved = (time_t)timestamp;
if(now <= saved) return;
n64 diff = now - saved;
while(diff >= 24 * 60 * 60) { tickDay(); diff -= 24 * 60 * 60; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
while(diff) { tickSecond(); diff -= 1; }
}
}
+20 -8
View File
@@ -7,7 +7,20 @@ auto DD::RTC::load() -> void {
//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
//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(!~check || !~timestamp) { //new save file
time_t t = time(0);
struct tm tmm = *localtime(&t);
ram.write<Byte>(0, BCD::encode(tmm.tm_year % 100));
ram.write<Byte>(1, BCD::encode(tmm.tm_mon + 1));
ram.write<Byte>(2, BCD::encode(tmm.tm_mday));
ram.write<Byte>(3, BCD::encode(tmm.tm_hour));
ram.write<Byte>(4, BCD::encode(tmm.tm_min));
ram.write<Byte>(5, BCD::encode(tmm.tm_sec));
return;
}
//check for invalid time info, if invalid, set time info to something invalid and ignore the rest
if (!valid()) {
@@ -15,14 +28,13 @@ auto DD::RTC::load() -> void {
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();
time_t now = time(0);
time_t saved = (time_t)timestamp;
if(now > saved) {
timestamp = now - saved;
while(timestamp--) tickSecond();
}
}
auto DD::RTC::reset() -> void {
+10 -1
View File
@@ -155,7 +155,16 @@ auto EpsonRTC::load(const n8* data) -> void {
timestamp |= (n64)(data[8 + byte]) << (byte * 8);
}
n64 diff = (n64)time(0) - timestamp;
if(!timestamp || !(timestamp + 1)) {
synchronize(time(0));
return;
}
time_t now = time(0);
time_t saved = (time_t)timestamp;
if(now <= saved) return;
n64 diff = now - saved;
while(diff >= 60 * 60 * 24) { tickDay(); diff -= 60 * 60 * 24; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
+10 -1
View File
@@ -46,7 +46,16 @@ auto SharpRTC::load(const n8* data) -> void {
timestamp |= (n64)(data[8 + byte]) << (byte * 8);
}
n64 diff = (n64)time(0) - timestamp;
if(!timestamp || !(timestamp + 1)) {
synchronize(time(0));
return;
}
time_t now = time(0);
time_t saved = (time_t)timestamp;
if(now <= saved) return;
n64 diff = now - saved;
while(diff >= 60 * 60 * 24) { tickDay(); diff -= 60 * 60 * 24; }
while(diff >= 60 * 60) { tickHour(); diff -= 60 * 60; }
while(diff >= 60) { tickMinute(); diff -= 60; }
+19 -4
View File
@@ -3,7 +3,21 @@
auto Cartridge::RTC::load() -> void {
n64 timestamp = 0;
for(auto n : range(8)) timestamp.byte(n) = ram.read(8 + n);
if(!timestamp || !(timestamp + 1)) return; //new save file
if(!timestamp || !(timestamp + 1)) { //new save file
time_t t = time(0);
struct tm tmm = *localtime(&t);
year() = BCD::encode(tmm.tm_year % 100);
month() = BCD::encode(tmm.tm_mon + 1);
day() = BCD::encode(tmm.tm_mday);
weekday() = tmm.tm_wday;
hour() = BCD::encode(tmm.tm_hour);
minute() = BCD::encode(tmm.tm_min);
second() = BCD::encode(tmm.tm_sec);
status() = 0x82;
alarmHour() = 0x00;
alarmMinute() = 0x80;
return;
}
if(status() & 0x15) {
// These status bits are always 0; reset state on invalid status.
@@ -11,9 +25,10 @@ auto Cartridge::RTC::load() -> void {
return;
}
timestamp = time(0) - timestamp;
// prevent insurmountable slowdown by limiting skips to 5 years
if(timestamp < 60*60*24*365*5) {
time_t now = time(0);
time_t saved = (time_t)timestamp;
if(now > saved) {
timestamp = now - saved;
while(timestamp--) tickSecond();
}
}