|
|
1.1 root 1: /* SDLMain.m - main entry point for our Cocoa-ized SDL app
2: Initial Version: Darrell Walisser <[email protected]>
3: Non-NIB-Code & other changes: Max Horn <[email protected]>
4:
5: Feb-Mar 2006, S�bastien Molines - Added prefs & create floppy
6: June 2006, S�bastien Molines - Added capture and memory snapshot
7:
8: Feel free to customize this file to suit your needs
9: */
10:
11: #import "SDL.h"
12: #import "SDLMain.h"
13: #import "SDL_events.h"
14: #import "Shared.h"
15: #import <sys/param.h> /* for MAXPATHLEN */
16: #import <unistd.h>
17:
18: #include "dialog.h"
19: #include "floppy.h"
20: #include "reset.h"
21: #include "screenSnapShot.h"
22: #include "memorySnapShot.h"
23: #include "sound.h"
24:
25: static int gArgc;
26: static char **gArgv;
27: static BOOL gFinderLaunch;
28:
29: @interface SDLApplication : NSApplication
30: @end
31:
32: @implementation SDLApplication
33: /* Invoked from the Quit menu item */
34: - (void)terminate:(id)sender
35: {
36: /* Post a SDL_QUIT event */
37: SDL_Event event;
38: event.type = SDL_QUIT;
39: SDL_PushEvent(&event);
40: }
41: @end
42:
43:
44: /* The main class of the application, the application's delegate */
45: @implementation SDLMain
46:
47: - (IBAction)prefsMenu:(id)sender
48: {
49: static int in_propdialog = 0;
50:
51: if (in_propdialog)
52: return;
53: ++in_propdialog;
54: Dialog_DoProperty();
55: --in_propdialog;
56: }
57:
58: - (IBAction)warmReset:(id)sender
59: {
60: int b;
61:
62: b = NSRunAlertPanel (@"Warm reset!",
63: @"Really reset the emulator? All current work will be lost. Click Cancel to continue without reset.",
64: @"OK", @"Cancel", nil);
65: //printf("b=%i\n",b);
66: if (b == 1)
67: Reset_Warm();
68: }
69:
70: - (IBAction)coldReset:(id)sender
71: {
72: int b;
73:
74: b = NSRunAlertPanel (@"Cold reset!",
75: @"Really reset the emulator? All current work will be lost. Click Cancel to continue without reset.",
76: @"OK", @"Cancel", nil);
77: //printf("b=%i\n",b);
78: if (b == 1)
79: Reset_Cold();
80: }
81:
82: - (IBAction)insertDiskA:(id)sender
83: {
84: NSString *path = nil;
85: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ];
86:
87: if ( [ openPanel runModalForDirectory:nil
88: file:@"SavedGame" types:nil ] ) {
89:
90: path = [ [ openPanel filenames ] objectAtIndex:0 ];
91: }
92:
93: if (path != nil)
94: {
95: // Make a non-const C string out of it
96: const char* constSzPath = [path cString];
97: size_t cbPath = strlen(constSzPath) + 1;
98: char szPath[cbPath];
99: strncpy(szPath, constSzPath, cbPath);
1.1.1.3 root 100:
101: Floppy_SetDiskFileName(0, szPath, NULL);
102: Floppy_InsertDiskIntoDrive(0);
1.1 root 103: }
104: }
105:
106: - (IBAction)insertDiskB:(id)sender
107: {
108: NSString *path = nil;
109: NSOpenPanel *openPanel = [ NSOpenPanel openPanel ];
110:
111: if ( [ openPanel runModalForDirectory:nil
112: file:@"SavedGame" types:nil ] ) {
113:
114: path = [ [ openPanel filenames ] objectAtIndex:0 ];
115: }
116:
117: if (path != nil)
118: {
119: // Make a non-const C string out of it
120: const char* constSzPath = [path cString];
121: size_t cbPath = strlen(constSzPath) + 1;
122: char szPath[cbPath];
123: strncpy(szPath, constSzPath, cbPath);
124:
1.1.1.3 root 125: Floppy_SetDiskFileName(1, szPath, NULL);
126: Floppy_InsertDiskIntoDrive(1);
1.1 root 127: }
128: }
129:
130: /*-----------------------------------------------------------------------*/
131: /*
132: Controls the enabled state of the menu items
133: */
134: - (BOOL)validateMenuItem:(NSMenuItem*)item
135: {
136: if (item == beginCaptureAnim)
137: {
138: return !ScreenSnapShot_AreWeRecording();
139: }
140: if (item == endCaptureAnim)
141: {
142: return ScreenSnapShot_AreWeRecording();
143: }
144: if (item == beginCaptureSound)
145: {
146: return !Sound_AreWeRecording();
147: }
148: if (item == endCaptureSound)
149: {
150: return Sound_AreWeRecording();
151: }
152:
153: return YES;
154: }
155:
156: - (IBAction)captureScreen:(id)sender
157: {
158: GuiOsx_PauseAndSwitchToCocoaUI();
159: ScreenSnapShot_SaveScreen();
160: GuiOsx_ResumeFromCocoaUI();
161: }
162:
163: - (IBAction)captureAnimation:(id)sender
164: {
165: GuiOsx_PauseAndSwitchToCocoaUI();
1.1.1.3 root 166: ScreenSnapShot_BeginRecording(ConfigureParams.Screen.bCaptureChange);
1.1 root 167: GuiOsx_ResumeFromCocoaUI();
168: }
169:
170: - (IBAction)endCaptureAnimation:(id)sender
171: {
172: GuiOsx_PauseAndSwitchToCocoaUI();
173: ScreenSnapShot_EndRecording();
174: GuiOsx_ResumeFromCocoaUI();
175: }
176:
177: - (IBAction)captureSound:(id)sender
178: {
179: GuiOsx_PauseAndSwitchToCocoaUI();
180:
181: // Get the path from the user settings
182: NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Sound.szYMCaptureFileName)] stringByAbbreviatingWithTildeInPath];
183:
184: // Determine the directory and filename
185: NSString *directoryToOpen;
186: NSString *fileToPreselect;
187: if ((preferredPath != nil) && ([preferredPath length] > 0))
188: {
189: // There is existing path: we will open its directory with its file pre-selected.
190: directoryToOpen = [preferredPath stringByDeletingLastPathComponent];
191: fileToPreselect = [preferredPath lastPathComponent];
192: }
193: else
194: {
195: // Currently no path: we will open the user's directory with no file selected.
196: directoryToOpen = [@"~" stringByExpandingTildeInPath];
197: fileToPreselect = @"hatari.wav";
198: }
199:
200: // Create and configure a SavePanel for choosing what file to write
201: NSSavePanel *savePanel = [NSSavePanel savePanel];
202: [savePanel setAllowedFileTypes:[NSArray arrayWithObjects:@"ym", @"wav", nil]];
203: [savePanel setExtensionHidden:NO];
204: [savePanel setMessage:@"Please specify an .ym or a .wav file."]; // TODO: Move to localizable resources
205:
206: // Run the SavePanel, then check if the user clicked OK and selected at least one file
207: if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] )
208: {
209: // Get the path to the selected file
210: NSString *path = [savePanel filename];
211:
212: // Store the path in the user settings
213: GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName));
214:
215: // Begin capture
216: Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName);
217: }
218:
219: GuiOsx_ResumeFromCocoaUI();
220: }
221:
222: - (IBAction)endCaptureSound:(id)sender
223: {
224: GuiOsx_PauseAndSwitchToCocoaUI();
225: Sound_EndRecording();
226: GuiOsx_ResumeFromCocoaUI();
227: }
228:
229: - (IBAction)saveMemorySnap:(id)sender
230: {
231: GuiOsx_PauseAndSwitchToCocoaUI();
232:
233: // Get the path from the user settings
234: NSString *preferredPath = [[NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName)] stringByAbbreviatingWithTildeInPath];
235:
236: // Determine the directory and filename
237: NSString *directoryToOpen;
238: NSString *fileToPreselect;
239: if ((preferredPath != nil) && ([preferredPath length] > 0))
240: {
241: // There is existing path: we will open its directory with its file pre-selected.
242: directoryToOpen = [preferredPath stringByDeletingLastPathComponent];
243: fileToPreselect = [preferredPath lastPathComponent];
244: }
245: else
246: {
247: // Currently no path: we will open the user's directory with the default filename.
248: directoryToOpen = [@"~" stringByExpandingTildeInPath];
249: fileToPreselect = @"hatari.sav";
250: }
251:
252: // Create and configure a SavePanel for choosing what file to write
253: NSSavePanel *savePanel = [NSSavePanel savePanel];
254: [savePanel setExtensionHidden:NO];
255:
256: // Run the SavePanel, then check if the user clicked OK and selected at least one file
257: if (NSFileHandlingPanelOKButton == [savePanel runModalForDirectory:directoryToOpen file:fileToPreselect] )
258: {
259: // Get the path to the selected file
260: NSString *path = [savePanel filename];
261:
262: // Store the path in the user settings
263: GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName));
264:
265: // Perform the memory snapshot save
1.1.1.2 root 266: MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE);
1.1 root 267: }
268:
269: GuiOsx_ResumeFromCocoaUI();
270: }
271:
272: - (IBAction)restoreMemorySnap:(id)sender
273: {
274: GuiOsx_PauseAndSwitchToCocoaUI();
275:
276: // Create and configure an OpenPanel
277: NSOpenPanel *openPanel = [NSOpenPanel openPanel];
278:
279: // Get the path from the user settings
280: NSString *oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName)];
281:
282: // Determine the directory and filename
283: NSString *directoryToOpen;
284: NSString *fileToPreselect;
285: if ((oldPath != nil) && ([oldPath length] > 0))
286: {
287: // There is existing path: we will open its directory with its file pre-selected.
288: directoryToOpen = [oldPath stringByDeletingLastPathComponent];
289: fileToPreselect = [oldPath lastPathComponent];
290: }
291: else
292: {
293: // Currently no path: we will open the user's directory with no file selected.
294: directoryToOpen = [@"~" stringByExpandingTildeInPath];
295: fileToPreselect = nil;
296: }
297:
298: // Run the OpenPanel, then check if the user clicked OK and selected at least one file
299: if ( (NSOKButton == [openPanel runModalForDirectory:directoryToOpen file:fileToPreselect types:nil] )
300: && ([[openPanel filenames] count] > 0) )
301: {
302: // Get the path to the selected file
303: NSString *path = [[openPanel filenames] objectAtIndex:0];
304:
305: // Perform the memory snapshot load
1.1.1.2 root 306: MemorySnapShot_Restore([path cString], TRUE);
1.1 root 307: }
308:
309: GuiOsx_ResumeFromCocoaUI();
310: }
311:
312: - (IBAction)doFullScreen:(id)sender
313: {
314: // A call to Screen_EnterFullScreen() would be required, but this causes a crash when using SDL runtime 1.2.11, probably due to conflicts between Cocoa and SDL.
315: // Therefore we simulate the fullscreen key press instead
316:
317: SDL_KeyboardEvent event;
318: event.type = SDL_KEYDOWN;
319: event.which = 0;
320: event.state = SDL_PRESSED;
321: event.keysym.sym = SDLK_F11;
322: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press
323: event.type = SDL_KEYUP;
324: event.state = SDL_RELEASED;
325: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release
326: }
327:
328: - (IBAction)help:(id)sender
329: {
1.1.1.4 ! root 330: [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:@"http://hatari.berlios.de/"]];
1.1 root 331: }
332:
333:
334: /* Set the working directory to the .app's parent directory */
335: - (void) setupWorkingDirectory:(BOOL)shouldChdir
336: {
337: char parentdir[MAXPATHLEN];
338: char *c;
339:
340: strncpy ( parentdir, gArgv[0], sizeof(parentdir) );
341: c = (char*) parentdir;
342:
343: while (*c != '\0') /* go to end */
344: c++;
345:
346: while (*c != '/') /* back up to parent */
347: c--;
348:
349: *c++ = '\0'; /* cut off last part (binary name) */
350:
351: if (shouldChdir)
352: {
353: assert ( chdir (parentdir) == 0 ); /* chdir to the binary app's parent */
354: assert ( chdir ("../../../") == 0 ); /* chdir to the .app's parent */
355: }
356: }
357:
358:
359: /* Called when the internal event loop has just started running */
360: - (void) applicationDidFinishLaunching: (NSNotification *) note
361: {
362: int status;
363:
364: /* Set the working directory to the .app's parent directory */
365: [self setupWorkingDirectory:gFinderLaunch];
366:
367: /* Hand off to main application code */
368: status = SDL_main (gArgc, gArgv);
369:
370: /* We're done, thank you for playing */
371: exit(status);
372: }
373:
374: @end
375:
376:
377: @implementation NSString (ReplaceSubString)
378:
379: - (NSString *)stringByReplacingRange:(NSRange)aRange with:(NSString *)aString
380: {
381: unsigned int bufferSize;
382: unsigned int selfLen = [self length];
383: unsigned int aStringLen = [aString length];
384: unichar *buffer;
385: NSRange localRange;
386: NSString *result;
387:
388: bufferSize = selfLen + aStringLen - aRange.length;
389: buffer = NSAllocateMemoryPages(bufferSize*sizeof(unichar));
390:
391: /* Get first part into buffer */
392: localRange.location = 0;
393: localRange.length = aRange.location;
394: [self getCharacters:buffer range:localRange];
395:
396: /* Get middle part into buffer */
397: localRange.location = 0;
398: localRange.length = aStringLen;
399: [aString getCharacters:(buffer+aRange.location) range:localRange];
400:
401: /* Get last part into buffer */
402: localRange.location = aRange.location + aRange.length;
403: localRange.length = selfLen - localRange.location;
404: [self getCharacters:(buffer+aRange.location+aStringLen) range:localRange];
405:
406: /* Build output string */
407: result = [NSString stringWithCharacters:buffer length:bufferSize];
408:
409: NSDeallocateMemoryPages(buffer, bufferSize);
410:
411: return result;
412: }
413:
414: @end
415:
416:
417:
418: #ifdef main
419: # undef main
420: #endif
421:
422:
423: /* Main entry point to executable - should *not* be SDL_main! */
424: int main (int argc, char **argv)
425: {
426:
427: /* Copy the arguments into a global variable */
428: int i;
429:
430: /* This is passed if we are launched by double-clicking */
431: if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) {
432: gArgc = 1;
433: gFinderLaunch = YES;
434: } else {
435: gArgc = argc;
436: gFinderLaunch = NO;
437: }
438: gArgv = (char**) malloc (sizeof(*gArgv) * (gArgc+1));
439: assert (gArgv != NULL);
440: for (i = 0; i < gArgc; i++)
441: gArgv[i] = argv[i];
442: gArgv[i] = NULL;
443:
444: [SDLApplication poseAsClass:[NSApplication class]];
445: NSApplicationMain (argc, (const char**)argv);
446:
447: return 0;
448: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.