diff --git a/Makefile b/Makefile index 761b825..88898f5 100644 --- a/Makefile +++ b/Makefile @@ -186,7 +186,9 @@ endif CFLAGS += -arch arm64 -miphoneos-version-min=11.0 -isysroot $(SYSROOT) -IAppleCommon LDFLAGS += -arch arm64 OCFLAGS += -x objective-c -fobjc-arc -Wno-deprecated-declarations -isysroot $(SYSROOT) -LDFLAGS += -lobjc -framework UIKit -framework Foundation -framework CoreGraphics -framework Metal -framework MetalKit -framework AudioToolbox -framework AVFoundation -framework QuartzCore -framework CoreMotion -framework CoreVideo -framework CoreMedia -framework CoreImage -weak_framework CoreHaptics -miphoneos-version-min=11.0 -isysroot $(SYSROOT) +LDFLAGS += -miphoneos-version-min=11.0 -isysroot $(SYSROOT) +REREGISTER_LDFLAGS := $(LDFLAGS) -lobjc -framework CoreServices -framework Foundation +LDFLAGS += -lobjc -framework UIKit -framework Foundation -framework CoreGraphics -framework Metal -framework MetalKit -framework AudioToolbox -framework AVFoundation -framework QuartzCore -framework CoreMotion -framework CoreVideo -framework CoreMedia -framework CoreImage -weak_framework CoreHaptics CODESIGN := codesign -fs - else ifeq ($(PLATFORM),Darwin) @@ -247,7 +249,9 @@ quicklook: $(BIN)/SameBoy.qlgenerator sdl: $(SDL_TARGET) $(BIN)/SDL/dmg_boot.bin $(BIN)/SDL/mgb_boot.bin $(BIN)/SDL/cgb0_boot.bin $(BIN)/SDL/cgb_boot.bin $(BIN)/SDL/agb_boot.bin $(BIN)/SDL/sgb_boot.bin $(BIN)/SDL/sgb2_boot.bin $(BIN)/SDL/LICENSE $(BIN)/SDL/registers.sym $(BIN)/SDL/background.bmp $(BIN)/SDL/Shaders $(BIN)/SDL/Palettes bootroms: $(BIN)/BootROMs/agb_boot.bin $(BIN)/BootROMs/cgb_boot.bin $(BIN)/BootROMs/cgb0_boot.bin $(BIN)/BootROMs/dmg_boot.bin $(BIN)/BootROMs/mgb_boot.bin $(BIN)/BootROMs/sgb_boot.bin $(BIN)/BootROMs/sgb2_boot.bin tester: $(TESTER_TARGET) $(BIN)/tester/dmg_boot.bin $(BIN)/tester/cgb_boot.bin $(BIN)/tester/agb_boot.bin $(BIN)/tester/sgb_boot.bin $(BIN)/tester/sgb2_boot.bin -_ios: $(BIN)/SameBoy-iOS.app +_ios: $(BIN)/SameBoy-iOS.app $(OBJ)/reregister +ios-ipa: $(BIN)/SameBoy-iOS.ipa +ios-deb: $(BIN)/SameBoy-iOS.deb all: cocoa sdl tester libretro # Get a list of our source files and their respective object file targets @@ -255,7 +259,7 @@ all: cocoa sdl tester libretro CORE_SOURCES := $(shell ls Core/*.c) SDL_SOURCES := $(shell ls SDL/*.c) $(OPEN_DIALOG) $(patsubst %,SDL/audio/%.c,$(SDL_AUDIO_DRIVERS)) TESTER_SOURCES := $(shell ls Tester/*.c) -IOS_SOURCES := $(shell ls iOS/*.m) $(shell ls AppleCommon/*.m) +IOS_SOURCES := $(filter-out iOS/reregister.m, $(shell ls iOS/*.m)) $(shell ls AppleCommon/*.m) COCOA_SOURCES := $(shell ls Cocoa/*.m) $(shell ls HexFiend/*.m) $(shell ls JoyKit/*.m) $(shell ls AppleCommon/*.m) QUICKLOOK_SOURCES := $(shell ls QuickLook/*.m) $(shell ls QuickLook/*.c) @@ -272,7 +276,7 @@ TESTER_OBJECTS := $(patsubst %,$(OBJ)/%.o,$(TESTER_SOURCES)) # Automatic dependency generation -ifneq ($(filter-out ios clean bootroms libretro %.bin, $(MAKECMDGOALS)),) +ifneq ($(filter-out ios ios-ipa ios-dev clean bootroms libretro %.bin, $(MAKECMDGOALS)),) -include $(CORE_OBJECTS:.o=.dep) ifneq ($(filter $(MAKECMDGOALS),sdl),) -include $(SDL_OBJECTS:.o=.dep) @@ -357,6 +361,9 @@ ifeq ($(CONF), release) $(STRIP) $@ endif +$(OBJ)/reregister: iOS/reregister.m + $(CC) $< -o $@ $(REREGISTER_LDFLAGS) $(CFLAGS) + # Cocoa Port $(BIN)/SameBoy.app: $(BIN)/SameBoy.app/Contents/MacOS/SameBoy \ @@ -587,7 +594,37 @@ endif ios: @$(MAKE) _ios + +$(BIN)/SameBoy-iOS.ipa: ios + $(MKDIR) -p $(OBJ)/Payload + cp -rf $(BIN)/SameBoy-iOS.app $(OBJ)/Payload/SameBoy-iOS.app + (cd $(OBJ) && zip $(abspath $@) -r Payload) + rm -rf $(OBJ)/Payload + +$(BIN)/SameBoy-iOS.deb: $(OBJ)/debian-binary $(OBJ)/control.tar.gz $(OBJ)/data.tar.gz + -@$(MKDIR) -p $(dir $@) + (cd $(OBJ) && ar cr $(abspath $@) $(notdir $^)) + +$(OBJ)/data.tar.gz: ios iOS/jailbreak.entitlements + $(MKDIR) -p $(OBJ)/Applications + cp -rf $(BIN)/SameBoy-iOS.app $(OBJ)/Applications/SameBoy-iOS.app + cp build/obj-ios/reregister iOS/reregister.entitlements $(OBJ)/Applications/SameBoy-iOS.app + codesign -fs - --entitlements iOS/jailbreak.entitlements $(OBJ)/Applications/SameBoy-iOS.app + (cd $(OBJ) && tar -czf $(abspath $@) ./Applications) + rm -rf $(OBJ)/Applications + +$(OBJ)/control.tar.gz: iOS/deb-postinst iOS/deb-control + -@$(MKDIR) -p $(dir $@) + sed "s/@VERSION/$(VERSION)/" < iOS/deb-control > $(OBJ)/control + ln iOS/deb-postinst $(OBJ)/postinst + (cd $(OBJ) && tar -czf $(abspath $@) ./control ./postinst) + rm $(OBJ)/control $(OBJ)/postinst + +$(OBJ)/debian-binary: + -@$(MKDIR) -p $(dir $@) + echo 2.0 > $@ + # Clean clean: rm -rf build diff --git a/iOS/deb-control b/iOS/deb-control new file mode 100644 index 0000000..7f3002e --- /dev/null +++ b/iOS/deb-control @@ -0,0 +1,10 @@ +Package: com.github.liji32.sameboy.ios +Name: SameBoy +Depends: firmware (>= 11.0) +Architecture: iphoneos-arm +Description: A Game Boy emulator for iOS +Maintainer: Lior Halphon +Author: Lior Halphon +Section: Games +Icon: file:///Applications/SameBoy-iOS.app/AppIcon60x60@2x.png +Version: @VERSION diff --git a/iOS/deb-postinst b/iOS/deb-postinst new file mode 100755 index 0000000..7581cbd --- /dev/null +++ b/iOS/deb-postinst @@ -0,0 +1,3 @@ +#!/bin/bash +ldid -S/Applications/SameBoy-iOS.app/reregister.entitlements /Applications/SameBoy-iOS.app/reregister +/Applications/SameBoy-iOS.app/reregister diff --git a/iOS/jailbreak.entitlements b/iOS/jailbreak.entitlements new file mode 100644 index 0000000..ce0a662 --- /dev/null +++ b/iOS/jailbreak.entitlements @@ -0,0 +1,8 @@ + + + + +com.apple.private.security.container-required + + + \ No newline at end of file diff --git a/iOS/main.m b/iOS/main.m index 75c516d..793390e 100644 --- a/iOS/main.m +++ b/iOS/main.m @@ -1,7 +1,7 @@ #import -#import "GBViewController.h" #include -#include "GBView.h" +#import "GBViewController.h" +#import "GBView.h" int main(int argc, char * argv[]) { diff --git a/iOS/reregister.entitlements b/iOS/reregister.entitlements new file mode 100644 index 0000000..c1ed56b --- /dev/null +++ b/iOS/reregister.entitlements @@ -0,0 +1,19 @@ + + + + +com.apple.private.mobileinstall.allowedSPI + + InstallForLaunchServices + UninstallForLaunchServices + +com.apple.lsapplicationworkspace.rebuildappdatabases + +com.apple.private.MobileContainerManager.allowed + +com.apple.frontboard.launchapplications + +platform-application + + + \ No newline at end of file diff --git a/iOS/reregister.m b/iOS/reregister.m new file mode 100644 index 0000000..49885ba --- /dev/null +++ b/iOS/reregister.m @@ -0,0 +1,54 @@ +#import +#import +#import + +@interface LSApplicationProxy : NSObject +@property (nonatomic, readonly, getter=isContainerized) bool containerized; +@property (nonatomic, readonly) NSString *bundleIdentifier; +@end + +@interface LSApplicationWorkspace : NSObject ++ (instancetype)defaultWorkspace; +- (NSArray *)allInstalledApplications; +- (bool)unregisterApplication:(NSURL *)url; +- (bool)registerApplicationDictionary:(NSDictionary *)dict; +@end + +@interface MCMAppDataContainer : NSObject ++ (MCMAppDataContainer *)containerWithIdentifier:(NSString *)identifier + createIfNecessary:(bool)create + existed:(bool *)existed + error:(NSError **)error; +@property(readonly, nonatomic) NSURL *url; +@end + + +int main(void) +{ + // Make sure MobileContainerManager is loaded + if (!dlopen("/System/Library/PrivateFrameworks/MobileContainerManager.framework/MobileContainerManager", RTLD_NOW)) return 1; + for (LSApplicationProxy *app in [[LSApplicationWorkspace defaultWorkspace] allInstalledApplications]) { + if (![app.bundleIdentifier isEqualToString:[NSBundle mainBundle].bundleIdentifier]) continue; + if (app.containerized) return 0; // Everything's fine, no need to reregister + // We're registered but not containerized, unregister ourselves first + if (![[LSApplicationWorkspace defaultWorkspace] unregisterApplication:[NSBundle mainBundle].bundleURL]) return 1; + + break; + } + + NSString *container = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:[NSBundle mainBundle].bundleIdentifier + createIfNecessary:true + existed:nil + error:nil].url.path; + + return ![[LSApplicationWorkspace defaultWorkspace] registerApplicationDictionary:@{ + @"ApplicationType": @"System", + @"CFBundleIdentifier": [NSBundle mainBundle].bundleIdentifier, + @"CompatibilityState": @NO, + @"Container": container, + @"IsDeletable": @NO, + @"Path": [NSBundle mainBundle].bundlePath, + @"_LSBundlePlugins": @{}, + @"IsContainerized": @YES, + }]; +}