From 0f3f173b6e2660a4520003d5fc59e8811e7007c7 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Sun, 5 Dec 2021 16:11:12 -0500 Subject: [PATCH] rework some of the playback logic paving the way for C64 --- src/engine/dispatch.h | 1 + src/engine/engine.h | 5 ++- src/engine/platform/c64.cpp | 45 ++++---------------- src/engine/platform/c64.h | 6 +-- src/engine/playback.cpp | 82 ++++++++++++++++++++++--------------- 5 files changed, 65 insertions(+), 74 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 0ddb30469..12831b5fb 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -15,6 +15,7 @@ enum DivDispatchCmds { DIV_CMD_PANNING, DIV_CMD_LEGATO, DIV_CMD_PRE_PORTA, + DIV_CMD_PRE_NOTE, // used in C64 DIV_CMD_SAMPLE_MODE, diff --git a/src/engine/engine.h b/src/engine/engine.h index d6ab70006..47c17ff62 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -20,6 +20,7 @@ struct DivChannelState { std::vector delayed; int note, pitch, portaSpeed, portaNote; int volume, volSpeed, cut, rowDelay, volMax; + int delayOrder, delayRow; int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine; int tremoloDepth, tremoloRate, tremoloPos; unsigned char arp, arpStage, arpTicks; @@ -34,6 +35,8 @@ struct DivChannelState { volSpeed(0), cut(-1), rowDelay(0), + delayOrder(0), + delayRow(0), vibratoDepth(0), vibratoRate(0), vibratoPos(0), @@ -104,7 +107,7 @@ class DivEngine { speedAB(false), ticks(0), cycles(0), - curRow(-1), + curRow(0), curOrder(0), changeOrd(-1), changePos(0), diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index 5ab17b432..075e6938a 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -10,31 +10,6 @@ void DivPlatformC64::acquire(int& l, int& r) { r=l; } -static unsigned char noiseTable[256]={ - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 4, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, - 3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, - 3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4, - 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, - 3, 2, 1, 0, 11, 10, 9, 8, 7, 6, 5, 4, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15 -}; - void DivPlatformC64::tick() { for (int i=0; i<3; i++) { chan[i].std.next(); @@ -84,16 +59,10 @@ void DivPlatformC64::tick() { //rWrite(16+i*5,chan[i].sweep); } } - if (chan[i].onTheKey) { - DivInstrument* ins=parent->getIns(chan[i].ins); - sid.write(i*7+4, - (ins->c64.noiseOn<<7)| - (ins->c64.pulseOn<<6)| - (ins->c64.sawOn<<5)| - (ins->c64.triOn<<4)| - 1 - ); - chan[i].onTheKey=false; + if (chan[i].testWhen>0) { + if (--chan[i].testWhen<1) { + sid.write(i*7+4,8); + } } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { DivInstrument* ins=parent->getIns(chan[i].ins); @@ -106,9 +75,8 @@ void DivPlatformC64::tick() { (ins->c64.pulseOn<<6)| (ins->c64.sawOn<<5)| (ins->c64.triOn<<4)| - 8 + 1 ); - chan[i].onTheKey=true; } if (chan[i].keyOff) { sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d)); @@ -207,6 +175,9 @@ int DivPlatformC64::dispatch(DivCommand c) { chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); chan[c.chan].inPorta=c.value; break; + case DIV_CMD_PRE_NOTE: + chan[c.chan].testWhen=c.value; + break; case DIV_CMD_GET_VOLMAX: return 15; break; diff --git a/src/engine/platform/c64.h b/src/engine/platform/c64.h index efd6a405c..20fe9bf38 100644 --- a/src/engine/platform/c64.h +++ b/src/engine/platform/c64.h @@ -7,9 +7,9 @@ class DivPlatformC64: public DivDispatch { struct Channel { - int freq, baseFreq, pitch, prevFreq; + int freq, baseFreq, pitch, prevFreq, testWhen; unsigned char ins, note, duty, sweep; - bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, onTheKey; + bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta; signed char vol, outVol, wave; DivMacroInt std; Channel(): @@ -17,6 +17,7 @@ class DivPlatformC64: public DivDispatch { baseFreq(0), pitch(0), prevFreq(65535), + testWhen(0), ins(-1), note(0), duty(0), @@ -28,7 +29,6 @@ class DivPlatformC64: public DivDispatch { keyOn(false), keyOff(false), inPorta(false), - onTheKey(false), vol(15), wave(-1) {} }; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index f71afe877..0c9072517 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -23,6 +23,7 @@ const char* cmdName[DIV_CMD_MAX]={ "PANNING", "LEGATO", "PRE_PORTA", + "PRE_NOTE", "SAMPLE_MODE", @@ -205,25 +206,29 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char } void DivEngine::processRow(int i, bool afterDelay) { - DivPattern* pat=song.pat[i]->data[curOrder]; + int whatOrder=afterDelay?chan[i].delayOrder:curOrder; + int whatRow=afterDelay?chan[i].delayRow:curRow; + DivPattern* pat=song.pat[i]->data[whatOrder]; // pre effects if (!afterDelay) for (int j=0; jeffectRows; j++) { - short effect=pat->data[curRow][4+(j<<1)]; - short effectVal=pat->data[curRow][5+(j<<1)]; + short effect=pat->data[whatRow][4+(j<<1)]; + short effectVal=pat->data[whatRow][5+(j<<1)]; if (effectVal==-1) effectVal=0; if (effect==0xed) { chan[i].rowDelay=effectVal+1; + chan[i].delayOrder=whatOrder; + chan[i].delayRow=whatRow; return; } } // instrument - if (pat->data[curRow][2]!=-1) { - dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[curRow][2])); + if (pat->data[whatRow][2]!=-1) { + dispatchCmd(DivCommand(DIV_CMD_INSTRUMENT,i,pat->data[whatRow][2])); } // note - if (pat->data[curRow][0]==100) { + if (pat->data[whatRow][0]==100) { chan[i].note=-1; chan[i].keyOn=false; if (chan[i].stopOnOff) { @@ -232,8 +237,8 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].stopOnOff=false; } dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); - } else if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) { - chan[i].note=pat->data[curRow][0]+pat->data[curRow][1]*12; + } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) { + chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12; if (!chan[i].keyOn) { chan[i].arp=0; } @@ -244,17 +249,17 @@ void DivEngine::processRow(int i, bool afterDelay) { } // volume - if (pat->data[curRow][3]!=-1) { - if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[curRow][3]) { - chan[i].volume=pat->data[curRow][3]<<8; + if (pat->data[whatRow][3]!=-1) { + if (dispatchCmd(DivCommand(DIV_ALWAYS_SET_VOLUME,i)) || (MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[whatRow][3]) { + chan[i].volume=pat->data[whatRow][3]<<8; dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8)); } } // effects for (int j=0; jeffectRows; j++) { - short effect=pat->data[curRow][4+(j<<1)]; - short effectVal=pat->data[curRow][5+(j<<1)]; + short effect=pat->data[whatRow][4+(j<<1)]; + short effectVal=pat->data[whatRow][5+(j<<1)]; if (effectVal==-1) effectVal=0; @@ -336,6 +341,8 @@ void DivEngine::processRow(int i, bool afterDelay) { break; case 0x0c: // retrigger chan[i].rowDelay=effectVal+1; + chan[i].delayOrder=whatOrder; + chan[i].delayRow=whatRow; break; case 0xe0: // arp speed @@ -399,8 +406,8 @@ void DivEngine::processRow(int i, bool afterDelay) { // post effects for (int j=0; jeffectRows; j++) { - short effect=pat->data[curRow][4+(j<<1)]; - short effectVal=pat->data[curRow][5+(j<<1)]; + short effect=pat->data[whatRow][4+(j<<1)]; + short effectVal=pat->data[whatRow][5+(j<<1)]; if (effectVal==-1) effectVal=0; perSystemPostEffect(i,effect,effectVal); @@ -412,18 +419,6 @@ void DivEngine::nextRow() { static char pb1[4096]; static char pb2[4096]; static char pb3[4096]; - if (++curRow>=song.patLen) { - nextOrder(); - } - if (changeOrd>=0) { - curRow=changePos; - curOrder=changeOrd; - if (curOrder>=song.ordersLen) { - curOrder=0; - } - changeOrd=-1; - } - if (view==DIV_STATUS_PATTERN) { strcpy(pb1,""); strcpy(pb3,""); @@ -469,6 +464,33 @@ void DivEngine::nextRow() { chan[i].rowDelay=0; processRow(i,false); } + + if (++curRow>=song.patLen) { + nextOrder(); + } + if (changeOrd>=0) { + curRow=changePos; + curOrder=changeOrd; + if (curOrder>=song.ordersLen) { + curOrder=0; + } + changeOrd=-1; + } + + if (speedAB) { + ticks=song.speed2*(song.timeBase+1); + } else { + ticks=song.speed1*(song.timeBase+1); + } + speedAB=!speedAB; + + // post row details + for (int i=0; idata[curOrder]; + if (!(pat->data[curRow][0]==0 && pat->data[curRow][1]==0)) { + dispatchCmd(DivCommand(DIV_CMD_PRE_NOTE,i,ticks)); + } + } } void DivEngine::nextTick() { @@ -483,12 +505,6 @@ void DivEngine::nextTick() { } if (--ticks<=0) { nextRow(); - if (speedAB) { - ticks=song.speed2*(song.timeBase+1); - } else { - ticks=song.speed1*(song.timeBase+1); - } - speedAB=!speedAB; } // process stuff for (int i=0; i