From 67f387b5a47118fed433c2a164353b67df1b2380 Mon Sep 17 00:00:00 2001 From: XargonWan Date: Mon, 14 Mar 2022 12:01:23 +0100 Subject: [PATCH] First upload --- es_input.cfg | 30 + es_settings.cfg | 78 + es_systems.cfg | 2168 +++++++++++ export_func.sh | 195 + install-retrodeck.sh | 248 ++ res/icon128.png | Bin 0 -> 3065 bytes res/logo.png | Bin 0 -> 97041 bytes .../distribution/configs/distribution.conf | 232 ++ storage/.config/retroarch/retroarch.cfg | 3195 +++++++++++++++++ usr/bin/351elec-es-packages | 236 ++ usr/bin/batocera-config | 373 ++ usr/bin/batocera-scraper | 84 + usr/bin/batocera-settings | 272 ++ usr/bin/runemu.py | 405 +++ usr/bin/setsettings.py | 700 ++++ 15 files changed, 8216 insertions(+) create mode 100644 es_input.cfg create mode 100644 es_settings.cfg create mode 100644 es_systems.cfg create mode 100755 export_func.sh create mode 100755 install-retrodeck.sh create mode 100644 res/icon128.png create mode 100644 res/logo.png create mode 100644 storage/.config/distribution/configs/distribution.conf create mode 100644 storage/.config/retroarch/retroarch.cfg create mode 100755 usr/bin/351elec-es-packages create mode 100755 usr/bin/batocera-config create mode 100755 usr/bin/batocera-scraper create mode 100755 usr/bin/batocera-settings create mode 100755 usr/bin/runemu.py create mode 100755 usr/bin/setsettings.py diff --git a/es_input.cfg b/es_input.cfg new file mode 100644 index 00000000..28efc546 --- /dev/null +++ b/es_input.cfg @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/es_settings.cfg b/es_settings.cfg new file mode 100644 index 00000000..0e05a386 --- /dev/null +++ b/es_settings.cfg @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/es_systems.cfg b/es_systems.cfg new file mode 100644 index 00000000..4393dab7 --- /dev/null +++ b/es_systems.cfg @@ -0,0 +1,2168 @@ + + + + 3do + 3DO + Panasonic + 1993 + console + ~/retrodeck/storage/roms/3do + .iso .ISO .bin .BIN .chd .CHD .cue .CUE + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + 3do + 3do + + + + opera + + + + + + amiga + Amiga + Commodore + 1985 + computer + ~/retrodeck/storage/roms/amiga + .zip .ZIP .adf .ADF .uae .UAE .ipf .IPF .dms .DMS .adz .ADZ .lha .LHA .m3u .M3U .hdf .HDF .hdz .HDZ + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + amiga + amiga + + + + puae + uae4arm + + + + + AMIBERRY + + + + + + amigacd32 + Amiga CD32 + Commodore + 1994 + console + ~/retrodeck/storage/roms/amigacd32 + .iso .ISO .cue .CUE .lha .LHA .chd .CHD + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + amigacd32 + amigacd32 + + + + puae + uae4arm + + + + + + amstradcpc + Amstrad CPC + Amstrad + 1984 + computer + ~/retrodeck/storage/roms/amstradcpc + .dsk .DSK .sna .SNA .tap .TAP .cdt .CDT .kcr .KCR .voc .VOC .m3u .M3U .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + amstradcpc + amstradcpc + + + + crocods + cap32 + + + + + + arcade + Arcade + Arcade + arcade + ~/retrodeck/storage/roms/arcade + .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + arcade + arcade + + + + mame2003_plus + mame2000 + mame2010 + mame2015 + mame + fbneo + fbalpha2012 + fbalpha2019 + + + + + AdvanceMame + + + + + + atari2600 + Atari 2600 + Atari + 1977 + console + ~/retrodeck/storage/roms/atari2600 + .a26 .A26 .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atari2600 + atari2600 + + + + stella + stella2014 + + + + + + atari5200 + Atari 5200 + Atari + 1982 + console + ~/retrodeck/storage/roms/atari5200 + .rom .ROM .xfd .XFD .atr .ATR .atx .ATX .cdm .CDM .cas .CAS .car .CAR .bin .BIN .a52 .A52 .xex .XEX .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atari5200 + atari5200 + + + + atari800 + + + + + + atari7800 + Atari 7800 + Atari + 1986 + console + ~/retrodeck/storage/roms/atari7800 + .a78 .A78 .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atari7800 + atari7800 + + + + prosystem + + + + + + atari800 + Atari 800 + Atari + 1979 + console + ~/retrodeck/storage/roms/atari800 + .rom .ROM .xfd .XFD .atr .ATR .atx .ATX .cdm .CDM .cas .CAS .car .CAR .bin .BIN .a52 .A52 .xex .XEX .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atari800 + atari800 + + + + atari800 + + + + + + atarist + Atari ST + Atari + 1985 + computer + ~/retrodeck/storage/roms/atarist + .st .ST .msa .MSA .stx .STX .dim .DIM .ipf .IPF .m3u .M3U .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atarist + atarist + + + + hatari + + + + + HATARISA + + + + + + atomiswave + Atomiswave + Sammy + 2003 + arcade + ~/retrodeck/storage/roms/atomiswave + .lst .LST .bin .BIN .dat .DAT .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atomiswave arcade + atomiswave + + + + flycast + + + + + flycast + + + + + + channelf + Channel F + Fairchild + 1976 + console + ~/retrodeck/storage/roms/channelf + .bin .BIN .chf .CHF .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + channelf + channelf + + + + freechaf + + + + + + colecovision + ColecoVision + Coleco + 1982 + console + ~/retrodeck/storage/roms/coleco + .bin .BIN .col .COL .rom .ROM .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + colecovision + colecovision + + + + bluemsx + gearcoleco + smsplus + + + + + + c128 + Commodore 128 + Commodore + 1985 + computer + ~/retrodeck/storage/roms/c128 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB . + .NBZ .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + c128 + c128 + + + + vice_x128 + + + + + + c16 + Commodore 16 + Commodore + 1984 + computer + ~/retrodeck/storage/roms/c16 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + c16 + c16 + + + + vice_xplus4 + + + + + + c64 + Commodore 64 + Commodore + 1982 + computer + ~/retrodeck/storage/roms/c64 + .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + c64 + c64 + + + + vice_x64 + + + + + + vic20 + Commodore VIC-20 + Commodore + 1980 + computer + ~/retrodeck/storage/roms/vic20 + .20 .40 .60 .a0 .A0 .b0 .B0 .d64 .D64 .d71 .D71 .d80 .D80 .d81 .D81 .d82 .D82 .g64 .G64 .g41 .G41 .x64 .X64 .t64 .T64 .tap .TAP .prg .PRG .p00 .P00 .crt .CRT .bin .BIN .gz .GZ .d6z .D6Z .d7z .D7Z .d8z .D8Z .g6z .G6Z .g4z .G4Z .x6z .X6Z .cmd .CMD .m3u .M3U .vsf .VSF .nib .NIB .nbz .NBZ .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + vic20 + vic20 + + + + vice_xvic + + + + + + laserdisc + LaserDisc + Arcade + arcade + ~/retrodeck/storage/roms/laserdisc + .daphne .DAPHNE .ld .LD + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + arcade daphne americanlasergames actionmax + laserdisc + + + + hyseus_singe + + + + + + dreamcast + Dreamcast + Sega + 1998 + console + ~/retrodeck/storage/roms/dreamcast + .cdi .CDI .gdi .GDI .chd .CHD .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + dreamcast + dreamcast + + + + flycast + + + + + flycast + + + + + + easyrpg + EasyRPG + Various + 2003 + game engine + ~/retrodeck/storage/roms/easyrpg + .zip .ZIP .easyrpg .EASYRPG .ldb .LDB + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + easyrpg + easyrpg + + + + easyrpg + + + + + + famicom + Famicom + Nintendo + 1983 + console + ~/retrodeck/storage/roms/famicom + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + nes + famicom + + + + fceumm + nestopia + quicknes + + + + + + fds + Famicom Disk System + Nintendo + 1986 + console + ~/retrodeck/storage/roms/fds + .fds .FDS .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + fds + fds + + + + fceumm + nestopia + quicknes + + + + + + fbn + Final Burn Neo + Arcade + arcade + ~/retrodeck/storage/roms/fbneo + .7z .zip .7Z .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + arcade + fbn + + + + fbneo + mame2003 + mame2010 + mame2015 + mame + fbalpha2012 + fbalpha2019 + + + + + + gameandwatch + Game and Watch + Nintendo + 1980 + portable + ~/retrodeck/storage/roms/gameandwatch + .mgw .MGW .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gameandwatch + gameandwatch + + + + gw + + + + + + gb + Game Boy + Nintendo + 1989 + portable + ~/retrodeck/storage/roms/gb + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gb + gb + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + mgba + vbam + + + + + + gbh + Game Boy (Hacks) + Nintendo + 1989 + portable + ~/retrodeck/storage/roms/gbh + .gb .GB .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gb + gbh + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + mgba + vbam + + + + + + gba + Game Boy Advance + Nintendo + 2001 + portable + ~/retrodeck/storage/roms/gba + .gba .GBA .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gba + gba + + + + mgba + gpsp + vbam + vba_next + beetle_gba + + + + + mgba + vbam + + + + + + gbah + Game Boy Advance (Hacks) + Nintendo + 2001 + portable + ~/retrodeck/storage/roms/gbah + .gba .GBA .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gba + gbah + + + + mgba + gpsp + vbam + vba_next + beetle_gba + + + + + mgba + vbam + + + + + + gbc + Game Boy Color + Nintendo + 1998 + portable + ~/retrodeck/storage/roms/gbc + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gbc + gbc + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + mgba + vbam + + + + + + gbch + Game Boy Color (Hacks) + Nintendo + 1998 + portable + ~/retrodeck/storage/roms/gbch + .gb .GB .gbc .GBC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gbc + gbch + + + + gambatte + sameboy + gearboy + tgbdual + mgba + vbam + + + + + mgba + vbam + + + + + + gamegear + Game Gear + Sega + 1990 + portable + ~/retrodeck/storage/roms/gamegear + .bin .BIN .gg .GG .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gamegear + gamegear + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + ggh + Game Gear (Hacks) + Sega + 1990 + portable + ~/retrodeck/storage/roms/gamegearh + .bin .BIN .gg .GG .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + gamegear + ggh + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + intellivision + Intellivision + Mattel + 1979 + console + ~/retrodeck/storage/roms/intellivision + .int .INT .bin .BIN .rom .ROM .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + intellivision + intellivision + + + + freeintv + + + + + + j2me + J2ME + Sun Microsystems + 2002 + portable + ~/retrodeck/storage/roms/j2me + .jar .JAR + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + j2me + j2me + + + + freej2me + + + + + + atarilynx + Lynx + Atari + 1989 + portable + ~/retrodeck/storage/roms/atarilynx + .lnx .LNX .o .O .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + atarilynx + atarilynx + + + + handy + beetle_lynx + + + + + + mame + MAME + Arcade + arcade + ~/retrodeck/storage/roms/mame + .7z .7Z .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + arcade + mame + + + + mame2003_plus + mame2000 + mame2010 + mame2015 + mame + fbneo + fbalpha2012 + fbalpha2019 + + + + + AdvanceMame + + + + + + pc + MS-DOS + Microsoft + 1981 + computer + ~/retrodeck/storage/roms/dos + .com .COM .bat .BAT .exe .EXE .dosz .DOSZ + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc + pc + + + + dosbox_pure + dosbox_svn + + + + + + snesmsu1 + MSU-1 + Nintendo + 2012 + console + ~/retrodeck/storage/roms/snesmsu1 + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + snesmsu1 snes + snesmsu1 + + + + snes9x + beetle_supafaust + + + + + + msx + MSX + Microsoft + 1983 + computer + ~/retrodeck/storage/roms/msx + .dsk .DSK .mx1 .MX1 .mx2 .MX2 .rom .ROM .zip .ZIP .7z .7Z .M3U .m3u + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + msx + msx + + + + bluemsx + fmsx + + + + + + msx2 + MSX2 + Microsoft + 1985 + computer + ~/retrodeck/storage/roms/msx2 + .dsk .DSK .mx1 .MX1 .mx2 .MX2 .rom .ROM .zip .ZIP .7z .7Z .M3U .m3u + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + msx + msx2 + + + + bluemsx + fmsx + + + + + + naomi + Naomi + Sega + 1998 + arcade + ~/retrodeck/storage/roms/naomi + .lst .LST .bin .BIN .dat .DAT .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + naomi arcade + naomi + + + + flycast + + + + + flycast + + + + + + neogeo + Neo Geo + SNK + 1990 + console + ~/retrodeck/storage/roms/neogeo + .7z .7Z .zip .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + neogeo + neogeo + + + + fbneo + mame2003_plus + fbalpha2012 + fbalpha2019 + mame2010 + mame2015 + mame + + + + + + neocd + Neo Geo CD + SNK + 1990 + console + ~/retrodeck/storage/roms/neocd + .cue .CUE .iso .ISO .chd .CHD + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + neogeocd + neogeocd + + + + neocd + fbneo + + + + + + ngp + Neo Geo Pocket + SNK + 1998 + portable + ~/retrodeck/storage/roms/ngp + .ngc .NGC .ngp .NGP .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + ngp + ngp + + + + beetle_ngp + race + + + + + + ngpc + Neo Geo Pocket Color + SNK + 1999 + portable + ~/retrodeck/storage/roms/ngpc + .ngc .NGC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + ngpc + ngpc + + + + beetle_ngp + race + + + + + + n64 + Nintendo 64 + Nintendo + 1996 + console + ~/retrodeck/storage/roms/n64 + .z64 .Z64 .n64 .N64 .v64 .V64 .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + n64 + n64 + + + + parallel_n64 + parallel_n64_gln64 + mupen64plus + mupen64plus_next + + + + + parallel_n64 + parallel_n64_gln64 + + + + + m64p_gl64mk2 + m64p_rice + + + + + + nds + Nintendo DS + Nintendo + 2005 + portable + ~/retrodeck/storage/roms/nds + .nds .zip .NDS .ZIP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + nds + nds + + + + drastic + + + + + + nes + Nintendo Entertainment System + Nintendo + 1985 + console + ~/retrodeck/storage/roms/nes + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + nes + nes + + + + fceumm + nestopia + quicknes + + + + + + nesh + Nintendo Entertainment System (Hacks) + Nintendo + 1985 + console + ~/retrodeck/storage/roms/nesh + .nes .NES .unif .UNIF .unf .UNF .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + nes + nesh + + + + fceumm + nestopia + quicknes + + + + + + odyssey2 + Odyssey² + Magnavox + 1979 + console + ~/retrodeck/storage/roms/odyssey + .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + odyssey2 + odyssey2 + + + + o2em + + + + + + openbor + OpenBOR + Various + 2008 + game engine + ~/retrodeck/storage/roms/openbor + .pak .PAK + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + openbor + openbor + + + + OPENBOR + + + + + + pc-8800 + PC-8800 + NEC + 1981 + computer + ~/retrodeck/storage/roms/pc88 + .d88 .D88 .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc88 + pc88 + + + + quasi88 + + + + + + pc-9800 + PC-9800 + NEC + 1983 + computer + ~/retrodeck/storage/roms/pc98 + .d98 .zip .98d .fdi .fdd .2hd .tfd .d88 .88d .hdm .xdf .dup .hdi .thd .nhd .hdd .hdn + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc98 + pc98 + + + + np2kai + nekop2 + + + + + + pcengine + PC Engine + NEC + 1987 + console + ~/retrodeck/storage/roms/pcengine + .pce .PCE .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pcengine + pcengine + + + + beetle_pce_fast + beetle_supergrafx + + + + + + pcenginecd + PC Engine CD + NEC + 1988 + console + ~/retrodeck/storage/roms/pcenginecd + .cue .CUE .ccd .CCD .chd .CHD .toc .TOC .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pcenginecd + pce-cd + + + + beetle_pce_fast + beetle_supergrafx + + + + + + pcfx + PC-FX + NEC + 1994 + console + ~/retrodeck/storage/roms/pcfx + .chd .CHD .cue .CUE .ccd .CCD .toc .TOC + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pcfx + pcfx + + + + beetle_pcfx + + + + + + pico-8 + PICO-8 + Lexaloffle + 2015 + console + ~/retrodeck/storage/roms/pico-8 + .sh .p8 .png .SH .P8 .PNG + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers %CONTROLLERSCONFIG% + pico-8 + pico-8 + + + + pico8_dyn + + + + + + piece + P/ece + Aquaplus + 2001 + console + ~/retrodeck/storage/roms/piece + .pex .pfi + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + piece + piece + + + + piemu + + + + + + psx + PlayStation + Sony + 1994 + console + ~/retrodeck/storage/roms/psx + .bin .BIN .cue .CUE .img .IMG .mdf .MDF .pbp .PBP .toc .TOC .cbn .CBN .m3u .M3U .ccd .CCD .chd .CHD .iso .ISO + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + psx + psx + + + + pcsx_rearmed + duckstation + swanstation + + + + + pcsx_rearmed + swanstation + + + + + + psp + PlayStation Portable + Sony + 2004 + portable + ~/retrodeck/storage/roms/psp + .iso .ISO .cso .CSO .pbp .PBP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + psp + psp + + + + PPSSPPSDL + + + + + ppsspp + + + + + + pspminis + PSP Minis + Sony + 2004 + portable + ~/retrodeck/storage/roms/pspminis + .iso .ISO .cso .CSO .pbp .PBP + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + psp + pspminis + + + + PPSSPPSDL + + + + + ppsspp + + + + + + pokemini + Pokémon Mini + Nintendo + 2001 + portable + ~/retrodeck/storage/roms/pokemini + .min .MIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pokemini + pokemini + + + + pokemini + + + + + + homebrew + Homebrew + Various + unknown + various + ~/retrodeck/storage/roms/homebrew + .sh .SH + ~/retrodeck/usr/bin/bash %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + homebrew + + + ports + Ports + Various + unknown + various + ~/retrodeck/storage/roms/ports + .sh .SH + ~/retrodeck/usr/bin/bash %ROM% -P%SYSTEM% --core=%CORE% --emulator=%EMULATOR% --controllers="%CONTROLLERSCONFIG%" + pc + ports + + + sc-3000 + SC-3000 + Sega + 1983 + computer + ~/retrodeck/storage/roms/sc-3000 + .bin .BIN .sg .SG .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + sc-3000 + sc-3000 + + + + bluemsx + + + + + + scummvm + ScummVM + Various + 2001 + game engine + ~/retrodeck/storage/.config/scummvm/games + .sh .SH .svm .SVM .scummvm + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc + scummvm + + + + scummvm + + + + + SCUMMVMSA + + + + + + sega32x + Sega 32X + Sega + 1994 + console + ~/retrodeck/storage/roms/sega32x + .32x .32X .smd .SMD .bin .BIN .md .MD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + sega32x + sega32x + + + + picodrive + + + + + + segacd + Sega CD + Sega + 1991 + console + ~/retrodeck/storage/roms/segacd + .chd .CHD .cue .CUE .iso .ISO .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + segacd + segacd + + + + genesis_plus_gx + picodrive + + + + + + megacd + Sega Mega-CD + Sega + 1991 + console + ~/retrodeck/storage/roms/megacd + .chd .CHD .cue .CUE .iso .ISO .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + segacd + megacd + + + + genesis_plus_gx + picodrive + + + + + + genesis + Sega Genesis + Sega + 1989 + console + ~/retrodeck/storage/roms/genesis + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + genesis + genesis + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + genh + Sega Genesis (Hacks) + Sega + 1989 + console + ~/retrodeck/storage/roms/genh + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + genesis + genh + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + mastersystem + Sega Master System + Sega + 1985 + console + ~/retrodeck/storage/roms/mastersystem + .bin .BIN .sms .SMS .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + mastersystem + mastersystem + + + + gearsystem + genesis_plus_gx + picodrive + smsplus + + + + + + megadrive + Sega Mega Drive + Sega + 1990 + console + ~/retrodeck/storage/roms/megadrive + .bin .BIN .gen .GEN .md .MD .sg .SG .smd .SMD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + megadrive + megadrive + + + + genesis_plus_gx + genesis_plus_gx_wide + picodrive + + + + + + megaduck + Mega Duck + Welback Holdings + 1993 + portable + ~/retrodeck/storage/roms/megaduck + .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + megaduck + megaduck + + + + sameduck + + + + + + saturn + Sega Saturn + Sega + 1994 + console + ~/retrodeck/storage/roms/saturn + .cue .CUE .chd .CHD .iso .ISO + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + saturn + saturn + + + + yabasanshiro + + + + + yabasanshiro + + + + + + sg-1000 + SG-1000 + Sega + 1983 + console + ~/retrodeck/storage/roms/sg-1000 + .bin .BIN .sg .SG .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + sg-1000 + sg-1000 + + + + gearsystem + genesis_plus_gx + picodrive + + + + + + x1 + Sharp X1 + Sharp + 1982 + computer + ~/retrodeck/storage/roms/x1 + .dx1 .DX1 .2d .2D .2hd .2HD .tfd .TFD .d88 .D88 .88d .88D .hdm .HDM .xdf .XDF .dup .DUP .tap .TAP .cmd .CMD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + x1 + x1 + + + + x1 + + + + + + zxspectrum + Sinclair ZX Spectrum + Sinclair + 1982 + computer + ~/retrodeck/storage/roms/zxspectrum + .tzx .TZX .tap .TAP .z80 .Z80 .rzx .RZX .scl .SCL .trd .TRD .dsk .DSK .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + zxspectrum + zxspectrum + + + + fuse + + + + + + zx81 + Sinclair ZX81 + Sinclair + 1981 + computer + ~/retrodeck/storage/roms/zx81 + .tzx .TZX .p .P .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + zx81 + zx81 + + + + 81 + + + + + + supergrafx + Super Grafx + NEC + 1989 + console + ~/retrodeck/storage/roms/sgfx + .pce .PCE .sgx .SGX .cue .CUE .ccd .CCD .chd .CHD .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + supergrafx + supergrafx + + + + beetle_supergrafx + + + + + + snes + Super Nintendo + Nintendo + 1991 + console + ~/retrodeck/storage/roms/snes + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + snes + snes + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + snesh + Super Nintendo (Hacks) + Nintendo + 1991 + console + ~/retrodeck/storage/roms/snesh + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + snes + snesh + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + sfc + Super Famicom + Nintendo + 1990 + console + ~/retrodeck/storage/roms/sfc + .smc .SMC .fig .FIG .sfc .SFC .swc .SWC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + snes + sfc + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + beetle_supafaust + + + + + + satellaview + Satellaview + Nintendo + 1995 + console + ~/retrodeck/storage/roms/satellaview + .smc .SMC .fig .FIG .bs .BS .sfc .SFC .bsx .BSX .swc .SWC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + satellaview + satellaview + + + + snes9x + snes9x2010 + snes9x2002 + snes9x2005_plus + + + + + + sufami + SuFami Turbo + Bandai + 1996 + console + ~/retrodeck/storage/roms/sufami + .st .ST .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + sufami + sufami + + + + snes9x + + + + + + solarus + Solarus + Solarus + 2020 + game engine + ~/retrodeck/storage/roms/solarus + .solarus + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + solarus + solarus + + + + solarus + + + + + + supervision + Watara Supervision + Watara + 1992 + portable + ~/retrodeck/storage/roms/supervision + .sv .SV .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + supervision + supervision + + + + potator + + + + + + tic-80 + TIC-80 + Nesbox + 2017 + computer + ~/retrodeck/storage/roms/tic-80 + .tic .TIC + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + tic80 + tic-80 + + + + tic80 + + + + + + tg16 + TurboGrafx-16 + NEC + 1989 + console + ~/retrodeck/storage/roms/tg16 + .pce .PCE .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pcengine + tg16 + + + + beetle_pce_fast + beetle_supergrafx + + + + + + tg16cd + TurboGrafx-CD + NEC + 1989 + console + ~/retrodeck/storage/roms/tg16cd + .cue .CUE .ccd .CCD .chd .CHD .toc .TOC .m3u .M3U + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pcenginecd + tg16cd + + + + beetle_pce_fast + beetle_supergrafx + + + + + + uzebox + Uzebox + belogic + 2008 + console + ~/retrodeck/storage/roms/uzebox + .uze .UZE + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + uzebox + uzebox + + + + uzem + + + + + + vectrex + Vectrex + Milton Bradley + 1982 + console + ~/retrodeck/storage/roms/vectrex + .bin .BIN .gam .GAM .vec .VEC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + vectrex + vectrex + + + + vecx + + + + + + videopac + VideoPac + Philips + 1978 + console + ~/retrodeck/storage/roms/videopac + .bin .BIN .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + videopac + videopac + + + + o2em + + + + + + virtualboy + Virtual Boy + Nintendo + 1995 + console + ~/retrodeck/storage/roms/virtualboy + .vb .VB .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + virtualboy + virtualboy + + + + beetle_vb + + + + + + wonderswan + Wonderswan + Bandai + 1999 + portable + ~/retrodeck/storage/roms/wonderswan + .ws .WS .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + wonderswan + wonderswan + + + + beetle_wswan + + + + + + wonderswancolor + Wonderswan Color + Bandai + 2000 + portable + ~/retrodeck/storage/roms/wonderswancolor + .wsc .WSC .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + wonderswancolor + wonderswancolor + + + + beetle_wswan + + + + + + x68000 + x68000 + Sharp + 1987 + computer + ~/retrodeck/storage/roms/x68000 + .dim .DIM .img .IMG .d88 .D88 .88d .88D .hdm .HDM .dup .DUP .2hd .2HD .xdf .XDF .hdf .HDF .cmd .CMD .m3u .M3U .zip .ZIP .7z .7Z + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + x68000 + x68000 + + + + px68k + + + + + + ecwolf + Wolfenstein 3D + id Software + 1992 + game engine + ~/retrodeck/storage/roms/ecwolf + .ecwolf + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc + ecwolf + + + + ecwolf + + + + + + doom + Doom + id Software + 1993 + game engine + ~/retrodeck/storage/roms/doom + .doom + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc + doom + + + + gzdoom + + + + + lzdoom + + + + + prboom + + + + + + build + Build Engine + 3D Realms + 1995 + game engine + ~/retrodeck/storage/roms/build + .build + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + pc + build + + + + raze + + + + + + mplayer + MPlayer + Various + unknown + system + ~/retrodeck/storage/roms/mplayer + .mp4 .MP4 .mkv .MKV .avi .AVI .mov .MOV .wmv .WMV .m3u .M3U .mpg .MPG .ytb .YTB .twi .TWI .sh .SH + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform %SYSTEM% --emulator %EMULATOR% --core %CORE% --controllers "%CONTROLLERSCONFIG%" + mplayer + mplayer + + + + mpv + + + + + + tools +  Tools + Various + unknown + system + ~/retrodeck/storage/.config/distribution/modules + .sh + ~/retrodeck/usr/bin/runemu.py --rom %ROM% --platform tools --controllers "%CONTROLLERSCONFIG%" + tools + tools + + + Screenshots + imageviewer + Various + unknown + system + /roms/screenshots + .jpg .jpeg .png .bmp .psd .tga .gif .hdr .pic .ppm .pgm .mkv .pdf .mp4 .avi + ~/retrodeck/usr/bin/true + imageviewer + imageviewer + + diff --git a/export_func.sh b/export_func.sh new file mode 100755 index 00000000..691e462e --- /dev/null +++ b/export_func.sh @@ -0,0 +1,195 @@ +#!/bin/bash + +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + +# This content was taken from 99-distribution.conf and made as a shell script for steam deck +# TODO: remove absolute paths and put the variables INSTALL_DIR + +export PATH="$PATH:/usr/local/bin:/usr/bin:/storage/bin" + +export SDL_GAMECONTROLLERCONFIG_FILE="~/retrodeck/storage/.config/SDL-GameControllerDB/gamecontrollerdb.txt" + +EE_DIR="~/retrodeck/storage/.config/distribution" +EE_CONF="${EE_DIR}/configs/distribution.conf" +ES_CONF="~/retrodeck/storage/.emulationstation/es_settings.cfg" +EE_DEVICE=$(cat ~/retrodeck/storage/.config/.OS_ARCH) +JSLISTENCONF="~/retrodeck/storage/.config/distribution/configs/jslisten.cfg" + +get_ee_setting() { +# Argument $1 is the setting name, EmuELEC settings alway start with ee_ e.g. ee_novideo +# Usage: get_ee_setting setting [platform] [rom] +# Only the setting argument is required +# Priority is: GAME, PLATFORM, GLOBAL, EE_SETTING if at any point one returns 0 it means its dissabled, if it returns empty it will continue onto the next one. + +SETTING="${1}" +PLATFORM="${2}" +ROM="${3}" + +#ROM +ROM=$(echo [\"${ROM}\"] | sed -e 's|\[|\\\[|g' | sed -e 's|\]|\\\]|g' | sed -e 's|(|\\\(|g' | sed -e 's|)|\\\)|g') +PAT="^${PLATFORM}${ROM}[.-]${SETTING}=(.*)" + EES=$(cat "${EE_CONF}" | grep -oE "${PAT}") + EES="${EES##*=}" + +if [ -z "${EES}" ]; then +#PLATFORM +PAT="^${PLATFORM}[.-]${SETTING}=(.*)" + EES=$(cat "${EE_CONF}" | grep -oE "${PAT}") + EES="${EES##*=}" +fi + +if [ -z "${EES}" ]; then +#GLOBAL +PAT="^global[.-]${SETTING}=(.*)" + EES=$(cat "${EE_CONF}" | grep -oE "${PAT}") + EES="${EES##*=}" +fi + +if [ -z "${EES}" ]; then +#EE_SETTINGS +PAT="^${SETTING}=(.*)" + EES=$(cat "${EE_CONF}" | grep -oE "${PAT}") + EES="${EES##*=}" +fi + +echo "${EES}" +} + +set_ee_setting() { +# argument $1 is the setting name e.g. nes.integerscale. $2 is the value, e.g "1" + sed -i "/$1=/d" "${EE_CONF}" + [ $2 == "disable" ] && echo "#${1}=" >> "${EE_CONF}" || echo "${1}=${2}" >> "${EE_CONF}" +} + +get_es_setting() { + echo $(sed -n "s|\s*<${1} name=\"${2}\" value=\"\(.*\)\" />|\1|p" ${ES_CONF}) +} + + +normperf() { + # A foo function as in steam deck is not needed, however sometime it's called and I am lazy to edit everything, sorry -Xargon + return +} + +maxperf() { + # A foo function as in steam deck is not needed, however sometime it's called and I am lazy to edit everything, sorry -Xargon + return +} + + +ee_check_bios() { + +PLATFORM="${1}" +CORE="${2}" +EMULATOR="${3}" +ROMNAME="${4}" +LOG="${5}" + +if [[ -z "$LOG" ]]; then + LOG="/tmp/logs/exec.log" + cat /etc/motd > "$LOG" +fi + +MISSINGBIOS="$(batocera-systems --strictfilter ${PLATFORM})" +if [ "$?" == "2" ]; then + +# formating so it looks nice :) +PLATFORMNAME="${MISSINGBIOS##*>}" # read from -P onwards +PLATFORMNAME="${PLATFORMNAME%%MISSING*}" # until a space is found +PLATFORMNAME=$(echo $PLATFORMNAME | sed -e 's/\\n//g') + +if [[ -f "${LOG}" ]]; then +echo "${CORE} ${EMULATOR} ${ROMNAME}" >> $LOG +echo "${PLATFORMNAME} missing BIOS - Could not find all BIOS: " >> $LOG +echo "please make sure you copied the files into the corresponding folder " >> $LOG +echo "${MISSINGBIOS}" >> $LOG +fi + MISSINGBIOS=$(echo "$MISSINGBIOS" | sed -e 's/$/\\n/g') + + /usr/bin/error.sh "${PLATFORMNAME} missing BIOS" "Could not find all BIOS/files in /storage/roms, the game may not work:\n\n ${MISSINGBIOS}\n\nPlease make sure you copied the files into the corresponding folder." + error_process="$!" + pkill -P $error_process +fi +} + +message_stream () { + local MESSAGE=$1 + local DELAY=$2 + local LOADBUFFER=0 + local ANSI=0 + for (( i=0; i<${#MESSAGE}; i++ )) + do + CHAR="${MESSAGE:$i:1}" + # Is this an escape character? + if [ "${CHAR}" == "\\" ] + then + LOADBUFFER=1 + BUFFER="$BUFFER${CHAR}" + continue + fi + + # Is this ANSI? (\e[*[a-Z]) + if [ "${BUFFER}" == "\e[" ] && [ "${LOADBUFFER}" -eq 1 ] + then + ANSI=1 + BUFFER="$BUFFER${CHAR}" + continue + fi + + if [ "${LOADBUFFER}" -eq 1 ] && [ "${ANSI}" -eq 1 ] + then + # If it isn't ANSI it's a control char like \n + if [[ "${CHAR}" =~ [a-Z] ]] + then + echo -ne "${BUFFER}${CHAR}" >/dev/console + unset BUFFER + LOADBUFFER=0 + ANSI=0 + fi + else + # otherwise it's text + echo -ne "${BUFFER}${CHAR}" >/dev/console + unset BUFFER + LOADBUFFER=0 + ANSI=0 + fi + sleep ${DELAY} + done +} + +spinny_cursor() { + message_stream "$1" 0 + for (( c=0; c<=$2; c++ )) + do + echo -ne '\e[2D' '-' > /dev/console + sleep .01 + echo -ne '\e[2D' '\\' > /dev/console + sleep .01 + echo -ne '\e[2D' '|' > /dev/console + sleep .01 + echo -ne '\e[2D' '/' > /dev/console + sleep .01 + done + echo -ne '\e[80D\e[K' > /dev/console +} + +jslisten() { + # A foo function as in steam deck is not needed, however sometime it's called and I am lazy to edit everything, sorry -Xargon + return +} + + +# 351EDECK specific code + +export -f get_ee_setting +export -f set_ee_setting +export -f get_es_setting +export -f maxperf +export -f normperf +export -f ee_check_bios +export -f message_stream +export -f spinny_cursor +#export -f jslisten +#export -f init_port diff --git a/install-retrodeck.sh b/install-retrodeck.sh new file mode 100755 index 00000000..9982b7a6 --- /dev/null +++ b/install-retrodeck.sh @@ -0,0 +1,248 @@ +#!/bin/bash + +INSTALL_DIR=~/retrodeck +CORES_LINK=https://buildbot.libretro.com/stable/1.10.1/linux/x86_64/RetroArch_cores.7z +PREVIOUS_DIR=$PWD + +echo "Welcome to the RetroDECK installer." +echo "RetroDECK will be installed in $INSTALL_DIR." + +# TODO-MAYBE: give the option to change the installation directory? + +echo "WARNING: RetroDECK will replace your retroarch.cfg, the former one will be renamed moved in ~/.config/retroarch/retroarch.cfg.bak." +echo "Whenever a choice is prompted just accept it to continue (yes/enter), root password will be asked." +# but maybe it will not affect the original retroarch, let's see +# maybe --root option of pacman may be useful to install my own copy of retroarch without messing the one already installed +read -n 1 -r -s -p $'Press enter to continue...\n' +echo "Installing RetroDECK in $INSTALL_DIR, please stand by." + +cd $INSTALL_DIR + +# TODO: download everything from retrodeck github +# git clone --recursive https://github.com/XargonWan/RetroDECK retrodeck + +# Initalizing rom folders +if [ test ! -d "$INSTALL_DIR/storage/roms/" ]; then + mkdir -p $INSTALL_DIR/storage/roms/ +fi +if [ test ! -d "$INSTALL_DIR/roms" ]; then + ln -s $INSTALL_DIR/storage/roms $INSTALL_DIR/roms +fi +mkdir -p $INSTALL_DIR/roms/3do +mkdir -p $INSTALL_DIR/roms/amiga +mkdir -p $INSTALL_DIR/roms/amigacd32 +mkdir -p $INSTALL_DIR/roms/amstradcpc +mkdir -p $INSTALL_DIR/roms/arcade +mkdir -p $INSTALL_DIR/roms/atari2600 +mkdir -p $INSTALL_DIR/roms/atari5200 +mkdir -p $INSTALL_DIR/roms/atari7800 +mkdir -p $INSTALL_DIR/roms/atarist +mkdir -p $INSTALL_DIR/roms/atari800 +mkdir -p $INSTALL_DIR/roms/atomiswave +mkdir -p $INSTALL_DIR/roms/channelf +mkdir -p $INSTALL_DIR/roms/colecovision +mkdir -p $INSTALL_DIR/roms/c64 +mkdir -p $INSTALL_DIR/roms/c128 +mkdir -p $INSTALL_DIR/roms/vic20 +mkdir -p $INSTALL_DIR/roms/laserdisc +mkdir -p $INSTALL_DIR/roms/dreamcast +mkdir -p $INSTALL_DIR/roms/easyrpg +mkdir -p $INSTALL_DIR/roms/famicom +mkdir -p $INSTALL_DIR/roms/fbn +mkdir -p $INSTALL_DIR/roms/gb +mkdir -p $INSTALL_DIR/roms/gbh +mkdir -p $INSTALL_DIR/roms/gameandwatch +mkdir -p $INSTALL_DIR/roms/gba +mkdir -p $INSTALL_DIR/roms/fds +mkdir -p $INSTALL_DIR/roms/c16 +mkdir -p $INSTALL_DIR/roms/ggh +mkdir -p $INSTALL_DIR/roms/gbah +mkdir -p $INSTALL_DIR/roms/intellivision +mkdir -p $INSTALL_DIR/roms/gbch +mkdir -p $INSTALL_DIR/roms/atarilynx +mkdir -p $INSTALL_DIR/roms/mame +mkdir -p $INSTALL_DIR/roms/dos +mkdir -p $INSTALL_DIR/roms/snesmsu1 +mkdir -p $INSTALL_DIR/roms/msx +mkdir -p $INSTALL_DIR/roms/msx2 +mkdir -p $INSTALL_DIR/roms/naomi +mkdir -p $INSTALL_DIR/roms/neogeo +mkdir -p $INSTALL_DIR/roms/ngp +mkdir -p $INSTALL_DIR/roms/nds +mkdir -p $INSTALL_DIR/roms/n64 +mkdir -p $INSTALL_DIR/roms/nes +mkdir -p $INSTALL_DIR/roms/nesh +mkdir -p $INSTALL_DIR/roms/ngpc +mkdir -p $INSTALL_DIR/roms/neocd +mkdir -p $INSTALL_DIR/roms/pc-9800 +mkdir -p $INSTALL_DIR/roms/pcengine +mkdir -p $INSTALL_DIR/roms/pcenginecd +mkdir -p $INSTALL_DIR/roms/pcfx +mkdir -p $INSTALL_DIR/roms/openbor +mkdir -p $INSTALL_DIR/roms/piece +mkdir -p $INSTALL_DIR/roms/odyssey2 +mkdir -p $INSTALL_DIR/roms/psp +mkdir -p $INSTALL_DIR/roms/pspminis +mkdir -p $INSTALL_DIR/roms/pokemini +mkdir -p $INSTALL_DIR/roms/homebrew +mkdir -p $INSTALL_DIR/roms/ports +mkdir -p $INSTALL_DIR/roms/sc-3000 +mkdir -p $INSTALL_DIR/roms/scummvm +mkdir -p $INSTALL_DIR/roms/psx +mkdir -p $INSTALL_DIR/roms/segacd +mkdir -p $INSTALL_DIR/roms/sega32x +mkdir -p $INSTALL_DIR/roms/genesis +mkdir -p $INSTALL_DIR/roms/genh +mkdir -p $INSTALL_DIR/roms/mastersystem +mkdir -p $INSTALL_DIR/roms/megadrive +mkdir -p $INSTALL_DIR/roms/megaduck +mkdir -p $INSTALL_DIR/roms/saturn +mkdir -p $INSTALL_DIR/roms/sg-1000 +mkdir -p $INSTALL_DIR/roms/x1 +mkdir -p $INSTALL_DIR/roms/zxspectrum +mkdir -p $INSTALL_DIR/roms/zx81 +mkdir -p $INSTALL_DIR/roms/pc-8800 +mkdir -p $INSTALL_DIR/roms/snes +mkdir -p $INSTALL_DIR/roms/supergrafx +mkdir -p $INSTALL_DIR/roms/pico-8 +mkdir -p $INSTALL_DIR/roms/megacd +mkdir -p $INSTALL_DIR/roms/snesh +mkdir -p $INSTALL_DIR/roms/satellaview +mkdir -p $INSTALL_DIR/roms/sfc +mkdir -p $INSTALL_DIR/roms/sufami +mkdir -p $INSTALL_DIR/roms/tic-80 +mkdir -p $INSTALL_DIR/roms/tg16 +mkdir -p $INSTALL_DIR/roms/solarus +mkdir -p $INSTALL_DIR/roms/vectrex +mkdir -p $INSTALL_DIR/roms/gbc +mkdir -p $INSTALL_DIR/roms/videopac +mkdir -p $INSTALL_DIR/roms/virtualboy +mkdir -p $INSTALL_DIR/roms/wonderswan +mkdir -p $INSTALL_DIR/roms/wonderswancolor +mkdir -p $INSTALL_DIR/roms/ecwolf +mkdir -p $INSTALL_DIR/roms/x68000 +mkdir -p $INSTALL_DIR/roms/build +mkdir -p $INSTALL_DIR/roms/tools +mkdir -p $INSTALL_DIR/roms/imageviewer +mkdir -p $INSTALL_DIR/roms/gamegear +mkdir -p $INSTALL_DIR/roms/tg16cd +mkdir -p $INSTALL_DIR/roms/j2me +mkdir -p $INSTALL_DIR/roms/uzebox +mkdir -p $INSTALL_DIR/roms/supervision +mkdir -p $INSTALL_DIR/roms/doom + +# Initializing directories +mkdir -p $INSTALL_DIR/storage/.config/ +mkdir -p $INSTALL_DIR/usr/ +mkdir -p $INSTALL_DIR/emulators +ln -s $INSTALL_DIR/emulationstation ~/.emulationstation + + +# Defining architecture +rm -f $INSTALL_DIR/storage/.config/.OS_ARCH +touch $INSTALL_DIR/storage/.config/.OS_ARCH +echo "DECK" >> $INSTALL_DIR/storage/.config/.OS_ARCH + +# Installing RetroArch +sudo pacman -S retroarch +# Setting up RetroArch +mkdir -p ~/.config/retroarch/ +mv ~/.config/retroarch/retroarch.cfg ~/.config/retroarch/retroarch.cfg.bak +mv $INSTALL_DIR/retroarch.cfg ~/.config/retroarch/ +# TODO: download controller config + +# Installing libretro cores +cd $INSTALL_DIR/emulators + +if test -f "$INSTALL_DIR/emulators/RetroArch_cores.7z"; then + read -p "The RetroArch cores seems to be already downloaded, do you want to re-download them? [Y/n]: " -n 1 -r + if [[ ! $REPLY =~ ^[Nn]$ ]]; then + break + else + rm -rf RetroArch* + wget $CORES_LINK + fi +else + wget $CORES_LINK +fi + +7z x RetroArch_cores.7z +mv $INSTALL_DIR/emulators/RetroArch-Linux-x86_64/RetroArch-Linux-x86_64.AppImage.home/.config/retroarch/cores $INSTALL_DIR/emulators/ + +# TODO: Installing standalone emulators + +# Installing 351elec-emulationstation +cd $INSTALL_DIR +git clone --recursive https://github.com/351ELEC/351elec-emulationstation emulationstation +cd emulationstation +sudo pacman -S base-devel cmake freeimage sdl2_mixer sdl2 rapidjson boost +cmake -DENABLE_EMUELEC=1 -DGLES2=0 -DDISABLE_KODI=1 -DENABLE_FILEMANAGER=0 -DCEC=0 -DRG552=1 +make -j$(nproc) +cp $INSTALL_DIR/es_systems.cfg $INSTALL_DIR/emulationstation/ +cp $INSTALL_DIR/es_settings.cfg $INSTALL_DIR/emulationstation/ +cp $INSTALL_DIR/es_input.cfg $INSTALL_DIR/emulationstation/ + +# Installing default theme +mkdir -p $INSTALL_DIR/emulationstation/themes +cd $INSTALL_DIR/emulationstation/themes +git clone --recursive https://github.com/anthonycaccese/es-theme-art-book-next + + +# Downloading needed files +# TODO 351elec-es-packages batocera-config batocera-scraper batocera-settings runemu.py setsettings.py + +# Creating desktop element +rm -f ~/Desktop/RetroDECK.desktop +touch ~/Desktop/RetroDECK.desktop +cat << EOF >> ~/Desktop/RetroDECK.desktop +[Desktop Entry] +Comment=An enbedded emulation system. +Exec=$INSTALL_DIR/retrodeck.sh +GenericName=RetroDECK +Icon=$INSTALL_DIR/res/icon128.png +MimeType= +Name=RetroDECK +Path=$INSTALL_DIR/ +StartupNotify=true +Terminal=false +TerminalOptions= +Type=Application +X-DBUS-ServiceName= +X-DBUS-StartupType= +X-KDE-SubstituteUID=false +X-KDE-Username= +EOF + +# Creating start script +rm -rf $INSTALL_DIR/retrodeck.sh +touch $INSTALL_DIR/retrodeck.sh +cat << EOF >> $INSTALL_DIR/retrodeck.sh +#!/bin/bash + +$INSTALL_DIR/export_func.sh + +mkdir -p /tmp/logs + +if [ test -d "/tmp/cores" ]; then break +else + ln -s $INSTALL_DIR/emulators/cores /tmp/cores +fi + +$INSTALL_DIR/emulationstation/emulationstation +EOF + +chmod 777 $INSTALL_DIR/retrodeck.sh +chmod 777 $INSTALL_DIR/export_func.sh + +# Cleaning up +# TODO: these removal must be made when I am sure tghis file is safe on github +#rm -rf $INSTALL_DIR/emulators/RetroArch-Linux-x86_64 +#rm -rf $INSTALL_DIR/emulators/RetroArch_cores.7z +#rm $INSTALL_DIR/es_systems.cfg $INSTALL_DIR/emulationstation/ +#rm $INSTALL_DIR/es_settings.cfg $INSTALL_DIR/emulationstation/ +#rm $INSTALL_DIR/es_input.cfg $INSTALL_DIR/emulationstation/ + +echo "Installation terminated, you can run RetroDECK from the desktop link or add it on your Steam Library." +# TODO: maybe I can add it to the steam library directly, I think I have to close steam and design a banner + +cd $PREVIOUS_DIR diff --git a/res/icon128.png b/res/icon128.png new file mode 100644 index 0000000000000000000000000000000000000000..0564c245bde9a2de3f7ed943b14f3b1098eca465 GIT binary patch literal 3065 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 gfSSSouUFg(754lsDlniwjNbdK)& default all options menu +## none -> no menu except the game search menu +## bartop -> less menu, only needed for bartops +#system.es.menu=default + +# ------------ B - Network ------------ # +## Set system hostname +system.hostname=351ELEC +## Activate wifi (0,1) +wifi.enabled=1 +## Wifi SSID (string) +#wifi.ssid= +## Wifi KEY (string) +## after rebooting the "new key" is replace by a hidden value "enc:xxxxx" +## you can edit the "enc:xxxxx" value to replace by a clear value, it will be updated again at the following reboot +## Escape your special chars (# ; $) with a backslash : $ => \$ +#wifi.key= + +# secondary wifi (not configurable via the user interface) +#wifi2.ssid=new ssid +#wifi2.key=new key + +# third wifi (not configurable via the user interface) +#wifi3.ssid=new ssid +#wifi3.key=new key + +# ------------ C - Audio ------------ # +## Set the audio device (auto, hdmi, jack, speakers, headphones) mostly for OdroidGoAdvance +## Set system volume (0..100) +## Enable or disable system sounds in ES (0,1) +audio.bgmusic=1 + +# -------------- D - Controllers ----------------- # +# Enable support for standard bluetooth controllers +controllers.bluetooth.enabled=1 + +# ------------ F - Language and keyboard ------------ # +## Set the language of the system (fr_FR,en_US,en_GB,de_DE,pt_BR,es_ES,it_IT,eu_ES,tr_TR,zh_CN) +system.language=en_US +## Set you local time +## Select your timezone from : ls /usr/share/zoneinfo/ (string) +system.timezone=Europe/London + +# ------------ G - UPDATES ------------ # +## Automatically check for updates at start (0,1) +updates.enabled=1 +updates.type=release + +# fan profile - controls fan speed (values: default/performance/quiet) +# Not used for DECK +# fan.profile=default + +# ------------ H - HERE IT IS - GLOBAL EMULATOR CONFIGURATION ------------ # +## The global value will be used for all emulators, except if the value +## is redefined in the emulator + +## Bezel on by default +global.bezel=default + +## Retroarch menu driver, ozone (default), rgui or xmb +global.retroarch.menu_driver=ozone + +## Shader set +## Automatically select shaders for all systems +## (none, retro, scanlines) + +## Once enabled, your screen will be cropped, and you will have a pixel perfect image (0,1) +global.integerscale=1 + +## Set gpslp shader for all emulators (prefer shadersets above). Absolute path (string) +#global.shaders= + +## Set ratio for all emulators (auto,4/3,16/9,16/10,custom) +global.ratio=4/3 + +## Set autosave/load savestate for all emulators (0,1,2,3) +global.autosave=2 + +## Set incremental savestates for all emulators (0,1) +global.incrementalsavestates=0 + +## Set runahead frames for all emulators (0,1,2,3,4,5,6) +global.runahead=0 + +## Set secondinstance for runahead for all emulators (0,1) +global.secondinstance=0 + +## Enable retroarchievements (0,1) +## Set your www.retroachievements.org username/password +## Escape your special chars (# ; $) with a backslash : $ => \$ +global.retroachievements=1 +global.retroachievements.hardcore=0 +global.retroachievements.leaderboards=disabled +global.retroachievements.challengeindicators=0 +global.retroachievements.richpresence=0 +global.retroachievements.testunofficial=0 +global.retroachievements.soundenable=0 +global.retroachievements.verbose=0 +global.retroachievements.screenshot=1 +global.retroachievements.username= +global.retroachievements.password= + +## Enable RetroArch AI game translation service +#global.ai_service_enabled=0 +#global.ai_service_url= +#global.ai_target_lang= + +## Configurations generated by Emulationstation +audio.display_titles=1 +audio.persystem=0 +global.netplay=0 +global.netplay.port=55435 +global.netplay.relay=none +audio.device=headphone +audio.volume=75 +brightness.level=50 +system.brightness=50 + +## Device Overclock +overclock=0 + +# ------------ I - EMULATORS CHOICES ----------- # +## You can override the global configuration here +## Here is the snes example +#snes.shaders=mysnesshader.gplsp + +3do.maxperf=1 +3do.rewind=0 +arcade.maxperf=1 +arcade.autosave=0 +atari2600.ratio=squarepixel +atarilynx.ratio=squarepixel +atarilynx.shaderset=handheld/lcd3x.glslp +atomiswave.maxperf=1 +dreamcast.maxperf=1 +fbn.ratio=squarepixel +gamegear.bezel.overlay.grid=1 +gamegear.bezel.overlay.shadow=1 +gamegear.ratio=squarepixel +gb.bezel.overlay.grid=1 +gb.bezel.overlay.shadow=1 +gb.ratio=squarepixel +gba.ratio=squarepixel +gba.shaderset=handheld/lcd3x.glslp +gbah.ratio=squarepixel +gbah.shaderset=handheld/lcd3x.glslp +gbc.bezel.overlay.grid=1 +gbc.bezel.overlay.shadow=1 +gbc.ratio=squarepixel +gbch.bezel.overlay.grid=1 +gbch.bezel.overlay.shadow=1 +gbch.ratio=squarepixel +gbh.bezel.overlay.grid=1 +gbh.bezel.overlay.shadow=1 +gbh.ratio=squarepixel +ggh.bezel.overlay.grid=1 +ggh.bezel.overlay.shadow=1 +ggh.ratio=squarepixel +j2me.maxperf=1 +megadrive.ratio=squarepixel +mame.autosave=0 +mame.maxperf=1 +n64.maxperf=1 +nds.maxperf=1 +naomi.maxperf=1 +ngp.ratio=squarepixel +ngp.shaderset=handheld/lcd3x.glslp +ngpc.ratio=squarepixel +ngpc.shaderset=handheld/lcd3x.glslp +pc.maxperf=1 +pcfx.maxperf=1 +pokemini.ratio=3/2 +psp.maxperf=1 +psp.ratio=squarepixel +pspminis.maxperf=1 +pspminis.ratio=squarepixel +psx.integerscaleoverscale=1 +saturn.ratio=squarepixel +segacd.ratio=squarepixel +supervision.bezel.overlay.grid=1 +supervision.bezel.overlay.shadow=1 +supervision.ratio=squarepixel +uzebox.integerscale=1 +vectrex.ratio=3/4 +virtualboy.maxperf=1 +virtualboy.ratio=squarepixel +wonderswan.ratio=squarepixel +wonderswan.shaderset=handheld/lcd3x.glslp +wonderswancolor.ratio=squarepixel +wonderswancolor.shaderset=handheld/lcd3x.glslp \ No newline at end of file diff --git a/storage/.config/retroarch/retroarch.cfg b/storage/.config/retroarch/retroarch.cfg new file mode 100644 index 00000000..9e8195fa --- /dev/null +++ b/storage/.config/retroarch/retroarch.cfg @@ -0,0 +1,3195 @@ +accessibility_enable = "false" +accessibility_narrator_speech_speed = "5" +ai_service_enable = "false" +ai_service_mode = "1" +ai_service_pause = "false" +ai_service_source_lang = "0" +ai_service_target_lang = "0" +ai_service_url = "http://localhost:4404/" +all_users_control_menu = "false" +apply_cheats_after_load = "false" +apply_cheats_after_toggle = "false" +aspect_ratio_index = "21" +assets_directory = "/usr/share/retroarch/assets" +audio_block_frames = "0" +audio_device = "" +audio_driver = "pulse" +audio_dsp_plugin = "" +audio_enable = "true" +audio_enable_menu = "false" +audio_enable_menu_bgm = "false" +audio_enable_menu_cancel = "false" +audio_enable_menu_notice = "false" +audio_enable_menu_ok = "false" +audio_fastforward_mute = "false" +audio_filter_dir = "/usr/share/retroarch/filters/64bit/audio" +audio_latency = "64" +audio_max_timing_skew = "0.050000" +audio_mixer_mute_enable = "false" +audio_mixer_volume = "0.000000" +audio_mute_enable = "false" +audio_out_rate = "48000" +audio_rate_control = "true" +audio_rate_control_delta = "0.005000" +audio_resampler = "sinc" +audio_resampler_quality = "3" +audio_sync = "true" +audio_volume = "0.000000" +auto_overrides_enable = "true" +auto_remaps_enable = "true" +auto_screenshot_filename = "true" +auto_shaders_enable = "true" +autosave_interval = "10" +block_sram_overwrite = "false" +bluetooth_driver = "null" +builtin_imageviewer_enable = "true" +builtin_mediaplayer_enable = "true" +bundle_assets_dst_path = "" +bundle_assets_dst_path_subdir = "" +bundle_assets_extract_enable = "false" +bundle_assets_extract_last_version = "0" +bundle_assets_extract_version_current = "0" +bundle_assets_src_path = "" +cache_directory = "" +camera_allow = "false" +camera_device = "" +camera_driver = "video4linux2" +cheat_database_path = "~/.config/retroarch/cheats" +check_firmware_before_loading = "false" +cheevos_auto_screenshot = "true" +cheevos_badges_enable = "false" +cheevos_challenge_indicators = "false" +cheevos_custom_host = "" +cheevos_enable = "true" +cheevos_hardcore_mode_enable = "false" +cheevos_leaderboards_enable = "false" +cheevos_password = "" +cheevos_richpresence_enable = "false" +cheevos_start_active = "false" +cheevos_test_unofficial = "false" +cheevos_token = "" +cheevos_unlock_sound_enable = "false" +cheevos_username = "" +cheevos_verbose_enable = "false" +config_save_on_exit = "true" +content_database_path = "~/.config/retroarch/database/rdb" +content_favorites_directory = "default" +content_favorites_path = "~/retrodeck/storage/.config/retroarch/content_favorites.lpl" +content_favorites_size = "200" +content_history_directory = "default" +content_history_path = "~/retrodeck/storage/.config/retroarch/content_history.lpl" +content_history_size = "200" +content_image_history_directory = "default" +content_image_history_path = "~/retrodeck/storage/.config/retroarch/content_image_history.lpl" +content_music_history_directory = "default" +content_music_history_path = "~/retrodeck/storage/.config/retroarch/content_music_history.lpl" +content_runtime_log = "true" +content_runtime_log_aggregate = "false" +content_show_add = "true" +content_show_add_entry = "2" +content_show_explore = "true" +content_show_favorites = "true" +content_show_history = "true" +content_show_images = "true" +content_show_music = "true" +content_show_netplay = "true" +content_show_playlists = "true" +content_show_settings = "true" +content_show_settings_password = "" +content_show_video = "true" +content_video_directory = "default" +content_video_history_path = "~/retrodeck/storage/.config/retroarch/content_video_history.lpl" +core_assets_directory = "~/.config/retroarch/downloads" +core_info_cache_enable = "false" +core_option_category_enable = "true" +core_options_path = "" +core_set_supports_no_game_enable = "true" +core_updater_auto_backup = "true" +core_updater_auto_backup_history_size = "1" +core_updater_auto_extract_archive = "true" +core_updater_buildbot_assets_url = "http://buildbot.libretro.com/assets/" +core_updater_buildbot_cores_url = "http://buildbot.libretro.com/nightly/linux/x86_64/latest/" +core_updater_show_experimental_cores = "false" +crt_switch_center_adjust = "0" +crt_switch_hires_menu = "false" +crt_switch_porch_adjust = "0" +crt_switch_resolution = "0" +crt_switch_resolution_super = "2560" +crt_switch_resolution_use_custom_refresh_rate = "false" +crt_switch_timings = "" +crt_video_refresh_rate = "60.000000" +current_resolution_id = "0" +cursor_directory = "~/.config/retroarch/database/cursors" +custom_viewport_height = "799" +custom_viewport_width = "1279" +custom_viewport_x = "1" +custom_viewport_y = "1" +desktop_menu_enable = "true" +discord_allow = "false" +discord_app_id = "475456035851599874" +driver_switch_enable = "true" +dynamic_wallpapers_directory = "default" +enable_device_vibration = "false" +facebook_stream_key = "" +fastforward_ratio = "0.000000" +filter_by_current_core = "false" +flicker_filter_enable = "false" +flicker_filter_index = "0" +fps_show = "false" +fps_update_interval = "256" +frame_time_counter_reset_after_fastforwarding = "false" +frame_time_counter_reset_after_load_state = "false" +frame_time_counter_reset_after_save_state = "false" +framecount_show = "false" +frontend_log_level = "1" +game_specific_options = "true" +gamemode_enable = "false" +gamma_correction = "0" +global_core_options = "false" +history_list_enable = "true" +input_ai_service = "nul" +input_ai_service_axis = "nul" +input_ai_service_btn = "nul" +input_ai_service_mbtn = "nul" +input_analog_deadzone = "0.000000" +input_analog_sensitivity = "1.000000" +input_audio_mute = "f9" +input_audio_mute_axis = "nul" +input_audio_mute_btn = "nul" +input_audio_mute_mbtn = "nul" +input_auto_game_focus = "0" +input_auto_mouse_grab = "false" +input_autodetect_enable = "true" +input_axis_threshold = "0.500000" +input_bind_hold = "2" +input_bind_timeout = "5" +input_cheat_index_minus = "t" +input_cheat_index_minus_axis = "nul" +input_cheat_index_minus_btn = "nul" +input_cheat_index_minus_mbtn = "nul" +input_cheat_index_plus = "y" +input_cheat_index_plus_axis = "nul" +input_cheat_index_plus_btn = "nul" +input_cheat_index_plus_mbtn = "nul" +input_cheat_toggle = "u" +input_cheat_toggle_axis = "nul" +input_cheat_toggle_btn = "nul" +input_cheat_toggle_mbtn = "nul" +input_close_content = "nul" +input_close_content_axis = "nul" +input_close_content_btn = "nul" +input_close_content_mbtn = "nul" +input_descriptor_hide_unbound = "false" +input_descriptor_label_show = "true" +input_desktop_menu_toggle = "f5" +input_desktop_menu_toggle_axis = "nul" +input_desktop_menu_toggle_btn = "nul" +input_desktop_menu_toggle_mbtn = "nul" +input_device_p1 = "0" +input_device_p10 = "0" +input_device_p11 = "0" +input_device_p12 = "0" +input_device_p13 = "0" +input_device_p14 = "0" +input_device_p15 = "0" +input_device_p16 = "0" +input_device_p2 = "0" +input_device_p3 = "0" +input_device_p4 = "0" +input_device_p5 = "0" +input_device_p6 = "0" +input_device_p7 = "0" +input_device_p8 = "0" +input_device_p9 = "0" +input_disk_eject_toggle = "nul" +input_disk_eject_toggle_axis = "nul" +input_disk_eject_toggle_btn = "nul" +input_disk_eject_toggle_mbtn = "nul" +input_disk_next = "nul" +input_disk_next_axis = "nul" +input_disk_next_btn = "nul" +input_disk_next_mbtn = "nul" +input_disk_prev = "nul" +input_disk_prev_axis = "nul" +input_disk_prev_btn = "nul" +input_disk_prev_mbtn = "nul" +input_driver = "x" +input_duty_cycle = "3" +input_enable_hotkey = "nul" +input_enable_hotkey_axis = "nul" +input_enable_hotkey_btn = "nul" +input_enable_hotkey_mbtn = "nul" +input_exit_emulator = "escape" +input_exit_emulator_axis = "nul" +input_exit_emulator_btn = "nul" +input_exit_emulator_mbtn = "nul" +input_fps_toggle = "f3" +input_fps_toggle_axis = "nul" +input_fps_toggle_btn = "nul" +input_fps_toggle_mbtn = "nul" +input_frame_advance = "k" +input_frame_advance_axis = "nul" +input_frame_advance_btn = "nul" +input_frame_advance_mbtn = "nul" +input_game_focus_toggle = "scroll_lock" +input_game_focus_toggle_axis = "nul" +input_game_focus_toggle_btn = "nul" +input_game_focus_toggle_mbtn = "nul" +input_grab_mouse_toggle = "f11" +input_grab_mouse_toggle_axis = "nul" +input_grab_mouse_toggle_btn = "nul" +input_grab_mouse_toggle_mbtn = "nul" +input_hold_fast_forward = "l" +input_hold_fast_forward_axis = "nul" +input_hold_fast_forward_btn = "nul" +input_hold_fast_forward_mbtn = "nul" +input_hold_slowmotion = "e" +input_hold_slowmotion_axis = "nul" +input_hold_slowmotion_btn = "nul" +input_hold_slowmotion_mbtn = "nul" +input_hotkey_block_delay = "5" +input_joypad_driver = "udev" +input_keyboard_layout = "" +input_libretro_device_p1 = "1" +input_libretro_device_p10 = "1" +input_libretro_device_p11 = "1" +input_libretro_device_p12 = "1" +input_libretro_device_p13 = "1" +input_libretro_device_p14 = "1" +input_libretro_device_p15 = "1" +input_libretro_device_p16 = "1" +input_libretro_device_p2 = "1" +input_libretro_device_p3 = "1" +input_libretro_device_p4 = "1" +input_libretro_device_p5 = "1" +input_libretro_device_p6 = "1" +input_libretro_device_p7 = "1" +input_libretro_device_p8 = "1" +input_libretro_device_p9 = "1" +input_load_state = "f4" +input_load_state_axis = "nul" +input_load_state_btn = "nul" +input_load_state_mbtn = "nul" +input_max_users = "5" +input_menu_toggle = "f1" +input_menu_toggle_axis = "nul" +input_menu_toggle_btn = "nul" +input_menu_toggle_gamepad_combo = "0" +input_menu_toggle_mbtn = "nul" +input_movie_record_toggle = "o" +input_movie_record_toggle_axis = "nul" +input_movie_record_toggle_btn = "nul" +input_movie_record_toggle_mbtn = "nul" +input_netplay_fade_chat_toggle = "nul" +input_netplay_fade_chat_toggle_axis = "nul" +input_netplay_fade_chat_toggle_btn = "nul" +input_netplay_fade_chat_toggle_mbtn = "nul" +input_netplay_game_watch = "i" +input_netplay_game_watch_axis = "nul" +input_netplay_game_watch_btn = "nul" +input_netplay_game_watch_mbtn = "nul" +input_netplay_host_toggle = "nul" +input_netplay_host_toggle_axis = "nul" +input_netplay_host_toggle_btn = "nul" +input_netplay_host_toggle_mbtn = "nul" +input_netplay_ping_toggle = "nul" +input_netplay_ping_toggle_axis = "nul" +input_netplay_ping_toggle_btn = "nul" +input_netplay_ping_toggle_mbtn = "nul" +input_netplay_player_chat = "tilde" +input_netplay_player_chat_axis = "nul" +input_netplay_player_chat_btn = "nul" +input_netplay_player_chat_mbtn = "nul" +input_nowinkey_enable = "false" +input_osk_toggle = "f12" +input_osk_toggle_axis = "nul" +input_osk_toggle_btn = "nul" +input_osk_toggle_mbtn = "nul" +input_overlay = "" +input_overlay_aspect_adjust_landscape = "0.000000" +input_overlay_aspect_adjust_portrait = "0.000000" +input_overlay_auto_rotate = "false" +input_overlay_auto_scale = "false" +input_overlay_behind_menu = "false" +input_overlay_enable = "false" +input_overlay_enable_autopreferred = "true" +input_overlay_hide_in_menu = "true" +input_overlay_hide_when_gamepad_connected = "false" +input_overlay_next = "nul" +input_overlay_next_axis = "nul" +input_overlay_next_btn = "nul" +input_overlay_next_mbtn = "nul" +input_overlay_opacity = "0.700000" +input_overlay_scale_landscape = "1.000000" +input_overlay_scale_portrait = "1.000000" +input_overlay_show_inputs = "2" +input_overlay_show_inputs_port = "0" +input_overlay_show_mouse_cursor = "true" +input_overlay_x_offset_landscape = "0.000000" +input_overlay_x_offset_portrait = "0.000000" +input_overlay_x_separation_landscape = "0.000000" +input_overlay_x_separation_portrait = "0.000000" +input_overlay_y_offset_landscape = "0.000000" +input_overlay_y_offset_portrait = "0.000000" +input_overlay_y_separation_landscape = "0.000000" +input_overlay_y_separation_portrait = "0.000000" +input_pause_toggle = "p" +input_pause_toggle_axis = "nul" +input_pause_toggle_btn = "nul" +input_pause_toggle_mbtn = "nul" +input_player10_a = "nul" +input_player10_a_axis = "nul" +input_player10_a_btn = "nul" +input_player10_a_mbtn = "nul" +input_player10_analog_dpad_mode = "0" +input_player10_b = "nul" +input_player10_b_axis = "nul" +input_player10_b_btn = "nul" +input_player10_b_mbtn = "nul" +input_player10_down = "nul" +input_player10_down_axis = "nul" +input_player10_down_btn = "nul" +input_player10_down_mbtn = "nul" +input_player10_gun_aux_a = "nul" +input_player10_gun_aux_a_axis = "nul" +input_player10_gun_aux_a_btn = "nul" +input_player10_gun_aux_a_mbtn = "nul" +input_player10_gun_aux_b = "nul" +input_player10_gun_aux_b_axis = "nul" +input_player10_gun_aux_b_btn = "nul" +input_player10_gun_aux_b_mbtn = "nul" +input_player10_gun_aux_c = "nul" +input_player10_gun_aux_c_axis = "nul" +input_player10_gun_aux_c_btn = "nul" +input_player10_gun_aux_c_mbtn = "nul" +input_player10_gun_dpad_down = "nul" +input_player10_gun_dpad_down_axis = "nul" +input_player10_gun_dpad_down_btn = "nul" +input_player10_gun_dpad_down_mbtn = "nul" +input_player10_gun_dpad_left = "nul" +input_player10_gun_dpad_left_axis = "nul" +input_player10_gun_dpad_left_btn = "nul" +input_player10_gun_dpad_left_mbtn = "nul" +input_player10_gun_dpad_right = "nul" +input_player10_gun_dpad_right_axis = "nul" +input_player10_gun_dpad_right_btn = "nul" +input_player10_gun_dpad_right_mbtn = "nul" +input_player10_gun_dpad_up = "nul" +input_player10_gun_dpad_up_axis = "nul" +input_player10_gun_dpad_up_btn = "nul" +input_player10_gun_dpad_up_mbtn = "nul" +input_player10_gun_offscreen_shot = "nul" +input_player10_gun_offscreen_shot_axis = "nul" +input_player10_gun_offscreen_shot_btn = "nul" +input_player10_gun_offscreen_shot_mbtn = "nul" +input_player10_gun_select = "nul" +input_player10_gun_select_axis = "nul" +input_player10_gun_select_btn = "nul" +input_player10_gun_select_mbtn = "nul" +input_player10_gun_start = "nul" +input_player10_gun_start_axis = "nul" +input_player10_gun_start_btn = "nul" +input_player10_gun_start_mbtn = "nul" +input_player10_gun_trigger = "nul" +input_player10_gun_trigger_axis = "nul" +input_player10_gun_trigger_btn = "nul" +input_player10_gun_trigger_mbtn = "1" +input_player10_joypad_index = "9" +input_player10_l = "nul" +input_player10_l2 = "nul" +input_player10_l2_axis = "nul" +input_player10_l2_btn = "nul" +input_player10_l2_mbtn = "nul" +input_player10_l3 = "nul" +input_player10_l3_axis = "nul" +input_player10_l3_btn = "nul" +input_player10_l3_mbtn = "nul" +input_player10_l_axis = "nul" +input_player10_l_btn = "nul" +input_player10_l_mbtn = "nul" +input_player10_l_x_minus = "nul" +input_player10_l_x_minus_axis = "nul" +input_player10_l_x_minus_btn = "nul" +input_player10_l_x_minus_mbtn = "nul" +input_player10_l_x_plus = "nul" +input_player10_l_x_plus_axis = "nul" +input_player10_l_x_plus_btn = "nul" +input_player10_l_x_plus_mbtn = "nul" +input_player10_l_y_minus = "nul" +input_player10_l_y_minus_axis = "nul" +input_player10_l_y_minus_btn = "nul" +input_player10_l_y_minus_mbtn = "nul" +input_player10_l_y_plus = "nul" +input_player10_l_y_plus_axis = "nul" +input_player10_l_y_plus_btn = "nul" +input_player10_l_y_plus_mbtn = "nul" +input_player10_left = "nul" +input_player10_left_axis = "nul" +input_player10_left_btn = "nul" +input_player10_left_mbtn = "nul" +input_player10_mouse_index = "9" +input_player10_r = "nul" +input_player10_r2 = "nul" +input_player10_r2_axis = "nul" +input_player10_r2_btn = "nul" +input_player10_r2_mbtn = "nul" +input_player10_r3 = "nul" +input_player10_r3_axis = "nul" +input_player10_r3_btn = "nul" +input_player10_r3_mbtn = "nul" +input_player10_r_axis = "nul" +input_player10_r_btn = "nul" +input_player10_r_mbtn = "nul" +input_player10_r_x_minus = "nul" +input_player10_r_x_minus_axis = "nul" +input_player10_r_x_minus_btn = "nul" +input_player10_r_x_minus_mbtn = "nul" +input_player10_r_x_plus = "nul" +input_player10_r_x_plus_axis = "nul" +input_player10_r_x_plus_btn = "nul" +input_player10_r_x_plus_mbtn = "nul" +input_player10_r_y_minus = "nul" +input_player10_r_y_minus_axis = "nul" +input_player10_r_y_minus_btn = "nul" +input_player10_r_y_minus_mbtn = "nul" +input_player10_r_y_plus = "nul" +input_player10_r_y_plus_axis = "nul" +input_player10_r_y_plus_btn = "nul" +input_player10_r_y_plus_mbtn = "nul" +input_player10_right = "nul" +input_player10_right_axis = "nul" +input_player10_right_btn = "nul" +input_player10_right_mbtn = "nul" +input_player10_select = "nul" +input_player10_select_axis = "nul" +input_player10_select_btn = "nul" +input_player10_select_mbtn = "nul" +input_player10_start = "nul" +input_player10_start_axis = "nul" +input_player10_start_btn = "nul" +input_player10_start_mbtn = "nul" +input_player10_turbo = "nul" +input_player10_turbo_axis = "nul" +input_player10_turbo_btn = "nul" +input_player10_turbo_mbtn = "nul" +input_player10_up = "nul" +input_player10_up_axis = "nul" +input_player10_up_btn = "nul" +input_player10_up_mbtn = "nul" +input_player10_x = "nul" +input_player10_x_axis = "nul" +input_player10_x_btn = "nul" +input_player10_x_mbtn = "nul" +input_player10_y = "nul" +input_player10_y_axis = "nul" +input_player10_y_btn = "nul" +input_player10_y_mbtn = "nul" +input_player11_a = "nul" +input_player11_a_axis = "nul" +input_player11_a_btn = "nul" +input_player11_a_mbtn = "nul" +input_player11_analog_dpad_mode = "0" +input_player11_b = "nul" +input_player11_b_axis = "nul" +input_player11_b_btn = "nul" +input_player11_b_mbtn = "nul" +input_player11_down = "nul" +input_player11_down_axis = "nul" +input_player11_down_btn = "nul" +input_player11_down_mbtn = "nul" +input_player11_gun_aux_a = "nul" +input_player11_gun_aux_a_axis = "nul" +input_player11_gun_aux_a_btn = "nul" +input_player11_gun_aux_a_mbtn = "nul" +input_player11_gun_aux_b = "nul" +input_player11_gun_aux_b_axis = "nul" +input_player11_gun_aux_b_btn = "nul" +input_player11_gun_aux_b_mbtn = "nul" +input_player11_gun_aux_c = "nul" +input_player11_gun_aux_c_axis = "nul" +input_player11_gun_aux_c_btn = "nul" +input_player11_gun_aux_c_mbtn = "nul" +input_player11_gun_dpad_down = "nul" +input_player11_gun_dpad_down_axis = "nul" +input_player11_gun_dpad_down_btn = "nul" +input_player11_gun_dpad_down_mbtn = "nul" +input_player11_gun_dpad_left = "nul" +input_player11_gun_dpad_left_axis = "nul" +input_player11_gun_dpad_left_btn = "nul" +input_player11_gun_dpad_left_mbtn = "nul" +input_player11_gun_dpad_right = "nul" +input_player11_gun_dpad_right_axis = "nul" +input_player11_gun_dpad_right_btn = "nul" +input_player11_gun_dpad_right_mbtn = "nul" +input_player11_gun_dpad_up = "nul" +input_player11_gun_dpad_up_axis = "nul" +input_player11_gun_dpad_up_btn = "nul" +input_player11_gun_dpad_up_mbtn = "nul" +input_player11_gun_offscreen_shot = "nul" +input_player11_gun_offscreen_shot_axis = "nul" +input_player11_gun_offscreen_shot_btn = "nul" +input_player11_gun_offscreen_shot_mbtn = "nul" +input_player11_gun_select = "nul" +input_player11_gun_select_axis = "nul" +input_player11_gun_select_btn = "nul" +input_player11_gun_select_mbtn = "nul" +input_player11_gun_start = "nul" +input_player11_gun_start_axis = "nul" +input_player11_gun_start_btn = "nul" +input_player11_gun_start_mbtn = "nul" +input_player11_gun_trigger = "nul" +input_player11_gun_trigger_axis = "nul" +input_player11_gun_trigger_btn = "nul" +input_player11_gun_trigger_mbtn = "1" +input_player11_joypad_index = "10" +input_player11_l = "nul" +input_player11_l2 = "nul" +input_player11_l2_axis = "nul" +input_player11_l2_btn = "nul" +input_player11_l2_mbtn = "nul" +input_player11_l3 = "nul" +input_player11_l3_axis = "nul" +input_player11_l3_btn = "nul" +input_player11_l3_mbtn = "nul" +input_player11_l_axis = "nul" +input_player11_l_btn = "nul" +input_player11_l_mbtn = "nul" +input_player11_l_x_minus = "nul" +input_player11_l_x_minus_axis = "nul" +input_player11_l_x_minus_btn = "nul" +input_player11_l_x_minus_mbtn = "nul" +input_player11_l_x_plus = "nul" +input_player11_l_x_plus_axis = "nul" +input_player11_l_x_plus_btn = "nul" +input_player11_l_x_plus_mbtn = "nul" +input_player11_l_y_minus = "nul" +input_player11_l_y_minus_axis = "nul" +input_player11_l_y_minus_btn = "nul" +input_player11_l_y_minus_mbtn = "nul" +input_player11_l_y_plus = "nul" +input_player11_l_y_plus_axis = "nul" +input_player11_l_y_plus_btn = "nul" +input_player11_l_y_plus_mbtn = "nul" +input_player11_left = "nul" +input_player11_left_axis = "nul" +input_player11_left_btn = "nul" +input_player11_left_mbtn = "nul" +input_player11_mouse_index = "10" +input_player11_r = "nul" +input_player11_r2 = "nul" +input_player11_r2_axis = "nul" +input_player11_r2_btn = "nul" +input_player11_r2_mbtn = "nul" +input_player11_r3 = "nul" +input_player11_r3_axis = "nul" +input_player11_r3_btn = "nul" +input_player11_r3_mbtn = "nul" +input_player11_r_axis = "nul" +input_player11_r_btn = "nul" +input_player11_r_mbtn = "nul" +input_player11_r_x_minus = "nul" +input_player11_r_x_minus_axis = "nul" +input_player11_r_x_minus_btn = "nul" +input_player11_r_x_minus_mbtn = "nul" +input_player11_r_x_plus = "nul" +input_player11_r_x_plus_axis = "nul" +input_player11_r_x_plus_btn = "nul" +input_player11_r_x_plus_mbtn = "nul" +input_player11_r_y_minus = "nul" +input_player11_r_y_minus_axis = "nul" +input_player11_r_y_minus_btn = "nul" +input_player11_r_y_minus_mbtn = "nul" +input_player11_r_y_plus = "nul" +input_player11_r_y_plus_axis = "nul" +input_player11_r_y_plus_btn = "nul" +input_player11_r_y_plus_mbtn = "nul" +input_player11_right = "nul" +input_player11_right_axis = "nul" +input_player11_right_btn = "nul" +input_player11_right_mbtn = "nul" +input_player11_select = "nul" +input_player11_select_axis = "nul" +input_player11_select_btn = "nul" +input_player11_select_mbtn = "nul" +input_player11_start = "nul" +input_player11_start_axis = "nul" +input_player11_start_btn = "nul" +input_player11_start_mbtn = "nul" +input_player11_turbo = "nul" +input_player11_turbo_axis = "nul" +input_player11_turbo_btn = "nul" +input_player11_turbo_mbtn = "nul" +input_player11_up = "nul" +input_player11_up_axis = "nul" +input_player11_up_btn = "nul" +input_player11_up_mbtn = "nul" +input_player11_x = "nul" +input_player11_x_axis = "nul" +input_player11_x_btn = "nul" +input_player11_x_mbtn = "nul" +input_player11_y = "nul" +input_player11_y_axis = "nul" +input_player11_y_btn = "nul" +input_player11_y_mbtn = "nul" +input_player12_a = "nul" +input_player12_a_axis = "nul" +input_player12_a_btn = "nul" +input_player12_a_mbtn = "nul" +input_player12_analog_dpad_mode = "0" +input_player12_b = "nul" +input_player12_b_axis = "nul" +input_player12_b_btn = "nul" +input_player12_b_mbtn = "nul" +input_player12_down = "nul" +input_player12_down_axis = "nul" +input_player12_down_btn = "nul" +input_player12_down_mbtn = "nul" +input_player12_gun_aux_a = "nul" +input_player12_gun_aux_a_axis = "nul" +input_player12_gun_aux_a_btn = "nul" +input_player12_gun_aux_a_mbtn = "nul" +input_player12_gun_aux_b = "nul" +input_player12_gun_aux_b_axis = "nul" +input_player12_gun_aux_b_btn = "nul" +input_player12_gun_aux_b_mbtn = "nul" +input_player12_gun_aux_c = "nul" +input_player12_gun_aux_c_axis = "nul" +input_player12_gun_aux_c_btn = "nul" +input_player12_gun_aux_c_mbtn = "nul" +input_player12_gun_dpad_down = "nul" +input_player12_gun_dpad_down_axis = "nul" +input_player12_gun_dpad_down_btn = "nul" +input_player12_gun_dpad_down_mbtn = "nul" +input_player12_gun_dpad_left = "nul" +input_player12_gun_dpad_left_axis = "nul" +input_player12_gun_dpad_left_btn = "nul" +input_player12_gun_dpad_left_mbtn = "nul" +input_player12_gun_dpad_right = "nul" +input_player12_gun_dpad_right_axis = "nul" +input_player12_gun_dpad_right_btn = "nul" +input_player12_gun_dpad_right_mbtn = "nul" +input_player12_gun_dpad_up = "nul" +input_player12_gun_dpad_up_axis = "nul" +input_player12_gun_dpad_up_btn = "nul" +input_player12_gun_dpad_up_mbtn = "nul" +input_player12_gun_offscreen_shot = "nul" +input_player12_gun_offscreen_shot_axis = "nul" +input_player12_gun_offscreen_shot_btn = "nul" +input_player12_gun_offscreen_shot_mbtn = "nul" +input_player12_gun_select = "nul" +input_player12_gun_select_axis = "nul" +input_player12_gun_select_btn = "nul" +input_player12_gun_select_mbtn = "nul" +input_player12_gun_start = "nul" +input_player12_gun_start_axis = "nul" +input_player12_gun_start_btn = "nul" +input_player12_gun_start_mbtn = "nul" +input_player12_gun_trigger = "nul" +input_player12_gun_trigger_axis = "nul" +input_player12_gun_trigger_btn = "nul" +input_player12_gun_trigger_mbtn = "1" +input_player12_joypad_index = "11" +input_player12_l = "nul" +input_player12_l2 = "nul" +input_player12_l2_axis = "nul" +input_player12_l2_btn = "nul" +input_player12_l2_mbtn = "nul" +input_player12_l3 = "nul" +input_player12_l3_axis = "nul" +input_player12_l3_btn = "nul" +input_player12_l3_mbtn = "nul" +input_player12_l_axis = "nul" +input_player12_l_btn = "nul" +input_player12_l_mbtn = "nul" +input_player12_l_x_minus = "nul" +input_player12_l_x_minus_axis = "nul" +input_player12_l_x_minus_btn = "nul" +input_player12_l_x_minus_mbtn = "nul" +input_player12_l_x_plus = "nul" +input_player12_l_x_plus_axis = "nul" +input_player12_l_x_plus_btn = "nul" +input_player12_l_x_plus_mbtn = "nul" +input_player12_l_y_minus = "nul" +input_player12_l_y_minus_axis = "nul" +input_player12_l_y_minus_btn = "nul" +input_player12_l_y_minus_mbtn = "nul" +input_player12_l_y_plus = "nul" +input_player12_l_y_plus_axis = "nul" +input_player12_l_y_plus_btn = "nul" +input_player12_l_y_plus_mbtn = "nul" +input_player12_left = "nul" +input_player12_left_axis = "nul" +input_player12_left_btn = "nul" +input_player12_left_mbtn = "nul" +input_player12_mouse_index = "11" +input_player12_r = "nul" +input_player12_r2 = "nul" +input_player12_r2_axis = "nul" +input_player12_r2_btn = "nul" +input_player12_r2_mbtn = "nul" +input_player12_r3 = "nul" +input_player12_r3_axis = "nul" +input_player12_r3_btn = "nul" +input_player12_r3_mbtn = "nul" +input_player12_r_axis = "nul" +input_player12_r_btn = "nul" +input_player12_r_mbtn = "nul" +input_player12_r_x_minus = "nul" +input_player12_r_x_minus_axis = "nul" +input_player12_r_x_minus_btn = "nul" +input_player12_r_x_minus_mbtn = "nul" +input_player12_r_x_plus = "nul" +input_player12_r_x_plus_axis = "nul" +input_player12_r_x_plus_btn = "nul" +input_player12_r_x_plus_mbtn = "nul" +input_player12_r_y_minus = "nul" +input_player12_r_y_minus_axis = "nul" +input_player12_r_y_minus_btn = "nul" +input_player12_r_y_minus_mbtn = "nul" +input_player12_r_y_plus = "nul" +input_player12_r_y_plus_axis = "nul" +input_player12_r_y_plus_btn = "nul" +input_player12_r_y_plus_mbtn = "nul" +input_player12_right = "nul" +input_player12_right_axis = "nul" +input_player12_right_btn = "nul" +input_player12_right_mbtn = "nul" +input_player12_select = "nul" +input_player12_select_axis = "nul" +input_player12_select_btn = "nul" +input_player12_select_mbtn = "nul" +input_player12_start = "nul" +input_player12_start_axis = "nul" +input_player12_start_btn = "nul" +input_player12_start_mbtn = "nul" +input_player12_turbo = "nul" +input_player12_turbo_axis = "nul" +input_player12_turbo_btn = "nul" +input_player12_turbo_mbtn = "nul" +input_player12_up = "nul" +input_player12_up_axis = "nul" +input_player12_up_btn = "nul" +input_player12_up_mbtn = "nul" +input_player12_x = "nul" +input_player12_x_axis = "nul" +input_player12_x_btn = "nul" +input_player12_x_mbtn = "nul" +input_player12_y = "nul" +input_player12_y_axis = "nul" +input_player12_y_btn = "nul" +input_player12_y_mbtn = "nul" +input_player13_a = "nul" +input_player13_a_axis = "nul" +input_player13_a_btn = "nul" +input_player13_a_mbtn = "nul" +input_player13_analog_dpad_mode = "0" +input_player13_b = "nul" +input_player13_b_axis = "nul" +input_player13_b_btn = "nul" +input_player13_b_mbtn = "nul" +input_player13_down = "nul" +input_player13_down_axis = "nul" +input_player13_down_btn = "nul" +input_player13_down_mbtn = "nul" +input_player13_gun_aux_a = "nul" +input_player13_gun_aux_a_axis = "nul" +input_player13_gun_aux_a_btn = "nul" +input_player13_gun_aux_a_mbtn = "nul" +input_player13_gun_aux_b = "nul" +input_player13_gun_aux_b_axis = "nul" +input_player13_gun_aux_b_btn = "nul" +input_player13_gun_aux_b_mbtn = "nul" +input_player13_gun_aux_c = "nul" +input_player13_gun_aux_c_axis = "nul" +input_player13_gun_aux_c_btn = "nul" +input_player13_gun_aux_c_mbtn = "nul" +input_player13_gun_dpad_down = "nul" +input_player13_gun_dpad_down_axis = "nul" +input_player13_gun_dpad_down_btn = "nul" +input_player13_gun_dpad_down_mbtn = "nul" +input_player13_gun_dpad_left = "nul" +input_player13_gun_dpad_left_axis = "nul" +input_player13_gun_dpad_left_btn = "nul" +input_player13_gun_dpad_left_mbtn = "nul" +input_player13_gun_dpad_right = "nul" +input_player13_gun_dpad_right_axis = "nul" +input_player13_gun_dpad_right_btn = "nul" +input_player13_gun_dpad_right_mbtn = "nul" +input_player13_gun_dpad_up = "nul" +input_player13_gun_dpad_up_axis = "nul" +input_player13_gun_dpad_up_btn = "nul" +input_player13_gun_dpad_up_mbtn = "nul" +input_player13_gun_offscreen_shot = "nul" +input_player13_gun_offscreen_shot_axis = "nul" +input_player13_gun_offscreen_shot_btn = "nul" +input_player13_gun_offscreen_shot_mbtn = "nul" +input_player13_gun_select = "nul" +input_player13_gun_select_axis = "nul" +input_player13_gun_select_btn = "nul" +input_player13_gun_select_mbtn = "nul" +input_player13_gun_start = "nul" +input_player13_gun_start_axis = "nul" +input_player13_gun_start_btn = "nul" +input_player13_gun_start_mbtn = "nul" +input_player13_gun_trigger = "nul" +input_player13_gun_trigger_axis = "nul" +input_player13_gun_trigger_btn = "nul" +input_player13_gun_trigger_mbtn = "1" +input_player13_joypad_index = "12" +input_player13_l = "nul" +input_player13_l2 = "nul" +input_player13_l2_axis = "nul" +input_player13_l2_btn = "nul" +input_player13_l2_mbtn = "nul" +input_player13_l3 = "nul" +input_player13_l3_axis = "nul" +input_player13_l3_btn = "nul" +input_player13_l3_mbtn = "nul" +input_player13_l_axis = "nul" +input_player13_l_btn = "nul" +input_player13_l_mbtn = "nul" +input_player13_l_x_minus = "nul" +input_player13_l_x_minus_axis = "nul" +input_player13_l_x_minus_btn = "nul" +input_player13_l_x_minus_mbtn = "nul" +input_player13_l_x_plus = "nul" +input_player13_l_x_plus_axis = "nul" +input_player13_l_x_plus_btn = "nul" +input_player13_l_x_plus_mbtn = "nul" +input_player13_l_y_minus = "nul" +input_player13_l_y_minus_axis = "nul" +input_player13_l_y_minus_btn = "nul" +input_player13_l_y_minus_mbtn = "nul" +input_player13_l_y_plus = "nul" +input_player13_l_y_plus_axis = "nul" +input_player13_l_y_plus_btn = "nul" +input_player13_l_y_plus_mbtn = "nul" +input_player13_left = "nul" +input_player13_left_axis = "nul" +input_player13_left_btn = "nul" +input_player13_left_mbtn = "nul" +input_player13_mouse_index = "12" +input_player13_r = "nul" +input_player13_r2 = "nul" +input_player13_r2_axis = "nul" +input_player13_r2_btn = "nul" +input_player13_r2_mbtn = "nul" +input_player13_r3 = "nul" +input_player13_r3_axis = "nul" +input_player13_r3_btn = "nul" +input_player13_r3_mbtn = "nul" +input_player13_r_axis = "nul" +input_player13_r_btn = "nul" +input_player13_r_mbtn = "nul" +input_player13_r_x_minus = "nul" +input_player13_r_x_minus_axis = "nul" +input_player13_r_x_minus_btn = "nul" +input_player13_r_x_minus_mbtn = "nul" +input_player13_r_x_plus = "nul" +input_player13_r_x_plus_axis = "nul" +input_player13_r_x_plus_btn = "nul" +input_player13_r_x_plus_mbtn = "nul" +input_player13_r_y_minus = "nul" +input_player13_r_y_minus_axis = "nul" +input_player13_r_y_minus_btn = "nul" +input_player13_r_y_minus_mbtn = "nul" +input_player13_r_y_plus = "nul" +input_player13_r_y_plus_axis = "nul" +input_player13_r_y_plus_btn = "nul" +input_player13_r_y_plus_mbtn = "nul" +input_player13_right = "nul" +input_player13_right_axis = "nul" +input_player13_right_btn = "nul" +input_player13_right_mbtn = "nul" +input_player13_select = "nul" +input_player13_select_axis = "nul" +input_player13_select_btn = "nul" +input_player13_select_mbtn = "nul" +input_player13_start = "nul" +input_player13_start_axis = "nul" +input_player13_start_btn = "nul" +input_player13_start_mbtn = "nul" +input_player13_turbo = "nul" +input_player13_turbo_axis = "nul" +input_player13_turbo_btn = "nul" +input_player13_turbo_mbtn = "nul" +input_player13_up = "nul" +input_player13_up_axis = "nul" +input_player13_up_btn = "nul" +input_player13_up_mbtn = "nul" +input_player13_x = "nul" +input_player13_x_axis = "nul" +input_player13_x_btn = "nul" +input_player13_x_mbtn = "nul" +input_player13_y = "nul" +input_player13_y_axis = "nul" +input_player13_y_btn = "nul" +input_player13_y_mbtn = "nul" +input_player14_a = "nul" +input_player14_a_axis = "nul" +input_player14_a_btn = "nul" +input_player14_a_mbtn = "nul" +input_player14_analog_dpad_mode = "0" +input_player14_b = "nul" +input_player14_b_axis = "nul" +input_player14_b_btn = "nul" +input_player14_b_mbtn = "nul" +input_player14_down = "nul" +input_player14_down_axis = "nul" +input_player14_down_btn = "nul" +input_player14_down_mbtn = "nul" +input_player14_gun_aux_a = "nul" +input_player14_gun_aux_a_axis = "nul" +input_player14_gun_aux_a_btn = "nul" +input_player14_gun_aux_a_mbtn = "nul" +input_player14_gun_aux_b = "nul" +input_player14_gun_aux_b_axis = "nul" +input_player14_gun_aux_b_btn = "nul" +input_player14_gun_aux_b_mbtn = "nul" +input_player14_gun_aux_c = "nul" +input_player14_gun_aux_c_axis = "nul" +input_player14_gun_aux_c_btn = "nul" +input_player14_gun_aux_c_mbtn = "nul" +input_player14_gun_dpad_down = "nul" +input_player14_gun_dpad_down_axis = "nul" +input_player14_gun_dpad_down_btn = "nul" +input_player14_gun_dpad_down_mbtn = "nul" +input_player14_gun_dpad_left = "nul" +input_player14_gun_dpad_left_axis = "nul" +input_player14_gun_dpad_left_btn = "nul" +input_player14_gun_dpad_left_mbtn = "nul" +input_player14_gun_dpad_right = "nul" +input_player14_gun_dpad_right_axis = "nul" +input_player14_gun_dpad_right_btn = "nul" +input_player14_gun_dpad_right_mbtn = "nul" +input_player14_gun_dpad_up = "nul" +input_player14_gun_dpad_up_axis = "nul" +input_player14_gun_dpad_up_btn = "nul" +input_player14_gun_dpad_up_mbtn = "nul" +input_player14_gun_offscreen_shot = "nul" +input_player14_gun_offscreen_shot_axis = "nul" +input_player14_gun_offscreen_shot_btn = "nul" +input_player14_gun_offscreen_shot_mbtn = "nul" +input_player14_gun_select = "nul" +input_player14_gun_select_axis = "nul" +input_player14_gun_select_btn = "nul" +input_player14_gun_select_mbtn = "nul" +input_player14_gun_start = "nul" +input_player14_gun_start_axis = "nul" +input_player14_gun_start_btn = "nul" +input_player14_gun_start_mbtn = "nul" +input_player14_gun_trigger = "nul" +input_player14_gun_trigger_axis = "nul" +input_player14_gun_trigger_btn = "nul" +input_player14_gun_trigger_mbtn = "1" +input_player14_joypad_index = "13" +input_player14_l = "nul" +input_player14_l2 = "nul" +input_player14_l2_axis = "nul" +input_player14_l2_btn = "nul" +input_player14_l2_mbtn = "nul" +input_player14_l3 = "nul" +input_player14_l3_axis = "nul" +input_player14_l3_btn = "nul" +input_player14_l3_mbtn = "nul" +input_player14_l_axis = "nul" +input_player14_l_btn = "nul" +input_player14_l_mbtn = "nul" +input_player14_l_x_minus = "nul" +input_player14_l_x_minus_axis = "nul" +input_player14_l_x_minus_btn = "nul" +input_player14_l_x_minus_mbtn = "nul" +input_player14_l_x_plus = "nul" +input_player14_l_x_plus_axis = "nul" +input_player14_l_x_plus_btn = "nul" +input_player14_l_x_plus_mbtn = "nul" +input_player14_l_y_minus = "nul" +input_player14_l_y_minus_axis = "nul" +input_player14_l_y_minus_btn = "nul" +input_player14_l_y_minus_mbtn = "nul" +input_player14_l_y_plus = "nul" +input_player14_l_y_plus_axis = "nul" +input_player14_l_y_plus_btn = "nul" +input_player14_l_y_plus_mbtn = "nul" +input_player14_left = "nul" +input_player14_left_axis = "nul" +input_player14_left_btn = "nul" +input_player14_left_mbtn = "nul" +input_player14_mouse_index = "13" +input_player14_r = "nul" +input_player14_r2 = "nul" +input_player14_r2_axis = "nul" +input_player14_r2_btn = "nul" +input_player14_r2_mbtn = "nul" +input_player14_r3 = "nul" +input_player14_r3_axis = "nul" +input_player14_r3_btn = "nul" +input_player14_r3_mbtn = "nul" +input_player14_r_axis = "nul" +input_player14_r_btn = "nul" +input_player14_r_mbtn = "nul" +input_player14_r_x_minus = "nul" +input_player14_r_x_minus_axis = "nul" +input_player14_r_x_minus_btn = "nul" +input_player14_r_x_minus_mbtn = "nul" +input_player14_r_x_plus = "nul" +input_player14_r_x_plus_axis = "nul" +input_player14_r_x_plus_btn = "nul" +input_player14_r_x_plus_mbtn = "nul" +input_player14_r_y_minus = "nul" +input_player14_r_y_minus_axis = "nul" +input_player14_r_y_minus_btn = "nul" +input_player14_r_y_minus_mbtn = "nul" +input_player14_r_y_plus = "nul" +input_player14_r_y_plus_axis = "nul" +input_player14_r_y_plus_btn = "nul" +input_player14_r_y_plus_mbtn = "nul" +input_player14_right = "nul" +input_player14_right_axis = "nul" +input_player14_right_btn = "nul" +input_player14_right_mbtn = "nul" +input_player14_select = "nul" +input_player14_select_axis = "nul" +input_player14_select_btn = "nul" +input_player14_select_mbtn = "nul" +input_player14_start = "nul" +input_player14_start_axis = "nul" +input_player14_start_btn = "nul" +input_player14_start_mbtn = "nul" +input_player14_turbo = "nul" +input_player14_turbo_axis = "nul" +input_player14_turbo_btn = "nul" +input_player14_turbo_mbtn = "nul" +input_player14_up = "nul" +input_player14_up_axis = "nul" +input_player14_up_btn = "nul" +input_player14_up_mbtn = "nul" +input_player14_x = "nul" +input_player14_x_axis = "nul" +input_player14_x_btn = "nul" +input_player14_x_mbtn = "nul" +input_player14_y = "nul" +input_player14_y_axis = "nul" +input_player14_y_btn = "nul" +input_player14_y_mbtn = "nul" +input_player15_a = "nul" +input_player15_a_axis = "nul" +input_player15_a_btn = "nul" +input_player15_a_mbtn = "nul" +input_player15_analog_dpad_mode = "0" +input_player15_b = "nul" +input_player15_b_axis = "nul" +input_player15_b_btn = "nul" +input_player15_b_mbtn = "nul" +input_player15_down = "nul" +input_player15_down_axis = "nul" +input_player15_down_btn = "nul" +input_player15_down_mbtn = "nul" +input_player15_gun_aux_a = "nul" +input_player15_gun_aux_a_axis = "nul" +input_player15_gun_aux_a_btn = "nul" +input_player15_gun_aux_a_mbtn = "nul" +input_player15_gun_aux_b = "nul" +input_player15_gun_aux_b_axis = "nul" +input_player15_gun_aux_b_btn = "nul" +input_player15_gun_aux_b_mbtn = "nul" +input_player15_gun_aux_c = "nul" +input_player15_gun_aux_c_axis = "nul" +input_player15_gun_aux_c_btn = "nul" +input_player15_gun_aux_c_mbtn = "nul" +input_player15_gun_dpad_down = "nul" +input_player15_gun_dpad_down_axis = "nul" +input_player15_gun_dpad_down_btn = "nul" +input_player15_gun_dpad_down_mbtn = "nul" +input_player15_gun_dpad_left = "nul" +input_player15_gun_dpad_left_axis = "nul" +input_player15_gun_dpad_left_btn = "nul" +input_player15_gun_dpad_left_mbtn = "nul" +input_player15_gun_dpad_right = "nul" +input_player15_gun_dpad_right_axis = "nul" +input_player15_gun_dpad_right_btn = "nul" +input_player15_gun_dpad_right_mbtn = "nul" +input_player15_gun_dpad_up = "nul" +input_player15_gun_dpad_up_axis = "nul" +input_player15_gun_dpad_up_btn = "nul" +input_player15_gun_dpad_up_mbtn = "nul" +input_player15_gun_offscreen_shot = "nul" +input_player15_gun_offscreen_shot_axis = "nul" +input_player15_gun_offscreen_shot_btn = "nul" +input_player15_gun_offscreen_shot_mbtn = "nul" +input_player15_gun_select = "nul" +input_player15_gun_select_axis = "nul" +input_player15_gun_select_btn = "nul" +input_player15_gun_select_mbtn = "nul" +input_player15_gun_start = "nul" +input_player15_gun_start_axis = "nul" +input_player15_gun_start_btn = "nul" +input_player15_gun_start_mbtn = "nul" +input_player15_gun_trigger = "nul" +input_player15_gun_trigger_axis = "nul" +input_player15_gun_trigger_btn = "nul" +input_player15_gun_trigger_mbtn = "1" +input_player15_joypad_index = "14" +input_player15_l = "nul" +input_player15_l2 = "nul" +input_player15_l2_axis = "nul" +input_player15_l2_btn = "nul" +input_player15_l2_mbtn = "nul" +input_player15_l3 = "nul" +input_player15_l3_axis = "nul" +input_player15_l3_btn = "nul" +input_player15_l3_mbtn = "nul" +input_player15_l_axis = "nul" +input_player15_l_btn = "nul" +input_player15_l_mbtn = "nul" +input_player15_l_x_minus = "nul" +input_player15_l_x_minus_axis = "nul" +input_player15_l_x_minus_btn = "nul" +input_player15_l_x_minus_mbtn = "nul" +input_player15_l_x_plus = "nul" +input_player15_l_x_plus_axis = "nul" +input_player15_l_x_plus_btn = "nul" +input_player15_l_x_plus_mbtn = "nul" +input_player15_l_y_minus = "nul" +input_player15_l_y_minus_axis = "nul" +input_player15_l_y_minus_btn = "nul" +input_player15_l_y_minus_mbtn = "nul" +input_player15_l_y_plus = "nul" +input_player15_l_y_plus_axis = "nul" +input_player15_l_y_plus_btn = "nul" +input_player15_l_y_plus_mbtn = "nul" +input_player15_left = "nul" +input_player15_left_axis = "nul" +input_player15_left_btn = "nul" +input_player15_left_mbtn = "nul" +input_player15_mouse_index = "14" +input_player15_r = "nul" +input_player15_r2 = "nul" +input_player15_r2_axis = "nul" +input_player15_r2_btn = "nul" +input_player15_r2_mbtn = "nul" +input_player15_r3 = "nul" +input_player15_r3_axis = "nul" +input_player15_r3_btn = "nul" +input_player15_r3_mbtn = "nul" +input_player15_r_axis = "nul" +input_player15_r_btn = "nul" +input_player15_r_mbtn = "nul" +input_player15_r_x_minus = "nul" +input_player15_r_x_minus_axis = "nul" +input_player15_r_x_minus_btn = "nul" +input_player15_r_x_minus_mbtn = "nul" +input_player15_r_x_plus = "nul" +input_player15_r_x_plus_axis = "nul" +input_player15_r_x_plus_btn = "nul" +input_player15_r_x_plus_mbtn = "nul" +input_player15_r_y_minus = "nul" +input_player15_r_y_minus_axis = "nul" +input_player15_r_y_minus_btn = "nul" +input_player15_r_y_minus_mbtn = "nul" +input_player15_r_y_plus = "nul" +input_player15_r_y_plus_axis = "nul" +input_player15_r_y_plus_btn = "nul" +input_player15_r_y_plus_mbtn = "nul" +input_player15_right = "nul" +input_player15_right_axis = "nul" +input_player15_right_btn = "nul" +input_player15_right_mbtn = "nul" +input_player15_select = "nul" +input_player15_select_axis = "nul" +input_player15_select_btn = "nul" +input_player15_select_mbtn = "nul" +input_player15_start = "nul" +input_player15_start_axis = "nul" +input_player15_start_btn = "nul" +input_player15_start_mbtn = "nul" +input_player15_turbo = "nul" +input_player15_turbo_axis = "nul" +input_player15_turbo_btn = "nul" +input_player15_turbo_mbtn = "nul" +input_player15_up = "nul" +input_player15_up_axis = "nul" +input_player15_up_btn = "nul" +input_player15_up_mbtn = "nul" +input_player15_x = "nul" +input_player15_x_axis = "nul" +input_player15_x_btn = "nul" +input_player15_x_mbtn = "nul" +input_player15_y = "nul" +input_player15_y_axis = "nul" +input_player15_y_btn = "nul" +input_player15_y_mbtn = "nul" +input_player16_a = "nul" +input_player16_a_axis = "nul" +input_player16_a_btn = "nul" +input_player16_a_mbtn = "nul" +input_player16_analog_dpad_mode = "0" +input_player16_b = "nul" +input_player16_b_axis = "nul" +input_player16_b_btn = "nul" +input_player16_b_mbtn = "nul" +input_player16_down = "nul" +input_player16_down_axis = "nul" +input_player16_down_btn = "nul" +input_player16_down_mbtn = "nul" +input_player16_gun_aux_a = "nul" +input_player16_gun_aux_a_axis = "nul" +input_player16_gun_aux_a_btn = "nul" +input_player16_gun_aux_a_mbtn = "nul" +input_player16_gun_aux_b = "nul" +input_player16_gun_aux_b_axis = "nul" +input_player16_gun_aux_b_btn = "nul" +input_player16_gun_aux_b_mbtn = "nul" +input_player16_gun_aux_c = "nul" +input_player16_gun_aux_c_axis = "nul" +input_player16_gun_aux_c_btn = "nul" +input_player16_gun_aux_c_mbtn = "nul" +input_player16_gun_dpad_down = "nul" +input_player16_gun_dpad_down_axis = "nul" +input_player16_gun_dpad_down_btn = "nul" +input_player16_gun_dpad_down_mbtn = "nul" +input_player16_gun_dpad_left = "nul" +input_player16_gun_dpad_left_axis = "nul" +input_player16_gun_dpad_left_btn = "nul" +input_player16_gun_dpad_left_mbtn = "nul" +input_player16_gun_dpad_right = "nul" +input_player16_gun_dpad_right_axis = "nul" +input_player16_gun_dpad_right_btn = "nul" +input_player16_gun_dpad_right_mbtn = "nul" +input_player16_gun_dpad_up = "nul" +input_player16_gun_dpad_up_axis = "nul" +input_player16_gun_dpad_up_btn = "nul" +input_player16_gun_dpad_up_mbtn = "nul" +input_player16_gun_offscreen_shot = "nul" +input_player16_gun_offscreen_shot_axis = "nul" +input_player16_gun_offscreen_shot_btn = "nul" +input_player16_gun_offscreen_shot_mbtn = "nul" +input_player16_gun_select = "nul" +input_player16_gun_select_axis = "nul" +input_player16_gun_select_btn = "nul" +input_player16_gun_select_mbtn = "nul" +input_player16_gun_start = "nul" +input_player16_gun_start_axis = "nul" +input_player16_gun_start_btn = "nul" +input_player16_gun_start_mbtn = "nul" +input_player16_gun_trigger = "nul" +input_player16_gun_trigger_axis = "nul" +input_player16_gun_trigger_btn = "nul" +input_player16_gun_trigger_mbtn = "1" +input_player16_joypad_index = "15" +input_player16_l = "nul" +input_player16_l2 = "nul" +input_player16_l2_axis = "nul" +input_player16_l2_btn = "nul" +input_player16_l2_mbtn = "nul" +input_player16_l3 = "nul" +input_player16_l3_axis = "nul" +input_player16_l3_btn = "nul" +input_player16_l3_mbtn = "nul" +input_player16_l_axis = "nul" +input_player16_l_btn = "nul" +input_player16_l_mbtn = "nul" +input_player16_l_x_minus = "nul" +input_player16_l_x_minus_axis = "nul" +input_player16_l_x_minus_btn = "nul" +input_player16_l_x_minus_mbtn = "nul" +input_player16_l_x_plus = "nul" +input_player16_l_x_plus_axis = "nul" +input_player16_l_x_plus_btn = "nul" +input_player16_l_x_plus_mbtn = "nul" +input_player16_l_y_minus = "nul" +input_player16_l_y_minus_axis = "nul" +input_player16_l_y_minus_btn = "nul" +input_player16_l_y_minus_mbtn = "nul" +input_player16_l_y_plus = "nul" +input_player16_l_y_plus_axis = "nul" +input_player16_l_y_plus_btn = "nul" +input_player16_l_y_plus_mbtn = "nul" +input_player16_left = "nul" +input_player16_left_axis = "nul" +input_player16_left_btn = "nul" +input_player16_left_mbtn = "nul" +input_player16_mouse_index = "15" +input_player16_r = "nul" +input_player16_r2 = "nul" +input_player16_r2_axis = "nul" +input_player16_r2_btn = "nul" +input_player16_r2_mbtn = "nul" +input_player16_r3 = "nul" +input_player16_r3_axis = "nul" +input_player16_r3_btn = "nul" +input_player16_r3_mbtn = "nul" +input_player16_r_axis = "nul" +input_player16_r_btn = "nul" +input_player16_r_mbtn = "nul" +input_player16_r_x_minus = "nul" +input_player16_r_x_minus_axis = "nul" +input_player16_r_x_minus_btn = "nul" +input_player16_r_x_minus_mbtn = "nul" +input_player16_r_x_plus = "nul" +input_player16_r_x_plus_axis = "nul" +input_player16_r_x_plus_btn = "nul" +input_player16_r_x_plus_mbtn = "nul" +input_player16_r_y_minus = "nul" +input_player16_r_y_minus_axis = "nul" +input_player16_r_y_minus_btn = "nul" +input_player16_r_y_minus_mbtn = "nul" +input_player16_r_y_plus = "nul" +input_player16_r_y_plus_axis = "nul" +input_player16_r_y_plus_btn = "nul" +input_player16_r_y_plus_mbtn = "nul" +input_player16_right = "nul" +input_player16_right_axis = "nul" +input_player16_right_btn = "nul" +input_player16_right_mbtn = "nul" +input_player16_select = "nul" +input_player16_select_axis = "nul" +input_player16_select_btn = "nul" +input_player16_select_mbtn = "nul" +input_player16_start = "nul" +input_player16_start_axis = "nul" +input_player16_start_btn = "nul" +input_player16_start_mbtn = "nul" +input_player16_turbo = "nul" +input_player16_turbo_axis = "nul" +input_player16_turbo_btn = "nul" +input_player16_turbo_mbtn = "nul" +input_player16_up = "nul" +input_player16_up_axis = "nul" +input_player16_up_btn = "nul" +input_player16_up_mbtn = "nul" +input_player16_x = "nul" +input_player16_x_axis = "nul" +input_player16_x_btn = "nul" +input_player16_x_mbtn = "nul" +input_player16_y = "nul" +input_player16_y_axis = "nul" +input_player16_y_btn = "nul" +input_player16_y_mbtn = "nul" +input_player1_a = "x" +input_player1_a_axis = "nul" +input_player1_a_btn = "nul" +input_player1_a_mbtn = "nul" +input_player1_analog_dpad_mode = "0" +input_player1_b = "z" +input_player1_b_axis = "nul" +input_player1_b_btn = "nul" +input_player1_b_mbtn = "nul" +input_player1_down = "down" +input_player1_down_axis = "nul" +input_player1_down_btn = "nul" +input_player1_down_mbtn = "nul" +input_player1_gun_aux_a = "nul" +input_player1_gun_aux_a_axis = "nul" +input_player1_gun_aux_a_btn = "nul" +input_player1_gun_aux_a_mbtn = "nul" +input_player1_gun_aux_b = "nul" +input_player1_gun_aux_b_axis = "nul" +input_player1_gun_aux_b_btn = "nul" +input_player1_gun_aux_b_mbtn = "nul" +input_player1_gun_aux_c = "nul" +input_player1_gun_aux_c_axis = "nul" +input_player1_gun_aux_c_btn = "nul" +input_player1_gun_aux_c_mbtn = "nul" +input_player1_gun_dpad_down = "nul" +input_player1_gun_dpad_down_axis = "nul" +input_player1_gun_dpad_down_btn = "nul" +input_player1_gun_dpad_down_mbtn = "nul" +input_player1_gun_dpad_left = "nul" +input_player1_gun_dpad_left_axis = "nul" +input_player1_gun_dpad_left_btn = "nul" +input_player1_gun_dpad_left_mbtn = "nul" +input_player1_gun_dpad_right = "nul" +input_player1_gun_dpad_right_axis = "nul" +input_player1_gun_dpad_right_btn = "nul" +input_player1_gun_dpad_right_mbtn = "nul" +input_player1_gun_dpad_up = "nul" +input_player1_gun_dpad_up_axis = "nul" +input_player1_gun_dpad_up_btn = "nul" +input_player1_gun_dpad_up_mbtn = "nul" +input_player1_gun_offscreen_shot = "nul" +input_player1_gun_offscreen_shot_axis = "nul" +input_player1_gun_offscreen_shot_btn = "nul" +input_player1_gun_offscreen_shot_mbtn = "nul" +input_player1_gun_select = "nul" +input_player1_gun_select_axis = "nul" +input_player1_gun_select_btn = "nul" +input_player1_gun_select_mbtn = "nul" +input_player1_gun_start = "nul" +input_player1_gun_start_axis = "nul" +input_player1_gun_start_btn = "nul" +input_player1_gun_start_mbtn = "nul" +input_player1_gun_trigger = "nul" +input_player1_gun_trigger_axis = "nul" +input_player1_gun_trigger_btn = "nul" +input_player1_gun_trigger_mbtn = "1" +input_player1_joypad_index = "0" +input_player1_l = "q" +input_player1_l2 = "nul" +input_player1_l2_axis = "nul" +input_player1_l2_btn = "nul" +input_player1_l2_mbtn = "nul" +input_player1_l3 = "nul" +input_player1_l3_axis = "nul" +input_player1_l3_btn = "nul" +input_player1_l3_mbtn = "nul" +input_player1_l_axis = "nul" +input_player1_l_btn = "nul" +input_player1_l_mbtn = "nul" +input_player1_l_x_minus = "nul" +input_player1_l_x_minus_axis = "nul" +input_player1_l_x_minus_btn = "nul" +input_player1_l_x_minus_mbtn = "nul" +input_player1_l_x_plus = "nul" +input_player1_l_x_plus_axis = "nul" +input_player1_l_x_plus_btn = "nul" +input_player1_l_x_plus_mbtn = "nul" +input_player1_l_y_minus = "nul" +input_player1_l_y_minus_axis = "nul" +input_player1_l_y_minus_btn = "nul" +input_player1_l_y_minus_mbtn = "nul" +input_player1_l_y_plus = "nul" +input_player1_l_y_plus_axis = "nul" +input_player1_l_y_plus_btn = "nul" +input_player1_l_y_plus_mbtn = "nul" +input_player1_left = "left" +input_player1_left_axis = "nul" +input_player1_left_btn = "nul" +input_player1_left_mbtn = "nul" +input_player1_mouse_index = "0" +input_player1_r = "w" +input_player1_r2 = "nul" +input_player1_r2_axis = "nul" +input_player1_r2_btn = "nul" +input_player1_r2_mbtn = "nul" +input_player1_r3 = "nul" +input_player1_r3_axis = "nul" +input_player1_r3_btn = "nul" +input_player1_r3_mbtn = "nul" +input_player1_r_axis = "nul" +input_player1_r_btn = "nul" +input_player1_r_mbtn = "nul" +input_player1_r_x_minus = "nul" +input_player1_r_x_minus_axis = "nul" +input_player1_r_x_minus_btn = "nul" +input_player1_r_x_minus_mbtn = "nul" +input_player1_r_x_plus = "nul" +input_player1_r_x_plus_axis = "nul" +input_player1_r_x_plus_btn = "nul" +input_player1_r_x_plus_mbtn = "nul" +input_player1_r_y_minus = "nul" +input_player1_r_y_minus_axis = "nul" +input_player1_r_y_minus_btn = "nul" +input_player1_r_y_minus_mbtn = "nul" +input_player1_r_y_plus = "nul" +input_player1_r_y_plus_axis = "nul" +input_player1_r_y_plus_btn = "nul" +input_player1_r_y_plus_mbtn = "nul" +input_player1_right = "right" +input_player1_right_axis = "nul" +input_player1_right_btn = "nul" +input_player1_right_mbtn = "nul" +input_player1_select = "rshift" +input_player1_select_axis = "nul" +input_player1_select_btn = "nul" +input_player1_select_mbtn = "nul" +input_player1_start = "enter" +input_player1_start_axis = "nul" +input_player1_start_btn = "nul" +input_player1_start_mbtn = "nul" +input_player1_turbo = "nul" +input_player1_turbo_axis = "nul" +input_player1_turbo_btn = "nul" +input_player1_turbo_mbtn = "nul" +input_player1_up = "up" +input_player1_up_axis = "nul" +input_player1_up_btn = "nul" +input_player1_up_mbtn = "nul" +input_player1_x = "s" +input_player1_x_axis = "nul" +input_player1_x_btn = "nul" +input_player1_x_mbtn = "nul" +input_player1_y = "a" +input_player1_y_axis = "nul" +input_player1_y_btn = "nul" +input_player1_y_mbtn = "nul" +input_player2_a = "nul" +input_player2_a_axis = "nul" +input_player2_a_btn = "nul" +input_player2_a_mbtn = "nul" +input_player2_analog_dpad_mode = "0" +input_player2_b = "nul" +input_player2_b_axis = "nul" +input_player2_b_btn = "nul" +input_player2_b_mbtn = "nul" +input_player2_down = "nul" +input_player2_down_axis = "nul" +input_player2_down_btn = "nul" +input_player2_down_mbtn = "nul" +input_player2_gun_aux_a = "nul" +input_player2_gun_aux_a_axis = "nul" +input_player2_gun_aux_a_btn = "nul" +input_player2_gun_aux_a_mbtn = "nul" +input_player2_gun_aux_b = "nul" +input_player2_gun_aux_b_axis = "nul" +input_player2_gun_aux_b_btn = "nul" +input_player2_gun_aux_b_mbtn = "nul" +input_player2_gun_aux_c = "nul" +input_player2_gun_aux_c_axis = "nul" +input_player2_gun_aux_c_btn = "nul" +input_player2_gun_aux_c_mbtn = "nul" +input_player2_gun_dpad_down = "nul" +input_player2_gun_dpad_down_axis = "nul" +input_player2_gun_dpad_down_btn = "nul" +input_player2_gun_dpad_down_mbtn = "nul" +input_player2_gun_dpad_left = "nul" +input_player2_gun_dpad_left_axis = "nul" +input_player2_gun_dpad_left_btn = "nul" +input_player2_gun_dpad_left_mbtn = "nul" +input_player2_gun_dpad_right = "nul" +input_player2_gun_dpad_right_axis = "nul" +input_player2_gun_dpad_right_btn = "nul" +input_player2_gun_dpad_right_mbtn = "nul" +input_player2_gun_dpad_up = "nul" +input_player2_gun_dpad_up_axis = "nul" +input_player2_gun_dpad_up_btn = "nul" +input_player2_gun_dpad_up_mbtn = "nul" +input_player2_gun_offscreen_shot = "nul" +input_player2_gun_offscreen_shot_axis = "nul" +input_player2_gun_offscreen_shot_btn = "nul" +input_player2_gun_offscreen_shot_mbtn = "nul" +input_player2_gun_select = "nul" +input_player2_gun_select_axis = "nul" +input_player2_gun_select_btn = "nul" +input_player2_gun_select_mbtn = "nul" +input_player2_gun_start = "nul" +input_player2_gun_start_axis = "nul" +input_player2_gun_start_btn = "nul" +input_player2_gun_start_mbtn = "nul" +input_player2_gun_trigger = "nul" +input_player2_gun_trigger_axis = "nul" +input_player2_gun_trigger_btn = "nul" +input_player2_gun_trigger_mbtn = "1" +input_player2_joypad_index = "1" +input_player2_l = "nul" +input_player2_l2 = "nul" +input_player2_l2_axis = "nul" +input_player2_l2_btn = "nul" +input_player2_l2_mbtn = "nul" +input_player2_l3 = "nul" +input_player2_l3_axis = "nul" +input_player2_l3_btn = "nul" +input_player2_l3_mbtn = "nul" +input_player2_l_axis = "nul" +input_player2_l_btn = "nul" +input_player2_l_mbtn = "nul" +input_player2_l_x_minus = "nul" +input_player2_l_x_minus_axis = "nul" +input_player2_l_x_minus_btn = "nul" +input_player2_l_x_minus_mbtn = "nul" +input_player2_l_x_plus = "nul" +input_player2_l_x_plus_axis = "nul" +input_player2_l_x_plus_btn = "nul" +input_player2_l_x_plus_mbtn = "nul" +input_player2_l_y_minus = "nul" +input_player2_l_y_minus_axis = "nul" +input_player2_l_y_minus_btn = "nul" +input_player2_l_y_minus_mbtn = "nul" +input_player2_l_y_plus = "nul" +input_player2_l_y_plus_axis = "nul" +input_player2_l_y_plus_btn = "nul" +input_player2_l_y_plus_mbtn = "nul" +input_player2_left = "nul" +input_player2_left_axis = "nul" +input_player2_left_btn = "nul" +input_player2_left_mbtn = "nul" +input_player2_mouse_index = "1" +input_player2_r = "nul" +input_player2_r2 = "nul" +input_player2_r2_axis = "nul" +input_player2_r2_btn = "nul" +input_player2_r2_mbtn = "nul" +input_player2_r3 = "nul" +input_player2_r3_axis = "nul" +input_player2_r3_btn = "nul" +input_player2_r3_mbtn = "nul" +input_player2_r_axis = "nul" +input_player2_r_btn = "nul" +input_player2_r_mbtn = "nul" +input_player2_r_x_minus = "nul" +input_player2_r_x_minus_axis = "nul" +input_player2_r_x_minus_btn = "nul" +input_player2_r_x_minus_mbtn = "nul" +input_player2_r_x_plus = "nul" +input_player2_r_x_plus_axis = "nul" +input_player2_r_x_plus_btn = "nul" +input_player2_r_x_plus_mbtn = "nul" +input_player2_r_y_minus = "nul" +input_player2_r_y_minus_axis = "nul" +input_player2_r_y_minus_btn = "nul" +input_player2_r_y_minus_mbtn = "nul" +input_player2_r_y_plus = "nul" +input_player2_r_y_plus_axis = "nul" +input_player2_r_y_plus_btn = "nul" +input_player2_r_y_plus_mbtn = "nul" +input_player2_right = "nul" +input_player2_right_axis = "nul" +input_player2_right_btn = "nul" +input_player2_right_mbtn = "nul" +input_player2_select = "nul" +input_player2_select_axis = "nul" +input_player2_select_btn = "nul" +input_player2_select_mbtn = "nul" +input_player2_start = "nul" +input_player2_start_axis = "nul" +input_player2_start_btn = "nul" +input_player2_start_mbtn = "nul" +input_player2_turbo = "nul" +input_player2_turbo_axis = "nul" +input_player2_turbo_btn = "nul" +input_player2_turbo_mbtn = "nul" +input_player2_up = "nul" +input_player2_up_axis = "nul" +input_player2_up_btn = "nul" +input_player2_up_mbtn = "nul" +input_player2_x = "nul" +input_player2_x_axis = "nul" +input_player2_x_btn = "nul" +input_player2_x_mbtn = "nul" +input_player2_y = "nul" +input_player2_y_axis = "nul" +input_player2_y_btn = "nul" +input_player2_y_mbtn = "nul" +input_player3_a = "nul" +input_player3_a_axis = "nul" +input_player3_a_btn = "nul" +input_player3_a_mbtn = "nul" +input_player3_analog_dpad_mode = "0" +input_player3_b = "nul" +input_player3_b_axis = "nul" +input_player3_b_btn = "nul" +input_player3_b_mbtn = "nul" +input_player3_down = "nul" +input_player3_down_axis = "nul" +input_player3_down_btn = "nul" +input_player3_down_mbtn = "nul" +input_player3_gun_aux_a = "nul" +input_player3_gun_aux_a_axis = "nul" +input_player3_gun_aux_a_btn = "nul" +input_player3_gun_aux_a_mbtn = "nul" +input_player3_gun_aux_b = "nul" +input_player3_gun_aux_b_axis = "nul" +input_player3_gun_aux_b_btn = "nul" +input_player3_gun_aux_b_mbtn = "nul" +input_player3_gun_aux_c = "nul" +input_player3_gun_aux_c_axis = "nul" +input_player3_gun_aux_c_btn = "nul" +input_player3_gun_aux_c_mbtn = "nul" +input_player3_gun_dpad_down = "nul" +input_player3_gun_dpad_down_axis = "nul" +input_player3_gun_dpad_down_btn = "nul" +input_player3_gun_dpad_down_mbtn = "nul" +input_player3_gun_dpad_left = "nul" +input_player3_gun_dpad_left_axis = "nul" +input_player3_gun_dpad_left_btn = "nul" +input_player3_gun_dpad_left_mbtn = "nul" +input_player3_gun_dpad_right = "nul" +input_player3_gun_dpad_right_axis = "nul" +input_player3_gun_dpad_right_btn = "nul" +input_player3_gun_dpad_right_mbtn = "nul" +input_player3_gun_dpad_up = "nul" +input_player3_gun_dpad_up_axis = "nul" +input_player3_gun_dpad_up_btn = "nul" +input_player3_gun_dpad_up_mbtn = "nul" +input_player3_gun_offscreen_shot = "nul" +input_player3_gun_offscreen_shot_axis = "nul" +input_player3_gun_offscreen_shot_btn = "nul" +input_player3_gun_offscreen_shot_mbtn = "nul" +input_player3_gun_select = "nul" +input_player3_gun_select_axis = "nul" +input_player3_gun_select_btn = "nul" +input_player3_gun_select_mbtn = "nul" +input_player3_gun_start = "nul" +input_player3_gun_start_axis = "nul" +input_player3_gun_start_btn = "nul" +input_player3_gun_start_mbtn = "nul" +input_player3_gun_trigger = "nul" +input_player3_gun_trigger_axis = "nul" +input_player3_gun_trigger_btn = "nul" +input_player3_gun_trigger_mbtn = "1" +input_player3_joypad_index = "2" +input_player3_l = "nul" +input_player3_l2 = "nul" +input_player3_l2_axis = "nul" +input_player3_l2_btn = "nul" +input_player3_l2_mbtn = "nul" +input_player3_l3 = "nul" +input_player3_l3_axis = "nul" +input_player3_l3_btn = "nul" +input_player3_l3_mbtn = "nul" +input_player3_l_axis = "nul" +input_player3_l_btn = "nul" +input_player3_l_mbtn = "nul" +input_player3_l_x_minus = "nul" +input_player3_l_x_minus_axis = "nul" +input_player3_l_x_minus_btn = "nul" +input_player3_l_x_minus_mbtn = "nul" +input_player3_l_x_plus = "nul" +input_player3_l_x_plus_axis = "nul" +input_player3_l_x_plus_btn = "nul" +input_player3_l_x_plus_mbtn = "nul" +input_player3_l_y_minus = "nul" +input_player3_l_y_minus_axis = "nul" +input_player3_l_y_minus_btn = "nul" +input_player3_l_y_minus_mbtn = "nul" +input_player3_l_y_plus = "nul" +input_player3_l_y_plus_axis = "nul" +input_player3_l_y_plus_btn = "nul" +input_player3_l_y_plus_mbtn = "nul" +input_player3_left = "nul" +input_player3_left_axis = "nul" +input_player3_left_btn = "nul" +input_player3_left_mbtn = "nul" +input_player3_mouse_index = "2" +input_player3_r = "nul" +input_player3_r2 = "nul" +input_player3_r2_axis = "nul" +input_player3_r2_btn = "nul" +input_player3_r2_mbtn = "nul" +input_player3_r3 = "nul" +input_player3_r3_axis = "nul" +input_player3_r3_btn = "nul" +input_player3_r3_mbtn = "nul" +input_player3_r_axis = "nul" +input_player3_r_btn = "nul" +input_player3_r_mbtn = "nul" +input_player3_r_x_minus = "nul" +input_player3_r_x_minus_axis = "nul" +input_player3_r_x_minus_btn = "nul" +input_player3_r_x_minus_mbtn = "nul" +input_player3_r_x_plus = "nul" +input_player3_r_x_plus_axis = "nul" +input_player3_r_x_plus_btn = "nul" +input_player3_r_x_plus_mbtn = "nul" +input_player3_r_y_minus = "nul" +input_player3_r_y_minus_axis = "nul" +input_player3_r_y_minus_btn = "nul" +input_player3_r_y_minus_mbtn = "nul" +input_player3_r_y_plus = "nul" +input_player3_r_y_plus_axis = "nul" +input_player3_r_y_plus_btn = "nul" +input_player3_r_y_plus_mbtn = "nul" +input_player3_right = "nul" +input_player3_right_axis = "nul" +input_player3_right_btn = "nul" +input_player3_right_mbtn = "nul" +input_player3_select = "nul" +input_player3_select_axis = "nul" +input_player3_select_btn = "nul" +input_player3_select_mbtn = "nul" +input_player3_start = "nul" +input_player3_start_axis = "nul" +input_player3_start_btn = "nul" +input_player3_start_mbtn = "nul" +input_player3_turbo = "nul" +input_player3_turbo_axis = "nul" +input_player3_turbo_btn = "nul" +input_player3_turbo_mbtn = "nul" +input_player3_up = "nul" +input_player3_up_axis = "nul" +input_player3_up_btn = "nul" +input_player3_up_mbtn = "nul" +input_player3_x = "nul" +input_player3_x_axis = "nul" +input_player3_x_btn = "nul" +input_player3_x_mbtn = "nul" +input_player3_y = "nul" +input_player3_y_axis = "nul" +input_player3_y_btn = "nul" +input_player3_y_mbtn = "nul" +input_player4_a = "nul" +input_player4_a_axis = "nul" +input_player4_a_btn = "nul" +input_player4_a_mbtn = "nul" +input_player4_analog_dpad_mode = "0" +input_player4_b = "nul" +input_player4_b_axis = "nul" +input_player4_b_btn = "nul" +input_player4_b_mbtn = "nul" +input_player4_down = "nul" +input_player4_down_axis = "nul" +input_player4_down_btn = "nul" +input_player4_down_mbtn = "nul" +input_player4_gun_aux_a = "nul" +input_player4_gun_aux_a_axis = "nul" +input_player4_gun_aux_a_btn = "nul" +input_player4_gun_aux_a_mbtn = "nul" +input_player4_gun_aux_b = "nul" +input_player4_gun_aux_b_axis = "nul" +input_player4_gun_aux_b_btn = "nul" +input_player4_gun_aux_b_mbtn = "nul" +input_player4_gun_aux_c = "nul" +input_player4_gun_aux_c_axis = "nul" +input_player4_gun_aux_c_btn = "nul" +input_player4_gun_aux_c_mbtn = "nul" +input_player4_gun_dpad_down = "nul" +input_player4_gun_dpad_down_axis = "nul" +input_player4_gun_dpad_down_btn = "nul" +input_player4_gun_dpad_down_mbtn = "nul" +input_player4_gun_dpad_left = "nul" +input_player4_gun_dpad_left_axis = "nul" +input_player4_gun_dpad_left_btn = "nul" +input_player4_gun_dpad_left_mbtn = "nul" +input_player4_gun_dpad_right = "nul" +input_player4_gun_dpad_right_axis = "nul" +input_player4_gun_dpad_right_btn = "nul" +input_player4_gun_dpad_right_mbtn = "nul" +input_player4_gun_dpad_up = "nul" +input_player4_gun_dpad_up_axis = "nul" +input_player4_gun_dpad_up_btn = "nul" +input_player4_gun_dpad_up_mbtn = "nul" +input_player4_gun_offscreen_shot = "nul" +input_player4_gun_offscreen_shot_axis = "nul" +input_player4_gun_offscreen_shot_btn = "nul" +input_player4_gun_offscreen_shot_mbtn = "nul" +input_player4_gun_select = "nul" +input_player4_gun_select_axis = "nul" +input_player4_gun_select_btn = "nul" +input_player4_gun_select_mbtn = "nul" +input_player4_gun_start = "nul" +input_player4_gun_start_axis = "nul" +input_player4_gun_start_btn = "nul" +input_player4_gun_start_mbtn = "nul" +input_player4_gun_trigger = "nul" +input_player4_gun_trigger_axis = "nul" +input_player4_gun_trigger_btn = "nul" +input_player4_gun_trigger_mbtn = "1" +input_player4_joypad_index = "3" +input_player4_l = "nul" +input_player4_l2 = "nul" +input_player4_l2_axis = "nul" +input_player4_l2_btn = "nul" +input_player4_l2_mbtn = "nul" +input_player4_l3 = "nul" +input_player4_l3_axis = "nul" +input_player4_l3_btn = "nul" +input_player4_l3_mbtn = "nul" +input_player4_l_axis = "nul" +input_player4_l_btn = "nul" +input_player4_l_mbtn = "nul" +input_player4_l_x_minus = "nul" +input_player4_l_x_minus_axis = "nul" +input_player4_l_x_minus_btn = "nul" +input_player4_l_x_minus_mbtn = "nul" +input_player4_l_x_plus = "nul" +input_player4_l_x_plus_axis = "nul" +input_player4_l_x_plus_btn = "nul" +input_player4_l_x_plus_mbtn = "nul" +input_player4_l_y_minus = "nul" +input_player4_l_y_minus_axis = "nul" +input_player4_l_y_minus_btn = "nul" +input_player4_l_y_minus_mbtn = "nul" +input_player4_l_y_plus = "nul" +input_player4_l_y_plus_axis = "nul" +input_player4_l_y_plus_btn = "nul" +input_player4_l_y_plus_mbtn = "nul" +input_player4_left = "nul" +input_player4_left_axis = "nul" +input_player4_left_btn = "nul" +input_player4_left_mbtn = "nul" +input_player4_mouse_index = "3" +input_player4_r = "nul" +input_player4_r2 = "nul" +input_player4_r2_axis = "nul" +input_player4_r2_btn = "nul" +input_player4_r2_mbtn = "nul" +input_player4_r3 = "nul" +input_player4_r3_axis = "nul" +input_player4_r3_btn = "nul" +input_player4_r3_mbtn = "nul" +input_player4_r_axis = "nul" +input_player4_r_btn = "nul" +input_player4_r_mbtn = "nul" +input_player4_r_x_minus = "nul" +input_player4_r_x_minus_axis = "nul" +input_player4_r_x_minus_btn = "nul" +input_player4_r_x_minus_mbtn = "nul" +input_player4_r_x_plus = "nul" +input_player4_r_x_plus_axis = "nul" +input_player4_r_x_plus_btn = "nul" +input_player4_r_x_plus_mbtn = "nul" +input_player4_r_y_minus = "nul" +input_player4_r_y_minus_axis = "nul" +input_player4_r_y_minus_btn = "nul" +input_player4_r_y_minus_mbtn = "nul" +input_player4_r_y_plus = "nul" +input_player4_r_y_plus_axis = "nul" +input_player4_r_y_plus_btn = "nul" +input_player4_r_y_plus_mbtn = "nul" +input_player4_right = "nul" +input_player4_right_axis = "nul" +input_player4_right_btn = "nul" +input_player4_right_mbtn = "nul" +input_player4_select = "nul" +input_player4_select_axis = "nul" +input_player4_select_btn = "nul" +input_player4_select_mbtn = "nul" +input_player4_start = "nul" +input_player4_start_axis = "nul" +input_player4_start_btn = "nul" +input_player4_start_mbtn = "nul" +input_player4_turbo = "nul" +input_player4_turbo_axis = "nul" +input_player4_turbo_btn = "nul" +input_player4_turbo_mbtn = "nul" +input_player4_up = "nul" +input_player4_up_axis = "nul" +input_player4_up_btn = "nul" +input_player4_up_mbtn = "nul" +input_player4_x = "nul" +input_player4_x_axis = "nul" +input_player4_x_btn = "nul" +input_player4_x_mbtn = "nul" +input_player4_y = "nul" +input_player4_y_axis = "nul" +input_player4_y_btn = "nul" +input_player4_y_mbtn = "nul" +input_player5_a = "nul" +input_player5_a_axis = "nul" +input_player5_a_btn = "nul" +input_player5_a_mbtn = "nul" +input_player5_analog_dpad_mode = "0" +input_player5_b = "nul" +input_player5_b_axis = "nul" +input_player5_b_btn = "nul" +input_player5_b_mbtn = "nul" +input_player5_down = "nul" +input_player5_down_axis = "nul" +input_player5_down_btn = "nul" +input_player5_down_mbtn = "nul" +input_player5_gun_aux_a = "nul" +input_player5_gun_aux_a_axis = "nul" +input_player5_gun_aux_a_btn = "nul" +input_player5_gun_aux_a_mbtn = "nul" +input_player5_gun_aux_b = "nul" +input_player5_gun_aux_b_axis = "nul" +input_player5_gun_aux_b_btn = "nul" +input_player5_gun_aux_b_mbtn = "nul" +input_player5_gun_aux_c = "nul" +input_player5_gun_aux_c_axis = "nul" +input_player5_gun_aux_c_btn = "nul" +input_player5_gun_aux_c_mbtn = "nul" +input_player5_gun_dpad_down = "nul" +input_player5_gun_dpad_down_axis = "nul" +input_player5_gun_dpad_down_btn = "nul" +input_player5_gun_dpad_down_mbtn = "nul" +input_player5_gun_dpad_left = "nul" +input_player5_gun_dpad_left_axis = "nul" +input_player5_gun_dpad_left_btn = "nul" +input_player5_gun_dpad_left_mbtn = "nul" +input_player5_gun_dpad_right = "nul" +input_player5_gun_dpad_right_axis = "nul" +input_player5_gun_dpad_right_btn = "nul" +input_player5_gun_dpad_right_mbtn = "nul" +input_player5_gun_dpad_up = "nul" +input_player5_gun_dpad_up_axis = "nul" +input_player5_gun_dpad_up_btn = "nul" +input_player5_gun_dpad_up_mbtn = "nul" +input_player5_gun_offscreen_shot = "nul" +input_player5_gun_offscreen_shot_axis = "nul" +input_player5_gun_offscreen_shot_btn = "nul" +input_player5_gun_offscreen_shot_mbtn = "nul" +input_player5_gun_select = "nul" +input_player5_gun_select_axis = "nul" +input_player5_gun_select_btn = "nul" +input_player5_gun_select_mbtn = "nul" +input_player5_gun_start = "nul" +input_player5_gun_start_axis = "nul" +input_player5_gun_start_btn = "nul" +input_player5_gun_start_mbtn = "nul" +input_player5_gun_trigger = "nul" +input_player5_gun_trigger_axis = "nul" +input_player5_gun_trigger_btn = "nul" +input_player5_gun_trigger_mbtn = "1" +input_player5_joypad_index = "4" +input_player5_l = "nul" +input_player5_l2 = "nul" +input_player5_l2_axis = "nul" +input_player5_l2_btn = "nul" +input_player5_l2_mbtn = "nul" +input_player5_l3 = "nul" +input_player5_l3_axis = "nul" +input_player5_l3_btn = "nul" +input_player5_l3_mbtn = "nul" +input_player5_l_axis = "nul" +input_player5_l_btn = "nul" +input_player5_l_mbtn = "nul" +input_player5_l_x_minus = "nul" +input_player5_l_x_minus_axis = "nul" +input_player5_l_x_minus_btn = "nul" +input_player5_l_x_minus_mbtn = "nul" +input_player5_l_x_plus = "nul" +input_player5_l_x_plus_axis = "nul" +input_player5_l_x_plus_btn = "nul" +input_player5_l_x_plus_mbtn = "nul" +input_player5_l_y_minus = "nul" +input_player5_l_y_minus_axis = "nul" +input_player5_l_y_minus_btn = "nul" +input_player5_l_y_minus_mbtn = "nul" +input_player5_l_y_plus = "nul" +input_player5_l_y_plus_axis = "nul" +input_player5_l_y_plus_btn = "nul" +input_player5_l_y_plus_mbtn = "nul" +input_player5_left = "nul" +input_player5_left_axis = "nul" +input_player5_left_btn = "nul" +input_player5_left_mbtn = "nul" +input_player5_mouse_index = "4" +input_player5_r = "nul" +input_player5_r2 = "nul" +input_player5_r2_axis = "nul" +input_player5_r2_btn = "nul" +input_player5_r2_mbtn = "nul" +input_player5_r3 = "nul" +input_player5_r3_axis = "nul" +input_player5_r3_btn = "nul" +input_player5_r3_mbtn = "nul" +input_player5_r_axis = "nul" +input_player5_r_btn = "nul" +input_player5_r_mbtn = "nul" +input_player5_r_x_minus = "nul" +input_player5_r_x_minus_axis = "nul" +input_player5_r_x_minus_btn = "nul" +input_player5_r_x_minus_mbtn = "nul" +input_player5_r_x_plus = "nul" +input_player5_r_x_plus_axis = "nul" +input_player5_r_x_plus_btn = "nul" +input_player5_r_x_plus_mbtn = "nul" +input_player5_r_y_minus = "nul" +input_player5_r_y_minus_axis = "nul" +input_player5_r_y_minus_btn = "nul" +input_player5_r_y_minus_mbtn = "nul" +input_player5_r_y_plus = "nul" +input_player5_r_y_plus_axis = "nul" +input_player5_r_y_plus_btn = "nul" +input_player5_r_y_plus_mbtn = "nul" +input_player5_right = "nul" +input_player5_right_axis = "nul" +input_player5_right_btn = "nul" +input_player5_right_mbtn = "nul" +input_player5_select = "nul" +input_player5_select_axis = "nul" +input_player5_select_btn = "nul" +input_player5_select_mbtn = "nul" +input_player5_start = "nul" +input_player5_start_axis = "nul" +input_player5_start_btn = "nul" +input_player5_start_mbtn = "nul" +input_player5_turbo = "nul" +input_player5_turbo_axis = "nul" +input_player5_turbo_btn = "nul" +input_player5_turbo_mbtn = "nul" +input_player5_up = "nul" +input_player5_up_axis = "nul" +input_player5_up_btn = "nul" +input_player5_up_mbtn = "nul" +input_player5_x = "nul" +input_player5_x_axis = "nul" +input_player5_x_btn = "nul" +input_player5_x_mbtn = "nul" +input_player5_y = "nul" +input_player5_y_axis = "nul" +input_player5_y_btn = "nul" +input_player5_y_mbtn = "nul" +input_player6_a = "nul" +input_player6_a_axis = "nul" +input_player6_a_btn = "nul" +input_player6_a_mbtn = "nul" +input_player6_analog_dpad_mode = "0" +input_player6_b = "nul" +input_player6_b_axis = "nul" +input_player6_b_btn = "nul" +input_player6_b_mbtn = "nul" +input_player6_down = "nul" +input_player6_down_axis = "nul" +input_player6_down_btn = "nul" +input_player6_down_mbtn = "nul" +input_player6_gun_aux_a = "nul" +input_player6_gun_aux_a_axis = "nul" +input_player6_gun_aux_a_btn = "nul" +input_player6_gun_aux_a_mbtn = "nul" +input_player6_gun_aux_b = "nul" +input_player6_gun_aux_b_axis = "nul" +input_player6_gun_aux_b_btn = "nul" +input_player6_gun_aux_b_mbtn = "nul" +input_player6_gun_aux_c = "nul" +input_player6_gun_aux_c_axis = "nul" +input_player6_gun_aux_c_btn = "nul" +input_player6_gun_aux_c_mbtn = "nul" +input_player6_gun_dpad_down = "nul" +input_player6_gun_dpad_down_axis = "nul" +input_player6_gun_dpad_down_btn = "nul" +input_player6_gun_dpad_down_mbtn = "nul" +input_player6_gun_dpad_left = "nul" +input_player6_gun_dpad_left_axis = "nul" +input_player6_gun_dpad_left_btn = "nul" +input_player6_gun_dpad_left_mbtn = "nul" +input_player6_gun_dpad_right = "nul" +input_player6_gun_dpad_right_axis = "nul" +input_player6_gun_dpad_right_btn = "nul" +input_player6_gun_dpad_right_mbtn = "nul" +input_player6_gun_dpad_up = "nul" +input_player6_gun_dpad_up_axis = "nul" +input_player6_gun_dpad_up_btn = "nul" +input_player6_gun_dpad_up_mbtn = "nul" +input_player6_gun_offscreen_shot = "nul" +input_player6_gun_offscreen_shot_axis = "nul" +input_player6_gun_offscreen_shot_btn = "nul" +input_player6_gun_offscreen_shot_mbtn = "nul" +input_player6_gun_select = "nul" +input_player6_gun_select_axis = "nul" +input_player6_gun_select_btn = "nul" +input_player6_gun_select_mbtn = "nul" +input_player6_gun_start = "nul" +input_player6_gun_start_axis = "nul" +input_player6_gun_start_btn = "nul" +input_player6_gun_start_mbtn = "nul" +input_player6_gun_trigger = "nul" +input_player6_gun_trigger_axis = "nul" +input_player6_gun_trigger_btn = "nul" +input_player6_gun_trigger_mbtn = "1" +input_player6_joypad_index = "5" +input_player6_l = "nul" +input_player6_l2 = "nul" +input_player6_l2_axis = "nul" +input_player6_l2_btn = "nul" +input_player6_l2_mbtn = "nul" +input_player6_l3 = "nul" +input_player6_l3_axis = "nul" +input_player6_l3_btn = "nul" +input_player6_l3_mbtn = "nul" +input_player6_l_axis = "nul" +input_player6_l_btn = "nul" +input_player6_l_mbtn = "nul" +input_player6_l_x_minus = "nul" +input_player6_l_x_minus_axis = "nul" +input_player6_l_x_minus_btn = "nul" +input_player6_l_x_minus_mbtn = "nul" +input_player6_l_x_plus = "nul" +input_player6_l_x_plus_axis = "nul" +input_player6_l_x_plus_btn = "nul" +input_player6_l_x_plus_mbtn = "nul" +input_player6_l_y_minus = "nul" +input_player6_l_y_minus_axis = "nul" +input_player6_l_y_minus_btn = "nul" +input_player6_l_y_minus_mbtn = "nul" +input_player6_l_y_plus = "nul" +input_player6_l_y_plus_axis = "nul" +input_player6_l_y_plus_btn = "nul" +input_player6_l_y_plus_mbtn = "nul" +input_player6_left = "nul" +input_player6_left_axis = "nul" +input_player6_left_btn = "nul" +input_player6_left_mbtn = "nul" +input_player6_mouse_index = "5" +input_player6_r = "nul" +input_player6_r2 = "nul" +input_player6_r2_axis = "nul" +input_player6_r2_btn = "nul" +input_player6_r2_mbtn = "nul" +input_player6_r3 = "nul" +input_player6_r3_axis = "nul" +input_player6_r3_btn = "nul" +input_player6_r3_mbtn = "nul" +input_player6_r_axis = "nul" +input_player6_r_btn = "nul" +input_player6_r_mbtn = "nul" +input_player6_r_x_minus = "nul" +input_player6_r_x_minus_axis = "nul" +input_player6_r_x_minus_btn = "nul" +input_player6_r_x_minus_mbtn = "nul" +input_player6_r_x_plus = "nul" +input_player6_r_x_plus_axis = "nul" +input_player6_r_x_plus_btn = "nul" +input_player6_r_x_plus_mbtn = "nul" +input_player6_r_y_minus = "nul" +input_player6_r_y_minus_axis = "nul" +input_player6_r_y_minus_btn = "nul" +input_player6_r_y_minus_mbtn = "nul" +input_player6_r_y_plus = "nul" +input_player6_r_y_plus_axis = "nul" +input_player6_r_y_plus_btn = "nul" +input_player6_r_y_plus_mbtn = "nul" +input_player6_right = "nul" +input_player6_right_axis = "nul" +input_player6_right_btn = "nul" +input_player6_right_mbtn = "nul" +input_player6_select = "nul" +input_player6_select_axis = "nul" +input_player6_select_btn = "nul" +input_player6_select_mbtn = "nul" +input_player6_start = "nul" +input_player6_start_axis = "nul" +input_player6_start_btn = "nul" +input_player6_start_mbtn = "nul" +input_player6_turbo = "nul" +input_player6_turbo_axis = "nul" +input_player6_turbo_btn = "nul" +input_player6_turbo_mbtn = "nul" +input_player6_up = "nul" +input_player6_up_axis = "nul" +input_player6_up_btn = "nul" +input_player6_up_mbtn = "nul" +input_player6_x = "nul" +input_player6_x_axis = "nul" +input_player6_x_btn = "nul" +input_player6_x_mbtn = "nul" +input_player6_y = "nul" +input_player6_y_axis = "nul" +input_player6_y_btn = "nul" +input_player6_y_mbtn = "nul" +input_player7_a = "nul" +input_player7_a_axis = "nul" +input_player7_a_btn = "nul" +input_player7_a_mbtn = "nul" +input_player7_analog_dpad_mode = "0" +input_player7_b = "nul" +input_player7_b_axis = "nul" +input_player7_b_btn = "nul" +input_player7_b_mbtn = "nul" +input_player7_down = "nul" +input_player7_down_axis = "nul" +input_player7_down_btn = "nul" +input_player7_down_mbtn = "nul" +input_player7_gun_aux_a = "nul" +input_player7_gun_aux_a_axis = "nul" +input_player7_gun_aux_a_btn = "nul" +input_player7_gun_aux_a_mbtn = "nul" +input_player7_gun_aux_b = "nul" +input_player7_gun_aux_b_axis = "nul" +input_player7_gun_aux_b_btn = "nul" +input_player7_gun_aux_b_mbtn = "nul" +input_player7_gun_aux_c = "nul" +input_player7_gun_aux_c_axis = "nul" +input_player7_gun_aux_c_btn = "nul" +input_player7_gun_aux_c_mbtn = "nul" +input_player7_gun_dpad_down = "nul" +input_player7_gun_dpad_down_axis = "nul" +input_player7_gun_dpad_down_btn = "nul" +input_player7_gun_dpad_down_mbtn = "nul" +input_player7_gun_dpad_left = "nul" +input_player7_gun_dpad_left_axis = "nul" +input_player7_gun_dpad_left_btn = "nul" +input_player7_gun_dpad_left_mbtn = "nul" +input_player7_gun_dpad_right = "nul" +input_player7_gun_dpad_right_axis = "nul" +input_player7_gun_dpad_right_btn = "nul" +input_player7_gun_dpad_right_mbtn = "nul" +input_player7_gun_dpad_up = "nul" +input_player7_gun_dpad_up_axis = "nul" +input_player7_gun_dpad_up_btn = "nul" +input_player7_gun_dpad_up_mbtn = "nul" +input_player7_gun_offscreen_shot = "nul" +input_player7_gun_offscreen_shot_axis = "nul" +input_player7_gun_offscreen_shot_btn = "nul" +input_player7_gun_offscreen_shot_mbtn = "nul" +input_player7_gun_select = "nul" +input_player7_gun_select_axis = "nul" +input_player7_gun_select_btn = "nul" +input_player7_gun_select_mbtn = "nul" +input_player7_gun_start = "nul" +input_player7_gun_start_axis = "nul" +input_player7_gun_start_btn = "nul" +input_player7_gun_start_mbtn = "nul" +input_player7_gun_trigger = "nul" +input_player7_gun_trigger_axis = "nul" +input_player7_gun_trigger_btn = "nul" +input_player7_gun_trigger_mbtn = "1" +input_player7_joypad_index = "6" +input_player7_l = "nul" +input_player7_l2 = "nul" +input_player7_l2_axis = "nul" +input_player7_l2_btn = "nul" +input_player7_l2_mbtn = "nul" +input_player7_l3 = "nul" +input_player7_l3_axis = "nul" +input_player7_l3_btn = "nul" +input_player7_l3_mbtn = "nul" +input_player7_l_axis = "nul" +input_player7_l_btn = "nul" +input_player7_l_mbtn = "nul" +input_player7_l_x_minus = "nul" +input_player7_l_x_minus_axis = "nul" +input_player7_l_x_minus_btn = "nul" +input_player7_l_x_minus_mbtn = "nul" +input_player7_l_x_plus = "nul" +input_player7_l_x_plus_axis = "nul" +input_player7_l_x_plus_btn = "nul" +input_player7_l_x_plus_mbtn = "nul" +input_player7_l_y_minus = "nul" +input_player7_l_y_minus_axis = "nul" +input_player7_l_y_minus_btn = "nul" +input_player7_l_y_minus_mbtn = "nul" +input_player7_l_y_plus = "nul" +input_player7_l_y_plus_axis = "nul" +input_player7_l_y_plus_btn = "nul" +input_player7_l_y_plus_mbtn = "nul" +input_player7_left = "nul" +input_player7_left_axis = "nul" +input_player7_left_btn = "nul" +input_player7_left_mbtn = "nul" +input_player7_mouse_index = "6" +input_player7_r = "nul" +input_player7_r2 = "nul" +input_player7_r2_axis = "nul" +input_player7_r2_btn = "nul" +input_player7_r2_mbtn = "nul" +input_player7_r3 = "nul" +input_player7_r3_axis = "nul" +input_player7_r3_btn = "nul" +input_player7_r3_mbtn = "nul" +input_player7_r_axis = "nul" +input_player7_r_btn = "nul" +input_player7_r_mbtn = "nul" +input_player7_r_x_minus = "nul" +input_player7_r_x_minus_axis = "nul" +input_player7_r_x_minus_btn = "nul" +input_player7_r_x_minus_mbtn = "nul" +input_player7_r_x_plus = "nul" +input_player7_r_x_plus_axis = "nul" +input_player7_r_x_plus_btn = "nul" +input_player7_r_x_plus_mbtn = "nul" +input_player7_r_y_minus = "nul" +input_player7_r_y_minus_axis = "nul" +input_player7_r_y_minus_btn = "nul" +input_player7_r_y_minus_mbtn = "nul" +input_player7_r_y_plus = "nul" +input_player7_r_y_plus_axis = "nul" +input_player7_r_y_plus_btn = "nul" +input_player7_r_y_plus_mbtn = "nul" +input_player7_right = "nul" +input_player7_right_axis = "nul" +input_player7_right_btn = "nul" +input_player7_right_mbtn = "nul" +input_player7_select = "nul" +input_player7_select_axis = "nul" +input_player7_select_btn = "nul" +input_player7_select_mbtn = "nul" +input_player7_start = "nul" +input_player7_start_axis = "nul" +input_player7_start_btn = "nul" +input_player7_start_mbtn = "nul" +input_player7_turbo = "nul" +input_player7_turbo_axis = "nul" +input_player7_turbo_btn = "nul" +input_player7_turbo_mbtn = "nul" +input_player7_up = "nul" +input_player7_up_axis = "nul" +input_player7_up_btn = "nul" +input_player7_up_mbtn = "nul" +input_player7_x = "nul" +input_player7_x_axis = "nul" +input_player7_x_btn = "nul" +input_player7_x_mbtn = "nul" +input_player7_y = "nul" +input_player7_y_axis = "nul" +input_player7_y_btn = "nul" +input_player7_y_mbtn = "nul" +input_player8_a = "nul" +input_player8_a_axis = "nul" +input_player8_a_btn = "nul" +input_player8_a_mbtn = "nul" +input_player8_analog_dpad_mode = "0" +input_player8_b = "nul" +input_player8_b_axis = "nul" +input_player8_b_btn = "nul" +input_player8_b_mbtn = "nul" +input_player8_down = "nul" +input_player8_down_axis = "nul" +input_player8_down_btn = "nul" +input_player8_down_mbtn = "nul" +input_player8_gun_aux_a = "nul" +input_player8_gun_aux_a_axis = "nul" +input_player8_gun_aux_a_btn = "nul" +input_player8_gun_aux_a_mbtn = "nul" +input_player8_gun_aux_b = "nul" +input_player8_gun_aux_b_axis = "nul" +input_player8_gun_aux_b_btn = "nul" +input_player8_gun_aux_b_mbtn = "nul" +input_player8_gun_aux_c = "nul" +input_player8_gun_aux_c_axis = "nul" +input_player8_gun_aux_c_btn = "nul" +input_player8_gun_aux_c_mbtn = "nul" +input_player8_gun_dpad_down = "nul" +input_player8_gun_dpad_down_axis = "nul" +input_player8_gun_dpad_down_btn = "nul" +input_player8_gun_dpad_down_mbtn = "nul" +input_player8_gun_dpad_left = "nul" +input_player8_gun_dpad_left_axis = "nul" +input_player8_gun_dpad_left_btn = "nul" +input_player8_gun_dpad_left_mbtn = "nul" +input_player8_gun_dpad_right = "nul" +input_player8_gun_dpad_right_axis = "nul" +input_player8_gun_dpad_right_btn = "nul" +input_player8_gun_dpad_right_mbtn = "nul" +input_player8_gun_dpad_up = "nul" +input_player8_gun_dpad_up_axis = "nul" +input_player8_gun_dpad_up_btn = "nul" +input_player8_gun_dpad_up_mbtn = "nul" +input_player8_gun_offscreen_shot = "nul" +input_player8_gun_offscreen_shot_axis = "nul" +input_player8_gun_offscreen_shot_btn = "nul" +input_player8_gun_offscreen_shot_mbtn = "nul" +input_player8_gun_select = "nul" +input_player8_gun_select_axis = "nul" +input_player8_gun_select_btn = "nul" +input_player8_gun_select_mbtn = "nul" +input_player8_gun_start = "nul" +input_player8_gun_start_axis = "nul" +input_player8_gun_start_btn = "nul" +input_player8_gun_start_mbtn = "nul" +input_player8_gun_trigger = "nul" +input_player8_gun_trigger_axis = "nul" +input_player8_gun_trigger_btn = "nul" +input_player8_gun_trigger_mbtn = "1" +input_player8_joypad_index = "7" +input_player8_l = "nul" +input_player8_l2 = "nul" +input_player8_l2_axis = "nul" +input_player8_l2_btn = "nul" +input_player8_l2_mbtn = "nul" +input_player8_l3 = "nul" +input_player8_l3_axis = "nul" +input_player8_l3_btn = "nul" +input_player8_l3_mbtn = "nul" +input_player8_l_axis = "nul" +input_player8_l_btn = "nul" +input_player8_l_mbtn = "nul" +input_player8_l_x_minus = "nul" +input_player8_l_x_minus_axis = "nul" +input_player8_l_x_minus_btn = "nul" +input_player8_l_x_minus_mbtn = "nul" +input_player8_l_x_plus = "nul" +input_player8_l_x_plus_axis = "nul" +input_player8_l_x_plus_btn = "nul" +input_player8_l_x_plus_mbtn = "nul" +input_player8_l_y_minus = "nul" +input_player8_l_y_minus_axis = "nul" +input_player8_l_y_minus_btn = "nul" +input_player8_l_y_minus_mbtn = "nul" +input_player8_l_y_plus = "nul" +input_player8_l_y_plus_axis = "nul" +input_player8_l_y_plus_btn = "nul" +input_player8_l_y_plus_mbtn = "nul" +input_player8_left = "nul" +input_player8_left_axis = "nul" +input_player8_left_btn = "nul" +input_player8_left_mbtn = "nul" +input_player8_mouse_index = "7" +input_player8_r = "nul" +input_player8_r2 = "nul" +input_player8_r2_axis = "nul" +input_player8_r2_btn = "nul" +input_player8_r2_mbtn = "nul" +input_player8_r3 = "nul" +input_player8_r3_axis = "nul" +input_player8_r3_btn = "nul" +input_player8_r3_mbtn = "nul" +input_player8_r_axis = "nul" +input_player8_r_btn = "nul" +input_player8_r_mbtn = "nul" +input_player8_r_x_minus = "nul" +input_player8_r_x_minus_axis = "nul" +input_player8_r_x_minus_btn = "nul" +input_player8_r_x_minus_mbtn = "nul" +input_player8_r_x_plus = "nul" +input_player8_r_x_plus_axis = "nul" +input_player8_r_x_plus_btn = "nul" +input_player8_r_x_plus_mbtn = "nul" +input_player8_r_y_minus = "nul" +input_player8_r_y_minus_axis = "nul" +input_player8_r_y_minus_btn = "nul" +input_player8_r_y_minus_mbtn = "nul" +input_player8_r_y_plus = "nul" +input_player8_r_y_plus_axis = "nul" +input_player8_r_y_plus_btn = "nul" +input_player8_r_y_plus_mbtn = "nul" +input_player8_right = "nul" +input_player8_right_axis = "nul" +input_player8_right_btn = "nul" +input_player8_right_mbtn = "nul" +input_player8_select = "nul" +input_player8_select_axis = "nul" +input_player8_select_btn = "nul" +input_player8_select_mbtn = "nul" +input_player8_start = "nul" +input_player8_start_axis = "nul" +input_player8_start_btn = "nul" +input_player8_start_mbtn = "nul" +input_player8_turbo = "nul" +input_player8_turbo_axis = "nul" +input_player8_turbo_btn = "nul" +input_player8_turbo_mbtn = "nul" +input_player8_up = "nul" +input_player8_up_axis = "nul" +input_player8_up_btn = "nul" +input_player8_up_mbtn = "nul" +input_player8_x = "nul" +input_player8_x_axis = "nul" +input_player8_x_btn = "nul" +input_player8_x_mbtn = "nul" +input_player8_y = "nul" +input_player8_y_axis = "nul" +input_player8_y_btn = "nul" +input_player8_y_mbtn = "nul" +input_player9_a = "nul" +input_player9_a_axis = "nul" +input_player9_a_btn = "nul" +input_player9_a_mbtn = "nul" +input_player9_analog_dpad_mode = "0" +input_player9_b = "nul" +input_player9_b_axis = "nul" +input_player9_b_btn = "nul" +input_player9_b_mbtn = "nul" +input_player9_down = "nul" +input_player9_down_axis = "nul" +input_player9_down_btn = "nul" +input_player9_down_mbtn = "nul" +input_player9_gun_aux_a = "nul" +input_player9_gun_aux_a_axis = "nul" +input_player9_gun_aux_a_btn = "nul" +input_player9_gun_aux_a_mbtn = "nul" +input_player9_gun_aux_b = "nul" +input_player9_gun_aux_b_axis = "nul" +input_player9_gun_aux_b_btn = "nul" +input_player9_gun_aux_b_mbtn = "nul" +input_player9_gun_aux_c = "nul" +input_player9_gun_aux_c_axis = "nul" +input_player9_gun_aux_c_btn = "nul" +input_player9_gun_aux_c_mbtn = "nul" +input_player9_gun_dpad_down = "nul" +input_player9_gun_dpad_down_axis = "nul" +input_player9_gun_dpad_down_btn = "nul" +input_player9_gun_dpad_down_mbtn = "nul" +input_player9_gun_dpad_left = "nul" +input_player9_gun_dpad_left_axis = "nul" +input_player9_gun_dpad_left_btn = "nul" +input_player9_gun_dpad_left_mbtn = "nul" +input_player9_gun_dpad_right = "nul" +input_player9_gun_dpad_right_axis = "nul" +input_player9_gun_dpad_right_btn = "nul" +input_player9_gun_dpad_right_mbtn = "nul" +input_player9_gun_dpad_up = "nul" +input_player9_gun_dpad_up_axis = "nul" +input_player9_gun_dpad_up_btn = "nul" +input_player9_gun_dpad_up_mbtn = "nul" +input_player9_gun_offscreen_shot = "nul" +input_player9_gun_offscreen_shot_axis = "nul" +input_player9_gun_offscreen_shot_btn = "nul" +input_player9_gun_offscreen_shot_mbtn = "nul" +input_player9_gun_select = "nul" +input_player9_gun_select_axis = "nul" +input_player9_gun_select_btn = "nul" +input_player9_gun_select_mbtn = "nul" +input_player9_gun_start = "nul" +input_player9_gun_start_axis = "nul" +input_player9_gun_start_btn = "nul" +input_player9_gun_start_mbtn = "nul" +input_player9_gun_trigger = "nul" +input_player9_gun_trigger_axis = "nul" +input_player9_gun_trigger_btn = "nul" +input_player9_gun_trigger_mbtn = "1" +input_player9_joypad_index = "8" +input_player9_l = "nul" +input_player9_l2 = "nul" +input_player9_l2_axis = "nul" +input_player9_l2_btn = "nul" +input_player9_l2_mbtn = "nul" +input_player9_l3 = "nul" +input_player9_l3_axis = "nul" +input_player9_l3_btn = "nul" +input_player9_l3_mbtn = "nul" +input_player9_l_axis = "nul" +input_player9_l_btn = "nul" +input_player9_l_mbtn = "nul" +input_player9_l_x_minus = "nul" +input_player9_l_x_minus_axis = "nul" +input_player9_l_x_minus_btn = "nul" +input_player9_l_x_minus_mbtn = "nul" +input_player9_l_x_plus = "nul" +input_player9_l_x_plus_axis = "nul" +input_player9_l_x_plus_btn = "nul" +input_player9_l_x_plus_mbtn = "nul" +input_player9_l_y_minus = "nul" +input_player9_l_y_minus_axis = "nul" +input_player9_l_y_minus_btn = "nul" +input_player9_l_y_minus_mbtn = "nul" +input_player9_l_y_plus = "nul" +input_player9_l_y_plus_axis = "nul" +input_player9_l_y_plus_btn = "nul" +input_player9_l_y_plus_mbtn = "nul" +input_player9_left = "nul" +input_player9_left_axis = "nul" +input_player9_left_btn = "nul" +input_player9_left_mbtn = "nul" +input_player9_mouse_index = "8" +input_player9_r = "nul" +input_player9_r2 = "nul" +input_player9_r2_axis = "nul" +input_player9_r2_btn = "nul" +input_player9_r2_mbtn = "nul" +input_player9_r3 = "nul" +input_player9_r3_axis = "nul" +input_player9_r3_btn = "nul" +input_player9_r3_mbtn = "nul" +input_player9_r_axis = "nul" +input_player9_r_btn = "nul" +input_player9_r_mbtn = "nul" +input_player9_r_x_minus = "nul" +input_player9_r_x_minus_axis = "nul" +input_player9_r_x_minus_btn = "nul" +input_player9_r_x_minus_mbtn = "nul" +input_player9_r_x_plus = "nul" +input_player9_r_x_plus_axis = "nul" +input_player9_r_x_plus_btn = "nul" +input_player9_r_x_plus_mbtn = "nul" +input_player9_r_y_minus = "nul" +input_player9_r_y_minus_axis = "nul" +input_player9_r_y_minus_btn = "nul" +input_player9_r_y_minus_mbtn = "nul" +input_player9_r_y_plus = "nul" +input_player9_r_y_plus_axis = "nul" +input_player9_r_y_plus_btn = "nul" +input_player9_r_y_plus_mbtn = "nul" +input_player9_right = "nul" +input_player9_right_axis = "nul" +input_player9_right_btn = "nul" +input_player9_right_mbtn = "nul" +input_player9_select = "nul" +input_player9_select_axis = "nul" +input_player9_select_btn = "nul" +input_player9_select_mbtn = "nul" +input_player9_start = "nul" +input_player9_start_axis = "nul" +input_player9_start_btn = "nul" +input_player9_start_mbtn = "nul" +input_player9_turbo = "nul" +input_player9_turbo_axis = "nul" +input_player9_turbo_btn = "nul" +input_player9_turbo_mbtn = "nul" +input_player9_up = "nul" +input_player9_up_axis = "nul" +input_player9_up_btn = "nul" +input_player9_up_mbtn = "nul" +input_player9_x = "nul" +input_player9_x_axis = "nul" +input_player9_x_btn = "nul" +input_player9_x_mbtn = "nul" +input_player9_y = "nul" +input_player9_y_axis = "nul" +input_player9_y_btn = "nul" +input_player9_y_mbtn = "nul" +input_poll_type_behavior = "2" +input_quit_gamepad_combo = "0" +input_recording_toggle = "nul" +input_recording_toggle_axis = "nul" +input_recording_toggle_btn = "nul" +input_recording_toggle_mbtn = "nul" +input_remap_binds_enable = "true" +input_remapping_directory = "~/.config/retroarch/config/remaps" +input_reset = "h" +input_reset_axis = "nul" +input_reset_btn = "nul" +input_reset_mbtn = "nul" +input_rewind = "r" +input_rewind_axis = "nul" +input_rewind_btn = "nul" +input_rewind_mbtn = "nul" +input_rumble_gain = "100" +input_runahead_toggle = "nul" +input_runahead_toggle_axis = "nul" +input_runahead_toggle_btn = "nul" +input_runahead_toggle_mbtn = "nul" +input_save_state = "f2" +input_save_state_axis = "nul" +input_save_state_btn = "nul" +input_save_state_mbtn = "nul" +input_screenshot = "f8" +input_screenshot_axis = "nul" +input_screenshot_btn = "nul" +input_screenshot_mbtn = "nul" +input_send_debug_info = "f10" +input_send_debug_info_axis = "nul" +input_send_debug_info_btn = "nul" +input_send_debug_info_mbtn = "nul" +input_sensors_enable = "true" +input_shader_next = "m" +input_shader_next_axis = "nul" +input_shader_next_btn = "nul" +input_shader_next_mbtn = "nul" +input_shader_prev = "n" +input_shader_prev_axis = "nul" +input_shader_prev_btn = "nul" +input_shader_prev_mbtn = "nul" +input_state_slot_decrease = "f6" +input_state_slot_decrease_axis = "nul" +input_state_slot_decrease_btn = "nul" +input_state_slot_decrease_mbtn = "nul" +input_state_slot_increase = "f7" +input_state_slot_increase_axis = "nul" +input_state_slot_increase_btn = "nul" +input_state_slot_increase_mbtn = "nul" +input_streaming_toggle = "nul" +input_streaming_toggle_axis = "nul" +input_streaming_toggle_btn = "nul" +input_streaming_toggle_mbtn = "nul" +input_toggle_fast_forward = "space" +input_toggle_fast_forward_axis = "nul" +input_toggle_fast_forward_btn = "nul" +input_toggle_fast_forward_mbtn = "nul" +input_toggle_fullscreen = "f" +input_toggle_fullscreen_axis = "nul" +input_toggle_fullscreen_btn = "nul" +input_toggle_fullscreen_mbtn = "nul" +input_toggle_slowmotion = "nul" +input_toggle_slowmotion_axis = "nul" +input_toggle_slowmotion_btn = "nul" +input_toggle_slowmotion_mbtn = "nul" +input_toggle_statistics = "nul" +input_toggle_statistics_axis = "nul" +input_toggle_statistics_btn = "nul" +input_toggle_statistics_mbtn = "nul" +input_touch_scale = "1" +input_turbo_default_button = "0" +input_turbo_mode = "0" +input_turbo_period = "6" +input_volume_down = "subtract" +input_volume_down_axis = "nul" +input_volume_down_btn = "nul" +input_volume_down_mbtn = "nul" +input_volume_up = "add" +input_volume_up_axis = "nul" +input_volume_up_btn = "nul" +input_volume_up_mbtn = "nul" +joypad_autoconfig_dir = "~/.config/retroarch/autoconfig" +keyboard_gamepad_enable = "true" +keyboard_gamepad_mapping_type = "1" +kiosk_mode_enable = "false" +kiosk_mode_password = "" +led_driver = "null" +libretro_directory = "/usr/lib/libretro" +libretro_info_path = "/usr/share/libretro/info" +libretro_log_level = "1" +load_dummy_on_core_shutdown = "true" +location_allow = "false" +location_driver = "null" +log_dir = "~/.config/retroarch/logs" +log_to_file = "false" +log_to_file_timestamp = "false" +log_verbosity = "false" +materialui_auto_rotate_nav_bar = "true" +materialui_dual_thumbnail_list_view_enable = "true" +materialui_icons_enable = "true" +materialui_landscape_layout_optimization = "1" +materialui_menu_color_theme = "9" +materialui_menu_transition_animation = "0" +materialui_playlist_icons_enable = "true" +materialui_show_nav_bar = "true" +materialui_thumbnail_background_enable = "true" +materialui_thumbnail_view_landscape = "2" +materialui_thumbnail_view_portrait = "1" +memory_show = "false" +memory_update_interval = "256" +menu_battery_level_enable = "true" +menu_core_enable = "true" +menu_driver = "ozone" +menu_dynamic_wallpaper_enable = "true" +menu_enable_widgets = "true" +menu_font_color_blue = "255" +menu_font_color_green = "255" +menu_font_color_red = "255" +menu_footer_opacity = "1.000000" +menu_framebuffer_opacity = "0.900000" +menu_header_opacity = "1.000000" +menu_horizontal_animation = "true" +menu_insert_disk_resume = "true" +menu_left_thumbnails = "0" +menu_linear_filter = "false" +menu_mouse_enable = "true" +menu_navigation_browser_filter_supported_extensions_enable = "true" +menu_navigation_wraparound_enable = "true" +menu_pause_libretro = "true" +menu_pointer_enable = "false" +menu_rgui_full_width_layout = "true" +menu_rgui_shadows = "false" +menu_rgui_transparency = "true" +menu_savestate_resume = "true" +menu_scale_factor = "1.000000" +menu_screensaver_animation = "0" +menu_screensaver_animation_speed = "1.000000" +menu_screensaver_timeout = "0" +menu_scroll_delay = "256" +menu_scroll_fast = "false" +menu_shader_pipeline = "2" +menu_show_advanced_settings = "false" +menu_show_configurations = "true" +menu_show_core_updater = "false" +menu_show_dump_disc = "true" +menu_show_help = "true" +menu_show_information = "true" +menu_show_latency = "true" +menu_show_legacy_thumbnail_updater = "false" +menu_show_load_content = "true" +menu_show_load_content_animation = "true" +menu_show_load_core = "true" +menu_show_load_disc = "true" +menu_show_online_updater = "true" +menu_show_overlays = "true" +menu_show_quit_retroarch = "true" +menu_show_reboot = "true" +menu_show_restart_retroarch = "true" +menu_show_rewind = "true" +menu_show_shutdown = "true" +menu_show_sublabels = "true" +menu_show_video_layout = "true" +menu_swap_ok_cancel_buttons = "false" +menu_throttle_framerate = "true" +menu_thumbnail_upscale_threshold = "0" +menu_thumbnails = "3" +menu_ticker_smooth = "true" +menu_ticker_speed = "2.000000" +menu_ticker_type = "1" +menu_timedate_date_separator = "0" +menu_timedate_enable = "true" +menu_timedate_style = "11" +menu_unified_controls = "false" +menu_use_preferred_system_color_theme = "false" +menu_wallpaper = "" +menu_wallpaper_opacity = "0.300000" +menu_widget_scale_auto = "true" +menu_widget_scale_factor = "1.000000" +menu_widget_scale_factor_windowed = "1.000000" +menu_xmb_animation_horizontal_highlight = "0" +menu_xmb_animation_move_up_down = "0" +menu_xmb_animation_opening_main_menu = "0" +menu_xmb_thumbnail_scale_factor = "100" +menu_xmb_vertical_fade_factor = "100" +midi_driver = "alsa" +midi_input = "Off" +midi_output = "Off" +midi_volume = "100" +netplay_allow_pausing = "false" +netplay_allow_slaves = "true" +netplay_check_frames = "600" +netplay_custom_mitm_server = "" +netplay_fade_chat = "true" +netplay_input_latency_frames_min = "0" +netplay_input_latency_frames_range = "0" +netplay_ip_address = "" +netplay_ip_port = "55435" +netplay_max_connections = "3" +netplay_max_ping = "0" +netplay_mitm_server = "nyc" +netplay_nat_traversal = "true" +netplay_nickname = "" +netplay_password = "" +netplay_ping_show = "false" +netplay_public_announce = "true" +netplay_request_device_p1 = "false" +netplay_request_device_p10 = "false" +netplay_request_device_p11 = "false" +netplay_request_device_p12 = "false" +netplay_request_device_p13 = "false" +netplay_request_device_p14 = "false" +netplay_request_device_p15 = "false" +netplay_request_device_p16 = "false" +netplay_request_device_p2 = "false" +netplay_request_device_p3 = "false" +netplay_request_device_p4 = "false" +netplay_request_device_p5 = "false" +netplay_request_device_p6 = "false" +netplay_request_device_p7 = "false" +netplay_request_device_p8 = "false" +netplay_request_device_p9 = "false" +netplay_require_slaves = "false" +netplay_share_analog = "1" +netplay_share_digital = "1" +netplay_show_only_connectable = "true" +netplay_spectate_password = "" +netplay_start_as_spectator = "false" +netplay_stateless_mode = "false" +netplay_use_mitm_server = "false" +network_cmd_enable = "false" +network_cmd_port = "55355" +network_on_demand_thumbnails = "false" +network_remote_base_port = "55400" +network_remote_enable = "false" +network_remote_enable_user_p1 = "false" +network_remote_enable_user_p10 = "false" +network_remote_enable_user_p11 = "false" +network_remote_enable_user_p12 = "false" +network_remote_enable_user_p13 = "false" +network_remote_enable_user_p14 = "false" +network_remote_enable_user_p15 = "false" +network_remote_enable_user_p16 = "false" +network_remote_enable_user_p2 = "false" +network_remote_enable_user_p3 = "false" +network_remote_enable_user_p4 = "false" +network_remote_enable_user_p5 = "false" +network_remote_enable_user_p6 = "false" +network_remote_enable_user_p7 = "false" +network_remote_enable_user_p8 = "false" +network_remote_enable_user_p9 = "false" +notification_show_autoconfig = "true" +notification_show_cheats_applied = "true" +notification_show_config_override_load = "true" +notification_show_fast_forward = "true" +notification_show_netplay_extra = "false" +notification_show_patch_applied = "true" +notification_show_refresh_rate = "true" +notification_show_remap_load = "true" +notification_show_screenshot = "true" +notification_show_screenshot_duration = "0" +notification_show_screenshot_flash = "0" +notification_show_set_initial_disk = "true" +notification_show_when_menu_is_alive = "false" +overlay_directory = "~/.config/retroarch/overlay" +ozone_collapse_sidebar = "false" +ozone_menu_color_theme = "1" +ozone_scroll_content_metadata = "false" +ozone_sort_after_truncate_playlist_name = "true" +ozone_truncate_playlist_name = "true" +pause_nonactive = "true" +perfcnt_enable = "false" +playlist_compression = "false" +playlist_directory = "~/.config/retroarch/playlists" +playlist_entry_remove_enable = "1" +playlist_entry_rename = "true" +playlist_fuzzy_archive_match = "false" +playlist_portable_paths = "false" +playlist_show_entry_idx = "true" +playlist_show_history_icons = "0" +playlist_show_inline_core_name = "0" +playlist_show_sublabels = "true" +playlist_sort_alphabetical = "true" +playlist_sublabel_last_played_style = "0" +playlist_sublabel_runtime_type = "0" +playlist_use_old_format = "false" +quick_menu_show_add_to_favorites = "true" +quick_menu_show_cheats = "true" +quick_menu_show_close_content = "true" +quick_menu_show_controls = "true" +quick_menu_show_core_options_flush = "false" +quick_menu_show_download_thumbnails = "true" +quick_menu_show_information = "true" +quick_menu_show_options = "true" +quick_menu_show_recording = "true" +quick_menu_show_reset_core_association = "true" +quick_menu_show_restart_content = "true" +quick_menu_show_resume_content = "true" +quick_menu_show_save_content_dir_overrides = "true" +quick_menu_show_save_core_overrides = "true" +quick_menu_show_save_game_overrides = "true" +quick_menu_show_save_load_state = "true" +quick_menu_show_set_core_association = "true" +quick_menu_show_shaders = "true" +quick_menu_show_start_recording = "true" +quick_menu_show_start_streaming = "true" +quick_menu_show_streaming = "true" +quick_menu_show_take_screenshot = "true" +quick_menu_show_undo_save_load_state = "true" +quit_on_close_content = "0" +quit_press_twice = "true" +record_driver = "ffmpeg" +recording_config_directory = "~/.config/retroarch/records_config" +recording_output_directory = "~/.config/retroarch/records" +resampler_directory = "" +rewind_buffer_size = "20971520" +rewind_buffer_size_step = "10" +rewind_enable = "false" +rewind_granularity = "1" +rgui_aspect_ratio = "0" +rgui_aspect_ratio_lock = "0" +rgui_background_filler_thickness_enable = "true" +rgui_border_filler_enable = "true" +rgui_border_filler_thickness_enable = "true" +rgui_browser_directory = "default" +rgui_config_directory = "~/.config/retroarch/config" +rgui_extended_ascii = "false" +rgui_inline_thumbnails = "false" +rgui_internal_upscale_level = "0" +rgui_menu_color_theme = "4" +rgui_menu_theme_preset = "" +rgui_particle_effect = "0" +rgui_particle_effect_screensaver = "true" +rgui_particle_effect_speed = "1.000000" +rgui_show_start_screen = "false" +rgui_swap_thumbnails = "false" +rgui_switch_icons = "true" +rgui_thumbnail_delay = "0" +rgui_thumbnail_downscaler = "0" +run_ahead_enabled = "false" +run_ahead_frames = "1" +run_ahead_hide_warnings = "false" +run_ahead_secondary_instance = "false" +runtime_log_directory = "default" +save_file_compression = "false" +savefile_directory = "~/.config/retroarch/saves" +savefiles_in_content_dir = "false" +savestate_auto_index = "false" +savestate_auto_load = "true" +savestate_auto_save = "true" +savestate_directory = "~/.config/retroarch/states" +savestate_file_compression = "true" +savestate_max_keep = "50" +savestate_thumbnail_enable = "false" +savestates_in_content_dir = "false" +scan_without_core_match = "false" +screen_brightness = "100" +screen_orientation = "0" +screenshot_directory = "~/.config/retroarch/screenshots" +screenshots_in_content_dir = "false" +settings_show_accessibility = "true" +settings_show_achievements = "true" +settings_show_ai_service = "true" +settings_show_audio = "true" +settings_show_configuration = "true" +settings_show_core = "true" +settings_show_directory = "true" +settings_show_drivers = "true" +settings_show_file_browser = "true" +settings_show_frame_throttle = "true" +settings_show_input = "true" +settings_show_latency = "true" +settings_show_logging = "true" +settings_show_network = "true" +settings_show_onscreen_display = "true" +settings_show_playlists = "true" +settings_show_power_management = "true" +settings_show_recording = "true" +settings_show_saving = "true" +settings_show_user = "true" +settings_show_user_interface = "true" +settings_show_video = "true" +show_hidden_files = "false" +slowmotion_ratio = "3.000000" +soft_filter_enable = "false" +soft_filter_index = "0" +sort_savefiles_by_content_enable = "false" +sort_savefiles_enable = "false" +sort_savestates_by_content_enable = "false" +sort_savestates_enable = "false" +sort_screenshots_by_content_enable = "false" +state_slot = "0" +statistics_show = "false" +stdin_cmd_enable = "false" +streaming_mode = "0" +suspend_screensaver_enable = "true" +sustained_performance_mode = "false" +system_directory = "~/.config/retroarch/system" +systemfiles_in_content_dir = "false" +threaded_data_runloop_enable = "true" +thumbnails_directory = "~/.config/retroarch/thumbnails" +twitch_stream_key = "" +ui_companion_enable = "false" +ui_companion_start_on_boot = "true" +ui_companion_toggle = "false" +ui_menubar_enable = "true" +use_last_start_directory = "false" +user_language = "0" +vibrate_on_keypress = "false" +video_adaptive_vsync = "false" +video_allow_rotate = "true" +video_aspect_ratio = "1.333300" +video_aspect_ratio_auto = "false" +video_black_frame_insertion = "0" +video_context_driver = "" +video_crop_overscan = "true" +video_ctx_scaling = "false" +video_disable_composition = "false" +video_driver = "gl" +video_filter = "" +video_filter_dir = "/usr/share/retroarch/filters/64bit/video" +video_font_enable = "true" +video_font_path = "" +video_font_size = "32.000000" +video_force_aspect = "true" +video_force_srgb_disable = "false" +video_frame_delay = "0" +video_frame_delay_auto = "false" +video_fullscreen = "true" +video_fullscreen_x = "0" +video_fullscreen_y = "0" +video_gpu_record = "false" +video_gpu_screenshot = "true" +video_hard_sync = "false" +video_hard_sync_frames = "0" +video_hdr_display_contrast = "5.000000" +video_hdr_enable = "false" +video_hdr_expand_gamut = "true" +video_hdr_max_nits = "1000.000000" +video_hdr_paper_white_nits = "200.000000" +video_layout_directory = "~/.config/retroarch/layouts" +video_layout_enable = "true" +video_layout_path = "" +video_layout_selected_view = "0" +video_max_swapchain_images = "3" +video_message_color = "ffff00" +video_message_pos_x = "0.050000" +video_message_pos_y = "0.050000" +video_monitor_index = "0" +video_msg_bgcolor_blue = "0" +video_msg_bgcolor_enable = "false" +video_msg_bgcolor_green = "0" +video_msg_bgcolor_opacity = "1.000000" +video_msg_bgcolor_red = "0" +video_notch_write_over_enable = "false" +video_post_filter_record = "false" +video_record_config = "" +video_record_quality = "2" +video_record_scale_factor = "1" +video_record_threads = "2" +video_refresh_rate = "60.000000" +video_rotation = "0" +video_scale = "3.000000" +video_scale_integer = "true" +video_scale_integer_overscale = "false" +video_shader_delay = "0" +video_shader_dir = "/usr/share/libretro/shaders" +video_shader_enable = "true" +video_shader_preset_save_reference_enable = "true" +video_shader_remember_last_dir = "false" +video_shader_watch_files = "false" +video_shared_context = "false" +video_smooth = "false" +video_stream_config = "" +video_stream_port = "56400" +video_stream_quality = "11" +video_stream_scale_factor = "1" +video_stream_url = "" +video_swap_interval = "1" +video_threaded = "false" +video_vsync = "true" +video_window_auto_height_max = "1080" +video_window_auto_width_max = "1920" +video_window_custom_size_enable = "false" +video_window_opacity = "100" +video_window_save_positions = "false" +video_window_show_decorations = "true" +video_windowed_fullscreen = "false" +video_windowed_position_height = "720" +video_windowed_position_width = "1280" +video_windowed_position_x = "0" +video_windowed_position_y = "0" +vrr_runloop_enable = "false" +vulkan_gpu_index = "0" +wifi_driver = "null" +wifi_enabled = "true" +xmb_alpha_factor = "75" +xmb_font = "" +xmb_layout = "0" +xmb_menu_color_theme = "4" +xmb_shadows_enable = "true" +xmb_theme = "0" +xmb_vertical_thumbnails = "false" +youtube_stream_key = "" diff --git a/usr/bin/351elec-es-packages b/usr/bin/351elec-es-packages new file mode 100755 index 00000000..ca6c2f64 --- /dev/null +++ b/usr/bin/351elec-es-packages @@ -0,0 +1,236 @@ +#!/bin/bash +# SPDX-License-Identifier: GPL-2.0-or-later +# Copyright (C) 2020-present Batocera +# Copyright (C) 2020-present Fewtarius + +# +# Download and install packages supported binary packages +# +# Usage: +# 351elec-es-package 'list' or 'install ' +# +# If you don't provide a , the list of packages will be downloaded and sent back to you. +# + +ARCH="$(cat /storage/.config/.OS_ARCH)" +if [ "${ARCH}" == "RG351P" ]; then + DEVICE="RG351P" +elif [ "${ARCH}" == "RG351V" ]; then + DEVICE="RG351V" +elif [ "${ARCH}" == "RG351MP" ]; then + DEVICE="RG351MP" +elif [ "${ARCH}" == "RG552" ]; then + DEVICE="RG552" +fi +DISTRO="351ELEC" +CONFIGDIR="/storage/.config/packages" +PACKAGELIST="https://raw.githubusercontent.com/351ELEC/351ELEC-metadata/main/${ARCH}/packages.cfg" +LOCALPACKAGELIST="/storage/.config/packages.cfg" + +# Community Package List Schema +# +# {PACKAGE NAME}|{PACKAGE URL}|{SHA256SUM} +# +# Half_Life|https://github.com/blah/half-life-1231.zip|d06489dcf04c602ddacc6f80b2809e6d25fd6298c461966e666e19d3188e04be +# +# packages.cfg must be a plain text pipe delimited file. + +# Community Package Schema +# +# URL: https://github.com/blah/half-life-1231.zip +# Content: +# half-life/ <- must match "package" name ^ +# install.sh <- must be named install.sh/uninstall.sh and be in the package root. +# uninstall.sh +# Relevant files/directories included in install.sh/uninstall.sh +# Minimum: +# system-half-life.png +# system-half-life-thumb.png +# +# The package blob may be hosted elsewhere, as long as install.sh is able to download it. + +############################### +# +# Prepare the system for installation +if [ ! -d "${CONFIGDIR}" ] +then + mkdir -p "${CONFIGDIR}" +fi + +############################### +# +function usage() { + echo "$0 - downloads and installs packages supported packages in ${DISTRO}" + echo " " + echo "It accepts two modes: 'list' and 'install '" + echo "- 'list' for the list of packages available online, and if they are" + echo " [A]vailable to install, [I]nstalled or [?]unknown." + echo "- 'install ' to install the package, from its package name." + echo "- 'remove ' to delete an installed package." + echo " " + exit 1 +} + +############################### +# +function check_url() { + [[ "$1" =~ ^(https?|ftp)://.*$ ]] && echo "[A]" || echo "[?]" +} + +############################### +# +function git_name() { + echo "$1" | sed "s,.*/\(.*\),\1," +} + +############################### +# +function repo_name() { + echo "$1" | sed "s,.*github.com/\([A-Za-z0-9_-]*\)/.*,\1," +} + +############################### +# +function list_packages() { + fn=$(date +"%s") + tmp="/tmp/packages_${fn}" + echo "* ${DISTRO} packages *" + if [ -f ${LOCALPACKAGELIST} ]; then + cp -f "${LOCALPACKAGELIST}" "${tmp}" + else + curl -H 'Cache-Control: no-cache' -sfL "${PACKAGELIST}" -o "${tmp}" || exit 1 + sed -i 's/\r$//' "${tmp}" + fi + while IFS=$'|' read name url shasum; do + [ x"${name}" == "x" ] && continue + ia=$(check_url "${url}") + [ -d "${CONFIGDIR}"/"${name}" ] && ia="[I]" + echo "${ia} ${name} - ${url}" + done < "${tmp}" + [[ -e "${tmp}" ]] && rm "${tmp}" +} + + +############################### +# +function getPer() { + TARFILE="$1" + TARVAL="$2" + while true; do + CURVAL=$(stat "$TARFILE" | grep -E '^[ ]*Size:' | sed -e s+'^[ ]*Size: \([0-9][0-9]*\) .*$'+'\1'+) + CURVAL=$((CURVAL / 1024 / 1024)) + PER=$((${CURVAL} * 100 / ${TARVAL})) + echo "${PER}% - ${package} - [${TARVAL}MB]" + sleep 2 + done +} + +############################### +# +function install_package() { + package="$1" + success_installed=0 + fn=$(date +"%s") + tmp="/tmp/packages_${fn}" + if [ -f ${LOCALPACKAGELIST} ]; then + cp -f "${LOCALPACKAGELIST}" "${tmp}" + else + curl -H 'Cache-Control: no-cache' -sfL "${PACKAGELIST}" -o "${tmp}" || exit 1 + sed -i 's/\r$//' "${tmp}" + fi + while IFS=$'|' read name url shasum; do + [ x"${name}" != x"${package}" ] && continue + ia=$(check_url "${url}") + if [ x"${ia}" != x"[A]" ]; then + echo "Error - invalid package URL ${url}" + exit 1 + else + cd ${CONFIGDIR} + filename=$(echo ${url} | sed "s#^.*/##") + curl -H 'Cache-Control: no-cache' -sfL "${url}" -o "${filename}" || exit 1 + if [ -f "${filename}" ]; then + echo "Verifying package checksum" + dldsum=$(sha256sum ${filename} | awk '{print $1}') + if [ ! "${shasum}" == "${dldsum}" ] + then + echo "Error - Checksum does not match." + success_installed=0 + else + echo "Unzipping ${filename} package files >>> 99%" + if [ -d "${CONFIGDIR}/${filename}" ] + then + rm -rf "${CONFIGDIR}/${filename}" + fi + unzip "${filename}" >/dev/null 2>&1 + rm "${filename}" + echo "Installing ${filename} package" + sh ./${package}/install.sh + if [ $? == 0 ] + then + success_installed=1 + else + echo "Error - Installation failed." + success_installed=0 + fi + fi + else + echo "Error - ${package} zip file could not be downloaded from ${url}" + exit 1 + fi + fi + done < "${tmp}" + [[ -e "${tmp}" ]] && rm "${tmp}" + if [ "${success_installed}" == 1 ]; then + echo "${package} is now installed >>> 100%" + exit 0 + else + echo "Error - ${package} could not be installed" + exit 1 + fi +} + +############################### +# +function remove_package() { + package="$1" + success_removed=0 + filename=${package} + if [ -d "${CONFIGDIR}/${package}" ]; then + sh ${CONFIGDIR}/${package}/uninstall.sh + if [ $? == 0 ] + then + rm -rf "${CONFIGDIR}"/"${filename}" && success_removed=1 + else + echo "Unable to uninstall ${package}" + success_removed=0 + fi + else + echo "${package} doesn't appear to be in ${CONFIGDIR}/${filename}" + fi + if [ "${success_removed}" == 1 ]; then + TERMINAL=0 && echo "${package} uninstalled >>>100" + exit 0 + else + echo "Error - ${package} could not be removed" + exit 1 + fi +} + +#### Main loop +# +command="$1" +package="$2" + +if ! [ -d "${CONFIGDIR}" ]; then + echo "Error - package directory ${CONFIGDIR} is not valid." + exit 1 +fi +if [ x"${command}" == "xlist" ]; then + list_packages +elif [ x"${command}" == "xinstall" ]; then + [ x"${package}" != "x" ] && install_package ${package} || usage +elif [ x"${command}" == "xremove" ]; then + [ x"${package}" != "x" ] && remove_package ${package} || usage +else + usage +fi diff --git a/usr/bin/batocera-config b/usr/bin/batocera-config new file mode 100755 index 00000000..94b0e359 --- /dev/null +++ b/usr/bin/batocera-config @@ -0,0 +1,373 @@ +#!/bin/bash + +if [ ! "$1" ];then + echo -e "usage : batocera-config [command] [args]\nWith command in\n\toverscan [enable|disable]\n\tlsaudio\n\tgetaudio\n\taudio [hdmi|jack|auto|custom|x,y]\n\tcanupdate\n\tupdate\n\twifi [enable|disable] ssid key\n\tstorage [current|list|INTERNAL|ANYEXTERNAL|RAM|DEV UUID]\n\tsetRootPassword [password]\n\tgetRootPassword\n\ttz [|tz]" + exit 1 +fi +configFile="/storage/.config/distribution/configs/config.txt" +storageFile="/storage/.config/distribution/configs/batocera-boot.conf" +command="$1" +mode="$2" +extra1="$3" +extra2="$4" +extra3="$5" +extra4="$6" +arch=$(cat /storage/.config/.OS_ARCH) + +updateurl="https://127.0.0.1" + +preBootConfig() { + mount -o remount,rw /boot +} + +postBootConfig() { + mount -o remount,ro /boot +} + +bato_config_set_value () { + key=$1 + value=$2 + [ -z "$value" ] && value=0 + cat "$configFile" | grep "$key" + valPresent=$? + if [ "$valPresent" != "0" ];then + echo "$key=$value" >> "$configFile" + else + sed -i "s/#\?$key=.*/$key=$value/g" "$configFile" + fi +} + +#log=/userdata/system/logs/batocera.log +#systemsetting="python /usr/lib/python2.7/site-packages/configgen/settings/batoceraSettings.py" + +log=/tmp/logs/systemsettings.log +systemsetting="/usr/bin/batocera-settings" + + +echo "----config ----" >> $log + +if [ "$command" == "getRootPassword" ]; then + # security disabled, force the default one without changing boot configuration + securityenabled="`$systemsetting -command load -key system.security.enabled`" + if [ "$securityenabled" != "1" ];then + echo "linux" + exit 0 + fi + + ENCPASSWD=$(grep -E '^[ \t]*rootshadowpassword[ \t]*=' "${storageFile}" | sed -e s+'^[ \t]*rootshadowpassword[ \t]*='++) + if test -z "${ENCPASSWD}" + then + exit 1 + fi + if ! batocera-encode decode "${ENCPASSWD}" + then + exit 1 + fi + exit 0 +fi + +if [ "$command" == "setRootPassword" ]; then + PASSWD=${2} + + # security disabled, don't change + securityenabled="`$systemsetting -command load -key system.security.enabled`" + if [ "$securityenabled" != "1" ];then + exit 0 + fi + + # if no password if provided, generate one + if test -z "${PASSWD}" + then + PASSWD=$(tr -cd _A-Z-a-z-0-9 < /dev/urandom | fold -w8 | head -n1) + fi + PASSWDENC=$(batocera-encode encode "${PASSWD}") + + preBootConfig + if grep -qE '^[ \t]*rootshadowpassword[ \t]*=' "${storageFile}" + then + # update it + if ! sed -i -e s@'^[ \t]*rootshadowpassword[ \t]*=.*$'@"rootshadowpassword=${PASSWDENC}"@ "${storageFile}" + then + postBootConfig + exit 1 + fi + postBootConfig + exit 0 + else + # create it + if ! echo "rootshadowpassword=${PASSWDENC}" >> "${storageFile}" + then + postBootConfig + exit 1 + fi + postBootConfig + exit 0 + fi +fi + +if [ "$command" == "overscan" ]; then +if [ "$mode" == "set" ];then +# set will set overscan values abd also enable this mode + if [ -z "$extra1" ] || [ -z "$extra2" ] || [ -z "$extra3" ] || [ -z "$extra4" ]; then + echo "$0 $command $mode needs 4 arguments:" + echo "$0 $command $mode overscan_left overscan_right overscan_top overscan_bottom" + exit 2 + fi + preBootConfig + [ -f "$configFile" ] || touch "$configFile" + + echo "setting overscan values $extra1 $extra2 $extra3 $extra4 " >> $log + bato_config_set_value disable_overscan 0 + bato_config_set_value overscan_scale 1 + bato_config_set_value overscan_left "$extra1" + bato_config_set_value overscan_right "$extra2" + bato_config_set_value overscan_top "$extra3" + bato_config_set_value overscan_bottom "$extra4" + + postBootConfig + exit 0 + +fi +if [ -f "$configFile" ];then + preBootConfig + if [ "$mode" == "enable" ];then + echo "enabling overscan" >> $log + bato_config_set_value disable_overscan 0 + bato_config_set_value overscan_scale 1 + elif [ "$mode" == "disable" ];then + echo "disabling overscan" >> $log + bato_config_set_value disable_overscan 1 + bato_config_set_value overscan_scale 0 + else + postBootConfig + exit 1 + fi + postBootConfig + exit 0 +else + exit 2 +fi +fi + +if [ "$command" == "lsoutputs" ] +then + echo "auto" + batocera-resolution listOutputs +fi + +if [ "$command" == "lsaudio" ];then + if [[ "${arch}" =~ "rpi" ]] + then + echo "hdmi" + echo "jack" + echo "auto" + elif [[ "${arch}" =~ "x86" ]];then + echo "auto" + echo "custom" + LANG=C aplay -l | grep -E '^card [0-9]*:' | sed -e s+'^card \([0-9]*\): \([^,]*\), device \([0-9]*\): [^\[]* \[\([^]]*\)].*$'+'\1,\3 \4 \2'+ + else + echo "auto" + fi +fi + +if [ "$command" == "getaudio" ];then + $systemsetting -command load -key audio.device + exit 0 +fi + +if [ "$command" == "audio" ];then + # this code is specific to the rpi + # don't set it on other boards + # find a more generic way would be nice + if [[ "${arch}" =~ "rpi" ]] + then + # this is specific to the rpi + cmdVal="0" + if [ "$mode" == "hdmi" ];then + cmdVal="2" + elif [ "$mode" == "jack" ];then + cmdVal="1" + fi + echo "setting audio output mode : $mode" >> $log + amixer cset numid=3 $cmdVal || exit 1 + elif [[ "${arch}" =~ "x86" ]] + then + # auto: no .asoundrc file + # custom: don't touch the .asoundrc file + # any other, create the .asoundrd file + if [ "$mode" == "auto" ];then + rm -rf /userdata/system/.asoundrc || exit 1 + elif [ "$mode" != "custom" ];then + if echo "${mode}" | grep -qE '^[0-9]*,[0-9]* ' + then + cardnb=$(echo "${mode}" | sed -e s+'^\([0-9]*\),.*$'+'\1'+) + devicenb=$(echo "${mode}" | sed -e s+'^[0-9]*,\([0-9]*\) .*$'+'\1'+) + cat > /userdata/system/.asoundrc <> $log + + # on my pc, the master is turned off at boot + # i don't know what are the rules to set here. + amixer set Master unmute || exit 1 + amixer set Master -- ${mode}% || exit 1 + + # maximize the sound to be sure it's not 0, allow errors + amixer set PCM -- 100% #|| exit 1 + amixer set Headphone -- 100% #|| exit 1 + exit 0 + fi + exit 12 +fi + +if [ "$command" == "gpiocontrollers" ];then + command="module" + mode="load" + extra1="mk_arcade_joystick_rpi" + extra2="map=1,2" +fi + +if [ "$command" == "module" ];then + modulename="$extra1" + map="$extra2" + # remove in all cases + rmmod /lib/modules/`uname -r`/extra/${modulename}.ko >> $log + + if [ "$mode" == "load" ];then + echo "loading module $modulename args = $map" >> $log + insmod /lib/modules/`uname -r`/extra/${modulename}.ko $map >> $log + [ "$?" ] || exit 1 + fi + exit 0 +fi + +if [ "$command" == "canupdate" ];then + available=$(updatecheck canupdate) + echo "$available" + if [[ "$available" != "no" ]]; then + exit 0 + fi + exit 12 +fi + +if [ "$command" == "update" ];then + 351elec-upgrade + exit $? +fi + +if [[ "$command" == "wifi" ]]; then + ssid="$3" + psk="$4" + + if [[ "$mode" == "enable" ]]; then + echo "configure wifi" >> $log + mkdir -p "/storage/.cache/connman" || exit 1 + cat > "/storage/.cache/connman/wifi.config" <> "/storage/.cache/connman/wifi.config" + fi + # Power up the WIFI device + if [ "$(cat /sys/firmware/devicetree/base/model)" == "Anbernic RG552" ]; then + echo 1 > /sys/class/gpio/gpio113/value + else + echo 1 > /sys/class/gpio/gpio5/value + fi + sleep 3 + connmanctl enable wifi || exit 1 + connmanctl scan wifi || exit 1 + exit 0 + fi + if [[ "$mode" =~ "start" ]]; then + if [[ "$mode" != "forcestart" ]]; then + settingsWlan="`$systemsetting -command load -key wifi.enabled`" + if [ "$settingsWlan" != "1" ];then + exit 1 + fi + fi + # Power up the WIFI device + if [ "$(cat /sys/firmware/devicetree/base/model)" == "Anbernic RG552" ]; then + echo 1 > /sys/class/gpio/gpio113/value + else + echo 1 > /sys/class/gpio/gpio5/value + fi + sleep 3 + connmanctl enable wifi || exit 1 + connmanctl scan wifi || exit 1 + exit 0 + fi + if [[ "$mode" == "disable" ]]; then + connmanctl disable wifi + # Power down the WIFI device + if [ "$(cat /sys/firmware/devicetree/base/model)" == "Anbernic RG552" ]; then + echo 0 > /sys/class/gpio/gpio113/value + else + echo 0 > /sys/class/gpio/gpio5/value + fi + exit $? + fi + if [[ "$mode" == "list" ]]; then + WAVAILABLE=$(connmanctl services | cut -b 5- | sed -e s+'^\([^ ]*\).*$'+'\1'+ | grep -vE '^Wired$|^$') + if test -n "${ssid}" + then + echo "${WAVAILABLE}" | grep -qE '^'"${ssid}"'$' || echo "${ssid}" + fi + echo "${WAVAILABLE}" + exit 0 + fi +fi + +if [[ "$command" == "storage" ]]; then + exit 0; +fi + +if [[ "$command" == "forgetBT" ]]; then + killall -9 hcitool + systemctl stop bluetooth + rm -rf /storage/.cache/bluetooth/* + systemctl start bluetooth + exit 0 +fi + +if [ "$command" == "tz" ];then + if test "$mode" == "" + then + cat /storage/.config/distribution/configs/tz + else + if test -f "/usr/share/zoneinfo/${mode}" + then + echo "TIMEZONE=${mode}" > /storage/.cache/timezone + systemctl restart tz-data.service + fi + fi + exit $? +fi + +exit 10 diff --git a/usr/bin/batocera-scraper b/usr/bin/batocera-scraper new file mode 100755 index 00000000..d9ead6ff --- /dev/null +++ b/usr/bin/batocera-scraper @@ -0,0 +1,84 @@ +#!/bin/bash + +# If we are on Steam Deck +arch=$(cat /storage/.config/.OS_ARCH) +if [ $arch == "DECK" ];then + INSTALL_DIR="~/retrodeck" + +systemsetting=$INSTALL_DIR+"/usr/bin/batocera-settings" +syslang=$($systemsetting -command load -key system.language) +IMGSTYLE=$($systemsetting -command load -key scrapper.style) + +if test $# = 1 +then + DOSYS=$1 +fi + +# supported languages : en, fr, es, de, pt +case "${syslang}" in + fr_FR) + sslang=fr,en + ;; + es_ES) + sslang=es,en + ;; + de_DE) + sslang=de,en + ;; + pt_PT) + sslang=pt,en + ;; + pt_BR) + sslang=pt,en + ;; + *) + sslang=en +esac + +if test -z "${IMGSTYLE}" +then + IMGSTYLE="b,f,a,l,3b,s" +fi + +do_scrap() { + LRDIR=$1 + NF=$(ls "${LRDIR}" | grep -vE '\.txt$|\.xml$' | wc -l) + if test "${NF}" -gt 0 + then + BASEDIR=$(basename "${LRDIR}") + echo "GAME: system ${BASEDIR}" + EXTRAOPT= + + for x in "mame" "fba" "fba_libretro" "neogeo" + do + test "${LRDIR}" = $INSTALL_DIR+"/storage/roms/${x}" && EXTRAOPT="-mame" + done + + (cd "${LRDIR}" && sselph-scraper -console_src ss,gdb,ovgdb -lang "${sslang}" -console_img "${IMGSTYLE}" -download_videos -workers 5 ${EXTRAOPT}) 2>&1 + fi +} + +# find system to scrape +(if test -n "${DOSYS}" + then + test -d $INSTALL_DIR+"/storage/roms/${DOSYS}" && echo $INSTALL_DIR+"/storage/roms/${DOSYS}" + else + find /storage/roms -maxdepth 1 -mindepth 1 -type d + fi) | + while read RDIR1 + do + # read the 2 next dir + read RDIR2 + read RDIR3 + read RDIR4 + + do_scrap "${RDIR1}" & + test -n "${RDIR2}" && do_scrap "${RDIR2}" & + test -n "${RDIR3}" && do_scrap "${RDIR3}" & + test -n "${RDIR4}" && do_scrap "${RDIR4}" & + wait + + done + +# synchronize to not make the usb/sdcard slowing down once finnished +sync diff --git a/usr/bin/batocera-settings b/usr/bin/batocera-settings new file mode 100755 index 00000000..2f76e45e --- /dev/null +++ b/usr/bin/batocera-settings @@ -0,0 +1,272 @@ +#!/bin/bash + +# batocera-settings can mimic batoceraSettings.py +# goal: abolish this python script, it's useless for the sake of the load feature only +# get a more user friendly environment for setting, getting and saving keys +# +# Usage of BASE COMMAND: +# longform: --command --key --value +# +# shortform: +# +# --command load write enable disable status +# --key any key in emuelec.conf (kodi.enabled...) +# --value any alphanumerical string +# use quotation marks to avoid globbing use slashes escape special characters + +# This script reads only 1st occurrence if string and writes only to this first hit +# +# This script uses #-Character to comment values +# +# If there is a boolean value (0,1) then then enable and disable command will set the corresponding +# boolean value. + +# Examples: +# 'batocera-settings --command load --key wifi.enabled' will print out 0 or 1 +# 'batocera-settings --command write --key wifi.ssid -value "This is my NET"' will set 'wlan.ssid=This is my NET' +# 'batocera-settings enable wifi.ssid' will remove # from configfile (activate) +# 'batocera-settings disable wifi.enabled' will set key wifi.enabled=0 +# 'botocera-settings /myown/config.file --command status --key my.key' will output status of own config.file and my.key + +# by cyperghost - 2019/12/30 + +##### INITS ##### +# If we are on Steam Deck +arch=$(cat /storage/.config/.OS_ARCH) +if [ $arch == "DECK" ];then + INSTALL_DIR="~/retrodeck" + +BATOCERA_CONFIGFILE=$INSTALL_DIR+"/storage/.config/distribution/configs/distribution.conf" +COMMENT_CHAR_SEARCH="[#|;]" +COMMENT_CHAR="#" +##### INITS ##### + +##### Function Calls ##### + +function get_config() { + #Will search for key.value and #key.value for only one occurrence + #If the character is the COMMENT CHAR then set value to it + #Otherwise strip till the equal-char to obtain value + local val + local ret + val="$(grep -E -m1 "^\s*$1\s*=" $BATOCERA_CONFIGFILE)" + ret=$? + if [[ $ret -eq 1 ]]; then + val="$(grep -E -m1 "^$COMMENT_CHAR_SEARCH\s*$1\s*=" $BATOCERA_CONFIGFILE)" + ret=$? + [[ $ret -eq 0 ]] && val=$COMMENT_CHAR + else + #Maybe here some finetuning to catch key.value = ENTRY without blanks + val="${val#*=}" + fi + echo "$val" + return $ret +} + +function set_config() { + #Will search for first key.name at beginning of line and write value to it + sed -i "1,/^\(\s*$1\s*=\).*/s//\1$2/" "$BATOCERA_CONFIGFILE" +} + +function uncomment_config() { + #Will search for first Comment Char at beginning of line and remove it + sed -i "1,/^$COMMENT_CHAR_SEARCH\(\s*$1\)/s//\1/" "$BATOCERA_CONFIGFILE" +} + +function comment_config() { + #Will search for first key.name at beginning of line and add a comment char to it + sed -i "1,/^\(\s*$1\)/s//$COMMENT_CHAR\1/" "$BATOCERA_CONFIGFILE" +} + +function check_argument() { + # This method does not accept arguments starting with '-'. + if [[ -z "$2" || "$2" =~ ^- ]]; then + echo >&2 + echo "ERROR: '$1' is missing an argument." >&2 + echo >&2 + echo "Just type '$0' to see usage page." >&2 + echo >&2 + return 1 + fi +} + +function dash_style() { + #This function is needed to "simulate" the python script with single dash + #commands. It will also accept the more common posix double dashes + #Accept dashes and double dashes and build new array ii with parameter set + #The else-branch can be used for the shortform + + for i in --command --key --value; do + if [[ -z "$1" ]]; then + continue + elif [[ "$i" =~ ^-{0,1}"${1,,}" ]]; then + check_argument $1 $2 + [[ $? -eq 0 ]] || exit 1 + ii+=("$2") + shift 2 + else + ii+=("$1") + shift 1 + fi + done +} + + +function usage() { +val=" Usage of BASE COMMAND: + + --command --key --value + + shortform: + + --command load write enable disable status + --key any key in emuelec.conf (kodi.enabled...) + --value any alphanumerical string + use quotation marks to avoid globbing + + For write command --value must be provided + + exit codes: exit 0 = value is available, proper exit + exit 1 = general error + exit 2 = file error + exit 10 = value found, but empty + exit 11 = value found, but not activated + exit 12 = value not found + + If you don't set a filename then default is '~/storage/.config/distribution.conf'" + +echo "$val" + +} +##### Function Calls ##### + +##### MAIN FUNCTION ##### +function main() { + + #Filename parsed? + if [[ -f "$1" ]]; then + BATOCERA_CONFIGFILE="$1" + shift + else + [[ -f "$BATOCERA_CONFIGFILE" ]] || { echo "not found: $BATOCERA_CONFIGFILE" >&2; exit 2; } + fi + + #How much arguments are parsed, up to 6 then it is the long format + #up to 3 then it is the short format + if [[ ${#@} -eq 0 || ${#@} -gt 6 ]]; then + usage + exit 1 + else + dash_style "$@" + command="${ii[0]}" + keyvalue="${ii[1]}" + newvalue="${ii[2]}" + unset ii + fi + + [[ -z $keyvalue ]] && { echo "error: Please provide a proper keyvalue" >&2; exit 1; } + + # value processing, switch case + case "${command,,}" in + + "read"|"get"|"load") + val="$(get_config $keyvalue)" + ret=$? + [[ "$val" == "$COMMENT_CHAR" ]] && exit 11 + [[ -z "$val" && $ret -eq 0 ]] && exit 10 + [[ -z "$val" && $ret -eq 1 ]] && exit 12 + [[ -n "$val" ]] && echo "$val" && exit 0 + ;; + + "stat"|"status") + val="$(get_config $keyvalue)" + ret=$? + [[ -f "$BATOCERA_CONFIGFILE" ]] && echo "ok: found '$BATOCERA_CONFIGFILE'" >&2 || echo "error: not found '$BATOCERA_CONFIGFILE'" >&2 + [[ -w "$BATOCERA_CONFIGFILE" ]] && echo "ok: r/w file '$BATOCERA_CONFIGFILE'" >&2 || echo "error: r/o file '$BATOCERA_CONFIGFILE'" >&2 + [[ -z "$val" && $ret -eq 1 ]] && echo "error: '$keyvalue' not found!" >&2 + [[ -z "$val" && $ret -eq 0 ]] && echo "error: '$keyvalue' is empty - use 'comment' command to retrieve" >&2 + [[ "$val" == "$COMMENT_CHAR" ]] && echo "error: '$keyvalue' is commented $COMMENT_CHAR!" >&2 && val= + [[ -n "$val" ]] && echo "ok: '$keyvalue' $val" + exit 0 + ;; + + "set"|"write"|"save") + #Is file write protected? + [[ -w "$BATOCERA_CONFIGFILE" ]] || { echo "r/o file: $BATOCERA_CONFIGFILE" >&2; exit 2; } + #We can comment line above to erase keys, it's much saver to check if a value is setted + [[ -z "$newvalue" ]] && echo "error: '$keyvalue' needs value to be setted" >&2 && exit 1 + + val="$(get_config $keyvalue)" + ret=$? + if [[ "$val" == "$COMMENT_CHAR" ]]; then + echo "$keyvalue: hashed out!" >&2 + uncomment_config "$keyvalue" + set_config "$keyvalue" "$newvalue" + echo "$keyvalue: set from '$val' to '$newvalue'" >&2 + exit 0 + elif [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" >&2 + exit 12 + elif [[ "$val" != "$newvalue" ]]; then + set_config "$keyvalue" "$newvalue" + exit 0 + fi + ;; + + "uncomment"|"enable"|"activate") + val="$(get_config $keyvalue)" + ret=$? + # Boolean + if [[ "$val" == "$COMMENT_CHAR" ]]; then + uncomment_config "$keyvalue" + echo "$keyvalue: removed '$COMMENT_CHAR', key is active" >&2 + elif [[ "$val" == "0" ]]; then + set_config "$keyvalue" "1" + echo "$keyvalue: boolean set '1'" >&2 + elif [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" && exit 2 + fi + ;; + + "comment"|"disable"|"remark") + val="$(get_config $keyvalue)" + ret=$? + # Boolean + [[ "$val" == "$COMMENT_CHAR" || "$val" == "0" ]] && exit 0 + if [[ -z "$val" && $ret -eq 1 ]]; then + echo "$keyvalue: not found!" >&2 && exit 12 + elif [[ "$val" == "1" ]]; then + set_config "$keyvalue" "0" + echo "$keyvalue: boolean set to '0'" >&2 + else + comment_config "$keyvalue" + echo "$keyvalue: added '$COMMENT_CHAR', key is not active" >&2 + fi + ;; + + *) + echo "ERROR: invalid command '$command'" >&2 + exit 1 + ;; + esac +} +##### MAIN FUNCTION ##### + +##### MAIN CALL ##### + +# Prepare arrays from fob python script +# Keyword for python call is mimic_python +# Attention the unset is needed to eliminate first argument (python basefile) + +if [[ "${#@}" -eq 1 && "$1" =~ "mimic_python" ]]; then + #batoceraSettings.py fob + readarray -t arr <<< "$1" + unset arr[0] +else + #regular call by shell + arr=("$@") +fi + +main "${arr[@]}" + +##### MAIN CALL ##### diff --git a/usr/bin/runemu.py b/usr/bin/runemu.py new file mode 100755 index 00000000..32ba1400 --- /dev/null +++ b/usr/bin/runemu.py @@ -0,0 +1,405 @@ +#!/usr/bin/env python3 + +import datetime +import os +import shlex +import subprocess +import sys +from dataclasses import dataclass +from pathlib import Path +from time import perf_counter +from typing import TYPE_CHECKING, Optional + +from setsettings import set_settings + +# If we are on Steam Deck we want a prefix + +# TODO: INSTALL_DIR + '/storage/.config/.OS_ARCH' was not working, dunno why, I'll check later +# DEVICE = "DECK" #for the moment this will do + +INSTALL_DIR = os.path.expanduser('~/retrodeck') +with open(INSTALL_DIR + r'/storage/.config/.OS_ARCH', 'r') as file: + DEVICE = file.read().rstrip() + +#if DEVICE == "DECK" : +# +#else: +# INSTALL_DIR = "" + +if TYPE_CHECKING: + #These except Union are deprecated in 3.9 and should be replaced with collections.abc / builtin list type, but we have 3.8 for now + from typing import List, Mapping, MutableMapping, Sequence, Union + +LOGS_DIR = Path('/tmp/logs') +RA_TEMP_CONF = INSTALL_DIR + '/storage/.config/retroarch/retroarch.cfg' +RA_APPEND_CONF = '/tmp/raappend.cfg' +log_path = LOGS_DIR / 'exec.log' + +def call_profile_func(function_name: str, *args: str) -> str: + # if we are on Steam Deck + if DEVICE == "DECK" : + proc = subprocess.run(f'. {INSTALL_DIR}/export_func.sh', shell=True, stdout=subprocess.PIPE, check=True, text=True) + else: + #We are going to want to call some stuff from /etc/profile, they are defined in ../profile.d/99-distribution.conf + #But on Steam Deck this is not needed as these stuff is called by another script as profile.d is just for embedded distros + proc = subprocess.run(f'. /etc/profile && {shlex.quote(function_name)} {shlex.join(args)}', shell=True, stdout=subprocess.PIPE, check=True, text=True) + return proc.stdout.strip('\n') + +def get_es_setting(setting_type: str, setting_name: str) -> str: + #from es_settings.cfg (XML) + return call_profile_func('get_es_setting', setting_type, setting_name) + +log_level = get_es_setting('string', 'LogLevel') #If set to default, would equal empty string + +def jslisten_set(*exe_names: str): + #exe_names are passed as one argument, intended for killall to use them later + if DEVICE != "DECK" : + call_profile_func('jslisten', 'set', shlex.join(exe_names)) + +def jslisten_stop(): + #call_profile_func('jslisten', 'stop') + if DEVICE != "DECK" : + subprocess.check_call(['systemctl', 'stop', 'jslisten']) + +def get_elec_setting(setting_name, platform=None, rom=None): + #From distribution.conf + #Potentially this can be reimplemented in Python if that turns out to be a good idea + return call_profile_func('get_ee_setting', setting_name, platform, rom) + +def set_elec_setting(setting_name, value): + call_profile_func('set_ee_setting', setting_name, value) + +def check_bios(platform, core, emulator, game, log_path_): + call_profile_func('ee_check_bios', platform, core, emulator, game, log_path_) + +def log(text): + with log_path.open('at', encoding='utf-8') as log_file: + print(text, file=log_file) + +def cleanup_and_quit(return_code): + if log_level == 'debug': + log(f'Cleaning up and exiting with return code {return_code}') + + if DEVICE != "DECK" : + jslisten_stop() + clear_screen() + call_profile_func('normperf') + call_profile_func('set_audio', 'default') + sys.exit(return_code) + +def clear_screen(): + if DEVICE != "DECK" : + if log_level == 'debug': + log('Clearing screen') + with open('/dev/console', 'wb') as console: + subprocess.run('clear', stdout=console, check=True) + +def list_archive(path: Path) -> 'List[str]': + #7z path needs to be given explicitly, otherwise it won't find 7z.so + sevenzip_proc = subprocess.run(['/usr/bin/7z', 'l', '-slt', path], stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=False) + if sevenzip_proc.returncode != 0: + raise OSError(sevenzip_proc.stderr.strip()) + #Ignore the first Path = line which is the archive itself + return [line[len('Path = '):] for line in sevenzip_proc.stdout.splitlines() if line.startswith('Path = ')][1:] + +def extract_archive(path: Path) -> Path: + #Assume there is only one file, otherwise things get weird + inner_filename = list_archive(path)[0] + #Since save files etc may be placed in the ROM folder, we should extract there so everything still works transparently, which also helps with overrides and such + subprocess.check_call(['/usr/bin/7z', 'e', f'-o{str(path.parent)}', path, inner_filename], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL) + return path.parent.joinpath(inner_filename) + +@dataclass(frozen=True) +class StandaloneEmulator(): + jskill_name: str + args: 'Sequence[str]' + should_extract: bool = False + +standalone_emulators: 'MutableMapping[str, StandaloneEmulator]' = { + 'AMIBERRY': StandaloneEmulator('amiberry', ['/usr/bin/amiberry.start', '']), + 'AdvanceMame': StandaloneEmulator('advmame', ['/usr/bin/advmame.sh', '']), + 'HATARISA': StandaloneEmulator('hatari', ['/usr/bin/hatari.start', '']), + 'hypseus_singe': StandaloneEmulator('hypseus', ['/usr/bin/hypseus.sh', '']), + 'OPENBOR': StandaloneEmulator('openbor', ['/usr/bin/openbor.sh', '']), + 'PPSSPPSDL': StandaloneEmulator('PPSSPPSDL', ['/usr/bin/ppsspp.sh', '']), + 'SCUMMVMSA': StandaloneEmulator('scummvm', ['/usr/bin/scummvm.start', 'sa', '']), + 'drastic': StandaloneEmulator('drastic', ['/usr/bin/drastic.sh', '']), + 'ecwolf': StandaloneEmulator('ecwolf', ['/usr/bin/ecwolf.sh', '']), + 'gzdoom': StandaloneEmulator('gzdoom', ['/usr/bin/gzdoom.sh', '']), + 'lzdoom': StandaloneEmulator('lzdoom', ['/usr/bin/lzdoom.sh', '']), + 'mpv': StandaloneEmulator('mpv', ['/usr/bin/mpv_video.sh', '']), + 'pico8': StandaloneEmulator('pico8_dyn', ['/usr/bin/pico-8.sh', '']), + 'piemu': StandaloneEmulator('piemu', ['/usr/bin/bash', '-l', '/usr/bin/piemu.sh', '']), + 'raze': StandaloneEmulator('raze', ['/usr/bin/raze.sh', '']), + 'solarus': StandaloneEmulator('solarus-run', ['/usr/bin/solarus.sh', '']), +} + +def _load_customized_standalone_emulators(): + try: + with open(INSTALL_DIR + '/storage/.config/standalone_emulators', 'rt', encoding='utf-8') as f: + for line in f: + if ': ' not in line or line.startswith('#'): + continue + name, rest = line.rstrip().split(': ', 1) + args = rest.split(' ') + kill_name = name + should_extract = False + #If name of exe to kill was not listed, assume it is the same as the emulator name + if not args[0].startswith('/'): + kill_name = args[0] + args = args[1:] + if args[-1] == 'should_extract': + args = args[:-1] + should_extract = True + standalone_emulators[name] = StandaloneEmulator(kill_name, args, should_extract) + except (FileNotFoundError, ValueError): + pass + +_load_customized_standalone_emulators() + +class EmuRunner(): + def __init__(self, rom: Optional[Path], platform: Optional[str], emulator: Optional[str], core: Optional[str], args: 'Mapping[str, str]') -> None: + self.rom = rom + self.platform = platform + self.emulator = emulator + self.core = core + self.args = args + self.temp_files: 'List[Path]' = [] #Files that we extracted from archives, etc. to clean up later + self.environment = os.environ.copy() + + def download_things_if_needed(self) -> None: + if self.core == 'freej2me': + #freej2me needs the JDK to be downloaded on the first run + subprocess.run(INSTALL_DIR + '/usr/bin/freej2me.sh', check=True) + self.environment['JAVA_HOME']=INSTALL_DIR + '/storage/jdk' + self.environment['PATH'] = INSTALL_DIR + '/storage/jdk/bin:' + os.environ['PATH'] + elif self.core == 'easyrpg': + # easyrpg needs runtime files to be downloaded on the first run + subprocess.run(INSTALL_DIR + '/usr/bin/easyrpg.sh', check=True) + + def toggle_max_performance(self) -> None: + if get_elec_setting('maxperf', self.platform, self.rom.name if self.rom else None) == '1': + if log_level == 'debug': + log('Enabling max performance as requested') + call_profile_func('maxperf') + else: + call_profile_func('normperf') + + def set_settings(self) -> str: + rom_name = str(self.rom) if self.rom else '' + core = self.core if self.core else '' + platform = self.platform if self.platform else '' + return set_settings(rom_name, core, platform, controllers=self.args.get('controllers', ''), autosave=self.args.get('autosave', ''), snapshot=self.args.get('state_slot', '')) + + def get_standalone_emulator_command(self) -> 'Sequence[Union[str, Path]]': + if not self.emulator: + raise ValueError('runemu.py was called improperly, tried to launch a standard emulator with no emulator') + if log_level != 'minimal': + log('Running a standalone emulator:') + log(f'platform: {self.platform}') + log(f'emulator: {self.emulator}') + #Core is not actually relevant (other than Mupen64Plus which is in another function) + + emu = standalone_emulators[self.emulator] + path = self.rom + if self.rom and emu.should_extract and self.rom.suffix in {'.zip', '.7z', '.gz', '.bz2'}: + path = extract_archive(self.rom) + self.temp_files.append(path) + + command = [arg for arg in (path if arg == '' else arg for arg in emu.args) if arg] + + jslisten_set(emu.jskill_name) + return command + + def get_retroarch_command(self, shader_arg: str) -> 'Sequence[Union[str, Path]]': + if log_level != 'minimal': + log('Running a libretro core via RetroArch') + log(f'platform: {self.platform}') + log(f'core: {self.core}') + retroarch_binary = 'retroarch' + if self.core in {'pcsx_rearmed', 'parallel_n64'}: + retroarch_binary = 'retroarch32' + self.environment['LD_LIBRARY_PATH'] = '/usr/lib32' + + rom_path: 'Optional[Union[str, Path]]' = self.rom + + if self.rom: + if self.platform == 'doom' and self.rom.suffix == '.doom': + subprocess.run(['dos2unix', self.rom], check=True) #Hmmmmm but do we need that + with self.rom.open('rt', encoding='utf-8') as doomfile: + for line in doomfile: + key, _, value = line.partition('=') + if key == 'IWAD': + rom_path = value + break + if self.core == 'scummvm' and self.rom.suffix == '.scummvm': + #ScummVM libretro core actually only works with .scummvm files that just have the game ID with no path specified, which isn't how they are generated by the scummvm scanner script + #But if you give it any other path to a file, it will autodetect a game inside that file's parent directory, even if the file doesn't actually exist + #This would otherwise be what /usr/bin/scummvm.start tries to do when its first arg is "libretro", by cd'ing into that game directory + path = Path(self.rom.read_text(encoding='utf-8').split('"')[1]) + rom_path = path / 'game' + + jslisten_set(retroarch_binary) + command: 'List[Union[str, Path]]' = [os.path.join('/usr/bin/', retroarch_binary), '-L', Path('/tmp/cores/', f'{self.core}_libretro.so')] + + if log_level != 'minimal': + command.append('--verbose') + + if 'host' in self.args or 'connect' in self.args: + netplay_nick = get_elec_setting('netplay.nickname') + if not netplay_nick: + netplay_nick = '351ELEC' + if 'connect' in self.args: + set_elec_setting('netplay.client.port', self.args['port']) + set_elec_setting('netplay.client.ip', self.args['connect']) #We should now have parsed that properly so it's just a hostname/IP address, no --port argument + command += ['--connect', self.args['connect'] + '|' + self.args['port']] + if 'host' in self.args: + command += ['--host', self.args['host']] + + command += ['--nick', netplay_nick] + + if self.core == 'fbneo' and self.platform == 'neocd': + command += ['--subsystem', self.platform] + if shader_arg: + #Returned from setsettings, this is of the form "--shader-set /tmp/shaders/blahblahblah", apparently actually needed even if video_shader is set in RA_APPEND_CONF + command += shlex.split(shader_arg) + command += ['--config', RA_TEMP_CONF, '--appendconfig', RA_APPEND_CONF] + if rom_path: + command.append(rom_path) + + return command + + def get_retrorun_command(self) -> 'Sequence[Union[str, Path]]': + if not self.rom: + raise ValueError('runemu.py was called improperly, tried to launch retrorun with no game') + if not self.platform: + raise ValueError('runemu.py was called improperly, tried to launch retrorun with no platform') + if not self.core: + raise ValueError('runemu.py was called improperly, tried to launch retrorun with no platform') + + core_path = Path('/tmp/cores/', f'{self.core}_libretro.so') + if log_level != 'minimal': + log('Running a libretro core via retrorun') + log(f'platform: {self.platform}') + log(f'core: {self.core}') + jslisten_set('retrorun', 'retrorun32') + + path = self.rom + if self.rom.suffix in {'.zip', '.7z', '.gz', '.bz2'} and self.platform not in {'arcade', 'naomi', 'atomiswave', 'fbneo', 'mame'}: + path = extract_archive(self.rom) + self.temp_files.append(path) + + return [INSTALL_DIR + '/usr/bin/retrorun.sh', core_path, path, self.platform] + + def get_mupen64plus_standalone_command(self) -> 'Sequence[Union[str, Path]]': + if not self.rom: + raise ValueError('runemu.py was called improperly, tried to launch Mupen64Plus standalone with no video plugin') + if not self.core: + raise ValueError('runemu.py was called improperly, tried to launch Mupen64Plus standalone with no video plugin') + if log_level != 'minimal': + log(f'Running Mupen64Plus standalone with {self.core} video plugin') + jslisten_set('mupen64plus') + path = self.rom + if self.rom.suffix in {'.zip', '.7z', '.gz', '.bz2'}: + path = extract_archive(self.rom) + self.temp_files.append(path) + + return [INSTALL_DIR + '/usr/bin/m64p.sh', self.core, path] + + def get_command(self, shader_arg: str='') -> 'Sequence[Union[str, Path]]': + is_libretro_port = self.core and not self.emulator + #If true this was called from the inside of a port .sh that runs a libretro port (e.g. 2048, tyrQuake, etc), it makes no sense otherwise + + if self.rom and (self.rom.suffix == '.sh' or self.platform == 'tools'): + #If the ROM is a shell script then just execute it (tools, ports, Pico-8 splore, ScummVM scanner, etc) + return ['/usr/bin/bash', '-l', self.rom] + elif self.emulator == 'retroarch' or is_libretro_port: + return self.get_retroarch_command(shader_arg) + elif self.emulator == 'retrorun': + return self.get_retrorun_command() + elif self.emulator == 'mupen64plussa': + return self.get_mupen64plus_standalone_command() + else: + return self.get_standalone_emulator_command() + + def run(self, command: 'Sequence[Union[str, Path]]') -> None: + clear_screen() + if log_level != 'minimal': + log(f'Executing game: {self.rom}') + log(f'Executing {command}') + with log_path.open('at', encoding='utf-8') as log_file: + subprocess.run(command, stdout=log_file, stderr=subprocess.STDOUT, check=True, text=True, env=self.environment) + + def cleanup_temp_files(self) -> None: + for temp_file in self.temp_files: + temp_file.unlink(missing_ok=True) + +def main(): + time_started = perf_counter() + + i = 0 + args: dict[str, str] = {} + while i < len(sys.argv)-1: + if sys.argv[i].startswith('--'): + args[sys.argv[i][2:]] = sys.argv[i + 1] + i += 1 + continue + if sys.argv[i].startswith('-'): + args[sys.argv[i][1:]] = sys.argv[i + 1] + i += 1 + continue + i += 1 + + rom = Path(args['rom']) if 'rom' in args else None + platform = args.get('platform') + core = args.get('core') + emulator = args.get('emulator') + + log_path.unlink(missing_ok=True) + LOGS_DIR.mkdir(parents=True, exist_ok=True) + log_path.touch() + + log(f'Emulation run log: Started at {datetime.datetime.now()}') + log(f'Args: {args}') + + runner = EmuRunner(rom, platform, emulator, core, args) + + runner.download_things_if_needed() + runner.toggle_max_performance() + + #Disable netplay by default + set_elec_setting('netplay.client.ip', 'disable') + set_elec_setting('netplay.client.port', 'disable') + + jslisten_stop() + + shader_arg = runner.set_settings() + command = runner.get_command(shader_arg) + if log_level != 'minimal': + log(f'Took {perf_counter() - time_started} seconds to start up') + clear_screen() + + try: + runner.run(command) + exit_code = 0 + except subprocess.CalledProcessError as cpe: + log(f'Process exited improperly with return code {cpe.returncode}') + exit_code = 1 + requires_bios = {'atari5200', 'atari800', 'atari7800', 'atarilynx', 'colecovision', 'amiga', 'amigacd32', 'o2em', 'intellivision', 'pcengine', 'pcenginecd', 'pcfx', 'fds', 'segacd', 'saturn', 'dreamcast', 'naomi', 'atomiswave', 'x68000', 'neogeo', 'neogeocd', 'msx', 'msx2', 'sc-3000'} + if platform in requires_bios: + if platform == 'msx2': + platform_to_check = 'msx2' + elif platform == 'pcenginecd': + platform_to_check = 'pcengine' + elif platform == 'amigacd32': + platform_to_check = 'amiga' + else: + platform_to_check = platform + check_bios(platform_to_check, core, emulator, rom, log_path) + finally: + runner.cleanup_temp_files() + cleanup_and_quit(exit_code) + + +if __name__ == '__main__': + main() diff --git a/usr/bin/setsettings.py b/usr/bin/setsettings.py new file mode 100755 index 00000000..aabdff08 --- /dev/null +++ b/usr/bin/setsettings.py @@ -0,0 +1,700 @@ +#!/usr/bin/env python3 + +# SPDX-License-Identifier: GPL-2.0-or-later +# +# setsettings.py: +# Copyright (C) 2021-present konsumschaf +# Copyright (C) 2021-present konsumlamm +# +# based on setsettings.sh: +# Copyright (C) 2019-present Shanti Gilbert (https://github.com/shantigilbert) +# Copyright (C) 2020-present Fewtarius + + +# Convert ES settings from distribution.conf to RetroArch configuration in raappend.conf. + +from argparse import ArgumentParser +from configparser import ConfigParser +from dataclasses import dataclass +from glob import iglob +import os +import random +import re +import shutil + +# If we are on Steam Deck we want a prefix +DEVICE = "DECK" +# TODO: put a real check on the .OS_ARCH file, or maybe not as we are obviously running on Deck +INSTALL_DIR = os.path.expanduser("~/retrodeck") + +# if DEVICE == "DECK" : +# +#else: +# INSTALL_DIR = "" + +# Files and Folder +ra_conf = INSTALL_DIR + "/storage/.config/retroarch/retroarch.cfg" +ra_source_conf = INSTALL_DIR + "/usr/config/retroarch/retroarch.cfg" +ra_core_conf = INSTALL_DIR + "/storage/.config/retroarch/retroarch-core-options.cfg" +ra_append_conf = "/tmp/raappend.cfg" +os_arch_conf = INSTALL_DIR + "/storage/.config/.OS_ARCH" +snapshots = INSTALL_DIR + "/storage/roms/savestates" + +# Logging +class Logger: + dir = "/tmp/logs" + file = "exec.log" + script_basename = os.path.basename(__file__) + + def __init__(self): + if not os.path.isdir(self.dir): + os.makedirs(self.dir) + self.file_handle = open(f'{self.dir}/{self.file}',"a+") + + def log(self, text: str) -> None: + self.file_handle.write(f'{self.script_basename}: {text}\n') + + def __del__(self): + self.file_handle.close() + + +# No Sections in distribution.conf, we have to fake our own +class MyConfigParser(ConfigParser): + def read(self, filename: str) -> None: + text = open(filename, encoding="utf_8").read() + self.read_string("[351elec]\n" + text, filename) + +@dataclass +class Config: + rom_name: str + platform: str + + distribution_conf = INSTALL_DIR + "/storage/.config/distribution/configs/distribution.conf" + + def __post_init__(self): + # Read the distribution.conf to a dictionary + config_parser = MyConfigParser(strict=False) + config_parser.read(self.distribution_conf) + self.config = config_parser['351elec'] + + def get_setting(self, setting: str) -> str: + """Get the settings from distribution.conf""" + + pat_rom = f'{self.platform}["{self.rom_name}"].{setting}' + pat_platform = f'{self.platform}.{setting}' + pat_global = f'global.{setting}' + + if pat_rom in self.config: + value = self.config[pat_rom] + elif pat_platform in self.config: + value = self.config[pat_platform] + elif pat_global in self.config: + value = self.config[pat_global] + else: + value = "" + + if value == "0": + value = "" + return value + + def get_bool_string(self, setting: str) -> str: + """For readability a function that returns "true" and "false" directly.""" + + if self.get_setting(setting): + return "true" + else: + return "false" + +# Delete lines from a config file +def delete_lines(file_path: str, lines: tuple) -> None: + with open(file_path, "r") as input: + tmp_file = f'/tmp/{os.path.basename(file_path)}.tmp' + with open(tmp_file, "w") as output: + for line in input: + write_this_line = True + for item in lines: + if line.strip().startswith(item): + write_this_line = False + break + if write_this_line: + output.write(line) + # replace file with original name + shutil.move(tmp_file, file_path) + +# Append dictionary to the end of a file +def write_file(file_path: str, dictionary: dict, separator: str = ' = ', quote_sign: str = '"') -> None: + os.makedirs(os.path.dirname(file_path), exist_ok=True) + with open(file_path, "a") as file: + for (key, value) in dictionary.items(): + file.write(f'{key}{separator}{quote_sign}{value}{quote_sign}\n') + +# Generate the config out of the distribution.conf +def set_settings(rom_name: str, core: str, platform: str, controllers: str, autosave: str, snapshot: str) -> str: + logger = Logger() + shader_path = '' + + # + # Do some checks and clean up first + # + + # Log current call: + logger.log(f'ROM: {rom_name}') + logger.log(f'Platform: {platform}') + logger.log(f'Core: {core}') + logger.log(f'Controllers: {controllers}') + logger.log(f'Autosave: {autosave}') + logger.log(f'Snapshot: {snapshot}') + + # We only need the ROM, but we get the fullpath + rom_name = os.path.basename(rom_name) + # Delete any existing raappend.cfg first + if os.path.isfile(ra_append_conf): + os.remove(ra_append_conf) + # Restore retroarch.cfg if it is missing or empty + if not os.path.isfile(ra_conf) or os.stat(ra_conf).st_size == 0: + shutil.copy(ra_source_conf,ra_conf) + + # Get the Device Name + with open(os_arch_conf, encoding="utf-8") as f: + device_name = f.readline().strip() + logger.log(f'Device: {device_name}') + + # Is the CORE 32 or 64bit? + if core in {'pcsx_rearmed', 'parallel_n64'}: + bits='32bit' + else: + bits='64bit' + logger.log(f'core is {bits}') + + # Dictionary for the raappend.cfg + ra_append_dict = {} + + # Create config from distribution.conf + config = Config(rom_name, platform) + + # + # Global configuration directly in retroarch.cfg + # + + # RA menu rgui, ozone, glui or xmb (fallback if everthing else fails) + # if empty (auto in ES) do nothing to enable configuration in RA + if menu_driver := config.get_setting('retroarch.menu_driver'): + ra_dict = {} + # delete setting only if we set new ones + # therefore configuring in RA is still possible + delete_lines(ra_conf, ('menu_driver', 'menu_linear_filter')) + if menu_driver == 'rgui': + ra_dict['menu_driver'] = 'rgui' + ra_dict['menu_linear_filter'] = 'true' + elif menu_driver == 'ozone': + ra_dict['menu_driver'] = 'ozone' + elif menu_driver == 'glui': + ra_dict['menu_driver'] = 'glui' + else: + # play it save and set xmb if nothing else matches + ra_dict['menu_driver'] = 'xmb' + write_file(ra_conf, ra_dict) + + # + # Convert the settings from distribution.conf to raappend.cfg + # + + # FPS + ra_append_dict['fps_show'] = config.get_bool_string("showFPS") + + # Retroachievements / Cheevos + retro_achievements = { + 'arcade', 'atari2600', 'atari7800', 'atarilynx', 'colecovision', + 'famicom', 'fbn', 'fds', 'gamegear', 'gb', 'gba', 'gbah', 'gbc', 'gbch', + 'gbh', 'genesis', 'genh', 'ggh', 'intellivision', 'mastersystem', + 'megacd', 'megadrive', 'megadrive-japan', 'msx', 'msx2', 'n64', + 'neogeo', 'neogeocd', 'nes', 'nesh', 'ngp', 'ngpc', 'odyssey2', + 'pcengine', 'pcenginecd', 'pcfx', 'pokemini', 'psp', 'psx', 'sega32x', + 'segacd', 'sfc', 'sg-1000', 'snes', 'snesh', 'snesmsu1', 'supergrafx', + 'supervision', 'tg16', 'tg16cd', 'vectrex', 'virtualboy', 'wonderswan', + 'wonderswancolor', + } + if platform in retro_achievements: + if config.get_setting("retroachievements"): + ra_append_dict['cheevos_enable'] = "true" + ra_append_dict['cheevos_username'] = config.get_setting("retroachievements.username") + ra_append_dict['cheevos_password'] = config.get_setting("retroachievements.password") + ra_append_dict['cheevos_hardcore_mode_enable'] = config.get_bool_string("retroachievements.hardcore") + value = config.get_setting("retroachievements.leaderboards") + if value == "enabled": + ra_append_dict['cheevos_leaderboards_enable'] = "true" + elif value == "trackers only": + ra_append_dict['cheevos_leaderboards_enable'] = "trackers" + elif value == "notifications only": + ra_append_dict['cheevos_leaderboards_enable'] = "notifications" + else: + ra_append_dict['cheevos_leaderboards_enable'] = "false" + ra_append_dict['cheevos_verbose_enable'] = config.get_bool_string("retroachievements.verbose") + ra_append_dict['cheevos_auto_screenshot'] = config.get_bool_string("retroachievements.screenshot") + ra_append_dict['cheevos_richpresence_enable'] = config.get_bool_string("retroachievements.richpresence") + ra_append_dict['cheevos_challenge_indicators'] = config.get_bool_string("retroachievements.challengeindicators") + ra_append_dict['cheevos_test_unofficial'] = config.get_bool_string("retroachievements.testunofficial") + ra_append_dict['cheevos_badges_enable'] = config.get_bool_string("retroachievements.badges") + ra_append_dict['cheevos_start_active'] = config.get_bool_string("retroachievements.active") + ra_append_dict['cheevos_unlock_sound_enable'] = config.get_bool_string("retroachievements.soundenable") + else: + ra_append_dict['cheevos_enable'] = "false" + ra_append_dict['cheevos_username'] = "" + ra_append_dict['cheevos_password'] = "" + ra_append_dict['cheevos_hardcore_mode_enable'] = "false" + ra_append_dict['cheevos_leaderboards_enable'] = "false" + ra_append_dict['cheevos_verbose_enable'] = "false" + ra_append_dict['cheevos_test_unofficial'] = "false" + ra_append_dict['cheevos_unlock_sound_enable'] = "false" + ra_append_dict['cheevos_auto_screenshot'] = "false" + ra_append_dict['cheevos_badges_enable'] = "false" + ra_append_dict['cheevos_start_active'] = "false" + ra_append_dict['cheevos_richpresence_enable'] = "false" + ra_append_dict['cheevos_challenge_indicators'] = "false" + + # Netplay + if config.get_setting("netplay"): + ra_append_dict['netplay'] = "true" + # Not needed any more? + ## Disable Cheevos Hardcore Mode to allow savestates + #if 'cheevos_hardcore_mode_enable' in ra_append_dict: + # ra_append_dict['cheevos_hardcore_mode_enable'] = "false" + # Host or Client + value = config.get_setting('netplay.mode') + if value == 'host': + ra_append_dict['netplay_mode'] = "false" + ra_append_dict['netplay_client_swap_input'] = "false" + ra_append_dict['netplay_ip_port'] = config.get_setting('netplay.port') + elif value == 'client': + ra_append_dict['netplay_mode'] = "true" + ra_append_dict['netplay_ip_address'] = config.get_setting('netplay.client.ip') + ra_append_dict['netplay_ip_port'] = config.get_setting('netplay.client.port') + ra_append_dict['netplay_client_swap_input'] = "true" + # Relay + if value := config.get_setting('netplay.relay'): + ra_append_dict['netplay_use_mitm_server'] = "true" + ra_append_dict['netplay_mitm_server'] = value + else: + ra_append_dict['netplay_use_mitm_server'] = "false" + ra_append_dict['netplay_delay_frames'] = config.get_setting('netplay.frames') + ra_append_dict['netplay_nickname'] = config.get_setting('netplay.nickname') + # spectator mode + ra_append_dict['netplay_spectator_mode_enable'] = config.get_bool_string("netplay.spectator") + ra_append_dict['netplay_public_announce'] = config.get_bool_string("netplay_public_announce") + else: + ra_append_dict['netplay'] = "false" + + # AI Translation Service + if config.get_setting('ai_service_enabled'): + ra_append_dict['ai_service_enable'] = "true" + LangCodes = { + "false": "0", "En": "1", "Fr": "3", "Pt": "49", "De": "5", + "El": "30", "Es": "2", "Cs": "8", "Da": "9", "Hr": "11", "Hu": "35", + "It": "4", "Ja": "6", "Ko": "12", "Nl": "7", "Nn": "46", "Po": "48", + "Ro": "50", "Ru": "51", "Sv": "10", "Tr": "59", "Zh": "13", + } + ai_lang = config.get_setting('ai_target_lang') + if ai_lang in LangCodes: + ra_append_dict['ai_service_target_lang'] = f'{LangCodes[ai_lang]}' + else: + # use English as default + ra_append_dict['ai_service_target_lang'] = "1" + if ai_url := config.get_setting('ai_service_url'): + ra_append_dict['ai_service_url'] = f'{ai_url}&mode=Fast&output=png&target_lang={ai_lang}' + else: + ra_append_dict['ai_service_url'] = f'http://ztranslate.net/service?api_key=BATOCERA&mode=Fast&output=png&target_lang={ai_lang}' + else: + ra_append_dict['ai_service_enable'] = "false" + + # + # Global/System/Game specific settings + # + + # Ratio + # default to 22 (core provided) if case anything goes wrong + ra_append_dict['aspect_ratio_index'] = "22" + if ratio := config.get_setting('ratio'): + index_rations = { + '4/3': '0', '16/9': '1', '16/10': '2', '16/15': '3', '21/9': '4', + '1/1': '5', '2/1': '6', '3/2': '7', '3/4': '8', '4/1': '9', + '9/16': '10', '5/4': '11', '6/5': '12', '7/9': '13', '8/3': '14', + '8/7': '15', '19/12': '16', '19/14': '17', '30/17': '18', + '32/9': '19', 'config': '20', 'squarepixel': '21', 'core': '22', + 'custom': '23', 'full' : '24', + } + if ratio in index_rations: + ra_append_dict['aspect_ratio_index'] = index_rations[ratio] + + # Bilinear filtering + ra_append_dict['video_smooth'] = config.get_bool_string("smooth") + + # Video Integer Scale + ra_append_dict['video_scale_integer'] = config.get_bool_string("integerscale") + + # Video Integer Scale Overscale + ra_append_dict['video_scale_integer_overscale'] = config.get_bool_string("integerscaleoverscale") + + # RGA Scaling / CTX Scaling + ra_append_dict['video_ctx_scaling'] = config.get_bool_string("rgascale") + + # Shaderset + if shaderset := config.get_setting('shaderset'): + ra_append_dict['video_shader_enable'] = "true" + ra_append_dict['video_shader'] = shaderset + # We need to print the shader folder for runemu.sh to use it + shader_path = f'--set-shader /tmp/shaders/{shaderset}' + else: + ra_append_dict['video_shader_enable'] = "false" + ra_append_dict['video_shader'] = "" + + # Filters + # Set correct path for video- and audio-filters depending on 32/64bit + ra_append_dict['audio_filter_dir'] = f'/usr/share/retroarch/filters/{bits}/audio' + ra_append_dict['video_filter_dir'] = f'/usr/share/retroarch/filters/{bits}/video' + # Filterset + if filterset := config.get_setting('filterset'): + # Filter do not work with RGA/CTX enabled + ra_append_dict['video_ctx_scaling'] = "false" + ra_append_dict['video_filter'] = f'/usr/share/retroarch/filters/{bits}/video/{filterset}' + else: + ra_append_dict['video_filter'] = "" + + # Rewind + no_rewind = {'sega32x', 'psx', 'zxspectrum', 'odyssey2', 'mame', 'n64', 'dreamcast', 'atomiswave', 'naomi', 'neogeocd', 'saturn', 'psp', 'pspminis'} + if config.get_setting('rewind') and platform not in no_rewind: + ra_append_dict['rewind_enable'] = "true" + else: + ra_append_dict['rewind_enable'] = "false" + + # Saves + # Incrementalsavestates + if config.get_setting('incrementalsavestates'): + ra_append_dict['savestate_auto_index'] = "true" + ra_append_dict['savestate_max_keep'] = "0" + else: + ra_append_dict['savestate_auto_index'] = "false" + ra_append_dict['savestate_max_keep'] = "50" + # Autosave + if config.get_setting('autosave'): + ra_append_dict['savestate_auto_save'] = "true" + ra_append_dict['savestate_auto_load'] = "true" + else: + ra_append_dict['savestate_auto_save'] = "false" + ra_append_dict['savestate_auto_load'] = "false" + # Snapshots + ra_append_dict['savestate_directory'] = f'{snapshots}/{platform}' + if snapshot: + if autosave == "1": + ra_append_dict['savestate_auto_load'] = "true" + ra_append_dict['savestate_auto_save'] = "true" + else: + ra_append_dict['savestate_auto_load'] = "false" + ra_append_dict['savestate_auto_save'] = "false" + ra_append_dict['state_slot'] = f'{snapshot}' + + # Runahead + # Runahead 1st Instance + no_run_ahead = {'psp', 'sega32x', 'n64', 'dreamcast', 'atomiswave', 'naomi', 'neogeocd', 'saturn'} + if (runahead := config.get_setting('runahead')) and platform not in no_run_ahead: + ra_append_dict['run_ahead_enabled'] = "true" + ra_append_dict['run_ahead_frames'] = runahead + else: + ra_append_dict['run_ahead_enabled'] = "false" + ra_append_dict['run_ahead_frames'] = "1" + # Runahead 2nd Instance + if config.get_setting('secondinstance') and platform not in no_run_ahead: + ra_append_dict['run_ahead_secondary_instance'] = "true" + else: + ra_append_dict['run_ahead_secondary_instance'] = "false" + + # Auto Frame Relay + ra_append_dict['video_frame_delay_auto'] = config.get_bool_string("video_frame_delay_auto") + + # maxperf / CPU Governor + if config.get_setting('maxperf'): + ra_append_dict['cpu_scaling_mode'] = '2' + else: + ra_append_dict['cpu_scaling_mode'] = '4' + + # + # Settings for special cores + # + + ## atari800 core needs other settings when emulation atari5200 + if core == 'atari800': + logger.log('Atari 800 section') + retrocore_dict = {} + atari800_dict = {} + atari_dict = {} + atari_conf = INSTALL_DIR + '/storage/.config/distribution/configs/atari800.cfg' + atari800_conf = INSTALL_DIR + '/storage/.config/retroarch/config/Atari800/Atari800.opt' + delete_lines(ra_core_conf, ('atari800_system =',)) + delete_lines(atari_conf, ('RAM_SIZE', 'STEREO_POKEY', 'BUILTIN_BASIC')) + if os.path.isfile(atari800_conf): + delete_lines(atari800_conf, ('atari800_system',)) + if platform == 'atari5200': + retrocore_dict['atari800_system'] = '5200' + atari800_dict['atari800_system'] = '5200' + atari_dict['RAM_SIZE'] = '16' + atari_dict['STEREO_POKEY'] = '0' + atari_dict['BUILTIN_BASIC'] = '0' + else: + retrocore_dict['atari800_system'] = '800XL (64K)' + atari800_dict['atari800_system'] = '800XL (64K)' + atari_dict['RAM_SIZE'] = '64' + atari_dict['STEREO_POKEY'] = '1' + atari_dict['BUILTIN_BASIC'] = '1' + write_file(ra_core_conf, retrocore_dict) + # The format of the atari800.cfg is different + # ('key=value' instead of 'key = "value"') + write_file(atari_conf, atari_dict, separator='=', quote_sign='') + write_file(atari800_conf, atari800_dict) + + # Gambatte + if core == 'gambatte': + logger.log('Gambatte section') + gambatte_dict = {} + gambatte_conf = INSTALL_DIR + "/storage/.config/retroarch/config/Gambatte/Gambatte.opt" + + if os.path.isfile(gambatte_conf): + delete_lines(gambatte_conf, ('gambatte_gb_colorization', 'gambatte_gb_internal_palette')) + else: + gambatte_dict['gambatte_gbc_color_correction'] = 'disabled' + + colorization = config.get_setting('renderer.colorization') + logger.log(f'gambatte colorization: {colorization}') + if not colorization or colorization == 'auto': + gambatte_dict['gambatte_gb_colorization'] = 'disabled' + elif colorization == 'Best Guess': + gambatte_dict['gambatte_gb_colorization'] = 'auto' + elif colorization == 'GBC' or colorization == 'SGB': + gambatte_dict['gambatte_gb_colorization'] = colorization + else: + gambatte_dict['gambatte_gb_colorization'] = 'internal' + gambatte_dict['gambatte_gb_internal_palette'] = colorization + + write_file(gambatte_conf, gambatte_dict) + + # + # Controllers + # + # We set up the controller index + if controllers: + for player in range(1,6): + logger.log(f'Controller section {player}') + if pindex := re.search(fr'p{player}index\s+([0-9]+)', controllers): + ra_append_dict['input_player{player}_joypad_index'] = pindex.group(1) + # Setting controller type for different cores + if platform == "atari5200": + ra_append_dict['input_libretro_device_p{player}'] = '513' + + # + # Bezels / Decorations + # + # List of possible Bezel Folders + bezel_dir = ('/tmp/overlays/bezels', INSTALL_DIR + '/storage/roms/bezels') + # Define the resolutions of the different systems (0:x 1:y 2:width 3:height) as seen in Scaling -> Aspect Ration -> Custom + # Devices (width x hight) + # RG351P/M = 480x320 + # RG351V/MP = 640x480 + # RG552 = 1920x1152 + # DECK = 1280x800 + # Consoles (width x hight) + # GB/GBC/GG = 160x144 + # supervision = 160x160 + # Pokemini = 96x64 + # ngp/ngpc = 160x152 + # wonderswan/wonderswancolor = 224×144 + if device_name == "RG351P": + system_viewport = { + 'standard': (1, 1, 479, 319), # max-1 + 'gb': (80, 16, 320, 288), # x2 + 'gbh': (80, 16, 320, 288), # x2 + 'gbc': (80, 16, 320, 288), # x2 + 'gbch': (80, 16, 320, 288), # x2 + 'supervision': (80, 0, 320, 320), # x2 + 'gamegear': (80, 16, 320, 288), # x2 + 'ggh': (80, 16, 320, 288), # x2 + 'pokemini': (96, 64, 288, 192), # x3 + 'ngp': (80, 8, 320, 304), # x2 + 'ngpc': (80, 8, 320, 304), # x2 + 'wonderswan': (16, 16, 448, 288), # x2 + 'wonderswancolor': (16, 16, 448, 288), # x2 + } + elif device_name == "RG351V" or device_name == "RG351MP": + system_viewport = { + 'standard': (1, 1, 639, 479), # max-1 + 'gb': (80, 24, 480, 432), # x3 + 'gbh': (80, 24, 480, 432), # x3 + 'gbc': (80, 24, 480, 432), # x3 + 'gbch': (80, 24, 480, 432), # x3 + 'supervision': (80, 0, 480, 480), # x3 + 'gamegear': (80, 24, 480, 432), # x3 + 'ggh': (80, 24, 480, 432), # x3 + 'pokemini': (128, 112, 384, 256), # x4 + 'ngp': (80, 12, 480, 456), # x3 + 'ngpc': (80, 12, 480, 456), # x3 + 'wonderswan': (96, 96, 448, 288), # x2 + 'wonderswancolor': (96, 96, 448, 288), # x2 + } + elif device_name == "RG552": + system_viewport = { + 'standard': (1, 1, 1919, 1151), # max-1 + 'gb': (320, 0, 1280, 1152), # x8 + 'gbh': (320, 0, 1280, 1152), # x8 + 'gbc': (320, 0, 1280, 1152), # x8 + 'gbch': (320, 0, 1280, 1152), # x8 + 'supervision': (400, 16, 1120, 1120), # x7 + 'gamegear': (320, 0, 1280, 1152), # x8 + 'ggh': (320, 0, 1280, 1152), # x8 + 'pokemini': (384, 192, 1152, 768), # x12 + 'ngp': (400, 44, 1120, 1064), # x7 + 'ngpc': (400, 44, 1120, 1064), # x7 + 'wonderswan': (64, 0, 1792, 1152), # x8 + 'wonderswancolor': (64, 0, 1792, 1152), # x8 + } + elif device_name == "DECK": + #just copied from 552, I have to edit this + system_viewport = { + 'standard': (1, 1, 1279, 799), # max-1 + 'gb': (320, 0, 1280, 1152), # x8 + 'gbh': (320, 0, 1280, 1152), # x8 + 'gbc': (320, 0, 1280, 1152), # x8 + 'gbch': (320, 0, 1280, 1152), # x8 + 'supervision': (400, 16, 1120, 1120), # x7 + 'gamegear': (320, 0, 1280, 1152), # x8 + 'ggh': (320, 0, 1280, 1152), # x8 + 'pokemini': (384, 192, 1152, 768), # x12 + 'ngp': (400, 44, 1120, 1064), # x7 + 'ngpc': (400, 44, 1120, 1064), # x7 + 'wonderswan': (64, 0, 1792, 1152), # x8 + 'wonderswancolor': (64, 0, 1792, 1152), # x8 + } + + bezel_cfg = None + + if (bezel := config.get_setting('bezel')) and platform in system_viewport: + logger.log(f'bezel: {bezel} platform: {platform} rom: {rom_name}') + tmp_bezel = "/tmp/351elec-bezel.cfg" + game_cfg = '' + # set path + path = '' + for searchpath in bezel_dir: + if os.path.isdir(f'{searchpath}/{bezel}'): + path = f'{searchpath}/{bezel}' + + bezel_system = config.get_setting('bezel.system.override') + if not bezel_system or bezel_system == "AUTO": + bezel_system = platform + + bezel_system_png = f'{path}/systems/{bezel_system}.png' + logger.log(f'Bezel system png: {bezel_system_png}') + + game_bezel_override = config.get_setting('bezel.game.override') + logger.log(f'Game bezel override: {game_bezel_override}') + if not game_bezel_override or game_bezel_override == "AUTO": + logger.log('No game specific override found. Looking for games') + # is there a $ROMNAME.cfg? + # exactly the same / just the name / default + # Random bezels have to match $ROMNAME./d+.cfg + romdir = f'{path}/systems/{bezel_system}/games' + full_name = os.path.splitext(rom_name)[0] + short_name = full_name.split(' (')[0] + if os.path.isdir(romdir): + with os.scandir(romdir) as it: + full_list = [entry.name for entry in it if entry.is_file() and entry.name.endswith('.cfg')] + for romname in (full_name, short_name , 'default'): + logger.log(f'Looking at: {romdir}/{romname}') + file_list = [file for file in full_list if re.fullmatch(fr'{re.escape(romname)}\.[0-9]+\.cfg', file)] + if len(file_list) > 0: + game_cfg = f'{romdir}/{random.choice(file_list)}' + logger.log(f'Using random config: {game_cfg}') + break + elif os.path.isfile(f'{romdir}/{romname}.cfg'): + game_cfg = f'{romdir}/{romname}.cfg' + logger.log(f'Using ROM config: {game_cfg}') + break + else: + game_cfg = f'{path}/systems/{bezel_system}/games/{game_bezel_override}.cfg' + + if os.path.isfile(game_cfg): + logger.log(f'game config file exists: {game_cfg}') + with open(game_cfg) as f: + contents = f.read().strip() + bezel_system_png = f'{path}/systems/{bezel_system}/games/{contents}' + logger.log(f'bezel png: {bezel_system_png}') + if os.path.isfile(bezel_system_png): + tmp_bezel_dict = {} + tmp_bezel_dict['overlays'] = '1' + tmp_bezel_dict['overlay0_full_screen'] = 'true' + tmp_bezel_dict['overlay0_normalized'] = 'true' + tmp_bezel_dict['overlay0_overlay'] = bezel_system_png + overlays_dir = f'{path}/systems/{bezel_system}/overlays/' + count = 0 + if os.path.isdir(overlays_dir): + for overlay_png in iglob(f'{overlays_dir}/*.png'): + overlay_name = os.path.splitext(os.path.basename(overlay_png))[0] + overlay_setting = config.get_setting(f'bezel.overlay.{overlay_name}') + if not overlay_setting: + continue + logger.log(f'Adding overlay. name: {overlay_name} overlay setting: {overlay_setting}') + tmp_bezel_dict[f'overlay0_desc{count}_overlay'] = overlay_png + tmp_bezel_dict[f'overlay0_desc{count}'] = 'nul,0.5,0.5,rect,0.5,0.5' + count += 1 + tmp_bezel_dict['overlay0_descs'] = count + if os.path.isfile(tmp_bezel): + os.remove(tmp_bezel) + write_file(tmp_bezel, tmp_bezel_dict) + bezel_cfg = tmp_bezel + + if bezel_cfg is not None: + logger.log('using bezel') + # configure bezel + ra_append_dict['input_overlay_enable'] = 'true' + ra_append_dict['input_overlay'] = bezel_cfg + ra_append_dict['input_overlay_hide_in_menu'] = 'true' + ra_append_dict['input_overlay_opacity'] = '1.000000' + ra_append_dict['input_overlay_show_inputs'] = '2' + ra_append_dict['video_scale_integer'] = 'false' + ra_append_dict['aspect_ratio_index'] = '23' + # configure custom scaling + # needs some grouping to reflect the hack systems as well (i. e. gb=gb, gbh, gbc and gbch) + ra_append_dict['custom_viewport_x'] = system_viewport[platform][0] + ra_append_dict['custom_viewport_y'] = system_viewport[platform][1] + ra_append_dict['custom_viewport_width'] = system_viewport[platform][2] + ra_append_dict['custom_viewport_height'] = system_viewport[platform][3] + else: + logger.log('not using bezel') + # disable decorations + ra_append_dict['input_overlay_enable'] = 'false' + # set standard resolution for custom scaling + ra_append_dict['custom_viewport_x'] = system_viewport['standard'][0] + ra_append_dict['custom_viewport_y'] = system_viewport['standard'][1] + ra_append_dict['custom_viewport_width'] = system_viewport['standard'][2] + ra_append_dict['custom_viewport_height'] = system_viewport['standard'][3] + + # DECK specific options TODO: integrate better in the code + # TODO: not working + #ra_append_dict['video_windowed_fullscreen'] = "true" + + # Write the raappend.cfg + logger.log('Write raappend.cfg') + write_file(ra_append_conf, ra_append_dict) + + logger.log('done ...') + return shader_path + +# Main (if we are run as a script and not as a module) +if __name__ == '__main__': + # Arguments + parser = ArgumentParser(description="Convert ES settings from distribution.conf to RetroArch configuration in raappend.conf.") + parser.add_argument("--core", help="core", required=True) + parser.add_argument("--platform", help="platform", required=True) + parser.add_argument("--rom", help="ROM file name", required=True) + parser.add_argument("--controllers", help="controller config", default="-p1index 0") + parser.add_argument("--autosave", help="autosave", default="0") + parser.add_argument("--snapshot", help="snapshot", default="") + args = parser.parse_args() + shader_path = set_settings(rom_name=args.rom, core=args.core, platform=args.platform, controllers=args.controllers, autosave=args.autosave, snapshot=args.snapshot) + if shader_path: + print(shader_path)