From 91dc245acb458b20dc5b36b7755e0888676e277d Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Mon, 12 Jun 2023 17:38:40 +0100 Subject: [PATCH 1/8] gb: add RTC latch to MBC3 Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 69 +++++++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 31 deletions(-) diff --git a/peanut_gb.h b/peanut_gb.h index bcda494..596f11e 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -483,6 +483,19 @@ enum gb_serial_rx_ret_e GB_SERIAL_RX_NO_CONNECTION = 1 }; +union cart_rtc +{ + struct + { + uint8_t sec; + uint8_t min; + uint8_t hour; + uint8_t yday; + uint8_t high; + } reg; + uint8_t bytes[5]; +}; + /** * Emulator context. * @@ -559,18 +572,8 @@ struct gb_s uint8_t enable_cart_ram; /* Cartridge ROM/RAM mode select. */ uint8_t cart_mode_select; - union - { - struct - { - uint8_t sec; - uint8_t min; - uint8_t hour; - uint8_t yday; - uint8_t high; - } rtc_bits; - uint8_t cart_rtc[5]; - }; + + union cart_rtc rtc_latched, rtc_real; struct cpu_registers_s cpu_reg; //struct gb_registers_s gb_reg; @@ -731,7 +734,7 @@ uint8_t __gb_read(struct gb_s *gb, uint16_t addr) case 0xB: if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08) { - return gb->cart_rtc[gb->cart_ram_bank - 0x08]; + return gb->rtc_latched.bytes[gb->cart_ram_bank - 0x08]; } else if(gb->cart_ram && gb->enable_cart_ram) { @@ -885,7 +888,11 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) case 0x6: case 0x7: - gb->cart_mode_select = (val & 1); + val &= 1; + if(gb->mbc == 3 && val && gb->cart_mode_select == 0) + memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_latched)); + + gb->cart_mode_select = val; return; case 0x8: @@ -897,7 +904,7 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) case 0xB: if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08) { - gb->cart_rtc[gb->cart_ram_bank - 0x08] = val; + gb->rtc_latched.bytes[gb->cart_ram_bank - 0x08] = val; } /* Do not write to RAM if unavailable or disabled. */ else if(gb->cart_ram && gb->enable_cart_ram) @@ -3674,28 +3681,28 @@ void gb_set_bootrom(struct gb_s *gb, void gb_tick_rtc(struct gb_s *gb) { /* is timer running? */ - if((gb->cart_rtc[4] & 0x40) == 0) + if((gb->rtc_latched.bytes[4] & 0x40) == 0) { - if(++gb->rtc_bits.sec == 60) + if(++gb->rtc_real.reg.sec == 60) { - gb->rtc_bits.sec = 0; + gb->rtc_real.reg.sec = 0; - if(++gb->rtc_bits.min == 60) + if(++gb->rtc_real.reg.min == 60) { - gb->rtc_bits.min = 0; + gb->rtc_real.reg.min = 0; - if(++gb->rtc_bits.hour == 24) + if(++gb->rtc_real.reg.hour == 24) { - gb->rtc_bits.hour = 0; + gb->rtc_real.reg.hour = 0; - if(++gb->rtc_bits.yday == 0) + if(++gb->rtc_real.reg.yday == 0) { - if(gb->rtc_bits.high & 1) /* Bit 8 of days*/ + if(gb->rtc_real.reg.high & 1) /* Bit 8 of days*/ { - gb->rtc_bits.high |= 0x80; /* Overflow bit */ + gb->rtc_real.reg.high |= 0x80; /* Overflow bit */ } - gb->rtc_bits.high ^= 1; + gb->rtc_real.reg.high ^= 1; } } } @@ -3705,11 +3712,11 @@ void gb_tick_rtc(struct gb_s *gb) void gb_set_rtc(struct gb_s *gb, const struct tm * const time) { - gb->cart_rtc[0] = time->tm_sec; - gb->cart_rtc[1] = time->tm_min; - gb->cart_rtc[2] = time->tm_hour; - gb->cart_rtc[3] = time->tm_yday & 0xFF; /* Low 8 bits of day counter. */ - gb->cart_rtc[4] = time->tm_yday >> 8; /* High 1 bit of day counter. */ + gb->rtc_real.bytes[0] = time->tm_sec; + gb->rtc_real.bytes[1] = time->tm_min; + gb->rtc_real.bytes[2] = time->tm_hour; + gb->rtc_real.bytes[3] = time->tm_yday & 0xFF; /* Low 8 bits of day counter. */ + gb->rtc_real.bytes[4] = time->tm_yday >> 8; /* High 1 bit of day counter. */ } #endif // PEANUT_GB_HEADER_ONLY From 225c1e5a0776acfa03588251c21050d4158a7c18 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Mon, 12 Jun 2023 17:46:07 +0100 Subject: [PATCH 2/8] gb: tick RTC with CPU emulation Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 69 +++++++++++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 28 deletions(-) diff --git a/peanut_gb.h b/peanut_gb.h index 596f11e..9d4c343 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -150,6 +150,9 @@ #define SCREEN_REFRESH_CYCLES 70224.0 #define VERTICAL_SYNC (DMG_CLOCK_FREQ/SCREEN_REFRESH_CYCLES) +/* Real Time Clock is locked to 1Hz. */ +#define RTC_CYCLES ((unsigned long)DMG_CLOCK_FREQ) + /* SERIAL SC register masks. */ #define SERIAL_SC_TX_START 0x80 #define SERIAL_SC_CLOCK_SRC 0x01 @@ -429,6 +432,7 @@ struct count_s uint_fast16_t div_count; /* Divider Register Counter */ uint_fast16_t tima_count; /* Timer Counter */ uint_fast16_t serial_count; /* Serial Counter */ + uint_fast32_t rtc_count; /* RTC Counter */ }; #if ENABLE_LCD @@ -3225,6 +3229,41 @@ void __gb_step_cpu(struct gb_s *gb) gb->counter.div_count -= DIV_CYCLES; } + /* Check for RTC tick. */ + if(gb->mbc == 3 && (gb->rtc_reg.cart_rtc[4] & 0x40) == 0) + { + gb->counter.rtc_count += inst_cycles; + if(gb->counter.rtc_count >= RTC_CYCLES) + { + gb->counter.rtc_count -= RTC_CYCLES; + + if(++gb->rtc_real.reg.sec == 60) + { + gb->rtc_real.reg.sec = 0; + + if(++gb->rtc_real.reg.min == 60) + { + gb->rtc_real.reg.min = 0; + + if(++gb->rtc_real.reg.hour == 24) + { + gb->rtc_real.reg.hour = 0; + + if(++gb->rtc_real.reg.yday == 0) + { + if(gb->rtc_real.reg.high & 1) /* Bit 8 of days*/ + { + gb->rtc_real.reg.high |= 0x80; /* Overflow bit */ + } + + gb->rtc_real.reg.high ^= 1; + } + } + } + } + } + } + /* Check serial transmission. */ if(gb->hram_io[IO_SC] & SERIAL_SC_TX_START) { @@ -3680,34 +3719,8 @@ void gb_set_bootrom(struct gb_s *gb, */ void gb_tick_rtc(struct gb_s *gb) { - /* is timer running? */ - if((gb->rtc_latched.bytes[4] & 0x40) == 0) - { - if(++gb->rtc_real.reg.sec == 60) - { - gb->rtc_real.reg.sec = 0; - - if(++gb->rtc_real.reg.min == 60) - { - gb->rtc_real.reg.min = 0; - - if(++gb->rtc_real.reg.hour == 24) - { - gb->rtc_real.reg.hour = 0; - - if(++gb->rtc_real.reg.yday == 0) - { - if(gb->rtc_real.reg.high & 1) /* Bit 8 of days*/ - { - gb->rtc_real.reg.high |= 0x80; /* Overflow bit */ - } - - gb->rtc_real.reg.high ^= 1; - } - } - } - } - } + (void) gb; + return; } void gb_set_rtc(struct gb_s *gb, const struct tm * const time) From 81df6575d0d7715cfc06769314997a0f58e2e419 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Mon, 12 Jun 2023 17:48:15 +0100 Subject: [PATCH 3/8] gb: fix incorrect RTC variable name Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peanut_gb.h b/peanut_gb.h index 9d4c343..56ab918 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -3230,7 +3230,7 @@ void __gb_step_cpu(struct gb_s *gb) } /* Check for RTC tick. */ - if(gb->mbc == 3 && (gb->rtc_reg.cart_rtc[4] & 0x40) == 0) + if(gb->mbc == 3 && (gb->rtc_real.bytes[4] & 0x40) == 0) { gb->counter.rtc_count += inst_cycles; if(gb->counter.rtc_count >= RTC_CYCLES) From 1fd0eeafb034993038bbf04ccd0a2d15f2a1450b Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Mon, 12 Jun 2023 17:59:22 +0100 Subject: [PATCH 4/8] gb: fix RTC writing Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/peanut_gb.h b/peanut_gb.h index 56ab918..9b98ce7 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -894,7 +894,7 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) case 0x7: val &= 1; if(gb->mbc == 3 && val && gb->cart_mode_select == 0) - memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_latched)); + memcpy(&gb->rtc_latched.bytes, &gb->rtc_real.bytes, sizeof(gb->rtc_latched.bytes)); gb->cart_mode_select = val; return; @@ -908,7 +908,7 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) case 0xB: if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08) { - gb->rtc_latched.bytes[gb->cart_ram_bank - 0x08] = val; + gb->rtc_real.bytes[gb->cart_ram_bank - 0x08] = val; } /* Do not write to RAM if unavailable or disabled. */ else if(gb->cart_ram && gb->enable_cart_ram) From 8db74db31ebf203810a9b7fd8c2c3b4b0a1b8f94 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Fri, 3 Nov 2023 18:39:30 +0000 Subject: [PATCH 5/8] gb: pass invalid rollovers RTC test Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 72 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 23 deletions(-) diff --git a/peanut_gb.h b/peanut_gb.h index bf3ad9f..7ae1008 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -917,7 +917,13 @@ void __gb_write(struct gb_s *gb, uint_fast16_t addr, uint8_t val) case 0xB: if(gb->mbc == 3 && gb->cart_ram_bank >= 0x08) { - gb->rtc_real.bytes[gb->cart_ram_bank - 0x08] = val; + const uint8_t rtc_reg_mask[5] = { + 0x3F, 0x3F, 0x1F, 0xFF, 0xC1 + }; + uint8_t reg = gb->cart_ram_bank - 0x08; + //if(reg == 0) gb->counter.rtc_count = 0; + + gb->rtc_real.bytes[reg] = val & rtc_reg_mask[reg]; } /* Do not write to RAM if unavailable or disabled. */ else if(gb->cart_ram && gb->enable_cart_ram) @@ -3245,37 +3251,57 @@ void __gb_step_cpu(struct gb_s *gb) } /* Check for RTC tick. */ - if(gb->mbc == 3 && (gb->rtc_real.bytes[4] & 0x40) == 0) + if(gb->mbc == 3 && (gb->rtc_real.reg.high & 0x40) == 0) { gb->counter.rtc_count += inst_cycles; - if(gb->counter.rtc_count >= RTC_CYCLES) + while(gb->counter.rtc_count >= RTC_CYCLES) { + printf("Count: %lu, ", gb->counter.rtc_count); gb->counter.rtc_count -= RTC_CYCLES; - if(++gb->rtc_real.reg.sec == 60) + printf("(%d)%d %02d:%02d:%02d\n", + (gb->rtc_real.reg.high & 0x80), + (gb->rtc_real.reg.high & 1) << 8 | gb->rtc_real.reg.yday, + gb->rtc_real.reg.hour, + gb->rtc_real.reg.min, + gb->rtc_real.reg.sec); + + /* Detect invalid rollover. */ + if(gb->rtc_real.reg.sec == 63) { gb->rtc_real.reg.sec = 0; + continue; + } + + if(++gb->rtc_real.reg.sec != 60) + continue; - if(++gb->rtc_real.reg.min == 60) - { - gb->rtc_real.reg.min = 0; - - if(++gb->rtc_real.reg.hour == 24) - { - gb->rtc_real.reg.hour = 0; - - if(++gb->rtc_real.reg.yday == 0) - { - if(gb->rtc_real.reg.high & 1) /* Bit 8 of days*/ - { - gb->rtc_real.reg.high |= 0x80; /* Overflow bit */ - } - - gb->rtc_real.reg.high ^= 1; - } - } - } + gb->rtc_real.reg.sec = 0; + if(gb->rtc_real.reg.min == 63) + { + gb->rtc_real.reg.min = 0; + continue; } + if(++gb->rtc_real.reg.min != 60) + continue; + + gb->rtc_real.reg.min = 0; + if(gb->rtc_real.reg.hour == 31) + { + gb->rtc_real.reg.hour = 0; + continue; + } + if(++gb->rtc_real.reg.hour != 24) + continue; + + gb->rtc_real.reg.hour = 0; + if(++gb->rtc_real.reg.yday != 0) + continue; + + if(gb->rtc_real.reg.high & 1) /* Bit 8 of days*/ + gb->rtc_real.reg.high |= 0x80; /* Overflow bit */ + + gb->rtc_real.reg.high ^= 1; } } From 871be2cfddbb3d301a47d0ce6ceedebd98d2e526 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Fri, 22 Dec 2023 22:27:35 +0000 Subject: [PATCH 6/8] core: remove RTC debugging & deprecate gb_tick_rtc() Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/peanut_gb.h b/peanut_gb.h index 7ae1008..70fee0c 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -3256,23 +3256,15 @@ void __gb_step_cpu(struct gb_s *gb) gb->counter.rtc_count += inst_cycles; while(gb->counter.rtc_count >= RTC_CYCLES) { - printf("Count: %lu, ", gb->counter.rtc_count); gb->counter.rtc_count -= RTC_CYCLES; - printf("(%d)%d %02d:%02d:%02d\n", - (gb->rtc_real.reg.high & 0x80), - (gb->rtc_real.reg.high & 1) << 8 | gb->rtc_real.reg.yday, - gb->rtc_real.reg.hour, - gb->rtc_real.reg.min, - gb->rtc_real.reg.sec); - /* Detect invalid rollover. */ if(gb->rtc_real.reg.sec == 63) { gb->rtc_real.reg.sec = 0; continue; } - + if(++gb->rtc_real.reg.sec != 60) continue; @@ -3756,7 +3748,7 @@ void gb_set_bootrom(struct gb_s *gb, } /** - * This was taken from SameBoy, which is released under MIT Licence. + * Deprecated. Will be removed in the next major version. */ void gb_tick_rtc(struct gb_s *gb) { @@ -3893,10 +3885,8 @@ uint8_t gb_colour_hash(struct gb_s *gb); const char* gb_get_rom_name(struct gb_s* gb, char *title_str); /** - * Tick the internal RTC by one second. This does not affect games with no RTC - * support. - * - * \param gb An initialised emulator context. Must not be NULL. + * Deprecated. Will be removed in the next major version. + * RTC is ticked internally and this function has no effect. */ void gb_tick_rtc(struct gb_s *gb); From d89bd2a306a549598b5c5b6674d362e21c030f37 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Sat, 23 Dec 2023 11:10:46 +0000 Subject: [PATCH 7/8] core: initialise rtc_count on init Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 1 + 1 file changed, 1 insertion(+) diff --git a/peanut_gb.h b/peanut_gb.h index 70fee0c..2629fcd 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -3584,6 +3584,7 @@ void gb_reset(struct gb_s *gb) gb->counter.div_count = 0; gb->counter.tima_count = 0; gb->counter.serial_count = 0; + gb->counter.rtc_count = 0; gb->direct.joypad = 0xFF; gb->hram_io[IO_JOYP] = 0xCF; From f6ed3b7e60e6060bf5267163cf7555c5517cb652 Mon Sep 17 00:00:00 2001 From: Mahyar Koshkouei Date: Sat, 23 Dec 2023 15:26:04 +0000 Subject: [PATCH 8/8] core: modify Sameboy statement Signed-off-by: Mahyar Koshkouei --- peanut_gb.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/peanut_gb.h b/peanut_gb.h index 2629fcd..9cfc6ed 100644 --- a/peanut_gb.h +++ b/peanut_gb.h @@ -21,7 +21,7 @@ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS * IN THE SOFTWARE. * - * Please note that at least three parts of source code within this project was + * Please note that at least two parts of source code within this project was * taken from the SameBoy project at https://github.com/LIJI32/SameBoy/ which at * the time of this writing is released under the MIT License. Occurrences of * this code is marked as being taken from SameBoy with a comment.