Prepare to (very) partially OPL4 support

This commit is contained in:
cam900 2024-07-11 15:13:02 +09:00
parent 73c301dd0e
commit c08edb1254
14 changed files with 691 additions and 233 deletions

File diff suppressed because it is too large Load diff

View file

@ -29,14 +29,16 @@ extern "C" {
}
#include "sound/ymfm/ymfm_adpcm.h"
#include "sound/ymfm/ymfm_opl.h"
#include "sound/ymfm/ymfm_pcm.h"
class DivOPLAInterface: public ymfm::ymfm_interface {
public:
unsigned char* adpcmBMem;
unsigned char* pcmMem;
int sampleBank;
uint8_t ymfm_external_read(ymfm::access_class type, uint32_t address);
void ymfm_external_write(ymfm::access_class type, uint32_t address, uint8_t data);
DivOPLAInterface(): adpcmBMem(NULL), sampleBank(0) {}
DivOPLAInterface(): adpcmBMem(NULL), pcmMem(NULL), sampleBank(0) {}
};
class DivPlatformOPL: public DivDispatch {
@ -62,9 +64,9 @@ class DivPlatformOPL: public DivDispatch {
state.ops=2;
}
};
Channel chan[20];
DivDispatchOscBuffer* oscBuf[20];
bool isMuted[20];
Channel chan[44];
DivDispatchOscBuffer* oscBuf[44];
bool isMuted[44];
struct QueuedWrite {
unsigned short addr;
unsigned char val;
@ -72,7 +74,7 @@ class DivPlatformOPL: public DivDispatch {
QueuedWrite(): addr(0), val(0), addrOrVal(false) {}
QueuedWrite(unsigned short a, unsigned char v): addr(a), val(v), addrOrVal(false) {}
};
FixedQueue<QueuedWrite,2048> writes;
FixedQueue<QueuedWrite,4096> writes;
unsigned int dacVal;
unsigned int dacVal2;
@ -86,8 +88,11 @@ class DivPlatformOPL: public DivDispatch {
unsigned char* adpcmBMem;
size_t adpcmBMemLen;
unsigned char* pcmMem;
size_t pcmMemLen;
DivOPLAInterface iface;
unsigned int sampleOffB[256];
unsigned int sampleOffPCM[256];
bool sampleLoaded[256];
ymfm::adpcm_b_engine* adpcmB;
@ -97,12 +102,12 @@ class DivPlatformOPL: public DivDispatch {
const unsigned short* chanMap;
const unsigned char* outChanMap;
int chipFreqBase, chipRateBase;
int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank, totalOutputs;
int delay, chipType, oplType, chans, melodicChans, totalChans, adpcmChan=-1, pcmChanOffs=-1, sampleBank, totalOutputs, ramSize;
unsigned char lastBusy;
unsigned char drumState;
unsigned char drumVol[5];
unsigned char regPool[512];
unsigned char regPool[768];
bool properDrums, properDrumsSys, dam, dvb;
@ -115,8 +120,8 @@ class DivPlatformOPL: public DivDispatch {
bool update4OpMask, pretendYMU, downsample, compatPan;
short oldWrites[512];
short pendingWrites[512];
short oldWrites[768];
short pendingWrites[768];
// chips
opl3_chip fm;
@ -124,6 +129,7 @@ class DivPlatformOPL: public DivDispatch {
ymfm::ym3812* fm_ymfm2;
ymfm::y8950* fm_ymfm8950;
ymfm::ymf262* fm_ymfm3;
ymfm::ymf278b* fm_ymfm4;
fmopl2_t fm_lle2;
fmopl3_t fm_lle3;
@ -141,6 +147,7 @@ class DivPlatformOPL: public DivDispatch {
void acquire_nukedLLE3(short** buf, size_t len);
void acquire_nuked(short** buf, size_t len);
void acquire_ymfm3(short** buf, size_t len);
void acquire_ymfm4(short** buf, size_t len);
void acquire_ymfm8950(short** buf, size_t len);
void acquire_ymfm2(short** buf, size_t len);
void acquire_ymfm1(short** buf, size_t len);

View file

@ -28,6 +28,11 @@ uint8_t DivOPLAInterface::ymfm_external_read(ymfm::access_class type, uint32_t a
return 0;
}
return adpcmBMem[address&0xffffff];
case ymfm::ACCESS_PCM:
if (pcmMem==NULL) {
return 0;
}
return pcmMem[address&0x3fffff];
default:
return 0;
}

View file

@ -304,9 +304,9 @@ public:
// simple getters for debugging
fm_operator<RegisterType> *debug_operator(uint32_t index) const { return m_op[index]; }
int32_t debug_output(uint32_t index) const { return m_output[index]; }
int32_t debug_special1() const { return m_special1; }
int32_t debug_special2() const { return m_special2; }
int32_t debug_output(uint32_t index) const { return m_output[index]; }
int32_t debug_special1() const { return m_special1; }
int32_t debug_special2() const { return m_special2; }
private:
// helper to add values to the outputs based on channel enables
@ -320,21 +320,21 @@ private:
constexpr int out3_index = 3 % RegisterType::OUTPUTS;
if (RegisterType::OUTPUTS == 1 || m_regs.ch_output_0(choffs)) {
m_output[out0_index]=value;
m_output[out0_index]=value;
output.data[out0_index] += value;
}
}
if (RegisterType::OUTPUTS >= 2 && m_regs.ch_output_1(choffs)) {
m_output[out1_index]=value;
m_output[out1_index]=value;
output.data[out1_index] += value;
}
}
if (RegisterType::OUTPUTS >= 3 && m_regs.ch_output_2(choffs)) {
m_output[out2_index]=value;
m_output[out2_index]=value;
output.data[out2_index] += value;
}
}
if (RegisterType::OUTPUTS >= 4 && m_regs.ch_output_3(choffs)) {
m_output[out3_index]=value;
m_output[out3_index]=value;
output.data[out3_index] += value;
}
}
}
// internal state
@ -344,9 +344,9 @@ private:
fm_operator<RegisterType> *m_op[4]; // up to 4 operators
RegisterType &m_regs; // direct reference to registers
fm_engine_base<RegisterType> &m_owner; // reference to the owning engine
mutable int32_t m_output[4];
mutable int32_t m_special1;
mutable int32_t m_special2;
mutable int32_t m_output[4];
mutable int32_t m_special1;
mutable int32_t m_special2;
};

View file

@ -529,7 +529,7 @@ public:
// generate samples of sound
void generate(output_data *output, uint32_t numsamples = 1);
fm_engine* debug_fm_engine() { return &m_fm; }
fm_engine* debug_fm_engine() { return &m_fm; }
protected:
// internal state
uint8_t m_address; // address register
@ -577,8 +577,8 @@ public:
// generate samples of sound
void generate(output_data *output, uint32_t numsamples = 1);
fm_engine* debug_fm_engine() { return &m_fm; }
adpcm_b_engine* debug_adpcm_b_engine() { return &m_adpcm_b; }
fm_engine* debug_fm_engine() { return &m_fm; }
adpcm_b_engine* debug_adpcm_b_engine() { return &m_adpcm_b; }
protected:
// internal state
@ -628,7 +628,7 @@ public:
// generate samples of sound
void generate(output_data *output, uint32_t numsamples = 1);
fm_engine* debug_fm_engine() { return &m_fm; }
fm_engine* debug_fm_engine() { return &m_fm; }
protected:
// internal state
@ -677,7 +677,7 @@ public:
// generate samples of sound
void generate(output_data *output, uint32_t numsamples = 1);
fm_engine* debug_fm_engine() { return &m_fm; }
fm_engine* debug_fm_engine() { return &m_fm; }
protected:
// internal state
@ -791,6 +791,8 @@ public:
// generate samples of sound
void generate(output_data *output, uint32_t numsamples = 1);
fm_engine* debug_fm_engine() { return &m_fm; }
pcm_engine* debug_pcm_engine() { return &m_pcm; }
protected:
// internal state
uint16_t m_address; // address register

View file

@ -309,6 +309,7 @@ void pcm_channel::clock(uint32_t env_counter)
void pcm_channel::output(output_data &output) const
{
m_output[0] = m_output[1] = m_output[2] = m_output[3] = 0;
// early out if the envelope is effectively off
uint32_t envelope = m_env_attenuation;
if (envelope > EG_QUIET)
@ -340,6 +341,8 @@ void pcm_channel::output(output_data &output) const
uint32_t outnum = m_regs.ch_output_channel(m_choffs) * 2;
output.data[outnum + 0] += (lvol * sample) >> 15;
output.data[outnum + 1] += (rvol * sample) >> 15;
m_output[outnum + 0] = output.data[outnum + 0];
m_output[outnum + 1] = output.data[outnum + 1];
}

View file

@ -267,6 +267,8 @@ public:
// load a new wavetable entry
void load_wavetable();
int32_t debug_output(uint32_t index) const { return m_output[index]; }
private:
// internal helpers
void start_attack();
@ -291,6 +293,7 @@ private:
pcm_cache m_cache; // cached data
pcm_registers &m_regs; // reference to registers
pcm_engine &m_owner; // reference to our owner
mutable int32_t m_output[4];
};
@ -331,6 +334,8 @@ public:
// return a reference to our registers
pcm_registers &regs() { return m_regs; }
// simple getters for debugging
pcm_channel *debug_channel(uint32_t index) const { return m_channel[index].get(); }
private:
// internal state
ymfm_interface &m_intf; // reference to the interface