diff --git a/Makefile.common b/Makefile.common index 4a872356bd..3277ff0a3e 100644 --- a/Makefile.common +++ b/Makefile.common @@ -2431,6 +2431,12 @@ ifeq ($(HAVE_WEBOS), 1) DEFINES += -DWEBOS endif +ifeq ($(HAVE_TEST_DRIVERS), 1) + DEFINES += -DHAVE_TEST_DRIVERS + OBJ += input/drivers_joypad/test_joypad.o +endif + + ##################################### ### Android Play Feature Delivery ### ### (Play Store build core ### diff --git a/configuration.c b/configuration.c index 8a5e272926..425740ee25 100644 --- a/configuration.c +++ b/configuration.c @@ -1645,6 +1645,10 @@ static struct config_path_setting *populate_settings_path( SETTING_PATH("bottom_assets_directory", settings->paths.directory_bottom_assets, true, NULL, true); #endif +#ifdef HAVE_TEST_DRIVERS + SETTING_PATH("test_input_file_joypad", settings->paths.test_input_file_joypad, false, NULL, true); +#endif + SETTING_ARRAY("log_dir", settings->paths.log_dir, true, NULL, true); SETTING_ARRAY("app_icon", settings->paths.app_icon, true, NULL, true); diff --git a/configuration.h b/configuration.h index ce7a5a42d7..6228682990 100644 --- a/configuration.h +++ b/configuration.h @@ -574,6 +574,9 @@ typedef struct settings char streaming_title[PATH_MAX_LENGTH]; #ifdef _3DS char directory_bottom_assets[PATH_MAX_LENGTH]; +#endif +#ifdef HAVE_TEST_DRIVERS + char test_input_file_joypad[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 61ef1e6f4a..d6816218f4 100644 --- a/cores/libretro-net-retropad/net_retropad_core.c +++ b/cores/libretro-net-retropad/net_retropad_core.c @@ -663,6 +663,9 @@ void NETRETROPAD_CORE_PREFIX(retro_run)(void) NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_INFO, "[Remote RetroPad]: Test sequence finished at frame %d, result: %d/%d inputs detected\n", current_frame, pass_count, last_test_step); + NETRETROPAD_CORE_PREFIX(log_cb)(RETRO_LOG_INFO, + "[Remote RetroPad]: Validated state: %08x combo: %08x\n", + input_state_validated, combo_state_validated); } } diff --git a/griffin/griffin.c b/griffin/griffin.c index 7465480a13..426e249e93 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -730,6 +730,10 @@ INPUT #endif #endif +#ifdef HAVE_TEST_DRIVERS +#include "../input/drivers_joypad/test_joypad.c" +#endif + /*============================================================ INPUT (HID) ============================================================ */ diff --git a/input/drivers_joypad/test_joypad.c b/input/drivers_joypad/test_joypad.c new file mode 100644 index 0000000000..2c3433b538 --- /dev/null +++ b/input/drivers_joypad/test_joypad.c @@ -0,0 +1,482 @@ +/* RetroArch - A frontend for libretro. + * 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 . + */ + +/* Possible improvement list: + * Add vid/pid to autoconf profile step, if autoconf matching needs testing + * Multiple device autoconf profiles, with different analog/digital setup, analog buttons, extra buttons, unconfigured buttons... + * Unimplemented functions (get_button, rumble) + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +#include "../../config.def.h" +#include "../../verbosity.h" +#include "../input_driver.h" +#include "../../tasks/tasks_internal.h" +#include "../../gfx/video_driver.h" + +#define MAX_TEST_STEPS 200 +#define NUM_BUTTONS 32 +#ifndef MAX_AXIS +#define MAX_AXIS 10 +#endif + +#define JOYPAD_TEST_COMMAND_ADD_CONTROLLER 1 +#define JOYPAD_TEST_COMMAND_BUTTON_PRESS_FIRST 16 +#define JOYPAD_TEST_COMMAND_BUTTON_PRESS_LAST 31 +#define JOYPAD_TEST_COMMAND_BUTTON_RELEASE_FIRST 32 +#define JOYPAD_TEST_COMMAND_BUTTON_RELEASE_LAST 47 +#define JOYPAD_TEST_COMMAND_BUTTON_AXIS_FIRST 1000 +#define JOYPAD_TEST_COMMAND_BUTTON_AXIS_LAST JOYPAD_TEST_COMMAND_BUTTON_AXIS_FIRST+MAX_AXIS*DEFAULT_MAX_PADS + +typedef struct +{ + char* name; + uint32_t button_state; + int32_t axis_state[MAX_AXIS]; +} test_joypad_data; + +static test_joypad_data test_joypads[MAX_USERS]; + +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; +} JTifJSONContext; + +static bool JTifJSONObjectEndHandler(void* context) +{ + JTifJSONContext *pCtx = (JTifJSONContext*)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 JTifJSONObjectMemberHandler(void* context, const char *pValue, size_t length) +{ + JTifJSONContext *pCtx = (JTifJSONContext*)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 JTifJSONNumberHandler(void* context, const char *pValue, size_t length) +{ + JTifJSONContext *pCtx = (JTifJSONContext*)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 JTifJSONStringHandler(void* context, const char *pValue, size_t length) +{ + JTifJSONContext *pCtx = (JTifJSONContext*)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; + JTifJSONContext 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, + JTifJSONObjectMemberHandler, + JTifJSONStringHandler, + JTifJSONNumberHandler, + NULL, JTifJSONObjectEndHandler, 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 */ +/********************************/ + +static const char *test_joypad_name(unsigned pad) +{ + if (pad >= MAX_USERS || string_is_empty(test_joypads[pad].name)) + return NULL; + + return test_joypads[pad].name; +} + + +static void test_joypad_autodetect_add(unsigned autoconf_pad) +{ + input_autoconfigure_connect( + test_joypad_name(autoconf_pad), + NULL, + "test", + autoconf_pad, + 0, + 0 + ); +} + +static void *test_joypad_init(void *data) +{ + settings_t *settings = config_get_ptr(); + unsigned i; + + input_test_file_read(settings->paths.test_input_file_joypad); + if (last_test_step > MAX_TEST_STEPS) + last_test_step = 0; + + for(i=0; i 0) + continue; + if (input_test_steps[i].action == JOYPAD_TEST_COMMAND_ADD_CONTROLLER) + { + test_joypads[input_test_steps[i].param_num].name = input_test_steps[i].param_str; + test_joypad_autodetect_add(input_test_steps[i].param_num); + input_test_steps[i].handled = true; + } + + } + return (void*)-1; +} + +static int32_t test_joypad_button(unsigned port_num, uint16_t joykey) +{ + int16_t ret = 0; + if (port_num >= DEFAULT_MAX_PADS) + return 0; + if (joykey < NUM_BUTTONS) + return (BIT32_GET(test_joypads[port_num].button_state, joykey)); + + return 0; +} + +static int16_t test_joypad_axis(unsigned port_num, uint32_t joyaxis) +{ + /*RARCH_DBG("test_joypad_axis %d / %u\n",port_num, joyaxis);*/ + if (port_num >= DEFAULT_MAX_PADS) + return 0; + if (AXIS_NEG_GET(joyaxis) < MAX_AXIS) + { + /* Kernel returns values in range [-0x7fff, 0x7fff]. */ + int16_t val = test_joypads[port_num].axis_state[AXIS_NEG_GET(joyaxis)]; + if (val < 0) + return val; + } + else if (AXIS_POS_GET(joyaxis) < MAX_AXIS) + { + int16_t val = test_joypads[port_num].axis_state[AXIS_POS_GET(joyaxis)]; + if (val > 0) + return val; + } + return 0; + +} + +static int16_t test_joypad_state( + rarch_joypad_info_t *joypad_info, + const struct retro_keybind *binds, + unsigned port) +{ + + unsigned i; + int16_t ret = 0; + uint16_t port_idx = joypad_info->joy_idx; + + if (port_idx < DEFAULT_MAX_PADS) + { + for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++) + { + /* Auto-binds are per joypad, not per user. */ + const uint16_t joykey = (binds[i].joykey != NO_BTN) + ? binds[i].joykey : joypad_info->auto_binds[i].joykey; + /* Test input driver uses same button layout internally as RA, so no conversion is needed */ + if (joykey != NO_BTN && (test_joypads[port_idx].button_state & (1 << i))) + { + ret |= ( 1 << i); + } + } + } + + return ret; +} + + +static void test_joypad_poll(void) +{ + + 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 == JOYPAD_TEST_COMMAND_ADD_CONTROLLER) + { + test_joypads[input_test_steps[i].param_num].name = input_test_steps[i].param_str; + test_joypad_autodetect_add(input_test_steps[i].param_num); + input_test_steps[i].handled = true; + } + else if( input_test_steps[i].action >= JOYPAD_TEST_COMMAND_BUTTON_PRESS_FIRST && + input_test_steps[i].action <= JOYPAD_TEST_COMMAND_BUTTON_PRESS_LAST) + { + unsigned targetpad = input_test_steps[i].action - JOYPAD_TEST_COMMAND_BUTTON_PRESS_FIRST; + 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", + 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 && + input_test_steps[i].action <= JOYPAD_TEST_COMMAND_BUTTON_RELEASE_LAST) + { + unsigned targetpad = input_test_steps[i].action - JOYPAD_TEST_COMMAND_BUTTON_RELEASE_FIRST; + 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", + 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 && + input_test_steps[i].action <= JOYPAD_TEST_COMMAND_BUTTON_AXIS_LAST) + { + unsigned targetpad = + (input_test_steps[i].action - JOYPAD_TEST_COMMAND_BUTTON_AXIS_FIRST) / MAX_AXIS; + unsigned targetaxis = + input_test_steps[i].action - JOYPAD_TEST_COMMAND_BUTTON_AXIS_FIRST - (targetpad*MAX_AXIS); + if (targetpad < DEFAULT_MAX_PADS && targetaxis < MAX_AXIS) + 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", + 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", + 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", + input_test_steps[i].action,i); + } + + } + } +} + +static bool test_joypad_query_pad(unsigned pad) +{ + return (pad < MAX_USERS); +} + +static void test_joypad_destroy(void) +{ + +} + +input_device_driver_t test_joypad = { + test_joypad_init, + test_joypad_query_pad, + test_joypad_destroy, + test_joypad_button, + test_joypad_state, + NULL, /* get_buttons */ + test_joypad_axis, + test_joypad_poll, + NULL, /* rumble */ + NULL, /* rumble_gain */ + test_joypad_name, + "test", +}; diff --git a/input/input_driver.c b/input/input_driver.c index 957ee3f901..dc524d3037 100644 --- a/input/input_driver.c +++ b/input/input_driver.c @@ -280,6 +280,9 @@ input_device_driver_t *joypad_drivers[] = { #endif #ifdef EMSCRIPTEN &rwebpad_joypad, +#endif +#ifdef HAVE_TEST_DRIVERS + &test_joypad, #endif &null_joypad, NULL, diff --git a/input/input_driver.h b/input/input_driver.h index 6fa75a3b35..99f5abf9bc 100644 --- a/input/input_driver.h +++ b/input/input_driver.h @@ -1113,6 +1113,7 @@ extern input_device_driver_t qnx_joypad; extern input_device_driver_t mfi_joypad; extern input_device_driver_t dos_joypad; extern input_device_driver_t rwebpad_joypad; +extern input_device_driver_t test_joypad; #ifdef HAVE_HID extern hid_driver_t iohidmanager_hid; diff --git a/qb/config.params.sh b/qb/config.params.sh index b314389706..d261c8f6f3 100644 --- a/qb/config.params.sh +++ b/qb/config.params.sh @@ -203,3 +203,4 @@ HAVE_CRTSWITCHRES=auto # CRT mode switching support (requires C++11) HAVE_MEMFD_CREATE=auto # libc supports memfd_create C89_CRTSWITCHRES=no HAVE_MICROPHONE=yes # Microphone support +HAVE_TEST_DRIVERS=yes # Test input driver diff --git a/tasks/task_autodetect.c b/tasks/task_autodetect.c index aa68e3b6c0..bf96d2a50a 100644 --- a/tasks/task_autodetect.c +++ b/tasks/task_autodetect.c @@ -481,7 +481,11 @@ static void input_autoconfigure_connect_handler(retro_task_t *task) else if (string_is_equal(autoconfig_handle->device_info.joypad_driver, "sdl2")) fallback_device_name = "Standard Gamepad"; - +#ifdef HAVE_TEST_DRIVERS + else if (string_is_equal(autoconfig_handle->device_info.joypad_driver, + "test")) + fallback_device_name = "Test Gamepad"; +#endif if (!string_is_empty(fallback_device_name) && !string_is_equal(autoconfig_handle->device_info.name, fallback_device_name)) diff --git a/tests-other/all_binds_empty.cfg b/tests-other/all_binds_empty.cfg new file mode 100644 index 0000000000..82d867584f --- /dev/null +++ b/tests-other/all_binds_empty.cfg @@ -0,0 +1,391 @@ +# Config file to be used with --appendconfig +# Sets input related settings to default (or nul, in case of bindings) +# so that tests can rely on a clean startup state. +# Escape button is deliberately retained, to be able to end / abort tests. + +input_exit_emulator = "escape" +input_max_users = "10" + +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_allow_turbo_dpad = "false" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.000000" +input_audio_mute = "nul" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute_mbtn = "nul" +input_auto_game_focus = "nul" +input_auto_mouse_grab = "false" +input_autodetect_enable = "true" +input_axis_threshold = "0.500000" +input_bind_hold = "0" +input_bind_timeout = "5" +input_cheat_index_minus = "nul" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "nul" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "nul" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_close_content = "nul" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_desktop_menu_toggle = "nul" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle_mbtn = "nul" +input_disk_eject_toggle = "nul" +input_disk_eject_toggle_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_next = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_prev = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_enable_hotkey = "nul" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "nul" +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_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "nul" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "nul" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "nul" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_halt_replay = "nul" +input_halt_replay_axis = "nul" +input_halt_replay_btn = "nul" +input_halt_replay_mbtn = "nul" +input_hold_fast_forward = "nul" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "nul" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_load_state = "nul" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_menu_toggle = "nul" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "nul" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle = "nul" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_netplay_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "nul" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "nul" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_osk_toggle = "nul" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle_mbtn = "nul" +input_overlay = "" +input_overlay_enable = "false" +input_overlay_next = "nul" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_pause_toggle = "nul" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_play_replay = "nul" +input_play_replay_axis = "nul" +input_play_replay_btn = "nul" +input_play_replay_mbtn = "nul" +input_player1_a = "x" +input_player1_a_axis = "nul" +input_player1_a_btn = "nul" +input_player1_a_mbtn = "nul" +input_player1_analog_dpad_mode = "1" +input_player1_b = "z" +input_player1_b_axis = "nul" +input_player1_b_btn = "nul" +input_player1_b_mbtn = "nul" +input_player1_down = "down" +input_player1_down_axis = "nul" +input_player1_down_btn = "nul" +input_player1_down_mbtn = "nul" +input_player1_gun_aux_a = "nul" +input_player1_gun_aux_a_axis = "nul" +input_player1_gun_aux_a_btn = "nul" +input_player1_gun_aux_a_mbtn = "nul" +input_player1_gun_aux_b = "nul" +input_player1_gun_aux_b_axis = "nul" +input_player1_gun_aux_b_btn = "nul" +input_player1_gun_aux_b_mbtn = "nul" +input_player1_gun_aux_c = "nul" +input_player1_gun_aux_c_axis = "nul" +input_player1_gun_aux_c_btn = "nul" +input_player1_gun_aux_c_mbtn = "nul" +input_player1_gun_dpad_down = "nul" +input_player1_gun_dpad_down_axis = "nul" +input_player1_gun_dpad_down_btn = "nul" +input_player1_gun_dpad_down_mbtn = "nul" +input_player1_gun_dpad_left = "nul" +input_player1_gun_dpad_left_axis = "nul" +input_player1_gun_dpad_left_btn = "nul" +input_player1_gun_dpad_left_mbtn = "nul" +input_player1_gun_dpad_right = "nul" +input_player1_gun_dpad_right_axis = "nul" +input_player1_gun_dpad_right_btn = "nul" +input_player1_gun_dpad_right_mbtn = "nul" +input_player1_gun_dpad_up = "nul" +input_player1_gun_dpad_up_axis = "nul" +input_player1_gun_dpad_up_btn = "nul" +input_player1_gun_dpad_up_mbtn = "nul" +input_player1_gun_offscreen_shot = "nul" +input_player1_gun_offscreen_shot_axis = "nul" +input_player1_gun_offscreen_shot_btn = "nul" +input_player1_gun_offscreen_shot_mbtn = "2" +input_player1_gun_select = "nul" +input_player1_gun_select_axis = "nul" +input_player1_gun_select_btn = "nul" +input_player1_gun_select_mbtn = "nul" +input_player1_gun_start = "nul" +input_player1_gun_start_axis = "nul" +input_player1_gun_start_btn = "nul" +input_player1_gun_start_mbtn = "nul" +input_player1_gun_trigger = "nul" +input_player1_gun_trigger_axis = "nul" +input_player1_gun_trigger_btn = "nul" +input_player1_gun_trigger_mbtn = "1" +input_player1_joypad_index = "0" +input_player1_l = "q" +input_player1_l2 = "nul" +input_player1_l2_axis = "nul" +input_player1_l2_btn = "nul" +input_player1_l2_mbtn = "nul" +input_player1_l3 = "nul" +input_player1_l3_axis = "nul" +input_player1_l3_btn = "nul" +input_player1_l3_mbtn = "nul" +input_player1_l_axis = "nul" +input_player1_l_btn = "nul" +input_player1_l_mbtn = "nul" +input_player1_l_x_minus = "nul" +input_player1_l_x_minus_axis = "nul" +input_player1_l_x_minus_btn = "nul" +input_player1_l_x_minus_mbtn = "nul" +input_player1_l_x_plus = "nul" +input_player1_l_x_plus_axis = "nul" +input_player1_l_x_plus_btn = "nul" +input_player1_l_x_plus_mbtn = "nul" +input_player1_l_y_minus = "nul" +input_player1_l_y_minus_axis = "nul" +input_player1_l_y_minus_btn = "nul" +input_player1_l_y_minus_mbtn = "nul" +input_player1_l_y_plus = "nul" +input_player1_l_y_plus_axis = "nul" +input_player1_l_y_plus_btn = "nul" +input_player1_l_y_plus_mbtn = "nul" +input_player1_left = "left" +input_player1_left_axis = "nul" +input_player1_left_btn = "nul" +input_player1_left_mbtn = "nul" +input_player1_mouse_index = "0" +input_player1_r = "w" +input_player1_r2 = "nul" +input_player1_r2_axis = "nul" +input_player1_r2_btn = "nul" +input_player1_r2_mbtn = "nul" +input_player1_r3 = "nul" +input_player1_r3_axis = "nul" +input_player1_r3_btn = "nul" +input_player1_r3_mbtn = "nul" +input_player1_r_axis = "nul" +input_player1_r_btn = "nul" +input_player1_r_mbtn = "nul" +input_player1_r_x_minus = "nul" +input_player1_r_x_minus_axis = "nul" +input_player1_r_x_minus_btn = "nul" +input_player1_r_x_minus_mbtn = "nul" +input_player1_r_x_plus = "nul" +input_player1_r_x_plus_axis = "nul" +input_player1_r_x_plus_btn = "nul" +input_player1_r_x_plus_mbtn = "nul" +input_player1_r_y_minus = "nul" +input_player1_r_y_minus_axis = "nul" +input_player1_r_y_minus_btn = "nul" +input_player1_r_y_minus_mbtn = "nul" +input_player1_r_y_plus = "nul" +input_player1_r_y_plus_axis = "nul" +input_player1_r_y_plus_btn = "nul" +input_player1_r_y_plus_mbtn = "nul" +input_player1_right = "right" +input_player1_right_axis = "nul" +input_player1_right_btn = "nul" +input_player1_right_mbtn = "nul" +input_player1_select = "rshift" +input_player1_select_axis = "nul" +input_player1_select_btn = "nul" +input_player1_select_mbtn = "nul" +input_player1_start = "enter" +input_player1_start_axis = "nul" +input_player1_start_btn = "nul" +input_player1_start_mbtn = "nul" +input_player1_turbo = "nul" +input_player1_turbo_axis = "nul" +input_player1_turbo_btn = "nul" +input_player1_turbo_mbtn = "nul" +input_player1_up = "up" +input_player1_up_axis = "nul" +input_player1_up_btn = "nul" +input_player1_up_mbtn = "nul" +input_player1_x = "s" +input_player1_x_axis = "nul" +input_player1_x_btn = "nul" +input_player1_x_mbtn = "nul" +input_player1_y = "a" +input_player1_y_axis = "nul" +input_player1_y_btn = "nul" +input_player1_y_mbtn = "nul" +input_poll_type_behavior = "1" +input_preempt_toggle = "nul" +input_preempt_toggle_axis = "nul" +input_preempt_toggle_btn = "nul" +input_preempt_toggle_mbtn = "nul" +input_quit_gamepad_combo = "0" +input_record_replay = "nul" +input_record_replay_axis = "nul" +input_record_replay_btn = "nul" +input_record_replay_mbtn = "nul" +input_recording_toggle = "nul" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_remap_binds_enable = "true" +input_replay_slot_decrease = "nul" +input_replay_slot_decrease_axis = "nul" +input_replay_slot_decrease_btn = "nul" +input_replay_slot_decrease_mbtn = "nul" +input_replay_slot_increase = "nul" +input_replay_slot_increase_axis = "nul" +input_replay_slot_increase_btn = "nul" +input_replay_slot_increase_mbtn = "nul" +input_reset = "nul" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "nul" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "100" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "nul" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "nul" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot_mbtn = "nul" +input_send_debug_info = "nul" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next = "nul" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "nul" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_shader_toggle = "nul" +input_shader_toggle_axis = "nul" +input_shader_toggle_btn = "nul" +input_shader_toggle_mbtn = "nul" +input_state_slot_decrease = "nul" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "nul" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_toggle_fast_forward = "nul" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "nul" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_toggle_vrr_runloop = "nul" +input_toggle_vrr_runloop_axis = "nul" +input_toggle_vrr_runloop_btn = "nul" +input_toggle_vrr_runloop_mbtn = "nul" +input_volume_down = "nul" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "nul" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" diff --git a/tests-other/autoconf/Testpad.cfg b/tests-other/autoconf/Testpad.cfg new file mode 100644 index 0000000000..fecf9e23f6 --- /dev/null +++ b/tests-other/autoconf/Testpad.cfg @@ -0,0 +1,27 @@ +input_driver = "test" +input_device = "Test joypad device" +input_b_btn = "0" +input_y_btn = "1" +input_select_btn = "2" +input_start_btn = "3" +input_up_btn = "4" +input_down_btn = "5" +input_left_btn = "6" +input_right_btn = "7" +input_a_btn = "8" +input_x_btn = "9" +input_l_btn = "10" +input_r_btn = "11" +input_l2_btn = "12" +input_r2_btn = "13" +input_l3_btn = "14" +input_r3_btn = "15" +input_l_x_plus_axis = "+0" +input_l_x_minus_axis = "-0" +input_l_y_plus_axis = "+1" +input_l_y_minus_axis = "-1" +input_r_x_plus_axis = "+2" +input_r_x_minus_axis = "-2" +input_r_y_plus_axis = "+3" +input_r_y_minus_axis = "-3" + diff --git a/cores/libretro-net-retropad/controllertest.ratst b/tests-other/netretropad_all_inputs.ratst similarity index 92% rename from cores/libretro-net-retropad/controllertest.ratst rename to tests-other/netretropad_all_inputs.ratst index 06ee6e35d8..77c4636fbf 100644 --- a/cores/libretro-net-retropad/controllertest.ratst +++ b/tests-other/netretropad_all_inputs.ratst @@ -1,19 +1,19 @@ [ { "expected_button": 8, - "message": "Press A" + "message": "Press A (face button right)" }, { "expected_button": 0, - "message": "Press B" + "message": "Press B (face button bottom)" }, { "expected_button": 9, - "message": "Press X" + "message": "Press X (face button top)" }, { "expected_button": 1, - "message": "Press Y" + "message": "Press Y (face button left)" }, { "expected_button": 2, @@ -127,4 +127,4 @@ "expected_button": 23, "message": "Move right analog stick right fully" } -] \ No newline at end of file +] diff --git a/tests-other/test_input_joypad.ratst b/tests-other/test_input_joypad.ratst new file mode 100644 index 0000000000..1b8d08222c --- /dev/null +++ b/tests-other/test_input_joypad.ratst @@ -0,0 +1,227 @@ +[ +{ + "action": 1, + "param_num": 0, + "param_str": "Test joypad device" +}, +{ + "action": 1, + "param_num": 1, + "param_str": "Test joypad device", + "frame": 0 +}, +{ + "action": 1, + "param_num": 2, + "param_str": "Test joypad device" +}, +{ + "action": 16, + "param_num": 256, + "frame": 330 +}, +{ + "action": 32, + "param_num": 256 +}, +{ + "action": 16, + "param_num": 1 +}, +{ + "action": 32, + "param_num": 1 +}, +{ + "action": 16, + "param_num": 512 +}, +{ + "action": 32, + "param_num": 512 +}, +{ + "action": 16, + "param_num": 2 +}, +{ + "action": 32, + "param_num": 2 +}, +{ + "action": 16, + "param_num": 4 +}, +{ + "action": 32, + "param_num": 4 +}, +{ + "action": 16, + "param_num": 8 +}, +{ + "action": 32, + "param_num": 8 +}, +{ + "action": 16, + "param_num": 16 +}, +{ + "action": 32, + "param_num": 16 +}, +{ + "action": 16, + "param_num": 32 +}, +{ + "action": 32, + "param_num": 32 +}, +{ + "action": 16, + "param_num": 64 +}, +{ + "action": 32, + "param_num": 64 +}, +{ + "action": 16, + "param_num": 128 +}, +{ + "action": 32, + "param_num": 128 +}, +{ + "action": 16, + "param_num": 1024 +}, +{ + "action": 32, + "param_num": 1024 +}, +{ + "action": 16, + "param_num": 2048 +}, +{ + "action": 32, + "param_num": 2048 +}, +{ + "action": 16, + "param_num": 4096 +}, +{ + "action": 32, + "param_num": 4096 +}, +{ + "action": 16, + "param_num": 8192 +}, +{ + "action": 32, + "param_num": 8192 +}, +{ + "action": 16, + "param_num": 16384 +}, +{ + "action": 32, + "param_num": 16384 +}, +{ + "action": 16, + "param_num": 32768 +}, +{ + "action": 32, + "param_num": 32768 +}, +{ + "action": 1001, + "param_num": 60000 +}, +{ + "action": 1001, + "param_num": 32768 +}, +{ + "action": 1001, + "param_num": 6000 +}, +{ + "action": 1001, + "param_num": 32767 +}, +{ + "action": 1001, + "param_num": 0 +}, +{ + "action": 1000, + "param_num": 60000 +}, +{ + "action": 1000, + "param_num": 32768 +}, +{ + "action": 1000, + "param_num": 6000 +}, +{ + "action": 1000, + "param_num": 32767 +}, +{ + "action": 1000, + "param_num": 0 +}, +{ + "action": 1003, + "param_num": 60000 +}, +{ + "action": 1003, + "param_num": 32768 +}, +{ + "action": 1003, + "param_num": 6000 +}, +{ + "action": 1003, + "param_num": 32767 +}, +{ + "action": 1003, + "param_num": 0 +}, +{ + "action": 1002, + "param_num": 60000 +}, +{ + "action": 1002, + "param_num": 32768 +}, +{ + "action": 1002, + "param_num": 6000 +}, +{ + "action": 1002, + "param_num": 32767 +}, +{ + "action": 1002, + "param_num": 0 +} +] \ No newline at end of file diff --git a/tests-other/testinput.cfg b/tests-other/testinput.cfg new file mode 100644 index 0000000000..06e0784a1d --- /dev/null +++ b/tests-other/testinput.cfg @@ -0,0 +1,13 @@ +# 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.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 + +input_joypad_driver = "test" +test_input_file_joypad = "tests-other/test_input_joypad.ratst" +joypad_autoconfig_dir = "tests-other/autoconf" +frontend_log_level = "0" +libretro_log_level = "0" +log_verbosity = "true" +config_save_on_exit = "false"