mirror of https://github.com/LIJI32/SameBoy.git
Fixed a bug where accurate RTC emulation halted while SameBoy wasn't running
This commit is contained in:
parent
4ab256d896
commit
048da6e6d1
|
@ -1040,7 +1040,9 @@ void GB_load_battery_from_buffer(GB_gameboy_t *gb, const uint8_t *buffer, size_t
|
|||
really RTC data. */
|
||||
goto reset_rtc;
|
||||
}
|
||||
GB_rtc_set_time(gb, time(NULL));
|
||||
goto exit;
|
||||
|
||||
reset_rtc:
|
||||
gb->last_rtc_second = time(NULL);
|
||||
gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */
|
||||
|
@ -1150,7 +1152,9 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path)
|
|||
really RTC data. */
|
||||
goto reset_rtc;
|
||||
}
|
||||
GB_rtc_set_time(gb, time(NULL));
|
||||
goto exit;
|
||||
|
||||
reset_rtc:
|
||||
gb->last_rtc_second = time(NULL);
|
||||
gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */
|
||||
|
|
146
Core/timing.c
146
Core/timing.c
|
@ -282,6 +282,81 @@ void GB_set_rtc_multiplier(GB_gameboy_t *gb, double multiplier)
|
|||
gb->rtc_second_length = GB_get_unmultiplied_clock_rate(gb) * 2 * multiplier;
|
||||
}
|
||||
|
||||
void GB_rtc_set_time(GB_gameboy_t *gb, uint64_t current_time)
|
||||
{
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
while (gb->last_rtc_second / 60 < current_time / 60) {
|
||||
gb->last_rtc_second += 60;
|
||||
gb->huc3.minutes++;
|
||||
if (gb->huc3.minutes == 60 * 24) {
|
||||
gb->huc3.days++;
|
||||
gb->huc3.minutes = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
bool running = false;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
running = gb->tpp1_mr4 & 0x4;
|
||||
}
|
||||
else {
|
||||
running = (gb->rtc_real.high & 0x40) == 0;
|
||||
}
|
||||
|
||||
if (!running) return;
|
||||
|
||||
while (gb->last_rtc_second + 60 * 60 * 24 < current_time) {
|
||||
gb->last_rtc_second += 60 * 60 * 24;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if (++gb->rtc_real.tpp1.weekday == 7) {
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (++gb->rtc_real.days == 0) {
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (gb->last_rtc_second < current_time) {
|
||||
gb->last_rtc_second++;
|
||||
if (++gb->rtc_real.seconds != 60) continue;
|
||||
gb->rtc_real.seconds = 0;
|
||||
|
||||
if (++gb->rtc_real.minutes != 60) continue;
|
||||
gb->rtc_real.minutes = 0;
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if (++gb->rtc_real.tpp1.hours != 24) continue;
|
||||
gb->rtc_real.tpp1.hours = 0;
|
||||
if (++gb->rtc_real.tpp1.weekday != 7) continue;
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++gb->rtc_real.hours != 24) continue;
|
||||
gb->rtc_real.hours = 0;
|
||||
|
||||
if (++gb->rtc_real.days != 0) continue;
|
||||
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void rtc_run(GB_gameboy_t *gb, uint8_t cycles)
|
||||
{
|
||||
if (likely(gb->cartridge_type->mbc_type != GB_HUC3 && !gb->cartridge_type->has_rtc)) return;
|
||||
|
@ -307,76 +382,7 @@ static void rtc_run(GB_gameboy_t *gb, uint8_t cycles)
|
|||
break;
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_HUC3) {
|
||||
while (gb->last_rtc_second / 60 < current_time / 60) {
|
||||
gb->last_rtc_second += 60;
|
||||
gb->huc3.minutes++;
|
||||
if (gb->huc3.minutes == 60 * 24) {
|
||||
gb->huc3.days++;
|
||||
gb->huc3.minutes = 0;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
bool running = false;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
running = gb->tpp1_mr4 & 0x4;
|
||||
}
|
||||
else {
|
||||
running = (gb->rtc_real.high & 0x40) == 0;
|
||||
}
|
||||
|
||||
if (running) { /* is timer running? */
|
||||
while (gb->last_rtc_second + 60 * 60 * 24 < current_time) {
|
||||
gb->last_rtc_second += 60 * 60 * 24;
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if (++gb->rtc_real.tpp1.weekday == 7) {
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (++gb->rtc_real.days == 0) {
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
|
||||
while (gb->last_rtc_second < current_time) {
|
||||
gb->last_rtc_second++;
|
||||
if (++gb->rtc_real.seconds != 60) continue;
|
||||
gb->rtc_real.seconds = 0;
|
||||
|
||||
if (++gb->rtc_real.minutes != 60) continue;
|
||||
gb->rtc_real.minutes = 0;
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_TPP1) {
|
||||
if (++gb->rtc_real.tpp1.hours != 24) continue;
|
||||
gb->rtc_real.tpp1.hours = 0;
|
||||
if (++gb->rtc_real.tpp1.weekday != 7) continue;
|
||||
gb->rtc_real.tpp1.weekday = 0;
|
||||
if (++gb->rtc_real.tpp1.weeks == 0) {
|
||||
gb->tpp1_mr4 |= 8; /* Overflow bit */
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (++gb->rtc_real.hours != 24) continue;
|
||||
gb->rtc_real.hours = 0;
|
||||
|
||||
if (++gb->rtc_real.days != 0) continue;
|
||||
|
||||
if (gb->rtc_real.high & 1) { /* Bit 8 of days*/
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
GB_rtc_set_time(gb, current_time);
|
||||
}
|
||||
|
||||
static void camera_run(GB_gameboy_t *gb, uint8_t cycles)
|
||||
|
|
|
@ -20,7 +20,7 @@ internal bool GB_timing_sync_turbo(GB_gameboy_t *gb); /* Returns true if should
|
|||
internal void GB_timing_sync(GB_gameboy_t *gb);
|
||||
internal void GB_set_internal_div_counter(GB_gameboy_t *gb, uint16_t value);
|
||||
internal void GB_serial_master_edge(GB_gameboy_t *gb);
|
||||
|
||||
internal void GB_rtc_set_time(GB_gameboy_t *gb, uint64_t time);
|
||||
|
||||
#define GB_SLEEP(gb, unit, state, cycles) do {\
|
||||
(gb)->unit##_cycles -= (cycles) * __state_machine_divisor; \
|
||||
|
|
Loading…
Reference in New Issue