changeset 915:9e882eca717e

Initial support for relative mouse mode and skeleton of support for capture mode. Avoid mouse position overflow in absolute mode. Allow absolute mode to be set by ROM DB.
author Michael Pavone <pavone@retrodev.com>
date Tue, 15 Dec 2015 20:01:50 -0800
parents 28ec32e720b2
children 20c464dbae8f
files io.c io.h render.h render_sdl.c rom.db romdb.c romdb.h
diffstat 7 files changed, 64 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/io.c	Mon Dec 14 19:36:01 2015 -0800
+++ b/io.c	Tue Dec 15 20:01:50 2015 -0800
@@ -68,6 +68,13 @@
 	UI_EXIT
 } ui_action;
 
+typedef enum {
+	MOUSE_ABSOLUTE, //really only useful for menu ROM
+	MOUSE_RELATIVE, //for full screen
+	MOUSE_CAPTURE   //for windowed mode
+} mouse_modes;
+
+
 typedef struct {
 	io_port *port;
 	uint8_t bind_type;
@@ -85,7 +92,6 @@
 	io_port    *motion_port;
 	keybinding buttons[MAX_MOUSE_BUTTONS];
 	uint8_t    bind_type;
-	uint8_t    motion_mode;
 } mousebinding;
 
 keybinding * bindings[0x10000];
@@ -93,6 +99,7 @@
 joydpad * joydpads[MAX_JOYSTICKS];
 mousebinding mice[MAX_MICE];
 const uint8_t dpadbits[] = {RENDER_DPAD_UP, RENDER_DPAD_DOWN, RENDER_DPAD_LEFT, RENDER_DPAD_RIGHT};
+mouse_modes mouse_mode;
 
 void bind_key(int keycode, uint8_t bind_type, uint8_t subtype_a, uint8_t subtype_b, uint8_t value)
 {
@@ -406,17 +413,30 @@
 	handle_binding_up(binding);
 }
 
-void handle_mouse_moved(int mouse, uint16_t x, uint16_t y)
+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay)
 {
 	if (mouse >= MAX_MICE || !mice[mouse].motion_port) {
 		return;
 	}
 	//TODO: relative mode
-	float scale_x = 640.0 / ((float)render_width());
-	float scale_y = 480.0 / ((float)render_height());
-	float scale = scale_x > scale_y ? scale_y : scale_x;
-	mice[mouse].motion_port->device.mouse.cur_x = x * scale_x;
-	mice[mouse].motion_port->device.mouse.cur_y = y * scale_y;
+	switch(mouse_mode)
+	{
+	case MOUSE_ABSOLUTE: {
+		float scale_x = 640.0 / ((float)render_width());
+		float scale_y = 480.0 / ((float)render_height());
+		float scale = scale_x > scale_y ? scale_y : scale_x;
+		mice[mouse].motion_port->device.mouse.cur_x = x * scale_x;
+		mice[mouse].motion_port->device.mouse.cur_y = y * scale_y;
+		break;
+	}
+	case MOUSE_RELATIVE: {
+		mice[mouse].motion_port->device.mouse.cur_x += deltax;
+		mice[mouse].motion_port->device.mouse.cur_y += deltay;
+		break;
+	}
+	case MOUSE_CAPTURE: {
+	}
+	}
 }
 
 int parse_binding_target(char * target, tern_node * padbuttons, tern_node *mousebuttons, int * ui_out, int * padnum_out, int * padbutton_out)
@@ -658,6 +678,17 @@
 	process_device(io_2, ports+1);
 	process_device(io_ext, ports+2);
 
+	if (rom->mouse_mode && !strcmp(rom->mouse_mode, "absolute")) {
+		mouse_mode = MOUSE_ABSOLUTE;
+	} else {
+		if (render_fullscreen()) {
+			mouse_mode = MOUSE_RELATIVE;
+			render_relative_mouse(1);
+		} else {
+			mouse_mode = MOUSE_CAPTURE;
+		}
+	}
+
 	for (int i = 0; i < 3; i++)
 	{
 #ifndef _WIN32
@@ -1013,6 +1044,17 @@
 		if (port->device.mouse.tr_counter == 3) {
 			port->device.mouse.latched_x = port->device.mouse.cur_x;
 			port->device.mouse.latched_y = port->device.mouse.cur_y;
+			if (mouse_mode == MOUSE_ABSOLUTE) {
+				//avoid overflow in absolute mode
+				int deltax = port->device.mouse.latched_x - port->device.mouse.last_read_x;
+				if (abs(deltax) > 255) {
+					port->device.mouse.latched_x = port->device.mouse.last_read_x + (deltax > 0 ? 255 : -255);
+				}
+				int deltay = port->device.mouse.latched_y - port->device.mouse.last_read_y;
+				if (abs(deltay) > 255) {
+					port->device.mouse.latched_y = port->device.mouse.last_read_y + (deltay > 0 ? 255 : -255);
+				}
+			}
 		}
 	}
 }
--- a/io.h	Mon Dec 14 19:36:01 2015 -0800
+++ b/io.h	Tue Dec 15 20:01:50 2015 -0800
@@ -79,7 +79,7 @@
 void handle_joydown(int joystick, int button);
 void handle_joyup(int joystick, int button);
 void handle_joy_dpad(int joystick, int dpad, uint8_t state);
-void handle_mouse_moved(int mouse, uint16_t x, uint16_t y);
+void handle_mouse_moved(int mouse, uint16_t x, uint16_t y, int16_t deltax, int16_t deltay);
 void handle_mousedown(int mouse, int button);
 void handle_mouseup(int mouse, int button);
 
--- a/render.h	Mon Dec 14 19:36:01 2015 -0800
+++ b/render.h	Tue Dec 15 20:01:50 2015 -0800
@@ -23,6 +23,7 @@
 #define RENDER_DPAD_DOWN  SDL_HAT_DOWN
 #define RENDER_DPAD_LEFT  SDL_HAT_LEFT
 #define RENDER_DPAD_RIGHT SDL_HAT_RIGHT
+#define render_relative_mouse SDL_SetRelativeMouseMode
 
 #define MAX_JOYSTICKS 8
 #define MAX_MICE 8
@@ -59,6 +60,7 @@
 int render_num_joysticks();
 int render_width();
 int render_height();
+int render_fullscreen();
 void process_events();
 void render_errorbox(char *title, char *message);
 void render_warnbox(char *title, char *message);
--- a/render_sdl.c	Mon Dec 14 19:36:01 2015 -0800
+++ b/render_sdl.c	Tue Dec 15 20:01:50 2015 -0800
@@ -22,7 +22,7 @@
 SDL_Rect      main_clip;
 SDL_GLContext *main_context;
 
-int main_width, main_height;
+int main_width, main_height, is_fullscreen;
 
 uint8_t render_dbg = 0;
 uint8_t debug_pal = 0;
@@ -108,6 +108,11 @@
 	return main_height;
 }
 
+int render_fullscreen()
+{
+	return is_fullscreen;
+}
+
 uint32_t render_map_color(uint8_t r, uint8_t g, uint8_t b)
 {
 	return 255 << 24 | r << 16 | g << 8 | b;
@@ -265,6 +270,7 @@
 	}
 	main_width = width;
 	main_height = height;
+	is_fullscreen = fullscreen;
 
 	render_gl = 0;
 
@@ -559,7 +565,7 @@
 		handle_joy_dpad(event->jbutton.which, event->jhat.hat, event->jhat.value);
 		break;
 	case SDL_MOUSEMOTION:
-		handle_mouse_moved(event->motion.which, event->motion.x, event->motion.y);
+		handle_mouse_moved(event->motion.which, event->motion.x, event->motion.y, event->motion.xrel, event->motion.yrel);
 		break;
 	case SDL_MOUSEBUTTONDOWN:
 		handle_mousedown(event->button.which, event->button.button);
--- a/rom.db	Mon Dec 14 19:36:01 2015 -0800
+++ b/rom.db	Tue Dec 15 20:01:50 2015 -0800
@@ -375,4 +375,5 @@
 		2 mouse.1
 		ext none
 	}
+	mouse_mode absolute
 }
--- a/romdb.c	Mon Dec 14 19:36:01 2015 -0800
+++ b/romdb.c	Tue Dec 15 20:01:50 2015 -0800
@@ -551,7 +551,7 @@
 	info.name = get_header_name(rom);
 	info.regions = get_header_regions(rom);
 	add_memmap_header(&info, rom, rom_size, base_map, base_chunks);
-	info.port1_override = info.port2_override = info.ext_override = NULL;
+	info.port1_override = info.port2_override = info.ext_override = info.mouse_mode = NULL;
 	return info;
 }
 
@@ -851,6 +851,7 @@
 	} else {
 		info.port1_override = info.port2_override = info.ext_override = NULL;
 	}
+	info.mouse_mode = tern_find_ptr(entry, "mouse_mode");
 
 	return info;
 }
--- a/romdb.h	Mon Dec 14 19:36:01 2015 -0800
+++ b/romdb.h	Tue Dec 15 20:01:50 2015 -0800
@@ -43,6 +43,7 @@
 	char          *port1_override;
 	char          *port2_override;
 	char          *ext_override;
+	char          *mouse_mode;
 	uint32_t      num_eeprom;
 	uint32_t      map_chunks;
 	uint32_t      save_size;