summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorMike Pavone <pavone@retrodev.com>2013-10-26 22:38:47 -0700
committerMike Pavone <pavone@retrodev.com>2013-10-26 22:38:47 -0700
commit7e61eaa7225bf025af42f88d0598aff8412f4144 (patch)
treebd19c2e555fc997065eba51715459185db566878 /io.c
parent4788b58c7290ad4a4a161d6bc69bc184acc2ef66 (diff)
parentb8dc9d69563379341f127af571b4bec1312f4ca0 (diff)
Update opengl branch from default. Fix build breakage unrelated to merge
--HG-- branch : opengl
Diffstat (limited to 'io.c')
-rw-r--r--io.c308
1 files changed, 275 insertions, 33 deletions
diff --git a/io.c b/io.c
index c951739..c83f756 100644
--- a/io.c
+++ b/io.c
@@ -1,3 +1,8 @@
+/*
+ Copyright 2013 Michael Pavone
+ This file is part of BlastEm.
+ BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
+*/
#include "io.h"
#include "blastem.h"
#include "render.h"
@@ -12,7 +17,12 @@ enum {
typedef enum {
UI_DEBUG_MODE_INC,
UI_DEBUG_PAL_INC,
- UI_ENTER_DEBUGGER
+ UI_ENTER_DEBUGGER,
+ UI_SAVE_STATE,
+ UI_SET_SPEED,
+ UI_NEXT_SPEED,
+ UI_PREV_SPEED,
+ UI_EXIT
} ui_action;
typedef struct {
@@ -106,7 +116,7 @@ void bind_dpad(int joystick, int dpad, int direction, uint8_t bind_type, uint8_t
void bind_gamepad(int keycode, int gamepadnum, int button)
{
-
+
if (gamepadnum < 1 || gamepadnum > 2) {
return;
}
@@ -132,9 +142,9 @@ void bind_dpad_gamepad(int joystick, int dpad, uint8_t direction, int gamepadnum
bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
}
-void bind_ui(int keycode, ui_action action)
+void bind_ui(int keycode, ui_action action, uint8_t param)
{
- bind_key(keycode, BIND_UI, action, 0, 0);
+ bind_key(keycode, BIND_UI, action, 0, param);
}
void handle_binding_down(keybinding * binding)
@@ -176,6 +186,10 @@ void handle_joydown(int joystick, int button)
uint8_t ui_debug_mode = 0;
uint8_t ui_debug_pal = 0;
+int current_speed = 0;
+int num_speeds = 1;
+uint32_t * speeds = NULL;
+
void handle_binding_up(keybinding * binding)
{
switch(binding->bind_type)
@@ -197,7 +211,7 @@ void handle_binding_up(keybinding * binding)
if (ui_debug_mode == 4) {
ui_debug_mode = 0;
}
- render_debug_mode(ui_debug_mode);
+ genesis->vdp->debug = ui_debug_mode;
break;
case UI_DEBUG_PAL_INC:
ui_debug_pal++;
@@ -209,6 +223,37 @@ void handle_binding_up(keybinding * binding)
case UI_ENTER_DEBUGGER:
break_on_sync = 1;
break;
+ case UI_SAVE_STATE:
+ save_state = 1;
+ break;
+ case UI_NEXT_SPEED:
+ current_speed++;
+ if (current_speed >= num_speeds) {
+ current_speed = 0;
+ }
+ printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
+ set_speed_percent(genesis, speeds[current_speed]);
+ break;
+ case UI_PREV_SPEED:
+ current_speed--;
+ if (current_speed < 0) {
+ current_speed = num_speeds - 1;
+ }
+ printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
+ set_speed_percent(genesis, speeds[current_speed]);
+ break;
+ case UI_SET_SPEED:
+ if (binding->value < num_speeds) {
+ current_speed = binding->value;
+ printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
+ set_speed_percent(genesis, speeds[current_speed]);
+ } else {
+ printf("Setting speed to %d\n", speeds[current_speed]);
+ set_speed_percent(genesis, binding->value);
+ }
+ break;
+ case UI_EXIT:
+ exit(0);
}
break;
}
@@ -252,36 +297,233 @@ void handle_joy_dpad(int joystick, int dpadnum, uint8_t value)
}
}
+int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out)
+{
+ int gpadslen = strlen("gamepads.");
+ if (!memcmp(target, "gamepads.", gpadslen)) {
+ if (target[gpadslen] >= '1' && target[gpadslen] <= '8') {
+ int padnum = target[gpadslen] - '0';
+ int button = tern_find_int(padbuttons, target + gpadslen + 1, 0);
+ if (button) {
+ *padnum_out = padnum;
+ *padbutton_out = button;
+ return 1;
+ } else {
+ if (target[gpadslen+1]) {
+ fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1);
+ } else {
+ fprintf(stderr, "Gamepad mapping string '%s' has no button component\n", target);
+ }
+ }
+ } else {
+ fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
+ }
+ } else if(!memcmp(target, "ui.", strlen("ui."))) {
+ *padbutton_out = 0;
+ if (!strcmp(target + 3, "vdp_debug_mode")) {
+ *ui_out = UI_DEBUG_MODE_INC;
+ } else if(!strcmp(target + 3, "vdp_debug_pal")) {
+ *ui_out = UI_DEBUG_PAL_INC;
+ } else if(!strcmp(target + 3, "enter_debugger")) {
+ *ui_out = UI_ENTER_DEBUGGER;
+ } else if(!strcmp(target + 3, "save_state")) {
+ *ui_out = UI_SAVE_STATE;
+ } else if(!memcmp(target + 3, "set_speed.", strlen("set_speed."))) {
+ *ui_out = UI_SET_SPEED;
+ *padbutton_out = atoi(target + 3 + strlen("set_speed."));
+ } else if(!strcmp(target + 3, "next_speed")) {
+ *ui_out = UI_NEXT_SPEED;
+ } else if(!strcmp(target + 3, "prev_speed")) {
+ *ui_out = UI_PREV_SPEED;
+ } else if(!strcmp(target + 3, "exit")) {
+ *ui_out = UI_EXIT;
+ } else {
+ fprintf(stderr, "Unreconized UI binding type %s\n", target);
+ return 0;
+ }
+ return 2;
+ } else {
+ fprintf(stderr, "Unrecognized binding type %s\n", target);
+ }
+ return 0;
+}
+
+void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix)
+{
+ char * curstr = NULL;
+ int len;
+ if (!cur) {
+ return;
+ }
+ char onec[2];
+ if (prefix) {
+ len = strlen(prefix);
+ curstr = malloc(len + 2);
+ memcpy(curstr, prefix, len);
+ } else {
+ curstr = onec;
+ len = 0;
+ }
+ curstr[len] = cur->el;
+ curstr[len+1] = 0;
+ if (cur->el) {
+ process_keys(cur->straight.next, special, padbuttons, curstr);
+ } else {
+ int keycode = tern_find_int(special, curstr, 0);
+ if (!keycode) {
+ keycode = curstr[0];
+ if (curstr[1] != 0) {
+ fprintf(stderr, "%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]);
+ }
+ }
+ char * target = cur->straight.value.ptrval;
+ int ui_func, padnum, button;
+ int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
+ if (bindtype == 1) {
+ bind_gamepad(keycode, padnum, button);
+ } else if(bindtype == 2) {
+ bind_ui(keycode, ui_func, button);
+ }
+ }
+ process_keys(cur->left, special, padbuttons, prefix);
+ process_keys(cur->right, special, padbuttons, prefix);
+ if (curstr && len) {
+ free(curstr);
+ }
+}
+
+void process_speeds(tern_node * cur, char * prefix)
+{
+ char * curstr = NULL;
+ int len;
+ if (!cur) {
+ return;
+ }
+ char onec[2];
+ if (prefix) {
+ len = strlen(prefix);
+ curstr = malloc(len + 2);
+ memcpy(curstr, prefix, len);
+ } else {
+ curstr = onec;
+ len = 0;
+ }
+ curstr[len] = cur->el;
+ curstr[len+1] = 0;
+ if (cur->el) {
+ process_speeds(cur->straight.next, curstr);
+ } else {
+ int speed_index = atoi(curstr);
+ if (speed_index < 1) {
+ if (!strcmp(curstr, "0")) {
+ fputs("Speed index 0 cannot be set to a custom value\n", stderr);
+ } else {
+ fprintf(stderr, "%s is not a valid speed index", curstr);
+ }
+ } else {
+ if (speed_index >= num_speeds) {
+ speeds = realloc(speeds, sizeof(uint32_t) * (speed_index+1));
+ for(; num_speeds < speed_index + 1; num_speeds++) {
+ speeds[num_speeds] = 0;
+ }
+ }
+ speeds[speed_index] = atoi(cur->straight.value.ptrval);
+ }
+ }
+ process_speeds(cur->left, prefix);
+ process_speeds(cur->right, prefix);
+ if (curstr && len) {
+ free(curstr);
+ }
+}
+
void set_keybindings()
{
- bind_gamepad(RENDERKEY_UP, 1, DPAD_UP);
- bind_gamepad(RENDERKEY_DOWN, 1, DPAD_DOWN);
- bind_gamepad(RENDERKEY_LEFT, 1, DPAD_LEFT);
- bind_gamepad(RENDERKEY_RIGHT, 1, DPAD_RIGHT);
- bind_gamepad('a', 1, BUTTON_A);
- bind_gamepad('s', 1, BUTTON_B);
- bind_gamepad('d', 1, BUTTON_C);
- bind_gamepad('q', 1, BUTTON_X);
- bind_gamepad('w', 1, BUTTON_Y);
- bind_gamepad('e', 1, BUTTON_Z);
- bind_gamepad('\r', 1, BUTTON_START);
- bind_gamepad('f', 1, BUTTON_MODE);
- bind_ui('[', UI_DEBUG_MODE_INC);
- bind_ui(']', UI_DEBUG_PAL_INC);
- bind_ui('u', UI_ENTER_DEBUGGER);
-
- bind_dpad_gamepad(0, 0, RENDER_DPAD_UP, 2, DPAD_UP);
- bind_dpad_gamepad(0, 0, RENDER_DPAD_DOWN, 2, DPAD_DOWN);
- bind_dpad_gamepad(0, 0, RENDER_DPAD_LEFT, 2, DPAD_LEFT);
- bind_dpad_gamepad(0, 0, RENDER_DPAD_RIGHT, 2, DPAD_RIGHT);
- bind_button_gamepad(0, 0, 2, BUTTON_A);
- bind_button_gamepad(0, 1, 2, BUTTON_B);
- bind_button_gamepad(0, 2, 2, BUTTON_C);
- bind_button_gamepad(0, 3, 2, BUTTON_X);
- bind_button_gamepad(0, 4, 2, BUTTON_Y);
- bind_button_gamepad(0, 5, 2, BUTTON_Z);
- bind_button_gamepad(0, 6, 2, BUTTON_START);
- bind_button_gamepad(0, 7, 2, BUTTON_MODE);
+ tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
+ special = tern_insert_int(special, "down", RENDERKEY_DOWN);
+ special = tern_insert_int(special, "left", RENDERKEY_LEFT);
+ special = tern_insert_int(special, "right", RENDERKEY_RIGHT);
+ special = tern_insert_int(special, "enter", '\r');
+ special = tern_insert_int(special, "esc", RENDERKEY_ESC);
+
+ tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP);
+ padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN);
+ padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT);
+ padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT);
+ padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A);
+ padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B);
+ padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C);
+ padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X);
+ padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
+ padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
+ padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
+ padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
+
+ tern_node * keys = tern_find_prefix(config, "bindingskeys");
+ process_keys(keys, special, padbuttons, NULL);
+ char prefix[] = "bindingspads00";
+ for (int i = 0; i < 100 && i < render_num_joysticks(); i++)
+ {
+ if (i < 10) {
+ prefix[strlen("bindingspads")] = i + '0';
+ prefix[strlen("bindingspads")+1] = 0;
+ } else {
+ prefix[strlen("bindingspads")] = i/10 + '0';
+ prefix[strlen("bindingspads")+1] = i%10 + '0';
+ }
+ tern_node * pad = tern_find_prefix(config, prefix);
+ if (pad) {
+ char dprefix[] = "dpads0";
+ for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++)
+ {
+ dprefix[strlen("dpads")] = dpad + '0';
+ tern_node * pad_dpad = tern_find_prefix(pad, dprefix);
+ char * dirs[] = {"up", "down", "left", "right"};
+ int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
+ for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
+ char * target = tern_find_ptr(pad_dpad, dirs[dir]);
+ if (target) {
+ int ui_func, padnum, button;
+ int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
+ if (bindtype == 1) {
+ bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button);
+ }
+ //TODO: Handle UI bindings
+ }
+ }
+ }
+ char bprefix[] = "buttons00";
+ for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++)
+ {
+ if (but < 10) {
+ bprefix[strlen("buttons")] = but + '0';
+ bprefix[strlen("buttons")+1] = 0;
+ } else {
+ bprefix[strlen("buttons")] = but/10 + '0';
+ bprefix[strlen("buttons")+1] = but%10 + '0';
+ }
+ char * target = tern_find_ptr(pad, bprefix);
+ if (target) {
+ int ui_func, padnum, button;
+ int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
+ if (bindtype == 1) {
+ bind_button_gamepad(i, but, padnum, button);
+ }
+ //TODO: Handle UI bindings
+ }
+ }
+ }
+ }
+ tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds");
+ speeds = malloc(sizeof(uint32_t));
+ speeds[0] = 100;
+ process_speeds(speed_nodes, NULL);
+ for (int i = 0; i < num_speeds; i++) {
+ if (!speeds[i]) {
+ fprintf(stderr, "Speed index %d was not set to a valid percentage!", i);
+ speeds[i] = 100;
+ }
+ }
}
#define TH 0x40