mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-07-09 17:14:47 -06:00
WinArm64-MSVC
This commit is contained in:
parent
8e3e961b8e
commit
d0c2212c5f
19
.github/workflows/build.yml
vendored
19
.github/workflows/build.yml
vendored
@ -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
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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}"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
328
dependencies/ih264d/CMakeLists.txt
vendored
328
dependencies/ih264d/CMakeLists.txt
vendored
@ -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 $<$<COMPILE_LANGUAGE:ASM,Clang>:-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$<$<CONFIG:Debug>:Debug>")
|
||||
|
||||
# tune settings for slightly better performance
|
||||
target_compile_options(ih264d PRIVATE $<$<CONFIG:Release,RelWithDebInfo>:/Oi>) # enable intrinsic functions
|
||||
target_compile_options(ih264d PRIVATE $<$<CONFIG:Release,RelWithDebInfo>:/Ot>) # favor speed
|
||||
target_compile_options(ih264d PRIVATE "/GS-") # disable runtime checks
|
||||
|
||||
set_property(TARGET ih264d PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
|
||||
target_compile_options(ih264d PRIVATE $<$<CONFIG:Release,RelWithDebInfo>:/Oi> $<$<CONFIG:Release,RelWithDebInfo>:/Ot> "/GS-")
|
||||
endif()
|
||||
|
||||
13
dependencies/ih264d/CMakeSettings.json
vendored
13
dependencies/ih264d/CMakeSettings.json
vendored
@ -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" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,144 +38,95 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#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 <arm_neon.h>
|
||||
|
||||
#define DATA_SYNC() __sync_synchronize()
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
|
||||
#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<<shift))
|
||||
|
||||
#define INLINE inline
|
||||
|
||||
/* In normal cases, 0 will not be passed as an argument to CLZ and CTZ.
|
||||
As CLZ and CTZ outputs are used as a shift value in few places, these return
|
||||
31 for u4_word == 0 case, just to handle error cases gracefully without any
|
||||
undefined behaviour */
|
||||
|
||||
static INLINE UWORD32 CLZ(UWORD32 u4_word)
|
||||
{
|
||||
if(u4_word)
|
||||
return (__builtin_clz(u4_word));
|
||||
else
|
||||
return 31;
|
||||
}
|
||||
static INLINE UWORD32 CTZ(UWORD32 u4_word)
|
||||
{
|
||||
if(0 == u4_word)
|
||||
return 31;
|
||||
else
|
||||
{
|
||||
unsigned int index;
|
||||
index = __builtin_ctz(u4_word);
|
||||
return (UWORD32)index;
|
||||
}
|
||||
}
|
||||
|
||||
#define MEM_ALIGN8 __attribute__ ((aligned (8)))
|
||||
#define MEM_ALIGN16 __attribute__ ((aligned (16)))
|
||||
#define MEM_ALIGN32 __attribute__ ((aligned (32)))
|
||||
|
||||
#endif /* _IH264_PLATFORM_MACROS_H_ */
|
||||
|
||||
23
dist/windows/Cemu.manifest
vendored
23
dist/windows/Cemu.manifest
vendored
@ -1,16 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
|
||||
<dependency>
|
||||
<dependentAssembly>
|
||||
<assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="amd64" publicKeyToken="6595b64144ccf1df" language="*"></assemblyIdentity>
|
||||
<!-- Changed processorArchitecture to "*" for ARM64/x64 compatibility -->
|
||||
<assemblyIdentity
|
||||
type="win32"
|
||||
name="Microsoft.Windows.Common-Controls"
|
||||
version="6.0.0.0"
|
||||
processorArchitecture="*"
|
||||
publicKeyToken="6595b64144ccf1df"
|
||||
language="*" />
|
||||
</dependentAssembly>
|
||||
</dependency>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"><security><requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel></requestedPrivileges></security>
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
<application xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<windowsSettings>
|
||||
<!-- Modern DPI awareness setting (covers Windows 7 through 11) -->
|
||||
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">True/PM</dpiAware>
|
||||
<dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
|
||||
</windowsSettings>
|
||||
</application>
|
||||
</assembly>
|
||||
</assembly>
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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$<$<CONFIG:Debug>: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)
|
||||
|
||||
@ -199,7 +199,7 @@ void debugger_updateMemoryBreakpoint(DebuggerBreakpoint* bp)
|
||||
{
|
||||
std::vector<std::thread::native_handle_type> 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)
|
||||
|
||||
@ -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 <immintrin.h>
|
||||
#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;
|
||||
|
||||
|
||||
@ -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;
|
||||
};
|
||||
};
|
||||
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
{
|
||||
|
||||
@ -113,4 +113,41 @@ static void* _ppc_va_arg(ppc_va_list* vargs, ppc_va_type argType)
|
||||
vargs->overflow_arg_area += 8;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include <string.h>
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
#include <x86intrin.h>
|
||||
#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
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
88
src/Common/Intrinsics.h
Normal file
88
src/Common/Intrinsics.h
Normal file
@ -0,0 +1,88 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h>
|
||||
#if defined(_M_ARM64)
|
||||
#include <arm64intr.h>
|
||||
#define BARRIER_FENCE() __dmb(_ARM64_BARRIER_ISH)
|
||||
#define READ_TSC() _ReadStatusReg(ARM64_CNTVCT_EL0)
|
||||
#else
|
||||
#include <immintrin.h>
|
||||
#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 <x86intrin.h>
|
||||
#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
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -191,6 +191,7 @@ endif()
|
||||
|
||||
if(WIN32)
|
||||
target_link_libraries(CemuWxGui PRIVATE bthprops)
|
||||
target_compile_options(CemuWxGui PRIVATE /wd4312)
|
||||
endif()
|
||||
|
||||
if(ALLOW_PORTABLE)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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}"
|
||||
|
||||
|
||||
@ -67,7 +67,8 @@
|
||||
"zip"
|
||||
]
|
||||
},
|
||||
"libusb"
|
||||
"libusb",
|
||||
"pkgconf"
|
||||
],
|
||||
"overrides": [
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user