hrydgard / ppsspp

A PSP emulator for Android, Windows, Mac and Linux, written in C++. Want to contribute? Join us on Discord at https://discord.gg/5NJB6dD or just send pull requests / issues. For discussion use the forums at forums.ppsspp.org.
https://www.ppsspp.org
Other
11.26k stars 2.17k forks source link

V1.8.0 on iOS #11905

Closed thorieo closed 4 years ago

thorieo commented 5 years ago

I’d love to help out in porting 1.8 or a 1.9 build to iOS. I’m gonna be honest I have no experience building apps or emulators but I’m basically proficient in most areas of Xcode and Opendev so if anyone can point me along or who I can help out I’d love you forever

unknownbrackets commented 5 years ago

Your interest is very welcome. It should be a matter of building it, mainly. There are instructions here:

https://github.com/hrydgard/ppsspp/wiki/Build-instructions#building-for-ios-cmake

There are some issues that only affect iOS.

One (I wouldn't suggest trying to tackle this, just making you aware) is that since Apple doesn't allow applications to use jit by default, we use a workaround that enables jit on some OS versions / some jailbreak versions:

https://github.com/hrydgard/ppsspp/blob/aa927e0681ed76fec3b540218981a2c407a78e47/ios/main.mm#L152

However, this same workaround (although it makes it faster) has the downside of not working on newer iOS versions (afaik) and also causing the app to hang when closed by the task switcher.

-[Unknown]

andyroid1023 commented 5 years ago

Before compiling your build, maybe you can apply this fix and maybe it can solve issues https://github.com/hrydgard/ppsspp/issues/9186#issuecomment-357570165

jeeeyul commented 5 years ago
syscall(SYS_ptrace, 0 /*PTRACE_TRACEME*/, 0, 0, 0); 

Above code enables W^X JIT. However newer iOS SDK seems to inject some assertion code dynamically when build PPSSPP. Those code seems to assert code signature validity of dynamically compiled code.

I could see log:

기본  16:08:45.028019 +0900   assertiond  [PPSSPP:409] Got exit context: <BKSProcessExitContext: 0x135e1c940; reason: badSignature>
기본  16:08:45.028039 +0900   SpringBoard <FBApplicationProcess: 0x10a90c4a0; PPSSPP (org.ppsspp.ppsspp); pid: 409> assertiond says the process actually exited with context: <BKSProcessExitContext: 0x283887b60; reason: badSignature>
기본  16:08:45.028059 +0900   SpringBoard <FBApplicationProcess: 0x10a90c4a0; PPSSPP (org.ppsspp.ppsspp); pid: 409> exited due to an invalid code signature.
기본  16:08:45.028188 +0900   SpringBoard Removing: <FBApplicationProcess: 0x10a90c4a0; PPSSPP (org.ppsspp.ppsspp); pid: 409>
기본  16:08:45.028207 +0900   SpringBoard Process exited: <FBApplicationProcess: 0x10a90c4a0; PPSSPP (org.ppsspp.ppsspp); pid: -1> -> <FBApplicationProcessExitContext: 0x28379c9f0; exitReason: badSignature; terminationReason: (none)> {
    stateAtExit = <FBProcessState: 0x283a8f780; pid: 409; taskState: Not Running; visibility: Unknown>;
}

So iOS seems to kill PPSSPP few second after JIT has began.

I think It's not runtime restriction. When I build it with old SDK, It runs well on iOS 12.2 beta device also with W^X JIT.

andyroid1023 commented 5 years ago

According to this issue: https://github.com/hrydgard/ppsspp/issues/11881, commenting out syscall(SYS_ptrace, 0 /PTRACE_TRACEME/, 0, 0, 0); solved the problem

unknownbrackets commented 5 years ago

According to this issue: #11881, commenting out syscall(SYS_ptrace, 0 /_PTRACETRACEME/, 0, 0, 0); solved the problem

I assume you mean solved the exit problem, not actually allowing jit. Or do you mean that you're able to use jit without this in some iOS version? It sounds like from @jeeeyul's comment that this isn't likely.

However newer iOS SDK seems to inject some assertion code dynamically when build PPSSPP.

This makes sense, and probably explains why some users have said it's still working while others say it doesn't. Thanks for checking into this.

Are we already targeting the old SDK by default in CMake or do we need to make that more explicit? I realize that eventually it won't be supported anymore.

-[Unknown]

mattkerrison commented 5 years ago

I'd LOVE for 1.8 to make it's way to ios, @thorieo please keep us posted!

jeeeyul commented 5 years ago

At least, I could launch PPSSPP 1.7.1 with W^X JIT on my iOS 12.2 beta device.

  1. Install Xcode 9.4 from here
  2. Launch latest Xcode(for me, it's 10.2 b4)
  3. In Xcode preference, in Locations tab, choose Command Line Tool as Xcode 9.4.1
  4. Quit the Xcode.
  5. Generate xcode project using cmake -DCMAKE_TOOLCHAIN_FILE=./cmake/Toolchains/ios.cmake -DIOS_PLATFORM=OS -H. -Bbuild.ios -GXcode
  6. Open the project with Xcode(10.2 b4).
  7. Change Singing Identity with own.
  8. Build and launch.
  9. Works well.

I will test with latest PPSSPP later and I will tell more.

jeeeyul commented 5 years ago

The unwelcome friend who injects unwanted code that disables JIT comes with iOS12.1 SDK. NOT iOS itself.

AppStore will force 12.1 or above SDK from 27 March.

iOS4all commented 5 years ago

Sorry fo noob question. I’m just wondering what is the different between W^X and X^Y JIT? Also which one is better for performance?

hrydgard commented 5 years ago

There's no such thing as X^Y jit, there's normal jit (fastest, used when we can map pages as Read, Write, eXecutable) and W^X jit (where Write and eXecute are mutually exclusive, that is, only one can be enabled at a time for a page of code, requiring special handling).

jeeeyul commented 5 years ago

Sorry for typo. @hrydgard is correct.

andyroid1023 commented 5 years ago

Any hopes or updates on this?

iOS4all commented 5 years ago

There's no such thing as X^Y jit, there's normal jit (fastest, used when we can map pages as Read, Write, eXecutable) and W^X jit (where Write and eXecute are mutually exclusive, that is, only one can be enabled at a time for a page of code, requiring special handling).

Thank you so much for clarification.

devinprater commented 5 years ago

For me even with IR interpretor, PPSSPP runs perfectly on my iPhone X R. There is one game that hangs after character and stage selection, Soul Calibur, Broken Destiny, but all other games I've tried, Mortal Kombat Unchained, Dissidia Final Fantasy and Duodecim, Tekken 6, all run perfectly. I know GIT will help older devices, but it may not be as big of a need.

hrydgard commented 5 years ago

Well yeah, those Apple CPUs are becoming ridiculously fast so for the latest ones the IR interpreter is a decent option.

DrConflict commented 5 years ago

Really hoping this can be figured out soon and someone compiles the latest versions. Would really love to have 1.8 on both iOS and Mac OS. It seems crazy with a high quality project like this to not have versions compiled for both iOS and Mac OS every time a big update number is released. The PPSSPP community is huge, I'm sure there is someone who can figure this out.

hrydgard commented 5 years ago

@DrConflict It would help a lot with motivation if Apple didn't ban emulators fully from their stores. I prefer to support platforms where emulators are officially allowed, Apple will always be an afterthought.

DrConflict commented 5 years ago

@hrydgard I totally understand your point, and I agree with you. It's just sad that the iOS and Mac community has to miss out because of it though. PPSSPP still has an active Cydia repo as well which makes things a bit confusing. I assumed those were latest builds until I figured out the project was at 1.8.0 haha. I do appreciate all the work though, I'll be using 1.6.3 for now which works great anyway. Cheers

devinprater commented 5 years ago

I hope that once 1.8.0 is built, the Build Store will be able to update their version.

On Mar 24, 2019, at 2:39 PM, DrConflict notifications@github.com wrote:

@hrydgard https://github.com/hrydgard I totally understand your point, and I agree with you. It's just sad that the iOS and Mac community has to miss out because of it though. PPSSPP still has an active Cydia repo as well which makes things a bit confusing. I assumed those were latest builds until I figured out the project was at 1.8.0 haha. I do appreciate all the work though, I'll be using 1.6.3 for now which works great anyway. Cheers

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/hrydgard/ppsspp/issues/11905#issuecomment-475992390, or mute the thread https://github.com/notifications/unsubscribe-auth/AOjJzmgGft10CeVh-3aDty72f-65WTyZks5vZ9SEgaJpZM4b4TTt.

hrydgard commented 5 years ago

@DrConflict Sad or not it's what it is until Apple changes their mind. And I understand the confusion, the official Cydia repo was maintained by a volunteer who has mostly disappeared. Need to do something about that (not the disappearance, the repo).

jeeeyul commented 5 years ago

I could build and run PPSSPP 1.8.0 on iOS 12.2 with W^X JIT just now.

All the things that I did:

main.mm

// main.mm boilerplate

#import <UIKit/UIKit.h>
#import <string>
#import <stdio.h>
#import <stdlib.h>
#import <sys/syscall.h>
#import <AudioToolbox/AudioToolbox.h>

#import "AppDelegate.h"
#import "PPSSPPUIApplication.h"
#import "ViewController.h"

#include "base/NativeApp.h"
#include "profiler/profiler.h"

std::string System_GetProperty(SystemProperty prop) {
    switch (prop) {
        case SYSPROP_NAME:
            return "iOS:";
        case SYSPROP_LANGREGION:
            return "en_US";
        default:
            return "";
    }
}

int System_GetPropertyInt(SystemProperty prop) {
    switch (prop) {
        case SYSPROP_AUDIO_SAMPLE_RATE:
            return 44100;
        case SYSPROP_DISPLAY_REFRESH_RATE:
            return 60000;
        case SYSPROP_DEVICE_TYPE:
            return DEVICE_TYPE_MOBILE;
        default:
            return -1;
    }
}

bool System_GetPropertyBool(SystemProperty prop) {
    switch (prop) {
        case SYSPROP_HAS_BACK_BUTTON:
            return false;
        case SYSPROP_APP_GOLD:
#ifdef GOLD
            return true;
#else
            return false;
#endif
        default:
            return false;
    }
}

void System_SendMessage(const char *command, const char *parameter) {
    if (!strcmp(command, "finish")) {
        exit(0);
    }
}

void System_AskForPermission(SystemPermission permission) {}
PermissionStatus System_GetPermissionStatus(SystemPermission permission) { return PERMISSION_STATUS_GRANTED; }

FOUNDATION_EXTERN void AudioServicesPlaySystemSoundWithVibration(unsigned long, objc_object*, NSDictionary*);

BOOL SupportsTaptic()
{
    // we're on an iOS version that cannot instantiate UISelectionFeedbackGenerator, so no.
    if(!NSClassFromString(@"UISelectionFeedbackGenerator"))
    {
        return NO;
    }

    // http://www.mikitamanko.com/blog/2017/01/29/haptic-feedback-with-uifeedbackgenerator/
    // use private API against UIDevice to determine the haptic stepping
    // 2 - iPhone 7 or above, full taptic feedback
    // 1 - iPhone 6S, limited taptic feedback
    // 0 - iPhone 6 or below, no taptic feedback
    NSNumber* val = (NSNumber*)[[UIDevice currentDevice] valueForKey:@"feedbackSupportLevel"];
    return [val intValue] >= 2;
}

void Vibrate(int mode) {

    if(SupportsTaptic())
    {
        PPSSPPUIApplication* app = (PPSSPPUIApplication*)[UIApplication sharedApplication];
        if(app.feedbackGenerator == nil)
        {
            app.feedbackGenerator = [[UISelectionFeedbackGenerator alloc] init];
            [app.feedbackGenerator prepare];
        }
        [app.feedbackGenerator selectionChanged];
    }
    else
    {
        NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
        NSArray *pattern = @[@YES, @30, @NO, @2];

        dictionary[@"VibePattern"] = pattern;
        dictionary[@"Intensity"] = @2;

        AudioServicesPlaySystemSoundWithVibration(kSystemSoundID_Vibrate, nil, dictionary);
    }
}

int main(int argc, char *argv[])
{
    // Simulates a debugger. Makes it possible to use JIT (though only W^X)
    syscall(SYS_ptrace, 0 /*PTRACE_TRACEME*/, 0, 0, 0);

    PROFILE_INIT();

    @autoreleasepool {
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
        NSString *bundlePath = [[[NSBundle mainBundle] resourcePath] stringByAppendingString:@"/assets/"];

        NativeInit(argc, (const char**)argv, documentsPath.UTF8String, bundlePath.UTF8String, NULL);

        return UIApplicationMain(argc, argv, NSStringFromClass([PPSSPPUIApplication class]), NSStringFromClass([AppDelegate class]));
    }
}

ViewController.mm

-(UIRectEdge)preferredScreenEdgesDeferringSystemGestures
{
    return UIRectEdgeAll;
}

iOS 12.1 SDK seems to inject some assertion code when build just like ARC mechanism. This assertion cause killing the app when JIT code runs. So we have to use iOS12.0 SDK or below. I'v done with iOS 11.4SDK (ships with Xcode 9.4)

In my inference, X^W JIT works on iOS because iOS think it's currently debugging by Xcode, PTRACE makes this available. (Debugging feature needs dynamic code evaluation to provide expression debugging - likes po command, So I think iOS allows JIT for this reason)

Calling PTRACE seems to play a role in deceiving iOS.

However, Some context, iOS waits signals from Xcode forever, I think this makes freezing. This may explain why PPSSPP works and terminate well when it attached with Xcode debugger.


All of these information are just came from my pure inference. If anyone find some error, please correct this.

jeeeyul commented 5 years ago

By the way, Apple will not change their mind. Even Apple allows emulators on AppStore, Allowing unsigned code running is too dangerous for normal users. All the problems related with JIT will remain.

The only official way to run dynamic code is using ScriptKit.

andyroid1023 commented 5 years ago

Are you planning to compile an IPA for 1.8.0 and post it here? I would be happy to test it for you

jeeeyul commented 5 years ago

@andyroid1023 I’ve already post everything those are needed to run PPSSPP1.8.0 on iOS 12.2. I wonder what you need to test.

DrConflict commented 5 years ago

@jeeeyul Can you upload the 1.8.0 PPSSPP iOS .ipa file so people can start testing it please?! I don't understand why you would not post the actual .ipa as well if you said you got it working. Thanks in advance.

coolstar commented 5 years ago

On the iOS 11 & 12 Electra jailbreaks, it isn't required to call syscall 26 (and I recommend you don't, otherwise iOS will keep the process hung rather than exit it when you try and exit PPSSPP). Electra already disables codesigning completely in PPSSPP; so just don't run the syscall and everything will continue working fine.

You can detect if it's bring run under Electra using csops:

#define CS_OPS_STATUS       0   /* return status */
#define CS_DEBUGGED         0x10000000  /* process is currently or has previously been debugged and allowed to run with invalid pages */

int csops(pid_t pid, unsigned int  ops, void * useraddr, size_t usersize);

uint32_t flags;
csops(getpid(), CS_OPS_STATUS, &flags, 0);
if (flags & CS_DEBUGGED){
  //being run either under a debugger or under Electra already
}
unknownbrackets commented 5 years ago

That makes sense. Want to send a PR wrapping the ptrace in that?

Also, @jeeeyul - I'm guessing the animatedExit isn't a big loss, might be good to PR that if it makes Exit more stable too.

-[Unknown]

jeeeyul commented 5 years ago

@coolstar @unknownbrackets I made a PR #11942 for this discussion.

jeeeyul commented 5 years ago

@andyroid1023 @DrConflict The ipa file that I made is singed with my certification. It means that the IPA file can't be executed on other iOS devices except registered test devices. You should have to build it with your own signing identity.

mattesorta commented 5 years ago

@jeeeyul Can you post the .ipa anyway? I can install it with AppSync

devinprater commented 5 years ago

Those who aren’t jailbroken can use Sidia Impactor to install it too, right?

On Mar 30, 2019, at 10:38 AM, mattesorta notifications@github.com wrote:

@jeeeyul https://github.com/jeeeyul Can you post the .ipa anyway? I can install it with AppSync

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/hrydgard/ppsspp/issues/11905#issuecomment-478257042, or mute the thread https://github.com/notifications/unsubscribe-auth/AOjJzjHyPsRWCVjStxINfqM7q5gck0oeks5vb4TtgaJpZM4b4TTt.

andyroid1023 commented 5 years ago

Yeah. You can use Cydia Impactor or ipastore to install the ipa

Halo-Michael commented 5 years ago

At least, I could launch PPSSPP 1.7.1 with W^X JIT on my iOS 12.2 beta device.

  1. Install Xcode 9.4 from here
  2. Launch latest Xcode(for me, it's 10.2 b4)
  3. In Xcode preference, in Locations tab, choose Command Line Tool as Xcode 9.4.1
  4. Quit the Xcode.
  5. Generate xcode project using cmake -DCMAKE_TOOLCHAIN_FILE=./cmake/Toolchains/ios.cmake -DIOS_PLATFORM=OS -H. -Bbuild.ios -GXcode
  6. Open the project with Xcode(10.2 b4).
  7. Change Singing Identity with own.
  8. Build and launch.
  9. Works well.

I will test with latest PPSSPP later and I will tell more.

Are you build for Debug or build for Release?

Halo-Michael commented 5 years ago

At least, I could launch PPSSPP 1.7.1 with W^X JIT on my iOS 12.2 beta device.

  1. Install Xcode 9.4 from here
  2. Launch latest Xcode(for me, it's 10.2 b4)
  3. In Xcode preference, in Locations tab, choose Command Line Tool as Xcode 9.4.1
  4. Quit the Xcode.
  5. Generate xcode project using cmake -DCMAKE_TOOLCHAIN_FILE=./cmake/Toolchains/ios.cmake -DIOS_PLATFORM=OS -H. -Bbuild.ios -GXcode
  6. Open the project with Xcode(10.2 b4).
  7. Change Singing Identity with own.
  8. Build and launch.
  9. Works well.

I will test with latest PPSSPP later and I will tell more.

Thanks! It work for me too!

Halo-Michael commented 5 years ago

So the full step should be like this: 1.Download the newest source git clone https://github.com/hrydgard/ppsspp.git cd ppsspp git submodule update --init --recursive 2.cmake by using iPhoneOS11.4SDK Setting to use Xcode 9.4 Make sure your working directory is ppsspp wget https://github.com/hrydgard/ppsspp/files/3341498/make.txt sh make.txt 3.build by using Final SDK Setting to use Xcode final(for me, it's Xcode 10.1) Make sure your working directory is ppsspp sh make.txt 4.Now you GOT the ipa :)

make.txt

andyroid1023 commented 5 years ago

Do you mind if you could just share the ipa file here? I don’t have a mac to compile 😞

Halo-Michael commented 5 years ago

Do you mind if you could just share the ipa file here? I don’t have a mac to compile 😞

https://github.com/Halo-Michael/PPSSPP-ipas :)

DrConflict commented 5 years ago

Do you mind if you could just share the ipa file here? I don’t have a mac to compile 😞

https://github.com/Halo-Michael/PPSSPP-ipas :)

HUGE thanks for providing the ipa's! Testing them out now. Any idea if a mac version is a possibility as well by any chance? Have you tested it?

Halo-Michael commented 5 years ago

Now that we know that the reason for the abnormal exit bug is to use the SDK of 12.0 or above to build the xcode project, and it will work properly to use the 11.4 SDK to build the xcode project, then I think this problem has changed. “How can I still not have the abnormal exit in the case of building a xcode project with the latest SDK?”

unknownbrackets commented 5 years ago

No, it's crashing on exit because jit is enabled. With iOS SDK 12 it crashes when even trying to use jit.

11942 already applied some changes to try to improve the situation. Apparently it will no longer crash on exit under Electra.

-[Unknown]

unknownbrackets commented 5 years ago

This issue itself is almost a duplicate of #9186 at this point.

I guess the only thing left for this issue is if we can somehow default the CMake file to the proper (older) toolchain. Though that's probably only a shortlived solution. Eventually once phones no longer allow that toolchain, I guess we need to disable jit entirely on iOS again (unless a jailbreak is detected.)

-[Unknown]

personaverygrata commented 5 years ago

Do you mind if you could just share the ipa file here? I don’t have a mac to compile disappointed

https://github.com/Halo-Michael/PPSSPP-ipas :)

hi, I'm a simple user, was happy to test the deb from your repo; unfortunately, while it worked out fine for the evening, this morning ppsspp wouldn't launch until the phone is rebooted, pretty much just as with previous versions. I'm jailbroken with unc0ver 3.0.0-b49 if that's of any help.

devinprater commented 5 years ago

Thanks so much for this. I’ll try to sandboxed version at some point, with Sidia-Impactor.

On Apr 12, 2019, at 1:37 AM, personaverygrata notifications@github.com wrote:

Do you mind if you could just share the ipa file here? I don’t have a mac to compile disappointed

https://github.com/Halo-Michael/PPSSPP-ipas https://github.com/Halo-Michael/PPSSPP-ipas :)

hi, I'm a simple user, was happy to test the deb from your repo; unfortunately, while it worked out fine for the evening, this morning ppsspp wouldn't launch until the phone is rebooted, pretty much just as with previous versions. I'm jailbroken with unc0ver 3.0.0-b49 if that's of any help.

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/hrydgard/ppsspp/issues/11905#issuecomment-482455967, or mute the thread https://github.com/notifications/unsubscribe-auth/AOjJztPXVU8G8zKGGbrgnyNNg21Lotgaks5vgCmPgaJpZM4b4TTt.

personaverygrata commented 5 years ago

Thanks so much for this. I’ll try to sandboxed version at some point, with Sidia-Impactor.

I hope you carefully read what halo-michael wrote on his link... "Please use Appsync to install PPSSPP. Using the signature service to install means that the rights in the main program will be destroyed (get-task-allow and platform-application and unsandbox version exclusive com.apple. Private.security.no-container right), this will cause you will not be able to use jit on iOS12, and the speed of PPSSPP will be affected" If I understood correctly, you might just break JIT if you install it with cydia impactor... hopefully you have a device powerful enough so that you won't care about this...

mattesorta commented 5 years ago

ok latest beta of unc0ver (for me at least) Fix PPSSPP freezing with his 2 new option enabled: get-task-allow and CS_DEBUGGED

Wh0ba commented 5 years ago

By now the syscall Should be removed Cuz it will only cause hanging and problems to users with and without jailbreak Also iPhones are really capable to run psp games without jailbreak using the IR Interpreter

So maybe the maintainers should include iOS releases that native users can use IR interpreter in and the jailbreak users can switch to JIT through the menu

jeeeyul commented 5 years ago

By now the syscall Should be removed Cuz it will only cause hanging and problems to users with and without jailbreak Also iPhones are really capable to run psp games without jailbreak using the IR Interpreter

No, It's not capable enough to iPhone 7 or below models. And IR interpreter is also has some bugs with physics it affects gaming experience, and I think that there are not so many people cares about maintaining IR Interpreter.


I agree with the using syscall is ugly trick to make enable JIT.

syscall trick makes iOS thinks that the PPSSPP is attached by Xcode debugger. It allows JIT. However when users quit PPSSPP manually, iOS will waits signals from Xcode forever.

May be there is another way how to trick iOS or stop tracing, however not found yet.

Wh0ba commented 5 years ago

But since we start the debugger with a syscall Can't we kill it with a syscall ? And put that call in the exit button or in applicationWillTerminate:

Also it seems for me that i can use PPSSPP for the first two times and then when i open it the third time and quit it freezes and turns into the SXs state as shown by ps and htop

jeeeyul commented 5 years ago

But since we start the debugger with a syscall Can't we kill it with a syscall ? And put that call in the exit button or in applicationWillTerminate:

Not that easy.

TRACEME is only one command that can be sent from tracee(PPSSPP). All other PTRACE commands must be triggered by tracer(iOS).

http://man7.org/linux/man-pages/man2/ptrace.2.html

Actually we don't start debugger. Just make iOS think it is under the debug.

Halo-Michael commented 5 years ago

I wrote a simple ppsspp build tool. :P https://github.com/Halo-Michael/ppsspp-builder Hope this will help you.