diff --git a/src/engine/platform/opl.cpp b/src/engine/platform/opl.cpp index dc121a06..7dad9e1c 100644 --- a/src/engine/platform/opl.cpp +++ b/src/engine/platform/opl.cpp @@ -841,6 +841,222 @@ int DivPlatformOPL::dispatch(DivCommand c) { } break; } + case DIV_CMD_FM_DR: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.dr=c.value2&15; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr); + } + break; + } + case DIV_CMD_FM_SL: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.sl=c.value2&15; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr); + } + break; + } + case DIV_CMD_FM_RR: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.rr=c.value2&15; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr); + } + break; + } + case DIV_CMD_FM_AM: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.am=c.value2&1; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult); + } + break; + } + case DIV_CMD_FM_VIB: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.vib=c.value2&1; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult); + } + break; + } + case DIV_CMD_FM_SUS: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.sus=c.value2&1; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult); + } + break; + } + case DIV_CMD_FM_KSR: { + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.ksr=c.value2&1; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult); + } + break; + } + case DIV_CMD_FM_WS: { + if (oplType<2) break; + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.ws=c.value2&7; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + rWrite(baseAddr+ADDR_WS,op.ws&((oplType==3)?7:3)); + } + break; + } + case DIV_CMD_FM_RS: { + if (oplType<2) break; + int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2; + if (c.value<0) { + for (int i=0; i=ops) break; + DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value]; + op.ksl=c.value2&3; + unsigned char slot=slots[c.value][c.chan]; + if (slot==255) break; + unsigned short baseAddr=slotMap[slot]; + if (isMuted[c.chan]) { + rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6)); + } else { + if (isOutputL[ops==4][chan[c.chan].state.alg][c.value]) { + rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6)); + } else { + rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6)); + } + } + } + break; + } case DIV_CMD_FM_EXTCH: { if (!properDrumsSys) break; properDrums=c.value; diff --git a/src/engine/platform/opll.cpp b/src/engine/platform/opll.cpp index 0e4e92d6..1e29a1e4 100644 --- a/src/engine/platform/opll.cpp +++ b/src/engine/platform/opll.cpp @@ -637,6 +637,150 @@ int DivPlatformOPLL::dispatch(DivCommand c) { rWrite(0x05,(car.ar<<4)|(car.dr)); break; } + case DIV_CMD_FM_DR: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.dr=c.value2&15; + car.dr=c.value2&15; + } else { + if (c.value==0) { + mod.dr=c.value2&15; + } else { + car.dr=c.value2&15; + } + } + rWrite(0x04,(mod.ar<<4)|(mod.dr)); + rWrite(0x05,(car.ar<<4)|(car.dr)); + break; + } + case DIV_CMD_FM_SL: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.sl=c.value2&15; + car.sl=c.value2&15; + } else { + if (c.value==0) { + mod.sl=c.value2&15; + } else { + car.sl=c.value2&15; + } + } + rWrite(0x06,(mod.sl<<4)|(mod.rr)); + rWrite(0x07,(car.sl<<4)|(car.rr)); + break; + } + case DIV_CMD_FM_RR: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.rr=c.value2&15; + car.rr=c.value2&15; + } else { + if (c.value==0) { + mod.rr=c.value2&15; + } else { + car.rr=c.value2&15; + } + } + rWrite(0x06,(mod.sl<<4)|(mod.rr)); + rWrite(0x07,(car.sl<<4)|(car.rr)); + break; + } + case DIV_CMD_FM_AM: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.am=c.value2&1; + car.am=c.value2&1; + } else { + if (c.value==0) { + mod.am=c.value2&1; + } else { + car.am=c.value2&1; + } + } + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + break; + } + case DIV_CMD_FM_VIB: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.vib=c.value2&1; + car.vib=c.value2&1; + } else { + if (c.value==0) { + mod.vib=c.value2&1; + } else { + car.vib=c.value2&1; + } + } + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + break; + } + case DIV_CMD_FM_KSR: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.ksr=c.value2&1; + car.ksr=c.value2&1; + } else { + if (c.value==0) { + mod.ksr=c.value2&1; + } else { + car.ksr=c.value2&1; + } + } + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + break; + } + case DIV_CMD_FM_SUS: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.ssgEnv=c.value2?8:0; + car.ssgEnv=c.value2?8:0; + } else { + if (c.value==0) { + mod.ssgEnv=c.value2?8:0; + } else { + car.ssgEnv=c.value2?8:0; + } + } + rWrite(0x00,(mod.am<<7)|(mod.vib<<6)|((mod.ssgEnv&8)<<2)|(mod.ksr<<4)|(mod.mult)); + rWrite(0x01,(car.am<<7)|(car.vib<<6)|((car.ssgEnv&8)<<2)|(car.ksr<<4)|(car.mult)); + break; + } + case DIV_CMD_FM_RS: { + if (c.chan>=9 && !properDrums) return 0; + DivInstrumentFM::Operator& mod=chan[c.chan].state.op[0]; + DivInstrumentFM::Operator& car=chan[c.chan].state.op[1]; + if (c.value<0) { + mod.ksl=c.value2&3; + car.ksl=c.value2&3; + } else { + if (c.value==0) { + mod.ksl=c.value2&3; + } else { + car.ksl=c.value2&3; + } + } + rWrite(0x02,(mod.ksl<<6)|(mod.tl&63)); + rWrite(0x03,(car.ksl<<6)|((chan[c.chan].state.fms&1)<<4)|((chan[c.chan].state.ams&1)<<3)|chan[c.chan].state.fb); + break; + } case DIV_CMD_FM_EXTCH: if (!properDrumsSys) break; if ((int)properDrums==c.value) break; diff --git a/src/engine/sysDef.cpp b/src/engine/sysDef.cpp index 1a371401..981358ed 100644 --- a/src/engine/sysDef.cpp +++ b/src/engine/sysDef.cpp @@ -542,7 +542,6 @@ void DivEngine::registerSystems() { OP_EFFECT_MULTI(0x58,DIV_CMD_FM_DR,1,15); OP_EFFECT_SINGLE(0x5b,DIV_CMD_FM_KSR,2,1); - OP_EFFECT_SINGLE(0x2a,DIV_CMD_FM_WS,4,7); default: return false; } @@ -608,6 +607,7 @@ void DivEngine::registerSystems() { OP_EFFECT_MULTI(0x5a,DIV_CMD_FM_DR,3,15); OP_EFFECT_SINGLE(0x5b,DIV_CMD_FM_KSR,4,1); + OP_EFFECT_SINGLE(0x2a,DIV_CMD_FM_WS,4,7); default: return false;