From 51a7c207a645258e998492db8acdf5aeda63230b Mon Sep 17 00:00:00 2001 From: Michael Buckley Date: Sat, 25 Mar 2023 13:58:25 -0700 Subject: [PATCH] Mac: Restore Open MultiCart feature --- macosx/Snes9x/AppDelegate.m | 70 ++- macosx/Snes9x/Base.lproj/MainMenu.xib | 13 +- macosx/Snes9x/S9xOpenMultipleViewController.h | 21 + macosx/Snes9x/S9xOpenMultipleViewController.m | 113 ++++ .../Snes9x/S9xOpenMultipleViewController.xib | 127 ++++ macosx/mac-multicart.h | 29 - macosx/mac-multicart.mm | 540 ------------------ macosx/mac-os.h | 2 +- macosx/mac-os.mm | 43 +- macosx/mac-snes9x.h | 2 +- macosx/mac-snes9x.mm | 26 +- macosx/snes9x.xcodeproj/project.pbxproj | 16 +- 12 files changed, 374 insertions(+), 628 deletions(-) create mode 100644 macosx/Snes9x/S9xOpenMultipleViewController.h create mode 100644 macosx/Snes9x/S9xOpenMultipleViewController.m create mode 100644 macosx/Snes9x/S9xOpenMultipleViewController.xib delete mode 100644 macosx/mac-multicart.h delete mode 100644 macosx/mac-multicart.mm diff --git a/macosx/Snes9x/AppDelegate.m b/macosx/Snes9x/AppDelegate.m index f636eb31..0e26d5a4 100644 --- a/macosx/Snes9x/AppDelegate.m +++ b/macosx/Snes9x/AppDelegate.m @@ -22,6 +22,7 @@ #import "AppDelegate.h" #import "S9xPreferencesConstants.h" #import "S9xCheatFinderViewController.h" +#import "S9xOpenMultipleViewController.h" NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow"; NSWindowFrameAutosaveName const kCheatsWindowIdentifier = @"s9xCheatsWindow"; @@ -450,6 +451,9 @@ NSWindowFrameAutosaveName const kCheatFinderWindowIdentifier = @"s9xCheatFinderW - (IBAction)openDocument:(id)sender { NSOpenPanel* panel = [NSOpenPanel new]; + panel.canChooseDirectories = NO; + panel.allowsMultipleSelection = NO; + NSModalResponse response = [panel runModal]; if ( response == NSModalResponseOK ) @@ -462,23 +466,7 @@ NSWindowFrameAutosaveName const kCheatFinderWindowIdentifier = @"s9xCheatFinderW { if ([self.s9xEngine loadROM:url]) { - [self.s9xEngine recreateS9xView]; - - NSWindow *gameWindow = self.gameWindow; - [gameWindow.contentView addSubview:s9xView]; - [s9xView.topAnchor constraintEqualToAnchor:gameWindow.contentView.topAnchor].active = YES; - [s9xView.bottomAnchor constraintEqualToAnchor:gameWindow.contentView.bottomAnchor].active = YES; - [s9xView.centerXAnchor constraintEqualToAnchor:gameWindow.contentView.centerXAnchor].active = YES; - [s9xView.leftAnchor constraintGreaterThanOrEqualToAnchor:gameWindow.contentView.leftAnchor].active = YES; - [s9xView.rightAnchor constraintLessThanOrEqualToAnchor:gameWindow.contentView.rightAnchor].active = YES; - - if (self.cheatsWindowController != nil) - { - [((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) deselectAll]; - [((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) reloadData]; - } - - [gameWindow makeKeyAndOrderFront:self]; + [self resetWindow]; [NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:url]; return YES; } @@ -486,6 +474,54 @@ NSWindowFrameAutosaveName const kCheatFinderWindowIdentifier = @"s9xCheatFinderW return NO; } +- (IBAction)openMultiple:(id)sender +{ + S9xOpenMultipleViewController *vc = [[S9xOpenMultipleViewController alloc] initWithNibName:@"S9xOpenMultipleViewController" bundle:nil]; + vc.completionBlock = ^(NSArray *fileURLs) + { + [self openMultipleURLs:fileURLs]; + }; + + NSWindow *window = [NSWindow windowWithContentViewController:vc]; + window.title = NSLocalizedString(@"Open MultiCart", @""); + window.styleMask = NSWindowStyleMaskTitled; + [window makeKeyAndOrderFront:self]; + + [NSApp runModalForWindow:window]; +} + +- (BOOL)openMultipleURLs:(NSArray *)urls +{ + if ([self.s9xEngine loadMultiple:urls]) + { + [self resetWindow]; + return YES; + } + + return NO; +} + +- (void)resetWindow +{ + [self.s9xEngine recreateS9xView]; + + NSWindow *gameWindow = self.gameWindow; + [gameWindow.contentView addSubview:s9xView]; + [s9xView.topAnchor constraintEqualToAnchor:gameWindow.contentView.topAnchor].active = YES; + [s9xView.bottomAnchor constraintEqualToAnchor:gameWindow.contentView.bottomAnchor].active = YES; + [s9xView.centerXAnchor constraintEqualToAnchor:gameWindow.contentView.centerXAnchor].active = YES; + [s9xView.leftAnchor constraintGreaterThanOrEqualToAnchor:gameWindow.contentView.leftAnchor].active = YES; + [s9xView.rightAnchor constraintLessThanOrEqualToAnchor:gameWindow.contentView.rightAnchor].active = YES; + + if (self.cheatsWindowController != nil) + { + [((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) deselectAll]; + [((S9xCheatsViewController *)self.cheatsWindowController.contentViewController) reloadData]; + } + + [gameWindow makeKeyAndOrderFront:self]; +} + - (BOOL)validateMenuItem:(NSMenuItem *)menuItem { SEL action = menuItem.action; diff --git a/macosx/Snes9x/Base.lproj/MainMenu.xib b/macosx/Snes9x/Base.lproj/MainMenu.xib index b6c63585..7330e74f 100644 --- a/macosx/Snes9x/Base.lproj/MainMenu.xib +++ b/macosx/Snes9x/Base.lproj/MainMenu.xib @@ -73,6 +73,11 @@ + + + + + @@ -404,18 +409,12 @@ - + - - - - - - diff --git a/macosx/Snes9x/S9xOpenMultipleViewController.h b/macosx/Snes9x/S9xOpenMultipleViewController.h new file mode 100644 index 00000000..a7f29368 --- /dev/null +++ b/macosx/Snes9x/S9xOpenMultipleViewController.h @@ -0,0 +1,21 @@ +// +// S9xOpenMultipleViewController.h +// Snes9x +// +// Created by Buckley on 3/25/23. +// + +#import + +NS_ASSUME_NONNULL_BEGIN + +@interface S9xOpenMultipleViewController : NSViewController + +@property (nonatomic, strong) NSURL *fileURL1; +@property (nonatomic, strong) NSURL *fileURL2; + +@property (nonatomic, strong) void(^completionBlock)(NSArray *fileURLs); + +@end + +NS_ASSUME_NONNULL_END diff --git a/macosx/Snes9x/S9xOpenMultipleViewController.m b/macosx/Snes9x/S9xOpenMultipleViewController.m new file mode 100644 index 00000000..026d8e99 --- /dev/null +++ b/macosx/Snes9x/S9xOpenMultipleViewController.m @@ -0,0 +1,113 @@ +// +// S9xOpenMultipleViewController.m +// Snes9x +// +// Created by Buckley on 3/25/23. +// + +#import "S9xOpenMultipleViewController.h" + +@interface S9xOpenMultipleViewController () +@property (nonatomic, weak) IBOutlet NSTextField *label1; +@property (nonatomic, weak) IBOutlet NSTextField *label2; +@property (nonatomic, weak) IBOutlet NSButton *okButton; +@end + +@implementation S9xOpenMultipleViewController + +- (void)open:(void (^)(NSURL *))completionBlock +{ + NSOpenPanel *openPanel = [NSOpenPanel new]; + openPanel.allowsMultipleSelection = NO; + openPanel.canChooseDirectories = NO; + + [openPanel beginSheetModalForWindow:self.view.window completionHandler:^(NSModalResponse response) + { + if (response == NSModalResponseOK) + { + completionBlock(openPanel.URL); + } + }]; +} + +- (void)updateOKButton +{ + self.okButton.enabled = (self.fileURL1 != nil); +} + +- (IBAction)choose1:(id)sender +{ + [self open:^(NSURL *fileURL) + { + self.fileURL1 = fileURL; + }]; +} + +- (IBAction)choose2:(id)sender +{ + [self open:^(NSURL *fileURL) + { + self.fileURL2 = fileURL; + }]; +} + +- (IBAction)go:(id)sender +{ + if (self.completionBlock != nil) + { + [self.view.window close]; + [NSApp stopModal]; + + if (self.fileURL1 != nil) + { + if (self.fileURL2 != nil) + { + self.completionBlock(@[self.fileURL1, self.fileURL2]); + } + else + { + self.completionBlock(@[self.fileURL1]); + } + } + } +} + +- (IBAction)cancel:(id)sender +{ + [self.view.window close]; + [NSApp stopModal]; +} + +- (void)setFileURL1:(NSURL *)fileURL1 +{ + _fileURL1 = fileURL1; + + if (fileURL1 != nil) + { + self.label1.stringValue = fileURL1.lastPathComponent; + } + else + { + self.label1.stringValue = @""; + } + + [self updateOKButton]; +} + +- (void)setFileURL2:(NSURL *)fileURL2 +{ + _fileURL2 = fileURL2; + + if (fileURL2 != nil) + { + self.label2.stringValue = fileURL2.lastPathComponent; + } + else + { + self.label2.stringValue = @""; + } + + [self updateOKButton]; +} + +@end diff --git a/macosx/Snes9x/S9xOpenMultipleViewController.xib b/macosx/Snes9x/S9xOpenMultipleViewController.xib new file mode 100644 index 00000000..0c12f0b3 --- /dev/null +++ b/macosx/Snes9x/S9xOpenMultipleViewController.xib @@ -0,0 +1,127 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macosx/mac-multicart.h b/macosx/mac-multicart.h deleted file mode 100644 index 28a24993..00000000 --- a/macosx/mac-multicart.h +++ /dev/null @@ -1,29 +0,0 @@ -/*****************************************************************************\ - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - This file is licensed under the Snes9x License. - For further information, consult the LICENSE file in the root directory. -\*****************************************************************************/ - -/*********************************************************************************** - SNES9X for Mac OS (c) Copyright John Stiles - - Snes9x for Mac OS X - - (c) Copyright 2001 - 2011 zones - (c) Copyright 2002 - 2005 107 - (c) Copyright 2002 PB1400c - (c) Copyright 2004 Alexander and Sander - (c) Copyright 2004 - 2005 Steven Seeger - (c) Copyright 2005 Ryan Vogt - (c) Copyright 2019 Michael Donald Buckley - ***********************************************************************************/ - - -#ifndef _mac_multicart_h_ -#define _mac_multicart_h_ - -void InitMultiCart (void); -void DeinitMultiCart (void); -Boolean MultiCartDialog (void); - -#endif diff --git a/macosx/mac-multicart.mm b/macosx/mac-multicart.mm deleted file mode 100644 index da53f2da..00000000 --- a/macosx/mac-multicart.mm +++ /dev/null @@ -1,540 +0,0 @@ -/*****************************************************************************\ - Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. - This file is licensed under the Snes9x License. - For further information, consult the LICENSE file in the root directory. -\*****************************************************************************/ - -/*********************************************************************************** - SNES9X for Mac OS (c) Copyright John Stiles - - Snes9x for Mac OS X - - (c) Copyright 2001 - 2011 zones - (c) Copyright 2002 - 2005 107 - (c) Copyright 2002 PB1400c - (c) Copyright 2004 Alexander and Sander - (c) Copyright 2004 - 2005 Steven Seeger - (c) Copyright 2005 Ryan Vogt - (c) Copyright 2019 Michael Donald Buckley - ***********************************************************************************/ - - -#include "port.h" - -#include "mac-prefix.h" -#include "mac-cart.h" -#include "mac-dialog.h" -#include "mac-os.h" -#include "mac-multicart.h" - -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 -#define truncEnd 0 -#endif - -static OSStatus MultiCartEventHandler (EventHandlerCallRef, EventRef, void *); -static OSStatus MultiCartPaneEventHandler (EventHandlerCallRef, EventRef, void *); - -static int multiCartDragHilite; -static Boolean multiCartDialogResult; - -void InitMultiCart (void) -{ - CFStringRef keyRef, pathRef; - char key[32]; - - multiCartPath[0] = multiCartPath[1] = NULL; - - for (int i = 0; i < 2; i++) - { - sprintf(key, "MultiCartPath_%02d", i); - keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); - if (keyRef) - { - pathRef = (CFStringRef) CFPreferencesCopyAppValue(keyRef, kCFPreferencesCurrentApplication); - if (pathRef) - multiCartPath[i] = pathRef; - - CFRelease(keyRef); - } - } -} - -void DeinitMultiCart (void) -{ - CFStringRef keyRef; - char key[32]; - - for (int i = 0; i < 2; i++) - { - sprintf(key, "MultiCartPath_%02d", i); - keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); - if (keyRef) - { - if (multiCartPath[i]) - { - CFPreferencesSetAppValue(keyRef, multiCartPath[i], kCFPreferencesCurrentApplication); - CFRelease(multiCartPath[i]); - } - else - CFPreferencesSetAppValue(keyRef, NULL, kCFPreferencesCurrentApplication); - - CFRelease(keyRef); - } - } - - CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); -} - -Boolean MultiCartDialog (void) -{ -// OSStatus err; -// IBNibRef nibRef; -// -// multiCartDragHilite = -1; -// multiCartDialogResult = false; -// -// err = CreateNibReference(kMacS9XCFString, &nibRef); -// if (err == noErr) -// { -// WindowRef window; -// -// err = CreateWindowFromNib(nibRef, CFSTR("MultiCart"), &window); -// if (err == noErr) -// { -// static int index[2] = { 0, 1 }; -// -// EventHandlerRef wRef, cRef[2]; -// EventHandlerUPP wUPP, cUPP[2]; -// EventTypeSpec wEvent[] = { { kEventClassCommand, kEventCommandProcess }, -// { kEventClassCommand, kEventCommandUpdateStatus } }, -// cEvent[] = { { kEventClassControl, kEventControlDraw }, -// { kEventClassControl, kEventControlDragEnter }, -// { kEventClassControl, kEventControlDragWithin }, -// { kEventClassControl, kEventControlDragLeave }, -// { kEventClassControl, kEventControlDragReceive } }; -// HIViewRef ctl, root, pane[2]; -// HIViewID cid; -// -// root = HIViewGetRoot(window); -// -// wUPP = NewEventHandlerUPP(MultiCartEventHandler); -// err = InstallWindowEventHandler(window, wUPP, GetEventTypeCount(wEvent), wEvent, (void *) window, &wRef); -// err = SetAutomaticControlDragTrackingEnabledForWindow(window, true); -// -// for (int i = 0; i < 2; i++) -// { -// cid.id = i; -// -// cid.signature = 'MPan'; -// HIViewFindByID(root, cid, &pane[i]); -// cUPP[i] = NewEventHandlerUPP(MultiCartPaneEventHandler); -// err = InstallControlEventHandler(pane[i], cUPP[i], GetEventTypeCount(cEvent), cEvent, (void *) &index[i], &cRef[i]); -// err = SetControlDragTrackingEnabled(pane[i], true); -// -// cid.signature = 'MNAM'; -// HIViewFindByID(root, cid, &ctl); -// SetStaticTextTrunc(ctl, truncEnd, false); -// if (multiCartPath[i]) -// { -// CFStringRef str; -// CFURLRef url; -// -// url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, multiCartPath[i], kCFURLPOSIXPathStyle, false); -// str = CFURLCopyLastPathComponent(url); -// SetStaticTextCFString(ctl, str, false); -// CFRelease(str); -// CFRelease(url); -// } -// else -// SetStaticTextCFString(ctl, CFSTR(""), false); -// } -// -// MoveWindowPosition(window, kWindowMultiCart, false); -// ShowWindow(window); -// err = RunAppModalLoopForWindow(window); -// HideWindow(window); -// SaveWindowPosition(window, kWindowMultiCart); -// -// for (int i = 0; i < 2; i++) -// { -// err = RemoveEventHandler(cRef[i]); -// DisposeEventHandlerUPP(cUPP[i]); -// } -// -// err = RemoveEventHandler(wRef); -// DisposeEventHandlerUPP(wUPP); -// -// CFRelease(window); -// } -// -// DisposeNibReference(nibRef); -// } -// -// return (multiCartDialogResult); - - return 0; -} - -static OSStatus MultiCartEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) -{ -// OSStatus err, result = eventNotHandledErr; -// WindowRef window = (WindowRef) inUserData; -// static int index = -1; -// -// switch (GetEventClass(inEvent)) -// { -// case kEventClassCommand: -// { -// switch (GetEventKind(inEvent)) -// { -// HICommand tHICommand; -// -// case kEventCommandUpdateStatus: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); -// if (err == noErr && tHICommand.commandID == 'clos') -// { -// UpdateMenuCommandStatus(false); -// result = noErr; -// } -// -// break; -// } -// -// case kEventCommandProcess: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &tHICommand); -// if (err == noErr) -// { -// HIViewRef ctl, root; -// HIViewID cid; -// FSRef ref; -// bool8 r; -// -// root = HIViewGetRoot(window); -// -// switch (tHICommand.commandID) -// { -// case 'Cho0': -// case 'Cho1': -// { -// index = (tHICommand.commandID & 0xFF) - '0'; -// // r = NavBeginOpenROMImageSheet(window, NULL); -// result = noErr; -// break; -// } -// -// case 'NvDn': -// { -// r = NavEndOpenROMImageSheet(&ref); -// if (r) -// { -// CFStringRef str; -// CFURLRef url; -// -// url = CFURLCreateFromFSRef(kCFAllocatorDefault, &ref); -// str = CFURLCopyLastPathComponent(url); -// cid.signature = 'MNAM'; -// cid.id = index; -// HIViewFindByID(root, cid, &ctl); -// SetStaticTextCFString(ctl, str, true); -// CFRelease(str); -// str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); -// if (multiCartPath[index]) -// CFRelease(multiCartPath[index]); -// multiCartPath[index] = str; -// CFRelease(url); -// } -// -// index = -1; -// result = noErr; -// break; -// } -// -// case 'Cle0': -// case 'Cle1': -// { -// index = (tHICommand.commandID & 0xFF) - '0'; -// cid.signature = 'MNAM'; -// cid.id = index; -// HIViewFindByID(root, cid, &ctl); -// SetStaticTextCFString(ctl, CFSTR(""), true); -// if (multiCartPath[index]) -// { -// CFRelease(multiCartPath[index]); -// multiCartPath[index] = NULL; -// } -// -// index = -1; -// result = noErr; -// break; -// } -// -// case 'SWAP': -// { -// CFStringRef str; -// CFURLRef url; -// -// str = multiCartPath[0]; -// multiCartPath[0] = multiCartPath[1]; -// multiCartPath[1] = str; -// -// cid.signature = 'MNAM'; -// -// for (int i = 0; i < 2; i++) -// { -// cid.id = i; -// HIViewFindByID(root, cid, &ctl); -// -// if (multiCartPath[i]) -// { -// url = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, multiCartPath[i], kCFURLPOSIXPathStyle, false); -// str = CFURLCopyLastPathComponent(url); -// SetStaticTextCFString(ctl, str, true); -// CFRelease(str); -// CFRelease(url); -// } -// else -// SetStaticTextCFString(ctl, CFSTR(""), true); -// } -// -// result = noErr; -// break; -// } -// -// case 'ok ': -// { -// QuitAppModalLoopForWindow(window); -// multiCartDialogResult = true; -// result = noErr; -// break; -// } -// -// case 'not!': -// { -// QuitAppModalLoopForWindow(window); -// multiCartDialogResult = false; -// result = noErr; -// break; -// } -// } -// } -// } -// } -// } -// } -// -// return (result); - - return 0; -} - -static OSStatus MultiCartPaneEventHandler (EventHandlerCallRef inHandlerRef, EventRef inEvent, void *inUserData) -{ -// OSStatus err, result = eventNotHandledErr; -// HIViewRef view; -// DragRef drag; -// PasteboardRef pasteboard; -// PasteboardItemID itemID; -// CFArrayRef array; -// CFStringRef flavorType; -// CFIndex numFlavors; -// ItemCount numItems; -// int index = *((int *) inUserData); -// -// switch (GetEventClass(inEvent)) -// { -// case kEventClassControl: -// { -// switch (GetEventKind(inEvent)) -// { -// case kEventControlDraw: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); -// if (err == noErr) -// { -// CGContextRef ctx; -// -// err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); -// if (err == noErr) -// { -// HIThemeFrameDrawInfo info; -// HIRect bounds, frame; -// -// HIViewGetBounds(view, &bounds); -// -// CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); -// CGContextFillRect(ctx, bounds); -// -// info.version = 0; -// info.kind = kHIThemeFrameTextFieldSquare; -// info.state = kThemeStateInactive; -// info.isFocused = false; -// err = HIThemeDrawFrame(&bounds, &info, ctx, kHIThemeOrientationNormal); -// -// if (multiCartDragHilite == index && systemVersion >= 0x1040) -// { -// err = HIThemeSetStroke(kThemeBrushDragHilite, NULL, ctx, kHIThemeOrientationNormal); -// frame = CGRectInset(bounds, 1, 1); -// CGContextBeginPath(ctx); -// CGContextAddRect(ctx, frame); -// CGContextStrokePath(ctx); -// } -// } -// } -// -// result = noErr; -// break; -// } -// -// case kEventControlDragEnter: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); -// if (err == noErr) -// { -// err = GetEventParameter(inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof(DragRef), NULL, &drag); -// if (err == noErr) -// { -// err = GetDragPasteboard(drag, &pasteboard); -// if (err == noErr) -// { -// err = PasteboardGetItemCount(pasteboard, &numItems); -// if (err == noErr && numItems == 1) -// { -// err = PasteboardGetItemIdentifier(pasteboard, 1, &itemID); -// if (err == noErr) -// { -// err = PasteboardCopyItemFlavors(pasteboard, itemID, &array); -// if (err == noErr) -// { -// numFlavors = CFArrayGetCount(array); -// for (CFIndex i = 0; i < numFlavors; i++) -// { -// flavorType = (CFStringRef) CFArrayGetValueAtIndex(array, i); -// if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) -// { -// Boolean accept = true; -// -// err = SetEventParameter(inEvent, kEventParamControlWouldAcceptDrop, typeBoolean, sizeof(Boolean), &accept); -// if (err == noErr) -// { -// multiCartDragHilite = index; -// HIViewSetNeedsDisplay(view, true); -// result = noErr; -// } -// } -// } -// -// CFRelease(array); -// } -// } -// } -// } -// } -// } -// -// break; -// } -// -// case kEventControlDragWithin: -// { -// result = noErr; -// break; -// } -// -// case kEventControlDragLeave: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); -// if (err == noErr) -// { -// multiCartDragHilite = -1; -// HIViewSetNeedsDisplay(view, true); -// } -// -// result = noErr; -// break; -// } -// -// case kEventControlDragReceive: -// { -// err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); -// if (err == noErr) -// { -// err = GetEventParameter(inEvent, kEventParamDragRef, typeDragRef, NULL, sizeof(DragRef), NULL, &drag); -// if (err == noErr) -// { -// multiCartDragHilite = -1; -// HIViewSetNeedsDisplay(view, true); -// -// err = GetDragPasteboard(drag, &pasteboard); -// if (err == noErr) -// { -// err = PasteboardGetItemIdentifier(pasteboard, 1, &itemID); -// if (err == noErr) -// { -// err = PasteboardCopyItemFlavors(pasteboard, itemID, &array); -// if (err == noErr) -// { -// numFlavors = CFArrayGetCount(array); -// for (CFIndex i = 0; i < numFlavors; i++) -// { -// flavorType = (CFStringRef) CFArrayGetValueAtIndex(array, i); -// if (UTTypeConformsTo(flavorType, CFSTR("public.file-url"))) -// { -// CFDataRef flavorData; -// -// err = PasteboardCopyItemFlavorData(pasteboard, itemID, flavorType, &flavorData); -// if (err == noErr) -// { -// CFIndex dataSize; -// UInt8 *data; -// -// dataSize = CFDataGetLength(flavorData); -// data = (UInt8 *) malloc(dataSize); -// if (data) -// { -// CFDataGetBytes(flavorData, CFRangeMake(0, dataSize), data); -// -// HIViewRef ctl; -// HIViewID cid; -// CFStringRef str; -// CFURLRef url; -// -// GetControlID(view, &cid); -// cid.signature = 'MNAM'; -// HIViewFindByID(view, cid, &ctl); -// -// url = CFURLCreateWithBytes(kCFAllocatorDefault, data, dataSize, kCFStringEncodingUTF8, NULL); -// str = CFURLCopyLastPathComponent(url); -// SetStaticTextCFString(ctl, str, true); -// CFRelease(str); -// str = CFURLCopyFileSystemPath(url, kCFURLPOSIXPathStyle); -// if (multiCartPath[cid.id]) -// CFRelease(multiCartPath[cid.id]); -// multiCartPath[cid.id] = str; -// CFRelease(url); -// -// result = noErr; -// -// free(data); -// } -// -// CFRelease(flavorData); -// } -// } -// } -// -// CFRelease(array); -// } -// } -// } -// } -// } -// } -// } -// } -// } -// -// return (result); - return 0; -} diff --git a/macosx/mac-os.h b/macosx/mac-os.h index 1b3a6083..9a6a8885 100644 --- a/macosx/mac-os.h +++ b/macosx/mac-os.h @@ -127,7 +127,6 @@ extern int macControllerOption; extern CGPoint unlimitedCursor; extern char npServerIP[256], npName[256]; extern AutoFireState autofireRec[MAC_MAX_PLAYERS]; -extern CFStringRef multiCartPath[2]; #ifdef MAC_PANTHER_SUPPORT extern IconRef macIconRef[118]; @@ -229,6 +228,7 @@ extern id inputDelegate; - (NSString *)labelForVendorID:(uint32)vendorID productID:(uint32)productID cookie:(uint32)cookie value:(int32)value; - (BOOL)loadROM:(NSURL *)fileURL; +- (BOOL)loadMultiple:(NSArray *)fileURLs; - (void)setVideoMode:(int)videoMode; - (void)setMacFrameSkip:(int)_macFrameSkip; diff --git a/macosx/mac-os.mm b/macosx/mac-os.mm index 2a80febf..8b5a7814 100644 --- a/macosx/mac-os.mm +++ b/macosx/mac-os.mm @@ -15,7 +15,7 @@ (c) Copyright 2004 Alexander and Sander (c) Copyright 2004 - 2005 Steven Seeger (c) Copyright 2005 Ryan Vogt - (c) Copyright 2019 Michael Donald Buckley + (c) Copyright 2019-2023 Michael Donald Buckley ***********************************************************************************/ #import @@ -54,7 +54,6 @@ #import "mac-gworld.h" #import "mac-joypad.h" #import "mac-keyboard.h" -#import "mac-multicart.h" #import "mac-musicbox.h" #import "mac-netplay.h" #import "mac-render.h" @@ -154,8 +153,6 @@ bool8 lastoverscan = false; CGPoint unlimitedCursor; -CFStringRef multiCartPath[2]; - #ifdef MAC_PANTHER_SUPPORT IconRef macIconRef[118]; #endif @@ -2569,8 +2566,6 @@ static void Initialize (void) InitMacSound(); SetUpHID(); - InitMultiCart(); - autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask) ? true : false; for (int a = 0; a < MAC_MAX_PLAYERS; a++) for (int b = 0; b < 12; b++) @@ -2598,7 +2593,6 @@ static void Deinitialize (void) { deviceSetting = deviceSettingMaster; - DeinitMultiCart(); ReleaseHID(); DeinitGraphics(); DeinitKeyboard(); @@ -3358,6 +3352,41 @@ void QuitWithFatalError ( NSString *message) return NO; } +- (BOOL)loadMultiple:(NSArray *)fileURLs +{ + if (fileURLs.count == 0) + { + return NO; + } + + running = false; + frzselecting = false; + + while (!Settings.StopEmulation) + { + usleep(Settings.FrameTime); + } + + if (SNES9X_OpenMultiCart(fileURLs.firstObject, fileURLs.lastObject)) + { + [self.emulationDelegate gameLoaded]; + + SNES9X_Go(); + s9xView.window.title = fileURLs.firstObject.lastPathComponent.stringByDeletingPathExtension; + [s9xView.window makeKeyAndOrderFront:nil]; + + dispatch_async(dispatch_get_main_queue(), ^ + { + [s9xView.window makeFirstResponder:s9xView]; + }); + + [self start]; + return YES; + } + + return NO; +} + - (void)setShowFPS:(BOOL)showFPS { Settings.DisplayFrameRate = showFPS; diff --git a/macosx/mac-snes9x.h b/macosx/mac-snes9x.h index cfa8bf76..23c4dfc2 100755 --- a/macosx/mac-snes9x.h +++ b/macosx/mac-snes9x.h @@ -60,7 +60,7 @@ void SNES9X_SoftReset (void); void SNES9X_Quit (void); void SNES9X_InitSound (void); bool8 SNES9X_OpenCart (NSURL *); -bool8 SNES9X_OpenMultiCart (void); +bool8 SNES9X_OpenMultiCart (NSURL *cart1FileURL, NSURL *cart2FileURL); bool8 SNES9X_Freeze (void); bool8 SNES9X_FreezeTo (void); bool8 SNES9X_Defrost (void); diff --git a/macosx/mac-snes9x.mm b/macosx/mac-snes9x.mm index 2a83d635..55704d82 100755 --- a/macosx/mac-snes9x.mm +++ b/macosx/mac-snes9x.mm @@ -34,7 +34,6 @@ #include "mac-cart.h" #include "mac-dialog.h" #include "mac-file.h" -#include "mac-multicart.h" #include "mac-os.h" #include "mac-screenshot.h" #include "mac-stringtools.h" @@ -118,10 +117,9 @@ bool8 SNES9X_OpenCart (NSURL *inRef) } } -bool8 SNES9X_OpenMultiCart (void) +bool8 SNES9X_OpenMultiCart (NSURL *cart1FileURL, NSURL *cart2FileURL) { Boolean r; - char cart[2][PATH_MAX + 1]; if (cartOpen) { @@ -130,12 +128,6 @@ bool8 SNES9X_OpenMultiCart (void) S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); } - if (!MultiCartDialog()) - { - cartOpen = false; - return (false); - } - spcFileCount = pngFileCount = 0; Settings.ForceHeader = (headerDetect == kHeaderForce ); @@ -148,25 +140,19 @@ bool8 SNES9X_OpenMultiCart (void) S9xResetSaveTimer(true); - for (int i = 0; i < 2; i++) - { - cart[i][0] = 0; - if (multiCartPath[i]) - r = CFStringGetCString(multiCartPath[i], cart[i], PATH_MAX, kCFStringEncodingUTF8); - } - SNES9X_InitSound(); - if (Memory.LoadMultiCart(cart[0], cart[1])) + if (Memory.LoadMultiCart(cart1FileURL.path.UTF8String, cart2FileURL.path.UTF8String)) { cartOpen = true; SNES9X_LoadSRAM(); - for (int i = 0; i < 2; i++) + ChangeTypeAndCreator(cart1FileURL.path.UTF8String, 'CART', '~9X~'); + + if (cart2FileURL != nil) { - if (cart[i][0]) - ChangeTypeAndCreator(cart[i], 'CART', '~9X~'); + ChangeTypeAndCreator(cart2FileURL.path.UTF8String, 'CART', '~9X~'); } ApplyNSRTHeaderControllers(); diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj index ebdb24e5..fe9a84ae 100755 --- a/macosx/snes9x.xcodeproj/project.pbxproj +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -52,7 +52,6 @@ 307C862622D29E29001B879E /* mac-cocoatools.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA85C24E0B4EC13300F5F9C9 /* mac-cocoatools.mm */; }; 307C862922D29E29001B879E /* mac-gworld.mm in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67904AC7FCE00A80003 /* mac-gworld.mm */; }; 307C862A22D29E29001B879E /* mac-keyboard.mm in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67D04AC7FCE00A80003 /* mac-keyboard.mm */; }; - 307C862B22D29E29001B879E /* mac-multicart.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA26BBD50B3676E800A570B5 /* mac-multicart.mm */; }; 307C862C22D29E29001B879E /* mac-musicbox.mm in Sources */ = {isa = PBXBuildFile; fileRef = EAECB67F04AC7FCE00A80003 /* mac-musicbox.mm */; }; 307C862D22D29E29001B879E /* mac-netplay.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA1605500639E735004412AB /* mac-netplay.mm */; }; 307C863022D29E29001B879E /* mac-render.mm in Sources */ = {isa = PBXBuildFile; fileRef = EA942A50059B0F9000D7D022 /* mac-render.mm */; }; @@ -240,6 +239,8 @@ 30F727EE29C7B365000235A8 /* S9xCheatFinderViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F727EC29C7B365000235A8 /* S9xCheatFinderViewController.m */; }; 30F727EF29C7B365000235A8 /* S9xCheatFinderViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 30F727ED29C7B365000235A8 /* S9xCheatFinderViewController.xib */; }; 30F72A8E29CCF8E2000235A8 /* S9xHexNumberFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F72A8D29CCF8E2000235A8 /* S9xHexNumberFormatter.m */; }; + 30F72BE929CF588B000235A8 /* S9xOpenMultipleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30F72BE729CF588B000235A8 /* S9xOpenMultipleViewController.m */; }; + 30F72BEA29CF588B000235A8 /* S9xOpenMultipleViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 30F72BE829CF588B000235A8 /* S9xOpenMultipleViewController.xib */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -354,6 +355,9 @@ 30F727ED29C7B365000235A8 /* S9xCheatFinderViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = S9xCheatFinderViewController.xib; sourceTree = ""; }; 30F72A8C29CCF8E2000235A8 /* S9xHexNumberFormatter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xHexNumberFormatter.h; sourceTree = ""; }; 30F72A8D29CCF8E2000235A8 /* S9xHexNumberFormatter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xHexNumberFormatter.m; sourceTree = ""; }; + 30F72BE629CF588B000235A8 /* S9xOpenMultipleViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xOpenMultipleViewController.h; sourceTree = ""; }; + 30F72BE729CF588B000235A8 /* S9xOpenMultipleViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xOpenMultipleViewController.m; sourceTree = ""; }; + 30F72BE829CF588B000235A8 /* S9xOpenMultipleViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = S9xOpenMultipleViewController.xib; sourceTree = ""; }; 85FEF90620DDB15B00C038E9 /* bml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bml.cpp; sourceTree = ""; usesTabs = 1; }; 85FEF90720DDB15C00C038E9 /* bml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bml.h; sourceTree = ""; usesTabs = 1; }; 85FEF90A20DDB18D00C038E9 /* sha256.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sha256.cpp; sourceTree = ""; usesTabs = 1; }; @@ -416,8 +420,6 @@ EA1605500639E735004412AB /* mac-netplay.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = "mac-netplay.mm"; sourceTree = ""; }; EA22EFA2053EEDE500A80003 /* sdd1emu.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = sdd1emu.h; sourceTree = ""; usesTabs = 1; }; EA22EFA4053EEE0700A80003 /* sdd1emu.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; path = sdd1emu.cpp; sourceTree = ""; usesTabs = 1; }; - EA26BBD50B3676E800A570B5 /* mac-multicart.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; lineEnding = 0; path = "mac-multicart.mm"; sourceTree = ""; }; - EA26BBD90B36771500A570B5 /* mac-multicart.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-multicart.h"; sourceTree = ""; }; EA2DBC070510ABE700A80003 /* mac-screenshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-screenshot.h"; sourceTree = ""; }; EA2DBC090510ABE700A80003 /* mac-render.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-render.h"; sourceTree = ""; }; EA2DBC0A0510ABE700A80003 /* mac-file.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = "mac-file.h"; sourceTree = ""; }; @@ -695,6 +697,9 @@ 30714722230E379600917F82 /* Snes9x.entitlements */, 3082C4282379199F0081CA7C /* S9xApplication.h */, 3082C4292379199F0081CA7C /* S9xApplication.m */, + 30F72BE629CF588B000235A8 /* S9xOpenMultipleViewController.h */, + 30F72BE729CF588B000235A8 /* S9xOpenMultipleViewController.m */, + 30F72BE829CF588B000235A8 /* S9xOpenMultipleViewController.xib */, ); path = Snes9x; sourceTree = ""; @@ -1014,7 +1019,6 @@ EAECB67A04AC7FCE00A80003 /* mac-gworld.h */, EAECB67C04AC7FCE00A80003 /* mac-joypad.h */, EAECB67E04AC7FCE00A80003 /* mac-keyboard.h */, - EA26BBD90B36771500A570B5 /* mac-multicart.h */, EAECB68004AC7FCE00A80003 /* mac-musicbox.h */, EA16053E0639E655004412AB /* mac-netplay.h */, EAECB68204AC7FCE00A80003 /* mac-os.h */, @@ -1036,7 +1040,6 @@ EAECB67904AC7FCE00A80003 /* mac-gworld.mm */, EAECB67B04AC7FCE00A80003 /* mac-joypad.mm */, EAECB67D04AC7FCE00A80003 /* mac-keyboard.mm */, - EA26BBD50B3676E800A570B5 /* mac-multicart.mm */, EAECB67F04AC7FCE00A80003 /* mac-musicbox.mm */, EA1605500639E735004412AB /* mac-netplay.mm */, EAE0E96604D582B700A80003 /* mac-os.mm */, @@ -1276,6 +1279,7 @@ 30D709C2236F7E3200AAB7C3 /* S9xPreferencesWindowController.xib in Resources */, 306937E32636352100007ABB /* S9xEmulationPreferencesViewController.xib in Resources */, 30CF849627AEF5B0002B37A9 /* S9xCheatsViewController.xib in Resources */, + 30F72BEA29CF588B000235A8 /* S9xOpenMultipleViewController.xib in Resources */, 3071471E230E379600917F82 /* MainMenu.xib in Resources */, 306937DD26362B2400007ABB /* S9xSoundPreferencesViewController.xib in Resources */, ); @@ -1304,6 +1308,7 @@ 309C54802627F3060055DD95 /* S9xControlsPreferencesViewController.m in Sources */, 30D709C5236F90DF00AAB7C3 /* S9xButtonConfigTextField.m in Sources */, 306937E82636365100007ABB /* S9xFilesPreferencesViewController.m in Sources */, + 30F72BE929CF588B000235A8 /* S9xOpenMultipleViewController.m in Sources */, 30F72A8E29CCF8E2000235A8 /* S9xHexNumberFormatter.m in Sources */, 30F727EE29C7B365000235A8 /* S9xCheatFinderViewController.m in Sources */, 30CF849C27AF0C61002B37A9 /* S9xCheatEditViewController.m in Sources */, @@ -1329,7 +1334,6 @@ 307C862622D29E29001B879E /* mac-cocoatools.mm in Sources */, 307C862922D29E29001B879E /* mac-gworld.mm in Sources */, 307C862A22D29E29001B879E /* mac-keyboard.mm in Sources */, - 307C862B22D29E29001B879E /* mac-multicart.mm in Sources */, 307C862C22D29E29001B879E /* mac-musicbox.mm in Sources */, 307C862D22D29E29001B879E /* mac-netplay.mm in Sources */, 307C863022D29E29001B879E /* mac-render.mm in Sources */,