total extinction of legacy sample mode, part 3

remove all the code which handles legacy sample mode
next up is a conversion strategy
This commit is contained in:
tildearrow 2025-11-08 20:05:52 -05:00
parent aa8054754c
commit 183526cdbd
21 changed files with 706 additions and 870 deletions

View file

@ -598,7 +598,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].dac.furnaceDAC) {
if (chan[i].curPSGMode.val&8) {
double off=1.0;
if (chan[i].dac.sample>=0 && chan[i].dac.sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].dac.sample);
@ -677,54 +677,49 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AY);
if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->amiga.useSample)) {
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
chan[c.chan].nextPSGMode.val|=8;
} else if (chan[c.chan].dac.furnaceDAC) {
} else {
chan[c.chan].nextPSGMode.val&=~8;
}
if (chan[c.chan].nextPSGMode.val&8) {
if (skipRegisterWrites) break;
if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->amiga.useSample)) {
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
chan[c.chan].dac.sample=-1;
//if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
if (dumpWrites) {
rWrite(0x08+c.chan,0);
//addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
}
}
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
//chan[c.chan].keyOn=true;
chan[c.chan].dac.furnaceDAC=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
chan[c.chan].dac.sample=-1;
//if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
if (dumpWrites) {
rWrite(0x08+c.chan,0);
//addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
}
}
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
//chan[c.chan].keyOn=true;
chan[c.chan].curPSGMode.val&=~8;
chan[c.chan].curPSGMode.val|=chan[c.chan].nextPSGMode.val&8;
break;

View file

@ -402,7 +402,7 @@ void DivPlatformAY8930::tick(bool sysTick) {
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].dac.furnaceDAC) {
if (chan[i].curPSGMode.val&8) {
double off=1.0;
if (chan[i].dac.sample>=0 && chan[i].dac.sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].dac.sample);
@ -507,52 +507,47 @@ int DivPlatformAY8930::dispatch(DivCommand c) {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_AY8930);
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
chan[c.chan].nextPSGMode.val|=8;
} else if (chan[c.chan].dac.furnaceDAC) {
} else {
chan[c.chan].nextPSGMode.val&=~8;
}
if (chan[c.chan].nextPSGMode.val&8) {
if (skipRegisterWrites) break;
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
chan[c.chan].dac.sample=-1;
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
if (dumpWrites) {
rWrite(0x08+c.chan,0);
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
}
}
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
//chan[c.chan].keyOn=true;
chan[c.chan].dac.furnaceDAC=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dac.sample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dac.sample<0 || chan[c.chan].dac.sample>=parent->song.sampleLen) {
chan[c.chan].dac.sample=-1;
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
if (dumpWrites) {
rWrite(0x08+c.chan,0);
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dac.sample);
}
}
if (chan[c.chan].dac.setPos) {
chan[c.chan].dac.setPos=false;
} else {
chan[c.chan].dac.pos=0;
}
chan[c.chan].dac.period=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
//chan[c.chan].keyOn=true;
chan[c.chan].curPSGMode.val&=~8;
chan[c.chan].curPSGMode.val|=chan[c.chan].nextPSGMode.val&8;
break;

View file

@ -681,7 +681,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
if (chan[i].std.vol.had) {
int inVol=chan[i].std.vol.val;
if (chan[i].furnaceDac && inVol>0) {
if (inVol>0) {
inVol+=63;
}
chan[i].outVol=VOL_SCALE_LOG_BROKEN(chan[i].vol,MIN(127,inVol),127);
@ -700,7 +700,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
}
}
if (i>=5 && chan[i].furnaceDac && chan[i].dacMode) {
if (i>=5 && chan[i].dacMode) {
if (NEW_ARP_STRAT) {
chan[i].handleArp();
} else if (chan[i].std.arp.had) {
@ -720,7 +720,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
}
}
if (i>=5 && chan[i].furnaceDac) {
if (i>=5 && chan[i].dacMode) {
if (chan[i].std.panL.had) {
chan[5].pan&=1;
chan[5].pan|=chan[i].std.panL.val?2:0;
@ -752,7 +752,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
}
if (i>=5 && chan[i].std.phaseReset.had) {
if (chan[i].std.phaseReset.val==1 && chan[i].furnaceDac) {
if (chan[i].std.phaseReset.val==1 && chan[i].dacMode) {
chan[i].dacPos=0;
}
}
@ -915,7 +915,7 @@ void DivPlatformGenesis::tick(bool sysTick) {
immWrite(chanOffs[i]+ADDR_FREQ,chan[i].freq&0xff);
hardResetElapsed+=2;
}
if (chan[i].furnaceDac && chan[i].dacMode) {
if (chan[i].dacMode) {
double off=1.0;
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].dacSample);
@ -1051,15 +1051,11 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
if (ins->type==DIV_INS_AMIGA) {
chan[c.chan].dacMode=1;
rWrite(0x2b,1<<7);
} else if (chan[c.chan].furnaceDac) {
} else {
chan[c.chan].dacMode=0;
rWrite(0x2b,0<<7);
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
} else if (!chan[c.chan].dacMode) {
rWrite(0x2b,0<<7);
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
}
}
if (c.chan>=5 && chan[c.chan].dacMode) {
@ -1097,7 +1093,6 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
chan[c.chan].note=c.value;
chan[c.chan].freqChanged=true;
}
chan[c.chan].furnaceDac=true;
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
@ -1251,7 +1246,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
}
break;
}
if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
if (c.chan>=5 && chan[c.chan].dacMode) {
int destFreq=parent->calcBaseFreq(1,1,c.value2+chan[c.chan].sampleNoteDelta,false);
bool return2=false;
if (destFreq>chan[c.chan].baseFreq) {
@ -1298,7 +1293,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
case DIV_CMD_LEGATO: {
if (c.chan==csmChan) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
} else if (c.chan>=5 && chan[c.chan].furnaceDac && chan[c.chan].dacMode) {
} else if (c.chan>=5 && chan[c.chan].dacMode) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value+chan[c.chan].sampleNoteDelta,false);
} else {
if (chan[c.chan].insChanged) {

View file

@ -171,15 +171,13 @@ void DivPlatformMMC5::tick(bool sysTick) {
// PCM
if (chan[2].freqChanged) {
chan[2].freq=parent->calcFreq(chan[2].baseFreq,chan[2].pitch,chan[2].fixedArp?chan[2].baseNoteOverride:chan[2].arpOff,chan[2].fixedArp,false,0,chan[2].pitch2,1,1);
if (chan[2].furnaceDac) {
double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample);
off=(double)s->centerRate/parent->getCenterRate();
}
dacRate=MIN(chan[2].freq*off,32000);
if (dumpWrites) addWrite(0xffff0001,dacRate);
double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample);
off=(double)s->centerRate/parent->getCenterRate();
}
dacRate=MIN(chan[2].freq*off,32000);
if (dumpWrites) addWrite(0xffff0001,dacRate);
chan[2].freqChanged=false;
}
}
@ -189,40 +187,35 @@ int DivPlatformMMC5::dispatch(DivCommand c) {
case DIV_CMD_NOTE_ON:
if (c.chan==2) { // PCM
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_STD);
if (ins->type==DIV_INS_AMIGA) {
if (c.value!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
dacSample=-1;
if (dumpWrites) addWrite(0xffff0002,0);
break;
} else {
if (dumpWrites) addWrite(0xffff0000,dacSample);
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
dacPos=0;
}
dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
chan[c.chan].furnaceDac=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
if (c.value!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
dacSample=-1;
if (dumpWrites) addWrite(0xffff0002,0);
break;
} else {
if (dumpWrites) addWrite(0xffff0000,dacSample);
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
dacPos=0;
}
dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
break;
} else {
if (c.value!=DIV_NOTE_NULL) {

View file

@ -162,29 +162,20 @@ int DivPlatformMSM6258::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
if (ins->type==DIV_INS_MSM6258 || ins->type==DIV_INS_AMIGA) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) sample=ins->amiga.getSample(c.value);
samplePos=0;
if (sample>=0 && sample<parent->song.sampleLen) {
//DivSample* s=parent->getSample(chan[c.chan].sample);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
break;
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) sample=ins->amiga.getSample(c.value);
samplePos=0;
if (sample>=0 && sample<parent->song.sampleLen) {
//DivSample* s=parent->getSample(chan[c.chan].sample);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
}
break;
}

View file

@ -27,12 +27,10 @@
class DivPlatformMSM6258: public DivDispatch {
protected:
struct Channel: public SharedChannel<int> {
bool furnacePCM;
int sample;
unsigned char pan;
Channel():
SharedChannel<int>(8),
furnacePCM(false),
sample(-1),
pan(3) {}
};

View file

@ -161,31 +161,22 @@ int DivPlatformMSM6295::dispatch(DivCommand c) {
switch (c.cmd) {
case DIV_CMD_NOTE_ON: {
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
if (ins->type==DIV_INS_MSM6295 || ins->type==DIV_INS_AMIGA) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
//DivSample* s=parent->getSample(chan[c.chan].sample);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
rWriteDelay(0,(8<<c.chan),180); // turn off
setPhrase(c.chan);
rWrite(0,(16<<c.chan)|(8-chan[c.chan].outVol)); // turn on
} else {
break;
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
//DivSample* s=parent->getSample(chan[c.chan].sample);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
rWriteDelay(0,(8<<c.chan),180); // turn off
setPhrase(c.chan);
rWrite(0,(16<<c.chan)|(8-chan[c.chan].outVol)); // turn on
}
break;
}

View file

@ -27,11 +27,9 @@
class DivPlatformMSM6295: public DivDispatch, public vgsound_emu_mem_intf {
protected:
struct Channel: public SharedChannel<int> {
bool furnacePCM;
int sample;
Channel():
SharedChannel<int>(8),
furnacePCM(false),
sample(-1) {}
};
Channel chan[4];

View file

@ -419,79 +419,78 @@ void DivPlatformNES::tick(bool sysTick) {
// PCM
if (chan[4].freqChanged || chan[4].keyOn) {
chan[4].freq=parent->calcFreq(chan[4].baseFreq,chan[4].pitch,chan[4].fixedArp?chan[4].baseNoteOverride:chan[4].arpOff,chan[4].fixedArp,false);
if (chan[4].furnaceDac) {
double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample);
off=(double)s->centerRate/parent->getCenterRate();
}
dacRate=MIN(chan[4].freq*off,32000);
if (chan[4].keyOn) {
if (dpcmMode && !skipRegisterWrites && dacSample>=0 && dacSample<parent->song.sampleLen) {
unsigned int dpcmAddr=sampleOffDPCM[dacSample]+(dacPos>>3);
int dpcmLen=(parent->getSample(dacSample)->lengthDPCM-(dacPos>>3))>>4;
if (dpcmLen<0) dpcmLen=0;
if (dpcmLen>255) dpcmLen=255;
goingToLoop=parent->getSample(dacSample)->isLoopable();
// write DPCM
rWrite(0x4015,15);
if (nextDPCMFreq>=0) {
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
nextDPCMFreq=-1;
} else {
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
}
if (nextDPCMDelta>=0) {
rWrite(0x4011,nextDPCMDelta);
nextDPCMDelta=-1;
}
rWrite(0x4012,(dpcmAddr>>6)&0xff);
rWrite(0x4013,dpcmLen&0xff);
rWrite(0x4015,31);
if (dpcmBank!=(dpcmAddr>>14)) {
dpcmBank=dpcmAddr>>14;
logV("switching bank to %d",dpcmBank);
if (dumpWrites) addWrite(0xffff0004,dpcmBank);
}
// sample custom loop point...
DivSample* lsamp=parent->getSample(dacSample);
// how it works:
// when the initial sample info is written (see above) and playback is launched,
// the parameters (start point in memory and length) are locked until sample end
// is reached.
// thus, if we write new data after just several APU clock cycles, it will be used only when
// sample finishes one full loop.
// thus we can write sample's loop point as "start address" and sample's looped part length
// as "full sample length".
// APU will play full sample once and then repeatedly cycle through the looped part.
// sources:
// https://www.nesdev.org/wiki/APU_DMC
// https://www.youtube.com/watch?v=vB4P8x2Am6Y
if (lsamp->loopEnd>lsamp->loopStart && goingToLoop) {
int loopStartAddr=sampleOffDPCM[dacSample]+(lsamp->loopStart>>3);
int loopLen=(lsamp->loopEnd-lsamp->loopStart)>>3;
rWrite(0x4012,(loopStartAddr>>6)&0xff);
rWrite(0x4013,(loopLen>>4)&0xff);
}
}
} else {
double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample);
off=(double)s->centerRate/parent->getCenterRate();
}
dacRate=MIN(chan[4].freq*off,32000);
if (chan[4].keyOn) {
if (dpcmMode && !skipRegisterWrites && dacSample>=0 && dacSample<parent->song.sampleLen) {
unsigned int dpcmAddr=sampleOffDPCM[dacSample]+(dacPos>>3);
int dpcmLen=(parent->getSample(dacSample)->lengthDPCM-(dacPos>>3))>>4;
if (dpcmLen<0) dpcmLen=0;
if (dpcmLen>255) dpcmLen=255;
goingToLoop=parent->getSample(dacSample)->isLoopable();
// write DPCM
rWrite(0x4015,15);
if (nextDPCMFreq>=0) {
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
nextDPCMFreq=-1;
} else {
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
}
if (nextDPCMDelta>=0) {
rWrite(0x4011,nextDPCMDelta);
nextDPCMDelta=-1;
}
rWrite(0x4012,(dpcmAddr>>6)&0xff);
rWrite(0x4013,dpcmLen&0xff);
rWrite(0x4015,31);
if (dpcmBank!=(dpcmAddr>>14)) {
dpcmBank=dpcmAddr>>14;
logV("switching bank to %d",dpcmBank);
if (dumpWrites) addWrite(0xffff0004,dpcmBank);
}
// sample custom loop point...
DivSample* lsamp=parent->getSample(dacSample);
// how it works:
// when the initial sample info is written (see above) and playback is launched,
// the parameters (start point in memory and length) are locked until sample end
// is reached.
// thus, if we write new data after just several APU clock cycles, it will be used only when
// sample finishes one full loop.
// thus we can write sample's loop point as "start address" and sample's looped part length
// as "full sample length".
// APU will play full sample once and then repeatedly cycle through the looped part.
// sources:
// https://www.nesdev.org/wiki/APU_DMC
// https://www.youtube.com/watch?v=vB4P8x2Am6Y
if (lsamp->loopEnd>lsamp->loopStart && goingToLoop) {
int loopStartAddr=sampleOffDPCM[dacSample]+(lsamp->loopStart>>3);
int loopLen=(lsamp->loopEnd-lsamp->loopStart)>>3;
rWrite(0x4012,(loopStartAddr>>6)&0xff);
rWrite(0x4013,(loopLen>>4)&0xff);
}
}
} else {
if (nextDPCMFreq>=0) {
rWrite(0x4010,nextDPCMFreq|(goingToLoop?0x40:0));
nextDPCMFreq=-1;
} else {
rWrite(0x4010,calcDPCMRate(dacRate)|(goingToLoop?0x40:0));
}
if (dumpWrites && !dpcmMode) addWrite(0xffff0001,dacRate);
}
if (dumpWrites && !dpcmMode) addWrite(0xffff0001,dacRate);
if (chan[4].keyOn) chan[4].keyOn=false;
chan[4].freqChanged=false;
}
@ -504,69 +503,64 @@ int DivPlatformNES::dispatch(DivCommand c) {
case DIV_CMD_NOTE_ON:
if (c.chan==4) { // PCM
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_NES);
if (ins->type==DIV_INS_AMIGA || (ins->type==DIV_INS_NES && !parent->song.oldDPCM)) {
if (ins->type==DIV_INS_NES) {
if (!dpcmMode) {
dpcmMode=true;
if (dumpWrites) addWrite(0xffff0002,0);
dacSample=-1;
rWrite(0x4015,15);
rWrite(0x4010,0);
rWrite(0x4012,0);
rWrite(0x4013,0);
rWrite(0x4015,31);
}
if (ins->amiga.useNoteMap) {
nextDPCMFreq=ins->amiga.getDPCMFreq(c.value);
if (nextDPCMFreq<0 || nextDPCMFreq>15) nextDPCMFreq=lastDPCMFreq;
lastDPCMFreq=nextDPCMFreq;
nextDPCMDelta=ins->amiga.getDPCMDelta(c.value);
} else {
if (c.value==DIV_NOTE_NULL) {
nextDPCMFreq=lastDPCMFreq;
} else {
nextDPCMFreq=c.value&15;
}
}
}
if (c.value!=DIV_NOTE_NULL) {
dacSample=(int)ins->amiga.getSample(c.value);
if (ins->type==DIV_INS_AMIGA) {
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=(int)ins->amiga.getSample(chan[c.chan].sampleNote);
if (ins->type==DIV_INS_AMIGA) {
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
if (ins->type==DIV_INS_NES) {
if (!dpcmMode) {
dpcmMode=true;
if (dumpWrites) addWrite(0xffff0002,0);
dacSample=-1;
if (dumpWrites && !dpcmMode) addWrite(0xffff0002,0);
break;
rWrite(0x4015,15);
rWrite(0x4010,0);
rWrite(0x4012,0);
rWrite(0x4013,0);
rWrite(0x4015,31);
}
if (ins->amiga.useNoteMap) {
nextDPCMFreq=ins->amiga.getDPCMFreq(c.value);
if (nextDPCMFreq<0 || nextDPCMFreq>15) nextDPCMFreq=lastDPCMFreq;
lastDPCMFreq=nextDPCMFreq;
nextDPCMDelta=ins->amiga.getDPCMDelta(c.value);
} else {
if (dumpWrites && !dpcmMode) addWrite(0xffff0000,dacSample);
if (c.value==DIV_NOTE_NULL) {
nextDPCMFreq=lastDPCMFreq;
} else {
nextDPCMFreq=c.value&15;
}
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
dacPos=0;
}
dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
chan[c.chan].furnaceDac=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
}
if (c.value!=DIV_NOTE_NULL) {
dacSample=(int)ins->amiga.getSample(c.value);
if (ins->type==DIV_INS_AMIGA) {
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=(int)ins->amiga.getSample(chan[c.chan].sampleNote);
if (ins->type==DIV_INS_AMIGA) {
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
dacSample=-1;
if (dumpWrites && !dpcmMode) addWrite(0xffff0002,0);
break;
} else {
if (dumpWrites && !dpcmMode) addWrite(0xffff0000,dacSample);
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
dacPos=0;
}
dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=parent->calcBaseFreq(1,1,c.value,false);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
break;
} else if (c.chan==3) { // noise
if (c.value!=DIV_NOTE_NULL) {

View file

@ -30,7 +30,7 @@ class DivPlatformNES: public DivDispatch {
struct Channel: public SharedChannel<signed char> {
int prevFreq;
unsigned char duty, sweep, envMode, len;
bool sweepChanged, furnaceDac, setPos;
bool sweepChanged, setPos;
Channel():
SharedChannel<signed char>(15),
prevFreq(65535),
@ -39,7 +39,6 @@ class DivPlatformNES: public DivDispatch {
envMode(3),
len(0x1f),
sweepChanged(false),
furnaceDac(false),
setPos(false) {}
};
Channel chan[5];

View file

@ -1387,26 +1387,24 @@ void DivPlatformOPL::tick(bool sysTick) {
// ADPCM
if (adpcmChan>=0) {
if (chan[adpcmChan].furnacePCM) {
chan[adpcmChan].std.next();
chan[adpcmChan].std.next();
if (chan[adpcmChan].std.vol.had) {
chan[adpcmChan].outVol=(chan[adpcmChan].vol*MIN(chan[adpcmChan].macroVolMul,chan[adpcmChan].std.vol.val))/chan[adpcmChan].macroVolMul;
immWrite(18,(isMuted[adpcmChan]?0:chan[adpcmChan].outVol));
}
if (chan[adpcmChan].std.vol.had) {
chan[adpcmChan].outVol=(chan[adpcmChan].vol*MIN(chan[adpcmChan].macroVolMul,chan[adpcmChan].std.vol.val))/chan[adpcmChan].macroVolMul;
immWrite(18,(isMuted[adpcmChan]?0:chan[adpcmChan].outVol));
}
if (NEW_ARP_STRAT) {
chan[adpcmChan].handleArp();
} else if (chan[adpcmChan].std.arp.had) {
if (!chan[adpcmChan].inPorta) {
chan[adpcmChan].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmChan].note,chan[adpcmChan].std.arp.val));
}
chan[adpcmChan].freqChanged=true;
if (NEW_ARP_STRAT) {
chan[adpcmChan].handleArp();
} else if (chan[adpcmChan].std.arp.had) {
if (!chan[adpcmChan].inPorta) {
chan[adpcmChan].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmChan].note,chan[adpcmChan].std.arp.val));
}
if (chan[adpcmChan].std.phaseReset.had) {
if ((chan[adpcmChan].std.phaseReset.val==1) && chan[adpcmChan].active) {
chan[adpcmChan].keyOn=true;
}
chan[adpcmChan].freqChanged=true;
}
if (chan[adpcmChan].std.phaseReset.had) {
if ((chan[adpcmChan].std.phaseReset.val==1) && chan[adpcmChan].active) {
chan[adpcmChan].keyOn=true;
}
}
if (chan[adpcmChan].freqChanged || chan[adpcmChan].keyOn || chan[adpcmChan].keyOff) {
@ -1838,48 +1836,39 @@ int DivPlatformOPL::dispatch(DivCommand c) {
} else if (c.chan==adpcmChan) { // ADPCM
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) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
chan[c.chan].fixedFreq=0;
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(18,(isMuted[adpcmChan]?0:chan[adpcmChan].outVol));
}
chan[c.chan].macroInit(ins);
chan[c.chan].fixedFreq=0;
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(18,(isMuted[adpcmChan]?0:chan[adpcmChan].outVol));
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
c.value=ins->amiga.getFreq(c.value);
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(8,0);
immWrite(9,(sampleOffB[chan[c.chan].sample]>>2)&0xff);
immWrite(10,(sampleOffB[chan[c.chan].sample]>>10)&0xff);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
c.value=ins->amiga.getFreq(c.value);
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(8,0);
immWrite(9,(sampleOffB[chan[c.chan].sample]>>2)&0xff);
immWrite(10,(sampleOffB[chan[c.chan].sample]>>10)&0xff);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(11,(end>>2)&0xff);
immWrite(12,(end>>10)&0xff);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
immWrite(7,0x01); // reset
immWrite(9,0);
immWrite(10,0);
immWrite(11,0);
immWrite(12,0);
break;
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
immWrite(7,0x01); // reset
immWrite(9,0);
immWrite(10,0);
immWrite(11,0);
immWrite(12,0);
break;
}
break;
}
@ -2060,9 +2049,6 @@ int DivPlatformOPL::dispatch(DivCommand c) {
break;
}
case DIV_CMD_PITCH: {
if (c.chan==adpcmChan) {
if (!chan[c.chan].furnacePCM) break;
}
chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true;
break;

View file

@ -59,7 +59,7 @@ class DivPlatformOPL: public DivDispatch {
DivInstrumentFM state;
unsigned int freqH, freqL;
int sample, fixedFreq;
bool furnacePCM, fourOp, hardReset, writeCtrl;
bool fourOp, hardReset, writeCtrl;
bool levelDirect, damp, pseudoReverb, lfoReset, ch;
int lfo, vib, am, ar, d1r, d2r, dl, rc, rr;
int pan;
@ -70,7 +70,6 @@ class DivPlatformOPL: public DivDispatch {
freqL(0),
sample(-1),
fixedFreq(0),
furnacePCM(false),
fourOp(false),
hardReset(false),
writeCtrl(false),

View file

@ -34,14 +34,12 @@ class DivPlatformOPLL: public DivDispatch {
DivInstrumentFM state;
unsigned char freqH, freqL;
int fixedFreq;
bool furnaceDac;
unsigned char pan;
Channel():
SharedChannel<int>(0),
freqH(0),
freqL(0),
fixedFreq(0),
furnaceDac(false),
pan(3) {}
};
Channel chan[11];

View file

@ -225,7 +225,7 @@ void DivPlatformPCE::tick(bool sysTick) {
chan[i].freqChanged=true;
}
if (chan[i].std.phaseReset.had && chan[i].std.phaseReset.val==1) {
if (chan[i].furnaceDac && chan[i].pcm) {
if (chan[i].pcm) {
if (chan[i].active && chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
if (chan[i].setPos) {
chan[i].setPos=false;
@ -249,7 +249,7 @@ void DivPlatformPCE::tick(bool sysTick) {
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
//DivInstrument* ins=parent->getIns(chan[i].ins,DIV_INS_PCE);
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (chan[i].furnaceDac && chan[i].pcm) {
if (chan[i].pcm) {
double off=1.0;
if (chan[i].dacSample>=0 && chan[i].dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[i].dacSample);
@ -301,54 +301,48 @@ int DivPlatformPCE::dispatch(DivCommand c) {
chan[c.chan].macroVolMul=ins->type==DIV_INS_AMIGA?64:31;
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
chan[c.chan].pcm=true;
} else if (chan[c.chan].furnaceDac) {
} else {
chan[c.chan].pcm=false;
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
}
if (chan[c.chan].pcm) {
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
chan[c.chan].furnaceDac=true;
if (skipRegisterWrites) break;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
chan[c.chan].dacSample=-1;
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
if (dumpWrites) {
chWrite(c.chan,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[c.chan].vol));
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample);
}
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
chan[c.chan].dacPos=0;
}
chan[c.chan].dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
//chan[c.chan].keyOn=true;
if (skipRegisterWrites) break;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
chan[c.chan].dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (chan[c.chan].dacSample<0 || chan[c.chan].dacSample>=parent->song.sampleLen) {
chan[c.chan].dacSample=-1;
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
break;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
if (dumpWrites) {
chWrite(c.chan,0x04,parent->song.disableSampleMacro?0xdf:(0xc0|chan[c.chan].vol));
addWrite(0xffff0000+(c.chan<<8),chan[c.chan].dacSample);
}
}
if (chan[c.chan].setPos) {
chan[c.chan].setPos=false;
} else {
chan[c.chan].dacPos=0;
}
chan[c.chan].dacPeriod=0;
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].baseFreq=NOTE_PERIODIC(c.value);
chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value;
}
chan[c.chan].active=true;
chan[c.chan].macroInit(ins);
if (!parent->song.brokenOutVol && !chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
break;
}

View file

@ -32,7 +32,7 @@ class DivPlatformPCE: public DivDispatch {
unsigned int dacPos;
int dacSample;
unsigned char pan;
bool noise, pcm, furnaceDac, deferredWaveUpdate, setPos;
bool noise, pcm, deferredWaveUpdate, setPos;
signed short wave;
int macroVolMul, noiseSeek;
DivWaveSynth ws;
@ -48,7 +48,6 @@ class DivPlatformPCE: public DivDispatch {
pan(255),
noise(false),
pcm(false),
furnaceDac(false),
deferredWaveUpdate(false),
setPos(false),
wave(-1),

View file

@ -278,7 +278,7 @@ void DivPlatformSwan::tick(bool sysTick) {
}
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER);
if (i==1 && pcm && furnaceDac) {
if (i==1 && pcm) {
double off=1.0;
if (dacSample>=0 && dacSample<parent->song.sampleLen) {
DivSample* s=parent->getSample(dacSample);
@ -355,7 +355,7 @@ int DivPlatformSwan::dispatch(DivCommand c) {
if (c.chan==1) {
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
pcm=true;
} else if (furnaceDac) {
} else {
pcm=false;
chan[c.chan].sampleNote=DIV_NOTE_NULL;
chan[c.chan].sampleNoteDelta=0;
@ -368,37 +368,32 @@ int DivPlatformSwan::dispatch(DivCommand c) {
dacPos=0;
}
dacPeriod=0;
if (ins->type==DIV_INS_AMIGA || ins->amiga.useSample) {
if (c.value!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
dacSample=-1;
if (dumpWrites) postWrite(0xffff0002,0);
break;
} else {
if (dumpWrites) {
postWrite(0xffff0000,dacSample);
}
}
if (c.value!=DIV_NOTE_NULL) {
chan[1].baseFreq=NOTE_PERIODIC(c.value);
chan[1].freqChanged=true;
chan[1].note=c.value;
}
chan[1].active=true;
chan[1].keyOn=true;
chan[1].macroInit(ins);
furnaceDac=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
if (c.value!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
dacSample=ins->amiga.getSample(chan[c.chan].sampleNote);
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
}
if (dacSample<0 || dacSample>=parent->song.sampleLen) {
dacSample=-1;
if (dumpWrites) postWrite(0xffff0002,0);
break;
} else {
if (dumpWrites) {
postWrite(0xffff0000,dacSample);
}
}
if (c.value!=DIV_NOTE_NULL) {
chan[1].baseFreq=NOTE_PERIODIC(c.value);
chan[1].freqChanged=true;
chan[1].note=c.value;
}
chan[1].active=true;
chan[1].keyOn=true;
chan[1].macroInit(ins);
break;
}
}
@ -652,7 +647,6 @@ void DivPlatformSwan::reset() {
swan_sound_init(&ws, true);
pcm=false;
sweep=false;
furnaceDac=false;
setPos=false;
noise=0;
dacPeriod=0;

View file

@ -41,7 +41,7 @@ class DivPlatformSwan: public DivDispatch {
bool isMuted[4];
bool stereo;
bool useMdfn;
bool pcm, sweep, furnaceDac, setPos;
bool pcm, sweep, setPos;
unsigned char noise;
int dacPeriod, dacRate;
unsigned int dacPos;

View file

@ -947,31 +947,29 @@ void DivPlatformYM2608::tick(bool sysTick) {
// RSS
for (int i=(9+isCSM); i<(15+isCSM); i++) {
if (chan[i].furnacePCM) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalRSSVolume!=(chan[i].std.duty.val&0x3f)) {
globalRSSVolume=chan[i].std.duty.val&0x3f;
immWrite(0x11,globalRSSVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x18+(i-(9+isCSM)),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalRSSVolume!=(chan[i].std.duty.val&0x3f)) {
globalRSSVolume=chan[i].std.duty.val&0x3f;
immWrite(0x11,globalRSSVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x18+(i-(9+isCSM)),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
hardResetElapsed++;
}
if (chan[i].keyOff) {
writeRSSOff|=(1<<(i-(9+isCSM)));
chan[i].keyOff=false;
@ -982,57 +980,54 @@ void DivPlatformYM2608::tick(bool sysTick) {
}
}
// ADPCM-B
if (chan[(15+isCSM)].furnacePCM) {
chan[(15+isCSM)].std.next();
chan[(15+isCSM)].std.next();
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 (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+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+isCSM)].freqChanged=true;
if (NEW_ARP_STRAT) {
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+isCSM)].freqChanged=true;
}
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+isCSM)].pitch2=chan[(15+isCSM)].std.pitch.val;
}
chan[(15+isCSM)].freqChanged=true;
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+isCSM)].pitch2=chan[(15+isCSM)].std.pitch.val;
}
chan[(15+isCSM)].freqChanged=true;
}
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 + isCSM)]) {
immWrite(0x101,(isMuted[(15 + isCSM)]?0:(chan[(15+isCSM)].pan<<6))|memConfig);
hardResetElapsed++;
}
}
}
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+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 + isCSM)]) {
immWrite(0x101,(isMuted[(15 + isCSM)]?0:(chan[(15+isCSM)].pan<<6))|memConfig);
hardResetElapsed++;
}
}
}
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+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)/parent->getCenterRate();
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+isCSM)].freq=0;
}
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)/parent->getCenterRate();
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+isCSM)].freq=0;
}
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
@ -1153,70 +1148,50 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
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) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x10b,chan[c.chan].outVol);
}
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x10b,chan[c.chan].outVol);
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x100,0x01); // reset
immWrite(0x102,(sampleOffB[chan[c.chan].sample]>>5)&0xff);
immWrite(0x103,(sampleOffB[chan[c.chan].sample]>>13)&0xff);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x104,(end>>5)&0xff);
immWrite(0x105,(end>>13)&0xff);
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|memConfig);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x100,0x01); // reset
immWrite(0x102,(sampleOffB[chan[c.chan].sample]>>5)&0xff);
immWrite(0x103,(sampleOffB[chan[c.chan].sample]>>13)&0xff);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x104,(end>>5)&0xff);
immWrite(0x105,(end>>13)&0xff);
immWrite(0x101,(isMuted[c.chan]?0:(chan[c.chan].pan<<6))|memConfig);
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
immWrite(0x100,0x01); // reset
immWrite(0x102,0);
immWrite(0x103,0);
immWrite(0x104,0);
immWrite(0x105,0);
break;
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
immWrite(0x100,0x01); // reset
immWrite(0x102,0);
immWrite(0x103,0);
immWrite(0x104,0);
immWrite(0x105,0);
break;
}
break;
}
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) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
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+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
}
} else {
chan[c.chan].macroInit(NULL);
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+isCSM)),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
}
@ -1337,7 +1312,6 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
break;
}
case DIV_CMD_PITCH: {
if (c.chan==(15+isCSM) && !chan[c.chan].furnacePCM) break;
chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true;
break;
@ -1396,7 +1370,6 @@ int DivPlatformYM2608::dispatch(DivCommand c) {
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);

View file

@ -867,31 +867,30 @@ void DivPlatformYM2610::tick(bool sysTick) {
// ADPCM-A
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
if (chan[i].furnacePCM) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalADPCMAVolume!=(chan[i].std.duty.val&0x3f)) {
globalADPCMAVolume=chan[i].std.duty.val&0x3f;
immWrite(0x101,globalADPCMAVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x108+(i-adpcmAChanOffs),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalADPCMAVolume!=(chan[i].std.duty.val&0x3f)) {
globalADPCMAVolume=chan[i].std.duty.val&0x3f;
immWrite(0x101,globalADPCMAVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x108+(i-adpcmAChanOffs),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
hardResetElapsed++;
}
if (chan[i].keyOff) {
writeADPCMAOff|=(1<<(i-adpcmAChanOffs));
chan[i].keyOff=false;
@ -904,63 +903,61 @@ void DivPlatformYM2610::tick(bool sysTick) {
}
}
// ADPCM-B
if (chan[adpcmBChanOffs].furnacePCM) {
chan[adpcmBChanOffs].std.next();
chan[adpcmBChanOffs].std.next();
if (chan[adpcmBChanOffs].std.vol.had) {
chan[adpcmBChanOffs].outVol=(chan[adpcmBChanOffs].vol*MIN(chan[adpcmBChanOffs].macroVolMul,chan[adpcmBChanOffs].std.vol.val))/chan[adpcmBChanOffs].macroVolMul;
immWrite(0x1b,chan[adpcmBChanOffs].outVol);
hardResetElapsed++;
}
if (chan[adpcmBChanOffs].std.vol.had) {
chan[adpcmBChanOffs].outVol=(chan[adpcmBChanOffs].vol*MIN(chan[adpcmBChanOffs].macroVolMul,chan[adpcmBChanOffs].std.vol.val))/chan[adpcmBChanOffs].macroVolMul;
immWrite(0x1b,chan[adpcmBChanOffs].outVol);
hardResetElapsed++;
}
if (NEW_ARP_STRAT) {
chan[adpcmBChanOffs].handleArp();
} else if (chan[adpcmBChanOffs].std.arp.had) {
if (!chan[adpcmBChanOffs].inPorta) {
chan[adpcmBChanOffs].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmBChanOffs].note,chan[adpcmBChanOffs].std.arp.val));
}
chan[adpcmBChanOffs].freqChanged=true;
if (NEW_ARP_STRAT) {
chan[adpcmBChanOffs].handleArp();
} else if (chan[adpcmBChanOffs].std.arp.had) {
if (!chan[adpcmBChanOffs].inPorta) {
chan[adpcmBChanOffs].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmBChanOffs].note,chan[adpcmBChanOffs].std.arp.val));
}
chan[adpcmBChanOffs].freqChanged=true;
}
if (chan[adpcmBChanOffs].std.pitch.had) {
if (chan[adpcmBChanOffs].std.pitch.mode) {
chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val;
CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535);
} else {
chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val;
}
chan[adpcmBChanOffs].freqChanged=true;
if (chan[adpcmBChanOffs].std.pitch.had) {
if (chan[adpcmBChanOffs].std.pitch.mode) {
chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val;
CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535);
} else {
chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val;
}
chan[adpcmBChanOffs].freqChanged=true;
}
if (chan[adpcmBChanOffs].std.panL.had) {
if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) {
chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3;
if (!isMuted[adpcmBChanOffs]) {
immWrite(0x11,(isMuted[adpcmBChanOffs]?0:(chan[adpcmBChanOffs].pan<<6)));
hardResetElapsed++;
}
}
}
if (chan[adpcmBChanOffs].std.phaseReset.had) {
if ((chan[adpcmBChanOffs].std.phaseReset.val==1) && chan[adpcmBChanOffs].active) {
chan[adpcmBChanOffs].keyOn=true;
if (chan[adpcmBChanOffs].std.panL.had) {
if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) {
chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3;
if (!isMuted[adpcmBChanOffs]) {
immWrite(0x11,(isMuted[adpcmBChanOffs]?0:(chan[adpcmBChanOffs].pan<<6)));
hardResetElapsed++;
}
}
}
if (chan[adpcmBChanOffs].freqChanged || chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
if (chan[adpcmBChanOffs].furnacePCM) {
if (chan[adpcmBChanOffs].sample>=0 && chan[adpcmBChanOffs].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmBChanOffs].sample)->centerRate)/parent->getCenterRate();
chan[adpcmBChanOffs].freq=parent->calcFreq(chan[adpcmBChanOffs].baseFreq,chan[adpcmBChanOffs].pitch,chan[adpcmBChanOffs].fixedArp?chan[adpcmBChanOffs].baseNoteOverride:chan[adpcmBChanOffs].arpOff,chan[adpcmBChanOffs].fixedArp,false,4,chan[adpcmBChanOffs].pitch2,(double)chipClock/144,off);
} else {
chan[adpcmBChanOffs].freq=0;
}
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
immWrite(0x19,chan[adpcmBChanOffs].freq&0xff);
immWrite(0x1a,(chan[adpcmBChanOffs].freq>>8)&0xff);
hardResetElapsed+=2;
if (chan[adpcmBChanOffs].std.phaseReset.had) {
if ((chan[adpcmBChanOffs].std.phaseReset.val==1) && chan[adpcmBChanOffs].active) {
chan[adpcmBChanOffs].keyOn=true;
}
}
if (chan[adpcmBChanOffs].freqChanged || chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
if (chan[adpcmBChanOffs].sample>=0 && chan[adpcmBChanOffs].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmBChanOffs].sample)->centerRate)/parent->getCenterRate();
chan[adpcmBChanOffs].freq=parent->calcFreq(chan[adpcmBChanOffs].baseFreq,chan[adpcmBChanOffs].pitch,chan[adpcmBChanOffs].fixedArp?chan[adpcmBChanOffs].baseNoteOverride:chan[adpcmBChanOffs].arpOff,chan[adpcmBChanOffs].fixedArp,false,4,chan[adpcmBChanOffs].pitch2,(double)chipClock/144,off);
} else {
chan[adpcmBChanOffs].freq=0;
}
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
immWrite(0x19,chan[adpcmBChanOffs].freq&0xff);
immWrite(0x1a,(chan[adpcmBChanOffs].freq>>8)&0xff);
hardResetElapsed+=2;
if (chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
immWrite(0x10,0x01); // reset
hardResetElapsed++;
@ -1071,92 +1068,74 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
if (c.chan>=adpcmBChanOffs) { // 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) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol);
}
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol);
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff);
immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff);
immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
immWrite(0x10,0x01); // reset
immWrite(0x12,0);
immWrite(0x13,0);
immWrite(0x14,0);
immWrite(0x15,0);
break;
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
immWrite(0x10,0x01); // reset
immWrite(0x12,0);
immWrite(0x13,0);
immWrite(0x14,0);
immWrite(0x15,0);
break;
}
break;
}
if (c.chan>=adpcmAChanOffs) { // ADPCM-A
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
chan[c.chan].macroVolMul=(ins->type==DIV_INS_AMIGA)?64:31;
if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ADPCMA)) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff);
immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16);
int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1;
immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff);
immWrite(0x128+c.chan-adpcmAChanOffs,end>>16);
immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
writeADPCMAOff|=(1<<(c.chan-adpcmAChanOffs));
immWrite(0x110+c.chan-adpcmAChanOffs,0);
immWrite(0x118+c.chan-adpcmAChanOffs,0);
immWrite(0x120+c.chan-adpcmAChanOffs,0);
immWrite(0x128+c.chan-adpcmAChanOffs,0);
break;
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff);
immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16);
int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1;
immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff);
immWrite(0x128+c.chan-adpcmAChanOffs,end>>16);
immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
writeADPCMAOff|=(1<<(c.chan-adpcmAChanOffs));
immWrite(0x110+c.chan-adpcmAChanOffs,0);
immWrite(0x118+c.chan-adpcmAChanOffs,0);
immWrite(0x120+c.chan-adpcmAChanOffs,0);
immWrite(0x128+c.chan-adpcmAChanOffs,0);
break;
}
break;
}
@ -1273,7 +1252,6 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
break;
}
case DIV_CMD_PITCH: {
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true;
break;
@ -1329,7 +1307,6 @@ 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);
}

View file

@ -936,31 +936,30 @@ void DivPlatformYM2610B::tick(bool sysTick) {
// ADPCM-A
for (int i=adpcmAChanOffs; i<adpcmBChanOffs; i++) {
if (chan[i].furnacePCM) {
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalADPCMAVolume!=(chan[i].std.duty.val&0x3f)) {
globalADPCMAVolume=chan[i].std.duty.val&0x3f;
immWrite(0x101,globalADPCMAVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x108+(i-adpcmAChanOffs),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
chan[i].std.next();
if (chan[i].std.vol.had) {
chan[i].outVol=(chan[i].vol*MIN(chan[i].macroVolMul,chan[i].std.vol.val))/chan[i].macroVolMul;
}
if (chan[i].std.duty.had) {
if (globalADPCMAVolume!=(chan[i].std.duty.val&0x3f)) {
globalADPCMAVolume=chan[i].std.duty.val&0x3f;
immWrite(0x101,globalADPCMAVolume);
hardResetElapsed++;
}
}
if (chan[i].std.panL.had) {
chan[i].pan=chan[i].std.panL.val&3;
}
if (chan[i].std.phaseReset.had) {
if ((chan[i].std.phaseReset.val==1) && chan[i].active) {
chan[i].keyOn=true;
}
}
if (!isMuted[i] && (chan[i].std.vol.had || chan[i].std.panL.had)) {
immWrite(0x108+(i-adpcmAChanOffs),isMuted[i]?0:((chan[i].pan<<6)|chan[i].outVol));
hardResetElapsed++;
}
if (chan[i].keyOff) {
writeADPCMAOff|=(1<<(i-adpcmAChanOffs));
chan[i].keyOff=false;
@ -973,63 +972,61 @@ void DivPlatformYM2610B::tick(bool sysTick) {
}
}
// ADPCM-B
if (chan[adpcmBChanOffs].furnacePCM) {
chan[adpcmBChanOffs].std.next();
chan[adpcmBChanOffs].std.next();
if (chan[adpcmBChanOffs].std.vol.had) {
chan[adpcmBChanOffs].outVol=(chan[adpcmBChanOffs].vol*MIN(chan[adpcmBChanOffs].macroVolMul,chan[adpcmBChanOffs].std.vol.val))/chan[adpcmBChanOffs].macroVolMul;
immWrite(0x1b,chan[adpcmBChanOffs].outVol);
hardResetElapsed++;
}
if (chan[adpcmBChanOffs].std.vol.had) {
chan[adpcmBChanOffs].outVol=(chan[adpcmBChanOffs].vol*MIN(chan[adpcmBChanOffs].macroVolMul,chan[adpcmBChanOffs].std.vol.val))/chan[adpcmBChanOffs].macroVolMul;
immWrite(0x1b,chan[adpcmBChanOffs].outVol);
hardResetElapsed++;
}
if (NEW_ARP_STRAT) {
chan[adpcmBChanOffs].handleArp();
} else if (chan[adpcmBChanOffs].std.arp.had) {
if (!chan[adpcmBChanOffs].inPorta) {
chan[adpcmBChanOffs].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmBChanOffs].note,chan[adpcmBChanOffs].std.arp.val));
}
chan[adpcmBChanOffs].freqChanged=true;
if (NEW_ARP_STRAT) {
chan[adpcmBChanOffs].handleArp();
} else if (chan[adpcmBChanOffs].std.arp.had) {
if (!chan[adpcmBChanOffs].inPorta) {
chan[adpcmBChanOffs].baseFreq=NOTE_ADPCMB(parent->calcArp(chan[adpcmBChanOffs].note,chan[adpcmBChanOffs].std.arp.val));
}
chan[adpcmBChanOffs].freqChanged=true;
}
if (chan[adpcmBChanOffs].std.pitch.had) {
if (chan[adpcmBChanOffs].std.pitch.mode) {
chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val;
CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535);
} else {
chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val;
}
chan[adpcmBChanOffs].freqChanged=true;
if (chan[adpcmBChanOffs].std.pitch.had) {
if (chan[adpcmBChanOffs].std.pitch.mode) {
chan[adpcmBChanOffs].pitch2+=chan[adpcmBChanOffs].std.pitch.val;
CLAMP_VAR(chan[adpcmBChanOffs].pitch2,-65535,65535);
} else {
chan[adpcmBChanOffs].pitch2=chan[adpcmBChanOffs].std.pitch.val;
}
chan[adpcmBChanOffs].freqChanged=true;
}
if (chan[adpcmBChanOffs].std.panL.had) {
if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) {
chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3;
if (!isMuted[adpcmBChanOffs]) {
immWrite(0x11,(isMuted[adpcmBChanOffs]?0:(chan[adpcmBChanOffs].pan<<6)));
hardResetElapsed++;
}
}
}
if (chan[adpcmBChanOffs].std.phaseReset.had) {
if ((chan[adpcmBChanOffs].std.phaseReset.val==1) && chan[adpcmBChanOffs].active) {
chan[adpcmBChanOffs].keyOn=true;
if (chan[adpcmBChanOffs].std.panL.had) {
if (chan[adpcmBChanOffs].pan!=(chan[adpcmBChanOffs].std.panL.val&3)) {
chan[adpcmBChanOffs].pan=chan[adpcmBChanOffs].std.panL.val&3;
if (!isMuted[adpcmBChanOffs]) {
immWrite(0x11,(isMuted[adpcmBChanOffs]?0:(chan[adpcmBChanOffs].pan<<6)));
hardResetElapsed++;
}
}
}
if (chan[adpcmBChanOffs].freqChanged || chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
if (chan[adpcmBChanOffs].furnacePCM) {
if (chan[adpcmBChanOffs].sample>=0 && chan[adpcmBChanOffs].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmBChanOffs].sample)->centerRate)/parent->getCenterRate();
chan[adpcmBChanOffs].freq=parent->calcFreq(chan[adpcmBChanOffs].baseFreq,chan[adpcmBChanOffs].pitch,chan[adpcmBChanOffs].fixedArp?chan[adpcmBChanOffs].baseNoteOverride:chan[adpcmBChanOffs].arpOff,chan[adpcmBChanOffs].fixedArp,false,4,chan[adpcmBChanOffs].pitch2,(double)chipClock/144,off);
} else {
chan[adpcmBChanOffs].freq=0;
}
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
immWrite(0x19,chan[adpcmBChanOffs].freq&0xff);
immWrite(0x1a,(chan[adpcmBChanOffs].freq>>8)&0xff);
hardResetElapsed+=2;
if (chan[adpcmBChanOffs].std.phaseReset.had) {
if ((chan[adpcmBChanOffs].std.phaseReset.val==1) && chan[adpcmBChanOffs].active) {
chan[adpcmBChanOffs].keyOn=true;
}
}
if (chan[adpcmBChanOffs].freqChanged || chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
if (chan[adpcmBChanOffs].sample>=0 && chan[adpcmBChanOffs].sample<parent->song.sampleLen) {
double off=65535.0*(double)(parent->getSample(chan[adpcmBChanOffs].sample)->centerRate)/parent->getCenterRate();
chan[adpcmBChanOffs].freq=parent->calcFreq(chan[adpcmBChanOffs].baseFreq,chan[adpcmBChanOffs].pitch,chan[adpcmBChanOffs].fixedArp?chan[adpcmBChanOffs].baseNoteOverride:chan[adpcmBChanOffs].arpOff,chan[adpcmBChanOffs].fixedArp,false,4,chan[adpcmBChanOffs].pitch2,(double)chipClock/144,off);
} else {
chan[adpcmBChanOffs].freq=0;
}
if (chan[adpcmBChanOffs].freq<0) chan[adpcmBChanOffs].freq=0;
if (chan[adpcmBChanOffs].freq>65535) chan[adpcmBChanOffs].freq=65535;
immWrite(0x19,chan[adpcmBChanOffs].freq&0xff);
immWrite(0x1a,(chan[adpcmBChanOffs].freq>>8)&0xff);
hardResetElapsed+=2;
if (chan[adpcmBChanOffs].keyOn || chan[adpcmBChanOffs].keyOff) {
immWrite(0x10,0x01); // reset
hardResetElapsed++;
@ -1140,92 +1137,74 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
if (c.chan>=adpcmBChanOffs) { // 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) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol);
}
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
immWrite(0x1b,chan[c.chan].outVol);
}
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff);
immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].sample=ins->amiga.getSample(c.value);
chan[c.chan].sampleNote=c.value;
c.value=ins->amiga.getFreq(c.value);
chan[c.chan].sampleNoteDelta=c.value-chan[c.chan].sampleNote;
}
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x12,(sampleOffB[chan[c.chan].sample]>>8)&0xff);
immWrite(0x13,sampleOffB[chan[c.chan].sample]>>16);
int end=sampleOffB[chan[c.chan].sample]+s->lengthB-1;
immWrite(0x14,(end>>8)&0xff);
immWrite(0x15,end>>16);
immWrite(0x11,isMuted[c.chan]?0:(chan[c.chan].pan<<6));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
immWrite(0x10,0x01); // reset
immWrite(0x12,0);
immWrite(0x13,0);
immWrite(0x14,0);
immWrite(0x15,0);
break;
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
immWrite(0x10,0x01); // reset
immWrite(0x12,0);
immWrite(0x13,0);
immWrite(0x14,0);
immWrite(0x15,0);
break;
}
break;
}
if (c.chan>=adpcmAChanOffs) { // ADPCM-A
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_FM);
chan[c.chan].macroVolMul=(ins->type==DIV_INS_AMIGA)?64:31;
if (!parent->song.disableSampleMacro && (ins->type==DIV_INS_AMIGA || ins->type==DIV_INS_ADPCMA)) {
chan[c.chan].furnacePCM=true;
} else {
chan[c.chan].furnacePCM=false;
}
if (skipRegisterWrites) break;
if (chan[c.chan].furnacePCM) {
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff);
immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16);
int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1;
immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff);
immWrite(0x128+c.chan-adpcmAChanOffs,end>>16);
immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
writeADPCMAOff|=(1<<(c.chan-adpcmAChanOffs));
immWrite(0x110+c.chan-adpcmAChanOffs,0);
immWrite(0x118+c.chan-adpcmAChanOffs,0);
immWrite(0x120+c.chan-adpcmAChanOffs,0);
immWrite(0x128+c.chan-adpcmAChanOffs,0);
break;
chan[c.chan].macroInit(ins);
if (!chan[c.chan].std.vol.will) {
chan[c.chan].outVol=chan[c.chan].vol;
}
if (c.value!=DIV_NOTE_NULL) chan[c.chan].sample=ins->amiga.getSample(c.value);
if (chan[c.chan].sample>=0 && chan[c.chan].sample<parent->song.sampleLen) {
DivSample* s=parent->getSample(chan[c.chan].sample);
immWrite(0x110+c.chan-adpcmAChanOffs,(sampleOffA[chan[c.chan].sample]>>8)&0xff);
immWrite(0x118+c.chan-adpcmAChanOffs,sampleOffA[chan[c.chan].sample]>>16);
int end=sampleOffA[chan[c.chan].sample]+s->lengthA-1;
immWrite(0x120+c.chan-adpcmAChanOffs,(end>>8)&0xff);
immWrite(0x128+c.chan-adpcmAChanOffs,end>>16);
immWrite(0x108+c.chan-adpcmAChanOffs,isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].outVol));
if (c.value!=DIV_NOTE_NULL) {
chan[c.chan].note=c.value;
chan[c.chan].baseFreq=NOTE_ADPCMB(chan[c.chan].note);
chan[c.chan].freqChanged=true;
}
chan[c.chan].active=true;
chan[c.chan].keyOn=true;
} else {
assert(false && "LEGACY SAMPLE MODE!!!");
writeADPCMAOff|=(1<<(c.chan-adpcmAChanOffs));
immWrite(0x110+c.chan-adpcmAChanOffs,0);
immWrite(0x118+c.chan-adpcmAChanOffs,0);
immWrite(0x120+c.chan-adpcmAChanOffs,0);
immWrite(0x128+c.chan-adpcmAChanOffs,0);
break;
}
break;
}
@ -1342,7 +1321,6 @@ int DivPlatformYM2610B::dispatch(DivCommand c) {
break;
}
case DIV_CMD_PITCH: {
if (c.chan==adpcmBChanOffs && !chan[c.chan].furnacePCM) break;
chan[c.chan].pitch=c.value;
chan[c.chan].freqChanged=true;
break;
@ -1398,7 +1376,6 @@ int DivPlatformYM2610B::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);
}

View file

@ -164,7 +164,6 @@
ImGui::Text("- pan: %x",ch->pan); \
ImGui::Text("- opMask: %x",ch->opMask); \
COMMON_CHAN_DEBUG_BOOL; \
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC"); \
ImGui::TextColored(ch->hardReset?colorOn:colorOff,">> hardReset"); \
ImGui::TextColored(ch->opMaskChanged?colorOn:colorOff,">> opMaskChanged"); \
ImGui::TextColored(ch->dacMode?colorOn:colorOff,">> DACMode"); \
@ -201,7 +200,6 @@
COMMON_CHAN_DEBUG_BOOL; \
ImGui::TextColored(ch->hardReset?colorOn:colorOff,">> hardReset"); \
ImGui::TextColored(ch->opMaskChanged?colorOn:colorOff,">> opMaskChanged"); \
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
#define OPN_OPCHAN_DEBUG \
DivPlatformOPN::OPNOpChannel* ch=(DivPlatformOPN::OPNOpChannel*)data; \
@ -227,7 +225,6 @@
COMMON_CHAN_DEBUG_BOOL; \
ImGui::TextColored(ch->hardReset?colorOn:colorOff,">> hardReset"); \
ImGui::TextColored(ch->opMaskChanged?colorOn:colorOff,">> opMaskChanged"); \
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
#define OPNB_OPCHAN_DEBUG \
ImGui::Text("- freqHL: %.2x%.2x",ch->freqH,ch->freqL); \
@ -697,7 +694,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->noise?colorOn:colorOff,">> Noise");
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_NES: {
@ -709,7 +705,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- sweep: %.2x",ch->sweep);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->sweepChanged?colorOn:colorOff,">> SweepChanged");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_C64_6581: case DIV_SYSTEM_C64_8580: {
@ -760,7 +755,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- chPanR: %.2x",ch->chPanR);
ImGui::Text("- macroVolMul: %.2x",ch->macroVolMul);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
ImGui::TextColored(ch->isNewSegaPCM?colorOn:colorOff,">> IsNewSegaPCM");
break;
}
@ -777,7 +771,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- autoEnvNum: %.2x",ch->autoEnvNum);
ImGui::Text("- autoEnvDen: %.2x",ch->autoEnvDen);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->dac.furnaceDAC?colorOn:colorOff,">> furnaceDAC");
break;
}
case DIV_SYSTEM_AY8930: {
@ -794,7 +787,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- autoEnvNum: %.2x",ch->autoEnvNum);
ImGui::Text("- autoEnvDen: %.2x",ch->autoEnvDen);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->dac.furnaceDAC?colorOn:colorOff,">> furnaceDAC");
break;
}
case DIV_SYSTEM_QSOUND: {
@ -831,7 +823,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- Rvol: %.2x",ch->rvol);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->envChanged?colorOn:colorOff,">> EnvChanged");
ImGui::TextColored(ch->furnacePCM?colorOn:colorOff,">> FurnacePCM");
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> PCM");
ImGui::TextColored(ch->env.flag.envEnable?colorOn:colorOff,">> EnvEnable");
ImGui::TextColored(ch->env.flag.envOneshot?colorOn:colorOff,">> EnvOneshot");
@ -870,7 +861,6 @@ void putDispatchChan(void* data, int chanNum, int type) {
ImGui::Text("- duty: %d",ch->duty);
COMMON_CHAN_DEBUG_BOOL;
ImGui::TextColored(ch->pcm?colorOn:colorOff,">> DAC");
ImGui::TextColored(ch->furnaceDac?colorOn:colorOff,">> FurnaceDAC");
break;
}
case DIV_SYSTEM_ES5506: {