From e63c209fa78f7a30e6b778b3e923f0c9f35d1f91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Apr 2026 22:04:55 +0200 Subject: [PATCH 1/5] Bump Cargo.lock for langtool --- Tools/langtool/Cargo.lock | 166 ++++++++++++++------------------------ 1 file changed, 62 insertions(+), 104 deletions(-) diff --git a/Tools/langtool/Cargo.lock b/Tools/langtool/Cargo.lock index ca77319ab1e6..6c5a6d1dadaa 100644 --- a/Tools/langtool/Cargo.lock +++ b/Tools/langtool/Cargo.lock @@ -149,12 +149,6 @@ dependencies = [ "shlex", ] -[[package]] -name = "cesu8" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" - [[package]] name = "cfg-if" version = "1.0.4" @@ -737,9 +731,9 @@ dependencies = [ [[package]] name = "idna_adapter" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344" +checksum = "cb68373c0d6620ef8105e855e7745e18b0d00d3bdb07fb532e434244cdb9a714" dependencies = [ "icu_normalizer", "icu_properties", @@ -787,27 +781,32 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "jni" -version = "0.21.1" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" dependencies = [ - "cesu8", "cfg-if", "combine", - "jni-sys 0.3.1", + "jni-macros", + "jni-sys", "log", - "thiserror 1.0.69", + "simd_cesu8", + "thiserror 2.0.18", "walkdir", - "windows-sys 0.45.0", + "windows-link", ] [[package]] -name = "jni-sys" -version = "0.3.1" +name = "jni-macros" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41a652e1f9b6e0275df1f15b32661cf0d4b78d4d87ddec5e0c3c20f097433258" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" dependencies = [ - "jni-sys 0.4.1", + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.117", ] [[package]] @@ -841,9 +840,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.95" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2964e92d1d9dc3364cae4d718d93f227e3abb088e747d92e0395bfdedf1c12ca" +checksum = "a1840c94c045fbcf8ba2812c95db44499f7c64910a912551aaaa541decebcacf" dependencies = [ "cfg-if", "futures-util", @@ -1222,9 +1221,9 @@ checksum = "dc897dd8d9e8bd1ed8cdad82b5966c3e0ecae09fb1907d58efaa013543185d0a" [[package]] name = "reqwest" -version = "0.13.2" +version = "0.13.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3f43e3283ab1488b624b44b0e988d0acea0b3214e694730a055cb6b2efa801" +checksum = "62e0021ea2c22aed41653bc7e1419abb2c97e038ff2c33d0e1309e49a97deec0" dependencies = [ "base64", "bytes", @@ -1282,6 +1281,15 @@ version = "2.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94300abf3f1ae2e2b8ffb7b58043de3d399c73fa6f4b73826402a5c457614dbe" +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" version = "1.1.4" @@ -1297,9 +1305,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.39" +version = "0.23.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c2c118cb077cca2822033836dfb1b975355dfb784b5e8da48f7b6c5db74e60e" +checksum = "ef86cd5876211988985292b91c96a8f2d298df24e75989a43a3c73f2d4d8168b" dependencies = [ "aws-lc-rs", "once_cell", @@ -1333,9 +1341,9 @@ dependencies = [ [[package]] name = "rustls-platform-verifier" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d99feebc72bae7ab76ba994bb5e121b8d83d910ca40b36e0921f53becc41784" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" dependencies = [ "core-foundation 0.10.1", "core-foundation-sys", @@ -1472,6 +1480,22 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "simd_cesu8" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94f90157bb87cddf702797c5dadfa0be7d266cdf49e22da2fcaa32eff75b2c33" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + [[package]] name = "slab" version = "0.4.12" @@ -1864,9 +1888,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bf938a0bacb0469e83c1e148908bd7d5a6010354cf4fb73279b7447422e3a89" +checksum = "df52b6d9b87e0c74c9edfa1eb2d9bf85e5d63515474513aa50fa181b3c4f5db1" dependencies = [ "cfg-if", "once_cell", @@ -1877,9 +1901,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.68" +version = "0.4.70" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f371d383f2fb139252e0bfac3b81b265689bf45b6874af544ffa4c975ac1ebf8" +checksum = "af934872acec734c2d80e6617bbb5ff4f12b052dd8e6332b0817bce889516084" dependencies = [ "js-sys", "wasm-bindgen", @@ -1887,9 +1911,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eeff24f84126c0ec2db7a449f0c2ec963c6a49efe0698c4242929da037ca28ed" +checksum = "78b1041f495fb322e64aca85f5756b2172e35cd459376e67f2a6c9dffcedb103" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1897,9 +1921,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d08065faf983b2b80a79fd87d8254c409281cf7de75fc4b773019824196c904" +checksum = "9dcd0ff20416988a18ac686d4d4d0f6aae9ebf08a389ff5d29012b05af2a1b41" dependencies = [ "bumpalo", "proc-macro2", @@ -1910,9 +1934,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.118" +version = "0.2.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fd04d9e306f1907bd13c6361b5c6bfc7b3b3c095ed3f8a9246390f8dbdee129" +checksum = "49757b3c82ebf16c57d69365a142940b384176c24df52a087fb748e2085359ea" dependencies = [ "unicode-ident", ] @@ -2012,9 +2036,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.95" +version = "0.3.97" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f2dfbb17949fa2088e5d39408c48368947b86f7834484e87b73de55bc14d97d" +checksum = "2eadbac71025cd7b0834f20d1fe8472e8495821b4e9801eb0a60bd1f19827602" dependencies = [ "js-sys", "wasm-bindgen", @@ -2114,15 +2138,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - [[package]] name = "windows-sys" version = "0.52.0" @@ -2150,21 +2165,6 @@ dependencies = [ "windows-link", ] -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - [[package]] name = "windows-targets" version = "0.52.6" @@ -2198,12 +2198,6 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -2216,12 +2210,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -2234,12 +2222,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -2264,12 +2246,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -2282,12 +2258,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -2300,12 +2270,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -2318,12 +2282,6 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - [[package]] name = "windows_x86_64_msvc" version = "0.52.6" From e0a5a3e2bf036f5cf6bfaa2d4b25db35cd9b9e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Apr 2026 19:12:00 +0200 Subject: [PATCH 2/5] iOS: Add basic deep link support. Fixes #21577 --- Common/Net/URL.h | 1 - Common/System/System.h | 1 + Core/HW/MemoryStick.cpp | 2 ++ UI/GameScreen.cpp | 19 +++++++++++ UI/PauseScreen.cpp | 5 +++ ios/AppDelegate.h | 5 +++ ios/AppDelegate.mm | 67 ++++++++++++++++++++++++++++++++++-- ios/PPSSPP-Info.plist | 11 ++++++ ios/PPSSPPUIApplication.mm | 70 +++++++++++++++++++------------------- ios/SceneDelegate.mm | 18 ++++++++++ ios/main.mm | 24 +++++++------ 11 files changed, 174 insertions(+), 49 deletions(-) diff --git a/Common/Net/URL.h b/Common/Net/URL.h index 9b3b96f7bf2a..20b296140a29 100644 --- a/Common/Net/URL.h +++ b/Common/Net/URL.h @@ -189,6 +189,5 @@ class Url { int port_; }; - std::string UriDecode(std::string_view sSrc); std::string UriEncode(std::string_view sSrc); diff --git a/Common/System/System.h b/Common/System/System.h index e58a5ccc8596..38d9c2a0e34e 100644 --- a/Common/System/System.h +++ b/Common/System/System.h @@ -168,6 +168,7 @@ enum SystemProperty { SYSPROP_HAS_LOGIN_DIALOG, SYSPROP_HAS_TEXT_CLIPBOARD, SYSPROP_HAS_TEXT_INPUT_DIALOG, // Indicates that System_InputBoxGetString is available. + SYSPROP_HAS_DEEP_LINKS, // ios-style deep links SYSPROP_CAN_CREATE_SHORTCUT, SYSPROP_CAN_SHOW_FILE, diff --git a/Core/HW/MemoryStick.cpp b/Core/HW/MemoryStick.cpp index 6c6d9a4d66f8..b3ba0ebfc681 100644 --- a/Core/HW/MemoryStick.cpp +++ b/Core/HW/MemoryStick.cpp @@ -167,6 +167,8 @@ void MemoryStick_SetState(MemStickState state) { return; } + INFO_LOG(Log::System, "Memory stick state changed: %d -> %d", memStickState, state); + memStickState = state; // If removed, we unmount. Otherwise, mounting is delayed. diff --git a/UI/GameScreen.cpp b/UI/GameScreen.cpp index ae164ff82312..cd46f2fbcee7 100644 --- a/UI/GameScreen.cpp +++ b/UI/GameScreen.cpp @@ -57,6 +57,14 @@ #include "UI/SavedataScreen.h" #include "UI/MiscViews.h" +// This is in an objective-C file. +#if PPSSPP_PLATFORM(IOS) +void copyDeepLinkForPath(std::string_view filePath); +#else +// dummy +void copyDeepLinkForPath(std::string_view) {} +#endif + constexpr GameInfoFlags g_desiredFlags = GameInfoFlags::PARAM_SFO | GameInfoFlags::ICON | GameInfoFlags::PIC0 | GameInfoFlags::PIC1 | GameInfoFlags::ICON1_PMF | GameInfoFlags::UNCOMPRESSED_SIZE | GameInfoFlags::SIZE | GameInfoFlags::SAVEDATA_SIZE; class PMFView : public UI::InertView { @@ -561,6 +569,17 @@ void GameScreen::CreateContextMenu(UI::ViewGroup *parent) { }); } + if (System_GetPropertyBool(SYSPROP_HAS_DEEP_LINKS)) { + Choice *btnCopyDeepLink = parent->Add(new Choice(di->T("Copy deep link"), ImageID("I_FILE_COPY"))); + btnCopyDeepLink->OnClick.Add([this](UI::EventParams &e) { + auto di = GetI18NCategory(I18NCat::DIALOG); + const std::string deepLink = gamePath_.ToString(); + copyDeepLinkForPath(deepLink); + // Success indication. Not worth a translatable string. + g_OSD.Show(OSDType::MESSAGE_INFO, ApplySafeSubstitutions(di->T("Copied to clipboard: %1"), deepLink), 0.0f, "copyToClip"); + }); + } + if (info_->saveDataSize) { Choice *btnDeleteSaveData = new Choice(ga->T("Delete Save Data"), ImageID("I_TRASHCAN")); parent->Add(btnDeleteSaveData)->OnClick.Handle(this, &GameScreen::OnDeleteSaveData); diff --git a/UI/PauseScreen.cpp b/UI/PauseScreen.cpp index 79b1c55b5803..849c5ccb4824 100644 --- a/UI/PauseScreen.cpp +++ b/UI/PauseScreen.cpp @@ -71,6 +71,11 @@ #include "UI/MiscViews.h" #include "UI/AdhocServerScreen.h" +// This is in an objective-C file. +#if PPSSPP_PLATFORM(IOS) +void copyDeepLinkForPath(std::string_view filePath); +#endif + static void AfterSaveStateAction(SaveState::Status status, std::string_view message) { if (!message.empty() && (!g_Config.bDumpFrames || !g_Config.bDumpVideoOutput)) { g_OSD.Show(status == SaveState::Status::SUCCESS ? OSDType::MESSAGE_SUCCESS : OSDType::MESSAGE_ERROR, diff --git a/ios/AppDelegate.h b/ios/AppDelegate.h index 3e48c9bfdac2..6d81b8b348c5 100644 --- a/ios/AppDelegate.h +++ b/ios/AppDelegate.h @@ -2,6 +2,8 @@ #import +#include + @protocol PPSSPPViewController; @interface AppDelegate : UIResponder @@ -11,5 +13,8 @@ @property (nonatomic, strong) NSDictionary *launchOptions; - (BOOL)launchPPSSPP:(int)argc argv:(char**)argv; +- (void)processFilePath:(NSString *)path; @end + +void copyDeepLinkForPath(std::string_view filePath); diff --git a/ios/AppDelegate.mm b/ios/AppDelegate.mm index c6b00767b952..b2bfc9c43440 100644 --- a/ios/AppDelegate.mm +++ b/ios/AppDelegate.mm @@ -5,6 +5,7 @@ #import "Common/System/NativeApp.h" #import "Core/System.h" #import "Core/Config.h" +#import "Core/Util/PathUtil.h" #import "Common/Log.h" #import "IAPManager.h" @@ -107,9 +108,48 @@ - (void)dealloc { - (void)applicationWillTerminate:(UIApplication *)application { } +// In AppDelegate.mm +- (void)processFilePath:(NSString *)path { + // Convert NSString to std::string + std::string cppPath([path UTF8String]); + + // Try to fixup the path, the app directory changes on every bootup. + Path gamePath(cppPath); + TryUpdateSavedPath(&gamePath); + + // Call the C++ function to handle the file + System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, gamePath.ToString()); +} + +- (BOOL)application:(UIApplication *)app + openURL:(NSURL *)url + options:(NSDictionary *)options { + + // 1. Check the scheme + if (![[url scheme] isEqualToString:@"ppsspp"]) { + NSLog(@"PPSSPPUIApplication.openURL called with invalid URL: %@", url); + return NO; + } + + NSLog(@"PPSSPPUIApplication.openURL called with valid URL: %@", url); + // 2. Parse the URL (using NSURLComponents is safer than manual string parsing) + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + NSArray *queryItems = [components queryItems]; + NSLog(@"PPSSPPUIApplication.openURL query items: %@", queryItems); + for (NSURLQueryItem *item in queryItems) { + if ([item.name isEqualToString:@"path"]) { + NSString *receivedPath = item.value; + [self processFilePath:receivedPath]; + } else { + NSLog(@"PPSSPPUIApplication.openURL: Unrecognized query item: %@=%@", item.name, item.value); + } + } + return YES; +} + - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { - switch (g_Config.iScreenRotation) { - case ROTATION_LOCKED_HORIZONTAL: + switch (g_Config.iScreenRotation) { + case ROTATION_LOCKED_HORIZONTAL: return UIInterfaceOrientationMaskLandscapeRight; case ROTATION_LOCKED_VERTICAL: case ROTATION_LOCKED_VERTICAL180: @@ -132,3 +172,26 @@ - (UIInterfaceOrientationMask)application:(UIApplication *)application supported } @end + +void copyDeepLinkForPath(std::string_view filePath) { + // 1. Convert std::string_view to NSString + // We use the length and data to avoid issues with null terminators + NSString *pathString = [[NSString alloc] initWithBytes:filePath.data() + length:filePath.length() + encoding:NSUTF8StringEncoding]; + + // 2. Percent-encode the path + // This handles spaces, slashes, and special characters for the URL query + NSCharacterSet *allowedChars = [NSCharacterSet URLQueryAllowedCharacterSet]; + NSString *encodedPath = [pathString stringByAddingPercentEncodingWithAllowedCharacters:allowedChars]; + + // 3. Construct the full URL + // Format: scheme://host?query + NSString *deepLink = [NSString stringWithFormat:@"ppsspp://open?path=%@", encodedPath]; + + // 4. Copy to the iOS System Clipboard (UIPasteboard) + [UIPasteboard generalPasteboard].string = deepLink; + + // Optional: Log it for debugging + NSLog(@"Deep link copied: %@", deepLink); +} diff --git a/ios/PPSSPP-Info.plist b/ios/PPSSPP-Info.plist index f977b05b70bc..65fb5f77d3cc 100644 --- a/ios/PPSSPP-Info.plist +++ b/ios/PPSSPP-Info.plist @@ -40,6 +40,17 @@ AppIcon + CFBundleURLTypes + + + CFBundleURLName + org.ppsspp.ppsspp-free + CFBundleURLSchemes + + ppsspp + + + LSRequiresIPhoneOS UIViewControllerBasedStatusBarAppearance diff --git a/ios/PPSSPPUIApplication.mm b/ios/PPSSPPUIApplication.mm index be3c76e44481..c973ed0dc333 100644 --- a/ios/PPSSPPUIApplication.mm +++ b/ios/PPSSPPUIApplication.mm @@ -70,48 +70,48 @@ @implementation PPSSPPUIApplication #if !PPSSPP_PLATFORM(IOS_APP_STORE) - (void)decodeKeyEvent:(NSInteger *)eventMem { - NSInteger eventType = eventMem[GSEVENT_TYPE]; - NSInteger eventScanCode = eventMem[GSEVENTKEY_KEYCODE]; - - //NSLog(@"Got key: %d", (int)eventScanCode); - - if (eventType == GSEVENT_TYPE_KEYUP) { - struct KeyInput key; - key.flags = KeyInputFlags::UP; - key.keyCode = getSmartKeyboardMap((int)eventScanCode); - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - } else if (GSEVENT_TYPE_KEYDOWN) { - struct KeyInput key; - key.flags = KeyInputFlags::DOWN; - key.keyCode = getSmartKeyboardMap((int)eventScanCode); - key.deviceId = DEVICE_ID_KEYBOARD; - NativeKey(key); - } + NSInteger eventType = eventMem[GSEVENT_TYPE]; + NSInteger eventScanCode = eventMem[GSEVENTKEY_KEYCODE]; + + //NSLog(@"Got key: %d", (int)eventScanCode); + + if (eventType == GSEVENT_TYPE_KEYUP) { + struct KeyInput key; + key.flags = KeyInputFlags::UP; + key.keyCode = getSmartKeyboardMap((int)eventScanCode); + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + } else if (GSEVENT_TYPE_KEYDOWN) { + struct KeyInput key; + key.flags = KeyInputFlags::DOWN; + key.keyCode = getSmartKeyboardMap((int)eventScanCode); + key.deviceId = DEVICE_ID_KEYBOARD; + NativeKey(key); + } } - (void)handleKeyUIEvent:(UIEvent *) event { - if ([event respondsToSelector:@selector(_gsEvent)]) { - NSInteger *eventMem; - - eventMem = (NSInteger *) (__bridge void*)[event performSelector:@selector(_gsEvent)]; - if (eventMem) { - [self decodeKeyEvent:eventMem]; - } - } + if ([event respondsToSelector:@selector(_gsEvent)]) { + NSInteger *eventMem; + + eventMem = (NSInteger *) (__bridge void*)[event performSelector:@selector(_gsEvent)]; + if (eventMem) { + [self decodeKeyEvent:eventMem]; + } + } } - (void)sendEvent:(UIEvent *)event { - [super sendEvent:event]; - if ([event respondsToSelector:@selector(_gsEvent)]) { - NSInteger *eventMem; - - eventMem = (NSInteger *) (__bridge void*)[event performSelector:@selector(_gsEvent)]; - if (eventMem) { - [self decodeKeyEvent:eventMem]; - } - } + [super sendEvent:event]; + if ([event respondsToSelector:@selector(_gsEvent)]) { + NSInteger *eventMem; + + eventMem = (NSInteger *) (__bridge void*)[event performSelector:@selector(_gsEvent)]; + if (eventMem) { + [self decodeKeyEvent:eventMem]; + } + } } #endif // !IOS_APP_STORE diff --git a/ios/SceneDelegate.mm b/ios/SceneDelegate.mm index d55e59c2c090..d7aaf5e0f456 100644 --- a/ios/SceneDelegate.mm +++ b/ios/SceneDelegate.mm @@ -95,6 +95,24 @@ - (void)restart:(const char*)restartArgs { [sharedViewController didBecomeActive]; } +- (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts { + for (UIOpenURLContext *context in URLContexts) { + NSLog(@"SceneDelegate: openURLContexts called with URL: %@", context.URL); + NSURL *url = context.URL; + if (![[url scheme] isEqualToString:@"ppsspp"]) { + NSLog(@"SceneDelegate: ignoring URL with unknown scheme: %@", url); + continue; + } + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + for (NSURLQueryItem *item in components.queryItems) { + if ([item.name isEqualToString:@"path"]) { + AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; + [appDelegate processFilePath:item.value]; + } + } + } +} + - (void)sceneWillResignActive:(UIScene *)scene { INFO_LOG(Log::G3D, "sceneWillResignActive"); diff --git a/ios/main.mm b/ios/main.mm index 0407b8bd3547..37e32d9653e6 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -83,7 +83,7 @@ static NSDictionary *parse_entitlements(const void *entitlements, size_t length) { char *copy = (char *)malloc(length); memcpy(copy, entitlements, length); - + // strip out psychic paper entitlement hiding if (@available(iOS 13.5, *)) { } else { @@ -95,7 +95,7 @@ } NSData *data = [NSData dataWithBytes:copy length:length]; free(copy); - + return [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListImmutable format:nil @@ -104,7 +104,7 @@ static NSDictionary *app_entitlements(void) { // Inspired by codesign.c in Darwin sources for Security.framework - + // Find our mach-o header Dl_info dl_info; if (dladdr((const void *)app_entitlements, &dl_info) == 0) @@ -115,7 +115,7 @@ struct mach_header_64 *header = (struct mach_header_64 *)dl_info.dli_fbase; if (header->magic != MH_MAGIC_64) return nil; - + // Simulator executables have fake entitlements in the code signature. The real entitlements can be found in an __entitlements section. size_t entitlements_size; uint8_t *entitlements_data = getsectiondata(header, "__TEXT", "__entitlements", &entitlements_size); @@ -128,7 +128,7 @@ format:nil error:nil]; } - + // Find the LC_CODE_SIGNATURE struct load_command *lc = (struct load_command *) (base + sizeof(*header)); struct linkedit_data_command *cs_lc = NULL; @@ -152,7 +152,7 @@ const struct cs_superblob *cs = (const struct cs_superblob *)csData.bytes; if (ntohl(cs->magic) != 0xfade0cc0) return nil; - + // Find the entitlements in the code signature for (uint32_t i = 0; i < ntohl(cs->count); i++) { struct cs_entitlements *ents = (struct cs_entitlements *) ((char *) cs + ntohl(cs->index[i].offset)); @@ -180,7 +180,7 @@ bool jb_has_container(void) { bool jb_spawn_ptrace_child(int argc, char **argv) { int ret; pid_t pid; - + if (argc > 1 && strcmp(argv[1], childArgv[1]) == 0) { ret = ptrace(PT_TRACE_ME, 0, NULL, 0); NSLog(@"child: ptrace(PT_TRACE_ME) %d", ret); @@ -250,7 +250,7 @@ static bool jb_has_debugger_attached(void) { bool jb_enable_ptrace_hack(void) { bool debugged = jb_has_debugger_attached(); - + // Thanks to this comment: https://news.ycombinator.com/item?id=18431524 // We use this hack to allow mmap with PROT_EXEC (which usually requires the // dynamic-codesigning entitlement) by tricking the process into thinking @@ -259,7 +259,7 @@ bool jb_enable_ptrace_hack(void) { if (ptrace(PT_TRACE_ME, 0, NULL, 0) < 0) { return false; } - + // ptracing ourselves confuses the kernel and will cause bad things to // happen to the system (hangs…) if an exception or signal occurs. Setup // some "safety nets" so we can cause the process to exit in a somewhat sane @@ -269,7 +269,7 @@ bool jb_enable_ptrace_hack(void) { if (!debugged) { // First, ensure that signals are delivered as Mach software exceptions… ptrace(PT_SIGEXC, 0, NULL, 0); - + // …then ensure that this exception goes through our exception handler. // I think it's OK to just watch for EXC_SOFTWARE because the other // exceptions (e.g. EXC_BAD_ACCESS, EXC_BAD_INSTRUCTION, and friends) @@ -282,7 +282,7 @@ bool jb_enable_ptrace_hack(void) { pthread_t thread; pthread_create(&thread, NULL, exception_handler, (void *)&port); } - + return true; } #endif @@ -358,6 +358,8 @@ float System_GetPropertyFloat(SystemProperty prop) { bool System_GetPropertyBool(SystemProperty prop) { switch (prop) { + case SYSPROP_HAS_DEEP_LINKS: + return true; case SYSPROP_DISPLAY_HAS_CAMERA_CUTOUT: return true; case SYSPROP_HAS_FILE_BROWSER: From 771f2b3fe068a4de522b20678e458c73b0e759dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Apr 2026 22:17:56 +0200 Subject: [PATCH 3/5] Avoid creating zero-size fonts (seems to be because of an init order problem during app switching) --- Common/Render/Text/draw_text_cocoa.mm | 4 ++++ Common/UI/View.cpp | 1 + 2 files changed, 5 insertions(+) diff --git a/Common/Render/Text/draw_text_cocoa.mm b/Common/Render/Text/draw_text_cocoa.mm index a98084112dd0..449ac404d1cf 100644 --- a/Common/Render/Text/draw_text_cocoa.mm +++ b/Common/Render/Text/draw_text_cocoa.mm @@ -138,6 +138,10 @@ void Destroy() { // TODO: Share with other backends. void TextDrawerCocoa::SetOrCreateFont(const FontStyle &style) { + if (style.sizePts <= 0) { + return; + } + auto iter = fontMap_.find(style); if (iter != fontMap_.end()) { fontStyle_ = style; diff --git a/Common/UI/View.cpp b/Common/UI/View.cpp index 489d03868c1b..f052661c7c19 100644 --- a/Common/UI/View.cpp +++ b/Common/UI/View.cpp @@ -1089,6 +1089,7 @@ const FontStyle *GetTextStyle(const UIContext &dc, TextSize size) { default: break; } + _dbg_assert_(style->sizePts > 0); return style; } From 1288070f952bbaf7ced7732a25287084aff5b3d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Apr 2026 22:18:30 +0200 Subject: [PATCH 4/5] Translation string --- assets/lang/ar_AE.ini | 1 + assets/lang/az_AZ.ini | 1 + assets/lang/be_BY.ini | 1 + assets/lang/bg_BG.ini | 1 + assets/lang/ca_ES.ini | 1 + assets/lang/cz_CZ.ini | 1 + assets/lang/da_DK.ini | 1 + assets/lang/de_DE.ini | 1 + assets/lang/dr_ID.ini | 1 + assets/lang/en_US.ini | 1 + assets/lang/es_ES.ini | 1 + assets/lang/es_LA.ini | 1 + assets/lang/fa_IR.ini | 1 + assets/lang/fi_FI.ini | 1 + assets/lang/fr_FR.ini | 1 + assets/lang/gl_ES.ini | 1 + assets/lang/gr_EL.ini | 1 + assets/lang/he_IL.ini | 1 + assets/lang/he_IL_invert.ini | 1 + assets/lang/hr_HR.ini | 1 + assets/lang/hu_HU.ini | 1 + assets/lang/id_ID.ini | 1 + assets/lang/it_IT.ini | 1 + assets/lang/ja_JP.ini | 1 + assets/lang/jv_ID.ini | 1 + assets/lang/ko_KR.ini | 1 + assets/lang/ku_SO.ini | 1 + assets/lang/lo_LA.ini | 1 + assets/lang/lt-LT.ini | 1 + assets/lang/ms_MY.ini | 1 + assets/lang/nl_NL.ini | 1 + assets/lang/no_NO.ini | 1 + assets/lang/pl_PL.ini | 1 + assets/lang/pt_BR.ini | 1 + assets/lang/pt_PT.ini | 1 + assets/lang/ro_RO.ini | 1 + assets/lang/ru_RU.ini | 1 + assets/lang/sv_SE.ini | 1 + assets/lang/tg_PH.ini | 1 + assets/lang/th_TH.ini | 1 + assets/lang/tr_TR.ini | 1 + assets/lang/uk_UA.ini | 1 + assets/lang/vi_VN.ini | 1 + assets/lang/zh_CN.ini | 1 + assets/lang/zh_TW.ini | 1 + 45 files changed, 45 insertions(+) diff --git a/assets/lang/ar_AE.ini b/assets/lang/ar_AE.ini index e1981a793380..c1893310b302 100644 --- a/assets/lang/ar_AE.ini +++ b/assets/lang/ar_AE.ini @@ -422,6 +422,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = نسخ الرابط العميق # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = إفتراضي diff --git a/assets/lang/az_AZ.ini b/assets/lang/az_AZ.ini index f29e6749ecbe..a80e2a033a0c 100644 --- a/assets/lang/az_AZ.ini +++ b/assets/lang/az_AZ.ini @@ -414,6 +414,7 @@ ConnectingAP = Giriş nöqtəsinə qoşulur.\nBuyurun, gözləyin... ConnectingPleaseWait = Qoşulur.\nBuyurun, gözləyin... ConnectionName = Qoşulma adı Copied to clipboard: %1 = Kəsintiliyə köçürüldü: %1 +Copy deep link = Dərin linki kopyalayın # AI translated Copy to clipboard = Kəsintiliyə köçürt Corrupted Data = Korlanmış verilən Default = Varsayılan diff --git a/assets/lang/be_BY.ini b/assets/lang/be_BY.ini index 92eef833fb20..a57f8d8574c3 100644 --- a/assets/lang/be_BY.ini +++ b/assets/lang/be_BY.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Скапіяваць глыбокую спасылку # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Па змаўчанні diff --git a/assets/lang/bg_BG.ini b/assets/lang/bg_BG.ini index f34177184df9..7fec95a4fe5e 100644 --- a/assets/lang/bg_BG.ini +++ b/assets/lang/bg_BG.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Копирайте дълбок линк # AI translated Copy to clipboard = Копиране в клипборда Corrupted Data = Повредени данни Default = По подразбиране diff --git a/assets/lang/ca_ES.ini b/assets/lang/ca_ES.ini index 8509e4bbafce..02cf74ab390f 100644 --- a/assets/lang/ca_ES.ini +++ b/assets/lang/ca_ES.ini @@ -414,6 +414,7 @@ ConnectingAP = Connectant al punt d'accés.\nPer favor espera... ConnectingPleaseWait = Connectant.\nPer favor espera... ConnectionName = Nom de la connexió Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copiar enllaç profund # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Dades corruptes Default = Per defecte diff --git a/assets/lang/cz_CZ.ini b/assets/lang/cz_CZ.ini index b550f876e39d..c277d2aee99f 100644 --- a/assets/lang/cz_CZ.ini +++ b/assets/lang/cz_CZ.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopírovat hluboký odkaz # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/da_DK.ini b/assets/lang/da_DK.ini index f99f6c175df7..2909a16662ce 100644 --- a/assets/lang/da_DK.ini +++ b/assets/lang/da_DK.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopier dyb link # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/de_DE.ini b/assets/lang/de_DE.ini index 128aed408fc4..6d530601da00 100644 --- a/assets/lang/de_DE.ini +++ b/assets/lang/de_DE.ini @@ -413,6 +413,7 @@ ConnectingAP = Verbindung mit dem Zugangspunkt herstellen.\nBitte warten... ConnectingPleaseWait = Verbindung wird hergestellt.\nBitte warten... ConnectionName = Verbindungsname Copied to clipboard: %1 = In Zwischenablage kopiert: %1 +Copy deep link = Tiefe Link kopieren # AI translated Copy to clipboard = In Zwischenablage kopieren Corrupted Data = Beschädigte Daten Default = Vorgabe diff --git a/assets/lang/dr_ID.ini b/assets/lang/dr_ID.ini index 1377dd575f08..0de49afc8472 100644 --- a/assets/lang/dr_ID.ini +++ b/assets/lang/dr_ID.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Salin pranala mendalam # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/en_US.ini b/assets/lang/en_US.ini index 99d993fab005..d3e523805daa 100644 --- a/assets/lang/en_US.ini +++ b/assets/lang/en_US.ini @@ -438,6 +438,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copy deep link Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/es_ES.ini b/assets/lang/es_ES.ini index 5605076f35cd..d39d37f1b147 100644 --- a/assets/lang/es_ES.ini +++ b/assets/lang/es_ES.ini @@ -415,6 +415,7 @@ ConnectingAP = Conectando al punto de acceso.\nPor favor, espera... ConnectingPleaseWait = Conectando.\nPor favor, espera... ConnectionName = Nombre de la conexión Copied to clipboard: %1 = Copiado a portapapeles: %1 +Copy deep link = Copiar enlace profundo # AI translated Copy to clipboard = Copiar a portapapeles Corrupted Data = Datos corruptos Default = Por defecto diff --git a/assets/lang/es_LA.ini b/assets/lang/es_LA.ini index ab041a930427..fabd4c9f30b4 100644 --- a/assets/lang/es_LA.ini +++ b/assets/lang/es_LA.ini @@ -414,6 +414,7 @@ ConnectingAP = Conectando a un punto de acceso.\nEspere un momento... ConnectingPleaseWait = Conectando \nEspere un momento... ConnectionName = Nombre de conexión Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copiar enlace profundo # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Datos dañados Default = Por defecto diff --git a/assets/lang/fa_IR.ini b/assets/lang/fa_IR.ini index 8664bf4f17fc..ecee13ceb805 100644 --- a/assets/lang/fa_IR.ini +++ b/assets/lang/fa_IR.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = نام اتصال Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = کپی لینک عمیق # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = داده‌ها خراب شده Default = پیشفرض diff --git a/assets/lang/fi_FI.ini b/assets/lang/fi_FI.ini index ad9138b270ab..5f0ff2ad0085 100644 --- a/assets/lang/fi_FI.ini +++ b/assets/lang/fi_FI.ini @@ -414,6 +414,7 @@ ConnectingAP = Yhdistetään tukiasemaan.\nOdota hetki... ConnectingPleaseWait = Yhdistetään.\nOdota hetki... ConnectionName = Yhteyden nimi Copied to clipboard: %1 = Kopioitu leikepöydälle: %1 +Copy deep link = Kopioi syvälinkki # AI translated Copy to clipboard = Kopioi leikepöydälle Corrupted Data = Vioittuneet tiedot Default = Oletus diff --git a/assets/lang/fr_FR.ini b/assets/lang/fr_FR.ini index 2edc78652cdf..f6e85b343987 100644 --- a/assets/lang/fr_FR.ini +++ b/assets/lang/fr_FR.ini @@ -438,6 +438,7 @@ ConnectingAP = Connexion au point d'accès\nVeuillez patienter... ConnectingPleaseWait = Connexion en cours\nVeuillez patienter... ConnectionName = Nom de la connexion Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copier le lien profond # AI translated Copy to clipboard = Copier dans le presse-papiers Corrupted Data = Données corrompues Default = Par défaut diff --git a/assets/lang/gl_ES.ini b/assets/lang/gl_ES.ini index 547700d6e360..fe29f4ef8f93 100644 --- a/assets/lang/gl_ES.ini +++ b/assets/lang/gl_ES.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copiar enlace profundo # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/gr_EL.ini b/assets/lang/gr_EL.ini index b3210571e5a3..5860b5e279d8 100644 --- a/assets/lang/gr_EL.ini +++ b/assets/lang/gr_EL.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Αντιγραφή βαθιού συνδέσμου # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/he_IL.ini b/assets/lang/he_IL.ini index 9d3620e6bf65..e8375ec9cefa 100644 --- a/assets/lang/he_IL.ini +++ b/assets/lang/he_IL.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = העתק קישור עמוק # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/he_IL_invert.ini b/assets/lang/he_IL_invert.ini index 37a28963dda8..a8c736cd72a0 100644 --- a/assets/lang/he_IL_invert.ini +++ b/assets/lang/he_IL_invert.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = קישור עמוק העתק # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/hr_HR.ini b/assets/lang/hr_HR.ini index 50abccfcf0bd..ccaed8ed740a 100644 --- a/assets/lang/hr_HR.ini +++ b/assets/lang/hr_HR.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopiraj duboku vezu # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/hu_HU.ini b/assets/lang/hu_HU.ini index 7f50a35cc020..60f7015b1ec5 100644 --- a/assets/lang/hu_HU.ini +++ b/assets/lang/hu_HU.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Másolja a mély linket # AI translated Copy to clipboard = Vágolapra másolás Corrupted Data = Sérült adat Default = Alapértelmezett diff --git a/assets/lang/id_ID.ini b/assets/lang/id_ID.ini index 59b6b33d09a4..6cdc4f366ac1 100644 --- a/assets/lang/id_ID.ini +++ b/assets/lang/id_ID.ini @@ -414,6 +414,7 @@ ConnectingAP = Menghubungkan ke titik akses.\nHarap tunggu... ConnectingPleaseWait = Menghubungkan.\nHarap tunggu... ConnectionName = Nama koneksi Copied to clipboard: %1 = Disalin ke papan klip: %1 +Copy deep link = Salin tautan dalam # AI translated Copy to clipboard = Salin ke papan klip Corrupted Data = Data rusak Default = Bawaan diff --git a/assets/lang/it_IT.ini b/assets/lang/it_IT.ini index 9faffe45946c..f81f12cea371 100644 --- a/assets/lang/it_IT.ini +++ b/assets/lang/it_IT.ini @@ -414,6 +414,7 @@ ConnectingAP = Connessione in corso dal punto di accesso.\nAttendere, prego... ConnectingPleaseWait = Connessione in corso.\nAttendere, prego... ConnectionName = Nome connessione Copied to clipboard: %1 = Copiato negli appunti: %1 +Copy deep link = Copia link profondo # AI translated Copy to clipboard = Copia negli appunti Corrupted Data = Dati corrotti Default = Predefinito diff --git a/assets/lang/ja_JP.ini b/assets/lang/ja_JP.ini index 696b639f6da7..ce8247c9c60f 100644 --- a/assets/lang/ja_JP.ini +++ b/assets/lang/ja_JP.ini @@ -414,6 +414,7 @@ ConnectingAP = アクセスポイントに接続中.\nしばらくお待ちく ConnectingPleaseWait = 接続中.\nしばらくお待ちください... ConnectionName = 接続名 Copied to clipboard: %1 = クリップボードへコピー: %1 +Copy deep link = ディープリンクをコピー # AI translated Copy to clipboard = クリップボードへコピー Corrupted Data = 破損したデータ Default = デフォルト diff --git a/assets/lang/jv_ID.ini b/assets/lang/jv_ID.ini index 337500695abd..9ae77b2f0efc 100644 --- a/assets/lang/jv_ID.ini +++ b/assets/lang/jv_ID.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Salin pranala jero # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/ko_KR.ini b/assets/lang/ko_KR.ini index 2c7831829dbf..5735647351f6 100644 --- a/assets/lang/ko_KR.ini +++ b/assets/lang/ko_KR.ini @@ -414,6 +414,7 @@ ConnectingAP = 접속 포인트에 연결하는 중입니다.\n잠시만 기다 ConnectingPleaseWait = 연결 중입니다.\n잠시만 기다려 주세요... ConnectionName = 연결 이름 Copied to clipboard: %1 = 클립보드에 복사됨: %1 +Copy deep link = 딥 링크 복사 # AI translated Copy to clipboard = 클립보드에 복사 Corrupted Data = 손상된 데이터 Default = 기본 diff --git a/assets/lang/ku_SO.ini b/assets/lang/ku_SO.ini index 4bfa98abdf5b..4453e81fdcd5 100644 --- a/assets/lang/ku_SO.ini +++ b/assets/lang/ku_SO.ini @@ -428,6 +428,7 @@ ConnectingAP = پەیوەندی ئەکەین بە خاڵی دەست بە یەک ConnectingPleaseWait = پەیوەندی ئەکەین.\nتکایە بووەستە... ConnectionName = ناوی پەیوەندی Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopîyaya girêdana qelew # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = زانیاریەکە تێکچووە Default = Default diff --git a/assets/lang/lo_LA.ini b/assets/lang/lo_LA.ini index d9366f3479ae..5c50a4e0f564 100644 --- a/assets/lang/lo_LA.ini +++ b/assets/lang/lo_LA.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = ສອນບິບສອນສູງ # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/lt-LT.ini b/assets/lang/lt-LT.ini index 58108ba1c1a7..f79ff62c52d7 100644 --- a/assets/lang/lt-LT.ini +++ b/assets/lang/lt-LT.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopijuoti gilią nuorodą # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/ms_MY.ini b/assets/lang/ms_MY.ini index c88177ab5c54..5289390e3f94 100644 --- a/assets/lang/ms_MY.ini +++ b/assets/lang/ms_MY.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Salin pautan mendalam # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/nl_NL.ini b/assets/lang/nl_NL.ini index 8282b43ba235..afff1f2e26f7 100644 --- a/assets/lang/nl_NL.ini +++ b/assets/lang/nl_NL.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopieer diepe link # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/no_NO.ini b/assets/lang/no_NO.ini index 248594b9f74a..431c5658b294 100644 --- a/assets/lang/no_NO.ini +++ b/assets/lang/no_NO.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Kopier dyp lenke # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Standard diff --git a/assets/lang/pl_PL.ini b/assets/lang/pl_PL.ini index 9d68c065b0fc..267af1ab48bf 100644 --- a/assets/lang/pl_PL.ini +++ b/assets/lang/pl_PL.ini @@ -414,6 +414,7 @@ ConnectingAP = Łączenie do punktu dostępowego.\nProszę czekać... ConnectingPleaseWait = Łączenie.\nProszę czekać... ConnectionName = Nazwa Połączenia Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Skopiuj link głęboki # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Uszkodzone dane Default = Domyślny diff --git a/assets/lang/pt_BR.ini b/assets/lang/pt_BR.ini index d09c1b259dfe..2647b9b82024 100644 --- a/assets/lang/pt_BR.ini +++ b/assets/lang/pt_BR.ini @@ -438,6 +438,7 @@ ConnectingAP = Conectando ao ponto de acesso.\nPor favor espere... ConnectingPleaseWait = Conectando.\nPor favor espere... ConnectionName = Nome da conexão Copied to clipboard: %1 = Copiou pra área de transferência: %1 +Copy deep link = Copiar link profundo # AI translated Copy to clipboard = Copiar pra área de transferência Corrupted Data = Dados corrompidos Default = Padrão diff --git a/assets/lang/pt_PT.ini b/assets/lang/pt_PT.ini index 3d631e8c17ee..038b289f628e 100644 --- a/assets/lang/pt_PT.ini +++ b/assets/lang/pt_PT.ini @@ -438,6 +438,7 @@ ConnectingAP = A conectar ao ponto de acesso.\nPor favor espere... ConnectingPleaseWait = A conectar.\nPor favor espere... ConnectionName = Nome da conexão Copied to clipboard: %1 = Copiado para a área de transferência: %1 +Copy deep link = Copiar link profundo # AI translated Copy to clipboard = Copiar para a área de transferência Corrupted Data = Dados corrompidos Default = Padrão diff --git a/assets/lang/ro_RO.ini b/assets/lang/ro_RO.ini index 46b45c7b6fa7..40e87df1412a 100644 --- a/assets/lang/ro_RO.ini +++ b/assets/lang/ro_RO.ini @@ -415,6 +415,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Copiați linkul profund # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/ru_RU.ini b/assets/lang/ru_RU.ini index 5eda909143b2..c34ae0861313 100644 --- a/assets/lang/ru_RU.ini +++ b/assets/lang/ru_RU.ini @@ -414,6 +414,7 @@ ConnectingAP = Подключение к точке доступа.\nПожал ConnectingPleaseWait = Подключение.\nПожалуйста, подождите... ConnectionName = Имя повреждено Copied to clipboard: %1 = Скопировано в буфер обмена: %1 +Copy deep link = Скопировать глубокую ссылку # AI translated Copy to clipboard = Копировать в буфер обмена Corrupted Data = Данные повреждены Default = По умолчанию diff --git a/assets/lang/sv_SE.ini b/assets/lang/sv_SE.ini index 71a31659db1e..d84c792653d8 100644 --- a/assets/lang/sv_SE.ini +++ b/assets/lang/sv_SE.ini @@ -414,6 +414,7 @@ ConnectingAP = Ansluter till accesspunkten.\nVänta... ConnectingPleaseWait = Ansluter.\nVänta... ConnectionName = Anslutningsnamn Copied to clipboard: %1 = Kopierat till urklipp: %1 +Copy deep link = Kopiera djup länk # AI translated Copy to clipboard = Kopiera till urklipp Corrupted Data = Korrupt data #Default = Standard diff --git a/assets/lang/tg_PH.ini b/assets/lang/tg_PH.ini index 37327d4a6777..2760bf1dbcb3 100644 --- a/assets/lang/tg_PH.ini +++ b/assets/lang/tg_PH.ini @@ -415,6 +415,7 @@ ConnectingAP = Kumokonekta na sa access point.\nSandali lamang... ConnectingPleaseWait = Kumokonekta na.\nSandali lamang... ConnectionName = Pangalan ng Koneksyon Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Копировать глубокую ссылку # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted ang data Default = Default diff --git a/assets/lang/th_TH.ini b/assets/lang/th_TH.ini index 7ab0d1ad7b41..0cf4aaf4f142 100644 --- a/assets/lang/th_TH.ini +++ b/assets/lang/th_TH.ini @@ -430,6 +430,7 @@ ConnectingAP = กำลังเชื่อมต่อกับแอคเ ConnectingPleaseWait = กำลังเชื่อมต่อ\nโปรดรอ... ConnectionName = ชื่อเครือข่าย Copied to clipboard: %1 = คัดลอกไปยังคลิปบอร์ด: %1 +Copy deep link = คัดลอกลิงก์ลึก # AI translated Copy to clipboard = คัดลอกไปยังคลิปบอร์ด Corrupted Data = ข้อมูลเสียหาย Default = ค่าดั้งเดิม diff --git a/assets/lang/tr_TR.ini b/assets/lang/tr_TR.ini index 9b66fed8908c..c692a38e93be 100644 --- a/assets/lang/tr_TR.ini +++ b/assets/lang/tr_TR.ini @@ -416,6 +416,7 @@ ConnectingAP = Erişim noktasına bağlanılıyor.\nLütfen bekleyin.... ConnectingPleaseWait = Bağlanılıyor.\nLütfen bekleyin... ConnectionName = Bağlantı adı Copied to clipboard: %1 = Panoya kopyalandı: %1 +Copy deep link = Derin bağlantıyı kopyala # AI translated Copy to clipboard = Panoya kopyala Corrupted Data = Bozuk veri Default = Varsayılan diff --git a/assets/lang/uk_UA.ini b/assets/lang/uk_UA.ini index 771b5c56fa8b..08387cf6d2dd 100644 --- a/assets/lang/uk_UA.ini +++ b/assets/lang/uk_UA.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Під'єднується.\nбудьласка, зачекайте... ConnectionName = Назва підключення Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Скопіювати глибоке посилання # AI translated Copy to clipboard = Копіювати в буфер обміну Corrupted Data = Пошкоджені дані Default = Звичайна diff --git a/assets/lang/vi_VN.ini b/assets/lang/vi_VN.ini index 4fee74d3f0e3..a961b6137f37 100644 --- a/assets/lang/vi_VN.ini +++ b/assets/lang/vi_VN.ini @@ -414,6 +414,7 @@ ConnectingAP = Connecting to the access point.\nPlease wait... ConnectingPleaseWait = Connecting.\nPlease wait... ConnectionName = Connection name Copied to clipboard: %1 = Copied to clipboard: %1 +Copy deep link = Sao chép liên kết sâu # AI translated Copy to clipboard = Copy to clipboard Corrupted Data = Corrupted data Default = Default diff --git a/assets/lang/zh_CN.ini b/assets/lang/zh_CN.ini index 98693c9002f5..f55c0cfec4c5 100644 --- a/assets/lang/zh_CN.ini +++ b/assets/lang/zh_CN.ini @@ -414,6 +414,7 @@ ConnectingAP = 连接到接入点。\n请稍候… ConnectingPleaseWait = 连接中。\n请稍候… ConnectionName = 连接名称 Copied to clipboard: %1 = 已复制到剪贴板: %1 +Copy deep link = 复制深层链接 # AI translated Copy to clipboard = 复制到剪贴板 Corrupted Data = 数据损坏 Default = 默认主题 diff --git a/assets/lang/zh_TW.ini b/assets/lang/zh_TW.ini index 91751f3688f6..bbe0a92b8b33 100644 --- a/assets/lang/zh_TW.ini +++ b/assets/lang/zh_TW.ini @@ -414,6 +414,7 @@ ConnectingAP = 正在連線至存取點\n請稍候… ConnectingPleaseWait = 正在連線\n請稍候… ConnectionName = 連線名稱 Copied to clipboard: %1 = 已複製到剪貼簿:%1 +Copy deep link = 複製深層連結 # AI translated Copy to clipboard = 複製到剪貼簿 Corrupted Data = 已損毀的資料 Default = 預設 From b4698eabfeab18101e39789fde7f2589719f8ee7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Tue, 28 Apr 2026 22:26:53 +0200 Subject: [PATCH 5/5] Support launching directly with the deep link, instead of just launching while already running. --- UI/NativeApp.cpp | 8 +++-- ios/AppDelegate.mm | 26 -------------- ios/SceneDelegate.mm | 85 ++++++++++++++++++++++++++++++++++---------- ios/main.mm | 4 +++ 4 files changed, 76 insertions(+), 47 deletions(-) diff --git a/UI/NativeApp.cpp b/UI/NativeApp.cpp index f3a84d44d339..41f7a7c24a72 100644 --- a/UI/NativeApp.cpp +++ b/UI/NativeApp.cpp @@ -624,12 +624,14 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch boot_filename = Path(str); skipLogo = true; } + // This is needed on iOS, to fixup the path to match the current app directory, if it's stored in it. + TryUpdateSavedPath(&boot_filename); if (okToLoad && okToCheck) { std::unique_ptr fileLoader(ConstructFileLoader(boot_filename)); if (!fileLoader->Exists()) { fprintf(stderr, "File not found: %s\n", boot_filename.c_str()); -#if defined(_WIN32) || defined(__ANDROID__) - // Ignore and proceed. + +#if defined(_WIN32) || defined(__ANDROID__) || PPSSPP_PLATFORM(IOS) boot_filename.clear(); #else // Bail. @@ -639,7 +641,7 @@ void NativeInit(int argc, const char *argv[], const char *savegame_dir, const ch } } else { fprintf(stderr, "Syntax error: Can only boot one file.\nNote: Many command line args need a =, like --appendconfig=FILENAME.ini.\n"); -#if defined(_WIN32) || defined(__ANDROID__) +#if defined(_WIN32) || defined(__ANDROID__) || PPSSPP_PLATFORM(IOS) // Ignore and proceed. #else // Bail. diff --git a/ios/AppDelegate.mm b/ios/AppDelegate.mm index b2bfc9c43440..db3fe9550c49 100644 --- a/ios/AppDelegate.mm +++ b/ios/AppDelegate.mm @@ -121,32 +121,6 @@ - (void)processFilePath:(NSString *)path { System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, gamePath.ToString()); } -- (BOOL)application:(UIApplication *)app - openURL:(NSURL *)url - options:(NSDictionary *)options { - - // 1. Check the scheme - if (![[url scheme] isEqualToString:@"ppsspp"]) { - NSLog(@"PPSSPPUIApplication.openURL called with invalid URL: %@", url); - return NO; - } - - NSLog(@"PPSSPPUIApplication.openURL called with valid URL: %@", url); - // 2. Parse the URL (using NSURLComponents is safer than manual string parsing) - NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; - NSArray *queryItems = [components queryItems]; - NSLog(@"PPSSPPUIApplication.openURL query items: %@", queryItems); - for (NSURLQueryItem *item in queryItems) { - if ([item.name isEqualToString:@"path"]) { - NSString *receivedPath = item.value; - [self processFilePath:receivedPath]; - } else { - NSLog(@"PPSSPPUIApplication.openURL: Unrecognized query item: %@=%@", item.name, item.value); - } - } - return YES; -} - - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window { switch (g_Config.iScreenRotation) { case ROTATION_LOCKED_HORIZONTAL: diff --git a/ios/SceneDelegate.mm b/ios/SceneDelegate.mm index d7aaf5e0f456..c1e52a894883 100644 --- a/ios/SceneDelegate.mm +++ b/ios/SceneDelegate.mm @@ -13,8 +13,31 @@ #import "Core/Config.h" #import "Common/Log.h" #import "IAPManager.h" +#include "Core/Util/PathUtil.h" #import +#include + +static std::string gStartupArgStorage; + +static NSString *ExtractDeepLinkPath(NSURL *url) { + if (![[url scheme] isEqualToString:@"ppsspp"]) { + return nil; + } + + NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; + for (NSURLQueryItem *item in components.queryItems) { + if ([item.name isEqualToString:@"path"] && item.value.length > 0) { + return item.value; + } + } + + return nil; +} + +@interface SceneDelegate () +@property (nonatomic, strong) NSString *pendingLaunchPath; +@end @implementation SceneDelegate @@ -22,11 +45,37 @@ + (void)load { NSLog(@"✅ SceneDelegate class was loaded!"); } +- (void)capturePendingPathFromURLContexts:(NSSet *)URLContexts { + for (UIOpenURLContext *context in URLContexts) { + NSString *path = ExtractDeepLinkPath(context.URL); + if (path.length > 0) { + self.pendingLaunchPath = path; + NSLog(@"SceneDelegate: captured cold-start deep link path: %@", self.pendingLaunchPath); + break; + } + } +} + +- (void)handleURLContextsWhileRunning:(NSSet *)URLContexts { + AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; + for (UIOpenURLContext *context in URLContexts) { + NSLog(@"SceneDelegate: openURLContexts called with URL: %@", context.URL); + NSString *path = ExtractDeepLinkPath(context.URL); + if (path.length > 0) { + [appDelegate processFilePath:path]; + } else { + NSLog(@"SceneDelegate: ignoring deep link URL (invalid scheme or missing path): %@", context.URL); + } + } +} + - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { if (![scene isKindOfClass:[UIWindowScene class]]) { return; } + [self capturePendingPathFromURLContexts:connectionOptions.URLContexts]; + UIWindowScene *windowScene = (UIWindowScene *)scene; if (self.window) { NSLog(@"✅ Window already exists, not creating again!"); @@ -43,12 +92,26 @@ -(void) launchPPSSPP { int argc = 1; char *argv[5]{}; + NSString *startupPath = nil; NSURL *nsUrl = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey]; - if (nsUrl != nullptr && nsUrl.isFileURL) { + if (self.pendingLaunchPath.length > 0) { + startupPath = self.pendingLaunchPath; + self.pendingLaunchPath = nil; + } + + if (startupPath == nil && nsUrl != nullptr && nsUrl.isFileURL) { NSString *nsString = nsUrl.path; - const char *string = nsString.UTF8String; - argv[argc++] = (char*)string; + startupPath = nsString; + } + + if (startupPath.length > 0) { + // Keep cold-start argv behavior aligned with processFilePath(). + std::string startupPathUtf8(startupPath.UTF8String); + Path gamePath(startupPathUtf8); + gStartupArgStorage = gamePath.ToString(); + argv[argc++] = (char *)gStartupArgStorage.c_str(); + NSLog(@"SceneDelegate: startup path passed to argv: %s", gStartupArgStorage.c_str()); } NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; @@ -96,21 +159,7 @@ - (void)restart:(const char*)restartArgs { } - (void)scene:(UIScene *)scene openURLContexts:(NSSet *)URLContexts { - for (UIOpenURLContext *context in URLContexts) { - NSLog(@"SceneDelegate: openURLContexts called with URL: %@", context.URL); - NSURL *url = context.URL; - if (![[url scheme] isEqualToString:@"ppsspp"]) { - NSLog(@"SceneDelegate: ignoring URL with unknown scheme: %@", url); - continue; - } - NSURLComponents *components = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO]; - for (NSURLQueryItem *item in components.queryItems) { - if ([item.name isEqualToString:@"path"]) { - AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate; - [appDelegate processFilePath:item.value]; - } - } - } + [self handleURLContextsWhileRunning:URLContexts]; } - (void)sceneWillResignActive:(UIScene *)scene { diff --git a/ios/main.mm b/ios/main.mm index 37e32d9653e6..3b9f574490b1 100644 --- a/ios/main.mm +++ b/ios/main.mm @@ -699,6 +699,10 @@ int main(int argc, char *argv[]) { } PROFILE_INIT(); +#if PPSSPP_PLATFORM(IOS_APP_STORE) && defined(_DEBUG) + g_logManager.SetOutputsEnabled(LogOutput::Stdio); +#endif + @autoreleasepool { return UIApplicationMain(argc, argv, NSStringFromClass([PPSSPPUIApplication class]), NSStringFromClass([AppDelegate class])); }