Mercurial > repos > blastem
diff io.c @ 487:c08a4efeee7f opengl
Update opengl branch from default. Fix build breakage unrelated to merge
author | Mike Pavone <pavone@retrodev.com> |
---|---|
date | Sat, 26 Oct 2013 22:38:47 -0700 |
parents | 3e1573fa22cf |
children | 36c080ece4ed |
line wrap: on
line diff
--- a/io.c Tue Jul 23 23:01:03 2013 -0700 +++ b/io.c Sat Oct 26 22:38:47 2013 -0700 @@ -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 @@ 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_gamepad(int keycode, int gamepadnum, int button) { - + if (gamepadnum < 1 || gamepadnum > 2) { return; } @@ -132,9 +142,9 @@ 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 @@ 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 @@ 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 @@ 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 @@ } } +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