From 78cd99af328fec1438f8e90b162c34c75f100d80 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Thu, 7 Apr 2022 00:57:52 -0500 Subject: [PATCH] update ymfm --- src/engine/platform/sound/ymfm/ymfm_fm.h | 3 ++- src/engine/platform/sound/ymfm/ymfm_fm.ipp | 19 ++++++++++++++----- src/engine/platform/sound/ymfm/ymfm_opm.cpp | 1 + src/engine/platform/sound/ymfm/ymfm_opn.cpp | 8 ++++---- src/engine/platform/sound/ymfm/ymfm_opn.h | 2 +- 5 files changed, 22 insertions(+), 11 deletions(-) diff --git a/src/engine/platform/sound/ymfm/ymfm_fm.h b/src/engine/platform/sound/ymfm/ymfm_fm.h index 01cb22e7..3239880e 100644 --- a/src/engine/platform/sound/ymfm/ymfm_fm.h +++ b/src/engine/platform/sound/ymfm/ymfm_fm.h @@ -426,7 +426,7 @@ protected: void assign_operators(); // update the state of the given timer - void update_timer(uint32_t which, uint32_t enable); + void update_timer(uint32_t which, uint32_t enable, int32_t delta_clocks); // internal state ymfm_interface &m_intf; // reference to the system interface @@ -436,6 +436,7 @@ protected: uint8_t m_irq_mask; // mask of which bits signal IRQs uint8_t m_irq_state; // current IRQ state uint8_t m_timer_running[2]; // current timer running state + uint8_t m_total_clocks; // low 8 bits of the total number of clocks processed uint32_t m_active_channels; // mask of active channels (computed by prepare) uint32_t m_modified_channels; // mask of channels that have been modified uint32_t m_prepare_count; // counter to do periodic prepare sweeps diff --git a/src/engine/platform/sound/ymfm/ymfm_fm.ipp b/src/engine/platform/sound/ymfm/ymfm_fm.ipp index 41056945..84948aed 100644 --- a/src/engine/platform/sound/ymfm/ymfm_fm.ipp +++ b/src/engine/platform/sound/ymfm/ymfm_fm.ipp @@ -1236,6 +1236,7 @@ void fm_engine_base::save_restore(ymfm_saved_state &state) state.save_restore(m_irq_state); state.save_restore(m_timer_running[0]); state.save_restore(m_timer_running[1]); + state.save_restore(m_total_clocks); // save the register/family data m_regs.save_restore(state); @@ -1261,6 +1262,9 @@ void fm_engine_base::save_restore(ymfm_saved_state &state) template uint32_t fm_engine_base::clock(uint32_t chanmask) { + // update the clock counter + m_total_clocks++; + // if something was modified, prepare // also prepare every 4k samples to catch ending notes if (m_modified_channels != 0 || m_prepare_count++ >= 4096) @@ -1455,7 +1459,7 @@ void fm_engine_base::assign_operators() //------------------------------------------------- template -void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable) +void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable, int32_t delta_clocks) { // if the timer is live, but not currently enabled, set the timer if (enable && !m_timer_running[tnum]) @@ -1463,6 +1467,9 @@ void fm_engine_base::update_timer(uint32_t tnum, uint32_t enable) // period comes from the registers, and is different for each uint32_t period = (tnum == 0) ? (1024 - m_regs.timer_a_value()) : 16 * (256 - m_regs.timer_b_value()); + // caller can also specify a delta to account for other effects + period += delta_clocks; + // reset it m_intf.ymfm_set_timer(tnum, period * OPERATORS * m_clock_prescale); m_timer_running[tnum] = 1; @@ -1499,7 +1506,7 @@ void fm_engine_base::engine_timer_expired(uint32_t tnum) // reset m_timer_running[tnum] = false; - update_timer(tnum, 1); + update_timer(tnum, 1, 0); } @@ -1557,9 +1564,11 @@ void fm_engine_base::engine_mode_write(uint8_t data) reset_mask |= RegisterType::STATUS_TIMERA; set_reset_status(0, reset_mask); - // load timers - update_timer(1, m_regs.load_timer_b()); - update_timer(0, m_regs.load_timer_a()); + // load timers; note that timer B gets a small negative adjustment because + // the *16 multiplier is free-running, so the first tick of the clock + // is a bit shorter + update_timer(1, m_regs.load_timer_b(), -(m_total_clocks & 15)); + update_timer(0, m_regs.load_timer_a(), 0); } } diff --git a/src/engine/platform/sound/ymfm/ymfm_opm.cpp b/src/engine/platform/sound/ymfm/ymfm_opm.cpp index 9fd447e8..544bbe89 100644 --- a/src/engine/platform/sound/ymfm/ymfm_opm.cpp +++ b/src/engine/platform/sound/ymfm/ymfm_opm.cpp @@ -74,6 +74,7 @@ opm_registers::opm_registers() : m_lfo_waveform[2][index] = am | (pm << 8); // waveform 3 is noise; it is filled in dynamically + m_lfo_waveform[3][index] = 0; } } diff --git a/src/engine/platform/sound/ymfm/ymfm_opn.cpp b/src/engine/platform/sound/ymfm/ymfm_opn.cpp index 4a334a63..00ac2cf6 100644 --- a/src/engine/platform/sound/ymfm/ymfm_opn.cpp +++ b/src/engine/platform/sound/ymfm/ymfm_opn.cpp @@ -2398,8 +2398,8 @@ void ym2612::generate(output_data *output, uint32_t numsamples) // a better sound mixer than we usually have, so just average over the six // channels; also apply a 64/65 factor to account for the discontinuity // adjustment above - output->data[0] = (output->data[0] << 7) * 64 / (6 * 65); - output->data[1] = (output->data[1] << 7) * 64 / (6 * 65); + output->data[0] = (output->data[0] * 128) * 64 / (6 * 65); + output->data[1] = (output->data[1] * 128) * 64 / (6 * 65); } } @@ -2432,8 +2432,8 @@ void ym3438::generate(output_data *output, uint32_t numsamples) // YM3438 doesn't have the same DAC discontinuity, though its output is // multiplexed like the YM2612 - output->data[0] = (output->data[0] << 7) / 6; - output->data[1] = (output->data[1] << 7) / 6; + output->data[0] = (output->data[0] * 128) / 6; + output->data[1] = (output->data[1] * 128) / 6; } } diff --git a/src/engine/platform/sound/ymfm/ymfm_opn.h b/src/engine/platform/sound/ymfm/ymfm_opn.h index 8d9b42de..f4136c73 100644 --- a/src/engine/platform/sound/ymfm/ymfm_opn.h +++ b/src/engine/platform/sound/ymfm/ymfm_opn.h @@ -763,7 +763,7 @@ public: protected: // simulate the DAC discontinuity - int32_t dac_discontinuity(int32_t value) const { return (value < 0) ? (value - 2) : (value + 3); } + constexpr int32_t dac_discontinuity(int32_t value) const { return (value < 0) ? (value - 2) : (value + 3); } // internal state uint16_t m_address; // address register