mirror of
https://github.com/tildearrow/furnace.git
synced 2024-12-03 09:47:26 +00:00
redo opnx csm
This commit is contained in:
parent
901bb110cc
commit
5f47166012
17 changed files with 572 additions and 147 deletions
|
@ -374,6 +374,16 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
} else {
|
||||
((DivPlatformYM2610Ext*)dispatch)->setCombo(eng->getConfInt("opnbCore",1));
|
||||
}
|
||||
((DivPlatformYM2610Ext*)dispatch)->setCSM(0);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2610_CSM:
|
||||
dispatch=new DivPlatformYM2610Ext;
|
||||
if (isRender) {
|
||||
((DivPlatformYM2610Ext*)dispatch)->setCombo(eng->getConfInt("opnCoreRender",1)==1);
|
||||
} else {
|
||||
((DivPlatformYM2610Ext*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
|
||||
}
|
||||
((DivPlatformYM2610Ext*)dispatch)->setCSM(1);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2610B:
|
||||
dispatch=new DivPlatformYM2610B;
|
||||
|
@ -390,6 +400,16 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
} else {
|
||||
((DivPlatformYM2610BExt*)dispatch)->setCombo(eng->getConfInt("opnbCore",1));
|
||||
}
|
||||
((DivPlatformYM2610BExt*)dispatch)->setCSM(0);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2610B_CSM:
|
||||
dispatch=new DivPlatformYM2610BExt;
|
||||
if (isRender) {
|
||||
((DivPlatformYM2610BExt*)dispatch)->setCombo(eng->getConfInt("opnCoreRender",1)==1);
|
||||
} else {
|
||||
((DivPlatformYM2610BExt*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
|
||||
}
|
||||
((DivPlatformYM2610BExt*)dispatch)->setCSM(1);
|
||||
break;
|
||||
case DIV_SYSTEM_AMIGA:
|
||||
dispatch=new DivPlatformAmiga;
|
||||
|
@ -431,6 +451,16 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
} else {
|
||||
((DivPlatformYM2203Ext*)dispatch)->setCombo(eng->getConfInt("opn1Core",1));
|
||||
}
|
||||
((DivPlatformYM2203Ext*)dispatch)->setCSM(0);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2203_CSM:
|
||||
dispatch=new DivPlatformYM2203Ext;
|
||||
if (isRender) {
|
||||
((DivPlatformYM2203Ext*)dispatch)->setCombo(eng->getConfInt("opnCoreRender",1)==1);
|
||||
} else {
|
||||
((DivPlatformYM2203Ext*)dispatch)->setCombo(eng->getConfInt("opnCore",1)==1);
|
||||
}
|
||||
((DivPlatformYM2203Ext*)dispatch)->setCSM(1);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2608:
|
||||
dispatch=new DivPlatformYM2608;
|
||||
|
@ -447,6 +477,16 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
|||
} else {
|
||||
((DivPlatformYM2608Ext*)dispatch)->setCombo(eng->getConfInt("opnaCore",1));
|
||||
}
|
||||
((DivPlatformYM2608Ext*)dispatch)->setCSM(0);
|
||||
break;
|
||||
case DIV_SYSTEM_YM2608_CSM:
|
||||
dispatch=new DivPlatformYM2608Ext;
|
||||
if (isRender) {
|
||||
((DivPlatformYM2608Ext*)dispatch)->setCombo(eng->getConfInt("opnaCoreRender",1));
|
||||
} else {
|
||||
((DivPlatformYM2608Ext*)dispatch)->setCombo(eng->getConfInt("opnaCore",1));
|
||||
}
|
||||
((DivPlatformYM2608Ext*)dispatch)->setCSM(1);
|
||||
break;
|
||||
case DIV_SYSTEM_OPLL:
|
||||
case DIV_SYSTEM_OPLL_DRUMS:
|
||||
|
|
|
@ -148,7 +148,7 @@ class DivPlatformOPN: public DivPlatformFMBase {
|
|||
pan(3) {}
|
||||
};
|
||||
|
||||
const int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs, chanNum;
|
||||
int extChanOffs, psgChanOffs, adpcmAChanOffs, adpcmBChanOffs, chanNum; // i really wanted to keep this constant...
|
||||
|
||||
double fmFreqBase;
|
||||
unsigned int fmDivBase;
|
||||
|
|
|
@ -237,8 +237,8 @@ void DivPlatformYM2203::acquire_combo(short** buf, size_t len) {
|
|||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(fm_nuked.ch_out[i]<<1,-32768,32767);
|
||||
}
|
||||
|
||||
for (int i=3; i<6; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2]<<1;
|
||||
for (int i=(3+isCSM); i<(6+isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2+isCSM]<<1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -290,8 +290,8 @@ void DivPlatformYM2203::acquire_ymfm(short** buf, size_t len) {
|
|||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(out,-32768,32767);
|
||||
}
|
||||
|
||||
for (int i=3; i<6; i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2]<<1;
|
||||
for (int i=(3+isCSM); i<(6+isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=fmout.data[i-2+isCSM]<<1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -723,15 +723,29 @@ void DivPlatformYM2203::commitState(int ch, DivInstrument* ins) {
|
|||
}
|
||||
|
||||
int DivPlatformYM2203::dispatch(DivCommand c) {
|
||||
if (c.chan>2) {
|
||||
c.chan-=3;
|
||||
if (c.chan>(2+isCSM)) {
|
||||
c.chan-=(3+isCSM);
|
||||
return ay->dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (c.chan==csmChan && extMode) { // CSM
|
||||
chan[c.chan].macroInit(ins);
|
||||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
break;
|
||||
}
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (c.chan<3) {
|
||||
if (c.chan<psgChanOffs) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
|
@ -801,7 +815,30 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan>2 || parent->song.linearPitch==2) { // PSG
|
||||
if (c.chan==csmChan) {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c.chan>(psgChanOffs-1) || parent->song.linearPitch==2) { // PSG
|
||||
int destFreq=NOTE_FNUM_BLOCK(c.value2,11);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
|
@ -828,6 +865,9 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan==csmChan) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
}
|
||||
if (chan[c.chan].insChanged) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
commitState(c.chan,ins);
|
||||
|
@ -1053,11 +1093,11 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
|||
chan[c.chan].std.restart(c.value);
|
||||
break;
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
if (c.chan>2) return 15;
|
||||
if (c.chan>(2+isCSM)) return 15;
|
||||
return 127;
|
||||
break;
|
||||
case DIV_CMD_PRE_PORTA:
|
||||
if (c.chan>2) {
|
||||
if (c.chan>(2+isCSM)) {
|
||||
if (chan[c.chan].active && c.value2) {
|
||||
if (parent->song.resetMacroOnPorta) chan[c.chan].macroInit(parent->getIns(chan[c.chan].ins,DIV_INS_FM));
|
||||
}
|
||||
|
@ -1075,8 +1115,8 @@ int DivPlatformYM2203::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformYM2203::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
if (ch>2) { // PSG
|
||||
ay->muteChannel(ch-3,mute);
|
||||
if (ch>(2+isCSM)) { // PSG
|
||||
ay->muteChannel(ch-(3+isCSM),mute);
|
||||
return;
|
||||
}
|
||||
for (int j=0; j<4; j++) {
|
||||
|
@ -1121,7 +1161,7 @@ void DivPlatformYM2203::forceIns() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
for (int i=3; i<6; i++) {
|
||||
for (int i=(3+isCSM); i<(6+isCSM); i++) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
||||
|
@ -1139,7 +1179,7 @@ void* DivPlatformYM2203::getChanState(int ch) {
|
|||
}
|
||||
|
||||
DivMacroInt* DivPlatformYM2203::getChanMacroInt(int ch) {
|
||||
if (ch>=3) return ay->getChanMacroInt(ch-3);
|
||||
if (ch>=(3+isCSM)) return ay->getChanMacroInt(ch-(3+isCSM));
|
||||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
|
@ -1173,15 +1213,15 @@ void DivPlatformYM2203::reset() {
|
|||
OPN2_SetChipType(&fm_nuked,ym3438_mode_opn);
|
||||
fm->reset();
|
||||
memset(&fm_lle,0,sizeof(fmopna_t));
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<7; i++) {
|
||||
chan[i]=DivPlatformOPN::OPNChannel();
|
||||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
for (int i=0; i<3; i++) {
|
||||
for (int i=0; i<3; i++) { // check back later / me from future: wha?
|
||||
chan[i].vol=0x7f;
|
||||
chan[i].outVol=0x7f;
|
||||
}
|
||||
for (int i=3; i<6; i++) {
|
||||
for (int i=(3+isCSM); i<(6+isCSM); i++) {
|
||||
chan[i].vol=0x0f;
|
||||
}
|
||||
|
||||
|
@ -1255,7 +1295,7 @@ bool DivPlatformYM2203::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2203::notifyInsChange(int ins) {
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<7; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
@ -1331,7 +1371,7 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) {
|
|||
} else {
|
||||
rate=fm->sample_rate(chipClock);
|
||||
}
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<7; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
immWrite(0x2d,0xff);
|
||||
|
@ -1345,7 +1385,7 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, const DivCo
|
|||
parent=p;
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<7; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
|
@ -1358,11 +1398,11 @@ int DivPlatformYM2203::init(DivEngine* p, int channels, int sugRate, const DivCo
|
|||
setFlags(flags);
|
||||
|
||||
reset();
|
||||
return 6;
|
||||
return 7;
|
||||
}
|
||||
|
||||
void DivPlatformYM2203::quit() {
|
||||
for (int i=0; i<6; i++) {
|
||||
for (int i=0; i<7; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
ay->quit();
|
||||
|
|
|
@ -42,9 +42,9 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
0, 1, 2
|
||||
};
|
||||
|
||||
OPNChannel chan[6];
|
||||
DivDispatchOscBuffer* oscBuf[6];
|
||||
bool isMuted[6];
|
||||
OPNChannel chan[7];
|
||||
DivDispatchOscBuffer* oscBuf[7];
|
||||
bool isMuted[7];
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2203* fm;
|
||||
ymfm::ym2203::output_data fmout;
|
||||
|
@ -73,6 +73,7 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
void acquire_lle(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
bool isCSM;
|
||||
void acquire(short** buf, size_t len);
|
||||
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
@ -98,7 +99,8 @@ class DivPlatformYM2203: public DivPlatformOPN {
|
|||
void quit();
|
||||
DivPlatformYM2203():
|
||||
DivPlatformOPN(2, 3, 6, 6, 6, 4720270.0, 36, 16),
|
||||
prescale(0x2d) {}
|
||||
prescale(0x2d),
|
||||
isCSM(false) {}
|
||||
~DivPlatformYM2203();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -414,6 +414,9 @@ void DivPlatformYM2203Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
@ -565,7 +568,28 @@ void DivPlatformYM2203Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (extMode) {
|
||||
if (chan[csmChan].freqChanged) {
|
||||
chan[csmChan].freq=parent->calcFreq(chan[csmChan].baseFreq,chan[csmChan].pitch,chan[csmChan].fixedArp?chan[csmChan].baseNoteOverride:chan[csmChan].arpOff,chan[csmChan].fixedArp,true,0,chan[csmChan].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[csmChan].freq<1) chan[csmChan].freq=1;
|
||||
if (chan[csmChan].freq>1024) chan[csmChan].freq=1024;
|
||||
int wf=0x400-chan[csmChan].freq;
|
||||
immWrite(0x24,wf>>2);
|
||||
immWrite(0x25,wf&3);
|
||||
chan[csmChan].freqChanged=false;
|
||||
}
|
||||
|
||||
if (chan[csmChan].keyOff || chan[csmChan].keyOn) {
|
||||
writeNoteOn=true;
|
||||
for (int i=0; i<4; i++) {
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
writeMask^=hardResetMask;
|
||||
immWrite(0x28,writeMask);
|
||||
writeMask^=hardResetMask;
|
||||
|
@ -587,6 +611,17 @@ void DivPlatformYM2203Ext::tick(bool sysTick) {
|
|||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (extMode) {
|
||||
if (chan[csmChan].keyOn) {
|
||||
immWrite(0x27,0x81);
|
||||
chan[csmChan].keyOn=false;
|
||||
}
|
||||
if (chan[csmChan].keyOff) {
|
||||
immWrite(0x27,0x40);
|
||||
chan[csmChan].keyOff=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2203Ext::muteChannel(int ch, bool mute) {
|
||||
|
@ -666,6 +701,12 @@ void DivPlatformYM2203Ext::forceIns() {
|
|||
opChan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
|
||||
if (extMode && chan[csmChan].active) { // CSM
|
||||
chan[csmChan].insChanged=true;
|
||||
chan[csmChan].freqChanged=true;
|
||||
chan[csmChan].keyOn=true;
|
||||
}
|
||||
if (!extMode) {
|
||||
immWrite(0x27,0x00);
|
||||
}
|
||||
|
@ -678,7 +719,7 @@ void* DivPlatformYM2203Ext::getChanState(int ch) {
|
|||
}
|
||||
|
||||
DivMacroInt* DivPlatformYM2203Ext::getChanMacroInt(int ch) {
|
||||
if (ch>=6) return ay->getChanMacroInt(ch-6);
|
||||
if (ch>=(6+isCSM)) return ay->getChanMacroInt(ch-(6+isCSM));
|
||||
if (ch>=2) return &opChan[ch-2].std;
|
||||
return &chan[ch].std;
|
||||
}
|
||||
|
@ -738,12 +779,19 @@ int DivPlatformYM2203Ext::init(DivEngine* parent, int channels, int sugRate, con
|
|||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 9;
|
||||
return 3+2+4+isCSM; // 3xPSG + 2xFM + 4xOP + optional CSM
|
||||
}
|
||||
|
||||
void DivPlatformYM2203Ext::quit() {
|
||||
DivPlatformYM2203::quit();
|
||||
}
|
||||
|
||||
void DivPlatformYM2203Ext::setCSM(bool isCSM) {
|
||||
this->isCSM=isCSM;
|
||||
if (isCSM) {
|
||||
csmChan=3;
|
||||
}
|
||||
}
|
||||
|
||||
DivPlatformYM2203Ext::~DivPlatformYM2203Ext() {
|
||||
}
|
||||
|
|
|
@ -44,6 +44,7 @@ class DivPlatformYM2203Ext: public DivPlatformYM2203 {
|
|||
void notifyInsDeletion(void* ins);
|
||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void quit();
|
||||
void setCSM(bool isCSM);
|
||||
~DivPlatformYM2203Ext();
|
||||
};
|
||||
|
||||
|
|
|
@ -480,15 +480,15 @@ void DivPlatformYM2608::acquire_ymfm(short** buf, size_t len) {
|
|||
}
|
||||
|
||||
ssge->get_last_out(ssgOut);
|
||||
for (int i=6; i<9; i++) {
|
||||
for (int i=(6+isCSM); i<(9+isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=ssgOut.data[i-6]<<1;
|
||||
}
|
||||
|
||||
for (int i=9; i<15; i++) {
|
||||
for (int i=(9+isCSM); i<(15+isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=(adpcmAChan[i-9]->get_last_out(0)+adpcmAChan[i-9]->get_last_out(1))>>1;
|
||||
}
|
||||
|
||||
oscBuf[15]->data[oscBuf[15]->needle++]=(abe->get_last_out(0)+abe->get_last_out(1))>>1;
|
||||
oscBuf[15+isCSM]->data[oscBuf[15+isCSM]->needle++]=(abe->get_last_out(0)+abe->get_last_out(1))>>1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -894,7 +894,7 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
|||
}
|
||||
|
||||
// RSS
|
||||
for (int i=9; i<15; i++) {
|
||||
for (int i=(9+isCSM); i<(15+isCSM); i++) {
|
||||
if (chan[i].furnacePCM) {
|
||||
chan[i].std.next();
|
||||
if (chan[i].std.vol.had) {
|
||||
|
@ -916,93 +916,93 @@ void DivPlatformYM2608::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
|
||||
immWrite(0x18+(i-9),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
immWrite(0x18+(i-(9+isCSM)),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
hardResetElapsed++;
|
||||
}
|
||||
}
|
||||
if (chan[i].keyOff) {
|
||||
writeRSSOff|=(1<<(i-9));
|
||||
writeRSSOff|=(1<<(i-(9+isCSM)));
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
writeRSSOn|=(1<<(i-9));
|
||||
writeRSSOn|=(1<<(i-(9+isCSM)));
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
}
|
||||
// ADPCM-B
|
||||
if (chan[15].furnacePCM) {
|
||||
chan[15].std.next();
|
||||
if (chan[(15+isCSM)].furnacePCM) {
|
||||
chan[(15+isCSM)].std.next();
|
||||
|
||||
if (chan[15].std.vol.had) {
|
||||
chan[15].outVol=(chan[15].vol*MIN(chan[15].macroVolMul,chan[15].std.vol.val))/chan[15].macroVolMul;
|
||||
immWrite(0x10b,chan[15].outVol);
|
||||
if (chan[(15+isCSM)].std.vol.had) {
|
||||
chan[(15+isCSM)].outVol=(chan[(15+isCSM)].vol*MIN(chan[(15+isCSM)].macroVolMul,chan[(15+isCSM)].std.vol.val))/chan[(15+isCSM)].macroVolMul;
|
||||
immWrite(0x10b,chan[(15+isCSM)].outVol);
|
||||
hardResetElapsed++;
|
||||
}
|
||||
|
||||
if (NEW_ARP_STRAT) {
|
||||
chan[15].handleArp();
|
||||
} else if (chan[15].std.arp.had) {
|
||||
if (!chan[15].inPorta) {
|
||||
chan[15].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[15].note,chan[15].std.arp.val));
|
||||
chan[(15+isCSM)].handleArp();
|
||||
} else if (chan[(15+isCSM)].std.arp.had) {
|
||||
if (!chan[(15+isCSM)].inPorta) {
|
||||
chan[(15+isCSM)].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[(15+isCSM)].note,chan[(15+isCSM)].std.arp.val));
|
||||
}
|
||||
chan[15].freqChanged=true;
|
||||
chan[(15+isCSM)].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[15].std.pitch.had) {
|
||||
if (chan[15].std.pitch.mode) {
|
||||
chan[15].pitch2+=chan[15].std.pitch.val;
|
||||
CLAMP_VAR(chan[15].pitch2,-65535,65535);
|
||||
if (chan[(15+isCSM)].std.pitch.had) {
|
||||
if (chan[(15+isCSM)].std.pitch.mode) {
|
||||
chan[(15+isCSM)].pitch2+=chan[(15+isCSM)].std.pitch.val;
|
||||
CLAMP_VAR(chan[(15+isCSM)].pitch2,-65535,65535);
|
||||
} else {
|
||||
chan[15].pitch2=chan[15].std.pitch.val;
|
||||
chan[(15+isCSM)].pitch2=chan[(15+isCSM)].std.pitch.val;
|
||||
}
|
||||
chan[15].freqChanged=true;
|
||||
chan[(15+isCSM)].freqChanged=true;
|
||||
}
|
||||
|
||||
if (chan[15].std.panL.had) {
|
||||
if (chan[15].pan!=(chan[15].std.panL.val&3)) {
|
||||
chan[15].pan=chan[15].std.panL.val&3;
|
||||
if (chan[(15+isCSM)].std.panL.had) {
|
||||
if (chan[(15+isCSM)].pan!=(chan[(15+isCSM)].std.panL.val&3)) {
|
||||
chan[(15+isCSM)].pan=chan[(15+isCSM)].std.panL.val&3;
|
||||
if (!isMuted[15]) {
|
||||
immWrite(0x101,(isMuted[15]?0:(chan[15].pan<<6))|1);
|
||||
immWrite(0x101,(isMuted[15]?0:(chan[(15+isCSM)].pan<<6))|1);
|
||||
hardResetElapsed++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[15].std.phaseReset.had) {
|
||||
if ((chan[15].std.phaseReset.val==1) && chan[15].active) {
|
||||
chan[15].keyOn=true;
|
||||
if (chan[(15+isCSM)].std.phaseReset.had) {
|
||||
if ((chan[(15+isCSM)].std.phaseReset.val==1) && chan[(15+isCSM)].active) {
|
||||
chan[(15+isCSM)].keyOn=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[15].freqChanged || chan[15].keyOn || chan[15].keyOff) {
|
||||
if (chan[15].furnacePCM) {
|
||||
if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
|
||||
double off=65535.0*(double)(parent->getSample(chan[15].sample)->centerRate)/8363.0;
|
||||
chan[15].freq=parent->calcFreq(chan[15].baseFreq,chan[15].pitch,chan[15].fixedArp?chan[15].baseNoteOverride:chan[15].arpOff,chan[15].fixedArp,false,4,chan[15].pitch2,(double)chipClock/144,off);
|
||||
if (chan[(15+isCSM)].freqChanged || chan[(15+isCSM)].keyOn || chan[(15+isCSM)].keyOff) {
|
||||
if (chan[(15+isCSM)].furnacePCM) {
|
||||
if (chan[(15+isCSM)].sample>=0 && chan[(15+isCSM)].sample<parent->song.sampleLen) {
|
||||
double off=65535.0*(double)(parent->getSample(chan[(15+isCSM)].sample)->centerRate)/8363.0;
|
||||
chan[(15+isCSM)].freq=parent->calcFreq(chan[(15+isCSM)].baseFreq,chan[(15+isCSM)].pitch,chan[(15+isCSM)].fixedArp?chan[(15+isCSM)].baseNoteOverride:chan[(15+isCSM)].arpOff,chan[(15+isCSM)].fixedArp,false,4,chan[(15+isCSM)].pitch2,(double)chipClock/144,off);
|
||||
} else {
|
||||
chan[15].freq=0;
|
||||
chan[(15+isCSM)].freq=0;
|
||||
}
|
||||
}
|
||||
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
|
||||
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
|
||||
immWrite(0x109,chan[15].freq&0xff);
|
||||
immWrite(0x10a,(chan[15].freq>>8)&0xff);
|
||||
immWrite(0x109,chan[15+isCSM].freq&0xff);
|
||||
immWrite(0x10a,(chan[15+isCSM].freq>>8)&0xff);
|
||||
hardResetElapsed+=2;
|
||||
if (chan[15].keyOn || chan[15].keyOff) {
|
||||
if (chan[15].keyOff) {
|
||||
if (chan[15+isCSM].keyOn || chan[15+isCSM].keyOff) {
|
||||
if (chan[15+isCSM].keyOff) {
|
||||
immWrite(0x100,0x01); // reset
|
||||
hardResetElapsed++;
|
||||
}
|
||||
if (chan[15].active && chan[15].keyOn && !chan[15].keyOff) {
|
||||
if (chan[15].sample>=0 && chan[15].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[15].sample);
|
||||
if (chan[15+isCSM].active && chan[15+isCSM].keyOn && !chan[15+isCSM].keyOff) {
|
||||
if (chan[15+isCSM].sample>=0 && chan[15+isCSM].sample<parent->song.sampleLen) {
|
||||
DivSample* s=parent->getSample(chan[15+isCSM].sample);
|
||||
immWrite(0x100,(s->isLoopable())?0xb0:0xa0); // start/repeat
|
||||
hardResetElapsed++;
|
||||
}
|
||||
}
|
||||
chan[15].keyOn=false;
|
||||
chan[15].keyOff=false;
|
||||
chan[15+isCSM].keyOn=false;
|
||||
chan[15+isCSM].keyOff=false;
|
||||
}
|
||||
chan[15].freqChanged=false;
|
||||
chan[15+isCSM].freqChanged=false;
|
||||
}
|
||||
|
||||
if (writeRSSOff) {
|
||||
|
@ -1094,13 +1094,13 @@ void DivPlatformYM2608::commitState(int ch, DivInstrument* ins) {
|
|||
}
|
||||
|
||||
int DivPlatformYM2608::dispatch(DivCommand c) {
|
||||
if (c.chan>5 && c.chan<9) {
|
||||
c.chan-=6;
|
||||
if (c.chan>(5+isCSM) && c.chan<(9+isCSM)) {
|
||||
c.chan-=(6+isCSM);
|
||||
return ay->dispatch(c);
|
||||
}
|
||||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>14) { // ADPCM-B
|
||||
if (c.chan>(14+isCSM)) { // ADPCM-B
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
chan[c.chan].macroVolMul=(ins->type==DIV_INS_AMIGA)?64:255;
|
||||
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ADPCMB) {
|
||||
|
@ -1179,7 +1179,7 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
}
|
||||
break;
|
||||
}
|
||||
if (c.chan>8) { // RSS
|
||||
if (c.chan>(8+isCSM)) { // RSS
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
chan[c.chan].macroVolMul=(ins->type==DIV_INS_AMIGA)?64:31;
|
||||
if (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ADPCMA) {
|
||||
|
@ -1192,18 +1192,32 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
chan[c.chan].macroInit(ins);
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
immWrite(0x18+(c.chan-(9+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].macroInit(NULL);
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
immWrite(0x18+(c.chan-(9+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
}
|
||||
chan[c.chan].active=true;
|
||||
chan[c.chan].keyOn=true;
|
||||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (c.chan==csmChan && extMode) { // CSM
|
||||
chan[c.chan].macroInit(ins);
|
||||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
break;
|
||||
}
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (c.chan<6) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
|
@ -1244,12 +1258,12 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
if (!chan[c.chan].std.vol.has) {
|
||||
chan[c.chan].outVol=c.value;
|
||||
}
|
||||
if (c.chan>14) { // ADPCM-B
|
||||
if (c.chan>(14+isCSM)) { // ADPCM-B
|
||||
immWrite(0x10b,chan[c.chan].outVol);
|
||||
break;
|
||||
}
|
||||
if (c.chan>8) { // ADPCM-A
|
||||
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
if (c.chan>(8+isCSM)) { // ADPCM-A
|
||||
immWrite(0x18+(c.chan-(9+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
break;
|
||||
}
|
||||
for (int i=0; i<4; i++) {
|
||||
|
@ -1290,25 +1304,48 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
} else {
|
||||
chan[c.chan].pan=(c.value2>0)|((c.value>0)<<1);
|
||||
}
|
||||
if (c.chan>14) {
|
||||
if (c.chan>(14+isCSM)) {
|
||||
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|1);
|
||||
break;
|
||||
}
|
||||
if (c.chan>8) {
|
||||
immWrite(0x18+(c.chan-9),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
immWrite(0x18+(c.chan-(9+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
|
||||
break;
|
||||
}
|
||||
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));
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_PITCH: {
|
||||
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||
if (c.chan==(15+isCSM) && !chan[c.chan].furnacePCM) break;
|
||||
chan[c.chan].pitch=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan>5 || parent->song.linearPitch==2) { // PSG, ADPCM-B
|
||||
if (c.chan==csmChan) {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c.chan>(5+isCSM) || parent->song.linearPitch==2) { // PSG, ADPCM-B
|
||||
int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
|
@ -1342,7 +1379,10 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
iface.sampleBank=sampleBank;
|
||||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan==15 && !chan[c.chan].furnacePCM) break;
|
||||
if (c.chan==csmChan) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
}
|
||||
if (c.chan==(15+isCSM) && !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);
|
||||
|
@ -1576,8 +1616,8 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
chan[c.chan].std.restart(c.value);
|
||||
break;
|
||||
case DIV_CMD_GET_VOLMAX:
|
||||
if (c.chan>14) return 255;
|
||||
if (c.chan>8) return 31;
|
||||
if (c.chan>(14+isCSM)) return 255;
|
||||
if (c.chan>(8+isCSM)) return 31;
|
||||
if (c.chan>5) return 15;
|
||||
return 127;
|
||||
break;
|
||||
|
@ -1600,10 +1640,10 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformYM2608::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
if (ch>14) { // ADPCM-B
|
||||
if (ch>(14+isCSM)) { // ADPCM-B
|
||||
immWrite(0x101,(isMuted[ch]?0:(chan[ch].pan<<6))|1);
|
||||
}
|
||||
if (ch>8) { // ADPCM-A
|
||||
if (ch>(8+isCSM)) { // ADPCM-A
|
||||
immWrite(0x18+(ch-9),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].outVol));
|
||||
return;
|
||||
}
|
||||
|
@ -1658,12 +1698,12 @@ void DivPlatformYM2608::forceIns() {
|
|||
}
|
||||
immWrite(0x11,globalRSSVolume&0x3f);
|
||||
immWrite(0x22,lfoValue);
|
||||
for (int i=9; i<16; i++) {
|
||||
for (int i=(+isCSM); i<(16+isCSM); i++) {
|
||||
chan[i].insChanged=true;
|
||||
if (i>14) { // ADPCM-B
|
||||
if (i>(14+isCSM)) { // ADPCM-B
|
||||
immWrite(0x10b,chan[i].outVol);
|
||||
} else {
|
||||
immWrite(0x18+(i-9),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
immWrite(0x18+(i-(9+isCSM)),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1681,7 +1721,7 @@ void* DivPlatformYM2608::getChanState(int ch) {
|
|||
}
|
||||
|
||||
DivMacroInt* DivPlatformYM2608::getChanMacroInt(int ch) {
|
||||
if (ch>=6 && ch<9) return ay->getChanMacroInt(ch-6);
|
||||
if (ch>=(6+isCSM) && ch<(9+isCSM)) return ay->getChanMacroInt(ch-6);
|
||||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
|
@ -1728,10 +1768,10 @@ void DivPlatformYM2608::reset() {
|
|||
chan[i].vol=0x7f;
|
||||
chan[i].outVol=0x7f;
|
||||
}
|
||||
for (int i=6; i<9; i++) {
|
||||
for (int i=(6+isCSM); i<(9+isCSM); i++) {
|
||||
chan[i].vol=0x0f;
|
||||
}
|
||||
for (int i=9; i<15; i++) {
|
||||
for (int i=(9+isCSM); i<(15+isCSM); i++) {
|
||||
chan[i].vol=0x1f;
|
||||
}
|
||||
chan[15].vol=0xff;
|
||||
|
@ -1833,7 +1873,7 @@ bool DivPlatformYM2608::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2608::notifyInsChange(int ins) {
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<(16+isCSM); i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
@ -1964,7 +2004,7 @@ void DivPlatformYM2608::setFlags(const DivConfig& flags) {
|
|||
} else {
|
||||
rate=fm->sample_rate(chipClock);
|
||||
}
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<(16+isCSM); i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
immWrite(0x2d,0xff);
|
||||
|
@ -1984,7 +2024,7 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, const DivCo
|
|||
iface.sampleBank=0;
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<16+isCSM; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
|
@ -1996,11 +2036,20 @@ int DivPlatformYM2608::init(DivEngine* p, int channels, int sugRate, const DivCo
|
|||
ay->toggleRegisterDump(true);
|
||||
setFlags(flags);
|
||||
reset();
|
||||
return 16;
|
||||
return 17;
|
||||
}
|
||||
|
||||
void DivPlatformYM2608::setCSM(bool isCSM) {
|
||||
this->isCSM=isCSM;
|
||||
if (isCSM) {
|
||||
csmChan=6;
|
||||
} else {
|
||||
csmChan=16; // me from the furute: ???
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2608::quit() {
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
ay->quit();
|
||||
|
|
|
@ -47,9 +47,9 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
0, 1, 2, 4, 5, 6
|
||||
};
|
||||
|
||||
OPNChannelStereo chan[16];
|
||||
DivDispatchOscBuffer* oscBuf[16];
|
||||
bool isMuted[16];
|
||||
OPNChannelStereo chan[17];
|
||||
DivDispatchOscBuffer* oscBuf[17];
|
||||
bool isMuted[17];
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2608* fm;
|
||||
ymfm::ym2608::output_data fmout;
|
||||
|
@ -92,6 +92,7 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
void acquire_lle(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
bool isCSM;
|
||||
void acquire(short** buf, size_t len);
|
||||
void fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
|
@ -121,10 +122,12 @@ class DivPlatformYM2608: public DivPlatformOPN {
|
|||
void renderSamples(int chipID);
|
||||
void setFlags(const DivConfig& flags);
|
||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void setCSM(bool isCSM);
|
||||
void quit();
|
||||
DivPlatformYM2608():
|
||||
DivPlatformOPN(2, 6, 9, 15, 16, 9440540.0, 72, 32),
|
||||
prescale(0x2d) {}
|
||||
prescale(0x2d),
|
||||
isCSM(false) {}
|
||||
~DivPlatformYM2608();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -438,6 +438,9 @@ void DivPlatformYM2608Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
@ -612,7 +615,28 @@ void DivPlatformYM2608Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (extMode) {
|
||||
if (chan[csmChan].freqChanged) {
|
||||
chan[csmChan].freq=parent->calcFreq(chan[csmChan].baseFreq,chan[csmChan].pitch,chan[csmChan].fixedArp?chan[csmChan].baseNoteOverride:chan[csmChan].arpOff,chan[csmChan].fixedArp,true,0,chan[csmChan].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[csmChan].freq<1) chan[csmChan].freq=1;
|
||||
if (chan[csmChan].freq>1024) chan[csmChan].freq=1024;
|
||||
int wf=0x400-chan[csmChan].freq;
|
||||
immWrite(0x24,wf>>2);
|
||||
immWrite(0x25,wf&3);
|
||||
chan[csmChan].freqChanged=false;
|
||||
}
|
||||
|
||||
if (chan[csmChan].keyOff || chan[csmChan].keyOn) {
|
||||
writeNoteOn=true;
|
||||
for (int i=0; i<4; i++) {
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
writeMask^=hardResetMask;
|
||||
immWrite(0x28,writeMask);
|
||||
writeMask^=hardResetMask;
|
||||
|
@ -634,6 +658,17 @@ void DivPlatformYM2608Ext::tick(bool sysTick) {
|
|||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (extMode) {
|
||||
if (chan[csmChan].keyOn) {
|
||||
immWrite(0x27,0x81);
|
||||
chan[csmChan].keyOn=false;
|
||||
}
|
||||
if (chan[csmChan].keyOff) {
|
||||
immWrite(0x27,0x40);
|
||||
chan[csmChan].keyOff=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2608Ext::muteChannel(int ch, bool mute) {
|
||||
|
@ -705,12 +740,12 @@ void DivPlatformYM2608Ext::forceIns() {
|
|||
chan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
for (int i=9; i<16; i++) {
|
||||
for (int i=(9+isCSM); i<(16+isCSM); i++) {
|
||||
chan[i].insChanged=true;
|
||||
if (i>14) { // ADPCM-B
|
||||
if (i>(14+isCSM)) { // ADPCM-B
|
||||
immWrite(0x10b,chan[i].outVol);
|
||||
} else {
|
||||
immWrite(0x18+(i-9),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
immWrite(0x18+(i-(9+isCSM)),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
|
||||
}
|
||||
}
|
||||
ay->forceIns();
|
||||
|
@ -728,6 +763,11 @@ void DivPlatformYM2608Ext::forceIns() {
|
|||
opChan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (extMode && chan[csmChan].active) { // CSM
|
||||
chan[csmChan].insChanged=true;
|
||||
chan[csmChan].freqChanged=true;
|
||||
chan[csmChan].keyOn=true;
|
||||
}
|
||||
if (!extMode) {
|
||||
immWrite(0x27,0x00);
|
||||
}
|
||||
|
@ -740,13 +780,14 @@ void* DivPlatformYM2608Ext::getChanState(int ch) {
|
|||
}
|
||||
|
||||
DivMacroInt* DivPlatformYM2608Ext::getChanMacroInt(int ch) {
|
||||
if (ch>=9 && ch<12) return ay->getChanMacroInt(ch-9);
|
||||
if (ch>=(9+isCSM) && ch<(12+isCSM)) return ay->getChanMacroInt(ch-(9+isCSM));
|
||||
if (ch>=6) return &chan[ch-3].std;
|
||||
if (ch>=2) return &opChan[ch-2].std;
|
||||
return &chan[ch].std;
|
||||
}
|
||||
|
||||
unsigned short DivPlatformYM2608Ext::getPan(int ch) {
|
||||
if (ch==4+csmChan) return 0;
|
||||
if (ch>=4+extChanOffs) return DivPlatformYM2608::getPan(ch-3);
|
||||
if (ch>=extChanOffs) {
|
||||
if (extMode) {
|
||||
|
@ -788,7 +829,7 @@ void DivPlatformYM2608Ext::reset() {
|
|||
}
|
||||
|
||||
bool DivPlatformYM2608Ext::keyOffAffectsArp(int ch) {
|
||||
return (ch>8);
|
||||
return (ch>(8+isCSM));
|
||||
}
|
||||
|
||||
void DivPlatformYM2608Ext::notifyInsChange(int ins) {
|
||||
|
@ -815,7 +856,7 @@ int DivPlatformYM2608Ext::init(DivEngine* parent, int channels, int sugRate, con
|
|||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 19;
|
||||
return 19+isCSM;
|
||||
}
|
||||
|
||||
void DivPlatformYM2608Ext::quit() {
|
||||
|
|
|
@ -335,7 +335,7 @@ void DivPlatformYM2610::acquire_combo(short** buf, size_t len) {
|
|||
buf[1][h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(fm_nuked.ch_out[bchOffs[i]]<<1,-32768,32767);
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ void DivPlatformYM2610::acquire_ymfm(short** buf, size_t len) {
|
|||
buf[0][h]=os[0];
|
||||
buf[1][h]=os[1];
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
int out=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1))<<1;
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(out,-32768,32767);
|
||||
}
|
||||
|
@ -615,7 +615,7 @@ void DivPlatformYM2610::acquire_lle(short** buf, size_t len) {
|
|||
|
||||
void DivPlatformYM2610::tick(bool sysTick) {
|
||||
// FM
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==1 && extMode) continue;
|
||||
chan[i].std.next();
|
||||
|
||||
|
@ -772,7 +772,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
|||
int hardResetElapsed=0;
|
||||
bool mustHardReset=false;
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==1 && extMode) continue;
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
immWrite(0x28,0x00|konOffs[i]);
|
||||
|
@ -788,7 +788,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==1 && extMode) continue;
|
||||
if (chan[i].freqChanged) {
|
||||
if (parent->song.linearPitch==2) {
|
||||
|
@ -959,7 +959,7 @@ void DivPlatformYM2610::tick(bool sysTick) {
|
|||
for (unsigned int i=hardResetElapsed; i<hardResetCycles; i++) {
|
||||
immWrite(0xf0,i&0xff);
|
||||
}
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==1 && extMode) continue;
|
||||
if ((chan[i].keyOn || chan[i].opMaskChanged) && chan[i].hardReset) {
|
||||
// restore SL/RR
|
||||
|
@ -1170,8 +1170,22 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (c.chan==csmChan && extMode) { // CSM
|
||||
chan[c.chan].macroInit(ins);
|
||||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
break;
|
||||
}
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (c.chan<psgChanOffs) {
|
||||
if (c.chan<(psgChanOffs-isCSM)) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
chan[c.chan].outVol=chan[c.chan].vol;
|
||||
}
|
||||
|
@ -1274,6 +1288,29 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan==csmChan) {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c.chan>=psgChanOffs || parent->song.linearPitch==2) { // PSG, ADPCM-B
|
||||
int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
|
||||
bool return2=false;
|
||||
|
@ -1309,6 +1346,9 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
||||
if (c.chan==csmChan) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
}
|
||||
if (c.chan<=psgChanOffs) {
|
||||
if (chan[c.chan].insChanged) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
|
@ -1588,7 +1628,7 @@ void DivPlatformYM2610::muteChannel(int ch, bool mute) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610::forceIns() {
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
for (int j=0; j<4; j++) {
|
||||
unsigned short baseAddr=chanOffs[i]|opOffs[j];
|
||||
DivInstrumentFM::Operator& op=chan[i].state.op[j];
|
||||
|
@ -1671,11 +1711,11 @@ void DivPlatformYM2610::reset() {
|
|||
addWrite(0xffffffff,0);
|
||||
}
|
||||
fm->reset();
|
||||
for (int i=0; i<14; i++) {
|
||||
for (int i=0; i<15; i++) {
|
||||
chan[i]=DivPlatformOPN::OPNChannelStereo();
|
||||
chan[i].std.setEngine(parent);
|
||||
}
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
chan[i].vol=0x7f;
|
||||
chan[i].outVol=0x7f;
|
||||
}
|
||||
|
@ -1721,7 +1761,7 @@ bool DivPlatformYM2610::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610::notifyInsChange(int ins) {
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
@ -1731,7 +1771,7 @@ void DivPlatformYM2610::notifyInsChange(int ins) {
|
|||
|
||||
void DivPlatformYM2610::notifyInsDeletion(void* ins) {
|
||||
ay->notifyInsDeletion(ins);
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||
}
|
||||
for (int i=adpcmAChanOffs; i<chanNum; i++) {
|
||||
|
@ -1747,7 +1787,20 @@ void DivPlatformYM2610::setSkipRegisterWrites(bool value) {
|
|||
int DivPlatformYM2610::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
DivPlatformYM2610Base::init(p, channels, sugRate, flags);
|
||||
reset();
|
||||
return 14;
|
||||
return 15;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::setCSM(bool isCSM) {
|
||||
this->isCSM=isCSM;
|
||||
psgChanOffs=4+isCSM; // doing this hurts me...
|
||||
adpcmAChanOffs=7+isCSM;
|
||||
adpcmBChanOffs=13+isCSM;
|
||||
chanNum=14+isCSM;
|
||||
if (isCSM) {
|
||||
csmChan=4;
|
||||
} else {
|
||||
csmChan=14;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::quit() {
|
||||
|
|
|
@ -45,6 +45,7 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
|||
void acquire_lle(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
bool isCSM;
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
|
@ -66,9 +67,11 @@ class DivPlatformYM2610: public DivPlatformYM2610Base {
|
|||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
const char** getRegisterSheet();
|
||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void setCSM(bool isCSM);
|
||||
void quit();
|
||||
DivPlatformYM2610():
|
||||
DivPlatformYM2610Base(1,4,7,13,14) {}
|
||||
DivPlatformYM2610Base(1,4,7,13,14),
|
||||
isCSM(false) {}
|
||||
~DivPlatformYM2610();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -403,7 +403,7 @@ void DivPlatformYM2610B::acquire_combo(short** buf, size_t len) {
|
|||
buf[1][h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(fm_nuked.ch_out[i]<<1,-32768,32767);
|
||||
}
|
||||
|
||||
|
@ -474,7 +474,7 @@ void DivPlatformYM2610B::acquire_ymfm(short** buf, size_t len) {
|
|||
buf[1][h]=os[1];
|
||||
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
int out=(fmChan[i]->debug_output(0)+fmChan[i]->debug_output(1))<<1;
|
||||
oscBuf[i]->data[oscBuf[i]->needle++]=CLAMP(out,-32768,32767);
|
||||
}
|
||||
|
@ -684,7 +684,7 @@ void DivPlatformYM2610B::acquire_lle(short** buf, size_t len) {
|
|||
|
||||
void DivPlatformYM2610B::tick(bool sysTick) {
|
||||
// FM
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
chan[i].std.next();
|
||||
|
||||
|
@ -841,7 +841,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
|||
int hardResetElapsed=0;
|
||||
bool mustHardReset=false;
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
immWrite(0x28,0x00|konOffs[i]);
|
||||
|
@ -857,7 +857,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
if (chan[i].freqChanged) {
|
||||
if (parent->song.linearPitch==2) {
|
||||
|
@ -1028,7 +1028,7 @@ void DivPlatformYM2610B::tick(bool sysTick) {
|
|||
for (unsigned int i=hardResetElapsed; i<hardResetCycles; i++) {
|
||||
immWrite(0xf0,i&0xff);
|
||||
}
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
if ((chan[i].keyOn || chan[i].opMaskChanged) && chan[i].hardReset) {
|
||||
// restore SL/RR
|
||||
|
@ -1239,6 +1239,20 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
if (c.chan==csmChan && extMode) { // CSM
|
||||
chan[c.chan].macroInit(ins);
|
||||
chan[c.chan].insChanged=false;
|
||||
|
||||
if (c.value!=DIV_NOTE_NULL) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
chan[c.chan].portaPause=false;
|
||||
chan[c.chan].note=c.value;
|
||||
chan[c.chan].freqChanged=true;
|
||||
}
|
||||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].active=true;
|
||||
break;
|
||||
}
|
||||
chan[c.chan].macroInit(ins);
|
||||
if (c.chan<6) {
|
||||
if (!chan[c.chan].std.vol.will) {
|
||||
|
@ -1343,6 +1357,29 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
case DIV_CMD_NOTE_PORTA: {
|
||||
if (c.chan==csmChan) {
|
||||
int destFreq=NOTE_PERIODIC(c.value2);
|
||||
bool return2=false;
|
||||
if (destFreq>chan[c.chan].baseFreq) {
|
||||
chan[c.chan].baseFreq+=c.value;
|
||||
if (chan[c.chan].baseFreq>=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
} else {
|
||||
chan[c.chan].baseFreq-=c.value;
|
||||
if (chan[c.chan].baseFreq<=destFreq) {
|
||||
chan[c.chan].baseFreq=destFreq;
|
||||
return2=true;
|
||||
}
|
||||
}
|
||||
chan[c.chan].freqChanged=true;
|
||||
if (return2) {
|
||||
chan[c.chan].inPorta=false;
|
||||
return 2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (c.chan>=psgChanOffs || parent->song.linearPitch==2) { // PSG, ADPCM-B
|
||||
int destFreq=NOTE_OPNB(c.chan,c.value2+chan[c.chan].sampleNoteDelta);
|
||||
bool return2=false;
|
||||
|
@ -1378,7 +1415,10 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_LEGATO: {
|
||||
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
|
||||
if (c.chan<=psgChanOffs) {
|
||||
if (c.chan==csmChan) {
|
||||
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
|
||||
}
|
||||
if (c.chan<=(psgChanOffs-isCSM)) {
|
||||
if (chan[c.chan].insChanged) {
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
|
||||
commitState(c.chan,ins);
|
||||
|
@ -1794,7 +1834,7 @@ bool DivPlatformYM2610B::keyOffAffectsArp(int ch) {
|
|||
}
|
||||
|
||||
void DivPlatformYM2610B::notifyInsChange(int ins) {
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
if (chan[i].ins==ins) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
|
@ -1804,7 +1844,7 @@ void DivPlatformYM2610B::notifyInsChange(int ins) {
|
|||
|
||||
void DivPlatformYM2610B::notifyInsDeletion(void* ins) {
|
||||
ay->notifyInsDeletion(ins);
|
||||
for (int i=0; i<psgChanOffs; i++) {
|
||||
for (int i=0; i<(psgChanOffs-isCSM); i++) {
|
||||
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||
}
|
||||
for (int i=adpcmAChanOffs; i<chanNum; i++) {
|
||||
|
@ -1820,7 +1860,20 @@ void DivPlatformYM2610B::setSkipRegisterWrites(bool value) {
|
|||
int DivPlatformYM2610B::init(DivEngine* p, int channels, int sugRate, const DivConfig& flags) {
|
||||
DivPlatformYM2610Base::init(p, channels, sugRate, flags);
|
||||
reset();
|
||||
return 16;
|
||||
return 17;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::setCSM(bool isCSM) {
|
||||
this->isCSM=isCSM;
|
||||
psgChanOffs=6+isCSM; // doing this hurts me...
|
||||
adpcmAChanOffs=9+isCSM;
|
||||
adpcmBChanOffs=15+isCSM;
|
||||
chanNum=16+isCSM;
|
||||
if (isCSM) {
|
||||
csmChan=6;
|
||||
} else {
|
||||
csmChan=16;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610B::quit() {
|
||||
|
|
|
@ -41,6 +41,7 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
|||
void acquire_lle(short** buf, size_t len);
|
||||
|
||||
public:
|
||||
bool isCSM;
|
||||
void acquire(short** buf, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void* getChanState(int chan);
|
||||
|
@ -62,9 +63,11 @@ class DivPlatformYM2610B: public DivPlatformYM2610Base {
|
|||
void poke(std::vector<DivRegWrite>& wlist);
|
||||
const char** getRegisterSheet();
|
||||
int init(DivEngine* parent, int channels, int sugRate, const DivConfig& flags);
|
||||
void setCSM(bool isCSM);
|
||||
void quit();
|
||||
DivPlatformYM2610B():
|
||||
DivPlatformYM2610Base(2,6,9,15,16) {}
|
||||
DivPlatformYM2610Base(2,6,9,15,16),
|
||||
isCSM(false) {}
|
||||
~DivPlatformYM2610B();
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -434,6 +434,9 @@ void DivPlatformYM2610BExt::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
@ -607,7 +610,28 @@ void DivPlatformYM2610BExt::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (extMode) {
|
||||
if (chan[csmChan].freqChanged) {
|
||||
chan[csmChan].freq=parent->calcFreq(chan[csmChan].baseFreq,chan[csmChan].pitch,chan[csmChan].fixedArp?chan[csmChan].baseNoteOverride:chan[csmChan].arpOff,chan[csmChan].fixedArp,true,0,chan[csmChan].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[csmChan].freq<1) chan[csmChan].freq=1;
|
||||
if (chan[csmChan].freq>1024) chan[csmChan].freq=1024;
|
||||
int wf=0x400-chan[csmChan].freq;
|
||||
immWrite(0x24,wf>>2);
|
||||
immWrite(0x25,wf&3);
|
||||
chan[csmChan].freqChanged=false;
|
||||
}
|
||||
|
||||
if (chan[csmChan].keyOff || chan[csmChan].keyOn) {
|
||||
writeNoteOn=true;
|
||||
for (int i=0; i<4; i++) {
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
writeMask^=hardResetMask;
|
||||
immWrite(0x28,writeMask);
|
||||
writeMask^=hardResetMask;
|
||||
|
@ -629,6 +653,17 @@ void DivPlatformYM2610BExt::tick(bool sysTick) {
|
|||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
if (extMode) {
|
||||
if (chan[csmChan].keyOn) {
|
||||
immWrite(0x27,0x81);
|
||||
chan[csmChan].keyOn=false;
|
||||
}
|
||||
if (chan[csmChan].keyOff) {
|
||||
immWrite(0x27,0x40);
|
||||
chan[csmChan].keyOff=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610BExt::muteChannel(int ch, bool mute) {
|
||||
|
@ -718,6 +753,11 @@ void DivPlatformYM2610BExt::forceIns() {
|
|||
opChan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (extMode && chan[csmChan].active) { // CSM
|
||||
chan[csmChan].insChanged=true;
|
||||
chan[csmChan].freqChanged=true;
|
||||
chan[csmChan].keyOn=true;
|
||||
}
|
||||
if (!extMode) {
|
||||
immWrite(0x27,0x00);
|
||||
}
|
||||
|
@ -737,6 +777,7 @@ DivMacroInt* DivPlatformYM2610BExt::getChanMacroInt(int ch) {
|
|||
}
|
||||
|
||||
unsigned short DivPlatformYM2610BExt::getPan(int ch) {
|
||||
if (ch==4+csmChan) return 0;
|
||||
if (ch>=4+extChanOffs) return DivPlatformYM2610B::getPan(ch-3);
|
||||
if (ch>=extChanOffs) {
|
||||
if (extMode) {
|
||||
|
@ -805,7 +846,7 @@ int DivPlatformYM2610BExt::init(DivEngine* parent, int channels, int sugRate, co
|
|||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 19;
|
||||
return 20;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610BExt::quit() {
|
||||
|
|
|
@ -434,6 +434,9 @@ void DivPlatformYM2610Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
@ -607,7 +610,28 @@ void DivPlatformYM2610Ext::tick(bool sysTick) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (extMode) {
|
||||
if (chan[csmChan].freqChanged) {
|
||||
chan[csmChan].freq=parent->calcFreq(chan[csmChan].baseFreq,chan[csmChan].pitch,chan[csmChan].fixedArp?chan[csmChan].baseNoteOverride:chan[csmChan].arpOff,chan[csmChan].fixedArp,true,0,chan[csmChan].pitch2,chipClock,CHIP_DIVIDER);
|
||||
if (chan[csmChan].freq<1) chan[csmChan].freq=1;
|
||||
if (chan[csmChan].freq>1024) chan[csmChan].freq=1024;
|
||||
int wf=0x400-chan[csmChan].freq;
|
||||
immWrite(0x24,wf>>2);
|
||||
immWrite(0x25,wf&3);
|
||||
chan[csmChan].freqChanged=false;
|
||||
}
|
||||
|
||||
if (chan[csmChan].keyOff || chan[csmChan].keyOn) {
|
||||
writeNoteOn=true;
|
||||
for (int i=0; i<4; i++) {
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
if (chan[csmChan].active) { // CSM
|
||||
writeMask^=0xf0;
|
||||
}
|
||||
writeMask^=hardResetMask;
|
||||
immWrite(0x28,writeMask);
|
||||
writeMask^=hardResetMask;
|
||||
|
@ -629,6 +653,16 @@ void DivPlatformYM2610Ext::tick(bool sysTick) {
|
|||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
if (extMode) {
|
||||
if (chan[csmChan].keyOn) {
|
||||
immWrite(0x27,0x81);
|
||||
chan[csmChan].keyOn=false;
|
||||
}
|
||||
if (chan[csmChan].keyOff) {
|
||||
immWrite(0x27,0x40);
|
||||
chan[csmChan].keyOff=false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::muteChannel(int ch, bool mute) {
|
||||
|
@ -718,6 +752,11 @@ void DivPlatformYM2610Ext::forceIns() {
|
|||
opChan[i].freqChanged=true;
|
||||
}
|
||||
}
|
||||
if (extMode && chan[csmChan].active) { // CSM
|
||||
chan[csmChan].insChanged=true;
|
||||
chan[csmChan].freqChanged=true;
|
||||
chan[csmChan].keyOn=true;
|
||||
}
|
||||
if (!extMode) {
|
||||
immWrite(0x27,0x00);
|
||||
}
|
||||
|
@ -737,6 +776,7 @@ DivMacroInt* DivPlatformYM2610Ext::getChanMacroInt(int ch) {
|
|||
}
|
||||
|
||||
unsigned short DivPlatformYM2610Ext::getPan(int ch) {
|
||||
if (ch==4+csmChan) return 0;
|
||||
if (ch>=4+extChanOffs) return DivPlatformYM2610::getPan(ch-3);
|
||||
if (ch>=extChanOffs) {
|
||||
if (extMode) {
|
||||
|
@ -805,7 +845,7 @@ int DivPlatformYM2610Ext::init(DivEngine* parent, int channels, int sugRate, con
|
|||
extSys=true;
|
||||
|
||||
reset();
|
||||
return 17;
|
||||
return 17+isCSM;
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::quit() {
|
||||
|
|
|
@ -49,9 +49,9 @@ class DivYM2610Interface: public ymfm::ymfm_interface {
|
|||
|
||||
class DivPlatformYM2610Base: public DivPlatformOPN {
|
||||
protected:
|
||||
OPNChannelStereo chan[16];
|
||||
DivDispatchOscBuffer* oscBuf[16];
|
||||
bool isMuted[16];
|
||||
OPNChannelStereo chan[17];
|
||||
DivDispatchOscBuffer* oscBuf[17];
|
||||
bool isMuted[17];
|
||||
|
||||
ym3438_t fm_nuked;
|
||||
ymfm::ym2610b* fm;
|
||||
|
@ -322,7 +322,7 @@ class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
} else {
|
||||
rate=fm->sample_rate(chipClock);
|
||||
}
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
oscBuf[i]->rate=rate;
|
||||
}
|
||||
}
|
||||
|
@ -332,7 +332,7 @@ class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
ayFlags.set("chipType",1);
|
||||
dumpWrites=false;
|
||||
skipRegisterWrites=false;
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
isMuted[i]=false;
|
||||
oscBuf[i]=new DivDispatchOscBuffer;
|
||||
}
|
||||
|
@ -354,7 +354,7 @@ class DivPlatformYM2610Base: public DivPlatformOPN {
|
|||
}
|
||||
|
||||
void quit() {
|
||||
for (int i=0; i<16; i++) {
|
||||
for (int i=0; i<17; i++) {
|
||||
delete oscBuf[i];
|
||||
}
|
||||
ay->quit();
|
||||
|
|
|
@ -1218,8 +1218,10 @@ const int availableSystems[]={
|
|||
DIV_SYSTEM_YM2610_EXT,
|
||||
DIV_SYSTEM_YM2610_FULL,
|
||||
DIV_SYSTEM_YM2610_FULL_EXT,
|
||||
DIV_SYSTEM_YM2610_CSM,
|
||||
DIV_SYSTEM_YM2610B,
|
||||
DIV_SYSTEM_YM2610B_EXT,
|
||||
DIV_SYSTEM_YM2610B_CSM,
|
||||
DIV_SYSTEM_T6W28,
|
||||
DIV_SYSTEM_AY8910,
|
||||
DIV_SYSTEM_AMIGA,
|
||||
|
@ -1232,8 +1234,10 @@ const int availableSystems[]={
|
|||
DIV_SYSTEM_SOUND_UNIT,
|
||||
DIV_SYSTEM_YM2203,
|
||||
DIV_SYSTEM_YM2203_EXT,
|
||||
DIV_SYSTEM_YM2203_CSM,
|
||||
DIV_SYSTEM_YM2608,
|
||||
DIV_SYSTEM_YM2608_EXT,
|
||||
DIV_SYSTEM_YM2608_CSM,
|
||||
DIV_SYSTEM_OPLL,
|
||||
DIV_SYSTEM_OPLL_DRUMS,
|
||||
DIV_SYSTEM_VRC7,
|
||||
|
@ -1314,13 +1318,17 @@ const int chipsFM[]={
|
|||
DIV_SYSTEM_YM2610_EXT,
|
||||
DIV_SYSTEM_YM2610_FULL,
|
||||
DIV_SYSTEM_YM2610_FULL_EXT,
|
||||
DIV_SYSTEM_YM2610_CSM,
|
||||
DIV_SYSTEM_YM2610B,
|
||||
DIV_SYSTEM_YM2610B_EXT,
|
||||
DIV_SYSTEM_YM2610B_CSM,
|
||||
DIV_SYSTEM_YMU759,
|
||||
DIV_SYSTEM_YM2203,
|
||||
DIV_SYSTEM_YM2203_EXT,
|
||||
DIV_SYSTEM_YM2203_CSM,
|
||||
DIV_SYSTEM_YM2608,
|
||||
DIV_SYSTEM_YM2608_EXT,
|
||||
DIV_SYSTEM_YM2608_CSM,
|
||||
DIV_SYSTEM_OPLL,
|
||||
DIV_SYSTEM_OPLL_DRUMS,
|
||||
DIV_SYSTEM_VRC7,
|
||||
|
|
Loading…
Reference in a new issue