shithub: cstory

Download patch

ref: 5b4778fb06583fd1406769fcada9961e9c4337de
parent: 6df224400cd015598c40a0bd33f00a934a49fe79
author: Clownacy <Clownacy@users.noreply.github.com>
date: Sun Oct 11 17:16:47 EDT 2020

Fix the 3DS crash when closing

For whatever reason, the 3DS *really* doesn't like it when I do all
the audio mixing in the callback function. Instead, it seems I have
to use a dedicated thread.

--- a/src/Backends/Audio/SoftwareMixer/3DS.cpp
+++ b/src/Backends/Audio/SoftwareMixer/3DS.cpp
@@ -22,6 +22,11 @@
 static LightLock mixer_mutex;
 static LightLock organya_mutex;
 
+static LightEvent audio_thread_event;
+
+static Thread audio_thread;
+static bool audio_thread_die;
+
 static void FullBuffer(short *stream, size_t frames_total)
 {
 	size_t frames_done = 0;
@@ -56,13 +61,25 @@
 {
 	(void)user_data;
 
-	if (dsp_buffers[current_dsp_buffer].status == NDSP_WBUF_DONE)
+	LightEvent_Signal(&audio_thread_event);
+}
+
+static void AudioThread(void *user_data)
+{
+	(void)user_data;
+
+	while (!audio_thread_die)
 	{
-		FullBuffer(dsp_buffers[current_dsp_buffer].data_pcm16, dsp_buffers[current_dsp_buffer].nsamples);
+		if (dsp_buffers[current_dsp_buffer].status == NDSP_WBUF_DONE)
+		{
+			FullBuffer(dsp_buffers[current_dsp_buffer].data_pcm16, dsp_buffers[current_dsp_buffer].nsamples);
 
-		ndspChnWaveBufAdd(0, &dsp_buffers[current_dsp_buffer]);
+			ndspChnWaveBufAdd(0, &dsp_buffers[current_dsp_buffer]);
 
-		current_dsp_buffer = !current_dsp_buffer;
+			current_dsp_buffer = !current_dsp_buffer;
+		}
+
+		LightEvent_Wait(&audio_thread_event);
 	}
 }
 
@@ -110,6 +127,12 @@
 			LightLock_Init(&mixer_mutex);
 			LightLock_Init(&organya_mutex);
 
+			LightEvent_Init(&audio_thread_event, RESET_ONESHOT);
+
+			audio_thread_die = false;
+
+			audio_thread = threadCreate(AudioThread, NULL, 32 * 1024, 0x18, -1, false);
+
 			return SAMPLE_RATE;
 		}
 		else
@@ -129,6 +152,16 @@
 
 void SoftwareMixerBackend_Deinit(void)
 {
+	ndspSetCallback(NULL, NULL);
+
+	// Kill audio thread
+	audio_thread_die = true;
+	LightEvent_Signal(&audio_thread_event);
+	threadJoin(audio_thread, UINT64_MAX);
+	threadFree(audio_thread);
+
+	ndspChnReset(0);
+
 	ndspExit();
 
 	linearFree(stream_buffer);