diff --git a/src/engine/platform/es5506.cpp b/src/engine/platform/es5506.cpp index 92aa2e20d..42ce685a3 100644 --- a/src/engine/platform/es5506.cpp +++ b/src/engine/platform/es5506.cpp @@ -143,13 +143,13 @@ void DivPlatformES5506::acquire(short* bufL, short* bufR, size_t start, size_t l void DivPlatformES5506::e_pin(bool state) { if (es5506.e_falling_edge()) { // get channel outputs if (es5506.voice_update()) { - chan[prevChanCycle].lOut=es5506.voice_lout(prevChanCycle); - chan[prevChanCycle].rOut=es5506.voice_rout(prevChanCycle); - chan[prevChanCycle].oscOut=CLAMP((chan[prevChanCycle].lOut+chan[prevChanCycle].rOut)>>5,-32768,32767); + const signed int lOut=es5506.voice_lout(prevChanCycle); + const signed int rOut=es5506.voice_rout(prevChanCycle); + chan[prevChanCycle].oscOut=CLAMP((lOut+rOut)>>5,-32768,32767); if (es5506.voice_end()) { if (prevChanCycle<31) { for (int c=31; c>prevChanCycle; c--) { - chan[c].lOut=chan[c].rOut=chan[c].oscOut=0; + chan[c].oscOut=0; } } } @@ -614,11 +614,9 @@ void DivPlatformES5506::tick(bool sysTick) { if (chan[i].noteChanged.offs) { if (chan[i].pcm.freqOffs!=chan[i].pcm.nextFreqOffs) { chan[i].pcm.freqOffs=chan[i].pcm.nextFreqOffs; - const int nextFreq=NOTE_ES5506(i,chan[i].currNote); - if (chan[i].nextFreq!=nextFreq) { - chan[i].nextFreq=nextFreq; - chan[i].noteChanged.freq=1; - } + chan[i].nextFreq=NOTE_ES5506(i,chan[i].currNote); + chan[i].noteChanged.freq=1; + chan[i].freqChanged=true; } } if (chan[i].noteChanged.note) { @@ -659,24 +657,36 @@ void DivPlatformES5506::tick(bool sysTick) { pageWrite(0x00|i,0x01,chan[i].freq); pageWrite(0x20|i,0x01,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.start:chan[i].pcm.loopStart); pageWrite(0x20|i,0x02,(chan[i].pcm.loopMode==DIV_SAMPLE_LOOP_MAX)?chan[i].pcm.end:chan[i].pcm.loopEnd); + // initialize overwrite + const DivInstrumentES5506::Filter::FilterMode filterModeInit=chan[i].overwrite.state.mode?chan[i].overwrite.filter.mode:chan[i].filter.mode; + const signed int k1Init=chan[i].overwrite.state.k1?chan[i].overwrite.filter.k1:chan[i].filter.k1; + const signed int k2Init=chan[i].overwrite.state.k2?chan[i].overwrite.filter.k2:chan[i].filter.k2; + + const unsigned short ecountInit=chan[i].overwrite.state.ecount?chan[i].overwrite.envelope.ecount:chan[i].envelope.ecount; + const unsigned char lVRampInit=(unsigned char)(chan[i].overwrite.state.lVRamp?chan[i].overwrite.envelope.lVRamp:chan[i].envelope.lVRamp); + const unsigned char rVRampInit=(unsigned char)(chan[i].overwrite.state.rVRamp?chan[i].overwrite.envelope.rVRamp:chan[i].envelope.rVRamp); + const unsigned char k1RampInit=(unsigned char)(chan[i].overwrite.state.k1Ramp?chan[i].overwrite.envelope.k1Ramp:chan[i].envelope.k1Ramp); + const unsigned char k2RampInit=(unsigned char)(chan[i].overwrite.state.k2Ramp?chan[i].overwrite.envelope.k2Ramp:chan[i].envelope.k2Ramp); + const bool k1SlowInit=chan[i].overwrite.state.k1Ramp?chan[i].overwrite.envelope.k1Slow:chan[i].envelope.k1Slow; + const bool k2SlowInit=chan[i].overwrite.state.k2Ramp?chan[i].overwrite.envelope.k2Slow:chan[i].envelope.k2Slow; // initialize envelope - pageWrite(0x00|i,0x03,((unsigned char)chan[i].envelope.lVRamp)<<8); - pageWrite(0x00|i,0x05,((unsigned char)chan[i].envelope.rVRamp)<<8); - pageWrite(0x00|i,0x0a,(((unsigned char)chan[i].envelope.k1Ramp)<<8)|(chan[i].envelope.k1Slow?1:0)); - pageWrite(0x00|i,0x08,(((unsigned char)chan[i].envelope.k2Ramp)<<8)|(chan[i].envelope.k2Slow?1:0)); + pageWrite(0x00|i,0x03,lVRampInit<<8); + pageWrite(0x00|i,0x05,rVRampInit<<8); + pageWrite(0x00|i,0x0a,(k1RampInit<<8)|(k1SlowInit?1:0)); + pageWrite(0x00|i,0x08,(k2RampInit<<8)|(k2SlowInit?1:0)); // initialize filter - pageWriteMask(0x00|i,0x5f,0x00,(chan[i].pcm.bank<<14)|(chan[i].filter.mode<<8),0xc300); + pageWriteMask(0x00|i,0x5f,0x00,(chan[i].pcm.bank<<14)|(filterModeInit<<8),0xc300); if ((chan[i].std.ex2.mode!=0) && (chan[i].std.ex2.had)) { - k2=CLAMP(chan[i].filter.k2+chan[i].k2Offs,0,65535); + k2=CLAMP(k2Init+chan[i].k2Offs,0,65535); } else { - k2=chan[i].filter.k2; + k2=k2Init; } pageWrite(0x00|i,0x07,k2); chan[i].k2Prev=k2; if ((chan[i].std.ex1.mode!=0) && (chan[i].std.ex1.had)) { - k1=CLAMP(chan[i].filter.k1+chan[i].k1Offs,0,65535); + k1=CLAMP(k1Init+chan[i].k1Offs,0,65535); } else { - k1=chan[i].filter.k1; + k1=k1Init; } pageWrite(0x00|i,0x09,k1); chan[i].k1Prev=k1; @@ -703,17 +713,20 @@ void DivPlatformES5506::tick(bool sysTick) { loopFlag|=0x0002; } // Run sample - pageWrite(0x00|i,0x06,chan[i].envelope.ecount); // Clear ECOUNT + pageWrite(0x00|i,0x06,ecountInit); // Clear ECOUNT pageWriteMask(0x00|i,0x5f,0x00,loopFlag,0x3cff); } } if (chan[i].keyOff) { pageWriteMask(0x00|i,0x5f,0x00,0x0303); // Wipeout CR - } else if (chan[i].active) { + } else if (!chan[i].keyOn && chan[i].active) { pageWrite(0x00|i,0x01,chan[i].freq); } if (chan[i].keyOn) chan[i].keyOn=false; if (chan[i].keyOff) chan[i].keyOff=false; + if (chan[i].overwrite.state.overwrited!=0) { + chan[i].overwrite.state.overwrited=0; + } chan[i].freqChanged=false; } if (!chan[i].keyOn && chan[i].active) { @@ -854,14 +867,35 @@ int DivPlatformES5506::dispatch(DivCommand c) { break; // Filter commands case DIV_CMD_ES5506_FILTER_MODE: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.mode) { + chan[c.chan].overwrite.filter.mode=chan[c.chan].filter.mode; + chan[c.chan].overwrite.state.mode=1; + } + chan[c.chan].overwrite.filter.mode=DivInstrumentES5506::Filter::FilterMode(c.value&3); + } chan[c.chan].filter.mode=DivInstrumentES5506::Filter::FilterMode(c.value&3); chan[c.chan].filterChanged.mode=1; break; case DIV_CMD_ES5506_FILTER_K1: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.k1) { + chan[c.chan].overwrite.filter.k1=chan[c.chan].filter.k1; + chan[c.chan].overwrite.state.k1=1; + } + chan[c.chan].overwrite.filter.k1=(chan[c.chan].overwrite.filter.k1&~c.value2)|(c.value&c.value2); + } chan[c.chan].filter.k1=(chan[c.chan].filter.k1&~c.value2)|(c.value&c.value2); chan[c.chan].filterChanged.k1=1; break; case DIV_CMD_ES5506_FILTER_K2: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.k2) { + chan[c.chan].overwrite.filter.k2=chan[c.chan].filter.k2; + chan[c.chan].overwrite.state.k2=1; + } + chan[c.chan].overwrite.filter.k2=(chan[c.chan].overwrite.filter.k2&~c.value2)|(c.value&c.value2); + } chan[c.chan].filter.k2=(chan[c.chan].filter.k2&~c.value2)|(c.value&c.value2); chan[c.chan].filterChanged.k2=1; break; @@ -873,23 +907,62 @@ int DivPlatformES5506::dispatch(DivCommand c) { break; // Envelope commands case DIV_CMD_ES5506_ENVELOPE_COUNT: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.ecount) { + chan[c.chan].overwrite.envelope.ecount=chan[c.chan].envelope.ecount; + chan[c.chan].overwrite.state.ecount=1; + } + chan[c.chan].overwrite.envelope.ecount=c.value&0x1ff; + } chan[c.chan].envelope.ecount=c.value&0x1ff; chan[c.chan].envChanged.ecount=1; break; case DIV_CMD_ES5506_ENVELOPE_LVRAMP: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.lVRamp) { + chan[c.chan].overwrite.envelope.lVRamp=chan[c.chan].envelope.lVRamp; + chan[c.chan].overwrite.state.lVRamp=1; + } + chan[c.chan].overwrite.envelope.lVRamp=(signed char)(c.value&0xff); + } chan[c.chan].envelope.lVRamp=(signed char)(c.value&0xff); chan[c.chan].envChanged.lVRamp=1; break; case DIV_CMD_ES5506_ENVELOPE_RVRAMP: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.rVRamp) { + chan[c.chan].overwrite.envelope.rVRamp=chan[c.chan].envelope.rVRamp; + chan[c.chan].overwrite.state.rVRamp=1; + } + chan[c.chan].overwrite.envelope.rVRamp=(signed char)(c.value&0xff); + } chan[c.chan].envelope.rVRamp=(signed char)(c.value&0xff); chan[c.chan].envChanged.rVRamp=1; break; case DIV_CMD_ES5506_ENVELOPE_K1RAMP: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.k1Ramp) { + chan[c.chan].overwrite.envelope.k1Ramp=chan[c.chan].envelope.k1Ramp; + chan[c.chan].overwrite.envelope.k1Slow=chan[c.chan].envelope.k1Slow; + chan[c.chan].overwrite.state.k1Ramp=1; + } + chan[c.chan].overwrite.envelope.k1Ramp=(signed char)(c.value&0xff); + chan[c.chan].overwrite.envelope.k1Slow=c.value2&1; + } chan[c.chan].envelope.k1Ramp=(signed char)(c.value&0xff); chan[c.chan].envelope.k1Slow=c.value2&1; chan[c.chan].envChanged.k1Ramp=1; break; case DIV_CMD_ES5506_ENVELOPE_K2RAMP: + if (!chan[c.chan].keyOn) { + if (!chan[c.chan].overwrite.state.k2Ramp) { + chan[c.chan].overwrite.envelope.k2Ramp=chan[c.chan].envelope.k2Ramp; + chan[c.chan].overwrite.envelope.k2Slow=chan[c.chan].envelope.k2Slow; + chan[c.chan].overwrite.state.k2Ramp=1; + } + chan[c.chan].overwrite.envelope.k2Ramp=(signed char)(c.value&0xff); + chan[c.chan].overwrite.envelope.k2Slow=c.value2&1; + } chan[c.chan].envelope.k2Ramp=(signed char)(c.value&0xff); chan[c.chan].envelope.k2Slow=c.value2&1; chan[c.chan].envChanged.k2Ramp=1; diff --git a/src/engine/platform/es5506.h b/src/engine/platform/es5506.h index 6bfcfc85c..d7b88c8b1 100644 --- a/src/engine/platform/es5506.h +++ b/src/engine/platform/es5506.h @@ -141,15 +141,46 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf { }; unsigned char changed; }; + PCMChanged(): + changed(0) {} } pcmChanged; + struct Overwrite { + DivInstrumentES5506::Filter filter; + DivInstrumentES5506::Envelope envelope; + + struct State { + // overwrited flag + union { + struct { + unsigned char mode: 1; // filter mode + unsigned char k1: 1; // k1 + unsigned char k2: 1; // k2 + unsigned char ecount: 1; // envelope count + unsigned char lVRamp: 1; // left volume ramp + unsigned char rVRamp: 1; // right volume ramp + unsigned char k1Ramp: 1; // k1 ramp + unsigned char k2Ramp: 1; // k2 ramp + }; + unsigned char overwrited; + }; + State(): + overwrited(0) {} + } state; + + Overwrite(): + filter(DivInstrumentES5506::Filter()), + envelope(DivInstrumentES5506::Envelope()), + state(State()) {} + } overwrite; + signed int k1Offs, k2Offs; signed int k1Slide, k2Slide; signed int k1Prev, k2Prev; unsigned int vol, lVol, rVol; unsigned int outVol, outLVol, outRVol; unsigned int resLVol, resRVol; - signed int lOut, rOut, oscOut; + signed int oscOut; DivInstrumentES5506::Filter filter; DivInstrumentES5506::Envelope envelope; DivMacroInt std; @@ -166,6 +197,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf { k2Prev=0xffff; } Channel(): + pcm(PCM()), freq(0), baseFreq(0), nextFreq(0), @@ -187,6 +219,12 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf { useWave(false), isReverseLoop(false), cr(0), + noteChanged(NoteChanged()), + volChanged(VolChanged()), + filterChanged(FilterChanged()), + envChanged(EnvChanged()), + pcmChanged(PCMChanged()), + overwrite(Overwrite()), k1Offs(0), k2Offs(0), k1Slide(0), @@ -201,9 +239,9 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf { outRVol(0xffff), resLVol(0xffff), resRVol(0xffff), - lOut(0), - rOut(0), - oscOut(0) {} + oscOut(0), + filter(DivInstrumentES5506::Filter()), + envelope(DivInstrumentES5506::Envelope()) {} }; Channel chan[32]; DivDispatchOscBuffer* oscBuf[32]; @@ -263,6 +301,7 @@ class DivPlatformES5506: public DivDispatch, public es550x_intf { es5506_core es5506; unsigned char regPool[4*16*128]; // 7 bit page x 16 registers per page x 32 bit per registers + friend void putDispatchChip(void*,int); friend void putDispatchChan(void*,int,int); public: diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index b1bcc3aac..de57b848d 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -1478,11 +1478,8 @@ void DivEngine::registerSystems() { ); EffectHandlerMap es5506PreEffectHandlerMap={ - {0x10, {DIV_CMD_WAVE, "10xx: Change waveform or sample (00 to FF)",effectVal}} - }; - EffectHandlerMap es5506PostEffectHandlerMap={ + {0x10, {DIV_CMD_WAVE, "10xx: Change waveform or sample (00 to FF)",effectVal}}, {0x11, {DIV_CMD_ES5506_FILTER_MODE, "11xx: Set filter mode (00 to 03)",effectValAnd<3>}}, - {0x12, {DIV_CMD_ES5506_PAUSE, "120x: Set pause (bit 0)",effectValAnd<1>}}, {0x14, {DIV_CMD_ES5506_FILTER_K1, "14xx: Set filter coefficient K1 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}}, {0x15, {DIV_CMD_ES5506_FILTER_K1, "15xx: Set filter coefficient K1 high byte (00 to FF)",effectValShift<8>,constVal<0xff00>}}, {0x16, {DIV_CMD_ES5506_FILTER_K2, "16xx: Set filter coefficient K2 low byte (00 to FF)",effectValShift<0>,constVal<0x00ff>}}, @@ -1498,12 +1495,15 @@ void DivEngine::registerSystems() { {0x26, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, "26xx: Set envelope filter coefficient k2 ramp (signed) (00 to FF)",effectVal,constVal<0>}}, {0x27, {DIV_CMD_ES5506_ENVELOPE_K2RAMP, "27xx: Set envelope filter coefficient k2 ramp (signed, slower) (00 to FF)",effectVal,constVal<1>}} }; + EffectHandlerMap es5506PostEffectHandlerMap={ + {0x12, {DIV_CMD_ES5506_PAUSE, "120x: Set pause (bit 0)",effectValAnd<1>}} + }; const EffectHandler es5506ECountHandler(DIV_CMD_ES5506_ENVELOPE_COUNT, "2xxx: Set envelope count (000 to 1FF)", effectValLong<9>); - const EffectHandler es5506K1Handler(DIV_CMD_ES5506_FILTER_K1, "3xxx: Set filter coefficient K1 (000 to FFF)", effectValLongShift<12,4>); - const EffectHandler es5506K2Handler(DIV_CMD_ES5506_FILTER_K2, "4xxx: Set filter coefficient K2 (000 to FFF)", effectValLongShift<12,4>); - for (int i=0; i<2; i++) es5506PostEffectHandlerMap.emplace(0x20+i,es5506ECountHandler); - for (int i=0; i<16; i++) es5506PostEffectHandlerMap.emplace(0x30+i, es5506K1Handler); - for (int i=0; i<16; i++) es5506PostEffectHandlerMap.emplace(0x40+i, es5506K2Handler); + const EffectHandler es5506K1Handler(DIV_CMD_ES5506_FILTER_K1, "3xxx: Set filter coefficient K1 (000 to FFF)", effectValLongShift<12,4>,constVal<0xfff0>); + const EffectHandler es5506K2Handler(DIV_CMD_ES5506_FILTER_K2, "4xxx: Set filter coefficient K2 (000 to FFF)", effectValLongShift<12,4>,constVal<0xfff0>); + for (int i=0; i<2; i++) es5506PreEffectHandlerMap.emplace(0x20+i,es5506ECountHandler); + for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x30+i, es5506K1Handler); + for (int i=0; i<16; i++) es5506PreEffectHandlerMap.emplace(0x40+i, es5506K2Handler); // TODO: custom sample format sysDefs[DIV_SYSTEM_ES5506]=new DivSysDef( diff --git a/src/gui/debug.cpp b/src/gui/debug.cpp index 51b8fbea8..1956b2fcd 100644 --- a/src/gui/debug.cpp +++ b/src/gui/debug.cpp @@ -554,6 +554,24 @@ void putDispatchChip(void* data, int type) { ImGui::TextColored(ch->outStereo?colorOn:colorOff,">> OutStereo"); break; } + case DIV_SYSTEM_ES5506: { + DivPlatformES5506* ch=(DivPlatformES5506*)data; + ImGui::Text("> ES5506"); + COMMON_CHIP_DEBUG; + ImGui::Text("- cycle: %d",ch->cycle); + ImGui::Text("- curPage: %d",ch->curPage); + ImGui::Text("- maskedVal: %.2x",ch->maskedVal); + ImGui::Text("- irqv: %.2x",ch->irqv); + ImGui::Text("- curCR: %.8x",ch->curCR); + ImGui::Text("- prevChanCycle: %d",ch->prevChanCycle); + ImGui::Text("- initChanMax: %d",ch->initChanMax); + ImGui::Text("- chanMax: %d",ch->chanMax); + COMMON_CHIP_DEBUG_BOOL; + ImGui::TextColored(ch->isMasked?colorOn:colorOff,">> IsMasked"); + ImGui::TextColored(ch->isReaded?colorOn:colorOff,">> isReaded"); + ImGui::TextColored(ch->irqTrigger?colorOn:colorOff,">> IrqTrigger"); + break; + } default: ImGui::Text("Unimplemented chip! Help!"); break; @@ -1095,6 +1113,17 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::Text(" - K2Slide: %d",ch->k2Slide); ImGui::Text(" - K1Prev: %.4x",ch->k1Prev); ImGui::Text(" - K2Prev: %.4x",ch->k2Prev); + ImGui::Text("* Overwrite:"); + ImGui::Text(" * Filter:"); + ImGui::Text(" - Mode: %d",ch->overwrite.filter.mode); + ImGui::Text(" - K1: %.4x",ch->overwrite.filter.k1); + ImGui::Text(" - K2: %.4x",ch->overwrite.filter.k2); + ImGui::Text(" * Envelope:"); + ImGui::Text(" - EnvCount: %.3x",ch->overwrite.envelope.ecount); + ImGui::Text(" - LVRamp: %d",ch->overwrite.envelope.lVRamp); + ImGui::Text(" - RVRamp: %d",ch->overwrite.envelope.rVRamp); + ImGui::Text(" - K1Ramp: %d",ch->overwrite.envelope.k1Ramp); + ImGui::Text(" - K2Ramp: %d",ch->overwrite.envelope.k2Ramp); ImGui::Text("- vol: %.2x",ch->vol); ImGui::Text("- LVol: %.2x",ch->lVol); ImGui::Text("- RVol: %.2x",ch->rVol); @@ -1103,8 +1132,6 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::Text("- outRVol: %.2x",ch->outRVol); ImGui::Text("- ResLVol: %.2x",ch->resLVol); ImGui::Text("- ResRVol: %.2x",ch->resRVol); - ImGui::Text("- LOut: %d",ch->lOut); - ImGui::Text("- ROut: %d",ch->rOut); ImGui::Text("- oscOut: %d",ch->oscOut); ImGui::TextColored(ch->active?colorOn:colorOff,">> Active"); ImGui::TextColored(ch->insChanged?colorOn:colorOff,">> InsChanged"); @@ -1127,6 +1154,16 @@ void putDispatchChan(void* data, int chanNum, int type) { ImGui::TextColored(ch->pcm.reversed?colorOn:colorOff,">> PCMReversed"); ImGui::TextColored(ch->envelope.k1Slow?colorOn:colorOff,">> EnvK1Slow"); ImGui::TextColored(ch->envelope.k2Slow?colorOn:colorOff,">> EnvK2Slow"); + ImGui::TextColored(ch->overwrite.envelope.k1Slow?colorOn:colorOff,">> EnvK1SlowOverwrite"); + ImGui::TextColored(ch->overwrite.envelope.k2Slow?colorOn:colorOff,">> EnvK2SlowOverwrite"); + ImGui::TextColored(ch->overwrite.state.mode?colorOn:colorOff,">> FilterModeOverwrited"); + ImGui::TextColored(ch->overwrite.state.k1?colorOn:colorOff,">> FilterK1Overwrited"); + ImGui::TextColored(ch->overwrite.state.k2?colorOn:colorOff,">> FilterK2Overwrited"); + ImGui::TextColored(ch->overwrite.state.ecount?colorOn:colorOff,">> EnvECountOverwrited"); + ImGui::TextColored(ch->overwrite.state.lVRamp?colorOn:colorOff,">> EnvLVRampOverwrited"); + ImGui::TextColored(ch->overwrite.state.rVRamp?colorOn:colorOff,">> EnvRVRampOverwrited"); + ImGui::TextColored(ch->overwrite.state.k1Ramp?colorOn:colorOff,">> EnvK1RampOverwrited"); + ImGui::TextColored(ch->overwrite.state.k2Ramp?colorOn:colorOff,">> EnvK2RampOverwrited"); break; } case DIV_SYSTEM_LYNX: {