mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-30 00:13:03 +00:00
implement some basic SID3 effects
Wave/PCM chan and pw/cutoff slides coming later ig
This commit is contained in:
parent
2e892b1aec
commit
2a322bff4f
4 changed files with 134 additions and 12 deletions
|
@ -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
|
||||
};
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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!");
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue