diff --git a/Resources/iOSEinstein Storyboards-Info.plist b/Resources/iOSEinstein Storyboards-Info.plist
index 39c3197ee..e82080af1 100644
--- a/Resources/iOSEinstein Storyboards-Info.plist
+++ b/Resources/iOSEinstein Storyboards-Info.plist
@@ -8,6 +8,29 @@
iOSEinstein
CFBundleExecutable
iOSEinstein
+ CFBundleDocumentTypes
+
+
+ CFBundleTypeName
+ Newton Package Data
+ LSHandlerRank
+ Owner
+ LSItemContentTypes
+
+ com.newton-inc.pkg
+
+
+
+ CFBundleTypeName
+ Newton ROM Image
+ LSHandlerRank
+ Owner
+ LSItemContentTypes
+
+ com.newton-inc.rom
+
+
+
CFBundleIconFile
CFBundleIdentifier
@@ -31,8 +54,12 @@
LSRequiresIPhoneOS
+ LSSupportsOpeningDocumentsInPlace
+
UIFileSharingEnabled
+ UISupportsDocumentBrowser
+
UILaunchStoryboardName
Launch Screen
UIMainStoryboardFile
@@ -48,5 +75,49 @@
UIInterfaceOrientationLandscapeLeft
UIInterfaceOrientationLandscapeRight
+ UTExportedTypeDeclarations
+
+
+ UTTypeConformsTo
+
+ public.data
+
+ UTTypeDescription
+ Newton Package Data
+ UTTypeIconFiles
+
+ UTTypeIdentifier
+ com.newton-inc.pkg
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ pkg
+ PKG
+ newtonpkg
+
+
+
+
+ UTTypeConformsTo
+
+ public.data
+
+ UTTypeDescription
+ Newton ROM Image
+ UTTypeIconFiles
+
+ UTTypeIdentifier
+ com.newton-inc.rom
+ UTTypeTagSpecification
+
+ public.filename-extension
+
+ rom
+ ROM
+
+
+
+
diff --git a/Resources/iOSEinstein-Info.plist b/Resources/iOSEinstein-Info.plist
index 0402782b1..d944fd345 100644
--- a/Resources/iOSEinstein-Info.plist
+++ b/Resources/iOSEinstein-Info.plist
@@ -33,8 +33,12 @@
MainWindow
NSMainNibFile~ipad
MainWindow_iPad
+ LSSupportsOpeningDocumentsInPlace
+
UIFileSharingEnabled
+ UISupportsDocumentBrowser
+
UIStatusBarHidden
diff --git a/app/iEinstein/Classes/iEinsteinAppDelegate.mm b/app/iEinstein/Classes/iEinsteinAppDelegate.mm
index de89a50d8..5b9703e34 100644
--- a/app/iEinstein/Classes/iEinsteinAppDelegate.mm
+++ b/app/iEinstein/Classes/iEinsteinAppDelegate.mm
@@ -66,6 +66,14 @@ - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(N
[window makeKeyAndVisible];
#endif
+ // Check if app was launched by opening a file
+ NSURL *url = launchOptions[UIApplicationLaunchOptionsURLKey];
+ if (url) {
+ fprintf(stderr, "App launched with URL: %s\n", [[url absoluteString] UTF8String]);
+ // Handle the file immediately before emulator initialization
+ [self handleIncomingFile:url];
+ }
+
NSUserDefaults* prefs = [NSUserDefaults standardUserDefaults];
bool clearFlash = [(NSNumber*) [prefs objectForKey:@"clear_flash_ram"] boolValue];
if (clearFlash)
@@ -88,6 +96,77 @@ - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(N
return YES;
}
+- (void)handleIncomingFile:(NSURL *)url
+{
+ if (![url.scheme isEqualToString:@"file"]) {
+ return;
+ }
+
+ [url startAccessingSecurityScopedResource];
+
+ NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
+ NSString *documentsDirectory = [paths objectAtIndex:0];
+ NSString *srcPath = url.path;
+ NSString *filename = [srcPath lastPathComponent];
+ NSString *dstPath = [documentsDirectory stringByAppendingPathComponent:filename];
+ NSError *error = nil;
+
+ // Determine file type
+ NSString *fileExtension = [[filename pathExtension] lowercaseString];
+ BOOL isROMFile = [fileExtension isEqualToString:@"rom"];
+ BOOL isPkgFile = [fileExtension isEqualToString:@"pkg"] || [fileExtension isEqualToString:@"newtonpkg"];
+
+ if(![srcPath isEqualToString:dstPath]) {
+ if ([[NSFileManager defaultManager] fileExistsAtPath:dstPath]) {
+ [[NSFileManager defaultManager] removeItemAtPath:dstPath error:&error];
+ if(error){
+ NSLog(@"%@ %ld %@",[error domain],(long)[error code],[[error userInfo] description]);
+ }
+ else{
+ NSLog(@"File removed.");
+ }
+ }
+ [[NSFileManager defaultManager] copyItemAtPath:srcPath toPath:dstPath error:&error];
+ }
+
+ if(error){
+ NSLog(@"%@ %ld %@",[error domain],(long)[error code],[[error userInfo] description]);
+ }
+ else if (isPkgFile) {
+ NSLog(@"Pkg File copied.");
+ [viewController installNewPackages];
+
+ // Remove the pkg file after installation
+ [[NSFileManager defaultManager] removeItemAtPath:dstPath error:&error];
+ if(error){
+ NSLog(@"%@ %ld %@",[error domain],(long)[error code],[[error userInfo] description]);
+ }
+ else{
+ NSLog(@"Installed Pkg file removed.");
+ }
+ }
+ else if (isROMFile) {
+ NSLog(@"ROM File copied to Documents directory: %@", filename);
+ // Dismiss the "missing ROM" action sheet if it's showing and restart the emulator
+ [viewController checkForROMImage];
+ }
+
+ [url stopAccessingSecurityScopedResource];
+}
+
+- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary *)options
+{
+ if ([url.scheme isEqualToString:@"file"]) {
+ [self handleIncomingFile:url];
+ return YES;
+ }
+ else {
+ [[UIApplication sharedApplication] openURL:url options:options completionHandler:nil];
+ return YES;
+ }
+ return NO;
+}
+
- (void)applicationWillResignActive:(UIApplication*)application
{
[viewController stopEmulator];
@@ -95,6 +174,10 @@ - (void)applicationWillResignActive:(UIApplication*)application
- (void)applicationDidBecomeActive:(UIApplication*)application
{
+ // Check if ROM was added while app was in background
+ // This will dismiss the missing ROM sheet if ROM is now available
+ [viewController checkForROMImage];
+
if (![viewController allResourcesFound])
return;
diff --git a/app/iEinstein/Classes/iEinsteinViewController.h b/app/iEinstein/Classes/iEinsteinViewController.h
index 957abd6ac..c0781af7c 100644
--- a/app/iEinstein/Classes/iEinsteinViewController.h
+++ b/app/iEinstein/Classes/iEinsteinViewController.h
@@ -47,6 +47,7 @@ class TLog;
TPlatformManager* mPlatformManager;
TLog* mLog;
int lastKnownScreenResolution;
+ UIAlertView* mMissingROMAlertView;
}
@property (retain, nonatomic) IBOutlet iEinsteinView* einsteinView;
@@ -95,6 +96,7 @@ class TLog;
- (void)verifyDeleteFlashRAM:(int)withTag;
- (void)explainMissingROM;
+- (BOOL)checkForROMImage;
//- (void)openEinsteinMenu;
- (int)allResourcesFound;
diff --git a/app/iEinstein/Classes/iEinsteinViewController.mm b/app/iEinstein/Classes/iEinsteinViewController.mm
index 9acc50054..aff854fc2 100644
--- a/app/iEinstein/Classes/iEinsteinViewController.mm
+++ b/app/iEinstein/Classes/iEinsteinViewController.mm
@@ -54,6 +54,11 @@ - (void)viewDidAppear:(BOOL)animated
[super viewDidAppear:animated];
}
+- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+ [[UIApplication sharedApplication] performSelector:@selector(terminateWithSuccess)];
+}
+
+
// Action sheet delegate method.
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
@@ -90,9 +95,6 @@ - (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)
break;
}
break;
- case 3:
- [[UIApplication sharedApplication] performSelector:@selector(terminateWithSuccess)];
- break;
default:
break;
}
@@ -118,22 +120,125 @@ - (void)verifyDeleteFlashRAM:(int)withTag;
- (void)explainMissingROM:(id)sender
{
- UIActionSheet* actionSheet = [[UIActionSheet alloc]
- initWithTitle:@"Newton ROM not found.\r\r"
- "Einstein Emulator requires an MP2x00 US ROM image. "
- "The ROM file must be named 717006.rom and copied to "
- "this device using the iTunes File Sharing feature.\r\r"
- "For more information please read the instructions at "
- "https://github.com/pguyot/Einstein/wiki/Build-Instructions"
- delegate:self
- cancelButtonTitle:nil
- destructiveButtonTitle:@"Quit Einstein"
- otherButtonTitles:nil];
- [actionSheet setTag:3];
- [actionSheet showInView:self.view];
+ NSString *message =
+ @"Einstein Emulator requires an MP2x00 US ROM image. "
+ "The ROM file must be named 717006.rom and copied to this device "
+ "using the Files app or the iOS share sheet.\n\n"
+ "For more information please read the instructions at "
+ "https://github.com/pguyot/Einstein/wiki/Build-Instructions";
+
+ mMissingROMAlertView = [[UIAlertView alloc]
+ initWithTitle:@"Newton ROM not found!" message:message delegate:self cancelButtonTitle:nil otherButtonTitles:@"Quit Einstein", nil];
+ [mMissingROMAlertView show];
+}
+
+- (void)dismissMissingROMAlertAndReset
+{
+ if (mMissingROMAlertView) {
+ [mMissingROMAlertView dismissWithClickedButtonIndex:-1 animated:YES];
#if !__has_feature(objc_arc)
- [actionSheet release];
+ [mMissingROMAlertView release];
+#endif
+ mMissingROMAlertView = nil;
+
+ // Reset the emulator now that we have a ROM
+ [self resetEmulator];
+ }
+}
+
+- (TROMImage*)loadROMImage
+{
+ // Create the ROM.
+ TROMImage* romImage = nil;
+ NSString* einsteinRExPath = nil;
+ NSBundle* thisBundle = [NSBundle mainBundle];
+
+ if (!(einsteinRExPath = [thisBundle pathForResource:@"Einstein" ofType:@"rex"]))
+ {
+ //[self abortWithMessage: @"Couldn't load Einstein REX"];
+ mLog->LogLine("Couldn't load Einstein REX");
+ return nil;
+ }
+
+ NSString* docdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
+
+ NSString* theROMPath = [docdir stringByAppendingPathComponent:@"717006.rom"];
+ NSString* theDebugROMPath = [docdir stringByAppendingPathComponent:@"717006.aif"];
+ NSString* theDebugHighROMPath = [docdir stringByAppendingPathComponent:@"717006.rex"];
+ NSString* theImagePath = [docdir stringByAppendingPathComponent:@"717006.img"];
+
+ NSFileManager* theFileManager = [NSFileManager defaultManager];
+
+ if ([theFileManager fileExistsAtPath:theROMPath])
+ {
+#if 0
+ romImage = new TFlatROMImageWithREX(
+ [theROMPath fileSystemRepresentation],
+ [einsteinRExPath fileSystemRepresentation],
+ "717006", false,
+ [theImagePath fileSystemRepresentation]);
+#else
+ romImage = new TFlatROMImageWithREX(
+ [theROMPath fileSystemRepresentation],
+ [einsteinRExPath fileSystemRepresentation]);
+#endif
+ } else if ([theFileManager fileExistsAtPath:theDebugROMPath]
+ && [theFileManager fileExistsAtPath:theDebugHighROMPath])
+ {
+#if 0
+ romImage = new TAIFROMImageWithREXes(
+ [theDebugROMPath fileSystemRepresentation],
+ [theDebugHighROMPath fileSystemRepresentation],
+ [einsteinRExPath fileSystemRepresentation],
+ "717006" );
+#else
+ romImage = new TAIFROMImageWithREXes(
+ [theDebugROMPath fileSystemRepresentation],
+ [theDebugHighROMPath fileSystemRepresentation],
+ [einsteinRExPath fileSystemRepresentation]);
#endif
+ }
+
+ NSString* theTempFilePath = [docdir stringByAppendingPathComponent:@"INSTALL ROM HERE.txt"];
+ if (romImage) {
+ // Remove the temporary file to make the Documents folder appear in the Files app
+ if([theFileManager fileExistsAtPath:theTempFilePath]) {
+ [theFileManager removeItemAtPath:theTempFilePath error:nil];
+ }
+ // Return the ROM image
+ return romImage;
+ } else {
+ // Add a temporary file to make the Documents folder appear in the Files app
+ if(![theFileManager fileExistsAtPath:theTempFilePath]) {
+ [theFileManager createFileAtPath:theTempFilePath contents:nil attributes:nil];
+ }
+ // Print a log message with the ROM location esp. for emulator users
+ fprintf(stderr, "ROM file required here:\n %s\nor here:\n %s\n %s\n\n",
+ [theROMPath fileSystemRepresentation],
+ [theDebugROMPath fileSystemRepresentation],
+ [theDebugHighROMPath fileSystemRepresentation]);
+ }
+ return nil;
+}
+
+- (BOOL)checkForROMImage
+{
+ // If we have a ROM already, do nothing
+ if (mROMImage) {
+ return YES;
+ }
+
+ // Try loading the ROM
+ mROMImage = [self loadROMImage];
+ if (mROMImage) {
+ if (mMissingROMAlertView) {
+ // ROM now exists and action sheet is showing - dismiss it and reset
+ [self dismissMissingROMAlertAndReset];
+ }
+ return YES;
+ }
+
+ return NO;
}
//- (void)setNeedsDisplayInNewtonRect:(NSValue*)v
@@ -207,7 +312,7 @@ - (void)dealloc
delete mSoundManager;
mSoundManager = NULL;
}
-
+
delete mPrinterManager;
mPrinterManager = NULL;
@@ -252,62 +357,10 @@ - (int)initEmulator
mLog = new TStdOutLog();
//#endif
- NSString* docdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
-
- // Create the ROM.
-
- NSString* einsteinRExPath = nil;
- NSBundle* thisBundle = [NSBundle mainBundle];
-
- if (!(einsteinRExPath = [thisBundle pathForResource:@"Einstein" ofType:@"rex"]))
- {
- //[self abortWithMessage: @"Couldn't load Einstein REX"];
- mLog->LogLine("Couldn't load Einstein REX");
- return 0;
- }
-
- NSString* theROMPath = [docdir stringByAppendingPathComponent:@"717006.rom"];
- NSString* theDebugROMPath = [docdir stringByAppendingPathComponent:@"717006.aif"];
- NSString* theDebugHighROMPath = [docdir stringByAppendingPathComponent:@"717006.rex"];
- NSString* theImagePath = [docdir stringByAppendingPathComponent:@"717006.img"];
-
- NSFileManager* theFileManager = [NSFileManager defaultManager];
-
- if ([theFileManager fileExistsAtPath:theROMPath])
+ // Load the ROM
+ mROMImage = [self loadROMImage];
+ if (!mROMImage)
{
-#if 0
- mROMImage = new TFlatROMImageWithREX(
- [theROMPath fileSystemRepresentation],
- [einsteinRExPath fileSystemRepresentation],
- "717006", false,
- [theImagePath fileSystemRepresentation]);
-#else
- mROMImage = new TFlatROMImageWithREX(
- [theROMPath fileSystemRepresentation],
- [einsteinRExPath fileSystemRepresentation]);
-#endif
- } else if ([theFileManager fileExistsAtPath:theDebugROMPath]
- && [theFileManager fileExistsAtPath:theDebugHighROMPath])
- {
-#if 0
- mROMImage = new TAIFROMImageWithREXes(
- [theDebugROMPath fileSystemRepresentation],
- [theDebugHighROMPath fileSystemRepresentation],
- [einsteinRExPath fileSystemRepresentation],
- "717006" );
-#else
- mROMImage = new TAIFROMImageWithREXes(
- [theDebugROMPath fileSystemRepresentation],
- [theDebugHighROMPath fileSystemRepresentation],
- [einsteinRExPath fileSystemRepresentation]);
-#endif
- } else
- {
- fprintf(stderr, "ROM file required here:\n %s\nor here:\n %s\n %s\n\n",
- [theROMPath fileSystemRepresentation],
- [theDebugROMPath fileSystemRepresentation],
- [theDebugHighROMPath fileSystemRepresentation]);
-
// Defer this call to explainMissingROM because self.view is not in the
// visible view hierarchy yet. (We arrive here from viewWillAppear due to
// other order-of-operations issues -- see issue #31)
@@ -361,7 +414,7 @@ - (int)initEmulator
mPrinterManager = new TIOSPrinterManager(mLog);
// Create the emulator.
-
+ NSString* docdir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString* theFlashPath = [docdir stringByAppendingPathComponent:@"flash"];
printf("Flash file is %s\n", [theFlashPath fileSystemRepresentation]);