Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
c7fe1c1
Add initial iOS port scaffolding
May 16, 2026
4f9e6cf
Make iOS packaging reproducible
May 18, 2026
ed6cd3c
Complete iOS IPA packaging flow
aperezro Jun 5, 2026
cd6e635
Add iOS bundle metadata
aperezro Jun 5, 2026
d7fb762
Use SDL iOS entry point
aperezro Jun 5, 2026
a2f0079
Add iOS app icons
aperezro Jun 5, 2026
7996b86
Port installer flow to iOS runtime
aperezro Jun 5, 2026
ecf0763
Improve iOS touch controls and IPA runtime
aperezro Jun 8, 2026
bf92b2c
Tune iOS rendering defaults
aperezro Jun 8, 2026
42ed8f1
Switch iOS renderer to Metal
aperezro Jun 8, 2026
f532a8e
Fix iOS Metal startup crash
aperezro Jun 8, 2026
e7e617c
Fix iOS Metal shader base vertex translation
aperezro Jun 8, 2026
cf8a346
Fix iOS landscape orientation
aperezro Jun 8, 2026
91f295c
Fix iOS Metal generated entry point patch
aperezro Jun 8, 2026
5a2ef3e
Fix iOS Metal shader function lookup
aperezro Jun 8, 2026
15cb87b
Fix iOS Metal vertical render orientation
aperezro Jun 8, 2026
294f633
Validate iOS installs before launch
aperezro Jun 8, 2026
f462e2f
Harden iOS install validation diagnostics
aperezro Jun 8, 2026
aa40213
Trace iOS black screen startup
aperezro Jun 9, 2026
a0d2390
Fix iOS startup event waits
aperezro Jun 9, 2026
a0b0ee8
perf: port works woth moltenvk attempting metal backend to improve pe…
aperezro Jun 9, 2026
fb31e3f
Run iOS guest off main thread
aperezro Jun 12, 2026
e73c1d3
feat: first decent running version of the ios port
aperezro Sep 21, 2026
cb4d80a
Merge branch 'hedge-dev:main' into codex/ios-port-scaffolding
aperezro Sep 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions CMakePresets.json
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,79 @@
"CMAKE_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true
}
},
{
"name": "ios-simulator-debug",
"displayName": "iOS Simulator Debug",
"generator": "Ninja",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"CMAKE_SYSTEM_NAME": "iOS",
"CMAKE_OSX_SYSROOT": "iphonesimulator",
"CMAKE_OSX_ARCHITECTURES": "arm64",
"CMAKE_BUILD_TYPE": "Debug",
"UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES": true,
"UNLEASHED_RECOMP_HOST_TOOLS_DIR": "${sourceDir}/out/build/macos-release",
"CMAKE_TOOLCHAIN_FILE": {
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake",
"type": "FILEPATH"
},
"VCPKG_TARGET_TRIPLET": {
"value": "arm64-ios-simulator",
"type": "STRING"
}
},
"environment": {
"VCPKG_ROOT": "${sourceDir}/thirdparty/vcpkg"
},
"condition": {
"type": "equals",
"lhs": "${hostSystemName}",
"rhs": "Darwin"
}
},
{
"name": "ios-device-release",
"displayName": "iOS Device Release (MoltenVK)",
"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_BUILD_TYPE": "Release",
"CMAKE_INTERPROCEDURAL_OPTIMIZATION": true,
"UNLEASHED_RECOMP_SKIP_TARGET_TOOL_EXECUTABLES": true,
"UNLEASHED_RECOMP_HOST_TOOLS_DIR": "${sourceDir}/out/build/macos-release",
"CMAKE_TOOLCHAIN_FILE": {
"value": "$env{VCPKG_ROOT}/scripts/buildsystems/vcpkg.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-native-metal-release",
"displayName": "iOS Native Metal Release",
"inherits": "ios-device-release",
"binaryDir": "${sourceDir}/out/build/${presetName}",
"installDir": "${sourceDir}/out/install/${presetName}",
"cacheVariables": {
"UNLEASHED_RECOMP_IOS_NATIVE_METAL": true
}
}
]
}
104 changes: 100 additions & 4 deletions UnleashedRecomp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,19 @@
project("UnleashedRecomp")

set(UNLEASHED_RECOMP_HOST_TOOLS_DIR "" CACHE PATH "Directory containing host-built recompilation tools.")

function(unleashed_recomp_resolve_tool OUT_VAR TARGET_NAME RELATIVE_PATH)
if (UNLEASHED_RECOMP_HOST_TOOLS_DIR)
set(${OUT_VAR} "${UNLEASHED_RECOMP_HOST_TOOLS_DIR}/${RELATIVE_PATH}" PARENT_SCOPE)
elseif (TARGET ${TARGET_NAME})
set(${OUT_VAR} "$<TARGET_FILE:${TARGET_NAME}>" PARENT_SCOPE)
else()
message(FATAL_ERROR "Tool ${TARGET_NAME} is not available. Set UNLEASHED_RECOMP_HOST_TOOLS_DIR.")
endif()
endfunction()

unleashed_recomp_resolve_tool(UNLEASHED_RECOMP_FILE_TO_C_TOOL file_to_c "tools/file_to_c/file_to_c")

if (WIN32)
option(UNLEASHED_RECOMP_D3D12 "Add D3D12 support for rendering" ON)
endif()
Expand Down Expand Up @@ -28,7 +42,7 @@ function(BIN2C)
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"
COMMAND "${UNLEASHED_RECOMP_FILE_TO_C_TOOL}" "${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}..."
Expand Down Expand Up @@ -58,11 +72,18 @@ else()
add_compile_options(-ffp-model=strict)
endif()

add_compile_definitions(
SDL_MAIN_HANDLED
set(UNLEASHED_RECOMP_COMPILE_DEFINITIONS
_DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR # Microsoft wtf?
_CRT_SECURE_NO_WARNINGS)

if (NOT CMAKE_SYSTEM_NAME STREQUAL "iOS")
list(APPEND UNLEASHED_RECOMP_COMPILE_DEFINITIONS SDL_MAIN_HANDLED)
else()
list(APPEND UNLEASHED_RECOMP_COMPILE_DEFINITIONS UNLEASHED_RECOMP_IOS)
endif()

add_compile_definitions(${UNLEASHED_RECOMP_COMPILE_DEFINITIONS})

set(UNLEASHED_RECOMP_PRECOMPILED_HEADERS
"stdafx.h"
)
Expand Down Expand Up @@ -97,6 +118,14 @@ elseif (CMAKE_SYSTEM_NAME MATCHES "Linux")
"os/linux/user_linux.cpp"
"os/linux/version_linux.cpp"
)
elseif (CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
"os/ios/logger_ios.cpp"
"os/ios/media_ios.cpp"
"os/ios/process_ios.mm"
"os/ios/user_ios.mm"
"os/ios/version_ios.mm"
)
elseif (APPLE)
set(UNLEASHED_RECOMP_OS_CXX_SOURCES
"os/macos/logger_macos.cpp"
Expand Down Expand Up @@ -156,10 +185,12 @@ set(UNLEASHED_RECOMP_UI_CXX_SOURCES
"ui/fader.cpp"
"ui/game_window.cpp"
"ui/imgui_utils.cpp"
"ui/input_coords.cpp"
"ui/installer_wizard.cpp"
"ui/message_window.cpp"
"ui/options_menu.cpp"
"ui/options_menu_thumbnails.cpp"
"ui/touch_controls.cpp"
"ui/tv_static.cpp"
)

Expand Down Expand Up @@ -292,6 +323,54 @@ if (WIN32)
if (${CMAKE_BUILD_TYPE} MATCHES "Release")
target_link_options(UnleashedRecomp PRIVATE "/SUBSYSTEM:WINDOWS" "/ENTRY:mainCRTStartup")
endif()
elseif (CMAKE_SYSTEM_NAME STREQUAL "iOS")
set(UNLEASHED_RECOMP_IOS_MINIMUM_VERSION "${CMAKE_OSX_DEPLOYMENT_TARGET}")
if (NOT UNLEASHED_RECOMP_IOS_MINIMUM_VERSION)
execute_process(COMMAND xcrun --sdk "${CMAKE_OSX_SYSROOT}" --show-sdk-version
OUTPUT_VARIABLE UNLEASHED_RECOMP_IOS_MINIMUM_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE COMMAND_ERROR_IS_FATAL ANY)
endif()
CreateVersionString(
VERSION_TXT ${VERSION_TXT}
OUTPUT_VAR IOS_BUNDLE_VERSION
)
string(REGEX REPLACE "^v" "" IOS_BUNDLE_VERSION "${IOS_BUNDLE_VERSION}")

set(UNLEASHED_RECOMP_IOS_ICON_FILES
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon20x20@2x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon20x20@3x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon29x29@2x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon29x29@3x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon40x40@2x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon40x40@3x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon60x60@2x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon60x60@3x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon76x76.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon76x76@2x.png"
"${CMAKE_CURRENT_SOURCE_DIR}/res/ios/icons/AppIcon83.5x83.5@2x.png"
)

add_executable(UnleashedRecomp MACOSX_BUNDLE
${UNLEASHED_RECOMP_CXX_SOURCES}
)
set_target_properties(UnleashedRecomp PROPERTIES
OUTPUT_NAME "Unleashed Recompiled"
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/res/ios/Info.plist.in
MACOSX_BUNDLE_GUI_IDENTIFIER hedge-dev.UnleashedRecomp
MACOSX_BUNDLE_BUNDLE_NAME "Unleashed Recompiled"
MACOSX_BUNDLE_BUNDLE_VERSION ${IOS_BUNDLE_VERSION}
MACOSX_BUNDLE_SHORT_VERSION_STRING ${IOS_BUNDLE_VERSION}
XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "hedge-dev.UnleashedRecomp"
XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2"
XCODE_ATTRIBUTE_ENABLE_BITCODE "NO"
)
foreach(UNLEASHED_RECOMP_IOS_ICON_FILE IN LISTS UNLEASHED_RECOMP_IOS_ICON_FILES)
add_custom_command(TARGET UnleashedRecomp POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_if_different
"${UNLEASHED_RECOMP_IOS_ICON_FILE}"
"$<TARGET_BUNDLE_DIR:UnleashedRecomp>"
)
endforeach()
elseif (APPLE)
# Create version number for app bundle.
CreateVersionString(
Expand Down Expand Up @@ -387,20 +466,37 @@ if (WIN32)
)
endif()

set(UNLEASHED_RECOMP_SDL_LIBS SDL2::SDL2-static)
if (CMAKE_SYSTEM_NAME STREQUAL "iOS" AND TARGET SDL2::SDL2main)
list(PREPEND UNLEASHED_RECOMP_SDL_LIBS SDL2::SDL2main)
endif()

set(UNLEASHED_RECOMP_PLATFORM_LIBS)
if (CMAKE_SYSTEM_NAME STREQUAL "iOS")
target_link_options(UnleashedRecomp PRIVATE "LINKER:-ObjC")
if (UNLEASHED_RECOMP_IOS_NATIVE_METAL)
target_compile_definitions(UnleashedRecomp PRIVATE UNLEASHED_RECOMP_METAL=1)
else()
list(APPEND UNLEASHED_RECOMP_PLATFORM_LIBS MoltenVK)
target_link_options(UnleashedRecomp PRIVATE "LINKER:-u,_vkGetInstanceProcAddr")
endif()
endif()

target_link_libraries(UnleashedRecomp PRIVATE
fmt::fmt
libzstd_static
msdf-atlas-gen::msdf-atlas-gen
nfd::nfd
o1heap
XenonUtils
SDL2::SDL2-static
${UNLEASHED_RECOMP_SDL_LIBS}
SDL2_mixer
tomlplusplus::tomlplusplus
UnleashedRecompLib
xxHash::xxhash
CURL::libcurl
plume
${UNLEASHED_RECOMP_PLATFORM_LIBS}
)

target_include_directories(UnleashedRecomp PRIVATE
Expand Down
23 changes: 22 additions & 1 deletion UnleashedRecomp/cpu/guest_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -144,10 +144,31 @@ uint32_t GuestThread::Start(const GuestThreadParams& params)
const auto procMask = (uint8_t)(params.flags >> 24);
const auto cpuNumber = procMask == 0 ? 0 : 7 - std::countl_zero(procMask);

#ifdef UNLEASHED_RECOMP_IOS
fprintf(stderr, "[iOS guest] start function=0x%08X value=0x%08X flags=0x%08X cpu=%u\n",
params.function,
params.value,
params.flags,
cpuNumber);
fflush(stderr);
#endif

GuestThreadContext ctx(cpuNumber);
ctx.ppcContext.r3.u64 = params.value;

g_memory.FindFunction(params.function)(ctx.ppcContext, g_memory.base);
PPCFunc* function = g_memory.FindFunction(params.function);

#ifdef UNLEASHED_RECOMP_IOS
fprintf(stderr, "[iOS guest] host function=%p\n", reinterpret_cast<void*>(function));
fflush(stderr);
#endif

function(ctx.ppcContext, g_memory.base);

#ifdef UNLEASHED_RECOMP_IOS
fprintf(stderr, "[iOS guest] returned r3=0x%08X\n", ctx.ppcContext.r3.u32);
fflush(stderr);
#endif

return ctx.ppcContext.r3.u32;
}
Expand Down
Loading