OPN/A/B: fix PCM and timer FX rates

unfortunately lowest divider (prescaler) is broken in LLE
This commit is contained in:
tildearrow 2026-01-13 03:34:42 -05:00
parent 1692114deb
commit 857d178860
6 changed files with 64 additions and 32 deletions

View file

@ -165,6 +165,7 @@ class DivPlatformOPN: public DivPlatformFMBase {
double fmFreqBase;
unsigned int fmDivBase;
unsigned int ayDiv;
int tfxRate;
unsigned char csmChan;
unsigned char lfoValue;
unsigned char lastExtChPan;

View file

@ -175,8 +175,8 @@ void DivPlatformYM2203::acquire_combo(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -269,8 +269,8 @@ void DivPlatformYM2203::acquire_ymfm(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -342,8 +342,8 @@ void DivPlatformYM2203::acquire_lle(short** buf, size_t len) {
}
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -1446,6 +1446,17 @@ void DivPlatformYM2203::setFlags(const DivConfig& flags) {
} else {
rate=fm->sample_rate(chipClock);
}
switch (ayDiv) {
case 4:
tfxRate=rate/2;
break;
case 8:
tfxRate=rate;
break;
default:
tfxRate=rate*2;
break;
}
for (int i=0; i<7; i++) {
oscBuf[i]->setRate(rate);
}

View file

@ -326,8 +326,8 @@ void DivPlatformYM2608::acquire_combo(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -453,8 +453,8 @@ void DivPlatformYM2608::acquire_ymfm(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -533,8 +533,8 @@ void DivPlatformYM2608::acquire_lle(short** buf, size_t len) {
unsigned char subSubCycle=0;
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -2038,6 +2038,17 @@ void DivPlatformYM2608::setFlags(const DivConfig& flags) {
} else {
rate=fm->sample_rate(chipClock);
}
switch (ayDiv) {
case 8:
tfxRate=rate;
break;
case 16:
tfxRate=rate*2;
break;
default:
tfxRate=rate*4;
break;
}
for (int i=0; i<17; i++) {
oscBuf[i]->setRate(rate);
}

View file

@ -262,8 +262,8 @@ void DivPlatformYM2610::acquire_combo(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -287,8 +287,8 @@ void DivPlatformYM2610::acquire_combo(short** buf, size_t len) {
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
delay=(w.addr>15)?32:1;
writes.pop_front();
delay=32;
} else {
// Nuked write
if (w.addrOrVal) {
@ -387,8 +387,8 @@ void DivPlatformYM2610::acquire_ymfm(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -397,8 +397,11 @@ void DivPlatformYM2610::acquire_ymfm(short** buf, size_t len) {
ay->getRegisterWrites().clear();
os[0]=0; os[1]=0;
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
while (!writes.empty()) {
if (!(fm->read(0)&0x80)) {
delay=0;
}
if (delay<1) {
QueuedWrite& w=writes.front();
if (w.addr==0xfffffffe) {
delay=w.val*2;
@ -406,10 +409,11 @@ void DivPlatformYM2610::acquire_ymfm(short** buf, size_t len) {
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
delay=1;
if (w.addr>15) delay=1;
}
writes.pop_front();
}
if (delay>0) break;
}
fm->generate(&fmout);
@ -466,8 +470,8 @@ void DivPlatformYM2610::acquire_lle(short** buf, size_t len) {
unsigned char subSubCycle=0;
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;

View file

@ -326,8 +326,8 @@ void DivPlatformYM2610B::acquire_combo(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -351,8 +351,8 @@ void DivPlatformYM2610B::acquire_combo(short** buf, size_t len) {
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
delay=(w.addr>15)?32:1;
writes.pop_front();
delay=32;
} else {
// Nuked write
if (w.addrOrVal) {
@ -453,8 +453,8 @@ void DivPlatformYM2610B::acquire_ymfm(short** buf, size_t len) {
for (size_t h=0; h<len; h++) {
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;
@ -463,8 +463,11 @@ void DivPlatformYM2610B::acquire_ymfm(short** buf, size_t len) {
ay->getRegisterWrites().clear();
os[0]=0; os[1]=0;
if (!writes.empty()) {
if (--delay<1 && !(fm->read(0)&0x80)) {
while (!writes.empty()) {
if (!(fm->read(0)&0x80)) {
delay=0;
}
if (delay<1) {
QueuedWrite& w=writes.front();
if (w.addr==0xfffffffe) {
delay=w.val*2;
@ -472,10 +475,11 @@ void DivPlatformYM2610B::acquire_ymfm(short** buf, size_t len) {
fm->write(0x0+((w.addr>>8)<<1),w.addr);
fm->write(0x1+((w.addr>>8)<<1),w.val);
regPool[w.addr&0x1ff]=w.val;
delay=1;
if (w.addr>15) delay=1;
}
writes.pop_front();
}
if (delay>0) break;
}
fm->generate(&fmout);
@ -534,8 +538,8 @@ void DivPlatformYM2610B::acquire_lle(short** buf, size_t len) {
unsigned char subSubCycle=0;
// AY -> OPN
ay->runDAC();
ay->runTFX(rate);
ay->runDAC(tfxRate);
ay->runTFX(tfxRate);
ay->flushWrites();
for (DivRegWrite& i: ay->getRegisterWrites()) {
if (i.addr>15) continue;

View file

@ -319,6 +319,7 @@ class DivPlatformYM2610Base: public DivPlatformOPN {
} else {
rate=fm->sample_rate(chipClock);
}
tfxRate=rate*4;
for (int i=0; i<17; i++) {
oscBuf[i]->setRate(rate);
}