mirror of https://github.com/bsnes-emu/bsnes.git
Support for RTC latching. Fixes #4.
This commit is contained in:
parent
92c2b22735
commit
ee4907949b
|
@ -369,7 +369,7 @@ int GB_save_battery(GB_gameboy_t *gb, const char *path)
|
|||
return EIO;
|
||||
}
|
||||
if (gb->cartridge_type->has_rtc) {
|
||||
if (fwrite(gb->rtc_data, 1, sizeof(gb->rtc_data), f) != sizeof(gb->rtc_data)) {
|
||||
if (fwrite(&gb->rtc_real, 1, sizeof(gb->rtc_real), f) != sizeof(gb->rtc_real)) {
|
||||
fclose(f);
|
||||
return EIO;
|
||||
}
|
||||
|
@ -397,7 +397,7 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path)
|
|||
goto reset_rtc;
|
||||
}
|
||||
|
||||
if (fread(gb->rtc_data, 1, sizeof(gb->rtc_data), f) != sizeof(gb->rtc_data)) {
|
||||
if (fread(&gb->rtc_real, 1, sizeof(gb->rtc_real), f) != sizeof(gb->rtc_real)) {
|
||||
goto reset_rtc;
|
||||
}
|
||||
|
||||
|
@ -418,7 +418,7 @@ void GB_load_battery(GB_gameboy_t *gb, const char *path)
|
|||
goto exit;
|
||||
reset_rtc:
|
||||
gb->last_rtc_second = time(NULL);
|
||||
gb->rtc_high |= 0x80; /* This gives the game a hint that the clock should be reset. */
|
||||
gb->rtc_real.high |= 0x80; /* This gives the game a hint that the clock should be reset. */
|
||||
exit:
|
||||
fclose(f);
|
||||
return;
|
||||
|
|
15
Core/gb.h
15
Core/gb.h
|
@ -306,15 +306,16 @@ typedef struct GB_gameboy_s {
|
|||
GB_SECTION(rtc,
|
||||
union {
|
||||
struct {
|
||||
uint8_t rtc_seconds;
|
||||
uint8_t rtc_minutes;
|
||||
uint8_t rtc_hours;
|
||||
uint8_t rtc_days;
|
||||
uint8_t rtc_high;
|
||||
uint8_t seconds;
|
||||
uint8_t minutes;
|
||||
uint8_t hours;
|
||||
uint8_t days;
|
||||
uint8_t high;
|
||||
};
|
||||
uint8_t rtc_data[5];
|
||||
};
|
||||
uint8_t data[5];
|
||||
} rtc_real, rtc_latched;
|
||||
time_t last_rtc_second;
|
||||
bool rtc_latch;
|
||||
);
|
||||
|
||||
/* Video Display */
|
||||
|
|
|
@ -78,8 +78,8 @@ static uint8_t read_mbc_ram(GB_gameboy_t *gb, uint16_t addr)
|
|||
|
||||
if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) {
|
||||
/* RTC read */
|
||||
gb->rtc_high |= ~0xC1; /* Not all bytes in RTC high are used. */
|
||||
return gb->rtc_data[gb->mbc_ram_bank - 8];
|
||||
gb->rtc_latched.high |= ~0xC1; /* Not all bytes in RTC high are used. */
|
||||
return gb->rtc_latched.data[gb->mbc_ram_bank - 8];
|
||||
}
|
||||
|
||||
if (!gb->mbc_ram) {
|
||||
|
@ -284,7 +284,12 @@ static void write_mbc(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
case 0x0000: case 0x1000: gb->mbc_ram_enable = (value & 0xF) == 0xA; break;
|
||||
case 0x2000: case 0x3000: gb->mbc3.rom_bank = value; break;
|
||||
case 0x4000: case 0x5000: gb->mbc3.ram_bank = value; break;
|
||||
case 0x6000: case 0x7000: /* Todo: Clock latching support */ break;
|
||||
case 0x6000: case 0x7000:
|
||||
if (!gb->rtc_latch && (value & 1)) { /* Todo: verify condition is correct*/
|
||||
memcpy(&gb->rtc_latched, &gb->rtc_real, sizeof(gb->rtc_real));
|
||||
}
|
||||
gb->rtc_latch = value & 1;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case GB_MBC5:
|
||||
|
@ -314,8 +319,7 @@ static void write_mbc_ram(GB_gameboy_t *gb, uint16_t addr, uint8_t value)
|
|||
|
||||
if (gb->cartridge_type->has_rtc && gb->mbc_ram_bank >= 8 && gb->mbc_ram_bank <= 0xC) {
|
||||
/* RTC read */
|
||||
gb->rtc_data[gb->mbc_ram_bank - 8] = value;
|
||||
gb->rtc_high |= ~0xC1; /* Not all bytes in RTC high are used. */
|
||||
gb->rtc_latched.data[gb->mbc_ram_bank - 8] = gb->rtc_real.data[gb->mbc_ram_bank - 8] = value; /* Todo: does it really write both? */
|
||||
}
|
||||
|
||||
if (gb->cartridge_type->mbc_type == GB_MBC2) {
|
||||
|
|
|
@ -114,26 +114,26 @@ void GB_emulate_timer_glitch(GB_gameboy_t *gb, uint8_t old_tac, uint8_t new_tac)
|
|||
|
||||
void GB_rtc_run(GB_gameboy_t *gb)
|
||||
{
|
||||
if ((gb->rtc_high & 0x40) == 0) { /* is timer running? */
|
||||
if ((gb->rtc_real.high & 0x40) == 0) { /* is timer running? */
|
||||
time_t current_time = time(NULL);
|
||||
while (gb->last_rtc_second < current_time) {
|
||||
gb->last_rtc_second++;
|
||||
if (++gb->rtc_seconds == 60)
|
||||
if (++gb->rtc_real.seconds == 60)
|
||||
{
|
||||
gb->rtc_seconds = 0;
|
||||
if (++gb->rtc_minutes == 60)
|
||||
gb->rtc_real.seconds = 0;
|
||||
if (++gb->rtc_real.minutes == 60)
|
||||
{
|
||||
gb->rtc_minutes = 0;
|
||||
if (++gb->rtc_hours == 24)
|
||||
gb->rtc_real.minutes = 0;
|
||||
if (++gb->rtc_real.hours == 24)
|
||||
{
|
||||
gb->rtc_hours = 0;
|
||||
if (++gb->rtc_days == 0)
|
||||
gb->rtc_real.hours = 0;
|
||||
if (++gb->rtc_real.days == 0)
|
||||
{
|
||||
if (gb->rtc_high & 1) /* Bit 8 of days*/
|
||||
if (gb->rtc_real.high & 1) /* Bit 8 of days*/
|
||||
{
|
||||
gb->rtc_high |= 0x80; /* Overflow bit */
|
||||
gb->rtc_real.high |= 0x80; /* Overflow bit */
|
||||
}
|
||||
gb->rtc_high ^= 1;
|
||||
gb->rtc_real.high ^= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue