aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backends/events/psp2sdl/psp2sdl-events.cpp296
-rw-r--r--backends/events/psp2sdl/psp2sdl-events.h13
-rw-r--r--backends/platform/sdl/psp2/psp2.cpp27
-rw-r--r--backends/platform/sdl/psp2/psp2.h14
4 files changed, 274 insertions, 76 deletions
diff --git a/backends/events/psp2sdl/psp2sdl-events.cpp b/backends/events/psp2sdl/psp2sdl-events.cpp
index b774b9eda1..81f057f2e0 100644
--- a/backends/events/psp2sdl/psp2sdl-events.cpp
+++ b/backends/events/psp2sdl/psp2sdl-events.cpp
@@ -25,6 +25,7 @@
#if defined(PSP2)
#include <psp2/kernel/processmgr.h>
+#include <psp2/touch.h>
#include "backends/platform/sdl/psp2/psp2.h"
#include "backends/events/psp2sdl/psp2sdl-events.h"
#include "backends/platform/sdl/sdl.h"
@@ -38,97 +39,256 @@
PSP2EventSource::PSP2EventSource() {
for (int i = 0; i < SCE_TOUCH_PORT_MAX_NUM; i++) {
- for (int j = 0; j < 2; j++) {
+ for (int j = 0; j < MAX_NUM_FINGERS; j++) {
_finger[i][j].id = -1;
}
}
+ // need specs of front panel for accurate direct touch
+ sceTouchGetPanelInfo(0, &panelInfo);
}
void PSP2EventSource::preprocessEvents(SDL_Event *event) {
- // prevent suspend (scummvm games contains a lot of cutscenes..)
+ // prevent suspend (scummvm games contain a lot of cutscenes..)
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_AUTO_SUSPEND);
sceKernelPowerTick(SCE_KERNEL_POWER_TICK_DISABLE_OLED_OFF);
- // left mouse click gesture: single finger short tap
- // right mouse click gesture: second finger short tap while first finger is still down
+ // 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
if (event->type == SDL_FINGERDOWN || event->type == SDL_FINGERUP || event->type == SDL_FINGERMOTION) {
- // front (0) or back (1) panel?
+ // front (0) or back (1) panel
SDL_TouchID port = event->tfinger.touchId;
- // which touchID (for multitouch)?
- SDL_FingerID id = event->tfinger.fingerId;
-
- int numFingersDown = 0;
- for (int j = 0; j < 2; j++) {
- if (_finger[port][j].id >= 0) {
- numFingersDown++;
+ if (port < SCE_TOUCH_PORT_MAX_NUM && port >= 0) {
+ switch (event->type) {
+ case SDL_FINGERDOWN:
+ preprocessFingerDown(event);
+ break;
+ case SDL_FINGERUP:
+ preprocessFingerUp(event);
+ break;
+ case SDL_FINGERMOTION:
+ preprocessFingerMotion(event);
+ break;
}
}
+ }
+}
- if (port < SCE_TOUCH_PORT_MAX_NUM && port >= 0) {
- if (event->type == SDL_FINGERDOWN) {
- for (int i = 0; i < 2; i++) {
- if (_finger[port][i].id == -1 || i == 1) {
- _finger[port][i].id = id;
- _finger[port][i].timeLastDown = event->tfinger.timestamp;
- break;
- }
- }
- } else if (event->type == SDL_FINGERUP) {
- // 250 ms long tap is interpreted as right/left mouse click depending on number of fingers down
- for (int i = 0; i < 2; i++) {
- if (_finger[port][i].id == id) {
-
- _finger[port][i].id = -1;
-
- if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= 250) {
- if (numFingersDown == 2 || numFingersDown == 1) {
- Uint8 simulatedButton = 0;
- if (numFingersDown == 2) {
- simulatedButton = SDL_BUTTON_RIGHT;
- } else if (numFingersDown == 1) {
- simulatedButton = SDL_BUTTON_LEFT;
- }
-
- // simulate button click due to tap gesture
- event->type = SDL_MOUSEBUTTONDOWN;
- event->button.button = simulatedButton;
- event->button.x = _km.x / MULTIPLIER;
- event->button.y = _km.y / MULTIPLIER;
-
- SDL_Event ev;
- ev.type = SDL_MOUSEBUTTONUP;
- ev.button.button = simulatedButton;
- ev.button.x = _km.x / MULTIPLIER;
- ev.button.y = _km.y / MULTIPLIER;
- SDL_PushEvent(&ev);
- }
- }
+void PSP2EventSource::preprocessFingerDown(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ // id (for multitouch)
+ SDL_FingerID 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 == -1) {
+ _finger[port][i].id = id;
+ _finger[port][i].timeLastDown = event->tfinger.timestamp;
+ break;
+ }
+ }
+}
+
+void PSP2EventSource::preprocessFingerUp(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+ // id (for multitouch)
+ SDL_FingerID 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++;
+ }
+ }
+
+ int x = _km.x / MULTIPLIER;
+ int y = _km.y / MULTIPLIER;
+
+ if (!ConfMan.getBool("touchpad_mouse_mode") && port == 0) {
+ convertTouchToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ }
+
+ for (int i = 0; i < MAX_NUM_FINGERS; i++) {
+ if (_finger[port][i].id == id) {
+ _finger[port][i].id = -1;
+ if ((event->tfinger.timestamp - _finger[port][i].timeLastDown) <= 250) {
+ // short (<250 ms) tap is interpreted as right/left mouse click depending on # fingers already down
+ if (numFingersDown == 2 || numFingersDown == 1) {
+ Uint8 simulatedButton = 0;
+ if (numFingersDown == 2) {
+ simulatedButton = SDL_BUTTON_RIGHT;
+ } else if (numFingersDown == 1) {
+ simulatedButton = SDL_BUTTON_LEFT;
}
- }
- } else if (event->type == SDL_FINGERMOTION && numFingersDown == 1) {
- // convert touch events to relative mouse pointer events
- Sint32 mouse_x = _km.x / MULTIPLIER + (event->tfinger.dx * _km.x_max);
- Sint32 mouse_y = _km.y / MULTIPLIER + (event->tfinger.dy * _km.y_max);
+ event->type = SDL_MOUSEBUTTONDOWN;
+ event->button.button = simulatedButton;
+ event->button.x = x;
+ event->button.y = y;
- if (mouse_x > _km.x_max) {
- mouse_x = _km.x_max;
- } else if (mouse_x < 0) {
- mouse_x = 0;
- }
- if (mouse_y > _km.y_max) {
- mouse_y = _km.y_max;
- } else if (mouse_y < 0) {
- mouse_y = 0;
+ SDL_Event ev;
+ ev.type = SDL_MOUSEBUTTONUP;
+ ev.button.button = simulatedButton;
+ ev.button.x = x;
+ ev.button.y = y;
+ SDL_PushEvent(&ev);
}
+ }
+ }
+ }
+}
+
+void PSP2EventSource::preprocessFingerMotion(SDL_Event *event) {
+ // front (0) or back (1) panel
+ SDL_TouchID port = event->tfinger.touchId;
+
+ // 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) {
- event->type = SDL_MOUSEMOTION;
- event->motion.x = mouse_x;
- event->motion.y = mouse_y;
+ int x = _km.x / MULTIPLIER;;
+ int y = _km.y / MULTIPLIER;
+
+ if (!ConfMan.getBool("touchpad_mouse_mode") && port == 0) {
+ convertTouchToGameXY(event->tfinger.x, event->tfinger.y, &x, &y);
+ } else {
+ // for relative mode, use the pointer speed setting
+ float speedFactor = 1.0;
+
+ switch (ConfMan.getInt("kbdmouse_speed")) {
+ // 0.25 keyboard pointer speed
+ case 0:
+ speedFactor = 0.25;
+ break;
+ // 0.5 speed
+ case 1:
+ speedFactor = 0.5;
+ break;
+ // 0.75 speed
+ case 2:
+ speedFactor = 0.75;
+ break;
+ // 1.0 speed
+ case 3:
+ speedFactor = 1.0;
+ break;
+ // 1.25 speed
+ case 4:
+ speedFactor = 1.25;
+ break;
+ // 1.5 speed
+ case 5:
+ speedFactor = 1.5;
+ break;
+ // 1.75 speed
+ case 6:
+ speedFactor = 1.75;
+ break;
+ // 2.0 speed
+ case 7:
+ speedFactor = 2.0;
+ break;
+ default:
+ speedFactor = 1.0;
}
+
+ // convert touch events to relative mouse pointer events
+ // Whenever an SDL_event involving the mouse is processed,
+ // _km.x/y are truncated from subpixel precision to regular pixel precision.
+ // Therefore, there's no need here to deal with subpixel precision in _km.x/y.
+ x = (_km.x / MULTIPLIER + (event->tfinger.dx * 1.25 * speedFactor * _km.x_max));
+ y = (_km.y / MULTIPLIER + (event->tfinger.dy * 1.25 * speedFactor * _km.y_max));
+ }
+
+ if (x > _km.x_max) {
+ x = _km.x_max;
+ } else if (x < 0) {
+ x = 0;
+ }
+ if (y > _km.y_max) {
+ y = _km.y_max;
+ } else if (y < 0) {
+ y = 0;
}
+
+ event->type = SDL_MOUSEMOTION;
+ event->motion.x = x;
+ event->motion.y = y;
+ }
+}
+
+void PSP2EventSource::convertTouchToGameXY(float touchX, float touchY, int *gameX, int *gameY) {
+ // Find touch coordinates in terms of Vita screen pixels
+ float aaTouchX = touchX * (panelInfo.maxAaX - panelInfo.minAaX) + panelInfo.minAaX;
+ float aaTouchY = touchY * (panelInfo.maxAaY - panelInfo.minAaY) + panelInfo.minAaY;
+
+ float screenTouchX = (aaTouchX - panelInfo.minDispX) * 960 / panelInfo.maxDispX;
+ float screenTouchY = (aaTouchY - panelInfo.minDispY) * 544 / panelInfo.maxDispY;
+
+ // Find four corners of game screen in Vita screen coordinates
+ // This depends on the fullscreen and aspect ratio correction settings (at least on Vita)
+
+ float gameXMin = 0;
+ float gameXMax = 0;
+ float gameYMin = 0;
+ float gameYMax = 0;
+ float aspectRatio = 4.0 / 3.0;
+
+ // vertical
+ if (ConfMan.getBool("fullscreen")) {
+ gameYMin = 0.0;
+ gameYMax = 544.0;
+ } else {
+ if (_km.y_max <= 272) {
+ gameYMin = (544.0 - (_km.y_max * 2.0)) / 2.0;
+ gameYMax = 544.0 - gameYMin;
+ } else {
+ gameYMin = (544.0 - (_km.y_max)) / 2.0;
+ gameYMax = 544 - gameYMin;
+ }
+ }
+ // horizontal
+ if (ConfMan.getBool("aspect_ratio")) {
+ aspectRatio = 4.0/3.0;
+ } else {
+ aspectRatio = (float)_km.x_max / (float)_km.y_max;
+ }
+ gameXMin = (960 - (gameYMax - gameYMin) * aspectRatio) / 2.0;
+ gameXMax = 960.0 - gameXMin;
+
+ // find game pixel coordinates corresponding to front panel touch coordinates
+ int x = (screenTouchX - gameXMin) / (gameXMax - gameXMin) * _km.x_max;
+ int y = (screenTouchY - gameYMin) / (gameYMax - gameYMin) * _km.y_max;
+
+ if (x < 0) {
+ x = 0;
+ } else if (x > _km.x_max) {
+ x = _km.x_max;
+ } else if (y < 0) {
+ y = 0;
+ } else if (y > _km.y_max) {
+ y = _km.y_max;
}
+ *gameX = x;
+ *gameY = y;
}
#endif
diff --git a/backends/events/psp2sdl/psp2sdl-events.h b/backends/events/psp2sdl/psp2sdl-events.h
index a71553681a..a4143af157 100644
--- a/backends/events/psp2sdl/psp2sdl-events.h
+++ b/backends/events/psp2sdl/psp2sdl-events.h
@@ -34,11 +34,22 @@ public:
PSP2EventSource();
protected:
void preprocessEvents(SDL_Event *event) override;
+private:
typedef struct {
int id; // -1: no touch
int timeLastDown;
} Touch;
- Touch _finger[SCE_TOUCH_PORT_MAX_NUM][2]; // track only two fingers per panel
+
+ enum {
+ MAX_NUM_FINGERS = 3,
+ }; // track three fingers per panel
+ Touch _finger[SCE_TOUCH_PORT_MAX_NUM][MAX_NUM_FINGERS]; // keep track of finger status
+
+ void preprocessFingerDown(SDL_Event *event);
+ void preprocessFingerUp(SDL_Event *event);
+ void preprocessFingerMotion(SDL_Event *event);
+ void convertTouchToGameXY(float touchX, float touchY, int *gameX, int *gameY);
+ SceTouchPanelInfo panelInfo;
};
#endif /* BACKEND_EVENTS_PSP2_H */
diff --git a/backends/platform/sdl/psp2/psp2.cpp b/backends/platform/sdl/psp2/psp2.cpp
index f959bbaf49..62b0a68320 100644
--- a/backends/platform/sdl/psp2/psp2.cpp
+++ b/backends/platform/sdl/psp2/psp2.cpp
@@ -80,6 +80,7 @@ void OSystem_PSP2::initBackend() {
ConfMan.registerDefault("kbdmouse_speed", 3);
ConfMan.registerDefault("joystick_deadzone", 2);
ConfMan.registerDefault("shader", 0);
+ ConfMan.registerDefault("touchpad_mouse_mode", true);
if (!ConfMan.hasKey("fullscreen")) {
ConfMan.setBool("fullscreen", true);
@@ -96,7 +97,10 @@ void OSystem_PSP2::initBackend() {
if (!ConfMan.hasKey("shader")) {
ConfMan.setInt("shader", 2);
}
-
+ if (!ConfMan.hasKey("touchpad_mouse_mode")) {
+ ConfMan.setBool("touchpad_mouse_mode", false);
+ }
+
// Create the savefile manager
if (_savefileManager == 0)
_savefileManager = new DefaultSaveFileManager("ux0:data/scummvm/saves");
@@ -125,9 +129,30 @@ bool OSystem_PSP2::hasFeature(Feature f) {
return (f == kFeatureKbdMouseSpeed ||
f == kFeatureJoystickDeadzone ||
f == kFeatureShader ||
+ f == kFeatureTouchpadMode ||
OSystem_SDL::hasFeature(f));
}
+void OSystem_PSP2::setFeatureState(Feature f, bool enable) {
+ switch (f) {
+ case kFeatureTouchpadMode:
+ ConfMan.setBool("touchpad_mouse_mode", enable);
+ break;
+ }
+ OSystem_SDL::setFeatureState(f, enable);
+}
+
+bool OSystem_PSP2::getFeatureState(Feature f) {
+ switch (f) {
+ case kFeatureTouchpadMode:
+ return ConfMan.getBool("touchpad_mouse_mode");
+ break;
+ default:
+ return OSystem_SDL::getFeatureState(f);
+ break;
+ }
+}
+
void OSystem_PSP2::logMessage(LogMessageType::Type type, const char *message) {
#if __PSP2_DEBUG__
psp2shell_print(message);
diff --git a/backends/platform/sdl/psp2/psp2.h b/backends/platform/sdl/psp2/psp2.h
index 65d98098be..db9140e4c1 100644
--- a/backends/platform/sdl/psp2/psp2.h
+++ b/backends/platform/sdl/psp2/psp2.h
@@ -34,19 +34,21 @@ public:
OSystem_PSP2(Common::String baseConfigName = "scummvm.ini");
virtual ~OSystem_PSP2() {}
- virtual void init();
- virtual void initBackend();
- virtual bool hasFeature(Feature f);
- virtual void logMessage(LogMessageType::Type type, const char *message);
+ virtual void init() override;
+ virtual void initBackend() override;
+ virtual bool hasFeature(Feature f) override;
+ virtual void setFeatureState(Feature f, bool enable) override;
+ virtual bool getFeatureState(Feature f) override;
+ virtual void logMessage(LogMessageType::Type type, const char *message) override;
protected:
// Base string for creating the default path and filename
// for the configuration file
Common::String _baseConfigName;
- virtual Common::String getDefaultConfigFileName();
+ virtual Common::String getDefaultConfigFileName() override;
- virtual Common::WriteStream *createLogFile();
+ virtual Common::WriteStream *createLogFile() override;
};
#endif