diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 6a23663ab..b20662057 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -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; } diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index c9996e296..c8d728292 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -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; imelodicChans && 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; imelodicChans) { + 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; diff --git a/src/engine/song.h b/src/engine/song.h index ee0d6ed1f..10c00d27f 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -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; } diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 6d6e424c8..e628e948b 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -2316,7 +2316,8 @@ void FurnaceGUI::drawInsEdit() { } for (int i=0; itype==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); }