|
|
1.1.1.11! root 1: // ! 2: // HatariAppDelegate.m ! 3: // Hatari ! 4: // ! 5: // Créé le 12/06/13 par Miguel Saro. ! 6: // Tout droits réservés, - Cocoa Pod -, 2013. ! 7: // ! 8: 1.1 root 9: /* SDLMain.m - main entry point for our Cocoa-ized SDL app 10: Initial Version: Darrell Walisser <[email protected]> 11: Non-NIB-Code & other changes: Max Horn <[email protected]> 12: 13: Feel free to customize this file to suit your needs 14: 1.1.1.6 root 15: 1.1.1.11! root 16: */ 1.1 root 17: 1.1.1.11! root 18: /* Use this flag to determine whether we use SDLMain.nib or not */ ! 19: #define SDL_USE_NIB_FILE 1 1.1.1.6 root 20: 1.1.1.11! root 21: /* Use this flag to determine whether we use CPS (docking) or not */ ! 22: #define SDL_USE_CPS 1 1.1.1.6 root 23: 1.1.1.11! root 24: #import "SDL.h" ! 25: #import "SDLMain.h" ! 26: #import <sys/param.h> // for MAXPATHLEN ! 27: #import <unistd.h> 1.1.1.6 root 28: 1.1.1.11! root 29: // for Hatari ! 30: #import "dialog.h" ! 31: #import "floppy.h" ! 32: #import "reset.h" ! 33: #import "screenSnapShot.h" ! 34: #import "memorySnapShot.h" ! 35: #import "sound.h" ! 36: #import "screen.h" ! 37: #import "PrefsController.h" ! 38: #import "Shared.h" ! 39: #import "video.h" ! 40: #import "avi_record.h" ! 41: #import "debugui.h" ! 42: #import "clocks_timings.h" ! 43: #import "change.h" 1.1.1.6 root 44: 45: 46: #ifdef SDL_USE_CPS 1.1.1.11! root 47: // Portions of CPS.h 1.1.1.6 root 48: typedef struct CPSProcessSerNum 49: { 50: UInt32 lo; 51: UInt32 hi; 52: } CPSProcessSerNum; 53: 54: extern OSErr CPSGetCurrentProcess( CPSProcessSerNum *psn); 55: extern OSErr CPSEnableForegroundOperation( CPSProcessSerNum *psn, UInt32 _arg2, UInt32 _arg3, UInt32 _arg4, UInt32 _arg5); 56: extern OSErr CPSSetFrontProcess( CPSProcessSerNum *psn); 57: 1.1.1.11! root 58: #endif // SDL_USE_CPS 1.1 root 59: 1.1.1.11! root 60: static int gArgc; ! 61: static char **gArgv; ! 62: static BOOL gFinderLaunch = NO ; ! 63: static BOOL gCalledAppMainline = NO ; 1.1.1.6 root 64: 65: 1.1.1.11! root 66: // The main class of the application, the application's delegate ! 67: // ! 68: @implementation HatariAppDelegate 1.1 root 69: 1.1.1.11! root 70: char szPath[FILENAME_MAX] ; // for general use 1.1 root 71: 1.1.1.11! root 72: // Set the working directory to the .app's parent directory 1.1.1.6 root 73: - (void) setupWorkingDirectory:(BOOL)shouldChdir 74: { 75: if (shouldChdir) 1.1.1.11! root 76: chdir([[[[NSBundle mainBundle] bundlePath] stringByDeletingLastPathComponent] cStringUsingEncoding:NSASCIIStringEncoding]) ; 1.1.1.6 root 77: } 78: 79: 80: /* 81: * Catch document open requests...this lets us notice files when the app 82: * was launched by double-clicking a document, or when a document was 83: * dragged/dropped on the app's icon. You need to have a 84: * CFBundleDocumentsType section in your Info.plist to get this message, 85: * apparently. 86: * 87: * Files are added to gArgv, so to the app, they'll look like command line 88: * arguments. Previously, apps launched from the finder had nothing but 89: * an argv[0]. 90: * 91: * This message may be received multiple times to open several docs on launch. 92: * 93: * This message is ignored once the app's mainline has been called. 94: */ 95: - (BOOL)application:(NSApplication *)theApplication openFile:(NSString *)filename 96: { 97: const char *temparg; 98: size_t arglen; 99: char *arg; 100: char **newargv; 101: 1.1.1.11! root 102: if (!gFinderLaunch) // MacOS is passing command line args. 1.1.1.6 root 103: return FALSE; 104: 1.1.1.11! root 105: if (gCalledAppMainline) // app has started, ignore this document. 1.1.1.6 root 106: return FALSE; 107: 1.1.1.11! root 108: temparg = [filename UTF8String] ; ! 109: arglen = SDL_strlen(temparg) + 1 ; ! 110: arg = (char *) SDL_malloc(arglen) ; 1.1.1.6 root 111: if (arg == NULL) 112: return FALSE; 113: 1.1.1.11! root 114: newargv = (char **) realloc(gArgv, sizeof (char *) * (gArgc + 2)) ; 1.1.1.6 root 115: if (newargv == NULL) 116: { 117: SDL_free(arg); 118: return FALSE; 119: } 1.1.1.11! root 120: gArgv = newargv ; 1.1.1.6 root 121: 1.1.1.11! root 122: SDL_strlcpy(arg, temparg, arglen) ; ! 123: gArgv[gArgc++] = arg ; ! 124: gArgv[gArgc] = NULL ; 1.1.1.6 root 125: return TRUE; 126: } 127: 128: 1.1.1.11! root 129: // Called when the internal event loop has just started running ! 130: // 1.1.1.6 root 131: - (void) applicationDidFinishLaunching: (NSNotification *) note 132: { 1.1.1.11! root 133: int status; 1.1.1.6 root 134: 1.1.1.11! root 135: // Set the working directory to the .app's parent directory ! 136: [self setupWorkingDirectory:gFinderLaunch]; 1.1.1.6 root 137: 1.1.1.11! root 138: //setenv ("SDL_ENABLEAPPEVENTS", "1", 1) ; 1.1.1.6 root 139: 1.1.1.11! root 140: // Hand off to main application code 1.1.1.6 root 141: 1.1.1.11! root 142: gCalledAppMainline = TRUE; ! 143: status = SDL_main (gArgc, gArgv) ; ! 144: ! 145: // We're done, thank you for playing ! 146: exit(status) ; 1.1.1.6 root 147: } 148: 149: // Hatari Stuff 1.1 root 150: - (IBAction)prefsMenu:(id)sender 151: { 152: static int in_propdialog = 0; 1.1.1.6 root 153: 1.1 root 154: if (in_propdialog) 1.1.1.11! root 155: return ; ! 156: ++in_propdialog ; ! 157: Dialog_DoProperty() ; 1.1 root 158: --in_propdialog; 159: } 160: 1.1.1.11! root 161: /*- (IBAction) openPreferences:(id)sender 1.1.1.9 root 162: { 163: [[PrefsController prefs] loadPrefs:sender]; 1.1.1.11! root 164: } // */ 1.1.1.9 root 165: 166: 1.1.1.6 root 167: - (IBAction)debugUI:(id)sender 168: { 1.1.1.8 root 169: DebugUI(REASON_USER); 1.1.1.6 root 170: } 171: 1.1 root 172: - (IBAction)warmReset:(id)sender 173: { 1.1.1.11! root 174: if (NSRunAlertPanel (localize(@"Warm reset"), localize(@"Really reset the emulator?"), ! 175: localize(@"OK"), localize(@"Cancel"), nil) == NSAlertDefaultReturn ) 1.1 root 176: Reset_Warm(); 1.1.1.10 root 177: } 1.1 root 178: 179: - (IBAction)coldReset:(id)sender 180: { 1.1.1.11! root 181: if (NSRunAlertPanel (localize(@"Cold reset!"), localize(@"Really reset the emulator?"), ! 182: localize(@"OK"),localize(@"Cancel"), nil) == NSAlertDefaultReturn ) 1.1 root 183: Reset_Cold(); 184: } 185: 186: - (IBAction)insertDiskA:(id)sender 187: { 1.1.1.11! root 188: [self insertDisk:0] ; 1.1 root 189: } 190: 191: - (IBAction)insertDiskB:(id)sender 192: { 1.1.1.11! root 193: [self insertDisk:1] ; ! 194: } 1.1.1.6 root 195: 1.1.1.11! root 196: - (void)insertDisk:(int)disque ! 197: { ! 198: NSString *aDisk ; 1.1.1.6 root 199: 1.1.1.11! root 200: aDisk = [NSApp hopenfile:NO defoDir:nil defoFile:@"" types:[NSArray arrayWithObjects:allF,nil]] ; ! 201: if ([aDisk length] == 0) return ; // user canceled 1.1.1.6 root 202: 1.1.1.11! root 203: [aDisk getCString:szPath maxLength:FILENAME_MAX-1 encoding:NSASCIIStringEncoding] ; ! 204: Floppy_SetDiskFileName(disque, szPath, NULL) ; ! 205: Floppy_InsertDiskIntoDrive(disque) ; 1.1 root 206: } 207: 1.1.1.11! root 208: 1.1 root 209: /*-----------------------------------------------------------------------*/ 210: /* 1.1.1.6 root 211: Controls the enabled state of the menu items 212: */ 1.1 root 213: - (BOOL)validateMenuItem:(NSMenuItem*)item 214: { 215: if (item == beginCaptureAnim) 216: { 1.1.1.11! root 217: return !Avi_AreWeRecording() ; 1.1 root 218: } 219: if (item == endCaptureAnim) 220: { 1.1.1.11! root 221: return Avi_AreWeRecording() ; 1.1 root 222: } 223: if (item == beginCaptureSound) 224: { 1.1.1.11! root 225: return !Sound_AreWeRecording() ; 1.1 root 226: } 227: if (item == endCaptureSound) 228: { 1.1.1.11! root 229: return Sound_AreWeRecording() ; 1.1 root 230: } 231: 232: return YES; 233: } 234: 1.1.1.7 root 235: - (NSString*)displayFileSelection:(const char*)pathInParams preferredFileName:(NSString*)preferredFileName allowedExtensions:(NSArray*)allowedExtensions 1.1 root 236: { 1.1.1.11! root 237: // BOOL test ; ! 238: NSString *directoryToOpen; ! 239: NSString *fileToPreselect; ! 240: NSString *preferredPath; ! 241: NSString *extensionText; ! 242: NSString *selectFile; 1.1.1.7 root 243: 1.1 root 244: // Get the path from the user settings 1.1.1.11! root 245: preferredPath = [[NSString stringWithCString:pathInParams encoding:NSASCIIStringEncoding] stringByAbbreviatingWithTildeInPath]; ! 246: 1.1.1.7 root 247: 1.1.1.11! root 248: if ((preferredPath != nil) && ([preferredPath length] > 0)) // Determine the directory and filename ! 249: { ! 250: directoryToOpen = [preferredPath stringByDeletingLastPathComponent]; // Existing path: we use it 1.1 root 251: fileToPreselect = [preferredPath lastPathComponent]; 1.1.1.11! root 252: } 1.1 root 253: else 1.1.1.11! root 254: { ! 255: directoryToOpen = [@"~" stringByExpandingTildeInPath]; // No path: we use the user's directory 1.1.1.7 root 256: fileToPreselect = preferredFileName; 1.1.1.11! root 257: } ; ! 258: ! 259: if(bInFullScreen) ! 260: Screen_ReturnFromFullScreen(); ! 261: // SavePanel for choosing what file to write ! 262: extensionText = [NSString stringWithFormat:localize(@"Please specify a .%@ file"), [allowedExtensions componentsJoinedByString:localize(@" or a .")] ]; ! 263: ! 264: selectFile = [NSApp hsavefile:YES defoDir:directoryToOpen defoFile:fileToPreselect types:allowedExtensions titre:extensionText ] ; ! 265: if ([selectFile length] != 0 ) ! 266: return selectFile ; 1.1.1.7 root 267: 268: return nil; 269: } 270: 271: - (IBAction)captureScreen:(id)sender 272: { 273: GuiOsx_Pause(); 274: ScreenSnapShot_SaveScreen(); 275: GuiOsx_Resume(); 276: } 277: 278: - (IBAction)captureAnimation:(id)sender 279: { 280: GuiOsx_Pause(); 281: if(!Avi_AreWeRecording()) { 282: NSString* path = [self displayFileSelection:ConfigureParams.Video.AviRecordFile preferredFileName:@"hatari.avi" 1.1.1.11! root 283: allowedExtensions:[NSArray arrayWithObject:@"avi"]]; 1.1 root 284: 1.1.1.7 root 285: if(path) { 286: GuiOsx_ExportPathString(path, ConfigureParams.Video.AviRecordFile, sizeof(ConfigureParams.Video.AviRecordFile)); 287: Avi_StartRecording ( ConfigureParams.Video.AviRecordFile , ConfigureParams.Screen.bCrop , 288: ConfigureParams.Video.AviRecordFps == 0 ? 289: ClocksTimings_GetVBLPerSec ( ConfigureParams.System.nMachineType , nScreenRefreshRate ) : 290: (Uint32)ConfigureParams.Video.AviRecordFps << CLOCKS_TIMINGS_SHIFT_VBL , 291: 1 << CLOCKS_TIMINGS_SHIFT_VBL , 292: ConfigureParams.Video.AviRecordVcodec ); 293: } 1.1.1.6 root 294: 1.1.1.7 root 295: } else { 296: Avi_StopRecording(); 1.1.1.6 root 297: } 1.1.1.7 root 298: GuiOsx_Resume(); 299: } 1.1 root 300: 1.1.1.7 root 301: - (IBAction)endCaptureAnimation:(id)sender 302: { 1.1.1.11! root 303: GuiOsx_Pause(); ! 304: Avi_StopRecording(); ! 305: GuiOsx_Resume(); 1.1.1.7 root 306: } 307: 308: - (IBAction)captureSound:(id)sender 309: { 310: GuiOsx_Pause(); 311: NSString* path = [self displayFileSelection:ConfigureParams.Sound.szYMCaptureFileName preferredFileName:@"hatari.wav" 312: allowedExtensions:[NSArray arrayWithObjects:@"ym", @"wav", nil]]; 313: if(path) { 314: GuiOsx_ExportPathString(path, ConfigureParams.Sound.szYMCaptureFileName, sizeof(ConfigureParams.Sound.szYMCaptureFileName)); 315: Sound_BeginRecording(ConfigureParams.Sound.szYMCaptureFileName); 316: } 1.1.1.5 root 317: GuiOsx_Resume(); 1.1 root 318: } 319: 320: - (IBAction)endCaptureSound:(id)sender 321: { 1.1.1.5 root 322: GuiOsx_Pause(); 1.1 root 323: Sound_EndRecording(); 1.1.1.5 root 324: GuiOsx_Resume(); 1.1 root 325: } 326: 327: - (IBAction)saveMemorySnap:(id)sender 328: { 1.1.1.5 root 329: GuiOsx_Pause(); 1.1 root 330: 1.1.1.7 root 331: NSString* path = [self displayFileSelection:ConfigureParams.Memory.szMemoryCaptureFileName preferredFileName:@"hatari.sav" 1.1.1.11! root 332: allowedExtensions:[NSArray arrayWithObject:@"sav"]]; 1.1.1.7 root 333: if(path) { 1.1 root 334: GuiOsx_ExportPathString(path, ConfigureParams.Memory.szMemoryCaptureFileName, sizeof(ConfigureParams.Memory.szMemoryCaptureFileName)); 1.1.1.2 root 335: MemorySnapShot_Capture(ConfigureParams.Memory.szMemoryCaptureFileName, TRUE); 1.1.1.6 root 336: } 1.1.1.7 root 337: 1.1.1.5 root 338: GuiOsx_Resume(); 1.1 root 339: } 340: 341: - (IBAction)restoreMemorySnap:(id)sender 342: { 1.1.1.11! root 343: NSString *directoryToOpen; ! 344: NSString *fileToPreselect; ! 345: NSString *oldPath ; ! 346: NSString *newPath ; 1.1 root 347: 1.1.1.11! root 348: GuiOsx_Pause(); 1.1 root 349: 350: // Get the path from the user settings 1.1.1.11! root 351: oldPath = [NSString stringWithCString:(ConfigureParams.Memory.szMemoryCaptureFileName) encoding:NSASCIIStringEncoding]; ! 352: ! 353: if ((oldPath != nil) && ([oldPath length] > 0)) // Determine directory and filename ! 354: { directoryToOpen = [oldPath stringByDeletingLastPathComponent]; // existing path: we use it. ! 355: fileToPreselect = [oldPath lastPathComponent]; } 1.1 root 356: else 1.1.1.11! root 357: { directoryToOpen = [@"~" stringByExpandingTildeInPath]; // Currently no path: we use user's directory ! 358: fileToPreselect = nil; } ; 1.1.1.6 root 359: 1.1.1.11! root 360: newPath = [NSApp hopenfile:NO defoDir:directoryToOpen defoFile:fileToPreselect types:[NSArray arrayWithObject:@"sav"] ] ; ! 361: if ([newPath length] != 0) // Perform the memory snapshot load ! 362: MemorySnapShot_Restore([newPath cStringUsingEncoding:NSASCIIStringEncoding], TRUE); 1.1.1.6 root 363: 1.1.1.5 root 364: GuiOsx_Resume(); 1.1 root 365: } 366: 367: - (IBAction)doFullScreen:(id)sender 368: { 1.1.1.11! root 369: // A call to Screen_EnterFullScreen() would be required, but this causes a crash when using ! 370: // SDL runtime 1.2.11, probably due to conflicts between Cocoa and SDL. 1.1 root 371: // Therefore we simulate the fullscreen key press instead 372: 373: SDL_KeyboardEvent event; 1.1.1.6 root 374: event.type = SDL_KEYDOWN; 375: event.which = 0; 376: event.state = SDL_PRESSED; 377: event.keysym.sym = SDLK_F11; 378: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key press 379: event.type = SDL_KEYUP; 380: event.state = SDL_RELEASED; 381: SDL_PushEvent((SDL_Event*)&event); // Send the F11 key release 1.1 root 382: } 383: 1.1.1.9 root 384: 1.1 root 385: - (IBAction)help:(id)sender 386: { 1.1.1.11! root 387: NSString *the_help; 1.1.1.10 root 388: 1.1.1.11! root 389: the_help = [[NSBundle mainBundle] pathForResource:@"manual" ofType:@"html" inDirectory:@"HatariHelp"]; 1.1.1.10 root 390: 1.1.1.11! root 391: if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"HelpViewer"]) ! 392: if (![[NSWorkspace sharedWorkspace] openFile:the_help withApplication:@"Help Viewer"]) ! 393: [[NSWorkspace sharedWorkspace] openFile:the_help]; 1.1 root 394: } 395: 1.1.1.10 root 396: - (IBAction)compat:(id)sender 397: { 398: NSString *C_aide ; 399: 1.1.1.11! root 400: C_aide = [[NSBundle mainBundle] pathForResource:@"compatibility" ofType:@"html" inDirectory:@"HatariHelp"] ; 1.1.1.10 root 401: 402: if (![[NSWorkspace sharedWorkspace] openFile:C_aide withApplication:@"HelpViewer"]) 403: if (![[NSWorkspace sharedWorkspace] openFile:C_aide withApplication:@"Help Viewer"]) 404: [[NSWorkspace sharedWorkspace] openFile:C_aide] ; 405: } 1.1 root 406: 1.1.1.9 root 407: - (IBAction)openConfig:(id)sender 408: { 1.1.1.11! root 409: BOOL applyChanges ; ! 410: NSString *ConfigFile, *newCfg ; ! 411: CNF_PARAMS CurrentParams; ! 412: ! 413: applyChanges = true ; ! 414: ConfigFile = [NSString stringWithCString:(sConfigFileName) encoding:NSASCIIStringEncoding]; 1.1.1.9 root 415: 416: // Backup of configuration settings to CurrentParams (which we will only 417: // commit back to the configuration settings if choosing user confirm) 418: CurrentParams = ConfigureParams; 419: 420: GuiOsx_Pause(); 421: 1.1.1.11! root 422: newCfg = [NSApp hopenfile:NO defoDir:nil defoFile:ConfigFile types:[NSArray arrayWithObject:@"cfg"] ] ; 1.1.1.9 root 423: 1.1.1.11! root 424: if ([newCfg length] != 0) ! 425: { ! 426: [newCfg getCString:szPath maxLength:FILENAME_MAX-1 encoding:NSASCIIStringEncoding] ; // get Cstring szPath ! 427: Configuration_Load(szPath) ; // Load the config into ConfigureParams ! 428: strcpy(sConfigFileName,szPath) ; ! 429: ! 430: // Refresh all the controls to match ConfigureParams 1.1.1.9 root 431: if (Change_DoNeedReset(&CurrentParams, &ConfigureParams)) 1.1.1.11! root 432: applyChanges = NSRunAlertPanel(localize(@"Reset the emulator"), localize(@"Must be reset"), ! 433: localize(@"Don't reset"), localize(@"Reset"), nil) == NSAlertAlternateReturn ; ! 434: 1.1.1.9 root 435: if (applyChanges) 1.1.1.11! root 436: Change_CopyChangedParamsToConfiguration(&CurrentParams, &ConfigureParams, true); // Ok with Reset ! 437: else ! 438: ConfigureParams = CurrentParams; //Restore previous Params. ! 439: } ; 1.1.1.9 root 440: 441: GuiOsx_Resume(); 1.1 root 442: } 443: 1.1.1.9 root 444: 1.1.1.6 root 445: - (IBAction)saveConfig:(id)sender { 1.1 root 446: } 447: 448: @end 449: 450: #ifdef main 451: # undef main 452: #endif 453: 1.1.1.11! root 454: // Main entry point to executable - should *not* be SDL_main! 1.1 root 455: int main (int argc, char **argv) 456: { 1.1.1.11! root 457: // Copy the arguments into a global variable ! 458: // This is passed if we are launched by double-clicking 1.1 root 459: if ( argc >= 2 && strncmp (argv[1], "-psn", 4) == 0 ) { 1.1.1.6 root 460: gArgv = (char **) SDL_malloc(sizeof (char *) * 2); 461: gArgv[0] = argv[0]; 462: gArgv[1] = NULL; 1.1 root 463: gArgc = 1; 1.1.1.6 root 464: gFinderLaunch = YES; 1.1 root 465: } else { 1.1.1.6 root 466: int i; 1.1 root 467: gArgc = argc; 1.1.1.6 root 468: gArgv = (char **) SDL_malloc(sizeof (char *) * (argc+1)); 469: for (i = 0; i <= argc; i++) 470: gArgv[i] = argv[i]; 471: gFinderLaunch = NO; 1.1.1.11! root 472: } // */ 1.1 root 473: 1.1.1.6 root 474: #if SDL_USE_NIB_FILE 1.1.1.7 root 475: NSApplicationMain (argc, (const char**)argv); 1.1.1.6 root 476: #else 477: CustomApplicationMain (argc, argv); 478: #endif 1.1 root 479: return 0; 1.1.1.11! root 480: } // */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.