add Y8950 system

This commit is contained in:
tildearrow 2022-05-13 16:52:44 -05:00
parent 4a563a416e
commit 7218710268
6 changed files with 225 additions and 15 deletions

View file

@ -273,6 +273,14 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
dispatch=new DivPlatformOPL; dispatch=new DivPlatformOPL;
((DivPlatformOPL*)dispatch)->setOPLType(3,true); ((DivPlatformOPL*)dispatch)->setOPLType(3,true);
break; break;
case DIV_SYSTEM_Y8950:
dispatch=new DivPlatformOPL;
((DivPlatformOPL*)dispatch)->setOPLType(8950,false);
break;
case DIV_SYSTEM_Y8950_DRUMS:
dispatch=new DivPlatformOPL;
((DivPlatformOPL*)dispatch)->setOPLType(8950,true);
break;
case DIV_SYSTEM_OPZ: case DIV_SYSTEM_OPZ:
dispatch=new DivPlatformTX81Z; dispatch=new DivPlatformTX81Z;
break; break;

View file

@ -286,7 +286,8 @@ void DivPlatformOPL::acquire_nuked(short* bufL, short* bufR, size_t start, size_
adpcmB->output<2>(aOut,0); adpcmB->output<2>(aOut,0);
os[0]+=aOut.data[0]; os[0]+=aOut.data[0];
os[1]+=aOut.data[1]; os[1]+=aOut.data[0];
oscBuf[adpcmChan]->data[oscBuf[adpcmChan]->needle++]+=aOut.data[0];
} }
for (int i=0; i<chans; i++) { for (int i=0; i<chans; i++) {
@ -322,6 +323,15 @@ void DivPlatformOPL::acquire(short* bufL, short* bufR, size_t start, size_t len)
//} //}
} }
double DivPlatformOPL::NOTE_ADPCMB(int note) {
if (adpcmChan<0) return 0;
if (chan[adpcmChan].sample>=0 && chan[adpcmChan].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmChan].sample)->centerRate)/8363.0;
return parent->calcBaseFreq((double)chipClock/144,off,note,false);
}
return 0;
}
void DivPlatformOPL::tick(bool sysTick) { void DivPlatformOPL::tick(bool sysTick) {
for (int i=0; i<totalChans; i++) { for (int i=0; i<totalChans; i++) {
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
@ -531,6 +541,45 @@ void DivPlatformOPL::tick(bool sysTick) {
} }
} }
// ADPCM
if (adpcmChan>=0) {
if (chan[adpcmChan].furnacePCM) {
chan[adpcmChan].std.next();
if (chan[adpcmChan].std.vol.had) {
chan[adpcmChan].outVol=(chan[adpcmChan].vol*MIN(64,chan[adpcmChan].std.vol.val))/64;
immWrite(18,chan[adpcmChan].outVol);
}
if (chan[adpcmChan].std.arp.had) {
if (!chan[adpcmChan].inPorta) {
if (chan[adpcmChan].std.arp.mode) {
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].std.arp.val);
} else {
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].note+(signed char)chan[adpcmChan].std.arp.val);
}
}
chan[adpcmChan].freqChanged=true;
} else {
if (chan[adpcmChan].std.arp.mode && chan[adpcmChan].std.arp.finished) {
chan[adpcmChan].baseFreq=NOTE_ADPCMB(chan[adpcmChan].note);
chan[adpcmChan].freqChanged=true;
}
}
}
if (chan[adpcmChan].freqChanged) {
if (chan[adpcmChan].sample>=0 && chan[adpcmChan].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmChan].sample)->centerRate)/8363.0;
chan[adpcmChan].freq=parent->calcFreq(chan[adpcmChan].baseFreq,chan[adpcmChan].pitch,false,4,chan[adpcmChan].pitch2,(double)chipClock/144,off);
} else {
chan[adpcmChan].freq=0;
}
immWrite(16,chan[adpcmChan].freq&0xff);
immWrite(17,(chan[adpcmChan].freq>>8)&0xff);
chan[adpcmChan].freqChanged=false;
}
}
for (int i=0; i<512; i++) { for (int i=0; i<512; i++) {
if (pendingWrites[i]!=oldWrites[i]) { if (pendingWrites[i]!=oldWrites[i]) {
immWrite(i,pendingWrites[i]&0xff); immWrite(i,pendingWrites[i]&0xff);
@ -655,13 +704,77 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
} }
int DivPlatformOPL::dispatch(DivCommand c) { int DivPlatformOPL::dispatch(DivCommand c) {
if (c.chan>=totalChans) return 0; if (c.chan>=totalChans && c.chan!=adpcmChan) return 0;
// ineffective in 4-op mode // ineffective in 4-op mode
if (oplType==3 && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX && c.cmd!=DIV_ALWAYS_SET_VOLUME) { if (oplType==3 && c.chan!=adpcmChan && c.chan<14 && (c.chan&1) && c.cmd!=DIV_CMD_GET_VOLMAX && c.cmd!=DIV_ALWAYS_SET_VOLUME) {
if (chan[c.chan-1].fourOp) return 0; if (chan[c.chan-1].fourOp) return 0;
} }
switch (c.cmd) { switch (c.cmd) {
case DIV_CMD_NOTE_ON: { case DIV_CMD_NOTE_ON: {
if (c.chan==adpcmChan) { // ADPCM
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
if (ins->type==DIV_INS_AMIGA) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(18,chan[c.chan].outVol);
}
chan[c.chan].sample=ins->amiga.initSample;
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(9,(s->offB>>2)&0xff);
immWrite(10,(s->offB>>10)&0xff);
int end=s->offB+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
immWrite(8,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|2);
immWrite(7,(s->loopStart>=0)?0xb0:0xa0); // start/repeat
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
immWrite(7,0x01); // reset
immWrite(9,0);
immWrite(10,0);
immWrite(11,0);
immWrite(12,0);
break;
}
} else {
chan[c.chan].sample=-1;
chan[c.chan].macroInit(NULL);
chan[c.chan].outVol=chan[c.chan].vol;
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
immWrite(7,0x01); // reset
immWrite(9,0);
immWrite(10,0);
immWrite(11,0);
immWrite(12,0);
break;
}
DivSample* s=parent->getSample(12*sampleBank+c.value%12);
immWrite(9,(s->offB>>2)&0xff);
immWrite(10,(s->offB>>10)&0xff);
int end=s->offB+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
immWrite(8,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
immWrite(7,(s->loopStart>=0)?0x90:0x80); // start/repeat
chan[c.chan].baseFreq=(((unsigned int)s->rate)<<16)/(chipClock/144);
chan[c.chan].freqChanged=true;
}
break;
}
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL); DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL);
if (chan[c.chan].insChanged) { if (chan[c.chan].insChanged) {
@ -744,11 +857,19 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_OFF: case DIV_CMD_NOTE_OFF:
if (c.chan==adpcmChan) {
immWrite(7,0x01); // reset
break;
}
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
chan[c.chan].active=false; chan[c.chan].active=false;
break; break;
case DIV_CMD_NOTE_OFF_ENV: case DIV_CMD_NOTE_OFF_ENV:
if (c.chan==adpcmChan) {
immWrite(7,0x01); // reset
break;
}
chan[c.chan].keyOff=true; chan[c.chan].keyOff=true;
chan[c.chan].keyOn=false; chan[c.chan].keyOn=false;
chan[c.chan].active=false; chan[c.chan].active=false;
@ -758,7 +879,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
chan[c.chan].std.release(); chan[c.chan].std.release();
break; break;
case DIV_CMD_VOLUME: { case DIV_CMD_VOLUME: {
if (pretendYMU) { if (pretendYMU && c.chan!=adpcmChan) {
c.value=pow(((double)c.value/127.0),0.5)*63.0; c.value=pow(((double)c.value/127.0),0.5)*63.0;
if (c.value<0) c.value=0; if (c.value<0) c.value=0;
if (c.value>63) c.value=63; if (c.value>63) c.value=63;
@ -767,6 +888,10 @@ int DivPlatformOPL::dispatch(DivCommand c) {
if (!chan[c.chan].std.vol.has) { if (!chan[c.chan].std.vol.has) {
chan[c.chan].outVol=c.value; chan[c.chan].outVol=c.value;
} }
if (c.chan==adpcmChan) { // ADPCM-B
immWrite(18,chan[c.chan].outVol);
break;
}
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
unsigned char slot=slots[i][c.chan]; unsigned char slot=slots[i][c.chan];
@ -787,7 +912,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_GET_VOLUME: { case DIV_CMD_GET_VOLUME: {
if (pretendYMU) { if (pretendYMU && c.chan!=adpcmChan) {
return pow(((double)chan[c.chan].vol/63.0),2.0)*127.0; return pow(((double)chan[c.chan].vol/63.0),2.0)*127.0;
} }
return chan[c.chan].vol; return chan[c.chan].vol;
@ -801,6 +926,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
case DIV_CMD_PANNING: { case DIV_CMD_PANNING: {
if (oplType!=3) break; if (oplType!=3) break;
if (c.chan==adpcmChan) break;
if (c.value==0 && c.value2==0) { if (c.value==0 && c.value2==0) {
chan[c.chan].pan=3; chan[c.chan].pan=3;
} else { } else {
@ -826,7 +952,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
int destFreq=NOTE_FREQUENCY(c.value2); int destFreq=(c.chan==adpcmChan)?(NOTE_ADPCMB(c.value2)):(NOTE_FREQUENCY(c.value2));
int newFreq; int newFreq;
bool return2=false; bool return2=false;
if (destFreq>chan[c.chan].baseFreq) { if (destFreq>chan[c.chan].baseFreq) {
@ -857,13 +983,22 @@ int DivPlatformOPL::dispatch(DivCommand c) {
} }
break; break;
} }
case DIV_CMD_SAMPLE_BANK:
if (adpcmChan<0) break;
sampleBank=c.value;
if (sampleBank>(int)(parent->song.sample.size()/12)) {
sampleBank=parent->song.sample.size()/12;
}
iface.sampleBank=sampleBank;
break;
case DIV_CMD_LEGATO: { case DIV_CMD_LEGATO: {
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value); chan[c.chan].baseFreq=(c.chan==adpcmChan)?(NOTE_ADPCMB(c.value)):(NOTE_FREQUENCY(c.value));
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
break; break;
} }
case DIV_CMD_FM_LFO: { case DIV_CMD_FM_LFO: {
if (c.chan==adpcmChan) break;
if (c.value&2) { if (c.value&2) {
dvb=c.value&1; dvb=c.value&1;
} else { } else {
@ -873,6 +1008,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_FB: { case DIV_CMD_FM_FB: {
if (c.chan==adpcmChan) break;
chan[c.chan].state.fb=c.value&7; chan[c.chan].state.fb=c.value&7;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (isMuted[c.chan]) { if (isMuted[c.chan]) {
@ -889,6 +1025,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_MULT: { case DIV_CMD_FM_MULT: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value>=ops) break; if (c.value>=ops) break;
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
@ -900,6 +1037,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_TL: { case DIV_CMD_FM_TL: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value>=ops) break; if (c.value>=ops) break;
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
@ -919,6 +1057,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_AR: { case DIV_CMD_FM_AR: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -941,6 +1080,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_DR: { case DIV_CMD_FM_DR: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -963,6 +1103,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_SL: { case DIV_CMD_FM_SL: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -985,6 +1126,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_RR: { case DIV_CMD_FM_RR: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -1007,6 +1149,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_AM: { case DIV_CMD_FM_AM: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -1029,6 +1172,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_VIB: { case DIV_CMD_FM_VIB: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -1051,6 +1195,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_SUS: { case DIV_CMD_FM_SUS: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -1073,6 +1218,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_KSR: { case DIV_CMD_FM_KSR: {
if (c.chan==adpcmChan) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
for (int i=0; i<ops; i++) { for (int i=0; i<ops; i++) {
@ -1095,6 +1241,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_WS: { case DIV_CMD_FM_WS: {
if (c.chan==adpcmChan) break;
if (oplType<2) break; if (oplType<2) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
@ -1118,6 +1265,7 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_RS: { case DIV_CMD_FM_RS: {
if (c.chan==adpcmChan) break;
if (oplType<2) break; if (oplType<2) break;
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
if (c.value<0) { if (c.value<0) {
@ -1173,12 +1321,14 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_FM_HARD_RESET: case DIV_CMD_FM_HARD_RESET:
if (c.chan==adpcmChan) break;
chan[c.chan].hardReset=c.value; chan[c.chan].hardReset=c.value;
break; break;
case DIV_ALWAYS_SET_VOLUME: case DIV_ALWAYS_SET_VOLUME:
return 0; return 0;
break; break;
case DIV_CMD_GET_VOLMAX: case DIV_CMD_GET_VOLMAX:
if (c.chan==adpcmChan) return 255;
if (pretendYMU) return 127; if (pretendYMU) return 127;
return 63; return 63;
break; break;
@ -1267,7 +1417,7 @@ unsigned char* DivPlatformOPL::getRegisterPool() {
} }
int DivPlatformOPL::getRegisterPoolSize() { int DivPlatformOPL::getRegisterPoolSize() {
return 512; return (oplType<3)?256:512;
} }
void DivPlatformOPL::reset() { void DivPlatformOPL::reset() {
@ -1303,6 +1453,21 @@ void DivPlatformOPL::reset() {
chan[i].outVol=0x3f; chan[i].outVol=0x3f;
} }
if (adpcmChan>=0) {
chan[adpcmChan]=DivPlatformOPL::Channel();
chan[adpcmChan].std.setEngine(parent);
chan[adpcmChan].vol=0xff;
chan[adpcmChan].outVol=0xff;
adpcmB->reset();
// volume
immWrite(18,0xff);
// ADPCM limit
immWrite(20,0xff);
immWrite(19,0xff);
}
if (oplType<3) for (int i=0; i<melodicChans; i++) { if (oplType<3) for (int i=0; i<melodicChans; i++) {
fm.channel[outChanMap[i]].muted=isMuted[i]; fm.channel[outChanMap[i]].muted=isMuted[i];
} }
@ -1315,6 +1480,7 @@ void DivPlatformOPL::reset() {
lastBusy=60; lastBusy=60;
lfoValue=8; lfoValue=8;
drumState=0; drumState=0;
sampleBank=0;
drumVol[0]=0; drumVol[0]=0;
drumVol[1]=0; drumVol[1]=0;
@ -1469,7 +1635,7 @@ const void* DivPlatformOPL::getSampleMem(int index) {
} }
size_t DivPlatformOPL::getSampleMemCapacity(int index) { size_t DivPlatformOPL::getSampleMemCapacity(int index) {
return (index==0 && adpcmChan>=0) ? 2097152 : 0; return (index==0 && adpcmChan>=0) ? 262144 : 0;
} }
size_t DivPlatformOPL::getSampleMemUsage(int index) { size_t DivPlatformOPL::getSampleMemUsage(int index) {

View file

@ -40,8 +40,8 @@ class DivPlatformOPL: public DivDispatch {
DivInstrumentFM state; DivInstrumentFM state;
DivMacroInt std; DivMacroInt std;
unsigned char freqH, freqL; unsigned char freqH, freqL;
int freq, baseFreq, pitch, pitch2, note, ins; int freq, baseFreq, pitch, pitch2, note, ins, sample;
bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, fourOp, hardReset; bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnacePCM, inPorta, fourOp, hardReset;
int vol, outVol; int vol, outVol;
unsigned char pan; unsigned char pan;
void macroInit(DivInstrument* which) { void macroInit(DivInstrument* which) {
@ -57,13 +57,14 @@ class DivPlatformOPL: public DivDispatch {
pitch2(0), pitch2(0),
note(0), note(0),
ins(-1), ins(-1),
sample(-1),
active(false), active(false),
insChanged(true), insChanged(true),
freqChanged(false), freqChanged(false),
keyOn(false), keyOn(false),
keyOff(false), keyOff(false),
portaPause(false), portaPause(false),
furnaceDac(false), furnacePCM(false),
inPorta(false), inPorta(false),
fourOp(false), fourOp(false),
hardReset(false), hardReset(false),
@ -94,7 +95,7 @@ class DivPlatformOPL: public DivDispatch {
const unsigned short* chanMap; const unsigned short* chanMap;
const unsigned char* outChanMap; const unsigned char* outChanMap;
double chipFreqBase; double chipFreqBase;
int delay, oplType, chans, melodicChans, totalChans, adpcmChan; int delay, oplType, chans, melodicChans, totalChans, adpcmChan, sampleBank;
unsigned char lastBusy; unsigned char lastBusy;
unsigned char drumState; unsigned char drumState;
unsigned char drumVol[5]; unsigned char drumVol[5];
@ -112,6 +113,7 @@ class DivPlatformOPL: public DivDispatch {
int octave(int freq); int octave(int freq);
int toFreq(int freq); int toFreq(int freq);
double NOTE_ADPCMB(int note);
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);

View file

@ -1736,7 +1736,10 @@ void DivEngine::registerSystems() {
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"}, {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "FM 7", "FM 8", "FM 9", "PCM"},
{"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "PCM"},
{DIV_CH_FM, DIV_CH_FM, 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_FM, DIV_CH_FM, 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_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_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},
{},
oplEffectHandler,
fmOPLPostEffectHandler
); );
sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef( sysDefs[DIV_SYSTEM_Y8950_DRUMS]=new DivSysDef(
@ -1744,7 +1747,10 @@ void DivEngine::registerSystems() {
{"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"}, {"FM 1", "FM 2", "FM 3", "FM 4", "FM 5", "FM 6", "Kick", "Snare", "Tom", "Top", "HiHat", "PCM"},
{"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"}, {"F1", "F2", "F3", "F4", "F5", "F6", "BD", "SD", "TM", "TP", "HH", "PCM"},
{DIV_CH_FM, DIV_CH_FM, 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_FM, DIV_CH_FM, 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_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_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},
{},
oplEffectHandler,
fmOPLPostEffectHandler
); );
sysDefs[DIV_SYSTEM_SCC_PLUS]=new DivSysDef( sysDefs[DIV_SYSTEM_SCC_PLUS]=new DivSysDef(

View file

@ -841,6 +841,8 @@ const int availableSystems[]={
DIV_SYSTEM_VRC7, DIV_SYSTEM_VRC7,
DIV_SYSTEM_OPL, DIV_SYSTEM_OPL,
DIV_SYSTEM_OPL_DRUMS, DIV_SYSTEM_OPL_DRUMS,
DIV_SYSTEM_Y8950,
DIV_SYSTEM_Y8950_DRUMS,
DIV_SYSTEM_OPL2, DIV_SYSTEM_OPL2,
DIV_SYSTEM_OPL2_DRUMS, DIV_SYSTEM_OPL2_DRUMS,
DIV_SYSTEM_OPL3, DIV_SYSTEM_OPL3,

View file

@ -106,6 +106,18 @@ void FurnaceGUI::initSystemPresets() {
0 0
} }
)); ));
cat.systems.push_back(FurnaceGUISysDef(
"Yamaha Y8950", {
DIV_SYSTEM_Y8950, 64, 0, 0,
0
}
));
cat.systems.push_back(FurnaceGUISysDef(
"Yamaha Y8950 (drums mode)", {
DIV_SYSTEM_Y8950_DRUMS, 64, 0, 0,
0
}
));
cat.systems.push_back(FurnaceGUISysDef( cat.systems.push_back(FurnaceGUISysDef(
"Yamaha YM3812", { "Yamaha YM3812", {
DIV_SYSTEM_OPL2, 64, 0, 0, DIV_SYSTEM_OPL2, 64, 0, 0,
@ -411,6 +423,20 @@ void FurnaceGUI::initSystemPresets() {
0 0
} }
)); ));
cat.systems.push_back(FurnaceGUISysDef(
"MSX + MSX-AUDIO", {
DIV_SYSTEM_AY8910, 64, 0, 16,
DIV_SYSTEM_Y8950, 64, 0, 0,
0
}
));
cat.systems.push_back(FurnaceGUISysDef(
"MSX + MSX-AUDIO (drums mode)", {
DIV_SYSTEM_AY8910, 64, 0, 16,
DIV_SYSTEM_Y8950_DRUMS, 64, 0, 0,
0
}
));
cat.systems.push_back(FurnaceGUISysDef( cat.systems.push_back(FurnaceGUISysDef(
"MSX + MSX-MUSIC", { "MSX + MSX-MUSIC", {
DIV_SYSTEM_AY8910, 64, 0, 16, DIV_SYSTEM_AY8910, 64, 0, 16,