Showing preview only (1,500K chars total). Download the full file or copy to clipboard to get everything.
Repository: RetroPie/RetroPie-Setup
Branch: master
Commit: 1d651c50bd65
Files: 398
Total size: 1.4 MB
Directory structure:
gitextract_5rddm1no/
├── .github/
│ ├── FUNDING.yml
│ └── ISSUE_TEMPLATE/
│ ├── bug-report.yml
│ └── config.yml
├── .gitignore
├── AUTHORS
├── CONTRIBUTING.md
├── COPYRIGHT.md
├── LICENSE.md
├── README.md
├── platforms.cfg
├── retropie_packages.sh
├── retropie_setup.sh
└── scriptmodules/
├── admin/
│ ├── apidocs.sh
│ ├── builder.sh
│ ├── crosscomp/
│ │ ├── asan_limits.diff
│ │ └── bullseye.diff
│ ├── crosscomp.sh
│ ├── image/
│ │ ├── dists/
│ │ │ ├── rpios-bookworm-64.ini
│ │ │ ├── rpios-bookworm.ini
│ │ │ ├── rpios-bullseye.ini
│ │ │ ├── rpios-buster.ini
│ │ │ ├── rpios-jessie.ini
│ │ │ └── rpios-stretch.ini
│ │ └── template.json
│ ├── image.sh
│ ├── joy2key/
│ │ ├── joy2key.py
│ │ ├── joy2key_sdl.py
│ │ └── osk.py
│ ├── joy2key.sh
│ ├── setup.sh
│ ├── stats/
│ │ ├── licences/
│ │ │ ├── app.css
│ │ │ ├── app.js
│ │ │ └── index.html
│ │ └── pkgflags/
│ │ ├── app.css
│ │ ├── app.js
│ │ └── index.html
│ ├── stats.sh
│ ├── tools.sh
│ └── wikidocs.sh
├── archivefuncs.sh
├── emulators/
│ ├── advmame/
│ │ ├── 01_rpi_framebuffer.diff
│ │ ├── 02_fix_extern_globals_0_94.diff
│ │ └── 02_fix_extern_globals_1_4.diff
│ ├── advmame-0.94.sh
│ ├── advmame-1.4.sh
│ ├── advmame.sh
│ ├── ags.sh
│ ├── amiberry/
│ │ ├── 01_preserve_env.diff
│ │ ├── 02_fix_uae_config_load.diff
│ │ └── 03_fix_crash_saving.diff
│ ├── amiberry.sh
│ ├── atari800/
│ │ ├── 01_rpi_fixes.diff
│ │ └── atari800.sh
│ ├── atari800.sh
│ ├── basilisk.sh
│ ├── capricerpi.sh
│ ├── coolcv.sh
│ ├── daphne/
│ │ └── dapinput.ini
│ ├── daphne.sh
│ ├── dgen.sh
│ ├── dolphin.sh
│ ├── dosbox/
│ │ └── 01-fully-bindable-joystick.diff
│ ├── dosbox-sdl2/
│ │ └── 001-sd2.0-check-remove.diff
│ ├── dosbox-sdl2.sh
│ ├── dosbox-staging/
│ │ └── 0.82.x-kmsdrm-fix.diff
│ ├── dosbox-staging.sh
│ ├── dosbox.sh
│ ├── drastic.sh
│ ├── fbzx.sh
│ ├── frotz.sh
│ ├── fs-uae/
│ │ └── fs-uae.sh
│ ├── fs-uae.sh
│ ├── fuse/
│ │ ├── 01_disable_cursor.diff
│ │ ├── 02_sdl_fix.diff
│ │ └── 03_gcc_10_fix.diff
│ ├── fuse.sh
│ ├── gngeopi.sh
│ ├── gpsp.sh
│ ├── hatari.sh
│ ├── hypseus/
│ │ ├── hypinput.ini
│ │ └── hypinput_gamepad.ini
│ ├── hypseus.sh
│ ├── jzintv/
│ │ ├── 01_rpi_hide_cursor_sdl2.patch
│ │ ├── 01_rpi_pillar_boxing_black_background_sdl2.patch
│ │ └── 02_Makefile_multiarch_pkg_config.patch
│ ├── jzintv.sh
│ ├── linapple.sh
│ ├── mame/
│ │ └── lzma_armv7_crc.diff
│ ├── mame.sh
│ ├── mame4all.sh
│ ├── minivmac.sh
│ ├── mupen64plus/
│ │ ├── 0001-GLideN64-use-emplace.patch
│ │ ├── mupen64plus.sh
│ │ └── remove_fast_math.diff
│ ├── mupen64plus.sh
│ ├── np2pi.sh
│ ├── openmsx/
│ │ └── retropie-init.tcl
│ ├── openmsx.sh
│ ├── oricutron.sh
│ ├── osmose.sh
│ ├── pcsx-rearmed.sh
│ ├── pcsx2.sh
│ ├── pifba.sh
│ ├── pisnes.sh
│ ├── ppsspp/
│ │ ├── gles2_fix.diff
│ │ ├── sdl_ttf_fix_before_1.19.diff
│ │ └── tinker.armv7.cmake
│ ├── ppsspp-1.5.4.sh
│ ├── ppsspp.sh
│ ├── px68k/
│ │ └── 001-missing-typedef.diff
│ ├── px68k.sh
│ ├── quasi88/
│ │ └── 01_cmake.diff
│ ├── quasi88.sh
│ ├── redream.sh
│ ├── reicast/
│ │ ├── 0001-enable-rpi4-sdl2-target.patch
│ │ ├── 0002-enable-vsync.patch
│ │ ├── 0003-fix-sdl2-sighandler-conflict.patch
│ │ └── reicast.sh
│ ├── reicast.sh
│ ├── retroarch/
│ │ ├── mess2016_libretro.info
│ │ └── mupen64plus_libretro.info
│ ├── retroarch.sh
│ ├── rpix86.sh
│ ├── scummvm-sdl1.sh
│ ├── scummvm.sh
│ ├── sdltrs.sh
│ ├── simcoupe.sh
│ ├── snes9x.sh
│ ├── stella.sh
│ ├── stratagus.sh
│ ├── supermodel3.sh
│ ├── ti99sim/
│ │ └── missing_cstring.diff
│ ├── ti99sim-sdl1/
│ │ └── missing_cstdio.diff
│ ├── ti99sim-sdl1.sh
│ ├── ti99sim.sh
│ ├── uae4all/
│ │ └── 01_guichan.diff
│ ├── uae4all.sh
│ ├── uae4arm/
│ │ └── uae4arm.sh
│ ├── uae4arm.sh
│ ├── vice.sh
│ ├── xm7/
│ │ └── 01_fix_build.diff
│ ├── xm7.sh
│ ├── xroar.sh
│ ├── yabasanshiro.sh
│ └── zesarux.sh
├── helpers.sh
├── inifuncs.sh
├── libretrocores/
│ ├── lr-81.sh
│ ├── lr-atari800.sh
│ ├── lr-beetle-lynx.sh
│ ├── lr-beetle-ngp.sh
│ ├── lr-beetle-pce-fast.sh
│ ├── lr-beetle-pce.sh
│ ├── lr-beetle-pcfx.sh
│ ├── lr-beetle-psx.sh
│ ├── lr-beetle-saturn.sh
│ ├── lr-beetle-supergrafx.sh
│ ├── lr-beetle-vb.sh
│ ├── lr-beetle-wswan.sh
│ ├── lr-bennugd.sh
│ ├── lr-bluemsx.sh
│ ├── lr-bsnes.sh
│ ├── lr-caprice32.sh
│ ├── lr-desmume.sh
│ ├── lr-desmume2015.sh
│ ├── lr-dinothawr.sh
│ ├── lr-dirksimple.sh
│ ├── lr-dolphin.sh
│ ├── lr-dosbox-pure.sh
│ ├── lr-dosbox.sh
│ ├── lr-ep128emu.sh
│ ├── lr-fbalpha2012.sh
│ ├── lr-fbneo.sh
│ ├── lr-fceumm.sh
│ ├── lr-flycast/
│ │ └── 01_flags_fix.diff
│ ├── lr-flycast-dev.sh
│ ├── lr-flycast.sh
│ ├── lr-fmsx.sh
│ ├── lr-freechaf.sh
│ ├── lr-freeintv.sh
│ ├── lr-fuse.sh
│ ├── lr-gambatte/
│ │ └── default.pal
│ ├── lr-gambatte.sh
│ ├── lr-geargrafx.sh
│ ├── lr-gearsystem.sh
│ ├── lr-genesis-plus-gx.sh
│ ├── lr-gpsp.sh
│ ├── lr-gw.sh
│ ├── lr-handy.sh
│ ├── lr-hatari/
│ │ └── 01_libcapsimage.diff
│ ├── lr-hatari.sh
│ ├── lr-kronos.sh
│ ├── lr-mame.sh
│ ├── lr-mame2000.sh
│ ├── lr-mame2003-plus.sh
│ ├── lr-mame2003.sh
│ ├── lr-mame2010.sh
│ ├── lr-mame2015/
│ │ └── 01-python3-irgen.diff
│ ├── lr-mame2015.sh
│ ├── lr-mame2016/
│ │ └── 01-python3-irgen.diff
│ ├── lr-mame2016.sh
│ ├── lr-mesen.sh
│ ├── lr-mess.sh
│ ├── lr-mess2016.sh
│ ├── lr-mgba.sh
│ ├── lr-mrboom.sh
│ ├── lr-mupen64plus/
│ │ ├── 0001-eliminate-conflicting-typedefs.patch
│ │ ├── 0002-rpi-gles3.patch
│ │ └── 0003-fix-fsqrt-conflict.patch
│ ├── lr-mupen64plus-next.sh
│ ├── lr-mupen64plus.sh
│ ├── lr-neocd.sh
│ ├── lr-nestopia.sh
│ ├── lr-np2kai.sh
│ ├── lr-nxengine.sh
│ ├── lr-o2em.sh
│ ├── lr-opera.sh
│ ├── lr-parallel-n64/
│ │ └── 01-fix-fsqrt-conflicts.diff
│ ├── lr-parallel-n64.sh
│ ├── lr-pcsx-rearmed.sh
│ ├── lr-picodrive.sh
│ ├── lr-pokemini.sh
│ ├── lr-ppsspp/
│ │ ├── v13-libretro_fix.diff
│ │ └── v16-clamp-include.diff
│ ├── lr-ppsspp.sh
│ ├── lr-prboom.sh
│ ├── lr-prosystem.sh
│ ├── lr-puae.sh
│ ├── lr-puae2021.sh
│ ├── lr-px68k.sh
│ ├── lr-quasi88.sh
│ ├── lr-quicknes.sh
│ ├── lr-retro8.sh
│ ├── lr-scummvm.sh
│ ├── lr-smsplus-gx.sh
│ ├── lr-snes9x.sh
│ ├── lr-snes9x2002.sh
│ ├── lr-snes9x2005.sh
│ ├── lr-snes9x2010.sh
│ ├── lr-stella.sh
│ ├── lr-stella2014.sh
│ ├── lr-superflappybirds.sh
│ ├── lr-tgbdual.sh
│ ├── lr-theodore.sh
│ ├── lr-tic80.sh
│ ├── lr-tyrquake.sh
│ ├── lr-uae4arm.sh
│ ├── lr-vba-next.sh
│ ├── lr-vecx.sh
│ ├── lr-vice.sh
│ ├── lr-virtualjaguar.sh
│ ├── lr-x1.sh
│ ├── lr-xrick.sh
│ └── lr-yabause.sh
├── packages.sh
├── ports/
│ ├── alephone.sh
│ ├── cannonball.sh
│ ├── cdogs-sdl.sh
│ ├── cgenius.sh
│ ├── darkplaces-quake/
│ │ ├── 01_rpi_fixes.diff
│ │ └── 02_makefile_fixes.diff
│ ├── darkplaces-quake.sh
│ ├── dsda-doom.sh
│ ├── dxx-rebirth.sh
│ ├── eduke32/
│ │ ├── 0001-revert-r6918.patch
│ │ ├── 0002-fix-skybox.patch
│ │ ├── 0003-replace-gl_red.patch
│ │ ├── 0004-recast-function.patch
│ │ ├── 0005-e1m4-shrinker-bug.patch
│ │ └── 0006-e4m4-water-bug.patch
│ ├── eduke32.sh
│ ├── gemrb.sh
│ ├── giana.sh
│ ├── gzdoom/
│ │ ├── armv8_gcc12_fix.diff
│ │ └── lzma_armv7_crc.diff
│ ├── gzdoom.sh
│ ├── ionfury.sh
│ ├── ioquake3.sh
│ ├── jumpnbump/
│ │ └── jumpnbump.sh
│ ├── jumpnbump.sh
│ ├── kodi.sh
│ ├── lincity-ng.sh
│ ├── love-0.10.2.sh
│ ├── love.sh
│ ├── lzdoom/
│ │ ├── 01_remove_cmake_arm_options.diff
│ │ ├── 02_lzma_sdk_dont_force_arm_crc32.diff
│ │ └── 03_extra_includes.diff
│ ├── lzdoom.sh
│ ├── micropolis.sh
│ ├── minecraft.sh
│ ├── mysticmine.sh
│ ├── openblok.sh
│ ├── openbor.sh
│ ├── openpht.sh
│ ├── openttd.sh
│ ├── opentyrian/
│ │ └── 01_fullscreen.diff
│ ├── opentyrian.sh
│ ├── quake3.sh
│ ├── sdlpop.sh
│ ├── smw.sh
│ ├── solarus.sh
│ ├── splitwolf.sh
│ ├── srb2/
│ │ └── 001-cmake-libfind.diff
│ ├── srb2.sh
│ ├── steamlink.sh
│ ├── supertux.sh
│ ├── tyrquake.sh
│ ├── uqm.sh
│ ├── vvvvvv.sh
│ ├── wolf4sdl.sh
│ ├── xrick.sh
│ ├── yquake2/
│ │ ├── hotkey_exit.diff
│ │ ├── sdl2_joylabels.diff
│ │ └── yq2.cfg
│ └── yquake2.sh
├── supplementary/
│ ├── attractmode.sh
│ ├── audiosettings.sh
│ ├── autostart.sh
│ ├── backends.sh
│ ├── bashwelcometweak.sh
│ ├── bluetooth/
│ │ ├── COPYING
│ │ ├── bluez-simple-agent
│ │ ├── bluez-test-device
│ │ ├── bluezutils.py
│ │ ├── connect.sh
│ │ └── readme.txt
│ ├── bluetooth.sh
│ ├── configedit.sh
│ ├── consolefont.sh
│ ├── controlblock.sh
│ ├── custombluez/
│ │ └── 01_raspbian_patches.diff
│ ├── customhidsony/
│ │ └── 0001-hidsony-gasiafix.diff
│ ├── customhidsony.sh
│ ├── dbar4gun.sh
│ ├── docsview.sh
│ ├── emulationstation/
│ │ ├── configscripts/
│ │ │ ├── daphne.sh
│ │ │ ├── emulationstation.sh
│ │ │ ├── mupen64plus.sh
│ │ │ ├── openmsx.sh
│ │ │ ├── pifba.sh
│ │ │ ├── pisnes.sh
│ │ │ ├── reicast.sh
│ │ │ ├── retroarch.sh
│ │ │ └── sdl2.sh
│ │ └── inputconfiguration.sh
│ ├── emulationstation-dev.sh
│ ├── emulationstation.sh
│ ├── esthemes/
│ │ ├── patch-ruckage-famicom-mini.diff
│ │ ├── patch-ruckage-nes-mini.diff
│ │ └── patch-ruckage-snes-mini.diff
│ ├── esthemes.sh
│ ├── gamecondriver.sh
│ ├── golang.sh
│ ├── kmsxx.sh
│ ├── launchingimages.sh
│ ├── mehstation.sh
│ ├── mesa-drm.sh
│ ├── mkarcadejoystick.sh
│ ├── mobilegamepad.sh
│ ├── moonlight.sh
│ ├── omxiv.sh
│ ├── pegasus-fe-dev.sh
│ ├── pegasus-fe.sh
│ ├── powerblock.sh
│ ├── ps3controller.sh
│ ├── raspbiantools.sh
│ ├── resetromdirs.sh
│ ├── retronetplay.sh
│ ├── retropiemenu.sh
│ ├── runcommand/
│ │ └── runcommand.sh
│ ├── runcommand.sh
│ ├── samba.sh
│ ├── scraper.sh
│ ├── sdl1.sh
│ ├── sdl12-compat.sh
│ ├── sdl2.sh
│ ├── sixaxis.sh
│ ├── skyscraper.sh
│ ├── snesdev/
│ │ └── 001-wiringpi-static.diff
│ ├── snesdev.sh
│ ├── splashscreen/
│ │ ├── 05-splash.sh
│ │ ├── asplashscreen.sh
│ │ └── rp-vlc
│ ├── splashscreen.sh
│ ├── steamcontroller.sh
│ ├── usbromservice/
│ │ ├── 01_retropie_copyroms
│ │ └── 10_retropie_mount
│ ├── usbromservice.sh
│ ├── virtualgamepad.sh
│ ├── wifi.sh
│ ├── xarcade2jstick.sh
│ ├── xboxdrv.sh
│ ├── xpad/
│ │ ├── 01_enable_leds_and_trigmapping.diff
│ │ ├── 02_dkms_updates_folder.diff
│ │ └── 03_xpad_add_version.diff
│ ├── xpad.sh
│ └── xpadneo.sh
└── system.sh
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/FUNDING.yml
================================================
patreon: retropie
custom: https://retropie.org.uk/donate/
================================================
FILE: .github/ISSUE_TEMPLATE/bug-report.yml
================================================
name: Create Issue
description: |
Report a bug with RetroPie-Setup scripts
body:
- type: markdown
id: info
attributes:
value: |
#### Important
Only RetroPie-Setup **bugs** should be reported here as an Issue.
For general support questions, games troubleshooting and enhancement requests please use the [RetroPie Forums](https://retropie.org.uk/forum).
validations:
required: false
- type: textarea
id: description
attributes:
label: Description
placeholder: describe the problem/bug in RetroPie's scripts
validations:
required: true
================================================
FILE: .github/ISSUE_TEMPLATE/config.yml
================================================
blank_issues_enabled: false
contact_links:
- name: RetroPie Forums
url: https://retropie.org.uk/forum
about: Community for discussion and support
- name: Documentation
url: https://retropie.org.uk/docs
about: Official RetroPie Documentation
================================================
FILE: .gitignore
================================================
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
Thumbs.db
# Generated files
logs/
tmp/
# 3rd Party Repos
ext/*
================================================
FILE: AUTHORS
================================================
Florian Müller - <contact [at] petrockblock.com>
- Main code, maintainer
Jools Wills - <buzz [at] exotica.org.uk>
- Main code, maintainer
================================================
FILE: CONTRIBUTING.md
================================================
# How to contribute
## Support Requests vs Bug Reporting
Please use the GitHub for bug reports only. For help / support in using RetroPie and the emulators
it ships with, please use the [RetroPie forum](https://retropie.org.uk/forum/).
## Pull Requests
Contributions to the project are welcome - please check out our [Shell Style Guide](https://retropie.org.uk/docs/Shell-Style-Guide/) before submitting changes.
================================================
FILE: COPYRIGHT.md
================================================
The RetroPie Project
Copyright (C) 2012-2025 by the following:
If you have contributed to this project then you deserve to be on this
list. Contact us (see: AUTHORS) and we'll add you.
* Florian Müller "petrockblog"
* Jools Wills "joolswills"
* Peter Mahlknecht
* Aloshi
* Martin Modahl
* marqs
* Juan Pablo Zapata, jpzapa
* Xevin
* James Le Cuirot
* Ewan Meadows
* Adam "adskiremote"
* Hyperspin
* Claudio Cesar Sanchez Tejeda,
* cdu13a
* Christian Bryn
* Adam Smith
* Adrian Moisey
* Sergej Tatarincev
* "HerbFargus"
* Stefan "gizmo98"
For most recent list see also https://github.com/RetroPie/RetroPie-Setup/graphs/contributors
================================================
FILE: LICENSE.md
================================================
# RetroPie Legal Information
## License
### GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
### Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
### TERMS AND CONDITIONS
#### 0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
#### 1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
#### 2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
#### 4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
#### 5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
#### 6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
#### 7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
#### 8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
#### 9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
#### 10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
#### 11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
#### 12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
#### 13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
#### 14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
#### 15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
#### 16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
#### 17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
---
## Copyright
(c) Copyright 2012-2015 RetroPie Project (See COPYRIGHT.md)
================================================
FILE: README.md
================================================
RetroPie-Setup
==============
General Usage
-------------
Shell script to setup the Raspberry Pi, Vero4K, ODroid-C1 or a PC running Ubuntu with many emulators and games, using EmulationStation as the graphical front end. Bootable pre-made images for the Raspberry Pi are available for those that want a ready-to-go system, downloadable from the releases section of GitHub or via our website at https://retropie.org.uk.
This script is designed for use on Raspberry Pi OS (previously called Raspbian) on the Raspberry Pi, OSMC on the Vero4K or Ubuntu on the ODroid-C1 or a PC.
To run the RetroPie Setup Script make sure that your APT repositories are up-to-date and that Git is installed:
```shell
sudo apt-get update
sudo apt-get dist-upgrade
sudo apt-get install git
```
Then you can download the latest RetroPie setup script with:
```shell
cd
git clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git
```
The script is executed with:
```shell
cd RetroPie-Setup
sudo ./retropie_setup.sh
```
When you first run the script it may install some additional packages that are needed.
Binaries and Sources
--------------------
On the Raspberry Pi, RetroPie Setup offers the possibility to install from binaries or source. For other supported platforms only a source install is available. Installing from binary is recommended on a Raspberry Pi as building everything from source can take a long time.
For more information, visit the site at https://retropie.org.uk or the repository at https://github.com/RetroPie/RetroPie-Setup.
Docs
----
You can find useful information about several components and answers to frequently asked questions in the [RetroPie Docs](https://retropie.org.uk/docs/). If you think that there is something missing, you are invited to submit a pull request to the [RetroPie-Docs repository](https://github.com/RetroPie/RetroPie-Docs).
Thanks
------
This script just simplifies the usage of the great works of many other people that enjoy the spirit of retrogaming. Many thanks go to them!
================================================
FILE: platforms.cfg
================================================
3do_exts=".chd .cue .iso .zip"
3do_fullname="3DO Interactive Multiplayer"
ags_exts=".exe"
ags_fullname="Adventure Game Studio"
amiga_exts=".adf .adz .chd .cue .dms .hdf .hdz .ipf .lha .m3u .sh .uae .zip"
amiga_fullname="Commodore Amiga"
amstradcpc_exts=".cdt .cpc .cpr .dsk .m3u .tap .zip"
amstradcpc_fullname="Amstrad CPC"
apple2_exts=".po .dsk .nib"
apple2_fullname="Apple II"
arcade_exts=".7z .cue .fba .iso .zip"
arcade_fullname="Arcade"
arcadia_exts=".bin .zip"
arcadia_fullname="Arcadia 2001"
atari2600_exts=".7z .a26 .bin .rom .zip .gz"
atari2600_fullname="Atari 2600"
atari5200_exts=".7z .a52 .bin .car .zip"
atari5200_fullname="Atari 5200"
atari7800_exts=".7z .a78 .bin .zip"
atari7800_fullname="Atari 7800 ProSystem"
atari800_exts=".7z .atr .atr.gz .atx .bas .bin .car .cas .com .dcm .rom .xex .xfd .xfd.gz .zip"
atari800_fullname="Atari 800"
atarijaguar_exts=".j64 .jag .zip"
atarijaguar_fullname="Atari Jaguar"
atarilynx_exts=".7z .lnx .zip"
atarilynx_fullname="Atari Lynx"
atarist_exts=".st .stx .img .m3u .rom .raw .ipf .ctr .zip"
atarist_fullname="Atari ST"
c64_exts=".cmd .crt .d64 .d71 .d80 .d81 .g64 .prg .m3u .t64 .tap .x64 .zip .vsf"
c64_fullname="Commodore 64"
channelf_exts=".bin .rom .zip .7z"
channelf_fullname="Fairchild ChannelF"
coco_exts=".bin .cas .wav .bas .asc .dmk .jvc .os9 .dsk .vdk .rom .ccc .sna"
coco_fullname="TRS-80 Color Computer"
coleco_exts=".bin .col .rom .zip"
coleco_fullname="ColecoVision"
coleco_theme="colecovision"
coleco_platform="colecovision"
crvision_exts=".rom .zip"
crvision_fullname="CreatiVision"
daphne_exts=".daphne .ogv"
daphne_fullname="Daphne"
dragon32_exts=".bin .cas .wav .bas .asc .dmk .jvc .os9 .dsk .vdk .rom .ccc .sna"
dragon32_fullname="Dragon 32"
dreamcast_exts=".cdi .chd .cue .gdi .sh .zip .m3u"
dreamcast_fullname="Dreamcast"
enterprise_exts=".img .dsk .tap .dtf .wav .bas .com .trn .128"
enterprise_fullname="Enterprise 128"
fba_exts=".7z .cue .fba .iso .zip"
fba_fullname="Final Burn Alpha"
fba_platform="arcade"
fds_exts=".7z .nes .fds .zip"
fds_fullname="Famicom Disk System"
fm7_exts=".d77 .t77 .d88 .2d"
fm7_fullname="Fujitsu FM-7 Series"
gameandwatch_exts=".mgw"
gameandwatch_fullname="Game and Watch"
gamegear_exts=".7z .gg .bin .sms .zip"
gamegear_fullname="Sega Gamegear"
gba_exts=".7z .gba .zip"
gba_fullname="Game Boy Advance"
gb_exts=".7z .gb .zip"
gb_fullname="Game Boy"
gbc_exts=".7z .gbc .zip"
gbc_fullname="Game Boy Color"
gc_exts=".ciso .gcm .gcz .iso .rvz .m3u"
gc_fullname="Nintendo Gamecube"
intellivision_exts=".7z .bin .int .itv .rom .zip"
intellivision_fullname="Intellivision"
love_exts=".love"
love_fullname="Love"
macintosh_exts=".txt .dsk"
macintosh_fullname="Apple Macintosh"
mame_exts=".zip .7z"
mame_fullname="Multiple Arcade Machine Emulator"
mame_platform="arcade"
mame_theme="mame"
mame-advmame_exts=".zip"
mame-advmame_fullname="Multiple Arcade Machine Emulator"
mame-advmame_platform="arcade"
mame-advmame_theme="mame"
mame-libretro_exts=".zip"
mame-libretro_fullname="Multiple Arcade Machine Emulator"
mame-libretro_platform="arcade"
mame-libretro_theme="mame"
mame-mame4all_exts=".zip"
mame-mame4all_fullname="Multiple Arcade Machine Emulator"
mame-mame4all_platform="arcade"
mame-mame4all_theme="mame"
mastersystem_exts=".7z .sms .bin .zip"
mastersystem_fullname="Sega Master System"
megadrive_exts=".7z .smd .bin .gen .md .sg .zip"
megadrive_fullname="Sega Mega Drive"
megadrive_theme="megadrive"
megadrive_platform="megadrive"
msx_exts=".cas .rom .mx1 .mx2 .col .dsk .zip .m3u"
msx_fullname="MSX"
moto_exts=".fd .k7 .m5 .m7 .rom .sap"
moto_fullname="Thomson MO/TO"
n64_exts=".z64 .n64 .v64 .zip"
n64_fullname="Nintendo 64"
nds_exts=".nds .zip"
nds_fullname="Nintendo DS"
neogeo_exts=".7z .chd .cue .fba .iso .zip"
neogeo_fullname="Neo Geo"
nes_exts=".7z .nes .zip"
nes_fullname="Nintendo Entertainment System"
ngp_exts=".7z .ngp .zip"
ngp_fullname="Neo Geo Pocket"
ngpc_exts=".7z .ngc .zip"
ngpc_fullname="Neo Geo Pocket Color"
np2pi_exts=".d88 .d98 .88d .98d .fdi .xdf .hdm .dup .2hd .tfd .hdi .thd .nhd .hdd"
np2pi_fullname="NEC PC-9801"
oric_exts=".dsk .tap"
oric_fullname="Oric 1"
pc88_exts=".d88 .cmt .m3u .t88"
pc88_fullname="NEC PC-8801"
pc98_exts=".2hd .88d .98d .cmd .d88 .d98 .dup .fdi .fdd .hdd .hdi .hdm .nhd .thd .tfd .xdf .zip"
pc98_fullname="NEC PC-9801"
pc_exts=".bat .com .conf .cue .dosz .exe .ins .ima .img .iso .m3u .m3u8 .sh .vhd .zip"
pc_fullname="PC"
pcengine_exts=".7z .pce .ccd .chd .cue .zip"
pcengine_fullname="PC Engine"
pcengine_theme="pcengine"
pcfx_exts=".pce .ccd .cue .iso .chd"
pcfx_fullname="PC-FX"
pico8_exts=".p8 .png .zip"
pico8_fullname="PICO-8"
pokemini_exts=".min .zip"
pokemini_fullname="Pokemon Mini"
ports_exts=".sh"
ports_fullname="Ports"
ports_platform="pc"
ps2_exts=".iso .img .bin .mdf .z .z2 .bz2 .dump .cso .chd .ima .gz"
ps2_fullname="PlayStation 2"
psp_exts=".chd .iso .pbp .cso"
psp_fullname="PlayStation Portable"
psx_exts=".cue .cbn .chd .img .iso .m3u .mdf .pbp .toc .z .znx"
psx_fullname="PlayStation"
samcoupe_exts=".dsk .mgt .sbt .sad"
samcoupe_fullname="SAM Coupe"
saturn_exts=".chd .cue .m3u .mdf .zip"
saturn_fullname="Sega Saturn"
scummvm_exts=".sh .svm"
scummvm_fullname="ScummVM"
sega32x_exts=".7z .32x .smd .bin .md .zip"
sega32x_fullname="Sega 32X"
segacd_exts=".iso .cue .chd .m3u"
segacd_fullname="Mega CD"
sg-1000_exts=".7z .sg .bin .zip"
sg-1000_fullname="Sega SG-1000"
snes_exts=".7z .bin .bs .smc .sfc .fig .swc .mgd .zip"
snes_fullname="Super Nintendo"
solarus_exts=".solarus .zip"
solarus_fullname="Solarus Engine"
ti99_exts=".ctg"
ti99_fullname="TI99"
tic80_exts=".tic .zip"
tic80_fullname="TIC-80"
trs-80_exts=".dsk"
trs-80_fullname="trs-80"
vectrex_exts=".7z .vec .gam .bin .zip"
vectrex_fullname="Vectrex"
videopac_exts=".7z .bin .zip"
videopac_fullname="Videopac"
virtualboy_exts=".7z .vb .zip"
virtualboy_fullname="Virtual Boy"
wii_exts=".ciso .gcm .gcz .iso .rvz .wad .wbfs .m3u"
wii_fullname="Nintendo Wii"
wonderswan_exts=".7z .ws .zip"
wonderswan_fullname="Wonderswan"
wonderswancolor_exts=".7z .wsc .zip"
wonderswancolor_fullname="Wonderswan Color"
x1_exts=".dx1 .zip .2d .2hd .tfd .d88 .88d .hdm .xdf .dup .cmd"
x1_fullname="Sharp X1"
x68000_exts=".dim .hdf .hdm .2hd .d88 .m3u .xdf"
x68000_fullname="X68000"
zmachine_exts=".dat .zip .z1 .z2 .z3 .z4 .z5 .z6 .z7 .z8"
zmachine_fullname="Z-machine"
zx81_exts=".7z .p .tzx .t81 .zip"
zx81_fullname="ZX81"
zxspectrum_exts=".7z .sh .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip .rzx"
zxspectrum_fullname="ZX Spectrum"
================================================
FILE: retropie_packages.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
__version="4.8.11"
[[ "$__debug" -eq 1 ]] && set -x
# main retropie install location
rootdir="/opt/retropie"
# if no user is specified
if [[ -z "$__user" ]]; then
# get the calling user from sudo env
__user="$SUDO_USER"
# if not called from sudo get the current user
[[ -z "$__user" ]] && __user="$(id -un)"
fi
# check if the user exists
if [[ -z "$(getent passwd "$__user")" ]]; then
echo "User $__user does not exist."
exit 1
fi
# if no group is specified get the users primary group
if [[ -z "$__group" ]]; then
__group="$(id -gn "$__user")"
fi
# check if the group exists
if [[ -z "$(getent group "$__group")" ]]; then
echo "Group $__group does not exist."
exit 1
fi
# backwards compatibility
user="$__user"
home="$(eval echo ~$__user)"
datadir="$home/RetroPie"
biosdir="$datadir/BIOS"
romdir="$datadir/roms"
emudir="$rootdir/emulators"
configdir="$rootdir/configs"
scriptdir="$(dirname "$0")"
scriptdir="$(cd "$scriptdir" && pwd)"
__logdir="$scriptdir/logs"
__tmpdir="$scriptdir/tmp"
__builddir="$__tmpdir/build"
__swapdir="$__tmpdir"
# check, if sudo is used
if [[ "$(id -u)" -ne 0 ]]; then
echo "Script must be run under sudo from the user you want to install for. Try 'sudo $0'"
exit 1
fi
__backtitle="retropie.org.uk - RetroPie Setup. Installation folder: $rootdir for user $__user"
source "$scriptdir/scriptmodules/system.sh"
source "$scriptdir/scriptmodules/helpers.sh"
source "$scriptdir/scriptmodules/inifuncs.sh"
source "$scriptdir/scriptmodules/packages.sh"
setup_env
rp_registerAllModules
ensureFBMode 320 240
rp_ret=0
if [[ $# -gt 0 ]]; then
setupDirectories
rp_callModule "$@"
rp_ret=$?
else
rp_printUsageinfo
fi
if [[ "${#__ERRMSGS[@]}" -gt 0 ]]; then
# override return code if ERRMSGS is set - eg in the case of calling basic_install from setup
# we won't get the return code, as we don't handle return codes when calling non packaging functions
# as it would require all modules functions to handle errors differently, and make things more complicated
[[ "$rp_ret" -eq 0 ]] && rp_ret=1
printMsgs "console" "Errors:\n${__ERRMSGS[@]}"
fi
if [[ "${#__INFMSGS[@]}" -gt 0 ]]; then
printMsgs "console" "Info:\n${__INFMSGS[@]}"
fi
exit $rp_ret
================================================
FILE: retropie_setup.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
scriptdir="$(dirname "$0")"
scriptdir="$(cd "$scriptdir" && pwd)"
"$scriptdir/retropie_packages.sh" setup gui
================================================
FILE: scriptmodules/admin/apidocs.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="apidocs"
rp_module_desc="Generate developer documentation"
rp_module_section=""
function depends_apidocs() {
getDepends doxygen graphviz
}
function sources_apidocs() {
gitPullOrClone "$md_build" https://github.com/Anvil/bash-doxygen.git
}
function build_apidocs() {
local config="Doxyfile"
rm -f "$config"
doxygen -g "$config" >/dev/null
iniConfig " = " '' "$config"
iniSet "PROJECT_NAME" "RetroPie-Setup"
iniSet "PROJECT_NUMBER" "$__version"
iniSet "EXTENSION_MAPPING" "sh=C"
iniSet "QUIET" "YES"
iniSet "WARN_IF_DOC_ERROR" "NO"
iniSet "INPUT" "$scriptdir"
iniSet "EXCLUDE_PATTERNS" "*/tmp/*"
iniSet "INPUT_FILTER" "\"sed -n -f $md_build/doxygen-bash.sed -- \""
iniSet "RECURSIVE" "YES"
# unable to use iniSet for latest doxygen "multi line" FILE_PATTERNS default
echo "FILE_PATTERNS = *.sh" >>"$config"
doxygen "$config"
}
function install_apidocs() {
rsync -a --delete "$md_build/html/" "$__tmpdir/apidocs/"
chown -R "$__user":"$__group" "$__tmpdir/apidocs"
}
function upload_apidocs() {
adminRsync "$__tmpdir/apidocs/" "api/" --delete
}
================================================
FILE: scriptmodules/admin/builder.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="builder"
rp_module_desc="Create binary archives for distribution"
rp_module_section=""
function depends_builder() {
getDepends rsync
}
function module_builder() {
local ids=($@)
# set log directories
local log_dir_ok="$__tmpdir/build_logs/$__os_binaries/ok/$__platform"
local log_dir_fail="$__tmpdir/build_logs/$__os_binaries/fail/$__platform"
# create the log directories
mkdir -p "$log_dir_ok" "$log_dir_fail"
local id
for id in "${ids[@]}"; do
printMsgs "console" "Checking module $id ..."
# don't build binaries for modules with flag nobin
# eg scraper which fails as go1.8 doesn't work under qemu
if hasFlag "${__mod_info[$id/flags]}" "nobin"; then
printMsgs "console" "Module has 'nobin' flag set, so not building."
continue
fi
# skip modules that are not enabled for the target system
if [[ "${__mod_info[$id/enabled]}" -ne 1 ]]; then
printMsgs "console" "Module is disabled for this platform ($__platform)."
continue
fi
# if the module has no install_ function skip to the next module
if ! fnExists "install_${id}"; then
printMsgs "console" "Module has no install_${id} function so cannot be pre-built."
continue
fi
# if there is no newer version, skip to the next module. Returns 1 when update is not required,
# but can also return 2, to mean "unknown" in which case we should do an update. Modules like sdl2
# will return 2 as they are handled differently, and don't use the package update mechanisms.
rp_hasNewerModule "$id" "source"
if [[ "$?" -eq 1 ]]; then
printMsgs "console" "No update was found."
continue
else
printMsgs "console" "Update found."
fi
# delete previous log if present
rm -f "$log_dir_ok/$id.log"
# build, install and create binary archive.
# initial clean in case anything was in the build folder when calling
local failed=0
local mode
for mode in clean depends sources build install create_bin clean remove "depends remove"; do
# don't try and create binary archives for modules with an install_bin such as sdl1/sdl2
if [[ "$mode" == "create_bin" ]] && fnExists "install_bin_${id}"; then
continue
fi
# call the module function, logging the output.
rp_callModule "$id" $mode 2>&1 | tee -a "$log_dir_ok/$id.log"
# if the module function returns an error mark as failed and continue to next module
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
failed=1
break
fi
done
if [[ "$failed" -eq 0 ]]; then
# if the build is successful, remove any previous fail log
rm -f "$log_dir_fail/$id.log"
else
# otherwise, the build failed or a module wasn't available so move the module output to a fail log
mv "$log_dir_ok/$id.log" "$log_dir_fail/$id.log"
fi
done
return 0
}
function section_builder() {
module_builder $(rp_getSectionIds $1) || return 1
}
function upload_builder() {
adminRsync "$__tmpdir/archives/" "files/binaries/"
}
function clean_archives_builder() {
rm -rfv "$__tmpdir/archives"
}
function chroot_build_builder() {
rp_callModule image depends
mkdir -p "$md_build"
# get current host ip for the distcc in the emulated chroot to connect to
local ip="$(getIPAddress)"
local dist
local dists="$__builder_dists"
[[ -z "$dists" ]] && return 1
local platform
local platforms="$__builder_platforms"
for dist in $dists; do
[[ -z "$platforms" ]] && platforms="$(_get_info_image "$dist" "platforms")"
[[ -z "$platforms" ]] && fatalError "Unable to get platforms information for $dist"
local chroot_dir="$md_build/$dist"
local chroot_rps_dir="$chroot_dir/home/pi/RetroPie-Setup"
local dist_name="$(_get_info_image "$dist" "name")"
[[ -z "$dist_name" ]] && fatalError "Unable to get name information for $dist"
local archive_dir="tmp/archives/$dist_name"
# set the host and chroot build_log locations
local chroot_build_logs="$chroot_rps_dir/tmp/build_logs"
local host_build_logs="$scriptdir/tmp/build_logs"
local distcc_hosts="$__builder_distcc_hosts"
local use_ccache="$__builder_use_ccache"
local makeflags="$__builder_makeflags"
[[ -z "$makeflags" ]] && makeflags="-j$(nproc)"
[[ ! -d "$chroot_dir" ]] && rp_callModule image create_chroot "$dist" "$chroot_dir"
if [[ ! -d "$chroot_rps_dir" ]]; then
gpg --export-secret-keys "$__gpg_signing_key" >"$chroot_dir/retropie.key"
rp_callModule image chroot "$chroot_dir" bash -c "
sudo gpg --import /retropie.key
sudo rm /retropie.key
sudo apt-get update; sudo apt-get install -y git
cd
git clone https://github.com/RetroPie/RetroPie-Setup.git
"
# copy existing packages from host if building in a clean chroot to avoid rebuilding everything
mkdir -p "$scriptdir/$archive_dir" "$chroot_rps_dir/$archive_dir"
rsync -av "$scriptdir/$archive_dir/" "$chroot_rps_dir/$archive_dir/"
# copy any previous build logs back to the chroot
mkdir -p "$host_build_logs/$dist_name" "$chroot_build_logs/$dist_name"
rsync -av --delete "$host_build_logs/$dist_name/" "$chroot_build_logs/$dist_name/"
else
rp_callModule image chroot "$chroot_dir" bash -c "
cd ~/RetroPie-Setup
git checkout master
git pull
if git remote | grep -q builder; then
git branch -D builder-branch
git remote remove builder
fi
"
fi
# if we have a __builder_repo and __builder_branch set, check out the branch and use that
if [[ -n "$__builder_repo" && "$__builder_branch" ]]; then
rp_callModule image chroot "$chroot_dir" bash -c "
cd ~/RetroPie-Setup
git remote add builder $__builder_repo
git fetch -q builder
git checkout builder/$__builder_branch -b builder-branch
"
fi
for platform in $platforms; do
rp_callModule image chroot "$chroot_dir" \
sudo \
__use_ccache="$use_ccache" \
__makeflags="$makeflags" \
DISTCC_HOSTS="$distcc_hosts" \
__platform="$platform" \
__has_binaries="$__chroot_has_binaries" \
/home/pi/RetroPie-Setup/retropie_packages.sh builder "$@"
done
rsync -av "$chroot_rps_dir/$archive_dir/" "$scriptdir/$archive_dir/"
# sync the build_logs from the chroot to the host system - note: $dist_name should be the same as $__os_binaries
rsync -av --delete "$chroot_build_logs/$dist_name/" "$host_build_logs/$dist_name/"
done
}
================================================
FILE: scriptmodules/admin/crosscomp/asan_limits.diff
================================================
# fixes gcc/libsanitizer/asan/asan_linux.cpp:217:21: error: ‘PATH_MAX’ was not declared in this scope
--- a/gcc/libsanitizer/asan/asan_linux.cpp
+++ b/gcc/libsanitizer/asan/asan_linux.cpp
@@ -31,7 +31,7 @@
#include <sys/types.h>
#include <dlfcn.h>
#include <fcntl.h>
-#include <limits.h>
+#include <linux/limits.h>
#include <pthread.h>
#include <stdio.h>
#include <unistd.h>
================================================
FILE: scriptmodules/admin/crosscomp/bullseye.diff
================================================
# see https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=49348beafe9ba150c9bd48595b3f372299bddbb0
diff --git a/math/Makefile b/math/Makefile
index 84a8b94c74..0a5a40430e 100644
--- a/glibc/math/Makefile
+++ b/glibc/math/Makefile
@@ -644,6 +644,128 @@
# We won't compile the `long double' code at all. Tell the `double' code
# to define aliases for the `FUNCl' names.
math-CPPFLAGS += -DNO_LONG_DOUBLE
+# GCC 10 diagnoses aliases with types conflicting with built-in
+# functions.
+CFLAGS-w_acos.c += -fno-builtin-acosl
+CFLAGS-w_acosh.c += -fno-builtin-acoshl
+CFLAGS-w_asin.c += -fno-builtin-asinl
+CFLAGS-s_asinh.c += -fno-builtin-asinhl
+CFLAGS-s_atan.c += -fno-builtin-atanl
+CFLAGS-w_atan2.c += -fno-builtin-atan2l
+CFLAGS-w_atanh.c += -fno-builtin-atanhl
+CFLAGS-s_cabs.c += -fno-builtin-cabsl
+CFLAGS-s_cacos.c += -fno-builtin-cacosl
+CFLAGS-s_cacosh.c += -fno-builtin-cacoshl
+CFLAGS-s_canonicalize.c += -fno-builtin-canonicalizel
+CFLAGS-s_carg.c += -fno-builtin-cargl
+CFLAGS-s_casin.c += -fno-builtin-casinl
+CFLAGS-s_casinh.c += -fno-builtin-casinhl
+CFLAGS-s_catan.c += -fno-builtin-catanl
+CFLAGS-s_catanh.c += -fno-builtin-catanhl
+CFLAGS-s_cbrt.c += -fno-builtin-cbrtl
+CFLAGS-s_ccos.c += -fno-builtin-ccosl
+CFLAGS-s_ccosh.c += -fno-builtin-ccoshl
+CFLAGS-s_ceil.c += -fno-builtin-ceill
+CFLAGS-s_cexp.c += -fno-builtin-cexpl
+CFLAGS-s_cimag.c += -fno-builtin-cimagl
+CFLAGS-s_clog.c += -fno-builtin-clogl
+CFLAGS-s_clog10.c += -fno-builtin-clog10l
+CFLAGS-s_conj.c += -fno-builtin-conjl
+CFLAGS-s_copysign.c += -fno-builtin-copysignl
+CFLAGS-s_cos.c += -fno-builtin-cosl
+CFLAGS-w_cosh.c += -fno-builtin-coshl
+CFLAGS-s_cpow.c += -fno-builtin-cpowl
+CFLAGS-s_cproj.c += -fno-builtin-cprojl
+CFLAGS-s_creal.c += -fno-builtin-creall
+CFLAGS-s_csin.c += -fno-builtin-csinl
+CFLAGS-s_csinh.c += -fno-builtin-csinhl
+CFLAGS-s_csqrt.c += -fno-builtin-csqrtl
+CFLAGS-s_ctan.c += -fno-builtin-ctanl
+CFLAGS-s_ctanh.c += -fno-builtin-ctanhl
+CFLAGS-s_dadd.c += -fno-builtin-daddl
+CFLAGS-s_ddiv.c += -fno-builtin-ddivl
+CFLAGS-s_dmul.c += -fno-builtin-dmull
+CFLAGS-s_dsub.c += -fno-builtin-dsubl
+CFLAGS-s_erf.c += -fno-builtin-erfl
+CFLAGS-s_erfc.c += -fno-builtin-erfcl
+CFLAGS-e_exp.c += -fno-builtin-expl
+CFLAGS-w_exp10.c += -fno-builtin-exp10l
+CFLAGS-e_exp2.c += -fno-builtin-exp2l
+CFLAGS-s_expm1.c += -fno-builtin-expm1l
+CFLAGS-s_fabs.c += -fno-builtin-fabsl
+CFLAGS-s_fadd.c += -fno-builtin-faddl
+CFLAGS-s_fdim.c += -fno-builtin-fdiml
+CFLAGS-s_fdiv.c += -fno-builtin-fdivl
+CFLAGS-s_finite.c += -fno-builtin-finitel
+CFLAGS-s_floor.c += -fno-builtin-floorl
+CFLAGS-s_fma.c += -fno-builtin-fmal
+CFLAGS-s_fmax.c += -fno-builtin-fmaxl
+CFLAGS-s_fmaxmag.c += -fno-builtin-fmaxmagl
+CFLAGS-s_fmin.c += -fno-builtin-fminl
+CFLAGS-s_fminmag.c += -fno-builtin-fminmagl
+CFLAGS-w_fmod.c += -fno-builtin-fmodl
+CFLAGS-s_fmul.c += -fno-builtin-fmull
+CFLAGS-s_frexp.c += -fno-builtin-frexpl
+CFLAGS-s_fromfp.c += -fno-builtin-fromfpl
+CFLAGS-s_fromfpx.c += -fno-builtin-fromfpxl
+CFLAGS-s_fsub.c += -fno-builtin-fsubl
+CFLAGS-s_gamma.c += -fno-builtin-gammal
+CFLAGS-s_getpayload.c += -fno-builtin-getpayloadl
+CFLAGS-w_hypot.c += -fno-builtin-hypotl
+CFLAGS-w_ilogb.c += -fno-builtin-ilogbl
+CFLAGS-s_isinf.c += -fno-builtin-isinfl
+CFLAGS-s_isnan.c += -fno-builtin-isnanl
+CFLAGS-w_j0.c += -fno-builtin-j0l
+CFLAGS-w_j1.c += -fno-builtin-j1l
+CFLAGS-w_jn.c += -fno-builtin-jnl
+CFLAGS-s_ldexp.c += -fno-builtin-ldexpl
+CFLAGS-w_lgamma.c += -fno-builtin-lgammal
+CFLAGS-w_lgamma_r.c += -fno-builtin-lgammal_r
+CFLAGS-w_llogb.c += -fno-builtin-llogbl
+CFLAGS-s_llrint.c += -fno-builtin-llrintl
+CFLAGS-s_llround.c += -fno-builtin-llroundl
+CFLAGS-e_log.c += -fno-builtin-logl
+CFLAGS-w_log10.c += -fno-builtin-log10l
+CFLAGS-w_log1p.c += -fno-builtin-log1pl
+CFLAGS-e_log2.c += -fno-builtin-log2l
+CFLAGS-s_logb.c += -fno-builtin-logbl
+CFLAGS-s_lrint.c += -fno-builtin-lrintl
+CFLAGS-s_lround.c += -fno-builtin-lroundl
+CFLAGS-s_modf.c += -fno-builtin-modfl
+CFLAGS-s_nan.c += -fno-builtin-nanl
+CFLAGS-s_nearbyint.c += -fno-builtin-nearbyintl
+CFLAGS-s_nextafter.c += -fno-builtin-nextafterl
+CFLAGS-s_nextdown.c += -fno-builtin-nextdownl
+CFLAGS-s_nexttoward.c += -fno-builtin-nexttoward -fno-builtin-nexttowardl
+CFLAGS-s_nexttowardf.c += -fno-builtin-nexttowardf
+CFLAGS-s_nextup.c += -fno-builtin-nextupl
+CFLAGS-e_pow.c += -fno-builtin-powl
+CFLAGS-w_remainder.c += -fno-builtin-remainderl -fno-builtin-dreml
+CFLAGS-s_remquo.c += -fno-builtin-remquol
+CFLAGS-s_rint.c += -fno-builtin-rintl
+CFLAGS-s_round.c += -fno-builtin-roundl
+CFLAGS-s_roundeven.c += -fno-builtin-roundevenl
+CFLAGS-w_scalb.c += -fno-builtin-scalbl
+CFLAGS-w_scalbln.c += -fno-builtin-scalblnl
+CFLAGS-s_scalbn.c += -fno-builtin-scalbnl
+CFLAGS-s_setpayload.c += -fno-builtin-setpayloadl
+CFLAGS-s_setpayloadsig.c += -fno-builtin-setpayloadsigl
+CFLAGS-s_significand.c += -fno-builtin-significandl
+CFLAGS-s_sin.c += -fno-builtin-sinl
+CFLAGS-s_sincos.c += -fno-builtin-sincosl
+CFLAGS-w_sinh.c += -fno-builtin-sinhl
+CFLAGS-w_sqrt.c += -fno-builtin-sqrtl
+CFLAGS-s_tan.c += -fno-builtin-tanl
+CFLAGS-s_tanh.c += -fno-builtin-tanhl
+CFLAGS-w_tgamma.c += -fno-builtin-tgammal
+CFLAGS-s_totalorder.c += -fno-builtin-totalorderl
+CFLAGS-s_totalordermag.c += -fno-builtin-totalordermagl
+CFLAGS-s_trunc.c += -fno-builtin-truncl
+CFLAGS-s_ufromfp.c += -fno-builtin-ufromfpl
+CFLAGS-s_ufromfpx.c += -fno-builtin-ufromfpxl
+CFLAGS-s_y0.c += -fno-builtin-y0l
+CFLAGS-s_y1.c += -fno-builtin-y1l
+CFLAGS-s_yn.c += -fno-builtin-ynl
endif
# These files quiet sNaNs in a way that is optimized away without
================================================
FILE: scriptmodules/admin/crosscomp.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="crosscomp"
rp_module_desc="Create am arm cross compiler env - based on examples from http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler"
rp_module_help="Can be used via distcc to build RetroPie binaries"
rp_module_section=""
rp_module_flags="!arm"
function _default_dist_crosscomp() {
echo "buster"
}
function depends_crosscomp() {
getDepends distcc
}
function sources_crosscomp() {
local dist="$1"
[[ -z "$dist" ]] && return
declare -A pkgs
case "$dist" in
stretch)
pkgs=(
[binutils]=2.28
[gcc]=6.4.0
[glibc]=2.24
[gmp]=6.1.2
[kernel]=4.9.80
[mpfr]=3.1.5
[mpc]=1.0.3
)
;;
buster)
pkgs=(
[binutils]=2.31.1
[gcc]=8.3.0
[glibc]=2.28
[gmp]=6.1.2
[kernel]=4.19.50
[mpfr]=4.0.2
[mpc]=1.1.0
)
;;
bullseye)
pkgs=(
[binutils]=2.35.2
[gcc]=10.2.0
[glibc]=2.31
[gmp]=6.2.1
[kernel]=5.15.61
[mpfr]=4.1.0
[mpc]=1.2.0
)
;;
bookworm)
pkgs=(
[binutils]=2.40
[gcc]=12.2.0
[glibc]=2.36
[gmp]=6.2.1
[kernel]=6.1
[mpfr]=4.2.0
[mpc]=1.3.1
)
;;
*)
md_ret_errors+=("Unsupported distribution $dist")
return 1
;;
esac
downloadAndExtract "https://ftp.gnu.org/gnu/binutils/binutils-${pkgs[binutils]}.tar.gz" binutils --strip-components 1
downloadAndExtract "https://ftp.gnu.org/gnu/mpfr/mpfr-${pkgs[mpfr]}.tar.gz" mpfr --strip-components 1
downloadAndExtract "https://ftp.gnu.org/gnu/gmp/gmp-${pkgs[gmp]}.tar.bz2" gmp --strip-components 1
downloadAndExtract "https://ftp.gnu.org/gnu/mpc/mpc-${pkgs[mpc]}.tar.gz" mpc --strip-components 1
downloadAndExtract "https://ftp.gnu.org/gnu/glibc/glibc-${pkgs[glibc]}.tar.bz2" glibc --strip-components 1
downloadAndExtract "https://ftp.gnu.org/gnu/gcc/gcc-${pkgs[gcc]}/gcc-${pkgs[gcc]}.tar.gz" gcc --strip-components 1
downloadAndExtract "https://www.kernel.org/pub/linux/kernel/v${pkgs[kernel]:0:1}.x/linux-${pkgs[kernel]}.tar.gz" linux --strip-components 1
local pkg
for pkg in gmp mpc mpfr; do
ln -sf "../$pkg" "gcc/$pkg"
done
# apply glibc patch required when compiling with GCC 10+
# see https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=49348beafe9ba150c9bd48595b3f372299bddbb0
if [[ "$dist" == "bullseye" ]]; then
applyPatch "$md_data/bullseye.diff"
fi
# fix incorrect limits.h include.
if compareVersions "${pkgs[gcc]}" ge 10; then
applyPatch "$md_data/asan_limits.diff"
fi
}
function build_crosscomp() {
local dist="$1"
[[ -z "$dist" ]] && return
# remove old build directories
rm -rf "$md_build/build-"*
local params=(--with-arch=armv6 --with-fpu=vfp --with-float=hard)
local target=arm-linux-gnueabihf
local dest="$md_inst/$dist"
local old_path="$PATH"
export PATH="$dest/bin:$old_path"
export ASFLAGS=""
export CFLAGS="-O2"
export CXXFLAGS="-O2"
# binutils
printHeading "Building binutils"
mkdir -p build-binutils
cd build-binutils
../binutils/configure --prefix="$dest" --target="$target" "${params[@]}"
make
make install
cd ..
# kernel headers
printHeading "Installing kernel headers"
cd linux
make ARCH=arm INSTALL_HDR_PATH="$dest/$target" headers_install
cd ..
# gcc
printHeading "Building gcc"
mkdir -p build-gcc
cd build-gcc
../gcc/configure --prefix="$dest" --target="$target" --enable-languages=c,c++ --disable-multilib --disable-werror "${params[@]}"
make all-gcc
make install-gcc
cd ..
# glibc
printHeading "Building glibc"
mkdir -p build-glibc
cd build-glibc
../glibc/configure --prefix="$dest/$target" --build="$MACHTYPE" --host="$target" --target="$target" --with-headers="$dest/$target/include" libc_cv_forced_unwind=yes
make install-bootstrap-headers=yes install-headers
make csu/subdir_lib
install csu/crt1.o csu/crti.o csu/crtn.o "$dest/$target/lib"
"$target-gcc" -nostdlib -nostartfiles -shared -x c /dev/null -o "$dest/$target/lib/libc.so"
touch "$dest/$target/include/gnu/stubs.h"
cd ..
# compiler support library
printHeading "Building libgcc"
cd build-gcc
make all-target-libgcc
make install-target-libgcc
cd ..
# standard c library
printHeading "Building glibc (2)"
cd build-glibc
make
make install
cd ..
# standard c++ library
printHeading "Building libcpp"
cd build-gcc
make all
make install
cd ..
export PATH="$old_path"
export ASFLAGS="$__asflags"
export CFLAGS="$__cflags"
export CXXFLAGS="$__cxxflags"
}
function setup_crosscomp() {
local dist="$1"
[[ -z "$dist" ]] && dist="$(_default_dist_crosscomp)"
if rp_callModule crosscomp sources "$dist"; then
rp_callModule crosscomp build "$dist"
rp_callModule crosscomp clean
fi
}
function setup_all_crosscomp() {
local dist
for dist in stretch buster bullseye; do
setup_crosscomp "$dist"
done
}
function configure_distcc_crosscomp() {
local dist="$1"
[[ -z "$dist" ]] && return 1
local port="$2"
[[ -z "$port" ]] && return 1
local bin_dir="$md_inst/$dist/bin"
# add additional symlinks for cc/gcc/c++/g++
local name
for name in cc gcc; do
ln -sfv "arm-linux-gnueabihf-gcc" "$bin_dir/$name"
done
for name in c++ g++; do
ln -sfv "arm-linux-gnueabihf-g++" "$bin_dir/$name"
done
local initd_script="/etc/init.d/distcc-$dist"
# duplicate distcc init.d script
cp /etc/init.d/distcc "$initd_script"
# add dist to NAME in new init.d
sed -i "s/NAME=distccd/NAME=distccd-$dist/" "$initd_script"
# add custom port to new init.d
sed -i "s/--daemon\"/--daemon --port $port\"/" "$initd_script"
# add the $dist cross compiler bin path to new init.d
local replace="PATH=$bin_dir:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin"
# if the PATH line exists, replace it (older distcc init.d script)
if grep -q "PATH=" "$initd_script"; then
sed -i "s#^PATH=.*#$replace#" "$initd_script"
# otherwise, insert it before the DAEMON= line (newer distcc init.d script)
else
sed -i "/^DAEMON=.*/i $replace" "$initd_script"
fi
# create log file
local log="/var/log/distccd-$dist.log"
touch "$log"
chown distccd:nogroup "$log"
# restart distcc
systemctl daemon-reload
service distcc restart
}
================================================
FILE: scriptmodules/admin/image/dists/rpios-bookworm-64.ini
================================================
name="bookworm-64"
version="12"
url="https://downloads.raspberrypi.com/raspios_oldstable_lite_arm64/images/raspios_oldstable_lite_arm64-2025-11-24/2025-11-24-raspios-bookworm-arm64-lite.img.xz"
format="xz"
platforms="rpi3 rpi4 rpi5"
file_rpi3="rpi3"
title_rpi3="Raspberry Pi 3"
file_rpi4="rpi4"
title_rpi4="Raspberry Pi 4"
file_rpi5="rpi5"
title_rpi5="Raspberry Pi 5"
================================================
FILE: scriptmodules/admin/image/dists/rpios-bookworm.ini
================================================
name="bookworm"
version="12"
url="https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2025-11-24/2025-11-24-raspios-bookworm-armhf-lite.img.xz"
format="xz"
platforms="rpi1 rpi2 rpi3 rpi4 rpi5"
file_rpi1="rpi1_zero"
title_rpi1="RPI 1/Zero"
file_rpi2="rpi2"
title_rpi2="RPI 2"
file_rpi3="rpi3_zero2w"
title_rpi3="RPI 3/Zero 2 W"
file_rpi4="rpi4_400"
title_rpi4="RPI 4/400"
file_rpi5="rpi5"
title_rpi5="RPI 5"
================================================
FILE: scriptmodules/admin/image/dists/rpios-bullseye.ini
================================================
name="bullseye"
version="11"
url="https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2025-05-07/2025-05-06-raspios-bullseye-armhf-lite.img.xz"
format="xz"
platforms="rpi1 rpi2 rpi3 rpi4"
file_rpi1="rpi1_zero"
title_rpi1="RPI 1/Zero"
file_rpi2="rpi2"
title_rpi2="RPI 2"
file_rpi3="rpi3_zero2w"
title_rpi3="RPI 3/Zero 2 W"
file_rpi4="rpi4_400"
title_rpi4="RPI 4/400"
================================================
FILE: scriptmodules/admin/image/dists/rpios-buster.ini
================================================
name="buster"
version="10"
url="https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_lite_armhf-2023-05-03/2023-05-03-raspios-buster-armhf-lite.img.xz"
format="xz"
platforms="rpi1 rpi2 rpi4"
file_rpi1="rpi1_zero"
title_rpi1="RPI 1/Zero"
file_rpi2="rpi2_3_zero2w"
title_rpi2="RPI 2/3/Zero 2 W"
file_rpi4="rpi4_400"
title_rpi4="RPI 4/400"
================================================
FILE: scriptmodules/admin/image/dists/rpios-jessie.ini
================================================
name="jessie"
version="8"
url="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2017-07-05/2017-07-05-raspbian-jessie-lite.zip"
format="zip"
platforms="rpi1 rpi2"
file_rpi1="rpi1_zero"
title_rpi1="RPI 1/Zero"
file_rpi2="rpi2_3"
title_rpi2="RPI 2/3"
================================================
FILE: scriptmodules/admin/image/dists/rpios-stretch.ini
================================================
name="stretch"
version="9"
url="https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-04-09/2019-04-08-raspbian-stretch-lite.zip"
format="zip"
platforms="rpi1 rpi2"
file_rpi1="rpi1_zero"
title_rpi1="RPI 1/Zero"
file_rpi2="rpi2_3"
title_rpi2="RPI 2/3"
================================================
FILE: scriptmodules/admin/image/template.json
================================================
{
"url": "https://github.com/RetroPie/RetroPie-Setup/releases/download/IMG_PATH",
"extract_size": IMG_EXTRACT_SIZE,
"extract_sha256": "IMG_SHA256",
"image_download_size": IMG_DOWNLOAD_SIZE,
"description": "Turn your Raspberry Pi into a retro-gaming machine.",
"icon": "https://retropie.org.uk/retropie-logo-40x40.png",
"name": "RetroPie IMG_VERSION (IMG_PLATFORM)",
"release_date": "IMG_DATE",
"website": "https://retropie.org.uk"
}
================================================
FILE: scriptmodules/admin/image.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="image"
rp_module_desc="Create/Manage RetroPie images"
rp_module_section=""
rp_module_flags=""
function depends_image() {
local depends=(kpartx unzip binfmt-support rsync parted squashfs-tools dosfstools e2fsprogs xz-utils)
isPlatform "x86" && depends+=(qemu-user-binfmt)
getDepends "${depends[@]}"
# enable C flag in qemu-aarch64/qemu-arm binfmt_misc override to allow suid binaries in emulated chroot
if isPlatform "x86"; then
local platform
for platform in arm aarch64; do
local config="qemu-$platform.conf"
local src_config="/usr/lib/binfmt.d/$config"
local dest_config="/etc/binfmt.d/$config"
if [[ ! -f "$dest_config" ]]; then
printMsgs "console" "Adding C flag to $src_config (overriding in $dest_config)"
sed "s/$/C/" "/usr/lib/binfmt.d/$config" >"/etc/binfmt.d/$config"
fi
done
systemctl restart systemd-binfmt
fi
}
function _get_info_image() {
local dist="$1"
local key="$2"
# don't use $md_data so this function can be used directly from builder.sh
local ini="${__mod_info[image/path]%/*}/image/dists/${dist}.ini"
# if the file is found try and extract the value else echo an empty string
if [[ -f "$ini" ]]; then
iniConfig "=" "\"" "$ini"
iniGet "$key"
echo "$ini_value"
else
echo ""
fi
}
function create_chroot_image() {
local dist="$1"
[[ -z "$dist" ]] && return 1
local chroot="$2"
[[ -z "$chroot" ]] && chroot="$md_build/$dist"
mkdir -p "$md_build"
pushd "$md_build"
mkdir -p "$chroot"
local url=$(_get_info_image "$dist" "url")
[[ -z "$url" ]] && fatalError "Unable to get url information for $dist"
local format=$(_get_info_image "$dist" "format")
[[ -z "$format" ]] && fatalError "Unable to get format information for $dist"
local base="raspbian-${dist}-lite"
local image="${dist}.img"
local dest="${image}.${format}"
if [[ ! -f "$image" ]]; then
case "$format" in
zip)
download "$url" "$dest"
unzip -o "$dest"
mv "$(unzip -Z -1 "$dest")" "$image"
rm "$dest"
;;
xz)
download "$url" "$dest"
xz -d -v "$dest"
;;
esac
fi
# abort if there is no extracted image present
[[ ! -f "$image" ]] && return 1
# mount image
local partitions=($(kpartx -s -a -v "$image" | awk '{ print "/dev/mapper/"$3 }'))
local part_boot="${partitions[0]}"
local part_root="${partitions[1]}"
# get temporary directory
local tmp="$(mktemp -d -p "$md_build")"
# mount root partition
mount "$part_root" "$tmp"
# get the mount location of the boot partition from etc/fstab
local boot_path="$(_get_boot_path_image "$tmp")"
# create the boot partition mountpoint and mount
mkdir -p "$tmp$boot_path"
mount "$part_boot" "$tmp$boot_path"
printMsgs "console" "Creating chroot from $image ..."
rsync -aAHX --numeric-ids --delete "$tmp/" "$chroot/"
# fix up raspberry pi repos for buster image building (see buster_fix_apt_raspbiantools in raspbiantools.sh scriptmodule)
if [[ "$dist" == "rpios-buster" ]]; then
sed -i "s/raspbian\.raspberrypi\.org/legacy.raspbian.org/" "$chroot/etc/apt/sources.list"
fi
umount -l "$tmp$boot_path" "$tmp"
rm -rf "$tmp"
dmsetup remove "${partitions[@]}"
kpartx -d "$image"
popd
return 0
}
function _get_boot_path_image() {
local chroot="$1"
# extract boot partition mount location from fstab
awk '$3=="vfat" {print $2}' "$chroot/etc/fstab"
}
function install_rp_image() {
local platform="$1"
if [[ -z "$platform" ]]; then
printMsgs "console" "Requires a platform (eg rpi3/rpi4)"
return 1
fi
local dist="$2"
if [[ -z "$dist" ]]; then
printMsgs "Requires a distribution name (eg rpios-buster/rpios-bullseye)"
return 1
fi
local chroot="$3"
[[ -z "$chroot" ]] && chroot="$md_build/$dist"
local dist_version="$(_get_info_image "$dist" "version")"
[[ -z "$dist_version" ]] && fatalError "Unable to get version information for $dist"
# hostname to retropie
echo "retropie" >"$chroot/etc/hostname"
sed -i "s/raspberrypi/retropie/" "$chroot/etc/hosts"
local boot_path="$(_get_boot_path_image "$chroot")"
# quieter boot / disable plymouth (as without the splash parameter it
# causes all boot messages to be displayed and interferes with people
# using tty3 to make the boot even quieter)
if ! grep -q consoleblank "$chroot$boot_path/cmdline.txt"; then
# extra quiet as the raspbian usr/lib/raspi-config/init_resize.sh does
# sed -i 's/ quiet init=.*$//' /boot/cmdline.txt so this will remove the last quiet
# and the init line but leave ours intact
sed -i "s/quiet/quiet loglevel=3 consoleblank=0 plymouth.enable=0 quiet/" "$chroot/boot/cmdline.txt"
fi
iniConfig "=" "" "$chroot$boot_path/config.txt"
# set default GPU mem (videocore only)
if [[ "$dist_version" -lt 11 && "$platform" == rpi[123] ]]; then
iniSet "gpu_mem_256" 128
iniSet "gpu_mem_512" 256
iniSet "gpu_mem_1024" 256
fi
# set overscan_scale so ES scales to overscan settings.
iniSet "overscan_scale" 1
# disable 64bit kernel on 32bit userland OSs (to disable rpi4 defaulting to 64bit kernel)
# 64 bit distros end in -64
if [[ "$dist" != *-64 ]]; then
iniSet "arm_64bit" 0
# otherwise if on 64bit switch to using the 4k page size kernel
else
iniSet "kernel" "kernel8.img"
fi
[[ -z "$__chroot_repo" ]] && __chroot_repo="https://github.com/RetroPie/RetroPie-Setup.git"
[[ -z "$__chroot_branch" ]] && __chroot_branch="master"
# fix up initramfs-tools installation in a chroot (can't find root partition, workaround is to use MODULES=most)
local config="$chroot/etc/initramfs-tools/initramfs.conf"
if [[ -f "$config" ]]; then
sed -i "s/MODULES=dep/MODULES=most/" "$config"
fi
cat > "$chroot/home/pi/install.sh" <<_EOF_
#!/bin/bash
cd
if systemctl is-enabled userconfig &>/dev/null; then
echo "pi:raspberry" | sudo chpasswd
sudo systemctl disable userconfig
sudo systemctl --quiet enable getty@tty1
fi
sudo apt-get update
sudo apt-get -y install git dialog xmlstarlet joystick
git clone -b "$__chroot_branch" "$__chroot_repo"
cd RetroPie-Setup
modules=(
'raspbiantools apt_upgrade'
'setup basic_install'
'bluetooth depends'
'raspbiantools enable_modules'
'autostart enable'
'usbromservice'
'samba depends'
'samba install_shares'
'splashscreen default'
'splashscreen enable'
'bashwelcometweak'
'xpad'
)
for module in "\${modules[@]}"; do
sudo __platform=$platform __nodialog=1 __has_binaries=$__chroot_has_binaries ./retropie_packages.sh \$module
done
sudo rm -rf tmp
sudo apt-get clean
_EOF_
# chroot and run install script
rp_callModule image chroot "$chroot" bash /home/pi/install.sh
rm "$chroot/home/pi/install.sh"
# restore initramfs-tools config to default
if [[ -f "$config" ]]; then
sed -i "s/MODULES=most/MODULES=dep/" "$config"
fi
# remove any ssh host keys that may have been generated during any ssh package upgrades
rm -f "$chroot/etc/ssh/ssh_host"*
}
function _init_chroot_image() {
local chroot="$1"
[[ -z "$chroot" ]] && return 1
# unmount on ctrl+c
trap "_trap_chroot_image '$chroot'" INT
# mount special filesystems to chroot
mkdir -p "$chroot"{/dev/pts,/proc,/sys}
mount none -t devpts "$chroot/dev/pts"
mount -t proc /proc "$chroot/proc"
mount -t sysfs /sys "$chroot/sys"
local nameserver="$__nameserver"
[[ -z "$nameserver" ]] && nameserver="$(nmcli device show | grep IP4.DNS | awk '{print $NF; exit}')"
# so we can resolve inside the chroot
echo "nameserver $nameserver" >"$chroot/etc/resolv.conf"
# move /etc/ld.so.preload out of the way to avoid warnings
if [[ -f "$chroot/etc/ld.so.preload" ]]; then
mv "$chroot/etc/ld.so.preload" "$chroot/etc/ld.so.preload.bak"
fi
}
function _deinit_chroot_image() {
local chroot="$1"
[[ -z "$chroot" ]] && return 1
trap "" INT
>"$chroot/etc/resolv.conf"
# restore /etc/ld.so.preload if backup present
if [[ -f "$chroot/etc/ld.so.preload.bak" ]]; then
mv "$chroot/etc/ld.so.preload.bak" "$chroot/etc/ld.so.preload"
fi
umount -l "$chroot/proc" "$chroot/dev/pts" "$chroot/sys"
trap INT
}
function _trap_chroot_image() {
_deinit_chroot_image "$1"
exit
}
function chroot_image() {
local chroot="$1"
[[ -z "$chroot" ]] && return 1
shift
printMsgs "console" "Chrooting to $chroot ..."
_init_chroot_image "$chroot"
HOME="/home/pi" chroot --userspec 1000:1000 "$chroot" "$@"
_deinit_chroot_image "$chroot"
}
function create_image() {
local image="$1"
[[ -z "$image" ]] && return 1
local chroot="$2"
[[ -z "$chroot" ]] && chroot="$md_build/chroot"
local boot_size_mib="$3"
# if not specified default the boot size partition to 512MiB
[[ -z "$boot_size_mib" ]] && boot_size_mib=512
# get size of files in MiB
local chroot_size_mib=$(du -s -m "$chroot" 2>/dev/null | cut -f1)
# make image size 256MiB larger than contents of chroot and boot partition
local image_size_mib=$((boot_size_mib + chroot_size_mib + 256))
# create image
printMsgs "console" "Creating image $image ..."
dd if=/dev/zero of="$image" bs=1M count="$image_size_mib"
# partition
printMsgs "console" "partitioning $image ..."
local boot_start_mib=8
local boot_end_mib=$((boot_start_mib + boot_size_mib))
parted -s "$image" -- \
mklabel msdos \
unit mib \
mkpart primary fat32 $boot_start_mib $boot_end_mib \
mkpart primary $boot_end_mib -1s
# format
printMsgs "console" "Formatting $image ..."
# change to the image folder as kpartx has problems removing the
# device mapper files when using a full path to the image
local image_path="${image%/*}"
local image_name="${image##*/}"
pushd "$image_path"
local partitions=($(kpartx -s -a -v "$image_name" | awk '{ print "/dev/mapper/"$3 }'))
local part_boot="${partitions[0]}"
local part_root="${partitions[1]}"
mkfs.vfat -F 32 -n bootfs "$part_boot"
# use the mke2fs config from the chroot so we create the filesystem with supported features
# disable huge_file & 64bit as with the Raspberry Pi OS images
MKE2FS_CONFIG="$chroot/etc/mke2fs.conf" mkfs.ext4 -O ^huge_file,^64bit -L retropie "$part_root"
parted "$image_name" print
# disable ctrl+c
trap "" INT
# mount
printMsgs "console" "Mounting $image_name ..."
# get temporary directory
local tmp="$(mktemp -d -p "$md_build")"
# mount root partition
mount "$part_root" "$tmp"
# get the mount location of the boot partition from etc/fstab
local boot_path="$(_get_boot_path_image "$chroot")"
# create the boot partition mountpoint and mount
mkdir -p "$tmp$boot_path"
mount "$part_boot" "$tmp$boot_path"
# copy files
printMsgs "console" "Rsyncing chroot to $image_name ..."
rsync -aAHX --numeric-ids "$chroot/" "$tmp/"
# we need to fix up the UUIDS for /boot/cmdline.txt and /etc/fstab
local old_id="$(sed "s/.*PARTUUID=\([^-]*\).*/\1/" $tmp$boot_path/cmdline.txt)"
local new_id="$(blkid -s PARTUUID -o value "$part_root" | cut -c -8)"
sed -i "s/$old_id/$new_id/" "$tmp$boot_path/cmdline.txt"
sed -i "s/$old_id/$new_id/g" "$tmp/etc/fstab"
# unmount
umount -l "$tmp$boot_path" "$tmp"
rm -rf "$tmp"
kpartx -d "$image_name"
trap INT
}
# generate berryboot squashfs from filesystem
function create_bb_image() {
local image="$1"
[[ -z "$image" ]] && return 1
local chroot="$2"
[[ -z "$chroot" ]] && return 1
# replace fstab
echo "proc /proc proc defaults 0 0" >"$chroot/etc/fstab"
# remove any earlier image
rm -f "$image"
mksquashfs "$chroot" "$image" -comp lzo -e boot -e lib/modules
}
function all_image() {
local dist="$1"
local make_bb="$2"
local platforms="$(_get_info_image "$dist" "platforms")"
[[ -z "$platforms" ]] && fatalError "Unable to get platforms information for $dist"
local platform
printMsgs "heading" "Building $platforms images based on $dist ..."
for platform in $platforms; do
platform_image "$platform" "$dist" "$make_bb"
done
combine_json_image
}
function platform_image() {
local platform="$1"
local dist="$2"
local make_bb="$3"
[[ -z "$platform" ]] && return 1
local dest="$__tmpdir/images"
mkdir -p "$dest"
printMsgs "heading" "Building $platform image based on $dist ..."
rp_callModule image create_chroot "$dist"
rp_callModule image install_rp "$platform" "$dist" "$md_build/$dist"
local dist_name="$(_get_info_image "$dist" "name")"
[[ -z "$dist_name" ]] && fatalError "Unable to get name information for $dist"
local dist_version="$(_get_info_image "$dist" "version")"
[[ -z "$dist_version" ]] && fatalError "Unable to get version information for $dist"
local file_add="$(_get_info_image "$dist" "file_${platform}")"
[[ -z "$file_add" ]] && fatalError "Unable to get file_* information for $dist"
local image_title="$(_get_info_image "$dist" "title_${platform}")"
[[ -z "$image_title" ]] && fatalError "Unable to get image_title information for $dist"
local image_base="retropie-${dist_name}-${__version}-${file_add}"
local image_name="${image_base}.img"
local image_file="$dest/$image_name"
local boot_size_mib=512
# use a 256MiB boot partition for Raspberry Pi OS lower than 12 (Bullseye and below)
if [[ "$dist_version" -lt 12 ]]; then
boot_size_mib=256
fi
rp_callModule image create "$image_file" "$md_build/$dist" $boot_size_mib
[[ "$make_bb" -eq 1 ]] && rp_callModule image create_bb "$dest/${image_base}-berryboot.img256"
printMsgs "console" "Compressing ${image_name} ..."
xz -v --compress --stdout "$image_file" > "${image_file}.xz"
printMsgs "console" "Generating JSON data for rpi-imager ..."
local template
template="$(<"$md_data/template.json")"
template="${template/IMG_PATH/$__version\/${image_name}.xz}"
template="${template/IMG_EXTRACT_SIZE/$(stat -c %s $image_file)}"
template="${template/IMG_SHA256/$(sha256sum $image_file | cut -d" " -f1)}"
template="${template/IMG_DOWNLOAD_SIZE/$(stat -c %s ${image_file}.xz)}"
template="${template/IMG_VERSION/$__version}"
template="${template/IMG_PLATFORM/$image_title}"
template="${template/IMG_DATE/$(date '+%Y-%m-%d')}"
echo "$template" >"${image_file}.json"
rm -f "$image_file"
}
function combine_json_image() {
local dest="$__tmpdir/images"
{
local template
echo -en "{\n \"os_list\": [\n"
local i=0
while read file; do
[[ "$i" -gt 0 ]] && echo -en ",\n"
template="$(<$file)"
echo -n "$template"
((i++))
done < <(find "$dest" -name "*.img.json" | sort)
echo -en "\n ]\n}\n"
} >"$dest/os_list_imagingutility.json"
}
================================================
FILE: scriptmodules/admin/joy2key/joy2key.py
================================================
#!/usr/bin/python3
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
import os, sys, struct, time, fcntl, termios, signal
import curses, errno, re
from pyudev import Context
# struct js_event {
# __u32 time; /* event timestamp in milliseconds */
# __s16 value; /* value */
# __u8 type; /* event type */
# __u8 number; /* axis/button number */
# };
JS_MIN = -32768
JS_MAX = 32768
JS_REP = 0.20
JS_THRESH = 0.75
JS_EVENT_BUTTON = 0x01
JS_EVENT_AXIS = 0x02
JS_EVENT_INIT = 0x80
CONFIG_DIR = '/opt/retropie/configs/'
RETROARCH_CFG = CONFIG_DIR + 'all/retroarch.cfg'
def ini_get(key, cfg_file):
pattern = r'[ |\t]*' + key + r'[ |\t]*=[ |\t]*'
value_m = r'"*([^"\|\r]*)"*'
value = ''
with open(cfg_file, 'r') as ini_file:
for line in ini_file:
if re.match(pattern, line):
value = re.sub(pattern + value_m + '.*\n', r'\1', line)
break
return value
def get_btn_num(btn, cfg):
num = ini_get('input_' + btn + '_btn', cfg)
if num: return num
num = ini_get('input_player1_' + btn + '_btn', cfg)
if num: return num
return ''
def sysdev_get(key, sysdev_path):
value = ''
for line in open(sysdev_path + key, 'r'):
value = line.rstrip('\n')
break
return value
def get_button_codes(dev_path):
js_cfg_dir = CONFIG_DIR + 'all/retroarch-joypads/'
js_cfg = ''
dev_name = ''
dev_button_codes = list(default_button_codes)
for device in Context().list_devices(DEVNAME=dev_path):
sysdev_path = os.path.normpath('/sys' + device.get('DEVPATH')) + '/'
if not os.path.isfile(sysdev_path + 'name'):
sysdev_path = os.path.normpath(sysdev_path + '/../') + '/'
# getting joystick name
dev_name = sysdev_get('name', sysdev_path)
# getting joystick vendor ID
dev_vendor_id = int(sysdev_get('id/vendor', sysdev_path), 16)
# getting joystick product ID
dev_product_id = int(sysdev_get('id/product', sysdev_path), 16)
if not dev_name:
return dev_button_codes
# getting retroarch config file for joystick
for f in os.listdir(js_cfg_dir):
if f.endswith('.cfg'):
input_device = ini_get('input_device', js_cfg_dir + f)
input_vendor_id = ini_get('input_vendor_id', js_cfg_dir + f)
input_product_id = ini_get('input_product_id', js_cfg_dir + f)
if (input_device == dev_name and
(input_vendor_id == '' or int(input_vendor_id) == dev_vendor_id) and
(input_product_id == '' or int(input_product_id) == dev_product_id)):
js_cfg = js_cfg_dir + f
break
if not js_cfg:
js_cfg = RETROARCH_CFG
# getting configs for dpad, buttons A, B, X and Y
btn_map = [ 'left', 'right', 'up', 'down', 'a', 'b', 'x', 'y' ]
btn_num = {}
biggest_num = 0
i = 0
for btn in list(btn_map):
if i >= len(dev_button_codes):
break
try:
btn_num[btn] = int(get_btn_num(btn, js_cfg))
except ValueError:
btn_map.pop(i)
dev_button_codes.pop(i)
btn_num.pop(btn, None)
continue
if btn_num[btn] > biggest_num:
biggest_num = btn_num[btn]
i += 1
# building the button codes list
btn_codes = [''] * (biggest_num + 1)
i = 0
for btn in btn_map:
if i >= len(dev_button_codes):
break
btn_codes[btn_num[btn]] = dev_button_codes[i]
i += 1
try:
# if button A is <enter> and menu_swap_ok_cancel_buttons is true, swap buttons A and B functions
if (ini_get('menu_swap_ok_cancel_buttons', RETROARCH_CFG) == 'true' and
'a' in btn_num and 'b' in btn_num and btn_codes[btn_num['a']] == '\n'):
btn_codes[btn_num['a']] = btn_codes[btn_num['b']]
btn_codes[btn_num['b']] = '\n'
except (IOError, ValueError):
pass
return btn_codes
def signal_handler(signum, frame):
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
if (js_fds):
close_fds(js_fds)
if (tty_fd):
os.close(tty_fd)
sys.exit(0)
def get_hex_chars(key_str):
if (key_str.startswith("0x")):
out = bytes.fromhex(key_str[2:])
else:
out = curses.tigetstr(key_str)
return out.decode('utf-8')
def get_devices():
devs = []
if sys.argv[1] == '/dev/input/jsX':
for dev in os.listdir('/dev/input'):
if dev.startswith('js'):
devs.append('/dev/input/' + dev)
else:
devs.append(sys.argv[1])
return devs
def open_devices():
devs = get_devices()
fds = []
for dev in devs:
try:
fds.append(os.open(dev, os.O_RDONLY | os.O_NONBLOCK ))
js_button_codes[fds[-1]] = get_button_codes(dev)
except (OSError, ValueError):
pass
return devs, fds
def close_fds(fds):
for fd in fds:
os.close(fd)
def read_event(fd):
while True:
try:
event = os.read(fd, event_size)
except OSError as e:
if e.errno == errno.EWOULDBLOCK:
return None
return False
else:
return event
def process_event(event):
(js_time, js_value, js_type, js_number) = struct.unpack(event_format, event)
# ignore init events
if js_type & JS_EVENT_INIT:
return False
hex_chars = ""
if js_type == JS_EVENT_BUTTON:
if js_number < len(button_codes) and js_value == 1:
hex_chars = button_codes[js_number]
if js_type == JS_EVENT_AXIS and js_number <= 7:
if js_number % 2 == 0:
if js_value <= JS_MIN * JS_THRESH:
hex_chars = axis_codes[0]
if js_value >= JS_MAX * JS_THRESH:
hex_chars = axis_codes[1]
if js_number % 2 == 1:
if js_value <= JS_MIN * JS_THRESH:
hex_chars = axis_codes[2]
if js_value >= JS_MAX * JS_THRESH:
hex_chars = axis_codes[3]
if hex_chars:
for c in hex_chars:
fcntl.ioctl(tty_fd, termios.TIOCSTI, c)
return True
return False
js_fds = []
tty_fd = []
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# daemonize when signal handlers are registered
if os.fork():
os._exit(0)
js_button_codes = {}
button_codes = []
default_button_codes = []
axis_codes = []
curses.setupterm()
i = 0
for arg in sys.argv[2:]:
chars = get_hex_chars(arg)
if i < 4:
axis_codes.append(chars)
default_button_codes.append(chars)
i += 1
event_format = 'IhBB'
event_size = struct.calcsize(event_format)
try:
tty_fd = os.open('/dev/tty', os.O_WRONLY)
except IOError:
print('Unable to open /dev/tty', file = sys.stderr)
sys.exit(1)
rescan_time = time.time()
while True:
do_sleep = True
if not js_fds:
js_devs, js_fds = open_devices()
if js_fds:
i = 0
current = time.time()
js_last = [None] * len(js_fds)
for js in js_fds:
js_last[i] = current
i += 1
else:
time.sleep(1)
else:
i = 0
for fd in js_fds:
event = read_event(fd)
if event:
do_sleep = False
if time.time() - js_last[i] > JS_REP:
if fd in js_button_codes:
button_codes = js_button_codes[fd]
else:
button_codes = default_button_codes
if process_event(event):
js_last[i] = time.time()
elif event == False:
close_fds(js_fds)
js_fds = []
break
i += 1
if time.time() - rescan_time > 2:
rescan_time = time.time()
if js_devs != get_devices():
close_fds(js_fds)
js_fds = []
if do_sleep:
time.sleep(0.01)
================================================
FILE: scriptmodules/admin/joy2key/joy2key_sdl.py
================================================
#!/usr/bin/env python3
"""
This file is part of The RetroPie Project
The RetroPie Project is the legal property of its developers, whose names are
too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
See the LICENSE.md file at the top-level directory of this distribution and
https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md.
Command line joystick to keyboard translator, using SDL2 for event handling
Example usage:
<script> kcub1 kcuf1 kcuu1 kcud1 0x0a 0x20 0x1b 0x00 kpp knp [--debug|-d]
See https://pubs.opengroup.org/onlinepubs/7908799/xcurses/terminfo.html for termcap codes
NB: not all capabilities are supported, but more can be added to the TERM_EVENTS below
SDL2 event handling is based on EmulationStation's event handling, see
https://github.com/RetroPie/EmulationStation/blob/62fd08c26d2f757259b7d890c98c0d7e212f6f84/es-core/src/InputManager.cpp#L205
EmulationStation is authored by Alec "Aloshi" Lofquist (http://www.aloshi.com,http://www.emulationstation.org)
This script uses the PySDL2 module from https://github.com/py-sdl/py-sdl2
This script uses the Python-uinput module from https://github.com/tuomasjjrasanen/python-uinput
"""
import logging
import sys
import signal
import re
import os
import uinput
from argparse import ArgumentParser
from ctypes import create_string_buffer, byref
from configparser import ConfigParser
from sdl2 import joystick, events, version, \
SDL_WasInit, SDL_Init, SDL_QuitSubSystem, SDL_GetError, \
SDL_INIT_JOYSTICK, version_info, \
SDL_Event, SDL_PollEvent, SDL_FlushEvent, SDL_Delay, SDL_Quit, \
SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED, SDL_QUIT, \
SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYHATMOTION, SDL_JOYAXISMOTION, \
SDL_GetTicks
logging.basicConfig(level=logging.INFO, format=u"%(asctime)s %(levelname)-6s %(message)s")
LOG = logging.getLogger(__name__)
# Switch for the HIDAPI driver usage in SDL. Disabled since RetroArch/EmulationStation don't use right now
SDL_USE_HIDAPI = False
# Joystick deadzone threshold, as used by EmulationStation (see es-core/InputManager::parseInput)
JS_AXIS_DEADZONE = 23000
# Event polling interval (ms)
JS_POLL_DELAY = 50
# Event repeat in (ms)
JS_REPEAT_DELAY = 125
# Event delay after a button is pressed (ms)
# Set a bit larger than the default repeat delay to prevent multiple inputs being fired
JS_INIT_DELAY = 250
# Hat values defined here, they're not exported by the sdl2.joystick module
SDL_HAT_CENTERED = 0x00
SDL_HAT_UP = 0x01
SDL_HAT_RIGHT = 0x02
SDL_HAT_DOWN = 0x04
SDL_HAT_LEFT = 0x08
JS_HAT_VALUES = {
"up": SDL_HAT_UP,
"down": SDL_HAT_DOWN,
"left": SDL_HAT_LEFT,
"right": SDL_HAT_RIGHT
}
# Map termios capabilitu codes to Linux (uinput) event ids, for backwards compatibility
# List of possible event IDs:
# https://github.com/tuomasjjrasanen/python-uinput/blob/master/src/ev.py
TERM_EVENTS = {
"kcub1": 105, # left
"kcuf1": 106, # right
"kcud1": 108, # down
"kcuu1": 103, # up
"khome": 102, # home
"kbs" : 14, # backspace
"kend" : 107, # end
"knp" : 109, # page-up
"kpp" : 104, # page-down
"kent" : 28, # enter
"kf1" : 59, # F1
"kf2" : 60, # F2
"kf3" : 61, # F3
"kf4" : 62, # F4
"kf5" : 63, # F5
"kf6" : 64, # F6
"kf7" : 65, # F7
"kf8" : 66, # F8
"kf9" : 67, # F9
"kf10" : 68 # F10
}
# A charmap with 'ascii_code': 'event_id', needed to translate hex valued parameters
# Copy the one defined in 'uinput', so we can extend it since it's missing some entries
CHAR_MAP = { ord(x):y[1] for (x,y) in uinput._CHAR_MAP.items() }
# add our entries to the map, so we can translate them
CHAR_MAP[27] = 1 # Escape
CHAR_MAP[61] = 13 # Equals (=)
CHAR_MAP[43] = 12 # Minus (-)
CHAR_MAP[91] = 26 # Left bracket ([)
CHAR_MAP[93] = 27 # Right bracket (])
CHAR_MAP[127] = 111 # Delete
# RetroPie configurations directory
CONFIG_DIR = '/opt/retropie/configs'
class InputDev(object):
"""
Class representing a joystick device config.
Maps the inputs of the device to event names
name: the device's name
guid: the GUID, as retuned by SDL
hats - a dictionary of { <HatNo>: list(<HatValue>, <Event>) }
buttons - a dict of { <ButtonNo>: <Event> }
axis - a dict of { <AxisNo>: list(<AxisDirection>, <Event>) }
"""
def __init__(self, _name: str, _guid: str):
self.name = _name
self.guid = _guid
self.axis = {}
self.buttons = {}
self.hats = {}
def add_mappings(self, _axis: dict, _buttons: dict, _hats: dict):
self.axis, self.buttons, self.hats = _axis, _buttons, _hats
def get_btn_event(self, index: int) -> list:
if index in self.buttons:
return [self.buttons[index]]
else:
return None
def get_hat_event(self, index: int, value: int) -> list:
if index in self.hats:
return [x[1] for x in self.hats[index] if x[0] & value > 0]
else:
return None
def get_axis_event(self, index: int, value: int) -> list:
if index in self.axis:
return [x[1] for x in self.axis[index] if x[0] == value]
else:
return None
def __str__(self) -> str:
return str(f'{self.name}, hats: {self.hats}, buttons: {self.buttons}, axis: {self.axis}')
def generic_event_map(input: str, event_map: dict) -> str:
for k, v in event_map.items():
if isinstance(v, list):
if input in v:
return k
elif isinstance(v, str) and input == v:
return k
return input
def ra_event_map(input_str: str) -> str:
"""
Maps a RetroArch input option name to an event name
Example:
'input_a_btn' -> 'a'
'input_l_axis' -> 'pageup'
"""
ra_event_map = {
'up': ['l_y_minus', 'r_y_minus'],
'down': ['l_y_plus', 'r_y_plus'],
'left': ['l_x_minus', 'r_x_minus'],
'right': ['l_x_plus', 'r_x_plus'],
'pageup': 'l',
'pagedown': 'r'
}
input_norm = input_str.replace('input_', '').replace('_axis', '').replace('_btn', '')
return generic_event_map(input_norm, ra_event_map)
def ra_input_parse(key: str, value: str):
"""
For a RetroArch input option line ('key = value'), returns a triplet consisting of
- the type of the input (button, hat, axis)
- the index of the input (button number, hat number, axis number)
- the input value associated: 1 for buttons, axis direction (-1/1), hat value (1,2,4,8)
Ex:
- ('input_a_btn', '1') -> 'button', 1, 1
- ('input_left_btn, 'h0left') -> 'hat', '0', 8
- ('input_r_x_axis_minus, -1) -> 'axis', 1, -1
"""
try:
if key.endswith('btn'):
if value.startswith('h'):
input_type = 'hat'
hat_value = re.split(r'([0-9]+)', value)[1:]
# reject malformed hat values
if hat_value[1] not in JS_HAT_VALUES:
raise ValueError('Not a valid hat value')
input_index, input_value = int(hat_value[0]), JS_HAT_VALUES[hat_value[1]]
else:
input_type = 'button'
input_index, input_value = int(value), 1
elif key.endswith('axis'):
input_type = 'axis'
input_index, input_value = int(value[1:]), int(f'{value[0]}1')
else: # unknown input
return None, None, None
return input_type, input_index, input_value
except ValueError as e:
return None, None, None
def get_all_ra_config(def_buttons: list) -> list:
"""
Reads the RetroArch's gamepad auto-configuration folder
and creates a list with of the configured joystick devices as InputDev objects
"""
ra_config_list = []
# add a generic mapping at index 0, to be used for un-configured joysticks
generic_dev = InputDev("*", "*")
generic_dev.add_mappings(
{}, # no axis
{0: 'b', 1: 'a', 3: 'y', 4: 'x'}, # 4 buttons
{0: [(1, 'up'), (8, 'left'), (4, 'down'), (2, 'right')]} # 1 D-Pad as 'hat0'
)
ra_config_list.append(generic_dev)
js_cfg_dir = CONFIG_DIR + '/all/retroarch-joypads/'
config = ConfigParser(delimiters="=", strict=False, interpolation=None)
for file in os.listdir(js_cfg_dir):
# skip non '.cfg' files
if not file.endswith('.cfg') or file.startswith('.'):
continue
with open(js_cfg_dir + file, 'r') as cfg_file:
try:
config.clear()
# ConfigParser needs a section, make up a section to appease it
config.read_string('[device]\n' + cfg_file.read())
conf_vals = config['device']
dev_name = conf_vals['input_device'].strip('"')
# translate the RetroArch inputs from the configuration file
axis, buttons, hats = {}, {}, {}
for i in conf_vals:
if i.startswith('input') and (i.endswith('btn') or i.endswith('axis')):
input_type, input_index, input_value = ra_input_parse(i, conf_vals[i].strip('"'))
# check if the input is mapped to one of the events we recognize
event_name = ra_event_map(i)
if event_name not in def_buttons:
continue
if input_type == 'button':
buttons[input_index] = event_name
elif input_type == 'hat':
hats.setdefault(input_index, []).append((input_value, event_name))
elif input_type == 'axis':
axis.setdefault(input_index, []).append((input_value, event_name))
else:
continue
ra_dev_config = InputDev(dev_name, None)
ra_dev_config.add_mappings(axis, buttons, hats)
ra_config_list.append(ra_dev_config)
except Exception as e:
LOG.warning(f'Parsing error for {file}: {e}')
continue
return ra_config_list
def filter_active_events(event_queue: dict) -> list:
"""
Method to filter out the event if the event:
* fired once within the JS_POLL_DELAY_DEBOUNCE
* fired multiple times, last fire within JS_POLL_POLL_DELAY_DEFAULT
"""
current_time = SDL_GetTicks()
filtered_events = []
for e in event_queue:
if event_queue[e][0] is None:
continue
last_fire_time = event_queue[e][2]
repeat_count = event_queue[e][1]
if repeat_count == 0 or \
(repeat_count == 1 and current_time > (last_fire_time + JS_INIT_DELAY)) or \
(repeat_count > 1 and current_time > (last_fire_time + JS_REPEAT_DELAY)):
filtered_events.extend(event_queue[e][0])
event_queue[e][2] = current_time
event_queue[e][1] += 1
# remove any duplicate events from the list
return list(set(filtered_events))
"""
Remove all queued events for a device
"""
def remove_events_for_device(event_queue: dict, dev_index: int):
return { key:value for (key,value) in event_queue.items() if not key.startswith(f"{dev_index}_")}
def event_loop(configs, joy_map):
event = SDL_Event()
# keep of dict of active joystick devices as a dict of
# instance_id -> (config_id, SDL_Joystick object)
active_devices = {}
# keep an event queue populated with the current active inputs
# indexed by joystick index, input type and input index
# the values consist of:
# - the event list (as taked from the event configuration)
# - the number of times event was emitted (repeated)
# - the last time when the event was fired
# e.g. { event_hash -> ([event_list], repeat_no, last_fire_time) }
event_queue = {}
# keep track of axis previous values
axis_prev_values = {}
# instantiate a keyboard device with uinput to send the translated joypad inputs as keys
keyboard_events = [ (0x1,code) for code in joy_map.values() ]
LOG.debug(f'Creating uinput keyboard devices with events: {keyboard_events}')
kbd = uinput.Device(events=keyboard_events, name="Joy2Key Keyboard")
def handle_new_input(e: SDL_Event, axis_norm_value: int = 0) -> bool:
"""
Event handling for button press/hat movement/axis movement
Only needed when an new input is present
Returns True when 'event_queue' is modified with a new event
"""
dev_index = active_devices[event.jdevice.which][0]
if e.type == SDL_JOYBUTTONDOWN:
mapped_events = configs[dev_index].get_btn_event(event.jbutton.button)
event_index = f'{dev_index}_btn{event.jbutton.button}'
elif e.type == SDL_JOYHATMOTION:
mapped_events = configs[dev_index].get_hat_event(event.jhat.hat, event.jhat.value)
event_index = f'{dev_index}_hat{event.jhat.hat}'
elif e.type == SDL_JOYAXISMOTION and axis_norm_value != 0:
mapped_events = configs[dev_index].get_axis_event(event.jaxis.axis, axis_norm_value)
event_index = f'{dev_index}_axis{event.jaxis.axis}'
if mapped_events is not None:
event_queue[event_index] = [ mapped_events, 0, SDL_GetTicks() ]
return True
return False
running = True
while running:
input_started = False
while SDL_PollEvent(byref(event)):
if event.type == SDL_QUIT:
running = False
break
if event.type == SDL_JOYDEVICEADDED:
stick = joystick.SDL_JoystickOpen(event.jdevice.which)
name = joystick.SDL_JoystickName(stick).decode('utf-8')
guid = create_string_buffer(33)
_SDL_JoystickGetGUIDString(joystick.SDL_JoystickGetGUID(stick), guid, 33)
LOG.debug(f'Joystick #{joystick.SDL_JoystickInstanceID(stick)} {name} added')
conf_found = False
# try to find a configuration for the joystick
for key, dev_conf in enumerate(configs):
if dev_conf.name == str(name) or dev_conf.guid == guid.value.decode():
# Add the matching joystick configuration to the watched list
active_devices[joystick.SDL_JoystickInstanceID(stick)] = (key, stick)
LOG.debug(f'Added configuration for known device {configs[key]}')
conf_found = True
break
# add the default configuration for unknown/un-configured joysticks
if not conf_found:
LOG.debug(f'Un-configured device "{str(name)}", mapped using generic mapping')
active_devices[joystick.SDL_JoystickInstanceID(stick)] = (0, stick)
# if the device has axis inputs, initialize to zero their initial position
if joystick.SDL_JoystickNumAxes(stick) > 0:
axis_prev_values[joystick.SDL_JoystickInstanceID(stick)] = [0 for x in range(joystick.SDL_JoystickNumAxes(stick))]
# Remove any spurious axis movements reported by SDL during initialization
SDL_FlushEvent(SDL_JOYAXISMOTION);
continue
if event.jdevice.which not in active_devices:
continue
else:
dev_index = active_devices[event.jdevice.which][0]
if event.type == SDL_JOYDEVICEREMOVED:
joystick.SDL_JoystickClose(active_devices[event.jdevice.which][1])
if event.jdevice.which in active_devices:
event_queue = remove_events_for_device(event_queue, active_devices[event.jdevice.which][0])
active_devices.pop(event.jdevice.which, None)
axis_prev_values.pop(event.jdevice.which, None)
LOG.debug(f'Removed joystick #{event.jdevice.which}')
if event.type == SDL_JOYBUTTONDOWN:
input_started = handle_new_input(event)
if event.type == SDL_JOYBUTTONUP:
event_queue.pop(f'{dev_index}_btn{event.jbutton.button}', None)
if event.type == SDL_JOYHATMOTION:
if event.jhat.value != SDL_HAT_CENTERED:
input_started = handle_new_input(event)
else:
event_queue.pop(f'{dev_index}_hat{event.jhat.hat}', None)
if event.type == SDL_JOYAXISMOTION:
# check if the axis value went over the deadzone threshold
if (abs(event.jaxis.value) > JS_AXIS_DEADZONE) \
!= (abs(axis_prev_values[event.jdevice.which][event.jaxis.axis]) > JS_AXIS_DEADZONE):
# normalize the axis value to the movement direction or stop the input
if abs(event.jaxis.value) <= JS_AXIS_DEADZONE:
event_queue.pop(f'{dev_index}_axis{event.jaxis.axis}', None)
else:
if event.jaxis.value < 0:
axis_norm_value = -1
else:
axis_norm_value = 1
input_started = handle_new_input(event, axis_norm_value)
# store the axis current values for tracking
axis_prev_values[event.jdevice.which][event.jaxis.axis] = event.jaxis.value
# process the current events in the queue
if len(event_queue):
emitted_events = filter_active_events(event_queue)
if len(emitted_events):
LOG.debug(f'Events to emit: {emitted_events}')
# send the events mapped key code(s) to the terminal
for k in emitted_events:
if k in joy_map:
c = joy_map[k]
LOG.debug(f'Emitting input code {c}')
kbd.emit_click( (0x1,c) )
SDL_Delay(JS_POLL_DELAY)
def parse_arguments(args):
parser = ArgumentParser(
description='Translate joystick events to keyboard inputs')
parser.add_argument(
'-d', '--debug',
action='store_true',
help='print debugging messages',
default=False)
parser.add_argument(
'hex_chars', type=str, nargs='+',
metavar='0xHEX',
help='list of mapped character codes to translate')
args = parser.parse_args()
return args.debug, args.hex_chars
def ra_btn_swap_config():
"""
Returns the state of 'menu_swap_ok_cancel_buttons' configuration for RetroArch
"""
config = ConfigParser(delimiters="=", strict=False, interpolation=None)
with open(CONFIG_DIR + '/all/retroarch.cfg', 'r') as cfg_file:
config.read_string('[device]\n' + cfg_file.read())
try:
menu_swap = config['device']['menu_swap_ok_cancel_buttons'].strip('"') == 'true'
except Exception as e:
menu_swap = False
return menu_swap
def get_uinput_event(key_str: str):
"""
For a Termios control string or an ASCII hex code, return the Linux scancode (integer)
See https://github.com/tuomasjjrasanen/python-uinput/blob/master/src/ev.py for an enumeratin of scancodes
If 'key_str' starts with '0x', it's assumed to be a hexadecimal value of an ASCII char,
otherwise it's presumed to be a termios control string tied to the terminal's capabilities
"""
try:
if key_str.startswith('/'):
# ignore any device name - they're not part of our assignment
return None
if key_str.startswith('0x'):
out = int(key_str,0)
# hex numbers are considered ASCII codes for keyboard keys
# we need to translate them to Linux input scancodes
out = CHAR_MAP[out]
else:
if (key_str in TERM_EVENTS.keys()):
out = TERM_EVENTS[key_str]
else:
LOG.warning(f'Unsupported termios control code "{key_str}", value ignored')
return 0
return out
except Exception as e:
LOG.debug(f'Cannot determine input code for "{key_str}", value ignored')
return 0
def _SDL_JoystickGetGUIDString(guid, pszGUID, cbGUID):
"""
Local method implementing https://github.com/marcusva/py-sdl2/pull/156
Prevents a segfault with older (<3.8) Python AND older Py-SDL2 (<0.9.7)
"""
if sys.version_info >= (3, 8, 0, 'final'):
joystick.SDL_JoystickGetGUIDString(guid, pszGUID, cbGUID)
else:
s = ""
for g in guid.data:
s += "{:x}".format(g >> 4)
s += "{:x}".format(g & 0x0F)
s = s.encode('utf-8')
pszGUID.value = s[:(cbGUID * 2)]
def main():
# install a signal handler so the script can stop safely
def signal_handler(signum, frame):
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
if SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK:
SDL_QuitSubSystem(SDL_INIT_JOYSTICK)
SDL_Quit()
LOG.debug(f'{sys.argv[0]} exiting cleanly')
sys.exit(0)
debug_flag, hex_chars = parse_arguments(sys.argv)
if debug_flag:
LOG.setLevel(logging.DEBUG)
signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)
# when running with no debugging, daemonize after signal handlers are registered
if not debug_flag:
if os.fork():
os._exit(0)
else:
LOG.debug(f'Debugging enabled, running in foreground')
mapped_chars = [get_uinput_event(code) for code in hex_chars if get_uinput_event(code) is not None]
def_buttons = ['left', 'right', 'up', 'down', 'a', 'b', 'x', 'y', 'pageup', 'pagedown']
joy_map = {}
# add for each button the mapped keycode, based on the arguments received
for i, btn in enumerate(def_buttons):
if i < len(mapped_chars):
joy_map[btn] = mapped_chars[i]
LOG.debug(f'Joy map:\n {joy_map}')
menu_swap = ra_btn_swap_config()
# if button A is <enter> and menu_swap_ok_cancel_buttons is true, swap buttons A and B functions
if menu_swap \
and 'a' in joy_map.keys() \
and 'b' in joy_map.keys() \
and joy_map['a'] == '\n':
joy_map['a'] = joy_map['b']
joy_map['b'] = '\n'
# tell SDL that we don't want to grab and lock the keyboard
os.environ['SDL_INPUT_LINUX_KEEP_KBD'] = '1'
# disable the HIDAPI joystick driver in SDL
if not(SDL_USE_HIDAPI):
os.environ['SDL_JOYSTICK_HIDAPI'] = '0'
# tell SDL to not add any signal handlers for TERM/INT
os.environ['SDL_NO_SIGNAL_HANDLERS'] = '1'
configs = get_all_ra_config(def_buttons)
if SDL_Init(SDL_INIT_JOYSTICK) < 0:
LOG.error(f'Error in SDL_Init: {SDL_GetError()}')
exit(2)
if LOG.isEnabledFor(logging.DEBUG):
sdl_ver = version.SDL_version()
version.SDL_GetVersion(byref(sdl_ver))
wrapper_version = '.'.join(str(i) for i in version_info)
LOG.debug(f'Using SDL Version {sdl_ver.major}.{sdl_ver.minor}.{sdl_ver.patch}, PySDL2 version {wrapper_version}')
if joystick.SDL_NumJoysticks() < 1:
LOG.debug(f'No available joystick devices found on startup')
event_loop(configs, joy_map)
SDL_QuitSubSystem(SDL_INIT_JOYSTICK)
SDL_Quit()
return 0
if __name__ == "__main__":
sys.exit(main())
================================================
FILE: scriptmodules/admin/joy2key/osk.py
================================================
#!/usr/bin/env python3
"""
This file is part of The RetroPie Project
The RetroPie Project is the legal property of its developers, whose names are
too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
See the LICENSE.md file at the top-level directory of this distribution and
https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md.
OnScreen Keyboard console utility.
Allows the user to enter a string (ASCII) and outputs the string.
It should be wrapped by 'joy2key' helper script,
so that the gamepad can be used to navigate and enter the necessary characters.
Keys:
- directional keys to move around
- Enter to select a key / press a button
- Esc to exit the form
It uses the [URWID](https://urwid.org) Python library to show a nice console based keyboard.
Example usage:
<script> WindowTitle StringName [min char number]
Exit code can be:
- 0 (success), the string entered by the user is written to STDERR
- 1 (cancel/error) if the user chose cancel to exit
"""
import sys
from os import get_terminal_size
from argparse import ArgumentParser
import urwid
from urwid.widget import Text, Divider, FLOW
from urwid.container import Columns, Frame, GridFlow, Overlay, Pile
from urwid.decoration import AttrMap, AttrWrap, Filler, Padding
from urwid.graphics import LineBox
from urwid.signals import connect_signal
from urwid.command_map import ACTIVATE
ASCII_BLOCK = '█'
# What we consider a small screen
SMALL_SCREEN_COLS = 43
SMALL_SCREEN_ROWS = 22
"""
Colors used in the application controls
"""
PALETTE = [
# Input box: border, text and prompt
('input', 'dark gray', 'light gray'),
('input text', 'black', 'light gray'),
('prompt', 'dark red', 'dark cyan' ),
# Body
('body', 'black', 'light gray'),
('bg', 'white', 'dark blue'),
# Focused key
('focus key', 'white', 'dark blue'),
# Header
('header', 'light cyan', 'dark blue'),
('bold header', 'dark cyan', 'dark blue'),
# Buttons
('button', 'black', 'light gray'),
('selected', 'white', 'dark blue' ),
('label', 'dark gray', 'light gray'),
('label selected', 'yellow', 'dark blue' ),
# Error dialog
('error', 'dark red', 'light gray')
]
class CenteredButton(urwid.WidgetWrap):
"""
Custom button class that:
* centers the label text
* allows to disable the left/righ button margins/characters
* disables the 'space' key handling
"""
def selectable(self):
return True
def sizing(self):
return frozenset([FLOW])
signals = ["click"]
def __init__(self, label, on_press=None, user_data=None, delimiters=True):
self._label = Text(label, align='center')
if delimiters:
cols = Columns(
[
('fixed', 1, Text("<")),
self._label,
('fixed', 1, Text(">"))
],
dividechars=1)
else:
cols = self._label
super().__init__(cols)
if on_press:
connect_signal(self, 'click', on_press, user_data)
# The rest of the methods are taken from urwid.Button
def set_label(self, label):
self._label.set_text(label)
def get_label(self):
return self._label.text
label = property(get_label)
def keypress(self, size, key):
# don't activate with the 'Space' key
if self._command_map[key] != ACTIVATE or key == ' ':
return key
self._emit('click')
def mouse_event(self, size, event, button, x, y, focus):
return False
class KeyButton(CenteredButton):
"""
Custom button class to model a keyboard key
It has primary and secondary key values, returned based on the shift state
"""
def __init__(self, text, primary=None, secondary=None, on_press=None, user_data=None):
super().__init__(text, on_press, user_data, delimiters=False)
# store the primary and secondary key values
if primary is None:
self.primary_val = text
else:
self.primary_val = primary
# calculate the secondary value when the label is a letter
if secondary is None and len(text) == 1:
self.secondary_val = text.upper()
else:
self.secondary_val = secondary
def shift(self, shifted):
"""
Simulate a shift key press, changing the key's label
This may change the button's appearance
"""
if (shifted
and self.secondary_val is not None
and len(self.secondary_val.strip()) > 0):
self.set_label(self.secondary_val)
if (not shifted
and self.primary_val is not None
and len(self.primary_val.strip()) > 0):
self.set_label(self.primary_val)
def get_value(self, shifted):
if shifted and self.secondary_val:
return self.secondary_val
if not shifted and self.primary_val:
return self.primary_val
class WrappableColumns(Columns):
"""
Custom Columns class
Adds the ability to wrap-around the children (left-right) when navigating
"""
def keypress(self, size, key):
if self.__super.keypress(size, key):
if key not in ('left', 'right'):
return key
# we have a key, so it wasn't handled by any parent container
# handle 'left'/'right' ourselves for cursor wrapping
if key in ('left'):
# iterate from last widget to first
widgets = list(range(len(self.contents) - 1, -1, -1))
else:
# iterate from first widget to last
widgets = list(range(0, len(self.contents)))
# Find the 1st selectable widget and focus it
for i in widgets:
if not self.contents[i][0].selectable():
continue
self.focus_position = i
break
class ViewExit(Exception):
pass
class OSK:
"""
Main class for the on-screen keyboard application
"""
def __init__(self, title, input_title, input_value, min_chars=8, dim=False):
"""
:param title: the string used in the application heading
:param input_title: the name of the input string being captured (e.g. Password)
:param input_value: existing string to populate the input
:param min_chars: minimum number of characters for a valid string (default: 8)
:param dim: optimize for a smaller screen (True/False)
"""
self._input_title = input_title
self._input_value = input_value
self._min_chars = min_chars
self.small_display = dim
self.def_keys = []
self.frame = self.setup_frame(title, input_title, input_value)
self.pop_up = self.setup_popup("Error")
# Create the main view, overlaying the popup widget with the main view
view = Overlay(self.pop_up, self.frame, 'center', None, 'middle', None)
self.view = view
def setup_frame(self, title, input_title, input_value):
"""
Creates the main view, with a 3 horizontal pane container (Frame)
"""
self.keys = [] # List of keys added to the OSK
self._shift = False # OSK Shift key state
# title frame (header) uses a LineBox with just the bottom line enabled
# if we're on a small display, use a simple Text with Padding
if self.small_display:
header = Padding(Text(title, align='center'))
else:
header = LineBox(Text(title),
tline=None, rline=' ', lline=' ',
trcorner=' ', tlcorner=' ', blcorner='', brcorner='')
header = AttrWrap(header, 'header')
# Body frame, containing the input and the OSK widget
input = Text([('input text', ''), ('prompt', ASCII_BLOCK)])
if input_value != '':
input.set_text([('input text', input_value), ('prompt', ASCII_BLOCK)])
self.input = input
Key = self.add_osk_key # alias the key creation function
osk = Pile([
# 1st keyboard row
WrappableColumns([
(1, Text(" ")),
(3, Key('`', shifted='~')),
(3, Key('1', shifted='!')),
(3, Key('2', shifted='@')),
(3, Key('3', shifted='#')),
(3, Key('4', shifted='$')),
(3, Key('5', shifted='%')),
(3, Key('6', shifted='^')),
(3, Key('7', shifted='&')),
(3, Key('8', shifted='*')),
(3, Key('9', shifted='(')),
(3, Key('0', shifted=')')),
(3, Key('-', shifted='_')),
(3, Key('=', shifted='+')),
(1, Text(" ")),
], 0),
Divider(),
# 2nd keyboard row
WrappableColumns([
(2, Text(" ")),
(3, Key('q')),
(3, Key('w')),
(3, Key('e')),
(3, Key('r')),
(3, Key('t')),
(3, Key('y')),
(3, Key('u')),
(3, Key('i')),
(3, Key('o')),
(3, Key('p')),
(3, Key('[', shifted='{')),
(3, Key(']', shifted='}')),
(3, Key('\\', shifted='|')),
], 0),
Divider(),
# 3rd keyboard row
WrappableColumns([
(3, Text(" ")),
(3, Key('a')),
(3, Key('s')),
(3, Key('d')),
(3, Key('f')),
(3, Key('g')),
(3, Key('h')),
(3, Key('j')),
(3, Key('k')),
(3, Key('l')),
(3, Key(';', shifted=':')),
(3, Key('\'', shifted='"')),
], 0),
Divider(),
# 4th keyboard row
WrappableColumns([
(4, Text(" ")),
(3, Key('z')),
(3, Key('x')),
(3, Key('c')),
(3, Key('v')),
(3, Key('b')),
(3, Key('n')),
(3, Key('m')),
(3, Key(',', shifted='<')),
(3, Key('.', shifted='>')),
(3, Key('/', shifted='?'))
], 0),
Divider(),
# 5th (last) keyboard row
WrappableColumns([
(1, Text(" ")),
(9, Key('↑ Shift', shifted='↑ SHIFT', callback=self.shift_key_press)),
(2, Text(" ")),
(15, Key('Space', value=' ', shifted=' ')),
(2, Text(" ")),
(10, Key('Delete ←', callback=self.bksp_key_press)),
], 0),
Divider()
])
if self.small_display:
# small displays: remove last divider line
osk.contents.pop(len(osk.contents) - 1)
osk = Padding(osk, 'center', 40)
# setup the text input and the buttons
input=AttrWrap(LineBox(input), 'input')
input = Padding(AttrWrap(input, 'input text'), 'center', ('relative', 80), min_width=30)
ok_btn = self.setup_button("OK", self.button_press, exitcode=0)
cancel_btn = self.setup_button("Cancel", self.button_press, exitcode=1)
# setup the main OSK area, depending on the screen size
if self.small_display:
body = Pile([
Text(f'{input_title}', align='center'),
input,
Divider(),
osk,
Divider(),
GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),
Divider()
])
else:
body = Pile([
Divider(), input,
Divider(), osk,
LineBox(
GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),
bline=None, lline=None, rline=None, tlcorner='─', trcorner='─')
])
body = LineBox(body, f'{input_title}')
body = AttrWrap(body, 'body') # Style the main OSK area
# wrap and align the main OSK in the frame
body = Padding(body, 'center', 55, min_width=42)
body = Filler(body, 'middle')
body = AttrWrap(body, 'bg') # Style the body containing the OSK
frame = Frame(body, header=header, focus_part='body')
return frame
def setup_button(self, label, callback, exitcode=None):
"""
Creates a button and applies the styling
"""
button = CenteredButton(('label', label), callback, delimiters=True)
button.exitcode = exitcode
button = AttrMap(button, {None: 'button'}, {None: 'selected', 'label': 'label selected'})
return button
def setup_popup(self, title):
"""
Overlays a dialog box on top of the working view using a Frame
"""
# Header
if self.small_display:
header = Padding(Text(title, align='center'))
else:
header = LineBox(Text(title),
tline=None, rline=' ', lline=' ',
trcorner=' ', tlcorner=' ', blcorner='', brcorner='')
header = AttrWrap(header, 'header')
# Body
error_text = Text("", align='center')
# register the Text widget with the application, so we can change it
self._error = error_text
error_text = AttrWrap(error_text, 'error')
body = Pile([
Divider(), error_text,
Divider(),
LineBox(
GridFlow([self.setup_button("Dismiss", self.close_popup)],
12, 2, 0, 'center'),
bline=None, lline=None, rline=None, tlcorner='─', trcorner='─')
])
body = LineBox(body)
body = AttrWrap(body, 'body')
# on small displays let the popup fill the screen (horizontal)
if self.small_display:
body = Padding(Filler(body, 'middle'), 'center')
else:
body = Padding(Filler(body, 'middle'), 'center', ('relative', 50))
body = AttrWrap(body, 'bg')
# Main dialog widget
dialog = Frame(
body,
header=header,
focus_part='body'
)
return dialog
def close_popup(self, widget=None):
self.loop.widget = self.frame
def open_popup(self):
self.loop.widget = self.pop_up
def set_shifted(self, state):
self._shift = state
for b in self.keys:
b.shift(state)
def get_shifted(self):
return self._shift
# create a class property for the shifted state
shifted = property(get_shifted, set_shifted, "The Shift key state")
def set_error_text(self, message):
"""
Sets the error message displayed by 'pop_up'
"""
self._error.set_text(message)
def shift_key_press(self, key=None):
"""
Toggle the Shift key, update display of all printable keys
"""
self.shifted = not self.shifted
def button_press(self, btn):
txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)
# check the input string length when OK is asking to exit
if len(txt) < self._min_chars and btn.exitcode == 0:
self.set_error_text(f"{self._input_title} must have at least {self._min_chars} characters")
self.open_popup()
return
raise ViewExit(btn.exitcode)
def bksp_key_press(self, key=None):
"""
Handle the pressing of the erase key
Remove one char from the end of the text input
"""
txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)
if len(txt) > 0:
txt = txt[:-1]
self.input.set_text([('input text', txt), ('prompt', ASCII_BLOCK)])
def def_key_press(self, key):
"""
Default OSK key press handler, it adds the pressed key to the text input
"""
_inner = key.get_value(self.shifted)
if _inner is None:
return
# remove the final block from the input control and append the value
txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)
self.input.set_text([('input text', txt + _inner), ('prompt', ASCII_BLOCK)])
# when keyboard is shifted, toggle the shift key after a key press
if self.shifted:
self.shift_key_press()
def add_osk_key(self, key, value=None, shifted=None, callback=None):
"""
Method to create a KeyButton with the primary/secondary values and the callback handler
"""
if callback is None:
callback = self.def_key_press
btn = KeyButton(key, primary=value, secondary=shifted, on_press=callback)
# store the key internally, so we can shift it when needed
self.keys.append(btn)
self.def_keys.append(btn.get_value(False))
self.def_keys.append(btn.get_value(True))
return AttrWrap(btn, None, 'focus key')
def unhandled_key(self, key):
"""
Keyboard input handling
"""
# handle the normal key press
if len(key) == 1 and ord(key) in range(32, 127):
txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)
self.input.set_text([('input text', txt + key), ('prompt', ASCII_BLOCK)])
return
if key == 'backspace':
self.bksp_key_press()
# handle Esccape:
# - close the error dialog, if in view, and return to main form
# - exit application if on main form
if str(key) in ('esc'):
if self.loop.widget == self.pop_up:
self.close_popup()
else:
raise urwid.ExitMainLoop()
# unhandled, pass it on
return key
def check_wpa_chars(self):
"""
Debugging method to check whether the OSK provides all valid WPA chars
All allowed WPA chars(https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#cite_note-21):
Each character in the passphrase must have an encoding in the range of 32 to 126 (decimal), inclusive
"""
wpa_chars = []
for i in range(32, 127):
wpa_chars.append(i)
print(f' All allowed WPA password characters:\n {[chr(k) for k in wpa_chars]}')
missing = False
for k in wpa_chars:
if chr(k) not in self.def_keys:
print(f' {chr(k)} is not provided !')
missing = True
if not missing:
print(f'All chars are handled !')
def on_exit(self, exitcode):
"""
On exit, return an exitcode and - conditionally - the input text
"""
if exitcode != 0:
return exitcode, ''
else:
return exitcode, self.input.get_text()[0].rstrip(ASCII_BLOCK)
def main(self):
"""
Runs the event/display loop for our view
When the OK/Cancel buttons are used, 'ViewExit' will be raised,
otherwise assume the user has used 'Esc' to close the dialog
"""
self.loop = urwid.MainLoop(self.frame, PALETTE, unhandled_input=self.unhandled_key)
try:
self.loop.run()
return self.on_exit(1)
except ViewExit as e:
return self.on_exit(e.args[0])
def parse_arguments(args):
parser = ArgumentParser(description="Reads a string using an On Screen Keyboard")
parser.add_argument('--backtitle', type=str, help='Window title', required=True)
parser.add_argument('--inputbox', type=str, help='Name of the string being captured', required=True)
parser.add_argument(
'--minchars', type=int, nargs='?',
help='Minimum number of characters needed (default: %(default)s)',
default=8)
parser.add_argument('input', type=str, help='Input value', default='', nargs='?')
args = parser.parse_args()
return args.backtitle, args.inputbox, args.minchars, args.input
def main():
backtitle, inputbox, minchars, value = parse_arguments(sys.argv)
# get the terminal size to detect small display
cols, rows = get_terminal_size(0)
osk = OSK(backtitle, inputbox, value, minchars, (cols < SMALL_SCREEN_COLS or rows < SMALL_SCREEN_ROWS))
exitcode, exitstring = osk.main()
# print the input text when returned by the application
if exitstring:
sys.stderr.write(exitstring + "\n")
sys.exit(exitcode)
if __name__ == "__main__":
main()
================================================
FILE: scriptmodules/admin/joy2key.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="joy2key"
rp_module_desc="Provides joystick to keyboard conversion for navigation of RetroPie dialog menus"
rp_module_section="core"
function _update_hook_joy2key() {
# make sure joy2key is always updated when updating retropie-setup
rp_isInstalled "$md_id" && rp_callModule "$md_id"
}
function depends_joy2key() {
local depends=(python3-urwid python3-uinput)
# 'python3-sdl2' might not be available
# it's packaged in Debian starting with version 11 (Bullseye)
local p_ver
p_ver="$(apt-cache madison python3-sdl2 | cut -d" " -f3 | head -n1)"
if [[ -n "$p_ver" ]]; then
depends+=(python3-sdl2)
fi
getDepends "${depends[@]}"
}
function install_bin_joy2key() {
local file
for file in "joy2key.py" "joy2key_sdl.py" "osk.py"; do
cp "$md_data/$file" "$md_inst/"
chmod +x "$md_inst/$file"
python3 -m compileall "$md_inst/$file"
done
local wrapper="$md_inst/joy2key"
cat >"$wrapper" <<_EOF_
#!/bin/bash
mode="\$1"
[[ -z "\$mode" ]] && mode="start"
shift
# allow overriding joystick device via __joy2key_dev env (by default will use /dev/input/jsX which will scan all)
device="/dev/input/jsX"
[[ -n "\$__joy2key_dev" ]] && device="\$__joy2key_dev"
params=("\$@")
if [[ "\${#params[@]}" -eq 0 ]]; then
# Default button-to-keyboard mappings:
# * cursor keys for axis/dpad
# * enter, space, esc and tab for buttons 'a', 'b', 'x' and 'y'
# * page up/page down for buttons 5,6 (shoulder buttons)
params=(kcub1 kcuf1 kcuu1 kcud1 0x0a 0x20 0x1b 0x09 kpp knp)
fi
script="joy2key_sdl.py"
grep --basic-regexp --quiet --no-messages '^legacy_joy2key[[:space:]]*=[[:space:]]*"\?1"\?' $configdir/all/runcommand.cfg && script="joy2key.py"
case "\$mode" in
start)
if pgrep -f "\$script" &>/dev/null; then
"\$0" stop
fi
"$md_inst/\$script" "\$device" "\${params[@]}" || exit 1
;;
stop)
if pid=\$(pgrep -f "\$script"); then
/sbin/start-stop-daemon --stop --oknodo --pid \$pid --retry 1
fi
;;
esac
exit 0
_EOF_
chmod +x "$wrapper"
if ! grep -q "uinput" /etc/modules; then
addLineToFile "uinput" "/etc/modules"
fi
# add an udev rule to give 'input' group write access to `/dev/uinput`
echo 'KERNEL=="uinput", MODE="0660", GROUP="input"' > /etc/udev/rules.d/80-rpi-uinput.rules
udevadm control --reload
modprobe uinput
# make sure the install user is part of 'input' group
usermod -a -G input "$__user"
joy2keyStart
}
function remove_joy2key() {
joy2keyStop
}
================================================
FILE: scriptmodules/admin/setup.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="setup"
rp_module_desc="GUI based setup for RetroPie"
rp_module_section=""
function _setup_gzip_log() {
setsid tee >(setsid gzip --stdout >"$1")
}
function rps_logInit() {
if [[ ! -d "$__logdir" ]]; then
if mkdir -p "$__logdir"; then
chown "$__user":"$__group" "$__logdir"
else
fatalError "Couldn't make directory $__logdir"
fi
fi
# remove all but the last 20 logs
find "$__logdir" -type f | sort | head -n -20 | xargs -d '\n' --no-run-if-empty rm
local now=$(date +'%Y-%m-%d_%H%M%S')
logfilename="$__logdir/rps_$now.log.gz"
touch "$logfilename"
chown "$__user":"$__group" "$logfilename"
time_start=$(date +"%s")
}
function rps_logStart() {
echo -e "Log started at: $(date -d @$time_start)\n"
echo "RetroPie-Setup version: $__version ($(sudo -u "$__user" git -C "$scriptdir" log -1 --pretty=format:%h))"
echo "System: $__platform ($__platform_arch) - $__os_desc - $(uname -a)"
}
function rps_logEnd() {
time_end=$(date +"%s")
echo
echo "Log ended at: $(date -d @$time_end)"
date_total=$((time_end-time_start))
local hours=$((date_total / 60 / 60 % 24))
local mins=$((date_total / 60 % 60))
local secs=$((date_total % 60))
echo "Total running time: $hours hours, $mins mins, $secs secs"
}
function rps_printInfo() {
local log="$1"
reset
if [[ ${#__ERRMSGS[@]} -gt 0 ]]; then
printMsgs "dialog" "${__ERRMSGS[@]}"
[[ -n "$log" ]] && printMsgs "dialog" "Please see $log for more in depth information regarding the errors."
fi
if [[ ${#__INFMSGS[@]} -gt 0 ]]; then
printMsgs "dialog" "${__INFMSGS[@]}"
fi
__ERRMSGS=()
__INFMSGS=()
}
function depends_setup() {
# check for VERSION file - if it doesn't exist we will run the post_update script as it won't be triggered
# on first upgrade to 4.x
if [[ ! -f "$rootdir/VERSION" ]]; then
joy2keyStop
exec "$scriptdir/retropie_packages.sh" setup post_update gui_setup
fi
if [[ "$__os_debian_ver" -le 10 ]] && isPlatform "rpi" && isPlatform "mesa" && ! isPlatform "rpi4"; then
printMsgs "dialog" "WARNING: You have the experimental desktop GL driver enabled. This is NOT supported by RetroPie, and Emulation Station as well as emulators may fail to launch.\n\nPlease disable the experimental desktop GL driver from the raspi-config 'Advanced Options' menu."
fi
if [[ "$__os_debian_ver" -eq 8 ]]; then
printMsgs "dialog" "Raspbian/Debian Jessie and versions of Ubuntu below 18.04 are no longer supported.\n\nPlease install RetroPie from a fresh image (or if running Ubuntu, upgrade your OS)."
fi
if [[ "$__os_debian_ver" -eq 9 ]] && [[ "$__os_id" == "Raspbian" ]]; then
printMsgs "dialog" "Your version of RetroPie which is based on Raspbian Stretch is no longer supported.\n\nWe recommend you install the latest RetroPie image.\n\nPre-built binaries are now disabled for your system. You can still update packages from source, but due to the age of Raspbian Stretch we can't guarantee all software included will work."
fi
# make sure user has the correct group permissions
if ! isPlatform "x11"; then
local group
for group in input video; do
if ! hasFlag "$(groups $__user)" "$group"; then
dialog --yesno "Your user '$__user' is not a member of the system group '$group'.\n\nThis is needed for RetroPie to function correctly. May I add '$__user' to group '$group'?\n\nYou will need to restart for these changes to take effect." 22 76 2>&1 >/dev/tty && usermod -a -G "$group" "$__user"
fi
done
fi
# set a global __setup to 1 which is used to adjust package function behaviour if called from the setup gui
__setup=1
# print any pending msgs - eg during module scanning which wouldn't be seen otherwise
rps_printInfo
}
function updatescript_setup()
{
clear
chown -R "$__user":"$__group" "$scriptdir"
printHeading "Fetching latest version of the RetroPie Setup Script."
pushd "$scriptdir" >/dev/null
if [[ ! -d ".git" ]]; then
printMsgs "dialog" "Cannot find directory '.git'. Please clone the RetroPie Setup script via 'git clone https://github.com/RetroPie/RetroPie-Setup.git'"
popd >/dev/null
return 1
fi
local error
if ! error=$(sudo -u "$__user" git pull --ff-only 2>&1 >/dev/null); then
printMsgs "dialog" "Update failed:\n\n$error"
popd >/dev/null
return 1
fi
popd >/dev/null
printMsgs "dialog" "Fetched the latest version of the RetroPie Setup script."
return 0
}
function post_update_setup() {
local return_func=("$@")
joy2keyStart
echo "$__version" >"$rootdir/VERSION"
clear
local logfilename
rps_logInit
{
rps_logStart
# run _update_hook_id functions - eg to fix up modules for retropie-setup 4.x install detection
printHeading "Running post update hooks"
rp_updateHooks
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
printMsgs "dialog" "NOTICE: The RetroPie-Setup script and pre-made RetroPie SD card images are available to download for free from https://retropie.org.uk.\n\nThe pre-built RetroPie image includes software that has non commercial licences. Selling RetroPie images or including RetroPie with your commercial product is not allowed.\n\nNo copyrighted games are included with RetroPie.\n\nIf you have been sold this software, you can let us know about it by emailing retropieproject@gmail.com."
# return to set return function
"${return_func[@]}"
}
function package_setup() {
local id="$1"
local default=""
if ! rp_isEnabled "$id"; then
printMsgs "dialog" "Sorry but package '$id' is not available for your system ($__platform)\n\nPackage flags: ${__mod_info[$id/flags]}\n\nYour $__platform flags: ${__platform_flags[*]}"
return 1
fi
# associative array so we can pull out the messages later for the confirmation requester
declare -A option_msgs=(
["U"]=""
["B"]="Install from pre-compiled binary"
["S"]="Install from source"
)
while true; do
local options=()
local status
local has_binary=0
local has_net=0
isConnected && has_net=1
# for modules with nonet flag that don't need to download data, we force has_net to 1, so we get install options
hasFlag "${__mod_info[$id/flags]}" "nonet" && has_net=1
if [[ "$has_net" -eq 1 ]]; then
dialog --backtitle "$__backtitle" --infobox "Checking for updates for $id ..." 3 60 >/dev/tty
rp_hasBinary "$id"
local ret="$?"
[[ "$ret" -eq 0 ]] && has_binary=1
[[ "$ret" -eq 2 ]] && has_net=0
fi
local is_installed=0
local pkg_origin=""
local pkg_date=""
if ! rp_isInstalled "$id"; then
status="Not installed"
else
is_installed=1
rp_loadPackageInfo "$id"
pkg_origin="${__mod_info[$id/pkg_origin]}"
pkg_date="${__mod_info[$id/pkg_date]}"
[[ -n "$pkg_date" ]] && pkg_date="$(date -u -d "$pkg_date" 2>/dev/null)"
status="Installed - via $pkg_origin"
[[ -n "$pkg_date" ]] && status+=" (built: $pkg_date)"
if [[ "$has_net" -eq 1 ]]; then
rp_hasNewerModule "$id" "$pkg_origin"
local has_newer="$?"
case "$has_newer" in
0)
status+="\nUpdate is available."
option_msgs["U"]="Update (from $pkg_origin)"
;;
1)
status+="\nYou are running the latest $pkg_origin."
option_msgs["U"]="Re-install (from $pkg_origin)"
;;
2)
if [[ "$pkg_origin" == "unknown" ]]; then
if [[ "$has_binary" -eq 1 ]]; then
pkg_origin="binary"
else
pkg_origin="source"
fi
fi
option_msgs["U"]="Update (from $pkg_origin)"
status+="\nUpdate may be available (Unable to check for this package)."
;;
3)
has_net=0
;;
esac
fi
fi
if [[ "$has_net" -eq 1 ]]; then
if [[ "$is_installed" -eq 1 ]]; then
options+=(U "${option_msgs["U"]}")
fi
if [[ "$pkg_origin" != "binary" && "$has_binary" -eq 1 ]]; then
options+=(B "${option_msgs["B"]}")
fi
if [[ "$pkg_origin" != "source" ]] && fnExists "sources_${id}"; then
options+=(S "${option_msgs[S]}")
fi
else
status+="\nInstall options disabled:\n$__NET_ERRMSG"
fi
if [[ "$is_installed" -eq 1 ]]; then
if fnExists "gui_${id}"; then
options+=(C "Configuration / Options")
fi
options+=(X "Remove")
fi
if [[ -d "$__builddir/$id" ]]; then
options+=(Z "Clean source folder")
fi
local help="${__mod_info[$id/desc]}\n\n${__mod_info[$id/help]}"
if [[ -n "$help" ]]; then
options+=(H "Package help")
fi
if [[ "$is_installed" -eq 1 ]]; then
options+=(V "Package version information")
fi
cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --default-item "$default" --menu "Choose an option for $id\n$status" 22 76 16)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
default="$choice"
local logfilename
case "$choice" in
U|B|S)
dialog --defaultno --yesno "Are you sure you want to ${option_msgs[$choice]}?" 22 76 2>&1 >/dev/tty || continue
local mode
case "$choice" in
U) mode="_auto_" ;;
B) mode="_binary_" ;;
S) mode="_source_" ;;
esac
clear
rps_logInit
{
rps_logStart
rp_installModule "$id" "$mode"
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
C)
rps_logInit
{
rps_logStart
rp_callModule "$id" gui
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
X)
local text="Are you sure you want to remove $id?"
case "${__mod_info[$id/section]}" in
core)
text+="\n\nWARNING - core packages are needed for RetroPie to function!"
;;
depends)
text+="\n\nWARNING - this package is required by other RetroPie packages - removing may cause other packages to fail."
text+="\n\nNOTE: This will be reinstalled if missing when updating packages that require it."
;;
esac
dialog --defaultno --yesno "$text" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
rps_logStart
clear
rp_callModule "$id" remove
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
H)
printMsgs "dialog" "$help"
;;
V)
local info
rp_loadPackageInfo "$id"
read -r -d '' info << _EOF_
Package Origin: ${__mod_info[$id/pkg_origin]}
Build Date: ${__mod_info[$id/pkg_date]}
Built from source via:
Type: ${__mod_info[$id/pkg_repo_type]}
URL: ${__mod_info[$id/pkg_repo_url]}
Branch: ${__mod_info[$id/pkg_repo_branch]}
Commit: ${__mod_info[$id/pkg_repo_commit]}
Date: ${__mod_info[$id/pkg_repo_date]}
_EOF_
printMsgs "dialog" "$info"
;;
Z)
rp_callModule "$id" clean
printMsgs "dialog" "$__builddir/$id has been removed."
;;
*)
break
;;
esac
done
}
function section_gui_setup() {
local section="$1"
local ids=()
case "$section" in
all|inst)
name="packages"
local id
for id in "${__mod_id[@]}"; do
# if we are showing installed packaged, skip those that are not installed
[[ "$section" == "inst" ]] && ! rp_isInstalled "$id" && continue
# don't show packages from depends or modules with no section (admin)
! [[ "${__mod_info[$id/section]}" =~ ^(depends|config|)$ ]] && ids+=("$id")
done
;;
*)
name="${__sections[$section]} packages"
ids=($(rp_getSectionIds $section))
;;
esac
local default=""
local status=""
local has_net=1
while true; do
local options=()
local pkgs=()
status="Please choose a package from below"
if ! isConnected; then
status+="\nInstall options disabled ($__NET_ERRMSG)"
has_net=0
fi
local id
local num_pkgs=0
local info
local type
local last_type=""
for id in "${ids[@]}"; do
local type="${__mod_info[$id/vendor]} - ${__mod_info[$id/type]}"
# do a heading for each origin and module type
if [[ "$last_type" != "$type" ]]; then
info="$type"
pkgs+=("----" "\Z4$info ----" "Packages from $info")
last_type="$type"
fi
if ! rp_isEnabled "$id"; then
info="\Z1$id\Zn"
else
if rp_isInstalled "$id"; then
rp_loadPackageInfo "$id" "pkg_origin"
local pkg_origin="${__mod_info[$id/pkg_origin]}"
info="$id (Installed - via $pkg_origin)"
((num_pkgs++))
else
info="$id"
fi
fi
pkgs+=("${__mod_idx[$id]}" "$info" "$id - ${__mod_info[$id/desc]}"$'\n\n'"${__mod_info[$id/help]}")
done
if [[ "$has_net" -eq 1 && "$num_pkgs" -gt 0 ]]; then
options+=(
U "Update all installed $name" "This will update any installed $name. The packages will be updated by the method used previously."
)
fi
# allow installing an entire section except for drivers and dependencies - as it's probably a bad idea
if [[ "$has_net" -eq 1 && "$section" != "driver" && "$section" != "depends" ]]; then
# don't show "Install all packages" when we are showing only installed packages
if [[ "$section" != "inst" ]]; then
options+=(I "Install all $name" "This will install all $name. If a package is not installed, and a pre-compiled binary is available it will be used. If a package is already installed, it will be updated by the method used previously.")
fi
options+=(X "Remove all installed $name" "X This will remove all installed $name.")
fi
options+=("${pkgs[@]}")
local cmd=(dialog --colors --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --default-item "$default" --menu "$status" 22 76 16)
local choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
# remove HELP
choice="${choice[@]:5}"
# get id of menu item
default="${choice/%\ */}"
# remove id
choice="${choice#* }"
printMsgs "dialog" "$choice"
continue
fi
default="$choice"
local logfilename
case "$choice" in
U|I)
local mode="update"
[[ "$choice" == "I" ]] && mode="install"
dialog --defaultno --yesno "Are you sure you want to $mode all installed $name?" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
rps_logStart
for id in "${ids[@]}"; do
! rp_isEnabled "$id" && continue
# if we are updating, skip packages that are not installed
if [[ "$mode" == "update" ]]; then
if rp_isInstalled "$id"; then
rp_installModule "$id" "_update_"
fi
else
rp_installModule "$id" "_auto_"
fi
done
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
X)
local text="Are you sure you want to remove all installed $name?"
[[ "$section" == "core" ]] && text+="\n\nWARNING - core packages are needed for RetroPie to function!"
dialog --defaultno --yesno "$text" 22 76 2>&1 >/dev/tty || continue
rps_logInit
{
rps_logStart
for id in "${ids[@]}"; do
rp_isInstalled "$id" && rp_callModule "$id" remove
done
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
----)
;;
*)
package_setup "${__mod_id[$choice]}"
;;
esac
done
}
function config_gui_setup() {
local default
while true; do
local options=()
local id
for id in "${__mod_id[@]}"; do
# show all configuration modules and any installed packages with a gui function
if [[ "${__mod_info[$id/section]}" == "config" ]] || rp_isInstalled "$id" && rp_isEnabled "$id" && fnExists "gui_$id"; then
options+=("${__mod_idx[$id]}" "$id - ${__mod_info[$id/desc]}" "${__mod_idx[$id]} ${__mod_info[$id/desc]}")
fi
done
local cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --default-item "$default" --menu "Choose an option" 22 76 16)
local choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
choice="${choice[@]:5}"
default="${choice/%\ */}"
choice="${choice#* }"
printMsgs "dialog" "$choice"
continue
fi
[[ -z "$choice" ]] && break
default="$choice"
id="${__mod_id[$choice]}"
local logfilename
rps_logInit
{
rps_logStart
if fnExists "gui_$id"; then
rp_callModule "$id" depends
rp_callModule "$id" gui
else
rp_callModule "$id" clean
rp_callModule "$id"
fi
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
done
}
function update_packages_setup() {
clear
local id
for id in ${__mod_id[@]}; do
if rp_isInstalled "$id" && [[ "${__mod_info[$id/section]}" != "depends" ]]; then
rp_installModule "$id" "_update_"
fi
done
}
function check_connection_gui_setup() {
local ip="$(getIPAddress)"
if [[ -z "$ip" ]]; then
printMsgs "dialog" "Sorry, you don't seem to be connected to the internet, so installing/updating is not available."
return 1
fi
return 0
}
function update_packages_gui_setup() {
local update="$1"
if [[ "$update" != "update" ]]; then
! check_connection_gui_setup && return 1
dialog --defaultno --yesno "Are you sure you want to update installed packages?" 22 76 2>&1 >/dev/tty || return 1
updatescript_setup || return 1
# restart at post_update and then call "update_packages_gui_setup update" afterwards
joy2keyStop
exec "$scriptdir/retropie_packages.sh" setup post_update update_packages_gui_setup update
fi
local update_os=0
dialog --yesno "Would you like to update the underlying OS packages (eg kernel etc) ?" 22 76 2>&1 >/dev/tty && update_os=1
clear
local logfilename
rps_logInit
{
rps_logStart
if [[ "$update_os" -eq 1 ]]; then
if rp_isEnabled "raspbiantools"; then
rp_callModule raspbiantools apt_upgrade
else
aptUpdate
apt-get -y dist-upgrade
fi
fi
update_packages_setup
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
printMsgs "dialog" "Installed packages have been updated."
gui_setup
}
function basic_install_setup() {
local id
for id in $(rp_getSectionIds core) $(rp_getSectionIds main); do
rp_installModule "$id"
done
return 0
}
function packages_gui_setup() {
local section
local default
local options=()
for section in core main opt driver exp depends; do
options+=("$section" "Manage ${__sections[$section]} packages" "$section Choose to install/update/configure packages from the ${__sections[$section]}")
done
options+=("----" "" "")
options+=("inst" "Manage all installed packages" "Install/update/remove currently installed packages")
options+=("all" "Manage all packages" "Install/update/remove packages from full list")
local cmd
while true; do
cmd=(dialog --backtitle "$__backtitle" --cancel-label "Back" --item-help --help-button --default-item "$default" --menu "Choose an option" 22 76 16)
local choice
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
choice="${choice[@]:5}"
default="${choice/%\ */}"
choice="${choice#* }"
printMsgs "dialog" "$choice"
continue
fi
[[ "$choice" != "----" ]] && section_gui_setup "$choice"
default="$choice"
done
}
function uninstall_setup()
{
dialog --defaultno --yesno "Are you sure you want to uninstall RetroPie?" 22 76 2>&1 >/dev/tty || return 0
dialog --defaultno --colors --yesno "Are you \ZbREALLY\Zn sure you want to uninstall RetroPie?\n\nThe \Z4\Zb$rootdir\Zn folder will be removed - this includes configuration files for all RetroPie components. If you wish to keep any config files of the emulators/ports that RetroPie used, then choose \ZrNo\Zn now and save it first." 22 76 2>&1 >/dev/tty || return 0
clear
printHeading "Uninstalling RetroPie"
for id in "${__mod_id[@]}"; do
rp_isInstalled "$id" && rp_callModule $id remove
done
rm -rfv "$rootdir"
dialog --defaultno --yesno "Do you want to remove all the files from $datadir - this includes all your installed ROMs, BIOS files and custom splashscreens." 22 76 2>&1 >/dev/tty && rm -rfv "$datadir"
if dialog --defaultno --yesno "Do you want to remove all the system packages that RetroPie depends on? \n\nWARNING: this will remove packages like SDL even if they were installed before you installed RetroPie - it will also remove any package configurations - such as those in /etc/samba for Samba.\n\nIf unsure choose No (selected by default)." 22 76 2>&1 >/dev/tty; then
clear
# remove all dependencies
for id in "${__mod_id[@]}"; do
rp_isInstalled "$id" && rp_callModule "$id" depends remove
done
fi
printMsgs "dialog" "RetroPie has been uninstalled."
}
function reboot_setup()
{
clear
reboot
}
# retropie-setup main menu
function gui_setup() {
joy2keyStart
depends_setup
local default
while true; do
local commit=$(sudo -u "$__user" git -C "$scriptdir" log -1 --pretty=format:"%cr (%h)")
cmd=(dialog --backtitle "$__backtitle" --title "RetroPie-Setup Script" --cancel-label "Exit" --item-help --help-button --default-item "$default" --menu "Version: $__version - Last Commit: $commit\nSystem: $__platform ($__platform_arch) - running on $__os_desc" 22 76 16)
options=(
I "Basic install" "I This will install all packages from Core and Main which gives a basic RetroPie install. Further packages can then be installed later from the Optional and Experimental sections. If binaries are available they will be used, alternatively packages will be built from source - which will take longer."
U "Update" "U Updates RetroPie-Setup and all currently installed packages. Will also allow to update OS packages. If binaries are available they will be used, otherwise packages will be built from source."
P "Manage packages"
"P Install/Remove and Configure the various components of RetroPie, including emulators, ports, and controller drivers."
C "Configuration / tools"
"C Configuration and Tools. Any packages you have installed that have additional configuration options will also appear here."
S "Update RetroPie-Setup script"
"S Update this RetroPie-Setup script. This will update this main management script only, but will not update any software packages. To update packages use the 'Update' option from the main menu, which will also update the RetroPie-Setup script."
X "Uninstall RetroPie"
"X Uninstall RetroPie completely."
R "Perform reboot"
"R Reboot your machine."
)
choice=$("${cmd[@]}" "${options[@]}" 2>&1 >/dev/tty)
[[ -z "$choice" ]] && break
if [[ "${choice[@]:0:4}" == "HELP" ]]; then
choice="${choice[@]:5}"
default="${choice/%\ */}"
choice="${choice#* }"
printMsgs "dialog" "$choice"
continue
fi
default="$choice"
case "$choice" in
I)
! check_connection_gui_setup && continue
dialog --defaultno --yesno "Are you sure you want to do a basic install?\n\nThis will install all packages from the 'Core' and 'Main' package sections." 22 76 2>&1 >/dev/tty || continue
clear
local logfilename
rps_logInit
{
rps_logStart
basic_install_setup
rps_logEnd
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
U)
update_packages_gui_setup
;;
P)
packages_gui_setup
;;
C)
config_gui_setup
;;
S)
! check_connection_gui_setup && continue
dialog --defaultno --yesno "Are you sure you want to update the RetroPie-Setup script ?" 22 76 2>&1 >/dev/tty || continue
if updatescript_setup; then
joy2keyStop
exec "$scriptdir/retropie_packages.sh" setup post_update gui_setup
fi
;;
X)
local logfilename
rps_logInit
{
uninstall_setup
} &> >(_setup_gzip_log "$logfilename")
rps_printInfo "$logfilename"
;;
R)
dialog --defaultno --yesno "Are you sure you want to reboot?\n\nNote that if you reboot when Emulation Station is running, you will lose any metadata changes." 22 76 2>&1 >/dev/tty || continue
reboot_setup
;;
esac
done
joy2keyStop
clear
}
================================================
FILE: scriptmodules/admin/stats/licences/app.css
================================================
body {
font-family: sans-serif;
line-height: 1.25;
}
.center {
display: flex;
flex-flow: column;
align-items: center;
}
h1, body > p {
max-width: 600px;
text-align: center;
}
canvas {
max-width: 500px;
margin: 1em 0;
}
#packages h3 {
margin: 0;
padding: .25em;
margin-bottom: .25em;
}
#packages table {
width: 100%;
max-width: 1280px;
border-collapse: collapse;
}
#packages thead {
border-bottom: 1px solid rgba(0,0,0,30%);
}
#packages td {
padding: .25em;
}
#packages tr td:first-child {
font-family: monospace;
min-width: 15%;
}
#packages tr td:last-child {
text-align: center;
min-width: 5%;
}
#packages thead td:nth-child(3),
#packages tr td:nth-child(3) {
text-align: center;
min-width: 8%;
}
#packages tr:hover {
background-color: #fffe;
}
#packages section {
margin: 2em 0;
padding: .5em;
}
#commit {
font-size: 90%;
margin-top: 0;
}
#commit code {
font-size: 110%;
}
footer {
font-size: 85%;
width: 100%;
max-width: 900px;
text-align: center;
margin-top: 2em;
border-top: 1px solid #ccc;
padding: 1.5em 0;
display: flex;
flex-flow: column;
align-items: center;
}
footer p {
max-width: 800px;
margin-bottom: 0;
}
================================================
FILE: scriptmodules/admin/stats/licences/app.js
================================================
async function fetch_packages() {
const resp = await fetch('../packages.csv');
const data = await resp.text();
return data
.split('\n')
.map(line => line.split(';'))
.filter(fields => fields.length >= 4)
.map(fields => ({
section: fields[0],
id: fields[1],
desc: fields[2],
licence: fields[3],
}));
}
async function fetch_commit_info() {
const resp = await fetch('../commit.csv');
const data = await resp.text();
const fields = data.split(';');
return {
sha: fields[0] || '',
when: fields[1] || '',
branch: fields[2] || '',
};
}
function create_commit_info(commit) {
const date = commit.when.slice(0, 10);
const time = commit.when.slice(11, 16);
const text = `Last update: ${date} ${time}, <code>${commit.branch}</code> branch at <code>${commit.sha}</code>`;
document.getElementById('commit').innerHTML = text;
}
function get_pkg_licence_name(pkg) {
return pkg.licence
? pkg.licence.split(' ', 1)[0]
: 'Unknown';
}
function get_pkg_licence_link(pkg) {
if (pkg.licence) {
const url = pkg.licence.split(' ', 2)[1];
if (url) {
const anchor = document.createElement('a');
anchor.href = url;
anchor.target = '_blank';
anchor.innerText = 'link';
return anchor.outerHTML;
}
}
return null;
}
const CATEGORIES = [
'copyleft',
'permissive',
'nonfree',
'other',
'unknown',
];
const CATEGORY_COLORS = {
unknown: '#555',
copyleft: '#d11',
permissive: '#1d1',
nonfree: '#fc0',
other: '#aaa',
};
function categorize_licence(licence) {
if (licence == 'Unknown')
return 'unknown';
if (/^L?GPL/.test(licence) || /^MPL/.test(licence))
return 'copyleft';
if (['ZLIB', 'MIT', 'BSD'].includes(licence))
return 'permissive';
if (['PROP', 'NONCOM'].includes(licence))
return 'nonfree';
return 'other';
}
function create_pie(packages) {
const counts = new Map();
packages
.map(get_pkg_licence_name)
.map(categorize_licence)
.forEach(lic => counts.set(lic, (counts.get(lic) || 0) + 1));
const categories = CATEGORIES.filter(cat => counts.has(cat));
const canvas = document.getElementById('pie');
const chart = new Chart(canvas, {
type: 'doughnut',
data: {
labels: CATEGORIES,
datasets: [{
data: categories.map(cat => counts.get(cat)),
backgroundColor: categories.map(cat => CATEGORY_COLORS[cat]),
}],
},
options: {
legend: {
position: 'bottom',
},
},
});
}
function append_cell(parent, html) {
const cell = document.createElement('td');
cell.innerHTML = html;
parent.appendChild(cell);
}
function create_section_row(type, cell_htmls) {
const row = document.createElement(type);
cell_htmls.forEach(str => append_cell(row, str))
return row;
}
function create_package_tables(packages) {
const pkg_licences = new Map();
packages.forEach(pkg => {
const licence = get_pkg_licence_name(pkg);
const packages = pkg_licences.get(licence) || [];
packages.push(pkg);
pkg_licences.set(licence, packages);
});
const fragment = new DocumentFragment();
const licence_names = [...pkg_licences.keys()].sort();
licence_names.forEach(lic => {
const lic_category = categorize_licence(lic);
const lic_color = CATEGORY_COLORS[lic_category];
const container = document.createElement('section');
container.style.backgroundColor = lic_color + '2';
const title = document.createElement('h3');
title.innerText = lic;
container.appendChild(title);
const table = document.createElement('table');
const thead = create_section_row('thead', ['Package', 'Description', 'Section', 'Licence']);
table.appendChild(thead);
pkg_licences
.get(lic)
.sort((a, b) => a.id.localeCompare(b.id))
.map(pkg => [
pkg.id,
pkg.desc,
pkg.section || '—',
get_pkg_licence_link(pkg) || '—',
])
.map(fields => create_section_row('tr', fields))
.forEach(row => table.appendChild(row));
container.appendChild(table);
fragment.appendChild(container);
});
document.getElementById('packages').appendChild(fragment);
}
window.onload = async () => {
const packages = await fetch_packages();
const commit = await fetch_commit_info();
create_pie(packages);
create_commit_info(commit);
create_package_tables(packages);
};
================================================
FILE: scriptmodules/admin/stats/licences/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<meta http-equiv='x-ua-compatible' content='ie=edge'>
<title>RetroPie package licences</title>
<link rel='stylesheet' type='text/css' href='app.css'>
<script defer type='text/javascript' src='Chart.min.js'></script>
<script defer type='text/javascript' src='app.js'></script>
</head>
<body class='center'>
<h1>RetroPie package licences</h1>
<p>This page shows an up-to-date list of all RetroPie packages and the licences they use.</p>
<canvas id='pie' width='550' height='400'></canvas>
<p id='commit'></p>
<div id='packages'></div>
<footer>
<p>This page is provided merely for informational purposes and should not be taken as a legal advice. Always check the licences of the individual softwares and the local laws if you have legal question.</p>
<p>Copyright © 2019 The RetroPie Project</p>
</footer>
</body>
</html>
================================================
FILE: scriptmodules/admin/stats/pkgflags/app.css
================================================
body {
font-family: sans-serif;
line-height: 1.25;
}
.center {
display: flex;
flex-flow: column;
align-items: center;
}
h1, p {
max-width: 600px;
text-align: center;
}
#packages table {
width: 100%;
max-width: 1280px;
border-collapse: collapse;
}
#packages td {
padding: .25rem;
}
#packages tr td.id {
font-family: monospace;
min-width: 15%;
}
#packages td.flag.first {
border-left: 1px solid rgba(0,0,0,30%);
}
#packages tr td.flag {
color: rgba(0,0,0,50%);
}
#packages tr td.flag.pass {
background-color: #dfd;
}
#packages tr td.flag.fail {
background-color: #fbb;
}
#packages table .flag {
text-align: center;
}
#packages thead {
vertical-align: bottom;
border-bottom: 1px solid rgba(0,0,0,30%);
}
#packages thead .flag {
writing-mode: vertical-rl;
width: 2rem;
line-height: 2rem;
}
#packages tr:hover {
background-color: #eee;
}
#packages tr:hover td.flag.pass {
background-color: #cfc;
}
#packages tr:hover td.flag.fail {
background-color: #f99;
}
#packages section {
position: relative;
margin: 2em 0;
}
#packages section h2 {
position: absolute;
top: 0;
}
#devices {
display: flex;
justify-content: center;
width: 100%;
max-width: 1000px;
}
#devices ul {
list-style-type: none;
padding: 0;
width: 100%;
display: flex;
flex-flow: column;
}
#devices li {
display: flex;
margin: .25em 0;
}
#devices li span {
width: 11em;
}
#devices li span:first-child {
text-align: right;
}
#devices li progress {
flex-grow: 1;
margin: 0 .5em;
height: auto; /* for webkit */
}
#commit {
font-size: 90%;
margin-top: 0;
}
#commit code {
font-size: 110%;
}
footer {
font-size: 85%;
width: 100%;
max-width: 900px;
text-align: center;
margin-top: 2em;
border-top: 1px solid #ccc;
padding: 1.5em 0;
}
================================================
FILE: scriptmodules/admin/stats/pkgflags/app.js
================================================
async function fetch_packages() {
const resp = await fetch('../packages.csv');
const data = await resp.text();
return data
.split('\n')
.map(line => line.split(';'))
.filter(fields => fields.length >= 5)
.map(fields => ({
section: fields[0],
id: fields[1],
desc: fields[2],
// fields[3] is the licence
flags: fields[4].split(' '),
}));
}
async function fetch_commit_info() {
const resp = await fetch('../commit.csv');
const data = await resp.text();
const fields = data.split(';');
return {
sha: fields[0] || '',
when: fields[1] || '',
branch: fields[2] || '',
};
}
function create_device_bars(packages) {
const devices = [{
name: 'Raspberry Pi 0/1',
flags: ['videocore', 'arm', 'armv6'],
hover: 'VideoCore + ARMv6',
}, {
name: 'Raspberry Pi 2',
flags: ['videocore', 'arm', 'armv7'],
hover: 'VideoCore + ARMv7',
},{
name: 'Raspberry Pi 3',
flags: ['videocore', 'arm', 'armv8'],
hover: 'VideoCore + ARMv8',
}, {
name: 'Raspberry Pi 4',
flags: ['kms', 'arm', 'armv8'],
hover: 'DRM/KMS + ARMv8',
}, {
name: 'Odroid C1/XU3/XU4',
flags: ['mali', 'arm', 'armv7'],
hover: 'Mali + ARMv7',
}, {
name: 'Odroid C2',
flags: ['mali', 'aarch64'],
hover: 'Mali + AArch64',
}, {
name: 'Desktop Linux',
flags: ['x11', 'x86'],
hover: 'X11 + x86',
},
];
const ui_holder = document.createElement('ul');
devices
.map(device => {
const label = document.createElement('span');
label.innerText = device.name;
const bar = document.createElement('progress');
bar.max = packages.length;
bar.value = packages
.filter(pkg => device.flags.every(flag => !pkg.flags.includes('!' + flag)))
.length;
bar.title = `${device.hover}\n${bar.value} / ${bar.max}`;
const percent = document.createElement('span');
percent.innerText = Math.round(100 * bar.value / bar.max) + '%';
const row = document.createElement('li');
row.appendChild(label);
row.appendChild(bar);
row.appendChild(percent);
return row;
})
.forEach(row => ui_holder.appendChild(row));
document.getElementById('devices').appendChild(ui_holder);
}
function create_commit_info(commit) {
const date = commit.when.slice(0, 10);
const time = commit.when.slice(11, 16);
const text = `Last update: ${date} ${time}, <code>${commit.branch}</code> branch at <code>${commit.sha}</code>`;
document.getElementById('commit').innerHTML = text;
}
function package_enabled_for(pkg, flag) {
const video_flag_synonyms = {
'videocore' : [ 'arm', 'rpi', 'rpi1', 'rpi2', 'rpi3', 'dispmanx', 'gles' ],
'mali' : [ 'arm' , 'gles' ],
'kms' : [ 'arm' , 'rpi', 'rpi4', 'dispmanx', 'mesa' , 'gles3' ],
'x11' : [ 'x86' , '64bit', 'mesa' ]
};
var equivs = (video_flag_synonyms[flag] ? [flag].concat(video_flag_synonyms[flag]) : [flag]);
if ( pkg.flags.includes('!all') ) {
return _flags_include(pkg.flags, equivs) && !_flags_exclude(pkg.flags, equivs);
} else {
return !_flags_exclude(pkg.flags, equivs);
}
}
function _flags_include(pkg_flags, flags) {
return flags.reduce( (acc, flag) => acc || pkg_flags.includes(flag), false);
}
function _flags_exclude(pkg_flags, flags) {
return flags.reduce( (acc, flag) => acc || pkg_flags.includes('!' + flag), false);
}
function append_pkg_text_cell(parent, klass, text) {
const cell = document.createElement('td');
cell.innerText = text;
if (Array.isArray(klass))
klass.forEach(k => cell.classList.add(k));
else
cell.classList.add(klass);
parent.appendChild(cell);
}
function append_pkg_flag_cell(parent, klass, is_pass) {
const cell = document.createElement('td');
cell.innerText = is_pass ? '\u2713' : '\u2717';
cell.classList.add('flag', klass, is_pass ? 'pass' : 'fail');
parent.appendChild(cell);
}
function create_section_thead() {
const thead = document.createElement('thead');
append_pkg_text_cell(thead, 'id', 'Package');
append_pkg_text_cell(thead, 'desc', 'Description');
append_pkg_text_cell(thead, ['flag', 'video'], 'VideoCore');
append_pkg_text_cell(thead, ['flag', 'video'], 'Mali');
append_pkg_text_cell(thead, ['flag', 'video'], 'DRM/KMS');
append_pkg_text_cell(thead, ['flag', 'video'], 'X11');
append_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv6');
append_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv7');
append_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv8 (32 bit)');
append_pkg_text_cell(thead, ['flag', 'cpu'], 'AArch64');
append_pkg_text_cell(thead, ['flag', 'cpu'], 'x86');
thead.querySelector('.flag.video').classList.add('first');
thead.querySelector('.flag.cpu').classList.add('first');
return thead;
}
function create_section_row(pkg) {
const row = document.createElement('tr');
row.title='Script flags: ' + pkg.flags.join(' ');
append_pkg_text_cell(row, 'id', pkg.id);
append_pkg_text_cell(row, 'desc', pkg.desc);
append_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'videocore'));
append_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'mali'));
append_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'kms'));
append_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'x11'));
append_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv6'));
append_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv7'));
append_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv8'));
append_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!aarch64'));
append_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!x86'));
row.querySelector('.flag.video').classList.add('first');
row.querySelector('.flag.cpu').classList.add('first');
return row;
}
function create_package_sections(packages) {
const section_ids = [
'core',
'main',
'opt',
'exp',
'driver',
'config',
'',
];
const section_names = {
opt: 'optional',
exp: 'experimental',
config: 'configuration',
'': 'other',
};
const sections = [];
section_ids.forEach(id => sections[id] = []);
packages.forEach(pkg => {
const section = sections[pkg.section] || sections[''];
section.push(pkg);
});
const fragment = new DocumentFragment();
section_ids
.filter(id => sections[id])
.forEach(id => {
const ui_container = document.createElement('section');
const ui_title = document.createElement('h2');
ui_title.innerText = section_names[id] || id;
ui_container.appendChild(ui_title);
const ui_table = document.createElement('table');
ui_table.appendChild(create_section_thead());
sections[id]
.sort((a, b) => a.id.localeCompare(b.id))
.map(pkg => create_section_row(pkg))
.forEach(row => ui_table.appendChild(row));
ui_container.appendChild(ui_table);
fragment.appendChild(ui_container);
});
document.getElementById('packages').appendChild(fragment);
document.querySelector('table .flag.video').classList.add('first');
document.querySelector('table .flag.cpu').classList.add('first');
}
window.onload = async () => {
const packages = await fetch_packages();
const commit = await fetch_commit_info();
create_device_bars(packages);
create_commit_info(commit);
create_package_sections(packages);
};
================================================
FILE: scriptmodules/admin/stats/pkgflags/index.html
================================================
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta name='viewport' content='width=device-width,initial-scale=1'>
<meta http-equiv='x-ua-compatible' content='ie=edge'>
<title>RetroPie package flags</title>
<link rel='stylesheet' type='text/css' href='app.css'>
<script type='text/javascript' src='app.js' defer></script>
</head>
<body class='center'>
<h1>RetroPie platform support</h1>
<p>This page shows an up-to-date list of all RetroPie packages and the platforms (devices and flags) they support.</p>
<div id='devices'></div>
<p id='commit'></p>
<div id='packages'></div>
<footer>Copyright © 2019 The RetroPie Project</footer>
</body>
</html>
================================================
FILE: scriptmodules/admin/stats.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="stats"
rp_module_desc="Generates statistics about packages"
rp_module_section=""
function _get_commit_data_stats() {
local hash=$(git -C "$scriptdir" log -1 --format=%h)
local date=$(git -C "$scriptdir" log -1 --format=%cd --date=iso-strict)
local branch=$(git -C "$scriptdir" rev-parse --abbrev-ref HEAD)
echo "$hash;$date;$branch;"
}
function _get_package_data_stats() {
local data=()
local id
for id in ${__mod_id[@]}; do
data+=("${__mod_info[$id/section]};$id;${__mod_info[$id/desc]};${__mod_info[$id/licence]};${__mod_info[$id/flags]};")
done
printf "%s\n" "${data[@]}"
}
function build_stats() {
local dest="$__tmpdir/stats"
mkUserDir "$dest"
# ignore platform flags to get info for all packages
__ignore_flags=1
rp_registerAllModules
echo "$(_get_package_data_stats)" > "$dest/packages.csv"
echo "$(_get_commit_data_stats)" > "$dest/commit.csv"
cp -rv "$md_data/licences" "$dest/"
cp -rv "$md_data/pkgflags" "$dest/"
chown -R "$__user":"$__group" "$dest"
}
function upload_stats() {
adminRsync "$__tmpdir/stats/" "stats/" --delete
}
================================================
FILE: scriptmodules/admin/tools.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="tools"
rp_module_desc="Various RetroPie development/administration tools"
rp_module_section=""
function check_repos_tools() {
local ids
if [[ -n "$1" ]]; then
ids=("$@")
else
ids=("${__mod_id[@]}")
fi
local id
local ret=0
for id in "${ids[@]}"; do
eval "$(rp_moduleVars $id)"
local out
[[ -z "$md_repo_type" ]] && continue
md_repo_branch="$(rp_resolveRepoParam "$md_repo_branch")"
md_repo_commit="$(rp_resolveRepoParam "$md_repo_commit")"
printMsgs "console" "Checking $id repository ($md_repo_url / $md_repo_branch) ..."
case "$md_repo_type" in
git|svn)
out=$(rp_getRemoteRepoHash "$md_repo_type" "$md_repo_url" "$md_repo_branch" "$md_repo_commit")
if [[ "$?" -ne 0 || -z "$out" ]]; then
printMsgs "console" "$id repository failed - $md_repo_url $md_repo_branch"
ret=1
fi
;;
file)
if ! rp_getFileDate "$md_repo_url" >/dev/null; then
printMsgs "console" "$id file archive failed - $md_repo_url"
ret=1
fi
;;
:*)
# handle checking via module function - function should return 1 if there was an error
local function="${md_repo_type:1}"
if fnExists "$function" ; then
! "$function" check && ret=1
fi
;;
esac
done
return "$ret"
}
function check_licences_tools() {
local ids
if [[ -n "$1" ]]; then
ids=("$@")
else
ids=("${__mod_id[@]}")
fi
local id
local ret=0
local licence
local url
for id in "${ids[@]}"; do
eval "$(rp_moduleVars $id)"
licence=($md_licence)
url="${licence[1]}"
if [[ -n "$url" ]]; then
printMsgs "console" "Checking $id ($md_licence) ..."
if ! download "$url" - &>/dev/null; then
printMsgs "console" "... $id licence URL failed ($url)"
ret=1
fi
fi
done
return "$ret"
}
================================================
FILE: scriptmodules/admin/wikidocs.sh
================================================
#!/usr/bin/env bash
# This file is part of The RetroPie Project
#
# The RetroPie Project is the legal property of its developers, whose names are
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
#
# See the LICENSE.md file at the top-level directory of this distribution and
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
#
rp_module_id="wikidocs"
rp_module_desc="Generate mkdocs documentation from wiki"
rp_module_section=""
function depends_wikidocs() {
getDepends python3 python3-pip libyaml-dev python3-setuptools python3-wheel python3-virtualenv
}
function sources_wikidocs() {
gitPullOrClone "$md_build" https://github.com/RetroPie/RetroPie-Docs.git
}
function build_wikidocs() {
python3 -m venv "$md_inst"
source "$md_inst/bin/activate"
pip3 install --upgrade mkdocs-material mdx_truly_sane_lists git+https://github.com/cmitu/mkdocs-altlink-plugin
mkdocs build
deactivate
}
function install_wikidocs() {
rsync -a --delete "$md_build/site/" "$__tmpdir/wikidocs/"
chown -R "$__user":"$__group" "$__tmpdir/wikidocs"
}
function upload_wikidocs() {
ad
gitextract_5rddm1no/
├── .github/
│ ├── FUNDING.yml
│ └── ISSUE_TEMPLATE/
│ ├── bug-report.yml
│ └── config.yml
├── .gitignore
├── AUTHORS
├── CONTRIBUTING.md
├── COPYRIGHT.md
├── LICENSE.md
├── README.md
├── platforms.cfg
├── retropie_packages.sh
├── retropie_setup.sh
└── scriptmodules/
├── admin/
│ ├── apidocs.sh
│ ├── builder.sh
│ ├── crosscomp/
│ │ ├── asan_limits.diff
│ │ └── bullseye.diff
│ ├── crosscomp.sh
│ ├── image/
│ │ ├── dists/
│ │ │ ├── rpios-bookworm-64.ini
│ │ │ ├── rpios-bookworm.ini
│ │ │ ├── rpios-bullseye.ini
│ │ │ ├── rpios-buster.ini
│ │ │ ├── rpios-jessie.ini
│ │ │ └── rpios-stretch.ini
│ │ └── template.json
│ ├── image.sh
│ ├── joy2key/
│ │ ├── joy2key.py
│ │ ├── joy2key_sdl.py
│ │ └── osk.py
│ ├── joy2key.sh
│ ├── setup.sh
│ ├── stats/
│ │ ├── licences/
│ │ │ ├── app.css
│ │ │ ├── app.js
│ │ │ └── index.html
│ │ └── pkgflags/
│ │ ├── app.css
│ │ ├── app.js
│ │ └── index.html
│ ├── stats.sh
│ ├── tools.sh
│ └── wikidocs.sh
├── archivefuncs.sh
├── emulators/
│ ├── advmame/
│ │ ├── 01_rpi_framebuffer.diff
│ │ ├── 02_fix_extern_globals_0_94.diff
│ │ └── 02_fix_extern_globals_1_4.diff
│ ├── advmame-0.94.sh
│ ├── advmame-1.4.sh
│ ├── advmame.sh
│ ├── ags.sh
│ ├── amiberry/
│ │ ├── 01_preserve_env.diff
│ │ ├── 02_fix_uae_config_load.diff
│ │ └── 03_fix_crash_saving.diff
│ ├── amiberry.sh
│ ├── atari800/
│ │ ├── 01_rpi_fixes.diff
│ │ └── atari800.sh
│ ├── atari800.sh
│ ├── basilisk.sh
│ ├── capricerpi.sh
│ ├── coolcv.sh
│ ├── daphne/
│ │ └── dapinput.ini
│ ├── daphne.sh
│ ├── dgen.sh
│ ├── dolphin.sh
│ ├── dosbox/
│ │ └── 01-fully-bindable-joystick.diff
│ ├── dosbox-sdl2/
│ │ └── 001-sd2.0-check-remove.diff
│ ├── dosbox-sdl2.sh
│ ├── dosbox-staging/
│ │ └── 0.82.x-kmsdrm-fix.diff
│ ├── dosbox-staging.sh
│ ├── dosbox.sh
│ ├── drastic.sh
│ ├── fbzx.sh
│ ├── frotz.sh
│ ├── fs-uae/
│ │ └── fs-uae.sh
│ ├── fs-uae.sh
│ ├── fuse/
│ │ ├── 01_disable_cursor.diff
│ │ ├── 02_sdl_fix.diff
│ │ └── 03_gcc_10_fix.diff
│ ├── fuse.sh
│ ├── gngeopi.sh
│ ├── gpsp.sh
│ ├── hatari.sh
│ ├── hypseus/
│ │ ├── hypinput.ini
│ │ └── hypinput_gamepad.ini
│ ├── hypseus.sh
│ ├── jzintv/
│ │ ├── 01_rpi_hide_cursor_sdl2.patch
│ │ ├── 01_rpi_pillar_boxing_black_background_sdl2.patch
│ │ └── 02_Makefile_multiarch_pkg_config.patch
│ ├── jzintv.sh
│ ├── linapple.sh
│ ├── mame/
│ │ └── lzma_armv7_crc.diff
│ ├── mame.sh
│ ├── mame4all.sh
│ ├── minivmac.sh
│ ├── mupen64plus/
│ │ ├── 0001-GLideN64-use-emplace.patch
│ │ ├── mupen64plus.sh
│ │ └── remove_fast_math.diff
│ ├── mupen64plus.sh
│ ├── np2pi.sh
│ ├── openmsx/
│ │ └── retropie-init.tcl
│ ├── openmsx.sh
│ ├── oricutron.sh
│ ├── osmose.sh
│ ├── pcsx-rearmed.sh
│ ├── pcsx2.sh
│ ├── pifba.sh
│ ├── pisnes.sh
│ ├── ppsspp/
│ │ ├── gles2_fix.diff
│ │ ├── sdl_ttf_fix_before_1.19.diff
│ │ └── tinker.armv7.cmake
│ ├── ppsspp-1.5.4.sh
│ ├── ppsspp.sh
│ ├── px68k/
│ │ └── 001-missing-typedef.diff
│ ├── px68k.sh
│ ├── quasi88/
│ │ └── 01_cmake.diff
│ ├── quasi88.sh
│ ├── redream.sh
│ ├── reicast/
│ │ ├── 0001-enable-rpi4-sdl2-target.patch
│ │ ├── 0002-enable-vsync.patch
│ │ ├── 0003-fix-sdl2-sighandler-conflict.patch
│ │ └── reicast.sh
│ ├── reicast.sh
│ ├── retroarch/
│ │ ├── mess2016_libretro.info
│ │ └── mupen64plus_libretro.info
│ ├── retroarch.sh
│ ├── rpix86.sh
│ ├── scummvm-sdl1.sh
│ ├── scummvm.sh
│ ├── sdltrs.sh
│ ├── simcoupe.sh
│ ├── snes9x.sh
│ ├── stella.sh
│ ├── stratagus.sh
│ ├── supermodel3.sh
│ ├── ti99sim/
│ │ └── missing_cstring.diff
│ ├── ti99sim-sdl1/
│ │ └── missing_cstdio.diff
│ ├── ti99sim-sdl1.sh
│ ├── ti99sim.sh
│ ├── uae4all/
│ │ └── 01_guichan.diff
│ ├── uae4all.sh
│ ├── uae4arm/
│ │ └── uae4arm.sh
│ ├── uae4arm.sh
│ ├── vice.sh
│ ├── xm7/
│ │ └── 01_fix_build.diff
│ ├── xm7.sh
│ ├── xroar.sh
│ ├── yabasanshiro.sh
│ └── zesarux.sh
├── helpers.sh
├── inifuncs.sh
├── libretrocores/
│ ├── lr-81.sh
│ ├── lr-atari800.sh
│ ├── lr-beetle-lynx.sh
│ ├── lr-beetle-ngp.sh
│ ├── lr-beetle-pce-fast.sh
│ ├── lr-beetle-pce.sh
│ ├── lr-beetle-pcfx.sh
│ ├── lr-beetle-psx.sh
│ ├── lr-beetle-saturn.sh
│ ├── lr-beetle-supergrafx.sh
│ ├── lr-beetle-vb.sh
│ ├── lr-beetle-wswan.sh
│ ├── lr-bennugd.sh
│ ├── lr-bluemsx.sh
│ ├── lr-bsnes.sh
│ ├── lr-caprice32.sh
│ ├── lr-desmume.sh
│ ├── lr-desmume2015.sh
│ ├── lr-dinothawr.sh
│ ├── lr-dirksimple.sh
│ ├── lr-dolphin.sh
│ ├── lr-dosbox-pure.sh
│ ├── lr-dosbox.sh
│ ├── lr-ep128emu.sh
│ ├── lr-fbalpha2012.sh
│ ├── lr-fbneo.sh
│ ├── lr-fceumm.sh
│ ├── lr-flycast/
│ │ └── 01_flags_fix.diff
│ ├── lr-flycast-dev.sh
│ ├── lr-flycast.sh
│ ├── lr-fmsx.sh
│ ├── lr-freechaf.sh
│ ├── lr-freeintv.sh
│ ├── lr-fuse.sh
│ ├── lr-gambatte/
│ │ └── default.pal
│ ├── lr-gambatte.sh
│ ├── lr-geargrafx.sh
│ ├── lr-gearsystem.sh
│ ├── lr-genesis-plus-gx.sh
│ ├── lr-gpsp.sh
│ ├── lr-gw.sh
│ ├── lr-handy.sh
│ ├── lr-hatari/
│ │ └── 01_libcapsimage.diff
│ ├── lr-hatari.sh
│ ├── lr-kronos.sh
│ ├── lr-mame.sh
│ ├── lr-mame2000.sh
│ ├── lr-mame2003-plus.sh
│ ├── lr-mame2003.sh
│ ├── lr-mame2010.sh
│ ├── lr-mame2015/
│ │ └── 01-python3-irgen.diff
│ ├── lr-mame2015.sh
│ ├── lr-mame2016/
│ │ └── 01-python3-irgen.diff
│ ├── lr-mame2016.sh
│ ├── lr-mesen.sh
│ ├── lr-mess.sh
│ ├── lr-mess2016.sh
│ ├── lr-mgba.sh
│ ├── lr-mrboom.sh
│ ├── lr-mupen64plus/
│ │ ├── 0001-eliminate-conflicting-typedefs.patch
│ │ ├── 0002-rpi-gles3.patch
│ │ └── 0003-fix-fsqrt-conflict.patch
│ ├── lr-mupen64plus-next.sh
│ ├── lr-mupen64plus.sh
│ ├── lr-neocd.sh
│ ├── lr-nestopia.sh
│ ├── lr-np2kai.sh
│ ├── lr-nxengine.sh
│ ├── lr-o2em.sh
│ ├── lr-opera.sh
│ ├── lr-parallel-n64/
│ │ └── 01-fix-fsqrt-conflicts.diff
│ ├── lr-parallel-n64.sh
│ ├── lr-pcsx-rearmed.sh
│ ├── lr-picodrive.sh
│ ├── lr-pokemini.sh
│ ├── lr-ppsspp/
│ │ ├── v13-libretro_fix.diff
│ │ └── v16-clamp-include.diff
│ ├── lr-ppsspp.sh
│ ├── lr-prboom.sh
│ ├── lr-prosystem.sh
│ ├── lr-puae.sh
│ ├── lr-puae2021.sh
│ ├── lr-px68k.sh
│ ├── lr-quasi88.sh
│ ├── lr-quicknes.sh
│ ├── lr-retro8.sh
│ ├── lr-scummvm.sh
│ ├── lr-smsplus-gx.sh
│ ├── lr-snes9x.sh
│ ├── lr-snes9x2002.sh
│ ├── lr-snes9x2005.sh
│ ├── lr-snes9x2010.sh
│ ├── lr-stella.sh
│ ├── lr-stella2014.sh
│ ├── lr-superflappybirds.sh
│ ├── lr-tgbdual.sh
│ ├── lr-theodore.sh
│ ├── lr-tic80.sh
│ ├── lr-tyrquake.sh
│ ├── lr-uae4arm.sh
│ ├── lr-vba-next.sh
│ ├── lr-vecx.sh
│ ├── lr-vice.sh
│ ├── lr-virtualjaguar.sh
│ ├── lr-x1.sh
│ ├── lr-xrick.sh
│ └── lr-yabause.sh
├── packages.sh
├── ports/
│ ├── alephone.sh
│ ├── cannonball.sh
│ ├── cdogs-sdl.sh
│ ├── cgenius.sh
│ ├── darkplaces-quake/
│ │ ├── 01_rpi_fixes.diff
│ │ └── 02_makefile_fixes.diff
│ ├── darkplaces-quake.sh
│ ├── dsda-doom.sh
│ ├── dxx-rebirth.sh
│ ├── eduke32/
│ │ ├── 0001-revert-r6918.patch
│ │ ├── 0002-fix-skybox.patch
│ │ ├── 0003-replace-gl_red.patch
│ │ ├── 0004-recast-function.patch
│ │ ├── 0005-e1m4-shrinker-bug.patch
│ │ └── 0006-e4m4-water-bug.patch
│ ├── eduke32.sh
│ ├── gemrb.sh
│ ├── giana.sh
│ ├── gzdoom/
│ │ ├── armv8_gcc12_fix.diff
│ │ └── lzma_armv7_crc.diff
│ ├── gzdoom.sh
│ ├── ionfury.sh
│ ├── ioquake3.sh
│ ├── jumpnbump/
│ │ └── jumpnbump.sh
│ ├── jumpnbump.sh
│ ├── kodi.sh
│ ├── lincity-ng.sh
│ ├── love-0.10.2.sh
│ ├── love.sh
│ ├── lzdoom/
│ │ ├── 01_remove_cmake_arm_options.diff
│ │ ├── 02_lzma_sdk_dont_force_arm_crc32.diff
│ │ └── 03_extra_includes.diff
│ ├── lzdoom.sh
│ ├── micropolis.sh
│ ├── minecraft.sh
│ ├── mysticmine.sh
│ ├── openblok.sh
│ ├── openbor.sh
│ ├── openpht.sh
│ ├── openttd.sh
│ ├── opentyrian/
│ │ └── 01_fullscreen.diff
│ ├── opentyrian.sh
│ ├── quake3.sh
│ ├── sdlpop.sh
│ ├── smw.sh
│ ├── solarus.sh
│ ├── splitwolf.sh
│ ├── srb2/
│ │ └── 001-cmake-libfind.diff
│ ├── srb2.sh
│ ├── steamlink.sh
│ ├── supertux.sh
│ ├── tyrquake.sh
│ ├── uqm.sh
│ ├── vvvvvv.sh
│ ├── wolf4sdl.sh
│ ├── xrick.sh
│ ├── yquake2/
│ │ ├── hotkey_exit.diff
│ │ ├── sdl2_joylabels.diff
│ │ └── yq2.cfg
│ └── yquake2.sh
├── supplementary/
│ ├── attractmode.sh
│ ├── audiosettings.sh
│ ├── autostart.sh
│ ├── backends.sh
│ ├── bashwelcometweak.sh
│ ├── bluetooth/
│ │ ├── COPYING
│ │ ├── bluez-simple-agent
│ │ ├── bluez-test-device
│ │ ├── bluezutils.py
│ │ ├── connect.sh
│ │ └── readme.txt
│ ├── bluetooth.sh
│ ├── configedit.sh
│ ├── consolefont.sh
│ ├── controlblock.sh
│ ├── custombluez/
│ │ └── 01_raspbian_patches.diff
│ ├── customhidsony/
│ │ └── 0001-hidsony-gasiafix.diff
│ ├── customhidsony.sh
│ ├── dbar4gun.sh
│ ├── docsview.sh
│ ├── emulationstation/
│ │ ├── configscripts/
│ │ │ ├── daphne.sh
│ │ │ ├── emulationstation.sh
│ │ │ ├── mupen64plus.sh
│ │ │ ├── openmsx.sh
│ │ │ ├── pifba.sh
│ │ │ ├── pisnes.sh
│ │ │ ├── reicast.sh
│ │ │ ├── retroarch.sh
│ │ │ └── sdl2.sh
│ │ └── inputconfiguration.sh
│ ├── emulationstation-dev.sh
│ ├── emulationstation.sh
│ ├── esthemes/
│ │ ├── patch-ruckage-famicom-mini.diff
│ │ ├── patch-ruckage-nes-mini.diff
│ │ └── patch-ruckage-snes-mini.diff
│ ├── esthemes.sh
│ ├── gamecondriver.sh
│ ├── golang.sh
│ ├── kmsxx.sh
│ ├── launchingimages.sh
│ ├── mehstation.sh
│ ├── mesa-drm.sh
│ ├── mkarcadejoystick.sh
│ ├── mobilegamepad.sh
│ ├── moonlight.sh
│ ├── omxiv.sh
│ ├── pegasus-fe-dev.sh
│ ├── pegasus-fe.sh
│ ├── powerblock.sh
│ ├── ps3controller.sh
│ ├── raspbiantools.sh
│ ├── resetromdirs.sh
│ ├── retronetplay.sh
│ ├── retropiemenu.sh
│ ├── runcommand/
│ │ └── runcommand.sh
│ ├── runcommand.sh
│ ├── samba.sh
│ ├── scraper.sh
│ ├── sdl1.sh
│ ├── sdl12-compat.sh
│ ├── sdl2.sh
│ ├── sixaxis.sh
│ ├── skyscraper.sh
│ ├── snesdev/
│ │ └── 001-wiringpi-static.diff
│ ├── snesdev.sh
│ ├── splashscreen/
│ │ ├── 05-splash.sh
│ │ ├── asplashscreen.sh
│ │ └── rp-vlc
│ ├── splashscreen.sh
│ ├── steamcontroller.sh
│ ├── usbromservice/
│ │ ├── 01_retropie_copyroms
│ │ └── 10_retropie_mount
│ ├── usbromservice.sh
│ ├── virtualgamepad.sh
│ ├── wifi.sh
│ ├── xarcade2jstick.sh
│ ├── xboxdrv.sh
│ ├── xpad/
│ │ ├── 01_enable_leds_and_trigmapping.diff
│ │ ├── 02_dkms_updates_folder.diff
│ │ └── 03_xpad_add_version.diff
│ ├── xpad.sh
│ └── xpadneo.sh
└── system.sh
SYMBOL INDEX (95 symbols across 6 files)
FILE: scriptmodules/admin/joy2key/joy2key.py
function ini_get (line 37) | def ini_get(key, cfg_file):
function get_btn_num (line 48) | def get_btn_num(btn, cfg):
function sysdev_get (line 55) | def sysdev_get(key, sysdev_path):
function get_button_codes (line 62) | def get_button_codes(dev_path):
function signal_handler (line 133) | def signal_handler(signum, frame):
function get_hex_chars (line 142) | def get_hex_chars(key_str):
function get_devices (line 149) | def get_devices():
function open_devices (line 160) | def open_devices():
function close_fds (line 173) | def close_fds(fds):
function read_event (line 177) | def read_event(fd):
function process_event (line 189) | def process_event(event):
FILE: scriptmodules/admin/joy2key/joy2key_sdl.py
class InputDev (line 116) | class InputDev(object):
method __init__ (line 127) | def __init__(self, _name: str, _guid: str):
method add_mappings (line 134) | def add_mappings(self, _axis: dict, _buttons: dict, _hats: dict):
method get_btn_event (line 137) | def get_btn_event(self, index: int) -> list:
method get_hat_event (line 143) | def get_hat_event(self, index: int, value: int) -> list:
method get_axis_event (line 149) | def get_axis_event(self, index: int, value: int) -> list:
method __str__ (line 155) | def __str__(self) -> str:
function generic_event_map (line 159) | def generic_event_map(input: str, event_map: dict) -> str:
function ra_event_map (line 169) | def ra_event_map(input_str: str) -> str:
function ra_input_parse (line 189) | def ra_input_parse(key: str, value: str):
function get_all_ra_config (line 223) | def get_all_ra_config(def_buttons: list) -> list:
function filter_active_events (line 281) | def filter_active_events(event_queue: dict) -> list:
function remove_events_for_device (line 309) | def remove_events_for_device(event_queue: dict, dev_index: int):
function event_loop (line 312) | def event_loop(configs, joy_map):
function parse_arguments (line 454) | def parse_arguments(args):
function ra_btn_swap_config (line 472) | def ra_btn_swap_config():
function get_uinput_event (line 486) | def get_uinput_event(key_str: str):
function _SDL_JoystickGetGUIDString (line 515) | def _SDL_JoystickGetGUIDString(guid, pszGUID, cbGUID):
function main (line 532) | def main():
FILE: scriptmodules/admin/joy2key/osk.py
class CenteredButton (line 82) | class CenteredButton(urwid.WidgetWrap):
method selectable (line 89) | def selectable(self):
method sizing (line 92) | def sizing(self):
method __init__ (line 97) | def __init__(self, label, on_press=None, user_data=None, delimiters=Tr...
method set_label (line 118) | def set_label(self, label):
method get_label (line 121) | def get_label(self):
method keypress (line 125) | def keypress(self, size, key):
method mouse_event (line 132) | def mouse_event(self, size, event, button, x, y, focus):
class KeyButton (line 136) | class KeyButton(CenteredButton):
method __init__ (line 141) | def __init__(self, text, primary=None, secondary=None, on_press=None, ...
method shift (line 156) | def shift(self, shifted):
method get_value (line 171) | def get_value(self, shifted):
class WrappableColumns (line 179) | class WrappableColumns(Columns):
method keypress (line 184) | def keypress(self, size, key):
class ViewExit (line 207) | class ViewExit(Exception):
class OSK (line 211) | class OSK:
method __init__ (line 216) | def __init__(self, title, input_title, input_value, min_chars=8, dim=F...
method setup_frame (line 237) | def setup_frame(self, title, input_title, input_value):
method setup_button (line 390) | def setup_button(self, label, callback, exitcode=None):
method setup_popup (line 400) | def setup_popup(self, title):
method close_popup (line 450) | def close_popup(self, widget=None):
method open_popup (line 453) | def open_popup(self):
method set_shifted (line 456) | def set_shifted(self, state):
method get_shifted (line 461) | def get_shifted(self):
method set_error_text (line 467) | def set_error_text(self, message):
method shift_key_press (line 473) | def shift_key_press(self, key=None):
method button_press (line 479) | def button_press(self, btn):
method bksp_key_press (line 490) | def bksp_key_press(self, key=None):
method def_key_press (line 502) | def def_key_press(self, key):
method add_osk_key (line 518) | def add_osk_key(self, key, value=None, shifted=None, callback=None):
method unhandled_key (line 534) | def unhandled_key(self, key):
method check_wpa_chars (line 559) | def check_wpa_chars(self):
method on_exit (line 580) | def on_exit(self, exitcode):
method main (line 589) | def main(self):
function parse_arguments (line 603) | def parse_arguments(args):
function main (line 617) | def main():
FILE: scriptmodules/admin/stats/licences/app.js
function fetch_packages (line 1) | async function fetch_packages() {
function fetch_commit_info (line 17) | async function fetch_commit_info() {
function create_commit_info (line 28) | function create_commit_info(commit) {
function get_pkg_licence_name (line 35) | function get_pkg_licence_name(pkg) {
function get_pkg_licence_link (line 41) | function get_pkg_licence_link(pkg) {
constant CATEGORIES (line 55) | const CATEGORIES = [
constant CATEGORY_COLORS (line 62) | const CATEGORY_COLORS = {
function categorize_licence (line 70) | function categorize_licence(licence) {
function create_pie (line 86) | function create_pie(packages) {
function append_cell (line 112) | function append_cell(parent, html) {
function create_section_row (line 118) | function create_section_row(type, cell_htmls) {
function create_package_tables (line 124) | function create_package_tables(packages) {
FILE: scriptmodules/admin/stats/pkgflags/app.js
function fetch_packages (line 1) | async function fetch_packages() {
function fetch_commit_info (line 18) | async function fetch_commit_info() {
function create_device_bars (line 29) | function create_device_bars(packages) {
function create_commit_info (line 88) | function create_commit_info(commit) {
function package_enabled_for (line 95) | function package_enabled_for(pkg, flag) {
function _flags_include (line 113) | function _flags_include(pkg_flags, flags) {
function _flags_exclude (line 117) | function _flags_exclude(pkg_flags, flags) {
function append_pkg_text_cell (line 121) | function append_pkg_text_cell(parent, klass, text) {
function append_pkg_flag_cell (line 131) | function append_pkg_flag_cell(parent, klass, is_pass) {
function create_section_thead (line 138) | function create_section_thead() {
function create_section_row (line 156) | function create_section_row(pkg) {
function create_package_sections (line 175) | function create_package_sections(packages) {
FILE: scriptmodules/supplementary/bluetooth/bluezutils.py
function get_managed_objects (line 7) | def get_managed_objects():
function find_adapter (line 13) | def find_adapter(pattern=None):
function find_adapter_in_objects (line 16) | def find_adapter_in_objects(objects, pattern=None):
function find_device (line 28) | def find_device(device_address, adapter_pattern=None):
function find_device_in_objects (line 32) | def find_device_in_objects(objects, device_address, adapter_pattern=None):
Condensed preview — 398 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,540K chars).
[
{
"path": ".github/FUNDING.yml",
"chars": 58,
"preview": "patreon: retropie\ncustom: https://retropie.org.uk/donate/\n"
},
{
"path": ".github/ISSUE_TEMPLATE/bug-report.yml",
"chars": 615,
"preview": "name: Create Issue\ndescription: |\n Report a bug with RetroPie-Setup scripts\nbody:\n\n - type: markdown\n id: info\n a"
},
{
"path": ".github/ISSUE_TEMPLATE/config.yml",
"chars": 264,
"preview": "blank_issues_enabled: false\ncontact_links:\n - name: RetroPie Forums\n url: https://retropie.org.uk/forum\n about: C"
},
{
"path": ".gitignore",
"chars": 179,
"preview": "# OS generated files #\n######################\n.DS_Store\n.DS_Store?\n._*\n.Spotlight-V100\n.Trashes\nIcon?\nehthumbs.db\nThumbs"
},
{
"path": "AUTHORS",
"chars": 145,
"preview": "Florian Müller - <contact [at] petrockblock.com>\n - Main code, maintainer\n\nJools Wills - <buzz [at] exotica.org.uk>\n "
},
{
"path": "CONTRIBUTING.md",
"chars": 417,
"preview": "# How to contribute\n\n## Support Requests vs Bug Reporting\n\nPlease use the GitHub for bug reports only. For help / suppor"
},
{
"path": "COPYRIGHT.md",
"chars": 634,
"preview": "The RetroPie Project\nCopyright (C) 2012-2025 by the following:\n\nIf you have contributed to this project then you deserve"
},
{
"path": "LICENSE.md",
"chars": 32265,
"preview": "# RetroPie Legal Information\n\n## License\n\n### GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007\n\nCopyright (C) 2007 Fr"
},
{
"path": "README.md",
"chars": 2033,
"preview": "RetroPie-Setup\n==============\n\nGeneral Usage\n-------------\n\nShell script to setup the Raspberry Pi, Vero4K, ODroid-C1 or"
},
{
"path": "platforms.cfg",
"chars": 6565,
"preview": "3do_exts=\".chd .cue .iso .zip\"\n3do_fullname=\"3DO Interactive Multiplayer\"\n\nags_exts=\".exe\"\nags_fullname=\"Adventure Game "
},
{
"path": "retropie_packages.sh",
"chars": 2670,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "retropie_setup.sh",
"chars": 520,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/apidocs.sh",
"chars": 1557,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/builder.sh",
"chars": 7713,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/crosscomp/asan_limits.diff",
"chars": 381,
"preview": "# fixes gcc/libsanitizer/asan/asan_linux.cpp:217:21: error: ‘PATH_MAX’ was not declared in this scope\n--- a/gcc/libsanit"
},
{
"path": "scriptmodules/admin/crosscomp/bullseye.diff",
"chars": 5597,
"preview": "# see https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=49348beafe9ba150c9bd48595b3f372299bddbb0\n\ndiff --git a/math/Ma"
},
{
"path": "scriptmodules/admin/crosscomp.sh",
"chars": 7421,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/image/dists/rpios-bookworm-64.ini",
"chars": 368,
"preview": "name=\"bookworm-64\"\nversion=\"12\"\nurl=\"https://downloads.raspberrypi.com/raspios_oldstable_lite_arm64/images/raspios_oldst"
},
{
"path": "scriptmodules/admin/image/dists/rpios-bookworm.ini",
"chars": 454,
"preview": "name=\"bookworm\"\nversion=\"12\"\nurl=\"https://downloads.raspberrypi.com/raspios_oldstable_lite_armhf/images/raspios_oldstabl"
},
{
"path": "scriptmodules/admin/image/dists/rpios-bullseye.ini",
"chars": 414,
"preview": "name=\"bullseye\"\nversion=\"11\"\nurl=\"https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstabl"
},
{
"path": "scriptmodules/admin/image/dists/rpios-buster.ini",
"chars": 373,
"preview": "name=\"buster\"\nversion=\"10\"\nurl=\"https://downloads.raspberrypi.org/raspios_oldstable_lite_armhf/images/raspios_oldstable_"
},
{
"path": "scriptmodules/admin/image/dists/rpios-jessie.ini",
"chars": 270,
"preview": "name=\"jessie\"\nversion=\"8\"\nurl=\"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2017-07-05/2017-07-0"
},
{
"path": "scriptmodules/admin/image/dists/rpios-stretch.ini",
"chars": 272,
"preview": "name=\"stretch\"\nversion=\"9\"\nurl=\"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-04-09/2019-04-"
},
{
"path": "scriptmodules/admin/image/template.json",
"chars": 556,
"preview": " {\n \"url\": \"https://github.com/RetroPie/RetroPie-Setup/releases/download/IMG_PATH\",\n \"extra"
},
{
"path": "scriptmodules/admin/image.sh",
"chars": 15955,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/joy2key/joy2key.py",
"chars": 8484,
"preview": "#!/usr/bin/python3\n\n# This file is part of The RetroPie Project\n# \n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/joy2key/joy2key_sdl.py",
"chars": 23680,
"preview": "#!/usr/bin/env python3\n\"\"\"\nThis file is part of The RetroPie Project\n\nThe RetroPie Project is the legal property of its "
},
{
"path": "scriptmodules/admin/joy2key/osk.py",
"chars": 21314,
"preview": "#!/usr/bin/env python3\n\"\"\"\nThis file is part of The RetroPie Project\nThe RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/joy2key.sh",
"chars": 3017,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/setup.sh",
"chars": 29097,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/stats/licences/app.css",
"chars": 1170,
"preview": "body {\n\tfont-family: sans-serif;\n\tline-height: 1.25;\n}\n.center {\n\tdisplay: flex;\n\tflex-flow: column;\n\talign-items: cente"
},
{
"path": "scriptmodules/admin/stats/licences/app.js",
"chars": 4195,
"preview": "async function fetch_packages() {\n\tconst resp = await fetch('../packages.csv');\n\tconst data = await resp.text();\n\n\tretur"
},
{
"path": "scriptmodules/admin/stats/licences/index.html",
"chars": 964,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset='utf-8'>\n\t<meta name='viewport' content='width=device-width,initial-scale=1"
},
{
"path": "scriptmodules/admin/stats/pkgflags/app.css",
"chars": 1748,
"preview": "body {\n\tfont-family: sans-serif;\n\tline-height: 1.25;\n}\n.center {\n\tdisplay: flex;\n\tflex-flow: column;\n\talign-items: cente"
},
{
"path": "scriptmodules/admin/stats/pkgflags/app.js",
"chars": 7173,
"preview": "async function fetch_packages() {\n\tconst resp = await fetch('../packages.csv');\n\tconst data = await resp.text();\n\n\tretur"
},
{
"path": "scriptmodules/admin/stats/pkgflags/index.html",
"chars": 671,
"preview": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset='utf-8'>\n\t<meta name='viewport' content='width=device-width,initial-scale=1"
},
{
"path": "scriptmodules/admin/stats.sh",
"chars": 1557,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/tools.sh",
"chars": 2618,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/admin/wikidocs.sh",
"chars": 1232,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/archivefuncs.sh",
"chars": 1836,
"preview": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developer"
},
{
"path": "scriptmodules/emulators/advmame/01_rpi_framebuffer.diff",
"chars": 3628,
"preview": "--- a/advance/linux/vfb.c\n+++ b/advance/linux/vfb.c\n@@ -268,7 +268,7 @@\n \tvar->height = 0;\n \tvar->width = 0;\n \tvar->acce"
},
{
"path": "scriptmodules/emulators/advmame/02_fix_extern_globals_0_94.diff",
"chars": 407,
"preview": "diff --git a/src/drivers/seibuspi.c b/src/drivers/seibuspi.c\nindex 143dcc2..91187f8 100644\n--- a/src/drivers/seibuspi.c\n"
},
{
"path": "scriptmodules/emulators/advmame/02_fix_extern_globals_1_4.diff",
"chars": 1196,
"preview": "From f8688cae05799a30cd5337e626a07fa9f004c0a3 Mon Sep 17 00:00:00 2001\nFrom: Andrea Mazzoleni <amadvance@gmail.com>\nDate"
},
{
"path": "scriptmodules/emulators/advmame-0.94.sh",
"chars": 1832,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/advmame-1.4.sh",
"chars": 2446,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/advmame.sh",
"chars": 5615,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/ags.sh",
"chars": 2795,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/amiberry/01_preserve_env.diff",
"chars": 1252,
"preview": "diff --git a/Makefile b/Makefile\nindex 9747718..dcdfb2f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -43,10 +43,10 @@ SDL_CON"
},
{
"path": "scriptmodules/emulators/amiberry/02_fix_uae_config_load.diff",
"chars": 2720,
"preview": "diff --git a/src/osdep/amiberry_whdbooter.cpp b/src/osdep/amiberry_whdbooter.cpp\nindex 8a03e732..939b26b8 100644\n--- a/s"
},
{
"path": "scriptmodules/emulators/amiberry/03_fix_crash_saving.diff",
"chars": 432,
"preview": "diff --git a/src/cfgfile.cpp b/src/cfgfile.cpp\nindex f96ee0d9..24bd58cb 100644\n--- a/src/cfgfile.cpp\n+++ b/src/cfgfile.c"
},
{
"path": "scriptmodules/emulators/amiberry.sh",
"chars": 6178,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/atari800/01_rpi_fixes.diff",
"chars": 552,
"preview": "diff --git a/configure.ac b/configure.ac\nindex adb899f..bc9d939 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -148,7 +"
},
{
"path": "scriptmodules/emulators/atari800/atari800.sh",
"chars": 462,
"preview": "#!/bin/bash\n\nemulator=\"./EMULATOR\"\nrom=\"$1\"\nshift\nparams=(\"$@\")\n\npushd \"${0%/*}\" >/dev/null\n\nif [[ -z \"$rom\" ]]; then\n "
},
{
"path": "scriptmodules/emulators/atari800.sh",
"chars": 4577,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/basilisk.sh",
"chars": 2040,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/capricerpi.sh",
"chars": 1646,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/coolcv.sh",
"chars": 1150,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/daphne/dapinput.ini",
"chars": 1023,
"preview": "# Daphne cutom keyboard and joystick mapping\n#\n# Each input is mapped to 2 keyboard keys and one joystick button.\n# A jo"
},
{
"path": "scriptmodules/emulators/daphne.sh",
"chars": 2379,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/dgen.sh",
"chars": 3746,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/dolphin.sh",
"chars": 4737,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/dosbox/01-fully-bindable-joystick.diff",
"chars": 3145,
"preview": "--- a/src/gui/sdl_mapper.cpp\t2019-03-10 04:19:35.938770333 +0000\n+++ b/src/gui/sdl_mapper.cpp\t2019-03-10 04:46:26.474081"
},
{
"path": "scriptmodules/emulators/dosbox-sdl2/001-sd2.0-check-remove.diff",
"chars": 697,
"preview": "diff --git a/configure.ac b/configure.ac\nindex 407d553..731d960 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -31,20 +"
},
{
"path": "scriptmodules/emulators/dosbox-sdl2.sh",
"chars": 2146,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/dosbox-staging/0.82.x-kmsdrm-fix.diff",
"chars": 978,
"preview": "# Workaround backported to 0.82.x from \n# https://github.com/dosbox-staging/dosbox-staging/pull/4589/commits/525e98ca340"
},
{
"path": "scriptmodules/emulators/dosbox-staging.sh",
"chars": 3780,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/dosbox.sh",
"chars": 4944,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/drastic.sh",
"chars": 1929,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/fbzx.sh",
"chars": 1782,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/frotz.sh",
"chars": 1731,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/fs-uae/fs-uae.sh",
"chars": 1271,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/fs-uae.sh",
"chars": 3629,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/fuse/01_disable_cursor.diff",
"chars": 331,
"preview": "--- a/ui/sdl/sdldisplay.c\t2017-07-02 05:36:42.000000000 +0000\n+++ b/ui/sdl/sdldisplay.c\t2018-08-22 13:55:03.474702732 +0"
},
{
"path": "scriptmodules/emulators/fuse/02_sdl_fix.diff",
"chars": 938,
"preview": "diff --git a/ui/sdl/sdldisplay.c b/ui/sdl/sdldisplay.c\nindex e4d640b..fafe0ac 100644\n--- a/ui/sdl/sdldisplay.c\n+++ b/ui/"
},
{
"path": "scriptmodules/emulators/fuse/03_gcc_10_fix.diff",
"chars": 356,
"preview": "--- a/ui/widget/widget.c\n+++ b/ui/widget/widget.c\n@@ -91,7 +91,7 @@\n static widget_recurse_t widget_return[10]; /* The s"
},
{
"path": "scriptmodules/emulators/fuse.sh",
"chars": 2900,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/gngeopi.sh",
"chars": 2173,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/gpsp.sh",
"chars": 1708,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/hatari.sh",
"chars": 3481,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/hypseus/hypinput.ini",
"chars": 2452,
"preview": "# Sample hypinput.ini\n# All key options listed\n# Hypseus uses SDL2 Keycodes\n#\n# The first two entries are SDL2 keyboard "
},
{
"path": "scriptmodules/emulators/hypseus/hypinput_gamepad.ini",
"chars": 2705,
"preview": "# Sample hypinput.ini using SDL_GameController\n# All key options listed for use with -gamepad\n#\n# Hypseus uses SDL2 Keyc"
},
{
"path": "scriptmodules/emulators/hypseus.sh",
"chars": 3321,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/jzintv/01_rpi_hide_cursor_sdl2.patch",
"chars": 707,
"preview": "--- a/gfx/gfx_sdl2.c\n+++ b/gfx/gfx_sdl2.c\n@@ -420,7 +420,12 @@ LOCAL int gfx_setup_sdl_display\n /* Hide the mouse i"
},
{
"path": "scriptmodules/emulators/jzintv/01_rpi_pillar_boxing_black_background_sdl2.patch",
"chars": 600,
"preview": "--- a/gfx/gfx_sdl2.c\n+++ b/gfx/gfx_sdl2.c\n@@ -511,7 +511,7 @@ LOCAL int gfx_flip(const gfx_t *const gfx)\n /* need t"
},
{
"path": "scriptmodules/emulators/jzintv/02_Makefile_multiarch_pkg_config.patch",
"chars": 479,
"preview": "--- a/Makefile\n+++ a/Makefile\n@@ -39,8 +39,8 @@\n GNU_READLINE ?= 1\n \n # Get SDL2 related build flags.\n-SDL2_CFLAGS := $("
},
{
"path": "scriptmodules/emulators/jzintv.sh",
"chars": 3609,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/linapple.sh",
"chars": 2070,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/mame/lzma_armv7_crc.diff",
"chars": 379,
"preview": "diff --git a/3rdparty/lzma/C/7zCrc.c b/3rdparty/lzma/C/7zCrc.c\nindex f186324d..f39fe1c9 100644\n--- a/3rdparty/lzma/C/7zC"
},
{
"path": "scriptmodules/emulators/mame.sh",
"chars": 7349,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/mame4all.sh",
"chars": 2936,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/minivmac.sh",
"chars": 2699,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/mupen64plus/0001-GLideN64-use-emplace.patch",
"chars": 438,
"preview": "diff --git a/GLideN64/src/Combiner.cpp b/GLideN64/src/Combiner.cpp\nindex f724cc0..0141f6c 100644\n--- a/GLideN64/src/Comb"
},
{
"path": "scriptmodules/emulators/mupen64plus/mupen64plus.sh",
"chars": 13085,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/mupen64plus/remove_fast_math.diff",
"chars": 3090,
"preview": "--- a/mupen64plus-audio-sdl/projects/unix/Makefile\n+++ b/mupen64plus-audio-sdl/projects/unix/Makefile\n@@ -99,7 +99,7 @@ "
},
{
"path": "scriptmodules/emulators/mupen64plus.sh",
"chars": 17258,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/np2pi.sh",
"chars": 1999,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/openmsx/retropie-init.tcl",
"chars": 1304,
"preview": "namespace eval retropie {\n\nproc init {} {\n set rom_name [guess_title]\n set config_dir [file normalize \"$::env(OPEN"
},
{
"path": "scriptmodules/emulators/openmsx.sh",
"chars": 4300,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/oricutron.sh",
"chars": 2061,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/osmose.sh",
"chars": 1573,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/pcsx-rearmed.sh",
"chars": 2355,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/pcsx2.sh",
"chars": 3323,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/pifba.sh",
"chars": 2211,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/pisnes.sh",
"chars": 1647,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/ppsspp/gles2_fix.diff",
"chars": 1293,
"preview": "diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp\nindex 425f247..ea690d8 100644\n--- a"
},
{
"path": "scriptmodules/emulators/ppsspp/sdl_ttf_fix_before_1.19.diff",
"chars": 1234,
"preview": "diff --git a/Common/Render/Text/draw_text_sdl.h b/Common/Render/Text/draw_text_sdl.h\nindex 87c543a..bfd3842 100644\n--- a"
},
{
"path": "scriptmodules/emulators/ppsspp/tinker.armv7.cmake",
"chars": 507,
"preview": "include_directories(SYSTEM\n /usr/local/include\n /usr/include\n)\n\nset(ARCH_FLAGS \"-O2 -marm -march=armv7-a -mfpu=neon-vf"
},
{
"path": "scriptmodules/emulators/ppsspp-1.5.4.sh",
"chars": 1097,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/ppsspp.sh",
"chars": 7825,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/px68k/001-missing-typedef.diff",
"chars": 311,
"preview": "diff --git a/win32api/peace.c b/win32api/peace.c\nindex 86989db..8a09337 100755\n--- a/win32api/peace.c\n+++ b/win32api/pea"
},
{
"path": "scriptmodules/emulators/px68k.sh",
"chars": 2635,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/quasi88/01_cmake.diff",
"chars": 768,
"preview": "diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex 83c52bc..98deb4f 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ "
},
{
"path": "scriptmodules/emulators/quasi88.sh",
"chars": 2080,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/redream.sh",
"chars": 1909,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/reicast/0001-enable-rpi4-sdl2-target.patch",
"chars": 643,
"preview": "diff --git a/shell/linux/Makefile b/shell/linux/Makefile\nindex 96c2e58..a975698 100644\n--- a/shell/linux/Makefile\n+++ b/"
},
{
"path": "scriptmodules/emulators/reicast/0002-enable-vsync.patch",
"chars": 321,
"preview": "diff --git a/core/sdl/sdl.cpp b/core/sdl/sdl.cpp\nindex 6dc0eea..c161fa1 100644\n--- a/core/sdl/sdl.cpp\n+++ b/core/sdl/sdl"
},
{
"path": "scriptmodules/emulators/reicast/0003-fix-sdl2-sighandler-conflict.patch",
"chars": 1214,
"preview": "diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp\nindex aa29515..f53c871 100644\n--- a/core/linux-dist/mai"
},
{
"path": "scriptmodules/emulators/reicast/reicast.sh",
"chars": 1247,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/reicast.sh",
"chars": 5498,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/retroarch/mess2016_libretro.info",
"chars": 1781,
"preview": "# Software Information\ndisplay_name = \"Mess (MAME 2016)\"\nauthors = \"MAMEdev\"\nsupported_extensions = \"zip|chd|7z|cmd\"\ncor"
},
{
"path": "scriptmodules/emulators/retroarch/mupen64plus_libretro.info",
"chars": 1213,
"preview": "# Software Information\ndisplay_name = \"Nintendo - Nintendo 64 (Mupen64Plus-Legacy)\"\nauthors = \"m4xw|Hacktarux|gonetz|GLi"
},
{
"path": "scriptmodules/emulators/retroarch.sh",
"chars": 16608,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/rpix86.sh",
"chars": 1465,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/scummvm-sdl1.sh",
"chars": 1359,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/scummvm.sh",
"chars": 3141,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/sdltrs.sh",
"chars": 2528,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/simcoupe.sh",
"chars": 2593,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/snes9x.sh",
"chars": 1461,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/stella.sh",
"chars": 1557,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/stratagus.sh",
"chars": 1543,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/supermodel3.sh",
"chars": 3255,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/ti99sim/missing_cstring.diff",
"chars": 260,
"preview": "--- a/src/core/device-support.cpp\n+++ b/src/core/device-support.cpp\n@@ -26,6 +26,7 @@\n //\n //---------------------------"
},
{
"path": "scriptmodules/emulators/ti99sim-sdl1/missing_cstdio.diff",
"chars": 268,
"preview": "--- a/include/common.hpp\n+++ b/include/common.hpp\n@@ -30,6 +30,7 @@\n #define COMMON_HPP_\n \n #include <cstdlib>\t// For de"
},
{
"path": "scriptmodules/emulators/ti99sim-sdl1.sh",
"chars": 1784,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/ti99sim.sh",
"chars": 1920,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/uae4all/01_guichan.diff",
"chars": 1274,
"preview": "diff --git a/src/widget.cpp b/src/widget.cpp\nindex 7dfc7e1..97978a7 100644\n--- a/src/widget.cpp\n+++ b/src/widget.cpp\n@@ "
},
{
"path": "scriptmodules/emulators/uae4all.sh",
"chars": 3401,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/uae4arm/uae4arm.sh",
"chars": 2982,
"preview": "#!/bin/bash\nis_amiberry=0\n\nemulator=\"./uae4arm\"\n[[ \"$is_amiberry\" -eq 1 ]] && emulator=\"./amiberry\"\n\npushd \"${0%/*}\" >/d"
},
{
"path": "scriptmodules/emulators/uae4arm.sh",
"chars": 3309,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/vice.sh",
"chars": 4116,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/xm7/01_fix_build.diff",
"chars": 1529,
"preview": "diff --git a/linux-sdl/CMakeLists.txt b/linux-sdl/CMakeLists.txt\nindex e6988ff..00582e5 100644\n--- a/linux-sdl/CMakeList"
},
{
"path": "scriptmodules/emulators/xm7.sh",
"chars": 3073,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/xroar.sh",
"chars": 2479,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/yabasanshiro.sh",
"chars": 2151,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/emulators/zesarux.sh",
"chars": 3268,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/helpers.sh",
"chars": 61153,
"preview": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developer"
},
{
"path": "scriptmodules/inifuncs.sh",
"chars": 7718,
"preview": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developer"
},
{
"path": "scriptmodules/libretrocores/lr-81.sh",
"chars": 1183,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-atari800.sh",
"chars": 1854,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-lynx.sh",
"chars": 1368,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-ngp.sh",
"chars": 1570,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-pce-fast.sh",
"chars": 1600,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-pce.sh",
"chars": 1645,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-pcfx.sh",
"chars": 1270,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-psx.sh",
"chars": 1567,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-saturn.sh",
"chars": 1385,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-supergrafx.sh",
"chars": 1450,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-vb.sh",
"chars": 1432,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-beetle-wswan.sh",
"chars": 1713,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-bennugd.sh",
"chars": 1436,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-bluemsx.sh",
"chars": 2230,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-bsnes.sh",
"chars": 1460,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-caprice32.sh",
"chars": 1452,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-desmume.sh",
"chars": 1560,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-desmume2015.sh",
"chars": 1332,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-dinothawr.sh",
"chars": 1542,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-dirksimple.sh",
"chars": 1633,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-dolphin.sh",
"chars": 1531,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-dosbox-pure.sh",
"chars": 1565,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-dosbox.sh",
"chars": 1497,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-ep128emu.sh",
"chars": 1285,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-fbalpha2012.sh",
"chars": 2064,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-fbneo.sh",
"chars": 4793,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-fceumm.sh",
"chars": 1651,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-flycast/01_flags_fix.diff",
"chars": 768,
"preview": "diff --git a/Makefile b/Makefile\nindex 2c477b4d..92a67b62 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -44,8 +44,6 @@ LDFLAGS"
},
{
"path": "scriptmodules/libretrocores/lr-flycast-dev.sh",
"chars": 2482,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-flycast.sh",
"chars": 3535,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-fmsx.sh",
"chars": 1525,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-freechaf.sh",
"chars": 1329,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-freeintv.sh",
"chars": 1343,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-fuse.sh",
"chars": 1431,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-gambatte/default.pal",
"chars": 263,
"preview": "[General]\r\nBackground0=10140443\r\nBackground1=9087769\r\nBackground2=3105072\r\nBackground3=931599\r\nSprite%2010=10140443\r\nSpr"
},
{
"path": "scriptmodules/libretrocores/lr-gambatte.sh",
"chars": 1762,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-geargrafx.sh",
"chars": 1460,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-gearsystem.sh",
"chars": 1518,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-genesis-plus-gx.sh",
"chars": 2012,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-gpsp.sh",
"chars": 1483,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-gw.sh",
"chars": 1257,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-handy.sh",
"chars": 1244,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-hatari/01_libcapsimage.diff",
"chars": 3675,
"preview": "diff --git a/Makefile.libretro b/Makefile.libretro\nindex 58e33e4..eb654c6 100755\n--- a/Makefile.libretro\n+++ b/Makefile."
},
{
"path": "scriptmodules/libretrocores/lr-hatari.sh",
"chars": 1987,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-kronos.sh",
"chars": 1568,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame.sh",
"chars": 3101,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2000.sh",
"chars": 1719,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2003-plus.sh",
"chars": 1257,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2003.sh",
"chars": 2783,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2010.sh",
"chars": 1894,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2015/01-python3-irgen.diff",
"chars": 2216,
"preview": "diff --git a/src/emu/cpu/m6502/m6502make.py b/src/emu/cpu/m6502/m6502make.py\nindex da29fc7..3de641d 100755\n--- a/src/emu"
},
{
"path": "scriptmodules/libretrocores/lr-mame2015.sh",
"chars": 1628,
"preview": "#!/usr/bin/env bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its d"
},
{
"path": "scriptmodules/libretrocores/lr-mame2016/01-python3-irgen.diff",
"chars": 2283,
"preview": "diff --git a/src/devices/cpu/m6502/m6502make.py b/src/devices/cpu/m6502/m6502make.py\nindex 8bcd85f8..557b1759 100755\n---"
}
]
// ... and 198 more files (download for full content)
About this extraction
This page contains the full source code of the RetroPie/RetroPie-Setup GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 398 files (1.4 MB), approximately 409.8k tokens, and a symbol index with 95 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.