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:
OBattler
2022-07-26 06:20:57 +02:00
parent f2e00a5a30
commit 1261f1cedb
3 changed files with 27 additions and 7 deletions

View File

@@ -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];

View File

@@ -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
//

View File

@@ -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);
}
}