pass absolute value for joystick axis key to input handlers instead

of splitting the axis into two keys

splitting the axis into two keys caused a logical issue where when
the axis's value swapped from positive to negative or vice versa,
the old key's value wouldn't be cleared
This commit is contained in:
Anthony Pesch 2017-12-03 19:57:48 -05:00
parent a887f4abfc
commit 107f7969b0
16 changed files with 149 additions and 178 deletions

View File

@ -696,7 +696,7 @@ int emu_load(struct emu *emu, const char *path) {
return dc_load(emu->dc, path);
}
int emu_keydown(struct emu *emu, int port, int key, uint16_t value) {
int emu_keydown(struct emu *emu, int port, int key, int16_t value) {
if (key >= K_CONT_C && key <= K_CONT_RTRIG) {
dc_input(emu->dc, port, key - K_CONT_C, value);
}

View File

@ -12,7 +12,7 @@ void emu_destroy(struct emu *emu);
void emu_vid_created(struct emu *emu, struct render_backend *r);
void emu_vid_destroyed(struct emu *emu);
int emu_keydown(struct emu *emu, int port, int key, uint16_t value);
int emu_keydown(struct emu *emu, int port, int key, int16_t value);
int emu_load(struct emu *emu, const char *path);
void emu_debug_menu(struct emu *emu);

View File

@ -100,7 +100,7 @@ void dc_add_serial_device(struct dreamcast *dc, struct serial *serial) {
dc->serial = serial;
}
void dc_input(struct dreamcast *dc, int port, int button, uint16_t value) {
void dc_input(struct dreamcast *dc, int port, int button, int16_t value) {
maple_handle_input(dc->maple, port, button, value);
}

View File

@ -159,7 +159,7 @@ int dc_running(struct dreamcast *dc);
void dc_suspend(struct dreamcast *dc);
void dc_resume(struct dreamcast *dc);
void dc_tick(struct dreamcast *dc, int64_t ns);
void dc_input(struct dreamcast *dc, int port, int button, uint16_t value);
void dc_input(struct dreamcast *dc, int port, int button, int16_t value);
void dc_add_serial_device(struct dreamcast *dc, struct serial *serial);
void dc_remove_serial_device(struct dreamcast *dc);

View File

@ -20,10 +20,8 @@ enum {
CONT_DPAD2_LEFT,
CONT_DPAD2_RIGHT,
/* only used internally, not by the real controller state */
CONT_JOYX_NEG,
CONT_JOYX_POS,
CONT_JOYY_NEG,
CONT_JOYY_POS,
CONT_JOYX,
CONT_JOYY,
CONT_LTRIG,
CONT_RTRIG,
NUM_CONTROLS,
@ -97,7 +95,7 @@ static int controller_frame(struct maple_device *dev,
}
static int controller_input(struct maple_device *dev, int button,
uint16_t value) {
int16_t value) {
struct controller *ctrl = (struct controller *)dev;
if (button <= CONT_DPAD2_RIGHT) {
@ -106,18 +104,24 @@ static int controller_input(struct maple_device *dev, int button,
} else {
ctrl->cnd.buttons |= (1 << button);
}
} else if (button == CONT_JOYX_NEG) {
ctrl->cnd.joyx = axis_neg_u16_to_u8(value);
} else if (button == CONT_JOYX_POS) {
ctrl->cnd.joyx = axis_pos_u16_to_u8(value);
} else if (button == CONT_JOYY_NEG) {
ctrl->cnd.joyy = axis_neg_u16_to_u8(value);
} else if (button == CONT_JOYY_POS) {
ctrl->cnd.joyy = axis_pos_u16_to_u8(value);
} else if (button == CONT_LTRIG) {
ctrl->cnd.ltrig = axis_u16_to_u8(value);
} else if (button == CONT_RTRIG) {
ctrl->cnd.rtrig = axis_u16_to_u8(value);
} else if (button == CONT_JOYX || button == CONT_JOYY) {
/* scale value from [INT16_MIN, INT16_MAX] to [0, UINT8_MAX] */
uint8_t scaled = ((int32_t)value - INT16_MIN) >> 8;
if (button == CONT_JOYX) {
ctrl->cnd.joyx = scaled;
} else {
ctrl->cnd.joyy = scaled;
}
} else if (button == CONT_LTRIG || button == CONT_RTRIG) {
/* scale value from [0, INT16_MAX] to [0, UINT8_MAX] */
uint8_t scaled = (int32_t)value >> 7;
if (button == CONT_LTRIG) {
ctrl->cnd.ltrig = scaled;
} else {
ctrl->cnd.rtrig = scaled;
}
}
return 1;

View File

@ -65,8 +65,7 @@ int maple_handle_frame(struct maple *mp, int port, union maple_frame *req,
return 1;
}
void maple_handle_input(struct maple *mp, int port, int button,
uint16_t value) {
void maple_handle_input(struct maple *mp, int port, int button, int16_t value) {
CHECK(port >= 0 && port < MAPLE_NUM_PORTS);
/* send to primary device */

View File

@ -10,7 +10,7 @@ struct maple_device;
struct maple_device {
struct maple *mp;
void (*destroy)(struct maple_device *);
int (*input)(struct maple_device *, int, uint16_t);
int (*input)(struct maple_device *, int, int16_t);
int (*frame)(struct maple_device *, const union maple_frame *,
union maple_frame *);
};
@ -22,7 +22,7 @@ struct maple *maple_create(struct dreamcast *dc);
void maple_destroy(struct maple *mp);
struct maple_device *maple_get_device(struct maple *mp, int port, int unit);
void maple_handle_input(struct maple *mp, int port, int button, uint16_t value);
void maple_handle_input(struct maple *mp, int port, int button, int16_t value);
int maple_handle_frame(struct maple *mp, int port, union maple_frame *frame,
union maple_frame *res);

View File

@ -2,7 +2,6 @@
#define KEYCODE_H
#include <stdint.h>
#include "core/math.h"
enum {
K_UNKNOWN,
@ -79,50 +78,14 @@ enum {
K_CONT_DPAD2_DOWN,
K_CONT_DPAD2_LEFT,
K_CONT_DPAD2_RIGHT,
K_CONT_JOYX_NEG,
K_CONT_JOYX_POS,
K_CONT_JOYY_NEG,
K_CONT_JOYY_POS,
K_CONT_JOYX,
K_CONT_JOYY,
K_CONT_LTRIG,
K_CONT_RTRIG,
K_NUM_KEYS
};
/* keyboard input callbacks are passed a key and a value which can represent
either a digital button press, or an analog key / axis movement. analog
sources are split into individual positive / negative keys, with a 16-bit
unsigned integer for a value */
#define KEY_UP 0
#define KEY_DOWN UINT16_MAX
static inline int axis_s16_to_u16(int16_t value, uint16_t *out) {
if (value < 0) {
/* scale from [INT16_MIN, 0] to [UINT16_MAX, 0] */
*out = (uint16_t)MIN(-(int32_t)value * 2, UINT16_MAX);
return 0;
}
/* scale from [0, INT16_MAX] to [0, UINT16_MAX] */
*out = (uint16_t)((int32_t)value * 2);
return 1;
}
static inline uint8_t axis_neg_u16_to_u8(uint16_t value) {
/* scale from [0, UINT16_MAX] to [127, 0] */
return 127 - (value >> 9);
}
static inline uint8_t axis_pos_u16_to_u8(uint16_t value) {
/* scale from [0, UINT16_MAX] to [128, 255] */
return 128 + (value >> 9);
}
static inline uint8_t axis_u16_to_u8(uint16_t value) {
/* scale from [0, UINT16_MAX] to [0, 255] */
return value >> 7;
}
int get_key_by_name(const char *keyname);
const char *get_name_by_key(int key);

View File

@ -54,8 +54,8 @@ static retro_input_state_t input_state_cb;
K_CONT_DPAD_RIGHT, \
K_CONT_Y, \
K_CONT_X, \
K_CONT_JOYX_NEG, \
K_CONT_JOYY_NEG, \
K_CONT_JOYX, \
K_CONT_JOYY, \
K_CONT_LTRIG, \
K_CONT_RTRIG
@ -105,32 +105,27 @@ static void input_poll(struct host *host) {
/* send updates for any inputs that've changed */
for (int i = 0; i < NUM_CONTROLLER_DESC; i++) {
struct retro_input_descriptor *desc = &controller_desc[i];
int16_t state =
int16_t value =
input_state_cb(desc->port, desc->device, desc->index, desc->id);
if (host->input.state[i] == state) {
/* retroarch's API provides a binary [0, 1] value for the triggers. map from
this to [0, INT16_MAX] as our host layer expects */
if (desc->id == RETRO_DEVICE_ID_JOYPAD_L2 ||
desc->id == RETRO_DEVICE_ID_JOYPAD_R2) {
value = value ? INT16_MAX : 0;
}
if (host->input.state[i] == value) {
continue;
}
host->input.state[i] = state;
/* retroarch provides a value in the range of [INT16_MIN, INT16_MAX] for
axis inputs, and a value between [0, and 1] for button and trigger
inputs. convert these values into the ranges our code expects */
int key = controller_buttons[i];
uint16_t value = 0;
if (desc->device == RETRO_DEVICE_ANALOG) {
int dir = axis_s16_to_u16(state, &value);
/* if value is positive, change to positive axis */
key += dir;
} else {
value = state ? KEY_DOWN : KEY_UP;
}
int button = controller_buttons[i];
if (host->emu) {
emu_keydown(host->emu, desc->port, key, value);
emu_keydown(host->emu, desc->port, button, value);
}
host->input.state[i] = value;
}
}

View File

@ -55,7 +55,7 @@ struct host {
} video;
struct {
int keymap[K_NUM_KEYS];
struct button_map *keymap[K_NUM_KEYS];
SDL_GameController *controllers[INPUT_MAX_CONTROLLERS];
} input;
@ -526,10 +526,10 @@ static void input_update_keymap(struct host *host) {
memset(host->input.keymap, 0, sizeof(host->input.keymap));
for (int i = 0; i < NUM_BUTTONS; i++) {
struct button_map *btnmap = &BUTTONS[i];
struct button_map *mapping = &BUTTONS[i];
if (btnmap->key) {
host->input.keymap[*btnmap->key] = K_CONT_C + i;
if (mapping->key) {
host->input.keymap[*mapping->key] = mapping;
}
}
}
@ -538,11 +538,19 @@ static void input_mousemove(struct host *host, int port, int x, int y) {
imgui_mousemove(host->imgui, x, y);
}
static void input_keydown(struct host *host, int port, int key,
uint16_t value) {
/* send event for both the original key as well as the mapped button, if a
mapping is available */
int mapping = host->input.keymap[key];
static void input_keydown(struct host *host, int port, int key, int16_t value) {
/* send event for both the key as well the button it's mapped to (if any) */
struct button_map *mapping = host->input.keymap[key];
int button = K_UNKNOWN;
if (mapping) {
button = mapping->btn;
/* if the mapping is to a negative axis, flip the value */
if (mapping->dir == DIR_NEG) {
value = -value;
}
}
if (key == K_F1 && value) {
host->dbg.show_menu = !host->dbg.show_menu;
@ -568,7 +576,8 @@ static void input_keydown(struct host *host, int port, int key,
imgui_keydown(host->imgui, key, value);
key = mapping;
/* send event for mapped button as well */
key = button;
}
}
@ -760,7 +769,7 @@ static void host_poll_events(struct host *host) {
int keycode = translate_sdl_key(ev.key.keysym);
if (keycode != K_UNKNOWN) {
input_keydown(host, 0, keycode, KEY_DOWN);
input_keydown(host, 0, keycode, INT16_MAX);
}
} break;
@ -768,7 +777,7 @@ static void host_poll_events(struct host *host) {
int keycode = translate_sdl_key(ev.key.keysym);
if (keycode != K_UNKNOWN) {
input_keydown(host, 0, keycode, KEY_UP);
input_keydown(host, 0, keycode, 0);
}
} break;
@ -798,18 +807,18 @@ static void host_poll_events(struct host *host) {
}
if (keycode != K_UNKNOWN) {
uint16_t value = ev.type == SDL_MOUSEBUTTONDOWN ? KEY_DOWN : KEY_UP;
int16_t value = ev.type == SDL_MOUSEBUTTONDOWN ? INT16_MAX : 0;
input_keydown(host, 0, keycode, value);
}
} break;
case SDL_MOUSEWHEEL:
if (ev.wheel.y > 0) {
input_keydown(host, 0, K_MWHEELUP, KEY_DOWN);
input_keydown(host, 0, K_MWHEELUP, KEY_UP);
input_keydown(host, 0, K_MWHEELUP, INT16_MAX);
input_keydown(host, 0, K_MWHEELUP, 0);
} else {
input_keydown(host, 0, K_MWHEELDOWN, KEY_DOWN);
input_keydown(host, 0, K_MWHEELDOWN, KEY_UP);
input_keydown(host, 0, K_MWHEELDOWN, INT16_MAX);
input_keydown(host, 0, K_MWHEELDOWN, 0);
}
break;
@ -832,18 +841,14 @@ static void host_poll_events(struct host *host) {
case SDL_CONTROLLERAXISMOTION: {
int port = input_find_controller_port(host, ev.caxis.which);
int key = K_UNKNOWN;
uint16_t value = 0;
/* SDL provides axis input in the range of [INT16_MIN, INT16_MAX],
convert to [0, UINT16_MAX] */
int dir = axis_s16_to_u16(ev.caxis.value, &value);
int16_t value = ev.caxis.value;
switch (ev.caxis.axis) {
case SDL_CONTROLLER_AXIS_LEFTX:
key = K_CONT_JOYX_NEG + dir;
key = K_CONT_JOYX;
break;
case SDL_CONTROLLER_AXIS_LEFTY:
key = K_CONT_JOYY_NEG + dir;
key = K_CONT_JOYY;
break;
case SDL_CONTROLLER_AXIS_TRIGGERLEFT:
key = K_CONT_LTRIG;
@ -862,8 +867,7 @@ static void host_poll_events(struct host *host) {
case SDL_CONTROLLERBUTTONUP: {
int port = input_find_controller_port(host, ev.cbutton.which);
int key = K_UNKNOWN;
uint16_t value =
ev.type == SDL_CONTROLLERBUTTONDOWN ? KEY_DOWN : KEY_UP;
int16_t value = ev.type == SDL_CONTROLLERBUTTONDOWN ? INT16_MAX : 0;
switch (ev.cbutton.button) {
case SDL_CONTROLLER_BUTTON_A:
@ -930,19 +934,19 @@ static void host_poll_events(struct host *host) {
OPTION_sync_dirty = 0;
}
/* update reverse button map when optionsc hange */
/* update reverse button map when options change */
int dirty_map = 0;
for (int i = 0; i < NUM_BUTTONS; i++) {
struct button_map *btnmap = &BUTTONS[i];
struct button_map *mapping = &BUTTONS[i];
if (!btnmap->desc) {
if (!mapping->desc) {
continue;
}
if (*btnmap->dirty) {
if (*mapping->dirty) {
dirty_map = 1;
*btnmap->dirty = 0;
*mapping->dirty = 0;
}
}

View File

@ -22,7 +22,7 @@ struct imgui {
int alt[2];
int ctrl[2];
int shift[2];
uint16_t keys[K_NUM_KEYS];
int16_t keys[K_NUM_KEYS];
};
/* maintain global pointer for ig* functions */
@ -388,42 +388,43 @@ void imgui_begin_frame(struct imgui *imgui) {
io.NavInputs[ImGuiNavInput_PadActivate] = imgui->keys[K_CONT_A];
io.NavInputs[ImGuiNavInput_PadCancel] = imgui->keys[K_CONT_B];
io.NavInputs[ImGuiNavInput_PadUp] =
imgui->keys[K_CONT_DPAD_UP] || imgui->keys[K_CONT_JOYY_NEG];
imgui->keys[K_CONT_DPAD_UP] || (imgui->keys[K_CONT_JOYY] < 0);
io.NavInputs[ImGuiNavInput_PadDown] =
imgui->keys[K_CONT_DPAD_DOWN] || imgui->keys[K_CONT_JOYY_POS];
imgui->keys[K_CONT_DPAD_DOWN] || (imgui->keys[K_CONT_JOYY] > 0);
io.NavInputs[ImGuiNavInput_PadLeft] =
imgui->keys[K_CONT_DPAD_LEFT] || imgui->keys[K_CONT_JOYX_NEG];
imgui->keys[K_CONT_DPAD_LEFT] || (imgui->keys[K_CONT_JOYX] < 0);
io.NavInputs[ImGuiNavInput_PadRight] =
imgui->keys[K_CONT_DPAD_RIGHT] || imgui->keys[K_CONT_JOYX_POS];
imgui->keys[K_CONT_DPAD_RIGHT] || (imgui->keys[K_CONT_JOYX] > 0);
ImGui::NewFrame();
}
int imgui_keydown(struct imgui *imgui, int key, uint16_t value) {
int imgui_keydown(struct imgui *imgui, int key, int16_t value) {
ImGuiIO &io = ImGui::GetIO();
int down = value != 0;
if (key == K_MWHEELUP) {
io.MouseWheel = 1.0f;
} else if (key == K_MWHEELDOWN) {
io.MouseWheel = -1.0f;
} else if (key == K_MOUSE1) {
io.MouseDown[0] = (bool)value;
io.MouseDown[0] = down;
} else if (key == K_MOUSE2) {
io.MouseDown[1] = (bool)value;
io.MouseDown[1] = down;
} else if (key == K_MOUSE3) {
io.MouseDown[2] = (bool)value;
io.MouseDown[2] = down;
} else if (key == K_LALT || key == K_RALT) {
imgui->alt[key == K_LALT ? 0 : 1] = value;
imgui->alt[key == K_LALT ? 0 : 1] = down;
io.KeyAlt = imgui->alt[0] || imgui->alt[1];
} else if (key == K_LCTRL || key == K_RCTRL) {
imgui->ctrl[key == K_LCTRL ? 0 : 1] = value;
imgui->ctrl[key == K_LCTRL ? 0 : 1] = down;
io.KeyCtrl = imgui->ctrl[0] || imgui->ctrl[1];
} else if (key == K_LSHIFT || key == K_RSHIFT) {
imgui->shift[key == K_LSHIFT ? 0 : 1] = value;
imgui->shift[key == K_LSHIFT ? 0 : 1] = down;
io.KeyShift = imgui->shift[0] || imgui->shift[1];
} else {
imgui->keys[key] = value;
io.KeysDown[key] = (bool)value;
io.KeysDown[key] = down;
}
return 0;
}

View File

@ -48,7 +48,7 @@ void imgui_destroy(struct imgui *imgui);
void imgui_vid_created(struct imgui *imgui, struct render_backend *r);
void imgui_vid_destroyed(struct imgui *imgui);
void imgui_mousemove(struct imgui *imgui, int x, int y);
int imgui_keydown(struct imgui *imgui, int key, uint16_t value);
int imgui_keydown(struct imgui *imgui, int key, int16_t value);
void imgui_begin_frame(struct imgui *imgui);
void imgui_end_frame(struct imgui *imgui);

View File

@ -2,70 +2,67 @@
#include "core/core.h"
#include "host/keycode.h"
/* clang-format off */
const char *ASPECT_RATIOS[] = {
"stretch", "16:9", "4:3",
"stretch", "16:9", "4:3",
};
const int NUM_ASPECT_RATIOS = ARRAY_SIZE(ASPECT_RATIOS);
struct button_map BUTTONS[] = {
{NULL, NULL, NULL}, /* K_CONT_C */
{"B button", &OPTION_key_b, &OPTION_key_b_dirty},
{"A button", &OPTION_key_a, &OPTION_key_a_dirty},
{"Start button", &OPTION_key_start, &OPTION_key_start_dirty},
{"DPAD Up", &OPTION_key_dup, &OPTION_key_dup_dirty},
{"DPAD Down", &OPTION_key_ddown, &OPTION_key_ddown_dirty},
{"DPAD Left", &OPTION_key_dleft, &OPTION_key_dleft_dirty},
{"DPAD Right", &OPTION_key_dright, &OPTION_key_dright_dirty},
{NULL, NULL, NULL}, /* K_CONT_Z */
{"Y button", &OPTION_key_y, &OPTION_key_y_dirty},
{"X button", &OPTION_key_x, &OPTION_key_x_dirty},
{NULL, NULL, NULL}, /* K_CONT_D */
{NULL, NULL, NULL}, /* K_CONT_DPAD2_UP */
{NULL, NULL, NULL}, /* K_CONT_DPAD2_DOWN */
{NULL, NULL, NULL}, /* K_CONT_DPAD2_LEFT */
{NULL, NULL, NULL}, /* K_CONT_DPAD2_RIGHT */
{"Joystick -X axis", &OPTION_key_joyx_neg, &OPTION_key_joyx_neg_dirty},
{"Joystick +X axis", &OPTION_key_joyx_pos, &OPTION_key_joyx_pos_dirty},
{"Joystick -Y axis", &OPTION_key_joyy_neg, &OPTION_key_joyy_neg_dirty},
{"Joystick +Y axis", &OPTION_key_joyy_pos, &OPTION_key_joyy_pos_dirty},
{"Left trigger", &OPTION_key_ltrig, &OPTION_key_ltrig_dirty},
{"Right trigger", &OPTION_key_rtrig, &OPTION_key_rtrig_dirty},
{"B button", K_CONT_B, DIR_NONE, &OPTION_key_b, &OPTION_key_b_dirty},
{"A button", K_CONT_A, DIR_NONE, &OPTION_key_a, &OPTION_key_a_dirty},
{"Start button", K_CONT_START, DIR_NONE, &OPTION_key_start, &OPTION_key_start_dirty},
{"DPAD Up", K_CONT_DPAD_UP, DIR_NONE, &OPTION_key_dup, &OPTION_key_dup_dirty},
{"DPAD Down", K_CONT_DPAD_DOWN, DIR_NONE, &OPTION_key_ddown, &OPTION_key_ddown_dirty},
{"DPAD Left", K_CONT_DPAD_LEFT, DIR_NONE, &OPTION_key_dleft, &OPTION_key_dleft_dirty},
{"DPAD Right", K_CONT_DPAD_RIGHT, DIR_NONE, &OPTION_key_dright, &OPTION_key_dright_dirty},
{"Y button", K_CONT_Y, DIR_NONE, &OPTION_key_y, &OPTION_key_y_dirty},
{"X button", K_CONT_X, DIR_NONE, &OPTION_key_x, &OPTION_key_x_dirty},
{"Joystick -X axis", K_CONT_JOYX, DIR_NEG, &OPTION_key_joyx_neg, &OPTION_key_joyx_neg_dirty},
{"Joystick +X axis", K_CONT_JOYX, DIR_POS, &OPTION_key_joyx_pos, &OPTION_key_joyx_pos_dirty},
{"Joystick -Y axis", K_CONT_JOYY, DIR_NEG, &OPTION_key_joyy_neg, &OPTION_key_joyy_neg_dirty},
{"Joystick +Y axis", K_CONT_JOYY, DIR_POS, &OPTION_key_joyy_pos, &OPTION_key_joyy_pos_dirty},
{"Left trigger", K_CONT_LTRIG, DIR_POS, &OPTION_key_ltrig, &OPTION_key_ltrig_dirty},
{"Right trigger", K_CONT_RTRIG, DIR_POS, &OPTION_key_rtrig, &OPTION_key_rtrig_dirty},
};
const int NUM_BUTTONS = ARRAY_SIZE(BUTTONS);
/* host */
DEFINE_OPTION_STRING(sync, "av", "Sync control");
DEFINE_OPTION_INT(bios, 0, "Boot to bios");
DEFINE_PERSISTENT_OPTION_INT(fullscreen, 0, "Start window fullscreen");
DEFINE_PERSISTENT_OPTION_INT(key_a, 'l', "A button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_b, 'p', "B button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_x, 'k', "X button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_y, 'o', "Y button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_start, K_SPACE, "Start button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dup, 't', "DPAD Up mapping");
DEFINE_PERSISTENT_OPTION_INT(key_ddown, 'g', "DPAD Down mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dleft, 'f', "DPAD Left mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dright, 'h', "DPAD Right mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyx_neg, 'a', "Joystick -X axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyx_pos, 'd', "Joystick +X axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyy_neg, 'w', "Joystick -Y axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyy_pos, 's', "Joystick +Y axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_ltrig, '[', "Left trigger mapping");
DEFINE_PERSISTENT_OPTION_INT(key_rtrig, ']', "Right trigger mapping");
DEFINE_OPTION_STRING(sync, "av", "Sync control");
DEFINE_OPTION_INT(bios, 0, "Boot to bios");
DEFINE_PERSISTENT_OPTION_INT(fullscreen, 0, "Start window fullscreen");
DEFINE_PERSISTENT_OPTION_INT(key_a, 'l', "A button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_b, 'p', "B button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_x, 'k', "X button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_y, 'o', "Y button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_start, ' ', "Start button mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dup, 't', "DPAD Up mapping");
DEFINE_PERSISTENT_OPTION_INT(key_ddown, 'g', "DPAD Down mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dleft, 'f', "DPAD Left mapping");
DEFINE_PERSISTENT_OPTION_INT(key_dright, 'h', "DPAD Right mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyx_neg, 'a', "Joystick -X axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyx_pos, 'd', "Joystick +X axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyy_neg, 'w', "Joystick -Y axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_joyy_pos, 's', "Joystick +Y axis mapping");
DEFINE_PERSISTENT_OPTION_INT(key_ltrig, '[', "Left trigger mapping");
DEFINE_PERSISTENT_OPTION_INT(key_rtrig, ']', "Right trigger mapping");
/* emulator */
DEFINE_PERSISTENT_OPTION_STRING(aspect, "4:3", "Video aspect ratio");
DEFINE_PERSISTENT_OPTION_STRING(aspect, "4:3", "Video aspect ratio");
/* bios */
DEFINE_PERSISTENT_OPTION_STRING(region, "usa", "System region");
DEFINE_PERSISTENT_OPTION_STRING(language, "english", "System language");
DEFINE_PERSISTENT_OPTION_STRING(broadcast, "ntsc", "System broadcast mode");
DEFINE_PERSISTENT_OPTION_STRING(region, "usa", "System region");
DEFINE_PERSISTENT_OPTION_STRING(language, "english", "System language");
DEFINE_PERSISTENT_OPTION_STRING(broadcast, "ntsc", "System broadcast mode");
/* jit */
DEFINE_OPTION_INT(perf, 0, "Create maps for compiled code for use with perf");
DEFINE_OPTION_INT(perf, 0, "Create maps for compiled code for use with perf");
/* ui */
DEFINE_PERSISTENT_OPTION_STRING(gamedir, "", "Directories to scan for games");
DEFINE_PERSISTENT_OPTION_STRING(gamedir, "", "Directories to scan for games");
/* clang-format on */
int audio_sync_enabled() {
const char *ptr = OPTION_sync;

View File

@ -2,8 +2,16 @@
#include "core/option.h"
enum {
DIR_NONE,
DIR_NEG,
DIR_POS,
};
struct button_map {
const char *desc;
int btn;
int dir;
int *key;
int *dirty;
};

View File

@ -716,7 +716,7 @@ int tracer_load(struct tracer *tracer, const char *path) {
return 1;
}
int tracer_keydown(struct tracer *tracer, int key, uint16_t value) {
int tracer_keydown(struct tracer *tracer, int key, int16_t value) {
if (key == K_LEFT && value) {
tracer_prev_context(tracer);
} else if (key == K_RIGHT && value) {

View File

@ -12,7 +12,7 @@ void tracer_destroy(struct tracer *tracer);
void tracer_vid_created(struct tracer *tracer, struct render_backend *r);
void tracer_vid_destroyed(struct tracer *tracer);
int tracer_keydown(struct tracer *tracer, int key, uint16_t value);
int tracer_keydown(struct tracer *tracer, int key, int16_t value);
int tracer_load(struct tracer *tracer, const char *path);
void tracer_render_frame(struct tracer *tracer);