port: flesh out the input system a bit
This commit is contained in:
parent
05889b54cb
commit
d6ee4f49d2
|
|
@ -60,6 +60,12 @@ typedef struct {
|
|||
u16 button;
|
||||
s8 stick_x; /* -80 <= stick_x <= 80 */
|
||||
s8 stick_y; /* -80 <= stick_y <= 80 */
|
||||
#ifndef PLATFORM_N64 /* for that sick mouselook */
|
||||
s32 mouse_x;
|
||||
s32 mouse_y;
|
||||
s32 mouse_dx;
|
||||
s32 mouse_dy;
|
||||
#endif
|
||||
u8 errnum;
|
||||
} OSContPad;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,68 @@
|
|||
#include <PR/os_cont.h>
|
||||
|
||||
#define INPUT_MAX_CONTROLLERS MAXCONTROLLERS
|
||||
#define INPUT_MAX_CONTROLLER_BUTTONS 32
|
||||
#define INPUT_RUMBLE_STRENGTH 0.333f
|
||||
|
||||
#define CONT_STICK_XNEG 0x10000
|
||||
#define CONT_STICK_XPOS 0x20000
|
||||
#define CONT_STICK_YNEG 0x40000
|
||||
#define CONT_STICK_YPOS 0x80000
|
||||
|
||||
#define CONT_NUM_BUTTONS 16 // not including the stick axes
|
||||
|
||||
enum virtkey {
|
||||
/* same order as SDL scancodes */
|
||||
VK_KEYBOARD_BEGIN = 0,
|
||||
VK_RETURN = 40,
|
||||
VK_ESCAPE = 41,
|
||||
|
||||
/* same order as SDL mouse buttons */
|
||||
VK_MOUSE_BEGIN = 512,
|
||||
VK_MOUSE_LEFT = VK_MOUSE_BEGIN,
|
||||
VK_MOUSE_MIDDLE,
|
||||
VK_MOUSE_RIGHT,
|
||||
VK_MOUSE_X1,
|
||||
VK_MOUSE_X2,
|
||||
VK_MOUSE_WHEEL_UP,
|
||||
VK_MOUSE_WHEEL_DN,
|
||||
|
||||
/* same order as SDL gamecontroller buttons plus two buttons for triggers */
|
||||
VK_JOY_BEGIN,
|
||||
VK_JOY1_BEGIN = VK_JOY_BEGIN,
|
||||
VK_JOY1_LTRIG = VK_JOY1_BEGIN + 30,
|
||||
VK_JOY1_RTRIG = VK_JOY1_BEGIN + 31,
|
||||
VK_JOY2_BEGIN = VK_JOY1_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY3_BEGIN = VK_JOY2_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
VK_JOY4_BEGIN = VK_JOY3_BEGIN + INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
|
||||
VK_TOTAL_COUNT = VK_JOY_BEGIN + INPUT_MAX_CONTROLLERS * INPUT_MAX_CONTROLLER_BUTTONS,
|
||||
};
|
||||
|
||||
enum contkey {
|
||||
CK_C_R,
|
||||
CK_C_L,
|
||||
CK_C_D,
|
||||
CK_C_U,
|
||||
CK_RTRIG,
|
||||
CK_LTRIG,
|
||||
CK_EXTRA0, // gap in CONT_
|
||||
CK_EXTRA1, // gap in CONT_
|
||||
CK_DPAD_R,
|
||||
CK_DPAD_L,
|
||||
CK_DPAD_D,
|
||||
CK_DPAD_U,
|
||||
CK_START,
|
||||
CK_ZTRIG,
|
||||
CK_B,
|
||||
CK_A,
|
||||
CK_STICK_XNEG,
|
||||
CK_STICK_XPOS,
|
||||
CK_STICK_YNEG,
|
||||
CK_STICK_YPOS,
|
||||
CK_TOTAL_COUNT
|
||||
};
|
||||
|
||||
// returns bitmask of connected controllers or -1 if failed
|
||||
s32 inputInit(void);
|
||||
|
||||
|
|
@ -22,9 +82,22 @@ s32 inputControllerConnected(s32 idx);
|
|||
// returns bitmask of connected controllers
|
||||
s32 inputControllerMask(void);
|
||||
|
||||
// vk is a value from the virtkey enum above
|
||||
s32 inputKeyPressed(u32 vk);
|
||||
|
||||
// bind virtkey vk to n64 pad #idx's button/axis nbtn as represented by its contkey value
|
||||
// if bind is -1, picks a bind slot automatically
|
||||
void inputKeyBind(s32 idx, u32 cbtn, s32 bind, u32 vk);
|
||||
|
||||
// 0 strength turns it off
|
||||
void inputRumble(s32 idx, f32 strength, f32 time);
|
||||
|
||||
// locks the mouse cursor in the window and makes it invisible if argument is true
|
||||
void inputLockMouse(s32 lock);
|
||||
|
||||
// returns the current state of the above
|
||||
s32 inputIsMouseLocked(void);
|
||||
|
||||
// call this every frame
|
||||
void inputUpdate(void);
|
||||
|
||||
|
|
|
|||
183
port/src/input.c
183
port/src/input.c
|
|
@ -4,32 +4,65 @@
|
|||
#include <PR/os_cont.h>
|
||||
#include "input.h"
|
||||
|
||||
#define MAX_BINDS 4
|
||||
#define TRIG_THRESHOLD (30 * 256)
|
||||
|
||||
static SDL_GameController *pads[INPUT_MAX_CONTROLLERS];
|
||||
static SDL_Haptic *haptics[INPUT_MAX_CONTROLLERS];
|
||||
|
||||
static const u16 buttonMap[] = {
|
||||
/* SDL_CONTROLLER_BUTTON_A */ A_BUTTON,
|
||||
/* SDL_CONTROLLER_BUTTON_B */ B_BUTTON,
|
||||
/* SDL_CONTROLLER_BUTTON_X */ Z_TRIG,
|
||||
/* SDL_CONTROLLER_BUTTON_Y */ Z_TRIG,
|
||||
/* SDL_CONTROLLER_BUTTON_BACK */ START_BUTTON,
|
||||
/* SDL_CONTROLLER_BUTTON_GUIDE */ 0,
|
||||
/* SDL_CONTROLLER_BUTTON_START */ START_BUTTON,
|
||||
/* SDL_CONTROLLER_BUTTON_LEFTSTICK */ 0,
|
||||
/* SDL_CONTROLLER_BUTTON_RIGHTSTICK */ 0,
|
||||
/* SDL_CONTROLLER_BUTTON_LEFTSHOULDER */ L_TRIG,
|
||||
/* SDL_CONTROLLER_BUTTON_RIGHTSHOULDER */ R_TRIG,
|
||||
/* SDL_CONTROLLER_BUTTON_DPAD_UP */ U_JPAD,
|
||||
/* SDL_CONTROLLER_BUTTON_DPAD_DOWN */ D_JPAD,
|
||||
/* SDL_CONTROLLER_BUTTON_DPAD_LEFT */ L_JPAD,
|
||||
/* SDL_CONTROLLER_BUTTON_DPAD_RIGHT */ R_JPAD,
|
||||
};
|
||||
|
||||
static const u16 buttonTrigLeft = Z_TRIG;
|
||||
static const u16 buttonTrigRight = Z_TRIG;
|
||||
static u32 binds[MAXCONTROLLERS][CK_TOTAL_COUNT][MAX_BINDS]; // [i][CK_][b] = [VK_]
|
||||
|
||||
static s32 connectedMask = 0;
|
||||
|
||||
static s32 mouseLocked = 0;
|
||||
static s32 mouseX, mouseY;
|
||||
static s32 mouseDX, mouseDY;
|
||||
static u32 mouseButtons;
|
||||
|
||||
void inputSetDefaultKeyBinds(void) {
|
||||
// TODO: make VK constants for all these
|
||||
static const u32 kbbinds[][3] = {
|
||||
{ CK_A, SDL_SCANCODE_Q, 0 },
|
||||
{ CK_B, SDL_SCANCODE_E, 0 },
|
||||
{ CK_LTRIG, VK_MOUSE_RIGHT, SDL_SCANCODE_Z },
|
||||
{ CK_RTRIG, VK_MOUSE_X1, SDL_SCANCODE_X },
|
||||
{ CK_ZTRIG, VK_MOUSE_LEFT, SDL_SCANCODE_SPACE },
|
||||
{ CK_START, VK_MOUSE_LEFT, SDL_SCANCODE_RETURN },
|
||||
{ CK_DPAD_D, SDL_SCANCODE_DOWN, 0 },
|
||||
{ CK_DPAD_U, SDL_SCANCODE_UP, 0 },
|
||||
{ CK_DPAD_R, SDL_SCANCODE_RIGHT, 0 },
|
||||
{ CK_DPAD_L, SDL_SCANCODE_LEFT, 0 },
|
||||
{ CK_STICK_XNEG, SDL_SCANCODE_A, 0 },
|
||||
{ CK_STICK_XPOS, SDL_SCANCODE_D, 0 },
|
||||
{ CK_STICK_YNEG, SDL_SCANCODE_S, 0 },
|
||||
{ CK_STICK_YPOS, SDL_SCANCODE_W, 0 },
|
||||
};
|
||||
|
||||
static const u32 joybinds[][2] = {
|
||||
{ CK_LTRIG, SDL_CONTROLLER_BUTTON_LEFTSHOULDER, },
|
||||
{ CK_RTRIG, SDL_CONTROLLER_BUTTON_RIGHTSHOULDER, },
|
||||
{ CK_ZTRIG, VK_JOY1_RTRIG, },
|
||||
{ CK_START, SDL_CONTROLLER_BUTTON_START, },
|
||||
{ CK_DPAD_D, SDL_CONTROLLER_BUTTON_DPAD_DOWN, },
|
||||
{ CK_DPAD_U, SDL_CONTROLLER_BUTTON_DPAD_UP, },
|
||||
{ CK_DPAD_R, SDL_CONTROLLER_BUTTON_DPAD_RIGHT, },
|
||||
{ CK_DPAD_L, SDL_CONTROLLER_BUTTON_DPAD_LEFT, },
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < sizeof(kbbinds) / sizeof(kbbinds[0]); ++i) {
|
||||
for (s32 j = 1; j < 3; ++j) {
|
||||
if (kbbinds[i][j]) {
|
||||
inputKeyBind(0, kbbinds[i][0], j - 1, kbbinds[i][j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < sizeof(joybinds) / sizeof(joybinds[0]); ++i) {
|
||||
for (s32 j = 0; j < INPUT_MAX_CONTROLLERS; ++j) {
|
||||
inputKeyBind(j, joybinds[i][0], -1, joybinds[i][1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s32 inputInit(void)
|
||||
{
|
||||
if (!SDL_WasInit(SDL_INIT_GAMECONTROLLER)) {
|
||||
|
|
@ -60,17 +93,51 @@ s32 inputInit(void)
|
|||
}
|
||||
}
|
||||
|
||||
inputSetDefaultKeyBinds();
|
||||
|
||||
connectedMask = ret;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static inline s32 inputBindPressed(const s32 idx, const u32 ck)
|
||||
{
|
||||
for (s32 i = 0; i < MAX_BINDS; ++i) {
|
||||
if (binds[idx][ck][i]) {
|
||||
if (inputKeyPressed(binds[idx][ck][i])) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
s32 inputReadController(s32 idx, OSContPad *npad)
|
||||
{
|
||||
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || !pads[idx] || !npad) {
|
||||
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || !npad) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < CONT_NUM_BUTTONS; ++i) {
|
||||
if (inputBindPressed(idx, i)) {
|
||||
npad->button |= 1U << i;
|
||||
}
|
||||
}
|
||||
|
||||
const s32 xdiff = (inputBindPressed(idx, CK_STICK_XPOS) - inputBindPressed(idx, CK_STICK_XNEG));
|
||||
const s32 ydiff = (inputBindPressed(idx, CK_STICK_YPOS) - inputBindPressed(idx, CK_STICK_YNEG));
|
||||
npad->stick_x = xdiff < 0 ? -0x80 : (xdiff > 0 ? 0x7F : 0);
|
||||
npad->stick_y = ydiff < 0 ? -0x80 : (ydiff > 0 ? 0x7F : 0);
|
||||
|
||||
npad->mouse_x = mouseX;
|
||||
npad->mouse_y = mouseY;
|
||||
npad->mouse_dx = mouseDX;
|
||||
npad->mouse_dy = mouseDY;
|
||||
|
||||
if (!pads[idx]) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const s16 leftX = SDL_GameControllerGetAxis(pads[idx], SDL_CONTROLLER_AXIS_LEFTX);
|
||||
const s16 leftY = SDL_GameControllerGetAxis(pads[idx], SDL_CONTROLLER_AXIS_LEFTY);
|
||||
const s16 rightX = SDL_GameControllerGetAxis(pads[idx], SDL_CONTROLLER_AXIS_RIGHTX);
|
||||
|
|
@ -83,14 +150,6 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
|||
if (rightY < -0x4000) npad->button |= U_CBUTTONS;
|
||||
if (rightY > +0x4000) npad->button |= D_CBUTTONS;
|
||||
|
||||
for (size_t i = 0; i < sizeof(buttonMap) / sizeof(*buttonMap); ++i) {
|
||||
if (buttonMap[i]) {
|
||||
if (SDL_GameControllerGetButton(pads[idx], i)) {
|
||||
npad->button |= buttonMap[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const s32 stickY = -leftY / 0x100;
|
||||
npad->stick_x = leftX / 0x100;
|
||||
npad->stick_y = (stickY == 128) ? 127 : stickY;
|
||||
|
|
@ -101,6 +160,18 @@ s32 inputReadController(s32 idx, OSContPad *npad)
|
|||
void inputUpdate(void)
|
||||
{
|
||||
SDL_GameControllerUpdate();
|
||||
|
||||
int mx, my;
|
||||
mouseButtons = SDL_GetMouseState(&mx, &my);
|
||||
if (mouseLocked) {
|
||||
SDL_GetRelativeMouseState(&mouseDX, &mouseDY);
|
||||
} else {
|
||||
mouseDX = mx - mouseX;
|
||||
mouseDY = my - mouseY;
|
||||
}
|
||||
mouseX = mx;
|
||||
mouseY = my;
|
||||
|
||||
// TODO: handle controller changes
|
||||
}
|
||||
|
||||
|
|
@ -136,3 +207,55 @@ s32 inputControllerMask(void)
|
|||
{
|
||||
return connectedMask;
|
||||
}
|
||||
|
||||
void inputKeyBind(s32 idx, u32 cbtn, s32 bind, u32 vk) {
|
||||
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || bind >= MAX_BINDS || cbtn >= CK_TOTAL_COUNT) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (bind < 0) {
|
||||
for (s32 i = 0; i < MAX_BINDS; ++i) {
|
||||
if (binds[idx][cbtn][i] == 0) {
|
||||
bind = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bind < 0) {
|
||||
bind = MAX_BINDS - 1; // just overwrite last
|
||||
}
|
||||
}
|
||||
|
||||
binds[idx][cbtn][bind] = vk;
|
||||
}
|
||||
|
||||
s32 inputKeyPressed(u32 vk)
|
||||
{
|
||||
if (vk >= VK_KEYBOARD_BEGIN && vk < VK_MOUSE_BEGIN) {
|
||||
const u8 *state = SDL_GetKeyboardState(NULL);
|
||||
return state[vk - VK_KEYBOARD_BEGIN];
|
||||
} else if (vk >= VK_MOUSE_BEGIN && vk < VK_JOY_BEGIN) {
|
||||
return mouseButtons & SDL_BUTTON(vk - VK_MOUSE_BEGIN + 1);
|
||||
} else if (vk >= VK_JOY_BEGIN && vk < VK_TOTAL_COUNT) {
|
||||
vk -= VK_JOY_BEGIN;
|
||||
const s32 idx = vk / INPUT_MAX_CONTROLLER_BUTTONS;
|
||||
if (idx < 0 || idx >= INPUT_MAX_CONTROLLERS || !pads[idx]) {
|
||||
return 0;
|
||||
}
|
||||
// triggers
|
||||
if (idx == 30 || idx == 31) {
|
||||
const s32 trig = SDL_CONTROLLER_AXIS_TRIGGERLEFT + idx - 30;
|
||||
return SDL_GameControllerGetAxis(pads[idx], trig) > TRIG_THRESHOLD;
|
||||
}
|
||||
return SDL_GameControllerGetButton(pads[idx], vk % INPUT_MAX_CONTROLLER_BUTTONS);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void inputLockMouse(s32 lock) {
|
||||
mouseLocked = !!lock;
|
||||
SDL_SetRelativeMouseMode(mouseLocked);
|
||||
}
|
||||
|
||||
s32 inputIsMouseLocked(void) {
|
||||
return mouseLocked;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@ void sysFatalError(const char *fmt, ...)
|
|||
va_end(ap);
|
||||
|
||||
fprintf(stderr, "FATAL ERROR: %s\n", errmsg);
|
||||
fflush(stderr);
|
||||
|
||||
SDL_ShowSimpleMessageBox(SDL_MESSAGEBOX_ERROR, "Fatal error", errmsg, NULL);
|
||||
exit(1);
|
||||
|
|
|
|||
Loading…
Reference in New Issue