diff -Nur a/core/linux-dist/bimap.h b/core/linux-dist/bimap.h
--- a/core/linux-dist/bimap.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/bimap.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,67 @@
+/* SimpleBimap
+ *
+ * A basic implementation of a bidirectional map that not only allows
+ * you to get a mapped value from a key, but also the other way around.
+ * Deleting elements and other fancy (and not-so-fancy) stuff is not
+ * supported.
+ *
+ * Usage example:
+ * 	SimpleBimap<std::string, std::string> bimap;
+ *  bimap.insert("foo", "bar");
+ *  printf("foo -> %s\n", bimap.get_by_key("foo")->c_str());
+ *  printf("bar <- %s\n", bimap.get_by_value("bar")->c_str());
+ *  if(bimap.get_by_key("somekey") == NULL)
+ *    puts("somekey not found");
+ *
+ * The above example's output:
+ *  foo -> bar
+ *  bar <- foo
+ *  somekey not found
+ */
+#include <cstddef>
+#include <utility>
+#include <map>
+
+template<typename T1, typename T2>
+class SimpleBimap
+{
+	private:
+		typedef typename std::map<T2, T1*> MapA;
+		typedef typename std::map<T1, T2*> MapB;
+		MapA map_a;
+		MapB map_b;
+	public:
+		void insert(const T1& a, const T2& b)
+		{
+			// create first pair
+			typename MapA::iterator iter_a = map_a.insert(std::pair<T2, T1*>(b, NULL)).first;
+			T2* ptr_b = const_cast<T2*>(&(iter_a->first));
+
+			// insert second pair (a, pointer_to_b)
+			typename MapB::iterator iter_b = map_b.insert(std::pair<T1, T2*>(a, ptr_b)).first; 
+
+			// update pointer in map_a to point to a
+			T1* ptr_a = const_cast<T1*>(&(iter_b->first));
+			iter_a->second = ptr_a;
+		}
+
+		const T2* get_by_key(const T1 &a)
+		{
+			typename MapB::iterator it = this->map_b.find(a);
+			if(it != this->map_b.end())
+			{
+				return (it->second);
+			}
+			return NULL;
+		}
+
+		const T1* get_by_value(const T2 &b)
+		{
+			typename MapA::iterator it = this->map_a.find(b);
+			if(it != this->map_a.end())
+			{
+				return (it->second);
+			}
+			return NULL;
+		}
+};
\ No newline at end of file
diff -Nur a/core/linux-dist/evdev.cpp b/core/linux-dist/evdev.cpp
--- a/core/linux-dist/evdev.cpp	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/evdev.cpp	1969-12-31 21:00:00.000000000 -0300
@@ -1,450 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <linux/input.h>
-#include "linux-dist/evdev.h"
-#include "linux-dist/main.h"
-#include "cfg/ini.h"
-#include <vector>
-#include <map>
-#include <dlfcn.h>
-
-#if defined(USE_EVDEV)
-	bool libevdev_tried = false;
-	bool libevdev_available = false;
-	typedef int (*libevdev_func1_t)(int, const char*);
-	typedef const char* (*libevdev_func2_t)(int, int);
-	libevdev_func1_t libevdev_event_code_from_name;
-	libevdev_func2_t libevdev_event_code_get_name;
-
-	void load_libevdev()
-	{
-		if (libevdev_tried)
-		{
-			return;
-		}
-
-		libevdev_tried = true;
-		void* lib_handle = dlopen("libevdev.so", RTLD_NOW);
-
-		bool failed = false;
-
-		if (!lib_handle)
-		{
-			fprintf(stderr, "%s\n", dlerror());
-			failed = true;
-		}
-		else
-		{
-			libevdev_event_code_from_name = reinterpret_cast<libevdev_func1_t>(dlsym(lib_handle, "libevdev_event_code_from_name"));
-
-			const char* error1 = dlerror();
-			if (error1 != NULL)
-			{
-				fprintf(stderr, "%s\n", error1);
-				failed = true;
-			}
-
-			libevdev_event_code_get_name = reinterpret_cast<libevdev_func2_t>(dlsym(lib_handle, "libevdev_event_code_get_name"));
-
-			const char* error2 = dlerror();
-			if (error2 != NULL)
-			{
-				fprintf(stderr, "%s\n", error2);
-				failed = true;
-			}
-		}
-
-		if(failed)
-		{
-			puts("WARNING: libevdev is not available. You'll not be able to use button names instead of numeric codes in your controller mappings!\n");
-			return;
-		}
-
-		libevdev_available = true;
-	}
-
-	s8 EvdevAxisData::convert(s32 value)
-	{
-		return (((value - min) * 255) / range);
-	}
-
-	void EvdevAxisData::init(int fd, int code, bool inverted)
-	{
-		struct input_absinfo abs;
-		if(code < 0 || ioctl(fd, EVIOCGABS(code), &abs))
-		{
-			if(code >= 0)
-			{
-				perror("evdev ioctl");
-			}
-			this->range = 255;
-			this->min = 0;
-			return;
-		}
-		s32 min = abs.minimum;
-		s32 max = abs.maximum;
-		printf("evdev: range of axis %d is from %d to %d\n", code, min, max);
-		if(inverted)
-		{
-			this->range = (min - max);
-			this->min = max;
-		}
-		else
-		{
-			this->range = (max - min);
-			this->min = min;
-		}
-	}
-
-	void EvdevController::init()
-	{
-		this->data_x.init(this->fd, this->mapping->Axis_Analog_X, this->mapping->Axis_Analog_X_Inverted);
-		this->data_y.init(this->fd, this->mapping->Axis_Analog_Y, this->mapping->Axis_Analog_Y_Inverted);
-		this->data_trigger_left.init(this->fd, this->mapping->Axis_Trigger_Left, this->mapping->Axis_Trigger_Left_Inverted);
-		this->data_trigger_right.init(this->fd, this->mapping->Axis_Trigger_Right, this->mapping->Axis_Trigger_Right_Inverted);
-	}
-
-	std::map<std::string, EvdevControllerMapping> loaded_mappings;
-
-	int load_keycode(ConfigFile* cfg, string section, string dc_key)
-	{
-		int code = -1;
-
-		string keycode = cfg->get(section, dc_key, "-1");
-		if (strstr(keycode.c_str(), "KEY_") != NULL ||
-			strstr(keycode.c_str(), "BTN_") != NULL ||
-			strstr(keycode.c_str(), "ABS_") != NULL)
-		{
-			if(libevdev_available)
-			{
-				int type = ((strstr(keycode.c_str(), "ABS_") != NULL) ? EV_ABS : EV_KEY);
-				code = libevdev_event_code_from_name(type, keycode.c_str());
-			}
-			if(code < 0)
-			{
-				printf("evdev: failed to find keycode for '%s'\n", keycode.c_str());
-			}
-			else
-			{
-				printf("%s = %s (%d)\n", dc_key.c_str(), keycode.c_str(), code);
-			}
-			return code;
-		}
-
-		code = cfg->get_int(section, dc_key, -1);
-		if(code >= 0)
-		{
-			char* name = NULL;
-			if(libevdev_available)
-			{
-				int type = ((strstr(dc_key.c_str(), "axis_") != NULL) ? EV_ABS : EV_KEY);
-				name = (char*)libevdev_event_code_get_name(type, code);
-			}
-			if (name != NULL)
-			{
-				printf("%s = %s (%d)\n", dc_key.c_str(), name, code);
-			}
-			else
-			{
-				printf("%s = %d\n", dc_key.c_str(), code);
-			}
-		}
-		return code;
-	}
-
-	EvdevControllerMapping load_mapping(FILE* fd)
-	{
-		ConfigFile mf;
-		mf.parse(fd);
-
-		EvdevControllerMapping mapping = {
-			mf.get("emulator", "mapping_name", "<Unknown>").c_str(),
-			load_keycode(&mf, "dreamcast", "btn_a"),
-			load_keycode(&mf, "dreamcast", "btn_b"),
-			load_keycode(&mf, "dreamcast", "btn_c"),
-			load_keycode(&mf, "dreamcast", "btn_d"),
-			load_keycode(&mf, "dreamcast", "btn_x"),
-			load_keycode(&mf, "dreamcast", "btn_y"),
-			load_keycode(&mf, "dreamcast", "btn_z"),
-			load_keycode(&mf, "dreamcast", "btn_start"),
-			load_keycode(&mf, "emulator",  "btn_escape"),
-			load_keycode(&mf, "dreamcast", "btn_dpad1_left"),
-			load_keycode(&mf, "dreamcast", "btn_dpad1_right"),
-			load_keycode(&mf, "dreamcast", "btn_dpad1_up"),
-			load_keycode(&mf, "dreamcast", "btn_dpad1_down"),
-			load_keycode(&mf, "dreamcast", "btn_dpad2_left"),
-			load_keycode(&mf, "dreamcast", "btn_dpad2_right"),
-			load_keycode(&mf, "dreamcast", "btn_dpad2_up"),
-			load_keycode(&mf, "dreamcast", "btn_dpad2_down"),
-			load_keycode(&mf, "compat",    "btn_trigger_left"),
-			load_keycode(&mf, "compat",    "btn_trigger_right"),
-			load_keycode(&mf, "compat",    "axis_dpad1_x"),
-			load_keycode(&mf, "compat",    "axis_dpad1_y"),
-			load_keycode(&mf, "compat",    "axis_dpad2_x"),
-			load_keycode(&mf, "compat",    "axis_dpad2_y"),
-			load_keycode(&mf, "dreamcast", "axis_x"),
-			load_keycode(&mf, "dreamcast", "axis_y"),
-			load_keycode(&mf, "dreamcast", "axis_trigger_left"),
-			load_keycode(&mf, "dreamcast", "axis_trigger_right"),
-			mf.get_bool("compat", "axis_x_inverted", false),
-			mf.get_bool("compat", "axis_y_inverted", false),
-			mf.get_bool("compat", "axis_trigger_left_inverted", false),
-			mf.get_bool("compat", "axis_trigger_right_inverted", false)
-		};
-		return mapping;
-	}
-
-	int input_evdev_init(EvdevController* controller, const char* device, const char* custom_mapping_fname = NULL)
-	{
-		load_libevdev();
-
-		char name[256] = "Unknown";
-
-		printf("evdev: Trying to open device at '%s'\n", device);
-
-		int fd = open(device, O_RDONLY);
-
-		if (fd >= 0)
-		{
-			fcntl(fd, F_SETFL, O_NONBLOCK);
-			if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0)
-			{
-				perror("evdev: ioctl");
-				return -2;
-			}
-			else
-			{
-				printf("evdev: Found '%s' at '%s'\n", name, device);
-
-				controller->fd = fd;
-
-				const char* mapping_fname;
-
-				if(custom_mapping_fname != NULL)
-				{
-					mapping_fname = custom_mapping_fname;
-				}
-				else
-				{
-					#if defined(TARGET_PANDORA)
-						mapping_fname = "controller_pandora.cfg";
-					#elif defined(TARGET_GCW0)
-						mapping_fname = "controller_gcwz.cfg";
-					#else
-						if (strcmp(name, "Microsoft X-Box 360 pad") == 0 ||
-							strcmp(name, "Xbox 360 Wireless Receiver") == 0 ||
-							strcmp(name, "Xbox 360 Wireless Receiver (XBOX)") == 0)
-						{
-							mapping_fname = "controller_xpad.cfg";
-						}
-						else if (strstr(name, "Xbox Gamepad (userspace driver)") != NULL)
-						{
-							mapping_fname = "controller_xboxdrv.cfg";
-						}
-						else if (strstr(name, "keyboard") != NULL ||
-								 strstr(name, "Keyboard") != NULL)
-						{
-							mapping_fname = "keyboard.cfg";
-						}
-						else
-						{
-							mapping_fname = "controller_generic.cfg";
-						}
-					#endif
-				}
-				if(loaded_mappings.count(string(mapping_fname)) == 0)
-				{
-					FILE* mapping_fd = NULL;
-					if(mapping_fname[0] == '/')
-					{
-						// Absolute mapping
-						mapping_fd = fopen(mapping_fname, "r");
-					}
-					else
-					{
-						// Mapping from ~/.reicast/mappings/
-						size_t size_needed = snprintf(NULL, 0, EVDEV_MAPPING_PATH, mapping_fname) + 1;
-						char* mapping_path = (char*)malloc(size_needed);
-						sprintf(mapping_path, EVDEV_MAPPING_PATH, mapping_fname);
-						mapping_fd = fopen(get_readonly_data_path(mapping_path).c_str(), "r");
-						free(mapping_path);
-					}
-					
-					if(mapping_fd != NULL)
-					{
-						printf("evdev: reading mapping file: '%s'\n", mapping_fname);
-						loaded_mappings.insert(std::make_pair(string(mapping_fname), load_mapping(mapping_fd)));
-						fclose(mapping_fd);
-
-					}
-					else
-					{
-						printf("evdev: unable to open mapping file '%s'\n", mapping_fname);
-						perror("evdev");
-						return -3;
-					}
-				}
-				controller->mapping = &loaded_mappings[string(mapping_fname)];
-				printf("evdev: Using '%s' mapping\n", controller->mapping->name);
-				controller->init();
-
-				return 0;
-			}
-		}
-		else
-		{
-			perror("evdev: open");
-			return -1;
-		}
-	}
-
-	bool input_evdev_handle(EvdevController* controller, u32 port)
-	{
-		#define SET_FLAG(field, mask, expr) field =((expr) ? (field & ~mask) : (field | mask))
-		if (controller->fd < 0 || controller->mapping == NULL)
-		{
-			return false;
-		}
-
-		input_event ie;
-
-		while(read(controller->fd, &ie, sizeof(ie)) == sizeof(ie))
-		{
-			switch(ie.type)
-			{
-				case EV_KEY:
-					if (ie.code == controller->mapping->Btn_A) {
-						SET_FLAG(kcode[port], DC_BTN_A, ie.value);
-					} else if (ie.code == controller->mapping->Btn_B) {
-						SET_FLAG(kcode[port], DC_BTN_B, ie.value);
-					} else if (ie.code == controller->mapping->Btn_C) {
-						SET_FLAG(kcode[port], DC_BTN_C, ie.value);
-					} else if (ie.code == controller->mapping->Btn_D) {
-						SET_FLAG(kcode[port], DC_BTN_D, ie.value);
-					} else if (ie.code == controller->mapping->Btn_X) {
-						SET_FLAG(kcode[port], DC_BTN_X, ie.value);
-					} else if (ie.code == controller->mapping->Btn_Y) {
-						SET_FLAG(kcode[port], DC_BTN_Y, ie.value);
-					} else if (ie.code == controller->mapping->Btn_Z) {
-						SET_FLAG(kcode[port], DC_BTN_Z, ie.value);
-					} else if (ie.code == controller->mapping->Btn_Start) {
-						SET_FLAG(kcode[port], DC_BTN_START, ie.value);
-					} else if (ie.code == controller->mapping->Btn_Escape) {
-						die("death by escape key");
-					} else if (ie.code == controller->mapping->Btn_DPad_Left) {
-						SET_FLAG(kcode[port], DC_DPAD_LEFT, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad_Right) {
-						SET_FLAG(kcode[port], DC_DPAD_RIGHT, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad_Up) {
-						SET_FLAG(kcode[port], DC_DPAD_UP, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad_Down) {
-						SET_FLAG(kcode[port], DC_DPAD_DOWN, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad2_Left) {
-						SET_FLAG(kcode[port], DC_DPAD2_LEFT, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad2_Right) {
-						SET_FLAG(kcode[port], DC_DPAD2_RIGHT, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad2_Up) {
-						SET_FLAG(kcode[port], DC_DPAD2_UP, ie.value);
-					} else if (ie.code == controller->mapping->Btn_DPad2_Down) {
-						SET_FLAG(kcode[port], DC_DPAD2_DOWN, ie.value);
-					} else if (ie.code == controller->mapping->Btn_Trigger_Left) {
-						lt[port] = (ie.value ? 255 : 0);
-					} else if (ie.code == controller->mapping->Btn_Trigger_Right) {
-						rt[port] = (ie.value ? 255 : 0);
-					}
-					break;
-				case EV_ABS:
-					if (ie.code == controller->mapping->Axis_DPad_X)
-					{
-						switch(ie.value)
-						{
-							case -1:
-								SET_FLAG(kcode[port], DC_DPAD_LEFT,  1);
-								SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
-								break;
-							case 0:
-								SET_FLAG(kcode[port], DC_DPAD_LEFT,  0);
-								SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
-								break;
-							case 1:
-								SET_FLAG(kcode[port], DC_DPAD_LEFT,  0);
-								SET_FLAG(kcode[port], DC_DPAD_RIGHT, 1);
-								break;
-						}
-					}
-					else if (ie.code == controller->mapping->Axis_DPad_Y)
-					{
-						switch(ie.value)
-						{
-							case -1:
-								SET_FLAG(kcode[port], DC_DPAD_UP,   1);
-								SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
-								break;
-							case 0:
-								SET_FLAG(kcode[port], DC_DPAD_UP,  0);
-								SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
-								break;
-							case 1:
-								SET_FLAG(kcode[port], DC_DPAD_UP,  0);
-								SET_FLAG(kcode[port], DC_DPAD_DOWN, 1);
-								break;
-						}
-					}
-					else if (ie.code == controller->mapping->Axis_DPad2_X)
-					{
-						switch(ie.value)
-						{
-							case -1:
-								SET_FLAG(kcode[port], DC_DPAD2_LEFT,  1);
-								SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
-								break;
-							case 0:
-								SET_FLAG(kcode[port], DC_DPAD2_LEFT,  0);
-								SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
-								break;
-							case 1:
-								SET_FLAG(kcode[port], DC_DPAD2_LEFT,  0);
-								SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 1);
-								break;
-						}
-					}
-					else if (ie.code == controller->mapping->Axis_DPad2_X)
-					{
-						switch(ie.value)
-						{
-							case -1:
-								SET_FLAG(kcode[port], DC_DPAD2_UP,   1);
-								SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
-								break;
-							case 0:
-								SET_FLAG(kcode[port], DC_DPAD2_UP,  0);
-								SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
-								break;
-							case 1:
-								SET_FLAG(kcode[port], DC_DPAD2_UP,  0);
-								SET_FLAG(kcode[port], DC_DPAD2_DOWN, 1);
-								break;
-						}
-					}
-					else if (ie.code == controller->mapping->Axis_Analog_X)
-					{
-						joyx[port] = (controller->data_x.convert(ie.value) + 128);
-					}
-					else if (ie.code == controller->mapping->Axis_Analog_Y)
-					{
-						joyy[port] = (controller->data_y.convert(ie.value) + 128);
-					}
-					else if (ie.code == controller->mapping->Axis_Trigger_Left)
-					{
-						lt[port] = controller->data_trigger_left.convert(ie.value);
-					}
-					else if (ie.code == controller->mapping->Axis_Trigger_Right)
-					{
-						rt[port] = controller->data_trigger_right.convert(ie.value);
-					}
-					break;
-			}
-		}
-	}
-#endif
-
diff -Nur a/core/linux-dist/evdev.h b/core/linux-dist/evdev.h
--- a/core/linux-dist/evdev.h	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/evdev.h	1969-12-31 21:00:00.000000000 -0300
@@ -1,74 +0,0 @@
-#pragma once
-#include <linux/input.h>
-#include "types.h"
-
-struct EvdevControllerMapping
-{
-	const char* name;
-	const int Btn_A;
-	const int Btn_B;
-	const int Btn_C;
-	const int Btn_D;
-	const int Btn_X;
-	const int Btn_Y;
-	const int Btn_Z;
-	const int Btn_Start;
-	const int Btn_Escape;
-	const int Btn_DPad_Left;
-	const int Btn_DPad_Right;
-	const int Btn_DPad_Up;
-	const int Btn_DPad_Down;
-	const int Btn_DPad2_Left;
-	const int Btn_DPad2_Right;
-	const int Btn_DPad2_Up;
-	const int Btn_DPad2_Down;
-	const int Btn_Trigger_Left;
-	const int Btn_Trigger_Right;
-	const int Axis_DPad_X;
-	const int Axis_DPad_Y;
-	const int Axis_DPad2_X;
-	const int Axis_DPad2_Y;
-	const int Axis_Analog_X;
-	const int Axis_Analog_Y;
-	const int Axis_Trigger_Left;
-	const int Axis_Trigger_Right;
-	const bool Axis_Analog_X_Inverted;
-	const bool Axis_Analog_Y_Inverted;
-	const bool Axis_Trigger_Left_Inverted;
-	const bool Axis_Trigger_Right_Inverted;
-};
-
-struct EvdevAxisData
-{
-	s32 range; // smaller size than 32 bit might cause integer overflows
-	s32 min;
-	void init(int fd, int code, bool inverted);
-	s8 convert(int value);
-};
-
-struct EvdevController
-{
-	int fd;
-	EvdevControllerMapping* mapping;
-	EvdevAxisData data_x;
-	EvdevAxisData data_y;
-	EvdevAxisData data_trigger_left;
-	EvdevAxisData data_trigger_right;
-	void init();
-};
-
-#define EVDEV_DEVICE_CONFIG_KEY "evdev_device_id_%d"
-#define EVDEV_MAPPING_CONFIG_KEY "evdev_mapping_%d"
-#define EVDEV_DEVICE_STRING "/dev/input/event%d"
-#define EVDEV_MAPPING_PATH "/mappings/%s"
-
-#ifdef TARGET_PANDORA
-	#define EVDEV_DEFAULT_DEVICE_ID_1 4
-#else
-	#define EVDEV_DEFAULT_DEVICE_ID_1 0
-#endif
-
-#define EVDEV_DEFAULT_DEVICE_ID(port) (port == 1 ? EVDEV_DEFAULT_DEVICE_ID_1 : -1)
-
-extern int input_evdev_init(EvdevController* controller, const char* device, const char* mapping_fname);
-extern bool input_evdev_handle(EvdevController* controller, u32 port);
diff -Nur a/core/linux-dist/handler.cpp b/core/linux-dist/handler.cpp
--- a/core/linux-dist/handler.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,263 @@
+#include "handler.h"
+
+#define SET_FLAG(field, mask, expr) field =((expr) ? (field & ~mask) : (field | mask))
+static 	InputAxisID axis_ids[] = { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_TRIGGER_LEFT, DC_AXIS_TRIGGER_RIGHT, EMU_AXIS_DPAD1_X, EMU_AXIS_DPAD1_Y, EMU_AXIS_DPAD2_X, EMU_AXIS_DPAD2_Y };
+
+InputAxisConverter::InputAxisConverter(bool inverted, InputAxisLimits limits)
+{
+	this->m_deadzone = limits.deadzone;
+	if(inverted)
+	{
+		this->m_range = (limits.minimum - limits.maximum);
+		this->m_minimum = limits.maximum;
+	}
+	else
+	{
+		this->m_range = (limits.maximum - limits.minimum);
+		this->m_minimum = limits.minimum;
+	}
+}
+
+s8 InputAxisConverter::convert(s32 value)
+{
+	// If value is in deadzone, return 0
+	if (this->m_deadzone && ((value >= 0 && value <= this->m_deadzone) || (value < 0 && value >= -this->m_deadzone)))
+	{
+		return 0;
+	}
+	if (this->m_range)
+	{
+		return (((value - this->m_minimum) * 255) / this->m_range);
+	}
+	return value;
+}
+
+InputMappingStore InputHandler::s_mappingstore;
+
+
+InputHandler::InputHandler()
+{
+	this->m_initialized = false;
+}
+
+InputHandler::~InputHandler()
+{
+	//TODO;
+}
+
+bool InputHandler::initialize(u32 port, std::string device, std::string custom_mapping_filename)
+{
+	if(this->m_initialized)
+	{
+		printf("%s: Handler is already initialized!\n", this->get_api_name().c_str());
+		return true;
+	}
+
+	this->m_port = port;
+
+	bool success = this->setup_device(device);
+
+	if(!success)
+	{
+		printf("%s: Initialization of device '%s' failed!\n", this->get_api_name().c_str(), device.c_str());
+		return false;
+	}
+
+	if(custom_mapping_filename.empty())
+	{
+		this->m_mapping = NULL;
+	}
+	else
+	{
+		this->m_mapping = InputHandler::s_mappingstore.get(custom_mapping_filename, this->get_api_name());
+	}
+
+	if(this->m_mapping == NULL)
+	{
+		if(!custom_mapping_filename.empty())
+		{
+			printf("%s: Loading custom mapping '%s' failed!\n", this->get_api_name().c_str(), custom_mapping_filename.c_str());
+		}
+		std::string default_mapping_filename = this->get_default_mapping_filename();
+		if(default_mapping_filename.empty())
+		{
+			printf("%s: No default mapping available!\n", this->get_api_name().c_str());
+		}
+		else
+		{
+			printf("%s: Using default mapping '%s'.\n", this->get_api_name().c_str(), default_mapping_filename.c_str());	
+			this->m_mapping = InputHandler::s_mappingstore.get(default_mapping_filename, this->get_api_name());
+		}
+	}
+	
+
+	if(this->m_mapping == NULL)
+	{
+		printf("%s: Couldn't load a mapping!\n", this->get_api_name().c_str());
+		return false;
+	}
+
+	for(int i = 0; i < 8; i++)
+	{
+		InputAxisID id = axis_ids[i];
+		const InputAxisCode* code = this->m_mapping->get_axis_code(id);
+		if(code != NULL)
+		{
+			InputAxisLimits limits;
+			this->get_axis_limits(*code, limits);
+			if(limits.minimum != limits.maximum)
+			{
+				bool inverted = this->m_mapping->get_axis_inverted(*code);
+				this->enable_axis_converter(id, inverted, limits);
+			}
+		}
+	}
+	this->m_initialized = true;
+	return true;
+}
+
+bool InputHandler::is_initialized()
+{
+	return this->m_initialized;
+}
+
+std::string InputHandler::get_default_mapping_filename()
+{
+	return "default.cfg";
+}
+
+void InputHandler::get_axis_limits(const InputAxisCode code, InputAxisLimits& limits)
+{
+	// Default stub, can be overridden in subclasses
+	limits.minimum = 0;
+	limits.maximum = 0;
+	limits.deadzone = 0;
+}
+
+void InputHandler::handle_button(InputButtonCode code, int value)
+{
+	if(this->m_mapping == NULL)
+	{
+		return;
+	}
+	const InputButtonID* button_id = this->m_mapping->get_button_id(code);
+	if(button_id == NULL)
+	{
+		printf("Ignoring %d (%d)\n", code, button_id);
+		return;
+	}
+	switch(*button_id)
+	{
+		case EMU_BTN_ESCAPE:
+			if(value)
+			{
+				die("death by escape key");
+			}
+			break;
+		case EMU_BTN_TRIGGER_LEFT:
+			lt[this->m_port] = (value ? 255 : 0);
+			break;
+		case EMU_BTN_TRIGGER_RIGHT:
+			rt[this->m_port] = (value ? 255 : 0);
+			break;
+		default:
+			SET_FLAG(kcode[this->m_port], *button_id, value);
+	};
+}
+
+void InputHandler::handle_axis(InputAxisCode code, int value)
+{
+	if(this->m_mapping == NULL)
+	{
+		return;
+	}
+	const InputAxisID* axis_id = this->m_mapping->get_axis_id(code);
+	if(axis_id == NULL)
+	{
+		printf("Ignoring %d\n", code);
+		return;
+	}
+	switch(*axis_id)
+	{
+		case EMU_AXIS_DPAD1_X:
+		case EMU_AXIS_DPAD1_Y:
+		case EMU_AXIS_DPAD2_X:
+		case EMU_AXIS_DPAD2_Y:
+		{
+			InputButtonID axis_button_id[2];
+			switch(*axis_id)
+			{
+				case EMU_AXIS_DPAD1_X:
+					axis_button_id[0] = DC_BTN_DPAD1_LEFT;
+					axis_button_id[1] = DC_BTN_DPAD1_RIGHT;
+					break;
+				case EMU_AXIS_DPAD1_Y:
+					axis_button_id[0] = DC_BTN_DPAD1_UP;
+					axis_button_id[1] = DC_BTN_DPAD1_DOWN;
+					break;
+				case EMU_AXIS_DPAD2_X:
+					axis_button_id[0] = DC_BTN_DPAD2_LEFT;
+					axis_button_id[1] = DC_BTN_DPAD2_RIGHT;
+					break;
+				case EMU_AXIS_DPAD2_Y:
+					axis_button_id[0] = DC_BTN_DPAD2_UP;
+					axis_button_id[1] = DC_BTN_DPAD2_DOWN;
+			}
+			bool axis_button_value[2];
+			axis_button_value[0] = (value < 0);
+			axis_button_value[1] = (value > 0);
+			SET_FLAG(kcode[this->m_port], axis_button_id[0], axis_button_value[0]);
+			SET_FLAG(kcode[this->m_port], axis_button_id[1], axis_button_value[1]);
+			break;
+		}
+		case DC_AXIS_X:
+		case DC_AXIS_Y:
+		case DC_AXIS_TRIGGER_LEFT:
+		case DC_AXIS_TRIGGER_RIGHT:
+		{
+			InputAxisConverter* converter = this->get_axis_converter(*axis_id);
+			s8 converted_value = ((converter == NULL) ? value : converter->convert(value));
+			switch(*axis_id)
+			{
+				case DC_AXIS_X:
+					joyx[this->m_port] = (converted_value + 128);
+					break;
+				case DC_AXIS_Y:
+					joyy[this->m_port] = (converted_value + 128);
+					break;
+				case DC_AXIS_TRIGGER_LEFT:
+					lt[this->m_port] = converted_value;
+					break;
+				case DC_AXIS_TRIGGER_RIGHT:
+					rt[this->m_port] = converted_value;
+					break;
+			}
+		}
+	}
+}
+
+void InputHandler::enable_axis_converter(InputAxisID axis, bool inverted, InputAxisLimits limits)
+{
+	this->disable_axis_converter(axis); // Delete old axis converter
+	this->m_axis_converters[axis] = new InputAxisConverter(inverted, limits);
+}
+
+void InputHandler::disable_axis_converter(InputAxisID axis)
+{
+	InputAxisConverterStore::iterator iter = this->m_axis_converters.find(axis);
+	if(iter != this->m_axis_converters.end())
+	{
+		delete iter->second;
+		this->m_axis_converters.erase(iter);
+	}
+}
+
+InputAxisConverter* InputHandler::get_axis_converter(InputAxisID axis)
+{
+	InputAxisConverterStore::iterator iter = this->m_axis_converters.find(axis);
+	if(iter == this->m_axis_converters.end())
+	{
+		return NULL;
+	}
+	return iter->second;
+}
\ No newline at end of file
diff -Nur a/core/linux-dist/handler_evdev.cpp b/core/linux-dist/handler_evdev.cpp
--- a/core/linux-dist/handler_evdev.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler_evdev.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,132 @@
+#if defined(USE_EVDEV)
+#include "handler_evdev.h"
+#include <cstring>
+#include <cerrno>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/input.h>
+
+#define EVDEV_DEVICE_STRING "/dev/input/event%s"
+
+void EvdevInputHandler::get_axis_limits(const InputAxisCode code, InputAxisLimits& limits)
+{
+	struct input_absinfo abs;
+	if(!this->m_evdev_fd < 0 || code < 0 || ioctl(this->m_evdev_fd, EVIOCGABS(code), &abs))
+	{
+		if(this->m_evdev_fd >= 0 && code >= 0)
+		{
+			perror("evdev ioctl");
+		}
+		limits.minimum = 0;
+		limits.maximum = 0;
+		limits.deadzone = 0;
+		return;
+	}
+	limits.minimum = abs.minimum;
+	limits.maximum = abs.maximum;
+	limits.deadzone = abs.flat;
+}
+
+std::string EvdevInputHandler::get_api_name()
+{
+	return "evdev";
+}
+
+bool EvdevInputHandler::setup_device(std::string device)
+{
+	size_t size_needed = snprintf(NULL, 0, EVDEV_DEVICE_STRING, device.c_str()) + 1;
+	char* evdev_fname = (char*)malloc(size_needed);
+	sprintf(evdev_fname, EVDEV_DEVICE_STRING, device.c_str());
+
+	printf("evdev: Trying to open device '%s'\n", evdev_fname);
+
+	this->m_evdev_fd = open(evdev_fname, O_RDONLY);
+
+	char device_name[256] = "Unknown";
+
+	if (this->m_evdev_fd < 0)
+	{
+		printf("evdev: Opening device '%s' failed - %s", evdev_fname, strerror(errno));
+		free(evdev_fname);
+		return false;
+	}
+
+	fcntl(this->m_evdev_fd, F_SETFL, O_NONBLOCK);
+
+	// Get device name
+	if(ioctl(this->m_evdev_fd, EVIOCGNAME(sizeof(device_name)), device_name) < 0)
+	{
+		printf("evdev: Getting name of '%s' (ioctl) failed - %s", evdev_fname, strerror(errno));
+		free(evdev_fname);
+		return false;
+	}
+
+	printf("evdev: Found '%s' at '%s'\n", device_name, evdev_fname);
+	this->m_evdev_devname = std::string(device_name);
+	
+	free(evdev_fname);
+
+	return true;
+}
+
+std::string EvdevInputHandler::get_default_mapping_filename()
+{
+	if (this->m_evdev_devname.empty())
+	{
+		return "";
+	}
+
+	std::string mapping_filename;
+	#if defined(TARGET_PANDORA)
+		mapping_filename = "controller_pandora.cfg";
+	#elif defined(TARGET_GCW0)
+		mapping_filename = "controller_gcwz.cfg";
+	#else
+		if (strstr(this->m_evdev_devname.c_str(), "Microsoft X-Box 360 pad") == NULL || strstr(this->m_evdev_devname.c_str(), "Xbox 360 Wireless Receiver") == NULL)
+		{
+			mapping_filename = "controller_xpad.cfg";
+		}
+		else if (strstr(this->m_evdev_devname.c_str(), "Xbox Gamepad (userspace driver)") != NULL)
+		{
+			mapping_filename = "controller_xboxdrv.cfg";
+		}
+		else if (strstr(this->m_evdev_devname.c_str(), "keyboard") != NULL || strstr(this->m_evdev_devname.c_str(), "Keyboard") != NULL)
+		{
+			mapping_filename = "keyboard.cfg";
+		}
+		else
+		{
+			mapping_filename = "controller_generic.cfg";
+		}
+	#endif
+		
+	return mapping_filename;
+}
+
+void EvdevInputHandler::handle()
+{
+	if (!this->is_initialized())
+	{
+		return;
+	}
+
+	input_event ie;
+	while(read(this->m_evdev_fd, &ie, sizeof(ie)) == sizeof(ie))
+	{
+		//printf("evdev: type = %d  - code = %d - value = %d\n", ie.type, ie.code, ie.value);
+		switch(ie.type)
+		{
+			case EV_KEY:
+			{
+				this->handle_button(ie.code, ie.value);
+				break;
+			}
+			case EV_ABS:
+			{
+				this->handle_axis(ie.code, ie.value);
+				break;
+			}
+		}
+	}
+}
+#endif
diff -Nur a/core/linux-dist/handler_evdev.h b/core/linux-dist/handler_evdev.h
--- a/core/linux-dist/handler_evdev.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler_evdev.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,15 @@
+#pragma once
+#include "handler.h"
+
+class EvdevInputHandler : public InputHandler
+{
+	private:
+		int m_evdev_fd;
+		std::string m_evdev_devname;
+		void get_axis_limits(const InputAxisCode code, InputAxisLimits& limits);
+	public:
+		void handle();
+		std::string get_api_name();
+		std::string get_default_mapping_filename();
+		bool setup_device(std::string device);
+};
\ No newline at end of file
diff -Nur a/core/linux-dist/handler.h b/core/linux-dist/handler.h
--- a/core/linux-dist/handler.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,49 @@
+#pragma once
+#include "types.h"
+#include "mapping.h"
+#include "mappingstore.h"
+
+struct InputAxisLimits
+{
+	s32 minimum;
+	s32 maximum;
+	s32 deadzone;
+};
+
+class InputAxisConverter
+{
+	private:
+		s32 m_minimum;
+		s32 m_range;
+		s32 m_deadzone;
+	public:
+		InputAxisConverter(bool inverted, InputAxisLimits limits);
+		s8 convert(s32 value);
+};
+
+class InputHandler
+{
+	typedef std::map<InputAxisID, InputAxisConverter*> InputAxisConverterStore;
+	private:
+		InputAxisConverterStore m_axis_converters;
+		void enable_axis_converter(InputAxisID axis, bool inverted, InputAxisLimits limits);
+		void disable_axis_converter(InputAxisID axis);
+		InputAxisConverter* get_axis_converter(InputAxisID axis);
+		bool m_initialized;
+	protected:
+		static InputMappingStore s_mappingstore;
+		u32 m_port;
+		InputMapping* m_mapping;
+		bool is_initialized();
+		void handle_button(InputButtonCode code, int value);
+		void handle_axis(InputAxisCode code, int value);
+		virtual void get_axis_limits(const InputAxisCode code, InputAxisLimits& limits);
+	public:
+		InputHandler();
+		~InputHandler();
+		bool initialize(u32 port, std::string device, std::string custom_mapping);
+		virtual std::string get_default_mapping_filename();
+		virtual void handle() = 0;
+		virtual std::string get_api_name() = 0;
+		virtual bool setup_device(std::string device) = 0;
+};
\ No newline at end of file
diff -Nur a/core/linux-dist/handler_linuxjs.cpp b/core/linux-dist/handler_linuxjs.cpp
--- a/core/linux-dist/handler_linuxjs.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler_linuxjs.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,127 @@
+#if defined(USE_JOYSTICK)
+#include "handler_linuxjs.h"
+#include <cstring>
+#include <cerrno>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/joystick.h>
+
+#define LINUXJS_DEVICE_STRING "/dev/input/js%s"
+
+void LinuxJoystickInputHandler::get_axis_limits(const InputAxisCode code, InputAxisLimits& limits)
+{
+	// The Linux Joystick API's axes always normalized to this minimum/maximum
+	limits.minimum = -32767;
+	limits.maximum = 32767;
+	limits.deadzone = 0;
+}
+
+std::string LinuxJoystickInputHandler::get_api_name()
+{
+	return "linuxjs";
+}
+
+bool LinuxJoystickInputHandler::setup_device(std::string device)
+{
+	size_t size_needed = snprintf(NULL, 0, LINUXJS_DEVICE_STRING, device.c_str()) + 1;
+	char* linuxjs_fname = (char*)malloc(size_needed);
+	sprintf(linuxjs_fname, LINUXJS_DEVICE_STRING, device.c_str());
+
+	printf("linuxjs: Trying to open device '%s'\n", linuxjs_fname);
+
+	this->m_linuxjs_fd = open(linuxjs_fname, O_RDONLY);
+
+	if (this->m_linuxjs_fd < 0)
+	{
+		printf("linuxjs: Opening device '%s' failed - %s", linuxjs_fname, strerror(errno));
+		free(linuxjs_fname);
+		return false;
+	}
+
+	fcntl(this->m_linuxjs_fd, F_SETFL, O_NONBLOCK);
+
+	char device_name[256] = "Unknown";
+	int button_count = 0;
+	int axis_count = 0;
+
+	// Get device name
+	if(ioctl(this->m_linuxjs_fd, JSIOCGNAME(sizeof(device_name)), device_name) < 0)
+	{
+		printf("linuxjs: Getting name of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
+		free(linuxjs_fname);
+		return false;
+	}
+
+	// Get number of buttons
+	if(ioctl(this->m_linuxjs_fd, JSIOCGBUTTONS, &button_count) < 0)
+	{
+		printf("linuxjs: Getting button count of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
+		free(linuxjs_fname);
+		return false;
+	}
+
+	// Get number of axes
+	if(ioctl(this->m_linuxjs_fd, JSIOCGAXES, &axis_count) < 0)
+	{
+		printf("linuxjs: Getting axis count of '%s' (ioctl) failed - %s", linuxjs_fname, strerror(errno));
+		free(linuxjs_fname);
+		return false;
+	}
+
+	printf("linuxjs: Found '%s' with %d axes and %d buttons at '%s'\n", device_name, axis_count, button_count, linuxjs_fname);
+	this->m_linuxjs_devname = std::string(device_name);
+
+	free(linuxjs_fname);
+
+	return true;
+}
+
+std::string LinuxJoystickInputHandler::get_default_mapping_filename()
+{
+	if (this->m_linuxjs_devname.empty())
+	{
+		return "";
+	}
+
+	std::string mapping_filename;
+	if (strstr(this->m_linuxjs_devname.c_str(), "Microsoft X-Box 360 pad") != NULL ||
+		strstr(this->m_linuxjs_devname.c_str(), "Xbox Gamepad (userspace driver)") != NULL ||
+		strstr(this->m_linuxjs_devname.c_str(), "Xbox 360 Wireless Receiver") != NULL)
+	{
+		mapping_filename = "controller_xbox360.cfg";
+	}
+	else
+	{
+		mapping_filename = "controller_generic.cfg";
+	}
+
+	return mapping_filename;
+}
+
+void LinuxJoystickInputHandler::handle()
+{
+	if (!this->is_initialized())
+	{
+		return;
+	}
+
+	struct js_event je;
+	while(read(this->m_linuxjs_fd, &je, sizeof(je)) == sizeof(je))
+	{
+		printf("linuxjs: type = %d  - code = %d - value = %d\n", je.type, je.number, je.value);
+		switch(je.type)
+		{
+			case JS_EVENT_BUTTON:
+			{
+				this->handle_button(je.number, je.value);
+				break;
+			}
+			case JS_EVENT_AXIS:
+			{
+				this->handle_axis(je.number, je.value);
+				break;
+			}
+		}
+	}
+}
+#endif
\ No newline at end of file
diff -Nur a/core/linux-dist/handler_linuxjs.h b/core/linux-dist/handler_linuxjs.h
--- a/core/linux-dist/handler_linuxjs.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/handler_linuxjs.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,15 @@
+#pragma once
+#include "handler.h"
+
+class LinuxJoystickInputHandler : public InputHandler
+{
+	private:
+		int m_linuxjs_fd;
+		std::string m_linuxjs_devname;
+		void get_axis_limits(const InputAxisCode code, InputAxisLimits& limits);
+	public:
+		void handle();
+		std::string get_api_name();
+		std::string get_default_mapping_filename();
+		bool setup_device(std::string device);
+};
\ No newline at end of file
diff -Nur a/core/linux-dist/joystick.cpp b/core/linux-dist/joystick.cpp
--- a/core/linux-dist/joystick.cpp	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/joystick.cpp	1969-12-31 21:00:00.000000000 -0300
@@ -1,158 +0,0 @@
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <linux/joystick.h>
-#include "linux-dist/joystick.h"
-
-#if defined(USE_JOYSTICK)
-	const u32 joystick_map_btn_usb[JOYSTICK_MAP_SIZE]      = { DC_BTN_Y, DC_BTN_B, DC_BTN_A, DC_BTN_X, 0, 0, 0, 0, 0, DC_BTN_START };
-	const u32 joystick_map_axis_usb[JOYSTICK_MAP_SIZE]     = { DC_AXIS_X, DC_AXIS_Y, 0, 0, 0, 0, 0, 0, 0, 0 };
-
-	const u32 joystick_map_btn_xbox360[JOYSTICK_MAP_SIZE]  = { DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, 0, 0, 0, DC_BTN_START, 0, 0 };
-	const u32 joystick_map_axis_xbox360[JOYSTICK_MAP_SIZE] = { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_DPAD_LEFT, DC_DPAD_UP, 0, 0 };
-
-	const u32* joystick_map_btn = joystick_map_btn_usb;
-	const u32* joystick_map_axis = joystick_map_axis_usb;
-
-	int input_joystick_init(const char* device)
-	{
-		int axis_count = 0;
-		int button_count = 0;
-		char name[128] = "Unknown";
-
-		printf("joystick: Trying to open device at '%s'\n", device);
-
-		int fd = open(device, O_RDONLY);
-
-		if(fd >= 0)
-		{
-			fcntl(fd, F_SETFL, O_NONBLOCK);
-			ioctl(fd, JSIOCGAXES, &axis_count);
-			ioctl(fd, JSIOCGBUTTONS, &button_count);
-			ioctl(fd, JSIOCGNAME(sizeof(name)), &name);
-
-			printf("joystick: Found '%s' with %d axis and %d buttons at '%s'.\n", name, axis_count, button_count, device);
-
-			if (strcmp(name, "Microsoft X-Box 360 pad") == 0 ||
-					strcmp(name, "Xbox Gamepad (userspace driver)") == 0 ||
-					strcmp(name, "Xbox 360 Wireless Receiver (XBOX)") == 0)
-			{
-				joystick_map_btn = joystick_map_btn_xbox360;
-				joystick_map_axis = joystick_map_axis_xbox360;
-				printf("joystick: Using Xbox 360 map\n");
-			}
-		}
-		else
-		{
-			perror("joystick open");
-		}
-
-		return fd;
-	}
-
-	bool input_joystick_handle(int fd, u32 port)
-	{
-		// Joystick must be connected
-		if(fd < 0) {
-			return false;
-		}
-
-		struct js_event JE;
-		while(read(fd, &JE, sizeof(JE)) == sizeof(JE))
-		if (JE.number < JOYSTICK_MAP_SIZE)
-		{
-			switch(JE.type & ~JS_EVENT_INIT)
-			{
-				case JS_EVENT_AXIS:
-				{
-					u32 mt = joystick_map_axis[JE.number] >> 16;
-					u32 mo = joystick_map_axis[JE.number] & 0xFFFF;
-
-					//printf("AXIS %d,%d\n",JE.number,JE.value);
-					s8 v=(s8)(JE.value/256); //-127 ... + 127 range
-
-					if (mt == 0)
-					{
-						kcode[port] |= mo;
-						kcode[port] |= mo*2;
-						if (v<-64)
-						{
-							kcode[port] &= ~mo;
-						}
-						else if (v>64)
-						{
-							kcode[port] &= ~(mo*2);
-						}
-
-					 //printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
-					}
-					else if (mt == 1)
-					{
-						if (v >= 0)
-						{
-							v++;  //up to 255
-						}
-						//printf("AXIS %d,%d Mapped to %d %d %d\n",JE.number,JE.value,mo,v,v+127);
-						if (mo == 0)
-						{
-							lt[port] = (v + 127);
-						}
-						else if (mo == 1)
-						{
-							rt[port] = (v + 127);
-						}
-					}
-					else if (mt == 2)
-					{
-						//  printf("AXIS %d,%d Mapped to %d %d [%d]",JE.number,JE.value,mo,v);
-						if (mo == 0)
-						{
-							joyx[port] = v;
-						}
-						else if (mo == 1)
-						{
-							joyy[port] = v;
-						}
-					}
-				}
-				break;
-
-				case JS_EVENT_BUTTON:
-				{
-					u32 mt = joystick_map_btn[JE.number] >> 16;
-					u32 mo = joystick_map_btn[JE.number] & 0xFFFF;
-
-					// printf("BUTTON %d,%d\n",JE.number,JE.value);
-
-					if (mt == 0)
-					{
-						// printf("Mapped to %d\n",mo);
-						if (JE.value)
-						{
-							kcode[port] &= ~mo;
-						}
-						else
-						{
-							kcode[port] |= mo;
-						}
-					}
-					else if (mt == 1)
-					{
-						// printf("Mapped to %d %d\n",mo,JE.value?255:0);
-						if (mo==0)
-						{
-							lt[port] = JE.value ? 255 : 0;
-						}
-						else if (mo==1)
-						{
-							rt[port] = JE.value ? 255 : 0;
-						}
-					}
-				}
-				break;
-			}
-		}
-
-		return true;
-	}
-#endif
diff -Nur a/core/linux-dist/joystick.h b/core/linux-dist/joystick.h
--- a/core/linux-dist/joystick.h	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/joystick.h	1969-12-31 21:00:00.000000000 -0300
@@ -1,10 +0,0 @@
-#include "types.h"
-#include "linux-dist/main.h"
-
-#pragma once
-#define JOYSTICK_DEVICE_STRING "/dev/input/js%d"
-#define JOYSTICK_DEFAULT_DEVICE_ID -1
-#define JOYSTICK_MAP_SIZE 32
-
-extern int input_joystick_init(const char* device);
-extern bool input_joystick_handle(int fd, u32 port);
diff -Nur a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp
--- a/core/linux-dist/main.cpp	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/main.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -14,6 +14,7 @@
 #include <sys/time.h>
 #include "hw/sh4/dyna/blockmanager.h"
 #include <unistd.h>
+#include "proxy.h"
 
 #if defined(TARGET_EMSCRIPTEN)
 	#include <emscripten.h>
@@ -32,11 +33,11 @@
 #endif
 
 #if defined(USE_EVDEV)
-	#include "linux-dist/evdev.h"
+	#include "linux-dist/handler_evdev.h"
 #endif
 
 #if defined(USE_JOYSTICK)
-	#include "linux-dist/joystick.h"
+	#include "linux-dist/handler_linuxjs.h"
 #endif
 
 #ifdef TARGET_PANDORA
@@ -84,82 +85,68 @@
 
 void emit_WriteCodeCache();
 
-#if defined(USE_EVDEV)
-	/* evdev input */
-	static EvdevController evdev_controllers[4] = {
-		{ -1, NULL },
-		{ -1, NULL },
-		{ -1, NULL },
-		{ -1, NULL }
-	};
-#endif
-
-#if defined(USE_JOYSTICK)
-	/* legacy joystick input */
-	static int joystick_fd = -1; // Joystick file descriptor
-#endif
+static InputHandlerProxy input_handlers;
 
 void SetupInput()
 {
 	#if defined(USE_EVDEV)
-		int evdev_device_id[4] = { -1, -1, -1, -1 };
-		size_t size_needed;
-		int port, i;
+		#define EVDEV_DEVICE_CONFIG_KEY "evdev_device_id_%d"
+		#define EVDEV_MAPPING_CONFIG_KEY "evdev_mapping_%d"
 
-		char* evdev_device;
+		#ifdef TARGET_PANDORA
+			#define EVDEV_DEFAULT_DEVICE_ID_1 "4"
+		#else
+			#define EVDEV_DEFAULT_DEVICE_ID_1 "0"
+		#endif
+		#define EVDEV_DEFAULT_DEVICE_ID(port) (port == 1 ? EVDEV_DEFAULT_DEVICE_ID_1 : "-1")
 
-		for (port = 0; port < 4; port++)
+		for (int port = 0; port < 4; port++)
 		{
+			size_t size_needed;
+			char* evdev_config_key;
+			std::string evdev_device;
+			std::string custom_mapping_filename;
+
 			size_needed = snprintf(NULL, 0, EVDEV_DEVICE_CONFIG_KEY, port+1) + 1;
-			char* evdev_config_key = (char*)malloc(size_needed);
+			evdev_config_key = (char*)malloc(size_needed);
 			sprintf(evdev_config_key, EVDEV_DEVICE_CONFIG_KEY, port+1);
-			evdev_device_id[port] = cfgLoadInt("input", evdev_config_key, EVDEV_DEFAULT_DEVICE_ID(port+1));
+			evdev_device = cfgLoadStr("input", evdev_config_key, EVDEV_DEFAULT_DEVICE_ID(port+1));
 			free(evdev_config_key);
 
-			// Check if the same device is already in use on another port
-			if (evdev_device_id[port] < 0)
+			if(evdev_device.c_str()[0] == '-')
 			{
 				printf("evdev: Controller %d disabled by config.\n", port + 1);
+				continue;
 			}
-			else
-			{
-				for (i = 0; i < port; i++)
-				{
-						if (evdev_device_id[port] == evdev_device_id[i])
-						{
-								die("You can't assign the same device to multiple ports!\n");
-						}
-				}
-
-				size_needed = snprintf(NULL, 0, EVDEV_DEVICE_STRING, evdev_device_id[port]) + 1;
-				evdev_device = (char*)malloc(size_needed);
-				sprintf(evdev_device, EVDEV_DEVICE_STRING, evdev_device_id[port]);
-
-				size_needed = snprintf(NULL, 0, EVDEV_MAPPING_CONFIG_KEY, port+1) + 1;
-				evdev_config_key = (char*)malloc(size_needed);
-				sprintf(evdev_config_key, EVDEV_MAPPING_CONFIG_KEY, port+1);
-				const char* mapping = (cfgExists("input", evdev_config_key) == 2 ? cfgLoadStr("input", evdev_config_key, "").c_str() : NULL);
-				free(evdev_config_key);
 
-				input_evdev_init(&evdev_controllers[port], evdev_device, mapping);
+			size_needed = snprintf(NULL, 0, EVDEV_MAPPING_CONFIG_KEY, port+1) + 1;
+			evdev_config_key = (char*)malloc(size_needed);
+			sprintf(evdev_config_key, EVDEV_MAPPING_CONFIG_KEY, port+1);
+			custom_mapping_filename = (cfgExists("input", evdev_config_key) == 2 ? cfgLoadStr("input", evdev_config_key, "") : "");
+			free(evdev_config_key);
 
-				free(evdev_device);
-			}
+			EvdevInputHandler* handler = new EvdevInputHandler();
+			handler->initialize(port, evdev_device, custom_mapping_filename);
+			input_handlers.add(port, handler);
 		}
 	#endif
 
 	#if defined(USE_JOYSTICK)
-		int joystick_device_id = cfgLoadInt("input", "joystick_device_id", JOYSTICK_DEFAULT_DEVICE_ID);
-		if (joystick_device_id < 0) {
-			puts("Legacy Joystick input disabled by config.\n");
+		#define JOYSTICK_DEFAULT_DEVICE_ID "-1"
+
+		std::string linuxjs_device;
+		std::string custom_mapping_filename = "";
+
+		linuxjs_device = cfgLoadStr("input", "joystick_device_id", JOYSTICK_DEFAULT_DEVICE_ID);
+		if (linuxjs_device.c_str()[0] == '-')
+		{
+			puts("LinuxJoystick input disabled by config.\n");
 		}
 		else
 		{
-			int joystick_device_length = snprintf(NULL, 0, JOYSTICK_DEVICE_STRING, joystick_device_id);
-			char* joystick_device = (char*)malloc(joystick_device_length + 1);
-			sprintf(joystick_device, JOYSTICK_DEVICE_STRING, joystick_device_id);
-			joystick_fd = input_joystick_init(joystick_device);
-			free(joystick_device);
+			LinuxJoystickInputHandler* handler = new LinuxJoystickInputHandler();
+			handler->initialize(0, linuxjs_device, custom_mapping_filename);
+			input_handlers.add(0, handler);
 		}
 	#endif
 
@@ -178,13 +165,7 @@
 		return;
 	#endif
 
-	#if defined(USE_JOYSTICK)
-		input_joystick_handle(joystick_fd, port);
-	#endif
-
-	#if defined(USE_EVDEV)
-		input_evdev_handle(&evdev_controllers[port], port);
-	#endif
+	input_handlers.handle(port);
 
 	#if defined(USE_SDL)
 		input_sdl_handle(port);
diff -Nur a/core/linux-dist/main.h b/core/linux-dist/main.h
--- a/core/linux-dist/main.h	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/main.h	2015-10-06 21:55:43.966475140 -0300
@@ -11,25 +11,34 @@
 
 enum DreamcastController
 {
-	DC_BTN_C       = 1,
-	DC_BTN_B       = 1<<1,
-	DC_BTN_A       = 1<<2,
-	DC_BTN_START   = 1<<3,
-	DC_DPAD_UP     = 1<<4,
-	DC_DPAD_DOWN   = 1<<5,
-	DC_DPAD_LEFT   = 1<<6,
-	DC_DPAD_RIGHT  = 1<<7,
-	DC_BTN_Z       = 1<<8,
-	DC_BTN_Y       = 1<<9,
-	DC_BTN_X       = 1<<10,
-	DC_BTN_D       = 1<<11,
-	DC_DPAD2_UP    = 1<<12,
-	DC_DPAD2_DOWN  = 1<<13,
-	DC_DPAD2_LEFT  = 1<<14,
-	DC_DPAD2_RIGHT = 1<<15,
+	EMU_BTN_NONE   = 0,
+	EMU_BTN_ESCAPE = 1<<16,
+	EMU_BTN_TRIGGER_LEFT  = 1<<17,
+	EMU_BTN_TRIGGER_RIGHT = 1<<18,
+	DC_BTN_C           = 1,
+	DC_BTN_B           = 1<<1,
+	DC_BTN_A           = 1<<2,
+	DC_BTN_START       = 1<<3,
+	DC_BTN_DPAD1_UP    = 1<<4,
+	DC_BTN_DPAD1_DOWN  = 1<<5,
+	DC_BTN_DPAD1_LEFT  = 1<<6,
+	DC_BTN_DPAD1_RIGHT = 1<<7,
+	DC_BTN_Z           = 1<<8,
+	DC_BTN_Y           = 1<<9,
+	DC_BTN_X           = 1<<10,
+	DC_BTN_D           = 1<<11,
+	DC_BTN_DPAD2_UP    = 1<<12,
+	DC_BTN_DPAD2_DOWN  = 1<<13,
+	DC_BTN_DPAD2_LEFT  = 1<<14,
+	DC_BTN_DPAD2_RIGHT = 1<<15,
 
-	DC_AXIS_LT = 0X10000,
-	DC_AXIS_RT = 0X10001,
-	DC_AXIS_X  = 0X20000,
-	DC_AXIS_Y  = 0X20001,
+	EMU_AXIS_NONE    = 0X00000,
+	EMU_AXIS_DPAD1_X = 0X00001,
+	EMU_AXIS_DPAD1_Y = 0X00002,
+	EMU_AXIS_DPAD2_X = 0X00003,
+	EMU_AXIS_DPAD2_Y = 0X00004,
+	DC_AXIS_TRIGGER_LEFT = 0X10000,
+	DC_AXIS_TRIGGER_RIGHT = 0X10001,
+	DC_AXIS_X        = 0X20000,
+	DC_AXIS_Y        = 0X20001,
 };
diff -Nur a/core/linux-dist/mapping.cpp b/core/linux-dist/mapping.cpp
--- a/core/linux-dist/mapping.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/mapping.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,159 @@
+#include "linux-dist/mapping.h"
+#include "cfg/ini.h"
+
+struct ButtonMap
+{
+	InputButtonID id;
+	string section;
+	string option;
+};
+
+struct AxisMap
+{
+	InputAxisID id;
+	string section;
+	string option;
+	string section_inverted;
+	string option_inverted;
+};
+
+static ButtonMap button_list[19] = {
+	{ DC_BTN_A, "dreamcast", "btn_a" },
+	{ DC_BTN_B, "dreamcast", "btn_b" },
+	{ DC_BTN_C, "dreamcast", "btn_c" },
+	{ DC_BTN_D, "dreamcast", "btn_d" },
+	{ DC_BTN_X, "dreamcast", "btn_x" },
+	{ DC_BTN_Y, "dreamcast", "btn_y" },
+	{ DC_BTN_Z, "dreamcast", "btn_z" },
+	{ DC_BTN_START, "dreamcast", "btn_start" },
+	{ DC_BTN_DPAD1_LEFT, "dreamcast", "btn_dpad1_left" },
+	{ DC_BTN_DPAD1_RIGHT, "dreamcast", "btn_dpad1_right" },
+	{ DC_BTN_DPAD1_UP, "dreamcast", "btn_dpad1_up" },
+	{ DC_BTN_DPAD1_DOWN, "dreamcast", "btn_dpad1_down" },
+	{ DC_BTN_DPAD2_LEFT, "dreamcast", "btn_dpad2_left" },
+	{ DC_BTN_DPAD2_RIGHT, "dreamcast", "btn_dpad2_right" },
+	{ DC_BTN_DPAD2_UP, "dreamcast", "btn_dpad2_up" },
+	{ DC_BTN_DPAD2_DOWN, "dreamcast", "btn_dpad2_down" },
+	{ EMU_BTN_ESCAPE, "emulator", "btn_escape" },
+	{ EMU_BTN_TRIGGER_LEFT, "compat", "btn_trigger_left" },
+	{ EMU_BTN_TRIGGER_RIGHT, "compat", "btn_trigger_right" }
+};
+
+static AxisMap axis_list[8] = {
+	{ DC_AXIS_X, "dreamcast", "axis_x", "compat", "axis_x_inverted" },
+	{ DC_AXIS_Y, "dreamcast", "axis_y", "compat", "axis_y_inverted" },
+	{ DC_AXIS_TRIGGER_LEFT,  "dreamcast", "axis_trigger_left",  "compat", "axis_trigger_left_inverted" },
+	{ DC_AXIS_TRIGGER_RIGHT, "dreamcast", "axis_trigger_right", "compat", "axis_trigger_right_inverted" },
+	{ EMU_AXIS_DPAD1_X, "compat", "axis_dpad1_x", "compat", "axis_dpad1_x_inverted" },
+	{ EMU_AXIS_DPAD1_Y, "compat", "axis_dpad1_y", "compat", "axis_dpad1_y_inverted" },
+	{ EMU_AXIS_DPAD2_X, "compat", "axis_dpad2_x", "compat", "axis_dpad2_x_inverted" },
+	{ EMU_AXIS_DPAD2_Y, "compat", "axis_dpad2_y", "compat", "axis_dpad2_y_inverted" }
+};
+
+const InputButtonID* InputMapping::get_button_id(InputButtonCode code)
+{
+	return this->buttons.get_by_value(code);
+}
+
+const InputButtonCode* InputMapping::get_button_code(InputButtonID id)
+{
+	return this->buttons.get_by_key(id);
+}
+
+void InputMapping::set_button(InputButtonID id, InputButtonCode code)
+{
+	if(id != EMU_BTN_NONE)
+	{
+		this->buttons.insert(id, code);
+	}
+}
+
+const InputAxisID* InputMapping::get_axis_id(InputAxisCode code)
+{
+	return this->axes.get_by_value(code);
+}
+
+const InputAxisCode* InputMapping::get_axis_code(InputAxisID id)
+{
+	return this->axes.get_by_key(id);
+}
+
+bool InputMapping::get_axis_inverted(InputAxisCode code)
+{
+	std::map<InputAxisCode, bool>::iterator it = this->axes_inverted.find('b');
+	if (it != this->axes_inverted.end())
+	{
+		return it->second;
+	}
+	return false;
+}
+
+void InputMapping::set_axis(InputAxisID id, InputAxisCode code, bool is_inverted)
+{
+	if(id != EMU_AXIS_NONE)
+	{
+		this->axes.insert(id, code);
+		this->axes_inverted.insert(std::pair<InputAxisCode,bool>(code, is_inverted));
+	}
+}
+
+void InputMapping::load(FILE* fd)
+{
+	ConfigFile mf;
+	mf.parse(fd);
+
+	this->name = mf.get("emulator", "mapping_name", "<Unknown>").c_str();
+
+	int i;
+	for(i = 0; i < 19; i++)
+	{
+		InputButtonCode button_code = mf.get_int(button_list[i].section, button_list[i].option, -1);
+		if (button_code >= 0)
+		{
+			this->set_button(button_list[i].id, button_code);
+		}
+	}
+
+	for(i = 0; i < 8; i++)
+	{
+		InputAxisCode axis_code = mf.get_int(axis_list[i].section, axis_list[i].option, -1);
+		if(axis_code >= 0)
+		{
+			this->set_axis(axis_list[i].id, axis_code, mf.get_bool(axis_list[i].section_inverted, axis_list[i].option_inverted, false));
+		}
+	}
+}
+
+void InputMapping::print()
+{
+	int i;
+
+	printf("\nMAPPING NAME: %s\n", this->name);
+
+	puts("MAPPED BUTTONS:");
+	for(i = 0; i < 19; i++)
+	{
+		const InputButtonCode* button_code = this->get_button_code(button_list[i].id);
+		if(button_code)
+		{
+			printf("%-18s = %d\n", button_list[i].option.c_str(), *button_code);
+		}
+	}
+
+	puts("MAPPED AXES:");
+	for(i = 0; i < 8; i++)
+	{
+		const InputAxisCode* axis_code = this->get_axis_code(axis_list[i].id);
+		if(axis_code)
+		{
+			printf("%-18s = %d", axis_list[i].option.c_str(), *axis_code);
+			if(this->get_axis_inverted(*axis_code))
+			{
+				printf("%s", "(inverted)");
+			}
+			printf("%s", "\n");
+		}
+	}
+	puts("");
+}
+
diff -Nur a/core/linux-dist/mapping.h b/core/linux-dist/mapping.h
--- a/core/linux-dist/mapping.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/mapping.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,32 @@
+#pragma once
+#include <map>
+#include "linux-dist/main.h"
+#include "linux-dist/bimap.h"
+
+typedef DreamcastController InputButtonID;
+typedef DreamcastController InputAxisID;
+typedef int InputButtonCode;
+typedef int InputAxisCode;
+
+class InputMapping
+{
+	private:
+		SimpleBimap<InputButtonID, InputButtonCode> buttons;
+		SimpleBimap<InputAxisID, InputAxisCode> axes;
+		std::map<InputAxisCode, bool> axes_inverted;
+
+	public:
+		const char* name;
+		
+		void set_button(InputButtonID id, InputButtonCode code);
+		const InputButtonID* get_button_id(InputButtonCode code);
+		const InputButtonCode* get_button_code(InputButtonID id);
+
+		void set_axis(InputAxisID id, InputAxisCode code, bool inverted);
+		const InputAxisID* get_axis_id(InputAxisCode code);
+		const InputAxisCode* get_axis_code(InputAxisID id);
+		bool get_axis_inverted(InputAxisCode code);
+
+		void load(FILE* file);
+		void print();
+};
diff -Nur a/core/linux-dist/mappingstore.cpp b/core/linux-dist/mappingstore.cpp
--- a/core/linux-dist/mappingstore.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/mappingstore.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,61 @@
+#include "mappingstore.h"
+#include <errno.h>
+
+static std::string get_mapping_path(std::string filepath, std::string subdir)
+{
+	if (filepath.empty())
+	{
+		return "";
+	}
+
+	std::string new_filepath;
+	if (filepath.at(0) != '/')
+	{
+		// It's not an absolute path
+		std::string mapping_dir = "/mappings/";
+		if(!subdir.empty())
+		{
+			mapping_dir.append(subdir);
+			mapping_dir.append("/");
+		}
+		filepath.insert(0, mapping_dir);
+		new_filepath = get_readonly_data_path(filepath);
+	}
+	else
+	{
+		new_filepath = filepath;
+	}
+	
+	// TODO: Some realpath magic? How portable is it?
+
+	return new_filepath;
+}
+
+InputMapping* InputMappingStore::get(std::string filepath, std::string subdir)
+{
+	std::string full_filepath = get_mapping_path(filepath, subdir);
+	if(!full_filepath.empty())
+	{
+		if(this->loaded_mappings.count(full_filepath) == 0)
+		{
+			// Mapping has not been loaded yet
+			FILE* fp = fopen(full_filepath.c_str(), "r");
+			if(fp == NULL)
+			{
+				printf("Unable to open mapping file '%s': %s\n", full_filepath.c_str(), strerror(errno));
+			}
+			else
+			{
+				InputMapping* mapping = new InputMapping();
+				mapping->load(fp);
+				this->loaded_mappings.insert(std::pair<std::string, InputMapping*>(full_filepath, mapping));
+			}
+		}
+		std::map<std::string, InputMapping*>::iterator it = loaded_mappings.find(full_filepath);
+		if(it != loaded_mappings.end())
+		{
+			return it->second;
+		}
+	}
+	return NULL;
+}
\ No newline at end of file
diff -Nur a/core/linux-dist/mappingstore.h b/core/linux-dist/mappingstore.h
--- a/core/linux-dist/mappingstore.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/mappingstore.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,11 @@
+#pragma once
+#include "mapping.h"
+#include <string>
+
+class InputMappingStore
+{
+	private:
+		std::map<std::string, InputMapping*> loaded_mappings;
+	public:
+		InputMapping* get(std::string filepath, std::string subdir = "");
+};
diff -Nur a/core/linux-dist/proxy.cpp b/core/linux-dist/proxy.cpp
--- a/core/linux-dist/proxy.cpp	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/proxy.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,25 @@
+#include "proxy.h"
+
+InputHandlerProxy::~InputHandlerProxy()
+{
+	//TODO
+}
+
+void InputHandlerProxy::add(u32 port, InputHandler* handler)
+{
+	if(handler != NULL)
+	{
+		this->handlers.insert(std::pair<u32, InputHandler*>(port, handler));
+	}
+}
+
+void InputHandlerProxy::handle(u32 port)
+{
+	std::pair <InputHandlerStore::iterator, InputHandlerStore::iterator> range;
+	range = this->handlers.equal_range(port);
+
+	for (InputHandlerStore::iterator it = range.first; it != range.second; ++it)
+	{
+		it->second->handle();
+	}
+}
\ No newline at end of file
diff -Nur a/core/linux-dist/proxy.h b/core/linux-dist/proxy.h
--- a/core/linux-dist/proxy.h	1969-12-31 21:00:00.000000000 -0300
+++ b/core/linux-dist/proxy.h	2015-10-06 21:55:43.966475140 -0300
@@ -0,0 +1,15 @@
+#pragma once
+#include <map>
+#include "types.h"
+#include "handler.h"
+
+class InputHandlerProxy
+{
+	typedef std::multimap<u32, InputHandler*> InputHandlerStore;
+	private:
+		InputHandlerStore handlers;
+	public:
+		~InputHandlerProxy();
+		void add(u32 port, InputHandler* handler);
+		void handle(u32 port);
+};
\ No newline at end of file
diff -Nur a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp
--- a/core/linux-dist/x11.cpp	2015-10-06 21:43:53.042336401 -0300
+++ b/core/linux-dist/x11.cpp	2015-10-06 21:55:43.966475140 -0300
@@ -112,11 +112,11 @@
 
 void input_x11_init()
 {
-	x11_keymap[113] = DC_DPAD_LEFT;
-	x11_keymap[114] = DC_DPAD_RIGHT;
+	x11_keymap[113] = DC_BTN_DPAD1_LEFT;
+	x11_keymap[114] = DC_BTN_DPAD1_RIGHT;
 
-	x11_keymap[111] = DC_DPAD_UP;
-	x11_keymap[116] = DC_DPAD_DOWN;
+	x11_keymap[111] = DC_BTN_DPAD1_UP;
+	x11_keymap[116] = DC_BTN_DPAD1_DOWN;
 
 	x11_keymap[53] = DC_BTN_X;
 	x11_keymap[54] = DC_BTN_B;