diff --git a/Core/memory.c b/Core/memory.c index 3e7d4a4..20aaac9 100644 --- a/Core/memory.c +++ b/Core/memory.c @@ -192,9 +192,20 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr) break; // Read RAM case 5: switch (addr & 3) { - case 0: return (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days) / 7; // Week count - case 1: return gb->rtc_latched.hours | - (((((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days) % 7) << 5); // Hours and weekday + case 0: { // Week count + unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days); + if (gb->rtc_latched.high & 0x20) { + return total_days / 7 - 1; + } + return total_days / 7; + } + case 1: { // Week count + unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days); + if (gb->rtc_latched.high & 0x20) { + return gb->rtc_latched.hours | 0xe0; // Hours and weekday + } + return gb->rtc_latched.hours | ((total_days % 7) << 5); // Hours and weekday + } case 2: return gb->rtc_latched.minutes; case 3: return gb->rtc_latched.seconds; } @@ -616,7 +627,7 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0x11: { uint8_t flags = gb->rtc_real.high & 0xc0; memcpy(&gb->rtc_real, &gb->rtc_latched, sizeof(gb->rtc_real)); - gb->rtc_real.high &= ~0xc0; + gb->rtc_real.high &= ~0xe0; gb->rtc_real.high |= flags; break; } @@ -762,8 +773,12 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) case 0: { unsigned total_days = (((gb->rtc_latched.high & 7) << 8) + gb->rtc_latched.days); total_days = total_days % 7 + value * 7; + bool had_illegal_weekday = gb->rtc_latched.high & 0x20; gb->rtc_latched.days = total_days; gb->rtc_latched.high = total_days >> 8; + if (had_illegal_weekday) { + gb->rtc_latched.high |= 0x20; + } return; } case 1: { @@ -772,6 +787,9 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value) gb->rtc_latched.hours = value & 0x1F; gb->rtc_latched.days = total_days; gb->rtc_latched.high = total_days >> 8; + if ((value & 0xE0) == 0xE0) { // Illegal weekday + gb->rtc_latched.high |= 0x20; + } return; } case 2: gb->rtc_latched.minutes = value; return;