diff options
author | Aaron Giles <aaron@aarongiles.com> | 2021-03-02 17:59:41 -0800 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2021-03-02 17:59:41 -0800 |
commit | e6320fd823b82c06c032e66266807ade47b8cdba (patch) | |
tree | b772c44747d32933b05e7f7c2ba399f25db7abd7 | |
parent | 9afa0d3db28207bca85749626f44386b755831c6 (diff) |
ymfm: Also explicitly sync writes to the mode register to ensure timer control bits are handled in sync.
-rw-r--r-- | src/devices/sound/ymfm.cpp | 45 | ||||
-rw-r--r-- | src/devices/sound/ymfm.h | 3 |
2 files changed, 34 insertions, 14 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<RegisterType>::output(s32 &lsum, s32 &rsum, u8 rshift, s16 template<class RegisterType> void ymfm_engine_base<RegisterType>::write(u16 regnum, u8 data) { - // most writes are passive, consumed only when needed - m_regs.write(regnum, data); - - // handle writes to the mode register + // special case: writes to the mode register can impact IRQs; + // schedule these writes to ensure ordering with timers 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()); + 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 + m_regs.write(regnum, data); + // 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<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 template class ymfm_engine_base<ymopm_registers>; template class ymfm_engine_base<ymopn_registers>; 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 |