83 Commits

Author SHA1 Message Date
04dd66319a actualitzada versió en el makefile 2025-03-25 09:04:40 +01:00
c041c64261 afegit intro03.png 2025-03-19 19:11:00 +01:00
d06617a1b0 mogut el contador de frames a un struct i de paso el shake_effect també l'he encapsulat millor 2025-03-17 21:37:06 +01:00
fbe877960a afegit intro04.png
retocat el timing en la intro
2025-03-16 20:49:18 +01:00
43a1f1a8f6 style: renomenat InputType a InputActions 2025-03-16 18:57:08 +01:00
1b38a5a581 actualitzat gamecontrollerdb.txt a la ultima versió i afegits els mappings de la recre 2025-03-16 17:12:54 +01:00
336c3119ff retocat el timing de la seqüencia final 2025-03-16 13:36:57 +01:00
bfb334bef0 style: eliminats uns fprintf 2025-03-16 13:24:33 +01:00
b3215bf381 retocat gif.cpp 2025-03-16 12:44:38 +01:00
4a07100e2a Arreglat jail_shader.cpp en windows també 2025-03-16 09:55:32 +01:00
e7359a1467 Acabat de repasar jail_shader.cpp 2025-03-16 09:39:24 +01:00
96680dae0f Els shaders ja respeten el escalat sencer 2025-03-16 09:00:19 +01:00
dc7b3bf7e0 Arreglos de disseny en Credits
El shaders ja respeten els SDL_RenderSetLogicalSize en pantalla completa, pero no el SDL_RenderSetIntegerScale
2025-03-16 08:50:35 +01:00
b5dbb694f3 fix: si la finestra no està visible, initShaders no fa be la faena 2025-03-15 20:43:01 +01:00
10997f8850 al fer reset desde Game, en Intro no sona la musica. Bypassejat obligant a recarregar sempre que fas reset 2025-03-15 20:34:26 +01:00
2e9b668426 Afegits mnappings de les palanques de la recre a gamecontrollerdb.txt 2025-03-15 20:04:36 +01:00
c2c55707c3 al acabar la partida i vore els records, torna al titol 2025-03-15 19:53:57 +01:00
a6d115342c fix: amb el audio muted, al acabar la partida el fade per al roido de boles el tornava a deixar activat 2025-03-15 19:33:18 +01:00
44f3f32d67 arreglets al posar el nom 2025-03-15 19:25:39 +01:00
1bb8534db7 c mas masizat gif.cpp 2025-03-15 19:20:04 +01:00
cad2c40024 fix: arreglos de codi 2025-03-15 19:03:12 +01:00
4343cbae69 canvi de pc 2025-03-14 23:04:09 +01:00
3670bad36a Modificades les tecles de funció 2025-03-14 22:01:04 +01:00
919e2b9ca7 Afegides traduccions a les notificacions que faltaven 2025-03-14 21:53:27 +01:00
6c7cfaae59 Pasaeta de IWYU 2025-03-14 21:22:55 +01:00
3ee47ba906 fix: eliminat el reloadTextures() en SDL_WINDOWEVENT_SIZE_CHANGED 2025-03-14 20:33:58 +01:00
ff4e356013 Treballant en la intro 2025-03-14 20:28:04 +01:00
c757886430 Treballant en la intro 2025-03-14 14:06:14 +01:00
f11cb32ac0 Afegida tecla per a canviar el integer scale 2025-03-13 23:07:32 +01:00
9692d01b42 Ja funciona correctament el canvi de tamany de finestra, el shaders, i la pantalla completa 2025-03-13 22:51:51 +01:00
d1db4f253e Treballant en la intro 2025-03-13 20:55:24 +01:00
5a6b96f7ab Treballant en la intro 2025-03-13 14:18:19 +01:00
a3d4b13f3b Treballant en la intro 2025-03-12 14:17:15 +01:00
215ce999c2 Treballan en la Intro 2025-03-12 13:39:48 +01:00
5ccd7eebcd Afegit param.game.speed i retocats els update() de les seccions 2025-03-12 10:06:38 +01:00
90313da3ce fix: una variable no s'havia renombrat correctament als estar en un ifdef 2025-03-11 21:25:04 +01:00
9251d2cf42 Treballan en la intro nova 2025-03-11 21:22:22 +01:00
059a9c863a Tocant coses d'Screen, pero no acaba de funcionar be res 2025-03-11 14:16:02 +01:00
be857cc8c8 Modificat checkInput en varies seccions per a gastar global_inputs.cpp 2025-03-11 09:27:34 +01:00
482dc3de54 Afegit global_events.cpp 2025-03-10 23:24:00 +01:00
9d98d3ea6a Passat gif.c a gif.cpp
Afegit reloadTextures a Resources
2025-03-10 22:38:23 +01:00
9c1b3c45b0 Demana confirmació per a canviar el idioma amb les tecles ràpides
Demana confirmació per reiniciar
2025-03-10 21:22:32 +01:00
79b2917112 Pots pasar quan mostra el nom que has introdiut apretant qualsevol botó de disparar 2025-03-10 20:13:38 +01:00
c88a277cba Si no poses cap nom, tria un nom de jailer al azar 2025-03-10 19:59:21 +01:00
e0c10f83d6 Codi preparat per als dibuixets nous per a la intro 2025-03-09 18:30:14 +01:00
72cb39da78 canvi de pc 2025-03-08 22:23:40 +01:00
9f8d1fbcd7 Eliminat el logo de RetroWeekend per falta de temps i pq era lleig 2025-03-08 20:17:31 +01:00
e523692e99 Els sprites de la intro ja apareixen i desapareixen com en el CC original 2025-03-08 17:47:13 +01:00
83bdd67cee No se perque ha aparegunt un SDL_Destroy(mi_textura) que no es meu i te pinta de que se l'ha inventat el autocompletar de la IA i estava pegant explosions en Linux 2025-03-08 17:27:06 +01:00
66e5105c84 Actualitzat README.md 2025-03-08 17:19:56 +01:00
f8449ea6d1 Afegida politica al fitxer CMakeLists.txt 2025-03-08 10:16:08 +01:00
f43d18e6f0 Arreglos tontos de codi 2025-02-23 09:12:15 +01:00
a42141ebd7 canvi de pc 2025-02-21 19:45:58 +01:00
29c85fecad canvi de pc 2025-02-21 18:26:32 +01:00
04ff428aa0 Treballant en el segon logo 2025-02-07 14:55:34 +01:00
84595da13a EnterName: si has plenat tots els slots de lletres, apretar una volta mes el de fixar lletra fixa el nom 2025-02-07 14:15:18 +01:00
01591175ef Pos pense que ja està tot apanyat lo de EnterName i Scoreboard 2025-02-07 13:45:07 +01:00
29bc4a64fd Afegit position_overflow_ per a EnterName i poder plenar tots els slots de lletres 2025-02-07 12:31:59 +01:00
559210652f Treballant en scoreboard::fillPanelTextures 2025-02-06 20:58:15 +01:00
44e4ca490d canvi de pc
treballant en enter name
2025-02-06 14:59:25 +01:00
3cebee2ae4 Implementat control de repetició per als eixos del joystick 2025-02-06 12:36:16 +01:00
270d7d1848 Duplicada la font 04b_25 per a tindre versió gris i versió negra. La gris es la que es por modular amb colors.
Eliminada la font nokia que ja no s'estava utilitzant.
Optimitzada la càrrega de fonts al permetre reutilitzar fitxers .txt de altres fonts
2025-02-06 10:31:32 +01:00
ccf005dce1 Afegit el disparador per a la aparició del enemic nou 2025-02-06 09:59:58 +01:00
5755947ff7 La tabla de puntuació ja mostra amb altre color la puntuació que s'acaba d'afegir
fix: la tabla de punts no guardava a disc el estat de 1CC de cada entrada
2025-02-05 22:52:19 +01:00
6f594b9a1f La tabla de puntuacions ja mostra aquelles aconseguides amb 1CC 2025-02-05 15:15:48 +01:00
7e2021da70 canvi de pc 2025-02-05 10:17:49 +01:00
0a9a92d4b7 El text de la tabla de puntuacion ja ix centrat i el "diferent" es el que fa 10 2025-02-05 09:45:30 +01:00
b01763b749 Dels credits ja passa a la tabla de puntuacions 2025-01-26 21:15:13 +01:00
59b9f61d69 Font nova per a la intro 2025-01-26 21:05:43 +01:00
b9f194a2b1 Afegit efecte d'eixida a les instruccions 2025-01-26 20:16:43 +01:00
59936f13eb Arreglos estetics i de colorets en hiscore_table.cpp 2025-01-26 17:48:10 +01:00
bad0a10328 Ja es mouen els sprites en hiscore_table.cpp, falta decidir-se per un disseny concret 2025-01-25 22:57:49 +01:00
52a0c2b91f Treballant en la nova tabla de records: ja pinta amb sprites 2025-01-25 21:17:45 +01:00
f12a456017 Alguns arreglos en updateTimeStopped() 2025-01-25 18:51:39 +01:00
f39e65afaf Ja no se que he tocat i qué no, cosetes del malo nou 2025-01-25 18:47:06 +01:00
d3183237df Estandaritzats els noms dels fitxers de audio
Eliminat el soroll de TNT que feia ANYS que no existía
2025-01-25 18:15:49 +01:00
60302004f4 Afegits efectes de audio nous
Retocats alguns efectes de audio al afagar items per a no solapar dos audios
2025-01-25 18:11:24 +01:00
e60938cb19 El malo nou ja suca cosetes, falta ajustar un poc els paràmetres 2025-01-25 17:41:45 +01:00
2b3cc719ba Fix del fix: aaaara si que lleva el garbage de la zona negra. Havia posat el clean() on no tocava 2025-01-25 13:14:25 +01:00
d01c91ebde Fix: m'havia carregat el shakeEffect() de la pantalla quan havia shaders, i de paso he vist que el que tenbia fet shakejava també les notificacions i els menus de debug. Ale, ja està tot arreglaet.
Fix: tampoc estava netejant la pantalla, pensava que no feia falta, pero quan SDL replena de negre la finestra en pantalla completa, havia gorrinades
2025-01-24 20:20:50 +01:00
7130f2298a Merge branch 'main' of https://gitea.sustancia.synology.me/JailDesigner/coffee_crisis_arcade_edition 2025-01-24 10:44:58 +01:00
380cc17861 Fix: ara apaga el sistem al final del tot, almenys quan ja ha escrit la configuració a disc 2025-01-24 10:43:00 +01:00
a5388873e3 Actualizar README.md 2025-01-05 15:47:51 +01:00
119 changed files with 4211 additions and 3264 deletions

View File

@@ -3,6 +3,9 @@
cmake_minimum_required(VERSION 3.10)
project(coffee_crisis_arcade_edition VERSION 0.01)
# Establece las políticas
cmake_policy(SET CMP0072 NEW)
# Configuración de compilador para MinGW en Windows, si es necesario
if(WIN32 AND NOT CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
set(CMAKE_CXX_COMPILER "g++")

View File

@@ -11,7 +11,7 @@ APP_NAME := Coffee Crisis Arcade Edition
RELEASE_FOLDER := ccae_release
RELEASE_FILE := $(RELEASE_FOLDER)/$(TARGET_NAME)
RESOURCE_FILE := release/coffee.res
VERSION := 2025-01-05
VERSION := 2025-03-25
# Nombres para los ficheros de lanzamiento
WINDOWS_RELEASE := $(TARGET_NAME)-$(VERSION)-win32-x64.zip
@@ -166,7 +166,7 @@ linux_release:
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
# Complia
# Compila
$(CXX) $(SOURCES) $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
@@ -178,11 +178,11 @@ linux_release:
$(RMDIR) "$(RELEASE_FOLDER)"
raspi:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
$(CXX) $(SOURCES) -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o $(TARGET_FILE)
strip -s -R .comment -R .gnu.version $(TARGET_FILE) --strip-unneeded
raspi_debug:
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
$(CXX) $(SOURCES) -D VERBOSE -D DEBUG $(CXXFLAGS_DEBUG) $(LDFLAGS) -o "$(TARGET_FILE)_debug"
raspi_release:
# Elimina carpetas previas
@@ -196,8 +196,8 @@ raspi_release:
cp LICENSE "$(RELEASE_FOLDER)"
cp README.md "$(RELEASE_FOLDER)"
# Complia
$(CXX) $(SOURCES) -D ARCADE -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
# Compila
$(CXX) $(SOURCES) -D VERBOSE $(CXXFLAGS) $(LDFLAGS) -o "$(RELEASE_FILE)"
strip -s -R .comment -R .gnu.version "$(RELEASE_FILE)" --strip-unneeded
# Empaqueta ficheros

View File

@@ -11,7 +11,7 @@ Coffee Crisis Arcade Edition és una versió ampliada i millorada del aclamat Co
Defensa el teu cafè contra les bambolles gegants en aquest trepidant joc d'arcade! 🍵
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae_title.png" alt="Títol" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae_title.png" alt="Títol" width="60%" />
</p>
## Controls
@@ -25,25 +25,28 @@ El joc està optimitzat per a ser jugat amb un mando de jocs, encara que un dels
> Nota: El joc suporta nomes un jugador amb teclat.
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae1.png" alt="Joc" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae1.png" alt="Joc" width="45%" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae3.png" alt="Joc" width="45%" />
</p>
## Altres tecles
| Tecla | Funció |
|-------------|----------------------------------------------|
| **ESC** | Tancar el joc |
| **F1** | Fa la finestra més xicoteta |
| **F2** | Fa la finestra més gran |
| Tecla | Funció |
|:-----------:|----------------------------------------------------|
| **ESC** | Tancar el joc |
| **P** | Pausar el joc |
| **F1** | Fa la finestra més xicoteta |
| **F2** | Fa la finestra més gran |
| **F3** | Alterna entre mode de pantalla completa i finestra |
| **F4** | Activa o desactiva els shaders |
| **F5** | Activa o desactiva l'àudio |
| **F6** | Activa o desactiva el dispar automàtic |
| **F7** | Canvia l'idioma del joc i reinicia |
| **F10** | Reset del joc |
| **F4** | Activa o desactiva el filtre de pantalla |
| **F5** | Activa o desactiva el mode d'escalat sencer |
| **F6** | Activa o desactiva l'àudio |
| **F7** | Activa o desactiva el dispar automàtic |
| **F8** | Canvia l'idioma del joc (Provoca el reinici) |
| **F10** | Reinicia el joc |
<p align="center">
<img src="https://php.sustancia.synology.me/images/ccae2.png" alt="Joc" />
<img src="https://php.sustancia.synology.me/images/ccae/ccae2.png" alt="Joc" width="50%" />
</p>
## Com instal·lar i jugar

View File

@@ -1,4 +1,7 @@
# JailDesigner - Custom mappings
### JailDesigner - Custom mappings
# Mandos recreativa CCAE
0300457e790000000600000010010000,DragonRise Inc. Generic USB Joystick,platform:Linux,a:b0,b:b1,x:b2,y:b6,back:b5,leftx:a0,lefty:a1,
# RAP4
030086650d0f00008c000000140100003853140,Generic X-Box 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,
@@ -14,6 +17,7 @@
# Windows
03000000300f00000a01000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
03000000fa190000918d000000000000,3 In 1 Conversion Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b8,x:b3,y:b0,platform:Windows,
03000000fa2d00000100000000000000,3dRudder Foot Motion Controller,leftx:a0,lefty:a1,rightx:a5,righty:a2,platform:Windows,
03000000d0160000040d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
03000000d0160000050d000000000000,4Play Adapter,a:b1,b:b3,back:b4,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,leftstick:b14,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b15,righttrigger:b9,rightx:a3,righty:a4,start:b5,x:b0,y:b2,platform:Windows,
@@ -30,6 +34,7 @@
03000000801000000900000000000000,8BitDo F30 Arcade Stick,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001038000000000000,8BitDo F30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000090000000000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
05000000c82d00006a28000000000000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Windows,
03000000c82d00001251000000000000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001151000000000000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000150000000000000,8BitDo M30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a5,start:b11,x:b4,y:b3,platform:Windows,
@@ -83,6 +88,8 @@
03000000c82d00000260000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00000261000000000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Windows,
03000000c82d00001230000000000000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001b30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001d30000000000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001530000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001630000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000c82d00001730000000000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
@@ -116,6 +123,9 @@
03000000491900001904000000000000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Windows,
03000000710100001904000000000000,Amazon Luna Controller,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b5,leftstick:b8,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b4,rightstick:b7,rightx:a3,righty:a4,start:b6,x:b3,y:b2,platform:Windows,
0300000008100000e501000000000000,Anbernic Game Pad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000020500000913000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000373500000710000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000373500004610000000000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000830500000160000000000000,Arcade,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b3,x:b4,y:b4,platform:Windows,
03000000120c0000100e000000000000,Armor 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
03000000490b00004406000000000000,ASCII Seamic Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
@@ -126,6 +136,7 @@
03000000050b00000679000000000000,ASUS ROG Kunai 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000503200000110000000000000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,start:b3,platform:Windows,
03000000503200000210000000000000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
03000000380800001889000000000000,AtGames Legends Gamer Pro,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b13,lefttrigger:b14,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000008a3500000102000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
030000008a3500000201000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
030000008a3500000302000000000000,Backbone One,a:b4,b:b5,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b10,leftstick:b17,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b18,righttrigger:b13,rightx:a3,righty:a4,start:b15,x:b7,y:b8,platform:Windows,
@@ -179,8 +190,6 @@
030000004f04000020b3000000000000,Dual Trigger,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
03000000bd12000002e0000000000000,Dual Vibration Joystick,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
03000000ff1100003133000000000000,DualForce,a:b2,b:b3,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:a4,start:b9,x:b0,y:b1,platform:Windows,
030000008f0e00000910000000000000,DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
03000000317300000100000000000000,DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
030000006f0e00003001000000000000,EA Sports 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,
03000000fc0400000250000000000000,Easy Grip,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
03000000bc2000000091000000000000,EasySMX Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows,
@@ -216,7 +225,7 @@
03000000b50700000399000000000000,Firestorm 2,a:b2,b:b4,back:b10,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b8,righttrigger:b9,start:b11,x:b3,y:b5,platform:Windows,
03000000b50700001302000000000000,Firestorm D3,a:b0,b:b2,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,x:b1,y:b3,platform:Windows,
03000000b40400001024000000000000,Flydigi Apex,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,misc1:b15,paddle1:b11,paddle2:b10,paddle3:b13,paddle4:b12,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
03000000151900004000000000000000,Flydigi Vader 2,a:b27,b:b26,back:b19,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b23,leftstick:b17,lefttrigger:b21,leftx:a0,lefty:a1,rightshoulder:b22,rightstick:b16,righttrigger:b20,rightx:a3,righty:a4,start:b18,x:b25,y:b24,platform:Windows,
03000000b40400001124000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b14,paddle1:b4,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b2,y:b3,platform:Windows,
03000000b40400001224000000000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:b8,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000008305000000a0000000000000,G08XU,a:b0,b:b1,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b5,x:b2,y:b3,platform:Windows,
@@ -250,6 +259,7 @@
03000000f025000031c1000000000000,Gioteck PS3 Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000f0250000c383000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000f0250000c483000000000000,Gioteck VX2 PlayStation Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000d11800000094000000000000,Google Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
030000004f04000026b3000000000000,GP XID,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
0300000079000000d418000000000000,GPD Win,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000025b000000000000,GPX,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -276,8 +286,8 @@
030000000d0f00005100000000000000,Hori Fighting Commander PS3,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:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00008600000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f0000ba00000000000000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000000d0f00008800000000000000,Hori Fighting Stick mini 4 (PS3),a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
030000000d0f00008700000000000000,Hori Fighting Stick mini 4 (PS4),a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000000d0f00008800000000000000,Hori Fighting Stick mini 4 PS3,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b8,x:b0,y:b3,platform:Windows,
030000000d0f00008700000000000000,Hori Fighting Stick mini 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
030000000d0f00001000000000000000,Hori Fightstick,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:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f00003200000000000000,Hori Fightstick 3W,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:a5,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000c000000000000000,Hori Fightstick 4,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -329,11 +339,13 @@
030000000d0f0000c100000000000000,Horipad Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
030000000d0f0000f600000000000000,Horipad Nintendo Switch Controller,a:b0,b:b1,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:b2,y:b3,platform:Windows,
030000000d0f00006700000000000000,Horipad One,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
030000000d0f00009601000000000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,misc2:b2,paddle1:b5,paddle2:b15,paddle3:b18,paddle4:b19,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
030000000d0f0000dc00000000000000,Horipad Switch,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000242e00000b20000000000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Windows,
03000000242e0000ff0b000000000000,Hyperkin N64 Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a3,start:b9,platform:Windows,
03000000790000004e95000000000000,Hyperkin N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a5,righty:a2,start:b9,platform:Windows,
03000000242e00006a48000000000000,Hyperkin RetroN Sq,a:b3,b:b7,back:b5,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b0,rightshoulder:b1,start:b4,x:b2,y:b6,platform:Windows,
03000000242f00000a20000000000000,Hyperkin Scout,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b2,y:b3,platform:Windows,
03000000242e00006a38000000000000,Hyperkin Trooper 2,a:b0,b:b1,back:b4,leftshoulder:b2,leftx:a0,lefty:a1,rightshoulder:b3,start:b5,platform:Windows,
03000000d81d00000e00000000000000,iBuffalo AC02 Arcade Joystick,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b11,righttrigger:b3,rightx:a2,righty:a5,start:b8,x:b4,y:b5,platform:Windows,
03000000d81d00000f00000000000000,iBuffalo BSGP1204 Series,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Windows,
@@ -389,7 +401,7 @@
03000000380700006652000000000000,Mad Catz CTRLR,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000380700005032000000000000,Mad Catz Fightpad Pro PS3,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,
03000000380700005082000000000000,Mad Catz Fightpad Pro PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000380700008031000000000000,Mad Catz FightStick Alpha PS3 ,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
03000000380700008031000000000000,Mad Catz FightStick Alpha PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
030000003807000038b7000000000000,Mad Catz Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b8,rightshoulder:b5,righttrigger:b9,start:b7,x:b2,y:b3,platform:Windows,
03000000380700008433000000000000,Mad Catz Fightstick TE S PS3,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,
03000000380700008483000000000000,Mad Catz Fightstick TE S PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
@@ -416,6 +428,7 @@
03000000242f00007300000000000000,Mayflash Magic NS,a:b1,b:b4,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b0,y:b3,platform:Windows,
0300000079000000d218000000000000,Mayflash Magic NS,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000d620000010a7000000000000,Mayflash Magic NS,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,
03000000242e0000f500000000000000,Mayflash N64 Adapter,a:b2,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
03000000242f0000f400000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a2,righty:a5,start:b9,platform:Windows,
03000000790000007918000000000000,Mayflash N64 Controller Adapter,a:b1,b:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,righttrigger:b7,rightx:a3,righty:a2,start:b8,platform:Windows,
030000008f0e00001030000000000000,Mayflash Saturn Adapter,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
@@ -447,7 +460,6 @@
03000000250900006688000000000000,MP-8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000091200004488000000000000,MUSIA PlayStation 2 Input Display,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,leftstick:b6,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b9,rightstick:b7,righttrigger:b11,rightx:a2,righty:a3,start:b5,x:b1,y:b3,platform:Windows,
03000000f70600000100000000000000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Windows,
030000006f0e00001311000000000000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Windows,
030000006b140000010c000000000000,Nacon GC 400ES,a:b0,b:b1,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:b2,y:b3,platform:Windows,
030000006b1400001106000000000000,Nacon Revolution 3 PS4 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:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
0300000085320000170d000000000000,Nacon Revolution 5 Pro,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
@@ -482,24 +494,21 @@
030000008916000000fd000000000000,Onza TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000d62000006d57000000000000,OPP 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,
030000006b14000001a1000000000000,Orange Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Windows,
0300000009120000072f000000000000,OrangeFox86 DreamPicoPort,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:-a2,leftx:a0,lefty:a1,righttrigger:-a5,start:b11,x:b3,y:b4,platform:Windows,
03000000362800000100000000000000,OUYA 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,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b2,platform:Windows,
03000000120c0000f60e000000000000,P4 Gamepad,a:b1,b:b2,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b7,rightshoulder:b4,righttrigger:b6,start:b9,x:b0,y:b3,platform:Windows,
03000000790000002201000000000000,PC Controller,a:b2,b:b1,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:b3,y:b0,platform:Windows,
030000006f0e00008501000000000000,PDP Fightpad Pro GameCube Controller,a:b1,b:b0,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
030000006f0e00000901000000000000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00008901000000000000,PDP Realmz Nintendo Switch 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,
030000008f0e00004100000000000000,PlaySega,a:b1,b:b0,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b4,y:b3,platform:Windows,
03000000666600006706000000000000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
03000000e30500009605000000000000,PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000004c050000da0c000000000000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002306000000000000,PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000f0250000c183000000000000,PlayStation 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,
03000000d9040000160f000000000000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
030000004c0500003713000000000000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core Plus GameCube Controller,a:b1,b:b0,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Windows,
03000000d620000011a7000000000000,PowerA Core 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000015a7000000000000,PowerA Fusion Nintendo Switch Arcade Stick,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000012a7000000000000,PowerA Fusion Nintendo Switch Fight Pad,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000dd62000016a7000000000000,PowerA Fusion Pro Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d620000013a7000000000000,PowerA Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
03000000d62000003340000000000000,PowerA OPS Pro Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000002640000000000000,PowerA OPS Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000d62000006dca000000000000,PowerA Pro Ex,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,
0300000062060000d570000000000000,PowerA PS3 Controller,a:b2,b:b1,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,
03000000d620000014a7000000000000,PowerA Spectra Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Windows,
@@ -598,6 +607,7 @@
030000009b2800002c00000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
030000009b2800008000000000000000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Windows,
03000000790000008f18000000000000,Rapoo Gamepad,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b3,y:b0,platform:Windows,
0300000032150000a602000000000000,Razer Huntsman V3 Pro,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b12,dpright:b13,dpup:b11,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000321500000003000000000000,Razer Hydra,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000f8270000bf0b000000000000,Razer Kishi,a:b6,b:b7,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b18,leftshoulder:b12,leftstick:b19,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b13,rightstick:b20,righttrigger:b15,rightx:a3,righty:a4,start:b17,x:b9,y:b10,platform:Windows,
03000000321500000204000000000000,Razer Panthera 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,
@@ -641,8 +651,9 @@
030000000d0f0000ad00000000000000,RX Gamepad,a:b0,b:b4,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b3,rightshoulder:b6,start:b9,x:b2,y:b1,platform:Windows,
030000008916000000fe000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000c6240000045d000000000000,Sabertooth,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000006f0e00001311000000000000,Saffun Controller,a:b2,b:b3,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:b1,y:b0,platform:Windows,
03000000a30600001af5000000000000,Saitek Cyborg,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:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000023f6000000000000,Saitek Cyborg V.1 Game,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:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000a306000023f6000000000000,Saitek Cyborg,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:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000300f00001201000000000000,Saitek Dual Analog,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000a30600000701000000000000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Windows,
03000000a30600000cff000000000000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b0,y:b1,platform:Windows,
@@ -669,7 +680,7 @@
03000000952e00002577000000000000,Scuf PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
03000000a30c00002500000000000000,Sega Genesis Mini 3B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,righttrigger:b5,start:b9,platform:Windows,
03000000a30c00002400000000000000,Sega Mega Drive Mini 6B Controller,a:b2,b:b1,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b7,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
03000000d804000086e6000000000000,Sega Multi Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:a2,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Windows,
0300000000050000289b000000000000,Sega Saturn Adapter,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b0,y:b3,platform:Windows,
0300000000f000000800000000000000,Sega Saturn Controller,a:b1,b:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b7,righttrigger:b3,start:b0,x:b5,y:b6,platform:Windows,
03000000730700000601000000000000,Sega Saturn Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b2,start:b9,x:b3,y:b4,platform:Windows,
@@ -682,13 +693,21 @@
03000000811700009d0a000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
030000008b2800000300000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
03000000921200004653000000000000,SNES Controller,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Windows,
030000008f0e00000910000000000000,Sony DualShock 2,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Windows,
03000000317300000100000000000000,Sony DualShock 3,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Windows,
03000000666600006706000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Windows,
03000000e30500009605000000000000,Sony PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
030000004c050000da0c000000000000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002306000000000000,Sony PlayStation Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Windows,
03000000f0250000c183000000000000,Sony PlayStation 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,
03000000d9040000160f000000000000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000ff000000cb01000000000000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
030000004c0500003713000000000000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Windows,
03000000341a00000208000000000000,Speedlink 6555,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:-a4,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a3,righty:a2,start:b7,x:b2,y:b3,platform:Windows,
03000000341a00000908000000000000,Speedlink 6566,a:b0,b:b1,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:b2,y:b3,platform:Windows,
03000000380700001722000000000000,Speedlink Competition Pro,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,x:b2,y:b3,platform:Windows,
030000008f0e00000800000000000000,Speedlink Strike FX,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000c01100000591000000000000,Speedlink Torid,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000d11800000094000000000000,Stadia Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b6,lefttrigger:b12,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:b11,rightx:a3,righty:a4,start:b9,x:b2,y:b3,platform:Windows,
03000000de280000fc11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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:Windows,
03000000de280000ff11000000000000,Steam Virtual Gamepad,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:+a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:-a2,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000120c0000160e000000000000,Steel Play Metaltech PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
@@ -698,7 +717,6 @@
03000000381000003014000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000381000003114000000000000,SteelSeries Stratus Duo,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000381000001814000000000000,SteelSeries Stratus XL,a:b0,b:b1,back:b18,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b19,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b2,y:b3,platform:Windows,
03000000790000001c18000000000000,STK 7024X,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000380700003847000000000000,Street Fighter Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b11,start:b7,x:b2,y:b3,platform:Windows,
030000001f08000001e4000000000000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Windows,
03000000790000000418000000000000,Super Famicom Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b33,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
@@ -713,17 +731,18 @@
03000000b50700001203000000000000,Techmobility X6-38V,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Windows,
03000000ba2200000701000000000000,Technology Innovation PS2 Adapter,a:b0,b:b1,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:a3,righty:a2,start:b9,x:b3,y:b2,platform:Windows,
03000000c61100001000000000000000,Tencent Xianyou Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,x:b3,y:b4,platform:Windows,
03000000790000002601000000000000,TGZ,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000790000001c18000000000000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a3,righty:a4,start:b11,x:b3,y:b4,platform:Windows,
03000000790000002601000000000000,TGZ Controller,a:b2,b:b1,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:a5,start:b9,x:b3,y:b0,platform:Windows,
03000000591c00002400000000000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000591c00002600000000000000,THEGamepad,a:b2,b:b1,back:b6,leftx:a0,lefty:a1,start:b7,x:b3,y:b0,platform:Windows,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 4,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000023b3000000000000,Thrustmaster Dual Trigger PlayStation 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:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ed0000000000000,ThrustMaster eSwap Pro 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000008d0000000000000,ThrustMaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f0400000ed0000000000000,Thrustmaster eSwap Pro 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000008d0000000000000,Thrustmaster Ferrari 150 PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Windows,
030000004f04000004b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Windows,
030000004f04000003d0000000000000,ThrustMaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000009d0000000000000,ThrustMaster Run N Drive PlayStation 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,
030000004f04000003d0000000000000,Thrustmaster Run N Drive PlayStation Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,leftshoulder:a3,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:a4,rightstick:b11,righttrigger:b5,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Windows,
030000004f04000009d0000000000000,Thrustmaster Run N Drive PlayStation 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,
030000006d04000088ca000000000000,Thunderpad,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000666600000288000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
03000000666600000488000000000000,TigerGame PlayStation Adapter,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Windows,
@@ -751,6 +770,7 @@
03000000bd12000012d0000000000000,USB Controller,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Windows,
03000000ff1100004133000000000000,USB Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a4,righty:a2,start:b9,x:b3,y:b0,platform:Windows,
03000000632500002305000000000000,USB Vibration Joystick,a:b2,b:b1,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:b3,y:b0,platform:Windows,
03000000882800000305000000000000,V5 Game Pad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,x:b2,y:b3,platform:Windows,
03000000790000001a18000000000000,Venom,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,
03000000790000001b18000000000000,Venom Arcade Joystick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Windows,
030000006f0e00000302000000000000,Victrix PS4 Pro Fightstick,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Windows,
@@ -782,7 +802,6 @@
03000000120c00000a88000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000120c00001088000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2~,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5~,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000002a0600002000000000000000,Xbox Controller,a:b0,b:b1,back:b13,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b5,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b15,righttrigger:b7,rightx:a2,righty:a5,start:b12,x:b2,y:b3,platform:Windows,
03000000300f00008888000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:b13,dpleft:b10,dpright:b11,dpup:b12,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000380700001645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
03000000380700002645000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
03000000380700003645000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b11,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
@@ -791,7 +810,6 @@
030000005e0400008502000000000000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400008702000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:b10,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000005e0400008902000000000000,Xbox Controller,a:b0,b:b1,back:b7,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b10,leftstick:b8,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b11,rightstick:b9,righttrigger:b4,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Windows,
030000000d0f00006300000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b9,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e0400000c0b000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000d102000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
030000005e040000dd02000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Windows,
@@ -825,6 +843,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Mac OS X,
03000000c82d00000090000001000000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Mac OS X,
03000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001251000000020000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001151000000010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
@@ -866,6 +885,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000260000001000000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b2,paddle2:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001d30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001530000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001630000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000c82d00001730000001000000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -878,20 +899,21 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a31,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000491900001904000001010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Mac OS X,
0300000008100000e501000019040000,Anbernic Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
0300000008100000e501000019040000,Anbernic Handheld,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b4,y:b3,platform:Mac OS X,
03000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000a30c00002700000003030000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a4,dpleft:-a3,dpright:+a3,dpup:-a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000a30c00002800000003030000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a3,lefty:a4,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000050b00000045000031000000,ASUS Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Mac OS X,
03000000050b00000579000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b42,paddle1:b9,paddle2:b11,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000050b00000679000000010000,ASUS ROG Kunai 3,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b23,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:MacOSX
03000000503200000110000045010000,Atari VCS Classic,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
03000000503200000110000047010000,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b3,start:b2,platform:Mac OS X,
03000000503200000210000047010000,Atari VCS Modern Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a4,rightx:a2,righty:a3,start:b8,x:b2,y:b3,platform:Mac OS X,
030000008a3500000102000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
030000008a3500000201000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000008a3500000202000000010000,Backbone One,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
030000008a3500000402000000010000,Backbone One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000008a3500000302000000010000,Backbone One PlayStationÆ Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
030000008a3500000302000000010000,Backbone One PlayStation Edition,a:b0,b:b1,back:b16,dpdown:b11,dpleft:b13,dpright:b12,dpup:b10,guide:b17,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a2,righty:a3~,start:b15,x:b2,y:b3,platform:Mac OS X,
03000000c62400001a89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b12,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b6,leftstick:b15,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b16,righttrigger:a4,rightx:a2,righty:a3,start:b13,x:b3,y:b4,platform:Mac OS X,
03000000c62400001b89000000010000,BDA MOGA XP5-X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000d62000002a79000000010000,BDA PS4 Fightpad,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
@@ -914,6 +936,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c01100000140000000010000,GameStop PS4 Fun 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000006f0e00000102000000000000,GameStop Xbox 360 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,
03000000ff1100003133000007010000,GameWare PC Control Pad,a:b2,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a4,start:b11,x:b3,y:b0,platform:Mac OS X,
03000000d11800000094000000010000,Google Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
030000007d0400000540000001010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000280400000140000000020000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00000300000007010000,GreenAsia Joystick,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Mac OS X,
@@ -925,8 +948,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f00008400000000010000,Hori Fighting Commander PS3,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00008500000000010000,Hori Fighting Commander PS3,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:Mac OS X,
03000000341a00000302000014010000,Hori Fighting Stick Mini,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00008800000000010000,Hori Fighting Stick mini 4 (PS3),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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00008700000000010000,Hori Fighting Stick mini 4 (PS4),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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000000d0f00008800000000010000,Hori Fighting Stick mini 4 PS3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000000d0f00008700000000010000,Hori Fighting Stick mini 4 PS4,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000000d0f00004d00000000000000,Hori Gem Pad 3,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:Mac OS X,
030000000d0f00003801000008010000,Hori PC Engine Mini Controller,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,platform:Mac OS X,
030000000d0f00009200000000010000,Hori Pokken Tournament DX Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -959,6 +982,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700008433000000010000,Mad Catz PS3 Fightstick TE S Plus,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:Mac OS X,
03000000380700005082000000010000,Mad Catz PS4 Fightpad Pro,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
03000000380700008483000000010000,Mad Catz PS4 Fightstick TE S Plus,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
0300000049190000020400001b010000,Manba One,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b22,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000790000000600000007010000,Marvo GT-004,a:b2,b:b1,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:b3,y:b0,platform:Mac OS X,
030000008f0e00001330000011010000,Mayflash Controller Adapter,a:b2,b:b4,back:b16,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b12,lefttrigger:b16,leftx:a0,lefty:a2,rightshoulder:b14,rightx:a6~,righty:a4,start:b18,x:b0,y:b6,platform:Mac OS X,
03000000790000004318000000010000,Mayflash GameCube Adapter,a:b4,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a12,leftx:a0,lefty:a4,rightshoulder:b28,righttrigger:a16,rightx:a20,righty:a8,start:b36,x:b8,y:b12,platform:Mac OS X,
@@ -992,9 +1016,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004b120000014d000000010000,Nyko Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Mac OS X,
030000006f0e00000901000002010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Mac OS X,
030000008f0e00000300000000000000,Piranha Xtreme PS3 Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Mac OS X,
03000000666600006706000088020000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
030000004c050000da0c000000010000,PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500003713000000010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
03000000d620000011a7000000020000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,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:b2,y:b3,platform:Mac OS X,
03000000d620000011a7000010050000,PowerA Nintendo Switch 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:Mac OS X,
03000000d62000006dca000000010000,PowerA Pro Ex,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:Mac OS X,
@@ -1012,7 +1033,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000004c050000e60c000000010000,PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
050000004c050000f20d000000010000,PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000005e040000e002000001000000,PXN P30 Pro Mobile,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000222c00000225000000010000,Qanba Dragon Arcade Joystick (PS3),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:Mac OS X,
03000000222c00000225000000010000,Qanba Dragon Arcade Joystick PS3,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:Mac OS X,
03000000222c00000020000000010000,Qanba Drone Arcade Stick,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000009b2800005600000020020000,Raphnet SNES Adapter,a:b1,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b5,platform:Mac OS X,
030000009b2800008000000022020000,Raphnet Wii Classic Adapter,a:b1,b:b4,back:b2,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,guide:b10,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a3,righty:a4,start:b3,x:b0,y:b5,platform:Mac OS X,
@@ -1047,7 +1068,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
0300000000f00000f100000000000000,SNES RetroPort,a:b2,b:b3,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b5,rightshoulder:b7,start:b6,x:b0,y:b1,platform:Mac OS X,
030000004c050000a00b000000000000,Sony DualShock 4 Adapter,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,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
030000004c050000cc09000000000000,Sony DualShock 4 V2,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,touchpad:b13,x:b0,y:b3,platform:Mac OS X,
03000000d11800000094000000010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000666600006706000088020000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Mac OS X,
030000004c050000da0c000000010000,Sony PlayStation Classic Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
030000004c0500003713000000010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Mac OS X,
030000005e0400008e02000001000000,Steam Virtual Gamepad,a:b0,b:b1,back:b9,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,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,
03000000110100002014000000000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
03000000110100002014000001000000,SteelSeries Nimbus,a:b0,b:b1,dpdown:b9,dpleft:b11,dpright:b10,dpup:b8,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1~,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3~,x:b2,y:b3,platform:Mac OS X,
@@ -1062,11 +1085,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000457500002211000000010000,SZMY Power PC Gamepad,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:Mac OS X,
03000000e40a00000307000001000000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
03000000e40a00000207000001000000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Mac OS X,
03000000790000001c18000000010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000790000001c18000003100000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000591c00002400000021000000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Mac OS X,
03000000591c00002600000021000000,THEGamepad,a:b2,b:b1,back:b6,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Mac OS X,
030000004f04000015b3000000000000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,ThrustMaster eSwap Pro 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f0400000ed0000000020000,Thrustmaster eSwap Pro 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
030000004f04000000b3000000000000,Thrustmaster Firestorm Dual Power,a:b0,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b11,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b1,y:b3,platform:Mac OS X,
03000000571d00002100000021000000,Tomee NES Controller Adapter,a:b1,b:b0,back:b2,dpdown:+a4,dpleft:-a0,dpright:+a0,dpup:-a4,start:b3,platform:Mac OS X,
03000000bd12000015d0000000010000,Tomee Retro Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Mac OS X,
@@ -1092,7 +1116,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000d102000000000000,Xbox One 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,
030000005e040000dd02000000000000,Xbox One 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,
030000005e040000e002000000000000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000e002000003090000,Xbox One Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Mac OS X,
030000005e040000e302000000000000,Xbox One 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,
030000005e040000ea02000000000000,Xbox One 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,
030000005e040000fd02000003090000,Xbox One Controller,a:b0,b:b1,back:b16,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
@@ -1104,6 +1128,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000130b000015050000,Xbox Series Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000007050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000130b000022050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
030000005e040000220b000017050000,Xbox Wireless Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000172700004431000029010000,XiaoMi Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a5,start:b11,x:b3,y:b4,platform:Mac OS X,
03000000120c0000100e000000010000,Zeroplus P4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Mac OS X,
@@ -1111,10 +1136,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
# Linux
03000000c82d00000031000011010000,8BitDo Adapter,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000631000000010000,8BitDo Adapter 2,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,
03000000c82d00000951000000010000,8BitDo Dogbone,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
03000000021000000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000090000011010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001038000000010000,8BitDo FC30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00006a28000000010000,8BitDo GameCube,a:b0,b:b3,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b9,paddle2:b8,rightshoulder:b10,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b1,y:b4,platform:Linux,
03000000c82d00001251000011010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001251000000010000,8BitDo Lite 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00001151000011010000,8BitDo Lite SE,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
@@ -1128,6 +1155,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000451000000010000,8BitDo N30,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b11,platform:Linux,
03000000c82d00001590000011010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00006528000000010000,8BitDo N30 Pro 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00006928000011010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
05000000c82d00006928000000010000,8BitDo N64,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b9,rightx:a2,righty:a3,start:b11,platform:Linux,
05000000c82d00002590000001000000,8BitDo NEOGEO,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000008000000210000011010000,8BitDo NES30,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
@@ -1149,6 +1177,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c82d00000331000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00000431000011010000,8BitDo Receiver,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c82d00002867000000010000,8BitDo S30,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b8,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:b7,rightx:a2,righty:a3,start:b10,x:b3,y:b4,platform:Linux,
03000000c82d00000060000011010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000060000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00000061000000010000,8BitDo SF30 Pro,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b2,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
030000003512000012ab000010010000,8BitDo SFC30,a:b2,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
@@ -1167,6 +1196,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c82d00000261000000010000,8BitDo SN30 Pro Plus,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
05000000202800000900000000010000,8BitDo SNES30,a:b1,b:b0,back:b10,dpdown:b122,dpleft:b119,dpright:b120,dpup:b117,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
05000000c82d00001230000000010000,8BitDo Ultimate,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00000a31000014010000,8BitDo Ultimate 2C,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,
03000000c82d00001d30000011010000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000c82d00001b30000001000000,8BitDo Ultimate 2C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,paddle1:b5,paddle2:b2,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001530000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001630000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001730000011010000,8BitDo Ultimate C,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1181,7 +1213,6 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000a00500003232000001000000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
05000000a00500003232000008010000,8BitDo Zero,a:b0,b:b1,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b3,y:b4,platform:Linux,
03000000c82d00001890000011010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b11,x:b4,y:b3,platform:Linux,
050000005e040000e002000030110000,8BitDo Zero 2,a:b0,b:b1,back:b6,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
05000000c82d00003032000000010000,8BitDo Zero 2,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2,righty:a3,start:b11,x:b4,y:b3,platform:Linux,
03000000c01100000355000011010000,Acrux Gamepad,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:Linux,
030000006f0e00008801000011010000,Afterglow Deluxe Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
@@ -1194,7 +1225,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000491900000204000021000000,Amazon Fire Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b17,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b12,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000491900001904000011010000,Amazon Luna Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b9,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b7,x:b2,y:b3,platform:Linux,
05000000710100001904000000010000,Amazon Luna Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b11,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Linux,
0300000008100000e501000001010000,Anbernic Gamepad,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux,
0300000008100000e501000001010000,Anbernic Handheld,a:b1,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a4,start:b11,x:b3,y:b4,platform:Linux,
03000000020500000913000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000373500000710000010010000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000373500004610000001000000,Anbernic RG P01,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b15,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000790000003018000011010000,Arcade Fightstick F300,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000a30c00002700000011010000,Astro City Mini,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000a30c00002800000011010000,Astro City Mini,a:b2,b:b1,back:b8,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
@@ -1226,6 +1260,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000bc2000000055000001000000,Betop AX1 BFM,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000bc2000006412000011010000,Betop Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b30,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006b1400000209000011010000,Bigben,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,
03000000120c0000300e000011010000,Brook Audio Fighting Board PS3,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:Linux,
03000000120c0000310e000011010000,Brook Audio Fighting Board PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000120c0000200e000011010000,Brook Mars PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000120c0000210e000011010000,Brook Mars PS4 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,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000120c0000f70e000011010000,Brook Universal Fighting Board,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
@@ -1234,6 +1270,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000b0400003365000000010000,Competition Pro,a:b0,b:b1,back:b2,leftx:a0,lefty:a1,start:b3,platform:Linux,
03000000260900008888000000010000,Cyber Gadget GameCube Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b6,righttrigger:a5,rightx:a2,righty:a3~,start:b7,x:b2,y:b3,platform:Linux,
03000000a306000022f6000011010000,Cyborg V3 Rumble,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:+a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:-a3,rightx:a2,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
030000005e0400008e02000002010000,Data Frog S80,a:b1,b:b0,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:b3,y:b2,platform:Linux,
03000000791d00000103000010010000,Dual Box Wii Classic Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,rightx:a2,righty:a3,start:b9,x:b3,y:b0,platform:Linux,
030000006f0e00003001000001010000,EA Sports 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:Linux,
03000000c11100000191000011010000,EasySMX,a:b2,b:b1,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:b3,y:b0,platform:Linux,
@@ -1246,6 +1283,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00008101000011010000,Faceoff Deluxe Pro Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00008001000011010000,Faceoff Pro Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03005036852100000201000010010000,Final Fantasy XIV Online 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:Linux,
05000000b40400001224000001010000,Flydigi APEX 4,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b14,leftshoulder:b4,leftstick:b10,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b20,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000b40400001124000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000b40400001224000011010000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b2,paddle1:b16,paddle2:b17,paddle3:b14,paddle4:b15,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000151900004000000001000000,Flydigi Vader 2,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b21,leftshoulder:b6,leftstick:b12,lefttrigger:a5,leftx:a0,lefty:a1,misc1:b14,paddle1:b2,paddle2:b5,paddle3:b16,paddle4:b17,rightshoulder:b7,rightstick:b13,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
@@ -1266,8 +1304,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
190000004b4800000010000001010000,GO-Advance Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,leftshoulder:b4,leftstick:b13,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b16,righttrigger:b15,start:b17,x:b2,y:b3,platform:Linux,
190000004b4800000011000000010000,GO-Super Controller,a:b1,b:b0,back:b12,dpdown:b9,dpleft:b10,dpright:b11,dpup:b8,guide:b16,leftshoulder:b4,leftstick:b14,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b15,righttrigger:b7,rightx:a2,righty:a3,start:b13,x:b2,y:b3,platform:Linux,
03000000f0250000c183000010010000,Goodbetterbest 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:Linux,
03000000d11800000094000011010000,Google Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000d11800000094000000010000,Google Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
0300000079000000d418000000010000,GPD Win 2 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,
030000005e0400008e02000001010000,GPD Win Max 2 (6800U) 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,
030000005e0400008e02000001010000,GPD Win Max 2 6800U 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,
030000007d0400000540000000010000,Gravis Eliminator Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000280400000140000000010000,Gravis GamePad Pro,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000008f0e00000610000000010000,GreenAsia Electronics Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a3,righty:a2,start:b11,x:b3,y:b0,platform:Linux,
@@ -1281,12 +1321,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f00008400000011010000,Hori Fighting Commander,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00005f00000011010000,Hori Fighting Commander 4 PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00005e00000011010000,Hori Fighting Commander 4 PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f00005001000009040000,Hori Fighting Commander OCTA Xbox One,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,
030000000d0f00005001000009040000,Hori Fighting Commander Octa Xbox One,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,
030000000d0f00008500000010010000,Hori Fighting Commander PS3,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:Linux,
030000000d0f00008600000002010000,Hori Fighting Commander Xbox 360,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00003701000013010000,Hori Fighting Stick Mini,a:b1,b:b0,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b3,y:b2,platform:Linux,
030000000d0f00008800000011010000,Hori Fighting Stick mini 4 (PS3),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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00008700000011010000,Hori Fighting Stick mini 4 (PS4),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:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f00008800000011010000,Hori Fighting Stick mini 4 PS3,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,rightshoulder:b5,rightstick:b11,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00008700000011010000,Hori Fighting Stick mini 4 PS4,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:a3,rightshoulder:b5,rightstick:b11,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f00001000000011010000,Hori Fightstick 3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
03000000ad1b000003f5000033050000,Hori Fightstick VX,+leftx:h0.2,+lefty:h0.4,-leftx:h0.8,-lefty:h0.1,a:b0,b:b1,back:b8,guide:b10,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
030000000d0f00004d00000011010000,Hori Gem Pad 3,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:Linux,
@@ -1303,9 +1343,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000000d0f00008501000015010000,Hori Switch Split Pad Pro,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,
030000000d0f00006e00000011010000,Horipad 4 PS3,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:Linux,
030000000d0f00006600000011010000,Horipad 4 PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f0000ee00000011010000,Horipad Mini 4,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:a5,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f0000ee00000011010000,Horipad Mini 4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,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,
030000000d0f0000c100000011010000,Horipad Nintendo Switch 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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f00006700000001010000,Horipad One,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,
030000000d0f0000ab01000011010000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000000d0f00009601000091000000,Horipad Steam,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,misc2:b2,paddle1:b19,paddle2:b18,paddle3:b15,paddle4:b5,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000000d0f0000f600000001000000,Horipad Switch Pro Controller,a:b0,b:b1,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:b2,y:b3,platform:Linux,
03000000341a000005f7000010010000,HuiJia GameCube Controller Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
05000000242e00000b20000001000000,Hyperkin Admiral N64 Controller,+rightx:b11,+righty:b13,-rightx:b8,-righty:b12,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b14,leftx:a0,lefty:a1,rightshoulder:b5,start:b9,platform:Linux,
@@ -1326,6 +1368,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000632500007505000011010000,Ipega PG 9099,a:b2,b:b1,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:b3,y:b0,platform:Linux,
0500000049190000030400001b010000,Ipega PG9099,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
05000000491900000204000000000000,Ipega PG9118,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000300f00001101000010010000,Jess Tech Colour Rumble Pad,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000300f00001001000010010000,Jess Tech Dual Analog Rumble,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
03000000300f00000b01000010010000,Jess Tech GGE909 PC Recoil,a:b2,b:b1,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:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000ba2200002010000001010000,Jess Technology Controller,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
@@ -1355,6 +1398,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700005032000011010000,Mad Catz Fightpad Pro PS3,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:Linux,
03000000380700005082000011010000,Mad Catz Fightpad Pro PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000ad1b00002ef0000090040000,Mad Catz Fightpad SFxT,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
03000000380700008031000011010000,Mad Catz FightStick Alpha PS3,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:Linux,
03000000380700008081000011010000,Mad Catz FightStick Alpha PS4,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:Linux,
03000000380700008034000011010000,Mad Catz Fightstick PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000380700008084000011010000,Mad Catz Fightstick PS4,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000380700008433000011010000,Mad Catz Fightstick TE S PS3,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:Linux,
@@ -1364,7 +1409,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000380700001647000010040000,Mad Catz Xbox 360 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,
03000000380700003847000090040000,Mad Catz Xbox 360 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
03000000ad1b000016f0000090040000,Mad Catz Xbox 360 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,
03000000120c00000500000000010000,Manta Dualshock 2,a:b0,b:b1,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000120c00000500000000010000,Manta DualShock 2,a:b0,b:b1,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:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
030000008f0e00001330000010010000,Mayflash Controller Adapter,a:b1,b:b2,back:b8,dpdown:h0.8,dpleft:h0.2,dpright:h0.1,dpup:h0.4,leftshoulder:b6,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a3~,righty:a2,start:b9,x:b0,y:b3,platform:Linux,
03000000790000004318000010010000,Mayflash GameCube Adapter,a:b1,b:b0,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000790000004418000010010000,Mayflash GameCube Controller,a:b1,b:b0,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:a4,rightx:a5,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
@@ -1401,7 +1446,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000050b000003090000,Microsoft Xbox One Elite 2,a:b0,b:b1,back:b17,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e0400008e02000030110000,Microsoft Xbox One Elite 2,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,paddle1:b11,paddle2:b13,paddle3:b12,paddle4:b14,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000005e040000120b00000b050000,Microsoft Xbox Series 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,
060000005e040000120b000001050000,Microsoft Xbox Series X Controller,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,platform:Linux,
060000005e040000120b000001050000,Microsoft Xbox Series X 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,
03000000030000000300000002000000,Miroof,a:b1,b:b0,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b2,platform:Linux,
03000000790000001c18000010010000,Mobapad Chitu HD,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000004d4f435554452d3035335800,Mocute 053X,a:b0,b:b1,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:b2,y:b3,platform:Linux,
@@ -1415,10 +1460,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000c62400001a89000000010000,MOGA XP5X Plus,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000250900006688000000010000,MP8866 Super Dual Box,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000005e0400008e02000010020000,MSI GC20 V2,a:b0,b:b1,back:b6,dpdown:b13,dpleft:b14,dpright:b15,dpup:b12,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,
030000006f0e00001311000011010000,N64 Controller,+rightx:b10,+righty:b3,-rightx:b0,-righty:b11,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,platform:Linux,
03000000f70600000100000000010000,N64 Adaptoid,+rightx:b2,+righty:b1,-rightx:b4,-righty:b5,a:b0,b:b3,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,leftshoulder:b6,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,start:b8,platform:Linux,
030000006b1400000906000014010000,Nacon Asymmetric Wireless PS4 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,
030000006b140000010c000010010000,Nacon GC 400ES,a:b0,b:b1,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:b2,y:b3,platform:Linux,
03000000853200000706000012010000,Nacon GC-100,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,
0300000085320000170d000011010000,Nacon Revolution 5 Pro,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
0300000085320000190d000011010000,Nacon Revolution 5 Pro,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000000d0f00000900000010010000,Natec Genesis P44,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:Linux,
030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
@@ -1447,8 +1494,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000007e0500001720000001000000,NSO SNES Controller,a:b0,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,lefttrigger:b7,rightshoulder:b6,righttrigger:b8,start:b10,x:b3,y:b2,platform:Linux,
050000007e0500001720000001800000,NSO SNES Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b3,y:b2,platform:Linux,
03000000550900001072000011010000,NVIDIA Controller,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b13,leftshoulder:b4,leftstick:b8,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000550900001472000011010000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
05000000550900001472000001000000,NVIDIA Controller v01.04,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
03000000550900001472000011010000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
05000000550900001472000001000000,NVIDIA Controller,a:b0,b:b1,back:b14,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b16,leftshoulder:b4,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b5,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Linux,
030000004b120000014d000000010000,NYKO Airflo EX,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b2,y:b3,platform:Linux,
03000000451300000830000010010000,NYKO CORE,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:a5,start:b9,x:b0,y:b3,platform:Linux,
19000000010000000100000001010000,ODROID Go 2,a:b1,b:b0,dpdown:b7,dpleft:b8,dpright:b9,dpup:b6,guide:b10,leftshoulder:b4,leftstick:b12,lefttrigger:b11,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b13,righttrigger:b14,start:b15,x:b2,y:b3,platform:Linux,
@@ -1469,17 +1516,15 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00000901000011010000,PDP PS3 Versus Fighting,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00002f01000011010000,PDP Wired 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:Linux,
03000000ad1b000004f9000000010000,PDP Xbox 360 Versus Fighting,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,rightshoulder:b5,righttrigger:a5,start:b7,x:b2,y:b3,platform:Linux,
030000006f0e0000f102000000000000,PDP Xbox Atomic,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,
030000006f0e0000a802000023020000,PDP Xbox One Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
030000006f0e0000a702000023020000,PDP Xbox One Raven Black,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,
030000006f0e0000d802000006640000,PDP Xbox Series 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,
030000006f0e0000ef02000007640000,PDP Xbox Series Kinetic Wired 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,
03000000666600006706000000010000,PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
030000004c050000da0c000011010000,PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000d9040000160f000000010000,PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
030000004c0500003713000011010000,PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000c62400000053000000010000,PowerA,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,
03000000c62400003a54000001010000,PowerA 1428124-01,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,
03000000d620000011a7000011010000,PowerA Core Plus Gamecube Controller,a:b1,b:b0,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:b2,y:b3,platform:Linux,
03000000d62000000540000001010000,PowerA Advantage Xbox Series X 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,
03000000d620000011a7000011010000,PowerA Core 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:Linux,
03000000dd62000015a7000011010000,PowerA Fusion Nintendo Switch Arcade Stick,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d620000012a7000011010000,PowerA Fusion Nintendo Switch Fight Pad,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,misc1:b13,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
03000000d62000000140000001010000,PowerA Fusion Pro 2 Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
@@ -1494,8 +1539,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000c62400001a54000001010000,PowerA Xbox One Mini 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,
03000000d62000000240000001010000,PowerA Xbox One Spectra Infinity,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,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,
03000000d62000000f20000001010000,PowerA Xbox Series Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b7,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,
03000000d62000000520000050010000,PowerA Xbox Series X 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,
03000000d62000000b20000001010000,PowerA Xbox Series X 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,
030000006d040000d2ca000011010000,Precision 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:Linux,
03000000250900000017000010010000,PS/SS/N64 Adapter,a:b1,b:b2,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b5,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b7,rightx:a2~,righty:a3,start:b8,platform:Linux,
03000000ff1100004133000010010000,PS2 Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000341a00003608000011010000,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:Linux,
030000004c0500006802000010010000,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,
@@ -1513,6 +1560,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
060000004c0500006802000000010000,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,
030000004c050000a00b000011010000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000a00b000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000c405000000810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000c405000011010000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000c405000011810000,PS4 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000cc09000000010000,PS4 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
@@ -1529,16 +1577,20 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000004c050000e60c000011010000,PS5 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:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000e60c000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
030000004c050000f20d000011010000,PS5 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:a3,leftx:a0,lefty:a1,misc1:b14,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000004c050000f20d000011810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000e60c000000010000,PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
050000004c050000e60c000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
050000004c050000f20d000000010000,PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
050000004c050000f20d000000810000,PS5 Controller,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b10,leftshoulder:b4,leftstick:b11,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:a5,rightx:a3,righty:a4,start:b9,x:b3,y:b2,platform:Linux,
03000000300f00001211000011010000,Qanba Arcade Joystick,a:b2,b:b0,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b5,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b6,start:b9,x:b1,y:b3,platform:Linux,
03000000222c00000225000011010000,Qanba Dragon Arcade Joystick (PS3),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:Linux,
03000000222c00000025000011010000,Qanba Dragon Arcade Joystick (PS4),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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000222c00000225000011010000,Qanba Dragon Arcade Joystick PS3,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:Linux,
03000000222c00000025000011010000,Qanba Dragon Arcade Joystick PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000222c00001220000011010000,Qanba Drone 2 Arcade Joystick PS4,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:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000222c00001020000011010000,Qanba Drone 2 Arcade Joystick PS5,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:a5,start:b9,x:b0,y:b3,platform:Linux,
03000000222c00000020000011010000,Qanba Drone Arcade PS4 Joystick,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:a3,rightshoulder:b5,righttrigger:a4,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000300f00001210000010010000,Qanba Joystick Plus,a:b0,b:b1,back:b8,leftshoulder:b5,lefttrigger:b7,leftx:a0,lefty:a1,rightshoulder:b4,righttrigger:b6,start:b9,x:b2,y:b3,platform:Linux,
03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick (PS3),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:Linux,
03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick (PS4),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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000222c00000223000011010000,Qanba Obsidian Arcade Joystick PS3,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:Linux,
03000000222c00000023000011010000,Qanba Obsidian Arcade Joystick PS4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
030000009b2800000300000001010000,Raphnet 4nes4snes,a:b0,b:b4,back:b2,leftshoulder:b6,leftx:a0,lefty:a1,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
030000009b2800004200000001010000,Raphnet Dual NES Adapter,a:b0,b:b1,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,start:b3,platform:Linux,
0300132d9b2800006500000000000000,Raphnet GameCube Adapter,a:b0,b:b7,dpdown:b11,dpleft:b12,dpright:b13,dpup:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b2,righttrigger:b5,rightx:a3,righty:a4,start:b3,x:b1,y:b8,platform:Linux,
@@ -1562,6 +1614,9 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000003215000000090000163a0000,Razer Serval,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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
0300000032150000030a000001010000,Razer Wildcat,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,
03000000321500000b10000011010000,Razer Wolverine PS5 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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
0300000032150000140a000001010000,Razer Wolverine Ultimate Xbox,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,
030000000d0f0000c100000010010000,Retro Bit Legacy16,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b12,leftshoulder:b4,lefttrigger:b6,misc1:b13,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
030000000d0f0000c100000072056800,Retro Bit Legacy16,a:b1,b:b0,back:b4,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,guide:b5,leftshoulder:b9,lefttrigger:+a4,misc1:b11,rightshoulder:b10,righttrigger:+a5,start:b6,x:b3,y:b2,platform:Linux,
03000000790000001100000010010000,Retro Controller,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,start:b9,x:b0,y:b3,platform:Linux,
0300000003040000c197000011010000,Retrode Adapter,a:b0,b:b4,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b1,y:b5,platform:Linux,
190000004b4800000111000000010000,RetroGame Joypad,a:b1,b:b0,back:b8,dpdown:b14,dpleft:b15,dpright:b16,dpup:b13,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b2,y:b3,platform:Linux,
@@ -1576,10 +1631,12 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000006f0e00001e01000011010000,Rock Candy 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:Linux,
03000000c6240000fefa000000010000,Rock Candy Xbox 360 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,
030000006f0e00004601000001010000,Rock Candy Xbox One Controller,a:b0,b:b1,back:b6,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,
03000000a306000023f6000011010000,Saitek Cyborg V1 PlayStation 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:a4,start:b9,x:b0,y:b3,platform:Linux,
030000006f0e00001311000011010000,Saffun Controller,a:b2,b:b3,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:b1,y:b0,platform:Linux,
03000000a306000023f6000011010000,Saitek Cyborg PlayStation 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:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000a30600001005000000010000,Saitek P150,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b7,lefttrigger:b6,rightshoulder:b2,righttrigger:b5,x:b3,y:b4,platform:Linux,
03000000a30600000701000000010000,Saitek P220,a:b2,b:b3,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b4,righttrigger:b5,x:b0,y:b1,platform:Linux,
03000000a30600000cff000010010000,Saitek P2500 Force Rumble,a:b2,b:b3,back:b11,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b8,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b9,righttrigger:b7,rightx:a3,righty:a2,start:b10,x:b0,y:b1,platform:Linux,
03000000a30600000d5f000010010000,Saitek P2600,a:b1,b:b2,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b11,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,rightx:a3,righty:a2,start:b8,x:b0,y:b3,platform:Linux,
03000000a30600000c04000011010000,Saitek P2900,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b12,x:b0,y:b3,platform:Linux,
03000000a306000018f5000010010000,Saitek P3200 Rumble,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000300f00001201000010010000,Saitek P380,a:b2,b:b3,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a3,righty:a2,start:b9,x:b0,y:b1,platform:Linux,
@@ -1595,20 +1652,22 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000790000001100000011010000,Sega Saturn,a:b1,b:b2,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b4,start:b9,x:b0,y:b3,platform:Linux,
03000000790000002201000011010000,Sega Saturn,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:b5,rightshoulder:b6,righttrigger:b7,start:b9,x:b2,y:b3,platform:Linux,
03000000b40400000a01000000010000,Sega Saturn,a:b0,b:b1,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b7,rightshoulder:b5,righttrigger:b2,start:b8,x:b3,y:b4,platform:Linux,
030000001f08000001e4000010010000,SFC Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000632500002305000010010000,ShanWan Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux,
03000000632500002605000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000632500007505000010010000,Shanwan Gamepad,a:b2,b:b1,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:b3,y:b0,platform:Linux,
03000000bc2000000055000010010000,Shanwan Gamepad,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000f025000021c1000010010000,Shanwan Gioteck PS3 Controller,a:b2,b:b1,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:b3,y:b0,platform:Linux,
03000000341a00000908000010010000,SL6566,a:b0,b:b1,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:b2,y:b3,platform:Linux,
030000004b2900000430000011000000,Snakebyte Xbox Series 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,
050000004c050000cc09000001000000,Sony DualShock 4,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:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
03000000666600006706000000010000,Sony PlayStation Adapter,a:b2,b:b1,back:b8,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b9,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b10,righttrigger:b5,rightx:a2,righty:a3,start:b11,x:b3,y:b0,platform:Linux,
030000004c050000da0c000011010000,Sony PlayStation Controller,a:b2,b:b1,back:b8,leftshoulder:b6,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,righttrigger:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000d9040000160f000000010000,Sony PlayStation Controller Adapter,a:b2,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a3,righty:a2,start:b9,x:b3,y:b0,platform:Linux,
03000000ff000000cb01000010010000,Sony PlayStation Portable,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
030000004c0500003713000011010000,Sony PlayStation Vita,a:b1,b:b2,back:b8,dpdown:b13,dpleft:b15,dpright:b14,dpup:b12,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,rightx:a3,righty:a4,start:b9,x:b0,y:b3,platform:Linux,
03000000250900000500000000010000,Sony PS2 pad with SmartJoy Adapter,a:b2,b:b1,back:b9,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
030000005e0400008e02000073050000,Speedlink Torid,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,
030000005e0400008e02000020200000,SpeedLink Xeox Pro Analog,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,
03000000d11800000094000011010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
05000000d11800000094000000010000,Stadia 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
03000000de2800000112000011010000,Steam Controller,a:b2,b:b3,back:b10,dpdown:+a5,dpleft:-a4,dpright:+a4,dpup:-a5,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a7,leftx:a0,lefty:a1,paddle1:b15,paddle2:b16,rightshoulder:b7,rightstick:b14,righttrigger:a6,rightx:a2,righty:a3,start:b11,x:b4,y:b5,platform:Linux,
03000000de2800000211000001000000,Steam Controller,a:b0,b:b1,back:b6,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,paddle1:b11,paddle2:b10,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Linux,
@@ -1629,6 +1688,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000110100001914000009010000,SteelSeries Stratus XL,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000ad1b000038f0000090040000,Street Fighter IV Fightstick TE,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b8,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
030000003b07000004a1000000010000,Suncom SFX Plus,a:b0,b:b2,back:b7,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,lefttrigger:b4,rightshoulder:b9,righttrigger:b5,start:b8,x:b1,y:b3,platform:Linux,
030000001f08000001e4000010010000,Super Famicom Controller,a:b2,b:b1,back:b8,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b4,rightshoulder:b5,start:b9,x:b3,y:b0,platform:Linux,
03000000666600000488000000010000,Super Joy Box 5 Pro,a:b2,b:b1,back:b9,dpdown:b14,dpleft:b15,dpright:b13,dpup:b12,leftshoulder:b6,leftstick:b10,lefttrigger:b4,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b11,righttrigger:b5,rightx:a2,righty:a3,start:b8,x:b3,y:b0,platform:Linux,
0300000000f00000f100000000010000,Super RetroPort,a:b1,b:b5,back:b2,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b6,rightshoulder:b7,start:b3,x:b0,y:b4,platform:Linux,
030000008f0e00000d31000010010000,SZMY Power 3 Turbo,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:Linux,
@@ -1638,7 +1698,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
03000000e40a00000307000011010000,Taito Egret II Mini Control Panel,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
03000000e40a00000207000011010000,Taito Egret II Mini Controller,a:b4,b:b2,back:b6,guide:b9,leftx:a0,lefty:a1,rightshoulder:b0,righttrigger:b1,start:b7,x:b8,y:b3,platform:Linux,
03000000ba2200000701000001010000,Technology Innovation PS2 Adapter,a:b0,b:b1,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:a5,righty:a2,start:b9,x:b3,y:b2,platform:Linux,
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000790000001c18000011010000,TGZ Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b15,leftshoulder:b6,leftstick:b13,lefttrigger:b8,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:b9,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
03000000591c00002400000010010000,THEC64 Joystick,a:b0,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b2,y:b3,platform:Linux,
03000000591c00002600000010010000,THEGamepad,a:b2,b:b1,back:b6,leftshoulder:b4,leftx:a0,lefty:a1,rightshoulder:b5,start:b7,x:b3,y:b0,platform:Linux,
030000004f04000015b3000001010000,Thrustmaster Dual Analog 3.2,a:b0,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b10,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b6,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b1,y:b3,platform:Linux,
@@ -1684,12 +1744,14 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
030000005e040000a102000000010000,Xbox 360 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,
030000005e040000a102000007010000,Xbox 360 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,
030000005e040000a102000030060000,Xbox 360 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,
030000006f0e00001503000000020000,Xbox 360 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,
030000005e0400008e02000000010000,Xbox 360 EasySMX,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,
030000005e040000a102000014010000,Xbox 360 Receiver,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,
0000000058626f782047616d65706100,Xbox 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400000202000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
030000005e0400008e02000072050000,Xbox 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,
030000006f0e00001304000000010000,Xbox 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,
03000000ffff0000ffff000000010000,Xbox Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b5,leftstick:b8,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b2,rightstick:b9,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b3,y:b4,platform:Linux,
0000000058626f782047616d65706100,Xbox 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:a5,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b10,righttrigger:a4,rightx:a2,righty:a3,start:b7,x:b2,y:b3,platform:Linux,
030000005e0400000a0b000005040000,Xbox One Controller,a:b1,b:b0,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b11,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b12,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b3,y:b2,platform:Linux,
030000005e040000d102000002010000,Xbox One 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,
030000005e040000ea02000000000000,Xbox One 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,
@@ -1701,8 +1763,10 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
050000005e040000220b000013050000,Xbox One Elite 2 Controller,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
050000005e040000050b000002090000,Xbox One Elite Series 2,a:b0,b:b1,back:b136,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b6,leftstick:b13,lefttrigger:a6,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a5,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
030000005e040000ea02000011050000,Xbox One S 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,
030000005e040000ea02000015050000,Xbox One S 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,
060000005e040000ea0200000b050000,Xbox One S 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,
060000005e040000ea0200000d050000,Xbox One S 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,
060000005e040000ea02000016050000,Xbox One S 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,
030000005e040000120b000001050000,Xbox Series 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,
030000005e040000120b000005050000,Xbox Series 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,
030000005e040000120b000007050000,Xbox Series 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,misc1:b11,rightshoulder:b5,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,start:b7,x:b2,y:b3,platform:Linux,
@@ -1746,6 +1810,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
33313433353539306634656436353432,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
38426974446f20446f67626f6e65204d,8BitDo Dogbone,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,start:b6,platform:Android,
34343439373236623466343934376233,8BitDo FC30 Pro,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b28,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b4,rightstick:b29,righttrigger:b7,start:b5,x:b30,y:b2,platform:Android,
38426974446f204e4743204d6f646b69,8BitDo GameCube,a:b0,b:b2,back:b4,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,paddle1:b18,paddle2:b17,rightshoulder:b15,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b1,y:b3,platform:Android,
38426974446f2038426974446f204c69,8BitDo Lite,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
30643332373663313263316637356631,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
38426974446f204c6974652032000000,8BitDo Lite 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b3,y:b2,platform:Android,
@@ -1819,7 +1884,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
63396666386564393334393236386630,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
63633435623263373466343461646430,8BitDo Zero 2,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftx:a0,lefty:a1,rightshoulder:b10,start:b6,x:b2,y:b3,platform:Android,
32333634613735616163326165323731,Amazon Luna Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,x:b2,y:b3,platform:Android,
4c696e757820342e31392e3137322077,Anbernic Gamepad,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android,
4c696e757820342e31392e3137322077,Anbernic Handheld,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a4,start:b6,x:b2,y:b3,platform:Android,
417374726f2063697479206d696e6920,Astro City Mini,a:b23,b:b22,back:b29,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,rightshoulder:b25,righttrigger:b26,start:b30,x:b24,y:b21,platform:Android,
35643263313264386134376362363435,Atari VCS Classic Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,start:b6,platform:Android,
32353831643566306563643065356239,Atari VCS Modern Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1833,6 +1898,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000bc20000000550000ffff3f00,GameSir G3w,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
34323662653333636330306631326233,Google Nexus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
35383633353935396534393230616564,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
476f6f676c65204c4c43205374616469,Google Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
5374616469614e3848532d6532633400,Google Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000d6020000e5890000dfff3f00,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a4,rightx:a2,righty:a5,start:b6,x:b2,y:b3,platform:Android,
05000000d6020000e5890000dfff3f80,GPD XD Plus,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a3,rightx:a4,righty:a5,start:b6,x:b2,y:b3,platform:Android,
66633030656131663837396562323935,Hori Battle,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:Android,
@@ -1906,14 +1973,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
39383335313438623439373538343266,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b16,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:b5,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:b7,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
4f5559412047616d6520436f6e74726f,OUYA Controller,a:b0,b:b2,dpdown:b18,dpleft:b15,dpright:b6,dpup:b17,leftshoulder:b3,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b10,righttrigger:a5,rightx:a3,righty:a4,x:b1,y:b19,platform:Android,
506572666f726d616e63652044657369,PDP PS3 Rock Candy Controller,a:b1,b:b17,back:h0.2,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b4,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b16,x:b0,y:b2,platform:Android,
62653335326261303663356263626339,PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
536f6e7920496e746572616374697665,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
576972656c65737320436f6e74726f6c,PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
61653962353232366130326530363061,Pokken,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,rightshoulder:b20,righttrigger:b10,start:b18,x:b0,y:b2,platform:Android,
32666633663735353234363064386132,PS2,a:b23,b:b22,back:b29,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b27,lefttrigger:b25,leftx:a0,lefty:a1,rightshoulder:b28,righttrigger:b26,rightx:a3,righty:a2,start:b30,x:b24,y:b21,platform:Android,
050000004c05000068020000dfff3f00,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
536f6e7920504c415953544154494f4e,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:a14,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
61363034663839376638653463633865,PS3 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
66366539656564653432353139356536,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
66383132326164626636313737373037,PS3 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000004c050000c405000000783f00,PS4 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -1936,7 +2000,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
65366465656364636137653363376531,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a3,start:b18,x:b0,y:b2,platform:Android,
66613532303965383534396638613230,PS4 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f00,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a4,rightx:a2,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f80,PS5 Controller,a:b1,b:b17,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b0,y:b2,platform:Android,
050000004c050000e60c0000fffe3f80,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b3,leftstick:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b18,rightstick:b6,righttrigger:a3,rightx:a4,righty:a5,start:b16,x:b2,y:b17,platform:Android,
050000004c050000e60c0000ffff3f00,PS5 Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
32346465346533616263386539323932,PS5 Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
32633532643734376632656664383733,PS5 Controller,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftstick:b15,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,rightstick:b6,righttrigger:b10,rightx:a2,righty:a5,start:b18,x:b0,y:b2,platform:Android,
@@ -1977,10 +2041,11 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
38376662666661636265313264613039,SNES,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
5346432f555342205061640000000000,SNES Adapter,a:b0,b:b1,back:b9,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b3,rightshoulder:b20,start:b10,x:b19,y:b2,platform:Android,
5553422047616d657061642000000000,SNES Controller,a:b1,b:b0,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,rightshoulder:b10,start:b6,x:b3,y:b2,platform:Android,
62653335326261303663356263626339,Sony PlayStation Classic Controller,a:b19,b:b1,back:b17,dpdown:+a1,dpleft:-a0,dpright:+a0,dpup:-a1,leftshoulder:b9,lefttrigger:b3,rightshoulder:b10,righttrigger:b20,start:b18,x:b2,y:b0,platform:Android,
536f6e7920496e746572616374697665,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,misc1:b8,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
576972656c65737320436f6e74726f6c,Sony PlayStation Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
63303964303462366136616266653561,Sony PSP,a:b21,b:b22,back:b27,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b23,y:b24,platform:Android,
63376637643462343766333462383235,Sony Vita,a:b1,b:b19,back:b17,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,leftx:a0,lefty:a1,rightshoulder:b20,rightx:a3,righty:a4,start:b18,x:b0,y:b2,platform:Android,
476f6f676c65204c4c43205374616469,Stadia Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
5374616469614e3848532d6532633400,Stadia Controller,a:b0,b:b1,back:b15,guide:b5,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
05000000de2800000511000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
05000000de2800000611000001000000,Steam Controller,a:b0,b:b1,back:b6,guide:b8,leftshoulder:b4,leftstick:b9,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a3,start:b7,x:b2,y:b3,platform:Android,
0500000011010000201400000f7e0f00,SteelSeries Nimbus,a:b0,b:b1,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b3,lefttrigger:b9,leftx:a0,lefty:a1,rightshoulder:b20,righttrigger:b10,rightx:a2,righty:a3,x:b19,y:b2,platform:Android,
@@ -1990,7 +2055,7 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
62363434353532386238336663643836,TGZ Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:b17,leftx:a0,lefty:a1,rightshoulder:b10,rightstick:b8,righttrigger:b18,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
37323236633763666465316365313236,THEC64 Joystick,a:b21,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b27,x:b23,y:b24,platform:Android,
38346162326232346533316164363336,THEGamepad,a:b23,b:b22,back:b27,leftshoulder:b25,leftx:a0,lefty:a1,rightshoulder:b26,start:b28,x:b24,y:b21,platform:Android,
050000004f0400000ed00000fffe3f00,ThrustMaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
050000004f0400000ed00000fffe3f00,Thrustmaster eSwap Pro Controller,a:b0,b:b1,back:b4,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b9,leftstick:b7,lefttrigger:a4,leftx:a0,lefty:a1,rightshoulder:b10,righttrigger:a5,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
5477696e20555342204a6f7973746963,Twin Joystick,a:b22,b:b21,back:b28,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,leftshoulder:b26,leftstick:b30,lefttrigger:b24,leftx:a0,lefty:a1,rightshoulder:b27,rightstick:b31,righttrigger:b25,rightx:a3,righty:a2,start:b29,x:b23,y:b20,platform:Android,
30623739343039643830333266346439,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
31643365666432386133346639383937,Valve Steam Controller,a:b0,b:b1,back:b15,dpdown:b12,dpleft:b13,dpright:b14,dpup:b11,guide:b5,leftshoulder:b9,leftstick:b7,leftx:a0,lefty:a1,paddle1:b24,paddle2:b23,rightshoulder:b10,rightstick:b8,rightx:a2,righty:a3,start:b6,x:b2,y:b3,platform:Android,
@@ -2037,6 +2102,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
05000000ac05000001000000ff076d01,*,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b9,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
05000000ac0500000200000000006d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,
05000000ac050000020000004f066d02,*,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b6,leftshoulder:b4,rightshoulder:b5,x:b2,y:b3,platform:iOS,
05000000ac05000004000000a8986d04,8BitDo Micro gamepad,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,lefttrigger:b12,rightshoulder:b13,righttrigger:b14,start:b3,x:b6,y:b5,platform:iOS,
05000000ac050000040000003b8a6d04,8BitDo SN30 Pro+,a:b1,b:b0,back:b4,dpdown:b7,dpleft:b8,dpright:b9,dpup:b10,guide:b2,leftshoulder:b11,leftstick:b12,lefttrigger:b13,leftx:a0,lefty:a1~,rightshoulder:b14,rightstick:b15,righttrigger:b16,rightx:a2,righty:a3~,start:b3,x:b6,y:b5,platform:iOS,
050000008a35000003010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
050000008a35000004010000ff070000,Backbone One,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,leftstick:b6,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b7,righttrigger:a5,rightx:a3,righty:a4,start:b10,x:b2,y:b3,platform:iOS,
4d466947616d65706164010000000000,MFi Extended Gamepad,a:b0,b:b1,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,leftshoulder:b4,lefttrigger:a2,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:a5,rightx:a3,righty:a4,start:b6,x:b2,y:b3,platform:iOS,

BIN
data/font/04b_25_grey.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

BIN
data/font/04b_25_metal.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -1,194 +0,0 @@
# box width
10
# box height
10
# 32 espacio ( )
5
# 33 !
4
# 34 "
5
# 35 #
7
# 36 $
7
# 37 %
8
# 38 &
8
# 39 '
3
# 40 (
5
# 41 )
5
# 42 *
7
# 43 +
7
# 44 ,
4
# 45 -
6
# 46 .
4
# 47 /
5
# 48 0
7
# 49 1
5
# 50 2
7
# 51 3
7
# 52 4
7
# 53 5
7
# 54 6
7
# 55 7
7
# 56 8
7
# 57 9
7
# 58 :
4
# 59 ;
4
# 60 <
6
# 61 =
6
# 62 >
6
# 63 ?
7
# 64 @
8
# 65 A
7
# 66 B
7
# 67 C
7
# 68 D
7
# 69 E
7
# 70 F
7
# 71 G
7
# 72 H
7
# 73 I
4
# 74 J
6
# 75 K
8
# 76 L
6
# 77 M
9
# 78 N
8
# 79 O
8
# 80 P
7
# 81 Q
8
# 82 R
7
# 83 S
6
# 84 T
8
# 85 U
7
# 86 V
8
# 87 W
9
# 88 X
8
# 89 Y
8
# 90 Z
7
# 91 [
4
# 92 \
5
# 93 ]
4
# 94 ^
5
# 95 _
8
# 96 `
4
# 97 a
7
# 98 b
7
# 99 c
6
# 100 d
7
# 101 e
7
# 102 f
5
# 103 g
7
# 104 h
7
# 105 i
4
# 106 j
5
# 107 k
7
# 108 l
4
# 109 m
10
# 110 n
7
# 111 o
7
# 112 p
7
# 113 q
7
# 114 r
6
# 115 s
6
# 116 t
5
# 117 u
7
# 118 v
7
# 119 w
9
# 120 x
7
# 121 y
7
# 122 z
7
# 123 { -> ñ
7
# 124 | -> ç
7
# 125 }
0
# 126 ~
0

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

BIN
data/gfx/intro/intro1.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 52 KiB

BIN
data/gfx/intro/intro2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

BIN
data/gfx/intro/intro3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

BIN
data/gfx/intro/intro4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

BIN
data/gfx/intro/intro5.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
data/gfx/intro/intro6.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

@@ -0,0 +1,9 @@
frame_width=20
frame_height=20
[animation]
name=default
speed=10
loop=0
frames=0,1
[/animation]

Binary file not shown.

After

Width:  |  Height:  |  Size: 565 B

View File

@@ -2,8 +2,15 @@ frame_width=32
frame_height=32
[animation]
name=default
name=fly
speed=2
loop=0
frames=0,1
[/animation]
[animation]
name=hit
speed=2
loop=0
frames=2,3
[/animation]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -32,7 +32,7 @@ IDIOMA
[ CANCELAR ]
## 11 - INSTRUCCIONES
OBJECTIU
Objectiu
## 12 - INSTRUCCIONES
HAS D'EXPLOTAR
@@ -47,7 +47,7 @@ LA DIFICULTAT AUGMENTA
A MESURA QUE VAS PUNTUANT
## 16 - INSTRUCCIONES
OBJECTES
Objectes
## 17 - INSTRUCCIONES
1.000 PUNTS
@@ -101,10 +101,10 @@ Espera un moment...
Si resulta que no tinc solt!
## 34 - INTRO
MERDA DE MAQUINA!
VAJA BIRRIA DE MAQUINA !!!
## 35 - INTRO
Blop... blop... blop...
blop... blop... blop...
## 36 - TEXTOS DEL JUEGO
Temps detes:
@@ -371,4 +371,37 @@ GRAFICS DIBUIXATS PER
MUSICA COMPOSADA PER
## 124 - CREDITS
EFECTES DE SO
EFECTES DE SO
## 125 - NOTIFICACIONES
Torna a polsar per reiniciar
## 126 - NOTIFICACIONES
Torna a polsar per canviar el idioma a
## 127 - NOTIFICACIONES
Idioma canviat a
## 128 - VARIOS
activat
## 129 - VARIOS
desactivat
## 130 - VARIOS
Dispar automatic
## 131 - VARIOS
Zoom de finestra
## 132 - VARIOS
Mode finestra
## 133 - VARIOS
Mode pantalla completa
## 134 - VARIOS
Mode d'escalat sencer
## 135 - VARIOS
Filtre

View File

@@ -371,4 +371,37 @@ PIXELART DRAWN BY
MUSIC COMPOSED BY
## 124 - CREDITS
SOUND EFFECTS
SOUND EFFECTS
## 125 - NOTIFICACIONES
Press again to reset
## 126 - NOTIFICACIONES
Press again to change languaje to
## 127 - NOTIFICACIONES
Language set to
## 128 - VARIOS
on
## 129 - VARIOS
off
## 130 - VARIOS
Autofire
## 131 - VARIOS
Window zoom
## 132 - VARIOS
Window mode
## 133 - VARIOS
Fullscreen mode
## 134 - VARIOS
Integer scale
## 135 - VARIOS
Filter

View File

@@ -371,4 +371,37 @@ GRAFICOS DIBUJADOS POR
MUSICA COMPUESTA POR
## 124 - CREDITS
EFECTOS DE SONIDO
EFECTOS DE SONIDO
## 125 - NOTIFICACIONES
Vuelve a pulsar para reiniciar
## 126 - NOTIFICACIONES
Vuelve a pulsar para cambiar el idioma a
## 127 - NOTIFICACIONES
Idioma cambiado a
## 128 - VARIOS
activado
## 129 - VARIOS
desactivado
## 130 - VARIOS
Disparo automático
## 131 - VARIOS
Zoom de ventana
## 132 - VARIOS
Modo ventana
## 133 - VARIOS
Modo pantalla completa
## 134 - VARIOS
Modo de escalado entero
## 135 - VARIOS
Filtro

BIN
data/sound/debian_drop.wav Normal file

Binary file not shown.

Binary file not shown.

BIN
data/sound/tabe_hit.wav Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -29,6 +29,7 @@ done
case $opcion in
w)
cppcheck --force --enable=warning,style,performance --std=c++20 \
--check-level=exhaustive \
--suppressions-list=./cppcheck_suppressions \
../source/ \
2>./cppcheck-result-warning-style-performance.txt

View File

@@ -46,7 +46,7 @@ public:
: MovingSprite(texture) {}
// Destructor
virtual ~AnimatedSprite() = default;
virtual ~AnimatedSprite() override = default;
// Actualiza las variables del objeto
void update() override;

View File

@@ -1,7 +1,7 @@
#pragma once
#include <string> // para string, basic_string
#include <vector> // para vector
#include <string> // Para string, basic_string
#include <vector> // Para vector
#include "utils.h"
enum class AssetType : int
@@ -56,13 +56,13 @@ private:
~Asset() = default;
public:
// [SINGLETON] Crearemos el objeto screen con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &executable_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Asset *get();
// Añade un elemento a la lista

View File

@@ -226,16 +226,6 @@ void Background::render()
SDL_RenderCopy(renderer_, color_texture_, &src_rect_, &dst_rect_);
}
// Vuelve a cargar las texturas
void Background::reloadTextures()
{
buildings_texture_->reLoad();
top_clouds_texture_->reLoad();
bottom_clouds_texture_->reLoad();
grass_texture_->reLoad();
gradients_texture_->reLoad();
}
// Ajusta el valor de la variable
void Background::setCloudsSpeed(float value)
{

View File

@@ -131,9 +131,6 @@ public:
// Establece la posición del objeto
void setPos(SDL_Rect pos);
// Vuelve a cargar las texturas
void reloadTextures();
// Ajusta el valor de la variable
void setCloudsSpeed(float value);

View File

@@ -118,7 +118,7 @@ void Balloon::render()
if (!invulnerable_)
{
SDL_Point p = {24, 24};
sprite_->setRotatingCenter(&p);
sprite_->setRotatingCenter(p);
sprite_->render();
}

View File

@@ -1,7 +1,7 @@
#include "balloon_formations.h"
#include "balloon.h" // para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include "param.h" // para param
#include "utils.h" // para ParamGame, Param, Zone, BLOCK
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include "param.h" // Para param
#include "utils.h" // Para ParamGame, Param, Zone, BLOCK
void BalloonFormations::initBalloonFormations()
{

View File

@@ -1,6 +1,6 @@
#pragma once
#include "balloon.h" // para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include "balloon.h" // Para BALLOON_VELX_NEGATIVE, BALLOON_VELX_POSITIVE
#include <vector>
constexpr int NUMBER_OF_BALLOON_FORMATIONS = 100;

View File

@@ -9,9 +9,8 @@
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "stage.h" // Para power
#include "texture.h" // Para Texture
#include "utils.h" // Para Zone, BLOCK, Color, flash_color
#include "stage.h" // Para addPower
#include "utils.h" // Para Zone, Color, flash_color
// Constructor
BalloonManager::BalloonManager()
@@ -321,7 +320,7 @@ int BalloonManager::destroyAllBalloons()
}
balloon_deploy_counter_ = 300;
JA_PlaySound(Resource::get()->getSound("powerball.wav"));
JA_PlaySound(Resource::get()->getSound("power_ball_explosion.wav"));
Screen::get()->flash(flash_color, 3);
Screen::get()->shake();
@@ -370,15 +369,6 @@ void BalloonManager::normalColorsToAllBalloons()
}
}
// Recarga las texturas
void BalloonManager::reLoad()
{
for (auto &texture : balloon_textures_)
{
texture->reLoad();
}
}
// Crea dos globos gordos
void BalloonManager::createTwoBigBalloons()
{

View File

@@ -104,9 +104,6 @@ public:
// Cambia el color de todos los globos
void normalColorsToAllBalloons();
// Recarga las texturas
void reLoad();
// Crea dos globos gordos
void createTwoBigBalloons();

View File

@@ -9,13 +9,14 @@
#include <stdexcept> // Para runtime_error
#include <string> // Para basic_string, string
#include <vector> // Para vector
#include <array> // Para vector
#include "balloon_manager.h" // Para BalloonManager
#include "fade.h" // Para Fade, FadeType, FadeMode
#include "global_inputs.h" // Para check, update
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_GetMusicState, JA_SetMusicVolume
#include "lang.h" // Para getText
#include "mouse.h" // Para handleEvent
#include "global_events.h" // Para handleEvent
#include "param.h" // Para Param, ParamGame, param
#include "player.h" // Para Player, PlayerState
#include "resource.h" // Para Resource
@@ -56,6 +57,9 @@ Credits::Credits()
fade_out_->setType(FadeType::FULLSCREEN);
fade_out_->setPostDuration(400);
updateRedRect();
tiled_bg_->setColor(Color(255, 96, 96));
initPlayers();
SDL_SetTextureBlendMode(text_texture_, SDL_BLENDMODE_BLEND);
fillTextTexture();
@@ -68,6 +72,7 @@ Credits::~Credits()
SDL_DestroyTexture(text_texture_);
SDL_DestroyTexture(canvas_);
resetVolume();
JA_StopMusic();
}
// Bucle principal
@@ -85,15 +90,14 @@ void Credits::run()
// Actualiza las variables
void Credits::update()
{
constexpr Uint32 TICKS_SPEED_ = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED_)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
ticks_ = SDL_GetTicks();
const int repeat = want_to_pass_ ? 4 : 1;
for (int i = 0; i < repeat; ++i)
const int REPEAT = want_to_pass_ ? 4 : 1;
for (int i = 0; i < REPEAT; ++i)
{
tiled_bg_->update();
cycleColors();
balloon_manager_->update();
updateTextureDstRects();
throwBalloons();
@@ -104,6 +108,7 @@ void Credits::update()
updateAllFades();
++counter_;
}
Screen::get()->update();
globalInputs::update();
@@ -128,20 +133,9 @@ void Credits::render()
void Credits::checkEvents()
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
@@ -149,18 +143,14 @@ void Credits::checkEvents()
void Credits::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
if (Input::get()->checkAnyButtonPressed(INPUT_ALLOW_REPEAT))
{
if (mini_logo_on_position_)
{
// Si el mini_logo ha llegado a su posición final, al pulsar cualquier tecla se activa el fundido
fading_ = true;
}
else
{
// Si todavía estan los creditos en marcha, se pasan solos a toda pastilla
want_to_pass_ = true;
}
want_to_pass_ = true;
fading_ = mini_logo_on_position_;
}
else
{
want_to_pass_ = false;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
@@ -176,7 +166,7 @@ void Credits::fillTextTexture()
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0);
SDL_RenderClear(Screen::get()->getRenderer());
std::vector<std::string> texts = {
const std::array<std::string, 10> TEXTS = {
lang::getText(121),
lang::getText(122),
lang::getText(123),
@@ -188,50 +178,50 @@ void Credits::fillTextTexture()
"WWW.KENNEY.NL",
"JAILDOCTOR"};
const int space_post_title = 3 + text->getCharacterSize();
const int space_pre_title = text->getCharacterSize() * 4;
const int texts_height = 1 * text->getCharacterSize() + 7 * space_post_title + 3 * space_pre_title;
credits_rect_dst_.h = credits_rect_src_.h = texts_height;
const int SPACE_POST_TITLE = 3 + text->getCharacterSize();
const int SPACE_PRE_TITLE = text->getCharacterSize() * 4;
const int TEXTS_HEIGHT = 1 * text->getCharacterSize() + 7 * SPACE_POST_TITLE + 3 * SPACE_PRE_TITLE;
credits_rect_dst_.h = credits_rect_src_.h = TEXTS_HEIGHT;
int y = (param.game.height - texts_height) / 2;
int y = (param.game.height - TEXTS_HEIGHT) / 2;
y = 0;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(0), 1, no_color, 1, shdw_txt_color);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(0), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(4), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(4), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
y += SPACE_PRE_TITLE;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(1), 1, no_color, 1, shdw_txt_color);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(1), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(4), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(4), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
y += SPACE_PRE_TITLE;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(2), 1, no_color, 1, shdw_txt_color);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(2), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(5), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(6), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(5), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(6), 1, no_color, 1, shdw_txt_color);
y += space_pre_title;
y += SPACE_PRE_TITLE;
text->setPalette(1);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(3), 1, no_color, 1, shdw_txt_color);
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(3), 1, no_color, 1, shdw_txt_color);
text->setPalette(0);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(7), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(8), 1, no_color, 1, shdw_txt_color);
y += space_post_title;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, texts.at(9), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(7), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(8), 1, no_color, 1, shdw_txt_color);
y += SPACE_POST_TITLE;
text->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, y, TEXTS.at(9), 1, no_color, 1, shdw_txt_color);
// Mini logo
y += space_pre_title;
y += SPACE_PRE_TITLE;
mini_logo_rect_src_.y = y;
auto mini_logo_sprite = std::make_unique<Sprite>(Resource::get()->getTexture("logo_jailgames_mini.png"));
mini_logo_sprite->setPosition(1 + param.game.game_area.center_x - mini_logo_sprite->getWidth() / 2, 1 + y);
@@ -278,12 +268,16 @@ void Credits::fillCanvas()
SDL_RenderCopy(Screen::get()->getRenderer(), text_texture_, &mini_logo_rect_src_, &mini_logo_rect_dst_);
// Dibuja los rectangulos negros
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 255);
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0, 0, 0, 0xFF);
SDL_RenderFillRect(Screen::get()->getRenderer(), &top_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &bottom_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &left_black_rect_);
SDL_RenderFillRect(Screen::get()->getRenderer(), &right_black_rect_);
// Dibuja el rectangulo rojo
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0xFF, 0, 0, 0xFF);
SDL_RenderDrawRect(Screen::get()->getRenderer(), &red_rect);
// Si el mini_logo está en su destino, lo dibuja encima de lo anterior
if (mini_logo_on_position_)
{
@@ -429,13 +423,14 @@ void Credits::updateBlackRects()
// Si los rectangulos superior e inferior han llegado al centro
if (left_black_rect_.w != param.game.game_area.center_x && right_black_rect_.x != param.game.game_area.center_x)
{
constexpr int SPEED = 2;
// Si los rectangulos izquierdo y derecho no han llegado al centro
// Incrementa la anchura del rectangulo situado a la izquierda
left_black_rect_.w = std::min(left_black_rect_.w + 4, param.game.game_area.center_x);
left_black_rect_.w = std::min(left_black_rect_.w + SPEED, param.game.game_area.center_x);
// Incrementa la anchura y modifica la posición del rectangulo situado a la derecha
right_black_rect_.w += 4;
right_black_rect_.x = std::max(right_black_rect_.x - 4, param.game.game_area.center_x);
right_black_rect_.w += SPEED;
right_black_rect_.x = std::max(right_black_rect_.x - SPEED, param.game.game_area.center_x);
--current_step;
setVolume(static_cast<int>(initial_volume_ * current_step / steps_));
@@ -457,12 +452,22 @@ void Credits::updateBlackRects()
}
}
// Actualiza el rectangulo rojo
void Credits::updateRedRect()
{
red_rect.x = left_black_rect_.x + left_black_rect_.w;
red_rect.y = top_black_rect_.y + top_black_rect_.h - 1;
red_rect.w = right_black_rect_.x - red_rect.x;
red_rect.h = bottom_black_rect_.y - red_rect.y + 1;
}
// Actualiza el estado de fade
void Credits::updateAllFades()
{
if (fading_)
{
updateBlackRects();
updateRedRect();
}
fade_in_->update();
@@ -477,7 +482,7 @@ void Credits::updateAllFades()
fade_out_->update();
if (fade_out_->hasEnded())
{
section::name = section::Name::LOGO;
section::name = section::Name::HI_SCORE_TABLE;
}
}
@@ -493,4 +498,42 @@ void Credits::resetVolume()
{
options.audio.music.volume = initial_volume_;
JA_SetMusicVolume(to_JA_volume(options.audio.music.volume));
}
}
// Cambia el color del fondo
void Credits::cycleColors()
{
constexpr int UPPER_LIMIT = 255; // Límite superior
constexpr int LOWER_LIMIT = 80; // Límite inferior
static float r = static_cast<float>(UPPER_LIMIT);
static float g = static_cast<float>(LOWER_LIMIT);
static float b = static_cast<float>(LOWER_LIMIT);
static float stepR = -0.5f; // Paso flotante para transiciones suaves
static float stepG = 0.3f;
static float stepB = 0.7f;
// Ajustar valores de R
r += stepR;
if (r >= UPPER_LIMIT || r <= LOWER_LIMIT)
{
stepR = -stepR; // Cambia de dirección al alcanzar los límites
}
// Ajustar valores de G
g += stepG;
if (g >= UPPER_LIMIT || g <= LOWER_LIMIT)
{
stepG = -stepG; // Cambia de dirección al alcanzar los límites
}
// Ajustar valores de B
b += stepB;
if (b >= UPPER_LIMIT || b <= LOWER_LIMIT)
{
stepB = -stepB; // Cambia de dirección al alcanzar los límites
}
// Aplicar el color, redondeando a enteros antes de usar
tiled_bg_->setColor(Color(static_cast<int>(r), static_cast<int>(g), static_cast<int>(b)));
}

View File

@@ -54,6 +54,7 @@ private:
SDL_Rect bottom_black_rect_ = {play_area_.x, param.game.game_area.rect.h - black_bars_size_, play_area_.w, black_bars_size_}; // Rectangulo negro inferior
SDL_Rect left_black_rect_ = {play_area_.x, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la izquierda
SDL_Rect right_black_rect_ = {play_area_.x + play_area_.w, param.game.game_area.center_y - 1, 0, 2}; // Rectangulo negro situado a la derecha
SDL_Rect red_rect = play_area_; // Rectangulo rojo para delimitar la ventana
// Actualiza las variables
void update();
@@ -85,6 +86,9 @@ private:
// Actualiza los rectangulos negros
void updateBlackRects();
// Actualiza el rectangulo rojo
void updateRedRect();
// Actualiza el estado de fade
void updateAllFades();
@@ -94,6 +98,9 @@ private:
// Reestablece el nivel de volumen
void resetVolume();
// Cambia el color del fondo
void cycleColors();
public:
// Constructor
Credits();

View File

@@ -1,7 +1,7 @@
#include "dbgtxt.h"
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_rwops.h> // para SDL_RWFromMem
#include <SDL2/SDL_surface.h> // para SDL_LoadBMP_RW
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_rwops.h> // Para SDL_RWFromMem
#include <SDL2/SDL_surface.h> // Para SDL_LoadBMP_RW
namespace
{

View File

@@ -1,7 +1,7 @@
#pragma once
#include <SDL2/SDL_render.h> // para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // para Uint8
#include <SDL2/SDL_render.h> // Para SDL_Renderer
#include <SDL2/SDL_stdinc.h> // Para Uint8
void dbg_init(SDL_Renderer *renderer);
void dbg_print(int x, int y, const char *text, Uint8 r, Uint8 g, Uint8 b);

View File

@@ -1,10 +1,9 @@
#include "define_buttons.h"
#include "input.h" // Para Input, InputType
#include "input.h" // Para Input, InputAction
#include "lang.h" // Para getText
#include "options.h" // Para OptionsController, Options, options
#include "param.h" // Para Param, param, ParamGame, ParamTitle
#include "resource.h" // Para Resource
#include "section.h" // Para Name, Options, name, options
#include "text.h" // Para Text
// Constructor
@@ -62,32 +61,11 @@ void DefineButtons::bindButtons()
}
// Comprueba los eventos
void DefineButtons::checkEvents()
void DefineButtons::checkEvents(const SDL_Event &event)
{
if (enabled_)
if (enabled_ && event.type == SDL_CONTROLLERBUTTONDOWN)
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_WITH_KEYBOARD;
break;
}
case SDL_CONTROLLERBUTTONDOWN:
{
doControllerButtonDown(event.cbutton);
break;
}
default:
break;
}
}
doControllerButtonDown(event.cbutton);
}
}
@@ -157,9 +135,9 @@ bool DefineButtons::checkButtonNotInUse(SDL_GameControllerButton button)
void DefineButtons::clearButtons()
{
buttons_.clear();
buttons_.emplace_back(lang::getText(95), InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(96), InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(97), InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(98), InputType::START, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(99), InputType::SERVICE, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(95), InputAction::FIRE_LEFT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(96), InputAction::FIRE_CENTER, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(97), InputAction::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(98), InputAction::START, SDL_CONTROLLER_BUTTON_INVALID);
buttons_.emplace_back(lang::getText(99), InputAction::SERVICE, SDL_CONTROLLER_BUTTON_INVALID);
}

View File

@@ -8,16 +8,16 @@
#include <vector> // Para vector
class Input; // lines 8-8
class Text; // lines 9-9
enum class InputType : int; // lines 10-10
enum class InputAction : int; // lines 10-10
struct DefineButtonsButton
{
std::string label; // Texto en pantalla para el botón
InputType input; // Input asociado
InputAction input; // Input asociado
SDL_GameControllerButton button; // Botón del mando correspondiente
// Constructor
DefineButtonsButton(const std::string &lbl, InputType inp, SDL_GameControllerButton btn)
DefineButtonsButton(const std::string &lbl, InputAction inp, SDL_GameControllerButton btn)
: label(lbl), input(inp), button(btn) {}
};
@@ -67,7 +67,7 @@ public:
void render();
// Comprueba los eventos
void checkEvents();
void checkEvents(const SDL_Event &event);
// Habilita el objeto
bool enable(int index);

View File

@@ -4,46 +4,49 @@
#include <SDL2/SDL_audio.h> // Para AUDIO_S16
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_events.h> // Para SDL_DISABLE
#include <SDL2/SDL_gamecontroller.h> // Para SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_hints.h> // Para SDL_SetHint, SDL_HINT_RENDER_DR...
#include <SDL2/SDL_mouse.h> // Para SDL_ShowCursor
#include <SDL2/SDL_scancode.h> // Para SDL_SCANCODE_0, SDL_SCANCODE_DOWN
#include <SDL2/SDL_stdinc.h> // Para SDL_bool, Uint32
#include <SDL2/SDL_stdinc.h> // Para Uint32, SDL_bool
#include <errno.h> // Para errno, EEXIST, EACCES, ENAMETOO...
#include <stdio.h> // Para printf, perror
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid
#include <algorithm> // Para min
#include <chrono> // Para chrono
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
#include <iostream> // Para basic_ostream, operator<<, basi...
#include <memory> // Para make_unique, unique_ptr
#include <stdexcept> // Para runtime_error
#include <string> // Para operator+, char_traits, allocator
#include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType
#include "credits.h" // Para Credits
#include "dbgtxt.h" // Para dbg_init
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
#include "hiscore_table.h" // Para HiScoreTable
#include "input.h" // Para Input, InputAction
#include "instructions.h" // Para Instructions
#include "intro.h" // Para Intro
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
#include "lang.h" // Para Code, loadFromFile
#include "logo.h" // Para Logo
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, options, OptionsContro...
#include "param.h" // Para Param, ParamGame, param, loadPa...
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, Options, name, options
#include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides
#ifndef _WIN32
#include <pwd.h> // Para getpwuid, passwd
#endif
#include <stdio.h> // Para printf, perror
#include <sys/stat.h> // Para mkdir, stat, S_IRWXU
#include <unistd.h> // Para getuid
#include <algorithm> // Para min
#include <chrono> // Para chrono
#include <cstdlib> // Para exit, EXIT_FAILURE, size_t, rand
#include <iostream> // Para basic_ostream, operator<<, basi...
#include <memory> // Para make_unique, unique_ptr
#include <stdexcept> // Para runtime_error
#include <string> // Para operator+, char_traits, allocator
#include <vector> // Para vector
#include "asset.h" // Para Asset, AssetType
#include "credits.h" // Para Credits
#include "dbgtxt.h" // Para dbg_init
#include "game.h" // Para Game, GAME_MODE_DEMO_OFF, GAME_...
#include "hiscore_table.h" // Para HiScoreTable
#include "input.h" // Para Input, InputType
#include "instructions.h" // Para Instructions
#include "intro.h" // Para Intro
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundV...
#include "lang.h" // Para Code, loadFromFile
#include "logo.h" // Para Logo
#include "manage_hiscore_table.h" // Para ManageHiScoreTable
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, options, OptionsContro...
#include "param.h" // Para Param, ParamGame, param, loadPa...
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, Options, name, options
#include "title.h" // Para Title
#include "utils.h" // Para Overrides, overrides
// Constructor
Director::Director(int argc, const char *argv[])
@@ -55,6 +58,7 @@ Director::Director(int argc, const char *argv[])
section::name = section::Name::LOGO;
#else // NORMAL GAME
section::name = section::Name::LOGO;
section::options = section::Options::NONE;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
#endif
@@ -97,6 +101,7 @@ void Director::init()
// Inicializa y crea el resto de objetos
initSDL();
SDL_ShowCursor(SDL_DISABLE);
initJailAudio();
dbg_init(renderer_);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
@@ -126,6 +131,10 @@ void Director::close()
SDL_DestroyWindow(window_);
SDL_Quit();
#ifdef ARCADE
shutdownSystem(section::options == section::Options::QUIT_WITH_CONTROLLER);
#endif
}
// Carga los parametros
@@ -158,53 +167,58 @@ void Director::loadScoreFile()
void Director::bindInputs()
{
// Teclado - Movimiento del jugador
Input::get()->bindKey(InputType::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputType::DOWN, SDL_SCANCODE_DOWN);
Input::get()->bindKey(InputType::LEFT, SDL_SCANCODE_LEFT);
Input::get()->bindKey(InputType::RIGHT, SDL_SCANCODE_RIGHT);
Input::get()->bindKey(InputAction::UP, SDL_SCANCODE_UP);
Input::get()->bindKey(InputAction::DOWN, SDL_SCANCODE_DOWN);
Input::get()->bindKey(InputAction::LEFT, SDL_SCANCODE_LEFT);
Input::get()->bindKey(InputAction::RIGHT, SDL_SCANCODE_RIGHT);
Input::get()->bindKey(InputType::FIRE_LEFT, SDL_SCANCODE_Q);
Input::get()->bindKey(InputType::FIRE_CENTER, SDL_SCANCODE_W);
Input::get()->bindKey(InputType::FIRE_RIGHT, SDL_SCANCODE_E);
Input::get()->bindKey(InputAction::FIRE_LEFT, SDL_SCANCODE_Q);
Input::get()->bindKey(InputAction::FIRE_CENTER, SDL_SCANCODE_W);
Input::get()->bindKey(InputAction::FIRE_RIGHT, SDL_SCANCODE_E);
Input::get()->bindKey(InputType::START, SDL_SCANCODE_RETURN);
Input::get()->bindKey(InputAction::START, SDL_SCANCODE_RETURN);
// Teclado - Control del programa
Input::get()->bindKey(InputType::SERVICE, SDL_SCANCODE_0);
Input::get()->bindKey(InputType::EXIT, SDL_SCANCODE_ESCAPE);
Input::get()->bindKey(InputType::PAUSE, SDL_SCANCODE_P);
Input::get()->bindKey(InputType::WINDOW_DEC_SIZE, SDL_SCANCODE_F1);
Input::get()->bindKey(InputType::WINDOW_INC_SIZE, SDL_SCANCODE_F2);
Input::get()->bindKey(InputType::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(InputType::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(InputType::MUTE, SDL_SCANCODE_F5);
Input::get()->bindKey(InputType::AUTO_FIRE, SDL_SCANCODE_F6);
Input::get()->bindKey(InputType::CHANGE_LANG, SDL_SCANCODE_F7);
Input::get()->bindKey(InputType::SHOWINFO, SDL_SCANCODE_F8);
Input::get()->bindKey(InputType::RESET, SDL_SCANCODE_F10);
Input::get()->bindKey(InputAction::SERVICE, SDL_SCANCODE_0);
Input::get()->bindKey(InputAction::EXIT, SDL_SCANCODE_ESCAPE);
Input::get()->bindKey(InputAction::PAUSE, SDL_SCANCODE_P);
Input::get()->bindKey(InputAction::WINDOW_DEC_SIZE, SDL_SCANCODE_F1);
Input::get()->bindKey(InputAction::WINDOW_INC_SIZE, SDL_SCANCODE_F2);
Input::get()->bindKey(InputAction::WINDOW_FULLSCREEN, SDL_SCANCODE_F3);
Input::get()->bindKey(InputAction::VIDEO_SHADERS, SDL_SCANCODE_F4);
Input::get()->bindKey(InputAction::VIDEO_INTEGER_SCALE, SDL_SCANCODE_F5);
Input::get()->bindKey(InputAction::MUTE, SDL_SCANCODE_F6);
Input::get()->bindKey(InputAction::AUTO_FIRE, SDL_SCANCODE_F7);
Input::get()->bindKey(InputAction::CHANGE_LANG, SDL_SCANCODE_F8);
Input::get()->bindKey(InputAction::RESET, SDL_SCANCODE_F10);
Input::get()->bindKey(InputAction::SHOW_INFO, SDL_SCANCODE_F12);
// Asigna botones a inputs
const int num_gamepads = Input::get()->getNumControllers();
for (int i = 0; i < num_gamepads; ++i)
const int NUM_GAMEPADS = Input::get()->getNumControllers();
for (int i = 0; i < NUM_GAMEPADS; ++i)
{
// Mando - Movimiento del jugador
Input::get()->bindGameControllerButton(i, InputType::UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
Input::get()->bindGameControllerButton(i, InputType::DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
Input::get()->bindGameControllerButton(i, InputType::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
Input::get()->bindGameControllerButton(i, InputType::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
Input::get()->bindGameControllerButton(i, InputAction::UP, SDL_CONTROLLER_BUTTON_DPAD_UP);
Input::get()->bindGameControllerButton(i, InputAction::DOWN, SDL_CONTROLLER_BUTTON_DPAD_DOWN);
Input::get()->bindGameControllerButton(i, InputAction::LEFT, SDL_CONTROLLER_BUTTON_DPAD_LEFT);
Input::get()->bindGameControllerButton(i, InputAction::RIGHT, SDL_CONTROLLER_BUTTON_DPAD_RIGHT);
Input::get()->bindGameControllerButton(i, InputType::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X);
Input::get()->bindGameControllerButton(i, InputType::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
Input::get()->bindGameControllerButton(i, InputType::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(i, InputAction::FIRE_LEFT, SDL_CONTROLLER_BUTTON_X);
Input::get()->bindGameControllerButton(i, InputAction::FIRE_CENTER, SDL_CONTROLLER_BUTTON_Y);
Input::get()->bindGameControllerButton(i, InputAction::FIRE_RIGHT, SDL_CONTROLLER_BUTTON_B);
Input::get()->bindGameControllerButton(i, InputType::START, SDL_CONTROLLER_BUTTON_START);
Input::get()->bindGameControllerButton(i, InputAction::START, SDL_CONTROLLER_BUTTON_START);
// Mando - Control del programa
Input::get()->bindGameControllerButton(i, InputType::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
Input::get()->bindGameControllerButton(i, InputAction::SERVICE, SDL_CONTROLLER_BUTTON_BACK);
}
// Mapea las asignaciones a los botones desde el archivo de configuración, si se da el caso
const size_t max_controllers = std::min(2, num_gamepads);
const size_t max_controllers = std::min(2, NUM_GAMEPADS);
for (size_t i = 0; i < max_controllers; ++i)
{
for (auto &controller : options.controllers)
@@ -220,16 +234,16 @@ void Director::bindInputs()
}
// Asigna botones a inputs desde otros inputs
for (int i = 0; i < num_gamepads; ++i)
for (int i = 0; i < NUM_GAMEPADS; ++i)
{
Input::get()->bindGameControllerButton(i, InputType::EXIT, InputType::START);
Input::get()->bindGameControllerButton(i, InputType::RESET, InputType::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, InputType::PAUSE, InputType::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, InputType::VIDEO_SHADERS, InputType::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, InputType::MUTE, InputType::LEFT);
Input::get()->bindGameControllerButton(i, InputType::SHOWINFO, InputType::RIGHT);
Input::get()->bindGameControllerButton(i, InputType::CONFIG, InputType::DOWN);
Input::get()->bindGameControllerButton(i, InputType::SWAP_CONTROLLERS, InputType::UP);
Input::get()->bindGameControllerButton(i, InputAction::EXIT, InputAction::START);
Input::get()->bindGameControllerButton(i, InputAction::RESET, InputAction::FIRE_CENTER);
Input::get()->bindGameControllerButton(i, InputAction::PAUSE, InputAction::FIRE_RIGHT);
Input::get()->bindGameControllerButton(i, InputAction::VIDEO_SHADERS, InputAction::FIRE_LEFT);
Input::get()->bindGameControllerButton(i, InputAction::MUTE, InputAction::LEFT);
Input::get()->bindGameControllerButton(i, InputAction::SHOW_INFO, InputAction::RIGHT);
Input::get()->bindGameControllerButton(i, InputAction::CONFIG, InputAction::DOWN);
Input::get()->bindGameControllerButton(i, InputAction::SWAP_CONTROLLERS, InputAction::UP);
}
// Guarda las asignaciones de botones en las opciones de los dos primeros mandos
@@ -283,28 +297,17 @@ bool Director::initSDL()
}
else
{
/*
// Muestra información de la pantalla
std::cout << "\nDisplay modes list:" << std::endl;
for (int i = 0; i < SDL_GetNumDisplayModes(0); ++i)
{
SDL_DisplayMode DM;
SDL_GetDisplayMode(0,i,&DM);
std::cout << " - " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
}
*/
// Obtiene información sobre la pantalla
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
options.video.window.max_size = std::min(DM.w / param.game.width, DM.h / param.game.height);
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
options.video.window.max_zoom = std::min(DM.w / param.game.width, DM.h / param.game.height);
options.video.window.zoom = std::min(options.video.window.zoom, options.video.window.max_zoom);
// Muestra información sobre el tamaño de la pantalla y de la ventana de juego
std::cout << "\nCurrent display mode: " << DM.w << "x" << DM.h << " @ " << DM.refresh_rate << "Hz" << std::endl;
std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.size << std::endl;
std::cout << "Window resolution : " << param.game.width << "x" << param.game.height << " x" << options.video.window.zoom << std::endl;
// Establece el filtro de la textura
if (!SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, std::to_string(static_cast<int>(options.video.filter)).c_str()))
@@ -312,15 +315,13 @@ bool Director::initSDL()
std::cout << "Warning: texture filtering not enabled!\n";
}
#ifndef NO_SHADERS
if (!SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl"))
{
std::cout << "Warning: opengl not enabled!\n";
}
#endif
// Crea la ventana
window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.size, param.game.height * options.video.window.size, SDL_WINDOW_HIDDEN);
window_ = SDL_CreateWindow(WINDOW_CAPTION, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, param.game.width * options.video.window.zoom, param.game.height * options.video.window.zoom, SDL_WINDOW_HIDDEN);
if (!window_)
{
std::cout << "Window could not be created!\nSDL Error: " << SDL_GetError() << std::endl;
@@ -335,10 +336,8 @@ bool Director::initSDL()
flags = SDL_RENDERER_PRESENTVSYNC;
}
#ifndef NO_SHADERS
// La aceleración se activa según el define
flags = flags | SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE;
#endif
renderer_ = SDL_CreateRenderer(window_, -1, flags);
@@ -352,6 +351,7 @@ bool Director::initSDL()
SDL_SetRenderDrawColor(renderer_, 0x00, 0x00, 0x00, 0xFF);
SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height);
SDL_RenderSetIntegerScale(renderer_, static_cast<SDL_bool>(options.video.integer_scale));
SDL_SetWindowFullscreen(window_, static_cast<Uint32>(options.video.mode));
SDL_SetRenderDrawBlendMode(renderer_, SDL_BLENDMODE_BLEND);
}
}
@@ -393,16 +393,16 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/sound/bubble4.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/bullet.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/clock.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/coffeeout.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/coffee_out.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/continue_clock.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/game_start.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/hiscore.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/itemdrop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/itempickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/hi_score_achieved.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/item_drop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/item_pickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/logo.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/notify.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/player_collision.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/powerball.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/power_ball_explosion.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/stage_change.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/tabe.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/title.wav", AssetType::SOUND);
@@ -411,6 +411,9 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/sound/voice_no.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/voice_power_up.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/walk.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/debian_drop.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/debian_pickup.wav", AssetType::SOUND);
Asset::get()->add(prefix + "/data/sound/tabe_hit.wav", AssetType::SOUND);
// Shaders
Asset::get()->add(prefix + "/data/shaders/crtpi_256.glsl", AssetType::DATA);
@@ -470,7 +473,12 @@ void Director::setFileList()
}
{ // Intro
Asset::get()->add(prefix + "/data/gfx/intro/intro.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro1.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro2.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro3.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro4.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro5.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/intro/intro6.png", AssetType::BITMAP);
}
{ // Logo
@@ -490,6 +498,8 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/gfx/item/item_clock.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_debian.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_debian.ani", AssetType::ANIMATION);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/gfx/item/item_coffee_machine.ani", AssetType::ANIMATION);
}
@@ -527,8 +537,6 @@ void Director::setFileList()
// Fuentes de texto
Asset::get()->add(prefix + "/data/font/8bithud.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/8bithud.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/nokia.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/nokia.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/smb2.gif", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/smb2_palette1.pal", AssetType::PALETTE);
Asset::get()->add(prefix + "/data/font/smb2.txt", AssetType::FONT);
@@ -536,6 +544,8 @@ void Director::setFileList()
Asset::get()->add(prefix + "/data/font/04b_25.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/04b_25_2x.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25_2x.txt", AssetType::FONT);
Asset::get()->add(prefix + "/data/font/04b_25_metal.png", AssetType::BITMAP);
Asset::get()->add(prefix + "/data/font/04b_25_grey.png", AssetType::BITMAP);
// Textos
Asset::get()->add(prefix + "/data/lang/es_ES.txt", AssetType::LANG);
@@ -544,7 +554,9 @@ void Director::setFileList()
// Si falta algun fichero, sale del programa
if (!Asset::get()->check())
{
throw std::runtime_error("Falta algun fichero");
}
}
// Comprueba los parametros del programa
@@ -696,7 +708,9 @@ void Director::runDemoGame()
// Ejecuta la sección init
void Director::runInit()
{
if (section::options == section::Options::RELOAD)
JA_StopMusic();
JA_StopChannel(-1);
if (section::options == section::Options::RELOAD || true)
{
Resource::get()->reload();
}
@@ -762,11 +776,6 @@ int Director::run()
// Habilita de nuevo los std::cout
std::cout.rdbuf(orig_buf);
#endif
#ifdef ARCADE
// Comprueba si ha de apagar el sistema
if (section::options == section::Options::QUIT_WITH_CONTROLLER)
shutdownSystem();
#endif
return (section::options == section::Options::QUIT_WITH_CONTROLLER) ? 1 : 0;
}
@@ -794,20 +803,23 @@ std::string Director::getLangFile(lang::Code code)
#ifdef ARCADE
// Apaga el sistema
void Director::shutdownSystem()
void Director::shutdownSystem(bool shouldShutdown)
{
if (shouldShutdown)
{
#ifdef _WIN32
// Apaga el sistema en Windows
system("shutdown /s /t 0");
// Apaga el sistema en Windows
system("shutdown /s /t 5");
#elif __APPLE__
// Apaga el sistema en macOS
system("sudo shutdown -h now");
// Apaga el sistema en macOS
system("sudo shutdown -h +0.1");
#elif __linux__
// Apaga el sistema en Linux
system("shutdown -h now");
// Apaga el sistema en Linux
system("sleep 5; shutdown -h now");
#else
// Sistema operativo no compatible
#error "Sistema operativo no soportado"
#endif
}
}
#endif // ARCADE

View File

@@ -74,7 +74,7 @@ private:
std::string getLangFile(lang::Code code);
#ifdef ARCADE
// Apaga el sistema
void shutdownSystem();
void shutdownSystem(bool shouldShutdown);
#endif
// Inicializa todo

View File

@@ -1,93 +1,159 @@
#include "enter_name.h"
#include <stddef.h> // Para size_t
#include <algorithm> // Para max, min
#include <stddef.h> // Para size_t
#include "utils.h" // Para trim
// Constructor
EnterName::EnterName()
{
init();
}
: character_list_(" ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()"),
character_index_{0} {}
// Inicializa el objeto
void EnterName::init()
void EnterName::init(const std::string &name)
{
// Obtiene el puntero al nombre
name_ = "A";
// No se pasa ningún nombre
if (name.empty())
{
name_ = "A";
position_ = 0;
position_overflow_ = false;
}
// Se pasa un nombre
else
{
name_ = name;
position_ = name_.length();
position_overflow_ = position_ >= MAX_NAME_LENGHT ? true : false;
}
// Inicia la lista de caracteres permitidos
character_list_ = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-+-*/=?¿<>!\"#$%&/()";
position_ = 0;
num_characters_ = static_cast<int>(character_list_.size());
// Pone la lista de indices para que refleje el nombre
updateCharacterIndex();
// Actualiza el nombre para que ocupe 8 espacios
updateName();
// Inicializa el vector de indices con el nombre y espacios
initCharacterIndex(name_);
}
// Incrementa la posición
void EnterName::incPosition()
{
position_++;
position_ = std::min(position_, NAME_LENGHT - 1);
checkIfPositionHasBeenUsed();
if (position_overflow_)
{
// Si ya estamos en overflow, no incrementamos más.
return;
}
++position_;
if (position_ >= MAX_NAME_LENGHT)
{
position_ = MAX_NAME_LENGHT; // Mantenemos en el índice máximo válido.
position_overflow_ = true; // Activamos el flag de overflow.
}
else if (position_ > 0) // No es necesario verificar position_ < MAX_NAME_LENGHT
{
// Copiamos el índice del carácter anterior si es posible.
character_index_[position_] = character_index_[position_ - 1];
}
else
{
// Si position_ es 0, inicializamos el carácter actual.
character_index_[position_] = 0;
}
updateNameFromCharacterIndex();
}
// Decrementa la posición
void EnterName::decPosition()
{
--position_;
position_ = std::max(position_, 0);
if (position_overflow_)
{
// Si estaba en overflow, lo desactivamos y mantenemos position_ en el máximo.
position_overflow_ = false;
position_ = MAX_NAME_LENGHT - 1;
}
else
{
if (position_ > 0)
{
--position_;
// Limpiamos el carácter siguiente si el índice es válido.
if (position_ + 1 < MAX_NAME_LENGHT)
{
character_index_[position_ + 1] = 0;
}
}
else
{
// Si position_ es 0, aseguramos que no vaya a ser negativo y limpiamos el carácter actual.
position_ = 0;
character_index_[position_] = 0;
}
// Si position_ es menor que NAME_LENGHT, aseguramos que el overflow esté desactivado.
if (position_ < MAX_NAME_LENGHT)
{
position_overflow_ = false;
}
}
updateNameFromCharacterIndex();
}
// Incrementa el índice
void EnterName::incIndex()
{
if (position_overflow_)
{
return;
}
++character_index_[position_];
if (character_index_[position_] >= num_characters_)
if (character_index_[position_] >= static_cast<int>(character_list_.size()))
{
character_index_[position_] = 0;
}
updateName();
updateNameFromCharacterIndex();
}
// Decrementa el índice
void EnterName::decIndex()
{
if (position_overflow_)
{
return;
}
--character_index_[position_];
if (character_index_[position_] < 0)
{
character_index_[position_] = num_characters_ - 1;
character_index_[position_] = character_list_.size() - 1;
}
updateName();
updateNameFromCharacterIndex();
}
// Actualiza el nombre a partir de la lista de índices
void EnterName::updateName()
void EnterName::updateNameFromCharacterIndex()
{
name_.clear();
for (int i = 0; i < NAME_LENGHT; ++i)
for (int i = 0; i < MAX_NAME_LENGHT; ++i)
{
name_.push_back(character_list_[character_index_[i]]);
}
name_ = trim(name_);
}
// Actualiza la variable
void EnterName::updateCharacterIndex()
void EnterName::initCharacterIndex(const std::string &name)
{
// Rellena de espacios y marca como no usados
for (size_t i = 0; i < NAME_LENGHT; ++i)
// Rellena de espacios
for (size_t i = 0; i < MAX_NAME_LENGHT; ++i)
{
character_index_[i] = 0;
position_has_been_used_[i] = false;
}
// Coloca los índices en función de los caracteres que forman el nombre
for (size_t i = 0; i < name_.size(); ++i)
for (size_t i = 0; i < name.substr(0, MAX_NAME_LENGHT).size(); ++i)
{
character_index_[i] = findIndex(name_.at(i));
position_has_been_used_[i] = true;
character_index_[i] = findIndex(name.at(i));
}
}
@@ -95,31 +161,11 @@ void EnterName::updateCharacterIndex()
int EnterName::findIndex(char character) const
{
for (size_t i = 0; i < character_list_.size(); ++i)
{
if (character == character_list_.at(i))
{
return i;
}
}
return 0;
}
// Obtiene el nombre
std::string EnterName::getName() const
{
return name_;
}
// Obtiene la posición que se está editando
int EnterName::getPosition() const
{
return position_;
}
// Comprueba la posición y copia el caracter si es necesario
void EnterName::checkIfPositionHasBeenUsed()
{
auto used = position_has_been_used_[position_];
if (!used && position_ > 0)
character_index_[position_] = character_index_[position_ - 1];
position_has_been_used_[position_] = true;
updateName();
}

View File

@@ -1,8 +1,10 @@
#pragma once
#include <string>
#include <array>
#include "utils.h"
constexpr int NAME_LENGHT = 6;
constexpr int MAX_NAME_LENGHT = 6;
/*
Un array, "characterList", contiene la lista de caracteres
@@ -16,25 +18,21 @@ constexpr int NAME_LENGHT = 6;
class EnterName
{
private:
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int position_; // Posición a editar del nombre
int num_characters_; // Cantidad de caracteres de la lista de caracteres
int character_index_[NAME_LENGHT]; // Indice de la lista para cada uno de los caracteres que forman el nombre
bool position_has_been_used_[NAME_LENGHT]; // Indica si en esa posición se ha puesto ya alguna letra. Se utiliza para replicar la letra anterior la primera vez
std::string character_list_; // Lista de todos los caracteres permitidos
std::string name_; // Nombre introducido
int position_ = 0; // Posición a editar del nombre
bool position_overflow_ = false; // Indica si hemos incrementado la posición más allá del límite
std::array<int, MAX_NAME_LENGHT> character_index_; // Indice de la lista para cada uno de los caracteres que forman el nombre
// Actualiza el nombre a partir de la lista de índices
void updateName();
void updateNameFromCharacterIndex();
// Actualiza la variable
void updateCharacterIndex();
void initCharacterIndex(const std::string &name);
// Encuentra el indice de un caracter en "characterList"
int findIndex(char character) const;
// Comprueba la posición y copia el caracter si es necesario
void checkIfPositionHasBeenUsed();
public:
// Constructor
EnterName();
@@ -43,7 +41,7 @@ public:
~EnterName() = default;
// Inicializa el objeto
void init();
void init(const std::string &name = "");
// Incrementa la posición
void incPosition();
@@ -57,9 +55,9 @@ public:
// Decrementa el índice
void decIndex();
// Obtiene el nombre
std::string getName() const;
// Obtiene la posición que se está editando
int getPosition() const;
// Getters
std::string getFinalName() const { return trim(name_.substr(0, position_)); }
std::string getCurrentName() const { return trim(name_); }
int getPosition() const { return position_; }
bool getPositionOverflow() const { return position_overflow_; }
};

View File

@@ -22,7 +22,6 @@ Fade::Fade()
Fade::~Fade()
{
SDL_DestroyTexture(backbuffer_);
backbuffer_ = nullptr;
}
// Inicializa las variables
@@ -141,11 +140,11 @@ void Fade::update()
SDL_SetRenderDrawColor(renderer_, r_, g_, b_, a_);
// Dibuja el cuadrado correspondiente
const int index = std::min(counter_ / fade_random_squares_delay_, (num_squares_width_ * num_squares_height_) - 1);
const int INDEX = std::min(counter_ / fade_random_squares_delay_, (num_squares_width_ * num_squares_height_) - 1);
for (int i = 0; i < fade_random_squares_mult_; ++i)
{
const int index2 = std::min(index * fade_random_squares_mult_ + i, (int)square_.size() - 1);
SDL_RenderFillRect(renderer_, &square_[index2]);
const int INDEX2 = std::min(INDEX * fade_random_squares_mult_ + i, (int)square_.size() - 1);
SDL_RenderFillRect(renderer_, &square_[INDEX2]);
}
// Deja el renderizador como estaba

View File

@@ -1,9 +1,9 @@
#pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint8, Uint16
#include <vector> // para vector
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint8, Uint16
#include <vector> // Para vector
// Tipos de fundido
enum class FadeType : Uint8

View File

@@ -1,6 +1,6 @@
#include "game.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <SDL2/SDL_events.h> // Para SDL_Event, SDL_PollEvent, SDL_KEYDOWN
#include <SDL2/SDL_keycode.h> // Para SDLK_1, SDLK_2, SDLK_3, SDLK_4
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
@@ -14,15 +14,14 @@
#include "balloon.h" // Para Balloon, BALLOON_SPEED
#include "balloon_manager.h" // Para BalloonManager
#include "bullet.h" // Para Bullet, BulletType, BulletMoveStatus
#include "enter_name.h" // Para NAME_LENGHT
#include "fade.h" // Para Fade, FadeType, FadeMode
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check, update
#include "input.h" // Para InputType, Input, INPUT_DO_NOT_ALL...
#include "input.h" // Para InputAction, Input, INPUT_DO_NOT_ALL...
#include "item.h" // Para Item, ItemType
#include "jail_audio.h" // Para JA_PlaySound, JA_GetMusicState
#include "lang.h" // Para getText
#include "manage_hiscore_table.h" // Para ManageHiScoreTable, HiScoreEntry
#include "mouse.h" // Para handleEvent
#include "notifier.h" // Para Notifier
#include "param.h" // Para Param, param, ParamGame, ParamFade
#include "path_sprite.h" // Para Path, PathSprite, createPath, Path...
@@ -30,10 +29,10 @@
#include "resource.h" // Para Resource
#include "scoreboard.h" // Para Scoreboard, ScoreboardMode, SCOREB...
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, AttractMode, Options
#include "section.h" // Para Name, name, AttractMode, attract_mode
#include "smart_sprite.h" // Para SmartSprite
#include "stage.h" // Para number, get, Stage, total_power
#include "tabe.h" // Para Tabe
#include "tabe.h" // Para Tabe, TabeState
#include "text.h" // Para Text
#include "texture.h" // Para Texture
@@ -140,6 +139,7 @@ void Game::setResources()
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_powerup"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_one_hit"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_stop"));
game_text_textures_.emplace_back(Resource::get()->getTexture("game_text_100000_points"));
}
// Texturas - Items
@@ -149,6 +149,7 @@ void Game::setResources()
item_textures_.emplace_back(Resource::get()->getTexture("item_points3_pacmar.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_clock.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_debian.png"));
item_textures_.emplace_back(Resource::get()->getTexture("item_coffee_machine.png"));
}
@@ -181,6 +182,7 @@ void Game::setResources()
item_animations_.emplace_back(Resource::get()->getAnimation("item_points3_pacmar.ani"));
item_animations_.emplace_back(Resource::get()->getAnimation("item_clock.ani"));
item_animations_.emplace_back(Resource::get()->getAnimation("item_coffee.ani"));
item_animations_.emplace_back(Resource::get()->getAnimation("item_debian.ani"));
item_animations_.emplace_back(Resource::get()->getAnimation("item_coffee_machine.ani"));
}
}
@@ -202,7 +204,7 @@ void Game::updateHiScore()
if (hi_score_achieved_ == false)
{
hi_score_achieved_ = true;
JA_PlaySound(Resource::get()->getSound("hiscore.wav"));
JA_PlaySound(Resource::get()->getSound("hi_score_achieved.wav"));
}
}
}
@@ -280,6 +282,13 @@ void Game::updateStage()
createMessage(paths, text->writeToTexture(caption, 1, -4));
}
}
// Modifica el color de fondo al llegar a la Fase 10
if (Stage::number == 9)
{
background_->setColor(Color(0xdd, 0x19, 0x1d).darken());
background_->setAlpha(96);
}
}
}
@@ -297,7 +306,7 @@ void Game::updateGameStateGameOver()
updateSmartSprites();
updatePathSprites();
updateTimeStopped();
checkBulletBalloonCollision();
checkBulletCollision();
cleanVectors();
if (game_over_counter_ > 0)
@@ -319,8 +328,11 @@ void Game::updateGameStateGameOver()
if (fade_out_->isEnabled())
{
const float vol = static_cast<float>(64 * (100 - fade_out_->getValue())) / 100.0f;
JA_SetSoundVolume(to_JA_volume(static_cast<int>(vol)));
if (options.audio.enabled)
{
const float vol = static_cast<float>(64 * (100 - fade_out_->getValue())) / 100.0f;
JA_SetSoundVolume(to_JA_volume(static_cast<int>(vol)));
}
}
if (fade_out_->hasEnded())
@@ -335,14 +347,21 @@ void Game::updateGameStateGameOver()
// La partida ha terminado con la derrota de los jugadores
section::name = section::Name::HI_SCORE_TABLE;
}
JA_StopChannel(-1);
JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
section::options = section::Options::HI_SCORE_AFTER_PLAYING;
if (options.audio.enabled)
{
JA_StopChannel(-1);
JA_SetSoundVolume(to_JA_volume(options.audio.sound.volume));
}
}
}
// Gestiona eventos para el estado del final del juego
void Game::updateGameStateCompleted()
{
constexpr int START_CELEBRATIONS = 400;
constexpr int END_CELEBRATIONS = START_CELEBRATIONS + 300;
updatePlayers();
updateScoreboard();
updateBackground();
@@ -362,11 +381,12 @@ void Game::updateGameStateCompleted()
balloon_manager_->destroyAllBalloons(); // Destruye a todos los globos
destroyAllItems(); // Destruye todos los items
Stage::power = 0; // Vuelve a dejar el poder a cero, por lo que hubiera podido subir al destruir todos los globos
background_->setAlpha(0); // Elimina el tono rojo de las últimas pantallas
}
// Comienza las celebraciones
// Muestra el mensaje de felicitación y da los puntos a los jugadores
if (game_completed_counter_ == 200)
if (game_completed_counter_ == START_CELEBRATIONS)
{
createMessage({paths_.at(4), paths_.at(5)}, Resource::get()->getTexture("game_text_congratulations"));
createMessage({paths_.at(6), paths_.at(7)}, Resource::get()->getTexture("game_text_1000000_points"));
@@ -386,7 +406,7 @@ void Game::updateGameStateCompleted()
}
// Termina las celebraciones
if (game_completed_counter_ == 500)
if (game_completed_counter_ == END_CELEBRATIONS)
{
for (auto &player : players_)
{
@@ -462,37 +482,41 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
case ItemType::DISK:
{
player->addScore(1000);
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[0]->getWidth()) / 2;
createItemText(x, game_text_textures_[0]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(0)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(0));
JA_PlaySound(Resource::get()->getSound("item_pickup.wav"));
break;
}
case ItemType::GAVINA:
{
player->addScore(2500);
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[1]->getWidth()) / 2;
createItemText(x, game_text_textures_[1]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(1)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(1));
JA_PlaySound(Resource::get()->getSound("item_pickup.wav"));
break;
}
case ItemType::PACMAR:
{
player->addScore(5000);
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[2]->getWidth()) / 2;
createItemText(x, game_text_textures_[2]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(2));
JA_PlaySound(Resource::get()->getSound("item_pickup.wav"));
break;
}
case ItemType::DEBIAN:
{
player->addScore(100000);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(6)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(6));
JA_PlaySound(Resource::get()->getSound("debian_pickup.wav"));
break;
}
case ItemType::CLOCK:
{
enableTimeStopItem();
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[5]->getWidth()) / 2;
createItemText(x, game_text_textures_[5]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(5)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(5));
JA_PlaySound(Resource::get()->getSound("item_pickup.wav"));
break;
}
case ItemType::COFFEE:
@@ -500,18 +524,14 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
if (player->getCoffees() == 2)
{
player->addScore(5000);
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[2]->getWidth()) / 2;
createItemText(x, game_text_textures_[2]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(2)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(2));
}
else
{
player->giveExtraHit();
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[4]->getWidth()) / 2;
createItemText(x, game_text_textures_[4]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(4)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(4));
}
JA_PlaySound(Resource::get()->getSound("voice_coffee.wav"));
break;
@@ -520,10 +540,8 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
{
player->setPowerUp();
coffee_machine_enabled_ = false;
const auto x =
item->getPosX() +
(item->getWidth() - game_text_textures_[3]->getWidth()) / 2;
createItemText(x, game_text_textures_[3]);
const auto x = item->getPosX() + (item->getWidth() - game_text_textures_.at(3)->getWidth()) / 2;
createItemText(x, game_text_textures_.at(3));
JA_PlaySound(Resource::get()->getSound("voice_power_up.wav"));
break;
}
@@ -532,18 +550,46 @@ void Game::checkPlayerItemCollision(std::shared_ptr<Player> &player)
}
updateHiScore();
JA_PlaySound(Resource::get()->getSound("itempickup.wav"));
item->disable();
}
}
}
}
// Comprueba y procesa la colisión entre las balas y los globos
void Game::checkBulletBalloonCollision()
// Comprueba y procesa la colisión de las balas
void Game::checkBulletCollision()
{
for (auto &bullet : bullets_)
{
// Comprueba la colisión con el Tabe
if (bullet->isEnabled() && tabe_->isEnabled())
if (checkCollision(bullet->getCollider(), tabe_->getCollider()))
{
tabe_->setState(TabeState::HIT);
bullet->disable();
auto pos = tabe_->getCollider();
if (tabe_->tryToGetBonus())
{
createItem(ItemType::DEBIAN, pos.x, pos.y);
JA_PlaySound(Resource::get()->getSound("debian_drop.wav"));
}
else
{
if (rand() % 3 == 0)
{
createItem(ItemType::COFFEE, pos.x, pos.y);
// JA_PlaySound(Resource::get()->getSound("item_drop.wav"));
}
else
{
// JA_PlaySound(Resource::get()->getSound("tabe_hit.wav"));
}
JA_PlaySound(Resource::get()->getSound("tabe_hit.wav"));
}
break;
}
// Comprueba la colisión con los globos
for (auto &balloon : balloon_manager_->getBalloons())
{
if (balloon->isEnabled() && (!balloon->isInvulnerable()) && bullet->isEnabled())
@@ -560,7 +606,7 @@ void Game::checkBulletBalloonCollision()
if (dropped_item != ItemType::COFFEE_MACHINE)
{
createItem(dropped_item, balloon->getPosX(), balloon->getPosY());
JA_PlaySound(Resource::get()->getSound("itemdrop.wav"));
JA_PlaySound(Resource::get()->getSound("item_drop.wav"));
}
else
{
@@ -745,7 +791,7 @@ void Game::createItemText(int x, std::shared_ptr<Texture> texture)
const auto h = texture->getHeight();
const int y0 = param.game.play_area.rect.h - h;
const int y1 = 155;
const int y1 = 160 - (h / 2);
const int y2 = -h;
// Ajusta para que no se dibuje fuera de pantalla
@@ -865,7 +911,7 @@ void Game::killPlayer(std::shared_ptr<Player> &player)
// Lo pierde
player->removeExtraHit();
throwCoffee(player->getPosX() + (player->getWidth() / 2), player->getPosY() + (player->getHeight() / 2));
JA_PlaySound(Resource::get()->getSound("coffeeout.wav"));
JA_PlaySound(Resource::get()->getSound("coffee_out.wav"));
screen_->shake();
}
else
@@ -893,28 +939,34 @@ void Game::updateTimeStopped()
if (time_stopped_counter_ > 120)
{
if (time_stopped_counter_ % 30 == 0)
{
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
}
else
{
if (time_stopped_counter_ % 15 == 0)
JA_PlaySound(Resource::get()->getSound("clock.wav"));
if (time_stopped_counter_ % 30 == 0)
{
balloon_manager_->normalColorsToAllBalloons();
if (time_stopped_counter_ % 30 == 15)
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
else if (time_stopped_counter_ % 30 == 15)
{
balloon_manager_->reverseColorsToAllBalloons();
JA_PlaySound(Resource::get()->getSound("clock.wav"));
}
}
}
else
{
disableTimeStopItem();
}
}
// Actualiza el juego
void Game::update()
{
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
ticks_ = SDL_GetTicks();
@@ -1173,15 +1225,7 @@ void Game::checkEvents()
SDL_Event event;
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
else if (event.type == SDL_WINDOWEVENT)
if (event.type == SDL_WINDOWEVENT)
{
switch (event.window.event)
{
@@ -1195,104 +1239,19 @@ void Game::checkEvents()
pause(false);
break;
}
case SDL_WINDOWEVENT_SIZE_CHANGED:
{
reloadTextures();
break;
}
default:
break;
}
}
#ifdef DEBUG
else if (event.type == SDL_KEYDOWN && event.key.repeat == 0)
{
switch (event.key.keysym.sym)
{
case SDLK_1: // Crea una powerball
{
balloon_manager_->createPowerBall();
break;
}
case SDLK_2: // Crea dos globos gordos
{
balloon_manager_->createTwoBigBalloons();
}
break;
case SDLK_3: // Activa el modo para pasar el juego automaticamente
{
auto_pop_balloons_ = !auto_pop_balloons_;
Notifier::get()->showText({"auto advance: " + boolToString(auto_pop_balloons_)});
balloon_manager_->destroyAllBalloons();
balloon_manager_->setDeployBalloons(!auto_pop_balloons_);
break;
}
case SDLK_4: // Suelta un item
{
createItem(ItemType::CLOCK, players_.at(0)->getPosX(), players_.at(0)->getPosY() - 40);
break;
}
case SDLK_5: // Crea un PathSprite
{
const int x = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2;
createItemText(x, game_text_textures_.at(3));
break;
}
case SDLK_6: // Crea un mensaje
{
createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready"));
break;
}
case SDLK_7: // Flash
{
screen_->flash(flash_color, 3);
break;
}
case SDLK_8:
{
for (auto player : players_)
{
if (player->isPlaying())
{
createItem(ItemType::COFFEE_MACHINE, player->getPosX(), param.game.game_area.rect.y - param.game.coffee_machine_h);
break;
}
}
break;
}
case SDLK_9:
{
tabe_->enable();
break;
}
default:
break;
}
}
checkDebugEvents(event);
#endif
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
// Recarga las texturas
void Game::reloadTextures()
{
for (auto &texture : item_textures_)
texture->reLoad();
for (auto &textures : player_textures_)
for (auto &texture : textures)
texture->reLoad();
for (auto &texture : game_text_textures_)
texture->reLoad();
bullet_texture_->reLoad();
background_->reloadTextures();
}
// Actualiza el marcador
void Game::updateScoreboard()
{
@@ -1320,11 +1279,11 @@ void Game::pause(bool value)
}
// Añade una puntuación a la tabla de records
void Game::addScoreToScoreBoard(const std::string &name, int score)
void Game::addScoreToScoreBoard(const std::shared_ptr<Player> &player)
{
const auto entry = HiScoreEntry(trim(name), score);
const auto entry = HiScoreEntry(trim(player->getRecordName()), player->getScore(), player->get1CC());
auto manager = std::make_unique<ManageHiScoreTable>(options.game.hi_score_table);
manager->add(entry);
options.game.last_hi_score_entry.at(player->getId() - 1) = manager->add(entry);
manager->saveToFile(asset_->get("score.bin"));
hi_score_.name = options.game.hi_score_table.front().name;
}
@@ -1405,15 +1364,17 @@ void Game::checkPauseInput()
{
// Comprueba los mandos
for (int i = 0; i < input_->getNumControllers(); ++i)
if (input_->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
input_->checkInput(InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
if (input_->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
input_->checkInput(InputAction::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
pause(!paused_);
return;
}
}
// Comprueba el teclado
if (input_->checkInput(InputType::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (input_->checkInput(InputAction::PAUSE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
pause(!paused_);
return;
@@ -1427,7 +1388,8 @@ void Game::handleDemoMode()
for (const auto &player : players_)
{
if (player->isPlaying())
{ // Maneja el input específico del jugador en modo demo.
{
// Maneja el input específico del jugador en modo demo.
handleDemoPlayerInput(player, index);
}
@@ -1448,15 +1410,15 @@ void Game::handleDemoPlayerInput(const std::shared_ptr<Player> &player, int inde
if (demoData.left == 1)
{
player->setInput(InputType::LEFT);
player->setInput(InputAction::LEFT);
}
else if (demoData.right == 1)
{
player->setInput(InputType::RIGHT);
player->setInput(InputAction::RIGHT);
}
else if (demoData.no_input == 1)
{
player->setInput(InputType::NONE);
player->setInput(InputAction::NONE);
}
if (demoData.fire == 1)
@@ -1478,8 +1440,8 @@ void Game::handleFireInput(const std::shared_ptr<Player> &player, BulletType bul
{
if (player->canFire())
{
player->setInput(bulletType == BulletType::UP ? InputType::FIRE_CENTER : bulletType == BulletType::LEFT ? InputType::FIRE_LEFT
: InputType::FIRE_RIGHT);
player->setInput(bulletType == BulletType::UP ? InputAction::FIRE_CENTER : bulletType == BulletType::LEFT ? InputAction::FIRE_LEFT
: InputAction::FIRE_RIGHT);
createBullet(player->getPosX() + (player->getWidth() / 2) - 6, player->getPosY() + (player->getHeight() / 2), bulletType, player->isPowerUp(), player->getId());
JA_PlaySound(Resource::get()->getSound("bullet.wav"));
@@ -1505,7 +1467,7 @@ void Game::handlePlayersInput()
// Gestiona la continuación del jugador.
handlePlayerContinue(player);
}
else if (player->isEnteringName() || player->isEnteringNameGameCompleted())
else if (player->isEnteringName() || player->isEnteringNameGameCompleted() || player->isShowingName())
{
// Gestiona la introducción del nombre del jugador.
handleNameInput(player);
@@ -1519,23 +1481,23 @@ void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player)
const auto &controller = options.controllers.at(player->getController());
const bool autofire = player->isPowerUp() || options.game.autofire;
if (input_->checkInput(InputType::LEFT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
if (input_->checkInput(InputAction::LEFT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
{
player->setInput(InputType::LEFT);
player->setInput(InputAction::LEFT);
#ifdef RECORDING
demo_.keys.left = 1;
#endif
}
else if (input_->checkInput(InputType::RIGHT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
else if (input_->checkInput(InputAction::RIGHT, INPUT_ALLOW_REPEAT, controller.type, controller.index))
{
player->setInput(InputType::RIGHT);
player->setInput(InputAction::RIGHT);
#ifdef RECORDING
demo_.keys.right = 1;
#endif
}
else
{
player->setInput(InputType::NONE);
player->setInput(InputAction::NONE);
#ifdef RECORDING
demo_.keys.no_input = 1;
#endif
@@ -1547,21 +1509,21 @@ void Game::handleNormalPlayerInput(const std::shared_ptr<Player> &player)
// Procesa las entradas de disparo del jugador, permitiendo disparos automáticos si está habilitado.
void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire, int controllerIndex)
{
if (input_->checkInput(InputType::FIRE_CENTER, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
if (input_->checkInput(InputAction::FIRE_CENTER, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
handleFireInput(player, BulletType::UP);
#ifdef RECORDING
demo_.keys.fire = 1;
#endif
}
else if (input_->checkInput(InputType::FIRE_LEFT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::FIRE_LEFT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
handleFireInput(player, BulletType::LEFT);
#ifdef RECORDING
demo_.keys.fire_left = 1;
#endif
}
else if (input_->checkInput(InputType::FIRE_RIGHT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::FIRE_RIGHT, autofire, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
handleFireInput(player, BulletType::RIGHT);
#ifdef RECORDING
@@ -1574,17 +1536,21 @@ void Game::handleFireInputs(const std::shared_ptr<Player> &player, bool autofire
void Game::handlePlayerContinue(const std::shared_ptr<Player> &player)
{
const auto controllerIndex = player->getController();
if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->setPlayingState(PlayerState::PLAYING);
player->addCredit();
}
// Disminuye el contador de continuación si se presiona cualquier botón de disparo.
if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->decContinueCounter();
if (player->getContinueCounter() < 7)
{
player->decContinueCounter();
}
}
}
@@ -1592,40 +1558,42 @@ void Game::handlePlayerContinue(const std::shared_ptr<Player> &player)
void Game::handleNameInput(const std::shared_ptr<Player> &player)
{
const auto controllerIndex = player->getController();
if (input_->checkInput(InputType::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputType::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
if (input_->checkInput(InputAction::FIRE_LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputAction::FIRE_CENTER, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index) ||
input_->checkInput(InputAction::FIRE_RIGHT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
if (player->getRecordNamePos() == NAME_LENGHT - 1)
if (player->isShowingName())
{
player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore());
const auto state = player->getPlayingState();
player->setPlayingState(state == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::LEAVING_SCREEN);
player->setPlayingState(PlayerState::CONTINUE);
}
else if (player->getEnterNamePositionOverflow())
{
player->setInput(InputAction::START);
addScoreToScoreBoard(player);
player->setPlayingState(PlayerState::SHOWING_NAME);
}
else
{
player->setInput(InputType::RIGHT);
player->setInput(InputAction::RIGHT);
}
}
else if (input_->checkInput(InputType::UP, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::UP, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->setInput(InputType::UP);
player->setInput(InputAction::UP);
}
else if (input_->checkInput(InputType::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::DOWN, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->setInput(InputType::DOWN);
player->setInput(InputAction::DOWN);
}
else if (input_->checkInput(InputType::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::LEFT, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->setInput(InputType::LEFT);
player->setInput(InputAction::LEFT);
}
else if (input_->checkInput(InputType::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
else if (input_->checkInput(InputAction::START, INPUT_DO_NOT_ALLOW_REPEAT, options.controllers[controllerIndex].type, options.controllers[controllerIndex].index))
{
player->setInput(InputType::START);
addScoreToScoreBoard(player->getRecordName(), player->getScore());
const auto state = player->getPlayingState();
player->setPlayingState(state == PlayerState::ENTERING_NAME ? PlayerState::CONTINUE : PlayerState::LEAVING_SCREEN);
player->setInput(InputAction::START);
addScoreToScoreBoard(player);
player->setPlayingState(PlayerState::SHOWING_NAME);
}
}
@@ -1887,7 +1855,7 @@ void Game::updateGameStateEnteringPlayer()
updatePlayers();
updateScoreboard();
updateBackground();
for (auto player : players_)
for (const auto &player : players_)
{
if (player->isPlaying())
{
@@ -1941,7 +1909,7 @@ void Game::updateGameStatePlaying()
updatePathSprites();
updateTimeStopped();
updateHelper();
checkBulletBalloonCollision();
checkBulletCollision();
updateMenace();
checkAndUpdateBalloonSpeed();
checkState();
@@ -2013,4 +1981,79 @@ void Game::setState(GameState state)
{
state_ = state;
counter_ = 0;
}
}
#ifdef DEBUG
// Comprueba los eventos en el modo DEBUG
void Game::checkDebugEvents(const SDL_Event &event)
{
if (event.type == SDL_KEYDOWN && event.key.repeat == 0)
{
switch (event.key.keysym.sym)
{
case SDLK_1: // Crea una powerball
{
balloon_manager_->createPowerBall();
break;
}
case SDLK_2: // Crea dos globos gordos
{
balloon_manager_->createTwoBigBalloons();
break;
}
case SDLK_3: // Activa el modo para pasar el juego automaticamente
{
auto_pop_balloons_ = !auto_pop_balloons_;
Notifier::get()->show({"auto advance: " + boolToString(auto_pop_balloons_)});
if (auto_pop_balloons_)
{
balloon_manager_->destroyAllBalloons();
}
balloon_manager_->setDeployBalloons(!auto_pop_balloons_);
break;
}
case SDLK_4: // Suelta un item
{
createItem(ItemType::CLOCK, players_.at(0)->getPosX(), players_.at(0)->getPosY() - 40);
break;
}
case SDLK_5: // 5.000
{
const int X = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2;
createItemText(X, game_text_textures_.at(2));
break;
}
case SDLK_6: // Crea un mensaje
{
createMessage({paths_.at(0), paths_.at(1)}, Resource::get()->getTexture("game_text_get_ready"));
break;
}
case SDLK_7: // 100.000
{
const int X = players_.at(0)->getPosX() + (players_.at(0)->getWidth() - game_text_textures_[3]->getWidth()) / 2;
createItemText(X, game_text_textures_.at(6));
break;
}
case SDLK_8:
{
for (const auto &player : players_)
{
if (player->isPlaying())
{
createItem(ItemType::COFFEE_MACHINE, player->getPosX(), param.game.game_area.rect.y - param.game.coffee_machine_h);
break;
}
}
break;
}
case SDLK_9:
{
tabe_->enable();
break;
}
default:
break;
}
}
}
#endif

View File

@@ -2,6 +2,7 @@
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_KEYDOWN
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
@@ -173,6 +174,9 @@ private:
GameState state_ = GameState::FADE_IN; // Estado
#ifdef DEBUG
bool auto_pop_balloons_ = false; // Si es true, incrementa automaticamente los globos explotados
// Comprueba los eventos en el modo DEBUG
void checkDebugEvents(const SDL_Event &event);
#endif
// Actualiza el juego
@@ -211,8 +215,8 @@ private:
// Comprueba la colisión entre el jugador y los items
void checkPlayerItemCollision(std::shared_ptr<Player> &player);
// Comprueba la colisión entre las balas y los globos
void checkBulletBalloonCollision();
// Comprueba y procesa la colisión de las balas
void checkBulletCollision();
// Mueve las balas activas
void updateBullets();
@@ -298,9 +302,6 @@ private:
// Comprueba si todos los jugadores han terminado de jugar
bool allPlayersAreNotPlaying();
// Recarga las texturas
void reloadTextures();
// Actualiza el marcador
void updateScoreboard();
@@ -311,7 +312,7 @@ private:
void pause(bool value);
// Añade una puntuación a la tabla de records
void addScoreToScoreBoard(const std::string &name, int score);
void addScoreToScoreBoard(const std::shared_ptr<Player> &player);
// Saca del estado de GAME OVER al jugador si el otro está activo
void checkAndUpdatePlayerStatus(int active_player_index, int inactive_player_index);

View File

@@ -244,15 +244,6 @@ bool GameLogo::hasFinished() const
return post_finished_counter_ == 0;
}
// Recarga las texturas
void GameLogo::reLoad()
{
dust_texture_->reLoad();
coffee_texture_->reLoad();
crisis_texture_->reLoad();
arcade_edition_texture_->reLoad();
}
// Calcula el desplazamiento vertical inicial
int GameLogo::getInitialVerticalDesp()
{

View File

@@ -25,7 +25,7 @@ private:
int lenght = 8; // Cantidad de desplazamientos a realizar
int remaining = lenght; // Cantidad de desplazamientos pendientes a realizar
int counter = delay; // Contador para el retraso
int origin; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
int origin = 0; // Valor inicial de la pantalla para dejarla igual tras el desplazamiento
// Constructor por defect
Shake() = default;
@@ -61,9 +61,9 @@ private:
std::unique_ptr<Sprite> arcade_edition_sprite_; // Sprite con los graficos de "Arcade Edition"
// Variables
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
float zoom_; // Zoom aplicado al texto "ARCADE EDITION"
int x_; // Posición donde dibujar el logo
int y_; // Posición donde dibujar el logo
float zoom_ = 1.0f; // Zoom aplicado al texto "ARCADE EDITION"
int post_finished_counter_ = 1; // Contador final una vez terminada las animaciones de los logos
Status coffee_crisis_status_ = Status::DISABLED; // Estado en el que se encuentra el texto "COFFEE CRISIS"
@@ -94,7 +94,4 @@ public:
// Indica si ha terminado la animación
bool hasFinished() const;
// Recarga las texturas
void reLoad();
};

View File

@@ -1,479 +0,0 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#define EXTENSION_INTRODUCER 0x21
#define IMAGE_DESCRIPTOR 0x2C
#define TRAILER 0x3B
#define GRAPHIC_CONTROL 0xF9
#define APPLICATION_EXTENSION 0xFF
#define COMMENT_EXTENSION 0xFE
#define PLAINTEXT_EXTENSION 0x01
#define READ(dst, size) memcpy(dst, buffer, size); buffer += size
typedef struct
{
unsigned short width;
unsigned short height;
unsigned char fields;
unsigned char background_color_index;
unsigned char pixel_aspect_ratio;
}
screen_descriptor_t;
typedef struct
{
unsigned char r;
unsigned char g;
unsigned char b;
}
rgb;
typedef struct
{
unsigned short image_left_position;
unsigned short image_top_position;
unsigned short image_width;
unsigned short image_height;
unsigned char fields;
}
image_descriptor_t;
typedef struct
{
unsigned char byte;
int prev;
int len;
}
dictionary_entry_t;
typedef struct
{
unsigned char extension_code;
unsigned char block_size;
}
extension_t;
typedef struct
{
unsigned char fields;
unsigned short delay_time;
unsigned char transparent_color_index;
}
graphic_control_extension_t;
typedef struct
{
unsigned char application_id[ 8 ];
unsigned char version[ 3 ];
}
application_extension_t;
typedef struct
{
unsigned short left;
unsigned short top;
unsigned short width;
unsigned short height;
unsigned char cell_width;
unsigned char cell_height;
unsigned char foreground_color;
unsigned char background_color;
}
plaintext_extension_t;
//static unsigned short width = 0;
//static unsigned short height = 0;
//static unsigned char* uncompressed_data = NULL;
void uncompress( int code_length,
const unsigned char *input,
int input_length,
unsigned char *out )
{
//int maxbits;
int i, bit;
int code, prev = -1;
dictionary_entry_t *dictionary;
int dictionary_ind;
unsigned int mask = 0x01;
int reset_code_length;
int clear_code; // This varies depending on code_length
int stop_code; // one more than clear code
int match_len;
clear_code = 1 << ( code_length );
stop_code = clear_code + 1;
// To handle clear codes
reset_code_length = code_length;
// Create a dictionary large enough to hold "code_length" entries.
// Once the dictionary overflows, code_length increases
dictionary = ( dictionary_entry_t * )
malloc( sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
// Initialize the first 2^code_len entries of the dictionary with their
// indices. The rest of the entries will be built up dynamically.
// Technically, it shouldn't be necessary to initialize the
// dictionary. The spec says that the encoder "should output a
// clear code as the first code in the image data stream". It doesn't
// say must, though...
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
// 2^code_len + 1 is the special "end" code; don't give it an entry here
dictionary_ind++;
dictionary_ind++;
// TODO verify that the very last byte is clear_code + 1
while ( input_length )
{
code = 0x0;
// Always read one more bit than the code length
for ( i = 0; i < ( code_length + 1 ); ++i )
{
// This is different than in the file read example; that
// was a call to "next_bit"
bit = ( *input & mask ) ? 1 : 0;
mask <<= 1;
if ( mask == 0x100 )
{
mask = 0x01;
input++;
input_length--;
}
code = code | ( bit << i );
}
if ( code == clear_code )
{
code_length = reset_code_length;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
for ( dictionary_ind = 0;
dictionary_ind < ( 1 << code_length );
dictionary_ind++ )
{
dictionary[ dictionary_ind ].byte = dictionary_ind;
// XXX this only works because prev is a 32-bit int (> 12 bits)
dictionary[ dictionary_ind ].prev = -1;
dictionary[ dictionary_ind ].len = 1;
}
dictionary_ind++;
dictionary_ind++;
prev = -1;
continue;
}
else if ( code == stop_code )
{
/*if ( input_length > 1 )
{
fprintf( stderr, "Malformed GIF (early stop code)\n" );
exit( 0 );
}*/
break;
}
// Update the dictionary with this character plus the _entry_
// (character or string) that came before it
if ( ( prev > -1 ) && ( code_length < 12 ) )
{
if ( code > dictionary_ind )
{
fprintf( stderr, "code = %.02x, but dictionary_ind = %.02x\n",
code, dictionary_ind );
exit( 0 );
}
// Special handling for KwKwK
if ( code == dictionary_ind )
{
int ptr = prev;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
else
{
int ptr = code;
while ( dictionary[ ptr ].prev != -1 )
{
ptr = dictionary[ ptr ].prev;
}
dictionary[ dictionary_ind ].byte = dictionary[ ptr ].byte;
}
dictionary[ dictionary_ind ].prev = prev;
dictionary[ dictionary_ind ].len = dictionary[ prev ].len + 1;
dictionary_ind++;
// GIF89a mandates that this stops at 12 bits
if ( ( dictionary_ind == ( 1 << ( code_length + 1 ) ) ) &&
( code_length < 11 ) )
{
code_length++;
dictionary = ( dictionary_entry_t * ) realloc( dictionary,
sizeof( dictionary_entry_t ) * ( 1 << ( code_length + 1 ) ) );
}
}
prev = code;
// Now copy the dictionary entry backwards into "out"
match_len = dictionary[ code ].len;
while ( code != -1 )
{
out[ dictionary[ code ].len - 1 ] = dictionary[ code ].byte;
if ( dictionary[ code ].prev == code )
{
fprintf( stderr, "Internal error; self-reference." );
exit( 0 );
}
code = dictionary[ code ].prev;
}
out += match_len;
}
}
static int read_sub_blocks( unsigned char* buffer, unsigned char **data )
{
int data_length;
int index;
unsigned char block_size;
// Everything following are data sub-blocks, until a 0-sized block is
// encountered.
data_length = 0;
*data = NULL;
index = 0;
while ( 1 )
{
READ(&block_size, 1);
if ( block_size == 0 ) // end of sub-blocks
{
break;
}
data_length += block_size;
*data = (unsigned char*)realloc( *data, data_length );
// TODO this could be split across block size boundaries
READ(*data + index, block_size);
index += block_size;
}
return data_length;
}
unsigned char* process_image_descriptor( unsigned char* buffer,
rgb *gct,
int gct_size,
int resolution_bits )
{
image_descriptor_t image_descriptor;
int compressed_data_length;
unsigned char *compressed_data = NULL;
unsigned char lzw_code_size;
int uncompressed_data_length = 0;
unsigned char *uncompressed_data = NULL;
// TODO there could actually be lots of these
READ(&image_descriptor, 9);
// TODO if LCT = true, read the LCT
READ(&lzw_code_size, 1);
compressed_data_length = read_sub_blocks( buffer, &compressed_data );
// width = image_descriptor.image_width;
// height = image_descriptor.image_height;
uncompressed_data_length = image_descriptor.image_width *
image_descriptor.image_height;
uncompressed_data = (unsigned char*)malloc( uncompressed_data_length );
uncompress( lzw_code_size, compressed_data, compressed_data_length,
uncompressed_data );
if ( compressed_data ) free( compressed_data );
//if ( uncompressed_data )
// free( uncompressed_data );
return uncompressed_data;
}
/**
* @param gif_file the file descriptor of a file containing a
* GIF-encoded file. This should point to the first byte in
* the file when invoked.
*/
#define rb (*(buffer++))
uint32_t* LoadPalette(unsigned char *buffer) {
unsigned char header[7];
screen_descriptor_t screen_descriptor;
//int color_resolution_bits;
int global_color_table_size = 0; // number of entries in global_color_table
uint32_t *global_color_table = NULL;
READ(header, 6);
READ(&screen_descriptor, 7);
//color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
global_color_table = (uint32_t *)calloc(1, 1024);
if (screen_descriptor.fields & 0x80) {
global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
//global_color_table = (rgb *)malloc(3 * global_color_table_size);
//READ(global_color_table, 3 * global_color_table_size);
for (int i=0; i<global_color_table_size;++i) {
global_color_table[i] = (buffer[0]<<16) + (buffer[1]<<8) + buffer[2];
buffer+=3;
}
}
return global_color_table;
}
static unsigned char* process_gif_stream(unsigned char *buffer, unsigned short* w, unsigned short* h)
{
unsigned char header[ 7 ];
screen_descriptor_t screen_descriptor;
int color_resolution_bits;
int global_color_table_size =0; // number of entries in global_color_table
rgb *global_color_table = NULL;
unsigned char block_type = 0x0;
// A GIF file starts with a Header (section 17)
READ(header, 6);
header[ 6 ] = 0x0;
// XXX there's another format, GIF87a, that you may still find
// floating around.
/*if ( strcmp( "GIF89a", (char*)header ) )
{
fprintf( stderr,
"Invalid GIF file (header is '%s', should be 'GIF89a')\n",
header );
return NULL;
}*/
// Followed by a logical screen descriptor
// Note that this works because GIFs specify little-endian order; on a
// big-endian machine, the height & width would need to be reversed.
// Can't use sizeof here since GCC does byte alignment;
// sizeof( screen_descriptor_t ) = 8!
READ(&screen_descriptor, 7);
*w = screen_descriptor.width;
*h = screen_descriptor.height;
color_resolution_bits = ( ( screen_descriptor.fields & 0x70 ) >> 4 ) + 1;
if ( screen_descriptor.fields & 0x80 )
{
//int i;
// If bit 7 is set, the next block is a global color table; read it
global_color_table_size = 1 <<
( ( ( screen_descriptor.fields & 0x07 ) + 1 ) );
global_color_table = ( rgb * ) malloc( 3 * global_color_table_size );
// XXX this could conceivably return a short count...
READ(global_color_table, 3 * global_color_table_size);
}
while ( block_type != TRAILER )
{
READ(&block_type, 1);
unsigned char size;
switch ( block_type )
{
case IMAGE_DESCRIPTOR:
return process_image_descriptor(buffer,
global_color_table,
global_color_table_size,
color_resolution_bits);
break;
case EXTENSION_INTRODUCER:
buffer++;
size = *(buffer++);
buffer += size;
do {
size = *(buffer++);
buffer += size;
} while (size != 0);
/*if ( !process_extension( buffer ) )
{
return NULL;
}*/
break;
case TRAILER:
break;
default:
fprintf( stderr, "Bailing on unrecognized block type %.02x\n",
block_type );
return NULL;
}
}
return NULL;
}
unsigned char* LoadGif(unsigned char *buffer, unsigned short* w, unsigned short* h) {
return process_gif_stream(buffer, w, h);
}
/*int main( int argc, char *argv[] )
{
FILE* gif_file;
if ( argc < 2 )
{
fprintf( stderr, "Usage: %s <path-to-gif-file>\n", argv[ 0 ] );
exit( 0 );
}
gif_file = fopen( argv[ 1 ], "rb" );
if ( gif_file == NULL )
{
fprintf( stderr, "Unable to open file '%s'", argv[ 1 ] );
perror( ": " );
}
process_gif_stream( gif_file );
fclose( gif_file );
}*/

316
source/gif.cpp Normal file
View File

@@ -0,0 +1,316 @@
#include "gif.h"
#include <iostream> // Para std::cout
#include <cstring> // Para memcpy, size_t
#include <stdexcept> // Para runtime_error
#include <string> // Para allocator, char_traits, operator==, basic_string
namespace GIF
{
// Función inline para reemplazar el macro READ.
// Actualiza el puntero 'buffer' tras copiar 'size' bytes a 'dst'.
inline void readBytes(const uint8_t *&buffer, void *dst, size_t size)
{
std::memcpy(dst, buffer, size);
buffer += size;
}
void Gif::decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out)
{
// Verifica que el code_length tenga un rango razonable.
if (code_length < 2 || code_length > 12)
{
throw std::runtime_error("Invalid LZW code length");
}
int i, bit;
int prev = -1;
std::vector<DictionaryEntry> dictionary;
int dictionary_ind;
unsigned int mask = 0x01;
int reset_code_length = code_length;
int clear_code = 1 << code_length;
int stop_code = clear_code + 1;
int match_len = 0;
// Inicializamos el diccionario con el tamaño correspondiente.
dictionary.resize(1 << (code_length + 1));
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++)
{
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
dictionary[dictionary_ind].prev = -1;
dictionary[dictionary_ind].len = 1;
}
dictionary_ind += 2; // Reservamos espacio para clear y stop codes
// Bucle principal: procesar el stream comprimido.
while (input_length > 0)
{
int code = 0;
// Lee (code_length + 1) bits para formar el código.
for (i = 0; i < (code_length + 1); i++)
{
if (input_length <= 0)
{
throw std::runtime_error("Unexpected end of input in decompress");
}
bit = ((*input & mask) != 0) ? 1 : 0;
mask <<= 1;
if (mask == 0x100)
{
mask = 0x01;
input++;
input_length--;
}
code |= (bit << i);
}
if (code == clear_code)
{
// Reinicia el diccionario.
code_length = reset_code_length;
dictionary.resize(1 << (code_length + 1));
for (dictionary_ind = 0; dictionary_ind < (1 << code_length); dictionary_ind++)
{
dictionary[dictionary_ind].byte = static_cast<uint8_t>(dictionary_ind);
dictionary[dictionary_ind].prev = -1;
dictionary[dictionary_ind].len = 1;
}
dictionary_ind += 2;
prev = -1;
continue;
}
else if (code == stop_code)
{
break;
}
if (prev > -1 && code_length < 12)
{
if (code > dictionary_ind)
{
std::cerr << "code = " << std::hex << code
<< ", but dictionary_ind = " << dictionary_ind << std::endl;
throw std::runtime_error("LZW error: code exceeds dictionary_ind.");
}
int ptr;
if (code == dictionary_ind)
{
ptr = prev;
while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
}
else
{
ptr = code;
while (dictionary[ptr].prev != -1)
ptr = dictionary[ptr].prev;
dictionary[dictionary_ind].byte = dictionary[ptr].byte;
}
dictionary[dictionary_ind].prev = prev;
dictionary[dictionary_ind].len = dictionary[prev].len + 1;
dictionary_ind++;
if ((dictionary_ind == (1 << (code_length + 1))) && (code_length < 11))
{
code_length++;
dictionary.resize(1 << (code_length + 1));
}
}
prev = code;
// Verifica que 'code' sea un índice válido antes de usarlo.
if (code < 0 || static_cast<size_t>(code) >= dictionary.size())
{
std::cerr << "Invalid LZW code " << code
<< ", dictionary size " << dictionary.size() << std::endl;
throw std::runtime_error("LZW error: invalid code encountered");
}
int curCode = code; // Variable temporal para recorrer la cadena.
match_len = dictionary[curCode].len;
while (curCode != -1)
{
// Se asume que dictionary[curCode].len > 0.
out[dictionary[curCode].len - 1] = dictionary[curCode].byte;
if (dictionary[curCode].prev == curCode)
{
std::cerr << "Internal error; self-reference detected." << std::endl;
throw std::runtime_error("Internal error in decompress: self-reference");
}
curCode = dictionary[curCode].prev;
}
out += match_len;
}
}
std::vector<uint8_t> Gif::readSubBlocks(const uint8_t *&buffer)
{
std::vector<uint8_t> data;
uint8_t block_size = *buffer;
buffer++;
while (block_size != 0)
{
data.insert(data.end(), buffer, buffer + block_size);
buffer += block_size;
block_size = *buffer;
buffer++;
}
return data;
}
std::vector<uint8_t> Gif::processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits)
{
ImageDescriptor image_descriptor;
// Lee 9 bytes para el image descriptor.
readBytes(buffer, &image_descriptor, sizeof(ImageDescriptor));
uint8_t lzw_code_size;
readBytes(buffer, &lzw_code_size, sizeof(uint8_t));
std::vector<uint8_t> compressed_data = readSubBlocks(buffer);
int uncompressed_data_length = image_descriptor.image_width * image_descriptor.image_height;
std::vector<uint8_t> uncompressed_data(uncompressed_data_length);
decompress(lzw_code_size, compressed_data.data(), static_cast<int>(compressed_data.size()), uncompressed_data.data());
return uncompressed_data;
}
std::vector<uint32_t> Gif::loadPalette(const uint8_t *buffer)
{
uint8_t header[6];
std::memcpy(header, buffer, 6);
buffer += 6;
ScreenDescriptor screen_descriptor;
std::memcpy(&screen_descriptor, buffer, sizeof(ScreenDescriptor));
buffer += sizeof(ScreenDescriptor);
std::vector<uint32_t> global_color_table;
if (screen_descriptor.fields & 0x80)
{
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
global_color_table.resize(global_color_table_size);
for (int i = 0; i < global_color_table_size; ++i)
{
uint8_t r = buffer[0];
uint8_t g = buffer[1];
uint8_t b = buffer[2];
global_color_table[i] = (r << 16) | (g << 8) | b;
buffer += 3;
}
}
return global_color_table;
}
std::vector<uint8_t> Gif::processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h)
{
// Leer la cabecera de 6 bytes ("GIF87a" o "GIF89a")
uint8_t header[6];
std::memcpy(header, buffer, 6);
buffer += 6;
// Opcional: Validar header
std::string headerStr(reinterpret_cast<char *>(header), 6);
if (headerStr != "GIF87a" && headerStr != "GIF89a")
{
throw std::runtime_error("Formato de archivo GIF inválido.");
}
// Leer el Screen Descriptor (7 bytes, empaquetado sin padding)
ScreenDescriptor screen_descriptor;
readBytes(buffer, &screen_descriptor, sizeof(ScreenDescriptor));
// Asigna ancho y alto
w = screen_descriptor.width;
h = screen_descriptor.height;
int color_resolution_bits = ((screen_descriptor.fields & 0x70) >> 4) + 1;
std::vector<RGB> global_color_table;
if (screen_descriptor.fields & 0x80)
{
int global_color_table_size = 1 << (((screen_descriptor.fields & 0x07) + 1));
global_color_table.resize(global_color_table_size);
std::memcpy(global_color_table.data(), buffer, 3 * global_color_table_size);
buffer += 3 * global_color_table_size;
}
// Supongamos que 'buffer' es el puntero actual y TRAILER es 0x3B
uint8_t block_type = *buffer++;
while (block_type != TRAILER)
{
if (block_type == EXTENSION_INTRODUCER) // 0x21
{
// Se lee la etiqueta de extensión, la cual indica el tipo de extensión.
uint8_t extension_label = *buffer++;
switch (extension_label)
{
case GRAPHIC_CONTROL: // 0xF9
{
// Procesar Graphic Control Extension:
uint8_t blockSize = *buffer++; // Normalmente, blockSize == 4
buffer += blockSize; // Saltamos los 4 bytes del bloque fijo
// Saltar los sub-bloques
uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0)
{
buffer += subBlockSize;
subBlockSize = *buffer++;
}
break;
}
case APPLICATION_EXTENSION: // 0xFF
case COMMENT_EXTENSION: // 0xFE
case PLAINTEXT_EXTENSION: // 0x01
{
// Para estas extensiones, saltamos el bloque fijo y los sub-bloques.
uint8_t blockSize = *buffer++;
buffer += blockSize;
uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0)
{
buffer += subBlockSize;
subBlockSize = *buffer++;
}
break;
}
default:
{
// Si la etiqueta de extensión es desconocida, saltarla también:
uint8_t blockSize = *buffer++;
buffer += blockSize;
uint8_t subBlockSize = *buffer++;
while (subBlockSize != 0)
{
buffer += subBlockSize;
subBlockSize = *buffer++;
}
break;
}
}
}
else if (block_type == IMAGE_DESCRIPTOR)
{
// Procesar el Image Descriptor y retornar los datos de imagen
return processImageDescriptor(buffer, global_color_table, color_resolution_bits);
}
else
{
std::cerr << "Unrecognized block type " << std::hex << static_cast<int>(block_type) << std::endl;
return std::vector<uint8_t>{};
}
block_type = *buffer++;
}
return std::vector<uint8_t>{};
}
std::vector<uint8_t> Gif::loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h)
{
return processGifStream(buffer, w, h);
}
} // namespace GIF

102
source/gif.h Normal file
View File

@@ -0,0 +1,102 @@
#pragma once
#include <cstdint> // Para uint8_t, uint16_t, uint32_t
#include <vector> // Para vector
namespace GIF
{
// Constantes definidas con constexpr, en lugar de macros
constexpr uint8_t EXTENSION_INTRODUCER = 0x21;
constexpr uint8_t IMAGE_DESCRIPTOR = 0x2C;
constexpr uint8_t TRAILER = 0x3B;
constexpr uint8_t GRAPHIC_CONTROL = 0xF9;
constexpr uint8_t APPLICATION_EXTENSION = 0xFF;
constexpr uint8_t COMMENT_EXTENSION = 0xFE;
constexpr uint8_t PLAINTEXT_EXTENSION = 0x01;
#pragma pack(push, 1)
struct ScreenDescriptor
{
uint16_t width;
uint16_t height;
uint8_t fields;
uint8_t background_color_index;
uint8_t pixel_aspect_ratio;
};
struct RGB
{
uint8_t r, g, b;
};
struct ImageDescriptor
{
uint16_t image_left_position;
uint16_t image_top_position;
uint16_t image_width;
uint16_t image_height;
uint8_t fields;
};
#pragma pack(pop)
struct DictionaryEntry
{
uint8_t byte;
int prev;
int len;
};
struct Extension
{
uint8_t extension_code;
uint8_t block_size;
};
struct GraphicControlExtension
{
uint8_t fields;
uint16_t delay_time;
uint8_t transparent_color_index;
};
struct ApplicationExtension
{
uint8_t application_id[8];
uint8_t version[3];
};
struct PlaintextExtension
{
uint16_t left, top, width, height;
uint8_t cell_width, cell_height;
uint8_t foreground_color, background_color;
};
class Gif
{
public:
// Descompone (uncompress) el bloque comprimido usando LZW.
// Este método puede lanzar std::runtime_error en caso de error.
void decompress(int code_length, const uint8_t *input, int input_length, uint8_t *out);
// Carga la paleta (global color table) a partir de un buffer,
// retornándola en un vector de uint32_t (cada color se compone de R, G, B).
std::vector<uint32_t> loadPalette(const uint8_t *buffer);
// Carga el stream GIF; devuelve un vector con los datos de imagen sin comprimir y
// asigna el ancho y alto mediante referencias.
std::vector<uint8_t> loadGif(const uint8_t *buffer, uint16_t &w, uint16_t &h);
private:
// Lee los sub-bloques de datos y los acumula en un std::vector<uint8_t>.
std::vector<uint8_t> readSubBlocks(const uint8_t *&buffer);
// Procesa el Image Descriptor y retorna el vector de datos sin comprimir.
std::vector<uint8_t> processImageDescriptor(const uint8_t *&buffer, const std::vector<RGB> &gct, int resolution_bits);
// Procesa el stream completo del GIF y devuelve los datos sin comprimir.
std::vector<uint8_t> processGifStream(const uint8_t *buffer, uint16_t &w, uint16_t &h);
};
} // namespace GIF

33
source/global_events.cpp Normal file
View File

@@ -0,0 +1,33 @@
#include "global_events.h"
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <iostream> // Para char_traits, basic_ostream, operator<<
#include "mouse.h" // Para handleEvent
#include "section.h" // Para Name, Options, name, options
namespace globalEvents
{
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void check(const SDL_Event &event)
{
switch (event.type)
{
case SDL_QUIT: // Evento de salida de la aplicación
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
return;
case SDL_RENDER_DEVICE_RESET:
case SDL_RENDER_TARGETS_RESET:
std::cout << "SDL_RENDER_TARGETS_RESET" << std::endl;
break;
case SDL_WINDOWEVENT:
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
std::cout << "SDL_WINDOWEVENT_SIZE_CHANGED" << std::endl;
}
break;
default:
break;
}
Mouse::handleEvent(event);
}
}

9
source/global_events.h Normal file
View File

@@ -0,0 +1,9 @@
#pragma once
#include <SDL2/SDL_events.h>
namespace globalEvents
{
// Comprueba los eventos que se pueden producir en cualquier sección del juego
void check(const SDL_Event &event);
}

View File

@@ -1,16 +1,18 @@
#include "global_inputs.h"
#include <string> // Para operator+, string, to_string, basic_string
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "input.h" // Para Input, InputDeviceToUse, InputType, INPU...
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundVolume
#include "lang.h" // Para Code, getText, change, loadFromFile
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, options, OptionsGame, OptionsAudio
#include "screen.h" // Para Screen, ScreenVideoMode
#include "section.h" // Para Name, Options, name, options
#include "utils.h" // Para boolToOnOff, stringInVector
#include <SDL2/SDL_render.h> // Para SDL_RenderSetIntegerScale
#include <SDL2/SDL_stdinc.h> // Para SDL_FALSE, SDL_TRUE
#include <string> // Para operator+, string, to_string, basic_string
#include <vector> // Para vector
#include "asset.h" // Para Asset
#include "input.h" // Para Input, InputDeviceToUse, InputAction, INP...
#include "jail_audio.h" // Para JA_SetMusicVolume, JA_SetSoundVolume
#include "lang.h" // Para getText, Code, getNextLangCode, loadFro...
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, options, OptionsGame, OptionsV...
#include "screen.h" // Para Screen, ScreenVideoMode
#include "section.h" // Para Name, name, Options, options, AttractMode
#include "utils.h" // Para boolToOnOff
namespace globalInputs
{
@@ -21,9 +23,8 @@ namespace globalInputs
// Termina
void quit(section::Options code)
{
const std::string exit_code = "QUIT";
auto code_found = stringInVector(Notifier::get()->getCodes(), exit_code);
if (code_found)
const std::string CODE = "QUIT";
if (Notifier::get()->checkCode(CODE))
{
// Si la notificación de salir está activa, cambia de sección
section::name = section::Name::QUIT;
@@ -33,10 +34,10 @@ namespace globalInputs
{
// Si la notificación de salir no está activa, muestra la notificación
#ifdef ARCADE
const int index = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->showText({lang::getText(index), std::string()}, -1, exit_code);
const int INDEX = code == section::Options::QUIT_WITH_CONTROLLER ? 116 : 94;
Notifier::get()->show({lang::getText(INDEX), std::string()}, -1, CODE);
#else
Notifier::get()->showText({lang::getText(94), std::string()}, -1, exit_code);
Notifier::get()->show({lang::getText(94), std::string()}, -1, CODE);
#endif
}
}
@@ -44,8 +45,16 @@ namespace globalInputs
// Reinicia
void reset()
{
section::name = section::Name::INIT;
Notifier::get()->showText({"Reset"});
const std::string CODE = "RESET";
if (Notifier::get()->checkCode(CODE))
{
section::name = section::Name::INIT;
Notifier::get()->show({lang::getText(111)});
}
else
{
Notifier::get()->show({lang::getText(125), std::string()}, -1, CODE);
}
}
// Activa o desactiva el audio
@@ -62,7 +71,23 @@ namespace globalInputs
JA_SetMusicVolume(0);
JA_SetSoundVolume(0);
}
Notifier::get()->showText({"Audio " + boolToOnOff(options.audio.enabled)});
Notifier::get()->show({"Audio " + boolToOnOff(options.audio.enabled)});
}
// Cambia el modo de escalado entero
void toggleintegerScale()
{
options.video.integer_scale = !options.video.integer_scale;
SDL_RenderSetIntegerScale(Screen::get()->getRenderer(), options.video.integer_scale ? SDL_TRUE : SDL_FALSE);
Screen::get()->setVideoMode();
Notifier::get()->show({lang::getText(134) + " " + boolToOnOff(options.video.integer_scale)});
}
// Activa o desactiva los shaders
void toggleShaders()
{
Screen::get()->toggleShaders();
Notifier::get()->show({lang::getText(135) + " " + boolToOnOff(options.video.shaders)});
}
// Obtiene una fichero a partir de un lang::Code
@@ -88,13 +113,13 @@ namespace globalInputs
switch (code)
{
case lang::Code::ba_BA:
return "ba_BA";
return " \"ba_BA\"";
break;
case lang::Code::es_ES:
return "es_ES";
return " \"es_ES\"";
break;
default:
return "en_UK";
return " \"en_UK\"";
break;
}
}
@@ -102,18 +127,49 @@ namespace globalInputs
// Cambia el idioma
void changeLang()
{
options.game.language = lang::change(options.game.language);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
section::name = section::Name::INIT;
section::options = section::Options::RELOAD;
Notifier::get()->showText({getLangName(options.game.language)});
const std::string CODE = "LANG";
if (Notifier::get()->checkCode(CODE))
{
options.game.language = lang::getNextLangCode(options.game.language);
lang::loadFromFile(getLangFile(static_cast<lang::Code>(options.game.language)));
section::name = section::Name::INIT;
section::options = section::Options::RELOAD;
Notifier::get()->show({lang::getText(127) + getLangName(options.game.language)});
}
else
{
const auto NEXT = lang::getNextLangCode(options.game.language);
Notifier::get()->show({lang::getText(126) + getLangName(NEXT), std::string()}, -1, CODE);
}
}
// Cambia el modo de disparo
void toggleFireMode()
{
options.game.autofire = !options.game.autofire;
Notifier::get()->showText({"Autofire " + boolToOnOff(options.game.autofire)});
Notifier::get()->show({lang::getText(130) + " " + boolToOnOff(options.game.autofire)});
}
// Salta una sección del juego
void skip_section()
{
switch (section::name)
{
case section::Name::INTRO:
JA_StopMusic();
/* Continua en el case de abajo */
case section::Name::LOGO:
case section::Name::HI_SCORE_TABLE:
case section::Name::INSTRUCTIONS:
{
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
break;
}
default:
break;
}
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
@@ -121,86 +177,100 @@ namespace globalInputs
{
// Teclado
{
#ifndef ARCADE
// Comprueba el teclado para cambiar entre pantalla completa y ventana
if (Input::get()->checkInput(InputType::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::WINDOW_FULLSCREEN, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleVideoMode();
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? "Window" : "Fullscreen";
Notifier::get()->showText({mode + " mode"});
const std::string mode = options.video.mode == ScreenVideoMode::WINDOW ? lang::getText(132) : lang::getText(133);
Notifier::get()->show({mode});
return;
}
// Comprueba el teclado para decrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::WINDOW_DEC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->decWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
if (Screen::get()->decWindowZoom())
{
Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.video.window.zoom)});
}
return;
}
// Comprueba el teclado para incrementar el tamaño de la ventana
if (Input::get()->checkInput(InputType::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::WINDOW_INC_SIZE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->incWindowSize();
const std::string size = std::to_string(options.video.window.size);
Notifier::get()->showText({"Window size x" + size});
if (Screen::get()->incWindowZoom())
{
Notifier::get()->show({lang::getText(131) + " x" + std::to_string(options.video.window.zoom)});
}
return;
}
#endif
// Salir
if (Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
quit(section::Options::QUIT_WITH_KEYBOARD);
return;
}
// Saltar sección
if (Input::get()->checkAnyButtonPressed())
{
skip_section();
return;
}
// Reset
if (Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
reset();
return;
}
// Audio
if (Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
toggleAudio();
return;
}
// Autofire
if (Input::get()->checkInput(InputType::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::AUTO_FIRE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
toggleFireMode();
return;
}
// Idioma
if (Input::get()->checkInput(InputType::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::CHANGE_LANG, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
changeLang();
return;
}
// Shaders
if (Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleShaders();
toggleShaders();
return;
}
if (Input::get()->checkInput(InputAction::VIDEO_INTEGER_SCALE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
toggleintegerScale();
return;
}
#ifdef DEBUG
// Comprueba el teclado para mostrar la información de debug
if (Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::SHOW_INFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::KEYBOARD))
{
service_pressed = true;
return;
@@ -212,47 +282,47 @@ namespace globalInputs
for (int i = 0; i < Input::get()->getNumControllers(); ++i)
{
// Salir
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputAction::EXIT, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
quit(section::Options::QUIT_WITH_CONTROLLER);
return;
}
// Reset
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputAction::RESET, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
reset();
return;
}
// Audio
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputAction::MUTE, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
toggleAudio();
return;
}
// Shaders
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputAction::VIDEO_SHADERS, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleShaders();
toggleShaders();
return;
}
#ifdef DEBUG
// Debug Info
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputType::SHOWINFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i) &&
Input::get()->checkInput(InputAction::SHOW_INFO, INPUT_DO_NOT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
Screen::get()->toggleDebugInfo();
return;
}
#endif
// OnScreenHelp
if (Input::get()->checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
if (Input::get()->checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::CONTROLLER, i))
{
service_pressed = true;
return;

View File

@@ -1,26 +1,29 @@
#include "hiscore_table.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <stdlib.h> // Para rand, size_t
#include <algorithm> // Para max
#include <functional> // Para function
#include <vector> // Para vector
#include "background.h" // Para Background
#include "fade.h" // Para Fade, FadeMode, FadeType
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check, update
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // Para getText
#include "manage_hiscore_table.h" // Para HiScoreEntry
#include "options.h" // Para Options, OptionsGame, options
#include "param.h" // Para Param, param, ParamGame, ParamFade
#include "path_sprite.h" // Para PathSprite, Path, PathType
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "text.h" // Para Text, TEXT_CENTER, TEXT_SHADOW
#include "utils.h" // Para Color, Zone, fade_color, orange_color
#include "mouse.h"
#include "section.h" // Para Name, name
#include "sprite.h" // Para Sprite
#include "text.h" // Para Text, TEXT_SHADOW, TEXT_COLOR
#include "texture.h" // Para Texture
#include "utils.h" // Para Color, easeOutQuint, fade_color, Zone
// Constructor
HiScoreTable::HiScoreTable()
@@ -28,60 +31,41 @@ HiScoreTable::HiScoreTable()
backbuffer_(SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height)),
fade_(std::make_unique<Fade>()),
background_(std::make_unique<Background>()),
text_(Resource::get()->getText("smb2")),
counter_(0),
ticks_(0),
view_area_({0, 0, param.game.width, param.game.height}),
fade_mode_(FadeMode::IN)
fade_mode_(FadeMode::IN),
background_fade_color_(Color(0, 0, 0))
{
// Inicializa el resto de variables
// Inicializa el resto
section::name = section::Name::HI_SCORE_TABLE;
// Inicializa objetos
SDL_SetTextureBlendMode(backbuffer_, SDL_BLENDMODE_BLEND);
background_->setPos(param.game.game_area.rect);
background_->setCloudsSpeed(-0.1f);
background_->setGradientNumber(1);
background_->setTransition(0.8f);
background_->setSunProgression(1.0f);
background_->setMoonProgression(0.6f);
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_->setType(FadeType::RANDOM_SQUARE);
fade_->setPostDuration(param.fade.post_duration);
fade_->setMode(fade_mode_);
fade_->activate();
// Crea el contenido de la textura con la lista de puntuaciones
fillTexture();
initFade();
initBackground();
iniEntryColors();
createSprites();
}
// Destructor
HiScoreTable::~HiScoreTable()
{
SDL_DestroyTexture(backbuffer_);
options.game.clear_last_hi_score_entries();
}
// Actualiza las variables
void HiScoreTable::update()
{
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
// Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
updateMusic();
// Actualiza el objeto screen
Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
// Actualiza las posiciones de los sprites de texto
updateSprites();
// Actualiza el fondo
background_->update();
@@ -90,31 +74,22 @@ void HiScoreTable::update()
updateFade();
// Gestiona el contador y sus eventos
counter_++;
updateCounter();
if (counter_ == 150)
{
background_->setColor(Color(0, 0, 0));
background_->setAlpha(96);
}
// Dibuja los sprites en la textura
fillTexture();
if (counter_ == COUNTER_END_)
{
fade_->activate();
}
// Actualiza el objeto screen
Screen::get()->update();
// Actualiza las variables de globalInputs
globalInputs::update();
}
}
// Crea el contenido de la textura con la lista de puntuaciones
// Dibuja los sprites en la textura
void HiScoreTable::fillTexture()
{
// hay 27 letras - 7 de puntos quedan 20 caracteres 20 - name_lenght 0 num_dots
constexpr auto max_names = 10;
constexpr auto space_between_header = 32;
const auto space_between_lines = text_->getCharacterSize() * 2.0f;
const auto size = space_between_header + space_between_lines * (max_names - 1) + text_->getCharacterSize();
const auto first_line = (param.game.height - size) / 2;
// Pinta en el backbuffer el texto y los sprites
auto temp = SDL_GetRenderTarget(renderer_);
SDL_SetRenderTarget(renderer_, backbuffer_);
@@ -122,22 +97,12 @@ void HiScoreTable::fillTexture()
SDL_RenderClear(renderer_);
// Escribe el texto: Mejores puntuaciones
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, first_line, lang::getText(42), 1, orange_color, 1, shdw_txt_color);
header_->render();
// Escribe los nombres de la tabla de puntuaciones
for (int i = 0; i < max_names; ++i)
for (auto const &entry : entry_names_)
{
const auto name_lenght = options.game.hi_score_table[i].name.length();
const auto score = format(options.game.hi_score_table[i].score);
const auto score_lenght = score.size();
const auto num_dots = 25 - name_lenght - score_lenght;
std::string dots;
for (int j = 0; j < (int)num_dots; ++j)
{
dots = dots + ".";
}
const auto line = options.game.hi_score_table[i].name + dots + score;
text_->writeDX(TEXT_CENTER | TEXT_SHADOW, param.game.game_area.center_x, (i * space_between_lines) + first_line + space_between_header, line, 1, orange_color, 1, shdw_txt_color);
entry->render();
}
// Cambia el destino de renderizado
@@ -169,56 +134,19 @@ void HiScoreTable::render()
Screen::get()->render();
}
// Recarga todas las texturas
void HiScoreTable::reloadTextures()
{
text_->reLoadTexture();
fillTexture();
}
// Comprueba los eventos
void HiScoreTable::checkEvents()
{
// Comprueba los eventos que hay en la cola
SDL_Event event;
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba si se ha cambiado el tamaño de la ventana
else if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
}
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
// Comprueba las entradas
void HiScoreTable::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
{
// JA_StopMusic();
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
return;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
@@ -248,7 +176,10 @@ void HiScoreTable::updateFade()
if (fade_->hasEnded() && fade_mode_ == FadeMode::OUT)
{
section::name = section::Name::INSTRUCTIONS;
section::name = (section::options == section::Options::HI_SCORE_AFTER_PLAYING)
? section::Name::TITLE
: section::Name::INSTRUCTIONS;
section::options = section::Options::NONE;
}
}
@@ -274,4 +205,239 @@ std::string HiScoreTable::format(int number)
}
return result;
}
// Crea los sprites con los textos
void HiScoreTable::createSprites()
{
auto header_text = Resource::get()->getText("04b_25_grey");
auto entry_text = Resource::get()->getText("smb2");
// Obtiene el tamaño de la textura
int backbuffer_width;
int backbuffer_height;
SDL_QueryTexture(backbuffer_, nullptr, nullptr, &backbuffer_width, &backbuffer_height);
constexpr int entry_lenght = 22;
constexpr int max_names = 10;
const int space_between_header = entry_text->getCharacterSize() * 4;
const int space_between_lines = entry_text->getCharacterSize() * 2;
const int size = space_between_header + space_between_lines * (max_names - 1) + entry_text->getCharacterSize();
const int first_line = (param.game.height - size) / 2;
// Crea el sprite para el texto de cabecera
header_ = std::make_unique<Sprite>(header_text->writeDXToTexture(TEXT_COLOR, lang::getText(42), -2, background_fade_color_.getInverse().lighten(25)));
header_->setPosition(param.game.game_area.center_x - (header_->getWidth() / 2), first_line);
// Crea los sprites para las entradas en la tabla de puntuaciones
const int animation = rand() % 4;
const std::string sample_line(entry_lenght + 3, ' ');
auto sample_entry = std::make_unique<Sprite>(entry_text->writeDXToTexture(TEXT_SHADOW, sample_line, 1, orange_color, 1, shdw_txt_color));
const auto entry_width = sample_entry->getWidth();
for (int i = 0; i < max_names; ++i)
{
const auto table_position = format(i + 1) + ". ";
const auto score = format(options.game.hi_score_table.at(i).score);
const auto num_dots = entry_lenght - options.game.hi_score_table.at(i).name.size() - score.size();
const auto one_cc = options.game.hi_score_table.at(i).one_credit_complete ? " }" : "";
std::string dots;
for (int j = 0; j < (int)num_dots; ++j)
{
dots = dots + ".";
}
const auto line = table_position + options.game.hi_score_table.at(i).name + dots + score + one_cc;
entry_names_.emplace_back(std::make_shared<PathSprite>(entry_text->writeDXToTexture(TEXT_SHADOW, line, 1, orange_color, 1, shdw_txt_color)));
const int default_pos_x = (backbuffer_width - entry_width) / 2;
const int pos_x = (i < 9) ? default_pos_x : default_pos_x - entry_text->getCharacterSize();
const int pos_y = (i * space_between_lines) + first_line + space_between_header;
constexpr int steps = 80;
switch (animation)
{
case 0: // Ambos lados alternativamente
{
if (i % 2 == 0)
{
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
}
else
{
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
entry_names_.back()->setPosition(backbuffer_width, 0);
}
break;
}
case 1: // Entran por la izquierda
{
entry_names_.back()->addPath(-entry_names_.back()->getWidth(), pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
entry_names_.back()->setPosition(-entry_names_.back()->getWidth(), 0);
break;
}
case 2: // Entran por la derecha
{
entry_names_.back()->addPath(backbuffer_width, pos_x, PathType::HORIZONTAL, pos_y, steps, easeOutQuint);
entry_names_.back()->setPosition(backbuffer_width, 0);
break;
}
case 3: // Entran desde la parte inferior
{
entry_names_.back()->addPath(backbuffer_height, pos_y, PathType::VERTICAL, pos_x, steps, easeOutQuint);
entry_names_.back()->setPosition(0, backbuffer_height);
}
default:
break;
}
}
}
// Actualiza las posiciones de los sprites de texto
void HiScoreTable::updateSprites()
{
constexpr int init_counter = 190;
const int counter_between_entries = 16;
if (counter_ >= init_counter)
{
const int counter2 = counter_ - init_counter;
if (counter2 % counter_between_entries == 0)
{
int index = counter2 / counter_between_entries;
if (index < static_cast<int>(entry_names_.size()))
{
entry_names_.at(index)->enable();
}
}
}
for (auto const &entry : entry_names_)
{
entry->update();
}
glowEntryNames();
}
// Inicializa el fade
void HiScoreTable::initFade()
{
fade_->setColor(fade_color.r, fade_color.g, fade_color.b);
fade_->setType(FadeType::RANDOM_SQUARE);
fade_->setPostDuration(param.fade.post_duration);
fade_->setMode(fade_mode_);
fade_->activate();
}
// Inicializa el fondo
void HiScoreTable::initBackground()
{
background_->setPos(param.game.game_area.rect);
background_->setCloudsSpeed(-0.1f);
const int lucky = rand() % 3;
switch (lucky)
{
case 0: // Fondo verde
{
background_->setGradientNumber(2);
background_->setTransition(0.0f);
background_->setSunProgression(1.0f);
background_->setMoonProgression(0.0f);
background_fade_color_ = green_sky_color;
break;
}
case 1: // Fondo naranja
{
background_->setGradientNumber(1);
background_->setTransition(0.0f);
background_->setSunProgression(0.65f);
background_->setMoonProgression(0.0f);
background_fade_color_ = pink_sky_color;
break;
}
case 2: // Fondo azul
{
background_->setGradientNumber(0);
background_->setTransition(0.0f);
background_->setSunProgression(0.0f);
background_->setMoonProgression(0.0f);
background_fade_color_ = blue_sky_color;
break;
}
default:
break;
}
}
// Obtiene un color del vector de colores de entradas
Color HiScoreTable::getEntryColor(int counter_)
{
int cycle_length = entry_colors_.size() * 2 - 2;
size_t n = counter_ % cycle_length;
size_t index;
if (n < entry_colors_.size())
{
index = n; // Avanza: 0,1,2,3
}
else
{
index = 2 * (entry_colors_.size() - 1) - n; // Retrocede: 2,1
}
return entry_colors_[index];
}
// Inicializa los colores de las entradas
void HiScoreTable::iniEntryColors()
{
entry_colors_.clear();
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(75));
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(50));
entry_colors_.emplace_back(background_fade_color_.getInverse().lighten(25));
entry_colors_.emplace_back(background_fade_color_.getInverse());
}
// Hace brillar los nombres de la tabla de records
void HiScoreTable::glowEntryNames()
{
const Color entry_color = getEntryColor(counter_ / 5);
for (const auto &entry_index : options.game.last_hi_score_entry)
{
if (entry_index != -1)
{
entry_names_.at(entry_index)->getTexture()->setColor(entry_color);
}
}
}
// Gestiona la musica
void HiScoreTable::updateMusic()
{
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
}
// Gestiona el contador
void HiScoreTable::updateCounter()
{
counter_++;
if (counter_ == 150)
{
background_->setColor(background_fade_color_.darken());
background_->setAlpha(96);
}
if (counter_ == COUNTER_END_)
{
fade_->activate();
}
}

View File

@@ -1,14 +1,18 @@
#pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // para Uint16, Uint32, Uint8
#include <memory> // para unique_ptr
#include <string> // para string
class Background; // lines 8-8
class Fade; // lines 9-9
class Text; // lines 10-10
enum class FadeMode : Uint8; // lines 11-11
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Renderer, SDL_Texture
#include <SDL2/SDL_stdinc.h> // Para Uint16, Uint32, Uint8
#include <memory> // Para unique_ptr, shared_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "utils.h"
class Background; // lines 10-10
class Fade; // lines 11-11
class PathSprite;
class Sprite;
enum class FadeMode : Uint8; // lines 13-13
struct Path;
/*
Esta clase gestiona un estado del programa. Se encarga de mostrar la tabla con las puntuaciones
@@ -31,15 +35,19 @@ private:
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *backbuffer_; // Textura para usar como backbuffer
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::shared_ptr<Text> text_; // Objeto para escribir texto
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
std::unique_ptr<Background> background_; // Objeto para dibujar el fondo del juego
std::unique_ptr<Sprite> header_; // Sprite con la cabecera del texto
std::vector<std::shared_ptr<PathSprite>> entry_names_; // Lista con los spritres de cada uno de los nombres de la tabla de records
std::vector<Path> paths_; // Vector con los recorridos precalculados
// Variables
Uint16 counter_; // Contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fade_mode_; // Modo de fade a utilizar
Uint16 counter_ = 0; // Contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_area_; // Parte de la textura que se muestra en pantalla
FadeMode fade_mode_; // Modo de fade a utilizar
Color background_fade_color_; // Color de atenuación del fondo
std::vector<Color> entry_colors_; // Colores para destacar las entradas en la tabla
// Actualiza las variables
void update();
@@ -56,15 +64,39 @@ private:
// Convierte un entero a un string con separadores de miles
std::string format(int number);
// Crea el contenido de la textura con la lista de puntuaciones
// Dibuja los sprites en la textura
void fillTexture();
// Recarga todas las texturas
void reloadTextures();
// Gestiona el fade
void updateFade();
// Crea los sprites con los textos
void createSprites();
// Actualiza las posiciones de los sprites de texto
void updateSprites();
// Inicializa el fade
void initFade();
// Inicializa el fondo
void initBackground();
// Obtiene un color del vector de colores de entradas
Color getEntryColor(int counter_);
// Inicializa los colores de las entradas
void iniEntryColors();
// Hace brillar los nombres de la tabla de records
void glowEntryNames();
// Gestiona la musica
void updateMusic();
// Gestiona el contador
void updateCounter();
public:
// Constructor
HiScoreTable();

View File

@@ -9,22 +9,22 @@
#include <unordered_map> // Para unordered_map, operator==, _Node_cons...
#include <utility> // Para pair
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
// [SINGLETON]
Input *Input::input_ = nullptr;
// [SINGLETON] Crearemos el objeto input con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
void Input::init(const std::string &game_controller_db_path)
{
Input::input_ = new Input(game_controller_db_path);
}
// [SINGLETON] Destruiremos el objeto input con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
void Input::destroy()
{
delete Input::input_;
}
// [SINGLETON] Con este método obtenemos el objeto input y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
Input *Input::get()
{
return Input::input_;
@@ -38,21 +38,21 @@ Input::Input(const std::string &game_controller_db_path)
discoverGameControllers();
// Inicializa los vectores
key_bindings_.resize(static_cast<int>(InputType::NUMBER_OF_INPUTS), KeyBindings());
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputType::NUMBER_OF_INPUTS), ControllerBindings()));
key_bindings_.resize(static_cast<int>(InputAction::SIZE), KeyBindings());
controller_bindings_.resize(num_gamepads_, std::vector<ControllerBindings>(static_cast<int>(InputAction::SIZE), ControllerBindings()));
// Listado de los inputs para jugar que utilizan botones, ni palancas ni crucetas
button_inputs_ = {InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START};
button_inputs_ = {InputAction::FIRE_LEFT, InputAction::FIRE_CENTER, InputAction::FIRE_RIGHT, InputAction::START};
}
// Asigna inputs a teclas
void Input::bindKey(InputType input, SDL_Scancode code)
void Input::bindKey(InputAction input, SDL_Scancode code)
{
key_bindings_.at(static_cast<int>(input)).scancode = code;
}
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(int controller_index, InputType input, SDL_GameControllerButton button)
void Input::bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button)
{
if (controller_index < num_gamepads_)
{
@@ -61,7 +61,7 @@ void Input::bindGameControllerButton(int controller_index, InputType input, SDL_
}
// Asigna inputs a botones del mando
void Input::bindGameControllerButton(int controller_index, InputType input_target, InputType input_source)
void Input::bindGameControllerButton(int controller_index, InputAction input_target, InputAction input_source)
{
if (controller_index < num_gamepads_)
{
@@ -70,7 +70,7 @@ void Input::bindGameControllerButton(int controller_index, InputType input_targe
}
// Comprueba si un input esta activo
bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, int controller_index)
bool Input::checkInput(InputAction input, bool repeat, InputDeviceToUse device, int controller_index)
{
bool success_keyboard = false;
bool success_controller = false;
@@ -110,9 +110,11 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
}
if (gameControllerFound() && controller_index >= 0 && controller_index < num_gamepads_)
{
if ((device == InputDeviceToUse::CONTROLLER) || (device == InputDeviceToUse::ANY))
{
success_controller = checkAxisInput(input, controller_index);
success_controller = checkAxisInput(input, controller_index, repeat);
if (!success_controller)
{
if (repeat)
@@ -144,6 +146,7 @@ bool Input::checkInput(InputType input, bool repeat, InputDeviceToUse device, in
}
}
}
}
return (success_keyboard || success_controller);
}
@@ -187,7 +190,7 @@ bool Input::checkAnyInput(InputDeviceToUse device, int controller_index)
int Input::checkAnyButtonPressed(bool repeat)
{
// Si está pulsado el botón de servicio, ningún botón se puede considerar pulsado
if (checkInput(InputType::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::ANY))
if (checkInput(InputAction::SERVICE, INPUT_ALLOW_REPEAT, InputDeviceToUse::ANY))
{
return 0;
}
@@ -332,7 +335,7 @@ void Input::printBindings(InputDeviceToUse device, int controller_index) const
}
// Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputType input) const
SDL_GameControllerButton Input::getControllerBinding(int controller_index, InputAction input) const
{
return controller_bindings_[controller_index][static_cast<int>(input)].button;
}
@@ -344,54 +347,88 @@ int Input::getIndexByName(const std::string &name) const
return it != controller_names_.end() ? std::distance(controller_names_.begin(), it) : -1;
}
// Convierte un InputType a std::string
std::string Input::to_string(InputType input) const
// Convierte un InputAction a std::string
std::string Input::to_string(InputAction input) const
{
switch (input)
{
case InputType::FIRE_LEFT:
case InputAction::FIRE_LEFT:
return "input_fire_left";
case InputType::FIRE_CENTER:
case InputAction::FIRE_CENTER:
return "input_fire_center";
case InputType::FIRE_RIGHT:
case InputAction::FIRE_RIGHT:
return "input_fire_right";
case InputType::START:
case InputAction::START:
return "input_start";
case InputType::SERVICE:
case InputAction::SERVICE:
return "input_service";
default:
return "";
}
}
// Convierte un std::string a InputType
InputType Input::to_inputs_e(const std::string &name) const
// Convierte un std::string a InputAction
InputAction Input::to_inputs_e(const std::string &name) const
{
static const std::unordered_map<std::string, InputType> inputMap = {
{"input_fire_left", InputType::FIRE_LEFT},
{"input_fire_center", InputType::FIRE_CENTER},
{"input_fire_right", InputType::FIRE_RIGHT},
{"input_start", InputType::START},
{"input_service", InputType::SERVICE}};
static const std::unordered_map<std::string, InputAction> inputMap = {
{"input_fire_left", InputAction::FIRE_LEFT},
{"input_fire_center", InputAction::FIRE_CENTER},
{"input_fire_right", InputAction::FIRE_RIGHT},
{"input_start", InputAction::START},
{"input_service", InputAction::SERVICE}};
auto it = inputMap.find(name);
return it != inputMap.end() ? it->second : InputType::NONE;
return it != inputMap.end() ? it->second : InputAction::NONE;
}
// Comprueba el eje del mando
bool Input::checkAxisInput(InputType input, int controller_index) const
bool Input::checkAxisInput(InputAction input, int controller_index, bool repeat)
{
// Umbral para considerar el eje como activo
const Sint16 threshold = 30000;
bool axis_active_now = false;
switch (input)
{
case InputType::LEFT:
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -30000;
case InputType::RIGHT:
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > 30000;
case InputType::UP:
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -30000;
case InputType::DOWN:
return SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > 30000;
case InputAction::LEFT:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) < -threshold;
break;
case InputAction::RIGHT:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTX) > threshold;
break;
case InputAction::UP:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) < -threshold;
break;
case InputAction::DOWN:
axis_active_now = SDL_GameControllerGetAxis(connected_controllers_[controller_index], SDL_CONTROLLER_AXIS_LEFTY) > threshold;
break;
default:
return false;
}
// Referencia al binding correspondiente
auto &binding = controller_bindings_.at(controller_index).at(static_cast<int>(input));
if (repeat)
{
// Si se permite repetir, simplemente devolvemos el estado actual
return axis_active_now;
}
else
{
// Si no se permite repetir, aplicamos la lógica de transición
if (axis_active_now && !binding.axis_active)
{
// Transición de inactivo a activo
binding.axis_active = true;
return true;
}
else if (!axis_active_now && binding.axis_active)
{
// Transición de activo a inactivo
binding.axis_active = false;
}
// Mantener el estado actual
return false;
}
}

View File

@@ -1,11 +1,11 @@
#pragma once
#include <SDL2/SDL_gamecontroller.h> // para SDL_GameControllerButton, SDL_G...
#include <SDL2/SDL_joystick.h> // para SDL_Joystick
#include <SDL2/SDL_scancode.h> // para SDL_Scancode
#include <SDL2/SDL_stdinc.h> // para Uint8
#include <string> // para string, basic_string
#include <vector> // para vector
#include <SDL2/SDL_gamecontroller.h> // Para SDL_GameControllerButton, SDL_G...
#include <SDL2/SDL_joystick.h> // Para SDL_Joystick
#include <SDL2/SDL_scancode.h> // Para SDL_Scancode
#include <SDL2/SDL_stdinc.h> // Para Uint8
#include <string> // Para string, basic_string
#include <vector> // Para vector
/*
connectedControllers es un vector donde estan todos los mandos encontrados [0 .. n]
@@ -16,7 +16,7 @@ device contiene el tipo de dispositivo a comprobar:
InputDeviceToUse::ANY mirará tanto el teclado como el PRIMER controlador
*/
enum class InputType : int
enum class InputAction : int
{
// Inputs de movimiento
UP,
@@ -38,17 +38,18 @@ enum class InputType : int
WINDOW_INC_SIZE,
WINDOW_DEC_SIZE,
VIDEO_SHADERS,
VIDEO_INTEGER_SCALE,
RESET,
MUTE,
CHANGE_LANG,
SHOWINFO,
SHOW_INFO,
CONFIG,
SWAP_CONTROLLERS,
AUTO_FIRE,
// Input obligatorio
NONE,
NUMBER_OF_INPUTS,
SIZE,
};
constexpr bool INPUT_ALLOW_REPEAT = true;
@@ -64,7 +65,7 @@ enum class InputDeviceToUse : int
class Input
{
private:
// [SINGLETON] Objeto screen privado para Don Melitón
// [SINGLETON] Objeto privado
static Input *input_;
struct KeyBindings
@@ -81,10 +82,11 @@ private:
{
SDL_GameControllerButton button; // GameControllerButton asociado
bool active; // Indica si está activo
bool axis_active; // Estado del eje
// Constructor
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false)
: button(btn), active(act) {}
explicit ControllerBindings(SDL_GameControllerButton btn = SDL_CONTROLLER_BUTTON_INVALID, bool act = false, bool axis_act = false)
: button(btn), active(act), axis_active(axis_act) {}
};
// Variables
@@ -93,13 +95,13 @@ private:
std::vector<KeyBindings> key_bindings_; // Vector con las teclas asociadas a los inputs predefinidos
std::vector<std::vector<ControllerBindings>> controller_bindings_; // Vector con los botones asociadas a los inputs predefinidos para cada mando
std::vector<std::string> controller_names_; // Vector con los nombres de los mandos
std::vector<InputType> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
std::vector<InputAction> button_inputs_; // Inputs asignados al jugador y a botones, excluyendo direcciones
int num_joysticks_ = 0; // Número de joysticks conectados
int num_gamepads_ = 0; // Número de mandos conectados
std::string game_controller_db_path_; // Ruta al archivo gamecontrollerdb.txt
// Comprueba el eje del mando
bool checkAxisInput(InputType input, int controller_index = 0) const;
bool checkAxisInput(InputAction input, int controller_index, bool repeat);
// Constructor
explicit Input(const std::string &game_controller_db_path);
@@ -108,24 +110,24 @@ private:
~Input() = default;
public:
// [SINGLETON] Crearemos el objeto screen con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &game_controller_db_path);
// [SINGLETON] Destruiremos el objeto screen con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Input *get();
// Asigna inputs a teclas
void bindKey(InputType input, SDL_Scancode code);
void bindKey(InputAction input, SDL_Scancode code);
// Asigna inputs a botones del mando
void bindGameControllerButton(int controller_index, InputType input, SDL_GameControllerButton button);
void bindGameControllerButton(int controller_index, InputType inputTarget, InputType inputSource);
void bindGameControllerButton(int controller_index, InputAction input, SDL_GameControllerButton button);
void bindGameControllerButton(int controller_index, InputAction inputTarget, InputAction inputSource);
// Comprueba si un input esta activo
bool checkInput(InputType input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
bool checkInput(InputAction input, bool repeat = true, InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
// Comprueba si hay almenos un input activo
bool checkAnyInput(InputDeviceToUse device = InputDeviceToUse::ANY, int controller_index = 0);
@@ -152,13 +154,13 @@ public:
void printBindings(InputDeviceToUse device = InputDeviceToUse::KEYBOARD, int controller_index = 0) const;
// Obtiene el SDL_GameControllerButton asignado a un input
SDL_GameControllerButton getControllerBinding(int controller_index, InputType input) const;
SDL_GameControllerButton getControllerBinding(int controller_index, InputAction input) const;
// Convierte un InputType a std::string
std::string to_string(InputType input) const;
// Convierte un InputAction a std::string
std::string to_string(InputAction input) const;
// Convierte un std::string a InputType
InputType to_inputs_e(const std::string &name) const;
// Convierte un std::string a InputAction
InputAction to_inputs_e(const std::string &name) const;
// Obtiene el indice a partir del nombre del mando
int getIndexByName(const std::string &name) const;

View File

@@ -1,14 +1,14 @@
#include "instructions.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <algorithm> // Para max
#include <utility> // Para move
#include <vector> // Para vector
#include "fade.h" // Para Fade, FadeMode, FadeType
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check, update
#include "jail_audio.h" // Para JA_GetMusicState, JA_Music_state
#include "lang.h" // Para getText
#include "param.h" // Para Param, param, ParamGame, ParamFade
@@ -17,10 +17,8 @@
#include "section.h" // Para Name, name, Options, options
#include "sprite.h" // Para Sprite
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR, TEXT_...
#include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, shdw_txt_color, Zone, no_color
#include "mouse.h"
// Constructor
Instructions::Instructions()
@@ -46,6 +44,9 @@ Instructions::Instructions()
fade_->setMode(FadeMode::IN);
fade_->activate();
// Inicializa las líneas con un retraso progresivo de 50 ms
lines_ = initializeLines(256);
// Rellena la textura de texto
fillTexture();
@@ -159,7 +160,6 @@ void Instructions::fillTexture()
text_->writeDX(TEXT_CENTER | TEXT_COLOR | TEXT_SHADOW, param.game.game_area.center_x, anchor2, lang::getText(16), 1, orange_color, 1, shdw_txt_color);
const int anchor3 = anchor2 + space_post_header;
// const int anchor4 = anchor3 + ((param.game.item_size + text->getCharacterSize()) / 2);
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 0, lang::getText(17), shdw_txt_color);
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 1, lang::getText(18), shdw_txt_color);
text_->writeShadowed(anchor_item + desp_x, anchor3 + space_between_item_lines * 2, lang::getText(19), shdw_txt_color);
@@ -201,18 +201,13 @@ void Instructions::fillBackbuffer()
// Actualiza las variables
void Instructions::update()
{
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
// Mantiene la música sonando
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
updateMusic();
// Actualiza el objeto screen
Screen::get()->update();
@@ -226,27 +221,23 @@ void Instructions::update()
// Actualiza los sprites
updateSprites();
// Gestiona la textura con los graficos
updateBackbuffer();
// Actualiza el mosaico de fondo
tiled_bg_->update();
// Actualiza el objeto "fade"
fade_->update();
// Comprueba si el contador ha llegado al final
if (counter_ == counter_end_)
{
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
}
// Rellena el backbuffer
fillBackbuffer();
}
}
// Pinta en pantalla
void Instructions::render()
{
// Rellena el backbuffer
fillBackbuffer();
// Prepara para empezar a dibujar en la textura de juego
Screen::get()->start();
@@ -256,11 +247,11 @@ void Instructions::render()
// Dibuja el mosacico de fondo
tiled_bg_->render();
// Establece la ventana del backbuffer
view_.y = std::max(0, param.game.height - counter_ + 100);
// Copia la textura y el backbuffer al renderizador
SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_);
if (view_.y == 0)
renderLines(renderer_, backbuffer_, lines_);
else
SDL_RenderCopy(renderer_, backbuffer_, nullptr, &view_);
fade_->render();
@@ -268,60 +259,19 @@ void Instructions::render()
Screen::get()->render();
}
// Recarga todas las texturas
void Instructions::reloadTextures()
{
for (auto &texture : item_textures_)
{
texture->reLoad();
}
text_->reLoadTexture();
fillTexture();
}
// Comprueba los eventos
void Instructions::checkEvents()
{
// Comprueba los eventos que hay en la cola
SDL_Event event;
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba si se ha cambiado el tamaño de la ventana
else if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
}
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
// Comprueba las entradas
void Instructions::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
{
// JA_StopMusic();
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
section::attract_mode = section::AttractMode::TITLE_TO_DEMO;
return;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
@@ -335,4 +285,100 @@ void Instructions::run()
checkEvents(); // Tiene que ir antes del render
render();
}
}
// Método para inicializar las líneas
std::vector<Line> Instructions::initializeLines(int height)
{
std::vector<Line> lines;
for (int y = 0; y < height; y++)
{
int direction = (y % 2 == 0) ? -1 : 1; // Pares a la izquierda, impares a la derecha
lines.emplace_back(y, 0.0f, direction);
}
return lines;
}
// Método para mover las líneas con suavizado
bool Instructions::moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay)
{
Uint32 currentTime = SDL_GetTicks();
bool allLinesOffScreen = true;
for (auto &line : lines)
{
// Establecer startTime en el primer cuadro de animación
if (line.startTime == 0)
{
line.startTime = currentTime + line.y * startDelay;
}
float elapsedTime = (currentTime - line.startTime) / 1000.0f; // Convertir a segundos
if (elapsedTime < 0)
{
allLinesOffScreen = false; // Si aún no se debe mover esta línea, no están todas fuera de pantalla
continue;
}
if (elapsedTime >= duration)
{
continue; // Si la línea ha salido de los límites, no la muevas más
}
float t = elapsedTime / duration;
float smoothFactor = easeInOutQuint(t);
line.x = line.direction * smoothFactor * width;
allLinesOffScreen = false; // Si alguna línea aún se está moviendo, no están todas fuera de pantalla
}
return allLinesOffScreen;
}
// Método para renderizar las líneas
void Instructions::renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines)
{
for (const auto &line : lines)
{
SDL_Rect srcRect = {0, line.y, 320, 1};
SDL_Rect dstRect = {static_cast<int>(line.x), line.y, 320, 1};
SDL_RenderCopy(renderer, texture, &srcRect, &dstRect);
}
}
// Gestiona la musica
void Instructions::updateMusic()
{
if ((JA_GetMusicState() == JA_MUSIC_INVALID) || (JA_GetMusicState() == JA_MUSIC_STOPPED))
{
JA_PlayMusic(Resource::get()->getMusic("title.ogg"));
}
}
// Gestiona la textura con los graficos
void Instructions::updateBackbuffer()
{
// Establece la ventana del backbuffer
view_.y = std::max(0, param.game.height - counter_ + 100);
// Verifica si view_.y == 0 y gestiona el temporizador
if (view_.y == 0)
{
if (!start_delay_triggered_)
{
// Activa el temporizador si no ha sido activado
start_delay_triggered_ = true;
start_delay_time_ = SDL_GetTicks();
}
else if (SDL_GetTicks() - start_delay_time_ >= 4000)
{
// Han pasado tres segundos, mover líneas
all_lines_off_screen_ = moveLines(lines_, 320, 1.0f, 5);
}
}
// Comprueba si el contador ha llegado al final
if (all_lines_off_screen_)
{
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
}
}

View File

@@ -24,6 +24,19 @@ class TiledBG; // lines 12-12
por la pantalla sobre el mosaico de fondo (gestionado por el correspondiente objeto)
*/
// Estructura para almacenar información de línea
struct Line
{
int y; // Coordenada Y de la línea
float x; // Coordenada X inicial (usamos float para mayor precisión en el suavizado)
int direction; // Dirección de movimiento: -1 para izquierda, 1 para derecha
Uint32 startTime; // Tiempo de inicio del movimiento
// Constructor de Line
Line(int y, float x, int direction)
: y(y), x(x), direction(direction), startTime(0) {}
};
// Clase Instructions
class Instructions
{
@@ -40,12 +53,15 @@ private:
std::unique_ptr<Fade> fade_; // Objeto para renderizar fades
// Variables
int counter_ = 0; // Contador
int counter_end_ = 700; // Valor final para el contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_; // Vista del backbuffer que se va amostrar por pantalla
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite
int item_space_ = 2; // Espacio entre los items
int counter_ = 0; // Contador para manejar el progreso en la pantalla de instrucciones
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
SDL_Rect view_; // Vista del backbuffer que se va a mostrar por pantalla
SDL_Point sprite_pos_ = {0, 0}; // Posición del primer sprite en la lista
int item_space_ = 2; // Espacio entre los items en pantalla
std::vector<Line> lines_; // Vector que contiene las líneas animadas en la pantalla
bool all_lines_off_screen_ = false; // Indica si todas las líneas han salido de la pantalla
Uint32 start_delay_time_ = 0; // Tiempo de inicio del retraso para mover las líneas
bool start_delay_triggered_ = false; // Bandera para determinar si el retraso ha comenzado
// Actualiza las variables
void update();
@@ -71,8 +87,20 @@ private:
// Actualiza los sprites
void updateSprites();
// Recarga todas las texturas
void reloadTextures();
// Método para inicializar las líneas
std::vector<Line> initializeLines(int height);
// Método para mover las líneas
bool moveLines(std::vector<Line> &lines, int width, float duration, Uint32 startDelay);
// Método para renderizar las líneas
void renderLines(SDL_Renderer *renderer, SDL_Texture *texture, const std::vector<Line> &lines);
// Gestiona la musica
void updateMusic();
// Gestiona la textura con los graficos
void updateBackbuffer();
public:
// Constructor

View File

@@ -1,243 +1,117 @@
#include "intro.h"
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // Para move
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_StopMusic, JA_PlayMusic
#include "lang.h" // Para getText
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "smart_sprite.h" // Para SmartSprite
#include "text.h" // Para Text
#include "texture.h" // Para Texture
#include "utils.h" // Para Zone, BLOCK, Color, bg_color
#include "writer.h" // Para Writer
#include "mouse.h"
#include <SDL2/SDL_blendmode.h> // Para SDL_BLENDMODE_BLEND, SDL_BLENDMODE_MOD
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_SetTextureBlendMode, SDL_GetRend...
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <array> // Para array
#include <functional> // Para function
#include <string> // Para basic_string, string
#include <utility> // Para move
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check, update
#include "jail_audio.h" // Para JA_PlayMusic, JA_StopMusic
#include "lang.h" // Para getText
#include "param.h" // Para Param, ParamGame, param
#include "path_sprite.h" // Para PathSprite, PathType
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "texture.h" // Para Texture
#include "tiled_bg.h" // Para TiledBG, TiledBGMode
#include "utils.h" // Para Color, Zone, easeOutQuint, BLOCK
#include "writer.h" // Para Writer
// Constructor
Intro::Intro()
: texture_(Resource::get()->getTexture("intro.png")),
text_(Resource::get()->getText("nokia"))
: tiled_bg_(std::make_unique<TiledBG>(param.game.game_area.rect, TiledBGMode::DIAGONAL))
{
// Inicializa variables
section::name = section::Name::INTRO;
section::options = section::Options::NONE;
// Inicializa los bitmaps de la intro
constexpr int totalBitmaps = 6;
for (int i = 0; i < totalBitmaps; ++i)
{
auto ss = std::make_unique<SmartSprite>(texture_);
ss->setWidth(128);
ss->setHeight(96);
ss->setFinishedCounter(20);
ss->setDestX(param.game.game_area.center_x - 64);
ss->setDestY(param.game.game_area.first_quarter_y - 24);
bitmaps_.push_back(std::move(ss));
}
// Inicializa las imagens
initSprites();
bitmaps_[0]->setPosX(-128);
bitmaps_[0]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps_[0]->setVelX(0.0f);
bitmaps_[0]->setVelY(0.0f);
bitmaps_[0]->setAccelX(0.6f);
bitmaps_[0]->setAccelY(0.0f);
bitmaps_[0]->setSpriteClip(0, 0, 128, 96);
// Inicializa los textos
initTexts();
bitmaps_[1]->setPosX(param.game.width);
bitmaps_[1]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps_[1]->setVelX(-1.0f);
bitmaps_[1]->setVelY(0.0f);
bitmaps_[1]->setAccelX(-0.3f);
bitmaps_[1]->setAccelY(0.0f);
bitmaps_[1]->setSpriteClip(128, 0, 128, 96);
bitmaps_[2]->setPosX(param.game.game_area.center_x - 64);
bitmaps_[2]->setPosY(-96);
bitmaps_[2]->setVelX(0.0f);
bitmaps_[2]->setVelY(3.0f);
bitmaps_[2]->setAccelX(0.1f);
bitmaps_[2]->setAccelY(0.3f);
bitmaps_[2]->setSpriteClip(0, 96, 128, 96);
bitmaps_[2]->setFinishedCounter(250);
bitmaps_[3]->setPosX(param.game.game_area.center_x - 64);
bitmaps_[3]->setPosY(param.game.height);
bitmaps_[3]->setVelX(0.0f);
bitmaps_[3]->setVelY(-0.7f);
bitmaps_[3]->setAccelX(0.0f);
bitmaps_[3]->setAccelY(0.0f);
bitmaps_[3]->setSpriteClip(128, 96, 128, 96);
bitmaps_[4]->setPosX(param.game.game_area.center_x - 64);
bitmaps_[4]->setPosY(-96);
bitmaps_[4]->setVelX(0.0f);
bitmaps_[4]->setVelY(3.0f);
bitmaps_[4]->setAccelX(0.1f);
bitmaps_[4]->setAccelY(0.3f);
bitmaps_[4]->setSpriteClip(0, 192, 128, 96);
bitmaps_[5]->setPosX(param.game.width);
bitmaps_[5]->setPosY(param.game.game_area.first_quarter_y - 24);
bitmaps_[5]->setVelX(-0.7f);
bitmaps_[5]->setVelY(0.0f);
bitmaps_[5]->setAccelX(0.0f);
bitmaps_[5]->setAccelY(0.0f);
bitmaps_[5]->setSpriteClip(128, 192, 128, 96);
// Inicializa los textos de la intro
constexpr int totalTexts = 9;
for (int i = 0; i < totalTexts; ++i)
{
auto w = std::make_unique<Writer>(text_);
w->setPosX(BLOCK * 0);
w->setPosY(param.game.height - (BLOCK * 6));
w->setKerning(-1);
w->setEnabled(false);
w->setFinishedCounter(180);
texts_.push_back(std::move(w));
}
// Un dia qualsevol de l'any 2000
texts_[0]->setCaption(lang::getText(27));
texts_[0]->setSpeed(8);
// Tot esta tranquil a la UPV
texts_[1]->setCaption(lang::getText(28));
texts_[1]->setSpeed(8);
// Fins que un desaprensiu...
texts_[2]->setCaption(lang::getText(29));
texts_[2]->setSpeed(12);
// HEY! ME ANE A FERME UN CORTAET...
texts_[3]->setCaption(lang::getText(30));
texts_[3]->setSpeed(8);
// UAAAAAAAAAAAAA!!!
texts_[4]->setCaption(lang::getText(31));
texts_[4]->setSpeed(1);
// Espera un moment...
texts_[5]->setCaption(lang::getText(32));
texts_[5]->setSpeed(16);
// Si resulta que no tinc solt!
texts_[6]->setCaption(lang::getText(33));
texts_[6]->setSpeed(2);
// MERDA DE MAQUINA!
texts_[7]->setCaption(lang::getText(34));
texts_[7]->setSpeed(3);
// Blop... blop... blop...
texts_[8]->setCaption(lang::getText(35));
texts_[8]->setSpeed(16);
for (auto &text : texts_)
text->center(param.game.game_area.center_x);
}
// Recarga todas las texturas
void Intro::reloadTextures()
{
texture_->reLoad();
text_->reLoadTexture();
// Configura el fondo
tiled_bg_->setSpeed(0.3f);
tiled_bg_->setColor(Color(bg_color_, bg_color_, bg_color_));
}
// Comprueba los eventos
void Intro::checkEvents()
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_QUIT:
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
case SDL_WINDOWEVENT:
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
break;
}
default:
break;
}
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
// Comprueba las entradas
void Intro::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
{
JA_StopMusic();
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
return;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
void Intro::checkInput() { globalInputs::check(); }
// Actualiza las escenas de la intro
void Intro::updateScenes()
{
switch (scene_)
{
case 1:
{ // Primera imagen - UPV
if (!bitmaps_[0]->hasFinished())
{
bitmaps_[0]->setEnabled(true);
}
case 0:
{
// Primera imagen - UPV
sprites_.at(0)->enable();
shadow_sprites_.at(0)->enable();
// Primer texto de la primera imagen
if (bitmaps_[0]->hasFinished() && !texts_[0]->hasFinished())
if (sprites_.at(0)->hasFinished() && !texts_.at(0)->hasFinished())
{
texts_[0]->setEnabled(true);
texts_.at(0)->setEnabled(true);
}
// Segundo texto de la primera imagen
if (texts_[0]->hasFinished() && !texts_[1]->hasFinished())
if (texts_.at(0)->hasFinished() && !texts_.at(1)->hasFinished())
{
texts_[0]->setEnabled(false);
texts_[1]->setEnabled(true);
texts_.at(0)->setEnabled(false);
texts_.at(1)->setEnabled(true);
}
// Tercer texto de la primera imagen
if (texts_[1]->hasFinished() && !texts_[2]->hasFinished())
if (texts_.at(1)->hasFinished() && !texts_.at(2)->hasFinished())
{
texts_[1]->setEnabled(false);
texts_[2]->setEnabled(true);
texts_.at(1)->setEnabled(false);
texts_.at(2)->setEnabled(true);
}
// Fin de la primera escena
if (texts_[2]->hasFinished())
if (texts_.at(2)->hasFinished())
{
bitmaps_[0]->setEnabled(false);
texts_[2]->setEnabled(false);
texts_.at(2)->setEnabled(false);
scene_++;
}
break;
}
case 1:
{
// Segunda imagen - Máquina
sprites_.at(1)->enable();
shadow_sprites_.at(1)->enable();
// Primer texto de la segunda imagen
if (sprites_.at(1)->hasFinished() && !texts_.at(3)->hasFinished())
{
texts_.at(3)->setEnabled(true);
}
// Fin de la segunda escena
if (texts_.at(3)->hasFinished())
{
texts_.at(3)->setEnabled(false);
scene_++;
}
@@ -245,41 +119,48 @@ void Intro::updateScenes()
}
case 2:
{ // Segunda imagen - Máquina
if (!bitmaps_[1]->hasFinished())
{
// Tercera imagen junto con primer texto - GRITO
if (!texts_.at(4)->hasFinished())
{
bitmaps_[1]->setEnabled(true);
sprites_.at(2)->enable();
shadow_sprites_.at(2)->enable();
texts_.at(4)->setEnabled(true);
}
// Primer texto de la segunda imagen
if (bitmaps_[1]->hasFinished() && !texts_[3]->hasFinished())
// Fin de la tercera escena
if (sprites_.at(2)->hasFinished() && texts_.at(4)->hasFinished())
{
texts_[3]->setEnabled(true);
}
// Fin de la segunda escena
if (texts_[3]->hasFinished())
{
bitmaps_[1]->setEnabled(false);
texts_[3]->setEnabled(false);
texts_.at(4)->setEnabled(false);
scene_++;
}
break;
}
case 3:
{ // Tercera imagen junto con primer texto - GRITO
if (!bitmaps_[2]->hasFinished() && !texts_[4]->hasFinished())
{
// Cuarta imagen junto con primer texto - Reflexión
sprites_.at(3)->enable();
shadow_sprites_.at(3)->enable();
if (!texts_.at(5)->hasFinished())
{
bitmaps_[2]->setEnabled(true);
texts_[4]->setEnabled(true);
texts_.at(5)->setEnabled(true);
}
// Fin de la tercera escena
if (bitmaps_[2]->hasFinished() && texts_[4]->hasFinished())
// Segundo texto de la cuarta imagen
if (texts_.at(5)->hasFinished() && !texts_.at(6)->hasFinished())
{
bitmaps_[2]->setEnabled(false);
texts_[4]->setEnabled(false);
texts_.at(5)->setEnabled(false);
texts_.at(6)->setEnabled(true);
}
// Fin de la cuarta escena
if (sprites_.at(3)->hasFinished() && texts_.at(6)->hasFinished())
{
texts_.at(6)->setEnabled(false);
scene_++;
}
@@ -287,25 +168,21 @@ void Intro::updateScenes()
}
case 4:
{ // Cuarta imagen junto con primer texto - Reflexión
if (!bitmaps_[3]->hasFinished() && !texts_[5]->hasFinished())
{
// Quinta imagen - Patada
sprites_.at(4)->enable();
shadow_sprites_.at(4)->enable();
// Primer texto de la quinta imagen
if (!texts_.at(7)->hasFinished())
{
bitmaps_[3]->setEnabled(true);
texts_[5]->setEnabled(true);
texts_.at(7)->setEnabled(true);
}
// Segundo texto de la cuarta imagen
if (texts_[5]->hasFinished() && !texts_[6]->hasFinished())
// Fin de la quinta escena
if (sprites_.at(4)->hasFinished() && texts_.at(7)->hasFinished())
{
texts_[5]->setEnabled(false);
texts_[6]->setEnabled(true);
}
// Fin de la cuarta escena
if (bitmaps_[3]->hasFinished() && texts_[6]->hasFinished())
{
bitmaps_[3]->setEnabled(false);
texts_[6]->setEnabled(false);
texts_.at(7)->setEnabled(false);
scene_++;
}
@@ -313,45 +190,27 @@ void Intro::updateScenes()
}
case 5:
{ // Quinta imagen - Patada
if (!bitmaps_[4]->hasFinished())
{
bitmaps_[4]->setEnabled(true);
}
{
// Sexta imagen junto con texto - Globos de café
sprites_.at(5)->enable();
shadow_sprites_.at(5)->enable();
// Primer texto de la quinta imagen
if (bitmaps_[4]->hasFinished() && !texts_[7]->hasFinished())
if (!texts_.at(8)->hasFinished())
{
texts_[7]->setEnabled(true);
}
// Fin de la quinta escena
if (bitmaps_[4]->hasFinished() && texts_[7]->hasFinished())
{
bitmaps_[4]->setEnabled(false);
texts_[7]->setEnabled(false);
scene_++;
}
break;
}
case 6:
{ // Sexta imagen junto con texto - Globos de café
if (!bitmaps_[5]->hasFinished() && !texts_[8]->hasFinished())
{
bitmaps_[5]->setEnabled(true);
texts_[8]->setEnabled(true);
texts_.at(8)->setEnabled(true);
}
// Acaba el último texto
if (bitmaps_[5]->hasFinished() && texts_[8]->hasFinished())
if (texts_.at(8)->hasFinished())
{
bitmaps_[5]->setEnabled(false);
texts_[8]->setEnabled(false);
JA_StopMusic();
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
texts_.at(8)->setEnabled(false);
}
// Acaba la ultima imagen
if (sprites_.at(5)->hasFinished() && texts_.at(8)->hasFinished())
{
state_ = IntroState::POST;
state_start_time_ = SDL_GetTicks();
}
break;
@@ -365,30 +224,30 @@ void Intro::updateScenes()
// Actualiza las variables del objeto
void Intro::update()
{
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
// Actualiza el fondo
tiled_bg_->update();
switch (state_)
{
case IntroState::SCENES:
updateSprites();
updateTexts();
updateScenes();
break;
case IntroState::POST:
updatePostState();
break;
}
// Actualiza el objeto screen
Screen::get()->update();
// Actualiza los objetos
for (auto &bitmap : bitmaps_)
{
bitmap->update();
}
for (auto &text : texts_)
{
text->update();
}
// Actualiza las escenas de la intro
updateScenes();
// Actualiza las variables de globalInputs
globalInputs::update();
}
@@ -403,15 +262,19 @@ void Intro::render()
// Limpia la pantalla
Screen::get()->clean(bg_color);
// Dibuja los objetos
for (const auto &bitmap : bitmaps_)
{
bitmap->render();
}
// Dibuja el fondo
tiled_bg_->render();
for (const auto &text : texts_)
switch (state_)
{
text->render();
case IntroState::SCENES:
{
renderSprites();
renderTexts();
break;
}
case IntroState::POST:
break;
}
// Vuelca el contenido del renderizador en pantalla
@@ -429,4 +292,237 @@ void Intro::run()
checkEvents(); // Tiene que ir antes del render
render();
}
}
}
// Inicializa las imagens
void Intro::initSprites()
{
// Listado de imagenes a usar
const std::array<std::string, 6> TEXTURE_LIST = {
"intro1.png",
"intro2.png",
"intro3.png",
"intro4.png",
"intro5.png",
"intro6.png"};
// Constantes
auto texture = Resource::get()->getTexture(TEXTURE_LIST.front());
const int SPRITE_WIDTH = texture->getWidth();
const int SPRITE_HEIGHT = texture->getHeight();
const int X_DEST = param.game.game_area.center_x - SPRITE_WIDTH / 2;
const int Y_DEST = param.game.game_area.first_quarter_y - (SPRITE_HEIGHT / 4);
// Inicializa los sprites con las imagenes
constexpr int TOTAL_SPRITES = 6;
for (int i = 0; i < TOTAL_SPRITES; ++i)
{
auto sprite = std::make_unique<PathSprite>(Resource::get()->getTexture(TEXTURE_LIST.at(i)));
sprite->setWidth(SPRITE_WIDTH);
sprite->setHeight(SPRITE_HEIGHT);
sprite->setSpriteClip(0, 0, SPRITE_WIDTH, SPRITE_HEIGHT);
sprites_.push_back(std::move(sprite));
}
sprites_.at(0)->addPath(-SPRITE_WIDTH - 10, X_DEST, PathType::HORIZONTAL, Y_DEST, 100, easeInOutExpo, 0);
sprites_.at(1)->addPath(param.game.width, X_DEST, PathType::HORIZONTAL, Y_DEST, 100, easeOutBounce, 0);
sprites_.at(2)->addPath(-SPRITE_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, 40, easeOutQuint, 0);
sprites_.at(3)->addPath(param.game.height, Y_DEST, PathType::VERTICAL, X_DEST, 300, easeInOutExpo, 0);
sprites_.at(4)->addPath(-SPRITE_HEIGHT, Y_DEST, PathType::VERTICAL, X_DEST, 70, easeOutElastic, 0);
sprites_.at(5)->addPath(param.game.width, X_DEST, PathType::HORIZONTAL, Y_DEST, 250, easeOutQuad, 450);
sprites_.at(5)->addPath(X_DEST, -SPRITE_WIDTH, PathType::HORIZONTAL, Y_DEST, 80, easeInElastic, 0);
// Constantes
const int BORDER = 4;
const int SHADOW_SPRITE_WIDTH = SPRITE_WIDTH + BORDER;
const int SHADOW_SPRITE_HEIGHT = SPRITE_HEIGHT + BORDER;
const int S_X_DEST = X_DEST - BORDER / 2;
const int S_Y_DEST = Y_DEST - BORDER / 2;
// Crea las texturas para las imágenes traseras
std::vector<std::shared_ptr<Texture>> shadow_textures;
for (int i = 0; i < TOTAL_SPRITES; ++i)
{
auto shadow_texture = std::make_shared<Texture>(Screen::get()->getRenderer());
shadow_texture->createBlank(SHADOW_SPRITE_WIDTH, SHADOW_SPRITE_HEIGHT, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET);
shadow_texture->setBlendMode(SDL_BLENDMODE_BLEND);
auto temp = SDL_GetRenderTarget(Screen::get()->getRenderer());
shadow_texture->setAsRenderTarget(Screen::get()->getRenderer());
SDL_SetRenderDrawColor(Screen::get()->getRenderer(), 0xFF, 0x00, 0x00, 0xFF);
SDL_RenderClear(Screen::get()->getRenderer());
SDL_Rect rect = {BORDER / 2, BORDER / 2, SPRITE_WIDTH, SPRITE_HEIGHT};
auto inner_texture = Resource::get()->getTexture(TEXTURE_LIST.at(i))->getSDLTexture();
SDL_SetTextureBlendMode(inner_texture, SDL_BLENDMODE_MOD);
SDL_RenderCopy(Screen::get()->getRenderer(), inner_texture, nullptr, &rect);
SDL_SetTextureBlendMode(inner_texture, SDL_BLENDMODE_NONE);
SDL_SetRenderTarget(Screen::get()->getRenderer(), temp);
shadow_textures.push_back(shadow_texture);
}
// Inicializa los sprites para la sombra
for (int i = 0; i < TOTAL_SPRITES; ++i)
{
auto sprite = std::make_unique<PathSprite>(shadow_textures.at(i));
sprite->setWidth(SHADOW_SPRITE_WIDTH);
sprite->setHeight(SHADOW_SPRITE_HEIGHT);
sprite->setSpriteClip(0, 0, SHADOW_SPRITE_WIDTH, SHADOW_SPRITE_HEIGHT);
shadow_sprites_.push_back(std::move(sprite));
}
shadow_sprites_.at(0)->addPath(param.game.height + 10, S_Y_DEST, PathType::VERTICAL, S_X_DEST, 100, easeInOutExpo, 0);
shadow_sprites_.at(1)->addPath(-SHADOW_SPRITE_HEIGHT, S_Y_DEST, PathType::VERTICAL, S_X_DEST, 100, easeOutBounce, 0);
shadow_sprites_.at(2)->addPath(-SHADOW_SPRITE_WIDTH, S_X_DEST, PathType::HORIZONTAL, S_Y_DEST, 40, easeOutQuint, 0);
shadow_sprites_.at(3)->addPath(-SHADOW_SPRITE_HEIGHT, S_Y_DEST, PathType::VERTICAL, S_X_DEST, 400, easeInOutExpo, 0);
shadow_sprites_.at(4)->addPath(param.game.height, S_Y_DEST, PathType::VERTICAL, S_X_DEST, 70, easeOutElastic, 0);
shadow_sprites_.at(5)->addPath(-SHADOW_SPRITE_HEIGHT, S_Y_DEST, PathType::VERTICAL, S_X_DEST, 250, easeOutQuad, 450);
shadow_sprites_.at(5)->addPath(S_X_DEST, param.game.width, PathType::HORIZONTAL, S_Y_DEST, 80, easeInElastic, 0);
}
// Inicializa los textos
void Intro::initTexts()
{
constexpr int TOTAL_TEXTS = 9;
for (int i = 0; i < TOTAL_TEXTS; ++i)
{
auto w = std::make_unique<Writer>(Resource::get()->getText("04b_25_metal"));
w->setPosX(BLOCK * 0);
w->setPosY(param.game.height - (BLOCK * 6));
w->setKerning(-2);
w->setEnabled(false);
w->setFinishedCounter(180);
texts_.push_back(std::move(w));
}
// Un dia qualsevol de l'any 2000
texts_.at(0)->setCaption(lang::getText(27));
texts_.at(0)->setSpeed(8);
// Tot esta tranquil a la UPV
texts_.at(1)->setCaption(lang::getText(28));
texts_.at(1)->setSpeed(8);
// Fins que un desaprensiu...
texts_.at(2)->setCaption(lang::getText(29));
texts_.at(2)->setSpeed(12);
// HEY! ME ANE A FERME UN CORTAET...
texts_.at(3)->setCaption(lang::getText(30));
texts_.at(3)->setSpeed(8);
// UAAAAAAAAAAAAA!!!
texts_.at(4)->setCaption(lang::getText(31));
texts_.at(4)->setSpeed(1);
// Espera un moment...
texts_.at(5)->setCaption(lang::getText(32));
texts_.at(5)->setSpeed(16);
// Si resulta que no tinc solt!
texts_.at(6)->setCaption(lang::getText(33));
texts_.at(6)->setSpeed(2);
// MERDA DE MAQUINA!
texts_.at(7)->setCaption(lang::getText(34));
texts_.at(7)->setSpeed(3);
// Blop... blop... blop...
texts_.at(8)->setCaption(lang::getText(35));
texts_.at(8)->setSpeed(20);
for (auto &text : texts_)
{
text->center(param.game.game_area.center_x);
}
}
// Actualiza los sprites
void Intro::updateSprites()
{
for (auto &sprite : sprites_)
{
sprite->update();
}
for (auto &sprite : shadow_sprites_)
{
sprite->update();
}
}
// Actualiza los textos
void Intro::updateTexts()
{
for (auto &text : texts_)
{
text->update();
}
}
// Dibuja los sprites
void Intro::renderSprites()
{
shadow_sprites_.at(scene_)->render();
sprites_.at(scene_)->render();
}
// Dibuja los textos
void Intro::renderTexts()
{
for (const auto &text : texts_)
{
text->render();
}
}
// Actualiza el estado POST
void Intro::updatePostState()
{
const Uint32 ELAPSED_TIME = SDL_GetTicks() - state_start_time_;
switch (post_state_)
{
case IntroPostState::STOP_BG:
// EVENTO: Detiene el fondo después de 2 segundos
if (ELAPSED_TIME >= 1000)
{
tiled_bg_->stopGracefully();
// Modifica el color del fondo hasta llegar a blanco
if (bg_color_ <= 253) // Garantiza que no se exceda de 255 al incrementar de 2 en 2
{
bg_color_ += 2;
}
else
{
bg_color_ = 255; // Asegura que bg_color_ no exceda el límite máximo
}
tiled_bg_->setColor(Color(bg_color_, bg_color_, bg_color_));
}
// Cambia de estado si el fondo se ha detenido y recuperado el color
if (tiled_bg_->isStopped() && bg_color_ == 255)
{
post_state_ = IntroPostState::END;
state_start_time_ = SDL_GetTicks();
}
break;
case IntroPostState::END:
// Finaliza la intro después de 1 segundo
if (ELAPSED_TIME >= 1000)
{
JA_StopMusic();
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
}
break;
default:
break;
}
}

View File

@@ -1,12 +1,11 @@
#pragma once
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para unique_ptr, shared_ptr
#include <SDL2/SDL_stdinc.h> // Para Uint32, Uint8
#include <memory> // Para unique_ptr
#include <vector> // Para vector
#include "smart_sprite.h" // Para SmartSprite
#include "path_sprite.h" // Para PathSprite
#include "tiled_bg.h" // Para TiledBG
#include "writer.h" // Para Writer
class Text; // lines 8-8
class Texture; // lines 9-9
/*
Esta clase gestiona un estado del programa. Se encarga de mostrar la secuencia
@@ -17,16 +16,31 @@ class Texture; // lines 9-9
class Intro
{
private:
// Objetos
std::shared_ptr<Texture> texture_; // Textura con los graficos
std::shared_ptr<Text> text_; // Textos de la intro
enum class IntroState
{
SCENES,
POST,
};
std::vector<std::unique_ptr<SmartSprite>> bitmaps_; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
enum class IntroPostState
{
STOP_BG,
END,
};
// Objetos
std::vector<std::unique_ptr<PathSprite>> sprites_; // Vector con los sprites inteligentes para los dibujos de la intro
std::vector<std::unique_ptr<PathSprite>> shadow_sprites_; // Vector con los sprites inteligentes para las sombras
std::vector<std::unique_ptr<Writer>> texts_; // Textos de la intro
std::unique_ptr<TiledBG> tiled_bg_;
// Variables
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
int scene_ = 1; // Indica que escena está activa
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
int scene_ = 0; // Indica que escena está activa
IntroState state_ = IntroState::SCENES; // Estado
IntroPostState post_state_ = IntroPostState::STOP_BG; // Estado
Uint32 state_start_time_;
Uint8 bg_color_ = 112;
// Actualiza las variables del objeto
void update();
@@ -43,8 +57,26 @@ private:
// Actualiza las escenas de la intro
void updateScenes();
// Recarga todas las texturas
void reloadTextures();
// Inicializa las imagens
void initSprites();
// Inicializa los textos
void initTexts();
// Actualiza los sprites
void updateSprites();
// Actualiza los textos
void updateTexts();
// Dibuja los sprites
void renderSprites();
// Dibuja los textos
void renderTexts();
// Actualiza el estado POST
void updatePostState();
public:
// Constructor

View File

@@ -1,29 +1,30 @@
#pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_stdinc.h> // para Uint16
#include <memory> // para shared_ptr, unique_ptr
#include <string> // para string
#include <vector> // para vector
#include "animated_sprite.h" // para SpriteAnimated
#include "utils.h" // para Circle
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_stdinc.h> // Para Uint16
#include <memory> // Para shared_ptr, unique_ptr
#include <string> // Para string
#include <vector> // Para vector
#include "animated_sprite.h" // Para SpriteAnimated
#include "utils.h" // Para Circle
class Texture;
/**
* @brief Tipos de objetos disponibles en el juego.
*
* Esta enumeración define los diferentes tipos de objetos que pueden existir en el juego,
* Esta enumeración define los diferentes tipos de objetos que pueden existir en el juego,
* cada uno con un identificador único.
*/
enum class ItemType : int
{
DISK = 1, /**< Disco */
GAVINA = 2, /**< Gavina */
PACMAR = 3, /**< Pacman */
CLOCK = 4, /**< Reloj */
COFFEE = 5, /**< Café */
COFFEE_MACHINE = 6,/**< Máquina de café */
NONE = 7, /**< Ninguno */
DISK = 1, /**< Disco */
GAVINA = 2, /**< Gavina */
PACMAR = 3, /**< Pacman */
CLOCK = 4, /**< Reloj */
COFFEE = 5, /**< Café */
DEBIAN = 6, /**< Debian */
COFFEE_MACHINE = 7, /**< Máquina de café */
NONE = 8, /**< Ninguno */
};
/**

View File

@@ -1,23 +1,22 @@
#ifndef NO_SHADERS
#include "jail_shader.h"
#include <SDL2/SDL_rect.h> // para SDL_Point
#include <stdlib.h> // para NULL, free, malloc, exit
#include <string.h> // para strncmp
#include <iostream> // para basic_ostream, char_traits, operator<<
#include <SDL2/SDL_rect.h> // Para SDL_Point
#include <SDL2/SDL_stdinc.h> // Para SDL_bool
#include <cstring> // Para strncmp
#include <iostream> // Para basic_ostream, operator<<, endl, cout
#include <stdexcept> // Para runtime_error
#include <vector> // Para vector
#ifdef __APPLE__
#include "CoreFoundation/CoreFoundation.h"
#include <OpenGL/OpenGL.h>
#include "CoreFoundation/CoreFoundation.h" // Para Core Foundation en macOS
#include <OpenGL/OpenGL.h> // Para OpenGL en macOS
#if ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#include <OpenGL/gl3.h>
#else
#include <OpenGL/gl.h>
#endif //! ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else
#include <SDL2/SDL_opengl.h>
#endif
#include <OpenGL/gl3.h> // Para OpenGL 3 en macOS
#else // NO ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#include <OpenGL/gl.h> // Para OpenGL (compatibilidad) en macOS
#endif // ESSENTIAL_GL_PRACTICES_SUPPORT_GL3
#else // SI NO ES __APPLE__
#include <SDL2/SDL_opengl.h> // Para GLuint, glTexCoord2f, glVertex2f, GLfloat
#endif // __APPLE__
namespace shader
{
@@ -27,12 +26,10 @@ namespace shader
SDL_Texture *backBuffer = nullptr;
SDL_Point win_size = {320 * 4, 256 * 4};
SDL_Point tex_size = {320, 256};
bool usingOpenGL;
bool usingOpenGL = false;
#ifndef __APPLE__
// I'm avoiding the use of GLEW or some extensions handler, but that
// doesn't mean you should...
// Declaración de funciones de extensión de OpenGL (evitando GLEW)
PFNGLCREATESHADERPROC glCreateShader;
PFNGLSHADERSOURCEPROC glShaderSource;
PFNGLCOMPILESHADERPROC glCompileShader;
@@ -68,120 +65,125 @@ namespace shader
glLinkProgram && glValidateProgram && glGetProgramiv && glGetProgramInfoLog &&
glUseProgram;
}
#endif
GLuint compileShader(const char *source, GLuint shaderType)
// Función para compilar un shader a partir de un std::string
GLuint compileShader(const std::string &source, GLuint shaderType)
{
// Create ID for shader
GLuint result = glCreateShader(shaderType);
// Add define depending on shader type
const char *sources[2] = {shaderType == GL_VERTEX_SHADER ? "#define VERTEX\n" : "#define FRAGMENT\n", source};
// Define shader text
glShaderSource(result, 2, sources, NULL);
// Compile shader
glCompileShader(result);
// Check vertex shader for errors
GLint shaderCompiled = GL_FALSE;
glGetShaderiv(result, GL_COMPILE_STATUS, &shaderCompiled);
if (shaderCompiled != GL_TRUE)
if (source.empty())
{
std::cout << "Error en la compilación: " << result << "!" << std::endl;
GLint logLength;
glGetShaderiv(result, GL_INFO_LOG_LENGTH, &logLength);
if (logLength > 0)
{
GLchar *log = (GLchar *)malloc(logLength);
glGetShaderInfoLog(result, logLength, &logLength, log);
std::cout << "Shader compile log:" << log << std::endl;
free(log);
}
glDeleteShader(result);
result = 0;
// } else {
// std::cout << "Shader compilado correctamente. Id = " << result << std::endl;
throw std::runtime_error("ERROR FATAL: El código fuente del shader está vacío.");
}
return result;
// Crear identificador del shader
GLuint resultado = glCreateShader(shaderType);
// Agregar una directiva según el tipo de shader
std::string directiva = (shaderType == GL_VERTEX_SHADER)
? "#define VERTEX\n"
: "#define FRAGMENT\n";
const char *sources[2] = {directiva.c_str(), source.c_str()};
// Especificar el código fuente del shader
glShaderSource(resultado, 2, sources, nullptr);
// Compilar el shader
glCompileShader(resultado);
// Verificar si la compilación fue exitosa
GLint compiladoCorrectamente = GL_FALSE;
glGetShaderiv(resultado, GL_COMPILE_STATUS, &compiladoCorrectamente);
if (compiladoCorrectamente != GL_TRUE)
{
std::cout << "Error en la compilación del shader (" << resultado << ")!" << std::endl;
GLint longitudLog;
glGetShaderiv(resultado, GL_INFO_LOG_LENGTH, &longitudLog);
if (longitudLog > 0)
{
std::vector<GLchar> log(longitudLog);
glGetShaderInfoLog(resultado, longitudLog, &longitudLog, log.data());
std::cout << "Registro de compilación del shader: " << log.data() << std::endl;
}
glDeleteShader(resultado);
resultado = 0;
}
return resultado;
}
GLuint compileProgram(const char *vertexShaderSource, const char *fragmentShaderSource)
// Función para compilar un programa de shaders (vertex y fragment) a partir de std::string
GLuint compileProgram(const std::string &vertexShaderSource, const std::string &fragmentShaderSource)
{
GLuint programId = 0;
GLuint vtxShaderId, fragShaderId;
GLuint idPrograma = glCreateProgram();
programId = glCreateProgram();
// Si el fragment shader está vacío, reutilizamos el código del vertex shader
GLuint idShaderVertice = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint idShaderFragmento = compileShader(fragmentShaderSource.empty() ? vertexShaderSource : fragmentShaderSource, GL_FRAGMENT_SHADER);
vtxShaderId = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
fragShaderId = compileShader(fragmentShaderSource ? fragmentShaderSource : vertexShaderSource, GL_FRAGMENT_SHADER);
if (vtxShaderId && fragShaderId)
if (idShaderVertice && idShaderFragmento)
{
// Associate shader with program
glAttachShader(programId, vtxShaderId);
glAttachShader(programId, fragShaderId);
glLinkProgram(programId);
glValidateProgram(programId);
// Asociar los shaders al programa
glAttachShader(idPrograma, idShaderVertice);
glAttachShader(idPrograma, idShaderFragmento);
glLinkProgram(idPrograma);
glValidateProgram(idPrograma);
// Check the status of the compile/link
GLint logLen;
glGetProgramiv(programId, GL_INFO_LOG_LENGTH, &logLen);
if (logLen > 0)
// Verificar el estado del enlace
GLint longitudLog;
glGetProgramiv(idPrograma, GL_INFO_LOG_LENGTH, &longitudLog);
if (longitudLog > 0)
{
char *log = (char *)malloc(logLen * sizeof(char));
// Show any errors as appropriate
glGetProgramInfoLog(programId, logLen, &logLen, log);
std::cout << "Prog Info Log: " << std::endl
<< log << std::endl;
free(log);
std::vector<char> log(longitudLog);
glGetProgramInfoLog(idPrograma, longitudLog, &longitudLog, log.data());
std::cout << "Registro de información del programa:" << std::endl
<< log.data() << std::endl;
}
}
if (vtxShaderId)
if (idShaderVertice)
{
glDeleteShader(vtxShaderId);
glDeleteShader(idShaderVertice);
}
if (fragShaderId)
if (idShaderFragmento)
{
glDeleteShader(fragShaderId);
glDeleteShader(idShaderFragmento);
}
return programId;
return idPrograma;
}
const bool init(SDL_Window *win, SDL_Texture *backBuffer, const char *vertexShader, const char *fragmentShader)
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader)
{
shader::win = win;
shader::renderer = SDL_GetRenderer(win);
shader::backBuffer = backBuffer;
SDL_GetWindowSize(win, &win_size.x, &win_size.y);
int access;
SDL_QueryTexture(backBuffer, NULL, &access, &tex_size.x, &tex_size.y);
if (access != SDL_TEXTUREACCESS_TARGET)
shader::win = ventana;
shader::renderer = SDL_GetRenderer(ventana);
shader::backBuffer = texturaBackBuffer;
SDL_GetWindowSize(ventana, &win_size.x, &win_size.y);
int acceso;
SDL_QueryTexture(texturaBackBuffer, nullptr, &acceso, &tex_size.x, &tex_size.y);
if (acceso != SDL_TEXTUREACCESS_TARGET)
{
std::cout << "ERROR FATAL: La textura per al render ha de tindre SDL_TEXTUREACCESS_TARGET definit." << std::endl;
exit(1);
throw std::runtime_error("ERROR FATAL: La textura debe tener definido SDL_TEXTUREACCESS_TARGET.");
}
SDL_RendererInfo rendererInfo;
SDL_GetRendererInfo(renderer, &rendererInfo);
SDL_RendererInfo infoRenderer;
SDL_GetRendererInfo(renderer, &infoRenderer);
if (!strncmp(rendererInfo.name, "opengl", 6))
// Verificar que el renderer sea OpenGL
if (!strncmp(infoRenderer.name, "opengl", 6))
{
// std::cout << "Es OpenGL!" << std::endl;
#ifndef __APPLE__
if (!initGLExtensions())
{
std::cout << "WARNING: No s'han pogut inicialitzar les extensions d'OpenGL!" << std::endl;
std::cout << "ADVERTENCIA: No se han podido inicializar las extensiones de OpenGL." << std::endl;
usingOpenGL = false;
return false;
}
#endif
// Compilar el shader y dejarlo listo para usar.
// Compilar el programa de shaders utilizando std::string
programId = compileProgram(vertexShader, fragmentShader);
// std::cout << "programId = " << programId << std::endl;
}
else
{
std::cout << "WARNING: El driver del renderer no es OpenGL." << std::endl;
std::cout << "ADVERTENCIA: El driver del renderer no es OpenGL." << std::endl;
usingOpenGL = false;
return false;
}
@@ -192,48 +194,90 @@ namespace shader
void render()
{
GLint oldProgramId;
// Guarrada para obtener el textureid (en driverdata->texture)
// Detach the texture
// Establece el color de fondo
SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
SDL_SetRenderTarget(renderer, NULL);
SDL_SetRenderTarget(renderer, nullptr);
SDL_RenderClear(renderer);
if (usingOpenGL)
{
SDL_GL_BindTexture(backBuffer, NULL, NULL);
SDL_GL_BindTexture(backBuffer, nullptr, nullptr);
if (programId != 0)
{
glGetIntegerv(GL_CURRENT_PROGRAM, &oldProgramId);
glUseProgram(programId);
}
GLfloat minx, miny, maxx, maxy;
GLfloat minu, maxu, minv, maxv;
// Recupera el tamaño lógico configurado con SDL_RenderSetLogicalSize
int logicalW, logicalH;
SDL_RenderGetLogicalSize(renderer, &logicalW, &logicalH);
if (logicalW == 0 || logicalH == 0)
{
logicalW = win_size.x;
logicalH = win_size.y;
}
// Coordenadas de la ventana donde pintar.
minx = 0.0f;
miny = 0.0f;
maxx = tex_size.x;
maxy = tex_size.y;
// Cálculo del viewport
int viewportX = 0, viewportY = 0, viewportW = win_size.x, viewportH = win_size.y;
SDL_bool useIntegerScale = SDL_RenderGetIntegerScale(renderer);
if (useIntegerScale)
{
// Calcula el factor de escalado entero máximo que se puede aplicar
int scaleX = win_size.x / logicalW;
int scaleY = win_size.y / logicalH;
int scale = (scaleX < scaleY ? scaleX : scaleY);
if (scale < 1)
scale = 1;
viewportW = logicalW * scale;
viewportH = logicalH * scale;
viewportX = (win_size.x - viewportW) / 2;
viewportY = (win_size.y - viewportH) / 2;
}
else
{
// Letterboxing: preserva la relación de aspecto usando una escala flotante
float windowAspect = static_cast<float>(win_size.x) / win_size.y;
float logicalAspect = static_cast<float>(logicalW) / logicalH;
if (windowAspect > logicalAspect)
{
viewportW = static_cast<int>(logicalAspect * win_size.y);
viewportX = (win_size.x - viewportW) / 2;
}
else
{
viewportH = static_cast<int>(win_size.x / logicalAspect);
viewportY = (win_size.y - viewportH) / 2;
}
}
glViewport(viewportX, viewportY, viewportW, viewportH);
minu = 0.0f;
maxu = 1.0f;
minv = 0.0f;
maxv = 1.0f;
// Configurar la proyección ortográfica usando el espacio lógico
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glViewport(0, 0, win_size.x, win_size.y);
// Queremos que el origen esté en la esquina superior izquierda del espacio lógico.
glOrtho(0, static_cast<GLdouble>(logicalW), static_cast<GLdouble>(logicalH), 0, -1, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
// Dibuja el quad con las coordenadas ajustadas.
// Se asignan las coordenadas de textura "normales" para que no quede espejado horizontalmente,
// y se mantiene el flip vertical para que la imagen no aparezca volteada.
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(minu, minv);
glVertex2f(minx, miny);
glTexCoord2f(maxu, minv);
glVertex2f(maxx, miny);
glTexCoord2f(minu, maxv);
glVertex2f(minx, maxy);
glTexCoord2f(maxu, maxv);
glVertex2f(maxx, maxy);
// Vértice superior izquierdo
glTexCoord2f(0.0f, 1.0f);
glVertex2f(0.0f, 0.0f);
// Vértice superior derecho
glTexCoord2f(1.0f, 1.0f);
glVertex2f(static_cast<GLfloat>(logicalW), 0.0f);
// Vértice inferior izquierdo
glTexCoord2f(0.0f, 0.0f);
glVertex2f(0.0f, static_cast<GLfloat>(logicalH));
// Vértice inferior derecho
glTexCoord2f(1.0f, 0.0f);
glVertex2f(static_cast<GLfloat>(logicalW), static_cast<GLfloat>(logicalH));
glEnd();
SDL_GL_SwapWindow(win);
if (programId != 0)
@@ -243,9 +287,8 @@ namespace shader
}
else
{
SDL_RenderCopy(renderer, backBuffer, NULL, NULL);
SDL_RenderCopy(renderer, backBuffer, nullptr, nullptr);
SDL_RenderPresent(renderer);
}
}
}
#endif
}

View File

@@ -1,9 +1,8 @@
#ifndef NO_SHADERS
#pragma once
#include <SDL2/SDL_render.h> // para SDL_Texture
#include <SDL2/SDL_video.h> // para SDL_Window
#include <SDL2/SDL_render.h> // Para SDL_Texture
#include <SDL2/SDL_video.h> // Para SDL_Window
#include <string>
// TIPS:
// =======================================================================
@@ -40,9 +39,7 @@
namespace shader
{
const bool init(SDL_Window *win, SDL_Texture *backBuffer,
const char *vertexShader, const char *fragmentShader = nullptr);
// const bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const char *vertexShader, const char *fragmentShader = nullptr);
bool init(SDL_Window *ventana, SDL_Texture *texturaBackBuffer, const std::string &vertexShader, const std::string &fragmentShader = "");
void render();
}
#endif
}

View File

@@ -1,6 +1,6 @@
#include "lang.h"
#include <fstream> // para basic_ifstream, basic_istream, ifstream
#include <vector> // para vector
#include <fstream> // Para basic_ifstream, basic_istream, ifstream
#include <vector> // Para vector
namespace lang
{
@@ -41,10 +41,10 @@ namespace lang
return texts.at(index);
}
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang)
// Obtiene el codigo del idioma del siguiente idioma
Code getNextLangCode(Code lang)
{
auto index = static_cast<int>(current_lang);
auto index = static_cast<int>(lang);
index = (index + 1) % 3;
return static_cast<Code>(index);
}

View File

@@ -1,6 +1,6 @@
#pragma once
#include <string> // para string
#include <string> // Para string
namespace lang
{
@@ -17,6 +17,6 @@ namespace lang
// Obtiene la cadena de texto del indice
std::string getText(int index);
// Cambia el idioma seleccionado al siguiente idioma disponible
Code change(Code current_lang);
// Obtiene el codigo del idioma del siguiente idioma
Code getNextLangCode(Code lang);
}

View File

@@ -1,45 +1,41 @@
#include "logo.h"
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event, SDL_QUIT, SDL...
#include <SDL2/SDL_events.h> // Para SDL_PollEvent, SDL_Event
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <SDL2/SDL_video.h> // Para SDL_WINDOWEVENT_SIZE_CHANGED
#include <utility> // Para move
#include "global_inputs.h" // Para check
#include "input.h" // Para Input
#include "jail_audio.h" // Para JA_StopMusic
#include "global_events.h" // Para check
#include "global_inputs.h" // Para check, update
#include "jail_audio.h" // Para JA_FadeOutMusic, JA_PlaySound, JA_StopC...
#include "param.h" // Para Param, ParamGame, param
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "section.h" // Para Name, name, Options, options
#include "section.h" // Para Name, name
#include "sprite.h" // Para Sprite
#include "texture.h" // Para Texture
#include "utils.h" // Para Color, Zone
#include "mouse.h"
// Constructor
Logo::Logo()
: since_texture_(Resource::get()->getTexture("logo_since_1998.png")),
since_sprite_(std::make_unique<Sprite>(since_texture_)),
jail_texture_(Resource::get()->getTexture("logo_jailgames.png")),
ticks_(0)
jail_texture_(Resource::get()->getTexture("logo_jailgames.png"))
{
// Inicializa variables
counter_ = 0;
section::name = section::Name::LOGO;
dest_.x = param.game.game_area.center_x - jail_texture_->getWidth() / 2;
dest_.y = param.game.game_area.center_y - jail_texture_->getHeight() / 2;
since_sprite_->setPosition({(param.game.width - since_texture_->getWidth()) / 2, 83 + jail_texture_->getHeight() + 5, since_texture_->getWidth(), since_texture_->getHeight()});
since_sprite_->setY(dest_.y + jail_texture_->getHeight() + 5);
since_sprite_->setSpriteClip(0, 0, since_texture_->getWidth(), since_texture_->getHeight());
since_texture_->setColor(0x00, 0x00, 0x00); // Esto en linux no hace nada ??
since_texture_->setColor(0x00, 0x00, 0x00);
// Crea los sprites de cada linea
for (int i = 0; i < jail_texture_->getHeight(); ++i)
{
auto temp = std::make_unique<Sprite>(jail_texture_, 0, i, jail_texture_->getWidth(), 1);
temp->setSpriteClip(0, i, jail_texture_->getWidth(), 1);
const int posX = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setX(posX);
const int POS_X = (i % 2 == 0) ? param.game.width + (i * 3) : -jail_texture_->getWidth() - (i * 3);
temp->setX(POS_X);
temp->setY(dest_.y + i);
jail_sprite_.push_back(std::move(temp));
}
@@ -63,58 +59,23 @@ Logo::~Logo()
JA_StopChannel(-1);
}
// Recarga todas las texturas
void Logo::reloadTextures()
{
jail_texture_->reLoad();
since_texture_->reLoad();
}
// Comprueba el manejador de eventos
void Logo::checkEvents()
{
SDL_Event event;
// Comprueba los eventos que hay en la cola
while (SDL_PollEvent(&event))
{
// Evento de salida de la aplicación
if (event.type == SDL_QUIT)
{
section::name = section::Name::QUIT;
section::options = section::Options::QUIT_FROM_EVENT;
break;
}
// Comprueba si se ha cambiado el tamaño de la ventana
else if (event.type == SDL_WINDOWEVENT)
{
if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED)
{
reloadTextures();
}
}
// Comprueba el cursor
Mouse::handleEvent(event);
globalEvents::check(event);
}
}
// Comprueba las entradas
void Logo::checkInput()
{
// Comprueba si se ha pulsado cualquier botón (de los usados para jugar)
if (Input::get()->checkAnyButtonPressed())
{
section::name = section::Name::TITLE;
section::options = section::Options::TITLE_1;
return;
}
// Comprueba los inputs que se pueden introducir en cualquier sección del juego
globalInputs::check();
}
// Gestiona el logo de JAILGAME
// Gestiona el logo de JAILGAMES
void Logo::updateJAILGAMES()
{
if (counter_ == 30)
@@ -147,6 +108,12 @@ void Logo::updateJAILGAMES()
}
}
}
// Comprueba si ha terminado el logo
if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
{
section::name = section::Name::INTRO;
}
}
// Gestiona el color de las texturas
@@ -177,9 +144,7 @@ void Logo::updateTextureColors()
// Actualiza las variables
void Logo::update()
{
constexpr int TICKS_SPEED = 15;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
if (SDL_GetTicks() - ticks_ > param.game.speed)
{
// Actualiza el contador de ticks
ticks_ = SDL_GetTicks();
@@ -190,21 +155,12 @@ void Logo::update()
// Comprueba las entradas
checkInput();
// Gestiona el logo de JAILGAME
updateJAILGAMES();
// Gestiona el color de las texturas
updateTextureColors();
// Gestiona el contador y sus eventos
// Gestiona el contador
counter_++;
// Comprueba si ha terminado el logo
if (counter_ == END_LOGO_COUNTER_MARK + POST_LOGO_DURATION)
{
section::name = section::Name::INTRO;
}
// Actualiza las variables de globalInputs
globalInputs::update();
}
@@ -213,24 +169,11 @@ void Logo::update()
// Dibuja en pantalla
void Logo::render()
{
// Prepara para empezar a dibujar en la textura de juego
Screen::get()->start();
// Limpia la pantalla
Screen::get()->clean();
// Dibuja los sprites
for (auto &sprite : jail_sprite_)
{
sprite->render();
}
renderJAILGAMES();
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
{
since_sprite_->render();
}
// Vuelca el contenido del renderizador en pantalla
Screen::get()->render();
}
@@ -247,4 +190,19 @@ void Logo::run()
checkEvents(); // Tiene que ir antes del render
render();
}
}
// Renderiza el logo de JAILGAMES
void Logo::renderJAILGAMES()
{
// Dibuja los sprites
for (auto &sprite : jail_sprite_)
{
sprite->render();
}
if (counter_ >= SHOW_SINCE_SPRITE_COUNTER_MARK)
{
since_sprite_->render();
}
}

View File

@@ -4,9 +4,9 @@
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <memory> // Para shared_ptr, unique_ptr
#include <vector> // Para vector
class Sprite;
class Texture; // lines 9-9
struct Color;
class Sprite; // lines 8-8
class Texture; // lines 9-9
struct Color; // lines 10-10
/*
Esta clase gestiona un estado del programa. Se encarga de dibujar por pantalla el
@@ -35,8 +35,8 @@ private:
// Variables
std::vector<Color> color_; // Vector con los colores para el fade
int counter_; // Contador
Uint32 ticks_; // Contador de ticks para ajustar la velocidad del programa
int counter_ = 0; // Contador
Uint32 ticks_ = 0; // Contador de ticks para ajustar la velocidad del programa
SDL_Point dest_; // Posición X donde dibujar el logo
// Actualiza las variables
@@ -51,15 +51,15 @@ private:
// Comprueba las entradas
void checkInput();
// Gestiona el logo de JAILGAME
// Gestiona el logo de JAILGAMES
void updateJAILGAMES();
// Renderiza el logo de JAILGAMES
void renderJAILGAMES();
// Gestiona el color de las texturas
void updateTextureColors();
// Recarga todas las texturas
void reloadTextures();
public:
// Constructor
Logo();

View File

@@ -1,9 +1,10 @@
#include "manage_hiscore_table.h"
#include <SDL2/SDL_error.h> // Para SDL_GetError
#include <SDL2/SDL_rwops.h> // Para SDL_RWread, SDL_RWwrite, SDL_RWFromFile
#include <algorithm> // Para sort
#include <algorithm> // Para find_if, sort
#include <iostream> // Para basic_ostream, operator<<, cout, endl
#include "utils.h" // Para HiScoreEntry, getFileName
#include <iterator> // Para distance
#include "utils.h" // Para getFileName
// Resetea la tabla a los valores por defecto
void ManageHiScoreTable::clear()
@@ -27,7 +28,7 @@ void ManageHiScoreTable::clear()
}
// Añade un elemento a la tabla
void ManageHiScoreTable::add(HiScoreEntry entry)
int ManageHiScoreTable::add(const HiScoreEntry &entry)
{
// Añade la entrada a la tabla
table_.push_back(entry);
@@ -35,8 +36,32 @@ void ManageHiScoreTable::add(HiScoreEntry entry)
// Ordena la tabla
sort();
// Encontrar la posición del nuevo elemento
auto it = std::find_if(table_.begin(), table_.end(), [&](const HiScoreEntry &e)
{ return e.name == entry.name &&
e.score == entry.score &&
e.one_credit_complete == entry.one_credit_complete; });
int position = -1;
if (it != table_.end())
{
position = std::distance(table_.begin(), it);
}
// Deja solo las 10 primeras entradas
table_.resize(10);
if (table_.size() > 10)
{
table_.resize(10);
// Si el nuevo elemento quedó fuera del top 10
if (position >= 10)
{
position = -1; // No entró en el top 10
}
}
// Devuelve la posición
return position;
}
// Ordena la tabla
@@ -50,52 +75,55 @@ void ManageHiScoreTable::sort()
std::sort(table_.begin(), table_.end(), scoreDescendingComparator);
}
// Carga la tabla con los datos de un fichero
// Carga la tabla desde un fichero
bool ManageHiScoreTable::loadFromFile(const std::string &file_path)
{
clear();
auto success = true;
auto file = SDL_RWFromFile(file_path.c_str(), "r+b");
auto file = SDL_RWFromFile(file_path.c_str(), "rb");
if (file)
{
std::cout << "Reading file: " << getFileName(file_path) << std::endl;
table_.clear(); // Limpia la tabla actual
for (auto &entry : table_)
// Lee el número de entradas en la tabla
int tableSize = 0;
SDL_RWread(file, &tableSize, sizeof(int), 1);
// Lee los datos de cada entrada
for (int i = 0; i < tableSize; ++i)
{
HiScoreEntry entry;
// Lee la puntuación
SDL_RWread(file, &entry.score, sizeof(int), 1);
// Lee el tamaño del nombre y luego el nombre
int nameSize = 0;
if (SDL_RWread(file, &entry.score, sizeof(int), 1) == 0)
{
success = false;
break;
}
if (SDL_RWread(file, &nameSize, sizeof(int), 1) == 0)
{
success = false;
break;
}
SDL_RWread(file, &nameSize, sizeof(int), 1);
std::vector<char> nameBuffer(nameSize + 1);
if (SDL_RWread(file, nameBuffer.data(), sizeof(char) * nameSize, 1) == 0)
{
success = false;
break;
}
nameBuffer[nameSize] = '\0';
SDL_RWread(file, nameBuffer.data(), nameSize, 1);
nameBuffer[nameSize] = '\0'; // Asegurar el fin de la cadena
entry.name = std::string(nameBuffer.data());
// Lee el valor de one_credit_complete
int occValue = 0;
SDL_RWread(file, &occValue, sizeof(int), 1);
entry.one_credit_complete = (occValue != 0);
// Añade la entrada a la tabla
table_.push_back(entry);
}
std::cout << "Reading file: " << getFileName(file_path) << std::endl;
SDL_RWclose(file);
}
if (!success)
else
{
clear();
std::cout << "Error: Unable to load " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl;
success = false;
}
return success;
}
@@ -107,21 +135,35 @@ bool ManageHiScoreTable::saveToFile(const std::string &file_path)
if (file)
{
// Guarda los datos
for (int i = 0; i < (int)table_.size(); ++i)
// Guarda el número de entradas en la tabla
int tableSize = static_cast<int>(table_.size());
SDL_RWwrite(file, &tableSize, sizeof(int), 1);
// Guarda los datos de cada entrada
for (int i = 0; i < tableSize; ++i)
{
SDL_RWwrite(file, &table_.at(i).score, sizeof(int), 1);
const int nameSize = (int)table_.at(i).name.size();
const HiScoreEntry &entry = table_.at(i);
// Guarda la puntuación
SDL_RWwrite(file, &entry.score, sizeof(int), 1);
// Guarda el tamaño del nombre y luego el nombre
int nameSize = static_cast<int>(entry.name.size());
SDL_RWwrite(file, &nameSize, sizeof(int), 1);
SDL_RWwrite(file, table_.at(i).name.c_str(), nameSize, 1);
SDL_RWwrite(file, entry.name.c_str(), nameSize, 1);
// Guarda el valor de one_credit_complete como un entero (0 o 1)
int occValue = entry.one_credit_complete ? 1 : 0;
SDL_RWwrite(file, &occValue, sizeof(int), 1);
}
std::cout << "Writing file: " << getFileName(file_path).c_str() << std::endl;
std::cout << "Writing file: " << getFileName(file_path) << std::endl;
SDL_RWclose(file);
}
else
{
std::cout << "Error: Unable to save " << getFileName(file_path).c_str() << " file! " << SDL_GetError() << std::endl;
std::cout << "Error: Unable to save " << getFileName(file_path) << " file! " << SDL_GetError() << std::endl;
success = false;
}
return success;
}

View File

@@ -1,7 +1,7 @@
#pragma once
#include <string> // para string
#include <vector> // para vector
#include <string> // Para string
#include <vector> // Para vector
/*
Esta clase sirve para añadir elementos hiScoreEntry_r a un vector (tabla), de manera
@@ -14,12 +14,13 @@
// Estructura para las entradas de la tabla de recirds
struct HiScoreEntry
{
std::string name; // Nombre
int score; // Puntuación
std::string name; // Nombre
int score; // Puntuación
bool one_credit_complete; // Indica si se ha conseguido 1CC
// Constructor
explicit HiScoreEntry(const std::string &n = "", int s = 0)
: name(n), score(s) {}
// Constructor
explicit HiScoreEntry(const std::string &n = "", int s = 0, bool occ = false)
: name(n.substr(0, 6)), score(s), one_credit_complete(occ) {}
};
// Clase ManageHiScoreTable
@@ -44,7 +45,7 @@ public:
void clear();
// Añade un elemento a la tabla
void add(HiScoreEntry entry);
int add(const HiScoreEntry &entry);
// Carga la tabla con los datos de un fichero
bool loadFromFile(const std::string &file_path);

View File

@@ -1,5 +1,4 @@
#include "moving_sprite.h"
#include <algorithm> // Para max
#include "texture.h" // Para Texture
// Constructor
@@ -73,46 +72,7 @@ void MovingSprite::update()
}
// Muestra el sprite por pantalla
void MovingSprite::render()
{
texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, rotate_.center, flip_);
}
// Establece el valor de la variable
void MovingSprite::setZoomW(float value)
{
zoom_w_ = value;
}
// Establece el valor de la variable
void MovingSprite::setZoomH(float value)
{
zoom_h_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAngle(double value)
{
rotate_.angle = value;
}
// Establece el valor de la variable
void MovingSprite::setRotatingCenter(SDL_Point *point)
{
rotate_.center = point;
}
// Incrementa el valor del ángulo
void MovingSprite::updateAngle()
{
rotate_.angle += rotate_.amount;
}
// Obtiene el valor de la variable
bool MovingSprite::isRotating() const
{
return rotate_.enabled;
}
void MovingSprite::render() { texture_->render(pos_.x, pos_.y, &sprite_clip_, zoom_w_, zoom_h_, rotate_.angle, &rotate_.center, flip_); }
// Establece la rotacion
void MovingSprite::rotate()
@@ -135,43 +95,6 @@ void MovingSprite::setRotate(bool enable)
rotate_.counter = 0;
}
// Establece el valor de la variable
void MovingSprite::setRotateSpeed(int value)
{
rotate_.speed = std::max(1, value);
}
// Establece el valor de la variable
void MovingSprite::setRotateAmount(double value)
{
rotate_.amount = value;
}
// Cambia el sentido de la rotación
void MovingSprite::switchRotate()
{
rotate_.amount *= -1;
}
// Establece el valor de la variable
void MovingSprite::setFlip(SDL_RendererFlip flip)
{
flip_ = flip;
}
// Gira el sprite horizontalmente
void MovingSprite::flip()
{
flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL;
}
// Obtiene el valor de la variable
SDL_RendererFlip MovingSprite::getFlip()
{
return flip_;
}
// Establece la posición y_ el tamaño del objeto
void MovingSprite::setPos(SDL_Rect rect)
{
@@ -203,28 +126,4 @@ void MovingSprite::setPosY(float value)
{
y_ = value;
pos_.y = static_cast<int>(y_);
}
// Establece el valor de la variable
void MovingSprite::setVelX(float value)
{
vx_ = value;
}
// Establece el valor de la variable
void MovingSprite::setVelY(float value)
{
vy_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAccelX(float value)
{
ax_ = value;
}
// Establece el valor de la variable
void MovingSprite::setAccelY(float value)
{
ay_ = value;
}

View File

@@ -3,8 +3,9 @@
#include <SDL2/SDL_rect.h> // Para SDL_Rect, SDL_Point
#include <SDL2/SDL_render.h> // Para SDL_RendererFlip
#include <memory> // Para shared_ptr
#include "sprite.h" // Para Sprite
class Texture; // lines 8-8
#include <algorithm>
#include "sprite.h" // Para Sprite
class Texture; // lines 8-8
// Clase MovingSprite. Añade movimiento y efectos de rotación, zoom y flip al sprite
class MovingSprite : public Sprite
@@ -12,14 +13,14 @@ class MovingSprite : public Sprite
public:
struct Rotate
{
bool enabled; // Indica si ha de rotar
int counter; // Contador
int speed; // Velocidad de giro
double angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
SDL_Point *center; // Centro de rotación
bool enabled; // Indica si ha de rotar
int counter; // Contador
int speed; // Velocidad de giro
double angle; // Angulo para dibujarlo
float amount; // Cantidad de grados a girar en cada iteración
SDL_Point center; // Centro de rotación
Rotate() : enabled(false), counter(0), speed(1), angle(0.0), amount(0.0f), center(nullptr) {}
Rotate() : enabled(false), counter(0), speed(1), angle(0.0), amount(0.0f), center({0, 0}) {}
};
protected:
@@ -38,7 +39,7 @@ protected:
SDL_RendererFlip flip_; // Indica como se voltea el sprite
// Incrementa el valor del ángulo
void updateAngle();
void updateAngle() { rotate_.angle += rotate_.amount; }
// Mueve el sprite
void move();
@@ -53,7 +54,7 @@ public:
explicit MovingSprite(std::shared_ptr<Texture> texture);
// Destructor
virtual ~MovingSprite() = default;
virtual ~MovingSprite() override = default;
// Actualiza las variables internas del objeto
virtual void update();
@@ -73,40 +74,40 @@ public:
float getAccelY() const { return ay_; }
// Establece la variable
void setVelX(float value);
void setVelY(float value);
void setAccelX(float value);
void setAccelY(float value);
void setVelX(float value) { vx_ = value; }
void setVelY(float value) { vy_ = value; }
void setAccelX(float value) { ax_ = value; }
void setAccelY(float value) { ay_ = value; }
// Obten el valor de la variable
bool isRotating() const;
bool isRotating() const { return rotate_.enabled; }
// Establece el valor de la variable
void setZoomW(float value);
void setZoomH(float value);
void setZoomW(float value) { zoom_w_ = value; }
void setZoomH(float value) { zoom_h_ = value; }
// Establece el valor de la variable
void setAngle(double vaue);
void setRotatingCenter(SDL_Point *point);
void setAngle(double value) { rotate_.angle = value; }
void setRotatingCenter(SDL_Point point) { rotate_.center = point; }
// Activa o desactiva el efecto de rotación
void setRotate(bool enable);
// Establece el valor de la variable
void setRotateSpeed(int value);
void setRotateAmount(double value);
void setRotateSpeed(int value) { rotate_.speed = std::max(1, value); }
void setRotateAmount(double value) { rotate_.amount = value; }
// Cambia el sentido de la rotación
void switchRotate();
void switchRotate() { rotate_.amount *= -1; }
// Establece el valor de la variable
void setFlip(SDL_RendererFlip flip);
void setFlip(SDL_RendererFlip flip) { flip_ = flip; }
// Gira el sprite horizontalmente
void flip();
void flip() { flip_ = (flip_ == SDL_FLIP_HORIZONTAL) ? SDL_FLIP_NONE : SDL_FLIP_HORIZONTAL; }
// Obtiene el valor de la variable
SDL_RendererFlip getFlip();
SDL_RendererFlip getFlip() { return flip_; }
// Establece la posición y_ el tamaño del objeto
void setPos(SDL_Rect rect);

View File

@@ -12,22 +12,22 @@
#include "texture.h" // Para Texture
#include "resource.h"
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
// [SINGLETON]
Notifier *Notifier::notifier_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
void Notifier::init(const std::string &icon_file, std::shared_ptr<Text> text)
{
Notifier::notifier_ = new Notifier(icon_file, text);
}
// [SINGLETON] Destruiremos el objeto screen con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
void Notifier::destroy()
{
delete Notifier::notifier_;
}
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
Notifier *Notifier::get()
{
return Notifier::notifier_;
@@ -153,7 +153,7 @@ void Notifier::clearFinishedNotifications()
}
}
void Notifier::showText(std::vector<std::string> texts, int icon, const std::string &code)
void Notifier::show(std::vector<std::string> texts, int icon, const std::string &code)
{
// Si no hay texto, acaba
if (texts.empty())
@@ -164,7 +164,7 @@ void Notifier::showText(std::vector<std::string> texts, int icon, const std::str
// Si las notificaciones no se apilan, elimina las anteriores
if (!stack_)
{
clearNotifications();
clearAllNotifications();
}
// Elimina las cadenas vacías
@@ -294,11 +294,8 @@ void Notifier::showText(std::vector<std::string> texts, int icon, const std::str
notifications_.emplace_back(n);
}
// Indica si hay notificaciones activas
bool Notifier::isActive() { return !notifications_.empty(); }
// Finaliza y elimnina todas las notificaciones activas
void Notifier::clearNotifications()
void Notifier::clearAllNotifications()
{
for (auto &notification : notifications_)
{

View File

@@ -13,7 +13,7 @@ class Texture; // lines 11-11
class Notifier
{
private:
// [SINGLETON] Objeto notifier privado para Don Melitón
// [SINGLETON] Objeto notifier
static Notifier *notifier_;
enum class NotificationStatus
@@ -66,7 +66,7 @@ private:
void clearFinishedNotifications();
// Finaliza y elimnina todas las notificaciones activas
void clearNotifications();
void clearAllNotifications();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos notifier desde fuera
@@ -77,13 +77,13 @@ private:
~Notifier() = default;
public:
// [SINGLETON] Crearemos el objeto notifier con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
static void init(const std::string &icon_file, std::shared_ptr<Text> text);
// [SINGLETON] Destruiremos el objeto notifier con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto notifier y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Notifier *get();
// Dibuja las notificaciones por pantalla
@@ -93,11 +93,14 @@ public:
void update();
// Muestra una notificación de texto por pantalla
void showText(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());
void show(std::vector<std::string> texts, int icon = -1, const std::string &code = std::string());
// Indica si hay notificaciones activas
bool isActive();
bool isActive() { return !notifications_.empty(); }
// Obtiene los códigos de las notificaciones
std::vector<std::string> getCodes();
// Comprueba si hay alguna notificacion con un código
bool checkCode(const std::string &code) { return stringInVector(getCodes(), code); }
};

View File

@@ -1,8 +1,8 @@
#pragma once
#include <SDL2/SDL_rect.h> // para SDL_Rect
#include <SDL2/SDL_render.h> // para SDL_Texture
#include <vector> // para vector
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_render.h> // Para SDL_Texture
#include <vector> // Para vector
class Sprite;
class Text;

View File

@@ -25,7 +25,7 @@ void initOptions()
options.video.window.size = 3;
#else
options.video.mode = ScreenVideoMode::WINDOW;
options.video.window.size = 2;
options.video.window.zoom = 2;
#endif
options.video.filter = ScreenFilter::NEAREST;
options.video.v_sync = true;
@@ -44,6 +44,7 @@ void initOptions()
options.game.difficulty = GameDifficulty::NORMAL;
options.game.language = lang::Code::ba_BA;
options.game.autofire = true;
options.game.clear_last_hi_score_entries();
// Opciones de control
options.controllers.clear();
@@ -104,7 +105,7 @@ bool loadOptionsFile(std::string file_path)
options.video.mode = ScreenVideoMode::WINDOW;
}
options.video.window.size = std::clamp(options.video.window.size, 1, 4);
options.video.window.zoom = std::clamp(options.video.window.zoom, 1, 4);
if (options.game.language != lang::Code::en_UK &&
options.game.language != lang::Code::ba_BA &&
@@ -136,7 +137,7 @@ bool saveOptionsFile(std::string file_path)
file << "\n";
file << "video.mode=" << static_cast<int>(options.video.mode) << "\n";
file << "video.window.size=" << options.video.window.size << "\n";
file << "video.window.size=" << options.video.window.zoom << "\n";
file << "video.filter=" << static_cast<int>(options.video.filter) << "\n";
file << "video.v_sync=" << boolToString(options.video.v_sync) << "\n";
file << "video.integer_scale=" << boolToString(options.video.integer_scale) << "\n";
@@ -203,10 +204,10 @@ bool setOptions(const std::string &var, const std::string &value)
}
else if (var == "video.window.size")
{
options.video.window.size = std::stoi(value);
if ((options.video.window.size < 1) || (options.video.window.size > 4))
options.video.window.zoom = std::stoi(value);
if ((options.video.window.zoom < 1) || (options.video.window.zoom > 4))
{
options.video.window.size = 3;
options.video.window.zoom = 3;
}
}
else if (var == "video.filter")

View File

@@ -1,16 +1,17 @@
#pragma once
#include <SDL2/SDL_gamecontroller.h> // Para SDL_CONTROLLER_BUTTON_B, SDL_CO...
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <string> // Para string
#include <vector> // Para vector
#include "input.h" // Para InputType, InputDeviceToUse
#include "input.h" // Para InputAction, InputDeviceToUse
#include "manage_hiscore_table.h" // Para HiScoreEntry
enum class ScreenFilter : int; // lines 10-10
enum class ScreenVideoMode : int; // lines 11-11
enum class ScreenFilter : int; // lines 8-8
enum class ScreenVideoMode : Uint32; // lines 9-9
namespace lang
{
enum class Code : int;
} // lines 14-14
} // lines 12-12
// Dificultad del juego
enum class GameDifficulty
@@ -23,8 +24,8 @@ enum class GameDifficulty
// Estructura para las opciones de la ventana
struct OptionsWindow
{
int size = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana
int max_size = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla
int zoom = 1; // Contiene el valor por el que se multiplica el tamaño de la ventana
int max_zoom = 1; // Tamaño máximo para que el tamaño de la ventana no sea mayor que el tamaño de la pantalla
};
// Estructura con opciones para el video
@@ -64,10 +65,18 @@ struct OptionsAudio
// Estructura para las opciones del juego
struct OptionsGame
{
GameDifficulty difficulty; // Dificultad del juego
lang::Code language; // Idioma usado en el juego
bool autofire; // Indica si el jugador ha de pulsar repetidamente para disparar o basta con mantener pulsado
std::vector<HiScoreEntry> hi_score_table; // Tabla con las mejores puntuaciones
GameDifficulty difficulty; // Dificultad del juego
lang::Code language; // Idioma usado en el juego
bool autofire; // Indicador de autofire
std::vector<HiScoreEntry> hi_score_table; // Tabla de mejores puntuaciones
std::vector<int> last_hi_score_entry = {-1, -1}; // Inicialización directa con dos elementos en -1
// Método para reiniciar las últimas entradas de puntuación
void clear_last_hi_score_entries()
{
last_hi_score_entry[0] = -1;
last_hi_score_entry[1] = -1;
}
};
// Estructura para los controles del juego
@@ -78,13 +87,13 @@ struct OptionsController
InputDeviceToUse type; // Indica si se utilizará teclado o mando o ambos
std::string name; // Nombre del dispositivo
bool plugged; // Indica si el mando se encuentra conectado
std::vector<InputType> inputs; // Listado de inputs
std::vector<InputAction> inputs; // Listado de inputs
std::vector<SDL_GameControllerButton> buttons; // Listado de botones asignados a cada input
// Constructor por defecto
OptionsController()
: index(-1), player_id(-1), type(InputDeviceToUse::CONTROLLER), name(""), plugged(false),
inputs{InputType::FIRE_LEFT, InputType::FIRE_CENTER, InputType::FIRE_RIGHT, InputType::START, InputType::SERVICE},
inputs{InputAction::FIRE_LEFT, InputAction::FIRE_CENTER, InputAction::FIRE_RIGHT, InputAction::START, InputAction::SERVICE},
buttons{SDL_CONTROLLER_BUTTON_X, SDL_CONTROLLER_BUTTON_Y, SDL_CONTROLLER_BUTTON_B, SDL_CONTROLLER_BUTTON_START, SDL_CONTROLLER_BUTTON_BACK} {}
};

View File

@@ -1,10 +1,10 @@
#include "param.h"
#include <fstream> // para char_traits, basic_ostream, basic_ifstream, basi...
#include <iostream> // para cout
#include <fstream> // Para char_traits, basic_ostream, basic_ifstream, basi...
#include <iostream> // Para cout
#include <sstream>
#include <string>
#include <stdexcept>
#include "utils.h" // para Param, ParamGame, Zone, ParamBalloon
#include "utils.h" // Para Param, ParamGame, Zone, ParamBalloon
Param param;
@@ -26,6 +26,7 @@ void initParam()
param.game.game_area.rect = {0, 0, param.game.width, param.game.height};
param.game.play_area.rect = {0, 0, param.game.width, 216};
param.game.enter_name_seconds = 30;
param.game.speed = 15;
precalculateZones();
// SCOREBOARD

View File

@@ -1,9 +1,10 @@
#pragma once
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <string> // Para string
#include <vector> // Para vector
#include "utils.h" // Para Color, Zone
#include <SDL2/SDL_rect.h> // Para SDL_Rect
#include <SDL2/SDL_stdinc.h> // Para Uint32
#include <string> // Para string
#include <vector> // Para vector
#include "utils.h" // Para Color, Zone
// param.game
struct ParamGame
@@ -16,6 +17,7 @@ struct ParamGame
Zone play_area; // Rectangulo con la posición de la zona de juego
Zone game_area; // Rectangulo con las dimensiones del juego
int enter_name_seconds; // Duración en segundos para introducir el nombre al finalizar la partida
Uint32 speed; // Velocidad a la que transcurre el juego
};
// param.fade
@@ -83,7 +85,5 @@ struct Param
extern Param param;
extern Param param;
// Establece valores para los parametros a partir de un fichero de texto
void loadParamsFromFile(const std::string &file_path);

View File

@@ -15,13 +15,9 @@ std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_p
double t = static_cast<double>(i) / (steps - 1);
double value = start + (end - start) * easingFunction(t);
if (start > 0 && end < 0)
if ((start > 0 && end < 0) || (start < 0 && end > 0))
{
value = start - std::abs(end - start) * easingFunction(t);
}
else if (start < 0 && end > 0)
{
value = start + std::abs(end - start) * easingFunction(t);
value = start + (end > 0 ? 1 : -1) * std::abs(end - start) * easingFunction(t);
}
switch (type)
@@ -43,13 +39,22 @@ std::vector<SDL_Point> createPath(int start, int end, PathType type, int fixed_p
// Actualiza la posición y comprueba si ha llegado a su destino
void PathSprite::update()
{
if (enabled_)
if (enabled_ && !has_finished_)
{
moveThroughCurrentPath();
goToNextPathOrDie();
}
}
// Muestra el sprite por pantalla
void PathSprite::render()
{
if (enabled_)
{
Sprite::render();
}
}
// Añade un recorrido
void PathSprite::addPath(Path path, bool centered)
{
@@ -96,7 +101,7 @@ void PathSprite::addPath(std::vector<SDL_Point> spots, int waiting_counter)
// Habilita el objeto
void PathSprite::enable()
{
if (paths_.size() == 0)
if (paths_.size() == 0 || enabled_)
{
return;
}
@@ -105,8 +110,8 @@ void PathSprite::enable()
// Establece la posición
auto &path = paths_.at(current_path_);
const auto &p = path.spots.at(path.counter);
setPosition(p);
const auto &P = path.spots.at(path.counter);
setPosition(P);
}
// Coloca el sprite en los diferentes puntos del recorrido
@@ -133,9 +138,13 @@ void PathSprite::moveThroughCurrentPath()
if (path.on_destination)
{
if (path.waiting_counter == 0)
{
path.finished = true;
}
else
{
--path.waiting_counter;
}
}
}
@@ -144,15 +153,17 @@ void PathSprite::goToNextPathOrDie()
{
// Comprueba si ha terminado el recorrdo actual
if (paths_.at(current_path_).finished)
{
++current_path_;
}
// Comprueba si quedan mas recorridos
if (current_path_ >= static_cast<int>(paths_.size()))
enabled_ = false;
{
has_finished_ = true;
current_path_ = 0;
}
}
// Indica si ha terminado todos los recorridos
bool PathSprite::hasFinished()
{
return !enabled_;
}
bool PathSprite::hasFinished() { return has_finished_; }

View File

@@ -42,9 +42,10 @@ class PathSprite : public Sprite
{
private:
// Variables
bool enabled_ = false; // Indica si el objeto está habilitado
int current_path_ = 0; // Path que se está recorriendo actualmente
std::vector<Path> paths_; // Caminos a recorrer por el sprite
bool enabled_ = false; // Indica si el objeto está habilitado
bool has_finished_ = false; // Indica si el objeto ha finalizado el recorrido
int current_path_ = 0; // Path que se está recorriendo actualmente
std::vector<Path> paths_; // Caminos a recorrer por el sprite
// Coloca el sprite en los diferentes puntos del recorrido
void moveThroughCurrentPath();
@@ -58,15 +59,18 @@ public:
: Sprite(texture) {}
// Destructor
~PathSprite() = default;
~PathSprite() override = default;
// Actualiza la posición del sprite
void update();
// Muestra el sprite por pantalla
void render() override;
// Añade un recorrido
void addPath(Path path, bool centered = false);
void addPath(std::vector<SDL_Point> spots, int waiting_counter);
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter);
void addPath(std::vector<SDL_Point> spots, int waiting_counter = 0);
void addPath(int start, int end, PathType type, int fixed_pos, int steps, const std::function<double(double)> &easingFunction, int waiting_counter = 0);
// Habilita el objeto
void enable();

View File

@@ -4,13 +4,14 @@
#include <stdlib.h> // Para rand
#include <algorithm> // Para clamp, max, min
#include "animated_sprite.h" // Para AnimatedSprite
#include "input.h" // Para InputType
#include "input.h" // Para InputAction
#include "param.h" // Para Param, ParamGame, param
#include "scoreboard.h" // Para Scoreboard, ScoreboardMode
#include "texture.h" // Para Texture
#include "resource.h"
#include "jail_audio.h"
#include "stage.h"
#include <array>
// Constructor
Player::Player(int id, float x, int y, bool demo, SDL_Rect &play_area, std::vector<std::shared_ptr<Texture>> texture, const std::vector<std::vector<std::string>> &animations)
@@ -58,7 +59,7 @@ void Player::init()
score_ = 0;
score_multiplier_ = 1.0f;
cool_down_ = 10;
enter_name_->init();
enter_name_->init(last_enter_name_);
// Establece la posición del sprite
player_sprite_->clear();
@@ -69,7 +70,7 @@ void Player::init()
}
// Actua en consecuencia de la entrada recibida
void Player::setInput(InputType input)
void Player::setInput(InputAction input)
{
switch (playing_state_)
{
@@ -90,33 +91,33 @@ void Player::setInput(InputType input)
}
// Procesa inputs para cuando está jugando
void Player::setInputPlaying(InputType input)
void Player::setInputPlaying(InputAction input)
{
switch (input)
{
case InputType::LEFT:
case InputAction::LEFT:
{
vel_x_ = -BASE_SPEED_;
setWalkingState(PlayerState::WALKING_LEFT);
break;
}
case InputType::RIGHT:
case InputAction::RIGHT:
{
vel_x_ = BASE_SPEED_;
setWalkingState(PlayerState::WALKING_RIGHT);
break;
}
case InputType::FIRE_CENTER:
case InputAction::FIRE_CENTER:
{
setFiringState(PlayerState::FIRING_UP);
break;
}
case InputType::FIRE_LEFT:
case InputAction::FIRE_LEFT:
{
setFiringState(PlayerState::FIRING_LEFT);
break;
}
case InputType::FIRE_RIGHT:
case InputAction::FIRE_RIGHT:
{
setFiringState(PlayerState::FIRING_RIGHT);
break;
@@ -131,23 +132,29 @@ void Player::setInputPlaying(InputType input)
}
// Procesa inputs para cuando está introduciendo el nombre
void Player::setInputEnteringName(InputType input)
void Player::setInputEnteringName(InputAction input)
{
switch (input)
{
case InputType::LEFT:
case InputAction::LEFT:
enter_name_->decPosition();
break;
case InputType::RIGHT:
case InputAction::RIGHT:
enter_name_->incPosition();
break;
case InputType::UP:
case InputAction::UP:
enter_name_->incIndex();
break;
case InputType::DOWN:
case InputAction::DOWN:
enter_name_->decIndex();
break;
case InputType::START:
case InputAction::START:
last_enter_name_ = getRecordName();
if (last_enter_name_.empty())
{
const std::array<std::string, 8> NAMES = {"BAL1", "TABE", "DOC", "MON", "SAM1", "JORDI", "JDES", "PEPE"};
last_enter_name_ = NAMES.at(rand() % NAMES.size());
}
break;
default:
break;
@@ -165,9 +172,9 @@ void Player::move()
pos_x_ += vel_x_;
// Si el jugador abandona el area de juego por los laterales, restaura su posición
const float min_x = play_area_.x - 5;
const float max_x = play_area_.w + 5 - WIDTH_;
pos_x_ = std::clamp(pos_x_, min_x, max_x);
const float MIN_X = play_area_.x - 5;
const float MAX_X = play_area_.w + 5 - WIDTH_;
pos_x_ = std::clamp(pos_x_, MIN_X, MAX_X);
shiftSprite();
break;
@@ -175,12 +182,12 @@ void Player::move()
case PlayerState::DYING:
{
// Si el cadaver abandona el area de juego por los laterales lo hace rebotar
const int x = player_sprite_->getPosX();
const int min_x = play_area_.x;
const int max_x = play_area_.x + play_area_.w - WIDTH_;
if ((x < min_x) || (x > max_x))
const int X = player_sprite_->getPosX();
const int MIN_X = play_area_.x;
const int MAX_X = play_area_.x + play_area_.w - WIDTH_;
if ((X < MIN_X) || (X > MAX_X))
{
player_sprite_->setPosX(std::clamp(x, min_x, max_x));
player_sprite_->setPosX(std::clamp(X, MIN_X, MAX_X));
player_sprite_->setVelX(-player_sprite_->getVelX());
playRandomBubbleSound();
}
@@ -220,10 +227,10 @@ void Player::move()
switch (id_)
{
case 1:
setInputPlaying(InputType::LEFT);
setInputPlaying(InputAction::LEFT);
break;
case 2:
setInputPlaying(InputType::RIGHT);
setInputPlaying(InputAction::RIGHT);
break;
default:
break;
@@ -251,7 +258,7 @@ void Player::move()
switch (id_)
{
case 1:
setInputPlaying(InputType::RIGHT);
setInputPlaying(InputAction::RIGHT);
pos_x_ += vel_x_;
if (pos_x_ > default_pos_x_)
{
@@ -261,7 +268,7 @@ void Player::move()
}
break;
case 2:
setInputPlaying(InputType::LEFT);
setInputPlaying(InputAction::LEFT);
pos_x_ += vel_x_;
if (pos_x_ < default_pos_x_)
{
@@ -281,22 +288,20 @@ void Player::move()
pos_x_ += vel_x_ / 2.0f;
if (vel_x_ > 0)
{
// setInputPlaying(InputType::RIGHT);
// setInputPlaying(InputAction::RIGHT);
if (pos_x_ > param.game.game_area.rect.w - WIDTH_)
{
pos_x_ = param.game.game_area.rect.w - WIDTH_;
vel_x_ *= -1;
// setInputPlaying(InputType::LEFT);
}
}
else
{
// setInputPlaying(InputType::LEFT);
// setInputPlaying(InputAction::LEFT);
if (pos_x_ < param.game.game_area.rect.x)
{
pos_x_ = param.game.game_area.rect.x;
vel_x_ *= -1;
// setInputPlaying(InputType::RIGHT);
}
}
@@ -355,17 +360,20 @@ void Player::setAnimation()
// Establece la animación a partir de las cadenas
if (firing_state_ == PlayerState::FIRING_NONE)
{ // No esta disparando
{
// No esta disparando
player_sprite_->setCurrentAnimation(a_walking);
player_sprite_->setFlip(flip_walk);
}
else if (isCooling())
{ // Acaba de disparar
{
// Acaba de disparar
player_sprite_->setCurrentAnimation(a_walking + "-" + a_cooling + "-cooldown");
player_sprite_->setFlip(flip_cooling);
}
else
{ // Está disparando
{
// Está disparando
player_sprite_->setCurrentAnimation(a_walking + "-" + a_firing);
// Si dispara de lado, invierte el sprite segun hacia donde dispara
// Si dispara recto, invierte el sprite segun hacia donde camina
@@ -449,6 +457,7 @@ void Player::update()
updateInvulnerable();
updateContinueCounter();
updateEnterNameCounter();
updateShowingName();
updateScoreboard();
}
@@ -474,7 +483,7 @@ void Player::updateScoreboard()
case PlayerState::ENTERING_NAME:
case PlayerState::ENTERING_NAME_GAME_COMPLETED:
{
Scoreboard::get()->setRecordName(getScoreBoardPanel(), enter_name_->getName());
Scoreboard::get()->setRecordName(getScoreBoardPanel(), enter_name_->getCurrentName());
Scoreboard::get()->setSelectorPos(getScoreBoardPanel(), getRecordNamePos());
break;
}
@@ -525,12 +534,19 @@ void Player::setPlayingState(PlayerState state)
setScoreboardMode(ScoreboardMode::ENTER_NAME);
break;
}
case PlayerState::SHOWING_NAME:
{
showing_name_ticks_ = SDL_GetTicks();
setScoreboardMode(ScoreboardMode::SHOW_NAME);
Scoreboard::get()->setRecordName(scoreboard_panel_, last_enter_name_);
break;
}
case PlayerState::DYING:
{
// Activa la animación de morir
player_sprite_->setAccelY(0.2f);
player_sprite_->setVelY(-6.6f);
rand() % 2 == 0 ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f);
(rand() % 2 == 0) ? player_sprite_->setVelX(3.3f) : player_sprite_->setVelX(-3.3f);
break;
}
case PlayerState::DIED:
@@ -546,6 +562,7 @@ void Player::setPlayingState(PlayerState state)
}
case PlayerState::CELEBRATING:
{
game_completed_ = true;
setScoreboardMode(ScoreboardMode::SCORE);
break;
}
@@ -711,6 +728,19 @@ void Player::updateEnterNameCounter()
}
}
// Actualiza el estado de SHOWING_NAME
void Player::updateShowingName()
{
if (playing_state_ == PlayerState::SHOWING_NAME)
{
constexpr int TICKS_SPEED = 5000;
if (SDL_GetTicks() - enter_name_ticks_ > TICKS_SPEED)
{
game_completed_ ? setPlayingState(PlayerState::LEAVING_SCREEN) : setPlayingState(PlayerState::CONTINUE);
}
}
}
// Decrementa el contador de continuar
void Player::decContinueCounter()
{

View File

@@ -11,7 +11,7 @@
#include "options.h" // Para Options, OptionsGame, options
#include "utils.h" // Para Circle
class Texture; // lines 13-13
enum class InputType : int; // lines 14-14
enum class InputAction : int; // lines 14-14
enum class ScoreboardMode; // lines 15-15
// Estados del jugador
@@ -34,6 +34,7 @@ enum class PlayerState
CONTINUE, // Está con la cuenta atras para continuar
WAITING, // No está jugando pero puede entrar a jugar
ENTERING_NAME, // Introduciendo nombre
SHOWING_NAME, // Mostrando el nombre introducido
DYING, // El cadaver está volando por ahi
DIED, // El cadaver ha desaparecido por el fondo
GAME_OVER, // No está jugando y no puede entrar a jugar
@@ -92,7 +93,11 @@ private:
bool demo_; // Para que el jugador sepa si está en el modo demostración
int enter_name_counter_; // Contador para poner nombre
Uint32 enter_name_ticks_ = 0; // Variable para poder cambiar el contador de poner nombre en función del tiempo
Uint32 showing_name_ticks_ = 0; // Tiempo en el que se entra al estado SHOWING_NAME
int step_counter_ = 0; // Cuenta los pasos para los estados en los que camina automáticamente
bool game_completed_ = false; // Indica si ha completado el juego
int credits_used_ = 1; // Indica el numero de veces que ha continuado
std::string last_enter_name_; // Ultimo nombre introducido en la tabla de puntuaciones
// Actualiza el circulo de colisión a la posición del jugador
void shiftColliders();
@@ -109,6 +114,9 @@ private:
// Actualiza el contador de entrar nombre
void updateEnterNameCounter();
// Actualiza el estado de SHOWING_NAME
void updateShowingName();
// Decrementa el contador de entrar nombre
void decEnterNameCounter();
@@ -144,13 +152,13 @@ public:
void setPlayerTextures(const std::vector<std::shared_ptr<Texture>> &texture);
// Actua en consecuencia de la entrada recibida
void setInput(InputType input);
void setInput(InputAction input);
// Procesa inputs para cuando está jugando
void setInputPlaying(InputType input);
void setInputPlaying(InputAction input);
// Procesa inputs para cuando está introduciendo el nombre
void setInputEnteringName(InputType input);
void setInputEnteringName(InputAction input);
// Mueve el jugador a la posición y animación que le corresponde
void move();
@@ -200,6 +208,7 @@ public:
bool isContinue() const { return playing_state_ == PlayerState::CONTINUE; }
bool isDying() const { return playing_state_ == PlayerState::DYING; }
bool isEnteringName() const { return playing_state_ == PlayerState::ENTERING_NAME; }
bool isShowingName() const { return playing_state_ == PlayerState::SHOWING_NAME; }
bool isEnteringNameGameCompleted() const { return playing_state_ == PlayerState::ENTERING_NAME_GAME_COMPLETED; }
bool isLeavingScreen() const { return playing_state_ == PlayerState::LEAVING_SCREEN; }
bool isGameOver() const { return playing_state_ == PlayerState::GAME_OVER; }
@@ -224,12 +233,14 @@ public:
int getPosX() const { return static_cast<int>(pos_x_); }
int getPosY() const { return pos_y_; }
int getPowerUpCounter() const { return power_up_counter_; }
std::string getRecordName() const { return enter_name_->getName(); }
std::string getRecordName() const { return enter_name_->getFinalName(); }
int getScore() const { return score_; }
int getScoreBoardPanel() const { return scoreboard_panel_; }
int getWidth() const { return WIDTH_; }
PlayerState getPlayingState() const { return playing_state_; }
std::string getName() const { return name_; }
const std::string &getName() const { return name_; }
bool get1CC() const { return game_completed_ && credits_used_ == 1; }
bool getEnterNamePositionOverflow() const { return enter_name_->getPositionOverflow(); }
// Setters
void setController(int index) { controller_index_ = index; }
@@ -242,4 +253,5 @@ public:
void setScoreBoardPanel(int panel) { scoreboard_panel_ = panel; }
void setScoreMultiplier(float value) { score_multiplier_ = value; }
void setWalkingState(PlayerState state) { walking_state_ = state; }
void addCredit() { ++credits_used_; }
};

View File

@@ -2,14 +2,13 @@
#include <algorithm> // Para find_if
#include <iostream> // Para basic_ostream, operator<<, endl, cout, cerr
#include <stdexcept> // Para runtime_error
#include <utility> // Para pair
#include "asset.h" // Para Asset, AssetType
#include "jail_audio.h" // Para JA_LoadMusic, JA_LoadSound
#include "jail_audio.h" // Para JA_DeleteMusic, JA_DeleteSound, JA_LoadMusic
#include "lang.h" // Para getText
#include "screen.h" // Para Screen
#include "text.h" // Para Text, loadTextFile
struct JA_Music_t; // lines 10-10
struct JA_Sound_t; // lines 11-11
struct JA_Music_t; // lines 11-11
struct JA_Sound_t; // lines 12-12
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Resource *Resource::resource_ = nullptr;
@@ -73,6 +72,14 @@ void Resource::reload()
load();
}
// Recarga las texturas
void Resource::reloadTextures()
{
loadTextures();
addPalettes();
createTextures();
}
// Obtiene el sonido a partir de un nombre
JA_Sound_t *Resource::getSound(const std::string &name)
{
@@ -301,6 +308,7 @@ void Resource::createTextures()
// Tamaño doble
std::vector<NameAndText> strings2X = {
NameAndText("game_text_100000_points", "100.000"),
NameAndText("game_text_get_ready", lang::getText(75)),
NameAndText("game_text_last_stage", lang::getText(79)),
NameAndText("game_text_congratulations", lang::getText(50)),
@@ -314,22 +322,35 @@ void Resource::createTextures()
}
}
// Crea los objetos de texto
void Resource::createText()
{
struct ResourceInfo
{
std::string key; // Identificador del recurso
std::string textureFile; // Nombre del archivo de textura
std::string textFile; // Nombre del archivo de texto
// Constructor para facilitar la creación de objetos ResourceInfo
ResourceInfo(const std::string &k, const std::string &tFile, const std::string &txtFile)
: key(k), textureFile(tFile), textFile(txtFile) {}
};
std::cout << "\n>> CREATING TEXT_OBJECTS" << std::endl;
std::vector<std::pair<std::string, std::string>> resources = {
{"04b_25", "04b_25.png"},
{"04b_25_2x", "04b_25_2x.png"},
{"8bithud", "8bithud.png"},
{"nokia", "nokia.png"},
{"smb2", "smb2.gif"}};
std::vector<ResourceInfo> resources = {
{"04b_25", "04b_25.png", "04b_25.txt"},
{"04b_25_2x", "04b_25_2x.png", "04b_25_2x.txt"},
{"04b_25_metal", "04b_25_metal.png", "04b_25.txt"},
{"04b_25_grey", "04b_25_grey.png", "04b_25.txt"},
{"8bithud", "8bithud.png", "8bithud.txt"},
{"smb2", "smb2.gif", "smb2.txt"}};
for (const auto &resource : resources)
{
texts_.emplace_back(ResourceText(resource.first, std::make_shared<Text>(getTexture(resource.second), getTextFile(resource.first + ".txt"))));
printWithDots("Text : ", resource.first, "[ DONE ]");
texts_.emplace_back(ResourceText(resource.key, std::make_shared<Text>(
getTexture(resource.textureFile),
getTextFile(resource.textFile))));
printWithDots("Text : ", resource.key, "[ DONE ]");
}
}

View File

@@ -170,4 +170,7 @@ public:
// Recarga todos los recursos
void reload();
// Recarga las texturas
void reloadTextures();
};

View File

@@ -5,12 +5,12 @@
#include <math.h> // Para roundf
#include <iomanip> // Para operator<<, setfill, setw
#include <sstream> // Para basic_ostream, basic_ostringstream
#include "enter_name.h" // Para MAX_NAME_LENGHT
#include "lang.h" // Para getText
#include "resource.h" // Para Resource
#include "screen.h" // Para Screen
#include "sprite.h" // Para Sprite
#include "text.h" // Para Text
#include "enter_name.h"
#include "text.h" // Para Text, TEXT_CENTER, TEXT_COLOR
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
Scoreboard *Scoreboard::scoreboard_ = nullptr;
@@ -68,6 +68,9 @@ Scoreboard::Scoreboard()
// Rellena la textura de fondo
fillBackgroundTexture();
// Inicializa el vector de colores para el nombre
iniNameColors();
}
Scoreboard::~Scoreboard()
@@ -86,23 +89,23 @@ Scoreboard::~Scoreboard()
}
}
// Transforma un valor numérico en una cadena de 6 cifras
// Transforma un valor numérico en una cadena de 7 cifras
std::string Scoreboard::updateScoreText(int num)
{
std::ostringstream oss;
oss << std::setw(8) << std::setfill('0') << num;
oss << std::setw(7) << std::setfill('0') << num;
return oss.str();
}
// Actualiza el contador
void Scoreboard::updateCounter()
void Scoreboard::updateTimeCounter()
{
constexpr int TICKS_SPEED = 100;
if (SDL_GetTicks() - ticks_ > TICKS_SPEED)
{
ticks_ = SDL_GetTicks();
counter_++;
++time_counter_;
}
}
@@ -110,7 +113,8 @@ void Scoreboard::updateCounter()
void Scoreboard::update()
{
fillBackgroundTexture();
updateCounter();
updateTimeCounter();
++loop_counter_;
}
// Pinta el marcador
@@ -150,7 +154,7 @@ void Scoreboard::fillPanelTextures()
// Guarda a donde apunta actualmente el renderizador
auto temp = SDL_GetRenderTarget(renderer_);
// Genera el contenidoi de cada panel_
// Genera el contenido de cada panel_
for (size_t i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{
// Cambia el destino del renderizador
@@ -180,7 +184,7 @@ void Scoreboard::fillPanelTextures()
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(101));
// PRESS START TO PLAY
if (counter_ % 10 < 8)
if (time_counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(103));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(104));
@@ -194,7 +198,7 @@ void Scoreboard::fillPanelTextures()
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// PRESS START TO PLAY
if (counter_ % 10 < 8)
if (time_counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(103));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(104));
@@ -208,7 +212,7 @@ void Scoreboard::fillPanelTextures()
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// PLEASE WAIT
if (counter_ % 10 < 8)
if (time_counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(114));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, lang::getText(115));
@@ -253,27 +257,58 @@ void Scoreboard::fillPanelTextures()
text_scoreboard_->writeCentered(slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]));
// ENTER NAME
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106));
SDL_Rect rect = {enter_name_pos_.x, enter_name_pos_.y, 5, 7};
SDL_SetRenderDrawColor(renderer_, 0xFF, 0xFF, 0xEB, 255);
for (size_t j = 0; j < record_name_[i].size(); ++j)
{
if (j != selector_pos_[i] || counter_ % 3 == 0)
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106));
SDL_Rect rect = {enter_name_pos_.x, enter_name_pos_.y, 5, 7};
// Recorre todos los slots de letras del nombre
for (size_t j = 0; j < MAX_NAME_LENGHT; ++j)
{
SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
text_scoreboard_->write(rect.x, rect.y, record_name_[i].substr(j, 1));
// Selecciona el color
const Color color = j < selector_pos_[i] ? orange_soft_color.lighten() : Color(0xFF, 0xFF, 0xEB);
if (j != selector_pos_[i] || time_counter_ % 3 == 0)
{
// Dibuja la linea
if (j >= selector_pos_[i])
{
SDL_SetRenderDrawColor(renderer_, color.r, color.g, color.b, 255);
SDL_RenderDrawLine(renderer_, rect.x, rect.y + rect.h, rect.x + rect.w, rect.y + rect.h);
}
// Dibuja la letra
if (j < record_name_->size())
{
text_scoreboard_->writeColored(rect.x, rect.y, record_name_[i].substr(j, 1), color);
}
}
rect.x += 7;
}
rect.x += 7;
}
break;
}
case ScoreboardMode::SHOW_NAME:
{
// SCORE
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y, name_[i]);
text_scoreboard_->writeCentered(slot4_2_.x, slot4_2_.y, updateScoreText(score_[i]));
// NAME
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y, lang::getText(106));
/* TEXTO CENTRADO */
//text_scoreboard_->writeDX(TEXT_CENTER | TEXT_COLOR, slot4_4_.x, slot4_4_.y, record_name_[i], 1, getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
/* TEXTO A LA IZQUIERDA */
text_scoreboard_->writeColored(enter_name_pos_.x, enter_name_pos_.y, record_name_[i], getColorLikeKnightRider(name_colors_, loop_counter_ / 5));
break;
}
case ScoreboardMode::GAME_COMPLETED:
{
// GAME OVER
text_scoreboard_->writeCentered(slot4_1_.x, slot4_1_.y + 4, lang::getText(102));
// SCORE
if (counter_ % 10 < 8)
if (time_counter_ % 10 < 8)
{
text_scoreboard_->writeCentered(slot4_3_.x, slot4_3_.y - 2, lang::getText(120));
text_scoreboard_->writeCentered(slot4_4_.x, slot4_4_.y - 2, updateScoreText(score_[i]));
@@ -319,27 +354,27 @@ void Scoreboard::fillBackgroundTexture()
void Scoreboard::recalculateAnchors()
{
// Recalcula la posición y el tamaño de los paneles
const float panelWidth = (float)rect_.w / (float)SCOREBOARD_MAX_PANELS;
const float panel_width = (float)rect_.w / (float)SCOREBOARD_MAX_PANELS;
for (int i = 0; i < SCOREBOARD_MAX_PANELS; ++i)
{
panel_[i].pos.x = roundf(panelWidth * i);
panel_[i].pos.x = roundf(panel_width * i);
panel_[i].pos.y = 0;
panel_[i].pos.w = roundf(panelWidth * (i + 1)) - panel_[i].pos.x;
panel_[i].pos.w = roundf(panel_width * (i + 1)) - panel_[i].pos.x;
panel_[i].pos.h = rect_.h;
}
// Constantes para definir las zonas del panel_: 4 filas y 1 columna
const int rowSize = rect_.h / 4;
const int textHeight = 7;
const int row_size = rect_.h / 4;
const int text_height = 7;
// Filas
const int row1 = (rowSize * 0) + (textHeight / 2);
const int row2 = (rowSize * 1) + (textHeight / 2) - 1;
const int row3 = (rowSize * 2) + (textHeight / 2) - 2;
const int row4 = (rowSize * 3) + (textHeight / 2) - 3;
const int row1 = (row_size * 0) + (text_height / 2);
const int row2 = (row_size * 1) + (text_height / 2) - 1;
const int row3 = (row_size * 2) + (text_height / 2) - 2;
const int row4 = (row_size * 3) + (text_height / 2) - 3;
// Columna
const int col = panelWidth / 2;
const int col = panel_width / 2;
// Slots de 4
slot4_1_ = {col, row1};
@@ -348,8 +383,8 @@ void Scoreboard::recalculateAnchors()
slot4_4_ = {col, row4};
// Primer cuadrado para poner el nombre de record
const int enterNameLenght = NAME_LENGHT * 7;
enter_name_pos_.x = (panelWidth - enterNameLenght) / 2;
const int enter_name_lenght = text_scoreboard_->lenght(std::string(MAX_NAME_LENGHT, 'A'));
enter_name_pos_.x = col - (enter_name_lenght / 2);
enter_name_pos_.y = row4;
// Recoloca los sprites
@@ -402,4 +437,16 @@ void Scoreboard::renderSeparator()
// Dibuja la linea que separa el marcador de la zona de juego
SDL_SetRenderDrawColor(renderer_, separator_color.r, separator_color.g, separator_color.b, 255);
SDL_RenderDrawLine(renderer_, 0, 0, rect_.w, 0);
}
// Inicializa el vector de colores para el nombre
void Scoreboard::iniNameColors()
{
Color color = green_color;
name_colors_.clear();
name_colors_.emplace_back(color.lighten(50));
name_colors_.emplace_back(color.lighten(25));
name_colors_.emplace_back(color);
name_colors_.emplace_back(color.darken(25));
}

View File

@@ -29,6 +29,7 @@ enum class ScoreboardMode : int
GAME_OVER,
DEMO,
ENTER_NAME,
SHOW_NAME,
GAME_COMPLETED,
NUM_MODES,
};
@@ -72,7 +73,9 @@ private:
Color color_ = Color(); // Color del marcador
SDL_Rect rect_ = {0, 0, 320, 40}; // Posición y dimensiones del marcador
Uint32 ticks_ = SDL_GetTicks(); // Variable donde almacenar el valor de SDL_GetTiks()
int counter_ = 0; // Contador
int time_counter_ = 0; // Contador de segundos
int loop_counter_ = 0; // Contador de bucle
std::vector<Color> name_colors_; // Colores para destacar el nombre una vez introducido
// Puntos predefinidos para colocar elementos en los paneles
SDL_Point slot4_1_, slot4_2_, slot4_3_, slot4_4_;
@@ -81,7 +84,7 @@ private:
// Recalcula las anclas de los elementos
void recalculateAnchors();
// Transforma un valor numérico en una cadena de 6 cifras
// Transforma un valor numérico en una cadena de 7 cifras
std::string updateScoreText(int num);
// Crea la textura de fondo
@@ -97,11 +100,14 @@ private:
void fillBackgroundTexture();
// Actualiza el contador
void updateCounter();
void updateTimeCounter();
// Dibuja la linea que separa la zona de juego del marcador
void renderSeparator();
// Inicializa el vector de colores para el nombre
void iniNameColors();
// [SINGLETON] Ahora el constructor y el destructor son privados
// Constructor

View File

@@ -1,45 +1,31 @@
#include "screen.h"
#include <SDL2/SDL_events.h> // Para SDL_DISABLE, SDL_ENABLE
#include <SDL2/SDL_mouse.h> // Para SDL_ShowCursor
#include <SDL2/SDL_pixels.h> // Para SDL_PIXELFORMAT_RGBA8888
#include <SDL2/SDL_timer.h> // Para SDL_GetTicks
#include <algorithm> // Para clamp, max, min
#include <algorithm> // Para max, min
#include <fstream> // Para basic_ifstream, ifstream
#include <iterator> // Para istreambuf_iterator, operator==
#include <string> // Para allocator, operator+, char_traits, to_s...
#include <vector> // Para vector
#include <string> // Para allocator, char_traits, operator+, to_s...
#include "asset.h" // Para Asset
#include "dbgtxt.h" // Para dbg_print
#include "global_inputs.h" // Para service_pressed_counter
#include "jail_shader.h" // Para init, render
#include "mouse.h" // Para updateCursorVisibility
#include "notifier.h" // Para Notifier
#include "on_screen_help.h" // Para OnScreenHelp
#include "options.h" // Para Options, OptionsVideo, options, Options...
#include "mouse.h"
#include "resource.h" // Para Resource
#ifndef NO_SHADERS
#include "jail_shader.h" // para init, render
#endif
// [SINGLETON] Hay que definir las variables estáticas, desde el .h sólo la hemos declarado
// [SINGLETON]
Screen *Screen::screen_ = nullptr;
// [SINGLETON] Crearemos el objeto screen con esta función estática
void Screen::init(SDL_Window *window, SDL_Renderer *renderer)
{
Screen::screen_ = new Screen(window, renderer);
}
// [SINGLETON] Crearemos el objeto con esta función estática
void Screen::init(SDL_Window *window, SDL_Renderer *renderer) { Screen::screen_ = new Screen(window, renderer); }
// [SINGLETON] Destruiremos el objeto screen con esta función estática
void Screen::destroy()
{
delete Screen::screen_;
}
// [SINGLETON] Destruiremos el objeto con esta función estática
void Screen::destroy() { delete Screen::screen_; }
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
Screen *Screen::get()
{
return Screen::screen_;
}
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
Screen *Screen::get() { return Screen::screen_; }
// Constructor
Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
@@ -53,19 +39,17 @@ Screen::Screen(SDL_Window *window, SDL_Renderer *renderer)
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
info_resolution_ = std::to_string(DM.w) + " X " + std::to_string(DM.h) + " AT " + std::to_string(DM.refresh_rate) + " HZ";
// Establece el modo de video
setVideoMode(options.video.mode);
adjustRenderLogicalSize();
// Muestra la ventana
SDL_ShowWindow(window_);
show();
// Inicializa los shaders
initShaders(); // Se ha de ejecutar con la ventana visible
}
// Destructor
Screen::~Screen()
{
SDL_DestroyTexture(game_canvas_);
}
Screen::~Screen() { SDL_DestroyTexture(game_canvas_); }
// Limpia la pantalla
void Screen::clean(Color color)
@@ -75,216 +59,116 @@ void Screen::clean(Color color)
}
// Prepara para empezar a dibujar en la textura de juego
void Screen::start()
{
SDL_SetRenderTarget(renderer_, game_canvas_);
}
void Screen::start() { SDL_SetRenderTarget(renderer_, game_canvas_); }
// Vuelca el contenido del renderizador en pantalla
void Screen::render()
{
// Actualiza el contador de FPS
++fps_counter_;
fps_.increment();
// Dibuja efectos y elementos sobre el game_canvas_
renderFlash();
renderAttenuate();
OnScreenHelp::get()->render();
renderInfo();
Notifier::get()->render();
// Renderiza todos los overlays y efectos
renderOverlays();
// Restablece el objetivo de renderizado al buffer de pantalla predeterminado
SDL_SetRenderTarget(renderer_, nullptr);
// Renderiza el contenido del game_canvas_ o aplica shaders según configuración
// Renderiza el contenido del game_canvas_
renderScreen();
}
// Selecciona y ejecuta el método de renderizado adecuado basado en la configuración de shaders
// Renderiza el contenido del game_canvas_
void Screen::renderScreen()
{
#ifdef NO_SHADERS
// Actualiza la pantalla con el contenido del game_canvas_
presentGameCanvas();
#else
SDL_SetRenderTarget(renderer_, nullptr);
clean();
if (options.video.shaders)
{
// Aplica shaders y renderiza el contenido
shader::render();
}
else
{
// Actualiza la pantalla con el contenido del game_canvas_
presentGameCanvas();
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
SDL_RenderPresent(renderer_);
}
#endif
}
// Establece el modo de video
void Screen::setVideoMode(ScreenVideoMode videoMode)
void Screen::setVideoMode(ScreenVideoMode mode)
{
#ifdef ARCADE
options.video.mode = ScreenVideoMode::WINDOW;
#else
options.video.mode = videoMode;
#endif
// Actualiza las opciones
options.video.mode = mode;
switch (options.video.mode)
// Configura el modo de pantalla
Uint32 flags = SDL_GetWindowFlags(window_);
if (flags != static_cast<Uint32>(options.video.mode))
{
case ScreenVideoMode::WINDOW:
{
// Cambia a modo de ventana
SDL_SetWindowFullscreen(window_, 0);
#ifdef ARCADE
// Oculta el puntero
SDL_ShowCursor(SDL_DISABLE);
#else
// Muestra el puntero
SDL_ShowCursor(SDL_ENABLE);
#endif
// Modifica el tamaño de la ventana
SDL_Point pos = getNewPosition();
SDL_SetWindowSize(window_, param.game.width * options.video.window.size, param.game.height * options.video.window.size);
SDL_SetWindowPosition(window_, pos.x, pos.y);
break;
SDL_SetWindowFullscreen(window_, static_cast<Uint32>(options.video.mode));
}
// Si está activo el modo de pantalla completa añade el borde
case ScreenVideoMode::FULLSCREEN:
{
// Aplica el modo de video
SDL_SetWindowFullscreen(window_, SDL_WINDOW_FULLSCREEN_DESKTOP);
// Oculta el puntero
SDL_ShowCursor(SDL_DISABLE);
break;
}
default:
break;
}
// Reinicia los shaders
if (options.video.shaders)
{
#ifndef NO_SHADERS
const std::string glsl_file = param.game.game_area.rect.h == 256 ? "crtpi_256.glsl" : "crtpi_240.glsl";
std::ifstream f(Asset::get()->get(glsl_file).c_str());
std::string source((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
shader::init(window_, game_canvas_, source.c_str());
#endif
}
initShaders();
}
// Camibia entre pantalla completa y ventana
void Screen::toggleVideoMode()
{
options.video.mode = options.video.mode == ScreenVideoMode::WINDOW ? ScreenVideoMode::FULLSCREEN : ScreenVideoMode::WINDOW;
setVideoMode(options.video.mode);
setVideoMode();
}
// Cambia el tamaño de la ventana
void Screen::setWindowSize(int size)
void Screen::setWindowZoom(int zoom)
{
options.video.window.size = size;
setVideoMode(ScreenVideoMode::WINDOW);
options.video.window.zoom = zoom;
adjustWindowSize();
}
// Reduce el tamaño de la ventana
void Screen::decWindowSize()
bool Screen::decWindowZoom()
{
--options.video.window.size;
options.video.window.size = std::max(options.video.window.size, 1);
setVideoMode(ScreenVideoMode::WINDOW);
if (options.video.mode == ScreenVideoMode::WINDOW)
{
const int PREVIOUS_ZOOM = options.video.window.zoom;
--options.video.window.zoom;
options.video.window.zoom = std::max(options.video.window.zoom, 1);
if (options.video.window.zoom != PREVIOUS_ZOOM)
{
adjustWindowSize();
return true;
}
}
return false;
}
// Aumenta el tamaño de la ventana
void Screen::incWindowSize()
bool Screen::incWindowZoom()
{
++options.video.window.size;
options.video.window.size = std::min(options.video.window.size, options.video.window.max_size);
setVideoMode(ScreenVideoMode::WINDOW);
}
if (options.video.mode == ScreenVideoMode::WINDOW)
{
const int PREVIOUS_ZOOM = options.video.window.zoom;
++options.video.window.zoom;
options.video.window.zoom = std::min(options.video.window.zoom, options.video.window.max_zoom);
// Cambia el color del borde
void Screen::setBorderColor(Color color)
{
border_color_ = color;
}
if (options.video.window.zoom != PREVIOUS_ZOOM)
{
adjustWindowSize();
return true;
}
}
// Cambia el tipo de mezcla
void Screen::setBlendMode(SDL_BlendMode blendMode)
{
SDL_SetRenderDrawBlendMode(renderer_, blendMode);
return false;
}
// Actualiza la lógica de la clase
void Screen::update()
{
updateShakeEffect();
updateFlash();
fps_.calculate(SDL_GetTicks());
shake_effect_.update(src_rect_, dst_rect_);
flash_effect_.update();
Notifier::get()->update();
updateFPS();
OnScreenHelp::get()->update();
Mouse::updateCursorVisibility();
}
// Agita la pantalla
void Screen::shake()
{
// Si no hay un shake effect activo, se guarda una copia de los valores actuales antes de modificarlos
if (!shake_effect_.enabled)
{
shake_effect_.enabled = true;
shake_effect_.originalPos = src_rect_.x;
shake_effect_.originalWidth = src_rect_.w;
src_rect_.w -= shake_effect_.desp;
dst_rect_.w = src_rect_.w;
}
// Si ya hay un shake effect en marcha no se pilla el origen, solo se renuevan los contadores
shake_effect_.remaining = shake_effect_.lenght;
shake_effect_.counter = shake_effect_.delay;
}
// Actualiza la logica para agitar la pantalla
void Screen::updateShakeEffect()
{
if (shake_effect_.enabled)
{
if (shake_effect_.counter > 0)
{
shake_effect_.counter--;
}
else
{
shake_effect_.counter = shake_effect_.delay;
const auto srcdesp = shake_effect_.remaining % 2 == 0 ? 0 : shake_effect_.desp;
const auto dstdesp = shake_effect_.remaining % 2 == 1 ? 0 : shake_effect_.desp;
src_rect_.x = shake_effect_.originalPos + srcdesp;
dst_rect_.x = shake_effect_.originalPos + dstdesp;
shake_effect_.remaining--;
shake_effect_.enabled = shake_effect_.remaining == -1 ? false : true;
if (!shake_effect_.enabled)
{
src_rect_.x = shake_effect_.originalPos;
src_rect_.w = shake_effect_.originalWidth;
dst_rect_ = src_rect_;
}
}
}
}
// Pone la pantalla de color
void Screen::flash(Color color, int lenght, int delay)
{
flash_effect_ = FlashEffect(true, lenght, delay, color);
}
// Actualiza y dibuja el efecto de flash en la pantalla
void Screen::renderFlash()
{
@@ -295,10 +179,123 @@ void Screen::renderFlash()
}
}
// Actualiza el efecto de flash
void Screen::updateFlash()
// Aplica el efecto de agitar la pantalla
void Screen::renderShake()
{
flash_effect_.update();
if (shake_effect_.enabled)
{
// Guarda el renderizador actual para dejarlo despues como estaba
auto current_target = SDL_GetRenderTarget(renderer_);
// Crea una textura temporal
auto temp_texture = SDL_CreateTexture(renderer_, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_TARGET, param.game.width, param.game.height);
// Vuelca game_canvas_ a la textura temporal
SDL_SetRenderTarget(renderer_, temp_texture);
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
// Vuelca textura temporal a game_canvas_
SDL_SetRenderTarget(renderer_, game_canvas_);
SDL_RenderCopy(renderer_, temp_texture, &src_rect_, &dst_rect_);
// Elimina la textura temporal
SDL_DestroyTexture(temp_texture);
// Restaura el renderizador de destino original
SDL_SetRenderTarget(renderer_, current_target);
}
}
// Muestra información por pantalla
void Screen::renderInfo()
{
if (show_debug_info_ && Resource::get())
{
auto text = Resource::get()->getText("smb2");
// FPS
const std::string FPS_TEXT = std::to_string(fps_.lastValue) + " FPS";
text->writeColored(param.game.width - text->lenght(FPS_TEXT), 0, FPS_TEXT, orange_soft_color);
// Resolution
text->writeColored(0, 0, info_resolution_, orange_soft_color);
}
}
// Carga el contenido del archivo GLSL
void Screen::loadShaders()
{
const std::string GLSL_FILE = param.game.game_area.rect.h == 256 ? "crtpi_256.glsl" : "crtpi_240.glsl";
std::ifstream f(Asset::get()->get(GLSL_FILE).c_str());
shader_source_ = std::string((std::istreambuf_iterator<char>(f)), std::istreambuf_iterator<char>());
}
// Inicializa los shaders
void Screen::initShaders()
{
if (shader_source_.empty())
{
loadShaders();
}
shader::init(window_, game_canvas_, shader_source_);
}
// Calcula el tamaño de la ventana
void Screen::adjustWindowSize()
{
options.video.window.max_zoom = getMaxZoom();
// Establece el nuevo tamaño
if (options.video.mode == ScreenVideoMode::WINDOW)
{
const int WIDTH = param.game.width * options.video.window.zoom;
const int HEIGHT = param.game.height * options.video.window.zoom;
int old_width, old_height;
SDL_GetWindowSize(window_, &old_width, &old_height);
int old_pos_x, old_pos_y;
SDL_GetWindowPosition(window_, &old_pos_x, &old_pos_y);
const int NEW_POS_X = old_pos_x + (old_width - WIDTH) / 2;
const int NEW_POS_Y = old_pos_y + (old_height - HEIGHT) / 2;
SDL_Rect viewport = {0, 0, WIDTH, HEIGHT};
SDL_RenderSetViewport(renderer_, &viewport);
SDL_SetWindowPosition(window_, std::max(NEW_POS_X, WINDOWS_DECORATIONS_), std::max(NEW_POS_Y, 0));
SDL_SetWindowSize(window_, WIDTH, HEIGHT);
initShaders();
}
}
// Obtiene el tamaño máximo de zoom posible para la ventana
int Screen::getMaxZoom()
{
// Obtiene información sobre la pantalla
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
// Calcula el máximo factor de zoom que se puede aplicar a la pantalla
const int MAX_ZOOM = std::min(DM.w / param.game.width, (DM.h - WINDOWS_DECORATIONS_) / param.game.height);
// Normaliza los valores de zoom
options.video.window.zoom = std::min(options.video.window.zoom, MAX_ZOOM);
return MAX_ZOOM;
}
// Renderiza todos los overlays y efectos
void Screen::renderOverlays()
{
// Dibuja efectos y elementos sobre el game_canvas_
renderShake();
renderFlash();
renderAttenuate();
OnScreenHelp::get()->render();
renderInfo();
Notifier::get()->render();
}
// Atenua la pantalla
@@ -309,114 +306,4 @@ void Screen::renderAttenuate()
SDL_SetRenderDrawColor(renderer_, 0, 0, 0, 64);
SDL_RenderFillRect(renderer_, nullptr);
}
}
// Activa / desactiva los shaders
void Screen::toggleShaders()
{
options.video.shaders = !options.video.shaders;
setVideoMode(options.video.mode);
const std::string value = options.video.shaders ? "on" : "off";
Notifier::get()->showText({"Shaders " + value});
}
// Activa / desactiva la información de debug
void Screen::toggleDebugInfo()
{
show_info_ = !show_info_;
}
// Atenua la pantalla
void Screen::attenuate(bool value)
{
attenuate_effect_ = value;
}
// Obtiene el puntero al renderizador
SDL_Renderer *Screen::getRenderer()
{
return renderer_;
}
// Calcula los frames por segundo
void Screen::updateFPS()
{
if (SDL_GetTicks() - fps_ticks_ > 1000)
{
fps_ticks_ = SDL_GetTicks();
fps_ = fps_counter_;
fps_counter_ = 0;
}
}
// Muestra información por pantalla
void Screen::renderInfo()
{
if (show_info_)
{
// FPS
const std::string fpstext = std::to_string(fps_) + " FPS";
dbg_print(param.game.width - fpstext.length() * 8, 0, fpstext.c_str(), 255, 255, 0);
// Resolution
dbg_print(0, 0, info_resolution_.c_str(), 255, 255, 0);
// Contador de service_pressed_counter
if (const int counter = globalInputs::service_pressed_counter; counter > 0)
dbg_print(0, 8, std::to_string(counter).c_str(), 255, 0, 255);
const std::string atten = attenuate_effect_ ? "ATTEN YES" : "ATTEN NO";
dbg_print(0, 16, atten.c_str(), 255, 0, 0);
}
}
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point Screen::getNewPosition()
{
// Obtiene la posición actual de la ventana
SDL_Point current_position;
SDL_GetWindowPosition(window_, &current_position.x, &current_position.y);
// Obtiene las dimensiones actuales de la ventana
int current_width, current_height;
SDL_GetWindowSize(window_, &current_width, &current_height);
// Obtiene las dimesiones que tendrá la ventana
const int new_width = param.game.width * options.video.window.size;
const int new_height = param.game.height * options.video.window.size;
// Obtiene el centro de la ventana actual
SDL_Point center;
center.x = current_position.x + current_width / 2;
center.y = current_position.y + current_height / 2;
// Calcula la nueva posición a partir del centro y las nuevas diemsiones
SDL_Point new_pos;
new_pos.x = center.x - new_width / 2;
new_pos.y = center.y - new_height / 2;
// Obtiene las dimensiones del escritorio
SDL_DisplayMode DM;
SDL_GetCurrentDisplayMode(0, &DM);
// Evita que la ventana quede fuera del escritorio
new_pos.x = std::clamp(new_pos.x, 30, DM.w - new_width);
new_pos.y = std::clamp(new_pos.y, 30, DM.h - new_height);
return new_pos;
}
// Actualiza la pantalla con el contenido del game_canvas_
void Screen::presentGameCanvas()
{
// Copia la textura de juego en el renderizador en la posición adecuada
if (shake_effect_.enabled)
{
// Esta copia es para evitar que se vea negro por los laterales
SDL_RenderCopy(renderer_, game_canvas_, nullptr, nullptr);
}
SDL_RenderCopy(renderer_, game_canvas_, &src_rect_, &dst_rect_);
// Actualiza la pantalla con el contenido del buffer de renderizado
SDL_RenderPresent(renderer_);
}

View File

@@ -8,6 +8,7 @@
#include <string> // Para string
#include "param.h" // Para Param, ParamGame, param
#include "utils.h" // Para Color
#include "options.h"
enum class ScreenFilter : int
{
@@ -15,37 +16,46 @@ enum class ScreenFilter : int
LINEAL = 1,
};
enum class ScreenVideoMode : int
enum class ScreenVideoMode : Uint32
{
WINDOW = 0,
FULLSCREEN = 1,
FULLSCREEN = SDL_WINDOW_FULLSCREEN_DESKTOP,
};
class Screen
{
private:
// [SINGLETON] Objeto screen privado para Don Melitón
static Screen *screen_;
// Constantes
static constexpr int WINDOWS_DECORATIONS_ = 35;
// Objetos y punteros
SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
// Estructuras
struct FPS
{
Uint32 ticks; // Tiempo en milisegundos desde que se comenzó a contar.
int frameCount; // Número acumulado de frames en el intervalo.
int lastValue; // Número de frames calculado en el último segundo.
// Variables
SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla
SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
Color border_color_ = Color(); // Color del borde añadido a la textura de juego para rellenar la pantalla
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
Uint32 fps_ticks_ = 0; // Ticks para contar los frames por segundo
int fps_counter_ = 0; // Contador de frames por segundo
int fps_ = 0; // Frames calculados en el último segundo
std::string info_resolution_; // Texto con la informacion de la pantalla
#ifdef DEBUG
bool show_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla
#else
bool show_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla
#endif
// Constructor para inicializar la estructura.
FPS() : ticks(0), frameCount(0), lastValue(0) {}
// Incrementador que se llama en cada frame.
void increment()
{
frameCount++;
}
// Método para calcular y devolver el valor de FPS.
int calculate(Uint32 currentTicks)
{
if (currentTicks - ticks >= 1000) // Si ha pasado un segundo o más.
{
lastValue = frameCount; // Actualizamos el valor del último FPS.
frameCount = 0; // Reiniciamos el contador de frames.
ticks = currentTicks; // Actualizamos el tiempo base.
}
return lastValue;
}
};
struct FlashEffect
{
@@ -68,52 +78,137 @@ private:
struct ShakeEffect
{
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso
int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar
int originalPos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento
int originalWidth; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento
bool enabled; // Indica si el efecto está activo
int desp; // Pixels de desplazamiento para agitar la pantalla en el eje x
int delay; // Retraso entre cada desplazamiento de la pantalla al agitarse
int counter; // Contador para el retraso
int lenght; // Cantidad de desplazamientos a realizar
int remaining; // Cantidad de desplazamientos pendientes a realizar
int original_pos; // Posición inicial de la pantalla para dejarla igual tras el desplazamiento
int original_width; // Anchura inicial de la pantalla para dejarla igual tras el desplazamiento
bool enabled; // Indica si el efecto está activo
// Constructor
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = param.game.width)
: desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), originalPos(origPos), originalWidth(origWidth), enabled(en) {}
explicit ShakeEffect(bool en = false, int dp = 2, int dl = 3, int cnt = 0, int len = 8, int rem = 0, int origPos = 0, int origWidth = 800)
: desp(dp), delay(dl), counter(cnt), lenght(len), remaining(rem), original_pos(origPos), original_width(origWidth), enabled(en) {}
// Método para habilitar el efecto
void enable(SDL_Rect &src_rect, SDL_Rect &dst_rect)
{
if (!enabled)
{
// Configurar el estado inicial si el efecto no está activo
enabled = true;
original_pos = src_rect.x;
original_width = src_rect.w;
// Acortar los anchos iniciales durante el efecto
src_rect.w -= desp;
dst_rect.w = src_rect.w;
}
// Renovar contadores y duración del efecto
remaining = lenght;
counter = delay;
}
// Método para actualizar el efecto de movimiento/agitación
void update(SDL_Rect &src_rect, SDL_Rect &dst_rect)
{
if (enabled)
{
if (counter > 0)
{
counter--;
}
else
{
counter = delay;
// Calcular desplazamientos según el estado de la agitación
const auto SRC_DESP = (remaining % 2 == 0) ? 0 : desp;
const auto DST_DESP = (remaining % 2 == 1) ? 0 : desp;
src_rect.x = original_pos + SRC_DESP;
dst_rect.x = original_pos + DST_DESP;
remaining--;
if (remaining == -1)
{
// Restaurar posición y dimensiones originales
enabled = false;
src_rect.x = original_pos;
src_rect.w = original_width;
dst_rect.x = original_pos;
dst_rect.w = original_width;
}
}
}
}
// Método para comprobar si el efecto está activo
bool isEnabled() const
{
return enabled;
}
};
// Variables - Efectos
FlashEffect flash_effect_; // Variable para gestionar el efecto de flash
ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla
// [SINGLETON] Objeto privado
static Screen *screen_;
// Actualiza la logica para agitar la pantalla
void updateShakeEffect();
// Objetos y punteros
SDL_Window *window_; // Ventana de la aplicación
SDL_Renderer *renderer_; // El renderizador de la ventana
SDL_Texture *game_canvas_; // Textura donde se dibuja todo antes de volcarse al renderizador
// Variables
SDL_Rect src_rect_; // Coordenadas de donde va a pillar la textura del juego para dibujarla
SDL_Rect dst_rect_; // Coordenadas donde se va a dibujar la textura del juego sobre la pantalla o ventana
FPS fps_; // Variable para gestionar los frames por segundo
std::string info_resolution_; // Texto con la informacion de la pantalla
std::string shader_source_; // Almacena el contenido del archivo GLSL
FlashEffect flash_effect_; // Variable para gestionar el efecto de flash
ShakeEffect shake_effect_; // Variable para gestionar el efecto de agitar la pantalla
bool attenuate_effect_ = false; // Indica si la pantalla ha de estar atenuada
#ifdef DEBUG
bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla
#else
bool show_debug_info_ = false; // Indica si ha de mostrar/ocultar la información de la pantalla
#endif
// Dibuja el efecto de flash en la pantalla
void renderFlash();
// Actualiza el efecto de flash
void updateFlash();
// Atenua la pantalla
void renderAttenuate();
// Calcula los frames por segundo
void updateFPS();
// Aplica el efecto de agitar la pantalla
void renderShake();
// Muestra información por pantalla
void renderInfo();
// Calcula la nueva posición de la ventana a partir de la antigua al cambiarla de tamaño
SDL_Point getNewPosition();
// Actualiza la pantalla con el contenido del game_canvas_
void presentGameCanvas();
// Selecciona y ejecuta el método de renderizado adecuado basado en la configuración de shaders
void renderScreen();
// [SINGLETON] Ahora el constructor y el destructor son privados, para no poder crear objetos screen desde fuera
// Carga el contenido del archivo GLSL
void loadShaders();
// Inicializa los shaders
void initShaders();
// Calcula el tamaño de la ventana
void adjustWindowSize();
// Ajusta el tamaño lógico del renderizador
void adjustRenderLogicalSize() { SDL_RenderSetLogicalSize(renderer_, param.game.width, param.game.height); }
// Obtiene el tamaño máximo de zoom posible para la ventana
int getMaxZoom();
// Renderiza todos los overlays y efectos
void renderOverlays();
// Atenua la pantalla
void renderAttenuate();
// Constructor
Screen(SDL_Window *window, SDL_Renderer *renderer);
@@ -122,13 +217,13 @@ private:
~Screen();
public:
// [SINGLETON] Crearemos el objeto screen con esta función estática
// [SINGLETON] Crearemos el objeto con esta función estática
static void init(SDL_Window *window, SDL_Renderer *renderer);
// [SINGLETON] Destruiremos el objeto screen con esta función estática
// [SINGLETON] Destruiremos el objeto con esta función estática
static void destroy();
// [SINGLETON] Con este método obtenemos el objeto screen y podemos trabajar con él
// [SINGLETON] Con este método obtenemos el objeto y podemos trabajar con él
static Screen *get();
// Actualiza la lógica de la clase
@@ -144,41 +239,41 @@ public:
void render();
// Establece el modo de video
void setVideoMode(ScreenVideoMode video_mode);
void setVideoMode(ScreenVideoMode mode = options.video.mode);
// Cambia entre pantalla completa y ventana
void toggleVideoMode();
// Cambia el tamaño de la ventana
void setWindowSize(int size);
void setWindowZoom(int size);
// Reduce el tamaño de la ventana
void decWindowSize();
bool decWindowZoom();
// Aumenta el tamaño de la ventana
void incWindowSize();
// Cambia el color del borde
void setBorderColor(Color color);
// Cambia el tipo de mezcla
void setBlendMode(SDL_BlendMode blend_mode);
bool incWindowZoom();
// Agita la pantalla
void shake();
void shake() { shake_effect_.enable(src_rect_, dst_rect_); }
// Pone la pantalla de color
void flash(Color color, int lenght, int delay = 0);
void flash(Color color, int lenght = 10, int delay = 0) { flash_effect_ = FlashEffect(true, lenght, delay, color); }
// Activa / desactiva los shaders
void toggleShaders();
void toggleShaders() { options.video.shaders = !options.video.shaders; }
// Activa / desactiva la información de debug
void toggleDebugInfo();
void toggleDebugInfo() { show_debug_info_ = !show_debug_info_; }
// Getters
SDL_Renderer *getRenderer() { return renderer_; }
// Muestra la ventana
void show() { SDL_ShowWindow(window_); }
// Oculta la ventana
void hide() { SDL_HideWindow(window_); }
// Atenua la pantalla
void attenuate(bool value);
// Obtiene el puntero al renderizador
SDL_Renderer *getRenderer();
void attenuate(bool value) { attenuate_effect_ = value; }
};

Some files were not shown because too many files have changed in this diff Show More