Compare commits

..
8 Commits
Author SHA1 Message Date
Kelvin Sherlock d058aa6588 233 version bump 2021-07-01 19:10:38 -04:00
Kelvin Sherlock 3889b42c14 add secret listmedia/listslots options in the right-click menu
when option key pressed.
also adjust log window to use monospace font, show error/signal in red, and don't mention a successful exit.
tweaks to file handling/task complete so task complete logic is delayed until file handle is drained.
2021-06-18 21:57:46 -04:00
Kelvin Sherlock 34fcc3b3ed more useful scripts. 2021-06-17 23:44:15 -04:00
Kelvin Sherlock c10f2153ff unused code to guess what sort of media a disk image is.
The general idea would be drag-n-drop a file (or double-click from the disk image window, etc)
and auto-place it in the right place.
2021-06-17 23:43:31 -04:00
Kelvin Sherlock 23afbd8952 move url update to main thread to prevent core animation mutation errors (???) 2021-06-17 13:25:39 -04:00
Kelvin Sherlock 5fbc00e375 print a descriptive error message when vmnet_helper fails. 2021-06-16 23:47:16 -04:00
Kelvin Sherlock 5dd04cd3b7 Apple III titan card (mame 2.33) 2021-06-16 23:46:47 -04:00
Kelvin Sherlock 27bfc1cd8b default to window mode since it's less surprising 2021-06-16 23:46:26 -04:00
14 changed files with 443 additions and 58 deletions

No files matched your search

+4 -4
View File
@@ -1498,7 +1498,7 @@
CODE_SIGN_ENTITLEMENTS = Ample/Ample.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 15;
CURRENT_PROJECT_VERSION = 16;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -1509,7 +1509,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = "0.233-wip";
MARKETING_VERSION = 0.233;
PRODUCT_BUNDLE_IDENTIFIER = com.ksherlock.ample;
PRODUCT_NAME = "$(TARGET_NAME)";
};
@@ -1522,7 +1522,7 @@
CODE_SIGN_ENTITLEMENTS = Ample/Ample.entitlements;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
CURRENT_PROJECT_VERSION = 15;
CURRENT_PROJECT_VERSION = 16;
ENABLE_HARDENED_RUNTIME = YES;
FRAMEWORK_SEARCH_PATHS = (
"$(inherited)",
@@ -1533,7 +1533,7 @@
"$(inherited)",
"@executable_path/../Frameworks",
);
MARKETING_VERSION = "0.233-wip";
MARKETING_VERSION = 0.233;
PRODUCT_BUNDLE_IDENTIFIER = com.ksherlock.ample;
PRODUCT_NAME = "$(TARGET_NAME)";
};
+26 -1
View File
@@ -573,6 +573,29 @@ Gw
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="Iti-F9-p35"/>
<menuItem title="List Media…" id="M5h-4W-0nV">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="listMedia:" target="-2" id="IO7-MG-zud"/>
<binding destination="-2" name="hidden" keyPath="optionKey" id="LhL-2l-iss">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</menuItem>
<menuItem title="List Slots…" id="cNj-Sb-KkE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="listSlots:" target="-2" id="3nb-mV-eUK"/>
<binding destination="-2" name="hidden" keyPath="optionKey" id="dwp-Kn-LfC">
<dictionary key="options">
<string key="NSValueTransformerName">NSNegateBoolean</string>
</dictionary>
</binding>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="yZx-W2-lZg"/>
<menuItem title="Reset All" id="PQ0-yO-SKz">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
@@ -598,11 +621,13 @@ Gw
</connections>
</menuItem>
</items>
<connections>
<outlet property="delegate" destination="-2" id="wqC-IG-63F"/>
</connections>
<point key="canvasLocation" x="-121" y="-2"/>
</menu>
</objects>
<resources>
<image name="NSAppleMenuImage" width="11" height="14"/>
<image name="NSAppleMenuImage" width="128" height="128"/>
</resources>
</document>
+1 -1
View File
@@ -3,7 +3,7 @@
<plist version="1.0">
<dict>
<key>MameComponentsDate</key>
<date>2021-06-15T16:00:00Z</date>
<date>2021-07-01T16:00:00Z</date>
<key>UseCustomMame</key>
<false/>
<key>AutoCloseLogWindow</key>
+5 -19
View File
@@ -386,9 +386,6 @@ enum {
[_taskIndex removeAllObjects];
[self setCurrentCount: 0];
[self setActive: NO];
//[_tableView reloadData];
//[_tableView setNeedsDisplay: YES]; // doesn't work...
}
- (IBAction)downloadMissing:(id)sender {
@@ -405,7 +402,6 @@ enum {
if (delta) {
[self setActive: YES];
//[_tableView reloadData];
}
}
- (IBAction)showRomFolder:(id)sender {
@@ -458,14 +454,12 @@ enum {
[self downloadItem: item];
[self setActive: YES];
//[self redrawRow: [item index]];
}
- (IBAction)cancel:(id)sender {
DownloadItem *item = [self clickedItem];
if (!item) return;
[item cancelDownload];
//[self redrawRow: [item index]];
}
// binding screws up with placeholder.
@@ -492,8 +486,7 @@ enum {
NSUInteger tag = [sender tag];
[sender setState: NSControlStateValueOn];
for (NSButton *b in _filterButtons) {
if (b != sender) [b setState: NSControlStateValueOff];
}
@@ -561,9 +554,6 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) {
if (item) {
[item completeWithError: error];
//NSUInteger row = [item index];
//[self redrawRow: row];
}
});
@@ -587,16 +577,12 @@ static NSInteger TaskStatusCode(NSURLSessionTask *task) {
[fm moveItemAtURL: location toURL: dest error: &error];
DownloadItem *item = [_taskIndex objectForKey: task];
[item setLocalURL: dest];
/*
dispatch_async(dispatch_get_main_queue(), ^(void){
NSMutableDictionary *taskIndex = self->_taskIndex;
DownloadItem *item = [taskIndex objectForKey: task];
[item setLocalURL: dest];
}
*/
});
NSLog(@"%@", src);
}
+1 -1
View File
@@ -10,7 +10,7 @@
NS_ASSUME_NONNULL_BEGIN
@interface LaunchWindowController : NSWindowController <NSBrowserDelegate>
@interface LaunchWindowController : NSWindowController <NSBrowserDelegate, NSMenuDelegate>
@end
+68 -1
View File
@@ -79,6 +79,9 @@ static NSString *kContextMachine = @"kContextMachine";
@property (strong) IBOutlet NSWindow *addBookmarkWindow;
@property (strong) NSString *bookmarkName;
@property (weak) IBOutlet NSTextField *bookmarkTextField;
@property BOOL optionKey;
@end
@interface LaunchWindowController (SoftwareList)
@@ -146,7 +149,7 @@ static int EffectsIndex(NSString *str) {
[self setMameSamples: NO];
[self setMameSquarePixels: NO];
[self setMameDebug: NO];
[self setMameWindowMode: 0];
[self setMameWindowMode: 1]; // default = 1x window.
[self setMameBackend: 0];
[self setMameEffects: 0];
@@ -600,6 +603,62 @@ static NSString *ShellQuote(NSString *s) {
}
- (IBAction)listMedia:(id)sender {
[[self window] makeFirstResponder: nil]; // in case text is being edited...
if (!_machine) return;
NSMutableArray *argv = [NSMutableArray new];
[argv addObject: _machine];
[argv addObject: @"-listmedia"];
NSArray *tmp;
tmp = [_slotController args];
if ([tmp count]) {
[argv addObjectsFromArray: tmp];
}
#if 0
tmp = [_mediaController args];
if ([tmp count]) {
[argv addObjectsFromArray: tmp];
}
#endif
[LogWindowController controllerForArgs: argv close: NO];
}
- (IBAction)listSlots:(id)sender {
[[self window] makeFirstResponder: nil]; // in case text is being edited...
if (!_machine) return;
NSMutableArray *argv = [NSMutableArray new];
[argv addObject: _machine];
[argv addObject: @"-listslots"];
NSArray *tmp;
tmp = [_slotController args];
if ([tmp count]) {
[argv addObjectsFromArray: tmp];
}
#if 0
tmp = [_mediaController args];
if ([tmp count]) {
[argv addObjectsFromArray: tmp];
}
#endif
[LogWindowController controllerForArgs: argv close: NO];
}
-(IBAction)exportShellScript: (id)sender {
NSSavePanel *p = [NSSavePanel savePanel];
@@ -924,4 +983,12 @@ static NSString *ShellQuote(NSString *s) {
}
#pragma mark - NSMenuDelegate
-(void)menuNeedsUpdate:(NSMenu *)menu {
NSEventModifierFlags modifiers = [NSEvent modifierFlags];
[self setOptionKey: modifiers & NSEventModifierFlagOption ? YES : NO];
}
@end
+5
View File
@@ -12,8 +12,13 @@ NS_ASSUME_NONNULL_BEGIN
@interface LogWindowController : NSWindowController <NSWindowDelegate>
#if 0
+(id)controllerForTask: (NSTask *)task;
+(id)controllerForTask: (NSTask *)task close: (BOOL)close;
#endif
+(id)controllerForArgs: (NSArray *)args;
+(id)controllerForArgs: (NSArray *)args close: (BOOL)close;
@end
NS_ASSUME_NONNULL_END
+53 -30
View File
@@ -19,6 +19,10 @@ static NSMutableSet *LogWindows;
@implementation LogWindowController {
NSTask *_task;
NSFileHandle *_handle;
NSFont *_font;
BOOL _close;
BOOL _eof;
}
+(void)initialize {
@@ -30,17 +34,14 @@ static NSMutableSet *LogWindows;
}
+(id)controllerForTask: (NSTask *)task {
+(id)controllerForTask: (NSTask *)task close: (BOOL)close{
LogWindowController *controller = [[LogWindowController alloc] initWithWindowNibName: @"LogWindow"];
[controller runTask: task];
[controller runTask: task close: close];
return controller;
}
+(id)controllerForArgs: (NSArray *)args {
// NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+(id)controllerForArgs: (NSArray *)args close: (BOOL)close {
NSURL *url = MameURL();
@@ -64,15 +65,24 @@ static NSMutableSet *LogWindows;
[task setArguments: args];
return [LogWindowController controllerForTask: task];
return [LogWindowController controllerForTask: task close: close];
}
+(id)controllerForArgs: (NSArray *)args {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
BOOL close = [defaults boolForKey: kAutoCloseLogWindow];
return [self controllerForArgs: args close: close];
}
- (void)windowDidLoad {
[super windowDidLoad];
[LogWindows addObject: self];
_font = [NSFont userFixedPitchFontOfSize: 0];
// Implement this method to handle any initialization after your window controller's window has been loaded from its nib file.
}
-(void)appendString: (NSString *)string
@@ -80,7 +90,10 @@ static NSMutableSet *LogWindows;
if ([string length])
{
// needs explicit color attribute for proper dark mode support.
NSDictionary *attr = @{ NSForegroundColorAttributeName: [NSColor textColor] };
NSDictionary *attr = @{
NSForegroundColorAttributeName: [NSColor textColor],
NSFontAttributeName: _font,
};
NSAttributedString *astr = [[NSAttributedString alloc] initWithString: string attributes: attr];
[[_textView textStorage] appendAttributedString: astr];
}
@@ -93,10 +106,12 @@ static NSMutableSet *LogWindows;
}
}
-(NSError *)runTask: (NSTask *)task {
-(NSError *)runTask: (NSTask *)task close: (BOOL)close {
if (_task) return nil;
_close = close;
_eof = NO;
NSPipe *pipe = [NSPipe pipe];
@@ -130,16 +145,6 @@ static NSMutableSet *LogWindows;
}
}
#if 0
if (error) {
// NSURL *url = [task executableURL];
// NSString *path = [NSString stringWithCString: [url fileSystemRepresentation] encoding: NSUTF8StringEncoding];
NSLog(@"NSTask error. Path = %s error = %@", path, error);
// [self appendString: path];
// [self appendString: [error description]];
return error;
}
#endif
_task = task;
NSString *title = [NSString stringWithFormat: @"Ample Log - %u", [task processIdentifier]];
[[self window] setTitle: title];
@@ -150,6 +155,7 @@ static NSMutableSet *LogWindows;
NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
[nc addObserver: self
selector: @selector(taskComplete:)
name: NSTaskDidTerminateNotification
@@ -160,6 +166,7 @@ static NSMutableSet *LogWindows;
object: _handle];
[_handle readInBackgroundAndNotify];
[[self window] setDocumentEdited: YES];
return nil;
}
@@ -172,21 +179,33 @@ static NSMutableSet *LogWindows;
// read complete, queue up another.
NSDictionary *dict = [notification userInfo];
NSData *data = [dict objectForKey: NSFileHandleNotificationDataItem];
if ([data length])
{
NSString *string = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];
[self appendString: string];
[_handle readInBackgroundAndNotify];
} else {
[self appendString: @"\n"]; // -listmedia sometimes causes display issues.
_eof = YES;
//[_textView setNeedsDisplay: YES]; // -listmedia sometimes weird.
}
}
-(void)taskCompleteHack {
}
/* hask! task complete may occur while output still being processed. add a delay to compensate. */
-(void)taskComplete: (NSNotification *)notification
{
if (!_eof) {
[self performSelector: @selector(taskComplete:) withObject: notification afterDelay: 0.5];
return;
}
BOOL ok = NO;
NSTaskTerminationReason reason;
int status;
@@ -200,7 +219,7 @@ static NSMutableSet *LogWindows;
if (status == 0)
{
string = @"\n\n[Success]\n\n";
//string = @"\n\n[Success]\n\n";
ok = YES;
}
else string = @"\n\n[An error occurred]\n\n";
@@ -209,18 +228,22 @@ static NSMutableSet *LogWindows;
{
string = [NSString stringWithFormat: @"\n\n[Caught signal %d (%s)]\n\n", status, strsignal(status)];
}
[self appendString: string];
if (string) {
NSDictionary *attr = @{
NSForegroundColorAttributeName: [NSColor systemRedColor],
NSFontAttributeName: _font,
};
NSAttributedString *astr = [[NSAttributedString alloc] initWithString: string attributes: attr];
[self appendAttributedString: astr];
}
_handle = nil;
_task = nil;
[[self window] setDocumentEdited: NO];
if (ok && [[NSUserDefaults standardUserDefaults] boolForKey: kAutoCloseLogWindow]) {
if (ok && _close) {
[[self window] close];
//[LogWindows removeObject: self]; // close sends WindowWillClose notification.
}
}
+141
View File
@@ -59,3 +59,144 @@ BOOL MediaEqual(const Media *lhs, const Media *rhs) {
return YES;
#undef _
}
#include <unistd.h>
#include <sys/stat.h>
enum {
MediaType_5_25,
MediaType_3_5,
MediaType_HardDisk,
MediaType_CD,
MediaType_Cassette,
};
#define _x2(a,b) (a | (b << 8))
#define _x3(a,b,c) (a | (b << 8) | (c << 16))
#define _x4(a,b,c, d) (a | (b << 8) | (c << 16) | (d << 24))
static unsigned hash(const char *cp) {
unsigned rv = 0;
int i, shift;
if (!cp) return 0;
for (i = 0, shift = 0; i < 4; ++i, shift += 8) {
unsigned c = cp[0];
if (!c) break;
c = tolower(c);
rv |= (c << shift);
}
if (i > 4) return 0;
return rv;
}
const char *extname(const char *path) {
const char *rv = NULL;
if (!path) return path;
for(unsigned i = 0; ; ++i) {
unsigned c = path[i];
if (c == 0) break;
if (c == '/') rv = NULL;
if (c == '.') rv = path + i + 1;
}
if (rv && !*rv) rv = NULL;
return rv;
}
int ClassifyMediaFile(NSString *file) {
struct stat st;
ssize_t size;
unsigned char buffer[128];
int fd;
const char *path = [file fileSystemRepresentation];
const char *ext = extname(path);
unsigned ext_hash = hash(ext);
memset(&st, 0, sizeof(st));
memset(buffer, 0, sizeof(buffer));
fd = open(path, O_RDONLY);
if (fd < 0) return -1;
fstat(fd, &st);
size = read(fd, buffer, sizeof(buffer));
close(fd);
if (size <= 0) return -1;
// 13 sector support ? not on an event 512 block boundary.
// = 116480 bytes.
/* woz 1/2 ? */
if (!memcmp(buffer, "WOZ1\xff\x0a\x0d\x0a", 8) || !memcmp(buffer, "WOZ2\xff\x0a\x0d\x0a", 8)) {
if (!memcmp(buffer + 12, "INFO", 4)) {
unsigned type = buffer[21]; // 1 = 5.25, 2 = 3.5
if (type == 1) return MediaType_5_25;
if (type == 2) return MediaType_3_5;
}
return -1;
}
/* 2mg? */
if (!memcmp(buffer, "2IMG", 4)) {
int format = OSReadLittleInt32(buffer, 0x0c); // 0 - dos order, 1 = prodos order, 2 = nib data
int blocks = OSReadLittleInt32(buffer, 0x14); // prodos only.
//int bytes = OSReadLittleInt32(buffer, 0x1c);
if (format == 2 || format == 0) return MediaType_5_25; // nib and dos order
if (blocks == 280) return MediaType_5_25;
if (blocks == 800 || blocks == 1600 || blocks == 1440 || blocks == 2880) return MediaType_3_5;
if (blocks > 2880) return MediaType_HardDisk; //
return -1;
}
/* chd? */
if (!memcmp(buffer, "MComprHD", 8)) {
static int offsets[] = { 0, 0, 0, 28, 28, 32}; // offset for logival bytes.
int version = OSReadBigInt32(buffer, 12);
if (version >= 3 && version <= 5) {
long bytes = OSReadBigInt64(buffer, offsets[version]);
long blocks = bytes >> 9;
if ((bytes & 511) == 0) {
if (blocks == 800 || blocks == 1600 || blocks == 1440 || blocks == 2880) return MediaType_3_5;
if (blocks == 280) return MediaType_5_25;
if (blocks > 2880) return MediaType_HardDisk; // iso?
}
}
return -1;
}
/* dc 4.2? magic is pretty weak. */
if (buffer[0x52] == 0x01 && buffer[0x53] == 0x00 && buffer[0] >= 1 && buffer[0] <= 0x3f) {
int dsize = OSReadBigInt32(buffer, 0x40);
int tsize = OSReadBigInt32(buffer, 0x44);
if (dsize + tsize + 0x54 == st.st_size && (size & 511) == 0) {
int blocks = dsize >>= 9;
if (blocks == 800 || blocks == 1600 || blocks == 1440 || blocks == 2880) return MediaType_3_5;
}
}
switch(ext_hash) {
case _x3('n', 'i', 'b'): return MediaType_5_25;
case _x3('w', 'a', 'v'): return MediaType_Cassette;
case _x3('i', 's', 'o'):
case _x3('c', 'u', 'e'):
case _x3('c', 'd', 'r'):
return MediaType_CD;
// po, do, hdv, dsk - based on size
case _x2('d', 'o'):
case _x3('d', 's', 'k'):
case _x2('p', 'o'):
case _x3('h', 'd', 'v'): // usually 3.5 or hard drive
if (st.st_size <= 143360) return MediaType_5_25;
if (st.st_size <= 1474560) return MediaType_3_5;
return MediaType_HardDisk;
return MediaType_HardDisk;
}
return -1;
}
+118
View File
@@ -129,6 +129,14 @@
<key>devname</key>
<string>a2aplcrd</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard Sound/Speech I</string>
<key>devname</key>
<string>a2mockbd</string>
</dict>
<dict>
<key>value</key>
<string>thclock</string>
@@ -137,6 +145,14 @@
<key>devname</key>
<string>a2thunpl</string>
</dict>
<dict>
<key>value</key>
<string>titan3plus2</string>
<key>description</key>
<string>Titan /// Plus //</string>
<key>devname</key>
<string>titan3p2</string>
</dict>
</array>
</dict>
<dict>
@@ -194,6 +210,14 @@
<key>devname</key>
<string>a2aplcrd</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard Sound/Speech I</string>
<key>devname</key>
<string>a2mockbd</string>
</dict>
<dict>
<key>value</key>
<string>thclock</string>
@@ -202,6 +226,14 @@
<key>devname</key>
<string>a2thunpl</string>
</dict>
<dict>
<key>value</key>
<string>titan3plus2</string>
<key>description</key>
<string>Titan /// Plus //</string>
<key>devname</key>
<string>titan3p2</string>
</dict>
</array>
</dict>
<dict>
@@ -259,6 +291,14 @@
<key>devname</key>
<string>a2aplcrd</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard Sound/Speech I</string>
<key>devname</key>
<string>a2mockbd</string>
</dict>
<dict>
<key>value</key>
<string>thclock</string>
@@ -267,6 +307,14 @@
<key>devname</key>
<string>a2thunpl</string>
</dict>
<dict>
<key>value</key>
<string>titan3plus2</string>
<key>description</key>
<string>Titan /// Plus //</string>
<key>devname</key>
<string>titan3p2</string>
</dict>
</array>
</dict>
<dict>
@@ -324,6 +372,14 @@
<key>devname</key>
<string>a2aplcrd</string>
</dict>
<dict>
<key>value</key>
<string>mockingboard</string>
<key>description</key>
<string>Sweet Micro Systems Mockingboard Sound/Speech I</string>
<key>devname</key>
<string>a2mockbd</string>
</dict>
<dict>
<key>value</key>
<string>thclock</string>
@@ -332,6 +388,14 @@
<key>devname</key>
<string>a2thunpl</string>
</dict>
<dict>
<key>value</key>
<string>titan3plus2</string>
<key>description</key>
<string>Titan /// Plus //</string>
<key>devname</key>
<string>titan3p2</string>
</dict>
</array>
</dict>
<dict>
@@ -1129,6 +1193,60 @@
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>titan3p2</string>
<key>slots</key>
<array>
<dict>
<key>name</key>
<string>:gameio</string>
<key>options</key>
<array>
<dict>
<key>value</key>
<string></string>
<key>description</key>
<string>—None—</string>
<key>default</key>
<true/>
</dict>
<dict>
<key>value</key>
<string>joy</string>
<key>description</key>
<string>Apple II analog joysticks</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>paddles</string>
<key>description</key>
<string>Apple II paddles</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>compeyes</string>
<key>description</key>
<string>Digital Vision ComputerEyes</string>
<key>default</key>
<false/>
</dict>
<dict>
<key>value</key>
<string>gizmo</string>
<key>description</key>
<string>HAL Labs Gizmo</string>
<key>default</key>
<false/>
</dict>
</array>
</dict>
</array>
</dict>
</array>
<key>software</key>
<array>
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
export DYLD_FALLBACK_FRAMEWORK_PATH=../embedded
../embedded/mame64 $* -listmedia
+6
View File
@@ -0,0 +1,6 @@
#!/bin/sh
export DYLD_FALLBACK_FRAMEWORK_PATH=../embedded
../embedded/mame64 $* -listslots
Regular → Executable
View File
File mode changed.
+9 -1
View File
@@ -277,7 +277,15 @@ void vm_startup(void) {
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
interface = NULL;
}
errx(1,"vmnet_start_interface failed");
warnx("vmnet_start_interface failed");
if (geteuid() != 0) {
fputs(
"\n\n"
"\tvmnet_helper must be run as root.\n"
"\tGo to Ample -> Preferences and Fix VMNet Permissions.\n\n"
,stderr);
}
exit(1);
}