summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2021-03-02 01:32:54 -0800
committer Aaron Giles <aaron@aarongiles.com>2021-03-02 01:32:54 -0800
commitc89cbcd0e599d7baca6d294e451fcd4249b4a74e (patch)
treebc120ef39a1ea6c154eec670d5ef46bdc54eb48e
parente35f24a48772987d5a3c9d28e44f7aa245d3e070 (diff)
Fix YM synchronization in Seibu sound device.
-rw-r--r--src/devices/sound/ymfm.cpp11
-rw-r--r--src/devices/sound/ymfm.h1
-rw-r--r--src/mame/audio/seibu.cpp7
-rw-r--r--src/mame/audio/seibu.h1
4 files changed, 19 insertions, 1 deletions
diff --git a/src/devices/sound/ymfm.cpp b/src/devices/sound/ymfm.cpp
index 55282f3c18b..4c4cc14ac48 100644
--- a/src/devices/sound/ymfm.cpp
+++ b/src/devices/sound/ymfm.cpp
@@ -1261,6 +1261,7 @@ ymfm_engine_base<RegisterType>::ymfm_engine_base(device_t &device) :
m_irq_mask(STATUS_TIMERA | STATUS_TIMERB),
m_irq_state(0),
m_busy_end(attotime::zero),
+ m_last_irq_update(attotime::zero),
m_timer{ nullptr, nullptr },
m_irq_handler(device),
m_regdata(RegisterType::REGISTERS),
@@ -1632,7 +1633,17 @@ void ymfm_engine_base<RegisterType>::check_interrupts()
// if changed, signal the new state
if (old_state != m_irq_state && !m_irq_handler.isnull())
+ {
+ // if writes to registers aren't synchronized, it is possible to induce
+ // scheduling errors handling IRQs; ensure that all IRQ handler updates
+ // are monotonically increasing in time
+ attotime curtime = m_device.machine().time();
+ if (m_last_irq_update > curtime)
+ fatalerror("IRQ signalling time went backwards; writes need to be synchronized");
+ m_last_irq_update = curtime;
+
m_irq_handler(m_irq_state ? ASSERT_LINE : CLEAR_LINE);
+ }
}
diff --git a/src/devices/sound/ymfm.h b/src/devices/sound/ymfm.h
index be9959a2ef5..18c0afa3d35 100644
--- a/src/devices/sound/ymfm.h
+++ b/src/devices/sound/ymfm.h
@@ -799,6 +799,7 @@ private:
u8 m_irq_mask; // mask of which bits signal IRQs
u8 m_irq_state; // current IRQ state
attotime m_busy_end; // end of the busy time
+ attotime m_last_irq_update; // time of last IRQ update
emu_timer *m_timer[2]; // our two timers
devcb_write_line m_irq_handler; // IRQ callback
std::unique_ptr<ymfm_channel<RegisterType>> m_channel[RegisterType::CHANNELS]; // channel pointers
diff --git a/src/mame/audio/seibu.cpp b/src/mame/audio/seibu.cpp
index ad865aa5d90..96bdd5e705b 100644
--- a/src/mame/audio/seibu.cpp
+++ b/src/mame/audio/seibu.cpp
@@ -196,9 +196,14 @@ u8 seibu_sound_device::ym_r(offs_t offset)
return m_ym_read_cb(offset);
}
+TIMER_CALLBACK_MEMBER(seibu_sound_device::ym_w_synced)
+{
+ m_ym_write_cb(param >> 8, param & 0xff);
+}
+
void seibu_sound_device::ym_w(offs_t offset, u8 data)
{
- m_ym_write_cb(offset, data);
+ machine().scheduler().synchronize(timer_expired_delegate(FUNC(seibu_sound_device::ym_w_synced), this), data | (offset << 8));
}
void seibu_sound_device::bank_w(u8 data)
diff --git a/src/mame/audio/seibu.h b/src/mame/audio/seibu.h
index 1763efb040c..d8da4b6f9d0 100644
--- a/src/mame/audio/seibu.h
+++ b/src/mame/audio/seibu.h
@@ -80,6 +80,7 @@ protected:
private:
void update_irq_lines(int param);
TIMER_CALLBACK_MEMBER(update_irq_synced);
+ TIMER_CALLBACK_MEMBER(ym_w_synced);
// device callbacks
devcb_write_line m_int_cb;