aboutsummaryrefslogtreecommitdiff
path: root/macosx/PcsxController.m
diff options
context:
space:
mode:
Diffstat (limited to 'macosx/PcsxController.m')
-rw-r--r--macosx/PcsxController.m425
1 files changed, 425 insertions, 0 deletions
diff --git a/macosx/PcsxController.m b/macosx/PcsxController.m
new file mode 100644
index 0000000..0bb9144
--- /dev/null
+++ b/macosx/PcsxController.m
@@ -0,0 +1,425 @@
+#import <Cocoa/Cocoa.h>
+#import "PcsxController.h"
+#import "ConfigurationController.h"
+#import "EmuThread.h"
+#include "psxcommon.h"
+#include "plugins.h"
+#include "misc.h"
+#include "ExtendedKeys.h"
+
+NSDictionary *prefStringKeys;
+NSDictionary *prefByteKeys;
+NSMutableArray *biosList;
+NSString *saveStatePath;
+
+@implementation PcsxController
+
+- (IBAction)ejectCD:(id)sender
+{
+ NSMutableString *deviceName;
+ NSTask *ejectTask;
+ NSRange rdiskRange;
+
+ BOOL wasPaused = [EmuThread pauseSafe];
+
+ /* close connection to current cd */
+ if ([EmuThread active])
+ CDR_close();
+
+ // switch to another ISO if using internal image reader, otherwise eject the CD
+ if (UsingIso()) {
+ NSOpenPanel* openDlg = [NSOpenPanel openPanel];
+
+ [openDlg setCanChooseFiles:YES];
+ [openDlg setCanChooseDirectories:NO];
+
+ if ([openDlg runModal] == NSOKButton) {
+ NSArray* files = [openDlg filenames];
+ SetCdOpenCaseTime(time(NULL) + 2);
+ SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
+ }
+ } else {
+ if (CDR_getDriveLetter() != nil) {
+ deviceName = [NSMutableString stringWithCString:CDR_getDriveLetter()];
+
+ // delete the 'r' in 'rdisk'
+ rdiskRange = [deviceName rangeOfString:@"rdisk"];
+ if (rdiskRange.length != 0) {
+ rdiskRange.length = 1;
+ [deviceName deleteCharactersInRange:rdiskRange];
+ }
+ // execute hdiutil to eject the device
+ ejectTask = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil" arguments:[NSArray arrayWithObjects:@"eject", deviceName, nil]];
+ [ejectTask waitUntilExit];
+ }
+ }
+
+ /* and open new cd */
+ if ([EmuThread active])
+ CDR_open();
+
+ if (!wasPaused) {
+ [EmuThread resume];
+ }
+}
+
+- (IBAction)pause:(id)sender
+{
+ if ([EmuThread isPaused]) {
+ //[sender setState:NSOffState];
+ [EmuThread resume];
+ }
+ else {
+ //[sender setState:NSOnState];
+ [EmuThread pause];
+ }
+}
+
+- (IBAction)preferences:(id)sender
+{
+ /* load the nib if it hasn't yet */
+ if (preferenceWindow == nil) {
+ if (preferencesController == nil) {
+ preferencesController = [[ConfigurationController alloc] initWithWindowNibName:@"Configuration"];
+ }
+ preferenceWindow = [preferencesController window];
+ }
+
+ /* show the window */
+ [preferenceWindow makeKeyAndOrderFront:self];
+ [preferencesController showWindow:self];
+}
+
+- (IBAction)reset:(id)sender
+{
+ [EmuThread reset];
+}
+
+- (IBAction)runCD:(id)sender
+{
+ SetIsoFile(NULL);
+ [EmuThread run];
+}
+
+- (IBAction)runIso:(id)sender
+{
+ NSOpenPanel* openDlg = [NSOpenPanel openPanel];
+
+ [openDlg setCanChooseFiles:YES];
+ [openDlg setCanChooseDirectories:NO];
+
+ if ([openDlg runModalForDirectory:nil file:nil] == NSOKButton) {
+ NSArray* files = [openDlg filenames];
+ SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
+ [EmuThread run];
+ }
+}
+
+- (IBAction)runBios:(id)sender
+{
+ SetIsoFile(NULL);
+ [EmuThread runBios];
+}
+
+- (IBAction)freeze:(id)sender
+{
+ int num = [sender tag];
+ NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, num];
+
+ [EmuThread freezeAt:path which:num-1];
+}
+
+- (IBAction)defrost:(id)sender
+{
+ NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [sender tag]];
+ [EmuThread defrostAt:path];
+}
+
+- (IBAction)fullscreen:(id)sender
+{
+ GPU_keypressed(GPU_FULLSCREEN_KEY);
+}
+
+- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
+{
+ if ([menuItem action] == @selector(pause:)) {
+ [menuItem setState:([EmuThread isPaused] ? NSOnState : NSOffState)];
+ }
+
+ if ([menuItem action] == @selector(pause:) || [menuItem action] == @selector(fullscreen:))
+ return [EmuThread active];
+
+ if ([menuItem action] == @selector(reset:) || [menuItem action] == @selector(ejectCD:) ||
+ [menuItem action] == @selector(freeze:))
+ return [EmuThread active] && ![EmuThread isRunBios];
+
+ if ([menuItem action] == @selector(runCD:) || [menuItem action] == @selector(runIso:) ||
+ [menuItem action] == @selector(runBios:)) {
+ if (preferenceWindow != nil)
+ if ([preferenceWindow isVisible])
+ return NO;
+
+ if ([menuItem action] == @selector(runBios:) && strcmp(Config.Bios, "HLE") == 0)
+ return NO;
+
+ return ![EmuThread active];
+ }
+
+ if ([menuItem action] == @selector(defrost:)) {
+ if (![EmuThread active] || [EmuThread isRunBios])
+ return NO;
+
+ NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [menuItem tag]];
+ return (CheckState((char *)[path fileSystemRepresentation]) == 0);
+ }
+
+ if ([menuItem action] == @selector(preferences:))
+ return ![EmuThread active];
+
+ return YES;
+}
+
+- (void)applicationWillResignActive:(NSNotification *)aNotification
+{
+ wasPausedBeforeBGSwitch = [EmuThread isPaused];
+
+ if (sleepInBackground) {
+ [EmuThread pause];
+ }
+}
+
+- (void)applicationDidBecomeActive:(NSNotification *)aNotification
+{
+ if (sleepInBackground && !wasPausedBeforeBGSwitch) {
+ [EmuThread resume];
+ }
+}
+
+- (void)awakeFromNib
+{
+ pluginList = [[PluginList alloc] init];
+ if (![pluginList configured] /*!Config.Gpu[0] || !Config.Spu[0] || !Config.Pad1[0] || !Config.Cdr[0]*/) {
+ // configure plugins
+ [self preferences:nil];
+
+ NSRunCriticalAlertPanel(NSLocalizedString(@"Missing plugins!", nil),
+ NSLocalizedString(@"Pcsx is missing one or more critical plugins. You will need to install these in order to play games.", nil),
+ nil, nil, nil);
+ }
+
+ if (![PcsxController biosAvailable]) {
+ NSRunInformationalAlertPanel(NSLocalizedString(@"Missing BIOS!", nil),
+ NSLocalizedString(@"Pcsx wasn't able to locate any Playstation BIOS ROM files. This means that it will run in BIOS simulation mode which is less stable and compatible than using a real Playstation BIOS.\n"
+ @"If you have a BIOS available, please copy it to\n~/Library/Application Support/Pcsx/Bios/", nil),
+ nil, nil, nil);
+ }
+
+ sleepInBackground = YES;
+}
+
+- (void)dealloc
+{
+ [pluginList release];
+ [super dealloc];
+}
+
++ (void)setConfigFromDefaults
+{
+ NSEnumerator *enumerator;
+ const char *str;
+ NSString *key;
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ /*
+ enumerator = [prefStringKeys keyEnumerator];
+ while ((key = [enumerator nextObject])) {
+ str = [[defaults stringForKey:key] fileSystemRepresentation];
+ char *dst = (char *)[[prefStringKeys objectForKey:key] pointerValue];
+ if (str != nil && dst != nil) strncpy(dst, str, 255);
+ }*/
+
+ enumerator = [prefByteKeys keyEnumerator];
+ while ((key = [enumerator nextObject])) {
+ u8 *dst = (u8 *)[[prefByteKeys objectForKey:key] pointerValue];
+ if (dst != nil) *dst = [defaults integerForKey:key];
+ }
+
+ // special cases
+ //str = [[defaults stringForKey:@"PluginPAD"] fileSystemRepresentation];
+ //if (str != nil) strncpy(Config.Pad2, str, 255);
+
+ str = [[defaults stringForKey:@"Bios"] fileSystemRepresentation];
+ if (str) {
+ NSString *path = [defaults stringForKey:@"Bios"];
+ int index = [biosList indexOfObject:path];
+
+ if (-1 == index) {
+ [biosList insertObject:path atIndex:0];
+ } else if (0 < index) {
+ [biosList exchangeObjectAtIndex:index withObjectAtIndex:0];
+ }
+ }
+
+ str = [[defaults stringForKey:@"Mcd1"] fileSystemRepresentation];
+ if (str) strncpy(Config.Mcd1, str, MAXPATHLEN);
+
+ str = [[defaults stringForKey:@"Mcd2"] fileSystemRepresentation];
+ if (str) strncpy(Config.Mcd2, str, MAXPATHLEN);
+
+ if ([defaults boolForKey:@"UseHLE"] || 0 == [biosList count]) {
+ strcpy(Config.Bios, "HLE");
+ } else {
+ str = [(NSString *)[biosList objectAtIndex:0] fileSystemRepresentation];
+ if (str != nil) strncpy(Config.Bios, str, MAXPATHLEN);
+ else strcpy(Config.Bios, "HLE");
+ }
+
+ // FIXME: hack
+ strcpy(Config.Net, "Disabled");
+}
+
++ (void)setDefaultFromConfig:(NSString *)defaultKey
+{
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+
+ char *str = (char *)[[prefStringKeys objectForKey:defaultKey] pointerValue];
+ if (str) {
+ [defaults setObject:[NSString stringWithCString:str] forKey:defaultKey];
+ return;
+ }
+
+ u8 *val = (u8 *)[[prefByteKeys objectForKey:defaultKey] pointerValue];
+ if (val) {
+ [defaults setInteger:*val forKey:defaultKey];
+ return;
+ }
+}
+
++ (BOOL)biosAvailable
+{
+ return ([biosList count] > 0);
+}
+
+// called when class is initialized
++ (void)initialize
+{
+ NSString *path;
+ const char *str;
+ NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
+ NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
+ @"Disabled", @"PluginNET",
+ [NSNumber numberWithInt:1], @"NoDynarec",
+ [NSNumber numberWithInt:1], @"AutoDetectVideoType",
+ [NSNumber numberWithInt:0], @"UseHLE",
+ nil];
+
+ [defaults registerDefaults:appDefaults];
+
+ prefStringKeys = [[NSDictionary alloc] initWithObjectsAndKeys:
+ [NSValue valueWithPointer:Config.Gpu], @"PluginGPU",
+ [NSValue valueWithPointer:Config.Spu], @"PluginSPU",
+ [NSValue valueWithPointer:Config.Pad1], @"PluginPAD",
+ [NSValue valueWithPointer:Config.Cdr], @"PluginCDR",
+ [NSValue valueWithPointer:Config.Net], @"PluginNET",
+ [NSValue valueWithPointer:Config.Mcd1], @"Mcd1",
+ [NSValue valueWithPointer:Config.Mcd2], @"Mcd2",
+ nil];
+
+ prefByteKeys = [[NSDictionary alloc] initWithObjectsAndKeys:
+ [NSValue valueWithPointer:&Config.Xa], @"NoXaAudio",
+ [NSValue valueWithPointer:&Config.Sio], @"SioIrqAlways",
+ [NSValue valueWithPointer:&Config.Mdec], @"BlackAndWhiteMDECVideo",
+ [NSValue valueWithPointer:&Config.PsxAuto], @"AutoDetectVideoType",
+ [NSValue valueWithPointer:&Config.PsxType], @"VideoTypePAL",
+ [NSValue valueWithPointer:&Config.Cdda], @"NoCDAudio",
+ [NSValue valueWithPointer:&Config.Cpu], @"NoDynarec",
+ [NSValue valueWithPointer:&Config.PsxOut], @"ConsoleOutput",
+ [NSValue valueWithPointer:&Config.SpuIrq], @"SpuIrqAlways",
+ [NSValue valueWithPointer:&Config.RCntFix], @"RootCounterFix",
+ [NSValue valueWithPointer:&Config.VSyncWA], @"VideoSyncWAFix",
+ nil];
+
+ // setup application support paths
+ NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
+ if ([libPaths count] > 0) {
+ NSString *path;
+ BOOL dir;
+
+ // create them if needed
+ NSFileManager *dfm = [NSFileManager defaultManager];
+ NSString *supportPath = [NSString stringWithFormat:@"%@/Application Support", [libPaths objectAtIndex:0]];
+ if (![dfm fileExistsAtPath:supportPath isDirectory:&dir])
+ [dfm createDirectoryAtPath:supportPath attributes:nil];
+
+ path = [NSString stringWithFormat:@"%@/Pcsx", supportPath];
+ if (![dfm fileExistsAtPath:path isDirectory:&dir])
+ [dfm createDirectoryAtPath:path attributes:nil];
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Bios", supportPath];
+ if (![dfm fileExistsAtPath:path isDirectory:&dir])
+ [dfm createDirectoryAtPath:path attributes:nil];
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards", supportPath];
+ if (![dfm fileExistsAtPath:path isDirectory:&dir])
+ [dfm createDirectoryAtPath:path attributes:nil];
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Patches", supportPath];
+ if (![dfm fileExistsAtPath:path isDirectory:&dir])
+ [dfm createDirectoryAtPath:path attributes:nil];
+
+ saveStatePath = [[NSString stringWithFormat:@"%@/Pcsx/Save States", supportPath] retain];
+ if (![dfm fileExistsAtPath:saveStatePath isDirectory:&dir])
+ [dfm createDirectoryAtPath:saveStatePath attributes:nil];
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd001.mcr", supportPath];
+ str = [path fileSystemRepresentation];
+ if (str != nil) strncpy(Config.Mcd1, str, 255);
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd002.mcr", supportPath];
+ str = [path fileSystemRepresentation];
+ if (str != nil) strncpy(Config.Mcd2, str, 255);
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Bios/", supportPath];
+ str = [path fileSystemRepresentation];
+ if (str != nil) strncpy(Config.BiosDir, str, 255);
+
+ path = [NSString stringWithFormat:@"%@/Pcsx/Patches/", supportPath];
+ str = [path fileSystemRepresentation];
+ if (str != nil) strncpy(Config.PatchesDir, str, 255);
+ } else {
+ strcpy(Config.BiosDir, "Bios/");
+ strcpy(Config.PatchesDir, "Patches/");
+
+ saveStatePath = @"sstates";
+ [saveStatePath retain];
+ }
+
+ // set plugin path
+ path = [[[NSBundle mainBundle] builtInPlugInsPath] stringByAppendingString:@"/"];
+ str = [path fileSystemRepresentation];
+ if (str != nil) strncpy(Config.PluginsDir, str, 255);
+
+ // locate a bios
+ biosList = [[NSMutableArray alloc] init];
+ NSFileManager *manager = [NSFileManager defaultManager];
+ NSArray *bioses = [manager directoryContentsAtPath:[NSString stringWithCString:Config.BiosDir]];
+ if (bioses) {
+ int i;
+ for (i = 0; i < [bioses count]; i++) {
+ NSString *file = [bioses objectAtIndex:i];
+ NSDictionary *attrib = [manager fileAttributesAtPath:[NSString stringWithFormat:@"%s%@", Config.BiosDir, file] traverseLink:YES];
+
+ if ([[attrib fileType] isEqualToString:NSFileTypeRegular]) {
+ unsigned long long size = [attrib fileSize];
+ if (([attrib fileSize] % (256 * 1024)) == 0 && size > 0) {
+ [biosList addObject:file];
+ }
+ }
+ }
+ }
+
+ [PcsxController setConfigFromDefaults];
+}
+
+
+@end