macemu/SheepShaver/src/MacOSX/Launcher/VMSettingsController.mm

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