[rocksndiamonds] 01/09: New upstream version 4.0.1.0+dfsg

Stephen Kitt skitt at moszumanska.debian.org
Sat Oct 21 21:16:40 UTC 2017


This is an automated email from the git hooks/post-receive script.

skitt pushed a commit to branch master
in repository rocksndiamonds.

commit 92f36cc62d865d2dd98cc08d944acbe4e1cc2cfe
Author: Stephen Kitt <skitt at debian.org>
Date:   Fri Oct 20 21:55:13 2017 +0200

    New upstream version 4.0.1.0+dfsg
---
 conf/gamecontrollerdb.txt | 181 +++++++++++++
 src/anim.c                | 330 ++++++++++++++++++++++-
 src/anim.h                |   2 +
 src/conf_gfx.c            |  52 +++-
 src/conf_gfx.h            | 668 +++++++++++++++++++++++++---------------------
 src/conftime.h            |   2 +-
 src/events.c              | 262 ++++++++++++------
 src/events.h              |   2 +
 src/files.c               |  92 ++++++-
 src/files.h               |   2 +
 src/game.c                |  23 +-
 src/game.h                |   2 +
 src/game_em/convert.c     |   3 +
 src/game_em/export.h      |   7 +
 src/game_em/input.c       |  18 +-
 src/game_sp/main.c        |   3 +
 src/init.c                |  56 +++-
 src/libgame/joystick.c    |  62 ++++-
 src/libgame/joystick.h    |  25 +-
 src/libgame/misc.c        | 120 ++++++++-
 src/libgame/sdl.c         | 341 ++++++++++++++++++++---
 src/libgame/sdl.h         |  10 +
 src/libgame/setup.c       |  15 +-
 src/libgame/system.c      |  38 ++-
 src/libgame/system.h      |  30 ++-
 src/main.c                |  79 +++++-
 src/main.h                | 113 +++++---
 src/screens.c             | 490 ++++++++++++++++++++++++++++++----
 src/tape.c                |  21 +-
 src/tools.c               |  64 ++++-
 30 files changed, 2525 insertions(+), 588 deletions(-)

diff --git a/conf/gamecontrollerdb.txt b/conf/gamecontrollerdb.txt
new file mode 100644
index 0000000..aefcc11
--- /dev/null
+++ b/conf/gamecontrollerdb.txt
@@ -0,0 +1,181 @@
+# Windows - DINPUT
+8f0e1200000000000000504944564944,Acme,platform:Windows,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+ffff0000000000000000504944564944,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
+6d0416c2000000000000504944564944,Generic DirectInput Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+0d0f6e00000000000000504944564944,HORIPAD 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+6d0419c2000000000000504944564944,Logitech F710 Gamepad,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
+88880803000000000000504944564944,PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b9,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
+4c056802000000000000504944564944,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Windows,
+25090500000000000000504944564944,PS3 DualShock,a:b2,b:b1,back:b9,dpdown:h0.8,dpleft:h0.4,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b0,y:b3,platform:Windows,
+4c05c405000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,
+4c05cc09000000000000504944564944,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,
+4c05a00b000000000000504944564944,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Windows,
+6d0418c2000000000000504944564944,Logitech RumblePad 2 USB,platform:Windows,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+36280100000000000000504944564944,OUYA Controller,platform:Windows,a:b0,b:b3,y:b2,x:b1,start:b14,guide:b15,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b8,dpleft:b10,dpdown:b9,dpright:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b12,righttrigger:b13,
+4f0400b3000000000000504944564944,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Windows,
+00f00300000000000000504944564944,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
+00f0f100000000000000504944564944,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Windows,
+28040140000000000000504944564944,GamePad Pro USB,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
+ff113133000000000000504944564944,SVEN X-PAD,platform:Windows,a:b2,b:b3,y:b1,x:b0,start:b5,back:b4,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b8,righttrigger:b9,
+8f0e0300000000000000504944564944,Piranha xtreme,platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+8f0e0d31000000000000504944564944,Multilaser JS071 USB,platform:Windows,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+10080300000000000000504944564944,PS2 USB,platform:Windows,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a4,righty:a2,lefttrigger:b4,righttrigger:b5,
+79000600000000000000504944564944,G-Shark GS-GP702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,
+4b12014d000000000000504944564944,NYKO AIRFLO,a:b0,b:b1,x:b2,y:b3,back:b8,guide:b10,start:b9,leftstick:a0,rightstick:a2,leftshoulder:a3,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:h0.6,lefty:h0.12,rightx:h0.9,righty:h0.4,lefttrigger:b6,righttrigger:b7,platform:Windows,
+d6206dca000000000000504944564944,PowerA Pro Ex,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.0,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+a3060cff000000000000504944564944,Saitek P2500,a:b2,b:b3,y:b1,x:b0,start:b4,guide:b10,back:b5,leftstick:b8,rightstick:b9,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,
+4f0415b3000000000000504944564944,Thrustmaster Dual Analog 3.2,platform:Windows,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+6f0e1e01000000000000504944564944,Rock Candy Gamepad for PS3,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+83056020000000000000504944564944,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,y:b2,x:b3,start:b7,back:b6,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Windows,
+10080100000000000000504944564944,PS1 USB,platform:Windows,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+49190204000000000000504944564944,Ipega PG-9023,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftstick:b13,rightstick:b14,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b8,righttrigger:b9,platform:Windows,
+4f0423b3000000000000504944564944,Dual Trigger 3-in-1,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,platform:Windows,
+0d0f4900000000000000504944564944,Hatsune Miku Sho Controller,a:b1,b:b2,x:b0,y:b3,back:b8,guide:b12,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+79004318000000000000504944564944,Mayflash GameCube Controller Adapter,platform:Windows,a:b1,b:b2,x:b0,y:b3,back:b0,start:b9,guide:b0,leftshoulder:b4,rightshoulder:b7,leftstick:b0,rightstick:b0,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+79000018000000000000504944564944,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+2509e803000000000000504944564944,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Windows,
+300f1001000000000000504944564944,Saitek P480 Rumble Pad,a:b2,b:b3,x:b0,y:b1,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b5,righttrigger:b7,platform:Windows,
+10280900000000000000504944564944,8Bitdo SFC30 GamePad,a:b1,b:b0,y:b3,x:b4,start:b11,back:b10,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,platform:Windows,
+63252305000000000000504944564944,USB Vibration Joystick (BM),platform:Windows,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+20380900000000000000504944564944,8Bitdo NES30 PRO Wireless,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
+02200090000000000000504944564944,8Bitdo NES30 PRO USB,platform:Windows,a:b0,b:b1,x:b3,y:b4,leftshoulder:b6,rightshoulder:b7,lefttrigger:b8,righttrigger:b9,back:b10,start:b11,leftstick:b13,rightstick:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,dpup:h0.1,dpright:h0.2,dpdown:h0.4,dpleft:h0.8,
+ff113133000000000000504944564944,Gembird JPD-DualForce,platform:Windows,a:b2,b:b3,x:b0,y:b1,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,leftstick:b10,rightstick:b11,
+341a0108000000000000504944564944,EXEQ RF USB Gamepad 8206,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,leftstick:b8,rightstick:b7,back:b8,start:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Windows,
+c0111352000000000000504944564944,Battalife Joystick,platform:Windows,x:b4,a:b6,b:b7,y:b5,back:b2,start:b3,leftshoulder:b0,rightshoulder:b1,leftx:a0,lefty:a1,
+100801e5000000000000504944564944,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Windows,
+79000600000000000000504944564944,NGS Phantom,a:b2,b:b3,y:b1,x:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Windows,
+
+# OS X
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
+6d0400000000000016c2000000000000,Logitech F310 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+6d0400000000000018c2000000000000,Logitech F510 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+6d040000000000001fc2000000000000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+6d0400000000000019c2000000000000,Logitech Wireless Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Mac OS X,
+4c050000000000006802000000000000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Mac OS X,
+4c05000000000000c405000000000000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,
+4c05000000000000cc09000000000000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Mac OS X,
+5e040000000000008e02000000000000,X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+891600000000000000fd000000000000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b8,guide:b10,back:b9,leftstick:b6,rightstick:b7,leftshoulder:b4,rightshoulder:b5,dpup:b11,dpleft:b13,dpdown:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Mac OS X,
+4f0400000000000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Mac OS X,
+8f0e0000000000000300000000000000,Piranha xtreme,platform:Mac OS X,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+0d0f0000000000004d00000000000000,HORI Gem Pad 3,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+79000000000000000600000000000000,G-Shark GP-702,a:b2,b:b1,x:b3,y:b0,back:b8,start:b9,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+4f0400000000000015b3000000000000,Thrustmaster Dual Analog 3.2,platform:Mac OS X,x:b1,a:b0,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+AD1B00000000000001F9000000000000,Gamestop BB-070 X360 Controller,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b8,x:b2,y:b3,platform:Mac OS X,
+050000005769696d6f74652028303000,Wii Remote,a:b4,b:b5,y:b9,x:b10,start:b6,guide:b8,back:b7,dpup:b2,dpleft:b0,dpdown:b3,dpright:b1,leftx:a0,lefty:a1,lefttrigger:b12,righttrigger:,leftshoulder:b11,platform:Mac OS X,
+83050000000000006020000000000000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,
+bd1200000000000015d0000000000000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Mac OS X,
+79000000000000001100000000000000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a3,lefty:a4,platform:Mac OS X,
+5e04000000000000dd02000000000000,Xbox One Wired Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+5e04000000000000ea02000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b9,guide:b10,start:b8,dpleft:b13,dpdown:b12,dpright:b14,dpup:b11,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b6,rightstick:b7,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+5e04000000000000e002000000000000,Xbox Wireless Controller,platform:Mac OS X,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b10,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+050000005769696d6f74652028313800,Wii U Pro Controller,a:b16,b:b15,x:b18,y:b17,back:b7,guide:b8,start:b6,leftstick:b23,rightstick:b24,leftshoulder:b19,rightshoulder:b20,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b21,righttrigger:b22,platform:Mac OS X,
+79000000000000000018000000000000,Mayflash WiiU Pro Game Controller Adapter (DInput),a:b4,b:b8,x:b0,y:b12,back:b32,start:b36,leftstick:b40,rightstick:b44,leftshoulder:b16,rightshoulder:b20,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftx:a0,lefty:a4,rightx:a8,righty:a12,lefttrigger:b24,righttrigger:b28,platform:Mac OS X,
+2509000000000000e803000000000000,Mayflash Wii Classic Controller,a:b1,b:b0,x:b3,y:b2,back:b8,guide:b10,start:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:b11,dpdown:b13,dpleft:b12,dpright:b14,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Mac OS X,
+351200000000000021ab000000000000,SFC30 Joystick,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
+b4040000000000000a01000000000000,Sega Saturn USB Gamepad,a:b0,b:b1,x:b3,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
+81170000000000007e05000000000000,Sega Saturn,x:b0,a:b2,b:b4,y:b6,start:b13,dpleft:b15,dpdown:b16,dpright:b14,dpup:b17,leftshoulder:b8,lefttrigger:a5,lefttrigger:b10,rightshoulder:b9,righttrigger:a4,righttrigger:b11,leftx:a0,lefty:a2,platform:Mac OS X,
+10280000000000000900000000000000,8Bitdo SFC30 GamePad,a:b1,b:b0,x:b4,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Mac OS X,
+d814000000000000cecf000000000000,MC Cthulhu,platform:Mac OS X,leftx:,lefty:,rightx:,righty:,lefttrigger:b6,a:b1,b:b2,y:b3,x:b0,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,righttrigger:b7,
+0d0f0000000000006600000000000000,HORIPAD FPS PLUS 4,platform:Mac OS X,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:a4,
+
+# Linux
+0500000047532047616d657061640000,GameStop Gamepad,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
+03000000ba2200002010000001010000,Jess Technology USB Game Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
+030000006d04000019c2000010010000,Logitech Cordless RumblePad 2,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001dc2000014400000,Logitech F310 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d04000016c2000011010000,Logitech F310 Gamepad (DInput),x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,platform:Linux,
+030000006d0400001ec2000020200000,Logitech F510 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000006d04000019c2000011010000,Logitech F710 Gamepad (DInput),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
+030000006d0400001fc2000005030000,Logitech F710 Gamepad (XInput),a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000004c0500006802000011010000,PS3 Controller,a:b14,b:b13,back:b0,dpdown:b6,dpleft:b7,dpright:b5,dpup:b4,guide:b16,leftshoulder:b10,leftstick:b1,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b2,righttrigger:b9,rightx:a2,righty:a3,start:b3,x:b15,y:b12,platform:Linux,
+030000004c050000c405000011010000,Sony DualShock 4,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
+050000004c050000c405000000010000,Sony DualShock 4 BT,a:b1,b:b2,back:b13,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
+030000004c050000cc09000011010000,Sony DualShock 4 V2,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
+050000004c050000cc09000000010000,Sony DualShock 4 V2 BT,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
+030000004c050000a00b000011010000,Sony DualShock 4 Wireless Adaptor,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b13,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:a3,righttrigger:a4,platform:Linux,
+030000006f0e00003001000001010000,EA Sports PS3 Controller,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+03000000de280000ff11000001000000,Valve Streaming Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000014010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400008e02000010010000,X360 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+030000005e0400001907000000010000,X360 Wireless Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b11,dpright:b12,dpup:b13,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
+03000000100800000100000010010000,Twin USB PS2 Adapter,a:b2,b:b1,y:b0,x:b3,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
+03000000a306000023f6000011010000,Saitek Cyborg V.1 Game Pad,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a4,lefttrigger:b6,righttrigger:b7,platform:Linux,
+030000004f04000020b3000010010000,Thrustmaster 2 in 1 DT,a:b0,b:b2,y:b3,x:b1,start:b9,guide:,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
+030000004f04000023b3000000010000,Thrustmaster Dual Trigger 3-in-1,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a5,
+030000008f0e00000300000010010000,GreenAsia Inc.    USB Joystick     ,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+030000008f0e00001200000010010000,GreenAsia Inc.      USB  Joystick  ,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a2,
+030000005e0400009102000007010000,X360 Wireless Controller,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000006d04000016c2000010010000,Logitech Logitech Dual Action,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+03000000260900008888000000010000,GameCube {WiseGroup USB box},a:b0,b:b2,y:b3,x:b1,start:b7,leftshoulder:,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,rightstick:,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a4,righttrigger:a5,platform:Linux,
+030000006d04000011c2000010010000,Logitech WingMan Cordless RumblePad,a:b0,b:b1,y:b4,x:b3,start:b8,guide:b5,back:b2,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:b9,righttrigger:b10,platform:Linux,
+030000006d04000018c2000010010000,Logitech Logitech RumblePad 2 USB,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+05000000d6200000ad0d000001000000,Moga Pro,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b6,leftstick:b7,rightstick:b8,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:a5,righttrigger:a4,
+030000004f04000009d0000000010000,Thrustmaster Run N Drive Wireless PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,guide:b12,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+030000004f04000008d0000000010000,Thrustmaster Run N Drive  Wireless,platform:Linux,a:b1,b:b2,x:b0,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a5,lefttrigger:b6,righttrigger:b7,
+0300000000f000000300000000010000,RetroUSB.com RetroPad,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
+0300000000f00000f100000000010000,RetroUSB.com Super RetroPort,a:b1,b:b5,x:b0,y:b4,back:b2,start:b3,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,platform:Linux,
+030000006f0e00001f01000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000280400000140000000010000,Gravis GamePad Pro USB ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftx:a0,lefty:a1,
+030000005e0400008902000021010000,Microsoft X-Box pad v2 (US),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000005e0400008502000000010000,Microsoft X-Box pad (Japan),platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b6,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:a2,rightshoulder:b2,righttrigger:a5,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000006f0e00001e01000011010000,Rock Candy Gamepad for PS3,platform:Linux,a:b1,b:b2,x:b0,y:b3,back:b8,start:b9,guide:b12,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+03000000250900000500000000010000,Sony PS2 pad with SmartJoy adapter,platform:Linux,a:b2,b:b1,y:b0,x:b3,start:b8,back:b9,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,
+030000008916000000fd000024010000,Razer Onza Tournament,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:b13,dpleft:b11,dpdown:b14,dpright:b12,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+030000004f04000000b3000010010000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,y:b3,x:b1,start:b10,guide:b8,back:b9,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,platform:Linux,
+03000000ad1b000001f5000033050000,Hori Pad EX Turbo 2,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,platform:Linux,
+060000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
+050000004c0500006802000000010000,PS3 Controller (Bluetooth),a:b14,b:b13,y:b12,x:b15,start:b3,guide:b16,back:b0,leftstick:b1,rightstick:b2,leftshoulder:b10,rightshoulder:b11,dpup:b4,dpleft:b7,dpdown:b6,dpright:b5,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b8,righttrigger:b9,platform:Linux,
+03000000790000000600000010010000,DragonRise Inc.   Generic   USB  Joystick  ,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a3,rightx:a1,righty:a4,
+03000000666600000488000000010000,Super Joy Box 5 Pro,platform:Linux,a:b2,b:b1,x:b3,y:b0,back:b9,start:b8,leftshoulder:b6,rightshoulder:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b4,righttrigger:b5,dpup:b12,dpleft:b15,dpdown:b14,dpright:b13,
+05000000362800000100000002010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
+05000000362800000100000003010000,OUYA Game Controller,a:b0,b:b3,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b14,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,platform:Linux,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,
+030000008916000001fd000024010000,Razer Onza Classic Edition,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:b11,dpdown:b14,dpright:b12,dpup:b13,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000005e040000d102000001010000,Microsoft X-Box One pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000005e040000dd02000003020000,Microsoft X-Box One pad v2,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,
+03000000790000001100000010010000,RetroLink Saturn Classic Controller,platform:Linux,x:b3,a:b0,b:b1,y:b4,back:b5,guide:b2,start:b8,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
+050000007e0500003003000001000000,Nintendo Wii U Pro Controller,platform:Linux,a:b0,b:b1,x:b3,y:b2,back:b8,start:b9,guide:b10,leftshoulder:b4,rightshoulder:b5,leftstick:b11,rightstick:b12,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,dpup:b13,dpleft:b15,dpdown:b14,dpright:b16,
+030000005e0400008e02000004010000,Microsoft X-Box 360 pad,platform:Linux,a:b0,b:b1,x:b2,y:b3,back:b6,start:b7,guide:b8,leftshoulder:b4,rightshoulder:b5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,
+030000000d0f00002200000011010000,HORI CO. LTD. REAL ARCADE Pro.V3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,
+030000000d0f00001000000011010000,HORI CO. LTD. FIGHTING STICK 3,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7
+03000000f0250000c183000010010000,Goodbetterbest Ltd USB Controller,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+0000000058626f782047616d65706100,Xbox Gamepad (userspace driver),platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b7,back:b6,guide:b8,dpup:h0.1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,lefttrigger:a5,righttrigger:a4,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+03000000ff1100003133000010010000,PC Game Controller,a:b2,b:b1,y:b0,x:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,platform:Linux,
+030000005e0400008e02000020200000,SpeedLink XEOX Pro Analog Gamepad pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000006f0e00001304000000010000,Generic X-Box pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:a0,rightstick:a3,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000a306000018f5000010010000,Saitek PLC Saitek P3200 Rumble Pad,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,start:b9,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000830500006020000010010000,iBuffalo USB 2-axis 8-button Gamepad,a:b1,b:b0,x:b3,y:b2,back:b6,start:b7,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,
+03000000bd12000015d0000010010000,Tomee SNES USB Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,
+03000000790000001100000010010000,Retrolink Classic Controller,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,platform:Linux,
+03000000c9110000f055000011010000,HJC Game GAMEPAD,leftx:a0,lefty:a1,dpdown:h0.4,rightstick:b11,rightshoulder:b5,rightx:a2,start:b9,righty:a3,dpleft:h0.8,lefttrigger:b6,x:b2,dpup:h0.1,back:b8,leftstick:b10,leftshoulder:b4,y:b3,a:b0,dpright:h0.2,righttrigger:b7,b:b1,platform:Linux,
+03000000a30600000c04000011010000,Saitek P2900 Wireless Pad,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,platform:Linux,
+03000000341a000005f7000010010000,GameCube {HuiJia USB box},a:b1,b:b2,y:b3,x:b0,start:b9,guide:,back:,leftstick:,rightstick:,leftshoulder:,dpleft:b15,dpdown:b14,dpright:b13,leftx:a0,lefty:a1,rightx:a5,righty:a2,lefttrigger:a3,righttrigger:a4,rightshoulder:b7,dpup:b12,platform:Linux,
+030000006e0500000320000010010000,JC-U3613M - DirectInput Mode,platform:Linux,x:b0,a:b2,b:b3,y:b1,back:b10,guide:b12,start:b11,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b8,rightstick:b9,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+030000006f0e00004601000001010000,Rock Candy Wired Controller for Xbox One,platform:Linux,a:b0,b:b1,x:b2,y:b3,leftshoulder:b4,rightshoulder:b5,back:b6,start:b7,guide:b8,leftstick:b9,rightstick:b10,lefttrigger:a2,righttrigger:a5,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000380700001647000010040000,Mad Catz Wired Xbox 360 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+030000006f0e00003901000020060000,Afterglow Wired Controller for Xbox One,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,platform:Linux,
+030000004f04000015b3000010010000,Thrustmaster Dual Analog 4,platform:Linux,a:b0,b:b2,x:b1,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b4,rightshoulder:b6,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b5,righttrigger:b7,
+05000000102800000900000000010000,8Bitdo SFC30 GamePad,platform:Linux,x:b4,a:b1,b:b0,y:b3,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
+03000000d81400000862000011010000,HitBox (PS3/PC) Analog Mode,platform:Linux,a:b1,b:b2,y:b3,x:b0,start:b12,guide:b9,back:b8,leftshoulder:b4,rightshoulder:b5,lefttrigger:b6,righttrigger:b7,leftx:a0,lefty:a1,
+030000000d0f00000d00000000010000,hori,platform:Linux,a:b0,b:b6,y:b2,x:b1,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,start:b9,guide:b10,back:b8,leftshoulder:b3,rightshoulder:b7,leftx:b4,lefty:b5,
+03000000ad1b000016f0000090040000,Mad Catz Xbox 360 Controller,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftstick:b9,rightstick:b10,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a4,lefttrigger:a2,righttrigger:a5,
+03000000d814000007cd000011010000,Toodles 2008 Chimp PC/PS3,platform:Linux,a:b0,b:b1,y:b2,x:b3,start:b9,back:b8,leftshoulder:b4,rightshoulder:b5,leftx:a0,lefty:a1,lefttrigger:b6,righttrigger:b7,
+03000000fd0500000030000000010000,InterAct GoPad I-73000 (Fighting Game Layout),platform:Linux,a:b3,b:b4,y:b1,x:b0,start:b7,back:b6,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,
+05000000010000000100000003000000,Nintendo Wiimote,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b9,guide:b10,back:b8,leftstick:b11,rightstick:b12,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7,
+030000005e0400008e02000062230000,Microsoft X-Box 360 pad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000a30600000901000000010000,Saitek P880,a:b2,b:b3,y:b1,x:b0,leftstick:b8,rightstick:b9,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b6,righttrigger:b7,platform:Linux,
+030000006f0e00000103000000020000,Logic3 Controller,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.0,dpdown:h0.4,dpright:h0.0,dpright:h0.2,dpup:h0.0,dpup:h0.1,leftshoulder:h0.0,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+05000000380700006652000025010000,Mad Catz C.T.R.L.R ,platform:Linux,x:b0,a:b1,b:b2,y:b3,back:b8,guide:b12,start:b9,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,
+030000005e0400008e02000073050000,Speedlink TORID Wireless Gamepad,platform:Linux,x:b2,a:b0,b:b1,y:b3,back:b6,guide:b8,start:b7,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,leftstick:b9,rightstick:b10,leftx:a0,lefty:a1,rightx:a3,righty:a4,
+03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,platform:Linux,a:b0,b:b1,y:b3,x:b2,start:b7,guide:b8,back:b6,leftshoulder:b4,rightshoulder:b5,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,lefttrigger:a2,righttrigger:a5,
+05000000a00500003232000001000000,8Bitdo Zero GamePad,platform:Linux,a:b0,b:b1,x:b3,y:b4,back:b10,start:b11,leftshoulder:b6,rightshoulder:b7,leftx:a0,lefty:a1,
+030000001008000001e5000010010000,NEXT Classic USB Game Controller,a:b0,b:b1,back:b8,start:b9,rightx:a2,righty:a3,leftx:a0,lefty:a1,platform:Linux,
+03000000100800000300000010010000,USB Gamepad,platform:Linux,a:b2,b:b1,x:b3,y:b0,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,
+05000000ac0500003232000001000000,VR-BOX,platform:Linux,a:b0,b:b1,x:b2,y:b3,start:b9,back:b8,leftstick:b10,rightstick:b11,leftshoulder:b6,rightshoulder:b7,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftx:a0,lefty:a1,rightx:a3,righty:a2,lefttrigger:b4,righttrigger:b5,
+03000000780000000600000010010000,Microntek USB Joystick,platform:Linux,x:b3,a:b2,b:b1,y:b0,back:b8,start:b9,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,leftx:a0,lefty:a1,
+
+# custom game controller mappings
+756e7520636f6e74726f6c6c65720000,SnakeByte GamePad,platform:Android,x:b2,a:b0,b:b1,y:b3,back:b4,start:b6,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,dpup:h0.1,leftshoulder:b9,lefttrigger:a6,rightshoulder:b10,righttrigger:a7,leftstick:b7,rightstick:b8,leftx:a0,lefty:a1,rightx:a2,righty:a5,
+030000000b0400003365000000010000,Competition Pro Joystick,platform:Linux,x:b2,a:b0,b:b1,y:b3,leftx:a0,lefty:a1,
+416d617a6f6e20466972652054562052,Amazon Fire TV Remote,platform:Android,a:b19,dpup:b11,dpdown:b12,dpleft:b13,dpright:b14,
diff --git a/src/anim.c b/src/anim.c
index b9ea8be..37c7193 100644
--- a/src/anim.c
+++ b/src/anim.c
@@ -9,6 +9,8 @@
 // anim.c
 // ============================================================================
 
+#include "libgame/libgame.h"
+
 #include "anim.h"
 #include "main.h"
 #include "tools.h"
@@ -27,20 +29,25 @@
 #define ANIM_CLASS_BIT_TITLE_INITIAL	0
 #define ANIM_CLASS_BIT_TITLE		1
 #define ANIM_CLASS_BIT_MAIN		2
-#define ANIM_CLASS_BIT_SUBMENU		3
-#define ANIM_CLASS_BIT_MENU		4
-#define ANIM_CLASS_BIT_TOONS		5
+#define ANIM_CLASS_BIT_SCORES		3
+#define ANIM_CLASS_BIT_SUBMENU		4
+#define ANIM_CLASS_BIT_MENU		5
+#define ANIM_CLASS_BIT_TOONS		6
 
-#define NUM_ANIM_CLASSES		6
+#define NUM_ANIM_CLASSES		7
 
 #define ANIM_CLASS_NONE			0
 #define ANIM_CLASS_TITLE_INITIAL	(1 << ANIM_CLASS_BIT_TITLE_INITIAL)
 #define ANIM_CLASS_TITLE		(1 << ANIM_CLASS_BIT_TITLE)
 #define ANIM_CLASS_MAIN			(1 << ANIM_CLASS_BIT_MAIN)
+#define ANIM_CLASS_SCORES		(1 << ANIM_CLASS_BIT_SCORES)
 #define ANIM_CLASS_SUBMENU		(1 << ANIM_CLASS_BIT_SUBMENU)
 #define ANIM_CLASS_MENU			(1 << ANIM_CLASS_BIT_MENU)
 #define ANIM_CLASS_TOONS		(1 << ANIM_CLASS_BIT_TOONS)
 
+#define ANIM_CLASS_TOONS_SCORES		(ANIM_CLASS_TOONS |	\
+					 ANIM_CLASS_SCORES)
+
 #define ANIM_CLASS_TOONS_MENU_MAIN	(ANIM_CLASS_TOONS |	\
 					 ANIM_CLASS_MENU  |	\
 					 ANIM_CLASS_MAIN)
@@ -64,10 +71,15 @@
 
 struct GlobalAnimPartControlInfo
 {
+  int old_nr;		// position before mapping animation parts linearly
+  int old_anim_nr;	// position before mapping animations linearly
+
   int nr;
   int anim_nr;
   int mode_nr;
 
+  boolean is_base;	// animation part is base/main/default animation part
+
   int sound;
   int music;
   int graphic;
@@ -90,6 +102,12 @@ struct GlobalAnimPartControlInfo
   int anim_delay_counter;
   int post_delay_counter;
 
+  boolean init_event_state;
+  boolean anim_event_state;
+
+  boolean clickable;
+  boolean clicked;
+
   int drawing_stage;
 
   int state;
@@ -106,11 +124,14 @@ struct GlobalAnimMainControlInfo
 
   struct GraphicInfo control_info;
 
-  int num_parts;
+  int num_parts;	// number of animation parts, but without base part
+  int num_parts_all;	// number of animation parts, including base part
   int part_counter;
   int active_part_nr;
 
-  boolean has_base;
+  boolean has_base;	// animation has base/main/default animation part
+
+  int last_x, last_y;
 
   int init_delay_counter;
 
@@ -149,7 +170,8 @@ struct GameModeAnimClass
   { GAME_MODE_SETUP,			ANIM_CLASS_TOONS_MENU_SUBMENU	},
   { GAME_MODE_PSEUDO_MAINONLY,		ANIM_CLASS_TOONS_MENU_MAIN	},
   { GAME_MODE_PSEUDO_TYPENAME,		ANIM_CLASS_TOONS_MENU_MAIN	},
-  { GAME_MODE_SCORES,			ANIM_CLASS_TOONS		},
+  { GAME_MODE_PSEUDO_SCORESOLD,		ANIM_CLASS_TOONS_SCORES		},
+  { GAME_MODE_PSEUDO_SCORESNEW,		ANIM_CLASS_TOONS_SCORES		},
 
   { -1,					-1				}
 };
@@ -163,6 +185,7 @@ struct AnimClassGameMode
   { ANIM_CLASS_BIT_TITLE_INITIAL,	GAME_MODE_TITLE_INITIAL		},
   { ANIM_CLASS_BIT_TITLE,		GAME_MODE_TITLE			},
   { ANIM_CLASS_BIT_MAIN,		GAME_MODE_MAIN			},
+  { ANIM_CLASS_BIT_SCORES,		GAME_MODE_SCORES		},
   { ANIM_CLASS_BIT_SUBMENU,		GAME_MODE_PSEUDO_SUBMENU	},
   { ANIM_CLASS_BIT_MENU,		GAME_MODE_PSEUDO_MENU		},
   { ANIM_CLASS_BIT_TOONS,		GAME_MODE_PSEUDO_TOONS		},
@@ -173,6 +196,8 @@ struct AnimClassGameMode
 /* forward declaration for internal use */
 static void HandleGlobalAnim(int, int);
 static void DoAnimationExt(void);
+static void ResetGlobalAnim_Clickable();
+static void ResetGlobalAnim_Clicked();
 
 static struct GlobalAnimControlInfo global_anim_ctrl[NUM_GAME_MODES];
 
@@ -318,11 +343,15 @@ static void InitToonControls()
   anim->control_info = graphic_info[control];
 
   anim->num_parts = 0;
+  anim->num_parts_all = 0;
   anim->part_counter = 0;
   anim->active_part_nr = 0;
 
   anim->has_base = FALSE;
 
+  anim->last_x = POS_OFFSCREEN;
+  anim->last_y = POS_OFFSCREEN;
+
   anim->init_delay_counter = 0;
 
   anim->state = ANIM_STATE_INACTIVE;
@@ -340,9 +369,13 @@ static void InitToonControls()
     part->nr = part_nr;
     part->anim_nr = anim_nr;
     part->mode_nr = mode_nr;
+
+    part->is_base = FALSE;
+
     part->sound = sound;
     part->music = music;
     part->graphic = graphic;
+
     part->graphic_info = graphic_info[graphic];
     part->control_info = graphic_info[control];
 
@@ -363,6 +396,8 @@ static void InitToonControls()
     part->last_anim_status = -1;
 
     anim->num_parts++;
+    anim->num_parts_all++;
+
     part_nr++;
   }
 
@@ -404,11 +439,15 @@ void InitGlobalAnimControls()
       anim->control_info = graphic_info[control];
 
       anim->num_parts = 0;
+      anim->num_parts_all = 0;
       anim->part_counter = 0;
       anim->active_part_nr = 0;
 
       anim->has_base = FALSE;
 
+      anim->last_x = POS_OFFSCREEN;
+      anim->last_y = POS_OFFSCREEN;
+
       anim->init_delay_counter = 0;
 
       anim->state = ANIM_STATE_INACTIVE;
@@ -438,12 +477,17 @@ void InitGlobalAnimControls()
 	       m, a, p, mode_nr, anim_nr, part_nr, sound);
 #endif
 
+	part->old_nr = p;
+	part->old_anim_nr = a;
+
 	part->nr = part_nr;
 	part->anim_nr = anim_nr;
 	part->mode_nr = mode_nr;
+
 	part->sound = sound;
 	part->music = music;
 	part->graphic = graphic;
+
 	part->graphic_info = graphic_info[graphic];
 	part->control_info = graphic_info[control];
 
@@ -455,13 +499,19 @@ void InitGlobalAnimControls()
 	part->state = ANIM_STATE_INACTIVE;
 	part->last_anim_status = -1;
 
+	anim->num_parts_all++;
+
 	if (p < GLOBAL_ANIM_ID_PART_BASE)
 	{
+	  part->is_base = FALSE;
+
 	  anim->num_parts++;
 	  part_nr++;
 	}
 	else
 	{
+	  part->is_base = TRUE;
+
 	  anim->base = *part;
 	  anim->has_base = TRUE;
 	}
@@ -663,6 +713,10 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
 	int cut_y = 0;
 	int sync_frame;
 	int frame;
+	void (*blit_bitmap)(Bitmap *, Bitmap *, int, int, int, int, int, int) =
+	  (g->draw_masked ? BlitBitmapMasked : BlitBitmap);
+	void (*blit_screen)(Bitmap *, int, int, int, int, int, int) =
+	  (g->draw_masked ? BlitToScreenMasked : BlitToScreen);
 
 	if (!(part->state & ANIM_STATE_RUNNING))
 	  continue;
@@ -706,11 +760,11 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
 	src_y += cut_y;
 
 	if (drawing_target == DRAW_TO_SCREEN)
-	  BlitToScreenMasked(src_bitmap, src_x, src_y, width, height,
-			     dst_x, dst_y);
+	  blit_screen(src_bitmap, src_x, src_y, width, height,
+		      dst_x, dst_y);
 	else
-	  BlitBitmapMasked(src_bitmap, fade_bitmap, src_x, src_y, width, height,
-			   dst_x, dst_y);
+	  blit_bitmap(src_bitmap, fade_bitmap, src_x, src_y, width, height,
+		      dst_x, dst_y);
       }
     }
   }
@@ -728,7 +782,13 @@ void DrawGlobalAnimationsExt(int drawing_target, int drawing_stage)
 
 void DrawGlobalAnimations(int drawing_target, int drawing_stage)
 {
+  if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_1)
+    ResetGlobalAnim_Clickable();
+
   DrawGlobalAnimationsExt(drawing_target, drawing_stage);
+
+  if (drawing_stage == DRAW_GLOBAL_ANIM_STAGE_2)
+    ResetGlobalAnim_Clicked();
 }
 
 boolean SetGlobalAnimPart_Viewport(struct GlobalAnimPartControlInfo *part)
@@ -881,8 +941,59 @@ static void StopGlobalAnimSoundAndMusic(struct GlobalAnimPartControlInfo *part)
   StopGlobalAnimMusic(part);
 }
 
+static boolean isClickablePart(struct GlobalAnimPartControlInfo *part, int mask)
+{
+  struct GraphicInfo *c = &part->control_info;
+  int trigger_mask = ANIM_EVENT_ANIM_MASK | ANIM_EVENT_PART_MASK;
+  int mask_anim_only = mask & ANIM_EVENT_ANIM_MASK;
+
+  if (mask & ANIM_EVENT_ANY)
+    return (c->init_event & ANIM_EVENT_ANY ||
+	    c->anim_event & ANIM_EVENT_ANY);
+  else if (mask & ANIM_EVENT_SELF)
+    return (c->init_event & ANIM_EVENT_SELF ||
+	    c->anim_event & ANIM_EVENT_SELF);
+  else
+    return ((c->init_event & trigger_mask) == mask ||
+	    (c->anim_event & trigger_mask) == mask ||
+	    (c->init_event & trigger_mask) == mask_anim_only ||
+	    (c->anim_event & trigger_mask) == mask_anim_only);
+}
+
+static boolean isClickedPart(struct GlobalAnimPartControlInfo *part,
+			     int mx, int my, boolean clicked)
+{
+  struct GraphicInfo *g = &part->graphic_info;
+  int part_x = part->viewport_x + part->x;
+  int part_y = part->viewport_y + part->y;
+  int part_width  = g->width;
+  int part_height = g->height;
+
+  // check if mouse click was detected at all
+  if (!clicked)
+    return FALSE;
+
+  // check if mouse click is inside the animation part's viewport
+  if (mx <  part->viewport_x ||
+      mx >= part->viewport_x + part->viewport_width ||
+      my <  part->viewport_y ||
+      my >= part->viewport_y + part->viewport_height)
+    return FALSE;
+
+  // check if mouse click is inside the animation part's graphic
+  if (mx <  part_x ||
+      mx >= part_x + part_width ||
+      my <  part_y ||
+      my >= part_y + part_height)
+    return FALSE;
+
+  return TRUE;
+}
+
 int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
 {
+  struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[part->mode_nr];
+  struct GlobalAnimMainControlInfo *anim = &ctrl->anim[part->anim_nr];
   struct GraphicInfo *g = &part->graphic_info;
   struct GraphicInfo *c = &part->control_info;
   boolean viewport_changed = SetGlobalAnimPart_Viewport(part);
@@ -905,6 +1016,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
     part->anim_delay_counter =
       (c->anim_delay_fixed + GetSimpleRandom(c->anim_delay_random));
 
+    part->init_event_state = c->init_event;
+    part->anim_event_state = c->anim_event;
+
     part->initial_anim_sync_frame =
       (g->anim_global_sync ? 0 : anim_sync_frame + part->init_delay_counter);
 
@@ -976,31 +1090,74 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
     if (c->y != ARG_UNDEFINED_VALUE)
       part->y = c->y;
 
+    if (c->position == POS_LAST &&
+	anim->last_x > -g->width  && anim->last_x < part->viewport_width &&
+	anim->last_y > -g->height && anim->last_y < part->viewport_height)
+    {
+      part->x = anim->last_x;
+      part->y = anim->last_y;
+    }
+
     if (c->step_xoffset != ARG_UNDEFINED_VALUE)
       part->step_xoffset = c->step_xoffset;
     if (c->step_yoffset != ARG_UNDEFINED_VALUE)
       part->step_yoffset = c->step_yoffset;
 
-    if (part->init_delay_counter == 0)
+    if (part->init_delay_counter == 0 &&
+	part->init_event_state == ANIM_EVENT_NONE)
       PlayGlobalAnimSoundAndMusic(part);
   }
 
+  if (part->clicked &&
+      part->init_event_state != ANIM_EVENT_NONE)
+  {
+    if (part->initial_anim_sync_frame > 0)
+      part->initial_anim_sync_frame -= part->init_delay_counter - 1;
+
+    part->init_delay_counter = 1;
+    part->init_event_state = ANIM_EVENT_NONE;
+
+    part->clicked = FALSE;
+  }
+
+  if (part->clicked &&
+      part->anim_event_state != ANIM_EVENT_NONE)
+  {
+    part->anim_delay_counter = 1;
+    part->anim_event_state = ANIM_EVENT_NONE;
+
+    part->clicked = FALSE;
+  }
+
   if (part->init_delay_counter > 0)
   {
     part->init_delay_counter--;
 
     if (part->init_delay_counter == 0)
+    {
+      part->init_event_state = ANIM_EVENT_NONE;
+
       PlayGlobalAnimSoundAndMusic(part);
+    }
 
     return ANIM_STATE_WAITING;
   }
 
+  if (part->init_event_state != ANIM_EVENT_NONE)
+    return ANIM_STATE_WAITING;
+
+  // animation part is now running/visible and therefore clickable
+  part->clickable = TRUE;
+
   // check if moving animation has left the visible screen area
   if ((part->x <= -g->width              && part->step_xoffset <= 0) ||
       (part->x >=  part->viewport_width  && part->step_xoffset >= 0) ||
       (part->y <= -g->height             && part->step_yoffset <= 0) ||
       (part->y >=  part->viewport_height && part->step_yoffset >= 0))
   {
+    // do not wait for "anim" events for off-screen animations
+    part->anim_event_state = ANIM_EVENT_NONE;
+
     // do not stop animation before "anim" or "post" counter are finished
     if (part->anim_delay_counter == 0 &&
 	part->post_delay_counter == 0)
@@ -1024,6 +1181,8 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
 
     if (part->anim_delay_counter == 0)
     {
+      part->anim_event_state = ANIM_EVENT_NONE;
+
       StopGlobalAnimSoundAndMusic(part);
 
       part->post_delay_counter =
@@ -1066,6 +1225,9 @@ int HandleGlobalAnim_Part(struct GlobalAnimPartControlInfo *part, int state)
   part->x += part->step_xoffset;
   part->y += part->step_yoffset;
 
+  anim->last_x = part->x;
+  anim->last_y = part->y;
+
   return ANIM_STATE_RUNNING;
 }
 
@@ -1263,3 +1425,147 @@ static void DoAnimationExt()
   redraw_mask = REDRAW_ALL;
 #endif
 }
+
+static void InitGlobalAnim_Clickable()
+{
+  int mode_nr;
+
+  for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+  {
+    struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+    int anim_nr;
+
+    for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
+    {
+      struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+      int part_nr;
+
+      for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++)
+      {
+	struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+
+	part->clickable = FALSE;
+      }
+    }
+  }
+}
+
+static boolean InitGlobalAnim_Clicked(int mx, int my, boolean clicked)
+{
+  boolean any_part_clicked = FALSE;
+  int mode_nr;
+
+  for (mode_nr = 0; mode_nr < NUM_GAME_MODES; mode_nr++)
+  {
+    struct GlobalAnimControlInfo *ctrl = &global_anim_ctrl[mode_nr];
+    int anim_nr;
+
+    for (anim_nr = 0; anim_nr < ctrl->num_anims; anim_nr++)
+    {
+      struct GlobalAnimMainControlInfo *anim = &ctrl->anim[anim_nr];
+      int part_nr;
+
+      for (part_nr = 0; part_nr < anim->num_parts_all; part_nr++)
+      {
+	struct GlobalAnimPartControlInfo *part = &anim->part[part_nr];
+
+	if (!clicked)
+	{
+	  part->clicked = FALSE;
+
+	  continue;
+	}
+
+	if (!part->clickable)
+	  continue;
+
+	if (isClickablePart(part, ANIM_EVENT_ANY))
+	  any_part_clicked = part->clicked = TRUE;
+
+	if (isClickedPart(part, mx, my, clicked))
+	{
+#if 0
+	  printf("::: %d.%d CLICKED\n", anim_nr, part_nr);
+#endif
+
+	  if (isClickablePart(part, ANIM_EVENT_SELF))
+	    any_part_clicked = part->clicked = TRUE;
+
+	  // check if this click is defined to trigger other animations
+	  int gic_anim_nr = part->old_anim_nr + 1;	// X as in "anim_X"
+	  int gic_part_nr = part->old_nr + 1;		// Y as in "part_Y"
+	  int mask = gic_anim_nr << ANIM_EVENT_ANIM_BIT;
+
+	  if (!part->is_base)
+	    mask |= gic_part_nr << ANIM_EVENT_PART_BIT;
+
+	  int anim2_nr;
+
+	  for (anim2_nr = 0; anim2_nr < ctrl->num_anims; anim2_nr++)
+	  {
+	    struct GlobalAnimMainControlInfo *anim2 = &ctrl->anim[anim2_nr];
+	    int part2_nr;
+
+	    for (part2_nr = 0; part2_nr < anim2->num_parts_all; part2_nr++)
+	    {
+	      struct GlobalAnimPartControlInfo *part2 = &anim2->part[part2_nr];
+
+	      if (isClickablePart(part2, mask))
+		any_part_clicked = part2->clicked = TRUE;
+
+#if 0
+	      struct GraphicInfo *c = &part2->control_info;
+
+	      printf("::: - %d.%d: 0x%08x, 0x%08x [0x%08x]",
+		     anim2_nr, part2_nr, c->init_event, c->anim_event, mask);
+
+	      if (isClickablePart(part2, mask))
+		printf(" <--- TRIGGERED BY %d.%d",
+		       anim_nr, part_nr);
+
+	      printf("\n");
+#endif
+	    }
+	  }
+	}
+      }
+    }
+  }
+
+  return any_part_clicked;
+}
+
+static void ResetGlobalAnim_Clickable()
+{
+  InitGlobalAnim_Clickable();
+}
+
+static void ResetGlobalAnim_Clicked()
+{
+  InitGlobalAnim_Clicked(-1, -1, FALSE);
+}
+
+boolean HandleGlobalAnimClicks(int mx, int my, int button)
+{
+  static boolean click_consumed = FALSE;
+  static int last_button = 0;
+  boolean press_event;
+  boolean release_event;
+  boolean click_consumed_current = click_consumed;
+
+  /* check if button state has changed since last invocation */
+  press_event   = (button != 0 && last_button == 0);
+  release_event = (button == 0 && last_button != 0);
+  last_button = button;
+
+  if (press_event)
+  {
+    click_consumed = InitGlobalAnim_Clicked(mx, my, TRUE);
+    click_consumed_current = click_consumed;
+  }
+
+  if (release_event)
+    click_consumed = FALSE;
+
+  return click_consumed_current;
+}
diff --git a/src/anim.h b/src/anim.h
index 99de93e..6b87a04 100644
--- a/src/anim.h
+++ b/src/anim.h
@@ -18,4 +18,6 @@ int getAnimationFrame(int, int, int, int, int);
 void InitGlobalAnimations(void);
 void DrawGlobalAnimations(int, int);
 
+boolean HandleGlobalAnimClicks(int, int, int);
+
 #endif
diff --git a/src/conf_gfx.c b/src/conf_gfx.c
index 9693b1f..745a464 100644
--- a/src/conf_gfx.c
+++ b/src/conf_gfx.c
@@ -52,7 +52,7 @@ struct ConfigTypeInfo image_config_suffix[] =
   { ".position",			ARG_UNDEFINED,	TYPE_STRING	},
   { ".draw_xoffset",			"0",		TYPE_INTEGER	},
   { ".draw_yoffset",			"0",		TYPE_INTEGER	},
-  { ".draw_masked",			"false",	TYPE_BOOLEAN	},
+  { ".draw_masked",			ARG_UNDEFINED,	TYPE_BOOLEAN	},
   { ".draw_order",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".init_delay_fixed",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".init_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
@@ -60,6 +60,8 @@ struct ConfigTypeInfo image_config_suffix[] =
   { ".anim_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".post_delay_fixed",		ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".post_delay_random",		ARG_UNDEFINED,	TYPE_INTEGER	},
+  { ".init_event",			ARG_UNDEFINED,	TYPE_STRING	},
+  { ".anim_event",			ARG_UNDEFINED,	TYPE_STRING	},
   { ".name",				ARG_UNDEFINED,	TYPE_STRING	},
   { ".scale_up_factor",			ARG_UNDEFINED,	TYPE_INTEGER	},
   { ".tile_size",			ARG_UNDEFINED,	TYPE_INTEGER	},
@@ -4601,6 +4603,30 @@ struct ConfigInfo image_config[] =
   { "gfx.global.anim_6",			UNDEFINED_FILENAME	},
   { "gfx.global.anim_7",			UNDEFINED_FILENAME	},
   { "gfx.global.anim_8",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_9",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_10",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_11",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_12",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_13",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_14",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_15",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_16",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_17",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_18",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_19",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_20",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_21",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_22",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_23",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_24",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_25",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_26",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_27",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_28",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_29",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_30",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_31",			UNDEFINED_FILENAME	},
+  { "gfx.global.anim_32",			UNDEFINED_FILENAME	},
 
   { "global.anim_1",				UNDEFINED_FILENAME	},
   { "global.anim_2",				UNDEFINED_FILENAME	},
@@ -4610,6 +4636,30 @@ struct ConfigInfo image_config[] =
   { "global.anim_6",				UNDEFINED_FILENAME	},
   { "global.anim_7",				UNDEFINED_FILENAME	},
   { "global.anim_8",				UNDEFINED_FILENAME	},
+  { "global.anim_9",				UNDEFINED_FILENAME	},
+  { "global.anim_10",				UNDEFINED_FILENAME	},
+  { "global.anim_11",				UNDEFINED_FILENAME	},
+  { "global.anim_12",				UNDEFINED_FILENAME	},
+  { "global.anim_13",				UNDEFINED_FILENAME	},
+  { "global.anim_14",				UNDEFINED_FILENAME	},
+  { "global.anim_15",				UNDEFINED_FILENAME	},
+  { "global.anim_16",				UNDEFINED_FILENAME	},
+  { "global.anim_17",				UNDEFINED_FILENAME	},
+  { "global.anim_18",				UNDEFINED_FILENAME	},
+  { "global.anim_19",				UNDEFINED_FILENAME	},
+  { "global.anim_20",				UNDEFINED_FILENAME	},
+  { "global.anim_21",				UNDEFINED_FILENAME	},
+  { "global.anim_22",				UNDEFINED_FILENAME	},
+  { "global.anim_23",				UNDEFINED_FILENAME	},
+  { "global.anim_24",				UNDEFINED_FILENAME	},
+  { "global.anim_25",				UNDEFINED_FILENAME	},
+  { "global.anim_26",				UNDEFINED_FILENAME	},
+  { "global.anim_27",				UNDEFINED_FILENAME	},
+  { "global.anim_28",				UNDEFINED_FILENAME	},
+  { "global.anim_29",				UNDEFINED_FILENAME	},
+  { "global.anim_30",				UNDEFINED_FILENAME	},
+  { "global.anim_31",				UNDEFINED_FILENAME	},
+  { "global.anim_32",				UNDEFINED_FILENAME	},
 
   { "internal.global.toon_default",		UNDEFINED_FILENAME	},
   { "internal.global.toon_default.anim_mode",	"random"		},
diff --git a/src/conf_gfx.h b/src/conf_gfx.h
index a69bc9b..b4bf4d0 100644
--- a/src/conf_gfx.h
+++ b/src/conf_gfx.h
@@ -1666,316 +1666,364 @@
 #define IMG_GFX_GLOBAL_ANIM_6				1647
 #define IMG_GFX_GLOBAL_ANIM_7				1648
 #define IMG_GFX_GLOBAL_ANIM_8				1649
-#define IMG_GLOBAL_ANIM_1				1650
-#define IMG_GLOBAL_ANIM_2				1651
-#define IMG_GLOBAL_ANIM_3				1652
-#define IMG_GLOBAL_ANIM_4				1653
-#define IMG_GLOBAL_ANIM_5				1654
-#define IMG_GLOBAL_ANIM_6				1655
-#define IMG_GLOBAL_ANIM_7				1656
-#define IMG_GLOBAL_ANIM_8				1657
-#define IMG_INTERNAL_GLOBAL_TOON_DEFAULT		1658
-#define IMG_INTERNAL_GLOBAL_ANIM_DEFAULT		1659
-#define IMG_MENU_CALIBRATE_RED				1660
-#define IMG_MENU_CALIBRATE_BLUE				1661
-#define IMG_MENU_CALIBRATE_YELLOW			1662
-#define IMG_MENU_BUTTON					1663
-#define IMG_MENU_BUTTON_ACTIVE				1664
-#define IMG_MENU_BUTTON_LEFT				1665
-#define IMG_MENU_BUTTON_LEFT_ACTIVE			1666
-#define IMG_MENU_BUTTON_RIGHT				1667
-#define IMG_MENU_BUTTON_RIGHT_ACTIVE			1668
-#define IMG_MENU_BUTTON_UP				1669
-#define IMG_MENU_BUTTON_UP_ACTIVE			1670
-#define IMG_MENU_BUTTON_DOWN				1671
-#define IMG_MENU_BUTTON_DOWN_ACTIVE			1672
-#define IMG_MENU_BUTTON_ENTER_MENU			1673
-#define IMG_MENU_BUTTON_ENTER_MENU_ACTIVE		1674
-#define IMG_MENU_BUTTON_LEAVE_MENU			1675
-#define IMG_MENU_BUTTON_LEAVE_MENU_ACTIVE		1676
-#define IMG_MENU_BUTTON_NEXT_LEVEL			1677
-#define IMG_MENU_BUTTON_NEXT_LEVEL_ACTIVE		1678
-#define IMG_MENU_BUTTON_PREV_LEVEL			1679
-#define IMG_MENU_BUTTON_PREV_LEVEL_ACTIVE		1680
-#define IMG_MENU_BUTTON_NAME				1681
-#define IMG_MENU_BUTTON_NAME_ACTIVE			1682
-#define IMG_MENU_BUTTON_LEVELS				1683
-#define IMG_MENU_BUTTON_LEVELS_ACTIVE			1684
-#define IMG_MENU_BUTTON_SCORES				1685
-#define IMG_MENU_BUTTON_SCORES_ACTIVE			1686
-#define IMG_MENU_BUTTON_EDITOR				1687
-#define IMG_MENU_BUTTON_EDITOR_ACTIVE			1688
-#define IMG_MENU_BUTTON_INFO				1689
-#define IMG_MENU_BUTTON_INFO_ACTIVE			1690
-#define IMG_MENU_BUTTON_GAME				1691
-#define IMG_MENU_BUTTON_GAME_ACTIVE			1692
-#define IMG_MENU_BUTTON_SETUP				1693
-#define IMG_MENU_BUTTON_SETUP_ACTIVE			1694
-#define IMG_MENU_BUTTON_QUIT				1695
-#define IMG_MENU_BUTTON_QUIT_ACTIVE			1696
-#define IMG_MENU_SCROLLBAR				1697
-#define IMG_MENU_SCROLLBAR_ACTIVE			1698
-#define IMG_GFX_GAME_BUTTON_STOP			1699
-#define IMG_GFX_GAME_BUTTON_PAUSE			1700
-#define IMG_GFX_GAME_BUTTON_PLAY			1701
-#define IMG_GFX_GAME_BUTTON_UNDO			1702
-#define IMG_GFX_GAME_BUTTON_REDO			1703
-#define IMG_GFX_GAME_BUTTON_SAVE			1704
-#define IMG_GFX_GAME_BUTTON_PAUSE2			1705
-#define IMG_GFX_GAME_BUTTON_LOAD			1706
-#define IMG_GFX_GAME_BUTTON_SOUND_MUSIC			1707
-#define IMG_GFX_GAME_BUTTON_SOUND_LOOPS			1708
-#define IMG_GFX_GAME_BUTTON_SOUND_SIMPLE		1709
-#define IMG_GFX_TAPE_BUTTON_EJECT			1710
-#define IMG_GFX_TAPE_BUTTON_EXTRA			1711
-#define IMG_GFX_TAPE_BUTTON_STOP			1712
-#define IMG_GFX_TAPE_BUTTON_PAUSE			1713
-#define IMG_GFX_TAPE_BUTTON_RECORD			1714
-#define IMG_GFX_TAPE_BUTTON_PLAY			1715
-#define IMG_GFX_TAPE_SYMBOL_EJECT			1716
-#define IMG_GFX_TAPE_SYMBOL_STOP			1717
-#define IMG_GFX_TAPE_SYMBOL_PAUSE			1718
-#define IMG_GFX_TAPE_SYMBOL_RECORD			1719
-#define IMG_GFX_TAPE_SYMBOL_PLAY			1720
-#define IMG_GFX_TAPE_SYMBOL_FAST_FORWARD		1721
-#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD		1722
-#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD_BLIND		1723
-#define IMG_GFX_TAPE_SYMBOL_PAUSE_BEFORE_END		1724
-#define IMG_GFX_TAPE_SYMBOL_SINGLE_STEP			1725
-#define IMG_GFX_TAPE_LABEL_EJECT			1726
-#define IMG_GFX_TAPE_LABEL_STOP				1727
-#define IMG_GFX_TAPE_LABEL_PAUSE			1728
-#define IMG_GFX_TAPE_LABEL_RECORD			1729
-#define IMG_GFX_TAPE_LABEL_PLAY				1730
-#define IMG_GFX_TAPE_LABEL_FAST_FORWARD			1731
-#define IMG_GFX_TAPE_LABEL_WARP_FORWARD			1732
-#define IMG_GFX_TAPE_LABEL_WARP_FORWARD_BLIND		1733
-#define IMG_GFX_TAPE_LABEL_PAUSE_BEFORE_END		1734
-#define IMG_GFX_TAPE_LABEL_SINGLE_STEP			1735
-#define IMG_GFX_TAPE_LABEL_DATE				1736
-#define IMG_GFX_TAPE_LABEL_TIME				1737
-#define IMG_GFX_REQUEST_BUTTON_YES			1738
-#define IMG_GFX_REQUEST_BUTTON_NO			1739
-#define IMG_GFX_REQUEST_BUTTON_CONFIRM			1740
-#define IMG_GFX_REQUEST_BUTTON_PLAYER_1			1741
-#define IMG_GFX_REQUEST_BUTTON_PLAYER_2			1742
-#define IMG_GFX_REQUEST_BUTTON_PLAYER_3			1743
-#define IMG_GFX_REQUEST_BUTTON_PLAYER_4			1744
-#define IMG_FONT_INITIAL_1				1745
-#define IMG_FONT_INITIAL_2				1746
-#define IMG_FONT_INITIAL_3				1747
-#define IMG_FONT_INITIAL_4				1748
-#define IMG_FONT_TITLE_1				1749
-#define IMG_FONT_TITLE_2				1750
-#define IMG_FONT_TITLE_2_SETUP				1751
-#define IMG_FONT_MENU_1					1752
-#define IMG_FONT_MENU_1_ACTIVE				1753
-#define IMG_FONT_MENU_2					1754
-#define IMG_FONT_MENU_2_ACTIVE				1755
-#define IMG_FONT_TEXT_1					1756
-#define IMG_FONT_TEXT_1_MAIN				1757
-#define IMG_FONT_TEXT_1_LEVELS				1758
-#define IMG_FONT_TEXT_1_LEVELNR				1759
-#define IMG_FONT_TEXT_1_SETUP				1760
-#define IMG_FONT_TEXT_1_PREVIEW				1761
-#define IMG_FONT_TEXT_1_SCORES				1762
-#define IMG_FONT_TEXT_1_ACTIVE_SCORES			1763
-#define IMG_FONT_TEXT_1_PANEL				1764
-#define IMG_FONT_TEXT_1_DOOR				1765
-#define IMG_FONT_TEXT_2					1766
-#define IMG_FONT_TEXT_2_MAIN				1767
-#define IMG_FONT_TEXT_2_LEVELS				1768
-#define IMG_FONT_TEXT_2_LEVELNR				1769
-#define IMG_FONT_TEXT_2_SETUP				1770
-#define IMG_FONT_TEXT_2_PREVIEW				1771
-#define IMG_FONT_TEXT_2_SCORES				1772
-#define IMG_FONT_TEXT_2_ACTIVE_SCORES			1773
-#define IMG_FONT_TEXT_3					1774
-#define IMG_FONT_TEXT_3_LEVELS				1775
-#define IMG_FONT_TEXT_3_LEVELNR				1776
-#define IMG_FONT_TEXT_3_SETUP				1777
-#define IMG_FONT_TEXT_3_PREVIEW				1778
-#define IMG_FONT_TEXT_3_SCORES				1779
-#define IMG_FONT_TEXT_3_ACTIVE_SCORES			1780
-#define IMG_FONT_TEXT_4					1781
-#define IMG_FONT_TEXT_4_MAIN				1782
-#define IMG_FONT_TEXT_4_LEVELS				1783
-#define IMG_FONT_TEXT_4_LEVELNR				1784
-#define IMG_FONT_TEXT_4_SETUP				1785
-#define IMG_FONT_TEXT_4_SCORES				1786
-#define IMG_FONT_TEXT_4_ACTIVE_SCORES			1787
-#define IMG_FONT_ENVELOPE_1				1788
-#define IMG_FONT_ENVELOPE_2				1789
-#define IMG_FONT_ENVELOPE_3				1790
-#define IMG_FONT_ENVELOPE_4				1791
-#define IMG_FONT_REQUEST				1792
-#define IMG_FONT_INPUT_1				1793
-#define IMG_FONT_INPUT_1_MAIN				1794
-#define IMG_FONT_INPUT_1_ACTIVE				1795
-#define IMG_FONT_INPUT_1_ACTIVE_MAIN			1796
-#define IMG_FONT_INPUT_1_ACTIVE_SETUP			1797
-#define IMG_FONT_INPUT_2				1798
-#define IMG_FONT_INPUT_2_ACTIVE				1799
-#define IMG_FONT_OPTION_OFF				1800
-#define IMG_FONT_OPTION_OFF_NARROW			1801
-#define IMG_FONT_OPTION_ON				1802
-#define IMG_FONT_OPTION_ON_NARROW			1803
-#define IMG_FONT_VALUE_1				1804
-#define IMG_FONT_VALUE_2				1805
-#define IMG_FONT_VALUE_OLD				1806
-#define IMG_FONT_VALUE_NARROW				1807
-#define IMG_FONT_LEVEL_NUMBER				1808
-#define IMG_FONT_LEVEL_NUMBER_ACTIVE			1809
-#define IMG_FONT_TAPE_RECORDER				1810
-#define IMG_FONT_GAME_INFO				1811
-#define IMG_FONT_INFO_ELEMENTS				1812
-#define IMG_FONT_INFO_LEVELSET				1813
-#define IMG_EDITOR_ELEMENT_BORDER			1814
-#define IMG_EDITOR_ELEMENT_BORDER_INPUT			1815
-#define IMG_EDITOR_COUNTER_DOWN				1816
-#define IMG_EDITOR_COUNTER_UP				1817
-#define IMG_EDITOR_COUNTER_INPUT			1818
-#define IMG_EDITOR_SELECTBOX_INPUT			1819
-#define IMG_EDITOR_SELECTBOX_BUTTON			1820
-#define IMG_EDITOR_CHECKBOX				1821
-#define IMG_EDITOR_RADIOBUTTON				1822
-#define IMG_EDITOR_STICKYBUTTON				1823
-#define IMG_EDITOR_TABBUTTON				1824
-#define IMG_EDITOR_TEXTBUTTON				1825
-#define IMG_EDITOR_INPUT_TEXT				1826
-#define IMG_EDITOR_INPUT_TEXTAREA			1827
-#define IMG_EDITOR_CASCADE_LIST				1828
-#define IMG_EDITOR_CASCADE_LIST_ACTIVE			1829
-#define IMG_EDITOR_PALETTE_BUTTON			1830
-#define IMG_EDITOR_PALETTE_SCROLL_UP			1831
-#define IMG_EDITOR_PALETTE_SCROLL_DOWN			1832
-#define IMG_EDITOR_PALETTE_SCROLLBAR			1833
-#define IMG_EDITOR_PLAYFIELD_SCROLL_UP			1834
-#define IMG_EDITOR_PLAYFIELD_SCROLL_DOWN		1835
-#define IMG_EDITOR_PLAYFIELD_SCROLL_LEFT		1836
-#define IMG_EDITOR_PLAYFIELD_SCROLL_RIGHT		1837
-#define IMG_EDITOR_PLAYFIELD_SCROLLBAR			1838
-#define IMG_GFX_EDITOR_BUTTON_PREV_LEVEL		1839
-#define IMG_GFX_EDITOR_BUTTON_NEXT_LEVEL		1840
-#define IMG_GFX_EDITOR_BUTTON_PROPERTIES		1841
-#define IMG_GFX_EDITOR_BUTTON_ELEMENT_LEFT		1842
-#define IMG_GFX_EDITOR_BUTTON_ELEMENT_MIDDLE		1843
-#define IMG_GFX_EDITOR_BUTTON_ELEMENT_RIGHT		1844
-#define IMG_GFX_EDITOR_BUTTON_PALETTE			1845
-#define IMG_EDITOR_NO_TOOLBOX_BUTTON			1846
-#define IMG_GFX_EDITOR_BUTTON_DRAW_SINGLE		1847
-#define IMG_GFX_EDITOR_BUTTON_DRAW_CONNECTED		1848
-#define IMG_GFX_EDITOR_BUTTON_DRAW_LINE			1849
-#define IMG_GFX_EDITOR_BUTTON_DRAW_ARC			1850
-#define IMG_GFX_EDITOR_BUTTON_DRAW_RECTANGLE		1851
-#define IMG_GFX_EDITOR_BUTTON_DRAW_FILLED_BOX		1852
-#define IMG_GFX_EDITOR_BUTTON_ROTATE_UP			1853
-#define IMG_GFX_EDITOR_BUTTON_DRAW_TEXT			1854
-#define IMG_GFX_EDITOR_BUTTON_FLOOD_FILL		1855
-#define IMG_GFX_EDITOR_BUTTON_ROTATE_LEFT		1856
-#define IMG_GFX_EDITOR_BUTTON_ZOOM_LEVEL		1857
-#define IMG_GFX_EDITOR_BUTTON_ROTATE_RIGHT		1858
-#define IMG_GFX_EDITOR_BUTTON_DRAW_RANDOM		1859
-#define IMG_GFX_EDITOR_BUTTON_GRAB_BRUSH		1860
-#define IMG_GFX_EDITOR_BUTTON_ROTATE_DOWN		1861
-#define IMG_GFX_EDITOR_BUTTON_PICK_ELEMENT		1862
-#define IMG_GFX_EDITOR_BUTTON_CE_COPY_FROM		1863
-#define IMG_GFX_EDITOR_BUTTON_CE_COPY_TO		1864
-#define IMG_GFX_EDITOR_BUTTON_CE_SWAP			1865
-#define IMG_GFX_EDITOR_BUTTON_CE_COPY			1866
-#define IMG_GFX_EDITOR_BUTTON_CE_PASTE			1867
-#define IMG_GFX_EDITOR_BUTTON_CP_COPY			1868
-#define IMG_GFX_EDITOR_BUTTON_CP_PASTE			1869
-#define IMG_GFX_EDITOR_BUTTON_UNDO			1870
-#define IMG_GFX_EDITOR_BUTTON_CONF			1871
-#define IMG_GFX_EDITOR_BUTTON_SAVE			1872
-#define IMG_GFX_EDITOR_BUTTON_CLEAR			1873
-#define IMG_GFX_EDITOR_BUTTON_TEST			1874
-#define IMG_GFX_EDITOR_BUTTON_EXIT			1875
-#define IMG_GFX_EDITOR_INPUT_LEVEL_NUMBER		1876
-#define IMG_GLOBAL_BORDER				1877
-#define IMG_GLOBAL_BORDER_MAIN				1878
-#define IMG_GLOBAL_BORDER_SCORES			1879
-#define IMG_GLOBAL_BORDER_EDITOR			1880
-#define IMG_GLOBAL_BORDER_PLAYING			1881
-#define IMG_GLOBAL_DOOR					1882
-#define IMG_GLOBAL_BUSY					1883
-#define IMG_BACKGROUND					1884
-#define IMG_BACKGROUND_TITLE_INITIAL			1885
-#define IMG_BACKGROUND_TITLE				1886
-#define IMG_BACKGROUND_MAIN				1887
-#define IMG_BACKGROUND_LEVELS				1888
-#define IMG_BACKGROUND_LEVELNR				1889
-#define IMG_BACKGROUND_SCORES				1890
-#define IMG_BACKGROUND_EDITOR				1891
-#define IMG_BACKGROUND_INFO				1892
-#define IMG_BACKGROUND_INFO_ELEMENTS			1893
-#define IMG_BACKGROUND_INFO_MUSIC			1894
-#define IMG_BACKGROUND_INFO_CREDITS			1895
-#define IMG_BACKGROUND_INFO_PROGRAM			1896
-#define IMG_BACKGROUND_INFO_VERSION			1897
-#define IMG_BACKGROUND_INFO_LEVELSET			1898
-#define IMG_BACKGROUND_SETUP				1899
-#define IMG_BACKGROUND_PLAYING				1900
-#define IMG_BACKGROUND_DOOR				1901
-#define IMG_BACKGROUND_TAPE				1902
-#define IMG_BACKGROUND_PANEL				1903
-#define IMG_BACKGROUND_PALETTE				1904
-#define IMG_BACKGROUND_TOOLBOX				1905
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_1		1906
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_2		1907
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_3		1908
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_4		1909
-#define IMG_BACKGROUND_TITLESCREEN_INITIAL_5		1910
-#define IMG_BACKGROUND_TITLESCREEN_1			1911
-#define IMG_BACKGROUND_TITLESCREEN_2			1912
-#define IMG_BACKGROUND_TITLESCREEN_3			1913
-#define IMG_BACKGROUND_TITLESCREEN_4			1914
-#define IMG_BACKGROUND_TITLESCREEN_5			1915
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1		1916
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2		1917
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3		1918
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4		1919
-#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5		1920
-#define IMG_BACKGROUND_TITLEMESSAGE_1			1921
-#define IMG_BACKGROUND_TITLEMESSAGE_2			1922
-#define IMG_BACKGROUND_TITLEMESSAGE_3			1923
-#define IMG_BACKGROUND_TITLEMESSAGE_4			1924
-#define IMG_BACKGROUND_TITLEMESSAGE_5			1925
-#define IMG_BACKGROUND_ENVELOPE_1			1926
-#define IMG_BACKGROUND_ENVELOPE_2			1927
-#define IMG_BACKGROUND_ENVELOPE_3			1928
-#define IMG_BACKGROUND_ENVELOPE_4			1929
-#define IMG_BACKGROUND_REQUEST				1930
-#define IMG_TITLESCREEN_INITIAL_1			1931
-#define IMG_TITLESCREEN_INITIAL_2			1932
-#define IMG_TITLESCREEN_INITIAL_3			1933
-#define IMG_TITLESCREEN_INITIAL_4			1934
-#define IMG_TITLESCREEN_INITIAL_5			1935
-#define IMG_TITLESCREEN_1				1936
-#define IMG_TITLESCREEN_2				1937
-#define IMG_TITLESCREEN_3				1938
-#define IMG_TITLESCREEN_4				1939
-#define IMG_TITLESCREEN_5				1940
-#define IMG_GFX_DOOR_1_PART_1				1941
-#define IMG_GFX_DOOR_1_PART_2				1942
-#define IMG_GFX_DOOR_1_PART_3				1943
-#define IMG_GFX_DOOR_1_PART_4				1944
-#define IMG_GFX_DOOR_1_PART_5				1945
-#define IMG_GFX_DOOR_1_PART_6				1946
-#define IMG_GFX_DOOR_1_PART_7				1947
-#define IMG_GFX_DOOR_1_PART_8				1948
-#define IMG_GFX_DOOR_2_PART_1				1949
-#define IMG_GFX_DOOR_2_PART_2				1950
-#define IMG_GFX_DOOR_2_PART_3				1951
-#define IMG_GFX_DOOR_2_PART_4				1952
-#define IMG_GFX_DOOR_2_PART_5				1953
-#define IMG_GFX_DOOR_2_PART_6				1954
-#define IMG_GFX_DOOR_2_PART_7				1955
-#define IMG_GFX_DOOR_2_PART_8				1956
-#define IMG_DOOR_2_TOP_BORDER_CORRECTION		1957
-#define IMG_LAST_IMAGE_ENTRY_BUG			1958
+#define IMG_GFX_GLOBAL_ANIM_9				1650
+#define IMG_GFX_GLOBAL_ANIM_10				1651
+#define IMG_GFX_GLOBAL_ANIM_11				1652
+#define IMG_GFX_GLOBAL_ANIM_12				1653
+#define IMG_GFX_GLOBAL_ANIM_13				1654
+#define IMG_GFX_GLOBAL_ANIM_14				1655
+#define IMG_GFX_GLOBAL_ANIM_15				1656
+#define IMG_GFX_GLOBAL_ANIM_16				1657
+#define IMG_GFX_GLOBAL_ANIM_17				1658
+#define IMG_GFX_GLOBAL_ANIM_18				1659
+#define IMG_GFX_GLOBAL_ANIM_19				1660
+#define IMG_GFX_GLOBAL_ANIM_20				1661
+#define IMG_GFX_GLOBAL_ANIM_21				1662
+#define IMG_GFX_GLOBAL_ANIM_22				1663
+#define IMG_GFX_GLOBAL_ANIM_23				1664
+#define IMG_GFX_GLOBAL_ANIM_24				1665
+#define IMG_GFX_GLOBAL_ANIM_25				1666
+#define IMG_GFX_GLOBAL_ANIM_26				1667
+#define IMG_GFX_GLOBAL_ANIM_27				1668
+#define IMG_GFX_GLOBAL_ANIM_28				1669
+#define IMG_GFX_GLOBAL_ANIM_29				1670
+#define IMG_GFX_GLOBAL_ANIM_30				1671
+#define IMG_GFX_GLOBAL_ANIM_31				1672
+#define IMG_GFX_GLOBAL_ANIM_32				1673
+#define IMG_GLOBAL_ANIM_1				1674
+#define IMG_GLOBAL_ANIM_2				1675
+#define IMG_GLOBAL_ANIM_3				1676
+#define IMG_GLOBAL_ANIM_4				1677
+#define IMG_GLOBAL_ANIM_5				1678
+#define IMG_GLOBAL_ANIM_6				1679
+#define IMG_GLOBAL_ANIM_7				1680
+#define IMG_GLOBAL_ANIM_8				1681
+#define IMG_GLOBAL_ANIM_9				1682
+#define IMG_GLOBAL_ANIM_10				1683
+#define IMG_GLOBAL_ANIM_11				1684
+#define IMG_GLOBAL_ANIM_12				1685
+#define IMG_GLOBAL_ANIM_13				1686
+#define IMG_GLOBAL_ANIM_14				1687
+#define IMG_GLOBAL_ANIM_15				1688
+#define IMG_GLOBAL_ANIM_16				1689
+#define IMG_GLOBAL_ANIM_17				1690
+#define IMG_GLOBAL_ANIM_18				1691
+#define IMG_GLOBAL_ANIM_19				1692
+#define IMG_GLOBAL_ANIM_20				1693
+#define IMG_GLOBAL_ANIM_21				1694
+#define IMG_GLOBAL_ANIM_22				1695
+#define IMG_GLOBAL_ANIM_23				1696
+#define IMG_GLOBAL_ANIM_24				1697
+#define IMG_GLOBAL_ANIM_25				1698
+#define IMG_GLOBAL_ANIM_26				1699
+#define IMG_GLOBAL_ANIM_27				1700
+#define IMG_GLOBAL_ANIM_28				1701
+#define IMG_GLOBAL_ANIM_29				1702
+#define IMG_GLOBAL_ANIM_30				1703
+#define IMG_GLOBAL_ANIM_31				1704
+#define IMG_GLOBAL_ANIM_32				1705
+#define IMG_INTERNAL_GLOBAL_TOON_DEFAULT		1706
+#define IMG_INTERNAL_GLOBAL_ANIM_DEFAULT		1707
+#define IMG_MENU_CALIBRATE_RED				1708
+#define IMG_MENU_CALIBRATE_BLUE				1709
+#define IMG_MENU_CALIBRATE_YELLOW			1710
+#define IMG_MENU_BUTTON					1711
+#define IMG_MENU_BUTTON_ACTIVE				1712
+#define IMG_MENU_BUTTON_LEFT				1713
+#define IMG_MENU_BUTTON_LEFT_ACTIVE			1714
+#define IMG_MENU_BUTTON_RIGHT				1715
+#define IMG_MENU_BUTTON_RIGHT_ACTIVE			1716
+#define IMG_MENU_BUTTON_UP				1717
+#define IMG_MENU_BUTTON_UP_ACTIVE			1718
+#define IMG_MENU_BUTTON_DOWN				1719
+#define IMG_MENU_BUTTON_DOWN_ACTIVE			1720
+#define IMG_MENU_BUTTON_ENTER_MENU			1721
+#define IMG_MENU_BUTTON_ENTER_MENU_ACTIVE		1722
+#define IMG_MENU_BUTTON_LEAVE_MENU			1723
+#define IMG_MENU_BUTTON_LEAVE_MENU_ACTIVE		1724
+#define IMG_MENU_BUTTON_NEXT_LEVEL			1725
+#define IMG_MENU_BUTTON_NEXT_LEVEL_ACTIVE		1726
+#define IMG_MENU_BUTTON_PREV_LEVEL			1727
+#define IMG_MENU_BUTTON_PREV_LEVEL_ACTIVE		1728
+#define IMG_MENU_BUTTON_NAME				1729
+#define IMG_MENU_BUTTON_NAME_ACTIVE			1730
+#define IMG_MENU_BUTTON_LEVELS				1731
+#define IMG_MENU_BUTTON_LEVELS_ACTIVE			1732
+#define IMG_MENU_BUTTON_SCORES				1733
+#define IMG_MENU_BUTTON_SCORES_ACTIVE			1734
+#define IMG_MENU_BUTTON_EDITOR				1735
+#define IMG_MENU_BUTTON_EDITOR_ACTIVE			1736
+#define IMG_MENU_BUTTON_INFO				1737
+#define IMG_MENU_BUTTON_INFO_ACTIVE			1738
+#define IMG_MENU_BUTTON_GAME				1739
+#define IMG_MENU_BUTTON_GAME_ACTIVE			1740
+#define IMG_MENU_BUTTON_SETUP				1741
+#define IMG_MENU_BUTTON_SETUP_ACTIVE			1742
+#define IMG_MENU_BUTTON_QUIT				1743
+#define IMG_MENU_BUTTON_QUIT_ACTIVE			1744
+#define IMG_MENU_SCROLLBAR				1745
+#define IMG_MENU_SCROLLBAR_ACTIVE			1746
+#define IMG_GFX_GAME_BUTTON_STOP			1747
+#define IMG_GFX_GAME_BUTTON_PAUSE			1748
+#define IMG_GFX_GAME_BUTTON_PLAY			1749
+#define IMG_GFX_GAME_BUTTON_UNDO			1750
+#define IMG_GFX_GAME_BUTTON_REDO			1751
+#define IMG_GFX_GAME_BUTTON_SAVE			1752
+#define IMG_GFX_GAME_BUTTON_PAUSE2			1753
+#define IMG_GFX_GAME_BUTTON_LOAD			1754
+#define IMG_GFX_GAME_BUTTON_SOUND_MUSIC			1755
+#define IMG_GFX_GAME_BUTTON_SOUND_LOOPS			1756
+#define IMG_GFX_GAME_BUTTON_SOUND_SIMPLE		1757
+#define IMG_GFX_TAPE_BUTTON_EJECT			1758
+#define IMG_GFX_TAPE_BUTTON_EXTRA			1759
+#define IMG_GFX_TAPE_BUTTON_STOP			1760
+#define IMG_GFX_TAPE_BUTTON_PAUSE			1761
+#define IMG_GFX_TAPE_BUTTON_RECORD			1762
+#define IMG_GFX_TAPE_BUTTON_PLAY			1763
+#define IMG_GFX_TAPE_SYMBOL_EJECT			1764
+#define IMG_GFX_TAPE_SYMBOL_STOP			1765
+#define IMG_GFX_TAPE_SYMBOL_PAUSE			1766
+#define IMG_GFX_TAPE_SYMBOL_RECORD			1767
+#define IMG_GFX_TAPE_SYMBOL_PLAY			1768
+#define IMG_GFX_TAPE_SYMBOL_FAST_FORWARD		1769
+#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD		1770
+#define IMG_GFX_TAPE_SYMBOL_WARP_FORWARD_BLIND		1771
+#define IMG_GFX_TAPE_SYMBOL_PAUSE_BEFORE_END		1772
+#define IMG_GFX_TAPE_SYMBOL_SINGLE_STEP			1773
+#define IMG_GFX_TAPE_LABEL_EJECT			1774
+#define IMG_GFX_TAPE_LABEL_STOP				1775
+#define IMG_GFX_TAPE_LABEL_PAUSE			1776
+#define IMG_GFX_TAPE_LABEL_RECORD			1777
+#define IMG_GFX_TAPE_LABEL_PLAY				1778
+#define IMG_GFX_TAPE_LABEL_FAST_FORWARD			1779
+#define IMG_GFX_TAPE_LABEL_WARP_FORWARD			1780
+#define IMG_GFX_TAPE_LABEL_WARP_FORWARD_BLIND		1781
+#define IMG_GFX_TAPE_LABEL_PAUSE_BEFORE_END		1782
+#define IMG_GFX_TAPE_LABEL_SINGLE_STEP			1783
+#define IMG_GFX_TAPE_LABEL_DATE				1784
+#define IMG_GFX_TAPE_LABEL_TIME				1785
+#define IMG_GFX_REQUEST_BUTTON_YES			1786
+#define IMG_GFX_REQUEST_BUTTON_NO			1787
+#define IMG_GFX_REQUEST_BUTTON_CONFIRM			1788
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_1			1789
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_2			1790
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_3			1791
+#define IMG_GFX_REQUEST_BUTTON_PLAYER_4			1792
+#define IMG_FONT_INITIAL_1				1793
+#define IMG_FONT_INITIAL_2				1794
+#define IMG_FONT_INITIAL_3				1795
+#define IMG_FONT_INITIAL_4				1796
+#define IMG_FONT_TITLE_1				1797
+#define IMG_FONT_TITLE_2				1798
+#define IMG_FONT_TITLE_2_SETUP				1799
+#define IMG_FONT_MENU_1					1800
+#define IMG_FONT_MENU_1_ACTIVE				1801
+#define IMG_FONT_MENU_2					1802
+#define IMG_FONT_MENU_2_ACTIVE				1803
+#define IMG_FONT_TEXT_1					1804
+#define IMG_FONT_TEXT_1_MAIN				1805
+#define IMG_FONT_TEXT_1_LEVELS				1806
+#define IMG_FONT_TEXT_1_LEVELNR				1807
+#define IMG_FONT_TEXT_1_SETUP				1808
+#define IMG_FONT_TEXT_1_PREVIEW				1809
+#define IMG_FONT_TEXT_1_SCORES				1810
+#define IMG_FONT_TEXT_1_ACTIVE_SCORES			1811
+#define IMG_FONT_TEXT_1_PANEL				1812
+#define IMG_FONT_TEXT_1_DOOR				1813
+#define IMG_FONT_TEXT_2					1814
+#define IMG_FONT_TEXT_2_MAIN				1815
+#define IMG_FONT_TEXT_2_LEVELS				1816
+#define IMG_FONT_TEXT_2_LEVELNR				1817
+#define IMG_FONT_TEXT_2_SETUP				1818
+#define IMG_FONT_TEXT_2_PREVIEW				1819
+#define IMG_FONT_TEXT_2_SCORES				1820
+#define IMG_FONT_TEXT_2_ACTIVE_SCORES			1821
+#define IMG_FONT_TEXT_3					1822
+#define IMG_FONT_TEXT_3_LEVELS				1823
+#define IMG_FONT_TEXT_3_LEVELNR				1824
+#define IMG_FONT_TEXT_3_SETUP				1825
+#define IMG_FONT_TEXT_3_PREVIEW				1826
+#define IMG_FONT_TEXT_3_SCORES				1827
+#define IMG_FONT_TEXT_3_ACTIVE_SCORES			1828
+#define IMG_FONT_TEXT_4					1829
+#define IMG_FONT_TEXT_4_MAIN				1830
+#define IMG_FONT_TEXT_4_LEVELS				1831
+#define IMG_FONT_TEXT_4_LEVELNR				1832
+#define IMG_FONT_TEXT_4_SETUP				1833
+#define IMG_FONT_TEXT_4_SCORES				1834
+#define IMG_FONT_TEXT_4_ACTIVE_SCORES			1835
+#define IMG_FONT_ENVELOPE_1				1836
+#define IMG_FONT_ENVELOPE_2				1837
+#define IMG_FONT_ENVELOPE_3				1838
+#define IMG_FONT_ENVELOPE_4				1839
+#define IMG_FONT_REQUEST				1840
+#define IMG_FONT_INPUT_1				1841
+#define IMG_FONT_INPUT_1_MAIN				1842
+#define IMG_FONT_INPUT_1_ACTIVE				1843
+#define IMG_FONT_INPUT_1_ACTIVE_MAIN			1844
+#define IMG_FONT_INPUT_1_ACTIVE_SETUP			1845
+#define IMG_FONT_INPUT_2				1846
+#define IMG_FONT_INPUT_2_ACTIVE				1847
+#define IMG_FONT_OPTION_OFF				1848
+#define IMG_FONT_OPTION_OFF_NARROW			1849
+#define IMG_FONT_OPTION_ON				1850
+#define IMG_FONT_OPTION_ON_NARROW			1851
+#define IMG_FONT_VALUE_1				1852
+#define IMG_FONT_VALUE_2				1853
+#define IMG_FONT_VALUE_OLD				1854
+#define IMG_FONT_VALUE_NARROW				1855
+#define IMG_FONT_LEVEL_NUMBER				1856
+#define IMG_FONT_LEVEL_NUMBER_ACTIVE			1857
+#define IMG_FONT_TAPE_RECORDER				1858
+#define IMG_FONT_GAME_INFO				1859
+#define IMG_FONT_INFO_ELEMENTS				1860
+#define IMG_FONT_INFO_LEVELSET				1861
+#define IMG_EDITOR_ELEMENT_BORDER			1862
+#define IMG_EDITOR_ELEMENT_BORDER_INPUT			1863
+#define IMG_EDITOR_COUNTER_DOWN				1864
+#define IMG_EDITOR_COUNTER_UP				1865
+#define IMG_EDITOR_COUNTER_INPUT			1866
+#define IMG_EDITOR_SELECTBOX_INPUT			1867
+#define IMG_EDITOR_SELECTBOX_BUTTON			1868
+#define IMG_EDITOR_CHECKBOX				1869
+#define IMG_EDITOR_RADIOBUTTON				1870
+#define IMG_EDITOR_STICKYBUTTON				1871
+#define IMG_EDITOR_TABBUTTON				1872
+#define IMG_EDITOR_TEXTBUTTON				1873
+#define IMG_EDITOR_INPUT_TEXT				1874
+#define IMG_EDITOR_INPUT_TEXTAREA			1875
+#define IMG_EDITOR_CASCADE_LIST				1876
+#define IMG_EDITOR_CASCADE_LIST_ACTIVE			1877
+#define IMG_EDITOR_PALETTE_BUTTON			1878
+#define IMG_EDITOR_PALETTE_SCROLL_UP			1879
+#define IMG_EDITOR_PALETTE_SCROLL_DOWN			1880
+#define IMG_EDITOR_PALETTE_SCROLLBAR			1881
+#define IMG_EDITOR_PLAYFIELD_SCROLL_UP			1882
+#define IMG_EDITOR_PLAYFIELD_SCROLL_DOWN		1883
+#define IMG_EDITOR_PLAYFIELD_SCROLL_LEFT		1884
+#define IMG_EDITOR_PLAYFIELD_SCROLL_RIGHT		1885
+#define IMG_EDITOR_PLAYFIELD_SCROLLBAR			1886
+#define IMG_GFX_EDITOR_BUTTON_PREV_LEVEL		1887
+#define IMG_GFX_EDITOR_BUTTON_NEXT_LEVEL		1888
+#define IMG_GFX_EDITOR_BUTTON_PROPERTIES		1889
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_LEFT		1890
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_MIDDLE		1891
+#define IMG_GFX_EDITOR_BUTTON_ELEMENT_RIGHT		1892
+#define IMG_GFX_EDITOR_BUTTON_PALETTE			1893
+#define IMG_EDITOR_NO_TOOLBOX_BUTTON			1894
+#define IMG_GFX_EDITOR_BUTTON_DRAW_SINGLE		1895
+#define IMG_GFX_EDITOR_BUTTON_DRAW_CONNECTED		1896
+#define IMG_GFX_EDITOR_BUTTON_DRAW_LINE			1897
+#define IMG_GFX_EDITOR_BUTTON_DRAW_ARC			1898
+#define IMG_GFX_EDITOR_BUTTON_DRAW_RECTANGLE		1899
+#define IMG_GFX_EDITOR_BUTTON_DRAW_FILLED_BOX		1900
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_UP			1901
+#define IMG_GFX_EDITOR_BUTTON_DRAW_TEXT			1902
+#define IMG_GFX_EDITOR_BUTTON_FLOOD_FILL		1903
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_LEFT		1904
+#define IMG_GFX_EDITOR_BUTTON_ZOOM_LEVEL		1905
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_RIGHT		1906
+#define IMG_GFX_EDITOR_BUTTON_DRAW_RANDOM		1907
+#define IMG_GFX_EDITOR_BUTTON_GRAB_BRUSH		1908
+#define IMG_GFX_EDITOR_BUTTON_ROTATE_DOWN		1909
+#define IMG_GFX_EDITOR_BUTTON_PICK_ELEMENT		1910
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY_FROM		1911
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY_TO		1912
+#define IMG_GFX_EDITOR_BUTTON_CE_SWAP			1913
+#define IMG_GFX_EDITOR_BUTTON_CE_COPY			1914
+#define IMG_GFX_EDITOR_BUTTON_CE_PASTE			1915
+#define IMG_GFX_EDITOR_BUTTON_CP_COPY			1916
+#define IMG_GFX_EDITOR_BUTTON_CP_PASTE			1917
+#define IMG_GFX_EDITOR_BUTTON_UNDO			1918
+#define IMG_GFX_EDITOR_BUTTON_CONF			1919
+#define IMG_GFX_EDITOR_BUTTON_SAVE			1920
+#define IMG_GFX_EDITOR_BUTTON_CLEAR			1921
+#define IMG_GFX_EDITOR_BUTTON_TEST			1922
+#define IMG_GFX_EDITOR_BUTTON_EXIT			1923
+#define IMG_GFX_EDITOR_INPUT_LEVEL_NUMBER		1924
+#define IMG_GLOBAL_BORDER				1925
+#define IMG_GLOBAL_BORDER_MAIN				1926
+#define IMG_GLOBAL_BORDER_SCORES			1927
+#define IMG_GLOBAL_BORDER_EDITOR			1928
+#define IMG_GLOBAL_BORDER_PLAYING			1929
+#define IMG_GLOBAL_DOOR					1930
+#define IMG_GLOBAL_BUSY					1931
+#define IMG_BACKGROUND					1932
+#define IMG_BACKGROUND_TITLE_INITIAL			1933
+#define IMG_BACKGROUND_TITLE				1934
+#define IMG_BACKGROUND_MAIN				1935
+#define IMG_BACKGROUND_LEVELS				1936
+#define IMG_BACKGROUND_LEVELNR				1937
+#define IMG_BACKGROUND_SCORES				1938
+#define IMG_BACKGROUND_EDITOR				1939
+#define IMG_BACKGROUND_INFO				1940
+#define IMG_BACKGROUND_INFO_ELEMENTS			1941
+#define IMG_BACKGROUND_INFO_MUSIC			1942
+#define IMG_BACKGROUND_INFO_CREDITS			1943
+#define IMG_BACKGROUND_INFO_PROGRAM			1944
+#define IMG_BACKGROUND_INFO_VERSION			1945
+#define IMG_BACKGROUND_INFO_LEVELSET			1946
+#define IMG_BACKGROUND_SETUP				1947
+#define IMG_BACKGROUND_PLAYING				1948
+#define IMG_BACKGROUND_DOOR				1949
+#define IMG_BACKGROUND_TAPE				1950
+#define IMG_BACKGROUND_PANEL				1951
+#define IMG_BACKGROUND_PALETTE				1952
+#define IMG_BACKGROUND_TOOLBOX				1953
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_1		1954
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_2		1955
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_3		1956
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_4		1957
+#define IMG_BACKGROUND_TITLESCREEN_INITIAL_5		1958
+#define IMG_BACKGROUND_TITLESCREEN_1			1959
+#define IMG_BACKGROUND_TITLESCREEN_2			1960
+#define IMG_BACKGROUND_TITLESCREEN_3			1961
+#define IMG_BACKGROUND_TITLESCREEN_4			1962
+#define IMG_BACKGROUND_TITLESCREEN_5			1963
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_1		1964
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_2		1965
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_3		1966
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_4		1967
+#define IMG_BACKGROUND_TITLEMESSAGE_INITIAL_5		1968
+#define IMG_BACKGROUND_TITLEMESSAGE_1			1969
+#define IMG_BACKGROUND_TITLEMESSAGE_2			1970
+#define IMG_BACKGROUND_TITLEMESSAGE_3			1971
+#define IMG_BACKGROUND_TITLEMESSAGE_4			1972
+#define IMG_BACKGROUND_TITLEMESSAGE_5			1973
+#define IMG_BACKGROUND_ENVELOPE_1			1974
+#define IMG_BACKGROUND_ENVELOPE_2			1975
+#define IMG_BACKGROUND_ENVELOPE_3			1976
+#define IMG_BACKGROUND_ENVELOPE_4			1977
+#define IMG_BACKGROUND_REQUEST				1978
+#define IMG_TITLESCREEN_INITIAL_1			1979
+#define IMG_TITLESCREEN_INITIAL_2			1980
+#define IMG_TITLESCREEN_INITIAL_3			1981
+#define IMG_TITLESCREEN_INITIAL_4			1982
+#define IMG_TITLESCREEN_INITIAL_5			1983
+#define IMG_TITLESCREEN_1				1984
+#define IMG_TITLESCREEN_2				1985
+#define IMG_TITLESCREEN_3				1986
+#define IMG_TITLESCREEN_4				1987
+#define IMG_TITLESCREEN_5				1988
+#define IMG_GFX_DOOR_1_PART_1				1989
+#define IMG_GFX_DOOR_1_PART_2				1990
+#define IMG_GFX_DOOR_1_PART_3				1991
+#define IMG_GFX_DOOR_1_PART_4				1992
+#define IMG_GFX_DOOR_1_PART_5				1993
+#define IMG_GFX_DOOR_1_PART_6				1994
+#define IMG_GFX_DOOR_1_PART_7				1995
+#define IMG_GFX_DOOR_1_PART_8				1996
+#define IMG_GFX_DOOR_2_PART_1				1997
+#define IMG_GFX_DOOR_2_PART_2				1998
+#define IMG_GFX_DOOR_2_PART_3				1999
+#define IMG_GFX_DOOR_2_PART_4				2000
+#define IMG_GFX_DOOR_2_PART_5				2001
+#define IMG_GFX_DOOR_2_PART_6				2002
+#define IMG_GFX_DOOR_2_PART_7				2003
+#define IMG_GFX_DOOR_2_PART_8				2004
+#define IMG_DOOR_2_TOP_BORDER_CORRECTION		2005
+#define IMG_LAST_IMAGE_ENTRY_BUG			2006
 
-#define NUM_IMAGE_FILES					1959
+#define NUM_IMAGE_FILES					2007
 
 #endif	/* CONF_GFX_H */
diff --git a/src/conftime.h b/src/conftime.h
index e4e2471..2ce7593 100644
--- a/src/conftime.h
+++ b/src/conftime.h
@@ -1 +1 @@
-#define SOURCE_DATE_STRING "2017-03-15 20:24"
+#define SOURCE_DATE_STRING "2017-10-02 20:25"
diff --git a/src/events.c b/src/events.c
index e2d5ab9..5b1e577 100644
--- a/src/events.c
+++ b/src/events.c
@@ -247,6 +247,19 @@ void HandleOtherEvents(Event *event)
       break;
 
 #if defined(TARGET_SDL)
+#if defined(TARGET_SDL2)
+    case SDL_CONTROLLERBUTTONDOWN:
+    case SDL_CONTROLLERBUTTONUP:
+      // for any game controller button event, disable overlay buttons
+      SetOverlayEnabled(FALSE);
+
+      HandleSpecialGameControllerButtons(event);
+
+      /* FALL THROUGH */
+    case SDL_CONTROLLERDEVICEADDED:
+    case SDL_CONTROLLERDEVICEREMOVED:
+    case SDL_CONTROLLERAXISMOTION:
+#endif
     case SDL_JOYAXISMOTION:
     case SDL_JOYBUTTONDOWN:
     case SDL_JOYBUTTONUP:
@@ -343,6 +356,13 @@ void ClearEventQueue()
 	ClearPlayerAction();
 	break;
 
+#if defined(TARGET_SDL2)
+      case SDL_CONTROLLERBUTTONUP:
+	HandleJoystickEvent(&event);
+	ClearPlayerAction();
+	break;
+#endif
+
       default:
 	HandleOtherEvents(&event);
 	break;
@@ -358,6 +378,8 @@ void ClearPlayerAction()
   key_joystick_mapping = 0;
   for (i = 0; i < MAX_PLAYERS; i++)
     stored_player[i].action = 0;
+
+  ClearJoystickState();
 }
 
 void SleepWhileUnmapped()
@@ -382,6 +404,13 @@ void SleepWhileUnmapped()
 	key_joystick_mapping = 0;
 	break;
 
+#if defined(TARGET_SDL2)
+      case SDL_CONTROLLERBUTTONUP:
+	HandleJoystickEvent(&event);
+	key_joystick_mapping = 0;
+	break;
+#endif
+
       case EVENT_MAPNOTIFY:
 	window_unmapped = FALSE;
 	break;
@@ -532,8 +561,8 @@ void HandleWindowEvent(WindowEvent *event)
       if (new_window_width  != video.window_width ||
 	  new_window_height != video.window_height)
       {
-	int new_xpercent = (100 * new_window_width  / video.screen_width);
-	int new_ypercent = (100 * new_window_height / video.screen_height);
+	int new_xpercent = 100.0 * new_window_width  / video.screen_width  + .5;
+	int new_ypercent = 100.0 * new_window_height / video.screen_height + .5;
 
 	// (extreme window scaling allowed, but cannot be saved permanently)
 	video.window_scaling_percent = MIN(new_xpercent, new_ypercent);
@@ -645,6 +674,9 @@ void HandleFingerEvent(FingerEvent *event)
 			     "KEY_PRESSED");
     int i;
 
+    // for any touch input event, enable overlay buttons (if activated)
+    SetOverlayEnabled(TRUE);
+
     Error(ERR_DEBUG, "::: key '%s' was '%s' [fingerId: %lld]",
 	  getKeyNameFromKey(key), key_status_name, event->fingerId);
 
@@ -1125,9 +1157,16 @@ void HandleKeyEvent(KeyEvent *event)
 #endif
 
 #if defined(PLATFORM_ANDROID)
-  // always map the "back" button to the "escape" key on Android devices
   if (key == KSYM_Back)
+  {
+    // always map the "back" button to the "escape" key on Android devices
     key = KSYM_Escape;
+  }
+  else
+  {
+    // for any key event other than "back" button, disable overlay buttons
+    SetOverlayEnabled(FALSE);
+  }
 #endif
 
   HandleKeyModState(keymod, key_status);
@@ -1233,6 +1272,12 @@ void HandleButton(int mx, int my, int button, int button_nr)
   }
 #endif
 
+  if (HandleGlobalAnimClicks(mx, my, button))
+  {
+    /* do not handle this button event anymore */
+    mx = my = -32;	/* force mouse event to be outside screen tiles */
+  }
+
   if (button_hold && game_status == GAME_MODE_PLAYING && tape.pausing)
     return;
 
@@ -1496,13 +1541,20 @@ void HandleKey(Key key, int key_status)
   int joy = 0;
   int i;
 
+#if defined(TARGET_SDL2)
+  /* map special keys (media keys / remote control buttons) to default keys */
+  if (key == KSYM_PlayPause)
+    key = KSYM_space;
+  else if (key == KSYM_Select)
+    key = KSYM_Return;
+#endif
+
+  HandleSpecialGameControllerKeys(key, key_status);
+
   if (game_status == GAME_MODE_PLAYING)
   {
     /* only needed for single-step tape recording mode */
-    static boolean clear_snap_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
-    static boolean clear_drop_button[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
-    static boolean element_snapped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
-    static boolean element_dropped[MAX_PLAYERS] = { FALSE,FALSE,FALSE,FALSE };
+    static boolean has_snapped[MAX_PLAYERS] = { FALSE, FALSE, FALSE, FALSE };
     int pnr;
 
     for (pnr = 0; pnr < MAX_PLAYERS; pnr++)
@@ -1528,22 +1580,6 @@ void HandleKey(Key key, int key_status)
 	    key_action |= key_info[i].action | JOY_BUTTON_SNAP;
       }
 
-      /* clear delayed snap and drop actions in single step mode (see below) */
-      if (tape.single_step)
-      {
-	if (clear_snap_button[pnr])
-	{
-	  stored_player[pnr].action &= ~KEY_BUTTON_SNAP;
-	  clear_snap_button[pnr] = FALSE;
-	}
-
-	if (clear_drop_button[pnr])
-	{
-	  stored_player[pnr].action &= ~KEY_BUTTON_DROP;
-	  clear_drop_button[pnr] = FALSE;
-	}
-      }
-
       if (key_status == KEY_PRESSED)
 	stored_player[pnr].action |= key_action;
       else
@@ -1555,63 +1591,29 @@ void HandleKey(Key key, int key_status)
 	{
 	  TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
-	  /* if snap key already pressed, don't snap when releasing (below) */
+	  /* if snap key already pressed, keep pause mode when releasing */
 	  if (stored_player[pnr].action & KEY_BUTTON_SNAP)
-	    element_snapped[pnr] = TRUE;
-
-	  /* if drop key already pressed, don't drop when releasing (below) */
-	  if (stored_player[pnr].action & KEY_BUTTON_DROP)
-	    element_dropped[pnr] = TRUE;
+	    has_snapped[pnr] = TRUE;
 	}
 	else if (key_status == KEY_PRESSED && key_action & KEY_BUTTON_DROP)
 	{
-	  if (level.game_engine_type == GAME_ENGINE_TYPE_EM ||
-	      level.game_engine_type == GAME_ENGINE_TYPE_SP)
-	  {
-
-	    if (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
-		getRedDiskReleaseFlag_SP() == 0)
-	      stored_player[pnr].action &= ~KEY_BUTTON_DROP;
+	  TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
-	    TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
+	  if (level.game_engine_type == GAME_ENGINE_TYPE_SP &&
+	      getRedDiskReleaseFlag_SP() == 0)
+	  {
+	    /* add a single inactive frame before dropping starts */
+	    stored_player[pnr].action &= ~KEY_BUTTON_DROP;
+	    stored_player[pnr].force_dropping = TRUE;
 	  }
 	}
-	else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON)
+	else if (key_status == KEY_RELEASED && key_action & KEY_BUTTON_SNAP)
 	{
-	  if (key_action & KEY_BUTTON_SNAP)
-	  {
-	    /* if snap key was released without moving (see above), snap now */
-	    if (!element_snapped[pnr])
-	    {
-	      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-
-	      stored_player[pnr].action |= KEY_BUTTON_SNAP;
-
-	      /* clear delayed snap button on next event */
-	      clear_snap_button[pnr] = TRUE;
-	    }
-
-	    element_snapped[pnr] = FALSE;
-	  }
-
-	  if (key_action & KEY_BUTTON_DROP &&
-	      level.game_engine_type == GAME_ENGINE_TYPE_RND)
-	  {
-	    /* if drop key was released without moving (see above), drop now */
-	    if (!element_dropped[pnr])
-	    {
-	      TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
-
-	      if (level.game_engine_type != GAME_ENGINE_TYPE_SP ||
-		  getRedDiskReleaseFlag_SP() != 0)
-		stored_player[pnr].action |= KEY_BUTTON_DROP;
-
-	      /* clear delayed drop button on next event */
-	      clear_drop_button[pnr] = TRUE;
-	    }
+	  /* if snap key was pressed without direction, leave pause mode */
+	  if (!has_snapped[pnr])
+	    TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
-	    element_dropped[pnr] = FALSE;
-	  }
+	  has_snapped[pnr] = FALSE;
 	}
       }
       else if (tape.recording && tape.pausing)
@@ -1697,6 +1699,15 @@ void HandleKey(Key key, int key_status)
     return;
   }
 
+  if (HandleGlobalAnimClicks(-1, -1, (key == KSYM_space ||
+				      key == KSYM_Return ||
+				      key == KSYM_Escape)))
+  {
+    /* do not handle this key event anymore */
+    if (key != KSYM_Escape)	/* always allow ESC key to be handled */
+      return;
+  }
+
   if (game_status == GAME_MODE_PLAYING && AllPlayersGone &&
       (key == KSYM_Return || key == setup.shortcut.toggle_pause))
   {
@@ -1915,23 +1926,30 @@ static int HandleJoystickForAllPlayers()
 {
   int i;
   int result = 0;
+  boolean no_joysticks_configured = TRUE;
+  boolean use_as_joystick_nr = (game_status != GAME_MODE_PLAYING);
+  static byte joy_action_last[MAX_PLAYERS];
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (setup.input[i].use_joystick)
+      no_joysticks_configured = FALSE;
+
+  /* if no joysticks configured, map connected joysticks to players */
+  if (no_joysticks_configured)
+    use_as_joystick_nr = TRUE;
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     byte joy_action = 0;
 
-    /*
-    if (!setup.input[i].use_joystick)
-      continue;
-      */
-
-    joy_action = Joystick(i);
+    joy_action = JoystickExt(i, use_as_joystick_nr);
     result |= joy_action;
 
-    if (!setup.input[i].use_joystick)
-      continue;
+    if ((setup.input[i].use_joystick || no_joysticks_configured) &&
+	joy_action != joy_action_last[i])
+      stored_player[i].action = joy_action;
 
-    stored_player[i].action = joy_action;
+    joy_action_last[i] = joy_action;
   }
 
   return result;
@@ -1951,6 +1969,12 @@ void HandleJoystick()
   int dx	= (left ? -1	: right ? 1	: 0);
   int dy	= (up   ? -1	: down  ? 1	: 0);
 
+  if (HandleGlobalAnimClicks(-1, -1, newbutton))
+  {
+    /* do not handle this button event anymore */
+    return;
+  }
+
   switch (game_status)
   {
     case GAME_MODE_TITLE:
@@ -1961,10 +1985,23 @@ void HandleJoystick()
     case GAME_MODE_INFO:
     {
       static unsigned int joystickmove_delay = 0;
+      static unsigned int joystickmove_delay_value = GADGET_FRAME_DELAY;
+      static int joystick_last = 0;
 
       if (joystick && !button &&
-	  !DelayReached(&joystickmove_delay, GADGET_FRAME_DELAY))
+	  !DelayReached(&joystickmove_delay, joystickmove_delay_value))
+      {
+	/* delay joystick actions if buttons/axes continually pressed */
 	newbutton = dx = dy = 0;
+      }
+      else
+      {
+	/* start with longer delay, then continue with shorter delay */
+	if (joystick != joystick_last)
+	  joystickmove_delay_value = GADGET_FRAME_DELAY_FIRST;
+	else
+	  joystickmove_delay_value = GADGET_FRAME_DELAY;
+      }
 
       if (game_status == GAME_MODE_TITLE)
 	HandleTitleScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
@@ -1978,6 +2015,9 @@ void HandleJoystick()
 	HandleSetupScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
       else if (game_status == GAME_MODE_INFO)
 	HandleInfoScreen(0,0,dx,dy, newbutton ? MB_MENU_CHOICE : MB_MENU_MARK);
+
+      joystick_last = joystick;
+
       break;
     }
 
@@ -1996,9 +2036,69 @@ void HandleJoystick()
 	return;
       }
 
+      if (tape.recording && tape.pausing)
+      {
+	if (joystick & JOY_ACTION)
+	  TapeTogglePause(TAPE_TOGGLE_MANUAL);
+      }
+
       break;
 
     default:
       break;
   }
 }
+
+void HandleSpecialGameControllerButtons(Event *event)
+{
+#if defined(TARGET_SDL2)
+  switch (event->type)
+  {
+    case SDL_CONTROLLERBUTTONDOWN:
+      if (event->cbutton.button == SDL_CONTROLLER_BUTTON_START)
+	HandleKey(KSYM_space, KEY_PRESSED);
+      else if (event->cbutton.button == SDL_CONTROLLER_BUTTON_BACK)
+	HandleKey(KSYM_Escape, KEY_PRESSED);
+
+      break;
+
+    case SDL_CONTROLLERBUTTONUP:
+      if (event->cbutton.button == SDL_CONTROLLER_BUTTON_START)
+	HandleKey(KSYM_space, KEY_RELEASED);
+      else if (event->cbutton.button == SDL_CONTROLLER_BUTTON_BACK)
+	HandleKey(KSYM_Escape, KEY_RELEASED);
+
+      break;
+  }
+#endif
+}
+
+void HandleSpecialGameControllerKeys(Key key, int key_status)
+{
+#if defined(TARGET_SDL2)
+#if defined(KSYM_Rewind) && defined(KSYM_FastForward)
+  int button = SDL_CONTROLLER_BUTTON_INVALID;
+
+  /* map keys to joystick buttons (special hack for Amazon Fire TV remote) */
+  if (key == KSYM_Rewind)
+    button = SDL_CONTROLLER_BUTTON_A;
+  else if (key == KSYM_FastForward || key == KSYM_Menu)
+    button = SDL_CONTROLLER_BUTTON_B;
+
+  if (button != SDL_CONTROLLER_BUTTON_INVALID)
+  {
+    Event event;
+
+    event.type = (key_status == KEY_PRESSED ? SDL_CONTROLLERBUTTONDOWN :
+		  SDL_CONTROLLERBUTTONUP);
+
+    event.cbutton.which = 0;	/* first joystick (Amazon Fire TV remote) */
+    event.cbutton.button = button;
+    event.cbutton.state = (key_status == KEY_PRESSED ? SDL_PRESSED :
+			   SDL_RELEASED);
+
+    HandleJoystickEvent(&event);
+  }
+#endif
+#endif
+}
diff --git a/src/events.h b/src/events.h
index e5d2dcc..71ff762 100644
--- a/src/events.h
+++ b/src/events.h
@@ -44,5 +44,7 @@ void HandleToonAnimations(void);
 void HandleButton(int, int, int, int);
 void HandleKey(Key, int);
 void HandleJoystick();
+void HandleSpecialGameControllerButtons(Event *);
+void HandleSpecialGameControllerKeys(Key, int);
 
 #endif
diff --git a/src/files.c b/src/files.c
index 4370cba..e9991e1 100644
--- a/src/files.c
+++ b/src/files.c
@@ -8624,7 +8624,7 @@ void LoadSetupFromFilename(char *filename)
   }
   else
   {
-    Error(ERR_WARN, "using default setup values");
+    Error(ERR_DEBUG, "using default setup values");
   }
 }
 
@@ -8690,6 +8690,55 @@ void LoadSetup_EditorCascade()
   free(filename);
 }
 
+static void addGameControllerMappingToHash(SetupFileHash *mappings_hash,
+					   char *mapping_line)
+{
+  char mapping_guid[MAX_LINE_LEN];
+  char *mapping_start, *mapping_end;
+
+  // get GUID from game controller mapping line: copy complete line
+  strncpy(mapping_guid, mapping_line, MAX_LINE_LEN - 1);
+  mapping_guid[MAX_LINE_LEN - 1] = '\0';
+
+  // get GUID from game controller mapping line: cut after GUID part
+  mapping_start = strchr(mapping_guid, ',');
+  if (mapping_start != NULL)
+    *mapping_start = '\0';
+
+  // cut newline from game controller mapping line
+  mapping_end = strchr(mapping_line, '\n');
+  if (mapping_end != NULL)
+    *mapping_end = '\0';
+
+  // add mapping entry to game controller mappings hash
+  setHashEntry(mappings_hash, mapping_guid, mapping_line);
+}
+
+static void LoadSetup_ReadGameControllerMappings(SetupFileHash *mappings_hash,
+						 char *filename)
+{
+  FILE *file;
+
+  if (!(file = fopen(filename, MODE_READ)))
+  {
+    Error(ERR_WARN, "cannot read game controller mappings file '%s'", filename);
+
+    return;
+  }
+
+  while (!feof(file))
+  {
+    char line[MAX_LINE_LEN];
+
+    if (!fgets(line, MAX_LINE_LEN, file))
+      break;
+
+    addGameControllerMappingToHash(mappings_hash, line);
+  }
+
+  fclose(file);
+}
+
 void SaveSetup()
 {
   char *filename = getSetupFilename();
@@ -8799,6 +8848,47 @@ void SaveSetup_EditorCascade()
   free(filename);
 }
 
+static void SaveSetup_WriteGameControllerMappings(SetupFileHash *mappings_hash,
+						  char *filename)
+{
+  FILE *file;
+
+  if (!(file = fopen(filename, MODE_WRITE)))
+  {
+    Error(ERR_WARN, "cannot write game controller mappings file '%s'",filename);
+
+    return;
+  }
+
+  BEGIN_HASH_ITERATION(mappings_hash, itr)
+  {
+    fprintf(file, "%s\n", HASH_ITERATION_VALUE(itr));
+  }
+  END_HASH_ITERATION(mappings_hash, itr)
+
+  fclose(file);
+}
+
+void SaveSetup_AddGameControllerMapping(char *mapping)
+{
+  char *filename = getPath2(getSetupDir(), GAMECONTROLLER_BASENAME);
+  SetupFileHash *mappings_hash = newSetupFileHash();
+
+  InitUserDataDirectory();
+
+  // load existing personal game controller mappings
+  LoadSetup_ReadGameControllerMappings(mappings_hash, filename);
+
+  // add new mapping to personal game controller mappings
+  addGameControllerMappingToHash(mappings_hash, mapping);
+
+  // save updated personal game controller mappings
+  SaveSetup_WriteGameControllerMappings(mappings_hash, filename);
+
+  freeSetupFileHash(mappings_hash);
+  free(filename);
+}
+
 void LoadCustomElementDescriptions()
 {
   char *filename = getCustomArtworkConfigFilename(ARTWORK_TYPE_GRAPHICS);
diff --git a/src/files.h b/src/files.h
index 46dcae9..1db4988 100644
--- a/src/files.h
+++ b/src/files.h
@@ -63,6 +63,8 @@ void SaveSetup();
 void LoadSetup_EditorCascade();
 void SaveSetup_EditorCascade();
 
+void SaveSetup_AddGameControllerMapping(char *);
+
 void LoadCustomElementDescriptions();
 void InitMenuDesignSettings_Static();
 void LoadMenuDesignSettings();
diff --git a/src/game.c b/src/game.c
index 8d2ed46..8978e70 100644
--- a/src/game.c
+++ b/src/game.c
@@ -1619,7 +1619,6 @@ void GetPlayerConfig()
   setup.sound = (setup.sound_simple || setup.sound_loops || setup.sound_music);
 
   SetAudioMode(setup.sound);
-  InitJoysticks();
 }
 
 int GetElementFromGroupElement(int element)
@@ -2699,6 +2698,9 @@ static void InitGameEngine()
   game.use_block_last_field_bug =
     (game.engine_version < VERSION_IDENT(3,1,1,0));
 
+  game_em.use_single_button =
+    (game.engine_version > VERSION_IDENT(4,0,0,2));
+
   /* ---------------------------------------------------------------------- */
 
   /* set maximal allowed number of custom element changes per game frame */
@@ -3222,6 +3224,8 @@ void InitGame()
     player->was_snapping = FALSE;
     player->was_dropping = FALSE;
 
+    player->force_dropping = FALSE;
+
     player->frame_counter_bored = -1;
     player->frame_counter_sleeping = -1;
 
@@ -10712,7 +10716,9 @@ static void CheckSingleStepMode(struct PlayerInfo *player)
   {
     /* as it is called "single step mode", just return to pause mode when the
        player stopped moving after one tile (or never starts moving at all) */
-    if (!player->is_moving && !player->is_pushing)
+    if (!player->is_moving &&
+	!player->is_pushing &&
+	!player->is_dropping_pressed)
     {
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
       SnapField(player, 0, 0);			/* stop snapping */
@@ -11266,6 +11272,14 @@ void GameActions_SP_Main()
     effective_action[i] = stored_player[i].effective_action;
 
   GameActions_SP(effective_action, warp_mode);
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    if (stored_player[i].force_dropping)
+      stored_player[i].action |= KEY_BUTTON_DROP;
+
+    stored_player[i].force_dropping = FALSE;
+  }
 }
 
 void GameActions_RND_Main()
@@ -13977,8 +13991,6 @@ static boolean DropElement(struct PlayerInfo *player)
   int drop_side = drop_direction;
   int drop_element = get_next_dropped_element(player);
 
-  player->is_dropping_pressed = TRUE;
-
   /* do not drop an element on top of another element; when holding drop key
      pressed without moving, dropped element must move away before the next
      element can be dropped (this is especially important if the next element
@@ -14006,6 +14018,9 @@ static boolean DropElement(struct PlayerInfo *player)
   if (new_element == EL_UNDEFINED)
     return FALSE;
 
+  /* only set if player has anything that can be dropped */
+  player->is_dropping_pressed = TRUE;
+
   /* check if drop key was pressed long enough for EM style dynamite */
   if (new_element == EL_EM_DYNAMITE && player->drop_pressed_delay < 40)
     return FALSE;
diff --git a/src/game.h b/src/game.h
index 7bf665e..70df8a2 100644
--- a/src/game.h
+++ b/src/game.h
@@ -281,6 +281,8 @@ struct PlayerInfo
 
   boolean cannot_move;
 
+  boolean force_dropping;	/* needed for single step mode */
+
   int frame_counter_bored;
   int frame_counter_sleeping;
 
diff --git a/src/game_em/convert.c b/src/game_em/convert.c
index d240739..086bc7a 100644
--- a/src/game_em/convert.c
+++ b/src/game_em/convert.c
@@ -1109,6 +1109,9 @@ void prepare_em_level(void)
 
   game_em.any_player_moving = FALSE;
   game_em.any_player_snapping = FALSE;
+
+  game_em.use_single_button = TRUE;
+
   game_em.last_moving_player = 0;	/* default: first player */
 
   for (i = 0; i < MAX_PLAYERS; i++)
diff --git a/src/game_em/export.h b/src/game_em/export.h
index 0968f1d..365cafe 100644
--- a/src/game_em/export.h
+++ b/src/game_em/export.h
@@ -666,6 +666,9 @@ struct GameInfo_EM
 {
   boolean any_player_moving;
   boolean any_player_snapping;
+
+  boolean use_single_button;
+
   int last_moving_player;
   int last_player_direction[MAX_PLAYERS];
 };
@@ -678,6 +681,9 @@ struct LevelInfo_EM
 
   struct LEVEL *lev;
   struct PLAYER *ply[MAX_PLAYERS];
+
+  /* used for runtime values */
+  struct GameInfo_EM *game_em;
 };
 
 struct GraphicInfo_EM
@@ -721,6 +727,7 @@ struct EngineSnapshotInfo_EM
 /* ------------------------------------------------------------------------- */
 
 extern struct GlobalInfo_EM global_em_info;
+extern struct GameInfo_EM game_em;
 extern struct LevelInfo_EM native_em_level;
 extern struct GraphicInfo_EM graphic_info_em_object[TILE_MAX][8];
 extern struct GraphicInfo_EM graphic_info_em_player[MAX_PLAYERS][SPR_MAX][8];
diff --git a/src/game_em/input.c b/src/game_em/input.c
index 4028f19..b8e2e66 100644
--- a/src/game_em/input.c
+++ b/src/game_em/input.c
@@ -119,6 +119,9 @@ void readjoy(byte action, struct PLAYER *ply)
   int north = 0, east = 0, south = 0, west = 0;
   int snap = 0, drop = 0;
 
+  if (game_em.use_single_button && action & (JOY_BUTTON_1 | JOY_BUTTON_2))
+    action |= JOY_BUTTON_1 | JOY_BUTTON_2;
+
   if (action & JOY_LEFT)
     west = 1;
 
@@ -137,16 +140,27 @@ void readjoy(byte action, struct PLAYER *ply)
   if (action & JOY_BUTTON_2)
     drop = 1;
 
-  ply->joy_snap = snap;
+  /* always update drop action */
   ply->joy_drop = drop;
 
-  if (ply->joy_stick || (north | east | south | west))
+  if (ply->joy_stick || (north | east | south | west))	/* (no "| snap"!) */
   {
     ply->joy_n = north;
     ply->joy_e = east;
     ply->joy_s = south;
     ply->joy_w = west;
+
+    /* when storing last action, only update snap action with direction */
+    /* (prevents clearing direction if snapping stopped before frame 7) */
+    ply->joy_snap = snap;
   }
+
+  /* if no direction was stored before, allow setting snap to current state */
+  if (!ply->joy_n &&
+      !ply->joy_e &&
+      !ply->joy_s &&
+      !ply->joy_w)
+    ply->joy_snap = snap;
 }
 
 void SaveEngineSnapshotValues_EM()
diff --git a/src/game_sp/main.c b/src/game_sp/main.c
index 92fc912..3373d46 100644
--- a/src/game_sp/main.c
+++ b/src/game_sp/main.c
@@ -92,5 +92,8 @@ void GameActions_SP(byte action[MAX_PLAYERS], boolean warp_mode)
 
 int getRedDiskReleaseFlag_SP()
 {
+  /* 0: when Murphy is moving (including the destination tile!) */
+  /* 1: when Murphy is not moving for at least one game frame */
+
   return RedDiskReleaseFlag;
 }
diff --git a/src/init.c b/src/init.c
index 97eaf2b..ea7c8f9 100644
--- a/src/init.c
+++ b/src/init.c
@@ -84,6 +84,10 @@ static int copy_properties[][5] =
 };
 
 
+/* forward declaration for internal use */
+static int get_graphic_parameter_value(char *, char *, int);
+
+
 void DrawInitAnim()
 {
   struct GraphicInfo *graphic_info_last = graphic_info;
@@ -409,7 +413,7 @@ void InitFontGraphicInfo()
     int special = property_mapping[i].ext3_index;
     int graphic = property_mapping[i].artwork_index;
 
-    if (font_nr < 0)
+    if (font_nr < 0 || font_nr >= NUM_FONTS)
       continue;
 
     if (IS_SPECIAL_GFX_ARG(special))
@@ -604,6 +608,19 @@ void InitGlobalAnimGraphicInfo()
       special = GFX_SPECIAL_ARG_DEFAULT;
 
     global_anim_info[anim_nr].graphic[part_nr][special] = graphic;
+
+    /* fix default value for ".draw_masked" (for backward compatibility) */
+    struct GraphicInfo *g = &graphic_info[graphic];
+    struct FileInfo *image = getImageListEntryFromImageID(graphic);
+    char **parameter_raw = image->parameter;
+    int p = GFX_ARG_DRAW_MASKED;
+    int draw_masked = get_graphic_parameter_value(parameter_raw[p],
+						  image_config_suffix[p].token,
+						  image_config_suffix[p].type);
+
+    /* if ".draw_masked" parameter is undefined, use default value "TRUE" */
+    if (draw_masked == ARG_UNDEFINED_VALUE)
+      g->draw_masked = TRUE;
   }
 
 #if 0
@@ -1258,6 +1275,9 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->anim_delay_random = 0;
   g->post_delay_fixed = 0;
   g->post_delay_random = 0;
+  g->init_event = ANIM_EVENT_DEFAULT;
+  g->anim_event = ANIM_EVENT_DEFAULT;
+  g->draw_masked = FALSE;
   g->draw_order = 0;
   g->fade_mode = FADE_MODE_DEFAULT;
   g->fade_delay = -1;
@@ -1474,6 +1494,12 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   if (parameter[GFX_ARG_POST_DELAY_RANDOM] != ARG_UNDEFINED_VALUE)
     g->post_delay_random = parameter[GFX_ARG_POST_DELAY_RANDOM];
 
+  /* used for global animations */
+  if (parameter[GFX_ARG_INIT_EVENT] != ARG_UNDEFINED_VALUE)
+    g->init_event = parameter[GFX_ARG_INIT_EVENT];
+  if (parameter[GFX_ARG_ANIM_EVENT] != ARG_UNDEFINED_VALUE)
+    g->anim_event = parameter[GFX_ARG_ANIM_EVENT];
+
   /* used for toon animations and global animations */
   g->step_offset  = parameter[GFX_ARG_STEP_OFFSET];
   g->step_xoffset = parameter[GFX_ARG_STEP_XOFFSET];
@@ -1488,8 +1514,14 @@ static void set_graphic_parameters_ext(int graphic, int *parameter,
   g->draw_xoffset = parameter[GFX_ARG_DRAW_XOFFSET];
   g->draw_yoffset = parameter[GFX_ARG_DRAW_YOFFSET];
 
-  /* this is only used for drawing envelope graphics */
-  g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
+  /* use a different default value for global animations and toons */
+  if ((graphic >= IMG_GFX_GLOBAL_ANIM_1 && graphic <= IMG_GFX_GLOBAL_ANIM_8) ||
+      (graphic >= IMG_TOON_1            && graphic <= IMG_TOON_20))
+    g->draw_masked = TRUE;
+
+  /* this is used for drawing envelopes, global animations and toons */
+  if (parameter[GFX_ARG_DRAW_MASKED] != ARG_UNDEFINED_VALUE)
+    g->draw_masked = parameter[GFX_ARG_DRAW_MASKED];
 
   /* used for toon animations and global animations */
   if (parameter[GFX_ARG_DRAW_ORDER] != ARG_UNDEFINED_VALUE)
@@ -4690,6 +4722,16 @@ static void InitGlobal()
     element_info[i].editor_description= element_name_info[i].editor_description;
   }
 
+  for (i = 0; i < NUM_GLOBAL_ANIM_TOKENS + 1; i++)
+  {
+    /* check if global_anim_name_info defined for each entry in "main.h" */
+    if (i < NUM_GLOBAL_ANIM_TOKENS &&
+	global_anim_name_info[i].token_name == NULL)
+      Error(ERR_EXIT, "undefined 'global_anim_name_info' entry for anim %d", i);
+
+    global_anim_info[i].token_name = global_anim_name_info[i].token_name;
+  }
+
   /* create hash from image config list */
   image_config_hash = newSetupFileHash();
   for (i = 0; image_config[i].token != NULL; i++)
@@ -6032,10 +6074,10 @@ void OpenAll()
   Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStoragePath() == '%s'",
 	SDL_AndroidGetExternalStoragePath());
   Error(ERR_DEBUG, "::: SDL_AndroidGetExternalStorageState() == '%s'",
-	(SDL_AndroidGetExternalStorageState() ==
-	 SDL_ANDROID_EXTERNAL_STORAGE_READ ? "read" :
-	 SDL_AndroidGetExternalStorageState() ==
-	 SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "write" : "not available"));
+	(SDL_AndroidGetExternalStorageState() &
+	 SDL_ANDROID_EXTERNAL_STORAGE_WRITE ? "writable" :
+	 SDL_AndroidGetExternalStorageState() &
+	 SDL_ANDROID_EXTERNAL_STORAGE_READ ? "readable" : "not available"));
 #endif
 #endif
 }
diff --git a/src/libgame/joystick.c b/src/libgame/joystick.c
index 92eec0e..dfe1cca 100644
--- a/src/libgame/joystick.c
+++ b/src/libgame/joystick.c
@@ -119,6 +119,39 @@ char *getDeviceNameFromJoystickNr(int joystick_nr)
 	  joystick_device_name[joystick_nr] : "");
 }
 
+char *getFormattedJoystickName(const char *name_raw)
+{
+  static char name[MAX_JOYSTICK_NAME_LEN + 1];
+  boolean name_skip_space = TRUE;
+  int i, j;
+
+  if (name_raw == NULL)
+    name_raw = "(unknown joystick)";
+
+  // copy joystick name, cutting leading and multiple spaces
+  for (i = 0, j = 0; i < strlen(name_raw) && i < MAX_JOYSTICK_NAME_LEN; i++)
+  {
+    if (name_raw[i] != ' ')
+    {
+      name[j++] = name_raw[i];
+      name_skip_space = FALSE;
+    }
+    else if (!name_skip_space)
+    {
+      name[j++] = name_raw[i];
+      name_skip_space = TRUE;
+    }
+  }
+
+  // cut trailing space
+  if (j > 0 && name[j - 1] == ' ')
+    j--;
+
+  name[j] = '\0';
+
+  return name;
+}
+
 static int JoystickPositionPercent(int center, int border, int actual)
 {
   int range, position;
@@ -159,21 +192,24 @@ void CheckJoystickData()
   }
 }
 
-int Joystick(int player_nr)
+int JoystickExt(int player_nr, boolean use_as_joystick_nr)
 {
-  int joystick_fd = joystick.fd[player_nr];
+  int joystick_nr = joystick.nr[player_nr];
   int js_x, js_y;
   boolean js_b1, js_b2;
   int left, right, up, down;
   int result = JOY_NO_ACTION;
 
+  if (use_as_joystick_nr)
+    joystick_nr = player_nr;
+
   if (joystick.status != JOYSTICK_ACTIVATED)
     return JOY_NO_ACTION;
 
-  if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
+  if (joystick_nr < 0)
     return JOY_NO_ACTION;
 
-  if (!ReadJoystick(joystick_fd, &js_x, &js_y, &js_b1, &js_b2))
+  if (!ReadJoystick(joystick_nr, &js_x, &js_y, &js_b1, &js_b2))
   {
     Error(ERR_WARN, "cannot read joystick device '%s'",
 	  setup.input[player_nr].joy.device_name);
@@ -208,10 +244,15 @@ int Joystick(int player_nr)
   return result;
 }
 
-int JoystickButton(int player_nr)
+int Joystick(int player_nr)
+{
+  return JoystickExt(player_nr, FALSE);
+}
+
+int JoystickButtonExt(int player_nr, boolean use_as_joystick_nr)
 {
   static int last_joy_button[MAX_PLAYERS] = { 0, 0, 0, 0 };
-  int joy_button = (Joystick(player_nr) & JOY_BUTTON);
+  int joy_button = (JoystickExt(player_nr, use_as_joystick_nr) & JOY_BUTTON);
   int result;
 
   if (joy_button)
@@ -233,13 +274,18 @@ int JoystickButton(int player_nr)
   return result;
 }
 
+int JoystickButton(int player_nr)
+{
+  return JoystickButtonExt(player_nr, FALSE);
+}
+
 int AnyJoystick()
 {
   int i;
   int result = 0;
 
   for (i = 0; i < MAX_PLAYERS; i++)
-    result |= Joystick(i);
+    result |= JoystickExt(i, TRUE);
 
   return result;
 }
@@ -251,7 +297,7 @@ int AnyJoystickButton()
 
   for (i = 0; i < MAX_PLAYERS; i++)
   {
-    result = JoystickButton(i);
+    result = JoystickButtonExt(i, TRUE);
     if (result != JOY_BUTTON_NOT_PRESSED)
       break;
   }
diff --git a/src/libgame/joystick.h b/src/libgame/joystick.h
index c7f65fe..48202d2 100644
--- a/src/libgame/joystick.h
+++ b/src/libgame/joystick.h
@@ -17,8 +17,12 @@
 #define JOYSTICK_NOT_AVAILABLE	0
 #define	JOYSTICK_AVAILABLE	(1 << 0)
 #define	JOYSTICK_ACTIVE		(1 << 1)
+#define JOYSTICK_CONFIGURED	(1 << 2)
+#define JOYSTICK_NOT_CONFIGURED	(1 << 3)
 #define JOYSTICK_ACTIVATED	(JOYSTICK_AVAILABLE | JOYSTICK_ACTIVE)
 
+#define MAX_JOYSTICK_NAME_LEN	40
+
 #if defined(PLATFORM_FREEBSD)
 #define DEV_JOYSTICK_0		"/dev/joy0"
 #define DEV_JOYSTICK_1		"/dev/joy1"
@@ -34,21 +38,14 @@
 /* get these values from the program 'js' from the joystick package, */
 /* set JOYSTICK_PERCENT to a threshold appropriate for your joystick */
 
-#if defined(TARGET_SDL)
-#define JOYSTICK_XLEFT		-32767
+#define JOYSTICK_MAX_AXIS_POS	32767
+
+#define JOYSTICK_XLEFT		-JOYSTICK_MAX_AXIS_POS
 #define JOYSTICK_XMIDDLE	0
-#define JOYSTICK_XRIGHT		32767
-#define JOYSTICK_YUPPER		-32767
+#define JOYSTICK_XRIGHT		+JOYSTICK_MAX_AXIS_POS
+#define JOYSTICK_YUPPER		-JOYSTICK_MAX_AXIS_POS
 #define JOYSTICK_YMIDDLE	0
-#define JOYSTICK_YLOWER		32767
-#else
-#define JOYSTICK_XLEFT		1
-#define JOYSTICK_XMIDDLE	128
-#define JOYSTICK_XRIGHT		255
-#define JOYSTICK_YUPPER		1
-#define JOYSTICK_YMIDDLE	128
-#define JOYSTICK_YLOWER		255
-#endif
+#define JOYSTICK_YLOWER		+JOYSTICK_MAX_AXIS_POS
 
 #define JOYSTICK_PERCENT	25
 
@@ -74,9 +71,11 @@ char *getJoyNameFromJoySymbol(int);
 int getJoySymbolFromJoyName(char *);
 int getJoystickNrFromDeviceName(char *);
 char *getDeviceNameFromJoystickNr(int);
+char *getFormattedJoystickName(const char *);
 
 void CheckJoystickData(void);
 int Joystick(int);
+int JoystickExt(int, boolean);
 int JoystickButton(int);
 int AnyJoystick(void);
 int AnyJoystickButton(void);
diff --git a/src/libgame/misc.c b/src/libgame/misc.c
index 0c0e82c..ed34319 100644
--- a/src/libgame/misc.c
+++ b/src/libgame/misc.c
@@ -985,6 +985,7 @@ void GetOptions(int argc, char *argv[],
   options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
   options.music_directory    = getPath2(ro_base_path, MUSIC_DIRECTORY);
   options.docs_directory     = getPath2(ro_base_path, DOCS_DIRECTORY);
+  options.conf_directory     = getPath2(ro_base_path, CONF_DIRECTORY);
 
   options.execute_command = NULL;
   options.special_flags = NULL;
@@ -1063,6 +1064,7 @@ void GetOptions(int argc, char *argv[],
       options.sounds_directory   = getPath2(ro_base_path, SOUNDS_DIRECTORY);
       options.music_directory    = getPath2(ro_base_path, MUSIC_DIRECTORY);
       options.docs_directory     = getPath2(ro_base_path, DOCS_DIRECTORY);
+      options.conf_directory     = getPath2(ro_base_path, CONF_DIRECTORY);
     }
     else if (strncmp(option, "-levels", option_len) == 0)
     {
@@ -1210,6 +1212,10 @@ void Error(int mode, char *format, ...)
 		      ANDROID_LOG_UNKNOWN);
 #endif
 
+  /* display debug messages only when running in debug mode */
+  if (mode & ERR_DEBUG && !options.debug)
+    return;
+
   /* display warnings only when running in verbose mode */
   if (mode & ERR_WARN && !options.verbose)
     return;
@@ -1611,8 +1617,14 @@ void translate_keyname(Key *keysym, char **x11name, char **name, int mode)
     { KSYM_Page_Down,	"XK_Page_Down",		"page down" },
 
 #if defined(TARGET_SDL2)
+    { KSYM_Select,	"XK_Select",		"select" },
     { KSYM_Menu,	"XK_Menu",		"menu" },	 /* menu key */
     { KSYM_Back,	"XK_Back",		"back" },	 /* back key */
+    { KSYM_PlayPause,	"XK_PlayPause",		"play/pause" },
+#if defined(PLATFORM_ANDROID)
+    { KSYM_Rewind,	"XK_Rewind",		"rewind" },
+    { KSYM_FastForward,	"XK_FastForward",	"fast forward" },
+#endif
 #endif
 
     /* ASCII 0x20 to 0x40 keys (except numbers) */
@@ -2655,6 +2667,30 @@ char *get_special_base_token(struct ArtworkListInfo *artwork_info, char *token)
     { "global.anim_6"	},
     { "global.anim_7"	},
     { "global.anim_8"	},
+    { "global.anim_9"	},
+    { "global.anim_10"	},
+    { "global.anim_11"	},
+    { "global.anim_12"	},
+    { "global.anim_13"	},
+    { "global.anim_14"	},
+    { "global.anim_15"	},
+    { "global.anim_16"	},
+    { "global.anim_17"	},
+    { "global.anim_18"	},
+    { "global.anim_19"	},
+    { "global.anim_20"	},
+    { "global.anim_21"	},
+    { "global.anim_22"	},
+    { "global.anim_23"	},
+    { "global.anim_24"	},
+    { "global.anim_25"	},
+    { "global.anim_26"	},
+    { "global.anim_27"	},
+    { "global.anim_28"	},
+    { "global.anim_29"	},
+    { "global.anim_30"	},
+    { "global.anim_31"	},
+    { "global.anim_32"	},
 
     { NULL		}
   };
@@ -2716,6 +2752,73 @@ static boolean string_has_parameter(char *s, char *s_contained)
   return string_has_parameter(substring, s_contained);
 }
 
+int get_anim_parameter_value(char *s)
+{
+  char *pattern_1 = "click:anim_";
+  char *pattern_2 = ".part_";
+  char *matching_char = NULL;
+  char *s_ptr = s;
+  int result = ANIM_EVENT_NONE;
+
+  matching_char = strstr(s_ptr, pattern_1);
+  if (matching_char == NULL)
+    return ANIM_EVENT_NONE;
+
+  s_ptr = matching_char + strlen(pattern_1);
+
+  // check for main animation number ("anim_X" or "anim_XX")
+  if (*s_ptr >= '0' && *s_ptr <= '9')
+  {
+    int gic_anim_nr = (*s_ptr++ - '0');
+
+    if (*s_ptr >= '0' && *s_ptr <= '9')
+      gic_anim_nr = 10 * gic_anim_nr + (*s_ptr++ - '0');
+
+    if (gic_anim_nr < 1 || gic_anim_nr > MAX_GLOBAL_ANIMS)
+      return ANIM_EVENT_NONE;
+
+    result |= gic_anim_nr << ANIM_EVENT_ANIM_BIT;
+  }
+  else
+  {
+    // invalid main animation number specified
+
+    return ANIM_EVENT_NONE;
+  }
+
+  // check for animation part number ("part_X" or "part_XX") (optional)
+  if (strPrefix(s_ptr, pattern_2))
+  {
+    s_ptr += strlen(pattern_2);
+
+    if (*s_ptr >= '0' && *s_ptr <= '9')
+    {
+      int gic_part_nr = (*s_ptr++ - '0');
+
+      if (*s_ptr >= '0' && *s_ptr <= '9')
+	gic_part_nr = 10 * gic_part_nr + (*s_ptr++ - '0');
+
+      if (gic_part_nr < 1 || gic_part_nr > MAX_GLOBAL_ANIM_PARTS)
+	return ANIM_EVENT_NONE;
+
+      result |= gic_part_nr << ANIM_EVENT_PART_BIT;
+    }
+    else
+    {
+      // invalid animation part number specified
+
+      return ANIM_EVENT_NONE;
+    }
+  }
+
+  /* discard result if next character is neither delimiter nor whitespace */
+  if (!(*s_ptr == ',' || *s_ptr == '\0' ||
+	*s_ptr == ' ' || *s_ptr == '\t'))
+    return ANIM_EVENT_NONE;
+
+  return result;
+}
+
 int get_parameter_value(char *value_raw, char *suffix, int type)
 {
   char *value = getStringToLower(value_raw);
@@ -2737,7 +2840,8 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
 	      strEqual(value, "middle") ? POS_MIDDLE :
 	      strEqual(value, "lower")  ? POS_LOWER :
 	      strEqual(value, "bottom") ? POS_BOTTOM :
-	      strEqual(value, "any")    ? POS_ANY : POS_UNDEFINED);
+	      strEqual(value, "any")    ? POS_ANY :
+	      strEqual(value, "last")   ? POS_LAST : POS_UNDEFINED);
   }
   else if (strEqual(suffix, ".align"))
   {
@@ -2782,6 +2886,20 @@ int get_parameter_value(char *value_raw, char *suffix, int type)
     if (string_has_parameter(value, "static_panel"))
       result |= ANIM_STATIC_PANEL;
   }
+  else if (strEqual(suffix, ".init_event") ||
+	   strEqual(suffix, ".anim_event"))
+  {
+    result = ANIM_EVENT_DEFAULT;
+
+    if (string_has_parameter(value, "any"))
+      result |= ANIM_EVENT_ANY;
+
+    if (string_has_parameter(value, "click"))
+      result |= ANIM_EVENT_SELF;
+
+    // add optional "click:anim_X" or "click:anim_X.part_X" parameter
+    result |= get_anim_parameter_value(value);
+  }
   else if (strEqual(suffix, ".class"))
   {
     result = (strEqual(value, ARG_UNDEFINED) ? ARG_UNDEFINED_VALUE :
diff --git a/src/libgame/sdl.c b/src/libgame/sdl.c
index e275149..14ad28f 100644
--- a/src/libgame/sdl.c
+++ b/src/libgame/sdl.c
@@ -17,6 +17,8 @@
 
 #define ENABLE_UNUSED_CODE	0	/* currently unused functions */
 
+#define DEBUG_JOYSTICKS		0
+
 
 /* ========================================================================= */
 /* video functions                                                           */
@@ -532,11 +534,7 @@ inline static void SDLInitVideoBuffer_VideoBuffer(boolean fullscreen)
   SDLSetWindowIcon(program.icon_filename);
 
   /* set window and icon title */
-#if defined(TARGET_SDL2)
-  SDL_SetWindowTitle(sdl_window, program.window_title);
-#else
-  SDL_WM_SetCaption(program.window_title, program.window_title);
-#endif
+  SDLSetWindowTitle();
 }
 
 inline static void SDLInitVideoBuffer_DrawBuffer()
@@ -830,6 +828,9 @@ boolean SDLSetVideoMode(boolean fullscreen)
 void SDLSetWindowTitle()
 {
 #if defined(TARGET_SDL2)
+  if (sdl_window == NULL)
+    return;
+
   SDL_SetWindowTitle(sdl_window, program.window_title);
 #else
   SDL_WM_SetCaption(program.window_title, program.window_title);
@@ -2591,31 +2592,83 @@ void SDLHandleWindowManagerEvent(Event *event)
 /* joystick functions                                                        */
 /* ========================================================================= */
 
-static SDL_Joystick *sdl_joystick[MAX_PLAYERS] = { NULL, NULL, NULL, NULL };
-static int sdl_js_axis[MAX_PLAYERS][2]   = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
-static int sdl_js_button[MAX_PLAYERS][2] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} };
+#if defined(TARGET_SDL2)
+static void *sdl_joystick[MAX_PLAYERS];		// game controller or joystick
+#else
+static SDL_Joystick *sdl_joystick[MAX_PLAYERS];	// only joysticks supported
+#endif
+static int sdl_js_axis_raw[MAX_PLAYERS][2];
+static int sdl_js_axis[MAX_PLAYERS][2];
+static int sdl_js_button[MAX_PLAYERS][2];
+static boolean sdl_is_controller[MAX_PLAYERS];
+
+void SDLClearJoystickState()
+{
+  int i, j;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+  {
+    for (j = 0; j < 2; j++)
+    {
+      sdl_js_axis_raw[i][j] = -1;
+      sdl_js_axis[i][j] = 0;
+      sdl_js_button[i][j] = 0;
+    }
+  }
+}
 
-static boolean SDLOpenJoystick(int nr)
+boolean SDLOpenJoystick(int nr)
 {
-  if (nr < 0 || nr > MAX_PLAYERS)
+  if (nr < 0 || nr >= MAX_PLAYERS)
     return FALSE;
 
-  return ((sdl_joystick[nr] = SDL_JoystickOpen(nr)) == NULL ? FALSE : TRUE);
+#if defined(TARGET_SDL2)
+  sdl_is_controller[nr] = SDL_IsGameController(nr);
+#else
+  sdl_is_controller[nr] = FALSE;
+#endif
+
+#if DEBUG_JOYSTICKS
+  Error(ERR_DEBUG, "opening joystick %d (%s)",
+	nr, (sdl_is_controller[nr] ? "game controller" : "joystick"));
+#endif
+
+#if defined(TARGET_SDL2)
+  if (sdl_is_controller[nr])
+    sdl_joystick[nr] = SDL_GameControllerOpen(nr);
+  else
+    sdl_joystick[nr] = SDL_JoystickOpen(nr);
+#else
+  sdl_joystick[nr] = SDL_JoystickOpen(nr);
+#endif
+
+  return (sdl_joystick[nr] != NULL);
 }
 
-static void SDLCloseJoystick(int nr)
+void SDLCloseJoystick(int nr)
 {
-  if (nr < 0 || nr > MAX_PLAYERS)
+  if (nr < 0 || nr >= MAX_PLAYERS)
     return;
 
+#if DEBUG_JOYSTICKS
+  Error(ERR_DEBUG, "closing joystick %d", nr);
+#endif
+
+#if defined(TARGET_SDL2)
+  if (sdl_is_controller[nr])
+    SDL_GameControllerClose(sdl_joystick[nr]);
+  else
+    SDL_JoystickClose(sdl_joystick[nr]);
+#else
   SDL_JoystickClose(sdl_joystick[nr]);
+#endif
 
   sdl_joystick[nr] = NULL;
 }
 
-static boolean SDLCheckJoystickOpened(int nr)
+boolean SDLCheckJoystickOpened(int nr)
 {
-  if (nr < 0 || nr > MAX_PLAYERS)
+  if (nr < 0 || nr >= MAX_PLAYERS)
     return FALSE;
 
 #if defined(TARGET_SDL2)
@@ -2625,23 +2678,164 @@ static boolean SDLCheckJoystickOpened(int nr)
 #endif
 }
 
+static void setJoystickAxis(int nr, int axis_id_raw, int axis_value)
+{
+#if defined(TARGET_SDL2)
+  int axis_id = (axis_id_raw == SDL_CONTROLLER_AXIS_LEFTX ||
+		 axis_id_raw == SDL_CONTROLLER_AXIS_RIGHTX ? 0 :
+		 axis_id_raw == SDL_CONTROLLER_AXIS_LEFTY ||
+		 axis_id_raw == SDL_CONTROLLER_AXIS_RIGHTY ? 1 : -1);
+#else
+  int axis_id = axis_id_raw % 2;
+#endif
+
+  if (nr < 0 || nr >= MAX_PLAYERS)
+    return;
+
+  if (axis_id == -1)
+    return;
+
+  // prevent (slightly jittering, but centered) axis A from resetting axis B
+  if (ABS(axis_value) < JOYSTICK_PERCENT * JOYSTICK_MAX_AXIS_POS / 100 &&
+      axis_id_raw != sdl_js_axis_raw[nr][axis_id])
+    return;
+
+  sdl_js_axis[nr][axis_id] = axis_value;
+  sdl_js_axis_raw[nr][axis_id] = axis_id_raw;
+}
+
+static void setJoystickButton(int nr, int button_id_raw, int button_state)
+{
+#if defined(TARGET_SDL2)
+  int button_id = (button_id_raw == SDL_CONTROLLER_BUTTON_A ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_X ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_LEFTSHOULDER ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_LEFTSTICK ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_RIGHTSTICK ? 0 :
+		   button_id_raw == SDL_CONTROLLER_BUTTON_B ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_Y ||
+		   button_id_raw == SDL_CONTROLLER_BUTTON_RIGHTSHOULDER ? 1 :
+		   -1);
+
+  if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_LEFT)
+    sdl_js_axis[nr][0] = button_state * JOYSTICK_XLEFT;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_RIGHT)
+    sdl_js_axis[nr][0] = button_state * JOYSTICK_XRIGHT;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_UP)
+    sdl_js_axis[nr][1] = button_state * JOYSTICK_YUPPER;
+  else if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
+    sdl_js_axis[nr][1] = button_state * JOYSTICK_YLOWER;
+
+  if (button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_LEFT ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_RIGHT ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_UP ||
+      button_id_raw == SDL_CONTROLLER_BUTTON_DPAD_DOWN)
+    sdl_js_axis_raw[nr][0] = sdl_js_axis_raw[nr][1] = -1;
+#else
+  int button_id = button_id_raw % 2;
+#endif
+
+  if (nr < 0 || nr >= MAX_PLAYERS)
+    return;
+
+  if (button_id == -1)
+    return;
+
+  sdl_js_button[nr][button_id] = button_state;
+}
+
 void HandleJoystickEvent(Event *event)
 {
   switch(event->type)
   {
+#if defined(TARGET_SDL2)
+    case SDL_CONTROLLERDEVICEADDED:
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_CONTROLLERDEVICEADDED: device %d added",
+	    event->cdevice.which);
+#endif
+      InitJoysticks();
+      break;
+
+    case SDL_CONTROLLERDEVICEREMOVED:
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_CONTROLLERDEVICEREMOVED: device %d removed",
+	    event->cdevice.which);
+#endif
+      InitJoysticks();
+      break;
+
+    case SDL_CONTROLLERAXISMOTION:
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_CONTROLLERAXISMOTION: device %d, axis %d: %d",
+	    event->caxis.which, event->caxis.axis, event->caxis.value);
+#endif
+      setJoystickAxis(event->caxis.which,
+		      event->caxis.axis,
+		      event->caxis.value);
+      break;
+
+    case SDL_CONTROLLERBUTTONDOWN:
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONDOWN: device %d, button %d",
+	    event->cbutton.which, event->cbutton.button);
+#endif
+      setJoystickButton(event->cbutton.which,
+			event->cbutton.button,
+			TRUE);
+      break;
+
+    case SDL_CONTROLLERBUTTONUP:
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_CONTROLLERBUTTONUP: device %d, button %d",
+	    event->cbutton.which, event->cbutton.button);
+#endif
+      setJoystickButton(event->cbutton.which,
+			event->cbutton.button,
+			FALSE);
+      break;
+#endif
+
     case SDL_JOYAXISMOTION:
-      if (event->jaxis.axis < 2)
-	sdl_js_axis[event->jaxis.which][event->jaxis.axis]= event->jaxis.value;
+      if (sdl_is_controller[event->jaxis.which])
+	break;
+
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_JOYAXISMOTION: device %d, axis %d: %d",
+	    event->jaxis.which, event->jaxis.axis, event->jaxis.value);
+#endif
+      if (event->jaxis.axis < 4)
+	setJoystickAxis(event->jaxis.which,
+			event->jaxis.axis,
+			event->jaxis.value);
       break;
 
     case SDL_JOYBUTTONDOWN:
-      if (event->jbutton.button < 2)
-	sdl_js_button[event->jbutton.which][event->jbutton.button] = TRUE;
+      if (sdl_is_controller[event->jaxis.which])
+	break;
+
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_JOYBUTTONDOWN: device %d, button %d",
+	    event->jbutton.which, event->jbutton.button);
+#endif
+      if (event->jbutton.button < 4)
+	setJoystickButton(event->jbutton.which,
+			  event->jbutton.button,
+			  TRUE);
       break;
 
     case SDL_JOYBUTTONUP:
-      if (event->jbutton.button < 2)
-	sdl_js_button[event->jbutton.which][event->jbutton.button] = FALSE;
+      if (sdl_is_controller[event->jaxis.which])
+	break;
+
+#if DEBUG_JOYSTICKS
+      Error(ERR_DEBUG, "SDL_JOYBUTTONUP: device %d, button %d",
+	    event->jbutton.which, event->jbutton.button);
+#endif
+      if (event->jbutton.button < 4)
+	setJoystickButton(event->jbutton.which,
+			  event->jbutton.button,
+			  FALSE);
       break;
 
     default:
@@ -2653,19 +2847,81 @@ void SDLInitJoysticks()
 {
   static boolean sdl_joystick_subsystem_initialized = FALSE;
   boolean print_warning = !sdl_joystick_subsystem_initialized;
+#if defined(TARGET_SDL2)
+  char *mappings_file_base = getPath2(options.conf_directory,
+				      GAMECONTROLLER_BASENAME);
+  char *mappings_file_user = getPath2(getUserGameDataDir(),
+				      GAMECONTROLLER_BASENAME);
+  int num_mappings;
+#endif
   int i;
 
   if (!sdl_joystick_subsystem_initialized)
   {
     sdl_joystick_subsystem_initialized = TRUE;
 
+#if defined(TARGET_SDL2)
+    SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
+
+    if (SDL_InitSubSystem(SDL_INIT_GAMECONTROLLER) < 0)
+#else
     if (SDL_InitSubSystem(SDL_INIT_JOYSTICK) < 0)
+#endif
     {
       Error(ERR_EXIT, "SDL_Init() failed: %s", SDL_GetError());
       return;
     }
+
+#if defined(TARGET_SDL2)
+    num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file_base);
+
+    /* the included game controller base mappings should always be found */
+    if (num_mappings == -1)
+      Error(ERR_WARN, "no game controller base mappings found");
+#if DEBUG_JOYSTICKS
+    else
+      Error(ERR_INFO, "%d game controller base mapping(s) added", num_mappings);
+#endif
+
+    num_mappings = SDL_GameControllerAddMappingsFromFile(mappings_file_user);
+
+#if DEBUG_JOYSTICKS
+    /* the personal game controller user mappings may or may not be found */
+    if (num_mappings == -1)
+      Error(ERR_WARN, "no game controller user mappings found");
+    else
+      Error(ERR_INFO, "%d game controller user mapping(s) added", num_mappings);
+
+    Error(ERR_INFO, "%d joystick(s) found:", SDL_NumJoysticks());
+#endif
+
+    checked_free(mappings_file_base);
+    checked_free(mappings_file_user);
+
+#if DEBUG_JOYSTICKS
+    for (i = 0; i < SDL_NumJoysticks(); i++)
+    {
+      const char *name, *type;
+
+      if (SDL_IsGameController(i))
+      {
+	name = SDL_GameControllerNameForIndex(i);
+	type = "game controller";
+      }
+      else
+      {
+	name = SDL_JoystickNameForIndex(i);
+	type = "joystick";
+      }
+
+      Error(ERR_INFO, "- joystick %d (%s): '%s'",
+	    i, type, (name ? name : "(Unknown)"));
+    }
+#endif
+#endif
   }
 
+  /* assign joysticks from configured to connected joystick for all players */
   for (i = 0; i < MAX_PLAYERS; i++)
   {
     /* get configured joystick for this player */
@@ -2680,29 +2936,24 @@ void SDLInitJoysticks()
       joystick_nr = -1;
     }
 
-    /* misuse joystick file descriptor variable to store joystick number */
-    joystick.fd[i] = joystick_nr;
-
-    if (joystick_nr == -1)
-      continue;
+    /* store configured joystick number for each player */
+    joystick.nr[i] = joystick_nr;
+  }
 
+  /* now open all connected joysticks (regardless if configured or not) */
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+  {
     /* this allows subsequent calls to 'InitJoysticks' for re-initialization */
-    if (SDLCheckJoystickOpened(joystick_nr))
-      SDLCloseJoystick(joystick_nr);
-
-    if (!setup.input[i].use_joystick)
-      continue;
-
-    if (!SDLOpenJoystick(joystick_nr))
-    {
-      if (print_warning)
-	Error(ERR_WARN, "cannot open joystick %d", joystick_nr);
-
-      continue;
-    }
+    if (SDLCheckJoystickOpened(i))
+      SDLCloseJoystick(i);
 
-    joystick.status = JOYSTICK_ACTIVATED;
+    if (SDLOpenJoystick(i))
+      joystick.status = JOYSTICK_ACTIVATED;
+    else if (print_warning)
+      Error(ERR_WARN, "cannot open joystick %d", i);
   }
+
+  SDLClearJoystickState();
 }
 
 boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
@@ -2723,6 +2974,11 @@ boolean SDLReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
   return TRUE;
 }
 
+
+/* ========================================================================= */
+/* touch input overlay functions                                             */
+/* ========================================================================= */
+
 #if defined(USE_TOUCH_INPUT_OVERLAY)
 static void DrawTouchInputOverlay()
 {
@@ -2734,11 +2990,12 @@ static void DrawTouchInputOverlay()
   static int alpha_step = 5;
   static int alpha_last = 0;
   static int alpha = 0;
+  boolean active = (overlay.enabled && overlay.active);
 
-  if (!overlay.active && deactivated)
+  if (!active && deactivated)
     return;
 
-  if (overlay.active)
+  if (active)
   {
     if (alpha < alpha_max)
       alpha = MIN(alpha + alpha_step, alpha_max);
diff --git a/src/libgame/sdl.h b/src/libgame/sdl.h
index c88b6a8..9ee6c69 100644
--- a/src/libgame/sdl.h
+++ b/src/libgame/sdl.h
@@ -199,8 +199,14 @@ struct MouseCursorInfo
 #define KSYM_Page_Down		SDLK_PAGEDOWN
 
 #if defined(TARGET_SDL2)
+#define KSYM_Select		SDLK_SELECT
 #define KSYM_Menu		SDLK_MENU
 #define KSYM_Back		SDLK_AC_BACK
+#define KSYM_PlayPause		SDLK_AUDIOPLAY
+#if defined(PLATFORM_ANDROID)
+#define KSYM_Rewind		SDLK_AUDIOREWIND
+#define KSYM_FastForward	SDLK_AUDIOFASTFORWARD
+#endif
 #endif
 
 #define KSYM_space		SDLK_SPACE
@@ -484,6 +490,10 @@ void SDLHandleWindowManagerEvent(Event *);
 void HandleJoystickEvent(Event *);
 void SDLInitJoysticks(void);
 boolean SDLReadJoystick(int, int *, int *, boolean *, boolean *);
+boolean SDLCheckJoystickOpened(int);
+void SDLClearJoystickState();
+boolean SDLOpenJoystick(int);
+void SDLCloseJoystick(int);
 
 void PrepareFadeBitmap(int);
 
diff --git a/src/libgame/setup.c b/src/libgame/setup.c
index 03d9bfd..defacd4 100644
--- a/src/libgame/setup.c
+++ b/src/libgame/setup.c
@@ -1400,7 +1400,10 @@ char *getUserGameDataDir(void)
 
 #if defined(PLATFORM_ANDROID)
   if (user_game_data_dir == NULL)
-    user_game_data_dir = (char *)SDL_AndroidGetInternalStoragePath();
+    user_game_data_dir = (char *)(SDL_AndroidGetExternalStorageState() &
+				  SDL_ANDROID_EXTERNAL_STORAGE_WRITE ?
+				  SDL_AndroidGetExternalStoragePath() :
+				  SDL_AndroidGetInternalStoragePath());
 #else
   if (user_game_data_dir == NULL)
     user_game_data_dir = getPath2(getPersonalDataDir(),
@@ -1952,7 +1955,7 @@ static boolean loadSetupFileData(void *setup_file_data, char *filename,
 
   if (!(file = openFile(filename, MODE_READ)))
   {
-    Error(ERR_WARN, "cannot open configuration file '%s'", filename);
+    Error(ERR_DEBUG, "cannot open configuration file '%s'", filename);
 
     return FALSE;
   }
@@ -3681,7 +3684,9 @@ void LoadLevelSetup_LastSeries()
     freeSetupFileHash(level_setup_hash);
   }
   else
-    Error(ERR_WARN, "using default setup values");
+  {
+    Error(ERR_DEBUG, "using default setup values");
+  }
 
   free(filename);
 }
@@ -3849,7 +3854,9 @@ void LoadLevelSetup_SeriesInfo()
     freeSetupFileHash(level_setup_hash);
   }
   else
-    Error(ERR_WARN, "using default setup values");
+  {
+    Error(ERR_DEBUG, "using default setup values");
+  }
 
   free(filename);
 }
diff --git a/src/libgame/system.c b/src/libgame/system.c
index b42c7e9..4d4c448 100644
--- a/src/libgame/system.c
+++ b/src/libgame/system.c
@@ -107,6 +107,21 @@ void InitScoresInfo()
   program.global_scores = directoryExists(global_scores_dir);
   program.many_scores_per_name = !program.global_scores;
 
+  if (options.debug)
+  {
+    if (program.global_scores)
+    {
+      Error(ERR_DEBUG, "Using global, multi-user scores directory '%s'.",
+	    global_scores_dir);
+      Error(ERR_DEBUG, "Remove to enable single-user scores directory.");
+      Error(ERR_DEBUG, "(This enables multipe score entries per user.)");
+    }
+    else
+    {
+      Error(ERR_DEBUG, "Using private, single-user scores directory.");
+    }
+  }
+
   free(global_scores_dir);
 }
 
@@ -285,7 +300,18 @@ void InitGfxOtherSettings()
 
 void InitOverlayInfo()
 {
+  overlay.enabled = FALSE;
   overlay.active = FALSE;
+
+#if defined(PLATFORM_ANDROID)
+  if (strEqual(setup.touch.control_type, TOUCH_CONTROL_VIRTUAL_BUTTONS))
+    overlay.enabled = TRUE;
+#endif
+}
+
+void SetOverlayEnabled(boolean enabled)
+{
+  overlay.enabled = enabled;
 }
 
 void SetOverlayActive(boolean active)
@@ -1605,7 +1631,7 @@ void InitJoysticks()
   /* always start with reliable default values */
   joystick.status = JOYSTICK_NOT_AVAILABLE;
   for (i = 0; i < MAX_PLAYERS; i++)
-    joystick.fd[i] = -1;		/* joystick device closed */
+    joystick.nr[i] = -1;		/* no joystick configured */
 
   SDLInitJoysticks();
 }
@@ -1614,3 +1640,13 @@ boolean ReadJoystick(int nr, int *x, int *y, boolean *b1, boolean *b2)
 {
   return SDLReadJoystick(nr, x, y, b1, b2);
 }
+
+boolean CheckJoystickOpened(int nr)
+{
+  return SDLCheckJoystickOpened(nr);
+}
+
+void ClearJoystickState()
+{
+  SDLClearJoystickState();
+}
diff --git a/src/libgame/system.h b/src/libgame/system.h
index 4a54de8..2f6c280 100644
--- a/src/libgame/system.h
+++ b/src/libgame/system.h
@@ -324,6 +324,19 @@
 
 #define STYLE_DEFAULT		STYLE_NONE
 
+/* values for special global animation events */
+#define ANIM_EVENT_NONE		0
+#define ANIM_EVENT_SELF		(1 << 16)
+#define ANIM_EVENT_ANY		(1 << 17)
+
+#define ANIM_EVENT_ANIM_BIT	0
+#define ANIM_EVENT_PART_BIT	8
+
+#define ANIM_EVENT_ANIM_MASK	(0xff << ANIM_EVENT_ANIM_BIT)
+#define ANIM_EVENT_PART_MASK	(0xff << ANIM_EVENT_PART_BIT)
+
+#define ANIM_EVENT_DEFAULT	ANIM_EVENT_NONE
+
 /* values for fade mode */
 #define FADE_TYPE_NONE		0
 #define FADE_TYPE_FADE_IN	(1 << 0)
@@ -357,6 +370,7 @@
 #define POS_LOWER		5
 #define POS_BOTTOM		6
 #define POS_ANY			7
+#define POS_LAST		8
 
 /* values for text alignment */
 #define ALIGN_LEFT		(1 << 0)
@@ -428,6 +442,10 @@
 /* maximum number of levels in a level set */
 #define MAX_LEVELS		1000
 
+/* maximum number of global animation and parts */
+#define MAX_GLOBAL_ANIMS		32
+#define MAX_GLOBAL_ANIM_PARTS		32
+
 /* default name for empty highscore entry */
 #define EMPTY_PLAYER_NAME	"no name"
 
@@ -480,6 +498,7 @@
 #define SCORES_DIRECTORY	"scores"
 #define DOCS_DIRECTORY		"docs"
 #define CACHE_DIRECTORY		"cache"
+#define CONF_DIRECTORY		"conf"
 
 #define GFX_CLASSIC_SUBDIR	"gfx_classic"
 #define SND_CLASSIC_SUBDIR	"snd_classic"
@@ -513,6 +532,8 @@
 #define TAPEFILE_EXTENSION	"tape"
 #define SCOREFILE_EXTENSION	"score"
 
+#define GAMECONTROLLER_BASENAME	"gamecontrollerdb.txt"
+
 #define LOG_OUT_BASENAME	"stdout.txt"
 #define LOG_ERR_BASENAME	"stderr.txt"
 
@@ -780,6 +801,7 @@ struct OptionInfo
   char *sounds_directory;
   char *music_directory;
   char *docs_directory;
+  char *conf_directory;
 
   char *execute_command;
 
@@ -921,13 +943,14 @@ struct GfxInfo
 
 struct OverlayInfo
 {
-  boolean active;
+  boolean enabled;		/* overlay generally enabled or disabled */
+  boolean active;		/* overlay activated (depending on game mode) */
 };
 
 struct JoystickInfo
 {
   int status;
-  int fd[MAX_PLAYERS];		/* file descriptor of player's joystick */
+  int nr[MAX_PLAYERS];		/* joystick number for each player */
 };
 
 struct SetupJoystickInfo
@@ -1449,6 +1472,7 @@ void InitGfxDrawGlobalBorderFunction(void (*draw_global_border_function)(int));
 void InitGfxCustomArtworkInfo();
 void InitGfxOtherSettings();
 void InitOverlayInfo();
+void SetOverlayEnabled(boolean);
 void SetOverlayActive(boolean);
 boolean GetOverlayActive();
 void SetDrawDeactivationMask(int);
@@ -1526,5 +1550,7 @@ boolean CheckCloseWindowEvent(ClientMessageEvent *);
 
 void InitJoysticks();
 boolean ReadJoystick(int, int *, int *, boolean *, boolean *);
+boolean CheckJoystickOpened(int);
+void ClearJoystickState();
 
 #endif /* SYSTEM_H */
diff --git a/src/main.c b/src/main.c
index 141a00a..690296d 100644
--- a/src/main.c
+++ b/src/main.c
@@ -5454,6 +5454,30 @@ struct ElementActionInfo element_action_info[NUM_ACTIONS + 1 + 1] =
   { ".part_6",			ACTION_PART_6,			FALSE	},
   { ".part_7",			ACTION_PART_7,			FALSE	},
   { ".part_8",			ACTION_PART_8,			FALSE	},
+  { ".part_9",			ACTION_PART_9,			FALSE	},
+  { ".part_10",			ACTION_PART_10,			FALSE	},
+  { ".part_11",			ACTION_PART_11,			FALSE	},
+  { ".part_12",			ACTION_PART_12,			FALSE	},
+  { ".part_13",			ACTION_PART_13,			FALSE	},
+  { ".part_14",			ACTION_PART_14,			FALSE	},
+  { ".part_15",			ACTION_PART_15,			FALSE	},
+  { ".part_16",			ACTION_PART_16,			FALSE	},
+  { ".part_17",			ACTION_PART_17,			FALSE	},
+  { ".part_18",			ACTION_PART_18,			FALSE	},
+  { ".part_19",			ACTION_PART_19,			FALSE	},
+  { ".part_20",			ACTION_PART_20,			FALSE	},
+  { ".part_21",			ACTION_PART_21,			FALSE	},
+  { ".part_22",			ACTION_PART_22,			FALSE	},
+  { ".part_23",			ACTION_PART_23,			FALSE	},
+  { ".part_24",			ACTION_PART_24,			FALSE	},
+  { ".part_25",			ACTION_PART_25,			FALSE	},
+  { ".part_26",			ACTION_PART_26,			FALSE	},
+  { ".part_27",			ACTION_PART_27,			FALSE	},
+  { ".part_28",			ACTION_PART_28,			FALSE	},
+  { ".part_29",			ACTION_PART_29,			FALSE	},
+  { ".part_30",			ACTION_PART_30,			FALSE	},
+  { ".part_31",			ACTION_PART_31,			FALSE	},
+  { ".part_32",			ACTION_PART_32,			FALSE	},
   { ".other",			ACTION_OTHER,			FALSE	},
 
   /* empty suffix always matches -- check as last entry in InitSoundInfo() */
@@ -5510,6 +5534,8 @@ struct SpecialSuffixInfo special_suffix_info[NUM_SPECIAL_GFX_ARGS + 1 + 1] =
   { ".SUBMENU",			GFX_SPECIAL_ARG_SUBMENU,		},
   { ".MENU",			GFX_SPECIAL_ARG_MENU,			},
   { ".TOONS",			GFX_SPECIAL_ARG_TOONS,			},
+  { ".SCORESOLD",		GFX_SPECIAL_ARG_SCORESOLD,		},
+  { ".SCORESNEW",		GFX_SPECIAL_ARG_SCORESNEW,		},
   { ".FADING",			GFX_SPECIAL_ARG_FADING,			},
   { ".QUIT",			GFX_SPECIAL_ARG_QUIT,			},
 
@@ -5577,7 +5603,10 @@ struct FontInfo font_info[NUM_FONTS + 1] =
   { NULL			}
 };
 
-struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
+struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1];
+
+/* this contains predefined structure elements to init "global_anim_info" */
+struct GlobalAnimNameInfo global_anim_name_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
 {
   /* (real) graphic definitions used to define animation graphics */
   { "gfx.global.anim_1",	},
@@ -5588,6 +5617,30 @@ struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
   { "gfx.global.anim_6",	},
   { "gfx.global.anim_7",	},
   { "gfx.global.anim_8",	},
+  { "gfx.global.anim_9",	},
+  { "gfx.global.anim_10",	},
+  { "gfx.global.anim_11",	},
+  { "gfx.global.anim_12",	},
+  { "gfx.global.anim_13",	},
+  { "gfx.global.anim_14",	},
+  { "gfx.global.anim_15",	},
+  { "gfx.global.anim_16",	},
+  { "gfx.global.anim_17",	},
+  { "gfx.global.anim_18",	},
+  { "gfx.global.anim_19",	},
+  { "gfx.global.anim_20",	},
+  { "gfx.global.anim_21",	},
+  { "gfx.global.anim_22",	},
+  { "gfx.global.anim_23",	},
+  { "gfx.global.anim_24",	},
+  { "gfx.global.anim_25",	},
+  { "gfx.global.anim_26",	},
+  { "gfx.global.anim_27",	},
+  { "gfx.global.anim_28",	},
+  { "gfx.global.anim_29",	},
+  { "gfx.global.anim_30",	},
+  { "gfx.global.anim_31",	},
+  { "gfx.global.anim_32",	},
 
   /* (dummy) graphic definitions used to define animation controls */
   { "global.anim_1",		},
@@ -5598,6 +5651,30 @@ struct GlobalAnimInfo global_anim_info[NUM_GLOBAL_ANIM_TOKENS + 1] =
   { "global.anim_6",		},
   { "global.anim_7",		},
   { "global.anim_8",		},
+  { "global.anim_9",		},
+  { "global.anim_10",		},
+  { "global.anim_11",		},
+  { "global.anim_12",		},
+  { "global.anim_13",		},
+  { "global.anim_14",		},
+  { "global.anim_15",		},
+  { "global.anim_16",		},
+  { "global.anim_17",		},
+  { "global.anim_18",		},
+  { "global.anim_19",		},
+  { "global.anim_20",		},
+  { "global.anim_21",		},
+  { "global.anim_22",		},
+  { "global.anim_23",		},
+  { "global.anim_24",		},
+  { "global.anim_25",		},
+  { "global.anim_26",		},
+  { "global.anim_27",		},
+  { "global.anim_28",		},
+  { "global.anim_29",		},
+  { "global.anim_30",		},
+  { "global.anim_31",		},
+  { "global.anim_32",		},
 
   { NULL			}
 };
diff --git a/src/main.h b/src/main.h
index 12c911b..90d6e88 100644
--- a/src/main.h
+++ b/src/main.h
@@ -1773,9 +1773,33 @@
 #define ACTION_PART_6			89
 #define ACTION_PART_7			90
 #define ACTION_PART_8			91
-#define ACTION_OTHER			92
-
-#define NUM_ACTIONS			93
+#define ACTION_PART_9			92
+#define ACTION_PART_10			93
+#define ACTION_PART_11			94
+#define ACTION_PART_12			95
+#define ACTION_PART_13			96
+#define ACTION_PART_14			97
+#define ACTION_PART_15			98
+#define ACTION_PART_16			99
+#define ACTION_PART_17			100
+#define ACTION_PART_18			101
+#define ACTION_PART_19			102
+#define ACTION_PART_20			103
+#define ACTION_PART_21			104
+#define ACTION_PART_22			105
+#define ACTION_PART_23			106
+#define ACTION_PART_24			107
+#define ACTION_PART_25			108
+#define ACTION_PART_26			109
+#define ACTION_PART_27			110
+#define ACTION_PART_28			111
+#define ACTION_PART_29			112
+#define ACTION_PART_30			113
+#define ACTION_PART_31			114
+#define ACTION_PART_32			115
+#define ACTION_OTHER			116
+
+#define NUM_ACTIONS			117
 
 #define ACTION_BORING_LAST		ACTION_BORING_10
 #define ACTION_SLEEPING_LAST		ACTION_SLEEPING_3
@@ -1814,10 +1838,12 @@
 #define GFX_SPECIAL_ARG_SUBMENU		29
 #define GFX_SPECIAL_ARG_MENU		30
 #define GFX_SPECIAL_ARG_TOONS		31
-#define GFX_SPECIAL_ARG_FADING		32
-#define GFX_SPECIAL_ARG_QUIT		33
+#define GFX_SPECIAL_ARG_SCORESOLD	32
+#define GFX_SPECIAL_ARG_SCORESNEW	33
+#define GFX_SPECIAL_ARG_FADING		34
+#define GFX_SPECIAL_ARG_QUIT		35
 
-#define NUM_SPECIAL_GFX_ARGS		34
+#define NUM_SPECIAL_GFX_ARGS		36
 
 /* these additional definitions are currently only used for draw offsets */
 #define GFX_SPECIAL_ARG_INFO_MAIN	0
@@ -1896,25 +1922,27 @@
 #define GFX_ARG_ANIM_DELAY_RANDOM	38
 #define GFX_ARG_POST_DELAY_FIXED	39
 #define GFX_ARG_POST_DELAY_RANDOM	40
-#define GFX_ARG_NAME			41
-#define GFX_ARG_SCALE_UP_FACTOR		42
-#define GFX_ARG_TILE_SIZE		43
-#define GFX_ARG_CLONE_FROM		44
-#define GFX_ARG_FADE_MODE		45
-#define GFX_ARG_FADE_DELAY		46
-#define GFX_ARG_POST_DELAY		47
-#define GFX_ARG_AUTO_DELAY		48
-#define GFX_ARG_ALIGN			49
-#define GFX_ARG_VALIGN			50
-#define GFX_ARG_SORT_PRIORITY		51
-#define GFX_ARG_CLASS			52
-#define GFX_ARG_STYLE			53
-#define GFX_ARG_ACTIVE_XOFFSET		54
-#define GFX_ARG_ACTIVE_YOFFSET		55
-#define GFX_ARG_PRESSED_XOFFSET		56
-#define GFX_ARG_PRESSED_YOFFSET		57
-
-#define NUM_GFX_ARGS			58
+#define GFX_ARG_INIT_EVENT		41
+#define GFX_ARG_ANIM_EVENT		42
+#define GFX_ARG_NAME			43
+#define GFX_ARG_SCALE_UP_FACTOR		44
+#define GFX_ARG_TILE_SIZE		45
+#define GFX_ARG_CLONE_FROM		46
+#define GFX_ARG_FADE_MODE		47
+#define GFX_ARG_FADE_DELAY		48
+#define GFX_ARG_POST_DELAY		49
+#define GFX_ARG_AUTO_DELAY		50
+#define GFX_ARG_ALIGN			51
+#define GFX_ARG_VALIGN			52
+#define GFX_ARG_SORT_PRIORITY		53
+#define GFX_ARG_CLASS			54
+#define GFX_ARG_STYLE			55
+#define GFX_ARG_ACTIVE_XOFFSET		56
+#define GFX_ARG_ACTIVE_YOFFSET		57
+#define GFX_ARG_PRESSED_XOFFSET		58
+#define GFX_ARG_PRESSED_YOFFSET		59
+
+#define NUM_GFX_ARGS			60
 
 
 /* values for sound configuration suffixes */
@@ -1981,19 +2009,19 @@
 #define MAX_NUM_TOONS			20
 
 /* values for global animation configuration (must match those from main.c) */
-#define NUM_GLOBAL_ANIMS		8
-#define NUM_GLOBAL_ANIM_PARTS		8
+#define NUM_GLOBAL_ANIMS		MAX_GLOBAL_ANIMS
+#define NUM_GLOBAL_ANIM_PARTS		MAX_GLOBAL_ANIM_PARTS
 #define NUM_GLOBAL_ANIM_PARTS_ALL	(NUM_GLOBAL_ANIM_PARTS + 1)
 #define NUM_GLOBAL_ANIM_TOKENS		(2 * NUM_GLOBAL_ANIMS)
 
 #define GLOBAL_ANIM_ID_GRAPHIC_FIRST	0
-#define GLOBAL_ANIM_ID_GRAPHIC_LAST	7
-#define GLOBAL_ANIM_ID_CONTROL_FIRST	(NUM_GLOBAL_ANIMS + 0)
-#define GLOBAL_ANIM_ID_CONTROL_LAST	(NUM_GLOBAL_ANIMS + 7)
+#define GLOBAL_ANIM_ID_GRAPHIC_LAST	(NUM_GLOBAL_ANIMS - 1)
+#define GLOBAL_ANIM_ID_CONTROL_FIRST	(NUM_GLOBAL_ANIMS)
+#define GLOBAL_ANIM_ID_CONTROL_LAST	(2 * NUM_GLOBAL_ANIMS - 1)
 
 #define GLOBAL_ANIM_ID_PART_FIRST	0
-#define GLOBAL_ANIM_ID_PART_LAST	7
-#define GLOBAL_ANIM_ID_PART_BASE	8
+#define GLOBAL_ANIM_ID_PART_LAST	(NUM_GLOBAL_ANIM_PARTS - 1)
+#define GLOBAL_ANIM_ID_PART_BASE	(NUM_GLOBAL_ANIM_PARTS)
 
 /* values for global border graphics */
 #define IMG_GLOBAL_BORDER_FIRST		IMG_GLOBAL_BORDER
@@ -2032,10 +2060,12 @@
 #define GAME_MODE_PSEUDO_SUBMENU	29
 #define GAME_MODE_PSEUDO_MENU		30
 #define GAME_MODE_PSEUDO_TOONS		31
-#define GAME_MODE_PSEUDO_FADING		32
-#define GAME_MODE_QUIT			33
+#define GAME_MODE_PSEUDO_SCORESOLD	32
+#define GAME_MODE_PSEUDO_SCORESNEW	33
+#define GAME_MODE_PSEUDO_FADING		34
+#define GAME_MODE_QUIT			35
 
-#define NUM_GAME_MODES			34
+#define NUM_GAME_MODES			36
 
 /* special definitions currently only used for custom artwork configuration */
 #define MUSIC_PREFIX_BACKGROUND		0
@@ -2049,8 +2079,8 @@
 /* program information and versioning definitions */
 #define PROGRAM_VERSION_MAJOR		4
 #define PROGRAM_VERSION_MINOR		0
-#define PROGRAM_VERSION_PATCH		0
-#define PROGRAM_VERSION_BUILD		2
+#define PROGRAM_VERSION_PATCH		1
+#define PROGRAM_VERSION_BUILD		0
 #define PROGRAM_VERSION_EXTRA		""
 
 #define PROGRAM_TITLE_STRING		"Rocks'n'Diamonds"
@@ -2829,6 +2859,11 @@ struct FontInfo
   				/* internal bitmap ID for special graphics */
 };
 
+struct GlobalAnimNameInfo
+{
+  char *token_name;		/* global animation token in config files */
+};
+
 struct GlobalAnimInfo
 {
   char *token_name;		/* global animation token in config files */
@@ -2883,6 +2918,9 @@ struct GraphicInfo
   int post_delay_fixed;		/* optional delay values after bored/global */
   int post_delay_random;	/* animations (pause before next animation) */
 
+  int init_event;		/* optional event triggering animation start */
+  int anim_event;		/* optional event triggering animation end   */
+
   int step_offset;		/* optional step offset of toon animations */
   int step_xoffset;		/* optional step offset of toon animations */
   int step_yoffset;		/* optional step offset of toon animations */
@@ -3130,6 +3168,7 @@ extern struct SpecialSuffixInfo special_suffix_info[];
 extern struct TokenIntPtrInfo	image_config_vars[];
 extern struct FontInfo		font_info[];
 extern struct GlobalAnimInfo	global_anim_info[];
+extern struct GlobalAnimNameInfo global_anim_name_info[];
 extern struct MusicPrefixInfo	music_prefix_info[];
 extern struct GraphicInfo      *graphic_info;
 extern struct SoundInfo	       *sound_info;
diff --git a/src/screens.c b/src/screens.c
index 0f47d87..ce99012 100644
--- a/src/screens.c
+++ b/src/screens.c
@@ -23,6 +23,10 @@
 #include "init.h"
 #include "config.h"
 
+
+#define DEBUG_JOYSTICKS		0
+
+
 /* screens on the info screen */
 #define INFO_MODE_MAIN			0
 #define INFO_MODE_TITLE			1
@@ -163,7 +167,7 @@ static void HandleScreenGadgets(struct GadgetInfo *);
 static void HandleSetupScreen_Generic(int, int, int, int, int);
 static void HandleSetupScreen_Input(int, int, int, int, int);
 static void CustomizeKeyboard(int);
-static void CalibrateJoystick(int);
+static void ConfigureJoystick(int);
 static void execSetupGame(void);
 static void execSetupGraphics(void);
 static void execSetupSound(void);
@@ -1413,7 +1417,6 @@ void DrawMainMenu()
   ExpireSoundLoops(FALSE);
 
   KeyboardAutoRepeatOn();
-  ActivateJoystick();
 
   audio.sound_deactivated = FALSE;
 
@@ -4146,9 +4149,9 @@ void DrawChooseLevelNr()
 		 LevelStats_getSolved(i) ? FC_GREEN :
 		 LevelStats_getPlayed(i) ? FC_YELLOW : FC_RED);
 
-    sprintf(identifier, "%d", value);
-    sprintf(name, "%03d: %s", value,
-	    (level.no_level_file ? "(no file)" : level.name));
+    snprintf(identifier, sizeof(identifier), "%d", value);
+    snprintf(name, sizeof(name), "%03d: %s", value,
+	     (level.no_level_file ? "(no file)" : level.name));
 
     setString(&ti->identifier, identifier);
     setString(&ti->name, name);
@@ -4190,7 +4193,6 @@ void DrawHallOfFame(int highlight_position)
 
   /* (this is needed when called from GameEnd() after winning a game) */
   KeyboardAutoRepeatOn();
-  ActivateJoystick();
 
   /* (this is needed when called from GameEnd() after winning a game) */
   SetDrawDeactivationMask(REDRAW_NONE);
@@ -4198,6 +4200,8 @@ void DrawHallOfFame(int highlight_position)
 
   if (highlight_position < 0) 
     LoadScore(level_nr);
+  else
+    SetAnimStatus(GAME_MODE_PSEUDO_SCORESNEW);
 
   FadeSetEnterScreen();
 
@@ -5237,14 +5241,12 @@ static void execSetupChooseMusic()
   DrawSetupScreen();
 }
 
-#if !defined(PLATFORM_ANDROID)
 static void execSetupInput()
 {
   setup_mode = SETUP_MODE_INPUT;
 
   DrawSetupScreen();
 }
-#endif
 
 static void execSetupShortcuts()
 {
@@ -5308,12 +5310,8 @@ static struct TokenInfo setup_info_main[] =
   { TYPE_ENTER_MENU,	execSetupGraphics,	"Graphics"		},
   { TYPE_ENTER_MENU,	execSetupSound,		"Sound & Music"		},
   { TYPE_ENTER_MENU,	execSetupArtwork,	"Custom Artwork"	},
-#if !defined(PLATFORM_ANDROID)
   { TYPE_ENTER_MENU,	execSetupInput,		"Input Devices"		},
   { TYPE_ENTER_MENU,	execSetupTouch,		"Touch Controls"	},
-#else
-  { TYPE_ENTER_MENU,	execSetupTouch,		"Touch Controls"	},
-#endif
   { TYPE_ENTER_MENU,	execSetupShortcuts,	"Key Shortcuts"		},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_LEAVE_MENU,	execExitSetup, 		"Exit"			},
@@ -5449,7 +5447,7 @@ static struct TokenInfo setup_info_input[] =
 {
   { TYPE_SWITCH,	NULL,			"Player:"		},
   { TYPE_SWITCH,	NULL,			"Device:"		},
-  { TYPE_ENTER_MENU,	NULL,			""			},
+  { TYPE_SWITCH,	NULL,			""			},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_EMPTY,		NULL,			""			},
   { TYPE_EMPTY,		NULL,			""			},
@@ -5954,9 +5952,6 @@ void DrawSetupScreen_Input()
 
   DrawTextSCentered(mSY - SY + 16, FONT_TITLE_1, "Setup Input");
 
-  DrawTextSCentered(SYSIZE - 20, FONT_TITLE_2,
-		    "Joysticks deactivated on this screen");
-
   for (i = 0; setup_info[i].type != 0 && i < MAX_MENU_ENTRIES_ON_SCREEN; i++)
   {
     if (setup_info[i].type & (TYPE_ENTER_MENU|TYPE_ENTER_LIST))
@@ -6012,12 +6007,12 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
     char *text;
   } custom[] =
   {
-    { &custom_key.left,  "Joystick Left"  },
-    { &custom_key.right, "Joystick Right" },
-    { &custom_key.up,    "Joystick Up"    },
-    { &custom_key.down,  "Joystick Down"  },
-    { &custom_key.snap,  "Button 1"       },
-    { &custom_key.drop,  "Button 2"       }
+    { &custom_key.left,  "Axis/Pad Left"  },
+    { &custom_key.right, "Axis/Pad Right" },
+    { &custom_key.up,    "Axis/Pad Up"    },
+    { &custom_key.down,  "Axis/Pad Down"  },
+    { &custom_key.snap,  "Button 1/A/X"   },
+    { &custom_key.drop,  "Button 2/B/Y"   }
   };
   static char *joystick_name[MAX_PLAYERS] =
   {
@@ -6028,8 +6023,6 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
   };
   int text_font_nr = (active ? FONT_MENU_1_ACTIVE : FONT_MENU_1);
 
-  InitJoysticks();
-
   custom_key = setup.input[player_nr].key;
 
   DrawText(mSX + 11 * 32, mSY + 2 * 32, int2str(player_nr + 1, 1),
@@ -6043,11 +6036,13 @@ static void drawPlayerSetupInputInfo(int player_nr, boolean active)
   if (setup.input[player_nr].use_joystick)
   {
     char *device_name = setup.input[player_nr].joy.device_name;
-    char *text = joystick_name[getJoystickNrFromDeviceName(device_name)];
-    int font_nr = (joystick.fd[player_nr] < 0 ? FONT_VALUE_OLD : FONT_VALUE_1);
+    int joystick_nr = getJoystickNrFromDeviceName(device_name);
+    boolean joystick_active = CheckJoystickOpened(joystick_nr);
+    char *text = joystick_name[joystick_nr];
+    int font_nr = (joystick_active ? FONT_VALUE_1 : FONT_VALUE_OLD);
 
     DrawText(mSX + 8 * 32, mSY + 3 * 32, text, font_nr);
-    DrawText(mSX + 32, mSY + 4 * 32, "Calibrate", text_font_nr);
+    DrawText(mSX + 32, mSY + 4 * 32, "Configure", text_font_nr);
   }
   else
   {
@@ -6140,7 +6135,6 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
     if (dx && choice == 0)
       x = (dx < 0 ? 10 : 12);
     else if ((dx && choice == 1) ||
-	     (dx == +1 && choice == 2) ||
 	     (dx == -1 && choice == pos_end))
       button = MB_MENU_CHOICE;
     else if (dy)
@@ -6199,10 +6193,7 @@ void HandleSetupScreen_Input(int mx, int my, int dx, int dy, int button)
       else if (y == 2)
       {
 	if (setup.input[input_player_nr].use_joystick)
-	{
-	  InitJoysticks();
-	  CalibrateJoystick(input_player_nr);
-	}
+	  ConfigureJoystick(input_player_nr);
 	else
 	  CustomizeKeyboard(input_player_nr);
       }
@@ -6349,7 +6340,8 @@ void CustomizeKeyboard(int player_nr)
   DrawSetupScreen_Input();
 }
 
-static boolean CalibrateJoystickMain(int player_nr)
+#if 0
+static boolean OLD_CalibrateJoystickMain(int player_nr)
 {
   int new_joystick_xleft = JOYSTICK_XMIDDLE;
   int new_joystick_xright = JOYSTICK_XMIDDLE;
@@ -6357,7 +6349,10 @@ static boolean CalibrateJoystickMain(int player_nr)
   int new_joystick_ylower = JOYSTICK_YMIDDLE;
   int new_joystick_xmiddle, new_joystick_ymiddle;
 
-  int joystick_fd = joystick.fd[player_nr];
+  char *device_name = setup.input[player_nr].joy.device_name;
+  int joystick_nr = getJoystickNrFromDeviceName(device_name);
+  boolean joystick_active = CheckJoystickOpened(joystick_nr);
+
   int x, y, last_x, last_y, xpos = 8, ypos = 3;
   boolean check[3][3];
   int check_remaining = 3 * 3;
@@ -6368,7 +6363,7 @@ static boolean CalibrateJoystickMain(int player_nr)
   if (joystick.status == JOYSTICK_NOT_AVAILABLE)
     return FALSE;
 
-  if (joystick_fd < 0 || !setup.input[player_nr].use_joystick)
+  if (!joystick_active || !setup.input[player_nr].use_joystick)
     return FALSE;
 
   FadeSetEnterMenu();
@@ -6393,12 +6388,12 @@ static boolean CalibrateJoystickMain(int player_nr)
   DrawTextSCentered(mSY - SY + 12 * 32, FONT_TITLE_1, "and");
   DrawTextSCentered(mSY - SY + 13 * 32, FONT_TITLE_1, "press any button!");
 
-  joy_value = Joystick(player_nr);
+  joy_value = JoystickExt(joystick_nr, TRUE);
   last_x = (joy_value & JOY_LEFT ? -1 : joy_value & JOY_RIGHT ? +1 : 0);
   last_y = (joy_value & JOY_UP   ? -1 : joy_value & JOY_DOWN  ? +1 : 0);
 
   /* eventually uncalibrated center position (joystick could be uncentered) */
-  if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL))
+  if (!ReadJoystick(joystick_nr, &joy_x, &joy_y, NULL, NULL))
     return FALSE;
 
   new_joystick_xmiddle = joy_x;
@@ -6408,11 +6403,12 @@ static boolean CalibrateJoystickMain(int player_nr)
 
   FadeIn(REDRAW_FIELD);
 
-  while (Joystick(player_nr) & JOY_BUTTON);	/* wait for released button */
+  /* wait for potentially still pressed button to be released */
+  while (JoystickExt(joystick_nr, TRUE) & JOY_BUTTON);
 
   while (result < 0)
   {
-    if (PendingEvent())		/* got event */
+    while (PendingEvent())		/* got event */
     {
       Event event;
 
@@ -6448,7 +6444,7 @@ static boolean CalibrateJoystickMain(int player_nr)
       }
     }
 
-    if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL))
+    if (!ReadJoystick(joystick_nr, &joy_x, &joy_y, NULL, NULL))
       return FALSE;
 
     new_joystick_xleft  = MIN(new_joystick_xleft,  joy_x);
@@ -6465,7 +6461,7 @@ static boolean CalibrateJoystickMain(int player_nr)
 
     CheckJoystickData();
 
-    joy_value = Joystick(player_nr);
+    joy_value = JoystickExt(joystick_nr, TRUE);
 
     if (joy_value & JOY_BUTTON && check_remaining == 0)
       result = 1;
@@ -6494,14 +6490,14 @@ static boolean CalibrateJoystickMain(int player_nr)
   }
 
   /* calibrated center position (joystick should now be centered) */
-  if (!ReadJoystick(joystick_fd, &joy_x, &joy_y, NULL, NULL))
+  if (!ReadJoystick(joystick_nr, &joy_x, &joy_y, NULL, NULL))
     return FALSE;
 
   new_joystick_xmiddle = joy_x;
   new_joystick_ymiddle = joy_y;
 
   /* wait until the last pressed button was released */
-  while (Joystick(player_nr) & JOY_BUTTON)
+  while (JoystickExt(joystick_nr, TRUE) & JOY_BUTTON)
   {
     if (PendingEvent())		/* got event */
     {
@@ -6516,23 +6512,419 @@ static boolean CalibrateJoystickMain(int player_nr)
 
   return TRUE;
 }
+#endif
+
+/* game controller mapping generator by Gabriel Jacobo <gabomdq at gmail.com> */
+
+#define MARKER_BUTTON		1
+#define MARKER_AXIS_X		2
+#define MARKER_AXIS_Y		3
+
+static boolean ConfigureJoystickMapButtonsAndAxes(SDL_Joystick *joystick)
+{
+#if defined(TARGET_SDL2)
+  static boolean bitmaps_initialized = FALSE;
+  boolean screen_initialized = FALSE;
+  static Bitmap *controller, *button, *axis_x, *axis_y;
+  char *name;
+  boolean success = TRUE;
+  boolean done = FALSE, next = FALSE;
+  Event event;
+  int alpha = 200, alpha_step = -1;
+  int alpha_ticks = 0;
+  char mapping[4096], temp[4096];
+  int font_name = FONT_TEXT_1;
+  int font_info = FONT_REQUEST;
+  int ystep1 = getFontHeight(font_name) + 2;
+  int ystep2 = getFontHeight(font_info) + 2;
+  int i, j;
+
+  struct
+  {
+    int x, y;
+    int marker;
+    char *field;
+    int axis, button, hat, hat_value;
+    char mapping[4096];
+  }
+  *step, *prev_step, steps[] =
+  {
+    { 356, 155, MARKER_BUTTON, "a",		},
+    { 396, 122, MARKER_BUTTON, "b",		},
+    { 320, 125, MARKER_BUTTON, "x",		},
+    { 358,  95, MARKER_BUTTON, "y",		},
+    { 162, 125, MARKER_BUTTON, "back",		},
+    { 216, 125, MARKER_BUTTON, "guide",		},
+    { 271, 125, MARKER_BUTTON, "start",		},
+    { 110, 200, MARKER_BUTTON, "dpleft",	},
+    { 146, 228, MARKER_BUTTON, "dpdown",	},
+    { 178, 200, MARKER_BUTTON, "dpright",	},
+    { 146, 172, MARKER_BUTTON, "dpup",		},
+    {  50,  40, MARKER_BUTTON, "leftshoulder",	},
+    {  88, -10, MARKER_AXIS_Y, "lefttrigger",	},
+    { 382,  40, MARKER_BUTTON, "rightshoulder",	},
+    { 346, -10, MARKER_AXIS_Y, "righttrigger",	},
+    {  73, 141, MARKER_BUTTON, "leftstick",	},
+    { 282, 210, MARKER_BUTTON, "rightstick",	},
+    {  73, 141, MARKER_AXIS_X, "leftx",		},
+    {  73, 141, MARKER_AXIS_Y, "lefty",		},
+    { 282, 210, MARKER_AXIS_X, "rightx",	},
+    { 282, 210, MARKER_AXIS_Y, "righty",	},
+  };
+
+  unsigned int event_frame_delay = 0;
+  unsigned int event_frame_delay_value = GAME_FRAME_DELAY;
+
+  ResetDelayCounter(&event_frame_delay);
+
+  if (!bitmaps_initialized)
+  {
+    controller = LoadCustomImage("joystick/controller.png");
+    button     = LoadCustomImage("joystick/button.png");
+    axis_x     = LoadCustomImage("joystick/axis_x.png");
+    axis_y     = LoadCustomImage("joystick/axis_y.png");
+
+    bitmaps_initialized = TRUE;
+  }
+
+  name = getFormattedJoystickName(SDL_JoystickName(joystick));
+
+#if DEBUG_JOYSTICKS
+  /* print info about the joystick we are watching */
+  Error(ERR_DEBUG, "watching joystick %d: (%s)\n",
+	SDL_JoystickInstanceID(joystick), name);
+  Error(ERR_DEBUG, "joystick has %d axes, %d hats, %d balls, and %d buttons\n",
+	SDL_JoystickNumAxes(joystick), SDL_JoystickNumHats(joystick),
+	SDL_JoystickNumBalls(joystick), SDL_JoystickNumButtons(joystick));
+#endif
+
+  /* initialize mapping with GUID and name */
+  SDL_JoystickGetGUIDString(SDL_JoystickGetGUID(joystick), temp, sizeof(temp));
+
+  snprintf(mapping, sizeof(mapping), "%s,%s,platform:%s,",
+	   temp, name, SDL_GetPlatform());
+
+  /* loop through all steps (buttons and axes), getting joystick events */
+  for (i = 0; i < SDL_arraysize(steps) && !done;)
+  {
+    Bitmap *marker = button;	/* initialize with reliable default value */
+
+    step = &steps[i];
+    strcpy(step->mapping, mapping);
+    step->axis = -1;
+    step->button = -1;
+    step->hat = -1;
+    step->hat_value = -1;
+
+    marker = (step->marker == MARKER_BUTTON ? button :
+	      step->marker == MARKER_AXIS_X ? axis_x :
+	      step->marker == MARKER_AXIS_Y ? axis_y : marker);
+
+    next = FALSE;
+
+    while (!done && !next)
+    {
+      alpha += alpha_step * (int)(SDL_GetTicks() - alpha_ticks) / 5;
+      alpha_ticks = SDL_GetTicks();
+
+      if (alpha >= 255)
+      {
+	alpha = 255;
+	alpha_step = -1;
+      }
+      else if (alpha < 128)
+      {
+	alpha = 127;
+	alpha_step = 1;
+      }
+
+      int controller_x = SX + (SXSIZE - controller->width) / 2;
+      int controller_y = SY + ystep2;
+
+      int marker_x = controller_x + step->x;
+      int marker_y = controller_y + step->y;
+
+      int ystart1 = mSY - 2 * SY + controller_y + controller->height;
+      int ystart2 = ystart1 + ystep1 + ystep2;
+
+      ClearField();
+
+      DrawTextSCentered(ystart1, font_name, name);
+
+      DrawTextSCentered(ystart2 + 0 * ystep2, font_info,
+			"Press buttons and move axes on");
+      DrawTextSCentered(ystart2 + 1 * ystep2, font_info,
+			"your controller when indicated.");
+      DrawTextSCentered(ystart2 + 2 * ystep2, font_info,
+			"(Your controller may look different.)");
+
+#if defined(PLATFORM_ANDROID)
+      DrawTextSCentered(ystart2 + 4 * ystep2, font_info,
+			"To correct a mistake,");
+      DrawTextSCentered(ystart2 + 5 * ystep2, font_info,
+			"press the 'back' button.");
+      DrawTextSCentered(ystart2 + 6 * ystep2, font_info,
+			"To skip a button or axis,");
+      DrawTextSCentered(ystart2 + 7 * ystep2, font_info,
+			"press the 'menu' button.");
+#else
+      DrawTextSCentered(ystart2 + 4 * ystep2, font_info,
+			"To correct a mistake,");
+      DrawTextSCentered(ystart2 + 5 * ystep2, font_info,
+			"press the 'backspace' key.");
+      DrawTextSCentered(ystart2 + 6 * ystep2, font_info,
+			"To skip a button or axis,");
+      DrawTextSCentered(ystart2 + 7 * ystep2, font_info,
+			"press the 'return' key.");
+
+      DrawTextSCentered(ystart2 + 8 * ystep2, font_info,
+			"To exit, press the 'escape' key.");
+#endif
+
+      BlitBitmapMasked(controller, drawto, 0, 0,
+		       controller->width, controller->height,
+		       controller_x, controller_y);
+
+      SDL_SetSurfaceAlphaMod(marker->surface_masked, alpha);
+
+      BlitBitmapMasked(marker, drawto, 0, 0,
+		       marker->width, marker->height,
+		       marker_x, marker_y);
+
+      if (!screen_initialized)
+	FadeIn(REDRAW_FIELD);
+      else
+	BackToFront();
+
+      screen_initialized = TRUE;
+
+      while (NextValidEvent(&event))
+      {
+	switch (event.type)
+	{
+	  case SDL_JOYAXISMOTION:
+	    if (event.jaxis.value > 20000 ||
+		event.jaxis.value < -20000)
+	    {
+	      for (j = 0; j < i; j++)
+		if (steps[j].axis == event.jaxis.axis)
+		  break;
+
+	      if (j == i)
+	      {
+		if (step->marker != MARKER_AXIS_X &&
+		    step->marker != MARKER_AXIS_Y)
+		  break;
+
+		step->axis = event.jaxis.axis;
+		strcat(mapping, step->field);
+		snprintf(temp, sizeof(temp), ":a%u,", event.jaxis.axis);
+		strcat(mapping, temp);
+		i++;
+		next = TRUE;
+	      }
+	    }
+
+	    break;
+
+	  case SDL_JOYHATMOTION:
+	    /* ignore centering; we're probably just coming back
+	       to the center from the previous item we set */
+	    if (event.jhat.value == SDL_HAT_CENTERED)
+	      break;
+
+	    for (j = 0; j < i; j++)
+	      if (steps[j].hat == event.jhat.hat &&
+		  steps[j].hat_value == event.jhat.value)
+		break;
+
+	    if (j == i)
+	    {
+	      step->hat = event.jhat.hat;
+	      step->hat_value = event.jhat.value;
+	      strcat(mapping, step->field);
+	      snprintf(temp, sizeof(temp), ":h%u.%u,",
+		       event.jhat.hat, event.jhat.value );
+	      strcat(mapping, temp);
+	      i++;
+	      next = TRUE;
+	    }
+
+	    break;
+
+	  case SDL_JOYBALLMOTION:
+	    break;
+
+	  case SDL_JOYBUTTONUP:
+	    for (j = 0; j < i; j++)
+	      if (steps[j].button == event.jbutton.button)
+		break;
+
+	    if (j == i)
+	    {
+	      step->button = event.jbutton.button;
+	      strcat(mapping, step->field);
+	      snprintf(temp, sizeof(temp), ":b%u,", event.jbutton.button);
+	      strcat(mapping, temp);
+	      i++;
+	      next = TRUE;
+	    }
+
+	    break;
+
+	  case SDL_FINGERDOWN:
+	  case SDL_MOUSEBUTTONDOWN:
+	    /* skip this step */
+	    i++;
+	    next = TRUE;
+
+	    break;
+
+	  case SDL_KEYDOWN:
+	    if (event.key.keysym.sym == KSYM_BackSpace ||
+		event.key.keysym.sym == KSYM_Back)
+	    {
+	      if (i == 0)
+	      {
+		/* leave screen */
+		success = FALSE;
+		done = TRUE;
+	      }
+
+	      /* undo this step */
+	      prev_step = &steps[i - 1];
+	      strcpy(mapping, prev_step->mapping);
+	      i--;
+	      next = TRUE;
+
+	      break;
+	    }
+
+	    if (event.key.keysym.sym == KSYM_space ||
+		event.key.keysym.sym == KSYM_Return ||
+		event.key.keysym.sym == KSYM_Menu)
+	    {
+	      /* skip this step */
+	      i++;
+	      next = TRUE;
+
+	      break;
+	    }
+
+	    if (event.key.keysym.sym == KSYM_Escape)
+	    {
+	      /* leave screen */
+	      success = FALSE;
+	      done = TRUE;
+	    }
+
+	    break;
+
+	  case SDL_QUIT:
+	    program.exit_function(0);
+	    break;
+
+	  default:
+	    break;
+	}
+
+	// do not handle events for longer than standard frame delay period
+	if (DelayReached(&event_frame_delay, event_frame_delay_value))
+	  break;
+      }
+    }
+  }
+
+  if (success)
+  {
+#if DEBUG_JOYSTICKS
+    Error(ERR_DEBUG, "New game controller mapping:\n\n%s\n\n", mapping);
+#endif
+
+    // activate mapping for this game
+    SDL_GameControllerAddMapping(mapping);
+
+    // save mapping to personal mappings
+    SaveSetup_AddGameControllerMapping(mapping);
+  }
+
+  /* wait until the last pending event was removed from event queue */
+  while (NextValidEvent(&event));
+
+  return success;
+#else
+  return TRUE;
+#endif
+}
 
-void CalibrateJoystick(int player_nr)
+static int ConfigureJoystickMain(int player_nr)
 {
-  if (!CalibrateJoystickMain(player_nr))
+  char *device_name = setup.input[player_nr].joy.device_name;
+  int joystick_nr = getJoystickNrFromDeviceName(device_name);
+  boolean joystick_active = CheckJoystickOpened(joystick_nr);
+  int success = FALSE;
+  int i;
+
+  if (joystick.status == JOYSTICK_NOT_AVAILABLE)
+    return JOYSTICK_NOT_AVAILABLE;
+
+  if (!joystick_active || !setup.input[player_nr].use_joystick)
+    return JOYSTICK_NOT_AVAILABLE;
+
+  FadeSetEnterMenu();
+  FadeOut(REDRAW_FIELD);
+
+  // close all joystick devices (potentially opened as game controllers)
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+    SDLCloseJoystick(i);
+
+  // open joystick device as plain joystick to configure as game controller
+  SDL_Joystick *joystick = SDL_JoystickOpen(joystick_nr);
+
+  // as the joystick was successfully opened before, this should not happen
+  if (joystick == NULL)
+    return FALSE;
+
+  // create new game controller mapping (buttons and axes) for joystick device
+  success = ConfigureJoystickMapButtonsAndAxes(joystick);
+
+  // close joystick (and maybe re-open as configured game controller later)
+  SDL_JoystickClose(joystick);
+
+  // re-open all joystick devices (potentially as game controllers)
+  for (i = 0; i < SDL_NumJoysticks(); i++)
+    SDLOpenJoystick(i);
+
+  // clear all joystick input actions for all joystick devices
+  SDLClearJoystickState();
+
+  return (success ? JOYSTICK_CONFIGURED : JOYSTICK_NOT_CONFIGURED);
+}
+
+void ConfigureJoystick(int player_nr)
+{
+  boolean state = ConfigureJoystickMain(player_nr);
+
+  if (state != JOYSTICK_NOT_CONFIGURED)
   {
+    boolean success = (state == JOYSTICK_CONFIGURED);
+    char *message = (success ? " IS CONFIGURED! " : " NOT AVAILABLE! ");
     char *device_name = setup.input[player_nr].joy.device_name;
     int nr = getJoystickNrFromDeviceName(device_name) + 1;
     int xpos = mSX - SX;
     int ypos = mSY - SY;
+    unsigned int wait_frame_delay = 0;
+    unsigned int wait_frame_delay_value = 2000;
+
+    ResetDelayCounter(&wait_frame_delay);
 
     ClearField();
 
     DrawTextF(xpos + 16, ypos + 6 * 32, FONT_TITLE_1, "   JOYSTICK %d   ", nr);
-    DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, " NOT AVAILABLE! ");
-    BackToFront();
+    DrawTextF(xpos + 16, ypos + 7 * 32, FONT_TITLE_1, message);
 
-    Delay(2000);		/* show error message for a short time */
+    while (!DelayReached(&wait_frame_delay, wait_frame_delay_value))
+      BackToFront();
 
     ClearEventQueue();
   }
@@ -6542,8 +6934,6 @@ void CalibrateJoystick(int player_nr)
 
 void DrawSetupScreen()
 {
-  DeactivateJoystick();
-
   if (setup_mode == SETUP_MODE_INPUT)
     DrawSetupScreen_Input();
   else if (setup_mode == SETUP_MODE_CHOOSE_GAME_SPEED)
diff --git a/src/tape.c b/src/tape.c
index f0a8f02..a8ac4ce 100644
--- a/src/tape.c
+++ b/src/tape.c
@@ -376,15 +376,18 @@ void DrawVideoDisplayCurrentState()
   {
     state |= VIDEO_STATE_PLAY_ON;
 
-    if (tape.deactivate_display)
-      state |= VIDEO_STATE_WARP2_ON;
-    else if (tape.warp_forward)
-      state |= VIDEO_STATE_WARP_ON;
-    else if (tape.fast_forward)
-      state |= VIDEO_STATE_FFWD_ON;
-
-    if (tape.pause_before_end)
-      state |= VIDEO_STATE_PBEND_ON;
+    if (!tape.pausing)
+    {
+      if (tape.deactivate_display)
+	state |= VIDEO_STATE_WARP2_ON;
+      else if (tape.warp_forward)
+	state |= VIDEO_STATE_WARP_ON;
+      else if (tape.fast_forward)
+	state |= VIDEO_STATE_FFWD_ON;
+
+      if (tape.pause_before_end)
+	state |= VIDEO_STATE_PBEND_ON;
+    }
   }
 
   // draw labels and symbols separately to prevent labels overlapping symbols
diff --git a/src/tools.c b/src/tools.c
index 6c990cb..d15f800 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -3759,6 +3759,10 @@ void WaitForEventToContinue()
       {
 	case EVENT_BUTTONPRESS:
 	case EVENT_KEYPRESS:
+#if defined(TARGET_SDL2)
+        case SDL_CONTROLLERBUTTONDOWN:
+#endif
+        case SDL_JOYBUTTONDOWN:
 	  still_wait = FALSE;
 	  break;
 
@@ -3886,6 +3890,19 @@ static int RequestHandleEvents(unsigned int req_state)
 	    break;
 	  }
 
+#if defined(TARGET_SDL2)
+	  case SDL_WINDOWEVENT:
+	    HandleWindowEvent((WindowEvent *) &event);
+	    break;
+
+	  case SDL_APP_WILLENTERBACKGROUND:
+	  case SDL_APP_DIDENTERBACKGROUND:
+	  case SDL_APP_WILLENTERFOREGROUND:
+	  case SDL_APP_DIDENTERFOREGROUND:
+	    HandlePauseResumeEvent((PauseResumeEvent *) &event);
+	    break;
+#endif
+
 	  case EVENT_KEYPRESS:
 	  {
 	    Key key = GetEventKey((KeyEvent *)&event, TRUE);
@@ -3899,7 +3916,11 @@ static int RequestHandleEvents(unsigned int req_state)
 
 	      case KSYM_Return:
 #if defined(TARGET_SDL2)
+	      case KSYM_Select:
 	      case KSYM_Menu:
+#if defined(KSYM_Rewind)
+	      case KSYM_Rewind:		/* for Amazon Fire TV remote */
+#endif
 #endif
 		result = 1;
 		break;
@@ -3907,6 +3928,9 @@ static int RequestHandleEvents(unsigned int req_state)
 	      case KSYM_Escape:
 #if defined(TARGET_SDL2)
 	      case KSYM_Back:
+#if defined(KSYM_FastForward)
+	      case KSYM_FastForward:	/* for Amazon Fire TV remote */
+#endif
 #endif
 		result = 0;
 		break;
@@ -3926,6 +3950,35 @@ static int RequestHandleEvents(unsigned int req_state)
 	    ClearPlayerAction();
 	    break;
 
+#if defined(TARGET_SDL2)
+	  case SDL_CONTROLLERBUTTONDOWN:
+	    switch (event.cbutton.button)
+	    {
+	      case SDL_CONTROLLER_BUTTON_A:
+	      case SDL_CONTROLLER_BUTTON_X:
+	      case SDL_CONTROLLER_BUTTON_LEFTSHOULDER:
+		result = 1;
+		break;
+
+	      case SDL_CONTROLLER_BUTTON_B:
+	      case SDL_CONTROLLER_BUTTON_Y:
+	      case SDL_CONTROLLER_BUTTON_RIGHTSHOULDER:
+	      case SDL_CONTROLLER_BUTTON_BACK:
+		result = 0;
+		break;
+	    }
+
+	    if (req_state & REQ_PLAYER)
+	      result = 0;
+
+	    break;
+
+	  case SDL_CONTROLLERBUTTONUP:
+	    HandleJoystickEvent(&event);
+	    ClearPlayerAction();
+	    break;
+#endif
+
 	  default:
 	    HandleOtherEvents(&event);
 	    break;
@@ -8317,8 +8370,15 @@ void CheckSingleStepMode_EM(byte action[MAX_PLAYERS], int frame,
 void CheckSingleStepMode_SP(boolean murphy_is_waiting,
 			    boolean murphy_is_dropping)
 {
+  boolean murphy_starts_dropping = FALSE;
+  int i;
+
+  for (i = 0; i < MAX_PLAYERS; i++)
+    if (stored_player[i].force_dropping)
+      murphy_starts_dropping = TRUE;
+
   if (tape.single_step && tape.recording && !tape.pausing)
-    if (murphy_is_waiting)
+    if (murphy_is_waiting && !murphy_starts_dropping)
       TapeTogglePause(TAPE_TOGGLE_AUTOMATIC);
 
   CheckSaveEngineSnapshot_SP(murphy_is_waiting, murphy_is_dropping);
@@ -8534,6 +8594,8 @@ void SetAnimStatus(int anim_status_new)
 {
   if (anim_status_new == GAME_MODE_MAIN)
     anim_status_new = GAME_MODE_PSEUDO_MAINONLY;
+  else if (anim_status_new == GAME_MODE_SCORES)
+    anim_status_new = GAME_MODE_PSEUDO_SCORESOLD;
 
   global.anim_status_next = anim_status_new;
 

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/collab-maint/rocksndiamonds.git



More information about the Pkg-games-commits mailing list