Prepare to (very) partially OPL4 support
This commit is contained in:
parent
73c301dd0e
commit
c08edb1254
1
extern/adpcm-xq
vendored
Submodule
1
extern/adpcm-xq
vendored
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 6220fed7655e86a29702b45dbc641a028ed5a4bf
|
|
@ -760,6 +760,18 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
case DIV_SYSTEM_SID2:
|
||||
dispatch=new DivPlatformSID2;
|
||||
break;
|
||||
case DIV_SYSTEM_OPL4:
|
||||
dispatch=new DivPlatformOPL;
|
||||
((DivPlatformOPL*)dispatch)->setOPLType(4,false);
|
||||
// YMFM for now
|
||||
((DivPlatformOPL*)dispatch)->setCore(1);
|
||||
break;
|
||||
case DIV_SYSTEM_OPL4_DRUMS:
|
||||
dispatch=new DivPlatformOPL;
|
||||
((DivPlatformOPL*)dispatch)->setOPLType(4,true);
|
||||
// YMFM for now
|
||||
((DivPlatformOPL*)dispatch)->setCore(1);
|
||||
break;
|
||||
case DIV_SYSTEM_DUMMY:
|
||||
dispatch=new DivPlatformDummy;
|
||||
break;
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 ®s() { 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
|
||||
|
|
|
@ -1621,7 +1621,10 @@ void DivEngine::registerSystems() {
|
|||
{_("4OP 1"), _("FM 2"), _("4OP 3"), _("FM 4"), _("4OP 5"), _("FM 6"), _("4OP 7"), _("FM 8"), _("4OP 9"), _("FM 10"), _("4OP 11"), _("FM 12"), _("FM 13"), _("FM 14"), _("FM 15"), _("FM 16"), _("FM 17"), _("FM 18"), _("PCM 1"), _("PCM 2"), _("PCM 3"), _("PCM 4"), _("PCM 5"), _("PCM 6"), _("PCM 7"), _("PCM 8"), _("PCM 9"), _("PCM 10"), _("PCM 11"), _("PCM 12"), _("PCM 13"), _("PCM 14"), _("PCM 15"), _("PCM 16"), _("PCM 17"), _("PCM 18"), _("PCM 19"), _("PCM 20"), _("PCM 21"), _("PCM 22"), _("PCM 23"), _("PCM 24")},
|
||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM}
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM},
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA},
|
||||
fmEffectHandlerMap,
|
||||
fmOPLPostEffectHandlerMap
|
||||
);
|
||||
|
||||
// TODO: same here
|
||||
|
@ -1631,7 +1634,10 @@ void DivEngine::registerSystems() {
|
|||
{_("4OP 1"), _("FM 2"), _("4OP 3"), _("FM 4"), _("4OP 5"), _("FM 6"), _("4OP 7"), _("FM 8"), _("4OP 9"), _("FM 10"), _("4OP 11"), _("FM 12"), _("FM 13"), _("FM 14"), _("FM 15"), _("Kick/FM 16"), _("Snare"), _("Tom"), _("Top"), _("HiHat"), _("PCM 1"), _("PCM 2"), _("PCM 3"), _("PCM 4"), _("PCM 5"), _("PCM 6"), _("PCM 7"), _("PCM 8"), _("PCM 9"), _("PCM 10"), _("PCM 11"), _("PCM 12"), _("PCM 13"), _("PCM 14"), _("PCM 15"), _("PCM 16"), _("PCM 17"), _("PCM 18"), _("PCM 19"), _("PCM 20"), _("PCM 21"), _("PCM 22"), _("PCM 23"), _("PCM 24")},
|
||||
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P8", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"},
|
||||
{DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_FM, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM},
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM}
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM},
|
||||
{DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA},
|
||||
fmOPLDrumsEffectHandlerMap,
|
||||
fmOPLPostEffectHandlerMap
|
||||
);
|
||||
|
||||
EffectHandlerMap es5506PreEffectHandlerMap={
|
||||
|
|
|
@ -987,6 +987,13 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_OPL4:
|
||||
case DIV_SYSTEM_OPL4_DRUMS:
|
||||
w->writeC(0xd0|baseAddr2);
|
||||
w->writeC(write.addr>>8);
|
||||
w->writeC(write.addr&0xff);
|
||||
w->writeC(write.val);
|
||||
break;
|
||||
case DIV_SYSTEM_SCC:
|
||||
if (write.addr<0x80) {
|
||||
w->writeC(0xd2);
|
||||
|
@ -1254,6 +1261,7 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
bool writeVOXSamples=false;
|
||||
DivDispatch* writeADPCM_OPNA[2]={NULL,NULL};
|
||||
DivDispatch* writeADPCM_OPNB[2]={NULL,NULL};
|
||||
DivDispatch* writePCM_OPL4[2]={NULL,NULL};
|
||||
DivDispatch* writeADPCM_Y8950[2]={NULL,NULL};
|
||||
DivDispatch* writeSegaPCM[2]={NULL,NULL};
|
||||
DivDispatch* writeX1010[2]={NULL,NULL};
|
||||
|
@ -1706,6 +1714,20 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
howManyChips++;
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_OPL4:
|
||||
case DIV_SYSTEM_OPL4_DRUMS:
|
||||
if (!hasOPL4) {
|
||||
hasOPL4=disCont[i].dispatch->chipClock;
|
||||
CHIP_VOL(12,1.0);
|
||||
willExport[i]=true;
|
||||
} else if (!(hasOPL4&0x40000000)) {
|
||||
isSecond[i]=true;
|
||||
CHIP_VOL_SECOND(12,1.0);
|
||||
willExport[i]=true;
|
||||
hasOPL4|=0x40000000;
|
||||
howManyChips++;
|
||||
}
|
||||
break;
|
||||
case DIV_SYSTEM_SCC:
|
||||
case DIV_SYSTEM_SCC_PLUS:
|
||||
if (!hasK051649) {
|
||||
|
@ -2150,6 +2172,16 @@ SafeWriter* DivEngine::saveVGM(bool* sysToExport, bool loop, int version, bool p
|
|||
w->writeI(0);
|
||||
w->write(writeADPCM_OPNB[i]->getSampleMem(1),writeADPCM_OPNB[i]->getSampleMemUsage(1));
|
||||
}
|
||||
// PCM (OPL4)
|
||||
if (writePCM_OPL4[i]!=NULL && writePCM_OPL4[i]->getSampleMemUsage(0)>0) {
|
||||
w->writeC(0x67);
|
||||
w->writeC(0x66);
|
||||
w->writeC(0x84);
|
||||
w->writeI((writePCM_OPL4[i]->getSampleMemUsage(0)+8)|(i*0x80000000));
|
||||
w->writeI(writePCM_OPL4[i]->getSampleMemCapacity(0));
|
||||
w->writeI(0);
|
||||
w->write(writePCM_OPL4[i]->getSampleMem(0),writePCM_OPL4[i]->getSampleMemUsage(0));
|
||||
}
|
||||
// ADPCM (Y8950)
|
||||
if (writeADPCM_Y8950[i]!=NULL && writeADPCM_Y8950[i]->getSampleMemUsage(0)>0) {
|
||||
w->writeC(0x67);
|
||||
|
|
|
@ -1260,6 +1260,8 @@ const int availableSystems[]={
|
|||
DIV_SYSTEM_5E01,
|
||||
DIV_SYSTEM_BIFURCATOR,
|
||||
DIV_SYSTEM_SID2,
|
||||
DIV_SYSTEM_OPL4,
|
||||
DIV_SYSTEM_OPL4_DRUMS,
|
||||
0 // don't remove this last one!
|
||||
};
|
||||
|
||||
|
@ -1295,6 +1297,8 @@ const int chipsFM[]={
|
|||
DIV_SYSTEM_OPL3_DRUMS,
|
||||
DIV_SYSTEM_OPZ,
|
||||
DIV_SYSTEM_ESFM,
|
||||
DIV_SYSTEM_OPL4,
|
||||
DIV_SYSTEM_OPL4_DRUMS,
|
||||
0 // don't remove this last one!
|
||||
};
|
||||
|
||||
|
@ -1380,6 +1384,8 @@ const int chipsSample[]={
|
|||
DIV_SYSTEM_NDS,
|
||||
DIV_SYSTEM_GBA_DMA,
|
||||
DIV_SYSTEM_GBA_MINMOD,
|
||||
DIV_SYSTEM_OPL4,
|
||||
DIV_SYSTEM_OPL4_DRUMS,
|
||||
0 // don't remove this last one!
|
||||
};
|
||||
|
||||
|
|
|
@ -519,6 +519,18 @@ void FurnaceGUI::initSystemPresets() {
|
|||
) // variable rate, Mono DAC
|
||||
}
|
||||
);
|
||||
SUB_ENTRY(
|
||||
"MSX + Moonsound", {
|
||||
CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"),
|
||||
CH(DIV_SYSTEM_OPL4, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
SUB_ENTRY(
|
||||
"MSX + Moonsound (drums mode)", {
|
||||
CH(DIV_SYSTEM_AY8910, 1.0f, 0, "chipType=1"),
|
||||
CH(DIV_SYSTEM_OPL4_DRUMS, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"NEC PC-88", {}
|
||||
);
|
||||
|
@ -2659,6 +2671,16 @@ void FurnaceGUI::initSystemPresets() {
|
|||
CH(DIV_SYSTEM_ESFM, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Yamaha YMF278B (OPL4)", {
|
||||
CH(DIV_SYSTEM_OPL4, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
SUB_ENTRY(
|
||||
"Yamaha YMF278B (drums mode)", {
|
||||
CH(DIV_SYSTEM_OPL4_DRUMS, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
if (settings.hiddenSystems) {
|
||||
ENTRY(
|
||||
"Yamaha YMU759 (MA-2)", {
|
||||
|
@ -2870,6 +2892,16 @@ void FurnaceGUI::initSystemPresets() {
|
|||
CH(DIV_SYSTEM_NDS, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
ENTRY(
|
||||
"Yamaha YMF278B (OPL4)", {
|
||||
CH(DIV_SYSTEM_OPL4, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
SUB_ENTRY(
|
||||
"Yamaha YMF278B (drums mode)", {
|
||||
CH(DIV_SYSTEM_OPL4_DRUMS, 1.0f, 0, "")
|
||||
}
|
||||
);
|
||||
CATEGORY_END;
|
||||
|
||||
CATEGORY_BEGIN("Wavetable","chips which use user-specified waveforms to generate sound.");
|
||||
|
|
|
@ -2503,6 +2503,59 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_OPL4:
|
||||
case DIV_SYSTEM_OPL4_DRUMS: {
|
||||
int clockSel=flags.getInt("clockSel",0);
|
||||
int ramSize=flags.getInt("ramSize",0);
|
||||
|
||||
ImGui::Text(_("Clock rate:"));
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton(_("33.8688MHz"),clockSel==0)) {
|
||||
clockSel=0;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("28.64MHz (NTSC)"),clockSel==1)) {
|
||||
clockSel=1;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("28.38MHz (PAL)"),clockSel==2)) {
|
||||
clockSel=2;
|
||||
altered=true;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
ImGui::Text(_("RAM size:"));
|
||||
ImGui::Indent();
|
||||
if (ImGui::RadioButton(_("4MB"),ramSize==0)) {
|
||||
ramSize=0;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("2MB"),ramSize==1)) {
|
||||
ramSize=1;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("1MB"),ramSize==2)) {
|
||||
ramSize=2;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("512KB"),ramSize==3)) {
|
||||
ramSize=3;
|
||||
altered=true;
|
||||
}
|
||||
if (ImGui::RadioButton(_("128KB"),ramSize==4)) {
|
||||
ramSize=4;
|
||||
altered=true;
|
||||
}
|
||||
ImGui::Unindent();
|
||||
|
||||
if (altered) {
|
||||
e->lockSave([&]() {
|
||||
flags.set("clockSel",clockSel);
|
||||
flags.set("ramSize",ramSize);
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_SYSTEM_SWAN:
|
||||
case DIV_SYSTEM_BUBSYS_WSG:
|
||||
case DIV_SYSTEM_PET:
|
||||
|
|
Loading…
Reference in a new issue