allow changing emulated machine without relaunching the app

This commit is contained in:
Jesús A. Álvarez 2020-09-25 00:29:30 +02:00
parent af3b2ba5b1
commit fd665a1761
12 changed files with 83 additions and 42 deletions

View File

@ -21,9 +21,11 @@ extern NSString *DocumentsChangedNotification;
@property (nonatomic, readonly) NSArray<NSBundle*> *emulatorBundles;
@property (nonatomic, readonly) NSString *emulatorBundlesPath;
@property (readonly, nonatomic, getter = isSandboxed) BOOL sandboxed;
@property (readonly, nonatomic) id<Emulator> sharedEmulator;
+ (instancetype)sharedInstance;
+ (id<Emulator>)sharedEmulator;
- (void)reloadEmulator;
- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message;
- (IBAction)showInsertDisk:(id)sender;

View File

@ -108,6 +108,24 @@ NSString *DocumentsChangedNotification = @"documentsChanged";
return sharedEmulator != nil;
}
- (void)reloadEmulator {
NSBundle *bundle = sharedEmulator.bundle;
[self willChangeValueForKey:@"sharedEmulator"];
id<Emulator> oldEmulator = sharedEmulator;
sharedEmulator = nil;
[oldEmulator shutdown];
[bundle unload];
if (![self loadEmulator:[[NSUserDefaults standardUserDefaults] stringForKey:@"machine"]]) {
[self loadEmulator:@"MacPlus4M"];
}
[self didChangeValueForKey:@"sharedEmulator"];
[sharedEmulator performSelector:@selector(run) withObject:nil afterDelay:0.1];
}
- (id<Emulator>)sharedEmulator {
return sharedEmulator;
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults synchronize];

View File

@ -38,11 +38,10 @@ typedef enum : NSInteger {
@property (nonatomic, readonly) BOOL anyDiskInserted;
@property (nonatomic, readonly) NSString *currentApplication;
+ (instancetype)sharedEmulator;
- (void)run;
- (void)reset;
- (void)interrupt;
- (void)shutdown;
- (void)keyDown:(int)scancode;
- (void)keyUp:(int)scancode;

View File

@ -36,14 +36,14 @@ EXPORTVAR(ui3p, RAM)
EXPORTVAR(ui3p, VidROM)
EXPORTVAR(ui3p, VidMem)
@interface Emulator : NSObject <Emulator, UIAlertViewDelegate>
@interface MNVMBundleClassName : NSObject <Emulator, UIAlertViewDelegate>
- (void)makeNewDisk:(NSString*)name size:(NSInteger)size;
- (void)updateScreen:(CGImageRef)screenImage;
@end
static Emulator *sharedEmulator = nil;
static __weak MNVMBundleClassName *sharedEmulator = nil;
#pragma mark - some simple utilities
@ -405,7 +405,7 @@ LOCALFUNC tMacErr vSonyEject0(tDrive Drive_No, blnr deleteit) {
}
#endif
[[NSNotificationCenter defaultCenter] postNotificationName:[Emulator sharedEmulator].ejectDiskNotification object:[Emulator sharedEmulator] userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotificationName:sharedEmulator.ejectDiskNotification object:sharedEmulator userInfo:userInfo];
return mnvm_noErr;
}
@ -455,7 +455,7 @@ LOCALFUNC blnr Sony_Insert0(FILE *refnum, blnr locked, NSString *filePath) {
} else {
NSDictionary *userInfo = @{@"path": filePath,
@"drive": @(Drive_No)};
[[NSNotificationCenter defaultCenter] postNotificationName:[Emulator sharedEmulator].insertDiskNotification object:[Emulator sharedEmulator] userInfo:userInfo];
[[NSNotificationCenter defaultCenter] postNotificationName:sharedEmulator.insertDiskNotification object:sharedEmulator userInfo:userInfo];
/* printf("Sony_Insert0 %d\n", (int)Drive_No); */
@ -787,7 +787,7 @@ LOCALPROC HaveChangedScreenBuff(ui4r top, ui4r left, ui4r bottom, ui4r right) {
if (colorSpace) {
CGImageRef screenImage = CGImageCreate(vMacScreenWidth, vMacScreenHeight, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpace, options, screenDataProvider, NULL, false, kCGRenderingIntentDefault);
[[Emulator sharedEmulator] updateScreen:screenImage];
[sharedEmulator updateScreen:screenImage];
CGImageRelease(screenImage);
}
}
@ -1644,31 +1644,24 @@ GLOBALPROC WaitForNextTick(void) {
#pragma mark - Objective-C Interface
static dispatch_once_t onceToken;
@implementation Emulator
@implementation MNVMBundleClassName
{
__block __weak UITextField *nameTextField;
}
@synthesize dataPath;
+ (instancetype)sharedEmulator {
dispatch_once(&onceToken, ^{
sharedEmulator = [self new];
});
return sharedEmulator;
}
- (instancetype)init {
if ((self = [super init])) {
dispatch_once(&onceToken, ^{
sharedEmulator = self;
});
sharedEmulator = self;
}
return self;
}
- (void)shutdown {
RequestMacOff = trueblnr;
}
- (void)run {
ZapOSGLUVars();
if (InitOSGLU()) {

View File

@ -39,6 +39,8 @@
#define AutoLocation 1
#define AutoTimeZone 1
#define MNVMBundleClassName Mac128KEmulator
#ifdef PLIST_PREPROCESSOR
#define MNVMBundleDisplayName Mac 128K
#define MNVMBundleGetInfoString 128K, 512×342

View File

@ -39,6 +39,8 @@
#define AutoLocation 1
#define AutoTimeZone 1
#define MNVMBundleClassName MacIIEmulator640x480
#ifdef PLIST_PREPROCESSOR
#define MNVMBundleDisplayName Mac II
#define MNVMBundleGetInfoString 8M, 640×480

View File

@ -39,6 +39,8 @@
#define AutoLocation 1
#define AutoTimeZone 1
#define MNVMBundleClassName MacIIEmulator
#ifdef PLIST_PREPROCESSOR
#define MNVMBundleDisplayName Mac II
#define MNVMBundleGetInfoString 8M, 1024×768

View File

@ -40,6 +40,8 @@
#define AutoLocation 1
#define AutoTimeZone 1
#define MNVMBundleClassName MacPlus4MEmulator
#ifdef PLIST_PREPROCESSOR
#define MNVMBundleDisplayName Mac Plus
#define MNVMBundleGetInfoString 4M, 512×342

View File

@ -25,6 +25,6 @@
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string>Emulator</string>
<string>MNVMBundleClassName</string>
</dict>
</plist>

View File

@ -26,13 +26,9 @@ static ScreenView *sharedScreenView = nil;
NSString *screenFilter = [[NSUserDefaults standardUserDefaults] stringForKey:@"screenFilter"];
videoLayer.magnificationFilter = screenFilter;
videoLayer.minificationFilter = screenFilter;
[AppDelegate sharedEmulator].screenLayer = videoLayer;
if ([AppDelegate sharedEmulator]) {
screenSize = [AppDelegate sharedEmulator].screenSize;
} else {
screenSize = CGSizeMake(1, 1);
}
[self updateVideoLayer];
[self.layer addSublayer:videoLayer];
[[AppDelegate sharedInstance] addObserver:self forKeyPath:@"sharedEmulator" options:NSKeyValueObservingOptionNew context:NULL];
[[NSUserDefaults standardUserDefaults] addObserver:self forKeyPath:@"screenFilter" options:NSKeyValueObservingOptionNew context:NULL];
}
@ -48,6 +44,15 @@ static ScreenView *sharedScreenView = nil;
return screenSize;
}
- (void)updateVideoLayer {
if ([AppDelegate sharedEmulator]) {
[AppDelegate sharedEmulator].screenLayer = videoLayer;
screenSize = [AppDelegate sharedEmulator].screenSize;
} else {
screenSize = CGSizeMake(1, 1);
}
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect viewBounds = self.bounds;
@ -73,10 +78,14 @@ static ScreenView *sharedScreenView = nil;
videoLayer.magnificationFilter = value;
videoLayer.minificationFilter = value;
}
} else if (object == [AppDelegate sharedInstance] && [keyPath isEqualToString:@"sharedEmulator"]) {
[self updateVideoLayer];
[self layoutSubviews];
}
}
- (void)dealloc {
[[NSUserDefaults standardUserDefaults] removeObserver:self forKeyPath:@"screenFilter" context:NULL];
}
@end

View File

@ -108,6 +108,9 @@ typedef enum : NSInteger {
- (void)viewWillDisappear:(BOOL)animated {
[super viewWillDisappear:animated];
[AppDelegate sharedEmulator].running = YES;
if (![selectedEmulatorBundle isEqual:[AppDelegate sharedEmulator].bundle] && ![AppDelegate sharedEmulator].anyDiskInserted) {
[[AppDelegate sharedInstance] reloadEmulator];
}
}
- (void)showInsertDisk:(id)sender {
@ -209,8 +212,8 @@ typedef enum : NSInteger {
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section {
if (section == SettingsSectionSpeed) {
return NSLocalizedString(@"Faster speeds and running in background drain the battery faster", nil);
} else if (section == SettingsSectionMachine) {
return NSLocalizedString(@"Changing the emulated machine requires to relaunch Mini vMac", nil);
} else if (section == SettingsSectionMachine && [AppDelegate sharedEmulator].anyDiskInserted) {
return NSLocalizedString(@"The emulated machine cannot be changed while disks are inserted.", nil);
} else {
return nil;
}
@ -328,6 +331,13 @@ typedef enum : NSInteger {
return cell;
}
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if (indexPath.section == SettingsSectionMachine && [AppDelegate sharedEmulator].anyDiskInserted) {
return nil;
}
return indexPath;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[tableView deselectRowAtIndexPath:indexPath animated:YES];

View File

@ -208,19 +208,21 @@ API_AVAILABLE(ios(13.4))
}
- (void)emulatorDidShutDown:(NSNotification*)notification {
UILabel *shutdownLabel = [[UILabel alloc] initWithFrame:self.view.bounds];
shutdownLabel.text = NSLocalizedString(@"the emulated Mac has shut down\ntap to restart", nil);
shutdownLabel.textColor = [UIColor whiteColor];
[self.view addSubview:shutdownLabel];
shutdownLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[shutdownLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(restartEmulator:)]];
shutdownLabel.numberOfLines = -1;
shutdownLabel.textAlignment = NSTextAlignmentCenter;
shutdownLabel.userInteractionEnabled = YES;
[UIView animateWithDuration:0.5 animations:^{
self.screenView.alpha = 0.5;
}];
[self hideKeyboard:notification];
if (notification.object == [AppDelegate sharedEmulator]) {
UILabel *shutdownLabel = [[UILabel alloc] initWithFrame:self.view.bounds];
shutdownLabel.text = NSLocalizedString(@"the emulated Mac has shut down\ntap to restart", nil);
shutdownLabel.textColor = [UIColor whiteColor];
[self.view addSubview:shutdownLabel];
shutdownLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
[shutdownLabel addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(restartEmulator:)]];
shutdownLabel.numberOfLines = -1;
shutdownLabel.textAlignment = NSTextAlignmentCenter;
shutdownLabel.userInteractionEnabled = YES;
[UIView animateWithDuration:0.5 animations:^{
self.screenView.alpha = 0.5;
}];
[self hideKeyboard:notification];
}
}
- (void)restartEmulator:(UITapGestureRecognizer*)gestureRecognizer {