C64: finish it all
all modules play correctly, bar: - motherfunksignal (almost) - filters are a bit weird
This commit is contained in:
parent
c26bb511d7
commit
3ee761fc87
|
@ -43,6 +43,15 @@ enum DivDispatchCmds {
|
||||||
DIV_CMD_PCE_LFO_MODE,
|
DIV_CMD_PCE_LFO_MODE,
|
||||||
DIV_CMD_PCE_LFO_SPEED,
|
DIV_CMD_PCE_LFO_SPEED,
|
||||||
|
|
||||||
|
DIV_CMD_C64_CUTOFF,
|
||||||
|
DIV_CMD_C64_RESONANCE,
|
||||||
|
DIV_CMD_C64_FILTER_MODE,
|
||||||
|
DIV_CMD_C64_RESET_TIME,
|
||||||
|
DIV_CMD_C64_RESET_MASK,
|
||||||
|
DIV_CMD_C64_FILTER_RESET,
|
||||||
|
DIV_CMD_C64_DUTY_RESET,
|
||||||
|
DIV_CMD_C64_EXTENDED,
|
||||||
|
|
||||||
DIV_ALWAYS_SET_VOLUME,
|
DIV_ALWAYS_SET_VOLUME,
|
||||||
|
|
||||||
DIV_CMD_MAX
|
DIV_CMD_MAX
|
||||||
|
@ -90,6 +99,7 @@ class DivDispatch {
|
||||||
virtual void tick();
|
virtual void tick();
|
||||||
|
|
||||||
virtual bool isStereo();
|
virtual bool isStereo();
|
||||||
|
virtual bool keyOffAffectsArp();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* initialize this DivDispatch.
|
* initialize this DivDispatch.
|
||||||
|
|
|
@ -484,8 +484,8 @@ bool DivEngine::load(void* f, size_t slen) {
|
||||||
ins->c64.res=reader.readC();
|
ins->c64.res=reader.readC();
|
||||||
ins->c64.cut=reader.readC();
|
ins->c64.cut=reader.readC();
|
||||||
ins->c64.hp=reader.readC();
|
ins->c64.hp=reader.readC();
|
||||||
ins->c64.lp=reader.readC();
|
|
||||||
ins->c64.bp=reader.readC();
|
ins->c64.bp=reader.readC();
|
||||||
|
ins->c64.lp=reader.readC();
|
||||||
ins->c64.ch3off=reader.readC();
|
ins->c64.ch3off=reader.readC();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ void DivMacroInt::next() {
|
||||||
hadVol=hasVol;
|
hadVol=hasVol;
|
||||||
if (hasVol) {
|
if (hasVol) {
|
||||||
vol=ins->std.volMacro[volPos++];
|
vol=ins->std.volMacro[volPos++];
|
||||||
if (volPos>=ins->std.volMacroLen && ins->std.volMacroLoop<ins->std.volMacroLen) {
|
if (volPos>=ins->std.volMacroLen) {
|
||||||
if (ins->std.volMacroLoop>=0) {
|
if (ins->std.volMacroLoop<ins->std.volMacroLen && ins->std.volMacroLoop>=0) {
|
||||||
volPos=ins->std.volMacroLoop;
|
volPos=ins->std.volMacroLoop;
|
||||||
} else {
|
} else {
|
||||||
hasVol=false;
|
hasVol=false;
|
||||||
|
|
|
@ -14,6 +14,10 @@ bool DivDispatch::isStereo() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivDispatch::keyOffAffectsArp() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
int DivDispatch::init(DivEngine* p, int channels, int sugRate) {
|
int DivDispatch::init(DivEngine* p, int channels, int sugRate) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,13 +11,27 @@ void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DivPlatformC64::updateFilter() {
|
||||||
|
sid.write(0x15,filtCut&7);
|
||||||
|
sid.write(0x16,filtCut>>3);
|
||||||
|
sid.write(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(chan[0].filter));
|
||||||
|
sid.write(0x18,(filtControl<<4)|vol);
|
||||||
|
}
|
||||||
|
|
||||||
void DivPlatformC64::tick() {
|
void DivPlatformC64::tick() {
|
||||||
for (int i=0; i<3; i++) {
|
for (int i=0; i<3; i++) {
|
||||||
chan[i].std.next();
|
chan[i].std.next();
|
||||||
if (chan[i].std.hadVol) {
|
if (chan[i].std.hadVol) {
|
||||||
// ok, why are the volumes like that?
|
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||||
chan[i].outVol=chan[i].std.vol-(15-chan[i].vol);
|
if (ins->c64.volIsCutoff) {
|
||||||
if (chan[i].outVol<0) chan[i].outVol=0;
|
filtCut-=((signed char)chan[i].std.vol-18)*7;
|
||||||
|
if (filtCut>2047) filtCut=2047;
|
||||||
|
if (filtCut<0) filtCut=0;
|
||||||
|
updateFilter();
|
||||||
|
} else {
|
||||||
|
vol=chan[i].std.vol;
|
||||||
|
updateFilter();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (chan[i].std.hadArp) {
|
if (chan[i].std.hadArp) {
|
||||||
if (i==3) { // noise
|
if (i==3) { // noise
|
||||||
|
@ -33,7 +47,7 @@ void DivPlatformC64::tick() {
|
||||||
if (chan[i].std.arpMode) {
|
if (chan[i].std.arpMode) {
|
||||||
chan[i].baseFreq=round(FREQ_BASE*pow(2.0f,((float)(chan[i].std.arp)/12.0f)));
|
chan[i].baseFreq=round(FREQ_BASE*pow(2.0f,((float)(chan[i].std.arp)/12.0f)));
|
||||||
} else {
|
} else {
|
||||||
chan[i].baseFreq=round(FREQ_BASE*pow(2.0f,((float)(chan[i].note+chan[i].std.arp-12)/12.0f)));
|
chan[i].baseFreq=round(FREQ_BASE*pow(2.0f,((float)(chan[i].note+(signed char)chan[i].std.arp-12)/12.0f)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,30 +63,33 @@ void DivPlatformC64::tick() {
|
||||||
sid.write(i*7+2,chan[i].duty&0xff);
|
sid.write(i*7+2,chan[i].duty&0xff);
|
||||||
sid.write(i*7+3,chan[i].duty>>8);
|
sid.write(i*7+3,chan[i].duty>>8);
|
||||||
}
|
}
|
||||||
if (chan[i].std.hadWave) {
|
|
||||||
chan[i].wave=chan[i].std.wave;
|
|
||||||
sid.write(i*7+4,(chan[i].wave<<4)|chan[i].active);
|
|
||||||
}
|
|
||||||
if (chan[i].testWhen>0) {
|
if (chan[i].testWhen>0) {
|
||||||
if (--chan[i].testWhen<1) {
|
if (--chan[i].testWhen<1) {
|
||||||
|
if (!chan[i].resetMask) {
|
||||||
sid.write(i*7+5,0);
|
sid.write(i*7+5,0);
|
||||||
sid.write(i*7+6,0);
|
sid.write(i*7+6,0);
|
||||||
sid.write(i*7+4,(chan[i].wave<<4)|8);
|
sid.write(i*7+4,(chan[i].wave<<4)|8|(chan[i].ring<<2)|(chan[i].sync<<1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (chan[i].std.hadWave) {
|
||||||
|
chan[i].wave=chan[i].std.wave;
|
||||||
|
sid.write(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|chan[i].active);
|
||||||
|
}
|
||||||
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) {
|
||||||
DivInstrument* ins=parent->getIns(chan[i].ins);
|
DivInstrument* ins=parent->getIns(chan[i].ins);
|
||||||
chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE+chan[i].pitch))/ONE_SEMITONE;
|
chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE+chan[i].pitch))/ONE_SEMITONE;
|
||||||
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
if (chan[i].freq>0xffff) chan[i].freq=0xffff;
|
||||||
|
if (chan[i].freq<0) chan[i].freq=0;
|
||||||
if (chan[i].keyOn) {
|
if (chan[i].keyOn) {
|
||||||
sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d));
|
sid.write(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||||
sid.write(i*7+6,(ins->c64.s<<4)|(ins->c64.r));
|
sid.write(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||||
sid.write(i*7+4,(chan[i].wave<<4)|1);
|
sid.write(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
||||||
}
|
}
|
||||||
if (chan[i].keyOff) {
|
if (chan[i].keyOff) {
|
||||||
sid.write(i*7+5,(ins->c64.a<<4)|(ins->c64.d));
|
sid.write(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||||
sid.write(i*7+6,(ins->c64.s<<4)|(ins->c64.r));
|
sid.write(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||||
sid.write(i*7+4,(chan[i].wave<<4)|0);
|
sid.write(i*7+4,(chan[i].wave<<4)|(chan[i].ring<<2)|(chan[i].sync<<1)|0);
|
||||||
}
|
}
|
||||||
sid.write(i*7,chan[i].freq&0xff);
|
sid.write(i*7,chan[i].freq&0xff);
|
||||||
sid.write(i*7+1,chan[i].freq>>8);
|
sid.write(i*7+1,chan[i].freq>>8);
|
||||||
|
@ -92,20 +109,43 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].note=c.value;
|
chan[c.chan].note=c.value;
|
||||||
chan[c.chan].active=true;
|
chan[c.chan].active=true;
|
||||||
chan[c.chan].keyOn=true;
|
chan[c.chan].keyOn=true;
|
||||||
|
if (chan[c.chan].insChanged || chan[c.chan].resetDuty || ins->std.waveMacroLen>0) {
|
||||||
chan[c.chan].duty=(ins->c64.duty*4095)/100;
|
chan[c.chan].duty=(ins->c64.duty*4095)/100;
|
||||||
sid.write(c.chan*7+2,chan[c.chan].duty&0xff);
|
sid.write(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
sid.write(c.chan*7+3,chan[c.chan].duty>>8);
|
sid.write(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
|
}
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
chan[c.chan].wave=(ins->c64.noiseOn<<3)|(ins->c64.pulseOn<<2)|(ins->c64.sawOn<<1)|(ins->c64.triOn);
|
chan[c.chan].wave=(ins->c64.noiseOn<<3)|(ins->c64.pulseOn<<2)|(ins->c64.sawOn<<1)|(ins->c64.triOn);
|
||||||
|
chan[c.chan].attack=ins->c64.a;
|
||||||
|
chan[c.chan].decay=ins->c64.d;
|
||||||
|
chan[c.chan].sustain=ins->c64.s;
|
||||||
|
chan[c.chan].release=ins->c64.r;
|
||||||
|
chan[c.chan].ring=ins->c64.ringMod;
|
||||||
|
chan[c.chan].sync=ins->c64.oscSync;
|
||||||
|
}
|
||||||
|
if (chan[c.chan].insChanged || chan[c.chan].resetFilter) {
|
||||||
|
chan[c.chan].filter=ins->c64.toFilter;
|
||||||
|
if (ins->c64.initFilter) {
|
||||||
|
filtCut=ins->c64.cut*2047/100;
|
||||||
|
filtRes=ins->c64.res;
|
||||||
|
filtControl=ins->c64.lp|(ins->c64.bp<<1)|(ins->c64.hp<<2)|(ins->c64.ch3off<<3);
|
||||||
|
updateFilter();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chan[c.chan].insChanged) {
|
||||||
|
chan[c.chan].insChanged=false;
|
||||||
|
}
|
||||||
chan[c.chan].std.init(ins);
|
chan[c.chan].std.init(ins);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_NOTE_OFF:
|
case DIV_CMD_NOTE_OFF:
|
||||||
chan[c.chan].active=false;
|
chan[c.chan].active=false;
|
||||||
chan[c.chan].keyOff=true;
|
chan[c.chan].keyOff=true;
|
||||||
chan[c.chan].std.init(NULL);
|
//chan[c.chan].std.init(NULL);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_INSTRUMENT:
|
case DIV_CMD_INSTRUMENT:
|
||||||
if (chan[c.chan].ins!=c.value) {
|
if (chan[c.chan].ins!=c.value) {
|
||||||
|
chan[c.chan].insChanged=true;
|
||||||
chan[c.chan].ins=c.value;
|
chan[c.chan].ins=c.value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -114,10 +154,11 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
chan[c.chan].vol=c.value;
|
chan[c.chan].vol=c.value;
|
||||||
if (!chan[c.chan].std.hasVol) {
|
if (!chan[c.chan].std.hasVol) {
|
||||||
chan[c.chan].outVol=c.value;
|
chan[c.chan].outVol=c.value;
|
||||||
}
|
vol=chan[c.chan].outVol;
|
||||||
if (c.chan==2) {
|
|
||||||
} else {
|
} else {
|
||||||
|
vol=chan[c.chan].vol;
|
||||||
}
|
}
|
||||||
|
updateFilter();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_GET_VOLUME:
|
case DIV_CMD_GET_VOLUME:
|
||||||
|
@ -151,7 +192,13 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DIV_CMD_STD_NOISE_MODE:
|
case DIV_CMD_STD_NOISE_MODE:
|
||||||
chan[c.chan].duty=c.value;
|
chan[c.chan].duty=(c.value*4095)/100;
|
||||||
|
sid.write(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
|
sid.write(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
|
break;
|
||||||
|
case DIV_CMD_WAVE:
|
||||||
|
chan[c.chan].wave=c.value;
|
||||||
|
sid.write(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
||||||
break;
|
break;
|
||||||
case DIV_CMD_LEGATO:
|
case DIV_CMD_LEGATO:
|
||||||
chan[c.chan].baseFreq=round(FREQ_BASE*pow(2.0f,((float)c.value/12.0f)));
|
chan[c.chan].baseFreq=round(FREQ_BASE*pow(2.0f,((float)c.value/12.0f)));
|
||||||
|
@ -164,11 +211,76 @@ 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:
|
||||||
chan[c.chan].testWhen=c.value;
|
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:
|
||||||
|
if (c.value>100) c.value=100;
|
||||||
|
filtCut=c.value*2047/100;
|
||||||
|
updateFilter();
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_RESONANCE:
|
||||||
|
if (c.value>15) c.value=15;
|
||||||
|
filtRes=c.value;
|
||||||
|
updateFilter();
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_FILTER_MODE:
|
||||||
|
filtControl=c.value&7;
|
||||||
|
updateFilter();
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_RESET_TIME:
|
||||||
|
resetTime=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_RESET_MASK:
|
||||||
|
chan[c.chan].resetMask=c.value;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_FILTER_RESET:
|
||||||
|
if (c.value&15) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||||
|
filtCut=ins->c64.cut*2047/100;
|
||||||
|
updateFilter();
|
||||||
|
}
|
||||||
|
chan[c.chan].resetFilter=c.value>>4;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_DUTY_RESET:
|
||||||
|
if (c.value&15) {
|
||||||
|
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||||
|
chan[c.chan].duty=(ins->c64.duty*4095)/100;
|
||||||
|
sid.write(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||||
|
sid.write(c.chan*7+3,chan[c.chan].duty>>8);
|
||||||
|
}
|
||||||
|
chan[c.chan].resetDuty=c.value>>4;
|
||||||
|
break;
|
||||||
|
case DIV_CMD_C64_EXTENDED:
|
||||||
|
switch (c.value>>4) {
|
||||||
|
case 0:
|
||||||
|
chan[c.chan].attack=c.value&15;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
chan[c.chan].decay=c.value&15;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
chan[c.chan].sustain=c.value&15;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
chan[c.chan].release=c.value&15;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
chan[c.chan].ring=c.value;
|
||||||
|
sid.write(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
chan[c.chan].sync=c.value;
|
||||||
|
sid.write(c.chan*7+4,(chan[c.chan].wave<<4)|(chan[c.chan].ring<<2)|(chan[c.chan].sync<<1)|chan[c.chan].active);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
filtControl&=7;
|
||||||
|
filtControl|=(!!c.value)<<3;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
case DIV_ALWAYS_SET_VOLUME:
|
case DIV_ALWAYS_SET_VOLUME:
|
||||||
return 1;
|
return 1;
|
||||||
break;
|
break;
|
||||||
|
@ -194,5 +306,11 @@ int DivPlatformC64::init(DivEngine* p, int channels, int sugRate) {
|
||||||
|
|
||||||
sid.write(0x18,0x0f);
|
sid.write(0x18,0x0f);
|
||||||
|
|
||||||
|
filtControl=0;
|
||||||
|
filtRes=0;
|
||||||
|
filtCut=0;
|
||||||
|
resetTime=1;
|
||||||
|
vol=15;
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
|
|
||||||
class DivPlatformC64: public DivDispatch {
|
class DivPlatformC64: public DivDispatch {
|
||||||
struct Channel {
|
struct Channel {
|
||||||
int freq, baseFreq, pitch, prevFreq, testWhen;
|
int freq, baseFreq, pitch, prevFreq, testWhen, note;
|
||||||
unsigned char ins, note, sweep, wave;
|
unsigned char ins, sweep, wave, attack, decay, sustain, release;
|
||||||
short duty;
|
short duty;
|
||||||
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta;
|
bool active, insChanged, freqChanged, sweepChanged, keyOn, keyOff, inPorta, filter;
|
||||||
|
bool resetMask, resetFilter, resetDuty, ring, sync;
|
||||||
signed char vol, outVol;
|
signed char vol, outVol;
|
||||||
DivMacroInt std;
|
DivMacroInt std;
|
||||||
Channel():
|
Channel():
|
||||||
|
@ -19,10 +20,14 @@ class DivPlatformC64: public DivDispatch {
|
||||||
pitch(0),
|
pitch(0),
|
||||||
prevFreq(65535),
|
prevFreq(65535),
|
||||||
testWhen(0),
|
testWhen(0),
|
||||||
ins(-1),
|
|
||||||
note(0),
|
note(0),
|
||||||
|
ins(-1),
|
||||||
sweep(0),
|
sweep(0),
|
||||||
wave(0),
|
wave(0),
|
||||||
|
attack(0),
|
||||||
|
decay(0),
|
||||||
|
sustain(0),
|
||||||
|
release(0),
|
||||||
duty(0),
|
duty(0),
|
||||||
active(false),
|
active(false),
|
||||||
insChanged(true),
|
insChanged(true),
|
||||||
|
@ -31,13 +36,22 @@ class DivPlatformC64: public DivDispatch {
|
||||||
keyOn(false),
|
keyOn(false),
|
||||||
keyOff(false),
|
keyOff(false),
|
||||||
inPorta(false),
|
inPorta(false),
|
||||||
|
filter(false),
|
||||||
|
resetMask(false),
|
||||||
|
resetFilter(false),
|
||||||
|
resetDuty(false),
|
||||||
|
ring(false),
|
||||||
|
sync(false),
|
||||||
vol(15) {}
|
vol(15) {}
|
||||||
};
|
};
|
||||||
Channel chan[3];
|
Channel chan[3];
|
||||||
|
|
||||||
|
unsigned char filtControl, filtRes, vol;
|
||||||
|
int filtCut, resetTime;
|
||||||
|
|
||||||
SID sid;
|
SID sid;
|
||||||
|
|
||||||
void updateWave();
|
void updateFilter();
|
||||||
public:
|
public:
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
|
|
|
@ -270,6 +270,10 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivPlatformNES::keyOffAffectsArp() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate) {
|
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate) {
|
||||||
parent=p;
|
parent=p;
|
||||||
rate=1789773;
|
rate=1789773;
|
||||||
|
|
|
@ -39,6 +39,7 @@ class DivPlatformNES: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void tick();
|
void tick();
|
||||||
|
bool keyOffAffectsArp();
|
||||||
int init(DivEngine* parent, int channels, int sugRate);
|
int init(DivEngine* parent, int channels, int sugRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -254,6 +254,11 @@ bool DivPlatformPCE::isStereo() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivPlatformPCE::keyOffAffectsArp() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate) {
|
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate) {
|
||||||
parent=p;
|
parent=p;
|
||||||
rate=1789773;
|
rate=1789773;
|
||||||
|
|
|
@ -54,6 +54,7 @@ class DivPlatformPCE: public DivDispatch {
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void tick();
|
void tick();
|
||||||
bool isStereo();
|
bool isStereo();
|
||||||
|
bool keyOffAffectsArp();
|
||||||
int init(DivEngine* parent, int channels, int sugRate);
|
int init(DivEngine* parent, int channels, int sugRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -159,6 +159,10 @@ int DivPlatformSMS::dispatch(DivCommand c) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DivPlatformSMS::keyOffAffectsArp() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate) {
|
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate) {
|
||||||
parent=p;
|
parent=p;
|
||||||
rate=223722;
|
rate=223722;
|
||||||
|
|
|
@ -34,6 +34,7 @@ class DivPlatformSMS: public DivDispatch {
|
||||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||||
int dispatch(DivCommand c);
|
int dispatch(DivCommand c);
|
||||||
void tick();
|
void tick();
|
||||||
|
bool keyOffAffectsArp();
|
||||||
int init(DivEngine* parent, int channels, int sugRate);
|
int init(DivEngine* parent, int channels, int sugRate);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#include "dispatch.h"
|
||||||
#include "engine.h"
|
#include "engine.h"
|
||||||
|
|
||||||
void DivEngine::nextOrder() {
|
void DivEngine::nextOrder() {
|
||||||
|
@ -49,6 +50,15 @@ const char* cmdName[DIV_CMD_MAX]={
|
||||||
"PCE_LFO_MODE",
|
"PCE_LFO_MODE",
|
||||||
"PCE_LFO_SPEED",
|
"PCE_LFO_SPEED",
|
||||||
|
|
||||||
|
"C64_CUTOFF",
|
||||||
|
"C64_RESONANCE",
|
||||||
|
"C64_FILTER_MODE",
|
||||||
|
"C64_RESET_TIME",
|
||||||
|
"C64_RESET_MASK",
|
||||||
|
"C64_FILTER_RESET",
|
||||||
|
"C64_DUTY_RESET",
|
||||||
|
"C64_EXTENDED",
|
||||||
|
|
||||||
"ALWAYS_SET_VOLUME"
|
"ALWAYS_SET_VOLUME"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -199,6 +209,42 @@ bool DivEngine::perSystemPostEffect(int ch, unsigned char effect, unsigned char
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case DIV_SYSTEM_C64_6581:
|
||||||
|
case DIV_SYSTEM_C64_8580:
|
||||||
|
switch (effect) {
|
||||||
|
case 0x10: // select waveform
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_WAVE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x11: // cutoff
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_CUTOFF,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x12: // duty
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_STD_NOISE_MODE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x13: // resonance
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_RESONANCE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x14: // filter mode
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_FILTER_MODE,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x15: // reset time
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_RESET_TIME,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x1a: // reset mask
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_RESET_MASK,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x1b: // cutoff reset
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_FILTER_RESET,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x1c: // duty reset
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_DUTY_RESET,ch,effectVal));
|
||||||
|
break;
|
||||||
|
case 0x1e: // extended
|
||||||
|
dispatchCmd(DivCommand(DIV_CMD_C64_EXTENDED,ch,effectVal));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -229,7 +275,7 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
}
|
}
|
||||||
// note
|
// note
|
||||||
if (pat->data[whatRow][0]==100) {
|
if (pat->data[whatRow][0]==100) {
|
||||||
chan[i].note=-1;
|
//chan[i].note=-1;
|
||||||
chan[i].keyOn=false;
|
chan[i].keyOn=false;
|
||||||
if (chan[i].stopOnOff) {
|
if (chan[i].stopOnOff) {
|
||||||
chan[i].portaNote=-1;
|
chan[i].portaNote=-1;
|
||||||
|
@ -240,8 +286,10 @@ void DivEngine::processRow(int i, bool afterDelay) {
|
||||||
} else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) {
|
} else if (!(pat->data[whatRow][0]==0 && pat->data[whatRow][1]==0)) {
|
||||||
chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
|
chan[i].note=pat->data[whatRow][0]+pat->data[whatRow][1]*12;
|
||||||
if (!chan[i].keyOn) {
|
if (!chan[i].keyOn) {
|
||||||
|
if (dispatch->keyOffAffectsArp()) {
|
||||||
chan[i].arp=0;
|
chan[i].arp=0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
chan[i].doNote=true;
|
chan[i].doNote=true;
|
||||||
if (chan[i].arp!=0) {
|
if (chan[i].arp!=0) {
|
||||||
chan[i].arpYield=true;
|
chan[i].arpYield=true;
|
||||||
|
|
Loading…
Reference in a new issue