Files
dusk/cmake/targets/dolphin.cmake
T
YourWishesandClaude Sonnet 5 fc1fc9f170 Rewrite Dolphin audio to use libogc's standard ASND API
Replaces the ansnd-based backend (a third-party library with a custom
DSP ucode Dolphin's HLE audio emulation doesn't recognize, requiring
-a LLE as a workaround) with libogc's own asndlib - the standard,
HLE-supported audio API most GC/Wii homebrew already uses.

Also fixes three real bugs found while getting a large (41MB) WAV
asset actually playing on Dolphin:

- audiostreamdolphin.c previously buffered a stream's entire loop
  segment into one allocation up front (inherited from the ansnd
  design) - fine for a short test tone, but an out-of-memory crash for
  a real multi-minute track on GameCube's 24MB (or even Wii's 88MB)
  total RAM. Rewritten to stream bounded windows via ASND's real
  double-buffer primitives (ASND_SetVoice + ASND_AddVoice, polled from
  the main thread - never from an interrupt callback), matching how
  Linux/PSP already work.

- ASND_TestVoiceBufferReady() returns SND_OK (0) when ready and
  SND_BUSY (1) when not, in the actual toolchain fork
  (extremscorner/libogc2) this project builds against - opposite of a
  plain boolean. Treating the raw result as one meant a genuinely
  ready voice's SND_OK read as false, silently skipping every
  ASND_AddVoice() call forever after a stream's first buffered window.

- audioStreamPcmRead()'s 16-bit fast path read WAV's little-endian
  sample bytes straight into the output buffer with no byte-swap -
  correct by coincidence on every little-endian platform this engine
  targets (Linux, PSP), but reversed every sample's bytes on
  Dolphin/GameCube/Wii's big-endian PowerPC.

libmad is GPL-licensed (see audiostreammp3decodersw.h's own note from
the prior MP3 change); libogc's asndlib is under a permissive
BSD-style license, so this doesn't add another such dependency.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
2026-09-02 12:49:53 -05:00

82 lines
2.9 KiB
CMake

# Build type: DOL (SD/USB via libfat) or ISO (DVD disc via libogc DVD driver)
set(DUSK_DOLPHIN_BUILD_TYPE "DOL" CACHE STRING "Dolphin asset source: DOL (SD/USB) or ISO (DVD disc)")
set_property(CACHE DUSK_DOLPHIN_BUILD_TYPE PROPERTY STRINGS "DOL" "ISO")
# Numeric tokens so #if DUSK_DOLPHIN_BUILD_TYPE == DOL works in C.
# DUSK_DOLPHIN_BUILD_TYPE is passed without quotes so it expands to the identifier.
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC
DUSK_DOLPHIN
DUSK_INPUT_GAMEPAD
# DUSK_DISPLAY_WIDTH=640
# DUSK_DISPLAY_HEIGHT=480
DUSK_DISPLAY_WIDTH=320
DUSK_DISPLAY_HEIGHT=240
DUSK_DISPLAY_OVERSCAN=16
DUSK_THREAD_PTHREAD
DOL=1
ISO=2
DUSK_DOLPHIN_BUILD_TYPE=${DUSK_DOLPHIN_BUILD_TYPE}
# GameCube/Wii PowerPC is always big-endian; declare it at compile time
# like every other target instead of relying on endian.h's runtime probe.
DUSK_PLATFORM_ENDIAN_BIG
)
# Custom compiler flags
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fno-rtti -fno-exceptions")
# Disable all warnings
target_compile_options(${DUSK_LIBRARY_TARGET_NAME} PRIVATE -w)
# cglm: fetched at source level via Findcglm.cmake (FetchContent, headers only)
find_package(cglm REQUIRED)
# Pre-create ZLIB::ZLIB so any downstream cmake module that resolves it
# (FindZLIB, pkg-config IMPORTED_TARGET Requires processing) gets plain -lz
# rather than an unresolvable IMPORTED target that the PPC linker rejects.
if(NOT TARGET ZLIB::ZLIB)
add_library(ZLIB::ZLIB INTERFACE IMPORTED GLOBAL)
set_target_properties(ZLIB::ZLIB PROPERTIES INTERFACE_LINK_LIBRARIES "z")
endif()
# Mark libzip as found so src/dusk/CMakeLists.txt skips Findlibzip.cmake.
# Findlibzip.cmake calls find_package(ZLIB) which can recreate a broken
# ZLIB::ZLIB IMPORTED target, bypassing the shim above.
set(libzip_FOUND TRUE CACHE BOOL "libzip found (devkitpro portlibs)" FORCE)
# Locate zip.h in the devkitpro sysroot (respects CMAKE_FIND_ROOT_PATH).
find_path(_dusk_zip_inc NAMES zip.h)
if(_dusk_zip_inc)
target_include_directories(${DUSK_LIBRARY_TARGET_NAME} PRIVATE "${_dusk_zip_inc}")
endif()
# Link libraries.
# zip/z/lzma use target_link_options (raw flags) to bypass cmake target
# resolution - pkg-config-generated targets for these carry ZLIB::ZLIB in
# INTERFACE_LINK_LIBRARIES which breaks the PPC link step.
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE
cglm
m
zip
bz2
zstd
z
lzma
asnd
mad
)
if(DUSK_DOLPHIN_BUILD_TYPE STREQUAL "ISO")
target_compile_definitions(${DUSK_LIBRARY_TARGET_NAME} PUBLIC DUSK_DOLPHIN_BUILD_ISO)
else()
target_link_libraries(${DUSK_LIBRARY_TARGET_NAME} PRIVATE fat)
endif()
# Postbuild: ELF -> DOL
set(DUSK_BINARY_TARGET_NAME_DOL "${DUSK_BUILD_DIR}/Dusk.dol")
add_custom_command(TARGET ${DUSK_BINARY_TARGET_NAME} POST_BUILD
COMMAND elf2dol
"$<TARGET_FILE:${DUSK_BINARY_TARGET_NAME}>"
"${DUSK_BINARY_TARGET_NAME_DOL}"
COMMENT "Generating ${DUSK_BINARY_TARGET_NAME_DOL} from ${DUSK_BINARY_TARGET_NAME}"
)