diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index f8c307ae7..0436ce2f7 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -31,6 +31,13 @@ enum DivDispatchCmds { DIV_CMD_STD_NOISE_FREQ, DIV_CMD_STD_NOISE_MODE, + DIV_CMD_WAVE, + + DIV_CMD_GB_SWEEP_TIME, + DIV_CMD_GB_SWEEP_DIR, + + DIV_ALWAYS_SET_VOLUME, + DIV_CMD_MAX }; diff --git a/src/engine/engine.h b/src/engine/engine.h index 046fc24c1..650f908ad 100644 --- a/src/engine/engine.h +++ b/src/engine/engine.h @@ -18,7 +18,7 @@ struct DivChannelState { int vibratoDepth, vibratoRate, vibratoPos, vibratoDir, vibratoFine; int tremoloDepth, tremoloRate, tremoloPos; unsigned char arp, arpStage, arpTicks; - bool doNote, legato, portaStop, keyOn, nowYouCanStop, stopOnOff; + bool doNote, legato, portaStop, keyOn, nowYouCanStop, stopOnOff, arpYield; DivChannelState(): note(-1), @@ -40,7 +40,7 @@ struct DivChannelState { arp(0), arpStage(-1), arpTicks(1), - doNote(false), legato(false), portaStop(false), keyOn(false), nowYouCanStop(true), stopOnOff(false) {} + doNote(false), legato(false), portaStop(false), keyOn(false), nowYouCanStop(true), stopOnOff(false), arpYield(false) {} }; class DivEngine { diff --git a/src/engine/platform/gb.cpp b/src/engine/platform/gb.cpp index 74e731451..efc5cf01a 100644 --- a/src/engine/platform/gb.cpp +++ b/src/engine/platform/gb.cpp @@ -169,11 +169,9 @@ int DivPlatformGB::dispatch(DivCommand c) { } break; case DIV_CMD_VOLUME: - if (chan[c.chan].vol!=c.value) { - chan[c.chan].vol=c.value; - if (c.chan==2) { - rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].vol]); - } + chan[c.chan].vol=c.value; + if (c.chan==2) { + rWrite(16+c.chan*5+2,gbVolMap[chan[c.chan].vol]); } break; case DIV_CMD_GET_VOLUME: @@ -183,6 +181,12 @@ int DivPlatformGB::dispatch(DivCommand c) { chan[c.chan].pitch=c.value; chan[c.chan].freqChanged=true; break; + case DIV_CMD_WAVE: + if (c.chan!=2) break; + chan[c.chan].wave=c.value; + updateWave(); + chan[c.chan].freqChanged=true; + break; case DIV_CMD_NOTE_PORTA: { int destFreq=round(FREQ_BASE/pow(2.0f,((float)c.value2/12.0f))); bool return2=false; @@ -225,6 +229,9 @@ int DivPlatformGB::dispatch(DivCommand c) { case DIV_CMD_GET_VOLMAX: return 15; break; + case DIV_ALWAYS_SET_VOLUME: + return 1; + break; default: break; } diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 88a04542d..fc3caab59 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -312,6 +312,9 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; } + case DIV_ALWAYS_SET_VOLUME: + return 0; + break; case DIV_CMD_GET_VOLMAX: return 127; break; diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index 5232ef942..cd84f7115 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -170,6 +170,9 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_GET_VOLMAX: return 127; break; + case DIV_ALWAYS_SET_VOLUME: + return 0; + break; case DIV_CMD_PRE_PORTA: break; default: diff --git a/src/engine/platform/sms.cpp b/src/engine/platform/sms.cpp index 9af28b49a..b88415229 100644 --- a/src/engine/platform/sms.cpp +++ b/src/engine/platform/sms.cpp @@ -147,6 +147,9 @@ int DivPlatformSMS::dispatch(DivCommand c) { case DIV_CMD_GET_VOLMAX: return 15; break; + case DIV_ALWAYS_SET_VOLUME: + return 0; + break; default: break; } diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index baba91199..a8b383c1f 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -37,7 +37,14 @@ const char* cmdName[DIV_CMD_MAX]={ "ARCADE_LFO", "STD_NOISE_FREQ", - "STD_NOISE_MODE" + "STD_NOISE_MODE", + + "WAVE", + + "GB_SWEEP_TIME", + "GB_SWEEP_DIR", + + "ALWAYS_SET_VOLUME" }; const char* formatNote(unsigned char note, unsigned char octave) { @@ -83,6 +90,15 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe return false; } break; + case DIV_SYSTEM_GB: + switch (effect) { + case 0x10: // select waveform + dispatchCmd(DivCommand(DIV_CMD_WAVE,ch,effectVal)); + break; + default: + return false; + } + break; default: return false; } @@ -176,11 +192,14 @@ void DivEngine::processRow(int i, bool afterDelay) { chan[i].arp=0; } chan[i].doNote=true; + if (chan[i].arp!=0) { + chan[i].arpYield=true; + } } // volume if (pat->data[curRow][3]!=-1) { - if ((MIN(chan[i].volMax,chan[i].volume)>>8)!=pat->data[curRow][3]) { + 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; dispatchCmd(DivCommand(DIV_CMD_VOLUME,i,chan[i].volume>>8)); } @@ -473,7 +492,7 @@ void DivEngine::nextTick() { dispatchCmd(DivCommand(DIV_CMD_NOTE_OFF,i)); } } - if (chan[i].arp!=0 && chan[i].portaSpeed<1) { + if (chan[i].arp!=0 && !chan[i].arpYield && chan[i].portaSpeed<1) { if (--chan[i].arpTicks<1) { chan[i].arpTicks=song.arpLen; chan[i].arpStage++; @@ -490,6 +509,8 @@ void DivEngine::nextTick() { break; } } + } else { + chan[i].arpYield=false; } }