diff --git a/Makefile.common b/Makefile.common index 17c5e401853d..a550c791462a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2445,6 +2445,7 @@ endif ifeq ($(HAVE_TEST_DRIVERS), 1) DEFINES += -DHAVE_TEST_DRIVERS OBJ += input/drivers_joypad/test_joypad.o + OBJ += input/drivers/test_input.o endif diff --git a/configuration.c b/configuration.c index 2371165abf6d..4f51d4863e04 100644 --- a/configuration.c +++ b/configuration.c @@ -1669,7 +1669,8 @@ static struct config_path_setting *populate_settings_path( #endif #ifdef HAVE_TEST_DRIVERS - SETTING_PATH("test_input_file_joypad", settings->paths.test_input_file_joypad, false, NULL, true); + SETTING_PATH("test_input_file_joypad", settings->paths.test_input_file_joypad, false, NULL, true); + SETTING_PATH("test_input_file_general", settings->paths.test_input_file_general, false, NULL, true); #endif SETTING_ARRAY("log_dir", settings->paths.log_dir, true, NULL, true); diff --git a/configuration.h b/configuration.h index 0d67a825fff5..e65fe8e0f3df 100644 --- a/configuration.h +++ b/configuration.h @@ -577,6 +577,7 @@ typedef struct settings #endif #ifdef HAVE_TEST_DRIVERS char test_input_file_joypad[PATH_MAX_LENGTH]; + char test_input_file_general[PATH_MAX_LENGTH]; #endif char log_dir[PATH_MAX_LENGTH]; char app_icon[PATH_MAX_LENGTH]; diff --git a/cores/libretro-net-retropad/net_retropad_core.c b/cores/libretro-net-retropad/net_retropad_core.c index f86ea8eb8346..8579a782f170 100644 --- a/cores/libretro-net-retropad/net_retropad_core.c +++ b/cores/libretro-net-retropad/net_retropad_core.c @@ -8,7 +8,6 @@ * - Allow changing IP address and port in runtime * - Input recording / Combos * - Enable test input loading from menu - * - Visualization of aux inputs (gyro, accelero, light) */ #include @@ -60,6 +59,8 @@ #define KEYBOARD_OFFSET 1000 #define NETRETROPAD_SCREEN_PAD 0 #define NETRETROPAD_SCREEN_KEYBOARD 1 +#define NETRETROPAD_SCREEN_SENSORS 2 +#define EVENT_RATE 60 struct descriptor { int device; @@ -82,6 +83,12 @@ struct remote_joypad_message { static bool keyboard_state[RETROK_LAST]; static bool keyboard_state_validated[RETROK_LAST]; +static bool tilt_sensor_enabled = false; +static bool gyro_sensor_enabled = false; +static bool lux_sensor_enabled = false; +static float tilt_sensor_values[3] = {0}; +static float gyro_sensor_values[3] = {0}; +static float lux_sensor_value = 0.0f; static int s; static int port; @@ -97,6 +104,8 @@ static retro_audio_sample_batch_t NETRETROPAD_CORE_PREFIX(audio_batch_cb); static retro_environment_t NETRETROPAD_CORE_PREFIX(environ_cb); static retro_input_poll_t NETRETROPAD_CORE_PREFIX(input_poll_cb); static retro_input_state_t NETRETROPAD_CORE_PREFIX(input_state_cb); +static retro_sensor_get_input_t NETRETROPAD_CORE_PREFIX(sensor_get_input_cb); +static retro_set_sensor_state_t NETRETROPAD_CORE_PREFIX(sensor_set_state_cb); static uint16_t *frame_buf; @@ -130,6 +139,8 @@ static struct descriptor analog_button = { .id_max = RETRO_DEVICE_ID_JOYPAD_R3 }; +/* Sensors are not fed to the descriptors. */ + static struct descriptor *descriptors[] = { &joypad, &analog, @@ -137,6 +148,7 @@ static struct descriptor *descriptors[] = { }; static uint16_t analog_item_colors[32]; +static uint16_t sensor_item_colors[70]; static uint16_t combo_def[] = { @@ -359,6 +371,38 @@ static bool input_test_file_read(const char* file_path) /* Test input file handling end */ /********************************/ +static void sensors_init(void) +{ + + struct retro_sensor_interface sensor_interface = {0}; + if (NETRETROPAD_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE, &sensor_interface)) { + + NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_DEBUG,"[Remote RetroPad]: Sensor interface supported, enabling.\n"); + + NETRETROPAD_CORE_PREFIX(sensor_get_input_cb) = sensor_interface.get_sensor_input; + NETRETROPAD_CORE_PREFIX(sensor_set_state_cb) = sensor_interface.set_sensor_state; + + + if (NETRETROPAD_CORE_PREFIX(sensor_set_state_cb) && NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)) { + + if (NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_ACCELEROMETER_ENABLE, EVENT_RATE)) { + tilt_sensor_enabled = true; + NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_DEBUG,"[Remote RetroPad]: Tilt sensor enabled.\n"); + } + + if (NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_GYROSCOPE_ENABLE, EVENT_RATE)) { + gyro_sensor_enabled = true; + NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_DEBUG,"[Remote RetroPad]: Gyro sensor enabled.\n"); + } + + if (NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_ILLUMINANCE_ENABLE, EVENT_RATE)) { + lux_sensor_enabled = true; + NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_DEBUG,"[Remote RetroPad]: Lux sensor enabled.\n"); + } + } + } +} + static void draw_background(void) { if (frame_buf) @@ -367,7 +411,7 @@ static void draw_background(void) /* Body is 255 * 142 within the 320 * 240 frame */ uint16_t *pixel = frame_buf + 49 * 320 + 32; - if (current_screen == NETRETROPAD_SCREEN_PAD) + if (current_screen == NETRETROPAD_SCREEN_PAD || current_screen == NETRETROPAD_SCREEN_SENSORS) for (rle = 0; rle < sizeof(body); ) { uint16_t color = 0; @@ -405,6 +449,8 @@ static void flip_screen(void) if (current_screen == NETRETROPAD_SCREEN_PAD) current_screen = NETRETROPAD_SCREEN_KEYBOARD; else if (current_screen == NETRETROPAD_SCREEN_KEYBOARD) + current_screen = NETRETROPAD_SCREEN_SENSORS; + else if (current_screen == NETRETROPAD_SCREEN_SENSORS) current_screen = NETRETROPAD_SCREEN_PAD; draw_background(); } @@ -445,6 +491,13 @@ void NETRETROPAD_CORE_PREFIX(retro_deinit)(void) free(descriptors[i]->value); descriptors[i]->value = NULL; } + + if (NETRETROPAD_CORE_PREFIX(sensor_set_state_cb) && NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)) + { + NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_ACCELEROMETER_DISABLE, EVENT_RATE); + NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_GYROSCOPE_DISABLE, EVENT_RATE); + NETRETROPAD_CORE_PREFIX(sensor_set_state_cb)(0, RETRO_SENSOR_ILLUMINANCE_DISABLE, EVENT_RATE); + } } unsigned NETRETROPAD_CORE_PREFIX(retro_api_version)(void) @@ -618,7 +671,7 @@ void NETRETROPAD_CORE_PREFIX(retro_set_environment)(retro_environment_t cb) { "net_retropad_ip_octet2", "IP address part 2; 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" }, { "net_retropad_ip_octet3", "IP address part 3; 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" }, { "net_retropad_ip_octet4", "IP address part 4; 0|1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31|32|33|34|35|36|37|38|39|40|41|42|43|44|45|46|47|48|49|50|51|52|53|54|55|56|57|58|59|60|61|62|63|64|65|66|67|68|69|70|71|72|73|74|75|76|77|78|79|80|81|82|83|84|85|86|87|88|89|90|91|92|93|94|95|96|97|98|99|100|101|102|103|104|105|106|107|108|109|110|111|112|113|114|115|116|117|118|119|120|121|122|123|124|125|126|127|128|129|130|131|132|133|134|135|136|137|138|139|140|141|142|143|144|145|146|147|148|149|150|151|152|153|154|155|156|157|158|159|160|161|162|163|164|165|166|167|168|169|170|171|172|173|174|175|176|177|178|179|180|181|182|183|184|185|186|187|188|189|190|191|192|193|194|195|196|197|198|199|200|201|202|203|204|205|206|207|208|209|210|211|212|213|214|215|216|217|218|219|220|221|222|223|224|225|226|227|228|229|230|231|232|233|234|235|236|237|238|239|240|241|242|243|244|245|246|247|248|249|250|251|252|253|254|255" }, - { "net_retropad_screen", "Start screen; Retropad|Keyboard tester" }, + { "net_retropad_screen", "Start screen; Retropad|Keyboard tester|Sensor tester" }, { "net_retropad_hide_analog_mismatch", "Hide mismatching analog button inputs; True|False" }, { NULL, NULL }, }; @@ -637,7 +690,6 @@ void NETRETROPAD_CORE_PREFIX(retro_set_environment)(retro_environment_t cb) NETRETROPAD_CORE_PREFIX(log_cb) = logger.log; NETRETROPAD_CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK, &kcb); - } static void netretropad_check_variables(void) @@ -662,9 +714,10 @@ static void netretropad_check_variables(void) snprintf(server, sizeof(server), "%s.%s.%s.%s", var.value, var2.value, var3.value, var4.value); port = atoi(port_var.value); - if (screen_var.value && - ((current_screen == NETRETROPAD_SCREEN_PAD && strstr(screen_var.value,"Keyboard")) || - (current_screen == NETRETROPAD_SCREEN_KEYBOARD && strstr(screen_var.value,"Retropad")))) + while (screen_var.value && !( + (current_screen == NETRETROPAD_SCREEN_PAD && strstr(screen_var.value,"Retropad")) || + (current_screen == NETRETROPAD_SCREEN_KEYBOARD && strstr(screen_var.value,"Keyboard")) || + (current_screen == NETRETROPAD_SCREEN_SENSORS && strstr(screen_var.value,"Sensor")))) flip_screen(); if (hide_a_var.value && strstr(hide_a_var.value,"True")) hide_analog_mismatch = true; @@ -713,6 +766,9 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void) uint32_t expected_input = 0; uint16_t *pixel = frame_buf + 49 * 320 + 32; + if (!current_frame && current_screen == NETRETROPAD_SCREEN_SENSORS) + sensors_init(); + current_frame++; /* Update input states and send them if needed */ retropad_update_input(); @@ -779,6 +835,84 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void) } } + /* Accelerometer and gyroscope. */ + + if (tilt_sensor_enabled) { + tilt_sensor_values[0] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_ACCELEROMETER_X); + tilt_sensor_values[1] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_ACCELEROMETER_Y); + tilt_sensor_values[2] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_ACCELEROMETER_Z); + } + if (gyro_sensor_enabled) { + gyro_sensor_values[0] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_GYROSCOPE_X); + gyro_sensor_values[1] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_GYROSCOPE_Y); + gyro_sensor_values[2] = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_GYROSCOPE_Z); + } + if (lux_sensor_enabled) + { + lux_sensor_value = NETRETROPAD_CORE_PREFIX(sensor_get_input_cb)(0, RETRO_SENSOR_ILLUMINANCE); + } + + if (tilt_sensor_enabled || gyro_sensor_enabled || lux_sensor_enabled) + { + int j; + bool range_found = false; + + /*NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_DEBUG, + "[Remote Retropad] %1.3f %1.3f %1.3f %1.3f %1.3f %1.3f %1.3f\n", + tilt_sensor_values[0], tilt_sensor_values[1], tilt_sensor_values[2], + gyro_sensor_values[0], gyro_sensor_values[1], gyro_sensor_values[2], + lux_sensor_value);*/ + + memset(sensor_item_colors,0,sizeof(sensor_item_colors)); + for (i = 0; i <= 6; i++) + { + unsigned median_index = 5; + bool range_found = false; + float value; + + /* Accelerometer display range: from 0 to 1g, covering tilt from a horizontal to a vertical position. */ + if (i < 3) + { + value = tilt_sensor_values[i]/9.81; + median_index += (i+1)*10; + } + else if (i < 6) + { + value = gyro_sensor_values[i-3]; + median_index += (i+1)*10; + } + else + { + /* Lux sensor approximate range: 10-10000, mapped using log10 / 4 */ + value = lux_sensor_value > 0 ? (float)log10(lux_sensor_value)/4.0f: 0; + } + if (value > 1.0f) + value = 1.0f; + else if (value < -1.0f) + value = -1.0f; + + for(j = 3 ; j > 0 && !range_found ; j--) + { + float boundary = j*0.25f; + if (value > 0 && value > boundary) + { + sensor_item_colors[median_index+j] = (uint16_t)(32*4*(value-boundary)) << 11; + range_found = true; + } + else if (value < 0 && value < boundary*-1.0f) + { + sensor_item_colors[median_index-j] = (uint16_t)(32*4*(boundary-value)) << 11; + range_found = true; + } + } + if (value != 0.0f && !range_found) + { + sensor_item_colors[median_index] = (uint16_t)(fabsf(32*4*value)) << 11; + } + } + } + + /* Input test section start. */ /* Check for predefined combo inputs. */ @@ -817,8 +951,8 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void) NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_INFO, "[Remote RetroPad]: Proceeding to test step %d at frame %d, next: %d\n", current_test_step,current_frame,next_teststep_frame+INITIAL_FRAMES); - if((input_test_steps[current_test_step].expected_button < KEYBOARD_OFFSET && current_screen == NETRETROPAD_SCREEN_KEYBOARD) || - (input_test_steps[current_test_step].expected_button >= KEYBOARD_OFFSET && current_screen == NETRETROPAD_SCREEN_PAD)) + while((input_test_steps[current_test_step].expected_button < KEYBOARD_OFFSET && current_screen != NETRETROPAD_SCREEN_PAD) || + (input_test_steps[current_test_step].expected_button >= KEYBOARD_OFFSET && current_screen != NETRETROPAD_SCREEN_KEYBOARD)) flip_screen(); } else @@ -977,6 +1111,43 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void) pixel += 65; } } + else if (current_screen == NETRETROPAD_SCREEN_SENSORS) + { + for (rle = 0; rle < ARRAY_SIZE(sensor_buttons); ) + { + unsigned runs; + char paint = 0; + + for (runs = sensor_buttons[rle++]; runs > 0; runs--) + { + if (paint) + { + unsigned count; + uint16_t color; + + /* Same color scheme as for retropad buttons */ + if (sensor_item_colors[sensor_buttons[rle]]) + { + color = sensor_item_colors[sensor_buttons[rle]]; + } + else + { + color = 0xffff; + } + rle++; + + for (count = sensor_buttons[rle++]; count > 0; count--) + *pixel++ = color; + } + else + pixel += sensor_buttons[rle++]; + + paint = !paint; + } + + pixel += 65; + } + } NETRETROPAD_CORE_PREFIX(video_cb)(frame_buf, 320, 240, 640); retro_sleep(4); diff --git a/cores/libretro-net-retropad/remotepad.h b/cores/libretro-net-retropad/remotepad.h index 963a86074305..0d10d0070586 100644 --- a/cores/libretro-net-retropad/remotepad.h +++ b/cores/libretro-net-retropad/remotepad.h @@ -592,4 +592,150 @@ static uint16_t keyboard_buttons[] = /* 140 */ 1, 255, /* 141 */ 1, 255, }; + +static uint16_t sensor_buttons[] = +{ + /* 0 */ 1, 255, + /* 1 */ 7, 117, 14, 5, 3, 15, 5, 3, 16, 5, 117, + /* 2 */ 7, 117, 14, 5, 2, 15, 7, 2, 16, 5, 117, + /* 3 */ 11, 111, 13, 4, 1, 14, 6, 1, 15, 9, 1, 16, 6, 1, 17, 4, 111, + /* 4 */ 11, 111, 13, 4, 1, 14, 5, 2, 15, 9, 2, 16, 5, 1, 17, 4, 111, + /* 5 */ 15, 105, 12, 4, 1, 13, 5, 1, 14, 5, 2, 15, 9, 2, 16, 5, 1, 17, 5, 1, 18, 4, 105, + /* 6 */ 15, 105, 12, 4, 1, 13, 4, 2, 14, 5, 2, 15, 9, 2, 16, 5, 2, 17, 4, 1, 18, 4, 105, + /* 7 */ 15, 104, 12, 5, 1, 13, 4, 2, 14, 6, 1, 15, 9, 1, 16, 6, 2, 17, 4, 1, 18, 5, 104, + /* 8 */ 15, 104, 12, 4, 2, 13, 4, 3, 14, 5, 2, 15, 7, 2, 16, 5, 3, 17, 4, 2, 18, 4, 104, + /* 9 */ 15, 104, 12, 4, 2, 13, 5, 2, 14, 5, 3, 15, 5, 3, 16, 5, 2, 17, 5, 2, 18, 4, 104, + /* 10 */ 9, 104, 12, 4, 3, 13, 4, 25, 17, 4, 3, 18, 4, 104, + /* 11 */ 9, 104, 12, 5, 2, 13, 4, 25, 17, 4, 2, 18, 5, 104, + /* 12 */ 5, 105, 12, 4, 37, 18, 4, 105, + /* 13 */ 5, 105, 12, 4, 37, 18, 4, 105, + /* 14 */ 1, 255, + /* 15 */ 1, 255, + /* 16 */ 1, 255, + /* 17 */ 1, 255, + /* 18 */ 1, 255, + /* 19 */ 1, 255, + /* 20 */ 1, 255, + /* 21 */ 1, 255, + /* 22 */ 1, 255, + /* 23 */ 1, 255, + /* 24 */ 1, 255, + /* 25 */ 1, 255, + /* 26 */ 1, 255, + /* 27 */ 1, 255, + /* 28 */ 1, 255, + /* 29 */ 1, 255, + /* 30 */ 1, 255, + /* 31 */ 1, 255, + /* 32 */ 1, 255, + /* 33 */ 1, 255, + /* 34 */ 1, 255, + /* 35 */ 1, 255, + /* 36 */ 1, 255, + /* 37 */ 1, 255, + /* 38 */ 1, 255, + /* 39 */ 1, 255, + /* 40 */ 7, 23, 28, 5, 97, 48, 5, 16, 62, 3, 106, + /* 41 */ 7, 21, 28, 9, 93, 48, 9, 14, 62, 4, 105, + /* 42 */ 7, 20, 28, 11, 92, 48, 9, 14, 62, 5, 104, + /* 43 */ 7, 19, 28, 13, 91, 48, 9, 14, 62, 5, 104, + /* 44 */ 11, 19, 28, 4, 5, 28, 4, 91, 48, 3, 3, 48, 3, 14, 62, 5, 104, + /* 45 */ 3, 146, 62, 5, 104, + /* 46 */ 7, 23, 27, 5, 97, 47, 5, 10, 63, 3, 112, + /* 47 */ 7, 21, 27, 9, 93, 47, 9, 8, 63, 4, 111, + /* 48 */ 7, 20, 27, 11, 92, 47, 9, 8, 63, 5, 110, + /* 49 */ 9, 20, 27, 11, 92, 47, 9, 8, 63, 5, 80, 8, 5, 25, + /* 50 */ 13, 20, 27, 4, 3, 27, 4, 92, 47, 3, 3, 47, 3, 8, 63, 5, 78, 8, 9, 23, + /* 51 */ 5, 140, 63, 5, 77, 8, 11, 22, + /* 52 */ 9, 23, 26, 5, 97, 46, 5, 4, 64, 3, 84, 8, 13, 21, + /* 53 */ 11, 21, 26, 9, 93, 46, 9, 2, 64, 4, 83, 8, 4, 5, 8, 4, 21, + /* 54 */ 7, 21, 26, 9, 93, 46, 9, 2, 64, 5, 116, + /* 55 */ 11, 21, 26, 9, 93, 46, 9, 2, 64, 5, 81, 7, 4, 7, 7, 4, 20, + /* 56 */ 11, 21, 26, 9, 93, 46, 9, 2, 64, 5, 80, 7, 4, 9, 7, 4, 19, + /* 57 */ 13, 21, 26, 3, 3, 26, 3, 93, 46, 3, 3, 46, 3, 87, 7, 4, 9, 7, 4, 19, + /* 58 */ 5, 219, 7, 4, 9, 7, 4, 19, + /* 59 */ 23, 23, 25, 5, 77, 52, 4, 2, 53, 4, 2, 54, 5, 3, 45, 3, 0, 65, 2, 3, 56, 5, 2, 57, 4, 2, 58, 4, 70, 7, 4, 7, 7, 4, 20, + /* 60 */ 19, 22, 25, 7, 76, 52, 4, 2, 53, 4, 2, 54, 5, 2, 45, 4, 0, 65, 3, 2, 56, 5, 2, 57, 4, 2, 58, 4, 105, + /* 61 */ 27, 21, 25, 9, 74, 52, 5, 1, 53, 5, 1, 54, 6, 1, 55, 2, 0, 45, 3, 0, 65, 3, 0, 55, 1, 1, 56, 6, 1, 57, 5, 1, 58, 5, 70, 6, 4, 5, 6, 4, 21, + /* 62 */ 27, 21, 25, 9, 74, 52, 4, 2, 53, 4, 2, 54, 5, 2, 55, 4, 0, 45, 1, 0, 65, 1, 0, 55, 3, 2, 56, 5, 2, 57, 4, 2, 58, 4, 70, 6, 4, 5, 6, 4, 21, + /* 63 */ 21, 21, 25, 9, 74, 52, 4, 2, 53, 4, 2, 54, 5, 2, 55, 9, 2, 56, 5, 2, 57, 4, 2, 58, 4, 71, 6, 4, 3, 6, 4, 22, + /* 64 */ 25, 21, 25, 9, 74, 52, 4, 2, 53, 4, 2, 54, 5, 2, 55, 4, 0, 65, 1, 0, 45, 1, 0, 55, 3, 2, 56, 5, 2, 57, 4, 2, 58, 4, 71, 6, 11, 22, + /* 65 */ 25, 21, 25, 9, 74, 52, 5, 1, 53, 5, 1, 54, 6, 1, 55, 3, 0, 65, 2, 0, 45, 3, 0, 55, 1, 1, 56, 6, 1, 57, 5, 1, 58, 5, 71, 6, 11, 22, + /* 66 */ 23, 22, 25, 7, 76, 52, 4, 2, 53, 4, 2, 54, 5, 2, 55, 1, 0, 65, 3, 0, 45, 3, 2, 56, 5, 2, 57, 4, 2, 58, 4, 73, 6, 9, 23, + /* 67 */ 19, 23, 25, 5, 77, 52, 4, 2, 53, 4, 2, 54, 5, 3, 65, 3, 0, 45, 2, 3, 56, 5, 2, 57, 4, 2, 58, 4, 105, + /* 68 */ 3, 225, 5, 5, 25, + /* 69 */ 11, 21, 24, 3, 3, 24, 3, 93, 44, 3, 3, 44, 3, 92, 5, 7, 24, + /* 70 */ 9, 21, 24, 9, 86, 66, 5, 2, 44, 9, 91, 5, 9, 23, + /* 71 */ 9, 21, 24, 9, 86, 66, 5, 2, 44, 9, 91, 5, 9, 23, + /* 72 */ 9, 21, 24, 9, 86, 66, 5, 2, 44, 9, 91, 5, 9, 23, + /* 73 */ 9, 21, 24, 9, 87, 66, 4, 2, 44, 9, 91, 5, 9, 23, + /* 74 */ 9, 23, 24, 5, 90, 66, 3, 4, 44, 5, 93, 5, 9, 23, + /* 75 */ 3, 224, 5, 7, 24, + /* 76 */ 13, 22, 23, 2, 3, 23, 2, 81, 67, 5, 8, 43, 3, 3, 43, 3, 93, 5, 5, 25, + /* 77 */ 7, 22, 23, 7, 81, 67, 5, 8, 43, 9, 123, + /* 78 */ 7, 22, 23, 7, 81, 67, 5, 8, 43, 9, 123, + /* 79 */ 7, 22, 23, 7, 82, 67, 4, 8, 43, 9, 123, + /* 80 */ 7, 23, 23, 5, 84, 67, 3, 10, 43, 5, 125, + /* 81 */ 1, 255, + /* 82 */ 11, 23, 22, 1, 3, 22, 1, 76, 68, 5, 14, 42, 3, 3, 42, 3, 123, + /* 83 */ 7, 23, 22, 5, 76, 68, 5, 14, 42, 9, 123, + /* 84 */ 7, 23, 22, 5, 76, 68, 5, 14, 42, 9, 123, + /* 85 */ 7, 23, 22, 5, 77, 68, 4, 14, 42, 9, 123, + /* 86 */ 7, 24, 22, 3, 79, 68, 3, 16, 42, 5, 125, + /* 87 */ 1, 255, + /* 88 */ 1, 255, + /* 89 */ 1, 255, + /* 90 */ 1, 255, + /* 91 */ 1, 255, + /* 92 */ 1, 255, + /* 93 */ 1, 255, + /* 94 */ 1, 255, + /* 95 */ 1, 255, + /* 96 */ 1, 255, + /* 97 */ 1, 255, + /* 98 */ 1, 255, + /* 99 */ 1, 255, + /* 100 */ 1, 255, + /* 101 */ 1, 255, + /* 102 */ 1, 255, + /* 103 */ 1, 255, + /* 104 */ 1, 255, + /* 105 */ 1, 255, + /* 106 */ 1, 255, + /* 107 */ 1, 255, + /* 108 */ 1, 255, + /* 109 */ 1, 255, + /* 110 */ 1, 255, + /* 111 */ 1, 255, + /* 112 */ 1, 255, + /* 113 */ 1, 255, + /* 114 */ 1, 255, + /* 115 */ 1, 255, + /* 116 */ 1, 255, + /* 117 */ 1, 255, + /* 118 */ 1, 255, + /* 119 */ 1, 255, + /* 120 */ 1, 255, + /* 121 */ 1, 255, + /* 122 */ 1, 255, + /* 123 */ 1, 255, + /* 124 */ 1, 255, + /* 125 */ 1, 255, + /* 126 */ 1, 255, + /* 127 */ 1, 255, + /* 128 */ 1, 255, + /* 129 */ 1, 255, + /* 130 */ 1, 255, + /* 131 */ 1, 255, + /* 132 */ 1, 255, + /* 133 */ 1, 255, + /* 134 */ 1, 255, + /* 135 */ 1, 255, + /* 136 */ 1, 255, + /* 137 */ 1, 255, + /* 138 */ 1, 255, + /* 139 */ 1, 255, + /* 140 */ 1, 255, + /* 141 */ 1, 255, +}; #endif /* REMOTEPAD_H */ diff --git a/griffin/griffin.c b/griffin/griffin.c index e1bb908f5888..d1986ea63801 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -733,6 +733,7 @@ INPUT #ifdef HAVE_TEST_DRIVERS #include "../input/drivers_joypad/test_joypad.c" +#include "../input/drivers/test_input.c" #endif /*============================================================ diff --git a/input/drivers/test_input.c b/input/drivers/test_input.c new file mode 100644 index 000000000000..432e4b7ab05b --- /dev/null +++ b/input/drivers/test_input.c @@ -0,0 +1,557 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2014 - Hans-Kristian Arntzen + * Copyright (C) 2011-2017 - Daniel De Matteis + * Copyright (C) 2016-2019 - Brad Parker + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "../input_driver.h" +#include "../input_keymaps.h" +#include "../../verbosity.h" +#include "../../gfx/video_driver.h" + +#define MAX_TEST_STEPS 200 + +#define INPUT_TEST_COMMAND_PRESS_KEY 1 +#define INPUT_TEST_COMMAND_RELEASE_KEY 2 +#define INPUT_TEST_COMMAND_SET_SENSOR_ACC_X 10 +#define INPUT_TEST_COMMAND_SET_SENSOR_ACC_Y 11 +#define INPUT_TEST_COMMAND_SET_SENSOR_ACC_Z 12 +#define INPUT_TEST_COMMAND_SET_SENSOR_GYR_X 13 +#define INPUT_TEST_COMMAND_SET_SENSOR_GYR_Y 14 +#define INPUT_TEST_COMMAND_SET_SENSOR_GYR_Z 15 +#define INPUT_TEST_COMMAND_SET_SENSOR_LUX 16 + +/* TODO/FIXME - static globals */ +static uint16_t test_key_state[DEFAULT_MAX_PADS+1][RETROK_LAST]; + +typedef struct +{ + float x; + float y; + float z; +} sensor_t; + +typedef struct test_input +{ + sensor_t accelerometer_state; /* float alignment */ + sensor_t gyroscope_state; /* float alignment */ + float lux_sensor_state; +} test_input_t; + +static test_input_t test_input_values; + +typedef struct +{ + unsigned frame; + unsigned action; + unsigned param_num; + char param_str[255]; + bool handled; +} input_test_step_t; + +static input_test_step_t input_test_steps[MAX_TEST_STEPS]; + +static unsigned current_frame = 0; +static unsigned next_teststep_frame = 0; +static unsigned current_test_step = 0; +static unsigned last_test_step = MAX_TEST_STEPS + 1; +static uint32_t input_state_validated = 0; +static uint32_t combo_state_validated = 0; +static bool dump_state_blocked = false; + +/************************************/ +/* JSON Helpers for test input file */ +/************************************/ + +typedef struct +{ + unsigned *current_entry_uint_val; + char **current_entry_str_val; + unsigned frame; + unsigned action; + unsigned param_num; + char *param_str; +} KTifJSONContext; + +static bool KTifJSONObjectEndHandler(void* context) +{ + KTifJSONContext *pCtx = (KTifJSONContext*)context; + + /* Too long input is handled elsewhere, it should not lead to parse error */ + if (current_test_step >= MAX_TEST_STEPS) + return true; + + /* Copy values read from JSON file + fill defaults */ + if (pCtx->frame == 0xffff) + input_test_steps[current_test_step].frame = input_test_steps[current_test_step-1].frame + 60; + else + input_test_steps[current_test_step].frame = pCtx->frame; + + input_test_steps[current_test_step].action = pCtx->action; + input_test_steps[current_test_step].param_num = pCtx->param_num; + input_test_steps[current_test_step].handled = false; + + if (!string_is_empty(pCtx->param_str)) + strlcpy( + input_test_steps[current_test_step].param_str, pCtx->param_str, + sizeof(input_test_steps[current_test_step].param_str)); + else + input_test_steps[current_test_step].param_str[0] = '\0'; + + current_test_step++; + last_test_step = current_test_step; + pCtx->frame = 0xffff; + return true; +} + +static bool KTifJSONObjectMemberHandler(void* context, const char *pValue, size_t length) +{ + KTifJSONContext *pCtx = (KTifJSONContext*)context; + + /* something went wrong */ + if (pCtx->current_entry_str_val) + return false; + + if (length) + { + if (string_is_equal(pValue, "frame")) + pCtx->current_entry_uint_val = &pCtx->frame; + else if (string_is_equal(pValue, "action")) + pCtx->current_entry_uint_val = &pCtx->action; + else if (string_is_equal(pValue, "param_num")) + pCtx->current_entry_uint_val = &pCtx->param_num; + else if (string_is_equal(pValue, "param_str")) + pCtx->current_entry_str_val = &pCtx->param_str; + /* ignore unknown members */ + } + + return true; +} + +static bool KTifJSONNumberHandler(void* context, const char *pValue, size_t length) +{ + KTifJSONContext *pCtx = (KTifJSONContext*)context; + + if (pCtx->current_entry_uint_val && length && !string_is_empty(pValue)) + *pCtx->current_entry_uint_val = string_to_unsigned(pValue); + /* ignore unknown members */ + + pCtx->current_entry_uint_val = NULL; + + return true; +} + +static bool KTifJSONStringHandler(void* context, const char *pValue, size_t length) +{ + KTifJSONContext *pCtx = (KTifJSONContext*)context; + + if (pCtx->current_entry_str_val && length && !string_is_empty(pValue)) + { + if (*pCtx->current_entry_str_val) + free(*pCtx->current_entry_str_val); + + *pCtx->current_entry_str_val = strdup(pValue); + } + /* ignore unknown members */ + + pCtx->current_entry_str_val = NULL; + + return true; +} + +/* Parses test input file referenced by file_path. + * Does nothing if test input file does not exist. */ +static bool input_test_file_read(const char* file_path) +{ + bool success = false; + KTifJSONContext context = {0}; + RFILE *file = NULL; + rjson_t* parser; + + /* Sanity check */ + if ( string_is_empty(file_path) + || !path_is_valid(file_path) + ) + { + RARCH_DBG("[Test input driver]: No test input file supplied.\n"); + return false; + } + + /* Attempt to open test input file */ + file = filestream_open( + file_path, + RETRO_VFS_FILE_ACCESS_READ, + RETRO_VFS_FILE_ACCESS_HINT_NONE); + + if (!file) + { + RARCH_ERR("[Test input driver]: Failed to open test input file: \"%s\".\n", + file_path); + return false; + } + + /* Initialise JSON parser */ + if (!(parser = rjson_open_rfile(file))) + { + RARCH_ERR("[Test input driver]: Failed to create JSON parser.\n"); + goto end; + } + + /* Configure parser */ + rjson_set_options(parser, RJSON_OPTION_ALLOW_UTF8BOM); + + /* Read file */ + if (rjson_parse(parser, &context, + KTifJSONObjectMemberHandler, + KTifJSONStringHandler, + KTifJSONNumberHandler, + NULL, KTifJSONObjectEndHandler, NULL, NULL, /* object/array handlers */ + NULL, NULL) /* unused boolean/null handlers */ + != RJSON_DONE) + { + if (rjson_get_source_context_len(parser)) + { + RARCH_ERR( + "[Test input driver]: Error parsing chunk of test input file: %s\n---snip---\n%.*s\n---snip---\n", + file_path, + rjson_get_source_context_len(parser), + rjson_get_source_context_buf(parser)); + } + RARCH_WARN( + "[Test input driver]: Error parsing test input file: %s\n", + file_path); + RARCH_ERR( + "[Test input driver]: Error: Invalid JSON at line %d, column %d - %s.\n", + (int)rjson_get_source_line(parser), + (int)rjson_get_source_column(parser), + (*rjson_get_error(parser) ? rjson_get_error(parser) : "format error")); + } + + /* Free parser */ + rjson_free(parser); + + success = true; +end: + /* Clean up leftover strings */ + if (context.param_str) + free(context.param_str); + + /* Close log file */ + filestream_close(file); + + if (last_test_step >= MAX_TEST_STEPS) + { + RARCH_WARN("[Test input driver]: too long test input json, maximum size: %d\n",MAX_TEST_STEPS); + } + for (current_test_step = 0; current_test_step < last_test_step; current_test_step++) + { + RARCH_DBG( + "[Test input driver]: test step %02d read from file: frame %d, action %x, num %x, str %s\n", + current_test_step, + input_test_steps[current_test_step].frame, + input_test_steps[current_test_step].action, + input_test_steps[current_test_step].param_num, + input_test_steps[current_test_step].param_str); + } + current_test_step = 0; + return success; +} + +/********************************/ +/* Test input file handling end */ +/********************************/ + + +/*uint16_t *test_keyboard_state_get(unsigned port) +{ + return test_key_state[port]; +}*/ + +static void test_keyboard_free(void) +{ + unsigned i, j; + + for (i = 0; i < DEFAULT_MAX_PADS; i++) + for (j = 0; j < RETROK_LAST; j++) + test_key_state[i][j] = 0; +} + +static int16_t test_input_state( + void *data, + const input_device_driver_t *joypad, + const input_device_driver_t *sec_joypad, + rarch_joypad_info_t *joypad_info, + const retro_keybind_set *binds, + bool keyboard_mapping_blocked, + unsigned port, + unsigned device, + unsigned idx, + unsigned id) +{ + if (port <= 0) + { + switch (device) + { +/* TODO: something clear here */ + case RETRO_DEVICE_JOYPAD: + if (id == RETRO_DEVICE_ID_JOYPAD_MASK) + { + unsigned i; + int16_t ret = 0; + + if (!keyboard_mapping_blocked && id < RARCH_BIND_LIST_END) + { + for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++) + { + if (binds[port][i].valid) + { + if ( (binds[port][i].key && binds[port][i].key < RETROK_LAST) + && test_key_state[DEFAULT_MAX_PADS][binds[port][id].key]) + ret |= (1 << i); + } + } + } + return ret; + } + + if (id < RARCH_BIND_LIST_END) + { + if (binds[port][id].valid) + { + if ( (binds[port][id].key && binds[port][id].key < RETROK_LAST) + && test_key_state[DEFAULT_MAX_PADS][binds[port][id].key] + && (id == RARCH_GAME_FOCUS_TOGGLE || !keyboard_mapping_blocked) + ) + return 1; + + } + } + break; + + case RETRO_DEVICE_KEYBOARD: + if (id && id < RETROK_LAST) + return (test_key_state[DEFAULT_MAX_PADS][id]); + break; + } + } + + return 0; +} + +static void test_input_free_input(void *data) +{ + test_keyboard_free(); +} + +static void* test_input_init(const char *joypad_driver) +{ + settings_t *settings = config_get_ptr(); + unsigned i; + + RARCH_DBG("[Test input driver]: start\n"); + + input_test_file_read(settings->paths.test_input_file_general); + if (last_test_step > MAX_TEST_STEPS) + last_test_step = 0; + + /* No need for keyboard mapping look-up table */ + /* input_keymaps_init_keyboard_lut(rarch_key_map_test);*/ + return (void*)-1; +} + +static float test_input_unsigned_to_float_acc(unsigned i) +{ + if (i>200) + return 0.0f; + return ((signed int)(100-i))/100.0f*9.81f; +} + +static float test_input_unsigned_to_float_gyro(unsigned i) +{ + if (i>200) + return 0.0f; + return ((signed int)(100-i))/100.0f; +} + +static float test_input_unsigned_to_float_lux(unsigned i) +{ + if (i>200 || i<100) + return 0.0f; + return (float)pow(10,(((i-100)/100.0f)*4)); +} + + +static void test_input_poll(void *data) +{ + video_driver_state_t *video_st = video_state_get_ptr(); + uint64_t curr_frame = video_st->frame_count; + unsigned i; + + for (i=0; i input_test_steps[i].frame) + { + if( input_test_steps[i].action == INPUT_TEST_COMMAND_PRESS_KEY) + { + if(input_test_steps[i].param_num < RETROK_LAST) + { + test_key_state[DEFAULT_MAX_PADS][input_test_steps[i].param_num] = 1; + input_keyboard_event(true, input_test_steps[i].param_num, 0, 0, RETRO_DEVICE_KEYBOARD); + } + input_test_steps[i].handled = true; + RARCH_DBG( + "[Test input driver]: Pressing keyboard button %d at frame %d\n", + input_test_steps[i].param_num, curr_frame); + } + else if( input_test_steps[i].action == INPUT_TEST_COMMAND_RELEASE_KEY) + { + if(input_test_steps[i].param_num < RETROK_LAST) + { + test_key_state[DEFAULT_MAX_PADS][input_test_steps[i].param_num] = 0; + input_keyboard_event(false, input_test_steps[i].param_num, 0, 0, RETRO_DEVICE_KEYBOARD); + } + input_test_steps[i].handled = true; + RARCH_DBG( + "[Test input driver]: Releasing keyboard button %d at frame %d\n", + input_test_steps[i].param_num, curr_frame); + } + else if(input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_ACC_X || + input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_ACC_Y || + input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_ACC_Z) + { + float setval = test_input_unsigned_to_float_acc(input_test_steps[i].param_num); + switch (input_test_steps[i].action) + { + case INPUT_TEST_COMMAND_SET_SENSOR_ACC_X: + test_input_values.accelerometer_state.x = setval; + break; + case INPUT_TEST_COMMAND_SET_SENSOR_ACC_Y: + test_input_values.accelerometer_state.y = setval; + break; + case INPUT_TEST_COMMAND_SET_SENSOR_ACC_Z: + test_input_values.accelerometer_state.z = setval; + break; + } + input_test_steps[i].handled = true; + RARCH_DBG( + "[Test input driver]: Setting accelerometer axis %d to %f at frame %d\n", + input_test_steps[i].action - INPUT_TEST_COMMAND_SET_SENSOR_ACC_X, setval, curr_frame); + } + else if(input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_GYR_X || + input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_GYR_Y || + input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_GYR_Z) + { + float setval = test_input_unsigned_to_float_gyro(input_test_steps[i].param_num); + switch (input_test_steps[i].action) + { + case INPUT_TEST_COMMAND_SET_SENSOR_GYR_X: + test_input_values.gyroscope_state.x = setval; + break; + case INPUT_TEST_COMMAND_SET_SENSOR_GYR_Y: + test_input_values.gyroscope_state.y = setval; + break; + case INPUT_TEST_COMMAND_SET_SENSOR_GYR_Z: + test_input_values.gyroscope_state.z = setval; + break; + } + input_test_steps[i].handled = true; + RARCH_DBG( + "[Test input driver]: Setting gyroscope axis %d to %f at frame %d\n", + input_test_steps[i].action - INPUT_TEST_COMMAND_SET_SENSOR_GYR_X, setval, curr_frame); + } + else if(input_test_steps[i].action == INPUT_TEST_COMMAND_SET_SENSOR_LUX) + { + float setval = test_input_unsigned_to_float_lux(input_test_steps[i].param_num); + test_input_values.lux_sensor_state = setval; + input_test_steps[i].handled = true; + RARCH_DBG( + "[Test input driver]: Setting lux sensor to %f at frame %d\n", + setval, curr_frame); + } + else + { + input_test_steps[i].handled = true; + RARCH_WARN( + "[Test input driver]: Unrecognized action %d in step %d, skipping\n", + input_test_steps[i].action,i); + } + } + } +} + +static bool test_input_set_sensor_state(void *data, unsigned port, + enum retro_sensor_action action, unsigned event_rate) +{ + RARCH_DBG("[Test input driver]: Setting sensor action %d rate %d\n",action, event_rate); + return true; +} + +static float test_input_get_sensor_input(void *data, + unsigned port, unsigned id) +{ + switch (id) + { + case RETRO_SENSOR_ACCELEROMETER_X: + return test_input_values.accelerometer_state.x; + case RETRO_SENSOR_ACCELEROMETER_Y: + return test_input_values.accelerometer_state.y; + case RETRO_SENSOR_ACCELEROMETER_Z: + return test_input_values.accelerometer_state.z; + case RETRO_SENSOR_GYROSCOPE_X: + return test_input_values.gyroscope_state.x; + case RETRO_SENSOR_GYROSCOPE_Y: + return test_input_values.gyroscope_state.y; + case RETRO_SENSOR_GYROSCOPE_Z: + return test_input_values.gyroscope_state.z; + case RETRO_SENSOR_ILLUMINANCE: + return test_input_values.lux_sensor_state; + } + + return 0.0f; +} + +static uint64_t test_input_get_capabilities(void *data) +{ + return + (1 << RETRO_DEVICE_JOYPAD) + | (1 << RETRO_DEVICE_ANALOG) + | (1 << RETRO_DEVICE_KEYBOARD) +/* | (1 << RETRO_DEVICE_MOUSE) + | (1 << RETRO_DEVICE_POINTER) + | (1 << RETRO_DEVICE_LIGHTGUN)*/; +} + +input_driver_t input_test = { + test_input_init, + test_input_poll, + test_input_state, + test_input_free_input, + test_input_set_sensor_state, + test_input_get_sensor_input, + test_input_get_capabilities, + "test", + NULL, /* grab_mouse */ + NULL, + NULL +}; diff --git a/input/drivers_joypad/test_joypad.c b/input/drivers_joypad/test_joypad.c index ac9a87a9f4c4..9c7dcf1fcfa1 100644 --- a/input/drivers_joypad/test_joypad.c +++ b/input/drivers_joypad/test_joypad.c @@ -194,7 +194,7 @@ static bool input_test_file_read(const char* file_path) || !path_is_valid(file_path) ) { - RARCH_DBG("[Test input driver]: No test input file supplied.\n"); + RARCH_DBG("[Test joypad driver]: No test input file supplied.\n"); return false; } @@ -206,7 +206,7 @@ static bool input_test_file_read(const char* file_path) if (!file) { - RARCH_ERR("[Test input driver]: Failed to open test input file: \"%s\".\n", + RARCH_ERR("[Test joypad driver]: Failed to open test input file: \"%s\".\n", file_path); return false; } @@ -214,7 +214,7 @@ static bool input_test_file_read(const char* file_path) /* Initialise JSON parser */ if (!(parser = rjson_open_rfile(file))) { - RARCH_ERR("[Test input driver]: Failed to create JSON parser.\n"); + RARCH_ERR("[Test joypad driver]: Failed to create JSON parser.\n"); goto end; } @@ -233,16 +233,16 @@ static bool input_test_file_read(const char* file_path) if (rjson_get_source_context_len(parser)) { RARCH_ERR( - "[Test input driver]: Error parsing chunk of test input file: %s\n---snip---\n%.*s\n---snip---\n", + "[Test joypad driver]: Error parsing chunk of test input file: %s\n---snip---\n%.*s\n---snip---\n", file_path, rjson_get_source_context_len(parser), rjson_get_source_context_buf(parser)); } RARCH_WARN( - "[Test input driver]: Error parsing test input file: %s\n", + "[Test joypad driver]: Error parsing test input file: %s\n", file_path); RARCH_ERR( - "[Test input driver]: Error: Invalid JSON at line %d, column %d - %s.\n", + "[Test joypad driver]: Error: Invalid JSON at line %d, column %d - %s.\n", (int)rjson_get_source_line(parser), (int)rjson_get_source_column(parser), (*rjson_get_error(parser) ? rjson_get_error(parser) : "format error")); @@ -262,12 +262,12 @@ static bool input_test_file_read(const char* file_path) if (last_test_step >= MAX_TEST_STEPS) { - RARCH_WARN("[Test input driver]: too long test input json, maximum size: %d\n",MAX_TEST_STEPS); + RARCH_WARN("[Test joypad driver]: too long test input json, maximum size: %d\n",MAX_TEST_STEPS); } for (current_test_step = 0; current_test_step < last_test_step; current_test_step++) { RARCH_DBG( - "[Test input driver]: test step %02d read from file: frame %d, action %x, num %x, str %s\n", + "[Test joypad driver]: test step %02d read from file: frame %d, action %x, num %x, str %s\n", current_test_step, input_test_steps[current_test_step].frame, input_test_steps[current_test_step].action, @@ -433,7 +433,7 @@ static void test_joypad_poll(void) test_joypads[targetpad].button_state |= input_test_steps[i].param_num; input_test_steps[i].handled = true; RARCH_DBG( - "[Test input driver]: Pressing device %d buttons %x, new state %x.\n", + "[Test joypad driver]: Pressing device %d buttons %x, new state %x.\n", targetpad,input_test_steps[i].param_num,test_joypads[targetpad].button_state); } else if( input_test_steps[i].action >= JOYPAD_TEST_COMMAND_BUTTON_RELEASE_FIRST && @@ -443,7 +443,7 @@ static void test_joypad_poll(void) test_joypads[targetpad].button_state &= ~input_test_steps[i].param_num; input_test_steps[i].handled = true; RARCH_DBG( - "[Test input driver]: Releasing device %d buttons %x, new state %x.\n", + "[Test joypad driver]: Releasing device %d buttons %x, new state %x.\n", targetpad,input_test_steps[i].param_num,test_joypads[targetpad].button_state); } else if( input_test_steps[i].action >= JOYPAD_TEST_COMMAND_BUTTON_AXIS_FIRST && @@ -457,19 +457,19 @@ static void test_joypad_poll(void) test_joypads[targetpad].axis_state[targetaxis] = (int16_t) input_test_steps[i].param_num; else RARCH_WARN( - "[Test input driver]: Decoded axis outside target range: action %d pad %d axis %d.\n", + "[Test joypad driver]: Decoded axis outside target range: action %d pad %d axis %d.\n", input_test_steps[i].action, targetpad, targetaxis); input_test_steps[i].handled = true; RARCH_DBG( - "[Test input driver]: Setting axis device %d axis %d value %d.\n", + "[Test joypad driver]: Setting axis device %d axis %d value %d.\n", targetpad, targetaxis, (int16_t)input_test_steps[i].param_num); } else { input_test_steps[i].handled = true; RARCH_WARN( - "[Test input driver]: Unrecognized action %d in step %d, skipping\n", + "[Test joypad driver]: Unrecognized action %d in step %d, skipping\n", input_test_steps[i].action,i); } diff --git a/input/input_driver.c b/input/input_driver.c index 33fafc37d728..76a2c278cd3f 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -363,6 +363,9 @@ input_driver_t *input_drivers[] = { #endif #ifdef DJGPP &input_dos, +#endif +#ifdef HAVE_TEST_DRIVERS + &input_test, #endif &input_null, NULL, @@ -4418,11 +4421,24 @@ bool video_driver_init_input( void *new_data = NULL; input_driver_t **input = &input_driver_st.current_driver; if (*input) +#if HAVE_TEST_DRIVERS + if (strcmp(settings->arrays.input_driver,"test") != 0) + /* Test driver not in use, keep selected driver */ + return true; + else if (string_is_empty(settings->paths.test_input_file_general)) + { + RARCH_LOG("[Input]: Test input driver selected, but no input file provided - falling back.\n"); + return true; + } + else + RARCH_LOG("[Video]: Graphics driver initialized an input driver, but ignoring it as test input driver is in use.\n"); +#else return true; - - /* Video driver didn't provide an input driver, - * so we use configured one. */ - RARCH_LOG("[Video]: Graphics driver did not initialize an input driver." +#endif + else + /* Video driver didn't provide an input driver, + * so we use configured one. */ + RARCH_LOG("[Video]: Graphics driver did not initialize an input driver." " Attempting to pick a suitable driver.\n"); if (tmp) diff --git a/input/input_driver.h b/input/input_driver.h index 3db9c79ebe65..50eb5d4ee692 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -1103,6 +1103,7 @@ extern input_driver_t input_rwebinput; extern input_driver_t input_dos; extern input_driver_t input_winraw; extern input_driver_t input_wayland; +extern input_driver_t input_test; extern input_device_driver_t dinput_joypad; extern input_device_driver_t linuxraw_joypad; diff --git a/tests-other/all_binds_empty.cfg b/tests-other/all_binds_empty.cfg index 82d867584fed..b672d927a123 100644 --- a/tests-other/all_binds_empty.cfg +++ b/tests-other/all_binds_empty.cfg @@ -5,6 +5,7 @@ input_exit_emulator = "escape" input_max_users = "10" +input_fps_toggle = "f3" input_ai_service = "nul" input_ai_service_axis = "nul" @@ -62,7 +63,7 @@ input_enable_hotkey_mbtn = "nul" input_exit_emulator_axis = "nul" input_exit_emulator_btn = "nul" input_exit_emulator_mbtn = "nul" -input_fps_toggle = "nul" +# input_fps_toggle = "nul" input_fps_toggle_axis = "nul" input_fps_toggle_btn = "nul" input_fps_toggle_mbtn = "nul" diff --git a/tests-other/test_input_gyroscope_tilt.ratst b/tests-other/test_input_gyroscope_tilt.ratst new file mode 100644 index 000000000000..159b9805930f --- /dev/null +++ b/tests-other/test_input_gyroscope_tilt.ratst @@ -0,0 +1,14 @@ +[ +{ "action": 15, "param_num": 10, "frame": 330 }, +{ "action": 15, "param_num": 40 }, +{ "action": 15, "param_num": 60 }, +{ "action": 15, "param_num": 90 }, +{ "action": 15, "param_num": 110 }, +{ "action": 15, "param_num": 140 }, +{ "action": 15, "param_num": 160 }, +{ "action": 15, "param_num": 190 }, +{ "action": 1, "param_num": 27 }, +{ "action": 2, "param_num": 27 }, +{ "action": 1, "param_num": 27 }, +{ "action": 2, "param_num": 27} +] diff --git a/tests-other/test_input_keyboard.ratst b/tests-other/test_input_keyboard.ratst new file mode 100644 index 000000000000..fffbec732791 --- /dev/null +++ b/tests-other/test_input_keyboard.ratst @@ -0,0 +1,26 @@ +[{ + "action": 1, + "param_num": 284, + "frame": 330 +},{ + "action": 2, + "param_num": 284 +},{ + "action": 1, + "param_num": 284 +},{ + "action": 2, + "param_num": 284 +},{ + "action": 1, + "param_num": 27 +},{ + "action": 2, + "param_num": 27 +},{ + "action": 1, + "param_num": 27 +},{ + "action": 2, + "param_num": 27 +}] diff --git a/tests-other/testinput.cfg b/tests-other/testinput.cfg index 494b04e197bc..6bb7d2e0028f 100644 --- a/tests-other/testinput.cfg +++ b/tests-other/testinput.cfg @@ -2,7 +2,7 @@ # Sets up joypad driver, test input file for the joypad driver, # logging and autoconfig dir, and prevents saving. # Usage: retroarch --appendconfig tests-other/testinput.cfg\|tests_other/all_binds_empty.cfg -# Usage with retropad test counterpart: retroarch --appendconfig tests_other/testinput.cfg\|tests_other/all_binds_empty.cfg -L netretropad tests_other/netretropad_all_inputs.ratst +# Usage with retropad test counterpart: retroarch --appendconfig tests-other/testinput.cfg\|tests-other/all_binds_empty.cfg -L netretropad tests-other/netretropad_all_inputs.ratst input_joypad_driver = "test" test_input_file_joypad = "tests-other/test_input_joypad.ratst" diff --git a/tests-other/testinput_device_reservation_test.cfg b/tests-other/testinput_device_reservation_test.cfg index 4529555dcb63..f05e8488f0f2 100644 --- a/tests-other/testinput_device_reservation_test.cfg +++ b/tests-other/testinput_device_reservation_test.cfg @@ -2,7 +2,7 @@ # Sets up joypad driver, test input file for the joypad driver, # logging and autoconfig dir, and prevents saving. # Usage: -# retroarch --appendconfig tests_other/testinput_device_reservation_test.cfg\|tests_other/all_binds_empty.cfg +# retroarch --appendconfig tests-other/testinput_device_reservation_test.cfg\|tests-other/all_binds_empty.cfg # Test scenario: # - Player 1 has preferred device C, Player 4 has reserved device B diff --git a/tests-other/testinput_device_reservation_test2.cfg b/tests-other/testinput_device_reservation_test2.cfg index 7be535a878ba..33a37941c1ec 100644 --- a/tests-other/testinput_device_reservation_test2.cfg +++ b/tests-other/testinput_device_reservation_test2.cfg @@ -2,7 +2,7 @@ # Sets up joypad driver, test input file for the joypad driver, # logging and autoconfig dir, and prevents saving. # Usage: -# retroarch --appendconfig tests_other/testinput_device_reservation_test.cfg\|tests_other/all_binds_empty.cfg +# retroarch --appendconfig tests-other/testinput_device_reservation_test.cfg\|tests-other/all_binds_empty.cfg # Test scenario: # - Player 1 through 4 has preferred device C @@ -26,4 +26,4 @@ input_player3_reserved_device = "0005:0006 Test joypad device C" input_player3_device_reservation_type = "2" input_player4_reserved_device = "0005:0006 " input_player4_device_reservation_type = "2" -# input_max_users = "3" \ No newline at end of file +# input_max_users = "3" diff --git a/tests-other/testinput_gyroscope.cfg b/tests-other/testinput_gyroscope.cfg new file mode 100644 index 000000000000..f371357755c1 --- /dev/null +++ b/tests-other/testinput_gyroscope.cfg @@ -0,0 +1,12 @@ +# Test configuration file to be used with --appendconfig. +# Sets up joypad driver, test input file for the joypad driver, +# logging and autoconfig dir, and prevents saving. +# Usage: retroarch --appendconfig tests-other/testinput_gyroscope.cfg\|tests_other/all_binds_empty.cfg -L netretropad + +input_driver = "test" +input_sensors_enable = "true" +test_input_file_general = "tests-other/test_input_gyroscope_tilt.ratst" +frontend_log_level = "0" +libretro_log_level = "0" +log_verbosity = "true" +config_save_on_exit = "false"