Merge branch 'master' of https://github.com/tildearrow/furnace into ay_divider
* 'master' of https://github.com/tildearrow/furnace: dev92 - GUI: customizable channel collapsing! GUI: more improvements to instrument loading GUI: implement instrument load replace NES: fix duty effect not working at all GUI: part 2 of previous commit GUI: only use edit color when pat view is focused GUI: fix more issues here's the new OPLL default instrument OPL: fix channel muting - PLEASE READ! OPLL: fix compatible drum mode the final part of extra FM effects implement extra FM effects (OPLL and OPL) update to-do list prepare for possible .ftm import implement extra FM effects (OPN, OPM and OPZ) # Conflicts: # src/engine/engine.h
This commit is contained in:
commit
9109d2c64f
38 changed files with 4244 additions and 97 deletions
|
|
@ -135,6 +135,54 @@ const char* DivPlatformArcade::getEffectName(unsigned char effect) {
|
|||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set detune 2 (x: operator from 1 to 4 (0 for all ops); y: detune from 0 to 3)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to 1F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxx: Set decay 2 of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x5c:
|
||||
return "5Cxx: Set decay 2 of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x5d:
|
||||
return "5Dxx: Set decay 2 of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x5e:
|
||||
return "5Exx: Set decay 2 of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5f:
|
||||
return "5Fxx: Set decay 2 of operator 4 (0 to 1F)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -650,6 +698,134 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT2: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt2=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt2=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM_DEPTH: {
|
||||
amDepth=c.value;
|
||||
immWrite(0x19,amDepth);
|
||||
|
|
|
|||
|
|
@ -77,6 +77,54 @@ const char* DivPlatformGenesis::getEffectName(unsigned char effect) {
|
|||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set SSG envelope (x: operator from 1 to 4 (0 for all ops); y: 0-7 on, 8 off)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to 1F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxx: Set decay 2 of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x5c:
|
||||
return "5Cxx: Set decay 2 of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x5d:
|
||||
return "5Dxx: Set decay 2 of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x5e:
|
||||
return "5Exx: Set decay 2 of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5f:
|
||||
return "5Fxx: Set decay 2 of operator 4 (0 to 1F)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -780,7 +828,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else {
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ar=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
|
|
@ -788,6 +836,134 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_HARD_RESET:
|
||||
chan[c.chan].hardReset=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -235,6 +235,134 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
return 127;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -304,6 +304,7 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_STD_NOISE_MODE:
|
||||
chan[c.chan].duty=c.value;
|
||||
rWrite(0x5000+c.chan*4,0x30|chan[c.chan].outVol|((chan[c.chan].duty&3)<<6));
|
||||
break;
|
||||
case DIV_CMD_SAMPLE_BANK:
|
||||
sampleBank=c.value;
|
||||
|
|
|
|||
|
|
@ -520,6 +520,8 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
chan[c.chan].duty=c.value;
|
||||
if (c.chan==3) { // noise
|
||||
chan[c.chan].freqChanged=true;
|
||||
} else if (c.chan<2) {
|
||||
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].outVol|((chan[c.chan].duty&3)<<6));
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_NES_SWEEP:
|
||||
|
|
|
|||
|
|
@ -197,6 +197,48 @@ const char* DivPlatformOPL::getEffectName(unsigned char effect) {
|
|||
case 0x1d:
|
||||
return "1Dxx: Set attack of operator 4 (0 to F; 4-op only)";
|
||||
break;
|
||||
case 0x2a:
|
||||
return "2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 3 in OPL2 and 0 to 7 in OPL3)";
|
||||
break;
|
||||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set vibrato (x: operator from 1 to 4 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set key scale level (x: operator from 1 to 4 (0 for all ops); y: level from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set envelope sustain (x: operator from 1 to 4 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to F; 4-op only)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to F; 4-op only)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxy: Set whether key will scale envelope (x: operator from 1 to 4 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -522,6 +564,9 @@ int DivPlatformOPL::toFreq(int freq) {
|
|||
|
||||
void DivPlatformOPL::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
if (ch<melodicChans) {
|
||||
fm.channel[outChanMap[ch]].muted=mute;
|
||||
}
|
||||
int ops=(slots[3][ch]!=255 && chan[ch].state.ops==4 && oplType==3)?4:2;
|
||||
chan[ch].fourOp=(ops==4);
|
||||
update4OpMask=true;
|
||||
|
|
@ -841,6 +886,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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.dr=c.value2&15;
|
||||
rWrite(baseAddr+ADDR_AR_DR,(op.ar<<4)|op.dr);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.sl=c.value2&15;
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.rr=c.value2&15;
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.sl<<4)|op.rr);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.am=c.value2&1;
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.vib=c.value2&1;
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.sus=c.value2&1;
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.ksr=c.value2&1;
|
||||
rWrite(baseAddr+ADDR_AM_VIB_SUS_KSR_MULT,(op.am<<7)|(op.vib<<6)|(op.sus<<5)|(op.ksr<<4)|op.mult);
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.ws=c.value2&7;
|
||||
rWrite(baseAddr+ADDR_WS,op.ws&((oplType==3)?7:3));
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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; i++) {
|
||||
unsigned char slot=slots[i][c.chan];
|
||||
if (slot==255) continue;
|
||||
unsigned short baseAddr=slotMap[slot];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[(ops==4)?orderedOpsL[i]:i];
|
||||
op.ksl=c.value2&3;
|
||||
if (isMuted[c.chan]) {
|
||||
rWrite(baseAddr+ADDR_KSL_TL,63|(op.ksl<<6));
|
||||
} else {
|
||||
if (isOutputL[ops==4][chan[c.chan].state.alg][i]) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (c.value>=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;
|
||||
|
|
@ -968,10 +1229,12 @@ void DivPlatformOPL::reset() {
|
|||
properDrums=properDrumsSys;
|
||||
if (oplType==3) {
|
||||
chanMap=properDrums?chanMapOPL3Drums:chanMapOPL3;
|
||||
outChanMap=outChanMapOPL3;
|
||||
melodicChans=properDrums?15:18;
|
||||
totalChans=properDrums?20:18;
|
||||
} else {
|
||||
chanMap=properDrums?chanMapOPL2Drums:chanMapOPL2;
|
||||
outChanMap=outChanMapOPL2;
|
||||
melodicChans=properDrums?6:9;
|
||||
totalChans=properDrums?11:9;
|
||||
}
|
||||
|
|
@ -982,6 +1245,10 @@ void DivPlatformOPL::reset() {
|
|||
chan[i].vol=0x3f;
|
||||
chan[i].outVol=0x3f;
|
||||
}
|
||||
|
||||
for (int i=0; i<melodicChans; i++) {
|
||||
fm.channel[outChanMap[i]].muted=isMuted[i];
|
||||
}
|
||||
|
||||
for (int i=0; i<512; i++) {
|
||||
oldWrites[i]=-1;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
#include "../dispatch.h"
|
||||
#include "../macroInt.h"
|
||||
#include <queue>
|
||||
#include "../../../extern/Nuked-OPL3/opl3.h"
|
||||
#include "../../../extern/opl/opl3.h"
|
||||
|
||||
class DivPlatformOPL: public DivDispatch {
|
||||
protected:
|
||||
|
|
|
|||
|
|
@ -55,6 +55,36 @@ const char* DivPlatformOPLL::getEffectName(unsigned char effect) {
|
|||
case 0x1b:
|
||||
return "1Bxx: Set attack of operator 2 (0 to F)";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 2 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 2 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 2 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set vibrato (x: operator from 1 to 2 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set key scale level (x: operator from 1 to 2 (0 for all ops); y: level from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set envelope sustain (x: operator from 1 to 2 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxy: Set whether key will scale envelope (x: operator from 1 to 2 (0 for all ops); y: enabled)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -447,6 +477,7 @@ int DivPlatformOPLL::dispatch(DivCommand c) {
|
|||
if (drums) {
|
||||
drums=false;
|
||||
immWrite(0x0e,0);
|
||||
drumState=0;
|
||||
}
|
||||
}
|
||||
if (c.chan<9) {
|
||||
|
|
@ -637,6 +668,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;
|
||||
|
|
|
|||
|
|
@ -137,8 +137,84 @@ const char* DivPlatformTX81Z::getEffectName(unsigned char effect) {
|
|||
case 0x1f:
|
||||
return "1Fxx: Set PM depth (0 to 7F)";
|
||||
break;
|
||||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
case 0x28:
|
||||
return "28xy: Set reverb (x: operator from 1 to 4 (0 for all ops); y: reverb from 0 to 7)";
|
||||
break;
|
||||
case 0x2a:
|
||||
return "2Axy: Set waveform (x: operator from 1 to 4 (0 for all ops); y: waveform from 0 to 7)";
|
||||
break;
|
||||
case 0x2b:
|
||||
return "2Bxy: Set envelope generator shift (x: operator from 1 to 4 (0 for all ops); y: shift from 0 to 3)";
|
||||
break;
|
||||
case 0x2c:
|
||||
return "2Cxy: Set fine multiplier (x: operator from 1 to 4 (0 for all ops); y: fine)";
|
||||
break;
|
||||
case 0x2f:
|
||||
return "2Fxx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x30: case 0x31: case 0x32: case 0x33:
|
||||
case 0x34: case 0x35: case 0x36: case 0x37:
|
||||
return "3xyy: Set fixed frequency of operator 1 (x: octave from 0 to 7; y: frequency)";
|
||||
break;
|
||||
case 0x38: case 0x39: case 0x3a: case 0x3b:
|
||||
case 0x3c: case 0x3d: case 0x3e: case 0x3f:
|
||||
return "3xyy: Set fixed frequency of operator 2 (x: octave from 8 to F; y: frequency)";
|
||||
break;
|
||||
case 0x40: case 0x41: case 0x42: case 0x43:
|
||||
case 0x44: case 0x45: case 0x46: case 0x47:
|
||||
return "4xyy: Set fixed frequency of operator 3 (x: octave from 0 to 7; y: frequency)";
|
||||
break;
|
||||
case 0x48: case 0x49: case 0x4a: case 0x4b:
|
||||
case 0x4c: case 0x4d: case 0x4e: case 0x4f:
|
||||
return "4xyy: Set fixed frequency of operator 4 (x: octave from 8 to F; y: frequency)";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set detune 2 (x: operator from 1 to 4 (0 for all ops); y: detune from 0 to 3)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to 1F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxx: Set decay 2 of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x5c:
|
||||
return "5Cxx: Set decay 2 of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x5d:
|
||||
return "5Dxx: Set decay 2 of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x5e:
|
||||
return "5Exx: Set decay 2 of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5f:
|
||||
return "5Fxx: Set decay 2 of operator 4 (0 to 1F)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -604,8 +680,10 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
|||
case DIV_CMD_FM_MULT: {
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.mult=c.value2&15;
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
if (!op.egt) {
|
||||
op.mult=c.value2&15;
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_TL: {
|
||||
|
|
@ -639,6 +717,221 @@ int DivPlatformTX81Z::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT2: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt2=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt2=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,(op.d2r&31)|(op.dt2<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
if (!op.egt) {
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
}
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
if (!op.egt) {
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_EG_SHIFT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.ksl=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ksl=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_REV: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dam=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dam=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_EGS_REV,(op.dam&7)|(op.ksl<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_WS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.ws=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ws=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_FINE: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
if (!op.egt) {
|
||||
op.dvb=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
|
||||
}
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
if (!op.egt) {
|
||||
op.dvb=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_FIXFREQ: {
|
||||
if (c.value<0 || c.value>3) break;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.egt=(c.value2>0);
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.egt<<5)|(op.rs<<6));
|
||||
if (op.egt) {
|
||||
rWrite(baseAddr+ADDR_MULT_DT,((c.value2>>4)&15)|((c.value2>>8)&7));
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(c.value2&15)|(op.ws<<4));
|
||||
} else {
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|((op.egt?(op.dt&7):dtTable[op.dt&7])<<4));
|
||||
rWrite(baseAddr+ADDR_WS_FINE,(op.dvb&15)|(op.ws<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM_DEPTH: {
|
||||
amDepth=c.value;
|
||||
immWrite(0x19,amDepth);
|
||||
|
|
|
|||
|
|
@ -397,6 +397,54 @@ const char* DivPlatformYM2610::getEffectName(unsigned char effect) {
|
|||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set SSG envelope (x: operator from 1 to 4 (0 for all ops); y: 0-7 on, 8 off)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to 1F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxx: Set decay 2 of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x5c:
|
||||
return "5Cxx: Set decay 2 of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x5d:
|
||||
return "5Dxx: Set decay 2 of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x5e:
|
||||
return "5Exx: Set decay 2 of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5f:
|
||||
return "5Fxx: Set decay 2 of operator 4 (0 to 1F)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1088,6 +1136,134 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_HARD_RESET:
|
||||
chan[c.chan].hardReset=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -377,6 +377,54 @@ const char* DivPlatformYM2610B::getEffectName(unsigned char effect) {
|
|||
case 0x30:
|
||||
return "30xx: Toggle hard envelope reset on new notes";
|
||||
break;
|
||||
case 0x50:
|
||||
return "50xy: Set AM (x: operator from 1 to 4 (0 for all ops); y: AM)";
|
||||
break;
|
||||
case 0x51:
|
||||
return "51xy: Set sustain level (x: operator from 1 to 4 (0 for all ops); y: sustain)";
|
||||
break;
|
||||
case 0x52:
|
||||
return "52xy: Set release (x: operator from 1 to 4 (0 for all ops); y: release)";
|
||||
break;
|
||||
case 0x53:
|
||||
return "53xy: Set detune (x: operator from 1 to 4 (0 for all ops); y: detune where 3 is center)";
|
||||
break;
|
||||
case 0x54:
|
||||
return "54xy: Set envelope scale (x: operator from 1 to 4 (0 for all ops); y: scale from 0 to 3)";
|
||||
break;
|
||||
case 0x55:
|
||||
return "55xy: Set SSG envelope (x: operator from 1 to 4 (0 for all ops); y: 0-7 on, 8 off)";
|
||||
break;
|
||||
case 0x56:
|
||||
return "56xx: Set decay of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x57:
|
||||
return "57xx: Set decay of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x58:
|
||||
return "58xx: Set decay of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x59:
|
||||
return "59xx: Set decay of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5a:
|
||||
return "5Axx: Set decay of operator 4 (0 to 1F)";
|
||||
break;
|
||||
case 0x5b:
|
||||
return "5Bxx: Set decay 2 of all operators (0 to 1F)";
|
||||
break;
|
||||
case 0x5c:
|
||||
return "5Cxx: Set decay 2 of operator 1 (0 to 1F)";
|
||||
break;
|
||||
case 0x5d:
|
||||
return "5Dxx: Set decay 2 of operator 2 (0 to 1F)";
|
||||
break;
|
||||
case 0x5e:
|
||||
return "5Exx: Set decay 2 of operator 3 (0 to 1F)";
|
||||
break;
|
||||
case 0x5f:
|
||||
return "5Fxx: Set decay 2 of operator 4 (0 to 1F)";
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -1066,6 +1114,134 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_HARD_RESET:
|
||||
chan[c.chan].hardReset=c.value;
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -175,17 +175,146 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AR: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[i];
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.ar=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||
rWrite(baseAddr+0x50,(c.value2&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||
op.ar=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+0x50,(c.value2&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[2]|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]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[2].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[2]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -175,17 +175,146 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AR: {
|
||||
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[i];
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.ar=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+0x50,(c.value2&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else {
|
||||
DivInstrumentFM::Operator op=ins->fm.op[orderedOps[c.value]];
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.ar=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+0x50,(c.value2&31)|(op.rs<<6));
|
||||
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RS: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.rs=c.value2&3;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_AM: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.am=c.value2&1;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.dr=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SL: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.sl=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_RR: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.rr=c.value2&15;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_D2R: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.d2r=c.value2&31;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_DT: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.dt=c.value&7;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.dt=c.value2&7;
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_FM_SSG: {
|
||||
if (c.value<0) {
|
||||
for (int i=0; i<4; i++) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[i];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[i];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
} else if (c.value<4) {
|
||||
DivInstrumentFM::Operator& op=chan[1].state.op[orderedOps[c.value]];
|
||||
op.ssgEnv=8^(c.value2&15);
|
||||
unsigned short baseAddr=chanOffs[1]|opOffs[orderedOps[c.value]];
|
||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue