Add Rapid A/B to Cocoa and SDL, closes #589

This commit is contained in:
Lior Halphon
2024-08-30 16:12:31 +03:00
parent d4c715b5f0
commit d97c2fb701
11 changed files with 148 additions and 40 deletions

View File

@@ -43,7 +43,7 @@ static uint32_t color_to_int(NSColor *color)
[NSApplication sharedApplication].applicationIconImage = [NSImage imageNamed:@"AppIcon"]; [NSApplication sharedApplication].applicationIconImage = [NSImage imageNamed:@"AppIcon"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
for (unsigned i = 0; i < GBButtonCount; i++) { for (unsigned i = 0; i < GBKeyboardButtonCount; i++) {
if ([[defaults objectForKey:button_to_preference_name(i, 0)] isKindOfClass:[NSString class]]) { if ([[defaults objectForKey:button_to_preference_name(i, 0)] isKindOfClass:[NSString class]]) {
[defaults removeObjectForKey:button_to_preference_name(i, 0)]; [defaults removeObjectForKey:button_to_preference_name(i, 0)];
} }

View File

@@ -7,20 +7,24 @@ typedef enum {
GBB, GBB,
GBSelect, GBSelect,
GBStart, GBStart,
GBRapidA,
GBRapidB,
GBTurbo, GBTurbo,
GBRewind, GBRewind,
GBUnderclock, GBUnderclock,
GBHotkey1, GBHotkey1,
GBHotkey2, GBHotkey2,
GBJoypadButtonCount, GBTotalButtonCount,
GBButtonCount = GBUnderclock + 1, GBKeyboardButtonCount = GBUnderclock + 1,
GBGameBoyButtonCount = GBStart + 1, GBPerPlayerButtonCount = GBRapidB + 1,
} GBButton; } GBButton;
#define GBJoyKitHotkey1 JOYButtonUsageGeneric0 + 0x100 #define GBJoyKitHotkey1 JOYButtonUsageGeneric0 + 0x100
#define GBJoyKitHotkey2 JOYButtonUsageGeneric0 + 0x101 #define GBJoyKitHotkey2 JOYButtonUsageGeneric0 + 0x101
#define GBJoyKitRapidA JOYButtonUsageGeneric0 + 0x102
#define GBJoyKitRapidB JOYButtonUsageGeneric0 + 0x103
extern NSString const *GBButtonNames[GBJoypadButtonCount]; extern NSString const *GBButtonNames[GBTotalButtonCount];
static inline NSString *n2s(uint64_t number) static inline NSString *n2s(uint64_t number)
{ {

View File

@@ -1,4 +1,4 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
#import "GBButtons.h" #import "GBButtons.h"
NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Turbo", @"Rewind", @"Slow-Motion", @"Hotkey 1", @"Hotkey 2"}; NSString const *GBButtonNames[] = {@"Right", @"Left", @"Up", @"Down", @"A", @"B", @"Select", @"Start", @"Rapid A", @"Rapid B", @"Turbo", @"Rewind", @"Slow-Motion", @"Hotkey 1", @"Hotkey 2"};

View File

@@ -40,16 +40,16 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView - (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView
{ {
if (self.playerListButton.selectedTag == 0) { if (self.playerListButton.selectedTag == 0) {
return GBButtonCount; return GBKeyboardButtonCount;
} }
return GBGameBoyButtonCount; return GBPerPlayerButtonCount;
} }
- (unsigned) usesForKey:(unsigned) key - (unsigned) usesForKey:(unsigned) key
{ {
unsigned ret = 0; unsigned ret = 0;
for (unsigned player = 4; player--;) { for (unsigned player = 4; player--;) {
for (unsigned button = player == 0? GBButtonCount:GBGameBoyButtonCount; button--;) { for (unsigned button = player == 0? GBKeyboardButtonCount:GBPerPlayerButtonCount; button--;) {
NSNumber *other = [[NSUserDefaults standardUserDefaults] valueForKey:button_to_preference_name(button, player)]; NSNumber *other = [[NSUserDefaults standardUserDefaults] valueForKey:button_to_preference_name(button, player)];
if (other && [other unsignedIntValue] == key) { if (other && [other unsignedIntValue] == key) {
ret++; ret++;
@@ -205,7 +205,7 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
if (joystick_configuration_state == GBUnderclock) { if (joystick_configuration_state == GBUnderclock) {
[self.configureJoypadButton setTitle:@"Press Button for Slo-Mo"]; // Full name is too long :< [self.configureJoypadButton setTitle:@"Press Button for Slo-Mo"]; // Full name is too long :<
} }
else if (joystick_configuration_state < GBJoypadButtonCount) { else if (joystick_configuration_state < GBTotalButtonCount) {
[self.configureJoypadButton setTitle:[NSString stringWithFormat:@"Press Button for %@", GBButtonNames[joystick_configuration_state]]]; [self.configureJoypadButton setTitle:[NSString stringWithFormat:@"Press Button for %@", GBButtonNames[joystick_configuration_state]]];
} }
else { else {
@@ -227,7 +227,7 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
if (!button.isPressed) return; if (!button.isPressed) return;
if (joystick_configuration_state == -1) return; if (joystick_configuration_state == -1) return;
if (joystick_configuration_state == GBJoypadButtonCount) return; if (joystick_configuration_state == GBTotalButtonCount) return;
if (!joystick_being_configured) { if (!joystick_being_configured) {
joystick_being_configured = controller.uniqueID; joystick_being_configured = controller.uniqueID;
} }
@@ -266,6 +266,8 @@ static inline NSString *keyEquivalentString(NSMenuItem *item)
[GBB] = JOYButtonUsageB, [GBB] = JOYButtonUsageB,
[GBSelect] = JOYButtonUsageSelect, [GBSelect] = JOYButtonUsageSelect,
[GBStart] = JOYButtonUsageStart, [GBStart] = JOYButtonUsageStart,
[GBRapidA] = GBJoyKitRapidA,
[GBRapidB] = GBJoyKitRapidB,
[GBTurbo] = JOYButtonUsageL1, [GBTurbo] = JOYButtonUsageL1,
[GBRewind] = JOYButtonUsageL2, [GBRewind] = JOYButtonUsageL2,
[GBUnderclock] = JOYButtonUsageR1, [GBUnderclock] = JOYButtonUsageR1,

View File

@@ -119,6 +119,9 @@ static const uint8_t workboy_vk_to_key[] = {
bool _mouseControlEnabled; bool _mouseControlEnabled;
NSMutableDictionary<NSNumber *, JOYController *> *_controllerMapping; NSMutableDictionary<NSNumber *, JOYController *> *_controllerMapping;
unsigned _lastPlayerCount; unsigned _lastPlayerCount;
bool _rapidA[4], _rapidB[4];
uint8_t _rapidACount[4], _rapidBCount[4];
} }
+ (instancetype)alloc + (instancetype)alloc
@@ -343,6 +346,17 @@ static const uint8_t workboy_vk_to_key[] = {
(analogClockMultiplierValid && analogClockMultiplier < 1)) { (analogClockMultiplierValid && analogClockMultiplier < 1)) {
[self.osdView displayText:@"Slow motion…"]; [self.osdView displayText:@"Slow motion…"];
} }
for (unsigned i = GB_get_player_count(_gb); i--;) {
if (_rapidA[i]) {
_rapidACount[i]++;
GB_set_key_state_for_player(_gb, GB_KEY_A, i, !(_rapidACount[i] & 2));
}
if (_rapidB[i]) {
_rapidBCount[i]++;
GB_set_key_state_for_player(_gb, GB_KEY_B, i, !(_rapidBCount[i] & 2));
}
}
[super flip]; [super flip];
} }
@@ -370,7 +384,7 @@ static const uint8_t workboy_vk_to_key[] = {
player_count = 2; player_count = 2;
} }
for (unsigned player = 0; player < player_count; player++) { for (unsigned player = 0; player < player_count; player++) {
for (GBButton button = 0; button < GBButtonCount; button++) { for (GBButton button = 0; button < GBKeyboardButtonCount; button++) {
NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)]; NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)];
if (!key) continue; if (!key) continue;
@@ -401,6 +415,18 @@ static const uint8_t workboy_vk_to_key[] = {
analogClockMultiplierValid = false; analogClockMultiplierValid = false;
break; break;
case GBRapidA:
_rapidA[player] = true;
_rapidACount[player] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_A, player, true);
break;
case GBRapidB:
_rapidB[player] = true;
_rapidBCount[player] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_B, player, true);
break;
default: default:
if (self.document.partner) { if (self.document.partner) {
if (player == 0) { if (player == 0) {
@@ -444,7 +470,7 @@ static const uint8_t workboy_vk_to_key[] = {
player_count = 2; player_count = 2;
} }
for (unsigned player = 0; player < player_count; player++) { for (unsigned player = 0; player < player_count; player++) {
for (GBButton button = 0; button < GBButtonCount; button++) { for (GBButton button = 0; button < GBKeyboardButtonCount; button++) {
NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)]; NSNumber *key = [defaults valueForKey:button_to_preference_name(button, player)];
if (!key) continue; if (!key) continue;
@@ -470,6 +496,16 @@ static const uint8_t workboy_vk_to_key[] = {
underclockKeyDown = false; underclockKeyDown = false;
analogClockMultiplierValid = false; analogClockMultiplierValid = false;
break; break;
case GBRapidA:
_rapidA[player] = false;
GB_set_key_state_for_player(_gb, GB_KEY_A, player, false);
break;
case GBRapidB:
_rapidB[player] = false;
GB_set_key_state_for_player(_gb, GB_KEY_B, player, false);
break;
default: default:
if (self.document.partner) { if (self.document.partner) {
@@ -651,7 +687,7 @@ static const uint8_t workboy_vk_to_key[] = {
} }
} }
switch (usage) { switch ((unsigned)usage) {
case JOYButtonUsageNone: break; case JOYButtonUsageNone: break;
case JOYButtonUsageA: GB_set_key_state_for_player(effectiveGB, GB_KEY_A, effectivePlayer, button.isPressed); break; case JOYButtonUsageA: GB_set_key_state_for_player(effectiveGB, GB_KEY_A, effectivePlayer, button.isPressed); break;
@@ -696,7 +732,16 @@ static const uint8_t workboy_vk_to_key[] = {
case JOYButtonUsageDPadUp: GB_set_key_state_for_player(effectiveGB, GB_KEY_UP, effectivePlayer, button.isPressed); break; case JOYButtonUsageDPadUp: GB_set_key_state_for_player(effectiveGB, GB_KEY_UP, effectivePlayer, button.isPressed); break;
case JOYButtonUsageDPadDown: GB_set_key_state_for_player(effectiveGB, GB_KEY_DOWN, effectivePlayer, button.isPressed); break; case JOYButtonUsageDPadDown: GB_set_key_state_for_player(effectiveGB, GB_KEY_DOWN, effectivePlayer, button.isPressed); break;
default: case GBJoyKitRapidA:
_rapidA[effectivePlayer] = button.isPressed;
_rapidACount[effectivePlayer] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_A, effectivePlayer, button.isPressed);
break;
case GBJoyKitRapidB:
_rapidB[effectivePlayer] = button.isPressed;
_rapidBCount[effectivePlayer] = 0;
GB_set_key_state_for_player(_gb, GB_KEY_B, effectivePlayer, button.isPressed);
break; break;
} }
} }

View File

@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11762" systemVersion="16D32" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct"> <document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="21507" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES" customObjectInstantitationMethod="direct">
<dependencies> <dependencies>
<deployment identifier="macosx"/> <deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11762"/> <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="21507"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/> <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies> </dependencies>
<objects> <objects>
@@ -13,7 +13,7 @@
</customObject> </customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/> <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/> <customObject id="-3" userLabel="Application" customClass="NSObject"/>
<textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="oUc-bq-d5t"> <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="YES" id="oUc-bq-d5t">
<rect key="frame" x="0.0" y="0.0" width="66" height="17"/> <rect key="frame" x="0.0" y="0.0" width="66" height="17"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" alignment="left" title="Test" id="xyx-iy-kse"> <textFieldCell key="cell" controlSize="mini" sendsActionOnEndEditing="YES" alignment="left" title="Test" id="xyx-iy-kse">

View File

@@ -986,15 +986,15 @@
</connections> </connections>
</button> </button>
<scrollView focusRingType="none" fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PBp-dj-EIa"> <scrollView focusRingType="none" fixedFrame="YES" autohidesScrollers="YES" horizontalLineScroll="19" horizontalPageScroll="10" verticalLineScroll="19" verticalPageScroll="10" hasHorizontalScroller="NO" hasVerticalScroller="NO" usesPredominantAxisScrolling="NO" horizontalScrollElasticity="none" verticalScrollElasticity="none" translatesAutoresizingMaskIntoConstraints="NO" id="PBp-dj-EIa">
<rect key="frame" x="32" y="124" width="262" height="211"/> <rect key="frame" x="32" y="87" width="262" height="249"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<clipView key="contentView" focusRingType="none" ambiguous="YES" drawsBackground="NO" id="AMs-PO-nid"> <clipView key="contentView" focusRingType="none" drawsBackground="NO" id="AMs-PO-nid">
<rect key="frame" x="1" y="1" width="260" height="209"/> <rect key="frame" x="1" y="1" width="260" height="247"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews> <subviews>
<tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="UDd-IJ-fxX"> <tableView focusRingType="none" verticalHuggingPriority="750" allowsExpansionToolTips="YES" columnAutoresizingStyle="lastColumnOnly" columnReordering="NO" columnResizing="NO" multipleSelection="NO" emptySelection="NO" autosaveColumns="NO" typeSelect="NO" id="UDd-IJ-fxX">
<rect key="frame" x="0.0" y="0.0" width="260" height="209"/> <rect key="frame" x="0.0" y="0.0" width="260" height="247"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<size key="intercellSpacing" width="3" height="2"/> <size key="intercellSpacing" width="3" height="2"/>
<color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/> <color key="backgroundColor" name="controlBackgroundColor" catalog="System" colorSpace="catalog"/>
<color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/> <color key="gridColor" name="gridColor" catalog="System" colorSpace="catalog"/>
@@ -1044,7 +1044,7 @@
</scroller> </scroller>
</scrollView> </scrollView>
<textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fcF-wc-KwM"> <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="fcF-wc-KwM">
<rect key="frame" x="30" y="99" width="231" height="17"/> <rect key="frame" x="30" y="62" width="231" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Controller for multiplayer games:" id="AJA-9b-VKI"> <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Controller for multiplayer games:" id="AJA-9b-VKI">
<font key="font" metaFont="system"/> <font key="font" metaFont="system"/>
@@ -1053,7 +1053,7 @@
</textFieldCell> </textFieldCell>
</textField> </textField>
<popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Az-0R-oNw"> <popUpButton verticalHuggingPriority="750" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="0Az-0R-oNw">
<rect key="frame" x="42" y="66" width="255" height="26"/> <rect key="frame" x="42" y="29" width="255" height="26"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/> <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingMiddle" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="hy8-cr-RrE" id="uEC-vN-8Jq"> <popUpButtonCell key="cell" type="push" title="None" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingMiddle" state="on" borderStyle="borderAndBezel" imageScaling="proportionallyDown" inset="2" selectedItem="hy8-cr-RrE" id="uEC-vN-8Jq">
<behavior key="behavior" lightByBackground="YES" lightByGray="YES"/> <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>

View File

@@ -11,6 +11,27 @@ enum scaling_mode {
GB_SDL_SCALING_MAX, GB_SDL_SCALING_MAX,
}; };
enum {
GB_CONF_KEYS_RIGHT = GB_KEY_RIGHT,
GB_CONF_KEYS_LEFT = GB_KEY_LEFT,
GB_CONF_KEYS_UP = GB_KEY_UP,
GB_CONF_KEYS_DOWN = GB_KEY_DOWN,
GB_CONF_KEYS_A = GB_KEY_A,
GB_CONF_KEYS_B = GB_KEY_B,
GB_CONF_KEYS_SELECT = GB_KEY_SELECT,
GB_CONF_KEYS_START = GB_KEY_START,
GB_CONF_KEYS_TURBO,
GB_CONF_KEYS_COUNT,
};
enum {
GB_CONF_KEYS2_REWIND,
GB_CONF_KEYS2_UNDERCLOCK,
GB_CONF_KEYS2_RAPID_A,
GB_CONF_KEYS2_RAPID_B,
GB_CONF_KEYS2_COUNT = 32,
};
typedef enum { typedef enum {
JOYPAD_BUTTON_RIGHT, JOYPAD_BUTTON_RIGHT,
JOYPAD_BUTTON_LEFT, JOYPAD_BUTTON_LEFT,
@@ -26,6 +47,8 @@ typedef enum {
JOYPAD_BUTTON_SLOW_MOTION, JOYPAD_BUTTON_SLOW_MOTION,
JOYPAD_BUTTON_HOTKEY_1, JOYPAD_BUTTON_HOTKEY_1,
JOYPAD_BUTTON_HOTKEY_2, JOYPAD_BUTTON_HOTKEY_2,
JOYPAD_BUTTON_RAPID_A,
JOYPAD_BUTTON_RAPID_B,
JOYPAD_BUTTONS_MAX JOYPAD_BUTTONS_MAX
} joypad_button_t; } joypad_button_t;
@@ -65,7 +88,7 @@ typedef enum {
} hotkey_action_t; } hotkey_action_t;
typedef struct { typedef struct {
SDL_Scancode keys[9]; SDL_Scancode keys[GB_CONF_KEYS_COUNT];
GB_color_correction_mode_t color_correction_mode; GB_color_correction_mode_t color_correction_mode;
enum scaling_mode scaling_mode; enum scaling_mode scaling_mode;
uint8_t blending_mode; uint8_t blending_mode;
@@ -89,7 +112,7 @@ typedef struct {
/* v0.11 */ /* v0.11 */
uint32_t rewind_length; uint32_t rewind_length;
SDL_Scancode keys_2[32]; /* Rewind and underclock, + padding for the future */ SDL_Scancode keys_2[GB_CONF_KEYS2_COUNT]; /* Rewind and underclock, + padding for the future */
uint8_t joypad_configuration[32]; /* 14 Keys + padding for the future*/; uint8_t joypad_configuration[32]; /* 14 Keys + padding for the future*/;
uint8_t joypad_axises[JOYPAD_AXISES_MAX]; uint8_t joypad_axises[JOYPAD_AXISES_MAX];

View File

@@ -1764,16 +1764,17 @@ static const struct menu_item keyboard_menu[] = {
{"Turbo:", modify_key, key_name,}, {"Turbo:", modify_key, key_name,},
{"Rewind:", modify_key, key_name,}, {"Rewind:", modify_key, key_name,},
{"Slow-Motion:", modify_key, key_name,}, {"Slow-Motion:", modify_key, key_name,},
{"Rapid A:", modify_key, key_name,},
{"Rapid B:", modify_key, key_name,},
{"Back", enter_controls_menu}, {"Back", enter_controls_menu},
{NULL,} {NULL,}
}; };
static const char *key_name(unsigned index) static const char *key_name(unsigned index)
{ {
if (index > 8) { SDL_Scancode code = index >= GB_CONF_KEYS_COUNT? configuration.keys_2[index - GB_CONF_KEYS_COUNT] : configuration.keys[index];
return SDL_GetScancodeName(configuration.keys_2[index - 9]); if (!code) return "Not Set";
} return SDL_GetScancodeName(code);
return SDL_GetScancodeName(configuration.keys[index]);
} }
static void enter_keyboard_menu(unsigned index) static void enter_keyboard_menu(unsigned index)
@@ -2532,7 +2533,7 @@ void run_gui(bool is_running)
} }
else if (gui_state == WAITING_FOR_KEY) { else if (gui_state == WAITING_FOR_KEY) {
if (current_selection > 8) { if (current_selection > 8) {
configuration.keys_2[current_selection - 9] = event.key.keysym.scancode; configuration.keys_2[current_selection - GB_CONF_KEYS_COUNT] = event.key.keysym.scancode;
} }
else { else {
configuration.keys[current_selection] = event.key.keysym.scancode; configuration.keys[current_selection] = event.key.keysym.scancode;
@@ -2773,6 +2774,8 @@ void run_gui(bool is_running)
"Slow-Motion", "Slow-Motion",
"Hotkey 1", "Hotkey 1",
"Hotkey 2", "Hotkey 2",
"Rapid A",
"Rapid B",
"", "",
}) [joypad_configuration_progress], }) [joypad_configuration_progress],
gui_palette_native[3], gui_palette_native[0], STYLE_CENTER); gui_palette_native[3], gui_palette_native[0], STYLE_CENTER);

View File

@@ -26,6 +26,8 @@ static bool paused = false;
static uint32_t pixel_buffer_1[256 * 224], pixel_buffer_2[256 * 224]; static uint32_t pixel_buffer_1[256 * 224], pixel_buffer_2[256 * 224];
static uint32_t *active_pixel_buffer = pixel_buffer_1, *previous_pixel_buffer = pixel_buffer_2; static uint32_t *active_pixel_buffer = pixel_buffer_1, *previous_pixel_buffer = pixel_buffer_2;
static bool underclock_down = false, rewind_down = false, do_rewind = false, rewind_paused = false, turbo_down = false; static bool underclock_down = false, rewind_down = false, do_rewind = false, rewind_paused = false, turbo_down = false;
static bool rapid_a = false, rapid_b = false;
static uint8_t rapid_a_count = 0, rapid_b_count = 0;
static double clock_mutliplier = 1.0; static double clock_mutliplier = 1.0;
char *filename = NULL; char *filename = NULL;
@@ -322,8 +324,18 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
} }
} }
else if (button == JOYPAD_BUTTON_RAPID_A) {
rapid_a = event.type == SDL_JOYBUTTONDOWN;
rapid_a_count = 0;
GB_set_key_state(gb, GB_KEY_A, event.type == SDL_JOYBUTTONDOWN);
}
else if (button == JOYPAD_BUTTON_RAPID_B) {
rapid_b = event.type == SDL_JOYBUTTONDOWN;
rapid_b_count = 0;
GB_set_key_state(gb, GB_KEY_B, event.type == SDL_JOYBUTTONDOWN);
}
} }
break; break;
case SDL_JOYAXISMOTION: { case SDL_JOYAXISMOTION: {
static bool axis_active[2] = {false, false}; static bool axis_active[2] = {false, false};
@@ -475,21 +487,31 @@ static void handle_events(GB_gameboy_t *gb)
break; break;
} }
case SDL_KEYUP: // Fallthrough case SDL_KEYUP: // Fallthrough
if (event.key.keysym.scancode == configuration.keys[8]) { if (event.key.keysym.scancode == configuration.keys[GB_CONF_KEYS_TURBO]) {
turbo_down = event.type == SDL_KEYDOWN; turbo_down = event.type == SDL_KEYDOWN;
GB_audio_clear_queue(); GB_audio_clear_queue();
GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down);
} }
else if (event.key.keysym.scancode == configuration.keys_2[0]) { else if (event.key.keysym.scancode == configuration.keys_2[GB_CONF_KEYS2_REWIND]) {
rewind_down = event.type == SDL_KEYDOWN; rewind_down = event.type == SDL_KEYDOWN;
if (event.type == SDL_KEYUP) { if (event.type == SDL_KEYUP) {
rewind_paused = false; rewind_paused = false;
} }
GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down); GB_set_turbo_mode(gb, turbo_down, turbo_down && rewind_down);
} }
else if (event.key.keysym.scancode == configuration.keys_2[1]) { else if (event.key.keysym.scancode == configuration.keys_2[GB_CONF_KEYS2_UNDERCLOCK]) {
underclock_down = event.type == SDL_KEYDOWN; underclock_down = event.type == SDL_KEYDOWN;
} }
else if (event.key.keysym.scancode == configuration.keys_2[GB_CONF_KEYS2_RAPID_A]) {
rapid_a = event.type == SDL_KEYDOWN;
rapid_a_count = 0;
GB_set_key_state(gb, GB_KEY_A, event.type == SDL_KEYDOWN);
}
else if (event.key.keysym.scancode == configuration.keys_2[GB_CONF_KEYS2_RAPID_B]) {
rapid_b = event.type == SDL_KEYDOWN;
rapid_b_count = 0;
GB_set_key_state(gb, GB_KEY_B, event.type == SDL_KEYDOWN);
}
else { else {
for (unsigned i = 0; i < GB_KEY_MAX; i++) { for (unsigned i = 0; i < GB_KEY_MAX; i++) {
if (event.key.keysym.scancode == configuration.keys[i]) { if (event.key.keysym.scancode == configuration.keys[i]) {
@@ -520,6 +542,15 @@ static void vblank(GB_gameboy_t *gb, GB_vblank_type_t type)
GB_set_clock_multiplier(gb, clock_mutliplier); GB_set_clock_multiplier(gb, clock_mutliplier);
} }
if (rapid_a) {
rapid_a_count++;
GB_set_key_state(gb, GB_KEY_A, !(rapid_a_count & 2));
}
if (rapid_b) {
rapid_b_count++;
GB_set_key_state(gb, GB_KEY_B, !(rapid_b_count & 2));
}
if (turbo_down) { if (turbo_down) {
show_osd_text("Fast forward..."); show_osd_text("Fast forward...");
} }

View File

@@ -17,9 +17,9 @@ typedef enum {
GBUnderclock, GBUnderclock,
// GBHotkey1, // Todo // GBHotkey1, // Todo
// GBHotkey2, // Todo // GBHotkey2, // Todo
GBJoypadButtonCount, GBTotalButtonCount,
GBButtonCount = GBUnderclock + 1, GBKeyboardButtonCount = GBUnderclock + 1,
GBGameBoyButtonCount = GBStart + 1, GBPerPlayerButtonCount = GBStart + 1,
GBUnusedButton = 0xFF, GBUnusedButton = 0xFF,
} GBButton; } GBButton;