mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-26 17:50:56 +00:00
Test input driver and sensor test screen
A new input driver (test_input), similar to test joypad driver. Takes its inputs from a json file provided in options. Supports keyboard input and sensor input (accelerometer, gyroscope, illuminance). Remote Retropad extended with a sensor test screen.
This commit is contained in:
parent
9abd8f3a3a
commit
7db9a2de60
@ -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
|
||||
|
||||
|
||||
|
@ -1670,6 +1670,7 @@ static struct config_path_setting *populate_settings_path(
|
||||
|
||||
#ifdef HAVE_TEST_DRIVERS
|
||||
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);
|
||||
|
@ -583,6 +583,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];
|
||||
|
@ -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 <stdio.h>
|
||||
@ -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 @@ end:
|
||||
/* 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);
|
||||
|
@ -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 */
|
||||
|
@ -733,6 +733,7 @@ INPUT
|
||||
|
||||
#ifdef HAVE_TEST_DRIVERS
|
||||
#include "../input/drivers_joypad/test_joypad.c"
|
||||
#include "../input/drivers/test_input.c"
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
|
557
input/drivers/test_input.c
Normal file
557
input/drivers/test_input.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <file/file_path.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <formats/rjson.h>
|
||||
|
||||
#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<last_test_step; i++)
|
||||
{
|
||||
if (!input_test_steps[i].handled && curr_frame > 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
|
||||
};
|
@ -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 @@ end:
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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,8 +4421,21 @@ 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;
|
||||
#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."
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
|
14
tests-other/test_input_gyroscope_tilt.ratst
Normal file
14
tests-other/test_input_gyroscope_tilt.ratst
Normal file
@ -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}
|
||||
]
|
26
tests-other/test_input_keyboard.ratst
Normal file
26
tests-other/test_input_keyboard.ratst
Normal file
@ -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
|
||||
}]
|
@ -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"
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
12
tests-other/testinput_gyroscope.cfg
Normal file
12
tests-other/testinput_gyroscope.cfg
Normal file
@ -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"
|
Loading…
Reference in New Issue
Block a user