forked from Ports/perfect_dark
port: read keybinds from config file
This commit is contained in:
1 parent
4fef14f9fc
commit
89849bc805
3 files changed
+298
No files matched your search
@@ -91,6 +91,18 @@ s32 inputButtonPressed(s32 idx, u16 contbtn);
|
||||
// if bind is -1, picks a bind slot automatically
|
||||
void inputKeyBind(s32 idx, u32 ck, s32 bind, u32 vk);
|
||||
|
||||
// get VK_ value from human-readable name
|
||||
s32 inputGetKeyByName(const char *name);
|
||||
|
||||
// get human-readable name from VK_ value
|
||||
const char *inputGetKeyName(s32 vk);
|
||||
|
||||
// get CK_ value from human-readable name
|
||||
s32 inputGetContKeyByName(const char *name);
|
||||
|
||||
// get human-readable name from CK_ value
|
||||
const char *inputGetContKeyName(u32 ck);
|
||||
|
||||
// strength is 0 .. 1; 0 strength turns it off
|
||||
void inputRumble(s32 idx, f32 strength, f32 time);
|
||||
|
||||
@@ -113,4 +125,7 @@ void inputMouseGetScaledDelta(f32 *dx, f32 *dy);
|
||||
// call this every frame
|
||||
void inputUpdate(void);
|
||||
|
||||
// call this before configSave()
|
||||
void inputSaveConfig(void);
|
||||
|
||||
#endif
|
||||
@@ -1,3 +1,5 @@
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <SDL.h>
|
||||
#include <PR/ultratypes.h>
|
||||
#include <PR/os_thread.h>
|
||||
@@ -53,6 +55,81 @@ static s32 deadzone[4] = {
|
||||
|
||||
static s32 stickCButtons = 1;
|
||||
|
||||
static const char *ckNames[CK_TOTAL_COUNT] = {
|
||||
"R_CBUTTONS",
|
||||
"L_CBUTTONS",
|
||||
"D_CBUTTONS",
|
||||
"U_CBUTTONS",
|
||||
"R_TRIG",
|
||||
"L_TRIG",
|
||||
"X_BUTTON",
|
||||
"Y_BUTTON",
|
||||
"R_JPAD",
|
||||
"L_JPAD",
|
||||
"D_JPAD",
|
||||
"U_JPAD",
|
||||
"START_BUTTON",
|
||||
"Z_TRIG",
|
||||
"B_BUTTON",
|
||||
"A_BUTTON",
|
||||
"STICK_XNEG",
|
||||
"STICK_XPOS",
|
||||
"STICK_YNEG",
|
||||
"STICK_YPOS",
|
||||
};
|
||||
|
||||
static const char *vkPunctNames[] = {
|
||||
"MINUS", "EQUALS", "LEFTBRACKET", "RIGHTBRACKET", "BACKSLASH",
|
||||
"HASH", "SEMICOLON", "APOSTROPHE", "GRAVE", "COMMA", "PERIOD", "SLASH"
|
||||
};
|
||||
|
||||
static const char *vkMouseNames[] = {
|
||||
"MOUSE_LEFT",
|
||||
"MOUSE_MIDDLE",
|
||||
"MOUSE_RIGHT",
|
||||
"MOUSE_X1",
|
||||
"MOUSE_X2",
|
||||
"MOUSE_WHEEL_UP",
|
||||
"MOUSE_WHEEL_DN",
|
||||
};
|
||||
|
||||
static const char *vkJoyNames[] = {
|
||||
"JOY1_A",
|
||||
"JOY1_B",
|
||||
"JOY1_X",
|
||||
"JOY1_Y",
|
||||
"JOY1_BACK",
|
||||
"JOY1_GUIDE",
|
||||
"JOY1_START",
|
||||
"JOY1_LSTICK",
|
||||
"JOY1_RSTICK",
|
||||
"JOY1_LSHOULDER",
|
||||
"JOY1_RSHOULDER",
|
||||
"JOY1_DPAD_UP",
|
||||
"JOY1_DPAD_DOWN",
|
||||
"JOY1_DPAD_LEFT",
|
||||
"JOY1_DPAD_RIGHT",
|
||||
"JOY1_BUTTON_15",
|
||||
"JOY1_BUTTON_16",
|
||||
"JOY1_BUTTON_17",
|
||||
"JOY1_BUTTON_18",
|
||||
"JOY1_BUTTON_19",
|
||||
"JOY1_TOUCHPAD",
|
||||
"JOY1_BUTTON_21",
|
||||
"JOY1_BUTTON_22",
|
||||
"JOY1_BUTTON_23",
|
||||
"JOY1_BUTTON_24",
|
||||
"JOY1_BUTTON_25",
|
||||
"JOY1_BUTTON_26",
|
||||
"JOY1_BUTTON_27",
|
||||
"JOY1_BUTTON_28",
|
||||
"JOY1_BUTTON_29",
|
||||
"JOY1_LTRIGGER",
|
||||
"JOY1_RTRIGGER",
|
||||
};
|
||||
|
||||
static char vkNames[VK_TOTAL_COUNT][64];
|
||||
|
||||
void inputSetDefaultKeyBinds(void)
|
||||
{
|
||||
// TODO: make VK constants for all these
|
||||
@@ -179,6 +256,143 @@ static int inputEventFilter(void *data, SDL_Event *event)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void inputGetScancodeName(const SDL_Scancode sc, char *out, size_t len)
|
||||
{
|
||||
const char *scname = SDL_GetScancodeName(sc);
|
||||
if (scname) {
|
||||
strncpy(out, scname, len - 1);
|
||||
for (u32 i = 0; i < len && out[i]; ++i) {
|
||||
if (out[i] == ' ') {
|
||||
out[i] = '_';
|
||||
} else {
|
||||
out[i] = toupper(out[i]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
snprintf(out, len, "KEY%d", (s32)sc);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inputInitKeyNames(void)
|
||||
{
|
||||
for (SDL_Scancode key = SDL_SCANCODE_A; key <= SDL_SCANCODE_SPACE; ++key) {
|
||||
inputGetScancodeName(key, vkNames[key], sizeof(vkNames[key]));
|
||||
}
|
||||
|
||||
// special characters
|
||||
for (SDL_Scancode key = SDL_SCANCODE_MINUS; key < SDL_SCANCODE_CAPSLOCK; ++key) {
|
||||
strcpy(vkNames[key], vkPunctNames[key - SDL_SCANCODE_MINUS]);
|
||||
}
|
||||
|
||||
for (SDL_Scancode key = SDL_SCANCODE_CAPSLOCK; key <= SDL_SCANCODE_NUMLOCKCLEAR; ++key) {
|
||||
inputGetScancodeName(key, vkNames[key], sizeof(vkNames[key]));
|
||||
}
|
||||
|
||||
// keypad names
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_DIVIDE], "KP_DIVIDE");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_MULTIPLY], "KP_MULTIPLY");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_MINUS], "KP_MINUS");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_PLUS], "KP_PLUS");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_ENTER], "KP_ENTER");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_PERIOD], "KP_PERIOD");
|
||||
strcpy(vkNames[SDL_SCANCODE_KP_EQUALS], "KP_EQUALS");
|
||||
for (SDL_Scancode key = SDL_SCANCODE_KP_1; key < SDL_SCANCODE_KP_0; ++key) {
|
||||
char tmp[8] = "KP_1";
|
||||
tmp[3] = '1' + (key - SDL_SCANCODE_KP_1);
|
||||
strcpy(vkNames[key], tmp);
|
||||
}
|
||||
|
||||
for (SDL_Scancode key = SDL_SCANCODE_LCTRL; key <= SDL_SCANCODE_RGUI; ++key) {
|
||||
inputGetScancodeName(key, vkNames[key], sizeof(vkNames[key]));
|
||||
}
|
||||
|
||||
// mouse names
|
||||
for (u32 vk = VK_MOUSE_BEGIN; vk < VK_JOY1_BEGIN; ++vk) {
|
||||
strcpy(vkNames[vk], vkMouseNames[vk - VK_MOUSE_BEGIN]);
|
||||
}
|
||||
|
||||
// joystick names
|
||||
for (u32 vk = VK_JOY1_BEGIN; vk < VK_TOTAL_COUNT; ++vk) {
|
||||
const u32 jidx = (vk - VK_JOY1_BEGIN) / INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
const u32 jbtn = (vk - VK_JOY1_BEGIN) % INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
strcpy(vkNames[vk], vkJoyNames[jbtn]);
|
||||
vkNames[vk][3] = '1' + jidx;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inputSaveBinds(void)
|
||||
{
|
||||
char bindstr[256];
|
||||
char keyname[256];
|
||||
char secname[] = "Input.Player1.Binds";
|
||||
|
||||
bindstr[sizeof(bindstr) - 1] = '\0';
|
||||
|
||||
for (s32 i = 0; i < MAXCONTROLLERS; ++i) {
|
||||
secname[12] = '1' + i;
|
||||
for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) {
|
||||
snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck));
|
||||
bindstr[0] = '\0';
|
||||
for (s32 b = 0; b < MAX_BINDS; ++b) {
|
||||
if (binds[i][ck][b]) {
|
||||
if (b) {
|
||||
strncat(bindstr, ", ", sizeof(bindstr) - 1);
|
||||
}
|
||||
strncat(bindstr, inputGetKeyName(binds[i][ck][b]), sizeof(bindstr) - 1);
|
||||
}
|
||||
}
|
||||
configSetString(keyname, bindstr[0] ? bindstr : "NONE");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inputParseBindString(const s32 ctrl, const u32 ck, char *bindstr)
|
||||
{
|
||||
// unbind all first
|
||||
memset(binds[ctrl][ck], 0, sizeof(binds[ctrl][ck]));
|
||||
|
||||
if (!strcasecmp(bindstr, "NONE")) {
|
||||
// explicitly nothing bound
|
||||
return;
|
||||
}
|
||||
|
||||
const char *tok = strtok(bindstr, ", ");
|
||||
while (tok) {
|
||||
if (tok[0]) {
|
||||
const s32 vk = inputGetKeyByName(tok);
|
||||
if (vk > 0) {
|
||||
inputKeyBind(ctrl, ck, -1, vk);
|
||||
}
|
||||
}
|
||||
tok = strtok(NULL, ", ");
|
||||
}
|
||||
}
|
||||
|
||||
static inline void inputLoadBinds(void)
|
||||
{
|
||||
char secname[] = "Input.Player1.Binds";
|
||||
char keyname[256];
|
||||
char bindstr[256];
|
||||
|
||||
for (s32 i = 0; i < MAXCONTROLLERS; ++i) {
|
||||
secname[12] = '1' + i;
|
||||
for (u32 ck = 0; ck < CK_TOTAL_COUNT; ++ck) {
|
||||
snprintf(keyname, sizeof(keyname), "%s.%s", secname, inputGetContKeyName(ck));
|
||||
const char *cfgstr = configGetString(keyname, "");
|
||||
if (cfgstr[0]) {
|
||||
strncpy(bindstr, cfgstr, sizeof(bindstr) - 1);
|
||||
bindstr[sizeof(bindstr) - 1] = '\0';
|
||||
inputParseBindString(i, ck, bindstr);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void inputSaveConfig(void)
|
||||
{
|
||||
inputSaveBinds();
|
||||
}
|
||||
|
||||
s32 inputInit(void)
|
||||
{
|
||||
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC)) {
|
||||
@@ -208,6 +422,8 @@ s32 inputInit(void)
|
||||
// since the main event loop is elsewhere, we can receive some events we need using a watcher
|
||||
SDL_AddEventWatch(inputEventFilter, NULL);
|
||||
|
||||
inputInitKeyNames();
|
||||
|
||||
inputSetDefaultKeyBinds();
|
||||
|
||||
mouseEnabled = configGetInt("Input.MouseEnabled", 1);
|
||||
@@ -241,6 +457,8 @@ s32 inputInit(void)
|
||||
connectedMask = overrideMask;
|
||||
}
|
||||
|
||||
inputLoadBinds();
|
||||
|
||||
return connectedMask;
|
||||
}
|
||||
|
||||
@@ -507,3 +725,67 @@ void inputMouseGetScaledDelta(f32 *dx, f32 *dy)
|
||||
if (dx) *dx = mdx;
|
||||
if (dy) *dy = mdy;
|
||||
}
|
||||
|
||||
const char *inputGetContKeyName(u32 ck)
|
||||
{
|
||||
if (ck >= CK_TOTAL_COUNT) {
|
||||
return "";
|
||||
}
|
||||
return ckNames[ck];
|
||||
}
|
||||
|
||||
s32 inputGetContKeyByName(const char *name)
|
||||
{
|
||||
for (u32 i = 0; i < CK_TOTAL_COUNT; ++i) {
|
||||
if (!strcmp(name, ckNames[i])) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "unknown bind name: `%s`\n", name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const char *inputGetKeyName(s32 vk)
|
||||
{
|
||||
if (vk < 0 || vk >= VK_TOTAL_COUNT) {
|
||||
vk = 0;
|
||||
}
|
||||
if (!vkNames[vk][0]) {
|
||||
snprintf(vkNames[vk], sizeof(vkNames[vk]), "UNKNOWN%d", vk);
|
||||
}
|
||||
return vkNames[vk];
|
||||
}
|
||||
|
||||
s32 inputGetKeyByName(const char *name)
|
||||
{
|
||||
s32 start = 0;
|
||||
s32 end = 0;
|
||||
|
||||
if (!strncmp(name, "JOY", 3) && isdigit(name[3])) {
|
||||
const s32 idx = name[3] - '1';
|
||||
if (idx >= 0 && idx < INPUT_MAX_CONTROLLERS) {
|
||||
start = VK_JOY1_BEGIN + idx * INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
end = start + INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
}
|
||||
} else if (!strncmp(name, "MOUSE", 5)) {
|
||||
start = VK_MOUSE_BEGIN;
|
||||
end = VK_JOY1_BEGIN;
|
||||
} else if (!strncmp(name, "UNKNOWN", 7) && isdigit(name[7])) {
|
||||
const s32 key = atoi(name + 7);
|
||||
if (key >= 0 && key < VK_TOTAL_COUNT) {
|
||||
return key;
|
||||
}
|
||||
} else {
|
||||
end = VK_MOUSE_BEGIN;
|
||||
}
|
||||
|
||||
for (s32 i = start; i < end; ++i) {
|
||||
if (!strcmp(vkNames[i], name)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(stderr, "unknown key name: `%s`\n", name);
|
||||
|
||||
return -1;
|
||||
}
|
||||
@@ -54,6 +54,7 @@ void bootCreateSched(void)
|
||||
|
||||
static void cleanup(void)
|
||||
{
|
||||
inputSaveConfig();
|
||||
configSave(CONFIG_FNAME);
|
||||
// TODO: actually shut down all subsystems
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user