AY Timer bug fixes and some QOL improvements (#2073)

* Create android.yml

* bug fixes part 1

* bollocks number 1

* Update android.yml

* why are you crackling you arent supposed to do that

* stop crackling please

* what a load of

* what a load of part 2

* what a load of part 3

* what a load of part 4

* final commit... i hope!

* final commit my rear bottom

* final commit for real this time

* Delete .github/workflows/android.yml

* Update sysDef.cpp
This commit is contained in:
Aleksi Knutsi 2024-08-16 03:55:29 +07:00 committed by GitHub
parent eaa943e724
commit a9591fae71
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 68 additions and 24 deletions

View file

@ -155,43 +155,76 @@ void DivPlatformAY8910::runDAC() {
} }
void DivPlatformAY8910::runTFX() { void DivPlatformAY8910::runTFX() {
if (selCore) return; /*
developer's note: if you are checking for intellivision
make sure to add "&& selCore"
because for some reason, the register remap doesn't work
when the user uses AtomicSSG core
*/
int timerPeriod, output; int timerPeriod, output;
for (int i=0; i<3; i++) { for (int i=0; i<3; i++) {
if (chan[i].active && (chan[i].curPSGMode.val&16) && !(chan[i].curPSGMode.val&8) && chan[i].tfx.mode!=-1) { if (chan[i].active && (chan[i].curPSGMode.val&16) && !(chan[i].curPSGMode.val&8) && chan[i].tfx.mode!=-1) {
if (chan[i].tfx.mode == -1 && !isMuted[i]) {
/*
bug: if in the timer FX macro the user enables
and then disables PWM while there is no volume macro
there is now a random chance that the resulting output
is silent or has volume set incorrectly
i've tried to implement a fix, but it seems to be
ineffective, so...
TODO: actually implement a proper fix
*/
if (intellivision && chan[i].curPSGMode.getEnvelope()) {
immWrite(0x08+i,(chan[i].outVol&0xc)<<2);
continue;
} else {
immWrite(0x08+i,(chan[i].outVol&15)|((chan[i].curPSGMode.getEnvelope())<<2));
continue;
}
}
chan[i].tfx.counter += 1; chan[i].tfx.counter += 1;
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 0) { if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 0) {
chan[i].tfx.counter = 0; chan[i].tfx.counter = 0;
chan[i].tfx.out ^= 1; chan[i].tfx.out ^= 1;
output = MAX(0, ((chan[i].tfx.out) ? (chan[i].outVol&15) : (chan[i].tfx.lowBound-(15-chan[i].outVol)))); output = ((chan[i].tfx.out) ? chan[i].outVol : (chan[i].tfx.lowBound-(15-chan[i].outVol)));
output &= 15; // TODO: fix this stupid crackling noise that happens
// everytime the volume changes
output = (output <= 0) ? 0 : output; // underflow
output = (output >= 15) ? 15 : output; // overflow
output &= 15; // i don't know if i need this but i'm too scared to remove it
if (!isMuted[i]) { if (!isMuted[i]) {
immWrite(0x08+i,output|(chan[i].curPSGMode.getEnvelope()<<2)); if (intellivision && selCore) {
immWrite(0x0b+i,(output&0xc)<<2);
} else {
immWrite(0x08+i,output|(chan[i].curPSGMode.getEnvelope()<<2));
}
} }
} }
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 1) { if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 1) {
chan[i].tfx.counter = 0; chan[i].tfx.counter = 0;
if (!isMuted[i]) { if (!isMuted[i]) {
immWrite(0xd, ayEnvMode); if (intellivision && selCore) {
immWrite(0xa, ayEnvMode);
} else {
immWrite(0xd, ayEnvMode);
}
} }
} }
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 2) { if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 2) {
chan[i].tfx.counter = 0; chan[i].tfx.counter = 0;
} }
if (chan[i].tfx.mode == -1 && !isMuted[i]) {
if (intellivision && chan[i].curPSGMode.getEnvelope()) {
immWrite(0x08+i,(chan[i].outVol&0xc)<<2);
} else {
immWrite(0x08+i,(chan[i].outVol&15)|((chan[i].curPSGMode.getEnvelope())<<2));
}
}
} }
if (chan[i].tfx.num > 0) { if (chan[i].tfx.num > 0) {
timerPeriod = chan[i].freq*chan[i].tfx.den/chan[i].tfx.num; timerPeriod = chan[i].freq*chan[i].tfx.den/chan[i].tfx.num;
} else { } else {
timerPeriod = chan[i].freq*chan[i].tfx.den; timerPeriod = chan[i].freq*chan[i].tfx.den;
} }
if (chan[i].tfx.num > 0 && chan[i].tfx.den > 0) chan[i].tfx.period=timerPeriod+chan[i].tfx.offset; if (chan[i].tfx.num > 0 && chan[i].tfx.den > 0) chan[i].tfx.period=timerPeriod+chan[i].tfx.offset;
// stupid pitch correction because:
// YM2149 half-clock and Sunsoft 5B: timers run an octave too high
// on AtomicSSG core timers run 2 octaves too high
if (clockSel || sunsoft) chan[i].tfx.period = chan[i].tfx.period * 2;
if (selCore) chan[i].tfx.period = chan[i].tfx.period * 4;
} }
} }
@ -388,6 +421,7 @@ void DivPlatformAY8910::tick(bool sysTick) {
if (chan[i].std.phaseReset.had) { if (chan[i].std.phaseReset.had) {
if (chan[i].std.phaseReset.val==1) { if (chan[i].std.phaseReset.val==1) {
chan[i].tfx.counter = 0; chan[i].tfx.counter = 0;
chan[i].tfx.out = 0;
if (chan[i].nextPSGMode.val&8) { if (chan[i].nextPSGMode.val&8) {
if (dumpWrites) addWrite(0xffff0002+(i<<8),0); if (dumpWrites) addWrite(0xffff0002+(i<<8),0);
if (chan[i].dac.sample<0 || chan[i].dac.sample>=parent->song.sampleLen) { if (chan[i].dac.sample<0 || chan[i].dac.sample>=parent->song.sampleLen) {
@ -726,12 +760,10 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
break; break;
} }
case DIV_CMD_STD_NOISE_MODE: case DIV_CMD_STD_NOISE_MODE:
if (c.value&0xf0 && !(chan[c.chan].nextPSGMode.val&8)) {
chan[c.chan].nextPSGMode.val|=16;
chan[c.chan].tfx.mode = (c.value&3);
}
if (!(chan[c.chan].nextPSGMode.val&8)) { if (!(chan[c.chan].nextPSGMode.val&8)) {
if (c.value<16) { chan[c.chan].nextPSGMode.val|=16;
chan[c.chan].tfx.mode=(((c.value&0xf0)>>4)&3)-1;
if ((c.value&15)<16) {
chan[c.chan].nextPSGMode.val=(c.value+1)&7; chan[c.chan].nextPSGMode.val=(c.value+1)&7;
chan[c.chan].nextPSGMode.val|=chan[c.chan].curPSGMode.val&16; chan[c.chan].nextPSGMode.val|=chan[c.chan].curPSGMode.val&16;
if (chan[c.chan].active) { if (chan[c.chan].active) {
@ -805,9 +837,16 @@ int DivPlatformAY8910::dispatch(DivCommand c) {
updateOutSel(true); updateOutSel(true);
immWrite(14+(c.value?1:0),(c.value?portBVal:portAVal)); immWrite(14+(c.value?1:0),(c.value?portBVal:portAVal));
break; break;
case DIV_CMD_AY_AUTO_PWM: case DIV_CMD_AY_NOISE_MASK_AND:
chan[c.chan].tfx.offset=c.value; chan[c.chan].tfx.num=c.value>>4;
chan[c.chan].tfx.den=c.value&15;
break; break;
case DIV_CMD_AY_AUTO_PWM: {
// best way i could find to do signed :/
signed char signVal=c.value;
chan[c.chan].tfx.offset=signVal;
break;
}
case DIV_CMD_SAMPLE_MODE: case DIV_CMD_SAMPLE_MODE:
if (c.value>0) { if (c.value>0) {
chan[c.chan].nextPSGMode.val|=8; chan[c.chan].nextPSGMode.val|=8;

View file

@ -433,6 +433,7 @@ void DivEngine::registerSystems() {
{0x25, {DIV_CMD_AY_ENVELOPE_SLIDE, _("25xx: Envelope slide up"), negEffectVal}}, {0x25, {DIV_CMD_AY_ENVELOPE_SLIDE, _("25xx: Envelope slide up"), negEffectVal}},
{0x26, {DIV_CMD_AY_ENVELOPE_SLIDE, _("26xx: Envelope slide down")}}, {0x26, {DIV_CMD_AY_ENVELOPE_SLIDE, _("26xx: Envelope slide down")}},
{0x29, {DIV_CMD_AY_AUTO_ENVELOPE, _("29xy: Set auto-envelope (x: numerator; y: denominator)")}}, {0x29, {DIV_CMD_AY_AUTO_ENVELOPE, _("29xy: Set auto-envelope (x: numerator; y: denominator)")}},
{0x2c, {DIV_CMD_AY_AUTO_PWM, _("2Cxx: Set timer period offset (bit 7: sign)")}},
{0x2e, {DIV_CMD_AY_IO_WRITE, _("2Exx: Write to I/O port A"), constVal<0>, effectVal}}, {0x2e, {DIV_CMD_AY_IO_WRITE, _("2Exx: Write to I/O port A"), constVal<0>, effectVal}},
{0x2f, {DIV_CMD_AY_IO_WRITE, _("2Fxx: Write to I/O port B"), constVal<1>, effectVal}}, {0x2f, {DIV_CMD_AY_IO_WRITE, _("2Fxx: Write to I/O port B"), constVal<1>, effectVal}},
}; };

View file

@ -130,7 +130,7 @@ const bool mobileButtonPersist[32]={
// page 1 // page 1
false, false,
false, false,
false, true,
false, false,
true, true,
true, true,

View file

@ -7569,6 +7569,10 @@ void FurnaceGUI::drawInsEdit() {
macroList.push_back(FurnaceGUIMacroDesc(_("Timer Num"),&ins->std.ex8Macro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(_("Timer Num"),&ins->std.ex8Macro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(_("Timer Den"),&ins->std.fmsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(_("Timer Den"),&ins->std.fmsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
macroList.push_back(FurnaceGUIMacroDesc(_("PWM Boundary"),&ins->std.amsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER])); macroList.push_back(FurnaceGUIMacroDesc(_("PWM Boundary"),&ins->std.amsMacro,0,15,64,uiColors[GUI_COLOR_MACRO_OTHER]));
// workaround, because the gui will not set
// zoom or scroll if we're not in macros tab
ins->std.ex7Macro.vZoom=128;
ins->std.ex7Macro.vScroll=2048-64;
drawMacros(macroList,macroEditStateMacros); drawMacros(macroList,macroEditStateMacros);
ImGui::EndTabItem(); ImGui::EndTabItem();
} }