initial work for ios port

This commit is contained in:
MarkosTh09 2026-06-05 21:45:39 +04:00
parent 5e8695a157
commit c50f020801
No known key found for this signature in database
GPG key ID: 72CBCC6CED88B416
24 changed files with 2016 additions and 104 deletions

View file

@ -165,6 +165,66 @@
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
}
},
{
"name": "ios-base",
"hidden": true,
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "iOS",
"CMAKE_OSX_SYSROOT": "iphoneos",
"CMAKE_OSX_ARCHITECTURES": "arm64",
"CMAKE_OSX_DEPLOYMENT_TARGET": "16.4",
"DEPLOYMENT_TARGET": "16.4",
"PLATFORM": "OS64",
"CMAKE_TOOLCHAIN_FILE": {
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"type": "FILEPATH"
},
"VCPKG_CHAINLOAD_TOOLCHAIN_FILE": {
"value": "${sourceDir}/toolchains/ios.toolchain.cmake",
"type": "FILEPATH"
},
"VCPKG_TARGET_TRIPLET": {
"value": "arm64-ios",
"type": "STRING"
}
},
"environment": {
"VCPKG_ROOT": "${sourceDir}/thirdparty/vcpkg"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
{
"name": "ios-device-debug",
"displayName": "iOS Device Debug",
"inherits": "ios-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug"
}
},
{
"name": "ios-device-relwithdebinfo",
"displayName": "iOS Device RelWithDebInfo",
"inherits": "ios-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "RelWithDebInfo"
}
},
{
"name": "ios-device-release",
"displayName": "iOS Device Release",
"inherits": "ios-base",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
}
}
]
}

View file

@ -1,10 +1,10 @@
project("UnleashedRecomp")
if (WIN32)
if(WIN32)
option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
endif()
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
option(UNLEASHED_RECOMP_FLATPAK "Configure the build for Flatpak compatibility." OFF)
endif()
@ -27,15 +27,40 @@ function(BIN2C)
set(BIN2C_ARGS_COMPRESSION_TYPE "none")
endif()
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
COMMAND $<TARGET_FILE:file_to_c> "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}"
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
)
if(NOT CMAKE_CROSSCOMPILING)
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
COMMAND $<TARGET_FILE:file_to_c> "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}"
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
COMMENT "Generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
)
else()
# When cross-compiling, build a host-native file_to_c out-of-tree and invoke it
set(HOST_FILE_TO_C_BUILD_DIR "${CMAKE_BINARY_DIR}/host-tools/file_to_c")
set(HOST_FILE_TO_C_BIN "${HOST_FILE_TO_C_BUILD_DIR}/file_to_c")
add_custom_command(OUTPUT "${BIN2C_ARGS_DEST_FILE}.c"
COMMAND ${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/tools/file_to_c" -B "${HOST_FILE_TO_C_BUILD_DIR}"
-G "${CMAKE_GENERATOR}"
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/host-tools/install
COMMAND ${CMAKE_COMMAND} --build "${HOST_FILE_TO_C_BUILD_DIR}" --config ${CMAKE_BUILD_TYPE}
COMMAND "${HOST_FILE_TO_C_BIN}" "${BIN2C_ARGS_SOURCE_FILE}" "${BIN2C_ARGS_ARRAY_NAME}" "${BIN2C_ARGS_COMPRESSION_TYPE}" "${BIN2C_ARGS_DEST_FILE}.c" "${BIN2C_ARGS_DEST_FILE}.h"
DEPENDS "${BIN2C_ARGS_SOURCE_FILE}"
BYPRODUCTS "${BIN2C_ARGS_DEST_FILE}.h"
COMMENT "Cross: building host file_to_c and generating binary header for ${BIN2C_ARGS_SOURCE_FILE}..."
USES_TERMINAL
)
endif()
set(_bin2c_target ${BIN2C_ARGS_TARGET_OBJ})
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND TARGET UnleashedRecompIOSLauncher)
set(_bin2c_target UnleashedRecompIOSLauncher)
endif()
set_source_files_properties(${BIN2C_ARGS_DEST_FILE}.c PROPERTIES SKIP_PRECOMPILE_HEADERS ON)
target_sources(${BIN2C_ARGS_TARGET_OBJ} PRIVATE ${BIN2C_ARGS_DEST_FILE}.c)
target_sources(${_bin2c_target} PRIVATE ${BIN2C_ARGS_DEST_FILE}.c)
endfunction()
add_compile_options(
@ -52,7 +77,7 @@ add_compile_options(
-Wno-tautological-undefined-compare
)
if (WIN32)
if(WIN32)
add_compile_options(/fp:strict)
else()
add_compile_options(-ffp-model=strict)
@ -81,7 +106,7 @@ set(UNLEASHED_RECOMP_LOCALE_CXX_SOURCES
"locale/locale.cpp"
)
if (WIN32)
if(WIN32)
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
"os/win32/logger_win32.cpp"
"os/win32/media_win32.cpp"
@ -89,7 +114,7 @@ if (WIN32)
"os/win32/user_win32.cpp"
"os/win32/version_win32.cpp"
)
elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux")
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
"os/linux/logger_linux.cpp"
"os/linux/media_linux.cpp"
@ -97,7 +122,7 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
"os/linux/user_linux.cpp"
"os/linux/version_linux.cpp"
)
elseif (APPLE)
elseif(APPLE)
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
"os/macos/logger_macos.cpp"
"os/macos/media_macos.cpp"
@ -229,7 +254,8 @@ set(UNLEASHED_RECOMP_CXX_SOURCES
"sdl_listener.cpp"
"stdafx.cpp"
"version.cpp"
"apple_utils.mm"
${UNLEASHED_RECOMP_KERNEL_CXX_SOURCES}
${UNLEASHED_RECOMP_LOCALE_CXX_SOURCES}
${UNLEASHED_RECOMP_OS_CXX_SOURCES}
@ -251,7 +277,8 @@ set(VERSION_TXT "${PROJECT_SOURCE_DIR}/res/version.txt")
# Only show Git info and build type if not Release.
set(SHOW_GIT_INFO_AND_BUILD_TYPE 0)
if (NOT ${CMAKE_BUILD_TYPE} MATCHES "Release")
if(NOT ${CMAKE_BUILD_TYPE} MATCHES "Release")
set(SHOW_GIT_INFO_AND_BUILD_TYPE 1)
endif()
@ -265,7 +292,7 @@ GenerateVersionSources(
SHOW_BUILD_TYPE ${SHOW_GIT_INFO_AND_BUILD_TYPE}
)
if (WIN32)
if(WIN32)
# Create binary version number for Win32 integer attributes.
CreateVersionString(
VERSION_TXT ${VERSION_TXT}
@ -289,16 +316,18 @@ if (WIN32)
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES} "${CMAKE_BINARY_DIR}/res.rc")
# Hide console for release configurations.
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
if(${CMAKE_BUILD_TYPE} MATCHES "Release")
target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
endif()
elseif (APPLE)
elseif(APPLE)
# Create version number for app bundle.
CreateVersionString(
VERSION_TXT ${VERSION_TXT}
OUTPUT_VAR MACOS_BUNDLE_VERSION
)
set(IOS_BUNDLE_VERSION ${MACOS_BUNDLE_VERSION})
add_executable(UnleashedRecomp MACOSX_BUNDLE
${UNLEASHED_RECOMP_CXX_SOURCES}
res/macos/game_icon.icns
@ -313,8 +342,85 @@ elseif (APPLE)
MACOSX_BUNDLE_BUNDLE_VERSION ${MACOS_BUNDLE_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${MACOS_BUNDLE_VERSION}
MACOSX_BUNDLE_ICON_FILE "game_icon.icns"
MACOSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
set_target_properties(UnleashedRecomp PROPERTIES
EXCLUDE_FROM_ALL TRUE
EXCLUDE_FROM_DEFAULT_BUILD TRUE
)
endif()
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
add_executable(UnleashedRecompIOSLauncher MACOSX_BUNDLE
${UNLEASHED_RECOMP_CXX_SOURCES}
"ios/launcher_main.mm"
)
set_target_properties(UnleashedRecompIOSLauncher PROPERTIES
OUTPUT_NAME "Unleashed Recompiled iOS"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/res/ios/iOSBundleInfo.plist.in
MACOSX_BUNDLE_GUI_IDENTIFIER hedge-dev.UnleashedRecomp.iOSLauncher
MACOSX_BUNDLE_BUNDLE_NAME "Unleashed Recompiled"
MACOSX_BUNDLE_BUNDLE_VERSION ${IOS_BUNDLE_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${IOS_BUNDLE_VERSION}
MACOSX_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
set_target_properties(UnleashedRecompIOSLauncher PROPERTIES
OUTPUT_NAME "Unleashed Recompiled iOS"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/res/ios/iOSBundleInfo.plist.in
MACOSX_BUNDLE_GUI_IDENTIFIER hedge-dev.UnleashedRecomp.iOSLauncher
MACOSX_BUNDLE_BUNDLE_NAME "Unleashed Recompiled"
MACOSX_BUNDLE_BUNDLE_VERSION ${IOS_BUNDLE_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${IOS_BUNDLE_VERSION}
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET "${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
target_compile_definitions(UnleashedRecompIOSLauncher PRIVATE
UNLEASHED_RECOMP_IOS_LAUNCHER
)
set(MVK_FRAMEWORK_PATH "Frameworks/MoltenVK.framework")
set(MVK_ICD_PATH "vulkan/icd.d")
set(MVK_APP_DIR "$<TARGET_BUNDLE_DIR:UnleashedRecompIOSLauncher>")
set(MVK_FRAMEWORK_DST "${MVK_APP_DIR}/${MVK_FRAMEWORK_PATH}")
set(MVK_ICD_DST "${MVK_APP_DIR}/${MVK_ICD_PATH}")
set_target_properties(UnleashedRecompIOSLauncher PROPERTIES
BUILD_RPATH "@executable_path/Frameworks"
INSTALL_RPATH "@executable_path/Frameworks"
)
set(MVK_ICD_SRC "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json")
set(MVK_FRAMEWORK_SRC
"${CMAKE_BINARY_DIR}/thirdparty/MoltenVK/MoltenVK.framework"
)
add_custom_command(
TARGET UnleashedRecompIOSLauncher POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${MVK_FRAMEWORK_DST}"
COMMAND ${CMAKE_COMMAND} -E copy_directory
"${MVK_FRAMEWORK_SRC}"
"${MVK_FRAMEWORK_DST}"
COMMENT "Copying MoltenVK.framework into iOS app bundle"
)
add_custom_command(
TARGET UnleashedRecompIOSLauncher POST_BUILD
COMMAND ${CMAKE_COMMAND} -E make_directory "${MVK_APP_DIR}/vulkan/icd.d"
COMMAND ${CMAKE_COMMAND} -E copy
"${MVK_ICD_SRC}"
"${MVK_APP_DIR}/vulkan/icd.d/MoltenVK_icd.json"
COMMENT "Copying MoltenVK ICD"
)
add_dependencies(UnleashedRecompIOSLauncher MoltenVK)
endif()
# Linking with MoltenVK directly would prevent using the system Vulkan loader to load with debug layers.
# Instead, copy the MoltenVK dylib to the app bundle along with an ICD file for the loader to find it.
# In the event the loader is not installed, the MoltenVK dylib can still be picked up directly in the app bundle.
@ -324,7 +430,7 @@ elseif (APPLE)
set(MVK_ICD_SRC "${UNLEASHED_RECOMP_THIRDPARTY_ROOT}/MoltenVK/MoltenVK/MoltenVK/icd/MoltenVK_icd.json")
set(MVK_ICD_DST "${MVK_DST}/MoltenVK_icd.json")
set(MVK_DYLIB_SRC "${CMAKE_BINARY_DIR}/thirdparty/MoltenVK/libMoltenVK.dylib")
set(MVK_DYLIB_SRC "${CMAKE_BINARY_DIR}/thirdparty/MoltenVK/MoltenVK.framework/MoltenVK")
set(MVK_DYLIB_DST "${MVK_DST}/libMoltenVK.dylib")
add_custom_command(
@ -345,16 +451,17 @@ else()
add_executable(UnleashedRecomp ${UNLEASHED_RECOMP_CXX_SOURCES})
endif()
if (UNLEASHED_RECOMP_FLATPAK)
target_compile_definitions(UnleashedRecomp PRIVATE
if(UNLEASHED_RECOMP_FLATPAK)
target_compile_definitions(UnleashedRecomp PRIVATE
"UNLEASHED_RECOMP_FLATPAK"
"GAME_INSTALL_DIRECTORY=\"/var/data\""
)
endif()
find_package(CURL REQUIRED)
find_package(zstd CONFIG REQUIRED)
if (UNLEASHED_RECOMP_D3D12)
if(UNLEASHED_RECOMP_D3D12)
find_package(directx-headers CONFIG REQUIRED)
find_package(directx12-agility CONFIG REQUIRED)
target_compile_definitions(UnleashedRecomp PRIVATE UNLEASHED_RECOMP_D3D12)
@ -375,7 +482,7 @@ if (UNLEASHED_RECOMP_D3D12)
)
endif()
if (WIN32)
if(WIN32)
target_link_libraries(UnleashedRecomp PRIVATE
comctl32
dwmapi
@ -387,9 +494,9 @@ if (WIN32)
)
endif()
target_link_libraries(UnleashedRecomp PRIVATE
set(UNLEASHED_RECOMP_LINK_LIBS
fmt::fmt
libzstd_static
zstd::libzstd
msdf-atlas-gen::msdf-atlas-gen
nfd::nfd
o1heap
@ -403,13 +510,19 @@ target_link_libraries(UnleashedRecomp PRIVATE
plume
)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
list(APPEND UNLEASHED_RECOMP_LINK_LIBS "-framework UniformTypeIdentifiers")
endif()
target_link_libraries(UnleashedRecomp PRIVATE ${UNLEASHED_RECOMP_LINK_LIBS})
target_include_directories(UnleashedRecomp PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/api"
${UNLEASHED_RECOMP_THIRDPARTY_INCLUDES}
)
if (CMAKE_SYSTEM_NAME MATCHES "Linux")
if(CMAKE_SYSTEM_NAME MATCHES "Linux")
find_package(X11 REQUIRED)
target_include_directories(UnleashedRecomp PRIVATE ${X11_INCLUDE_DIR})
target_link_libraries(UnleashedRecomp PRIVATE ${X11_LIBRARIES})
@ -417,23 +530,65 @@ endif()
target_precompile_headers(UnleashedRecomp PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS})
if(TARGET UnleashedRecompIOSLauncher)
target_link_libraries(UnleashedRecompIOSLauncher PRIVATE ${UNLEASHED_RECOMP_LINK_LIBS})
target_include_directories(UnleashedRecompIOSLauncher PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}
"${CMAKE_CURRENT_SOURCE_DIR}/api"
${UNLEASHED_RECOMP_THIRDPARTY_INCLUDES}
)
target_precompile_headers(UnleashedRecompIOSLauncher PUBLIC ${UNLEASHED_RECOMP_PRECOMPILED_HEADERS})
endif()
# If DXC tool not provided, try to pick up vendored host DXC (used for shader compilation)
if(NOT DEFINED DIRECTX_DXC_TOOL)
set(_dxc_vendor_dir "${CMAKE_SOURCE_DIR}/tools/XenosRecomp/thirdparty/dxc-bin")
if(EXISTS "${_dxc_vendor_dir}")
if(DEFINED CMAKE_HOST_SYSTEM_PROCESSOR)
set(_dxc_arch ${CMAKE_HOST_SYSTEM_PROCESSOR})
elseif(DEFINED CMAKE_SYSTEM_PROCESSOR)
set(_dxc_arch ${CMAKE_SYSTEM_PROCESSOR})
else()
set(_dxc_arch "x64")
endif()
string(TOLOWER "${_dxc_arch}" _dxc_arch)
set(_dxc_bin "${_dxc_vendor_dir}/bin/${_dxc_arch}/dxc-macos")
set(_dxc_libdir "${_dxc_vendor_dir}/lib/${_dxc_arch}")
if(EXISTS "${_dxc_bin}")
set(DIRECTX_DXC_TOOL "DYLD_LIBRARY_PATH=${_dxc_libdir}" "${_dxc_bin}" CACHE INTERNAL "Location of the dxc tool for shader compilation")
message(STATUS "Using vendored DXC: ${_dxc_bin}")
endif()
endif()
endif()
function(compile_shader FILE_PATH TARGET_NAME)
set(FILE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/gpu/shader/${FILE_PATH}.hlsl)
cmake_path(GET FILE_PATH STEM VARIABLE_NAME)
if (UNLEASHED_RECOMP_D3D12)
set(_shader_target UnleashedRecomp)
if(CMAKE_SYSTEM_NAME STREQUAL "iOS" AND TARGET UnleashedRecompIOSLauncher)
set(_shader_target UnleashedRecompIOSLauncher)
endif()
if(UNLEASHED_RECOMP_D3D12)
add_custom_command(
OUTPUT ${FILE_PATH}.dxil.h
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -Wno-ignored-attributes -Fh ${FILE_PATH}.dxil.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_dxil
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.dxil.h)
target_sources(${_shader_target} PRIVATE ${FILE_PATH}.dxil.h)
endif()
add_custom_command(
OUTPUT ${FILE_PATH}.spirv.h
COMMAND ${DIRECTX_DXC_TOOL} -T ${TARGET_NAME} -HV 2021 -all-resources-bound -spirv -fvk-use-dx-layout ${ARGN} -Fh ${FILE_PATH}.spirv.h ${FILE_PATH} -Vn g_${VARIABLE_NAME}_spirv
DEPENDS ${FILE_PATH}
)
target_sources(UnleashedRecomp PRIVATE ${FILE_PATH}.spirv.h)
target_sources(${_shader_target} PRIVATE ${FILE_PATH}.spirv.h)
endfunction()
function(compile_vertex_shader FILE_PATH)
@ -471,7 +626,7 @@ compile_pixel_shader(resolve_msaa_depth_8x)
set(RESOURCES_SOURCE_PATH "${PROJECT_SOURCE_DIR}/../UnleashedRecompResources")
set(RESOURCES_OUTPUT_PATH "${PROJECT_SOURCE_DIR}/res")
## Miscellaneous ##
# # Miscellaneous ##
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/bc_diff/button_bc_diff.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/bc_diff/button_bc_diff.bin" ARRAY_NAME "g_button_bc_diff" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.bin" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.bin" ARRAY_NAME "g_im_font_atlas" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/font/im_font_atlas.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/font/im_font_atlas.dds" ARRAY_NAME "g_im_font_atlas_texture" COMPRESSION_TYPE "zstd")
@ -483,7 +638,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/co
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/select.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/select.dds" ARRAY_NAME "g_select" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/common/light.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/common/light.dds" ARRAY_NAME "g_light" COMPRESSION_TYPE "zstd")
## Installer ##
# # Installer ##
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/arrow_circle.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/arrow_circle.dds" ARRAY_NAME "g_arrow_circle" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_001.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_001.dds" ARRAY_NAME "g_install_001" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/install_002.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/install_002.dds" ARRAY_NAME "g_install_002" COMPRESSION_TYPE "zstd")
@ -496,7 +651,7 @@ BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/in
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/miles_electric_icon.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/miles_electric_icon.dds" ARRAY_NAME "g_miles_electric_icon" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/installer/pulse_install.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/installer/pulse_install.dds" ARRAY_NAME "g_pulse_install" COMPRESSION_TYPE "zstd")
## Options Menu ##
# # Options Menu ##
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/achievement_notifications.dds" ARRAY_NAME "g_achievement_notifications" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_ps.dds" ARRAY_NAME "g_allow_background_input_ps" COMPRESSION_TYPE "zstd")
BIN2C(TARGET_OBJ UnleashedRecomp SOURCE_FILE "${RESOURCES_SOURCE_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" DEST_FILE "${RESOURCES_OUTPUT_PATH}/images/options_menu/thumbnails/allow_background_input_xb.dds" ARRAY_NAME "g_allow_background_input_xb" COMPRESSION_TYPE "zstd")

View file

@ -0,0 +1,27 @@
#pragma once
#include <filesystem>
namespace apple {
/// Get the user data directory (Documents folder on iOS, ~/Documents on macOS)
/// Returns absolute path suitable for user-editable files like saves and mods
std::filesystem::path GetUserDataDirectory();
/// Get the application support directory (Library/Application Support)
/// Returns absolute path suitable for app configuration and preferences
std::filesystem::path GetApplicationSupportDirectory();
/// Get the caches directory (Library/Caches)
/// Returns absolute path suitable for temporary/cached data
std::filesystem::path GetCachesDirectory();
/// Open a URL in the system browser
/// Returns true if the URL was opened successfully, false otherwise
bool OpenBrowser(const char* url);
/// Check if the current Apple device supports BC texture formats
/// (Apple 9 family and later, select Apple 7/8 family on iPadOS 16.4+)
bool SupportsBCTextures();
} // namespace cocoa

View file

@ -0,0 +1,127 @@
#import <Foundation/Foundation.h>
#import <Metal/Metal.h>
#import <TargetConditionals.h>
#if TARGET_OS_OSX
#import <AppKit/AppKit.h>
#else
#import <UIKit/UIKit.h>
#endif
#include "apple_utils.h"
namespace apple {
std::filesystem::path GetUserDataDirectory() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES);
if ([paths count] > 0) {
NSString *documentsPath = [paths objectAtIndex:0];
return std::filesystem::path([documentsPath UTF8String]);
}
const char *homeDir = getenv("HOME");
if (homeDir != nullptr) {
return std::filesystem::path(homeDir) / "Documents";
}
return std::filesystem::path();
}
std::filesystem::path GetApplicationSupportDirectory() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSApplicationSupportDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) {
NSString *appSupportPath = [paths objectAtIndex:0];
// Ensure application support directory exists as it is not guaranteed to be
// created by the system
NSFileManager *fileManager = [NSFileManager defaultManager];
if (![fileManager fileExistsAtPath:appSupportPath]) {
NSError *error = nil;
[fileManager createDirectoryAtPath:appSupportPath
withIntermediateDirectories:YES
attributes:nil
error:&error];
if (error) {
NSLog(@"Failed to create Application Support directory: %@", error);
return std::filesystem::path();
}
}
return std::filesystem::path([appSupportPath UTF8String]);
}
const char *homeDir = getenv("HOME");
if (homeDir != nullptr) {
return std::filesystem::path(homeDir) / "Library" / "Application Support";
}
return std::filesystem::path();
}
std::filesystem::path GetCachesDirectory() {
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES);
if ([paths count] > 0) {
NSString *cachesPath = [paths objectAtIndex:0];
return std::filesystem::path([cachesPath UTF8String]);
}
const char *homeDir = getenv("HOME");
if (homeDir != nullptr) {
return std::filesystem::path(homeDir) / "Library" / "Caches";
}
return std::filesystem::path();
}
bool OpenBrowser(const char *url) {
@try {
NSString *nsUrl = [NSString stringWithUTF8String:url];
NSURL *nsUrlObj = [NSURL URLWithString:nsUrl];
if (nsUrlObj == nil) {
return false;
}
#if TARGET_OS_OSX
return [[NSWorkspace sharedWorkspace] openURL:nsUrlObj];
#else
if (@available(iOS 13.0, *)) {
__block bool success = false;
[[UIApplication sharedApplication] openURL:nsUrlObj
options:@{}
completionHandler:^(BOOL succeeded) {
success = succeeded;
}];
return success;
} else {
// Fallback for older iOS versions
return [[UIApplication sharedApplication] openURL:nsUrlObj];
}
#endif
} @catch (NSException *exception) {
return false;
}
}
bool SupportsBCTextures() {
static bool cachedResult = false;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
@try {
id<MTLDevice> device = MTLCreateSystemDefaultDevice();
if (device == nil) {
return;
}
if (@available(iOS 16.4, macOS 13.3, *)) {
cachedResult = [device supportsBCTextureCompression];
}
} @catch (NSException *exception) {
}
});
return cachedResult;
}
} // namespace apple

View file

@ -2769,6 +2769,13 @@ static void ProcDrawImGui(const RenderCommand& cmd)
// 4. Loading thread presents and quits.
// 5. After the loading thread quits, application also presents.
static bool g_pendingWaitOnSwapChain = true;
void Video::HandleApplicationBackgroundState(bool isBackgrounded)
{
if (isBackgrounded)
{
g_pendingWaitOnSwapChain = false;
}
}
void Video::WaitOnSwapChain()
{

View file

@ -20,6 +20,7 @@ struct Video
static bool CreateHostDevice(const char *sdlVideoDriver, bool graphicsApiRetry);
static void WaitOnSwapChain();
static void HandleApplicationBackgroundState(bool isBackgrounded);
static void Present();
static void StartPipelinePrecompilation();
static void WaitForGPU();

View file

@ -9,6 +9,10 @@
#include <shellapi.h>
#endif
#if defined(__APPLE__)
#include "../apple_utils.h"
#endif
#include <os/logger.h>
// UpdateChecker
@ -167,8 +171,7 @@ void UpdateChecker::visitWebsite()
std::string command = "xdg-open " + std::string(VISIT_URL) + " &";
std::system(command.c_str());
#elif defined(__APPLE__)
std::string command = "open " + std::string(VISIT_URL) + " &";
std::system(command.c_str());
apple::OpenBrowser(VISIT_URL);
#else
static_assert(false, "Visit website not implemented for this platform.");
#endif

View file

@ -0,0 +1,51 @@
#include <SDL.h>
#include <SDL_main.h>
int UnleashedMain(int argc, char *argv[]);
int HandleAppEvents(void *userdata, SDL_Event *event)
{
switch (event->type)
{
case SDL_APP_TERMINATING:
/* Terminate the app.
Shut everything down before returning from this function.
*/
return 0;
case SDL_APP_LOWMEMORY:
/* You will get this when your app is paused and iOS wants more memory.
Release as much memory as possible.
*/
return 0;
case SDL_APP_WILLENTERBACKGROUND:
/* Prepare your app to go into the background. Stop loops, etc.
This gets called when the user hits the home button, or gets a call.
*/
return 0;
case SDL_APP_DIDENTERBACKGROUND:
/* This will get called if the user accepted whatever sent your app to the background.
If the user got a phone call and canceled it, you'll instead get an SDL_APP_DIDENTERFOREGROUND event and restart your loops.
When you get this, you have 5 seconds to save all your state or the app will be terminated.
Your app is NOT active at this point.
*/
return 0;
case SDL_APP_WILLENTERFOREGROUND:
/* This call happens when your app is coming back to the foreground.
Restore all your state here.
*/
return 0;
case SDL_APP_DIDENTERFOREGROUND:
/* Restart your loops here.
Your app is interactive and getting CPU again.
*/
return 0;
default:
/* No special processing, add it to the event queue */
return 1;
}
}
int main(int argc, char *argv[]) {
SDL_SetEventFilter(HandleAppEvents, NULL);
return SDL_UIKitRunApp(argc, argv, UnleashedMain);
}

View file

@ -1,3 +1,4 @@
#include <atomic>
#include <stdafx.h>
#include <cpu/ppc_context.h>
#include <cpu/guest_thread.h>
@ -10,6 +11,7 @@
#include <memory>
#include "xam.h"
#include "xdm.h"
#include <thread>
#include <user/config.h>
#include <os/logger.h>
@ -678,13 +680,16 @@ uint32_t KeSetAffinityThread(uint32_t Thread, uint32_t Affinity, be<uint32_t>* l
void RtlLeaveCriticalSection(XRTL_CRITICAL_SECTION* cs)
{
uint32_t thisThread = g_ppcContext->r13.u32;
assert(thisThread != NULL);
std::atomic_ref owningThread(cs->OwningThread);
cs->RecursionCount--;
if (cs->RecursionCount != 0)
return;
std::atomic_ref owningThread(cs->OwningThread);
owningThread.store(0);
owningThread.store(0, std::memory_order_release);
owningThread.notify_one();
}
@ -694,18 +699,27 @@ void RtlEnterCriticalSection(XRTL_CRITICAL_SECTION* cs)
assert(thisThread != NULL);
std::atomic_ref owningThread(cs->OwningThread);
while (true)
uint32_t currentOwner = owningThread.load(std::memory_order_acquire);
while (true)
{
uint32_t previousOwner = 0;
if (owningThread.compare_exchange_weak(previousOwner, thisThread) || previousOwner == thisThread)
if (currentOwner == thisThread)
{
cs->RecursionCount++;
return;
}
owningThread.wait(previousOwner);
if (currentOwner == 0)
{
if (owningThread.compare_exchange_weak(currentOwner, thisThread, std::memory_order_acquire, std::memory_order_relaxed))
{
cs->RecursionCount = 1;
return;
}
continue;
}
owningThread.wait(currentOwner, std::memory_order_relaxed);
currentOwner = owningThread.load(std::memory_order_acquire);
}
}
@ -1594,7 +1608,7 @@ void XMACreateContext()
// uint32_t XAudioRegisterRenderDriverClient(be<uint32_t>* callback, be<uint32_t>* driver)
// {
// //printf("XAudioRegisterRenderDriverClient(): %x %x\n");
//
//
// *driver = apu::RegisterClient(callback[0], callback[1]);
// return 0;
// }
@ -1608,7 +1622,7 @@ void XMACreateContext()
// {
// // printf("!!! STUB !!! XAudioSubmitRenderDriverFrame\n");
// apu::SubmitFrames(samples);
//
//
// return 0;
// }

View file

@ -714,6 +714,18 @@ std::unordered_map<std::string_view, std::unordered_map<ELanguage, std::string>>
{ ELanguage::Italian, "Impossibile allocare la memoria per il gioco.\n\nAssicurati che:\n\n- Soddisfi i requisiti minimi di sistema (8 GB).\n- Il tuo file di paging sia configurato con almeno 4 o 8 GB di memoria virtuale." }
}
},
{
"System_iOS_UnsupportedGPU_BCTextures",
{
// TODO: Localize the GPU requirements for iOS devices.
{ ELanguage::English, "Your device's GPU is not supported.\n\nUnleashed Recompiled requires an iOS device with hardware support for BC texture compression.\n\nMinimum requirement:\n- Apple A17 Pro chip or newer\n- Apple A18 / A18 Pro chip or newer\n- Apple M-series chips (M1, M2, M3, M4 or newer)\n\nSupported devices include:\n- iPhone 15 Pro / 15 Pro Max and newer\n- iPhone 16 / 16 Plus / 16 Pro / 16 Pro Max and newer\n- iPhone 16e and newer\n- iPad mini (A17 Pro) and newer\n- iPad Pro models with M-series chips (M1 / 11-inch 3rd gen / 12.9-inch 5th gen or newer)\n- iPad Air models with M-series chips (M1 / 5th gen or newer)\n\nUnsupported devices include:\n- All iPhones with A16 Bionic chip or earlier (iPhone 15, iPhone 14 Pro, and older)\n- iPads with A-series chips (iPad 10th gen, iPad Air 4th gen, older iPad Pros)\n\nWe aim to support more devices in the future." },
// { ELanguage::Japanese, ""},
{ ELanguage::German, "Deine Geräte-GPU wird nicht unterstützt.\n\nUnleashed Recompiled benötigt ein iOS-Gerät mit Hardware-Unterstützung für BC-Texturen.\n\nMindestanforderungen:\n- Apple A17 Pro-Chip oder neuer\n- Apple A18 / A18 Pro-Chip oder neuer\n- Apple M-Series-Chips (M1, M2, M3, M4 oder neuer)\n\nUnterstützte Geräte:\n- iPhone 15 Pro / 15 Pro Max und neuer\n- iPhone 16 / 16 Plus / 16 Pro / 16 Pro Max und neuer\n- iPhone 16e und neuer\n- iPad mini (A17 Pro) und neuer\n- iPad Pro-Modelle mit M-Series-Chips (M1 / 11\" 3. Gen / 12,9\" 5. Gen oder neuer)\n- iPad Air-Modelle mit M-Series-Chips (M1 / 5. Gen oder neuer)\n\nNicht unterstützte Geräte:\n- Alle iPhones mit A16 Bionic-Chip oder früher (iPhone 15, iPhone 14 Pro und älter)\n- iPads mit A-Series-Chips (iPad 10. Gen, iPad Air 4. Gen, ältere iPad Pros)\n\nWir bemühen uns, in Zukunft mehr Geräte zu unterstützen." },
// { ELanguage::French, "" },
{ ELanguage::Spanish, "La GPU en tu dispositivo no es compatible.\n\nUnleashed Recompiled requiere un dispositivo iOS con soporte hardware para texturas BC.\n\nRequisitos mínimos:\n- Chip Apple A17 Pro o superior\n- Chip Apple A18 / A18 Pro o superior\n- Chips Apple M-series (M1, M2, M3, M4 o más recientes)\n\nDispositivos compatibles incluyen:\n- iPhone 15 Pro / 15 Pro Max y más recientes\n- iPhone 16 / 16 Plus / 16 Pro / 16 Pro Max y más recientes\n- iPhone 16e y más recientes\n- iPad mini (A17 Pro) y más recientes\n- Modelos de iPad Pro con chips M-series (M1 / 11 pulgadas 3.ª gen / 12.9 pulgadas 5.ª gen o más recientes)\n- Modelos de iPad Air con chips M-series (M1 / 5.ª gen o más recientes)\n\nDispositivos no compatibles incluyen:\n- Todos los iPhones con chip A16 Bionic o anterior (iPhone 15, iPhone 14 Pro y anteriores)\n- iPads con chips de la serie A (iPad 10.ª gen, iPad Air 4.ª gen, iPad Pro más antiguos)\n\nEsperamos admitir más dispositivos en el futuro." },
// { ELanguage::Italian, "" }
}
},
{
"IntegrityCheck_Success",
{
@ -856,7 +868,7 @@ std::unordered_map<std::string_view, std::unordered_map<ELanguage, std::string>>
{ ELanguage::Spanish, "Cambiar" },
{ ELanguage::Italian, "Cambia" }
}
}
},
};
std::string& Localise(const std::string_view& key)

View file

@ -32,6 +32,10 @@
#include <timeapi.h>
#endif
#ifdef __APPLE__
#include "apple_utils.h"
#endif
#if defined(_WIN32) && defined(UNLEASHED_RECOMP_D3D12)
static std::array<std::string_view, 3> g_D3D12RequiredModules =
{
@ -192,7 +196,11 @@ void init()
}
#endif
#if defined(UNLEASHED_RECOMP_IOS_LAUNCHER)
int UnleashedMain(int argc, char *argv[])
#else
int main(int argc, char *argv[])
#endif
{
#ifdef _WIN32
timeBeginPeriod(1);
@ -205,6 +213,13 @@ int main(int argc, char *argv[])
os::logger::Init();
#if TARGET_OS_IOS
if (!apple::SupportsBCTextures()) {
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, GameWindow::GetTitle(), Localise("System_iOS_UnsupportedGPU_BCTextures").c_str(), GameWindow::s_pWindow);
std::_Exit(1);
}
#endif
PreloadContext preloadContext;
preloadContext.PreloadExecutable();
@ -234,9 +249,12 @@ int main(int argc, char *argv[])
if (!useDefaultWorkingDirectory)
{
#if !defined(TARGET_OS_IPHONE)
// Set the current working directory to the executable's path.
// iOS: CWD is not meaningful in app sandbox; paths must be absolute.
std::error_code ec;
std::filesystem::current_path(os::process::GetExecutableRoot(), ec);
#endif
}
Config::Load();

View file

@ -1,17 +1,30 @@
#include <os/logger.h>
#if TARGET_OS_IPHONE
#include <os/log.h>
#endif
void os::logger::Init()
{
}
void os::logger::Log(const std::string_view str, ELogType type, const char* func)
{
if (func)
{
fmt::println("[{}] {}", func, str);
}
else
{
fmt::println("{}", str);
}
#if TARGET_OS_IPHONE
if (func)
{
os_log(OS_LOG_DEFAULT, "%{public}s: %{public}s", func, str.data());
}
else
{
os_log(OS_LOG_DEFAULT, "%{public}s", str.data());
}
#else
if (func)
{
fmt::println("[{}] {}", func, str);
}
else
{
fmt::println("{}", str);
}
#endif
}

View file

@ -41,6 +41,7 @@ std::filesystem::path os::process::GetExecutableRoot()
std::filesystem::path os::process::GetWorkingDirectory()
{
#if !TARGET_OS_IPHONE
char cwd[PATH_MAX] = {};
char *res = getcwd(cwd, sizeof(cwd));
if (res != nullptr)
@ -51,15 +52,26 @@ std::filesystem::path os::process::GetWorkingDirectory()
{
return std::filesystem::path();
}
#else
// iOS: Working directory is not meaningful in app sandbox
// Return app bundle path as fallback
return GetExecutableRoot();
#endif
}
bool os::process::SetWorkingDirectory(const std::filesystem::path& path)
{
#if !TARGET_OS_IPHONE
return chdir(path.c_str()) == 0;
#else
// iOS: Cannot change working directory in sandbox; return false
return false;
#endif
}
bool os::process::StartProcess(const std::filesystem::path& path, const std::vector<std::string>& args, std::filesystem::path work)
{
#if !TARGET_OS_IPHONE
pid_t pid = fork();
if (pid < 0)
return false;
@ -83,6 +95,10 @@ bool os::process::StartProcess(const std::filesystem::path& path, const std::vec
}
return true;
#else
// iOS: Cannot start other processes in app sandbox
return false;
#endif
}
void os::process::CheckConsole()

View file

@ -0,0 +1,49 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>Unleashed Recompiled iOS</string>
<key>CFBundleIdentifier</key>
<string>hedge-dev.UnleashedRecomp</string>
<key>CFBundleName</key>
<string>Unleashed Recompiled</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>@IOS_BUNDLE_VERSION@</string>
<key>CFBundleVersion</key>
<string>@IOS_BUNDLE_VERSION@</string>
<key>MinimumOSVersion</key>
<string>@IOS_DEPLOYMENT_TARGET@</string>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>CFBundleDisplayName</key>
<string>Unleashed Recompiled</string>
<key>CFBundleIconName</key>
<string>AppIcon</string>
<key>UIFileSharingEnabled</key>
<true />
<key>LSSupportsOpeningDocumentsInPlace</key>
<true />
<key>NSDocumentsFolderUsageDescription</key>
<string>Allows access to game files and user-provided content.</string>
<key>UIApplicationSupportsIndirectInputEvents</key>
<true />
<key>LSSupportsGameMode</key>
<true />
<key>LSApplicationCategoryType</key>
<string>public.app-category.action-games</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

View file

@ -33,6 +33,16 @@ int Window_OnSDLEvent(void*, SDL_Event* event)
switch (event->type)
{
case SDL_APP_WILLENTERBACKGROUND:
case SDL_APP_DIDENTERBACKGROUND:
Video::HandleApplicationBackgroundState(true);
break;
case SDL_APP_WILLENTERFOREGROUND:
case SDL_APP_DIDENTERFOREGROUND:
Video::HandleApplicationBackgroundState(false);
break;
case SDL_QUIT:
{
if (App::s_isSaving)
@ -218,7 +228,11 @@ void GameWindow::Init(const char* sdlVideoDriver)
#elif defined(__linux__)
s_renderWindow = { info.info.x11.display, info.info.x11.window };
#elif defined(__APPLE__)
#if defined(SDL_VIDEO_DRIVER_UIKIT)
s_renderWindow.window = info.info.uikit.window;
#else
s_renderWindow.window = info.info.cocoa.window;
#endif
s_renderWindow.view = SDL_Metal_GetLayer(SDL_Metal_CreateView(s_pWindow));
#else
static_assert(false, "Unknown platform.");
@ -346,7 +360,7 @@ bool GameWindow::SetFullscreen(bool isEnabled)
return isEnabled;
}
void GameWindow::SetFullscreenCursorVisibility(bool isVisible)
{
s_isFullscreenCursorVisible = isVisible;

View file

@ -1,5 +1,8 @@
#include "paths.h"
#include <os/process.h>
#ifdef TARGET_OS_IPHONE
#include "../apple_utils.h"
#endif
std::filesystem::path g_executableRoot = os::process::GetExecutableRoot();
std::filesystem::path g_userPath = BuildUserPath();
@ -22,6 +25,8 @@ std::filesystem::path BuildUserPath()
userPath = std::filesystem::path{ knownPath } / USER_DIRECTORY;
CoTaskMemFree(knownPath);
#elif TARGET_OS_IPHONE
userPath = apple::GetUserDataDirectory();
#elif defined(__linux__) || defined(__APPLE__)
const char* homeDir = getenv("HOME");
#if defined(__linux__)

View file

@ -4,17 +4,17 @@ add_compile_options(
-fno-strict-aliasing
)
if (WIN32)
if(WIN32)
add_compile_options(/fp:strict)
else()
add_compile_options(-ffp-model=strict)
endif()
target_compile_definitions(XenonRecomp PRIVATE
target_compile_definitions(XenonRecomp PRIVATE
XENON_RECOMP_CONFIG_FILE_PATH=\"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml\"
XENON_RECOMP_HEADER_FILE_PATH=\"${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils/ppc_context.h\")
set(UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES
set(UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES
"${CMAKE_CURRENT_SOURCE_DIR}/ppc/ppc_config.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ppc/ppc_context.h"
"${CMAKE_CURRENT_SOURCE_DIR}/ppc/ppc_func_mapping.cpp"
@ -25,57 +25,146 @@ foreach(i RANGE 0 260)
list(APPEND UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/ppc/ppc_recomp.${i}.cpp")
endforeach()
add_custom_command(
OUTPUT
if(NOT CMAKE_CROSSCOMPILING)
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
${UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES}
COMMAND
COMMAND
$<TARGET_FILE:XenonRecomp>
DEPENDS
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex"
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xexp"
"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml"
USES_TERMINAL
)
USES_TERMINAL
)
add_custom_command(
OUTPUT
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
COMMAND
COMMAND
$<TARGET_FILE:x_decompress> "${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
DEPENDS
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar"
)
)
set(XENOS_RECOMP_ROOT "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/XenosRecomp")
set(XENOS_RECOMP_INCLUDE "${XENOS_RECOMP_ROOT}/shader_common.h")
set(XENOS_RECOMP_ROOT "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/XenosRecomp")
set(XENOS_RECOMP_INCLUDE "${XENOS_RECOMP_ROOT}/shader_common.h")
target_compile_definitions(XenosRecomp PRIVATE
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\"
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
UNLEASHED_RECOMP
)
target_compile_definitions(XenosRecomp PRIVATE
XENOS_RECOMP_INPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/private\"
XENOS_RECOMP_OUTPUT=\"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp\"
XENOS_RECOMP_INCLUDE_INPUT=\"${XENOS_RECOMP_INCLUDE}\"
UNLEASHED_RECOMP
)
file(GLOB XENOS_RECOMP_SOURCES
"${XENOS_RECOMP_ROOT}/*.h"
"${XENOS_RECOMP_ROOT}/*.cpp"
)
file(GLOB XENOS_RECOMP_SOURCES
"${XENOS_RECOMP_ROOT}/*.h"
"${XENOS_RECOMP_ROOT}/*.cpp"
)
add_custom_command(
OUTPUT
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp"
COMMAND
COMMAND
$<TARGET_FILE:XenosRecomp>
DEPENDS
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
${XENOS_RECOMP_SOURCES}
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
${XENOS_RECOMP_SOURCES}
${XENOS_RECOMP_INCLUDE}
USES_TERMINAL
)
USES_TERMINAL
)
else()
message(STATUS "Cross-compiling: building host tools for code generation")
add_library(UnleashedRecompLib
# Build host-native tools out-of-tree
set(HOST_XENONRECOMP_BUILD_DIR "${CMAKE_BINARY_DIR}/host-tools/XenonRecomp")
set(HOST_X_DECOMPRESS_BUILD_DIR "${CMAKE_BINARY_DIR}/host-tools/x_decompress")
set(HOST_XENOSRECOMP_BUILD_DIR "${CMAKE_BINARY_DIR}/host-tools/XenosRecomp")
set(HOST_VCPKG_TRIPLET "${CMAKE_HOST_SYSTEM_PROCESSOR}-osx")
set(HOST_XENONRECOMP_BIN "${HOST_XENONRECOMP_BUILD_DIR}/XenonRecomp/XenonRecomp")
set(HOST_X_DECOMPRESS_BIN "${HOST_X_DECOMPRESS_BUILD_DIR}/x_decompress")
set(HOST_XENOSRECOMP_BIN "${HOST_XENOSRECOMP_BUILD_DIR}/XenosRecomp/XenosRecomp")
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
${UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES}
COMMAND
${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/tools/XenonRecomp" -B "${HOST_XENONRECOMP_BUILD_DIR}"
-G "${CMAKE_GENERATOR}"
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/host-tools/install
COMMAND
${CMAKE_COMMAND} --build "${HOST_XENONRECOMP_BUILD_DIR}" --config ${CMAKE_BUILD_TYPE}
COMMAND
"${HOST_XENONRECOMP_BIN}" "${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml" "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp/XenonUtils/ppc_context.h"
WORKING_DIRECTORY
"${CMAKE_CURRENT_SOURCE_DIR}"
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xex"
"${CMAKE_CURRENT_SOURCE_DIR}/private/default.xexp"
"${CMAKE_CURRENT_SOURCE_DIR}/config/SWA.toml"
COMMENT "Building host XenonRecomp and generating patched XEX + sources"
USES_TERMINAL
)
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
COMMAND
${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/tools/x_decompress" -B "${HOST_X_DECOMPRESS_BUILD_DIR}"
-G "${CMAKE_GENERATOR}"
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DUNLEASHED_RECOMP_TOOLS_ROOT=${UNLEASHED_RECOMP_TOOLS_ROOT}
COMMAND
${CMAKE_COMMAND} --build "${HOST_X_DECOMPRESS_BUILD_DIR}" --config ${CMAKE_BUILD_TYPE}
COMMAND
"${HOST_X_DECOMPRESS_BIN}" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar" "${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader.ar"
COMMENT "Building host x_decompress and decompressing shader archive"
USES_TERMINAL
)
set(XENOS_RECOMP_ROOT "${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp/XenosRecomp")
set(XENOS_RECOMP_INCLUDE "${XENOS_RECOMP_ROOT}/shader_common.h")
file(GLOB XENOS_RECOMP_SOURCES
"${XENOS_RECOMP_ROOT}/*.h"
"${XENOS_RECOMP_ROOT}/*.cpp"
)
add_custom_command(
OUTPUT
"${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp"
COMMAND
${CMAKE_COMMAND} -S "${CMAKE_SOURCE_DIR}/tools/XenosRecomp" -B "${HOST_XENOSRECOMP_BUILD_DIR}"
-G "${CMAKE_GENERATOR}"
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/host-tools/install
COMMAND
${CMAKE_COMMAND} --build "${HOST_XENOSRECOMP_BUILD_DIR}" --config ${CMAKE_BUILD_TYPE}
COMMAND
"${HOST_XENOSRECOMP_BIN}" "${CMAKE_CURRENT_SOURCE_DIR}/private" "${CMAKE_CURRENT_SOURCE_DIR}/shader/shader_cache.cpp" "${XENOS_RECOMP_INCLUDE}"
DEPENDS
"${CMAKE_CURRENT_SOURCE_DIR}/private/default_patched.xex"
"${CMAKE_CURRENT_SOURCE_DIR}/private/shader_decompressed.ar"
${XENOS_RECOMP_SOURCES}
${XENOS_RECOMP_INCLUDE}
COMMENT "Building host XenosRecomp and generating shader cache"
USES_TERMINAL
)
endif()
add_library(UnleashedRecompLib
${UNLEASHED_RECOMP_PPC_RECOMPILED_SOURCES}
"shader/shader_cache.h"
"shader/shader_cache.cpp"

View file

@ -2,13 +2,15 @@
# Prepare MoltenVK Git revision
find_package(Git)
if(GIT_FOUND)
execute_process(COMMAND ${GIT_EXECUTABLE} rev-parse --short HEAD
OUTPUT_VARIABLE MVK_GIT_REV
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
OUTPUT_VARIABLE MVK_GIT_REV
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/MoltenVK
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
set(MVK_GENERATED_INCLUDES ${CMAKE_CURRENT_BINARY_DIR}/Generated)
file(WRITE ${MVK_GENERATED_INCLUDES}/mvkGitRevDerived.h "static const char* mvkRevString = \"${MVK_GIT_REV}\";")
message(STATUS "MoltenVK revision: ${MVK_GIT_REV}")
@ -25,9 +27,15 @@ set(MVK_VERSION "${MVK_VERSION_MAJOR}.${MVK_VERSION_MINOR}.${MVK_VERSION_PATCH}"
message(STATUS "MoltenVK version: ${MVK_VERSION}")
# Find required system libraries
find_library(APPKIT_LIBRARY AppKit REQUIRED)
if(IOS)
find_library(UIKIT_LIBRARY UIKit REQUIRED)
find_library(COREGRAPHICS_LIBRARY CoreGraphics REQUIRED)
else()
find_library(APPKIT_LIBRARY AppKit REQUIRED)
find_library(IOKIT_LIBRARY IOKit REQUIRED)
endif()
find_library(FOUNDATION_LIBRARY Foundation REQUIRED)
find_library(IOKIT_LIBRARY IOKit REQUIRED)
find_library(IOSURFACE_LIBRARY IOSurface REQUIRED)
find_library(METAL_LIBRARY Metal REQUIRED)
find_library(QUARTZCORE_LIBRARY QuartzCore REQUIRED)
@ -81,6 +89,53 @@ add_library(MoltenVK SHARED ${MVK_SOURCES})
target_include_directories(MoltenVK PRIVATE ${MVK_INCLUDES})
target_compile_options(MoltenVK PRIVATE -w)
target_link_libraries(MoltenVK PRIVATE
${APPKIT_LIBRARY} ${FOUNDATION_LIBRARY} ${IOKIT_LIBRARY} ${IOSURFACE_LIBRARY} ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY}
${FOUNDATION_LIBRARY} ${IOSURFACE_LIBRARY} ${METAL_LIBRARY} ${QUARTZCORE_LIBRARY}
spirv-cross-msl MoltenVKCommon MoltenVKShaderConverter)
target_compile_definitions(MoltenVK PRIVATE MVK_FRAMEWORK_VERSION=${MVK_VERSION} MVK_USE_CEREAL=0)
if(IOS)
target_link_libraries(MoltenVK PRIVATE ${UIKIT_LIBRARY} ${COREGRAPHICS_LIBRARY})
else()
target_link_libraries(MoltenVK PRIVATE ${APPKIT_LIBRARY} ${IOKIT_LIBRARY})
endif()
target_compile_definitions(MoltenVK PRIVATE
MVK_FRAMEWORK_VERSION=${MVK_VERSION}
MVK_USE_CEREAL=0
VK_USE_PLATFORM_METAL_EXT=1)
set_source_files_properties(
${MVK_SOURCES}
PROPERTIES
COMPILE_FLAGS "-fno-objc-arc"
)
set_target_properties(MoltenVK PROPERTIES
FRAMEWORK TRUE
FRAMEWORK_VERSION A
MACOSX_FRAMEWORK_IDENTIFIER org.moltenvk.MoltenVK
MACOSX_FRAMEWORK_BUNDLE_VERSION ${MVK_VERSION}
MACOSX_FRAMEWORK_SHORT_VERSION_STRING ${MVK_VERSION}
PUBLIC_HEADER "${MVK_PUBLIC_HEADERS}"
POSITION_INDEPENDENT_CODE ON
XCODE_ATTRIBUTE_DEFINES_MODULE YES
XCODE_ATTRIBUTE_DYLIB_INSTALL_NAME_BASE "@rpath"
BUILD_WITH_INSTALL_RPATH YES
INSTALL_RPATH "@executable_path/Frameworks;@loader_path/Frameworks"
)
if(IOS)
set_target_properties(MoltenVK PROPERTIES
XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH YES
XCODE_ATTRIBUTE_ENABLE_BITCODE NO
XCODE_ATTRIBUTE_SKIP_INSTALL NO
XCODE_ATTRIBUTE_IPHONEOS_DEPLOYMENT_TARGET
"${CMAKE_OSX_DEPLOYMENT_TARGET}"
)
endif()

2
thirdparty/plume vendored

@ -1 +1 @@
Subproject commit 11926860e878e68626ea99ec88562ce2b8badc4f
Subproject commit e213c40fa4a9c01ed4fdb1aa683ce1e78d15d970

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,9 @@
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/bc_diff)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/file_to_c)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/fshasher)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/x_decompress)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenonRecomp)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp)
if(NOT CMAKE_CROSSCOMPILING)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/file_to_c)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/x_decompress)
add_subdirectory(${UNLEASHED_RECOMP_TOOLS_ROOT}/XenosRecomp)
endif()

View file

@ -7,4 +7,18 @@ set(CMAKE_CXX_STANDARD 17)
add_executable(file_to_c "file_to_c.cpp")
target_link_libraries(file_to_c PRIVATE $<IF:$<TARGET_EXISTS:libzstd_static>,libzstd_static,libzstd_shared>)
find_package(ZSTD)
if(TARGET ZSTD::ZSTD)
target_link_libraries(file_to_c PRIVATE ZSTD::ZSTD)
else()
find_path(ZSTD_INCLUDE_DIR zstd.h)
find_library(ZSTD_LIBRARY NAMES zstd libzstd libzstd_static)
if(ZSTD_INCLUDE_DIR AND ZSTD_LIBRARY)
target_include_directories(file_to_c PRIVATE ${ZSTD_INCLUDE_DIR})
target_link_libraries(file_to_c PRIVATE ${ZSTD_LIBRARY})
else()
message(FATAL_ERROR "zstd library not found. Install zstd (e.g. via vcpkg) or ensure zstd.h and libzstd are on the include/library path.")
endif()
endif()

View file

@ -1,3 +1,4 @@
cmake_minimum_required(VERSION 3.20)
project("x_decompress")
set(CMAKE_CXX_STANDARD 17)

View file

@ -10,7 +10,8 @@
"platform": "windows"
},
"freetype",
"curl"
"curl",
"zstd"
],
"vcpkg-configuration": {
"overlay-triplets": [