diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index e077d8f4d..81753c9b7 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -265,6 +265,14 @@ enum DivDispatchCmds { DIV_CMD_FDS_MOD_AUTO, + DIV_CMD_SID3_SPECIAL_WAVE, + DIV_CMD_SID3_RING_MOD_SRC, + DIV_CMD_SID3_HARD_SYNC_SRC, + DIV_CMD_SID3_PHASE_MOD_SRC, + DIV_CMD_SID3_WAVE_MIX, + DIV_CMD_SID3_LFSR_FEEDBACK_BITS, + DIV_CMD_SID3_1_BIT_NOISE, + DIV_CMD_MAX }; diff --git a/src/engine/platform/sid3.cpp b/src/engine/platform/sid3.cpp index 7940893a1..44f01cc08 100644 --- a/src/engine/platform/sid3.cpp +++ b/src/engine/platform/sid3.cpp @@ -481,6 +481,9 @@ void DivPlatformSID3::tick(bool sysTick) int DivPlatformSID3::dispatch(DivCommand c) { if (c.chan>SID3_NUM_CHANNELS - 1) return 0; + + bool updEnv = false; + switch (c.cmd) { case DIV_CMD_NOTE_ON: { DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SID3); @@ -669,6 +672,81 @@ int DivPlatformSID3::dispatch(DivCommand c) { case DIV_CMD_GET_VOLMAX: return SID3_MAX_VOL; break; + case DIV_CMD_WAVE: + chan[c.chan].wave = c.value & 0xff; + rWrite(SID3_REGISTER_WAVEFORM + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].wave); + break; + case DIV_CMD_SID3_SPECIAL_WAVE: + chan[c.chan].special_wave = c.value % SID3_NUM_SPECIAL_WAVES; + rWrite(SID3_REGISTER_SPECIAL_WAVE + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].special_wave); + break; + case DIV_CMD_C64_EXTENDED: + chan[c.chan].ring = c.value & 1; + chan[c.chan].sync = c.value & 2; + chan[c.chan].phase = c.value & 4; + updateFlags(c.chan, chan[c.chan].gate); + break; + case DIV_CMD_C64_DUTY_RESET: + if (c.value&15) { + DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_SID3); + chan[c.chan].duty=ins->c64.duty; + updateDuty(c.chan); + } + chan[c.chan].resetDuty=c.value>>4; + break; + case DIV_CMD_SID3_RING_MOD_SRC: + chan[c.chan].ringSrc = c.value % (SID3_NUM_CHANNELS + 1); + rWrite(SID3_REGISTER_RING_MOD_SRC + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].ringSrc); + break; + case DIV_CMD_SID3_HARD_SYNC_SRC: + chan[c.chan].syncSrc = c.value % SID3_NUM_CHANNELS; + rWrite(SID3_REGISTER_SYNC_SRC + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].syncSrc); + break; + case DIV_CMD_SID3_PHASE_MOD_SRC: + chan[c.chan].phaseSrc = c.value % SID3_NUM_CHANNELS; + rWrite(SID3_REGISTER_PHASE_MOD_SRC + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].phaseSrc); + break; + case DIV_CMD_FM_AR: + chan[c.chan].attack = c.value & 0xff; + updEnv = true; + break; + case DIV_CMD_FM_DR: + chan[c.chan].decay = c.value & 0xff; + updEnv = true; + break; + case DIV_CMD_FM_SL: + chan[c.chan].sustain = c.value & 0xff; + updEnv = true; + break; + case DIV_CMD_FM_D2R: + chan[c.chan].sr = c.value & 0xff; + updEnv = true; + break; + case DIV_CMD_FM_RR: + chan[c.chan].release = c.value & 0xff; + updEnv = true; + break; + case DIV_CMD_SID3_WAVE_MIX: + chan[c.chan].mix_mode = c.value % 5; + rWrite(SID3_REGISTER_MIXMODE + c.chan * SID3_REGISTERS_PER_CHANNEL, chan[c.chan].mix_mode); + break; + case DIV_CMD_SID3_LFSR_FEEDBACK_BITS: + chan[c.chan].noiseLFSRMask &= ~(0xffU << (8 * c.value2)); + chan[c.chan].noiseLFSRMask |= ((c.value & (c.value2 == 3 ? 0x3f : 0xff)) << (8 * c.value2)); + updateNoiseLFSRMask(c.chan); + break; + case DIV_CMD_SID3_1_BIT_NOISE: + chan[c.chan].oneBitNoise = c.value & 1; + updateFlags(c.chan, chan[c.chan].gate); + break; + case DIV_CMD_C64_FINE_DUTY: + chan[c.chan].duty = (c.value & 0xfff) << 4; + updateDuty(c.chan); + break; + case DIV_CMD_C64_FINE_CUTOFF: + chan[c.chan].filt[c.value2].cutoff = (c.value & 0xfff) << 4; + updateFilter(c.chan, c.value2); + break; case DIV_CMD_MACRO_OFF: chan[c.chan].std.mask(c.value,true); break; @@ -681,6 +759,11 @@ int DivPlatformSID3::dispatch(DivCommand c) { default: break; } + + if(updEnv) + { + updateEnvelope(c.chan); + } return 1; } diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index c61415abd..063dea01f 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -263,7 +263,15 @@ const char* cmdName[]={ "BIFURCATOR_STATE_LOAD", "BIFURCATOR_PARAMETER", - "FDS_MOD_AUTO" + "FDS_MOD_AUTO", + + "SID3_SPECIAL_WAVE", + "SID3_RING_MOD_SRC", + "SID3_HARD_SYNC_SRC", + "SID3_PHASE_MOD_SRC", + "SID3_WAVE_MIX", + "SID3_LFSR_FEEDBACK_BITS", + "SID3_1_BIT_NOISE", }; static_assert((sizeof(cmdName)/sizeof(void*))==DIV_CMD_MAX,"update cmdName!"); diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 2e0ef1ee0..c87654ddc 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -691,18 +691,41 @@ void DivEngine::registerSystems() { for (int i=0; i<16; i++) SID2PostEffectHandlerMap.emplace(0x40+i,SID2FineCutoffHandler); EffectHandlerMap SID3PostEffectHandlerMap={ - {0x10, {DIV_CMD_WAVE, _("10xx: Set waveform (bit 0: triangle; bit 1: saw; bit 2: pulse; bit 3: noise)")}}, - {0x11, {DIV_CMD_C64_RESONANCE, _("11xx: Set resonance (0 to FF)")}}, - {0x12, {DIV_CMD_C64_FILTER_MODE, _("12xx: Set filter mode (bit 0: low pass; bit 1: band pass; bit 2: high pass)")}}, - {0x13, {DIV_CMD_C64_RESET_MASK, _("13xx: Disable envelope reset for this channel (1 disables; 0 enables)")}}, - {0x14, {DIV_CMD_C64_FILTER_RESET, _("14xy: Reset cutoff (x: on new note; y: now)")}}, - {0x15, {DIV_CMD_C64_DUTY_RESET, _("15xy: Reset pulse width (x: on new note; y: now)")}}, - {0x16, {DIV_CMD_C64_EXTENDED, _("16xy: Change other parameters")}}, + {0x60, {DIV_CMD_WAVE, _("60xx: Set waveform (bit 0: triangle; bit 1: saw; bit 2: pulse; bit 3: noise; bit 4: special wave)")}}, + {0x61, {DIV_CMD_SID3_SPECIAL_WAVE, _("61xx: Set special wave (00-39)")}}, + {0x62, {DIV_CMD_C64_EXTENDED, _("62xx: Modulation control (bit 0: ring mod; bit 1: osc. sync; bit 2: phase mod)")}}, + {0x63, {DIV_CMD_C64_DUTY_RESET, _("63xy: Reset pulse width (x: on new note; y: now)")}}, + + {0x64, {DIV_CMD_SID3_RING_MOD_SRC, _("64xx: Set ring modulation source channel (0-7)")}}, + {0x65, {DIV_CMD_SID3_HARD_SYNC_SRC, _("65xx: Set hard sync source channel (0-6)")}}, + {0x66, {DIV_CMD_SID3_PHASE_MOD_SRC, _("66xx: Set phase modulation source channel (0-6)")}}, + + {0x67, {DIV_CMD_FM_AR, _("67xx: Set attack")}}, + {0x68, {DIV_CMD_FM_DR, _("68xx: Set decay")}}, + {0x69, {DIV_CMD_FM_SL, _("69xx: Set sustain level")}}, + {0x6A, {DIV_CMD_FM_D2R, _("6Axx: Set sustain rate")}}, + {0x6B, {DIV_CMD_FM_RR, _("6Bxx: Set release")}}, + + {0x6C, {DIV_CMD_SID3_WAVE_MIX, _("6Cxx: Set wave mix mode (0-4)")}}, + + {0x6D, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Dxx: Set noise LFSR feedback bits (low byte)"), effectVal, constVal<0>}}, + {0x6E, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Exx: Set noise LFSR feedback bits (medium byte)"), effectVal, constVal<1>}}, + {0x6F, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("6Fxx: Set noise LFSR feedback bits (higher byte)"), effectVal, constVal<2>}}, + {0x70, {DIV_CMD_SID3_LFSR_FEEDBACK_BITS, _("70xx: Set noise LFSR feedback bits (highest bits, 0-3F)"), effectVal, constVal<3>}}, + + {0x71, {DIV_CMD_SID3_1_BIT_NOISE, _("71xx: Set noise mode (0: usual noise, 1: 1-bit noise (PCM mode on wave channel))")}}, }; - const EffectHandler SID3FineDutyHandler(DIV_CMD_C64_FINE_DUTY, _("3xxx: Set pulse width (0 to FFF)"), effectValLong<12>); - const EffectHandler SID3FineCutoffHandler(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff (0 to FFF)"), effectValLong<11>); - for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x30+i,SID3FineDutyHandler); - for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x40+i,SID3FineCutoffHandler); + + const EffectHandler SID3FineDutyHandler(DIV_CMD_C64_FINE_DUTY, _("5xxx: Set pulse width (0 to FFF)"), effectValLong<12>); + const EffectHandler SID3FineCutoffHandler1(DIV_CMD_C64_FINE_CUTOFF, _("1xxx: Set cutoff of filter 1 (0 to FFF)"), effectValLong<12>, constVal<0>); + const EffectHandler SID3FineCutoffHandler2(DIV_CMD_C64_FINE_CUTOFF, _("2xxx: Set cutoff of filter 2 (0 to FFF)"), effectValLong<12>, constVal<1>); + const EffectHandler SID3FineCutoffHandler3(DIV_CMD_C64_FINE_CUTOFF, _("3xxx: Set cutoff of filter 3 (0 to FFF)"), effectValLong<12>, constVal<2>); + const EffectHandler SID3FineCutoffHandler4(DIV_CMD_C64_FINE_CUTOFF, _("4xxx: Set cutoff of filter 4 (0 to FFF)"), effectValLong<12>, constVal<3>); + for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x50+i,SID3FineDutyHandler); + for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x10+i,SID3FineCutoffHandler1); + for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x20+i,SID3FineCutoffHandler2); + for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x30+i,SID3FineCutoffHandler3); + for (int i=0; i<16; i++) SID3PostEffectHandlerMap.emplace(0x40+i,SID3FineCutoffHandler4); // SysDefs