mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
parent
050a98d63d
commit
9d10b5bf2b
4 changed files with 163 additions and 54 deletions
|
@ -987,6 +987,9 @@ DivInstrument* DivEngine::getIns(int index, DivInstrumentType fallbackType) {
|
|||
case DIV_INS_OPL:
|
||||
return &song.nullInsOPL;
|
||||
break;
|
||||
case DIV_INS_OPL_DRUMS:
|
||||
return &song.nullInsOPLDrums;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1683,6 +1686,9 @@ int DivEngine::addInstrument(int refChan) {
|
|||
case DIV_INS_OPL:
|
||||
*ins=song.nullInsOPL;
|
||||
break;
|
||||
case DIV_INS_OPL_DRUMS:
|
||||
*ins=song.nullInsOPLDrums;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -784,10 +784,23 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_OPL);
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,c.chan>melodicChans?DIV_INS_OPL_DRUMS:DIV_INS_OPL);
|
||||
|
||||
if (chan[c.chan].insChanged) {
|
||||
chan[c.chan].state=ins->fm;
|
||||
if (c.chan>melodicChans && ins->type==DIV_INS_OPL_DRUMS) {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[melodicChans+i+1].state.alg=ins->fm.alg;
|
||||
chan[melodicChans+i+1].state.fb=ins->fm.fb;
|
||||
chan[melodicChans+i+1].state.opllPreset=ins->fm.opllPreset;
|
||||
chan[melodicChans+i+1].state.fixedDrums=ins->fm.fixedDrums;
|
||||
chan[melodicChans+i+1].state.kickFreq=ins->fm.kickFreq;
|
||||
chan[melodicChans+i+1].state.snareHatFreq=ins->fm.snareHatFreq;
|
||||
chan[melodicChans+i+1].state.tomTopFreq=ins->fm.tomTopFreq;
|
||||
chan[melodicChans+i+1].state.op[0]=ins->fm.op[i];
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].state=ins->fm;
|
||||
}
|
||||
}
|
||||
|
||||
chan[c.chan].macroInit(ins);
|
||||
|
@ -795,49 +808,81 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
if (chan[c.chan].insChanged) {
|
||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||
chan[c.chan].fourOp=(ops==4);
|
||||
if (chan[c.chan].fourOp) {
|
||||
chan[c.chan+1].macroInit(NULL);
|
||||
}
|
||||
update4OpMask=true;
|
||||
for (int i=0; i<ops; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
if (c.chan>melodicChans && ins->type==DIV_INS_OPL_DRUMS) {
|
||||
for (int i=0; i<4; i++) {
|
||||
int ch=melodicChans+1+i;
|
||||
unsigned char slot=slots[0][ch];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[ch].state.op[0];
|
||||
chan[ch].fourOp=false;
|
||||
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||
} else {
|
||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>melodicChans) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
|
||||
if (isMuted[ch]) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[ch].outVol&0x3f))/63))|(op.ksl<<6));
|
||||
}
|
||||
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr);
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr);
|
||||
if (oplType>1) {
|
||||
rWrite(baseAddr+ADDR_WS,op.ws&((oplType==3)?7:3));
|
||||
}
|
||||
|
||||
if (isMuted[ch]) {
|
||||
oldWrites[chanMap[ch]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1));
|
||||
} else {
|
||||
oldWrites[chanMap[ch]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[ch]+ADDR_LR_FB_ALG,(chan[ch].state.alg&1)|(chan[ch].state.fb<<1)|((chan[ch].pan&3)<<4));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||
chan[c.chan].fourOp=(ops==4);
|
||||
if (chan[c.chan].fourOp) {
|
||||
chan[c.chan+1].macroInit(NULL);
|
||||
}
|
||||
update4OpMask=true;
|
||||
for (int i=0; i<ops; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||
} else {
|
||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i] || c.chan>melodicChans) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||
}
|
||||
}
|
||||
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr);
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr);
|
||||
if (oplType>1) {
|
||||
rWrite(baseAddr+ADDR_WS,op.ws&((oplType==3)?7:3));
|
||||
}
|
||||
}
|
||||
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr);
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr);
|
||||
if (oplType>1) {
|
||||
rWrite(baseAddr+ADDR_WS,op.ws&((oplType==3)?7:3));
|
||||
}
|
||||
}
|
||||
|
||||
if (isMuted[c.chan]) {
|
||||
oldWrites[chanMap[c.chan]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1));
|
||||
if (ops==4) {
|
||||
oldWrites[chanMap[c.chan+1]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1));
|
||||
}
|
||||
} else {
|
||||
oldWrites[chanMap[c.chan]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||
if (ops==4) {
|
||||
oldWrites[chanMap[c.chan+1]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||
if (isMuted[c.chan]) {
|
||||
oldWrites[chanMap[c.chan]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1));
|
||||
if (ops==4) {
|
||||
oldWrites[chanMap[c.chan+1]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1));
|
||||
}
|
||||
} else {
|
||||
oldWrites[chanMap[c.chan]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||
if (ops==4) {
|
||||
oldWrites[chanMap[c.chan+1]+ADDR_LR_FB_ALG]=-1;
|
||||
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -845,20 +890,32 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
|||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
if (c.chan>=melodicChans && chan[c.chan].state.opllPreset==16 && chan[c.chan].state.fixedDrums) { // drums
|
||||
if (c.chan==melodicChans) {
|
||||
chan[c.chan].fixedFreq=(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].fixedFreq=(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].fixedFreq=(chan[c.chan].state.tomTopFreq&1023)<<(chan[c.chan].state.tomTopFreq>>10);
|
||||
if (c.chan>melodicChans && ins->type==DIV_INS_OPL_DRUMS && chan[c.chan].state.fixedDrums) {
|
||||
chan[melodicChans+1].fixedFreq=(chan[melodicChans+1].state.snareHatFreq&1023)<<(chan[melodicChans+1].state.snareHatFreq>>10);
|
||||
chan[melodicChans+2].fixedFreq=(chan[melodicChans+2].state.tomTopFreq&1023)<<(chan[melodicChans+2].state.tomTopFreq>>10);
|
||||
chan[melodicChans+3].fixedFreq=chan[melodicChans+2].fixedFreq;
|
||||
chan[melodicChans+4].fixedFreq=chan[melodicChans+1].fixedFreq;
|
||||
|
||||
chan[melodicChans+1].freqChanged=true;
|
||||
chan[melodicChans+2].freqChanged=true;
|
||||
chan[melodicChans+3].freqChanged=true;
|
||||
chan[melodicChans+4].freqChanged=true;
|
||||
} else {
|
||||
if (c.chan>=melodicChans && (chan[c.chan].state.opllPreset==16 || ins->type==DIV_INS_OPL_DRUMS) && chan[c.chan].state.fixedDrums) { // drums
|
||||
if (c.chan==melodicChans) {
|
||||
chan[c.chan].fixedFreq=(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].fixedFreq=(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].fixedFreq=(chan[c.chan].state.tomTopFreq&1023)<<(chan[c.chan].state.tomTopFreq>>10);
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].fixedFreq=0;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].fixedFreq=0;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||
chan[c.chan].fixedFreq=0;
|
||||
}
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
|
|
|
@ -510,6 +510,7 @@ struct DivSong {
|
|||
system[1]=DIV_SYSTEM_SMS;
|
||||
|
||||
// OPLL default instrument contest winner - piano_guitar_idk by Weeppiko
|
||||
nullInsOPLL.type=DIV_INS_OPLL;
|
||||
nullInsOPLL.fm.opllPreset=0;
|
||||
nullInsOPLL.fm.alg=0;
|
||||
nullInsOPLL.fm.fb=7;
|
||||
|
@ -539,6 +540,7 @@ struct DivSong {
|
|||
nullInsOPLL.fm.op[1].ssgEnv=8;
|
||||
nullInsOPLL.name="This is a bug! Report!";
|
||||
|
||||
nullInsOPL.type=DIV_INS_OPL;
|
||||
nullInsOPL.fm.alg=0;
|
||||
nullInsOPL.fm.fb=7;
|
||||
nullInsOPL.fm.op[0].dr=2;
|
||||
|
@ -551,9 +553,52 @@ struct DivSong {
|
|||
nullInsOPL.fm.op[1].rr=12;
|
||||
nullInsOPL.fm.op[1].mult=1;
|
||||
nullInsOPL.name="This is a bug! Report!";
|
||||
nullInsOPL.fm.kickFreq=0x520;
|
||||
nullInsOPL.fm.snareHatFreq=0x550;
|
||||
nullInsOPL.fm.tomTopFreq=0x1c0;
|
||||
nullInsOPL.fm.kickFreq=(1<<10)|576;
|
||||
nullInsOPL.fm.snareHatFreq=(1<<10)|672;
|
||||
nullInsOPL.fm.tomTopFreq=896;
|
||||
|
||||
nullInsOPLDrums=nullInsOPL;
|
||||
nullInsOPLDrums.type=DIV_INS_OPL_DRUMS;
|
||||
nullInsOPLDrums.fm.fixedDrums=true;
|
||||
|
||||
for (int i=0; i<4; i++) {
|
||||
nullInsOPLDrums.fm.op[i].am=0;
|
||||
nullInsOPLDrums.fm.op[i].vib=0;
|
||||
nullInsOPLDrums.fm.op[i].ksr=0;
|
||||
nullInsOPLDrums.fm.op[i].sus=0;
|
||||
nullInsOPLDrums.fm.op[i].ws=0;
|
||||
nullInsOPLDrums.fm.op[i].ksl=0;
|
||||
nullInsOPLDrums.fm.op[i].tl=0;
|
||||
}
|
||||
|
||||
// snare
|
||||
nullInsOPLDrums.fm.op[0].ar=13;
|
||||
nullInsOPLDrums.fm.op[0].dr=8;
|
||||
nullInsOPLDrums.fm.op[0].sl=4;
|
||||
nullInsOPLDrums.fm.op[0].rr=8;
|
||||
nullInsOPLDrums.fm.op[0].mult=1;
|
||||
|
||||
// tom
|
||||
nullInsOPLDrums.fm.op[1].ar=15;
|
||||
nullInsOPLDrums.fm.op[1].dr=8;
|
||||
nullInsOPLDrums.fm.op[1].sl=5;
|
||||
nullInsOPLDrums.fm.op[1].rr=9;
|
||||
nullInsOPLDrums.fm.op[1].mult=5;
|
||||
|
||||
// top
|
||||
nullInsOPLDrums.fm.op[2].ar=10;
|
||||
nullInsOPLDrums.fm.op[2].dr=10;
|
||||
nullInsOPLDrums.fm.op[2].sl=5;
|
||||
nullInsOPLDrums.fm.op[2].rr=5;
|
||||
nullInsOPLDrums.fm.op[2].mult=1;
|
||||
nullInsOPLDrums.fm.op[2].ksr=1;
|
||||
|
||||
// hi-hat
|
||||
nullInsOPLDrums.fm.op[3].ar=12;
|
||||
nullInsOPLDrums.fm.op[3].dr=8;
|
||||
nullInsOPLDrums.fm.op[3].sl=10;
|
||||
nullInsOPLDrums.fm.op[3].rr=7;
|
||||
nullInsOPLDrums.fm.op[3].mult=2;
|
||||
|
||||
nullInsQSound.std.panLMacro.mode=true;
|
||||
}
|
||||
|
|
|
@ -2316,7 +2316,8 @@ void FurnaceGUI::drawInsEdit() {
|
|||
}
|
||||
for (int i=0; i<opCount; i++) {
|
||||
if (ins->type==DIV_INS_OPL_DRUMS) {
|
||||
snprintf(label,31,"%s Macros",oplDrumNames[i]);
|
||||
if (i>0) break;
|
||||
snprintf(label,31,"Operator Macros");
|
||||
} else {
|
||||
snprintf(label,31,"OP%d Macros",i+1);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue