1 #import <Cocoa/Cocoa.h>
2 #import "PcsxController.h"
3 #import "ConfigurationController.h"
8 #include "ExtendedKeys.h"
10 NSDictionary *prefStringKeys;
11 NSDictionary *prefByteKeys;
12 NSMutableArray *biosList;
13 NSString *saveStatePath;
15 @implementation PcsxController
17 - (IBAction)ejectCD:(id)sender
19 NSMutableString *deviceName;
23 BOOL wasPaused = [EmuThread pauseSafe];
25 /* close connection to current cd */
26 if ([EmuThread active])
29 // switch to another ISO if using internal image reader, otherwise eject the CD
31 NSOpenPanel* openDlg = [NSOpenPanel openPanel];
33 [openDlg setCanChooseFiles:YES];
34 [openDlg setCanChooseDirectories:NO];
36 if ([openDlg runModal] == NSOKButton) {
37 NSArray* files = [openDlg filenames];
38 SetCdOpenCaseTime(time(NULL) + 2);
39 SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
42 if (CDR_getDriveLetter() != nil) {
43 deviceName = [NSMutableString stringWithCString:CDR_getDriveLetter()];
45 // delete the 'r' in 'rdisk'
46 rdiskRange = [deviceName rangeOfString:@"rdisk"];
47 if (rdiskRange.length != 0) {
48 rdiskRange.length = 1;
49 [deviceName deleteCharactersInRange:rdiskRange];
51 // execute hdiutil to eject the device
52 ejectTask = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil" arguments:[NSArray arrayWithObjects:@"eject", deviceName, nil]];
53 [ejectTask waitUntilExit];
58 if ([EmuThread active])
66 - (IBAction)pause:(id)sender
68 if ([EmuThread isPaused]) {
69 //[sender setState:NSOffState];
73 //[sender setState:NSOnState];
78 - (IBAction)preferences:(id)sender
80 /* load the nib if it hasn't yet */
81 if (preferenceWindow == nil) {
82 if (preferencesController == nil) {
83 preferencesController = [[ConfigurationController alloc] initWithWindowNibName:@"Configuration"];
85 preferenceWindow = [preferencesController window];
89 [preferenceWindow makeKeyAndOrderFront:self];
90 [preferencesController showWindow:self];
93 - (IBAction)reset:(id)sender
98 - (IBAction)runCD:(id)sender
104 - (IBAction)runIso:(id)sender
106 NSOpenPanel* openDlg = [NSOpenPanel openPanel];
108 [openDlg setCanChooseFiles:YES];
109 [openDlg setCanChooseDirectories:NO];
111 if ([openDlg runModalForDirectory:nil file:nil] == NSOKButton) {
112 NSArray* files = [openDlg filenames];
113 SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
118 - (IBAction)runBios:(id)sender
124 - (IBAction)freeze:(id)sender
126 int num = [sender tag];
127 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, num];
129 [EmuThread freezeAt:path which:num-1];
132 - (IBAction)defrost:(id)sender
134 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [sender tag]];
135 [EmuThread defrostAt:path];
138 - (IBAction)fullscreen:(id)sender
140 GPU_keypressed(GPU_FULLSCREEN_KEY);
143 - (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
145 if ([menuItem action] == @selector(pause:)) {
146 [menuItem setState:([EmuThread isPaused] ? NSOnState : NSOffState)];
149 if ([menuItem action] == @selector(pause:) || [menuItem action] == @selector(fullscreen:))
150 return [EmuThread active];
152 if ([menuItem action] == @selector(reset:) || [menuItem action] == @selector(ejectCD:) ||
153 [menuItem action] == @selector(freeze:))
154 return [EmuThread active] && ![EmuThread isRunBios];
156 if ([menuItem action] == @selector(runCD:) || [menuItem action] == @selector(runIso:) ||
157 [menuItem action] == @selector(runBios:)) {
158 if (preferenceWindow != nil)
159 if ([preferenceWindow isVisible])
162 if ([menuItem action] == @selector(runBios:) && strcmp(Config.Bios, "HLE") == 0)
165 return ![EmuThread active];
168 if ([menuItem action] == @selector(defrost:)) {
169 if (![EmuThread active] || [EmuThread isRunBios])
172 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [menuItem tag]];
173 return (CheckState((char *)[path fileSystemRepresentation]) == 0);
176 if ([menuItem action] == @selector(preferences:))
177 return ![EmuThread active];
182 - (void)applicationWillResignActive:(NSNotification *)aNotification
184 wasPausedBeforeBGSwitch = [EmuThread isPaused];
186 if (sleepInBackground) {
191 - (void)applicationDidBecomeActive:(NSNotification *)aNotification
193 if (sleepInBackground && !wasPausedBeforeBGSwitch) {
200 pluginList = [[PluginList alloc] init];
201 if (![pluginList configured] /*!Config.Gpu[0] || !Config.Spu[0] || !Config.Pad1[0] || !Config.Cdr[0]*/) {
203 [self preferences:nil];
205 NSRunCriticalAlertPanel(NSLocalizedString(@"Missing plugins!", nil),
206 NSLocalizedString(@"Pcsx is missing one or more critical plugins. You will need to install these in order to play games.", nil),
210 if (![PcsxController biosAvailable]) {
211 NSRunInformationalAlertPanel(NSLocalizedString(@"Missing BIOS!", nil),
212 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"
213 @"If you have a BIOS available, please copy it to\n~/Library/Application Support/Pcsx/Bios/", nil),
217 sleepInBackground = YES;
222 [pluginList release];
226 + (void)setConfigFromDefaults
228 NSEnumerator *enumerator;
231 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
234 enumerator = [prefStringKeys keyEnumerator];
235 while ((key = [enumerator nextObject])) {
236 str = [[defaults stringForKey:key] fileSystemRepresentation];
237 char *dst = (char *)[[prefStringKeys objectForKey:key] pointerValue];
238 if (str != nil && dst != nil) strncpy(dst, str, 255);
241 enumerator = [prefByteKeys keyEnumerator];
242 while ((key = [enumerator nextObject])) {
243 u8 *dst = (u8 *)[[prefByteKeys objectForKey:key] pointerValue];
244 if (dst != nil) *dst = [defaults integerForKey:key];
248 //str = [[defaults stringForKey:@"PluginPAD"] fileSystemRepresentation];
249 //if (str != nil) strncpy(Config.Pad2, str, 255);
251 str = [[defaults stringForKey:@"Bios"] fileSystemRepresentation];
253 NSString *path = [defaults stringForKey:@"Bios"];
254 int index = [biosList indexOfObject:path];
257 [biosList insertObject:path atIndex:0];
258 } else if (0 < index) {
259 [biosList exchangeObjectAtIndex:index withObjectAtIndex:0];
263 str = [[defaults stringForKey:@"Mcd1"] fileSystemRepresentation];
264 if (str) strncpy(Config.Mcd1, str, MAXPATHLEN);
266 str = [[defaults stringForKey:@"Mcd2"] fileSystemRepresentation];
267 if (str) strncpy(Config.Mcd2, str, MAXPATHLEN);
269 if ([defaults boolForKey:@"UseHLE"] || 0 == [biosList count]) {
270 strcpy(Config.Bios, "HLE");
272 str = [(NSString *)[biosList objectAtIndex:0] fileSystemRepresentation];
273 if (str != nil) strncpy(Config.Bios, str, MAXPATHLEN);
274 else strcpy(Config.Bios, "HLE");
278 strcpy(Config.Net, "Disabled");
281 + (void)setDefaultFromConfig:(NSString *)defaultKey
283 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
285 char *str = (char *)[[prefStringKeys objectForKey:defaultKey] pointerValue];
287 [defaults setObject:[NSString stringWithCString:str] forKey:defaultKey];
291 u8 *val = (u8 *)[[prefByteKeys objectForKey:defaultKey] pointerValue];
293 [defaults setInteger:*val forKey:defaultKey];
298 + (BOOL)biosAvailable
300 return ([biosList count] > 0);
303 // called when class is initialized
308 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
309 NSDictionary *appDefaults = [NSDictionary dictionaryWithObjectsAndKeys:
310 @"Disabled", @"PluginNET",
311 [NSNumber numberWithInt:1], @"NoDynarec",
312 [NSNumber numberWithInt:1], @"AutoDetectVideoType",
313 [NSNumber numberWithInt:0], @"UseHLE",
316 [defaults registerDefaults:appDefaults];
318 prefStringKeys = [[NSDictionary alloc] initWithObjectsAndKeys:
319 [NSValue valueWithPointer:Config.Gpu], @"PluginGPU",
320 [NSValue valueWithPointer:Config.Spu], @"PluginSPU",
321 [NSValue valueWithPointer:Config.Pad1], @"PluginPAD",
322 [NSValue valueWithPointer:Config.Cdr], @"PluginCDR",
323 [NSValue valueWithPointer:Config.Net], @"PluginNET",
324 [NSValue valueWithPointer:Config.Mcd1], @"Mcd1",
325 [NSValue valueWithPointer:Config.Mcd2], @"Mcd2",
328 prefByteKeys = [[NSDictionary alloc] initWithObjectsAndKeys:
329 [NSValue valueWithPointer:&Config.Xa], @"NoXaAudio",
330 [NSValue valueWithPointer:&Config.Sio], @"SioIrqAlways",
331 [NSValue valueWithPointer:&Config.Mdec], @"BlackAndWhiteMDECVideo",
332 [NSValue valueWithPointer:&Config.PsxAuto], @"AutoDetectVideoType",
333 [NSValue valueWithPointer:&Config.PsxType], @"VideoTypePAL",
334 [NSValue valueWithPointer:&Config.Cdda], @"NoCDAudio",
335 [NSValue valueWithPointer:&Config.Cpu], @"NoDynarec",
336 [NSValue valueWithPointer:&Config.PsxOut], @"ConsoleOutput",
337 [NSValue valueWithPointer:&Config.SpuIrq], @"SpuIrqAlways",
338 [NSValue valueWithPointer:&Config.RCntFix], @"RootCounterFix",
339 [NSValue valueWithPointer:&Config.VSyncWA], @"VideoSyncWAFix",
342 // setup application support paths
343 NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
344 if ([libPaths count] > 0) {
348 // create them if needed
349 NSFileManager *dfm = [NSFileManager defaultManager];
350 NSString *supportPath = [NSString stringWithFormat:@"%@/Application Support", [libPaths objectAtIndex:0]];
351 if (![dfm fileExistsAtPath:supportPath isDirectory:&dir])
352 [dfm createDirectoryAtPath:supportPath attributes:nil];
354 path = [NSString stringWithFormat:@"%@/Pcsx", supportPath];
355 if (![dfm fileExistsAtPath:path isDirectory:&dir])
356 [dfm createDirectoryAtPath:path attributes:nil];
358 path = [NSString stringWithFormat:@"%@/Pcsx/Bios", supportPath];
359 if (![dfm fileExistsAtPath:path isDirectory:&dir])
360 [dfm createDirectoryAtPath:path attributes:nil];
362 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards", supportPath];
363 if (![dfm fileExistsAtPath:path isDirectory:&dir])
364 [dfm createDirectoryAtPath:path attributes:nil];
366 path = [NSString stringWithFormat:@"%@/Pcsx/Patches", supportPath];
367 if (![dfm fileExistsAtPath:path isDirectory:&dir])
368 [dfm createDirectoryAtPath:path attributes:nil];
370 saveStatePath = [[NSString stringWithFormat:@"%@/Pcsx/Save States", supportPath] retain];
371 if (![dfm fileExistsAtPath:saveStatePath isDirectory:&dir])
372 [dfm createDirectoryAtPath:saveStatePath attributes:nil];
374 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd001.mcr", supportPath];
375 str = [path fileSystemRepresentation];
376 if (str != nil) strncpy(Config.Mcd1, str, 255);
378 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd002.mcr", supportPath];
379 str = [path fileSystemRepresentation];
380 if (str != nil) strncpy(Config.Mcd2, str, 255);
382 path = [NSString stringWithFormat:@"%@/Pcsx/Bios/", supportPath];
383 str = [path fileSystemRepresentation];
384 if (str != nil) strncpy(Config.BiosDir, str, 255);
386 path = [NSString stringWithFormat:@"%@/Pcsx/Patches/", supportPath];
387 str = [path fileSystemRepresentation];
388 if (str != nil) strncpy(Config.PatchesDir, str, 255);
390 strcpy(Config.BiosDir, "Bios/");
391 strcpy(Config.PatchesDir, "Patches/");
393 saveStatePath = @"sstates";
394 [saveStatePath retain];
398 path = [[[NSBundle mainBundle] builtInPlugInsPath] stringByAppendingString:@"/"];
399 str = [path fileSystemRepresentation];
400 if (str != nil) strncpy(Config.PluginsDir, str, 255);
403 biosList = [[NSMutableArray alloc] init];
404 NSFileManager *manager = [NSFileManager defaultManager];
405 NSArray *bioses = [manager directoryContentsAtPath:[NSString stringWithCString:Config.BiosDir]];
408 for (i = 0; i < [bioses count]; i++) {
409 NSString *file = [bioses objectAtIndex:i];
410 NSDictionary *attrib = [manager fileAttributesAtPath:[NSString stringWithFormat:@"%s%@", Config.BiosDir, file] traverseLink:YES];
412 if ([[attrib fileType] isEqualToString:NSFileTypeRegular]) {
413 unsigned long long size = [attrib fileSize];
414 if (([attrib fileSize] % (256 * 1024)) == 0 && size > 0) {
415 [biosList addObject:file];
421 [PcsxController setConfigFromDefaults];