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

This commit is contained in:
cam900 2022-03-18 03:20:33 +09:00
commit a7c750a44e
6 changed files with 268 additions and 114 deletions

View file

@ -105,7 +105,7 @@ struct DivInstrumentFM {
fb(0),
fms(0),
ams(0),
ops(4),
ops(2),
opllPreset(0),
fixedDrums(false),
kickFreq(0x520),
@ -115,11 +115,12 @@ struct DivInstrumentFM {
fb=4;
op[0].tl=42;
op[0].ar=31;
op[0].dr=8;
op[0].dr=2;
op[0].sl=15;
op[0].rr=3;
op[0].mult=5;
op[0].dt=5;
op[0].rs=3;
op[2].tl=18;
op[2].ar=31;
@ -129,13 +130,14 @@ struct DivInstrumentFM {
op[2].mult=1;
op[2].dt=0;
op[1].tl=48;
op[1].tl=64;
op[1].ar=31;
op[1].dr=4;
op[1].dr=2;
op[1].sl=11;
op[1].rr=1;
op[1].rr=8;
op[1].mult=1;
op[1].dt=5;
op[1].rs=2;
op[3].tl=2;
op[3].ar=31;

View file

@ -48,6 +48,10 @@ const unsigned short chanMapOPL2[20]={
0, 1, 2, 3, 4, 5, 6, 7, 8, N, N, N, N, N, N, N, N, N, N, N
};
const unsigned short chanMapOPL2Drums[20]={
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 7, N, N, N, N, N, N, N, N, N
};
const unsigned char* slotsOPL2[4]={
slotsOPL2i[0],
slotsOPL2i[1],
@ -71,7 +75,7 @@ const unsigned char slotsOPL3i[4][20]={
const unsigned char slotsOPL3Drumsi[4][20]={
{0, 6, 1, 7, 2, 8, 18, 24, 19, 25, 20, 26, 30, 31, 32, 12, 16, 14, 17, 13}, // OP1
{3, 9, 4, 10, 5, 11, 21, 27, 22, 28, 23, 29, 33, 34, 35, N, N, N, N, N}, // OP2
{3, 9, 4, 10, 5, 11, 21, 27, 22, 28, 23, 29, 33, 34, 35, 15, N, N, N, N}, // OP2
{6, N, 7, N, 8, N, 24, N, 25, N, 26, N, N, N, N, N, N, N, N, N}, // OP3
{9, N, 10, N, 11, N, 27, N, 28, N, 29, N, N, N, N, N, N, N, N, N} // OP4
};
@ -80,6 +84,10 @@ const unsigned short chanMapOPL3[20]={
0, 3, 1, 4, 2, 5, 0x100, 0x103, 0x101, 0x104, 0x102, 0x105, 0x106, 0x107, 0x108, 6, 7, 8, N, N
};
const unsigned short chanMapOPL3Drums[20]={
0, 3, 1, 4, 2, 5, 0x100, 0x103, 0x101, 0x104, 0x102, 0x105, 0x106, 0x107, 0x108, 6, 7, 8, 8, 7
};
const unsigned char* slotsOPL3[4]={
slotsOPL3i[0],
slotsOPL3i[1],
@ -224,7 +232,7 @@ void DivPlatformOPL::acquire(short* bufL, short* bufR, size_t start, size_t len)
}
void DivPlatformOPL::tick() {
for (int i=0; i<melodicChans; i++) {
for (int i=0; i<totalChans; i++) {
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
chan[i].std.next();
@ -266,7 +274,6 @@ void DivPlatformOPL::tick() {
if (chan[i].std.hadAlg) {
chan[i].state.alg=chan[i].std.alg;
}
if (chan[i].std.hadFb) {
chan[i].state.fb=chan[i].std.fb;
@ -356,9 +363,11 @@ void DivPlatformOPL::tick() {
}
}
if (chan[i].keyOn || chan[i].keyOff) {
immWrite(chanMap[i]+ADDR_FREQH,0x00|(chan[i].freqH&31));
chan[i].keyOff=false;
if (i<melodicChans) {
if (chan[i].keyOn || chan[i].keyOff) {
immWrite(chanMap[i]+ADDR_FREQH,0x00|(chan[i].freqH&31));
chan[i].keyOff=false;
}
}
}
@ -371,6 +380,22 @@ void DivPlatformOPL::tick() {
}
}
// update drums
if (properDrums) {
bool updateDrums=false;
for (int i=melodicChans; i<totalChans; i++) {
if (chan[i].keyOn || chan[i].keyOff) {
drumState&=~(1<<(totalChans-i-1));
updateDrums=true;
chan[i].keyOff=false;
}
}
if (updateDrums) {
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
}
}
for (int i=0; i<512; i++) {
if (pendingWrites[i]!=oldWrites[i]) {
immWrite(i,pendingWrites[i]&0xff);
@ -378,7 +403,8 @@ void DivPlatformOPL::tick() {
}
}
for (int i=0; i<melodicChans; i++) {
bool updateDrums=false;
for (int i=0; i<totalChans; i++) {
if (chan[i].freqChanged) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,false,octave(chan[i].baseFreq));
if (chan[i].freq>131071) chan[i].freq=131071;
@ -387,14 +413,29 @@ void DivPlatformOPL::tick() {
chan[i].freqL=freqt&0xff;
immWrite(chanMap[i]+ADDR_FREQ,chan[i].freqL);
}
if (chan[i].keyOn) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(0x20));
chan[i].keyOn=false;
} else if (chan[i].freqChanged) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(chan[i].active<<5));
if (i<melodicChans) {
if (chan[i].keyOn) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(0x20));
chan[i].keyOn=false;
} else if (chan[i].freqChanged) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH|(chan[i].active<<5));
}
} else {
if (chan[i].keyOn) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH);
drumState|=(1<<(totalChans-i-1));
updateDrums=true;
chan[i].keyOn=false;
} else if (chan[i].freqChanged) {
immWrite(chanMap[i]+ADDR_FREQH,chan[i].freqH);
}
}
chan[i].freqChanged=false;
}
if (updateDrums) {
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
}
}
#define OPLL_C_NUM 686
@ -476,8 +517,7 @@ void DivPlatformOPL::muteChannel(int ch, bool mute) {
}
int DivPlatformOPL::dispatch(DivCommand c) {
// TODO: drums mode!
if (c.chan>=melodicChans) return 0;
if (c.chan>=totalChans) return 0;
// 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 (chan[c.chan-1].fourOp) return 0;
@ -542,7 +582,19 @@ int DivPlatformOPL::dispatch(DivCommand c) {
chan[c.chan].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
if (c.chan>=melodicChans && chan[c.chan].state.opllPreset==16 && chan[c.chan].state.fixedDrums) { // drums
if (c.chan==melodicChans) {
chan[c.chan].baseFreq=(chan[c.chan].state.kickFreq&1023)<<(chan[c.chan].state.kickFreq>>10);
} else if (c.chan==melodicChans+1 || c.chan==melodicChans+4) {
chan[c.chan].baseFreq=(chan[c.chan].state.snareHatFreq&1023)<<(chan[c.chan].state.snareHatFreq>>10);
} else if (c.chan==melodicChans+2 || c.chan==melodicChans+3) {
chan[c.chan].baseFreq=(chan[c.chan].state.tomTopFreq&1023)<<(chan[c.chan].state.tomTopFreq>>10);
} else {
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
}
} else {
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
}
chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true;
}
@ -748,8 +800,19 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break;
}
case DIV_CMD_FM_EXTCH: {
if (!properDrumsSys) break;
properDrums=c.value;
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
slots=properDrums?slotsDrums:slotsNonDrums;
if (oplType==3) {
chanMap=properDrums?chanMapOPL3Drums:chanMapOPL3;
melodicChans=properDrums?15:18;
totalChans=properDrums?20:18;
} else {
chanMap=properDrums?chanMapOPL2Drums:chanMapOPL2;
melodicChans=properDrums?6:9;
totalChans=properDrums?11:9;
}
break;
}
case DIV_ALWAYS_SET_VOLUME:
@ -772,7 +835,16 @@ int DivPlatformOPL::dispatch(DivCommand c) {
}
void DivPlatformOPL::forceIns() {
for (int i=0; i<melodicChans; i++) {
if (oplType==3) {
chanMap=properDrums?chanMapOPL3Drums:chanMapOPL3;
melodicChans=properDrums?15:18;
totalChans=properDrums?20:18;
} else {
chanMap=properDrums?chanMapOPL2Drums:chanMapOPL2;
melodicChans=properDrums?6:9;
totalChans=properDrums?11:9;
}
for (int i=0; i<totalChans; i++) {
int ops=(slots[3][i]!=255 && chan[i].state.ops==4 && oplType==3)?4:2;
chan[i].insChanged=true;
chan[i].freqChanged=true;
@ -845,6 +917,18 @@ void DivPlatformOPL::reset() {
if (dumpWrites) {
addWrite(0xffffffff,0);
}
properDrums=properDrumsSys;
if (oplType==3) {
chanMap=properDrums?chanMapOPL3Drums:chanMapOPL3;
melodicChans=properDrums?15:18;
totalChans=properDrums?20:18;
} else {
chanMap=properDrums?chanMapOPL2Drums:chanMapOPL2;
melodicChans=properDrums?6:9;
totalChans=properDrums?11:9;
}
for (int i=0; i<totalChans; i++) {
chan[i]=DivPlatformOPL::Channel();
chan[i].vol=0x3f;
@ -858,7 +942,6 @@ void DivPlatformOPL::reset() {
lastBusy=60;
lfoValue=8;
properDrums=properDrumsSys;
drumState=0;
drumVol[0]=0;
@ -879,6 +962,8 @@ void DivPlatformOPL::reset() {
dam=false;
dvb=false;
delay=0;
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
}
bool DivPlatformOPL::isStereo() {
@ -927,7 +1012,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
slotsNonDrums=slotsOPL2;
slotsDrums=slotsOPL2Drums;
slots=drums?slotsDrums:slotsNonDrums;
chanMap=chanMapOPL2;
chanMap=drums?chanMapOPL2Drums:chanMapOPL2;
chipFreqBase=9440540*0.25;
chans=9;
melodicChans=drums?6:9;
@ -937,7 +1022,7 @@ void DivPlatformOPL::setOPLType(int type, bool drums) {
slotsNonDrums=slotsOPL3;
slotsDrums=slotsOPL3Drums;
slots=drums?slotsDrums:slotsNonDrums;
chanMap=chanMapOPL3;
chanMap=drums?chanMapOPL3Drums:chanMapOPL3;
chipFreqBase=9440540;
chans=18;
melodicChans=drums?15:18;
@ -997,7 +1082,7 @@ int DivPlatformOPL::init(DivEngine* p, int channels, int sugRate, unsigned int f
setFlags(flags);
reset();
return 10;
return totalChans;
}
void DivPlatformOPL::quit() {