1/*****************************************************************************\ 2 Snes9x - Portable Super Nintendo Entertainment System (TM) emulator. 3 This file is licensed under the Snes9x License. 4 For further information, consult the LICENSE file in the root directory. 5\*****************************************************************************/ 6 7/*********************************************************************************** 8 SNES9X for Mac OS (c) Copyright John Stiles 9 10 Snes9x for Mac OS X 11 12 (c) Copyright 2001 - 2011 zones 13 (c) Copyright 2002 - 2005 107 14 (c) Copyright 2002 PB1400c 15 (c) Copyright 2004 Alexander and Sander 16 (c) Copyright 2004 - 2005 Steven Seeger 17 (c) Copyright 2005 Ryan Vogt 18 ***********************************************************************************/ 19 20 21#import "snes9x.h" 22#import "memmap.h" 23#import "apu.h" 24#import "controls.h" 25#import "crosshairs.h" 26#import "cheats.h" 27#import "movie.h" 28#import "snapshot.h" 29#import "display.h" 30#import "blit.h" 31 32#ifdef DEBUGGER 33#import "debug.h" 34#endif 35 36#import <Cocoa/Cocoa.h> 37#import <QuickTime/QuickTime.h> 38#import <pthread.h> 39 40#import "mac-prefix.h" 41#import "mac-appleevent.h" 42#import "mac-audio.h" 43#import "mac-cheat.h" 44#import "mac-cheatfinder.h" 45#import "mac-client.h" 46#import "mac-cocoatools.h" 47#import "mac-controls.h" 48#import "mac-coreimage.h" 49#import "mac-dialog.h" 50#import "mac-file.h" 51#import "mac-gworld.h" 52#import "mac-joypad.h" 53#import "mac-keyboard.h" 54#import "mac-multicart.h" 55#import "mac-musicbox.h" 56#import "mac-netplay.h" 57#import "mac-prefs.h" 58#import "mac-quicktime.h" 59#import "mac-render.h" 60#import "mac-screenshot.h" 61#import "mac-server.h" 62#import "mac-snes9x.h" 63#import "mac-stringtools.h" 64#import "mac-os.h" 65 66#define kRecentMenu_MAX 20 67#define KeyIsPressed(km, k) (1 & (((unsigned char *) km) [(k) >> 3] >> ((k) & 7))) 68 69volatile bool8 running = false; 70volatile bool8 s9xthreadrunning = false; 71 72volatile bool8 eventQueued = false; 73 74volatile int windowResizeCount = 1; 75volatile bool8 windowExtend = true; 76 77SInt32 systemVersion; 78 79uint32 controlPad[MAC_MAX_PLAYERS]; 80 81uint8 romDetect = 0, 82 interleaveDetect = 0, 83 videoDetect = 0, 84 headerDetect = 0; 85 86WindowRef gWindow = NULL; 87HIRect gWindowRect; 88int glScreenW, 89 glScreenH; 90CGRect glScreenBounds; 91Point windowPos[kWindowCount]; 92CGSize windowSize[kWindowCount]; 93 94CGImageRef macIconImage[118]; 95int macPadIconIndex, 96 macLegendIconIndex, 97 macMusicBoxIconIndex, 98 macFunctionIconIndex; 99 100int macFrameSkip = -1; 101int32 skipFrames = 3; 102int64 lastFrame = 0; 103 104int macFastForwardRate = 5, 105 macFrameAdvanceRate = 1000000; 106 107unsigned long spcFileCount = 0, 108 pngFileCount = 0; 109 110bool8 finished = false, 111 cartOpen = false, 112 autofire = false, 113 hidExist = true, 114 directDisplay = false; 115 116bool8 fullscreen = false, 117 autoRes = false, 118 glstretch = true, 119 gl32bit = true, 120 vsync = true, 121 drawoverscan = false, 122 screencurvature = false, 123 multiprocessor = false, 124 ciFilterEnable = false; 125long drawingMethod = kDrawingOpenGL; 126int videoMode = VIDEOMODE_SMOOTH; 127 128SInt32 macSoundVolume = 80; // % 129uint32 macSoundBuffer_ms = 80; // ms 130uint32 macSoundInterval_ms = 16; // ms 131bool8 macSoundLagEnable = false; 132uint16 aueffect = 0; 133 134uint8 saveInROMFolder = 2; // 0 : Snes9x 1 : ROM 2 : Application Support 135CFStringRef saveFolderPath; 136 137int macCurvatureWarp = 15, 138 macAspectRatio = 0; 139 140bool8 startopendlog = false, 141 showtimeinfrz = true, 142 enabletoggle = true, 143 savewindowpos = false, 144 onscreeninfo = true; 145int inactiveMode = 2; 146int musicboxmode = kMBXSoundEmulation; 147 148bool8 applycheat = false; 149int padSetting = 1, 150 deviceSetting = 1, 151 deviceSettingMaster = 1; 152int macControllerOption = SNES_JOYPAD; 153AutoFireState autofireRec[MAC_MAX_PLAYERS]; 154 155bool8 macQTRecord = false; 156uint16 macQTMovFlag = 0; 157 158uint16 macRecordFlag = 0x3, 159 macPlayFlag = 0x1; 160wchar_t macRecordWChar[MOVIE_MAX_METADATA]; 161 162char npServerIP[256], 163 npName[256]; 164 165bool8 lastoverscan = false; 166 167CGPoint unlimitedCursor; 168 169ExtraOption extraOptions; 170 171CFStringRef multiCartPath[2]; 172 173#ifdef MAC_PANTHER_SUPPORT 174IconRef macIconRef[118]; 175#endif 176 177enum 178{ 179 mApple = 128, 180 iAbout = 1, 181 182 mFile = 129, 183 iOpen = 1, 184 iOpenMulti = 2, 185 iOpenRecent = 3, 186 iClose = 5, 187 iRomInfo = 7, 188 189 mControl = 134, 190 iKeyboardLayout = 1, 191 iISpLayout = 2, 192 iAutoFire = 4, 193 iISpPreset = 6, 194 195 mEdit = 130, 196 197 mEmulation = 131, 198 iResume = 1, 199 iSoftReset = 3, 200 iReset = 4, 201 iDevice = 6, 202 203 mCheat = 132, 204 iApplyCheats = 1, 205 iGameGenie = 3, 206 iCheatFinder = 4, 207 208 mOption = 133, 209 iFreeze = 1, 210 iDefrost = 2, 211 iFreezeTo = 4, 212 iDefrostFrom = 5, 213 iRecordMovie = 7, 214 iPlayMovie = 8, 215 iQTMovie = 10, 216 iSaveSPC = 12, 217 iSaveSRAM = 13, 218 iCIFilter = 15, 219 iMusicBox = 17, 220 221 mNetplay = 135, 222 iServer = 1, 223 iClient = 2, 224 225 mPresets = 201, 226 227 mDevice = 202, 228 iPad = 1, 229 iMouse = 2, 230 iMouse2 = 3, 231 iSuperScope = 4, 232 iMultiPlayer5 = 5, 233 iMultiPlayer5_2 = 6, 234 iJustifier1 = 7, 235 iJustifier2 = 8, 236 237 mRecentItem = 203 238}; 239 240enum 241{ 242 kmF1Key = 0x7A, 243 kmF2Key = 0x78, 244 kmF3Key = 0x63, 245 kmF4Key = 0x76, 246 kmF5Key = 0x60, 247 kmF6Key = 0x61, 248 km0Key = 0x1D, 249 km1Key = 0x12, 250 km2Key = 0x13, 251 km3Key = 0x14, 252 km4Key = 0x15, 253 km5Key = 0x17, 254 km6Key = 0x16, 255 km7Key = 0x1A, 256 km8Key = 0x1C, 257 km9Key = 0x19, 258 kmAKey = 0x00, 259 kmBKey = 0x0B, 260 kmCKey = 0x08, 261 kmEscKey = 0x35, 262 kmCtrKey = 0x3B, 263 kmMinusKey = 0x1B, 264 kmQKey = 0x0C, 265 kmWKey = 0x0D, 266 kmOKey = 0x1F, 267 kmPKey = 0x23 268}; 269 270struct ButtonCommand 271{ 272 char command[16]; 273 uint8 keycode; 274 bool8 held; 275}; 276 277struct GameViewInfo 278{ 279 int globalLeft; 280 int globalTop; 281 int width; 282 int height; 283}; 284 285static volatile bool8 rejectinput = false; 286 287static bool8 pauseEmulation = false, 288 frameAdvance = false; 289 290static pthread_t s9xthread; 291 292static MenuRef recentMenu; 293static CFStringRef recentItem[kRecentMenu_MAX + 1]; 294 295static EventHandlerUPP gameWindowUPP, 296 gameWUPaneUPP; 297static EventHandlerRef gameWindowEventRef, 298 gameWUPaneEventRef; 299 300static int windowZoomCount = 0; 301 302static int frameCount = 0; 303 304static bool8 frzselecting = false; 305 306static uint16 changeAuto[2] = { 0x0000, 0x0000 }; 307 308static GameViewInfo scopeViewInfo; 309 310static ButtonCommand btncmd[] = 311{ 312 { "ToggleBG0", kmF1Key, false }, 313 { "ToggleBG1", kmF2Key, false }, 314 { "ToggleBG2", kmF3Key, false }, 315 { "ToggleBG3", kmF4Key, false }, 316 { "ToggleSprites", kmF5Key, false }, 317 { "SwapJoypads", kmF6Key, false }, 318 { "SoundChannel0", km1Key, false }, 319 { "SoundChannel1", km2Key, false }, 320 { "SoundChannel2", km3Key, false }, 321 { "SoundChannel3", km4Key, false }, 322 { "SoundChannel4", km5Key, false }, 323 { "SoundChannel5", km6Key, false }, 324 { "SoundChannel6", km7Key, false }, 325 { "SoundChannel7", km8Key, false }, 326 { "SoundChannelsOn", km9Key, false }, 327 { "_mac1", km0Key, false }, 328 { "_mac2", kmMinusKey, false }, 329 { "_mac3", kmQKey, false }, 330 { "_mac4", kmWKey, false }, 331 { "_mac5", kmOKey, false }, 332 { "_mac6", kmPKey, false } 333}; 334 335#define kCommandListSize (sizeof(btncmd) / sizeof(btncmd[0])) 336 337static void Initialize (void); 338static void Deinitialize (void); 339static void InitAutofire (void); 340static void InitRecentItems (void); 341static void DeinitRecentItems (void); 342static void ClearRecentItems (void); 343static void InitRecentMenu (void); 344static void DeinitRecentMenu (void); 345static void ProcessInput (void); 346static void ResizeGameWindow (void); 347static void ChangeAutofireSettings (int, int); 348static void ChangeTurboRate (int); 349static void ForceChangingKeyScript (void); 350static void CFTimerCallback (CFRunLoopTimerRef, void *); 351static void UpdateFreezeDefrostScreen (int, CGImageRef, uint8 *, CGContextRef); 352static void * MacSnes9xThread (void *); 353static OSStatus HandleMenuChoice (UInt32, Boolean *); 354static inline void EmulationLoop (void); 355static pascal OSStatus MainEventHandler (EventHandlerCallRef, EventRef, void *); 356static pascal OSStatus SubEventHandler (EventHandlerCallRef, EventRef, void *); 357static pascal OSStatus GameWindowEventHandler (EventHandlerCallRef, EventRef, void *); 358static pascal OSStatus GameWindowUserPaneEventHandler (EventHandlerCallRef, EventRef, void *); 359 360 361int main (int argc, char **argv) 362{ 363#ifdef MAC_PANTHER_SUPPORT 364 NSAutoreleasePool *pool; 365#endif 366 OSStatus err; 367 EventHandlerRef eref; 368 EventHandlerUPP eUPP; 369 EventTypeSpec mEvents[] = { { kEventClassCommand, kEventCommandProcess }, 370 { kEventClassCommand, kEventCommandUpdateStatus } }, 371 sEvents[] = { { kEventClassCommand, kEventCommandProcess }, 372 { kEventClassCommand, kEventCommandUpdateStatus }, 373 { kEventClassMouse, kEventMouseUp }, 374 { kEventClassMouse, kEventMouseMoved }, 375 { kEventClassMouse, kEventMouseDragged } }; 376 377#ifdef MAC_PANTHER_SUPPORT 378 pool = [[NSAutoreleasePool alloc] init]; 379#endif 380 eUPP = NewEventHandlerUPP(MainEventHandler); 381 err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(mEvents), mEvents, NULL, &eref); 382 383 Initialize(); 384 385 while (!finished) 386 { 387 if (cartOpen && running) 388 { 389 #ifdef DEBUGGER 390 CPU.Flags |= DEBUG_MODE_FLAG; 391 S9xDoDebug(); 392 #endif 393 394 eventQueued = false; 395 396 Microseconds((UnsignedWide *) &lastFrame); 397 frameCount = 0; 398 if (macFrameSkip < 0) 399 skipFrames = 3; 400 else 401 skipFrames = macFrameSkip; 402 403 err = RemoveEventHandler(eref); 404 DisposeEventHandlerUPP(eUPP); 405 #ifdef MAC_PANTHER_SUPPORT 406 [pool release]; 407 408 pool = [[NSAutoreleasePool alloc] init]; 409 #endif 410 eUPP = NewEventHandlerUPP(SubEventHandler); 411 err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(sEvents), sEvents, NULL, &eref); 412 413 S9xInitDisplay(NULL, NULL); 414 ClearGFXScreen(); 415 416 if (!fullscreen) 417 ForceChangingKeyScript(); 418 419 pthread_create(&s9xthread, NULL, MacSnes9xThread, NULL); 420 421 CFRunLoopTimerRef cftimer = NULL; 422 CFRunLoopTimerContext cftimerctx = { 0, NULL, NULL, NULL, NULL }; 423 424 if (!fullscreen) 425 { 426 cftimer = CFRunLoopTimerCreate(kCFAllocatorDefault, CFAbsoluteTimeGetCurrent(), 30, 0, 0, CFTimerCallback, &cftimerctx); 427 if (cftimer) 428 CFRunLoopAddTimer(CFRunLoopGetCurrent(), cftimer, kCFRunLoopCommonModes); 429 } 430 431 AdjustMenus(); 432 433 RunApplicationEventLoop(); 434 435 if (!fullscreen) 436 { 437 if (cftimer) 438 { 439 CFRunLoopTimerInvalidate(cftimer); 440 CFRelease(cftimer); 441 cftimer = NULL; 442 } 443 } 444 445 pthread_join(s9xthread, NULL); 446 447 if (!Settings.NetPlay || Settings.NetPlayServer) 448 { 449 SNES9X_SaveSRAM(); 450 S9xResetSaveTimer(false); 451 S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR)); 452 } 453 454 S9xDeinitDisplay(); 455 456 if (Settings.NetPlay) 457 { 458 if (!Settings.NetPlayServer) 459 { 460 DeinitGameWindow(); 461 cartOpen = false; 462 } 463 464 Settings.NetPlay = false; 465 Settings.NetPlayServer = false; 466 } 467 468 err = RemoveEventHandler(eref); 469 DisposeEventHandlerUPP(eUPP); 470 #ifdef MAC_PANTHER_SUPPORT 471 [pool release]; 472 473 pool = [[NSAutoreleasePool alloc] init]; 474 #endif 475 eUPP = NewEventHandlerUPP(MainEventHandler); 476 err = InstallApplicationEventHandler(eUPP, GetEventTypeCount(mEvents), mEvents, NULL, &eref); 477 } 478 479 if (!finished) 480 { 481 AdjustMenus(); 482 RunApplicationEventLoop(); 483 } 484 } 485 486 Deinitialize(); 487 488 err = RemoveEventHandler(eref); 489 DisposeEventHandlerUPP(eUPP); 490#ifdef MAC_PANTHER_SUPPORT 491 [pool release]; 492#endif 493 494 return (0); 495} 496 497static void CFTimerCallback (CFRunLoopTimerRef timer, void *info) 498{ 499 OSStatus err; 500 501 err = UpdateSystemActivity(OverallAct); 502} 503 504static void * MacSnes9xThread (void *) 505{ 506 Settings.StopEmulation = false; 507 s9xthreadrunning = true; 508 509 EmulationLoop(); 510 511 s9xthreadrunning = false; 512 Settings.StopEmulation = true; 513 514 return (NULL); 515} 516 517static inline void EmulationLoop (void) 518{ 519 bool8 olddisplayframerate = false; 520 int storedMacFrameSkip = macFrameSkip; 521 522 pauseEmulation = false; 523 frameAdvance = false; 524 525 if (macQTRecord) 526 { 527 olddisplayframerate = Settings.DisplayFrameRate; 528 Settings.DisplayFrameRate = false; 529 } 530 531 MacStartSound(); 532 533 if (Settings.NetPlay) 534 { 535 if (Settings.NetPlayServer) 536 { 537 NPServerDetachNetPlayThread(); 538 NPServerStartClients(); 539 540 while (running) 541 { 542 NPServerProcessInput(); 543 S9xMainLoop(); 544 } 545 546 NPServerStopNetPlayThread(); 547 NPServerStopServer(); 548 } 549 else 550 { 551 NPClientDetachNetPlayThread(); 552 NPClientNetPlayWaitStart(); 553 554 while (running) 555 { 556 NPClientProcessInput(); 557 S9xMainLoop(); 558 } 559 560 NPClientStopNetPlayThread(); 561 NPClientDisconnect(); 562 563 NPClientRestoreConfig(); 564 } 565 } 566 else 567 { 568 while (running) 569 { 570 ProcessInput(); 571 572 if (!pauseEmulation) 573 S9xMainLoop(); 574 else 575 { 576 if (frameAdvance) 577 { 578 macFrameSkip = 1; 579 skipFrames = 1; 580 frameAdvance = false; 581 S9xMainLoop(); 582 macFrameSkip = storedMacFrameSkip; 583 } 584 585 usleep(Settings.FrameTime); 586 } 587 } 588 } 589 590 MacStopSound(); 591 592 if (macQTRecord) 593 { 594 MacQTStopRecording(); 595 macQTRecord = false; 596 597 Settings.DisplayFrameRate = olddisplayframerate; 598 } 599 600 S9xMovieShutdown(); 601} 602 603static pascal OSStatus MainEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 604{ 605 OSStatus err, result = eventNotHandledErr; 606 Boolean done = false; 607 608 if (frzselecting) 609 return (result); 610 611 switch (GetEventClass(inEvent)) 612 { 613 case kEventClassCommand: 614 switch (GetEventKind(inEvent)) 615 { 616 HICommand cmd; 617 618 case kEventCommandUpdateStatus: 619 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); 620 if (err == noErr && cmd.commandID == 'clos') 621 { 622 UpdateMenuCommandStatus(false); 623 result = noErr; 624 } 625 626 break; 627 628 case kEventCommandProcess: 629 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); 630 if (err == noErr) 631 { 632 UInt32 modifierkey; 633 634 err = GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifierkey); 635 if (err == noErr) 636 { 637 if ((cmd.commandID == 'pref') && (modifierkey & optionKey)) 638 cmd.commandID = 'EXTR'; 639 640 result = HandleMenuChoice(cmd.commandID, &done); 641 642 if (done) 643 QuitApplicationEventLoop(); 644 } 645 } 646 647 break; 648 } 649 650 break; 651 } 652 653 return (result); 654} 655 656static pascal OSStatus SubEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 657{ 658 OSStatus err, result = eventNotHandledErr; 659 660 if (frzselecting) 661 return (result); 662 663 switch (GetEventClass(inEvent)) 664 { 665 case kEventClassCommand: 666 switch (GetEventKind(inEvent)) 667 { 668 HICommand cmd; 669 670 case kEventCommandUpdateStatus: 671 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); 672 if (err == noErr && cmd.commandID == 'clos') 673 { 674 UpdateMenuCommandStatus(false); 675 result = noErr; 676 } 677 678 break; 679 680 case kEventCommandProcess: 681 err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd); 682 if (err == noErr) 683 { 684 switch (cmd.commandID) 685 { 686 case 'Erun': // Pause 687 case 'SubQ': // Queue from emulation thread 688 running = false; 689 while (s9xthreadrunning) 690 sleep(0); 691 QuitApplicationEventLoop(); 692 result = noErr; 693 break; 694 695 case 'Ocif': // Core Image Filter 696 HiliteMenu(0); 697 ConfigureCoreImageFilter(); 698 result = noErr; 699 break; 700 } 701 } 702 703 break; 704 } 705 706 break; 707 708 case kEventClassMouse: 709 if (fullscreen) 710 { 711 if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) 712 { 713 if (!(Settings.NetPlay && !Settings.NetPlayServer)) 714 { 715 switch (GetEventKind(inEvent)) 716 { 717 case kEventMouseUp: 718 HIPoint hipt; 719 720 err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt); 721 if (err == noErr) 722 { 723 if (CGRectContainsPoint(glScreenBounds, hipt)) 724 { 725 running = false; 726 while (s9xthreadrunning) 727 sleep(0); 728 QuitApplicationEventLoop(); 729 result = noErr; 730 } 731 } 732 733 break; 734 } 735 } 736 } 737 else 738 if ((macControllerOption == SNES_MOUSE) || (macControllerOption == SNES_MOUSE_SWAPPED)) 739 { 740 switch (GetEventKind(inEvent)) 741 { 742 case kEventMouseMoved: 743 case kEventMouseDragged: 744 HIPoint hipt; 745 746 err = GetEventParameter(inEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt); 747 if (err == noErr) 748 { 749 unlimitedCursor.x += hipt.x; 750 unlimitedCursor.y += hipt.y; 751 } 752 753 break; 754 } 755 } 756 } 757 758 break; 759 } 760 761 return (result); 762} 763 764void PostQueueToSubEventLoop (void) 765{ 766 OSStatus err; 767 EventRef event; 768 769 err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, 0, kEventAttributeUserEvent, &event); 770 if (err == noErr) 771 { 772 HICommand cmd; 773 774 cmd.commandID = 'SubQ'; 775 cmd.attributes = kEventAttributeUserEvent; 776 cmd.menu.menuRef = NULL; 777 cmd.menu.menuItemIndex = 0; 778 779 err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd); 780 if (err == noErr) 781 err = PostEventToQueue(GetMainEventQueue(), event, kEventPriorityStandard); 782 783 ReleaseEvent(event); 784 } 785} 786 787void InitGameWindow (void) 788{ 789 OSStatus err; 790 IBNibRef nibRef; 791 WindowAttributes attr; 792 CFStringRef ref; 793 HIViewRef ctl; 794 HIViewID cid = { 'Pict', 0 }; 795 Rect rct; 796 char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; 797 EventTypeSpec wupaneEvents[] = { { kEventClassControl, kEventControlClick }, 798 { kEventClassControl, kEventControlDraw } }, 799 windowEvents[] = { { kEventClassWindow, kEventWindowDeactivated }, 800 { kEventClassWindow, kEventWindowActivated }, 801 { kEventClassWindow, kEventWindowBoundsChanging }, 802 { kEventClassWindow, kEventWindowBoundsChanged }, 803 { kEventClassWindow, kEventWindowZoom }, 804 { kEventClassWindow, kEventWindowToolbarSwitchMode } }; 805 806 if (gWindow) 807 return; 808 809 err = CreateNibReference(kMacS9XCFString, &nibRef); 810 if (err) 811 QuitWithFatalError(err, "os 02"); 812 813 err = CreateWindowFromNib(nibRef, CFSTR("GameWindow"), &gWindow); 814 if (err) 815 QuitWithFatalError(err, "os 03"); 816 817 DisposeNibReference(nibRef); 818 819 HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl); 820 821 gameWindowUPP = NewEventHandlerUPP(GameWindowEventHandler); 822 err = InstallWindowEventHandler(gWindow, gameWindowUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) gWindow, &gameWindowEventRef); 823 824 gameWUPaneUPP = NewEventHandlerUPP(GameWindowUserPaneEventHandler); 825 err = InstallControlEventHandler(ctl, gameWUPaneUPP, GetEventTypeCount(wupaneEvents), wupaneEvents, (void *) gWindow, &gameWUPaneEventRef); 826 827 _splitpath(Memory.ROMFilename, drive, dir, fname, ext); 828 ref = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8); 829 if (ref) 830 { 831 SetWindowTitleWithCFString(gWindow, ref); 832 CFRelease(ref); 833 } 834 835 attr = kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute; 836 err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes); 837 838 attr = kWindowToolbarButtonAttribute; 839 if (!drawoverscan) 840 err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes); 841 else 842 err = ChangeWindowAttributes(gWindow, kWindowNoAttributes, attr); 843 844 if (savewindowpos) 845 { 846 MoveWindow(gWindow, windowPos[kWindowScreen].h, windowPos[kWindowScreen].v, false); 847 848 if ((windowSize[kWindowScreen].width <= 0) || (windowSize[kWindowScreen].height <= 0)) 849 { 850 windowExtend = true; 851 windowSize[kWindowScreen].width = 512; 852 windowSize[kWindowScreen].height = kMacWindowHeight; 853 } 854 855 if (!lastoverscan && !windowExtend && drawoverscan) 856 { 857 windowExtend = true; 858 windowSize[kWindowScreen].height = (int) ((float) (windowSize[kWindowScreen].height + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT); 859 } 860 861 SizeWindow(gWindow, (short) windowSize[kWindowScreen].width, (short) windowSize[kWindowScreen].height, false); 862 } 863 else 864 { 865 if (drawoverscan) 866 windowExtend = true; 867 868 SizeWindow(gWindow, 512, (windowExtend ? kMacWindowHeight : (SNES_HEIGHT << 1)), false); 869 RepositionWindow(gWindow, NULL, kWindowCenterOnMainScreen); 870 } 871 872 windowZoomCount = 0; 873 874 GetWindowBounds(gWindow, kWindowContentRgn, &rct); 875 gWindowRect = CGRectMake((float) rct.left, (float) rct.top, (float) (rct.right - rct.left), (float) (rct.bottom - rct.top)); 876 877 ActivateWindow(gWindow, true); 878} 879 880void UpdateGameWindow (void) 881{ 882 OSStatus err; 883 HIViewRef ctl; 884 HIViewID cid = { 'Pict', 0 }; 885 886 if (!gWindow) 887 return; 888 889 HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl); 890 err = HIViewSetNeedsDisplay(ctl, true); 891} 892 893static void ResizeGameWindow (void) 894{ 895 Rect rct; 896 int ww, wh; 897 898 if (!gWindow) 899 return; 900 901 GetWindowBounds(gWindow, kWindowContentRgn, &rct); 902 903 wh = (windowExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * ((windowZoomCount >> 1) + 1); 904 905 if (windowZoomCount % 2) 906 ww = SNES_NTSC_OUT_WIDTH(SNES_WIDTH) * ((windowZoomCount >> 1) + 1) / 2; 907 else 908 ww = SNES_WIDTH * ((windowZoomCount >> 1) + 1); 909 910 rct.right = rct.left + ww; 911 rct.bottom = rct.top + wh; 912 913 SetWindowBounds(gWindow, kWindowContentRgn, &rct); 914 915 printf("Window Size: %d, %d\n", ww, wh); 916 917 windowZoomCount++; 918 if (windowZoomCount == 8) 919 windowZoomCount = 0; 920} 921 922void DeinitGameWindow (void) 923{ 924 OSStatus err; 925 926 if (!gWindow) 927 return; 928 929 SaveWindowPosition(gWindow, kWindowScreen); 930 lastoverscan = drawoverscan; 931 932 err = RemoveEventHandler(gameWUPaneEventRef); 933 DisposeEventHandlerUPP(gameWUPaneUPP); 934 935 err = RemoveEventHandler(gameWindowEventRef); 936 DisposeEventHandlerUPP(gameWindowUPP); 937 938 CFRelease(gWindow); 939 gWindow = NULL; 940} 941 942static pascal OSStatus GameWindowEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 943{ 944 OSStatus err, result = eventNotHandledErr; 945 HIRect rct; 946 Rect r; 947 UInt32 attr; 948 949 switch (GetEventClass(inEvent)) 950 { 951 case kEventClassWindow: 952 switch (GetEventKind(inEvent)) 953 { 954 case kEventWindowDeactivated: 955 if (running) 956 { 957 if (!(Settings.NetPlay && !Settings.NetPlayServer)) 958 { 959 if (inactiveMode == 3) 960 { 961 running = false; 962 while (s9xthreadrunning) 963 sleep(0); 964 QuitApplicationEventLoop(); 965 result = noErr; 966 } 967 else 968 if (inactiveMode == 2) 969 { 970 rejectinput = true; 971 result = noErr; 972 } 973 } 974 } 975 976 break; 977 978 case kEventWindowActivated: 979 if (running) 980 { 981 if (!(Settings.NetPlay && !Settings.NetPlayServer)) 982 { 983 ForceChangingKeyScript(); 984 985 if (inactiveMode == 2) 986 { 987 rejectinput = false; 988 result = noErr; 989 } 990 } 991 } 992 993 break; 994 995 case kEventWindowBoundsChanging: 996 windowResizeCount = 0x7FFFFFFF; 997 998 err = GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attr); 999 if ((err == noErr) && (attr & kWindowBoundsChangeSizeChanged)) 1000 { 1001 err = GetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &rct); 1002 if (err == noErr) 1003 { 1004 if (GetCurrentEventKeyModifiers() & shiftKey) 1005 { 1006 HIRect origRct; 1007 1008 err = GetEventParameter(inEvent, kEventParamOriginalBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &origRct); 1009 if (err == noErr) 1010 { 1011 rct.size.width = (float) (int) (origRct.size.width * rct.size.height / origRct.size.height); 1012 err = SetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, sizeof(HIRect), &rct); 1013 } 1014 } 1015 1016 gWindowRect = rct; 1017 } 1018 } 1019 1020 result = noErr; 1021 break; 1022 1023 case kEventWindowBoundsChanged: 1024 windowResizeCount = 3; 1025 result = noErr; 1026 break; 1027 1028 case kEventWindowZoom: 1029 ResizeGameWindow(); 1030 result = noErr; 1031 break; 1032 1033 case kEventWindowToolbarSwitchMode: 1034 windowExtend = !windowExtend; 1035 1036 GetWindowBounds(gWindow, kWindowContentRgn, &r); 1037 1038 if (windowExtend) 1039 r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT); 1040 else 1041 r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT / SNES_HEIGHT_EXTENDED); 1042 1043 SetWindowBounds(gWindow, kWindowContentRgn, &r); 1044 1045 result = noErr; 1046 break; 1047 } 1048 1049 break; 1050 } 1051 1052 return (result); 1053} 1054 1055static pascal OSStatus GameWindowUserPaneEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData) 1056{ 1057 OSStatus err, result = eventNotHandledErr; 1058 1059 switch (GetEventClass(inEvent)) 1060 { 1061 case kEventClassControl: 1062 switch (GetEventKind(inEvent)) 1063 { 1064 case kEventControlClick: 1065 if (running) 1066 { 1067 if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) 1068 { 1069 if (!(Settings.NetPlay && !Settings.NetPlayServer)) 1070 { 1071 if (!frzselecting) 1072 { 1073 running = false; 1074 while (s9xthreadrunning) 1075 sleep(0); 1076 QuitApplicationEventLoop(); 1077 result = noErr; 1078 } 1079 } 1080 } 1081 } 1082 else 1083 { 1084 UInt32 count; 1085 1086 err = GetEventParameter(inEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &count); 1087 if ((err == noErr) && (count == 2)) 1088 { 1089 SNES9X_Go(); 1090 QuitApplicationEventLoop(); 1091 result = noErr; 1092 } 1093 } 1094 1095 break; 1096 1097 case kEventControlDraw: 1098 CGContextRef ctx; 1099 HIViewRef view; 1100 HIRect bounds; 1101 1102 err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view); 1103 if (err == noErr) 1104 { 1105 err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx); 1106 if (err == noErr) 1107 { 1108 if (!running) 1109 { 1110 HIViewGetBounds(view, &bounds); 1111 CGContextTranslateCTM(ctx, 0, bounds.size.height); 1112 CGContextScaleCTM(ctx, 1.0f, -1.0f); 1113 DrawPauseScreen(ctx, bounds); 1114 } 1115 } 1116 } 1117 1118 result = noErr; 1119 break; 1120 } 1121 1122 break; 1123 } 1124 1125 return (result); 1126} 1127 1128static void InitRecentItems (void) 1129{ 1130 CFStringRef keyRef, pathRef; 1131 int count; 1132 char key[32]; 1133 1134 count = 0; 1135 1136 for (int i = 0; i <= kRecentMenu_MAX; i++) 1137 recentItem[i] = NULL; 1138 1139 for (int i = 0; i < kRecentMenu_MAX; i++) 1140 { 1141 sprintf(key, "RecentItem_%02d", i); 1142 keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); 1143 if (keyRef) 1144 { 1145 pathRef = (CFStringRef) CFPreferencesCopyAppValue(keyRef, kCFPreferencesCurrentApplication); 1146 if (pathRef) 1147 { 1148 recentItem[count] = pathRef; 1149 count++; 1150 } 1151 1152 CFRelease(keyRef); 1153 } 1154 } 1155} 1156 1157static void DeinitRecentItems (void) 1158{ 1159 CFStringRef keyRef; 1160 char key[32]; 1161 1162 for (int i = 0; i < kRecentMenu_MAX; i++) 1163 { 1164 sprintf(key, "RecentItem_%02d", i); 1165 keyRef = CFStringCreateWithCString(kCFAllocatorDefault, key, CFStringGetSystemEncoding()); 1166 if (keyRef) 1167 { 1168 if (recentItem[i]) 1169 { 1170 CFPreferencesSetAppValue(keyRef, recentItem[i], kCFPreferencesCurrentApplication); 1171 CFRelease(recentItem[i]); 1172 recentItem[i] = NULL; 1173 } 1174 else 1175 CFPreferencesSetAppValue(keyRef, NULL, kCFPreferencesCurrentApplication); 1176 1177 CFRelease(keyRef); 1178 } 1179 } 1180 1181 CFPreferencesAppSynchronize(kCFPreferencesCurrentApplication); 1182} 1183 1184static void ClearRecentItems (void) 1185{ 1186 for (int i = 0; i < kRecentMenu_MAX; i++) 1187 { 1188 if (recentItem[i]) 1189 { 1190 CFRelease(recentItem[i]); 1191 recentItem[i] = NULL; 1192 } 1193 } 1194} 1195 1196void AddRecentItem (FSRef *ref) 1197{ 1198 OSStatus err; 1199 char path[PATH_MAX + 1]; 1200 1201 err = FSRefMakePath(ref, (unsigned char *) path, PATH_MAX); 1202 if (err == noErr) 1203 { 1204 CFStringRef pathRef; 1205 1206 pathRef = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); 1207 if (pathRef) 1208 { 1209 int i, j; 1210 1211 for (i = 0; i < kRecentMenu_MAX; i++) 1212 if (recentItem[i] && (CFStringCompare(pathRef, recentItem[i], 0) == 0)) 1213 break; 1214 1215 if (i == kRecentMenu_MAX) 1216 { 1217 for (j = kRecentMenu_MAX - 1; j >= 0; j--) 1218 recentItem[j + 1] = recentItem[j]; 1219 1220 if (recentItem[kRecentMenu_MAX]) 1221 { 1222 CFRelease(recentItem[kRecentMenu_MAX]); 1223 recentItem[kRecentMenu_MAX] = NULL; 1224 } 1225 1226 recentItem[0] = pathRef; 1227 } 1228 else 1229 { 1230 CFRelease(pathRef); 1231 1232 if (i > 0) 1233 { 1234 CFStringRef temp; 1235 1236 temp = recentItem[i]; 1237 1238 for (j = i - 1; j >= 0; j--) 1239 recentItem[j + 1] = recentItem[j]; 1240 1241 recentItem[0] = temp; 1242 } 1243 } 1244 } 1245 } 1246} 1247 1248static void InitRecentMenu (void) 1249{ 1250 OSStatus err; 1251 1252 err = CreateNewMenu(mRecentItem, 0, &recentMenu); 1253 err = SetMenuItemHierarchicalMenu(GetMenuRef(mFile), iOpenRecent, recentMenu); 1254} 1255 1256static void DeinitRecentMenu (void) 1257{ 1258 CFRelease(recentMenu); 1259} 1260 1261void BuildRecentMenu (void) 1262{ 1263 OSStatus err; 1264 CFStringRef str; 1265 1266 err = DeleteMenuItems(recentMenu, 1, CountMenuItems(recentMenu)); 1267 1268 for (int i = 0; i < kRecentMenu_MAX; i++) 1269 { 1270 if (!recentItem[i]) 1271 break; 1272 1273 Boolean r; 1274 char path[PATH_MAX + 1]; 1275 1276 r = CFStringGetCString(recentItem[i], path, PATH_MAX, kCFStringEncodingUTF8); 1277 if (r) 1278 { 1279 CFStringRef nameRef; 1280 char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1]; 1281 1282 _splitpath(path, drive, dir, fname, ext); 1283 snprintf(path, PATH_MAX + 1, "%s%s", fname, ext); 1284 nameRef = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8); 1285 if (nameRef) 1286 { 1287 err = AppendMenuItemTextWithCFString(recentMenu, nameRef, 0, 'FRe0' + i, NULL); 1288 CFRelease(nameRef); 1289 } 1290 } 1291 } 1292 1293 err = AppendMenuItemTextWithCFString(recentMenu, NULL, kMenuItemAttrSeparator, 'FR__', NULL); 1294 1295 str = CFCopyLocalizedString(CFSTR("ClearMenu"), "ClearMenu"); 1296 if (str) 1297 { 1298 err = AppendMenuItemTextWithCFString(recentMenu, str, 0, 'FRcr', NULL); 1299 CFRelease(str); 1300 } 1301} 1302 1303void AdjustMenus (void) 1304{ 1305 OSStatus err; 1306 MenuRef menu; 1307 CFStringRef str; 1308 1309 if (running) 1310 { 1311 menu = GetMenuRef(mApple); 1312 DisableMenuItem(menu, iAbout); 1313 DisableMenuCommand(NULL, kHICommandPreferences); 1314 DisableMenuCommand(NULL, kHICommandQuit); 1315 1316 menu = GetMenuRef(mFile); 1317 DisableMenuItem(menu, iOpen); 1318 DisableMenuItem(menu, iOpenMulti); 1319 DisableMenuItem(menu, iOpenRecent); 1320 DisableMenuItem(menu, iRomInfo); 1321 1322 menu = GetMenuRef(mControl); 1323 DisableMenuItem(menu, iKeyboardLayout); 1324 DisableMenuItem(menu, iISpLayout); 1325 DisableMenuItem(menu, iAutoFire); 1326 DisableMenuItem(menu, iISpPreset); 1327 1328 menu = GetMenuRef(mEmulation); 1329 str = CFCopyLocalizedString(CFSTR("PauseMenu"), "pause"); 1330 err = SetMenuItemTextWithCFString(menu, iResume, str); 1331 CFRelease(str); 1332 DisableMenuItem(menu, iSoftReset); 1333 DisableMenuItem(menu, iReset); 1334 DisableMenuItem(menu, iDevice); 1335 1336 if (Settings.NetPlay) 1337 { 1338 if (Settings.NetPlayServer) 1339 EnableMenuItem(menu, iResume); 1340 else 1341 DisableMenuItem(menu, iResume); 1342 } 1343 else 1344 EnableMenuItem(menu, iResume); 1345 1346 menu = GetMenuRef(mCheat); 1347 DisableMenuItem(menu, iApplyCheats); 1348 DisableMenuItem(menu, iGameGenie); 1349 DisableMenuItem(menu, iCheatFinder); 1350 1351 menu = GetMenuRef(mOption); 1352 DisableMenuItem(menu, iFreeze); 1353 DisableMenuItem(menu, iDefrost); 1354 DisableMenuItem(menu, iFreezeTo); 1355 DisableMenuItem(menu, iDefrostFrom); 1356 DisableMenuItem(menu, iRecordMovie); 1357 DisableMenuItem(menu, iPlayMovie); 1358 DisableMenuItem(menu, iQTMovie); 1359 DisableMenuItem(menu, iSaveSPC); 1360 DisableMenuItem(menu, iSaveSRAM); 1361 DisableMenuItem(menu, iMusicBox); 1362 if (ciFilterEnable) 1363 EnableMenuItem(menu, iCIFilter); 1364 else 1365 DisableMenuItem(menu, iCIFilter); 1366 1367 menu = GetMenuRef(mNetplay); 1368 DisableMenuItem(menu, iServer); 1369 DisableMenuItem(menu, iClient); 1370 } 1371 else 1372 { 1373 menu = GetMenuRef(mApple); 1374 EnableMenuItem(menu, iAbout); 1375 EnableMenuCommand(NULL, kHICommandPreferences); 1376 EnableMenuCommand(NULL, kHICommandQuit); 1377 1378 menu = GetMenuRef(mFile); 1379 EnableMenuItem(menu, iOpen); 1380 EnableMenuItem(menu, iOpenMulti); 1381 EnableMenuItem(menu, iOpenRecent); 1382 if (cartOpen) 1383 EnableMenuItem(menu, iRomInfo); 1384 else 1385 DisableMenuItem(menu, iRomInfo); 1386 1387 menu = GetMenuRef(mControl); 1388 EnableMenuItem(menu, iKeyboardLayout); 1389 EnableMenuItem(menu, iAutoFire); 1390 if (hidExist) 1391 { 1392 EnableMenuItem(menu, iISpLayout); 1393 EnableMenuItem(menu, iISpPreset); 1394 } 1395 else 1396 { 1397 DisableMenuItem(menu, iISpLayout); 1398 DisableMenuItem(menu, iISpPreset); 1399 } 1400 1401 menu = GetMenuRef(mEmulation); 1402 str = CFCopyLocalizedString(CFSTR("RunMenu"), "run"); 1403 err = SetMenuItemTextWithCFString(menu, iResume, str); 1404 CFRelease(str); 1405 EnableMenuItem(menu, iDevice); 1406 if (cartOpen) 1407 { 1408 EnableMenuItem(menu, iResume); 1409 EnableMenuItem(menu, iSoftReset); 1410 EnableMenuItem(menu, iReset); 1411 } 1412 else 1413 { 1414 DisableMenuItem(menu, iResume); 1415 DisableMenuItem(menu, iSoftReset); 1416 DisableMenuItem(menu, iReset); 1417 } 1418 1419 menu = GetMenuRef(mCheat); 1420 if (cartOpen) 1421 { 1422 EnableMenuItem(menu, iApplyCheats); 1423 EnableMenuItem(menu, iGameGenie); 1424 EnableMenuItem(menu, iCheatFinder); 1425 } 1426 else 1427 { 1428 DisableMenuItem(menu, iApplyCheats); 1429 DisableMenuItem(menu, iGameGenie); 1430 DisableMenuItem(menu, iCheatFinder); 1431 } 1432 1433 menu = GetMenuRef(mOption); 1434 DisableMenuItem(menu, iCIFilter); 1435 if (cartOpen) 1436 { 1437 EnableMenuItem(menu, iFreeze); 1438 EnableMenuItem(menu, iDefrost); 1439 EnableMenuItem(menu, iFreezeTo); 1440 EnableMenuItem(menu, iDefrostFrom); 1441 EnableMenuItem(menu, iRecordMovie); 1442 EnableMenuItem(menu, iPlayMovie); 1443 EnableMenuItem(menu, iQTMovie); 1444 EnableMenuItem(menu, iSaveSPC); 1445 EnableMenuItem(menu, iSaveSRAM); 1446 EnableMenuItem(menu, iMusicBox); 1447 } 1448 else 1449 { 1450 DisableMenuItem(menu, iFreeze); 1451 DisableMenuItem(menu, iDefrost); 1452 DisableMenuItem(menu, iFreezeTo); 1453 DisableMenuItem(menu, iDefrostFrom); 1454 DisableMenuItem(menu, iRecordMovie); 1455 DisableMenuItem(menu, iPlayMovie); 1456 DisableMenuItem(menu, iQTMovie); 1457 DisableMenuItem(menu, iSaveSPC); 1458 DisableMenuItem(menu, iSaveSRAM); 1459 DisableMenuItem(menu, iMusicBox); 1460 } 1461 1462 menu = GetMenuRef(mNetplay); 1463 EnableMenuItem(menu, iClient); 1464 if (cartOpen) 1465 EnableMenuItem(menu, iServer); 1466 else 1467 DisableMenuItem(menu, iServer); 1468 } 1469 1470 DrawMenuBar(); 1471} 1472 1473void UpdateMenuCommandStatus (Boolean closeMenu) 1474{ 1475 if (closeMenu) 1476 EnableMenuItem(GetMenuRef(mFile), iClose); 1477 else 1478 DisableMenuItem(GetMenuRef(mFile), iClose); 1479} 1480 1481static OSStatus HandleMenuChoice (UInt32 command, Boolean *done) 1482{ 1483 OSStatus err, result = noErr; 1484 MenuRef mh; 1485 int item; 1486 bool8 isok = true; 1487 1488 if ((command & 0xFFFFFF00) == 'FRe\0') 1489 { 1490 Boolean r; 1491 int index; 1492 char path[PATH_MAX + 1]; 1493 1494 index = (int) (command & 0x000000FF) - (int) '0'; 1495 r = CFStringGetCString(recentItem[index], path, PATH_MAX, kCFStringEncodingUTF8); 1496 if (r) 1497 { 1498 FSRef ref; 1499 1500 err = FSPathMakeRef((unsigned char *) path, &ref, NULL); 1501 if (err == noErr) 1502 { 1503 if (SNES9X_OpenCart(&ref)) 1504 { 1505 SNES9X_Go(); 1506 *done = true; 1507 } 1508 else 1509 AdjustMenus(); 1510 } 1511 } 1512 } 1513 else 1514 { 1515 switch (command) 1516 { 1517 case 'abou': // About SNES9X 1518 StartCarbonModalDialog(); 1519 AboutDialog(); 1520 FinishCarbonModalDialog(); 1521 1522 break; 1523 1524 case 'pref': // Preferences... 1525 StartCarbonModalDialog(); 1526 ConfigurePreferences(); 1527 FinishCarbonModalDialog(); 1528 1529 break; 1530 1531 case 'EXTR': // Extra Options... 1532 StartCarbonModalDialog(); 1533 ConfigureExtraOptions(); 1534 FinishCarbonModalDialog(); 1535 1536 break; 1537 1538 case 'quit': // Quit SNES9X 1539 SNES9X_Quit(); 1540 *done = true; 1541 1542 break; 1543 1544 case 'open': // Open ROM Image... 1545 if (SNES9X_OpenCart(NULL)) 1546 { 1547 SNES9X_Go(); 1548 *done = true; 1549 } 1550 else 1551 AdjustMenus(); 1552 1553 break; 1554 1555 case 'Mult': // Open Multiple ROM Images... 1556 if (SNES9X_OpenMultiCart()) 1557 { 1558 SNES9X_Go(); 1559 *done = true; 1560 } 1561 else 1562 AdjustMenus(); 1563 1564 break; 1565 1566 case 'FRcr': // Clear Menu 1567 ClearRecentItems(); 1568 BuildRecentMenu(); 1569 1570 break; 1571 1572 case 'Finf': // ROM Information 1573 StartCarbonModalDialog(); 1574 RomInfoDialog(); 1575 FinishCarbonModalDialog(); 1576 1577 break; 1578 1579 case 'Ckey': // Configure Keyboard... 1580 StartCarbonModalDialog(); 1581 ConfigureKeyboard(); 1582 FinishCarbonModalDialog(); 1583 1584 break; 1585 1586 case 'Cpad': // Configure Controllers... 1587 StartCarbonModalDialog(); 1588 ConfigureHID(); 1589 FinishCarbonModalDialog(); 1590 1591 break; 1592 1593 case 'Caut': // Automatic Fire... 1594 StartCarbonModalDialog(); 1595 ConfigureAutofire(); 1596 FinishCarbonModalDialog(); 1597 1598 break; 1599 1600 case 'Hapl': // Apply Cheat Entries 1601 mh = GetMenuRef(mCheat); 1602 applycheat = !applycheat; 1603 CheckMenuItem(mh, iApplyCheats, applycheat); 1604 Settings.ApplyCheats = applycheat; 1605 1606 if (!Settings.ApplyCheats) 1607 S9xCheatsDisable(); 1608 else 1609 S9xCheatsEnable(); 1610 1611 break; 1612 1613 case 'Hent': // Cheat Entry... 1614 StartCarbonModalDialog(); 1615 ConfigureCheat(); 1616 FinishCarbonModalDialog(); 1617 1618 break; 1619 1620 case 'Hfnd': // Cheat Finder... 1621 StartCarbonModalDialog(); 1622 CheatFinder(); 1623 FinishCarbonModalDialog(); 1624 1625 break; 1626 1627 case 'Erun': // Run 1628 SNES9X_Go(); 1629 *done = true; 1630 1631 break; 1632 1633 case 'Esrs': // Software Reset 1634 SNES9X_SoftReset(); 1635 SNES9X_Go(); 1636 *done = true; 1637 1638 break; 1639 1640 case 'Erst': // Hardware Reset 1641 SNES9X_Reset(); 1642 SNES9X_Go(); 1643 *done = true; 1644 1645 break; 1646 1647 case 'Ofrz': // Freeze State 1648 isok = SNES9X_Freeze(); 1649 *done = true; 1650 1651 break; 1652 1653 case 'Odfr': // Defrost state 1654 isok = SNES9X_Defrost(); 1655 *done = true; 1656 1657 break; 1658 1659 case 'Ofrd': // Freeze State to... 1660 StartCarbonModalDialog(); 1661 isok = SNES9X_FreezeTo(); 1662 FinishCarbonModalDialog(); 1663 1664 break; 1665 1666 case 'Odfd': // Defrost State From... 1667 StartCarbonModalDialog(); 1668 isok = SNES9X_DefrostFrom(); 1669 if (gWindow) 1670 ActivateWindow(gWindow, true); 1671 FinishCarbonModalDialog(); 1672 *done = true; 1673 1674 break; 1675 1676 case 'MVrc': // Record Movie... 1677 StartCarbonModalDialog(); 1678 isok = SNES9X_RecordMovie(); 1679 if (gWindow) 1680 ActivateWindow(gWindow, true); 1681 FinishCarbonModalDialog(); 1682 *done = true; 1683 1684 break; 1685 1686 case 'MVpl': // Play Movie... 1687 StartCarbonModalDialog(); 1688 isok = SNES9X_PlayMovie(); 1689 if (isok && (macPlayFlag & 0x2)) 1690 { 1691 running = false; 1692 isok = SNES9X_QTMovieRecord(); 1693 running = true; 1694 } 1695 1696 if (gWindow) 1697 ActivateWindow(gWindow, true); 1698 FinishCarbonModalDialog(); 1699 *done = true; 1700 1701 break; 1702 1703 case 'QTmv': // Record QuickTime Movie... 1704 StartCarbonModalDialog(); 1705 isok = SNES9X_QTMovieRecord(); 1706 if (gWindow) 1707 ActivateWindow(gWindow, true); 1708 FinishCarbonModalDialog(); 1709 *done = true; 1710 1711 break; 1712 1713 case 'Ospc': // Save SPC File at Next Note-on 1714 S9xDumpSPCSnapshot(); 1715 1716 break; 1717 1718 case 'Osrm': // Save SRAM Now 1719 SNES9X_SaveSRAM(); 1720 1721 break; 1722 1723 case 'Ombx': // Music Box 1724 StartCarbonModalDialog(); 1725 MusicBoxDialog(); 1726 FinishCarbonModalDialog(); 1727 1728 break; 1729 1730 case 'Nser': // Server... 1731 bool8 sr; 1732 1733 Settings.NetPlay = false; 1734 Settings.NetPlayServer = false; 1735 1736 NPServerInit(); 1737 1738 if (!NPServerStartServer(NP_PORT)) 1739 { 1740 NPServerStopServer(); 1741 break; 1742 } 1743 1744 StartCarbonModalDialog(); 1745 sr = NPServerDialog(); 1746 FinishCarbonModalDialog(); 1747 1748 if (sr) 1749 { 1750 SNES9X_Reset(); 1751 SNES9X_Go(); 1752 Settings.NetPlay = true; 1753 Settings.NetPlayServer = true; 1754 1755 *done = true; 1756 } 1757 else 1758 NPServerStopServer(); 1759 1760 break; 1761 1762 case 'Ncli': // Client... 1763 bool8 cr; 1764 1765 Settings.NetPlay = false; 1766 Settings.NetPlayServer = false; 1767 1768 NPClientInit(); 1769 1770 StartCarbonModalDialog(); 1771 cr = NPClientDialog(); 1772 FinishCarbonModalDialog(); 1773 1774 if (cr) 1775 { 1776 SNES9X_Go(); 1777 Settings.NetPlay = true; 1778 Settings.NetPlayServer = false; 1779 1780 *done = true; 1781 } 1782 else 1783 AdjustMenus(); 1784 1785 break; 1786 1787 case 'CPr1': // Controller Preset 1788 case 'CPr2': 1789 case 'CPr3': 1790 case 'CPr4': 1791 case 'CPr5': 1792 item = (int) (command & 0x000000FF) - (int) '0'; 1793 err = GetMenuItemHierarchicalMenu(GetMenuRef(mControl), iISpPreset, &mh); 1794 CheckMenuItem(mh, padSetting, false); 1795 padSetting = item; 1796 CheckMenuItem(mh, padSetting, true); 1797 ClearPadSetting(); 1798 LoadControllerSettings(); 1799 1800 break; 1801 1802 case 'EIp1': // Input Device 1803 case 'EIp2': 1804 case 'EIp3': 1805 case 'EIp4': 1806 case 'EIp5': 1807 case 'EIp6': 1808 case 'EIp7': 1809 case 'EIp8': 1810 item = (int) (command & 0x000000FF) - (int) '0'; 1811 err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &mh); 1812 CheckMenuItem(mh, deviceSetting, false); 1813 deviceSetting = item; 1814 deviceSettingMaster = deviceSetting; 1815 CheckMenuItem(mh, deviceSetting, true); 1816 ChangeInputDevice(); 1817 1818 break; 1819 1820 default: 1821 result = eventNotHandledErr; 1822 break; 1823 } 1824 } 1825 1826 return (result); 1827} 1828 1829void ChangeInputDevice (void) 1830{ 1831 switch (deviceSetting) 1832 { 1833 case iPad: 1834 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1835 S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); 1836 macControllerOption = SNES_JOYPAD; 1837 break; 1838 1839 case iMouse: 1840 S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0); 1841 S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0); 1842 macControllerOption = SNES_MOUSE; 1843 break; 1844 1845 case iMouse2: 1846 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1847 S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0); 1848 macControllerOption = SNES_MOUSE_SWAPPED; 1849 break; 1850 1851 case iSuperScope: 1852 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1853 S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0); 1854 macControllerOption = SNES_SUPERSCOPE; 1855 break; 1856 1857 case iMultiPlayer5: 1858 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1859 S9xSetController(1, CTL_MP5, 1, 2, 3, 4); 1860 macControllerOption = SNES_MULTIPLAYER5; 1861 break; 1862 1863 case iMultiPlayer5_2: 1864 S9xSetController(0, CTL_MP5, 0, 1, 2, 3); 1865 S9xSetController(1, CTL_MP5, 4, 5, 6, 7); 1866 macControllerOption = SNES_MULTIPLAYER5_2; 1867 break; 1868 1869 case iJustifier1: 1870 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1871 S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0); 1872 macControllerOption = SNES_JUSTIFIER; 1873 break; 1874 1875 case iJustifier2: 1876 S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0); 1877 S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0); 1878 macControllerOption = SNES_JUSTIFIER_2; 1879 break; 1880 } 1881} 1882 1883void ApplyNSRTHeaderControllers (void) 1884{ 1885 OSStatus err; 1886 MenuRef menu; 1887 1888 err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &menu); 1889 if (err) 1890 return; 1891 1892 for (int i = 1; i <= CountMenuItems(menu); i++) 1893 { 1894 CheckMenuItem(menu, i, false); 1895 SetItemStyle(menu, i, normal); 1896 } 1897 1898 deviceSetting = deviceSettingMaster; 1899 1900 uint32 valid = 0; 1901 1902 if (!strncmp((const char *) Memory.NSRTHeader + 24, "NSRT", 4)) 1903 { 1904 switch (Memory.NSRTHeader[29]) 1905 { 1906 case 0x00: // Everything goes 1907 deviceSetting = iPad; 1908 valid = (1 << iPad); 1909 break; 1910 1911 case 0x10: // Mouse in Port 0 1912 deviceSetting = iMouse; 1913 valid = (1 << iMouse); 1914 break; 1915 1916 case 0x01: // Mouse in Port 1 1917 deviceSetting = iMouse2; 1918 valid = (1 << iMouse2); 1919 break; 1920 1921 case 0x03: // Super Scope in Port 1 1922 deviceSetting = iSuperScope; 1923 valid = (1 << iSuperScope); 1924 break; 1925 1926 case 0x06: // Multitap in Port 1 1927 deviceSetting = iMultiPlayer5; 1928 valid = (1 << iPad) | (1 << iMultiPlayer5); 1929 break; 1930 1931 case 0x66: // Multitap in Ports 0 and 1 1932 deviceSetting = iMultiPlayer5_2; 1933 valid = (1 << iPad) | (1 << iMultiPlayer5) | (1 << iMultiPlayer5_2); 1934 break; 1935 1936 case 0x08: // Multitap in Port 1, Mouse in new Port 1 1937 deviceSetting = iMouse2; 1938 valid = (1 << iPad) | (1 << iMouse2) | (1 << iMultiPlayer5); 1939 break; 1940 1941 case 0x04: // Pad or Super Scope in Port 1 1942 deviceSetting = iSuperScope; 1943 valid = (1 << iPad) | (1 << iSuperScope); 1944 break; 1945 1946 case 0x05: // Justifier - Must ask user... 1947 deviceSetting = iJustifier1; 1948 valid = (1 << iJustifier1) | (1 << iJustifier2); 1949 break; 1950 1951 case 0x20: // Pad or Mouse in Port 0 1952 deviceSetting = iMouse; 1953 valid = (1 << iPad) | (1 << iMouse); 1954 break; 1955 1956 case 0x22: // Pad or Mouse in Port 0 & 1 1957 deviceSetting = iMouse; 1958 valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2); 1959 break; 1960 1961 case 0x24: // Pad or Mouse in Port 0, Pad or Super Scope in Port 1 1962 deviceSetting = iSuperScope; 1963 valid = (1 << iPad) | (1 << iMouse) | (1 << iSuperScope); 1964 break; 1965 1966 case 0x27: // Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1 1967 deviceSetting = iSuperScope; 1968 valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2) | (1 << iSuperScope); 1969 break; 1970 1971 case 0x99: // Lasabirdie 1972 break; 1973 1974 case 0x0A: // Barcode Battler 1975 break; 1976 1977 default: 1978 break; 1979 } 1980 } 1981 1982 CheckMenuItem(menu, deviceSetting, true); 1983 1984 for (int i = 1; i <= CountMenuItems(menu); i++) 1985 { 1986 if (valid & (1 << i)) 1987 SetItemStyle(menu, i, underline); 1988 } 1989 1990 ChangeInputDevice(); 1991} 1992 1993int PromptFreezeDefrost (Boolean freezing) 1994{ 1995 OSStatus err; 1996 CGContextRef ctx; 1997 CGColorSpaceRef color; 1998 CGDataProviderRef prov; 1999 CGImageRef image; 2000 CGRect rct; 2001 CGPoint pt; 2002 CFURLRef url; 2003 FSCatalogInfo info; 2004 FSRef ref; 2005 KeyMap keys; 2006 UInt64 newestDate, currentDate; 2007 UInt32 startTime; 2008 float x, y, textw; 2009 int result, newestIndex, current_selection, oldInactiveMode; 2010 char dateC[256]; 2011 uint8 *back, *draw; 2012 2013 const UInt32 repeatDelay = 10; 2014 const int w = SNES_WIDTH << 1, h = kMacWindowHeight; 2015 const char letters[] = "123456789ABC", *filename; 2016 const uint8 keyCheck[] = { kmEscKey, km1Key, km2Key, km3Key, km4Key, km5Key, km6Key, km7Key, km8Key, km9Key, kmAKey, kmBKey, kmCKey }; 2017 2018 if (!directDisplay) 2019 { 2020 S9xInitDisplay(NULL, NULL); 2021 SNES9X_Go(); 2022 } 2023 2024 frzselecting = true; 2025 oldInactiveMode = inactiveMode; 2026 if (inactiveMode == 3) 2027 inactiveMode = 2; 2028 2029 S9xSetSoundMute(true); 2030 2031 back = (uint8 *) malloc(w * h * 2); 2032 draw = (uint8 *) malloc(w * h * 2); 2033 if (!back || !draw) 2034 QuitWithFatalError(0, "os 04"); 2035 2036 color = CGColorSpaceCreateDeviceRGB(); 2037 if (!color) 2038 QuitWithFatalError(0, "os 05"); 2039 2040 ctx = CGBitmapContextCreate(back, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0)); 2041 if (!ctx) 2042 QuitWithFatalError(0, "os 06"); 2043 2044 rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h); 2045 CGContextClearRect(ctx, rct); 2046 2047 image = NULL; 2048 2049 if (freezing) 2050 url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_freeze"), CFSTR("png"), NULL); 2051 else 2052 url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_defrost"), CFSTR("png"), NULL); 2053 if (url) 2054 { 2055 prov = CGDataProviderCreateWithURL(url); 2056 if (prov) 2057 { 2058 image = CGImageCreateWithPNGDataProvider(prov, NULL, true, kCGRenderingIntentDefault); 2059 CGDataProviderRelease(prov); 2060 } 2061 2062 CFRelease(url); 2063 } 2064 2065 if (image) 2066 { 2067 rct = CGRectMake(0.0f, (float) h - 118.0f, 512.0f, 118.0f); 2068 CGContextDrawImage(ctx, rct, image); 2069 CGImageRelease(image); 2070 } 2071 2072 newestDate = 0; 2073 newestIndex = -1; 2074 2075 CGContextSetLineJoin(ctx, kCGLineJoinRound); 2076 2077 rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); 2078 2079 for (int count = 0; count < 12; count++) 2080 { 2081 filename = S9xGetFreezeFilename(count); 2082 err = FSPathMakeRef((unsigned char *) filename, &ref, NULL); 2083 if (err == noErr) 2084 { 2085 err = FSGetCatalogInfo(&ref, kFSCatInfoContentMod, &info, NULL, NULL, NULL); 2086 currentDate = (((UInt64) info.contentModDate.highSeconds << 48) | ((UInt64) info.contentModDate.lowSeconds << 16) | (UInt64) info.contentModDate.fraction); 2087 2088 if (currentDate > newestDate) 2089 { 2090 newestIndex = count; 2091 newestDate = currentDate; 2092 } 2093 2094 DrawThumbnailResource(&ref, ctx, rct); 2095 2096 CGContextSetShouldAntialias(ctx, false); 2097 CGContextSetLineWidth(ctx, 1.0f); 2098 2099 CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); 2100 x = rct.origin.x + 127.0f; 2101 y = rct.origin.y + 119.0f; 2102 CGContextBeginPath(ctx); 2103 CGContextMoveToPoint(ctx, x, y); 2104 CGContextAddLineToPoint(ctx, x, y - 119.0f); 2105 CGContextAddLineToPoint(ctx, x - 127.0f, y - 119.0f); 2106 CGContextStrokePath(ctx); 2107 2108 CGContextSetShouldAntialias(ctx, true); 2109 CGContextSetLineWidth(ctx, 3.0f); 2110 2111 CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman); 2112 x = rct.origin.x + 5.0f; 2113 y = rct.origin.y + 107.0f; 2114 CGContextSetTextDrawingMode(ctx, kCGTextStroke); 2115 CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f); 2116 CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); 2117 CGContextSetTextDrawingMode(ctx, kCGTextFill); 2118 CGContextSetRGBFillColor(ctx, 1.0f, 0.7f, 0.7f, 1.0f); 2119 CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); 2120 2121 if (showtimeinfrz) 2122 { 2123 CFAbsoluteTime at; 2124 CFDateFormatterRef format; 2125 CFLocaleRef locale; 2126 CFStringRef datstr; 2127 Boolean r; 2128 2129 err = UCConvertUTCDateTimeToCFAbsoluteTime(&(info.contentModDate), &at); 2130 locale = CFLocaleCopyCurrent(); 2131 format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle); 2132 datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at); 2133 r = CFStringGetCString(datstr, dateC, sizeof(dateC), CFStringGetSystemEncoding()); 2134 CFRelease(datstr); 2135 CFRelease(format); 2136 CFRelease(locale); 2137 2138 CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman); 2139 x = rct.origin.x + 20.0f; 2140 y = rct.origin.y + 107.0f; 2141 CGContextSetTextDrawingMode(ctx, kCGTextInvisible); 2142 CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); 2143 pt = CGContextGetTextPosition(ctx); 2144 textw = pt.x - x; 2145 x = rct.origin.x + 122.0f - textw; 2146 CGContextSetTextDrawingMode(ctx, kCGTextStroke); 2147 CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f); 2148 CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); 2149 CGContextSetTextDrawingMode(ctx, kCGTextFill); 2150 CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f); 2151 CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC)); 2152 } 2153 } 2154 else 2155 { 2156 CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman); 2157 x = rct.origin.x + 5.0f; 2158 y = rct.origin.y + 107.0f; 2159 CGContextSetTextDrawingMode(ctx, kCGTextFill); 2160 CGContextSetRGBFillColor(ctx, 0.7f, 0.7f, 0.7f, 1.0f); 2161 CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1); 2162 } 2163 2164 if ((count % 4) == 3) 2165 rct = CGRectOffset(rct, -128.0f * 3.0f, -120.0f); 2166 else 2167 rct = CGRectOffset(rct, 128.0f, 0.0f); 2168 } 2169 2170 if (newestIndex < 0) 2171 newestIndex = 0; 2172 2173 CGContextRelease(ctx); 2174 2175 image = NULL; 2176 2177 prov = CGDataProviderCreateWithData(NULL, back, w * h * 2, NULL); 2178 if (prov) 2179 { 2180 image = CGImageCreate(w, h, 5, 16, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0), prov, NULL, 0, kCGRenderingIntentDefault); 2181 CGDataProviderRelease(prov); 2182 } 2183 2184 if (!image) 2185 QuitWithFatalError(0, "os 07"); 2186 2187 ctx = CGBitmapContextCreate(draw, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0)); 2188 if (!ctx) 2189 QuitWithFatalError(0, "os 08"); 2190 2191 CGContextSetShouldAntialias(ctx, false); 2192 2193 UpdateFreezeDefrostScreen(newestIndex, image, draw, ctx); 2194 2195 CocoaPlayFreezeDefrostSound(); 2196 2197 result = -2; 2198 current_selection = newestIndex; 2199 2200 do 2201 { 2202 if (!rejectinput) 2203 { 2204 GetKeys(keys); 2205 2206 for (int count = 0; count <= 12; count++) 2207 { 2208 while (KeyIsPressed(keys, keyCheck[count])) 2209 { 2210 result = count - 1; 2211 GetKeys(keys); 2212 } 2213 } 2214 2215 while (KeyIsPressed(keys, keyCode[k1PRight])) 2216 { 2217 startTime = TickCount(); 2218 current_selection += 1; 2219 if (current_selection > 11) 2220 current_selection -= 12; 2221 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2222 while (KeyIsPressed(keys, keyCode[k1PRight]) && (TickCount() < (startTime + repeatDelay))) 2223 GetKeys(keys); 2224 } 2225 2226 while (KeyIsPressed(keys, keyCode[k1PLeft])) 2227 { 2228 startTime = TickCount(); 2229 current_selection -= 1; 2230 if (current_selection < 0) 2231 current_selection += 12; 2232 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2233 while (KeyIsPressed(keys, keyCode[k1PLeft]) && (TickCount() < (startTime + repeatDelay))) 2234 GetKeys(keys); 2235 } 2236 2237 while (KeyIsPressed(keys, keyCode[k1PDown])) 2238 { 2239 startTime = TickCount(); 2240 current_selection += 4; 2241 if (current_selection > 11) 2242 current_selection -= 12; 2243 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2244 while (KeyIsPressed(keys, keyCode[k1PDown]) && (TickCount() < (startTime + repeatDelay))) 2245 GetKeys(keys); 2246 } 2247 2248 while (KeyIsPressed(keys, keyCode[k1PUp])) 2249 { 2250 startTime = TickCount(); 2251 current_selection -= 4; 2252 if (current_selection < 0) 2253 current_selection += 12; 2254 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2255 while (KeyIsPressed(keys, keyCode[k1PUp]) && (TickCount() < (startTime + repeatDelay))) 2256 GetKeys(keys); 2257 } 2258 2259 while (KeyIsPressed(keys, keyCode[k1PA] ) || 2260 KeyIsPressed(keys, keyCode[k2PA] ) || 2261 KeyIsPressed(keys, keyCode[k1PB] ) || 2262 KeyIsPressed(keys, keyCode[k2PB] ) || 2263 KeyIsPressed(keys, keyCode[k1PX] ) || 2264 KeyIsPressed(keys, keyCode[k2PX] ) || 2265 KeyIsPressed(keys, keyCode[k1PY] ) || 2266 KeyIsPressed(keys, keyCode[k2PY] ) || 2267 KeyIsPressed(keys, keyCode[k1PStart] ) || 2268 KeyIsPressed(keys, keyCode[k2PStart] ) || 2269 KeyIsPressed(keys, keyCode[k1PSelect]) || 2270 KeyIsPressed(keys, keyCode[k2PSelect])) 2271 { 2272 GetKeys(keys); 2273 result = current_selection; 2274 } 2275 2276 uint32 pad1, pad2; 2277 2278 while (ISpKeyIsPressed(kISpEsc ) || 2279 ISpKeyIsPressed(kISp1PStart) || 2280 ISpKeyIsPressed(kISp2PStart)) 2281 result = -1; 2282 2283 pad1 = pad2 = 0; 2284 JoypadScanDirection(0, &pad1); 2285 JoypadScanDirection(1, &pad2); 2286 while ((pad1 & 0x0100) || (pad2 & 0x0100)) // Rt 2287 { 2288 startTime = TickCount(); 2289 current_selection += 1; 2290 if (current_selection > 11) 2291 current_selection -= 12; 2292 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2293 do 2294 { 2295 pad1 = pad2 = 0; 2296 JoypadScanDirection(0, &pad1); 2297 JoypadScanDirection(1, &pad2); 2298 } while (((pad1 & 0x0100) || (pad2 & 0x0100)) && (TickCount() < (startTime + repeatDelay))); 2299 } 2300 2301 pad1 = pad2 = 0; 2302 JoypadScanDirection(0, &pad1); 2303 JoypadScanDirection(1, &pad2); 2304 while ((pad1 & 0x0200) || (pad2 & 0x0200)) // Lf 2305 { 2306 startTime = TickCount(); 2307 current_selection -= 1; 2308 if (current_selection < 0) 2309 current_selection += 12; 2310 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2311 do 2312 { 2313 pad1 = pad2 = 0; 2314 JoypadScanDirection(0, &pad1); 2315 JoypadScanDirection(1, &pad2); 2316 } while (((pad1 & 0x0200) || (pad2 & 0x0200)) && (TickCount() < (startTime + repeatDelay))); 2317 } 2318 2319 pad1 = pad2 = 0; 2320 JoypadScanDirection(0, &pad1); 2321 JoypadScanDirection(1, &pad2); 2322 while ((pad1 & 0x0800) || (pad2 & 0x0800)) // Up 2323 { 2324 startTime = TickCount(); 2325 current_selection -= 4; 2326 if (current_selection < 0) 2327 current_selection += 12; 2328 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2329 do 2330 { 2331 pad1 = pad2 = 0; 2332 JoypadScanDirection(0, &pad1); 2333 JoypadScanDirection(1, &pad2); 2334 } while (((pad1 & 0x0800) || (pad2 & 0x0800)) && (TickCount() < (startTime + repeatDelay))); 2335 } 2336 2337 pad1 = pad2 = 0; 2338 JoypadScanDirection(0, &pad1); 2339 JoypadScanDirection(1, &pad2); 2340 while ((pad1 & 0x0400) || (pad2 & 0x0400)) // Dn 2341 { 2342 startTime = TickCount(); 2343 current_selection += 4; 2344 if (current_selection > 11) 2345 current_selection -= 12; 2346 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2347 do 2348 { 2349 pad1 = pad2 = 0; 2350 JoypadScanDirection(0, &pad1); 2351 JoypadScanDirection(1, &pad2); 2352 } while (((pad1 & 0x0400) || (pad2 & 0x0400)) && (TickCount() < (startTime + repeatDelay))); 2353 } 2354 2355 while (ISpKeyIsPressed(kISp1PA) || 2356 ISpKeyIsPressed(kISp2PA) || 2357 ISpKeyIsPressed(kISp1PB) || 2358 ISpKeyIsPressed(kISp2PB) || 2359 ISpKeyIsPressed(kISp1PX) || 2360 ISpKeyIsPressed(kISp2PX) || 2361 ISpKeyIsPressed(kISp1PY) || 2362 ISpKeyIsPressed(kISp2PY)) 2363 result = current_selection; 2364 } 2365 2366 usleep(30000); 2367 2368 windowResizeCount = 2; 2369 UpdateFreezeDefrostScreen(current_selection, image, draw, ctx); 2370 } while (result == -2); 2371 2372 CocoaPlayFreezeDefrostSound(); 2373 2374 CGContextRelease(ctx); 2375 CGImageRelease(image); 2376 CGColorSpaceRelease(color); 2377 free(draw); 2378 free(back); 2379 2380 S9xSetSoundMute(false); 2381 2382 inactiveMode = oldInactiveMode; 2383 frzselecting = false; 2384 2385 windowResizeCount = 2; 2386 2387 return (result); 2388} 2389 2390static void UpdateFreezeDefrostScreen (int newIndex, CGImageRef image, uint8 *draw, CGContextRef ctx) 2391{ 2392 if (newIndex >= 0 && newIndex < 12) 2393 { 2394 CGRect rct; 2395 const int w = SNES_WIDTH << 1, h = kMacWindowHeight; 2396 2397 CGContextSetLineWidth(ctx, 1.0f); 2398 2399 rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h); 2400 CGContextDrawImage(ctx, rct, image); 2401 2402 rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f); 2403 rct = CGRectOffset(rct, (float) (128 * (newIndex % 4)), (float) (-120 * (newIndex / 4))); 2404 rct.size.width -= 1.0f; 2405 rct.size.height -= 1.0f; 2406 2407 CGContextSetRGBStrokeColor(ctx, 1.0f, 1.0f, 0.0f, 1.0f); 2408 CGContextStrokeRect(ctx, rct); 2409 rct = CGRectInset(rct, 1.0f, 1.0f); 2410 CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f); 2411 CGContextStrokeRect(ctx, rct); 2412 } 2413 2414 DrawFreezeDefrostScreen(draw); 2415} 2416 2417static void ProcessInput (void) 2418{ 2419 KeyMap myKeys; 2420 bool8 isok, fnbtn, altbtn, tcbtn; 2421 static bool8 toggleff = false, lastTimeTT = false, lastTimeFn = false, ffUp = false, ffDown = false, ffUpSp = false, ffDownSp = false; 2422 2423 if (rejectinput) 2424 return; 2425 2426 if (ISpKeyIsPressed(kISpEsc)) 2427 { 2428 if (s9xthreadrunning) 2429 { 2430 if (!eventQueued) 2431 { 2432 PostQueueToSubEventLoop(); 2433 eventQueued = true; 2434 } 2435 } 2436 else 2437 running = false; 2438 2439 return; 2440 } 2441 2442 if (ISpKeyIsPressed(kISpFreeze)) 2443 { 2444 MacStopSound(); 2445 while (ISpKeyIsPressed(kISpFreeze)); 2446 2447 isok = SNES9X_Freeze(); 2448 ClearGFXScreen(); 2449 return; 2450 } 2451 2452 if (ISpKeyIsPressed(kISpDefrost)) 2453 { 2454 MacStopSound(); 2455 while (ISpKeyIsPressed(kISpDefrost)); 2456 2457 isok = SNES9X_Defrost(); 2458 ClearGFXScreen(); 2459 return; 2460 } 2461 2462 if (ISpKeyIsPressed(kISpScreenshot)) 2463 { 2464 Settings.TakeScreenshot = true; 2465 while (ISpKeyIsPressed(kISpScreenshot)); 2466 } 2467 2468 if (ISpKeyIsPressed(kISpSPC)) 2469 { 2470 S9xDumpSPCSnapshot(); 2471 while (ISpKeyIsPressed(kISpSPC)); 2472 } 2473 2474 if (ISpKeyIsPressed(kISpFFUp)) 2475 { 2476 if (!ffUpSp) 2477 { 2478 ChangeTurboRate(+1); 2479 ffUpSp = true; 2480 } 2481 } 2482 else 2483 ffUpSp = false; 2484 2485 if (ISpKeyIsPressed(kISpFFDown)) 2486 { 2487 if (!ffDownSp) 2488 { 2489 ChangeTurboRate(-1); 2490 ffDownSp = true; 2491 } 2492 } 2493 else 2494 ffDownSp = false; 2495 2496 controlPad[0] = controlPad[1] = 0; 2497 2498 JoypadScanDirection(0, &(controlPad[0])); 2499 if (ISpKeyIsPressed(kISp1PR )) controlPad[0] |= 0x0010; 2500 if (ISpKeyIsPressed(kISp1PL )) controlPad[0] |= 0x0020; 2501 if (ISpKeyIsPressed(kISp1PX )) controlPad[0] |= 0x0040; 2502 if (ISpKeyIsPressed(kISp1PA )) controlPad[0] |= 0x0080; 2503 if (ISpKeyIsPressed(kISp1PStart )) controlPad[0] |= 0x1000; 2504 if (ISpKeyIsPressed(kISp1PSelect)) controlPad[0] |= 0x2000; 2505 if (ISpKeyIsPressed(kISp1PY )) controlPad[0] |= 0x4000; 2506 if (ISpKeyIsPressed(kISp1PB )) controlPad[0] |= 0x8000; 2507 2508 JoypadScanDirection(1, &(controlPad[1])); 2509 if (ISpKeyIsPressed(kISp2PR )) controlPad[1] |= 0x0010; 2510 if (ISpKeyIsPressed(kISp2PL )) controlPad[1] |= 0x0020; 2511 if (ISpKeyIsPressed(kISp2PX )) controlPad[1] |= 0x0040; 2512 if (ISpKeyIsPressed(kISp2PA )) controlPad[1] |= 0x0080; 2513 if (ISpKeyIsPressed(kISp2PStart )) controlPad[1] |= 0x1000; 2514 if (ISpKeyIsPressed(kISp2PSelect)) controlPad[1] |= 0x2000; 2515 if (ISpKeyIsPressed(kISp2PY )) controlPad[1] |= 0x4000; 2516 if (ISpKeyIsPressed(kISp2PB )) controlPad[1] |= 0x8000; 2517 2518 if (((macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) && Settings.MultiPlayer5Master) 2519 { 2520 controlPad[2] = controlPad[3] = controlPad[4] = 0; 2521 2522 JoypadScanDirection(2, &(controlPad[2])); 2523 if (ISpKeyIsPressed(kISp3PR )) controlPad[2] |= 0x0010; 2524 if (ISpKeyIsPressed(kISp3PL )) controlPad[2] |= 0x0020; 2525 if (ISpKeyIsPressed(kISp3PX )) controlPad[2] |= 0x0040; 2526 if (ISpKeyIsPressed(kISp3PA )) controlPad[2] |= 0x0080; 2527 if (ISpKeyIsPressed(kISp3PStart )) controlPad[2] |= 0x1000; 2528 if (ISpKeyIsPressed(kISp3PSelect)) controlPad[2] |= 0x2000; 2529 if (ISpKeyIsPressed(kISp3PY )) controlPad[2] |= 0x4000; 2530 if (ISpKeyIsPressed(kISp3PB )) controlPad[2] |= 0x8000; 2531 2532 JoypadScanDirection(3, &(controlPad[3])); 2533 if (ISpKeyIsPressed(kISp4PR )) controlPad[3] |= 0x0010; 2534 if (ISpKeyIsPressed(kISp4PL )) controlPad[3] |= 0x0020; 2535 if (ISpKeyIsPressed(kISp4PX )) controlPad[3] |= 0x0040; 2536 if (ISpKeyIsPressed(kISp4PA )) controlPad[3] |= 0x0080; 2537 if (ISpKeyIsPressed(kISp4PStart )) controlPad[3] |= 0x1000; 2538 if (ISpKeyIsPressed(kISp4PSelect)) controlPad[3] |= 0x2000; 2539 if (ISpKeyIsPressed(kISp4PY )) controlPad[3] |= 0x4000; 2540 if (ISpKeyIsPressed(kISp4PB )) controlPad[3] |= 0x8000; 2541 2542 JoypadScanDirection(4, &(controlPad[4])); 2543 if (ISpKeyIsPressed(kISp5PR )) controlPad[4] |= 0x0010; 2544 if (ISpKeyIsPressed(kISp5PL )) controlPad[4] |= 0x0020; 2545 if (ISpKeyIsPressed(kISp5PX )) controlPad[4] |= 0x0040; 2546 if (ISpKeyIsPressed(kISp5PA )) controlPad[4] |= 0x0080; 2547 if (ISpKeyIsPressed(kISp5PStart )) controlPad[4] |= 0x1000; 2548 if (ISpKeyIsPressed(kISp5PSelect)) controlPad[4] |= 0x2000; 2549 if (ISpKeyIsPressed(kISp5PY )) controlPad[4] |= 0x4000; 2550 if (ISpKeyIsPressed(kISp5PB )) controlPad[4] |= 0x8000; 2551 2552 ControlPadFlagsToS9xReportButtons(2, controlPad[2]); 2553 ControlPadFlagsToS9xReportButtons(3, controlPad[3]); 2554 ControlPadFlagsToS9xReportButtons(4, controlPad[4]); 2555 2556 if (macControllerOption == SNES_MULTIPLAYER5_2) 2557 { 2558 controlPad[5] = controlPad[6] = controlPad[7] = 0; 2559 2560 JoypadScanDirection(5, &(controlPad[5])); 2561 if (ISpKeyIsPressed(kISp6PR )) controlPad[5] |= 0x0010; 2562 if (ISpKeyIsPressed(kISp6PL )) controlPad[5] |= 0x0020; 2563 if (ISpKeyIsPressed(kISp6PX )) controlPad[5] |= 0x0040; 2564 if (ISpKeyIsPressed(kISp6PA )) controlPad[5] |= 0x0080; 2565 if (ISpKeyIsPressed(kISp6PStart )) controlPad[5] |= 0x1000; 2566 if (ISpKeyIsPressed(kISp6PSelect)) controlPad[5] |= 0x2000; 2567 if (ISpKeyIsPressed(kISp6PY )) controlPad[5] |= 0x4000; 2568 if (ISpKeyIsPressed(kISp6PB )) controlPad[5] |= 0x8000; 2569 2570 JoypadScanDirection(6, &(controlPad[6])); 2571 if (ISpKeyIsPressed(kISp7PR )) controlPad[6] |= 0x0010; 2572 if (ISpKeyIsPressed(kISp7PL )) controlPad[6] |= 0x0020; 2573 if (ISpKeyIsPressed(kISp7PX )) controlPad[6] |= 0x0040; 2574 if (ISpKeyIsPressed(kISp7PA )) controlPad[6] |= 0x0080; 2575 if (ISpKeyIsPressed(kISp7PStart )) controlPad[6] |= 0x1000; 2576 if (ISpKeyIsPressed(kISp7PSelect)) controlPad[6] |= 0x2000; 2577 if (ISpKeyIsPressed(kISp7PY )) controlPad[6] |= 0x4000; 2578 if (ISpKeyIsPressed(kISp7PB )) controlPad[6] |= 0x8000; 2579 2580 JoypadScanDirection(7, &(controlPad[7])); 2581 if (ISpKeyIsPressed(kISp8PR )) controlPad[7] |= 0x0010; 2582 if (ISpKeyIsPressed(kISp8PL )) controlPad[7] |= 0x0020; 2583 if (ISpKeyIsPressed(kISp8PX )) controlPad[7] |= 0x0040; 2584 if (ISpKeyIsPressed(kISp8PA )) controlPad[7] |= 0x0080; 2585 if (ISpKeyIsPressed(kISp8PStart )) controlPad[7] |= 0x1000; 2586 if (ISpKeyIsPressed(kISp8PSelect)) controlPad[7] |= 0x2000; 2587 if (ISpKeyIsPressed(kISp8PY )) controlPad[7] |= 0x4000; 2588 if (ISpKeyIsPressed(kISp8PB )) controlPad[7] |= 0x8000; 2589 2590 ControlPadFlagsToS9xReportButtons(5, controlPad[5]); 2591 ControlPadFlagsToS9xReportButtons(6, controlPad[6]); 2592 ControlPadFlagsToS9xReportButtons(7, controlPad[7]); 2593 } 2594 } 2595 2596 GetKeys(myKeys); 2597 2598 fnbtn = (KeyIsPressed(myKeys, keyCode[kKeyFunction]) || ISpKeyIsPressed(kISpFunction)); 2599 altbtn = (KeyIsPressed(myKeys, keyCode[kKeyAlt] ) || ISpKeyIsPressed(kISpAlt) ); 2600 2601 if (fnbtn) 2602 { 2603 if (!lastTimeFn) 2604 { 2605 for (unsigned int i = 0; i < kCommandListSize; i++) 2606 btncmd[i].held = false; 2607 } 2608 2609 lastTimeFn = true; 2610 lastTimeTT = false; 2611 ffUp = ffDown = false; 2612 2613 for (unsigned int i = 0; i < kCommandListSize; i++) 2614 { 2615 if (KeyIsPressed(myKeys, btncmd[i].keycode)) 2616 { 2617 if (!(btncmd[i].held)) 2618 { 2619 btncmd[i].held = true; 2620 2621 if (strncmp(btncmd[i].command, "_mac", 4) == 0) 2622 { 2623 static char msg[64]; 2624 2625 switch (btncmd[i].command[4] - '0') 2626 { 2627 case 1: 2628 Settings.DisplayPressedKeys = !Settings.DisplayPressedKeys; 2629 break; 2630 2631 case 2: 2632 if (S9xMovieActive()) 2633 Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame; 2634 break; 2635 2636 case 3: 2637 if (macFrameAdvanceRate < 5000000) 2638 macFrameAdvanceRate += 100000; 2639 sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000); 2640 S9xSetInfoString(msg); 2641 break; 2642 2643 case 4: 2644 if (macFrameAdvanceRate > 500000) 2645 macFrameAdvanceRate -= 100000; 2646 sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000); 2647 S9xSetInfoString(msg); 2648 break; 2649 2650 case 5: 2651 pauseEmulation = !pauseEmulation; 2652 break; 2653 2654 case 6: 2655 frameAdvance = true; 2656 break; 2657 } 2658 } 2659 else 2660 { 2661 s9xcommand_t s9xcmd; 2662 2663 s9xcmd = S9xGetCommandT(btncmd[i].command); 2664 S9xApplyCommand(s9xcmd, 1, 0); 2665 } 2666 } 2667 } 2668 else 2669 btncmd[i].held = false; 2670 } 2671 } 2672 else 2673 { 2674 lastTimeFn = false; 2675 2676 if (KeyIsPressed(myKeys, keyCode[kKeyEsc])) 2677 { 2678 if (s9xthreadrunning) 2679 { 2680 if (!eventQueued) 2681 { 2682 PostQueueToSubEventLoop(); 2683 eventQueued = true; 2684 } 2685 } 2686 else 2687 running = false; 2688 2689 return; 2690 } 2691 2692 if (KeyIsPressed(myKeys, keyCode[kKeyFreeze])) 2693 { 2694 MacStopSound(); 2695 while (KeyIsPressed(myKeys, keyCode[kKeyFreeze])) 2696 GetKeys(myKeys); 2697 2698 isok = SNES9X_Freeze(); 2699 ClearGFXScreen(); 2700 return; 2701 } 2702 2703 if (KeyIsPressed(myKeys, keyCode[kKeyDefrost])) 2704 { 2705 MacStopSound(); 2706 while (KeyIsPressed(myKeys, keyCode[kKeyDefrost])) 2707 GetKeys(myKeys); 2708 2709 isok = SNES9X_Defrost(); 2710 ClearGFXScreen(); 2711 return; 2712 } 2713 2714 if (KeyIsPressed(myKeys, keyCode[kKeyScreenshot])) 2715 { 2716 Settings.TakeScreenshot = true; 2717 while (KeyIsPressed(myKeys, keyCode[kKeyScreenshot])) 2718 GetKeys(myKeys); 2719 } 2720 2721 if (KeyIsPressed(myKeys, keyCode[kKeySPC])) 2722 { 2723 S9xDumpSPCSnapshot(); 2724 while (KeyIsPressed(myKeys, keyCode[kKeySPC])) 2725 GetKeys(myKeys); 2726 } 2727 2728 if (KeyIsPressed(myKeys, keyCode[kKeyFFUp])) 2729 { 2730 if (!ffUp) 2731 { 2732 ChangeTurboRate(+1); 2733 ffUp = true; 2734 } 2735 } 2736 else 2737 ffUp = false; 2738 2739 if (KeyIsPressed(myKeys, keyCode[kKeyFFDown])) 2740 { 2741 if (!ffDown) 2742 { 2743 ChangeTurboRate(-1); 2744 ffDown = true; 2745 } 2746 } 2747 else 2748 ffDown = false; 2749 2750 if (KeyIsPressed(myKeys, keyCode[k1PR] )) controlPad[0] |= 0x0010; 2751 if (KeyIsPressed(myKeys, keyCode[k1PL] )) controlPad[0] |= 0x0020; 2752 if (KeyIsPressed(myKeys, keyCode[k1PX] )) controlPad[0] |= 0x0040; 2753 if (KeyIsPressed(myKeys, keyCode[k1PA] )) controlPad[0] |= 0x0080; 2754 if (KeyIsPressed(myKeys, keyCode[k1PRight] )) controlPad[0] |= 0x0100; 2755 if (KeyIsPressed(myKeys, keyCode[k1PLeft] )) controlPad[0] |= 0x0200; 2756 if (KeyIsPressed(myKeys, keyCode[k1PDown] )) controlPad[0] |= 0x0400; 2757 if (KeyIsPressed(myKeys, keyCode[k1PUp] )) controlPad[0] |= 0x0800; 2758 if (KeyIsPressed(myKeys, keyCode[k1PStart] )) controlPad[0] |= 0x1000; 2759 if (KeyIsPressed(myKeys, keyCode[k1PSelect])) controlPad[0] |= 0x2000; 2760 if (KeyIsPressed(myKeys, keyCode[k1PY] )) controlPad[0] |= 0x4000; 2761 if (KeyIsPressed(myKeys, keyCode[k1PB] )) controlPad[0] |= 0x8000; 2762 2763 if (KeyIsPressed(myKeys, keyCode[k2PR] )) controlPad[1] |= 0x0010; 2764 if (KeyIsPressed(myKeys, keyCode[k2PL] )) controlPad[1] |= 0x0020; 2765 if (KeyIsPressed(myKeys, keyCode[k2PX] )) controlPad[1] |= 0x0040; 2766 if (KeyIsPressed(myKeys, keyCode[k2PA] )) controlPad[1] |= 0x0080; 2767 if (KeyIsPressed(myKeys, keyCode[k2PRight] )) controlPad[1] |= 0x0100; 2768 if (KeyIsPressed(myKeys, keyCode[k2PLeft] )) controlPad[1] |= 0x0200; 2769 if (KeyIsPressed(myKeys, keyCode[k2PDown] )) controlPad[1] |= 0x0400; 2770 if (KeyIsPressed(myKeys, keyCode[k2PUp] )) controlPad[1] |= 0x0800; 2771 if (KeyIsPressed(myKeys, keyCode[k2PStart] )) controlPad[1] |= 0x1000; 2772 if (KeyIsPressed(myKeys, keyCode[k2PSelect])) controlPad[1] |= 0x2000; 2773 if (KeyIsPressed(myKeys, keyCode[k2PY] )) controlPad[1] |= 0x4000; 2774 if (KeyIsPressed(myKeys, keyCode[k2PB] )) controlPad[1] |= 0x8000; 2775 2776 if (altbtn) 2777 { 2778 if (!lastTimeTT) 2779 changeAuto[0] = changeAuto[1] = 0; 2780 2781 for (int i = 0; i < 2; i++) 2782 { 2783 for (int j = 0; j < 12; j++) 2784 { 2785 uint16 mask = 0x0010 << j; 2786 2787 if (controlPad[i] & mask & autofireRec[i].toggleMask) 2788 { 2789 controlPad[i] &= ~mask; 2790 2791 if (!(changeAuto[i] & mask)) 2792 { 2793 changeAuto[i] |= mask; 2794 ChangeAutofireSettings(i, j); 2795 } 2796 } 2797 else 2798 changeAuto[i] &= ~mask; 2799 } 2800 } 2801 2802 lastTimeTT = true; 2803 } 2804 else 2805 lastTimeTT = false; 2806 } 2807 2808 if (enabletoggle) 2809 { 2810 if ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn) 2811 { 2812 if (!toggleff) 2813 { 2814 toggleff = true; 2815 Settings.TurboMode = !Settings.TurboMode; 2816 S9xSetInfoString(Settings.TurboMode ? "Turbo mode on" : "Turbo mode off"); 2817 if (!Settings.TurboMode) 2818 S9xClearSamples(); 2819 } 2820 } 2821 else 2822 toggleff = false; 2823 } 2824 else 2825 { 2826 bool8 old = Settings.TurboMode; 2827 Settings.TurboMode = ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn) ? true : false; 2828 if (!Settings.TurboMode && old) 2829 S9xClearSamples(); 2830 } 2831 2832 for (int i = 0; i < 2; i++) 2833 controlPad[i] ^= autofireRec[i].invertMask; 2834 2835 if (autofire) 2836 { 2837 long long currentTime; 2838 uint16 changeMask; 2839 2840 Microseconds((UnsignedWide *) ¤tTime); 2841 tcbtn = (KeyIsPressed(myKeys, keyCode[kKeyTC]) || ISpKeyIsPressed(kISpTC)); 2842 2843 for (int i = 0; i < 2; i++) 2844 { 2845 changeMask = (lastTimeTT ? (~changeAuto[i]) : 0xFFFF); 2846 2847 for (int j = 0; j < 12; j++) 2848 { 2849 uint16 mask = (0x0010 << j) & changeMask; 2850 2851 if (autofireRec[i].tcMask & mask) 2852 { 2853 if (!tcbtn) 2854 continue; 2855 } 2856 2857 if (autofireRec[i].buttonMask & mask) 2858 { 2859 if (controlPad[i] & mask) 2860 { 2861 if (currentTime > autofireRec[i].nextTime[j]) 2862 { 2863 if (Settings.TurboMode) 2864 autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0 / macFastForwardRate); 2865 else 2866 autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0); 2867 } 2868 else 2869 controlPad[i] &= ~mask; 2870 } 2871 } 2872 } 2873 } 2874 } 2875 2876 ControlPadFlagsToS9xReportButtons(0, controlPad[0]); 2877 ControlPadFlagsToS9xReportButtons(1, controlPad[1]); 2878 2879 if (macControllerOption == SNES_JUSTIFIER_2) 2880 ControlPadFlagsToS9xPseudoPointer(controlPad[1]); 2881} 2882 2883static void ChangeAutofireSettings (int player, int btn) 2884{ 2885 static char msg[64]; 2886 uint16 mask, m; 2887 2888 mask = 0x0010 << btn; 2889 autofireRec[player].buttonMask ^= mask; 2890 autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask); 2891 2892 m = autofireRec[player].buttonMask; 2893 if (m) 2894 snprintf(msg, sizeof(msg), "Autofire %d:%s%s%s%s%s%s%s%s%s%s%s%s%s", player + 1, 2895 (m & 0xC0F0 ? " " : ""), 2896 (m & 0x0080 ? "A" : ""), 2897 (m & 0x8000 ? "B" : ""), 2898 (m & 0x0040 ? "X" : ""), 2899 (m & 0x4000 ? "Y" : ""), 2900 (m & 0x0020 ? "L" : ""), 2901 (m & 0x0010 ? "R" : ""), 2902 (m & 0x0800 ? " Up" : ""), 2903 (m & 0x0400 ? " Dn" : ""), 2904 (m & 0x0200 ? " Lf" : ""), 2905 (m & 0x0100 ? " Rt" : ""), 2906 (m & 0x1000 ? " St" : ""), 2907 (m & 0x2000 ? " Se" : "")); 2908 else 2909 snprintf(msg, sizeof(msg), "Autofire %d: Off", player + 1); 2910 2911 S9xSetInfoString(msg); 2912} 2913 2914static void ChangeTurboRate (int d) 2915{ 2916 static char msg[64]; 2917 2918 macFastForwardRate += d; 2919 if (macFastForwardRate < 1) 2920 macFastForwardRate = 1; 2921 else 2922 if (macFastForwardRate > 15) 2923 macFastForwardRate = 15; 2924 2925 snprintf(msg, sizeof(msg), "Turbo Rate: %d", macFastForwardRate); 2926 S9xSetInfoString(msg); 2927} 2928 2929void GetGameScreenPointer (int16 *x, int16 *y, bool fullmouse) 2930{ 2931 int ph; 2932 2933 ph = !drawoverscan ? ((IPPU.RenderedScreenHeight > 256) ? IPPU.RenderedScreenHeight : (IPPU.RenderedScreenHeight << 1)) : (SNES_HEIGHT_EXTENDED << 1); 2934 2935 if (fullscreen) 2936 { 2937 if (glstretch) 2938 { 2939 float fpw = (float) glScreenH / (float) ph * 512.0f; 2940 2941 scopeViewInfo.width = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0); 2942 scopeViewInfo.height = glScreenH; 2943 scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - scopeViewInfo.width) >> 1); 2944 scopeViewInfo.globalTop = (int) glScreenBounds.origin.y; 2945 } 2946 else 2947 { 2948 scopeViewInfo.width = 512; 2949 scopeViewInfo.height = ph; 2950 scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - 512) >> 1); 2951 scopeViewInfo.globalTop = (int) glScreenBounds.origin.y + ((glScreenH - ph ) >> 1); 2952 } 2953 } 2954 else 2955 { 2956 Rect rct; 2957 2958 GetWindowBounds(gWindow, kWindowContentRgn, &rct); 2959 2960 int ww = rct.right - rct.left, 2961 wh = rct.bottom - rct.top; 2962 2963 scopeViewInfo.width = ww; 2964 scopeViewInfo.globalLeft = rct.left; 2965 2966 if (windowExtend) 2967 { 2968 scopeViewInfo.height = ph * wh / kMacWindowHeight; 2969 scopeViewInfo.globalTop = rct.top + ((kMacWindowHeight - ph) >> 1) * wh / kMacWindowHeight; 2970 } 2971 else 2972 { 2973 scopeViewInfo.height = wh; 2974 scopeViewInfo.globalTop = rct.top; 2975 } 2976 } 2977 2978 if (!fullmouse) 2979 { 2980 Point pos; 2981 2982 GetGlobalMouse(&pos); 2983 2984 *x = (int16) (((float) (pos.h - scopeViewInfo.globalLeft)) / ((float) scopeViewInfo.width ) * (float) IPPU.RenderedScreenWidth); 2985 *y = (int16) (((float) (pos.v - scopeViewInfo.globalTop )) / ((float) scopeViewInfo.height) * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED)); 2986 } 2987 else 2988 { 2989 *x = (int16) (unlimitedCursor.x / (float) scopeViewInfo.width * (float) IPPU.RenderedScreenWidth); 2990 *y = (int16) (unlimitedCursor.y / (float) scopeViewInfo.height * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED)); 2991 } 2992} 2993 2994static void Initialize (void) 2995{ 2996 OSStatus err; 2997 IBNibRef menuNibRef; 2998 MenuRef menu; 2999 SInt32 qtVersion; 3000 3001 printf("\nSnes9x for Mac OS X %s (%s), ", VERSION, MAC_VERSION); 3002#ifdef __BIG_ENDIAN__ 3003 printf("PowerPC\n\n"); 3004#else 3005 printf("Intel\n\n"); 3006#endif 3007 3008 err = Gestalt(gestaltSystemVersion, &systemVersion); 3009 err = Gestalt(gestaltQuickTimeVersion, &qtVersion); 3010 3011 if ((systemVersion < 0x1039) || (qtVersion < 0x07008000)) 3012 { 3013 AppearanceAlert(kAlertStopAlert, kS9xMacAlertRequiredSystem, kS9xMacAlertRequiredSystemHint); 3014 QuitWithFatalError(0, "os 09"); 3015 } 3016 3017 printf("OS: %x QuickTime: %x\n\n", (unsigned) systemVersion, (unsigned) qtVersion); 3018 3019#ifdef ZLIB 3020 printf("zlib header version: %s\n\n", ZLIB_VERSION); 3021#endif 3022 3023 NSApplicationLoad(); 3024 3025 bzero(&Settings, sizeof(Settings)); 3026 Settings.MouseMaster = true; 3027 Settings.SuperScopeMaster = true; 3028 Settings.JustifierMaster = true; 3029 Settings.MultiPlayer5Master = true; 3030 Settings.FrameTimePAL = 20000; 3031 Settings.FrameTimeNTSC = 16667; 3032 Settings.SixteenBitSound = true; 3033 Settings.Stereo = true; 3034 Settings.SoundPlaybackRate = 32000; 3035 Settings.SoundInputRate = 31950; 3036 Settings.SupportHiRes = true; 3037 Settings.Transparency = true; 3038 Settings.AutoDisplayMessages = true; 3039 Settings.InitialInfoStringTimeout = 120; 3040 Settings.HDMATimingHack = 100; 3041 Settings.BlockInvalidVRAMAccessMaster = true; 3042 Settings.StopEmulation = true; 3043 Settings.WrongMovieStateProtection = true; 3044 Settings.DumpStreamsMaxFrames = -1; 3045 Settings.StretchScreenshots = 1; 3046 Settings.SnapshotScreenshots = true; 3047 Settings.OpenGLEnable = true; 3048 Settings.SuperFXClockMultiplier = 100; 3049 Settings.InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN; 3050 Settings.MaxSpriteTilesPerLine = 34; 3051 Settings.OneClockCycle = 6; 3052 Settings.OneSlowClockCycle = 8; 3053 Settings.TwoClockCycles = 12; 3054 3055 for (int a = 0; a < kWindowCount; a++) 3056 { 3057 windowPos[a].h = 40; 3058 windowPos[a].v = 80; 3059 windowSize[a].width = -1.0f; 3060 windowSize[a].height = -1.0f; 3061 } 3062 3063 extraOptions.benchmark = false; 3064 extraOptions.glForceNoTextureRectangle = false; 3065 extraOptions.glUseClientStrageApple = true; 3066 extraOptions.glUseTexturePriority = false; 3067 extraOptions.glStorageHint = 2; 3068 3069 npServerIP[0] = 0; 3070 npName[0] = 0; 3071 3072 saveFolderPath = NULL; 3073 3074 CreateIconImages(); 3075 3076 InitAppleEvents(); 3077 InitKeyboard(); 3078 InitAutofire(); 3079 InitCheatFinder(); 3080 3081 LoadPrefs(); 3082 3083 InitGraphics(); 3084 InitMacSound(); 3085 SetUpHID(); 3086 3087 RegisterHelpBook(); 3088 3089 if (systemVersion < 0x1040) 3090 ciFilterEnable = false; 3091 3092 err = CreateNibReference(kMacS9XCFString, &menuNibRef); 3093 err = SetMenuBarFromNib(menuNibRef, CFSTR("MenuBar")); 3094 DisposeNibReference(menuNibRef); 3095 3096 EnableMenuCommand(NULL, kHICommandPreferences); 3097 3098 DisableMenuItem(GetMenuRef(mEdit), 0); 3099 3100 CheckMenuItem(GetMenuRef(mCheat), iApplyCheats, applycheat); 3101 Settings.ApplyCheats = applycheat; 3102 3103 err = GetMenuItemHierarchicalMenu(GetMenuRef(mControl), iISpPreset, &menu); 3104 CheckMenuItem(menu, padSetting, true); 3105 3106 err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &menu); 3107 CheckMenuItem(menu, deviceSetting, true); 3108 deviceSettingMaster = deviceSetting; 3109 3110 DisableMenuItem(GetMenuRef(mOption), iCIFilter); 3111 3112 InitRecentItems(); 3113 InitRecentMenu(); 3114 BuildRecentMenu(); 3115 3116 InitMultiCart(); 3117 3118 DrawMenuBar(); 3119 3120 autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask) ? true : false; 3121 for (int a = 0; a < MAC_MAX_PLAYERS; a++) 3122 for (int b = 0; b < 12; b++) 3123 autofireRec[a].nextTime[b] = 0; 3124 3125 S9xMovieInit(); 3126 3127 S9xUnmapAllControls(); 3128 S9xSetupDefaultKeymap(); 3129 ChangeInputDevice(); 3130 3131 err = EnterMovies(); 3132 3133 if (!Memory.Init() || !S9xInitAPU() || !S9xGraphicsInit()) 3134 QuitWithFatalError(err, "os 01"); 3135 3136 frzselecting = false; 3137 3138 S9xSetControllerCrosshair(X_MOUSE1, 0, NULL, NULL); 3139 S9xSetControllerCrosshair(X_MOUSE2, 0, NULL, NULL); 3140 3141 if (systemVersion >= 0x1040) 3142 { 3143 InitCoreImage(); 3144 InitCoreImageFilter(); 3145 } 3146} 3147 3148static void Deinitialize (void) 3149{ 3150 if (systemVersion >= 0x1040) 3151 { 3152 DeinitCoreImageFilter(); 3153 DeinitCoreImage(); 3154 } 3155 3156 deviceSetting = deviceSettingMaster; 3157 3158 ExitMovies(); 3159 3160 DeinitMultiCart(); 3161 DeinitRecentMenu(); 3162 DeinitRecentItems(); 3163 SavePrefs(); 3164 ReleaseHID(); 3165 DeinitCheatFinder(); 3166 DeinitGraphics(); 3167 DeinitKeyboard(); 3168 DeinitMacSound(); 3169 DeinitAppleEvents(); 3170 ReleaseIconImages(); 3171 3172 S9xGraphicsDeinit(); 3173 S9xDeinitAPU(); 3174 Memory.Deinit(); 3175} 3176 3177static void InitAutofire (void) 3178{ 3179 autofire = false; 3180 3181 for (int i = 0; i < 2; i++) 3182 { 3183 for (int j = 0; j < 12; j++) 3184 autofireRec[i].nextTime[j] = 0; 3185 3186 autofireRec[i].buttonMask = 0x0000; 3187 autofireRec[i].toggleMask = 0xFFF0; 3188 autofireRec[i].tcMask = 0x0000; 3189 autofireRec[i].invertMask = 0x0000; 3190 autofireRec[i].frequency = 10; 3191 } 3192} 3193 3194static void ForceChangingKeyScript (void) 3195{ 3196 if (systemVersion >= 0x1050) 3197 { 3198 OSStatus err; 3199 TISInputSourceRef tis; 3200 3201 tis = TISCopyCurrentASCIICapableKeyboardInputSource(); 3202 err = TISSelectInputSource(tis); 3203 CFRelease(tis); 3204 } 3205#ifdef MAC_TIGER_PANTHER_SUPPORT 3206 else 3207 { 3208 long script; 3209 3210 script = GetScriptManagerVariable(smKeyScript); 3211 if (script == smJapanese) 3212 KeyScript(smRoman | smKeyForceKeyScriptMask); 3213 } 3214#endif 3215} 3216 3217void S9xSyncSpeed (void) 3218{ 3219 long long currentFrame, adjustment; 3220 3221 if (directDisplay) 3222 { 3223 if (extraOptions.benchmark) 3224 IPPU.RenderThisFrame = true; 3225 else 3226 { 3227 if (Settings.SoundSync) 3228 { 3229 while (!S9xSyncSound()) 3230 usleep(0); 3231 } 3232 3233 if (!macQTRecord) 3234 { 3235 if (macFrameSkip < 0) // auto skip 3236 { 3237 skipFrames--; 3238 3239 if (skipFrames <= 0) 3240 { 3241 adjustment = (Settings.TurboMode ? (macFrameAdvanceRate / macFastForwardRate) : macFrameAdvanceRate) / Memory.ROMFramesPerSecond; 3242 Microseconds((UnsignedWide *) ¤tFrame); 3243 3244 skipFrames = (int32) ((currentFrame - lastFrame) / adjustment); 3245 lastFrame += frameCount * adjustment; 3246 3247 if (skipFrames < 1) 3248 skipFrames = 1; 3249 else 3250 if (skipFrames > 7) 3251 { 3252 skipFrames = 7; 3253 Microseconds((UnsignedWide *) &lastFrame); 3254 } 3255 3256 frameCount = skipFrames; 3257 3258 if (lastFrame > currentFrame) 3259 usleep((useconds_t) (lastFrame - currentFrame)); 3260 3261 IPPU.RenderThisFrame = true; 3262 } 3263 else 3264 IPPU.RenderThisFrame = false; 3265 } 3266 else // constant 3267 { 3268 skipFrames--; 3269 3270 if (skipFrames <= 0) 3271 { 3272 adjustment = macFrameAdvanceRate * macFrameSkip / Memory.ROMFramesPerSecond; 3273 Microseconds((UnsignedWide *) ¤tFrame); 3274 3275 if (currentFrame - lastFrame < adjustment) 3276 { 3277 usleep((useconds_t) (adjustment + lastFrame - currentFrame)); 3278 Microseconds((UnsignedWide *) ¤tFrame); 3279 } 3280 3281 lastFrame = currentFrame; 3282 skipFrames = macFrameSkip; 3283 if (Settings.TurboMode) 3284 skipFrames *= macFastForwardRate; 3285 3286 IPPU.RenderThisFrame = true; 3287 } 3288 else 3289 IPPU.RenderThisFrame = false; 3290 } 3291 } 3292 else 3293 { 3294 MacQTRecordFrame(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight); 3295 3296 adjustment = macFrameAdvanceRate / Memory.ROMFramesPerSecond; 3297 Microseconds((UnsignedWide *) ¤tFrame); 3298 3299 if (currentFrame - lastFrame < adjustment) 3300 usleep((useconds_t) (adjustment + lastFrame - currentFrame)); 3301 3302 lastFrame = currentFrame; 3303 3304 IPPU.RenderThisFrame = true; 3305 } 3306 } 3307 } 3308 else 3309 IPPU.RenderThisFrame = false; 3310} 3311 3312void S9xAutoSaveSRAM (void) 3313{ 3314 SNES9X_SaveSRAM(); 3315} 3316 3317void S9xMessage (int type, int number, const char *message) 3318{ 3319 static char mes[256]; 3320 3321 if (!onscreeninfo) 3322 { 3323 printf("%s\n", message); 3324 3325 if ((type == S9X_INFO) && (number == S9X_ROM_INFO)) 3326 if (strstr(message, "checksum ok") == NULL) 3327 AppearanceAlert(kAlertCautionAlert, kS9xMacAlertkBadRom, kS9xMacAlertkBadRomHint); 3328 } 3329 else 3330 { 3331 strncpy(mes, message, 255); 3332 S9xSetInfoString(mes); 3333 } 3334} 3335 3336const char * S9xStringInput (const char *s) 3337{ 3338 return (NULL); 3339} 3340 3341void S9xToggleSoundChannel (int c) 3342{ 3343 static int channel_enable = 255; 3344 3345 if (c == 8) 3346 channel_enable = 255; 3347 else 3348 channel_enable ^= 1 << c; 3349 3350 S9xSetSoundControl(channel_enable); 3351} 3352 3353void S9xExit (void) 3354{ 3355 PlayAlertSound(); 3356 3357 running = false; 3358 cartOpen = false; 3359 3360 QuitApplicationEventLoop(); 3361} 3362 3363void QuitWithFatalError (OSStatus err, const char *msg) 3364{ 3365 printf("Quit. %s err: %ld\n", msg, err); 3366 ExitToShell(); 3367} 3368