[Scummvm-git-logs] scummvm master -> 0b334f4579e90bb72a04972d0e83567129129714

mikrosk noreply at scummvm.org
Sat Aug 22 12:15:26 UTC 2026


This automated email contains information about 6 new commits which have been
pushed to the 'scummvm' repo located at https://api.github.com/repos/scummvm/scummvm .

Summary:
87d52b74e5 BACKENDS: ATARI: Don't write audio settings back to scummvm.ini
93fba2e972 BACKENDS: ATARI: Adjust audio latency
a232f869a4 BACKENDS: ATARI: Clamp at the end of mixing
d02ad6fe4a BACKENDS: ATARI: Add support for 16-bit mono
b7c1ff1f7a BACKENDS: ATARI: Rework the underrun algorithm
0b334f4579 BACKENDS: ATARI: Introduce SIDECART_OUTPUT for log messages


Commit: 87d52b74e590465f56d4b8e1c0b259a9447990d7
    https://github.com/scummvm/scummvm/commit/87d52b74e590465f56d4b8e1c0b259a9447990d7
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T21:56:29+10:00

Commit Message:
BACKENDS: ATARI: Don't write audio settings back to scummvm.ini

Basically user can enter PC frequencies only and not worry about exact
Falcon/TT values.

Changed paths:
    backends/mixer/atari/atari-mixer.cpp
    backends/platform/atari/readme.txt
    backends/platform/atari/readme.txt.in


diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index 52428b6a1d7..55a02ba39b8 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -128,16 +128,10 @@ void AtariMixerManager::init() {
 	_samples = obtained.samples;
 	_downsample = (obtained.format == USoundFormatSigned8);
 
-	ConfMan.setInt("output_rate", _outputRate, Common::ConfigManager::kApplicationDomain);
-	ConfMan.setInt("output_channels", _outputChannels, Common::ConfigManager::kApplicationDomain);
-	ConfMan.setInt("audio_buffer_size", _samples, Common::ConfigManager::kApplicationDomain);
-
 	debug("setting %d Hz mixing frequency (%d-bit, %s)",
 		  _outputRate, obtained.format == USoundFormatSigned8 ? 8 : 16, _outputChannels == 1 ? "mono" : "stereo");
 	debug("sample buffer size: %d", _samples);
 
-	ConfMan.flushToDisk();
-
 	_atariSampleBuffer = (byte*)Mxalloc(obtained.size * 2, MX_STRAM);
 	if (!_atariSampleBuffer)
 		error("Failed to allocate memory in ST RAM");
diff --git a/backends/platform/atari/readme.txt b/backends/platform/atari/readme.txt
index 2931b9cb076..aac1a64b41d 100644
--- a/backends/platform/atari/readme.txt
+++ b/backends/platform/atari/readme.txt
@@ -178,6 +178,12 @@ If you want to play with "audio_buffer_size", the rule of thumb is: (lag in ms)
 = (audio_buffer_size / output_rate) * 1000. But it's totally OK just to double
 the samples value to get rid of stuttering in a heavier game.
 
+Please note that unlike previous versions, these values will never be written
+back to scummvm.ini. This is beneficial if you want to switch between Falcon
+and TT or between Falcon with and without external DSP clock (as mentioned,
+DOS/Windows friendly values are automatically converted to a frequency which
+TT/Falcon supports).
+
 "gaudio" debug channel: used for optimising sample playback (where
 available). It prints input and output sample format as well as the name of the
 converter used. See below for details.
diff --git a/backends/platform/atari/readme.txt.in b/backends/platform/atari/readme.txt.in
index d74fa7cebbd..377aaf0b232 100644
--- a/backends/platform/atari/readme.txt.in
+++ b/backends/platform/atari/readme.txt.in
@@ -178,6 +178,12 @@ If you want to play with "audio_buffer_size", the rule of thumb is: (lag in ms)
 = (audio_buffer_size / output_rate) * 1000. But it's totally OK just to double
 the samples value to get rid of stuttering in a heavier game.
 
+Please note that unlike previous versions, these values will never be written
+back to scummvm.ini. This is beneficial if you want to switch between Falcon
+and TT or between Falcon with and without external DSP clock (as mentioned,
+DOS/Windows friendly values are automatically converted to a frequency which
+TT/Falcon supports).
+
 "gaudio" debug channel: used for optimising sample playback (where
 available). It prints input and output sample format as well as the name of the
 converter used. See below for details.


Commit: 93fba2e972277117c792f1251466feb53f571544
    https://github.com/scummvm/scummvm/commit/93fba2e972277117c792f1251466feb53f571544
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T21:56:29+10:00

Commit Message:
BACKENDS: ATARI: Adjust audio latency

There was a bug in Lite, too: it set twice as big latency against Full.

Changed paths:
    backends/mixer/atari/atari-mixer.cpp


diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index 55a02ba39b8..26ec9c32adc 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -38,12 +38,13 @@
 
 #ifdef DISABLE_FANCY_THEMES
 #define DEFAULT_OUTPUT_RATE 11025
+#define DEFAULT_SAMPLES 512	// 2 * 46ms (42ms at 12292 Hz) latency
 #else
 #define DEFAULT_OUTPUT_RATE 22050
+#define DEFAULT_SAMPLES 1024	// 2 * 46ms (42ms at 24585 Hz) latency
 #endif
 
 #define DEFAULT_OUTPUT_CHANNELS 2
-#define DEFAULT_SAMPLES 2048	// 83ms
 
 static USoundContext usoundContext;
 


Commit: a232f869a479c40c20c6a6044eaced448e28586b
    https://github.com/scummvm/scummvm/commit/a232f869a479c40c20c6a6044eaced448e28586b
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T22:11:42+10:00

Commit Message:
BACKENDS: ATARI: Clamp at the end of mixing

Also document the optimization already merged: not mixing of muted
channels.

Changed paths:
    backends/mixer/atari/atari-mixer.cpp
    backends/mixer/atari/atari-mixer.h
    backends/platform/atari/readme.txt
    backends/platform/atari/readme.txt.in


diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index 26ec9c32adc..cab782e0e26 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -100,8 +100,8 @@ AtariMixerManager::~AtariMixerManager() {
 	Mfree(_atariSampleBuffer);
 	_atariSampleBuffer = _atariPhysicalSampleBuffer = _atariLogicalSampleBuffer = nullptr;
 
-	delete[] _samplesBuf;
-	_samplesBuf = nullptr;
+	delete[] _sampleBuf;
+	_sampleBuf = nullptr;
 }
 
 void AtariMixerManager::init() {
@@ -149,9 +149,10 @@ void AtariMixerManager::init() {
 	// enable and mix both sources (ADC and connection matrix) to the output
 	Soundcmd(ADDERIN, MATIN|ADCIN);
 
-	_samplesBuf = new uint8[_samples * _outputChannels * 2];	// always 16-bit
+	_sampleBufSize = _samples * _outputChannels * 4;	// always 32-bit
+	_sampleBuf = new uint8[_sampleBufSize];
 
-	_mixer = new Audio::MixerImpl(_outputRate, _outputChannels == 2, _samples);
+	_mixer = new Audio::MixerImpl(_outputRate, _outputChannels == 2, _samples, 4, false);
 	_mixer->setReady(true);
 
 	resumeAudio();
@@ -201,7 +202,7 @@ void AtariMixerManager::update() {
 
 	if (muted || endOfPlayback) {
 		endOfPlayback = false;
-		processed = _mixer->mixCallback(_samplesBuf, _samples * _outputChannels * 2);
+		processed = _mixer->mixCallback(_sampleBuf, _sampleBufSize);
 	}
 
 	if (processed > 0) {
@@ -210,42 +211,54 @@ void AtariMixerManager::update() {
 		_atariLogicalSampleBuffer = tmp;
 
 		if (_downsample) {
-			// use the trick with move.b (a7)+,dx which skips two bytes at once
-			// basically supplying move.w (src)+,dx; asr.w #8,dx; move.b dx,(dst)+
 			__asm__ volatile(
-				"	move.l	%%a7,%%d0\n"
-				"	move.l	%0,%%a7\n"
-				"	moveq	#0x0f,%%d1\n"
-				"	and.l	%2,%%d1\n"
-				"	neg.l	%%d1\n"
-				"	lsr.l	#4,%2\n"
-				"	jmp		(2f,%%pc,%%d1.l*2)\n"
-				"1:	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"	move.b	(%%a7)+,(%1)+\n"
-				"2:	dbra	%2,1b\n"
-				"	move.l	%%d0,%%a7\n"
+				"	move.l	#32768,%%d2\n"
+				"	move.l	#65535,%%d3\n"
+				"	subq.l	#1,%2\n"
+				"1:	move.l	(%0)+,%%d0\n"
+				"	move.l	%%d0,%%d1\n"
+				"	add.l	%%d2,%%d1\n"
+				"	cmp.l	%%d3,%%d1\n"
+				"	bhi.b	3f\n"
+				"2:	asr.l	#8,%%d0\n"	// TODO: tweak (there were reports that >> 8 is too quiet)
+				"	move.b	%%d0,(%1)+\n"
+				"	dbra	%2,1b\n"
+				"	bra.b	4f\n"
+				"3:	tst.l	%%d0\n"
+				"	spl		%%d0\n"
+				"	ext.w	%%d0\n"
+				"	add.w	%%d2,%%d0\n"
+				"	bra.b	2b\n"
+				"4:\n"
 				: // outputs
-				: "g"(_samplesBuf), "a"(_atariPhysicalSampleBuffer), "d"(processed * _outputChannels * 2/2) // inputs
-				: "d0", "d1", "cc" AND_MEMORY
+				: "a"(_sampleBuf), "a"(_atariPhysicalSampleBuffer), "d"(processed * _outputChannels) // inputs
+				: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
 				);
 			memset(_atariPhysicalSampleBuffer + processed * _outputChannels * 2/2, 0, (_samples - processed) * _outputChannels * 2/2);
 			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * _outputChannels * 2/2);
 		} else {
-			memcpy(_atariPhysicalSampleBuffer, _samplesBuf, processed * _outputChannels * 2);
+			__asm__ volatile(
+				"	move.l	#32768,%%d2\n"
+				"	move.l	#65535,%%d3\n"
+				"	subq.l	#1,%2\n"
+				"1:	move.l	(%0)+,%%d0\n"
+				"	move.l	%%d0,%%d1\n"
+				"	add.l	%%d2,%%d1\n"
+				"	cmp.l	%%d3,%%d1\n"
+				"	bhi.b	3f\n"
+				"2:	move.w	%%d0,(%1)+\n"
+				"	dbra	%2,1b\n"
+				"	bra.b	4f\n"
+				"3:	tst.l	%%d0\n"
+				"	spl		%%d0\n"
+				"	ext.w	%%d0\n"
+				"	add.w	%%d2,%%d0\n"
+				"	bra.b	2b\n"
+				"4:\n"
+				: // outputs
+				: "a"(_sampleBuf), "a"(_atariPhysicalSampleBuffer), "d"(processed * _outputChannels) // inputs
+				: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
+				);
 			memset(_atariPhysicalSampleBuffer + processed * _outputChannels * 2, 0, (_samples - processed) * _outputChannels * 2);
 			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * _outputChannels * 2);
 		}
diff --git a/backends/mixer/atari/atari-mixer.h b/backends/mixer/atari/atari-mixer.h
index 6e3e40af730..03a27247d43 100644
--- a/backends/mixer/atari/atari-mixer.h
+++ b/backends/mixer/atari/atari-mixer.h
@@ -46,7 +46,8 @@ private:
 	int _outputRate = 0;
 	int _outputChannels = 0;
 	int _samples = 0;
-	uint8 *_samplesBuf = nullptr;
+	int _sampleBufSize = 0;
+	byte *_sampleBuf = nullptr;
 
 	byte *_atariSampleBuffer = nullptr;
 	byte *_atariPhysicalSampleBuffer = nullptr;
diff --git a/backends/platform/atari/readme.txt b/backends/platform/atari/readme.txt
index aac1a64b41d..4acf8ec410c 100644
--- a/backends/platform/atari/readme.txt
+++ b/backends/platform/atari/readme.txt
@@ -408,15 +408,20 @@ Mute vs. "No music"
 
 Currently ScummVM requires each backend to mix samples, even though they may
 contain muted output (i.e. zeroes). This is because the progression of sample
-playback tells ScummVM how much time has passed in e.g. an animation.
+playback tells ScummVM how much time has passed in e.g. an animation. However,
+an optimisation kicks in for muted channels: the input stream is still loaded
+and decoded but it is not mixed which alone leads to an enormous performance
+boost!
 
 "No music" means using the null audio plugin which prevents generating any MIDI
 music (and therefore avoiding the expensive synthesis emulation) but beware, it
-doesn't affect CD (*.wav) playback at all! Same applies for speech and sfx.
+doesn't affect CD (*.wav) playback at all! Same applies for speech and sfx. So
+mute one or all of those if frame rate drops noticeably.
 
 The least amount of cycles is spent when:
 - "No music" as "Preferred device": This prevents MIDI/OPL synthesis of any
   kind.
+- "Mute all" in "Volume" setting.
 - "output_rate" set to a DOS/Windows compatible value (default). Even if game
   uses 22050 Hz and your Falcon supports 22050 Hz, it is always faster to use
   11025 Hz!
diff --git a/backends/platform/atari/readme.txt.in b/backends/platform/atari/readme.txt.in
index 377aaf0b232..41cd1700f33 100644
--- a/backends/platform/atari/readme.txt.in
+++ b/backends/platform/atari/readme.txt.in
@@ -408,15 +408,20 @@ Mute vs. "No music"
 
 Currently ScummVM requires each backend to mix samples, even though they may
 contain muted output (i.e. zeroes). This is because the progression of sample
-playback tells ScummVM how much time has passed in e.g. an animation.
+playback tells ScummVM how much time has passed in e.g. an animation. However,
+an optimisation kicks in for muted channels: the input stream is still loaded
+and decoded but it is not mixed which alone leads to an enormous performance
+boost!
 
 "No music" means using the null audio plugin which prevents generating any MIDI
 music (and therefore avoiding the expensive synthesis emulation) but beware, it
-doesn't affect CD (*.wav) playback at all! Same applies for speech and sfx.
+doesn't affect CD (*.wav) playback at all! Same applies for speech and sfx. So
+mute one or all of those if frame rate drops noticeably.
 
 The least amount of cycles is spent when:
 - "No music" as "Preferred device": This prevents MIDI/OPL synthesis of any
   kind.
+- "Mute all" in "Volume" setting.
 - "output_rate" set to a DOS/Windows compatible value (default). Even if game
   uses 22050 Hz and your Falcon supports 22050 Hz, it is always faster to use
   11025 Hz!


Commit: d02ad6fe4abb7e4f83ee668997e9dc96647ac46c
    https://github.com/scummvm/scummvm/commit/d02ad6fe4abb7e4f83ee668997e9dc96647ac46c
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T22:11:42+10:00

Commit Message:
BACKENDS: ATARI: Add support for 16-bit mono

Changed paths:
    backends/mixer/atari/atari-mixer.cpp
    backends/mixer/atari/atari-mixer.h
    backends/platform/atari/readme.txt
    backends/platform/atari/readme.txt.in
    graphics/blit/blit-atari.cpp


diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index cab782e0e26..d75522950f2 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -37,15 +37,15 @@
 #include "common/textconsole.h"
 
 #ifdef DISABLE_FANCY_THEMES
-#define DEFAULT_OUTPUT_RATE 11025
-#define DEFAULT_SAMPLES 512	// 2 * 46ms (42ms at 12292 Hz) latency
+#define DEFAULT_OUTPUT_RATE			11025
+#define DEFAULT_OUTPUT_CHANNELS		1
+#define DEFAULT_SAMPLES				512		// 2 * 46ms (42ms at 12292 Hz) latency
 #else
-#define DEFAULT_OUTPUT_RATE 22050
-#define DEFAULT_SAMPLES 1024	// 2 * 46ms (42ms at 24585 Hz) latency
+#define DEFAULT_OUTPUT_RATE			22050
+#define DEFAULT_OUTPUT_CHANNELS		2
+#define DEFAULT_SAMPLES				1024	// 2 * 46ms (42ms at 24585 Hz) latency
 #endif
 
-#define DEFAULT_OUTPUT_CHANNELS 2
-
 static USoundContext usoundContext;
 
 void AtariAudioShutdown() {
@@ -125,12 +125,24 @@ void AtariMixerManager::init() {
 	obtained.samples = desired.samples;
 
 	_outputRate = obtained.frequency;
-	_outputChannels = obtained.channels;
-	_samples = obtained.samples;
+	if (desired.channels == 1 && obtained.channels == 2 && obtained.format == USoundFormatSigned16MSB) {
+		_outputChannels = 1;
+		_emulated16bitMono = true;
+	} else {
+		_outputChannels = obtained.channels;
+		_emulated16bitMono = false;
+	}
 	_downsample = (obtained.format == USoundFormatSigned8);
+	_samples = obtained.samples;
 
 	debug("setting %d Hz mixing frequency (%d-bit, %s)",
-		  _outputRate, obtained.format == USoundFormatSigned8 ? 8 : 16, _outputChannels == 1 ? "mono" : "stereo");
+		_outputRate,
+		obtained.format == USoundFormatSigned8 ? 8 : 16,
+		_outputChannels == 2
+			? "stereo"
+			: _emulated16bitMono
+				? "mono (emulated)"
+				: "mono");
 	debug("sample buffer size: %d", _samples);
 
 	_atariSampleBuffer = (byte*)Mxalloc(obtained.size * 2, MX_STRAM);
@@ -210,19 +222,23 @@ void AtariMixerManager::update() {
 		_atariPhysicalSampleBuffer = _atariLogicalSampleBuffer;
 		_atariLogicalSampleBuffer = tmp;
 
+		// WARNING: loopCount, src and dst are modified by the asm code
+		int loopCount = processed * _outputChannels;
+		const byte *src = _sampleBuf;
+		byte *dst = _atariPhysicalSampleBuffer;
 		if (_downsample) {
 			__asm__ volatile(
 				"	move.l	#32768,%%d2\n"
 				"	move.l	#65535,%%d3\n"
-				"	subq.l	#1,%2\n"
-				"1:	move.l	(%0)+,%%d0\n"
+				"	subq.l	#1,%0\n"
+				"1:	move.l	(%1)+,%%d0\n"
 				"	move.l	%%d0,%%d1\n"
 				"	add.l	%%d2,%%d1\n"
 				"	cmp.l	%%d3,%%d1\n"
 				"	bhi.b	3f\n"
 				"2:	asr.l	#8,%%d0\n"	// TODO: tweak (there were reports that >> 8 is too quiet)
-				"	move.b	%%d0,(%1)+\n"
-				"	dbra	%2,1b\n"
+				"	move.b	%%d0,(%2)+\n"
+				"	dbra	%0,1b\n"
 				"	bra.b	4f\n"
 				"3:	tst.l	%%d0\n"
 				"	spl		%%d0\n"
@@ -230,37 +246,68 @@ void AtariMixerManager::update() {
 				"	add.w	%%d2,%%d0\n"
 				"	bra.b	2b\n"
 				"4:\n"
-				: // outputs
-				: "a"(_sampleBuf), "a"(_atariPhysicalSampleBuffer), "d"(processed * _outputChannels) // inputs
+				: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
+				: // inputs
 				: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
-				);
+			);
 			memset(_atariPhysicalSampleBuffer + processed * _outputChannels * 2/2, 0, (_samples - processed) * _outputChannels * 2/2);
 			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * _outputChannels * 2/2);
 		} else {
-			__asm__ volatile(
-				"	move.l	#32768,%%d2\n"
-				"	move.l	#65535,%%d3\n"
-				"	subq.l	#1,%2\n"
-				"1:	move.l	(%0)+,%%d0\n"
-				"	move.l	%%d0,%%d1\n"
-				"	add.l	%%d2,%%d1\n"
-				"	cmp.l	%%d3,%%d1\n"
-				"	bhi.b	3f\n"
-				"2:	move.w	%%d0,(%1)+\n"
-				"	dbra	%2,1b\n"
-				"	bra.b	4f\n"
-				"3:	tst.l	%%d0\n"
-				"	spl		%%d0\n"
-				"	ext.w	%%d0\n"
-				"	add.w	%%d2,%%d0\n"
-				"	bra.b	2b\n"
-				"4:\n"
-				: // outputs
-				: "a"(_sampleBuf), "a"(_atariPhysicalSampleBuffer), "d"(processed * _outputChannels) // inputs
-				: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
+			int bytesPerFrame = _outputChannels * 2;
+
+			if (!_emulated16bitMono) {
+				__asm__ volatile(
+					"	move.l	#32768,%%d2\n"
+					"	move.l	#65535,%%d3\n"
+					"	subq.l	#1,%0\n"
+					"1:	move.l	(%1)+,%%d0\n"
+					"	move.l	%%d0,%%d1\n"
+					"	add.l	%%d2,%%d1\n"
+					"	cmp.l	%%d3,%%d1\n"
+					"	bhi.b	3f\n"
+					"2:	move.w	%%d0,(%2)+\n"
+					"	dbra	%0,1b\n"
+					"	bra.b	4f\n"
+					"3:	tst.l	%%d0\n"
+					"	spl		%%d0\n"
+					"	ext.w	%%d0\n"
+					"	add.w	%%d2,%%d0\n"
+					"	bra.b	2b\n"
+					"4:\n"
+					: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
+					: // inputs
+					: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
+				);
+			} else {
+				bytesPerFrame *= 2;
+
+				__asm__ volatile(
+					"	move.l	#32768,%%d2\n"
+					"	move.l	#65535,%%d3\n"
+					"	subq.l	#1,%0\n"
+					"1:	move.l	(%1)+,%%d0\n"
+					"	move.l	%%d0,%%d1\n"
+					"	add.l	%%d2,%%d1\n"
+					"	cmp.l	%%d3,%%d1\n"
+					"	bhi.b	3f\n"
+					"2:	move.w	%%d0,(%2)+\n"
+					"	move.w	%%d0,(%2)+\n"
+					"	dbra	%0,1b\n"
+					"	bra.b	4f\n"
+					"3:	tst.l	%%d0\n"
+					"	spl		%%d0\n"
+					"	ext.w	%%d0\n"
+					"	add.w	%%d2,%%d0\n"
+					"	bra.b	2b\n"
+					"4:\n"
+					: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
+					: // inputs
+					: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
 				);
-			memset(_atariPhysicalSampleBuffer + processed * _outputChannels * 2, 0, (_samples - processed) * _outputChannels * 2);
-			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * _outputChannels * 2);
+			}
+			const int bufferSize = processed * bytesPerFrame;
+			memset(_atariPhysicalSampleBuffer + bufferSize, 0, (_samples - processed) * bytesPerFrame);
+			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * bytesPerFrame);
 		}
 
 		if (muted) {
diff --git a/backends/mixer/atari/atari-mixer.h b/backends/mixer/atari/atari-mixer.h
index 03a27247d43..fafe83bfb58 100644
--- a/backends/mixer/atari/atari-mixer.h
+++ b/backends/mixer/atari/atari-mixer.h
@@ -45,6 +45,8 @@ public:
 private:
 	int _outputRate = 0;
 	int _outputChannels = 0;
+	bool _emulated16bitMono = false;
+	bool _downsample = false;
 	int _samples = 0;
 	int _sampleBufSize = 0;
 	byte *_sampleBuf = nullptr;
@@ -52,7 +54,6 @@ private:
 	byte *_atariSampleBuffer = nullptr;
 	byte *_atariPhysicalSampleBuffer = nullptr;
 	byte *_atariLogicalSampleBuffer = nullptr;
-	bool _downsample = false;
 };
 
 #endif
diff --git a/backends/platform/atari/readme.txt b/backends/platform/atari/readme.txt
index 4acf8ec410c..db97ca79a9f 100644
--- a/backends/platform/atari/readme.txt
+++ b/backends/platform/atari/readme.txt
@@ -166,9 +166,10 @@ systems without an external DSP clock, these frequencies are adjusted to
 the exact value; it will be rounded automatically to the nearest suitable
 value.
 
-"output_channels" in scummvm.ini: mono (1) or stereo (2) mixing. Please note
-that Falcon doesn't allow mixing in 16-bit mono, so this will have no effect on
-this machine.
+"output_channels" in scummvm.ini: mono (1) or stereo (2) mixing. Falcon always
+outputs 16-bit stereo however when set to mono, a fast mono-to-stereo
+conversion takes place (so I encourage everyone to use mono when music playback
+is too demanding).
 
 "audio_buffer_size" in scummvm.ini: number of samples to preload. Default is
 2048 which equals to about 83ms of audio lag and seems to be about right for
diff --git a/backends/platform/atari/readme.txt.in b/backends/platform/atari/readme.txt.in
index 41cd1700f33..b8ce5749b04 100644
--- a/backends/platform/atari/readme.txt.in
+++ b/backends/platform/atari/readme.txt.in
@@ -166,9 +166,10 @@ systems without an external DSP clock, these frequencies are adjusted to
 the exact value; it will be rounded automatically to the nearest suitable
 value.
 
-"output_channels" in scummvm.ini: mono (1) or stereo (2) mixing. Please note
-that Falcon doesn't allow mixing in 16-bit mono, so this will have no effect on
-this machine.
+"output_channels" in scummvm.ini: mono (1) or stereo (2) mixing. Falcon always
+outputs 16-bit stereo however when set to mono, a fast mono-to-stereo
+conversion takes place (so I encourage everyone to use mono when music playback
+is too demanding).
 
 "audio_buffer_size" in scummvm.ini: number of samples to preload. Default is
 2048 which equals to about 83ms of audio lag and seems to be about right for
diff --git a/graphics/blit/blit-atari.cpp b/graphics/blit/blit-atari.cpp
index e8cfa81a272..5f301051ff8 100644
--- a/graphics/blit/blit-atari.cpp
+++ b/graphics/blit/blit-atari.cpp
@@ -186,10 +186,11 @@ void copyBlit(byte *dst, const byte *src,
 			"	move.b	(%0)+,(%1)+\n"
 			"	move.b	(%0)+,(%1)+\n"
 			"4:\n"
-				: // outputs
-				: "a"(src), "a"(dst), "g"(dstPitch * h) // inputs
+				: "+a"(src), "+a"(dst) // outputs
+				: "g"(dstPitch * h) // inputs
 				: "d0", "d1", "cc" AND_MEMORY
 			);
+			// WARNING: src and dst are modified by the asm code
 		} else {
 #else
 		{
@@ -199,8 +200,9 @@ void copyBlit(byte *dst, const byte *src,
 	} else {
 #ifdef USE_MOVE16
 		if (hasMove16() && isAligned(src) && isAligned(dst) && isAligned(srcPitch) && isAligned(dstPitch)) {
+			int loopCount = h - 1;
 			__asm__ volatile(
-			"	move.l	%2,%%d0\n"
+			"	move.l	%3,%%d0\n"
 
 			"	moveq	#0x0f,%%d1\n"
 			"	and.l	%%d0,%%d1\n"
@@ -261,12 +263,13 @@ void copyBlit(byte *dst, const byte *src,
 			"4:\n"
 			"	add.l	%4,%1\n"
 			"	add.l	%5,%0\n"
-			"	dbra	%3,0b\n"
-				: // outputs
-				: "a"(src), "a"(dst), "g"(w * bytesPerPixel), "d"(h - 1),
+			"	dbra	%2,0b\n"
+				: "+a"(src), "+a"(dst), "+d"(loopCount) // outputs
+				: "g"(w * bytesPerPixel),
 				  "g"(dstPitch - w * bytesPerPixel), "g"(srcPitch - w * bytesPerPixel) // inputs
 				: "d0", "d1", "a0", "a1", "cc" AND_MEMORY
 			);
+			// WARNING: src and dst are modified by the asm code
 		} else {
 #else
 		{


Commit: b7c1ff1f7af8a44ce9bf707c352df6be0a0a1c92
    https://github.com/scummvm/scummvm/commit/b7c1ff1f7af8a44ce9bf707c352df6be0a0a1c92
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T22:11:50+10:00

Commit Message:
BACKENDS: ATARI: Rework the underrun algorithm

Changed paths:
    backends/mixer/atari/atari-mixer.cpp
    backends/mixer/atari/atari-mixer.h


diff --git a/backends/mixer/atari/atari-mixer.cpp b/backends/mixer/atari/atari-mixer.cpp
index d75522950f2..63947b95e1c 100644
--- a/backends/mixer/atari/atari-mixer.cpp
+++ b/backends/mixer/atari/atari-mixer.cpp
@@ -23,7 +23,6 @@
 
 #include "backends/mixer/atari/atari-mixer.h"
 
-#include <math.h>
 #include <mint/falcon.h>
 #include <mint/osbind.h>
 #include <mint/ostruct.h>
@@ -53,18 +52,30 @@ void AtariAudioShutdown() {
 	USoundDeinitXbios(&usoundContext);
 }
 
-static volatile bool muted;
-static volatile bool endOfPlayback;
-static void __attribute__((interrupt)) timerA(void)
-{
-	if (endOfPlayback && !muted) {
-		*((volatile unsigned char *)0xFFFF8901L) &= 0xFC;	// disable playback/repeat (and triggers another interrupt)
-		muted = true;
-	}
+static volatile enum {
+	kPlaybackStopped,	// DMA not playing (initial or after starvation)
+	kPlay1stHalf,		// DMA looping [Beg, Mid)
+	kPlay2ndHalf		// DMA looping [Mid, End)
+} s_playbackState = kPlaybackStopped;
+
+static volatile uint32 s_updatePulse;
+static volatile bool s_dmaWrapped;
+static volatile bool s_isrStoppedDma;
+
+static void __attribute__((interrupt)) timerA(void) {
+	static uint32 s_lastPulseSeen;
 
-	endOfPlayback = true;
+	if (s_updatePulse == s_lastPulseSeen) {
+		// update() didn't run since the previous wrap: stop the playback
+		*((volatile byte *)0xFFFF8901L) = 0;
+		s_isrStoppedDma = true;
+	} else {
+		s_dmaWrapped = true;
+	}
+	s_lastPulseSeen = s_updatePulse;
 
-	*((volatile byte *)0xFFFFFA0FL) &= ~(1<<5);	// clear in service bit
+	// clear in-service bit
+	*((volatile byte *)0xFFFFFA0FL) = ~(1 << 5);
 }
 
 AtariMixerManager::AtariMixerManager() : MixerManager() {
@@ -98,10 +109,10 @@ AtariMixerManager::~AtariMixerManager() {
 	AtariAudioShutdown();
 
 	Mfree(_atariSampleBuffer);
-	_atariSampleBuffer = _atariPhysicalSampleBuffer = _atariLogicalSampleBuffer = nullptr;
+	_atariSampleBuffer = nullptr;
 
-	delete[] _sampleBuf;
-	_sampleBuf = nullptr;
+	delete[] _sampleBuffer;
+	_sampleBuffer = nullptr;
 }
 
 void AtariMixerManager::init() {
@@ -135,7 +146,7 @@ void AtariMixerManager::init() {
 	_downsample = (obtained.format == USoundFormatSigned8);
 	_samples = obtained.samples;
 
-	debug("setting %d Hz mixing frequency (%d-bit, %s)",
+	debug("setting %d Hz mixing frequency, %d-bit, %s",
 		_outputRate,
 		obtained.format == USoundFormatSigned8 ? 8 : 16,
 		_outputChannels == 2
@@ -143,14 +154,14 @@ void AtariMixerManager::init() {
 			: _emulated16bitMono
 				? "mono (emulated)"
 				: "mono");
-	debug("sample buffer size: %d", _samples);
+	debug("audio buffer size: %d", _samples);
 
-	_atariSampleBuffer = (byte*)Mxalloc(obtained.size * 2, MX_STRAM);
-	if (!_atariSampleBuffer)
+	_atariSampleBufferSize = obtained.size * 2;	// two buffers
+	_atariSampleBuffer = (byte *)Mxalloc(_atariSampleBufferSize, MX_STRAM);
+	if (!_atariSampleBuffer) {
+		_atariSampleBufferSize = 0;
 		error("Failed to allocate memory in ST RAM");
-
-	_atariPhysicalSampleBuffer = _atariSampleBuffer;
-	_atariLogicalSampleBuffer = _atariSampleBuffer + obtained.size;
+	}
 
 	Setinterrupt(SI_TIMERA, SI_PLAY);
 	Xbtimer(XB_TIMERA, 1<<3, 1, timerA);	// event count mode, count to '1'
@@ -161,8 +172,8 @@ void AtariMixerManager::init() {
 	// enable and mix both sources (ADC and connection matrix) to the output
 	Soundcmd(ADDERIN, MATIN|ADCIN);
 
-	_sampleBufSize = _samples * _outputChannels * 4;	// always 32-bit
-	_sampleBuf = new uint8[_sampleBufSize];
+	_sampleBufferSize = _samples * _outputChannels * 4;	// always 32-bit
+	_sampleBuffer = new uint8[_sampleBufferSize];
 
 	_mixer = new Audio::MixerImpl(_outputRate, _outputChannels == 2, _samples, 4, false);
 	_mixer->setReady(true);
@@ -174,7 +185,7 @@ void AtariMixerManager::suspendAudio() {
 	debug("suspendAudio");
 
 	Buffoper(0x00);
-	muted = true;
+	s_playbackState = kPlaybackStopped;
 	_audioSuspended = true;
 }
 
@@ -190,10 +201,9 @@ bool AtariMixerManager::notifyEvent(const Common::Event &event) {
 	switch (event.type) {
 	case Common::EVENT_QUIT:
 	case Common::EVENT_RETURN_TO_LAUNCHER:
-		if (!muted) {
-			Buffoper(0x00);
-			muted = true;
+		if (s_playbackState != kPlaybackStopped) {
 			debug("silencing the mixer");
+			suspendAudio();
 		}
 		return false;
 	default:
@@ -210,114 +220,146 @@ void AtariMixerManager::update() {
 
 	assert(_mixer);
 
-	int processed = -1;
+	s_updatePulse++;
 
-	if (muted || endOfPlayback) {
-		endOfPlayback = false;
-		processed = _mixer->mixCallback(_sampleBuf, _sampleBufSize);
+	// Translate ISR's starvation signal into a state transition. Done
+	// here so that update() is the only writer of s_playbackState.
+	if (s_isrStoppedDma) {
+		s_isrStoppedDma = false;
+		s_playbackState = kPlaybackStopped;
 	}
 
-	if (processed > 0) {
-		byte* tmp = _atariPhysicalSampleBuffer;
-		_atariPhysicalSampleBuffer = _atariLogicalSampleBuffer;
-		_atariLogicalSampleBuffer = tmp;
+	byte *atariSampleBuffer1stHalf = _atariSampleBuffer;
+	byte *atariSampleBuffer2ndHalf = _atariSampleBuffer + _atariSampleBufferSize/2;
+	byte *atariSampleBufferEnd     = _atariSampleBuffer + _atariSampleBufferSize;
+
+	bool needsMix = false;
+
+	if (s_playbackState == kPlaybackStopped) {
+		memset(_atariSampleBuffer, 0, _atariSampleBufferSize);
+		Setbuffer(SR_PLAY, atariSampleBuffer1stHalf, atariSampleBuffer2ndHalf);
+		Buffoper(SB_PLA_ENA | SB_PLA_RPT);
+		s_playbackState = kPlay1stHalf;
+		// Buffoper's 0->ENA transition can fire a spurious SI_PLAY which
+		// would set s_dmaWrapped here. The resulting extra state toggle
+		// is benign — it just shuffles which physical half holds the next
+		// mix. Audio output is continuous either way.
+		needsMix = true;
+	}
 
-		// WARNING: loopCount, src and dst are modified by the asm code
-		int loopCount = processed * _outputChannels;
-		const byte *src = _sampleBuf;
-		byte *dst = _atariPhysicalSampleBuffer;
-		if (_downsample) {
+	if (s_dmaWrapped) {
+		s_dmaWrapped = false;
+		if (s_playbackState == kPlay1stHalf)
+			s_playbackState = kPlay2ndHalf;
+		else if (s_playbackState == kPlay2ndHalf)
+			s_playbackState = kPlay1stHalf;
+		needsMix = true;
+	}
+
+	if (!needsMix)
+		return;
+
+	// Mix into the half DMA is NOT currently playing, and Setbuffer to
+	// it so DMA wraps there at the next frame boundary.
+	byte *buf;
+	if (s_playbackState == kPlay1stHalf) {
+		buf = atariSampleBuffer2ndHalf;
+		Setbuffer(SR_PLAY, atariSampleBuffer2ndHalf, atariSampleBufferEnd);
+	} else {
+		buf = atariSampleBuffer1stHalf;
+		Setbuffer(SR_PLAY, atariSampleBuffer1stHalf, atariSampleBuffer2ndHalf);
+	}
+
+	int processed = _mixer->mixCallback(_sampleBuffer, _sampleBufferSize);
+
+	// WARNING: loopCount, src and dst are modified by the asm code
+	int loopCount = processed * _outputChannels;
+	const byte *src = _sampleBuffer;
+	byte *dst = buf;
+
+	if (_downsample) {
+		__asm__ volatile(
+			"	subq.l	#1,%0\n"
+			"	bmi.b	3f\n"
+			"	move.l	#32768,%%d2\n"
+			"	move.l	#65535,%%d3\n"
+			"	moveq	#31,%%d4\n"
+			"	moveq	#0x7f,%%d5\n"
+			"1:	move.l	(%1)+,%%d0\n"
+			"	move.l	%%d0,%%d1\n"
+			"	add.l	%%d2,%%d1\n"
+			"	cmp.l	%%d3,%%d1\n"
+			"	bhi.b	2f\n"
+			"	asr.l	#8,%%d0\n"	// TODO: tweak (there were reports that >> 8 is too quiet)
+			"	move.b	%%d0,(%2)+\n"
+			"	dbra	%0,1b\n"
+			"	bra.b	3f\n"
+			"2:	asr.l	%%d4,%%d0\n"
+			"	eor.b	%%d5,%%d0\n"
+			"	move.b	%%d0,(%2)+\n"
+			"	dbra	%0,1b\n"
+			"3:\n"
+			: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
+			: // inputs
+			: "d0", "d1", "d2", "d3", "d4", "d5", "cc" AND_MEMORY
+		);
+		memset(buf + processed * _outputChannels *2/2, 0, (_samples - processed) * _outputChannels * 2/2);
+	} else {
+		if (!_emulated16bitMono) {
 			__asm__ volatile(
+				"	subq.l	#1,%0\n"
+				"	bmi.b	3f\n"
 				"	move.l	#32768,%%d2\n"
 				"	move.l	#65535,%%d3\n"
-				"	subq.l	#1,%0\n"
+				"	moveq	#31,%%d4\n"
+				"	move.w	#0x7fff,%%d5\n"
 				"1:	move.l	(%1)+,%%d0\n"
 				"	move.l	%%d0,%%d1\n"
 				"	add.l	%%d2,%%d1\n"
 				"	cmp.l	%%d3,%%d1\n"
-				"	bhi.b	3f\n"
-				"2:	asr.l	#8,%%d0\n"	// TODO: tweak (there were reports that >> 8 is too quiet)
-				"	move.b	%%d0,(%2)+\n"
+				"	bhi.b	2f\n"
+				"	move.w	%%d0,(%2)+\n"
+				"	dbra	%0,1b\n"
+				"	bra.b	3f\n"
+				"2:	asr.l	%%d4,%%d0\n"
+				"	eor.w	%%d5,%%d0\n"
+				"	move.w	%%d0,(%2)+\n"
 				"	dbra	%0,1b\n"
-				"	bra.b	4f\n"
-				"3:	tst.l	%%d0\n"
-				"	spl		%%d0\n"
-				"	ext.w	%%d0\n"
-				"	add.w	%%d2,%%d0\n"
-				"	bra.b	2b\n"
-				"4:\n"
+				"3:\n"
 				: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
 				: // inputs
-				: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
+				: "d0", "d1", "d2", "d3", "d4", "d5", "cc" AND_MEMORY
 			);
-			memset(_atariPhysicalSampleBuffer + processed * _outputChannels * 2/2, 0, (_samples - processed) * _outputChannels * 2/2);
-			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * _outputChannels * 2/2);
+			memset(buf + processed * _outputChannels * 2, 0, (_samples - processed) * _outputChannels * 2);
 		} else {
-			int bytesPerFrame = _outputChannels * 2;
-
-			if (!_emulated16bitMono) {
-				__asm__ volatile(
-					"	move.l	#32768,%%d2\n"
-					"	move.l	#65535,%%d3\n"
-					"	subq.l	#1,%0\n"
-					"1:	move.l	(%1)+,%%d0\n"
-					"	move.l	%%d0,%%d1\n"
-					"	add.l	%%d2,%%d1\n"
-					"	cmp.l	%%d3,%%d1\n"
-					"	bhi.b	3f\n"
-					"2:	move.w	%%d0,(%2)+\n"
-					"	dbra	%0,1b\n"
-					"	bra.b	4f\n"
-					"3:	tst.l	%%d0\n"
-					"	spl		%%d0\n"
-					"	ext.w	%%d0\n"
-					"	add.w	%%d2,%%d0\n"
-					"	bra.b	2b\n"
-					"4:\n"
-					: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
-					: // inputs
-					: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
-				);
-			} else {
-				bytesPerFrame *= 2;
-
-				__asm__ volatile(
-					"	move.l	#32768,%%d2\n"
-					"	move.l	#65535,%%d3\n"
-					"	subq.l	#1,%0\n"
-					"1:	move.l	(%1)+,%%d0\n"
-					"	move.l	%%d0,%%d1\n"
-					"	add.l	%%d2,%%d1\n"
-					"	cmp.l	%%d3,%%d1\n"
-					"	bhi.b	3f\n"
-					"2:	move.w	%%d0,(%2)+\n"
-					"	move.w	%%d0,(%2)+\n"
-					"	dbra	%0,1b\n"
-					"	bra.b	4f\n"
-					"3:	tst.l	%%d0\n"
-					"	spl		%%d0\n"
-					"	ext.w	%%d0\n"
-					"	add.w	%%d2,%%d0\n"
-					"	bra.b	2b\n"
-					"4:\n"
-					: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
-					: // inputs
-					: "d0", "d1", "d2", "d3", "cc" AND_MEMORY
-				);
-			}
-			const int bufferSize = processed * bytesPerFrame;
-			memset(_atariPhysicalSampleBuffer + bufferSize, 0, (_samples - processed) * bytesPerFrame);
-			Setbuffer(SR_PLAY, _atariPhysicalSampleBuffer, _atariPhysicalSampleBuffer + _samples * bytesPerFrame);
-		}
-
-		if (muted) {
-			Buffoper(SB_PLA_ENA | SB_PLA_RPT);
-			endOfPlayback = true;
-			muted = false;
+			__asm__ volatile(
+				"	subq.l	#1,%0\n"
+				"	bmi.b	3f\n"
+				"	move.l	#32768,%%d2\n"
+				"	move.l	#65535,%%d3\n"
+				"	moveq	#31,%%d4\n"
+				"	move.w	#0x7fff,%%d5\n"
+				"1:	move.l	(%1)+,%%d0\n"
+				"	move.l	%%d0,%%d1\n"
+				"	add.l	%%d2,%%d1\n"
+				"	cmp.l	%%d3,%%d1\n"
+				"	bhi.b	2f\n"
+				"	move.w	%%d0,(%2)+\n"
+				"	move.w	%%d0,(%2)+\n"
+				"	dbra	%0,1b\n"
+				"	bra.b	3f\n"
+				"2:	asr.l	%%d4,%%d0\n"
+				"	eor.w	%%d5,%%d0\n"
+				"	move.w	%%d0,(%2)+\n"
+				"	move.w	%%d0,(%2)+\n"
+				"	dbra	%0,1b\n"
+				"3:\n"
+				: "+d"(loopCount), "+a"(src), "+a"(dst) // outputs
+				: // inputs
+				: "d0", "d1", "d2", "d3", "d4", "d5", "cc" AND_MEMORY
+			);
+			memset(buf + processed * _outputChannels * 2*2, 0, (_samples - processed) * _outputChannels * 2*2);
 		}
-	} else if (processed == 0 && !muted) {
-		Buffoper(0x00);
-		muted = true;
 	}
 
 	if (processed > 0 && processed != _samples) {
diff --git a/backends/mixer/atari/atari-mixer.h b/backends/mixer/atari/atari-mixer.h
index fafe83bfb58..4ada0178c6e 100644
--- a/backends/mixer/atari/atari-mixer.h
+++ b/backends/mixer/atari/atari-mixer.h
@@ -47,13 +47,13 @@ private:
 	int _outputChannels = 0;
 	bool _emulated16bitMono = false;
 	bool _downsample = false;
+
 	int _samples = 0;
-	int _sampleBufSize = 0;
-	byte *_sampleBuf = nullptr;
+	int _sampleBufferSize = 0;
+	byte *_sampleBuffer = nullptr;
 
+	int _atariSampleBufferSize = 0;
 	byte *_atariSampleBuffer = nullptr;
-	byte *_atariPhysicalSampleBuffer = nullptr;
-	byte *_atariLogicalSampleBuffer = nullptr;
 };
 
 #endif


Commit: 0b334f4579e90bb72a04972d0e83567129129714
    https://github.com/scummvm/scummvm/commit/0b334f4579e90bb72a04972d0e83567129129714
Author: Miro Kropacek (miro.kropacek at gmail.com)
Date: 2026-08-22T22:11:50+10:00

Commit Message:
BACKENDS: ATARI: Introduce SIDECART_OUTPUT for log messages

When enabled, log messages are sent to the cartridge port so devices
like SidecarT can capture them. Disabled by default.

Also unify the _KEYTAB cast style.

Changed paths:
    backends/events/atari/atari-events.cpp
    backends/platform/atari/osystem_atari.cpp


diff --git a/backends/events/atari/atari-events.cpp b/backends/events/atari/atari-events.cpp
index ce848acbebe..c1dc3f7947e 100644
--- a/backends/events/atari/atari-events.cpp
+++ b/backends/events/atari/atari-events.cpp
@@ -50,7 +50,7 @@ AtariEventSource::AtariEventSource() {
 	_system = dynamic_cast<OSystem_Atari*>(g_system);
 	assert(_system != nullptr);
 
-	_KEYTAB *pKeyTables = (_KEYTAB*)Keytbl(KT_NOCHANGE, KT_NOCHANGE, KT_NOCHANGE);
+	_KEYTAB *pKeyTables = (_KEYTAB *)Keytbl(KT_NOCHANGE, KT_NOCHANGE, KT_NOCHANGE);
 
 	memcpy(_unshiftToAscii, pKeyTables->unshift, 128);
 	memcpy(_shiftToAscii, pKeyTables->shift, 128);
diff --git a/backends/platform/atari/osystem_atari.cpp b/backends/platform/atari/osystem_atari.cpp
index 20ca45612ca..8230afd5018 100644
--- a/backends/platform/atari/osystem_atari.cpp
+++ b/backends/platform/atari/osystem_atari.cpp
@@ -59,6 +59,7 @@
 #include "common/config-manager.h"
 #include "common/debug.h"
 
+//#define SIDECART_OUTPUT
 #define INPUT_ACTIVE
 
 /*
@@ -474,6 +475,7 @@ void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
 	if (nf_stderr_id) {
 		nf_print(str);
 	} else {
+#ifndef SIDECART_OUTPUT
 		FILE *output = 0;
 
 		if (type == LogMessageType::kInfo || type == LogMessageType::kDebug)
@@ -483,6 +485,11 @@ void OSystem_Atari::logMessage(LogMessageType::Type type, const char *message) {
 
 		fputs(str, output);
 		fflush(output);
+#else
+#define CARTRIDGE_ROM3 0xFB0000ul
+		for (const char *s = str; *s; s++)
+			(void)(*((volatile uint16 *)(CARTRIDGE_ROM3 + ((*s & 0xFF)<<1))));
+#endif
 	}
 }
 




More information about the Scummvm-git-logs mailing list