From 69f5c46b469ed7787c9aff6dade97a3ce335ad86 Mon Sep 17 00:00:00 2001 From: Craig Carnell <1188869+cscd98@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:46:18 +0000 Subject: [PATCH 1/2] Disable features not needed for libretro core, fix compilation errors --- CMakeLists.txt | 24 +++++++ src/citra_libretro/CMakeLists.txt | 9 ++- src/core/core.cpp | 2 +- src/core/file_sys/archive_extsavedata.cpp | 2 +- src/core/file_sys/archive_ncch.cpp | 2 +- src/core/file_sys/ivfc_archive.cpp | 4 +- src/video_core/CMakeLists.txt | 85 ++++++++++++----------- 7 files changed, 81 insertions(+), 47 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7654bccb268..b81899c3cfd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,6 +54,8 @@ else() set(IS_RELEASE_BUILD ON) endif() +option(ENABLE_VULKAN "Enable Vulkan Video Core" ON) + # LTO takes too much memory and time using MSVC. if (NOT MSVC AND NOT MINGW AND IS_RELEASE_BUILD) set(DEFAULT_ENABLE_LTO ON) @@ -92,6 +94,20 @@ option(ENABLE_LTO "Enable link time optimization" ${DEFAULT_ENABLE_LTO}) option(CITRA_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON) option(CITRA_WARNINGS_AS_ERRORS "Enable warnings as errors" ON) +# Disable features not used by a libretro core +# ======================================================================= +if(ENABLE_LIBRETRO) + set(ENABLE_QT OFF) + set(ENABLE_QT_UPDATER OFF) + set(ENABLE_DEDICATED_ROOM OFF) + set(ENABLE_WEB_SERVICE OFF) + set(ENABLE_SCRIPTING OFF) + set(ENABLE_CUBEB OFF) + set(ENABLE_OPENAL OFF) + set(ENABLE_TESTS OFF) + set(CITRA_ENABLE_BUNDLE_TARGET OFF) +endif() + include(CitraHandleSystemLibs) if (CITRA_USE_PRECOMPILED_HEADERS) @@ -326,6 +342,14 @@ endif() # Use system tsl::robin_map if available (otherwise we fallback to version bundled with dynarmic) find_package(tsl-robin-map QUIET) +if (NOT TARGET tsl::robin_map) + if (EXISTS "${CMAKE_SOURCE_DIR}/externals/dynarmic/externals/robin-map/CMakeLists.txt") + add_subdirectory(externals/dynarmic/externals/robin-map) + else() + message(FATAL_ERROR "tsl-robin-map not found: please install it or initialize submodules") + endif() +endif() + # Platform-specific library requirements # ====================================== diff --git a/src/citra_libretro/CMakeLists.txt b/src/citra_libretro/CMakeLists.txt index 8fe7cc267b6..7569b30f745 100644 --- a/src/citra_libretro/CMakeLists.txt +++ b/src/citra_libretro/CMakeLists.txt @@ -8,8 +8,6 @@ add_library(citra_libretro SHARED input/input_factory.h input/mouse_tracker.cpp input/mouse_tracker.h - vulkan/vk_swapchain.cpp - vulkan/vk_swapchain.h citra_libretro.cpp citra_libretro.h environment.cpp @@ -17,6 +15,13 @@ add_library(citra_libretro SHARED core_settings.cpp core_settings.h) +if(ENABLE_VULKAN) + add_library(citra_libretro SHARED + vulkan/vk_swapchain.cpp + vulkan/vk_swapchain.h + ) +endif() + create_target_directory_groups(citra_libretro) target_link_libraries(citra_common PRIVATE libretro) diff --git a/src/core/core.cpp b/src/core/core.cpp index 22d0a1de6bd..d5df8087d58 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -395,7 +395,7 @@ System::ResultStatus System::Init(Frontend::EmuWindow& emu_window, #else for (u32 i = 0; i < num_cores; ++i) { cpu_cores.push_back( - std::make_shared(this, *memory, USER32MODE, i, timing->GetTimer(i))); + std::make_shared(*this, *memory, USER32MODE, i, timing->GetTimer(i))); } LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif diff --git a/src/core/file_sys/archive_extsavedata.cpp b/src/core/file_sys/archive_extsavedata.cpp index 06c0334670d..8f9566280ea 100644 --- a/src/core/file_sys/archive_extsavedata.cpp +++ b/src/core/file_sys/archive_extsavedata.cpp @@ -42,7 +42,7 @@ class FixSizeDiskFile : public DiskFile { if (offset > size) { return ERR_WRITE_BEYOND_END; } else if (offset == size) { - return 0ULL; + return static_cast(0); } if (offset + length > size) { diff --git a/src/core/file_sys/archive_ncch.cpp b/src/core/file_sys/archive_ncch.cpp index 49744efd263..4c705cb94dd 100644 --- a/src/core/file_sys/archive_ncch.cpp +++ b/src/core/file_sys/archive_ncch.cpp @@ -258,7 +258,7 @@ ResultVal NCCHFile::Write(const u64 offset, const std::size_t lengt const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to NCCH file"); // TODO(shinyquagsire23): Find error code - return 0ULL; + return static_cast(0); } u64 NCCHFile::GetSize() const { diff --git a/src/core/file_sys/ivfc_archive.cpp b/src/core/file_sys/ivfc_archive.cpp index d5d46e0ef58..f393b828a36 100644 --- a/src/core/file_sys/ivfc_archive.cpp +++ b/src/core/file_sys/ivfc_archive.cpp @@ -105,7 +105,7 @@ ResultVal IVFCFile::Write(const u64 offset, const std::size_t lengt const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); // TODO(Subv): Find error code - return 0ULL; + return static_cast(0); } u64 IVFCFile::GetSize() const { @@ -136,7 +136,7 @@ ResultVal IVFCFileInMemory::Write(const u64 offset, const std::size const bool flush, const u8* buffer) { LOG_ERROR(Service_FS, "Attempted to write to IVFC file"); // TODO(Subv): Find error code - return 0ULL; + return static_cast(0); } u64 IVFCFileInMemory::GetSize() const { diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 50c262becdd..80f3f271aaf 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -96,46 +96,6 @@ add_library(video_core STATIC renderer_software/sw_rasterizer.h renderer_software/sw_texturing.cpp renderer_software/sw_texturing.h - renderer_vulkan/pica_to_vk.h - renderer_vulkan/renderer_vulkan.cpp - renderer_vulkan/renderer_vulkan.h - renderer_vulkan/vk_blit_helper.cpp - renderer_vulkan/vk_blit_helper.h - renderer_vulkan/vk_common.cpp - renderer_vulkan/vk_common.h - renderer_vulkan/vk_descriptor_pool.cpp - renderer_vulkan/vk_descriptor_pool.h - renderer_vulkan/vk_graphics_pipeline.cpp - renderer_vulkan/vk_graphics_pipeline.h - renderer_vulkan/vk_master_semaphore.cpp - renderer_vulkan/vk_master_semaphore.h - renderer_vulkan/vk_memory_util.cpp - renderer_vulkan/vk_memory_util.h - renderer_vulkan/vk_rasterizer.cpp - renderer_vulkan/vk_rasterizer.h - renderer_vulkan/vk_rasterizer_cache.cpp - renderer_vulkan/vk_scheduler.cpp - renderer_vulkan/vk_scheduler.h - renderer_vulkan/vk_resource_pool.cpp - renderer_vulkan/vk_resource_pool.h - renderer_vulkan/vk_instance.cpp - renderer_vulkan/vk_instance.h - renderer_vulkan/vk_pipeline_cache.cpp - renderer_vulkan/vk_pipeline_cache.h - renderer_vulkan/vk_platform.cpp - renderer_vulkan/vk_platform.h - renderer_vulkan/vk_present_window.cpp - renderer_vulkan/vk_present_window.h - renderer_vulkan/vk_renderpass_cache.cpp - renderer_vulkan/vk_renderpass_cache.h - renderer_vulkan/vk_shader_util.cpp - renderer_vulkan/vk_shader_util.h - renderer_vulkan/vk_stream_buffer.cpp - renderer_vulkan/vk_stream_buffer.h - renderer_vulkan/vk_swapchain.cpp - renderer_vulkan/vk_swapchain.h - renderer_vulkan/vk_texture_runtime.cpp - renderer_vulkan/vk_texture_runtime.h shader/debug_data.h shader/generator/glsl_fs_shader_gen.cpp shader/generator/glsl_fs_shader_gen.h @@ -173,6 +133,51 @@ add_library(video_core STATIC video_core.h ) +if(ENABLE_VULKAN) + add_library(video_core STATIC + renderer_vulkan/pica_to_vk.h + renderer_vulkan/renderer_vulkan.cpp + renderer_vulkan/renderer_vulkan.h + renderer_vulkan/vk_blit_helper.cpp + renderer_vulkan/vk_blit_helper.h + renderer_vulkan/vk_common.cpp + renderer_vulkan/vk_common.h + renderer_vulkan/vk_descriptor_pool.cpp + renderer_vulkan/vk_descriptor_pool.h + renderer_vulkan/vk_graphics_pipeline.cpp + renderer_vulkan/vk_graphics_pipeline.h + renderer_vulkan/vk_master_semaphore.cpp + renderer_vulkan/vk_master_semaphore.h + renderer_vulkan/vk_memory_util.cpp + renderer_vulkan/vk_memory_util.h + renderer_vulkan/vk_rasterizer.cpp + renderer_vulkan/vk_rasterizer.h + renderer_vulkan/vk_rasterizer_cache.cpp + renderer_vulkan/vk_scheduler.cpp + renderer_vulkan/vk_scheduler.h + renderer_vulkan/vk_resource_pool.cpp + renderer_vulkan/vk_resource_pool.h + renderer_vulkan/vk_instance.cpp + renderer_vulkan/vk_instance.h + renderer_vulkan/vk_pipeline_cache.cpp + renderer_vulkan/vk_pipeline_cache.h + renderer_vulkan/vk_platform.cpp + renderer_vulkan/vk_platform.h + renderer_vulkan/vk_present_window.cpp + renderer_vulkan/vk_present_window.h + renderer_vulkan/vk_renderpass_cache.cpp + renderer_vulkan/vk_renderpass_cache.h + renderer_vulkan/vk_shader_util.cpp + renderer_vulkan/vk_shader_util.h + renderer_vulkan/vk_stream_buffer.cpp + renderer_vulkan/vk_stream_buffer.h + renderer_vulkan/vk_swapchain.cpp + renderer_vulkan/vk_swapchain.h + renderer_vulkan/vk_texture_runtime.cpp + renderer_vulkan/vk_texture_runtime.h + ) +endif() + add_dependencies(video_core host_shaders) target_include_directories(video_core PRIVATE ${HOST_SHADERS_INCLUDE}) From ee2c4d2b3d509dade7480083a63f281d28bd1cfd Mon Sep 17 00:00:00 2001 From: Craig Carnell <1188869+cscd98@users.noreply.github.com> Date: Tue, 16 Dec 2025 16:46:35 +0000 Subject: [PATCH 2/2] Add webOS support --- CMakeLists.txt | 12 +++++++ src/common/atomic_ops.h | 73 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index b81899c3cfd..27083812ea4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -108,6 +108,18 @@ if(ENABLE_LIBRETRO) set(CITRA_ENABLE_BUNDLE_TARGET OFF) endif() +if(CMAKE_CXX_COMPILER MATCHES "webos" OR + CMAKE_CXX_COMPILER MATCHES "starfish") + set(WEBOS ON) + add_definitions(-DWEBOS=1) +endif() + +if(WEBOS) + set(ENABLE_VULKAN OFF) + # temp fix for fmt/ranges.h:211:59: error: self-comparison always evaluates to true [-Werror=tautological-compare] + add_definitions(-Wno-tautological-compare) +endif() + include(CitraHandleSystemLibs) if (CITRA_USE_PRECOMPILED_HEADERS) diff --git a/src/common/atomic_ops.h b/src/common/atomic_ops.h index c18bb33c4a2..f7eb64f58a7 100644 --- a/src/common/atomic_ops.h +++ b/src/common/atomic_ops.h @@ -7,6 +7,9 @@ #if _MSC_VER #include +#if #WEBOS +#include +#endif #else #include #endif @@ -89,6 +92,76 @@ namespace Common { return result; } +#elif defined(WEBOS) + +inline std::mutex g_atomic128_mutex; + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) { + return __sync_bool_compare_and_swap(pointer, expected, value); +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected) { + return __sync_bool_compare_and_swap(pointer, expected, value); +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected) { + return __sync_bool_compare_and_swap(pointer, expected, value); +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected) { + return __sync_bool_compare_and_swap(pointer, expected, value); +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected) { + std::lock_guard lock(g_atomic128_mutex); + u128 current; + std::memcpy(current.data(), (const void*)pointer, sizeof(u128)); + bool match = (current == expected); + if (match) { + std::memcpy((void*)pointer, value.data(), sizeof(u128)); + } + return match; +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected, u8& actual) { + actual = __sync_val_compare_and_swap(pointer, expected, value); + return actual == expected; +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u16* pointer, u16 value, u16 expected, u16& actual) { + actual = __sync_val_compare_and_swap(pointer, expected, value); + return actual == expected; +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u32* pointer, u32 value, u32 expected, u32& actual) { + actual = __sync_val_compare_and_swap(pointer, expected, value); + return actual == expected; +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u64 value, u64 expected, u64& actual) { + actual = __sync_val_compare_and_swap(pointer, expected, value); + return actual == expected; +} + +[[nodiscard]] inline bool AtomicCompareAndSwap(volatile u64* pointer, u128 value, u128 expected, u128& actual) { + std::lock_guard lock(g_atomic128_mutex); + u128 current; + std::memcpy(current.data(), (const void*)pointer, sizeof(u128)); + bool match = (current == expected); + if (match) { + std::memcpy((void*)pointer, value.data(), sizeof(u128)); + } + actual = current; + return match; +} + +[[nodiscard]] inline u128 AtomicLoad128(volatile u64* pointer) { + std::lock_guard lock(g_atomic128_mutex); + u128 result; + std::memcpy(result.data(), (const void*)pointer, sizeof(u128)); + return result; +} + #else [[nodiscard]] inline bool AtomicCompareAndSwap(volatile u8* pointer, u8 value, u8 expected) {