diff --git a/macosx/.DS_Store b/macosx/.DS_Store index 3489d03d..3565c27c 100644 Binary files a/macosx/.DS_Store and b/macosx/.DS_Store differ diff --git a/macosx/Snes9x/AppDelegate.h b/macosx/Snes9x/AppDelegate.h index c9c16577..5ccb09d2 100644 --- a/macosx/Snes9x/AppDelegate.h +++ b/macosx/Snes9x/AppDelegate.h @@ -1,14 +1,28 @@ -// -// AppDelegate.h -// Snes9x -// -// Created by Buckley on 8/21/19. -// +/*****************************************************************************\ + 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 @interface AppDelegate : NSObject +- (void)setButtonCode:(S9xButtonCode)buttonCode forKeyCode:(int16)keyCode player:(int8)player; @end diff --git a/macosx/Snes9x/AppDelegate.m b/macosx/Snes9x/AppDelegate.m index c6025d18..b2c0c7e8 100644 --- a/macosx/Snes9x/AppDelegate.m +++ b/macosx/Snes9x/AppDelegate.m @@ -1,23 +1,39 @@ -// -// AppDelegate.m -// Snes9x -// -// Created by Buckley on 8/21/19. -// +/*****************************************************************************\ + 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. +\*****************************************************************************/ -#import "AppDelegate.h" +/*********************************************************************************** + 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 #import +#import "AppDelegate.h" + +#import "S9xPrefsConstants.h" +#import "S9xPrefsViewController.h" + @interface AppDelegate () @property (nonatomic, strong) S9xEngine *s9xEngine; @property (nonatomic, strong) NSMutableDictionary *keys; @property (nonatomic, strong) NSWindow *window; +@property (nonatomic, strong, nullable) NSWindowController *prefsWindowController; @end static NSWindowFrameAutosaveName const kMainWindowIdentifier = @"s9xMainWindow"; -static NSString * const kKeyboardPrefs = @"KeyboardConfig"; @implementation AppDelegate @@ -64,7 +80,7 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; { NSUserDefaults *defaults = NSUserDefaults.standardUserDefaults; - NSDictionary *defaultKeyBindings = @{ + NSDictionary *defaultSettings = @{ kKeyboardPrefs : @{ @(kUp).stringValue : @(kVK_UpArrow), @(kDown).stringValue : @(kVK_DownArrow), @@ -99,7 +115,7 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; @(kKeySPC).stringValue : @(kVK_ANSI_R), @(kKeyScopeTurbo).stringValue : @(kVK_ANSI_B), @(kKeyScopePause).stringValue : @(kVK_ANSI_N), - @(kKeyScopeCursor).stringValue : @(kVK_ANSI_Q), + @(kKeyScopeCursor).stringValue : @(kVK_ANSI_M), @(kKeyOffScreen).stringValue : @(kVK_Tab), @(kKeyFunction).stringValue : @(kVK_ANSI_Slash), @(kKeyAlt).stringValue : @(kVK_ANSI_Period), @@ -107,10 +123,12 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; @(kKeyFFUp).stringValue : @(kVK_ANSI_W), @(kKeyEsc).stringValue : @(kVK_Escape), @(kKeyTC).stringValue : @(kVK_ANSI_Comma) - } + }, + kShowFPSPref: @(NO), + kVideoModePref:@(VIDEOMODE_BLOCKY) }; - [defaults registerDefaults:defaultKeyBindings]; + [defaults registerDefaults:defaultSettings]; self.keys = [[defaults objectForKey:kKeyboardPrefs] mutableCopy]; @@ -123,6 +141,7 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; } [self importKeySettings]; + [self importGraphicsSettings]; [defaults synchronize]; } @@ -139,7 +158,7 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; int8 oldPlayer = -1; if ([self.s9xEngine setButton:buttonCode forKey:keyCode player:player oldButton:&oldButton oldPlayer:&oldPlayer oldKey:NULL]) { - if (oldButton >= 0 && oldButton < kNumButtons && oldPlayer >= 0 && oldPlayer < MAC_MAX_PLAYERS) + if (oldButton >= 0 && oldButton < kNumButtons && oldPlayer >= 0 && oldPlayer < MAC_MAX_PLAYERS && (oldPlayer != player || oldButton != buttonCode)) { [self.keys removeObjectForKey:@(oldButton + (kNumButtons * oldPlayer)).stringValue]; } @@ -169,21 +188,7 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; - (void)importKeySettings { - NSData *data = [NSUserDefaults.standardUserDefaults objectForKey:@"Preferences_byek"]; - - if (data == nil) - { - data = [NSUserDefaults.standardUserDefaults objectForKey:@"Preferences_keyb"]; - - if (data != nil) - { - [NSUserDefaults.standardUserDefaults removeObjectForKey:@"Preferences_keyb"]; - } - } - else - { - [NSUserDefaults.standardUserDefaults removeObjectForKey:@"Preferences_byek"]; - } + NSData *data = [self objectForPrefOSCode:'keyb']; NSUInteger length = data.length; char *bytes = (char*)data.bytes; @@ -202,6 +207,49 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; } } +- (void)importGraphicsSettings +{ + NSData *data = [self objectForPrefOSCode:'dfps']; + + if (data != nil) + { + [NSUserDefaults.standardUserDefaults setBool:(data.length > 0 && ((char *)data.bytes)[0]) forKey:kShowFPSPref]; + } + + data = [self objectForPrefOSCode:'Vmod']; + + if ( data != nil) + { + [NSUserDefaults.standardUserDefaults setInteger:((data.length >= 0 && ((char *)data.bytes)[0]) ? VIDEOMODE_SMOOTH : VIDEOMODE_BLOCKY) forKey:kVideoModePref]; + } +} + +- (id)objectForPrefOSCode:(uint32_t)osCode +{ + NSString *key = [@"Preferences_" stringByAppendingString:[[NSString alloc] initWithBytes:(char *)&osCode length:sizeof(uint32_t) encoding:NSASCIIStringEncoding]]; + + id obj = [NSUserDefaults.standardUserDefaults objectForKey:key]; + + if (obj == nil) + { + osCode =CFSwapInt32(osCode); + key = [@"Preferences_" stringByAppendingString:[[NSString alloc] initWithBytes:(char *)&osCode length:sizeof(uint32_t) encoding:NSASCIIStringEncoding]]; + + obj = [NSUserDefaults.standardUserDefaults objectForKey:key]; + + if (obj != nil) + { + [NSUserDefaults.standardUserDefaults removeObjectForKey:key]; + } + } + else + { + [NSUserDefaults.standardUserDefaults removeObjectForKey:key]; + } + + return obj; +} + - (BOOL)application:(NSApplication *)sender openFile:(NSString *)filename { return [self openURL:[NSURL fileURLWithPath:filename]]; @@ -242,4 +290,18 @@ static NSString * const kKeyboardPrefs = @"KeyboardConfig"; [NSApp terminate:sender]; } +- (IBAction)openPrefs:(id)sender +{ + if ( self.prefsWindowController == nil ) + { + NSWindow *prefsWindow = [[NSWindow alloc] initWithContentRect:NSMakeRect(0, 0, 100, 100) styleMask:NSWindowStyleMaskTitled|NSWindowStyleMaskClosable|NSWindowStyleMaskMiniaturizable backing:NSBackingStoreBuffered defer:NO]; + self.prefsWindowController = [[NSWindowController alloc] initWithWindow:prefsWindow]; + + prefsWindow.contentViewController = [[S9xPrefsViewController alloc] initWithNibName:@"S9xPrefsViewController" bundle:nil]; + [prefsWindow center]; + } + + [self.prefsWindowController.window makeKeyAndOrderFront:self]; +} + @end diff --git a/macosx/Snes9x/Base.lproj/MainMenu.xib b/macosx/Snes9x/Base.lproj/MainMenu.xib index 2bf409d1..b9bf5b86 100644 --- a/macosx/Snes9x/Base.lproj/MainMenu.xib +++ b/macosx/Snes9x/Base.lproj/MainMenu.xib @@ -27,7 +27,11 @@ - + + + + + diff --git a/macosx/Snes9x/S9xButtonConfigTextField.h b/macosx/Snes9x/S9xButtonConfigTextField.h new file mode 100644 index 00000000..369cedc9 --- /dev/null +++ b/macosx/Snes9x/S9xButtonConfigTextField.h @@ -0,0 +1,31 @@ +/*****************************************************************************\ + 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 + +NS_ASSUME_NONNULL_BEGIN + +@interface S9xButtonConfigTextField : NSSearchField + +@property (nonatomic, assign) CGKeyCode keyCode; + +@end + +NS_ASSUME_NONNULL_END diff --git a/macosx/Snes9x/S9xButtonConfigTextField.m b/macosx/Snes9x/S9xButtonConfigTextField.m new file mode 100644 index 00000000..a10bafc4 --- /dev/null +++ b/macosx/Snes9x/S9xButtonConfigTextField.m @@ -0,0 +1,316 @@ +/*****************************************************************************\ + 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 + ***********************************************************************************/ + +#include +#include + +#import "S9xButtonConfigTextField.h" + +@implementation S9xButtonConfigTextField + +- (void)awakeFromNib +{ + self.delegate = self; + self.placeholderString = @""; + [[self cell] setSearchButtonCell:nil]; +} + +- (void)setKeyCode:(CGKeyCode)keyCode +{ + NSString *stringValue = nil; + + switch (keyCode) + { + case kVK_Shift: + stringValue = NSLocalizedString(@"Shift", @""); + break; + + case kVK_Command: + stringValue = NSLocalizedString(@"Command", @""); + break; + + case kVK_Control: + stringValue = NSLocalizedString(@"Control", @""); + break; + + case kVK_Option: + stringValue = NSLocalizedString(@"Option", @""); + break; + + case kVK_F1: + stringValue = NSLocalizedString(@"F1", @""); + break; + + case kVK_F2: + stringValue = NSLocalizedString(@"F2", @""); + break; + + case kVK_F3: + stringValue = NSLocalizedString(@"F3", @""); + break; + + case kVK_F4: + stringValue = NSLocalizedString(@"F4", @""); + break; + + case kVK_F5: + stringValue = NSLocalizedString(@"F5", @""); + break; + + case kVK_F6: + stringValue = NSLocalizedString(@"F6", @""); + break; + + case kVK_F7: + stringValue = NSLocalizedString(@"F7", @""); + break; + + case kVK_F8: + stringValue = NSLocalizedString(@"F8", @""); + break; + + case kVK_F9: + stringValue = NSLocalizedString(@"F9", @""); + break; + + case kVK_F10: + stringValue = NSLocalizedString(@"F10", @""); + break; + + case kVK_F11: + stringValue = NSLocalizedString(@"F11", @""); + break; + + case kVK_F12: + stringValue = NSLocalizedString(@"F12", @""); + break; + + case kVK_F13: + stringValue = NSLocalizedString(@"F13", @""); + break; + + case kVK_F14: + stringValue = NSLocalizedString(@"F14", @""); + break; + + case kVK_F15: + stringValue = NSLocalizedString(@"F15", @""); + break; + + case kVK_F16: + stringValue = NSLocalizedString(@"F16", @""); + break; + + case kVK_F17: + stringValue = NSLocalizedString(@"F17", @""); + break; + + case kVK_F18: + stringValue = NSLocalizedString(@"F18", @""); + break; + + case kVK_F19: + stringValue = NSLocalizedString(@"F19", @""); + break; + + case kVK_F20: + stringValue = NSLocalizedString(@"F20", @""); + break; + + case kVK_Delete: + stringValue = NSLocalizedString(@"Delete", @""); + break; + + case kVK_ForwardDelete: + stringValue = NSLocalizedString(@"⌦", @""); + break; + + case kVK_Home: + stringValue = NSLocalizedString(@"Home", @""); + break; + + case kVK_End: + stringValue = NSLocalizedString(@"End", @""); + break; + + case kVK_PageUp: + stringValue = NSLocalizedString(@"Page Up", @""); + break; + + case kVK_PageDown: + stringValue = NSLocalizedString(@"Page Down", @""); + break; + + case kVK_Tab: + stringValue = NSLocalizedString(@"Tab", @""); + break; + + case kVK_Space: + stringValue = NSLocalizedString(@"Space", @""); + break; + + case kVK_ANSI_KeypadClear: + stringValue = NSLocalizedString(@"Clear", @""); + break; + + case kVK_LeftArrow: + stringValue = NSLocalizedString(@"←", @""); + break; + + case kVK_RightArrow: + stringValue = NSLocalizedString(@"→", @""); + break; + + case kVK_UpArrow: + stringValue = NSLocalizedString(@"↑", @""); + break; + + case kVK_DownArrow: + stringValue = NSLocalizedString(@"↓", @""); + break; + + case kVK_Return: + stringValue = NSLocalizedString(@"Return", @""); + break; + + case kVK_ANSI_KeypadEnter: + stringValue = NSLocalizedString(@"Enter", @""); + break; + + case kVK_Escape: + stringValue = NSLocalizedString(@"Escape", @""); + break; + + default: + { + TISInputSourceRef keyboard = TISCopyCurrentKeyboardInputSource(); + CFDataRef layoutData = (CFDataRef)TISGetInputSourceProperty(keyboard, kTISPropertyUnicodeKeyLayoutData); + + if ( layoutData != NULL ) + { + const UCKeyboardLayout *layout = (const UCKeyboardLayout*)CFDataGetBytePtr(layoutData); + UniCharCount maxStringLength = 0xFF; + UniCharCount actualStringLength = 0; + UniChar unicodeString[maxStringLength]; + uint32_t deadKeyState = 0; + + OSErr status = UCKeyTranslate(layout, keyCode, kUCKeyActionDisplay, kUCKeyTranslateNoDeadKeysBit, LMGetKbdType(), 0, &deadKeyState, maxStringLength, &actualStringLength, unicodeString); + + if (status == noErr && actualStringLength > 0) + { + stringValue = [NSString stringWithCharacters:unicodeString length:actualStringLength]; + + switch (keyCode) + { + case kVK_ANSI_Keypad0: + case kVK_ANSI_Keypad1: + case kVK_ANSI_Keypad2: + case kVK_ANSI_Keypad3: + case kVK_ANSI_Keypad4: + case kVK_ANSI_Keypad5: + case kVK_ANSI_Keypad6: + case kVK_ANSI_Keypad7: + case kVK_ANSI_Keypad8: + case kVK_ANSI_Keypad9: + case kVK_ANSI_KeypadPlus: + case kVK_ANSI_KeypadMinus: + case kVK_ANSI_KeypadDivide: + case kVK_ANSI_KeypadMultiply: + case kVK_ANSI_KeypadEquals: + case kVK_ANSI_KeypadDecimal: + stringValue = [[stringValue stringByAppendingString:@" "] stringByAppendingString:NSLocalizedString(@"(Keypad)", @"")]; + break; + } + } + } + } + } + + if ( stringValue != nil ) + { + stringValue = [[stringValue componentsSeparatedByCharactersInSet:NSCharacterSet.controlCharacterSet] componentsJoinedByString:@""]; + stringValue = [[stringValue componentsSeparatedByCharactersInSet:NSCharacterSet.newlineCharacterSet] componentsJoinedByString:@""]; + stringValue = [[stringValue componentsSeparatedByCharactersInSet:NSCharacterSet.illegalCharacterSet] componentsJoinedByString:@""]; + + if ( stringValue.length > 0 ) + { + self.stringValue = stringValue.capitalizedString; + [self.window makeFirstResponder:self.window.contentView]; + } + } + + _keyCode = keyCode; +} + +- (void)controlTextDidChange:(NSNotification *)obj +{ + self.stringValue = @""; +} + +- (void)keyUp:(NSEvent *)event +{ + [self setKeyCode:event.keyCode]; +} + +- (void)flagsChanged:(NSEvent *)event +{ + NSEventModifierFlags flags = event.modifierFlags; + + if ( flags & NSEventModifierFlagShift ) + { + [self setKeyCode:kVK_Shift]; + } + else if ( flags & NSEventModifierFlagOption ) + { + [self setKeyCode:kVK_Option]; + } + else if ( flags & NSEventModifierFlagCommand ) + { + [self setKeyCode:kVK_Command]; + } + else if ( flags & NSEventModifierFlagControl ) + { + [self setKeyCode:kVK_Control]; + } +} + +- (void)mouseDown:(NSEvent *)event +{ + [super mouseDown:event]; + [self.currentEditor selectAll:self]; +} + +- (BOOL)control:(NSControl *)control textView:(NSTextView *)textView doCommandBySelector:(SEL)commandSelector +{ + if (commandSelector == @selector(insertTab:)) + { + [self setKeyCode:kVK_Tab]; + return YES; + } + else if (commandSelector == @selector(cancelOperation:)) + { + [self setKeyCode:kVK_Escape]; + return YES; + } + + return NO; +} + +@end diff --git a/macosx/Snes9x/S9xPrefsConstants.h b/macosx/Snes9x/S9xPrefsConstants.h new file mode 100644 index 00000000..9bbcb872 --- /dev/null +++ b/macosx/Snes9x/S9xPrefsConstants.h @@ -0,0 +1,25 @@ +/*****************************************************************************\ + 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 + +extern NSString * const kKeyboardPrefs; +extern NSString * const kShowFPSPref; +extern NSString * const kVideoModePref; diff --git a/macosx/Snes9x/S9xPrefsConstants.m b/macosx/Snes9x/S9xPrefsConstants.m new file mode 100644 index 00000000..16c4d0b7 --- /dev/null +++ b/macosx/Snes9x/S9xPrefsConstants.m @@ -0,0 +1,25 @@ +/*****************************************************************************\ + 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 kShowFPSPref = @"ShowFPS"; +NSString * const kVideoModePref = @"VideoMode"; diff --git a/macosx/Snes9x/S9xPrefsViewController.h b/macosx/Snes9x/S9xPrefsViewController.h new file mode 100644 index 00000000..9e71a884 --- /dev/null +++ b/macosx/Snes9x/S9xPrefsViewController.h @@ -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 + +NS_ASSUME_NONNULL_BEGIN + +@interface S9xPrefsViewController : NSViewController + +@end + +NS_ASSUME_NONNULL_END diff --git a/macosx/Snes9x/S9xPrefsViewController.m b/macosx/Snes9x/S9xPrefsViewController.m new file mode 100644 index 00000000..1cb0d6ce --- /dev/null +++ b/macosx/Snes9x/S9xPrefsViewController.m @@ -0,0 +1,114 @@ +/*****************************************************************************\ + 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 + +#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 +{ + 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]; + } + } +} + +- (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]; + + NSMutableDictionary *controlsDict = [NSMutableDictionary new]; + if (self.devicePopUp.selectedItem.tag < 0) + { + 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]; + } + } + + for (NSView *subview in self.view.subviews) + { + if ( [subview isKindOfClass:[S9xButtonConfigTextField class]] ) + { + S9xButtonConfigTextField *field = (S9xButtonConfigTextField *)subview; + + [field removeObserver:self forKeyPath:@"keyCode"]; + + NSNumber *keyCode = controlsDict[@(field.tag)]; + + if ( keyCode != nil ) + { + field.keyCode = keyCode.intValue; + } + else + { + field.stringValue = @""; + } + + [field addObserver:self forKeyPath:@"keyCode" options:NSKeyValueObservingOptionNew context:NULL]; + } + } +} + +- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)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; + + [((AppDelegate *) NSApp.delegate) setButtonCode:buttonCode forKeyCode:keyCode player:player]; + [NSUserDefaults.standardUserDefaults synchronize]; + + [self refresh]; + } +} + +@end diff --git a/macosx/Snes9x/S9xPrefsViewController.xib b/macosx/Snes9x/S9xPrefsViewController.xib new file mode 100644 index 00000000..81feda5d --- /dev/null +++ b/macosx/Snes9x/S9xPrefsViewController.xib @@ -0,0 +1,805 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/macosx/Snes9x/main.m b/macosx/Snes9x/main.m index 777c2034..cc7f4966 100644 --- a/macosx/Snes9x/main.m +++ b/macosx/Snes9x/main.m @@ -1,9 +1,22 @@ -// -// main.m -// Snes9x -// -// Created by Buckley on 8/21/19. -// +/*****************************************************************************\ + 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 diff --git a/macosx/mac-controls.h b/macosx/mac-controls.h index bf1f7c2f..aab48d3f 100644 --- a/macosx/mac-controls.h +++ b/macosx/mac-controls.h @@ -199,6 +199,7 @@ typedef enum kKeyFastForward, kKeyFreeze, kKeyDefrost, + kKeyScreenshot, kKeySPC, kKeyScopeTurbo, diff --git a/macosx/mac-controls.mm b/macosx/mac-controls.mm index f3251087..fc011260 100644 --- a/macosx/mac-controls.mm +++ b/macosx/mac-controls.mm @@ -210,7 +210,7 @@ bool S9xPollButton (uint32 id, bool *pressed) switch (id & 0xFF) { case 0: *pressed = ISpKeyIsPressed(keys, gamepadButtons, kISpOffScreen); break; - case 1: *pressed = ISpKeyIsPressed(keys, gamepadButtons, kISpMouseLeft); break; break; + case 1: *pressed = ISpKeyIsPressed(keys, gamepadButtons, kISpMouseLeft); break; case 2: *pressed = ISpKeyIsPressed(keys, gamepadButtons, kISpMouseRight); } } @@ -218,8 +218,8 @@ bool S9xPollButton (uint32 id, bool *pressed) { switch (id & 0xFF) { - case 0: *pressed = KeyIsPressed(keys, gamepadButtons, 1, kStart); break; - case 1: *pressed = KeyIsPressed(keys, gamepadButtons, 1, kB); break; + case 0: *pressed = KeyIsPressed(keys, gamepadButtons, 1, kStart); break; + case 1: *pressed = KeyIsPressed(keys, gamepadButtons, 1, kB); break; case 2: *pressed = KeyIsPressed(keys, gamepadButtons, 1, kA); } } diff --git a/macosx/mac-os.mm b/macosx/mac-os.mm index f2ff9a21..bc753fbd 100644 --- a/macosx/mac-os.mm +++ b/macosx/mac-os.mm @@ -368,30 +368,12 @@ void CopyPressedKeys(bool8 keys[MAC_MAX_PLAYERS][kNumButtons], bool8 gamepadButt pressedKeys[button.player][button.buttonCode] = (flags & NSEventModifierFlagControl) != 0; } - button = keyCodes[kVK_CapsLock]; - if (button.buttonCode >= 0 && button.buttonCode < kNumButtons && button.player >= 0 && button.player < MAC_MAX_PLAYERS) - { - pressedKeys[button.player][button.buttonCode] = (flags & NSEventModifierFlagCapsLock) != 0; - } - button = keyCodes[kVK_Option]; if (button.buttonCode >= 0 && button.buttonCode < kNumButtons && button.player >= 0 && button.player < MAC_MAX_PLAYERS) { pressedKeys[button.player][button.buttonCode] = (flags & NSEventModifierFlagOption) != 0; } - button = keyCodes[kVK_Help]; - if (button.buttonCode >= 0 && button.buttonCode < kNumButtons && button.player >= 0 && button.player < MAC_MAX_PLAYERS) - { - pressedKeys[button.player][button.buttonCode] = (flags & NSEventModifierFlagHelp) != 0; - } - - button = keyCodes[kVK_Function]; - if (button.buttonCode >= 0 && button.buttonCode < kNumButtons && button.player >= 0 && button.player < MAC_MAX_PLAYERS) - { - pressedKeys[button.player][button.buttonCode] = (flags & NSEventModifierFlagFunction) != 0; - } - memcpy(keys, pressedKeys, sizeof(pressedKeys)); memcpy(gamepadButtons, pressedGamepadButtons, sizeof(pressedGamepadButtons)); os_unfair_lock_unlock(&keyLock); diff --git a/macosx/snes9x.xcodeproj/project.pbxproj b/macosx/snes9x.xcodeproj/project.pbxproj index a77150a2..e098095f 100755 --- a/macosx/snes9x.xcodeproj/project.pbxproj +++ b/macosx/snes9x.xcodeproj/project.pbxproj @@ -202,6 +202,7 @@ 30D15DE822CE6BC9005BC352 /* ioapi.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518D60EBCB4CA008379F6 /* ioapi.h */; }; 30D15DE922CE6BC9005BC352 /* unzip.h in Headers */ = {isa = PBXBuildFile; fileRef = CFA518DA0EBCB4D2008379F6 /* unzip.h */; }; 30D15DEA22CE6FE1005BC352 /* mac-os.mm in Sources */ = {isa = PBXBuildFile; fileRef = EAE0E96604D582B700A80003 /* mac-os.mm */; }; + 30D2506E2373AACC0076A160 /* S9xPrefsConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D2506D2373AACC0076A160 /* S9xPrefsConstants.m */; }; 30D709B0236F583600AAB7C3 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEA980A28384E00A8FAE5 /* Localizable.strings */; }; 30D709B1236F585100AAB7C3 /* Snes9x Help in Resources */ = {isa = PBXBuildFile; fileRef = EA3BEAA80A28386500A8FAE5 /* Snes9x Help */; }; 30D709B2236F731B00AAB7C3 /* CART.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3C0A26083B00BDACCC /* CART.icns */; }; @@ -211,6 +212,9 @@ 30D709B6236F731B00AAB7C3 /* folder_Freezes.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F3B0A26083B00BDACCC /* folder_Freezes.icns */; }; 30D709B7236F731B00AAB7C3 /* musicbox_ledon.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F380A26083B00BDACCC /* musicbox_ledon.icns */; }; 30D709B8236F731B00AAB7C3 /* musicbox_ledoff.icns in Resources */ = {isa = PBXBuildFile; fileRef = EA3D2F390A26083B00BDACCC /* musicbox_ledoff.icns */; }; + 30D709C1236F7E3200AAB7C3 /* S9xPrefsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D709BF236F7E3200AAB7C3 /* S9xPrefsViewController.m */; }; + 30D709C2236F7E3200AAB7C3 /* S9xPrefsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 30D709C0236F7E3200AAB7C3 /* S9xPrefsViewController.xib */; }; + 30D709C5236F90DF00AAB7C3 /* S9xButtonConfigTextField.m in Sources */ = {isa = PBXBuildFile; fileRef = 30D709C4236F90DF00AAB7C3 /* S9xButtonConfigTextField.m */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -261,6 +265,13 @@ 30D15CEF22CE6B5A005BC352 /* snes9x_framework.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = snes9x_framework.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 30D15CF122CE6B5A005BC352 /* snes9x_framework.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = snes9x_framework.h; sourceTree = ""; }; 30D15CF222CE6B5A005BC352 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; + 30D2506D2373AACC0076A160 /* S9xPrefsConstants.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xPrefsConstants.m; sourceTree = ""; }; + 30D2506F2373AB880076A160 /* S9xPrefsConstants.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xPrefsConstants.h; sourceTree = ""; }; + 30D709BE236F7E3200AAB7C3 /* S9xPrefsViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xPrefsViewController.h; sourceTree = ""; }; + 30D709BF236F7E3200AAB7C3 /* S9xPrefsViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xPrefsViewController.m; sourceTree = ""; }; + 30D709C0236F7E3200AAB7C3 /* S9xPrefsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = S9xPrefsViewController.xib; sourceTree = ""; }; + 30D709C3236F90DF00AAB7C3 /* S9xButtonConfigTextField.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = S9xButtonConfigTextField.h; sourceTree = ""; }; + 30D709C4236F90DF00AAB7C3 /* S9xButtonConfigTextField.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = S9xButtonConfigTextField.m; sourceTree = ""; }; 85FEF90620DDB15B00C038E9 /* bml.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = bml.cpp; sourceTree = ""; usesTabs = 1; }; 85FEF90720DDB15C00C038E9 /* bml.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = bml.h; sourceTree = ""; usesTabs = 1; }; 85FEF90A20DDB18D00C038E9 /* sha256.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = sha256.cpp; sourceTree = ""; usesTabs = 1; }; @@ -602,6 +613,13 @@ 3071471F230E379600917F82 /* Info.plist */, 30714720230E379600917F82 /* main.m */, 30714722230E379600917F82 /* Snes9x.entitlements */, + 30D709BE236F7E3200AAB7C3 /* S9xPrefsViewController.h */, + 30D709BF236F7E3200AAB7C3 /* S9xPrefsViewController.m */, + 30D709C0236F7E3200AAB7C3 /* S9xPrefsViewController.xib */, + 30D709C3236F90DF00AAB7C3 /* S9xButtonConfigTextField.h */, + 30D709C4236F90DF00AAB7C3 /* S9xButtonConfigTextField.m */, + 30D2506D2373AACC0076A160 /* S9xPrefsConstants.m */, + 30D2506F2373AB880076A160 /* S9xPrefsConstants.h */, ); path = Snes9x; sourceTree = ""; @@ -1114,6 +1132,7 @@ 30D709B2236F731B00AAB7C3 /* CART.icns in Resources */, 30D709B7236F731B00AAB7C3 /* musicbox_ledon.icns in Resources */, 30D709B6236F731B00AAB7C3 /* folder_Freezes.icns in Resources */, + 30D709C2236F7E3200AAB7C3 /* S9xPrefsViewController.xib in Resources */, 3071471E230E379600917F82 /* MainMenu.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1136,8 +1155,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 30D709C5236F90DF00AAB7C3 /* S9xButtonConfigTextField.m in Sources */, 30714721230E379600917F82 /* main.m in Sources */, 30714719230E379500917F82 /* AppDelegate.m in Sources */, + 30D709C1236F7E3200AAB7C3 /* S9xPrefsViewController.m in Sources */, + 30D2506E2373AACC0076A160 /* S9xPrefsConstants.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };