5 // Created by Gil Pedersen on Sun Sep 21 2003.
6 // Copyright (c) 2003 __MyCompanyName__. All rights reserved.
9 #import <ExceptionHandling/NSExceptionHandler.h>
10 #import <AppKit/NSApplication.h>
14 #include "psxcommon.h"
19 NSString *defrostPath = nil;
24 static pthread_cond_t eventCond;
25 static pthread_mutex_t eventMutex;
27 #define EMUEVENT_NONE 0
28 #define EMUEVENT_PAUSE (1<<0)
29 #define EMUEVENT_RESET (1<<1)
30 #define EMUEVENT_STOP (1<<2)
32 @implementation EmuThread
34 - (void)EmuThreadRun:(id)anObject
36 pool = [[NSAutoreleasePool alloc] init];
38 [[NSNotificationCenter defaultCenter] addObserver:self
39 selector:@selector(emuWindowDidClose:)
40 name:@"emuWindowDidClose" object:nil];
42 [[NSNotificationCenter defaultCenter] addObserver:self
43 selector:@selector(emuWindowWantPause:)
44 name:@"emuWindowWantPause" object:nil];
46 [[NSNotificationCenter defaultCenter] addObserver:self
47 selector:@selector(emuWindowWantResume:)
48 name:@"emuWindowWantResume" object:nil];
50 // we shouldn't change the priority, since we might depend on subthreads
51 //[NSThread setThreadPriority:1.0-((1.0-[NSThread threadPriority])/4.0)];
54 if (OpenPlugins() == -1)
61 int res = CheckCdrom();
64 SysMessage(_("Could not check CD-ROM!\n"));
71 LoadState([defrostPath fileSystemRepresentation]);
72 [defrostPath release]; defrostPath = nil;
78 [pool release]; pool = nil;
84 - (void)EmuThreadRunBios:(id)anObject
86 pool = [[NSAutoreleasePool alloc] init];
88 [[NSNotificationCenter defaultCenter] addObserver:self
89 selector:@selector(emuWindowDidClose:)
90 name:@"emuWindowDidClose" object:nil];
92 [[NSNotificationCenter defaultCenter] addObserver:self
93 selector:@selector(emuWindowWantPause:)
94 name:@"emuWindowWantPause" object:nil];
96 [[NSNotificationCenter defaultCenter] addObserver:self
97 selector:@selector(emuWindowWantResume:)
98 name:@"emuWindowWantResume" object:nil];
100 // we shouldn't change the priority, since we might depend on subthreads
101 //[NSThread setThreadPriority:1.0-((1.0-[NSThread threadPriority])/4.0)];
103 // Do processing here
104 if (OpenPlugins() == -1)
112 [pool release]; pool = nil;
120 // remove all registered observers
121 [[NSNotificationCenter defaultCenter] removeObserver:self name:nil object:nil];
129 - (void)emuWindowDidClose:(NSNotification *)aNotification
134 - (void)emuWindowWantPause:(NSNotification *)aNotification
136 wasPaused = [EmuThread pause];
139 - (void)emuWindowWantResume:(NSNotification *)aNotification
147 /* called periodically from the emulation thread */
150 /* only do a trylock here, since we're not interested in blocking,
151 and we can just handle events next time round */
152 if (pthread_mutex_trylock(&eventMutex) == 0) {
154 if (safeEvent & EMUEVENT_STOP) {
155 /* signify that the emulation has stopped */
156 [emuThread autorelease];
160 /* better unlock the mutex before killing ourself */
161 pthread_mutex_unlock(&eventMutex);
166 //[[NSThread currentThread] autorelease];
171 if (safeEvent & EMUEVENT_RESET) {
173 /* signify that the emulation has stopped */
174 [emuThread autorelease];
177 /* better unlock the mutex before killing ourself */
178 pthread_mutex_unlock(&eventMutex);
182 // start a new emulation thread
185 //[[NSThread currentThread] autorelease];
189 safeEvent &= ~EMUEVENT_RESET;
190 pthread_mutex_unlock(&eventMutex);
192 longjmp(restartJmp, 0);
196 if (safeEvent & EMUEVENT_PAUSE) {
198 /* wait until we're signalled */
199 pthread_cond_wait(&eventCond, &eventMutex);
202 pthread_mutex_unlock(&eventMutex);
215 if (pthread_mutex_lock(&eventMutex) != 0) {
216 err = pthread_cond_init(&eventCond, NULL);
219 err = pthread_mutex_init(&eventMutex, NULL);
222 pthread_mutex_lock(&eventMutex);
225 safeEvent = EMUEVENT_NONE;
229 if (SysInit() != 0) {
230 pthread_mutex_unlock(&eventMutex);
234 emuThread = [[EmuThread alloc] init];
236 [NSThread detachNewThreadSelector:@selector(EmuThreadRun:)
237 toTarget:emuThread withObject:nil];
239 pthread_mutex_unlock(&eventMutex);
251 if (pthread_mutex_lock(&eventMutex) != 0) {
252 err = pthread_cond_init(&eventCond, NULL);
255 err = pthread_mutex_init(&eventMutex, NULL);
258 pthread_mutex_lock(&eventMutex);
261 safeEvent = EMUEVENT_NONE;
265 if (SysInit() != 0) {
266 pthread_mutex_unlock(&eventMutex);
270 emuThread = [[EmuThread alloc] init];
272 [NSThread detachNewThreadSelector:@selector(EmuThreadRunBios:)
273 toTarget:emuThread withObject:nil];
275 pthread_mutex_unlock(&eventMutex);
280 pthread_mutex_lock(&eventMutex);
281 safeEvent = EMUEVENT_STOP;
282 pthread_mutex_unlock(&eventMutex);
284 // wake it if it's sleeping
285 pthread_cond_broadcast(&eventCond);
290 if (paused || ![EmuThread active])
293 pthread_mutex_lock(&eventMutex);
294 safeEvent |= EMUEVENT_PAUSE;
296 pthread_mutex_unlock(&eventMutex);
298 pthread_cond_broadcast(&eventCond);
305 if ((paused == 2) || ![EmuThread active])
309 while ([EmuThread isPaused] != 2) [NSThread sleepUntilDate:[[NSDate date] addTimeInterval:0.05]];
316 if (!paused || ![EmuThread active])
319 pthread_mutex_lock(&eventMutex);
321 safeEvent &= ~EMUEVENT_PAUSE;
323 pthread_mutex_unlock(&eventMutex);
325 pthread_cond_broadcast(&eventCond);
330 pthread_mutex_lock(&eventMutex);
331 safeEvent = EMUEVENT_RESET;
332 pthread_mutex_unlock(&eventMutex);
334 pthread_cond_broadcast(&eventCond);
337 // must only be called from within the emulation thread!!!
340 /* signify that the emulation has stopped */
341 [emuThread autorelease];
346 // start a new emulation thread
349 //[[NSThread currentThread] autorelease];
366 return emuThread ? YES : NO;
369 + (void)freezeAt:(NSString *)path which:(int)num
371 BOOL emuWasPaused = [EmuThread pauseSafe];
374 GPU_freeze(2, (GPUFreeze_t *)&num);
375 int ret = SaveState([path fileSystemRepresentation]);
376 if (ret == 0) sprintf (Text, _("*PCSX*: Saved State %d"), num+1);
377 else sprintf (Text, _("*PCSX*: Error Saving State %d"), num+1);
378 GPU_displayText(Text);
385 + (BOOL)defrostAt:(NSString *)path
387 const char *cPath = [path fileSystemRepresentation];
388 if (CheckState(cPath) != 0)
391 defrostPath = [path retain];
394 GPU_displayText(_("*PCSX*: Loaded State"));