mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-27 06:53:01 +00:00
OPN/2/A/B: Seamless Legato Ins Change
This commit is contained in:
parent
982b250307
commit
1b05fe577d
10 changed files with 238 additions and 178 deletions
|
@ -569,6 +569,47 @@ void DivPlatformGenesis::muteChannel(int ch, bool mute) {
|
||||||
rWrite(chanOffs[ch]+ADDR_LRAF,(IS_REALLY_MUTED(ch)?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
rWrite(chanOffs[ch]+ADDR_LRAF,(IS_REALLY_MUTED(ch)?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformGenesis::commitState(int ch, DivInstrument* ins) {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
chan[ch].state=ins->fm;
|
||||||
|
chan[ch].opMask=
|
||||||
|
(chan[ch].state.op[0].enable?1:0)|
|
||||||
|
(chan[ch].state.op[2].enable?2:0)|
|
||||||
|
(chan[ch].state.op[1].enable?4:0)|
|
||||||
|
(chan[ch].state.op[3].enable?8:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[i];
|
||||||
|
if (isMuted[ch]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
|
} else {
|
||||||
|
if (KVS(ch,i)) {
|
||||||
|
if (!chan[ch].active || chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(chanOffs[ch]+ADDR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
|
||||||
|
rWrite(chanOffs[ch]+ADDR_LRAF,(IS_REALLY_MUTED(ch)?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformGenesis::dispatch(DivCommand c) {
|
int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
|
@ -651,49 +692,12 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
if (c.chan>=6) break;
|
if (c.chan>=6) break;
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
chan[c.chan].state=ins->fm;
|
|
||||||
chan[c.chan].opMask=
|
|
||||||
(chan[c.chan].state.op[0].enable?1:0)|
|
|
||||||
(chan[c.chan].state.op[2].enable?2:0)|
|
|
||||||
(chan[c.chan].state.op[1].enable?4:0)|
|
|
||||||
(chan[c.chan].state.op[3].enable?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
chan[c.chan].macroInit(ins);
|
chan[c.chan].macroInit(ins);
|
||||||
if (!chan[c.chan].std.vol.will) {
|
if (!chan[c.chan].std.vol.will) {
|
||||||
chan[c.chan].outVol=chan[c.chan].vol;
|
chan[c.chan].outVol=chan[c.chan].vol;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
commitState(c.chan,ins);
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
|
||||||
if (isMuted[c.chan]) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
|
||||||
} else {
|
|
||||||
if (KVS(c.chan,i)) {
|
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
|
||||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
|
||||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
|
||||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(IS_REALLY_MUTED(c.chan)?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
@ -876,6 +880,11 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
||||||
} else if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
|
} else if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
|
||||||
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
|
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
|
||||||
} else {
|
} else {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
commitState(c.chan,ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
|
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
|
||||||
}
|
}
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
|
|
|
@ -92,6 +92,7 @@ class DivPlatformGenesis: public DivPlatformOPN {
|
||||||
friend void putDispatchChan(void*,int,int);
|
friend void putDispatchChan(void*,int,int);
|
||||||
|
|
||||||
inline void processDAC(int iRate);
|
inline void processDAC(int iRate);
|
||||||
|
inline void commitState(int ch, DivInstrument* ins);
|
||||||
void acquire_nuked(short** buf, size_t len);
|
void acquire_nuked(short** buf, size_t len);
|
||||||
void acquire_ymfm(short** buf, size_t len);
|
void acquire_ymfm(short** buf, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -474,6 +474,46 @@ void DivPlatformYM2203::tick(bool sysTick) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2203::commitState(int ch, DivInstrument* ins) {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
chan[ch].state=ins->fm;
|
||||||
|
chan[ch].opMask=
|
||||||
|
(chan[ch].state.op[0].enable?1:0)|
|
||||||
|
(chan[ch].state.op[2].enable?2:0)|
|
||||||
|
(chan[ch].state.op[1].enable?4:0)|
|
||||||
|
(chan[ch].state.op[3].enable?8:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[i];
|
||||||
|
if (isMuted[ch]) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127);
|
||||||
|
} else {
|
||||||
|
if (KVS(ch,i)) {
|
||||||
|
if (!chan[ch].active || chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(chanOffs[ch]+ADDR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformYM2203::dispatch(DivCommand c) {
|
int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
if (c.chan>2) {
|
if (c.chan>2) {
|
||||||
c.chan-=3;
|
c.chan-=3;
|
||||||
|
@ -489,43 +529,7 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
commitState(c.chan,ins);
|
||||||
chan[c.chan].state=ins->fm;
|
|
||||||
chan[c.chan].opMask=
|
|
||||||
(chan[c.chan].state.op[0].enable?1:0)|
|
|
||||||
(chan[c.chan].state.op[2].enable?2:0)|
|
|
||||||
(chan[c.chan].state.op[1].enable?4:0)|
|
|
||||||
(chan[c.chan].state.op[3].enable?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
|
||||||
if (isMuted[c.chan]) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127);
|
|
||||||
} else {
|
|
||||||
if (KVS(c.chan,i)) {
|
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
|
||||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
|
||||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
|
||||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
|
||||||
}
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
@ -616,6 +620,11 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
commitState(c.chan,ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
|
chan[c.chan].baseFreq=NOTE_FNUM_BLOCK(c.value,11);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -55,6 +55,8 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
|
||||||
|
inline void commitState(int ch, DivInstrument* ins);
|
||||||
|
|
||||||
void acquire_combo(short** buf, size_t len);
|
void acquire_combo(short** buf, size_t len);
|
||||||
void acquire_ymfm(short** buf, size_t len);
|
void acquire_ymfm(short** buf, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -789,6 +789,43 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2608::commitState(int ch, DivInstrument* ins) {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
chan[ch].state=ins->fm;
|
||||||
|
chan[ch].opMask=
|
||||||
|
(chan[ch].state.op[0].enable?1:0)|
|
||||||
|
(chan[ch].state.op[2].enable?2:0)|
|
||||||
|
(chan[ch].state.op[1].enable?4:0)|
|
||||||
|
(chan[ch].state.op[3].enable?8:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[i];
|
||||||
|
if (KVS(ch,i)) {
|
||||||
|
if (!chan[ch].active || chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(chanOffs[ch]+ADDR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
|
||||||
|
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformYM2608::dispatch(DivCommand c) {
|
int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
if (c.chan>5 && c.chan<9) {
|
if (c.chan>5 && c.chan<9) {
|
||||||
c.chan-=6;
|
c.chan-=6;
|
||||||
|
@ -902,40 +939,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
commitState(c.chan,ins);
|
||||||
chan[c.chan].state=ins->fm;
|
|
||||||
chan[c.chan].opMask=
|
|
||||||
(chan[c.chan].state.op[0].enable?1:0)|
|
|
||||||
(chan[c.chan].state.op[2].enable?2:0)|
|
|
||||||
(chan[c.chan].state.op[1].enable?4:0)|
|
|
||||||
(chan[c.chan].state.op[3].enable?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
|
||||||
if (KVS(c.chan,i)) {
|
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
|
||||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
|
||||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
|
||||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
@ -1063,6 +1067,13 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||||
|
if (c.chan<=psgChanOffs) {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
commitState(c.chan,ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -70,6 +70,8 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
|
||||||
|
inline void commitState(int ch, DivInstrument* ins);
|
||||||
|
|
||||||
void acquire_combo(short** buf, size_t len);
|
void acquire_combo(short** buf, size_t len);
|
||||||
void acquire_ymfm(short** buf, size_t len);
|
void acquire_ymfm(short** buf, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -724,6 +724,43 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610::commitState(int ch, DivInstrument* ins) {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
chan[ch].state=ins->fm;
|
||||||
|
chan[ch].opMask=
|
||||||
|
(chan[ch].state.op[0].enable?1:0)|
|
||||||
|
(chan[ch].state.op[2].enable?2:0)|
|
||||||
|
(chan[ch].state.op[1].enable?4:0)|
|
||||||
|
(chan[ch].state.op[3].enable?8:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[i];
|
||||||
|
if (KVS(ch,i)) {
|
||||||
|
if (!chan[ch].active || chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(chanOffs[ch]+ADDR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
|
||||||
|
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformYM2610::dispatch(DivCommand c) {
|
int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
if (c.chan>=psgChanOffs && c.chan<adpcmAChanOffs) {
|
if (c.chan>=psgChanOffs && c.chan<adpcmAChanOffs) {
|
||||||
c.chan-=psgChanOffs;
|
c.chan-=psgChanOffs;
|
||||||
|
@ -878,40 +915,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
commitState(c.chan,ins);
|
||||||
chan[c.chan].state=ins->fm;
|
|
||||||
chan[c.chan].opMask=
|
|
||||||
(chan[c.chan].state.op[0].enable?1:0)|
|
|
||||||
(chan[c.chan].state.op[2].enable?2:0)|
|
|
||||||
(chan[c.chan].state.op[1].enable?4:0)|
|
|
||||||
(chan[c.chan].state.op[3].enable?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
|
||||||
if (KVS(c.chan,i)) {
|
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
|
||||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
|
||||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
|
||||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
@ -1039,6 +1043,13 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
||||||
|
if (c.chan<=psgChanOffs) {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
commitState(c.chan,ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -38,6 +38,8 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
|
||||||
|
void commitState(int ch, DivInstrument* ins);
|
||||||
|
|
||||||
void acquire_combo(short** buf, size_t len);
|
void acquire_combo(short** buf, size_t len);
|
||||||
void acquire_ymfm(short** buf, size_t len);
|
void acquire_ymfm(short** buf, size_t len);
|
||||||
|
|
||||||
|
|
|
@ -791,6 +791,43 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
||||||
ay->getRegisterWrites().clear();
|
ay->getRegisterWrites().clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformYM2610B::commitState(int ch, DivInstrument* ins) {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
chan[ch].state=ins->fm;
|
||||||
|
chan[ch].opMask=
|
||||||
|
(chan[ch].state.op[0].enable?1:0)|
|
||||||
|
(chan[ch].state.op[2].enable?2:0)|
|
||||||
|
(chan[ch].state.op[1].enable?4:0)|
|
||||||
|
(chan[ch].state.op[3].enable?8:0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i=0; i<4; i++) {
|
||||||
|
unsigned short baseAddr=chanOffs[ch]|opOffs[i];
|
||||||
|
DivInstrumentFM::Operator& op=chan[ch].state.op[i];
|
||||||
|
if (KVS(ch,i)) {
|
||||||
|
if (!chan[ch].active || chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[ch].outVol&0x7f,127));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_TL,op.tl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
||||||
|
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
||||||
|
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
||||||
|
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
||||||
|
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
||||||
|
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[ch].insChanged) {
|
||||||
|
rWrite(chanOffs[ch]+ADDR_FB_ALG,(chan[ch].state.alg&7)|(chan[ch].state.fb<<3));
|
||||||
|
rWrite(chanOffs[ch]+ADDR_LRAF,(isMuted[ch]?0:(chan[ch].pan<<6))|(chan[ch].state.fms&7)|((chan[ch].state.ams&3)<<4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformYM2610B::dispatch(DivCommand c) {
|
int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
if (c.chan>=psgChanOffs && c.chan<adpcmAChanOffs) {
|
if (c.chan>=psgChanOffs && c.chan<adpcmAChanOffs) {
|
||||||
c.chan-=psgChanOffs;
|
c.chan-=psgChanOffs;
|
||||||
|
@ -945,40 +982,7 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chan[c.chan].insChanged) {
|
commitState(c.chan,ins);
|
||||||
chan[c.chan].state=ins->fm;
|
|
||||||
chan[c.chan].opMask=
|
|
||||||
(chan[c.chan].state.op[0].enable?1:0)|
|
|
||||||
(chan[c.chan].state.op[2].enable?2:0)|
|
|
||||||
(chan[c.chan].state.op[1].enable?4:0)|
|
|
||||||
(chan[c.chan].state.op[3].enable?8:0);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<4; i++) {
|
|
||||||
unsigned short baseAddr=chanOffs[c.chan]|opOffs[i];
|
|
||||||
DivInstrumentFM::Operator& op=chan[c.chan].state.op[i];
|
|
||||||
if (KVS(c.chan,i)) {
|
|
||||||
if (!chan[c.chan].active || chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,127-VOL_SCALE_LOG_BROKEN(127-op.tl,chan[c.chan].outVol&0x7f,127));
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_TL,op.tl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(baseAddr+ADDR_MULT_DT,(op.mult&15)|(dtTable[op.dt&7]<<4));
|
|
||||||
rWrite(baseAddr+ADDR_RS_AR,(op.ar&31)|(op.rs<<6));
|
|
||||||
rWrite(baseAddr+ADDR_AM_DR,(op.dr&31)|(op.am<<7));
|
|
||||||
rWrite(baseAddr+ADDR_DT2_D2R,op.d2r&31);
|
|
||||||
rWrite(baseAddr+ADDR_SL_RR,(op.rr&15)|(op.sl<<4));
|
|
||||||
rWrite(baseAddr+ADDR_SSG,op.ssgEnv&15);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (chan[c.chan].insChanged) {
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_FB_ALG,(chan[c.chan].state.alg&7)|(chan[c.chan].state.fb<<3));
|
|
||||||
rWrite(chanOffs[c.chan]+ADDR_LRAF,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|(chan[c.chan].state.fms&7)|((chan[c.chan].state.ams&3)<<4));
|
|
||||||
}
|
|
||||||
chan[c.chan].insChanged=false;
|
chan[c.chan].insChanged=false;
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
@ -1106,6 +1110,13 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO: {
|
case DIV_CMD_LEGATO: {
|
||||||
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
||||||
|
if (c.chan<=psgChanOffs) {
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||||
|
commitState(c.chan,ins);
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
|
}
|
||||||
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
chan[c.chan].baseFreq=NOTE_OPNB(c.chan,c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -34,6 +34,8 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
||||||
|
|
||||||
friend void putDispatchChip(void*,int);
|
friend void putDispatchChip(void*,int);
|
||||||
|
|
||||||
|
void commitState(int ch, DivInstrument* ins);
|
||||||
|
|
||||||
void acquire_combo(short** buf, size_t len);
|
void acquire_combo(short** buf, size_t len);
|
||||||
void acquire_ymfm(short** buf, size_t len);
|
void acquire_ymfm(short** buf, size_t len);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue