greatly improved playback resume
no more song weirding out when changing orders
This commit is contained in:
parent
84f36a8c66
commit
997c460fc1
|
@ -95,6 +95,10 @@ class DivEngine;
|
|||
class DivDispatch {
|
||||
protected:
|
||||
DivEngine* parent;
|
||||
/**
|
||||
* please honor this variable if needed.
|
||||
*/
|
||||
bool skipRegisterWrites;
|
||||
public:
|
||||
/**
|
||||
* the rate the samples are provided.
|
||||
|
@ -167,6 +171,16 @@ class DivDispatch {
|
|||
*/
|
||||
virtual void setPAL(bool pal);
|
||||
|
||||
/**
|
||||
* set skip reg writes.
|
||||
*/
|
||||
void setSkipRegisterWrites(bool value);
|
||||
|
||||
/**
|
||||
* force-retrigger instruments.
|
||||
*/
|
||||
virtual void forceIns();
|
||||
|
||||
/**
|
||||
* initialize this DivDispatch.
|
||||
* @param parent the parent DivEngine.
|
||||
|
|
|
@ -1419,15 +1419,30 @@ void DivEngine::setLoops(int loops) {
|
|||
remainingLoops=loops;
|
||||
}
|
||||
|
||||
void DivEngine::play() {
|
||||
isBusy.lock();
|
||||
void DivEngine::playSub() {
|
||||
reset();
|
||||
int goal=curOrder;
|
||||
curOrder=0;
|
||||
curRow=0;
|
||||
clockDrift=0;
|
||||
cycles=0;
|
||||
ticks=1;
|
||||
speedAB=false;
|
||||
playing=true;
|
||||
dispatch->setSkipRegisterWrites(true);
|
||||
while (curOrder<goal) {
|
||||
if (nextTick()) break;
|
||||
}
|
||||
dispatch->setSkipRegisterWrites(false);
|
||||
dispatch->forceIns();
|
||||
clockDrift=0;
|
||||
cycles=0;
|
||||
ticks=1;
|
||||
}
|
||||
|
||||
void DivEngine::play() {
|
||||
isBusy.lock();
|
||||
playSub();
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
||||
|
@ -1667,12 +1682,7 @@ void DivEngine::setOrder(unsigned char order) {
|
|||
curOrder=order;
|
||||
if (order>=song.ordersLen) curOrder=0;
|
||||
if (playing) {
|
||||
reset();
|
||||
curRow=0;
|
||||
clockDrift=0;
|
||||
cycles=0;
|
||||
ticks=1;
|
||||
speedAB=false;
|
||||
playSub();
|
||||
}
|
||||
isBusy.unlock();
|
||||
}
|
||||
|
|
|
@ -113,6 +113,7 @@ class DivEngine {
|
|||
bool perSystemPostEffect(int ch, unsigned char effect, unsigned char effectVal);
|
||||
void renderSamples();
|
||||
void reset();
|
||||
void playSub();
|
||||
|
||||
public:
|
||||
DivSong song;
|
||||
|
|
|
@ -34,6 +34,14 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
|
|||
void DivDispatch::setPAL(bool pal) {
|
||||
}
|
||||
|
||||
void DivDispatch::setSkipRegisterWrites(bool value) {
|
||||
skipRegisterWrites=value;
|
||||
}
|
||||
|
||||
void DivDispatch::forceIns() {
|
||||
|
||||
}
|
||||
|
||||
int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -31,7 +31,8 @@ static int orderedOps[4]={
|
|||
0,2,1,3
|
||||
};
|
||||
|
||||
#define rWrite(a,v) pendingWrites[a]=v;
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
||||
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v);}
|
||||
|
||||
void DivPlatformArcade::acquire_nuked(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
static int o[2];
|
||||
|
@ -167,14 +168,14 @@ int hScale(int note) {
|
|||
void DivPlatformArcade::tick() {
|
||||
for (int i=0; i<8; i++) {
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
writes.emplace(0x08,i);
|
||||
immWrite(0x08,i);
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<256; i++) {
|
||||
if (pendingWrites[i]!=oldWrites[i]) {
|
||||
writes.emplace(i,pendingWrites[i]&0xff);
|
||||
immWrite(i,pendingWrites[i]&0xff);
|
||||
oldWrites[i]=pendingWrites[i];
|
||||
}
|
||||
}
|
||||
|
@ -182,12 +183,12 @@ void DivPlatformArcade::tick() {
|
|||
for (int i=0; i<8; i++) {
|
||||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=chan[i].baseFreq+(chan[i].pitch>>1)-64;
|
||||
writes.emplace(i+0x28,hScale(chan[i].freq>>6));
|
||||
writes.emplace(i+0x30,chan[i].freq<<2);
|
||||
immWrite(i+0x28,hScale(chan[i].freq>>6));
|
||||
immWrite(i+0x30,chan[i].freq<<2);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
writes.emplace(0x08,0x78|i);
|
||||
immWrite(0x08,0x78|i);
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
}
|
||||
|
@ -209,6 +210,7 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>7) {
|
||||
if (skipRegisterWrites) break;
|
||||
chan[c.chan].pcm.sample=12*sampleBank+c.value%12;
|
||||
if (chan[c.chan].pcm.sample>=parent->song.sampleLen) {
|
||||
chan[c.chan].pcm.sample=-1;
|
||||
|
@ -425,6 +427,12 @@ int DivPlatformArcade::dispatch(DivCommand c) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void DivPlatformArcade::forceIns() {
|
||||
for (int i=0; i<13; i++) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformArcade::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
if (useYMFM) {
|
||||
|
@ -451,8 +459,8 @@ void DivPlatformArcade::reset() {
|
|||
delay=0;
|
||||
|
||||
//rWrite(0x18,0x10);
|
||||
writes.emplace(0x19,0x7f);
|
||||
writes.emplace(0x19,0xff);
|
||||
immWrite(0x19,0x7f);
|
||||
immWrite(0x19,0xff);
|
||||
//rWrite(0x1b,0x00);
|
||||
|
||||
extMode=false;
|
||||
|
|
|
@ -64,6 +64,7 @@ class DivPlatformArcade: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#define FREQ_BASE 277.0f
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {sid.write(a,v);}
|
||||
|
||||
void DivPlatformC64::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
for (size_t i=start; i<start+len; i++) {
|
||||
sid.clock();
|
||||
|
@ -12,10 +14,10 @@ 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);
|
||||
rWrite(0x15,filtCut&7);
|
||||
rWrite(0x16,filtCut>>3);
|
||||
rWrite(0x17,(filtRes<<4)|(chan[2].filter<<2)|(chan[1].filter<<1)|(chan[0].filter));
|
||||
rWrite(0x18,(filtControl<<4)|vol);
|
||||
}
|
||||
|
||||
void DivPlatformC64::tick() {
|
||||
|
@ -50,37 +52,37 @@ void DivPlatformC64::tick() {
|
|||
}
|
||||
if (chan[i].std.hadDuty) {
|
||||
chan[i].duty-=((signed char)chan[i].std.duty-12)*4;
|
||||
sid.write(i*7+2,chan[i].duty&0xff);
|
||||
sid.write(i*7+3,chan[i].duty>>8);
|
||||
rWrite(i*7+2,chan[i].duty&0xff);
|
||||
rWrite(i*7+3,chan[i].duty>>8);
|
||||
}
|
||||
if (chan[i].testWhen>0) {
|
||||
if (--chan[i].testWhen<1) {
|
||||
if (!chan[i].resetMask && !isMuted[i]) {
|
||||
sid.write(i*7+5,0);
|
||||
sid.write(i*7+6,0);
|
||||
sid.write(i*7+4,(isMuted[i]?0:(chan[i].wave<<4))|8|(chan[i].ring<<2)|(chan[i].sync<<1));
|
||||
rWrite(i*7+5,0);
|
||||
rWrite(i*7+6,0);
|
||||
rWrite(i*7+4,(isMuted[i]?0:(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,(isMuted[i]?0:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|chan[i].active);
|
||||
rWrite(i*7+4,(isMuted[i]?0:(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) {
|
||||
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].keyOn) {
|
||||
sid.write(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
sid.write(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
sid.write(i*7+4,(isMuted[i]?0:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
rWrite(i*7+4,(isMuted[i]?0:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|1);
|
||||
}
|
||||
if (chan[i].keyOff && !isMuted[i]) {
|
||||
sid.write(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
sid.write(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
sid.write(i*7+4,(isMuted[i]?0:(chan[i].wave<<4))|(chan[i].ring<<2)|(chan[i].sync<<1)|0);
|
||||
rWrite(i*7+5,(chan[i].attack<<4)|(chan[i].decay));
|
||||
rWrite(i*7+6,(chan[i].sustain<<4)|(chan[i].release));
|
||||
rWrite(i*7+4,(isMuted[i]?0:(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+1,chan[i].freq>>8);
|
||||
rWrite(i*7,chan[i].freq&0xff);
|
||||
rWrite(i*7+1,chan[i].freq>>8);
|
||||
if (chan[i].keyOn) chan[i].keyOn=false;
|
||||
if (chan[i].keyOff) chan[i].keyOff=false;
|
||||
chan[i].freqChanged=false;
|
||||
|
@ -99,8 +101,8 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
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;
|
||||
sid.write(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||
sid.write(c.chan*7+3,chan[c.chan].duty>>8);
|
||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||
rWrite(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);
|
||||
|
@ -181,12 +183,12 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_STD_NOISE_MODE:
|
||||
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);
|
||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||
rWrite(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);
|
||||
rWrite(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 DIV_CMD_LEGATO:
|
||||
chan[c.chan].baseFreq=round(FREQ_BASE*pow(2.0f,((float)(c.value+((chan[c.chan].std.willArp && !chan[c.chan].std.arpMode)?(chan[c.chan].std.arp-12):(0)))/12.0f)));
|
||||
|
@ -236,8 +238,8 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
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);
|
||||
rWrite(c.chan*7+2,chan[c.chan].duty&0xff);
|
||||
rWrite(c.chan*7+3,chan[c.chan].duty>>8);
|
||||
}
|
||||
chan[c.chan].resetDuty=c.value>>4;
|
||||
break;
|
||||
|
@ -257,11 +259,11 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
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);
|
||||
rWrite(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);
|
||||
rWrite(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;
|
||||
|
@ -280,7 +282,14 @@ int DivPlatformC64::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformC64::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
sid.write(ch*7+4,(isMuted[ch]?0:(chan[ch].wave<<4))|(chan[ch].ring<<2)|(chan[ch].sync<<1)|chan[ch].active);
|
||||
rWrite(ch*7+4,(isMuted[ch]?0:(chan[ch].wave<<4))|(chan[ch].ring<<2)|(chan[ch].sync<<1)|chan[ch].active);
|
||||
}
|
||||
|
||||
void DivPlatformC64::forceIns() {
|
||||
for (int i=0; i<3; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].testWhen=0;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformC64::reset() {
|
||||
|
@ -290,7 +299,7 @@ void DivPlatformC64::reset() {
|
|||
|
||||
sid.reset();
|
||||
|
||||
sid.write(0x18,0x0f);
|
||||
rWrite(0x18,0x0f);
|
||||
|
||||
filtControl=0;
|
||||
filtRes=0;
|
||||
|
|
|
@ -57,6 +57,7 @@ class DivPlatformC64: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
void setPAL(bool pal);
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
#include <math.h>
|
||||
|
||||
//#define rWrite(a,v) pendingWrites[a]=v;
|
||||
#define rWrite(a,v) GB_apu_write(gb,a,v);
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {GB_apu_write(gb,a,v);}
|
||||
|
||||
#define FREQ_BASE 8015.85f
|
||||
|
||||
|
@ -286,6 +286,14 @@ int DivPlatformGB::dispatch(DivCommand c) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void DivPlatformGB::forceIns() {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
GB_apu_write(gb,0x25,procMute());
|
||||
updateWave();
|
||||
}
|
||||
|
||||
void DivPlatformGB::reset() {
|
||||
for (int i=0; i<4; i++) {
|
||||
chan[i]=DivPlatformGB::Channel();
|
||||
|
|
|
@ -41,6 +41,7 @@ class DivPlatformGB: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
|
|
|
@ -23,9 +23,9 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
|
|||
DivSample* s=parent->song.sample[dacSample];
|
||||
if (!isMuted[5]) {
|
||||
if (s->depth==8) {
|
||||
writes.emplace(0x2a,(unsigned char)s->rendData[dacPos++]+0x80);
|
||||
immWrite(0x2a,(unsigned char)s->rendData[dacPos++]+0x80);
|
||||
} else {
|
||||
writes.emplace(0x2a,((unsigned short)s->rendData[dacPos++]+0x8000)>>8);
|
||||
immWrite(0x2a,((unsigned short)s->rendData[dacPos++]+0x8000)>>8);
|
||||
}
|
||||
}
|
||||
if (dacPos>=s->rendLength) {
|
||||
|
@ -82,14 +82,14 @@ void DivPlatformGenesis::tick() {
|
|||
for (int i=0; i<6; i++) {
|
||||
if (i==2 && extMode) continue;
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
writes.emplace(0x28,0x00|konOffs[i]);
|
||||
immWrite(0x28,0x00|konOffs[i]);
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<512; i++) {
|
||||
if (pendingWrites[i]!=oldWrites[i]) {
|
||||
writes.emplace(i,pendingWrites[i]&0xff);
|
||||
immWrite(i,pendingWrites[i]&0xff);
|
||||
oldWrites[i]=pendingWrites[i];
|
||||
}
|
||||
}
|
||||
|
@ -99,12 +99,12 @@ void DivPlatformGenesis::tick() {
|
|||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE+chan[i].pitch))/ONE_SEMITONE;
|
||||
int freqt=toFreq(chan[i].freq);
|
||||
writes.emplace(chanOffs[i]+0xa4,freqt>>8);
|
||||
writes.emplace(chanOffs[i]+0xa0,freqt&0xff);
|
||||
immWrite(chanOffs[i]+0xa4,freqt>>8);
|
||||
immWrite(chanOffs[i]+0xa0,freqt&0xff);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
writes.emplace(0x28,0xf0|konOffs[i]);
|
||||
immWrite(0x28,0xf0|konOffs[i]);
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
}
|
||||
|
@ -171,6 +171,7 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan==5 && dacMode) {
|
||||
if (skipRegisterWrites) break;
|
||||
dacSample=12*sampleBank+c.value%12;
|
||||
if (dacSample>=parent->song.sampleLen) {
|
||||
dacSample=-1;
|
||||
|
@ -370,6 +371,15 @@ int DivPlatformGenesis::dispatch(DivCommand c) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::forceIns() {
|
||||
for (int i=0; i<10; i++) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
if (dacMode) {
|
||||
rWrite(0x2b,0x80);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformGenesis::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
OPN2_Reset(&fm);
|
||||
|
@ -394,7 +404,7 @@ void DivPlatformGenesis::reset() {
|
|||
extMode=false;
|
||||
|
||||
// LFO
|
||||
writes.emplace(0x22,0x08);
|
||||
immWrite(0x22,0x08);
|
||||
|
||||
delay=0;
|
||||
|
||||
|
|
|
@ -53,6 +53,7 @@ class DivPlatformGenesis: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
|
|
|
@ -231,7 +231,7 @@ void DivPlatformGenesisExt::tick() {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
writes.emplace(0x28,writeMask);
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -267,8 +267,8 @@ void DivPlatformGenesisExt::tick() {
|
|||
opChan[i].freqH=(opChan[i].freq>>8)&7;
|
||||
opChan[i].freqL=opChan[i].freq&0xff;
|
||||
}
|
||||
writes.emplace(opChanOffsH[i],opChan[i].freqH);
|
||||
writes.emplace(opChanOffsL[i],opChan[i].freqL);
|
||||
immWrite(opChanOffsH[i],opChan[i].freqH);
|
||||
immWrite(opChanOffsL[i],opChan[i].freqL);
|
||||
}
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
if (opChan[i].keyOn) {
|
||||
|
@ -278,7 +278,14 @@ void DivPlatformGenesisExt::tick() {
|
|||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
writes.emplace(0x28,writeMask);
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformGenesisExt::forceIns() {
|
||||
DivPlatformGenesis::forceIns();
|
||||
for (int i=0; i<4; i++) {
|
||||
opChan[i].insChanged=true;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +298,7 @@ void DivPlatformGenesisExt::reset() {
|
|||
}
|
||||
|
||||
// channel 3 mode
|
||||
writes.emplace(0x27,0x40);
|
||||
immWrite(0x27,0x40);
|
||||
extMode=true;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
|
|||
public:
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
@ -23,4 +23,5 @@ static int orderedOps[4]={
|
|||
0,2,1,3
|
||||
};
|
||||
|
||||
#define rWrite(a,v) pendingWrites[a]=v;
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
||||
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v);}
|
||||
|
|
|
@ -6,6 +6,8 @@
|
|||
#define FREQ_BASE 3424.0f
|
||||
#define FREQ_BASE_PAL 3180.0f
|
||||
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {apu_wr_reg(a,v);}
|
||||
|
||||
void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) {
|
||||
for (size_t i=start; i<start+len; i++) {
|
||||
if (dacSample!=-1) {
|
||||
|
@ -14,9 +16,9 @@ void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len)
|
|||
DivSample* s=parent->song.sample[dacSample];
|
||||
if (!isMuted[4]) {
|
||||
if (s->depth==8) {
|
||||
apu_wr_reg(0x4011,((unsigned char)s->rendData[dacPos++]+0x80)>>1);
|
||||
rWrite(0x4011,((unsigned char)s->rendData[dacPos++]+0x80)>>1);
|
||||
} else {
|
||||
apu_wr_reg(0x4011,((unsigned short)s->rendData[dacPos++]+0x8000)>>9);
|
||||
rWrite(0x4011,((unsigned short)s->rendData[dacPos++]+0x8000)>>9);
|
||||
}
|
||||
}
|
||||
if (dacPos>=s->rendLength) {
|
||||
|
@ -72,10 +74,10 @@ void DivPlatformNES::tick() {
|
|||
chan[i].outVol=chan[i].std.vol-(15-chan[i].vol);
|
||||
if (chan[i].outVol<0) chan[i].outVol=0;
|
||||
if (i==2) { // triangle
|
||||
apu_wr_reg(0x4000+i*4,(chan[i].outVol==0)?0:255);
|
||||
rWrite(0x4000+i*4,(chan[i].outVol==0)?0:255);
|
||||
chan[i].freqChanged=true;
|
||||
} else {
|
||||
apu_wr_reg(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
|
||||
rWrite(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
|
||||
}
|
||||
}
|
||||
if (chan[i].std.hadArp) {
|
||||
|
@ -107,7 +109,7 @@ void DivPlatformNES::tick() {
|
|||
chan[i].duty=chan[i].std.duty;
|
||||
if (i==3 && chan[i].duty>1) chan[i].duty=1;
|
||||
if (i!=2) {
|
||||
apu_wr_reg(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
|
||||
rWrite(0x4000+i*4,0x30|chan[i].outVol|((chan[i].duty&3)<<6));
|
||||
}
|
||||
if (i==3) { // noise
|
||||
chan[i].freqChanged=true;
|
||||
|
@ -133,18 +135,18 @@ void DivPlatformNES::tick() {
|
|||
if (chan[i].keyOff) {
|
||||
//rWrite(16+i*5+2,8);
|
||||
if (i==2) { // triangle
|
||||
apu_wr_reg(0x4000+i*4,0x00);
|
||||
rWrite(0x4000+i*4,0x00);
|
||||
} else {
|
||||
apu_wr_reg(0x4000+i*4,0x30);
|
||||
rWrite(0x4000+i*4,0x30);
|
||||
}
|
||||
}
|
||||
if (i==3) { // noise
|
||||
apu_wr_reg(0x4002+i*4,(chan[i].duty<<7)|chan[i].freq);
|
||||
apu_wr_reg(0x4003+i*4,0xf0);
|
||||
rWrite(0x4002+i*4,(chan[i].duty<<7)|chan[i].freq);
|
||||
rWrite(0x4003+i*4,0xf0);
|
||||
} else {
|
||||
apu_wr_reg(0x4002+i*4,chan[i].freq&0xff);
|
||||
rWrite(0x4002+i*4,chan[i].freq&0xff);
|
||||
if ((chan[i].prevFreq>>8)!=(chan[i].freq>>8) || i==2) {
|
||||
apu_wr_reg(0x4003+i*4,0xf8|(chan[i].freq>>8));
|
||||
rWrite(0x4003+i*4,0xf8|(chan[i].freq>>8));
|
||||
}
|
||||
if (chan[i].freq!=65535 && chan[i].freq!=0) {
|
||||
chan[i].prevFreq=chan[i].freq;
|
||||
|
@ -181,9 +183,9 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
chan[c.chan].keyOn=true;
|
||||
chan[c.chan].std.init(parent->getIns(chan[c.chan].ins));
|
||||
if (c.chan==2) {
|
||||
apu_wr_reg(0x4000+c.chan*4,0xff);
|
||||
rWrite(0x4000+c.chan*4,0xff);
|
||||
} else {
|
||||
apu_wr_reg(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
|
||||
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
|
||||
}
|
||||
break;
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
|
@ -204,9 +206,9 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
chan[c.chan].outVol=c.value;
|
||||
}
|
||||
if (c.chan==2) {
|
||||
apu_wr_reg(0x4000+c.chan*4,0xff);
|
||||
rWrite(0x4000+c.chan*4,0xff);
|
||||
} else {
|
||||
apu_wr_reg(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
|
||||
rWrite(0x4000+c.chan*4,0x30|chan[c.chan].vol|((chan[c.chan].duty&3)<<6));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -276,9 +278,16 @@ int DivPlatformNES::dispatch(DivCommand c) {
|
|||
|
||||
void DivPlatformNES::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
apu_wr_reg(0x4015,(!isMuted[0])|((!isMuted[1])<<1)|((!isMuted[2])<<2)|((!isMuted[3])<<3)|((!isMuted[4])<<4));
|
||||
rWrite(0x4015,(!isMuted[0])|((!isMuted[1])<<1)|((!isMuted[2])<<2)|((!isMuted[3])<<3)|((!isMuted[4])<<4));
|
||||
if (isMuted[4]) {
|
||||
apu_wr_reg(0x4011,0);
|
||||
rWrite(0x4011,0);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformNES::forceIns() {
|
||||
for (int i=0; i<5; i++) {
|
||||
chan[i].insChanged=true;
|
||||
chan[i].prevFreq=65535;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -297,9 +306,9 @@ void DivPlatformNES::reset() {
|
|||
apu.cpu_cycles=0;
|
||||
apu.cpu_opcode_cycle=0;
|
||||
|
||||
apu_wr_reg(0x4015,(!isMuted[0])|((!isMuted[1])<<1)|((!isMuted[2])<<2)|((!isMuted[3])<<3)|((!isMuted[4])<<4));
|
||||
apu_wr_reg(0x4001,0x08);
|
||||
apu_wr_reg(0x4005,0x08);
|
||||
rWrite(0x4015,(!isMuted[0])|((!isMuted[1])<<1)|((!isMuted[2])<<2)|((!isMuted[3])<<3)|((!isMuted[4])<<4));
|
||||
rWrite(0x4001,0x08);
|
||||
rWrite(0x4005,0x08);
|
||||
}
|
||||
|
||||
bool DivPlatformNES::keyOffAffectsArp(int ch) {
|
||||
|
|
|
@ -41,11 +41,11 @@ class DivPlatformNES: public DivDispatch {
|
|||
|
||||
float freqBase;
|
||||
|
||||
void updateWave();
|
||||
public:
|
||||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
@ -3,13 +3,15 @@
|
|||
#include <math.h>
|
||||
|
||||
//#define rWrite(a,v) pendingWrites[a]=v;
|
||||
#define rWrite(a,v) writes.emplace(a,v);
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v);}
|
||||
#define chWrite(c,a,v) \
|
||||
if (curChan!=c) { \
|
||||
curChan=c; \
|
||||
rWrite(0,curChan); \
|
||||
} \
|
||||
rWrite(a,v);
|
||||
if (!skipRegisterWrites) { \
|
||||
if (curChan!=c) { \
|
||||
curChan=c; \
|
||||
rWrite(0,curChan); \
|
||||
} \
|
||||
rWrite(a,v); \
|
||||
}
|
||||
|
||||
#define FREQ_BASE 1712.0f*2
|
||||
|
||||
|
@ -268,6 +270,13 @@ void DivPlatformPCE::muteChannel(int ch, bool mute) {
|
|||
chWrite(ch,0x05,isMuted[ch]?0:chan[ch].pan);
|
||||
}
|
||||
|
||||
void DivPlatformPCE::forceIns() {
|
||||
for (int i=0; i<6; i++) {
|
||||
chan[i].insChanged=true;
|
||||
updateWave(i);
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformPCE::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
for (int i=0; i<6; i++) {
|
||||
|
|
|
@ -57,6 +57,7 @@ class DivPlatformPCE: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
|
|
|
@ -104,14 +104,14 @@ void DivPlatformYM2610::tick() {
|
|||
for (int i=0; i<4; i++) {
|
||||
if (i==1 && extMode) continue;
|
||||
if (chan[i].keyOn || chan[i].keyOff) {
|
||||
writes.emplace(0x28,0x00|konOffs[i]);
|
||||
immWrite(0x28,0x00|konOffs[i]);
|
||||
chan[i].keyOff=false;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<512; i++) {
|
||||
if (pendingWrites[i]!=oldWrites[i]) {
|
||||
writes.emplace(i,pendingWrites[i]&0xff);
|
||||
immWrite(i,pendingWrites[i]&0xff);
|
||||
oldWrites[i]=pendingWrites[i];
|
||||
}
|
||||
}
|
||||
|
@ -121,12 +121,12 @@ void DivPlatformYM2610::tick() {
|
|||
if (chan[i].freqChanged) {
|
||||
chan[i].freq=(chan[i].baseFreq*(ONE_SEMITONE+chan[i].pitch))/ONE_SEMITONE;
|
||||
int freqt=toFreq(chan[i].freq);
|
||||
writes.emplace(chanOffs[i]+0xa4,freqt>>8);
|
||||
writes.emplace(chanOffs[i]+0xa0,freqt&0xff);
|
||||
immWrite(chanOffs[i]+0xa4,freqt>>8);
|
||||
immWrite(chanOffs[i]+0xa0,freqt&0xff);
|
||||
chan[i].freqChanged=false;
|
||||
}
|
||||
if (chan[i].keyOn) {
|
||||
writes.emplace(0x28,0xf0|konOffs[i]);
|
||||
immWrite(0x28,0xf0|konOffs[i]);
|
||||
chan[i].keyOn=false;
|
||||
}
|
||||
}
|
||||
|
@ -177,22 +177,23 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
switch (c.cmd) {
|
||||
case DIV_CMD_NOTE_ON: {
|
||||
if (c.chan>6) { // ADPCM
|
||||
if (skipRegisterWrites) break;
|
||||
if ((12*sampleBank+c.value%12)>=parent->song.sampleLen) {
|
||||
writes.emplace(0x100,0x80|(1<<(c.chan-7)));
|
||||
writes.emplace(0x110+c.chan-7,0);
|
||||
writes.emplace(0x118+c.chan-7,0);
|
||||
writes.emplace(0x120+c.chan-7,0);
|
||||
writes.emplace(0x128+c.chan-7,0);
|
||||
immWrite(0x100,0x80|(1<<(c.chan-7)));
|
||||
immWrite(0x110+c.chan-7,0);
|
||||
immWrite(0x118+c.chan-7,0);
|
||||
immWrite(0x120+c.chan-7,0);
|
||||
immWrite(0x128+c.chan-7,0);
|
||||
break;
|
||||
}
|
||||
DivSample* s=parent->song.sample[12*sampleBank+c.value%12];
|
||||
writes.emplace(0x110+c.chan-7,(s->rendOff>>8)&0xff);
|
||||
writes.emplace(0x118+c.chan-7,s->rendOff>>16);
|
||||
immWrite(0x110+c.chan-7,(s->rendOff>>8)&0xff);
|
||||
immWrite(0x118+c.chan-7,s->rendOff>>16);
|
||||
int end=s->rendOff+s->adpcmRendLength-1;
|
||||
writes.emplace(0x120+c.chan-7,(end>>8)&0xff);
|
||||
writes.emplace(0x128+c.chan-7,end>>16);
|
||||
writes.emplace(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
writes.emplace(0x100,0x00|(1<<(c.chan-7)));
|
||||
immWrite(0x120+c.chan-7,(end>>8)&0xff);
|
||||
immWrite(0x128+c.chan-7,end>>16);
|
||||
immWrite(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
immWrite(0x100,0x00|(1<<(c.chan-7)));
|
||||
break;
|
||||
}
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
|
@ -247,7 +248,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
}
|
||||
case DIV_CMD_NOTE_OFF:
|
||||
if (c.chan>6) {
|
||||
writes.emplace(0x100,0x80|(1<<(c.chan-7)));
|
||||
immWrite(0x100,0x80|(1<<(c.chan-7)));
|
||||
break;
|
||||
}
|
||||
chan[c.chan].keyOff=true;
|
||||
|
@ -258,7 +259,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
chan[c.chan].vol=c.value;
|
||||
DivInstrument* ins=parent->getIns(chan[c.chan].ins);
|
||||
if (c.chan>6) { // ADPCM
|
||||
writes.emplace(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
immWrite(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
break;
|
||||
}
|
||||
if (c.chan>3) { // PSG
|
||||
|
@ -306,7 +307,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
}
|
||||
if (c.chan>6) {
|
||||
writes.emplace(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
immWrite(0x108+(c.chan-7),isMuted[c.chan]?0:((chan[c.chan].pan<<6)|chan[c.chan].vol));
|
||||
break;
|
||||
}
|
||||
if (c.chan>3) break;
|
||||
|
@ -434,7 +435,8 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
break;
|
||||
case DIV_CMD_AY_ENVELOPE_SET:
|
||||
if (c.chan<4 || c.chan>6) break;
|
||||
rWrite(0x0d,c.value>>4);
|
||||
ayEnvMode=c.value>>4;
|
||||
rWrite(0x0d,ayEnvMode);
|
||||
if (c.value&15) {
|
||||
chan[c.chan].psgMode|=4;
|
||||
} else {
|
||||
|
@ -450,15 +452,15 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
if (c.chan<4 || c.chan>6) break;
|
||||
ayEnvPeriod&=0xff00;
|
||||
ayEnvPeriod|=c.value;
|
||||
writes.emplace(0x0b,ayEnvPeriod);
|
||||
writes.emplace(0x0c,ayEnvPeriod>>8);
|
||||
immWrite(0x0b,ayEnvPeriod);
|
||||
immWrite(0x0c,ayEnvPeriod>>8);
|
||||
break;
|
||||
case DIV_CMD_AY_ENVELOPE_HIGH:
|
||||
if (c.chan<4 || c.chan>6) break;
|
||||
ayEnvPeriod&=0xff;
|
||||
ayEnvPeriod|=c.value<<8;
|
||||
writes.emplace(0x0b,ayEnvPeriod);
|
||||
writes.emplace(0x0c,ayEnvPeriod>>8);
|
||||
immWrite(0x0b,ayEnvPeriod);
|
||||
immWrite(0x0c,ayEnvPeriod>>8);
|
||||
break;
|
||||
case DIV_ALWAYS_SET_VOLUME:
|
||||
return 0;
|
||||
|
@ -486,7 +488,7 @@ int DivPlatformYM2610::dispatch(DivCommand c) {
|
|||
void DivPlatformYM2610::muteChannel(int ch, bool mute) {
|
||||
isMuted[ch]=mute;
|
||||
if (ch>6) { // ADPCM
|
||||
writes.emplace(0x108+(ch-7),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].vol));
|
||||
immWrite(0x108+(ch-7),isMuted[ch]?0:((chan[ch].pan<<6)|chan[ch].vol));
|
||||
return;
|
||||
}
|
||||
if (ch>3) { // PSG
|
||||
|
@ -502,6 +504,15 @@ void DivPlatformYM2610::muteChannel(int ch, bool mute) {
|
|||
rWrite(chanOffs[ch]+0xb4,(isMuted[ch]?0:(chan[ch].pan<<6))|(ins->fm.fms&7)|((ins->fm.ams&3)<<4));
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::forceIns() {
|
||||
for (int i=0; i<13; i++) {
|
||||
chan[i].insChanged=true;
|
||||
}
|
||||
immWrite(0x0b,ayEnvPeriod);
|
||||
immWrite(0x0c,ayEnvPeriod>>8);
|
||||
immWrite(0x0d,ayEnvMode);
|
||||
}
|
||||
|
||||
void DivPlatformYM2610::reset() {
|
||||
while (!writes.empty()) writes.pop();
|
||||
fm->reset();
|
||||
|
@ -531,16 +542,17 @@ void DivPlatformYM2610::reset() {
|
|||
dacSample=-1;
|
||||
sampleBank=0;
|
||||
ayEnvPeriod=0;
|
||||
ayEnvMode=0;
|
||||
|
||||
delay=0;
|
||||
|
||||
extMode=false;
|
||||
|
||||
// LFO
|
||||
writes.emplace(0x22,0x08);
|
||||
immWrite(0x22,0x08);
|
||||
|
||||
// PCM volume
|
||||
writes.emplace(0x101,0x3f);
|
||||
immWrite(0x101,0x3f);
|
||||
}
|
||||
|
||||
bool DivPlatformYM2610::isStereo() {
|
||||
|
|
|
@ -54,6 +54,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
|
||||
short oldWrites[512];
|
||||
short pendingWrites[512];
|
||||
unsigned char ayEnvMode;
|
||||
unsigned short ayEnvPeriod;
|
||||
|
||||
int octave(int freq);
|
||||
|
@ -63,6 +64,7 @@ class DivPlatformYM2610: public DivDispatch {
|
|||
void acquire(short* bufL, short* bufR, size_t start, size_t len);
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool isStereo();
|
||||
|
|
|
@ -207,7 +207,7 @@ void DivPlatformYM2610Ext::tick() {
|
|||
}
|
||||
}
|
||||
if (writeSomething) {
|
||||
writes.emplace(0x28,writeMask);
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -221,8 +221,8 @@ void DivPlatformYM2610Ext::tick() {
|
|||
int freqt=toFreq(opChan[i].freq);
|
||||
opChan[i].freqH=freqt>>8;
|
||||
opChan[i].freqL=freqt&0xff;
|
||||
writes.emplace(opChanOffsH[i],opChan[i].freqH);
|
||||
writes.emplace(opChanOffsL[i],opChan[i].freqL);
|
||||
immWrite(opChanOffsH[i],opChan[i].freqH);
|
||||
immWrite(opChanOffsL[i],opChan[i].freqL);
|
||||
opChan[i].freqChanged=false;
|
||||
}
|
||||
writeMask|=opChan[i].active<<(4+i);
|
||||
|
@ -233,7 +233,7 @@ void DivPlatformYM2610Ext::tick() {
|
|||
}
|
||||
}
|
||||
if (writeNoteOn) {
|
||||
writes.emplace(0x28,writeMask);
|
||||
immWrite(0x28,writeMask);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -261,6 +261,13 @@ void DivPlatformYM2610Ext::muteChannel(int ch, bool mute) {
|
|||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::forceIns() {
|
||||
DivPlatformYM2610::forceIns();
|
||||
for (int i=0; i<4; i++) {
|
||||
opChan[i].insChanged=true;
|
||||
}
|
||||
}
|
||||
|
||||
void DivPlatformYM2610Ext::reset() {
|
||||
DivPlatformYM2610::reset();
|
||||
|
||||
|
@ -270,7 +277,7 @@ void DivPlatformYM2610Ext::reset() {
|
|||
}
|
||||
|
||||
// channel 2 mode
|
||||
writes.emplace(0x27,0x40);
|
||||
immWrite(0x27,0x40);
|
||||
extMode=true;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ class DivPlatformYM2610Ext: public DivPlatformYM2610 {
|
|||
public:
|
||||
int dispatch(DivCommand c);
|
||||
void reset();
|
||||
void forceIns();
|
||||
void tick();
|
||||
void muteChannel(int ch, bool mute);
|
||||
bool keyOffAffectsArp(int ch);
|
||||
|
|
|
@ -23,7 +23,8 @@ static int orderedOps[4]={
|
|||
0,2,1,3
|
||||
};
|
||||
|
||||
#define rWrite(a,v) pendingWrites[a]=v;
|
||||
#define rWrite(a,v) if (!skipRegisterWrites) {pendingWrites[a]=v;}
|
||||
#define immWrite(a,v) if (!skipRegisterWrites) {writes.emplace(a,v);}
|
||||
|
||||
#define FM_FREQ_BASE 622.0f
|
||||
#define PSG_FREQ_BASE 7640.0f
|
||||
|
|
Loading…
Reference in New Issue