diff --git a/src/engine/dispatch.h b/src/engine/dispatch.h index 3b9d231f9..bd720b597 100644 --- a/src/engine/dispatch.h +++ b/src/engine/dispatch.h @@ -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 }; diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 0dd891d59..1215b4a61 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -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]]; diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index b6d17a67a..510c1c106 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -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]]; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 4ba74d12c..5f37fc1a8 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -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]]; diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 1d526bad1..4fca0f4ad 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -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]]; diff --git a/src/engine/playback.cpp b/src/engine/playback.cpp index 81e4c3ae0..541580731 100644 --- a/src/engine/playback.cpp +++ b/src/engine/playback.cpp @@ -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!"); diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 10d2ec502..a1d26a56e 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -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>},