Mac: Restore Mouse, SuperScope and Justifier support

This commit is contained in:
Michael Buckley 2020-12-28 21:13:01 -08:00
parent 364aa1ba5d
commit f7c6625d67
12 changed files with 421 additions and 182 deletions

View File

@ -31,6 +31,7 @@ extern NSWindowFrameAutosaveName const kMainWindowIdentifier;
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *keys;
@property (nonatomic, strong) NSWindow *gameWindow;
@property (nonatomic, strong) S9xPreferencesWindowController *preferencesWindowController;
@property (nonatomic, readonly, assign) S9xDeviceSetting deviceSetting;
- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player;
- (void)clearButton:(S9xButtonCode)button forPlayer:(int8)player;

View File

@ -179,6 +179,8 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
}
}
self.deviceSetting = Gamepads;
[self importKeySettings];
[self importGraphicsSettings];
[defaults synchronize];
@ -465,6 +467,9 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
if (action == @selector(resume:) || action == @selector(softwareReset:) || action == @selector(hardwareReset:)) {
return [self.s9xEngine isRunning] && [self.s9xEngine isPaused];
}
else if (action == @selector(updateDeviceSetting:)) {
menuItem.state = (self.deviceSetting == (S9xDeviceSetting)menuItem.tag) ? NSOnState : NSOffState;
}
return !self.isRunningEmulation;
}
@ -529,6 +534,17 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
[self.s9xEngine hardwareReset];
}
- (IBAction)updateDeviceSetting:(id)sender
{
self.deviceSetting = (S9xDeviceSetting)[sender tag];
}
- (void)setDeviceSetting:(S9xDeviceSetting)deviceSetting
{
_deviceSetting = deviceSetting;
[self.s9xEngine setDeviceSetting:deviceSetting];
}
- (BOOL)handleInput:(S9xJoypadInput *)input fromJoypad:(S9xJoypad *)joypad
{
if (NSApp.keyWindow != nil && NSApp.keyWindow == self.preferencesWindowController.window)
@ -539,4 +555,10 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
return NO;
}
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting
{
_deviceSetting = deviceSetting;
}
@end

View File

@ -115,6 +115,62 @@
<action selector="hardwareReset:" target="-1" id="dRy-5Q-N2I"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="YAv-y2-CdP"/>
<menuItem title="Controls" id="2xu-Kh-K2Q">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" id="Scs-jj-0pz">
<items>
<menuItem title="Gamepads" tag="1" id="ntk-uz-aiW">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="GxE-k5-uWL"/>
</connections>
</menuItem>
<menuItem title="Mouse (Port 1)" tag="2" id="5es-Zi-iof">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="jtg-E2-98q"/>
</connections>
</menuItem>
<menuItem title="Mouse (Port 2)" tag="3" id="vrV-Bh-KyE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="LGe-fJ-vTb"/>
</connections>
</menuItem>
<menuItem title="Super Scope (Port 2)" tag="4" id="ZF8-Xw-08U">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="1qY-rM-anV"/>
</connections>
</menuItem>
<menuItem title="Multitap (Port 2)" tag="5" id="cdn-s1-eHL">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="qrs-Ih-u7R"/>
</connections>
</menuItem>
<menuItem title="Multitap (Both Ports)" tag="6" id="fQJ-1V-NpK">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="5d9-tW-Rfm"/>
</connections>
</menuItem>
<menuItem title="Justifier (Port 2)" tag="7" id="hUi-aI-ihE">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="QBV-bU-viB"/>
</connections>
</menuItem>
<menuItem title="Double Justifier (Port 2)" tag="8" id="wTw-mT-ha1">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="updateDeviceSetting:" target="-1" id="XZV-DZ-rX3"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
</menuItem>
@ -171,5 +227,8 @@
</items>
<point key="canvasLocation" x="132" y="154"/>
</menu>
<menuItem title="Mouse (Port 2)" id="P6N-Mq-1PD">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</objects>
</document>

View File

@ -236,68 +236,70 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
return NO;
}
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting {}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
if ([keyPath isEqualToString:@"keyCode"])
{
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
uint16_t keyCode = field.keyCode;
int8_t player = self.playerPopUp.selectedItem.tag;
if ([keyPath isEqualToString:@"keyCode"])
{
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
uint16_t keyCode = field.keyCode;
int8_t player = self.playerPopUp.selectedItem.tag;
if (keyCode != (CGKeyCode)-1)
{
[((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player];
}
else
{
[((AppDelegate *) NSApp.delegate) clearButton:buttonCode forPlayer:player];
}
if (keyCode != (CGKeyCode)-1)
{
[((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player];
}
else
{
[((AppDelegate *) NSApp.delegate) clearButton:buttonCode forPlayer:player];
}
[NSUserDefaults.standardUserDefaults synchronize];
[NSUserDefaults.standardUserDefaults synchronize];
[self refresh];
}
else if ( [keyPath isEqualToString:@"joypadInput"])
{
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
S9xJoypad *joypad = self.devicePopUp.selectedItem.representedObject;
[self refresh];
}
else if ( [keyPath isEqualToString:@"joypadInput"])
{
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
S9xJoypad *joypad = self.devicePopUp.selectedItem.representedObject;
if ([joypad isKindOfClass:[S9xJoypad class]])
{
S9xJoypadInput *input = field.joypadInput;
if ([joypad isKindOfClass:[S9xJoypad class]])
{
S9xJoypadInput *input = field.joypadInput;
if (input != nil)
{
[((AppDelegate *)NSApp.delegate) setButton:buttonCode forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index cookie:input.cookie value:input.value];
}
else
{
[((AppDelegate *)NSApp.delegate) clearJoypadForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index buttonCode:buttonCode];
}
}
if (input != nil)
{
[((AppDelegate *)NSApp.delegate) setButton:buttonCode forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index cookie:input.cookie value:input.value];
}
else
{
[((AppDelegate *)NSApp.delegate) clearJoypadForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index buttonCode:buttonCode];
}
}
[NSUserDefaults.standardUserDefaults synchronize];
[self refresh];
}
[NSUserDefaults.standardUserDefaults synchronize];
[self refresh];
}
}
- (void)setShowFPS:(BOOL)value
{
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setShowFPS:value];
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setShowFPS:value];
}
- (void)setVideoMode:(int)value
{
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setVideoMode:value];
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setVideoMode:value];
}
- (void)setMacFrameSkip:(int)value
{
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setMacFrameSkip:value];
}
@ -313,7 +315,7 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
- (IBAction)onSelectVideoMode:(NSPopUpButton *)sender
{
[self setVideoMode:(int)sender.selectedTag];
[self setVideoMode:(int)sender.selectedTag];
}
- (IBAction)bumpMacFrameSkip:(NSStepper *)sender
@ -358,19 +360,20 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
- (IBAction)onChangePlayerDropdown:(NSPopUpButton *)sender
{
[self selectDeviceForPlayer:sender.selectedTag];
[self refresh];
[self selectDeviceForPlayer:sender.selectedTag];
[self refresh];
}
- (IBAction)onChangeDeviceDropdown:(NSPopUpButton *)sender
{
if (sender.selectedTag >= 0)
{
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
S9xJoypad *joypad = sender.selectedItem.representedObject;
[appDelegate setPlayer:self.playerPopUp.selectedTag forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
[NSUserDefaults.standardUserDefaults synchronize];
}
[self refresh];
if (sender.selectedTag >= 0)
{
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
S9xJoypad *joypad = sender.selectedItem.representedObject;
[appDelegate setPlayer:self.playerPopUp.selectedTag forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
[NSUserDefaults.standardUserDefaults synchronize];
}
[self refresh];
}
@end

View File

@ -0,0 +1,28 @@
/*****************************************************************************\
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 "S9xPrefsConstants.h"
NSString * const kKeyboardPrefs = @"KeyboardConfig";
NSString * const kJoypadInputPrefs = @"JoypadInputs";
NSString * const kJoypadPlayerPrefs = @"JoypadPlayers";
NSString * const kShowFPSPref = @"ShowFPS";
NSString * const kVideoModePref = @"VideoMode";
NSString * const kDeviceSettingPref = @"DeviceSetting";

View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
<dict/>
</plist>

View File

@ -177,6 +177,7 @@ enum
kMacCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2,
kMacCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1,
kMacCMapJustifier1Pointer = k_HD | k_PT | k_LG | k_C1,
kMacCMapJustifier2Pointer = k_HD | k_PT | k_LG | k_C2,
kMacCMapPseudoPtrBase = k_HD | k_PS | k_LG | k_C2 // for Justifier 2P
};

View File

@ -163,8 +163,9 @@ void S9xSetupDefaultKeymap (void)
ASSIGN_POINTRt(kMacCMapMouse2Pointer, "Pointer Mouse2");
ASSIGN_POINTRt(kMacCMapSuperscopePointer, "Pointer Superscope");
ASSIGN_POINTRt(kMacCMapJustifier1Pointer, "Pointer Justifier1");
ASSIGN_POINTRt(kMacCMapJustifier2Pointer, "Pointer Justifier2");
ASSIGN_POINTRf(PseudoPointerBase, "Pointer Justifier2");
ASSIGN_POINTRf(PseudoPointerBase, "Pointer Justifier2 (Controller)");
ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 0, "ButtonToPointer 1u Med");
ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med");
ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 2, "ButtonToPointer 1l Med");
@ -232,13 +233,13 @@ bool S9xPollPointer (uint32 id, int16 *x, int16 *y)
{
if (id & k_PT)
{
if ((id & k_MO) && fullscreen)
GetGameScreenPointer(x, y, true);
else
GetGameScreenPointer(x, y, false);
*x = (int16) mouseX;
*y = (int16) mouseY;
}
else
{
*x = *y = 0;
}
return (true);
}

View File

@ -718,7 +718,7 @@ void SetUpHID (void)
NSNumber *usagePage = (NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey));
NSNumber *usage = (NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey));
return usagePage.intValue != kHIDPage_GenericDesktop || (usage.intValue != kHIDUsage_GD_GamePad && usage.intValue != kHIDUsage_GD_Joystick);
return usagePage.intValue != kHIDPage_GenericDesktop || (usage.intValue != kHIDUsage_GD_GamePad && usage.intValue != kHIDUsage_GD_Joystick && usage.intValue != kHIDUsage_GD_Mouse);
}]];
[orderedDevices sortUsingComparator:^NSComparisonResult(id a, id b)

View File

@ -65,6 +65,17 @@ enum
VIDEOMODE_NTSC_TV_M
};
typedef enum S9xMacDeviceSettings {
Gamepads = 1,
Mouse = 2,
Mouse2 = 3,
SuperScope = 4,
MultiTap = 5,
DoubleMultiTap = 6,
Justifier1 = 7,
Justifier2 = 8,
} S9xDeviceSetting;
typedef struct
{
long long nextTime[12];
@ -84,6 +95,8 @@ extern uint32 controlPad[MAC_MAX_PLAYERS];
extern uint8 romDetect, interleaveDetect, videoDetect, headerDetect;
extern WindowRef gWindow;
extern uint32 glScreenW, glScreenH;
extern CGFloat rawMouseX, rawMouseY;
extern int16 mouseX, mouseY;
extern CGRect glScreenBounds;
extern CGImageRef macIconImage[118];
extern int macPadIconIndex, macLegendIconIndex, macMusicBoxIconIndex, macFunctionIconIndex;
@ -92,7 +105,7 @@ extern int32 skipFrames;
extern int64 lastFrame;
extern unsigned long spcFileCount, pngFileCount;
extern bool8 finished, cartOpen, autofire;
extern bool8 fullscreen, autoRes, glstretch, gl32bit, vsync, drawoverscan, lastoverscan;
extern bool8 autoRes, glstretch, gl32bit, vsync, drawoverscan, lastoverscan;
extern long drawingMethod;
extern int videoMode;
extern SInt32 macSoundVolume;
@ -109,7 +122,7 @@ extern uint16 macRecordFlag, macPlayFlag, macQTMovFlag;
extern bool8 startopendlog, showtimeinfrz, enabletoggle, savewindowpos, onscreeninfo;
extern int musicboxmode;
extern bool8 applycheat;
extern int padSetting, deviceSetting, deviceSettingMaster;
extern S9xDeviceSetting deviceSetting, deviceSettingMaster;
extern int macControllerOption;
extern CGPoint unlimitedCursor;
extern char npServerIP[256], npName[256];
@ -134,7 +147,6 @@ void UpdateMenuCommandStatus (Boolean);
void ApplyNSRTHeaderControllers (void);
void QuitWithFatalError (NSString *);
void ChangeInputDevice (void);
void GetGameScreenPointer (int16 *, int16 *, bool);
void PostQueueToSubEventLoop (void);
int PromptFreezeDefrost (Boolean);
uint64 GetMicroseconds(void);
@ -156,6 +168,7 @@ void CopyPressedKeys(uint8 keys[MAC_MAX_PLAYERS][kNumButtons], uint8 gamepadButt
@protocol S9xInputDelegate <NSObject>
- (BOOL)handleInput:(S9xJoypadInput *)input fromJoypad:(S9xJoypad *)joypad;
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting;
@end
extern id<S9xInputDelegate> inputDelegate;
@ -195,6 +208,8 @@ extern id<S9xInputDelegate> inputDelegate;
- (void)setMacFrameSkip:(int)_macFrameSkip;
- (void)setShowFPS:(BOOL)showFPS;
- (void)setDeviceSetting:(S9xDeviceSetting)_deviceSetting;
@end
#endif

View File

@ -83,6 +83,9 @@ uint32 glScreenW,
glScreenH;
CGRect glScreenBounds;
CGFloat rawMouseX, rawMouseY = 0;
int16 mouseX, mouseY = 0;
CGImageRef macIconImage[118];
int macPadIconIndex,
macLegendIconIndex,
@ -105,8 +108,7 @@ unsigned long spcFileCount = 0,
bool8 cartOpen = false,
autofire = false;
bool8 fullscreen = false,
autoRes = false,
bool8 autoRes = false,
glstretch = true,
gl32bit = true,
vsync = true,
@ -134,9 +136,8 @@ int inactiveMode = 2;
int musicboxmode = kMBXSoundEmulation;
bool8 applycheat = false;
int padSetting = 1,
deviceSetting = 1,
deviceSettingMaster = 1;
S9xDeviceSetting deviceSetting = Gamepads,
deviceSettingMaster = Gamepads;
int macControllerOption = SNES_JOYPAD;
AutoFireState autofireRec[MAC_MAX_PLAYERS];
@ -272,14 +273,6 @@ enum
mPresets = 201,
mDevice = 202,
iPad = 1,
iMouse = 2,
iMouse2 = 3,
iSuperScope = 4,
iMultiPlayer5 = 5,
iMultiPlayer5_2 = 6,
iJustifier1 = 7,
iJustifier2 = 8,
mRecentItem = 203
};
@ -296,7 +289,8 @@ static volatile bool8 rejectinput = false;
static bool8 pauseEmulation = false,
escKeyDown = false,
frameAdvance = false;
frameAdvance = false,
useMouse = false;
static int frameCount = 0;
@ -304,8 +298,6 @@ static bool8 frzselecting = false;
static uint16 changeAuto[2] = { 0x0000, 0x0000 };
static GameViewInfo scopeViewInfo;
static void Initialize (void);
static void Deinitialize (void);
static void InitAutofire (void);
@ -1533,54 +1525,64 @@ void ChangeInputDevice (void)
{
switch (deviceSetting)
{
case iPad:
case Gamepads:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
macControllerOption = SNES_JOYPAD;
useMouse = false;
break;
case iMouse:
case Mouse:
S9xSetController(0, CTL_MOUSE, 0, 0, 0, 0);
S9xSetController(1, CTL_JOYPAD, 1, 0, 0, 0);
macControllerOption = SNES_MOUSE;
useMouse = true;
break;
case iMouse2:
case Mouse2:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_MOUSE, 1, 0, 0, 0);
macControllerOption = SNES_MOUSE_SWAPPED;
useMouse = true;
break;
case iSuperScope:
case SuperScope:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_SUPERSCOPE, 0, 0, 0, 0);
macControllerOption = SNES_SUPERSCOPE;
useMouse = true;
break;
case iMultiPlayer5:
case MultiTap:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_MP5, 1, 2, 3, 4);
macControllerOption = SNES_MULTIPLAYER5;
useMouse = false;
break;
case iMultiPlayer5_2:
case DoubleMultiTap:
S9xSetController(0, CTL_MP5, 0, 1, 2, 3);
S9xSetController(1, CTL_MP5, 4, 5, 6, 7);
macControllerOption = SNES_MULTIPLAYER5_2;
useMouse = false;
break;
case iJustifier1:
case Justifier1:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JUSTIFIER, 0, 0, 0, 0);
macControllerOption = SNES_JUSTIFIER;
useMouse = true;
break;
case iJustifier2:
case Justifier2:
S9xSetController(0, CTL_JOYPAD, 0, 0, 0, 0);
S9xSetController(1, CTL_JUSTIFIER, 1, 0, 0, 0);
macControllerOption = SNES_JUSTIFIER_2;
useMouse = true;
break;
}
[inputDelegate deviceSettingChanged:deviceSetting];
}
void ApplyNSRTHeaderControllers (void)
@ -1593,68 +1595,68 @@ void ApplyNSRTHeaderControllers (void)
switch (Memory.NSRTHeader[29])
{
case 0x00: // Everything goes
deviceSetting = iPad;
valid = (1 << iPad);
deviceSetting = Gamepads;
valid = (1 << Gamepads);
break;
case 0x10: // Mouse in Port 0
deviceSetting = iMouse;
valid = (1 << iMouse);
deviceSetting = Mouse;
valid = (1 << Mouse);
break;
case 0x01: // Mouse in Port 1
deviceSetting = iMouse2;
valid = (1 << iMouse2);
deviceSetting = Mouse2;
valid = (1 << Mouse2);
break;
case 0x03: // Super Scope in Port 1
deviceSetting = iSuperScope;
valid = (1 << iSuperScope);
deviceSetting = SuperScope;
valid = (1 << SuperScope);
break;
case 0x06: // Multitap in Port 1
deviceSetting = iMultiPlayer5;
valid = (1 << iPad) | (1 << iMultiPlayer5);
deviceSetting = MultiTap;
valid = (1 << Gamepads) | (1 << MultiTap);
break;
case 0x66: // Multitap in Ports 0 and 1
deviceSetting = iMultiPlayer5_2;
valid = (1 << iPad) | (1 << iMultiPlayer5) | (1 << iMultiPlayer5_2);
deviceSetting = DoubleMultiTap;
valid = (1 << Gamepads) | (1 << MultiTap) | (1 << DoubleMultiTap);
break;
case 0x08: // Multitap in Port 1, Mouse in new Port 1
deviceSetting = iMouse2;
valid = (1 << iPad) | (1 << iMouse2) | (1 << iMultiPlayer5);
deviceSetting = Mouse;
valid = (1 << Gamepads) | (1 << Mouse2) | (1 << MultiTap);
break;
case 0x04: // Pad or Super Scope in Port 1
deviceSetting = iSuperScope;
valid = (1 << iPad) | (1 << iSuperScope);
deviceSetting = SuperScope;
valid = (1 << Gamepads) | (1 << SuperScope);
break;
case 0x05: // Justifier - Must ask user...
deviceSetting = iJustifier1;
valid = (1 << iJustifier1) | (1 << iJustifier2);
deviceSetting = Justifier1;
valid = (1 << Justifier1) | (1 << Justifier2);
break;
case 0x20: // Pad or Mouse in Port 0
deviceSetting = iMouse;
valid = (1 << iPad) | (1 << iMouse);
deviceSetting = Mouse;
valid = (1 << Gamepads) | (1 << Mouse);
break;
case 0x22: // Pad or Mouse in Port 0 & 1
deviceSetting = iMouse;
valid = (1 << iPad) | (1 << iMouse) | (1 << iMouse2);
deviceSetting = Mouse;
valid = (1 << Gamepads) | (1 << Mouse) | (1 << Mouse2);
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);
deviceSetting = SuperScope;
valid = (1 << Gamepads) | (1 << Mouse) | (1 << SuperScope);
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);
deviceSetting = SuperScope;
valid = (1 << Gamepads) | (1 << Mouse) | (1 << Mouse2) | (1 << SuperScope);
break;
case 0x99: // Lasabirdie
@ -2442,7 +2444,9 @@ static void ProcessInput (void)
}
if (macControllerOption == SNES_JUSTIFIER_2)
{
ControlPadFlagsToS9xPseudoPointer(controlPad[1]);
}
}
static void ChangeAutofireSettings (int player, int btn)
@ -2491,66 +2495,6 @@ static void ChangeTurboRate (int d)
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));
@ -2644,6 +2588,8 @@ static void Deinitialize (void)
S9xGraphicsDeinit();
S9xDeinitAPU();
Memory.Deinit();
pthread_mutex_destroy(&keyLock);
}
uint64 GetMicroseconds(void)
@ -2846,6 +2792,11 @@ void QuitWithFatalError ( NSString *message)
return self;
}
- (void)viewWillMoveToWindow:(NSWindow *)newWindow
{
newWindow.acceptsMouseMovedEvents = YES;
}
- (void)keyDown:(NSEvent *)event
{
if (!NSApp.isActive)
@ -2943,8 +2894,145 @@ void QuitWithFatalError ( NSString *message)
- (void)mouseDown:(NSEvent *)event
{
pauseEmulation = true;
[s9xView updatePauseOverlay];
if ( useMouse )
{
switch (deviceSetting)
{
case Mouse:
case SuperScope:
case Justifier1:
pressedKeys[0][kKeyMouseLeft] = true;
break;
case Mouse2:
case Justifier2:
pressedKeys[1][kKeyMouseLeft] = true;
break;
default:
break;
}
}
else
{
pauseEmulation = true;
[s9xView updatePauseOverlay];
}
}
- (void)mouseUp:(NSEvent *)event
{
if ( useMouse )
{
switch (deviceSetting)
{
case Mouse:
case SuperScope:
case Justifier1:
pressedKeys[0][kKeyMouseLeft] = false;
break;
case Mouse2:
case Justifier2:
pressedKeys[1][kKeyMouseLeft] = false;
break;
default:
break;
}
}
}
- (void)rightMouseDown:(NSEvent *)event
{
if ( useMouse )
{
switch (deviceSetting)
{
case Mouse:
case SuperScope:
case Justifier1:
pressedKeys[0][kKeyMouseRight] = true;
break;
case Mouse2:
case Justifier2:
pressedKeys[1][kKeyMouseRight] = true;
break;
default:
break;
}
}
}
- (void)rightMouseUp:(NSEvent *)event
{
if ( useMouse )
{
switch (deviceSetting)
{
case Mouse:
case SuperScope:
case Justifier1:
pressedKeys[0][kKeyMouseRight] = false;
break;
case Mouse2:
case Justifier2:
pressedKeys[1][kKeyMouseRight] = false;
break;
default:
break;
}
}
}
- (void)mouseMoved:(NSEvent *)event
{
if ( useMouse && running && !pauseEmulation )
{
rawMouseX += event.deltaX;
rawMouseY += event.deltaY;
CGRect bounds = self.bounds;
if (rawMouseX < 0)
{
rawMouseX = 0;
}
else if (rawMouseX > bounds.size.width)
{
rawMouseX = bounds.size.width;
}
if (rawMouseY < 0)
{
rawMouseY = 0;
}
else if ( rawMouseY > bounds.size.height)
{
rawMouseY = bounds.size.height;
}
mouseX = (int16) (rawMouseX / ((float) bounds.size.width ) * (float) IPPU.RenderedScreenWidth);
mouseY = (int16) (rawMouseY / ((float) bounds.size.height) * (float) IPPU.RenderedScreenHeight);
}
}
- (void)mouseDragged:(NSEvent *)event
{
[self mouseMoved:event];
}
- (void)rightMouseDragged:(NSEvent *)event
{
[self mouseMoved:event];
}
- (void)otherMouseDragged:(NSEvent *)event
{
[self mouseMoved:event];
}
- (void)updatePauseOverlay
@ -2954,6 +3042,24 @@ void QuitWithFatalError ( NSString *message)
CGFloat scaleFactor = MAX(self.window.backingScaleFactor, 1.0);
glScreenW = self.frame.size.width * scaleFactor;
glScreenH = self.frame.size.height * scaleFactor;
BOOL showMouse = !useMouse || !running || pauseEmulation;
CGAssociateMouseAndMouseCursorPosition(showMouse);
if (showMouse)
{
[NSCursor unhide];
}
else
{
CGRect frame = self.frame;
CGPoint point = CGPointMake(frame.size.width / 2.0, frame.size.height / 2.0);
point = [self convertPoint:point toView:nil];
point = [self.window convertPointToScreen:point];
point.y = self.window.screen.frame.size.height - point.y;
CGWarpMouseCursorPosition(point);
[NSCursor hide];
}
});
}
@ -3246,6 +3352,12 @@ void QuitWithFatalError ( NSString *message)
macFrameSkip = 200;
}
- (void)setDeviceSetting:(S9xDeviceSetting)_deviceSetting
{
deviceSetting = _deviceSetting;
ChangeInputDevice();
}
@dynamic inputDelegate;
- (void)setInputDelegate:(id<S9xInputDelegate>)delegate
{

View File

@ -263,7 +263,7 @@
306561FF236A8BA700A1B3B2 /* gamecontrollerdb.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = gamecontrollerdb.txt; sourceTree = "<group>"; };
30714715230E379500917F82 /* Snes9x.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Snes9x.app; sourceTree = BUILT_PRODUCTS_DIR; };
30714717230E379500917F82 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
30714718230E379500917F82 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
30714718230E379500917F82 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; usesTabs = 0; };
3071471A230E379600917F82 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
3071471D230E379600917F82 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = "<group>"; };
3071471F230E379600917F82 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -1428,7 +1428,7 @@
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES;
ENABLE_HARDENED_RUNTIME = NO;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;