comparison 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
comparison
equal deleted inserted replaced
449:7696d824489d 487:c08a4efeee7f
1 /*
2 Copyright 2013 Michael Pavone
3 This file is part of BlastEm.
4 BlastEm is free software distributed under the terms of the GNU General Public License version 3 or greater. See COPYING for full license text.
5 */
1 #include "io.h" 6 #include "io.h"
2 #include "blastem.h" 7 #include "blastem.h"
3 #include "render.h" 8 #include "render.h"
4 9
5 enum { 10 enum {
10 }; 15 };
11 16
12 typedef enum { 17 typedef enum {
13 UI_DEBUG_MODE_INC, 18 UI_DEBUG_MODE_INC,
14 UI_DEBUG_PAL_INC, 19 UI_DEBUG_PAL_INC,
15 UI_ENTER_DEBUGGER 20 UI_ENTER_DEBUGGER,
21 UI_SAVE_STATE,
22 UI_SET_SPEED,
23 UI_NEXT_SPEED,
24 UI_PREV_SPEED,
25 UI_EXIT
16 } ui_action; 26 } ui_action;
17 27
18 typedef struct { 28 typedef struct {
19 uint8_t bind_type; 29 uint8_t bind_type;
20 uint8_t subtype_a; 30 uint8_t subtype_a;
104 #define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20) 114 #define BUTTON_START GAMEPAD_BUTTON(GAMEPAD_TH0, GAMEPAD_NONE, 0x20)
105 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20) 115 #define BUTTON_C GAMEPAD_BUTTON(GAMEPAD_TH1, GAMEPAD_NONE, 0x20)
106 116
107 void bind_gamepad(int keycode, int gamepadnum, int button) 117 void bind_gamepad(int keycode, int gamepadnum, int button)
108 { 118 {
109 119
110 if (gamepadnum < 1 || gamepadnum > 2) { 120 if (gamepadnum < 1 || gamepadnum > 2) {
111 return; 121 return;
112 } 122 }
113 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 123 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
114 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 124 bind_key(keycode, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
130 } 140 }
131 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 141 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
132 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF); 142 bind_dpad(joystick, dpad, direction, bind_type, button >> 12, button >> 8 & 0xF, button & 0xFF);
133 } 143 }
134 144
135 void bind_ui(int keycode, ui_action action) 145 void bind_ui(int keycode, ui_action action, uint8_t param)
136 { 146 {
137 bind_key(keycode, BIND_UI, action, 0, 0); 147 bind_key(keycode, BIND_UI, action, 0, param);
138 } 148 }
139 149
140 void handle_binding_down(keybinding * binding) 150 void handle_binding_down(keybinding * binding)
141 { 151 {
142 switch(binding->bind_type) 152 switch(binding->bind_type)
173 handle_binding_down(binding); 183 handle_binding_down(binding);
174 } 184 }
175 185
176 uint8_t ui_debug_mode = 0; 186 uint8_t ui_debug_mode = 0;
177 uint8_t ui_debug_pal = 0; 187 uint8_t ui_debug_pal = 0;
188
189 int current_speed = 0;
190 int num_speeds = 1;
191 uint32_t * speeds = NULL;
178 192
179 void handle_binding_up(keybinding * binding) 193 void handle_binding_up(keybinding * binding)
180 { 194 {
181 switch(binding->bind_type) 195 switch(binding->bind_type)
182 { 196 {
195 case UI_DEBUG_MODE_INC: 209 case UI_DEBUG_MODE_INC:
196 ui_debug_mode++; 210 ui_debug_mode++;
197 if (ui_debug_mode == 4) { 211 if (ui_debug_mode == 4) {
198 ui_debug_mode = 0; 212 ui_debug_mode = 0;
199 } 213 }
200 render_debug_mode(ui_debug_mode); 214 genesis->vdp->debug = ui_debug_mode;
201 break; 215 break;
202 case UI_DEBUG_PAL_INC: 216 case UI_DEBUG_PAL_INC:
203 ui_debug_pal++; 217 ui_debug_pal++;
204 if (ui_debug_pal == 4) { 218 if (ui_debug_pal == 4) {
205 ui_debug_pal = 0; 219 ui_debug_pal = 0;
207 render_debug_pal(ui_debug_pal); 221 render_debug_pal(ui_debug_pal);
208 break; 222 break;
209 case UI_ENTER_DEBUGGER: 223 case UI_ENTER_DEBUGGER:
210 break_on_sync = 1; 224 break_on_sync = 1;
211 break; 225 break;
226 case UI_SAVE_STATE:
227 save_state = 1;
228 break;
229 case UI_NEXT_SPEED:
230 current_speed++;
231 if (current_speed >= num_speeds) {
232 current_speed = 0;
233 }
234 printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
235 set_speed_percent(genesis, speeds[current_speed]);
236 break;
237 case UI_PREV_SPEED:
238 current_speed--;
239 if (current_speed < 0) {
240 current_speed = num_speeds - 1;
241 }
242 printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
243 set_speed_percent(genesis, speeds[current_speed]);
244 break;
245 case UI_SET_SPEED:
246 if (binding->value < num_speeds) {
247 current_speed = binding->value;
248 printf("Setting speed to %d: %d\n", current_speed, speeds[current_speed]);
249 set_speed_percent(genesis, speeds[current_speed]);
250 } else {
251 printf("Setting speed to %d\n", speeds[current_speed]);
252 set_speed_percent(genesis, binding->value);
253 }
254 break;
255 case UI_EXIT:
256 exit(0);
212 } 257 }
213 break; 258 break;
214 } 259 }
215 } 260 }
216 261
250 handle_binding_up(dpad->bindings + i); 295 handle_binding_up(dpad->bindings + i);
251 } 296 }
252 } 297 }
253 } 298 }
254 299
300 int parse_binding_target(char * target, tern_node * padbuttons, int * ui_out, int * padnum_out, int * padbutton_out)
301 {
302 int gpadslen = strlen("gamepads.");
303 if (!memcmp(target, "gamepads.", gpadslen)) {
304 if (target[gpadslen] >= '1' && target[gpadslen] <= '8') {
305 int padnum = target[gpadslen] - '0';
306 int button = tern_find_int(padbuttons, target + gpadslen + 1, 0);
307 if (button) {
308 *padnum_out = padnum;
309 *padbutton_out = button;
310 return 1;
311 } else {
312 if (target[gpadslen+1]) {
313 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid button '%s'\n", target, target + gpadslen + 1);
314 } else {
315 fprintf(stderr, "Gamepad mapping string '%s' has no button component\n", target);
316 }
317 }
318 } else {
319 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
320 }
321 } else if(!memcmp(target, "ui.", strlen("ui."))) {
322 *padbutton_out = 0;
323 if (!strcmp(target + 3, "vdp_debug_mode")) {
324 *ui_out = UI_DEBUG_MODE_INC;
325 } else if(!strcmp(target + 3, "vdp_debug_pal")) {
326 *ui_out = UI_DEBUG_PAL_INC;
327 } else if(!strcmp(target + 3, "enter_debugger")) {
328 *ui_out = UI_ENTER_DEBUGGER;
329 } else if(!strcmp(target + 3, "save_state")) {
330 *ui_out = UI_SAVE_STATE;
331 } else if(!memcmp(target + 3, "set_speed.", strlen("set_speed."))) {
332 *ui_out = UI_SET_SPEED;
333 *padbutton_out = atoi(target + 3 + strlen("set_speed."));
334 } else if(!strcmp(target + 3, "next_speed")) {
335 *ui_out = UI_NEXT_SPEED;
336 } else if(!strcmp(target + 3, "prev_speed")) {
337 *ui_out = UI_PREV_SPEED;
338 } else if(!strcmp(target + 3, "exit")) {
339 *ui_out = UI_EXIT;
340 } else {
341 fprintf(stderr, "Unreconized UI binding type %s\n", target);
342 return 0;
343 }
344 return 2;
345 } else {
346 fprintf(stderr, "Unrecognized binding type %s\n", target);
347 }
348 return 0;
349 }
350
351 void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix)
352 {
353 char * curstr = NULL;
354 int len;
355 if (!cur) {
356 return;
357 }
358 char onec[2];
359 if (prefix) {
360 len = strlen(prefix);
361 curstr = malloc(len + 2);
362 memcpy(curstr, prefix, len);
363 } else {
364 curstr = onec;
365 len = 0;
366 }
367 curstr[len] = cur->el;
368 curstr[len+1] = 0;
369 if (cur->el) {
370 process_keys(cur->straight.next, special, padbuttons, curstr);
371 } else {
372 int keycode = tern_find_int(special, curstr, 0);
373 if (!keycode) {
374 keycode = curstr[0];
375 if (curstr[1] != 0) {
376 fprintf(stderr, "%s is not recognized as a key identifier, truncating to %c\n", curstr, curstr[0]);
377 }
378 }
379 char * target = cur->straight.value.ptrval;
380 int ui_func, padnum, button;
381 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
382 if (bindtype == 1) {
383 bind_gamepad(keycode, padnum, button);
384 } else if(bindtype == 2) {
385 bind_ui(keycode, ui_func, button);
386 }
387 }
388 process_keys(cur->left, special, padbuttons, prefix);
389 process_keys(cur->right, special, padbuttons, prefix);
390 if (curstr && len) {
391 free(curstr);
392 }
393 }
394
395 void process_speeds(tern_node * cur, char * prefix)
396 {
397 char * curstr = NULL;
398 int len;
399 if (!cur) {
400 return;
401 }
402 char onec[2];
403 if (prefix) {
404 len = strlen(prefix);
405 curstr = malloc(len + 2);
406 memcpy(curstr, prefix, len);
407 } else {
408 curstr = onec;
409 len = 0;
410 }
411 curstr[len] = cur->el;
412 curstr[len+1] = 0;
413 if (cur->el) {
414 process_speeds(cur->straight.next, curstr);
415 } else {
416 int speed_index = atoi(curstr);
417 if (speed_index < 1) {
418 if (!strcmp(curstr, "0")) {
419 fputs("Speed index 0 cannot be set to a custom value\n", stderr);
420 } else {
421 fprintf(stderr, "%s is not a valid speed index", curstr);
422 }
423 } else {
424 if (speed_index >= num_speeds) {
425 speeds = realloc(speeds, sizeof(uint32_t) * (speed_index+1));
426 for(; num_speeds < speed_index + 1; num_speeds++) {
427 speeds[num_speeds] = 0;
428 }
429 }
430 speeds[speed_index] = atoi(cur->straight.value.ptrval);
431 }
432 }
433 process_speeds(cur->left, prefix);
434 process_speeds(cur->right, prefix);
435 if (curstr && len) {
436 free(curstr);
437 }
438 }
439
255 void set_keybindings() 440 void set_keybindings()
256 { 441 {
257 bind_gamepad(RENDERKEY_UP, 1, DPAD_UP); 442 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
258 bind_gamepad(RENDERKEY_DOWN, 1, DPAD_DOWN); 443 special = tern_insert_int(special, "down", RENDERKEY_DOWN);
259 bind_gamepad(RENDERKEY_LEFT, 1, DPAD_LEFT); 444 special = tern_insert_int(special, "left", RENDERKEY_LEFT);
260 bind_gamepad(RENDERKEY_RIGHT, 1, DPAD_RIGHT); 445 special = tern_insert_int(special, "right", RENDERKEY_RIGHT);
261 bind_gamepad('a', 1, BUTTON_A); 446 special = tern_insert_int(special, "enter", '\r');
262 bind_gamepad('s', 1, BUTTON_B); 447 special = tern_insert_int(special, "esc", RENDERKEY_ESC);
263 bind_gamepad('d', 1, BUTTON_C); 448
264 bind_gamepad('q', 1, BUTTON_X); 449 tern_node * padbuttons = tern_insert_int(NULL, ".up", DPAD_UP);
265 bind_gamepad('w', 1, BUTTON_Y); 450 padbuttons = tern_insert_int(padbuttons, ".down", DPAD_DOWN);
266 bind_gamepad('e', 1, BUTTON_Z); 451 padbuttons = tern_insert_int(padbuttons, ".left", DPAD_LEFT);
267 bind_gamepad('\r', 1, BUTTON_START); 452 padbuttons = tern_insert_int(padbuttons, ".right", DPAD_RIGHT);
268 bind_gamepad('f', 1, BUTTON_MODE); 453 padbuttons = tern_insert_int(padbuttons, ".a", BUTTON_A);
269 bind_ui('[', UI_DEBUG_MODE_INC); 454 padbuttons = tern_insert_int(padbuttons, ".b", BUTTON_B);
270 bind_ui(']', UI_DEBUG_PAL_INC); 455 padbuttons = tern_insert_int(padbuttons, ".c", BUTTON_C);
271 bind_ui('u', UI_ENTER_DEBUGGER); 456 padbuttons = tern_insert_int(padbuttons, ".x", BUTTON_X);
272 457 padbuttons = tern_insert_int(padbuttons, ".y", BUTTON_Y);
273 bind_dpad_gamepad(0, 0, RENDER_DPAD_UP, 2, DPAD_UP); 458 padbuttons = tern_insert_int(padbuttons, ".z", BUTTON_Z);
274 bind_dpad_gamepad(0, 0, RENDER_DPAD_DOWN, 2, DPAD_DOWN); 459 padbuttons = tern_insert_int(padbuttons, ".start", BUTTON_START);
275 bind_dpad_gamepad(0, 0, RENDER_DPAD_LEFT, 2, DPAD_LEFT); 460 padbuttons = tern_insert_int(padbuttons, ".mode", BUTTON_MODE);
276 bind_dpad_gamepad(0, 0, RENDER_DPAD_RIGHT, 2, DPAD_RIGHT); 461
277 bind_button_gamepad(0, 0, 2, BUTTON_A); 462 tern_node * keys = tern_find_prefix(config, "bindingskeys");
278 bind_button_gamepad(0, 1, 2, BUTTON_B); 463 process_keys(keys, special, padbuttons, NULL);
279 bind_button_gamepad(0, 2, 2, BUTTON_C); 464 char prefix[] = "bindingspads00";
280 bind_button_gamepad(0, 3, 2, BUTTON_X); 465 for (int i = 0; i < 100 && i < render_num_joysticks(); i++)
281 bind_button_gamepad(0, 4, 2, BUTTON_Y); 466 {
282 bind_button_gamepad(0, 5, 2, BUTTON_Z); 467 if (i < 10) {
283 bind_button_gamepad(0, 6, 2, BUTTON_START); 468 prefix[strlen("bindingspads")] = i + '0';
284 bind_button_gamepad(0, 7, 2, BUTTON_MODE); 469 prefix[strlen("bindingspads")+1] = 0;
470 } else {
471 prefix[strlen("bindingspads")] = i/10 + '0';
472 prefix[strlen("bindingspads")+1] = i%10 + '0';
473 }
474 tern_node * pad = tern_find_prefix(config, prefix);
475 if (pad) {
476 char dprefix[] = "dpads0";
477 for (int dpad = 0; dpad < 10 && dpad < render_joystick_num_hats(i); dpad++)
478 {
479 dprefix[strlen("dpads")] = dpad + '0';
480 tern_node * pad_dpad = tern_find_prefix(pad, dprefix);
481 char * dirs[] = {"up", "down", "left", "right"};
482 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
483 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
484 char * target = tern_find_ptr(pad_dpad, dirs[dir]);
485 if (target) {
486 int ui_func, padnum, button;
487 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
488 if (bindtype == 1) {
489 bind_dpad_gamepad(i, dpad, dirnums[dir], padnum, button);
490 }
491 //TODO: Handle UI bindings
492 }
493 }
494 }
495 char bprefix[] = "buttons00";
496 for (int but = 0; but < 100 && but < render_joystick_num_buttons(i); but++)
497 {
498 if (but < 10) {
499 bprefix[strlen("buttons")] = but + '0';
500 bprefix[strlen("buttons")+1] = 0;
501 } else {
502 bprefix[strlen("buttons")] = but/10 + '0';
503 bprefix[strlen("buttons")+1] = but%10 + '0';
504 }
505 char * target = tern_find_ptr(pad, bprefix);
506 if (target) {
507 int ui_func, padnum, button;
508 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
509 if (bindtype == 1) {
510 bind_button_gamepad(i, but, padnum, button);
511 }
512 //TODO: Handle UI bindings
513 }
514 }
515 }
516 }
517 tern_node * speed_nodes = tern_find_prefix(config, "clocksspeeds");
518 speeds = malloc(sizeof(uint32_t));
519 speeds[0] = 100;
520 process_speeds(speed_nodes, NULL);
521 for (int i = 0; i < num_speeds; i++) {
522 if (!speeds[i]) {
523 fprintf(stderr, "Speed index %d was not set to a valid percentage!", i);
524 speeds[i] = 100;
525 }
526 }
285 } 527 }
286 528
287 #define TH 0x40 529 #define TH 0x40
288 #define TH_TIMEOUT 8000 530 #define TH_TIMEOUT 8000
289 531