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

@ -26,23 +26,8 @@
#define IS_REALLY_MUTED(x) (isMuted[x] && (x<5 || !softPCM || (isMuted[5] && isMuted[6])))
int DivPlatformGenesisExt::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformGenesis::dispatch(c);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformGenesis::dispatch(c);
}
int ch=c.chan-2;
void DivPlatformGenesisExt::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformGenesis::dispatch(c);
}
switch (c.cmd) {
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;
@ -54,15 +39,6 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
chan[2].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
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?!
@ -86,6 +62,36 @@ int DivPlatformGenesisExt::dispatch(DivCommand c) {
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 DivPlatformGenesisExt::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformGenesis::dispatch(c);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformGenesis::dispatch(c);
}
int ch=c.chan-2;
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformGenesis::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -202,6 +208,11 @@ int DivPlatformGenesisExt::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;

View file

@ -29,6 +29,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
bool isOpMuted[4];
friend void putDispatchChip(void*,int);
friend void putDispatchChan(void*,int,int);
inline void commitStateExt(int ch, DivInstrument* ins);
public:
int dispatch(DivCommand c);
void* getChanState(int chan);

View file

@ -24,23 +24,8 @@
#define CHIP_FREQBASE fmFreqBase
#define CHIP_DIVIDER fmDivBase
int DivPlatformYM2203Ext::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformYM2203::dispatch(c);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformYM2203::dispatch(c);
}
int ch=c.chan-2;
void DivPlatformYM2203Ext::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformYM2203::dispatch(c);
}
switch (c.cmd) {
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;
@ -50,15 +35,6 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) {
chan[2].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
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?!
@ -81,6 +57,36 @@ int DivPlatformYM2203Ext::dispatch(DivCommand c) {
if (opChan[ch].insChanged) { // TODO how does this work?
rWrite(chanOffs[2]+0xb0,(chan[2].state.alg&7)|(chan[2].state.fb<<3));
}
}
int DivPlatformYM2203Ext::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformYM2203::dispatch(c);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformYM2203::dispatch(c);
}
int ch=c.chan-2;
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformYM2203::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -166,6 +172,11 @@ int DivPlatformYM2203Ext::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;

View file

@ -28,6 +28,7 @@ class DivPlatformYM2203Ext: public DivPlatformYM2203 {
OPNOpChannel opChan[4];
bool isOpMuted[4];
friend void putDispatchChip(void*,int);
inline void commitStateExt(int ch, DivInstrument* ins);
public:
int dispatch(DivCommand c);
void* getChanState(int chan);

View file

@ -24,23 +24,8 @@
#define CHIP_FREQBASE fmFreqBase
#define CHIP_DIVIDER fmDivBase
int DivPlatformYM2608Ext::dispatch(DivCommand c) {
if (c.chan<2) {
return DivPlatformYM2608::dispatch(c);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformYM2608::dispatch(c);
}
int ch=c.chan-2;
void DivPlatformYM2608Ext::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformYM2608::dispatch(c);
}
switch (c.cmd) {
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;
@ -52,15 +37,6 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
chan[2].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
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?!
@ -84,6 +60,36 @@ int DivPlatformYM2608Ext::dispatch(DivCommand c) {
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);
}
if (c.chan>5) {
c.chan-=3;
return DivPlatformYM2608::dispatch(c);
}
int ch=c.chan-2;
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=2;
return DivPlatformYM2608::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
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;

View file

@ -28,6 +28,7 @@ class DivPlatformYM2608Ext: public DivPlatformYM2608 {
OPNOpChannelStereo opChan[4];
bool isOpMuted[4];
friend void putDispatchChip(void*,int);
inline void commitStateExt(int ch, DivInstrument* ins);
public:
int dispatch(DivCommand c);
void* getChanState(int chan);

View file

@ -20,23 +20,8 @@
#include "ym2610bext.h"
#include <math.h>
int DivPlatformYM2610BExt::dispatch(DivCommand c) {
if (c.chan<extChanOffs) {
return DivPlatformYM2610B::dispatch(c);
}
if (c.chan>(extChanOffs+3)) {
c.chan-=3;
return DivPlatformYM2610B::dispatch(c);
}
int ch=c.chan-extChanOffs;
void DivPlatformYM2610BExt::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=extChanOffs;
return DivPlatformYM2610B::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (opChan[ch].insChanged) {
chan[extChanOffs].state.alg=ins->fm.alg;
@ -48,15 +33,6 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
chan[extChanOffs].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[ordch];
DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[ordch];
// TODO: how does this work?!
@ -80,6 +56,36 @@ int DivPlatformYM2610BExt::dispatch(DivCommand c) {
rWrite(chanOffs[extChanOffs]+0xb0,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3));
rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4));
}
}
int DivPlatformYM2610BExt::dispatch(DivCommand c) {
if (c.chan<extChanOffs) {
return DivPlatformYM2610B::dispatch(c);
}
if (c.chan>(extChanOffs+3)) {
c.chan-=3;
return DivPlatformYM2610B::dispatch(c);
}
int ch=c.chan-extChanOffs;
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=extChanOffs;
return DivPlatformYM2610B::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -180,6 +186,11 @@ int DivPlatformYM2610BExt::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;

View file

@ -28,6 +28,7 @@ class DivPlatformYM2610BExt: public DivPlatformYM2610B {
OPNOpChannelStereo opChan[4];
bool isOpMuted[4];
friend void putDispatchChip(void*,int);
inline void commitStateExt(int ch, DivInstrument* ins);
public:
int dispatch(DivCommand c);
void* getChanState(int chan);

View file

@ -20,23 +20,8 @@
#include "ym2610ext.h"
#include <math.h>
int DivPlatformYM2610Ext::dispatch(DivCommand c) {
if (c.chan<extChanOffs) {
return DivPlatformYM2610::dispatch(c);
}
if (c.chan>(extChanOffs+3)) {
c.chan-=3;
return DivPlatformYM2610::dispatch(c);
}
int ch=c.chan-extChanOffs;
void DivPlatformYM2610Ext::commitStateExt(int ch, DivInstrument* ins) {
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=extChanOffs;
return DivPlatformYM2610::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (opChan[ch].insChanged) {
chan[extChanOffs].state.alg=ins->fm.alg;
@ -48,15 +33,6 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
chan[extChanOffs].state.op[ordch]=ins->fm.op[ordch];
}
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
unsigned short baseAddr=chanOffs[extChanOffs]|opOffs[ordch];
DivInstrumentFM::Operator& op=chan[extChanOffs].state.op[ordch];
// TODO: how does this work?!
@ -80,6 +56,36 @@ int DivPlatformYM2610Ext::dispatch(DivCommand c) {
rWrite(chanOffs[extChanOffs]+0xb0,(chan[extChanOffs].state.alg&7)|(chan[extChanOffs].state.fb<<3));
rWrite(chanOffs[extChanOffs]+0xb4,(IS_EXTCH_MUTED?0:(opChan[ch].pan<<6))|(chan[extChanOffs].state.fms&7)|((chan[extChanOffs].state.ams&3)<<4));
}
}
int DivPlatformYM2610Ext::dispatch(DivCommand c) {
if (c.chan<extChanOffs) {
return DivPlatformYM2610::dispatch(c);
}
if (c.chan>(extChanOffs+3)) {
c.chan-=3;
return DivPlatformYM2610::dispatch(c);
}
int ch=c.chan-extChanOffs;
int ordch=orderedOps[ch];
if (!extMode) {
c.chan=extChanOffs;
return DivPlatformYM2610::dispatch(c);
}
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(opChan[ch].ins,DIV_INS_FM);
if (noExtMacros) {
opChan[ch].macroInit(NULL);
} else {
opChan[ch].macroInit(ins);
}
if (!opChan[ch].std.vol.will) {
opChan[ch].outVol=opChan[ch].vol;
}
commitStateExt(ch,ins);
opChan[ch].insChanged=false;
if (c.value!=DIV_NOTE_NULL) {
@ -180,6 +186,11 @@ int DivPlatformYM2610Ext::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;

View file

@ -28,6 +28,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
OPNOpChannelStereo opChan[4];
bool isOpMuted[4];
friend void putDispatchChip(void*,int);
inline void commitStateExt(int ch, DivInstrument* ins);
public:
int dispatch(DivCommand c);
void* getChanState(int chan);