Merge branch 'master' of https://github.com/tildearrow/furnace into es5506_alt

This commit is contained in:
cam900 2022-12-25 18:48:29 +09:00
commit 96c0bea63b
60 changed files with 19453 additions and 190 deletions

View file

@ -249,16 +249,20 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
case DIV_SYSTEM_YM2610:
case DIV_SYSTEM_YM2610_FULL:
dispatch=new DivPlatformYM2610;
((DivPlatformYM2610*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2610_EXT:
case DIV_SYSTEM_YM2610_FULL_EXT:
dispatch=new DivPlatformYM2610Ext;
((DivPlatformYM2610Ext*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2610B:
dispatch=new DivPlatformYM2610B;
((DivPlatformYM2610B*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2610B_EXT:
dispatch=new DivPlatformYM2610BExt;
((DivPlatformYM2610BExt*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_AMIGA:
dispatch=new DivPlatformAmiga;
@ -278,15 +282,19 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
break;
case DIV_SYSTEM_YM2203:
dispatch=new DivPlatformYM2203;
((DivPlatformYM2203*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2203_EXT:
dispatch=new DivPlatformYM2203Ext;
((DivPlatformYM2203Ext*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2608:
dispatch=new DivPlatformYM2608;
((DivPlatformYM2608*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_YM2608_EXT:
dispatch=new DivPlatformYM2608Ext;
((DivPlatformYM2608Ext*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
break;
case DIV_SYSTEM_OPLL:
case DIV_SYSTEM_OPLL_DRUMS:

View file

@ -47,8 +47,8 @@
#define BUSY_BEGIN_SOFT softLocked=true; isBusy.lock();
#define BUSY_END isBusy.unlock(); softLocked=false;
#define DIV_VERSION "dev130"
#define DIV_ENGINE_VERSION 130
#define DIV_VERSION "0.6pre2"
#define DIV_ENGINE_VERSION 132
// for imports
#define DIV_VERSION_MOD 0xff01
#define DIV_VERSION_FC 0xff02

View file

@ -506,6 +506,8 @@ void DivInstrument::writeFeatureSN(SafeWriter* w) {
w->writeC(snes.gain);
w->writeC(((snes.sus&3)<<5)|(snes.d2&31));
FEATURE_END;
}
@ -1809,7 +1811,7 @@ void DivInstrument::putInsData(SafeWriter* w) {
#define READ_FEAT_END \
if (reader.tell()<endOfFeat) reader.seek(endOfFeat,SEEK_SET);
void DivInstrument::readFeatureNA(SafeReader& reader) {
void DivInstrument::readFeatureNA(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
name=reader.readString();
@ -1817,7 +1819,7 @@ void DivInstrument::readFeatureNA(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureFM(SafeReader& reader) {
void DivInstrument::readFeatureFM(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned char opCount=reader.readC();
@ -1888,7 +1890,7 @@ void DivInstrument::readFeatureFM(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureMA(SafeReader& reader) {
void DivInstrument::readFeatureMA(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned short macroHeaderLen=reader.readS();
@ -2010,7 +2012,7 @@ void DivInstrument::readFeatureMA(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeature64(SafeReader& reader) {
void DivInstrument::readFeature64(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned char next=reader.readC();
@ -2050,7 +2052,7 @@ void DivInstrument::readFeature64(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureGB(SafeReader& reader) {
void DivInstrument::readFeatureGB(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned char next=reader.readC();
@ -2073,7 +2075,7 @@ void DivInstrument::readFeatureGB(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureSM(SafeReader& reader) {
void DivInstrument::readFeatureSM(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
amiga.initSample=reader.readS();
@ -2095,7 +2097,7 @@ void DivInstrument::readFeatureSM(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureOx(SafeReader& reader, int op) {
void DivInstrument::readFeatureOx(SafeReader& reader, int op, short version) {
READ_FEAT_BEGIN;
unsigned short macroHeaderLen=reader.readS();
@ -2214,7 +2216,7 @@ void DivInstrument::readFeatureOx(SafeReader& reader, int op) {
READ_FEAT_END;
}
void DivInstrument::readFeatureLD(SafeReader& reader) {
void DivInstrument::readFeatureLD(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
fm.fixedDrums=reader.readC();
@ -2225,7 +2227,7 @@ void DivInstrument::readFeatureLD(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureSN(SafeReader& reader) {
void DivInstrument::readFeatureSN(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
unsigned char next=reader.readC();
@ -2238,18 +2240,23 @@ void DivInstrument::readFeatureSN(SafeReader& reader) {
next=reader.readC();
snes.useEnv=next&16;
snes.sus=next&8;
snes.sus=(next&8)?1:0;
snes.gainMode=(DivInstrumentSNES::GainMode)(next&7);
if (snes.gainMode==1 || snes.gainMode==2 || snes.gainMode==3) snes.gainMode=DivInstrumentSNES::GAIN_MODE_DIRECT;
snes.gain=reader.readC();
if (version>=131) {
next=reader.readC();
snes.sus=(next>>5)&3;
snes.d2=next&31;
}
READ_FEAT_END;
}
void DivInstrument::readFeatureN1(SafeReader& reader) {
void DivInstrument::readFeatureN1(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
n163.wave=reader.readI();
@ -2260,7 +2267,7 @@ void DivInstrument::readFeatureN1(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureFD(SafeReader& reader) {
void DivInstrument::readFeatureFD(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
fds.modSpeed=reader.readI();
@ -2271,7 +2278,7 @@ void DivInstrument::readFeatureFD(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureWS(SafeReader& reader) {
void DivInstrument::readFeatureWS(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
ws.wave1=reader.readI();
@ -2406,7 +2413,7 @@ void DivInstrument::readFeatureWL(SafeReader& reader, DivSong* song, short versi
READ_FEAT_END;
}
void DivInstrument::readFeatureMP(SafeReader& reader) {
void DivInstrument::readFeatureMP(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
multipcm.ar=reader.readC();
@ -2422,7 +2429,7 @@ void DivInstrument::readFeatureMP(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureSU(SafeReader& reader) {
void DivInstrument::readFeatureSU(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
su.switchRoles=reader.readC();
@ -2430,7 +2437,7 @@ void DivInstrument::readFeatureSU(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureES(SafeReader& reader) {
void DivInstrument::readFeatureES(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
es5506.filter.mode=(DivInstrumentES5506::Filter::FilterMode)reader.readC();
@ -2447,7 +2454,7 @@ void DivInstrument::readFeatureES(SafeReader& reader) {
READ_FEAT_END;
}
void DivInstrument::readFeatureX1(SafeReader& reader) {
void DivInstrument::readFeatureX1(SafeReader& reader, short version) {
READ_FEAT_BEGIN;
x1_010.bankSlot=reader.readI();
@ -2479,47 +2486,47 @@ DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, b
if (memcmp(featCode,"EN",2)==0) { // end of instrument
break;
} else if (memcmp(featCode,"NA",2)==0) { // name
readFeatureNA(reader);
readFeatureNA(reader,version);
} else if (memcmp(featCode,"FM",2)==0) { // FM
readFeatureFM(reader);
readFeatureFM(reader,version);
} else if (memcmp(featCode,"MA",2)==0) { // macros
readFeatureMA(reader);
readFeatureMA(reader,version);
} else if (memcmp(featCode,"64",2)==0) { // C64
readFeature64(reader);
readFeature64(reader,version);
} else if (memcmp(featCode,"GB",2)==0) { // Game Boy
readFeatureGB(reader);
readFeatureGB(reader,version);
} else if (memcmp(featCode,"SM",2)==0) { // sample
readFeatureSM(reader);
readFeatureSM(reader,version);
} else if (memcmp(featCode,"O1",2)==0) { // op1 macros
readFeatureOx(reader,0);
readFeatureOx(reader,0,version);
} else if (memcmp(featCode,"O2",2)==0) { // op2 macros
readFeatureOx(reader,1);
readFeatureOx(reader,1,version);
} else if (memcmp(featCode,"O3",2)==0) { // op3 macros
readFeatureOx(reader,2);
readFeatureOx(reader,2,version);
} else if (memcmp(featCode,"O4",2)==0) { // op4 macros
readFeatureOx(reader,3);
readFeatureOx(reader,3,version);
} else if (memcmp(featCode,"LD",2)==0) { // OPL drums
readFeatureLD(reader);
readFeatureLD(reader,version);
} else if (memcmp(featCode,"SN",2)==0) { // SNES
readFeatureSN(reader);
readFeatureSN(reader,version);
} else if (memcmp(featCode,"N1",2)==0) { // Namco 163
readFeatureN1(reader);
readFeatureN1(reader,version);
} else if (memcmp(featCode,"FD",2)==0) { // FDS/VB
readFeatureFD(reader);
readFeatureFD(reader,version);
} else if (memcmp(featCode,"WS",2)==0) { // WaveSynth
readFeatureWS(reader);
readFeatureWS(reader,version);
} else if (memcmp(featCode,"SL",2)==0 && fui && song!=NULL) { // sample list
readFeatureSL(reader,song,version);
} else if (memcmp(featCode,"WL",2)==0 && fui && song!=NULL) { // wave list
readFeatureWL(reader,song,version);
} else if (memcmp(featCode,"MP",2)==0) { // MultiPCM
readFeatureMP(reader);
readFeatureMP(reader,version);
} else if (memcmp(featCode,"SU",2)==0) { // Sound Unit
readFeatureSU(reader);
readFeatureSU(reader,version);
} else if (memcmp(featCode,"ES",2)==0) { // ES5506
readFeatureES(reader);
readFeatureES(reader,version);
} else if (memcmp(featCode,"X1",2)==0) { // X1-010
readFeatureX1(reader);
readFeatureX1(reader,version);
} else {
if (song==NULL && (memcmp(featCode,"SL",2)==0 || (memcmp(featCode,"WL",2)==0))) {
// nothing
@ -3134,7 +3141,7 @@ DivDataErrors DivInstrument::readInsDataOld(SafeReader &reader, short version) {
snes.a=reader.readC();
snes.d=reader.readC();
snes.s=reader.readC();
snes.sus=snes.s&8;
snes.sus=(snes.s&8)?1:0;
snes.s&=7;
snes.r=reader.readC();
}

View file

@ -630,10 +630,15 @@ struct DivInstrumentSNES {
GAIN_MODE_INC_LINEAR=6,
GAIN_MODE_INC_INVLOG=7
};
bool useEnv, sus;
bool useEnv;
// 0: no sustain (key off = cut)
// 1: sustain (R = d2; key off = dec linear to r)
// 2: sustain (R = d2; key off = dec exponential to r)
// 3: sustain (R = d2; key off = R to r)
unsigned char sus;
GainMode gainMode;
unsigned char gain;
unsigned char a, d, s, r;
unsigned char a, d, s, r, d2;
bool operator==(const DivInstrumentSNES& other);
bool operator!=(const DivInstrumentSNES& other) {
@ -642,13 +647,14 @@ struct DivInstrumentSNES {
DivInstrumentSNES():
useEnv(true),
sus(false),
sus(0),
gainMode(GAIN_MODE_DIRECT),
gain(127),
a(15),
d(7),
s(7),
r(0) {}
r(0),
d2(0) {}
};
struct DivInstrument {
@ -691,24 +697,24 @@ struct DivInstrument {
void writeFeatureES(SafeWriter* w);
void writeFeatureX1(SafeWriter* w);
void readFeatureNA(SafeReader& reader);
void readFeatureFM(SafeReader& reader);
void readFeatureMA(SafeReader& reader);
void readFeature64(SafeReader& reader);
void readFeatureGB(SafeReader& reader);
void readFeatureSM(SafeReader& reader);
void readFeatureOx(SafeReader& reader, int op);
void readFeatureLD(SafeReader& reader);
void readFeatureSN(SafeReader& reader);
void readFeatureN1(SafeReader& reader);
void readFeatureFD(SafeReader& reader);
void readFeatureWS(SafeReader& reader);
void readFeatureNA(SafeReader& reader, short version);
void readFeatureFM(SafeReader& reader, short version);
void readFeatureMA(SafeReader& reader, short version);
void readFeature64(SafeReader& reader, short version);
void readFeatureGB(SafeReader& reader, short version);
void readFeatureSM(SafeReader& reader, short version);
void readFeatureOx(SafeReader& reader, int op, short version);
void readFeatureLD(SafeReader& reader, short version);
void readFeatureSN(SafeReader& reader, short version);
void readFeatureN1(SafeReader& reader, short version);
void readFeatureFD(SafeReader& reader, short version);
void readFeatureWS(SafeReader& reader, short version);
void readFeatureSL(SafeReader& reader, DivSong* song, short version);
void readFeatureWL(SafeReader& reader, DivSong* song, short version);
void readFeatureMP(SafeReader& reader);
void readFeatureSU(SafeReader& reader);
void readFeatureES(SafeReader& reader);
void readFeatureX1(SafeReader& reader);
void readFeatureMP(SafeReader& reader, short version);
void readFeatureSU(SafeReader& reader, short version);
void readFeatureES(SafeReader& reader, short version);
void readFeatureX1(SafeReader& reader, short version);
DivDataErrors readInsDataOld(SafeReader& reader, short version);
DivDataErrors readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song);

View file

@ -21,6 +21,7 @@
#define _FMSHARED_OPN_H
#include "fmsharedbase.h"
#include "../../../extern/opn/ym3438.h"
#define PLEASE_HELP_ME(_targetChan) \
int boundaryBottom=parent->calcBaseFreq(chipClock,CHIP_FREQBASE,0,false); \
@ -146,26 +147,37 @@ class DivPlatformOPN: public DivPlatformFMBase {
pan(3) {}
};
const int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs, chanNum;
double fmFreqBase;
unsigned int fmDivBase;
unsigned int ayDiv;
unsigned char csmChan;
unsigned char lfoValue;
bool extSys;
bool extSys, useCombo;
DivConfig ayFlags;
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
DivPlatformOPN(double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false, unsigned char cc=255):
DivPlatformOPN(int ext, int psg, int adpcmA, int adpcmB, int chanCount, double f=9440540.0, unsigned int d=72, unsigned int a=32, bool isExtSys=false, unsigned char cc=255):
DivPlatformFMBase(),
extChanOffs(ext),
psgChanOffs(psg),
adpcmAChanOffs(adpcmA),
adpcmBChanOffs(adpcmB),
chanNum(chanCount),
fmFreqBase(f),
fmDivBase(d),
ayDiv(a),
csmChan(cc),
lfoValue(0),
extSys(isExtSys) {}
extSys(isExtSys),
useCombo(false) {}
public:
void setCombo(bool combo) {
useCombo=combo;
}
};
#endif

View file

@ -1155,7 +1155,7 @@ void DivPlatformGenesis::reset() {
fm_ymfm->reset();
}
OPN2_Reset(&fm);
OPN2_SetChipType(ladder?ym3438_mode_ym2612:0);
OPN2_SetChipType(&fm,ladder?ym3438_mode_ym2612:0);
if (dumpWrites) {
addWrite(0xffffffff,0);
}
@ -1253,7 +1253,7 @@ void DivPlatformGenesis::setFlags(const DivConfig& flags) {
}
ladder=flags.getBool("ladderEffect",false);
noExtMacros=flags.getBool("noExtMacros",false);
OPN2_SetChipType(ladder?ym3438_mode_ym2612:0);
OPN2_SetChipType(&fm,ladder?ym3438_mode_ym2612:0);
CHECK_CUSTOM_CLOCK;
if (useYMFM) {
if (fm_ymfm!=NULL) delete fm_ymfm;

View file

@ -21,7 +21,6 @@
#define _GENESIS_H
#include "fmshared_OPN.h"
#include "../../../extern/Nuked-OPN2/ym3438.h"
#include "sound/ymfm/ymfm_opn.h"
@ -131,7 +130,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
DivPlatformGenesis():
DivPlatformOPN(9440540.0, 72, 32, false, 7) {}
DivPlatformOPN(2, 6, 6, 6, 6, 9440540.0, 72, 32, false, 7) {}
~DivPlatformGenesis();
};
#endif

View file

@ -248,6 +248,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
if (chan[i].freq<0) chan[i].freq=0;
if (chan[i].freq>65535) chan[i].freq=65535;
int freqt=toFreq(chan[i].freq);
if (freqt>2047) freqt=2047;
chan[i].freqL=freqt&0xff;
if (i>=6 && properDrums && (i<9 || !noTopHatFreq)) {
immWrite(0x10+drumSlot[i],freqt&0xff);
@ -257,7 +258,7 @@ void DivPlatformOPLL::tick(bool sysTick) {
immWrite(0x10+i,freqt&0xff);
}
}
chan[i].freqH=freqt>>8;
chan[i].freqH=(freqt>>8)&15;
}
if (chan[i].keyOn && i>=6 && properDrums) {
if (!isMuted[i]) {

View file

@ -455,6 +455,7 @@ void DivPlatformPOKEY::setFlags(const DivConfig& flags) {
oscBuf[i]->rate=rate/2;
}
altASAP.init(chipClock,rate);
altASAP.reset();
} else {
rate=chipClock;
for (int i=0; i<4; i++) {

View file

@ -607,10 +607,23 @@ void DivPlatformSNES::writeEnv(int ch) {
if (chan[ch].state.sus) {
if (chan[ch].active) {
chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80);
chWrite(ch,6,chan[ch].state.s<<5);
} else { // dec linear
chWrite(ch,7,0x80|chan[ch].state.r);
chWrite(ch,5,0);
chWrite(ch,6,(chan[ch].state.s<<5)|(chan[ch].state.d2&31));
} else {
switch (chan[ch].state.sus) {
case 1: // dec linear
chWrite(ch,7,0x80|chan[ch].state.r);
chWrite(ch,5,0);
break;
case 2: // dec exp
chWrite(ch,7,0xa0|chan[ch].state.r);
chWrite(ch,5,0);
break;
case 3: // update r
chWrite(ch,6,(chan[ch].state.s<<5)|(chan[ch].state.r&31));
break;
default: // what?
break;
}
}
} else {
chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80);

View file

@ -157,6 +157,80 @@ const char** DivPlatformYM2203::getRegisterSheet() {
}
void DivPlatformYM2203::acquire(short* bufL, short* bufR, size_t start, size_t len) {
if (useCombo) {
acquire_combo(bufL,bufR,start,len);
} else {
acquire_ymfm(bufL,bufR,start,len);
}
}
void DivPlatformYM2203::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
static int os;
static short ignored[2];
for (size_t h=start; h<start+len; h++) {
os=0;
// Nuked part
for (unsigned int i=0; i<nukedMult; i++) {
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
if (w.addr<=0x1c || w.addr==0x2d || w.addr==0x2e || w.addr==0x2f) {
// ymfm write
fm->write(0x0,w.addr);
fm->write(0x1,w.val);
regPool[w.addr&0xff]=w.val;
writes.pop_front();
delay=1;
} else {
// Nuked write
if (w.addrOrVal) {
OPN2_Write(&fm_nuked,0x1,w.val);
regPool[w.addr&0xff]=w.val;
writes.pop_front();
} else {
lastBusy++;
if (fm_nuked.write_busy==0) {
OPN2_Write(&fm_nuked,0x0,w.addr);
w.addrOrVal=true;
}
}
}
}
}
OPN2_Clock(&fm_nuked,ignored);
}
os=(
(fm_nuked.ch_out[0])+
(fm_nuked.ch_out[1])+
(fm_nuked.ch_out[2])
);
os&=~3;
// ymfm part
fm->generate(&fmout);
os+=((fmout.data[1]+fmout.data[2]+fmout.data[3])>>1);
if (os<-32768) os=-32768;
if (os>32767) os=32767;
bufL[h]=os;
for (int i=0; i<3; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
}
for (int i=3; i<6; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2];
}
}
}
void DivPlatformYM2203::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os;
ymfm::ym2203::fm_engine* fme=fm->debug_fm_engine();
@ -857,6 +931,8 @@ void DivPlatformYM2203::reset() {
if (dumpWrites) {
addWrite(0xffffffff,0);
}
OPN2_Reset(&fm_nuked);
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
fm->reset();
for (int i=0; i<6; i++) {
chan[i]=DivPlatformOPN::OPNChannel();
@ -946,18 +1022,21 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) {
fmFreqBase=4720270.0/2.0,
fmDivBase=18,
ayDiv=8;
nukedMult=16;
break;
case 0x02: // /2
prescale=0x2f;
fmFreqBase=4720270.0/3.0,
fmDivBase=12,
ayDiv=4;
nukedMult=24;
break;
default: // /6
prescale=0x2d;
fmFreqBase=4720270.0,
fmDivBase=36,
ayDiv=16;
nukedMult=8;
break;
}
CHECK_CUSTOM_CLOCK;

View file

@ -42,6 +42,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
OPNChannel chan[6];
DivDispatchOscBuffer* oscBuf[6];
bool isMuted[6];
ym3438_t fm_nuked;
ymfm::ym2203* fm;
ymfm::ym2203::output_data fmout;
DivYM2203Interface iface;
@ -50,9 +51,13 @@ class DivPlatformYM2203: public DivPlatformOPN {
unsigned char sampleBank;
bool extMode, noExtMacros;
unsigned char prescale;
unsigned char prescale, nukedMult;
friend void putDispatchChip(void*,int);
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c);
@ -77,7 +82,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
DivPlatformYM2203():
DivPlatformOPN(4720270.0, 36, 16),
DivPlatformOPN(2, 3, 6, 6, 6, 4720270.0, 36, 16),
prescale(0x2d) {}
~DivPlatformYM2203();
};

View file

@ -298,6 +298,116 @@ double DivPlatformYM2608::NOTE_ADPCMB(int note) {
}
void DivPlatformYM2608::acquire(short* bufL, short* bufR, size_t start, size_t len) {
if (useCombo) {
acquire_combo(bufL,bufR,start,len);
} else {
acquire_ymfm(bufL,bufR,start,len);
}
}
void DivPlatformYM2608::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
static short ignored[2];
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut;
ymfm::adpcm_a_channel* adpcmAChan[6];
for (int i=0; i<6; i++) {
adpcmAChan[i]=aae->debug_channel(i);
}
for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0;
// Nuked part
for (int i=0; i<nukedMult; i++) {
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
if (w.addr<=0x1c || w.addr==0x2d || w.addr==0x2e || w.addr==0x2f || (w.addr>=0x100 && w.addr<=0x12d)) {
// ymfm write
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
delay=1;
} else {
// Nuked write
if (w.addrOrVal) {
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
} else {
lastBusy++;
if (fm_nuked.write_busy==0) {
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
w.addrOrVal=true;
}
}
}
}
}
OPN2_Clock(&fm_nuked,ignored);
}
os[0]=(
(fm_nuked.pan_l[0]?fm_nuked.ch_out[0]:0)+
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_l[3]?fm_nuked.ch_out[3]:0)+
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
);
os[1]=(
(fm_nuked.pan_r[0]?fm_nuked.ch_out[0]:0)+
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_r[3]?fm_nuked.ch_out[3]:0)+
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
);
os[0]>>=1;
os[1]>>=1;
// ymfm part
fm->generate(&fmout);
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767;
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
if (os[1]<-32768) os[1]=-32768;
if (os[1]>32767) os[1]=32767;
bufL[h]=os[0];
bufR[h]=os[1];
for (int i=0; i<psgChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
}
ssge->get_last_out(ssgOut);
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
}
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
}
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
}
}
void DivPlatformYM2608::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
ymfm::ym2608::fm_engine* fme=fm->debug_fm_engine();
@ -1256,6 +1366,8 @@ void DivPlatformYM2608::reset() {
if (dumpWrites) {
addWrite(0xffffffff,0);
}
OPN2_Reset(&fm_nuked);
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
fm->reset();
for (int i=0; i<16; i++) {
chan[i]=DivPlatformOPN::OPNChannelStereo();
@ -1407,18 +1519,21 @@ void DivPlatformYM2608::setFlags(const DivConfig& flags) {
fmFreqBase=9440540.0/2.0,
fmDivBase=36,
ayDiv=16;
nukedMult=16;
break;
case 0x02: // /2
prescale=0x2f;
fmFreqBase=9440540.0/3.0,
fmDivBase=24,
ayDiv=8;
nukedMult=24;
break;
default: // /6
prescale=0x2d;
fmFreqBase=9440540.0,
fmDivBase=72,
ayDiv=32;
nukedMult=8;
break;
}
CHECK_CUSTOM_CLOCK;

View file

@ -47,6 +47,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
OPNChannelStereo chan[16];
DivDispatchOscBuffer* oscBuf[16];
bool isMuted[16];
ym3438_t fm_nuked;
ymfm::ym2608* fm;
ymfm::ym2608::output_data fmout;
@ -62,12 +63,16 @@ class DivPlatformYM2608: public DivPlatformOPN {
int globalRSSVolume;
bool extMode, noExtMacros;
unsigned char prescale;
unsigned char prescale, nukedMult;
double NOTE_OPNB(int ch, int note);
double NOTE_ADPCMB(int note);
friend void putDispatchChip(void*,int);
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c);
@ -97,7 +102,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
DivPlatformYM2608():
DivPlatformOPN(9440540.0, 72, 32),
DivPlatformOPN(2, 6, 9, 15, 16, 9440540.0, 72, 32),
prescale(0x2d) {}
~DivPlatformYM2608();
};

View file

@ -233,6 +233,112 @@ const char** DivPlatformYM2610::getRegisterSheet() {
}
void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t len) {
if (useCombo) {
acquire_combo(bufL,bufR,start,len);
} else {
acquire_ymfm(bufL,bufR,start,len);
}
}
void DivPlatformYM2610::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
static short ignored[2];
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut;
ymfm::adpcm_a_channel* adpcmAChan[6];
for (int i=0; i<6; i++) {
adpcmAChan[i]=aae->debug_channel(i);
}
for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0;
// Nuked part
for (int i=0; i<24; i++) {
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
if (w.addr<=0x1c || (w.addr>=0x100 && w.addr<=0x12d)) {
// ymfm write
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
delay=32;
} else {
// Nuked write
if (w.addrOrVal) {
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
} else {
lastBusy++;
if (fm_nuked.write_busy==0) {
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
w.addrOrVal=true;
}
}
}
}
}
OPN2_Clock(&fm_nuked,ignored);
}
os[0]=(
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
);
os[1]=(
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
);
os[0]>>=1;
os[1]>>=1;
// ymfm part
fm->generate(&fmout);
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767;
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
if (os[1]<-32768) os[1]=-32768;
if (os[1]>32767) os[1]=32767;
bufL[h]=os[0];
bufR[h]=os[1];
for (int i=0; i<psgChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[bchOffs[i]];
}
ssge->get_last_out(ssgOut);
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
}
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
}
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
}
}
void DivPlatformYM2610::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
ymfm::ym2610::fm_engine* fme=fm->debug_fm_engine();
@ -254,13 +360,13 @@ void DivPlatformYM2610::acquire(short* bufL, short* bufR, size_t start, size_t l
for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0;
if (!writes.empty()) {
if (--delay<1) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
delay=4;
delay=1;
}
}
@ -1275,7 +1381,7 @@ bool DivPlatformYM2610::keyOffAffectsArp(int ch) {
}
void DivPlatformYM2610::notifyInsChange(int ins) {
for (int i=0; i<chanNum; i++) {
for (int i=0; i<16; i++) {
if (chan[i].ins==ins) {
chan[i].insChanged=true;
}

View file

@ -22,7 +22,7 @@
#include "ym2610shared.h"
class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
class DivPlatformYM2610: public DivPlatformYM2610Base {
protected:
const unsigned short chanOffs[4]={
0x01, 0x02, 0x101, 0x102
@ -37,6 +37,10 @@ class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
};
friend void putDispatchChip(void*,int);
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c);
@ -60,7 +64,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base<14> {
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
DivPlatformYM2610():
DivPlatformYM2610Base<14>(1,4,7,13) {}
DivPlatformYM2610Base(1,4,7,13,14) {}
~DivPlatformYM2610();
};
#endif

View file

@ -297,6 +297,116 @@ const char** DivPlatformYM2610B::getRegisterSheet() {
}
void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t len) {
if (useCombo) {
acquire_combo(bufL,bufR,start,len);
} else {
acquire_ymfm(bufL,bufR,start,len);
}
}
void DivPlatformYM2610B::acquire_combo(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
static short ignored[2];
ymfm::ssg_engine* ssge=fm->debug_ssg_engine();
ymfm::adpcm_a_engine* aae=fm->debug_adpcm_a_engine();
ymfm::adpcm_b_engine* abe=fm->debug_adpcm_b_engine();
ymfm::ssg_engine::output_data ssgOut;
ymfm::adpcm_a_channel* adpcmAChan[6];
for (int i=0; i<6; i++) {
adpcmAChan[i]=aae->debug_channel(i);
}
for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0;
// Nuked part
for (int i=0; i<24; i++) {
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
if (w.addr<=0x1c || (w.addr>=0x100 && w.addr<=0x12d)) {
// ymfm write
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
delay=32;
} else {
// Nuked write
if (w.addrOrVal) {
OPN2_Write(&fm_nuked,0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
} else {
lastBusy++;
if (fm_nuked.write_busy==0) {
OPN2_Write(&fm_nuked,0x0+((w.addr>>8)<<1),w.addr);
w.addrOrVal=true;
}
}
}
}
}
OPN2_Clock(&fm_nuked,ignored);
}
os[0]=(
(fm_nuked.pan_l[0]?fm_nuked.ch_out[0]:0)+
(fm_nuked.pan_l[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_l[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_l[3]?fm_nuked.ch_out[3]:0)+
(fm_nuked.pan_l[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_l[5]?fm_nuked.ch_out[5]:0)
);
os[1]=(
(fm_nuked.pan_r[0]?fm_nuked.ch_out[0]:0)+
(fm_nuked.pan_r[1]?fm_nuked.ch_out[1]:0)+
(fm_nuked.pan_r[2]?fm_nuked.ch_out[2]:0)+
(fm_nuked.pan_r[3]?fm_nuked.ch_out[3]:0)+
(fm_nuked.pan_r[4]?fm_nuked.ch_out[4]:0)+
(fm_nuked.pan_r[5]?fm_nuked.ch_out[5]:0)
);
os[0]>>=1;
os[1]>>=1;
// ymfm part
fm->generate(&fmout);
os[0]+=fmout.data[0]+(fmout.data[2]>>1);
if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767;
os[1]+=fmout.data[1]+(fmout.data[2]>>1);
if (os[1]<-32768) os[1]=-32768;
if (os[1]>32767) os[1]=32767;
bufL[h]=os[0];
bufR[h]=os[1];
for (int i=0; i<psgChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=fm_nuked.ch_out[i];
}
ssge->get_last_out(ssgOut);
for (int i=psgChanOffs; i<adpcmAChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-psgChanOffs];
}
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
oscBuf[i]->data[oscBuf[i]->needle++]=adpcmAChan[i-adpcmAChanOffs]->get_last_out(0)+adpcmAChan[i-adpcmAChanOffs]->get_last_out(1);
}
oscBuf[adpcmBChanOffs]->data[oscBuf[adpcmBChanOffs]->needle++]=abe->get_last_out(0)+abe->get_last_out(1);
}
}
void DivPlatformYM2610B::acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len) {
static int os[2];
ymfm::ym2610b::fm_engine* fme=fm->debug_fm_engine();
@ -316,13 +426,13 @@ void DivPlatformYM2610B::acquire(short* bufL, short* bufR, size_t start, size_t
for (size_t h=start; h<start+len; h++) {
os[0]=0; os[1]=0;
if (!writes.empty()) {
if (--delay<1) {
if (--delay<1 && !(fm->read(0)&0x80)) {
QueuedWrite& w=writes.front();
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
writes.pop_front();
delay=4;
delay=1;
}
}
@ -1342,7 +1452,7 @@ bool DivPlatformYM2610B::keyOffAffectsArp(int ch) {
}
void DivPlatformYM2610B::notifyInsChange(int ins) {
for (int i=0; i<chanNum; i++) {
for (int i=0; i<16; i++) {
if (chan[i].ins==ins) {
chan[i].insChanged=true;
}

View file

@ -22,7 +22,7 @@
#include "ym2610shared.h"
class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
class DivPlatformYM2610B: public DivPlatformYM2610Base {
protected:
const unsigned short chanOffs[6]={
0x00, 0x01, 0x02, 0x100, 0x101, 0x102
@ -33,6 +33,10 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
};
friend void putDispatchChip(void*,int);
void acquire_combo(short* bufL, short* bufR, size_t start, size_t len);
void acquire_ymfm(short* bufL, short* bufR, size_t start, size_t len);
public:
void acquire(short* bufL, short* bufR, size_t start, size_t len);
int dispatch(DivCommand c);
@ -56,7 +60,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base<16> {
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
void quit();
DivPlatformYM2610B():
DivPlatformYM2610Base<16>(2,6,9,15) {}
DivPlatformYM2610Base(2,6,9,15,16) {}
~DivPlatformYM2610B();
};
#endif

View file

@ -44,12 +44,13 @@ class DivYM2610Interface: public ymfm::ymfm_interface {
sampleBank(0) {}
};
template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
class DivPlatformYM2610Base: public DivPlatformOPN {
protected:
OPNChannelStereo chan[ChanNum];
DivDispatchOscBuffer* oscBuf[ChanNum];
bool isMuted[ChanNum];
OPNChannelStereo chan[16];
DivDispatchOscBuffer* oscBuf[16];
bool isMuted[16];
ym3438_t fm_nuked;
ymfm::ym2610b* fm;
ymfm::ym2610b::output_data fmout;
DivPlatformAY8910* ay;
@ -72,9 +73,6 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
unsigned char writeADPCMAOff, writeADPCMAOn;
int globalADPCMAVolume;
const int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs;
const int chanNum=ChanNum;
double NOTE_OPNB(int ch, int note) {
if (ch>=adpcmBChanOffs) { // ADPCM
return NOTE_ADPCMB(note);
@ -98,6 +96,9 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
writeADPCMAOn=0;
globalADPCMAVolume=0x3f;
OPN2_Reset(&fm_nuked);
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
ay->reset();
ay->getRegisterWrites().clear();
ay->flushWrites();
@ -220,8 +221,8 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
}
CHECK_CUSTOM_CLOCK;
noExtMacros=flags.getBool("noExtMacros",false);
rate=chipClock/16;
for (int i=0; i<ChanNum; i++) {
rate=fm->sample_rate(chipClock);
for (int i=0; i<16; i++) {
oscBuf[i]->rate=rate;
}
}
@ -231,7 +232,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
ayFlags.set("chipType",1);
dumpWrites=false;
skipRegisterWrites=false;
for (int i=0; i<ChanNum; i++) {
for (int i=0; i<16; i++) {
isMuted[i]=false;
oscBuf[i]=new DivDispatchOscBuffer;
}
@ -243,7 +244,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
iface.adpcmBMem=adpcmBMem;
iface.sampleBank=0;
fm=new ymfm::ym2610b(iface);
fm->set_fidelity(ymfm::OPN_FIDELITY_MAX);
fm->set_fidelity(ymfm::OPN_FIDELITY_MED);
setFlags(flags);
// YM2149, 2MHz
ay=new DivPlatformAY8910(true,chipClock,32);
@ -253,7 +254,7 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
}
void quit() {
for (int i=0; i<ChanNum; i++) {
for (int i=0; i<16; i++) {
delete oscBuf[i];
}
ay->quit();
@ -262,12 +263,8 @@ template<int ChanNum> class DivPlatformYM2610Base: public DivPlatformOPN {
delete[] adpcmBMem;
}
DivPlatformYM2610Base(int ext, int psg, int adpcmA, int adpcmB):
DivPlatformOPN(9440540.0, 72, 32),
extChanOffs(ext),
psgChanOffs(psg),
adpcmAChanOffs(adpcmA),
adpcmBChanOffs(adpcmB) {}
DivPlatformYM2610Base(int ext, int psg, int adpcmA, int adpcmB, int chanCount):
DivPlatformOPN(ext,psg,adpcmA,adpcmB,chanCount,9440540.0, 72, 32) {}
};
#endif