SNES: implement more effects

This commit is contained in:
tildearrow 2022-09-28 18:28:01 -05:00
parent 3329e98c51
commit 6f1a41de1e
3 changed files with 115 additions and 36 deletions

View file

@ -296,29 +296,7 @@ int DivPlatformSNES::dispatch(DivCommand c) {
} }
if (chan[c.chan].insChanged) { if (chan[c.chan].insChanged) {
chan[c.chan].state=ins->snes; chan[c.chan].state=ins->snes;
if (chan[c.chan].state.useEnv) { writeEnv(c.chan);
chWrite(c.chan,5,chan[c.chan].state.a|(chan[c.chan].state.d<<4)|0x80);
chWrite(c.chan,6,chan[c.chan].state.r|(chan[c.chan].state.s<<5));
} else {
chWrite(c.chan,5,0);
switch (chan[c.chan].state.gainMode) {
case DivInstrumentSNES::GAIN_MODE_DIRECT:
chWrite(c.chan,7,chan[c.chan].state.gain&127);
break;
case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR:
chWrite(c.chan,7,0x80|(chan[c.chan].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_INC_LINEAR:
chWrite(c.chan,7,0xc0|(chan[c.chan].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_DEC_LOG:
chWrite(c.chan,7,0xa0|(chan[c.chan].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_INC_INVLOG:
chWrite(c.chan,7,0xe0|(chan[c.chan].state.gain&31));
break;
}
}
} }
if (c.value!=DIV_NOTE_NULL) { if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value)); chan[c.chan].baseFreq=round(NOTE_FREQUENCY(c.value));
@ -368,6 +346,11 @@ int DivPlatformSNES::dispatch(DivCommand c) {
chan[c.chan].pitch=c.value; chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
break; break;
case DIV_CMD_WAVE:
if (!chan[c.chan].useWave) break;
chan[c.chan].wave=c.value;
chan[c.chan].ws.changeWave1(chan[c.chan].wave);
break;
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
int destFreq=round(NOTE_FREQUENCY(c.value2)); int destFreq=round(NOTE_FREQUENCY(c.value2));
bool return2=false; bool return2=false;
@ -404,9 +387,76 @@ int DivPlatformSNES::dispatch(DivCommand c) {
chan[c.chan].inPorta=c.value; chan[c.chan].inPorta=c.value;
break; break;
case DIV_CMD_SAMPLE_POS: case DIV_CMD_SAMPLE_POS:
// may have to remove this
chan[c.chan].audPos=c.value; chan[c.chan].audPos=c.value;
chan[c.chan].setPos=true; chan[c.chan].setPos=true;
break; break;
case DIV_CMD_STD_NOISE_MODE:
chan[c.chan].noise=c.value;
writeNoise=true;
break;
case DIV_CMD_SNES_PITCH_MOD:
chan[c.chan].pitchMod=c.value;
writePitchMod=true;
break;
case DIV_CMD_SNES_INVERT:
chan[c.chan].invertL=(c.value>>4);
chan[c.chan].invertR=c.chan&15;
writeOutVol(c.chan);
break;
case DIV_CMD_SNES_GAIN_MODE:
if (c.value) {
chan[c.chan].state.useEnv=false;
switch (c.value) {
case 1:
chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DIRECT;
break;
case 2:
chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DEC_LINEAR;
break;
case 3:
chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_DEC_LOG;
break;
case 4:
chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_INC_LINEAR;
break;
case 5:
chan[c.chan].state.gainMode=DivInstrumentSNES::GAIN_MODE_INC_INVLOG;
break;
}
} else {
chan[c.chan].state.useEnv=true;
}
writeEnv(c.chan);
break;
case DIV_CMD_SNES_GAIN:
if (chan[c.chan].state.gainMode==DivInstrumentSNES::GAIN_MODE_DIRECT) {
chan[c.chan].state.gain=c.value&0x7f;
} else {
chan[c.chan].state.gain=c.value&0x1f;
}
if (!chan[c.chan].state.useEnv) writeEnv(c.chan);
break;
case DIV_CMD_STD_NOISE_FREQ:
noiseFreq=c.value&0x1f;
writeControl=true;
break;
case DIV_CMD_FM_AR:
chan[c.chan].state.a=c.value&15;
if (chan[c.chan].state.useEnv) writeEnv(c.chan);
break;
case DIV_CMD_FM_DR:
chan[c.chan].state.d=c.value&7;
if (chan[c.chan].state.useEnv) writeEnv(c.chan);
break;
case DIV_CMD_FM_SL:
chan[c.chan].state.s=c.value&7;
if (chan[c.chan].state.useEnv) writeEnv(c.chan);
break;
case DIV_CMD_FM_RR:
chan[c.chan].state.r=c.value&0x1f;
if (chan[c.chan].state.useEnv) writeEnv(c.chan);
break;
case DIV_CMD_SNES_ECHO: case DIV_CMD_SNES_ECHO:
chan[c.chan].echo=c.value; chan[c.chan].echo=c.value;
writeEcho=true; writeEcho=true;
@ -484,6 +534,32 @@ void DivPlatformSNES::writeOutVol(int ch) {
chWrite(ch,1,outR); chWrite(ch,1,outR);
} }
void DivPlatformSNES::writeEnv(int ch) {
if (chan[ch].state.useEnv) {
chWrite(ch,5,chan[ch].state.a|(chan[ch].state.d<<4)|0x80);
chWrite(ch,6,chan[ch].state.r|(chan[ch].state.s<<5));
} else {
chWrite(ch,5,0);
switch (chan[ch].state.gainMode) {
case DivInstrumentSNES::GAIN_MODE_DIRECT:
chWrite(ch,7,chan[ch].state.gain&127);
break;
case DivInstrumentSNES::GAIN_MODE_DEC_LINEAR:
chWrite(ch,7,0x80|(chan[ch].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_INC_LINEAR:
chWrite(ch,7,0xc0|(chan[ch].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_DEC_LOG:
chWrite(ch,7,0xa0|(chan[ch].state.gain&31));
break;
case DivInstrumentSNES::GAIN_MODE_INC_INVLOG:
chWrite(ch,7,0xe0|(chan[ch].state.gain&31));
break;
}
}
}
void DivPlatformSNES::muteChannel(int ch, bool mute) { void DivPlatformSNES::muteChannel(int ch, bool mute) {
isMuted[ch]=mute; isMuted[ch]=mute;
writeOutVol(ch); writeOutVol(ch);

View file

@ -131,6 +131,7 @@ class DivPlatformSNES: public DivDispatch {
private: private:
void updateWave(int ch); void updateWave(int ch);
void writeOutVol(int ch); void writeOutVol(int ch);
void writeEnv(int ch);
void initEcho(); void initEcho();
}; };

View file

@ -867,23 +867,11 @@ void DivEngine::registerSystems() {
{DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES}, {DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES, DIV_INS_SNES},
{}, {},
{ {
{0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}},
{0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Toggle noise mode"}},
{0x12, {DIV_CMD_SNES_ECHO, "12xx: Toggle echo on this channel"}},
{0x13, {DIV_CMD_SNES_PITCH_MOD, "13xx: Toggle pitch modulation"}},
{0x14, {DIV_CMD_SNES_INVERT, "14xy: Toggle invert (x: left; y: right)"}},
{0x15, {DIV_CMD_SNES_GAIN_MODE, "15xx: Set gain mode"}},
{0x16, {DIV_CMD_SNES_GAIN, "16xx: Set gain"}},
{0x18, {DIV_CMD_SNES_ECHO_ENABLE, "18xx: Enable echo buffer"}}, {0x18, {DIV_CMD_SNES_ECHO_ENABLE, "18xx: Enable echo buffer"}},
{0x19, {DIV_CMD_SNES_ECHO_DELAY, "19xx: Set echo delay"}}, {0x19, {DIV_CMD_SNES_ECHO_DELAY, "19xx: Set echo delay (0 to F)"}},
{0x1a, {DIV_CMD_SNES_ECHO_VOL_LEFT, "1Axx: Set left echo volume"}}, {0x1a, {DIV_CMD_SNES_ECHO_VOL_LEFT, "1Axx: Set left echo volume"}},
{0x1b, {DIV_CMD_SNES_ECHO_VOL_RIGHT, "1Bxx: Set right echo volume"}}, {0x1b, {DIV_CMD_SNES_ECHO_VOL_RIGHT, "1Bxx: Set right echo volume"}},
{0x1c, {DIV_CMD_SNES_ECHO_FEEDBACK, "1Cxx: Set echo feedback"}}, {0x1c, {DIV_CMD_SNES_ECHO_FEEDBACK, "1Cxx: Set echo feedback"}},
{0x1d, {DIV_CMD_STD_NOISE_FREQ, "1Dxx: Set noise frequency"}},
{0x20, {DIV_CMD_FM_AR, "20xx: Set attack"}},
{0x21, {DIV_CMD_FM_DR, "21xx: Set decay"}},
{0x22, {DIV_CMD_FM_SL, "22xx: Set sustain"}},
{0x23, {DIV_CMD_FM_RR, "23xx: Set release"}},
{0x30, {DIV_CMD_SNES_ECHO_FIR, "30xx: Set echo filter coefficient 0",constVal<0>,effectVal}}, {0x30, {DIV_CMD_SNES_ECHO_FIR, "30xx: Set echo filter coefficient 0",constVal<0>,effectVal}},
{0x31, {DIV_CMD_SNES_ECHO_FIR, "31xx: Set echo filter coefficient 1",constVal<1>,effectVal}}, {0x31, {DIV_CMD_SNES_ECHO_FIR, "31xx: Set echo filter coefficient 1",constVal<1>,effectVal}},
{0x32, {DIV_CMD_SNES_ECHO_FIR, "32xx: Set echo filter coefficient 2",constVal<2>,effectVal}}, {0x32, {DIV_CMD_SNES_ECHO_FIR, "32xx: Set echo filter coefficient 2",constVal<2>,effectVal}},
@ -892,6 +880,20 @@ void DivEngine::registerSystems() {
{0x35, {DIV_CMD_SNES_ECHO_FIR, "35xx: Set echo filter coefficient 5",constVal<5>,effectVal}}, {0x35, {DIV_CMD_SNES_ECHO_FIR, "35xx: Set echo filter coefficient 5",constVal<5>,effectVal}},
{0x36, {DIV_CMD_SNES_ECHO_FIR, "36xx: Set echo filter coefficient 6",constVal<6>,effectVal}}, {0x36, {DIV_CMD_SNES_ECHO_FIR, "36xx: Set echo filter coefficient 6",constVal<6>,effectVal}},
{0x37, {DIV_CMD_SNES_ECHO_FIR, "37xx: Set echo filter coefficient 7",constVal<7>,effectVal}}, {0x37, {DIV_CMD_SNES_ECHO_FIR, "37xx: Set echo filter coefficient 7",constVal<7>,effectVal}},
},
{
{0x10, {DIV_CMD_WAVE, "10xx: Set waveform"}},
{0x11, {DIV_CMD_STD_NOISE_MODE, "11xx: Toggle noise mode"}},
{0x12, {DIV_CMD_SNES_ECHO, "12xx: Toggle echo on this channel"}},
{0x13, {DIV_CMD_SNES_PITCH_MOD, "13xx: Toggle pitch modulation"}},
{0x14, {DIV_CMD_SNES_INVERT, "14xy: Toggle invert (x: left; y: right)"}},
{0x15, {DIV_CMD_SNES_GAIN_MODE, "15xx: Set envelope mode (0: ADSR, 1: gain/direct, 2: dec, 3: exp, 4: inc, 5: bent)"}},
{0x16, {DIV_CMD_SNES_GAIN, "16xx: Set gain (00 to 7F if direct; 00 to 1F otherwise)"}},
{0x1d, {DIV_CMD_STD_NOISE_FREQ, "1Dxx: Set noise frequency (00 to 1F)"}},
{0x20, {DIV_CMD_FM_AR, "20xx: Set attack (0 to F)"}},
{0x21, {DIV_CMD_FM_DR, "21xx: Set decay (0 to 7)"}},
{0x22, {DIV_CMD_FM_SL, "22xx: Set sustain (0 to 7)"}},
{0x23, {DIV_CMD_FM_RR, "23xx: Set release (00 to 1F)"}},
} }
); );