diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index c1afde6c..966e4911 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,16 @@ jobs: path: artifacts build-windows: - runs-on: windows-2022 + strategy: + fail-fast: false + matrix: + include: + - os: windows-2022 + arch: x64 + - os: windows-11-arm + arch: arm64 + name: build-windows-${{ matrix.arch }} + runs-on: ${{ matrix.os }} steps: - name: "Checkout repo" uses: actions/checkout@v6 @@ -190,19 +199,19 @@ jobs: shell: cmd run: | cd src\resource - makensis /DPRODUCT_VERSION=${{ inputs.next_version_major }}.${{ inputs.next_version_minor }} installer.nsi + makensis /DPRODUCT_VERSION=${{ inputs.next_version_major }}.${{ inputs.next_version_minor }} /DARCH=${{ matrix.arch }} installer.nsi - name: Upload artifact uses: actions/upload-artifact@v6 with: - name: cemu-bin-windows-x64 + name: cemu-bin-windows-${{ matrix.arch }} path: ./bin/Cemu.exe - name: Upload NSIS Installer uses: actions/upload-artifact@v6 with: - name: cemu-installer-windows-x64 - path: ./src/resource/cemu-${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}-windows-x64-installer.exe + name: cemu-installer-windows-${{ matrix.arch }} + path: ./src/resource/cemu-${{ inputs.next_version_major }}.${{ inputs.next_version_minor }}-windows-${{ matrix.arch }}-installer.exe build-macos: runs-on: macos-14 diff --git a/CMakeLists.txt b/CMakeLists.txt index 69a5b0b0..f2dbfa7f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,8 +51,16 @@ if (ENABLE_VCPKG) # CONFIG option set(CMAKE_FIND_PACKAGE_PREFER_CONFIG TRUE) if (WIN32) - set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "") - endif() + message(STATUS "CPU Arch is: $ENV{PROCESSOR_ARCHITECTURE}") + if($ENV{PROCESSOR_ARCHITECTURE} MATCHES "x86_64|amd64|AMD64") + set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "" FORCE) + set(VCPKG_HOST_TRIPLET "x64-windows-static" CACHE STRING "" FORCE) + else() + set(VCPKG_TARGET_TRIPLET "arm64-windows-static" CACHE STRING "" FORCE) + set(VCPKG_HOST_TRIPLET "arm64-windows-static" CACHE STRING "" FORCE) + endif() + message(STATUS "Using VCPKG triplet: ${VCPKG_TARGET_TRIPLET}") + endif() endif() project(Cemu VERSION 2.0.0) @@ -79,6 +87,7 @@ set(CMAKE_INTERPROCEDURAL_OPTIMIZATION_RELWITHDEBINFO ON) if (MSVC) set_property(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT CemuBin) # floating point model: precise, fiber safe optimizations + add_compile_definitions(NOMINMAX) add_compile_options(/EHsc /fp:precise) if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang") # Speeds up static linking (especially helpful in incremental compilation) @@ -173,6 +182,19 @@ if (NOT TARGET glslang::SPIRV AND TARGET SPIRV) add_library(glslang::SPIRV ALIAS SPIRV) endif() +if (UNIX AND NOT APPLE) + if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") + set(ARCH_TRIPLET "aarch64-linux-gnu") + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + set(ARCH_TRIPLET "x86_64-linux-gnu") + else() + message(WARNING "Unknown architecture: ${CMAKE_SYSTEM_PROCESSOR}") + endif() + if(ARCH_TRIPLET) + set(ENV{PKG_CONFIG_PATH} "$ENV{PKG_CONFIG_PATH}:/usr/share/pkgconfig:/usr/lib/${ARCH_TRIPLET}/pkgconfig:/usr/local/share/pkgconfig") + endif() +endif() + if (UNIX AND NOT APPLE) find_package(X11 REQUIRED) if (ENABLE_WAYLAND) @@ -253,6 +275,9 @@ if (ENABLE_CUBEB) endif() add_subdirectory("dependencies/ih264d" EXCLUDE_FROM_ALL) +if(MSVC) + target_compile_options(ih264d PRIVATE /wd4005) +endif() if (CMAKE_OSX_ARCHITECTURES) set(CEMU_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES}) @@ -261,6 +286,9 @@ else() endif() if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)") add_subdirectory("dependencies/xbyak_aarch64" EXCLUDE_FROM_ALL) + if(MSVC) + set_target_properties(xbyak_aarch64 PROPERTIES COMPILE_FLAGS "/wd4245 /wd4458") + endif() endif() find_package(ZArchive QUIET) diff --git a/CMakeSettings.json b/CMakeSettings.json index 0927e98b..8095dc54 100644 --- a/CMakeSettings.json +++ b/CMakeSettings.json @@ -1,4 +1,4 @@ -{ +{ "configurations": [ { "name": "RelWithDebInfo", @@ -16,6 +16,14 @@ "buildRoot": "${projectDir}\\out\\build\\${name}", "installRoot": "${projectDir}\\out\\install\\${name}" }, + { + "name": "ARM64-Release", + "configurationType": "Release", + "generator": "Ninja", + "inheritEnvironments": [ "msvc_arm64_x64" ], + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}" + }, { "name": "Debug", "configurationType": "Debug", @@ -25,4 +33,4 @@ "installRoot": "${projectDir}\\out\\install\\${name}" } ] -} \ No newline at end of file +} diff --git a/dependencies/ih264d/CMakeLists.txt b/dependencies/ih264d/CMakeLists.txt index a8ef3776..3f26cc49 100644 --- a/dependencies/ih264d/CMakeLists.txt +++ b/dependencies/ih264d/CMakeLists.txt @@ -1,204 +1,148 @@ -cmake_minimum_required (VERSION 3.8) +cmake_minimum_required(VERSION 3.10) -project ("ih264d") +project(ih264d LANGUAGES C) -add_library (ih264d -"common/ih264_buf_mgr.c" -"common/ih264_buf_mgr.h" -"common/ih264_cabac_tables.c" -"common/ih264_cabac_tables.h" -"common/ih264_cavlc_tables.c" -"common/ih264_cavlc_tables.h" -"common/ih264_chroma_intra_pred_filters.c" -"common/ih264_common_tables.c" -"common/ih264_common_tables.h" -"common/ih264_deblk_edge_filters.c" -"common/ih264_deblk_edge_filters.h" -"common/ih264_deblk_tables.c" -"common/ih264_deblk_tables.h" -"common/ih264_debug.h" -"common/ih264_defs.h" -"common/ih264_disp_mgr.c" -"common/ih264_disp_mgr.h" -"common/ih264_dpb_mgr.c" -"common/ih264_dpb_mgr.h" -"common/ih264_error.h" -"common/ih264_ihadamard_scaling.c" -"common/ih264_inter_pred_filters.c" -"common/ih264_inter_pred_filters.h" -"common/ih264_intra_pred_filters.h" -"common/ih264_iquant_itrans_recon.c" -"common/ih264_list.c" -"common/ih264_list.h" -"common/ih264_luma_intra_pred_filters.c" -"common/ih264_macros.h" -"common/ih264_mem_fns.c" -"common/ih264_mem_fns.h" -"common/ih264_padding.c" -"common/ih264_padding.h" -"common/ih264_resi_trans.h" -"common/ih264_resi_trans_quant.c" -"common/ih264_size_defs.h" -"common/ih264_structs.h" -"common/ih264_trans_data.c" -"common/ih264_trans_data.h" -"common/ih264_trans_macros.h" -"common/ih264_trans_quant_itrans_iquant.h" -"common/ih264_typedefs.h" -"common/ih264_weighted_pred.c" -"common/ih264_weighted_pred.h" -"common/ithread.c" -"common/ithread.h" -"decoder/ih264d.h" -"decoder/ih264d_api.c" -"decoder/ih264d_bitstrm.c" -"decoder/ih264d_bitstrm.h" -"decoder/ih264d_cabac.c" -"decoder/ih264d_cabac.h" -"decoder/ih264d_cabac_init_tables.c" -"decoder/ih264d_compute_bs.c" -"decoder/ih264d_deblocking.c" -"decoder/ih264d_deblocking.h" -"decoder/ih264d_debug.h" -"decoder/ih264d_defs.h" -"decoder/ih264d_dpb_manager.h" -"decoder/ih264d_dpb_mgr.c" -"decoder/ih264d_error_handler.h" -"decoder/ih264d_format_conv.c" -"decoder/ih264d_format_conv.h" -"decoder/ih264d_function_selector.h" -"decoder/ih264d_function_selector_generic.c" -"decoder/ih264d_inter_pred.c" -"decoder/ih264d_inter_pred.h" -"decoder/ih264d_mb_utils.c" -"decoder/ih264d_mb_utils.h" -"decoder/ih264d_mem_request.h" -"decoder/ih264d_mvpred.c" -"decoder/ih264d_mvpred.h" -"decoder/ih264d_nal.c" -"decoder/ih264d_nal.h" -"decoder/ih264d_parse_bslice.c" -"decoder/ih264d_parse_cabac.c" -"decoder/ih264d_parse_cabac.h" -"decoder/ih264d_parse_cavlc.c" -"decoder/ih264d_parse_cavlc.h" -"decoder/ih264d_parse_headers.c" -"decoder/ih264d_parse_headers.h" -"decoder/ih264d_parse_islice.c" -"decoder/ih264d_parse_islice.h" -"decoder/ih264d_parse_mb_header.c" -"decoder/ih264d_parse_mb_header.h" -"decoder/ih264d_parse_pslice.c" -"decoder/ih264d_parse_slice.c" -"decoder/ih264d_parse_slice.h" -"decoder/ih264d_process_bslice.c" -"decoder/ih264d_process_bslice.h" -"decoder/ih264d_process_intra_mb.c" -"decoder/ih264d_process_intra_mb.h" -"decoder/ih264d_process_pslice.c" -"decoder/ih264d_process_pslice.h" -"decoder/ih264d_quant_scaling.c" -"decoder/ih264d_quant_scaling.h" -"decoder/ih264d_sei.c" -"decoder/ih264d_sei.h" -"decoder/ih264d_structs.h" -"decoder/ih264d_tables.c" -"decoder/ih264d_tables.h" -"decoder/ih264d_thread_compute_bs.c" -"decoder/ih264d_thread_compute_bs.h" -"decoder/ih264d_thread_parse_decode.c" -"decoder/ih264d_thread_parse_decode.h" -"decoder/ih264d_transfer_address.h" -"decoder/ih264d_utils.c" -"decoder/ih264d_utils.h" -"decoder/ih264d_vui.c" -"decoder/ih264d_vui.h" -"decoder/iv.h" -"decoder/ivd.h" +add_library(ih264d STATIC + "common/ih264_buf_mgr.c" + "common/ih264_cabac_tables.c" + "common/ih264_cavlc_tables.c" + "common/ih264_chroma_intra_pred_filters.c" + "common/ih264_common_tables.c" + "common/ih264_deblk_edge_filters.c" + "common/ih264_deblk_tables.c" + "common/ih264_disp_mgr.c" + "common/ih264_dpb_mgr.c" + "common/ih264_ihadamard_scaling.c" + "common/ih264_inter_pred_filters.c" + "common/ih264_iquant_itrans_recon.c" + "common/ih264_list.c" + "common/ih264_luma_intra_pred_filters.c" + "common/ih264_mem_fns.c" + "common/ih264_padding.c" + "common/ih264_resi_trans_quant.c" + "common/ih264_trans_data.c" + "common/ih264_weighted_pred.c" + "common/ithread.c" + "decoder/ih264d_api.c" + "decoder/ih264d_bitstrm.c" + "decoder/ih264d_cabac.c" + "decoder/ih264d_cabac_init_tables.c" + "decoder/ih264d_compute_bs.c" + "decoder/ih264d_deblocking.c" + "decoder/ih264d_dpb_mgr.c" + "decoder/ih264d_format_conv.c" + "decoder/ih264d_function_selector_generic.c" + "decoder/ih264d_inter_pred.c" + "decoder/ih264d_mb_utils.c" + "decoder/ih264d_mvpred.c" + "decoder/ih264d_nal.c" + "decoder/ih264d_parse_bslice.c" + "decoder/ih264d_parse_cabac.c" + "decoder/ih264d_parse_cavlc.c" + "decoder/ih264d_parse_headers.c" + "decoder/ih264d_parse_islice.c" + "decoder/ih264d_parse_mb_header.c" + "decoder/ih264d_parse_pslice.c" + "decoder/ih264d_parse_slice.c" + "decoder/ih264d_process_bslice.c" + "decoder/ih264d_process_intra_mb.c" + "decoder/ih264d_process_pslice.c" + "decoder/ih264d_quant_scaling.c" + "decoder/ih264d_sei.c" + "decoder/ih264d_tables.c" + "decoder/ih264d_thread_compute_bs.c" + "decoder/ih264d_thread_parse_decode.c" + "decoder/ih264d_utils.c" + "decoder/ih264d_vui.c" ) -if (CMAKE_OSX_ARCHITECTURES) -set(IH264D_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES}) +if(CMAKE_OSX_ARCHITECTURES) + set(IH264D_ARCHITECTURE ${CMAKE_OSX_ARCHITECTURES}) else() -set(IH264D_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) + set(IH264D_ARCHITECTURE ${CMAKE_SYSTEM_PROCESSOR}) endif() -if (IH264D_ARCHITECTURE STREQUAL "x86_64" OR IH264D_ARCHITECTURE STREQUAL "amd64" OR IH264D_ARCHITECTURE STREQUAL "AMD64") -set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86") -include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES}) -target_sources(ih264d PRIVATE -"common/x86/ih264_chroma_intra_pred_filters_ssse3.c" -"common/x86/ih264_deblk_chroma_ssse3.c" -"common/x86/ih264_deblk_luma_ssse3.c" -"common/x86/ih264_ihadamard_scaling_sse42.c" -"common/x86/ih264_ihadamard_scaling_ssse3.c" -"common/x86/ih264_inter_pred_filters_ssse3.c" -"common/x86/ih264_iquant_itrans_recon_dc_ssse3.c" -"common/x86/ih264_iquant_itrans_recon_sse42.c" -"common/x86/ih264_iquant_itrans_recon_ssse3.c" -"common/x86/ih264_luma_intra_pred_filters_ssse3.c" -"common/x86/ih264_mem_fns_ssse3.c" -"common/x86/ih264_padding_ssse3.c" -"common/x86/ih264_platform_macros.h" -"common/x86/ih264_resi_trans_quant_sse42.c" -"common/x86/ih264_weighted_pred_sse42.c" -"decoder/x86/ih264d_function_selector.c" -"decoder/x86/ih264d_function_selector_sse42.c" -"decoder/x86/ih264d_function_selector_ssse3.c" -) -elseif(IH264D_ARCHITECTURE STREQUAL "aarch64" OR IH264D_ARCHITECTURE STREQUAL "arm64") -enable_language( C CXX ASM ) -set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm") -include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES}) -target_sources(ih264d PRIVATE -"common/armv8/ih264_deblk_chroma_av8.s" -"common/armv8/ih264_deblk_luma_av8.s" -"common/armv8/ih264_default_weighted_pred_av8.s" -"common/armv8/ih264_ihadamard_scaling_av8.s" -"common/armv8/ih264_inter_pred_chroma_av8.s" -"common/armv8/ih264_inter_pred_filters_luma_horz_av8.s" -"common/armv8/ih264_inter_pred_filters_luma_vert_av8.s" -"common/armv8/ih264_inter_pred_luma_copy_av8.s" -"common/armv8/ih264_inter_pred_luma_horz_hpel_vert_hpel_av8.s" -"common/armv8/ih264_inter_pred_luma_horz_hpel_vert_qpel_av8.s" -"common/armv8/ih264_inter_pred_luma_horz_qpel_av8.s" -"common/armv8/ih264_inter_pred_luma_horz_qpel_vert_hpel_av8.s" -"common/armv8/ih264_inter_pred_luma_horz_qpel_vert_qpel_av8.s" -"common/armv8/ih264_inter_pred_luma_vert_qpel_av8.s" -"common/armv8/ih264_intra_pred_chroma_av8.s" -"common/armv8/ih264_intra_pred_luma_16x16_av8.s" -"common/armv8/ih264_intra_pred_luma_4x4_av8.s" -"common/armv8/ih264_intra_pred_luma_8x8_av8.s" -"common/armv8/ih264_iquant_itrans_recon_av8.s" -"common/armv8/ih264_iquant_itrans_recon_dc_av8.s" -"common/armv8/ih264_mem_fns_neon_av8.s" -"common/armv8/ih264_neon_macros.s" -"common/armv8/ih264_padding_neon_av8.s" -"common/armv8/ih264_platform_macros.h" -"common/armv8/ih264_resi_trans_quant_av8.s" -"common/armv8/ih264_weighted_bi_pred_av8.s" -"common/armv8/ih264_weighted_pred_av8.s" -"decoder/arm/ih264d_function_selector_a9q.c" -"decoder/arm/ih264d_function_selector_av8.c" -"decoder/arm/ih264d_function_selector.c" -) -target_compile_options(ih264d PRIVATE -DARMV8 $<$:-Wno-unused-command-line-argument>) -if(NOT MSVC) - set(CMAKE_ASM_FLAGS "${CFLAGS} -x assembler-with-cpp") -endif() -if(APPLE) - target_sources(ih264d PRIVATE "common/armv8/macos_arm_symbol_aliases.s") -endif() +message(STATUS "DEBUG: ih264d detected architecture is: ${IH264D_ARCHITECTURE}") + +if(IH264D_ARCHITECTURE MATCHES "x86_64|amd64|AMD64|i386|i686") + set(LIBAVCDEC_X86_INCLUDES "common/x86" "decoder/x86") + include_directories("common/" "decoder/" ${LIBAVCDEC_X86_INCLUDES}) + target_sources(ih264d PRIVATE + "common/x86/ih264_chroma_intra_pred_filters_ssse3.c" + "common/x86/ih264_deblk_chroma_ssse3.c" + "common/x86/ih264_deblk_luma_ssse3.c" + "common/x86/ih264_ihadamard_scaling_sse42.c" + "common/x86/ih264_ihadamard_scaling_ssse3.c" + "common/x86/ih264_inter_pred_filters_ssse3.c" + "common/x86/ih264_iquant_itrans_recon_dc_ssse3.c" + "common/x86/ih264_iquant_itrans_recon_sse42.c" + "common/x86/ih264_iquant_itrans_recon_ssse3.c" + "common/x86/ih264_luma_intra_pred_filters_ssse3.c" + "common/x86/ih264_mem_fns_ssse3.c" + "common/x86/ih264_padding_ssse3.c" + "common/x86/ih264_resi_trans_quant_sse42.c" + "common/x86/ih264_weighted_pred_sse42.c" + "decoder/x86/ih264d_function_selector.c" + "decoder/x86/ih264d_function_selector_sse42.c" + "decoder/x86/ih264d_function_selector_ssse3.c" + ) + +elseif(IH264D_ARCHITECTURE MATCHES "aarch64|arm64|ARM64") + set(LIBAVCDEC_ARM_INCLUDES "common/armv8" "decoder/arm") + include_directories("common/" "decoder/" ${LIBAVCDEC_ARM_INCLUDES}) + + if(MSVC) + message(STATUS "MSVC ARM64 detected: Forcing portable C implementation.") + target_sources(ih264d PRIVATE + "decoder/arm/ih264d_function_selector.c" + "decoder/arm/ih264d_function_selector_av8.c" + ) + target_compile_definitions(ih264d PRIVATE PORTABLE_C ARCH_GENERIC DISABLE_NEON) + else() + enable_language(ASM) + message(STATUS "ARM64 Clang/GCC detected: Enabling assembly optimization.") + target_sources(ih264d PRIVATE + "common/armv8/ih264_deblk_chroma_av8.s" + "common/armv8/ih264_deblk_luma_av8.s" + "common/armv8/ih264_default_weighted_pred_av8.s" + "common/armv8/ih264_ihadamard_scaling_av8.s" + "common/armv8/ih264_inter_pred_chroma_av8.s" + "common/armv8/ih264_inter_pred_filters_luma_horz_av8.s" + "common/armv8/ih264_inter_pred_filters_luma_vert_av8.s" + "common/armv8/ih264_inter_pred_luma_copy_av8.s" + "common/armv8/ih264_inter_pred_luma_horz_hpel_vert_hpel_av8.s" + "common/armv8/ih264_inter_pred_luma_horz_hpel_vert_qpel_av8.s" + "common/armv8/ih264_inter_pred_luma_horz_qpel_av8.s" + "common/armv8/ih264_inter_pred_luma_horz_qpel_vert_hpel_av8.s" + "common/armv8/ih264_inter_pred_luma_horz_qpel_vert_qpel_av8.s" + "common/armv8/ih264_inter_pred_luma_vert_qpel_av8.s" + "common/armv8/ih264_intra_pred_chroma_av8.s" + "common/armv8/ih264_intra_pred_luma_16x16_av8.s" + "common/armv8/ih264_intra_pred_luma_4x4_av8.s" + "common/armv8/ih264_intra_pred_luma_8x8_av8.s" + "common/armv8/ih264_iquant_itrans_recon_av8.s" + "common/armv8/ih264_iquant_itrans_recon_dc_av8.s" + "common/armv8/ih264_mem_fns_neon_av8.s" + "common/armv8/ih264_padding_neon_av8.s" + "common/armv8/ih264_resi_trans_quant_av8.s" + "common/armv8/ih264_weighted_bi_pred_av8.s" + "common/armv8/ih264_weighted_pred_av8.s" + "decoder/arm/ih264d_function_selector_av8.c" + "decoder/arm/ih264d_function_selector.c" + ) + target_compile_definitions(ih264d PRIVATE ARMV8) + set(CMAKE_ASM_FLAGS "${CMAKE_ASM_FLAGS} -x assembler-with-cpp") + endif() + + if(APPLE) + target_sources(ih264d PRIVATE "common/armv8/macos_arm_symbol_aliases.s") + endif() + else() -message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}") + message(FATAL_ERROR "ih264d unknown architecture: ${IH264D_ARCHITECTURE}") endif() if(MSVC) -set_property(TARGET ih264d PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") - -# tune settings for slightly better performance -target_compile_options(ih264d PRIVATE $<$:/Oi>) # enable intrinsic functions -target_compile_options(ih264d PRIVATE $<$:/Ot>) # favor speed -target_compile_options(ih264d PRIVATE "/GS-") # disable runtime checks - + set_property(TARGET ih264d PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") + target_compile_options(ih264d PRIVATE $<$:/Oi> $<$:/Ot> "/GS-") endif() diff --git a/dependencies/ih264d/CMakeSettings.json b/dependencies/ih264d/CMakeSettings.json index d2bcfced..709110af 100644 --- a/dependencies/ih264d/CMakeSettings.json +++ b/dependencies/ih264d/CMakeSettings.json @@ -21,6 +21,17 @@ "buildCommandArgs": "", "ctestCommandArgs": "", "inheritEnvironments": [ "msvc_x64_x64" ] + }, + { + "name": "arm64-Release", + "generator": "Ninja", + "configurationType": "Release", + "buildRoot": "${projectDir}\\out\\build\\${name}", + "installRoot": "${projectDir}\\out\\install\\${name}", + "cmakeCommandArgs": "", + "buildCommandArgs": "", + "ctestCommandArgs": "", + "inheritEnvironments": [ "msvc_arm64_x64" ] } ] -} \ No newline at end of file +} diff --git a/dependencies/ih264d/common/armv8/ih264_platform_macros.h b/dependencies/ih264d/common/armv8/ih264_platform_macros.h index a4d7f3a7..162ff97e 100644 --- a/dependencies/ih264d/common/armv8/ih264_platform_macros.h +++ b/dependencies/ih264d/common/armv8/ih264_platform_macros.h @@ -38,144 +38,95 @@ #include -#ifndef ARMV8 - -static __inline WORD32 CLIP_U8(WORD32 x) -{ - asm("usat %0, #8, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_S8(WORD32 x) -{ - asm("ssat %0, #8, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_U10(WORD32 x) -{ - asm("usat %0, #10, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_S10(WORD32 x) -{ - asm("ssat %0, #10, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_U11(WORD32 x) -{ - asm("usat %0, #11, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_S11(WORD32 x) -{ - asm("ssat %0, #11, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_U12(WORD32 x) -{ - asm("usat %0, #12, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_S12(WORD32 x) -{ - asm("ssat %0, #12, %1" : "=r"(x) : "r"(x)); - return x; -} - -static __inline WORD32 CLIP_U16(WORD32 x) -{ - asm("usat %0, #16, %1" : "=r"(x) : "r"(x)); - return x; -} -static __inline WORD32 CLIP_S16(WORD32 x) -{ - asm("ssat %0, #16, %1" : "=r"(x) : "r"(x)); - return x; -} - - -static __inline UWORD32 ITT_BIG_ENDIAN(UWORD32 x) -{ - asm("rev %0, %1" : "=r"(x) : "r"(x)); - return x; -} -#define NOP(nop_cnt) {UWORD32 nop_i; for (nop_i = 0; nop_i < nop_cnt; nop_i++) asm("nop");} - -#else - -#define CLIP_U8(x) CLIP3(0, UINT8_MAX, (x)) -#define CLIP_S8(x) CLIP3(INT8_MIN, INT8_MAX, (x)) - -#define CLIP_U10(x) CLIP3(0, 1023, (x)) -#define CLIP_S10(x) CLIP3(-512, 511, (x)) - -#define CLIP_U11(x) CLIP3(0, 2047, (x)) -#define CLIP_S11(x) CLIP3(-1024, 1023, (x)) - -#define CLIP_U12(x) CLIP3(0, 4095, (x)) -#define CLIP_S12(x) CLIP3(-2048, 2047, (x)) - -#define CLIP_U16(x) CLIP3(0, UINT16_MAX, (x)) -#define CLIP_S16(x) CLIP3(INT16_MIN, INT16_MAX, (x)) - -#define ITT_BIG_ENDIAN(x) __asm__("rev %0, %1" : "=r"(x) : "r"(x)); - -#define NOP(nop_cnt) \ -{ \ - UWORD32 nop_i; \ - for (nop_i = 0; nop_i < nop_cnt; nop_i++) \ - __asm__ __volatile__("mov x0, x0"); \ -} - +#ifndef WORD32 +typedef int32_t WORD32; +#endif +#ifndef UWORD32 +typedef uint32_t UWORD32; #endif -/*saturating instructions are not available for WORD64 in ARMv7, hence we cannot - * use inline assembly like other clips*/ -#define CLIP_U32(x) CLIP3(0, UINT32_MAX, (x)) -#define CLIP_S32(x) CLIP3(INT32_MIN, INT32_MAX, (x)) +#include -#define DATA_SYNC() __sync_synchronize() +#ifdef _MSC_VER + #include + + #if defined(_M_ARM64) && !defined(__arm64_intrinsics_h__) + #ifndef _ARM64_BARRIER_ISH + #define _ARM64_BARRIER_ISH 0xB + #endif + #endif -#define SHL(x,y) (((y) < 32) ? ((x) << (y)) : 0) -#define SHR(x,y) (((y) < 32) ? ((x) >> (y)) : 0) + #define INLINE __inline + #define MEM_ALIGN8 __declspec(align(8)) + #define MEM_ALIGN16 __declspec(align(16)) + #define MEM_ALIGN32 __declspec(align(32)) + + #define DATA_SYNC() __dmb(_ARM64_BARRIER_ISH) + + #define NOP(nop_cnt) { for (int i = 0; i < (int)nop_cnt; i++) __nop(); } + + #define ITT_BIG_ENDIAN(x) _byteswap_ulong(x) +#else + #define INLINE inline + #define MEM_ALIGN8 __attribute__ ((aligned (8))) + #define MEM_ALIGN16 __attribute__ ((aligned (16))) + #define MEM_ALIGN32 __attribute__ ((aligned (32))) + + #define DATA_SYNC() __sync_synchronize() + + #define NOP(nop_cnt) \ + { \ + uint32_t nop_i; \ + for (nop_i = 0; nop_i < nop_cnt; nop_i++) \ + __asm__ __volatile__("mov x0, x0"); \ + } + + static INLINE uint32_t ITT_BIG_ENDIAN(uint32_t x) { + return __builtin_bswap32(x); + } +#endif + +#ifndef CLIP3 +#define CLIP3(min_val, max_val, x) (((x) < (min_val)) ? (min_val) : (((x) > (max_val)) ? (max_val) : (x))) +#endif + +#define CLIP_U8(x) CLIP3(0, 255, (x)) +#define CLIP_S8(x) CLIP3(-128, 127, (x)) +#define CLIP_U10(x) CLIP3(0, 1023, (x)) +#define CLIP_S10(x) CLIP3(-512, 511, (x)) +#define CLIP_U11(x) CLIP3(0, 2047, (x)) +#define CLIP_S11(x) CLIP3(-1024, 1023, (x)) +#define CLIP_U12(x) CLIP3(0, 4095, (x)) +#define CLIP_S12(x) CLIP3(-2048, 2047, (x)) +#define CLIP_U16(x) CLIP3(0, 65535, (x)) +#define CLIP_S16(x) CLIP3(-32768, 32767, (x)) +#define CLIP_U32(x) CLIP3(0, 0xFFFFFFFF, (x)) +#define CLIP_S32(x) CLIP3(-2147483647-1, 2147483647, (x)) + +static INLINE uint32_t CLZ(uint32_t u4_word) { + if (u4_word == 0) return 31; +#ifdef _MSC_VER + return (uint32_t)_CountLeadingZeros(u4_word); +#else + return (uint32_t)__builtin_clz(u4_word); +#endif +} + +static INLINE uint32_t CTZ(uint32_t u4_word) { + if (u4_word == 0) return 31; +#ifdef _MSC_VER + unsigned long index; + _BitScanForward(&index, u4_word); + return (uint32_t)index; +#else + return (uint32_t)__builtin_ctz(u4_word); +#endif +} + +#define SHL(x,y) (((y) < 32) ? ((uint32_t)(x) << (y)) : 0) +#define SHR(x,y) (((y) < 32) ? ((uint32_t)(x) >> (y)) : 0) #define SHR_NEG(val,shift) ((shift>0)?(val>>shift):(val<<(-shift))) #define SHL_NEG(val,shift) ((shift<0)?(val>>(-shift)):(val< + - + + - - + + + + + + + True/PM + PerMonitorV2 - \ No newline at end of file + diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 977f48b7..c63f8dd3 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -70,10 +70,15 @@ add_executable(CemuBin cemu_use_precompiled_header(CemuBin) -if(MSVC AND MSVC_VERSION EQUAL 1940) - # workaround for an msvc issue on VS 17.10 where generated ILK files are too large - # see https://developercommunity.visualstudio.com/t/After-updating-to-VS-1710-the-size-of-/10665511 - set_target_properties(CemuBin PROPERTIES LINK_FLAGS "/INCREMENTAL:NO") +if(MSVC) + set(CEMU_LINKER_FLAGS "/NODEFAULTLIB:MSVCRT") + + # Check for the specific VS 17.10 version + if(MSVC_VERSION EQUAL 1940) + string(APPEND CEMU_LINKER_FLAGS " /INCREMENTAL:NO") + endif() + + set_target_properties(CemuBin PROPERTIES LINK_FLAGS "${CEMU_LINKER_FLAGS}") endif() if(WIN32) diff --git a/src/Cafe/CMakeLists.txt b/src/Cafe/CMakeLists.txt index b509e722..f750a747 100644 --- a/src/Cafe/CMakeLists.txt +++ b/src/Cafe/CMakeLists.txt @@ -83,13 +83,6 @@ add_library(CemuCafe HW/Espresso/Recompiler/PPCRecompilerImlGenFPU.cpp HW/Espresso/Recompiler/PPCRecompilerIml.h HW/Espresso/Recompiler/PPCRecompilerIntermediate.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64AVX.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64BMI.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64FPU.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64Gen.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64GenFPU.cpp - HW/Espresso/Recompiler/BackendX64/BackendX64.h HW/Espresso/Recompiler/BackendX64/X64Emit.hpp HW/Espresso/Recompiler/BackendX64/x86Emitter.h HW/Latte/Common/RegisterSerializer.cpp @@ -618,12 +611,23 @@ if(ENABLE_METAL) ) endif() -if(CEMU_ARCHITECTURE MATCHES "(aarch64)|(AARCH64)|(arm64)|(ARM64)") - target_sources(CemuCafe PRIVATE - HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp - HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.h - ) - target_link_libraries(CemuCafe PRIVATE xbyak_aarch64) +if(CEMU_ARCHITECTURE MATCHES "(x86_64|amd64|AMD64)") + target_sources(CemuCafe PRIVATE + HW/Espresso/Recompiler/BackendX64/BackendX64.cpp + HW/Espresso/Recompiler/BackendX64/BackendX64.h + HW/Espresso/Recompiler/BackendX64/BackendX64AVX.cpp + HW/Espresso/Recompiler/BackendX64/BackendX64BMI.cpp + HW/Espresso/Recompiler/BackendX64/BackendX64FPU.cpp + HW/Espresso/Recompiler/BackendX64/BackendX64Gen.cpp + HW/Espresso/Recompiler/BackendX64/BackendX64GenFPU.cpp + ) +else() + target_sources(CemuCafe PRIVATE + HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp + HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.h + ) + target_link_libraries(CemuCafe PRIVATE xbyak_aarch64) + target_compile_definitions(ih264d PRIVATE ARCH_GENERIC DISABLE_NEON) endif() set_property(TARGET CemuCafe PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") @@ -646,7 +650,7 @@ else() endif() target_link_libraries(CemuCafe PRIVATE - CemuCommon + CemuCommon CemuGui ZArchive::zarchive imguiImpl @@ -660,6 +664,10 @@ target_link_libraries(CemuCafe PRIVATE OpenSSL::SSL ) +if(MSVC AND CMAKE_SYSTEM_PROCESSOR STREQUAL "ARM64") + target_link_libraries(CemuCafe PRIVATE ntdll.lib) +endif() + if (ENABLE_WAYLAND) # PUBLIC because wayland-client.h is included in VulkanAPI.h target_link_libraries(CemuCafe PUBLIC Wayland::Client) @@ -668,7 +676,9 @@ endif() if (ENABLE_LIBUSB) if (ENABLE_VCPKG) if(WIN32) - set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/x64-windows/tools/pkgconf/pkgconf.exe") + if(DEFINED VCPKG_TARGET_TRIPLET) + set(PKG_CONFIG_EXECUTABLE "${VCPKG_INSTALLED_DIR}/${VCPKG_TARGET_TRIPLET}/tools/pkgconf/pkgconf.exe") + endif() endif() find_package(PkgConfig REQUIRED) pkg_check_modules(libusb REQUIRED IMPORTED_TARGET libusb-1.0) diff --git a/src/Cafe/HW/Espresso/Debugger/Debugger.cpp b/src/Cafe/HW/Espresso/Debugger/Debugger.cpp index e4a22387..8f68da9f 100644 --- a/src/Cafe/HW/Espresso/Debugger/Debugger.cpp +++ b/src/Cafe/HW/Espresso/Debugger/Debugger.cpp @@ -199,7 +199,7 @@ void debugger_updateMemoryBreakpoint(DebuggerBreakpoint* bp) { std::vector schedulerThreadHandles = coreinit::OSGetSchedulerThreads(); -#if BOOST_OS_WINDOWS +#if BOOST_OS_WINDOWS && defined(_M_X64) s_debuggerState.activeMemoryBreakpoint = bp; for (auto& hThreadNH : schedulerThreadHandles) { @@ -235,9 +235,51 @@ void debugger_updateMemoryBreakpoint(DebuggerBreakpoint* bp) SetThreadContext(hThread, &ctx); ResumeThread(hThread); } - #else +#elif defined(_M_X64) + s_debuggerState.activeMemoryBreakpoint = bp; + for (auto& hThreadNH : schedulerThreadHandles) + { + HANDLE hThread = (HANDLE)hThreadNH; + CONTEXT ctx{}; + ctx.ContextFlags = CONTEXT_DEBUG_REGISTERS; + + SuspendThread(hThread); + if (GetThreadContext(hThread, &ctx)) + { + if (s_debuggerState.activeMemoryBreakpoint) + { + // ARM64 uses Bvr/Bcr pairs. We'll use slot 0. + ctx.Bvr[0] = (DWORD64)memory_getPointerFromVirtualOffset(bp->address); + + // Construct the Control Register (BCR) + DWORD64 bcr = 0; + bcr |= 0x1; // Bit 0: Global Enable + bcr |= (0x3 << 1); // Bits 1-2: User and Privileged access + bcr |= (0xF << 5); // Bits 5-8: Byte address select (watch all 4 bytes) + + // Map Cemu BP types to ARM64 Watchpoint types + if (bp->bpType == DEBUGGER_BP_T_MEMORY_READ) + bcr |= (0x1 << 21); // Bit 21-22: 1 = Load + else if (bp->bpType == DEBUGGER_BP_T_MEMORY_WRITE) + bcr |= (0x2 << 21); // Bit 21-22: 2 = Store + else + bcr |= (0x3 << 21); // Bit 21-22: 3 = Either + + ctx.Bcr[0] = bcr; + } + else + { + // Disable breakpoint slot 0 + ctx.Bvr[0] = 0; + ctx.Bcr[0] = 0; + } + SetThreadContext(hThread, &ctx); + } + ResumeThread(hThread); + } +#else cemuLog_log(LogType::Force, "Debugger breakpoints are not supported"); - #endif +#endif } void debugger_handleSingleStepException(uint64 dr6) diff --git a/src/Cafe/HW/Espresso/PPCTimer.cpp b/src/Cafe/HW/Espresso/PPCTimer.cpp index 257973a6..88fdd683 100644 --- a/src/Cafe/HW/Espresso/PPCTimer.cpp +++ b/src/Cafe/HW/Espresso/PPCTimer.cpp @@ -3,14 +3,11 @@ #include "util/helpers/fspinlock.h" #include "util/highresolutiontimer/HighResolutionTimer.h" #include "Common/cpu_features.h" - -#if defined(ARCH_X86_64) -#include -#pragma intrinsic(__rdtsc) -#endif +#include "Common/Intrinsics.h" uint64 _rdtscLastMeasure = 0; uint64 _rdtscFrequency = 0; +uint64 _tickSummary = 0; struct uint128_t { @@ -33,39 +30,32 @@ uint64 muldiv64(uint64 a, uint64 b, uint64 d) uint64 PPCTimer_estimateRDTSCFrequency() { - #if defined(ARCH_X86_64) +#if defined(ARCH_X86_64) if (!g_CPUFeatures.x86.invariant_tsc) cemuLog_log(LogType::Force, "Invariant TSC not supported"); - #endif +#endif - _mm_mfence(); - uint64 tscStart = __rdtsc(); + BARRIER_FENCE(); + uint64 tscStart = READ_TSC(); unsigned int startTime = GetTickCount(); HRTick startTick = HighResolutionTimer::now().getTick(); - // wait roughly 3 seconds + while (true) { if ((GetTickCount() - startTime) >= 3000) break; std::this_thread::sleep_for(std::chrono::milliseconds(10)); } - _mm_mfence(); + + BARRIER_FENCE(); HRTick stopTick = HighResolutionTimer::now().getTick(); - uint64 tscEnd = __rdtsc(); - // derive frequency approximation from measured time difference + uint64 tscEnd = READ_TSC(); + uint64 tsc_diff = tscEnd - tscStart; uint64 hrtFreq = 0; uint64 hrtDiff = HighResolutionTimer::getTimeDiffEx(startTick, stopTick, hrtFreq); uint64 tsc_freq = muldiv64(tsc_diff, hrtFreq, hrtDiff); - // uint64 freqMultiplier = tsc_freq / hrtFreq; - //cemuLog_log(LogType::Force, "RDTSC measurement test:"); - //cemuLog_log(LogType::Force, "TSC-diff: 0x{:016x}", tsc_diff); - //cemuLog_log(LogType::Force, "TSC-freq: 0x{:016x}", tsc_freq); - //cemuLog_log(LogType::Force, "HPC-diff: 0x{:016x}", qpc_diff); - //cemuLog_log(LogType::Force, "HPC-freq: 0x{:016x}", (uint64)qpc_freq.QuadPart); - //cemuLog_log(LogType::Force, "Multiplier: 0x{:016x}", freqMultiplier); - return tsc_freq; } @@ -79,20 +69,18 @@ void PPCTimer_init() { std::thread t(PPCTimer_initThread); t.detach(); - _rdtscLastMeasure = __rdtsc(); + _rdtscLastMeasure = READ_TSC(); } -uint64 _tickSummary = 0; - void PPCTimer_start() { - _rdtscLastMeasure = __rdtsc(); + _rdtscLastMeasure = READ_TSC(); _tickSummary = 0; } uint64 PPCTimer_getRawTsc() { - return __rdtsc(); + return READ_TSC(); } uint64 PPCTimer_microsecondsToTsc(uint64 us) @@ -103,10 +91,12 @@ uint64 PPCTimer_microsecondsToTsc(uint64 us) uint64 PPCTimer_tscToMicroseconds(uint64 us) { uint128_t r{}; - r.low = _umul128(us, 1000000ULL, &r.high); + // Changed: Using Multiply64to128 wrapper + r.low = Multiply64to128(us, 1000000ULL, &r.high); uint64 remainder; - const uint64 microseconds = _udiv128(r.high, r.low, _rdtscFrequency, &remainder); + // Changed: Using Divide128by64 wrapper + const uint64 microseconds = Divide128by64(r.high, r.low, _rdtscFrequency, &remainder); return microseconds; } @@ -123,40 +113,37 @@ void PPCTimer_waitForInit() FSpinlock sTimerSpinlock; -// thread safe uint64 PPCTimer_getFromRDTSC() { sTimerSpinlock.lock(); - _mm_mfence(); - uint64 rdtscCurrentMeasure = __rdtsc(); + BARRIER_FENCE(); + uint64 rdtscCurrentMeasure = READ_TSC(); uint64 rdtscDif = rdtscCurrentMeasure - _rdtscLastMeasure; - // optimized max(rdtscDif, 0) without conditionals + rdtscDif = rdtscDif & ~(uint64)((sint64)rdtscDif >> 63); uint128_t diff{}; - diff.low = _umul128(rdtscDif, Espresso::CORE_CLOCK, &diff.high); + diff.low = Multiply64to128(rdtscDif, Espresso::CORE_CLOCK, &diff.high); if(rdtscCurrentMeasure > _rdtscLastMeasure) - _rdtscLastMeasure = rdtscCurrentMeasure; // only travel forward in time + _rdtscLastMeasure = rdtscCurrentMeasure; uint8 c = 0; - #if BOOST_OS_WINDOWS + #if defined(_MSC_VER) c = _addcarry_u64(c, _rdtscAcc.low, diff.low, &_rdtscAcc.low); _addcarry_u64(c, _rdtscAcc.high, diff.high, &_rdtscAcc.high); #else - // requires casting because of long / long long nonesense c = _addcarry_u64(c, _rdtscAcc.low, diff.low, (unsigned long long*)&_rdtscAcc.low); _addcarry_u64(c, _rdtscAcc.high, diff.high, (unsigned long long*)&_rdtscAcc.high); #endif uint64 remainder; - uint64 elapsedTick = _udiv128(_rdtscAcc.high, _rdtscAcc.low, _rdtscFrequency, &remainder); + uint64 elapsedTick = Divide128by64(_rdtscAcc.high, _rdtscAcc.low, _rdtscFrequency, &remainder); _rdtscAcc.low = remainder; _rdtscAcc.high = 0; - // timer scaling - elapsedTick <<= 3ull; // *8 + elapsedTick <<= 3ull; uint8 timerShiftFactor = ActiveSettings::GetTimerShiftFactor(); elapsedTick >>= timerShiftFactor; diff --git a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h index 4df2a666..270ba92e 100644 --- a/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h +++ b/src/Cafe/HW/Espresso/Recompiler/IML/IMLInstruction.h @@ -758,7 +758,7 @@ struct IMLInstruction void make_fpr_compare(IMLReg regA, IMLReg regB, IMLReg regR, IMLCondition cond) { this->type = PPCREC_IML_TYPE_FPR_COMPARE; - this->operation = -999; + this->operation = 255; this->op_fpr_compare.regR = regR; this->op_fpr_compare.regA = regA; this->op_fpr_compare.regB = regB; @@ -807,7 +807,7 @@ struct IMLInstruction void make_x86_eflags_jcc(IMLCondition cond, bool invertedCondition) { this->type = PPCREC_IML_TYPE_X86_EFLAGS_JCC; - this->operation = -999; + this->operation = 255; this->op_x86_eflags_jcc.cond = cond; this->op_x86_eflags_jcc.invertedCondition = invertedCondition; } @@ -823,4 +823,4 @@ namespace IMLArchX86 { static constexpr int PHYSREG_GPR_BASE = 0; static constexpr int PHYSREG_FPR_BASE = 16; -}; \ No newline at end of file +}; diff --git a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp index 3145e90e..bd6f7277 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureCache.cpp @@ -146,7 +146,7 @@ uint32 LatteTexture_CalculateTextureDataHash(LatteTexture* hostTexture) bool isCompressedFormat = hostTexture->IsCompressedFormat(); if( isCompressedFormat == false ) { -#if BOOST_OS_WINDOWS +#if BOOST_OS_WINDOWS && defined(_M_X64) if (g_CPUFeatures.x86.avx2) { __m256i h256 = { 0 }; @@ -430,4 +430,4 @@ void LatteTC_UnloadAllTextures() LatteTexture_Delete(itr); } LatteRenderTarget_unloadAll(); -} \ No newline at end of file +} diff --git a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp index 589b3bd0..caeca487 100644 --- a/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp +++ b/src/Cafe/HW/Latte/Core/LatteTextureLoader.cpp @@ -1,3 +1,4 @@ +#include "Cafe/OS/common/OSCommon.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" #include "Cafe/HW/Latte/LatteAddrLib/LatteAddrLib.h" #include "config/ActiveSettings.h" @@ -707,7 +708,7 @@ void optimizedLinearReadbackWriteLoop(LatteTextureLoaderCtx* textureLoader, uint copyType* blockData = (copyType*)LatteTextureLoader_getInputLinearOptimized_(textureLoader, 0, y, 1, 1, sizeof(copyType) * 8, 0, 1, 0, textureLoader->pitch, textureLoader->height); if constexpr (sizeof(copyType) == 4) { - memcpy_dwords(blockData, rowPixelData, textureLoader->width); + SAFE_MOVSD(blockData, rowPixelData, textureLoader->width); } else { diff --git a/src/Cafe/OS/common/OSCommon.h b/src/Cafe/OS/common/OSCommon.h index d35ff893..efee7191 100644 --- a/src/Cafe/OS/common/OSCommon.h +++ b/src/Cafe/OS/common/OSCommon.h @@ -113,4 +113,41 @@ static void* _ppc_va_arg(ppc_va_list* vargs, ppc_va_type argType) vargs->overflow_arg_area += 8; return r; } -} \ No newline at end of file +} + +#ifdef _WIN32 + #include +#else + #include + #if defined(__x86_64__) || defined(__i386__) + #include + #endif +#endif + +#ifdef _WIN32 + static inline void safe_memcpy_dwords(void* dest, const void* src, size_t count) { + #if defined(_M_ARM64) || defined(_M_ARM) + memcpy(dest, src, count * 4); + #else + __movsd((unsigned long*)dest, (const unsigned long*)src, (unsigned long)count); + #endif + } + static inline void safe_memcpy_qwords(void* dest, const void* src, size_t count) { + #if defined(_M_ARM64) || defined(_M_ARM) + memcpy(dest, src, count * 8); + #else + __movsq((unsigned __int64*)dest, (const unsigned __int64*)src, count); + #endif + } + #define SAFE_MOVSD(d, s, c) safe_memcpy_dwords((d), (s), (c)) + #define SAFE_MOVSQ(d, s, c) safe_memcpy_qwords((d), (s), (c)) +#else + static inline void safe_memcpy_dwords(void* dest, const void* src, size_t count) { + memcpy(dest, src, count * 4); + } + static inline void safe_memcpy_qwords(void* dest, const void* src, size_t count) { + memcpy(dest, src, count * 8); + } + #define SAFE_MOVSD(d, s, c) safe_memcpy_dwords((d), (s), (c)) + #define SAFE_MOVSQ(d, s, c) safe_memcpy_qwords((d), (s), (c)) +#endif diff --git a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp index a051fce1..4298677d 100644 --- a/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp +++ b/src/Cafe/OS/libs/coreinit/coreinit_LockedCache.cpp @@ -256,7 +256,7 @@ namespace coreinit uint8* destPtr = memory_getPointerFromVirtualOffset(hCPU->gpr[3]); uint8* srcPtr = memory_getPointerFromVirtualOffset(hCPU->gpr[4]); // copy right away, we don't emulate the DMAQueue currently - memcpy_qwords(destPtr, srcPtr, numBlocks * (32 / sizeof(uint64))); + SAFE_MOVSQ(destPtr, srcPtr, (size_t)numBlocks * 4); LatteBufferCache_notifyDCFlush(hCPU->gpr[3], numBlocks * 32); diff --git a/src/Cafe/OS/libs/gx2/GX2_Command.cpp b/src/Cafe/OS/libs/gx2/GX2_Command.cpp index d12bf210..5e05b50f 100644 --- a/src/Cafe/OS/libs/gx2/GX2_Command.cpp +++ b/src/Cafe/OS/libs/gx2/GX2_Command.cpp @@ -42,7 +42,7 @@ void gx2WriteGather_submitU32AsLEArray(uint32* v, uint32 numValues) uint32 coreIndex = PPCInterpreter_getCoreIndex(PPCInterpreter_getCurrentInstance()); if (GX2::s_perCoreCBState[coreIndex].currentWritePtr == nullptr) return; - memcpy_dwords(GX2::s_perCoreCBState[coreIndex].currentWritePtr, v, numValues); + SAFE_MOVSD(GX2::s_perCoreCBState[coreIndex].currentWritePtr, v, numValues); GX2::s_perCoreCBState[coreIndex].currentWritePtr += numValues; cemu_assert_debug(GX2::s_perCoreCBState[coreIndex].currentWritePtr <= (GX2::s_perCoreCBState[coreIndex].bufferPtr + GX2::s_perCoreCBState[coreIndex].bufferSizeInU32s)); } diff --git a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp index 6b205d26..3bd715f6 100644 --- a/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp +++ b/src/Common/ExceptionHandler/ExceptionHandler_win32.cpp @@ -209,6 +209,20 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context) // register info sprintf(dumpLine, "\n"); cemuLog_writePlainToLog(dumpLine); +#if defined(_M_ARM64) + // ARM64 Register Dump + sprintf(dumpLine, "X0 =%016I64x X1 =%016I64x X2 =%016I64x X3 =%016I64x\n", context->X0, context->X1, context->X2, context->X3); + cemuLog_writePlainToLog(dumpLine); + sprintf(dumpLine, "X4 =%016I64x X5 =%016I64x X6 =%016I64x X7 =%016I64x\n", context->X4, context->X5, context->X6, context->X7); + cemuLog_writePlainToLog(dumpLine); + sprintf(dumpLine, "X8 =%016I64x X9 =%016I64x X10=%016I64x X11=%016I64x\n", context->X8, context->X9, context->X10, context->X11); + cemuLog_writePlainToLog(dumpLine); + sprintf(dumpLine, "X12=%016I64x X13=%016I64x X14=%016I64x X15=%016I64x\n", context->X12, context->X13, context->X14, context->X15); + cemuLog_writePlainToLog(dumpLine); + sprintf(dumpLine, "SP =%016I64x PC =%016I64x\n", context->Sp, context->Pc); + cemuLog_writePlainToLog(dumpLine); +#else + // x86_64 Register Dump sprintf(dumpLine, "RAX=%016I64x RBX=%016I64x RCX=%016I64x RDX=%016I64x\n", context->Rax, context->Rbx, context->Rcx, context->Rdx); cemuLog_writePlainToLog(dumpLine); sprintf(dumpLine, "RSP=%016I64x RBP=%016I64x RDI=%016I64x RSI=%016I64x\n", context->Rsp, context->Rbp, context->Rdi, context->Rsi); @@ -217,6 +231,7 @@ void createCrashlog(EXCEPTION_POINTERS* e, PCONTEXT context) cemuLog_writePlainToLog(dumpLine); sprintf(dumpLine, "R12=%016I64x R13=%016I64x R14=%016I64x R15=%016I64x\n", context->R12, context->R13, context->R14, context->R15); cemuLog_writePlainToLog(dumpLine); +#endif CrashLog_SetOutputChannels(false, true); ExceptionHandler_LogGeneralInfo(); @@ -264,10 +279,13 @@ LONG WINAPI VectoredExceptionHandler(PEXCEPTION_POINTERS pExceptionInfo) if (r != EXCEPTION_CONTINUE_SEARCH) return r; +#if !defined(_M_ARM64) + // Hardware breakpoints (Dr6) are x86-specific in the Windows CONTEXT struct if (GetBits(pExceptionInfo->ContextRecord->Dr6, 0, 1) || GetBits(pExceptionInfo->ContextRecord->Dr6, 1, 1)) debugger_handleSingleStepException(pExceptionInfo->ContextRecord->Dr6); else if (GetBits(pExceptionInfo->ContextRecord->Dr6, 2, 1) || GetBits(pExceptionInfo->ContextRecord->Dr6, 3, 1)) g_gdbstub->HandleAccessException(pExceptionInfo->ContextRecord->Dr6); +#endif return EXCEPTION_CONTINUE_EXECUTION; } return EXCEPTION_CONTINUE_SEARCH; diff --git a/src/Common/Intrinsics.h b/src/Common/Intrinsics.h new file mode 100644 index 00000000..698509fc --- /dev/null +++ b/src/Common/Intrinsics.h @@ -0,0 +1,88 @@ +#pragma once +#include + +#if defined(_MSC_VER) + #include + #if defined(_M_ARM64) + #include + #define BARRIER_FENCE() __dmb(_ARM64_BARRIER_ISH) + #define READ_TSC() _ReadStatusReg(ARM64_CNTVCT_EL0) + #else + #include + #define BARRIER_FENCE() _mm_mfence() + #define READ_TSC() __rdtsc() + #endif +#else + #if defined(__aarch64__) + #define BARRIER_FENCE() __asm__ __volatile__ ("dmb ish" : : : "memory") + static inline uint64_t READ_TSC() { + uint64_t val; + __asm__ __volatile__("mrs %0, cntvct_el0" : "=r" (val)); + return val; + } + #else + #include + #define BARRIER_FENCE() __asm__ __volatile__ ("mfence" : : : "memory") + #define READ_TSC() __rdtsc() + #endif +#endif + +static inline uint64_t Multiply64to128(uint64_t a, uint64_t b, uint64_t* high) { +#if defined(__SIZEOF_INT128__) + unsigned __int128 res = (unsigned __int128)a * b; + *high = (uint64_t)(res >> 64); + return (uint64_t)res; +#elif defined(_MSC_VER) && defined(_M_X64) + return _umul128(a, b, high); +#elif defined(_MSC_VER) && defined(_M_ARM64) + *high = __umulh(a, b); + return a * b; +#else + // Generic fallback for other compilers/archs + uint64_t a_lo = (uint32_t)a, a_hi = a >> 32; + uint64_t b_lo = (uint32_t)b, b_hi = b >> 32; + uint64_t p0 = a_lo * b_lo; + uint64_t p1 = a_lo * b_hi; + uint64_t p2 = a_hi * b_lo; + uint64_t p3 = a_hi * b_hi; + uint64_t cy = (uint32_t)(p0 >> 32) + (uint32_t)p1 + (uint32_t)p2; + *high = p3 + (p1 >> 32) + (p2 >> 32) + (cy >> 32); + return (p0 & 0xFFFFFFFF) | (cy << 32); +#endif +} + +static inline uint64_t Divide128by64(uint64_t high, uint64_t low, uint64_t divisor, uint64_t* remainder) { +#if defined(__SIZEOF_INT128__) + unsigned __int128 dividend = ((unsigned __int128)high << 64) | low; + *remainder = (uint64_t)(dividend % divisor); + return (uint64_t)(dividend / divisor); +#elif defined(_MSC_VER) && defined(_M_X64) + return _udiv128(high, low, divisor, remainder); +#else + // Software fallback for MSVC ARM64 and others + // This implements long division for 128-bit / 64-bit + if (high < divisor) { + // Common case for many emulators: quotient fits in 64 bits + uint64_t q, r; + // Schoolbook division: split 128-bit into 4x32-bit if necessary, + // but here we use a binary long division for simplicity and correctness. + uint64_t rem = high; + uint64_t quot = 0; + for (int i = 63; i >= 0; i--) { + rem = (rem << 1) | ((low >> i) & 1); + if (rem >= divisor) { + rem -= divisor; + quot |= (1ULL << i); + } + } + *remainder = rem; + return quot; + } else { + // Quotient overflow: high >= divisor means result > 64 bits. + // If your code expects a 64-bit return, this is technically an error state. + // Return max value as a sentinel or handle as needed. + *remainder = 0; + return 0xFFFFFFFFFFFFFFFFULL; + } +#endif +} diff --git a/src/Common/precompiled.h b/src/Common/precompiled.h index e0373952..5f9e6d3a 100644 --- a/src/Common/precompiled.h +++ b/src/Common/precompiled.h @@ -341,44 +341,62 @@ inline uint64 _udiv128(uint64 highDividend, uint64 lowDividend, uint64 divisor, #define FORCE_INLINE inline #endif -FORCE_INLINE int BSF(uint32 v) // returns index of first bit set, counting from LSB. If v is 0 then result is undefined +FORCE_INLINE int BSF(uint32 v) // returns index of first bit set, counting from LSB. If v is 0 then result is 32 { #if defined(_MSC_VER) - return _tzcnt_u32(v); // TZCNT requires BMI1. But if not supported it will execute as BSF + #if defined(_M_ARM64) || defined(_M_ARM) + unsigned long index; + if (_BitScanForward(&index, (unsigned long)v)) + return (int)index; + return 32; + #else + // This is the x86/x64 specific intrinsic that was causing ARM64 build failures + return (v == 0) ? 32 : (int)_tzcnt_u32(v); + #endif #elif defined(__GNUC__) || defined(__clang__) - return __builtin_ctz(v); + return v == 0 ? 32 : __builtin_ctz(v); #else - return std::countr_zero(v); + return (int)std::countr_zero(v); #endif } -// On aarch64 we handle some of the x86 intrinsics by implementing them as wrappers -#if defined(__aarch64__) +#if defined(__aarch64__) || defined(_M_ARM64) inline void _mm_pause() { +#if defined(_MSC_VER) + __yield(); +#else asm volatile("yield"); +#endif } inline uint64 __rdtsc() { +#if defined(_MSC_VER) + return (uint64)_ReadStatusReg(ARM64_CNTVCT_EL0); +#else uint64 t; asm volatile("mrs %0, cntvct_el0" : "=r" (t)); return t; +#endif } inline void _mm_mfence() { - asm volatile("" ::: "memory"); - std::atomic_thread_fence(std::memory_order_seq_cst); +#if defined(_MSC_VER) + __dmb(_ARM64_BARRIER_ISH); // Inner Shareable Data Memory Barrier +#else + asm volatile("" ::: "memory"); + std::atomic_thread_fence(std::memory_order_seq_cst); +#endif } inline unsigned char _addcarry_u64(unsigned char carry, unsigned long long a, unsigned long long b, unsigned long long *result) { - *result = a + b + (unsigned long long)carry; - if (*result < a) - return 1; - return 0; + unsigned __int128 res = (unsigned __int128)a + b + carry; + *result = (unsigned long long)res; + return (res >> 64) ? 1 : 0; } #endif diff --git a/src/gui/wxgui/CMakeLists.txt b/src/gui/wxgui/CMakeLists.txt index 079a78cd..875937b0 100644 --- a/src/gui/wxgui/CMakeLists.txt +++ b/src/gui/wxgui/CMakeLists.txt @@ -191,6 +191,7 @@ endif() if(WIN32) target_link_libraries(CemuWxGui PRIVATE bthprops) + target_compile_options(CemuWxGui PRIVATE /wd4312) endif() if(ALLOW_PORTABLE) diff --git a/src/resource/cemu.rc b/src/resource/cemu.rc index e6332032..33ad1c65 100644 --- a/src/resource/cemu.rc +++ b/src/resource/cemu.rc @@ -13,38 +13,25 @@ #undef APSTUDIO_READONLY_SYMBOLS ///////////////////////////////////////////////////////////////////////////// -// Neutral (Default) (unknown sub-lang: 0x8) resources +// Neutral (Default) resources #if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ZZZ) -LANGUAGE LANG_NEUTRAL, 0x8 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL ///////////////////////////////////////////////////////////////////////////// // // Icon // -// Icon with lowest ID value placed first to ensure application icon -// remains consistent on all systems. M_WND_ICON128 ICON "resource\\logo_icon.ico" - M_WND_ICON16 ICON "resource\\logo_icon16.ico" - X_INPUT_CONTROLLER ICON "resource\\input\\icons8-game-controller-24.ico" - X_BOX ICON "resource\\icons8_cardboard_box_filled.ico" - X_SETTINGS ICON "resource\\icons8_automatic_26_xQK_icon.ico" - X_GAME_PROFILE ICON "resource\\icons8-compose-filled-50.ico" - X_HOTKEY_SETTINGS ICON "resource\\icons8_hotkeys.ico" #ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - 1 TEXTINCLUDE BEGIN "resource.h\0" @@ -61,10 +48,8 @@ BEGIN "\r\n" "\0" END - #endif // APSTUDIO_INVOKED - ///////////////////////////////////////////////////////////////////////////// // // Version @@ -73,16 +58,25 @@ END #define xstr(s) str(s) #define str(s) #s +#if defined(_M_ARM64) + #define ARCH_DESC " (ARM64)" +#elif defined(_M_X64) || defined(_M_AMD64) + #define ARCH_DESC " (x64)" +#else + #define ARCH_DESC "" +#endif + VS_VERSION_INFO VERSIONINFO -FILEVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 -PRODUCTVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 + FILEVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 + PRODUCTVERSION EMULATOR_VERSION_MAJOR, EMULATOR_VERSION_MINOR, EMULATOR_VERSION_PATCH, 0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L #else FILEFLAGS 0x0L #endif - FILEOS 0x0L + // VOS_NT_WINDOWS32 is used for both x64 and ARM64 NT-based systems + FILEOS 0x40004L FILETYPE 0x1L FILESUBTYPE 0x0L BEGIN @@ -90,12 +84,12 @@ BEGIN BEGIN BLOCK "040904b0" BEGIN - VALUE "FileDescription", "Cemu Wii U emulator" + VALUE "FileDescription", "Cemu Wii U emulator" ARCH_DESC VALUE "InternalName", "Cemu" VALUE "LegalCopyright", "Team Cemu" VALUE "OriginalFilename", "Cemu.exe" VALUE "ProductName", "Cemu" - VALUE "ProductVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) EMULATOR_VERSION_SUFFIX "\0" + VALUE "ProductVersion", xstr(EMULATOR_VERSION_MAJOR) "." xstr(EMULATOR_VERSION_MINOR) "." xstr(EMULATOR_VERSION_PATCH) EMULATOR_VERSION_SUFFIX "\0" END END BLOCK "VarFileInfo" @@ -104,7 +98,6 @@ BEGIN END END - ///////////////////////////////////////////////////////////////////////////// // // RCDATA @@ -112,10 +105,7 @@ END IDR_FONTAWESOME RCDATA "resource\\fontawesome-webfont.ttf" -#endif // Neutral (Default) (unknown sub-lang: 0x8) resources -///////////////////////////////////////////////////////////////////////////// - - +#endif // Neutral resources #ifndef APSTUDIO_INVOKED ///////////////////////////////////////////////////////////////////////////// @@ -126,4 +116,3 @@ IDR_FONTAWESOME RCDATA "resource\\fontawesome-webfont.t ///////////////////////////////////////////////////////////////////////////// #endif // not APSTUDIO_INVOKED - diff --git a/src/resource/installer.nsi b/src/resource/installer.nsi index 9d35c738..684798c4 100644 --- a/src/resource/installer.nsi +++ b/src/resource/installer.nsi @@ -2,12 +2,16 @@ ; Licensed under MPL 2.0 with permission from authors ; Usage: -; get the latest nsis: https://nsis.sourceforge.io/Download -; probably also want vscode extension: https://marketplace.visualstudio.com/items?itemName=idleberg.nsis +; makensis.exe /DPRODUCT_VERSION=2.0 /DARCH=arm64 installer.nsi +; makensis.exe /DPRODUCT_VERSION=2.0 /DARCH=x64 installer.nsi -; Require /DPRODUCT_VERSION for makensis. !ifndef PRODUCT_VERSION - !error "PRODUCT_VERSION must be defined" + !error "PRODUCT_VERSION must be defined (e.g. /DPRODUCT_VERSION=2.0)" +!endif + +; Default to x64 if ARCH is not defined +!ifndef ARCH + !define ARCH "x64" !endif ManifestDPIAware true @@ -19,38 +23,33 @@ ManifestDPIAware true !define PRODUCT_UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCT_NAME}" !define BINARY_SOURCE_DIR "..\..\bin" +OutFile "cemu-${PRODUCT_VERSION}-windows-${ARCH}-installer.exe" -Name "${PRODUCT_NAME}" -OutFile "cemu-${PRODUCT_VERSION}-windows-x64-installer.exe" +Name "${PRODUCT_NAME} (${ARCH})" SetCompressor /SOLID lzma InstallDir "$LOCALAPPDATA\Cemu" ShowInstDetails show ShowUnInstDetails show !include "MUI2.nsh" -; Custom page plugin !include "nsDialogs.nsh" +!include "x64.nsh" ; MUI Settings !define MUI_ICON "logo_icon.ico" !define MUI_UNICON "${NSISDIR}\Contrib\Graphics\Icons\modern-uninstall.ico" -; License page !insertmacro MUI_PAGE_LICENSE "..\..\LICENSE.txt" -; Desktop Shortcut page Page custom desktopShortcutPageCreate desktopShortcutPageLeave -; Directory page !insertmacro MUI_PAGE_DIRECTORY -; Instfiles page !insertmacro MUI_PAGE_INSTFILES -; Finish page + !define MUI_FINISHPAGE_RUN "$INSTDIR\Cemu.exe" !insertmacro MUI_PAGE_FINISH ; Uninstaller pages !insertmacro MUI_UNPAGE_INSTFILES -; Variables Var DesktopShortcutPageDialog Var DesktopShortcutCheckbox Var DesktopShortcut @@ -81,8 +80,19 @@ Var DesktopShortcut ; MUI end ------ Function .onInit - StrCpy $DesktopShortcut 1 + ; Block installation if trying to install x64 on ARM without emulation, + ; or ensure the user is aware. + ${If} "${ARCH}" == "arm64" + ${Unless} ${IsNativeARM64} + MessageBox MB_OK|MB_ICONEXCLAMATION "This installer is for ARM64 systems. Your CPU does not appear to support it natively." + ${EndUnless} + ${Else} + ${If} ${IsNativeARM64} + DetailPrint "Running x64 installer on ARM64 system via Prism/Emulation." + ${EndIf} + ${EndIf} + StrCpy $DesktopShortcut 1 !insertmacro MUI_LANGDLL_DISPLAY FunctionEnd @@ -97,7 +107,6 @@ Function desktopShortcutPageCreate ${NSD_CreateCheckbox} 0u 0u 100% 12u "Create a desktop shortcut" Pop $DesktopShortcutCheckbox ${NSD_SetState} $DesktopShortcutCheckbox $DesktopShortcut - nsDialogs::Show FunctionEnd @@ -106,16 +115,16 @@ Function desktopShortcutPageLeave FunctionEnd Section "Base" + ; Prevent running the uninstaller of a different arch in the same folder + ; without cleaning up first ExecWait '"$INSTDIR\uninst.exe" /S _?=$INSTDIR' SectionIn RO - SetOutPath "$INSTDIR" - ; The binplaced build output will be included verbatim. + ; This will pull files from the directory defined at the top File /r "${BINARY_SOURCE_DIR}\*" - ; Create start menu and desktop shortcuts CreateShortCut "$SMPROGRAMS\$(^Name).lnk" "$INSTDIR\Cemu.exe" ${If} $DesktopShortcut == 1 CreateShortCut "$DESKTOP\$(^Name).lnk" "$INSTDIR\Cemu.exe" @@ -126,20 +135,19 @@ SectionEnd Section -Post WriteUninstaller "$INSTDIR\uninst.exe" - WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\Cemu.exe" - - ; Write metadata for add/remove programs applet WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\Cemu.exe" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "URLInfoAbout" "${PRODUCT_WEB_SITE}" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}" WriteRegStr HKCU "${PRODUCT_UNINST_KEY}" "InstallLocation" "$INSTDIR" + ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 IntFmt $0 "0x%08X" $0 WriteRegDWORD HKCU "${PRODUCT_UNINST_KEY}" "EstimatedSize" "$0" + ; File Associations WriteRegStr HKCU "Software\Classes\.wud" "" "$(^Name)" WriteRegStr HKCU "Software\Classes\.wux" "" "$(^Name)" WriteRegStr HKCU "Software\Classes\.wua" "" "$(^Name)" @@ -150,8 +158,6 @@ SectionEnd Section Uninstall Delete "$DESKTOP\$(^Name).lnk" Delete "$SMPROGRAMS\$(^Name).lnk" - -; Be a bit careful to not delete files a user may have put into the install directory Delete "$INSTDIR\Cemu.exe" Delete "$INSTDIR\uninst.exe" RMDir /r "$INSTDIR\gameProfiles" @@ -162,9 +168,6 @@ Section Uninstall DeleteRegKey HKCU "Software\Classes\.wux" DeleteRegKey HKCU "Software\Classes\.wua" DeleteRegKey HKCU "Software\Classes\$(^Name)" - - DeleteRegKey HKCU "Software\Classes\discord-460807638964371468" - DeleteRegKey HKCU "${PRODUCT_UNINST_KEY}" DeleteRegKey HKCU "${PRODUCT_DIR_REGKEY}" diff --git a/vcpkg.json b/vcpkg.json index 576c7b27..116d26d6 100644 --- a/vcpkg.json +++ b/vcpkg.json @@ -67,7 +67,8 @@ "zip" ] }, - "libusb" + "libusb", + "pkgconf" ], "overrides": [ {