OPN: FMS/AMS effects

This commit is contained in:
tildearrow 2025-05-21 15:10:47 -05:00
parent 78fb9c4df5
commit 7210187df5
7 changed files with 61 additions and 1 deletions

View file

@ -316,6 +316,10 @@ enum DivDispatchCmds {
DIV_CMD_WS_GLOBAL_SPEAKER_VOLUME, // (multiplier)
DIV_CMD_FM_ALG,
DIV_CMD_FM_FMS,
DIV_CMD_FM_AMS,
DIV_CMD_FM_FMS2,
DIV_CMD_FM_AMS2,
DIV_CMD_MAX
};

View file

@ -1340,6 +1340,18 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
break;
}
case DIV_CMD_FM_FMS: {
if (c.chan>=6) break;
chan[c.chan].state.fms=c.value&7;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(IS_REALLY_MUTED(c.chan)?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_AMS: {
if (c.chan>=6) break;
chan[c.chan].state.ams=c.value&3;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(IS_REALLY_MUTED(c.chan)?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_MULT: {
if (c.chan>=6) break;
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];

View file

@ -1473,6 +1473,18 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
break;
}
case DIV_CMD_FM_FMS: {
if (c.chan>5) break;
chan[c.chan].state.fms=c.value&7;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_AMS: {
if (c.chan>5) break;
chan[c.chan].state.ams=c.value&3;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_MULT: {
if (c.chan>5) break;
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];

View file

@ -1432,6 +1432,18 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
break;
}
case DIV_CMD_FM_FMS: {
if (c.chan>=psgChanOffs) break;
chan[c.chan].state.fms=c.value&7;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_AMS: {
if (c.chan>=psgChanOffs) break;
chan[c.chan].state.ams=c.value&3;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_MULT: {
if (c.chan>=psgChanOffs) break;
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];

View file

@ -1501,6 +1501,18 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
break;
}
case DIV_CMD_FM_FMS: {
if (c.chan>=psgChanOffs) break;
chan[c.chan].state.fms=c.value&7;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_AMS: {
if (c.chan>=psgChanOffs) break;
chan[c.chan].state.ams=c.value&3;
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
break;
}
case DIV_CMD_FM_MULT: {
if (c.chan>=psgChanOffs) break;
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];

View file

@ -311,7 +311,11 @@ const char* cmdName[]={
"WS_GLOBAL_SPEAKER_VOLUME",
"FM_ALG"
"FM_ALG",
"FM_FMS",
"FM_AMS",
"FM_FMS2",
"FM_AMS2"
};
static_assert((sizeof(cmdName)/sizeof(void*))==DIV_CMD_MAX,"update cmdName!");

View file

@ -503,6 +503,8 @@ void DivEngine::registerSystems() {
{0x5f, {DIV_CMD_FM_D2R, _("5Fxx: Set decay 2 of operator 4 (0 to 1F)"), constVal<3>, effectValAnd<31>}},
{0x60, {DIV_CMD_FM_OPMASK, _("60xx: Set operator mask (bits 0-3)")}},
{0x61, {DIV_CMD_FM_ALG, _("61xx: Set algorithm (0 to 7)")}},
{0x62, {DIV_CMD_FM_FMS, _("62xx: Set LFO FM depth (0 to 7)")}},
{0x63, {DIV_CMD_FM_AMS, _("63xx: Set LFO AM depth (0 to 3)")}},
};
EffectHandlerMap fmOPMPostEffectHandlerMap(fmOPNPostEffectHandlerMap);
@ -526,6 +528,8 @@ void DivEngine::registerSystems() {
{0x2a, {DIV_CMD_FM_WS, _("2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 7)"), effectOpVal<4>, effectValAnd<7>}},
{0x2b, {DIV_CMD_FM_EG_SHIFT, _("2Bxy: Set envelope generator shift (x: operator from 1 to 4 (0 for all ops); y: shift from 0 to 3)"), effectOpVal<4>, effectValAnd<3>}},
{0x2c, {DIV_CMD_FM_FINE, _("2Cxy: Set fine multiplier (x: operator from 1 to 4 (0 for all ops); y: fine)"), effectOpVal<4>, effectValAnd<15>}},
{0x64, {DIV_CMD_FM_FMS2, _("62xx: Set LFO2 FM depth (0 to 7)")}},
{0x65, {DIV_CMD_FM_AMS2, _("63xx: Set LFO2 AM depth (0 to 3)")}},
});
const EffectHandler fmOPZFixFreqHandler[4]={
{DIV_CMD_FM_FIXFREQ, _("3xyy: Set fixed frequency of operator 1 (x: octave from 0 to 7; y: frequency)"), constVal<0>, effectValLong<11>},