C64: add a sample channel
but don't get too excited! it's just $D418 PCM for now...
This commit is contained in:
parent
f16b23772e
commit
0d8b97b1a3
|
@ -328,6 +328,7 @@ void DivDispatchContainer::init(DivSystem sys, DivEngine* eng, int chanCount, do
|
||||||
((DivPlatformNES*)dispatch)->set5E01(false);
|
((DivPlatformNES*)dispatch)->set5E01(false);
|
||||||
break;
|
break;
|
||||||
case DIV_SYSTEM_C64_6581:
|
case DIV_SYSTEM_C64_6581:
|
||||||
|
case DIV_SYSTEM_C64_PCM:
|
||||||
dispatch=new DivPlatformC64;
|
dispatch=new DivPlatformC64;
|
||||||
if (isRender) {
|
if (isRender) {
|
||||||
((DivPlatformC64*)dispatch)->setCore(eng->getConfInt("c64CoreRender",1));
|
((DivPlatformC64*)dispatch)->setCore(eng->getConfInt("c64CoreRender",1));
|
||||||
|
|
|
@ -37,6 +37,7 @@ bool DivInstrumentFM::operator==(const DivInstrumentFM& other) {
|
||||||
_C(ams2) &&
|
_C(ams2) &&
|
||||||
_C(ops) &&
|
_C(ops) &&
|
||||||
_C(opllPreset) &&
|
_C(opllPreset) &&
|
||||||
|
_C(block) &&
|
||||||
_C(fixedDrums) &&
|
_C(fixedDrums) &&
|
||||||
_C(kickFreq) &&
|
_C(kickFreq) &&
|
||||||
_C(snareHatFreq) &&
|
_C(snareHatFreq) &&
|
||||||
|
|
|
@ -100,9 +100,50 @@ short DivPlatformC64::runFakeFilter(unsigned char ch, int in) {
|
||||||
return CLAMP(fout,-32768,32767);
|
return CLAMP(fout,-32768,32767);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformC64::processDAC(int sRate) {
|
||||||
|
bool didWrite=false;
|
||||||
|
if (chan[3].sample>=0 && chan[3].sample<parent->song.sampleLen) {
|
||||||
|
chan[3].pcmPeriod-=chan[3].pcmRate*4;
|
||||||
|
while (chan[3].pcmPeriod<0) {
|
||||||
|
chan[3].pcmPeriod+=sRate;
|
||||||
|
DivSample* s=parent->getSample(chan[3].sample);
|
||||||
|
if (s!=NULL) {
|
||||||
|
if (chan[3].pcmPos<0 || chan[3].pcmPos>=(int)s->samples) {
|
||||||
|
chan[3].pcmOut=15;
|
||||||
|
didWrite=true;
|
||||||
|
} else {
|
||||||
|
chan[3].pcmOut=(0x80+s->data8[chan[3].pcmPos])>>4;
|
||||||
|
didWrite=true;
|
||||||
|
}
|
||||||
|
chan[3].pcmPos++;
|
||||||
|
|
||||||
|
if (s->isLoopable() && chan[3].pcmPos>=s->loopEnd) {
|
||||||
|
chan[3].pcmPos=s->loopStart;
|
||||||
|
} else if (chan[3].pcmPos>=(int)s->samples) {
|
||||||
|
chan[3].sample=-1;
|
||||||
|
didWrite=true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
chan[3].sample=-1;
|
||||||
|
didWrite=true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (didWrite && !isMuted[3]) updateVolume();
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformC64::acquire(short** buf, size_t len) {
|
void DivPlatformC64::acquire(short** buf, size_t len) {
|
||||||
int dcOff=(sidCore)?0:sid->get_dc(0);
|
int dcOff=(sidCore)?0:sid->get_dc(0);
|
||||||
for (size_t i=0; i<len; i++) {
|
for (size_t i=0; i<len; i++) {
|
||||||
|
// run PCM
|
||||||
|
pcmCycle+=lineRate;
|
||||||
|
while (pcmCycle>=(rate*2)) {
|
||||||
|
pcmCycle-=(rate*2);
|
||||||
|
processDAC(lineRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
// the rest
|
||||||
if (!writes.empty()) {
|
if (!writes.empty()) {
|
||||||
QueuedWrite w=writes.front();
|
QueuedWrite w=writes.front();
|
||||||
if (sidCore==2) {
|
if (sidCore==2) {
|
||||||
|
@ -149,7 +190,15 @@ void DivPlatformC64::updateFilter() {
|
||||||
rWrite(0x15,filtCut&7);
|
rWrite(0x15,filtCut&7);
|
||||||
rWrite(0x16,filtCut>>3);
|
rWrite(0x16,filtCut>>3);
|
||||||
rWrite(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(int)(chan[0].filter));
|
rWrite(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(int)(chan[0].filter));
|
||||||
|
updateVolume();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DivPlatformC64::updateVolume() {
|
||||||
|
if (chan[3].sample>=0 && !isMuted[3]) {
|
||||||
|
rWrite(0x18,(filtControl<<4)|chan[3].pcmOut);
|
||||||
|
} else {
|
||||||
rWrite(0x18,(filtControl<<4)|vol);
|
rWrite(0x18,(filtControl<<4)|vol);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::tick(bool sysTick) {
|
void DivPlatformC64::tick(bool sysTick) {
|
||||||
|
@ -308,14 +357,64 @@ void DivPlatformC64::tick(bool sysTick) {
|
||||||
chan[i].freqChanged=false;
|
chan[i].freqChanged=false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chan[3].freqChanged) {
|
||||||
|
int i=3;
|
||||||
|
double off=1.0;
|
||||||
|
if (chan[i].sample>=0 && chan[i].sample<parent->song.sampleLen) {
|
||||||
|
DivSample* s=parent->getSample(chan[i].sample);
|
||||||
|
if (s->centerRate<1) {
|
||||||
|
off=1.0;
|
||||||
|
} else {
|
||||||
|
off=(double)s->centerRate/8363.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chan[i].pcmRate=off*parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,false,2,chan[i].pitch2,2,1);
|
||||||
|
if (dumpWrites) addWrite(0xffff0001+(i<<8),chan[i].pcmRate);
|
||||||
|
}
|
||||||
|
|
||||||
if (willUpdateFilter) updateFilter();
|
if (willUpdateFilter) updateFilter();
|
||||||
}
|
}
|
||||||
|
|
||||||
int DivPlatformC64::dispatch(DivCommand c) {
|
int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
if (c.chan>2) return 0;
|
if (c.chan>3) return 0;
|
||||||
switch (c.cmd) {
|
switch (c.cmd) {
|
||||||
case DIV_CMD_NOTE_ON: {
|
case DIV_CMD_NOTE_ON: {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||||
|
|
||||||
|
if (chan[c.chan].pcm || c.chan>2) {
|
||||||
|
if (skipRegisterWrites) break;
|
||||||
|
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;
|
||||||
|
} else if (chan[c.chan].sampleNote!=DIV_NOTE_NULL) {
|
||||||
|
chan[c.chan].sample=ins->amiga.getSample(chan[c.chan].sampleNote);
|
||||||
|
c.value=ins->amiga.getFreq(chan[c.chan].sampleNote);
|
||||||
|
}
|
||||||
|
if (chan[c.chan].sample<0 || chan[c.chan].sample>=parent->song.sampleLen) {
|
||||||
|
chan[c.chan].sample=-1;
|
||||||
|
if (dumpWrites) addWrite(0xffff0002+(c.chan<<8),0);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (chan[c.chan].setPos) {
|
||||||
|
chan[c.chan].setPos=false;
|
||||||
|
} else {
|
||||||
|
chan[c.chan].pcmPos=0;
|
||||||
|
}
|
||||||
|
chan[c.chan].pcmPeriod=0;
|
||||||
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
|
chan[c.chan].baseFreq=parent->calcBaseFreq(2,1,c.value,false);
|
||||||
|
chan[c.chan].freqChanged=true;
|
||||||
|
chan[c.chan].note=c.value;
|
||||||
|
}
|
||||||
|
chan[c.chan].active=true;
|
||||||
|
chan[c.chan].macroInit(ins);
|
||||||
|
chan[c.chan].keyOn=true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (c.value!=DIV_NOTE_NULL) {
|
if (c.value!=DIV_NOTE_NULL) {
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value);
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
|
@ -364,18 +463,22 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
|
chan[c.chan].sample=-1;
|
||||||
|
chan[c.chan].pcm=false;
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].keyOn=false;
|
chan[c.chan].keyOn=false;
|
||||||
//chan[c.chan].macroInit(NULL);
|
//chan[c.chan].macroInit(NULL);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_OFF_ENV:
|
case DIV_CMD_NOTE_OFF_ENV:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].keyOn=false;
|
chan[c.chan].keyOn=false;
|
||||||
chan[c.chan].std.release();
|
chan[c.chan].std.release();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_ENV_RELEASE:
|
case DIV_CMD_ENV_RELEASE:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].std.release();
|
chan[c.chan].std.release();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_INSTRUMENT:
|
case DIV_CMD_INSTRUMENT:
|
||||||
|
@ -385,6 +488,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_VOLUME:
|
case DIV_CMD_VOLUME:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (chan[c.chan].vol!=c.value) {
|
if (chan[c.chan].vol!=c.value) {
|
||||||
chan[c.chan].vol=c.value;
|
chan[c.chan].vol=c.value;
|
||||||
if (!chan[c.chan].std.vol.has) {
|
if (!chan[c.chan].std.vol.has) {
|
||||||
|
@ -405,6 +509,9 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_NOTE_PORTA: {
|
case DIV_CMD_NOTE_PORTA: {
|
||||||
int destFreq=NOTE_FREQUENCY(c.value2);
|
int destFreq=NOTE_FREQUENCY(c.value2);
|
||||||
|
if (c.chan>2 || chan[c.chan].pcm) {
|
||||||
|
destFreq=parent->calcBaseFreq(2,1,c.value2+chan[c.chan].sampleNoteDelta,false);
|
||||||
|
}
|
||||||
bool return2=false;
|
bool return2=false;
|
||||||
if (destFreq>chan[c.chan].baseFreq) {
|
if (destFreq>chan[c.chan].baseFreq) {
|
||||||
chan[c.chan].baseFreq+=c.value;
|
chan[c.chan].baseFreq+=c.value;
|
||||||
|
@ -427,21 +534,28 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_STD_NOISE_MODE:
|
case DIV_CMD_STD_NOISE_MODE:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].duty=(c.value*4095)/100;
|
chan[c.chan].duty=(c.value*4095)/100;
|
||||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_FINE_DUTY:
|
case DIV_CMD_C64_FINE_DUTY:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].duty=c.value;
|
chan[c.chan].duty=c.value;
|
||||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_WAVE:
|
case DIV_CMD_WAVE:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].wave=c.value;
|
chan[c.chan].wave=c.value;
|
||||||
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active && chan[c.chan].gate));
|
rWrite(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].test<<3)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|(int)(chan[c.chan].active && chan[c.chan].gate));
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
|
if (c.chan>2 || chan[c.chan].pcm) {
|
||||||
|
chan[c.chan].baseFreq=parent->calcBaseFreq(2,1,c.value+chan[c.chan].sampleNoteDelta+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)),false);
|
||||||
|
} else {
|
||||||
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
|
chan[c.chan].baseFreq=NOTE_FREQUENCY(c.value+((HACKY_LEGATO_MESS)?(chan[c.chan].std.arp.val):(0)));
|
||||||
|
}
|
||||||
chan[c.chan].freqChanged=true;
|
chan[c.chan].freqChanged=true;
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
break;
|
break;
|
||||||
|
@ -456,36 +570,44 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].inPorta=c.value;
|
chan[c.chan].inPorta=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_PRE_NOTE:
|
case DIV_CMD_PRE_NOTE:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (resetTime) chan[c.chan].testWhen=c.value-resetTime+1;
|
if (resetTime) chan[c.chan].testWhen=c.value-resetTime+1;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_GET_VOLMAX:
|
case DIV_CMD_GET_VOLMAX:
|
||||||
return 15;
|
return 15;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_CUTOFF:
|
case DIV_CMD_C64_CUTOFF:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (c.value>100) c.value=100;
|
if (c.value>100) c.value=100;
|
||||||
filtCut=(c.value+2)*2047/102;
|
filtCut=(c.value+2)*2047/102;
|
||||||
updateFilter();
|
updateFilter();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_FINE_CUTOFF:
|
case DIV_CMD_C64_FINE_CUTOFF:
|
||||||
|
if (c.chan>2) break;
|
||||||
filtCut=c.value;
|
filtCut=c.value;
|
||||||
updateFilter();
|
updateFilter();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_RESONANCE:
|
case DIV_CMD_C64_RESONANCE:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (c.value>15) c.value=15;
|
if (c.value>15) c.value=15;
|
||||||
filtRes=c.value;
|
filtRes=c.value;
|
||||||
updateFilter();
|
updateFilter();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_FILTER_MODE:
|
case DIV_CMD_C64_FILTER_MODE:
|
||||||
|
if (c.chan>2) break;
|
||||||
filtControl=c.value&7;
|
filtControl=c.value&7;
|
||||||
updateFilter();
|
updateFilter();
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_RESET_TIME:
|
case DIV_CMD_C64_RESET_TIME:
|
||||||
|
if (c.chan>2) break;
|
||||||
resetTime=c.value;
|
resetTime=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_RESET_MASK:
|
case DIV_CMD_C64_RESET_MASK:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].resetMask=c.value;
|
chan[c.chan].resetMask=c.value;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_FILTER_RESET:
|
case DIV_CMD_C64_FILTER_RESET:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (c.value&15) {
|
if (c.value&15) {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||||
if (ins->c64.initFilter) {
|
if (ins->c64.initFilter) {
|
||||||
|
@ -496,6 +618,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].resetFilter=c.value>>4;
|
chan[c.chan].resetFilter=c.value>>4;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_DUTY_RESET:
|
case DIV_CMD_C64_DUTY_RESET:
|
||||||
|
if (c.chan>2) break;
|
||||||
if (c.value&15) {
|
if (c.value&15) {
|
||||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins,DIV_INS_C64);
|
||||||
chan[c.chan].duty=ins->c64.duty;
|
chan[c.chan].duty=ins->c64.duty;
|
||||||
|
@ -505,6 +628,7 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].resetDuty=c.value>>4;
|
chan[c.chan].resetDuty=c.value>>4;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_EXTENDED:
|
case DIV_CMD_C64_EXTENDED:
|
||||||
|
if (c.chan>2) break;
|
||||||
switch (c.value>>4) {
|
switch (c.value>>4) {
|
||||||
case 0:
|
case 0:
|
||||||
chan[c.chan].attack=c.value&15;
|
chan[c.chan].attack=c.value&15;
|
||||||
|
@ -545,19 +669,23 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_AD:
|
case DIV_CMD_C64_AD:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].attack=c.value>>4;
|
chan[c.chan].attack=c.value>>4;
|
||||||
chan[c.chan].decay=c.value&15;
|
chan[c.chan].decay=c.value&15;
|
||||||
rWrite(c.chan*7+5,(chan[c.chan].attack<<4)|(chan[c.chan].decay));
|
rWrite(c.chan*7+5,(chan[c.chan].attack<<4)|(chan[c.chan].decay));
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_SR:
|
case DIV_CMD_C64_SR:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].sustain=c.value>>4;
|
chan[c.chan].sustain=c.value>>4;
|
||||||
chan[c.chan].release=c.value&15;
|
chan[c.chan].release=c.value&15;
|
||||||
rWrite(c.chan*7+6,(chan[c.chan].sustain<<4)|(chan[c.chan].release));
|
rWrite(c.chan*7+6,(chan[c.chan].sustain<<4)|(chan[c.chan].release));
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_PW_SLIDE:
|
case DIV_CMD_C64_PW_SLIDE:
|
||||||
|
if (c.chan>2) break;
|
||||||
chan[c.chan].pw_slide=c.value*c.value2;
|
chan[c.chan].pw_slide=c.value*c.value2;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_C64_CUTOFF_SLIDE:
|
case DIV_CMD_C64_CUTOFF_SLIDE:
|
||||||
|
if (c.chan>2) break;
|
||||||
cutoff_slide=c.value*c.value2;
|
cutoff_slide=c.value*c.value2;
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_MACRO_OFF:
|
case DIV_CMD_MACRO_OFF:
|
||||||
|
@ -589,10 +717,11 @@ void DivPlatformC64::muteChannel(int ch, bool mute) {
|
||||||
} else {
|
} else {
|
||||||
sid->set_is_muted(ch,mute);
|
sid->set_is_muted(ch,mute);
|
||||||
}
|
}
|
||||||
|
if (ch==3) updateVolume();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::forceIns() {
|
void DivPlatformC64::forceIns() {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
chan[i].testWhen=0;
|
chan[i].testWhen=0;
|
||||||
if (chan[i].active) {
|
if (chan[i].active) {
|
||||||
|
@ -604,7 +733,7 @@ void DivPlatformC64::forceIns() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::notifyInsChange(int ins) {
|
void DivPlatformC64::notifyInsChange(int ins) {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
if (chan[i].ins==ins) {
|
if (chan[i].ins==ins) {
|
||||||
chan[i].insChanged=true;
|
chan[i].insChanged=true;
|
||||||
}
|
}
|
||||||
|
@ -612,7 +741,7 @@ void DivPlatformC64::notifyInsChange(int ins) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::notifyInsDeletion(void* ins) {
|
void DivPlatformC64::notifyInsDeletion(void* ins) {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
chan[i].std.notifyInsDeletion((DivInstrument*)ins);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -690,7 +819,7 @@ float DivPlatformC64::getPostAmp() {
|
||||||
|
|
||||||
void DivPlatformC64::reset() {
|
void DivPlatformC64::reset() {
|
||||||
while (!writes.empty()) writes.pop();
|
while (!writes.empty()) writes.pop();
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
chan[i]=DivPlatformC64::Channel();
|
chan[i]=DivPlatformC64::Channel();
|
||||||
chan[i].std.setEngine(parent);
|
chan[i].std.setEngine(parent);
|
||||||
fakeLow[i]=0;
|
fakeLow[i]=0;
|
||||||
|
@ -699,6 +828,7 @@ void DivPlatformC64::reset() {
|
||||||
}
|
}
|
||||||
|
|
||||||
cutoff_slide=0;
|
cutoff_slide=0;
|
||||||
|
pcmCycle=0;
|
||||||
|
|
||||||
if (sidCore==2) {
|
if (sidCore==2) {
|
||||||
dSID_init(sid_d,chipClock,rate,sidIs6581?6581:8580,needInitTables);
|
dSID_init(sid_d,chipClock,rate,sidIs6581?6581:8580,needInitTables);
|
||||||
|
@ -761,18 +891,21 @@ void DivPlatformC64::setFlags(const DivConfig& flags) {
|
||||||
switch (flags.getInt("clockSel",0)) {
|
switch (flags.getInt("clockSel",0)) {
|
||||||
case 0x0: // NTSC C64
|
case 0x0: // NTSC C64
|
||||||
chipClock=COLOR_NTSC*2.0/7.0;
|
chipClock=COLOR_NTSC*2.0/7.0;
|
||||||
|
lineRate=15734;
|
||||||
break;
|
break;
|
||||||
case 0x1: // PAL C64
|
case 0x1: // PAL C64
|
||||||
chipClock=COLOR_PAL*2.0/9.0;
|
chipClock=COLOR_PAL*2.0/9.0;
|
||||||
|
lineRate=15625;
|
||||||
break;
|
break;
|
||||||
case 0x2: // SSI 2001
|
case 0x2: // SSI 2001
|
||||||
default:
|
default:
|
||||||
chipClock=14318180.0/16.0;
|
chipClock=14318180.0/16.0;
|
||||||
|
lineRate=15734;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CHECK_CUSTOM_CLOCK;
|
CHECK_CUSTOM_CLOCK;
|
||||||
rate=chipClock;
|
rate=chipClock;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
oscBuf[i]->rate=rate/16;
|
oscBuf[i]->rate=rate/16;
|
||||||
}
|
}
|
||||||
if (sidCore>0) {
|
if (sidCore>0) {
|
||||||
|
@ -839,7 +972,7 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfi
|
||||||
skipRegisterWrites=false;
|
skipRegisterWrites=false;
|
||||||
needInitTables=true;
|
needInitTables=true;
|
||||||
writeOscBuf=0;
|
writeOscBuf=0;
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
isMuted[i]=false;
|
isMuted[i]=false;
|
||||||
oscBuf[i]=new DivDispatchOscBuffer;
|
oscBuf[i]=new DivDispatchOscBuffer;
|
||||||
}
|
}
|
||||||
|
@ -884,7 +1017,7 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, const DivConfi
|
||||||
}
|
}
|
||||||
|
|
||||||
void DivPlatformC64::quit() {
|
void DivPlatformC64::quit() {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<4; i++) {
|
||||||
delete oscBuf[i];
|
delete oscBuf[i];
|
||||||
}
|
}
|
||||||
if (sid!=NULL) delete sid;
|
if (sid!=NULL) delete sid;
|
||||||
|
|
|
@ -33,8 +33,8 @@
|
||||||
class DivPlatformC64: public DivDispatch {
|
class DivPlatformC64: public DivDispatch {
|
||||||
struct Channel: public SharedChannel<signed char> {
|
struct Channel: public SharedChannel<signed char> {
|
||||||
int prevFreq, testWhen;
|
int prevFreq, testWhen;
|
||||||
unsigned int audPos, pcmPos;
|
unsigned int audPos;
|
||||||
int sample, pcmPeriod, pcmRate, pcmOut;
|
int pcmPos, sample, pcmPeriod, pcmRate, pcmOut;
|
||||||
unsigned char sweep, wave, attack, decay, sustain, release;
|
unsigned char sweep, wave, attack, decay, sustain, release;
|
||||||
short duty;
|
short duty;
|
||||||
bool sweepChanged, filter, setPos, pcm;
|
bool sweepChanged, filter, setPos, pcm;
|
||||||
|
@ -49,7 +49,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
sample(-1),
|
sample(-1),
|
||||||
pcmPeriod(0),
|
pcmPeriod(0),
|
||||||
pcmRate(0),
|
pcmRate(0),
|
||||||
pcmOut(0),
|
pcmOut(15),
|
||||||
sweep(0),
|
sweep(0),
|
||||||
wave(0),
|
wave(0),
|
||||||
attack(0),
|
attack(0),
|
||||||
|
@ -88,6 +88,7 @@ class DivPlatformC64: public DivDispatch {
|
||||||
unsigned char writeOscBuf;
|
unsigned char writeOscBuf;
|
||||||
unsigned char sidCore;
|
unsigned char sidCore;
|
||||||
int filtCut, resetTime, initResetTime;
|
int filtCut, resetTime, initResetTime;
|
||||||
|
int pcmCycle, lineRate;
|
||||||
short cutoff_slide;
|
short cutoff_slide;
|
||||||
|
|
||||||
bool keyPriority, sidIs6581, needInitTables, no1EUpdate, multiplyRel, macroRace;
|
bool keyPriority, sidIs6581, needInitTables, no1EUpdate, multiplyRel, macroRace;
|
||||||
|
@ -105,10 +106,12 @@ class DivPlatformC64: public DivDispatch {
|
||||||
|
|
||||||
inline short runFakeFilter(unsigned char ch, int in);
|
inline short runFakeFilter(unsigned char ch, int in);
|
||||||
|
|
||||||
|
void processDAC(int sRate);
|
||||||
void acquire_classic(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire_classic(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
void acquire_fp(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire_fp(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
|
|
||||||
void updateFilter();
|
void updateFilter();
|
||||||
|
void updateVolume();
|
||||||
public:
|
public:
|
||||||
void acquire(short** buf, size_t len);
|
void acquire(short** buf, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
|
|
|
@ -145,6 +145,7 @@ enum DivSystem {
|
||||||
DIV_SYSTEM_SUPERVISION,
|
DIV_SYSTEM_SUPERVISION,
|
||||||
DIV_SYSTEM_UPD1771C,
|
DIV_SYSTEM_UPD1771C,
|
||||||
DIV_SYSTEM_SID3,
|
DIV_SYSTEM_SID3,
|
||||||
|
DIV_SYSTEM_C64_PCM,
|
||||||
|
|
||||||
DIV_SYSTEM_MAX
|
DIV_SYSTEM_MAX
|
||||||
};
|
};
|
||||||
|
|
|
@ -2316,6 +2316,18 @@ void DivEngine::registerSystems() {
|
||||||
SID3PostEffectHandlerMap
|
SID3PostEffectHandlerMap
|
||||||
);
|
);
|
||||||
|
|
||||||
|
sysDefs[DIV_SYSTEM_C64_PCM]=new DivSysDef(
|
||||||
|
_("Commodore 64 (SID 6581) with software PCM"), NULL, 0xe2, 0, 4, false, true, 0, false, (1U<<DIV_SAMPLE_DEPTH_8BIT)|(1U<<DIV_SAMPLE_DEPTH_16BIT), 0, 0,
|
||||||
|
_("the 6581 had a quirk which allowed playback of 4-bit samples by writing PCM data to the volume register."),
|
||||||
|
{_("Channel 1"), _("Channel 2"), _("Channel 3"), _("PCM")},
|
||||||
|
{"CH1", "CH2", "CH3", "P"},
|
||||||
|
{DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_NOISE, DIV_CH_PCM},
|
||||||
|
{DIV_INS_C64, DIV_INS_C64, DIV_INS_C64, DIV_INS_AMIGA},
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
c64PostEffectHandlerMap
|
||||||
|
);
|
||||||
|
|
||||||
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
sysDefs[DIV_SYSTEM_DUMMY]=new DivSysDef(
|
||||||
_("Dummy System"), NULL, 0xfd, 0, 8, false, true, 0, false, 0, 0, 0,
|
_("Dummy System"), NULL, 0xfd, 0, 8, false, true, 0, false, 0, 0, 0,
|
||||||
_("this is a system designed for testing purposes."),
|
_("this is a system designed for testing purposes."),
|
||||||
|
|
|
@ -1228,6 +1228,7 @@ const int availableSystems[]={
|
||||||
DIV_SYSTEM_NES,
|
DIV_SYSTEM_NES,
|
||||||
DIV_SYSTEM_C64_8580,
|
DIV_SYSTEM_C64_8580,
|
||||||
DIV_SYSTEM_C64_6581,
|
DIV_SYSTEM_C64_6581,
|
||||||
|
DIV_SYSTEM_C64_PCM,
|
||||||
DIV_SYSTEM_YM2151,
|
DIV_SYSTEM_YM2151,
|
||||||
DIV_SYSTEM_SEGAPCM,
|
DIV_SYSTEM_SEGAPCM,
|
||||||
DIV_SYSTEM_SEGAPCM_COMPAT,
|
DIV_SYSTEM_SEGAPCM_COMPAT,
|
||||||
|
@ -1402,6 +1403,7 @@ const int chipsSpecial[]={
|
||||||
DIV_SYSTEM_NES,
|
DIV_SYSTEM_NES,
|
||||||
DIV_SYSTEM_C64_8580,
|
DIV_SYSTEM_C64_8580,
|
||||||
DIV_SYSTEM_C64_6581,
|
DIV_SYSTEM_C64_6581,
|
||||||
|
DIV_SYSTEM_C64_PCM,
|
||||||
DIV_SYSTEM_SFX_BEEPER,
|
DIV_SYSTEM_SFX_BEEPER,
|
||||||
DIV_SYSTEM_SFX_BEEPER_QUADTONE,
|
DIV_SYSTEM_SFX_BEEPER_QUADTONE,
|
||||||
DIV_SYSTEM_DUMMY,
|
DIV_SYSTEM_DUMMY,
|
||||||
|
|
|
@ -680,7 +680,8 @@ bool FurnaceGUI::drawSysConf(int chan, int sysPos, DivSystem type, DivConfig& fl
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_SYSTEM_C64_8580:
|
case DIV_SYSTEM_C64_8580:
|
||||||
case DIV_SYSTEM_C64_6581: {
|
case DIV_SYSTEM_C64_6581:
|
||||||
|
case DIV_SYSTEM_C64_PCM: {
|
||||||
int clockSel=flags.getInt("clockSel",0);
|
int clockSel=flags.getInt("clockSel",0);
|
||||||
bool keyPriority=flags.getBool("keyPriority",true);
|
bool keyPriority=flags.getBool("keyPriority",true);
|
||||||
bool no1EUpdate=flags.getBool("no1EUpdate",false);
|
bool no1EUpdate=flags.getBool("no1EUpdate",false);
|
||||||
|
|
Loading…
Reference in a new issue