diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 090b9e1f..1d3b5e5f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,6 +41,7 @@ jobs: - { name: 'msys2 mingw32', os: 'windows-latest', generator: 'Ninja', dx5: false, config: false, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw32', msys-env: 'mingw-w64-i686', shell: 'msys2 {0}' } - { name: 'msys2 mingw64', os: 'windows-latest', generator: 'Ninja', dx5: false, config: true, mingw: true, werror: true, clang-tidy: true, msystem: 'mingw64', msys-env: 'mingw-w64-x86_64', shell: 'msys2 {0}' } - { name: 'macOS', os: 'macos-latest', generator: 'Ninja', dx5: false, config: true, brew: true, werror: true, clang-tidy: false } + - { name: 'iOS', os: 'macos-15', generator: 'Xcode', dx5: false, config: false, brew: true, werror: true, clang-tidy: false, cmake-args: '-DCMAKE_SYSTEM_NAME=iOS' } - { name: 'Emscripten', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, emsdk: true, werror: true, clang-tidy: false, cmake-wrapper: 'emcmake' } - { name: 'Nintendo 3DS', os: 'ubuntu-latest', generator: 'Ninja', dx5: false, config: false, n3ds: true, werror: true, clang-tidy: false, container: 'devkitpro/devkitarm:latest', cmake-args: '-DCMAKE_TOOLCHAIN_FILE=/opt/devkitpro/cmake/3DS.cmake' } - { name: 'Xbox One', os: 'windows-latest', generator: 'Visual Studio 17 2022', dx5: false, config: false, msvc: true, werror: false, clang-tidy: false, vc-arch: 'amd64', cmake-args: '-DCMAKE_SYSTEM_NAME=WindowsStore -DCMAKE_SYSTEM_VERSION=10.0.26100.0', xbox-one: true} diff --git a/CMakeLists.txt b/CMakeLists.txt index 1f26a28b..70ddba15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,12 @@ cmake_minimum_required(VERSION 3.25...4.0 FATAL_ERROR) project(isle LANGUAGES CXX C VERSION 0.1) +if (IOS) + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO) + set(CMAKE_OSX_DEPLOYMENT_TARGET "12.0") + add_compile_definitions(IOS) +endif() + if (WINDOWS_STORE) add_compile_definitions(WINDOWS_STORE) endif() @@ -551,6 +557,11 @@ if (ISLE_BUILD_APP) ISLE/xbox_one_series/config.cpp ) endif() + if (IOS) + target_sources(isle PRIVATE + ISLE/ios/config.cpp + ) + endif() if(Python3_FOUND) if(NOT DEFINED PYTHON_PIL_AVAILABLE) execute_process( @@ -803,8 +814,12 @@ if(WINDOWS_STORE) PATTERN "*/*.msix" PATTERN "*/*.msixbundle") endif() -if(MSVC) +if(MSVC OR IOS) set(CPACK_GENERATOR ZIP) + if(IOS) + set(CPACK_ARCHIVE_FILE_EXTENSION ".ipa") + set(CPACK_INCLUDE_TOPLEVEL_DIRECTORY OFF) + endif() elseif(APPLE AND NOT IOS) set(CPACK_GENERATOR DragNDrop) else() diff --git a/ISLE/ios/config.cpp b/ISLE/ios/config.cpp new file mode 100644 index 00000000..ee9349fa --- /dev/null +++ b/ISLE/ios/config.cpp @@ -0,0 +1,25 @@ +#include "config.h" + +#include +#include +#include + +void IOS_SetupDefaultConfigOverrides(dictionary* p_dictionary) +{ + SDL_Log("Overriding default config for iOS"); + + // Use DevelopmentFiles path for disk and cd paths + // It's good to use that path since user can easily + // connect through SMB and copy the files + const char* documentFolder = SDL_GetUserFolder(SDL_FOLDER_DOCUMENTS); + char* diskPath = new char[strlen(documentFolder) + strlen("isle") + 1](); + strcpy(diskPath, documentFolder); + strcat(diskPath, "isle"); + + if (!SDL_GetPathInfo(diskPath, NULL)) { + SDL_CreateDirectory(diskPath); + } + + iniparser_set(p_dictionary, "isle:diskpath", diskPath); + iniparser_set(p_dictionary, "isle:cdpath", diskPath); +} diff --git a/ISLE/ios/config.h b/ISLE/ios/config.h new file mode 100644 index 00000000..53caf824 --- /dev/null +++ b/ISLE/ios/config.h @@ -0,0 +1,8 @@ +#ifndef IOS_CONFIG_H +#define IOS_CONFIG_H + +#include "dictionary.h" + +void IOS_SetupDefaultConfigOverrides(dictionary* p_dictionary); + +#endif // IOS_CONFIG_H diff --git a/ISLE/isleapp.cpp b/ISLE/isleapp.cpp index 2788b8a7..f8f80e3a 100644 --- a/ISLE/isleapp.cpp +++ b/ISLE/isleapp.cpp @@ -63,6 +63,10 @@ #include "xbox_one_series/config.h" #endif +#ifdef IOS +#include "ios/config.h" +#endif + DECOMP_SIZE_ASSERT(IsleApp, 0x8c) // GLOBAL: ISLE 0x410030 @@ -917,7 +921,11 @@ MxResult IsleApp::SetupWindow() // FUNCTION: ISLE 0x4028d0 bool IsleApp::LoadConfig() { +#ifdef IOS + const char* prefPath = SDL_GetUserFolder(SDL_FOLDER_DOCUMENTS); +#else char* prefPath = SDL_GetPrefPath("isledecomp", "isle"); +#endif char* iniConfig; #ifdef __EMSCRIPTEN__ @@ -1000,6 +1008,9 @@ bool IsleApp::LoadConfig() #endif #ifdef WINDOWS_STORE XBONE_SetupDefaultConfigOverrides(dict); +#endif +#ifdef IOS + IOS_SetupDefaultConfigOverrides(dict); #endif iniparser_dump_ini(dict, iniFP); SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "New config written at '%s'", iniConfig); @@ -1071,7 +1082,9 @@ bool IsleApp::LoadConfig() iniparser_freedict(dict); delete[] iniConfig; +#ifndef IOS SDL_free(prefPath); +#endif return true; } diff --git a/packaging/CMakeLists.txt b/packaging/CMakeLists.txt index 1b178b63..6f5769e9 100644 --- a/packaging/CMakeLists.txt +++ b/packaging/CMakeLists.txt @@ -28,3 +28,7 @@ endif() if(APPLE AND NOT IOS) add_subdirectory(macos) endif() + +if(IOS) + add_subdirectory(ios) +endif() diff --git a/packaging/ios/CMakeLists.txt b/packaging/ios/CMakeLists.txt new file mode 100644 index 00000000..418ad518 --- /dev/null +++ b/packaging/ios/CMakeLists.txt @@ -0,0 +1,52 @@ +set(MACOSX_BUNDLE_GUI_IDENTIFIER ${APP_ID}) +set(MACOSX_BUNDLE_COPYRIGHT ${APP_SPDX}) +set(ISLE_TARGET_NAME isle) +set(MACOSX_ISLE_BUNDLE_NAME ${APP_NAME}) # Do note that it can be up to 15 characters long +set(MACOSX_ISLE_BUNDLE_DISPLAY_NAME ${APP_NAME}) +set(MACOSX_BUNDLE_INFO_STRING ${PROJECT_VERSION}) +set(MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION}) +set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${PROJECT_VERSION}) +set(MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${PROJECT_VERSION}") +set(MACOSX_BUNDLE_REQUIRED_PLATFORM IPhoneOS) + +if(ISLE_BUILD_APP) + configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/isle/Info.plist.in" + "${CMAKE_CURRENT_BINARY_DIR}/isle/Info.plist" + @ONLY + ) + set(RESOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/isle/LaunchScreen.storyboard" "${CMAKE_CURRENT_SOURCE_DIR}/isle/Assets.xcassets") + target_sources(${ISLE_TARGET_NAME} PRIVATE ${RESOURCE_FILES}) + set_source_files_properties(${RESOURCE_FILES} + TARGET_DIRECTORY isle + PROPERTIES MACOSX_PACKAGE_LOCATION Resources) + set_target_properties(${ISLE_TARGET_NAME} PROPERTIES + MACOSX_BUNDLE TRUE + MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_BINARY_DIR}/isle/Info.plist" + XCODE_ATTRIBUTE_ASSETCATALOG_COMPILER_APPICON_NAME "AppIcon" + XCODE_ATTRIBUTE_TARGETED_DEVICE_FAMILY "1,2") + install(TARGETS ${ISLE_TARGET_NAME} DESTINATION ./) + install(CODE " + file(COPY + \"\$\" + \"\$\" + DESTINATION \"\$\{CMAKE_INSTALL_PREFIX\}/${ISLE_TARGET_NAME}.app/Frameworks\") + execute_process(COMMAND /usr/bin/install_name_tool + -add_rpath @executable_path/Frameworks + \"\$\{CMAKE_INSTALL_PREFIX\}/${ISLE_TARGET_NAME}.app/${ISLE_TARGET_NAME}\" + ) + file(MAKE_DIRECTORY + \"\$\{CMAKE_INSTALL_PREFIX\}/Payload\") + file(RENAME + \"\$\{CMAKE_INSTALL_PREFIX\}/${ISLE_TARGET_NAME}.app\" + \"\$\{CMAKE_INSTALL_PREFIX\}/Payload/${ISLE_TARGET_NAME}.app\") + ") +endif() + +install(CODE " + if(IS_DIRECTORY \"\$\{CMAKE_INSTALL_PREFIX\}/bin\" OR IS_DIRECTORY \"\$\{CMAKE_INSTALL_PREFIX\}/lib\" OR EXISTS \"\$\{CMAKE_INSTALL_PREFIX\}/AppIcon.icns\") + execute_process(COMMAND /bin/rm + -rf \"\$\{CMAKE_INSTALL_PREFIX\}/bin\" \"\$\{CMAKE_INSTALL_PREFIX\}/lib\" \"\$\{CMAKE_INSTALL_PREFIX\}/AppIcon.icns\" + ) + endif() +") diff --git a/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/AppIcon.png b/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/AppIcon.png new file mode 100644 index 00000000..f51e7069 Binary files /dev/null and b/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/AppIcon.png differ diff --git a/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/Contents.json b/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/Contents.json new file mode 100644 index 00000000..ce8e776e --- /dev/null +++ b/packaging/ios/isle/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -0,0 +1,36 @@ +{ + "images" : [ + { + "filename" : "AppIcon.png", + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "dark" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + }, + { + "appearances" : [ + { + "appearance" : "luminosity", + "value" : "tinted" + } + ], + "idiom" : "universal", + "platform" : "ios", + "size" : "1024x1024" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packaging/ios/isle/Assets.xcassets/Contents.json b/packaging/ios/isle/Assets.xcassets/Contents.json new file mode 100644 index 00000000..73c00596 --- /dev/null +++ b/packaging/ios/isle/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/packaging/ios/isle/Info.plist.in b/packaging/ios/isle/Info.plist.in new file mode 100644 index 00000000..714324a3 --- /dev/null +++ b/packaging/ios/isle/Info.plist.in @@ -0,0 +1,86 @@ + + + + + CFBundleDevelopmentRegion + English + CFBundleExecutable + ${MACOSX_BUNDLE_EXECUTABLE_NAME} + CFBundleGetInfoString + @MACOSX_BUNDLE_INFO_STRING@ + CFBundleIdentifier + @MACOSX_BUNDLE_GUI_IDENTIFIER@ + CFBundleInfoDictionaryVersion + 6.0 + CFBundleLongVersionString + @MACOSX_BUNDLE_LONG_VERSION_STRING@ + CFBundleName + @MACOSX_ISLE_BUNDLE_NAME@ + CFBundleDisplayName + @MACOSX_ISLE_BUNDLE_DISPLAY_NAME@ + CFBundlePackageType + APPL + CFBundleShortVersionString + @MACOSX_BUNDLE_SHORT_VERSION_STRING@ + CFBundleSignature + ???? + CFBundleVersion + @MACOSX_BUNDLE_BUNDLE_VERSION@ + UILaunchStoryboardName + LaunchScreen + NSHighResolutionCapable + + CSResourcesFileMapped + + LSRequires@MACOSX_BUNDLE_REQUIRED_PLATFORM@ + + NSHumanReadableCopyright + @MACOSX_BUNDLE_COPYRIGHT@ + SDL_FILESYSTEM_BASE_DIR_TYPE + resource + NSSupportsAutomaticGraphicsSwitching + + UIApplicationSupportsIndirectInputEvents + + LSSupportsOpeningDocumentsInPlace + + UIFileSharingEnabled + + CADisableMinimumFrameDurationOnPhone + + UIDeviceFamily + + 1 + 2 + + UIRequiresFullScreen + + UIStatusBarHidden + + UISupportedInterfaceOrientations + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UISupportedInterfaceOrientations~ipad + + UIInterfaceOrientationLandscapeLeft + UIInterfaceOrientationLandscapeRight + + UIApplicationSceneManifest + + UIApplicationSupportsMultipleScenes + + + CFBundleAllowMixedLocalizations + + LSApplicationCategoryType + public.app-category.games + DTPlatformName + iphoneos + UIFileSharingEnabled + + LSSupportsOpeningDocumentsInPlace + + + \ No newline at end of file diff --git a/packaging/ios/isle/LaunchScreen.storyboard b/packaging/ios/isle/LaunchScreen.storyboard new file mode 100644 index 00000000..ad167a8a --- /dev/null +++ b/packaging/ios/isle/LaunchScreen.storyboard @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +