pcsxr-1.9.92
[pcsx_rearmed.git] / macosx / PcsxController.m
CommitLineData
ef79bbde
P
1#import <Cocoa/Cocoa.h>
2#import "PcsxController.h"
3#import "ConfigurationController.h"
4#import "EmuThread.h"
5#include "psxcommon.h"
6#include "plugins.h"
7#include "misc.h"
8#include "ExtendedKeys.h"
9
10NSDictionary *prefStringKeys;
11NSDictionary *prefByteKeys;
12NSMutableArray *biosList;
13NSString *saveStatePath;
14
15@implementation PcsxController
16
17- (IBAction)ejectCD:(id)sender
18{
19 NSMutableString *deviceName;
20 NSTask *ejectTask;
21 NSRange rdiskRange;
22
23 BOOL wasPaused = [EmuThread pauseSafe];
24
25 /* close connection to current cd */
26 if ([EmuThread active])
27 CDR_close();
28
29 // switch to another ISO if using internal image reader, otherwise eject the CD
30 if (UsingIso()) {
31 NSOpenPanel* openDlg = [NSOpenPanel openPanel];
32
33 [openDlg setCanChooseFiles:YES];
34 [openDlg setCanChooseDirectories:NO];
35
36 if ([openDlg runModal] == NSOKButton) {
37 NSArray* files = [openDlg filenames];
38 SetCdOpenCaseTime(time(NULL) + 2);
39 SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
40 }
41 } else {
42 if (CDR_getDriveLetter() != nil) {
43 deviceName = [NSMutableString stringWithCString:CDR_getDriveLetter()];
44
45 // delete the 'r' in 'rdisk'
46 rdiskRange = [deviceName rangeOfString:@"rdisk"];
47 if (rdiskRange.length != 0) {
48 rdiskRange.length = 1;
49 [deviceName deleteCharactersInRange:rdiskRange];
50 }
51 // execute hdiutil to eject the device
52 ejectTask = [NSTask launchedTaskWithLaunchPath:@"/usr/bin/hdiutil" arguments:[NSArray arrayWithObjects:@"eject", deviceName, nil]];
53 [ejectTask waitUntilExit];
54 }
55 }
56
57 /* and open new cd */
58 if ([EmuThread active])
59 CDR_open();
60
61 if (!wasPaused) {
62 [EmuThread resume];
63 }
64}
65
66- (IBAction)pause:(id)sender
67{
68 if ([EmuThread isPaused]) {
69 //[sender setState:NSOffState];
70 [EmuThread resume];
71 }
72 else {
73 //[sender setState:NSOnState];
74 [EmuThread pause];
75 }
76}
77
78- (IBAction)preferences:(id)sender
79{
80 /* load the nib if it hasn't yet */
81 if (preferenceWindow == nil) {
82 if (preferencesController == nil) {
83 preferencesController = [[ConfigurationController alloc] initWithWindowNibName:@"Configuration"];
84 }
85 preferenceWindow = [preferencesController window];
86 }
87
88 /* show the window */
89 [preferenceWindow makeKeyAndOrderFront:self];
90 [preferencesController showWindow:self];
91}
92
93- (IBAction)reset:(id)sender
94{
95 [EmuThread reset];
96}
97
98- (IBAction)runCD:(id)sender
99{
100 SetIsoFile(NULL);
101 [EmuThread run];
102}
103
104- (IBAction)runIso:(id)sender
105{
106 NSOpenPanel* openDlg = [NSOpenPanel openPanel];
107
108 [openDlg setCanChooseFiles:YES];
109 [openDlg setCanChooseDirectories:NO];
110
111 if ([openDlg runModalForDirectory:nil file:nil] == NSOKButton) {
112 NSArray* files = [openDlg filenames];
113 SetIsoFile((const char *)[[files objectAtIndex:0] fileSystemRepresentation]);
114 [EmuThread run];
115 }
116}
117
118- (IBAction)runBios:(id)sender
119{
120 SetIsoFile(NULL);
121 [EmuThread runBios];
122}
123
124- (IBAction)freeze:(id)sender
125{
126 int num = [sender tag];
127 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, num];
128
129 [EmuThread freezeAt:path which:num-1];
130}
131
132- (IBAction)defrost:(id)sender
133{
134 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [sender tag]];
135 [EmuThread defrostAt:path];
136}
137
138- (IBAction)fullscreen:(id)sender
139{
140 GPU_keypressed(GPU_FULLSCREEN_KEY);
141}
142
143- (BOOL)validateMenuItem:(id <NSMenuItem>)menuItem
144{
145 if ([menuItem action] == @selector(pause:)) {
146 [menuItem setState:([EmuThread isPaused] ? NSOnState : NSOffState)];
147 }
148
149 if ([menuItem action] == @selector(pause:) || [menuItem action] == @selector(fullscreen:))
150 return [EmuThread active];
151
152 if ([menuItem action] == @selector(reset:) || [menuItem action] == @selector(ejectCD:) ||
153 [menuItem action] == @selector(freeze:))
154 return [EmuThread active] && ![EmuThread isRunBios];
155
156 if ([menuItem action] == @selector(runCD:) || [menuItem action] == @selector(runIso:) ||
157 [menuItem action] == @selector(runBios:)) {
158 if (preferenceWindow != nil)
159 if ([preferenceWindow isVisible])
160 return NO;
161
162 if ([menuItem action] == @selector(runBios:) && strcmp(Config.Bios, "HLE") == 0)
163 return NO;
164
165 return ![EmuThread active];
166 }
167
168 if ([menuItem action] == @selector(defrost:)) {
169 if (![EmuThread active] || [EmuThread isRunBios])
170 return NO;
171
172 NSString *path = [NSString stringWithFormat:@"%@/%s-%3.3d.pcsxstate", saveStatePath, CdromId, [menuItem tag]];
173 return (CheckState((char *)[path fileSystemRepresentation]) == 0);
174 }
175
176 if ([menuItem action] == @selector(preferences:))
177 return ![EmuThread active];
178
179 return YES;
180}
181
182- (void)applicationWillResignActive:(NSNotification *)aNotification
183{
184 wasPausedBeforeBGSwitch = [EmuThread isPaused];
185
186 if (sleepInBackground) {
187 [EmuThread pause];
188 }
189}
190
191- (void)applicationDidBecomeActive:(NSNotification *)aNotification
192{
193 if (sleepInBackground && !wasPausedBeforeBGSwitch) {
194 [EmuThread resume];
195 }
196}
197
198- (void)awakeFromNib
199{
200 pluginList = [[PluginList alloc] init];
201 if (![pluginList configured] /*!Config.Gpu[0] || !Config.Spu[0] || !Config.Pad1[0] || !Config.Cdr[0]*/) {
202 // configure plugins
203 [self preferences:nil];
204
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),
207 nil, nil, nil);
208 }
209
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),
214 nil, nil, nil);
215 }
216
217 sleepInBackground = YES;
218}
219
220- (void)dealloc
221{
222 [pluginList release];
223 [super dealloc];
224}
225
226+ (void)setConfigFromDefaults
227{
228 NSEnumerator *enumerator;
229 const char *str;
230 NSString *key;
231 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
232
233 /*
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);
239 }*/
240
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];
245 }
246
247 // special cases
248 //str = [[defaults stringForKey:@"PluginPAD"] fileSystemRepresentation];
249 //if (str != nil) strncpy(Config.Pad2, str, 255);
250
251 str = [[defaults stringForKey:@"Bios"] fileSystemRepresentation];
252 if (str) {
253 NSString *path = [defaults stringForKey:@"Bios"];
254 int index = [biosList indexOfObject:path];
255
256 if (-1 == index) {
257 [biosList insertObject:path atIndex:0];
258 } else if (0 < index) {
259 [biosList exchangeObjectAtIndex:index withObjectAtIndex:0];
260 }
261 }
262
263 str = [[defaults stringForKey:@"Mcd1"] fileSystemRepresentation];
264 if (str) strncpy(Config.Mcd1, str, MAXPATHLEN);
265
266 str = [[defaults stringForKey:@"Mcd2"] fileSystemRepresentation];
267 if (str) strncpy(Config.Mcd2, str, MAXPATHLEN);
268
269 if ([defaults boolForKey:@"UseHLE"] || 0 == [biosList count]) {
270 strcpy(Config.Bios, "HLE");
271 } else {
272 str = [(NSString *)[biosList objectAtIndex:0] fileSystemRepresentation];
273 if (str != nil) strncpy(Config.Bios, str, MAXPATHLEN);
274 else strcpy(Config.Bios, "HLE");
275 }
276
277 // FIXME: hack
278 strcpy(Config.Net, "Disabled");
279}
280
281+ (void)setDefaultFromConfig:(NSString *)defaultKey
282{
283 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
284
285 char *str = (char *)[[prefStringKeys objectForKey:defaultKey] pointerValue];
286 if (str) {
287 [defaults setObject:[NSString stringWithCString:str] forKey:defaultKey];
288 return;
289 }
290
291 u8 *val = (u8 *)[[prefByteKeys objectForKey:defaultKey] pointerValue];
292 if (val) {
293 [defaults setInteger:*val forKey:defaultKey];
294 return;
295 }
296}
297
298+ (BOOL)biosAvailable
299{
300 return ([biosList count] > 0);
301}
302
303// called when class is initialized
304+ (void)initialize
305{
306 NSString *path;
307 const char *str;
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",
314 nil];
315
316 [defaults registerDefaults:appDefaults];
317
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",
326 nil];
327
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",
340 nil];
341
342 // setup application support paths
343 NSArray *libPaths = NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES);
344 if ([libPaths count] > 0) {
345 NSString *path;
346 BOOL dir;
347
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];
353
354 path = [NSString stringWithFormat:@"%@/Pcsx", supportPath];
355 if (![dfm fileExistsAtPath:path isDirectory:&dir])
356 [dfm createDirectoryAtPath:path attributes:nil];
357
358 path = [NSString stringWithFormat:@"%@/Pcsx/Bios", supportPath];
359 if (![dfm fileExistsAtPath:path isDirectory:&dir])
360 [dfm createDirectoryAtPath:path attributes:nil];
361
362 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards", supportPath];
363 if (![dfm fileExistsAtPath:path isDirectory:&dir])
364 [dfm createDirectoryAtPath:path attributes:nil];
365
366 path = [NSString stringWithFormat:@"%@/Pcsx/Patches", supportPath];
367 if (![dfm fileExistsAtPath:path isDirectory:&dir])
368 [dfm createDirectoryAtPath:path attributes:nil];
369
370 saveStatePath = [[NSString stringWithFormat:@"%@/Pcsx/Save States", supportPath] retain];
371 if (![dfm fileExistsAtPath:saveStatePath isDirectory:&dir])
372 [dfm createDirectoryAtPath:saveStatePath attributes:nil];
373
374 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd001.mcr", supportPath];
375 str = [path fileSystemRepresentation];
376 if (str != nil) strncpy(Config.Mcd1, str, 255);
377
378 path = [NSString stringWithFormat:@"%@/Pcsx/Memory Cards/Mcd002.mcr", supportPath];
379 str = [path fileSystemRepresentation];
380 if (str != nil) strncpy(Config.Mcd2, str, 255);
381
382 path = [NSString stringWithFormat:@"%@/Pcsx/Bios/", supportPath];
383 str = [path fileSystemRepresentation];
384 if (str != nil) strncpy(Config.BiosDir, str, 255);
385
386 path = [NSString stringWithFormat:@"%@/Pcsx/Patches/", supportPath];
387 str = [path fileSystemRepresentation];
388 if (str != nil) strncpy(Config.PatchesDir, str, 255);
389 } else {
390 strcpy(Config.BiosDir, "Bios/");
391 strcpy(Config.PatchesDir, "Patches/");
392
393 saveStatePath = @"sstates";
394 [saveStatePath retain];
395 }
396
397 // set plugin path
398 path = [[[NSBundle mainBundle] builtInPlugInsPath] stringByAppendingString:@"/"];
399 str = [path fileSystemRepresentation];
400 if (str != nil) strncpy(Config.PluginsDir, str, 255);
401
402 // locate a bios
403 biosList = [[NSMutableArray alloc] init];
404 NSFileManager *manager = [NSFileManager defaultManager];
405 NSArray *bioses = [manager directoryContentsAtPath:[NSString stringWithCString:Config.BiosDir]];
406 if (bioses) {
407 int i;
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];
411
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];
416 }
417 }
418 }
419 }
420
421 [PcsxController setConfigFromDefaults];
422}
423
424
425@end