From 78fb9c4df50e953f2442ed296c6ae313d5e93a81 Mon Sep 17 00:00:00 2001 From: tildearrow Date: Wed, 21 May 2025 04:46:11 -0500 Subject: [PATCH] DIV_CMD_FM_ALG for OPM/OPN/OPZ --- src/engine/platform/arcade.cpp | 20 ++++++++++++++++++++ src/engine/platform/genesis.cpp | 23 +++++++++++++++++++---- src/engine/platform/tx81z.cpp | 18 ++++++++++++++++++ src/engine/platform/ym2203.cpp | 19 +++++++++++++++++++ src/engine/platform/ym2608.cpp | 19 +++++++++++++++++++ src/engine/platform/ym2610.cpp | 19 +++++++++++++++++++ src/engine/platform/ym2610b.cpp | 19 +++++++++++++++++++ 7 files changed, 133 insertions(+), 4 deletions(-) diff --git a/src/engine/platform/arcade.cpp b/src/engine/platform/arcade.cpp index 24ed8a405..7acbe3a7e 100644 --- a/src/engine/platform/arcade.cpp +++ b/src/engine/platform/arcade.cpp @@ -601,6 +601,26 @@ int DivPlatformArcade::dispatch(DivCommand c) { rWrite(0x1b,c.value&3); break; } + case DIV_CMD_FM_ALG: { + chan[c.chan].state.alg=c.value&7; + if (isMuted[c.chan]) { + rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + } else { + rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)|((chan[c.chan].chVolL&1)<<6)|((chan[c.chan].chVolR&1)<<7)); + } + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (!op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + break; + } case DIV_CMD_FM_FB: { chan[c.chan].state.fb=c.value&7; if (isMuted[c.chan]) { diff --git a/src/engine/platform/genesis.cpp b/src/engine/platform/genesis.cpp index 4c0cc3d91..0dd891d59 100644 --- a/src/engine/platform/genesis.cpp +++ b/src/engine/platform/genesis.cpp @@ -1315,6 +1315,25 @@ int DivPlatformGenesis::dispatch(DivCommand c) { rWrite(0x22,lfoValue); break; } + case DIV_CMD_FM_ALG: { + if (c.chan>=6) break; + chan[c.chan].state.alg=c.value&7; + rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (isMuted[c.chan] || !op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else { + if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + } + break; + } case DIV_CMD_FM_FB: { if (c.chan>=6) break; chan[c.chan].state.fb=c.value&7; @@ -1539,10 +1558,6 @@ int DivPlatformGenesis::dispatch(DivCommand c) { break; case DIV_CMD_PRE_NOTE: break; - case DIV_CMD_FM_ALG: - if (c.value>7) break; - chan[c.chan].state.alg=c.value&7; - rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); default: //printf("WARNING: unimplemented command %d\n",c.cmd); break; diff --git a/src/engine/platform/tx81z.cpp b/src/engine/platform/tx81z.cpp index 80fd30018..fe709240d 100644 --- a/src/engine/platform/tx81z.cpp +++ b/src/engine/platform/tx81z.cpp @@ -651,6 +651,24 @@ int DivPlatformTX81Z::dispatch(DivCommand c) { immWrite(0x1b,lfoShape|(lfoShape2<<2)); break; } + case DIV_CMD_FM_ALG: { + chan[c.chan].state.alg=c.value&7; + if (isMuted[c.chan]) { + rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + } else { + rWrite(chanOffs[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)|((chan[c.chan].chVolL&1)<<6)|((chan[c.chan].chVolR&1)<<7)); + } + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (KVS(c.chan,c.value)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + break; + } case DIV_CMD_FM_FB: { chan[c.chan].state.fb=c.value&7; /* diff --git a/src/engine/platform/ym2203.cpp b/src/engine/platform/ym2203.cpp index fa4bd2d20..33747168d 100644 --- a/src/engine/platform/ym2203.cpp +++ b/src/engine/platform/ym2203.cpp @@ -914,6 +914,25 @@ int DivPlatformYM2203::dispatch(DivCommand c) { } break; } + case DIV_CMD_FM_ALG: { + if (c.chan>2) break; + chan[c.chan].state.alg=c.value&7; + rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (isMuted[c.chan] || !op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else { + if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + } + break; + } case DIV_CMD_FM_FB: { if (c.chan>2) break; chan[c.chan].state.fb=c.value&7; diff --git a/src/engine/platform/ym2608.cpp b/src/engine/platform/ym2608.cpp index b3099c8a0..b6d17a67a 100644 --- a/src/engine/platform/ym2608.cpp +++ b/src/engine/platform/ym2608.cpp @@ -1448,6 +1448,25 @@ int DivPlatformYM2608::dispatch(DivCommand c) { rWrite(0x22,lfoValue); break; } + case DIV_CMD_FM_ALG: { + if (c.chan>5) break; + chan[c.chan].state.alg=c.value&7; + rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (isMuted[c.chan] || !op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else { + if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + } + break; + } case DIV_CMD_FM_FB: { if (c.chan>5) break; chan[c.chan].state.fb=c.value&7; diff --git a/src/engine/platform/ym2610.cpp b/src/engine/platform/ym2610.cpp index 3ecd410e3..4ba74d12c 100644 --- a/src/engine/platform/ym2610.cpp +++ b/src/engine/platform/ym2610.cpp @@ -1407,6 +1407,25 @@ int DivPlatformYM2610::dispatch(DivCommand c) { rWrite(0x22,lfoValue); break; } + case DIV_CMD_FM_ALG: { + if (c.chan>=psgChanOffs) break; + chan[c.chan].state.alg=c.value&7; + rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (isMuted[c.chan] || !op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else { + if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + } + break; + } case DIV_CMD_FM_FB: { if (c.chan>=psgChanOffs) break; chan[c.chan].state.fb=c.value&7; diff --git a/src/engine/platform/ym2610b.cpp b/src/engine/platform/ym2610b.cpp index 970a33d2a..1d526bad1 100644 --- a/src/engine/platform/ym2610b.cpp +++ b/src/engine/platform/ym2610b.cpp @@ -1476,6 +1476,25 @@ int DivPlatformYM2610B::dispatch(DivCommand c) { rWrite(0x22,lfoValue); break; } + case DIV_CMD_FM_ALG: { + if (c.chan>=psgChanOffs) break; + chan[c.chan].state.alg=c.value&7; + rWrite(ADDR_FB_ALG+chanOffs[c.chan],(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3)); + for (int i=0; i<4; i++) { + unsigned short baseAddr=chanOffs[c.chan]|opOffs[i]; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[i]; + if (isMuted[c.chan] || !op.enable) { + rWrite(baseAddr+ADDR_TL,127); + } else { + if (KVS(c.chan,i)) { + rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127)); + } else { + rWrite(baseAddr+ADDR_TL,op.tl); + } + } + } + break; + } case DIV_CMD_FM_FB: { if (c.chan>=psgChanOffs) break; chan[c.chan].state.fb=c.value&7;