mirror of
https://github.com/holub/mame
synced 2025-04-21 07:52:35 +03:00
gb.cpp: Improved MBC3 RTC handling. (#9035)
This commit is contained in:
parent
1e32a43b50
commit
76152ba35e
@ -4,8 +4,8 @@
|
||||
|
||||
Game Boy carts with MBC (Memory Bank Controller)
|
||||
|
||||
|
||||
TODO: RTC runs too fast while in-game, in MBC-3 games... find the problem!
|
||||
TODO:
|
||||
- The MBC3 RTC should count the time that passed since the game was last played.
|
||||
|
||||
***********************************************************************************************************/
|
||||
|
||||
@ -189,12 +189,26 @@ void gb_rom_mbc3_device::device_start()
|
||||
shared_start();
|
||||
save_item(NAME(m_rtc_regs));
|
||||
save_item(NAME(m_rtc_ready));
|
||||
save_item(NAME(m_rtc_ticks));
|
||||
save_item(NAME(m_latched_regs));
|
||||
|
||||
m_rtc_ticks = 0;
|
||||
system_time curtime;
|
||||
machine().current_datetime(curtime);
|
||||
|
||||
m_rtc_regs[REG_SECONDS] = curtime.local_time.second;
|
||||
m_rtc_regs[REG_MINUTES] = curtime.local_time.minute;
|
||||
m_rtc_regs[REG_HOURS] = curtime.local_time.hour;
|
||||
m_rtc_regs[REG_DAYS] = curtime.local_time.day & 0xff;
|
||||
m_rtc_regs[REG_CONTROL] = (curtime.local_time.day >> 8) & 0x01;
|
||||
|
||||
m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(gb_rom_mbc3_device::rtc_tick),this));
|
||||
m_rtc_timer->adjust(attotime::from_hz(RTC_FREQUENCY), 0, attotime::from_hz(RTC_FREQUENCY));
|
||||
}
|
||||
|
||||
void gb_rom_mbc3_device::device_reset()
|
||||
{
|
||||
shared_reset();
|
||||
memset(m_rtc_regs, 0, sizeof(m_rtc_regs));
|
||||
m_rtc_ready = 0;
|
||||
}
|
||||
|
||||
@ -468,16 +482,39 @@ void gb_rom_mbc2_device::write_ram(offs_t offset, uint8_t data)
|
||||
|
||||
// MBC3
|
||||
|
||||
void gb_rom_mbc3_device::update_rtc()
|
||||
TIMER_CALLBACK_MEMBER(gb_rom_mbc3_device::rtc_tick)
|
||||
{
|
||||
system_time curtime;
|
||||
machine().current_datetime(curtime);
|
||||
|
||||
m_rtc_regs[0] = curtime.local_time.second;
|
||||
m_rtc_regs[1] = curtime.local_time.minute;
|
||||
m_rtc_regs[2] = curtime.local_time.hour;
|
||||
m_rtc_regs[3] = curtime.local_time.day & 0xff;
|
||||
m_rtc_regs[4] = (m_rtc_regs[4] & 0xf0) | (curtime.local_time.day >> 8);
|
||||
if (BIT(m_rtc_regs[REG_CONTROL], 6)) {
|
||||
return;
|
||||
}
|
||||
m_rtc_ticks++;
|
||||
if (m_rtc_ticks >= RTC_FREQUENCY)
|
||||
{
|
||||
m_rtc_ticks = 0;
|
||||
m_rtc_regs[REG_SECONDS] = (m_rtc_regs[REG_SECONDS] + 1) & 0x3f;
|
||||
if (m_rtc_regs[REG_SECONDS] == 60)
|
||||
{
|
||||
m_rtc_regs[REG_SECONDS] = 0;
|
||||
m_rtc_regs[REG_MINUTES] = (m_rtc_regs[REG_MINUTES] + 1) & 0x3f;
|
||||
if (m_rtc_regs[REG_MINUTES] == 60)
|
||||
{
|
||||
m_rtc_regs[REG_MINUTES] -= 60;
|
||||
m_rtc_regs[REG_HOURS] = (m_rtc_regs[REG_HOURS] + 1) & 0x1f;
|
||||
if (m_rtc_regs[REG_HOURS] == 24)
|
||||
{
|
||||
m_rtc_regs[REG_HOURS] = 0;
|
||||
m_rtc_regs[REG_DAYS]++;
|
||||
if (m_rtc_regs[REG_DAYS] == 0)
|
||||
{
|
||||
m_rtc_regs[REG_CONTROL] = (m_rtc_regs[REG_CONTROL] & 0xfe) | ((m_rtc_regs[REG_CONTROL] + 1) & 0x01);
|
||||
if (!(m_rtc_regs[REG_CONTROL] & 0x01)) {
|
||||
m_rtc_regs[REG_CONTROL] |= RTC_CARRY;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gb_rom_mbc3_device::read_rom(offs_t offset)
|
||||
@ -512,42 +549,66 @@ void gb_rom_mbc3_device::write_bank(offs_t offset, uint8_t data)
|
||||
m_rtc_ready = 0;
|
||||
if (m_rtc_ready == 0 && data == 1)
|
||||
{
|
||||
m_latched_regs[REG_SECONDS] = m_rtc_regs[REG_SECONDS];
|
||||
m_latched_regs[REG_MINUTES] = m_rtc_regs[REG_MINUTES];
|
||||
m_latched_regs[REG_HOURS] = m_rtc_regs[REG_HOURS];
|
||||
m_latched_regs[REG_DAYS] = m_rtc_regs[REG_DAYS];
|
||||
m_latched_regs[REG_CONTROL] = m_rtc_regs[REG_CONTROL];
|
||||
m_rtc_ready = 1;
|
||||
update_rtc();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t gb_rom_mbc3_device::read_ram(offs_t offset)
|
||||
{
|
||||
if (m_ram_bank < 4 && m_ram_enable)
|
||||
if (m_ram_enable)
|
||||
{
|
||||
// RAM
|
||||
if (!m_ram.empty())
|
||||
if (m_ram_bank < 4 && !m_ram.empty())
|
||||
{
|
||||
// RAM
|
||||
return m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)];
|
||||
}
|
||||
if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc)
|
||||
{
|
||||
// RTC registers
|
||||
if (has_timer)
|
||||
return m_rtc_regs[m_ram_bank - 8];
|
||||
}
|
||||
else if (m_ram_bank >= 0x08 && m_ram_bank <= 0x0c && has_timer)
|
||||
{
|
||||
// RTC registers
|
||||
return m_latched_regs[m_ram_bank - 8];
|
||||
}
|
||||
}
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
void gb_rom_mbc3_device::write_ram(offs_t offset, uint8_t data)
|
||||
{
|
||||
if (m_ram_bank < 4 && m_ram_enable)
|
||||
if (m_ram_enable)
|
||||
{
|
||||
// RAM
|
||||
if (!m_ram.empty())
|
||||
if (m_ram_bank < 4 && !m_ram.empty())
|
||||
{
|
||||
// RAM
|
||||
m_ram[ram_bank_map[m_ram_bank] * 0x2000 + (offset & 0x1fff)] = data;
|
||||
}
|
||||
if (m_ram_bank >= 0x8 && m_ram_bank <= 0xc && m_ram_enable)
|
||||
{
|
||||
// RTC registers are writeable too
|
||||
if (has_timer)
|
||||
m_rtc_regs[m_ram_bank - 8] = data;
|
||||
}
|
||||
else if (m_ram_bank >= 0x08 && m_ram_bank <= 0x0c && has_timer)
|
||||
{
|
||||
// RTC registers are writeable too
|
||||
uint8_t reg = m_ram_bank - 8;
|
||||
switch(reg)
|
||||
{
|
||||
case REG_SECONDS:
|
||||
case REG_MINUTES:
|
||||
data &= 0x3f;
|
||||
break;
|
||||
case REG_HOURS:
|
||||
data &= 0x1f;
|
||||
break;
|
||||
case REG_CONTROL:
|
||||
data &= 0xc1;
|
||||
break;
|
||||
}
|
||||
m_rtc_regs[reg] = data;
|
||||
if (reg == REG_SECONDS)
|
||||
{
|
||||
m_rtc_ticks = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -100,9 +100,23 @@ protected:
|
||||
virtual void device_reset() override;
|
||||
|
||||
private:
|
||||
void update_rtc();
|
||||
static constexpr uint32_t RTC_FREQUENCY = 32'768;
|
||||
static constexpr uint8_t RTC_CARRY = 0x80;
|
||||
static constexpr uint8_t RTC_HALT = 0x40;
|
||||
static constexpr uint8_t REG_SECONDS = 0;
|
||||
static constexpr uint8_t REG_MINUTES = 1;
|
||||
static constexpr uint8_t REG_HOURS = 2;
|
||||
static constexpr uint8_t REG_DAYS = 3;
|
||||
static constexpr uint8_t REG_CONTROL = 4;
|
||||
|
||||
|
||||
emu_timer *m_rtc_timer;
|
||||
uint32_t m_rtc_ticks;
|
||||
uint8_t m_rtc_regs[5];
|
||||
uint8_t m_latched_regs[5];
|
||||
int m_rtc_ready;
|
||||
|
||||
TIMER_CALLBACK_MEMBER(rtc_tick);
|
||||
};
|
||||
|
||||
// ======================> gb_rom_mbc5_device
|
||||
|
Loading…
Reference in New Issue
Block a user