[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