OPN/2/A/B: Seamless Legato Ins Change (ExtCh)

This commit is contained in:
tildearrow 2023-01-19 03:15:41 -05:00
parent 3e43cdacd2
commit cac807551f
10 changed files with 227 additions and 167 deletions

View file

@ -24,6 +24,44 @@
#define CHIP_FREQBASE fmFreqBase
#define CHIP_DIVIDER fmDivBase
void DivPlatformYM2608Ext::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (opChan[ch].insChanged) {
chan[2].state.alg=ins->fm.alg;
if (ch==0 || fbAllOps) {
chan[2].state.fb=ins->fm.fb;
}
chan[2].state.fms=ins->fm.fms;
chan[2].state.ams=ins->fm.ams;
chan[2].state.op[ordch]=ins->fm.op[ordch];
}
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
DivInstrumentFM::Operator& op=chan[2].state.op[ordch];
// TODO: how does this work?!
if (isOpMuted[ch]) {
rWrite(baseAddr+0x40,127);
} else {
if (opChan[ch].insChanged) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch].outVol&0x7f,127));
}
}
if (opChan[ch].insChanged) {
rWrite(baseAddr+0x30,(op.mult&15)|(dtTable[op.dt&7]<<4));
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
rWrite(baseAddr+0x60,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+0x70,op.d2r&31);
rWrite(baseAddr+0x80,(op.rr&15)|(op.sl<<4));
rWrite(baseAddr+0x90,op.ssgEnv&15);
opChan[ch].mask=op.enable;
}
if (opChan[ch].insChanged) { // TODO how does this work?
rWrite(chanOffs[2]+0xb0,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4));
}
}
int DivPlatformYM2608Ext::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformYM2608::dispatch(c);
@ -42,16 +80,6 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (opChan[ch].insChanged) {
chan[2].state.alg=ins->fm.alg;
if (ch==0 || fbAllOps) {
chan[2].state.fb=ins->fm.fb;
}
chan[2].state.fms=ins->fm.fms;
chan[2].state.ams=ins->fm.ams;
chan[2].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
@ -60,30 +88,8 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
unsigned short baseAddr=chanOffs[2]|opOffs[ordch];
DivInstrumentFM::Operator& op=chan[2].state.op[ordch];
// TODO: how does this work?!
if (isOpMuted[ch]) {
rWrite(baseAddr+0x40,127);
} else {
if (opChan[ch].insChanged) {
rWrite(baseAddr+0x40,127-VOL_SCALE_LOG_BROKEN(127-op.tl,opChan[ch].outVol&0x7f,127));
}
}
if (opChan[ch].insChanged) {
rWrite(baseAddr+0x30,(op.mult&15)|(dtTable[op.dt&7]<<4));
rWrite(baseAddr+0x50,(op.ar&31)|(op.rs<<6));
rWrite(baseAddr+0x60,(op.dr&31)|(op.am<<7));
rWrite(baseAddr+0x70,op.d2r&31);
rWrite(baseAddr+0x80,(op.rr&15)|(op.sl<<4));
rWrite(baseAddr+0x90,op.ssgEnv&15);
opChan[ch].mask=op.enable;
}
if (opChan[ch].insChanged) { // TODO how does this work?
rWrite(chanOffs[2]+0xb0,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
rWrite(chanOffs[2]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[2].state.fms&7)|((chan[2].state.ams&3)<<4));
}
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -184,6 +190,11 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
break;
}
case DIV_CMD_LEGATO: {
if (opChan[ch].insChanged) {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
}
opChan[ch].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
opChan[ch].freqChanged=true;
break;