mirror of
https://github.com/holub/mame
synced 2025-04-17 22:13:04 +03:00
3rdparty/ymfm: sync to latest (#13263)
This commit is contained in:
parent
7de0190232
commit
5e41c0e195
21
3rdparty/ymfm/src/ymfm.h
vendored
21
3rdparty/ymfm/src/ymfm.h
vendored
@ -42,6 +42,7 @@
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -109,17 +110,6 @@ inline int32_t clamp(int32_t value, int32_t minval, int32_t maxval)
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// array_size - return the size of an array
|
||||
//-------------------------------------------------
|
||||
|
||||
template<typename ArrayType, int ArraySize>
|
||||
constexpr uint32_t array_size(ArrayType (&array)[ArraySize])
|
||||
{
|
||||
return ArraySize;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// count_leading_zeros - return the number of
|
||||
// leading zeros in a 32-bit value; CPU-optimized
|
||||
@ -254,7 +244,8 @@ inline int16_t roundtrip_fp(int32_t value)
|
||||
|
||||
// apply the shift back and forth to zero out bits that are lost
|
||||
exponent -= 1;
|
||||
return (value >> exponent) << exponent;
|
||||
int32_t mask = (1 << exponent) - 1;
|
||||
return value & ~mask;
|
||||
}
|
||||
|
||||
|
||||
@ -350,7 +341,7 @@ public:
|
||||
{
|
||||
// create file
|
||||
char name[20];
|
||||
sprintf(name, "wavlog-%02d.wav", m_index);
|
||||
snprintf(&name[0], sizeof(name), "wavlog-%02d.wav", m_index);
|
||||
FILE *out = fopen(name, "wb");
|
||||
|
||||
// make the wav file header
|
||||
@ -483,6 +474,8 @@ public:
|
||||
class ymfm_engine_callbacks
|
||||
{
|
||||
public:
|
||||
virtual ~ymfm_engine_callbacks() = default;
|
||||
|
||||
// timer callback; called by the interface when a timer fires
|
||||
virtual void engine_timer_expired(uint32_t tnum) = 0;
|
||||
|
||||
@ -504,6 +497,8 @@ class ymfm_interface
|
||||
template<typename RegisterType> friend class fm_engine_base;
|
||||
|
||||
public:
|
||||
virtual ~ymfm_interface() = default;
|
||||
|
||||
// the following functions must be implemented by any derived classes; the
|
||||
// default implementations are sufficient for some minimal operation, but will
|
||||
// likely need to be overridden to integrate with the outside world; they are
|
||||
|
4
3rdparty/ymfm/src/ymfm_fm.h
vendored
4
3rdparty/ymfm/src/ymfm_fm.h
vendored
@ -267,7 +267,7 @@ public:
|
||||
// assign operators
|
||||
void assign(uint32_t index, fm_operator<RegisterType> *op)
|
||||
{
|
||||
assert(index < array_size(m_op));
|
||||
assert(index < m_op.size());
|
||||
m_op[index] = op;
|
||||
if (op != nullptr)
|
||||
op->set_choffs(m_choffs);
|
||||
@ -330,7 +330,7 @@ private:
|
||||
uint32_t m_choffs; // channel offset in registers
|
||||
int16_t m_feedback[2]; // feedback memory for operator 1
|
||||
mutable int16_t m_feedback_in; // next input value for op 1 feedback (set in output)
|
||||
fm_operator<RegisterType> *m_op[4]; // up to 4 operators
|
||||
std::array<fm_operator<RegisterType> *, 4> m_op; // up to 4 operators
|
||||
RegisterType &m_regs; // direct reference to registers
|
||||
fm_engine_base<RegisterType> &m_owner; // reference to the owning engine
|
||||
};
|
||||
|
14
3rdparty/ymfm/src/ymfm_fm.ipp
vendored
14
3rdparty/ymfm/src/ymfm_fm.ipp
vendored
@ -839,12 +839,12 @@ void fm_channel<RegisterType>::save_restore(ymfm_saved_state &state)
|
||||
template<class RegisterType>
|
||||
void fm_channel<RegisterType>::keyonoff(uint32_t states, keyon_type type, uint32_t chnum)
|
||||
{
|
||||
for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++)
|
||||
for (uint32_t opnum = 0; opnum < m_op.size(); opnum++)
|
||||
if (m_op[opnum] != nullptr)
|
||||
m_op[opnum]->keyonoff(bitfield(states, opnum), type);
|
||||
|
||||
if (debug::LOG_KEYON_EVENTS && ((debug::GLOBAL_FM_CHANNEL_MASK >> chnum) & 1) != 0)
|
||||
for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++)
|
||||
for (uint32_t opnum = 0; opnum < m_op.size(); opnum++)
|
||||
if (m_op[opnum] != nullptr)
|
||||
debug::log_keyon("%c%s\n", bitfield(states, opnum) ? '+' : '-', m_regs.log_keyon(m_choffs, m_op[opnum]->opoffs()).c_str());
|
||||
}
|
||||
@ -860,7 +860,7 @@ bool fm_channel<RegisterType>::prepare()
|
||||
uint32_t active_mask = 0;
|
||||
|
||||
// prepare all operators and determine if they are active
|
||||
for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++)
|
||||
for (uint32_t opnum = 0; opnum < m_op.size(); opnum++)
|
||||
if (m_op[opnum] != nullptr)
|
||||
if (m_op[opnum]->prepare())
|
||||
active_mask |= 1 << opnum;
|
||||
@ -880,7 +880,7 @@ void fm_channel<RegisterType>::clock(uint32_t env_counter, int32_t lfo_raw_pm)
|
||||
m_feedback[0] = m_feedback[1];
|
||||
m_feedback[1] = m_feedback_in;
|
||||
|
||||
for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++)
|
||||
for (uint32_t opnum = 0; opnum < m_op.size(); opnum++)
|
||||
if (m_op[opnum] != nullptr)
|
||||
m_op[opnum]->clock(env_counter, lfo_raw_pm);
|
||||
|
||||
@ -888,7 +888,7 @@ void fm_channel<RegisterType>::clock(uint32_t env_counter, int32_t lfo_raw_pm)
|
||||
useful temporary code for envelope debugging
|
||||
if (m_choffs == 0x101)
|
||||
{
|
||||
for (uint32_t opnum = 0; opnum < array_size(m_op); opnum++)
|
||||
for (uint32_t opnum = 0; opnum < m_op.size(); opnum++)
|
||||
{
|
||||
auto &op = *m_op[((opnum & 1) << 1) | ((opnum >> 1) & 1)];
|
||||
printf(" %c%03X%c%c ",
|
||||
@ -1504,6 +1504,8 @@ void fm_engine_base<RegisterType>::update_timer(uint32_t tnum, uint32_t enable,
|
||||
template<class RegisterType>
|
||||
void fm_engine_base<RegisterType>::engine_timer_expired(uint32_t tnum)
|
||||
{
|
||||
assert(tnum == 0 || tnum == 1);
|
||||
|
||||
// update status
|
||||
if (tnum == 0 && m_regs.enable_timer_a())
|
||||
set_reset_status(STATUS_TIMERA, 0);
|
||||
@ -1515,7 +1517,7 @@ void fm_engine_base<RegisterType>::engine_timer_expired(uint32_t tnum)
|
||||
for (uint32_t chnum = 0; chnum < CHANNELS; chnum++)
|
||||
if (bitfield(RegisterType::CSM_TRIGGER_MASK, chnum))
|
||||
{
|
||||
m_channel[chnum]->keyonoff(1, KEYON_CSM, chnum);
|
||||
m_channel[chnum]->keyonoff(0xf, KEYON_CSM, chnum);
|
||||
m_modified_channels |= 1 << chnum;
|
||||
}
|
||||
|
||||
|
1
3rdparty/ymfm/src/ymfm_misc.h
vendored
1
3rdparty/ymfm/src/ymfm_misc.h
vendored
@ -90,5 +90,4 @@ protected:
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // YMFM_MISC_H
|
||||
|
44
3rdparty/ymfm/src/ymfm_opl.cpp
vendored
44
3rdparty/ymfm/src/ymfm_opl.cpp
vendored
@ -386,9 +386,9 @@ std::string opl_registers_base<Revision>::log_keyon(uint32_t choffs, uint32_t op
|
||||
uint32_t opnum = (opoffs & 31) - 2 * ((opoffs & 31) / 8) + 18 * bitfield(opoffs, 8);
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%2u.%02u freq=%04X fb=%u alg=%X mul=%X tl=%02X ksr=%u ns=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%2u.%02u freq=%04X fb=%u alg=%X mul=%X tl=%02X ksr=%u ns=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u",
|
||||
chnum, opnum,
|
||||
ch_block_freq(choffs),
|
||||
ch_feedback(choffs),
|
||||
@ -405,25 +405,25 @@ std::string opl_registers_base<Revision>::log_keyon(uint32_t choffs, uint32_t op
|
||||
op_eg_sustain(opoffs));
|
||||
|
||||
if (OUTPUTS > 1)
|
||||
end += sprintf(end, " out=%c%c%c%c",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " out=%c%c%c%c",
|
||||
ch_output_0(choffs) ? 'L' : '-',
|
||||
ch_output_1(choffs) ? 'R' : '-',
|
||||
ch_output_2(choffs) ? '0' : '-',
|
||||
ch_output_3(choffs) ? '1' : '-');
|
||||
if (op_lfo_am_enable(opoffs) != 0)
|
||||
end += sprintf(end, " am=%u", lfo_am_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", lfo_am_depth());
|
||||
if (op_lfo_pm_enable(opoffs) != 0)
|
||||
end += sprintf(end, " pm=%u", lfo_pm_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", lfo_pm_depth());
|
||||
if (waveform_enable() && op_waveform(opoffs) != 0)
|
||||
end += sprintf(end, " wf=%u", op_waveform(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=%u", op_waveform(opoffs));
|
||||
if (is_rhythm(choffs))
|
||||
end += sprintf(end, " rhy=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " rhy=1");
|
||||
if (DYNAMIC_OPS)
|
||||
{
|
||||
operator_mapping map;
|
||||
operator_map(map);
|
||||
if (bitfield(map.chan[chnum], 16, 8) != 0xff)
|
||||
end += sprintf(end, " 4op");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " 4op");
|
||||
}
|
||||
|
||||
return buffer;
|
||||
@ -685,9 +685,9 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
uint32_t opnum = opoffs;
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%u.%02u freq=%04X inst=%X fb=%u mul=%X",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X inst=%X fb=%u mul=%X",
|
||||
chnum, opnum,
|
||||
ch_block_freq(choffs),
|
||||
ch_instrument(choffs),
|
||||
@ -695,11 +695,11 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
op_multiple(opoffs));
|
||||
|
||||
if (bitfield(opoffs, 0) == 1 || (is_rhythm(choffs) && choffs >= 6))
|
||||
end += sprintf(end, " vol=%X", op_volume(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " vol=%X", op_volume(opoffs));
|
||||
else
|
||||
end += sprintf(end, " tl=%02X", ch_total_level(choffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " tl=%02X", ch_total_level(choffs));
|
||||
|
||||
end += sprintf(end, " ksr=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u/%u",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " ksr=%u ksl=%u adr=%X/%X/%X sl=%X sus=%u/%u",
|
||||
op_ksr(opoffs),
|
||||
op_ksl(opoffs),
|
||||
op_attack_rate(opoffs),
|
||||
@ -710,13 +710,13 @@ std::string opll_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
ch_sustain(choffs));
|
||||
|
||||
if (op_lfo_am_enable(opoffs))
|
||||
end += sprintf(end, " am=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=1");
|
||||
if (op_lfo_pm_enable(opoffs))
|
||||
end += sprintf(end, " pm=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=1");
|
||||
if (op_waveform(opoffs) != 0)
|
||||
end += sprintf(end, " wf=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=1");
|
||||
if (is_rhythm(choffs))
|
||||
end += sprintf(end, " rhy=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " rhy=1");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
@ -1715,9 +1715,15 @@ uint8_t ymf278b::read_status()
|
||||
|
||||
uint8_t ymf278b::read_data_pcm()
|
||||
{
|
||||
// write to FM
|
||||
// read from PCM
|
||||
if (bitfield(m_address, 9) != 0)
|
||||
return m_pcm.read(m_address & 0xff);
|
||||
{
|
||||
uint8_t result = m_pcm.read(m_address & 0xff);
|
||||
if ((m_address & 0xff) == 0x02)
|
||||
result |= 0x20;
|
||||
|
||||
return result;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
20
3rdparty/ymfm/src/ymfm_opm.cpp
vendored
20
3rdparty/ymfm/src/ymfm_opm.cpp
vendored
@ -60,17 +60,17 @@ opm_registers::opm_registers() :
|
||||
{
|
||||
// waveform 0 is a sawtooth
|
||||
uint8_t am = index ^ 0xff;
|
||||
int8_t pm = int8_t(index);
|
||||
uint8_t pm = index;
|
||||
m_lfo_waveform[0][index] = am | (pm << 8);
|
||||
|
||||
// waveform 1 is a square wave
|
||||
am = bitfield(index, 7) ? 0 : 0xff;
|
||||
pm = int8_t(am ^ 0x80);
|
||||
pm = am ^ 0x80;
|
||||
m_lfo_waveform[1][index] = am | (pm << 8);
|
||||
|
||||
// waveform 2 is a triangle wave
|
||||
am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1);
|
||||
pm = int8_t(bitfield(index, 6) ? am : ~am);
|
||||
pm = bitfield(index, 6) ? am : ~am;
|
||||
m_lfo_waveform[2][index] = am | (pm << 8);
|
||||
|
||||
// waveform 3 is noise; it is filled in dynamically
|
||||
@ -330,7 +330,7 @@ uint32_t opm_registers::compute_phase_step(uint32_t choffs, uint32_t opoffs, opd
|
||||
if (pm_sensitivity < 6)
|
||||
delta += lfo_raw_pm >> (6 - pm_sensitivity);
|
||||
else
|
||||
delta += lfo_raw_pm << (pm_sensitivity - 5);
|
||||
delta += uint32_t(lfo_raw_pm) << (pm_sensitivity - 5);
|
||||
}
|
||||
|
||||
// apply delta and convert to a frequency number
|
||||
@ -354,9 +354,9 @@ std::string opm_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
uint32_t opnum = opoffs;
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%u.%02u freq=%04X dt2=%u dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt2=%u dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
chnum, opnum,
|
||||
ch_block_freq(choffs),
|
||||
op_detune2(opoffs),
|
||||
@ -376,14 +376,14 @@ std::string opm_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
|
||||
bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0);
|
||||
if (am)
|
||||
end += sprintf(end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth());
|
||||
bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0);
|
||||
if (pm)
|
||||
end += sprintf(end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth());
|
||||
if (am || pm)
|
||||
end += sprintf(end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]);
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]);
|
||||
if (noise_enable() && opoffs == 31)
|
||||
end += sprintf(end, " noise=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " noise=1");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
16
3rdparty/ymfm/src/ymfm_opn.cpp
vendored
16
3rdparty/ymfm/src/ymfm_opn.cpp
vendored
@ -409,9 +409,9 @@ std::string opn_registers_base<IsOpnA>::log_keyon(uint32_t choffs, uint32_t opof
|
||||
}
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%u.%02u freq=%04X dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X",
|
||||
chnum, opnum,
|
||||
block_freq,
|
||||
op_detune(opoffs),
|
||||
@ -427,21 +427,21 @@ std::string opn_registers_base<IsOpnA>::log_keyon(uint32_t choffs, uint32_t opof
|
||||
op_sustain_level(opoffs));
|
||||
|
||||
if (OUTPUTS > 1)
|
||||
end += sprintf(end, " out=%c%c",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " out=%c%c",
|
||||
ch_output_0(choffs) ? 'L' : '-',
|
||||
ch_output_1(choffs) ? 'R' : '-');
|
||||
if (op_ssg_eg_enable(opoffs))
|
||||
end += sprintf(end, " ssg=%X", op_ssg_eg_mode(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " ssg=%X", op_ssg_eg_mode(opoffs));
|
||||
bool am = (op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0);
|
||||
if (am)
|
||||
end += sprintf(end, " am=%u", ch_lfo_am_sens(choffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", ch_lfo_am_sens(choffs));
|
||||
bool pm = (ch_lfo_pm_sens(choffs) != 0);
|
||||
if (pm)
|
||||
end += sprintf(end, " pm=%u", ch_lfo_pm_sens(choffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", ch_lfo_pm_sens(choffs));
|
||||
if (am || pm)
|
||||
end += sprintf(end, " lfo=%02X", lfo_rate());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X", lfo_rate());
|
||||
if (multi_freq() && choffs == 2)
|
||||
end += sprintf(end, " multi=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " multi=1");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
2
3rdparty/ymfm/src/ymfm_opn.h
vendored
2
3rdparty/ymfm/src/ymfm_opn.h
vendored
@ -793,7 +793,7 @@ public:
|
||||
ymf276(ymfm_interface &intf) : ym2612(intf) { }
|
||||
|
||||
// generate one sample of sound
|
||||
void generate(output_data *output, uint32_t numsamples);
|
||||
void generate(output_data *output, uint32_t numsamples = 1);
|
||||
};
|
||||
|
||||
}
|
||||
|
12
3rdparty/ymfm/src/ymfm_opq.cpp
vendored
12
3rdparty/ymfm/src/ymfm_opq.cpp
vendored
@ -339,9 +339,9 @@ std::string opq_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
uint32_t opnum = opoffs;
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%u.%02u freq=%04X dt=%+2d fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u freq=%04X dt=%+2d fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
chnum, opnum,
|
||||
(opoffs & 1) ? ch_block_freq_24(choffs) : ch_block_freq_13(choffs),
|
||||
int32_t(op_detune(opoffs)) - 0x20,
|
||||
@ -360,14 +360,14 @@ std::string opq_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
|
||||
bool am = (lfo_enable() && op_lfo_am_enable(opoffs) && ch_lfo_am_sens(choffs) != 0);
|
||||
if (am)
|
||||
end += sprintf(end, " am=%u", ch_lfo_am_sens(choffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u", ch_lfo_am_sens(choffs));
|
||||
bool pm = (lfo_enable() && ch_lfo_pm_sens(choffs) != 0);
|
||||
if (pm)
|
||||
end += sprintf(end, " pm=%u", ch_lfo_pm_sens(choffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u", ch_lfo_pm_sens(choffs));
|
||||
if (am || pm)
|
||||
end += sprintf(end, " lfo=%02X", lfo_rate());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X", lfo_rate());
|
||||
if (ch_reverb(choffs))
|
||||
end += sprintf(end, " reverb");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " reverb");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
290
3rdparty/ymfm/src/ymfm_opx.h
vendored
Normal file
290
3rdparty/ymfm/src/ymfm_opx.h
vendored
Normal file
@ -0,0 +1,290 @@
|
||||
// BSD 3-Clause License
|
||||
//
|
||||
// Copyright (c) 2021, Aaron Giles
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#ifndef YMFM_OPX_H
|
||||
#define YMFM_OPX_H
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "ymfm.h"
|
||||
#include "ymfm_fm.h"
|
||||
|
||||
namespace ymfm
|
||||
{
|
||||
|
||||
//*********************************************************
|
||||
// REGISTER CLASSES
|
||||
//*********************************************************
|
||||
|
||||
// ======================> opx_registers
|
||||
|
||||
//
|
||||
// OPX register map:
|
||||
//
|
||||
// System-wide registers:
|
||||
//
|
||||
// Per-channel registers (channel in address bits 0-2)
|
||||
//
|
||||
// Per-operator registers (4 banks):
|
||||
// 00-0F x------- Enable
|
||||
// -xxxx--- EXT out
|
||||
// -------x Key on
|
||||
// 10-1F xxxxxxxx LFO frequency
|
||||
// 20-2F xx------ AM sensitivity (0-3)
|
||||
// --xxx--- PM sensitivity (0-7)
|
||||
// ------xx LFO waveform (0=disable, 1=saw, 2=
|
||||
// 30-3F -xxx---- Detune (0-7)
|
||||
// ----xxxx Multiple (0-15)
|
||||
// 40-4F -xxxxxxx Total level (0-127)
|
||||
// 50-5F xxx----- Key scale (0-7)
|
||||
// ---xxxxx Attack rate (0-31)
|
||||
// 60-6F ---xxxxx Decay rate (0-31)
|
||||
// 70-7F ---xxxxx Sustain rate (0-31)
|
||||
// 80-8F xxxx---- Sustain level (0-15)
|
||||
// ----xxxx Release rate (0-15)
|
||||
// 90-9F xxxxxxxx Frequency number (low 8 bits)
|
||||
// A0-AF xxxx---- Block (0-15)
|
||||
// ----xxxx Frequency number (high 4 bits)
|
||||
// B0-BF x------- Acc on
|
||||
// -xxx---- Feedback level (0-7)
|
||||
// -----xxx Waveform (0-7, 7=PCM)
|
||||
// C0-CF ----xxxx Algorithm (0-15)
|
||||
// D0-DF xxxx---- CH0 level (0-15)
|
||||
// ----xxxx CH1 level (0-15)
|
||||
// E0-EF xxxx---- CH2 level (0-15)
|
||||
// ----xxxx CH3 level (0-15)
|
||||
//
|
||||
|
||||
class opx_registers : public fm_registers_base
|
||||
{
|
||||
// LFO waveforms are 256 entries long
|
||||
static constexpr uint32_t LFO_WAVEFORM_LENGTH = 256;
|
||||
|
||||
public:
|
||||
// constants
|
||||
static constexpr uint32_t OUTPUTS = 8;
|
||||
static constexpr uint32_t CHANNELS = 24;
|
||||
static constexpr uint32_t ALL_CHANNELS = (1 << CHANNELS) - 1;
|
||||
static constexpr uint32_t OPERATORS = CHANNELS * 2;
|
||||
static constexpr uint32_t WAVEFORMS = 8;
|
||||
static constexpr uint32_t REGISTERS = 0x800;
|
||||
static constexpr uint32_t DEFAULT_PRESCALE = 8;
|
||||
static constexpr uint32_t EG_CLOCK_DIVIDER = 2;
|
||||
static constexpr uint32_t CSM_TRIGGER_MASK = ALL_CHANNELS;
|
||||
static constexpr uint32_t REG_MODE = 0x14;
|
||||
static constexpr uint8_t STATUS_TIMERA = 0x01;
|
||||
static constexpr uint8_t STATUS_TIMERB = 0x02;
|
||||
static constexpr uint8_t STATUS_BUSY = 0x80;
|
||||
static constexpr uint8_t STATUS_IRQ = 0;
|
||||
|
||||
// constructor
|
||||
opx_registers();
|
||||
|
||||
// reset to initial state
|
||||
void reset();
|
||||
|
||||
// save/restore
|
||||
void save_restore(ymfm_saved_state &state);
|
||||
|
||||
// map channel number to register offset
|
||||
static constexpr uint32_t channel_offset(uint32_t chnum)
|
||||
{
|
||||
assert(chnum < CHANNELS);
|
||||
return chnum;
|
||||
}
|
||||
|
||||
// map operator number to register offset
|
||||
static constexpr uint32_t operator_offset(uint32_t opnum)
|
||||
{
|
||||
assert(opnum < OPERATORS);
|
||||
return opnum;
|
||||
}
|
||||
|
||||
// return an array of operator indices for each channel
|
||||
struct operator_mapping { uint32_t chan[CHANNELS]; };
|
||||
void operator_map(operator_mapping &dest) const;
|
||||
|
||||
// handle writes to the register array
|
||||
bool write(uint16_t index, uint8_t data, uint32_t &chan, uint32_t &opmask);
|
||||
|
||||
// clock the noise and LFO, if present, returning LFO PM value
|
||||
int32_t clock_noise_and_lfo();
|
||||
|
||||
// return the AM offset from LFO for the given channel
|
||||
uint32_t lfo_am_offset(uint32_t choffs) const;
|
||||
|
||||
// return the current noise state, gated by the noise clock
|
||||
uint32_t noise_state() const { return m_noise_state; }
|
||||
|
||||
// caching helpers
|
||||
void cache_operator_data(uint32_t choffs, uint32_t opoffs, opdata_cache &cache);
|
||||
|
||||
// compute the phase step, given a PM value
|
||||
uint32_t compute_phase_step(uint32_t choffs, uint32_t opoffs, opdata_cache const &cache, int32_t lfo_raw_pm);
|
||||
|
||||
// log a key-on event
|
||||
std::string log_keyon(uint32_t choffs, uint32_t opoffs);
|
||||
|
||||
// system-wide registers
|
||||
uint32_t noise_frequency() const { return byte(0x0f, 0, 5); }
|
||||
uint32_t noise_enable() const { return byte(0x0f, 7, 1); }
|
||||
uint32_t timer_a_value() const { return word(0x10, 0, 8, 0x11, 0, 2); }
|
||||
uint32_t timer_b_value() const { return byte(0x12, 0, 8); }
|
||||
uint32_t csm() const { return byte(0x14, 7, 1); }
|
||||
uint32_t reset_timer_b() const { return byte(0x14, 5, 1); }
|
||||
uint32_t reset_timer_a() const { return byte(0x14, 4, 1); }
|
||||
uint32_t enable_timer_b() const { return byte(0x14, 3, 1); }
|
||||
uint32_t enable_timer_a() const { return byte(0x14, 2, 1); }
|
||||
uint32_t load_timer_b() const { return byte(0x14, 1, 1); }
|
||||
uint32_t load_timer_a() const { return byte(0x14, 0, 1); }
|
||||
uint32_t lfo2_pm_depth() const { return byte(0x148, 0, 7); } // fake
|
||||
uint32_t lfo2_rate() const { return byte(0x16, 0, 8); }
|
||||
uint32_t lfo2_am_depth() const { return byte(0x17, 0, 7); }
|
||||
uint32_t lfo_rate() const { return byte(0x18, 0, 8); }
|
||||
uint32_t lfo_am_depth() const { return byte(0x19, 0, 7); }
|
||||
uint32_t lfo_pm_depth() const { return byte(0x149, 0, 7); } // fake
|
||||
uint32_t output_bits() const { return byte(0x1b, 6, 2); }
|
||||
uint32_t lfo2_sync() const { return byte(0x1b, 5, 1); }
|
||||
uint32_t lfo_sync() const { return byte(0x1b, 4, 1); }
|
||||
uint32_t lfo2_waveform() const { return byte(0x1b, 2, 2); }
|
||||
uint32_t lfo_waveform() const { return byte(0x1b, 0, 2); }
|
||||
|
||||
// per-channel registers
|
||||
uint32_t ch_volume(uint32_t choffs) const { return byte(0x00, 0, 8, choffs); }
|
||||
uint32_t ch_output_any(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); }
|
||||
uint32_t ch_output_0(uint32_t choffs) const { return byte(0x30, 0, 1, choffs); }
|
||||
uint32_t ch_output_1(uint32_t choffs) const { return byte(0x20, 7, 1, choffs) | byte(0x30, 0, 1, choffs); }
|
||||
uint32_t ch_output_2(uint32_t choffs) const { return 0; }
|
||||
uint32_t ch_output_3(uint32_t choffs) const { return 0; }
|
||||
uint32_t ch_key_on(uint32_t choffs) const { return byte(0x20, 6, 1, choffs); }
|
||||
uint32_t ch_feedback(uint32_t choffs) const { return byte(0x20, 3, 3, choffs); }
|
||||
uint32_t ch_algorithm(uint32_t choffs) const { return byte(0x20, 0, 3, choffs); }
|
||||
uint32_t ch_block_freq(uint32_t choffs) const { return word(0x28, 0, 7, 0x30, 2, 6, choffs); }
|
||||
uint32_t ch_lfo_pm_sens(uint32_t choffs) const { return byte(0x38, 4, 3, choffs); }
|
||||
uint32_t ch_lfo_am_sens(uint32_t choffs) const { return byte(0x38, 0, 2, choffs); }
|
||||
uint32_t ch_lfo2_pm_sens(uint32_t choffs) const { return byte(0x140, 4, 3, choffs); } // fake
|
||||
uint32_t ch_lfo2_am_sens(uint32_t choffs) const { return byte(0x140, 0, 2, choffs); } // fake
|
||||
|
||||
// per-operator registers
|
||||
uint32_t op_detune(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); }
|
||||
uint32_t op_multiple(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); }
|
||||
uint32_t op_fix_range(uint32_t opoffs) const { return byte(0x40, 4, 3, opoffs); }
|
||||
uint32_t op_fix_frequency(uint32_t opoffs) const { return byte(0x40, 0, 4, opoffs); }
|
||||
uint32_t op_waveform(uint32_t opoffs) const { return byte(0x100, 4, 3, opoffs); } // fake
|
||||
uint32_t op_fine(uint32_t opoffs) const { return byte(0x100, 0, 4, opoffs); } // fake
|
||||
uint32_t op_total_level(uint32_t opoffs) const { return byte(0x60, 0, 7, opoffs); }
|
||||
uint32_t op_ksr(uint32_t opoffs) const { return byte(0x80, 6, 2, opoffs); }
|
||||
uint32_t op_fix_mode(uint32_t opoffs) const { return byte(0x80, 5, 1, opoffs); }
|
||||
uint32_t op_attack_rate(uint32_t opoffs) const { return byte(0x80, 0, 5, opoffs); }
|
||||
uint32_t op_lfo_am_enable(uint32_t opoffs) const { return byte(0xa0, 7, 1, opoffs); }
|
||||
uint32_t op_decay_rate(uint32_t opoffs) const { return byte(0xa0, 0, 5, opoffs); }
|
||||
uint32_t op_detune2(uint32_t opoffs) const { return byte(0xc0, 6, 2, opoffs); }
|
||||
uint32_t op_sustain_rate(uint32_t opoffs) const { return byte(0xc0, 0, 5, opoffs); }
|
||||
uint32_t op_eg_shift(uint32_t opoffs) const { return byte(0x120, 6, 2, opoffs); } // fake
|
||||
uint32_t op_reverb_rate(uint32_t opoffs) const { return byte(0x120, 0, 3, opoffs); } // fake
|
||||
uint32_t op_sustain_level(uint32_t opoffs) const { return byte(0xe0, 4, 4, opoffs); }
|
||||
uint32_t op_release_rate(uint32_t opoffs) const { return byte(0xe0, 0, 4, opoffs); }
|
||||
|
||||
protected:
|
||||
// return a bitfield extracted from a byte
|
||||
uint32_t byte(uint32_t offset, uint32_t start, uint32_t count, uint32_t extra_offset = 0) const
|
||||
{
|
||||
return bitfield(m_regdata[offset + extra_offset], start, count);
|
||||
}
|
||||
|
||||
// return a bitfield extracted from a pair of bytes, MSBs listed first
|
||||
uint32_t word(uint32_t offset1, uint32_t start1, uint32_t count1, uint32_t offset2, uint32_t start2, uint32_t count2, uint32_t extra_offset = 0) const
|
||||
{
|
||||
return (byte(offset1, start1, count1, extra_offset) << count2) | byte(offset2, start2, count2, extra_offset);
|
||||
}
|
||||
|
||||
// internal state
|
||||
uint32_t m_lfo_counter[2]; // LFO counter
|
||||
uint32_t m_noise_lfsr; // noise LFSR state
|
||||
uint8_t m_noise_counter; // noise counter
|
||||
uint8_t m_noise_state; // latched noise state
|
||||
uint8_t m_noise_lfo; // latched LFO noise value
|
||||
uint8_t m_lfo_am[2]; // current LFO AM value
|
||||
uint8_t m_regdata[REGISTERS]; // register data
|
||||
uint16_t m_phase_substep[OPERATORS]; // phase substep for fixed frequency
|
||||
int16_t m_lfo_waveform[4][LFO_WAVEFORM_LENGTH]; // LFO waveforms; AM in low 8, PM in upper 8
|
||||
uint16_t m_waveform[WAVEFORMS][WAVEFORM_LENGTH]; // waveforms
|
||||
};
|
||||
|
||||
|
||||
|
||||
//*********************************************************
|
||||
// IMPLEMENTATION CLASSES
|
||||
//*********************************************************
|
||||
|
||||
// ======================> ymf271
|
||||
|
||||
class ymf271
|
||||
{
|
||||
public:
|
||||
using fm_engine = fm_engine_base<opx_registers>;
|
||||
static constexpr uint32_t OUTPUTS = fm_engine::OUTPUTS;
|
||||
using output_data = fm_engine::output_data;
|
||||
|
||||
// constructor
|
||||
ymf271(ymfm_interface &intf);
|
||||
|
||||
// reset
|
||||
void reset();
|
||||
|
||||
// save/restore
|
||||
void save_restore(ymfm_saved_state &state);
|
||||
|
||||
// pass-through helpers
|
||||
uint32_t sample_rate(uint32_t input_clock) const { return m_fm.sample_rate(input_clock); }
|
||||
void invalidate_caches() { m_fm.invalidate_caches(); }
|
||||
|
||||
// read access
|
||||
uint8_t read_status();
|
||||
uint8_t read(uint32_t offset);
|
||||
|
||||
// write access
|
||||
void write_address(uint8_t data);
|
||||
void write_data(uint8_t data);
|
||||
void write(uint32_t offset, uint8_t data);
|
||||
|
||||
// generate one sample of sound
|
||||
void generate(output_data *output, uint32_t numsamples = 1);
|
||||
|
||||
protected:
|
||||
// internal state
|
||||
uint8_t m_address; // address register
|
||||
fm_engine m_fm; // core FM engine
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif // YMFM_OPX_H
|
36
3rdparty/ymfm/src/ymfm_opz.cpp
vendored
36
3rdparty/ymfm/src/ymfm_opz.cpp
vendored
@ -129,17 +129,17 @@ opz_registers::opz_registers() :
|
||||
{
|
||||
// waveform 0 is a sawtooth
|
||||
uint8_t am = index ^ 0xff;
|
||||
int8_t pm = int8_t(index);
|
||||
uint8_t pm = index;
|
||||
m_lfo_waveform[0][index] = am | (pm << 8);
|
||||
|
||||
// waveform 1 is a square wave
|
||||
am = bitfield(index, 7) ? 0 : 0xff;
|
||||
pm = int8_t(am ^ 0x80);
|
||||
pm = am ^ 0x80;
|
||||
m_lfo_waveform[1][index] = am | (pm << 8);
|
||||
|
||||
// waveform 2 is a triangle wave
|
||||
am = bitfield(index, 7) ? (index << 1) : ((index ^ 0xff) << 1);
|
||||
pm = int8_t(bitfield(index, 6) ? am : ~am);
|
||||
pm = bitfield(index, 6) ? am : ~am;
|
||||
m_lfo_waveform[2][index] = am | (pm << 8);
|
||||
|
||||
// waveform 3 is noise; it is filled in dynamically
|
||||
@ -555,16 +555,16 @@ std::string opz_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
uint32_t opnum = opoffs;
|
||||
|
||||
char buffer[256];
|
||||
char *end = &buffer[0];
|
||||
int end = 0;
|
||||
|
||||
end += sprintf(end, "%u.%02u", chnum, opnum);
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, "%u.%02u", chnum, opnum);
|
||||
|
||||
if (op_fix_mode(opoffs))
|
||||
end += sprintf(end, " fixfreq=%X fine=%X shift=%X", op_fix_frequency(opoffs), op_fine(opoffs), op_fix_range(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " fixfreq=%X fine=%X shift=%X", op_fix_frequency(opoffs), op_fine(opoffs), op_fix_range(opoffs));
|
||||
else
|
||||
end += sprintf(end, " freq=%04X dt2=%u fine=%X", ch_block_freq(choffs), op_detune2(opoffs), op_fine(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " freq=%04X dt2=%u fine=%X", ch_block_freq(choffs), op_detune2(opoffs), op_fine(opoffs));
|
||||
|
||||
end += sprintf(end, " dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " dt=%u fb=%u alg=%X mul=%X tl=%02X ksr=%u adsr=%02X/%02X/%02X/%X sl=%X out=%c%c",
|
||||
op_detune(opoffs),
|
||||
ch_feedback(choffs),
|
||||
ch_algorithm(choffs),
|
||||
@ -580,32 +580,32 @@ std::string opz_registers::log_keyon(uint32_t choffs, uint32_t opoffs)
|
||||
ch_output_1(choffs) ? 'R' : '-');
|
||||
|
||||
if (op_eg_shift(opoffs) != 0)
|
||||
end += sprintf(end, " egshift=%u", op_eg_shift(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " egshift=%u", op_eg_shift(opoffs));
|
||||
|
||||
bool am = (lfo_am_depth() != 0 && ch_lfo_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0);
|
||||
if (am)
|
||||
end += sprintf(end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am=%u/%02X", ch_lfo_am_sens(choffs), lfo_am_depth());
|
||||
bool pm = (lfo_pm_depth() != 0 && ch_lfo_pm_sens(choffs) != 0);
|
||||
if (pm)
|
||||
end += sprintf(end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm=%u/%02X", ch_lfo_pm_sens(choffs), lfo_pm_depth());
|
||||
if (am || pm)
|
||||
end += sprintf(end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]);
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo=%02X/%c", lfo_rate(), "WQTN"[lfo_waveform()]);
|
||||
|
||||
bool am2 = (lfo2_am_depth() != 0 && ch_lfo2_am_sens(choffs) != 0 && op_lfo_am_enable(opoffs) != 0);
|
||||
if (am2)
|
||||
end += sprintf(end, " am2=%u/%02X", ch_lfo2_am_sens(choffs), lfo2_am_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " am2=%u/%02X", ch_lfo2_am_sens(choffs), lfo2_am_depth());
|
||||
bool pm2 = (lfo2_pm_depth() != 0 && ch_lfo2_pm_sens(choffs) != 0);
|
||||
if (pm2)
|
||||
end += sprintf(end, " pm2=%u/%02X", ch_lfo2_pm_sens(choffs), lfo2_pm_depth());
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " pm2=%u/%02X", ch_lfo2_pm_sens(choffs), lfo2_pm_depth());
|
||||
if (am2 || pm2)
|
||||
end += sprintf(end, " lfo2=%02X/%c", lfo2_rate(), "WQTN"[lfo2_waveform()]);
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " lfo2=%02X/%c", lfo2_rate(), "WQTN"[lfo2_waveform()]);
|
||||
|
||||
if (op_reverb_rate(opoffs) != 0)
|
||||
end += sprintf(end, " rev=%u", op_reverb_rate(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " rev=%u", op_reverb_rate(opoffs));
|
||||
if (op_waveform(opoffs) != 0)
|
||||
end += sprintf(end, " wf=%u", op_waveform(opoffs));
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " wf=%u", op_waveform(opoffs));
|
||||
if (noise_enable() && opoffs == 31)
|
||||
end += sprintf(end, " noise=1");
|
||||
end += snprintf(&buffer[end], sizeof(buffer) - end, " noise=1");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
1
3rdparty/ymfm/src/ymfm_pcm.cpp
vendored
1
3rdparty/ymfm/src/ymfm_pcm.cpp
vendored
@ -46,7 +46,6 @@ namespace ymfm
|
||||
void pcm_registers::reset()
|
||||
{
|
||||
std::fill_n(&m_regdata[0], REGISTERS, 0);
|
||||
m_regdata[0x02] = 0x20;
|
||||
m_regdata[0xf8] = 0x1b;
|
||||
}
|
||||
|
||||
|
2
3rdparty/ymfm/src/ymfm_ssg.h
vendored
2
3rdparty/ymfm/src/ymfm_ssg.h
vendored
@ -49,6 +49,8 @@ namespace ymfm
|
||||
class ssg_override
|
||||
{
|
||||
public:
|
||||
virtual ~ssg_override() = default;
|
||||
|
||||
// reset our status
|
||||
virtual void ssg_reset() = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user