Some patches to YMFM for OPL3 to correctly instantly begin counting on control register write instead of only after a period.
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include "ymfm/ymfm_opl.h"
|
||||
|
||||
extern "C" {
|
||||
#include <86box/86box.h>
|
||||
#include <86box/timer.h>
|
||||
#include <86box/device.h>
|
||||
#include <86box/sound.h>
|
||||
@@ -81,6 +82,9 @@ public:
|
||||
memset(m_oldsamples, 0, sizeof(m_oldsamples));
|
||||
m_rateratio = (samplerate << RSM_FRAC) / m_chip.sample_rate(m_clock);
|
||||
m_clock_us = 1000000 / (double) m_clock;
|
||||
m_subtract[0] = 80.0;
|
||||
m_subtract[1] = 320.0;
|
||||
m_type = type;
|
||||
|
||||
timer_add(&m_timers[0], YMFMChip::timer1, this, 0);
|
||||
timer_add(&m_timers[1], YMFMChip::timer2, this, 0);
|
||||
@@ -97,11 +101,14 @@ public:
|
||||
return;
|
||||
|
||||
pc_timer_t *timer = &m_timers[tnum];
|
||||
if (duration_in_clocks < 0) {
|
||||
if (duration_in_clocks < 0)
|
||||
timer_stop(timer);
|
||||
} else {
|
||||
else {
|
||||
double period = m_clock_us * duration_in_clocks;
|
||||
timer_on_auto(timer, period);
|
||||
if (period < m_subtract[tnum])
|
||||
m_engine->engine_timer_expired(tnum);
|
||||
else
|
||||
timer_on_auto(timer, period);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,6 +179,11 @@ virtual void generate_resampled(int32_t *data, uint32_t num_samples) override
|
||||
return m_chip.read(addr);
|
||||
}
|
||||
|
||||
virtual uint32_t get_special_flags(void) override
|
||||
{
|
||||
return ((m_type == FM_YMF262) || (m_type == FM_YMF289B)) ? 0x8000 : 0x0000;
|
||||
}
|
||||
|
||||
static void timer1(void *priv)
|
||||
{
|
||||
YMFMChip<ChipType> *drv = (YMFMChip<ChipType> *) priv;
|
||||
@@ -187,7 +199,7 @@ virtual void generate_resampled(int32_t *data, uint32_t num_samples) override
|
||||
private:
|
||||
ChipType m_chip;
|
||||
uint32_t m_clock;
|
||||
double m_clock_us;
|
||||
double m_clock_us, m_subtract[2];
|
||||
typename ChipType::output_data m_output;
|
||||
pc_timer_t m_timers[2];
|
||||
|
||||
|
@@ -543,6 +543,8 @@ public:
|
||||
// noted busy end time and return true if we haven't yet passed it
|
||||
virtual bool ymfm_is_busy() { return false; }
|
||||
|
||||
virtual uint32_t get_special_flags(void) { return 0x0000; }
|
||||
|
||||
//
|
||||
// I/O functions
|
||||
//
|
||||
|
@@ -1472,11 +1472,14 @@ void fm_engine_base<RegisterType>::assign_operators()
|
||||
template<class RegisterType>
|
||||
void fm_engine_base<RegisterType>::update_timer(uint32_t tnum, uint32_t enable, int32_t delta_clocks)
|
||||
{
|
||||
uint32_t subtract = !!(tnum >> 15);
|
||||
tnum &= 0x7fff;
|
||||
|
||||
// if the timer is live, but not currently enabled, set the timer
|
||||
if (enable && !m_timer_running[tnum])
|
||||
{
|
||||
// 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());
|
||||
uint32_t period = (tnum == 0) ? (1024 - subtract - m_regs.timer_a_value()) : 16 * (256 - subtract - m_regs.timer_b_value());
|
||||
|
||||
// caller can also specify a delta to account for other effects
|
||||
period += delta_clocks;
|
||||
@@ -1581,8 +1584,11 @@ void fm_engine_base<RegisterType>::engine_mode_write(uint8_t data)
|
||||
// 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);
|
||||
// OPL3 begins counting immediately instead of after the first period is over.
|
||||
// We use bit 15 of the timer number on those chips to inform that this was a
|
||||
// control register write, and to therefore, subtract 1 counting cycle.
|
||||
update_timer(1 | m_intf.get_special_flags(), m_regs.load_timer_b(), -(m_total_clocks & 15));
|
||||
update_timer(0 | m_intf.get_special_flags(), m_regs.load_timer_a(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user