From e6320fd823b82c06c032e66266807ade47b8cdba Mon Sep 17 00:00:00 2001 From: Aaron Giles Date: Tue, 2 Mar 2021 17:59:41 -0800 Subject: [PATCH] ymfm: Also explicitly sync writes to the mode register to ensure timer control bits are handled in sync. --- src/devices/sound/ymfm.cpp | 47 ++++++++++++++++++++++++++------------ src/devices/sound/ymfm.h | 3 +++ 2 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/devices/sound/ymfm.cpp b/src/devices/sound/ymfm.cpp index c57986856b3..35fff69c3a0 100644 --- a/src/devices/sound/ymfm.cpp +++ b/src/devices/sound/ymfm.cpp @@ -1388,25 +1388,19 @@ void ymfm_engine_base::output(s32 &lsum, s32 &rsum, u8 rshift, s16 template void ymfm_engine_base::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::synced_mode_w), this), data); + return; + } + // most writes are passive, consumed only when needed 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 - else if (regnum == RegisterType::REG_KEYON) + if (regnum == RegisterType::REG_KEYON) { u8 chnum = m_regs.keyon_channel(); if (chnum < RegisterType::CHANNELS) @@ -1654,6 +1648,29 @@ TIMER_CALLBACK_MEMBER(ymfm_engine_base::check_interrupts) } +//------------------------------------------------- +// synced_mode_w - handle a mode register write +// via timer callback +//------------------------------------------------- + +template +TIMER_CALLBACK_MEMBER(ymfm_engine_base::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 template class ymfm_engine_base; template class ymfm_engine_base; diff --git a/src/devices/sound/ymfm.h b/src/devices/sound/ymfm.h index 8cf7e854f7d..9d5c4197dad 100644 --- a/src/devices/sound/ymfm.h +++ b/src/devices/sound/ymfm.h @@ -790,6 +790,9 @@ private: // check interrupts TIMER_CALLBACK_MEMBER(check_interrupts); + // handle a mode register write + TIMER_CALLBACK_MEMBER(synced_mode_w); + // internal state device_t &m_device; // reference to the owning device u32 m_env_counter; // envelope counter; low 2 bits are sub-counter