OPL: implement effects
This commit is contained in:
parent
492533e5c0
commit
592cbb56aa
|
@ -138,7 +138,7 @@ const int orderedOpsL[4]={
|
||||||
const char* DivPlatformOPL::getEffectName(unsigned char effect) {
|
const char* DivPlatformOPL::getEffectName(unsigned char effect) {
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x10:
|
case 0x10:
|
||||||
return "10xy: Setup LFO (x: enable; y: speed)";
|
return "10xx: Set global AM depth (0: 1dB, 1: 4.8dB)";
|
||||||
break;
|
break;
|
||||||
case 0x11:
|
case 0x11:
|
||||||
return "11xx: Set feedback (0 to 7)";
|
return "11xx: Set feedback (0 to 7)";
|
||||||
|
@ -159,10 +159,12 @@ const char* DivPlatformOPL::getEffectName(unsigned char effect) {
|
||||||
return "16xy: Set operator multiplier (x: operator from 1 to 4; y: multiplier)";
|
return "16xy: Set operator multiplier (x: operator from 1 to 4; y: multiplier)";
|
||||||
break;
|
break;
|
||||||
case 0x17:
|
case 0x17:
|
||||||
return "17xx: Enable channel 6 DAC";
|
return "17xx: Set global vibrato depth (0: normal, 1: double)";
|
||||||
break;
|
break;
|
||||||
case 0x18:
|
case 0x18:
|
||||||
return "18xx: Toggle extended channel 3 mode";
|
if (properDrumsSys) {
|
||||||
|
return "18xx: Toggle drums mode (1: enabled; 0: disabled)";
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 0x19:
|
case 0x19:
|
||||||
return "19xx: Set attack of all operators (0 to F)";
|
return "19xx: Set attack of all operators (0 to F)";
|
||||||
|
@ -242,6 +244,7 @@ void DivPlatformOPL::tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
if (chan[i].std.hadArp) {
|
if (chan[i].std.hadArp) {
|
||||||
if (!chan[i].inPorta) {
|
if (!chan[i].inPorta) {
|
||||||
|
@ -259,6 +262,7 @@ void DivPlatformOPL::tick() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
if (chan[i].std.hadAlg) {
|
if (chan[i].std.hadAlg) {
|
||||||
chan[i].state.alg=chan[i].std.alg;
|
chan[i].state.alg=chan[i].std.alg;
|
||||||
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
rWrite(chanOffs[i]+ADDR_FB_ALG,(chan[i].state.alg&7)|(chan[i].state.fb<<3));
|
||||||
|
@ -358,7 +362,7 @@ void DivPlatformOPL::tick() {
|
||||||
if (oplType==3) {
|
if (oplType==3) {
|
||||||
unsigned char opMask=chan[0].fourOp|(chan[2].fourOp<<1)|(chan[4].fourOp<<2)|(chan[6].fourOp<<3)|(chan[8].fourOp<<4)|(chan[10].fourOp<<5);
|
unsigned char opMask=chan[0].fourOp|(chan[2].fourOp<<1)|(chan[4].fourOp<<2)|(chan[6].fourOp<<3)|(chan[8].fourOp<<4)|(chan[10].fourOp<<5);
|
||||||
immWrite(0x104,opMask);
|
immWrite(0x104,opMask);
|
||||||
printf("updating opMask to %.2x\n",opMask);
|
//printf("updating opMask to %.2x\n",opMask);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -662,58 +666,85 @@ int DivPlatformOPL::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_LFO: {
|
case DIV_CMD_FM_LFO: {
|
||||||
lfoValue=(c.value&7)|((c.value>>4)<<3);
|
if (c.value&2) {
|
||||||
rWrite(0x22,lfoValue);
|
dvb=c.value&1;
|
||||||
|
} else {
|
||||||
|
dam=c.value&1;
|
||||||
|
}
|
||||||
|
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_FB: {
|
case DIV_CMD_FM_FB: {
|
||||||
chan[c.chan].state.fb=c.value&7;
|
chan[c.chan].state.fb=c.value&7;
|
||||||
//rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
|
if (isMuted[c.chan]) {
|
||||||
|
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1));
|
||||||
|
if (ops==4) {
|
||||||
|
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
rWrite(chanMap[c.chan]+ADDR_LR_FB_ALG,(chan[c.chan].state.alg&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||||
|
if (ops==4) {
|
||||||
|
rWrite(chanMap[c.chan+1]+ADDR_LR_FB_ALG,((chan[c.chan].state.alg>>1)&1)|(chan[c.chan].state.fb<<1)|((chan[c.chan].pan&3)<<4));
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_MULT: {
|
case DIV_CMD_FM_MULT: {
|
||||||
/*
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
if (c.value>=ops) break;
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
||||||
op.mult=c.value2&15;
|
op.mult=c.value2&15;
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_TL: {
|
case DIV_CMD_FM_TL: {
|
||||||
/*
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
if (c.value>=ops) break;
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
||||||
op.tl=c.value2;
|
op.tl=c.value2&63;
|
||||||
|
unsigned char slot=slots[c.value][c.chan];
|
||||||
|
if (slot==255) break;
|
||||||
|
unsigned short baseAddr=slotMap[slot];
|
||||||
if (isMuted[c.chan]) {
|
if (isMuted[c.chan]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
if (isOutput[chan[c.chan].state.alg][c.value]) {
|
if (isOutputL[ops==4][chan[c.chan].state.alg][c.value]) {
|
||||||
rWrite(baseAddr+ADDR_TL,127-(((127-op.tl)*(chan[c.chan].outVol&0x7f))/127));
|
rWrite(baseAddr+ADDR_KSL_TL,(63-(((63-op.tl)*(chan[c.chan].outVol&0x3f))/63))|(op.ksl<<6));
|
||||||
} else {
|
} else {
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
rWrite(baseAddr+ADDR_KSL_TL,op.tl|(op.ksl<<6));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_FM_AR: {
|
case DIV_CMD_FM_AR: {
|
||||||
/*
|
int ops=(slots[3][c.chan]!=255 && chan[c.chan].state.ops==4 && oplType==3)?4:2;
|
||||||
if (c.value<0) {
|
if (c.value<0) {
|
||||||
for (int i=0; i<4; i++) {
|
for (int i=0; i<ops; i++) {
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
unsigned char slot=slots[i][c.chan];
|
||||||
op.ar=c.value2&31;
|
if (slot==255) continue;
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
unsigned short baseAddr=slotMap[slot];
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||||
|
op.ar=c.value2&15;
|
||||||
|
rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
if (c.value>=ops) break;
|
||||||
op.ar=c.value2&31;
|
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[c.value]:c.value];
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
op.ar=c.value2&15;
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
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_EXTCH: {
|
||||||
|
properDrums=c.value;
|
||||||
|
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_ALWAYS_SET_VOLUME:
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
|
@ -777,6 +808,7 @@ void DivPlatformOPL::forceIns() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
immWrite(0xbd,(dam<<7)|(dvb<<6)|(properDrums<<5)|drumState);
|
||||||
update4OpMask=true;
|
update4OpMask=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,6 +854,13 @@ void DivPlatformOPL::reset() {
|
||||||
lastBusy=60;
|
lastBusy=60;
|
||||||
lfoValue=8;
|
lfoValue=8;
|
||||||
properDrums=properDrumsSys;
|
properDrums=properDrumsSys;
|
||||||
|
drumState=0;
|
||||||
|
|
||||||
|
drumVol[0]=0;
|
||||||
|
drumVol[1]=0;
|
||||||
|
drumVol[2]=0;
|
||||||
|
drumVol[3]=0;
|
||||||
|
drumVol[4]=0;
|
||||||
|
|
||||||
if (oplType==1) { // disable waveforms
|
if (oplType==1) { // disable waveforms
|
||||||
immWrite(0x01,0x20);
|
immWrite(0x01,0x20);
|
||||||
|
@ -832,6 +871,8 @@ void DivPlatformOPL::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
update4OpMask=true;
|
update4OpMask=true;
|
||||||
|
dam=false;
|
||||||
|
dvb=false;
|
||||||
delay=0;
|
delay=0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,9 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
fourOp(false),
|
fourOp(false),
|
||||||
vol(0),
|
vol(0),
|
||||||
pan(3) {}
|
pan(3) {
|
||||||
|
state.ops=2;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
Channel chan[20];
|
Channel chan[20];
|
||||||
bool isMuted[20];
|
bool isMuted[20];
|
||||||
|
@ -72,10 +74,12 @@ class DivPlatformOPL: public DivDispatch {
|
||||||
double chipFreqBase;
|
double chipFreqBase;
|
||||||
int delay, oplType, chans, melodicChans, totalChans;
|
int delay, oplType, chans, melodicChans, totalChans;
|
||||||
unsigned char lastBusy;
|
unsigned char lastBusy;
|
||||||
|
unsigned char drumState;
|
||||||
|
unsigned char drumVol[5];
|
||||||
|
|
||||||
unsigned char regPool[512];
|
unsigned char regPool[512];
|
||||||
|
|
||||||
bool properDrums, properDrumsSys;
|
bool properDrums, properDrumsSys, dam, dvb;
|
||||||
|
|
||||||
unsigned char lfoValue;
|
unsigned char lfoValue;
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,9 @@ bool DivEngine::perSystemEffect(int ch, unsigned char effect, unsigned char effe
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_OPLL_DRUMS:
|
case DIV_SYSTEM_OPLL_DRUMS:
|
||||||
|
case DIV_SYSTEM_OPL_DRUMS:
|
||||||
|
case DIV_SYSTEM_OPL2_DRUMS:
|
||||||
|
case DIV_SYSTEM_OPL3_DRUMS:
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x18: // drum mode toggle
|
case 0x18: // drum mode toggle
|
||||||
dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal));
|
dispatchCmd(DivCommand(DIV_CMD_FM_EXTCH,ch,effectVal));
|
||||||
|
@ -474,6 +477,58 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DIV_SYSTEM_OPL:
|
||||||
|
case DIV_SYSTEM_OPL2:
|
||||||
|
case DIV_SYSTEM_OPL3:
|
||||||
|
case DIV_SYSTEM_OPL_DRUMS:
|
||||||
|
case DIV_SYSTEM_OPL2_DRUMS:
|
||||||
|
case DIV_SYSTEM_OPL3_DRUMS:
|
||||||
|
switch (effect) {
|
||||||
|
case 0x10: // DAM
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,effectVal&1));
|
||||||
|
break;
|
||||||
|
case 0x11: // FB
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_FB,ch,effectVal&7));
|
||||||
|
break;
|
||||||
|
case 0x12: // TL op1
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,0,effectVal&0x3f));
|
||||||
|
break;
|
||||||
|
case 0x13: // TL op2
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,1,effectVal&0x3f));
|
||||||
|
break;
|
||||||
|
case 0x14: // TL op3
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,2,effectVal&0x3f));
|
||||||
|
break;
|
||||||
|
case 0x15: // TL op4
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_TL,ch,3,effectVal&0x3f));
|
||||||
|
break;
|
||||||
|
case 0x16: // MULT
|
||||||
|
if ((effectVal>>4)>0 && (effectVal>>4)<5) {
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_MULT,ch,(effectVal>>4)-1,effectVal&15));
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0x17: // DVB
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_LFO,ch,2+(effectVal&1)));
|
||||||
|
break;
|
||||||
|
case 0x19: // AR global
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,-1,effectVal&15));
|
||||||
|
break;
|
||||||
|
case 0x1a: // AR op1
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,0,effectVal&15));
|
||||||
|
break;
|
||||||
|
case 0x1b: // AR op2
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,1,effectVal&15));
|
||||||
|
break;
|
||||||
|
case 0x1c: // AR op3
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,2,effectVal&15));
|
||||||
|
break;
|
||||||
|
case 0x1d: // AR op4
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_FM_AR,ch,3,effectVal&15));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580:
|
||||||
switch (effect) {
|
switch (effect) {
|
||||||
case 0x10: // select waveform
|
case 0x10: // select waveform
|
||||||
|
|
Loading…
Reference in New Issue