From 48746a9a67d7780a0ab8524a9d929db6cb00e9a3 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 4 Sep 2026 02:01:41 -0600 Subject: [PATCH] Use aurora::thp; remove libjpeg-turbo (#2386) --- CMakeLists.txt | 76 +-------------- extern/aurora | 2 +- include/d/actor/d_a_movie_player.h | 28 +----- src/d/actor/d_a_demo00.cpp | 6 -- src/d/actor/d_a_movie_player.cpp | 147 ++--------------------------- 5 files changed, 12 insertions(+), 247 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 31ec15e505..834713ed00 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,6 +72,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL Linux) endif () set(AURORA_ENABLE_DVD ON CACHE BOOL "Enable DVD API support" FORCE) set(AURORA_ENABLE_CARD ON CACHE BOOL "Enable CARD API support" FORCE) +set(AURORA_ENABLE_THP ON CACHE BOOL "Enable THP decoder" FORCE) set(AURORA_ENABLE_RMLUI ON CACHE BOOL "Enable RmlUi UI support" FORCE) add_subdirectory(extern/aurora EXCLUDE_FROM_ALL) target_compile_definitions(aurora_mtx PRIVATE MTX_USE_PS=1) @@ -88,7 +89,6 @@ endif () option(DUSK_BUILD_WARNINGS "Enable compiler warnings (off by default)") option(DUSK_SELECTED_OPT "If on, selected parts of the project will be compiled with optimizations on Debug, intending to make the game run at 30 FPS. Note for MSVC: you will need to remove '/RTC1' from your debug flags in CMake.") -option(DUSK_MOVIE_SUPPORT "If on, compile against libjpeg-turbo to enable THP file decoding" ON) option(DUSK_PACKAGE_INSTALL "Install Dusklight with a Linux-native file structure" OFF) option(DUSK_GFX_DEBUG_GROUPS "Report debug groups to the native graphics API" ${DUSK_GFX_DEBUG_GROUPS_DEFAULT}) option(DUSK_ENABLE_CODE_MODS "Enable code mods" ON) @@ -133,69 +133,6 @@ if (MSVC) endif () endif () -if (DUSK_MOVIE_SUPPORT) - find_package(libjpeg-turbo 3.0 CONFIG QUIET) - if (libjpeg-turbo_FOUND) - message(STATUS "dusklight: Using system libjpeg-turbo") - else () - message(STATUS "dusklight: Fetching libjpeg-turbo") - include(ExternalProject) - set(_jpeg_install_dir ${CMAKE_BINARY_DIR}/libjpeg-turbo-install) - if (WIN32) - set(_jpeg_lib ${_jpeg_install_dir}/lib/turbojpeg-static.lib) - else () - set(_jpeg_lib ${_jpeg_install_dir}/lib/libturbojpeg.a) - endif () - set(_jpeg_cmake_args - -DCMAKE_INSTALL_PREFIX=${_jpeg_install_dir} - -DCMAKE_PROJECT_INCLUDE=${CMAKE_CURRENT_SOURCE_DIR}/cmake/WindowsTargetProcessor.cmake - -DENABLE_SHARED=OFF - -DWITH_TURBOJPEG=ON - -DWITH_JAVA=OFF - -DCMAKE_INSTALL_LIBDIR=lib - ) - if (CMAKE_TOOLCHAIN_FILE) - get_filename_component(_jpeg_toolchain_file "${CMAKE_TOOLCHAIN_FILE}" ABSOLUTE BASE_DIR "${CMAKE_SOURCE_DIR}") - list(APPEND _jpeg_cmake_args -DCMAKE_TOOLCHAIN_FILE=${_jpeg_toolchain_file}) - endif () - set(_jpeg_passthrough_vars - ANDROID_ABI - ANDROID_PLATFORM - CMAKE_BUILD_TYPE - CMAKE_C_COMPILER - CMAKE_C_COMPILER_LAUNCHER - CMAKE_MAKE_PROGRAM - CMAKE_MSVC_RUNTIME_LIBRARY - CMAKE_MSVC_DEBUG_INFORMATION_FORMAT - CMAKE_OSX_ARCHITECTURES - CMAKE_OSX_DEPLOYMENT_TARGET - CMAKE_OSX_SYSROOT - DEPLOYMENT_TARGET - ENABLE_ARC - ENABLE_BITCODE - PLATFORM - ) - foreach(_var IN LISTS _jpeg_passthrough_vars) - if (DEFINED ${_var}) - list(APPEND _jpeg_cmake_args -D${_var}=${${_var}}) - endif () - endforeach () - ExternalProject_Add(libjpeg-turbo-ext - URL https://github.com/libjpeg-turbo/libjpeg-turbo/archive/refs/tags/3.1.0.tar.gz - URL_HASH SHA256=35fec2e1ddfb05ecf6d93e50bc57c1e54bc81c16d611ddf6eff73fff266d8285 - CMAKE_ARGS ${_jpeg_cmake_args} - BUILD_BYPRODUCTS ${_jpeg_lib} - ) - file(MAKE_DIRECTORY ${_jpeg_install_dir}/include) - add_library(libjpeg-turbo::turbojpeg-static STATIC IMPORTED GLOBAL) - set_target_properties(libjpeg-turbo::turbojpeg-static PROPERTIES - IMPORTED_LOCATION ${_jpeg_lib} - INTERFACE_INCLUDE_DIRECTORIES ${_jpeg_install_dir}/include - ) - add_dependencies(libjpeg-turbo::turbojpeg-static libjpeg-turbo-ext) - endif () -endif () - if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") # -Wno-multichar: Multi-character constants ('ABCD') are implementation-defined but all compilers # (CW, GCC, Clang, MSVC) encode them identically in big-endian order. @@ -303,7 +240,7 @@ include(cmake/GameABIConfig.cmake) find_package(Threads REQUIRED) set(GAME_COMPILE_DEFS DUSK_BUILDING_GAME=1) -set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd +set(GAME_LIBS aurora::core aurora::gx aurora::gd aurora::si aurora::vi aurora::pad aurora::mtx aurora::os aurora::dvd aurora::thp aurora::card borealis::cli borealis::crash borealis::data borealis::disc borealis::discord borealis::file_select borealis::io borealis::log borealis::net borealis::presentation borealis::sentry borealis::update borealis::ws freeverb cxxopts::cxxopts absl::flat_hash_map nlohmann_json::nlohmann_json TracyClient fmt::fmt Threads::Threads zstd::libzstd dusklight_game_headers) if (DUSK_HAS_FUNCHOOK) @@ -314,15 +251,6 @@ if (WIN32) list(APPEND GAME_LIBS Ws2_32) endif () -if (DUSK_MOVIE_SUPPORT) - if (TARGET libjpeg-turbo::turbojpeg-static) - list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg-static) - else () - list(APPEND GAME_LIBS libjpeg-turbo::turbojpeg) - endif () - list(APPEND GAME_COMPILE_DEFS MOVIE_SUPPORT=1) -endif () - if (DUSK_ENABLE_CODE_MODS) list(APPEND GAME_COMPILE_DEFS DUSK_CODE_MODS=1) endif () diff --git a/extern/aurora b/extern/aurora index f1189541e5..b6b0b34c4a 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit f1189541e5d8b97fdf61946377853488d504d9df +Subproject commit b6b0b34c4a4f3e15cec39f97b9ae7e397bd5d8cf diff --git a/include/d/actor/d_a_movie_player.h b/include/d/actor/d_a_movie_player.h index 24b1c683d3..785f9458ab 100644 --- a/include/d/actor/d_a_movie_player.h +++ b/include/d/actor/d_a_movie_player.h @@ -4,6 +4,7 @@ #if !TARGET_PC #include #else +#include #include #include #endif @@ -17,29 +18,6 @@ struct daMP_THPReadBuffer { }; #if TARGET_PC -// Copying here because thp.h is probably erroneous in the dolphin lib, -// and it's kind of a problem being there (Aurora owns the headers). -// TODO: Move this stuff in decomp? -typedef struct THPAudioRecordHeader { - BE(u32) offsetNextChannel; - BE(u32) sampleSize; - BE(s16) lCoef[8][2]; - BE(s16) rCoef[8][2]; - BE(s16) lYn1; - BE(s16) lYn2; - BE(s16) rYn1; - BE(s16) rYn2; -} THPAudioRecordHeader; - -typedef struct THPAudioDecodeInfo { - u8* encodeData; - u32 offsetNibbles; - u8 predictor; - u8 scale; - s16 yn1; - s16 yn2; -} THPAudioDecodeInfo; - typedef struct THPTextureSet { u8* ytexture; u8* utexture; @@ -86,10 +64,6 @@ typedef struct THPHeader { /* 0x2C */ BE(u32) finalFrameDataOffsets; } THPHeader; -static u32 THPAudioDecode(s16* audioBuffer, u8* audioFrame, s32 flag); -static s32 __THPAudioGetNewSample(THPAudioDecodeInfo* info); -static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr); - #define THP_AUDIO_BUFFER_COUNT 3 #define THP_READ_BUFFER_COUNT 10 #define THP_TEXTURE_SET_COUNT 3 diff --git a/src/d/actor/d_a_demo00.cpp b/src/d/actor/d_a_demo00.cpp index 60a99d4d54..b89965a8ce 100644 --- a/src/d/actor/d_a_demo00.cpp +++ b/src/d/actor/d_a_demo00.cpp @@ -1103,14 +1103,8 @@ inline int daDemo00_c::execute() { case 2: { u16 sp0A = sp0E & 0x3FFF; if ((sp0E & 0xC000) == 0) { -#if !MOVIE_SUPPORT - // If movie support isn't available, automatically reset. - // TPHD-esque. Maybe not the best solution, but it works. - dComIfGp_event_reset(); -#else fopAcM_create(fpcNm_MOVIE_PLAYER_e, sp0A, NULL, fopAcM_GetRoomNo(this), NULL, NULL, 0xFF); mDoGph_gInf_c::fadeOut(1.0f); -#endif } else { switch (sp0A) { case 0: diff --git a/src/d/actor/d_a_movie_player.cpp b/src/d/actor/d_a_movie_player.cpp index 5f4290611f..5d076b759e 100644 --- a/src/d/actor/d_a_movie_player.cpp +++ b/src/d/actor/d_a_movie_player.cpp @@ -15,15 +15,12 @@ #pragma optimize_for_size off #include -#include #include "JSystem/JAudio2/JASAiCtrl.h" #include "JSystem/JAudio2/JASDriverIF.h" #include "JSystem/JKernel/JKRExpHeap.h" #include "Z2AudioLib/Z2Instances.h" #include "d/actor/d_a_movie_player.h" -#include - #include "f_op/f_op_overlap_mng.h" #include "JSystem/JAudio2/JASCriticalSection.h" @@ -32,9 +29,6 @@ #include "helpers/gx_helper.h" #include "dusk/os.h" #include "dusk/layout.hpp" -#if MOVIE_SUPPORT -#include "turbojpeg.h" -#endif #endif inline s32 daMP_NEXT_READ_SIZE(daMP_THPReadBuffer* readBuf) { @@ -49,7 +43,8 @@ inline s32 daMP_NEXT_READ_SIZE(daMP_THPReadBuffer* readBuf) { #define OS_THREAD_ATTR OS_THREAD_ATTR_DETACH #endif -#if defined(__cplusplus) && !TARGET_PC +#if !TARGET_PC +#if defined(__cplusplus) extern "C" { #endif @@ -217,7 +212,6 @@ static void __THPAudioInitialize(THPAudioDecodeInfo* info, u8* ptr) { info->encodeData++; } -#if !TARGET_PC ATTRIBUTE_ALIGN(32) static u8 THPStatistics[1120]; ATTRIBUTE_ALIGN(32) static THPHuffmanTab* Ydchuff; @@ -2587,104 +2581,9 @@ static void __THPHuffDecodeDCTCompV(__REGISTER THPFileInfo* info, THPCoeff* bloc #else // !TARGET_PC static daMP_THPPlayer daMP_ActivePlayer; - -#if MOVIE_SUPPORT -static std::vector FixedJpegData; -static tjhandle JpegDecompressHandle; - -static const std::vector& FixJpeg(const std::span data) { - FixedJpegData.resize(0); - FixedJpegData.reserve(data.size()); - - size_t startOfScanLocation = 0; - for (; startOfScanLocation < data.size() - 1; startOfScanLocation++) { - if (data[startOfScanLocation] == 0xFF && data[startOfScanLocation + 1] == 0xDA) { - goto sosFound; - } - } - - CRASH("Unable to find SOS marker!"); - - sosFound: - - startOfScanLocation += 2; // TODO: Skip entire SOS header? - - size_t endOfImage = data.size() - 1; - for (; endOfImage > startOfScanLocation; endOfImage--) { - if (data[endOfImage] == 0xFF && data[endOfImage + 1] == 0xD9) { - goto eoiFound; - } - } - - CRASH("Unable to find EOI marker!"); - eoiFound: - - // Copy data before SOS - for (size_t i = 0; i < startOfScanLocation; i++) { - FixedJpegData.push_back(data[i]); - } - - // Copy data inside SOS, fixing up lacking of "byte shuffling" - for (size_t i = startOfScanLocation; i < endOfImage; i++) { - u8 value = data[i]; - FixedJpegData.push_back(value); - if (value == 0xFF) { - FixedJpegData.push_back(0x00); - } - } - - // Copy data after SOS. - for (size_t i = endOfImage; i < data.size(); i++) { - FixedJpegData.push_back(data[i]); - } - - return FixedJpegData; -} - -static s32 THPVideoDecode(void* file, size_t fileSize, void* tileY, void* tileU, void* tileV, void*) { - assert(JpegDecompressHandle); - - const auto handle = JpegDecompressHandle; - const auto fixedData = FixJpeg(std::span(static_cast(file), fileSize)); - - auto ret = tj3DecompressHeader(handle, fixedData.data(), fixedData.size()); - if (ret == -1) { - OSReport_Error("Parsing JPEG header failed: %s", tj3GetErrorStr(handle)); - return 1; - } - - if (tj3Get(handle, TJPARAM_JPEGWIDTH) != daMP_ActivePlayer.videoInfo.xSize) { - OSReport_Error("Invalid width in video frame!"); - return 1; - } - - if (tj3Get(handle, TJPARAM_JPEGHEIGHT) != daMP_ActivePlayer.videoInfo.ySize) { - OSReport_Error("Invalid height in video frame!"); - return 1; - } - - ret = tj3Set(handle, TJPARAM_SUBSAMP, TJSAMP_420); - if (ret != 0) { - OSReport_Error("Failed to set subsampling mode: %s", tj3GetErrorStr(handle)); - return 1; - } - - u8* planes[3] = {static_cast(tileY), static_cast(tileU), static_cast(tileV)}; - ret = tj3DecompressToYUVPlanes8(handle, fixedData.data(), fixedData.size(), planes, nullptr); - if (ret != 0) { - OSReport_Error("Image decompression failed: %s", tj3GetErrorStr(handle)); - return 1; - } - - return 0; -} -#else // MOVIE_SUPPORT -static s32 THPVideoDecode(void*, size_t, void*, void*, void*, void*) { - return 1; // Immediate error. -} -#endif #endif +#if !TARGET_PC static BOOL THPInit() { #if !TARGET_PC u8* base; @@ -2712,9 +2611,10 @@ static BOOL THPInit() { return TRUE; } -#if defined(__cplusplus) && !TARGET_PC +#if defined(__cplusplus) } #endif +#endif // !TARGET_PC #if !TARGET_PC // Defined earlier in file. static daMP_THPPlayer daMP_ActivePlayer; @@ -2937,9 +2837,6 @@ static void daMP_VideoDecode(daMP_THPReadBuffer* readBuffer) { case 0: { if ((daMP_ActivePlayer.videoError = THPVideoDecode( tile, -#if TARGET_PC - *tileOffsets, -#endif textureSet->ytexture, textureSet->utexture, textureSet->vtexture, daMP_ActivePlayer.thpWork))) { @@ -3434,26 +3331,19 @@ static void daMP_THPGXYuv2RgbDraw(u8* y_data, u8* u_data, u8* v_data, s16 x, TGXTexObj tobj0; TGXTexObj tobj1; TGXTexObj tobj2; -#if TARGET_PC -#define FMT (GXTexFmt)GX_TF_R8_PC -#else -#define FMT GX_TF_I8 -#endif - GXInitTexObj(&tobj0, y_data, textureWidth, textureHeight, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj0, y_data, textureWidth, textureHeight, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj0, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj0, GX_TEXMAP0); - GXInitTexObj(&tobj1, u_data, textureWidth >> 1, textureHeight >> 1, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj1, u_data, textureWidth >> 1, textureHeight >> 1, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj1, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj1, GX_TEXMAP1); - GXInitTexObj(&tobj2, v_data, textureWidth >> 1, textureHeight >> 1, FMT, GX_CLAMP, GX_CLAMP, GX_FALSE); + GXInitTexObj(&tobj2, v_data, textureWidth >> 1, textureHeight >> 1, GX_TF_I8, GX_CLAMP, GX_CLAMP, GX_FALSE); GXInitTexObjLOD(&tobj2, GX_NEAR, GX_NEAR, 0.0f, 0.0f, 0.0f, 0, 0, GX_ANISO_1); GXLoadTexObj(&tobj2, GX_TEXMAP2); -#undef FMT - GXBegin(GX_QUADS, GX_VTXFMT7, 4); GXPosition3s16(x, y, 0); GXTexCoord2u16(0, 0); @@ -3774,13 +3664,6 @@ static BOOL daMP_THPPlayerOpen(char const* filename, BOOL onMemory) { } static BOOL daMP_THPPlayerClose() { -#if TARGET_PC && MOVIE_SUPPORT - tj3Destroy(JpegDecompressHandle); - JpegDecompressHandle = nullptr; - - FixedJpegData.clear(); -#endif - if (daMP_ActivePlayer.open && daMP_ActivePlayer.state == 0) { daMP_ActivePlayer.open = 0; DVDClose(&daMP_ActivePlayer.fileInfo); @@ -3832,11 +3715,6 @@ static BOOL daMP_THPPlayerSetBuffer(u8* buffer) { ysize = ALIGN_NEXT(daMP_ActivePlayer.videoInfo.xSize * daMP_ActivePlayer.videoInfo.ySize, 32); uvsize = ALIGN_NEXT(daMP_ActivePlayer.videoInfo.xSize * daMP_ActivePlayer.videoInfo.ySize / 4, 32); -#if TARGET_PC - assert(ysize >= tj3YUVPlaneSize(0, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); - assert(uvsize >= tj3YUVPlaneSize(1, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); - assert(uvsize >= tj3YUVPlaneSize(2, daMP_ActivePlayer.videoInfo.xSize, 0, daMP_ActivePlayer.videoInfo.ySize, TJSAMP_420)); -#endif for (i = 0; i < ARRAY_SIZE(daMP_ActivePlayer.textureSet); i++) { daMP_ActivePlayer.textureSet[i].ytexture = ptr; @@ -4329,15 +4207,6 @@ static BOOL daMP_ActivePlayer_Init(char const* moviePath) { daMP_THPPlayerSetBuffer((u8*)daMP_buffer); -#if TARGET_PC && MOVIE_SUPPORT - assert(JpegDecompressHandle == nullptr); - JpegDecompressHandle = tj3Init(TJINIT_DECOMPRESS); - if (JpegDecompressHandle == nullptr) { - OSReport_Error("Failed to create turbojpeg handle: %s", tj3GetErrorStr(nullptr)); - return 0; - } -#endif - if (!daMP_THPPlayerPrepare(0, 0, daMP_audioInfo.sndNumTracks != 1 ? OSGetTick() % daMP_audioInfo.sndNumTracks : 0)) { OSReport("Fail to prepare\n"); #if DEBUG