diff --git a/config/NxEmu.config.development b/config/NxEmu.config.development index 69b2a705..143b2a8b 100644 --- a/config/NxEmu.config.development +++ b/config/NxEmu.config.development @@ -1,6 +1,7 @@ { "Core" : { - "ModuleDirectory-x64" : "..\\..\\..\\modules\\x64" + "ModuleDirectory-x64" : "..\\..\\..\\modules\\x64", + "ModuleDirectory-arm64" : "../../../modules/arm64" }, "UI" : { "Language" : { diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt index 47b06e47..81910255 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -3,6 +3,16 @@ if (NOT TARGET fmt::fmt) add_subdirectory(fmt) endif() +# AppleClang 21 rejects the consteval path used by the bundled fmt 10.x. +# fmt 10.1.1 controls the constructor qualifier with FMT_CONSTEVAL; the newer +# FMT_USE_CONSTEVAL switch does not exist in this bundled version. Define +# FMT_CONSTEVAL to an empty replacement on the affected toolchain, matching +# the upstream workaround for fmt 10.x on AppleClang 21. +if(APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" AND + CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 21) + target_compile_definitions(fmt PUBLIC FMT_CONSTEVAL=) +endif() + # Boost if(NOT TARGET Boost::headers) set(BOOST_SUPERPROJECT_VERSION "1.84.0" CACHE STRING "Boost version string for modular CMakeLists") @@ -69,12 +79,16 @@ if(TARGET libzstd_static AND NOT TARGET zstd::zstd) endif() # zlib + minizip (nxemu-loader firmware zip extraction) -if(NOT TARGET zlibstatic) +# The bundled zlib 1.3.1 CMake temporarily renames its source zconf.h during +# out-of-source configuration. Restoring that file immediately makes quoted +# includes select the unconfigured source header on macOS, so POSIX prototypes +# such as read/write/lseek are lost. Use the SDK zlib on Apple instead. +if(APPLE) + find_package(ZLIB REQUIRED) +elseif(NOT TARGET zlibstatic) set(ZLIB_BUILD_EXAMPLES OFF CACHE BOOL "Build zlib example/minigzip programs" FORCE) add_subdirectory("${CMAKE_SOURCE_DIR}/external/zlib" "${CMAKE_BINARY_DIR}/external/zlib") - # zlib's CMake renames the tracked source zconf.h -> zconf.h.included during - # out-of-source configure. Undo that so the submodule working tree stays clean. - # The build still uses the generated header in ${CMAKE_BINARY_DIR}/external/zlib. + # Preserve the existing non-Apple behavior. set(_nxemu_zlib_src "${CMAKE_SOURCE_DIR}/external/zlib") if(EXISTS "${_nxemu_zlib_src}/zconf.h.included" AND NOT EXISTS "${_nxemu_zlib_src}/zconf.h") file(RENAME "${_nxemu_zlib_src}/zconf.h.included" "${_nxemu_zlib_src}/zconf.h") diff --git a/src/3rd_party/discord-rpc/CMakeLists.txt b/src/3rd_party/discord-rpc/CMakeLists.txt index 127a4b70..079f76fc 100644 --- a/src/3rd_party/discord-rpc/CMakeLists.txt +++ b/src/3rd_party/discord-rpc/CMakeLists.txt @@ -1,3 +1,7 @@ +if(APPLE) + enable_language(OBJC) +endif() + add_library(discord-rpc STATIC src/discord_rpc.cpp src/rpc_connection.cpp diff --git a/src/common/path.cpp b/src/common/path.cpp index 3df37914..571ec65d 100644 --- a/src/common/path.cpp +++ b/src/common/path.cpp @@ -9,6 +9,9 @@ #include #include #include +#ifdef __APPLE__ +#include +#endif #endif #ifdef _WIN32 @@ -613,6 +616,29 @@ void Path::SetToModuleDirectory() bufferSize *= 2; buffPath.resize(bufferSize); } +#elif defined(__APPLE__) + uint32_t bufferSize = 4096; + std::vector buffPath(bufferSize); + + while (true) + { + uint32_t requiredSize = bufferSize; + if (_NSGetExecutablePath(buffPath.data(), &requiredSize) == 0) + { + m_path = buffPath.data(); + SetNameExtension(""); + return; + } + + if (requiredSize <= bufferSize) + { + m_path = ""; + return; + } + + bufferSize = requiredSize; + buffPath.resize(bufferSize); + } #else size_t bufferSize = 4096; std::vector buffPath(bufferSize); diff --git a/src/nxemu-core/modules/module_list.cpp b/src/nxemu-core/modules/module_list.cpp index 02206659..57ae620b 100644 --- a/src/nxemu-core/modules/module_list.cpp +++ b/src/nxemu-core/modules/module_list.cpp @@ -31,7 +31,14 @@ void ModuleList::AddModuleFromDir(const Path & dir) } while (dirFinder.FindNext(foundDir)); } - PathFinder fileFinder(Path(dir.GetDriveDirectory().c_str(), "*.dll")); +#if defined(_WIN32) + constexpr const char * modulePattern = "*.dll"; +#elif defined(__APPLE__) + constexpr const char * modulePattern = "*.dylib"; +#else + constexpr const char * modulePattern = "*.so"; +#endif + PathFinder fileFinder(Path(dir.GetDriveDirectory().c_str(), modulePattern)); Path foundFile; if (fileFinder.FindFirst(foundFile)) { diff --git a/src/nxemu-core/settings/core_settings.cpp b/src/nxemu-core/settings/core_settings.cpp index 2825dce4..a585c4d2 100644 --- a/src/nxemu-core/settings/core_settings.cpp +++ b/src/nxemu-core/settings/core_settings.cpp @@ -49,10 +49,16 @@ namespace } clearValue; }; +#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) + constexpr const char * ModuleDirectorySettingKey = "ModuleDirectory-arm64"; +#else + constexpr const char * ModuleDirectorySettingKey = "ModuleDirectory-x64"; +#endif + static CoreSetting settings[] = { { NXCoreSetting::AppBaseDirectory, &coreSettings.baseDir }, { NXCoreSetting::AppDirectory, &coreSettings.appDir }, - { NXCoreSetting::ModuleDirectory, "", "ModuleDirectory-x64", &coreSettings.moduleDir, &coreSettings.moduleDirValue, "./modules" }, + { NXCoreSetting::ModuleDirectory, "", ModuleDirectorySettingKey, &coreSettings.moduleDir, &coreSettings.moduleDirValue, "./modules" }, #ifdef _WIN32 #ifdef _DEBUG { NXCoreSetting::ModuleLoader, "modules", "loader", &coreSettings.moduleLoader, "loader\\nxemu-loader_d.dll" }, @@ -65,6 +71,11 @@ namespace { NXCoreSetting::ModuleVideo, "modules", "video", &coreSettings.moduleVideo, "video\\nxemu-video.dll" }, { NXCoreSetting::ModuleOs, "modules", "os", &coreSettings.moduleOs, "operating_system\\nxemu-os.dll" }, #endif +#elif defined(__APPLE__) + {NXCoreSetting::ModuleLoader, "modules", "loader", &coreSettings.moduleLoader, "loader/libnxemu-loader.dylib"}, + {NXCoreSetting::ModuleCpu, "modules", "cpu", &coreSettings.moduleCpu, "cpu/libnxemu-cpu.dylib"}, + {NXCoreSetting::ModuleVideo, "modules", "video", &coreSettings.moduleVideo, "video/libnxemu-video.dylib"}, + {NXCoreSetting::ModuleOs, "modules", "os", &coreSettings.moduleOs, "operating_system/libnxemu-os.dylib"}, #elif defined(ANDROID) {NXCoreSetting::ModuleLoader, "modules", "loader", &coreSettings.moduleLoader, "libnxemu-loader.so"}, {NXCoreSetting::ModuleCpu, "modules", "cpu", &coreSettings.moduleCpu, "libnxemu-cpu.so"}, diff --git a/src/nxemu-cpu/CMakeLists.txt b/src/nxemu-cpu/CMakeLists.txt index c2bfc5b2..dda0cc21 100644 --- a/src/nxemu-cpu/CMakeLists.txt +++ b/src/nxemu-cpu/CMakeLists.txt @@ -377,13 +377,12 @@ if(ARCHITECTURE_arm64) enable_language(C ASM) set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -x assembler-with-cpp") - if(NOT MSVC) + if(UNIX AND NOT APPLE) target_compile_options(nxemu-cpu PRIVATE $<$:-Wa,--noexecstack>) target_link_options(nxemu-cpu PRIVATE -Wl,-z,noexecstack) endif() target_sources(nxemu-cpu PRIVATE - dynarmic/backend/exception_handler_generic.cpp dynarmic/common/spin_lock_arm64.cpp dynarmic/backend/arm64/a32_jitstate.cpp dynarmic/backend/arm64/a32_address_space.cpp @@ -419,19 +418,83 @@ if(ARCHITECTURE_arm64) dynarmic/backend/arm64/stack_layout.h dynarmic/backend/arm64/verbose_debugging_output.cpp dynarmic/backend/arm64/verbose_debugging_output.h - nce/arm_nce_asm_definitions.h - nce/arm_nce.cpp - nce/arm_nce.h - nce/arm_nce.s - nce/guest_context.h - nce/instructions.h - nce/interpreter_visitor.cpp - nce/interpreter_visitor.h - nce/patcher.cpp - nce/patcher.h - nce/visitor_base.h ) + if(APPLE) + find_program(NXEMU_MIG_EXECUTABLE mig REQUIRED) + + find_path(NXEMU_MACH_EXC_INCLUDE_DIR mach/mach_exc.defs) + if(NOT NXEMU_MACH_EXC_INCLUDE_DIR) + execute_process( + COMMAND xcrun --sdk macosx --show-sdk-path + OUTPUT_VARIABLE NXEMU_MACOS_SDK + OUTPUT_STRIP_TRAILING_WHITESPACE + COMMAND_ERROR_IS_FATAL ANY + ) + if(EXISTS "${NXEMU_MACOS_SDK}/usr/include/mach/mach_exc.defs") + set(NXEMU_MACH_EXC_INCLUDE_DIR "${NXEMU_MACOS_SDK}/usr/include") + endif() + endif() + if(NOT NXEMU_MACH_EXC_INCLUDE_DIR) + message(FATAL_ERROR "Unable to locate mach/mach_exc.defs required by Dynarmic fastmem on macOS") + endif() + + set(_nxemu_mig_dir "${CMAKE_CURRENT_BINARY_DIR}/dynarmic/backend/arm64/mig") + set(_nxemu_mig_user_c "${_nxemu_mig_dir}/mach_exc_user.c") + set(_nxemu_mig_user_h "${_nxemu_mig_dir}/mach_exc_user.h") + set(_nxemu_mig_server_c "${_nxemu_mig_dir}/mach_exc_server.c") + set(_nxemu_mig_server_h "${_nxemu_mig_dir}/mach_exc_server.h") + + add_custom_command( + OUTPUT + "${_nxemu_mig_user_c}" + "${_nxemu_mig_user_h}" + "${_nxemu_mig_server_c}" + "${_nxemu_mig_server_h}" + COMMAND ${CMAKE_COMMAND} -E make_directory "${_nxemu_mig_dir}" + COMMAND "${NXEMU_MIG_EXECUTABLE}" + -arch arm64 + -user "${_nxemu_mig_user_c}" + -header "${_nxemu_mig_user_h}" + -server "${_nxemu_mig_server_c}" + -sheader "${_nxemu_mig_server_h}" + "${NXEMU_MACH_EXC_INCLUDE_DIR}/mach/mach_exc.defs" + DEPENDS "${NXEMU_MACH_EXC_INCLUDE_DIR}/mach/mach_exc.defs" + VERBATIM + COMMENT "Generating Dynarmic Mach exception server for arm64" + ) + add_custom_target(nxemu-dynarmic-mig DEPENDS + "${_nxemu_mig_user_c}" + "${_nxemu_mig_user_h}" + "${_nxemu_mig_server_c}" + "${_nxemu_mig_server_h}" + ) + add_dependencies(nxemu-cpu nxemu-dynarmic-mig) + target_include_directories(nxemu-cpu PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + target_sources(nxemu-cpu PRIVATE + dynarmic/backend/exception_handler_macos.cpp + dynarmic/backend/exception_handler_macos_mig.c + ) + elseif(ANDROID OR CMAKE_SYSTEM_NAME STREQUAL "Linux") + target_compile_definitions(nxemu-cpu PRIVATE NXEMU_HAS_NCE=1) + target_sources(nxemu-cpu PRIVATE + dynarmic/backend/exception_handler_generic.cpp + nce/arm_nce_asm_definitions.h + nce/arm_nce.cpp + nce/arm_nce.h + nce/arm_nce.s + nce/guest_context.h + nce/instructions.h + nce/interpreter_visitor.cpp + nce/interpreter_visitor.h + nce/patcher.cpp + nce/patcher.h + nce/visitor_base.h + ) + else() + target_sources(nxemu-cpu PRIVATE dynarmic/backend/exception_handler_generic.cpp) + endif() + if(TARGET merry::oaknut) target_link_libraries(nxemu-cpu PRIVATE merry::oaknut) elseif(TARGET oaknut) diff --git a/src/nxemu-cpu/arm_dynarmic_32.cpp b/src/nxemu-cpu/arm_dynarmic_32.cpp index 52f01948..4396a7ec 100644 --- a/src/nxemu-cpu/arm_dynarmic_32.cpp +++ b/src/nxemu-cpu/arm_dynarmic_32.cpp @@ -520,7 +520,7 @@ void ArmDynarmic32::ClearInstructionCache() m_jit->ClearCache(); } -void ArmDynarmic32::InvalidateCacheRange(u64 addr, std::size_t size) +void ArmDynarmic32::InvalidateCacheRange(uint64_t addr, uint64_t size) { m_jit->InvalidateCacheRange(static_cast(addr), size); } diff --git a/src/nxemu-cpu/arm_dynarmic_64.cpp b/src/nxemu-cpu/arm_dynarmic_64.cpp index e293baef..fd1b07c8 100644 --- a/src/nxemu-cpu/arm_dynarmic_64.cpp +++ b/src/nxemu-cpu/arm_dynarmic_64.cpp @@ -158,7 +158,7 @@ public: return CheckMemoryAccess(vaddr, 16, CpuDebugWatchpointType::Write) && m_memory.WriteExclusive128(vaddr, value[1], value[0], expected[1], expected[0]); } - void InterpreterFallback(uint64_t /*pc*/, uint64_t /*num_instructions*/) override + void InterpreterFallback(uint64_t /*pc*/, std::size_t /*num_instructions*/) override { g_notify->BreakPoint(__FILE__, __LINE__); } diff --git a/src/nxemu-cpu/cpu_manager.cpp b/src/nxemu-cpu/cpu_manager.cpp index 765f805a..58ce318c 100644 --- a/src/nxemu-cpu/cpu_manager.cpp +++ b/src/nxemu-cpu/cpu_manager.cpp @@ -5,7 +5,7 @@ #if defined(_M_X64) || defined(ARCHITECTURE_x86_64) || defined(_M_ARM64) || defined(ARCHITECTURE_arm64) #include "exclusive_monitor_interface.h" #endif -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) #include "cpu_settings_identifiers.h" #include "nce/arm_nce.h" #include @@ -45,7 +45,7 @@ IPatchCollection * CpuInterface::CreatePatchCollection(bool is_application) ICpuCore * CpuInterface::CreateCpuCore(ICoreSystem & system, bool is64Bit, bool usesWallClock, IKernelProcess & process, uint32_t coreIndex) { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) if (is64Bit && g_settings && g_settings->GetBool(NXCpuSetting::NceEnabled)) { return new Core::ArmNce(system, usesWallClock, process, coreIndex); diff --git a/src/nxemu-cpu/cpu_settings.cpp b/src/nxemu-cpu/cpu_settings.cpp index cdaf0c50..a4b5e1c9 100644 --- a/src/nxemu-cpu/cpu_settings.cpp +++ b/src/nxemu-cpu/cpu_settings.cpp @@ -49,7 +49,7 @@ public: }; static CpuSetting settings[] = { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) +#if defined(NXEMU_HAS_NCE) {NXCpuSetting::CpuBackend, "cpu", "cpu_backend", &cpuSettings.cpu_backend, CpuBackend::Nce}, #else {NXCpuSetting::CpuBackend, "cpu", "cpu_backend", &cpuSettings.cpu_backend, CpuBackend::Dynarmic}, @@ -120,7 +120,11 @@ bool IsFastmemEnabled() void UpdateNceEnabled() { const bool has_39bit = g_settings->GetBool(NXCoreSetting::Has39BitAddressSpace); +#if defined(NXEMU_HAS_NCE) const bool is_nce = g_settings->GetInt(NXCpuSetting::CpuBackend) == static_cast(CpuBackend::Nce); +#else + const bool is_nce = false; +#endif if (is_nce && !IsFastmemEnabled()) { LOG_WARNING(Common, "Fastmem is required to natively execute code in a performant manner, falling back to Dynarmic"); @@ -237,6 +241,14 @@ void SetupCpuSetting(void) } } +#if !defined(NXEMU_HAS_NCE) + if (cpuSettings.cpu_backend == CpuBackend::Nce) + { + LOG_WARNING(Common, "NCE is unavailable on this host; using Dynarmic"); + cpuSettings.cpu_backend = CpuBackend::Dynarmic; + } +#endif + for (const CpuSetting & cpuSetting : settings) { switch (cpuSetting.settingType) diff --git a/src/nxemu-cpu/patch/patch_collection.cpp b/src/nxemu-cpu/patch/patch_collection.cpp index 72fb9afd..ca069382 100644 --- a/src/nxemu-cpu/patch/patch_collection.cpp +++ b/src/nxemu-cpu/patch/patch_collection.cpp @@ -12,14 +12,14 @@ PatchCollection::PatchCollection(ISystemModules & modules, bool is_application) m_is_application(is_application) { std::fill(std::begin(m_module_patcher_indices), std::end(m_module_patcher_indices), -1); -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) m_patchers.emplace_back(); #endif } void PatchCollection::PatchText(int32_t patch_index, const uint8_t * program_image, uint32_t image_size, uint32_t code_offset, uint32_t code_size) { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) if (!m_is_application || !g_settings->GetBool(NXCpuSetting::NceEnabled)) { return; @@ -41,7 +41,7 @@ void PatchCollection::PatchText(int32_t patch_index, const uint8_t * program_ima void PatchCollection::Relocate(int32_t patch_index, uint64_t load_base, uint8_t * program_image, uint32_t * image_size, uint32_t code_offset, uint32_t code_size, uint64_t * segment_addr, uint32_t * segment_size) { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) if (!m_is_application || !g_settings->GetBool(NXCpuSetting::NceEnabled)) { return; @@ -99,7 +99,7 @@ void PatchCollection::Relocate(int32_t patch_index, uint64_t load_base, uint8_t uint32_t PatchCollection::GetTotalPatchSize() const { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) if (!m_is_application || !g_settings->GetBool(NXCpuSetting::NceEnabled)) { return 0; @@ -118,7 +118,7 @@ uint32_t PatchCollection::GetTotalPatchSize() const uint32_t PatchCollection::GetPreTextSize(int32_t patch_index) const { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) if (!m_is_application || !g_settings->GetBool(NXCpuSetting::NceEnabled)) { return 0; @@ -142,7 +142,7 @@ uint32_t PatchCollection::GetPreTextSize(int32_t patch_index) const int32_t PatchCollection::GetLastIndex() const { -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) return (int32_t)(m_patchers.size()) - 1; #else return 0; diff --git a/src/nxemu-cpu/patch/patch_collection.h b/src/nxemu-cpu/patch/patch_collection.h index 3652a2e0..83f490f9 100644 --- a/src/nxemu-cpu/patch/patch_collection.h +++ b/src/nxemu-cpu/patch/patch_collection.h @@ -1,7 +1,7 @@ #pragma once #include -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) #include "nce/patcher.h" #include #endif @@ -25,7 +25,7 @@ private: ISystemModules & m_modules; bool m_is_application; int32_t m_module_patcher_indices[13]; -#if defined(_M_ARM64) || defined(ARCHITECTURE_arm64) || defined(__aarch64__) +#if defined(NXEMU_HAS_NCE) std::vector m_patchers; #endif }; diff --git a/src/nxemu-os/CMakeLists.txt b/src/nxemu-os/CMakeLists.txt index fc78feaa..ca9d0f4a 100644 --- a/src/nxemu-os/CMakeLists.txt +++ b/src/nxemu-os/CMakeLists.txt @@ -2,8 +2,8 @@ cmake_minimum_required(VERSION 3.18) # nxemu-os depends on yuzu "core", yuzu_audio_core, src/network, hid_core (which itself # links "core"), cubeb, SDL, etc. Host desktop builds may still be incomplete — default OFF. -# Android needs the OS plugin .so alongside loader/cpu/video, so default ON there. -if(ANDROID) +# Android and macOS require the OS plugin alongside loader/cpu/video. +if(ANDROID OR APPLE) set(_NXEMU_OS_BUILD_DEFAULT ON) else() set(_NXEMU_OS_BUILD_DEFAULT OFF) @@ -77,6 +77,13 @@ target_link_libraries(nxemu-os PRIVATE if(ANDROID) target_link_libraries(nxemu-os PRIVATE log) +elseif(APPLE) + find_library(NXEMU_SECURITY_FRAMEWORK Security REQUIRED) + find_library(NXEMU_COREFOUNDATION_FRAMEWORK CoreFoundation REQUIRED) + target_link_libraries(nxemu-os PRIVATE + "${NXEMU_SECURITY_FRAMEWORK}" + "${NXEMU_COREFOUNDATION_FRAMEWORK}" + ) endif() # Use BSD socket headers and TranslateIPv4(in_addr) path (Linux/macOS/Android). diff --git a/src/nxemu-os/core/hle/kernel/k_thread.h b/src/nxemu-os/core/hle/kernel/k_thread.h index fdd18f75..ecb43520 100644 --- a/src/nxemu-os/core/hle/kernel/k_thread.h +++ b/src/nxemu-os/core/hle/kernel/k_thread.h @@ -626,7 +626,8 @@ public: void ClearDpc(DpcFlag flag) { - this->GetStackParameters().dpc_flags &= ~static_cast(flag); + this->GetStackParameters().dpc_flags = static_cast( + this->GetStackParameters().dpc_flags & ~static_cast(flag)); } u8 GetDpc() const diff --git a/src/nxemu-os/core/hle/kernel/svc/svc_query_memory.cpp b/src/nxemu-os/core/hle/kernel/svc/svc_query_memory.cpp index 047ccc0a..1826b849 100644 --- a/src/nxemu-os/core/hle/kernel/svc/svc_query_memory.cpp +++ b/src/nxemu-os/core/hle/kernel/svc/svc_query_memory.cpp @@ -36,7 +36,8 @@ Result QueryProcessMemory(Core::System& system, uint64_t out_memory_info, PageIn R_TRY(process->GetKPageTable().QueryInfo(std::addressof(mem_info), out_page_info, address)); const auto svc_mem_info = mem_info.GetSvcMemoryInfo(); - current_memory.WriteBlock(out_memory_info, std::addressof(svc_mem_info), sizeof(svc_mem_info)); + current_memory.WriteBlock(Common::ProcessAddress{out_memory_info}, std::addressof(svc_mem_info), + sizeof(svc_mem_info)); R_SUCCEED(); } diff --git a/src/nxemu-os/core/hle/kernel/svc/svc_thread.cpp b/src/nxemu-os/core/hle/kernel/svc/svc_thread.cpp index d37e582c..51d3857e 100644 --- a/src/nxemu-os/core/hle/kernel/svc/svc_thread.cpp +++ b/src/nxemu-os/core/hle/kernel/svc/svc_thread.cpp @@ -160,7 +160,9 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha R_TRY(thread->GetThreadContext3(std::addressof(context))); // Copy the thread context to user space. - R_UNLESS(GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)), ResultInvalidPointer); + R_UNLESS(GetCurrentMemory(kernel).WriteBlock(Common::ProcessAddress{out_context}, + std::addressof(context), sizeof(context)), + ResultInvalidPointer); R_SUCCEED(); } diff --git a/src/nxemu-os/core/hle/service/hle_ipc.cpp b/src/nxemu-os/core/hle/service/hle_ipc.cpp index fd6f257c..e5b191fb 100644 --- a/src/nxemu-os/core/hle/service/hle_ipc.cpp +++ b/src/nxemu-os/core/hle/service/hle_ipc.cpp @@ -429,7 +429,7 @@ std::size_t HLERequestContext::WriteBufferB(const void* buffer, std::size_t size size = buffer_size; // TODO(bunnei): This needs to be HW tested } - memory.WriteBlock(BufferDescriptorB()[buffer_index].Address(), buffer, size); + memory.WriteBlock(Common::ProcessAddress{BufferDescriptorB()[buffer_index].Address()}, buffer, size); return size; } @@ -446,7 +446,7 @@ std::size_t HLERequestContext::WriteBufferC(const void* buffer, std::size_t size size = buffer_size; // TODO(bunnei): This needs to be HW tested } - memory.WriteBlock(BufferDescriptorC()[buffer_index].Address(), buffer, size); + memory.WriteBlock(Common::ProcessAddress{BufferDescriptorC()[buffer_index].Address()}, buffer, size); return size; } diff --git a/src/yuzu_audio_core/CMakeLists.txt b/src/yuzu_audio_core/CMakeLists.txt index fff900b2..44166a04 100644 --- a/src/yuzu_audio_core/CMakeLists.txt +++ b/src/yuzu_audio_core/CMakeLists.txt @@ -3,6 +3,9 @@ cmake_minimum_required(VERSION 3.18) if(NOT TARGET cubeb) set(USE_SANITIZERS OFF CACHE BOOL "cubeb: skip sanitizers-cmake" FORCE) + if(APPLE) + set(BUNDLE_SPEEX ON CACHE BOOL "cubeb: use bundled Speex resampler" FORCE) + endif() set(BUILD_TESTS OFF CACHE BOOL "cubeb: skip gtest" FORCE) set(BUILD_TOOLS OFF CACHE BOOL "cubeb: skip tools" FORCE) add_subdirectory("${CMAKE_SOURCE_DIR}/external/cubeb" "${CMAKE_BINARY_DIR}/external/cubeb") diff --git a/src/yuzu_common/CMakeLists.txt b/src/yuzu_common/CMakeLists.txt index 3bb912a6..84556701 100644 --- a/src/yuzu_common/CMakeLists.txt +++ b/src/yuzu_common/CMakeLists.txt @@ -189,4 +189,9 @@ target_include_directories(yuzu_common PUBLIC target_link_libraries(yuzu_common PUBLIC Boost::context Boost::headers fmt::fmt stb::headers Threads::Threads) target_link_libraries(yuzu_common PRIVATE lz4::lz4 zstd::zstd) +if(APPLE) + find_library(YUZU_COMMON_COREFOUNDATION_FRAMEWORK CoreFoundation REQUIRED) + target_link_libraries(yuzu_common PRIVATE ${YUZU_COMMON_COREFOUNDATION_FRAMEWORK}) +endif() + create_target_directory_groups(yuzu_common) \ No newline at end of file diff --git a/src/yuzu_video_core/CMakeLists.txt b/src/yuzu_video_core/CMakeLists.txt index 3b72ac78..5567661c 100644 --- a/src/yuzu_video_core/CMakeLists.txt +++ b/src/yuzu_video_core/CMakeLists.txt @@ -329,10 +329,29 @@ target_include_directories(video_core PRIVATE ${CMAKE_SOURCE_DIR}/src/nxemu-vide target_link_libraries(video_core PUBLIC common nxemu_core yuzu_common) target_link_libraries(video_core PUBLIC glad shader_recompiler stb::headers bc_decoder stb_dxt) -if (YUZU_USE_BUNDLED_FFMPEG AND NOT (WIN32 OR ANDROID)) +if (YUZU_USE_BUNDLED_FFMPEG AND NOT (WIN32 OR ANDROID OR APPLE)) add_dependencies(video_core ffmpeg-build) endif() +if(APPLE AND NOT FFmpeg_LIBRARIES) + set(_ffmpeg_macos_root "${CMAKE_SOURCE_DIR}/external/ffmpeg/lib/macos-arm64") + set(_ffmpeg_macos_libs + "${_ffmpeg_macos_root}/libavfilter.a" + "${_ffmpeg_macos_root}/libavcodec.a" + "${_ffmpeg_macos_root}/libswscale.a" + "${_ffmpeg_macos_root}/libavutil.a" + ) + + foreach(_ffmpeg_lib IN LISTS _ffmpeg_macos_libs) + if(NOT EXISTS "${_ffmpeg_lib}") + message(FATAL_ERROR "Missing FFmpeg macOS arm64 library: ${_ffmpeg_lib}") + endif() + endforeach() + + set(FFmpeg_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/external/ffmpeg/include") + set(FFmpeg_LIBRARIES ${_ffmpeg_macos_libs}) +endif() + if(NOT FFmpeg_INCLUDE_DIR) set(FFmpeg_INCLUDE_DIR "${CMAKE_SOURCE_DIR}/external/ffmpeg/include") endif()