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) NSMutableDictionary<NSString *, NSNumber *> *keys;
@property (nonatomic, strong) NSWindow *gameWindow; @property (nonatomic, strong) NSWindow *gameWindow;
@property (nonatomic, strong) S9xPreferencesWindowController *preferencesWindowController; @property (nonatomic, strong) S9xPreferencesWindowController *preferencesWindowController;
@property (nonatomic, readonly, assign) S9xDeviceSetting deviceSetting;
- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player; - (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player;
- (void)clearButton:(S9xButtonCode)button forPlayer:(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 importKeySettings];
[self importGraphicsSettings]; [self importGraphicsSettings];
[defaults synchronize]; [defaults synchronize];
@ -465,6 +467,9 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
if (action == @selector(resume:) || action == @selector(softwareReset:) || action == @selector(hardwareReset:)) { if (action == @selector(resume:) || action == @selector(softwareReset:) || action == @selector(hardwareReset:)) {
return [self.s9xEngine isRunning] && [self.s9xEngine isPaused]; return [self.s9xEngine isRunning] && [self.s9xEngine isPaused];
} }
else if (action == @selector(updateDeviceSetting:)) {
menuItem.state = (self.deviceSetting == (S9xDeviceSetting)menuItem.tag) ? NSOnState : NSOffState;
}
return !self.isRunningEmulation; return !self.isRunningEmulation;
} }
@ -529,6 +534,17 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
[self.s9xEngine hardwareReset]; [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 - (BOOL)handleInput:(S9xJoypadInput *)input fromJoypad:(S9xJoypad *)joypad
{ {
if (NSApp.keyWindow != nil && NSApp.keyWindow == self.preferencesWindowController.window) if (NSApp.keyWindow != nil && NSApp.keyWindow == self.preferencesWindowController.window)
@ -539,4 +555,10 @@ NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow";
return NO; return NO;
} }
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting
{
_deviceSetting = deviceSetting;
}
@end @end

View File

@ -115,6 +115,62 @@
<action selector="hardwareReset:" target="-1" id="dRy-5Q-N2I"/> <action selector="hardwareReset:" target="-1" id="dRy-5Q-N2I"/>
</connections> </connections>
</menuItem> </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> </items>
</menu> </menu>
</menuItem> </menuItem>
@ -171,5 +227,8 @@
</items> </items>
<point key="canvasLocation" x="132" y="154"/> <point key="canvasLocation" x="132" y="154"/>
</menu> </menu>
<menuItem title="Mouse (Port 2)" id="P6N-Mq-1PD">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
</objects> </objects>
</document> </document>

View File

@ -236,68 +236,70 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
return NO; return NO;
} }
- (void)deviceSettingChanged:(S9xDeviceSetting)deviceSetting {}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{ {
if ([keyPath isEqualToString:@"keyCode"]) if ([keyPath isEqualToString:@"keyCode"])
{ {
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object; S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag; S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
uint16_t keyCode = field.keyCode; uint16_t keyCode = field.keyCode;
int8_t player = self.playerPopUp.selectedItem.tag; int8_t player = self.playerPopUp.selectedItem.tag;
if (keyCode != (CGKeyCode)-1) if (keyCode != (CGKeyCode)-1)
{ {
[((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player]; [((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player];
} }
else else
{ {
[((AppDelegate *) NSApp.delegate) clearButton:buttonCode forPlayer:player]; [((AppDelegate *) NSApp.delegate) clearButton:buttonCode forPlayer:player];
} }
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
[self refresh]; [self refresh];
} }
else if ( [keyPath isEqualToString:@"joypadInput"]) else if ( [keyPath isEqualToString:@"joypadInput"])
{ {
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object; S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
S9xButtonCode buttonCode = (S9xButtonCode)field.tag; S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
S9xJoypad *joypad = self.devicePopUp.selectedItem.representedObject; S9xJoypad *joypad = self.devicePopUp.selectedItem.representedObject;
if ([joypad isKindOfClass:[S9xJoypad class]]) if ([joypad isKindOfClass:[S9xJoypad class]])
{ {
S9xJoypadInput *input = field.joypadInput; S9xJoypadInput *input = field.joypadInput;
if (input != nil) if (input != nil)
{ {
[((AppDelegate *)NSApp.delegate) setButton:buttonCode forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index cookie:input.cookie value:input.value]; [((AppDelegate *)NSApp.delegate) setButton:buttonCode forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index cookie:input.cookie value:input.value];
} }
else else
{ {
[((AppDelegate *)NSApp.delegate) clearJoypadForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index buttonCode:buttonCode]; [((AppDelegate *)NSApp.delegate) clearJoypadForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index buttonCode:buttonCode];
} }
} }
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
[self refresh]; [self refresh];
} }
} }
- (void)setShowFPS:(BOOL)value - (void)setShowFPS:(BOOL)value
{ {
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate; AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setShowFPS:value]; [appDelegate setShowFPS:value];
} }
- (void)setVideoMode:(int)value - (void)setVideoMode:(int)value
{ {
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate; AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setVideoMode:value]; [appDelegate setVideoMode:value];
} }
- (void)setMacFrameSkip:(int)value - (void)setMacFrameSkip:(int)value
{ {
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate; AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
[appDelegate setMacFrameSkip:value]; [appDelegate setMacFrameSkip:value];
} }
@ -313,14 +315,14 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
- (IBAction)onSelectVideoMode:(NSPopUpButton *)sender - (IBAction)onSelectVideoMode:(NSPopUpButton *)sender
{ {
[self setVideoMode:(int)sender.selectedTag]; [self setVideoMode:(int)sender.selectedTag];
} }
- (IBAction)bumpMacFrameSkip:(NSStepper *)sender - (IBAction)bumpMacFrameSkip:(NSStepper *)sender
{ {
int bumpValue = sender.intValue; // 1 or -1 int bumpValue = sender.intValue; // 1 or -1
int nextValue = self.macFrameSkipTextField.intValue + bumpValue; int nextValue = self.macFrameSkipTextField.intValue + bumpValue;
// constrain value // constrain value
if (nextValue < 0) { if (nextValue < 0) {
nextValue = 0; nextValue = 0;
@ -328,7 +330,7 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
if (nextValue > 200) { if (nextValue > 200) {
nextValue = 200; nextValue = 200;
} }
[self.macFrameSkipTextField setIntValue: nextValue]; [self.macFrameSkipTextField setIntValue: nextValue];
[sender setIntValue:0]; // reset stepper value [sender setIntValue:0]; // reset stepper value
[self setMacFrameSkip:self.macFrameSkipTextField.intValue]; // execute setter [self setMacFrameSkip:self.macFrameSkipTextField.intValue]; // execute setter
@ -358,19 +360,20 @@ NSString * const kMacFrameSkipPref = @"FrameSkip";
- (IBAction)onChangePlayerDropdown:(NSPopUpButton *)sender - (IBAction)onChangePlayerDropdown:(NSPopUpButton *)sender
{ {
[self selectDeviceForPlayer:sender.selectedTag]; [self selectDeviceForPlayer:sender.selectedTag];
[self refresh]; [self refresh];
} }
- (IBAction)onChangeDeviceDropdown:(NSPopUpButton *)sender - (IBAction)onChangeDeviceDropdown:(NSPopUpButton *)sender
{ {
if (sender.selectedTag >= 0) if (sender.selectedTag >= 0)
{ {
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate; AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
S9xJoypad *joypad = sender.selectedItem.representedObject; S9xJoypad *joypad = sender.selectedItem.representedObject;
[appDelegate setPlayer:self.playerPopUp.selectedTag forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index]; [appDelegate setPlayer:self.playerPopUp.selectedTag forVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
[NSUserDefaults.standardUserDefaults synchronize]; [NSUserDefaults.standardUserDefaults synchronize];
} }
[self refresh]; [self refresh];
} }
@end @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"?> <?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"> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0"> <plist version="1.0">
<dict> <dict/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
</dict>
</plist> </plist>

View File

@ -177,6 +177,7 @@ enum
kMacCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2, kMacCMapMouse2Pointer = k_HD | k_PT | k_MO | k_C2,
kMacCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1, kMacCMapSuperscopePointer = k_HD | k_PT | k_SS | k_C1,
kMacCMapJustifier1Pointer = k_HD | k_PT | k_LG | 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 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(kMacCMapMouse2Pointer, "Pointer Mouse2");
ASSIGN_POINTRt(kMacCMapSuperscopePointer, "Pointer Superscope"); ASSIGN_POINTRt(kMacCMapSuperscopePointer, "Pointer Superscope");
ASSIGN_POINTRt(kMacCMapJustifier1Pointer, "Pointer Justifier1"); 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 + 0, "ButtonToPointer 1u Med");
ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med"); ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 1, "ButtonToPointer 1d Med");
ASSIGN_BUTTONf(kMacCMapPseudoPtrBase + 2, "ButtonToPointer 1l 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_PT)
{ {
if ((id & k_MO) && fullscreen) *x = (int16) mouseX;
GetGameScreenPointer(x, y, true); *y = (int16) mouseY;
else
GetGameScreenPointer(x, y, false);
} }
else else
{
*x = *y = 0; *x = *y = 0;
}
return (true); return (true);
} }

View File

@ -718,7 +718,7 @@ void SetUpHID (void)
NSNumber *usagePage = (NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey)); NSNumber *usagePage = (NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsagePageKey));
NSNumber *usage = (NSNumber *)IOHIDDeviceGetProperty(device, CFSTR(kIOHIDPrimaryUsageKey)); 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) [orderedDevices sortUsingComparator:^NSComparisonResult(id a, id b)

View File

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

View File

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

View File

@ -263,7 +263,7 @@
306561FF236A8BA700A1B3B2 /* gamecontrollerdb.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = gamecontrollerdb.txt; sourceTree = "<group>"; }; 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; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 3071471F230E379600917F82 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
@ -1428,7 +1428,7 @@
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf; DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = ""; DEVELOPMENT_TEAM = "";
ENABLE_HARDENED_RUNTIME = YES; ENABLE_HARDENED_RUNTIME = NO;
GCC_C_LANGUAGE_STANDARD = gnu11; GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0; GCC_OPTIMIZATION_LEVEL = 0;