summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/sound/ymf278b.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/sound/ymf278b.h')
-rw-r--r--src/devices/sound/ymf278b.h68
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)