comparison io.c @ 1326:071e761bcdcf

Fix a deficiency in the way types were handled in my ternary tree. Fixes in which some paths that were constructed from a template with variables would sometimes get an extra garbage character thrown in
author Michael Pavone <pavone@retrodev.com>
date Fri, 21 Apr 2017 23:35:32 -0700
parents a719e2c98b54
children 040c5600e2d9
comparison
equal deleted inserted replaced
1325:58bfbed6cdb5 1326:071e761bcdcf
492 break; 492 break;
493 case UI_SOFT_RESET: 493 case UI_SOFT_RESET:
494 current_system->soft_reset(current_system); 494 current_system->soft_reset(current_system);
495 break; 495 break;
496 case UI_SCREENSHOT: { 496 case UI_SCREENSHOT: {
497 char *screenshot_base = tern_find_path(config, "ui\0screenshot_path\0").ptrval; 497 char *screenshot_base = tern_find_path(config, "ui\0screenshot_path\0", TVAL_PTR).ptrval;
498 if (!screenshot_base) { 498 if (!screenshot_base) {
499 screenshot_base = "$HOME"; 499 screenshot_base = "$HOME";
500 } 500 }
501 tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir()); 501 tern_node *vars = tern_insert_ptr(NULL, "HOME", get_home_dir());
502 vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir()); 502 vars = tern_insert_ptr(vars, "EXEDIR", get_exe_dir());
503 screenshot_base = replace_vars(screenshot_base, vars, 1); 503 screenshot_base = replace_vars(screenshot_base, vars, 1);
504 tern_free(vars); 504 tern_free(vars);
505 time_t now = time(NULL); 505 time_t now = time(NULL);
506 struct tm local_store; 506 struct tm local_store;
507 char fname_part[256]; 507 char fname_part[256];
508 char *template = tern_find_path(config, "ui\0screenshot_template\0").ptrval; 508 char *template = tern_find_path(config, "ui\0screenshot_template\0", TVAL_PTR).ptrval;
509 if (!template) { 509 if (!template) {
510 template = "blastem_%c.ppm"; 510 template = "blastem_%c.ppm";
511 } 511 }
512 strftime(fname_part, sizeof(fname_part), template, localtime_r(&now, &local_store)); 512 strftime(fname_part, sizeof(fname_part), template, localtime_r(&now, &local_store));
513 char const *parts[] = {screenshot_base, PATH_SEP, fname_part}; 513 char const *parts[] = {screenshot_base, PATH_SEP, fname_part};
874 874
875 void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io) 875 void setup_io_devices(tern_node * config, rom_info *rom, sega_io *io)
876 { 876 {
877 current_io = io; 877 current_io = io;
878 io_port * ports = current_io->ports; 878 io_port * ports = current_io->ports;
879 tern_node *io_nodes = tern_get_node(tern_find_path(config, "io\0devices\0")); 879 tern_node *io_nodes = tern_find_path(config, "io\0devices\0", TVAL_NODE).ptrval;
880 char * io_1 = rom->port1_override ? rom->port1_override : tern_find_ptr(io_nodes, "1"); 880 char * io_1 = rom->port1_override ? rom->port1_override : io_nodes ? tern_find_ptr(io_nodes, "1") : NULL;
881 char * io_2 = rom->port2_override ? rom->port2_override : tern_find_ptr(io_nodes, "2"); 881 char * io_2 = rom->port2_override ? rom->port2_override : io_nodes ? tern_find_ptr(io_nodes, "2") : NULL;
882 char * io_ext = rom->ext_override ? rom->ext_override : tern_find_ptr(io_nodes, "ext"); 882 char * io_ext = rom->ext_override ? rom->ext_override : io_nodes ? tern_find_ptr(io_nodes, "ext") : NULL;
883 883
884 process_device(io_1, ports); 884 process_device(io_1, ports);
885 process_device(io_2, ports+1); 885 process_device(io_2, ports+1);
886 process_device(io_ext, ports+2); 886 process_device(io_ext, ports+2);
887 887
899 for (int i = 0; i < 3; i++) 899 for (int i = 0; i < 3; i++)
900 { 900 {
901 #ifndef _WIN32 901 #ifndef _WIN32
902 if (ports[i].device_type == IO_SEGA_PARALLEL) 902 if (ports[i].device_type == IO_SEGA_PARALLEL)
903 { 903 {
904 char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0").ptrval; 904 char *pipe_name = tern_find_path(config, "io\0parallel_pipe\0", TVAL_PTR).ptrval;
905 if (!pipe_name) 905 if (!pipe_name)
906 { 906 {
907 warning("IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i)); 907 warning("IO port %s is configured to use the sega parallel board, but no paralell_pipe is set!\n", io_name(i));
908 ports[i].device_type = IO_NONE; 908 ports[i].device_type = IO_NONE;
909 } else { 909 } else {
925 } 925 }
926 } 926 }
927 } 927 }
928 } 928 }
929 } else if (ports[i].device_type == IO_GENERIC) { 929 } else if (ports[i].device_type == IO_GENERIC) {
930 char *sock_name = tern_find_path(config, "io\0socket\0").ptrval; 930 char *sock_name = tern_find_path(config, "io\0socket\0", TVAL_PTR).ptrval;
931 if (!sock_name) 931 if (!sock_name)
932 { 932 {
933 warning("IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i)); 933 warning("IO port %s is configured to use generic IO, but no socket is set!\n", io_name(i));
934 ports[i].device_type = IO_NONE; 934 ports[i].device_type = IO_NONE;
935 } else { 935 } else {
1011 tern_node *padbuttons; 1011 tern_node *padbuttons;
1012 tern_node *mousebuttons; 1012 tern_node *mousebuttons;
1013 int mouseidx; 1013 int mouseidx;
1014 } pmb_state; 1014 } pmb_state;
1015 1015
1016 void process_mouse_button(char *buttonstr, tern_val value, void *data) 1016 void process_mouse_button(char *buttonstr, tern_val value, uint8_t valtype, void *data)
1017 { 1017 {
1018 pmb_state *state = data; 1018 pmb_state *state = data;
1019 int buttonnum = atoi(buttonstr); 1019 int buttonnum = atoi(buttonstr);
1020 if (buttonnum < 1 || buttonnum > MAX_MOUSE_BUTTONS) { 1020 if (buttonnum < 1 || buttonnum > MAX_MOUSE_BUTTONS) {
1021 warning("Mouse button %s is out of the supported range of 1-8\n", buttonstr); 1021 warning("Mouse button %s is out of the supported range of 1-8\n", buttonstr);
1022 return; 1022 return;
1023 } 1023 }
1024 if (valtype != TVAL_PTR) {
1025 warning("Mouse button %s is not a scalar value!\n", buttonstr);
1026 return;
1027 }
1024 buttonnum--; 1028 buttonnum--;
1025 int ui_func, devicenum, button; 1029 int ui_func, devicenum, button;
1026 int bindtype = parse_binding_target(value.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &devicenum, &button); 1030 int bindtype = parse_binding_target(value.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &devicenum, &button);
1027 switch (bindtype) 1031 switch (bindtype)
1028 { 1032 {
1043 } 1047 }
1044 mice[state->mouseidx].buttons[buttonnum].bind_type = bindtype; 1048 mice[state->mouseidx].buttons[buttonnum].bind_type = bindtype;
1045 1049
1046 } 1050 }
1047 1051
1048 void process_mouse(char *mousenum, tern_val value, void *data) 1052 void process_mouse(char *mousenum, tern_val value, uint8_t valtype, void *data)
1049 { 1053 {
1050 tern_node **buttonmaps = data; 1054 tern_node **buttonmaps = data;
1051 tern_node *mousedef = tern_get_node(value); 1055 if (valtype != TVAL_NODE) {
1056 warning("Binding for mouse %s is a scalar!\n", mousenum);
1057 return;
1058 }
1059 tern_node *mousedef = value.ptrval;
1052 tern_node *padbuttons = buttonmaps[0]; 1060 tern_node *padbuttons = buttonmaps[0];
1053 tern_node *mousebuttons = buttonmaps[1]; 1061 tern_node *mousebuttons = buttonmaps[1];
1054 1062
1055 if (!mousedef) {
1056 warning("Binding for mouse %s is a scalar!\n", mousenum);
1057 return;
1058 }
1059 int mouseidx = atoi(mousenum); 1063 int mouseidx = atoi(mousenum);
1060 if (mouseidx < 0 || mouseidx >= MAX_MICE) { 1064 if (mouseidx < 0 || mouseidx >= MAX_MICE) {
1061 warning("Mouse numbers must be between 0 and %d, but %d is not\n", MAX_MICE, mouseidx); 1065 warning("Mouse numbers must be between 0 and %d, but %d is not\n", MAX_MICE, mouseidx);
1062 return; 1066 return;
1063 } 1067 }
1072 mice[mouseidx].bind_type = bindtype; 1076 mice[mouseidx].bind_type = bindtype;
1073 } else { 1077 } else {
1074 warning("Mouse motion can't be bound to target %s\n", motion); 1078 warning("Mouse motion can't be bound to target %s\n", motion);
1075 } 1079 }
1076 } 1080 }
1077 tern_node *buttons = tern_get_node(tern_find_path(mousedef, "buttons\0\0")); 1081 tern_node *buttons = tern_find_path(mousedef, "buttons\0\0", TVAL_NODE).ptrval;
1078 if (buttons) { 1082 if (buttons) {
1079 pmb_state state = {padbuttons, mousebuttons, mouseidx}; 1083 pmb_state state = {padbuttons, mousebuttons, mouseidx};
1080 tern_foreach(buttons, process_mouse_button, &state); 1084 tern_foreach(buttons, process_mouse_button, &state);
1081 } 1085 }
1082 } 1086 }
1085 int padnum; 1089 int padnum;
1086 tern_node *padbuttons; 1090 tern_node *padbuttons;
1087 tern_node *mousebuttons; 1091 tern_node *mousebuttons;
1088 } pad_button_state; 1092 } pad_button_state;
1089 1093
1090 void process_pad_button(char *key, tern_val val, void *data) 1094 void process_pad_button(char *key, tern_val val, uint8_t valtype, void *data)
1091 { 1095 {
1092 pad_button_state *state = data; 1096 pad_button_state *state = data;
1093 int hostpadnum = state->padnum; 1097 int hostpadnum = state->padnum;
1094 int ui_func, padnum, button; 1098 int ui_func, padnum, button;
1099 if (valtype != TVAL_PTR) {
1100 warning("Pad button %s has a non-scalar value\n", key);
1101 return;
1102 }
1095 int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button); 1103 int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button);
1096 char *end; 1104 char *end;
1097 long hostbutton = strtol(key, &end, 10); 1105 long hostbutton = strtol(key, &end, 10);
1098 if (*end) { 1106 if (*end) {
1099 //key is not a valid base 10 integer 1107 //key is not a valid base 10 integer
1127 } else if (bindtype == BIND_UI) { 1135 } else if (bindtype == BIND_UI) {
1128 bind_button_ui(hostpadnum, hostbutton, ui_func, button); 1136 bind_button_ui(hostpadnum, hostbutton, ui_func, button);
1129 } 1137 }
1130 } 1138 }
1131 1139
1132 void process_pad_axis(char *key, tern_val val, void *data) 1140 void process_pad_axis(char *key, tern_val val, uint8_t valtype, void *data)
1133 { 1141 {
1134 key = strdup(key); 1142 key = strdup(key);
1135 pad_button_state *state = data; 1143 pad_button_state *state = data;
1136 int hostpadnum = state->padnum; 1144 int hostpadnum = state->padnum;
1137 int ui_func, padnum, button; 1145 int ui_func, padnum, button;
1146 if (valtype != TVAL_PTR) {
1147 warning("Mapping for axis %s has a non-scalar value", key);
1148 return;
1149 }
1138 int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button); 1150 int bindtype = parse_binding_target(val.ptrval, state->padbuttons, state->mousebuttons, &ui_func, &padnum, &button);
1139 char *modifier = strchr(key, '.'); 1151 char *modifier = strchr(key, '.');
1140 int positive = 1; 1152 int positive = 1;
1141 if (modifier) { 1153 if (modifier) {
1142 *modifier = 0; 1154 *modifier = 0;
1224 void handle_joy_added(int joystick) 1236 void handle_joy_added(int joystick)
1225 { 1237 {
1226 if (joystick > MAX_JOYSTICKS) { 1238 if (joystick > MAX_JOYSTICKS) {
1227 return; 1239 return;
1228 } 1240 }
1229 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); 1241 tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
1230 if (pads) { 1242 if (pads) {
1231 char numstr[11]; 1243 char numstr[11];
1232 sprintf(numstr, "%d", joystick); 1244 sprintf(numstr, "%d", joystick);
1233 tern_node * pad = tern_find_ptr(pads, numstr); 1245 tern_node * pad = tern_find_node(pads, numstr);
1234 if (pad) { 1246 if (pad) {
1235 tern_node * dpad_node = tern_find_ptr(pad, "dpads"); 1247 tern_node * dpad_node = tern_find_node(pad, "dpads");
1236 if (dpad_node) { 1248 if (dpad_node) {
1237 for (int dpad = 0; dpad < 10; dpad++) 1249 for (int dpad = 0; dpad < 10; dpad++)
1238 { 1250 {
1239 numstr[0] = dpad + '0'; 1251 numstr[0] = dpad + '0';
1240 numstr[1] = 0; 1252 numstr[1] = 0;
1241 tern_node * pad_dpad = tern_find_ptr(dpad_node, numstr); 1253 tern_node * pad_dpad = tern_find_node(dpad_node, numstr);
1242 char * dirs[] = {"up", "down", "left", "right"}; 1254 char * dirs[] = {"up", "down", "left", "right"};
1243 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT}; 1255 int dirnums[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
1244 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) { 1256 for (int dir = 0; dir < sizeof(dirs)/sizeof(dirs[0]); dir++) {
1245 char * target = tern_find_ptr(pad_dpad, dirs[dir]); 1257 char * target = tern_find_ptr(pad_dpad, dirs[dir]);
1246 if (target) { 1258 if (target) {
1253 } 1265 }
1254 } 1266 }
1255 } 1267 }
1256 } 1268 }
1257 } 1269 }
1258 tern_node *button_node = tern_find_ptr(pad, "buttons"); 1270 tern_node *button_node = tern_find_node(pad, "buttons");
1259 if (button_node) { 1271 if (button_node) {
1260 pad_button_state state = { 1272 pad_button_state state = {
1261 .padnum = joystick, 1273 .padnum = joystick,
1262 .padbuttons = get_pad_buttons(), 1274 .padbuttons = get_pad_buttons(),
1263 .mousebuttons = get_mouse_buttons() 1275 .mousebuttons = get_mouse_buttons()
1264 }; 1276 };
1265 tern_foreach(button_node, process_pad_button, &state); 1277 tern_foreach(button_node, process_pad_button, &state);
1266 } 1278 }
1267 tern_node *axes_node = tern_find_ptr(pad, "axes"); 1279 tern_node *axes_node = tern_find_node(pad, "axes");
1268 if (axes_node) { 1280 if (axes_node) {
1269 pad_button_state state = { 1281 pad_button_state state = {
1270 .padnum = joystick, 1282 .padnum = joystick,
1271 .padbuttons = get_pad_buttons(), 1283 .padbuttons = get_pad_buttons(),
1272 .mousebuttons = get_mouse_buttons() 1284 .mousebuttons = get_mouse_buttons()
1345 1357
1346 tern_node *padbuttons = get_pad_buttons(); 1358 tern_node *padbuttons = get_pad_buttons();
1347 1359
1348 tern_node *mousebuttons = get_mouse_buttons(); 1360 tern_node *mousebuttons = get_mouse_buttons();
1349 1361
1350 tern_node * keys = tern_get_node(tern_find_path(config, "bindings\0keys\0")); 1362 tern_node * keys = tern_find_path(config, "bindings\0keys\0", TVAL_NODE).ptrval;
1351 process_keys(keys, special, padbuttons, mousebuttons, NULL); 1363 process_keys(keys, special, padbuttons, mousebuttons, NULL);
1352 char numstr[] = "00"; 1364 char numstr[] = "00";
1353 tern_node * pads = tern_get_node(tern_find_path(config, "bindings\0pads\0")); 1365 tern_node * pads = tern_find_path(config, "bindings\0pads\0", TVAL_NODE).ptrval;
1354 if (pads) { 1366 if (pads) {
1355 for (int i = 0; i < MAX_JOYSTICKS; i++) 1367 for (int i = 0; i < MAX_JOYSTICKS; i++)
1356 { 1368 {
1357 1369
1358 if (i < 10) { 1370 if (i < 10) {
1364 } 1376 }
1365 1377
1366 } 1378 }
1367 } 1379 }
1368 memset(mice, 0, sizeof(mice)); 1380 memset(mice, 0, sizeof(mice));
1369 tern_node * mice = tern_get_node(tern_find_path(config, "bindings\0mice\0")); 1381 tern_node * mice = tern_find_path(config, "bindings\0mice\0", TVAL_NODE).ptrval;
1370 if (mice) { 1382 if (mice) {
1371 tern_node *buttonmaps[2] = {padbuttons, mousebuttons}; 1383 tern_node *buttonmaps[2] = {padbuttons, mousebuttons};
1372 tern_foreach(mice, process_mouse, buttonmaps); 1384 tern_foreach(mice, process_mouse, buttonmaps);
1373 } 1385 }
1374 tern_node * speed_nodes = tern_get_node(tern_find_path(config, "clocks\0speeds\0")); 1386 tern_node * speed_nodes = tern_find_path(config, "clocks\0speeds\0", TVAL_NODE).ptrval;
1375 speeds = malloc(sizeof(uint32_t)); 1387 speeds = malloc(sizeof(uint32_t));
1376 speeds[0] = 100; 1388 speeds[0] = 100;
1377 process_speeds(speed_nodes, NULL); 1389 process_speeds(speed_nodes, NULL);
1378 for (int i = 0; i < num_speeds; i++) 1390 for (int i = 0; i < num_speeds; i++)
1379 { 1391 {