ymfm: Also explicitly sync writes to the mode register to ensure timer control bits are handled in sync.

This commit is contained in:
Aaron Giles 2021-03-02 17:59:41 -08:00
parent 9afa0d3db2
commit e6320fd823
2 changed files with 35 additions and 15 deletions

View File

@ -1388,25 +1388,19 @@ void ymfm_engine_base<RegisterType>::output(s32 &lsum, s32 &rsum, u8 rshift, s16
template<class RegisterType> template<class RegisterType>
void ymfm_engine_base<RegisterType>::write(u16 regnum, u8 data) void ymfm_engine_base<RegisterType>::write(u16 regnum, u8 data)
{ {
// special case: writes to the mode register can impact IRQs;
// schedule these writes to ensure ordering with timers
if (regnum == RegisterType::REG_MODE)
{
m_device.machine().scheduler().synchronize(timer_expired_delegate(FUNC(ymfm_engine_base<RegisterType>::synced_mode_w), this), data);
return;
}
// most writes are passive, consumed only when needed // most writes are passive, consumed only when needed
m_regs.write(regnum, data); m_regs.write(regnum, data);
// handle writes to the mode register
if (regnum == RegisterType::REG_MODE)
{
// reset timer status
if (m_regs.reset_timer_b())
set_reset_status(0, STATUS_TIMERB);
if (m_regs.reset_timer_a())
set_reset_status(0, STATUS_TIMERA);
// load timers
update_timer(1, m_regs.load_timer_b());
update_timer(0, m_regs.load_timer_a());
}
// handle writes to the keyon registers // handle writes to the keyon registers
else if (regnum == RegisterType::REG_KEYON) if (regnum == RegisterType::REG_KEYON)
{ {
u8 chnum = m_regs.keyon_channel(); u8 chnum = m_regs.keyon_channel();
if (chnum < RegisterType::CHANNELS) if (chnum < RegisterType::CHANNELS)
@ -1654,6 +1648,29 @@ TIMER_CALLBACK_MEMBER(ymfm_engine_base<RegisterType>::check_interrupts)
} }
//-------------------------------------------------
// synced_mode_w - handle a mode register write
// via timer callback
//-------------------------------------------------
template<class RegisterType>
TIMER_CALLBACK_MEMBER(ymfm_engine_base<RegisterType>::synced_mode_w)
{
// actually write the mode register now
m_regs.write(RegisterType::REG_MODE, param);
// reset timer status
if (m_regs.reset_timer_b())
set_reset_status(0, STATUS_TIMERB);
if (m_regs.reset_timer_a())
set_reset_status(0, STATUS_TIMERA);
// load timers
update_timer(1, m_regs.load_timer_b());
update_timer(0, m_regs.load_timer_a());
}
// Explicit template instantiation // Explicit template instantiation
template class ymfm_engine_base<ymopm_registers>; template class ymfm_engine_base<ymopm_registers>;
template class ymfm_engine_base<ymopn_registers>; template class ymfm_engine_base<ymopn_registers>;

View File

@ -790,6 +790,9 @@ private:
// check interrupts // check interrupts
TIMER_CALLBACK_MEMBER(check_interrupts); TIMER_CALLBACK_MEMBER(check_interrupts);
// handle a mode register write
TIMER_CALLBACK_MEMBER(synced_mode_w);
// internal state // internal state
device_t &m_device; // reference to the owning device device_t &m_device; // reference to the owning device
u32 m_env_counter; // envelope counter; low 2 bits are sub-counter u32 m_env_counter; // envelope counter; low 2 bits are sub-counter