diff options
Diffstat (limited to 'src/devices/sound/ymf278b.h')
-rw-r--r-- | src/devices/sound/ymf278b.h | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/src/devices/sound/ymf278b.h b/src/devices/sound/ymf278b.h index b98b35bfe49..07812279283 100644 --- a/src/devices/sound/ymf278b.h +++ b/src/devices/sound/ymf278b.h @@ -5,23 +5,23 @@ #pragma once +#include "ymfm/src/ymfm_opl.h" #include "dirom.h" -#include "sound/ymfm.h" -class ymf278b_device : public device_t, public device_sound_interface, public device_rom_interface<22> +class ymf278b_device : public device_t, public device_sound_interface, public device_rom_interface<22>, public ymfm::ymfm_interface { public: static constexpr u8 STATUS_BUSY = 0x01; static constexpr u8 STATUS_LD = 0x02; // YMF278B is OPL4 - using fm_engine = ymopl4_engine; + using fm_engine = ymfm::fm_engine_base<ymfm::opl4_registers>; // constructor ymf278b_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); // configuration helpers - auto irq_handler() { return m_fm.irq_handler(); } + auto irq_handler() { return m_update_irq.bind(); } // read/write access u8 read(offs_t offset); @@ -32,6 +32,8 @@ protected: virtual void device_start() override; virtual void device_reset() override; virtual void device_clock_changed() override; + virtual void device_pre_save() override; + virtual void device_post_load() override; virtual void device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) override; @@ -42,6 +44,11 @@ protected: virtual void rom_bank_updated() override; private: + // timer callbacks + void fm_timer_handler(void *ptr, int param) { m_engine->engine_timer_expired(param); } + void fm_mode_write(void *ptr, int param) { m_engine->engine_mode_write(param); } + void fm_check_interrupts(void *ptr, int param) { m_engine->engine_check_interrupts(); } + struct YMF278BSlot { int16_t wave; /* wavetable number */ @@ -125,8 +132,59 @@ private: sound_stream * m_stream; std::vector<int32_t> m_mix_buffer; - // ymf262 + // ymfm OPL4 -- cribbed from ymfm_device_base_common until we figure out how to + // make a proper chip out of this hybrid fm_engine m_fm; + attotime m_busy_end; // busy end time + emu_timer *m_timer[2]; // two timers + devcb_write_line m_update_irq; // IRQ update callback + std::vector<uint8_t> m_save_blob;// save state blob for FM + + // perform a synchronized write + virtual void ymfm_sync_mode_write(uint8_t data) override + { + machine().scheduler().synchronize(timer_expired_delegate(FUNC(ymf278b_device::fm_mode_write), this), data); + } + + // perform a synchronized interrupt check + virtual void ymfm_sync_check_interrupts() override + { + // if we're currently executing a CPU, schedule the interrupt check; + // otherwise, do it directly + auto &scheduler = machine().scheduler(); + if (scheduler.currently_executing()) + scheduler.synchronize(timer_expired_delegate(FUNC(ymf278b_device::fm_check_interrupts), this)); + else + m_engine->engine_check_interrupts(); + } + + // set a timer + virtual void ymfm_set_timer(uint32_t tnum, int32_t duration_in_clocks) override + { + if (duration_in_clocks >= 0) + m_timer[tnum]->adjust(attotime::from_ticks(duration_in_clocks, device_t::clock()), tnum); + else + m_timer[tnum]->enable(false); + } + + // set the time when busy will be clear + virtual void ymfm_set_busy_end(uint32_t clocks) override + { + m_busy_end = machine().time() + attotime::from_ticks(clocks, device_t::clock()); + } + + // are we past the busy clear time? + virtual bool ymfm_is_busy() override + { + return (machine().time() < m_busy_end); + } + + // handle IRQ signaling + virtual void ymfm_update_irq(bool asserted) override + { + if (!m_update_irq.isnull()) + m_update_irq(asserted ? ASSERT_LINE : CLEAR_LINE); + } }; DECLARE_DEVICE_TYPE(YMF278B, ymf278b_device) |