summaryrefslogtreecommitdiff
path: root/pcr/reicast-git
diff options
context:
space:
mode:
authorcoadde [Márcio Alexandre Silva Delgado] <coadde@parabola.nu>2016-03-19 02:42:06 -0300
committercoadde [Márcio Alexandre Silva Delgado] <coadde@parabola.nu>2016-03-19 02:43:41 -0300
commitd67412b3ffe38c911bc6a716dd444a71171cbf9d (patch)
tree6e351db1460a9ba678fd6f821214205d391c9191 /pcr/reicast-git
parent6074fa94890e02956055826f43e9abd720f4767d (diff)
reicast: update pkgbuild
Diffstat (limited to 'pcr/reicast-git')
-rw-r--r--pcr/reicast-git/PKGBUILD40
-rw-r--r--pcr/reicast-git/fix-android-translations.patch12
-rw-r--r--pcr/reicast-git/purupuru.patch435
3 files changed, 463 insertions, 24 deletions
diff --git a/pcr/reicast-git/PKGBUILD b/pcr/reicast-git/PKGBUILD
index 304b738e6..6b646a466 100644
--- a/pcr/reicast-git/PKGBUILD
+++ b/pcr/reicast-git/PKGBUILD
@@ -4,8 +4,8 @@
_pkgname=reicast
pkgname=${_pkgname}-git
-pkgver=r1688.0e4949e
-pkgrel=2
+pkgver=r1695.0a1689c
+pkgrel=1
pkgdesc="A multiplatform Sega Dreamcast emulator"
arch=('i686' 'x86_64' 'armv7h')
url="http://${_pkgname}.com/"
@@ -13,7 +13,7 @@ license=('GPL2')
provides=("${_pkgname}")
conflicts=("${_pkgname}")
makedepends=('git')
-depends=('libgl' 'alsa-plugins' 'libpulse' 'python-evdev' )
+depends=('libgl' 'alsa-plugins' 'libpulse' 'python-evdev') # 'sdl2')
source=(${_pkgname}-${pkgver}::"git+https://github.com/${_pkgname}/${_pkgname}-emulator.git"
'enable_multiplayer_support.patch'
'fix-dyna-constprop.patch'
@@ -27,7 +27,8 @@ source=(${_pkgname}-${pkgver}::"git+https://github.com/${_pkgname}/${_pkgname}-e
'sdl-opengl.patch'
'sh-block-graphs.patch'
'multiplayer_new.patch'
- 'fix-android-translations.patch')
+ 'fix-android-translations.patch'
+ 'purupuru.patch')
sha256sums=('SKIP'
'12bfc58e12b3ee79b0c82159cdc70c76a4b6804f5c6986853156602bb0e6beb0'
'c14287cf2b2289b9de28cedeee06fcb89ca40da50e34607780dce55d7d8e5fd6'
@@ -41,7 +42,8 @@ sha256sums=('SKIP'
'cf386ebaeafce046a1fc971a5b140bb6a1245840ad2c2a341541327ed6f5606c'
'94694d1b615facb39b5ee92ed90c6cefc77fab23fb97f2fcc82e0aa6e1cb14c5'
'51681ec7f90d3b23f57e2946097798266b709570f5c8567a5742873cb14bda64'
- '097362301f82c3e878352b9fb9812baa6840af054b9dc335600c39de5c22130a')
+ 'a651fd92d1bfbef0a1ca524c54b2a59a8a45c53ef76a1fe53d36d87abef93a85'
+ '02b01a8b1a33aa543213371ec6022559c1eebbeb2d6a20173995ee618d7396a1')
pkgver() {
cd "${srcdir}/${_pkgname}-${pkgver}"
@@ -55,8 +57,8 @@ prepare() {
rm -v core/deps/libpng/fp.h
# Add Multiplayer support
- # patch -Np1 -i "$srcdir"/enable_multiplayer_support.patch
- patch -Np1 -i "$srcdir"/multiplayer_new.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
@@ -65,10 +67,13 @@ prepare() {
# 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"/sdl-opengl.patch
+# patch -Np1 -i "$srcdir"/sdl-opengl.patch
patch -Np1 -i "$srcdir"/sh-block-graphs.patch
patch -Np1 -i "$srcdir"/fix-android-translations.patch
+ # Enable Purupuru Pack (rumble support)
+ patch -Np1 -i "$srcdir"/purupuru.patch
+
# Add experimental shadow support: http://github.com/reicast-emulator/issues/94
sed -i 's|//DrawModVols|DrawModVols|' core/rend/gles/gldraw.cpp
@@ -78,12 +83,19 @@ prepare() {
# Enable Pulseaudio
sed -i 's|#USE_PULSEAUDIO|USE_PULSEAUDIO|' shell/linux/Makefile
+
+ # Enable SDL
+# sed -i 's|USE_JOYSTICK[ ][:][=][ ]1|USE_JOYSTICK := 1\nUSE_SDL := 1|' shell/linux/Makefile
}
build() {
mkdir -vm 0755 "$srcdir"/pkgbuild-dir
+ mkdir -vm 0755 "$srcdir"/purupuru-dir
if [ $CARCH == x86_64 ]; then
make -C ${_pkgname}-${pkgver}/shell/linux platform=x64 PREFIX=/usr DESTDIR="$srcdir"/pkgbuild-dir install
+ # Enable Purupuru Pack (rumble support)
+ sed -i 's|SegaVMU[,]i[,]1|PurupuruPack,i,1|' ${_pkgname}-${pkgver}/core/hw/maple/maple_cfg.cpp
+ make -C ${_pkgname}-${pkgver}/shell/linux platform=x64 PREFIX=/usr DESTDIR="$srcdir"/purupuru-dir install
# Error in platform=lincpp:
# ../../core/linux-dist/evdev.cpp:287:65: required from here
# /usr/include/c++/5.2.0/tuple:1172:70: error: use of deleted function 'EvdevControllerMapping::EvdevControllerMapping()'
@@ -92,6 +104,9 @@ build() {
# make -C ${_pkgname}-${pkgver}/shell/linux platform=lincpp PREFIX=/usr DESTDIR="$srcdir"/pkgbuild-cpp-dir install
elif [ $CARCH == i686 ]; then
make -C ${_pkgname}-${pkgver}/shell/linux platform=x86 PREFIX=/usr DESTDIR="$srcdir"/pkgbuild-dir install
+ # Enable Purupuru Pack (rumble support)
+ sed -i 's|SegaVMU[,]i[,]1|PurupuruPack,i,1|' ${_pkgname}-${pkgver}/core/hw/maple/maple_cfg.cpp
+ make -C ${_pkgname}-${pkgver}/shell/linux platform=x86 PREFIX=/usr DESTDIR="$srcdir"/purupuru-dir install
elif [ $CARCH == armv7h ]; then
make -C ${_pkgname}-${pkgver}/shell/linux platform=armv7h PREFIX=/usr DESTDIR="$srcdir"/pkgbuild-dir install
# mkdir -vm 0755 "$srcdir"/pkgbuild-{rpi2,beagle,pandora,odroid{c1,xu3,xu,x2,x,u2}}-dir
@@ -108,11 +123,12 @@ build() {
}
package() {
- cp -va "$srcdir"/pkgbuild-dir/* "$pkgdir"
+ cp -va "$srcdir"/pkgbuild-dir/* "$pkgdir"
+ cp -va "$srcdir"/purupuru-dir/usr/bin/${_pkgname} "$pkgdir"/usr/bin/${_pkgname}-purupuru
if [ -d "$srcdir"/pkgbuild-cpp-dir ]; then
- cp -va "$srcdir"/pkgbuild-cpp-dir/usr/bin/${_pkgname} "$pkgdir"/usr/bin/${_pkgname}-c++
- cp -va "$srcdir"/pkgbuild-cpp-dir/usr/share/applications/${_pkgname}.desktop "$pkgdir"/usr/share/applications/${_pkgname}-c++.desktop
- cp -va "$srcdir"/pkgbuild-cpp-dir/usr/share/man/man1/${_pkgname} "$pkgdir"/usr/share/man/man1/${_pkgname}-c++
+ cp -va "$srcdir"/pkgbuild-cpp-dir/usr/bin/${_pkgname} "$pkgdir"/usr/bin/${_pkgname}-c++
+ cp -va "$srcdir"/pkgbuild-cpp-dir/usr/share/applications/${_pkgname}.desktop "$pkgdir"/usr/share/applications/${_pkgname}-c++.desktop
+ cp -va "$srcdir"/pkgbuild-cpp-dir/usr/share/man/man1/${_pkgname} "$pkgdir"/usr/share/man/man1/${_pkgname}-c++
sed -i '\|Name| s|reicast|reicast-c++|
\|Exec| s|reicast|reicast-c++|
' "$pkgdir"/usr/share/applications/${_pkgname}-c++.desktop
diff --git a/pcr/reicast-git/fix-android-translations.patch b/pcr/reicast-git/fix-android-translations.patch
index 7431c7993..d43154e3e 100644
--- a/pcr/reicast-git/fix-android-translations.patch
+++ b/pcr/reicast-git/fix-android-translations.patch
@@ -20,15 +20,3 @@ diff -Nur a/shell/android/res/values-pt/strings.xml b/shell/android/res/values-p
<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/purupuru.patch b/pcr/reicast-git/purupuru.patch
new file mode 100644
index 000000000..d05ca41b3
--- /dev/null
+++ b/pcr/reicast-git/purupuru.patch
@@ -0,0 +1,435 @@
+diff -Nur a/core/hw/maple/maple_cfg.cpp b/core/hw/maple/maple_cfg.cpp
+--- a/core/hw/maple/maple_cfg.cpp 2016-03-18 23:11:34.099340091 -0300
++++ b/core/hw/maple/maple_cfg.cpp 2016-03-18 23:12:24.396511206 -0300
+@@ -21,6 +21,7 @@
+ ImageUpdate(data);
+ */
+ void UpdateInputState(u32 port);
++void UpdateVibration(u32 port, u32 value);
+
+ extern u16 kcode[4];
+ extern u32 vks[4];
+@@ -41,6 +42,11 @@
+ this->dev=dev;
+ }
+
++ void SetVibration(u32 value)
++ {
++ UpdateVibration(dev->bus_id, value);
++ }
++
+ void GetInput(PlainJoystickState* pjs)
+ {
+ UpdateInputState(dev->bus_id);
+diff -Nur a/core/hw/maple/maple_cfg.h b/core/hw/maple/maple_cfg.h
+--- a/core/hw/maple/maple_cfg.h 2016-03-18 23:11:34.099340091 -0300
++++ b/core/hw/maple/maple_cfg.h 2016-03-18 23:12:24.396511206 -0300
+@@ -57,6 +57,7 @@
+
+ struct IMapleConfigMap
+ {
++ virtual void SetVibration(u32 value) = 0;
+ virtual void GetInput(PlainJoystickState* pjs)=0;
+ virtual void SetImage(void* img)=0;
+ virtual ~IMapleConfigMap() {}
+diff -Nur a/core/hw/maple/maple_devs.cpp b/core/hw/maple/maple_devs.cpp
+--- a/core/hw/maple/maple_devs.cpp 2016-03-18 23:11:34.099340091 -0300
++++ b/core/hw/maple/maple_devs.cpp 2016-03-18 23:12:24.396511206 -0300
+@@ -22,6 +22,7 @@
+ const char* maple_sega_dreameye_name_1 = "Dreamcast Camera Flash Devic";
+ const char* maple_sega_dreameye_name_2 = "Dreamcast Camera Flash LDevic";
+ const char* maple_sega_mic_name = "MicDevice for Dreameye";
++const char* maple_sega_purupuru_name = "Puru Puru Pack";
+
+ const char* maple_sega_brand = "Produced By or Under License From SEGA ENTERPRISES,LTD.";
+
+@@ -844,6 +845,98 @@
+ }
+ };
+
++
++struct maple_sega_purupuru : maple_base
++{
++ u16 AST, AST_ms;
++ u32 VIBSET;
++
++ virtual u32 dma(u32 cmd)
++ {
++ switch (cmd)
++ {
++ case MDC_DeviceRequest:
++ //caps
++ //4
++ w32(MFID_8_Vibration);
++
++ //struct data
++ //3*4
++ w32(0x00000101);
++ w32(0);
++ w32(0);
++
++ //1 area code
++ w8(0xFF);
++
++ //1 direction
++ w8(0);
++
++ //30
++ wstr(maple_sega_purupuru_name, 30);
++
++ //60
++ wstr(maple_sega_brand, 60);
++
++ //2
++ w16(0x00C8);
++
++ //2
++ w16(0x0640);
++
++ return MDRS_DeviceStatus;
++
++ //get last vibration
++ case MDCF_GetCondition:
++
++ w32(MFID_8_Vibration);
++
++ w32(VIBSET);
++
++ return MDRS_DataTransfer;
++
++ case MDCF_GetMediaInfo:
++
++ w32(MFID_8_Vibration);
++
++ // PuruPuru vib specs
++ w32(0x3B07E010);
++
++ return MDRS_DataTransfer;
++
++ case MDCF_BlockRead:
++
++ w32(MFID_8_Vibration);
++ w32(0);
++
++ w16(2);
++ w16(AST);
++
++ return MDRS_DataTransfer;
++
++ case MDCF_BlockWrite:
++
++ //Auto-stop time
++ AST = dma_buffer_in[10];
++ AST_ms = AST * 250 + 250;
++
++ return MDRS_DeviceReply;
++
++ case MDCF_SetCondition:
++
++ VIBSET = *(u32*)&dma_buffer_in[4];
++ //Do the rumble thing!
++ config->SetVibration(VIBSET);
++
++ return MDRS_DeviceReply;
++
++ default:
++ //printf("UNKOWN MAPLE COMMAND %d\n",cmd);
++ return MDRE_UnknownFunction;
++ }
++ }
++};
++
+ char EEPROM[0x100];
+ bool EEPROM_loaded = false;
+
+@@ -1300,6 +1393,11 @@
+ rv = new maple_sega_vmu();
+ break;
+
++ case MDT_PurupuruPack:
++ rv = new maple_sega_purupuru();
++ break;
++
++
+
+ case MDT_NaomiJamma:
+ rv = new maple_naomi_jamma();
+diff -Nur a/core/hw/maple/maple_devs.h b/core/hw/maple/maple_devs.h
+--- a/core/hw/maple/maple_devs.h 2016-03-18 23:11:34.099340091 -0300
++++ b/core/hw/maple/maple_devs.h 2016-03-18 23:12:24.396511206 -0300
+@@ -6,6 +6,7 @@
+ MDT_SegaController,
+ MDT_SegaVMU,
+ MDT_Microphone,
++ MDT_PurupuruPack,
+
+ MDT_NaomiJamma,
+
+diff -Nur a/core/linux-dist/evdev.cpp b/core/linux-dist/evdev.cpp
+--- a/core/linux-dist/evdev.cpp 2016-03-18 23:11:34.113340136 -0300
++++ b/core/linux-dist/evdev.cpp 2016-03-18 23:12:24.397511209 -0300
+@@ -102,6 +102,7 @@
+ 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);
++ this->rumble_effect_id = -1;
+ }
+
+ std::map<std::string, EvdevControllerMapping> loaded_mappings;
+@@ -202,7 +203,7 @@
+
+ printf("evdev: Trying to open device at '%s'\n", device);
+
+- int fd = open(device, O_RDONLY);
++ int fd = open(device, O_RDWR);
+
+ if (fd >= 0)
+ {
+@@ -446,5 +447,43 @@
+ }
+ }
+ }
++
++ void input_evdev_rumble(EvdevController* controller, u16 pow_strong, u16 pow_weak)
++ {
++ if (controller->fd < 0 || controller->rumble_effect_id == -2)
++ {
++ // Either the controller is not used or previous rumble effect failed
++ printf("RUMBLE: %s\n", "Skipped!");
++ return;
++ }
++ printf("RUMBLE: %u / %u (%d)\n", pow_strong, pow_weak, controller->rumble_effect_id);
++ struct ff_effect effect;
++ effect.type = FF_RUMBLE;
++ effect.id = controller->rumble_effect_id;
++ effect.u.rumble.strong_magnitude = pow_strong;
++ effect.u.rumble.weak_magnitude = pow_weak;
++ effect.replay.length = 0;
++ effect.replay.delay = 0;
++ if (ioctl(controller->fd, EVIOCSFF, &effect) == -1)
++ {
++ perror("evdev: Force feedback error");
++ controller->rumble_effect_id = -2;
++ }
++ else
++ {
++ controller->rumble_effect_id = effect.id;
++
++ // Let's play the effect
++ input_event play;
++ play.type = EV_FF;
++ play.code = effect.id;
++ play.value = 1;
++ if (write(controller->fd, (const void*) &play, sizeof(play)) == -1)
++ {
++ perror("evdev: Force feedback error");
++ controller->rumble_effect_id = -2;
++ }
++ }
++ }
+ #endif
+
+diff -Nur a/core/linux-dist/evdev.h b/core/linux-dist/evdev.h
+--- a/core/linux-dist/evdev.h 2016-03-18 23:11:34.113340136 -0300
++++ b/core/linux-dist/evdev.h 2016-03-18 23:12:24.397511209 -0300
+@@ -54,6 +54,7 @@
+ EvdevAxisData data_y;
+ EvdevAxisData data_trigger_left;
+ EvdevAxisData data_trigger_right;
++ int rumble_effect_id;
+ void init();
+ };
+
+@@ -72,3 +73,4 @@
+
+ extern int input_evdev_init(EvdevController* controller, const char* device, const char* mapping_fname);
+ extern bool input_evdev_handle(EvdevController* controller, u32 port);
++extern void input_evdev_rumble(EvdevController* controller, u16 pow_strong, u16 pow_weak);
+diff -Nur a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp
+--- a/core/linux-dist/main.cpp 2016-03-18 23:11:34.113340136 -0300
++++ b/core/linux-dist/main.cpp 2016-03-18 23:12:24.397511209 -0300
+@@ -191,6 +191,30 @@
+ #endif
+ }
+
++void UpdateVibration(u32 port, u32 value)
++{
++ #if defined(USE_EVDEV)
++ const u8 freq_l = 0x16;
++ //const u8 freq_h = 0x31;
++
++ u8 POW_POS = (value >> 8) & 0x3;
++ u8 POW_NEG = (value >> 12) & 0x3;
++ u8 FREQ = (value >> 16) & 0xFF;
++
++ double pow = (POW_POS + POW_NEG) / 7.0;
++ double pow_l = pow * (0x3B - FREQ) / 17.0;
++ double pow_r = pow * (FREQ / (double)freq_l);
++
++ if (pow_l > 1.0) pow_l = 1.0;
++ if (pow_r > 1.0) pow_r = 1.0;
++
++ u16 pow_strong = (u16)(65535 * pow_l);
++ u16 pow_weak = (u16)(65535 * pow_r);
++
++ input_evdev_rumble(&evdev_controllers[port], pow_strong, pow_weak);
++ #endif
++}
++
+ void os_DoEvents()
+ {
+ #if defined(SUPPORT_X11)
+diff -Nur a/core/nacl/nacl.cpp b/core/nacl/nacl.cpp
+--- a/core/nacl/nacl.cpp 2016-03-18 23:11:34.114340140 -0300
++++ b/core/nacl/nacl.cpp 2016-03-18 23:12:24.397511209 -0300
+@@ -257,6 +257,10 @@
+
+ }
+
++void UpdateVibration(u32 port, u32 value) {
++
++}
++
+ void os_CreateWindow() {
+
+ }
+diff -Nur a/core/windows/winmain.cpp b/core/windows/winmain.cpp
+--- a/core/windows/winmain.cpp 2016-03-18 23:11:34.119340156 -0300
++++ b/core/windows/winmain.cpp 2016-03-18 23:12:24.399511217 -0300
+@@ -5,6 +5,8 @@
+ #define _WIN32_WINNT 0x0500
+ #include <windows.h>
+
++#include <Xinput.h>
++#pragma comment(lib, "XInput9_1_0.lib")
+
+ PCHAR*
+ CommandLineToArgvA(
+@@ -105,7 +107,7 @@
+ bool VramLockedWrite(u8* address);
+ bool ngen_Rewrite(unat& addr,unat retadr,unat acc);
+ bool BM_LockedWrite(u8* address);
+-
++void UpdateController(u32 port);
+
+ LONG ExeptionHandler(EXCEPTION_POINTERS *ExceptionInfo)
+ {
+@@ -235,6 +237,8 @@
+ if (GetAsyncKeyState(VK_RIGHT))
+ kcode[port]&=~key_CONT_DPAD_RIGHT;
+
++ UpdateController(port);
++
+ if (GetAsyncKeyState(VK_F1))
+ settings.pvr.ta_skip = 100;
+
+@@ -245,7 +249,66 @@
+ DiscSwap();
+ }
+
++void UpdateController(u32 port)
++ {
++ XINPUT_STATE state;
++
++ if (XInputGetState(port, &state) == 0)
++ {
++ WORD xbutton = state.Gamepad.wButtons;
++
++ if (xbutton & XINPUT_GAMEPAD_A)
++ kcode[port] &= ~key_CONT_A;
++ if (xbutton & XINPUT_GAMEPAD_B)
++ kcode[port] &= ~key_CONT_B;
++ if (xbutton & XINPUT_GAMEPAD_Y)
++ kcode[port] &= ~key_CONT_Y;
++ if (xbutton & XINPUT_GAMEPAD_X)
++ kcode[port] &= ~key_CONT_X;
++
++ if (xbutton & XINPUT_GAMEPAD_START)
++ kcode[port] &= ~key_CONT_START;
++
++ if (xbutton & XINPUT_GAMEPAD_DPAD_UP)
++ kcode[port] &= ~key_CONT_DPAD_UP;
++ if (xbutton & XINPUT_GAMEPAD_DPAD_DOWN)
++ kcode[port] &= ~key_CONT_DPAD_DOWN;
++ if (xbutton & XINPUT_GAMEPAD_DPAD_LEFT)
++ kcode[port] &= ~key_CONT_DPAD_LEFT;
++ if (xbutton & XINPUT_GAMEPAD_DPAD_RIGHT)
++ kcode[port] &= ~key_CONT_DPAD_RIGHT;
++
++ lt[port] |= state.Gamepad.bLeftTrigger;
++ rt[port] |= state.Gamepad.bRightTrigger;
++
++ joyx[port] |= state.Gamepad.sThumbLX / 257;
++ joyy[port] |= -state.Gamepad.sThumbLY / 257;
++ }
++ }
+
++void UpdateVibration(u32 port, u32 value)
++{
++ const u8 freq_l = 0x16;
++ //const u8 freq_h = 0x31;
++
++ u8 POW_POS = (value >> 8) & 0x3;
++ u8 POW_NEG = (value >> 12) & 0x3;
++ u8 FREQ = (value >> 16) & 0xFF;
++
++ XINPUT_VIBRATION vib;
++
++ double pow = (POW_POS + POW_NEG) / 7.0;
++ double pow_l = pow * (0x3B - FREQ) / 17.0;
++ double pow_r = pow * (FREQ - 0x07) / 15.0;
++
++ if (pow_l > 1.0) pow_l = 1.0;
++ if (pow_r > 1.0) pow_r = 1.0;
++
++ vib.wLeftMotorSpeed = (u16)(65535 * pow_l);
++ vib.wRightMotorSpeed = (u16)(65535 * pow_r);
++
++ XInputSetState(port, &vib);
++}
+
+ LRESULT CALLBACK WndProc2(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
+ {
+diff -Nur a/shell/android/jni/src/Android.cpp b/shell/android/jni/src/Android.cpp
+--- a/shell/android/jni/src/Android.cpp 2016-03-18 23:11:34.145340240 -0300
++++ b/shell/android/jni/src/Android.cpp 2016-03-18 23:12:24.399511217 -0300
+@@ -231,6 +231,11 @@
+ // @@@ Nothing here yet
+ }
+
++void UpdateVibration(u32 port, u32 value)
++{
++
++}
++
+ void *libPvr_GetRenderTarget()
+ {
+ // No X11 window in Android
+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-03-18 23:11:34.192340393 -0300
++++ b/shell/apple/emulator-ios/emulator/ios_main.mm 2016-03-18 23:12:24.400511220 -0300
+@@ -106,6 +106,10 @@
+
+ }
+
++void UpdateVibration(u32 port, u32 value) {
++
++}
++
+ void get_mic_data(u8* ) {
+
+ }
+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-03-18 23:11:34.194340399 -0300
++++ b/shell/apple/emulator-osx/emulator-osx/osx-main.mm 2016-03-18 23:12:24.401511224 -0300
+@@ -59,6 +59,10 @@
+
+ }
+
++void UpdateVibration(u32 port, u32 value) {
++
++}
++
+ void os_CreateWindow() {
+
+ }