mirror of https://github.com/LIJI32/SameBoy.git
597 lines
23 KiB
Objective-C
597 lines
23 KiB
Objective-C
#import "GBPreferencesWindow.h"
|
||
#import "GBJoyConManager.h"
|
||
#import "NSString+StringForKey.h"
|
||
#import "GBButtons.h"
|
||
#import "BigSurToolbar.h"
|
||
#import "GBViewMetal.h"
|
||
#import "GBWarningPopover.h"
|
||
#import <Carbon/Carbon.h>
|
||
|
||
@implementation GBPreferencesWindow
|
||
{
|
||
bool is_button_being_modified;
|
||
NSInteger button_being_modified;
|
||
signed joystick_configuration_state;
|
||
NSString *joystick_being_configured;
|
||
bool joypad_wait;
|
||
|
||
NSEventModifierFlags previousModifiers;
|
||
}
|
||
|
||
- (NSWindowToolbarStyle)toolbarStyle
|
||
{
|
||
return NSWindowToolbarStylePreference;
|
||
}
|
||
|
||
- (void)close
|
||
{
|
||
joystick_configuration_state = -1;
|
||
[self.configureJoypadButton setEnabled:true];
|
||
[self.skipButton setEnabled:false];
|
||
[self.configureJoypadButton setTitle:@"Configure Controller"];
|
||
[super close];
|
||
}
|
||
|
||
static inline NSString *keyEquivalentString(NSMenuItem *item)
|
||
{
|
||
return [NSString stringWithFormat:@"%s%@", (item.keyEquivalentModifierMask & NSEventModifierFlagShift)? "^":"", item.keyEquivalent];
|
||
}
|
||
|
||
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
|
||
{
|
||
if (self.playerListButton.selectedTag == 0) {
|
||
return GBKeyboardButtonCount;
|
||
}
|
||
return GBPerPlayerButtonCount;
|
||
}
|
||
|
||
- (unsigned) usesForKey:(unsigned) key
|
||
{
|
||
unsigned ret = 0;
|
||
for (unsigned player = 4; player--;) {
|
||
for (unsigned button = player == 0? GBKeyboardButtonCount:GBPerPlayerButtonCount; button--;) {
|
||
NSNumber *other = [[NSUserDefaults standardUserDefaults] valueForKey:button_to_preference_name(button, player)];
|
||
if (other && [other unsignedIntValue] == key) {
|
||
ret++;
|
||
}
|
||
}
|
||
}
|
||
return ret;
|
||
}
|
||
|
||
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||
{
|
||
if ([tableColumn.identifier isEqualToString:@"keyName"]) {
|
||
return GBButtonNames[row];
|
||
}
|
||
|
||
if (is_button_being_modified && button_being_modified == row) {
|
||
return @"Select a new key…";
|
||
}
|
||
|
||
NSNumber *key = [[NSUserDefaults standardUserDefaults] valueForKey:button_to_preference_name(row, self.playerListButton.selectedTag)];
|
||
if (key) {
|
||
if ([self usesForKey:[key unsignedIntValue]] > 1) {
|
||
return [[NSAttributedString alloc] initWithString:[NSString displayStringForKeyCode: [key unsignedIntegerValue]]
|
||
attributes:@{NSForegroundColorAttributeName: [NSColor colorWithRed:0.9375 green:0.25 blue:0.25 alpha:1.0],
|
||
NSFontAttributeName: [NSFont boldSystemFontOfSize:[NSFont systemFontSize]]
|
||
}];
|
||
}
|
||
return [NSString displayStringForKeyCode: [key unsignedIntegerValue]];
|
||
}
|
||
|
||
return @"";
|
||
}
|
||
|
||
- (BOOL)tableView:(NSTableView *)tableView shouldEditTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
|
||
{
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
is_button_being_modified = true;
|
||
button_being_modified = row;
|
||
tableView.enabled = false;
|
||
self.playerListButton.enabled = false;
|
||
[tableView reloadData];
|
||
[self makeFirstResponder:self];
|
||
});
|
||
return false;
|
||
}
|
||
|
||
-(void)keyDown:(NSEvent *)theEvent
|
||
{
|
||
if (!is_button_being_modified) {
|
||
if (self.firstResponder != self.controlsTableView && [theEvent type] != NSEventTypeFlagsChanged) {
|
||
[super keyDown:theEvent];
|
||
}
|
||
return;
|
||
}
|
||
|
||
is_button_being_modified = false;
|
||
|
||
[[NSUserDefaults standardUserDefaults] setInteger:theEvent.keyCode
|
||
forKey:button_to_preference_name(button_being_modified, self.playerListButton.selectedTag)];
|
||
self.controlsTableView.enabled = true;
|
||
self.playerListButton.enabled = true;
|
||
[self.controlsTableView reloadData];
|
||
[self makeFirstResponder:self.controlsTableView];
|
||
}
|
||
|
||
- (void) flagsChanged:(NSEvent *)event
|
||
{
|
||
if (event.modifierFlags > previousModifiers) {
|
||
[self keyDown:event];
|
||
}
|
||
|
||
previousModifiers = event.modifierFlags;
|
||
}
|
||
|
||
- (void)updatePalettesMenu
|
||
{
|
||
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
|
||
NSDictionary *themes = [defaults dictionaryForKey:@"GBThemes"];
|
||
NSMenu *menu = _colorPalettePopupButton.menu;
|
||
while (menu.itemArray.count != 4) {
|
||
[menu removeItemAtIndex:4];
|
||
}
|
||
[menu addItem:[NSMenuItem separatorItem]];
|
||
for (NSString *name in [themes.allKeys sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)]) {
|
||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:name action:nil keyEquivalent:@""];
|
||
item.tag = -2;
|
||
[menu addItem:item];
|
||
}
|
||
if (themes) {
|
||
[menu addItem:[NSMenuItem separatorItem]];
|
||
}
|
||
NSMenuItem *item = [[NSMenuItem alloc] initWithTitle:@"Custom…" action:nil keyEquivalent:@""];
|
||
item.tag = -1;
|
||
[menu addItem:item];
|
||
}
|
||
|
||
- (IBAction)colorPaletteChanged:(id)sender
|
||
{
|
||
signed tag = [sender selectedItem].tag;
|
||
if (tag == -2) {
|
||
[[NSUserDefaults standardUserDefaults] setObject:@(-1)
|
||
forKey:@"GBColorPalette"];
|
||
[[NSUserDefaults standardUserDefaults] setObject:[sender selectedItem].title
|
||
forKey:@"GBCurrentTheme"];
|
||
|
||
}
|
||
else if (tag == -1) {
|
||
[[NSUserDefaults standardUserDefaults] setObject:@(-1)
|
||
forKey:@"GBColorPalette"];
|
||
[_paletteEditorController awakeFromNib];
|
||
[self beginSheet:_paletteEditor completionHandler:^(NSModalResponse returnCode) {
|
||
[self updatePalettesMenu];
|
||
[_colorPalettePopupButton selectItemWithTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] ?: @""];
|
||
}];
|
||
}
|
||
else {
|
||
[[NSUserDefaults standardUserDefaults] setObject:@([sender selectedItem].tag)
|
||
forKey:@"GBColorPalette"];
|
||
}
|
||
[[NSNotificationCenter defaultCenter] postNotificationName:@"GBColorPaletteChanged" object:nil];
|
||
}
|
||
|
||
- (IBAction)hotkey1Changed:(id)sender
|
||
{
|
||
[[NSUserDefaults standardUserDefaults] setObject:keyEquivalentString([sender selectedItem])
|
||
forKey:@"GBJoypadHotkey1"];
|
||
}
|
||
|
||
- (IBAction)hotkey2Changed:(id)sender
|
||
{
|
||
[[NSUserDefaults standardUserDefaults] setObject:keyEquivalentString([sender selectedItem])
|
||
forKey:@"GBJoypadHotkey2"];
|
||
}
|
||
|
||
|
||
- (IBAction) configureJoypad:(id)sender
|
||
{
|
||
[self.configureJoypadButton setEnabled:false];
|
||
[self.skipButton setEnabled:true];
|
||
joystick_being_configured = nil;
|
||
[self advanceConfigurationStateMachine];
|
||
}
|
||
|
||
- (IBAction) skipButton:(id)sender
|
||
{
|
||
[self advanceConfigurationStateMachine];
|
||
}
|
||
|
||
- (void) advanceConfigurationStateMachine
|
||
{
|
||
joystick_configuration_state++;
|
||
if (joystick_configuration_state == GBUnderclock) {
|
||
[self.configureJoypadButton setTitle:@"Press Button for Slo-Mo"]; // Full name is too long :<
|
||
}
|
||
else if (joystick_configuration_state < GBTotalButtonCount) {
|
||
[self.configureJoypadButton setTitle:[NSString stringWithFormat:@"Press Button for %@", GBButtonNames[joystick_configuration_state]]];
|
||
}
|
||
else {
|
||
joystick_configuration_state = -1;
|
||
[self.configureJoypadButton setEnabled:true];
|
||
[self.skipButton setEnabled:false];
|
||
[self.configureJoypadButton setTitle:@"Configure Joypad"];
|
||
}
|
||
}
|
||
|
||
- (void)controller:(JOYController *)controller buttonChangedState:(JOYButton *)button
|
||
{
|
||
/* Debounce */
|
||
if (joypad_wait) return;
|
||
joypad_wait = true;
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
joypad_wait = false;
|
||
});
|
||
|
||
if (!button.isPressed) return;
|
||
if (joystick_configuration_state == -1) return;
|
||
if (joystick_configuration_state == GBTotalButtonCount) return;
|
||
if (!joystick_being_configured) {
|
||
joystick_being_configured = controller.uniqueID;
|
||
}
|
||
else if (![joystick_being_configured isEqualToString:controller.uniqueID]) {
|
||
return;
|
||
}
|
||
|
||
NSMutableDictionary *instance_mappings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitInstanceMapping"] mutableCopy];
|
||
|
||
NSMutableDictionary *name_mappings = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitNameMapping"] mutableCopy];
|
||
|
||
|
||
if (!instance_mappings) {
|
||
instance_mappings = [[NSMutableDictionary alloc] init];
|
||
}
|
||
|
||
if (!name_mappings) {
|
||
name_mappings = [[NSMutableDictionary alloc] init];
|
||
}
|
||
|
||
NSMutableDictionary *mapping = nil;
|
||
if (joystick_configuration_state != 0) {
|
||
mapping = [instance_mappings[controller.uniqueID] mutableCopy];
|
||
}
|
||
else {
|
||
mapping = [[NSMutableDictionary alloc] init];
|
||
}
|
||
|
||
|
||
static const unsigned gb_to_joykit[] = {
|
||
[GBRight] = JOYButtonUsageDPadRight,
|
||
[GBLeft] = JOYButtonUsageDPadLeft,
|
||
[GBUp] = JOYButtonUsageDPadUp,
|
||
[GBDown] = JOYButtonUsageDPadDown,
|
||
[GBA] = JOYButtonUsageA,
|
||
[GBB] = JOYButtonUsageB,
|
||
[GBSelect] = JOYButtonUsageSelect,
|
||
[GBStart] = JOYButtonUsageStart,
|
||
[GBRapidA] = GBJoyKitRapidA,
|
||
[GBRapidB] = GBJoyKitRapidB,
|
||
[GBTurbo] = JOYButtonUsageL1,
|
||
[GBRewind] = JOYButtonUsageL2,
|
||
[GBUnderclock] = JOYButtonUsageR1,
|
||
[GBHotkey1] = GBJoyKitHotkey1,
|
||
[GBHotkey2] = GBJoyKitHotkey2,
|
||
};
|
||
|
||
if (joystick_configuration_state == GBUnderclock) {
|
||
mapping[@"AnalogUnderclock"] = nil;
|
||
double max = 0;
|
||
for (JOYAxis *axis in controller.axes) {
|
||
if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) {
|
||
mapping[@"AnalogUnderclock"] = @(axis.uniqueID);
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
if (joystick_configuration_state == GBTurbo) {
|
||
mapping[@"AnalogTurbo"] = nil;
|
||
double max = 0;
|
||
for (JOYAxis *axis in controller.axes) {
|
||
if ((axis.value > 0.5 || (axis.equivalentButtonUsage == button.usage)) && axis.value >= max) {
|
||
max = axis.value;
|
||
mapping[@"AnalogTurbo"] = @(axis.uniqueID);
|
||
}
|
||
}
|
||
}
|
||
|
||
mapping[n2s(button.uniqueID)] = @(gb_to_joykit[joystick_configuration_state]);
|
||
|
||
instance_mappings[controller.uniqueID] = mapping;
|
||
name_mappings[controller.deviceName] = mapping;
|
||
[[NSUserDefaults standardUserDefaults] setObject:instance_mappings forKey:@"JoyKitInstanceMapping"];
|
||
[[NSUserDefaults standardUserDefaults] setObject:name_mappings forKey:@"JoyKitNameMapping"];
|
||
[self advanceConfigurationStateMachine];
|
||
}
|
||
|
||
- (void)awakeFromNib
|
||
{
|
||
[super awakeFromNib];
|
||
[self updateBootROMFolderButton];
|
||
[[NSDistributedNotificationCenter defaultCenter] addObserver:self.controlsTableView selector:@selector(reloadData) name:(NSString*)kTISNotifySelectedKeyboardInputSourceChanged object:nil];
|
||
[JOYController registerListener:self];
|
||
joystick_configuration_state = -1;
|
||
[self refreshJoypadMenu:nil];
|
||
|
||
NSString *keyEquivalent = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBJoypadHotkey1"];
|
||
for (NSMenuItem *item in _hotkey1PopupButton.menu.itemArray) {
|
||
if ([keyEquivalent isEqualToString:keyEquivalentString(item)]) {
|
||
[_hotkey1PopupButton selectItem:item];
|
||
break;
|
||
}
|
||
}
|
||
|
||
keyEquivalent = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBJoypadHotkey2"];
|
||
for (NSMenuItem *item in _hotkey2PopupButton.menu.itemArray) {
|
||
if ([keyEquivalent isEqualToString:keyEquivalentString(item)]) {
|
||
[_hotkey2PopupButton selectItem:item];
|
||
break;
|
||
}
|
||
}
|
||
|
||
[self updatePalettesMenu];
|
||
NSInteger mode = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBColorPalette"];
|
||
if (mode >= 0) {
|
||
[_colorPalettePopupButton selectItemWithTag:mode];
|
||
}
|
||
else {
|
||
[_colorPalettePopupButton selectItemWithTitle:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBCurrentTheme"] ?: @""];
|
||
}
|
||
|
||
_fontSizeStepper.intValue = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"];
|
||
[self updateFonts];
|
||
|
||
double cap = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboCap"];
|
||
if (cap) {
|
||
_turboCapSlider.intValue = round(cap * 100);
|
||
_turboCapButton.state = NSOnState;
|
||
}
|
||
[self turboCapToggled:_turboCapButton];
|
||
}
|
||
|
||
- (IBAction)fontSizeChanged:(id)sender
|
||
{
|
||
NSString *selectedFont = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"];
|
||
[[NSUserDefaults standardUserDefaults] setInteger:[sender intValue] forKey:@"GBDebuggerFontSize"];
|
||
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
|
||
}
|
||
|
||
- (IBAction)fontChanged:(id)sender
|
||
{
|
||
NSString *selectedFont = _fontPopupButton.selectedItem.title;
|
||
[[NSUserDefaults standardUserDefaults] setObject:selectedFont forKey:@"GBDebuggerFont"];
|
||
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
|
||
|
||
}
|
||
|
||
- (void)updateFonts
|
||
{
|
||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||
NSFontManager *fontManager = [NSFontManager sharedFontManager];
|
||
NSArray *allFamilies = [fontManager availableFontFamilies];
|
||
NSMutableSet *families = [NSMutableSet set];
|
||
for (NSString *family in allFamilies) {
|
||
if ([fontManager fontNamed:family hasTraits:NSFixedPitchFontMask]) {
|
||
[families addObject:family];
|
||
}
|
||
}
|
||
|
||
bool hasSFMono = false;
|
||
if (@available(macOS 10.15, *)) {
|
||
hasSFMono = [[NSFont monospacedSystemFontOfSize:12 weight:NSFontWeightRegular].displayName containsString:@"SF"];
|
||
}
|
||
|
||
if (hasSFMono) {
|
||
[families addObject:@"SF Mono"];
|
||
}
|
||
|
||
NSArray *sortedFamilies = [[families allObjects] sortedArrayUsingSelector:@selector(compare:)];
|
||
|
||
dispatch_async(dispatch_get_main_queue(), ^{
|
||
if (![families containsObject:[[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"]]) {
|
||
[[NSUserDefaults standardUserDefaults] removeObjectForKey:@"GBDebuggerFont"];
|
||
}
|
||
|
||
[_fontPopupButton.menu removeAllItems];
|
||
for (NSString *family in sortedFamilies) {
|
||
[_fontPopupButton addItemWithTitle:family];
|
||
}
|
||
NSString *selectedFont = [[NSUserDefaults standardUserDefaults] stringForKey:@"GBDebuggerFont"];
|
||
[_fontPopupButton selectItemWithTitle:selectedFont];
|
||
[_fontPopupButton setDisplayTitle:[NSString stringWithFormat:@"%@ %upt", selectedFont, (unsigned)[[NSUserDefaults standardUserDefaults] integerForKey:@"GBDebuggerFontSize"]]];
|
||
});
|
||
});
|
||
}
|
||
|
||
- (void)dealloc
|
||
{
|
||
[JOYController unregisterListener:self];
|
||
[[NSDistributedNotificationCenter defaultCenter] removeObserver:self.controlsTableView];
|
||
}
|
||
|
||
- (IBAction)selectOtherBootROMFolder:(id)sender
|
||
{
|
||
NSOpenPanel *panel = [[NSOpenPanel alloc] init];
|
||
[panel setCanChooseDirectories:true];
|
||
[panel setCanChooseFiles:false];
|
||
[panel setPrompt:@"Select"];
|
||
[panel setDirectoryURL:[[NSUserDefaults standardUserDefaults] URLForKey:@"GBBootROMsFolder"]];
|
||
[panel beginSheetModalForWindow:self completionHandler:^(NSModalResponse result) {
|
||
if (result == NSModalResponseOK) {
|
||
NSURL *url = [[panel URLs] firstObject];
|
||
[[NSUserDefaults standardUserDefaults] setURL:url forKey:@"GBBootROMsFolder"];
|
||
}
|
||
[self updateBootROMFolderButton];
|
||
}];
|
||
|
||
}
|
||
|
||
- (void) updateBootROMFolderButton
|
||
{
|
||
NSURL *url = [[NSUserDefaults standardUserDefaults] URLForKey:@"GBBootROMsFolder"];
|
||
BOOL is_dir = false;
|
||
[[NSFileManager defaultManager] fileExistsAtPath:[url path] isDirectory:&is_dir];
|
||
if (!is_dir) url = nil;
|
||
|
||
if (url) {
|
||
[self.bootROMsFolderItem setTitle:[url lastPathComponent]];
|
||
NSImage *icon = [[NSWorkspace sharedWorkspace] iconForFile:[url path]];
|
||
[icon setSize:NSMakeSize(16, 16)];
|
||
[self.bootROMsFolderItem setHidden:false];
|
||
[self.bootROMsFolderItem setImage:icon];
|
||
[self.bootROMsButton selectItemAtIndex:1];
|
||
}
|
||
else {
|
||
[self.bootROMsFolderItem setHidden:true];
|
||
[self.bootROMsButton selectItemAtIndex:0];
|
||
}
|
||
}
|
||
|
||
- (IBAction)useBuiltinBootROMs:(id)sender
|
||
{
|
||
[[NSUserDefaults standardUserDefaults] setURL:nil forKey:@"GBBootROMsFolder"];
|
||
[self updateBootROMFolderButton];
|
||
}
|
||
|
||
- (void)controllerConnected:(JOYController *)controller
|
||
{
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[self refreshJoypadMenu:nil];
|
||
});
|
||
}
|
||
|
||
- (void)controllerDisconnected:(JOYController *)controller
|
||
{
|
||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||
[self refreshJoypadMenu:nil];
|
||
});
|
||
}
|
||
|
||
- (IBAction)refreshJoypadMenu:(id)sender
|
||
{
|
||
bool preferred_is_connected = false;
|
||
NSString *player_string = n2s(self.playerListButton.selectedTag);
|
||
NSString *selected_controller = [[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitDefaultControllers"][player_string];
|
||
|
||
[self.preferredJoypadButton removeAllItems];
|
||
[self.preferredJoypadButton addItemWithTitle:@"None"];
|
||
for (JOYController *controller in [JOYController allControllers]) {
|
||
[self.preferredJoypadButton addItemWithTitle:[NSString stringWithFormat:@"%@ (%@)", controller.deviceName, controller.uniqueID]];
|
||
|
||
self.preferredJoypadButton.lastItem.identifier = controller.uniqueID;
|
||
|
||
if ([controller.uniqueID isEqualToString:selected_controller]) {
|
||
preferred_is_connected = true;
|
||
[self.preferredJoypadButton selectItem:self.preferredJoypadButton.lastItem];
|
||
}
|
||
}
|
||
|
||
if (!preferred_is_connected && selected_controller) {
|
||
[self.preferredJoypadButton addItemWithTitle:[NSString stringWithFormat:@"Unavailable Controller (%@)", selected_controller]];
|
||
self.preferredJoypadButton.lastItem.identifier = selected_controller;
|
||
[self.preferredJoypadButton selectItem:self.preferredJoypadButton.lastItem];
|
||
}
|
||
|
||
|
||
if (!selected_controller) {
|
||
[self.preferredJoypadButton selectItemWithTitle:@"None"];
|
||
}
|
||
[self.controlsTableView reloadData];
|
||
}
|
||
|
||
- (IBAction)changeDefaultJoypad:(id)sender
|
||
{
|
||
NSMutableDictionary *default_joypads = [[[NSUserDefaults standardUserDefaults] dictionaryForKey:@"JoyKitDefaultControllers"] mutableCopy];
|
||
if (!default_joypads) {
|
||
default_joypads = [[NSMutableDictionary alloc] init];
|
||
}
|
||
|
||
NSString *player_string = n2s(self.playerListButton.selectedTag);
|
||
if ([[sender titleOfSelectedItem] isEqualToString:@"None"]) {
|
||
[default_joypads removeObjectForKey:player_string];
|
||
}
|
||
else {
|
||
default_joypads[player_string] = [[sender selectedItem] identifier];
|
||
}
|
||
[[NSUserDefaults standardUserDefaults] setObject:default_joypads forKey:@"JoyKitDefaultControllers"];
|
||
}
|
||
|
||
- (IBAction)displayColorCorrectionHelp:(id)sender
|
||
{
|
||
[GBWarningPopover popoverWithContents:
|
||
GB_inline_const(NSString *[], {
|
||
[GB_COLOR_CORRECTION_DISABLED] = @"Colors are directly interpreted as sRGB, resulting in unbalanced colors and inaccurate hues.",
|
||
[GB_COLOR_CORRECTION_CORRECT_CURVES] = @"Colors have their brightness corrected, but hues remain unbalanced.",
|
||
[GB_COLOR_CORRECTION_MODERN_BALANCED] = @"Emulates a modern display. Blue contrast is moderately enhanced at the cost of slight hue inaccuracy.",
|
||
[GB_COLOR_CORRECTION_MODERN_BOOST_CONTRAST] = @"Like Modern – Balanced, but further boosts the contrast of greens and magentas that is lacking on the original hardware.",
|
||
[GB_COLOR_CORRECTION_REDUCE_CONTRAST] = @"Slightly reduce the contrast to better represent the tint and contrast of the original display.",
|
||
[GB_COLOR_CORRECTION_LOW_CONTRAST] = @"Harshly reduce the contrast to accurately represent the tint and low contrast of the original display.",
|
||
[GB_COLOR_CORRECTION_MODERN_ACCURATE] = @"Emulates a modern display. Colors have their hues and brightness corrected.",
|
||
}) [self.colorCorrectionPopupButton.selectedItem.tag]
|
||
title:self.colorCorrectionPopupButton.selectedItem.title
|
||
onView:sender
|
||
timeout:6
|
||
preferredEdge:NSRectEdgeMaxX];
|
||
}
|
||
|
||
- (IBAction)displayHighPassHelp:(id)sender
|
||
{
|
||
[GBWarningPopover popoverWithContents:
|
||
GB_inline_const(NSString *[], {
|
||
[GB_HIGHPASS_OFF] = @"No high-pass filter will be applied. DC offset will be kept, pausing and resuming will trigger audio pops.",
|
||
[GB_HIGHPASS_ACCURATE] = @"An accurate high-pass filter will be applied, removing the DC offset while somewhat attenuating the bass.",
|
||
[GB_HIGHPASS_REMOVE_DC_OFFSET] = @"A high-pass filter will be applied to the DC offset itself, removing the DC offset while preserving the waveform.",
|
||
}) [self.highpassFilterPopupButton.selectedItem.tag]
|
||
title:self.highpassFilterPopupButton.selectedItem.title
|
||
onView:sender
|
||
timeout:6
|
||
preferredEdge:NSRectEdgeMaxX];
|
||
}
|
||
|
||
- (IBAction)arrangeJoyCons:(id)sender
|
||
{
|
||
[GBJoyConManager sharedInstance].arrangementMode = true;
|
||
[self beginSheet:self.joyconsSheet completionHandler:nil];
|
||
}
|
||
|
||
- (IBAction)closeJoyConsSheet:(id)sender
|
||
{
|
||
[self endSheet:self.joyconsSheet];
|
||
[GBJoyConManager sharedInstance].arrangementMode = false;
|
||
}
|
||
|
||
- (IBAction)turboCapToggled:(NSButton *)sender
|
||
{
|
||
if (sender.state) {
|
||
_turboCapSlider.enabled = true;
|
||
[self turboCapChanged:_turboCapSlider];
|
||
if (@available(macOS 10.10, *)) {
|
||
_turboCapLabel.textColor = [NSColor labelColor];
|
||
}
|
||
else {
|
||
_turboCapLabel.textColor = [NSColor blackColor];
|
||
}
|
||
}
|
||
else {
|
||
_turboCapSlider.enabled = false;
|
||
_turboCapLabel.enabled = false;
|
||
[[NSUserDefaults standardUserDefaults] setDouble:0 forKey:@"GBTurboCap"];
|
||
if (@available(macOS 10.10, *)) {
|
||
_turboCapLabel.textColor = [NSColor disabledControlTextColor];
|
||
}
|
||
else {
|
||
_turboCapLabel.textColor = [NSColor colorWithWhite:0 alpha:0.25];
|
||
}
|
||
}
|
||
}
|
||
|
||
- (IBAction)turboCapChanged:(NSSlider *)sender
|
||
{
|
||
_turboCapLabel.stringValue = [NSString stringWithFormat:@"%d%%", sender.intValue];
|
||
[[NSUserDefaults standardUserDefaults] setDouble:sender.doubleValue / 100.0 forKey:@"GBTurboCap"];
|
||
}
|
||
|
||
@end
|