diff --git a/CMakeLists.txt b/CMakeLists.txt index 4429cc59943..c23f0303e8e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,10 +81,24 @@ add_compile_options($<$:/utf-8>) add_compile_options($<$:/Zc:preprocessor>) if (CMAKE_SYSTEM_NAME STREQUAL "Windows") + if(NOT CMAKE_VS_PLATFORM_NAME) + set(CMAKE_VS_PLATFORM_NAME "x64") + endif() + + if("${CMAKE_VS_PLATFORM_NAME}" MATCHES "^[Aa][Rr][Mm]64$") + set(SOH_WINDOWS_ARM64 TRUE) + else() + set(SOH_WINDOWS_ARM64 FALSE) + endif() + include(CMake/automate-vcpkg.cmake) set(VCPKG_TRIPLET x64-windows-static) set(VCPKG_TARGET_TRIPLET x64-windows-static) + if(SOH_WINDOWS_ARM64) + set(VCPKG_TRIPLET arm64-windows-static) + set(VCPKG_TARGET_TRIPLET arm64-windows-static) + endif() vcpkg_bootstrap() vcpkg_install_packages(zlib bzip2 libzip libpng sdl2 sdl2-net glew glfw3 nlohmann-json tinyxml2 spdlog libogg libvorbis opus opusfile) @@ -103,7 +117,8 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") message("${CMAKE_VS_PLATFORM_NAME} architecture in use") if(NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64" - OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")) + OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32" + OR SOH_WINDOWS_ARM64)) message(FATAL_ERROR "${CMAKE_VS_PLATFORM_NAME} arch is not supported!") endif() endif() diff --git a/soh/CMakeLists.txt b/soh/CMakeLists.txt index 31955ebf90a..1a921505099 100644 --- a/soh/CMakeLists.txt +++ b/soh/CMakeLists.txt @@ -22,10 +22,21 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") if(NOT CMAKE_VS_PLATFORM_NAME) set(CMAKE_VS_PLATFORM_NAME "x64") endif() + if("${CMAKE_VS_PLATFORM_NAME}" MATCHES "^[Aa][Rr][Mm]64$") + set(SOH_WINDOWS_ARM64 TRUE) + else() + set(SOH_WINDOWS_ARM64 FALSE) + endif() + if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64" OR SOH_WINDOWS_ARM64) + set(SOH_WINDOWS_64BIT TRUE) + else() + set(SOH_WINDOWS_64BIT FALSE) + endif() message("${CMAKE_VS_PLATFORM_NAME} architecture in use") if(NOT ("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64" - OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32")) + OR "${CMAKE_VS_PLATFORM_NAME}" STREQUAL "Win32" + OR SOH_WINDOWS_ARM64)) message(FATAL_ERROR "${CMAKE_VS_PLATFORM_NAME} arch is not supported!") endif() endif() @@ -235,7 +246,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") set_target_properties(${PROJECT_NAME} PROPERTIES VS_GLOBAL_KEYWORD "Win32Proj" ) - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) set_target_properties(${PROJECT_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_RELEASE "TRUE" ) @@ -259,7 +270,7 @@ endif() ################################################################################ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") get_property(MSVC_RUNTIME_LIBRARY_DEFAULT TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY) - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) string(CONCAT "MSVC_RUNTIME_LIBRARY_STR" $<$: MultiThreadedDebug @@ -329,7 +340,7 @@ target_include_directories(${PROJECT_NAME} PRIVATE assets ) if (CMAKE_SYSTEM_NAME STREQUAL "Windows") - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) target_compile_definitions(${PROJECT_NAME} PRIVATE "$<$:" "_DEBUG;" @@ -410,7 +421,7 @@ endif() # Compile and link options ################################################################################ if(MSVC) - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) target_compile_options(${PROJECT_NAME} PRIVATE $<$: /w; @@ -447,7 +458,7 @@ if(MSVC) ${DEFAULT_CXX_EXCEPTION_HANDLING} ) endif() - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) target_link_options(${PROJECT_NAME} PRIVATE $<$: /INCREMENTAL @@ -635,7 +646,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Windows") link_libraries(Opus::opus) find_package(OpusFile CONFIG REQUIRED) link_libraries(OpusFile::opusfile CONFIG REQUIRED) - if("${CMAKE_VS_PLATFORM_NAME}" STREQUAL "x64") + if(SOH_WINDOWS_64BIT) set(ADDITIONAL_LIBRARY_DEPENDENCIES "libultraship;" "ZAPDLib;" diff --git a/soh/soh/Extractor/FastCrc32C.c b/soh/soh/Extractor/FastCrc32C.c index 2dccda61eca..795cc42d749 100644 --- a/soh/soh/Extractor/FastCrc32C.c +++ b/soh/soh/Extractor/FastCrc32C.c @@ -12,11 +12,18 @@ #pragma GCC target("sse4.2") #endif -// Include headers for the CRC32 intrinsic and cpuid instruction on windows. No need to do any other checks because it -// assumes the target will support CRC32 +// Include headers for the CRC32 intrinsic and CPU feature checks on Windows x86/x64/ARM64. #ifdef _WIN32 -#include +#if defined(_M_X64) || defined(_M_IX86) || defined(_M_ARM64) #include +#if defined(_M_X64) || defined(_M_IX86) +#include +#elif defined(_M_ARM64) +#include +#endif +#else +#define NO_CRC_INTRIN +#endif // Same as above but these platforms use slightly different headers #elif ((defined(__GNUC__) && (defined(__x86_64__) || defined(__i386__)))) #include @@ -27,12 +34,18 @@ #define NO_CRC_INTRIN #endif -#if defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) +#if defined(_MSC_VER) && defined(_M_ARM64) +#define INTRIN_CRC32_64(crc, data) crc = __crc32cd(crc, data) +#define INTRIN_CRC32_32(crc, data) crc = __crc32cw(crc, data) +#define INTRIN_CRC32_16(crc, data) crc = __crc32ch(crc, data) +#define INTRIN_CRC32_8(crc, data) crc = __crc32cb(crc, data) +#elif defined(__aarch64__) && defined(__ARM_FEATURE_CRC32) #define INTRIN_CRC32_64(crc, value) __asm__("crc32cx %w[c], %w[c], %x[v]" : [c] "+r"(crc) : [v] "r"(value)) #define INTRIN_CRC32_32(crc, value) __asm__("crc32cw %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value)) #define INTRIN_CRC32_16(crc, value) __asm__("crc32ch %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value)) #define INTRIN_CRC32_8(crc, value) __asm__("crc32cb %w[c], %w[c], %w[v]" : [c] "+r"(crc) : [v] "r"(value)) -#elif defined(__GNUC__) || defined(_MSC_VER) +#elif ((defined(__GNUC__) || defined(_MSC_VER)) && \ + (defined(_M_X64) || defined(_M_IX86) || defined(__x86_64__) || defined(__i386__))) #define INTRIN_CRC32_64(crc, data) crc = _mm_crc32_u64(crc, data) #define INTRIN_CRC32_32(crc, data) crc = _mm_crc32_u32(crc, data) #define INTRIN_CRC32_16(crc, data) crc = _mm_crc32_u16(crc, data) @@ -78,7 +91,7 @@ static uint32_t CRC32IntrinImpl(unsigned char* data, size_t dataSize) { uint32_t ret = 0xFFFFFFFF; int64_t sizeSigned = dataSize; // Only 64bit platforms support doing a CRC32 operation on a 64bit value -#if defined(_M_X64) || defined(__x86_64__) || defined(__aarch64__) +#if defined(_M_X64) || defined(_M_ARM64) || defined(__x86_64__) || defined(__aarch64__) while ((sizeSigned -= sizeof(uint64_t)) >= 0) { INTRIN_CRC32_64(ret, *(uint64_t*)data); data += sizeof(uint64_t); @@ -122,6 +135,11 @@ static uint32_t CRC32TableImpl(unsigned char* data, size_t dataSize) { uint32_t CRC32C(unsigned char* data, size_t dataSize) { #ifndef NO_CRC_INTRIN // Test to make sure the CPU supports the CRC32 intrinsic +#if defined(_WIN32) && defined(_M_ARM64) + if (IsProcessorFeaturePresent(PF_ARM_V8_CRC32_INSTRUCTIONS_AVAILABLE)) { + return CRC32IntrinImpl(data, dataSize); + } +#else unsigned int cpuidData[4]; #ifdef _WIN32 __cpuid(cpuidData, 1); @@ -135,6 +153,7 @@ uint32_t CRC32C(unsigned char* data, size_t dataSize) { if (cpuidData[2] & (1 << 20)) { // bit_SSE4_2 return CRC32IntrinImpl(data, dataSize); } +#endif #endif // NO_CRC_INTRIN return CRC32TableImpl(data, dataSize); } diff --git a/soh/soh/ShipUtils.h b/soh/soh/ShipUtils.h index 9046ffb08ea..f0c85adaba5 100644 --- a/soh/soh/ShipUtils.h +++ b/soh/soh/ShipUtils.h @@ -4,6 +4,7 @@ #include #ifdef __cplusplus +#include void LoadGuiTextures();