504 lines
15 KiB
Plaintext
Executable File
504 lines
15 KiB
Plaintext
Executable File
/*
|
|
* VMSettingsController.mm - Preferences editing in Cocoa on Mac OS X
|
|
*
|
|
* Copyright (C) 2006-2010 Alexei Svitkine
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*/
|
|
|
|
#import "sysdeps.h"
|
|
#import "prefs.h"
|
|
|
|
// The _UINT64 define is needed to guard against a typedef mismatch with Snow Leopard headers.
|
|
#define _UINT64
|
|
|
|
#import "VMSettingsController.h"
|
|
|
|
#import "DiskType.h"
|
|
|
|
#include <unistd.h>
|
|
|
|
#include "SDL.h"
|
|
|
|
// NSInteger was added in 10.5 SDK.
|
|
#if MAC_OS_X_VERSION_MIN_REQUIRED < 1050
|
|
#if __LP64__ || NS_BUILD_32_LIKE_64
|
|
typedef long NSInteger;
|
|
#else
|
|
typedef int NSInteger;
|
|
#endif
|
|
#endif
|
|
|
|
const int CDROMRefNum = -62; // RefNum of driver
|
|
|
|
#ifdef STANDALONE_PREFS
|
|
void prefs_init()
|
|
{
|
|
}
|
|
|
|
void prefs_exit()
|
|
{
|
|
}
|
|
#endif
|
|
|
|
@implementation VMSettingsController
|
|
|
|
+ (id) sharedInstance
|
|
{
|
|
static VMSettingsController *_sharedInstance = nil;
|
|
if (!_sharedInstance) {
|
|
_sharedInstance = [[VMSettingsController allocWithZone:[self zone]] init];
|
|
}
|
|
return _sharedInstance;
|
|
}
|
|
|
|
- (id) init
|
|
{
|
|
self = [super initWithWindowNibName:@"VMSettingsWindow"];
|
|
|
|
cancelWasClicked = NO;
|
|
|
|
return self;
|
|
}
|
|
|
|
- (NSInteger) numberOfRowsInTableView: (NSTableView *) table
|
|
{
|
|
return [diskArray count];
|
|
}
|
|
|
|
- (id) tableView: (NSTableView *) table objectValueForTableColumn: (NSTableColumn *) col row: (NSInteger) row
|
|
{
|
|
DiskType *d = (DiskType*)[diskArray objectAtIndex:row];
|
|
|
|
if ([[col identifier] isEqualTo:@"isCDROMcol"]) {
|
|
return [NSString stringWithFormat:@"%d", [d isCDROM]];
|
|
}
|
|
|
|
return [d path];
|
|
}
|
|
|
|
- (void) tableView: (NSTableView *) table setObjectValue: (id) object forTableColumn: (NSTableColumn *) tableColumn row: (NSInteger) row
|
|
{
|
|
if ([[tableColumn identifier] isEqual:@"isCDROMcol"]) {
|
|
DiskType *d = (DiskType*)[diskArray objectAtIndex:row];
|
|
[d setIsCDROM:![d isCDROM]];
|
|
}
|
|
}
|
|
|
|
static NSString *getStringFromPrefs(const char *key)
|
|
{
|
|
const char *value = PrefsFindString(key);
|
|
if (value == NULL)
|
|
return @"";
|
|
return [NSString stringWithUTF8String: value];
|
|
}
|
|
|
|
- (void) setupGUI
|
|
{
|
|
diskArray = [[NSMutableArray alloc] init];
|
|
|
|
const char *dsk;
|
|
int index = 0;
|
|
while ((dsk = PrefsFindString("disk", index++)) != NULL) {
|
|
DiskType *disk = [[[DiskType alloc] init] autorelease];
|
|
[disk setPath:[NSString stringWithUTF8String: dsk ]];
|
|
[disk setIsCDROM:NO];
|
|
|
|
[diskArray addObject:disk];
|
|
}
|
|
|
|
/* Fetch all CDROMs */
|
|
index = 0;
|
|
while ((dsk = PrefsFindString("cdrom", index++)) != NULL) {
|
|
NSString *path = [NSString stringWithUTF8String: dsk ];
|
|
if (![path hasPrefix:@"/dev/"]) {
|
|
DiskType *disk = [[[DiskType alloc] init] autorelease];
|
|
[disk setPath:[NSString stringWithUTF8String: dsk ]];
|
|
[disk setIsCDROM:YES];
|
|
|
|
[diskArray addObject:disk];
|
|
}
|
|
}
|
|
|
|
[disks setDataSource: self];
|
|
[disks reloadData];
|
|
|
|
int bootdriver = PrefsFindInt32("bootdriver"), active = 0;
|
|
switch (bootdriver) {
|
|
case 0: active = 0; break;
|
|
case CDROMRefNum: active = 1; break;
|
|
}
|
|
[bootFrom selectItemAtIndex: active ];
|
|
|
|
[romFile setStringValue: getStringFromPrefs("rom") ];
|
|
[unixRoot setStringValue: getStringFromPrefs("extfs") ];
|
|
[disableCdrom setIntValue: PrefsFindBool("nocdrom") ];
|
|
int ramsize = PrefsFindInt32("ramsize");
|
|
if (ramsize > 1000) ramsize >>= 20;
|
|
[ramSize setIntValue: ramsize ];
|
|
[ramSizeStepper setIntValue: ramsize ];
|
|
|
|
int display_type = 0;
|
|
int dis_width = 640;
|
|
int dis_height = 480;
|
|
|
|
const char *str = PrefsFindString("screen");
|
|
if (str != NULL) {
|
|
if (sscanf(str, "win/%d/%d", &dis_width, &dis_height) == 2)
|
|
display_type = 0;
|
|
else if (sscanf(str, "dga/%d/%d", &dis_width, &dis_height) == 2)
|
|
display_type = 1;
|
|
}
|
|
|
|
[videoType selectItemAtIndex: display_type ];
|
|
[width setStringValue:[NSString stringWithFormat:@"%d", dis_width]];
|
|
[height setStringValue:[NSString stringWithFormat:@"%d", dis_height]];
|
|
|
|
int frameskip = PrefsFindInt32("frameskip");
|
|
int item = -1;
|
|
switch (frameskip) {
|
|
case 12: item = 0; break;
|
|
case 8: item = 1; break;
|
|
case 6: item = 2; break;
|
|
case 4: item = 3; break;
|
|
case 2: item = 4; break;
|
|
case 1: item = 5; break;
|
|
case 0: item = 6; break;
|
|
}
|
|
if (item >= 0)
|
|
[refreshRate selectItemAtIndex: item ];
|
|
|
|
[qdAccel setIntValue: PrefsFindBool("gfxaccel") ];
|
|
|
|
[disableSound setIntValue: PrefsFindBool("nosound") ];
|
|
[outDevice setStringValue: getStringFromPrefs("dsp") ];
|
|
[mixDevice setStringValue: getStringFromPrefs("mixer") ];
|
|
|
|
[useRawKeyCodes setIntValue: PrefsFindBool("keycodes") ];
|
|
[rawKeyCodes setStringValue: getStringFromPrefs("keycodefile") ];
|
|
[rawKeyCodes setEnabled:[useRawKeyCodes intValue]];
|
|
[browseRawKeyCodesButton setEnabled:[useRawKeyCodes intValue]];
|
|
|
|
int wheelmode = PrefsFindInt32("mousewheelmode"), wheel = 0;
|
|
switch (wheelmode) {
|
|
case 0: wheel = 0; break;
|
|
case 1: wheel = 1; break;
|
|
}
|
|
[mouseWheel selectItemAtIndex: wheel ];
|
|
|
|
[scrollLines setIntValue: PrefsFindInt32("mousewheellines") ];
|
|
[scrollLinesStepper setIntValue: PrefsFindInt32("mousewheellines") ];
|
|
|
|
[ignoreIllegalMemoryAccesses setIntValue: PrefsFindBool("ignoresegv") ];
|
|
[ignoreIllegalInstructions setIntValue: PrefsFindBool("ignoreillegal") ];
|
|
[dontUseCPUWhenIdle setIntValue: PrefsFindBool("idlewait") ];
|
|
[enableJIT setIntValue: PrefsFindBool("jit") ];
|
|
[enable68kDREmulator setIntValue: PrefsFindBool("jit68k") ];
|
|
|
|
[modemPort setStringValue: getStringFromPrefs("seriala") ];
|
|
[printerPort setStringValue: getStringFromPrefs("serialb") ];
|
|
[ethernetInterface setStringValue: getStringFromPrefs("ether") ];
|
|
}
|
|
|
|
- (void) editSettingsFor: (NSString *) vmdir sender: (id) sender
|
|
{
|
|
chdir([vmdir fileSystemRepresentation]);
|
|
AddPrefsDefaults();
|
|
AddPlatformPrefsDefaults();
|
|
LoadPrefs([vmdir fileSystemRepresentation]);
|
|
NSWindow *window = [self window];
|
|
[self setupGUI];
|
|
[NSApp runModalForWindow:window];
|
|
}
|
|
|
|
- (void) editSettingsForNewVM: (NSString *) vmdir sender: (id) sender
|
|
{
|
|
chdir([vmdir fileSystemRepresentation]);
|
|
AddPrefsDefaults();
|
|
AddPlatformPrefsDefaults();
|
|
LoadPrefs([vmdir fileSystemRepresentation]);
|
|
PrefsReplaceString("screen", "win/800/600");
|
|
PrefsReplaceString("extfs", "");
|
|
PrefsReplaceString("ether", "slirp");
|
|
PrefsReplaceInt32("ramsize", 64 << 20);
|
|
PrefsReplaceInt32("frameskip", 2);
|
|
PrefsReplaceBool("jit", true);
|
|
NSWindow *window = [self window];
|
|
[self setupGUI];
|
|
[NSApp runModalForWindow:window];
|
|
}
|
|
|
|
static NSString *makeRelativeIfNecessary(NSString *path)
|
|
{
|
|
char cwd[1024], filename[1024];
|
|
int cwdlen;
|
|
strlcpy(filename, [path fileSystemRepresentation], sizeof(filename));
|
|
getcwd(cwd, sizeof(cwd));
|
|
cwdlen = strlen(cwd);
|
|
if (!strncmp(cwd, filename, cwdlen)) {
|
|
if (cwdlen >= 0 && cwd[cwdlen-1] != '/')
|
|
cwdlen++;
|
|
return [NSString stringWithUTF8String: filename + cwdlen];
|
|
}
|
|
return path;
|
|
}
|
|
|
|
- (IBAction) addDisk: (id) sender
|
|
{
|
|
NSOpenPanel *open = [NSOpenPanel openPanel];
|
|
[open setCanChooseDirectories:YES];
|
|
[open setAccessoryView:isCDROM];
|
|
[open setAllowsMultipleSelection:NO];
|
|
[open setTreatsFilePackagesAsDirectories:YES];
|
|
[open beginSheetForDirectory: [[NSFileManager defaultManager] currentDirectoryPath]
|
|
file: @"Unknown"
|
|
modalForWindow: [self window]
|
|
modalDelegate: self
|
|
didEndSelector: @selector(_addDiskEnd: returnCode: contextInfo:)
|
|
contextInfo: nil];
|
|
}
|
|
|
|
- (void) _addDiskEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo
|
|
{
|
|
if (theReturnCode == NSOKButton) {
|
|
DiskType *d = [[[DiskType alloc] init] autorelease];
|
|
[d setPath:makeRelativeIfNecessary([open filename])];
|
|
|
|
[d setIsCDROM:([isCDROMcheckbox state] == NSOnState)];
|
|
|
|
[diskArray addObject: d];
|
|
[disks reloadData];
|
|
}
|
|
}
|
|
|
|
- (IBAction) removeDisk: (id) sender
|
|
{
|
|
int selectedRow = [disks selectedRow];
|
|
if (selectedRow >= 0) {
|
|
[diskArray removeObjectAtIndex: selectedRow];
|
|
[disks reloadData];
|
|
}
|
|
}
|
|
|
|
- (IBAction) createDisk: (id) sender
|
|
{
|
|
NSSavePanel *save = [NSSavePanel savePanel];
|
|
[save setAccessoryView: diskSaveSize];
|
|
[save setTreatsFilePackagesAsDirectories:YES];
|
|
[save beginSheetForDirectory: [[NSFileManager defaultManager] currentDirectoryPath]
|
|
file: @"New.dsk"
|
|
modalForWindow: [self window]
|
|
modalDelegate: self
|
|
didEndSelector: @selector(_createDiskEnd: returnCode: contextInfo:)
|
|
contextInfo: nil];
|
|
}
|
|
|
|
- (void) _createDiskEnd: (NSSavePanel *) save returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo
|
|
{
|
|
if (theReturnCode == NSOKButton) {
|
|
int size = [diskSaveSizeField intValue];
|
|
if (size >= 0 && size <= 10000) {
|
|
char cmd[1024];
|
|
snprintf(cmd, sizeof(cmd), "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", [[save filename] UTF8String], [diskSaveSizeField intValue]);
|
|
int ret = system(cmd);
|
|
if (ret == 0) {
|
|
DiskType *d = [[[DiskType alloc] init] autorelease];
|
|
[d setPath:makeRelativeIfNecessary([save filename])];
|
|
[d setIsCDROM:NO];
|
|
|
|
[diskArray addObject: d];
|
|
[disks reloadData];
|
|
}
|
|
}
|
|
}
|
|
[(NSData *)theContextInfo release];
|
|
}
|
|
|
|
- (IBAction) useRawKeyCodesClicked: (id) sender
|
|
{
|
|
[rawKeyCodes setEnabled:[useRawKeyCodes intValue]];
|
|
[browseRawKeyCodesButton setEnabled:[useRawKeyCodes intValue]];
|
|
}
|
|
|
|
- (IBAction) browseForROMFileClicked: (id) sender
|
|
{
|
|
NSOpenPanel *open = [NSOpenPanel openPanel];
|
|
[open setCanChooseDirectories:NO];
|
|
[open setAllowsMultipleSelection:NO];
|
|
[open setTreatsFilePackagesAsDirectories:YES];
|
|
[open beginSheetForDirectory: @""
|
|
file: [romFile stringValue]
|
|
modalForWindow: [self window]
|
|
modalDelegate: self
|
|
didEndSelector: @selector(_browseForROMFileEnd: returnCode: contextInfo:)
|
|
contextInfo: nil];
|
|
}
|
|
|
|
- (void) _browseForROMFileEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo
|
|
{
|
|
if (theReturnCode == NSOKButton) {
|
|
[romFile setStringValue: makeRelativeIfNecessary([open filename])];
|
|
}
|
|
}
|
|
|
|
- (IBAction) browseForUnixRootClicked: (id) sender
|
|
{
|
|
NSOpenPanel *open = [NSOpenPanel openPanel];
|
|
[open setCanChooseDirectories:YES];
|
|
[open setCanChooseFiles:NO];
|
|
[open setAllowsMultipleSelection:NO];
|
|
[open beginSheetForDirectory: @""
|
|
file: [unixRoot stringValue]
|
|
modalForWindow: [self window]
|
|
modalDelegate: self
|
|
didEndSelector: @selector(_browseForUnixRootEnd: returnCode: contextInfo:)
|
|
contextInfo: nil];
|
|
}
|
|
|
|
- (void) _browseForUnixRootEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo
|
|
{
|
|
if (theReturnCode == NSOKButton) {
|
|
[unixRoot setStringValue: makeRelativeIfNecessary([open filename])];
|
|
}
|
|
}
|
|
|
|
- (IBAction) browseForKeyCodesFileClicked: (id) sender
|
|
{
|
|
NSOpenPanel *open = [NSOpenPanel openPanel];
|
|
[open setCanChooseDirectories:NO];
|
|
[open setAllowsMultipleSelection:NO];
|
|
[open setTreatsFilePackagesAsDirectories:YES];
|
|
[open beginSheetForDirectory: @""
|
|
file: [unixRoot stringValue]
|
|
modalForWindow: [self window]
|
|
modalDelegate: self
|
|
didEndSelector: @selector(_browseForKeyCodesFileEnd: returnCode: contextInfo:)
|
|
contextInfo: nil];
|
|
}
|
|
|
|
- (void) _browseForKeyCodesFileEnd: (NSOpenPanel *) open returnCode: (int) theReturnCode contextInfo: (void *) theContextInfo
|
|
{
|
|
if (theReturnCode == NSOKButton) {
|
|
[rawKeyCodes setStringValue: makeRelativeIfNecessary([open filename])];
|
|
}
|
|
}
|
|
|
|
- (void) cancelEdit: (id) sender
|
|
{
|
|
#ifdef STANDALONE_PREFS
|
|
PrefsExit();
|
|
#endif
|
|
[[self window] close];
|
|
[NSApp stopModal];
|
|
cancelWasClicked = YES;
|
|
}
|
|
|
|
- (void) saveChanges: (id) sender
|
|
{
|
|
// Remove all disks
|
|
while (PrefsFindString("disk"))
|
|
PrefsRemoveItem("disk");
|
|
// Remove all cdroms (but keep the ones in /dev/)
|
|
const char *path;
|
|
int index = 0;
|
|
while ((path = PrefsFindString("cdrom", index)) != NULL) {
|
|
NSString *p = [NSString stringWithUTF8String: path];
|
|
if (![p hasPrefix:@"/dev/"]) {
|
|
PrefsRemoveItem("cdrom", index);
|
|
} else {
|
|
// only increase the index if the current entry has not been deleted
|
|
// if it has been deleted, the next entry is on the current entrys index
|
|
index++;
|
|
}
|
|
}
|
|
|
|
// Write all disks
|
|
for (int i = 0; i < [diskArray count]; i++) {
|
|
DiskType *d = [diskArray objectAtIndex:i];
|
|
PrefsAddString([d isCDROM] ? "cdrom" : "disk", [[d path] UTF8String]);
|
|
}
|
|
|
|
PrefsReplaceInt32("bootdriver", ([bootFrom indexOfSelectedItem] == 1 ? CDROMRefNum : 0));
|
|
PrefsReplaceString("rom", [[romFile stringValue] UTF8String]);
|
|
PrefsReplaceString("extfs", [[unixRoot stringValue] UTF8String]);
|
|
PrefsReplaceBool("nocdrom", [disableCdrom intValue]);
|
|
PrefsReplaceInt32("ramsize", [ramSize intValue] << 20);
|
|
|
|
char pref[256];
|
|
snprintf(pref, sizeof(pref), "%s/%d/%d", [videoType indexOfSelectedItem] == 0 ? "win" : "dga", [width intValue], [height intValue]);
|
|
PrefsReplaceString("screen", pref);
|
|
|
|
int rate = 8;
|
|
switch ([refreshRate indexOfSelectedItem]) {
|
|
case 0: rate = 12; break;
|
|
case 1: rate = 8; break;
|
|
case 2: rate = 6; break;
|
|
case 3: rate = 4; break;
|
|
case 4: rate = 2; break;
|
|
case 5: rate = 1; break;
|
|
case 6: rate = 0; break;
|
|
}
|
|
PrefsReplaceInt32("frameskip", rate);
|
|
PrefsReplaceBool("gfxaccel", [qdAccel intValue]);
|
|
|
|
PrefsReplaceBool("nosound", [disableSound intValue]);
|
|
PrefsReplaceString("dsp", [[outDevice stringValue] UTF8String]);
|
|
PrefsReplaceString("mixer", [[mixDevice stringValue] UTF8String]);
|
|
|
|
PrefsReplaceBool("keycodes", [useRawKeyCodes intValue]);
|
|
PrefsReplaceString("keycodefile", [[rawKeyCodes stringValue] UTF8String]);
|
|
|
|
PrefsReplaceInt32("mousewheelmode", [mouseWheel indexOfSelectedItem]);
|
|
PrefsReplaceInt32("mousewheellines", [scrollLines intValue]);
|
|
|
|
PrefsReplaceBool("ignoresegv", [ignoreIllegalMemoryAccesses intValue]);
|
|
PrefsReplaceBool("ignoreillegal", [ignoreIllegalInstructions intValue]);
|
|
PrefsReplaceBool("idlewait", [dontUseCPUWhenIdle intValue]);
|
|
PrefsReplaceBool("jit", [enableJIT intValue]);
|
|
PrefsReplaceBool("jit68k", [enable68kDREmulator intValue]);
|
|
|
|
PrefsReplaceString("seriala", [[modemPort stringValue] UTF8String]);
|
|
PrefsReplaceString("serialb", [[printerPort stringValue] UTF8String]);
|
|
PrefsReplaceString("ether", [[ethernetInterface stringValue] UTF8String]);
|
|
SavePrefs();
|
|
#ifdef STANDALONE_PREFS
|
|
PrefsExit();
|
|
#endif
|
|
|
|
[[self window] close];
|
|
[NSApp stopModal];
|
|
cancelWasClicked = NO;
|
|
|
|
// quit
|
|
#if !SDL_VERSION_ATLEAST(3, 0, 0)
|
|
#define SDL_EVENT_QUIT SDL_QUIT
|
|
#endif
|
|
SDL_Event event = { .type = SDL_EVENT_QUIT };
|
|
SDL_PushEvent(&event);
|
|
}
|
|
|
|
- (BOOL) cancelWasClicked
|
|
{
|
|
return cancelWasClicked;
|
|
}
|
|
|
|
- (void) dealloc
|
|
{
|
|
[super dealloc];
|
|
}
|
|
|
|
@end
|
|
|