summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pcr/reicast-git/PKGBUILD85
-rw-r--r--pcr/reicast-git/fix-android-translations.patch34
-rw-r--r--pcr/reicast-git/multiplayer_new.patch1133
3 files changed, 1180 insertions, 72 deletions
diff --git a/pcr/reicast-git/PKGBUILD b/pcr/reicast-git/PKGBUILD
index 20edf1fcb..304b738e6 100644
--- a/pcr/reicast-git/PKGBUILD
+++ b/pcr/reicast-git/PKGBUILD
@@ -5,7 +5,7 @@
_pkgname=reicast
pkgname=${_pkgname}-git
pkgver=r1688.0e4949e
-pkgrel=1
+pkgrel=2
pkgdesc="A multiplatform Sega Dreamcast emulator"
arch=('i686' 'x86_64' 'armv7h')
url="http://${_pkgname}.com/"
@@ -25,7 +25,9 @@ source=(${_pkgname}-${pkgver}::"git+https://github.com/${_pkgname}/${_pkgname}-e
'multiplayer-unstable.patch'
'refactor-rend-stuff.patch'
'sdl-opengl.patch'
- 'sh-block-graphs.patch')
+ 'sh-block-graphs.patch'
+ 'multiplayer_new.patch'
+ 'fix-android-translations.patch')
sha256sums=('SKIP'
'12bfc58e12b3ee79b0c82159cdc70c76a4b6804f5c6986853156602bb0e6beb0'
'c14287cf2b2289b9de28cedeee06fcb89ca40da50e34607780dce55d7d8e5fd6'
@@ -37,7 +39,9 @@ sha256sums=('SKIP'
'7c0e2a158d7d37ddbf99a40d11a0a889e55c1e85f9c17a2602e5a2bc809ff4ac'
'aead8326ac6815b555be03030ffbdc8f6ced625c980e77eca89e570591c5eb34'
'cf386ebaeafce046a1fc971a5b140bb6a1245840ad2c2a341541327ed6f5606c'
- '94694d1b615facb39b5ee92ed90c6cefc77fab23fb97f2fcc82e0aa6e1cb14c5')
+ '94694d1b615facb39b5ee92ed90c6cefc77fab23fb97f2fcc82e0aa6e1cb14c5'
+ '51681ec7f90d3b23f57e2946097798266b709570f5c8567a5742873cb14bda64'
+ '097362301f82c3e878352b9fb9812baa6840af054b9dc335600c39de5c22130a')
pkgver() {
cd "${srcdir}/${_pkgname}-${pkgver}"
@@ -48,85 +52,22 @@ prepare() {
cd "${srcdir}/${_pkgname}-${pkgver}"
# Remove nonfree fp.h header
- # rm -v core/deps/libpng/fp.h
+ rm -v core/deps/libpng/fp.h
# Add Multiplayer support
- patch -Np1 -i "$srcdir"/enable_multiplayer_support.patch
+ # patch -Np1 -i "$srcdir"/enable_multiplayer_support.patch
+ patch -Np1 -i "$srcdir"/multiplayer_new.patch
# Add extra patches
patch -Np1 -i "$srcdir"/fix-dyna-constprop.patch
patch -Np1 -i "$srcdir"/futuristic-memops.patch
# patch -Np1 -i "$srcdir"/generalize-mappings.patch
# patch -Np1 -i "$srcdir"/loop-tracing.patch # failed build on i686
- patch -Np1 -i "$srcdir"/loungekatt_rm-nonfree-fp.patch
- patch -Np1 -i "$srcdir"/refactor-rend-stuff.patch
+# patch -Np1 -i "$srcdir"/loungekatt_rm-nonfree-fp.patch
+# patch -Np1 -i "$srcdir"/refactor-rend-stuff.patch
patch -Np1 -i "$srcdir"/sdl-opengl.patch
patch -Np1 -i "$srcdir"/sh-block-graphs.patch
-
- # Add Multiplayer support (unstable)
- # core/linux-dist/main.cpp
- # evdev_controllers[port] = { -1, NULL };
- # evdev_device_id[port] = -1;
- # maple_controller[port].enabled = true;
-# patch -Np1 -i "$srcdir"/multiplayer-unstable.patch
-# sed -i 's|kcode[[]port[]]|maple_controller[port].buttons|g
-# s|lt[[]port[]]|maple_controller[port].trigger_left|g
-# s|rt[[]port[]]|maple_controller[port].trigger_right|g
-# s|joyx[[]port[]]|maple_controller[port].stick_x|g
-# s|joyy[[]port[]]|maple_controller[port].stick_y|g
-# s|DC_DPAD_LEFT|DC_BTN_DPAD1_LEFT|g
-# s|DC_DPAD_RIGHT|DC_BTN_DPAD1_RIGHT|g
-# s|DC_DPAD_UP|DC_BTN_DPAD1_UP|g
-# s|DC_DPAD_DOWN|DC_BTN_DPAD1_DOWN|g
-# s|DC_DPAD2_LEFT|DC_BTN_DPAD2_LEFT|g
-# s|DC_DPAD2_RIGHT|DC_BTN_DPAD2_RIGHT|g
-# s|DC_DPAD2_UP|DC_BTN_DPAD2_UP|g
-# s|DC_DPAD2_DOWN|DC_BTN_DPAD2_DOWN|g
-# s|const u32 sdl_map_|const DreamcastControllerCodes sdl_map_|
-# s|const u32[*] sdl_map_|const DreamcastControllerCodes* sdl_map_|
-# \|extern u16|d
-# \|extern u32|d
-# \|extern u8 |d
-# \|extern s8 |d
-# \|#define DC_|d
-# \|u16 kcode|d
-# \|u8 rt|d
-# \|u8 lt|d
-# \|u32 vks|d
-# \|s8 joy|d
-# \|int port = 0; port| s|4|MAPLE_NUM_PORTS|
-# \|enum DreamcastController|,+32 d
-# s|#include ["]types[.]h["]|#include "types.h"\n#include "hw/maple/maple_controller.h"|
-# ' core/sdl/sdl.cpp \
-# core/linux-dist/main.cpp \
-# core/linux-dist/main.h \
-# shell/apple/emulator-ios/emulator/EmulatorView.mm
-# sed -i 's|kcode[[]port[]]|maple_controller[port].buttons|g
-# s|lt[[]port[]]|maple_controller[port].trigger_left|g
-# s|rt[[]port[]]|maple_controller[port].trigger_right|g
-# s|joyx[[]port[]]|maple_controller[port].stick_x|g
-# s|joyy[[]port[]]|maple_controller[port].stick_y|g
-# s|DC_DPAD_LEFT|DC_BTN_DPAD1_LEFT|g
-# s|DC_DPAD_RIGHT|DC_BTN_DPAD1_RIGHT|g
-# s|DC_DPAD_UP|DC_BTN_DPAD1_UP|g
-# s|DC_DPAD_DOWN|DC_BTN_DPAD1_DOWN|g
-# s|DC_DPAD2_LEFT|DC_BTN_DPAD2_LEFT|g
-# s|DC_DPAD2_RIGHT|DC_BTN_DPAD2_RIGHT|g
-# s|DC_DPAD2_UP|DC_BTN_DPAD2_UP|g
-# s|DC_DPAD2_DOWN|DC_BTN_DPAD2_DOWN|g
-# \|extern u16|d
-# \|extern u8 |d
-# \|extern s8 |d
-# \|#define key_CONT_|d
-# s|#include ["]glshaders[.]h["]|#include "glshaders.h"\n#include "hw/maple/maple_controller.h"|
-# ' core/rend/gles/gles.cpp
-# sed -i 's|x11_keymap[[]53[]] = DC_BTN_X;|x11_keymap[53] = DC_BTN_X;\nx11_keymap[52] = DC_BTN_Y;|
-# ' core/linux-dist/x11.cpp
-# sed -i 's|DC_BTN_DPAD_|DC_BTN_DPAD1_|
-# ' core/hw/maple/maple_controller.h \
-# core/windows/winmain.cpp \
-# core/rend/gles/gles.cpp \
-# shell/apple/emulator-osx/emulator-osx/osx-main.mm
+ patch -Np1 -i "$srcdir"/fix-android-translations.patch
# Add experimental shadow support: http://github.com/reicast-emulator/issues/94
sed -i 's|//DrawModVols|DrawModVols|' core/rend/gles/gldraw.cpp
diff --git a/pcr/reicast-git/fix-android-translations.patch b/pcr/reicast-git/fix-android-translations.patch
new file mode 100644
index 000000000..7431c7993
--- /dev/null
+++ b/pcr/reicast-git/fix-android-translations.patch
@@ -0,0 +1,34 @@
+diff -Nur a/shell/android/res/values-de/strings.xml b/shell/android/res/values-de/strings.xml
+--- a/shell/android/res/values-de/strings.xml 2016-01-18 21:29:18.744938257 -0300
++++ b/shell/android/res/values-de/strings.xml 2016-01-18 21:31:48.198216307 -0300
+@@ -22,7 +22,6 @@
+ <string name="missing_flash">Für einen funktionsfähigen Emulator ist der Dreamcast-Flash erforderlich. Legen Sie die Flash-Datei unter %1$s/data/dc_flash.bin ab.</string>
+ <string name="require_bios">Es muss ein BIOS bereitgestellt werden.</string>
+ <string name="data_folder">Das aktuelle Datenverzeichnis wird überprüft.</string>
+- <string name="emu_crash">Emulator-Fehler!</string>
+
+ <string name="folder_bios">BIOS STARTEN</string>
+ <string name="folder_select">AKTUELLES VERZEICHNIS WÄHLEN</string>
+diff -Nur a/shell/android/res/values-pt/strings.xml b/shell/android/res/values-pt/strings.xml
+--- a/shell/android/res/values-pt/strings.xml 2016-01-18 21:29:18.745938265 -0300
++++ b/shell/android/res/values-pt/strings.xml 2016-01-18 21:31:48.198216307 -0300
+@@ -22,7 +22,6 @@
+ <string name="missing_flash">Arquivo de Flash está faltando. A Flash do Dreamcast é necessária para este emulador funcionar. Coloque o arquivo Flash em %1$s/data/dc_flash.bin</string>
+ <string name="require_bios">Você tem que informar a localização da BIOS do Dreamcast</string>
+ <string name="data_folder">A pasta de dados atual está selecionada.</string>
+- <string name="emu_crash">Erro do emulador:\n %1$s</string>
+
+ <string name="folder_bios">Iniciar BIOS</string>
+ <string name="folder_select">Selecionar diretório atual</string>
+diff -Nur a/shell/android/res/values-ru/strings.xml b/shell/android/res/values-ru/strings.xml
+--- a/shell/android/res/values-ru/strings.xml 2016-01-18 21:29:18.745938265 -0300
++++ b/shell/android/res/values-ru/strings.xml 2016-01-18 21:31:48.198216307 -0300
+@@ -118,7 +118,7 @@
+ <string name="options">Опции</string>
+ <string name="report">Сообщить</string>
+
+- <string name="cloudInfos">Данная утилита позволяет загружать и скачивать файлы карт памяти (VMU) с Dropbox для синхронизации с другими устройствамию./string>
++ <string name="cloudInfos">Данная утилита позволяет загружать и скачивать файлы карт памяти (VMU) с Dropbox для синхронизации с другими устройствамию.</string>
+ <string name="uploadWarning">ВНИМАНИЕ: вы собираетесь загрузить VMU на Dropbox. Это действие ЗАМЕНИТ загруженные ранее файлы!!</string>
+ <string name="downloadWarning">ВНИМАНИЕ: вы собираетесь скачать VMU с Dropbox. Это действие ЗАМЕНИТ скачанные ранее файлы!! Копия файлов будет сохранена
+ в папке VmuBackups</string>
diff --git a/pcr/reicast-git/multiplayer_new.patch b/pcr/reicast-git/multiplayer_new.patch
new file mode 100644
index 000000000..ed2ba8772
--- /dev/null
+++ b/pcr/reicast-git/multiplayer_new.patch
@@ -0,0 +1,1133 @@
+diff -Nur a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp
+--- a/core/hw/maple/maple_cfg.cpp 2016-01-18 21:29:18.658937519 -0300
++++ b/core/hw/maple/maple_cfg.cpp 2016-01-18 21:35:15.480978214 -0300
+@@ -3,6 +3,7 @@
+ #include "maple_helper.h"
+ #include "maple_devs.h"
+ #include "maple_cfg.h"
++#include "maple_controller.h"
+
+ #define HAS_VMU
+ /*
+@@ -22,11 +23,6 @@
+ */
+ void UpdateInputState(u32 port);
+
+-extern u16 kcode[4];
+-extern u32 vks[4];
+-extern s8 joyx[4],joyy[4];
+-extern u8 rt[4],lt[4];
+-
+ u8 GetBtFromSgn(s8 val)
+ {
+ return val+128;
+@@ -45,11 +41,11 @@
+ {
+ UpdateInputState(dev->bus_id);
+
+- pjs->kcode=kcode[dev->bus_id] | 0xF901;
+- pjs->joy[PJAI_X1]=GetBtFromSgn(joyx[dev->bus_id]);
+- pjs->joy[PJAI_Y1]=GetBtFromSgn(joyy[dev->bus_id]);
+- pjs->trigger[PJTI_R]=rt[dev->bus_id];
+- pjs->trigger[PJTI_L]=lt[dev->bus_id];
++ pjs->kcode = maple_controller[dev->bus_id].buttons | 0xF901;
++ pjs->joy[PJAI_X1] = GetBtFromSgn(maple_controller[dev->bus_id].stick_x);
++ pjs->joy[PJAI_Y1] = GetBtFromSgn(maple_controller[dev->bus_id].stick_y);
++ pjs->trigger[PJTI_R] = maple_controller[dev->bus_id].trigger_right;
++ pjs->trigger[PJTI_L] = maple_controller[dev->bus_id].trigger_left;
+ }
+ void SetImage(void* img)
+ {
+@@ -68,14 +64,19 @@
+
+ void mcfg_CreateDevices()
+ {
+-#if DC_PLATFORM == DC_PLATFORM_DREAMCAST
+- mcfg_Create(MDT_SegaController,0,5);
+-
+- mcfg_Create(MDT_SegaVMU,0,0);
+- mcfg_Create(MDT_SegaVMU,0,1);
+-#else
+- mcfg_Create(MDT_NaomiJamma, 0, 5);
+-#endif
++ #if DC_PLATFORM == DC_PLATFORM_DREAMCAST
++ for(int port = 0; port < MAPLE_NUM_PORTS; port++)
++ {
++ if(maple_controller[port].enabled)
++ {
++ mcfg_Create(MDT_SegaController, port, 5);
++ mcfg_Create(MDT_SegaVMU, port, 0);
++ mcfg_Create(MDT_SegaVMU, port, 1);
++ }
++ }
++ #else
++ mcfg_Create(MDT_NaomiJamma, 0, 5);
++ #endif
+ }
+
+ void mcfg_DestroyDevices()
+diff -Nur a/core/hw/maple/maple_controller.cpp b/core/hw/maple/maple_controller.cpp
+--- a/core/hw/maple/maple_controller.cpp 1969-12-31 21:00:00.000000000 -0300
++++ b/core/hw/maple/maple_controller.cpp 2016-01-18 21:35:15.480978214 -0300
+@@ -0,0 +1,8 @@
++#include "hw/maple/maple_controller.h"
++
++MapleController maple_controller[MAPLE_NUM_PORTS] = {
++ { 1 , 0xFFFF, 0, 0, 0, 0 },
++ { 0 , 0xFFFF, 0, 0, 0, 0 },
++ { 0 , 0xFFFF, 0, 0, 0, 0 },
++ { 0 , 0xFFFF, 0, 0, 0, 0 }
++};
+diff -Nur a/core/hw/maple/maple_controller.h b/core/hw/maple/maple_controller.h
+--- a/core/hw/maple/maple_controller.h 1969-12-31 21:00:00.000000000 -0300
++++ b/core/hw/maple/maple_controller.h 2016-01-18 21:35:15.480978214 -0300
+@@ -0,0 +1,42 @@
++#pragma once
++#include "types.h"
++
++// If you change the value of MAPLE_NUM_PORTS, please note that you need to change the initializers in maple_controller.cpp as well
++#define MAPLE_NUM_PORTS 4
++
++struct MapleController
++{
++ bool enabled;
++ u16 buttons;
++ u8 trigger_left;
++ u8 trigger_right;
++ s8 stick_x;
++ s8 stick_y;
++};
++
++extern MapleController maple_controller[MAPLE_NUM_PORTS];
++
++enum MapleControllerCode
++{
++ DC_BTN_C = 1,
++ DC_BTN_B = 1<<1,
++ DC_BTN_A = 1<<2,
++ DC_BTN_START = 1<<3,
++ DC_BTN_DPAD_UP = 1<<4,
++ DC_BTN_DPAD_DOWN = 1<<5,
++ DC_BTN_DPAD_LEFT = 1<<6,
++ DC_BTN_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_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
++};
+diff -Nur a/core/linux-dist/evdev.cpp b/core/linux-dist/evdev.cpp
+--- a/core/linux-dist/evdev.cpp 2016-01-18 21:29:18.672937639 -0300
++++ b/core/linux-dist/evdev.cpp 2016-01-18 21:35:15.480978214 -0300
+@@ -314,43 +314,43 @@
+ {
+ case EV_KEY:
+ if (ie.code == controller->mapping->Btn_A) {
+- SET_FLAG(kcode[port], DC_BTN_A, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_A, ie.value);
+ } else if (ie.code == controller->mapping->Btn_B) {
+- SET_FLAG(kcode[port], DC_BTN_B, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_B, ie.value);
+ } else if (ie.code == controller->mapping->Btn_C) {
+- SET_FLAG(kcode[port], DC_BTN_C, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_C, ie.value);
+ } else if (ie.code == controller->mapping->Btn_D) {
+- SET_FLAG(kcode[port], DC_BTN_D, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_D, ie.value);
+ } else if (ie.code == controller->mapping->Btn_X) {
+- SET_FLAG(kcode[port], DC_BTN_X, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_X, ie.value);
+ } else if (ie.code == controller->mapping->Btn_Y) {
+- SET_FLAG(kcode[port], DC_BTN_Y, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_Y, ie.value);
+ } else if (ie.code == controller->mapping->Btn_Z) {
+- SET_FLAG(kcode[port], DC_BTN_Z, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_Z, ie.value);
+ } else if (ie.code == controller->mapping->Btn_Start) {
+- SET_FLAG(kcode[port], DC_BTN_START, ie.value);
++ SET_FLAG(maple_controller[port].buttons, 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);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_LEFT, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad_Right) {
+- SET_FLAG(kcode[port], DC_DPAD_RIGHT, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_RIGHT, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad_Up) {
+- SET_FLAG(kcode[port], DC_DPAD_UP, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_UP, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad_Down) {
+- SET_FLAG(kcode[port], DC_DPAD_DOWN, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_DOWN, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad2_Left) {
+- SET_FLAG(kcode[port], DC_DPAD2_LEFT, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_LEFT, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad2_Right) {
+- SET_FLAG(kcode[port], DC_DPAD2_RIGHT, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_RIGHT, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad2_Up) {
+- SET_FLAG(kcode[port], DC_DPAD2_UP, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_UP, ie.value);
+ } else if (ie.code == controller->mapping->Btn_DPad2_Down) {
+- SET_FLAG(kcode[port], DC_DPAD2_DOWN, ie.value);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_DOWN, ie.value);
+ } else if (ie.code == controller->mapping->Btn_Trigger_Left) {
+- lt[port] = (ie.value ? 255 : 0);
++ maple_controller[port].trigger_left = (ie.value ? 255 : 0);
+ } else if (ie.code == controller->mapping->Btn_Trigger_Right) {
+- rt[port] = (ie.value ? 255 : 0);
++ maple_controller[port].trigger_right = (ie.value ? 255 : 0);
+ }
+ break;
+ case EV_ABS:
+@@ -359,16 +359,16 @@
+ switch(ie.value)
+ {
+ case -1:
+- SET_FLAG(kcode[port], DC_DPAD_LEFT, 1);
+- SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_LEFT, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_RIGHT, 0);
+ break;
+ case 0:
+- SET_FLAG(kcode[port], DC_DPAD_LEFT, 0);
+- SET_FLAG(kcode[port], DC_DPAD_RIGHT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_LEFT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_RIGHT, 0);
+ break;
+ case 1:
+- SET_FLAG(kcode[port], DC_DPAD_LEFT, 0);
+- SET_FLAG(kcode[port], DC_DPAD_RIGHT, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_LEFT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_RIGHT, 1);
+ break;
+ }
+ }
+@@ -377,16 +377,16 @@
+ switch(ie.value)
+ {
+ case -1:
+- SET_FLAG(kcode[port], DC_DPAD_UP, 1);
+- SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_UP, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_DOWN, 0);
+ break;
+ case 0:
+- SET_FLAG(kcode[port], DC_DPAD_UP, 0);
+- SET_FLAG(kcode[port], DC_DPAD_DOWN, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_UP, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_DOWN, 0);
+ break;
+ case 1:
+- SET_FLAG(kcode[port], DC_DPAD_UP, 0);
+- SET_FLAG(kcode[port], DC_DPAD_DOWN, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_UP, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD_DOWN, 1);
+ break;
+ }
+ }
+@@ -395,16 +395,16 @@
+ switch(ie.value)
+ {
+ case -1:
+- SET_FLAG(kcode[port], DC_DPAD2_LEFT, 1);
+- SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_LEFT, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_RIGHT, 0);
+ break;
+ case 0:
+- SET_FLAG(kcode[port], DC_DPAD2_LEFT, 0);
+- SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_LEFT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_RIGHT, 0);
+ break;
+ case 1:
+- SET_FLAG(kcode[port], DC_DPAD2_LEFT, 0);
+- SET_FLAG(kcode[port], DC_DPAD2_RIGHT, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_LEFT, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_RIGHT, 1);
+ break;
+ }
+ }
+@@ -413,34 +413,34 @@
+ switch(ie.value)
+ {
+ case -1:
+- SET_FLAG(kcode[port], DC_DPAD2_UP, 1);
+- SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_UP, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_DOWN, 0);
+ break;
+ case 0:
+- SET_FLAG(kcode[port], DC_DPAD2_UP, 0);
+- SET_FLAG(kcode[port], DC_DPAD2_DOWN, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_UP, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_DOWN, 0);
+ break;
+ case 1:
+- SET_FLAG(kcode[port], DC_DPAD2_UP, 0);
+- SET_FLAG(kcode[port], DC_DPAD2_DOWN, 1);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_UP, 0);
++ SET_FLAG(maple_controller[port].buttons, DC_BTN_DPAD2_DOWN, 1);
+ break;
+ }
+ }
+ else if (ie.code == controller->mapping->Axis_Analog_X)
+ {
+- joyx[port] = (controller->data_x.convert(ie.value) + 128);
++ maple_controller[port].stick_x = (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);
++ maple_controller[port].stick_y = (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);
++ maple_controller[port].trigger_left = 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);
++ maple_controller[port].trigger_right = controller->data_trigger_right.convert(ie.value);
+ }
+ break;
+ }
+diff -Nur a/core/linux-dist/joystick.cpp b/core/linux-dist/joystick.cpp
+--- a/core/linux-dist/joystick.cpp 2016-01-18 21:29:18.672937639 -0300
++++ b/core/linux-dist/joystick.cpp 2016-01-18 21:35:15.480978214 -0300
+@@ -9,7 +9,7 @@
+ 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_axis_xbox360[JOYSTICK_MAP_SIZE] = { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_BTN_DPAD_LEFT, DC_BTN_DPAD_UP, 0, 0 };
+
+ const u32* joystick_map_btn = joystick_map_btn_usb;
+ const u32* joystick_map_axis = joystick_map_axis_usb;
+@@ -73,18 +73,18 @@
+
+ if (mt == 0)
+ {
+- kcode[port] |= mo;
+- kcode[port] |= mo*2;
++ maple_controller[port].buttons |= mo;
++ maple_controller[port].buttons |= mo*2;
+ if (v<-64)
+ {
+- kcode[port] &= ~mo;
++ maple_controller[port].buttons &= ~mo;
+ }
+ else if (v>64)
+ {
+- kcode[port] &= ~(mo*2);
++ maple_controller[port].buttons &= ~(mo*2);
+ }
+
+- //printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
++ //printf("Mapped to %d %d %d\n",mo,maple_controller[port].buttons&mo,maple_controller[port].buttons&(mo*2));
+ }
+ else if (mt == 1)
+ {
+@@ -95,11 +95,11 @@
+ //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);
++ maple_controller[port].trigger_left = (v + 127);
+ }
+ else if (mo == 1)
+ {
+- rt[port] = (v + 127);
++ maple_controller[port].trigger_right = (v + 127);
+ }
+ }
+ else if (mt == 2)
+@@ -107,11 +107,11 @@
+ // printf("AXIS %d,%d Mapped to %d %d [%d]",JE.number,JE.value,mo,v);
+ if (mo == 0)
+ {
+- joyx[port] = v;
++ maple_controller[port].stick_x = v;
+ }
+ else if (mo == 1)
+ {
+- joyy[port] = v;
++ maple_controller[port].stick_y = v;
+ }
+ }
+ }
+@@ -129,11 +129,11 @@
+ // printf("Mapped to %d\n",mo);
+ if (JE.value)
+ {
+- kcode[port] &= ~mo;
++ maple_controller[port].buttons &= ~mo;
+ }
+ else
+ {
+- kcode[port] |= mo;
++ maple_controller[port].buttons |= mo;
+ }
+ }
+ else if (mt == 1)
+@@ -141,11 +141,11 @@
+ // printf("Mapped to %d %d\n",mo,JE.value?255:0);
+ if (mo==0)
+ {
+- lt[port] = JE.value ? 255 : 0;
++ maple_controller[port].trigger_left = JE.value ? 255 : 0;
+ }
+ else if (mo==1)
+ {
+- rt[port] = JE.value ? 255 : 0;
++ maple_controller[port].trigger_right = JE.value ? 255 : 0;
+ }
+ }
+ }
+diff -Nur a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp
+--- a/core/linux-dist/main.cpp 2016-01-18 21:29:18.673937648 -0300
++++ b/core/linux-dist/main.cpp 2016-01-18 21:35:15.480978214 -0300
+@@ -76,22 +76,11 @@
+ return x11_disp;
+ }
+
+-u16 kcode[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF};
+-u8 rt[4] = {0, 0, 0, 0};
+-u8 lt[4] = {0, 0, 0, 0};
+-u32 vks[4];
+-s8 joyx[4], joyy[4];
+-
+ void emit_WriteCodeCache();
+
+ #if defined(USE_EVDEV)
+ /* evdev input */
+- static EvdevController evdev_controllers[4] = {
+- { -1, NULL },
+- { -1, NULL },
+- { -1, NULL },
+- { -1, NULL }
+- };
++ static EvdevController evdev_controllers[MAPLE_NUM_PORTS];
+ #endif
+
+ #if defined(USE_JOYSTICK)
+@@ -102,14 +91,17 @@
+ void SetupInput()
+ {
+ #if defined(USE_EVDEV)
+- int evdev_device_id[4] = { -1, -1, -1, -1 };
++ int evdev_device_id[MAPLE_NUM_PORTS];
+ size_t size_needed;
+ int port, i;
+
+ char* evdev_device;
+
+- for (port = 0; port < 4; port++)
++ for (port = 0; port < MAPLE_NUM_PORTS; port++)
+ {
++ evdev_controllers[port] = { -1, NULL };
++ evdev_device_id[port] = -1;
++
+ size_needed = snprintf(NULL, 0, EVDEV_DEVICE_CONFIG_KEY, port+1) + 1;
+ char* evdev_config_key = (char*)malloc(size_needed);
+ sprintf(evdev_config_key, EVDEV_DEVICE_CONFIG_KEY, port+1);
+@@ -142,6 +134,7 @@
+ free(evdev_config_key);
+
+ input_evdev_init(&evdev_controllers[port], evdev_device, mapping);
++ maple_controller[port].enabled = true;
+
+ free(evdev_device);
+ }
+diff -Nur a/core/linux-dist/main.h b/core/linux-dist/main.h
+--- a/core/linux-dist/main.h 2016-01-18 21:29:18.673937648 -0300
++++ b/core/linux-dist/main.h 2016-01-18 21:35:15.480978214 -0300
+@@ -1,35 +1,6 @@
+ #pragma once
+ #include "types.h"
+-
+-extern u16 kcode[4];
+-extern u32 vks[4];
+-extern u8 rt[4], lt[4];
+-extern s8 joyx[4], joyy[4];
++#include "hw/maple/maple_controller.h"
+
+ extern void* x11_win;
+ extern void* x11_disp;
+-
+-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,
+-
+- DC_AXIS_LT = 0X10000,
+- DC_AXIS_RT = 0X10001,
+- DC_AXIS_X = 0X20000,
+- DC_AXIS_Y = 0X20001,
+-};
+diff -Nur a/core/linux-dist/x11.cpp b/core/linux-dist/x11.cpp
+--- a/core/linux-dist/x11.cpp 2016-01-18 21:29:18.673937648 -0300
++++ b/core/linux-dist/x11.cpp 2016-01-18 21:35:15.481978222 -0300
+@@ -101,11 +101,11 @@
+ int dc_key = x11_keymap[e.xkey.keycode];
+ if (e.type == KeyPress)
+ {
+- kcode[0] &= ~dc_key;
++ maple_controller[0].buttons &= ~dc_key;
+ }
+ else
+ {
+- kcode[0] |= dc_key;
++ maple_controller[0].buttons |= dc_key;
+ }
+ }
+ //printf("KEY: %d -> %d: %d\n",e.xkey.keycode, dc_key, x11_dc_buttons );
+@@ -117,11 +117,11 @@
+
+ void input_x11_init()
+ {
+- x11_keymap[113] = DC_DPAD_LEFT;
+- x11_keymap[114] = DC_DPAD_RIGHT;
++ x11_keymap[113] = DC_BTN_DPAD_LEFT;
++ x11_keymap[114] = DC_BTN_DPAD_RIGHT;
+
+- x11_keymap[111] = DC_DPAD_UP;
+- x11_keymap[116] = DC_DPAD_DOWN;
++ x11_keymap[111] = DC_BTN_DPAD_UP;
++ x11_keymap[116] = DC_BTN_DPAD_DOWN;
+
+ x11_keymap[53] = DC_BTN_X;
+ x11_keymap[54] = DC_BTN_B;
+diff -Nur a/core/nacl/nacl.cpp b/core/nacl/nacl.cpp
+--- a/core/nacl/nacl.cpp 2016-01-18 21:29:18.673937648 -0300
++++ b/core/nacl/nacl.cpp 2016-01-18 21:35:15.481978222 -0300
+@@ -15,6 +15,7 @@
+ #include "ppapi/utility/completion_callback_factory.h"
+
+ #include "types.h"
++#include "hw/maple/maple_controller.h"
+
+ #include <GLES2/gl2.h>
+
+@@ -235,12 +236,6 @@
+ }
+ } // namespace pp
+
+-
+-u16 kcode[4];
+-u32 vks[4];
+-s8 joyx[4],joyy[4];
+-u8 rt[4],lt[4];
+-
+ int get_mic_data(u8* buffer) { return 0; }
+ int push_vmu_screen(u8* buffer) { return 0; }
+
+diff -Nur a/core/rend/gles/gles.cpp b/core/rend/gles/gles.cpp
+--- a/core/rend/gles/gles.cpp 2016-01-18 21:29:18.677937682 -0300
++++ b/core/rend/gles/gles.cpp 2016-01-18 21:35:15.481978222 -0300
+@@ -2,6 +2,7 @@
+ #include "gles.h"
+ #include "rend/TexCache.h"
+ #include "cfg/cfg.h"
++#include "hw/maple/maple_controller.h"
+
+ #ifdef TARGET_PANDORA
+ #include <unistd.h>
+@@ -1043,28 +1044,6 @@
+ //printf("%f\n",B*log(maxdev)/log(2.0)+A);
+ }
+
+-
+-
+-extern u16 kcode[4];
+-extern u8 rt[4],lt[4];
+-
+-#define key_CONT_C (1 << 0)
+-#define key_CONT_B (1 << 1)
+-#define key_CONT_A (1 << 2)
+-#define key_CONT_START (1 << 3)
+-#define key_CONT_DPAD_UP (1 << 4)
+-#define key_CONT_DPAD_DOWN (1 << 5)
+-#define key_CONT_DPAD_LEFT (1 << 6)
+-#define key_CONT_DPAD_RIGHT (1 << 7)
+-#define key_CONT_Z (1 << 8)
+-#define key_CONT_Y (1 << 9)
+-#define key_CONT_X (1 << 10)
+-#define key_CONT_D (1 << 11)
+-#define key_CONT_DPAD2_UP (1 << 12)
+-#define key_CONT_DPAD2_DOWN (1 << 13)
+-#define key_CONT_DPAD2_LEFT (1 << 14)
+-#define key_CONT_DPAD2_RIGHT (1 << 15)
+-
+ u32 osd_base;
+ u32 osd_count;
+
+@@ -1260,21 +1239,21 @@
+ osd_count=0;
+
+ #ifndef TARGET_PANDORA
+- DrawButton2(vjoy_pos[0],kcode[0]&key_CONT_DPAD_LEFT);
+- DrawButton2(vjoy_pos[1],kcode[0]&key_CONT_DPAD_UP);
+- DrawButton2(vjoy_pos[2],kcode[0]&key_CONT_DPAD_RIGHT);
+- DrawButton2(vjoy_pos[3],kcode[0]&key_CONT_DPAD_DOWN);
++ DrawButton2(vjoy_pos[0], maple_controller[0].buttons & DC_BTN_DPAD_LEFT);
++ DrawButton2(vjoy_pos[1], maple_controller[0].buttons & DC_BTN_DPAD_UP);
++ DrawButton2(vjoy_pos[2], maple_controller[0].buttons & DC_BTN_DPAD_RIGHT);
++ DrawButton2(vjoy_pos[3], maple_controller[0].buttons & DC_BTN_DPAD_DOWN);
+
+- DrawButton2(vjoy_pos[4],kcode[0]&key_CONT_X);
+- DrawButton2(vjoy_pos[5],kcode[0]&key_CONT_Y);
+- DrawButton2(vjoy_pos[6],kcode[0]&key_CONT_B);
+- DrawButton2(vjoy_pos[7],kcode[0]&key_CONT_A);
++ DrawButton2(vjoy_pos[4], maple_controller[0].buttons & DC_BTN_X);
++ DrawButton2(vjoy_pos[5], maple_controller[0].buttons & DC_BTN_Y);
++ DrawButton2(vjoy_pos[6], maple_controller[0].buttons & DC_BTN_B);
++ DrawButton2(vjoy_pos[7], maple_controller[0].buttons & DC_BTN_A);
+
+- DrawButton2(vjoy_pos[8],kcode[0]&key_CONT_START);
++ DrawButton2(vjoy_pos[8], maple_controller[0].buttons & DC_BTN_START);
+
+- DrawButton(vjoy_pos[9],lt[0]);
++ DrawButton(vjoy_pos[9], maple_controller[0].trigger_left);
+
+- DrawButton(vjoy_pos[10],rt[0]);
++ DrawButton(vjoy_pos[10], maple_controller[0].trigger_right);
+
+ DrawButton2(vjoy_pos[11],1);
+ DrawButton2(vjoy_pos[12],0);
+@@ -1818,8 +1797,6 @@
+ #endif
+ #endif
+
+-extern u16 kcode[4];
+-
+ /*
+ bool rend_single_frame()
+ {
+@@ -1833,7 +1810,7 @@
+ }
+
+ bool do_swp=false;
+- //if (kcode[0]&(1<<9))
++ //if (maple_controller[0].buttons&(1<<9))
+ {
+
+
+diff -Nur a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp
+--- a/core/sdl/sdl.cpp 2016-01-18 21:29:18.678937690 -0300
++++ b/core/sdl/sdl.cpp 2016-01-18 21:35:15.481978222 -0300
+@@ -41,7 +41,7 @@
+ { DC_BTN_A, DC_BTN_B, DC_BTN_X, DC_BTN_Y, 0, 0, 0, DC_BTN_START, 0, 0 };
+
+ const u32 sdl_map_axis_xbox360[SDL_MAP_SIZE] =
+- { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_DPAD_LEFT, DC_DPAD_UP, 0, 0 };
++ { DC_AXIS_X, DC_AXIS_Y, DC_AXIS_LT, 0, 0, DC_AXIS_RT, DC_BTN_DPAD_LEFT, DC_BTN_DPAD_UP, 0, 0 };
+
+ const u32* sdl_map_btn = sdl_map_btn_usb;
+ const u32* sdl_map_axis = sdl_map_axis_usb;
+@@ -206,20 +206,20 @@
+ {
+ // printf("Mapped to %d\n",mo);
+ if (value)
+- kcode[port] &= ~mo;
++ maple_controller[port].buttons &= ~mo;
+ else
+- kcode[port] |= mo;
++ maple_controller[port].buttons |= mo;
+ }
+ else if (mt == 1)
+ {
+ // printf("Mapped to %d %d\n",mo,JE.value?255:0);
+ if (mo == 0)
+ {
+- lt[port] = value ? 255 : 0;
++ maple_controller[port].trigger_left = value ? 255 : 0;
+ }
+ else if (mo == 1)
+ {
+- rt[port] = value ? 255 : 0;
++ maple_controller[port].trigger_right = value ? 255 : 0;
+ }
+ }
+
+@@ -240,18 +240,18 @@
+
+ if (mt == 0)
+ {
+- kcode[port] |= mo;
+- kcode[port] |= mo*2;
++ maple_controller[port].buttons |= mo;
++ maple_controller[port].buttons |= mo*2;
+ if (v < -64)
+ {
+- kcode[port] &= ~mo;
++ maple_controller[port].buttons &= ~mo;
+ }
+ else if (v > 64)
+ {
+- kcode[port] &= ~(mo*2);
++ maple_controller[port].buttons &= ~(mo*2);
+ }
+
+- // printf("Mapped to %d %d %d\n",mo,kcode[port]&mo,kcode[port]&(mo*2));
++ // printf("Mapped to %d %d %d\n",mo,maple_controller[port].buttons&mo,maple_controller[port].buttons&(mo*2));
+ }
+ else if (mt == 1)
+ {
+@@ -261,11 +261,11 @@
+
+ if (mo == 0)
+ {
+- lt[port] = v + 127;
++ maple_controller[port].trigger_left = v + 127;
+ }
+ else if (mo == 1)
+ {
+- rt[port] = v + 127;
++ maple_controller[port].trigger_right = v + 127;
+ }
+ }
+ else if (mt == 2)
+@@ -273,11 +273,11 @@
+ // printf("AXIS %d,%d Mapped to %d %d [%d]",JE.number,JE.value,mo,v);
+ if (mo == 0)
+ {
+- joyx[port] = v;
++ maple_controller[port].stick_x = v;
+ }
+ else if (mo==1)
+ {
+- joyy[port] = v;
++ maple_controller[port].stick_y = v;
+ }
+ }
+ }
+@@ -325,39 +325,39 @@
+ case 1: // Up=RT, Down=LT
+ if (yy<0)
+ {
+- rt[port] = -yy;
++ maple_controller[port].trigger_right = -yy;
+ }
+ else if (yy>0)
+ {
+- lt[port] = yy;
++ maple_controller[port].trigger_left = yy;
+ }
+ break;
+ case 2: // Left=LT, Right=RT
+ if (xx < 0)
+ {
+- lt[port] = -xx;
++ maple_controller[port].trigger_left = -xx;
+ }
+ else if (xx > 0)
+ {
+- rt[port] = xx;
++ maple_controller[port].trigger_right = xx;
+ }
+ break;
+ case 3: // Nub = ABXY
+ if (xx < -127)
+ {
+- kcode[port] &= ~DC_BTN_X;
++ maple_controller[port].buttons &= ~DC_BTN_X;
+ }
+ else if (xx > 127)
+ {
+- kcode[port] &= ~DC_BTN_B;
++ maple_controller[port].buttons &= ~DC_BTN_B;
+ }
+ if (yy < -127)
+ {
+- kcode[port] &= ~DC_BTN_Y;
++ maple_controller[port].buttons &= ~DC_BTN_Y;
+ }
+ else if (yy > 127)
+ {
+- kcode[port] &= ~DC_BTN_A;
++ maple_controller[port].buttons &= ~DC_BTN_A;
+ }
+ break;
+ }
+@@ -365,16 +365,16 @@
+ }
+ }
+
+- if (keys[0]) { kcode[port] &= ~DC_BTN_C; }
+- if (keys[6]) { kcode[port] &= ~DC_BTN_A; }
+- if (keys[7]) { kcode[port] &= ~DC_BTN_B; }
+- if (keys[5]) { kcode[port] &= ~DC_BTN_Y; }
+- if (keys[8]) { kcode[port] &= ~DC_BTN_X; }
+- if (keys[1]) { kcode[port] &= ~DC_DPAD_UP; }
+- if (keys[2]) { kcode[port] &= ~DC_DPAD_DOWN; }
+- if (keys[3]) { kcode[port] &= ~DC_DPAD_LEFT; }
+- if (keys[4]) { kcode[port] &= ~DC_DPAD_RIGHT; }
+- if (keys[12]){ kcode[port] &= ~DC_BTN_START; }
++ if (keys[0]) { maple_controller[port].buttons &= ~DC_BTN_C; }
++ if (keys[6]) { maple_controller[port].buttons &= ~DC_BTN_A; }
++ if (keys[7]) { maple_controller[port].buttons &= ~DC_BTN_B; }
++ if (keys[5]) { maple_controller[port].buttons &= ~DC_BTN_Y; }
++ if (keys[8]) { maple_controller[port].buttons &= ~DC_BTN_X; }
++ if (keys[1]) { maple_controller[port].buttons &= ~DC_BTN_DPAD_UP; }
++ if (keys[2]) { maple_controller[port].buttons &= ~DC_BTN_DPAD_DOWN; }
++ if (keys[3]) { maple_controller[port].buttons &= ~DC_BTN_DPAD_LEFT; }
++ if (keys[4]) { maple_controller[port].buttons &= ~DC_BTN_DPAD_RIGHT; }
++ if (keys[12]){ maple_controller[port].buttons &= ~DC_BTN_START; }
+ if (keys[9])
+ {
+ dc_term();
+@@ -384,11 +384,11 @@
+ }
+ if (keys[10])
+ {
+- rt[port] = 255;
++ maple_controller[port].trigger_right = 255;
+ }
+ if (keys[11])
+ {
+- lt[port] = 255;
++ maple_controller[port].trigger_left = 255;
+ }
+ }
+
+diff -Nur a/core/windows/winmain.cpp b/core/windows/winmain.cpp
+--- a/core/windows/winmain.cpp 2016-01-18 21:29:18.679937699 -0300
++++ b/core/windows/winmain.cpp 2016-01-18 21:35:15.482978230 -0300
+@@ -1,5 +1,6 @@
+ #include "oslib\oslib.h"
+ #include "oslib\audiostream.h"
++#include "hw\maple\maple_controller.h"
+ #include "imgread\common.h"
+
+ #define _WIN32_WINNT 0x0500
+@@ -174,66 +175,46 @@
+ return MessageBox(NULL,temp,VER_SHORTNAME,type | MB_TASKMODAL);
+ }
+
+-u16 kcode[4];
+-u32 vks[4];
+-s8 joyx[4],joyy[4];
+-u8 rt[4],lt[4];
+-#define key_CONT_C (1 << 0)
+-#define key_CONT_B (1 << 1)
+-#define key_CONT_A (1 << 2)
+-#define key_CONT_START (1 << 3)
+-#define key_CONT_DPAD_UP (1 << 4)
+-#define key_CONT_DPAD_DOWN (1 << 5)
+-#define key_CONT_DPAD_LEFT (1 << 6)
+-#define key_CONT_DPAD_RIGHT (1 << 7)
+-#define key_CONT_Z (1 << 8)
+-#define key_CONT_Y (1 << 9)
+-#define key_CONT_X (1 << 10)
+-#define key_CONT_D (1 << 11)
+-#define key_CONT_DPAD2_UP (1 << 12)
+-#define key_CONT_DPAD2_DOWN (1 << 13)
+-#define key_CONT_DPAD2_LEFT (1 << 14)
+-#define key_CONT_DPAD2_RIGHT (1 << 15)
+ void UpdateInputState(u32 port)
+ {
+- //joyx[port]=pad.Lx;
+- //joyy[port]=pad.Ly;
+- lt[port]=GetAsyncKeyState('A')?255:0;
+- rt[port]=GetAsyncKeyState('S')?255:0;
++ //maple_controller[port].stick_x = pad.Lx;
++ //maple_controller[port].stick_y = pad.Ly;
++ maple_controller[port].trigger_left = GetAsyncKeyState('A') ? 255 : 0;
++ maple_controller[port].trigger_right = GetAsyncKeyState('S') ? 255 : 0;
+
+- joyx[port]=joyy[port]=0;
++ maple_controller[port].stick_x = maple_controller[port].stick_y = 0;
+
+ if (GetAsyncKeyState('J'))
+- joyx[port]-=126;
++ maple_controller[port].stick_x -= 126;
+ if (GetAsyncKeyState('L'))
+- joyx[port]+=126;
++ maple_controller[port].stick_x += 126;
+
+ if (GetAsyncKeyState('I'))
+- joyy[port]-=126;
++ maple_controller[port].stick_y -= 126;
+ if (GetAsyncKeyState('K'))
+- joyy[port]+=126;
++ maple_controller[port].stick_y += 126;
+
+- kcode[port]=0xFFFF;
++ maple_controller[port].buttons = 0xFFFF;
+ if (GetAsyncKeyState('V'))
+- kcode[port]&=~key_CONT_A;
++ maple_controller[port].buttons &= ~DC_BTN_A;
+ if (GetAsyncKeyState('C'))
+- kcode[port]&=~key_CONT_B;
++ maple_controller[port].buttons &= ~DC_BTN_B;
+ if (GetAsyncKeyState('X'))
+- kcode[port]&=~key_CONT_Y;
++ maple_controller[port].buttons &= ~DC_BTN_Y;
+ if (GetAsyncKeyState('Z'))
+- kcode[port]&=~key_CONT_X;
++ maple_controller[port].buttons &= ~DC_BTN_X;
+
+ if (GetAsyncKeyState(VK_SHIFT))
+- kcode[port]&=~key_CONT_START;
++ maple_controller[port].buttons &= ~DC_BTN_START;
+
+ if (GetAsyncKeyState(VK_UP))
+- kcode[port]&=~key_CONT_DPAD_UP;
++ maple_controller[port].buttons &= ~DC_BTN_DPAD_UP;
+ if (GetAsyncKeyState(VK_DOWN))
+- kcode[port]&=~key_CONT_DPAD_DOWN;
++ maple_controller[port].buttons &= ~DC_BTN_DPAD_DOWN;
+ if (GetAsyncKeyState(VK_LEFT))
+- kcode[port]&=~key_CONT_DPAD_LEFT;
++ maple_controller[port].buttons &= ~DC_BTN_DPAD_LEFT;
+ if (GetAsyncKeyState(VK_RIGHT))
+- kcode[port]&=~key_CONT_DPAD_RIGHT;
++ maple_controller[port].buttons &= ~DC_BTN_DPAD_RIGHT;
+
+ if (GetAsyncKeyState(VK_F1))
+ settings.pvr.ta_skip = 100;
+diff -Nur a/shell/android/jni/src/Android.cpp b/shell/android/jni/src/Android.cpp
+--- a/shell/android/jni/src/Android.cpp 2016-01-18 21:29:18.705937922 -0300
++++ b/shell/android/jni/src/Android.cpp 2016-01-18 21:35:15.482978230 -0300
+@@ -16,6 +16,7 @@
+ #include "rend/TexCache.h"
+ #include "hw/maple/maple_devs.h"
+ #include "hw/maple/maple_if.h"
++#include "hw/maple/maple_controller.h"
+ #include "oslib/audiobackend_android.h"
+
+ #include "util.h"
+@@ -175,10 +176,6 @@
+ // Additonal controllers 2, 3 and 4 connected ?
+ static bool add_controllers[3] = { false, false, false };
+
+-u16 kcode[4];
+-u32 vks[4];
+-s8 joyx[4],joyy[4];
+-u8 rt[4],lt[4];
+ float vjoy_pos[14][8];
+
+ extern bool print_stats;
+@@ -211,7 +208,7 @@
+ }
+
+ // Add additonal controllers
+- for (int i = 0; i < 3; i++)
++ for (int i = 0; i < (MAPLE_NUM_PORTS - 1); i++)
+ {
+ if (add_controllers[i])
+ mcfg_Create(MDT_SegaController,i+1,5);
+@@ -445,13 +442,13 @@
+ jint *jx_body = env->GetIntArrayElements(jx, 0);
+ jint *jy_body = env->GetIntArrayElements(jy, 0);
+
+- for(int i = 0; i < 4; i++)
++ for(int i = 0; i < MAPLE_NUM_PORTS; i++)
+ {
+- kcode[i] = k_code_body[i];
+- lt[i] = l_t_body[i];
+- rt[i] = r_t_body[i];
+- joyx[i] = jx_body[i];
+- joyy[i] = jy_body[i];
++ maple_controller[i].buttons = k_code_body[i];
++ maple_controller[i].trigger_left = l_t_body[i];
++ maple_controller[i].trigger_right = r_t_body[i];
++ maple_controller[i].stick_x = jx_body[i];
++ maple_controller[i].stick_y = jy_body[i];
+ }
+
+ env->ReleaseIntArrayElements(k_code, k_code_body, 0);
+diff -Nur a/shell/apple/emulator-ios/emulator/EmulatorView.mm b/shell/apple/emulator-ios/emulator/EmulatorView.mm
+--- a/shell/apple/emulator-ios/emulator/EmulatorView.mm 2016-01-18 21:29:18.777938539 -0300
++++ b/shell/apple/emulator-ios/emulator/EmulatorView.mm 2016-01-18 21:35:15.482978230 -0300
+@@ -9,15 +9,7 @@
+ #import "EmulatorView.h"
+
+ #include "types.h"
+-
+-extern u16 kcode[4];
+-extern u32 vks[4];
+-extern s8 joyx[4],joyy[4];
+-extern u8 rt[4],lt[4];
+-
+-#define key_CONT_A (1 << 2)
+-#define key_CONT_START (1 << 3)
+-#define key_CONT_DPAD_LEFT (1 << 6)
++#include "hw/maple/maple_controller.h"
+
+ int dpad_or_btn = 0;
+
+@@ -34,9 +26,9 @@
+ -(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
+
+ if (dpad_or_btn &1)
+- kcode[0] &= ~(key_CONT_START|key_CONT_A);
++ maple_controller[0].buttons &= ~(DC_BTN_START|DC_BTN_A);
+ else
+- kcode[0] &= ~(key_CONT_DPAD_LEFT);
++ maple_controller[0].buttons &= ~(DC_BTN_DPAD_LEFT);
+ }
+
+ -(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
+@@ -44,9 +36,9 @@
+ // [event allTouches];
+
+ if (dpad_or_btn &1)
+- kcode[0] |= (key_CONT_START|key_CONT_A);
++ maple_controller[0].buttons |= (DC_BTN_START|DC_BTN_A);
+ else
+- kcode[0] |= (key_CONT_DPAD_LEFT);
++ maple_controller[0].buttons |= (DC_BTN_DPAD_LEFT);
+
+ dpad_or_btn++;
+ }
+diff -Nur a/shell/apple/emulator-ios/emulator/ios_main.mm b/shell/apple/emulator-ios/emulator/ios_main.mm
+--- a/shell/apple/emulator-ios/emulator/ios_main.mm 2016-01-18 21:29:18.780938565 -0300
++++ b/shell/apple/emulator-ios/emulator/ios_main.mm 2016-01-18 21:35:15.482978230 -0300
+@@ -20,6 +20,7 @@
+ #include <sys/mman.h>
+ #include <sys/time.h>
+ #include "hw/sh4/dyna/blockmanager.h"
++#include "hw/maple/maple_controller.h"
+ #include <unistd.h>
+
+
+@@ -55,11 +56,6 @@
+ int dc_init(int argc,wchar* argv[]);
+ void dc_run();
+
+-u16 kcode[4];
+-u32 vks[4];
+-s8 joyx[4],joyy[4];
+-u8 rt[4],lt[4];
+-
+ extern "C" int reicast_main(int argc, wchar* argv[])
+ {
+ //if (argc==2)
+diff -Nur a/shell/apple/emulator-osx/emulator-osx/osx-main.mm b/shell/apple/emulator-osx/emulator-osx/osx-main.mm
+--- a/shell/apple/emulator-osx/emulator-osx/osx-main.mm 2016-01-18 21:29:18.782938582 -0300
++++ b/shell/apple/emulator-osx/emulator-osx/osx-main.mm 2016-01-18 21:35:15.482978230 -0300
+@@ -8,6 +8,7 @@
+ #import <Carbon/Carbon.h>
+
+ #include "types.h"
++#include "hw/maple/maple_controller.h"
+ #include <sys/stat.h>
+
+ #include <OpenGL/gl3.h>
+@@ -38,11 +39,6 @@
+ return 0;
+ }
+
+-u16 kcode[4] = { 0xFFFF };
+-u32 vks[4];
+-s8 joyx[4],joyy[4];
+-u8 rt[4],lt[4];
+-
+ int get_mic_data(u8* buffer) { return 0; }
+ int push_vmu_screen(u8* buffer) { return 0; }
+
+@@ -135,35 +131,11 @@
+ gles_init();
+ }
+
+-enum DCPad {
+- Btn_C = 1,
+- Btn_B = 1<<1,
+- Btn_A = 1<<2,
+- Btn_Start = 1<<3,
+- DPad_Up = 1<<4,
+- DPad_Down = 1<<5,
+- DPad_Left = 1<<6,
+- DPad_Right = 1<<7,
+- Btn_Z = 1<<8,
+- Btn_Y = 1<<9,
+- Btn_X = 1<<10,
+- Btn_D = 1<<11,
+- DPad2_Up = 1<<12,
+- DPad2_Down = 1<<13,
+- DPad2_Left = 1<<14,
+- DPad2_Right = 1<<15,
+-
+- Axis_LT= 0x10000,
+- Axis_RT= 0x10001,
+- Axis_X= 0x20000,
+- Axis_Y= 0x20001,
+-};
+-
+ void handle_key(int dckey, int state) {
+ if (state)
+- kcode[0] &= ~dckey;
++ maple_controller[0].buttons &= ~dckey;
+ else
+- kcode[0] |= dckey;
++ maple_controller[0].buttons |= dckey;
+ }
+
+ void handle_trig(u8* dckey, int state) {
+@@ -176,18 +148,18 @@
+ extern "C" void emu_key_input(char* keyt, int state) {
+ int key = keyt[0];
+ switch(key) {
+- case 'z': handle_key(Btn_X, state); break;
+- case 'x': handle_key(Btn_Y, state); break;
+- case 'c': handle_key(Btn_B, state); break;
+- case 'v': handle_key(Btn_A, state); break;
++ case 'z': handle_key(DC_BTN_X, state); break;
++ case 'x': handle_key(DC_BTN_Y, state); break;
++ case 'c': handle_key(DC_BTN_B, state); break;
++ case 'v': handle_key(DC_BTN_A, state); break;
+
+ case 'a': handle_trig(lt, state); break;
+ case 's': handle_trig(rt, state); break;
+
+- case 'j': handle_key(DPad_Left, state); break;
+- case 'k': handle_key(DPad_Down, state); break;
+- case 'l': handle_key(DPad_Right, state); break;
+- case 'i': handle_key(DPad_Up, state); break;
+- case 0xa: handle_key(Btn_Start, state); break;
++ case 'j': handle_key(DC_BTN_DPAD_LEFT, state); break;
++ case 'k': handle_key(DC_BTN_DPAD_DOWN, state); break;
++ case 'l': handle_key(DC_BTN_DPAD_RIGHT, state); break;
++ case 'i': handle_key(DC_BTN_DPAD_UP, state); break;
++ case 0xa: handle_key(DC_BTN_START, state); break;
+ }
+ }
+\ No newline at end of file
+diff -Nur a/shell/reicast.vcxproj b/shell/reicast.vcxproj
+--- a/shell/reicast.vcxproj 2016-01-18 21:29:18.820938908 -0300
++++ b/shell/reicast.vcxproj 2016-01-18 21:35:15.483978239 -0300
+@@ -92,6 +92,7 @@
+ <ClCompile Include="..\core\hw\holly\sb_dma.cpp" />
+ <ClCompile Include="..\core\hw\holly\sb_mem.cpp" />
+ <ClCompile Include="..\core\hw\maple\maple_cfg.cpp" />
++ <ClCompile Include="..\core\hw\maple\maple_controller.cpp" />
+ <ClCompile Include="..\core\hw\maple\maple_devs.cpp" />
+ <ClCompile Include="..\core\hw\maple\maple_helper.cpp" />
+ <ClCompile Include="..\core\hw\maple\maple_if.cpp" />