# SDL-1.2: atari:audio:xbios: FireTOS lacks end-of-frame interrupt

**URL:** <https://discourse.libsdl.org/t/sdl-1-2-atarixbios-firetos-lacks-end-of-frame-interrupt/69455>\
**Category:** SDL Commits\
**Created:** [October 2, 2026, 9:58am UTC](https://discourse.libsdl.org/t/sdl-1-2-atarixbios-firetos-lacks-end-of-frame-interrupt/69455 "2026-10-02T09:58:10Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![SDLPushPostBot](https://discourse.libsdl.org/user_avatar/discourse.libsdl.org/sdlpushpostbot/32/4370_2.png) [@SDLPushPostBot](https://discourse.libsdl.org/u/SDLPushPostBot)\
**Post date:** [October 2, 2026, 9:58am UTC](https://discourse.libsdl.org/t/sdl-1-2-atarixbios-firetos-lacks-end-of-frame-interrupt/69455/1 "2026-10-02T09:58:10Z")

</div>

> **[atari:audio:xbios: FireTOS lacks end-of-frame interrupt ·...](https://github.com/libsdl-org/SDL-1.2/commit/a4b2b2d9efa3c8c16940586cf731d841af0b33af)**
>
> Use polling instead. I keep forgetting about this, again and again.

```diff
From a4b2b2d9efa3c8c16940586cf731d841af0b33af Mon Sep 17 00:00:00 2001
From: Miro Kropacek <[EMAIL REDACTED]>
Date: Thu, 1 Oct 2026 22:22:21 +1000
Subject: [PATCH] atari:audio:xbios: FireTOS lacks end-of-frame interrupt

Use polling instead. I keep forgetting about this, again and again.
---
 src/audio/mint/SDL_mintaudio.c | 31 ++++++++++++++++++++++++++++
 src/audio/mint/SDL_mintaudio_xbios.c | 23 +++++++++++----------
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/src/audio/mint/SDL_mintaudio.c b/src/audio/mint/SDL_mintaudio.c
index a05109073..b95e98359 100644
--- a/src/audio/mint/SDL_mintaudio.c
+++ b/src/audio/mint/SDL_mintaudio.c
@@ -42,6 +42,7 @@
 /* The audio device */
 
 #define MAX_DMA_BUF	8
+#define POLL_DMA_BUF	2
 
 /* Minimum number of updates per buffer, and number of consecutive buffers
    meeting it, before the latency is decreased */
@@ -76,7 +77,12 @@ int SDL_MintAudio_InitBuffers(SDL_AudioSpec *spec)
 	SDL_AudioDevice *this = SDL_MintAudio_device;
 
 	SDL_CalculateAudioSpec(spec);
+#if defined( __mcoldfire__ )
+	/* Fixed size: both halves of the ring must stay contiguous */
+	MINTAUDIO_audiosize = spec->size * POLL_DMA_BUF;
+#else
 	MINTAUDIO_audiosize = spec->size * MAX_DMA_BUF;
+#endif
 
 	/* Allocate audio buffer memory for application in FastRAM */
 	MINTAUDIO_fastrambuf = Atari_SysMalloc(MINTAUDIO_audiosize, MX_TTRAM);
@@ -99,7 +105,11 @@ int SDL_MintAudio_InitBuffers(SDL_AudioSpec *spec)
 
 	SDL_MintAudio_numbuf = SDL_MintAudio_num_its = SDL_MintAudio_num_upd = 0;
 	SDL_MintAudio_num_idle = 0;
+#if defined( __mcoldfire__ )
+	SDL_MintAudio_max_buf = POLL_DMA_BUF;
+#else
 	SDL_MintAudio_max_buf = 1;
+#endif
 
 	/* For filling silence when too many interrupts per update */
 	SDL_MintAudio_itbuffer = NULL;
@@ -138,6 +148,26 @@ void SDL_AtariMint_UpdateAudio(void)
 		return;
 	}
 
+#if defined( __mcoldfire__ )
+	{
+ SndBufPtr pointers;
+ int playing;
+
+ if (Buffptr(&pointers) != 0) {
+ return;
+ }
+
+ /* Here SDL_MintAudio_numbuf is the half being replayed */
+ playing = ((Uint8 *)pointers.play >= MINTAUDIO_audiobuf[1]);
+ if (playing == SDL_MintAudio_numbuf) {
+ return;
+ }
+
+ /* Refill the half the replay has just left */
+ SDL_MintAudio_Callback();
+ SDL_MintAudio_numbuf = playing;
+	}
+#else
 	++SDL_MintAudio_num_upd;
 
 	/* No interrupt triggered? still playing current buffer */
@@ -181,6 +211,7 @@ void SDL_AtariMint_UpdateAudio(void)
 
 	SDL_MintAudio_itbuffer = MINTAUDIO_audiobuf[SDL_MintAudio_numbuf];
 	SDL_MintAudio_itbuflen = MINTAUDIO_audiosize >> 2;
+#endif
 }
 
 /* The callback function, called by each driver whenever needed */
diff --git a/src/audio/mint/SDL_mintaudio_xbios.c b/src/audio/mint/SDL_mintaudio_xbios.c
index 999ada088..7709e60c3 100644
--- a/src/audio/mint/SDL_mintaudio_xbios.c
+++ b/src/audio/mint/SDL_mintaudio_xbios.c
@@ -82,10 +82,10 @@ static void Mint_GsxbNullInterrupt(void);
 /* uSound state, shared between Mint_OpenAudio() and Mint_CloseAudio() */
 static USoundContext usound_context;
 
-/* Do we use GSXB's own end of frame callback instead of Timer A ? */
-#if defined( __mcoldfire__ )
-#define use_gsxb 0	/* no ColdFire machine implements GSXB */
-#else
+/* Do we use GSXB's own end of frame callback instead of Timer A ?
+ ColdFire machines have neither: FireTOS raises no end of frame
+ interrupt, so the replay position is polled instead. */
+#if !defined( __mcoldfire__ )
 static int use_gsxb;
 #endif
 
@@ -216,11 +216,10 @@ static void Mint_CloseAudio(_THIS)
 #if !defined( __mcoldfire__ )
 	if (use_gsxb) {
 		NSetinterrupt(SI_GSXB, SI_NONE, Mint_GsxbNullInterrupt);
-	}
-#endif
-	if (!use_gsxb) {
+	} else {
 		Jdisint(MFP_DMASOUND);
 	}
+#endif
 
 	/* Restore and unlock the sound system */
 	USoundDeinitXbios(&usound_context);
@@ -281,10 +280,13 @@ static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
 
 	/* Set buffer */
 	MINTAUDIO_swapbuf = Mint_SwapBuffers;
+#if defined( __mcoldfire__ )
+	/* Both halves of the ring at once, replayed in a loop */
+	Mint_SwapBuffers(MINTAUDIO_audiobuf[0], 2 * MINTAUDIO_audiosize);
+#else
 	Mint_SwapBuffers(MINTAUDIO_audiobuf[0], MINTAUDIO_audiosize);
 
 	/* Install interrupt */
-#if !defined( __mcoldfire__ )
 	use_gsxb = Mint_GsxbAvailable();
 	if (use_gsxb) {
 		if (NSetinterrupt(SI_GSXB, SI_PLAY, SDL_MintAudio_GsxbInterrupt)<0) {
@@ -294,9 +296,7 @@ static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
 			SDL_MintAudio_device = NULL;
 			return(-1);
 		}
-	}
-#endif
-	if (!use_gsxb) {
+	} else {
 		Jdisint(MFP_DMASOUND);
 		Xbtimer(XB_TIMERA, 8, 1, SDL_MintAudio_XbiosInterrupt);
 		Jenabint(MFP_DMASOUND);
@@ -305,6 +305,7 @@ static int Mint_OpenAudio(_THIS, SDL_AudioSpec *spec)
 			DEBUG_PRINT((DEBUG_NAME "Setinterrupt() failed\n"));
 		}
 	}
+#endif
 
 	/* Go */
 	Buffoper(SB_PLA_ENA|SB_PLA_RPT);

```
