diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index 7ca58611b..8f631bc6c 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -938,7 +938,8 @@ void DivEngine::delUnusedSamples() { i->type==DIV_INS_C219 || i->type==DIV_INS_NDS || i->type==DIV_INS_GBA_DMA || - i->type==DIV_INS_GBA_MINMOD) { + i->type==DIV_INS_GBA_MINMOD || + i->type==DIV_INS_OPL4_PCM) { if (i->amiga.initSample>=0 && i->amiga.initSampleamiga.initSample]=true; } diff --git a/src/engine/instrument.cpp b/src/engine/instrument.cpp index a44572ab8..e568754f5 100644 --- a/src/engine/instrument.cpp +++ b/src/engine/instrument.cpp @@ -175,9 +175,6 @@ bool DivInstrumentMultiPCM::operator==(const DivInstrumentMultiPCM& other) { _C(lfo) && _C(vib) && _C(am) && - _C(damp) && - _C(pseudoReverb) && - _C(lfoReset) && _C(levelDirect) ); } @@ -270,6 +267,14 @@ bool DivInstrumentSID2::operator==(const DivInstrumentSID2& other) { ); } +bool DivInstrumentOPL4PCM::operator==(const DivInstrumentOPL4PCM& other) { + return ( + _C(damp) && + _C(pseudoReverb) && + _C(lfoReset) + ); +} + #undef _C #define CONSIDER(x,t) \ @@ -762,9 +767,6 @@ void DivInstrument::writeFeatureMP(SafeWriter* w) { w->writeC(multipcm.am); /* - w->writeC(multipcm.damp); - w->writeC(multipcm.pseudoReverb); - w->writeC(multipcm.lfoReset); w->writeC(multipcm.levelDirect); */ @@ -859,6 +861,16 @@ void DivInstrument::writeFeatureS2(SafeWriter* w) { FEATURE_END; } +void DivInstrument::writeFeatureOP(SafeWriter* w) { + FEATURE_BEGIN("OP"); + + w->writeC(opl4pcm.damp); + w->writeC(opl4pcm.pseudoReverb); + w->writeC(opl4pcm.lfoReset); + + FEATURE_END; +} + void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bool insName) { size_t blockStartSeek=0; size_t blockEndSeek=0; @@ -905,6 +917,7 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo bool featureEF=false; bool featurePN=false; bool featureS2=false; + bool featureOP=false; bool checkForWL=false; @@ -1148,6 +1161,12 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo feature64=true; featureS2=true; break; + case DIV_INS_OPL4_PCM: + featureSM=true; + featureSL=true; + featureMP=true; + featureOP=true; + break; case DIV_INS_MAX: break; case DIV_INS_NULL: @@ -1204,6 +1223,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo if (sid2!=defaultIns.sid2) { featureS2=true; } + if (opl4pcm!=defaultIns.opl4pcm) { + featureOP=true; + } } // check ins name @@ -1355,6 +1377,9 @@ void DivInstrument::putInsData2(SafeWriter* w, bool fui, const DivSong* song, bo if (featureS2) { writeFeatureS2(w); } + if (featureOP) { + writeFeatureOP(w); + } if (fui && (featureSL || featureWL)) { w->write("EN",2); @@ -2077,9 +2102,6 @@ void DivInstrument::readFeatureMP(SafeReader& reader, short version) { multipcm.am=reader.readC(); /* - multipcm.damp=reader.readC(); - multipcm.pseudoReverb=reader.readC(); - multipcm.lfoReset=reader.readC(); multipcm.levelDirect=reader.readC(); */ @@ -2190,6 +2212,16 @@ void DivInstrument::readFeatureS2(SafeReader& reader, short version) { READ_FEAT_END; } +void DivInstrument::readFeatureOP(SafeReader& reader, short version) { + READ_FEAT_BEGIN; + + opl4pcm.damp=reader.readC(); + opl4pcm.pseudoReverb=reader.readC(); + opl4pcm.lfoReset=reader.readC(); + + READ_FEAT_END; +} + DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song) { unsigned char featCode[2]; @@ -2265,6 +2297,8 @@ DivDataErrors DivInstrument::readInsDataNew(SafeReader& reader, short version, b readFeaturePN(reader,version); } else if (memcmp(featCode,"S2",2)==0) { // SID2 readFeatureS2(reader,version); + } else if (memcmp(featCode,"OP",2)==0) { // OPL4 PCM + readFeatureOP(reader,version); } else { if (song==NULL && (memcmp(featCode,"SL",2)==0 || (memcmp(featCode,"WL",2)==0))) { // nothing diff --git a/src/engine/instrument.h b/src/engine/instrument.h index 95a86755a..16f690a35 100644 --- a/src/engine/instrument.h +++ b/src/engine/instrument.h @@ -94,6 +94,7 @@ enum DivInstrumentType: unsigned short { DIV_INS_GBA_MINMOD=61, DIV_INS_BIFURCATOR=62, DIV_INS_SID2=63, // coincidence! + DIV_INS_OPL4_PCM=64, DIV_INS_MAX, DIV_INS_NULL }; @@ -608,7 +609,7 @@ struct DivInstrumentFDS { struct DivInstrumentMultiPCM { unsigned char ar, d1r, dl, d2r, rr, rc; unsigned char lfo, vib, am; - bool damp, pseudoReverb, lfoReset, levelDirect; + bool levelDirect; bool operator==(const DivInstrumentMultiPCM& other); bool operator!=(const DivInstrumentMultiPCM& other) { @@ -618,9 +619,6 @@ struct DivInstrumentMultiPCM { DivInstrumentMultiPCM(): ar(15), d1r(15), dl(0), d2r(0), rr(15), rc(15), lfo(0), vib(0), am(0), - damp(false), - pseudoReverb(false), - lfoReset(false), levelDirect(true) { } }; @@ -865,6 +863,21 @@ struct DivInstrumentSID2 { noiseMode(0) {} }; +struct DivInstrumentOPL4PCM { + bool damp, pseudoReverb, lfoReset; + + bool operator==(const DivInstrumentOPL4PCM& other); + bool operator!=(const DivInstrumentOPL4PCM& other) { + return !(*this==other); + } + + DivInstrumentOPL4PCM(): + damp(false), + pseudoReverb(false), + lfoReset(false) { + } +}; + struct DivInstrument { String name; DivInstrumentType type; @@ -884,6 +897,7 @@ struct DivInstrument { DivInstrumentESFM esfm; DivInstrumentPowerNoise powernoise; DivInstrumentSID2 sid2; + DivInstrumentOPL4PCM opl4pcm; /** * these are internal functions. @@ -911,6 +925,7 @@ struct DivInstrument { void writeFeatureEF(SafeWriter* w); void writeFeaturePN(SafeWriter* w); void writeFeatureS2(SafeWriter* w); + void writeFeatureOP(SafeWriter* w); void readFeatureNA(SafeReader& reader, short version); void readFeatureFM(SafeReader& reader, short version); @@ -934,6 +949,7 @@ struct DivInstrument { void readFeatureEF(SafeReader& reader, short version); void readFeaturePN(SafeReader& reader, short version); void readFeatureS2(SafeReader& reader, short version); + void readFeatureOP(SafeReader& reader, short version); DivDataErrors readInsDataOld(SafeReader& reader, short version); DivDataErrors readInsDataNew(SafeReader& reader, short version, bool fui, DivSong* song); diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index f048af2c0..8a4c1916c 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -1711,7 +1711,7 @@ int DivPlatformOPL::dispatch(DivCommand c) { chan[c.chan].freqChanged=true; chan[c.chan].note=c.value; } - if (ins->type==DIV_INS_MULTIPCM) { + if (ins->type==DIV_INS_OPL4_PCM) { chan[c.chan].lfo=ins->multipcm.lfo; chan[c.chan].vib=ins->multipcm.vib; chan[c.chan].am=ins->multipcm.am; @@ -1721,10 +1721,10 @@ int DivPlatformOPL::dispatch(DivCommand c) { chan[c.chan].d2r=ins->multipcm.d2r; chan[c.chan].rc=ins->multipcm.rc; chan[c.chan].rr=ins->multipcm.rr; - chan[c.chan].damp=ins->multipcm.damp; - chan[c.chan].pseudoReverb=ins->multipcm.pseudoReverb; chan[c.chan].levelDirect=ins->multipcm.levelDirect; - chan[c.chan].lfoReset=ins->multipcm.lfoReset; + chan[c.chan].damp=ins->opl4pcm.damp; + chan[c.chan].pseudoReverb=ins->opl4pcm.pseudoReverb; + chan[c.chan].lfoReset=ins->opl4pcm.lfoReset; } else { chan[c.chan].lfo=0; chan[c.chan].vib=0; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 94a699754..b7562277b 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1640,7 +1640,7 @@ void DivEngine::registerSystems() { {_("4OP 1"), _("FM 2"), _("4OP 3"), _("FM 4"), _("4OP 5"), _("FM 6"), _("4OP 7"), _("FM 8"), _("4OP 9"), _("FM 10"), _("4OP 11"), _("FM 12"), _("FM 13"), _("FM 14"), _("FM 15"), _("FM 16"), _("FM 17"), _("FM 18"), _("PCM 1"), _("PCM 2"), _("PCM 3"), _("PCM 4"), _("PCM 5"), _("PCM 6"), _("PCM 7"), _("PCM 8"), _("PCM 9"), _("PCM 10"), _("PCM 11"), _("PCM 12"), _("PCM 13"), _("PCM 14"), _("PCM 15"), _("PCM 16"), _("PCM 17"), _("PCM 18"), _("PCM 19"), _("PCM 20"), _("PCM 21"), _("PCM 22"), _("PCM 23"), _("PCM 24")}, {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"}, {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, 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_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, 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_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM}, + {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_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_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_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_OPL, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, fmEffectHandlerMap, fmOPL4PostEffectHandlerMap @@ -1653,7 +1653,7 @@ void DivEngine::registerSystems() { {_("4OP 1"), _("FM 2"), _("4OP 3"), _("FM 4"), _("4OP 5"), _("FM 6"), _("4OP 7"), _("FM 8"), _("4OP 9"), _("FM 10"), _("4OP 11"), _("FM 12"), _("FM 13"), _("FM 14"), _("FM 15"), _("Kick/FM 16"), _("Snare"), _("Tom"), _("Top"), _("HiHat"), _("PCM 1"), _("PCM 2"), _("PCM 3"), _("PCM 4"), _("PCM 5"), _("PCM 6"), _("PCM 7"), _("PCM 8"), _("PCM 9"), _("PCM 10"), _("PCM 11"), _("PCM 12"), _("PCM 13"), _("PCM 14"), _("PCM 15"), _("PCM 16"), _("PCM 17"), _("PCM 18"), _("PCM 19"), _("PCM 20"), _("PCM 21"), _("PCM 22"), _("PCM 23"), _("PCM 24")}, {"F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "F13", "F14", "F15", "BD", "SD", "TM", "TP", "HH", "P1", "P2", "P3", "P4", "P5", "P6", "P7", "P8", "P9", "P10", "P11", "P12", "P13", "P14", "P15", "P16", "P17", "P18", "P19", "P20", "P21", "P22", "P23", "P24"}, {DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, DIV_CH_FM, DIV_CH_OP, 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_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, DIV_CH_PCM, 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_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_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM, DIV_INS_MULTIPCM}, + {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_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_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_PCM, DIV_INS_OPL4_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_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_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA, DIV_INS_AMIGA}, fmOPLDrumsEffectHandlerMap, fmOPL4PostEffectHandlerMap diff --git a/src/engine/vgmOps.cpp b/src/engine/vgmOps.cpp index e0391fe6e..b3729dffe 100644 --- a/src/engine/vgmOps.cpp +++ b/src/engine/vgmOps.cpp @@ -615,6 +615,96 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeC(0); } break; + case DIV_SYSTEM_OPL4: + case DIV_SYSTEM_OPL4_DRUMS: + // disable envelope + for (int i=0; i<6; i++) { + w->writeC(0xd0); + w->writeC(0x00|baseAddr2); + w->writeC(0x80+i); + w->writeC(0x0f); + w->writeC(0xd0); + w->writeC(0x00|baseAddr2); + w->writeC(0x88+i); + w->writeC(0x0f); + w->writeC(0xd0); + w->writeC(0x00|baseAddr2); + w->writeC(0x90+i); + w->writeC(0x0f); + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0x80+i); + w->writeC(0x0f); + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0x88+i); + w->writeC(0x0f); + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0x90+i); + w->writeC(0x0f); + } + for (int i=0; i<24; i++) { + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0x80+i); + w->writeC(0x00); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0x98+i); + w->writeC(0x00); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0xb0+i); + w->writeC(0x00); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0xc8+i); + w->writeC(0x00); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0xe0+i); + w->writeC(0x00); + } + // key off + freq reset + for (int i=0; i<9; i++) { + w->writeC(0xd0); + w->writeC(0x00|baseAddr2); + w->writeC(0xa0+i); + w->writeC(0); + w->writeC(0xd0); + w->writeC(0x00|baseAddr2); + w->writeC(0xb0+i); + w->writeC(0); + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0xa0+i); + w->writeC(0); + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0xb0+i); + w->writeC(0); + } + for (int i=0; i<24; i++) { + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0x20+i); + w->writeC(0); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0x38+i); + w->writeC(0); + w->writeC(0xd0); + w->writeC(0x02|baseAddr2); + w->writeC(0x68+i); + w->writeC(8); + } + // reset 4-op + w->writeC(0xd0); + w->writeC(0x01|baseAddr2); + w->writeC(0x04); + w->writeC(0x00); + break; default: break; } @@ -987,13 +1077,6 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write break; } break; - case DIV_SYSTEM_OPL4: - case DIV_SYSTEM_OPL4_DRUMS: - w->writeC(0xd0|baseAddr2); - w->writeC(write.addr>>8); - w->writeC(write.addr&0xff); - w->writeC(write.val); - break; case DIV_SYSTEM_SCC: if (write.addr<0x80) { w->writeC(0xd2); @@ -1096,6 +1179,13 @@ void DivEngine::performVGMWrite(SafeWriter* w, DivSystem sys, DivRegWrite& write w->writeS_BE(baseAddr2S|(write.addr&0x1ff)); w->writeC(write.val&0xff); break; + case DIV_SYSTEM_OPL4: + case DIV_SYSTEM_OPL4_DRUMS: + w->writeC(0xd0); + w->writeC(((write.addr>>8)&0x7f)|baseAddr2); + w->writeC(write.addr&0xff); + w->writeC(write.val); + break; default: logW("write not handled!"); break; diff --git a/src/gui/doAction.cpp b/src/gui/doAction.cpp index d6d8ea434..ffcbcce5a 100644 --- a/src/gui/doAction.cpp +++ b/src/gui/doAction.cpp @@ -1043,7 +1043,8 @@ void FurnaceGUI::doAction(int what) { i==DIV_INS_K053260 || i==DIV_INS_C140 || i==DIV_INS_C219 || - i==DIV_INS_NDS) { + i==DIV_INS_NDS || + i==DIV_INS_OPL4_PCM) { makeInsTypeList.push_back(i); } } @@ -1572,7 +1573,8 @@ void FurnaceGUI::doAction(int what) { i==DIV_INS_C219 || i==DIV_INS_NDS || i==DIV_INS_GBA_DMA || - i==DIV_INS_GBA_MINMOD) { + i==DIV_INS_GBA_MINMOD || + i==DIV_INS_OPL4_PCM) { makeInsTypeList.push_back(i); } } diff --git a/src/gui/gui.h b/src/gui/gui.h index 51161c224..4ad5f6649 100644 --- a/src/gui/gui.h +++ b/src/gui/gui.h @@ -351,6 +351,7 @@ enum FurnaceGUIColors { GUI_COLOR_INSTR_GBA_MINMOD, GUI_COLOR_INSTR_BIFURCATOR, GUI_COLOR_INSTR_SID2, + GUI_COLOR_INSTR_OPL4_PCM, GUI_COLOR_INSTR_UNKNOWN, GUI_COLOR_CHANNEL_BG, diff --git a/src/gui/guiConst.cpp b/src/gui/guiConst.cpp index b9d9ae85d..d05e84e7d 100644 --- a/src/gui/guiConst.cpp +++ b/src/gui/guiConst.cpp @@ -184,6 +184,7 @@ const char* insTypes[DIV_INS_MAX+1][3]={ {"GBA MinMod",ICON_FA_VOLUME_UP,ICON_FUR_INS_GBA_MINMOD}, {"Bifurcator",ICON_FA_LINE_CHART,ICON_FUR_INS_BIFURCATOR}, {"SID2",ICON_FA_KEYBOARD_O,ICON_FUR_INS_SID2}, + {"OPL4 PCM",ICON_FA_VOLUME_UP,ICON_FUR_INS_MULTIPCM}, {NULL,ICON_FA_QUESTION,ICON_FA_QUESTION} }; @@ -1012,6 +1013,7 @@ const FurnaceGUIColorDef guiColors[GUI_COLOR_MAX]={ D(GUI_COLOR_INSTR_GBA_MINMOD,"",ImVec4(0.5f,0.45f,0.7f,1.0f)), D(GUI_COLOR_INSTR_BIFURCATOR,"",ImVec4(0.8925f,0.8925f,0.8925f,1.0f)), D(GUI_COLOR_INSTR_SID2,"",ImVec4(0.6f,0.75f,1.0f,1.0f)), + D(GUI_COLOR_INSTR_OPL4_PCM,"",ImVec4(1.0f,0.8f,0.1f,1.0f)), D(GUI_COLOR_INSTR_UNKNOWN,"",ImVec4(0.3f,0.3f,0.3f,1.0f)), D(GUI_COLOR_CHANNEL_BG,"",ImVec4(0.4f,0.6f,0.8f,1.0f)), diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 974188e96..4c0bed32a 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -6205,7 +6205,8 @@ void FurnaceGUI::drawInsEdit() { ins->type==DIV_INS_C219 || ins->type==DIV_INS_NDS || ins->type==DIV_INS_GBA_DMA || - ins->type==DIV_INS_GBA_MINMOD) { + ins->type==DIV_INS_GBA_MINMOD || + ins->type==DIV_INS_OPL4_PCM) { insTabSample(ins); } if (ins->type==DIV_INS_N163) if (ImGui::BeginTabItem("Namco 163")) { @@ -6437,8 +6438,8 @@ void FurnaceGUI::drawInsEdit() { } ImGui::EndTabItem(); } - if (ins->type==DIV_INS_MULTIPCM) { - if (ImGui::BeginTabItem("MultiPCM")) { + if (ins->type==DIV_INS_MULTIPCM || ins->type==DIV_INS_OPL4_PCM) { + if (ImGui::BeginTabItem(ins->type==DIV_INS_OPL4_PCM?"OPL4 PCM":"MultiPCM")) { ImVec2 sliderSize=ImVec2(20.0f*dpiScale,128.0*dpiScale); if (ImGui::BeginTable("MultiPCMADSRParams",7,ImGuiTableFlags_NoHostExtendX)) { ImGui::TableSetupColumn("c0",ImGuiTableColumnFlags_WidthFixed,sliderSize.x); @@ -6519,19 +6520,12 @@ void FurnaceGUI::drawInsEdit() { P(CWSliderScalar(_("AM Depth"),ImGuiDataType_U8,&ins->multipcm.am,&_ZERO,&_SEVEN)); rightClickable ImGui::EndTable(); } - P(ImGui::Checkbox(_("Damp"),&ins->multipcm.damp)); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(_("Only for OPL4 PCM.")); - } - P(ImGui::Checkbox(_("Pseudo Reverb"),&ins->multipcm.pseudoReverb)); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(_("Only for OPL4 PCM.")); - } - P(ImGui::Checkbox(_("LFO Reset"),&ins->multipcm.lfoReset)); - if (ImGui::IsItemHovered()) { - ImGui::SetTooltip(_("Only for OPL4 PCM.")); - } P(ImGui::Checkbox(_("Level Direct"),&ins->multipcm.levelDirect)); + if (ins->type==DIV_INS_OPL4_PCM) { + P(ImGui::Checkbox(_("Damp"),&ins->opl4pcm.damp)); + P(ImGui::Checkbox(_("Pseudo Reverb"),&ins->opl4pcm.pseudoReverb)); + P(ImGui::Checkbox(_("LFO Reset"),&ins->opl4pcm.lfoReset)); + } ImGui::EndTabItem(); } } @@ -7226,12 +7220,6 @@ void FurnaceGUI::drawInsEdit() { macroList.push_back(FurnaceGUIMacroDesc(_("LFO speed"),&ins->std.ex1Macro,0,7,160,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(_("LFO vibrato depth"),&ins->std.fmsMacro,0,7,160,uiColors[GUI_COLOR_MACRO_PITCH])); macroList.push_back(FurnaceGUIMacroDesc(_("LFO AM depth"),&ins->std.amsMacro,0,7,160,uiColors[GUI_COLOR_MACRO_VOLUME])); - macroList.push_back(FurnaceGUIMacroDesc(_("AR"),&ins->std.ex2Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); - macroList.push_back(FurnaceGUIMacroDesc(_("D1R"),&ins->std.ex3Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); - macroList.push_back(FurnaceGUIMacroDesc(_("DL"),&ins->std.ex4Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); - macroList.push_back(FurnaceGUIMacroDesc(_("D2R"),&ins->std.ex5Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); - macroList.push_back(FurnaceGUIMacroDesc(_("Rate correction"),&ins->std.ex6Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); - macroList.push_back(FurnaceGUIMacroDesc(_("RR"),&ins->std.ex7Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); break; case DIV_INS_SNES: macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,127,160,uiColors[GUI_COLOR_MACRO_VOLUME])); @@ -7525,6 +7513,22 @@ void FurnaceGUI::drawInsEdit() { macroList.push_back(FurnaceGUIMacroDesc(_("Noise Mode"),&ins->std.fmsMacro,0,3,64,uiColors[GUI_COLOR_MACRO_NOISE])); macroList.push_back(FurnaceGUIMacroDesc(_("Wave Mix"),&ins->std.amsMacro,0,3,64,uiColors[GUI_COLOR_MACRO_OTHER])); break; + case DIV_INS_OPL4_PCM: + macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,127,160,uiColors[GUI_COLOR_MACRO_VOLUME])); + macroList.push_back(FurnaceGUIMacroDesc(_("Arpeggio"),&ins->std.arpMacro,-120,120,160,uiColors[GUI_COLOR_MACRO_PITCH],true,NULL,macroHoverNote,false,NULL,true,ins->std.arpMacro.val)); + macroList.push_back(FurnaceGUIMacroDesc(_("Panning"),&ins->std.panLMacro,-7,7,45,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL)); + macroList.push_back(FurnaceGUIMacroDesc(_("Pitch"),&ins->std.pitchMacro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode)); + macroList.push_back(FurnaceGUIMacroDesc(_("Phase Reset"),&ins->std.phaseResetMacro,0,1,32,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,NULL,true)); + macroList.push_back(FurnaceGUIMacroDesc(_("LFO speed"),&ins->std.ex1Macro,0,7,160,uiColors[GUI_COLOR_MACRO_OTHER])); + macroList.push_back(FurnaceGUIMacroDesc(_("LFO vibrato depth"),&ins->std.fmsMacro,0,7,160,uiColors[GUI_COLOR_MACRO_PITCH])); + macroList.push_back(FurnaceGUIMacroDesc(_("LFO AM depth"),&ins->std.amsMacro,0,7,160,uiColors[GUI_COLOR_MACRO_VOLUME])); + macroList.push_back(FurnaceGUIMacroDesc(_("AR"),&ins->std.ex2Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("D1R"),&ins->std.ex3Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("DL"),&ins->std.ex4Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("D2R"),&ins->std.ex5Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("Rate correction"),&ins->std.ex6Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("RR"),&ins->std.ex7Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + break; case DIV_INS_MAX: case DIV_INS_NULL: diff --git a/src/gui/settings.cpp b/src/gui/settings.cpp index 63815cd02..541960ed3 100644 --- a/src/gui/settings.cpp +++ b/src/gui/settings.cpp @@ -4107,6 +4107,7 @@ void FurnaceGUI::drawSettings() { UI_COLOR_CONFIG(GUI_COLOR_INSTR_GBA_MINMOD,_("GBA MinMod")); UI_COLOR_CONFIG(GUI_COLOR_INSTR_BIFURCATOR,_("Bifurcator")); UI_COLOR_CONFIG(GUI_COLOR_INSTR_SID2,_("SID2")); + UI_COLOR_CONFIG(GUI_COLOR_INSTR_OPL4_PCM,_("OPL4 PCM")); UI_COLOR_CONFIG(GUI_COLOR_INSTR_UNKNOWN,_("Other/Unknown")); ImGui::TreePop(); }