From ec1542a2b4d1db2c63181f44832d6f38a05de53c Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 21 May 2025 17:10:40 -0500 Subject: [PATCH] OPN: ExtCh FMS/AMS effects --- src/engine/platform/genesisext.cpp | 134 ++++++++++++++++------------- src/engine/platform/ym2608ext.cpp | 10 +++ src/engine/platform/ym2610bext.cpp | 10 +++ src/engine/platform/ym2610ext.cpp | 10 +++ 4 files changed, 102 insertions(+), 62 deletions(-) diff --git a/src/engine/platform/genesisext.cpp b/src/engine/platform/genesisext.cpp index b56e3dc21..068a7fc78 100644 --- a/src/engine/platform/genesisext.cpp +++ b/src/engine/platform/genesisext.cpp @@ -31,17 +31,17 @@ void DivPlatformGenesisExt::commitStateExt(int ch, DivInstrument* ins) { int ordch=orderedOps[ch]; if (opChan[ch].insChanged) { - chan[2].state.alg=ins->fm.alg; + chan[extChanOffs].state.alg=ins->fm.alg; if (ch==0 || fbAllOps) { - chan[2].state.fb=ins->fm.fb; + chan[extChanOffs].state.fb=ins->fm.fb; } - chan[2].state.fms=ins->fm.fms; - chan[2].state.ams=ins->fm.ams; - chan[2].state.op[ordch]=ins->fm.op[ordch]; + chan[extChanOffs].state.fms=ins->fm.fms; + chan[extChanOffs].state.ams=ins->fm.ams; + chan[extChanOffs].state.op[ordch]=ins->fm.op[ordch]; } - unsigned short baseAddr=chanOffs[2]|opOffs[ordch]; - DivInstrumentFM::Operator& op=chan[2].state.op[ordch]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[ordch]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[ordch]; // TODO: how does this work?! if (isOpMuted[ch] || !op.enable) { rWrite(baseAddr+0x40,127); @@ -60,8 +60,8 @@ void DivPlatformGenesisExt::commitStateExt(int ch, DivInstrument* ins) { opChan[ch].mask=op.enable; } if (opChan[ch].insChanged) { // TODO how does this work? - rWrite(chanOffs[2]+0xb0,(chan[2].state.alg&7)|(chan[2].state.fb<<3)); - rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); + rWrite(chanOffs[extChanOffs]+0xb0,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); } } @@ -73,7 +73,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { c.chan-=3; return DivPlatformGenesis::dispatch(c); } - int ch=c.chan-2; + int ch=c.chan-extChanOffs; int ordch=orderedOps[ch]; if (!extMode) { c.chan=2; @@ -126,8 +126,8 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { if (!opChan[ch].std.vol.has) { opChan[ch].outVol=c.value; } - unsigned short baseAddr=chanOffs[2]|opOffs[ordch]; - DivInstrumentFM::Operator& op=chan[2].state.op[ordch]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[ordch]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[ordch]; if (isOpMuted[ch] || !op.enable) { rWrite(baseAddr+0x40,127); } else { @@ -158,7 +158,7 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { opChan[i].pan=opChan[ch].pan; } } - rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); lastExtChPan=opChan[ch].pan; break; } @@ -238,20 +238,30 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { break; } case DIV_CMD_FM_FB: { - chan[2].state.fb=c.value&7; - rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3)); + chan[extChanOffs].state.fb=c.value&7; + rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); + break; + } + case DIV_CMD_FM_FMS: { + chan[extChanOffs].state.fms=c.value&7; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } + case DIV_CMD_FM_AMS: { + chan[extChanOffs].state.ams=c.value&3; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); break; } case DIV_CMD_FM_MULT: { - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.mult=c.value2&15; rWrite(baseAddr+0x30,(op.mult&15)|(dtTable[op.dt&7]<<4)); break; } case DIV_CMD_FM_TL: { - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.tl=c.value2; if (isOpMuted[ch] || !op.enable) { rWrite(baseAddr+0x40,127); @@ -265,15 +275,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_AR: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.ar=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6)); } } else { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.ar=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6)); } break; @@ -281,15 +291,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_RS: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.rs=c.value2&3; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.rs=c.value2&3; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6)); } break; @@ -297,15 +307,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_AM: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.am=c.value2&1; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.am=c.value2&1; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); } break; @@ -313,15 +323,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_DR: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.dr=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.dr=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7)); } break; @@ -329,15 +339,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_SL: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.sl=c.value2&15; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.sl=c.value2&15; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); } break; @@ -345,15 +355,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_RR: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.rr=c.value2&15; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.rr=c.value2&15; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4)); } break; @@ -361,15 +371,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_D2R: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.d2r=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.d2r=c.value2&31; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31); } break; @@ -377,15 +387,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_DT: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.dt=c.value&7; - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4)); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.dt=c.value2&7; - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4)); } break; @@ -393,15 +403,15 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) { case DIV_CMD_FM_SSG: { if (c.value<0) { for (int i=0; i<4; i++) { - DivInstrumentFM::Operator& op=chan[2].state.op[i]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[i]; op.ssgEnv=8^(c.value2&15); - unsigned short baseAddr=chanOffs[2]|opOffs[i]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[i]; rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15); } } else if (c.value<4) { - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; op.ssgEnv=8^(c.value2&15); - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15); } break; @@ -443,8 +453,8 @@ void DivPlatformGenesisExt::muteChannel(int ch, bool mute) { if (extMode) { for (int i=0; i<4; i++) { int ordch=orderedOps[i]; - unsigned short baseAddr=chanOffs[2]|opOffs[ordch]; - DivInstrumentFM::Operator op=chan[2].state.op[ordch]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[ordch]; + DivInstrumentFM::Operator op=chan[extChanOffs].state.op[ordch]; if (isOpMuted[i] || !op.enable) { rWrite(baseAddr+0x40,127); } else { @@ -452,7 +462,7 @@ void DivPlatformGenesisExt::muteChannel(int ch, bool mute) { } } - rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-2].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4)); + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch-2].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); } } @@ -506,8 +516,8 @@ void DivPlatformGenesisExt::tick(bool sysTick) { if (extMode && !noExtMacros) for (int i=0; i<4; i++) { if (opChan[i].std.vol.had) { opChan[i].outVol=VOL_SCALE_LOG_BROKEN(opChan[i].vol,MIN(127,opChan[i].std.vol.val),127); - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[i]]; - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[i]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[i]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[i]]; if (isOpMuted[i]) { rWrite(baseAddr+ADDR_TL,127); } else { @@ -579,8 +589,8 @@ void DivPlatformGenesisExt::tick(bool sysTick) { } // param macros - unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[i]]; - DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[i]]; + unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[i]]; + DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[i]]; DivMacroInt::IntOp& m=opChan[i].std.op[orderedOps[i]]; if (m.am.had) { op.am=m.am.val; diff --git a/src/engine/platform/ym2608ext.cpp b/src/engine/platform/ym2608ext.cpp index 1272d1bc2..21449f1ed 100644 --- a/src/engine/platform/ym2608ext.cpp +++ b/src/engine/platform/ym2608ext.cpp @@ -223,6 +223,16 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) { rWrite(chanOffs[2]+ADDR_FB_ALG,(chan[2].state.alg&7)|(chan[2].state.fb<<3)); break; } + case DIV_CMD_FM_FMS: { + chan[extChanOffs].state.fms=c.value&7; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } + case DIV_CMD_FM_AMS: { + chan[extChanOffs].state.ams=c.value&3; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } case DIV_CMD_FM_MULT: { unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]]; DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]]; diff --git a/src/engine/platform/ym2610bext.cpp b/src/engine/platform/ym2610bext.cpp index 2e40048d9..abedea0f5 100644 --- a/src/engine/platform/ym2610bext.cpp +++ b/src/engine/platform/ym2610bext.cpp @@ -219,6 +219,16 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) { rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); break; } + case DIV_CMD_FM_FMS: { + chan[extChanOffs].state.fms=c.value&7; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } + case DIV_CMD_FM_AMS: { + chan[extChanOffs].state.ams=c.value&3; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } case DIV_CMD_FM_MULT: { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]]; diff --git a/src/engine/platform/ym2610ext.cpp b/src/engine/platform/ym2610ext.cpp index 032f07756..e61ff6d68 100644 --- a/src/engine/platform/ym2610ext.cpp +++ b/src/engine/platform/ym2610ext.cpp @@ -219,6 +219,16 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) { rWrite(chanOffs[extChanOffs]+ADDR_FB_ALG,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3)); break; } + case DIV_CMD_FM_FMS: { + chan[extChanOffs].state.fms=c.value&7; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } + case DIV_CMD_FM_AMS: { + chan[extChanOffs].state.ams=c.value&3; + rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4)); + break; + } case DIV_CMD_FM_MULT: { unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[orderedOps[c.value]]; DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[orderedOps[c.value]];