mirror of
https://github.com/tildearrow/furnace.git
synced 2024-11-26 06:25:16 +00:00
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:
parent
eaa943e724
commit
a9591fae71
4 changed files with 68 additions and 24 deletions
|
@ -155,36 +155,64 @@ 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]) {
|
||||||
|
if (intellivision && selCore) {
|
||||||
|
immWrite(0x0b+i,(output&0xc)<<2);
|
||||||
|
} else {
|
||||||
immWrite(0x08+i,output|(chan[i].curPSGMode.getEnvelope()<<2));
|
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]) {
|
||||||
|
if (intellivision && selCore) {
|
||||||
|
immWrite(0xa, ayEnvMode);
|
||||||
|
} else {
|
||||||
immWrite(0xd, ayEnvMode);
|
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;
|
||||||
|
@ -192,6 +220,11 @@ void DivPlatformAY8910::runTFX() {
|
||||||
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;
|
||||||
|
|
|
@ -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}},
|
||||||
};
|
};
|
||||||
|
|
|
@ -130,7 +130,7 @@ const bool mobileButtonPersist[32]={
|
||||||
// page 1
|
// page 1
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
true,
|
||||||
false,
|
false,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue