2019-11-07 04:44:19 +00:00
|
|
|
/*****************************************************************************\
|
|
|
|
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 <snes9x_framework/snes9x_framework.h>
|
|
|
|
|
|
|
|
#import "AppDelegate.h"
|
|
|
|
#import "S9xPrefsConstants.h"
|
|
|
|
#import "S9xPrefsViewController.h"
|
|
|
|
#import "S9xButtonConfigTextField.h"
|
|
|
|
|
|
|
|
@interface S9xPrefsViewController ()
|
|
|
|
@property (nonatomic, weak) IBOutlet NSPopUpButton *videoModePopup;
|
|
|
|
@property (nonatomic, weak) IBOutlet NSButton *showFPSCheckbox;
|
|
|
|
@property (nonatomic, weak) IBOutlet NSPopUpButton *devicePopUp;
|
|
|
|
@property (nonatomic, weak) IBOutlet NSPopUpButton *playerPopUp;
|
|
|
|
@end
|
|
|
|
|
|
|
|
@implementation S9xPrefsViewController
|
|
|
|
|
|
|
|
- (void)awakeFromNib
|
|
|
|
{
|
2019-11-10 21:02:21 +00:00
|
|
|
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
|
|
|
|
NSUInteger joypadIndex = 0;
|
|
|
|
for (S9xJoypad *joypad in [appDelegate listJoypads])
|
|
|
|
{
|
|
|
|
NSMenuItem *item = [NSMenuItem new];
|
|
|
|
item.title = joypad.name;
|
|
|
|
item.tag = joypadIndex++;
|
|
|
|
item.representedObject = joypad;
|
|
|
|
[self.devicePopUp.menu addItem:item];
|
|
|
|
}
|
|
|
|
|
|
|
|
[self selectDeviceForPlayer:0];
|
|
|
|
|
2019-11-07 04:44:19 +00:00
|
|
|
for (NSView *subview in self.view.subviews)
|
|
|
|
{
|
|
|
|
if ( [subview isKindOfClass:[S9xButtonConfigTextField class]] )
|
|
|
|
{
|
|
|
|
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)subview;
|
|
|
|
[field addObserver:self forKeyPath:@"keyCode" options:NSKeyValueObservingOptionNew context:NULL];
|
2019-11-10 21:02:21 +00:00
|
|
|
[field addObserver:self forKeyPath:@"joypadInput" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)selectDeviceForPlayer:(int8_t)player
|
|
|
|
{
|
|
|
|
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
|
|
|
|
NSString* joypadKey = [[NSUserDefaults.standardUserDefaults objectForKey:kJoypadPlayerPrefs] objectForKey:@(player).stringValue];
|
|
|
|
|
|
|
|
[self.devicePopUp selectItemAtIndex:0];
|
|
|
|
|
|
|
|
if (joypadKey != nil)
|
|
|
|
{
|
|
|
|
uint32 vendorID = 0;
|
|
|
|
uint32 productID = 0;
|
|
|
|
uint32 index = 0;
|
|
|
|
|
|
|
|
if ( [appDelegate getValuesFromString:joypadKey vendorID:&vendorID productID:&productID index:&index])
|
|
|
|
{
|
|
|
|
S9xJoypad *joypad = [S9xJoypad new];
|
|
|
|
joypad.vendorID = vendorID;
|
|
|
|
joypad.productID = productID;
|
|
|
|
joypad.index = index;
|
|
|
|
|
|
|
|
for (NSMenuItem *item in self.devicePopUp.menu.itemArray)
|
|
|
|
{
|
|
|
|
if ([joypad isEqual:item.representedObject])
|
|
|
|
{
|
|
|
|
[self.devicePopUp selectItem:item];
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-11-07 04:44:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)viewDidAppear
|
|
|
|
{
|
|
|
|
[super viewDidAppear];
|
|
|
|
[self.view.window makeFirstResponder:self.view];
|
|
|
|
[self refresh];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)refresh
|
|
|
|
{
|
|
|
|
NSUInteger index = MIN([NSUserDefaults.standardUserDefaults integerForKey:kVideoModePref], 1);
|
|
|
|
[self.videoModePopup selectItemAtIndex:index];
|
|
|
|
self.showFPSCheckbox.state = [NSUserDefaults.standardUserDefaults boolForKey:kShowFPSPref];
|
|
|
|
|
|
|
|
if (self.devicePopUp.selectedItem.tag < 0)
|
|
|
|
{
|
2019-11-10 21:02:21 +00:00
|
|
|
NSMutableDictionary<NSNumber *, NSNumber *> *controlsDict = [NSMutableDictionary new];
|
|
|
|
|
2019-11-07 04:44:19 +00:00
|
|
|
NSDictionary *keyboardDict = [NSUserDefaults.standardUserDefaults objectForKey:kKeyboardPrefs];
|
|
|
|
NSInteger playerNum = self.playerPopUp.selectedItem.tag;
|
|
|
|
|
|
|
|
for (NSUInteger i = 0; i < kNumButtons; ++i)
|
|
|
|
{
|
|
|
|
controlsDict[@(i)] = keyboardDict[@(i + playerNum).stringValue];
|
|
|
|
}
|
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
for (NSView *subview in self.view.subviews)
|
2019-11-07 04:44:19 +00:00
|
|
|
{
|
2019-11-10 21:02:21 +00:00
|
|
|
if ([subview isKindOfClass:[S9xButtonConfigTextField class]])
|
|
|
|
{
|
|
|
|
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)subview;
|
2019-11-07 04:44:19 +00:00
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
[field removeObserver:self forKeyPath:@"keyCode"];
|
|
|
|
[field removeObserver:self forKeyPath:@"joypadInput"];
|
2019-11-07 04:44:19 +00:00
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
NSNumber *keyCode = controlsDict[@(field.tag)];
|
2019-11-07 04:44:19 +00:00
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
field.joypadInput = nil;
|
|
|
|
|
|
|
|
if ( keyCode != nil )
|
|
|
|
{
|
|
|
|
field.keyCode = keyCode.intValue;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
field.keyCode = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
[field addObserver:self forKeyPath:@"keyCode" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
|
[field addObserver:self forKeyPath:@"joypadInput" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
|
|
|
|
|
field.disableKeyboardInput = NO;
|
2019-11-07 04:44:19 +00:00
|
|
|
}
|
2019-11-10 21:02:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
|
|
|
|
S9xJoypad *joypad = self.devicePopUp.selectedItem.representedObject;
|
|
|
|
NSString *joypadKey = [appDelegate prefsKeyForVendorID:joypad.vendorID productID:joypad.productID index:joypad.index];
|
|
|
|
NSDictionary *joypadDIct = [[NSUserDefaults.standardUserDefaults objectForKey:kJoypadInputPrefs] objectForKey:joypadKey];
|
|
|
|
|
|
|
|
for (NSView *subview in self.view.subviews)
|
|
|
|
{
|
|
|
|
if ([subview isKindOfClass:[S9xButtonConfigTextField class]])
|
2019-11-07 04:44:19 +00:00
|
|
|
{
|
2019-11-10 21:02:21 +00:00
|
|
|
S9xButtonConfigTextField *textField = (S9xButtonConfigTextField *)subview;
|
2019-11-07 04:44:19 +00:00
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
[textField removeObserver:self forKeyPath:@"keyCode"];
|
|
|
|
[textField removeObserver:self forKeyPath:@"joypadInput"];
|
|
|
|
|
|
|
|
uint32 cookie = 0;
|
|
|
|
int32 value = 0;
|
|
|
|
S9xButtonCode buttonCode = (S9xButtonCode)textField.tag;
|
|
|
|
NSString *inputString = joypadDIct[@(buttonCode).stringValue];
|
|
|
|
|
|
|
|
textField.keyCode = -1;
|
|
|
|
|
|
|
|
if ([appDelegate getValuesFromString:inputString cookie:&cookie value:&value])
|
|
|
|
{
|
|
|
|
S9xJoypadInput *input = [S9xJoypadInput new];
|
|
|
|
input.cookie = cookie;
|
|
|
|
input.value = value;
|
|
|
|
input.buttonCode = buttonCode;
|
|
|
|
textField.joypadInput = input;
|
|
|
|
textField.stringValue = [appDelegate labelForVendorID:joypad.vendorID productID:joypad.productID cookie:cookie value:value];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
textField.joypadInput = nil;
|
|
|
|
textField.stringValue = @"";
|
|
|
|
}
|
|
|
|
|
|
|
|
[textField addObserver:self forKeyPath:@"keyCode" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
|
[textField addObserver:self forKeyPath:@"joypadInput" options:NSKeyValueObservingOptionNew context:NULL];
|
|
|
|
|
|
|
|
textField.disableKeyboardInput = YES;
|
|
|
|
}
|
2019-11-07 04:44:19 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
|
|
|
|
{
|
2019-11-10 21:02:21 +00:00
|
|
|
if ([keyPath isEqualToString:@"keyCode"])
|
2019-11-07 04:44:19 +00:00
|
|
|
{
|
|
|
|
S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)object;
|
|
|
|
S9xButtonCode buttonCode = (S9xButtonCode)field.tag;
|
|
|
|
uint16_t keyCode = field.keyCode;
|
|
|
|
int8_t player = self.playerPopUp.selectedItem.tag;
|
|
|
|
|
2019-11-10 21:02:21 +00:00
|
|
|
if (keyCode != (CGKeyCode)-1)
|
|
|
|
{
|
|
|
|
[((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player];
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
[((AppDelegate *) NSApp.delegate) clearButton:buttonCode forPlayer:player];
|
|
|
|
}
|
|
|
|
|
2019-11-07 04:44:19 +00:00
|
|
|
[NSUserDefaults.standardUserDefaults synchronize];
|
|
|
|
|
|
|
|
[self refresh];
|
|
|
|
}
|
2019-11-10 21:02:21 +00:00
|
|
|
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 (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];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)playerDropdownChanged:(NSPopUpButton *)sender
|
|
|
|
{
|
|
|
|
[self selectDeviceForPlayer:sender.selectedTag];
|
|
|
|
[self refresh];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)deviceDropdownChanged:(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];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)showFPS:(NSButton *)sender
|
|
|
|
{
|
|
|
|
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
|
|
|
|
[appDelegate setShowFPS:sender.state == NSOnState];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (IBAction)setVideoMode:(NSPopUpButton *)sender
|
|
|
|
{
|
|
|
|
AppDelegate *appDelegate = (AppDelegate *)NSApp.delegate;
|
|
|
|
[appDelegate setVideoMode:(int)sender.selectedTag];
|
|
|
|
}
|
|
|
|
|
|
|
|
- (BOOL)handleInput:(S9xJoypadInput *)input fromJoypad:(S9xJoypad *)joypad
|
|
|
|
{
|
|
|
|
id firstResponder = self.view.window.firstResponder;
|
|
|
|
|
2019-11-12 03:12:10 +00:00
|
|
|
if ([firstResponder respondsToSelector:@selector(isFieldEditor)] && [firstResponder isFieldEditor])
|
2019-11-10 21:02:21 +00:00
|
|
|
{
|
|
|
|
firstResponder = [firstResponder delegate];
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([firstResponder respondsToSelector:@selector(setJoypadInput:)])
|
|
|
|
{
|
|
|
|
S9xJoypad *currentJoypad = self.devicePopUp.selectedItem.representedObject;
|
|
|
|
|
|
|
|
if ([joypad isEqual:currentJoypad])
|
|
|
|
{
|
|
|
|
[firstResponder setJoypadInput:input];
|
|
|
|
return YES;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return NO;
|
2019-11-07 04:44:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@end
|