diff --git a/src/engine/platform/ay.cpp b/src/engine/platform/ay.cpp index 015aa3306..4d57d022f 100644 --- a/src/engine/platform/ay.cpp +++ b/src/engine/platform/ay.cpp @@ -360,6 +360,15 @@ void DivPlatformAY8910::tick(bool sysTick) { chan[i].freqChanged=true; if (!chan[i].std.ex3.will) chan[i].autoEnvNum=1; } + if (chan[i].std.ex4.had) { + chan[i].fixedFreq=chan[i].std.ex4.val; + chan[i].freqChanged=true; + } + if (chan[i].std.ex5.had) { + ayEnvPeriod=chan[i].std.ex5.val; + immWrite(0x0b,ayEnvPeriod); + immWrite(0x0c,ayEnvPeriod>>8); + } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].dac.furnaceDAC) { @@ -377,6 +386,7 @@ void DivPlatformAY8910::tick(bool sysTick) { } if (chan[i].freq<0) chan[i].freq=0; if (chan[i].freq>4095) chan[i].freq=4095; + if (chan[i].fixedFreq>4095) chan[i].fixedFreq=4095; if (chan[i].keyOn) { //rWrite(16+i*5+1,((chan[i].duty&3)<<6)|(63-(ins->gb.soundLen&63))); //rWrite(16+i*5+2,((chan[i].vol<<4))|(ins->gb.envLen&7)|((ins->gb.envDir&1)<<3)); @@ -388,8 +398,13 @@ void DivPlatformAY8910::tick(bool sysTick) { chan[i].curPSGMode.val=0; rWrite(0x08+i,0); } - rWrite((i)<<1,chan[i].freq&0xff); - rWrite(1+((i)<<1),chan[i].freq>>8); + if (chan[i].fixedFreq>0) { + rWrite((i)<<1,chan[i].fixedFreq&0xff); + rWrite(1+((i)<<1),chan[i].fixedFreq>>8); + } else { + rWrite((i)<<1,chan[i].freq&0xff); + rWrite(1+((i)<<1),chan[i].freq>>8); + } if (chan[i].keyOn) chan[i].keyOn=false; if (chan[i].keyOff) chan[i].keyOff=false; if (chan[i].freqChanged && chan[i].autoEnvNum>0 && chan[i].autoEnvDen>0) { @@ -516,6 +531,7 @@ int DivPlatformAY8910::dispatch(DivCommand c) { chan[c.chan].freqChanged=true; chan[c.chan].note=c.value; } + chan[c.chan].fixedFreq=0; chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); diff --git a/src/engine/platform/ay.h b/src/engine/platform/ay.h index ea37a5cba..49641c328 100644 --- a/src/engine/platform/ay.h +++ b/src/engine/platform/ay.h @@ -74,6 +74,7 @@ class DivPlatformAY8910: public DivDispatch { unsigned char autoEnvNum, autoEnvDen; signed char konCycles; + unsigned short fixedFreq; Channel(): SharedChannel(15), curPSGMode(PSGMode(0)), @@ -81,7 +82,8 @@ class DivPlatformAY8910: public DivDispatch { dac(DAC()), autoEnvNum(0), autoEnvDen(0), - konCycles(0) {} + konCycles(0), + fixedFreq(0) {} }; Channel chan[3]; bool isMuted[3]; diff --git a/src/engine/platform/ay8930.cpp b/src/engine/platform/ay8930.cpp index 68e25740a..334bb5295 100644 --- a/src/engine/platform/ay8930.cpp +++ b/src/engine/platform/ay8930.cpp @@ -323,6 +323,15 @@ void DivPlatformAY8930::tick(bool sysTick) { ayNoiseOr=chan[i].std.fms.val; immWrite(0x1a,ayNoiseOr); } + if (chan[i].std.ex4.had) { + chan[i].fixedFreq=chan[i].std.ex4.val; + chan[i].freqChanged=true; + } + if (chan[i].std.ex5.had) { + chan[i].envelope.period=chan[i].std.ex5.val; + immWrite(regPeriodL[i],chan[i].envelope.period); + immWrite(regPeriodH[i],chan[i].envelope.period>>8); + } if (chan[i].freqChanged || chan[i].keyOn || chan[i].keyOff) { chan[i].freq=parent->calcFreq(chan[i].baseFreq,chan[i].pitch,chan[i].fixedArp?chan[i].baseNoteOverride:chan[i].arpOff,chan[i].fixedArp,true,0,chan[i].pitch2,chipClock,CHIP_DIVIDER); if (chan[i].dac.furnaceDAC) { @@ -353,8 +362,13 @@ void DivPlatformAY8930::tick(bool sysTick) { chan[i].curPSGMode.val=0; rWrite(0x08+i,0); } - rWrite((i)<<1,chan[i].freq&0xff); - rWrite(1+((i)<<1),chan[i].freq>>8); + if (chan[i].fixedFreq>0) { + rWrite((i)<<1,chan[i].fixedFreq&0xff); + rWrite(1+((i)<<1),chan[i].fixedFreq>>8); + } else { + rWrite((i)<<1,chan[i].freq&0xff); + rWrite(1+((i)<<1),chan[i].freq>>8); + } if (chan[i].keyOn) chan[i].keyOn=false; if (chan[i].keyOff) chan[i].keyOff=false; if (chan[i].freqChanged && chan[i].autoEnvNum>0 && chan[i].autoEnvDen>0) { @@ -504,6 +518,7 @@ int DivPlatformAY8930::dispatch(DivCommand c) { chan[c.chan].freqChanged=true; chan[c.chan].note=c.value; } + chan[c.chan].fixedFreq=0; chan[c.chan].active=true; chan[c.chan].keyOn=true; chan[c.chan].macroInit(ins); diff --git a/src/engine/platform/ay8930.h b/src/engine/platform/ay8930.h index e9f3cf21e..7087a246b 100644 --- a/src/engine/platform/ay8930.h +++ b/src/engine/platform/ay8930.h @@ -79,6 +79,7 @@ class DivPlatformAY8930: public DivDispatch { unsigned char autoEnvNum, autoEnvDen, duty, autoNoiseMode; signed char konCycles, autoNoiseOff; + unsigned short fixedFreq; Channel(): SharedChannel(31), envelope(Envelope()), @@ -90,7 +91,8 @@ class DivPlatformAY8930: public DivDispatch { duty(4), autoNoiseMode(0), konCycles(0), - autoNoiseOff(0) {} + autoNoiseOff(0), + fixedFreq(0) {} }; Channel chan[3]; bool isMuted[3]; diff --git a/src/gui/insEdit.cpp b/src/gui/insEdit.cpp index 71f18fdb0..ef239557f 100644 --- a/src/gui/insEdit.cpp +++ b/src/gui/insEdit.cpp @@ -7000,6 +7000,8 @@ void FurnaceGUI::drawInsEdit() { macroList.push_back(FurnaceGUIMacroDesc(_("Envelope"),&ins->std.ex2Macro,0,4,64,uiColors[GUI_COLOR_MACRO_ENVELOPE],false,NULL,NULL,true,ayEnvBits)); macroList.push_back(FurnaceGUIMacroDesc(_("AutoEnv Num"),&ins->std.ex3Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); macroList.push_back(FurnaceGUIMacroDesc(_("AutoEnv Den"),&ins->std.algMacro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("Force Period"),&ins->std.ex4Macro,0,4095,160,uiColors[GUI_COLOR_MACRO_PITCH])); + macroList.push_back(FurnaceGUIMacroDesc(_("Env Period"),&ins->std.ex5Macro,0,65535,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); break; case DIV_INS_AY8930: macroList.push_back(FurnaceGUIMacroDesc(_("Volume"),&ins->std.volMacro,0,31,160,uiColors[GUI_COLOR_MACRO_VOLUME])); @@ -7014,6 +7016,8 @@ void FurnaceGUI::drawInsEdit() { macroList.push_back(FurnaceGUIMacroDesc(_("Envelope"),&ins->std.ex2Macro,0,4,64,uiColors[GUI_COLOR_MACRO_ENVELOPE],false,NULL,NULL,true,ayEnvBits)); macroList.push_back(FurnaceGUIMacroDesc(_("AutoEnv Num"),&ins->std.ex3Macro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); macroList.push_back(FurnaceGUIMacroDesc(_("AutoEnv Den"),&ins->std.algMacro,0,15,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); + macroList.push_back(FurnaceGUIMacroDesc(_("Force Period"),&ins->std.ex4Macro,0,65535,160,uiColors[GUI_COLOR_MACRO_PITCH])); + macroList.push_back(FurnaceGUIMacroDesc(_("Env Period"),&ins->std.ex5Macro,0,65535,160,uiColors[GUI_COLOR_MACRO_ENVELOPE])); macroList.push_back(FurnaceGUIMacroDesc(_("Noise AND Mask"),&ins->std.fbMacro,0,8,96,uiColors[GUI_COLOR_MACRO_NOISE],false,NULL,NULL,true)); macroList.push_back(FurnaceGUIMacroDesc(_("Noise OR Mask"),&ins->std.fmsMacro,0,8,96,uiColors[GUI_COLOR_MACRO_NOISE],false,NULL,NULL,true)); break;