From e87239f8ced53968a342f7fb3908b98b4d70d384 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 19 Jan 2022 00:01:34 -0500 Subject: [PATCH] fix retrigger implementation no longer broken --- src/engine/dispatch.h | 2 ++ src/engine/engine.h | 4 +++- src/engine/platform/amiga.cpp | 10 +++++++--- src/engine/platform/arcade.cpp | 6 ++++-- src/engine/platform/ay.cpp | 8 +++++--- src/engine/platform/ay8930.cpp | 8 +++++--- src/engine/platform/c64.cpp | 8 +++++--- src/engine/platform/dummy.cpp | 6 ++++-- src/engine/platform/gb.cpp | 14 ++++++++------ src/engine/platform/genesis.cpp | 6 ++++-- src/engine/platform/genesisext.cpp | 6 ++++-- src/engine/platform/nes.cpp | 14 ++++++++++---- src/engine/platform/pce.cpp | 10 ++++++---- src/engine/platform/saa.cpp | 8 +++++--- src/engine/platform/sms.cpp | 8 +++++--- src/engine/platform/tia.cpp | 8 +++++--- src/engine/platform/ym2610.cpp | 14 +++++++++----- src/engine/platform/ym2610ext.cpp | 6 ++++-- src/engine/playback.cpp | 13 ++++++++++--- 19 files changed, 105 insertions(+), 54 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 52477f7b0..ef3190eeb 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -6,6 +6,8 @@ #define ONE_SEMITONE 2200 +#define DIV_NOTE_NULL 0x7fffffff + #define addWrite(a,v) regWrites.push_back(DivRegWrite(a,v)); enum DivDispatchCmds { diff --git a/src/engine/engine.h b/src/engine/engine.h index 128aad2f7..40480863f 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -34,7 +34,7 @@ struct DivChannelState { std::vector delayed; int note, oldNote, pitch, portaSpeed, portaNote; int volume, volSpeed, cut, rowDelay, volMax; - int delayOrder, delayRow; + int delayOrder, delayRow, retrigSpeed, retrigTick; int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine; int tremoloDepth, tremoloRate, tremoloPos; unsigned char arp, arpStage, arpTicks; @@ -53,6 +53,8 @@ struct DivChannelState { volMax(0), delayOrder(0), delayRow(0), + retrigSpeed(0), + retrigTick(0), vibratoDepth(0), vibratoRate(0), vibratoPos(0), diff --git a/src/engine/platform/amiga.cpp b/src/engine/platform/amiga.cpp index 831416a0a..c6734108c 100644 --- a/src/engine/platform/amiga.cpp +++ b/src/engine/platform/amiga.cpp @@ -95,15 +95,19 @@ int DivPlatformAmiga::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + } chan[c.chan].sample=ins->amiga.initSample; if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) { chan[c.chan].sample=-1; } chan[c.chan].audPos=0; chan[c.chan].audSub=0; - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index b7500fef0..ec3e0ac2f 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -249,8 +249,10 @@ int DivPlatformArcade::dispatch(DivCommand c) { } chan[c.chan].insChanged=false; - chan[c.chan].baseFreq=c.value<<6; - chan[c.chan].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=c.value<<6; + chan[c.chan].freqChanged=true; + } chan[c.chan].keyOn=true; chan[c.chan].active=true; break; diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 41fd89ecc..2f3d62c4a 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -126,9 +126,11 @@ int DivPlatformAY8910::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 8ec3428ac..9b9cb26ba 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -152,9 +152,11 @@ int DivPlatformAY8930::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); diff --git a/src/engine/platform/c64.cpp b/src/engine/platform/c64.cpp index 4239a2ae7..414544056 100644 --- a/src/engine/platform/c64.cpp +++ b/src/engine/platform/c64.cpp @@ -103,9 +103,11 @@ int DivPlatformC64::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=round(FREQ_BASE*pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(FREQ_BASE*pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacroLen>0) { diff --git a/src/engine/platform/dummy.cpp b/src/engine/platform/dummy.cpp index bd0082159..497e2a01d 100644 --- a/src/engine/platform/dummy.cpp +++ b/src/engine/platform/dummy.cpp @@ -34,8 +34,10 @@ void DivPlatformDummy::tick() { int DivPlatformDummy::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: - chan[c.chan].baseFreq=65.6f*pow(2.0f,((float)c.value/12.0f)); - chan[c.chan].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=65.6f*pow(2.0f,((float)c.value/12.0f)); + chan[c.chan].freqChanged=true; + } chan[c.chan].active=true; chan[c.chan].amp=64; break; diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 7cef95f58..e642a524e 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -176,13 +176,15 @@ void DivPlatformGB::muteChannel(int ch, bool mute) { int DivPlatformGB::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: - if (c.chan==3) { // noise - chan[c.chan].baseFreq=c.value; - } else { - chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + if (c.value!=DIV_NOTE_NULL) { + if (c.chan==3) { // noise + chan[c.chan].baseFreq=c.value; + } else { + chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + } + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; } - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 11c903976..441872fb7 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -209,8 +209,10 @@ int DivPlatformGenesis::dispatch(DivCommand c) { } chan[c.chan].insChanged=false; - chan[c.chan].baseFreq=644.0f*pow(2.0f,((float)c.value/12.0f)); - chan[c.chan].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=644.0f*pow(2.0f,((float)c.value/12.0f)); + chan[c.chan].freqChanged=true; + } chan[c.chan].keyOn=true; chan[c.chan].active=true; break; diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index abc4ec8c9..fb81d8f8d 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -45,8 +45,10 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { } opChan[ch].insChanged=false; - opChan[ch].baseFreq=644.0f*pow(2.0f,((float)c.value/12.0f)); - opChan[ch].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + opChan[ch].baseFreq=644.0f*pow(2.0f,((float)c.value/12.0f)); + opChan[ch].freqChanged=true; + } opChan[ch].keyOn=true; opChan[ch].active=true; break; diff --git a/src/engine/platform/nes.cpp b/src/engine/platform/nes.cpp index 40c8d210c..48157df56 100644 --- a/src/engine/platform/nes.cpp +++ b/src/engine/platform/nes.cpp @@ -170,12 +170,18 @@ int DivPlatformNES::dispatch(DivCommand c) { dacRate=parent->song.sample[dacSample]->rate; break; } else if (c.chan==3) { // noise - chan[c.chan].baseFreq=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=c.value; + } } else { - chan[c.chan].baseFreq=round(freqBase/pow(2.0f,((float)c.value/12.0f))); + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(freqBase/pow(2.0f,((float)c.value/12.0f))); + } + } + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; } - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); diff --git a/src/engine/platform/pce.cpp b/src/engine/platform/pce.cpp index f8a4b7b0b..cc6121368 100644 --- a/src/engine/platform/pce.cpp +++ b/src/engine/platform/pce.cpp @@ -159,10 +159,12 @@ int DivPlatformPCE::dispatch(DivCommand c) { chan[c.chan].dacRate=1789773/parent->song.sample[chan[c.chan].dacSample]->rate; break; } - chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; - chWrite(c.chan,0x07,chan[c.chan].noise?(0x80|noiseFreq[chan[c.chan].note%12]):0); + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + chWrite(c.chan,0x07,chan[c.chan].noise?(0x80|noiseFreq[chan[c.chan].note%12]):0); + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chWrite(c.chan,0x04,0x80|chan[c.chan].vol); diff --git a/src/engine/platform/saa.cpp b/src/engine/platform/saa.cpp index e853e9556..4455ff4b4 100644 --- a/src/engine/platform/saa.cpp +++ b/src/engine/platform/saa.cpp @@ -123,9 +123,11 @@ int DivPlatformSAA1099::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 515ce769e..258f5434f 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -90,9 +90,11 @@ void DivPlatformSMS::tick() { int DivPlatformSMS::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: - chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; rWrite(0x90|c.chan<<5|(isMuted[c.chan]?15:(15-(chan[c.chan].vol&15)))); chan[c.chan].std.init(parent->getIns(chan[c.chan].ins)); diff --git a/src/engine/platform/tia.cpp b/src/engine/platform/tia.cpp index 25d408ab1..9816eee63 100644 --- a/src/engine/platform/tia.cpp +++ b/src/engine/platform/tia.cpp @@ -109,9 +109,11 @@ int DivPlatformTIA::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins); - chan[c.chan].baseFreq=c.value<<8; - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=c.value<<8; + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; rWrite(0x15+c.chan,chan[c.chan].shape); diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index f0f13d57b..55443da5c 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -223,9 +223,11 @@ int DivPlatformYM2610::dispatch(DivCommand c) { DivInstrument* ins=parent->getIns(chan[c.chan].ins); if (c.chan>3) { // PSG - chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); - chan[c.chan].freqChanged=true; - chan[c.chan].note=c.value; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=round(PSG_FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); + chan[c.chan].freqChanged=true; + chan[c.chan].note=c.value; + } chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].std.init(ins); @@ -264,8 +266,10 @@ int DivPlatformYM2610::dispatch(DivCommand c) { } chan[c.chan].insChanged=false; - chan[c.chan].baseFreq=FM_FREQ_BASE*pow(2.0f,((float)c.value/12.0f)); - chan[c.chan].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + chan[c.chan].baseFreq=FM_FREQ_BASE*pow(2.0f,((float)c.value/12.0f)); + chan[c.chan].freqChanged=true; + } chan[c.chan].keyOn=true; chan[c.chan].active=true; break; diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index 00360c630..d582199f5 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -45,8 +45,10 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) { } opChan[ch].insChanged=false; - opChan[ch].baseFreq=FM_FREQ_BASE*pow(2.0f,((float)c.value/12.0f)); - opChan[ch].freqChanged=true; + if (c.value!=DIV_NOTE_NULL) { + opChan[ch].baseFreq=FM_FREQ_BASE*pow(2.0f,((float)c.value/12.0f)); + opChan[ch].freqChanged=true; + } opChan[ch].keyOn=true; opChan[ch].active=true; break; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 0d32a4c49..e0835d940 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -468,6 +468,8 @@ void DivEngine::processRow(int i, bool afterDelay) { } } + chan[i].retrigSpeed=0; + // effects for (int j=0; jdata[whatRow][4+(j<<1)]; @@ -566,9 +568,8 @@ void DivEngine::processRow(int i, bool afterDelay) { break; case 0x0c: // retrigger if (effectVal!=0) { - chan[i].rowDelay=effectVal; // this was +1 before. what happened?! - chan[i].delayOrder=whatOrder; - chan[i].delayRow=whatRow; + chan[i].retrigSpeed=effectVal; + chan[i].retrigTick=0; } break; case 0xc0: case 0xc1: case 0xc2: case 0xc3: // set Hz @@ -797,6 +798,12 @@ bool DivEngine::nextTick(bool noAccum) { processRow(i,true); } } + if (chan[i].retrigSpeed) { + if (--chan[i].retrigTick<0) { + chan[i].retrigTick=chan[i].retrigSpeed-1; + dispatchCmd(DivCommand(DIV_CMD_NOTE_ON,i,DIV_NOTE_NULL)); + } + } if (chan[i].volSpeed!=0) { chan[i].volume=(chan[i].volume&0xff)|(dispatchCmd(DivCommand(DIV_CMD_GET_VOLUME,i))<<8); chan[i].volume+=chan[i].volSpeed;