summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commite6320fd823b82c06c032e66266807ade47b8cdba (patch)
treeb772c44747d32933b05e7f7c2ba399f25db7abd7
parent9afa0d3db28207bca85749626f44386b755831c6 (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.cpp45
-rw-r--r--src/devices/sound/ymfm.h3
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