diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 5a1c2db64..37e36a2bf 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -56,6 +56,7 @@ enum DivDispatchCmds { DIV_CMD_SAMPLE_BANK, DIV_CMD_SAMPLE_POS, + DIV_CMD_FM_HARD_RESET, DIV_CMD_FM_LFO, DIV_CMD_FM_LFO_WAVE, DIV_CMD_FM_TL, diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index 7c465a511..e9618f29b 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -132,6 +132,9 @@ const char* DivPlatformArcade::getEffectName(unsigned char effect) { case 0x1f: return "1Fxx: Set PM depth (0 to 7F)"; break; + case 0x30: + return "30xx: Toggle hard envelope reset on new notes"; + break; } return NULL; } diff --git a/src/engine/platform/arcade.h b/src/engine/platform/arcade.h index a305eefdb..a6ec82c94 100644 --- a/src/engine/platform/arcade.h +++ b/src/engine/platform/arcade.h @@ -39,10 +39,30 @@ class DivPlatformArcade: public DivDispatch { int freq, baseFreq, pitch, note; unsigned char ins; signed char konCycles; - bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM; + bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset; int vol, outVol; unsigned char chVolL, chVolR; - Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), note(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), inPorta(false), portaPause(false), furnacePCM(false), vol(0), outVol(0), chVolL(127), chVolR(127) {} + Channel(): + freqH(0), + freqL(0), + freq(0), + baseFreq(0), + pitch(0), + note(0), + ins(-1), + active(false), + insChanged(true), + freqChanged(false), + keyOn(false), + keyOff(false), + inPorta(false), + portaPause(false), + furnacePCM(false), + hardReset(false), + vol(0), + outVol(0), + chVolL(127), + chVolR(127) {} }; Channel chan[8]; struct QueuedWrite { diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 0aff2b43a..ba9c0f566 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -74,9 +74,9 @@ const char* DivPlatformGenesis::getEffectName(unsigned char effect) { case 0x1d: return "1Dxx: Set attack of operator 4 (0 to 1F)"; break; - case 0x20: - return "20xy: Set PSG noise mode (x: preset freq/ch3 freq; y: thin pulse/noise)"; - break; + case 0x30: + return "30xx: Toggle hard envelope reset on new notes"; + break; } return NULL; } @@ -346,7 +346,25 @@ void DivPlatformGenesis::tick() { } if (chan[i].keyOn || chan[i].keyOff) { + if (chan[i].hardReset && chan[i].keyOn) { + for (int j=0; j<4; j++) { + unsigned short baseAddr=chanOffs[i]|opOffs[j]; + immWrite(baseAddr+ADDR_SL_RR,0x0f); + immWrite(baseAddr+ADDR_TL,0x7f); + oldWrites[baseAddr+ADDR_SL_RR]=-1; + oldWrites[baseAddr+ADDR_TL]=-1; + //rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); + } + } immWrite(0x28,0x00|konOffs[i]); + if (chan[i].hardReset && chan[i].keyOn) { + for (int j=0; j<4; j++) { + unsigned short baseAddr=chanOffs[i]|opOffs[j]; + for (int k=0; k<5; k++) { + immWrite(baseAddr+ADDR_SL_RR,0x0f); + } + } + } chan[i].keyOff=false; } } @@ -715,9 +733,11 @@ int DivPlatformGenesis::dispatch(DivCommand c) { unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); } - break; } + case DIV_CMD_FM_HARD_RESET: + chan[c.chan].hardReset=c.value; + break; case DIV_ALWAYS_SET_VOLUME: return 0; break; diff --git a/src/engine/platform/genesis.h b/src/engine/platform/genesis.h index 095744dfe..51d98d807 100644 --- a/src/engine/platform/genesis.h +++ b/src/engine/platform/genesis.h @@ -38,7 +38,7 @@ class DivPlatformGenesis: public DivDispatch { unsigned char freqH, freqL; int freq, baseFreq, pitch, note; unsigned char ins; - bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta; + bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, furnaceDac, inPorta, hardReset; int vol, outVol; unsigned char pan; Channel(): @@ -57,6 +57,7 @@ class DivPlatformGenesis: public DivDispatch { portaPause(false), furnaceDac(false), inPorta(false), + hardReset(false), vol(0), pan(3) {} }; diff --git a/src/engine/platform/tx81z.h b/src/engine/platform/tx81z.h index b3d00e523..363d5c234 100644 --- a/src/engine/platform/tx81z.h +++ b/src/engine/platform/tx81z.h @@ -38,10 +38,30 @@ class DivPlatformTX81Z: public DivDispatch { int freq, baseFreq, pitch, note; unsigned char ins; signed char konCycles; - bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM; + bool active, insChanged, freqChanged, keyOn, keyOff, inPorta, portaPause, furnacePCM, hardReset; int vol, outVol; unsigned char chVolL, chVolR; - Channel(): freqH(0), freqL(0), freq(0), baseFreq(0), pitch(0), note(0), ins(-1), active(false), insChanged(true), freqChanged(false), keyOn(false), keyOff(false), inPorta(false), portaPause(false), furnacePCM(false), vol(0), outVol(0), chVolL(127), chVolR(127) {} + Channel(): + freqH(0), + freqL(0), + freq(0), + baseFreq(0), + pitch(0), + note(0), + ins(-1), + active(false), + insChanged(true), + freqChanged(false), + keyOn(false), + keyOff(false), + inPorta(false), + portaPause(false), + furnacePCM(false), + hardReset(false), + vol(0), + outVol(0), + chVolL(127), + chVolR(127) {} }; Channel chan[8]; struct QueuedWrite { diff --git a/src/engine/platform/ym2610.h b/src/engine/platform/ym2610.h index bc70144e6..2fd525b08 100644 --- a/src/engine/platform/ym2610.h +++ b/src/engine/platform/ym2610.h @@ -46,7 +46,7 @@ class DivPlatformYM2610: public DivDispatch { int freq, baseFreq, pitch, note; unsigned char ins, psgMode, autoEnvNum, autoEnvDen; signed char konCycles; - bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM; + bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset; int vol, outVol; int sample; unsigned char pan; @@ -70,6 +70,7 @@ class DivPlatformYM2610: public DivDispatch { portaPause(false), inPorta(false), furnacePCM(false), + hardReset(false), vol(0), outVol(15), sample(-1), diff --git a/src/engine/platform/ym2610b.h b/src/engine/platform/ym2610b.h index 85b9b4514..d6b616c50 100644 --- a/src/engine/platform/ym2610b.h +++ b/src/engine/platform/ym2610b.h @@ -38,7 +38,7 @@ class DivPlatformYM2610B: public DivDispatch { int freq, baseFreq, pitch, note; unsigned char ins, psgMode, autoEnvNum, autoEnvDen; signed char konCycles; - bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM; + bool active, insChanged, freqChanged, keyOn, keyOff, portaPause, inPorta, furnacePCM, hardReset; int vol, outVol; int sample; unsigned char pan; @@ -62,6 +62,7 @@ class DivPlatformYM2610B: public DivDispatch { portaPause(false), inPorta(false), furnacePCM(false), + hardReset(false), vol(0), outVol(15), sample(-1), diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 0118acc42..a9497d667 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -61,6 +61,7 @@ const char* cmdName[DIV_CMD_MAX]={ "SAMPLE_BANK", "SAMPLE_POS", + "FM_HARD_RESET", "FM_LFO", "FM_LFO_WAVE", "FM_TL", @@ -240,6 +241,23 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe case 0x20: // SN noise mode dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal)); break; + case 0x30: // toggle hard-reset + dispatchCmd(DivCommand(DIV_CMD_FM_HARD_RESET,ch,effectVal)); + break; + default: + return false; + } + break; + case DIV_SYSTEM_YM2151: + case DIV_SYSTEM_YM2610: + case DIV_SYSTEM_YM2610_EXT: + case DIV_SYSTEM_YM2610B: + case DIV_SYSTEM_YM2610B_EXT: + case DIV_SYSTEM_OPZ: + switch (effect) { + case 0x30: // toggle hard-reset + dispatchCmd(DivCommand(DIV_CMD_FM_HARD_RESET,ch,effectVal)); + break; default: return false; } @@ -340,6 +358,22 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe case 0x18: // drum mode toggle dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal)); break; + case 0x30: // toggle hard-reset + dispatchCmd(DivCommand(DIV_CMD_FM_HARD_RESET,ch,effectVal)); + break; + default: + return false; + } + break; + case DIV_SYSTEM_OPLL: + case DIV_SYSTEM_VRC7: + case DIV_SYSTEM_OPL: + case DIV_SYSTEM_OPL2: + case DIV_SYSTEM_OPL3: + switch (effect) { + case 0x30: // toggle hard-reset + dispatchCmd(DivCommand(DIV_CMD_FM_HARD_RESET,ch,effectVal)); + break; default: return false; } diff --git a/src/engine/song.h b/src/engine/song.h index 438c22143..75e5a03e9 100644 --- a/src/engine/song.h +++ b/src/engine/song.h @@ -143,12 +143,15 @@ struct DivSong { // - 9: v3.9 // - introduces Genesis system // - introduces system number + // - patterns now stored in current known format // - 7: ??? - // - 5: BETA 3 (?) + // - 5: BETA 3 // - adds arpeggio tick - // - 3: BETA 2 + // - 4: BETA 2 + // - 3: BETA 1 // - possibly the first version that could save // - basic format, no system number, 16 instruments, one speed, YMU759-only + // - patterns were stored in a different format (chars instead of shorts) // - if somebody manages to find a version 2 or even 1 module, please tell me as it will be worth more than a luxury vehicle unsigned short version; bool isDMF;