Fix Dolphin ansnd audio failing to configure on GameCube/Wii

ansnd_configure_pcm_voice requires frame_data_ptr to be a physical
address - it rejects cached virtual pointers (0x8xxxxxxx) as
ANSND_ERROR_INVALID_MEMORY. Convert via MEM_VIRTUAL_TO_PHYSICAL and flush
the CPU cache first so the DSP's DMA read sees what was actually written.

Root-caused by disassembling libansnd's ansnd_configure_pcm_voice (no
source available, only the static lib) and confirming via a temporary
debug print that frame_data_ptr's top bit being set was what tripped the
check. Confirmed fixed by running the Wii DOL build in Dolphin under -a
LLE - voice configure/start now succeed with no errors.
This commit is contained in:
2026-08-31 15:43:29 -05:00
parent e47a2c3e5c
commit 8049e90853
+10 -1
View File
@@ -10,6 +10,8 @@
#include "assert/assert.h" #include "assert/assert.h"
#include "util/memory.h" #include "util/memory.h"
#include <ansndlib.h> #include <ansndlib.h>
#include <ogc/cache.h>
#include <ogc/system.h>
errorret_t audioStreamDolphinInit(audiostream_t *stream) { errorret_t audioStreamDolphinInit(audiostream_t *stream) {
assertNotNull(stream, "Stream cannot be NULL."); assertNotNull(stream, "Stream cannot be NULL.");
@@ -57,7 +59,14 @@ errorret_t audioStreamDolphinBuffer(audiostream_t *stream) {
config.pitch = 1.0f; config.pitch = 1.0f;
config.left_volume = baseVolume * (pan > 0 ? (1.0f - pan) : 1.0f); config.left_volume = baseVolume * (pan > 0 ? (1.0f - pan) : 1.0f);
config.right_volume = baseVolume * (pan < 0 ? (1.0f + pan) : 1.0f); config.right_volume = baseVolume * (pan < 0 ? (1.0f + pan) : 1.0f);
config.frame_data_ptr = (u32) stream->data; // The DSP DMAs frame_data_ptr directly out of main memory, bypassing the
// CPU cache, and rejects any pointer in cached virtual address space
// (0x8xxxxxxx.. - checked as "negative" internally, returned as
// ANSND_ERROR_INVALID_MEMORY) - it needs the physical address instead.
// Flush first so the DMA sees what the CPU actually wrote, not stale
// memory contents.
DCFlushRange(stream->data, stream->dataSize);
config.frame_data_ptr = MEM_VIRTUAL_TO_PHYSICAL(stream->data);
config.frame_count = (u32) (stream->dataSize / frameSize); config.frame_count = (u32) (stream->dataSize / frameSize);
config.voice_callback = audioStreamDolphinVoiceCallback; config.voice_callback = audioStreamDolphinVoiceCallback;
config.stream_callback = NULL; // single-buffer playback config.stream_callback = NULL; // single-buffer playback