mirror of https://github.com/ksherlock/ample.git
move main window to a separate nib/controller.
This commit is contained in:
parent
fe94158187
commit
ef959a623b
|
@ -65,6 +65,8 @@
|
|||
B6BA258824E99BEB005FB8FF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = B6BA258724E99BEB005FB8FF /* main.m */; };
|
||||
B6D6DE3924FAC8B500661A5F /* Preferences.xib in Resources */ = {isa = PBXBuildFile; fileRef = B6D6DE3724FAC8B500661A5F /* Preferences.xib */; };
|
||||
B6D6DE3B24FACF4F00661A5F /* Defaults.plist in Resources */ = {isa = PBXBuildFile; fileRef = B6D6DE3A24FACF4F00661A5F /* Defaults.plist */; };
|
||||
B6D6DE3E24FADF8B00661A5F /* LaunchWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = B6D6DE3C24FADF8B00661A5F /* LaunchWindow.xib */; };
|
||||
B6D6DE4124FADFAC00661A5F /* LaunchWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = B6D6DE4024FADFAC00661A5F /* LaunchWindowController.m */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
|
@ -137,6 +139,9 @@
|
|||
B6BA258924E99BEB005FB8FF /* MA2ME.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = MA2ME.entitlements; sourceTree = "<group>"; };
|
||||
B6D6DE3824FAC8B500661A5F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/Preferences.xib; sourceTree = "<group>"; };
|
||||
B6D6DE3A24FACF4F00661A5F /* Defaults.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Defaults.plist; sourceTree = "<group>"; };
|
||||
B6D6DE3D24FADF8B00661A5F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchWindow.xib; sourceTree = "<group>"; };
|
||||
B6D6DE3F24FADFAC00661A5F /* LaunchWindowController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LaunchWindowController.h; sourceTree = "<group>"; };
|
||||
B6D6DE4024FADFAC00661A5F /* LaunchWindowController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LaunchWindowController.m; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
|
@ -250,9 +255,12 @@
|
|||
B6BA258724E99BEB005FB8FF /* main.m */,
|
||||
B6BA258924E99BEB005FB8FF /* MA2ME.entitlements */,
|
||||
B6BA258324E99BEB005FB8FF /* MainMenu.xib */,
|
||||
B6D6DE3C24FADF8B00661A5F /* LaunchWindow.xib */,
|
||||
B6D6DE3724FAC8B500661A5F /* Preferences.xib */,
|
||||
B61099E524F5F230005CB652 /* MediaView.xib */,
|
||||
B61099E324F5F230005CB652 /* SlotView.xib */,
|
||||
B6D6DE3F24FADFAC00661A5F /* LaunchWindowController.h */,
|
||||
B6D6DE4024FADFAC00661A5F /* LaunchWindowController.m */,
|
||||
);
|
||||
path = MA2ME;
|
||||
sourceTree = "<group>";
|
||||
|
@ -318,6 +326,7 @@
|
|||
B6109A2424F5F377005CB652 /* las128ex.plist in Resources */,
|
||||
B6109A1D24F5F377005CB652 /* space84.plist in Resources */,
|
||||
B6109A3F24F5F377005CB652 /* agat9.plist in Resources */,
|
||||
B6D6DE3E24FADF8B00661A5F /* LaunchWindow.xib in Resources */,
|
||||
B6109A3124F5F377005CB652 /* apple1.plist in Resources */,
|
||||
B6109A3524F5F377005CB652 /* ace100.plist in Resources */,
|
||||
B6109A3424F5F377005CB652 /* am64.plist in Resources */,
|
||||
|
@ -377,6 +386,7 @@
|
|||
files = (
|
||||
B6BA258824E99BEB005FB8FF /* main.m in Sources */,
|
||||
B64E15AC24EA1FD400E8AD3D /* SlotBrowserDelegate.m in Sources */,
|
||||
B6D6DE4124FADFAC00661A5F /* LaunchWindowController.m in Sources */,
|
||||
B64E15A924EA1D5300E8AD3D /* ROMBrowserDelegate.m in Sources */,
|
||||
B64979C224EF6703008ABD20 /* MediaViewController.m in Sources */,
|
||||
B60A6E1424EE0AE2004B7EEF /* FlippedView.m in Sources */,
|
||||
|
@ -420,6 +430,14 @@
|
|||
name = Preferences.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
B6D6DE3C24FADF8B00661A5F /* LaunchWindow.xib */ = {
|
||||
isa = PBXVariantGroup;
|
||||
children = (
|
||||
B6D6DE3D24FADF8B00661A5F /* Base */,
|
||||
);
|
||||
name = LaunchWindow.xib;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate, NSBrowserDelegate>
|
||||
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||
|
||||
- (IBAction)displayPreferences:(id)sender;
|
||||
|
||||
|
|
|
@ -9,36 +9,17 @@
|
|||
#import "AppDelegate.h"
|
||||
#import "SlotViewController.h"
|
||||
#import "MediaViewController.h"
|
||||
#import "LaunchWindowController.h"
|
||||
|
||||
@interface AppDelegate ()
|
||||
|
||||
@property (weak) IBOutlet NSWindow *window;
|
||||
@property (strong) IBOutlet SlotViewController *slotController;
|
||||
@property (strong) IBOutlet MediaViewController *mediaController;
|
||||
|
||||
|
||||
@property (weak) IBOutlet NSView *modelView;
|
||||
@property (weak) IBOutlet NSView *slotView;
|
||||
@property (weak) IBOutlet NSView *mediaView;
|
||||
|
||||
/* kvo */
|
||||
@property NSString *commandLine;
|
||||
@property NSArray *args;
|
||||
|
||||
@property NSString *mameROM;
|
||||
@property BOOL mameWindow;
|
||||
@property BOOL mameNoThrottle;
|
||||
@property BOOL mameDebug;
|
||||
@property BOOL mameSquarePixels;
|
||||
|
||||
@property NSArray *browserItems;
|
||||
@end
|
||||
|
||||
@implementation AppDelegate {
|
||||
NSWindowController *_prefs;
|
||||
NSWindowController *_launcher;
|
||||
}
|
||||
|
||||
static NSString *kMyContext = @"kMyContext";
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||
// Insert code here to initialize your application
|
||||
|
@ -56,63 +37,8 @@ static NSString *kMyContext = @"kMyContext";
|
|||
[[NSUserDefaults standardUserDefaults] registerDefaults: dict];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* My Copy of XCode/Interface Builder barfs on NSBrowser. */
|
||||
|
||||
|
||||
path = [bundle pathForResource: @"models" ofType: @"plist"];
|
||||
_browserItems = [NSArray arrayWithContentsOfFile: path];
|
||||
|
||||
NSView *view = [_window contentView];
|
||||
|
||||
NSRect frame;
|
||||
NSBrowser *browser = nil;
|
||||
|
||||
frame = [_modelView frame];
|
||||
browser = [[NSBrowser alloc] initWithFrame: frame];
|
||||
|
||||
[browser setMaxVisibleColumns: 2];
|
||||
//[browser setTakesTitleFromPreviousColumn: YES];
|
||||
//[browser setTitled: NO];
|
||||
[browser setAllowsEmptySelection: NO];
|
||||
[browser setDelegate: self];
|
||||
[browser setAction: @selector(modelClick:)];
|
||||
|
||||
[view addSubview: browser];
|
||||
//[browser setTitled: YES]; // NSBrowser title bug.
|
||||
|
||||
#if 0
|
||||
frame = [_slotView frame];
|
||||
browser = [[NSBrowser alloc] initWithFrame: frame];
|
||||
|
||||
[browser setMaxVisibleColumns: 2];
|
||||
[browser setTakesTitleFromPreviousColumn: YES];
|
||||
[browser setTitled: NO];
|
||||
[browser setDelegate: _slotDelegate];
|
||||
//[browser setAction: @selector(modelClick:)];
|
||||
|
||||
[view addSubview: browser];
|
||||
[browser setTitled: YES]; // NSBrowser title bug.
|
||||
[_slotDelegate setBrowser: browser];
|
||||
#endif
|
||||
|
||||
[_slotView addSubview: [_slotController view]];
|
||||
[_mediaView addSubview: [_mediaController view]];
|
||||
|
||||
|
||||
[self addObserver: self forKeyPath: @"mameROM" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameWindow" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameSquarePixels" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameDebug" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameNoThrottle" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_slotController addObserver: self forKeyPath: @"args" options: 0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[_mediaController addObserver: self forKeyPath: @"args" options: 0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_mediaController bind: @"media" toObject: _slotController withKeyPath: @"media" options: 0];
|
||||
|
||||
[self buildCommandLine];
|
||||
_launcher = [LaunchWindowController new];
|
||||
[_launcher showWindow: nil];
|
||||
}
|
||||
|
||||
|
||||
|
@ -125,248 +51,10 @@ static NSString *kMyContext = @"kMyContext";
|
|||
}
|
||||
|
||||
|
||||
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
|
||||
|
||||
if (context == (__bridge void *)kMyContext) {
|
||||
[self buildCommandLine];
|
||||
} else {
|
||||
[super observeValueForKeyPath: keyPath ofObject: object change: change context: context];
|
||||
}
|
||||
}
|
||||
|
||||
static NSString * JoinArguments(NSArray *argv) {
|
||||
|
||||
static NSCharacterSet *safe = nil;
|
||||
static NSCharacterSet *unsafe = nil;
|
||||
|
||||
if (!safe) {
|
||||
NSString *str =
|
||||
@"%+-./:=_"
|
||||
@"0123456789"
|
||||
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
;
|
||||
safe = [NSCharacterSet characterSetWithCharactersInString: str];
|
||||
unsafe = [safe invertedSet];
|
||||
}
|
||||
|
||||
NSMutableString *rv = [NSMutableString new];
|
||||
|
||||
|
||||
//unsigned ix = 0;
|
||||
[rv appendString: @"mame"];
|
||||
for (NSString *s in argv) {
|
||||
[rv appendString: @" "];
|
||||
NSUInteger l = [s length];
|
||||
|
||||
if (!l) {
|
||||
[rv appendString: @"''"];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CFStringFindCharacterFromSet((CFStringRef)s, (CFCharacterSetRef)unsafe, CFRangeMake(0, l), 0, NULL)) {
|
||||
[rv appendString: s];
|
||||
continue;
|
||||
}
|
||||
|
||||
unichar *buffer = malloc(sizeof(unichar) * l);
|
||||
[s getCharacters: buffer range: NSMakeRange(0, l)];
|
||||
|
||||
[rv appendString: @"'"];
|
||||
for (NSUInteger i = 0; i < l; ++i) {
|
||||
unichar c = buffer[i];
|
||||
switch (c) {
|
||||
case '\'':
|
||||
[rv appendString: @"\\'"];
|
||||
break;
|
||||
case '\\':
|
||||
[rv appendString: @"\\\\"];
|
||||
break;
|
||||
case 0x7f:
|
||||
[rv appendString: @"\\177"];
|
||||
break;
|
||||
default: {
|
||||
NSString *cc;
|
||||
if (c < 0x20) {
|
||||
cc = [NSString stringWithFormat: @"\\%o", c];
|
||||
} else {
|
||||
cc = [NSString stringWithCharacters: &c length: 1];
|
||||
}
|
||||
[rv appendString: cc];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[rv appendString: @"'"];
|
||||
free(buffer);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
-(void)buildCommandLine {
|
||||
|
||||
|
||||
if (!_mameROM) {
|
||||
[self setCommandLine: @""];
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *argv = [NSMutableArray new];
|
||||
|
||||
//[argv addObject: @"mame"];
|
||||
[argv addObject: _mameROM];
|
||||
|
||||
if (_mameDebug) [argv addObject: @"-debug"];
|
||||
if (_mameWindow) [argv addObject: @"-window"];
|
||||
|
||||
// -nounevenstretch -video soft
|
||||
[argv addObject: @"-skip_gameinfo"];
|
||||
|
||||
if (_mameWindow && _mameSquarePixels) {
|
||||
NSSize screen = [_slotController resolution];
|
||||
|
||||
NSString *res = [NSString stringWithFormat: @"%ux%u", (unsigned)screen.width, (unsigned)screen.height];
|
||||
NSString *aspect = [NSString stringWithFormat: @"%u:%u", (unsigned)screen.width, (unsigned)screen.height];
|
||||
|
||||
[argv addObject: @"-nomax"];
|
||||
[argv addObject: @"-nounevenstretch"];
|
||||
|
||||
if ([_mameROM hasPrefix: @"apple2gs"]) {
|
||||
[argv addObject: @"-resolution"];
|
||||
[argv addObject: res]; // @"704x462"];
|
||||
[argv addObject: @"-video"];
|
||||
[argv addObject: @"soft"];
|
||||
[argv addObject: @"-aspect"];
|
||||
[argv addObject: aspect];
|
||||
} else {
|
||||
[argv addObject: @"-resolution"];
|
||||
[argv addObject: res]; // @"560x384"];
|
||||
|
||||
}
|
||||
}
|
||||
// -speed n
|
||||
// -scale n
|
||||
|
||||
NSArray *tmp;
|
||||
tmp = [_slotController args];
|
||||
if ([tmp count]) {
|
||||
[argv addObjectsFromArray: tmp];
|
||||
}
|
||||
|
||||
tmp = [_mediaController args];
|
||||
if ([tmp count]) {
|
||||
[argv addObjectsFromArray: tmp];
|
||||
}
|
||||
|
||||
if (_mameNoThrottle) [argv addObject: @"-nothrottle"];
|
||||
|
||||
|
||||
[self setCommandLine: JoinArguments(argv)]; //[argv componentsJoinedByString:@" "]];
|
||||
[self setArgs: argv];
|
||||
}
|
||||
|
||||
-(IBAction)modelClick:(id)sender {
|
||||
|
||||
NSDictionary *item = [self itemForBrowser: sender];
|
||||
NSString *model = [item objectForKey: @"value"];
|
||||
|
||||
[self setMameROM: model];
|
||||
|
||||
// [self buildCommandLine];
|
||||
|
||||
[_slotController setModel: model];
|
||||
}
|
||||
|
||||
#pragma mark NSBrowser
|
||||
|
||||
-(NSDictionary *)itemForBrowser: (NSBrowser *)browser {
|
||||
|
||||
NSIndexPath *path = [browser selectionIndexPath];
|
||||
|
||||
NSArray *a = _browserItems;
|
||||
NSDictionary *item = nil;
|
||||
|
||||
NSUInteger l = [path length];
|
||||
for (NSUInteger i = 0; i < l; ++i) {
|
||||
NSUInteger ix = [path indexAtPosition: i];
|
||||
if (ix > [a count]) return nil;
|
||||
item = [a objectAtIndex: ix];
|
||||
a = [item objectForKey: @"children"];
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
-(NSArray *)itemsForBrowser: (NSBrowser *)browser column: (NSInteger) column {
|
||||
|
||||
NSArray *a = _browserItems;
|
||||
for (unsigned i = 0; i < column; ++i) {
|
||||
NSInteger ix = [browser selectedRowInColumn: i];
|
||||
if (ix < 0) return 0;
|
||||
|
||||
NSDictionary *item = [a objectAtIndex: ix];
|
||||
a = [item objectForKey: @"children"];
|
||||
if (!a) return 0;
|
||||
}
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
- (void)browser:(NSBrowser *)sender willDisplayCell:(id)cell atRow:(NSInteger)row column:(NSInteger)column {
|
||||
NSArray *a = [self itemsForBrowser: sender column: column];
|
||||
if (!a || row >= [a count]) return;
|
||||
|
||||
NSDictionary *item = [a objectAtIndex: row];
|
||||
|
||||
NSBrowserCell *bc = (NSBrowserCell *)cell;
|
||||
|
||||
[bc setStringValue: [item objectForKey: @"description"]];
|
||||
[bc setLeaf: ![item objectForKey: @"children"]];
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)browser:(NSBrowser *)sender titleOfColumn:(NSInteger)column {
|
||||
return column == 0 ? @"Model" : @"Submodel";
|
||||
}
|
||||
|
||||
#if 0
|
||||
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item {
|
||||
return nil;
|
||||
}
|
||||
-(id)rootItemForBrowser:(NSBrowser *)browser {
|
||||
return _browserItems;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column {
|
||||
|
||||
NSArray *a = [self itemsForBrowser: sender column: column];
|
||||
return [a count];
|
||||
}
|
||||
|
||||
#pragma mark - IBActions
|
||||
|
||||
- (IBAction)launchAction:(id)sender {
|
||||
if (![_args count]) return;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSString *path = [defaults stringForKey: @"MamePath"];
|
||||
if (![path length]) path = @"/usr/local/bin/mame";
|
||||
|
||||
NSError *error = nil;
|
||||
NSURL *url = [NSURL fileURLWithPath: path];
|
||||
|
||||
NSTask *task = [NSTask launchedTaskWithExecutableURL: url
|
||||
arguments: _args
|
||||
error: &error
|
||||
terminationHandler: ^(NSTask *t){
|
||||
|
||||
|
||||
|
||||
|
||||
}];
|
||||
if (error) NSLog(@"launchAction: %@", error);
|
||||
}
|
||||
|
||||
- (IBAction)displayPreferences:(id)sender {
|
||||
if (!_prefs) {
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="15705" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
|
||||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="LaunchWindowController">
|
||||
<connections>
|
||||
<outlet property="mediaController" destination="t7c-zy-czN" id="a7d-HC-TWx"/>
|
||||
<outlet property="mediaView" destination="J9O-xI-P5J" id="PmZ-VC-4SN"/>
|
||||
<outlet property="modelView" destination="oVt-eD-aaj" id="nam-De-IQe"/>
|
||||
<outlet property="slotController" destination="lyS-mc-3Tf" id="LXo-Ii-fDX"/>
|
||||
<outlet property="slotView" destination="P9d-sS-qEb" id="T2q-ON-owm"/>
|
||||
<outlet property="window" destination="Vze-YF-m6e" id="JUs-Eb-MW8"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<window title="MA2ME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="Vze-YF-m6e">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="718" height="947"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="Ssv-Jw-EE0">
|
||||
<rect key="frame" x="0.0" y="0.0" width="718" height="947"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="oVt-eD-aaj">
|
||||
<rect key="frame" x="0.0" y="747" width="718" height="200"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zVI-uU-muo">
|
||||
<rect key="frame" x="18" y="102" width="71" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Window" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="vx1-I7-8kN">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.mameWindow" id="uS7-cg-wqb"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ZUp-ni-Rr6">
|
||||
<rect key="frame" x="18" y="82" width="62" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Debug" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="6is-QN-JEc">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.mameDebug" id="vkc-sR-KnB"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="pKK-yY-vnY">
|
||||
<rect key="frame" x="0.0" y="0.0" width="718" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="bk2-0p-jUj">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.commandLine" id="9gW-Y2-kvp"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="nKp-px-nHg">
|
||||
<rect key="frame" x="621" y="53" width="85" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Launch" bezelStyle="rounded" image="NSAppleMenuImage" imagePosition="left" alignment="center" borderStyle="border" inset="2" id="Ct1-Rb-7uI">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="launchAction:" target="-2" id="a4d-zv-1CU"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="rLP-n2-0eY">
|
||||
<rect key="frame" x="18" y="62" width="91" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="No Throttle" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="NyE-jT-WqC">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.mameNoThrottle" id="tUN-EX-7PF"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="D5h-dm-fuZ">
|
||||
<rect key="frame" x="131" y="102" width="104" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="yWK-BP-7Z9">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.mameSquarePixels" id="BiP-wC-Hpn"/>
|
||||
</connections>
|
||||
</button>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="P9d-sS-qEb" customClass="FlippedView">
|
||||
<rect key="frame" x="20" y="169" width="306" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="J9O-xI-P5J" customClass="FlippedView">
|
||||
<rect key="frame" x="392" y="169" width="306" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="zoQ-mU-ARl">
|
||||
<rect key="frame" x="261" y="102" width="67" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="No Blur" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="r3s-5h-Xv5">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="-2" name="value" keyPath="self.mameNoBlur" id="Pvn-zw-OsQ"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<point key="canvasLocation" x="769" y="196.5"/>
|
||||
</window>
|
||||
<viewController title="Media View" nibName="MediaView" id="t7c-zy-czN" customClass="MediaViewController"/>
|
||||
<viewController title="Slot View" nibName="SlotView" id="lyS-mc-3Tf" customClass="SlotViewController"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSAppleMenuImage" width="11" height="14"/>
|
||||
</resources>
|
||||
</document>
|
|
@ -3,7 +3,6 @@
|
|||
<dependencies>
|
||||
<deployment identifier="macosx"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="15705"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
|
||||
|
@ -13,16 +12,7 @@
|
|||
</customObject>
|
||||
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
|
||||
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate">
|
||||
<connections>
|
||||
<outlet property="mediaController" destination="kiU-IX-LTW" id="HXj-YL-bBX"/>
|
||||
<outlet property="mediaView" destination="Jcd-jI-Pje" id="d1b-R8-L4a"/>
|
||||
<outlet property="modelView" destination="jf6-4d-ms1" id="HUy-kg-cCk"/>
|
||||
<outlet property="slotController" destination="CYF-Xd-EdF" id="14d-v7-98c"/>
|
||||
<outlet property="slotView" destination="cFJ-CO-Dzm" id="u9o-0O-D5i"/>
|
||||
<outlet property="window" destination="QvC-M9-y7g" id="gIp-Ho-8D9"/>
|
||||
</connections>
|
||||
</customObject>
|
||||
<customObject id="Voe-Tx-rLC" customClass="AppDelegate"/>
|
||||
<customObject id="YLy-65-1bz" customClass="NSFontManager"/>
|
||||
<menu title="Main Menu" systemMenu="main" id="AYu-sK-qS6">
|
||||
<items>
|
||||
|
@ -690,110 +680,5 @@
|
|||
</items>
|
||||
<point key="canvasLocation" x="132" y="154"/>
|
||||
</menu>
|
||||
<window title="MA2ME" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="QvC-M9-y7g">
|
||||
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES"/>
|
||||
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
|
||||
<rect key="contentRect" x="335" y="390" width="718" height="947"/>
|
||||
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
|
||||
<view key="contentView" id="EiT-Mj-1SZ">
|
||||
<rect key="frame" x="0.0" y="0.0" width="718" height="947"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="jf6-4d-ms1">
|
||||
<rect key="frame" x="0.0" y="747" width="718" height="200"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Ymx-Ml-AsE">
|
||||
<rect key="frame" x="18" y="102" width="71" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Window" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="McP-bf-5Zu">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="value" keyPath="self.mameWindow" id="0bg-kj-1JX"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="bkv-BK-7TC">
|
||||
<rect key="frame" x="18" y="82" width="62" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Debug" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="WPk-zw-UFD">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="value" keyPath="self.mameDebug" id="mGk-ML-ncm"/>
|
||||
</connections>
|
||||
</button>
|
||||
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" fixedFrame="YES" textCompletion="NO" translatesAutoresizingMaskIntoConstraints="NO" id="g2S-iX-zTe">
|
||||
<rect key="frame" x="0.0" y="0.0" width="718" height="52"/>
|
||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
|
||||
<textFieldCell key="cell" selectable="YES" allowsUndo="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="vbg-gA-6dg">
|
||||
<font key="font" metaFont="system"/>
|
||||
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
|
||||
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
|
||||
</textFieldCell>
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="value" keyPath="self.commandLine" id="gkK-GV-onk"/>
|
||||
</connections>
|
||||
</textField>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="ug9-kz-ZSS">
|
||||
<rect key="frame" x="621" y="53" width="85" height="32"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxY="YES"/>
|
||||
<buttonCell key="cell" type="push" title="Launch" bezelStyle="rounded" image="NSAppleMenuImage" imagePosition="leading" alignment="center" borderStyle="border" inset="2" id="evD-kp-H2u">
|
||||
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<action selector="launchAction:" target="Voe-Tx-rLC" id="469-Yy-fyx"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="QSr-Gw-xV3">
|
||||
<rect key="frame" x="18" y="62" width="91" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="No Throttle" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Kgs-UM-HeU">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="value" keyPath="self.mameNoThrottle" id="v1f-ka-XkT"/>
|
||||
</connections>
|
||||
</button>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="PUB-So-kAo">
|
||||
<rect key="frame" x="131" y="102" width="104" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="Square Pixels" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Bj2-i5-4h1">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
<connections>
|
||||
<binding destination="Voe-Tx-rLC" name="value" keyPath="self.mameSquarePixels" id="rNk-1d-QZl"/>
|
||||
</connections>
|
||||
</button>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="cFJ-CO-Dzm" customClass="FlippedView">
|
||||
<rect key="frame" x="20" y="169" width="306" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<customView fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="Jcd-jI-Pje" customClass="FlippedView">
|
||||
<rect key="frame" x="392" y="169" width="306" height="570"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMinY="YES"/>
|
||||
</customView>
|
||||
<button verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="XMQ-jr-w2i">
|
||||
<rect key="frame" x="261" y="102" width="67" height="18"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
|
||||
<buttonCell key="cell" type="check" title="No Blur" bezelStyle="regularSquare" imagePosition="left" state="on" inset="2" id="Xxl-Eu-ziO">
|
||||
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
|
||||
<font key="font" metaFont="system"/>
|
||||
</buttonCell>
|
||||
</button>
|
||||
</subviews>
|
||||
</view>
|
||||
<point key="canvasLocation" x="769" y="196.5"/>
|
||||
</window>
|
||||
<viewController title="Slot View" nibName="SlotView" id="CYF-Xd-EdF" customClass="SlotViewController"/>
|
||||
<viewController title="Media View" nibName="MediaView" id="kiU-IX-LTW" customClass="MediaViewController"/>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="NSAppleMenuImage" width="11" height="14"/>
|
||||
</resources>
|
||||
</document>
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
//
|
||||
// LaunchWindowController.h
|
||||
// MA2ME
|
||||
//
|
||||
// Created by Kelvin Sherlock on 8/29/2020.
|
||||
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Cocoa/Cocoa.h>
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface LaunchWindowController : NSWindowController <NSBrowserDelegate>
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
|
@ -0,0 +1,351 @@
|
|||
//
|
||||
// LaunchWindowController.m
|
||||
// MA2ME
|
||||
//
|
||||
// Created by Kelvin Sherlock on 8/29/2020.
|
||||
// Copyright © 2020 Kelvin Sherlock. All rights reserved.
|
||||
//
|
||||
|
||||
#import "LaunchWindowController.h"
|
||||
#import "MediaViewController.h"
|
||||
#import "SlotViewController.h"
|
||||
|
||||
static NSString *kMyContext = @"kMyContext";
|
||||
|
||||
|
||||
@interface LaunchWindowController ()
|
||||
@property (strong) IBOutlet MediaViewController *mediaController;
|
||||
@property (strong) IBOutlet SlotViewController *slotController;
|
||||
|
||||
@property (weak) IBOutlet NSView *modelView;
|
||||
@property (weak) IBOutlet NSView *slotView;
|
||||
@property (weak) IBOutlet NSView *mediaView;
|
||||
|
||||
/* kvo */
|
||||
@property NSString *commandLine;
|
||||
@property NSArray *args;
|
||||
|
||||
@property NSString *mameMachine;
|
||||
@property BOOL mameWindow;
|
||||
@property BOOL mameNoThrottle;
|
||||
@property BOOL mameDebug;
|
||||
@property BOOL mameSquarePixels;
|
||||
@property BOOL mameNoBlur;
|
||||
|
||||
|
||||
@property NSArray *browserItems;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation LaunchWindowController
|
||||
|
||||
-(NSString *)windowNibName {
|
||||
return @"LaunchWindow";
|
||||
}
|
||||
|
||||
- (void)windowDidLoad {
|
||||
[super windowDidLoad];
|
||||
|
||||
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
|
||||
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
NSString *path;
|
||||
NSWindow *window = [self window];
|
||||
|
||||
|
||||
/* My Copy of XCode/Interface Builder barfs on NSBrowser. */
|
||||
|
||||
|
||||
path = [bundle pathForResource: @"models" ofType: @"plist"];
|
||||
_browserItems = [NSArray arrayWithContentsOfFile: path];
|
||||
|
||||
NSView *view = [window contentView];
|
||||
|
||||
NSRect frame;
|
||||
NSBrowser *browser = nil;
|
||||
|
||||
frame = [_modelView frame];
|
||||
browser = [[NSBrowser alloc] initWithFrame: frame];
|
||||
|
||||
[browser setMaxVisibleColumns: 2];
|
||||
//[browser setTakesTitleFromPreviousColumn: YES];
|
||||
//[browser setTitled: NO];
|
||||
[browser setAllowsEmptySelection: NO];
|
||||
[browser setDelegate: self];
|
||||
[browser setAction: @selector(modelClick:)];
|
||||
|
||||
[view addSubview: browser];
|
||||
//[browser setTitled: YES]; // NSBrowser title bug.
|
||||
|
||||
|
||||
[_slotView addSubview: [_slotController view]];
|
||||
[_mediaView addSubview: [_mediaController view]];
|
||||
|
||||
|
||||
[self addObserver: self forKeyPath: @"mameMachine" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameWindow" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameSquarePixels" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameDebug" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[self addObserver: self forKeyPath: @"mameNoThrottle" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[self addObserver: self forKeyPath: @"mameNoBlur" options:0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_slotController addObserver: self forKeyPath: @"args" options: 0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
[_mediaController addObserver: self forKeyPath: @"args" options: 0 context: (__bridge void * _Nullable)(kMyContext)];
|
||||
|
||||
[_mediaController bind: @"media" toObject: _slotController withKeyPath: @"media" options: 0];
|
||||
|
||||
[self buildCommandLine];
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
|
||||
|
||||
if (context == (__bridge void *)kMyContext) {
|
||||
[self buildCommandLine];
|
||||
} else {
|
||||
[super observeValueForKeyPath: keyPath ofObject: object change: change context: context];
|
||||
}
|
||||
}
|
||||
|
||||
static NSString * JoinArguments(NSArray *argv) {
|
||||
|
||||
static NSCharacterSet *safe = nil;
|
||||
static NSCharacterSet *unsafe = nil;
|
||||
|
||||
if (!safe) {
|
||||
NSString *str =
|
||||
@"%+-./:=_"
|
||||
@"0123456789"
|
||||
@"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
||||
;
|
||||
safe = [NSCharacterSet characterSetWithCharactersInString: str];
|
||||
unsafe = [safe invertedSet];
|
||||
}
|
||||
|
||||
NSMutableString *rv = [NSMutableString new];
|
||||
|
||||
|
||||
//unsigned ix = 0;
|
||||
[rv appendString: @"mame"];
|
||||
for (NSString *s in argv) {
|
||||
[rv appendString: @" "];
|
||||
NSUInteger l = [s length];
|
||||
|
||||
if (!l) {
|
||||
[rv appendString: @"''"];
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!CFStringFindCharacterFromSet((CFStringRef)s, (CFCharacterSetRef)unsafe, CFRangeMake(0, l), 0, NULL)) {
|
||||
[rv appendString: s];
|
||||
continue;
|
||||
}
|
||||
|
||||
unichar *buffer = malloc(sizeof(unichar) * l);
|
||||
[s getCharacters: buffer range: NSMakeRange(0, l)];
|
||||
|
||||
[rv appendString: @"'"];
|
||||
for (NSUInteger i = 0; i < l; ++i) {
|
||||
unichar c = buffer[i];
|
||||
switch (c) {
|
||||
case '\'':
|
||||
[rv appendString: @"\\'"];
|
||||
break;
|
||||
case '\\':
|
||||
[rv appendString: @"\\\\"];
|
||||
break;
|
||||
case 0x7f:
|
||||
[rv appendString: @"\\177"];
|
||||
break;
|
||||
default: {
|
||||
NSString *cc;
|
||||
if (c < 0x20) {
|
||||
cc = [NSString stringWithFormat: @"\\%o", c];
|
||||
} else {
|
||||
cc = [NSString stringWithCharacters: &c length: 1];
|
||||
}
|
||||
[rv appendString: cc];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
[rv appendString: @"'"];
|
||||
free(buffer);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
-(void)buildCommandLine {
|
||||
|
||||
|
||||
if (!_mameMachine) {
|
||||
[self setCommandLine: @""];
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableArray *argv = [NSMutableArray new];
|
||||
|
||||
//[argv addObject: @"mame"];
|
||||
[argv addObject: _mameMachine];
|
||||
|
||||
if (_mameDebug) [argv addObject: @"-debug"];
|
||||
if (_mameWindow) [argv addObject: @"-window"];
|
||||
|
||||
// -nounevenstretch -video soft
|
||||
[argv addObject: @"-skip_gameinfo"];
|
||||
|
||||
if (_mameWindow && _mameSquarePixels) {
|
||||
NSSize screen = [_slotController resolution];
|
||||
|
||||
NSString *res = [NSString stringWithFormat: @"%ux%u", (unsigned)screen.width, (unsigned)screen.height];
|
||||
NSString *aspect = [NSString stringWithFormat: @"%u:%u", (unsigned)screen.width, (unsigned)screen.height];
|
||||
|
||||
[argv addObject: @"-nomax"];
|
||||
[argv addObject: @"-nounevenstretch"];
|
||||
|
||||
[argv addObject: @"-resolution"];
|
||||
[argv addObject: res];
|
||||
|
||||
[argv addObject: @"-aspect"];
|
||||
[argv addObject: aspect];
|
||||
|
||||
if (_mameNoBlur) {
|
||||
[argv addObject: @"-video"];
|
||||
[argv addObject: @"soft"];
|
||||
}
|
||||
}
|
||||
// -speed n
|
||||
// -scale n
|
||||
|
||||
NSArray *tmp;
|
||||
tmp = [_slotController args];
|
||||
if ([tmp count]) {
|
||||
[argv addObjectsFromArray: tmp];
|
||||
}
|
||||
|
||||
tmp = [_mediaController args];
|
||||
if ([tmp count]) {
|
||||
[argv addObjectsFromArray: tmp];
|
||||
}
|
||||
|
||||
if (_mameNoThrottle) [argv addObject: @"-nothrottle"];
|
||||
|
||||
|
||||
[self setCommandLine: JoinArguments(argv)]; //[argv componentsJoinedByString:@" "]];
|
||||
[self setArgs: argv];
|
||||
}
|
||||
|
||||
# pragma mark - IBActions
|
||||
|
||||
-(IBAction)modelClick:(id)sender {
|
||||
|
||||
NSDictionary *item = [self itemForBrowser: sender];
|
||||
NSString *model = [item objectForKey: @"value"];
|
||||
|
||||
[self setMameMachine: model];
|
||||
|
||||
// [self buildCommandLine];
|
||||
|
||||
[_slotController setModel: model];
|
||||
}
|
||||
|
||||
|
||||
- (IBAction)launchAction:(id)sender {
|
||||
|
||||
if (![_args count]) return;
|
||||
|
||||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||||
|
||||
NSString *path = [defaults stringForKey: @"MamePath"];
|
||||
if (![path length]) path = @"/usr/local/bin/mame";
|
||||
|
||||
NSError *error = nil;
|
||||
NSURL *url = [NSURL fileURLWithPath: path];
|
||||
|
||||
NSTask *task = [NSTask new];
|
||||
[task setExecutableURL: url];
|
||||
[task setArguments: _args];
|
||||
[task setTerminationHandler: ^(NSTask *t){
|
||||
|
||||
}];
|
||||
// set stderr/stdout...
|
||||
[task launchAndReturnError: &error];
|
||||
|
||||
|
||||
if (error) NSLog(@"launchAction: %@", error);
|
||||
|
||||
}
|
||||
|
||||
#pragma mark - NSBrowser
|
||||
|
||||
-(NSDictionary *)itemForBrowser: (NSBrowser *)browser {
|
||||
|
||||
NSIndexPath *path = [browser selectionIndexPath];
|
||||
|
||||
NSArray *a = _browserItems;
|
||||
NSDictionary *item = nil;
|
||||
|
||||
NSUInteger l = [path length];
|
||||
for (NSUInteger i = 0; i < l; ++i) {
|
||||
NSUInteger ix = [path indexAtPosition: i];
|
||||
if (ix > [a count]) return nil;
|
||||
item = [a objectAtIndex: ix];
|
||||
a = [item objectForKey: @"children"];
|
||||
}
|
||||
|
||||
return item;
|
||||
}
|
||||
-(NSArray *)itemsForBrowser: (NSBrowser *)browser column: (NSInteger) column {
|
||||
|
||||
NSArray *a = _browserItems;
|
||||
for (unsigned i = 0; i < column; ++i) {
|
||||
NSInteger ix = [browser selectedRowInColumn: i];
|
||||
if (ix < 0) return 0;
|
||||
|
||||
NSDictionary *item = [a objectAtIndex: ix];
|
||||
a = [item objectForKey: @"children"];
|
||||
if (!a) return 0;
|
||||
}
|
||||
return a;
|
||||
|
||||
}
|
||||
|
||||
- (void)browser:(NSBrowser *)sender willDisplayCell:(id)cell atRow:(NSInteger)row column:(NSInteger)column {
|
||||
NSArray *a = [self itemsForBrowser: sender column: column];
|
||||
if (!a || row >= [a count]) return;
|
||||
|
||||
NSDictionary *item = [a objectAtIndex: row];
|
||||
|
||||
NSBrowserCell *bc = (NSBrowserCell *)cell;
|
||||
|
||||
[bc setStringValue: [item objectForKey: @"description"]];
|
||||
[bc setLeaf: ![item objectForKey: @"children"]];
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (NSString *)browser:(NSBrowser *)sender titleOfColumn:(NSInteger)column {
|
||||
return column == 0 ? @"Model" : @"Submodel";
|
||||
}
|
||||
|
||||
#if 0
|
||||
- (id)browser:(NSBrowser *)browser child:(NSInteger)index ofItem:(id)item {
|
||||
return nil;
|
||||
}
|
||||
-(id)rootItemForBrowser:(NSBrowser *)browser {
|
||||
return _browserItems;
|
||||
}
|
||||
#endif
|
||||
|
||||
- (NSInteger)browser:(NSBrowser *)sender numberOfRowsInColumn:(NSInteger)column {
|
||||
|
||||
NSArray *a = [self itemsForBrowser: sender column: column];
|
||||
return [a count];
|
||||
}
|
||||
|
||||
|
||||
@end
|
Loading…
Reference in New Issue