diff options
| -rw-r--r-- | backends/events/psp2sdl/psp2sdl-events.cpp | 296 | ||||
| -rw-r--r-- | backends/events/psp2sdl/psp2sdl-events.h | 13 | ||||
| -rw-r--r-- | backends/platform/sdl/psp2/psp2.cpp | 27 | ||||
| -rw-r--r-- | backends/platform/sdl/psp2/psp2.h | 14 | 
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 | 
