diff --git a/3rdparty/ymfm/src/ymfm_fm.h b/3rdparty/ymfm/src/ymfm_fm.h index 01cb22e77b8..3239880e563 100644 --- a/3rdparty/ymfm/src/ymfm_fm.h +++ b/3rdparty/ymfm/src/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/3rdparty/ymfm/src/ymfm_fm.ipp b/3rdparty/ymfm/src/ymfm_fm.ipp index ab5fc064e30..917a2ace870 100644 --- a/3rdparty/ymfm/src/ymfm_fm.ipp +++ b/3rdparty/ymfm/src/ymfm_fm.ipp @@ -1227,6 +1227,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); @@ -1252,6 +1253,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) @@ -1428,7 +1432,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]) @@ -1436,6 +1440,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; @@ -1472,7 +1479,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); } @@ -1530,9 +1537,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); } }