AY: get TFX and DAC working!

sadly I don't think I can improve this any further for now...
This commit is contained in:
tildearrow 2025-03-08 03:05:09 -05:00
parent 42920b9101
commit b8f214020f
4 changed files with 123 additions and 78 deletions

View file

@ -113,15 +113,15 @@ const unsigned char dacLogTableAY[256]={
15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15
}; };
void DivPlatformAY8910::runDAC(int runRate) { void DivPlatformAY8910::runDAC(int runRate, int advance) {
if (runRate==0) runRate=dacRate; if (runRate==0) runRate=dacRate;
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (chan[i].active && (chan[i].curPSGMode.val&8) && chan[i].dac.sample!=-1) { if (chan[i].active && (chan[i].curPSGMode.val&8) && chan[i].dac.sample!=-1) {
chan[i].dac.period+=chan[i].dac.rate; chan[i].dac.period+=chan[i].dac.rate*advance;
bool end=false; bool end=false;
bool changed=false; bool changed=false;
int prevOut=chan[i].dac.out; int prevOut=chan[i].dac.out;
while (chan[i].dac.period>runRate && !end) { while (chan[i].dac.period>=runRate && !end) {
DivSample* s=parent->getSample(chan[i].dac.sample); DivSample* s=parent->getSample(chan[i].dac.sample);
if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) { if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) {
chan[i].dac.sample=-1; chan[i].dac.sample=-1;
@ -155,14 +155,14 @@ void DivPlatformAY8910::runDAC(int runRate) {
} }
} }
void DivPlatformAY8910::runTFX(int runRate) { void DivPlatformAY8910::runTFX(int runRate, int advance) {
/* /*
developer's note: if you are checking for intellivision developer's note: if you are checking for intellivision
make sure to add "&& selCore" make sure to add "&& selCore"
because for some reason, the register remap doesn't work because for some reason, the register remap doesn't work
when the user uses AtomicSSG core when the user uses AtomicSSG core
*/ */
float counterRatio=1.0; float counterRatio=advance;
if (runRate!=0) counterRatio=(double)rate/(double)runRate; if (runRate!=0) counterRatio=(double)rate/(double)runRate;
int timerPeriod, output; int timerPeriod, output;
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
@ -255,13 +255,14 @@ void DivPlatformAY8910::acquire_mame(blip_buffer_t** bb, size_t len) {
oscBuf[i]->begin(len); oscBuf[i]->begin(len);
} }
//logV("%d, %d, %d",ay->noise_enable(0),ay->noise_enable(1),ay->noise_enable(2));
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
int advance=len-i; int advance=len-i;
bool careAboutEnv=false; bool careAboutEnv=false;
bool careAboutNoise=false; bool careAboutNoise=false;
// heuristic // heuristic
if (!writes.empty()) {
advance=1;
} else {
for (int j=0; j<3; j++) { for (int j=0; j<3; j++) {
// tone counter // tone counter
if (!ay->tone_enable(j) && ay->m_tone[j].volume!=0) { if (!ay->tone_enable(j) && ay->m_tone[j].volume!=0) {
@ -281,6 +282,21 @@ void DivPlatformAY8910::acquire_mame(blip_buffer_t** bb, size_t len) {
if (ay->m_tone[j].volume&16) { if (ay->m_tone[j].volume&16) {
careAboutEnv=true; careAboutEnv=true;
} }
// DAC
if (chan[j].active && (chan[j].curPSGMode.val&8) && chan[j].dac.sample!=-1) {
if (chan[j].dac.rate<=0) continue;
const int remainTime=(rate-chan[j].dac.period+chan[j].dac.rate-1)/chan[j].dac.rate;
if (remainTime<advance) advance=remainTime;
}
// TFX
if (chan[j].active && (chan[j].curPSGMode.val&16) && !(chan[j].curPSGMode.val&8) && chan[j].tfx.mode!=-1) {
const int remainTime=chan[j].tfx.period-chan[j].tfx.counter;
if (remainTime<advance) advance=remainTime;
}
if (advance<=1) break;
} }
// envelope // envelope
if (careAboutEnv) { if (careAboutEnv) {
@ -300,14 +316,12 @@ void DivPlatformAY8910::acquire_mame(blip_buffer_t** bb, size_t len) {
advance=noiseRemain; advance=noiseRemain;
} }
} }
//runDAC();
//runTFX();
if (!writes.empty() || advance<1) {
//logV("must write, advance is 1");
advance=1;
} }
if (advance<1) advance=1;
runDAC(0,advance);
runTFX(0,advance);
checkWrites(); checkWrites();
ay->sound_stream_update(ayBuf,advance); ay->sound_stream_update(ayBuf,advance);
@ -360,8 +374,8 @@ void DivPlatformAY8910::acquire_atomic(short** buf, size_t len) {
oscBuf[i]->begin(len); oscBuf[i]->begin(len);
} }
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
runDAC(); runDAC(0,1);
runTFX(); runTFX(0,1);
if (!writes.empty()) { if (!writes.empty()) {
QueuedWrite w=writes.front(); QueuedWrite w=writes.front();
@ -404,8 +418,8 @@ void DivPlatformAY8910::acquire(short** buf, size_t len) {
void DivPlatformAY8910::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) { void DivPlatformAY8910::fillStream(std::vector<DivDelayedWrite>& stream, int sRate, size_t len) {
writes.clear(); writes.clear();
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
runDAC(sRate); runDAC(sRate,1);
runTFX(sRate); runTFX(sRate,1);
while (!writes.empty()) { while (!writes.empty()) {
QueuedWrite& w=writes.front(); QueuedWrite& w=writes.front();
stream.push_back(DivDelayedWrite(i,w.addr,w.val)); stream.push_back(DivDelayedWrite(i,w.addr,w.val));

View file

@ -157,8 +157,8 @@ class DivPlatformAY8910: public DivDispatch {
friend void putDispatchChan(void*,int,int); friend void putDispatchChan(void*,int,int);
public: public:
void runDAC(int runRate=0); void runDAC(int runRate=0, int advance=1);
void runTFX(int runRate=0); void runTFX(int runRate=0, int advance=1);
void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8); void setExtClockDiv(unsigned int eclk=COLOR_NTSC, unsigned char ediv=8);
void acquire(short** buf, size_t len); void acquire(short** buf, size_t len);
void acquireDirect(blip_buffer_t** bb, size_t len); void acquireDirect(blip_buffer_t** bb, size_t len);

View file

@ -109,14 +109,14 @@ const unsigned char dacLogTableAY8930[256]={
30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31 30, 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
}; };
void DivPlatformAY8930::runDAC() { void DivPlatformAY8930::runDAC(int advance) {
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (chan[i].active && (chan[i].curPSGMode.val&8) && chan[i].dac.sample!=-1) { if (chan[i].active && (chan[i].curPSGMode.val&8) && chan[i].dac.sample!=-1) {
chan[i].dac.period+=chan[i].dac.rate; chan[i].dac.period+=chan[i].dac.rate*advance;
bool end=false; bool end=false;
bool changed=false; bool changed=false;
int prevOut=chan[i].dac.out; int prevOut=chan[i].dac.out;
while (chan[i].dac.period>rate && !end) { while (chan[i].dac.period>=rate && !end) {
DivSample* s=parent->getSample(chan[i].dac.sample); DivSample* s=parent->getSample(chan[i].dac.sample);
if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) { if (s->samples<=0 || chan[i].dac.pos<0 || chan[i].dac.pos>=(int)s->samples) {
chan[i].dac.sample=-1; chan[i].dac.sample=-1;
@ -172,28 +172,59 @@ void DivPlatformAY8930::acquireDirect(blip_buffer_t** bb, size_t len) {
for (size_t i=0; i<len; i++) { for (size_t i=0; i<len; i++) {
int advance=len-i; int advance=len-i;
bool careAboutNoise=false;
// heuristic // heuristic
if (!writes.empty()) {
advance=1;
} else {
for (int j=0; j<3; j++) { for (int j=0; j<3; j++) {
// tone counter // tone counter
if (!ay->tone_enable(j) && ay->m_tone[j].volume!=0) {
const int period=MAX(1,ay->m_tone[j].period)*(ay->m_step_mul<<1); const int period=MAX(1,ay->m_tone[j].period)*(ay->m_step_mul<<1);
const int remain=(period-ay->m_tone[j].count)>>5; const int remain=(period-ay->m_tone[j].count)>>5;
if (remain<advance) advance=remain; if (remain<advance) {
advance=remain;
}
}
// envelope // count me in if I have noise enabled
if (!ay->noise_enable(j) && ay->m_tone[j].volume!=0) {
careAboutNoise=true;
}
// envelope check
if (ay->m_tone[j].volume&32) {
if (ay->m_envelope[j].holding==0) { if (ay->m_envelope[j].holding==0) {
const int periodEnv=MAX(1,ay->m_envelope[j].period)*ay->m_env_step_mul; const int periodEnv=MAX(1,ay->m_envelope[j].period)*ay->m_env_step_mul;
const int remainEnv=periodEnv-ay->m_envelope[j].count; const int remainEnv=periodEnv-ay->m_envelope[j].count;
if (remainEnv<advance) advance=remainEnv; if (remainEnv<advance) {
advance=remainEnv;
} }
} }
}
// DAC
if (chan[j].active && (chan[j].curPSGMode.val&8) && chan[j].dac.sample!=-1) {
if (chan[j].dac.rate<=0) continue;
const int remainTime=(rate-chan[j].dac.period+chan[j].dac.rate-1)/chan[j].dac.rate;
if (remainTime<advance) advance=remainTime;
}
if (advance<=1) break;
}
// noise // noise
if (careAboutNoise) {
const int noisePeriod=((int)ay->noise_period())*ay->m_step_mul; const int noisePeriod=((int)ay->noise_period())*ay->m_step_mul;
const int noiseRemain=noisePeriod-ay->m_count_noise; const int noiseRemain=noisePeriod-ay->m_count_noise;
if (noiseRemain<advance) advance=noiseRemain; if (noiseRemain<advance) {
advance=noiseRemain;
}
}
}
//runDAC(); if (advance<1) advance=1;
if (!writes.empty() || advance<1) advance=1; runDAC(advance);
checkWrites(); checkWrites();
ay->sound_stream_update(ayBuf,advance); ay->sound_stream_update(ayBuf,advance);

View file

@ -123,7 +123,7 @@ class DivPlatformAY8930: public DivDispatch {
short oldWrites[32]; short oldWrites[32];
short pendingWrites[32]; short pendingWrites[32];
void runDAC(); void runDAC(int advance);
void checkWrites(); void checkWrites();
void updateOutSel(bool immediate=false); void updateOutSel(bool immediate=false);
void immWrite(unsigned char a, unsigned char v); void immWrite(unsigned char a, unsigned char v);