From dc5990a37eee579f7a8d2af2aa3e571ca762b4d0 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 29 Dec 2021 02:08:50 -0500 Subject: [PATCH] a lot of master system fixes! fixes forest frolick, professional tracker, YZYX, Monday (kinda), MasterTracker and Ice Fields --- src/engine/dispatch.h | 14 +++++++++++++ src/engine/engine.cpp | 1 + src/engine/platform/abstract.cpp | 8 ++++++++ src/engine/platform/genesis.cpp | 4 ++++ src/engine/platform/genesis.h | 1 + src/engine/platform/genesisext.cpp | 4 ++++ src/engine/platform/genesisext.h | 1 + src/engine/platform/sms.cpp | 32 ++++++++++++++++++++++-------- src/engine/platform/sms.h | 2 ++ src/engine/playback.cpp | 19 +++++++++++++----- 10 files changed, 73 insertions(+), 13 deletions(-) diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index e5ed9407..b2438aa4 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -165,6 +165,20 @@ class DivDispatch { */ virtual bool keyOffAffectsArp(int ch); + /** + * test whether sending a key off command to a channel should reset slides too. + * @param ch the channel in question. + * @return whether it does. + */ + virtual bool keyOffAffectsPorta(int ch); + + /** + * get the lowest note in a portamento. + * @param ch the channel in question. + * @return the lowest note. + */ + virtual int getPortaFloor(int ch); + /** * set the region to PAL. * @param pal whether to set it to PAL. diff --git a/src/engine/engine.cpp b/src/engine/engine.cpp index fc61fa80..cae2166b 100644 --- a/src/engine/engine.cpp +++ b/src/engine/engine.cpp @@ -1565,6 +1565,7 @@ void DivEngine::reset() { extValuePresent=0; speed1=song.speed1; speed2=song.speed2; + nextSpeed=speed1; globalPitch=0; dispatch->reset(); } diff --git a/src/engine/platform/abstract.cpp b/src/engine/platform/abstract.cpp index 8f5ad455..c7881531 100644 --- a/src/engine/platform/abstract.cpp +++ b/src/engine/platform/abstract.cpp @@ -31,6 +31,14 @@ bool DivDispatch::keyOffAffectsArp(int ch) { return false; } +bool DivDispatch::keyOffAffectsPorta(int ch) { + return false; +} + +int DivDispatch::getPortaFloor(int ch) { + return 0x00; +} + void DivDispatch::setPAL(bool pal) { } diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 7b11b1b1..203a4c00 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -419,6 +419,10 @@ bool DivPlatformGenesis::keyOffAffectsArp(int ch) { return (ch>5); } +bool DivPlatformGenesis::keyOffAffectsPorta(int ch) { + return (ch>5); +} + void DivPlatformGenesis::setPAL(bool pal) { if (pal) { rate=211125; diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 427c628c..53d731c3 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -58,6 +58,7 @@ class DivPlatformGenesis: public DivDispatch { void muteChannel(int ch, bool mute); bool isStereo(); bool keyOffAffectsArp(int ch); + bool keyOffAffectsPorta(int ch); void setPAL(bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal); void quit(); diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 50669c44..792b0c7e 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -306,6 +306,10 @@ bool DivPlatformGenesisExt::keyOffAffectsArp(int ch) { return (ch>8); } +bool DivPlatformGenesisExt::keyOffAffectsPorta(int ch) { + return (ch>8); +} + int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, bool pal) { DivPlatformGenesis::init(parent,channels,sugRate,pal); for (int i=0; i<4; i++) { diff --git a/src/engine/platform/genesisext.h b/src/engine/platform/genesisext.h index de77c085..21daeaa0 100644 --- a/src/engine/platform/genesisext.h +++ b/src/engine/platform/genesisext.h @@ -22,6 +22,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis { void tick(); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); + bool keyOffAffectsPorta(int ch); int init(DivEngine* parent, int channels, int sugRate, bool pal); void quit(); ~DivPlatformGenesisExt(); diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index acb87a12..7b072b98 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -2,6 +2,8 @@ #include "../engine.h" #include +#define FREQ_BASE 1712.0f + void DivPlatformSMS::acquire(short* bufL, short* bufR, size_t start, size_t len) { sn->sound_stream_update(bufL+start,len); } @@ -21,14 +23,19 @@ void DivPlatformSMS::tick() { } if (chan[i].std.hadArp) { if (chan[i].std.arpMode) { - chan[i].baseFreq=round(1712.0f/pow(2.0f,((float)(chan[i].std.arp)/12.0f))); + chan[i].baseFreq=round(FREQ_BASE/pow(2.0f,((float)(chan[i].std.arp)/12.0f))); } else { - chan[i].baseFreq=round(1712.0f/pow(2.0f,((float)(chan[i].note+chan[i].std.arp-12)/12.0f))); + chan[i].baseFreq=round(FREQ_BASE/pow(2.0f,((float)(chan[i].note+chan[i].std.arp-12)/12.0f))); } chan[i].freqChanged=true; + } else { + if (chan[i].std.arpMode && chan[i].std.finishedArp) { + chan[i].baseFreq=round(FREQ_BASE/pow(2.0f,((float)(chan[i].note)/12.0f))); + chan[i].freqChanged=true; + } } - if (chan[i].std.hadDuty) { - snNoiseMode=(snNoiseMode&2)|(chan[i].std.duty&1); + if (i==3) if (chan[i].std.hadDuty) { + snNoiseMode=chan[i].std.duty; if (chan[i].std.duty<2) { chan[3].freqChanged=false; } @@ -46,7 +53,8 @@ void DivPlatformSMS::tick() { } if (chan[3].freqChanged || updateSNMode) { updateSNMode=false; - chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch,true); + // seems arbitrary huh? + chan[3].freq=parent->calcFreq(chan[3].baseFreq,chan[3].pitch-1,true); if (chan[3].note>0x5d) chan[3].freq=0x01; chan[3].freqChanged=false; if (snNoiseMode&2) { // take period from channel 3 @@ -80,7 +88,7 @@ void DivPlatformSMS::tick() { int DivPlatformSMS::dispatch(DivCommand c) { switch (c.cmd) { case DIV_CMD_NOTE_ON: - chan[c.chan].baseFreq=round(1712.0f/pow(2.0f,((float)c.value/12.0f))); + 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; @@ -116,7 +124,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { chan[c.chan].freqChanged=true; break; case DIV_CMD_NOTE_PORTA: { - int destFreq=round(1712.0f/pow(2.0f,((float)c.value2/12.0f))); + int destFreq=round(FREQ_BASE/pow(2.0f,((float)c.value2/12.0f))); bool return2=false; if (destFreq>chan[c.chan].baseFreq) { chan[c.chan].baseFreq+=c.value; @@ -140,7 +148,7 @@ int DivPlatformSMS::dispatch(DivCommand c) { updateSNMode=true; break; case DIV_CMD_LEGATO: - chan[c.chan].baseFreq=round(1712.0f/pow(2.0f,((float)(c.value+((chan[c.chan].std.willArp && !chan[c.chan].std.arpMode)?(chan[c.chan].std.arp-12):(0)))/12.0f))); + chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)(c.value+((chan[c.chan].std.willArp && !chan[c.chan].std.arpMode)?(chan[c.chan].std.arp-12):(0)))/12.0f))); chan[c.chan].freqChanged=true; chan[c.chan].note=c.value; break; @@ -177,6 +185,14 @@ bool DivPlatformSMS::keyOffAffectsArp(int ch) { return true; } +bool DivPlatformSMS::keyOffAffectsPorta(int ch) { + return true; +} + +int DivPlatformSMS::getPortaFloor(int ch) { + return 12; +} + void DivPlatformSMS::setPAL(bool pal) { if (pal) { rate=221681; diff --git a/src/engine/platform/sms.h b/src/engine/platform/sms.h index 3109e82b..3b5ac640 100644 --- a/src/engine/platform/sms.h +++ b/src/engine/platform/sms.h @@ -39,6 +39,8 @@ class DivPlatformSMS: public DivDispatch { void tick(); void muteChannel(int ch, bool mute); bool keyOffAffectsArp(int ch); + bool keyOffAffectsPorta(int ch); + int getPortaFloor(int ch); void setPAL(bool pal); int init(DivEngine* parent, int channels, int sugRate, bool pal); void quit(); diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 7570e0a0..eb1cd41f 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -347,6 +347,14 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].portaSpeed=-1; chan[i].stopOnOff=false; } + if (dispatch->keyOffAffectsPorta(i)) { + chan[i].portaNote=-1; + chan[i].portaSpeed=-1; + if (i==2 && song.system==DIV_SYSTEM_SMS) { + chan[i+1].portaNote=-1; + chan[i+1].portaSpeed=-1; + } + } dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); } else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) { chan[i].oldNote=chan[i].note; @@ -419,7 +427,7 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].portaSpeed=-1; chan[i].inPorta=false; } else { - chan[i].portaNote=0x00; + chan[i].portaNote=dispatch->getPortaFloor(i); chan[i].portaSpeed=effectVal; chan[i].portaStop=true; chan[i].nowYouCanStop=false; @@ -467,11 +475,12 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].arp=effectVal; break; case 0x0c: // retrigger - chan[i].rowDelay=effectVal+1; - chan[i].delayOrder=whatOrder; - chan[i].delayRow=whatRow; + if (effectVal!=0) { + chan[i].rowDelay=effectVal; // this was +1 before. what happened?! + chan[i].delayOrder=whatOrder; + chan[i].delayRow=whatRow; + } break; - case 0xe0: // arp speed song.arpLen=effectVal; break;