mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
keybinds: dual bindings per control (primary + alt, comma ini syntax)
This commit is contained in:
committed by
Matthew Stanley
parent
e4658ee680
commit
63db8f430d
@@ -93,7 +93,13 @@ const char *psx_keybinds_button_name(int button); /* "up".."rs_right"
|
||||
const char *psx_keybinds_button_label(int button); /* pretty, e.g. "Cross" */
|
||||
SDL_Scancode psx_keybinds_get_button(int player, int button);
|
||||
void psx_keybinds_set_button(int player, int button, SDL_Scancode sc);
|
||||
/* Reset one player's bindings to the built-in defaults (same map for every slot). */
|
||||
/* Alternate (secondary) binding per control: both the primary and the alt
|
||||
* assert the input (e.g. cross = X, Mouse1). Stored in keybinds.ini as a
|
||||
* comma-separated second name; SDL_SCANCODE_UNKNOWN = no alt. */
|
||||
SDL_Scancode psx_keybinds_get_button_alt(int player, int button);
|
||||
void psx_keybinds_set_button_alt(int player, int button, SDL_Scancode sc);
|
||||
/* Reset one player's bindings to the shared built-in primary defaults and
|
||||
* clear that player's alternate bindings. */
|
||||
void psx_keybinds_reset_player(int player);
|
||||
/* Persist the current bindings to keybinds.ini (path resolved by
|
||||
* psx_keybinds_init; call that first). */
|
||||
|
||||
+62
-11
@@ -82,6 +82,10 @@
|
||||
|
||||
static PsxKeyBinds s_binds = PSXKB_DEFAULTS;
|
||||
static const PsxKeyBinds s_default_binds = PSXKB_DEFAULTS;
|
||||
/* Alternate bindings: zero-initialised = SDL_SCANCODE_UNKNOWN = no alt bound.
|
||||
* Primary OR alt asserts the input; both persist to keybinds.ini as
|
||||
* "primary, alt" on one line. */
|
||||
static PsxKeyBinds s_alt_binds;
|
||||
|
||||
typedef struct {
|
||||
const char *name; /* ini key */
|
||||
@@ -212,11 +216,18 @@ static void derive_ini_path(const char *exe_path) {
|
||||
snprintf(s_ini_path, sizeof(s_ini_path), "%skeybinds.ini", dir);
|
||||
}
|
||||
|
||||
static void write_player_section(FILE *f, const char *section, const PsxPlayerBinds *pb) {
|
||||
static void write_player_section(FILE *f, const char *section,
|
||||
const PsxPlayerBinds *pb,
|
||||
const PsxPlayerBinds *alt) {
|
||||
fprintf(f, "[%s]\n", section);
|
||||
for (int i = 0; i < PSXKB_N; i++) {
|
||||
SDL_Scancode sc = *(const SDL_Scancode *)((const char *)pb + s_buttons[i].offset);
|
||||
fprintf(f, "%-9s = %s\n", s_buttons[i].name, scancode_to_name(sc));
|
||||
SDL_Scancode sc = *(const SDL_Scancode *)((const char *)pb + s_buttons[i].offset);
|
||||
SDL_Scancode al = *(const SDL_Scancode *)((const char *)alt + s_buttons[i].offset);
|
||||
if (al != SDL_SCANCODE_UNKNOWN)
|
||||
fprintf(f, "%-9s = %s, %s\n", s_buttons[i].name,
|
||||
scancode_to_name(sc), scancode_to_name(al));
|
||||
else
|
||||
fprintf(f, "%-9s = %s\n", s_buttons[i].name, scancode_to_name(sc));
|
||||
}
|
||||
fprintf(f, "\n");
|
||||
}
|
||||
@@ -232,6 +243,8 @@ static void write_ini(const char *path) {
|
||||
"# Backspace, Escape, Backslash. Use \"None\" to leave an input unbound.\n"
|
||||
"# Mouse buttons also bind: Mouse1 (left), Mouse2 (middle), Mouse3 (right),\n"
|
||||
"# Mouse4/Mouse5 (side); aliases LMB, MMB, RMB.\n"
|
||||
"# Each input accepts an optional SECOND binding after a comma - both\n"
|
||||
"# assert the input: cross = X, Mouse1\n"
|
||||
"#\n"
|
||||
"# Buttons: up/down/left/right, cross/circle/square/triangle, l1/r1/l2/r2,\n"
|
||||
"# l3/r3 (stick clicks), start/select. ls_* / rs_* are the left/right\n"
|
||||
@@ -243,7 +256,8 @@ static void write_ini(const char *path) {
|
||||
for (int p = 0; p < PSXKB_MAX_PLAYERS; ++p) {
|
||||
char section[16];
|
||||
snprintf(section, sizeof(section), "player%d", p + 1);
|
||||
write_player_section(f, section, &s_binds.player[p]);
|
||||
write_player_section(f, section, &s_binds.player[p],
|
||||
&s_alt_binds.player[p]);
|
||||
}
|
||||
fclose(f);
|
||||
printf("[Keybinds] Wrote %s\n", path);
|
||||
@@ -269,7 +283,7 @@ static void promote_empty_players(void) {
|
||||
static void load_ini(const char *path) {
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) return;
|
||||
PsxPlayerBinds *current = NULL;
|
||||
PsxPlayerBinds *current = NULL, *current_alt = NULL;
|
||||
char line[256];
|
||||
while (fgets(line, sizeof(line), f)) {
|
||||
trim(line);
|
||||
@@ -278,11 +292,13 @@ static void load_ini(const char *path) {
|
||||
char *end = strchr(line, ']');
|
||||
if (end) *end = '\0';
|
||||
const char *section = line + 1;
|
||||
current = NULL;
|
||||
current = NULL; current_alt = NULL;
|
||||
if (!strncmp(section, "player", 6)) {
|
||||
int n = atoi(section + 6);
|
||||
if (n >= 1 && n <= PSXKB_MAX_PLAYERS)
|
||||
if (n >= 1 && n <= PSXKB_MAX_PLAYERS) {
|
||||
current = &s_binds.player[n - 1];
|
||||
current_alt = &s_alt_binds.player[n - 1];
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -293,9 +309,16 @@ static void load_ini(const char *path) {
|
||||
trim(key); trim(val);
|
||||
for (char *c = key; *c; c++) *c = (char)tolower((unsigned char)*c);
|
||||
if (!current) continue;
|
||||
/* Optional alternate binding after a comma: "cross = X, Mouse1". */
|
||||
char *comma = strchr(val, ',');
|
||||
char *alt_val = NULL;
|
||||
if (comma) { *comma = '\0'; alt_val = comma + 1; trim(val); trim(alt_val); }
|
||||
for (int i = 0; i < PSXKB_N; i++) {
|
||||
if (!strcmp(key, s_buttons[i].name)) {
|
||||
*(SDL_Scancode *)((char *)current + s_buttons[i].offset) = name_to_scancode(val);
|
||||
*(SDL_Scancode *)((char *)current + s_buttons[i].offset) =
|
||||
name_to_scancode(val);
|
||||
*(SDL_Scancode *)((char *)current_alt + s_buttons[i].offset) =
|
||||
alt_val ? name_to_scancode(alt_val) : SDL_SCANCODE_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -325,11 +348,10 @@ static PsxPlayerBinds *player_binds(int player) {
|
||||
return &s_binds.player[player - 1];
|
||||
}
|
||||
|
||||
/* Is the scancode at button-def index i currently held for this player?
|
||||
/* Is this single scancode (keyboard or mouse pseudo-code) currently held?
|
||||
* Mouse pseudo-scancodes MUST be checked before indexing keys[] — they sit
|
||||
* beyond the keyboard state array (SDL_NUM_SCANCODES entries). */
|
||||
static int held(const uint8_t *keys, const PsxPlayerBinds *pb, int i) {
|
||||
SDL_Scancode sc = *(const SDL_Scancode *)((const char *)pb + s_buttons[i].offset);
|
||||
static int held_sc(const uint8_t *keys, SDL_Scancode sc) {
|
||||
if (PSXKB_IS_MOUSE_SC(sc)) {
|
||||
Uint32 m = SDL_GetMouseState(NULL, NULL);
|
||||
return (m & SDL_BUTTON((int)sc - PSXKB_MOUSE_SC_BASE)) != 0;
|
||||
@@ -337,6 +359,18 @@ static int held(const uint8_t *keys, const PsxPlayerBinds *pb, int i) {
|
||||
return sc != SDL_SCANCODE_UNKNOWN && (int)sc < SDL_NUM_SCANCODES && keys[sc];
|
||||
}
|
||||
|
||||
/* Is the input at button-def index i held for this player, via either its
|
||||
* primary or its alternate binding? The alternate table uses the same player
|
||||
* slot as the primary table. */
|
||||
static int held(const uint8_t *keys, const PsxPlayerBinds *pb, int i) {
|
||||
ptrdiff_t slot = pb - &s_binds.player[0];
|
||||
if (slot < 0 || slot >= PSXKB_MAX_PLAYERS) slot = 0;
|
||||
const PsxPlayerBinds *alt = &s_alt_binds.player[slot];
|
||||
SDL_Scancode p = *(const SDL_Scancode *)((const char *)pb + s_buttons[i].offset);
|
||||
SDL_Scancode a = *(const SDL_Scancode *)((const char *)alt + s_buttons[i].offset);
|
||||
return held_sc(keys, p) || held_sc(keys, a);
|
||||
}
|
||||
|
||||
uint16_t psx_keybinds_pad_word(const uint8_t *keys, int player) {
|
||||
if (!keys || player < 1 || player > PSXKB_MAX_PLAYERS) return 0xFFFF;
|
||||
const PsxPlayerBinds *pb = player_binds_c(player);
|
||||
@@ -393,9 +427,26 @@ void psx_keybinds_set_button(int player, int button, SDL_Scancode sc) {
|
||||
*(SDL_Scancode *)((char *)player_binds(player) + s_buttons[button].offset) = sc;
|
||||
}
|
||||
|
||||
static PsxPlayerBinds *player_alt_binds(int player) {
|
||||
if (player < 1 || player > PSXKB_MAX_PLAYERS)
|
||||
return &s_alt_binds.player[0];
|
||||
return &s_alt_binds.player[player - 1];
|
||||
}
|
||||
|
||||
SDL_Scancode psx_keybinds_get_button_alt(int player, int button) {
|
||||
if (button < 0 || button >= PSXKB_N) return SDL_SCANCODE_UNKNOWN;
|
||||
return *(SDL_Scancode *)((char *)player_alt_binds(player) + s_buttons[button].offset);
|
||||
}
|
||||
|
||||
void psx_keybinds_set_button_alt(int player, int button, SDL_Scancode sc) {
|
||||
if (button < 0 || button >= PSXKB_N) return;
|
||||
*(SDL_Scancode *)((char *)player_alt_binds(player) + s_buttons[button].offset) = sc;
|
||||
}
|
||||
|
||||
void psx_keybinds_reset_player(int player) {
|
||||
if (player < 1 || player > PSXKB_MAX_PLAYERS) return;
|
||||
*player_binds(player) = s_default_binds.player[0];
|
||||
memset(player_alt_binds(player), 0, sizeof(PsxPlayerBinds)); /* alts: unbound */
|
||||
}
|
||||
|
||||
void psx_keybinds_save(void) {
|
||||
|
||||
Reference in New Issue
Block a user