From c4ea6b3d7cf12913d6f34404f6a36ba7a0684891 Mon Sep 17 00:00:00 2001 From: rsn8887 Date: Fri, 16 Mar 2018 00:22:06 -0500 Subject: [PATCH] rear & indirect front touch, pointer speed, radial scaled deadzone --- src/PSP2/main_psp.cpp | 3 + src/PSP2/makefile | 3 +- src/PSP2/prefs_editor_psp.cpp | 50 ++++ src/PSP2/prefs_psp.cpp | 22 +- src/PSP2/psp2_touch.cpp | 424 ++++++++++++++++++++++++++++++++++ src/PSP2/psp2_touch.h | 51 ++++ src/PSP2/user_strings_psp.cpp | 4 + src/PSP2/user_strings_psp.h | 5 + src/PSP2/video_psp.cpp | 104 ++++++--- 9 files changed, 628 insertions(+), 38 deletions(-) create mode 100644 src/PSP2/psp2_touch.cpp create mode 100644 src/PSP2/psp2_touch.h diff --git a/src/PSP2/main_psp.cpp b/src/PSP2/main_psp.cpp index e253fc8..065d7d7 100644 --- a/src/PSP2/main_psp.cpp +++ b/src/PSP2/main_psp.cpp @@ -57,6 +57,7 @@ using std::string; #include "user_strings.h" #include "version.h" #include "main.h" +#include "psp2_touch.h" #define Get_String(x) const_cast(GetString(x)) @@ -206,6 +207,8 @@ int main(int argc, char **argv) danzeff_load(); + psp2InitTouch(); + // Initialize variables RAMBaseHost = NULL; ROMBaseHost = NULL; diff --git a/src/PSP2/makefile b/src/PSP2/makefile index cbff803..c401f2f 100644 --- a/src/PSP2/makefile +++ b/src/PSP2/makefile @@ -14,7 +14,8 @@ OBJS = ../main.o main_psp.o ../prefs.o ../prefs_items.o prefs_psp.o \ ../disk.o ../cdrom.o ../scsi.o scsi_psp.o ../video.o \ video_psp.o ../audio.o audio_psp.o ../extfs.o extfs_psp.o \ ftruncate.o ../user_strings.o user_strings_psp.o \ - gui_psp.o reqfile.o debugScreen.o danzeff/danzeff.o\ + gui_psp.o reqfile.o debugScreen.o danzeff/danzeff.o \ + psp2_touch.o \ $(CPUOBJS) INCLUDES = -I../include -I./include -I. -I../uae_cpu -I../uae_cpu/fpu/softfloat diff --git a/src/PSP2/prefs_editor_psp.cpp b/src/PSP2/prefs_editor_psp.cpp index a870ec9..42b6e72 100644 --- a/src/PSP2/prefs_editor_psp.cpp +++ b/src/PSP2/prefs_editor_psp.cpp @@ -79,6 +79,10 @@ int psp_lcd_aspect = 0; // 4:3 int psp_lcd_border = 1; // default to inverting the data int psp_60hz_timing = 1; // default to relaxed timing +int psp_rear_touch_enable = 0; // do not use rear touch panel +int psp_indirect_touch_enable = 0; // do not use indirect touch on front panel +int psp_pointer_speed = 3; // indirect touch pointer speed is 1.0 +int psp_analog_deadzone = 2; // analog deadzone default is 10% extern char *psp_floppy_inserted; // String: filename of floppy inserted extern char *psp_cdrom_inserted; // String: filename of cdrom inserted @@ -260,10 +264,36 @@ void psp_create_floppy(void *arg) { 0, GUI_END_OF_LIST } }; + struct gui_list psp_pointer_speed_list[] = { + { "0.25", 0 }, + { "0.50", 1 }, + { "0.75", 2 }, + { "1.00", 3 }, + { "1.25", 4 }, + { "1.50", 5 }, + { "1.75", 6 }, + { "2.00", 7 }, + { 0, GUI_END_OF_LIST } + }; + + struct gui_list psp_analog_deadzone_list[] = { + { "5%", 0 }, + { "10%", 1 }, + { "15%", 2 }, + { "20%", 3 }, + { "25%", 4 }, + { "30%", 5 }, + { 0, GUI_END_OF_LIST } + }; + struct gui_menu PspLevel[] = { { Get_String(STR_PSP_CPU_FREQ), GUI_CENTER | GUI_SELECT, &psp_cpu_speed_list, &psp_cpu_speed, GUI_ENABLED }, { Get_String(STR_PSP_DISPLAY_ASPECT), GUI_CENTER | GUI_SELECT, &psp_aspect_list, &psp_lcd_aspect, GUI_ENABLED }, { Get_String(STR_PSP_RELAXED_60HZ), GUI_CENTER | GUI_TOGGLE, &psp_60hz_timing, 0, GUI_ENABLED }, + { Get_String(STR_PSP_REAR_TOUCH), GUI_CENTER | GUI_TOGGLE, &psp_rear_touch_enable, 0, GUI_ENABLED }, + { Get_String(STR_PSP_INDIRECT_TOUCH), GUI_CENTER | GUI_TOGGLE, &psp_indirect_touch_enable, 0, GUI_ENABLED }, + { Get_String(STR_PSP_POINTER_SPEED), GUI_CENTER | GUI_SELECT, &psp_pointer_speed_list, &psp_pointer_speed, GUI_ENABLED }, + { Get_String(STR_PSP_ANALOG_DEADZONE), GUI_CENTER | GUI_SELECT, &psp_analog_deadzone_list, &psp_analog_deadzone, GUI_ENABLED }, { 0, GUI_END_OF_MENU, 0, 0, 0 } // end of menu }; @@ -577,6 +607,18 @@ bool PrefsEditor(void) if (PrefsFindBool("relaxed60hz")) psp_60hz_timing = PrefsFindBool("relaxed60hz") ? 1 : 0; + if (PrefsFindBool("reartouch")) + psp_rear_touch_enable = PrefsFindBool("reartouch") ? 1 : 0; + + if (PrefsFindBool("indirecttouch")) + psp_indirect_touch_enable = PrefsFindBool("indirecttouch") ? 1 : 0; + + if (PrefsFindInt32("pointerspeed")) + psp_pointer_speed = PrefsFindInt32("pointerspeed"); + + if (PrefsFindInt32("analogdeadzone")) + psp_analog_deadzone = PrefsFindInt32("analogdeadzone"); + // YEAH!! Do that GUI!! do_gui(TopLevel, NULL, Get_String(STR_PREFS_ITEM_START)); @@ -659,6 +701,14 @@ bool PrefsEditor(void) PrefsReplaceBool("relaxed60hz", psp_60hz_timing ? true : false); + PrefsReplaceBool("reartouch", psp_rear_touch_enable ? true : false); + + PrefsReplaceBool("indirecttouch", psp_indirect_touch_enable ? true : false); + + PrefsReplaceInt32("pointerspeed", psp_pointer_speed); + + PrefsReplaceInt32("analogdeadzone", psp_analog_deadzone); + SavePrefs(); return true; diff --git a/src/PSP2/prefs_psp.cpp b/src/PSP2/prefs_psp.cpp index dbec033..c42fd14 100644 --- a/src/PSP2/prefs_psp.cpp +++ b/src/PSP2/prefs_psp.cpp @@ -29,15 +29,19 @@ // Platform-specific preferences items prefs_desc platform_prefs_items[] = { - {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, - {"udpapoint", TYPE_INT32, false, "UDP tunnel access point"}, - {"pspspeed", TYPE_INT32, false, "PSP CPU frequency"}, - {"psptv", TYPE_BOOLEAN, false, "Use video output"}, - {"pspmar", TYPE_INT32, false, "PSP TV monitor aspect ratio"}, - {"psplaced", TYPE_BOOLEAN, false, "PSP TV monitor uses interlace"}, - {"pspdar", TYPE_INT32, false, "PSP display aspect ratio"}, - {"psposcan", TYPE_BOOLEAN, false, "PSP video overscan enable"}, - {"relaxed60hz", TYPE_BOOLEAN, false, "Use relaxed timing for 60 Hz IRQ"}, + {"keycodefile", TYPE_STRING, false, "path of keycode translation file"}, + {"udpapoint", TYPE_INT32, false, "UDP tunnel access point"}, + {"pspspeed", TYPE_INT32, false, "PSP CPU frequency"}, + {"psptv", TYPE_BOOLEAN, false, "Use video output"}, + {"pspmar", TYPE_INT32, false, "PSP TV monitor aspect ratio"}, + {"psplaced", TYPE_BOOLEAN, false, "PSP TV monitor uses interlace"}, + {"pspdar", TYPE_INT32, false, "PSP display aspect ratio"}, + {"psposcan", TYPE_BOOLEAN, false, "PSP video overscan enable"}, + {"relaxed60hz", TYPE_BOOLEAN, false, "Use relaxed timing for 60 Hz IRQ"}, + {"reartouch", TYPE_BOOLEAN, false, "Enable rear touch panel"}, + {"indirecttouch", TYPE_BOOLEAN, false, "Use indirect front touch"}, + {"pointerspeed", TYPE_INT32, false, "Mouse pointer speed"}, + {"analogdeadzone", TYPE_INT32, false, "Analog joystick deadzone"}, {NULL, TYPE_END, false, NULL} // End of list }; diff --git a/src/PSP2/psp2_touch.cpp b/src/PSP2/psp2_touch.cpp new file mode 100644 index 0000000..0a863c0 --- /dev/null +++ b/src/PSP2/psp2_touch.cpp @@ -0,0 +1,424 @@ +// +// Created by rsn8887 on 02/05/18. + +#include +#include +#include "psp2_touch.h" +#include "sysdeps.h" +#include "adb.h" +#include +//#include "math.h" + +#define SDL_BUTTON_LEFT 0 +#define SDL_BUTTON_RIGHT 1 +typedef int Uint8; + +SceTouchData touch_old[SCE_TOUCH_PORT_MAX_NUM]; +SceTouchData touch[SCE_TOUCH_PORT_MAX_NUM]; + +SceTouchPanelInfo panelinfo[SCE_TOUCH_PORT_MAX_NUM]; + +float aAWidth[SCE_TOUCH_PORT_MAX_NUM]; +float aAHeight[SCE_TOUCH_PORT_MAX_NUM]; +float dispWidth[SCE_TOUCH_PORT_MAX_NUM]; +float dispHeight[SCE_TOUCH_PORT_MAX_NUM]; +float forcerange[SCE_TOUCH_PORT_MAX_NUM]; + +extern bool psp_rear_touch; +extern bool psp_indirect_touch; +extern float psp_pointer_speed_factor; +extern int32 psp_screen_x; +extern double scale_x; +extern double scale_y; +static int hires_dx; +static int hires_dy; + +enum { + MAX_NUM_FINGERS = 3, // number of fingers to track per panel + MAX_TAP_TIME = 250, // taps longer than this will not result in mouse click events + SIMULATED_CLICK_DURATION = 50, // time in ms how long simulated mouse clicks should be +}; // track three fingers per panel + +typedef struct { + int id; // -1: no touch + int timeLastDown; +} Touch; + +Touch _finger[SCE_TOUCH_PORT_MAX_NUM][MAX_NUM_FINGERS]; // keep track of finger status + +typedef enum DraggingType { + DRAG_NONE = 0, + DRAG_TWO_FINGER, + DRAG_THREE_FINGER, +} DraggingType; + +DraggingType _multiFingerDragging[SCE_TOUCH_PORT_MAX_NUM]; // keep track whether we are currently drag-and-dropping + +int _simulatedClickStartTime[SCE_TOUCH_PORT_MAX_NUM][2]; // initiation time of last simulated left or right click (zero if no click) + +void psp2InitTouch(void) { + sceTouchSetSamplingState(SCE_TOUCH_PORT_FRONT, SCE_TOUCH_SAMPLING_STATE_START); + sceTouchSetSamplingState(SCE_TOUCH_PORT_BACK, SCE_TOUCH_SAMPLING_STATE_START); + sceTouchEnableTouchForce(SCE_TOUCH_PORT_FRONT); + sceTouchEnableTouchForce(SCE_TOUCH_PORT_BACK); + + SceTouchPanelInfo panelinfo[SCE_TOUCH_PORT_MAX_NUM]; + for(int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) { + sceTouchGetPanelInfo(port, &panelinfo[port]); + aAWidth[port] = (float)(panelinfo[port].maxAaX - panelinfo[port].minAaX); + aAHeight[port] = (float)(panelinfo[port].maxAaY - panelinfo[port].minAaY); + dispWidth[port] = (float)(panelinfo[port].maxDispX - panelinfo[port].minDispX); + dispHeight[port] = (float)(panelinfo[port].maxDispY - panelinfo[port].minDispY); + forcerange[port] = (float)(panelinfo[port].maxForce - panelinfo[port].minForce); + } + + for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) { + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + _finger[port][i].id = -1; + } + _multiFingerDragging[port] = DRAG_NONE; + } + + for (int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) { + for (int i = 0; i < 2; i++) { + _simulatedClickStartTime[port][i] = 0; + } + } +} + +void psp2QuitTouch(void) { + sceTouchDisableTouchForce(SCE_TOUCH_PORT_FRONT); + sceTouchDisableTouchForce(SCE_TOUCH_PORT_BACK); +} + +void psp2PollTouch(void) { + int finger_id = 0; + + memcpy(touch_old, touch, sizeof(touch_old)); + + for(int port = 0; port < SCE_TOUCH_PORT_MAX_NUM; port++) { + if ((psp_indirect_touch && port == SCE_TOUCH_PORT_FRONT) || (psp_rear_touch && port == SCE_TOUCH_PORT_BACK)) { + sceTouchPeek(port, &touch[port], 1); + psp2FinishSimulatedMouseClicks(port, touch[port].timeStamp / 1000); + if (touch[port].reportNum > 0) { + for (int i = 0; i < touch[port].reportNum; i++) { + // adjust coordinates and forces to return normalized values + // for the front, screen area is used as a reference (for direct touch) + // e.g. touch_x = 1.0 corresponds to screen_x = 960 + // for the back panel, the active touch area is used as reference + float x = 0; + float y = 0; + psp2ConvertTouchXYToSDLXY(&x, &y, touch[port].report[i].x, touch[port].report[i].y, port); + finger_id = touch[port].report[i].id; + + // Send an initial touch if finger hasn't been down + bool hasBeenDown = false; + int j = 0; + if (touch_old[port].reportNum > 0) { + for (j = 0; j < touch_old[port].reportNum; j++) { + if (touch_old[port].report[j].id == touch[port].report[i].id ) { + hasBeenDown = true; + break; + } + } + } + if (!hasBeenDown) { + TouchEvent ev; + ev.type = FINGERDOWN; + ev.tfinger.timestamp = touch[port].timeStamp / 1000; + ev.tfinger.touchId = port; + ev.tfinger.fingerId = finger_id; + ev.tfinger.x = x; + ev.tfinger.y = y; + psp2ProcessTouchEvent(&ev); + } else { + // If finger moved, send motion event instead + if (touch_old[port].report[j].x != touch[port].report[i].x || + touch_old[port].report[j].y != touch[port].report[i].y) { + float oldx = 0; + float oldy = 0; + psp2ConvertTouchXYToSDLXY(&oldx, &oldy, touch_old[port].report[j].x, touch_old[port].report[j].y, port); + TouchEvent ev; + ev.type = FINGERMOTION; + ev.tfinger.timestamp = touch[port].timeStamp / 1000; + ev.tfinger.touchId = port; + ev.tfinger.fingerId = finger_id; + ev.tfinger.x = x; + ev.tfinger.y = y; + ev.tfinger.dx = x - oldx; + ev.tfinger.dy = y - oldy; + psp2ProcessTouchEvent(&ev); + } + } + } + } + // some fingers might have been let go + if (touch_old[port].reportNum > 0) { + for (int i = 0; i < touch_old[port].reportNum; i++) { + int finger_up = 1; + if (touch[port].reportNum > 0) { + for (int j = 0; j < touch[port].reportNum; j++) { + if (touch[port].report[j].id == touch_old[port].report[i].id ) { + finger_up = 0; + } + } + } + if (finger_up == 1) { + float x = 0; + float y = 0; + psp2ConvertTouchXYToSDLXY(&x, &y, touch_old[port].report[i].x, touch_old[port].report[i].y, port); + finger_id = touch_old[port].report[i].id; + // Finger released from screen + TouchEvent ev; + ev.type = FINGERUP; + ev.tfinger.timestamp = touch[port].timeStamp / 1000; + ev.tfinger.touchId = port; + ev.tfinger.fingerId = finger_id; + ev.tfinger.x = x; + ev.tfinger.y = y; + psp2ProcessTouchEvent(&ev); + } + } + } + } + } +} + +void psp2ConvertTouchXYToSDLXY(float *sdl_x, float *sdl_y, int vita_x, int vita_y, int port) { + float x = 0; + float y = 0; + if (port == SCE_TOUCH_PORT_FRONT) { + x = (vita_x - panelinfo[port].minDispX) / dispWidth[port]; + y = (vita_y - panelinfo[port].minDispY) / dispHeight[port]; + } else { + x = (vita_x - panelinfo[port].minAaX) / aAWidth[port]; + y = (vita_y - panelinfo[port].minAaY) / aAHeight[port]; + } + if (x < 0.0) { + x = 0.0; + } else if (x > 1.0) { + x = 1.0; + } + if (y < 0.0) { + y = 0.0; + } else if (y > 1.0) { + y = 1.0; + } + *sdl_x = x; + *sdl_y = y; +} + +void psp2ProcessTouchEvent(TouchEvent *event) { + // Supported touch gestures: + // left mouse click: single finger short tap + // right mouse click: second finger short tap while first finger is still down + // pointer motion: single finger drag + // drag and drop: dual finger drag + if (event->type == FINGERDOWN || event->type == FINGERUP || event->type == FINGERMOTION) { + // front (0) or back (1) panel + int port = event->tfinger.touchId; + if (port >= 0 && port < SCE_TOUCH_PORT_MAX_NUM) { + switch (event->type) { + case FINGERDOWN: + psp2ProcessFingerDown(event); + break; + case FINGERUP: + psp2ProcessFingerUp(event); + break; + case FINGERMOTION: + psp2ProcessFingerMotion(event); + break; + } + } + } +} + +void psp2ProcessFingerDown(TouchEvent *event) { + // front (0) or back (1) panel + int port = event->tfinger.touchId; + // id (for multitouch) + int id = event->tfinger.fingerId; + + // make sure each finger is not reported down multiple times + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id == id) { + _finger[port][i].id = -1; + } + } + + // we need the timestamps to decide later if the user performed a short tap (click) + // or a long tap (drag) + // we also need the last coordinates for each finger to keep track of dragging + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id == -1) { + _finger[port][i].id = id; + _finger[port][i].timeLastDown = event->tfinger.timestamp; + break; + } + } +} + +void psp2ProcessFingerUp(TouchEvent *event) { + // front (0) or back (1) panel + int port = event->tfinger.touchId; + // id (for multitouch) + int id = event->tfinger.fingerId; + + // find out how many fingers were down before this event + int numFingersDown = 0; + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id >= 0) { + numFingersDown++; + } + } + + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id == id) { + _finger[port][i].id = -1; + if (!_multiFingerDragging[port]) { + if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= MAX_TAP_TIME) { + // short (tfinger.timestamp; + } else if (numFingersDown == 1) { + if (port == 0 && !psp_indirect_touch) { + // this direct touch branch is disabled via a check in video_psp.cpp for now + // because direct touch is already implemented nicely there + int x, y; + ADBSetRelMouseMode(false); + psp2ConvertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y); + ADBMouseMoved(x, y); + } + simulatedButton = SDL_BUTTON_LEFT; + // need to raise the button later + _simulatedClickStartTime[port][0] = event->tfinger.timestamp; + } + ADBMouseDown(simulatedButton); + } + } + } else if (numFingersDown == 1) { + // when dragging, and the last finger is lifted, the drag is over + Uint8 simulatedButton = 0; + if (_multiFingerDragging[port] == DRAG_THREE_FINGER) { + simulatedButton = SDL_BUTTON_RIGHT; + } + else { + simulatedButton = SDL_BUTTON_LEFT; + } + ADBMouseUp(simulatedButton); + _multiFingerDragging[port] = DRAG_NONE; + } + } + } +} + +void psp2ProcessFingerMotion(TouchEvent *event) { + // front (0) or back (1) panel + int port = event->tfinger.touchId; + // id (for multitouch) + int id = event->tfinger.fingerId; + + // find out how many fingers were down before this event + int numFingersDown = 0; + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id >= 0) { + numFingersDown++; + } + } + + if (numFingersDown >= 1) { + // If we are starting a multi-finger drag, start holding down the mouse button + if (numFingersDown >= 2) { + if (!_multiFingerDragging[port]) { + // only start a multi-finger drag if at least two fingers have been down long enough + int numFingersDownLong = 0; + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id >= 0) { + if (event->tfinger.timestamp - _finger[port][i].timeLastDown > MAX_TAP_TIME) { + numFingersDownLong++; + } + } + } + if (numFingersDownLong >= 2) { + Uint8 simulatedButton = 0; + if (numFingersDownLong == 2) { + simulatedButton = SDL_BUTTON_LEFT; + _multiFingerDragging[port] = DRAG_TWO_FINGER; + } else { + simulatedButton = SDL_BUTTON_RIGHT; + _multiFingerDragging[port] = DRAG_THREE_FINGER; + } + + ADBMouseDown(simulatedButton); + } + } + } + + //check if this is the "oldest" finger down (or the only finger down), otherwise it will not affect mouse motion + bool updatePointer = true; + if (numFingersDown > 1) { + for (int i = 0; i < MAX_NUM_FINGERS; i++) { + if (_finger[port][i].id == id) { + for (int j = 0; j < MAX_NUM_FINGERS; j++) { + if (_finger[port][j].id >= 0 && (i != j) ) { + if (_finger[port][j].timeLastDown < _finger[port][i].timeLastDown) { + updatePointer = false; + } + } + } + } + } + } + if (updatePointer) { + if (port == 0 && !psp_indirect_touch) { + // this direct touch branch is disabled via a check in video_psp.cpp for now + // because direct touch is already implemented nicely there + ADBSetRelMouseMode(false); + int x, y; + psp2ConvertTouchXYToGameXY(event->tfinger.x, event->tfinger.y, &x, &y); + ADBMouseMoved(x, y); + } else { + ADBSetRelMouseMode(true); + // for relative mode, use the pointer speed setting + int dx = event->tfinger.dx * 960.0 * 256 * psp_pointer_speed_factor; + int dy = event->tfinger.dy * 544.0 * 256 * psp_pointer_speed_factor; + hires_dx += dx; + hires_dy += dy; + ADBMouseMoved(hires_dx / 256, hires_dy / 256); + hires_dx %= 256; + hires_dy %= 256; + } + } + } +} + + +void psp2ConvertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY) { + //map to display + float x = touchX * 960.0; + float y = touchY * 544.0; + *gameX = (x - ((960.0 - psp_screen_x*scale_x)/2)) / scale_x; + *gameY = y / scale_y; +} + +void psp2FinishSimulatedMouseClicks(int port, SceUInt64 currentTime) { + for (int i = 0; i < 2; i++) { + if (_simulatedClickStartTime[port][i] != 0) { + if (currentTime - _simulatedClickStartTime[port][i] >= SIMULATED_CLICK_DURATION) { + int simulatedButton; + if (i == 0) { + simulatedButton = SDL_BUTTON_LEFT; + } else { + simulatedButton = SDL_BUTTON_RIGHT; + } + ADBMouseUp(simulatedButton); + + _simulatedClickStartTime[port][i] = 0; + } + } + } +} diff --git a/src/PSP2/psp2_touch.h b/src/PSP2/psp2_touch.h new file mode 100644 index 0000000..130851b --- /dev/null +++ b/src/PSP2/psp2_touch.h @@ -0,0 +1,51 @@ +// +// Created by rsn8887 on 02/05/18. + +#ifndef BASILISKII_PSP2_TOUCH_H +#define BASILISKII_PSP2_TOUCH_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum TouchEventType { + FINGERDOWN, + FINGERUP, + FINGERMOTION, +} TouchEventType; + +typedef struct { + TouchEventType type; + SceUInt64 timestamp; + int touchId; + int fingerId; + float x; + float y; + float dx; + float dy; +} FingerType; + +typedef struct { + TouchEventType type; + FingerType tfinger; +} TouchEvent; + +/* Touch functions */ +void psp2InitTouch(void); +void psp2QuitTouch(void); +void psp2PollTouch(void); +void psp2ProcessTouchEvent(TouchEvent *event); +void psp2ProcessFingerDown(TouchEvent *event); +void psp2ProcessFingerUp(TouchEvent *event); +void psp2ProcessFingerMotion(TouchEvent *event); +void psp2ConvertTouchXYToSDLXY(float *sdl_x, float *sdl_y, int vita_x, int vita_y, int port); +void psp2ConvertTouchXYToGameXY(float touchX, float touchY, int *gameX, int *gameY); +void psp2FinishSimulatedMouseClicks(int port, SceUInt64 currentTime); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/PSP2/user_strings_psp.cpp b/src/PSP2/user_strings_psp.cpp index 39ae580..0cd80fe 100644 --- a/src/PSP2/user_strings_psp.cpp +++ b/src/PSP2/user_strings_psp.cpp @@ -62,6 +62,10 @@ user_string_def platform_strings[] = { {STR_PSP_DISPLAY_ASPECT, "Display Aspect Ratio"}, {STR_PSP_OVERSCAN, "Draw in Overscan Region"}, {STR_PSP_RELAXED_60HZ, "Relaxed timing for 60 Hz IRQ"}, + {STR_PSP_REAR_TOUCH, "Enable rear touch panel"}, + {STR_PSP_INDIRECT_TOUCH, "Use indirect front touch"}, + {STR_PSP_POINTER_SPEED, "Mouse pointer speed"}, + {STR_PSP_ANALOG_DEADZONE, "Analog joystick deadzone"}, {STR_TICK_THREAD_ERR, "Cannot create thread for ticks."}, {STR_NO_NET_THREAD_ERR, "Cannot create network thread."}, diff --git a/src/PSP2/user_strings_psp.h b/src/PSP2/user_strings_psp.h index c7c8ceb..ca94e61 100644 --- a/src/PSP2/user_strings_psp.h +++ b/src/PSP2/user_strings_psp.h @@ -47,6 +47,11 @@ enum { STR_PSP_DISPLAY_ASPECT, STR_PSP_OVERSCAN, STR_PSP_RELAXED_60HZ, + STR_PSP_REAR_TOUCH, + STR_PSP_INDIRECT_TOUCH, + STR_PSP_POINTER_SPEED, + STR_PSP_ANALOG_DEADZONE, + STR_TICK_THREAD_ERR, STR_NO_NET_THREAD_ERR, diff --git a/src/PSP2/video_psp.cpp b/src/PSP2/video_psp.cpp index e79cfdb..2caf781 100644 --- a/src/PSP2/video_psp.cpp +++ b/src/PSP2/video_psp.cpp @@ -41,6 +41,8 @@ #include "user_strings.h" #include "video.h" #include "video_defs.h" +#include "psp2_touch.h" +#include "math.h" #define DEBUG 0 #include "debug.h" @@ -77,7 +79,13 @@ vita2d_texture *screen, *screen_16; unsigned int *screen_data; unsigned short *screen_16_data; +static int hires_dx; +static int hires_dy; static int32 frame_skip; // Prefs items +bool psp_rear_touch; +bool psp_indirect_touch; +float psp_pointer_speed_factor; +int psp_analog_dead; bool refresh_okay = false; @@ -91,7 +99,7 @@ static uint32 DISP_BUF = 0; static uint8 *the_buffer = NULL; // Mac frame buffer (where MacOS draws into) static uint32 the_buffer_size; // Size of allocated the_buffer -static int32 psp_screen_x = 640; +int32 psp_screen_x = 640; static int32 psp_screen_y = 480; static int32 psp_screen_d = VDEPTH_8BIT; @@ -489,6 +497,11 @@ bool VideoInit(bool classic) // Read prefs frame_skip = PrefsFindInt32("frameskip"); psp_lcd_aspect = PrefsFindInt32("pspdar"); + psp_rear_touch = PrefsFindBool("reartouch"); + psp_indirect_touch = PrefsFindBool("indirecttouch"); + psp_pointer_speed_factor = PrefsFindInt32("pointerspeed") * 0.25 + 0.25; + psp_analog_dead = PrefsFindInt32("analogdeadzone") * 1600 + 1600; + // set PSP screen variables BUF_WIDTH = 768; SCR_WIDTH = 960; @@ -1161,6 +1174,30 @@ void handle_menu(SceCtrlData pad) } } +/* + * Rescale Analog joystick axes + */ + +void rescaleAnalog(int *x, int *y, int dead) { + //radial and scaled deadzone + //http://www.third-helix.com/2013/04/12/doing-thumbstick-dead-zones-right.html + + float analogX = *x; + float analogY = *y; + float deadZone = dead; + float maximum = 32768.0f; + float magnitude = sqrt(analogX * analogX + analogY * analogY); + if (magnitude >= deadZone) + { + float scalingFactor = maximum / magnitude * (magnitude - deadZone) / (maximum - deadZone); + *x = (int) analogX * scalingFactor; + *y = (int) analogY * scalingFactor; + } else { + *x = 0; + *y = 0; + } +} + /* * Mac VBL interrupt */ @@ -1243,40 +1280,52 @@ void VideoInterrupt(void) // process inputs if (!input_mode && !show_menu) { - if (touch.reportNum <= 0 && mouseClickedTouch) - { - mouseClickedTouch = false; - initialTouch = true; - ADBMouseUp(0); - } - else if (touch.reportNum > 0) { - ADBSetRelMouseMode(false); + // touch + if (psp_indirect_touch || psp_rear_touch) { + psp2PollTouch(); + } + if (!psp_indirect_touch) { + if (touch.reportNum <= 0 && mouseClickedTouch) + { + mouseClickedTouch = false; + initialTouch = true; + ADBMouseUp(0); + } + else if (touch.reportNum > 0) { + ADBSetRelMouseMode(false); - int x = lerp(touch.report[0].x, 1920, 960); - int y =lerp(touch.report[0].y, 1088, 544); + int x = lerp(touch.report[0].x, 1920, 960); + int y =lerp(touch.report[0].y, 1088, 544); - //map to display - int display_x = (x - ((960.0 - psp_screen_x*scale_x)/2)) / scale_x; - int display_y = y / scale_y; + //map to display + int display_x = (x - ((960.0 - psp_screen_x*scale_x)/2)) / scale_x; + int display_y = y / scale_y; - ADBMouseMoved(display_x, display_y); + ADBMouseMoved(display_x, display_y); - if (!mouseClickedTouch && initialTouch) - { - initialTouch = false; - } - else if (!mouseClickedTouch) - { - mouseClickedTouch = true; - ADBMouseDown(0); + if (!mouseClickedTouch && initialTouch) + { + initialTouch = false; + } + else if (!mouseClickedTouch) + { + mouseClickedTouch = true; + ADBMouseDown(0); + } } } - + // mouse - if (abs(pad.lx - 128) >= 32 || abs(pad.ly - 128) >= 32) - { + int x = (pad.lx - 128) * 256; + int y = (pad.ly - 128) * 256; + rescaleAnalog(&x, &y, psp_analog_dead); + hires_dx += (int) (x * psp_pointer_speed_factor); + hires_dy += (int) (y * psp_pointer_speed_factor); + if (hires_dx != 0 || hires_dy != 0) { ADBSetRelMouseMode(true); - ADBMouseMoved(stick[((pad.lx - 128) >> 4) + 8], stick[((pad.ly - 128) >> 4) + 8]); + ADBMouseMoved(hires_dx / 4096, hires_dy / 4096); + hires_dx %= 4096; + hires_dy %= 4096; } for (int i=0; i