comparison io.c @ 483:3e1573fa22cf

Implement turbo/slow motion feature that overclocks or underclocks the entire system at the push of a button
author Mike Pavone <pavone@retrodev.com>
date Tue, 01 Oct 2013 23:51:16 -0700
parents 140af5509ce7
children 36c080ece4ed
comparison
equal deleted inserted replaced
482:4b24260125f3 483:3e1573fa22cf
1 /* 1 /*
2 Copyright 2013 Michael Pavone 2 Copyright 2013 Michael Pavone
3 This file is part of BlastEm. 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. 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 */ 5 */
6 #include "io.h" 6 #include "io.h"
7 #include "blastem.h" 7 #include "blastem.h"
8 #include "render.h" 8 #include "render.h"
16 16
17 typedef enum { 17 typedef enum {
18 UI_DEBUG_MODE_INC, 18 UI_DEBUG_MODE_INC,
19 UI_DEBUG_PAL_INC, 19 UI_DEBUG_PAL_INC,
20 UI_ENTER_DEBUGGER, 20 UI_ENTER_DEBUGGER,
21 UI_SAVE_STATE, 21 UI_SAVE_STATE,
22 UI_SET_SPEED,
23 UI_NEXT_SPEED,
24 UI_PREV_SPEED,
22 UI_EXIT 25 UI_EXIT
23 } ui_action; 26 } ui_action;
24 27
25 typedef struct { 28 typedef struct {
26 uint8_t bind_type; 29 uint8_t bind_type;
137 } 140 }
138 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1; 141 uint8_t bind_type = gamepadnum - 1 + BIND_GAMEPAD1;
139 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);
140 } 143 }
141 144
142 void bind_ui(int keycode, ui_action action) 145 void bind_ui(int keycode, ui_action action, uint8_t param)
143 { 146 {
144 bind_key(keycode, BIND_UI, action, 0, 0); 147 bind_key(keycode, BIND_UI, action, 0, param);
145 } 148 }
146 149
147 void handle_binding_down(keybinding * binding) 150 void handle_binding_down(keybinding * binding)
148 { 151 {
149 switch(binding->bind_type) 152 switch(binding->bind_type)
180 handle_binding_down(binding); 183 handle_binding_down(binding);
181 } 184 }
182 185
183 uint8_t ui_debug_mode = 0; 186 uint8_t ui_debug_mode = 0;
184 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;
185 192
186 void handle_binding_up(keybinding * binding) 193 void handle_binding_up(keybinding * binding)
187 { 194 {
188 switch(binding->bind_type) 195 switch(binding->bind_type)
189 { 196 {
216 case UI_ENTER_DEBUGGER: 223 case UI_ENTER_DEBUGGER:
217 break_on_sync = 1; 224 break_on_sync = 1;
218 break; 225 break;
219 case UI_SAVE_STATE: 226 case UI_SAVE_STATE:
220 save_state = 1; 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 }
221 break; 254 break;
222 case UI_EXIT: 255 case UI_EXIT:
223 exit(0); 256 exit(0);
224 } 257 }
225 break; 258 break;
284 } 317 }
285 } else { 318 } else {
286 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]); 319 fprintf(stderr, "Gamepad mapping string '%s' refers to an invalid gamepad number %c\n", target, target[gpadslen]);
287 } 320 }
288 } else if(!memcmp(target, "ui.", strlen("ui."))) { 321 } else if(!memcmp(target, "ui.", strlen("ui."))) {
322 *padbutton_out = 0;
289 if (!strcmp(target + 3, "vdp_debug_mode")) { 323 if (!strcmp(target + 3, "vdp_debug_mode")) {
290 *ui_out = UI_DEBUG_MODE_INC; 324 *ui_out = UI_DEBUG_MODE_INC;
291 } else if(!strcmp(target + 3, "vdp_debug_pal")) { 325 } else if(!strcmp(target + 3, "vdp_debug_pal")) {
292 *ui_out = UI_DEBUG_PAL_INC; 326 *ui_out = UI_DEBUG_PAL_INC;
293 } else if(!strcmp(target + 3, "enter_debugger")) { 327 } else if(!strcmp(target + 3, "enter_debugger")) {
294 *ui_out = UI_ENTER_DEBUGGER; 328 *ui_out = UI_ENTER_DEBUGGER;
295 } else if(!strcmp(target + 3, "save_state")) { 329 } else if(!strcmp(target + 3, "save_state")) {
296 *ui_out = UI_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;
297 } else if(!strcmp(target + 3, "exit")) { 338 } else if(!strcmp(target + 3, "exit")) {
298 *ui_out = UI_EXIT; 339 *ui_out = UI_EXIT;
299 } else { 340 } else {
300 fprintf(stderr, "Unreconized UI binding type %s\n", target); 341 fprintf(stderr, "Unreconized UI binding type %s\n", target);
301 return 0; 342 return 0;
307 return 0; 348 return 0;
308 } 349 }
309 350
310 void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix) 351 void process_keys(tern_node * cur, tern_node * special, tern_node * padbuttons, char * prefix)
311 { 352 {
312 char * curstr; 353 char * curstr = NULL;
313 int len; 354 int len;
314 if (!cur) { 355 if (!cur) {
315 return; 356 return;
316 } 357 }
317 char onec[2]; 358 char onec[2];
322 } else { 363 } else {
323 curstr = onec; 364 curstr = onec;
324 len = 0; 365 len = 0;
325 } 366 }
326 curstr[len] = cur->el; 367 curstr[len] = cur->el;
368 curstr[len+1] = 0;
327 if (cur->el) { 369 if (cur->el) {
328 curstr[len+1] = 0;
329 process_keys(cur->straight.next, special, padbuttons, curstr); 370 process_keys(cur->straight.next, special, padbuttons, curstr);
330 } else { 371 } else {
331 int keycode = tern_find_int(special, curstr, 0); 372 int keycode = tern_find_int(special, curstr, 0);
332 if (!keycode) { 373 if (!keycode) {
333 keycode = curstr[0]; 374 keycode = curstr[0];
339 int ui_func, padnum, button; 380 int ui_func, padnum, button;
340 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button); 381 int bindtype = parse_binding_target(target, padbuttons, &ui_func, &padnum, &button);
341 if (bindtype == 1) { 382 if (bindtype == 1) {
342 bind_gamepad(keycode, padnum, button); 383 bind_gamepad(keycode, padnum, button);
343 } else if(bindtype == 2) { 384 } else if(bindtype == 2) {
344 bind_ui(keycode, ui_func); 385 bind_ui(keycode, ui_func, button);
345 } 386 }
346 } 387 }
347 process_keys(cur->left, special, padbuttons, prefix); 388 process_keys(cur->left, special, padbuttons, prefix);
348 process_keys(cur->right, 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 }
349 } 438 }
350 439
351 void set_keybindings() 440 void set_keybindings()
352 { 441 {
353 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP); 442 tern_node * special = tern_insert_int(NULL, "up", RENDERKEY_UP);
423 //TODO: Handle UI bindings 512 //TODO: Handle UI bindings
424 } 513 }
425 } 514 }
426 } 515 }
427 } 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 }
428 } 527 }
429 528
430 #define TH 0x40 529 #define TH 0x40
431 #define TH_TIMEOUT 8000 530 #define TH_TIMEOUT 8000
432 531