shithub: pt2-clone

Download patch

ref: 6f0d2c3ee753d40fd9bc5d325fe6605e4e38c3bc
parent: 0d1a2cf15c023a03f0ee62017133b7035e142a56
author: Olav Sørensen <olav.sorensen@live.no>
date: Fri Apr 3 15:01:30 EDT 2020

Pushed v1.08 code

- The mouse system has been rewritten so that we don't need to do mouse
  capturing while interacting with GUI widgets, which could be buggy sometimes.
- Fixed a bug when exiting from Edit Op. screen #4 ("Sample chord editor") and
  reopening it. It could mess up the UI in worst case scenarios.
- Some other small miscellaneous changes not worth of a mention
- Small code cleanup (and also the opposite :-)

--- a/src/pt2_audio.c
+++ b/src/pt2_audio.c
@@ -53,11 +53,10 @@
 } paulaVoice_t;
 
 static volatile int8_t filterFlags;
-static volatile bool audioLocked;
 static int8_t defStereoSep;
 static bool amigaPanFlag, wavRenderingDone;
-static uint16_t ch1Pan, ch2Pan, ch3Pan, ch4Pan, oldPeriod;
-static int32_t sampleCounter, maxSamplesToMix, randSeed = INITIAL_DITHER_SEED;
+static uint16_t ch1Pan, ch2Pan, ch3Pan, ch4Pan;
+static int32_t oldPeriod, sampleCounter, maxSamplesToMix, randSeed = INITIAL_DITHER_SEED;
 static uint32_t oldScopeDelta;
 static double *dMixBufferL, *dMixBufferR, *dMixBufferLUnaligned, *dMixBufferRUnaligned, dOldVoiceDelta, dOldVoiceDeltaMul;
 static double dPrngStateL, dPrngStateR;
@@ -69,7 +68,6 @@
 static SDL_AudioDeviceID dev;
 
 // globalized
-bool forceMixerOff = false;
 int32_t samplesPerTick;
 
 bool intMusic(void); // defined in pt_modplayer.c
@@ -128,7 +126,8 @@
 
 #ifndef NO_FILTER_FINETUNING
 	/* 8bitbubsy: makes the filter curve sound (and look) much closer to the real deal.
-	** This has been tested against both an A500 and A1200 (real units). */
+	** This has been tested against both an A500 and A1200 (real units).
+	*/
 	dFb *= 0.62;
 #endif
 
@@ -184,7 +183,8 @@
 	** This implementation has a less smooth cutoff curve compared to the old one, so it's
 	** maybe not the best. However, I stick to this one because it has a higher gain
 	** at the end of the curve (closer to real tested Amiga 500). It also sounds much closer when
-	** comparing whitenoise on an A500. */
+	** comparing whitenoise on an A500.
+	*/
 
 	// left channel low-pass
 	filter->dBuffer[0] = (filter->b0 * dIn[0]) + (filter->b1 * filter->dBuffer[0]) + DENORMAL_OFFSET;
@@ -224,7 +224,8 @@
 ** parameter range and have 'normalized' (1/2 = 0db) coeffs
 **
 ** the coeffs are for LERP(x, x * x, 0.224) * sqrt(2)
-** max_error is minimized with 0.224 = 0.0013012886 */
+** max_error is minimized with 0.224 = 0.0013012886
+*/
 static double sinApx(double fX)
 {
 	fX = fX * (2.0 - fX);
@@ -242,7 +243,7 @@
 	if (dev != 0)
 		SDL_LockAudioDevice(dev);
 
-	audioLocked = true;
+	audio.locked = true;
 }
 
 void unlockAudio(void)
@@ -250,41 +251,15 @@
 	if (dev != 0)
 		SDL_UnlockAudioDevice(dev);
 
-	audioLocked = false;
+	audio.locked = false;
 }
 
-void clearPaulaAndScopes(void)
-{
-	uint8_t i;
-	double dOldPanL[4], dOldPanR[4];
-
-	// copy old pans
-	for (i = 0; i < AMIGA_VOICES; i++)
-	{
-		dOldPanL[i] = paula[i].dPanL;
-		dOldPanR[i] = paula[i].dPanR;
-	}
-
-	lockAudio();
-	memset(paula, 0, sizeof (paula));
-	unlockAudio();
-
-	// store old pans
-	for (i = 0; i < AMIGA_VOICES; i++)
-	{
-		paula[i].dPanL = dOldPanL[i];
-		paula[i].dPanR = dOldPanR[i];
-	}
-
-	clearScopes();
-}
-
 void mixerUpdateLoops(void) // updates Paula loop (+ scopes)
 {
 	moduleChannel_t *ch;
 	moduleSample_t *s;
 
-	for (uint8_t i = 0; i < AMIGA_VOICES; i++)
+	for (int32_t i = 0; i < AMIGA_VOICES; i++)
 	{
 		ch = &modEntry->channels[i];
 		if (ch->n_samplenum == editor.currSample)
@@ -291,7 +266,7 @@
 		{
 			s = &modEntry->samples[editor.currSample];
 			paulaSetData(i, ch->n_start + s->loopStart);
-			paulaSetLength(i, s->loopLength / 2);
+			paulaSetLength(i, s->loopLength >> 1);
 		}
 	}
 }
@@ -302,7 +277,8 @@
 
 	/* proper 'normalized' equal-power panning is (assuming pan left to right):
 	** L = cos(p * pi * 1/2) * sqrt(2);
-	** R = sin(p * pi * 1/2) * sqrt(2); */
+	** R = sin(p * pi * 1/2) * sqrt(2);
+	*/
 	dPan = pan * (1.0 / 256.0); // 0.0..1.0
 
 	paula[ch].dPanL = cosApx(dPan);
@@ -311,24 +287,34 @@
 
 void mixerKillVoice(uint8_t ch)
 {
-	paulaVoice_t *v;
-	scopeChannelExt_t *s;
+	const bool wasLocked = audio.locked;
+	if (!wasLocked)
+		lockAudio();
 
-	v = &paula[ch];
-	s = &scopeExt[ch];
+	// copy old pans
+	const double dOldPanL = paula[ch].dPanL;
+	const double dOldPanR = paula[ch].dPanR;
 
-	v->active = false;
-	v->dVolume = 0.0;
+	memset(&paula[ch], 0, sizeof (paulaVoice_t));
+	stopScope(ch);
 
-	s->active = false;
-	s->didSwapData = false;
+	// store old pans
+	paula[ch].dPanL = dOldPanL;
+	paula[ch].dPanR = dOldPanR;
 
 	memset(&blep[ch], 0, sizeof (blep_t));
 	memset(&blepVol[ch], 0, sizeof (blep_t));
+
+	if (!wasLocked)
+		unlockAudio();
 }
 
 void turnOffVoices(void)
 {
+	const bool wasLocked = audio.locked;
+	if (!wasLocked)
+		lockAudio();
+
 	for (uint8_t i = 0; i < AMIGA_VOICES; i++)
 		mixerKillVoice(i);
 
@@ -339,72 +325,21 @@
 	resetAudioDithering();
 
 	editor.tuningFlag = false;
-}
 
-void paulaStopDMA(uint8_t ch)
-{
-	scopeExt[ch].active = paula[ch].active = false;
+	if (!wasLocked)
+		unlockAudio();
 }
 
-void paulaStartDMA(uint8_t ch)
-{
-	const int8_t *dat;
-	int32_t length;
-	paulaVoice_t *v;
-	scopeChannel_t s, *sc;
-	scopeChannelExt_t *se;
-
-	// trigger voice
-
-	v  = &paula[ch];
-
-	dat = v->newData;
-	if (dat == NULL)
-		dat = &modEntry->sampleData[RESERVED_SAMPLE_OFFSET]; // dummy sample
-
-	length = v->newLength;
-	if (length < 2)
-		length = 2; // for safety
-
-	v->dPhase = 0.0;
-	v->pos = 0;
-	v->data = dat;
-	v->length = length;
-	v->active = true;
-
-	// trigger scope
-
-	sc = &scope[ch];
-	se = &scopeExt[ch];
-	s = *sc; // cache it
-
-	dat = se->newData;
-	if (dat == NULL)
-		dat = &modEntry->sampleData[RESERVED_SAMPLE_OFFSET]; // dummy sample
-
-	s.length = length;
-	s.data = dat;
-
-	s.pos = 0;
-	s.posFrac = 0;
-
-	// data/length is already set from replayer thread (important)
-	s.loopFlag = se->newLoopFlag;
-	s.loopStart = se->newLoopStart;
-
-	se->didSwapData = false;
-	se->active = true;
-
-	*sc = s; // update it
-}
-
 void resetCachedMixerPeriod(void)
 {
-	oldPeriod = 0;
+	oldPeriod = 0xFFFFFFFF;
 }
 
+// the following routines are only called from the mixer thread.
+
 void paulaSetPeriod(uint8_t ch, uint16_t period)
 {
+	int32_t realPeriod;
 	double dPeriodToDeltaDiv;
 	paulaVoice_t *v;
 
@@ -411,32 +346,22 @@
 	v = &paula[ch];
 
 	if (period == 0)
-	{
-		v->dDelta = 0.0; // confirmed behavior on real Amiga
-		v->dDeltaMul = 1.0; // for BLEP synthesis
-		setScopeDelta(ch, 0);
-		return;
-	}
+		realPeriod = 65536; // confirmed behavior on real Amiga
+	else if (period < 113)
+		realPeriod = 113; // confirmed behavior on real Amiga
+	else
+		realPeriod = period;
 
-	if (period < 113)
-		period = 113; // confirmed behavior on real Amiga
-
 	// if the new period was the same as the previous period, use cached deltas
-	if (period == oldPeriod)
+	if (realPeriod != oldPeriod)
 	{
-		v->dDelta = dOldVoiceDelta;
-		v->dDeltaMul = dOldVoiceDeltaMul; // for BLEP synthesis
-		setScopeDelta(ch, oldScopeDelta);
-	}
-	else 
-	{
+		oldPeriod = realPeriod;
+
 		// this period is not cached, calculate mixer/scope deltas
 
 #if SCOPE_HZ != 64
 #error Scope Hz is not 64 (2^n), change rate calc. to use doubles+round in pt2_scope.c
 #endif
-		oldPeriod = period;
-
 		// if we are rendering pattern to sample (PAT2SMP), use different frequencies
 		if (editor.isSMPRendering)
 			dPeriodToDeltaDiv = editor.pat2SmpHQ ? (PAULA_PAL_CLK / 28836.0) : (PAULA_PAL_CLK / 22168.0);
@@ -443,17 +368,16 @@
 		else
 			dPeriodToDeltaDiv = audio.dPeriodToDeltaDiv;
 
-		v->dDelta = dPeriodToDeltaDiv / period;
-		v->dDeltaMul = 1.0 / v->dDelta; // for BLEP synthesis
-
 		// cache these
-		dOldVoiceDelta = v->dDelta;
-		dOldVoiceDeltaMul = v->dDeltaMul; // for BLEP synthesis
-		oldScopeDelta = (PAULA_PAL_CLK * (65536UL / SCOPE_HZ)) / period;
-
-		setScopeDelta(ch, oldScopeDelta);
+		dOldVoiceDelta = dPeriodToDeltaDiv / realPeriod;
+		dOldVoiceDeltaMul = 1.0 / dOldVoiceDelta; // for BLEP synthesis
+		oldScopeDelta = (PAULA_PAL_CLK * (65536UL / SCOPE_HZ)) / realPeriod;
 	}
 
+	v->dDelta = dOldVoiceDelta;
+	v->dDeltaMul = dOldVoiceDeltaMul; // for BLEP synthesis
+	setScopeDelta(ch, oldScopeDelta);
+
 	// for BLEP synthesis
 
 	if (v->dLastDelta == 0.0)
@@ -478,13 +402,13 @@
 	if (len == 0)
 	{
 		len = 65535;
-		/* confirmed behavior on real Amiga (also needed for safety)
+		/* Confirmed behavior on real Amiga (also needed for safety).
 		** And yes, we have room for this, it will never overflow!
 		*/
 	}
 
 	// our mixer works with bytes, not words. Multiply by two
-	scopeExt[ch].newLength = paula[ch].newLength = len * 2;
+	scopeExt[ch].newLength = paula[ch].newLength = len << 1;
 }
 
 void paulaSetData(uint8_t ch, const int8_t *src)
@@ -514,25 +438,86 @@
 	*se = tmp; // update it
 }
 
+void paulaStopDMA(uint8_t ch)
+{
+	scopeExt[ch].active = paula[ch].active = false;
+}
+
+void paulaStartDMA(uint8_t ch)
+{
+	const int8_t *dat;
+	int32_t length;
+	paulaVoice_t *v;
+	scopeChannel_t s, *sc;
+	scopeChannelExt_t *se;
+
+	// trigger voice
+
+	v  = &paula[ch];
+
+	dat = v->newData;
+	if (dat == NULL)
+		dat = &modEntry->sampleData[RESERVED_SAMPLE_OFFSET]; // dummy sample
+
+	length = v->newLength;
+	if (length < 2)
+		length = 2; // for safety
+
+	v->dPhase = 0.0;
+	v->pos = 0;
+	v->data = dat;
+	v->length = length;
+	v->active = true;
+
+	// trigger scope
+
+	sc = &scope[ch];
+	se = &scopeExt[ch];
+	s = *sc; // cache it
+
+	dat = se->newData;
+	if (dat == NULL)
+		dat = &modEntry->sampleData[RESERVED_SAMPLE_OFFSET]; // dummy sample
+
+	s.length = length;
+	s.data = dat;
+
+	s.pos = 0;
+	s.posFrac = 0;
+
+	// data/length is already set from replayer thread (important)
+	s.loopFlag = se->newLoopFlag;
+	s.loopStart = se->newLoopStart;
+
+	se->didSwapData = false;
+	se->active = true;
+
+	*sc = s; // update it
+}
+
 void toggleA500Filters(void)
 {
+	lockAudio();
+	clearLossyIntegrator(&filterLo);
+	clearLossyIntegrator(&filterHi);
+	clearLEDFilter(&filterLED);
+	unlockAudio();
+
 	if (filterFlags & FILTER_A500)
 	{
 		filterFlags &= ~FILTER_A500;
-		displayMsg("FILTER MOD: A1200");
+		displayMsg("LP FILTER: A1200");
 	}
 	else
 	{
 		filterFlags |= FILTER_A500;
-		clearLossyIntegrator(&filterLo);
-		displayMsg("FILTER MOD: A500");
+		displayMsg("LP FILTER: A500");
 	}
 }
 
 void mixChannels(int32_t numSamples)
 {
-	const int8_t *dataPtr;
-	double dTempSample, dTempVolume;
+	double dSmp, dVol;
 	blep_t *bSmp, *bVol;
 	paulaVoice_t *v;
 
@@ -542,7 +527,7 @@
 	for (int32_t i = 0; i < AMIGA_VOICES; i++)
 	{
 		v = &paula[i];
-		if (!v->active)
+		if (!v->active || v->data == NULL)
 			continue;
 
 		bSmp = &blep[i];
@@ -550,47 +535,108 @@
 
 		for (int32_t j = 0; j < numSamples; j++)
 		{
-			dataPtr = v->data;
-			if (dataPtr == NULL)
+			assert(v->data != NULL);
+			dSmp = v->data[v->pos] * (1.0 / 128.0);
+			dVol = v->dVolume;
+
+			if (dSmp != bSmp->dLastValue)
 			{
-				dTempSample = 0.0;
-				dTempVolume = 0.0;
+				if (v->dLastDelta > v->dLastPhase)
+				{
+					// div->mul trick: v->dLastDeltaMul is 1.0 / v->dLastDelta
+					blepAdd(bSmp, v->dLastPhase * v->dLastDeltaMul, bSmp->dLastValue - dSmp);
+				}
+
+				bSmp->dLastValue = dSmp;
 			}
-			else
+
+			if (dVol != bVol->dLastValue)
 			{
-				dTempSample = dataPtr[v->pos] * (1.0 / 128.0);
-				dTempVolume = v->dVolume;
+				blepVolAdd(bVol, bVol->dLastValue - dVol);
+				bVol->dLastValue = dVol;
 			}
 
-			if (dTempSample != bSmp->dLastValue)
+			if (bSmp->samplesLeft > 0) dSmp += blepRun(bSmp);
+			if (bVol->samplesLeft > 0) dVol += blepRun(bVol);
+
+			dSmp *= dVol;
+
+			dMixBufferL[j] += dSmp * v->dPanL;
+			dMixBufferR[j] += dSmp * v->dPanR;
+
+			v->dPhase += v->dDelta;
+			if (v->dPhase >= 1.0)
 			{
+				v->dPhase -= 1.0;
+
+				v->dLastPhase = v->dPhase;
+				v->dLastDelta = v->dDelta;
+				v->dLastDeltaMul = v->dDeltaMul;
+
+				if (++v->pos >= v->length)
+				{
+					v->pos = 0;
+
+					// re-fetch new Paula register values now
+					v->length = v->newLength;
+					v->data = v->newData;
+				}
+			}
+		}
+	}
+}
+
+void mixChannelsMultiStep(int32_t numSamples) // for PAT2SMP
+{
+	double dSmp, dVol;
+	blep_t *bSmp, *bVol;
+	paulaVoice_t *v;
+
+	memset(dMixBufferL, 0, numSamples * sizeof (double));
+	memset(dMixBufferR, 0, numSamples * sizeof (double));
+
+	for (int32_t i = 0; i < AMIGA_VOICES; i++)
+	{
+		v = &paula[i];
+		if (!v->active || v->data == NULL)
+			continue;
+
+		bSmp = &blep[i];
+		bVol = &blepVol[i];
+
+		for (int32_t j = 0; j < numSamples; j++)
+		{
+			assert(v->data != NULL);
+			dSmp = v->data[v->pos] * (1.0 / 128.0);
+			dVol = v->dVolume;
+
+			if (dSmp != bSmp->dLastValue)
+			{
 				if (v->dLastDelta > v->dLastPhase)
 				{
 					// div->mul trick: v->dLastDeltaMul is 1.0 / v->dLastDelta
-					blepAdd(bSmp, v->dLastPhase * v->dLastDeltaMul, bSmp->dLastValue - dTempSample);
+					blepAdd(bSmp, v->dLastPhase * v->dLastDeltaMul, bSmp->dLastValue - dSmp);
 				}
 
-				bSmp->dLastValue = dTempSample;
+				bSmp->dLastValue = dSmp;
 			}
 
-			if (dTempVolume != bVol->dLastValue)
+			if (dVol != bVol->dLastValue)
 			{
-				blepVolAdd(bVol, bVol->dLastValue - dTempVolume);
-				bVol->dLastValue = dTempVolume;
+				blepVolAdd(bVol, bVol->dLastValue - dVol);
+				bVol->dLastValue = dVol;
 			}
 
-			if (bSmp->samplesLeft > 0) dTempSample += blepRun(bSmp);
-			if (bVol->samplesLeft > 0) dTempVolume += blepRun(bVol);
+			if (bSmp->samplesLeft > 0) dSmp += blepRun(bSmp);
+			if (bVol->samplesLeft > 0) dVol += blepRun(bVol);
 
-			dTempSample *= dTempVolume;
+			dSmp *= dVol;
 
-			dMixBufferL[j] += dTempSample * v->dPanL;
-			dMixBufferR[j] += dTempSample * v->dPanR;
+			dMixBufferL[j] += dSmp * v->dPanL;
+			dMixBufferR[j] += dSmp * v->dPanR;
 
 			v->dPhase += v->dDelta;
-
-			// PAT2SMP needs multi-step, so use while() here (will be only one iteration in normal mixing mode)
-			while (v->dPhase >= 1.0)
+			while (v->dPhase >= 1.0) // multi-step
 			{
 				v->dPhase -= 1.0;
 
@@ -636,9 +682,42 @@
 
 	// don't process any low-pass filter since the cut-off is around 28-31kHz on A1200
 
+	// process high-pass filter
+	lossyIntegratorHighPass(&filterHi, dOut, dOut);
+
+	// normalize and flip phase (A500/A1200 has an inverted audio signal)
+	dOut[0] *= -(INT16_MAX / AMIGA_VOICES);
+	dOut[1] *= -(INT16_MAX / AMIGA_VOICES);
+
+	// left channel - 1-bit triangular dithering (high-pass filtered)
+	dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+	dOut[0] = (dOut[0] + dPrng) - dPrngStateL;
+	dPrngStateL = dPrng;
+	smp32 = (int32_t)dOut[0];
+	CLAMP16(smp32);
+	out[0] = (int16_t)smp32;
+
+	// right channel - 1-bit triangular dithering (high-pass filtered)
+	dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+	dOut[1] = (dOut[1] + dPrng) - dPrngStateR;
+	dPrngStateR = dPrng;
+	smp32 = (int32_t)dOut[1];
+	CLAMP16(smp32);
+	out[1] = (int16_t)smp32;
+}
+
+static inline void processMixedSamplesA1200LED(int32_t i, int16_t *out)
+{
+	int32_t smp32;
+	double dOut[2], dPrng;
+
+	dOut[0] = dMixBufferL[i];
+	dOut[1] = dMixBufferR[i];
+
+	// don't process any low-pass filter since the cut-off is around 28-31kHz on A1200
+
 	// process "LED" filter
-	if (filterFlags & FILTER_LED_ENABLED)
-		lossyIntegratorLED(filterLEDC, &filterLED, dOut, dOut);
+	lossyIntegratorLED(filterLEDC, &filterLED, dOut, dOut);
 
 	// process high-pass filter
 	lossyIntegratorHighPass(&filterHi, dOut, dOut);
@@ -702,17 +781,54 @@
 	out[1] = (int16_t)smp32;
 }
 
+static inline void processMixedSamplesA500LED(int32_t i, int16_t *out)
+{
+	int32_t smp32;
+	double dOut[2], dPrng;
+
+	dOut[0] = dMixBufferL[i];
+	dOut[1] = dMixBufferR[i];
+
+	// process low-pass filter
+	lossyIntegrator(&filterLo, dOut, dOut);
+
+	// process "LED" filter
+	lossyIntegratorLED(filterLEDC, &filterLED, dOut, dOut);
+
+	// process high-pass filter
+	lossyIntegratorHighPass(&filterHi, dOut, dOut);
+
+	dOut[0] *= -(INT16_MAX / AMIGA_VOICES);
+	dOut[1] *= -(INT16_MAX / AMIGA_VOICES);
+
+	// left channel - 1-bit triangular dithering (high-pass filtered)
+	dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+	dOut[0] = (dOut[0] + dPrng) - dPrngStateL;
+	dPrngStateL = dPrng;
+	smp32 = (int32_t)dOut[0];
+	CLAMP16(smp32);
+	out[0] = (int16_t)smp32;
+
+	// right channel - 1-bit triangular dithering (high-pass filtered)
+	dPrng = random32() * (0.5 / INT32_MAX); // -0.5..0.5
+	dOut[1] = (dOut[1] + dPrng) - dPrngStateR;
+	dPrngStateR = dPrng;
+	smp32 = (int32_t)dOut[1];
+	CLAMP16(smp32);
+	out[1] = (int16_t)smp32;
+}
+
 void outputAudio(int16_t *target, int32_t numSamples)
 {
 	int16_t *outStream, out[2];
 	int32_t j;
 
-	mixChannels(numSamples);
-
 	if (editor.isSMPRendering)
 	{
 		// render to sample (PAT2SMP)
 
+		mixChannelsMultiStep(numSamples);
+
 		for (j = 0; j < numSamples; j++)
 		{
 			processMixedSamplesA1200(j, out);
@@ -730,24 +846,54 @@
 	{
 		// render to stream
 
+		mixChannels(numSamples);
+
 		outStream = target;
 		if (filterFlags & FILTER_A500)
 		{
-			for (j = 0; j < numSamples; j++)
+			// Amiga 500 filter model
+
+			if (filterFlags & FILTER_LED_ENABLED)
 			{
-				processMixedSamplesA500(j, out);
-				*outStream++ = out[0];
-				*outStream++ = out[1];
+				for (j = 0; j < numSamples; j++)
+				{
+					processMixedSamplesA500LED(j, out);
+					*outStream++ = out[0];
+					*outStream++ = out[1];
+				}
 			}
+			else
+			{
+				for (j = 0; j < numSamples; j++)
+				{
+					processMixedSamplesA500(j, out);
+					*outStream++ = out[0];
+					*outStream++ = out[1];
+				}
+			}
 		}
 		else
 		{
-			for (j = 0; j < numSamples; j++)
+			// Amiga 1200 filter model
+
+			if (filterFlags & FILTER_LED_ENABLED)
 			{
-				processMixedSamplesA1200(j, out);
-				*outStream++ = out[0];
-				*outStream++ = out[1];
+				for (j = 0; j < numSamples; j++)
+				{
+					processMixedSamplesA1200LED(j, out);
+					*outStream++ = out[0];
+					*outStream++ = out[1];
+				}
 			}
+			else
+			{
+				for (j = 0; j < numSamples; j++)
+				{
+					processMixedSamplesA1200(j, out);
+					*outStream++ = out[0];
+					*outStream++ = out[1];
+				}
+			}
 		}
 	}
 }
@@ -759,7 +905,7 @@
 
 	(void)userdata;
 
-	if (forceMixerOff) // during MOD2WAV
+	if (audio.forceMixerOff) // during MOD2WAV
 	{
 		memset(stream, 0, len);
 		return;
@@ -878,12 +1024,12 @@
 {
 	SDL_AudioSpec want, have;
 
-	want.freq = ptConfig.soundFrequency;
+	want.freq = config.soundFrequency;
 	want.format = AUDIO_S16;
 	want.channels = 2;
 	want.callback = audioCallback;
 	want.userdata = NULL;
-	want.samples = ptConfig.soundBufferSize;
+	want.samples = config.soundBufferSize;
 
 	dev = SDL_OpenAudioDevice(NULL, 0, &want, &have, 0);
 	if (dev == 0)
@@ -921,15 +1067,15 @@
 	dMixBufferR = (double *)ALIGN_PTR(dMixBufferRUnaligned, 256);
 
 	audio.audioBufferSize = have.samples;
-	ptConfig.soundFrequency = have.freq;
-	audio.audioFreq = ptConfig.soundFrequency;
-	audio.dAudioFreq = (double)ptConfig.soundFrequency;
+	config.soundFrequency = have.freq;
+	audio.audioFreq = config.soundFrequency;
+	audio.dAudioFreq = (double)config.soundFrequency;
 	audio.dPeriodToDeltaDiv = PAULA_PAL_CLK / audio.dAudioFreq;
 
-	mixerCalcVoicePans(ptConfig.stereoSeparation);
-	defStereoSep = ptConfig.stereoSeparation;
+	mixerCalcVoicePans(config.stereoSeparation);
+	defStereoSep = config.stereoSeparation;
 
-	filterFlags = ptConfig.a500LowPassFilter ? FILTER_A500 : 0;
+	filterFlags = config.a500LowPassFilter ? FILTER_A500 : 0;
 
 	calculateFilterCoeffs();
 	generateBpmTables();
--- a/src/pt2_audio.h
+++ b/src/pt2_audio.h
@@ -37,7 +37,6 @@
 void paulaSetData(uint8_t ch, const int8_t *src);
 void lockAudio(void);
 void unlockAudio(void);
-void clearPaulaAndScopes(void);
 void mixerUpdateLoops(void);
 void mixerKillVoice(uint8_t ch);
 void turnOffVoices(void);
--- a/src/pt2_config.c
+++ b/src/pt2_config.c
@@ -41,26 +41,26 @@
 	FILE *f;
 
 	// set default config values first
-	ptConfig.fullScreenStretch = false;
-	ptConfig.pattDots = false;
-	ptConfig.dottedCenterFlag = true;
-	ptConfig.a500LowPassFilter = false;
-	ptConfig.soundFrequency = 48000;
-	ptConfig.rememberPlayMode = false;
-	ptConfig.stereoSeparation = 20;
-	ptConfig.videoScaleFactor = 2;
-	ptConfig.realVuMeters = false;
-	ptConfig.modDot = false;
-	ptConfig.accidental = 0; // sharp
-	ptConfig.quantizeValue = 1;
-	ptConfig.transDel = false;
-	ptConfig.blankZeroFlag = false;
-	ptConfig.compoMode = false;
-	ptConfig.soundBufferSize = 1024;
-	ptConfig.autoCloseDiskOp = true;
-	ptConfig.vsyncOff = false;
-	ptConfig.hwMouse = false;
-	ptConfig.sampleLowpass = true;
+	config.fullScreenStretch = false;
+	config.pattDots = false;
+	config.dottedCenterFlag = true;
+	config.a500LowPassFilter = false;
+	config.soundFrequency = 48000;
+	config.rememberPlayMode = false;
+	config.stereoSeparation = 20;
+	config.videoScaleFactor = 2;
+	config.realVuMeters = false;
+	config.modDot = false;
+	config.accidental = 0; // sharp
+	config.quantizeValue = 1;
+	config.transDel = false;
+	config.blankZeroFlag = false;
+	config.compoMode = false;
+	config.soundBufferSize = 1024;
+	config.autoCloseDiskOp = true;
+	config.vsyncOff = false;
+	config.hwMouse = false;
+	config.sampleLowpass = true;
 
 #ifndef _WIN32
 	getcwd(oldCwd, PATH_MAX);
@@ -191,78 +191,78 @@
 		// HWMOUSE
 		else if (!_strnicmp(configLine, "HWMOUSE=", 8))
 		{
-			     if (!_strnicmp(&configLine[8], "TRUE",  4)) ptConfig.hwMouse = true;
-			else if (!_strnicmp(&configLine[8], "FALSE", 5)) ptConfig.hwMouse = false;
+			     if (!_strnicmp(&configLine[8], "TRUE",  4)) config.hwMouse = true;
+			else if (!_strnicmp(&configLine[8], "FALSE", 5)) config.hwMouse = false;
 		}
 
 		// SAMPLELOWPASS
 		else if (!_strnicmp(configLine, "SAMPLELOWPASS=", 14))
 		{
-			     if (!_strnicmp(&configLine[14], "TRUE",  4)) ptConfig.sampleLowpass = true;
-			else if (!_strnicmp(&configLine[14], "FALSE", 5)) ptConfig.sampleLowpass = false;
+			     if (!_strnicmp(&configLine[14], "TRUE",  4)) config.sampleLowpass = true;
+			else if (!_strnicmp(&configLine[14], "FALSE", 5)) config.sampleLowpass = false;
 		}
 
 		// VSYNCOFF
 		else if (!_strnicmp(configLine, "VSYNCOFF=", 9))
 		{
-			     if (!_strnicmp(&configLine[9], "TRUE",  4)) ptConfig.vsyncOff = true;
-			else if (!_strnicmp(&configLine[9], "FALSE", 5)) ptConfig.vsyncOff = false;
+			     if (!_strnicmp(&configLine[9], "TRUE",  4)) config.vsyncOff = true;
+			else if (!_strnicmp(&configLine[9], "FALSE", 5)) config.vsyncOff = false;
 		}
 
 		// FULLSCREENSTRETCH
 		else if (!_strnicmp(configLine, "FULLSCREENSTRETCH=", 18))
 		{
-			     if (!_strnicmp(&configLine[18], "TRUE",  4)) ptConfig.fullScreenStretch = true;
-			else if (!_strnicmp(&configLine[18], "FALSE", 5)) ptConfig.fullScreenStretch = false;
+			     if (!_strnicmp(&configLine[18], "TRUE",  4)) config.fullScreenStretch = true;
+			else if (!_strnicmp(&configLine[18], "FALSE", 5)) config.fullScreenStretch = false;
 		}
 
 		// HIDEDISKOPDATES
 		else if (!_strnicmp(configLine, "HIDEDISKOPDATES=", 16))
 		{
-			     if (!_strnicmp(&configLine[16], "TRUE",  4)) ptConfig.hideDiskOpDates = true;
-			else if (!_strnicmp(&configLine[16], "FALSE", 5)) ptConfig.hideDiskOpDates = false;
+			     if (!_strnicmp(&configLine[16], "TRUE",  4)) config.hideDiskOpDates = true;
+			else if (!_strnicmp(&configLine[16], "FALSE", 5)) config.hideDiskOpDates = false;
 		}
 
 		// AUTOCLOSEDISKOP
 		else if (!_strnicmp(configLine, "AUTOCLOSEDISKOP=", 16))
 		{
-			     if (!_strnicmp(&configLine[16], "TRUE",  4)) ptConfig.autoCloseDiskOp = true;
-			else if (!_strnicmp(&configLine[16], "FALSE", 5)) ptConfig.autoCloseDiskOp = false;
+			     if (!_strnicmp(&configLine[16], "TRUE",  4)) config.autoCloseDiskOp = true;
+			else if (!_strnicmp(&configLine[16], "FALSE", 5)) config.autoCloseDiskOp = false;
 		}
 
 		// COMPOMODE
 		else if (!_strnicmp(configLine, "COMPOMODE=", 10))
 		{
-			     if (!_strnicmp(&configLine[10], "TRUE",  4)) ptConfig.compoMode = true;
-			else if (!_strnicmp(&configLine[10], "FALSE", 5)) ptConfig.compoMode = false;
+			     if (!_strnicmp(&configLine[10], "TRUE",  4)) config.compoMode = true;
+			else if (!_strnicmp(&configLine[10], "FALSE", 5)) config.compoMode = false;
 		}
 
 		// PATTDOTS
 		else if (!_strnicmp(configLine, "PATTDOTS=", 9))
 		{
-			     if (!_strnicmp(&configLine[9], "TRUE",  4)) ptConfig.pattDots = true;
-			else if (!_strnicmp(&configLine[9], "FALSE", 5)) ptConfig.pattDots = false;
+			     if (!_strnicmp(&configLine[9], "TRUE",  4)) config.pattDots = true;
+			else if (!_strnicmp(&configLine[9], "FALSE", 5)) config.pattDots = false;
 		}
 
 		// BLANKZERO
 		else if (!_strnicmp(configLine, "BLANKZERO=", 10))
 		{
-			     if (!_strnicmp(&configLine[10], "TRUE",  4)) ptConfig.blankZeroFlag = true;
-			else if (!_strnicmp(&configLine[10], "FALSE", 5)) ptConfig.blankZeroFlag = false;
+			     if (!_strnicmp(&configLine[10], "TRUE",  4)) config.blankZeroFlag = true;
+			else if (!_strnicmp(&configLine[10], "FALSE", 5)) config.blankZeroFlag = false;
 		}
 
 		// REALVUMETERS
 		else if (!_strnicmp(configLine, "REALVUMETERS=", 13))
 		{
-			     if (!_strnicmp(&configLine[13], "TRUE",  4)) ptConfig.realVuMeters = true;
-			else if (!_strnicmp(&configLine[13], "FALSE", 5)) ptConfig.realVuMeters = false;
+			     if (!_strnicmp(&configLine[13], "TRUE",  4)) config.realVuMeters = true;
+			else if (!_strnicmp(&configLine[13], "FALSE", 5)) config.realVuMeters = false;
 		}
 
 		// ACCIDENTAL
 		else if (!_strnicmp(configLine, "ACCIDENTAL=", 11))
 		{
-			     if (!_strnicmp(&configLine[11], "SHARP", 4)) ptConfig.accidental = 0;
-			else if (!_strnicmp(&configLine[11], "FLAT",  5)) ptConfig.accidental = 1;
+			     if (!_strnicmp(&configLine[11], "SHARP", 4)) config.accidental = 0;
+			else if (!_strnicmp(&configLine[11], "FLAT",  5)) config.accidental = 1;
 		}
 
 		// QUANTIZE
@@ -269,35 +269,35 @@
 		else if (!_strnicmp(configLine, "QUANTIZE=", 9))
 		{
 			if (configLine[9] != '\0')
-				ptConfig.quantizeValue = (int16_t)(CLAMP(atoi(&configLine[9]), 0, 63));
+				config.quantizeValue = (int16_t)(CLAMP(atoi(&configLine[9]), 0, 63));
 		}
 
 		// TRANSDEL
 		else if (!_strnicmp(configLine, "TRANSDEL=", 9))
 		{
-			     if (!_strnicmp(&configLine[9], "TRUE",  4)) ptConfig.transDel = true;
-			else if (!_strnicmp(&configLine[9], "FALSE", 5)) ptConfig.transDel = false;
+			     if (!_strnicmp(&configLine[9], "TRUE",  4)) config.transDel = true;
+			else if (!_strnicmp(&configLine[9], "FALSE", 5)) config.transDel = false;
 		}
 
 		// DOTTEDCENTER
 		else if (!_strnicmp(configLine, "DOTTEDCENTER=", 13))
 		{
-			     if (!_strnicmp(&configLine[13], "TRUE",  4)) ptConfig.dottedCenterFlag = true;
-			else if (!_strnicmp(&configLine[13], "FALSE", 5)) ptConfig.dottedCenterFlag = false;
+			     if (!_strnicmp(&configLine[13], "TRUE",  4)) config.dottedCenterFlag = true;
+			else if (!_strnicmp(&configLine[13], "FALSE", 5)) config.dottedCenterFlag = false;
 		}
 
 		// MODDOT
 		else if (!_strnicmp(configLine, "MODDOT=", 7))
 		{
-			     if (!_strnicmp(&configLine[7], "TRUE",  4)) ptConfig.modDot = true;
-			else if (!_strnicmp(&configLine[7], "FALSE", 5)) ptConfig.modDot = false;
+			     if (!_strnicmp(&configLine[7], "TRUE",  4)) config.modDot = true;
+			else if (!_strnicmp(&configLine[7], "FALSE", 5)) config.modDot = false;
 		}
 
 		// SCALE3X (deprecated)
 		else if (!_strnicmp(configLine, "SCALE3X=", 8))
 		{
-			     if (!_strnicmp(&configLine[8], "TRUE",  4)) ptConfig.videoScaleFactor = 3;
-			else if (!_strnicmp(&configLine[8], "FALSE", 5)) ptConfig.videoScaleFactor = 2;
+			     if (!_strnicmp(&configLine[8], "TRUE",  4)) config.videoScaleFactor = 3;
+			else if (!_strnicmp(&configLine[8], "FALSE", 5)) config.videoScaleFactor = 2;
 		}
 
 		// VIDEOSCALE
@@ -304,14 +304,14 @@
 		else if (!_strnicmp(configLine, "VIDEOSCALE=", 11))
 		{
 			if (lineLen >= 13 && configLine[12] == 'X' && isdigit(configLine[11]))
-				ptConfig.videoScaleFactor = configLine[11] - '0';
+				config.videoScaleFactor = configLine[11] - '0';
 		}
 
 		// REMEMBERPLAYMODE
 		else if (!_strnicmp(configLine, "REMEMBERPLAYMODE=", 17))
 		{
-			     if (!_strnicmp(&configLine[17], "TRUE",  4)) ptConfig.rememberPlayMode = true;
-			else if (!_strnicmp(&configLine[17], "FALSE", 5)) ptConfig.rememberPlayMode = false;
+			     if (!_strnicmp(&configLine[17], "TRUE",  4)) config.rememberPlayMode = true;
+			else if (!_strnicmp(&configLine[17], "FALSE", 5)) config.rememberPlayMode = false;
 		}
 
 		// DEFAULTDIR
@@ -325,7 +325,7 @@
 
 				lineLen -= i;
 				if (lineLen > 0)
-					strncpy(ptConfig.defModulesDir, &configLine[i], (lineLen > PATH_MAX) ? PATH_MAX : lineLen);
+					strncpy(config.defModulesDir, &configLine[i], (lineLen > PATH_MAX) ? PATH_MAX : lineLen);
 			}
 		}
 
@@ -340,7 +340,7 @@
 
 				lineLen -= i;
 				if (lineLen > 0)
-					strncpy(ptConfig.defSamplesDir, &configLine[i], (lineLen > PATH_MAX) ? PATH_MAX : lineLen);
+					strncpy(config.defSamplesDir, &configLine[i], (lineLen > PATH_MAX) ? PATH_MAX : lineLen);
 			}
 		}
 
@@ -347,15 +347,15 @@
 		// A500LOWPASSFILTER
 		else if (!_strnicmp(configLine, "A500LOWPASSFILTER=", 18))
 		{
-			     if (!_strnicmp(&configLine[18], "TRUE",  4)) ptConfig.a500LowPassFilter = true;
-			else if (!_strnicmp(&configLine[18], "FALSE", 5)) ptConfig.a500LowPassFilter = false;
+			     if (!_strnicmp(&configLine[18], "TRUE",  4)) config.a500LowPassFilter = true;
+			else if (!_strnicmp(&configLine[18], "FALSE", 5)) config.a500LowPassFilter = false;
 		}
 
 		// A4000LOWPASSFILTER (deprecated, same as A500LOWPASSFILTER)
 		else if (!_strnicmp(configLine, "A4000LOWPASSFILTER=", 19))
 		{
-			     if (!_strnicmp(&configLine[19], "TRUE",  4)) ptConfig.a500LowPassFilter = true;
-			else if (!_strnicmp(&configLine[19], "FALSE", 5)) ptConfig.a500LowPassFilter = false;
+			     if (!_strnicmp(&configLine[19], "TRUE",  4)) config.a500LowPassFilter = true;
+			else if (!_strnicmp(&configLine[19], "FALSE", 5)) config.a500LowPassFilter = false;
 		}
 
 		// FREQUENCY
@@ -362,7 +362,7 @@
 		else if (!_strnicmp(configLine, "FREQUENCY=", 10))
 		{
 			if (configLine[10] != '\0')
-				ptConfig.soundFrequency = (uint32_t)(CLAMP(atoi(&configLine[10]), 32000, 96000));
+				config.soundFrequency = (uint32_t)(CLAMP(atoi(&configLine[10]), 32000, 96000));
 		}
 
 		// BUFFERSIZE
@@ -369,7 +369,7 @@
 		else if (!_strnicmp(configLine, "BUFFERSIZE=", 11))
 		{
 			if (configLine[11] != '\0')
-				ptConfig.soundBufferSize = (uint32_t)(CLAMP(atoi(&configLine[11]), 128, 8192));
+				config.soundBufferSize = (uint32_t)(CLAMP(atoi(&configLine[11]), 128, 8192));
 		}
 
 		// STEREOSEPARATION
@@ -376,7 +376,7 @@
 		else if (!_strnicmp(configLine, "STEREOSEPARATION=", 17))
 		{
 			if (configLine[17] != '\0')
-				ptConfig.stereoSeparation = (int8_t)(CLAMP(atoi(&configLine[17]), 0, 100));
+				config.stereoSeparation = (int8_t)(CLAMP(atoi(&configLine[17]), 0, 100));
 		}
 
 		configLine = strtok(NULL, "\n");
@@ -450,20 +450,20 @@
 	{
 		fread(&tmp16, 2, 1, f); // stored as Big-Endian
 		tmp16 = SWAP16(tmp16);
-		palette[i] = RGB12_to_RGB24(tmp16);
+		video.palette[i] = RGB12_to_RGB24(tmp16);
 	}
 
 	// Transpose Delete (delete out of range notes on transposing)
 	fseek(f, 174, SEEK_SET);
 	fread(&tmp8, 1, 1, f);
-	ptConfig.transDel = tmp8 ? true : false;
-	ptConfig.transDel = ptConfig.transDel;
+	config.transDel = tmp8 ? true : false;
+	config.transDel = config.transDel;
 
 	// Note style (sharps/flats)
 	fseek(f, 200, SEEK_SET);
 	fread(&tmp8, 1, 1, f);
-	ptConfig.accidental = tmp8 ? 1 : 0;
-	ptConfig.accidental = ptConfig.accidental;
+	config.accidental = tmp8 ? 1 : 0;
+	config.accidental = config.accidental;
 
 	// Multi Mode Next
 	fseek(f, 462, SEEK_SET);
@@ -489,8 +489,8 @@
 	// Blank Zeroes
 	fseek(f, 490, SEEK_SET);
 	fread(&tmp8, 1, 1, f);
-	ptConfig.blankZeroFlag = tmp8 ? true : false;
-	ptConfig.blankZeroFlag = ptConfig.blankZeroFlag;
+	config.blankZeroFlag = tmp8 ? true : false;
+	config.blankZeroFlag = config.blankZeroFlag;
 
 	// Initial Tempo (don't load if timing is set to VBLANK)
 	if (editor.timingMode == TEMPO_MODE_CIA)
@@ -603,7 +603,7 @@
 				{
 					color = (hex2int(configLine[0]) << 8) | (hex2int(configLine[1]) << 4) | hex2int(configLine[2]);
 					color &= 0xFFF;
-					palette[line] = RGB12_to_RGB24(color);
+					video.palette[line] = RGB12_to_RGB24(color);
 
 					configLine = strtok(NULL, "\n");
 					line++;
--- a/src/pt2_config.h
+++ b/src/pt2_config.h
@@ -3,7 +3,7 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-struct ptConfig_t
+struct config_t
 {
 	char *defModulesDir, *defSamplesDir;
 	bool dottedCenterFlag, pattDots, a500LowPassFilter, compoMode, autoCloseDiskOp, hideDiskOpDates, hwMouse;
@@ -12,6 +12,6 @@
 	int8_t stereoSeparation, videoScaleFactor, accidental;
 	uint16_t quantizeValue;
 	uint32_t soundFrequency, soundBufferSize;
-} ptConfig;
+} config;
 
 void loadConfig(void);
--- a/src/pt2_diskop.c
+++ b/src/pt2_diskop.c
@@ -450,12 +450,12 @@
 void diskOpSetInitPath(void)
 {
 	// default module path
-	if (ptConfig.defModulesDir[0] != '\0')
+	if (config.defModulesDir[0] != '\0')
 	{
 #ifdef _WIN32
-		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ptConfig.defModulesDir, -1, pathTmp, PATH_MAX);
+		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.defModulesDir, -1, pathTmp, PATH_MAX);
 #else
-		strcpy(pathTmp, ptConfig.defModulesDir);
+		strcpy(pathTmp, config.defModulesDir);
 #endif
 		UNICHAR_STRCPY(editor.modulesPathU, pathTmp);
 	}
@@ -466,12 +466,12 @@
 	}
 
 	// default sample path
-	if (ptConfig.defSamplesDir[0] != '\0')
+	if (config.defSamplesDir[0] != '\0')
 	{
 #ifdef _WIN32
-		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, ptConfig.defSamplesDir, -1, pathTmp, PATH_MAX);
+		MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, config.defSamplesDir, -1, pathTmp, PATH_MAX);
 #else
-		strcpy(pathTmp, ptConfig.defSamplesDir);
+		strcpy(pathTmp, config.defSamplesDir);
 #endif
 		UNICHAR_STRCPY(editor.samplesPathU, pathTmp);
 	}
@@ -715,7 +715,7 @@
 	return true;
 }
 
-static void printFileSize(uint32_t *frameBuffer, fileEntry_t *entry, uint16_t x, uint16_t y)
+static void printFileSize(fileEntry_t *entry, uint16_t x, uint16_t y)
 {
 	char tmpStr[7];
 	uint32_t fileSize, j;
@@ -722,7 +722,7 @@
 
 	if (entry->filesize == -1) // -1 means that the original filesize is above 2GB in our directory reader
 	{
-		textOut(frameBuffer, x, y, "  >2GB", palette[PAL_QADSCP]);
+		textOut(x, y, "  >2GB", video.palette[PAL_QADSCP]);
 		return;
 	}
 
@@ -754,27 +754,27 @@
 		tmpStr[j] = ' ';
 	}
 
-	textOut(frameBuffer, x, y, tmpStr, palette[PAL_QADSCP]);
+	textOut(x, y, tmpStr, video.palette[PAL_QADSCP]);
 }
 
-static void printEntryName(uint32_t *frameBuffer, char *entryName, int32_t entryLength, int32_t maxLength, uint16_t x, uint16_t y)
+static void printEntryName(char *entryName, int32_t entryLength, int32_t maxLength, uint16_t x, uint16_t y)
 {
 	if (entryLength > maxLength)
 	{
 		// shorten name and add ".." to end
 		for (int32_t j = 0; j < maxLength-2; j++)
-			charOut(frameBuffer, x + (j * FONT_CHAR_W), y, entryName[j], palette[PAL_QADSCP]);
+			charOut(x + (j * FONT_CHAR_W), y, entryName[j], video.palette[PAL_QADSCP]);
 
-		textOut(frameBuffer, x + ((maxLength - 2) * FONT_CHAR_W), y, "..", palette[PAL_QADSCP]);
+		textOut(x + ((maxLength - 2) * FONT_CHAR_W), y, "..", video.palette[PAL_QADSCP]);
 	}
 	else
 	{
 		// print whole name
-		textOut(frameBuffer, x, y, entryName, palette[PAL_QADSCP]);
+		textOut(x, y, entryName, video.palette[PAL_QADSCP]);
 	}
 }
 
-void diskOpRenderFileList(uint32_t *frameBuffer)
+void diskOpRenderFileList(void)
 {
 	char *entryName;
 	uint8_t maxFilenameChars, maxDirNameChars;
@@ -783,7 +783,7 @@
 	uint32_t *dstPtr;
 	fileEntry_t *entry;
 
-	if (ptConfig.hideDiskOpDates)
+	if (config.hideDiskOpDates)
 	{
 		textXStart = 8;
 		maxFilenameChars = 30;
@@ -813,11 +813,11 @@
 	}
 
 	// clear list
-	dstPtr = &frameBuffer[(35 * SCREEN_W) + 8];
+	dstPtr = &video.frameBuffer[(35 * SCREEN_W) + 8];
 	for (y = 0; y < 59; y++)
 	{
 		for (x = 0; x < 295; x++)
-			dstPtr[x] = palette[PAL_BACKGRD];
+			dstPtr[x] = video.palette[PAL_BACKGRD];
 
 		dstPtr += SCREEN_W;
 	}
@@ -840,19 +840,19 @@
 
 		if (!entry->isDir)
 		{
-			printEntryName(frameBuffer, entryName, entryLength, maxFilenameChars, x, y);
+			printEntryName(entryName, entryLength, maxFilenameChars, x, y);
 
 			// print modification date
-			if (!ptConfig.hideDiskOpDates)
-				textOut(frameBuffer, 8, y, entry->dateChanged, palette[PAL_QADSCP]);
+			if (!config.hideDiskOpDates)
+				textOut(8, y, entry->dateChanged, video.palette[PAL_QADSCP]);
 
 			// print file size
-			printFileSize(frameBuffer, entry, 256, y);
+			printFileSize(entry, 256, y);
 		}
 		else
 		{
-			printEntryName(frameBuffer, entryName, entryLength, maxDirNameChars, x, y);
-			textOut(frameBuffer, 264, y, "(DIR)", palette[PAL_QADSCP]);
+			printEntryName(entryName, entryLength, maxDirNameChars, x, y);
+			textOut(264, y, "(DIR)", video.palette[PAL_QADSCP]);
 		}
 	}
 }
@@ -900,10 +900,10 @@
 
 					statusAllRight();
 
-					if (ptConfig.autoCloseDiskOp)
+					if (config.autoCloseDiskOp)
 						editor.ui.diskOpScreenShown = false;
 
-					if (ptConfig.rememberPlayMode)
+					if (config.rememberPlayMode)
 					{
 						if (oldMode == MODE_PLAY || oldMode == MODE_RECORD)
 						{
--- a/src/pt2_diskop.h
+++ b/src/pt2_diskop.h
@@ -22,7 +22,7 @@
 UNICHAR *diskOpGetUnicodeEntry(int32_t fileIndex);
 bool diskOpSetPath(UNICHAR *path, bool cache);
 void diskOpSetInitPath(void);
-void diskOpRenderFileList(uint32_t *frameBuffer);
+void diskOpRenderFileList(void);
 bool allocDiskOpVars(void);
 void freeDiskOpMem(void);
 void freeDiskOpEntryMem(void);
--- a/src/pt2_edit.c
+++ b/src/pt2_edit.c
@@ -256,7 +256,7 @@
 
 			case PTB_EO_QUANTIZE:
 			{
-				editor.quantizeValueDisp = &ptConfig.quantizeValue;
+				editor.quantizeValueDisp = &config.quantizeValue;
 
 				if (updateValue)
 				{
@@ -263,7 +263,7 @@
 					if (editor.ui.tmpDisp16 > 63)
 						editor.ui.tmpDisp16 = 63;
 
-					ptConfig.quantizeValue = editor.ui.tmpDisp16;
+					config.quantizeValue = editor.ui.tmpDisp16;
 					editor.ui.updateQuantizeText = true;
 				}
 			}
@@ -679,7 +679,7 @@
 	if (editor.ui.samplerScreenShown || (editor.currMode == MODE_IDLE || editor.currMode == MODE_PLAY))
 	{
 		// at this point it will only jam, not place it
-		if (!input.keyb.leftAltPressed && !input.keyb.leftAmigaPressed && !input.keyb.leftCtrlPressed && !input.keyb.shiftPressed)
+		if (!keyb.leftAltPressed && !keyb.leftAmigaPressed && !keyb.leftCtrlPressed && !keyb.shiftPressed)
 			jamAndPlaceSample(scancode, normalMode);
 
 		return;
@@ -701,7 +701,7 @@
 	if (editor.cursor.mode != CURSOR_NOTE)
 	{
 		// if we held down any key modifier at this point, then do nothing
-		if (input.keyb.leftAltPressed || input.keyb.leftAmigaPressed || input.keyb.leftCtrlPressed || input.keyb.shiftPressed)
+		if (keyb.leftAltPressed || keyb.leftAmigaPressed || keyb.leftCtrlPressed || keyb.shiftPressed)
 			return;
 
 		if (editor.currMode == MODE_EDIT || editor.currMode == MODE_RECORD)
@@ -821,13 +821,13 @@
 			{
 				note = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 
-				if (!input.keyb.leftAltPressed)
+				if (!keyb.leftAltPressed)
 				{
 					note->sample = 0;
 					note->period = 0;
 				}
 
-				if (input.keyb.shiftPressed || input.keyb.leftAltPressed)
+				if (keyb.shiftPressed || keyb.leftAltPressed)
 				{
 					note->command = 0;
 					note->param = 0;
@@ -842,7 +842,7 @@
 		else
 		{
 			// if we held down any key modifier at this point, then do nothing
-			if (input.keyb.leftAltPressed || input.keyb.leftAmigaPressed || input.keyb.leftCtrlPressed || input.keyb.shiftPressed)
+			if (keyb.leftAltPressed || keyb.leftAmigaPressed || keyb.leftCtrlPressed || keyb.shiftPressed)
 				return;
 
 			jamAndPlaceSample(scancode, normalMode);
@@ -854,7 +854,7 @@
 {
 	note_t *patt, *note, *prevNote;
 
-	if (!input.keyb.leftAltPressed)
+	if (!keyb.leftAltPressed)
 		return false;
 
 	patt = modEntry->patterns[modEntry->currPattern];
@@ -1015,7 +1015,7 @@
 {
 	uint8_t tempRow, quantize;
 
-	quantize = (uint8_t)ptConfig.quantizeValue;
+	quantize = (uint8_t)config.quantizeValue;
 
 	editor.didQuantize = false;
 	if (editor.currMode == MODE_RECORD)
@@ -1307,7 +1307,7 @@
 			{
 				j = 35;
 
-				if (ptConfig.transDel)
+				if (config.transDel)
 				{
 					noteSrc->period = 0;
 					noteSrc->sample = 0;
@@ -1360,7 +1360,7 @@
 			{
 				j = 0;
 
-				if (ptConfig.transDel)
+				if (config.transDel)
 				{
 					noteSrc->period = 0;
 					noteSrc->sample = 0;
@@ -1409,7 +1409,7 @@
 			}
 
 			noteDeleted = false;
-			if (j+12 > 35 && ptConfig.transDel)
+			if (j+12 > 35 && config.transDel)
 			{
 				noteSrc->period = 0;
 				noteSrc->sample = 0;
@@ -1460,7 +1460,7 @@
 			}
 
 			noteDeleted = false;
-			if (j-12 < 0 && ptConfig.transDel)
+			if (j-12 < 0 && config.transDel)
 			{
 				noteSrc->period = 0;
 				noteSrc->sample = 0;
@@ -1510,7 +1510,7 @@
 				{
 					k = 35;
 
-					if (ptConfig.transDel)
+					if (config.transDel)
 					{
 						noteSrc->period = 0;
 						noteSrc->sample = 0;
@@ -1559,7 +1559,7 @@
 				{
 					k = 0;
 
-					if (ptConfig.transDel)
+					if (config.transDel)
 					{
 						noteSrc->period = 0;
 						noteSrc->sample = 0;
@@ -1604,7 +1604,7 @@
 				}
 
 				noteDeleted = false;
-				if (k+12 > 35 && ptConfig.transDel)
+				if (k+12 > 35 && config.transDel)
 				{
 					noteSrc->period = 0;
 					noteSrc->sample = 0;
@@ -1651,7 +1651,7 @@
 				}
 
 				noteDeleted = false;
-				if (k-12 < 0 && ptConfig.transDel)
+				if (k-12 < 0 && config.transDel)
 				{
 					noteSrc->period = 0;
 					noteSrc->sample = 0;
--- a/src/pt2_header.h
+++ b/src/pt2_header.h
@@ -12,8 +12,9 @@
 #endif
 #include <stdint.h>
 #include "pt2_unicode.h"
+#include "pt2_palette.h"
 
-#define PROG_VER_STR "1.07"
+#define PROG_VER_STR "1.08"
 
 #ifdef _WIN32
 #define DIR_DELIMITER '\\'
@@ -285,40 +286,54 @@
 	note_t *patterns[MAX_PATTERNS];
 } module_t;
 
-struct cpu_t
-{
-	bool hasSSE, hasSSE2;
-} cpu;
-
 struct audio_t
 {
+	volatile bool locked;
+	bool forceMixerOff;
 	uint16_t bpmTab[256-32], bpmTab28kHz[256-32], bpmTab22kHz[256-32];
 	uint32_t audioFreq, audioBufferSize;
 	double dAudioFreq, dPeriodToDeltaDiv;
 } audio;
 
-struct input_t
+struct keyb_t
 {
-	struct keyb_t
-	{
-		bool repeatKey, delayKey;
-		bool shiftPressed, leftCtrlPressed, leftAltPressed;
-		bool leftCommandPressed, leftAmigaPressed, keypadEnterPressed;
-		uint8_t repeatCounter, delayCounter;
-		uint64_t repeatFrac;
-		SDL_Scancode lastRepKey, lastKey;
-	} keyb;
+	bool repeatKey, delayKey;
+	bool shiftPressed, leftCtrlPressed, leftAltPressed;
+	bool leftCommandPressed, leftAmigaPressed, keypadEnterPressed;
+	uint8_t repeatCounter, delayCounter;
+	uint64_t repeatFrac;
+	SDL_Scancode lastRepKey, lastKey;
+} keyb;
 
-	struct mouse_t
-	{
-		volatile bool setPosFlag;
-		bool buttonWaiting, leftButtonPressed, rightButtonPressed;
-		uint8_t repeatCounter, buttonWaitCounter;
-		int32_t setPosX, setPosY, lastGUIButton, lastSmpFilterButton, prevX, prevY;
-		int16_t x, y, lastMouseX;
-	} mouse;
-} input;
+struct mouse_t
+{
+	volatile bool setPosFlag;
+	bool buttonWaiting, leftButtonPressed, rightButtonPressed;
+	uint8_t repeatCounter, buttonWaitCounter;
+	int32_t x, y, lastMouseX, setPosX, setPosY, lastGUIButton, lastSmpFilterButton, prevX, prevY;
+	uint32_t buttonState;
+} mouse;
 
+struct video_t
+{
+	bool fullscreen, vsync60HzPresent, windowHidden;
+	int32_t renderX, renderY, renderW, renderH, displayW, displayH;
+	int32_t xScale, yScale;
+	double dMouseXMul, dMouseYMul;
+	SDL_PixelFormat *pixelFormat;
+	uint32_t *frameBuffer, *frameBufferUnaligned;
+
+	SDL_Window *window;
+	SDL_Renderer *renderer;
+	SDL_Texture  *texture;
+
+	uint32_t palette[PALETTE_NUM];
+
+#ifdef _WIN32
+	HWND hWnd;
+#endif
+} video;
+
 // this is massive...
 struct editor_t
 {
@@ -337,7 +352,7 @@
 
 	bool errorMsgActive, errorMsgBlock, multiFlag, metroFlag, keypadToggle8CFlag, normalizeFiltersFlag;
 	bool sampleAllFlag, halfClipFlag, newOldFlag, pat2SmpHQ, mixFlag, useLEDFilter;
-	bool modLoaded, fullscreen, autoInsFlag, repeatKeyFlag, sampleZero, tuningFlag;
+	bool modLoaded, autoInsFlag, repeatKeyFlag, sampleZero, tuningFlag;
 	bool stepPlayEnabled, stepPlayBackwards, blockBufferFlag, blockMarkFlag, didQuantize;
 	bool swapChannelFlag, configFound, abortMod2Wav, chordLengthMin, rowVisitTable[MOD_ORDERS * MOD_ROWS];
 	bool muted[AMIGA_VOICES];
@@ -430,17 +445,10 @@
 		// these are used when things are drawn on top, for example clear/ask dialogs
 		bool disablePosEd, disableVisualizer;
 
-		bool vsync60HzPresent;
 		int16_t lineCurX, lineCurY, editObject, sampleMarkingPos;
 		uint16_t *numPtr16, tmpDisp16, *dstOffset, dstPos, textLength, editTextPos;
 		uint16_t dstOffsetEnd, lastSampleOffset;
-		int32_t askTempData, renderX, renderY, renderW, renderH, displayW, displayH;
-		int32_t xScale, yScale;
-		double dMouseXMul, dMouseYMul;
-		SDL_PixelFormat *pixelFormat;
-#ifdef _WIN32
-		HWND hWnd;
-#endif
+		int32_t askTempData;
 	} ui;
 
 	struct sampler_t
@@ -448,8 +456,8 @@
 		const int8_t *samStart;
 		int8_t *blankSample, *copyBuf;
 		int16_t loopStartPos, loopEndPos;
-		uint16_t dragStart, dragEnd, saveMouseX, lastSamPos;
-		int32_t samPointWidth, samOffset, samDisplay, samLength;
+		uint16_t dragStart, dragEnd;
+		int32_t samPointWidth, samOffset, samDisplay, samLength, saveMouseX, lastSamPos;
 		int32_t lastMouseX, lastMouseY, tmpLoopStart, tmpLoopLength;
 		uint32_t copyBufSize, samDrawStart, samDrawEnd;
 	} sampler;
--- a/src/pt2_helpers.c
+++ b/src/pt2_helpers.c
@@ -20,8 +20,6 @@
 #include "pt2_tables.h"
 #include "pt2_palette.h"
 
-extern SDL_Window *window; // pt_main.c
-
 // used for Windows usleep() implementation
 #ifdef _WIN32
 static NTSTATUS (__stdcall *NtDelayExecution)(BOOL Alertable, PLARGE_INTEGER DelayInterval);
@@ -71,7 +69,7 @@
 	va_end(args);
 
 	// window can be NULL here, no problem...
-	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Critical Error", strBuf, window);
+	SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Critical Error", strBuf, video.window);
 }
 
 void sanitizeFilenameChar(char *chr)
@@ -129,7 +127,7 @@
 	{
 		if (modified)
 		{
-			if (ptConfig.modDot)
+			if (config.modDot)
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"mod.%s\" (unsaved)", PROG_VER_STR, modEntry->head.moduleTitle);
 			else
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"%s.mod\" (unsaved)", PROG_VER_STR, modEntry->head.moduleTitle);
@@ -136,7 +134,7 @@
 		}
 		else
 		{
-			if (ptConfig.modDot)
+			if (config.modDot)
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"mod.%s\"", PROG_VER_STR, modEntry->head.moduleTitle);
 			else
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"%s.mod\"", PROG_VER_STR, modEntry->head.moduleTitle);
@@ -146,7 +144,7 @@
 	{
 		if (modified)
 		{
-			if (ptConfig.modDot)
+			if (config.modDot)
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"mod.untitled\" (unsaved)", PROG_VER_STR);
 			else
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"untitled.mod\" (unsaved)", PROG_VER_STR);
@@ -153,7 +151,7 @@
 		}
 		else
 		{
-			if (ptConfig.modDot)
+			if (config.modDot)
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"mod.untitled\"", PROG_VER_STR);
 			else
 				sprintf(titleTemp, "ProTracker 2 clone v%s - \"untitled.mod\"", PROG_VER_STR);
@@ -160,7 +158,7 @@
 		}
 	}
 
-	 SDL_SetWindowTitle(window, titleTemp);
+	 SDL_SetWindowTitle(video.window, titleTemp);
 }
 
 void recalcChordLength(void)
--- a/src/pt2_keyboard.c
+++ b/src/pt2_keyboard.c
@@ -32,8 +32,6 @@
 extern HHOOK g_hKeyboardHook;
 #endif
 
-extern SDL_Window *window;
-
 void movePatCurPrevCh(void);
 void movePatCurNextCh(void);
 void movePatCurRight(void);
@@ -58,14 +56,14 @@
 
 	modState = SDL_GetModState();
 
-	input.keyb.leftCtrlPressed = (modState & KMOD_LCTRL)  ? true : false;
-	input.keyb.leftAltPressed = (modState & KMOD_LALT) ? true : false;
-	input.keyb.shiftPressed = (modState & (KMOD_LSHIFT + KMOD_RSHIFT)) ? true : false;
+	keyb.leftCtrlPressed = (modState & KMOD_LCTRL)  ? true : false;
+	keyb.leftAltPressed = (modState & KMOD_LALT) ? true : false;
+	keyb.shiftPressed = (modState & (KMOD_LSHIFT + KMOD_RSHIFT)) ? true : false;
 #ifdef __APPLE__
-	input.keyb.leftCommandPressed = (modState & KMOD_LGUI) ? true : false;
+	keyb.leftCommandPressed = (modState & KMOD_LGUI) ? true : false;
 #endif
 #ifndef _WIN32 // MS Windows: handled in lowLevelKeyboardProc
-	input.keyb.leftAmigaPressed = (modState & KMOD_LGUI) ? true : false;
+	keyb.leftAmigaPressed = (modState & KMOD_LGUI) ? true : false;
 #endif
 }
 
@@ -88,7 +86,7 @@
 		case WM_KEYUP:
 		case WM_KEYDOWN:
 		{
-			bEatKeystroke = (SDL_GetWindowFlags(window) & SDL_WINDOW_INPUT_FOCUS) && (p->vkCode == VK_LWIN || p->vkCode == VK_NUMLOCK);
+			bEatKeystroke = (SDL_GetWindowFlags(video.window) & SDL_WINDOW_INPUT_FOCUS) && (p->vkCode == VK_LWIN || p->vkCode == VK_NUMLOCK);
 
 			if (bEatKeystroke)
 			{
@@ -109,7 +107,7 @@
 					else if (!windowsKeyIsDown)
 					{
 						windowsKeyIsDown = true;
-						input.keyb.leftAmigaPressed = true;
+						keyb.leftAmigaPressed = true;
 
 						memset(&inputEvent, 0, sizeof (SDL_Event));
 						inputEvent.type = SDL_KEYDOWN;
@@ -136,7 +134,7 @@
 					else
 					{
 						windowsKeyIsDown = false;
-						input.keyb.leftAmigaPressed = false;
+						keyb.leftAmigaPressed = false;
 
 						memset(&inputEvent, 0, sizeof (SDL_Event));
 						inputEvent.type = SDL_KEYUP;
@@ -329,11 +327,11 @@
 
 	if (scancode == SDL_SCANCODE_KP_PLUS)
 	{
-		input.keyb.keypadEnterPressed = false;
+		keyb.keypadEnterPressed = false;
 	}
 
-	if (scancode == input.keyb.lastRepKey)
-		input.keyb.lastRepKey = SDL_SCANCODE_UNKNOWN;
+	if (scancode == keyb.lastRepKey)
+		keyb.lastRepKey = SDL_SCANCODE_UNKNOWN;
 
 	switch (scancode)
 	{
@@ -353,10 +351,10 @@
 
 		default:
 		{
-			input.keyb.repeatKey = false;
-			input.keyb.delayKey = false;
-			input.keyb.repeatFrac = 0;
-			input.keyb.delayCounter = 0;
+			keyb.repeatKey = false;
+			keyb.delayKey = false;
+			keyb.repeatFrac = 0;
+			keyb.delayCounter = 0;
 		}
 		break;
 	}
@@ -392,17 +390,17 @@
 	}
 
 	// kludge to allow certain repeat-keys to use custom repeat/delay values
-	if (editor.repeatKeyFlag && input.keyb.repeatKey && scancode == input.keyb.lastRepKey &&
-	    (input.keyb.leftAltPressed || input.keyb.leftAmigaPressed || input.keyb.leftCtrlPressed))
+	if (editor.repeatKeyFlag && keyb.repeatKey && scancode == keyb.lastRepKey &&
+	    (keyb.leftAltPressed || keyb.leftAmigaPressed || keyb.leftCtrlPressed))
 	{
 		return;
 	}
 
 	if (scancode == SDL_SCANCODE_KP_PLUS)
-		input.keyb.keypadEnterPressed = true;
+		keyb.keypadEnterPressed = true;
 
 	// TOGGLE FULLSCREEN (should always react)
-	if (scancode == SDL_SCANCODE_F11 && !input.keyb.leftAltPressed)
+	if (scancode == SDL_SCANCODE_F11 && !keyb.leftAltPressed)
 	{
 		toggleFullScreen();
 
@@ -428,23 +426,23 @@
 		if (editor.repeatKeyFlag)
 		{
 			// if Repeat Flag, repeat all keys
-			if (!input.keyb.repeatKey)
+			if (!keyb.repeatKey)
 			{
-				input.keyb.repeatCounter = 0;
-				input.keyb.repeatFrac = 0;
+				keyb.repeatCounter = 0;
+				keyb.repeatFrac = 0;
 			}
 
-			input.keyb.repeatKey = true;
-			input.keyb.delayKey = true;
+			keyb.repeatKey = true;
+			keyb.delayKey = true;
 		}
 
-		input.keyb.repeatCounter = 0;
-		input.keyb.repeatFrac = 0;
-		input.keyb.lastRepKey = scancode;
+		keyb.repeatCounter = 0;
+		keyb.repeatFrac = 0;
+		keyb.lastRepKey = scancode;
 	}
 
 	// ENTRY JUMPING IN DISK OP. FILELIST
-	if (editor.ui.diskOpScreenShown && input.keyb.shiftPressed && !editor.ui.editTextFlag)
+	if (editor.ui.diskOpScreenShown && keyb.shiftPressed && !editor.ui.editTextFlag)
 	{
 		if (keycode >= 32 && keycode <= 126)
 		{
@@ -472,7 +470,7 @@
 		{
 			if (editor.autoInsFlag)
 			{
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 					editor.autoInsSlot -= 4;
 				else
 					editor.autoInsSlot--;
@@ -487,7 +485,7 @@
 
 		case SDL_SCANCODE_BACKSLASH:
 		{
-			if (input.keyb.leftAltPressed)
+			if (keyb.leftAltPressed)
 			{
 				if (handleSpecialKeys(scancode) && editor.currMode != MODE_RECORD)
 					modSetPos(DONT_SET_ORDER, (modEntry->currRow + editor.editMoveAdd) & 0x3F);
@@ -496,7 +494,7 @@
 			{
 				if (editor.autoInsFlag)
 				{
-					if (input.keyb.shiftPressed)
+					if (keyb.shiftPressed)
 						editor.autoInsSlot += 4;
 					else
 						editor.autoInsSlot++;
@@ -644,11 +642,11 @@
 				}
 			}
 
-			if (!input.keyb.repeatKey)
-				input.keyb.delayCounter = 0;
+			if (!keyb.repeatKey)
+				keyb.delayCounter = 0;
 
-			input.keyb.repeatKey = true;
-			input.keyb.delayKey = true;
+			keyb.repeatKey = true;
+			keyb.delayKey = true;
 		}
 		break;
 
@@ -681,11 +679,11 @@
 					modSetPos(DONT_SET_ORDER, modEntry->currRow + 16);
 			}
 
-			if (!input.keyb.repeatKey)
-				input.keyb.delayCounter = 0;
+			if (!keyb.repeatKey)
+				keyb.delayCounter = 0;
 
-			input.keyb.repeatKey = true;
-			input.keyb.delayKey = true;
+			keyb.repeatKey = true;
+			keyb.delayKey = true;
 		}
 		break;
 
@@ -745,7 +743,7 @@
 
 		case SDL_SCANCODE_F12:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.timingMode ^= 1;
 				if (editor.timingMode == TEMPO_MODE_VBLANK)
@@ -760,7 +758,7 @@
 
 				editor.ui.updateSongTiming = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				toggleAmigaPanMode();
 			}
@@ -783,10 +781,10 @@
 			}
 			else
 			{
-				if (input.keyb.shiftPressed || input.keyb.leftAltPressed || input.keyb.leftCtrlPressed)
+				if (keyb.shiftPressed || keyb.leftAltPressed || keyb.leftCtrlPressed)
 				{
 					saveUndo();
-					if (input.keyb.leftAltPressed && !input.keyb.leftCtrlPressed)
+					if (keyb.leftAltPressed && !keyb.leftCtrlPressed)
 					{
 						if (modEntry->currRow < 63)
 						{
@@ -821,7 +819,7 @@
 								noteSrc = &modEntry->patterns[modEntry->currPattern][((i + 0) * AMIGA_VOICES) + editor.cursor.channel];
 								noteDst = &modEntry->patterns[modEntry->currPattern][((i + 1) * AMIGA_VOICES) + editor.cursor.channel];
 
-								if (input.keyb.leftCtrlPressed)
+								if (keyb.leftCtrlPressed)
 								{
 									noteDst->command = noteSrc->command;
 									noteDst->param = noteSrc->param;
@@ -834,7 +832,7 @@
 
 							noteDst = &modEntry->patterns[modEntry->currPattern][((i + 1) * AMIGA_VOICES) + editor.cursor.channel];
 
-							if (!input.keyb.leftCtrlPressed)
+							if (!keyb.leftCtrlPressed)
 							{
 								noteDst->period = 0;
 								noteDst->sample = 0;
@@ -903,7 +901,7 @@
 			}
 			else
 			{
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 				{
 					// cut channel and put in buffer
 					saveUndo();
@@ -923,7 +921,7 @@
 					updateWindowTitle(MOD_IS_MODIFIED);
 					editor.ui.updatePatternData = true;
 				}
-				else if (input.keyb.leftAltPressed)
+				else if (keyb.leftAltPressed)
 				{
 					// cut pattern and put in buffer
 					saveUndo();
@@ -937,7 +935,7 @@
 					updateWindowTitle(MOD_IS_MODIFIED);
 					editor.ui.updatePatternData = true;
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					// cut channel commands and put in buffer
 					saveUndo();
@@ -967,7 +965,7 @@
 			}
 			else
 			{
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 				{
 					// copy channel to buffer
 
@@ -975,7 +973,7 @@
 					for (i = 0; i < MOD_ROWS; i++)
 						*noteDst++ = modEntry->patterns[modEntry->currPattern][(i * AMIGA_VOICES) + editor.cursor.channel];
 				}
-				else if (input.keyb.leftAltPressed)
+				else if (keyb.leftAltPressed)
 				{
 					// copy pattern to buffer
 
@@ -982,7 +980,7 @@
 					memcpy(editor.patternBuffer, modEntry->patterns[modEntry->currPattern],
 						sizeof (note_t) * (AMIGA_VOICES * MOD_ROWS));
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					// copy channel commands to buffer
 
@@ -1008,7 +1006,7 @@
 			}
 			else
 			{
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 				{
 					// paste channel buffer to channel
 					saveUndo();
@@ -1020,7 +1018,7 @@
 					updateWindowTitle(MOD_IS_MODIFIED);
 					editor.ui.updatePatternData = true;
 				}
-				else if (input.keyb.leftAltPressed)
+				else if (keyb.leftAltPressed)
 				{
 					// paste pattern buffer to pattern
 					saveUndo();
@@ -1031,7 +1029,7 @@
 					updateWindowTitle(MOD_IS_MODIFIED);
 					editor.ui.updatePatternData = true;
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					// paste channel commands buffer to channel
 					saveUndo();
@@ -1055,7 +1053,7 @@
 
 		case SDL_SCANCODE_F6:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 			{
 				editor.f6Pos = modEntry->currRow;
 				displayMsg("POSITION SET");
@@ -1062,7 +1060,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.playMode = PLAY_MODE_PATTERN;
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, editor.f6Pos);
@@ -1071,7 +1069,7 @@
 					pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
 					statusAllRight();
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					if (!editor.ui.samplerScreenShown)
 					{
@@ -1083,7 +1081,7 @@
 						statusAllRight();
 					}
 				}
-				else if (input.keyb.leftAmigaPressed)
+				else if (keyb.leftAmigaPressed)
 				{
 					editor.playMode = PLAY_MODE_NORMAL;
 					modPlay(DONT_SET_PATTERN, modEntry->currOrder, editor.f6Pos);
@@ -1102,7 +1100,7 @@
 
 		case SDL_SCANCODE_F7:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 			{
 				editor.f7Pos = modEntry->currRow;
 				displayMsg("POSITION SET");
@@ -1109,7 +1107,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.playMode = PLAY_MODE_PATTERN;
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, editor.f7Pos);
@@ -1118,7 +1116,7 @@
 					pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
 					statusAllRight();
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					if (!editor.ui.samplerScreenShown)
 					{
@@ -1130,7 +1128,7 @@
 						statusAllRight();
 					}
 				}
-				else if (input.keyb.leftAmigaPressed)
+				else if (keyb.leftAmigaPressed)
 				{
 					editor.playMode = PLAY_MODE_NORMAL;
 					modPlay(DONT_SET_PATTERN, modEntry->currOrder, editor.f7Pos);
@@ -1149,7 +1147,7 @@
 
 		case SDL_SCANCODE_F8:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 			{
 				editor.f8Pos = modEntry->currRow;
 				displayMsg("POSITION SET");
@@ -1156,7 +1154,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.playMode = PLAY_MODE_PATTERN;
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, editor.f8Pos);
@@ -1165,7 +1163,7 @@
 					pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
 					statusAllRight();
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					if (!editor.ui.samplerScreenShown)
 					{
@@ -1177,7 +1175,7 @@
 						statusAllRight();
 					}
 				}
-				else if (input.keyb.leftAmigaPressed)
+				else if (keyb.leftAmigaPressed)
 				{
 					editor.playMode = PLAY_MODE_NORMAL;
 					modPlay(DONT_SET_PATTERN, modEntry->currOrder, editor.f8Pos);
@@ -1196,7 +1194,7 @@
 
 		case SDL_SCANCODE_F9:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 			{
 				editor.f9Pos = modEntry->currRow;
 				displayMsg("POSITION SET");
@@ -1203,7 +1201,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.playMode = PLAY_MODE_PATTERN;
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, editor.f9Pos);
@@ -1212,7 +1210,7 @@
 					pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
 					statusAllRight();
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					if (!editor.ui.samplerScreenShown)
 					{
@@ -1224,7 +1222,7 @@
 						statusAllRight();
 					}
 				}
-				else if (input.keyb.leftAmigaPressed)
+				else if (keyb.leftAmigaPressed)
 				{
 					editor.playMode = PLAY_MODE_NORMAL;
 					modPlay(DONT_SET_PATTERN, modEntry->currOrder, editor.f9Pos);
@@ -1243,7 +1241,7 @@
 
 		case SDL_SCANCODE_F10:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 			{
 				editor.f10Pos = modEntry->currRow;
 				displayMsg("POSITION SET");
@@ -1250,7 +1248,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.playMode = PLAY_MODE_PATTERN;
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, editor.f10Pos);
@@ -1259,7 +1257,7 @@
 					pointerSetMode(POINTER_MODE_PLAY, DO_CARRY);
 					statusAllRight();
 				}
-				else if (input.keyb.leftCtrlPressed)
+				else if (keyb.leftCtrlPressed)
 				{
 					if (!editor.ui.samplerScreenShown)
 					{
@@ -1271,7 +1269,7 @@
 						statusAllRight();
 					}
 				}
-				else if (input.keyb.leftAmigaPressed)
+				else if (keyb.leftAmigaPressed)
 				{
 					editor.playMode = PLAY_MODE_NORMAL;
 					modPlay(DONT_SET_PATTERN, modEntry->currOrder, editor.f10Pos);
@@ -1290,10 +1288,10 @@
 
 		case SDL_SCANCODE_F11:
 		{
-			if (input.keyb.leftAltPressed)
+			if (keyb.leftAltPressed)
 			{
-				ptConfig.realVuMeters ^= 1;
-				displayMsg(ptConfig.realVuMeters ? "VU-METERS: REAL" : "VU-METERS: FAKE");
+				config.realVuMeters ^= 1;
+				displayMsg(config.realVuMeters ? "VU-METERS: REAL" : "VU-METERS: FAKE");
 			}
 		}
 		break;
@@ -1300,7 +1298,7 @@
 
 		case SDL_SCANCODE_TAB:
 		{
-			if (input.keyb.shiftPressed)
+			if (keyb.shiftPressed)
 				movePatCurPrevCh();
 			else
 				movePatCurNextCh();
@@ -1309,13 +1307,13 @@
 
 		case SDL_SCANCODE_0:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 0;
 				displayMsg("EDITSKIP = 0");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[9] = (noteSrc->command << 8) | noteSrc->param;
@@ -1330,23 +1328,23 @@
 
 		case SDL_SCANCODE_1:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackNoteUp(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 1;
 				displayMsg("EDITSKIP = 1");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[0] = (noteSrc->command << 8) | noteSrc->param;
 				displayMsg("COMMAND STORED!");
 			}
-			else if (editor.currMode == MODE_IDLE && input.keyb.leftAltPressed)
+			else if (editor.currMode == MODE_IDLE && keyb.leftAltPressed)
 			{
 				incMulti(0);
 			}
@@ -1359,23 +1357,23 @@
 
 		case SDL_SCANCODE_2:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattNoteUp(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 2;
 				displayMsg("EDITSKIP = 2");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[1] = (noteSrc->command << 8) | noteSrc->param;
 				displayMsg("COMMAND STORED!");
 			}
-			else if (editor.currMode == MODE_IDLE && input.keyb.leftAltPressed)
+			else if (editor.currMode == MODE_IDLE && keyb.leftAltPressed)
 			{
 				incMulti(1);
 			}
@@ -1388,23 +1386,23 @@
 
 		case SDL_SCANCODE_3:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackNoteUp(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 3;
 				displayMsg("EDITSKIP = 3");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[2] = (noteSrc->command << 8) | noteSrc->param;
 				displayMsg("COMMAND STORED!");
 			}
-			else if (editor.currMode == MODE_IDLE && input.keyb.leftAltPressed)
+			else if (editor.currMode == MODE_IDLE && keyb.leftAltPressed)
 			{
 				incMulti(2);
 			}
@@ -1417,23 +1415,23 @@
 
 		case SDL_SCANCODE_4:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattNoteUp(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 4;
 				displayMsg("EDITSKIP = 4");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[3] = (noteSrc->command << 8) | noteSrc->param;
 				displayMsg("COMMAND STORED!");
 			}
-			else if (editor.currMode == MODE_IDLE && input.keyb.leftAltPressed)
+			else if (editor.currMode == MODE_IDLE && keyb.leftAltPressed)
 			{
 				incMulti(3);
 			}
@@ -1446,13 +1444,13 @@
 
 		case SDL_SCANCODE_5:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 5;
 				displayMsg("EDITSKIP = 5");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[4] = (noteSrc->command << 8) | noteSrc->param;
@@ -1467,13 +1465,13 @@
 
 		case SDL_SCANCODE_6:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 6;
 				displayMsg("EDITSKIP = 6");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[5] = (noteSrc->command << 8) | noteSrc->param;
@@ -1488,13 +1486,13 @@
 
 		case SDL_SCANCODE_7:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 7;
 				displayMsg("EDITSKIP = 7");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[6] = (noteSrc->command << 8) | noteSrc->param;
@@ -1509,13 +1507,13 @@
 
 		case SDL_SCANCODE_8:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 8;
 				displayMsg("EDITSKIP = 8");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[7] = (noteSrc->command << 8) | noteSrc->param;
@@ -1530,13 +1528,13 @@
 
 		case SDL_SCANCODE_9:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.editMoveAdd = 9;
 				displayMsg("EDITSKIP = 9");
 				editor.ui.updateTrackerFlags = true;
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				noteSrc = &modEntry->patterns[modEntry->currPattern][(modEntry->currRow * AMIGA_VOICES) + editor.cursor.channel];
 				editor.effectMacros[8] = (noteSrc->command << 8) | noteSrc->param;
@@ -1562,7 +1560,7 @@
 			editor.currSample = editor.keypadSampleOffset + 12;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1581,7 +1579,7 @@
 			editor.currSample = editor.keypadSampleOffset + 13;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1600,7 +1598,7 @@
 			editor.currSample = editor.keypadSampleOffset + 14;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1619,7 +1617,7 @@
 			editor.currSample = editor.keypadSampleOffset + 8;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1638,7 +1636,7 @@
 			editor.currSample = editor.keypadSampleOffset + 9;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1657,7 +1655,7 @@
 			editor.currSample = editor.keypadSampleOffset + 10;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1676,7 +1674,7 @@
 			editor.currSample = editor.keypadSampleOffset + 4;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1695,7 +1693,7 @@
 			editor.currSample = editor.keypadSampleOffset + 5;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1714,7 +1712,7 @@
 			editor.currSample = editor.keypadSampleOffset + 6;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1757,7 +1755,7 @@
 				editor.currSample--;
 
 				updateCurrSample();
-				if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+				if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 				{
 					editor.ui.changingDrumPadNote = true;
 					setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1782,7 +1780,7 @@
 				editor.currSample = editor.keypadSampleOffset + (0x08 - 1);
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 				displayErrorMsg("INVALID PAD KEY !");
 
 			editor.keypadToggle8CFlag ^= 1;
@@ -1795,7 +1793,7 @@
 			editor.currSample = editor.keypadSampleOffset + 3;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1814,7 +1812,7 @@
 			editor.currSample = editor.keypadSampleOffset + 2;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1833,7 +1831,7 @@
 			editor.currSample = editor.keypadSampleOffset + 1;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 				setStatusMessage("SELECT NOTE", NO_CARRY);
@@ -1852,7 +1850,7 @@
 			editor.currSample = editor.keypadSampleOffset + 0;
 
 			updateCurrSample();
-			if (input.keyb.leftAltPressed && editor.pNoteFlag > 0)
+			if (keyb.leftAltPressed && editor.pNoteFlag > 0)
 			{
 				editor.ui.changingDrumPadNote = true;
 
@@ -1879,8 +1877,8 @@
 
 		case SDL_SCANCODE_DOWN:
 		{
-			input.keyb.delayKey = false;
-			input.keyb.repeatKey = false;
+			keyb.delayKey = false;
+			keyb.repeatKey = false;
 
 			if (editor.ui.diskOpScreenShown)
 			{
@@ -1887,7 +1885,7 @@
 				if (editor.diskop.numEntries > DISKOP_LINES)
 				{
 					editor.diskop.scrollOffset++;
-					if (input.mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
+					if (mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
 						editor.diskop.scrollOffset += 3;
 
 					if (editor.diskop.scrollOffset > editor.diskop.numEntries-DISKOP_LINES)
@@ -1896,11 +1894,11 @@
 					editor.ui.updateDiskOpFileList = true;
 				}
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 			}
 			else if (editor.ui.posEdScreenShown)
 			{
@@ -1913,11 +1911,11 @@
 					editor.ui.updatePosEd = true;
 				}
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = true;
+				keyb.repeatKey = true;
+				keyb.delayKey = true;
 			}
 			else if (!editor.ui.samplerScreenShown)
 			{
@@ -1924,7 +1922,7 @@
 				if (editor.currMode != MODE_PLAY && editor.currMode != MODE_RECORD)
 					modSetPos(DONT_SET_ORDER, (modEntry->currRow + 1) & 0x3F);
 
-				input.keyb.repeatKey = true;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -1931,13 +1929,13 @@
 
 		case SDL_SCANCODE_UP:
 		{
-			input.keyb.delayKey  = false;
-			input.keyb.repeatKey = false;
+			keyb.delayKey  = false;
+			keyb.repeatKey = false;
 
 			if (editor.ui.diskOpScreenShown)
 			{
 				editor.diskop.scrollOffset--;
-				if (input.mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
+				if (mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
 					editor.diskop.scrollOffset -= 3;
 
 				if (editor.diskop.scrollOffset < 0)
@@ -1945,11 +1943,11 @@
 
 				editor.ui.updateDiskOpFileList = true;
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 			}
 			else if (editor.ui.posEdScreenShown)
 			{
@@ -1959,11 +1957,11 @@
 					editor.ui.updatePosEd = true;
 				}
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = true;
+				keyb.repeatKey = true;
+				keyb.delayKey = true;
 			}
 			else if (!editor.ui.samplerScreenShown)
 			{
@@ -1970,7 +1968,7 @@
 				if ((editor.currMode != MODE_PLAY) && (editor.currMode != MODE_RECORD))
 					modSetPos(DONT_SET_ORDER, (modEntry->currRow - 1) & 0x3F);
 
-				input.keyb.repeatKey = true;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -1977,19 +1975,19 @@
 
 		case SDL_SCANCODE_LEFT:
 		{
-			input.keyb.delayKey = false;
-			input.keyb.repeatKey = false;
+			keyb.delayKey = false;
+			keyb.repeatKey = false;
 
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				sampleDownButton();
 				if (editor.repeatKeyFlag)
 				{
-					input.keyb.delayKey = true;
-					input.keyb.repeatKey = true;
+					keyb.delayKey = true;
+					keyb.repeatKey = true;
 				}
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				if (modEntry->currOrder > 0)
 				{
@@ -1996,24 +1994,24 @@
 					modSetPos(modEntry->currOrder - 1, DONT_SET_ROW);
 					if (editor.repeatKeyFlag)
 					{
-						input.keyb.delayKey = true;
-						input.keyb.repeatKey = true;
+						keyb.delayKey = true;
+						keyb.repeatKey = true;
 					}
 				}
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				decPatt();
 				if (editor.repeatKeyFlag)
 				{
-					input.keyb.delayKey = true;
-					input.keyb.repeatKey = true;
+					keyb.delayKey = true;
+					keyb.repeatKey = true;
 				}
 			}
 			else
 			{
 				movePatCurLeft();
-				input.keyb.repeatKey = true;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -2020,19 +2018,19 @@
 
 		case SDL_SCANCODE_RIGHT:
 		{
-			input.keyb.delayKey = false;
-			input.keyb.repeatKey = false;
+			keyb.delayKey = false;
+			keyb.repeatKey = false;
 
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				sampleUpButton();
 				if (editor.repeatKeyFlag)
 				{
-					input.keyb.delayKey = true;
-					input.keyb.repeatKey = true;
+					keyb.delayKey = true;
+					keyb.repeatKey = true;
 				}
 			}
-			else if (input.keyb.shiftPressed)
+			else if (keyb.shiftPressed)
 			{
 				if (modEntry->currOrder < 126)
 				{
@@ -2039,24 +2037,24 @@
 					modSetPos(modEntry->currOrder + 1, DONT_SET_ROW);
 					if (editor.repeatKeyFlag)
 					{
-						input.keyb.delayKey = true;
-						input.keyb.repeatKey = true;
+						keyb.delayKey = true;
+						keyb.repeatKey = true;
 					}
 				}
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				incPatt();
 				if (editor.repeatKeyFlag)
 				{
-					input.keyb.delayKey = true;
-					input.keyb.repeatKey = true;
+					keyb.delayKey = true;
+					keyb.repeatKey = true;
 				}
 			}
 			else
 			{
 				movePatCurRight();
-				input.keyb.repeatKey = true;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -2063,11 +2061,11 @@
 
 		case SDL_SCANCODE_A:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackOctaUp(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				if (editor.ui.samplerScreenShown)
 				{
@@ -2075,7 +2073,7 @@
 				}
 				else
 				{
-					if (input.keyb.shiftPressed)
+					if (keyb.shiftPressed)
 					{
 						editor.muted[0] = true;
 						editor.muted[1] = true;
@@ -2100,7 +2098,7 @@
 
 		case SDL_SCANCODE_B:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				// CTRL+B doesn't change the status message back, so do this:
 				if (editor.ui.introScreenShown)
@@ -2122,7 +2120,7 @@
 
 				editor.ui.updateStatusText = true;
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				s = &modEntry->samples[editor.currSample];
 				if (s->length == 0)
@@ -2145,11 +2143,11 @@
 
 		case SDL_SCANCODE_C:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackOctaDown(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				if (editor.ui.samplerScreenShown)
 				{
@@ -2184,7 +2182,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.muted[2] ^= 1; // toggle channel 3
 					renderMuteButtons();
@@ -2199,17 +2197,17 @@
 
 		case SDL_SCANCODE_D:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackOctaUp(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				saveUndo();
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					if (!editor.ui.posEdScreenShown)
 					{
@@ -2239,11 +2237,11 @@
 
 		case SDL_SCANCODE_E:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackNoteDown(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				if (!editor.ui.diskOpScreenShown && !editor.ui.posEdScreenShown)
 				{
@@ -2255,7 +2253,7 @@
 					renderEditOpScreen();
 				}
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				saveUndo();
 
@@ -2290,17 +2288,17 @@
 		case SDL_SCANCODE_F:
 		{
 #ifdef __APPLE__
-			if (input.keyb.leftCommandPressed && input.keyb.leftCtrlPressed)
+			if (keyb.leftCommandPressed && keyb.leftCtrlPressed)
 			{
 				toggleFullScreen();
 			}
 			else
 #endif
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattOctaUp(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				toggleLEDFilter();
 
@@ -2309,7 +2307,7 @@
 				else
 					displayMsg("LED FILTER OFF");
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				s = &modEntry->samples[editor.currSample];
 				if (s->length == 0)
@@ -2331,7 +2329,7 @@
 
 		case SDL_SCANCODE_G:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.ui.askScreenShown = true;
 				editor.ui.askScreenType = ASK_BOOST_ALL_SAMPLES;
@@ -2339,7 +2337,7 @@
 				setStatusMessage("BOOST ALL SAMPLES", NO_CARRY);
 				renderAskDialog();
 			}
-			else if (input.keyb.leftAltPressed) // toggle record mode (PT clone and PT2.3E only)
+			else if (keyb.leftAltPressed) // toggle record mode (PT clone and PT2.3E only)
 			{
 				editor.recordMode ^= 1;
 				if (editor.recordMode == 0)
@@ -2359,7 +2357,7 @@
 
 		case SDL_SCANCODE_H:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockMarkFlag)
 				{
@@ -2378,7 +2376,7 @@
 
 		case SDL_SCANCODE_I:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockBufferFlag)
 				{
@@ -2408,7 +2406,7 @@
 						= editor.blockBuffer[editor.buffFromPos + i];
 				}
 
-				if (!input.keyb.shiftPressed)
+				if (!keyb.shiftPressed)
 				{
 					modEntry->currRow += i & 0xFF;
 					if (modEntry->currRow > 63)
@@ -2418,7 +2416,7 @@
 				updateWindowTitle(MOD_IS_MODIFIED);
 				editor.ui.updatePatternData = true;
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.autoInsFlag ^= 1;
 				editor.ui.updateTrackerFlags = true;
@@ -2432,7 +2430,7 @@
 
 		case SDL_SCANCODE_J:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockBufferFlag)
 				{
@@ -2466,7 +2464,7 @@
 					j++;
 				}
 
-				if (!input.keyb.shiftPressed)
+				if (!keyb.shiftPressed)
 				{
 					modEntry->currRow += (editor.buffToPos-editor.buffFromPos) + 1;
 					if (modEntry->currRow > 63)
@@ -2485,7 +2483,7 @@
 
 		case SDL_SCANCODE_K:
 		{
-			if (input.keyb.leftAltPressed)
+			if (keyb.leftAltPressed)
 			{
 				for (i = 0; i < MOD_ROWS; i++)
 				{
@@ -2502,12 +2500,12 @@
 				updateWindowTitle(MOD_IS_MODIFIED);
 				editor.ui.updatePatternData = true;
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				saveUndo();
 
 				i = modEntry->currRow;
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 				{
 					// kill to start
 					while (i >= 0)
@@ -2548,7 +2546,7 @@
 
 		case SDL_SCANCODE_L:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockMarkFlag)
 				{
@@ -2567,15 +2565,15 @@
 
 		case SDL_SCANCODE_M:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.multiFlag ^= 1;
 				editor.ui.updateTrackerFlags = true;
 				editor.ui.updateKeysText = true;
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
-				if (input.keyb.shiftPressed)
+				if (keyb.shiftPressed)
 					editor.metroChannel = editor.cursor.channel + 1;
 				else
 					editor.metroFlag ^= 1;
@@ -2591,7 +2589,7 @@
 
 		case SDL_SCANCODE_N:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.blockMarkFlag = true;
 				modEntry->currRow = editor.blockToPos;
@@ -2605,7 +2603,7 @@
 
 		case SDL_SCANCODE_O:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				// fun fact: this function is broken in PT but I fixed it in my clone
 
@@ -2642,7 +2640,7 @@
 
 		case SDL_SCANCODE_P:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockBufferFlag)
 				{
@@ -2667,7 +2665,7 @@
 					j++;
 				}
 
-				if (!input.keyb.shiftPressed)
+				if (!keyb.shiftPressed)
 				{
 					modEntry->currRow += (editor.buffToPos-editor.buffFromPos) + 1;
 					if (modEntry->currRow > 63)
@@ -2677,7 +2675,7 @@
 				updateWindowTitle(MOD_IS_MODIFIED);
 				editor.ui.updatePatternData = true;
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				if (!editor.ui.diskOpScreenShown)
 				{
@@ -2702,11 +2700,11 @@
 
 		case SDL_SCANCODE_Q:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackNoteDown(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.muted[0] = false;
 				editor.muted[1] = false;
@@ -2714,7 +2712,7 @@
 				editor.muted[3] = false;
 				renderMuteButtons();
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.ui.askScreenShown = true;
 				editor.ui.askScreenType = ASK_QUIT;
@@ -2732,11 +2730,11 @@
 
 		case SDL_SCANCODE_R:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattNoteDown(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				editor.f6Pos = 0;
 				editor.f7Pos = 16;
@@ -2746,7 +2744,7 @@
 
 				displayMsg("POS RESTORED !");
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.ui.askScreenShown = true;
 				editor.ui.askScreenType = ASK_RESAMPLE;
@@ -2763,7 +2761,7 @@
 
 		case SDL_SCANCODE_S:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				// if we're in sample load/save mode, set current dir to modules path
 				if (editor.diskop.mode == DISKOP_MODE_SMP)
@@ -2775,11 +2773,11 @@
 				if (editor.diskop.mode == DISKOP_MODE_SMP)
 					UNICHAR_CHDIR(editor.samplesPathU);
 			}
-			else if (input.keyb.leftAmigaPressed)
+			else if (keyb.leftAmigaPressed)
 			{
 				pattOctaUp(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				samplerScreen();
 			}
@@ -2792,13 +2790,13 @@
 
 		case SDL_SCANCODE_T:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				editor.swapChannelFlag = true;
 				pointerSetMode(POINTER_MODE_MSG1, NO_CARRY);
 				setStatusMessage("SWAP (1/2/3/4) ?", NO_CARRY);
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				toggleTuningTone();
 			}
@@ -2811,7 +2809,7 @@
 
 		case SDL_SCANCODE_U:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 				undoLastChange();
 			else
 				handleEditKeys(scancode, EDIT_NORMAL);
@@ -2820,11 +2818,11 @@
 
 		case SDL_SCANCODE_V:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattOctaDown(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				if (editor.ui.samplerScreenShown)
 				{
@@ -2840,7 +2838,7 @@
 					renderAskDialog();
 				}
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.muted[3] ^= 1; // toggle channel 4
 				renderMuteButtons();
@@ -2854,11 +2852,11 @@
 
 		case SDL_SCANCODE_W:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattNoteDown(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				// Polyphonize Block
 				if (!editor.blockBufferFlag)
@@ -2893,7 +2891,7 @@
 					gotoNextMulti();
 				}
 
-				if (!input.keyb.shiftPressed)
+				if (!keyb.shiftPressed)
 				{
 					modEntry->currRow += (editor.buffToPos-editor.buffFromPos) + 1;
 					if (modEntry->currRow > 63)
@@ -2912,11 +2910,11 @@
 
 		case SDL_SCANCODE_X:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				pattOctaDown(TRANSPOSE_ALL);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				if (editor.ui.samplerScreenShown)
 				{
@@ -2963,7 +2961,7 @@
 			}
 			else
 			{
-				if (input.keyb.leftAltPressed)
+				if (keyb.leftAltPressed)
 				{
 					editor.muted[1] ^= 1; // toggle channel 2
 					renderMuteButtons();
@@ -2978,7 +2976,7 @@
 
 		case SDL_SCANCODE_Y:
 		{
-			if (input.keyb.leftCtrlPressed)
+			if (keyb.leftCtrlPressed)
 			{
 				if (!editor.blockMarkFlag)
 				{
@@ -3018,7 +3016,7 @@
 				updateWindowTitle(MOD_IS_MODIFIED);
 				editor.ui.updatePatternData = true;
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.ui.askScreenShown = true;
 				editor.ui.askScreenType = ASK_SAVE_ALL_SAMPLES;
@@ -3035,11 +3033,11 @@
 
 		case SDL_SCANCODE_Z:
 		{
-			if (input.keyb.leftAmigaPressed)
+			if (keyb.leftAmigaPressed)
 			{
 				trackOctaDown(TRANSPOSE_ALL, 0, MOD_ROWS - 1);
 			}
-			else if (input.keyb.leftCtrlPressed)
+			else if (keyb.leftCtrlPressed)
 			{
 				if (editor.ui.samplerScreenShown)
 				{
@@ -3067,7 +3065,7 @@
 					displayMsg("EFX RESTORED !");
 				}
 			}
-			else if (input.keyb.leftAltPressed)
+			else if (keyb.leftAltPressed)
 			{
 				editor.muted[0] ^= 1; // toggle channel 1
 				renderMuteButtons();
@@ -3145,16 +3143,16 @@
 {
 	uint8_t repeatNum;
 
-	if (!input.keyb.repeatKey || (editor.ui.clearScreenShown || editor.ui.askScreenShown))
+	if (!keyb.repeatKey || (editor.ui.clearScreenShown || editor.ui.askScreenShown))
 	{
-		input.keyb.repeatFrac = 0;
-		input.keyb.repeatCounter = 0;
+		keyb.repeatFrac = 0;
+		keyb.repeatCounter = 0;
 		return;
 	}
 
-	if (input.keyb.delayKey && input.keyb.delayCounter < KEYB_REPEAT_DELAY)
+	if (keyb.delayKey && keyb.delayCounter < KEYB_REPEAT_DELAY)
 	{
-		input.keyb.delayCounter++;
+		keyb.delayCounter++;
 		return;
 	}
 
@@ -3162,9 +3160,9 @@
 	{
 		case SDL_SCANCODE_PAGEUP:
 		{
-			if (input.keyb.repeatCounter >= 3)
+			if (keyb.repeatCounter >= 3)
 			{
-				input.keyb.repeatCounter = 0;
+				keyb.repeatCounter = 0;
 
 				if (editor.ui.posEdScreenShown)
 				{
@@ -3199,9 +3197,9 @@
 
 		case SDL_SCANCODE_PAGEDOWN:
 		{
-			if (input.keyb.repeatCounter >= 3)
+			if (keyb.repeatCounter >= 3)
 			{
-				input.keyb.repeatCounter = 0;
+				keyb.repeatCounter = 0;
 
 				if (editor.ui.posEdScreenShown)
 				{
@@ -3233,45 +3231,45 @@
 		{
 			if (editor.ui.editTextFlag)
 			{
-				if (input.keyb.repeatCounter >= 4)
+				if (keyb.repeatCounter >= 4)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 					textCharPrevious();
 				}
 			}
 			else
 			{
-				if (input.keyb.leftCtrlPressed)
+				if (keyb.leftCtrlPressed)
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						sampleDownButton();
 					}
 				}
-				else if (input.keyb.shiftPressed)
+				else if (keyb.shiftPressed)
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						if (modEntry->currOrder > 0)
 							modSetPos(modEntry->currOrder - 1, DONT_SET_ROW);
 					}
 				}
-				else if (input.keyb.leftAltPressed)
+				else if (keyb.leftAltPressed)
 				{
-					if (input.keyb.repeatCounter >= 4)
+					if (keyb.repeatCounter >= 4)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						decPatt();
 					}
 				}
 				else
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
-						if (!input.keyb.shiftPressed && !input.keyb.leftAltPressed && !input.keyb.leftCtrlPressed)
+						keyb.repeatCounter = 0;
+						if (!keyb.shiftPressed && !keyb.leftAltPressed && !keyb.leftCtrlPressed)
 							movePatCurLeft();
 					}
 				}
@@ -3283,45 +3281,45 @@
 		{
 			if (editor.ui.editTextFlag)
 			{
-				if (input.keyb.repeatCounter >= 4)
+				if (keyb.repeatCounter >= 4)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 					textCharNext();
 				}
 			}
 			else
 			{
-				if (input.keyb.leftCtrlPressed)
+				if (keyb.leftCtrlPressed)
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						sampleUpButton();
 					}
 				}
-				else if (input.keyb.shiftPressed)
+				else if (keyb.shiftPressed)
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						if (modEntry->currOrder < 126)
 							modSetPos(modEntry->currOrder + 1, DONT_SET_ROW);
 					}
 				}
-				else if (input.keyb.leftAltPressed)
+				else if (keyb.leftAltPressed)
 				{
-					if (input.keyb.repeatCounter >= 4)
+					if (keyb.repeatCounter >= 4)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						incPatt();
 					}
 				}
 				else
 				{
-					if (input.keyb.repeatCounter >= 6)
+					if (keyb.repeatCounter >= 6)
 					{
-						input.keyb.repeatCounter = 0;
-						if (!input.keyb.shiftPressed && !input.keyb.leftAltPressed && !input.keyb.leftCtrlPressed)
+						keyb.repeatCounter = 0;
+						if (!keyb.shiftPressed && !keyb.leftAltPressed && !keyb.leftCtrlPressed)
 							movePatCurRight();
 					}
 				}
@@ -3333,12 +3331,12 @@
 		{
 			if (editor.ui.diskOpScreenShown)
 			{
-				if (input.keyb.repeatCounter >= 1)
+				if (keyb.repeatCounter >= 1)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 
 					editor.diskop.scrollOffset--;
-					if (input.mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
+					if (mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
 						editor.diskop.scrollOffset -= 3;
 
 					if (editor.diskop.scrollOffset < 0)
@@ -3349,9 +3347,9 @@
 			}
 			else if (editor.ui.posEdScreenShown)
 			{
-				if (input.keyb.repeatCounter >= 3)
+				if (keyb.repeatCounter >= 3)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 					if (modEntry->currOrder > 0)
 					{
 						modSetPos(modEntry->currOrder - 1, DONT_SET_ROW);
@@ -3364,14 +3362,14 @@
 				if (editor.currMode != MODE_PLAY && editor.currMode != MODE_RECORD)
 				{
 					repeatNum = 6;
-					if (input.keyb.leftAltPressed)
+					if (keyb.leftAltPressed)
 						repeatNum = 1;
-					else if (input.keyb.shiftPressed)
+					else if (keyb.shiftPressed)
 						repeatNum = 3;
 
-					if (input.keyb.repeatCounter >= repeatNum)
+					if (keyb.repeatCounter >= repeatNum)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						modSetPos(DONT_SET_ORDER, (modEntry->currRow - 1) & 0x3F);
 					}
 				}
@@ -3383,14 +3381,14 @@
 		{
 			if (editor.ui.diskOpScreenShown)
 			{
-				if (input.keyb.repeatCounter >= 1)
+				if (keyb.repeatCounter >= 1)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 
 					if (editor.diskop.numEntries > DISKOP_LINES)
 					{
 						editor.diskop.scrollOffset++;
-						if (input.mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
+						if (mouse.rightButtonPressed) // PT quirk: right mouse button speeds up scrolling even on keyb UP/DOWN
 							editor.diskop.scrollOffset += 3;
 
 						if (editor.diskop.scrollOffset > editor.diskop.numEntries-DISKOP_LINES)
@@ -3402,9 +3400,9 @@
 			}
 			else if (editor.ui.posEdScreenShown)
 			{
-				if (input.keyb.repeatCounter >= 3)
+				if (keyb.repeatCounter >= 3)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 
 					if (modEntry->currOrder != modEntry->head.orderCount-1)
 					{
@@ -3421,14 +3419,14 @@
 				if (editor.currMode != MODE_PLAY && editor.currMode != MODE_RECORD)
 				{
 					repeatNum = 6;
-					if (input.keyb.leftAltPressed)
+					if (keyb.leftAltPressed)
 						repeatNum = 1;
-					else if (input.keyb.shiftPressed)
+					else if (keyb.shiftPressed)
 						repeatNum = 3;
 
-					if (input.keyb.repeatCounter >= repeatNum)
+					if (keyb.repeatCounter >= repeatNum)
 					{
-						input.keyb.repeatCounter = 0;
+						keyb.repeatCounter = 0;
 						modSetPos(DONT_SET_ORDER, (modEntry->currRow + 1) & 0x3F);
 					}
 				}
@@ -3441,9 +3439,9 @@
 			if (editor.ui.editTextFlag)
 			{
 				// only repeat backspace while editing texts
-				if (input.keyb.repeatCounter >= 3)
+				if (keyb.repeatCounter >= 3)
 				{
-					input.keyb.repeatCounter = 0;
+					keyb.repeatCounter = 0;
 					keyDownHandler(scancode, 0);
 				}
 			}
@@ -3456,9 +3454,9 @@
 
 		default:
 		{
-			if (input.keyb.repeatCounter >= 3)
+			if (keyb.repeatCounter >= 3)
 			{
-				input.keyb.repeatCounter = 0;
+				keyb.repeatCounter = 0;
 				keyDownHandler(scancode, 0);
 			}
 		}
@@ -3469,11 +3467,11 @@
 
 	const uint64_t keyRepeatDelta = ((uint64_t)AMIGA_PAL_VBLANK_HZ << 32) / VBLANK_HZ;
 
-	input.keyb.repeatFrac += keyRepeatDelta; // 32.32 fixed-point counter
-	if (input.keyb.repeatFrac > 0xFFFFFFFF)
+	keyb.repeatFrac += keyRepeatDelta; // 32.32 fixed-point counter
+	if (keyb.repeatFrac > 0xFFFFFFFF)
 	{
-		input.keyb.repeatFrac &= 0xFFFFFFFF;
-		input.keyb.repeatCounter++;
+		keyb.repeatFrac &= 0xFFFFFFFF;
+		keyb.repeatCounter++;
 	}
 }
 
@@ -4064,11 +4062,11 @@
 
 	updateTextObject(editor.ui.editObject);
 
-	if (!input.keyb.repeatKey)
-		input.keyb.delayCounter = 0;
+	if (!keyb.repeatKey)
+		keyb.delayCounter = 0;
 
-	input.keyb.repeatKey = true;
-	input.keyb.delayKey = true;
+	keyb.repeatKey = true;
+	keyb.delayKey = true;
 }
 
 bool handleTextEditMode(SDL_Scancode scancode)
@@ -4119,16 +4117,16 @@
 			if (editor.ui.editTextFlag)
 			{
 				textCharPrevious();
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 			}
 			else
 			{
-				input.keyb.delayKey = false;
-				input.keyb.repeatKey = true;
+				keyb.delayKey = false;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -4138,16 +4136,16 @@
 			if (editor.ui.editTextFlag)
 			{
 				textCharNext();
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 			}
 			else
 			{
-				input.keyb.delayKey = false;
-				input.keyb.repeatKey = true;
+				keyb.delayKey = false;
+				keyb.repeatKey = true;
 			}
 		}
 		break;
@@ -4170,11 +4168,11 @@
 				if (editor.ui.editObject == PTB_SONGNAME || editor.ui.editObject == PTB_SAMPLENAME)
 					 *editor.ui.textEndPtr = '\0';
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 
 				updateTextObject(editor.ui.editObject);
 			}
@@ -4207,11 +4205,11 @@
 					updateTextObject(editor.ui.editObject);
 				}
 
-				if (!input.keyb.repeatKey)
-					input.keyb.delayCounter = 0;
+				if (!keyb.repeatKey)
+					keyb.delayCounter = 0;
 
-				input.keyb.repeatKey = true;
-				input.keyb.delayKey = false;
+				keyb.repeatKey = true;
+				keyb.delayKey = false;
 			}
 			else
 			{
@@ -4223,10 +4221,10 @@
 					diskOpSetPath("..", DISKOP_CACHE);
 #endif
 				}
-				else if (input.keyb.shiftPressed || input.keyb.leftAltPressed || input.keyb.leftCtrlPressed)
+				else if (keyb.shiftPressed || keyb.leftAltPressed || keyb.leftCtrlPressed)
 				{
 					saveUndo();
-					if (input.keyb.leftAltPressed && !input.keyb.leftCtrlPressed)
+					if (keyb.leftAltPressed && !keyb.leftCtrlPressed)
 					{
 						if (modEntry->currRow > 0)
 						{
@@ -4259,7 +4257,7 @@
 								noteSrc = &modEntry->patterns[modEntry->currPattern][((i + 1) * AMIGA_VOICES) + editor.cursor.channel];
 								noteDst = &modEntry->patterns[modEntry->currPattern][(i * AMIGA_VOICES) + editor.cursor.channel];
 
-								if (input.keyb.leftCtrlPressed)
+								if (keyb.leftCtrlPressed)
 								{
 									noteDst->command = noteSrc->command;
 									noteDst->param = noteSrc->param;
--- a/src/pt2_main.c
+++ b/src/pt2_main.c
@@ -40,13 +40,6 @@
 
 module_t *modEntry = NULL; // globalized
 
-// accessed by pt_visuals.c
-uint32_t *pixelBuffer = NULL;
-SDL_Window *window = NULL;
-SDL_Renderer *renderer = NULL;
-SDL_Texture  *texture = NULL;
-// -----------------------------
-
 static bool backupMadeAfterCrash;
 
 #ifdef _WIN32
@@ -73,9 +66,6 @@
 #endif
 #endif
 
-extern bool forceMixerOff; // pt_audio.c
-extern uint32_t palette[PALETTE_NUM]; // pt_palette.c
-
 #ifdef _WIN32
 static void makeSureDirIsProgramDir(void);
 static void disableWasapi(void);
@@ -110,9 +100,6 @@
 	#pragma message("WARNING: The SDL2 dev lib is older than ver 2.0.5. You'll get fullscreen mode issues.")
 #endif
 
-	cpu.hasSSE = SDL_HasSSE();
-	cpu.hasSSE2 = SDL_HasSSE2();
-
 	// set up crash handler
 #ifndef _DEBUG
 #ifdef _WIN32
@@ -154,14 +141,14 @@
 #endif
 
 #ifdef _WIN32
-	if (!cpu.hasSSE)
+	if (!SDL_HasSSE())
 	{
-		showErrorMsgBox("Your computer's processor doesn't have the SSE instruction set\n" \
+		showErrorMsgBox("Your computer's processor doesn't have the SSE+SSE2 instruction set\n" \
 		                "which is needed for this program to run. Sorry!");
 		return 0;
 	}
 
-	if (!cpu.hasSSE2)
+	if (!SDL_HasSSE2())
 	{
 		showErrorMsgBox("Your computer's processor doesn't have the SSE2 instruction set\n" \
 		                "which is needed for this program to run. Sorry!");
@@ -170,12 +157,14 @@
 
 	setupWin32Usleep();
 	disableWasapi(); // disable problematic WASAPI SDL2 audio driver on Windows (causes clicks/pops sometimes...)
+	                 // 13.03.2020: This is still needed with SDL 2.0.12...
 #endif
 
 	/* SDL 2.0.9 for Windows has a serious bug where you need to initialize the joystick subsystem
 	** (even if you don't use it) or else weird things happen like random stutters, keyboard (rarely) being
 	** reinitialized in Windows and what not.
-	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4391 */
+	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4391
+	*/
 #if defined _WIN32 && SDL_PATCHLEVEL == 9
 	if (SDL_Init(SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_JOYSTICK) != 0)
 #else
@@ -190,7 +179,8 @@
 
 	/* Text input is started by default in SDL2, turn it off to remove ~2ms spikes per key press.
 	** We manuallay start it again when someone clicks on a text edit box, and stop it when done.
-	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4166 */
+	** Ref.: https://bugzilla.libsdl.org/show_bug.cgi?id=4166
+	*/
 	SDL_StopTextInput();
 
  #ifdef __APPLE__
@@ -299,7 +289,7 @@
 	fillToVuMetersBgBuffer();
 	updateCursorPos();
 
-	SDL_ShowWindow(window);
+	SDL_ShowWindow(video.window);
 
 	changePathToHome(); // set path to home/user-dir now
 	diskOpSetInitPath(); // set path to custom path in config (if present)
@@ -313,9 +303,9 @@
 		readKeyModifiers(); // set/clear CTRL/ALT/SHIFT/AMIGA key states
 		handleInput();
 		updateMouseCounters();
-		handleKeyRepeat(input.keyb.lastRepKey);
+		handleKeyRepeat(keyb.lastRepKey);
 
-		if (!input.mouse.buttonWaiting && editor.ui.sampleMarkingPos == -1 &&
+		if (!mouse.buttonWaiting && editor.ui.sampleMarkingPos == -1 &&
 			!editor.ui.forceSampleDrag && !editor.ui.forceVolDrag && !editor.ui.forceSampleEdit)
 		{
 			handleGUIButtonRepeat();
@@ -339,17 +329,27 @@
 
 	while (SDL_PollEvent(&event))
 	{
-		if (editor.ui.vsync60HzPresent)
+		if (event.type == SDL_WINDOWEVENT)
 		{
-			/* if we minimize the window and vsync is present, vsync is temporarily turned off.
-			** recalc waitVBL() vars so that it can sleep properly in said mode. */
-			if (event.type == SDL_WINDOWEVENT &&
-				(event.window.event == SDL_WINDOWEVENT_MINIMIZED || event.window.event == SDL_WINDOWEVENT_FOCUS_LOST))
+			if (event.window.event == SDL_WINDOWEVENT_HIDDEN)
+				video.windowHidden = true;
+			else if (event.window.event == SDL_WINDOWEVENT_SHOWN)
+				video.windowHidden = false;
+
+			if (video.vsync60HzPresent)
 			{
-				setupWaitVBL();
+				/* if we minimize the window and vsync is present, vsync is temporarily turned off.
+				** recalc waitVBL() vars so that it can sleep properly in said mode.
+				*/
+				if (event.window.event == SDL_WINDOWEVENT_MINIMIZED ||
+					event.window.event == SDL_WINDOWEVENT_FOCUS_LOST)
+				{
+					setupWaitVBL();
+				}
 			}
 		}
 
+
 #ifdef _WIN32
 		handleSysMsg(event);
 #endif
@@ -373,7 +373,7 @@
 		{
 			loadDroppedFile(event.drop.file, (uint32_t)strlen(event.drop.file), false, true);
 			SDL_free(event.drop.file);
-			SDL_RaiseWindow(window); // set window focus
+			SDL_RaiseWindow(video.window); // set window focus
 		}
 		if (event.type == SDL_QUIT)
 		{
@@ -385,7 +385,7 @@
 		}
 		else if (event.type == SDL_KEYDOWN)
 		{
-			if (editor.repeatKeyFlag || input.keyb.lastRepKey != event.key.keysym.scancode)
+			if (editor.repeatKeyFlag || keyb.lastRepKey != event.key.keysym.scancode)
 				keyDownHandler(event.key.keysym.scancode, event.key.keysym.sym);
 		}
 		else if (event.type == SDL_MOUSEBUTTONUP)
@@ -435,10 +435,14 @@
 static bool initializeVars(void)
 {
 	// clear common structs
-	memset(&input, 0, sizeof (input));
+	memset(&keyb, 0, sizeof (keyb));
+	memset(&mouse, 0, sizeof (mouse));
+	memset(&video, 0, sizeof (video));
 	memset(&editor, 0, sizeof (editor));
-	memset(&ptConfig, 0, sizeof (ptConfig));
+	memset(&config, 0, sizeof (config));
 
+	setDefaultPalette();
+
 	editor.repeatKeyFlag = (SDL_GetModState() & KMOD_CAPS) ? true : false;
 
 	modEntry = NULL;
@@ -450,17 +454,17 @@
 	if (!allocSamplerVars() || !allocDiskOpVars())
 		goto oom;
 
-	ptConfig.defModulesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
-	ptConfig.defSamplesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
+	config.defModulesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
+	config.defSamplesDir = (char *)calloc(PATH_MAX + 1, sizeof (char));
 	editor.tempSample = (int8_t *)calloc(MAX_SAMPLE_LEN, 1);
 
-	if (ptConfig.defModulesDir == NULL || ptConfig.defSamplesDir == NULL ||
+	if (config.defModulesDir == NULL || config.defSamplesDir == NULL ||
 		editor.tempSample == NULL)
 	{
 		goto oom;
 	}
 
-	clearPaulaAndScopes();
+	turnOffVoices();
 
 	// set various non-zero values
 	editor.vol1 = 100;
@@ -519,7 +523,7 @@
 	editor.sampleFromDisp = &editor.sampleFrom;
 	editor.chordLengthDisp = &editor.chordLength;
 	editor.metroChannelDisp = &editor.metroChannel;
-	editor.quantizeValueDisp = &ptConfig.quantizeValue;
+	editor.quantizeValueDisp = &config.quantizeValue;
 
 	editor.programRunning = true;
 	return true;
@@ -535,11 +539,11 @@
 	{
 		resetAllScreens();
 
-		if (!editor.fullscreen)
+		if (!video.fullscreen)
 		{
 			// de-minimize window and set focus so that the user sees the message box
-			SDL_RestoreWindow(window);
-			SDL_RaiseWindow(window);
+			SDL_RestoreWindow(video.window);
+			SDL_RaiseWindow(video.window);
 		}
 
 		editor.ui.askScreenShown = true;
@@ -725,7 +729,7 @@
 		sharedMemBuf = (LPTSTR)MapViewOfFile(oneInstHandle, FILE_MAP_ALL_ACCESS, 0, 0, sizeof (HWND));
 		if (sharedMemBuf != NULL)
 		{
-			CopyMemory((PVOID)sharedMemBuf, &editor.ui.hWnd, sizeof (HWND));
+			CopyMemory((PVOID)sharedMemBuf, &video.hWnd, sizeof (HWND));
 			UnmapViewOfFile(sharedMemBuf);
 			sharedMemBuf = NULL;
 		}
@@ -739,10 +743,10 @@
 	SDL_SysWMinfo wmInfo;
 
 	SDL_VERSION(&wmInfo.version);
-	if (!SDL_GetWindowWMInfo(window, &wmInfo))
+	if (!SDL_GetWindowWMInfo(video.window, &wmInfo))
 		return false;
 
-	editor.ui.hWnd = wmInfo.info.win.window;
+	video.hWnd = wmInfo.info.win.window;
 	if (instanceAlreadyOpen() && argc >= 2 && argv[1][0] != '\0')
 	{
 		sharedMemBuf = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, sizeof (HWND));
@@ -864,8 +868,8 @@
 	videoClose();
 	freeSprites();
 
-	if (ptConfig.defModulesDir != NULL) free(ptConfig.defModulesDir);
-	if (ptConfig.defSamplesDir != NULL) free(ptConfig.defSamplesDir);
+	if (config.defModulesDir != NULL) free(config.defModulesDir);
+	if (config.defSamplesDir != NULL) free(config.defSamplesDir);
 	if (editor.tempSample != NULL) free(editor.tempSample);
 
 #ifdef _WIN32
--- a/src/pt2_modloader.c
+++ b/src/pt2_modloader.c
@@ -39,8 +39,6 @@
 static uint32_t oldFullPathLen;
 static module_t *tempMod;
 
-extern SDL_Window *window;
-
 static MEMFILE *mopen(const uint8_t *src, uint32_t length);
 static void mclose(MEMFILE **buf);
 static int32_t mgetc(MEMFILE *buf);
@@ -656,6 +654,7 @@
 					{
 						// "DFJ SoundTracker II" or later
 
+						// TODO: This needs more detection and is NOT correct!
 						if (note->command == 0xD)
 						{
 							if (veryLateSTKVerFlag) // "DFJ SoundTracker III" or later
@@ -806,7 +805,7 @@
 
 	memset(fileName, 0, sizeof (fileName));
 
-	if (ptConfig.modDot)
+	if (config.modDot)
 	{
 		// extension.filename
 		if (*modEntry->head.moduleTitle == '\0')
@@ -848,7 +847,7 @@
 		for (uint16_t j = 1; j <= 9999; j++)
 		{
 			memset(fileName, 0, sizeof (fileName));
-			if (ptConfig.modDot)
+			if (config.modDot)
 			{
 				// extension.filename
 				if (*modEntry->head.moduleTitle == '\0')
@@ -1326,8 +1325,8 @@
 			oldAutoPlay = autoPlay;
 
 			// de-minimize window and set focus so that the user sees the message box
-			SDL_RestoreWindow(window);
-			SDL_RaiseWindow(window);
+			SDL_RestoreWindow(video.window);
+			SDL_RaiseWindow(video.window);
 
 			showSongUnsavedAskBox(ASK_DISCARD_SONG_DRAGNDROP);
 			return;
--- a/src/pt2_modplayer.c
+++ b/src/pt2_modplayer.c
@@ -24,8 +24,6 @@
 #include "pt2_textout.h"
 #include "pt2_scopes.h"
 
-extern bool forceMixerOff; // pt_audio.c
-
 static bool posJumpAssert, pBreakFlag, updateUIPositions, modHasBeenPlayed;
 static int8_t pBreakPosition, oldRow, modPattern;
 static uint8_t pattDelTime, setBPMFlag, lowMask = 0xFF, pattDelTime2, oldSpeed;
@@ -63,6 +61,8 @@
 	moduleChannel_t *c;
 	uint8_t i;
 
+	editor.songPlaying = false;
+
 	resetCachedMixerPeriod();
 
 	pattDelTime = 0;
@@ -69,7 +69,6 @@
 	pattDelTime2 = 0;
 	editor.playMode = PLAY_MODE_NORMAL;
 	editor.currMode = MODE_IDLE;
-	editor.songPlaying = false;
 
 	pointerSetMode(POINTER_MODE_IDLE, DO_CARRY);
 
@@ -919,7 +918,7 @@
 			modOrder = 0;
 			modHasBeenPlayed = true;
 
-			if (ptConfig.compoMode) // stop song for music competitions playing
+			if (config.compoMode) // stop song for music competitions playing
 			{
 				doStopIt();
 				turnOffVoices();
@@ -1249,6 +1248,10 @@
 {
 	uint8_t oldPlayMode, oldMode;
 
+	doStopIt();
+	turnOffVoices();
+	mixerClearSampleCounter();
+
 	if (row != -1)
 	{
 		if (row >= 0 && row <= 63)
@@ -1301,9 +1304,6 @@
 	oldPlayMode = editor.playMode;
 	oldMode = editor.currMode;
 
-	doStopIt();
-	turnOffVoices();
-
 	editor.playMode = oldPlayMode;
 	editor.currMode = oldMode;
 
@@ -1320,8 +1320,6 @@
 		editor.ui.updateSongPattern = true;
 		editor.ui.updateCurrPattText = true;
 	}
-
-	mixerClearSampleCounter();
 }
 
 void clearSong(void)
@@ -1438,8 +1436,12 @@
 	if (modEntry == NULL)
 		return; // not allocated
 
-	lockAudio();
+	const bool wasLocked = audio.locked;
+	if (!wasLocked)
+		lockAudio();
 
+	turnOffVoices();
+
 	for (i = 0; i < MAX_PATTERNS; i++)
 	{
 		if (modEntry->patterns[i] != NULL)
@@ -1447,15 +1449,13 @@
 	}
 
 	if (modEntry->sampleData != NULL)
-	{
-		clearPaulaAndScopes();
 		free(modEntry->sampleData);
-	}
 
 	free(modEntry);
 	modEntry = NULL;
 
-	unlockAudio();
+	if (!wasLocked)
+		unlockAudio();
 }
 
 void restartSong(void) // for the beginning of MOD2WAV/PAT2SMP
@@ -1465,7 +1465,7 @@
 
 	editor.playMode = PLAY_MODE_NORMAL;
 	editor.blockMarkFlag = false;
-	forceMixerOff = true;
+	audio.forceMixerOff = true;
 
 	modEntry->row = 0;
 	modEntry->currRow = 0;
@@ -1528,5 +1528,5 @@
 
 	editor.modTick = 0;
 	modHasBeenPlayed = false;
-	forceMixerOff = false;
+	audio.forceMixerOff = false;
 }
--- a/src/pt2_mouse.c
+++ b/src/pt2_mouse.c
@@ -25,13 +25,11 @@
 #include "pt2_keyboard.h"
 
 /* TODO: Move irrelevant routines outta here! Disgusting design!
- * Keep in mind that this was programmed in my early programming days... */
+** Keep in mind that this was programmed in my early programming days...
+**/
 
 SDL_Cursor *cursors[NUM_CURSORS];
 
-extern SDL_Renderer *renderer;
-extern SDL_Window *window;
-
 void edNote1UpButton(void);
 void edNote1DownButton(void);
 void edNote2UpButton(void);
@@ -80,11 +78,11 @@
 {
 	assert(cursorColorIndex <= 5);
 
-	palette[PAL_MOUSE_1] = cursorColors[cursorColorIndex][0];
-	palette[PAL_MOUSE_2] = cursorColors[cursorColorIndex][1];
-	palette[PAL_MOUSE_3] = cursorColors[cursorColorIndex][2];
+	video.palette[PAL_MOUSE_1] = cursorColors[cursorColorIndex][0];
+	video.palette[PAL_MOUSE_2] = cursorColors[cursorColorIndex][1];
+	video.palette[PAL_MOUSE_3] = cursorColors[cursorColorIndex][2];
 
-	if (ptConfig.hwMouse)
+	if (config.hwMouse)
 		setSystemCursor(cursors[cursorColorIndex]);
 }
 
@@ -155,14 +153,15 @@
 {
 	freeMouseCursors();
 
-	uint8_t scaling = editor.ui.yScale;
+	uint8_t scaleFactor = video.yScale;
+
 	for (uint32_t i = 0; i < NUM_CURSORS; i++)
 	{
-		SDL_Surface *surface = SDL_CreateRGBSurface(0, POINTER_W*scaling, POINTER_H*scaling, 32, 0, 0, 0, 0);
+		SDL_Surface *surface = SDL_CreateRGBSurface(0, POINTER_W*scaleFactor, POINTER_H*scaleFactor, 32, 0, 0, 0, 0);
 		if (surface == NULL)
 		{
 			freeMouseCursors();
-			ptConfig.hwMouse = false; // enable software mouse
+			config.hwMouse = false; // enable software mouse
 			return false;
 		}
 
@@ -171,9 +170,9 @@
 		uint32_t color3 = cursorColors[i][2];
 		uint32_t colorkey = 0x12345678;
 
-		color1   = SDL_MapRGB(surface->format, R24(color1),   G24(color1),   B24(color1));
-		color2   = SDL_MapRGB(surface->format, R24(color2),   G24(color2),   B24(color2));
-		color3   = SDL_MapRGB(surface->format, R24(color3),   G24(color3),   B24(color3));
+		color1 = SDL_MapRGB(surface->format, R24(color1), G24(color1), B24(color1));
+		color2 = SDL_MapRGB(surface->format, R24(color2), G24(color2), B24(color2));
+		color3 = SDL_MapRGB(surface->format, R24(color3), G24(color3), B24(color3));
 		colorkey = SDL_MapRGB(surface->format, R24(colorkey), G24(colorkey), B24(colorkey));
 
 		SDL_SetSurfaceBlendMode(surface, SDL_BLENDMODE_NONE);
@@ -190,8 +189,8 @@
 		// blit upscaled cursor to surface
 		for (uint32_t y = 0; y < POINTER_H; y++)
 		{
-			uint32_t *outX = &dstPixels32[(y * scaling) * surface->w];
-			for (uint32_t yScale = 0; yScale < scaling; yScale++)
+			uint32_t *outX = &dstPixels32[(y * scaleFactor) * surface->w];
+			for (uint32_t yScale = 0; yScale < scaleFactor; yScale++)
 			{
 				for (uint32_t x = 0; x < POINTER_W; x++)
 				{
@@ -204,11 +203,11 @@
 						else if (srcPix == PAL_MOUSE_2) pixel = color2;
 						else if (srcPix == PAL_MOUSE_3) pixel = color3;
 
-						for (uint32_t xScale = 0; xScale < scaling; xScale++)
+						for (uint32_t xScale = 0; xScale < scaleFactor; xScale++)
 							outX[xScale] = pixel;
 					}
 
-					outX += scaling;
+					outX += scaleFactor;
 				}
 			}
 		}
@@ -220,7 +219,7 @@
 		{
 			SDL_FreeSurface(surface);
 			freeMouseCursors();
-			ptConfig.hwMouse = false; // enable software mouse
+			config.hwMouse = false; // enable software mouse
 			return false;
 		}
 
@@ -233,95 +232,105 @@
 
 void updateMouseScaling(void)
 {
-	if (editor.ui.renderW > 0) editor.ui.dMouseXMul = (double)SCREEN_W / editor.ui.renderW;
-	if (editor.ui.renderH > 0) editor.ui.dMouseYMul = (double)SCREEN_H / editor.ui.renderH;
+	if (video.renderW > 0) video.dMouseXMul = (double)SCREEN_W / video.renderW;
+	if (video.renderH > 0) video.dMouseYMul = (double)SCREEN_H / video.renderH;
 }
 
 void readMouseXY(void)
 {
-	int32_t mx, my;
+	int32_t mx, my, windowX, windowY;
 
-	if (input.mouse.setPosFlag)
+	if (mouse.setPosFlag)
 	{
-		input.mouse.setPosFlag = false;
+		if (!video.windowHidden)
+			SDL_WarpMouseInWindow(video.window, mouse.setPosX, mouse.setPosY);
 
-		if (SDL_GetWindowFlags(window) & SDL_WINDOW_SHOWN)
-			SDL_WarpMouseInWindow(window, input.mouse.setPosX, input.mouse.setPosY);
-
+		mouse.setPosFlag = false;
 		return;
 	}
 
-	SDL_PumpEvents(); // gathers all pending input from devices into the event queue (less mouse lag)
-	SDL_GetMouseState(&mx, &my);
+	mouse.buttonState = SDL_GetGlobalMouseState(&mx, &my);
 
-	/* in centered fullscreen mode, trap the mouse inside the framed image
-	 * and subtract the coords to match the OS mouse position (fixes touch from touchscreens) */
-	if (editor.fullscreen && !ptConfig.fullScreenStretch)
+	if (video.fullscreen)
 	{
-		if (mx < editor.ui.renderX)
-		{
-			mx = editor.ui.renderX;
-			SDL_WarpMouseInWindow(window, mx, my);
-		}
-		else if (mx >= editor.ui.renderX+editor.ui.renderW)
-		{
-			mx = (editor.ui.renderX + editor.ui.renderW) - 1;
-			SDL_WarpMouseInWindow(window, mx, my);
-		}
+		/* If fullscreen without filtering mode, translate coords and warp mouse
+		** inside the render space.
+		** Fullscreen + filtering mode takes up 100% of the screen area used, so no
+		** need to translate coords in that mode.
+		*/
 
-		if (my < editor.ui.renderY)
+		if (!config.fullScreenStretch)
 		{
-			my = editor.ui.renderY;
-			SDL_WarpMouseInWindow(window, mx, my);
-		}
-		else if (my >= editor.ui.renderY+editor.ui.renderH)
-		{
-			my = (editor.ui.renderY + editor.ui.renderH) - 1;
-			SDL_WarpMouseInWindow(window, mx, my);
-		}
+			if (!config.hwMouse)
+			{
+				bool warpMouse = false;
 
-		mx -= editor.ui.renderX;
-		my -= editor.ui.renderY;
-	}
+				if (mx < video.renderX)
+				{
+					mx = video.renderX;
+					warpMouse = true;
+				}
+				else if (mx >= video.renderX+video.renderW)
+				{
+					mx = (video.renderX + video.renderW) - 1;
+					warpMouse = true;
+				}
 
-	if (mx < 0) mx = 0;
-	if (my < 0) my = 0;
+				if (my < video.renderY)
+				{
+					my = video.renderY;
+					warpMouse = true;
+				}
+				else if (my >= video.renderY+video.renderH)
+				{
+					my = (video.renderY + video.renderH) - 1;
+					warpMouse = true;
+				}
 
-	// multiply coords by video scaling factors (do not round)
-	mx = (int32_t)(mx * editor.ui.dMouseXMul);
-	my = (int32_t)(my * editor.ui.dMouseYMul);
+				if (warpMouse)
+					SDL_WarpMouseInWindow(video.window, mx, my);
+			}
 
-	if (mx >= SCREEN_W) mx = SCREEN_W - 1;
-	if (my >= SCREEN_H) my = SCREEN_H - 1;
+			// convert fullscreen coords to window (centered image) coords
+			mx -= video.renderX;
+			my -= video.renderY;
+		}
+	}
+	else
+	{
+		// convert desktop coords to window coords
 
-	input.mouse.x = (int16_t)mx;
-	input.mouse.y = (int16_t)my;
+		// (a call to this function is really fast in windowed mode)
+		SDL_GetWindowPosition(video.window, &windowX, &windowY);
 
-	if (ptConfig.hwMouse)
+		mx -= windowX;
+		my -= windowY;
+	}
+
+	// multiply coords by video upscaling factors (don't round)
+	mouse.x = (int32_t)(mx * video.dMouseXMul);
+	mouse.y = (int32_t)(my * video.dMouseYMul);
+
+	if (config.hwMouse)
 	{
-		// hardware mouse
+		// hardware mouse mode (OS)
 		hideSprite(SPRITE_MOUSE_POINTER);
 	}
 	else
 	{
-		// software mouse
-		setSpritePos(SPRITE_MOUSE_POINTER, input.mouse.x, input.mouse.y);
+		// software mouse mode (PT mouse)
+		setSpritePos(SPRITE_MOUSE_POINTER, mouse.x, mouse.y);
 	}
 }
 
 void mouseButtonUpHandler(uint8_t mouseButton)
 {
-#ifndef __APPLE__
-	if (!editor.fullscreen)
-		SDL_SetWindowGrab(window, SDL_FALSE);
-#endif
+	mouse.buttonWaitCounter = 0;
+	mouse.buttonWaiting = false;
 
-	input.mouse.buttonWaitCounter = 0;
-	input.mouse.buttonWaiting = false;
-
 	if (mouseButton == SDL_BUTTON_LEFT)
 	{
-		input.mouse.leftButtonPressed = false;
+		mouse.leftButtonPressed = false;
 		editor.ui.forceSampleDrag = false;
 		editor.ui.forceVolDrag = false;
 		editor.ui.leftLoopPinMoving = false;
@@ -328,7 +337,7 @@
 		editor.ui.rightLoopPinMoving = false;
 		editor.ui.sampleMarkingPos = -1;
 
-		switch (input.mouse.lastGUIButton)
+		switch (mouse.lastGUIButton)
 		{
 			case PTB_SLENGTHU:
 			case PTB_SLENGTHD:
@@ -358,13 +367,13 @@
 				break;
 		}
 
-		input.mouse.lastGUIButton = -1;
-		input.mouse.lastSmpFilterButton = -1;
+		mouse.lastGUIButton = -1;
+		mouse.lastSmpFilterButton = -1;
 	}
 
 	if (mouseButton == SDL_BUTTON_RIGHT)
 	{
-		input.mouse.rightButtonPressed = false;
+		mouse.rightButtonPressed = false;
 		editor.ui.forceSampleEdit = false;
 	}
 }
@@ -371,19 +380,14 @@
 
 void mouseButtonDownHandler(uint8_t mouseButton)
 {
-#ifndef __APPLE__
-	if (!editor.fullscreen)
-		SDL_SetWindowGrab(window, SDL_TRUE);
-#endif
-
 	if (mouseButton == SDL_BUTTON_LEFT)
 	{
-		input.mouse.leftButtonPressed = true;
-		input.mouse.buttonWaiting = true;
+		mouse.leftButtonPressed = true;
+		mouse.buttonWaiting = true;
 	}
 
 	if (mouseButton == SDL_BUTTON_RIGHT)
-		input.mouse.rightButtonPressed = true;
+		mouse.rightButtonPressed = true;
 
 	// when red mouse pointer (error), block further input for a while
 	if (editor.errorMsgActive && editor.errorMsgBlock)
@@ -397,10 +401,10 @@
 
 void handleGUIButtonRepeat(void)
 {
-	if (!input.mouse.leftButtonPressed)
+	if (!mouse.leftButtonPressed)
 	{
 		// left mouse button released, stop repeating buttons
-		input.mouse.repeatCounter = 0;
+		mouse.repeatCounter = 0;
 		return;
 	}
 
@@ -410,20 +414,20 @@
 		return;
 	}
 
-	if (input.mouse.lastGUIButton != checkGUIButtons()) // FIXME: This can potentially do a ton of iterations, bad design!
+	if (mouse.lastGUIButton != checkGUIButtons()) // FIXME: This can potentially do a ton of iterations, bad design!
 	{
 		// only repeat the button that was first clicked (e.g. if you hold and move mouse to another button)
-		input.mouse.repeatCounter = 0;
+		mouse.repeatCounter = 0;
 		return;
 	}
 
 	handleRepeatedGUIButtons();
-	input.mouse.repeatCounter++;
+	mouse.repeatCounter++;
 }
 
 void edNote1UpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note1 += 12;
 	else
 		editor.note1++;
@@ -437,7 +441,7 @@
 
 void edNote1DownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note1 -= 12;
 	else
 		editor.note1--;
@@ -451,7 +455,7 @@
 
 void edNote2UpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note2 += 12;
 	else
 		editor.note2++;
@@ -465,7 +469,7 @@
 
 void edNote2DownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note2 -= 12;
 	else
 		editor.note2--;
@@ -479,7 +483,7 @@
 
 void edNote3UpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note3 += 12;
 	else
 		editor.note3++;
@@ -493,7 +497,7 @@
 
 void edNote3DownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note3 -= 12;
 	else
 		editor.note3--;
@@ -507,7 +511,7 @@
 
 void edNote4UpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note4 += 12;
 	else
 		editor.note4++;
@@ -521,7 +525,7 @@
 
 void edNote4DownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.note4 -= 12;
 	else
 		editor.note4--;
@@ -535,7 +539,7 @@
 
 void edPosUpButton(bool fast)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 		{
@@ -578,7 +582,7 @@
 
 void edPosDownButton(bool fast)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 		{
@@ -618,7 +622,7 @@
 
 void edModUpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		editor.modulateSpeed += 10;
 	else
 		editor.modulateSpeed++;
@@ -631,7 +635,7 @@
 
 void edModDownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		editor.modulateSpeed -= 10;
 	}
@@ -648,7 +652,7 @@
 
 void edVolUpButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (editor.sampleVol <= 999-10)
 			editor.sampleVol += 10;
@@ -666,7 +670,7 @@
 
 void edVolDownButton(void)
 {
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (editor.sampleVol >= 10)
 			editor.sampleVol -= 10;
@@ -712,7 +716,7 @@
 	if (finetune != 7)
 		modEntry->samples[editor.currSample].fineTune = (finetune + 1) & 0xF;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		modEntry->samples[editor.currSample].fineTune = 0;
 
 	recalcChordLength();
@@ -725,7 +729,7 @@
 	if (finetune != 8)
 		modEntry->samples[editor.currSample].fineTune = (finetune - 1) & 0xF;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		modEntry->samples[editor.currSample].fineTune = 0;
 
 	recalcChordLength();
@@ -736,7 +740,7 @@
 {
 	int8_t val = modEntry->samples[editor.currSample].volume;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val += 16;
 	else
 		val++;
@@ -752,7 +756,7 @@
 {
 	int8_t val = modEntry->samples[editor.currSample].volume;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val -= 16;
 	else
 		val--;
@@ -772,7 +776,7 @@
 		return;
 
 	val = modEntry->samples[editor.currSample].length;
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val += 64;
@@ -812,7 +816,7 @@
 	}
 
 	val = modEntry->samples[editor.currSample].length;
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val -= 64;
@@ -855,7 +859,7 @@
 		return;
 	}
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val += 64;
@@ -898,7 +902,7 @@
 		return;
 	}
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val -= 64;
@@ -942,7 +946,7 @@
 		return;
 	}
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val += 64;
@@ -985,7 +989,7 @@
 		return;
 	}
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (fast)
 			val -= 64;
@@ -1023,7 +1027,7 @@
 		return;
 
 	val = modEntry->currBPM;
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val += 10;
 	else
 		val++;
@@ -1044,7 +1048,7 @@
 		return;
 
 	val = modEntry->currBPM;
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val -= 10;
 	else
 		val--;
@@ -1062,7 +1066,7 @@
 	int16_t val;
 
 	val = modEntry->head.orderCount;
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val += 10;
 	else
 		val++;
@@ -1084,7 +1088,7 @@
 {
 	int16_t val = modEntry->head.orderCount;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val -= 10;
 	else
 		val--;
@@ -1106,7 +1110,7 @@
 {
 	int16_t val = modEntry->head.order[modEntry->currOrder];
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val += 10;
 	else
 		val++;
@@ -1126,7 +1130,7 @@
 {
 	int16_t val = modEntry->head.order[modEntry->currOrder];
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val -= 10;
 	else
 		val--;
@@ -1146,7 +1150,7 @@
 {
 	int16_t val = modEntry->currOrder;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val += 10;
 	else
 		val++;
@@ -1161,7 +1165,7 @@
 {
 	int16_t val = modEntry->currOrder;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 		val -= 10;
 	else
 		val--;
@@ -1181,7 +1185,7 @@
 	double dSmp;
 	moduleSample_t *s;
 
-	if (input.mouse.rightButtonPressed)
+	if (mouse.rightButtonPressed)
 	{
 		if (editor.ui.editTextFlag)
 		{
@@ -1200,14 +1204,14 @@
 		return;
 
 	// check buttons
-	if (input.mouse.leftButtonPressed)
+	if (mouse.leftButtonPressed)
 	{
 		// restore sample ask dialog
 		if (editor.ui.askScreenShown && editor.ui.askScreenType == ASK_RESTORE_SAMPLE)
 		{
-			if (input.mouse.y >= 71 && input.mouse.y <= 81)
+			if (mouse.y >= 71 && mouse.y <= 81)
 			{
-				if (input.mouse.x >= 171 && input.mouse.x <= 196)
+				if (mouse.x >= 171 && mouse.x <= 196)
 				{
 					// YES button
 					editor.ui.askScreenShown = false;
@@ -1215,7 +1219,7 @@
 					editor.ui.answerYes = true;
 					handleAskYes();
 				}
-				else if (input.mouse.x >= 234 && input.mouse.x <= 252)
+				else if (mouse.x >= 234 && mouse.x <= 252)
 				{
 					// NO button
 					editor.ui.askScreenShown = false;
@@ -1231,7 +1235,7 @@
 		// MAIN SCREEN STOP
 		if (!editor.ui.diskOpScreenShown && !editor.ui.posEdScreenShown)
 		{
-			if (input.mouse.x >= 182 && input.mouse.x <= 243 && input.mouse.y >= 0 && input.mouse.y <= 10)
+			if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10)
 			{
 				modStop();
 				return;
@@ -1238,10 +1242,10 @@
 			}
 		}
 
-		if (input.mouse.x >= 32 && input.mouse.x <= 95)
+		if (mouse.x >= 32 && mouse.x <= 95)
 		{
 			// SAMPLER SCREEN PLAY WAVEFORM
-			if (input.mouse.y >= 211 && input.mouse.y <= 221)
+			if (mouse.y >= 211 && mouse.y <= 221)
 			{
 				samplerPlayWaveform();
 				return;
@@ -1248,7 +1252,7 @@
 			}
 
 			// SAMPLER SCREEN PLAY DISPLAY
-			else if (input.mouse.y >= 222 && input.mouse.y <= 232)
+			else if (mouse.y >= 222 && mouse.y <= 232)
 			{
 				samplerPlayDisplay();
 				return;
@@ -1255,7 +1259,7 @@
 			}
 
 			// SAMPLER SCREEN PLAY RANGE
-			else if (input.mouse.y >= 233 && input.mouse.y <= 243)
+			else if (mouse.y >= 233 && mouse.y <= 243)
 			{
 				samplerPlayRange();
 				return;
@@ -1263,7 +1267,7 @@
 		}
 
 		// SAMPLER SCREEN STOP
-		if (input.mouse.x >= 0 && input.mouse.x <= 31 && input.mouse.y >= 222 && input.mouse.y <= 243)
+		if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243)
 		{
 			for (i = 0; i < AMIGA_VOICES; i++)
 				mixerKillVoice(i);
@@ -1271,7 +1275,7 @@
 		}
 
 		// VOLUME button (toggle)
-		if (input.mouse.x >= 96 && input.mouse.x <= 135 && input.mouse.y >= 244 && input.mouse.y <= 254)
+		if (mouse.x >= 96 && mouse.x <= 135 && mouse.y >= 244 && mouse.y <= 254)
 		{
 			editor.ui.samplerVolBoxShown = false;
 			removeSamplerVolBox();
@@ -1279,16 +1283,16 @@
 		}
 
 		// DRAG BOXES
-		if (input.mouse.x >= 72 && input.mouse.x <= 173 && input.mouse.y >= 154 && input.mouse.y <= 175)
+		if (mouse.x >= 72 && mouse.x <= 173 && mouse.y >= 154 && mouse.y <= 175)
 		{
 			volBoxBarPressed(MOUSE_BUTTON_NOT_HELD);
 			return;
 		}
 
-		if (input.mouse.x >= 174 && input.mouse.x <= 207)
+		if (mouse.x >= 174 && mouse.x <= 207)
 		{
 			// FROM NUM
-			if (input.mouse.y >= 154 && input.mouse.y <= 164)
+			if (mouse.y >= 154 && mouse.y <= 164)
 			{
 				editor.ui.tmpDisp16 = editor.vol1;
 				editor.vol1Disp = &editor.ui.tmpDisp16;
@@ -1300,7 +1304,7 @@
 			}
 
 			// TO NUM
-			else if (input.mouse.y >= 165 && input.mouse.y <= 175)
+			else if (mouse.y >= 165 && mouse.y <= 175)
 			{
 				editor.ui.tmpDisp16 = editor.vol2;
 				editor.vol2Disp = &editor.ui.tmpDisp16;
@@ -1312,10 +1316,10 @@
 			}
 		}
 
-		if (input.mouse.y >= 176 && input.mouse.y <= 186)
+		if (mouse.y >= 176 && mouse.y <= 186)
 		{
 			// NORMALIZE
-			if (input.mouse.x >= 101 && input.mouse.x <= 143)
+			if (mouse.x >= 101 && mouse.x <= 143)
 			{
 				s = &modEntry->samples[editor.currSample];
 				if (s->length == 0)
@@ -1374,7 +1378,7 @@
 			}
 
 			// RAMP DOWN
-			else if (input.mouse.x >= 144 && input.mouse.x <= 153)
+			else if (mouse.x >= 144 && mouse.x <= 153)
 			{
 				editor.vol1 = 100;
 				editor.vol2 = 0;
@@ -1386,7 +1390,7 @@
 			}
 
 			// RAMP UP
-			else if (input.mouse.x >= 154 && input.mouse.x <= 163)
+			else if (mouse.x >= 154 && mouse.x <= 163)
 			{
 				editor.vol1 = 0;
 				editor.vol2 = 100;
@@ -1398,7 +1402,7 @@
 			}
 
 			// RAMP UNITY
-			else if (input.mouse.x >= 164 && input.mouse.x <= 173)
+			else if (mouse.x >= 164 && mouse.x <= 173)
 			{
 				editor.vol1 = 100;
 				editor.vol2 = 100;
@@ -1410,7 +1414,7 @@
 			}
 
 			// CANCEL
-			else if (input.mouse.x >= 174 && input.mouse.x <= 207)
+			else if (mouse.x >= 174 && mouse.x <= 207)
 			{
 				editor.ui.samplerVolBoxShown = false;
 				removeSamplerVolBox();
@@ -1418,7 +1422,7 @@
 			}
 
 			// RAMP
-			else if (input.mouse.x >= 72 && input.mouse.x <= 100)
+			else if (mouse.x >= 72 && mouse.x <= 100)
 			{
 				s = &modEntry->samples[editor.currSample];
 				if (s->length == 0)
@@ -1478,14 +1482,14 @@
 
 static void handleRepeatedSamplerFilterButtons(void)
 {
-	if (!input.mouse.leftButtonPressed || input.mouse.lastSmpFilterButton == -1)
+	if (!mouse.leftButtonPressed || mouse.lastSmpFilterButton == -1)
 		return;
 
-	switch (input.mouse.lastSmpFilterButton)
+	switch (mouse.lastSmpFilterButton)
 	{
 		case 0: // low-pass cutoff up
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.lpCutOff <= 0xFFFF-50)
 					editor.lpCutOff += 50;
@@ -1509,7 +1513,7 @@
 
 		case 1: // low-pass cutoff down
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.lpCutOff >= 50)
 					editor.lpCutOff -= 50;
@@ -1530,7 +1534,7 @@
 
 		case 2: // high-pass cutoff up
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.hpCutOff <= 0xFFFF-50)
 					editor.hpCutOff += 50;
@@ -1554,7 +1558,7 @@
 
 		case 3: // high-pass cutoff down
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.hpCutOff >= 50)
 					editor.hpCutOff -= 50;
@@ -1582,21 +1586,21 @@
 	uint8_t i;
 	moduleSample_t *s;
 
-	if (input.mouse.rightButtonPressed && editor.ui.editTextFlag)
+	if (mouse.rightButtonPressed && editor.ui.editTextFlag)
 	{
 		exitGetTextLine(EDIT_TEXT_NO_UPDATE);
 		return;
 	}
 
-	if (editor.ui.editTextFlag || input.mouse.lastSmpFilterButton > -1 || !input.mouse.leftButtonPressed)
+	if (editor.ui.editTextFlag || mouse.lastSmpFilterButton > -1 || !mouse.leftButtonPressed)
 		return;
 
 	// restore sample ask dialog
 	if (editor.ui.askScreenShown && editor.ui.askScreenType == ASK_RESTORE_SAMPLE)
 	{
-		if (input.mouse.y >= 71 && input.mouse.y <= 81)
+		if (mouse.y >= 71 && mouse.y <= 81)
 		{
-			if (input.mouse.x >= 171 && input.mouse.x <= 196)
+			if (mouse.x >= 171 && mouse.x <= 196)
 			{
 				// YES button
 				editor.ui.askScreenShown = false;
@@ -1604,7 +1608,7 @@
 				editor.ui.answerYes = true;
 				handleAskYes();
 			}
-			else if ((input.mouse.x >= 234) && (input.mouse.x <= 252))
+			else if ((mouse.x >= 234) && (mouse.x <= 252))
 			{
 				// NO button
 				editor.ui.askScreenShown = false;
@@ -1618,7 +1622,7 @@
 	}
 
 	// FILTERS button (toggle)
-	if (input.mouse.x >= 211 && input.mouse.x <= 245 && input.mouse.y >= 244 && input.mouse.y <= 254)
+	if (mouse.x >= 211 && mouse.x <= 245 && mouse.y >= 244 && mouse.y <= 254)
 	{
 		editor.ui.samplerFiltersBoxShown = false;
 		removeSamplerFiltersBox();
@@ -1628,7 +1632,7 @@
 	// MAIN SCREEN STOP
 	if (!editor.ui.diskOpScreenShown && !editor.ui.posEdScreenShown)
 	{
-		if (input.mouse.x >= 182 && input.mouse.x <= 243 && input.mouse.y >= 0 && input.mouse.y <= 10)
+		if (mouse.x >= 182 && mouse.x <= 243 && mouse.y >= 0 && mouse.y <= 10)
 		{
 			modStop();
 			return;
@@ -1635,10 +1639,10 @@
 		}
 	}
 
-	if (input.mouse.x >= 32 && input.mouse.x <= 95)
+	if (mouse.x >= 32 && mouse.x <= 95)
 	{
 		// SAMPLER SCREEN PLAY WAVEFORM
-		if (input.mouse.y >= 211 && input.mouse.y <= 221)
+		if (mouse.y >= 211 && mouse.y <= 221)
 		{
 			samplerPlayWaveform();
 			return;
@@ -1645,7 +1649,7 @@
 		}
 
 		// SAMPLER SCREEN PLAY DISPLAY
-		else if (input.mouse.y >= 222 && input.mouse.y <= 232)
+		else if (mouse.y >= 222 && mouse.y <= 232)
 		{
 			samplerPlayDisplay();
 			return;
@@ -1652,7 +1656,7 @@
 		}
 
 		// SAMPLER SCREEN PLAY RANGE
-		else if (input.mouse.y >= 233 && input.mouse.y <= 243)
+		else if (mouse.y >= 233 && mouse.y <= 243)
 		{
 			samplerPlayRange();
 			return;
@@ -1660,7 +1664,7 @@
 	}
 
 	// SAMPLER SCREEN STOP
-	if (input.mouse.x >= 0 && input.mouse.x <= 31 && input.mouse.y >= 222 && input.mouse.y <= 243)
+	if (mouse.x >= 0 && mouse.x <= 31 && mouse.y >= 222 && mouse.y <= 243)
 	{
 		for (i = 0; i < AMIGA_VOICES; i++)
 			mixerKillVoice(i);
@@ -1668,7 +1672,7 @@
 	}
 
 	// UNDO
-	if (input.mouse.x >= 65 && input.mouse.x <= 75 && input.mouse.y >= 154 && input.mouse.y <= 184)
+	if (mouse.x >= 65 && mouse.x <= 75 && mouse.y >= 154 && mouse.y <= 184)
 	{
 		s = &modEntry->samples[editor.currSample];
 		if (s->length == 0)
@@ -1686,10 +1690,10 @@
 		return;
 	}
 
-	if (input.mouse.y >= 154 && input.mouse.y <= 164)
+	if (mouse.y >= 154 && mouse.y <= 164)
 	{
 		// DO LOW-PASS FILTER
-		if (input.mouse.x >= 76 && input.mouse.x <= 165)
+		if (mouse.x >= 76 && mouse.x <= 165)
 		{
 			lowPassSample(editor.lpCutOff);
 			renderSamplerFiltersBox();
@@ -1697,9 +1701,9 @@
 		}
 
 		// LOW-PASS CUTOFF
-		else if (input.mouse.x >= 166 && input.mouse.x <= 217)
+		else if (mouse.x >= 166 && mouse.x <= 217)
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.lpCutOff = 0;
 				editor.ui.updateLPText = true;
@@ -1718,10 +1722,10 @@
 		}
 
 		// LOW-PASS CUTOFF UP
-		else if (input.mouse.x >= 218 && input.mouse.x <= 228)
+		else if (mouse.x >= 218 && mouse.x <= 228)
 		{
-			input.mouse.lastSmpFilterButton = 0;
-			if (input.mouse.rightButtonPressed)
+			mouse.lastSmpFilterButton = 0;
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.lpCutOff <= 0xFFFF-100)
 					editor.lpCutOff += 100;
@@ -1744,10 +1748,10 @@
 		}
 
 		// LOW-PASS CUTOFF DOWN
-		else if (input.mouse.x >= 229 && input.mouse.x <= 239)
+		else if (mouse.x >= 229 && mouse.x <= 239)
 		{
-			input.mouse.lastSmpFilterButton = 1;
-			if (input.mouse.rightButtonPressed)
+			mouse.lastSmpFilterButton = 1;
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.lpCutOff >= 100)
 					editor.lpCutOff -= 100;
@@ -1767,10 +1771,10 @@
 		}
 	}
 
-	if (input.mouse.y >= 164 && input.mouse.y <= 174)
+	if (mouse.y >= 164 && mouse.y <= 174)
 	{
 		// DO HIGH-PASS FILTER
-		if (input.mouse.x >= 76 && input.mouse.x <= 165)
+		if (mouse.x >= 76 && mouse.x <= 165)
 		{
 			highPassSample(editor.hpCutOff);
 			renderSamplerFiltersBox();
@@ -1778,9 +1782,9 @@
 		}
 
 		// HIGH-PASS CUTOFF
-		else if (input.mouse.x >= 166 && input.mouse.x <= 217)
+		else if (mouse.x >= 166 && mouse.x <= 217)
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.hpCutOff = 0;
 				editor.ui.updateHPText = true;
@@ -1799,10 +1803,10 @@
 		}
 
 		// HIGH-PASS CUTOFF UP
-		else if (input.mouse.x >= 218 && input.mouse.x <= 228)
+		else if (mouse.x >= 218 && mouse.x <= 228)
 		{
-			input.mouse.lastSmpFilterButton = 2;
-			if (input.mouse.rightButtonPressed)
+			mouse.lastSmpFilterButton = 2;
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.hpCutOff <= 0xFFFF-100)
 					editor.hpCutOff += 100;
@@ -1825,10 +1829,10 @@
 		}
 
 		// HIGH-PASS CUTOFF DOWN
-		else if (input.mouse.x >= 229 && input.mouse.x <= 239)
+		else if (mouse.x >= 229 && mouse.x <= 239)
 		{
-			input.mouse.lastSmpFilterButton = 3;
-			if (input.mouse.rightButtonPressed)
+			mouse.lastSmpFilterButton = 3;
+			if (mouse.rightButtonPressed)
 			{
 				if (editor.hpCutOff >= 100)
 					editor.hpCutOff -= 100;
@@ -1849,7 +1853,7 @@
 	}
 
 	// NORMALIZE SAMPLE FLAG
-	if (input.mouse.x >= 76 && input.mouse.x <= 239 && input.mouse.y >= 174 && input.mouse.y <= 186)
+	if (mouse.x >= 76 && mouse.x <= 239 && mouse.y >= 174 && mouse.y <= 186)
 	{
 		editor.normalizeFiltersFlag ^= 1;
 		editor.ui.updateNormFlag = true;
@@ -1857,7 +1861,7 @@
 	}
 
 	// EXIT
-	if (input.mouse.x >= 240 && input.mouse.x <= 250 && input.mouse.y >= 154 && input.mouse.y <= 186)
+	if (mouse.x >= 240 && mouse.x <= 250 && mouse.y >= 154 && mouse.y <= 186)
 	{
 		editor.ui.samplerFiltersBoxShown = false;
 		removeSamplerFiltersBox();
@@ -1866,7 +1870,7 @@
 
 static bool withinButtonRect(const guiButton_t *b)
 {
-	if (input.mouse.x >= b->x1 && input.mouse.x <= b->x2 && input.mouse.y >= b->y1 && input.mouse.y <= b->y2)
+	if (mouse.x >= b->x1 && mouse.x <= b->x2 && mouse.y >= b->y1 && mouse.y <= b->y2)
 		return true;
 
 	return false;
@@ -1900,7 +1904,7 @@
 	}
 
 	// QUIT (xy 0,0) works on all screens except for ask/clear screen
-	if (input.mouse.x == 0 && input.mouse.y == 0)
+	if (mouse.x == 0 && mouse.y == 0)
 		return PTB_QUIT;
 
 	// top screen buttons
@@ -1960,10 +1964,10 @@
 		}
 		else if (mouseButton == SDL_BUTTON_LEFT && !editor.mixFlag)
 		{
-			tmp16 = input.mouse.y - editor.ui.lineCurY;
+			tmp16 = mouse.y - editor.ui.lineCurY;
 			if (tmp16 <= 2 && tmp16 >= -9)
 			{
-				tmp16 = (uint16_t)((input.mouse.x - editor.ui.lineCurX) + 4) >> 3;
+				tmp16 = (uint16_t)((mouse.x - editor.ui.lineCurX) + 4) >> 3;
 				while (tmp16 != 0) // 0 = pos we want
 				{
 					if (tmp16 > 0)
@@ -2038,7 +2042,7 @@
 	if (editor.ui.editTextFlag || editor.ui.askScreenShown || editor.ui.clearScreenShown || editor.swapChannelFlag)
 		return;
 
-	if (input.mouse.y < 121)
+	if (mouse.y < 121)
 	{
 		// upper part of screen
 		if (editor.ui.diskOpScreenShown)
@@ -2069,7 +2073,7 @@
 	if (editor.ui.editTextFlag || editor.ui.askScreenShown || editor.ui.clearScreenShown || editor.swapChannelFlag)
 		return;
 
-	if (input.mouse.y < 121)
+	if (mouse.y < 121)
 	{
 		// upper part of screen
 		if (editor.ui.diskOpScreenShown)
@@ -2097,7 +2101,7 @@
 
 bool handleRightMouseButton(void)
 {
-	if (!input.mouse.rightButtonPressed)
+	if (!mouse.rightButtonPressed)
 		return false;
 
 	// exit sample swap mode with right mouse button (if present)
@@ -2136,16 +2140,16 @@
 	}
 
 	// toggle channel muting with right mouse button
-	if (editor.ui.visualizerMode == VISUAL_QUADRASCOPE && input.mouse.y >= 55 && input.mouse.y <= 87)
+	if (editor.ui.visualizerMode == VISUAL_QUADRASCOPE && mouse.y >= 55 && mouse.y <= 87)
 	{
 		if (!editor.ui.posEdScreenShown && !editor.ui.editOpScreenShown && !editor.ui.diskOpScreenShown &&
 			!editor.ui.aboutScreenShown && !editor.ui.samplerVolBoxShown &&
 			!editor.ui.samplerFiltersBoxShown && !editor.isWAVRendering)
 		{
-			     if (input.mouse.x > 127 && input.mouse.x <= 167) editor.muted[0] ^= 1;
-			else if (input.mouse.x > 175 && input.mouse.x <= 215) editor.muted[1] ^= 1;
-			else if (input.mouse.x > 223 && input.mouse.x <= 263) editor.muted[2] ^= 1;
-			else if (input.mouse.x > 271 && input.mouse.x <= 311) editor.muted[3] ^= 1;
+			     if (mouse.x > 127 && mouse.x <= 167) editor.muted[0] ^= 1;
+			else if (mouse.x > 175 && mouse.x <= 215) editor.muted[1] ^= 1;
+			else if (mouse.x > 223 && mouse.x <= 263) editor.muted[2] ^= 1;
+			else if (mouse.x > 271 && mouse.x <= 311) editor.muted[3] ^= 1;
 
 			renderMuteButtons();
 		}
@@ -2152,7 +2156,7 @@
 	}
 
 	// sample hand drawing
-	if (input.mouse.y >= 138 && input.mouse.y <= 201 && editor.ui.samplerScreenShown &&
+	if (mouse.y >= 138 && mouse.y <= 201 && editor.ui.samplerScreenShown &&
 		!editor.ui.samplerVolBoxShown && !editor.ui.samplerFiltersBoxShown)
 	{
 		samplerEditSample(false);
@@ -2185,9 +2189,9 @@
 	// "downsample before loading sample" ask dialog
 	if (editor.ui.askScreenShown && editor.ui.askScreenType == ASK_LOAD_DOWNSAMPLE)
 	{
-		if (input.mouse.y >= 83 && input.mouse.y <= 93)
+		if (mouse.y >= 83 && mouse.y <= 93)
 		{
-			if (input.mouse.x >= 179 && input.mouse.x <= 204)
+			if (mouse.x >= 179 && mouse.x <= 204)
 			{
 				// YES button
 				editor.ui.askScreenShown = false;
@@ -2196,7 +2200,7 @@
 				handleAskYes();
 				return true;
 			}
-			else if (input.mouse.x >= 242 && input.mouse.x <= 260)
+			else if (mouse.x >= 242 && mouse.x <= 260)
 			{
 				// NO button
 				editor.ui.askScreenShown = false;
@@ -2213,7 +2217,7 @@
 	// cancel note input gadgets with left/right mouse button
 	if (editor.ui.changingSmpResample || editor.ui.changingChordNote || editor.ui.changingDrumPadNote)
 	{
-		if (input.mouse.leftButtonPressed || input.mouse.rightButtonPressed)
+		if (mouse.leftButtonPressed || mouse.rightButtonPressed)
 		{
 			editor.ui.changingSmpResample = false;
 			editor.ui.changingChordNote = false;
@@ -2232,7 +2236,7 @@
 		return true;
 	}
 
-	if (!input.mouse.leftButtonPressed)
+	if (!mouse.leftButtonPressed)
 		return false;
 
 	// handle QUIT ask dialog while Disk Op. filling is ongoing
@@ -2240,9 +2244,9 @@
 	{
 		if (editor.ui.askScreenShown && editor.ui.askScreenType == ASK_QUIT)
 		{
-			if (input.mouse.y >= 71 && input.mouse.y <= 81)
+			if (mouse.y >= 71 && mouse.y <= 81)
 			{
-				if (input.mouse.x >= 171 && input.mouse.x <= 196)
+				if (mouse.x >= 171 && mouse.x <= 196)
 				{
 					// YES button
 					editor.ui.askScreenShown = false;
@@ -2250,7 +2254,7 @@
 					editor.ui.answerYes = true;
 					handleAskYes();
 				}
-				else if (input.mouse.x >= 234 && input.mouse.x <= 252)
+				else if (mouse.x >= 234 && mouse.x <= 252)
 				{
 					// NO button
 					editor.ui.askScreenShown = false;
@@ -2269,7 +2273,7 @@
 	{
 		if (editor.ui.askScreenShown && editor.ui.askScreenType == ASK_QUIT)
 		{
-			if (input.mouse.x >= 171 && input.mouse.x <= 196)
+			if (mouse.x >= 171 && mouse.x <= 196)
 			{
 				// YES button
 				editor.isWAVRendering = false;
@@ -2280,7 +2284,7 @@
 				editor.ui.answerYes = true;
 				handleAskYes();
 			}
-			else if (input.mouse.x >= 234 && input.mouse.x <= 252)
+			else if (mouse.x >= 234 && mouse.x <= 252)
 			{
 				// NO button
 				editor.ui.askScreenShown = false;
@@ -2292,7 +2296,7 @@
 				setStatusMessage("RENDERING MOD...", NO_CARRY);
 			}
 		}
-		else if (input.mouse.y >= 58 && input.mouse.y <= 68 && input.mouse.x >= 133 && input.mouse.x <= 186)
+		else if (mouse.y >= 58 && mouse.y <= 68 && mouse.x >= 133 && mouse.x <= 186)
 		{
 			// CANCEL button
 			editor.abortMod2Wav = true;
@@ -2310,12 +2314,12 @@
 
 void updateMouseCounters(void)
 {
-	if (input.mouse.buttonWaiting)
+	if (mouse.buttonWaiting)
 	{
-		if (++input.mouse.buttonWaitCounter > VBLANK_HZ/4) // quarter of a second
+		if (++mouse.buttonWaitCounter > VBLANK_HZ/4) // quarter of a second
 		{
-			input.mouse.buttonWaitCounter = 0;
-			input.mouse.buttonWaiting = false;
+			mouse.buttonWaitCounter = 0;
+			mouse.buttonWaiting = false;
 		}
 	}
 
@@ -2465,7 +2469,7 @@
 
 		case PTB_EO_QUANTIZE:
 		{
-			editor.ui.tmpDisp16 = ptConfig.quantizeValue;
+			editor.ui.tmpDisp16 = config.quantizeValue;
 			editor.quantizeValueDisp = &editor.ui.tmpDisp16;
 			editor.ui.numPtr16 = &editor.ui.tmpDisp16;
 			editor.ui.numLen = 2;
@@ -2573,7 +2577,7 @@
 
 		case PTB_EO_MIX:
 		{
-			if (!input.mouse.rightButtonPressed)
+			if (!mouse.rightButtonPressed)
 			{
 				editor.mixFlag = true;
 				editor.ui.showTextPtr = editor.mixText;
@@ -2729,7 +2733,7 @@
 
 		case PTB_EO_POS_NUM:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.samplePos = 0;
 				editor.ui.updatePosText = true;
@@ -2786,7 +2790,7 @@
 
 		case PTB_EO_MOD_NUM:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.modulateSpeed = 0;
 				editor.ui.updateModText = true;
@@ -3089,7 +3093,7 @@
 
 		case PTB_EO_VOL_NUM:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.sampleVol = 100;
 				editor.ui.updateVolText = true;
@@ -3212,7 +3216,7 @@
 
 		case PTB_EO_NOTE1:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.note1 = 36;
 			}
@@ -3231,7 +3235,7 @@
 
 		case PTB_EO_NOTE2:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.note2 = 36;
 			}
@@ -3250,7 +3254,7 @@
 
 		case PTB_EO_NOTE3:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.note3 = 36;
 			}
@@ -3269,7 +3273,7 @@
 
 		case PTB_EO_NOTE4:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.note4 = 36;
 			}
@@ -3440,7 +3444,7 @@
 		{
 			if (modEntry->samples[editor.currSample].loopLength == 2 && modEntry->samples[editor.currSample].loopStart == 0)
 			{
-				editor.chordLengthMin = input.mouse.rightButtonPressed ? true : false;
+				editor.chordLengthMin = mouse.rightButtonPressed ? true : false;
 				recalcChordLength();
 			}
 		}
@@ -3563,7 +3567,7 @@
 		{
 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
 			{
-				if (input.mouse.rightButtonPressed)
+				if (mouse.rightButtonPressed)
 				{
 					modEntry->currOrder = 0;
 					editor.currPatternDisp = &modEntry->head.order[modEntry->currOrder];
@@ -3588,7 +3592,7 @@
 		{
 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
 			{
-				if (input.mouse.rightButtonPressed)
+				if (mouse.rightButtonPressed)
 				{
 					modEntry->head.order[modEntry->currOrder] = 0;
 
@@ -3615,7 +3619,7 @@
 		{
 			if (editor.currMode == MODE_IDLE || editor.currMode == MODE_EDIT)
 			{
-				if (input.mouse.rightButtonPressed)
+				if (mouse.rightButtonPressed)
 				{
 					modEntry->head.orderCount = 1;
 
@@ -3674,7 +3678,7 @@
 
 		case PTB_SVOLUMES:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				modEntry->samples[editor.currSample].volume = 0;
 			}
@@ -3693,7 +3697,7 @@
 
 		case PTB_SLENGTHS:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				s = &modEntry->samples[editor.currSample];
 
@@ -3730,7 +3734,7 @@
 
 		case PTB_SREPEATS:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				s = &modEntry->samples[editor.currSample];
 
@@ -3770,7 +3774,7 @@
 
 		case PTB_SREPLENS:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				s = &modEntry->samples[editor.currSample];
 
@@ -3813,12 +3817,17 @@
 
 		case PTB_EDITOP:
 		{
-			if (editor.ui.editOpScreen == 3) // chord screen
-				editor.ui.editOpScreen = 0;
-			else if (editor.ui.editOpScreenShown)
-				editor.ui.editOpScreen = (editor.ui.editOpScreen + 1) % 3;
+			if (editor.ui.editOpScreenShown)
+			{
+				if (editor.ui.editOpScreen == 3)
+					editor.ui.editOpScreen = 0;
+				else
+					editor.ui.editOpScreen = (editor.ui.editOpScreen + 1) % 3;
+			}
 			else
+			{
 				editor.ui.editOpScreenShown = true;
+			}
 
 			renderEditOpScreen();
 		}
@@ -3927,7 +3936,7 @@
 
 		case PTB_SA_ZOOMBARAREA:
 		{
-			input.mouse.lastGUIButton = button;
+			mouse.lastGUIButton = button;
 			if (!editor.ui.forceSampleDrag)
 			{
 				samplerBarPressed(MOUSE_BUTTON_NOT_HELD);
@@ -4083,7 +4092,7 @@
 
 		case PTB_DO_DATAPATH:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				memset(editor.currPath, 0, PATH_MAX + 1);
 				editor.ui.updateDiskOpPathText = true;
@@ -4101,7 +4110,7 @@
 
 		case PTB_SONGNAME:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				memset(modEntry->head.moduleTitle, 0, sizeof (modEntry->head.moduleTitle));
 				editor.ui.updateSongName = true;
@@ -4122,7 +4131,7 @@
 
 		case PTB_SAMPLENAME:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				memset(modEntry->samples[editor.currSample].text, 0, sizeof (modEntry->samples[editor.currSample].text));
 				editor.ui.updateCurrSampleName = true;
@@ -4186,7 +4195,7 @@
 			{
 				editor.ui.aboutScreenShown = false;
 			}
-			else if (!input.mouse.rightButtonPressed)
+			else if (!mouse.rightButtonPressed)
 			{
 				editor.ui.visualizerMode = (editor.ui.visualizerMode + 1) % 2;
 				if (editor.ui.visualizerMode == VISUAL_SPECTRUM)
@@ -4212,7 +4221,7 @@
 
 		case PTB_CHAN1:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.muted[0] = false;
 				editor.muted[1] = true;
@@ -4230,7 +4239,7 @@
 
 		case PTB_CHAN2:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.muted[0] = true;
 				editor.muted[1] = false;
@@ -4248,7 +4257,7 @@
 
 		case PTB_CHAN3:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.muted[0] = true;
 				editor.muted[1] = true;
@@ -4266,7 +4275,7 @@
 
 		case PTB_CHAN4:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.muted[0] = true;
 				editor.muted[1] = true;
@@ -4285,7 +4294,7 @@
 		case PTB_SAMPLER: samplerScreen(); break;
 		case PTB_SA_EXIT: exitFromSam();   break;
 
-		case PTB_DO_FILEAREA: diskOpLoadFile((input.mouse.y - 34) / 6, true); break;
+		case PTB_DO_FILEAREA: diskOpLoadFile((mouse.y - 34) / 6, true); break;
 		case PTB_DO_PARENT:
 		{
 #ifdef _WIN32
@@ -4366,7 +4375,7 @@
 		{
 			editor.playMode = PLAY_MODE_NORMAL;
 
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 				modPlay(DONT_SET_PATTERN, modEntry->currOrder, modEntry->currRow);
 			else
 				modPlay(DONT_SET_PATTERN, modEntry->currOrder, DONT_SET_ROW);
@@ -4381,7 +4390,7 @@
 		{
 			editor.playMode = PLAY_MODE_PATTERN;
 
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 				modPlay(modEntry->currPattern, DONT_SET_ORDER, modEntry->currRow);
 			else
 				modPlay(modEntry->currPattern, DONT_SET_ORDER, DONT_SET_ROW);
@@ -4411,7 +4420,7 @@
 			{
 				editor.playMode = PLAY_MODE_PATTERN;
 
-				if (input.mouse.rightButtonPressed)
+				if (mouse.rightButtonPressed)
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, modEntry->currRow);
 				else
 					modPlay(modEntry->currPattern, DONT_SET_ORDER, DONT_SET_ROW);
@@ -4486,7 +4495,7 @@
 
 		case PTB_SAMPLEU:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.sampleZero = true;
 				editor.ui.updateCurrSampleNum = true;
@@ -4500,7 +4509,7 @@
 
 		case PTB_SAMPLED:
 		{
-			if (input.mouse.rightButtonPressed)
+			if (mouse.rightButtonPressed)
 			{
 				editor.sampleZero = true;
 				editor.ui.updateCurrSampleNum = true;
@@ -4658,7 +4667,7 @@
 		default: displayErrorMsg("NOT IMPLEMENTED"); return false; // button not mapped
 	}
 
-	input.mouse.lastGUIButton = button;
+	mouse.lastGUIButton = button;
 	return false;
 }
 
@@ -4665,13 +4674,13 @@
 static void handleRepeatedGUIButtons(void)
 {
 	// repeat button
-	switch (input.mouse.lastGUIButton)
+	switch (mouse.lastGUIButton)
 	{
 		case PTB_EO_NOTE1_UP:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote1UpButton();
 			}
 		}
@@ -4679,9 +4688,9 @@
 
 		case PTB_EO_NOTE1_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote1DownButton();
 			}
 		}
@@ -4689,9 +4698,9 @@
 
 		case PTB_EO_NOTE2_UP:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote2UpButton();
 			}
 		}
@@ -4699,9 +4708,9 @@
 
 		case PTB_EO_NOTE2_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote2DownButton();
 			}
 		}
@@ -4709,9 +4718,9 @@
 
 		case PTB_EO_NOTE3_UP:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote3UpButton();
 			}
 		}
@@ -4719,9 +4728,9 @@
 
 		case PTB_EO_NOTE3_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote3DownButton();
 			}
 		}
@@ -4729,9 +4738,9 @@
 
 		case PTB_EO_NOTE4_UP:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote4UpButton();
 			}
 		}
@@ -4739,9 +4748,9 @@
 
 		case PTB_EO_NOTE4_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edNote4DownButton();
 			}
 		}
@@ -4749,9 +4758,9 @@
 
 		case PTB_EO_VOL_UP:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edVolUpButton();
 			}
 		}
@@ -4759,9 +4768,9 @@
 
 		case PTB_EO_VOL_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edVolDownButton();
 			}
 		}
@@ -4769,9 +4778,9 @@
 
 		case PTB_EO_MOD_UP:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edModUpButton();
 			}
 		}
@@ -4779,9 +4788,9 @@
 
 		case PTB_EO_MOD_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edModDownButton();
 			}
 		}
@@ -4789,9 +4798,9 @@
 
 		case PTB_EO_POS_UP:
 		{
-			if (input.mouse.repeatCounter >= 1)
+			if (mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edPosUpButton(INCREMENT_FAST);
 			}
 		}
@@ -4799,9 +4808,9 @@
 
 		case PTB_EO_POS_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 1)
+			if (mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				edPosDownButton(INCREMENT_FAST);
 			}
 		}
@@ -4809,9 +4818,9 @@
 
 		case PTB_EO_FROM_UP:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (editor.sampleFrom < 0x1F)
 				{
 					editor.sampleFrom++;
@@ -4823,9 +4832,9 @@
 
 		case PTB_EO_FROM_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (editor.sampleFrom > 0x00)
 				{
 					editor.sampleFrom--;
@@ -4837,9 +4846,9 @@
 
 		case PTB_EO_TO_UP:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (editor.sampleTo < 0x1F)
 				{
 					editor.sampleTo++;
@@ -4851,9 +4860,9 @@
 
 		case PTB_EO_TO_DOWN:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (editor.sampleTo > 0x00)
 				{
 					editor.sampleTo--;
@@ -4865,10 +4874,10 @@
 
 		case PTB_SAMPLEU:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
-				if (!input.mouse.rightButtonPressed)
+				mouse.repeatCounter = 0;
+				if (!mouse.rightButtonPressed)
 					sampleUpButton();
 				else
 					editor.ui.updateCurrSampleNum = true;
@@ -4878,10 +4887,10 @@
 
 		case PTB_SAMPLED:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
-				if (!input.mouse.rightButtonPressed)
+				mouse.repeatCounter = 0;
+				if (!mouse.rightButtonPressed)
 					sampleDownButton();
 				else
 					editor.ui.updateCurrSampleNum = true;
@@ -4891,9 +4900,9 @@
 
 		case PTB_FTUNEU:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleFineTuneUpButton();
 			}
 		}
@@ -4901,9 +4910,9 @@
 
 		case PTB_FTUNED:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleFineTuneDownButton();
 			}
 		}
@@ -4911,9 +4920,9 @@
 
 		case PTB_SVOLUMEU:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleVolumeUpButton();
 			}
 		}
@@ -4921,9 +4930,9 @@
 
 		case PTB_SVOLUMED:
 		{
-			if (input.mouse.repeatCounter >= 5)
+			if (mouse.repeatCounter >= 5)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleVolumeDownButton();
 			}
 		}
@@ -4931,9 +4940,9 @@
 
 		case PTB_SLENGTHU:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleLengthUpButton(INCREMENT_FAST);
 			}
 		}
@@ -4941,9 +4950,9 @@
 
 		case PTB_SLENGTHD:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleLengthDownButton(INCREMENT_FAST);
 			}
 		}
@@ -4951,9 +4960,9 @@
 
 		case PTB_SREPEATU:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleRepeatUpButton(INCREMENT_FAST);
 			}
 		}
@@ -4961,9 +4970,9 @@
 
 		case PTB_SREPEATD:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleRepeatDownButton(INCREMENT_FAST);
 			}
 		}
@@ -4971,9 +4980,9 @@
 
 		case PTB_SREPLENU:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleRepeatLengthUpButton(INCREMENT_FAST);
 			}
 		}
@@ -4981,9 +4990,9 @@
 
 		case PTB_SREPLEND:
 		{
-			if (input.mouse.rightButtonPressed || input.mouse.repeatCounter >= 1)
+			if (mouse.rightButtonPressed || mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				sampleRepeatLengthDownButton(INCREMENT_FAST);
 			}
 		}
@@ -4991,9 +5000,9 @@
 
 		case PTB_TEMPOU:
 		{
-			if (input.mouse.repeatCounter >= 3)
+			if (mouse.repeatCounter >= 3)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				tempoUpButton();
 			}
 		}
@@ -5001,9 +5010,9 @@
 
 		case PTB_TEMPOD:
 		{
-			if (input.mouse.repeatCounter >= 3)
+			if (mouse.repeatCounter >= 3)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				tempoDownButton();
 			}
 		}
@@ -5011,9 +5020,9 @@
 
 		case PTB_LENGTHU:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				songLengthUpButton();
 			}
 		}
@@ -5021,9 +5030,9 @@
 
 		case PTB_LENGTHD:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				songLengthDownButton();
 			}
 		}
@@ -5031,9 +5040,9 @@
 
 		case PTB_PATTERNU:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				patternUpButton();
 			}
 		}
@@ -5041,9 +5050,9 @@
 
 		case PTB_PATTERND:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				patternDownButton();
 			}
 		}
@@ -5051,9 +5060,9 @@
 
 		case PTB_POSU:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				positionUpButton();
 			}
 		}
@@ -5061,9 +5070,9 @@
 
 		case PTB_POSD:
 		{
-			if (input.mouse.repeatCounter >= 7)
+			if (mouse.repeatCounter >= 7)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				positionDownButton();
 			}
 		}
@@ -5071,9 +5080,9 @@
 
 		case PTB_PE_SCROLLUP:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (modEntry->currOrder > 0)
 					modSetPos(modEntry->currOrder - 1, DONT_SET_ROW);
 			}
@@ -5082,9 +5091,9 @@
 
 		case PTB_PE_SCROLLDOWN:
 		{
-			if (input.mouse.repeatCounter >= 2)
+			if (mouse.repeatCounter >= 2)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (modEntry->currOrder < modEntry->head.orderCount-1)
 					modSetPos(modEntry->currOrder + 1, DONT_SET_ROW);
 			}
@@ -5093,12 +5102,12 @@
 
 		case PTB_DO_SCROLLUP:
 		{
-			if (input.mouse.repeatCounter >= 1)
+			if (mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 
 				editor.diskop.scrollOffset--;
-				if (input.mouse.rightButtonPressed)
+				if (mouse.rightButtonPressed)
 					editor.diskop.scrollOffset -= 3;
 
 				if (editor.diskop.scrollOffset < 0)
@@ -5111,14 +5120,14 @@
 
 		case PTB_DO_SCROLLDOWN:
 		{
-			if (input.mouse.repeatCounter >= 1)
+			if (mouse.repeatCounter >= 1)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 
 				if (editor.diskop.numEntries > DISKOP_LINES)
 				{
 					editor.diskop.scrollOffset++;
-					if (input.mouse.rightButtonPressed)
+					if (mouse.rightButtonPressed)
 						editor.diskop.scrollOffset += 3;
 
 					if (editor.diskop.scrollOffset > editor.diskop.numEntries-DISKOP_LINES)
@@ -5132,9 +5141,9 @@
 
 		case PTB_SA_ZOOMBARAREA:
 		{
-			if (input.mouse.repeatCounter >= 4)
+			if (mouse.repeatCounter >= 4)
 			{
-				input.mouse.repeatCounter = 0;
+				mouse.repeatCounter = 0;
 				if (!editor.ui.forceSampleDrag)
 					samplerBarPressed(MOUSE_BUTTON_NOT_HELD);
 			}
--- a/src/pt2_palette.c
+++ b/src/pt2_palette.c
@@ -1,28 +1,21 @@
-#include <stdint.h>
 #include "pt2_palette.h"
 #include "pt2_header.h"
-#include "pt2_helpers.h"
-#include "pt2_tables.h"
 
-uint32_t palette[PALETTE_NUM] =
+void setDefaultPalette(void)
 {
-	// -----------------------------
-	0x000000, // 00- PAL_BACKGRD
-	0xBBBBBB, // 01- PAL_BORDER
-	0x888888, // 02- PAL_GENBKG
-	0x555555, // 03- PAL_GENBKG2
-	0xFFDD00, // 04- PAL_QADSCP
-	0xDD0044, // 05- PAL_PATCURSOR
-	0x000000, // 06- PAL_GENTXT
-	0x3344FF, // 07- PAL_PATTXT
-	// -----------------------------
-	0x00FFFF, // 08- PAL_SAMPLLINE
-	0x0000FF, // 09- PAL_LOOPPIN
-	0x770077, // 10- PAL_TEXTMARK
-	0x444444, // 11- PAL_MOUSE_1
-	0x777777, // 12- PAL_MOUSE_2
-	0xAAAAAA, // 13- PAL_MOUSE_3
-	// -----------------------------
-	0xC0FFEE  // 14- PAL_COLORKEY
-	// -----------------------------
-};
+	video.palette[PAL_BACKGRD] = 0x000000;
+	video.palette[PAL_BORDER] = 0xBBBBBB;
+	video.palette[PAL_GENBKG] = 0x888888;
+	video.palette[PAL_GENBKG2] = 0x555555;
+	video.palette[PAL_QADSCP] = 0xFFDD00;
+	video.palette[PAL_PATCURSOR] = 0xDD0044;
+	video.palette[PAL_GENTXT] = 0x000000;
+	video.palette[PAL_PATTXT] = 0x3344FF;
+	video.palette[PAL_SAMPLLINE] = 0x00FFFF;
+	video.palette[PAL_LOOPPIN] = 0x0000FF;
+	video.palette[PAL_TEXTMARK] = 0x770077;
+	video.palette[PAL_MOUSE_1] = 0x444444;
+	video.palette[PAL_MOUSE_2] = 0x777777;
+	video.palette[PAL_MOUSE_3] = 0xAAAAAA;
+	video.palette[PAL_COLORKEY] = 0xC0FFEE;
+}
--- a/src/pt2_palette.h
+++ b/src/pt2_palette.h
@@ -1,8 +1,5 @@
 #pragma once
 
-#include <stdint.h>
-#include <stdbool.h>
-
 enum
 {
 	// -----------------------------
@@ -26,3 +23,5 @@
 	// -----------------------------
 	PALETTE_NUM
 };
+
+void setDefaultPalette(void);
--- a/src/pt2_patternviewer.c
+++ b/src/pt2_patternviewer.c
@@ -33,11 +33,11 @@
 	return 255; // illegal period
 }
 
-void drawPatternNormal(uint32_t *frameBuffer)
+static void drawPatternNormal(void)
 {
 	int8_t rowMiddlePos;
 	uint8_t j, h, tempNote, rowDispCheck;
-	uint16_t putXOffset, putYOffset, rowData;
+	uint16_t x, y, rowData;
 	const uint32_t *srcPtr;
 	uint32_t bufferOffset, *dstPtr;
 	note_t note;
@@ -50,93 +50,93 @@
 		if (rowDispCheck < MOD_ROWS)
 		{
 			rowData = rowDispCheck * 4;
-			putYOffset = 140 + (i * 7);
+			y = 140 + (i * 7);
 
 			if (i == 7) // are we on the play row (middle)?
 			{
-				putYOffset++; // align font to play row (middle)
+				y++; // align font to play row (middle)
 
 				// put current row number
-				printTwoDecimalsBigBg(frameBuffer, 8, putYOffset, rowMiddlePos + modEntry->currRow, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				printTwoDecimalsBigBg(8, y, rowMiddlePos + modEntry->currRow, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 				// pattern data
 				for (j = 0; j < AMIGA_VOICES; j++)
 				{
 					note = modEntry->patterns[modEntry->currPattern][rowData + j];
-					putXOffset = 26 + (j * 72);
+					x = 26 + (j * 72);
 
 					if (note.period == 0)
 					{
-						textOutBigBg(frameBuffer, putXOffset + 6, putYOffset, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						textOutBigBg(x + 6, y, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 					else
 					{
 						tempNote = periodToNote(note.period);
 						if (tempNote == 255)
-							textOutBigBg(frameBuffer, putXOffset + 6, putYOffset, "???", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+							textOutBigBg(x + 6, y, "???", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 						else
-							textOutBigBg(frameBuffer, putXOffset + 6, putYOffset, ptConfig.accidental ? noteNames2[tempNote] : noteNames1[tempNote], palette[PAL_GENTXT], palette[PAL_GENBKG]);
+							textOutBigBg(x + 6, y, config.accidental ? noteNames2[tempNote] : noteNames1[tempNote], video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 
-					if (ptConfig.blankZeroFlag)
+					if (config.blankZeroFlag)
 					{
 						if (note.sample & 0xF0)
-							printOneHexBigBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+							printOneHexBigBg(x + 30, y, note.sample >> 4, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 						else
-							printOneHexBigBg(frameBuffer, putXOffset + 30, putYOffset, ' ', palette[PAL_GENBKG], palette[PAL_GENBKG]);
+							printOneHexBigBg(x + 30, y, ' ', video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
 					}
 					else
 					{
-						printOneHexBigBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						printOneHexBigBg(x + 30, y, note.sample >> 4, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 
-					printOneHexBigBg(frameBuffer, putXOffset + 38, putYOffset, note.sample & 0x0F, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-					printOneHexBigBg(frameBuffer, putXOffset + 46, putYOffset, note.command, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-					printTwoHexBigBg(frameBuffer, putXOffset + 54, putYOffset, note.param, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+					printOneHexBigBg(x + 38, y, note.sample & 0x0F, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+					printOneHexBigBg(x + 46, y, note.command, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+					printTwoHexBigBg(x + 54, y, note.param, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 				}
 			}
 			else
 			{
 				if (i > 7)
-					putYOffset += 7; // beyond play row, jump some pixels out of the row (middle)
+					y += 7; // beyond play row, jump some pixels out of the row (middle)
 
 				// put current row number
-				printTwoDecimalsBg(frameBuffer, 8, putYOffset, rowMiddlePos + modEntry->currRow, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+				printTwoDecimalsBg(8, y, rowMiddlePos + modEntry->currRow, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 
 				// pattern data
 				for (j = 0; j < AMIGA_VOICES; j++)
 				{
 					note = modEntry->patterns[modEntry->currPattern][rowData + j];
-					putXOffset = 26 + (j * 72);
+					x = 26 + (j * 72);
 
 					if (note.period == 0)
 					{
-						textOutBg(frameBuffer, putXOffset + 6, putYOffset, "---", palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						textOutBg(x + 6, y, "---", video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 					else
 					{
 						tempNote = periodToNote(note.period);
 						if (tempNote == 255)
-							textOutBg(frameBuffer, putXOffset + 6, putYOffset, "???", palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+							textOutBg(x + 6, y, "???", video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 						else
-							textOutBg(frameBuffer, putXOffset + 6, putYOffset, ptConfig.accidental ? noteNames2[tempNote] : noteNames1[tempNote], palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+							textOutBg(x + 6, y, config.accidental ? noteNames2[tempNote] : noteNames1[tempNote], video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 
-					if (ptConfig.blankZeroFlag)
+					if (config.blankZeroFlag)
 					{
 						if (note.sample & 0xF0)
-							printOneHexBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+							printOneHexBg(x + 30, y, note.sample >> 4, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 						else
-							printOneHexBg(frameBuffer, putXOffset + 30, putYOffset, ' ', palette[PAL_BACKGRD], palette[PAL_BACKGRD]);
+							printOneHexBg(x + 30, y, ' ', video.palette[PAL_BACKGRD], video.palette[PAL_BACKGRD]);
 					}
 					else
 					{
-						printOneHexBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						printOneHexBg(x + 30, y, note.sample >> 4, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 
-					printOneHexBg(frameBuffer, putXOffset + 38, putYOffset, note.sample & 0x0F, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-					printOneHexBg(frameBuffer, putXOffset + 46, putYOffset, note.command, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-					printTwoHexBg(frameBuffer, putXOffset + 54, putYOffset, note.param, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+					printOneHexBg(x + 38, y, note.sample & 0x0F, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+					printOneHexBg(x + 46, y, note.command, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+					printTwoHexBg(x + 54, y, note.param, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 				}
 			}
 		}
@@ -147,7 +147,7 @@
 	if (modEntry->currRow <= 6)
 	{
 		srcPtr = &trackerFrameBMP[140 * SCREEN_W];
-		dstPtr = &frameBuffer[140 * SCREEN_W];
+		dstPtr = &video.frameBuffer[140 * SCREEN_W];
 		memcpy(dstPtr, srcPtr, (SCREEN_W * sizeof (int32_t)) * ((7 - modEntry->currRow) * 7));
 	}
 	else if (modEntry->currRow >= 57)
@@ -156,16 +156,16 @@
 		bufferOffset = (250 - h) * SCREEN_W;
 
 		srcPtr = &trackerFrameBMP[bufferOffset];
-		dstPtr = &frameBuffer[bufferOffset];
+		dstPtr = &video.frameBuffer[bufferOffset];
 		memcpy(dstPtr, srcPtr, (SCREEN_W * sizeof (int32_t)) * h);
 	}
 }
 
-void drawPatternDotted(uint32_t *frameBuffer)
+static void drawPatternDotted(void)
 {
 	int8_t rowMiddlePos;
 	uint8_t j, h, tempNote, rowDispCheck;
-	uint16_t putXOffset, putYOffset, rowData;
+	uint16_t x, y, rowData;
 	const uint32_t *srcPtr;
 	uint32_t bufferOffset, *dstPtr;
 	note_t note;
@@ -178,57 +178,57 @@
 		if (rowDispCheck < MOD_ROWS)
 		{
 			rowData = rowDispCheck * 4;
-			putYOffset = 140 + (i * 7);
+			y = 140 + (i * 7);
 
 			if (i == 7) // are we on the play row (middle)?
 			{
-				putYOffset++; // align font to play row (middle)
+				y++; // align font to play row (middle)
 
 				// put current row number
-				printTwoDecimalsBigBg(frameBuffer, 8, putYOffset, rowMiddlePos + modEntry->currRow, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				printTwoDecimalsBigBg(8, y, rowMiddlePos + modEntry->currRow, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 				// pattern data
 				for (j = 0; j < AMIGA_VOICES; j++)
 				{
 					note = modEntry->patterns[modEntry->currPattern][rowData + j];
-					putXOffset = 26 + (j * 72);
+					x = 26 + (j * 72);
 
 					if (note.period == 0)
 					{
-						charOutBigBg(frameBuffer, putXOffset + 6, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						charOutBigBg(frameBuffer, putXOffset + 14, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						charOutBigBg(frameBuffer, putXOffset + 22, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						charOutBigBg(x + 6, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						charOutBigBg(x + 14, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						charOutBigBg(x + 22, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 					else
 					{
 						tempNote = periodToNote(note.period);
 						if (tempNote == 255)
-							textOutBigBg(frameBuffer, putXOffset + 6, putYOffset, "???", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+							textOutBigBg(x + 6, y, "???", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 						else
-							textOutBigBg(frameBuffer, putXOffset + 6, putYOffset, ptConfig.accidental ? noteNames2[tempNote] : noteNames1[tempNote], palette[PAL_GENTXT], palette[PAL_GENBKG]);
+							textOutBigBg(x + 6, y, config.accidental ? noteNames2[tempNote] : noteNames1[tempNote], video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 
 					if (note.sample)
 					{
-						printOneHexBigBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						printOneHexBigBg(frameBuffer, putXOffset + 38, putYOffset, note.sample & 0x0F, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						printOneHexBigBg(x + 30, y, note.sample >> 4, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						printOneHexBigBg(x + 38, y, note.sample & 0x0F, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 					else
 					{
-						charOutBigBg(frameBuffer, putXOffset + 30, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						charOutBigBg(frameBuffer, putXOffset + 38, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						charOutBigBg(x + 30, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						charOutBigBg(x + 38, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 
 					if ((note.command | note.param) == 0)
 					{
-						charOutBigBg(frameBuffer, putXOffset + 46, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						charOutBigBg(frameBuffer, putXOffset + 54, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						charOutBigBg(frameBuffer, putXOffset + 62, putYOffset, -128, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						charOutBigBg(x + 46, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						charOutBigBg(x + 54, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						charOutBigBg(x + 62, y, -128, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 					else
 					{
-						printOneHexBigBg(frameBuffer, putXOffset + 46, putYOffset, note.command, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-						printTwoHexBigBg(frameBuffer, putXOffset + 54, putYOffset, note.param, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+						printOneHexBigBg(x + 46, y, note.command, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+						printTwoHexBigBg(x + 54, y, note.param, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 					}
 				}
 			}
@@ -235,53 +235,53 @@
 			else
 			{
 				if (i > 7)
-					putYOffset += 7; // beyond play row, jump some pixels out of the row (middle)
+					y += 7; // beyond play row, jump some pixels out of the row (middle)
 
 				// put current row number
-				printTwoDecimalsBg(frameBuffer, 8, putYOffset, rowMiddlePos + modEntry->currRow, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+				printTwoDecimalsBg(8, y, rowMiddlePos + modEntry->currRow, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 
 				// pattern data
 				for (j = 0; j < AMIGA_VOICES; j++)
 				{
 					note = modEntry->patterns[modEntry->currPattern][rowData + j];
-					putXOffset = 26 + (j * 72);
+					x = 26 + (j * 72);
 
 					if (note.period == 0)
 					{
-						charOutBg(frameBuffer, putXOffset + 6, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						charOutBg(frameBuffer, putXOffset + 14, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						charOutBg(frameBuffer, putXOffset + 22, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						charOutBg(x + 6, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						charOutBg(x + 14, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						charOutBg(x + 22, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 					else
 					{
 						tempNote = periodToNote(note.period);
 						if (tempNote == 255)
-							textOutBg(frameBuffer, putXOffset + 6, putYOffset, "???", palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+							textOutBg(x + 6, y, "???", video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 						else
-							textOutBg(frameBuffer, putXOffset + 6, putYOffset, ptConfig.accidental ? noteNames2[tempNote] : noteNames1[tempNote], palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+							textOutBg(x + 6, y, config.accidental ? noteNames2[tempNote] : noteNames1[tempNote], video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 
 					if (note.sample)
 					{
-						printOneHexBg(frameBuffer, putXOffset + 30, putYOffset, note.sample >> 4, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						printOneHexBg(frameBuffer, putXOffset + 38, putYOffset, note.sample & 0x0F, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						printOneHexBg(x + 30, y, note.sample >> 4, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						printOneHexBg(x + 38, y, note.sample & 0x0F, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 					else
 					{
-						charOutBg(frameBuffer, putXOffset + 30, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						charOutBg(frameBuffer, putXOffset + 38, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						charOutBg(x + 30, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						charOutBg(x + 38, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 
 					if ((note.command | note.param) == 0)
 					{
-						charOutBg(frameBuffer, putXOffset + 46, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						charOutBg(frameBuffer, putXOffset + 54, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						charOutBg(frameBuffer, putXOffset + 62, putYOffset, -128, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						charOutBg(x + 46, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						charOutBg(x + 54, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						charOutBg(x + 62, y, -128, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 					else
 					{
-						printOneHexBg(frameBuffer, putXOffset + 46, putYOffset, note.command, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
-						printTwoHexBg(frameBuffer, putXOffset + 54, putYOffset, note.param, palette[PAL_PATTXT], palette[PAL_BACKGRD]);
+						printOneHexBg(x + 46, y, note.command, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
+						printTwoHexBg(x + 54, y, note.param, video.palette[PAL_PATTXT], video.palette[PAL_BACKGRD]);
 					}
 				}
 			}
@@ -293,7 +293,7 @@
 	if (modEntry->currRow <= 6)
 	{
 		srcPtr = &trackerFrameBMP[140 * SCREEN_W];
-		dstPtr = &frameBuffer[140 * SCREEN_W];
+		dstPtr = &video.frameBuffer[140 * SCREEN_W];
 		memcpy(dstPtr, srcPtr, (SCREEN_W * sizeof (int32_t)) * ((7 - modEntry->currRow) * 7));
 	}
 	else if (modEntry->currRow >= 57)
@@ -302,15 +302,15 @@
 		bufferOffset = (250 - h) * SCREEN_W;
 
 		srcPtr = &trackerFrameBMP[bufferOffset];
-		dstPtr = &frameBuffer[bufferOffset];
+		dstPtr = &video.frameBuffer[bufferOffset];
 		memcpy(dstPtr, srcPtr, (SCREEN_W * sizeof (int32_t)) * h);
 	}
 }
 
-void redrawPattern(uint32_t *frameBuffer)
+void redrawPattern(void)
 {
-	if (ptConfig.pattDots)
-		drawPatternDotted(frameBuffer);
+	if (config.pattDots)
+		drawPatternDotted();
 	else
-		drawPatternNormal(frameBuffer);
+		drawPatternNormal();
 }
--- a/src/pt2_patternviewer.h
+++ b/src/pt2_patternviewer.h
@@ -1,5 +1,3 @@
 #pragma once
 
-#include <stdint.h>
-
-void redrawPattern(uint32_t *frameBuffer);
+void redrawPattern(void);
--- a/src/pt2_sampleloader.c
+++ b/src/pt2_sampleloader.c
@@ -289,7 +289,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample8BitUnsigned(audioDataU8, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -348,7 +348,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample16Bit(audioDataS16, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -410,7 +410,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample32Bit(audioDataS32, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -473,7 +473,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample32Bit(audioDataS32, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -536,7 +536,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSampleFloat(fAudioDataFloat, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -605,7 +605,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSampleDouble(dAudioDataDouble, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -1295,7 +1295,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample8Bit(audioDataS8, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -1358,7 +1358,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample16Bit(audioDataS16, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -1428,7 +1428,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample32Bit(audioDataS32, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
@@ -1495,7 +1495,7 @@
 		// 2x downsampling - remove every other sample (if needed)
 		if (forceDownSampling)
 		{
-			if (ptConfig.sampleLowpass)
+			if (config.sampleLowpass)
 				lowPassSample32Bit(audioDataS32, sampleLength, sampleRate, sampleRate / DOWNSAMPLE_CUTOFF_FACTOR);
 
 			sampleLength /= 2;
--- a/src/pt2_sampler.c
+++ b/src/pt2_sampler.c
@@ -32,7 +32,7 @@
 	uint32_t posFrac, delta;
 } sampleMixer_t;
 
-static int32_t samOffsetScaled;
+static int32_t samOffsetScaled, lastDrawX, lastDrawY;
 static uint32_t waveInvertTable[8];
 
 static const int8_t tuneToneData[32] = // Tuning Tone (Sine Wave)
@@ -43,8 +43,6 @@
 	-127,-126,-118,-106, -91, -71, -49, -25
 };
 
-extern uint32_t *pixelBuffer; // pt_main.c
-
 void setLoopSprites(void);
 
 void createSampleMarkTable(void)
@@ -51,8 +49,8 @@
 {
 	// used for invertRange()  (sample data marking)
 
-	waveInvertTable[0] = 0x00000000 | palette[PAL_BACKGRD];
-	waveInvertTable[1] = 0x01000000 | palette[PAL_QADSCP];
+	waveInvertTable[0] = 0x00000000 | video.palette[PAL_BACKGRD];
+	waveInvertTable[1] = 0x01000000 | video.palette[PAL_QADSCP];
 	waveInvertTable[2] = 0x02000000 | CENTER_LINE_COLOR;
 	waveInvertTable[3] = 0x03000000; // spacer, not used
 	waveInvertTable[4] = 0x04000000 | MARK_COLOR_1;
@@ -106,10 +104,10 @@
 	}
 }
 
-static void sampleLine(uint32_t *frameBuffer, int16_t line_x1, int16_t line_x2, int16_t line_y1, int16_t line_y2)
+static void sampleLine(int16_t line_x1, int16_t line_x2, int16_t line_y1, int16_t line_y2)
 {
 	int16_t d, x, y, ax, ay, sx, sy, dx, dy;
-	uint32_t color = 0x01000000 | palette[PAL_QADSCP];
+	uint32_t color = 0x01000000 | video.palette[PAL_QADSCP];
 
 	assert(line_x1 >= 0 || line_x2 >= 0 || line_x1 < SCREEN_W || line_x2 < SCREEN_W);
 	assert(line_y1 >= 0 || line_y2 >= 0 || line_y1 < SCREEN_H || line_y2 < SCREEN_H);
@@ -130,7 +128,7 @@
 		{
 			assert(y >= 0 || x >= 0 || y < SCREEN_H || x < SCREEN_W);
 
-			frameBuffer[(y * SCREEN_W) + x] = color;
+			video.frameBuffer[(y * SCREEN_W) + x] = color;
 
 			if (x == line_x2)
 				break;
@@ -152,7 +150,7 @@
 		{
 			assert(y >= 0 || x >= 0 || y < SCREEN_H || x < SCREEN_W);
 
-			frameBuffer[(y * SCREEN_W) + x] = color;
+			video.frameBuffer[(y * SCREEN_W) + x] = color;
 
 			if (y == line_y2)
 				break;
@@ -192,9 +190,9 @@
 
 		// draw drag bar
 
-		dstPtr = &pixelBuffer[206 * SCREEN_W];
-		pixel = palette[PAL_QADSCP];
-		bgPixel = palette[PAL_BACKGRD];
+		dstPtr = &video.frameBuffer[206 * SCREEN_W];
+		pixel = video.palette[PAL_QADSCP];
+		bgPixel = video.palette[PAL_BACKGRD];
 
 		for (int32_t y = 0; y < 4; y++)
 		{
@@ -213,8 +211,8 @@
 	{
 		// clear drag bar background
 
-		dstPtr = &pixelBuffer[(206 * SCREEN_W) + 4];
-		pixel = palette[PAL_BACKGRD];
+		dstPtr = &video.frameBuffer[(206 * SCREEN_W) + 4];
+		pixel = video.palette[PAL_BACKGRD];
 
 		for (int32_t y = 0; y < 4; y++)
 		{
@@ -264,6 +262,9 @@
 	x += samOffsetScaled;
 	x = (uint32_t)(x * editor.sampler.samDisplay) / SAMPLE_AREA_WIDTH; // truncate here
 
+	if (x > editor.sampler.samLength)
+		x = editor.sampler.samLength;
+
 	return x;
 }
 
@@ -297,8 +298,8 @@
 
 	// clear sample data background
 
-	dstPtr = &pixelBuffer[(138 * SCREEN_W) + 3];
-	pixel = palette[PAL_BACKGRD];
+	dstPtr = &video.frameBuffer[(138 * SCREEN_W) + 3];
+	pixel = video.palette[PAL_BACKGRD];
 
 	for (y = 0; y < SAMPLE_VIEW_HEIGHT; y++)
 	{
@@ -309,9 +310,9 @@
 	}
 
 	// display center line
-	if (ptConfig.dottedCenterFlag)
+	if (config.dottedCenterFlag)
 	{
-		dstPtr = &pixelBuffer[(SAMPLE_AREA_Y_CENTER * SCREEN_W) + 3];
+		dstPtr = &video.frameBuffer[(SAMPLE_AREA_Y_CENTER * SCREEN_W) + 3];
 		for (x = 0; x < SAMPLE_AREA_WIDTH; x++)
 			dstPtr[x] = 0x02000000 | CENTER_LINE_COLOR;
 	}
@@ -327,7 +328,7 @@
 			for (x = 1; x < SAMPLE_AREA_WIDTH; x++)
 			{
 				y2 = SAMPLE_AREA_Y_CENTER - getScaledSample(scr2SmpPos(x));
-				sampleLine(pixelBuffer, x + 2, x + 3, y1, y2);
+				sampleLine(x + 2, x + 3, y1, y2);
 				y1 = y2;
 			}
 		}
@@ -355,11 +356,11 @@
 
 				if (x > 0)
 				{
-					if (min > oldMax) sampleLine(pixelBuffer, x + 2, x + 3, oldMax, min);
-					if (max < oldMin) sampleLine(pixelBuffer, x + 2, x + 3, oldMin, max);
+					if (min > oldMax) sampleLine(x + 2, x + 3, oldMax, min);
+					if (max < oldMin) sampleLine(x + 2, x + 3, oldMin, max);
 				}
 
-				sampleLine(pixelBuffer, x + 3, x + 3, max, min);
+				sampleLine(x + 3, x + 3, max, min);
 
 				oldMin = min;
 				oldMax = max;
@@ -369,9 +370,9 @@
 
 	// render "sample display" text
 	if (editor.sampler.samStart == editor.sampler.blankSample)
-		printFiveDecimalsBg(pixelBuffer, 272, 214, 0, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printFiveDecimalsBg(272, 214, 0, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	else
-		printFiveDecimalsBg(pixelBuffer, 272, 214, editor.sampler.samDisplay, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printFiveDecimalsBg(272, 214, editor.sampler.samDisplay, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 	setDragBar();
 	setLoopSprites();
@@ -398,7 +399,7 @@
 	if (rangeLen < 1)
 		rangeLen = 1;
 
-	dstPtr = &pixelBuffer[(138 * SCREEN_W) + (start + 3)];
+	dstPtr = &video.frameBuffer[(138 * SCREEN_W) + (start + 3)];
 	for (y = 0; y < 64; y++)
 	{
 		for (x = 0; x < rangeLen; x++)
@@ -1435,7 +1436,7 @@
 	else
 	{
 		invertRange();
-		if (input.keyb.shiftPressed && editor.markStartOfs != -1)
+		if (keyb.shiftPressed && editor.markStartOfs != -1)
 		{
 			editor.markStartOfs = editor.sampler.samOffset;
 		}
@@ -1471,7 +1472,7 @@
 		middlePos = editor.sampler.samOffset + ((editor.sampler.samDisplay + 1) / 2);
 
 		invertRange();
-		if (input.keyb.shiftPressed && editor.markStartOfs != -1)
+		if (keyb.shiftPressed && editor.markStartOfs != -1)
 		{
 			if (editor.markStartOfs < middlePos)
 				editor.markEndOfs = middlePos;
@@ -1507,7 +1508,7 @@
 	else
 	{
 		invertRange();
-		if (input.keyb.shiftPressed && editor.markStartOfs != -1)
+		if (keyb.shiftPressed && editor.markStartOfs != -1)
 		{
 			editor.markEndOfs = s->length;
 		}
@@ -1995,7 +1996,7 @@
 		hideSprite(SPRITE_LOOP_PIN_RIGHT);
 	}
 
-	textOutBg(pixelBuffer, 288, 225, (s->loopStart+s->loopLength > 2) ? "ON " : "OFF", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+	textOutBg(288, 225, (s->loopStart+s->loopLength > 2) ? "ON " : "OFF", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 }
 
 void samplerShowAll(void)
@@ -2081,12 +2082,12 @@
 
 void samplerZoomInMouseWheel(void)
 {
-	samplerZoomIn((editor.sampler.samDisplay + 5) / 10, input.mouse.x);
+	samplerZoomIn((editor.sampler.samDisplay + 5) / 10, mouse.x);
 }
 
 void samplerZoomOutMouseWheel(void)
 {
-	samplerZoomOut((editor.sampler.samDisplay + 5) / 10, input.mouse.x);
+	samplerZoomOut((editor.sampler.samDisplay + 5) / 10, mouse.x);
 }
 
 void samplerZoomOut2x(void)
@@ -2158,22 +2159,19 @@
 {
 	int32_t mouseX;
 
-	if (input.mouse.y < 0 || input.mouse.x < 0 || input.mouse.y >= SCREEN_H || input.mouse.x >= SCREEN_W)
-		return;
-
 	if (!mouseButtonHeld)
 	{
-		if (input.mouse.x >= 72 && input.mouse.x <= 173)
+		if (mouse.x >= 72 && mouse.x <= 173)
 		{
-			if (input.mouse.y >= 154 && input.mouse.y <= 174) editor.ui.forceVolDrag = 1;
-			if (input.mouse.y >= 165 && input.mouse.y <= 175) editor.ui.forceVolDrag = 2;
+			if (mouse.y >= 154 && mouse.y <= 174) editor.ui.forceVolDrag = 1;
+			if (mouse.y >= 165 && mouse.y <= 175) editor.ui.forceVolDrag = 2;
 		}
 	}
 	else
 	{
-		if (editor.sampler.lastMouseX != input.mouse.x)
+		if (editor.sampler.lastMouseX != mouse.x)
 		{
-			editor.sampler.lastMouseX = input.mouse.x;
+			editor.sampler.lastMouseX = mouse.x;
 			mouseX = CLAMP(editor.sampler.lastMouseX - 107, 0, 60);
 
 			if (editor.ui.forceVolDrag == 1)
@@ -2196,14 +2194,11 @@
 {
 	int32_t tmp32;
 
-	if (input.mouse.y < 0 || input.mouse.x < 0 || input.mouse.y >= SCREEN_H || input.mouse.x >= SCREEN_W)
-		return;
-
 	if (!mouseButtonHeld)
 	{
-		if (input.mouse.x >= 4 && input.mouse.x <= 315)
+		if (mouse.x >= 4 && mouse.x <= 315)
 		{
-			if (input.mouse.x < editor.sampler.dragStart)
+			if (mouse.x < editor.sampler.dragStart)
 			{
 				tmp32 = editor.sampler.samOffset - editor.sampler.samDisplay;
 				if (tmp32 < 0)
@@ -2219,7 +2214,7 @@
 				return;
 			}
 
-			if (input.mouse.x > editor.sampler.dragEnd)
+			if (mouse.x > editor.sampler.dragEnd)
 			{
 				tmp32 = editor.sampler.samOffset + editor.sampler.samDisplay;
 				if (tmp32+editor.sampler.samDisplay <= editor.sampler.samLength)
@@ -2243,7 +2238,7 @@
 				return;
 			}
 
-			editor.sampler.lastSamPos = (uint16_t)input.mouse.x;
+			editor.sampler.lastSamPos = mouse.x;
 			editor.sampler.saveMouseX = editor.sampler.lastSamPos - editor.sampler.dragStart;
 
 			editor.ui.forceSampleDrag = true;
@@ -2250,15 +2245,14 @@
 		}
 	}
 
-	if (input.mouse.x != editor.sampler.lastSamPos)
+	if (mouse.x != editor.sampler.lastSamPos)
 	{
-		editor.sampler.lastSamPos = (uint16_t)input.mouse.x;
+		editor.sampler.lastSamPos = mouse.x;
 
 		tmp32 = editor.sampler.lastSamPos - editor.sampler.saveMouseX - 4;
-		if (tmp32 < 0)
-			tmp32 = 0;
+		tmp32 = CLAMP(tmp32, 0, SAMPLE_AREA_WIDTH);
 
-		tmp32 = (int32_t)(((tmp32 * editor.sampler.samLength) + (311/2)) / 311); // rounded
+		tmp32 = ((tmp32 * editor.sampler.samLength) + (311/2)) / 311; // rounded
 		if (tmp32+editor.sampler.samDisplay <= editor.sampler.samLength)
 		{
 			if (tmp32 == editor.sampler.samOffset)
@@ -2280,134 +2274,137 @@
 	}
 }
 
-static int32_t x2LoopX(int32_t mouseX)
+static int32_t mouseYToSampleY(int32_t my)
 {
-	moduleSample_t *s = &modEntry->samples[editor.currSample];
+	int32_t tmp32;
 
-	mouseX -= 3;
-	if (mouseX < 0)
-		mouseX = 0;
+	if (my == SAMPLE_AREA_Y_CENTER) // center
+	{
+		return 128;
+	}
+	else
+	{
+		tmp32 = my - 138;
+		tmp32 = ((tmp32 << 8) + (SAMPLE_AREA_HEIGHT/2)) / SAMPLE_AREA_HEIGHT;
+		tmp32 = CLAMP(tmp32, 0, 255);
+		tmp32 ^= 0xFF;
+	}
 
-	mouseX = scr2SmpPos(mouseX);
-	mouseX = CLAMP(mouseX, 0, s->length);
-
-	return mouseX;
+	return tmp32;
 }
 
-static int32_t xToSmpX(int32_t x, int32_t smpLen)
-{
-	x = scr2SmpPos(x);
-	x = CLAMP(x, 0, smpLen - 1);
-
-	return x;
-}
-
-static int8_t yToSmpY(int32_t mouseY)
-{
-	mouseY = (SAMPLE_AREA_Y_CENTER - mouseY) * 4;
-	CLAMP8(mouseY);
-
-	return mouseY;
-}
-
 void samplerEditSample(bool mouseButtonHeld)
 {
-	int8_t y;
-	int32_t mouseY, x, smp_x0, smp_x1, xDistance, smp_y0, smp_y1, yDistance, smp;
+	int8_t *ptr8;
+	int32_t mx, my, tmp32, p, vl, tvl, r, rl, rvl, start, end;
 	moduleSample_t *s;
 
 	assert(editor.currSample >= 0 && editor.currSample <= 30);
+	s = &modEntry->samples[editor.currSample];
 
-	if (input.mouse.y < 0 || input.mouse.x < 0 || input.mouse.y >= SCREEN_H || input.mouse.x >= SCREEN_W)
+	if (s->length == 0)
+	{
+		displayErrorMsg("SAMPLE LENGTH = 0");
 		return;
+	}
 
-	s = &modEntry->samples[editor.currSample];
+	mx = mouse.x;
+	if (mx > 4+SAMPLE_AREA_WIDTH)
+		mx = 4+SAMPLE_AREA_WIDTH;
 
+	my = mouse.y;
+
 	if (!mouseButtonHeld)
 	{
-		if (input.mouse.x >= 3 && input.mouse.x <= 316 && input.mouse.y >= 138 && input.mouse.y <= 201)
-		{
-			if (s->length == 0)
-			{
-				displayErrorMsg("SAMPLE LENGTH = 0");
-			}
-			else
-			{
-				editor.sampler.lastMouseX = input.mouse.x;
-				editor.sampler.lastMouseY = input.mouse.y;
-				editor.ui.forceSampleEdit = true;
-				updateWindowTitle(MOD_IS_MODIFIED);
-			}
-		}
+		lastDrawX = scr2SmpPos(mx);
+		lastDrawY = mouseYToSampleY(my);
 
-		return;
+		editor.ui.forceSampleEdit = true;
+		updateWindowTitle(MOD_IS_MODIFIED);
 	}
+	else if (mx == editor.sampler.lastMouseX && my == editor.sampler.lastMouseY)
+	{
+		return; // don't continue if we didn't move the mouse
+	}
 
-	mouseY = input.keyb.shiftPressed ? editor.sampler.lastMouseY : input.mouse.y;
+	if (mx != editor.sampler.lastMouseX)
+		p = scr2SmpPos(mx);
+	else
+		p = lastDrawX;
 
-	x = xToSmpX(input.mouse.x - 3, s->length);
-	y = yToSmpY(mouseY);
+	if (!keyb.shiftPressed && my != editor.sampler.lastMouseY)
+		vl = mouseYToSampleY(my);
+	else
+		vl = lastDrawY;
 
-	modEntry->sampleData[s->offset+x] = y;
+	editor.sampler.lastMouseX = mx;
+	editor.sampler.lastMouseY = my;
 
-	// interpolate x gaps
-	if (input.mouse.x != editor.sampler.lastMouseX)
+	r = p;
+	rvl = vl;
+
+	// swap x/y if needed
+	if (p > lastDrawX)
 	{
-		smp_y0 = yToSmpY(editor.sampler.lastMouseY);
+		// swap x
+		tmp32 = p;
+		p = lastDrawX;
+		lastDrawX = tmp32;
 
-		smp_y1 = y;
-		yDistance = smp_y1 - smp_y0;
+		// swap y
+		tmp32 = lastDrawY;
+		lastDrawY = vl;
+		vl = tmp32;
+	}
 
-		if (input.mouse.x > editor.sampler.lastMouseX)
-		{
-			smp_x1 = x;
-			smp_x0 = xToSmpX(editor.sampler.lastMouseX - 3, s->length);
+	ptr8 = &modEntry->sampleData[s->offset];
 
-			xDistance = smp_x1 - smp_x0;
-			if (xDistance > 0)
-			{
-				for (x = smp_x0; x < smp_x1; x++)
-				{
-					assert(x < s->length);
+	start = p;
+	if (start < 0)
+		start = 0;
 
-					smp = smp_y0 + (((x - smp_x0) * yDistance) / xDistance);
-					CLAMP8(smp);
-					modEntry->sampleData[s->offset + x] = (int8_t)smp;
-				}
-			}
-		}
-		else if (input.mouse.x < editor.sampler.lastMouseX)
+	end = lastDrawX+1;
+	if (end > s->length)
+		end = s->length;
+
+	if (p == lastDrawX)
+	{
+		const int8_t smpVal = (int8_t)(vl ^ 0x80);
+		for (rl = start; rl < end; rl++)
+			ptr8[rl] = smpVal;
+	}
+	else
+	{
+		int32_t y = lastDrawY - vl;
+		int32_t x = lastDrawX - p;
+
+		if (x != 0)
 		{
-			smp_x0 = x;
-			smp_x1 = xToSmpX(editor.sampler.lastMouseX - 3, s->length);
+			double dMul = 1.0 / x;
+			int32_t i = 0;
 
-			xDistance = smp_x1 - smp_x0;
-			if (xDistance > 0)
+			for (rl = start; rl < end; rl++)
 			{
-				for (x = smp_x0; x < smp_x1; x++)
-				{
-					assert(x < s->length);
+				tvl = y * i;
+				tvl = (int32_t)(tvl * dMul); // tvl /= x
+				tvl += vl;
+				tvl ^= 0x80;
 
-					smp = smp_y0 + (((smp_x1 - x) * yDistance) / xDistance);
-					CLAMP8(smp);
-					modEntry->sampleData[s->offset + x] = (int8_t)smp;
-				}
+				ptr8[rl] = (int8_t)tvl;
+				i++;
 			}
 		}
-
-		editor.sampler.lastMouseX = input.mouse.x;
-
-		if (!input.keyb.shiftPressed)
-			editor.sampler.lastMouseY = input.mouse.y;
 	}
 
+	lastDrawY = rvl;
+	lastDrawX = r;
+
 	displaySample();
 }
 
 void samplerSamplePressed(bool mouseButtonHeld)
 {
-	int16_t mouseX;
-	int32_t tmpPos;
+	int32_t mouseX, tmpPos;
 	moduleSample_t *s;
 
 	assert(editor.currSample >= 0 && editor.currSample <= 30);
@@ -2414,28 +2411,29 @@
 
 	if (!mouseButtonHeld)
 	{
-		if (input.mouse.y < 142)
+		if (mouse.y < 142)
 		{
-			if (input.mouse.x >= editor.sampler.loopStartPos && input.mouse.x <= editor.sampler.loopStartPos+3)
+			if (mouse.x >= editor.sampler.loopStartPos && mouse.x <= editor.sampler.loopStartPos+3)
 			{
 				editor.ui.leftLoopPinMoving = true;
 				editor.ui.rightLoopPinMoving = false;
 				editor.ui.sampleMarkingPos = 1;
-				editor.sampler.lastMouseX = input.mouse.x;
+				editor.sampler.lastMouseX = mouse.x;
 				return;
 			}
-			else if (input.mouse.x >= editor.sampler.loopEndPos+3 && input.mouse.x <= editor.sampler.loopEndPos+6)
+			else if (mouse.x >= editor.sampler.loopEndPos+3 && mouse.x <= editor.sampler.loopEndPos+6)
 			{
 				editor.ui.rightLoopPinMoving = true;
 				editor.ui.leftLoopPinMoving = false;
 				editor.ui.sampleMarkingPos = 1;
-				editor.sampler.lastMouseX = input.mouse.x;
+				editor.sampler.lastMouseX = mouse.x;
 				return;
 			}
 		}
 	}
 
-	mouseX = (int16_t)input.mouse.x;
+	mouseX = CLAMP(mouse.x, 0, SCREEN_W+8); // allow some extra pixels outside of the screen
+
 	s = &modEntry->samples[editor.currSample];
 
 	if (editor.ui.leftLoopPinMoving)
@@ -2444,7 +2442,7 @@
 		{
 			editor.sampler.lastMouseX = mouseX;
 
-			tmpPos = (x2LoopX(mouseX + 2) - s->loopStart) & 0xFFFFFFFE;
+			tmpPos = (scr2SmpPos(mouseX - 1) - s->loopStart) & 0xFFFFFFFE;
 			if (tmpPos > MAX_SAMPLE_LEN)
 				tmpPos = MAX_SAMPLE_LEN;
 
@@ -2482,7 +2480,7 @@
 
 			s = &modEntry->samples[editor.currSample];
 
-			tmpPos = (x2LoopX(mouseX - 1) - s->loopStart) & 0xFFFFFFFE;
+			tmpPos = (scr2SmpPos(mouseX - 4) - s->loopStart) & 0xFFFFFFFE;
 			tmpPos = CLAMP(tmpPos, 2, MAX_SAMPLE_LEN);
 
 			s->loopLength = tmpPos;
@@ -2500,7 +2498,7 @@
 
 	if (!mouseButtonHeld)
 	{
-		if (mouseX < 3 || mouseX > 319)
+		if (mouseX < 3 || mouseX >= SCREEN_W)
 			return;
 
 		editor.ui.sampleMarkingPos = (int16_t)mouseX;
@@ -2540,7 +2538,7 @@
 		return;
 	}
 
-	mouseX = CLAMP(mouseX, 3, 319);
+	mouseX = CLAMP(mouseX, 3, SCREEN_W);
 
 	if (mouseX != editor.sampler.lastSamPos)
 	{
@@ -2643,7 +2641,7 @@
 void exitFromSam(void)
 {
 	editor.ui.samplerScreenShown = false;
-	memcpy(&pixelBuffer[121 * SCREEN_W], &trackerFrameBMP[121 * SCREEN_W], 320 * 134 * sizeof (int32_t));
+	memcpy(&video.frameBuffer[121 * SCREEN_W], &trackerFrameBMP[121 * SCREEN_W], 320 * 134 * sizeof (int32_t));
 
 	updateCursorPos();
 	setLoopSprites();
@@ -2667,7 +2665,7 @@
 	}
 
 	editor.ui.samplerScreenShown = true;
-	memcpy(&pixelBuffer[(121 * SCREEN_W)], samplerScreenBMP, 320 * 134 * sizeof (int32_t));
+	memcpy(&video.frameBuffer[(121 * SCREEN_W)], samplerScreenBMP, 320 * 134 * sizeof (int32_t));
 	hideSprite(SPRITE_PATTERN_CURSOR);
 
 	editor.ui.updateStatusText = true;
--- a/src/pt2_scopes.c
+++ b/src/pt2_scopes.c
@@ -24,12 +24,9 @@
 static uint64_t timeNext64, timeNext64Frac;
 static SDL_Thread *scopeThread;
 
-scopeChannel_t scope[4]; // global
-scopeChannelExt_t scopeExt[4]; // global
+scopeChannel_t scope[AMIGA_VOICES]; // global
+scopeChannelExt_t scopeExt[AMIGA_VOICES]; // global
 
-extern bool forceMixerOff; // pt_audio.c
-extern uint32_t *pixelBuffer; // pt_main.c
-
 int32_t getSampleReadPos(uint8_t ch, uint8_t smpNum)
 {
 	const int8_t *data;
@@ -47,9 +44,10 @@
 	{
 		s = &modEntry->samples[smpNum];
 
-		/* get real sampling position regardless of where the scope data points to
+		/* Get real sampling position regardless of where the scope data points to
 		** sc->data changes during loop, offset and so on, so this has to be done
-		** (sadly, because it's really hackish) */
+		** (sadly, because it's really hackish).
+		*/
 		pos = (int32_t)(&data[pos] - &modEntry->sampleData[s->offset]);
 		if (pos >= s->length)
 			return -1;
@@ -73,7 +71,7 @@
 	if (editor.isWAVRendering)
 		return;
 
-	for (uint32_t i = 0; i < AMIGA_VOICES; i++)
+	for (int32_t i = 0; i < AMIGA_VOICES; i++)
 	{
 		sc = &scope[i];
 		se = &scopeExt[i];
@@ -93,8 +91,9 @@
 		{
 			// sample reached end, simulate Paula register update (sample swapping)
 
-			/* wrap pos around one time with current length, then set new length
-			** and wrap around it (handles one-shot loops and sample swapping) */
+			/* Wrap pos around one time with current length, then set new length
+			** and wrap around it (handles one-shot loops and sample swapping).
+			*/
 			tmp.pos -= tmp.length;
 			tmp.length = tmpExt.newLength;
 
@@ -114,7 +113,8 @@
 
 /* This routine gets the average sample peak through the running scope voices.
 ** This gives a much more smooth and stable result than getting the peak from
-** the mixer, and we don't care about including filters/BLEP in the peak calculation. */
+** the mixer, and we don't care about including filters/BLEP in the peak calculation.
+*/
 static void updateRealVuMeters(void) 
 {
 	bool didSwapData;
@@ -195,7 +195,7 @@
 				}
 			}
 
-			smpPeak = ((smpPeak * 48) + (1 << 12)) >> 13;
+			smpPeak = ((smpPeak * 48) + (1 << 12)) >> 13; // rounded
 			if (smpPeak > editor.realVuMeterVolumes[i])
 				editor.realVuMeterVolumes[i] = smpPeak;
 		}
@@ -216,7 +216,7 @@
 	{
 		// --- QUADRASCOPE ---
 
-		scopePtr = &pixelBuffer[(71 * SCREEN_W) + 128];
+		scopePtr = &video.frameBuffer[(71 * SCREEN_W) + 128];
 		for (i = 0; i < AMIGA_VOICES; i++)
 		{
 			sc = &scope[i];
@@ -226,7 +226,7 @@
 			tmpScope = *sc;
 			didSwapData = se->didSwapData;
 
-			volume = -modEntry->channels[i].n_volume; // 0..64 -> -64..0
+			volume = -modEntry->channels[i].n_volume; // invert volume
 
 			// render scope
 			if (se->active && tmpScope.data != NULL && volume != 0 && tmpScope.length > 0)
@@ -237,8 +237,8 @@
 
 				// draw scope background
 
-				dstPtr = &pixelBuffer[(55 * SCREEN_W) + (128 + (i * (SCOPE_WIDTH + 8)))];
-				scopePixel = palette[PAL_BACKGRD]; // this palette can change
+				dstPtr = &video.frameBuffer[(55 * SCREEN_W) + (128 + (i * (SCOPE_WIDTH + 8)))];
+				scopePixel = video.palette[PAL_BACKGRD]; // this palette can change
 
 				for (y = 0; y < SCOPE_HEIGHT; y++)
 				{
@@ -250,7 +250,7 @@
 
 				// render scope data
 
-				scopePixel = palette[PAL_QADSCP];
+				scopePixel = video.palette[PAL_QADSCP];
 
 				readPos = tmpScope.pos;
 				if (tmpScope.loopFlag)
@@ -299,8 +299,8 @@
 				{
 					// draw scope background
 
-					dstPtr = &pixelBuffer[(55 * SCREEN_W) + (128 + (i * (SCOPE_WIDTH + 8)))];
-					scopePixel = palette[PAL_BACKGRD];
+					dstPtr = &video.frameBuffer[(55 * SCREEN_W) + (128 + (i * (SCOPE_WIDTH + 8)))];
+					scopePixel = video.palette[PAL_BACKGRD];
 
 					for (y = 0; y < SCOPE_HEIGHT; y++)
 					{
@@ -312,7 +312,7 @@
 
 					// draw line
 
-					scopePixel = palette[PAL_QADSCP];
+					scopePixel = video.palette[PAL_QADSCP];
 					for (x = 0; x < SCOPE_WIDTH; x++)
 						scopePtr[x] = scopePixel;
 
@@ -332,8 +332,6 @@
 	uint32_t diff32;
 	uint64_t time64;
 
-	(void)ptr;
-
 	// this is needed for scope stability (confirmed)
 	SDL_SetThreadPriority(SDL_THREAD_PRIORITY_HIGH);
 
@@ -343,7 +341,7 @@
 
 	while (editor.programRunning)
 	{
-		if (ptConfig.realVuMeters)
+		if (config.realVuMeters)
 			updateRealVuMeters();
 
 		updateScopes();
@@ -372,6 +370,7 @@
 		}
 	}
 
+	(void)ptr;
 	return true;
 }
 
@@ -383,7 +382,7 @@
 	dFrac = modf(editor.dPerfFreq / SCOPE_HZ, &dInt);
 
 	// integer part
-	scopeTimeLen = (uint32_t)dInt;
+	scopeTimeLen = (int32_t)dInt;
 
 	// fractional part scaled to 0..2^32-1
 	dFrac *= UINT32_MAX;
@@ -400,18 +399,20 @@
 	return true;
 }
 
-void waitOnScopes(void)
+void stopScope(uint8_t ch)
 {
 	while (scopesReading);
-}
+	memset(&scopeExt[ch], 0, sizeof (scopeChannelExt_t));
 
-void clearScopes(void)
-{
-	waitOnScopes();
+	while (scopesReading);
+	memset(&scope[ch], 0, sizeof (scopeChannel_t));
 
-	memset(scope, 0, sizeof (scope));
-	memset(scopeExt, 0, sizeof (scopeExt));
+	scope[ch].length = scopeExt[ch].newLength = 2;
+	while (scopesReading); // final wait to make sure scopes are all inactive
+}
 
-	for (uint8_t i = 0; i < AMIGA_VOICES; i++)
-		scope[i].length = scopeExt[i].newLength = 2;
+void stopAllScopes(void)
+{
+	for (int32_t i = 0; i < AMIGA_VOICES; i++)
+		stopScope(i);
 }
--- a/src/pt2_scopes.h
+++ b/src/pt2_scopes.h
@@ -2,6 +2,7 @@
 
 #include <stdint.h>
 #include <stdbool.h>
+#include "pt2_header.h"
 
 typedef struct scopeChannel_t // internal scope state
 {
@@ -24,8 +25,8 @@
 void updateScopes(void);
 void drawScopes(void);
 bool initScopes(void);
-void waitOnScopes(void);
-void clearScopes(void);
+void stopScope(uint8_t ch);
+void stopAllScopes(void);
 
-extern scopeChannel_t scope[4];
-extern scopeChannelExt_t scopeExt[4];
+extern scopeChannel_t scope[AMIGA_VOICES];
+extern scopeChannelExt_t scopeExt[AMIGA_VOICES];
--- a/src/pt2_tables.h
+++ b/src/pt2_tables.h
@@ -70,9 +70,6 @@
 extern uint32_t *editOpModeCharsBMP;
 extern uint32_t *pat2SmpDialogBMP;
 
-// PALETTE
-extern uint32_t palette[PALETTE_NUM];
-
 // button tables taken from the ptplay project + modified
 
 // MODIFY THESE EVERY TIME YOU REMOVE/ADD A BUTTON!
--- a/src/pt2_textout.c
+++ b/src/pt2_textout.c
@@ -12,7 +12,7 @@
 	'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
 };
 
-void charOut(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t color)
+void charOut(uint32_t xPos, uint32_t yPos, char ch, uint32_t color)
 {
 	const uint8_t *srcPtr;
 	uint32_t *dstPtr;
@@ -21,7 +21,7 @@
 		return;
 
 	srcPtr = &fontBMP[(uint8_t)ch * (FONT_CHAR_W * FONT_CHAR_H)];
-	dstPtr = &frameBuffer[(yPos * SCREEN_W) + xPos];
+	dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
 
 	for (uint32_t y = 0; y < FONT_CHAR_H; y++)
 	{
@@ -36,7 +36,7 @@
 	}
 }
 
-void charOutBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor)
+void charOutBg(uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor)
 {
 	const uint8_t *srcPtr;
 	uint32_t *dstPtr;
@@ -48,7 +48,7 @@
 		ch = ' ';
 
 	srcPtr = &fontBMP[(uint8_t)ch * (FONT_CHAR_W * FONT_CHAR_H)];
-	dstPtr = &frameBuffer[(yPos * SCREEN_W) + xPos];
+	dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
 
 	for (uint32_t y = 0; y < FONT_CHAR_H; y++)
 	{
@@ -60,7 +60,7 @@
 	}
 }
 
-void charOutBig(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t color)
+void charOutBig(uint32_t xPos, uint32_t yPos, char ch, uint32_t color)
 {
 	const uint8_t *srcPtr;
 	uint32_t *dstPtr;
@@ -69,7 +69,7 @@
 		return;
 
 	srcPtr = &fontBMP[(uint8_t)ch * (FONT_CHAR_W * FONT_CHAR_H)];
-	dstPtr = &frameBuffer[(yPos * SCREEN_W) + xPos];
+	dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
 
 	for (uint32_t y = 0; y < FONT_CHAR_H; y++)
 	{
@@ -87,7 +87,7 @@
 	}
 }
 
-void charOutBigBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor)
+void charOutBigBg(uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor)
 {
 	const uint8_t *srcPtr;
 	uint32_t *dstPtr;
@@ -99,7 +99,7 @@
 		ch = ' ';
 
 	srcPtr = &fontBMP[(uint8_t)ch * (FONT_CHAR_W * FONT_CHAR_H)];
-	dstPtr = &frameBuffer[(yPos * SCREEN_W) + xPos];
+	dstPtr = &video.frameBuffer[(yPos * SCREEN_W) + xPos];
 
 	for (uint32_t y = 0; y < FONT_CHAR_H; y++)
 	{
@@ -122,61 +122,61 @@
 	}
 }
 
-void textOut(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
+void textOut(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
 {
 	uint32_t x = xPos;
 	while (*text != '\0')
 	{
-		charOut(frameBuffer, x, yPos, *text++, color);
+		charOut(x, yPos, *text++, color);
 		x += FONT_CHAR_W;
 	}
 }
 
-void textOutTight(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
+void textOutTight(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
 {
 	uint32_t x = xPos;
 	while (*text != '\0')
 	{
-		charOut(frameBuffer, x, yPos, *text++, color);
+		charOut(x, yPos, *text++, color);
 		x += (FONT_CHAR_W - 1);
 	}
 }
 
-void textOutBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor)
+void textOutBg(uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor)
 {
 	uint32_t x = xPos;
 	while (*text != '\0')
 	{
-		charOutBg(frameBuffer, x, yPos, *text++, fgColor, bgColor);
+		charOutBg(x, yPos, *text++, fgColor, bgColor);
 		x += FONT_CHAR_W;
 	}
 }
 
-void textOutBig(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
+void textOutBig(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color)
 {
 	uint32_t x = xPos;
 	while (*text != '\0')
 	{
-		charOutBig(frameBuffer, x, yPos, *text++, color);
+		charOutBig(x, yPos, *text++, color);
 		x += FONT_CHAR_W;
 	}
 }
 
-void textOutBigBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor)
+void textOutBigBg(uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor)
 {
 	uint32_t x = xPos;
 	while (*text != '\0')
 	{
-		charOutBigBg(frameBuffer, x, yPos, *text++, fgColor, bgColor);
+		charOutBigBg(x, yPos, *text++, fgColor, bgColor);
 		x += FONT_CHAR_W;
 	}
 }
 
-void printTwoDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printTwoDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "00", fontColor);
+		textOut(x, y, "00", fontColor);
 	}
 	else
 	{
@@ -183,16 +183,16 @@
 		if (value > 99)
 			value = 99;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
+		charOut(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
 	}
 }
 
-void printTwoDecimalsBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printTwoDecimalsBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOutBig(frameBuffer, x, y, "00", fontColor);
+		textOutBig(x, y, "00", fontColor);
 	}
 	else
 	{
@@ -199,16 +199,16 @@
 		if (value > 99)
 			value = 99;
 
-		charOutBig(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
-		charOutBig(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
+		charOutBig(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
+		charOutBig(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
 	}
 }
 
-void printThreeDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printThreeDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "000", fontColor);
+		textOut(x, y, "000", fontColor);
 	}
 	else
 	{
@@ -215,17 +215,17 @@
 		if (value > 999)
 			value = 999;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
+		charOut(x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
 	}
 }
 
-void printFourDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printFourDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "0000", fontColor);
+		textOut(x, y, "0000", fontColor);
 	}
 	else
 	{
@@ -232,18 +232,18 @@
 		if (value > 9999)
 			value = 9999;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
+		charOut(x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
 	}
 }
 
-void printFiveDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printFiveDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "00000", fontColor);
+		textOut(x, y, "00000", fontColor);
 	}
 	else
 	{
@@ -250,16 +250,16 @@
 		if (value > 99999)
 			value = 99999;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 4), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
+		charOut(x + (FONT_CHAR_W * 4), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor); value /= 10;
+		charOut(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor);
 	}
 }
 
 // this one is used for module size and sampler screen display length (zeroes are padded with space)
-void printSixDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printSixDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	char numberText[7];
 	uint8_t i;
@@ -266,7 +266,7 @@
 
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "     0", fontColor);
+		textOut(x, y, "     0", fontColor);
 	}
 	else
 	{
@@ -285,106 +285,106 @@
 		while (numberText[i] == '0')
 			numberText[i++] = ' ';
 
-		textOut(frameBuffer, x, y, numberText, fontColor);
+		textOut(x, y, numberText, fontColor);
 	}
 }
 
-void printOneHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printOneHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
-	charOut(frameBuffer, x, y, hexTable[value & 15], fontColor);
+	charOut(x, y, hexTable[value & 15], fontColor);
 }
 
-void printOneHexBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printOneHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
-	charOutBig(frameBuffer, x, y, hexTable[value & 15], fontColor);
+	charOutBig(x, y, hexTable[value & 15], fontColor);
 }
 
-void printTwoHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printTwoHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "00", fontColor);
+		textOut(x, y, "00", fontColor);
 	}
 	else
 	{
 		value &= 0xFF;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor);
+		charOut(x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor);
+		charOut(x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor);
 	}
 }
 
-void printTwoHexBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printTwoHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOutBig(frameBuffer, x, y, "00", fontColor);
+		textOutBig(x, y, "00", fontColor);
 	}
 	else
 	{
 		value &= 0xFF;
 
-		charOutBig(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor);
-		charOutBig(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor);
+		charOutBig(x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor);
+		charOutBig(x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor);
 	}
 }
 
-void printThreeHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printThreeHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "000", fontColor);
+		textOut(x, y, "000", fontColor);
 	}
 	else
 	{
 		value &= 0xFFF;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 8], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[value & 15], fontColor);
+		charOut(x + (FONT_CHAR_W * 0), y, hexTable[value >> 8], fontColor);
+		charOut(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
+		charOut(x + (FONT_CHAR_W * 2), y, hexTable[value & 15], fontColor);
 	}
 }
 
-void printFourHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printFourHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "0000", fontColor);
+		textOut(x, y, "0000", fontColor);
 	}
 	else
 	{
 		value &= 0xFFFF;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 12], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 8)) >> 8], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 3), y, hexTable[value & 15], fontColor);
+		charOut(x + (FONT_CHAR_W * 0), y, hexTable[value >> 12], fontColor);
+		charOut(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 8)) >> 8], fontColor);
+		charOut(x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
+		charOut(x + (FONT_CHAR_W * 3), y, hexTable[value & 15], fontColor);
 	}
 }
 
-void printFiveHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
+void printFiveHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor)
 {
 	if (value == 0)
 	{
-		textOut(frameBuffer, x, y, "00000", fontColor);
+		textOut(x, y, "00000", fontColor);
 	}
 	else
 	{
 		value &= 0xFFFFF;
 
-		charOut(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value  >> 16], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 12)) >> 12], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 8)) >> 8], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 3), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
-		charOut(frameBuffer, x + (FONT_CHAR_W * 4), y, hexTable[value & 15], fontColor);
+		charOut(x + (FONT_CHAR_W * 0), y, hexTable[value  >> 16], fontColor);
+		charOut(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 12)) >> 12], fontColor);
+		charOut(x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 8)) >> 8], fontColor);
+		charOut(x + (FONT_CHAR_W * 3), y, hexTable[(value & (15 << 4)) >> 4], fontColor);
+		charOut(x + (FONT_CHAR_W * 4), y, hexTable[value & 15], fontColor);
 	}
 }
 
-void printTwoDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printTwoDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "00", fontColor, backColor);
+		textOutBg(x, y, "00", fontColor, backColor);
 	}
 	else
 	{
@@ -391,16 +391,16 @@
 		if (value > 99)
 			value = 99;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
 	}
 }
 
-void printTwoDecimalsBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printTwoDecimalsBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBigBg(frameBuffer, x, y, "00", fontColor, backColor);
+		textOutBigBg(x, y, "00", fontColor, backColor);
 	}
 	else
 	{
@@ -407,16 +407,16 @@
 		if (value > 99)
 			value = 99;
 
-		charOutBigBg(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBigBg(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
+		charOutBigBg(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBigBg(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
 	}
 }
 
-void printThreeDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printThreeDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "000", fontColor, backColor);
+		textOutBg(x, y, "000", fontColor, backColor);
 	}
 	else
 	{
@@ -423,17 +423,17 @@
 		if (value > 999)
 			value = 999;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
 	}
 }
 
-void printFourDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printFourDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "0000", fontColor, backColor);
+		textOutBg(x, y, "0000", fontColor, backColor);
 	}
 	else
 	{
@@ -440,15 +440,15 @@
 		if (value > 9999)
 			value = 9999;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 3), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 2), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 1), y, '0' + (value % 10), fontColor, backColor); value /= 10;
+		charOutBg(x + (FONT_CHAR_W * 0), y, '0' + (value % 10), fontColor, backColor);
 	}
 }
 
 // this one is used for "DISP:" in the sampler screen (zeroes are padded with space)
-void printFiveDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printFiveDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	char numberText[6];
 	uint8_t i;
@@ -455,7 +455,7 @@
 
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "    0", fontColor, backColor);
+		textOutBg(x, y, "    0", fontColor, backColor);
 	}
 	else
 	{
@@ -473,12 +473,12 @@
 		while (numberText[i] == '0')
 			numberText[i++] = ' ';
 
-		textOutBg(frameBuffer, x, y, numberText, fontColor, backColor);
+		textOutBg(x, y, numberText, fontColor, backColor);
 	}
 }
 
 // this one is used for module size (zeroes are padded with space)
-void printSixDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printSixDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	char numberText[7];
 	uint8_t i;
@@ -485,7 +485,7 @@
 
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "     0", fontColor, backColor);
+		textOutBg(x, y, "     0", fontColor, backColor);
 	}
 	else
 	{
@@ -504,98 +504,98 @@
 		while (numberText[i] == '0')
 			numberText[i++] = ' ';
 
-		textOutBg(frameBuffer, x, y, numberText, fontColor, backColor);
+		textOutBg(x, y, numberText, fontColor, backColor);
 	}
 }
 
-void printOneHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printOneHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
-	charOutBg(frameBuffer, x, y, hexTable[value & 0xF], fontColor, backColor);
+	charOutBg(x, y, hexTable[value & 0xF], fontColor, backColor);
 }
 
-void printOneHexBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printOneHexBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
-	charOutBigBg(frameBuffer, x, y, hexTable[value & 0xF], fontColor, backColor);
+	charOutBigBg(x, y, hexTable[value & 0xF], fontColor, backColor);
 }
 
-void printTwoHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printTwoHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "00", fontColor, backColor);
+		textOutBg(x, y, "00", fontColor, backColor);
 	}
 	else
 	{
 		value &= 0xFF;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor, backColor);
 	}
 }
 
-void printTwoHexBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printTwoHexBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBigBg(frameBuffer, x, y, "00", fontColor, backColor);
+		textOutBigBg(x, y, "00", fontColor, backColor);
 	}
 	else
 	{
 		value &= 0xFF;
 
-		charOutBigBg(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor, backColor);
-		charOutBigBg(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor, backColor);
+		charOutBigBg(x + (FONT_CHAR_W * 0), y, hexTable[value >> 4], fontColor, backColor);
+		charOutBigBg(x + (FONT_CHAR_W * 1), y, hexTable[value & 15], fontColor, backColor);
 	}
 }
 
-void printThreeHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printThreeHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "000", fontColor, backColor);
+		textOutBg(x, y, "000", fontColor, backColor);
 	}
 	else
 	{
 		value &= 0xFFF;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 8], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[value & 15], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 0), y, hexTable[value >> 8], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 2), y, hexTable[value & 15], fontColor, backColor);
 	}
 }
 
-void printFourHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printFourHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "0000", fontColor, backColor);
+		textOutBg(x, y, "0000", fontColor, backColor);
 	}
 	else
 	{
 		value &= 0xFFFF;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 12], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 8)) >> 8], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 3), y, hexTable[value & 15], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 0), y, hexTable[value >> 12], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 8)) >> 8], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 3), y, hexTable[value & 15], fontColor, backColor);
 	}
 }
 
-void printFiveHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
+void printFiveHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor)
 {
 	if (value == 0)
 	{
-		textOutBg(frameBuffer, x, y, "00000", fontColor, backColor);
+		textOutBg(x, y, "00000", fontColor, backColor);
 	}
 	else
 	{
 		value &= 0xFFFFF;
 
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 0), y, hexTable[value >> 16], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 12)) >> 12], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 8)) >> 8], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 3), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
-		charOutBg(frameBuffer, x + (FONT_CHAR_W * 4), y, hexTable[value & 15], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 0), y, hexTable[value >> 16], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 1), y, hexTable[(value & (15 << 12)) >> 12], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 2), y, hexTable[(value & (15 << 8)) >> 8], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 3), y, hexTable[(value & (15 << 4)) >> 4], fontColor, backColor);
+		charOutBg(x + (FONT_CHAR_W * 4), y, hexTable[value & 15], fontColor, backColor);
 	}
 }
 
--- a/src/pt2_textout.h
+++ b/src/pt2_textout.h
@@ -3,41 +3,41 @@
 #include <stdint.h>
 #include <stdbool.h>
 
-void charOut(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t color);
-void charOutBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor);
-void charOutBig(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t color);
-void charOutBigBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor);
-void textOut(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
-void textOutTight(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
-void textOutBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor);
-void textOutBig(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
-void textOutBigBg(uint32_t *frameBuffer, uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor);
-void printOneHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printTwoHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printThreeHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printFourHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printFiveHex(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printOneHexBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printTwoHexBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printSixDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printTwoDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printFourDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printFiveDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printThreeDecimals(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printTwoDecimalsBig(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
-void printOneHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printTwoHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printThreeHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printFourHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printFiveHexBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printOneHexBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printTwoHexBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printSixDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printTwoDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printFourDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printFiveDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printThreeDecimalsBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
-void printTwoDecimalsBigBg(uint32_t *frameBuffer, uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void charOut(uint32_t xPos, uint32_t yPos, char ch, uint32_t color);
+void charOutBg(uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor);
+void charOutBig(uint32_t xPos, uint32_t yPos, char ch, uint32_t color);
+void charOutBigBg(uint32_t xPos, uint32_t yPos, char ch, uint32_t fgColor, uint32_t bgColor);
+void textOut(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
+void textOutTight(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
+void textOutBg(uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor);
+void textOutBig(uint32_t xPos, uint32_t yPos, const char *text, uint32_t color);
+void textOutBigBg(uint32_t xPos, uint32_t yPos, const char *text, uint32_t fgColor, uint32_t bgColor);
+void printOneHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printTwoHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printThreeHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printFourHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printFiveHex(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printOneHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printTwoHexBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printSixDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printTwoDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printFourDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printFiveDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printThreeDecimals(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printTwoDecimalsBig(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor);
+void printOneHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printTwoHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printThreeHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printFourHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printFiveHexBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printOneHexBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printTwoHexBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printSixDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printTwoDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printFourDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printFiveDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printThreeDecimalsBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
+void printTwoDecimalsBigBg(uint32_t x, uint32_t y, uint32_t value, uint32_t fontColor, uint32_t backColor);
 void setPrevStatusMessage(void);
 void setStatusMessage(const char *msg, bool carry);
 void displayMsg(const char *msg);
--- a/src/pt2_visuals.c
+++ b/src/pt2_visuals.c
@@ -40,24 +40,16 @@
 {
 	bool visible;
 	int8_t pixelType;
-	uint16_t newX, newY, x, y, w, h;
+	int16_t newX, newY, x, y, w, h;
 	uint32_t colorKey, *refreshBuffer;
 	const void *data;
 } sprite_t;
 
 static uint32_t vuMetersBg[4 * (10 * 48)];
-static uint64_t timeNext64, timeNext64Frac, _50HzCounter;
+static uint64_t timeNext64, timeNext64Frac;
 
 sprite_t sprites[SPRITE_NUM]; // globalized
 
-extern bool forceMixerOff; // pt_audio.c
-
-// pt_main.c
-extern uint32_t *pixelBuffer;
-extern SDL_Window *window;
-extern SDL_Renderer *renderer;
-extern SDL_Texture *texture;
-
 static const uint16_t cursorPosTable[24] =
 {
 	 30,  54,  62,  70,  78,  86,
@@ -98,7 +90,7 @@
 	dFrac = modf(editor.dPerfFreq / VBLANK_HZ, &dInt);
 
 	// integer part
-	editor.vblankTimeLen = (uint32_t)dInt;
+	editor.vblankTimeLen = (int32_t)dInt;
 
 	// fractional part scaled to 0..2^32-1
 	dFrac *= UINT32_MAX;
@@ -156,7 +148,7 @@
 	updateSampler();
 	updatePosEd();
 	updateVisualizer();
-	updateDragBars();
+	handleLastGUIObjectDown();
 	drawSamplerLine();
 }
 
@@ -203,7 +195,7 @@
 	// render ask dialog
 
 	srcPtr = editor.ui.pat2SmpDialogShown ? pat2SmpDialogBMP : yesNoDialogBMP;
-	dstPtr = &pixelBuffer[(51 * SCREEN_W) + 160];
+	dstPtr = &video.frameBuffer[(51 * SCREEN_W) + 160];
 
 	for (uint32_t y = 0; y < 39; y++)
 	{
@@ -225,7 +217,7 @@
 	// render custom big ask dialog
 
 	srcPtr = bigYesNoDialogBMP;
-	dstPtr = &pixelBuffer[(44 * SCREEN_W) + 120];
+	dstPtr = &video.frameBuffer[(44 * SCREEN_W) + 120];
 
 	for (uint32_t y = 0; y < 55; y++)
 	{
@@ -244,10 +236,10 @@
 	setStatusMessage("PLEASE SELECT", NO_CARRY);
 	renderBigAskDialog();
 
-	textOutTight(pixelBuffer, 133, 49, "THE SAMPLE'S FREQUENCY IS", palette[PAL_BACKGRD]);
-	textOutTight(pixelBuffer, 178, 57, "ABOVE 22KHZ.", palette[PAL_BACKGRD]);
-	textOutTight(pixelBuffer, 133, 65, "DO YOU WANT TO DOWNSAMPLE", palette[PAL_BACKGRD]);
-	textOutTight(pixelBuffer, 156, 73, "BEFORE LOADING IT?", palette[PAL_BACKGRD]);
+	textOutTight(133, 49, "THE SAMPLE'S FREQUENCY IS", video.palette[PAL_BACKGRD]);
+	textOutTight(178, 57, "ABOVE 22KHZ.", video.palette[PAL_BACKGRD]);
+	textOutTight(133, 65, "DO YOU WANT TO DOWNSAMPLE", video.palette[PAL_BACKGRD]);
+	textOutTight(156, 73, "BEFORE LOADING IT?", video.palette[PAL_BACKGRD]);
 }
 
 static void fillFromVuMetersBgBuffer(void)
@@ -259,7 +251,7 @@
 		return;
 
 	srcPtr = vuMetersBg;
-	dstPtr = &pixelBuffer[(187 * SCREEN_W) + 55];
+	dstPtr = &video.frameBuffer[(187 * SCREEN_W) + 55];
 
 	for (uint32_t i = 0; i < AMIGA_VOICES; i++)
 	{
@@ -284,7 +276,7 @@
 	if (editor.ui.samplerScreenShown || editor.isWAVRendering || editor.isSMPRendering)
 		return;
 
-	srcPtr = &pixelBuffer[(187 * SCREEN_W) + 55];
+	srcPtr = &video.frameBuffer[(187 * SCREEN_W) + 55];
 	dstPtr = vuMetersBg;
 
 	for (uint32_t i = 0; i < AMIGA_VOICES; i++)
@@ -312,10 +304,10 @@
 
 	fillToVuMetersBgBuffer();
 	
-	dstPtr = &pixelBuffer[(187 * SCREEN_W) + 55];
+	dstPtr = &video.frameBuffer[(187 * SCREEN_W) + 55];
 	for (uint32_t i = 0; i < AMIGA_VOICES; i++)
 	{
-		if (ptConfig.realVuMeters)
+		if (config.realVuMeters)
 			h = editor.realVuMeterVolumes[i];
 		else
 			h = editor.vuMeterVolumes[i];
@@ -349,13 +341,13 @@
 	if (editor.ui.updateSongPos)
 	{
 		editor.ui.updateSongPos = false;
-		printThreeDecimalsBg(pixelBuffer, 72, 3, *editor.currPosDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printThreeDecimalsBg(72, 3, *editor.currPosDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateSongPattern)
 	{
 		editor.ui.updateSongPattern = false;
-		printTwoDecimalsBg(pixelBuffer, 80, 14, *editor.currPatternDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printTwoDecimalsBg(80, 14, *editor.currPatternDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateSongLength)
@@ -362,7 +354,7 @@
 	{
 		editor.ui.updateSongLength = false;
 		if (!editor.isWAVRendering)
-			printThreeDecimalsBg(pixelBuffer, 72, 25, *editor.currLengthDisp,palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printThreeDecimalsBg(72, 25, *editor.currLengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateCurrSampleFineTune)
@@ -373,18 +365,18 @@
 		{
 			if (currSample->fineTune >= 8)
 			{
-				charOutBg(pixelBuffer, 80, 36, '-', palette[PAL_GENTXT], palette[PAL_GENBKG]);
-				charOutBg(pixelBuffer, 88, 36, '0' + (0x10 - (currSample->fineTune & 0xF)), palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				charOutBg(80, 36, '-', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+				charOutBg(88, 36, '0' + (0x10 - (currSample->fineTune & 0xF)), video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			}
 			else if (currSample->fineTune > 0)
 			{
-				charOutBg(pixelBuffer, 80, 36, '+', palette[PAL_GENTXT], palette[PAL_GENBKG]);
-				charOutBg(pixelBuffer, 88, 36, '0' + (currSample->fineTune & 0xF), palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				charOutBg(80, 36, '+', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+				charOutBg(88, 36, '0' + (currSample->fineTune & 0xF), video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			}
 			else
 			{
-				charOutBg(pixelBuffer, 80, 36, ' ', palette[PAL_GENBKG], palette[PAL_GENBKG]);
-				charOutBg(pixelBuffer, 88, 36, '0', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				charOutBg(80, 36, ' ', video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
+				charOutBg(88, 36, '0', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			}
 		}
 	}
@@ -394,8 +386,8 @@
 		editor.ui.updateCurrSampleNum = false;
 		if (!editor.isWAVRendering)
 		{
-			printTwoHexBg(pixelBuffer, 80, 47,
-				editor.sampleZero ? 0 : ((*editor.currSampleDisp) + 1), palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoHexBg(80, 47,
+				editor.sampleZero ? 0 : ((*editor.currSampleDisp) + 1), video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 
@@ -403,7 +395,7 @@
 	{
 		editor.ui.updateCurrSampleVolume = false;
 		if (!editor.isWAVRendering)
-			printTwoHexBg(pixelBuffer, 80, 58, *currSample->volumeDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoHexBg(80, 58, *currSample->volumeDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateCurrSampleLength)
@@ -410,19 +402,19 @@
 	{
 		editor.ui.updateCurrSampleLength = false;
 		if (!editor.isWAVRendering)
-			printFourHexBg(pixelBuffer, 64, 69, *currSample->lengthDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printFourHexBg(64, 69, *currSample->lengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateCurrSampleRepeat)
 	{
 		editor.ui.updateCurrSampleRepeat = false;
-		printFourHexBg(pixelBuffer, 64, 80, *currSample->loopStartDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printFourHexBg(64, 80, *currSample->loopStartDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateCurrSampleReplen)
 	{
 		editor.ui.updateCurrSampleReplen = false;
-		printFourHexBg(pixelBuffer, 64, 91, *currSample->loopLengthDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printFourHexBg(64, 91, *currSample->loopLengthDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 }
 
@@ -437,30 +429,30 @@
 		editor.ui.updateStatusText = false;
 
 		// clear background
-		textOutBg(pixelBuffer, 88, 127, "                 ", palette[PAL_GENBKG], palette[PAL_GENBKG]);
+		textOutBg(88, 127, "                 ", video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
 
 		// render status text
 		if (!editor.errorMsgActive && editor.blockMarkFlag && !editor.ui.askScreenShown
 			&& !editor.ui.clearScreenShown && !editor.swapChannelFlag)
 		{
-			textOut(pixelBuffer, 88, 127, "MARK BLOCK", palette[PAL_GENTXT]);
-			charOut(pixelBuffer, 192, 127, '-', palette[PAL_GENTXT]);
+			textOut(88, 127, "MARK BLOCK", video.palette[PAL_GENTXT]);
+			charOut(192, 127, '-', video.palette[PAL_GENTXT]);
 
 			editor.blockToPos = modEntry->currRow;
 			if (editor.blockFromPos >= editor.blockToPos)
 			{
-				printTwoDecimals(pixelBuffer, 176, 127, editor.blockToPos, palette[PAL_GENTXT]);
-				printTwoDecimals(pixelBuffer, 200, 127, editor.blockFromPos, palette[PAL_GENTXT]);
+				printTwoDecimals(176, 127, editor.blockToPos, video.palette[PAL_GENTXT]);
+				printTwoDecimals(200, 127, editor.blockFromPos, video.palette[PAL_GENTXT]);
 			}
 			else
 			{
-				printTwoDecimals(pixelBuffer, 176, 127, editor.blockFromPos, palette[PAL_GENTXT]);
-				printTwoDecimals(pixelBuffer, 200, 127, editor.blockToPos, palette[PAL_GENTXT]);
+				printTwoDecimals(176, 127, editor.blockFromPos, video.palette[PAL_GENTXT]);
+				printTwoDecimals(200, 127, editor.blockToPos, video.palette[PAL_GENTXT]);
 			}
 		}
 		else
 		{
-			textOut(pixelBuffer, 88, 127, editor.ui.statusMessage, palette[PAL_GENTXT]);
+			textOut(88, 127, editor.ui.statusMessage, video.palette[PAL_GENTXT]);
 		}
 	}
 
@@ -468,7 +460,7 @@
 	{
 		editor.ui.updateSongBPM = false;
 		if (!editor.ui.samplerScreenShown)
-			printThreeDecimalsBg(pixelBuffer, 32, 123, modEntry->currBPM, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printThreeDecimalsBg(32, 123, modEntry->currBPM, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateCurrPattText)
@@ -475,7 +467,7 @@
 	{
 		editor.ui.updateCurrPattText = false;
 		if (!editor.ui.samplerScreenShown)
-			printTwoDecimalsBg(pixelBuffer, 8, 127, *editor.currEditPatternDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoDecimalsBg(8, 127, *editor.currEditPatternDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateTrackerFlags)
@@ -482,48 +474,48 @@
 	{
 		editor.ui.updateTrackerFlags = false;
 
-		charOutBg(pixelBuffer, 1, 113, ' ', palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		charOutBg(pixelBuffer, 8, 113, ' ', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		charOutBg(1, 113, ' ', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		charOutBg(8, 113, ' ', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 		if (editor.autoInsFlag)
 		{
-			charOut(pixelBuffer, 0, 113, 'I', palette[PAL_GENTXT]);
+			charOut(0, 113, 'I', video.palette[PAL_GENTXT]);
 
 			// in Amiga PT, "auto insert" 9 means 0
 			if (editor.autoInsSlot == 9)
-				charOut(pixelBuffer, 8, 113, '0', palette[PAL_GENTXT]);
+				charOut(8, 113, '0', video.palette[PAL_GENTXT]);
 			else
-				charOut(pixelBuffer, 8, 113, '1' + editor.autoInsSlot, palette[PAL_GENTXT]);
+				charOut(8, 113, '1' + editor.autoInsSlot, video.palette[PAL_GENTXT]);
 		}
 
-		charOutBg(pixelBuffer, 1, 102, ' ', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		charOutBg(1, 102, ' ', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		if (editor.metroFlag)
-			charOut(pixelBuffer, 0, 102, 'M', palette[PAL_GENTXT]);
+			charOut(0, 102, 'M', video.palette[PAL_GENTXT]);
 
-		charOutBg(pixelBuffer, 16, 102, ' ', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		charOutBg(16, 102, ' ', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		if (editor.multiFlag)
-			charOut(pixelBuffer, 16, 102, 'M', palette[PAL_GENTXT]);
+			charOut(16, 102, 'M', video.palette[PAL_GENTXT]);
 
-		charOutBg(pixelBuffer, 24, 102, '0' + editor.editMoveAdd,palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		charOutBg(24, 102, '0' + editor.editMoveAdd, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
-		charOutBg(pixelBuffer, 311, 128, ' ', palette[PAL_GENBKG], palette[PAL_GENBKG]);
+		charOutBg(311, 128, ' ', video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
 		if (editor.pNoteFlag == 1)
 		{
-			pixelBuffer[(129 * SCREEN_W) + 314] = palette[PAL_GENTXT];
-			pixelBuffer[(129 * SCREEN_W) + 315] = palette[PAL_GENTXT];
+			video.frameBuffer[(129 * SCREEN_W) + 314] = video.palette[PAL_GENTXT];
+			video.frameBuffer[(129 * SCREEN_W) + 315] = video.palette[PAL_GENTXT];
 		}
 		else if (editor.pNoteFlag == 2)
 		{
-			pixelBuffer[(128 * SCREEN_W) + 314] = palette[PAL_GENTXT];
-			pixelBuffer[(128 * SCREEN_W) + 315] = palette[PAL_GENTXT];
-			pixelBuffer[(130 * SCREEN_W) + 314] = palette[PAL_GENTXT];
-			pixelBuffer[(130 * SCREEN_W) + 315] = palette[PAL_GENTXT];
+			video.frameBuffer[(128 * SCREEN_W) + 314] = video.palette[PAL_GENTXT];
+			video.frameBuffer[(128 * SCREEN_W) + 315] = video.palette[PAL_GENTXT];
+			video.frameBuffer[(130 * SCREEN_W) + 314] = video.palette[PAL_GENTXT];
+			video.frameBuffer[(130 * SCREEN_W) + 315] = video.palette[PAL_GENTXT];
 		}
 	}
 
 	// playback timer
 
-	secs = ((editor.musicTime / 256) * 5) / 512;
+	secs = ((editor.musicTime >> 8) * 5) >> 9;
 	secs -= ((secs / 3600) * 3600);
 
 	if (secs <= 5999) // below 99 minutes 59 seconds
@@ -532,14 +524,14 @@
 		MI_TimeS = secs - (MI_TimeM * 60);
 
 		// xx:xx
-		printTwoDecimalsBg(pixelBuffer, 272, 102, MI_TimeM, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		printTwoDecimalsBg(pixelBuffer, 296, 102, MI_TimeS, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printTwoDecimalsBg(272, 102, MI_TimeM, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		printTwoDecimalsBg(296, 102, MI_TimeS, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 	else
 	{
 		// 99:59
-		printTwoDecimalsBg(pixelBuffer, 272, 102, 99, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		printTwoDecimalsBg(pixelBuffer, 296, 102, 59, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printTwoDecimalsBg(272, 102, 99, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		printTwoDecimalsBg(296, 102, 59, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateSongName)
@@ -551,7 +543,7 @@
 			if (tempChar == '\0')
 				tempChar = '_';
 
-			charOutBg(pixelBuffer, 104 + (x * FONT_CHAR_W), 102, tempChar, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			charOutBg(104 + (x * FONT_CHAR_W), 102, tempChar, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 
@@ -566,7 +558,7 @@
 			if (tempChar == '\0')
 				tempChar = '_';
 
-			charOutBg(pixelBuffer, 104 + (x * FONT_CHAR_W), 113, tempChar, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			charOutBg(104 + (x * FONT_CHAR_W), 113, tempChar, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 
@@ -575,7 +567,7 @@
 		editor.ui.updateSongSize = false;
 
 		// clear background
-		textOutBg(pixelBuffer, 264, 123, "      ", palette[PAL_GENBKG], palette[PAL_GENBKG]);
+		textOutBg(264, 123, "      ", video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
 
 		// calculate module length
 		uint32_t totalSampleDataSize = 0;
@@ -592,12 +584,12 @@
 		uint32_t moduleSize = 2108 + (totalPatterns * 1024) + totalSampleDataSize;
 		if (moduleSize > 999999)
 		{
-			charOut(pixelBuffer, 304, 123, 'K', palette[PAL_GENTXT]);
-			printFourDecimals(pixelBuffer, 272, 123, moduleSize / 1000, palette[PAL_GENTXT]);
+			charOut(304, 123, 'K', video.palette[PAL_GENTXT]);
+			printFourDecimals(272, 123, moduleSize / 1000, video.palette[PAL_GENTXT]);
 		}
 		else
 		{
-			printSixDecimals(pixelBuffer, 264, 123, moduleSize, palette[PAL_GENTXT]);
+			printSixDecimals(264, 123, moduleSize, video.palette[PAL_GENTXT]);
 		}
 	}
 
@@ -604,7 +596,7 @@
 	if (editor.ui.updateSongTiming)
 	{
 		editor.ui.updateSongTiming = false;
-		textOutBg(pixelBuffer, 288, 130, (editor.timingMode == TEMPO_MODE_CIA) ? "CIA" : "VBL", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		textOutBg(288, 130, (editor.timingMode == TEMPO_MODE_CIA) ? "CIA" : "VBL", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 }
 
@@ -626,11 +618,11 @@
 	s = &modEntry->samples[editor.currSample];
 
 	// update 9xx offset
-	if (input.mouse.y >= 138 && input.mouse.y <= 201 && input.mouse.x >= 3 && input.mouse.x <= 316)
+	if (mouse.y >= 138 && mouse.y <= 201 && mouse.x >= 3 && mouse.x <= 316)
 	{
 		if (!editor.ui.samplerVolBoxShown && !editor.ui.samplerFiltersBoxShown && s->length > 0)
 		{
-			tmpSampleOffset = (scr2SmpPos(input.mouse.x-3) + (1 << 7)) >> 8; // rounded
+			tmpSampleOffset = (scr2SmpPos(mouse.x-3) + (1 << 7)) >> 8; // rounded
 			tmpSampleOffset = 0x900 + CLAMP(tmpSampleOffset, 0x00, 0xFF);
 
 			if (tmpSampleOffset != editor.ui.lastSampleOffset)
@@ -645,7 +637,7 @@
 	if (editor.ui.update9xxPos)
 	{
 		editor.ui.update9xxPos = false;
-		printThreeHexBg(pixelBuffer, 288, 247, editor.ui.lastSampleOffset, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printThreeHexBg(288, 247, editor.ui.lastSampleOffset, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateResampleNote)
@@ -655,14 +647,14 @@
 		// show resample note
 		if (editor.ui.changingSmpResample)
 		{
-			textOutBg(pixelBuffer, 288, 236, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			textOutBg(288, 236, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 		else
 		{
 			assert(editor.resampleNote < 36);
-			textOutBg(pixelBuffer, 288, 236,
-				ptConfig.accidental ? noteNames2[editor.resampleNote] : noteNames1[editor.resampleNote],
-				palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			textOutBg(288, 236,
+				config.accidental ? noteNames2[editor.resampleNote] : noteNames1[editor.resampleNote],
+				video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 
@@ -671,13 +663,13 @@
 		if (editor.ui.updateVolFromText)
 		{
 			editor.ui.updateVolFromText = false;
-			printThreeDecimalsBg(pixelBuffer, 176, 157, *editor.vol1Disp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printThreeDecimalsBg(176, 157, *editor.vol1Disp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateVolToText)
 		{
 			editor.ui.updateVolToText = false;
-			printThreeDecimalsBg(pixelBuffer, 176, 168, *editor.vol2Disp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printThreeDecimalsBg(176, 168, *editor.vol2Disp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 	else if (editor.ui.samplerFiltersBoxShown)
@@ -685,13 +677,13 @@
 		if (editor.ui.updateLPText)
 		{
 			editor.ui.updateLPText = false;
-			printFourDecimalsBg(pixelBuffer, 168, 157, *editor.lpCutOffDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printFourDecimalsBg(168, 157, *editor.lpCutOffDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateHPText)
 		{
 			editor.ui.updateHPText = false;
-			printFourDecimalsBg(pixelBuffer, 168, 168, *editor.hpCutOffDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printFourDecimalsBg(168, 168, *editor.hpCutOffDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateNormFlag)
@@ -699,9 +691,9 @@
 			editor.ui.updateNormFlag = false;
 
 			if (editor.normalizeFiltersFlag)
-				textOutBg(pixelBuffer, 208, 179, "YES", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(208, 179, "YES", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				textOutBg(pixelBuffer, 208, 179, "NO ", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(208, 179, "NO ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 }
@@ -712,9 +704,9 @@
 
 	sliderStart = ((editor.vol1 * 3) + 5) / 10;
 	sliderEnd  = sliderStart + 4;
-	pixel = palette[PAL_QADSCP];
-	bgPixel = palette[PAL_BACKGRD];
-	dstPtr = &pixelBuffer[(158 * SCREEN_W) + 105];
+	pixel = video.palette[PAL_QADSCP];
+	bgPixel = video.palette[PAL_BACKGRD];
+	dstPtr = &video.frameBuffer[(158 * SCREEN_W) + 105];
 
 	for (uint32_t y = 0; y < 3; y++)
 	{
@@ -736,9 +728,9 @@
 
 	sliderStart = ((editor.vol2 * 3) + 5) / 10;
 	sliderEnd = sliderStart + 4;
-	pixel = palette[PAL_QADSCP];
-	bgPixel = palette[PAL_BACKGRD];
-	dstPtr = &pixelBuffer[(169 * SCREEN_W) + 105];
+	pixel = video.palette[PAL_QADSCP];
+	bgPixel = video.palette[PAL_BACKGRD];
+	dstPtr = &video.frameBuffer[(169 * SCREEN_W) + 105];
 
 	for (uint32_t y = 0; y < 3; y++)
 	{
@@ -760,7 +752,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = samplerVolumeBMP;
-	dstPtr = &pixelBuffer[(154 * SCREEN_W) + 72];
+	dstPtr = &video.frameBuffer[(154 * SCREEN_W) + 72];
 
 	for (uint32_t y = 0; y < 33; y++)
 	{
@@ -791,7 +783,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = samplerFiltersBMP;
-	dstPtr = &pixelBuffer[(154 * SCREEN_W) + 65];
+	dstPtr = &video.frameBuffer[(154 * SCREEN_W) + 65];
 
 	for (uint32_t y = 0; y < 33; y++)
 	{
@@ -801,8 +793,8 @@
 		dstPtr += SCREEN_W;
 	}
 
-	textOut(pixelBuffer, 200, 157, "HZ", palette[PAL_GENTXT]);
-	textOut(pixelBuffer, 200, 168, "HZ", palette[PAL_GENTXT]);
+	textOut(200, 157, "HZ", video.palette[PAL_GENTXT]);
+	textOut(200, 168, "HZ", video.palette[PAL_GENTXT]);
 
 	editor.ui.updateLPText = true;
 	editor.ui.updateHPText = true;
@@ -820,7 +812,7 @@
 
 void renderDiskOpScreen(void)
 {
-	memcpy(pixelBuffer, diskOpScreenBMP, (99 * 320) * sizeof (int32_t));
+	memcpy(video.frameBuffer, diskOpScreenBMP, (99 * 320) * sizeof (int32_t));
 
 	editor.ui.updateDiskOpPathText = true;
 	editor.ui.updatePackText = true;
@@ -841,7 +833,7 @@
 	if (editor.ui.updateDiskOpFileList)
 	{
 		editor.ui.updateDiskOpFileList = false;
-		diskOpRenderFileList(pixelBuffer);
+		diskOpRenderFileList();
 	}
 
 	if (editor.ui.updateLoadMode)
@@ -849,13 +841,13 @@
 		editor.ui.updateLoadMode = false;
 
 		// clear backgrounds
-		charOutBg(pixelBuffer, 147,  3, ' ', palette[PAL_GENBKG], palette[PAL_GENBKG]);
-		charOutBg(pixelBuffer, 147, 14, ' ', palette[PAL_GENBKG], palette[PAL_GENBKG]);
+		charOutBg(147,  3, ' ', video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
+		charOutBg(147, 14, ' ', video.palette[PAL_GENBKG], video.palette[PAL_GENBKG]);
 
 		// draw load mode arrow
 
 		srcPtr = arrowBMP;
-		dstPtr = &pixelBuffer[(((11 * editor.diskop.mode) + 3) * SCREEN_W) + 148];
+		dstPtr = &video.frameBuffer[(((11 * editor.diskop.mode) + 3) * SCREEN_W) + 148];
 
 		for (uint32_t y = 0; y < 5; y++)
 		{
@@ -870,15 +862,15 @@
 	if (editor.ui.updatePackText)
 	{
 		editor.ui.updatePackText = false;
-		textOutBg(pixelBuffer, 120, 3, editor.diskop.modPackFlg ? "ON " : "OFF", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		textOutBg(120, 3, editor.diskop.modPackFlg ? "ON " : "OFF", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateSaveFormatText)
 	{
 		editor.ui.updateSaveFormatText = false;
-		     if (editor.diskop.smpSaveType == DISKOP_SMP_WAV) textOutBg(pixelBuffer, 120, 14, "WAV", palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		else if (editor.diskop.smpSaveType == DISKOP_SMP_IFF) textOutBg(pixelBuffer, 120, 14, "IFF", palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		else if (editor.diskop.smpSaveType == DISKOP_SMP_RAW) textOutBg(pixelBuffer, 120, 14, "RAW", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		     if (editor.diskop.smpSaveType == DISKOP_SMP_WAV) textOutBg(120, 14, "WAV", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		else if (editor.diskop.smpSaveType == DISKOP_SMP_IFF) textOutBg(120, 14, "IFF", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		else if (editor.diskop.smpSaveType == DISKOP_SMP_RAW) textOutBg(120, 14, "RAW", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 	}
 
 	if (editor.ui.updateDiskOpPathText)
@@ -892,7 +884,7 @@
 			if (tmpChar == '\0')
 				tmpChar = '_';
 
-			charOutBg(pixelBuffer, 24 + (i * FONT_CHAR_W), 25, tmpChar, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			charOutBg(24 + (i * FONT_CHAR_W), 25, tmpChar, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 }
@@ -910,7 +902,7 @@
 
 	if (!editor.ui.disablePosEd)
 	{
-		bgPixel = palette[PAL_BACKGRD];
+		bgPixel = video.palette[PAL_BACKGRD];
 
 		posEdPosition = modEntry->currOrder;
 		if (posEdPosition > modEntry->head.orderCount-1)
@@ -921,15 +913,12 @@
 		{
 			if (posEdPosition-(5-y) >= 0)
 			{
-				printThreeDecimalsBg(pixelBuffer, 128, 23+(y*6),
-					posEdPosition-(5-y), palette[PAL_QADSCP], palette[PAL_BACKGRD]);
-
-				printTwoDecimalsBg(pixelBuffer, 160, 23+(y*6), modEntry->head.order[posEdPosition-(5-y)],
-					palette[PAL_QADSCP], palette[PAL_BACKGRD]);
+				printThreeDecimalsBg(128, 23+(y*6), posEdPosition-(5-y), video.palette[PAL_QADSCP], video.palette[PAL_BACKGRD]);
+				printTwoDecimalsBg(160, 23+(y*6), modEntry->head.order[posEdPosition-(5-y)], video.palette[PAL_QADSCP], video.palette[PAL_BACKGRD]);
 			}
 			else
 			{
-				dstPtr = &pixelBuffer[((23+(y*6)) * SCREEN_W) + 128];
+				dstPtr = &video.frameBuffer[((23+(y*6)) * SCREEN_W) + 128];
 				for (y2 = 0; y2 < 5; y2++)
 				{
 					for (x = 0; x < FONT_CHAR_W*22; x++)
@@ -941,8 +930,8 @@
 		}
 
 		// middle
-		printThreeDecimalsBg(pixelBuffer, 128, 53, posEdPosition, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-		printTwoDecimalsBg(pixelBuffer, 160, 53, *editor.currPosEdPattDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+		printThreeDecimalsBg(128, 53, posEdPosition, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+		printTwoDecimalsBg(160, 53, *editor.currPosEdPattDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 		// bottom six
 		for (y = 0; y < 6; y++)
@@ -949,15 +938,12 @@
 		{
 			if (posEdPosition+y < modEntry->head.orderCount-1)
 			{
-				printThreeDecimalsBg(pixelBuffer, 128, 59+(y*6), posEdPosition+(y+1),
-					palette[PAL_QADSCP], palette[PAL_BACKGRD]);
-
-				printTwoDecimalsBg(pixelBuffer, 160, 59+(y*6), modEntry->head.order[posEdPosition+(y+1)],
-					palette[PAL_QADSCP], palette[PAL_BACKGRD]);
+				printThreeDecimalsBg(128, 59+(y*6), posEdPosition+(y+1), video.palette[PAL_QADSCP], video.palette[PAL_BACKGRD]);
+				printTwoDecimalsBg(160, 59+(y*6), modEntry->head.order[posEdPosition+(y+1)], video.palette[PAL_QADSCP], video.palette[PAL_BACKGRD]);
 			}
 			else
 			{
-				dstPtr = &pixelBuffer[((59+(y*6)) * SCREEN_W) + 128];
+				dstPtr = &video.frameBuffer[((59+(y*6)) * SCREEN_W) + 128];
 				for (y2 = 0; y2 < 5; y2++)
 				{
 					for (x = 0; x < FONT_CHAR_W*22; x++)
@@ -980,7 +966,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = posEdBMP;
-	dstPtr = &pixelBuffer[120];
+	dstPtr = &video.frameBuffer[120];
 
 	for (uint32_t y = 0; y < 99; y++)
 	{
@@ -999,7 +985,7 @@
 	if (editor.ui.diskOpScreenShown || editor.ui.posEdScreenShown)
 		return;
 
-	dstPtr = &pixelBuffer[(3 * SCREEN_W) + 310];
+	dstPtr = &video.frameBuffer[(3 * SCREEN_W) + 310];
 	for (uint32_t i = 0; i < AMIGA_VOICES; i++)
 	{
 		if (editor.muted[i])
@@ -1035,7 +1021,7 @@
 	editor.ui.disableVisualizer = true;
 
 	srcPtr = clearDialogBMP;
-	dstPtr = &pixelBuffer[(51 * SCREEN_W) + 160];
+	dstPtr = &video.frameBuffer[(51 * SCREEN_W) + 160];
 
 	for (uint32_t y = 0; y < 39; y++)
 	{
@@ -1085,7 +1071,7 @@
 	{
 		editor.ui.updatePatternData = false;
 		if (!editor.ui.samplerScreenShown)
-			redrawPattern(pixelBuffer);
+			redrawPattern();
 	}
 }
 
@@ -1096,13 +1082,13 @@
 	if (!editor.ui.editTextFlag)
 		return;
 
-	dstPtr = &pixelBuffer[((editor.ui.lineCurY - 1) * SCREEN_W) + (editor.ui.lineCurX - 4)];
+	dstPtr = &video.frameBuffer[((editor.ui.lineCurY - 1) * SCREEN_W) + (editor.ui.lineCurX - 4)];
 
 	if (editor.ui.editObject == PTB_PE_PATT)
 	{
 		// position editor text editing
 
-		pixel = palette[PAL_GENBKG2];
+		pixel = video.palette[PAL_GENBKG2];
 		for (uint32_t x = 0; x < 7; x++)
 			dstPtr[x] = pixel;
 
@@ -1114,7 +1100,7 @@
 	{
 		// all others
 
-		pixel = palette[PAL_GENBKG];
+		pixel = video.palette[PAL_GENBKG];
 		for (uint32_t y = 0; y < 2; y++)
 		{
 			for (uint32_t x = 0; x < 7; x++)
@@ -1132,8 +1118,8 @@
 	if (!editor.ui.editTextFlag)
 		return;
 
-	dstPtr = &pixelBuffer[((editor.ui.lineCurY - 1) * SCREEN_W) + (editor.ui.lineCurX - 4)];
-	pixel = palette[PAL_TEXTMARK];
+	dstPtr = &video.frameBuffer[((editor.ui.lineCurY - 1) * SCREEN_W) + (editor.ui.lineCurX - 4)];
+	pixel = video.palette[PAL_TEXTMARK];
 
 	for (uint32_t y = 0; y < 2; y++)
 	{
@@ -1144,14 +1130,62 @@
 	}
 }
 
-void updateDragBars(void)
+static void sendMouseButtonUpEvent(uint8_t button)
 {
-	if (editor.ui.sampleMarkingPos >= 0) samplerSamplePressed(MOUSE_BUTTON_HELD);
-	if (editor.ui.forceSampleDrag) samplerBarPressed(MOUSE_BUTTON_HELD);
-	if (editor.ui.forceSampleEdit) samplerEditSample(MOUSE_BUTTON_HELD);
-	if (editor.ui.forceVolDrag) volBoxBarPressed(MOUSE_BUTTON_HELD);
+	SDL_Event event;
+
+	memset(&event, 0, sizeof (event));
+
+	event.type = SDL_MOUSEBUTTONUP;
+	event.button.button = button;
+
+	SDL_PushEvent(&event);
 }
 
+void handleLastGUIObjectDown(void)
+{
+	bool testMouseButtonRelease = false;
+
+	if (editor.ui.sampleMarkingPos >= 0)
+	{
+		samplerSamplePressed(MOUSE_BUTTON_HELD);
+		testMouseButtonRelease = true;
+	}
+
+	if (editor.ui.forceSampleDrag)
+	{
+		samplerBarPressed(MOUSE_BUTTON_HELD);
+		testMouseButtonRelease = true;
+	}
+
+	if (editor.ui.forceSampleEdit)
+	{
+		samplerEditSample(MOUSE_BUTTON_HELD);
+		testMouseButtonRelease = true;
+	}
+
+	if (editor.ui.forceVolDrag)
+	{
+		volBoxBarPressed(MOUSE_BUTTON_HELD);
+		testMouseButtonRelease = true;
+	}
+
+	/* Hack to send "mouse button up" events if we released the mouse button(s)
+	** outside of the window...
+	*/
+	if (testMouseButtonRelease)
+	{
+		if (mouse.x < 0 || mouse.x >= SCREEN_W || mouse.y < 0 || mouse.y >= SCREEN_H)
+		{
+			if (mouse.leftButtonPressed && !(mouse.buttonState & SDL_BUTTON_LMASK))
+				sendMouseButtonUpEvent(SDL_BUTTON_LEFT);
+
+			if (mouse.rightButtonPressed && !(mouse.buttonState & SDL_BUTTON_RMASK))
+				sendMouseButtonUpEvent(SDL_BUTTON_RIGHT);
+		}
+	}
+}
+
 void updateVisualizer(void)
 {
 	const uint32_t *srcPtr;
@@ -1170,11 +1204,11 @@
 	{
 		// spectrum analyzer
 
-		dstPtr = &pixelBuffer[(59 * SCREEN_W) + 129];
+		dstPtr = &video.frameBuffer[(59 * SCREEN_W) + 129];
 		for (uint32_t i = 0; i < SPECTRUM_BAR_NUM; i++)
 		{
 			srcPtr = spectrumAnaBMP;
-			pixel = palette[PAL_GENBKG];
+			pixel = video.palette[PAL_GENBKG];
 
 			tmpVol = editor.spectrumVolumes[i];
 			if (tmpVol > SPECTRUM_BAR_HEIGHT)
@@ -1206,7 +1240,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = &trackerFrameBMP[(44 * SCREEN_W) + 120];
-	dstPtr = &pixelBuffer[(44 * SCREEN_W) + 120];
+	dstPtr = &video.frameBuffer[(44 * SCREEN_W) + 120];
 
 	for (uint32_t y = 0; y < 55; y++)
 	{
@@ -1226,7 +1260,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = spectrumVisualsBMP;
-	dstPtr = &pixelBuffer[(44 * SCREEN_W) + 120];
+	dstPtr = &video.frameBuffer[(44 * SCREEN_W) + 120];
 
 	for (uint32_t y = 0; y < 55; y++)
 	{
@@ -1247,7 +1281,7 @@
 		return;
 
 	srcPtr = aboutScreenBMP;
-	dstPtr = &pixelBuffer[(44 * SCREEN_W) + 120];
+	dstPtr = &video.frameBuffer[(44 * SCREEN_W) + 120];
 
 	for (uint32_t y = 0; y < 55; y++)
 	{
@@ -1261,7 +1295,7 @@
 
 	sprintf(verString, "v%s", PROG_VER_STR);
 	verStringX = 260 + (((63 - ((uint32_t)strlen(verString) * (FONT_CHAR_W - 1))) + 1) / 2);
-	textOutTight(pixelBuffer, verStringX, 67, verString, palette[PAL_GENBKG2]);
+	textOutTight(verStringX, 67, verString, video.palette[PAL_GENBKG2]);
 }
 
 void renderEditOpMode(void)
@@ -1297,7 +1331,7 @@
 
 	// render it...
 
-	dstPtr = &pixelBuffer[(47 * SCREEN_W) + 310];
+	dstPtr = &video.frameBuffer[(47 * SCREEN_W) + 310];
 	for (uint32_t y = 0; y < 6; y++)
 	{
 		for (uint32_t x = 0; x < 7; x++)
@@ -1324,7 +1358,7 @@
 	}
 
 	// render background
-	dstPtr = &pixelBuffer[(44 * SCREEN_W) + 120];
+	dstPtr = &video.frameBuffer[(44 * SCREEN_W) + 120];
 	for (uint32_t y = 0; y < 55; y++)
 	{
 		memcpy(dstPtr, srcPtr, 200 * sizeof (int32_t));
@@ -1338,11 +1372,11 @@
 	// render text and content
 	if (editor.ui.editOpScreen == 0)
 	{
-		textOut(pixelBuffer, 128, 47, "  TRACK      PATTERN  ", palette[PAL_GENTXT]);
+		textOut(128, 47, "  TRACK      PATTERN  ", video.palette[PAL_GENTXT]);
 	}
 	else if (editor.ui.editOpScreen == 1)
 	{
-		textOut(pixelBuffer, 128, 47, "  RECORD     SAMPLES  ", palette[PAL_GENTXT]);
+		textOut(128, 47, "  RECORD     SAMPLES  ", video.palette[PAL_GENTXT]);
 
 		editor.ui.updateRecordText = true;
 		editor.ui.updateQuantizeText = true;
@@ -1354,8 +1388,8 @@
 	}
 	else if (editor.ui.editOpScreen == 2)
 	{
-		textOut(pixelBuffer, 128, 47, "    SAMPLE EDITOR     ", palette[PAL_GENTXT]);
-		charOut(pixelBuffer, 272, 91, '%', palette[PAL_GENTXT]); // for Volume text
+		textOut(128, 47, "    SAMPLE EDITOR     ", video.palette[PAL_GENTXT]);
+		charOut(272, 91, '%', video.palette[PAL_GENTXT]); // for Volume text
 
 		editor.ui.updatePosText = true;
 		editor.ui.updateModText = true;
@@ -1363,7 +1397,7 @@
 	}
 	else if (editor.ui.editOpScreen == 3)
 	{
-		textOut(pixelBuffer, 128, 47, " SAMPLE CHORD EDITOR  ", palette[PAL_GENTXT]);
+		textOut(128, 47, " SAMPLE CHORD EDITOR  ", video.palette[PAL_GENTXT]);
 
 		editor.ui.updateLengthText = true;
 		editor.ui.updateNote1Text = true;
@@ -1379,7 +1413,7 @@
 	uint32_t *dstPtr;
 
 	srcPtr = mod2wavBMP;
-	dstPtr = &pixelBuffer[(27 * SCREEN_W) + 64];
+	dstPtr = &video.frameBuffer[(27 * SCREEN_W) + 64];
 
 	for (uint32_t y = 0; y < 48; y++)
 	{
@@ -1431,9 +1465,9 @@
 				percent = 100;
 
 			barLength = ((percent * 180) + 50) / 100;
-			dstPtr = &pixelBuffer[(42 * SCREEN_W) + 70];
-			pixel = palette[PAL_GENBKG2];
-			bgPixel = palette[PAL_BORDER];
+			dstPtr = &video.frameBuffer[(42 * SCREEN_W) + 70];
+			pixel = video.palette[PAL_GENBKG2];
+			bgPixel = video.palette[PAL_BORDER];
 
 			for (int32_t y = 0; y < 11; y++)
 			{
@@ -1450,13 +1484,13 @@
 			}
 
 			// render percentage
-			pixel = palette[PAL_GENTXT];
+			pixel = video.palette[PAL_GENTXT];
 			if (percent > 99)
-				printThreeDecimals(pixelBuffer, 144, 45, percent, pixel);
+				printThreeDecimals(144, 45, percent, pixel);
 			else
-				printTwoDecimals(pixelBuffer, 152, 45, percent, pixel);
+				printTwoDecimals(152, 45, percent, pixel);
 
-			charOut(pixelBuffer, 168, 45, '%', pixel);
+			charOut(168, 45, '%', pixel);
 		}
 	}
 }
@@ -1471,44 +1505,43 @@
 		if (editor.ui.updateRecordText)
 		{
 			editor.ui.updateRecordText = false;
-			textOutBg(pixelBuffer, 176, 58, (editor.recordMode == RECORD_PATT) ? "PATT" : "SONG",
-				palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			textOutBg(176, 58, (editor.recordMode == RECORD_PATT) ? "PATT" : "SONG", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateQuantizeText)
 		{
 			editor.ui.updateQuantizeText = false;
-			printTwoDecimalsBg(pixelBuffer, 192, 69, *editor.quantizeValueDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoDecimalsBg(192, 69, *editor.quantizeValueDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateMetro1Text)
 		{
 			editor.ui.updateMetro1Text = false;
-			printTwoDecimalsBg(pixelBuffer, 168, 80, *editor.metroSpeedDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoDecimalsBg(168, 80, *editor.metroSpeedDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateMetro2Text)
 		{
 			editor.ui.updateMetro2Text = false;
-			printTwoDecimalsBg(pixelBuffer, 192, 80, *editor.metroChannelDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoDecimalsBg(192, 80, *editor.metroChannelDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateFromText)
 		{
 			editor.ui.updateFromText = false;
-			printTwoHexBg(pixelBuffer, 264, 80, *editor.sampleFromDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoHexBg(264, 80, *editor.sampleFromDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateKeysText)
 		{
 			editor.ui.updateKeysText = false;
-			textOutBg(pixelBuffer, 160, 91, editor.multiFlag ? "MULTI " : "SINGLE", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			textOutBg(160, 91, editor.multiFlag ? "MULTI " : "SINGLE", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateToText)
 		{
 			editor.ui.updateToText = false;
-			printTwoHexBg(pixelBuffer, 264, 91, *editor.sampleToDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printTwoHexBg(264, 91, *editor.sampleToDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 	else if (editor.ui.editOpScreen == 2)
@@ -1518,12 +1551,12 @@
 			editor.ui.updateMixText = false;
 			if (editor.mixFlag)
 			{
-				textOutBg(pixelBuffer, 128, 47, editor.mixText, palette[PAL_GENTXT], palette[PAL_GENBKG]);
-				textOutBg(pixelBuffer, 248, 47, "  ", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(128, 47, editor.mixText, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+				textOutBg(248, 47, "  ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			}
 			else
 			{
-				textOutBg(pixelBuffer, 128, 47, "    SAMPLE EDITOR     ", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(128, 47, "    SAMPLE EDITOR     ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			}
 		}
 
@@ -1530,26 +1563,26 @@
 		if (editor.ui.updatePosText)
 		{
 			editor.ui.updatePosText = false;
-			printFourHexBg(pixelBuffer, 248, 58, *editor.samplePosDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printFourHexBg(248, 58, *editor.samplePosDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateModText)
 		{
 			editor.ui.updateModText = false;
-			printThreeDecimalsBg(pixelBuffer, 256, 69,
+			printThreeDecimalsBg(256, 69,
 				(editor.modulateSpeed < 0) ? (0 - editor.modulateSpeed) : editor.modulateSpeed,
-				palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 
 			if (editor.modulateSpeed < 0)
-				charOutBg(pixelBuffer, 248, 69, '-', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				charOutBg(248, 69, '-', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				charOutBg(pixelBuffer, 248, 69, ' ', palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				charOutBg(248, 69, ' ', video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateVolText)
 		{
 			editor.ui.updateVolText = false;
-			printThreeDecimalsBg(pixelBuffer, 248, 91, *editor.sampleVolDisp, palette[PAL_GENTXT], palette[PAL_GENBKG]);
+			printThreeDecimalsBg(248, 91, *editor.sampleVolDisp, video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 	else if (editor.ui.editOpScreen == 3)
@@ -1559,17 +1592,17 @@
 			editor.ui.updateLengthText = false;
 
 			// clear background
-			textOutBg(pixelBuffer, 168, 91, "    ", palette[PAL_GENTXT], palette[PAL_GENBKG]);
-			charOut(pixelBuffer, 198, 91,    ':', palette[PAL_GENBKG]);
+			textOutBg(168, 91, "    ", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
+			charOut(198, 91,    ':', video.palette[PAL_GENBKG]);
 
 			if (modEntry->samples[editor.currSample].loopLength > 2 || modEntry->samples[editor.currSample].loopStart >= 2)
 			{
-				textOut(pixelBuffer, 168, 91, "LOOP", palette[PAL_GENTXT]);
+				textOut(168, 91, "LOOP", video.palette[PAL_GENTXT]);
 			}
 			else
 			{
-				printFourHex(pixelBuffer, 168, 91, *editor.chordLengthDisp, palette[PAL_GENTXT]); // CHORD MAX LENGTH
-				charOut(pixelBuffer, 198, 91, (editor.chordLengthMin) ? '.' : ':', palette[PAL_GENTXT]); // MIN/MAX FLAG
+				printFourHex(168, 91, *editor.chordLengthDisp, video.palette[PAL_GENTXT]); // chord max length
+				charOut(198, 91, (editor.chordLengthMin) ? '.' : ':', video.palette[PAL_GENTXT]); // min/max flag
 			}
 		}
 
@@ -1577,10 +1610,10 @@
 		{
 			editor.ui.updateNote1Text = false;
 			if (editor.note1 > 35)
-				textOutBg(pixelBuffer, 256, 58, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 58, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				textOutBg(pixelBuffer, 256, 58, ptConfig.accidental ? noteNames2[editor.note1] : noteNames1[editor.note1],
-					palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 58, config.accidental ? noteNames2[editor.note1] : noteNames1[editor.note1],
+					video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateNote2Text)
@@ -1587,10 +1620,10 @@
 		{
 			editor.ui.updateNote2Text = false;
 			if (editor.note2 > 35)
-				textOutBg(pixelBuffer, 256, 69, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 69, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				textOutBg(pixelBuffer, 256, 69, ptConfig.accidental ? noteNames2[editor.note2] : noteNames1[editor.note2],
-					palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 69, config.accidental ? noteNames2[editor.note2] : noteNames1[editor.note2],
+					video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 
 		if (editor.ui.updateNote3Text)
@@ -1597,10 +1630,10 @@
 		{
 			editor.ui.updateNote3Text = false;
 			if (editor.note3 > 35)
-				textOutBg(pixelBuffer, 256, 80, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 80, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				textOutBg(pixelBuffer, 256, 80, ptConfig.accidental ? noteNames2[editor.note3] : noteNames1[editor.note3],
-					palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 80, config.accidental ? noteNames2[editor.note3] : noteNames1[editor.note3],
+					video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 			
 		if (editor.ui.updateNote4Text)
@@ -1607,10 +1640,10 @@
 		{
 			editor.ui.updateNote4Text = false;
 			if (editor.note4 > 35)
-				textOutBg(pixelBuffer, 256, 91, "---", palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 91, "---", video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 			else
-				textOutBg(pixelBuffer, 256, 91, ptConfig.accidental ? noteNames2[editor.note4] : noteNames1[editor.note4],
-					palette[PAL_GENTXT], palette[PAL_GENBKG]);
+				textOutBg(256, 91, config.accidental ? noteNames2[editor.note4] : noteNames1[editor.note4],
+					video.palette[PAL_GENTXT], video.palette[PAL_GENBKG]);
 		}
 	}
 }
@@ -1640,14 +1673,14 @@
 	if (editor.ui.samplerScreenShown)
 	{
 		if (!editor.ui.diskOpScreenShown)
-			memcpy(pixelBuffer, trackerFrameBMP, 320 * 121 * sizeof (int32_t));
+			memcpy(video.frameBuffer, trackerFrameBMP, 320 * 121 * sizeof (int32_t));
 	}
 	else
 	{
 		if (!editor.ui.diskOpScreenShown)
-			memcpy(pixelBuffer, trackerFrameBMP, 320 * 255 * sizeof (int32_t));
+			memcpy(video.frameBuffer, trackerFrameBMP, 320 * 255 * sizeof (int32_t));
 		else
-			memcpy(&pixelBuffer[121 * SCREEN_W], &trackerFrameBMP[121 * SCREEN_W], 320 * 134 * sizeof (int32_t));
+			memcpy(&video.frameBuffer[121 * SCREEN_W], &trackerFrameBMP[121 * SCREEN_W], 320 * 134 * sizeof (int32_t));
 
 		editor.ui.updateSongBPM = true;
 		editor.ui.updateCurrPattText = true;
@@ -1665,14 +1698,14 @@
 		editor.ui.updateSongLength = true;
 
 		// zeroes (can't integrate zeroes in the graphics, the palette entry is above the 2-bit range)
-		charOut(pixelBuffer, 64,  3, '0', palette[PAL_GENTXT]);
-		textOut(pixelBuffer, 64, 14, "00", palette[PAL_GENTXT]);
+		charOut(64,  3, '0', video.palette[PAL_GENTXT]);
+		textOut(64, 14, "00", video.palette[PAL_GENTXT]);
 
 		if (!editor.isWAVRendering)
 		{
-			charOut(pixelBuffer, 64, 25, '0', palette[PAL_GENTXT]);
-			textOut(pixelBuffer, 64, 47, "00", palette[PAL_GENTXT]);
-			textOut(pixelBuffer, 64, 58, "00", palette[PAL_GENTXT]);
+			charOut(64, 25, '0', video.palette[PAL_GENTXT]);
+			textOut(64, 47, "00", video.palette[PAL_GENTXT]);
+			textOut(64, 58, "00", video.palette[PAL_GENTXT]);
 		}
 
 		if (editor.ui.posEdScreenShown)
@@ -2167,7 +2200,7 @@
 	uint16_t pixel12;
 	uint32_t i, j, x, y, pixel24;
 
-	pixel24 = palette[PAL_PATCURSOR];
+	pixel24 = video.palette[PAL_PATCURSOR];
 	for (y = 0; y < 14; y++)
 	{
 		// top two rows have a lighter color
@@ -2202,7 +2235,7 @@
 			patternCursorBMP[(y * 11) + 0] = pixel24;
 
 			for (x = 1; x < 10; x++)
-				patternCursorBMP[(y * 11) + x] = palette[PAL_COLORKEY];
+				patternCursorBMP[(y * 11) + x] = video.palette[PAL_COLORKEY];
 
 			patternCursorBMP[(y * 11) + 10] = pixel24;
 		}
@@ -2299,7 +2332,7 @@
 		vuMeterBMP[(i * 10) + 9] = pixel24;
 	}
 
-	for (i = 0; i < 30; i++) arrowBMP[i] = palette[arrowPaletteBMP[i]];
+	for (i = 0; i < 30; i++) arrowBMP[i] = video.palette[arrowPaletteBMP[i]];
 	for (i = 0; i < 64; i++) samplingPosBMP[i] = samplingPosBMP[i];
 	for (i = 0; i < 512; i++) loopPinsBMP[i] = loopPinsBMP[i];
 }
@@ -2379,19 +2412,19 @@
 	{
 		byteIn = (tmpBuffer[i] & 0xC0) >> 6;
 		assert(byteIn < PALETTE_NUM);
-		dst[(i * 4) + 0] = palette[byteIn];
+		dst[(i * 4) + 0] = video.palette[byteIn];
 
 		byteIn = (tmpBuffer[i] & 0x30) >> 4;
 		assert(byteIn < PALETTE_NUM);
-		dst[(i * 4) + 1] = palette[byteIn];
+		dst[(i * 4) + 1] = video.palette[byteIn];
 
 		byteIn = (tmpBuffer[i] & 0x0C) >> 2;
 		assert(byteIn < PALETTE_NUM);
-		dst[(i * 4) + 2] = palette[byteIn];
+		dst[(i * 4) + 2] = video.palette[byteIn];
 
 		byteIn = (tmpBuffer[i] & 0x03) >> 0;
 		assert(byteIn < PALETTE_NUM);
-		dst[(i * 4) + 3] = palette[byteIn];
+		dst[(i * 4) + 3] = video.palette[byteIn];
 	}
 
 	free(tmpBuffer);
@@ -2440,10 +2473,10 @@
 
 void videoClose(void)
 {
-	SDL_DestroyTexture(texture);
-	SDL_DestroyRenderer(renderer);
-	SDL_DestroyWindow(window);
-	free(pixelBuffer);
+	SDL_DestroyTexture(video.texture);
+	SDL_DestroyRenderer(video.renderer);
+	SDL_DestroyWindow(video.window);
+	free(video.frameBufferUnaligned);
 }
 
 void setupSprites(void)
@@ -2459,7 +2492,7 @@
 
 	sprites[SPRITE_PATTERN_CURSOR].data = patternCursorBMP;
 	sprites[SPRITE_PATTERN_CURSOR].pixelType = SPRITE_TYPE_RGB;
-	sprites[SPRITE_PATTERN_CURSOR].colorKey = palette[PAL_COLORKEY];
+	sprites[SPRITE_PATTERN_CURSOR].colorKey = video.palette[PAL_COLORKEY];
 	sprites[SPRITE_PATTERN_CURSOR].w = 11;
 	sprites[SPRITE_PATTERN_CURSOR].h = 14;
 	hideSprite(SPRITE_PATTERN_CURSOR);
@@ -2466,7 +2499,7 @@
 
 	sprites[SPRITE_LOOP_PIN_LEFT].data = loopPinsBMP;
 	sprites[SPRITE_LOOP_PIN_LEFT].pixelType = SPRITE_TYPE_RGB;
-	sprites[SPRITE_LOOP_PIN_LEFT].colorKey = palette[PAL_COLORKEY];
+	sprites[SPRITE_LOOP_PIN_LEFT].colorKey = video.palette[PAL_COLORKEY];
 	sprites[SPRITE_LOOP_PIN_LEFT].w = 4;
 	sprites[SPRITE_LOOP_PIN_LEFT].h = 64;
 	hideSprite(SPRITE_LOOP_PIN_LEFT);
@@ -2473,7 +2506,7 @@
 
 	sprites[SPRITE_LOOP_PIN_RIGHT].data = &loopPinsBMP[4 * 64];
 	sprites[SPRITE_LOOP_PIN_RIGHT].pixelType = SPRITE_TYPE_RGB;
-	sprites[SPRITE_LOOP_PIN_RIGHT].colorKey = palette[PAL_COLORKEY];
+	sprites[SPRITE_LOOP_PIN_RIGHT].colorKey = video.palette[PAL_COLORKEY];
 	sprites[SPRITE_LOOP_PIN_RIGHT].w = 4;
 	sprites[SPRITE_LOOP_PIN_RIGHT].h = 64;
 	hideSprite(SPRITE_LOOP_PIN_RIGHT);
@@ -2480,7 +2513,7 @@
 
 	sprites[SPRITE_SAMPLING_POS_LINE].data = samplingPosBMP;
 	sprites[SPRITE_SAMPLING_POS_LINE].pixelType = SPRITE_TYPE_RGB;
-	sprites[SPRITE_SAMPLING_POS_LINE].colorKey = palette[PAL_COLORKEY];
+	sprites[SPRITE_SAMPLING_POS_LINE].colorKey = video.palette[PAL_COLORKEY];
 	sprites[SPRITE_SAMPLING_POS_LINE].w = 1;
 	sprites[SPRITE_SAMPLING_POS_LINE].h = 64;
 	hideSprite(SPRITE_SAMPLING_POS_LINE);
@@ -2509,7 +2542,7 @@
 
 void eraseSprites(void)
 {
-	int32_t sw, sh, srcPitch, dstPitch;
+	int32_t sx, sy, x, y, sw, sh, srcPitch, dstPitch;
 	const uint32_t *src32;
 	uint32_t *dst32;
 	sprite_t *s;
@@ -2517,26 +2550,43 @@
 	for (int32_t i = SPRITE_NUM-1; i >= 0; i--) // erasing must be done in reverse order
 	{
 		s = &sprites[i];
-		if (s->x >= SCREEN_W) // sprite is hidden, don't erase
+		if (s->x >= SCREEN_W || s->y >= SCREEN_H) // sprite is hidden, don't draw nor fill clear buffer
 			continue;
 
-		assert(s->x >= 0 && s->y >= 0 && s->refreshBuffer != NULL);
+		assert(s->refreshBuffer != NULL);
 
 		sw = s->w;
 		sh = s->h;
-		dst32 = &pixelBuffer[(s->y * SCREEN_W) + s->x];
+		sx = s->x;
+		sy = s->y;
+
+		// if x is negative, adjust variables
+		if (sx < 0)
+		{
+			sw += sx; // subtraction
+			sx = 0;
+		}
+
+		// if y is negative, adjust variables
+		if (sy < 0)
+		{
+			sh += sy; // subtraction
+			sy = 0;
+		}
+
+		dst32 = &video.frameBuffer[(sy * SCREEN_W) + sx];
 		src32 = s->refreshBuffer;
 
-		// handle xy clipping
-		if (s->y+sh >= SCREEN_H) sh = SCREEN_H - s->y;
-		if (s->x+sw >= SCREEN_W) sw = SCREEN_W - s->x;
+		// handle x/y clipping
+		if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
+		if (sy+sh >= SCREEN_H) sh = SCREEN_H - sy;
 
 		srcPitch = s->w - sw;
 		dstPitch = SCREEN_W - sw;
 
-		for (int32_t y = 0; y < sh; y++)
+		for (y = 0; y < sh; y++)
 		{
-			for (int32_t x = 0; x < sw; x++)
+			for (x = 0; x < sw; x++)
 				*dst32++ = *src32++;
 
 			src32 += srcPitch;
@@ -2550,10 +2600,9 @@
 void renderSprites(void)
 {
 	const uint8_t *src8;
-	int32_t x, y, sw, sh, srcPitch, dstPitch;
+	int32_t sx, sy, x, y, srcPtrBias, sw, sh, srcPitch, dstPitch;
 	const uint32_t *src32;
-	uint32_t *dst32, *clr32;
-	register uint32_t colorKey;
+	uint32_t *dst32, *clr32, colorKey;
 	sprite_t *s;
 
 	renderVuMeters(); // let's put it here even though it's not sprite-based
@@ -2566,19 +2615,39 @@
 		s->x = s->newX;
 		s->y = s->newY;
 
-		if (s->x >= SCREEN_W) // sprite is hidden, don't draw nor fill clear buffer
+		if (s->x >= SCREEN_W || s->y >= SCREEN_H) // sprite is hidden, don't draw nor fill clear buffer
 			continue;
 
-		assert(s->x >= 0 && s->y >= 0 && s->data != NULL && s->refreshBuffer != NULL);
+		assert(s->data != NULL && s->refreshBuffer != NULL);
 
 		sw = s->w;
 		sh = s->h;
-		dst32 = &pixelBuffer[(s->y * SCREEN_W) + s->x];
+		sx = s->x;
+		sy = s->y;
+		srcPtrBias = 0;
+
+		// if x is negative, adjust variables
+		if (sx < 0)
+		{
+			sw += sx; // subtraction
+			srcPtrBias += -sx;
+			sx = 0;
+		}
+
+		// if y is negative, adjust variables
+		if (sy < 0)
+		{
+			sh += sy; // subtraction
+			srcPtrBias += (-sy * s->w);
+			sy = 0;
+		}
+
+		dst32 = &video.frameBuffer[(sy * SCREEN_W) + sx];
 		clr32 = s->refreshBuffer;
 
-		// handle xy clipping
-		if (s->y+sh >= SCREEN_H) sh = SCREEN_H - s->y;
-		if (s->x+sw >= SCREEN_W) sw = SCREEN_W - s->x;
+		// handle x/y clipping
+		if (sx+sw >= SCREEN_W) sw = SCREEN_W - sx;
+		if (sy+sh >= SCREEN_H) sh = SCREEN_H - sy;
 
 		srcPitch = s->w - sw;
 		dstPitch = SCREEN_W - sw;
@@ -2587,7 +2656,7 @@
 		if (sprites[i].pixelType == SPRITE_TYPE_RGB)
 		{
 			// 24-bit RGB sprite
-			src32 = (uint32_t *)sprites[i].data;
+			src32 = ((uint32_t *)sprites[i].data) + srcPtrBias;
 			for (y = 0; y < sh; y++)
 			{
 				for (x = 0; x < sw; x++)
@@ -2608,7 +2677,7 @@
 		else
 		{
 			// 8-bit paletted sprite
-			src8 = (uint8_t *)sprites[i].data;
+			src8 = ((uint8_t *)sprites[i].data) + srcPtrBias;
 			for (y = 0; y < sh; y++)
 			{
 				for (x = 0; x < sw; x++)
@@ -2617,7 +2686,7 @@
 					if (*src8 != colorKey)
 					{
 						assert(*src8 < PALETTE_NUM);
-						*dst32 = palette[*src8];
+						*dst32 = video.palette[*src8];
 					}
 
 					dst32++;
@@ -2634,21 +2703,21 @@
 
 void flipFrame(void)
 {
-	uint32_t windowFlags = SDL_GetWindowFlags(window);
-
 	renderSprites();
-	SDL_UpdateTexture(texture, NULL, pixelBuffer, SCREEN_W * sizeof (int32_t));
-	SDL_RenderClear(renderer);
-	SDL_RenderCopy(renderer, texture, NULL, NULL);
-	SDL_RenderPresent(renderer);
+	SDL_UpdateTexture(video.texture, NULL, video.frameBuffer, SCREEN_W * sizeof (int32_t));
+	SDL_RenderClear(video.renderer);
+	SDL_RenderCopy(video.renderer, video.texture, NULL, NULL);
+	SDL_RenderPresent(video.renderer);
 	eraseSprites();
 
-	if (!editor.ui.vsync60HzPresent)
+	if (!video.vsync60HzPresent)
 	{
 		waitVBL(); // we have no VSync, do crude thread sleeping to sync to ~60Hz
 	}
 	else
 	{
+		uint32_t windowFlags = SDL_GetWindowFlags(video.window);
+
 		/* We have VSync, but it can unexpectedly get inactive in certain scenarios.
 		** We have to force thread sleeping (to ~60Hz) if so.
 		*/
@@ -2658,7 +2727,7 @@
 			waitVBL();
 #elif __unix__
 		// *NIX: VSync gets disabled in fullscreen mode (at least on some distros/systems). Let's add a fix:
-		if ((windowFlags & SDL_WINDOW_MINIMIZED) || editor.fullscreen)
+		if ((windowFlags & SDL_WINDOW_MINIMIZED) || video.fullscreen)
 			waitVBL();
 #else
 		if (windowFlags & SDL_WINDOW_MINIMIZED)
@@ -2670,20 +2739,18 @@
 void updateSpectrumAnalyzer(int8_t vol, int16_t period)
 {
 	const uint8_t maxHeight = SPECTRUM_BAR_HEIGHT + 1; // +1 because of audio latency - allows full height to be seen
-	int16_t scaledVol;
-	int32_t scaledNote;
+	int32_t scaledVol, scaledNote;
 
 	if (editor.ui.visualizerMode != VISUAL_SPECTRUM || vol <= 0)
 		return;
 
-	scaledVol = (vol * 256) / ((64 * 256) / (SPECTRUM_BAR_NUM+1)); // 64 = max sample vol
+	scaledVol = (vol * 24600L) >> 16; // scaledVol = (vol << 8) / 682
 
 	period = CLAMP(period, 113, 856);
 
-	// 856 = C-1 period, 113 = B-3 period
-	scaledNote = (856-113) - (period - 113);
+	scaledNote = 856 - period;
 	scaledNote *= scaledNote;
-	scaledNote /= ((856 - 113) * (856 - 113)) / (SPECTRUM_BAR_NUM-1);
+	scaledNote = ((int64_t)scaledNote * 171162) >> 32; // scaledNote /= 25093
 
 	// scaledNote now ranges 0..22, no need to clamp
 
@@ -2711,17 +2778,20 @@
 
 void sinkVisualizerBars(void)
 {
+	int32_t i;
+
 	// sink stuff @ 50Hz rate
 
-	const uint64_t _50HzCounterDelta = ((uint64_t)AMIGA_PAL_VBLANK_HZ << 32) / VBLANK_HZ;
+	static uint64_t counter50Hz;
+	const uint64_t counter50HzDelta = ((uint64_t)AMIGA_PAL_VBLANK_HZ << 32) / VBLANK_HZ;
 
-	_50HzCounter += _50HzCounterDelta; // 32.32 fixed-point counter
-	if (_50HzCounter > 0xFFFFFFFF)
+	counter50Hz += counter50HzDelta; // 32.32 fixed-point counter
+	if (counter50Hz > 0xFFFFFFFF)
 	{
-		_50HzCounter &= 0xFFFFFFFF;
+		counter50Hz &= 0xFFFFFFFF;
 
 		// sink VU-meters
-		for (uint32_t i = 0; i < AMIGA_VOICES; i++)
+		for (i = 0; i < AMIGA_VOICES; i++)
 		{
 			if (editor.vuMeterVolumes[i] > 0)
 				editor.vuMeterVolumes[i]--;
@@ -2728,7 +2798,7 @@
 		}
 
 		// sink "spectrum analyzer" bars
-		for (uint32_t i = 0; i < SPECTRUM_BAR_NUM; i++)
+		for (i = 0; i < SPECTRUM_BAR_NUM; i++)
 		{
 			if (editor.spectrumVolumes[i] > 0)
 				editor.spectrumVolumes[i]--;
@@ -2746,57 +2816,57 @@
 	float fXScale, fYScale;
 	SDL_DisplayMode dm;
 
-	di = SDL_GetWindowDisplayIndex(window);
+	di = SDL_GetWindowDisplayIndex(video.window);
 	if (di < 0)
 		di = 0; /* return display index 0 (default) on error */
 
 	SDL_GetDesktopDisplayMode(di, &dm);
-	editor.ui.displayW = dm.w;
-	editor.ui.displayH = dm.h;
+	video.displayW = dm.w;
+	video.displayH = dm.h;
 
-	if (editor.fullscreen)
+	if (video.fullscreen)
 	{
-		if (ptConfig.fullScreenStretch)
+		if (config.fullScreenStretch)
 		{
-			editor.ui.renderW = editor.ui.displayW;
-			editor.ui.renderH = editor.ui.displayH;
-			editor.ui.renderX = 0;
-			editor.ui.renderY = 0;
+			video.renderW = video.displayW;
+			video.renderH = video.displayH;
+			video.renderX = 0;
+			video.renderY = 0;
 		}
 		else
 		{
-			SDL_RenderGetScale(renderer, &fXScale, &fYScale);
+			SDL_RenderGetScale(video.renderer, &fXScale, &fYScale);
 
-			editor.ui.renderW = (int32_t)(SCREEN_W * fXScale);
-			editor.ui.renderH = (int32_t)(SCREEN_H * fYScale);
+			video.renderW = (int32_t)(SCREEN_W * fXScale);
+			video.renderH = (int32_t)(SCREEN_H * fYScale);
 
 #ifdef __APPLE__
 			// retina high-DPI hackery (SDL2 is bad at reporting actual rendering sizes on macOS w/ high-DPI)
-			SDL_GL_GetDrawableSize(window, &actualScreenW, &actualScreenH);
+			SDL_GL_GetDrawableSize(video.window, &actualScreenW, &actualScreenH);
 			SDL_GetDesktopDisplayMode(0, &dm);
 
-			dXUpscale = ((double)actualScreenW / editor.ui.displayW);
-			dYUpscale = ((double)actualScreenH / editor.ui.displayH);
+			dXUpscale = ((double)actualScreenW / video.displayW);
+			dYUpscale = ((double)actualScreenH / video.displayH);
 
 			// downscale back to correct sizes
-			if (dXUpscale != 0.0) editor.ui.renderW = (int32_t)(editor.ui.renderW / dXUpscale);
-			if (dYUpscale != 0.0) editor.ui.renderH = (int32_t)(editor.ui.renderH / dYUpscale);
+			if (dXUpscale != 0.0) video.renderW = (int32_t)(video.renderW / dXUpscale);
+			if (dYUpscale != 0.0) video.renderH = (int32_t)(video.renderH / dYUpscale);
 #endif
-			editor.ui.renderX = (editor.ui.displayW - editor.ui.renderW) / 2;
-			editor.ui.renderY = (editor.ui.displayH - editor.ui.renderH) / 2;
+			video.renderX = (video.displayW - video.renderW) >> 1;
+			video.renderY = (video.displayH - video.renderH) >> 1;
 		}
 	}
 	else
 	{
-		SDL_GetWindowSize(window, &editor.ui.renderW, &editor.ui.renderH);
+		SDL_GetWindowSize(video.window, &video.renderW, &video.renderH);
 
-		editor.ui.renderX = 0;
-		editor.ui.renderY = 0;
+		video.renderX = 0;
+		video.renderY = 0;
 	}
 
 	// for mouse cursor creation
-	editor.ui.xScale = (int32_t)((editor.ui.renderW / (double)SCREEN_W) + 0.5);
-	editor.ui.yScale = (int32_t)((editor.ui.renderH / (double)SCREEN_H) + 0.5);
+	video.xScale = (int32_t)((video.renderW * (1.0 / SCREEN_W)) + 0.5);
+	video.yScale = (int32_t)((video.renderH * (1.0 / SCREEN_H)) + 0.5);
 	createMouseCursors();
 }
 
@@ -2804,47 +2874,47 @@
 {
 	SDL_DisplayMode dm;
 
-	editor.fullscreen ^= 1;
-	if (editor.fullscreen)
+	video.fullscreen ^= 1;
+	if (video.fullscreen)
 	{
-		if (ptConfig.fullScreenStretch)
+		if (config.fullScreenStretch)
 		{
 			SDL_GetDesktopDisplayMode(0, &dm);
-			SDL_RenderSetLogicalSize(renderer, dm.w, dm.h);
+			SDL_RenderSetLogicalSize(video.renderer, dm.w, dm.h);
 		}
 		else
 		{
-			SDL_RenderSetLogicalSize(renderer, SCREEN_W, SCREEN_H);
+			SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
 		}
 
-		SDL_SetWindowSize(window, SCREEN_W, SCREEN_H);
-		SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
-		SDL_SetWindowGrab(window, SDL_TRUE);
+		SDL_SetWindowSize(video.window, SCREEN_W, SCREEN_H);
+		SDL_SetWindowFullscreen(video.window, SDL_WINDOW_FULLSCREEN_DESKTOP);
+		SDL_SetWindowGrab(video.window, SDL_TRUE);
 	}
 	else
 	{
-		SDL_SetWindowFullscreen(window, 0);
-		SDL_RenderSetLogicalSize(renderer, SCREEN_W, SCREEN_H);
-		SDL_SetWindowSize(window, SCREEN_W * ptConfig.videoScaleFactor, SCREEN_H * ptConfig.videoScaleFactor);
-		SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
-		SDL_SetWindowGrab(window, SDL_FALSE);
+		SDL_SetWindowFullscreen(video.window, 0);
+		SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
+		SDL_SetWindowSize(video.window, SCREEN_W * config.videoScaleFactor, SCREEN_H * config.videoScaleFactor);
+		SDL_SetWindowPosition(video.window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
+		SDL_SetWindowGrab(video.window, SDL_FALSE);
 	}
 
 	updateRenderSizeVars();
 	updateMouseScaling();
 
-	if (editor.fullscreen)
+	if (video.fullscreen)
 	{
-		input.mouse.setPosX = editor.ui.displayW / 2;
-		input.mouse.setPosY = editor.ui.displayH / 2;
+		mouse.setPosX = video.displayW >> 1;
+		mouse.setPosY = video.displayH >> 1;
 	}
 	else
 	{
-		input.mouse.setPosX = editor.ui.renderW / 2;
-		input.mouse.setPosY = editor.ui.renderH / 2;
+		mouse.setPosX = video.renderW >> 1;
+		mouse.setPosY = video.renderH >> 1;
 	}
 
-	input.mouse.setPosFlag = true;
+	mouse.setPosFlag = true;
 }
 
 bool setupVideo(void)
@@ -2853,8 +2923,8 @@
 	uint32_t rendererFlags;
 	SDL_DisplayMode dm;
 
-	screenW = SCREEN_W * ptConfig.videoScaleFactor;
-	screenH = SCREEN_H * ptConfig.videoScaleFactor;
+	screenW = SCREEN_W * config.videoScaleFactor;
+	screenH = SCREEN_H * config.videoScaleFactor;
 
 	rendererFlags = 0;
 
@@ -2868,38 +2938,38 @@
 	SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
 #endif
 
-	editor.ui.vsync60HzPresent = false;
-	if (!ptConfig.vsyncOff)
+	video.vsync60HzPresent = false;
+	if (!config.vsyncOff)
 	{
 		SDL_GetDesktopDisplayMode(0, &dm);
 		if (dm.refresh_rate >= 59 && dm.refresh_rate <= 61)
 		{
-			editor.ui.vsync60HzPresent = true;
+			video.vsync60HzPresent = true;
 			rendererFlags |= SDL_RENDERER_PRESENTVSYNC;
 		}
 	}
 
-	window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED,
+	video.window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED,
 		SDL_WINDOWPOS_CENTERED, screenW, screenH,
 		SDL_WINDOW_HIDDEN | SDL_WINDOW_ALLOW_HIGHDPI);
 
-	if (window == NULL)
+	if (video.window == NULL)
 	{
 		showErrorMsgBox("Couldn't create SDL window:\n%s", SDL_GetError());
 		return false;
 	}
 
-	renderer = SDL_CreateRenderer(window, -1, rendererFlags);
-	if (renderer == NULL)
+	video.renderer = SDL_CreateRenderer(video.window, -1, rendererFlags);
+	if (video.renderer == NULL)
 	{
-		if (editor.ui.vsync60HzPresent) // try again without vsync flag
+		if (video.vsync60HzPresent) // try again without vsync flag
 		{
-			editor.ui.vsync60HzPresent = false;
+			video.vsync60HzPresent = false;
 			rendererFlags &= ~SDL_RENDERER_PRESENTVSYNC;
-			renderer = SDL_CreateRenderer(window, -1, rendererFlags);
+			video.renderer = SDL_CreateRenderer(video.window, -1, rendererFlags);
 		}
 
-		if (renderer == NULL)
+		if (video.renderer == NULL)
 		{
 			showErrorMsgBox("Couldn't create SDL renderer:\n%s\n\n" \
 			                "Is your GPU (+ driver) too old?", SDL_GetError());
@@ -2907,18 +2977,18 @@
 		}
 	}
 
-	SDL_RenderSetLogicalSize(renderer, SCREEN_W, SCREEN_H);
+	SDL_RenderSetLogicalSize(video.renderer, SCREEN_W, SCREEN_H);
 
 #if SDL_PATCHLEVEL >= 5
-	SDL_RenderSetIntegerScale(renderer, SDL_TRUE);
+	SDL_RenderSetIntegerScale(video.renderer, SDL_TRUE);
 #endif
 
-	SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_NONE);
+	SDL_SetRenderDrawBlendMode(video.renderer, SDL_BLENDMODE_NONE);
 
 	SDL_SetHint("SDL_RENDER_SCALE_QUALITY", "nearest");
 
-	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_W, SCREEN_H);
-	if (texture == NULL)
+	video.texture = SDL_CreateTexture(video.renderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STREAMING, SCREEN_W, SCREEN_H);
+	if (video.texture == NULL)
 	{
 		showErrorMsgBox("Couldn't create %dx%d GPU texture:\n%s\n\n" \
 		                "Is your GPU (+ driver) too old?", SCREEN_W, SCREEN_H, SDL_GetError());
@@ -2925,20 +2995,23 @@
 		return false;
 	}
 
-	SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_NONE);
+	SDL_SetTextureBlendMode(video.texture, SDL_BLENDMODE_NONE);
 
 	// frame buffer used by SDL (for texture)
-	pixelBuffer = (uint32_t *)malloc(SCREEN_W * SCREEN_H * sizeof (int32_t));
-	if (pixelBuffer == NULL)
+	video.frameBufferUnaligned = (uint32_t *)MALLOC_PAD(SCREEN_W * SCREEN_H * sizeof (int32_t), 256);
+	if (video.frameBufferUnaligned == NULL)
 	{
 		showErrorMsgBox("Out of memory!");
 		return false;
 	}
 
+	// we want an aligned pointer
+	video.frameBuffer = (uint32_t *)ALIGN_PTR(video.frameBufferUnaligned, 256);
+
 	updateRenderSizeVars();
 	updateMouseScaling();
 
-	if (ptConfig.hwMouse)
+	if (config.hwMouse)
 		SDL_ShowCursor(SDL_TRUE);
 	else
 		SDL_ShowCursor(SDL_FALSE);
--- a/src/pt2_visuals.h
+++ b/src/pt2_visuals.h
@@ -68,7 +68,7 @@
 void updateCurrSample(void);
 void eraseSprites(void);
 void renderSprites(void);
-void updateDragBars(void);
+void handleLastGUIObjectDown(void);
 void invertRange(void);
 void updateCursorPos(void);
 void renderVuMeters(void);
--- a/vs2019_project/pt2-clone/pt2-clone.vcxproj
+++ b/vs2019_project/pt2-clone/pt2-clone.vcxproj
@@ -206,6 +206,7 @@
       <OpenMPSupport>false</OpenMPSupport>
       <LanguageStandard>stdcpplatest</LanguageStandard>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <Optimization>Disabled</Optimization>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>
@@ -247,6 +248,8 @@
       <OpenMPSupport>false</OpenMPSupport>
       <LanguageStandard>stdcpplatest</LanguageStandard>
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
+      <Optimization>Disabled</Optimization>
+      <OmitFramePointers>false</OmitFramePointers>
     </ClCompile>
     <Link>
       <SubSystem>Windows</SubSystem>