add PAL flag to dispatch

now platforms run at their correct clock speed when in PAL mode

also fix clipping in Genesis
This commit is contained in:
tildearrow 2021-12-08 01:56:40 -05:00
parent fe5f8afa05
commit 6a02754996
19 changed files with 69 additions and 36 deletions

View file

@ -108,6 +108,6 @@ class DivDispatch {
* @param sugRate the suggested rate. this may change, so don't rely on it. * @param sugRate the suggested rate. this may change, so don't rely on it.
* @return the number of channels allocated. * @return the number of channels allocated.
*/ */
virtual int init(DivEngine* parent, int channels, int sugRate); virtual int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif

View file

@ -801,7 +801,7 @@ bool DivEngine::init(String outName) {
dispatch=new DivPlatformDummy; dispatch=new DivPlatformDummy;
break; break;
} }
dispatch->init(this,getChannelCount(song.system),got.rate); dispatch->init(this,getChannelCount(song.system),got.rate,(!song.pal) || (song.customTempo!=0 && song.hz<53));
blip_set_rates(bb[0],dispatch->rate,got.rate); blip_set_rates(bb[0],dispatch->rate,got.rate);
blip_set_rates(bb[1],dispatch->rate,got.rate); blip_set_rates(bb[1],dispatch->rate,got.rate);

View file

@ -18,6 +18,6 @@ bool DivDispatch::keyOffAffectsArp(int ch) {
return false; return false;
} }
int DivDispatch::init(DivEngine* p, int channels, int sugRate) { int DivDispatch::init(DivEngine* p, int channels, int sugRate, bool pal) {
return 0; return 0;
} }

View file

@ -287,9 +287,13 @@ void DivPlatformC64::setChipModel(bool is6581) {
} }
} }
int DivPlatformC64::init(DivEngine* p, int channels, int sugRate) { int DivPlatformC64::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
if (pal) {
rate=985248; rate=985248;
} else {
rate=1022727;
}
sid.reset(); sid.reset();

View file

@ -56,7 +56,7 @@ class DivPlatformC64: 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();
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
void setChipModel(bool is6581); void setChipModel(bool is6581);
}; };

View file

@ -61,7 +61,7 @@ int DivPlatformDummy::dispatch(DivCommand c) {
return 1; return 1;
} }
int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate) { int DivPlatformDummy::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
rate=65536; rate=65536;
chans=channels; chans=channels;

View file

@ -18,5 +18,5 @@ class DivPlatformDummy: 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();
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };

View file

@ -274,7 +274,7 @@ bool DivPlatformGB::isStereo() {
return true; return true;
} }
int DivPlatformGB::init(DivEngine* p, int channels, int sugRate) { int DivPlatformGB::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
rate=262144; rate=262144;
gb=new GB_gameboy_t; gb=new GB_gameboy_t;

View file

@ -40,7 +40,7 @@ class DivPlatformGB: public DivDispatch {
int dispatch(DivCommand c); int dispatch(DivCommand c);
void tick(); void tick();
bool isStereo(); bool isStereo();
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif

View file

@ -57,14 +57,22 @@ void DivPlatformGenesis::acquire(short* bufL, short* bufR, size_t start, size_t
//OPN2_Write(&fm,0,0); //OPN2_Write(&fm,0,0);
} }
psgClocks+=223722; psgClocks+=psg.rate;
while (psgClocks>=rate) { while (psgClocks>=rate) {
psgOut=(psg.acquireOne()*3)>>3; psgOut=(psg.acquireOne()*3)>>3;
psgClocks-=rate; psgClocks-=rate;
} }
bufL[h]=(os[0]<<5)+psgOut; os[0]=(os[0]<<5)+psgOut;
bufR[h]=(os[1]<<5)+psgOut; if (os[0]<-32768) os[0]=-32768;
if (os[0]>32767) os[0]=32767;
os[1]=(os[1]<<5)+psgOut;
if (os[1]<-32768) os[1]=-32768;
if (os[1]>32767) os[1]=32767;
bufL[h]=os[0];
bufR[h]=os[1];
} }
} }
@ -348,9 +356,13 @@ bool DivPlatformGenesis::keyOffAffectsArp(int ch) {
return (ch>5); return (ch>5);
} }
int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate) { int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
if (pal) {
rate=211125;
} else {
rate=213068; rate=213068;
}
OPN2_Reset(&fm); OPN2_Reset(&fm);
for (int i=0; i<10; i++) { for (int i=0; i<10; i++) {
chan[i].vol=0x7f; chan[i].vol=0x7f;
@ -376,7 +388,7 @@ int DivPlatformGenesis::init(DivEngine* p, int channels, int sugRate) {
delay=0; delay=0;
// PSG // PSG
psg.init(p,4,sugRate); psg.init(p,4,sugRate,pal);
psgClocks=0; psgClocks=0;
psgOut=0; psgOut=0;
return 10; return 10;

View file

@ -53,6 +53,6 @@ class DivPlatformGenesis: public DivDispatch {
void tick(); void tick();
bool isStereo(); bool isStereo();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif

View file

@ -258,8 +258,8 @@ bool DivPlatformGenesisExt::keyOffAffectsArp(int ch) {
return (ch>8); return (ch>8);
} }
int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate) { int DivPlatformGenesisExt::init(DivEngine* parent, int channels, int sugRate, bool pal) {
DivPlatformGenesis::init(parent,channels,sugRate); DivPlatformGenesis::init(parent,channels,sugRate,pal);
for (int i=0; i<4; i++) { for (int i=0; i<4; i++) {
opChan[i].vol=127; opChan[i].vol=127;

View file

@ -18,5 +18,5 @@ class DivPlatformGenesisExt: public DivPlatformGenesis {
int dispatch(DivCommand c); int dispatch(DivCommand c);
void tick(); void tick();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };

View file

@ -4,6 +4,7 @@
#include <math.h> #include <math.h>
#define FREQ_BASE 3424.0f #define FREQ_BASE 3424.0f
#define FREQ_BASE_PAL 3180.0f
void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) { void DivPlatformNES::acquire(short* bufL, short* bufR, size_t start, size_t len) {
for (size_t i=start; i<start+len; i++) { for (size_t i=start; i<start+len; i++) {
@ -87,16 +88,16 @@ void DivPlatformNES::tick() {
} else { } else {
if (!chan[i].inPorta) { if (!chan[i].inPorta) {
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(freqBase/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(freqBase/pow(2.0f,((float)(chan[i].note+chan[i].std.arp-12)/12.0f)));
} }
} }
} }
chan[i].freqChanged=true; chan[i].freqChanged=true;
} else { } else {
if (chan[i].std.arpMode && chan[i].std.finishedArp) { if (chan[i].std.arpMode && chan[i].std.finishedArp) {
chan[i].baseFreq=round(FREQ_BASE/pow(2.0f,((float)(chan[i].note)/12.0f))); chan[i].baseFreq=round(freqBase/pow(2.0f,((float)(chan[i].note)/12.0f)));
chan[i].freqChanged=true; chan[i].freqChanged=true;
} }
} }
@ -172,7 +173,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
} else if (c.chan==3) { // noise } else if (c.chan==3) { // noise
chan[c.chan].baseFreq=c.value; chan[c.chan].baseFreq=c.value;
} else { } else {
chan[c.chan].baseFreq=round(FREQ_BASE/pow(2.0f,((float)c.value/12.0f))); chan[c.chan].baseFreq=round(freqBase/pow(2.0f,((float)c.value/12.0f)));
} }
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
@ -216,7 +217,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
break; break;
case DIV_CMD_NOTE_PORTA: { case DIV_CMD_NOTE_PORTA: {
int destFreq=round(FREQ_BASE/pow(2.0f,((float)c.value2/12.0f))); int destFreq=round(freqBase/pow(2.0f,((float)c.value2/12.0f)));
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;
@ -252,7 +253,7 @@ int DivPlatformNES::dispatch(DivCommand c) {
} }
case DIV_CMD_LEGATO: case DIV_CMD_LEGATO:
if (c.chan==3) break; if (c.chan==3) break;
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))); chan[c.chan].baseFreq=round(freqBase/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)));
chan[c.chan].freqChanged=true; chan[c.chan].freqChanged=true;
chan[c.chan].note=c.value; chan[c.chan].note=c.value;
break; break;
@ -276,9 +277,15 @@ bool DivPlatformNES::keyOffAffectsArp(int ch) {
return true; return true;
} }
int DivPlatformNES::init(DivEngine* p, int channels, int sugRate) { int DivPlatformNES::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
if (pal) {
rate=1662607;
freqBase=FREQ_BASE_PAL;
} else {
rate=1789773; rate=1789773;
freqBase=FREQ_BASE;
}
dacPeriod=0; dacPeriod=0;
dacPos=0; dacPos=0;

View file

@ -35,13 +35,15 @@ class DivPlatformNES: public DivDispatch {
int dacPeriod, dacRate, dacPos, dacSample; int dacPeriod, dacRate, dacPos, dacSample;
unsigned char lastPan; unsigned char lastPan;
float freqBase;
void updateWave(); void updateWave();
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);
void tick(); void tick();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif

View file

@ -264,9 +264,13 @@ bool DivPlatformPCE::keyOffAffectsArp(int ch) {
} }
int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate) { int DivPlatformPCE::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
if (pal) { // technically there is no PAL PC Engine but oh well...
rate=1773448;
} else {
rate=1789773; rate=1789773;
}
pce=new PCE_PSG(&tempL,&tempR,PCE_PSG::REVISION_HUC6280); pce=new PCE_PSG(&tempL,&tempR,PCE_PSG::REVISION_HUC6280);
lastPan=0xff; lastPan=0xff;
tempL=0; tempL=0;

View file

@ -55,7 +55,7 @@ class DivPlatformPCE: public DivDispatch {
void tick(); void tick();
bool isStereo(); bool isStereo();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif

View file

@ -163,10 +163,14 @@ bool DivPlatformSMS::keyOffAffectsArp(int ch) {
return true; return true;
} }
int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate) { int DivPlatformSMS::init(DivEngine* p, int channels, int sugRate, bool pal) {
parent=p; parent=p;
if (pal) {
rate=221681;
} else {
rate=223722; rate=223722;
sn=new sn76496_device(223722); }
sn=new sn76496_device(rate);
sn->device_start(); sn->device_start();
snNoiseMode=3; snNoiseMode=3;
updateSNMode=false; updateSNMode=false;

View file

@ -36,7 +36,7 @@ class DivPlatformSMS: public DivDispatch {
int dispatch(DivCommand c); int dispatch(DivCommand c);
void tick(); void tick();
bool keyOffAffectsArp(int ch); bool keyOffAffectsArp(int ch);
int init(DivEngine* parent, int channels, int sugRate); int init(DivEngine* parent, int channels, int sugRate, bool pal);
}; };
#endif #endif