diff --git a/.gitmodules b/.gitmodules index 6dd72bcb..a0686d70 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "third_party/enet"] path = third_party/enet url = https://github.com/cgutman/enet.git +[submodule "third_party/inih"] + path = third_party/inih + url = https://github.com/benhoyt/inih diff --git a/CMakeLists.txt b/CMakeLists.txt index 89bfb0d6..49c709cb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,6 +15,7 @@ include_directories( third_party/libuuid/src/ third_party/h264bitstream/ third_party/enet/include/ + third_party/inih/ ) add_executable(${PROJECT_NAME}.elf @@ -84,6 +85,8 @@ add_executable(${PROJECT_NAME}.elf third_party/enet/peer.c third_party/enet/protocol.c third_party/enet/vita.c + + third_party/inih/ini.c ) target_link_libraries(${PROJECT_NAME}.elf diff --git a/mappings/vita.conf b/mappings/vita.conf index 41734b47..3bc95ec8 100644 --- a/mappings/vita.conf +++ b/mappings/vita.conf @@ -34,13 +34,13 @@ btn_thumbl = 300100 btn_thumbr = 300200 # LT -btn_tl = 500258 +btn_tl = 500001 # RT -btn_tr = 500259 +btn_tr = 500002 # LS -btn_tl2 = 50025a +btn_tl2 = 500004 # RS -btn_tr2 = 50025b +btn_tr2 = 500008 # not used btn_mode = -1 diff --git a/src/config.c b/src/config.c index 6362efc9..55c18f37 100644 --- a/src/config.c +++ b/src/config.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "graphics.h" #include "input/vita.h" @@ -36,7 +37,9 @@ #define write_config_string(fd, key, value) fprintf(fd, "%s = %s\n", key, value) #define write_config_int(fd, key, value) fprintf(fd, "%s = %d\n", key, value) +#define write_config_hex(fd, key, value) fprintf(fd, "%s = %X\n", key, value) #define write_config_bool(fd, key, value) fprintf(fd, "%s = %s\n", key, value?"true":"false"); +#define write_config_section(fd, key) fprintf(fd, "\n[%s]\n", key) CONFIGURATION config; char *config_path; @@ -46,80 +49,34 @@ static bool mapped = true; const char* audio_device = NULL; static struct option long_options[] = { - {"720", no_argument, NULL, 'a'}, - {"1080", no_argument, NULL, 'b'}, - {"width", required_argument, NULL, 'c'}, - {"height", required_argument, NULL, 'd'}, - {"30fps", no_argument, NULL, 'e'}, - {"60fps", no_argument, NULL, 'f'}, - {"bitrate", required_argument, NULL, 'g'}, - {"packetsize", required_argument, NULL, 'h'}, - {"app", required_argument, NULL, 'i'}, - {"input", required_argument, NULL, 'j'}, - {"mapping", required_argument, NULL, 'k'}, - {"nosops", no_argument, NULL, 'l'}, - {"audio", required_argument, NULL, 'm'}, - {"localaudio", no_argument, NULL, 'n'}, - {"config", required_argument, NULL, 'o'}, - {"platform", required_argument, 0, 'p'}, - {"save", required_argument, NULL, 'q'}, - {"keydir", required_argument, NULL, 'r'}, - {"remote", no_argument, NULL, 's'}, - {"windowed", no_argument, NULL, 't'}, - {"surround", no_argument, NULL, 'u'}, - {"fps", required_argument, NULL, 'v'}, - {"forcehw", no_argument, NULL, 'w'}, - {"forcehevc", no_argument, NULL, 'x'}, - {"unsupported", no_argument, NULL, 'y'}, + {"720", no_argument, NULL, 'a'}, + {"1080", no_argument, NULL, 'b'}, + {"width", required_argument, NULL, 'c'}, + {"height", required_argument, NULL, 'd'}, + {"30fps", no_argument, NULL, 'e'}, + {"60fps", no_argument, NULL, 'f'}, + {"bitrate", required_argument, NULL, 'g'}, + {"packetsize", required_argument, NULL, 'h'}, + {"app", required_argument, NULL, 'i'}, + {"input", required_argument, NULL, 'j'}, + {"mapping", required_argument, NULL, 'k'}, + {"nosops", no_argument, NULL, 'l'}, + {"audio", required_argument, NULL, 'm'}, + {"localaudio", no_argument, NULL, 'n'}, + {"config", required_argument, NULL, 'o'}, + {"platform", required_argument, 0, 'p'}, + {"save", required_argument, NULL, 'q'}, + {"keydir", required_argument, NULL, 'r'}, + {"remote", no_argument, NULL, 's'}, + {"windowed", no_argument, NULL, 't'}, + {"surround", no_argument, NULL, 'u'}, + {"fps", required_argument, NULL, 'v'}, + {"forcehw", no_argument, NULL, 'w'}, + {"forcehevc", no_argument, NULL, 'x'}, + {"unsupported", no_argument, NULL, 'y'}, {0, 0, 0, 0}, }; -char* __get_path(char* name, char* extra_data_dirs) { - const char *xdg_config_dir = getenv("XDG_CONFIG_DIR"); - const char *home_dir = getenv("HOME"); - - if (access(name, R_OK) != -1) { - return name; - } - - if (!extra_data_dirs) - extra_data_dirs = "/usr/share:/usr/local/share"; - if (!xdg_config_dir) - xdg_config_dir = home_dir; - - char *data_dirs = malloc(strlen(USER_PATHS) + 1 + strlen(xdg_config_dir) + 1 + strlen(home_dir) + 1 + strlen(DEFAULT_CONFIG_DIR) + 1 + strlen(extra_data_dirs) + 2); - sprintf(data_dirs, USER_PATHS ":%s:%s/" DEFAULT_CONFIG_DIR ":%s/", xdg_config_dir, home_dir, extra_data_dirs); - - char *path = malloc(strlen(data_dirs)+strlen(MOONLIGHT_PATH)+strlen(name)+2); - if (path == NULL) { - fprintf(stderr, "Not enough memory\n"); - exit(-1); - } - - char* data_dir = data_dirs; - char* end; - do { - end = strstr(data_dir, ":"); - int length = end != NULL?end - data_dir:strlen(data_dir); - memcpy(path, data_dir, length); - if (path[0] == '/') - sprintf(path+length, MOONLIGHT_PATH "/%s", name); - else - sprintf(path+length, "/%s", name); - - if(access(path, R_OK) != -1) { - free(data_dirs); - return path; - } - - data_dir = end + 1; - } while (end != NULL); - - free(data_dirs); - free(path); - return NULL; -} - static void parse_argument(int c, char* value, PCONFIGURATION config) { switch (c) { case 'a': @@ -226,56 +183,55 @@ static void parse_argument(int c, char* value, PCONFIGURATION config) { } } -bool config_file_parse(char* filename, PCONFIGURATION config) { - FILE* fd = fopen(filename, "r"); - if (fd == NULL) { - printf("Can't open configuration file: %s\n", filename); - return false; - } - - char *line = NULL; - size_t len = 0; - - while (__getline(&line, &len, fd) != -1) { - char key[256], scan_value[256]; - if (sscanf(line, "%s = %s\n", &key, &scan_value) == 2) { - char *value = malloc(sizeof(char) * strlen(scan_value)); - strcpy(value, scan_value); - if (strcmp(key, "address") == 0) { - config->address = malloc(sizeof(char)*strlen(value)); - strcpy(config->address, value); - } else if (strcmp(key, "sops") == 0) { - config->sops = strcmp("true", value) == 0; - } else if (strcmp(key, "localaudio") == 0) { - config->localaudio = strcmp("true", value) == 0; - } else if (strcmp(key, "backtouchscreen_deadzone") == 0) { - sscanf(value, - "%d,%d,%d,%d", - &config->back_deadzone.top, - &config->back_deadzone.right, - &config->back_deadzone.bottom, - &config->back_deadzone.left); - } else if (strcmp(key, "special_keys") == 0) { - sscanf(value, - "%x,%x,%x,%x,%d,%d", - &config->special_keys.nw, - &config->special_keys.ne, - &config->special_keys.sw, - &config->special_keys.se, - &config->special_keys.offset, - &config->special_keys.size); - } else if (strcmp(key, "disable_powersave") == 0) { - config->disable_powersave = strcmp("true", value) == 0; - } else { - for (int i=0;long_options[i].name != NULL;i++) { - if (long_options[i].has_arg == required_argument && strcmp(long_options[i].name, key) == 0) { - parse_argument(long_options[i].val, value, config); - } - } - } +static int ini_handle(void *out, const char *section, const char *name, + const char *value) { +#define HEX(v) strtol((v), NULL, 16) +#define INT(v) atoi((v)) +#define BOOL(v) strcmp((v), "true") == 0 +#define STR(v) strdup((v)) + + PCONFIGURATION config = (PCONFIGURATION)out; + if (strcmp(section, "backtouchscreen_deadzone") == 0) { + if (strcmp(name, "top") == 0) { + config->back_deadzone.top = INT(value); + } else if (strcmp(name, "right") == 0) { + config->back_deadzone.right = INT(value); + } else if (strcmp(name, "bottom") == 0) { + config->back_deadzone.bottom = INT(value); + } else if (strcmp(name, "left") == 0) { + config->back_deadzone.left = INT(value); + } + } else if (strcmp(section, "special_keys") == 0) { + if (strcmp(name, "nw") == 0) { + config->special_keys.nw = HEX(value); + } else if (strcmp(name, "ne") == 0) { + config->special_keys.ne = HEX(value); + } else if (strcmp(name, "sw") == 0) { + config->special_keys.sw = HEX(value); + } else if (strcmp(name, "se") == 0) { + config->special_keys.se = HEX(value); + } else if (strcmp(name, "offset") == 0) { + config->special_keys.offset = INT(value); + } else if (strcmp(name, "size") == 0) { + config->special_keys.size = INT(value); + } + } else { + if (strcmp(name, "address") == 0) { + config->address = STR(value); + } else if (strcmp(name, "bitrate") == 0) { + config->stream.bitrate = INT(value); + } else if (strcmp(name, "sops") == 0) { + config->sops = BOOL(value); + } else if (strcmp(name, "localaudio") == 0) { + config->localaudio = BOOL(value); + } else if (strcmp(name, "disable_powersave") == 0) { + config->disable_powersave = BOOL(value); } } - return true; +} + +bool config_file_parse(char* filename, PCONFIGURATION config) { + return ini_parse(filename, ini_handle, config); } void config_save(char* filename, PCONFIGURATION config) { @@ -311,26 +267,19 @@ void config_save(char* filename, PCONFIGURATION config) { write_config_bool(fd, "disable_powersave", config->disable_powersave); - char value[256]; - sprintf( - value, - "%d,%d,%d,%d", - config->back_deadzone.top, - config->back_deadzone.right, - config->back_deadzone.bottom, - config->back_deadzone.left); - write_config_string(fd, "backtouchscreen_deadzone", value); + write_config_section(fd, "backtouchscreen_deadzone"); + write_config_int(fd, "top", config->back_deadzone.top); + write_config_int(fd, "right", config->back_deadzone.right); + write_config_int(fd, "bottom", config->back_deadzone.bottom); + write_config_int(fd, "left", config->back_deadzone.left); - sprintf( - value, - "%x,%x,%x,%x,%d,%d", - config->special_keys.nw, - config->special_keys.ne, - config->special_keys.sw, - config->special_keys.se, - config->special_keys.offset, - config->special_keys.size); - write_config_string(fd, "special_keys", value); + write_config_section(fd, "special_keys"); + write_config_hex(fd, "nw", config->special_keys.nw); + write_config_hex(fd, "ne", config->special_keys.ne); + write_config_hex(fd, "sw", config->special_keys.sw); + write_config_hex(fd, "se", config->special_keys.se); + write_config_int(fd, "offset", config->special_keys.offset); + write_config_int(fd, "size", config->special_keys.size); fclose(fd); } @@ -347,7 +296,7 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) { config->stream.audioConfiguration = AUDIO_CONFIGURATION_STEREO; config->stream.supportsHevc = false; - config->platform = "default"; + config->platform = "vita"; config->app = "Steam"; config->action = NULL; config->address = NULL; @@ -372,18 +321,6 @@ void config_parse(int argc, char* argv[], PCONFIGURATION config) { if (config_file) { config_file_parse(config_file, config); } - if (argc == 2 && access(argv[1], F_OK) == 0) { - config->action = "stream"; - if (!config_file_parse(argv[1], config)) - exit(EXIT_FAILURE); - - } else { - int option_index = 0; - int c; - while ((c = getopt_long_only(argc, argv, "-abc:d:efg:h:i:j:k:lm:no:p:q:r:stuv:w:xy", long_options, &option_index)) != -1) { - parse_argument(c, optarg, config); - } - } if (config->config_file != NULL) config_save(config->config_file, config); diff --git a/src/gui/ui_connect.c b/src/gui/ui_connect.c index c31cf720..db779fc9 100644 --- a/src/gui/ui_connect.c +++ b/src/gui/ui_connect.c @@ -211,7 +211,17 @@ int ui_connect(char *address) { server_connected = true; } - struct menu_entry menu[48]; + int app_count = 0; + if (server_applist != NULL) { + PAPP_LIST list = server_applist; + while (list) { + list = list->next; + app_count += 1; + } + } + + // current menu = 11 + app_count. but little more alloc ;) + struct menu_entry menu[app_count + 16]; int idx = 0; @@ -257,7 +267,7 @@ int ui_connect(char *address) { } } - assert(idx < 48); + //assert(idx < 48); return display_menu(menu, idx, NULL, &ui_connect_loop, NULL, NULL, NULL); } @@ -270,6 +280,8 @@ void ui_connect_ip() { switch (ime_dialog(&ip, "Enter IP:", "192.168.")) { case 0: server_connected = false; + if (config.address) + free(config.address); config.address = malloc(sizeof(char) * strlen(ip)); strcpy(config.address, ip); ui_settings_save_config(); @@ -285,5 +297,5 @@ bool ui_connect_connected() { } void ui_connect_address(char *addr) { - strcpy(addr, server.address); + strcpy(addr, server.serverInfo.address); } diff --git a/src/input/vita.c b/src/input/vita.c index 13c84096..bae0bef3 100644 --- a/src/input/vita.c +++ b/src/input/vita.c @@ -29,6 +29,7 @@ #include "../graphics.h" #include "../config.h" +#include "../connection.h" #include "vita.h" #include "mapping.h" @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -45,87 +47,39 @@ #define WIDTH 960 #define HEIGHT 544 -static struct mapping map = {0}; +struct mapping map = {0}; typedef struct input_data { short button; - char left_trigger; - char right_trigger; short lx; short ly; short rx; short ry; + char lt; + char rt; } input_data; -#define lerp(value, from_max, to_max) ((((value*10) * (to_max*10))/(from_max*10))/10) +typedef struct Point { + short x; + short y; +} Point; -static int check_touch(SceTouchData scr, int lx, int ly, int rx, int ry) { - for (int i = 0; i < scr.reportNum; i++) { - int x = lerp(scr.report[i].x, 1919, WIDTH); - int y = lerp(scr.report[i].y, 1087, HEIGHT); - if (x < lx || x > rx || y < ly || y > ry) continue; - return i; - } - return -1; -} +typedef struct Section { + Point left; + Point right; +} Section; -int check_touch_sector(SceTouchData scr, int section) { - int vertical = (WIDTH - config.back_deadzone.left - config.back_deadzone.right) / 2 + config.back_deadzone.left, - horizontal = (HEIGHT - config.back_deadzone.top - config.back_deadzone.bottom) / 2 + config.back_deadzone.top; - - int special_offset = config.special_keys.offset, - special_size = config.special_keys.size; - - switch (section) { - case TOUCHSEC_NORTHWEST: - return check_touch(scr, config.back_deadzone.left, config.back_deadzone.top, vertical, horizontal); - case TOUCHSEC_NORTHEAST: - return check_touch(scr, vertical, config.back_deadzone.top, WIDTH - config.back_deadzone.right, horizontal); - case TOUCHSEC_SOUTHWEST: - return check_touch(scr, config.back_deadzone.left, horizontal, vertical, HEIGHT - config.back_deadzone.bottom); - case TOUCHSEC_SOUTHEAST: - return check_touch(scr, vertical, horizontal, WIDTH - config.back_deadzone.left, HEIGHT - config.back_deadzone.bottom); - case TOUCHSEC_SPECIAL_SW: - return check_touch( - scr, - special_offset, - HEIGHT - special_size - special_offset, - special_size + special_offset, - HEIGHT - special_offset - ); - case TOUCHSEC_SPECIAL_SE: - return check_touch( - scr, - WIDTH - special_size - special_offset, - HEIGHT - special_size - special_offset, - WIDTH - special_offset, - HEIGHT - special_offset - ); - case TOUCHSEC_SPECIAL_NW: - return check_touch( - scr, - special_offset, - special_offset, - special_offset + special_size, - special_offset + special_size - ); - case TOUCHSEC_SPECIAL_NE: - return check_touch( - scr, - WIDTH - special_size - special_offset, - special_offset, - WIDTH - special_offset, - special_offset + special_size - ); - - default: - return false; - } -} +typedef struct TouchData { + short button; + short finger; + Point points[4]; +} TouchData; + +#define lerp(value, from_max, to_max) ((((value*10) * (to_max*10))/(from_max*10))/10) #define MOUSE_ACTION_DELAY 100000 // 100ms -static bool mouse_click(SceTouchData screen, short finger_count, bool press) { +inline bool mouse_click(short finger_count, bool press) { int mode; if (press) { @@ -145,9 +99,9 @@ static bool mouse_click(SceTouchData screen, short finger_count, bool press) { return false; } -static void move_mouse(SceTouchData old, SceTouchData cur) { - int delta_x = (cur.report[0].x - old.report[0].x) / 2; - int delta_y = (cur.report[0].y - old.report[0].y) / 2; +inline void move_mouse(TouchData old, TouchData cur) { + int delta_x = (cur.points[0].x - old.points[0].x) / 2; + int delta_y = (cur.points[0].y - old.points[0].y) / 2; if (!delta_x && !delta_y) { return; @@ -155,9 +109,9 @@ static void move_mouse(SceTouchData old, SceTouchData cur) { LiSendMouseMoveEvent(delta_x, delta_y); } -static void move_wheel(SceTouchData old, SceTouchData cur) { - int old_y = (old.report[0].y + old.report[1].y) / 2; - int cur_y = (cur.report[0].y + cur.report[1].y) / 2; +inline void move_wheel(TouchData old, TouchData cur) { + int old_y = (old.points[0].y + old.points[1].y) / 2; + int cur_y = (cur.points[0].y + cur.points[1].y) / 2; int delta_y = (cur_y - old_y) / 2; if (!delta_y) { return; @@ -165,215 +119,297 @@ static void move_wheel(SceTouchData old, SceTouchData cur) { LiSendScrollEvent(delta_y); } -bool check_input(uint32_t identifier, SceCtrlData pad, SceTouchData screen) { - uint32_t type = identifier & INPUT_TYPE_MASK; - int value = identifier & INPUT_VALUE_MASK; - switch (type) { - case INPUT_TYPE_TOUCHSCREEN: - if (value < TOUCHSEC_NORTHWEST || value > TOUCHSEC_SOUTHEAST) { - return false; - } - return check_touch_sector(screen, value) != -1; - case INPUT_TYPE_GAMEPAD: - return pad.buttons & value; - } - return false; -} +SceCtrlData pad, pad_old; +TouchData touch; +TouchData touch_old, swipe; +SceTouchData front, back; -static short pad_analog_value(uint32_t identifier, SceCtrlData pad, SceTouchData screen) { - unsigned char value = 0; +int front_state = NO_TOUCH_ACTION; +short finger_count = 0; +SceRtcTick current, until; - if ((identifier & INPUT_TYPE_MASK) != INPUT_TYPE_ANALOG) { - return check_input(identifier, pad, screen) ? 0xff : 0; - } - switch (identifier & INPUT_VALUE_MASK) { - case LEFT_TRIGGER: - return pad.lt; - case RIGHT_TRIGGER: - return pad.rt; - case LEFTX: - value = pad.lx; - break; - case RIGHTX: - value = pad.rx; - break; - case LEFTY: - value = pad.ly; - break; - case RIGHTY: - value = pad.ry; - break; - } +static int special_status; - return (short) (value * 256 - (1 << 15) + 128); -} +input_data curr, old; +int controller_port; + +// TODO config +static int VERTICAL; +static int HORIZONTAL; + +#define IN_SECTION(SECTION, X, Y) \ + ((SECTION).left.x <= (X) && (X) <= (SECTION).right.x && \ + (SECTION).left.y <= (Y) && (Y) <= (SECTION).right.y) + +// TODO sections +Section BACK_SECTIONS[4]; +Section FRONT_SECTIONS[4]; -static int special_input_config_code(short identifier) { - switch (identifier) { - case TOUCHSEC_SPECIAL_NW: - return config.special_keys.nw; - case TOUCHSEC_SPECIAL_NE: - return config.special_keys.ne; - case TOUCHSEC_SPECIAL_SW: - return config.special_keys.sw; - case TOUCHSEC_SPECIAL_SE: - return config.special_keys.se; - default: - return 0; +inline uint8_t read_backscreen() { + for (int i = 0; i < back.reportNum; i++) { + int x = lerp(back.report[i].x, 1919, WIDTH); + int y = lerp(back.report[i].y, 1087, HEIGHT); + + if ((touch.button & TOUCHSEC_NORTHWEST) == 0) { + if (IN_SECTION(BACK_SECTIONS[0], x, y)) { + touch.button |= TOUCHSEC_NORTHWEST; + continue; + } + } + + if ((touch.button & TOUCHSEC_NORTHEAST) == 0) { + if (IN_SECTION(BACK_SECTIONS[1], x, y)) { + touch.button |= TOUCHSEC_NORTHEAST; + continue; + } + } + + if (touch.button & TOUCHSEC_SOUTHWEST) { + if (IN_SECTION(BACK_SECTIONS[2], x, y)) { + touch.button |= TOUCHSEC_SOUTHWEST; + continue; + } + } + + if (touch.button & TOUCHSEC_SOUTHEAST) { + if (IN_SECTION(BACK_SECTIONS[3], x, y)) { + touch.button |= TOUCHSEC_SOUTHEAST; + continue; + } + } } + return 0; } -static bool special_input_status[4] = {0, 0, 0, 0}; -static void special_input(SceTouchData screen, input_data *input) { - for (int identifier = TOUCHSEC_SPECIAL_NW; identifier <= TOUCHSEC_SPECIAL_SE; identifier++) { - int idx = identifier - TOUCHSEC_SPECIAL_NW; - bool current_status = special_input_status[idx]; - unsigned int config_code = special_input_config_code(identifier); - - unsigned int type = config_code & INPUT_TYPE_MASK; - unsigned int code = config_code & INPUT_VALUE_MASK; - if (check_touch_sector(screen, identifier) != -1 && !current_status) { - switch (type) { - case INPUT_TYPE_SPECIAL: - if (code == INPUT_SPECIAL_KEY_PAUSE) { - connection_minimize(); - } break; - case INPUT_TYPE_GAMEPAD: - input->button |= code; - break; - case INPUT_TYPE_MOUSE: - special_input_status[idx] = true; - LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, code); - break; - case INPUT_TYPE_ANALOG: - switch (code) { - case LEFT_TRIGGER: - input->left_trigger = 0xff; - break; - case RIGHT_TRIGGER: - input->right_trigger = 0xff; - break; - } - break; - case INPUT_TYPE_KEYBOARD: - special_input_status[idx] = true; - LiSendKeyboardEvent(code, KEY_ACTION_DOWN, 0); - break; + +inline uint8_t read_frontscreen() { + for (int i = 0; i < front.reportNum; i++) { + int x = lerp(front.report[i].x, 1919, WIDTH); + int y = lerp(front.report[i].y, 1087, HEIGHT); + + if ((touch.button & TOUCHSEC_SPECIAL_NW) == 0) { + if (IN_SECTION(FRONT_SECTIONS[0], x, y)) { + touch.button |= TOUCHSEC_SPECIAL_NW; + continue; + } + } + + if ((touch.button & TOUCHSEC_SPECIAL_NE) == 0) { + if (IN_SECTION(FRONT_SECTIONS[1], x, y)) { + touch.button |= TOUCHSEC_SPECIAL_NE; + continue; + } + } + + if (touch.button & TOUCHSEC_SPECIAL_SW) { + if (IN_SECTION(FRONT_SECTIONS[2], x, y)) { + touch.button |= TOUCHSEC_SPECIAL_SW; + continue; } - } else if (check_touch_sector(screen, identifier) == -1 && current_status) { - special_input_status[idx] = false; - - switch (type) { - case INPUT_TYPE_MOUSE: - LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, code); - break; - case INPUT_TYPE_KEYBOARD: - LiSendKeyboardEvent(code, KEY_ACTION_UP, 0); - break; + } + + if (touch.button & TOUCHSEC_SPECIAL_SE) { + if (IN_SECTION(FRONT_SECTIONS[3], x, y)) { + touch.button |= TOUCHSEC_SPECIAL_SE; + continue; } } + + // FIXME if touch same section using multiple finger, they can count finger + touch.points[touch.finger].x = x; + touch.points[touch.finger].y = y; + touch.finger += 1; } + return 0; } -#define INPUT_BUTTON(id, flag) if (check_input((id), pad, back)) input.button |= (flag); -#define INPUT_ANALOG(id) pad_analog_value((id), pad, back) +inline uint32_t is_pressed(uint32_t defined) { + uint32_t dev_type = defined & INPUT_TYPE_MASK; + uint32_t dev_val = defined & INPUT_VALUE_MASK; -static SceCtrlData pad; -static SceTouchData front; -static SceTouchData front_old; -static SceTouchData back; + switch(dev_type) { + case INPUT_TYPE_GAMEPAD: + return pad.buttons & dev_val; + case INPUT_TYPE_TOUCHSCREEN: + return touch.button & dev_val; + } + return 0; +} -static int front_state = NO_TOUCH_ACTION; -static short finger_count = 0; -static SceRtcTick current, until; +inline uint32_t is_old_pressed(uint32_t defined) { + uint32_t dev_type = defined & INPUT_TYPE_MASK; + uint32_t dev_val = defined & INPUT_VALUE_MASK; + switch(dev_type) { + case INPUT_TYPE_GAMEPAD: + return pad_old.buttons & dev_val; + case INPUT_TYPE_TOUCHSCREEN: + return touch_old.button & dev_val; + } + return 0; +} -static int special_status; +inline short read_analog(uint32_t defined) { + uint32_t dev_type = defined & INPUT_TYPE_MASK; + uint32_t dev_val = defined & INPUT_VALUE_MASK; + + if (dev_type == INPUT_TYPE_ANALOG) { + int v; + switch(dev_val) { + case LEFTX: + v = pad.lx; + break; + case LEFTY: + v = pad.ly; + break; + case RIGHTX: + v = pad.rx; + break; + case RIGHTY: + v = pad.ry; + break; + case LEFT_TRIGGER: + return pad.lt; + case RIGHT_TRIGGER: + return pad.rt; + default: + return 0; + } + v = v * 256 - (1 << 15) + 128; + return (short)(v); + } + return is_pressed(defined) ? 0xff : 0; +} -static input_data old; -static int controller_port; +inline void special(uint32_t defined, uint32_t pressed, uint32_t old_pressed) { + uint32_t dev_type = defined & INPUT_TYPE_MASK; + uint32_t dev_val = defined & INPUT_VALUE_MASK; -void vitainput_process(void) { + if (pressed) { + switch(dev_type) { + case INPUT_TYPE_SPECIAL: + if (dev_val == INPUT_SPECIAL_KEY_PAUSE) { + connection_minimize(); + return; + } + case INPUT_TYPE_GAMEPAD: + curr.button |= dev_val; + return; + case INPUT_TYPE_ANALOG: + switch(dev_val) { + case LEFT_TRIGGER: + curr.lt = 0xff; + return; + case RIGHT_TRIGGER: + curr.rt = 0xff; + return; + } + return; + case INPUT_TYPE_MOUSE: + if (!old_pressed) { + LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, dev_val); + } + return; + case INPUT_TYPE_KEYBOARD: + if (!old_pressed) { + LiSendKeyboardEvent(dev_val, KEY_ACTION_DOWN, 0); + } + return; + } + } else { + // released + switch(dev_type) { + case INPUT_TYPE_MOUSE: + if (old_pressed) { + LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, dev_val); + } + return; + case INPUT_TYPE_KEYBOARD: + if (old_pressed) { + LiSendKeyboardEvent(dev_val, KEY_ACTION_UP, 0); + } + return; + } + } + +} + +inline void vitainput_process(void) { memset(&pad, 0, sizeof(pad)); + memset(&touch, 0, sizeof(TouchData)); + memset(&curr, 0, sizeof(input_data)); sceCtrlReadBufferPositiveExt2(controller_port, &pad, 1); sceTouchPeek(SCE_TOUCH_PORT_FRONT, &front, 1); sceTouchPeek(SCE_TOUCH_PORT_BACK, &back, 1); - sceRtcGetCurrentTick(¤t); + read_frontscreen(); + read_backscreen(); - input_data input = {0}; + sceRtcGetCurrentTick(¤t); // buttons - INPUT_BUTTON(map.btn_dpad_up, UP_FLAG); - INPUT_BUTTON(map.btn_dpad_left, LEFT_FLAG); - INPUT_BUTTON(map.btn_dpad_down, DOWN_FLAG); - INPUT_BUTTON(map.btn_dpad_right, RIGHT_FLAG); - - INPUT_BUTTON(map.btn_start, PLAY_FLAG); - INPUT_BUTTON(map.btn_select, BACK_FLAG); - - INPUT_BUTTON(map.btn_north, Y_FLAG); - INPUT_BUTTON(map.btn_east, B_FLAG); - INPUT_BUTTON(map.btn_south, A_FLAG); - INPUT_BUTTON(map.btn_west, X_FLAG); - - INPUT_BUTTON(map.btn_tl2, LS_CLK_FLAG); - INPUT_BUTTON(map.btn_tr2, RS_CLK_FLAG); - - INPUT_BUTTON(map.btn_thumbl, LB_FLAG); - INPUT_BUTTON(map.btn_thumbr, RB_FLAG); - - // ANALOG - input.left_trigger = INPUT_ANALOG(map.btn_tl); - input.right_trigger = INPUT_ANALOG(map.btn_tr); - - input.lx = INPUT_ANALOG(map.abs_x); - input.ly = INPUT_ANALOG(map.abs_y); - input.rx = INPUT_ANALOG(map.abs_rx); - input.ry = INPUT_ANALOG(map.abs_ry); + curr.button |= is_pressed(map.btn_dpad_up) ? UP_FLAG : 0; + curr.button |= is_pressed(map.btn_dpad_left) ? LEFT_FLAG : 0; + curr.button |= is_pressed(map.btn_dpad_down) ? DOWN_FLAG : 0; + curr.button |= is_pressed(map.btn_dpad_right) ? RIGHT_FLAG : 0; + curr.button |= is_pressed(map.btn_start) ? PLAY_FLAG : 0; + curr.button |= is_pressed(map.btn_select) ? BACK_FLAG : 0; + curr.button |= is_pressed(map.btn_north) ? Y_FLAG : 0; + curr.button |= is_pressed(map.btn_east) ? B_FLAG : 0; + curr.button |= is_pressed(map.btn_south) ? A_FLAG : 0; + curr.button |= is_pressed(map.btn_west) ? X_FLAG : 0; + curr.button |= is_pressed(map.btn_thumbl) ? LB_FLAG : 0; // l1 + curr.button |= is_pressed(map.btn_thumbr) ? RB_FLAG : 0; // r1 + curr.button |= is_pressed(map.btn_tl2) ? LS_CLK_FLAG : 0; // l3 + curr.button |= is_pressed(map.btn_tr2) ? RS_CLK_FLAG : 0; // r3 + + // analogs + curr.lt = read_analog(map.btn_tl); // l2 + curr.rt = read_analog(map.btn_tr); // r2 + curr.lx = read_analog(map.abs_x); + curr.ly = read_analog(map.abs_y); + curr.rx = read_analog(map.abs_rx); + curr.ry = read_analog(map.abs_ry); // special touchscreen buttons - special_input(front, &input); - - // remove touches for special actions - for (int i = TOUCHSEC_SPECIAL_NW, touchIdx = -1; i <= TOUCHSEC_SPECIAL_SE; i++) { - unsigned int config_code = special_input_config_code(i); - if (config_code && (touchIdx = check_touch_sector(front, i)) != -1) { - for (int n = 0, idx = 0; n < front.reportNum; n++) { - if (n != touchIdx) { - front.report[idx++] = front.report[n]; - } - } - - front.reportNum--; - } - } + special(config.special_keys.nw, + is_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NW), + is_old_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NW)); + special(config.special_keys.ne, + is_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NE), + is_old_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NE)); + special(config.special_keys.sw, + is_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NW), + is_old_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_NW)); + special(config.special_keys.se, + is_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_SE), + is_old_pressed(INPUT_TYPE_TOUCHSCREEN | TOUCHSEC_SPECIAL_SE)); // mouse switch (front_state) { case NO_TOUCH_ACTION: - if (front.reportNum > 0) { + if (touch.finger > 0) { front_state = ON_SCREEN_TOUCH; - finger_count = front.reportNum; + finger_count = touch.finger; sceRtcTickAddMicroseconds(&until, ¤t, MOUSE_ACTION_DELAY); } break; case ON_SCREEN_TOUCH: if (sceRtcCompareTick(¤t, &until) < 0) { - if (front.reportNum < finger_count) { + if (touch.finger < finger_count) { // TAP - if (mouse_click(front, finger_count, true)) { + if (mouse_click(finger_count, true)) { front_state = SCREEN_TAP; sceRtcTickAddMicroseconds(&until, ¤t, MOUSE_ACTION_DELAY); } else { front_state = NO_TOUCH_ACTION; } - } else if (front.reportNum > finger_count) { + } else if (touch.finger > finger_count) { // finger count changed - finger_count = front.reportNum; + finger_count = touch.finger; } } else { front_state = SWIPE_START; @@ -381,36 +417,40 @@ void vitainput_process(void) { break; case SCREEN_TAP: if (sceRtcCompareTick(¤t, &until) >= 0) { - mouse_click(front, finger_count, false); + mouse_click(finger_count, false); front_state = NO_TOUCH_ACTION; } break; case SWIPE_START: - memcpy(&front_old, &front, sizeof(front_old)); + memcpy(&swipe, &touch, sizeof(swipe)); front_state = ON_SCREEN_SWIPE; break; case ON_SCREEN_SWIPE: - if (front.reportNum > 0) { - switch (front.reportNum) { + if (touch.finger > 0) { + switch (touch.finger) { case 1: - move_mouse(front_old, front); + move_mouse(swipe, touch); break; case 2: - move_wheel(front_old, front); + move_wheel(swipe, touch); break; } - memcpy(&front_old, &front, sizeof(front_old)); + memcpy(&swipe, &touch, sizeof(swipe)); } else { front_state = NO_TOUCH_ACTION; } break; } - if (memcmp(&input, &old, sizeof(input_data)) != 0) { - LiSendControllerEvent(input.button, input.left_trigger, input.right_trigger, - input.lx, -1 * input.ly, input.rx, -1 * input.ry); - memcpy(&old, &input, sizeof(input_data)); + if (memcmp(&curr, &old, sizeof(input_data)) != 0) { + LiSendControllerEvent(curr.button, curr.lt, curr.rt, + curr.lx, -1 * curr.ly, curr.rx, -1 * curr.ry); + memcpy(&old, &curr, sizeof(input_data)); + memcpy(&pad_old, &pad, sizeof(SceCtrlData)); + } + if (memcmp(&touch, &touch_old, sizeof(TouchData)) != 0) { + memcpy(&touch_old, &touch, sizeof(TouchData)); } } @@ -423,18 +463,6 @@ int vitainput_thread(SceSize args, void *argp) { } sceKernelDelayThread(5000); // 5 ms - - /* - SceRtcTick before, after; - sceRtcGetCurrentTick(&before); - sceKernelDelayThread(1 * 1000); // 1 ms - sceRtcGetCurrentTick(&after); - - if (active_input_thread) { - if (after.tick - before.tick > 150 * 1000) { - connection_terminate(); - } - } */ } return 0; @@ -495,6 +523,51 @@ void vitainput_config(CONFIGURATION config) { } controller_port = config.model == SCE_KERNEL_MODEL_VITATV ? 1 : 0; + + VERTICAL = (WIDTH - config.back_deadzone.left - config.back_deadzone.right) / 2 + + config.back_deadzone.left; + HORIZONTAL = (HEIGHT - config.back_deadzone.top - config.back_deadzone.bottom) / 2 + + config.back_deadzone.top; + + BACK_SECTIONS[0].left.x = config.back_deadzone.left; + BACK_SECTIONS[0].left.y = config.back_deadzone.top; + BACK_SECTIONS[0].right.x = VERTICAL; + BACK_SECTIONS[0].right.y = HORIZONTAL; + + BACK_SECTIONS[1].left.x = VERTICAL; + BACK_SECTIONS[1].left.y = config.back_deadzone.top; + BACK_SECTIONS[1].right.x = WIDTH - config.back_deadzone.right; + BACK_SECTIONS[1].right.y = HORIZONTAL; + + BACK_SECTIONS[2].left.x = config.back_deadzone.left; + BACK_SECTIONS[2].left.y = HORIZONTAL; + BACK_SECTIONS[2].right.x = VERTICAL; + BACK_SECTIONS[2].right.y = HEIGHT - config.back_deadzone.bottom; + + BACK_SECTIONS[3].left.x = VERTICAL; + BACK_SECTIONS[3].left.y = HORIZONTAL; + BACK_SECTIONS[3].right.x = WIDTH - config.back_deadzone.right; + BACK_SECTIONS[3].right.y = HEIGHT - config.back_deadzone.bottom; + + FRONT_SECTIONS[0].left.x = config.special_keys.offset; + FRONT_SECTIONS[0].left.y = config.special_keys.offset; + FRONT_SECTIONS[0].right.x = config.special_keys.offset + config.special_keys.size; + FRONT_SECTIONS[0].right.y = config.special_keys.offset + config.special_keys.size; + + FRONT_SECTIONS[1].left.x = WIDTH - config.special_keys.offset - config.special_keys.size; + FRONT_SECTIONS[1].left.y = config.special_keys.offset; + FRONT_SECTIONS[1].right.x = WIDTH - config.special_keys.offset; + FRONT_SECTIONS[1].right.y = config.special_keys.offset + config.special_keys.size; + + FRONT_SECTIONS[2].left.x = config.special_keys.offset; + FRONT_SECTIONS[2].left.y = HEIGHT - config.special_keys.offset - config.special_keys.size; + FRONT_SECTIONS[2].right.x = config.special_keys.offset + config.special_keys.size; + FRONT_SECTIONS[2].right.y = HEIGHT - config.special_keys.offset; + + FRONT_SECTIONS[3].left.x = WIDTH - config.special_keys.offset - config.special_keys.size; + FRONT_SECTIONS[3].left.y = HEIGHT - config.special_keys.offset - config.special_keys.size; + FRONT_SECTIONS[3].right.x = WIDTH - config.special_keys.offset; + FRONT_SECTIONS[3].right.y = HEIGHT - config.special_keys.offset; } void vitainput_start(void) { diff --git a/src/input/vita.h b/src/input/vita.h index 52385101..ed4eca36 100644 --- a/src/input/vita.h +++ b/src/input/vita.h @@ -26,14 +26,14 @@ enum { } TouchScreenState; enum { - TOUCHSEC_NORTHWEST = 600, - TOUCHSEC_NORTHEAST, - TOUCHSEC_SOUTHWEST, - TOUCHSEC_SOUTHEAST, - TOUCHSEC_SPECIAL_NW = 700, - TOUCHSEC_SPECIAL_NE, - TOUCHSEC_SPECIAL_SW, - TOUCHSEC_SPECIAL_SE + TOUCHSEC_NORTHWEST = 0x1, + TOUCHSEC_NORTHEAST = 0x2, + TOUCHSEC_SOUTHWEST = 0x4, + TOUCHSEC_SOUTHEAST = 0x8, + TOUCHSEC_SPECIAL_NW = 0x10, + TOUCHSEC_SPECIAL_NE = 0x20, + TOUCHSEC_SPECIAL_SW = 0x30, + TOUCHSEC_SPECIAL_SE = 0x40, } TouchScreenSection; enum { diff --git a/src/main.c b/src/main.c index f95c774e..cee238b6 100644 --- a/src/main.c +++ b/src/main.c @@ -160,7 +160,6 @@ int main(int argc, char* argv[]) { sceIoMkdir("ux0:/data/moonlight", 0777); config_path = "ux0:data/moonlight/moonlight.conf"; config_parse(argc, argv, &config); - config.platform = "vita"; strcpy(config.key_dir, "ux0:data/moonlight/"); vitapower_config(config); diff --git a/third_party/inih b/third_party/inih new file mode 160000 index 00000000..18a67c51 --- /dev/null +++ b/third_party/inih @@ -0,0 +1 @@ +Subproject commit 18a67c516358e2791ab720a1abe411d991774f3e