snes9x/macosx/mac-os.mm
2019-11-27 16:08:12 -08:00

3185 lines
100 KiB
Plaintext

/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
/***********************************************************************************
SNES9X for Mac OS (c) Copyright John Stiles
Snes9x for Mac OS X
(c) Copyright 2001 - 2011 zones
(c) Copyright 2002 - 2005 107
(c) Copyright 2002 PB1400c
(c) Copyright 2004 Alexander and Sander
(c) Copyright 2004 - 2005 Steven Seeger
(c) Copyright 2005 Ryan Vogt
(c) Copyright 2019 Michael Donald Buckley
***********************************************************************************/
#import <Cocoa/Cocoa.h>
#import <mach/mach_time.h>
#include <OpenGL/OpenGL.h>
#include <OpenGL/CGLRenderers.h>
#include <OpenGL/gl.h>
#include <OpenGL/glu.h>
#include <OpenGL/glext.h>
#import "snes9x.h"
#import "memmap.h"
#import "apu.h"
#import "controls.h"
#import "crosshairs.h"
#import "cheats.h"
#import "movie.h"
#import "snapshot.h"
#import "display.h"
#import "blit.h"
#ifdef DEBUGGER
#import "debug.h"
#endif
#import <pthread.h>
#import "mac-prefix.h"
#import "mac-appleevent.h"
#import "mac-audio.h"
#import "mac-cheat.h"
#import "mac-cheatfinder.h"
#import "mac-cocoatools.h"
#import "mac-controls.h"
#import "mac-coreimage.h"
#import "mac-dialog.h"
#import "mac-file.h"
#import "mac-gworld.h"
#import "mac-joypad.h"
#import "mac-keyboard.h"
#import "mac-multicart.h"
#import "mac-musicbox.h"
#import "mac-netplay.h"
#import "mac-prefs.h"
#import "mac-render.h"
#import "mac-screenshot.h"
#import "mac-snes9x.h"
#import "mac-stringtools.h"
#import "mac-os.h"
#define kRecentMenu_MAX 20
#define KeyIsPressed(km, k) (km[k])
volatile bool8 running = false;
volatile bool8 s9xthreadrunning = false;
volatile int windowResizeCount = 1;
volatile bool8 windowExtend = true;
uint32 controlPad[MAC_MAX_PLAYERS];
uint8 romDetect = 0,
interleaveDetect = 0,
videoDetect = 0,
headerDetect = 0;
WindowRef gWindow = NULL;
uint32 glScreenW,
glScreenH;
CGRect glScreenBounds;
Point windowPos[kWindowCount];
CGSize windowSize[kWindowCount];
CGImageRef macIconImage[118];
int macPadIconIndex,
macLegendIconIndex,
macMusicBoxIconIndex,
macFunctionIconIndex;
int macFrameSkip = -1;
int32 skipFrames = 3;
int64 lastFrame = 0;
int64 machTimeNumerator = 0;
int64 machTimeDenominator = 0;
int macFastForwardRate = 5,
macFrameAdvanceRate = 1000000;
unsigned long spcFileCount = 0,
pngFileCount = 0;
bool8 finished = false,
cartOpen = false,
autofire = false,
hidExist = true,
directDisplay = false;
bool8 fullscreen = false,
autoRes = false,
glstretch = true,
gl32bit = true,
vsync = true,
drawoverscan = false,
screencurvature = false,
multiprocessor = false,
ciFilterEnable = false;
long drawingMethod = kDrawingOpenGL;
int videoMode = VIDEOMODE_BLOCKY;
SInt32 macSoundVolume = 80; // %
uint32 macSoundBuffer_ms = 80; // ms
uint32 macSoundInterval_ms = 16; // ms
bool8 macSoundLagEnable = false;
uint16 aueffect = 0;
uint8 saveInROMFolder = 2; // 0 : Snes9x 1 : ROM 2 : Application Support
NSString *saveFolderPath;
int macCurvatureWarp = 15,
macAspectRatio = 0;
bool8 startopendlog = false,
showtimeinfrz = true,
enabletoggle = true,
savewindowpos = false,
onscreeninfo = true;
int inactiveMode = 2;
int musicboxmode = kMBXSoundEmulation;
bool8 applycheat = false;
int padSetting = 1,
deviceSetting = 1,
deviceSettingMaster = 1;
int macControllerOption = SNES_JOYPAD;
AutoFireState autofireRec[MAC_MAX_PLAYERS];
bool8 macQTRecord = false;
uint16 macQTMovFlag = 0;
uint16 macRecordFlag = 0x3,
macPlayFlag = 0x1;
wchar_t macRecordWChar[MOVIE_MAX_METADATA];
char npServerIP[256],
npName[256];
bool8 lastoverscan = false;
CGPoint unlimitedCursor;
ExtraOption extraOptions;
CFStringRef multiCartPath[2];
#ifdef MAC_PANTHER_SUPPORT
IconRef macIconRef[118];
#endif
bool8 pressedKeys[MAC_NUM_KEYCODES];
os_unfair_lock keyLock;
os_unfair_lock renderLock;
NSOpenGLView *s9xView;
enum
{
mApple = 128,
iAbout = 1,
mFile = 129,
iOpen = 1,
iOpenMulti = 2,
iOpenRecent = 3,
iClose = 5,
iRomInfo = 7,
mControl = 134,
iKeyboardLayout = 1,
iISpLayout = 2,
iAutoFire = 4,
iISpPreset = 6,
mEdit = 130,
mEmulation = 131,
iResume = 1,
iSoftReset = 3,
iReset = 4,
iDevice = 6,
mCheat = 132,
iApplyCheats = 1,
iGameGenie = 3,
iCheatFinder = 4,
mOption = 133,
iFreeze = 1,
iDefrost = 2,
iFreezeTo = 4,
iDefrostFrom = 5,
iRecordMovie = 7,
iPlayMovie = 8,
iQTMovie = 10,
iSaveSPC = 12,
iSaveSRAM = 13,
iCIFilter = 15,
iMusicBox = 17,
mNetplay = 135,
iServer = 1,
iClient = 2,
mPresets = 201,
mDevice = 202,
iPad = 1,
iMouse = 2,
iMouse2 = 3,
iSuperScope = 4,
iMultiPlayer5 = 5,
iMultiPlayer5_2 = 6,
iJustifier1 = 7,
iJustifier2 = 8,
mRecentItem = 203
};
enum
{
kmF1Key = 0x7A,
kmF2Key = 0x78,
kmF3Key = 0x63,
kmF4Key = 0x76,
kmF5Key = 0x60,
kmF6Key = 0x61,
km0Key = 0x1D,
km1Key = 0x12,
km2Key = 0x13,
km3Key = 0x14,
km4Key = 0x15,
km5Key = 0x17,
km6Key = 0x16,
km7Key = 0x1A,
km8Key = 0x1C,
km9Key = 0x19,
kmAKey = 0x00,
kmBKey = 0x0B,
kmCKey = 0x08,
kmEscKey = 0x35,
kmCtrKey = 0x3B,
kmMinusKey = 0x1B,
kmQKey = 0x0C,
kmWKey = 0x0D,
kmOKey = 0x1F,
kmPKey = 0x23
};
struct ButtonCommand
{
char command[16];
uint8 keycode;
bool8 held;
};
struct GameViewInfo
{
int globalLeft;
int globalTop;
int width;
int height;
};
static volatile bool8 rejectinput = false;
static bool8 pauseEmulation = false,
frameAdvance = false;
static CFStringRef recentItem[kRecentMenu_MAX + 1];
static int frameCount = 0;
static bool8 frzselecting = false;
static uint16 changeAuto[2] = { 0x0000, 0x0000 };
static GameViewInfo scopeViewInfo;
static ButtonCommand btncmd[] =
{
{ "ToggleBG0", kmF1Key, false },
{ "ToggleBG1", kmF2Key, false },
{ "ToggleBG2", kmF3Key, false },
{ "ToggleBG3", kmF4Key, false },
{ "ToggleSprites", kmF5Key, false },
{ "SwapJoypads", kmF6Key, false },
{ "SoundChannel0", km1Key, false },
{ "SoundChannel1", km2Key, false },
{ "SoundChannel2", km3Key, false },
{ "SoundChannel3", km4Key, false },
{ "SoundChannel4", km5Key, false },
{ "SoundChannel5", km6Key, false },
{ "SoundChannel6", km7Key, false },
{ "SoundChannel7", km8Key, false },
{ "SoundChannelsOn", km9Key, false },
{ "_mac1", km0Key, false },
{ "_mac2", kmMinusKey, false },
{ "_mac3", kmQKey, false },
{ "_mac4", kmWKey, false },
{ "_mac5", kmOKey, false },
{ "_mac6", kmPKey, false }
};
#define kCommandListSize (sizeof(btncmd) / sizeof(btncmd[0]))
static void Initialize (void);
static void Deinitialize (void);
static void InitAutofire (void);
static void ProcessInput (void);
static void ResizeGameWindow (void);
static void ChangeAutofireSettings (int, int);
static void ChangeTurboRate (int);
static void CFTimerCallback (CFRunLoopTimerRef, void *);
static void UpdateFreezeDefrostScreen (int, CGImageRef, uint8 *, CGContextRef);
static void * MacSnes9xThread (void *);
static inline void EmulationLoop (void);
static inline void CopyPressedKeys(uint8 destination[MAC_NUM_KEYCODES]);
int main (int argc, const char *argv[])
{
return NSApplicationMain(argc, argv);
}
static void * MacSnes9xThread (void *)
{
Settings.StopEmulation = false;
s9xthreadrunning = true;
EmulationLoop();
s9xthreadrunning = false;
Settings.StopEmulation = true;
return (NULL);
}
static inline void CopyPressedKeys(uint8 destination[MAC_NUM_KEYCODES])
{
os_unfair_lock_lock(&keyLock);
NSEventModifierFlags flags = [NSEvent modifierFlags];
pressedKeys[kVK_Shift] = (flags & NSEventModifierFlagShift) != 0;
pressedKeys[kVK_Command] = (flags & NSEventModifierFlagCommand) != 0;
pressedKeys[kVK_Control] = (flags & NSEventModifierFlagControl) != 0;
pressedKeys[kVK_CapsLock] = (flags & NSEventModifierFlagCapsLock) != 0;
pressedKeys[kVK_Option] = (flags & NSEventModifierFlagOption) != 0;
pressedKeys[kVK_Help] = (flags & NSEventModifierFlagHelp) != 0;
pressedKeys[kVK_Function] = (flags & NSEventModifierFlagFunction) != 0;
memcpy(destination, pressedKeys, sizeof(pressedKeys));
os_unfair_lock_unlock(&keyLock);
}
static inline void EmulationLoop (void)
{
bool8 olddisplayframerate = false;
int storedMacFrameSkip = macFrameSkip;
pauseEmulation = false;
frameAdvance = false;
if (macQTRecord)
{
olddisplayframerate = Settings.DisplayFrameRate;
Settings.DisplayFrameRate = false;
}
MacStartSound();
if (Settings.NetPlay)
{
// if (Settings.NetPlayServer)
// {
// NPServerDetachNetPlayThread();
// NPServerStartClients();
//
// while (running)
// {
// NPServerProcessInput();
// S9xMainLoop();
// }
//
// NPServerStopNetPlayThread();
// NPServerStopServer();
// }
// else
// {
// NPClientDetachNetPlayThread();
// NPClientNetPlayWaitStart();
//
// while (running)
// {
// NPClientProcessInput();
// S9xMainLoop();
// }
//
// NPClientStopNetPlayThread();
// NPClientDisconnect();
//
// NPClientRestoreConfig();
// }
}
else
{
while (running)
{
ProcessInput();
if (!pauseEmulation)
{
os_unfair_lock_lock(&renderLock);
S9xMainLoop();
os_unfair_lock_unlock(&renderLock);
}
else
{
if (frameAdvance)
{
macFrameSkip = 1;
skipFrames = 1;
frameAdvance = false;
os_unfair_lock_lock(&renderLock);
S9xMainLoop();
os_unfair_lock_unlock(&renderLock);
macFrameSkip = storedMacFrameSkip;
}
usleep(Settings.FrameTime);
}
}
}
MacStopSound();
if (macQTRecord)
{
// MacQTStopRecording();
// macQTRecord = false;
Settings.DisplayFrameRate = olddisplayframerate;
}
S9xMovieShutdown();
}
//
//static OSStatus MainEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
//{
// OSStatus err, result = eventNotHandledErr;
// Boolean done = false;
//
// if (frzselecting)
// return (result);
//
// switch (GetEventClass(inEvent))
// {
// case kEventClassCommand:
// switch (GetEventKind(inEvent))
// {
// HICommand cmd;
//
// case kEventCommandUpdateStatus:
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd);
// if (err == noErr && cmd.commandID == 'clos')
// {
// UpdateMenuCommandStatus(false);
// result = noErr;
// }
//
// break;
//
// case kEventCommandProcess:
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd);
// if (err == noErr)
// {
// UInt32 modifierkey;
//
// err = GetEventParameter(inEvent, kEventParamKeyModifiers, typeUInt32, NULL, sizeof(UInt32), NULL, &modifierkey);
// if (err == noErr)
// {
// if ((cmd.commandID == 'pref') && (modifierkey & optionKey))
// cmd.commandID = 'EXTR';
//
// result = HandleMenuChoice(cmd.commandID, &done);
//
// if (done)
// QuitApplicationEventLoop();
// }
// }
//
// break;
// }
//
// break;
// }
//
// return (result);
//}
//
//static OSStatus SubEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
//{
// OSStatus err, result = eventNotHandledErr;
//
// if (frzselecting)
// return (result);
//
// switch (GetEventClass(inEvent))
// {
// case kEventClassCommand:
// switch (GetEventKind(inEvent))
// {
// HICommand cmd;
//
// case kEventCommandUpdateStatus:
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd);
// if (err == noErr && cmd.commandID == 'clos')
// {
// UpdateMenuCommandStatus(false);
// result = noErr;
// }
//
// break;
//
// case kEventCommandProcess:
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeHICommand, NULL, sizeof(HICommand), NULL, &cmd);
// if (err == noErr)
// {
// switch (cmd.commandID)
// {
// case 'Erun': // Pause
// case 'SubQ': // Queue from emulation thread
// running = false;
// while (s9xthreadrunning)
// sleep(0);
// QuitApplicationEventLoop();
// result = noErr;
// break;
//
// case 'Ocif': // Core Image Filter
// HiliteMenu(0);
// ConfigureCoreImageFilter();
// result = noErr;
// break;
// }
// }
//
// break;
// }
//
// break;
//
// case kEventClassMouse:
// if (fullscreen)
// {
// if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2))
// {
// if (!(Settings.NetPlay && !Settings.NetPlayServer))
// {
// switch (GetEventKind(inEvent))
// {
// case kEventMouseUp:
// HIPoint hipt;
//
// err = GetEventParameter(inEvent, kEventParamMouseLocation, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt);
// if (err == noErr)
// {
// if (CGRectContainsPoint(glScreenBounds, hipt))
// {
// running = false;
// while (s9xthreadrunning)
// sleep(0);
// QuitApplicationEventLoop();
// result = noErr;
// }
// }
//
// break;
// }
// }
// }
// else
// if ((macControllerOption == SNES_MOUSE) || (macControllerOption == SNES_MOUSE_SWAPPED))
// {
// switch (GetEventKind(inEvent))
// {
// case kEventMouseMoved:
// case kEventMouseDragged:
// HIPoint hipt;
//
// err = GetEventParameter(inEvent, kEventParamMouseDelta, typeHIPoint, NULL, sizeof(HIPoint), NULL, &hipt);
// if (err == noErr)
// {
// unlimitedCursor.x += hipt.x;
// unlimitedCursor.y += hipt.y;
// }
//
// break;
// }
// }
// }
//
// break;
// }
//
// return (result);
//}
//
//void PostQueueToSubEventLoop (void)
//{
// OSStatus err;
// EventRef event;
//
// err = CreateEvent(kCFAllocatorDefault, kEventClassCommand, kEventCommandProcess, 0, kEventAttributeUserEvent, &event);
// if (err == noErr)
// {
// HICommand cmd;
//
// cmd.commandID = 'SubQ';
// cmd.attributes = kEventAttributeUserEvent;
// cmd.menu.menuRef = NULL;
// cmd.menu.menuItemIndex = 0;
//
// err = SetEventParameter(event, kEventParamDirectObject, typeHICommand, sizeof(HICommand), &cmd);
// if (err == noErr)
// err = PostEventToQueue(GetMainEventQueue(), event, kEventPriorityStandard);
//
// ReleaseEvent(event);
// }
//}
//
//void InitGameWindow (void)
//{
// OSStatus err;
// IBNibRef nibRef;
// WindowAttributes attr;
// CFStringRef ref;
// HIViewRef ctl;
// HIViewID cid = { 'Pict', 0 };
// Rect rct;
// char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
// EventTypeSpec wupaneEvents[] = { { kEventClassControl, kEventControlClick },
// { kEventClassControl, kEventControlDraw } },
// windowEvents[] = { { kEventClassWindow, kEventWindowDeactivated },
// { kEventClassWindow, kEventWindowActivated },
// { kEventClassWindow, kEventWindowBoundsChanging },
// { kEventClassWindow, kEventWindowBoundsChanged },
// { kEventClassWindow, kEventWindowZoom },
// { kEventClassWindow, kEventWindowToolbarSwitchMode } };
//
// if (gWindow)
// return;
//
// err = CreateNibReference(kMacS9XCFString, &nibRef);
// if (err)
// QuitWithFatalError(err, "os 02");
//
// err = CreateWindowFromNib(nibRef, CFSTR("GameWindow"), &gWindow);
// if (err)
// QuitWithFatalError(err, "os 03");
//
// DisposeNibReference(nibRef);
//
// HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl);
//
// gameWindowUPP = NewEventHandlerUPP(GameWindowEventHandler);
// err = InstallWindowEventHandler(gWindow, gameWindowUPP, GetEventTypeCount(windowEvents), windowEvents, (void *) gWindow, &gameWindowEventRef);
//
// gameWUPaneUPP = NewEventHandlerUPP(GameWindowUserPaneEventHandler);
// err = InstallControlEventHandler(ctl, gameWUPaneUPP, GetEventTypeCount(wupaneEvents), wupaneEvents, (void *) gWindow, &gameWUPaneEventRef);
//
// _splitpath(Memory.ROMFilename, drive, dir, fname, ext);
// ref = CFStringCreateWithCString(kCFAllocatorDefault, fname, kCFStringEncodingUTF8);
// if (ref)
// {
// SetWindowTitleWithCFString(gWindow, ref);
// CFRelease(ref);
// }
//
// attr = kWindowFullZoomAttribute | kWindowResizableAttribute | kWindowLiveResizeAttribute;
// err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes);
//
// attr = kWindowToolbarButtonAttribute;
// if (!drawoverscan)
// err = ChangeWindowAttributes(gWindow, attr, kWindowNoAttributes);
// else
// err = ChangeWindowAttributes(gWindow, kWindowNoAttributes, attr);
//
// if (savewindowpos)
// {
// MoveWindow(gWindow, windowPos[kWindowScreen].h, windowPos[kWindowScreen].v, false);
//
// if ((windowSize[kWindowScreen].width <= 0) || (windowSize[kWindowScreen].height <= 0))
// {
// windowExtend = true;
// windowSize[kWindowScreen].width = 512;
// windowSize[kWindowScreen].height = kMacWindowHeight;
// }
//
// if (!lastoverscan && !windowExtend && drawoverscan)
// {
// windowExtend = true;
// windowSize[kWindowScreen].height = (int) ((float) (windowSize[kWindowScreen].height + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT);
// }
//
// SizeWindow(gWindow, (short) windowSize[kWindowScreen].width, (short) windowSize[kWindowScreen].height, false);
// }
// else
// {
// if (drawoverscan)
// windowExtend = true;
//
// SizeWindow(gWindow, 512, (windowExtend ? kMacWindowHeight : (SNES_HEIGHT << 1)), false);
// RepositionWindow(gWindow, NULL, kWindowCenterOnMainScreen);
// }
//
// windowZoomCount = 0;
//
// GetWindowBounds(gWindow, kWindowContentRgn, &rct);
// gWindowRect = CGRectMake((float) rct.left, (float) rct.top, (float) (rct.right - rct.left), (float) (rct.bottom - rct.top));
//
// ActivateWindow(gWindow, true);
//}
//
//void UpdateGameWindow (void)
//{
// OSStatus err;
// HIViewRef ctl;
// HIViewID cid = { 'Pict', 0 };
//
// if (!gWindow)
// return;
//
// HIViewFindByID(HIViewGetRoot(gWindow), cid, &ctl);
// err = HIViewSetNeedsDisplay(ctl, true);
//}
//
//static void ResizeGameWindow (void)
//{
// Rect rct;
// int ww, wh;
//
// if (!gWindow)
// return;
//
// GetWindowBounds(gWindow, kWindowContentRgn, &rct);
//
// wh = (windowExtend ? SNES_HEIGHT_EXTENDED : SNES_HEIGHT) * ((windowZoomCount >> 1) + 1);
//
// if (windowZoomCount % 2)
// ww = SNES_NTSC_OUT_WIDTH(SNES_WIDTH) * ((windowZoomCount >> 1) + 1) / 2;
// else
// ww = SNES_WIDTH * ((windowZoomCount >> 1) + 1);
//
// rct.right = rct.left + ww;
// rct.bottom = rct.top + wh;
//
// SetWindowBounds(gWindow, kWindowContentRgn, &rct);
//
// printf("Window Size: %d, %d\n", ww, wh);
//
// windowZoomCount++;
// if (windowZoomCount == 8)
// windowZoomCount = 0;
//}
//
//void DeinitGameWindow (void)
//{
// OSStatus err;
//
// if (!gWindow)
// return;
//
// SaveWindowPosition(gWindow, kWindowScreen);
// lastoverscan = drawoverscan;
//
// err = RemoveEventHandler(gameWUPaneEventRef);
// DisposeEventHandlerUPP(gameWUPaneUPP);
//
// err = RemoveEventHandler(gameWindowEventRef);
// DisposeEventHandlerUPP(gameWindowUPP);
//
// CFRelease(gWindow);
// gWindow = NULL;
//}
//
//static OSStatus GameWindowEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
//{
// OSStatus err, result = eventNotHandledErr;
// HIRect rct;
// Rect r;
// UInt32 attr;
//
// switch (GetEventClass(inEvent))
// {
// case kEventClassWindow:
// switch (GetEventKind(inEvent))
// {
// case kEventWindowDeactivated:
// if (running)
// {
// if (!(Settings.NetPlay && !Settings.NetPlayServer))
// {
// if (inactiveMode == 3)
// {
// running = false;
// while (s9xthreadrunning)
// sleep(0);
// QuitApplicationEventLoop();
// result = noErr;
// }
// else
// if (inactiveMode == 2)
// {
// rejectinput = true;
// result = noErr;
// }
// }
// }
//
// break;
//
// case kEventWindowActivated:
// if (running)
// {
// if (!(Settings.NetPlay && !Settings.NetPlayServer))
// {
// ForceChangingKeyScript();
//
// if (inactiveMode == 2)
// {
// rejectinput = false;
// result = noErr;
// }
// }
// }
//
// break;
//
// case kEventWindowBoundsChanging:
// windowResizeCount = 0x7FFFFFFF;
//
// err = GetEventParameter(inEvent, kEventParamAttributes, typeUInt32, NULL, sizeof(UInt32), NULL, &attr);
// if ((err == noErr) && (attr & kWindowBoundsChangeSizeChanged))
// {
// err = GetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &rct);
// if (err == noErr)
// {
// if (GetCurrentEventKeyModifiers() & shiftKey)
// {
// HIRect origRct;
//
// err = GetEventParameter(inEvent, kEventParamOriginalBounds, typeHIRect, NULL, sizeof(HIRect), NULL, &origRct);
// if (err == noErr)
// {
// rct.size.width = (float) (int) (origRct.size.width * rct.size.height / origRct.size.height);
// err = SetEventParameter(inEvent, kEventParamCurrentBounds, typeHIRect, sizeof(HIRect), &rct);
// }
// }
//
// gWindowRect = rct;
// }
// }
//
// result = noErr;
// break;
//
// case kEventWindowBoundsChanged:
// windowResizeCount = 3;
// result = noErr;
// break;
//
// case kEventWindowZoom:
// ResizeGameWindow();
// result = noErr;
// break;
//
// case kEventWindowToolbarSwitchMode:
// windowExtend = !windowExtend;
//
// GetWindowBounds(gWindow, kWindowContentRgn, &r);
//
// if (windowExtend)
// r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT_EXTENDED / SNES_HEIGHT);
// else
// r.bottom = r.top + (int) (((float) (r.bottom - r.top) + 0.5) * SNES_HEIGHT / SNES_HEIGHT_EXTENDED);
//
// SetWindowBounds(gWindow, kWindowContentRgn, &r);
//
// result = noErr;
// break;
// }
//
// break;
// }
//
// return (result);
//}
//
//static OSStatus GameWindowUserPaneEventHandler (EventHandlerCallRef inHandlerCallRef, EventRef inEvent, void *inUserData)
//{
// OSStatus err, result = eventNotHandledErr;
//
// switch (GetEventClass(inEvent))
// {
// case kEventClassControl:
// switch (GetEventKind(inEvent))
// {
// case kEventControlClick:
// if (running)
// {
// if ((macControllerOption == SNES_JOYPAD) || (macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2))
// {
// if (!(Settings.NetPlay && !Settings.NetPlayServer))
// {
// if (!frzselecting)
// {
// running = false;
// while (s9xthreadrunning)
// sleep(0);
// QuitApplicationEventLoop();
// result = noErr;
// }
// }
// }
// }
// else
// {
// UInt32 count;
//
// err = GetEventParameter(inEvent, kEventParamClickCount, typeUInt32, NULL, sizeof(UInt32), NULL, &count);
// if ((err == noErr) && (count == 2))
// {
// SNES9X_Go();
// QuitApplicationEventLoop();
// result = noErr;
// }
// }
//
// break;
//
// case kEventControlDraw:
// CGContextRef ctx;
// HIViewRef view;
// HIRect bounds;
//
// err = GetEventParameter(inEvent, kEventParamDirectObject, typeControlRef, NULL, sizeof(ControlRef), NULL, &view);
// if (err == noErr)
// {
// err = GetEventParameter(inEvent, kEventParamCGContextRef, typeCGContextRef, NULL, sizeof(CGContextRef), NULL, &ctx);
// if (err == noErr)
// {
// if (!running)
// {
// HIViewGetBounds(view, &bounds);
// CGContextTranslateCTM(ctx, 0, bounds.size.height);
// CGContextScaleCTM(ctx, 1.0f, -1.0f);
// DrawPauseScreen(ctx, bounds);
// }
// }
// }
//
// result = noErr;
// break;
// }
//
// break;
// }
//
// return (result);
//}
//
//
//static void InitRecentMenu (void)
//{
// OSStatus err;
//
// err = CreateNewMenu(mRecentItem, 0, &recentMenu);
// err = SetMenuItemHierarchicalMenu(GetMenuRef(mFile), iOpenRecent, recentMenu);
//}
//
//static void DeinitRecentMenu (void)
//{
// CFRelease(recentMenu);
//}
//
//void BuildRecentMenu (void)
//{
// OSStatus err;
// CFStringRef str;
//
// err = DeleteMenuItems(recentMenu, 1, CountMenuItems(recentMenu));
//
// for (int i = 0; i < kRecentMenu_MAX; i++)
// {
// if (!recentItem[i])
// break;
//
// Boolean r;
// char path[PATH_MAX + 1];
//
// r = CFStringGetCString(recentItem[i], path, PATH_MAX, kCFStringEncodingUTF8);
// if (r)
// {
// CFStringRef nameRef;
// char drive[_MAX_DRIVE + 1], dir[_MAX_DIR + 1], fname[_MAX_FNAME + 1], ext[_MAX_EXT + 1];
//
// _splitpath(path, drive, dir, fname, ext);
// snprintf(path, PATH_MAX + 1, "%s%s", fname, ext);
// nameRef = CFStringCreateWithCString(kCFAllocatorDefault, path, kCFStringEncodingUTF8);
// if (nameRef)
// {
// err = AppendMenuItemTextWithCFString(recentMenu, nameRef, 0, 'FRe0' + i, NULL);
// CFRelease(nameRef);
// }
// }
// }
//
// err = AppendMenuItemTextWithCFString(recentMenu, NULL, kMenuItemAttrSeparator, 'FR__', NULL);
//
// str = CFCopyLocalizedString(CFSTR("ClearMenu"), "ClearMenu");
// if (str)
// {
// err = AppendMenuItemTextWithCFString(recentMenu, str, 0, 'FRcr', NULL);
// CFRelease(str);
// }
//}
//
//void AdjustMenus (void)
//{
// OSStatus err;
// MenuRef menu;
// CFStringRef str;
//
// if (running)
// {
// menu = GetMenuRef(mApple);
// DisableMenuItem(menu, iAbout);
// DisableMenuCommand(NULL, kHICommandPreferences);
// DisableMenuCommand(NULL, kHICommandQuit);
//
// menu = GetMenuRef(mFile);
// DisableMenuItem(menu, iOpen);
// DisableMenuItem(menu, iOpenMulti);
// DisableMenuItem(menu, iOpenRecent);
// DisableMenuItem(menu, iRomInfo);
//
// menu = GetMenuRef(mControl);
// DisableMenuItem(menu, iKeyboardLayout);
// DisableMenuItem(menu, iISpLayout);
// DisableMenuItem(menu, iAutoFire);
// DisableMenuItem(menu, iISpPreset);
//
// menu = GetMenuRef(mEmulation);
// str = CFCopyLocalizedString(CFSTR("PauseMenu"), "pause");
// err = SetMenuItemTextWithCFString(menu, iResume, str);
// CFRelease(str);
// DisableMenuItem(menu, iSoftReset);
// DisableMenuItem(menu, iReset);
// DisableMenuItem(menu, iDevice);
//
// if (Settings.NetPlay)
// {
// if (Settings.NetPlayServer)
// EnableMenuItem(menu, iResume);
// else
// DisableMenuItem(menu, iResume);
// }
// else
// EnableMenuItem(menu, iResume);
//
// menu = GetMenuRef(mCheat);
// DisableMenuItem(menu, iApplyCheats);
// DisableMenuItem(menu, iGameGenie);
// DisableMenuItem(menu, iCheatFinder);
//
// menu = GetMenuRef(mOption);
// DisableMenuItem(menu, iFreeze);
// DisableMenuItem(menu, iDefrost);
// DisableMenuItem(menu, iFreezeTo);
// DisableMenuItem(menu, iDefrostFrom);
// DisableMenuItem(menu, iRecordMovie);
// DisableMenuItem(menu, iPlayMovie);
// DisableMenuItem(menu, iQTMovie);
// DisableMenuItem(menu, iSaveSPC);
// DisableMenuItem(menu, iSaveSRAM);
// DisableMenuItem(menu, iMusicBox);
// if (ciFilterEnable)
// EnableMenuItem(menu, iCIFilter);
// else
// DisableMenuItem(menu, iCIFilter);
//
// menu = GetMenuRef(mNetplay);
// DisableMenuItem(menu, iServer);
// DisableMenuItem(menu, iClient);
// }
// else
// {
// menu = GetMenuRef(mApple);
// EnableMenuItem(menu, iAbout);
// EnableMenuCommand(NULL, kHICommandPreferences);
// EnableMenuCommand(NULL, kHICommandQuit);
//
// menu = GetMenuRef(mFile);
// EnableMenuItem(menu, iOpen);
// EnableMenuItem(menu, iOpenMulti);
// EnableMenuItem(menu, iOpenRecent);
// if (cartOpen)
// EnableMenuItem(menu, iRomInfo);
// else
// DisableMenuItem(menu, iRomInfo);
//
// menu = GetMenuRef(mControl);
// EnableMenuItem(menu, iKeyboardLayout);
// EnableMenuItem(menu, iAutoFire);
// if (hidExist)
// {
// EnableMenuItem(menu, iISpLayout);
// EnableMenuItem(menu, iISpPreset);
// }
// else
// {
// DisableMenuItem(menu, iISpLayout);
// DisableMenuItem(menu, iISpPreset);
// }
//
// menu = GetMenuRef(mEmulation);
// str = CFCopyLocalizedString(CFSTR("RunMenu"), "run");
// err = SetMenuItemTextWithCFString(menu, iResume, str);
// CFRelease(str);
// EnableMenuItem(menu, iDevice);
// if (cartOpen)
// {
// EnableMenuItem(menu, iResume);
// EnableMenuItem(menu, iSoftReset);
// EnableMenuItem(menu, iReset);
// }
// else
// {
// DisableMenuItem(menu, iResume);
// DisableMenuItem(menu, iSoftReset);
// DisableMenuItem(menu, iReset);
// }
//
// menu = GetMenuRef(mCheat);
// if (cartOpen)
// {
// EnableMenuItem(menu, iApplyCheats);
// EnableMenuItem(menu, iGameGenie);
// EnableMenuItem(menu, iCheatFinder);
// }
// else
// {
// DisableMenuItem(menu, iApplyCheats);
// DisableMenuItem(menu, iGameGenie);
// DisableMenuItem(menu, iCheatFinder);
// }
//
// menu = GetMenuRef(mOption);
// DisableMenuItem(menu, iCIFilter);
// if (cartOpen)
// {
// EnableMenuItem(menu, iFreeze);
// EnableMenuItem(menu, iDefrost);
// EnableMenuItem(menu, iFreezeTo);
// EnableMenuItem(menu, iDefrostFrom);
// EnableMenuItem(menu, iRecordMovie);
// EnableMenuItem(menu, iPlayMovie);
// EnableMenuItem(menu, iQTMovie);
// EnableMenuItem(menu, iSaveSPC);
// EnableMenuItem(menu, iSaveSRAM);
// EnableMenuItem(menu, iMusicBox);
// }
// else
// {
// DisableMenuItem(menu, iFreeze);
// DisableMenuItem(menu, iDefrost);
// DisableMenuItem(menu, iFreezeTo);
// DisableMenuItem(menu, iDefrostFrom);
// DisableMenuItem(menu, iRecordMovie);
// DisableMenuItem(menu, iPlayMovie);
// DisableMenuItem(menu, iQTMovie);
// DisableMenuItem(menu, iSaveSPC);
// DisableMenuItem(menu, iSaveSRAM);
// DisableMenuItem(menu, iMusicBox);
// }
//
// menu = GetMenuRef(mNetplay);
// EnableMenuItem(menu, iClient);
// if (cartOpen)
// EnableMenuItem(menu, iServer);
// else
// DisableMenuItem(menu, iServer);
// }
//
// DrawMenuBar();
//}
//
//void UpdateMenuCommandStatus (Boolean closeMenu)
//{
// if (closeMenu)
// EnableMenuItem(GetMenuRef(mFile), iClose);
// else
// DisableMenuItem(GetMenuRef(mFile), iClose);
//}
//
//static OSStatus HandleMenuChoice (UInt32 command, Boolean *done)
//{
// OSStatus err, result = noErr;
// MenuRef mh;
// int item;
// bool8 isok = true;
//
// if ((command & 0xFFFFFF00) == 'FRe\0')
// {
// Boolean r;
// int index;
// char path[PATH_MAX + 1];
//
// index = (int) (command & 0x000000FF) - (int) '0';
// r = CFStringGetCString(recentItem[index], path, PATH_MAX, kCFStringEncodingUTF8);
// if (r)
// {
// FSRef ref;
//
// err = FSPathMakeRef((unsigned char *) path, &ref, NULL);
// if (err == noErr)
// {
// if (SNES9X_OpenCart(&ref))
// {
// SNES9X_Go();
// *done = true;
// }
// else
// AdjustMenus();
// }
// }
// }
// else
// {
// switch (command)
// {
// case 'abou': // About SNES9X
// StartCarbonModalDialog();
// AboutDialog();
// FinishCarbonModalDialog();
//
// break;
//
// case 'pref': // Preferences...
// StartCarbonModalDialog();
// ConfigurePreferences();
// FinishCarbonModalDialog();
//
// break;
//
// case 'EXTR': // Extra Options...
// StartCarbonModalDialog();
// ConfigureExtraOptions();
// FinishCarbonModalDialog();
//
// break;
//
// case 'quit': // Quit SNES9X
// SNES9X_Quit();
// *done = true;
//
// break;
//
// case 'open': // Open ROM Image...
// if (SNES9X_OpenCart(NULL))
// {
// SNES9X_Go();
// *done = true;
// }
// else
// AdjustMenus();
//
// break;
//
// case 'Mult': // Open Multiple ROM Images...
// if (SNES9X_OpenMultiCart())
// {
// SNES9X_Go();
// *done = true;
// }
// else
// AdjustMenus();
//
// break;
//
// case 'FRcr': // Clear Menu
// ClearRecentItems();
// BuildRecentMenu();
//
// break;
//
// case 'Finf': // ROM Information
// StartCarbonModalDialog();
// RomInfoDialog();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Ckey': // Configure Keyboard...
// StartCarbonModalDialog();
// ConfigureKeyboard();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Cpad': // Configure Controllers...
// StartCarbonModalDialog();
// ConfigureHID();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Caut': // Automatic Fire...
// StartCarbonModalDialog();
// ConfigureAutofire();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Hapl': // Apply Cheat Entries
// mh = GetMenuRef(mCheat);
// applycheat = !applycheat;
// CheckMenuItem(mh, iApplyCheats, applycheat);
// Settings.ApplyCheats = applycheat;
//
// if (!Settings.ApplyCheats)
// S9xCheatsDisable();
// else
// S9xCheatsEnable();
//
// break;
//
// case 'Hent': // Cheat Entry...
// StartCarbonModalDialog();
// ConfigureCheat();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Hfnd': // Cheat Finder...
// StartCarbonModalDialog();
// CheatFinder();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Erun': // Run
// SNES9X_Go();
// *done = true;
//
// break;
//
// case 'Esrs': // Software Reset
// SNES9X_SoftReset();
// SNES9X_Go();
// *done = true;
//
// break;
//
// case 'Erst': // Hardware Reset
// SNES9X_Reset();
// SNES9X_Go();
// *done = true;
//
// break;
//
// case 'Ofrz': // Freeze State
// isok = SNES9X_Freeze();
// *done = true;
//
// break;
//
// case 'Odfr': // Defrost state
// isok = SNES9X_Defrost();
// *done = true;
//
// break;
//
// case 'Ofrd': // Freeze State to...
// StartCarbonModalDialog();
// isok = SNES9X_FreezeTo();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Odfd': // Defrost State From...
// StartCarbonModalDialog();
// isok = SNES9X_DefrostFrom();
// if (gWindow)
// ActivateWindow(gWindow, true);
// FinishCarbonModalDialog();
// *done = true;
//
// break;
//
// case 'MVrc': // Record Movie...
// StartCarbonModalDialog();
// isok = SNES9X_RecordMovie();
// if (gWindow)
// ActivateWindow(gWindow, true);
// FinishCarbonModalDialog();
// *done = true;
//
// break;
//
// case 'MVpl': // Play Movie...
// StartCarbonModalDialog();
// isok = SNES9X_PlayMovie();
// if (isok && (macPlayFlag & 0x2))
// {
// running = false;
// isok = SNES9X_QTMovieRecord();
// running = true;
// }
//
// if (gWindow)
// ActivateWindow(gWindow, true);
// FinishCarbonModalDialog();
// *done = true;
//
// break;
//
// case 'QTmv': // Record QuickTime Movie...
// StartCarbonModalDialog();
// isok = SNES9X_QTMovieRecord();
// if (gWindow)
// ActivateWindow(gWindow, true);
// FinishCarbonModalDialog();
// *done = true;
//
// break;
//
// case 'Ospc': // Save SPC File at Next Note-on
// S9xDumpSPCSnapshot();
//
// break;
//
// case 'Osrm': // Save SRAM Now
// SNES9X_SaveSRAM();
//
// break;
//
// case 'Ombx': // Music Box
// StartCarbonModalDialog();
// MusicBoxDialog();
// FinishCarbonModalDialog();
//
// break;
//
// case 'Nser': // Server...
// bool8 sr;
//
// Settings.NetPlay = false;
// Settings.NetPlayServer = false;
//
// NPServerInit();
//
// if (!NPServerStartServer(NP_PORT))
// {
// NPServerStopServer();
// break;
// }
//
// StartCarbonModalDialog();
// sr = NPServerDialog();
// FinishCarbonModalDialog();
//
// if (sr)
// {
// SNES9X_Reset();
// SNES9X_Go();
// Settings.NetPlay = true;
// Settings.NetPlayServer = true;
//
// *done = true;
// }
// else
// NPServerStopServer();
//
// break;
//
// case 'Ncli': // Client...
// bool8 cr;
//
// Settings.NetPlay = false;
// Settings.NetPlayServer = false;
//
// NPClientInit();
//
// StartCarbonModalDialog();
// cr = NPClientDialog();
// FinishCarbonModalDialog();
//
// if (cr)
// {
// SNES9X_Go();
// Settings.NetPlay = true;
// Settings.NetPlayServer = false;
//
// *done = true;
// }
// else
// AdjustMenus();
//
// break;
//
// case 'CPr1': // Controller Preset
// case 'CPr2':
// case 'CPr3':
// case 'CPr4':
// case 'CPr5':
// item = (int) (command & 0x000000FF) - (int) '0';
// err = GetMenuItemHierarchicalMenu(GetMenuRef(mControl), iISpPreset, &mh);
// CheckMenuItem(mh, padSetting, false);
// padSetting = item;
// CheckMenuItem(mh, padSetting, true);
// ClearPadSetting();
// LoadControllerSettings();
//
// break;
//
// case 'EIp1': // Input Device
// case 'EIp2':
// case 'EIp3':
// case 'EIp4':
// case 'EIp5':
// case 'EIp6':
// case 'EIp7':
// case 'EIp8':
// item = (int) (command & 0x000000FF) - (int) '0';
// err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &mh);
// CheckMenuItem(mh, deviceSetting, false);
// deviceSetting = item;
// deviceSettingMaster = deviceSetting;
// CheckMenuItem(mh, deviceSetting, true);
// ChangeInputDevice();
//
// break;
//
// default:
// result = eventNotHandledErr;
// break;
// }
// }
//
// return (result);
//}
//
void ChangeInputDevice (void)
{
switch (deviceSetting)
{
case iPad:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
macControllerOption = SNES_JOYPAD;
break;
case iMouse:
S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0);
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
macControllerOption = SNES_MOUSE;
break;
case iMouse2:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0);
macControllerOption = SNES_MOUSE_SWAPPED;
break;
case iSuperScope:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0);
macControllerOption = SNES_SUPERSCOPE;
break;
case iMultiPlayer5:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_MP5, 1, 2, 3, 4);
macControllerOption = SNES_MULTIPLAYER5;
break;
case iMultiPlayer5_2:
S9xSetController(0, CTL_MP5, 0, 1, 2, 3);
S9xSetController(1, CTL_MP5, 4, 5, 6, 7);
macControllerOption = SNES_MULTIPLAYER5_2;
break;
case iJustifier1:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0);
macControllerOption = SNES_JUSTIFIER;
break;
case iJustifier2:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0);
macControllerOption = SNES_JUSTIFIER_2;
break;
}
}
//
void ApplyNSRTHeaderControllers (void)
{
// OSStatus err;
// MenuRef menu;
//
// err = GetMenuItemHierarchicalMenu(GetMenuRef(mEmulation), iDevice, &menu);
// if (err)
// return;
//
// for (int i = 1; i <= CountMenuItems(menu); i++)
// {
// CheckMenuItem(menu, i, false);
// SetItemStyle(menu, i, normal);
// }
//
// deviceSetting = deviceSettingMaster;
//
// uint32 valid = 0;
//
// if (!strncmp((const char *) Memory.NSRTHeader + 24, "NSRT", 4))
// {
// switch (Memory.NSRTHeader[29])
// {
// case 0x00: // Everything goes
// deviceSetting = iPad;
// valid = (1 << iPad);
// break;
//
// case 0x10: // Mouse in Port 0
// deviceSetting = iMouse;
// valid = (1 << iMouse);
// break;
//
// case 0x01: // Mouse in Port 1
// deviceSetting = iMouse2;
// valid = (1 << iMouse2);
// break;
//
// case 0x03: // Super Scope in Port 1
// deviceSetting = iSuperScope;
// valid = (1 << iSuperScope);
// break;
//
// case 0x06: // Multitap in Port 1
// deviceSetting = iMultiPlayer5;
// valid = (1 << iPad) | (1 << iMultiPlayer5);
// break;
//
// case 0x66: // Multitap in Ports 0 and 1
// deviceSetting = iMultiPlayer5_2;
// valid = (1 << iPad) | (1 << iMultiPlayer5) | (1 << iMultiPlayer5_2);
// break;
//
// case 0x08: // Multitap in Port 1, Mouse in new Port 1
// deviceSetting = iMouse2;
// valid = (1 << iPad) | (1 << iMouse2) | (1 << iMultiPlayer5);
// break;
//
// case 0x04: // Pad or Super Scope in Port 1
// deviceSetting = iSuperScope;
// valid = (1 << iPad) | (1 << iSuperScope);
// break;
//
// case 0x05: // Justifier - Must ask user...
// deviceSetting = iJustifier1;
// valid = (1 << iJustifier1) | (1 << iJustifier2);
// break;
//
// case 0x20: // Pad or Mouse in Port 0
// deviceSetting = iMouse;
// valid = (1 << iPad) | (1 << iMouse);
// break;
//
// case 0x22: // Pad or Mouse in Port 0 & 1
// deviceSetting = iMouse;
// valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2);
// break;
//
// case 0x24: // Pad or Mouse in Port 0, Pad or Super Scope in Port 1
// deviceSetting = iSuperScope;
// valid = (1 << iPad) | (1 << iMouse) | (1 << iSuperScope);
// break;
//
// case 0x27: // Pad or Mouse in Port 0, Pad or Mouse or Super Scope in Port 1
// deviceSetting = iSuperScope;
// valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2) | (1 << iSuperScope);
// break;
//
// case 0x99: // Lasabirdie
// break;
//
// case 0x0A: // Barcode Battler
// break;
//
// default:
// break;
// }
// }
//
// CheckMenuItem(menu, deviceSetting, true);
//
// for (int i = 1; i <= CountMenuItems(menu); i++)
// {
// if (valid & (1 << i))
// SetItemStyle(menu, i, underline);
// }
//
// ChangeInputDevice();
}
//
int PromptFreezeDefrost (Boolean freezing)
{
// OSStatus err;
// CGContextRef ctx;
// CGColorSpaceRef color;
// CGDataProviderRef prov;
// CGImageRef image;
// CGRect rct;
// CGPoint pt;
// CFURLRef url;
// FSCatalogInfo info;
// FSRef ref;
// KeyMap keys;
// UInt64 newestDate, currentDate;
// UInt32 startTime;
// float x, y, textw;
// int result, newestIndex, current_selection, oldInactiveMode;
// char dateC[256];
// uint8 *back, *draw;
//
// const UInt32 repeatDelay = 10;
// const int w = SNES_WIDTH << 1, h = kMacWindowHeight;
// const char letters[] = "123456789ABC", *filename;
// const uint8 keyCheck[] = { kmEscKey, km1Key, km2Key, km3Key, km4Key, km5Key, km6Key, km7Key, km8Key, km9Key, kmAKey, kmBKey, kmCKey };
//
// if (!directDisplay)
// {
// S9xInitDisplay(NULL, NULL);
// SNES9X_Go();
// }
//
// frzselecting = true;
// oldInactiveMode = inactiveMode;
// if (inactiveMode == 3)
// inactiveMode = 2;
//
// S9xSetSoundMute(true);
//
// back = (uint8 *) malloc(w * h * 2);
// draw = (uint8 *) malloc(w * h * 2);
// if (!back || !draw)
// QuitWithFatalError(@"os 04");
//
// color = CGColorSpaceCreateDeviceRGB();
// if (!color)
// QuitWithFatalError(@"os 05");
//
// ctx = CGBitmapContextCreate(back, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0));
// if (!ctx)
// QuitWithFatalError(@"os 06");
//
// rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h);
// CGContextClearRect(ctx, rct);
//
// image = NULL;
//
// if (freezing)
// url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_freeze"), CFSTR("png"), NULL);
// else
// url = CFBundleCopyResourceURL(CFBundleGetMainBundle(), CFSTR("logo_defrost"), CFSTR("png"), NULL);
// if (url)
// {
// prov = CGDataProviderCreateWithURL(url);
// if (prov)
// {
// image = CGImageCreateWithPNGDataProvider(prov, NULL, true, kCGRenderingIntentDefault);
// CGDataProviderRelease(prov);
// }
//
// CFRelease(url);
// }
//
// if (image)
// {
// rct = CGRectMake(0.0f, (float) h - 118.0f, 512.0f, 118.0f);
// CGContextDrawImage(ctx, rct, image);
// CGImageRelease(image);
// }
//
// newestDate = 0;
// newestIndex = -1;
//
// CGContextSetLineJoin(ctx, kCGLineJoinRound);
//
// rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f);
//
// for (int count = 0; count < 12; count++)
// {
// filename = S9xGetFreezeFilename(count);
// err = FSPathMakeRef((unsigned char *) filename, &ref, NULL);
// if (err == noErr)
// {
// err = FSGetCatalogInfo(&ref, kFSCatInfoContentMod, &info, NULL, NULL, NULL);
// currentDate = (((UInt64) info.contentModDate.highSeconds << 48) | ((UInt64) info.contentModDate.lowSeconds << 16) | (UInt64) info.contentModDate.fraction);
//
// if (currentDate > newestDate)
// {
// newestIndex = count;
// newestDate = currentDate;
// }
//
// DrawThumbnailFromExtendedAttribute(filename, ctx, rct);
//
// CGContextSetShouldAntialias(ctx, false);
// CGContextSetLineWidth(ctx, 1.0f);
//
// CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f);
// x = rct.origin.x + 127.0f;
// y = rct.origin.y + 119.0f;
// CGContextBeginPath(ctx);
// CGContextMoveToPoint(ctx, x, y);
// CGContextAddLineToPoint(ctx, x, y - 119.0f);
// CGContextAddLineToPoint(ctx, x - 127.0f, y - 119.0f);
// CGContextStrokePath(ctx);
//
// CGContextSetShouldAntialias(ctx, true);
// CGContextSetLineWidth(ctx, 3.0f);
//
// CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman);
// x = rct.origin.x + 5.0f;
// y = rct.origin.y + 107.0f;
// CGContextSetTextDrawingMode(ctx, kCGTextStroke);
// CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f);
// CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1);
// CGContextSetTextDrawingMode(ctx, kCGTextFill);
// CGContextSetRGBFillColor(ctx, 1.0f, 0.7f, 0.7f, 1.0f);
// CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1);
//
// if (showtimeinfrz)
// {
// CFAbsoluteTime at;
// CFDateFormatterRef format;
// CFLocaleRef locale;
// CFStringRef datstr;
// Boolean r;
//
// err = UCConvertUTCDateTimeToCFAbsoluteTime(&(info.contentModDate), &at);
// locale = CFLocaleCopyCurrent();
// format = CFDateFormatterCreate(kCFAllocatorDefault, locale, kCFDateFormatterShortStyle, kCFDateFormatterMediumStyle);
// datstr = CFDateFormatterCreateStringWithAbsoluteTime(kCFAllocatorDefault, format, at);
// r = CFStringGetCString(datstr, dateC, sizeof(dateC), CFStringGetSystemEncoding());
// CFRelease(datstr);
// CFRelease(format);
// CFRelease(locale);
//
// CGContextSelectFont(ctx, "Helvetica", 10.0f, kCGEncodingMacRoman);
// x = rct.origin.x + 20.0f;
// y = rct.origin.y + 107.0f;
// CGContextSetTextDrawingMode(ctx, kCGTextInvisible);
// CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC));
// pt = CGContextGetTextPosition(ctx);
// textw = pt.x - x;
// x = rct.origin.x + 122.0f - textw;
// CGContextSetTextDrawingMode(ctx, kCGTextStroke);
// CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 0.8f);
// CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC));
// CGContextSetTextDrawingMode(ctx, kCGTextFill);
// CGContextSetRGBFillColor(ctx, 1.0f, 1.0f, 1.0f, 1.0f);
// CGContextShowTextAtPoint(ctx, x, y, dateC, strlen(dateC));
// }
// }
// else
// {
// CGContextSelectFont(ctx, "Helvetica", 12.0f, kCGEncodingMacRoman);
// x = rct.origin.x + 5.0f;
// y = rct.origin.y + 107.0f;
// CGContextSetTextDrawingMode(ctx, kCGTextFill);
// CGContextSetRGBFillColor(ctx, 0.7f, 0.7f, 0.7f, 1.0f);
// CGContextShowTextAtPoint(ctx, x, y, &letters[count], 1);
// }
//
// if ((count % 4) == 3)
// rct = CGRectOffset(rct, -128.0f * 3.0f, -120.0f);
// else
// rct = CGRectOffset(rct, 128.0f, 0.0f);
// }
//
// if (newestIndex < 0)
// newestIndex = 0;
//
// CGContextRelease(ctx);
//
// image = NULL;
//
// prov = CGDataProviderCreateWithData(NULL, back, w * h * 2, NULL);
// if (prov)
// {
// image = CGImageCreate(w, h, 5, 16, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0), prov, NULL, 0, kCGRenderingIntentDefault);
// CGDataProviderRelease(prov);
// }
//
// if (!image)
// QuitWithFatalError(@"os 07");
//
// ctx = CGBitmapContextCreate(draw, w, h, 5, w * 2, color, kCGImageAlphaNoneSkipFirst | ((systemVersion >= 0x1040) ? kCGBitmapByteOrder16Host : 0));
// if (!ctx)
// QuitWithFatalError(@"os 08");
//
// CGContextSetShouldAntialias(ctx, false);
//
// UpdateFreezeDefrostScreen(newestIndex, image, draw, ctx);
//
// CocoaPlayFreezeDefrostSound();
//
// result = -2;
// current_selection = newestIndex;
//
// do
// {
// if (!rejectinput)
// {
// CopyPressedKeys(keys);
//
// for (int count = 0; count <= 12; count++)
// {
// while (KeyIsPressed(keys, keyCheck[count]))
// {
// result = count - 1;
// CopyPressedKeys(keys);
// }
// }
//
// while (KeyIsPressed(keys, keyCode[k1PRight]))
// {
// startTime = TickCount();
// current_selection += 1;
// if (current_selection > 11)
// current_selection -= 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// while (KeyIsPressed(keys, keyCode[k1PRight]) && (TickCount() < (startTime + repeatDelay)))
// CopyPressedKeys(keys);
// }
//
// while (KeyIsPressed(keys, keyCode[k1PLeft]))
// {
// startTime = TickCount();
// current_selection -= 1;
// if (current_selection < 0)
// current_selection += 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// while (KeyIsPressed(keys, keyCode[k1PLeft]) && (TickCount() < (startTime + repeatDelay)))
// CopyPressedKeys(keys);
// }
//
// while (KeyIsPressed(keys, keyCode[k1PDown]))
// {
// startTime = TickCount();
// current_selection += 4;
// if (current_selection > 11)
// current_selection -= 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// while (KeyIsPressed(keys, keyCode[k1PDown]) && (TickCount() < (startTime + repeatDelay)))
// CopyPressedKeys(keys);
// }
//
// while (KeyIsPressed(keys, keyCode[k1PUp]))
// {
// startTime = TickCount();
// current_selection -= 4;
// if (current_selection < 0)
// current_selection += 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// while (KeyIsPressed(keys, keyCode[k1PUp]) && (TickCount() < (startTime + repeatDelay)))
// CopyPressedKeys(keys);
// }
//
// while (KeyIsPressed(keys, keyCode[k1PA] ) ||
// KeyIsPressed(keys, keyCode[k2PA] ) ||
// KeyIsPressed(keys, keyCode[k1PB] ) ||
// KeyIsPressed(keys, keyCode[k2PB] ) ||
// KeyIsPressed(keys, keyCode[k1PX] ) ||
// KeyIsPressed(keys, keyCode[k2PX] ) ||
// KeyIsPressed(keys, keyCode[k1PY] ) ||
// KeyIsPressed(keys, keyCode[k2PY] ) ||
// KeyIsPressed(keys, keyCode[k1PStart] ) ||
// KeyIsPressed(keys, keyCode[k2PStart] ) ||
// KeyIsPressed(keys, keyCode[k1PSelect]) ||
// KeyIsPressed(keys, keyCode[k2PSelect]))
// {
// CopyPressedKeys(keys);
// result = current_selection;
// }
//
// uint32 pad1, pad2;
//
// while (ISpKeyIsPressed(kISpEsc ) ||
// ISpKeyIsPressed(kISp1PStart) ||
// ISpKeyIsPressed(kISp2PStart))
// result = -1;
//
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// while ((pad1 & 0x0100) || (pad2 & 0x0100)) // Rt
// {
// startTime = TickCount();
// current_selection += 1;
// if (current_selection > 11)
// current_selection -= 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// do
// {
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// } while (((pad1 & 0x0100) || (pad2 & 0x0100)) && (TickCount() < (startTime + repeatDelay)));
// }
//
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// while ((pad1 & 0x0200) || (pad2 & 0x0200)) // Lf
// {
// startTime = TickCount();
// current_selection -= 1;
// if (current_selection < 0)
// current_selection += 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// do
// {
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// } while (((pad1 & 0x0200) || (pad2 & 0x0200)) && (TickCount() < (startTime + repeatDelay)));
// }
//
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// while ((pad1 & 0x0800) || (pad2 & 0x0800)) // Up
// {
// startTime = TickCount();
// current_selection -= 4;
// if (current_selection < 0)
// current_selection += 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// do
// {
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// } while (((pad1 & 0x0800) || (pad2 & 0x0800)) && (TickCount() < (startTime + repeatDelay)));
// }
//
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// while ((pad1 & 0x0400) || (pad2 & 0x0400)) // Dn
// {
// startTime = TickCount();
// current_selection += 4;
// if (current_selection > 11)
// current_selection -= 12;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// do
// {
// pad1 = pad2 = 0;
// JoypadScanDirection(0, &pad1);
// JoypadScanDirection(1, &pad2);
// } while (((pad1 & 0x0400) || (pad2 & 0x0400)) && (TickCount() < (startTime + repeatDelay)));
// }
//
// while (ISpKeyIsPressed(kISp1PA) ||
// ISpKeyIsPressed(kISp2PA) ||
// ISpKeyIsPressed(kISp1PB) ||
// ISpKeyIsPressed(kISp2PB) ||
// ISpKeyIsPressed(kISp1PX) ||
// ISpKeyIsPressed(kISp2PX) ||
// ISpKeyIsPressed(kISp1PY) ||
// ISpKeyIsPressed(kISp2PY))
// result = current_selection;
// }
//
// usleep(30000);
//
// windowResizeCount = 2;
// UpdateFreezeDefrostScreen(current_selection, image, draw, ctx);
// } while (result == -2);
//
// CocoaPlayFreezeDefrostSound();
//
// CGContextRelease(ctx);
// CGImageRelease(image);
// CGColorSpaceRelease(color);
// free(draw);
// free(back);
//
// S9xSetSoundMute(false);
//
// inactiveMode = oldInactiveMode;
// frzselecting = false;
//
// windowResizeCount = 2;
//
// return (result);
return true;
}
//
//static void UpdateFreezeDefrostScreen (int newIndex, CGImageRef image, uint8 *draw, CGContextRef ctx)
//{
// if (newIndex >= 0 && newIndex < 12)
// {
// CGRect rct;
// const int w = SNES_WIDTH << 1, h = kMacWindowHeight;
//
// CGContextSetLineWidth(ctx, 1.0f);
//
// rct = CGRectMake(0.0f, 0.0f, (float) w, (float) h);
// CGContextDrawImage(ctx, rct, image);
//
// rct = CGRectMake(0.0f, (float) h - 238.0f, 128.0f, 120.0f);
// rct = CGRectOffset(rct, (float) (128 * (newIndex % 4)), (float) (-120 * (newIndex / 4)));
// rct.size.width -= 1.0f;
// rct.size.height -= 1.0f;
//
// CGContextSetRGBStrokeColor(ctx, 1.0f, 1.0f, 0.0f, 1.0f);
// CGContextStrokeRect(ctx, rct);
// rct = CGRectInset(rct, 1.0f, 1.0f);
// CGContextSetRGBStrokeColor(ctx, 0.0f, 0.0f, 0.0f, 1.0f);
// CGContextStrokeRect(ctx, rct);
// }
//
// DrawFreezeDefrostScreen(draw);
//}
//
static void ProcessInput (void)
{
bool8 myKeys[MAC_NUM_KEYCODES];
bool8 isok, fnbtn, altbtn, tcbtn;
static bool8 toggleff = false, lastTimeTT = false, lastTimeFn = false, ffUp = false, ffDown = false, ffUpSp = false, ffDownSp = false;
if (rejectinput)
return;
if (ISpKeyIsPressed(kISpEsc))
{
if (!s9xthreadrunning)
running = false;
return;
}
if (ISpKeyIsPressed(kISpFreeze))
{
MacStopSound();
while (ISpKeyIsPressed(kISpFreeze));
isok = SNES9X_Freeze();
os_unfair_lock_lock(&renderLock);
ClearGFXScreen();
os_unfair_lock_unlock(&renderLock);
return;
}
if (ISpKeyIsPressed(kISpDefrost))
{
MacStopSound();
while (ISpKeyIsPressed(kISpDefrost));
isok = SNES9X_Defrost();
os_unfair_lock_lock(&renderLock);
ClearGFXScreen();
os_unfair_lock_unlock(&renderLock);
return;
}
if (ISpKeyIsPressed(kISpScreenshot))
{
Settings.TakeScreenshot = true;
while (ISpKeyIsPressed(kISpScreenshot));
}
if (ISpKeyIsPressed(kISpSPC))
{
S9xDumpSPCSnapshot();
while (ISpKeyIsPressed(kISpSPC));
}
if (ISpKeyIsPressed(kISpFFUp))
{
if (!ffUpSp)
{
ChangeTurboRate(+1);
ffUpSp = true;
}
}
else
ffUpSp = false;
if (ISpKeyIsPressed(kISpFFDown))
{
if (!ffDownSp)
{
ChangeTurboRate(-1);
ffDownSp = true;
}
}
else
ffDownSp = false;
controlPad[0] = controlPad[1] = 0;
JoypadScanDirection(0, &(controlPad[0]));
if (ISpKeyIsPressed(kISp1PR )) controlPad[0] |= 0x0010;
if (ISpKeyIsPressed(kISp1PL )) controlPad[0] |= 0x0020;
if (ISpKeyIsPressed(kISp1PX )) controlPad[0] |= 0x0040;
if (ISpKeyIsPressed(kISp1PA )) controlPad[0] |= 0x0080;
if (ISpKeyIsPressed(kISp1PStart )) controlPad[0] |= 0x1000;
if (ISpKeyIsPressed(kISp1PSelect)) controlPad[0] |= 0x2000;
if (ISpKeyIsPressed(kISp1PY )) controlPad[0] |= 0x4000;
if (ISpKeyIsPressed(kISp1PB )) controlPad[0] |= 0x8000;
JoypadScanDirection(1, &(controlPad[1]));
if (ISpKeyIsPressed(kISp2PR )) controlPad[1] |= 0x0010;
if (ISpKeyIsPressed(kISp2PL )) controlPad[1] |= 0x0020;
if (ISpKeyIsPressed(kISp2PX )) controlPad[1] |= 0x0040;
if (ISpKeyIsPressed(kISp2PA )) controlPad[1] |= 0x0080;
if (ISpKeyIsPressed(kISp2PStart )) controlPad[1] |= 0x1000;
if (ISpKeyIsPressed(kISp2PSelect)) controlPad[1] |= 0x2000;
if (ISpKeyIsPressed(kISp2PY )) controlPad[1] |= 0x4000;
if (ISpKeyIsPressed(kISp2PB )) controlPad[1] |= 0x8000;
if (((macControllerOption == SNES_MULTIPLAYER5) || (macControllerOption == SNES_MULTIPLAYER5_2)) && Settings.MultiPlayer5Master)
{
controlPad[2] = controlPad[3] = controlPad[4] = 0;
JoypadScanDirection(2, &(controlPad[2]));
if (ISpKeyIsPressed(kISp3PR )) controlPad[2] |= 0x0010;
if (ISpKeyIsPressed(kISp3PL )) controlPad[2] |= 0x0020;
if (ISpKeyIsPressed(kISp3PX )) controlPad[2] |= 0x0040;
if (ISpKeyIsPressed(kISp3PA )) controlPad[2] |= 0x0080;
if (ISpKeyIsPressed(kISp3PStart )) controlPad[2] |= 0x1000;
if (ISpKeyIsPressed(kISp3PSelect)) controlPad[2] |= 0x2000;
if (ISpKeyIsPressed(kISp3PY )) controlPad[2] |= 0x4000;
if (ISpKeyIsPressed(kISp3PB )) controlPad[2] |= 0x8000;
JoypadScanDirection(3, &(controlPad[3]));
if (ISpKeyIsPressed(kISp4PR )) controlPad[3] |= 0x0010;
if (ISpKeyIsPressed(kISp4PL )) controlPad[3] |= 0x0020;
if (ISpKeyIsPressed(kISp4PX )) controlPad[3] |= 0x0040;
if (ISpKeyIsPressed(kISp4PA )) controlPad[3] |= 0x0080;
if (ISpKeyIsPressed(kISp4PStart )) controlPad[3] |= 0x1000;
if (ISpKeyIsPressed(kISp4PSelect)) controlPad[3] |= 0x2000;
if (ISpKeyIsPressed(kISp4PY )) controlPad[3] |= 0x4000;
if (ISpKeyIsPressed(kISp4PB )) controlPad[3] |= 0x8000;
JoypadScanDirection(4, &(controlPad[4]));
if (ISpKeyIsPressed(kISp5PR )) controlPad[4] |= 0x0010;
if (ISpKeyIsPressed(kISp5PL )) controlPad[4] |= 0x0020;
if (ISpKeyIsPressed(kISp5PX )) controlPad[4] |= 0x0040;
if (ISpKeyIsPressed(kISp5PA )) controlPad[4] |= 0x0080;
if (ISpKeyIsPressed(kISp5PStart )) controlPad[4] |= 0x1000;
if (ISpKeyIsPressed(kISp5PSelect)) controlPad[4] |= 0x2000;
if (ISpKeyIsPressed(kISp5PY )) controlPad[4] |= 0x4000;
if (ISpKeyIsPressed(kISp5PB )) controlPad[4] |= 0x8000;
ControlPadFlagsToS9xReportButtons(2, controlPad[2]);
ControlPadFlagsToS9xReportButtons(3, controlPad[3]);
ControlPadFlagsToS9xReportButtons(4, controlPad[4]);
if (macControllerOption == SNES_MULTIPLAYER5_2)
{
controlPad[5] = controlPad[6] = controlPad[7] = 0;
JoypadScanDirection(5, &(controlPad[5]));
if (ISpKeyIsPressed(kISp6PR )) controlPad[5] |= 0x0010;
if (ISpKeyIsPressed(kISp6PL )) controlPad[5] |= 0x0020;
if (ISpKeyIsPressed(kISp6PX )) controlPad[5] |= 0x0040;
if (ISpKeyIsPressed(kISp6PA )) controlPad[5] |= 0x0080;
if (ISpKeyIsPressed(kISp6PStart )) controlPad[5] |= 0x1000;
if (ISpKeyIsPressed(kISp6PSelect)) controlPad[5] |= 0x2000;
if (ISpKeyIsPressed(kISp6PY )) controlPad[5] |= 0x4000;
if (ISpKeyIsPressed(kISp6PB )) controlPad[5] |= 0x8000;
JoypadScanDirection(6, &(controlPad[6]));
if (ISpKeyIsPressed(kISp7PR )) controlPad[6] |= 0x0010;
if (ISpKeyIsPressed(kISp7PL )) controlPad[6] |= 0x0020;
if (ISpKeyIsPressed(kISp7PX )) controlPad[6] |= 0x0040;
if (ISpKeyIsPressed(kISp7PA )) controlPad[6] |= 0x0080;
if (ISpKeyIsPressed(kISp7PStart )) controlPad[6] |= 0x1000;
if (ISpKeyIsPressed(kISp7PSelect)) controlPad[6] |= 0x2000;
if (ISpKeyIsPressed(kISp7PY )) controlPad[6] |= 0x4000;
if (ISpKeyIsPressed(kISp7PB )) controlPad[6] |= 0x8000;
JoypadScanDirection(7, &(controlPad[7]));
if (ISpKeyIsPressed(kISp8PR )) controlPad[7] |= 0x0010;
if (ISpKeyIsPressed(kISp8PL )) controlPad[7] |= 0x0020;
if (ISpKeyIsPressed(kISp8PX )) controlPad[7] |= 0x0040;
if (ISpKeyIsPressed(kISp8PA )) controlPad[7] |= 0x0080;
if (ISpKeyIsPressed(kISp8PStart )) controlPad[7] |= 0x1000;
if (ISpKeyIsPressed(kISp8PSelect)) controlPad[7] |= 0x2000;
if (ISpKeyIsPressed(kISp8PY )) controlPad[7] |= 0x4000;
if (ISpKeyIsPressed(kISp8PB )) controlPad[7] |= 0x8000;
ControlPadFlagsToS9xReportButtons(5, controlPad[5]);
ControlPadFlagsToS9xReportButtons(6, controlPad[6]);
ControlPadFlagsToS9xReportButtons(7, controlPad[7]);
}
}
CopyPressedKeys(myKeys);
fnbtn = (KeyIsPressed(myKeys, keyCode[kKeyFunction]) || ISpKeyIsPressed(kISpFunction));
altbtn = (KeyIsPressed(myKeys, keyCode[kKeyAlt] ) || ISpKeyIsPressed(kISpAlt) );
if (fnbtn)
{
if (!lastTimeFn)
{
for (unsigned int i = 0; i < kCommandListSize; i++)
btncmd[i].held = false;
}
lastTimeFn = true;
lastTimeTT = false;
ffUp = ffDown = false;
for (unsigned int i = 0; i < kCommandListSize; i++)
{
if (KeyIsPressed(myKeys, btncmd[i].keycode))
{
if (!(btncmd[i].held))
{
btncmd[i].held = true;
if (strncmp(btncmd[i].command, "_mac", 4) == 0)
{
static char msg[64];
switch (btncmd[i].command[4] - '0')
{
case 1:
Settings.DisplayPressedKeys = !Settings.DisplayPressedKeys;
break;
case 2:
if (S9xMovieActive())
Settings.DisplayMovieFrame = !Settings.DisplayMovieFrame;
break;
case 3:
if (macFrameAdvanceRate < 5000000)
macFrameAdvanceRate += 100000;
sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000);
S9xSetInfoString(msg);
break;
case 4:
if (macFrameAdvanceRate > 500000)
macFrameAdvanceRate -= 100000;
sprintf(msg, "Emulation Speed: 100/%d", macFrameAdvanceRate / 10000);
S9xSetInfoString(msg);
break;
case 5:
pauseEmulation = !pauseEmulation;
break;
case 6:
frameAdvance = true;
break;
}
}
else
{
s9xcommand_t s9xcmd;
s9xcmd = S9xGetCommandT(btncmd[i].command);
S9xApplyCommand(s9xcmd, 1, 0);
}
}
}
else
btncmd[i].held = false;
}
}
else
{
lastTimeFn = false;
if (KeyIsPressed(myKeys, keyCode[kKeyEsc]))
{
if (!s9xthreadrunning)
running = false;
return;
}
if (KeyIsPressed(myKeys, keyCode[kKeyFreeze]))
{
MacStopSound();
while (KeyIsPressed(myKeys, keyCode[kKeyFreeze]))
CopyPressedKeys(myKeys);
isok = SNES9X_Freeze();
os_unfair_lock_lock(&renderLock);
ClearGFXScreen();
os_unfair_lock_unlock(&renderLock);
return;
}
if (KeyIsPressed(myKeys, keyCode[kKeyDefrost]))
{
MacStopSound();
while (KeyIsPressed(myKeys, keyCode[kKeyDefrost]))
CopyPressedKeys(myKeys);
isok = SNES9X_Defrost();
os_unfair_lock_lock(&renderLock);
ClearGFXScreen();
os_unfair_lock_unlock(&renderLock);
return;
}
if (KeyIsPressed(myKeys, keyCode[kKeyScreenshot]))
{
Settings.TakeScreenshot = true;
while (KeyIsPressed(myKeys, keyCode[kKeyScreenshot]))
CopyPressedKeys(myKeys);
}
if (KeyIsPressed(myKeys, keyCode[kKeySPC]))
{
S9xDumpSPCSnapshot();
while (KeyIsPressed(myKeys, keyCode[kKeySPC]))
CopyPressedKeys(myKeys);
}
if (KeyIsPressed(myKeys, keyCode[kKeyFFUp]))
{
if (!ffUp)
{
ChangeTurboRate(+1);
ffUp = true;
}
}
else
ffUp = false;
if (KeyIsPressed(myKeys, keyCode[kKeyFFDown]))
{
if (!ffDown)
{
ChangeTurboRate(-1);
ffDown = true;
}
}
else
ffDown = false;
if (KeyIsPressed(myKeys, keyCode[k1PR] )) controlPad[0] |= 0x0010;
if (KeyIsPressed(myKeys, keyCode[k1PL] )) controlPad[0] |= 0x0020;
if (KeyIsPressed(myKeys, keyCode[k1PX] )) controlPad[0] |= 0x0040;
if (KeyIsPressed(myKeys, keyCode[k1PA] )) controlPad[0] |= 0x0080;
if (KeyIsPressed(myKeys, keyCode[k1PRight] )) controlPad[0] |= 0x0100;
if (KeyIsPressed(myKeys, keyCode[k1PLeft] )) controlPad[0] |= 0x0200;
if (KeyIsPressed(myKeys, keyCode[k1PDown] )) controlPad[0] |= 0x0400;
if (KeyIsPressed(myKeys, keyCode[k1PUp] )) controlPad[0] |= 0x0800;
if (KeyIsPressed(myKeys, keyCode[k1PStart] )) controlPad[0] |= 0x1000;
if (KeyIsPressed(myKeys, keyCode[k1PSelect])) controlPad[0] |= 0x2000;
if (KeyIsPressed(myKeys, keyCode[k1PY] )) controlPad[0] |= 0x4000;
if (KeyIsPressed(myKeys, keyCode[k1PB] )) controlPad[0] |= 0x8000;
if (KeyIsPressed(myKeys, keyCode[k2PR] )) controlPad[1] |= 0x0010;
if (KeyIsPressed(myKeys, keyCode[k2PL] )) controlPad[1] |= 0x0020;
if (KeyIsPressed(myKeys, keyCode[k2PX] )) controlPad[1] |= 0x0040;
if (KeyIsPressed(myKeys, keyCode[k2PA] )) controlPad[1] |= 0x0080;
if (KeyIsPressed(myKeys, keyCode[k2PRight] )) controlPad[1] |= 0x0100;
if (KeyIsPressed(myKeys, keyCode[k2PLeft] )) controlPad[1] |= 0x0200;
if (KeyIsPressed(myKeys, keyCode[k2PDown] )) controlPad[1] |= 0x0400;
if (KeyIsPressed(myKeys, keyCode[k2PUp] )) controlPad[1] |= 0x0800;
if (KeyIsPressed(myKeys, keyCode[k2PStart] )) controlPad[1] |= 0x1000;
if (KeyIsPressed(myKeys, keyCode[k2PSelect])) controlPad[1] |= 0x2000;
if (KeyIsPressed(myKeys, keyCode[k2PY] )) controlPad[1] |= 0x4000;
if (KeyIsPressed(myKeys, keyCode[k2PB] )) controlPad[1] |= 0x8000;
if (altbtn)
{
if (!lastTimeTT)
changeAuto[0] = changeAuto[1] = 0;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 12; j++)
{
uint16 mask = 0x0010 << j;
if (controlPad[i] & mask & autofireRec[i].toggleMask)
{
controlPad[i] &= ~mask;
if (!(changeAuto[i] & mask))
{
changeAuto[i] |= mask;
ChangeAutofireSettings(i, j);
}
}
else
changeAuto[i] &= ~mask;
}
}
lastTimeTT = true;
}
else
lastTimeTT = false;
}
if (enabletoggle)
{
if ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn)
{
if (!toggleff)
{
toggleff = true;
Settings.TurboMode = !Settings.TurboMode;
S9xSetInfoString(Settings.TurboMode ? "Turbo mode on" : "Turbo mode off");
if (!Settings.TurboMode)
S9xClearSamples();
}
}
else
toggleff = false;
}
else
{
bool8 old = Settings.TurboMode;
Settings.TurboMode = ((ISpKeyIsPressed(kISpFastForward) || KeyIsPressed(myKeys, keyCode[kKeyFastForward])) && !fnbtn) ? true : false;
if (!Settings.TurboMode && old)
S9xClearSamples();
}
for (int i = 0; i < 2; i++)
controlPad[i] ^= autofireRec[i].invertMask;
if (autofire)
{
long long currentTime;
uint16 changeMask;
currentTime = GetMicroseconds();
tcbtn = (KeyIsPressed(myKeys, keyCode[kKeyTC]) || ISpKeyIsPressed(kISpTC));
for (int i = 0; i < 2; i++)
{
changeMask = (lastTimeTT ? (~changeAuto[i]) : 0xFFFF);
for (int j = 0; j < 12; j++)
{
uint16 mask = (0x0010 << j) & changeMask;
if (autofireRec[i].tcMask & mask)
{
if (!tcbtn)
continue;
}
if (autofireRec[i].buttonMask & mask)
{
if (controlPad[i] & mask)
{
if (currentTime > autofireRec[i].nextTime[j])
{
if (Settings.TurboMode)
autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0 / macFastForwardRate);
else
autofireRec[i].nextTime[j] = currentTime + (long long) ((1.0 / (float) autofireRec[i].frequency) * 1000000.0);
}
else
controlPad[i] &= ~mask;
}
}
}
}
}
ControlPadFlagsToS9xReportButtons(0, controlPad[0]);
ControlPadFlagsToS9xReportButtons(1, controlPad[1]);
if (macControllerOption == SNES_JUSTIFIER_2)
ControlPadFlagsToS9xPseudoPointer(controlPad[1]);
}
static void ChangeAutofireSettings (int player, int btn)
{
static char msg[64];
uint16 mask, m;
mask = 0x0010 << btn;
autofireRec[player].buttonMask ^= mask;
autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask);
m = autofireRec[player].buttonMask;
if (m)
snprintf(msg, sizeof(msg), "Autofire %d:%s%s%s%s%s%s%s%s%s%s%s%s%s", player + 1,
(m & 0xC0F0 ? " " : ""),
(m & 0x0080 ? "A" : ""),
(m & 0x8000 ? "B" : ""),
(m & 0x0040 ? "X" : ""),
(m & 0x4000 ? "Y" : ""),
(m & 0x0020 ? "L" : ""),
(m & 0x0010 ? "R" : ""),
(m & 0x0800 ? " Up" : ""),
(m & 0x0400 ? " Dn" : ""),
(m & 0x0200 ? " Lf" : ""),
(m & 0x0100 ? " Rt" : ""),
(m & 0x1000 ? " St" : ""),
(m & 0x2000 ? " Se" : ""));
else
snprintf(msg, sizeof(msg), "Autofire %d: Off", player + 1);
S9xSetInfoString(msg);
}
static void ChangeTurboRate (int d)
{
static char msg[64];
macFastForwardRate += d;
if (macFastForwardRate < 1)
macFastForwardRate = 1;
else
if (macFastForwardRate > 15)
macFastForwardRate = 15;
snprintf(msg, sizeof(msg), "Turbo Rate: %d", macFastForwardRate);
S9xSetInfoString(msg);
}
void GetGameScreenPointer (int16 *x, int16 *y, bool fullmouse)
{
int ph;
ph = !drawoverscan ? ((IPPU.RenderedScreenHeight > 256) ? IPPU.RenderedScreenHeight : (IPPU.RenderedScreenHeight << 1)) : (SNES_HEIGHT_EXTENDED << 1);
if (fullscreen)
{
if (glstretch)
{
float fpw = (float) glScreenH / (float) ph * 512.0f;
scopeViewInfo.width = (int) (fpw + ((float) glScreenW - fpw) * (float) macAspectRatio / 10000.0);
scopeViewInfo.height = glScreenH;
scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - scopeViewInfo.width) >> 1);
scopeViewInfo.globalTop = (int) glScreenBounds.origin.y;
}
else
{
scopeViewInfo.width = 512;
scopeViewInfo.height = ph;
scopeViewInfo.globalLeft = (int) glScreenBounds.origin.x + ((glScreenW - 512) >> 1);
scopeViewInfo.globalTop = (int) glScreenBounds.origin.y + ((glScreenH - ph ) >> 1);
}
}
else
{
CGRect frame = s9xView.frame;
frame = [s9xView convertRect:frame toView:nil];
frame = [s9xView.window convertRectToScreen:frame];
scopeViewInfo.width = frame.size.width;
scopeViewInfo.globalLeft = frame.origin.x;
if (windowExtend)
{
scopeViewInfo.height = ph * frame.size.height / kMacWindowHeight;
scopeViewInfo.globalTop = frame.origin.y + ((kMacWindowHeight - ph) >> 1) * frame.size.height / kMacWindowHeight;
}
else
{
scopeViewInfo.height = frame.size.height;
scopeViewInfo.globalTop = frame.origin.y;
}
}
if (!fullmouse)
{
CGPoint point = [NSEvent mouseLocation];
*x = (int16) (((float) (point.x - scopeViewInfo.globalLeft)) / ((float) scopeViewInfo.width ) * (float) IPPU.RenderedScreenWidth);
*y = (int16) (((float) (point.y - scopeViewInfo.globalTop )) / ((float) scopeViewInfo.height) * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED));
}
else
{
*x = (int16) (unlimitedCursor.x / (float) scopeViewInfo.width * (float) IPPU.RenderedScreenWidth);
*y = (int16) (unlimitedCursor.y / (float) scopeViewInfo.height * (float) (!drawoverscan ? IPPU.RenderedScreenHeight : SNES_HEIGHT_EXTENDED));
}
}
static void Initialize (void)
{
bzero(&Settings, sizeof(Settings));
Settings.MouseMaster = true;
Settings.SuperScopeMaster = true;
Settings.JustifierMaster = true;
Settings.MultiPlayer5Master = true;
Settings.FrameTimePAL = 20000;
Settings.FrameTimeNTSC = 16667;
Settings.SixteenBitSound = true;
Settings.Stereo = true;
Settings.SoundPlaybackRate = 32000;
Settings.SoundInputRate = 31950;
Settings.SupportHiRes = true;
Settings.Transparency = true;
Settings.AutoDisplayMessages = true;
Settings.InitialInfoStringTimeout = 120;
Settings.HDMATimingHack = 100;
Settings.BlockInvalidVRAMAccessMaster = true;
Settings.StopEmulation = true;
Settings.WrongMovieStateProtection = true;
Settings.DumpStreamsMaxFrames = -1;
Settings.StretchScreenshots = 1;
Settings.SnapshotScreenshots = true;
Settings.OpenGLEnable = true;
Settings.SuperFXClockMultiplier = 100;
Settings.InterpolationMethod = DSP_INTERPOLATION_GAUSSIAN;
Settings.MaxSpriteTilesPerLine = 34;
Settings.OneClockCycle = 6;
Settings.OneSlowClockCycle = 8;
Settings.TwoClockCycles = 12;
mach_timebase_info_data_t info;
mach_timebase_info(&info);
machTimeNumerator = info.numer;
machTimeDenominator = info.denom * 1000;
for (int a = 0; a < kWindowCount; a++)
{
windowPos[a].h = 40;
windowPos[a].v = 80;
windowSize[a].width = -1.0f;
windowSize[a].height = -1.0f;
}
extraOptions.benchmark = false;
extraOptions.glForceNoTextureRectangle = false;
extraOptions.glUseClientStrageApple = true;
extraOptions.glUseTexturePriority = false;
extraOptions.glStorageHint = 2;
npServerIP[0] = 0;
npName[0] = 0;
saveFolderPath = NULL;
CreateIconImages();
InitAppleEvents();
InitKeyboard();
InitAutofire();
InitCheatFinder();
LoadPrefs();
InitGraphics();
InitMacSound();
SetUpHID();
InitMultiCart();
autofire = (autofireRec[0].buttonMask || autofireRec[1].buttonMask) ? true : false;
for (int a = 0; a < MAC_MAX_PLAYERS; a++)
for (int b = 0; b < 12; b++)
autofireRec[a].nextTime[b] = 0;
S9xMovieInit();
S9xUnmapAllControls();
S9xSetupDefaultKeymap();
ChangeInputDevice();
if (!Memory.Init() || !S9xInitAPU() || !S9xGraphicsInit())
{
}
frzselecting = false;
S9xSetControllerCrosshair(X_MOUSE1, 0, NULL, NULL);
S9xSetControllerCrosshair(X_MOUSE2, 0, NULL, NULL);
InitCoreImage();
InitCoreImageFilter();
}
static void Deinitialize (void)
{
DeinitCoreImageFilter();
DeinitCoreImage();
deviceSetting = deviceSettingMaster;
DeinitMultiCart();
SavePrefs();
ReleaseHID();
DeinitCheatFinder();
DeinitGraphics();
DeinitKeyboard();
DeinitMacSound();
DeinitAppleEvents();
ReleaseIconImages();
S9xGraphicsDeinit();
S9xDeinitAPU();
Memory.Deinit();
}
uint64 GetMicroseconds(void)
{
uint64 ms = mach_absolute_time();
ms *= machTimeNumerator;
ms /= machTimeDenominator;
return ms;
}
static void InitAutofire (void)
{
autofire = false;
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 12; j++)
autofireRec[i].nextTime[j] = 0;
autofireRec[i].buttonMask = 0x0000;
autofireRec[i].toggleMask = 0xFFF0;
autofireRec[i].tcMask = 0x0000;
autofireRec[i].invertMask = 0x0000;
autofireRec[i].frequency = 10;
}
}
void S9xSyncSpeed (void)
{
long long currentFrame, adjustment;
if (directDisplay)
{
if (extraOptions.benchmark)
IPPU.RenderThisFrame = true;
else
{
if (Settings.SoundSync)
{
while (!S9xSyncSound())
usleep(0);
}
if (!macQTRecord)
{
if (macFrameSkip < 0) // auto skip
{
skipFrames--;
if (skipFrames <= 0)
{
adjustment = (Settings.TurboMode ? (macFrameAdvanceRate / macFastForwardRate) : macFrameAdvanceRate) / Memory.ROMFramesPerSecond;
currentFrame = GetMicroseconds();
skipFrames = (int32) ((currentFrame - lastFrame) / adjustment);
lastFrame += frameCount * adjustment;
if (skipFrames < 1)
skipFrames = 1;
else
if (skipFrames > 7)
{
skipFrames = 7;
lastFrame = GetMicroseconds();
}
frameCount = skipFrames;
if (lastFrame > currentFrame)
usleep((useconds_t) (lastFrame - currentFrame));
IPPU.RenderThisFrame = true;
}
else
IPPU.RenderThisFrame = false;
}
else // constant
{
skipFrames--;
if (skipFrames <= 0)
{
adjustment = macFrameAdvanceRate * macFrameSkip / Memory.ROMFramesPerSecond;
currentFrame = GetMicroseconds();
if (currentFrame - lastFrame < adjustment)
{
usleep((useconds_t) (adjustment + lastFrame - currentFrame));
currentFrame = GetMicroseconds();
}
lastFrame = currentFrame;
skipFrames = macFrameSkip;
if (Settings.TurboMode)
skipFrames *= macFastForwardRate;
IPPU.RenderThisFrame = true;
}
else
IPPU.RenderThisFrame = false;
}
}
else
{
//MacQTRecordFrame(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
adjustment = macFrameAdvanceRate / Memory.ROMFramesPerSecond;
currentFrame = GetMicroseconds();
if (currentFrame - lastFrame < adjustment)
usleep((useconds_t) (adjustment + lastFrame - currentFrame));
lastFrame = currentFrame;
IPPU.RenderThisFrame = true;
}
}
}
else
IPPU.RenderThisFrame = false;
}
void S9xAutoSaveSRAM (void)
{
SNES9X_SaveSRAM();
}
void S9xMessage (int type, int number, const char *message)
{
static char mes[256];
if (!onscreeninfo)
{
printf("%s\n", message);
// if ((type == S9X_INFO) && (number == S9X_ROM_INFO))
// if (strstr(message, "checksum ok") == NULL)
// AppearanceAlert(kAlertCautionAlert, kS9xMacAlertkBadRom, kS9xMacAlertkBadRomHint);
}
else
{
strncpy(mes, message, 255);
S9xSetInfoString(mes);
}
}
const char * S9xStringInput (const char *s)
{
return (NULL);
}
void S9xToggleSoundChannel (int c)
{
static int channel_enable = 255;
if (c == 8)
channel_enable = 255;
else
channel_enable ^= 1 << c;
S9xSetSoundControl(channel_enable);
}
void S9xExit (void)
{
NSBeep();
running = false;
cartOpen = false;
}
void QuitWithFatalError ( NSString *message)
{
NSError *error = [NSError errorWithDomain:@"com.snes9x" code:0 userInfo:@{ NSLocalizedFailureReasonErrorKey: message }];
NSAlert *alert = [NSAlert alertWithError:error];
[alert runModal];
[NSApp terminate:nil];
}
@interface S9xView : NSOpenGLView
@end
@implementation S9xView
+ (void)initialize
{
keyLock = OS_UNFAIR_LOCK_INIT;
renderLock = OS_UNFAIR_LOCK_INIT;
}
- (void)keyDown:(NSEvent *)event
{
os_unfair_lock_lock(&keyLock);
pressedKeys[event.keyCode] = true;
os_unfair_lock_unlock(&keyLock);
}
- (void)keyUp:(NSEvent *)event
{
os_unfair_lock_lock(&keyLock);
pressedKeys[event.keyCode] = false;
os_unfair_lock_unlock(&keyLock);
}
- (void)drawRect:(NSRect)dirtyRect
{
os_unfair_lock_lock(&renderLock);
glScreenW = self.frame.size.width;
glScreenH = self.frame.size.height;
S9xPutImage(IPPU.RenderedScreenWidth, IPPU.RenderedScreenHeight);
os_unfair_lock_unlock(&renderLock);
}
- (void)setFrame:(NSRect)frame
{
if ( !NSEqualRects(frame, self.frame) )
{
windowResizeCount = 2;
}
}
- (BOOL)acceptsFirstResponder
{
return YES;
}
- (BOOL)canBecomeKeyView
{
return YES;
}
@end
@implementation S9xEngine
- (instancetype)init
{
if (self = [super init])
{
Initialize();
CGRect frame = NSMakeRect(0, 0, SNES_WIDTH * 2.0, kMacWindowHeight);
s9xView = [[S9xView alloc] initWithFrame:frame pixelFormat:nil];
s9xView.autoresizingMask = NSViewWidthSizable|NSViewHeightSizable;
NSWindow *window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable|NSWindowStyleMaskResizable backing:NSBackingStoreBuffered defer:NO];
window.contentView = s9xView;
window.title = @"Snes9x";
[window center];
[window makeKeyAndOrderFront:self];
}
return self;
}
- (void)dealloc
{
Deinitialize();
}
- (void) start
{
NSLog(@"Starting");
if (!finished)
{
#ifdef DEBUGGER
CPU.Flags |= DEBUG_MODE_FLAG;
S9xDoDebug();
#endif
lastFrame = GetMicroseconds();
frameCount = 0;
if (macFrameSkip < 0)
skipFrames = 3;
else
skipFrames = macFrameSkip;
S9xInitDisplay(NULL, NULL);
os_unfair_lock_lock(&renderLock);
ClearGFXScreen();
os_unfair_lock_unlock(&renderLock);
[NSThread detachNewThreadWithBlock:^
{
MacSnes9xThread(NULL);
dispatch_sync(dispatch_get_main_queue(), ^
{
if (!Settings.NetPlay || Settings.NetPlayServer)
{
SNES9X_SaveSRAM();
S9xResetSaveTimer(false);
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
}
S9xDeinitDisplay();
if (Settings.NetPlay)
{
if (!Settings.NetPlayServer)
{
// DeinitGameWindow();
cartOpen = false;
}
Settings.NetPlay = false;
Settings.NetPlayServer = false;
}
if (!finished)
{
[self start];
}
});
}];
}
}
- (BOOL)loadROM:(NSURL *)fileURL
{
if ( SNES9X_OpenCart(fileURL) )
{
SNES9X_Go();
s9xView.window.title = fileURL.lastPathComponent.stringByDeletingPathExtension;
[s9xView.window makeKeyAndOrderFront:nil];
[self start];
return YES;
}
return NO;
}
@end