AY/YM Timer FX bug fixes and improvements
pull request #2547 manual merge due to modification of unrelated files according to GitHub's files view Co-authored-by: host12prog <hungnguyen.481335@gmail.com>
This commit is contained in:
parent
80a92b8b43
commit
dc87bc489f
2 changed files with 54 additions and 37 deletions
|
|
@ -166,17 +166,8 @@ void DivPlatformAY8910::runTFX(int runRate, int advance) {
|
|||
if (runRate!=0) counterRatio=(double)rate/(double)runRate;
|
||||
int timerPeriod, output;
|
||||
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)) {
|
||||
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;
|
||||
|
|
@ -186,12 +177,40 @@ void DivPlatformAY8910::runTFX(int runRate, int advance) {
|
|||
}
|
||||
}
|
||||
chan[i].tfx.counter += counterRatio;
|
||||
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.counter -= chan[i].tfx.period;
|
||||
chan[i].tfx.out ^= 1;
|
||||
switch (chan[i].tfx.mode) {
|
||||
case 0:
|
||||
// pwm
|
||||
// we will handle the modulator gen after this switch... if we don't, crackling happens
|
||||
chan[i].tfx.out ^= 1;
|
||||
break;
|
||||
case 1:
|
||||
// syncbuzzer
|
||||
if (!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 (intellivision && selCore) {
|
||||
immWrite(0xa, ayEnvMode);
|
||||
}
|
||||
else {
|
||||
immWrite(0xd, ayEnvMode);
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
default:
|
||||
// unimplemented, or invalid effects here
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.mode == 0) {
|
||||
// pwm
|
||||
output = ((chan[i].tfx.out) ? chan[i].outVol : (chan[i].tfx.lowBound-(15-chan[i].outVol)));
|
||||
// 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
|
||||
|
|
@ -204,20 +223,6 @@ void DivPlatformAY8910::runTFX(int runRate, int advance) {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 1) {
|
||||
chan[i].tfx.counter -= chan[i].tfx.period;
|
||||
if (!isMuted[i]) {
|
||||
// TODO: ???????
|
||||
if (intellivision && selCore) {
|
||||
immWrite(0xa, ayEnvMode);
|
||||
} else {
|
||||
immWrite(0xd, ayEnvMode);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.counter >= chan[i].tfx.period && chan[i].tfx.mode == 2) {
|
||||
chan[i].tfx.counter -= chan[i].tfx.period;
|
||||
}
|
||||
}
|
||||
if (chan[i].tfx.num > 0) {
|
||||
timerPeriod = chan[i].freq*chan[i].tfx.den/chan[i].tfx.num;
|
||||
|
|
|
|||
|
|
@ -838,6 +838,22 @@ String macroSoundUnitWaves(int id, float val, void* u) {
|
|||
return fmt::sprintf("%d: %s",id,label);
|
||||
}
|
||||
|
||||
String macroTFXModes(int id, float val, void* u) {
|
||||
switch (((int)val)&3) {
|
||||
case 0:
|
||||
return _("Disabled");
|
||||
case 1:
|
||||
return _("PWM");
|
||||
case 2:
|
||||
return _("SyncBuzzer");
|
||||
case 3:
|
||||
return _("Reserved");
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
return "???";
|
||||
}
|
||||
|
||||
String macroSID3SpecialWaves(int id, float val, void* u) {
|
||||
if ((int)val<0 || (int)val>=SID3_NUM_SPECIAL_WAVES) return "???";
|
||||
|
||||
|
|
@ -2099,12 +2115,12 @@ void FurnaceGUI::drawMacroEdit(FurnaceGUIMacroDesc& i, int totalFit, float avail
|
|||
}
|
||||
}
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding,ImVec2(0.0f,0.0f));
|
||||
|
||||
if (MACRO_VZOOM<1) {
|
||||
if (i.macro->macroType==DIV_MACRO_ARP || i.isArp) {
|
||||
MACRO_VZOOM=24;
|
||||
MACRO_VSCROLL=120-12;
|
||||
} else if (i.macro->macroType==DIV_MACRO_PITCH || i.isPitch) {
|
||||
}
|
||||
else if ((i.macro->macroType == DIV_MACRO_PITCH || i.isPitch) || (i.macro->macroType == DIV_MACRO_EX7 && i.isPitch)) {
|
||||
MACRO_VZOOM=128;
|
||||
MACRO_VSCROLL=2048-64;
|
||||
} else {
|
||||
|
|
@ -8762,16 +8778,12 @@ void FurnaceGUI::drawInsEdit() {
|
|||
{
|
||||
if (ImGui::BeginTabItem(_("Timer Macros")))
|
||||
{
|
||||
ImGui::Text(_("warning: timer effects are not supported by VGM export!"));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Timer FX"),&ins->std.ex6Macro,0,3,64,uiColors[GUI_COLOR_MACRO_OTHER]));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("TFX Offset"),&ins->std.ex7Macro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true));
|
||||
ImGui::Text(_("warning: timer effects require direct stream mode to be enabled during VGM export!"));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Timer FX"),&ins->std.ex6Macro,0,2,64,uiColors[GUI_COLOR_MACRO_OTHER],false,NULL,macroTFXModes));
|
||||
macroList.push_back(FurnaceGUIMacroDesc(_("Timer Offset"),&ins->std.ex7Macro,-2048,2047,160,uiColors[GUI_COLOR_MACRO_PITCH],true,macroRelativeMode,NULL,false,NULL,false,NULL,false,true));
|
||||
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(_("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->temp.vZoom[DIV_MACRO_EX7]=128;
|
||||
ins->temp.vScroll[DIV_MACRO_EX7]=2048-64;
|
||||
drawMacros(macroList,macroEditStateMacros,ins);
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue