[
  {
    "path": ".github/FUNDING.yml",
    "content": "patreon: retropie\ncustom: https://retropie.org.uk/donate/\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug-report.yml",
    "content": "name: Create Issue\ndescription: |\n Report a bug with RetroPie-Setup scripts\nbody:\n\n  - type: markdown\n    id: info\n    attributes:\n     value: |\n       #### Important\n       Only RetroPie-Setup **bugs** should be reported here as an Issue.\n       For general support questions, games troubleshooting and enhancement requests please use the [RetroPie Forums](https://retropie.org.uk/forum).\n    validations:\n      required: false\n\n  - type: textarea\n    id: description\n    attributes:\n      label: Description\n      placeholder: describe the problem/bug in RetroPie's scripts\n    validations:\n      required: true\n\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: RetroPie Forums\n    url: https://retropie.org.uk/forum\n    about: Community for discussion and support\n  \n  - name: Documentation\n    url: https://retropie.org.uk/docs\n    about: Official RetroPie Documentation\n"
  },
  {
    "path": ".gitignore",
    "content": "# OS generated files #\n######################\n.DS_Store\n.DS_Store?\n._*\n.Spotlight-V100\n.Trashes\nIcon?\nehthumbs.db\nThumbs.db\n\n# Generated files\nlogs/\ntmp/\n\n# 3rd Party Repos\next/*\n"
  },
  {
    "path": "AUTHORS",
    "content": "Florian Müller - <contact [at] petrockblock.com>\n   - Main code, maintainer\n\nJools Wills - <buzz [at] exotica.org.uk>\n   - Main code, maintainer\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# How to contribute\n\n## Support Requests vs Bug Reporting\n\nPlease use the GitHub for bug reports only. For help / support in using RetroPie and the emulators\nit ships with, please use the [RetroPie forum](https://retropie.org.uk/forum/).\n\n## Pull Requests\n\nContributions to the project are welcome - please check out our [Shell Style Guide](https://retropie.org.uk/docs/Shell-Style-Guide/) before submitting changes.\n"
  },
  {
    "path": "COPYRIGHT.md",
    "content": "The RetroPie Project\nCopyright (C) 2012-2025 by the following:\n\nIf you have contributed to this project then you deserve to be on this\nlist. Contact us (see: AUTHORS) and we'll add you.\n\n* Florian Müller \"petrockblog\"\n* Jools Wills \"joolswills\"\n* Peter Mahlknecht\n* Aloshi\n* Martin Modahl\n* marqs\n* Juan Pablo Zapata, jpzapa\n* Xevin\n* James Le Cuirot\n* Ewan Meadows\n* Adam \"adskiremote\"\n* Hyperspin\n* Claudio Cesar Sanchez Tejeda,\n* cdu13a\n* Christian Bryn\n* Adam Smith\n* Adrian Moisey\n* Sergej Tatarincev\n* \"HerbFargus\"\n* Stefan \"gizmo98\"\n\nFor most recent list see also https://github.com/RetroPie/RetroPie-Setup/graphs/contributors\n"
  },
  {
    "path": "LICENSE.md",
    "content": "# RetroPie Legal Information\n\n## License\n\n### GNU GENERAL PUBLIC LICENSE, Version 3, 29 June 2007\n\nCopyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n### Preamble\n\n  The GNU General Public License is a free, copyleft license for\nsoftware and other kinds of works.\n\n  The licenses for most software and other practical works are designed\nto take away your freedom to share and change the works.  By contrast,\nthe GNU General Public License is intended to guarantee your freedom to\nshare and change all versions of a program--to make sure it remains free\nsoftware for all its users.  We, the Free Software Foundation, use the\nGNU General Public License for most of our software; it applies also to\nany other work released this way by its authors.  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthem if you wish), that you receive source code or can get it if you\nwant it, that you can change the software or use pieces of it in new\nfree programs, and that you know you can do these things.\n\n  To protect your rights, we need to prevent others from denying you\nthese rights or asking you to surrender the rights.  Therefore, you have\ncertain responsibilities if you distribute copies of the software, or if\nyou modify it: responsibilities to respect the freedom of others.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must pass on to the recipients the same\nfreedoms that you received.  You must make sure that they, too, receive\nor can get the source code.  And you must show them these terms so they\nknow their rights.\n\n  Developers that use the GNU GPL protect your rights with two steps:\n(1) assert copyright on the software, and (2) offer you this License\ngiving you legal permission to copy, distribute and/or modify it.\n\n  For the developers' and authors' protection, the GPL clearly explains\nthat there is no warranty for this free software.  For both users' and\nauthors' sake, the GPL requires that modified versions be marked as\nchanged, so that their problems will not be attributed erroneously to\nauthors of previous versions.\n\n  Some devices are designed to deny users access to install or run\nmodified versions of the software inside them, although the manufacturer\ncan do so.  This is fundamentally incompatible with the aim of\nprotecting users' freedom to change the software.  The systematic\npattern of such abuse occurs in the area of products for individuals to\nuse, which is precisely where it is most unacceptable.  Therefore, we\nhave designed this version of the GPL to prohibit the practice for those\nproducts.  If such problems arise substantially in other domains, we\nstand ready to extend this provision to those domains in future versions\nof the GPL, as needed to protect the freedom of users.\n\n  Finally, every program is threatened constantly by software patents.\nStates should not allow patents to restrict development and use of\nsoftware on general-purpose computers, but in those that do, we wish to\navoid the special danger that patents applied to a free program could\nmake it effectively proprietary.  To prevent this, the GPL assures that\npatents cannot be used to render the program non-free.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n### TERMS AND CONDITIONS\n\n#### 0. Definitions.\n\n  \"This License\" refers to version 3 of the GNU General Public License.\n\n  \"Copyright\" also means copyright-like laws that apply to other kinds of\nworks, such as semiconductor masks.\n\n  \"The Program\" refers to any copyrightable work licensed under this\nLicense.  Each licensee is addressed as \"you\".  \"Licensees\" and\n\"recipients\" may be individuals or organizations.\n\n  To \"modify\" a work means to copy from or adapt all or part of the work\nin a fashion requiring copyright permission, other than the making of an\nexact copy.  The resulting work is called a \"modified version\" of the\nearlier work or a work \"based on\" the earlier work.\n\n  A \"covered work\" means either the unmodified Program or a work based\non the Program.\n\n  To \"propagate\" a work means to do anything with it that, without\npermission, would make you directly or secondarily liable for\ninfringement under applicable copyright law, except executing it on a\ncomputer or modifying a private copy.  Propagation includes copying,\ndistribution (with or without modification), making available to the\npublic, and in some countries other activities as well.\n\n  To \"convey\" a work means any kind of propagation that enables other\nparties to make or receive copies.  Mere interaction with a user through\na computer network, with no transfer of a copy, is not conveying.\n\n  An interactive user interface displays \"Appropriate Legal Notices\"\nto the extent that it includes a convenient and prominently visible\nfeature that (1) displays an appropriate copyright notice, and (2)\ntells the user that there is no warranty for the work (except to the\nextent that warranties are provided), that licensees may convey the\nwork under this License, and how to view a copy of this License.  If\nthe interface presents a list of user commands or options, such as a\nmenu, a prominent item in the list meets this criterion.\n\n#### 1. Source Code.\n\n  The \"source code\" for a work means the preferred form of the work\nfor making modifications to it.  \"Object code\" means any non-source\nform of a work.\n\n  A \"Standard Interface\" means an interface that either is an official\nstandard defined by a recognized standards body, or, in the case of\ninterfaces specified for a particular programming language, one that\nis widely used among developers working in that language.\n\n  The \"System Libraries\" of an executable work include anything, other\nthan the work as a whole, that (a) is included in the normal form of\npackaging a Major Component, but which is not part of that Major\nComponent, and (b) serves only to enable use of the work with that\nMajor Component, or to implement a Standard Interface for which an\nimplementation is available to the public in source code form.  A\n\"Major Component\", in this context, means a major essential component\n(kernel, window system, and so on) of the specific operating system\n(if any) on which the executable work runs, or a compiler used to\nproduce the work, or an object code interpreter used to run it.\n\n  The \"Corresponding Source\" for a work in object code form means all\nthe source code needed to generate, install, and (for an executable\nwork) run the object code and to modify the work, including scripts to\ncontrol those activities.  However, it does not include the work's\nSystem Libraries, or general-purpose tools or generally available free\nprograms which are used unmodified in performing those activities but\nwhich are not part of the work.  For example, Corresponding Source\nincludes interface definition files associated with source files for\nthe work, and the source code for shared libraries and dynamically\nlinked subprograms that the work is specifically designed to require,\nsuch as by intimate data communication or control flow between those\nsubprograms and other parts of the work.\n\n  The Corresponding Source need not include anything that users\ncan regenerate automatically from other parts of the Corresponding\nSource.\n\n  The Corresponding Source for a work in source code form is that\nsame work.\n\n#### 2. Basic Permissions.\n\n  All rights granted under this License are granted for the term of\ncopyright on the Program, and are irrevocable provided the stated\nconditions are met.  This License explicitly affirms your unlimited\npermission to run the unmodified Program.  The output from running a\ncovered work is covered by this License only if the output, given its\ncontent, constitutes a covered work.  This License acknowledges your\nrights of fair use or other equivalent, as provided by copyright law.\n\n  You may make, run and propagate covered works that you do not\nconvey, without conditions so long as your license otherwise remains\nin force.  You may convey covered works to others for the sole purpose\nof having them make modifications exclusively for you, or provide you\nwith facilities for running those works, provided that you comply with\nthe terms of this License in conveying all material for which you do\nnot control copyright.  Those thus making or running the covered works\nfor you must do so exclusively on your behalf, under your direction\nand control, on terms that prohibit them from making any copies of\nyour copyrighted material outside their relationship with you.\n\n  Conveying under any other circumstances is permitted solely under\nthe conditions stated below.  Sublicensing is not allowed; section 10\nmakes it unnecessary.\n\n#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.\n\n  No covered work shall be deemed part of an effective technological\nmeasure under any applicable law fulfilling obligations under article\n11 of the WIPO copyright treaty adopted on 20 December 1996, or\nsimilar laws prohibiting or restricting circumvention of such\nmeasures.\n\n  When you convey a covered work, you waive any legal power to forbid\ncircumvention of technological measures to the extent such circumvention\nis effected by exercising rights under this License with respect to\nthe covered work, and you disclaim any intention to limit operation or\nmodification of the work as a means of enforcing, against the work's\nusers, your or third parties' legal rights to forbid circumvention of\ntechnological measures.\n\n#### 4. Conveying Verbatim Copies.\n\n  You may convey verbatim copies of the Program's source code as you\nreceive it, in any medium, provided that you conspicuously and\nappropriately publish on each copy an appropriate copyright notice;\nkeep intact all notices stating that this License and any\nnon-permissive terms added in accord with section 7 apply to the code;\nkeep intact all notices of the absence of any warranty; and give all\nrecipients a copy of this License along with the Program.\n\n  You may charge any price or no price for each copy that you convey,\nand you may offer support or warranty protection for a fee.\n\n#### 5. Conveying Modified Source Versions.\n\n  You may convey a work based on the Program, or the modifications to\nproduce it from the Program, in the form of source code under the\nterms of section 4, provided that you also meet all of these conditions:\n\na) The work must carry prominent notices stating that you modified\nit, and giving a relevant date.\n\nb) The work must carry prominent notices stating that it is\nreleased under this License and any conditions added under section\n7.  This requirement modifies the requirement in section 4 to\n\"keep intact all notices\".\n\nc) You must license the entire work, as a whole, under this\nLicense to anyone who comes into possession of a copy.  This\nLicense will therefore apply, along with any applicable section 7\nadditional terms, to the whole of the work, and all its parts,\nregardless of how they are packaged.  This License gives no\npermission to license the work in any other way, but it does not\ninvalidate such permission if you have separately received it.\n\nd) If the work has interactive user interfaces, each must display\nAppropriate Legal Notices; however, if the Program has interactive\ninterfaces that do not display Appropriate Legal Notices, your\nwork need not make them do so.\n\n  A compilation of a covered work with other separate and independent\nworks, which are not by their nature extensions of the covered work,\nand which are not combined with it such as to form a larger program,\nin or on a volume of a storage or distribution medium, is called an\n\"aggregate\" if the compilation and its resulting copyright are not\nused to limit the access or legal rights of the compilation's users\nbeyond what the individual works permit.  Inclusion of a covered work\nin an aggregate does not cause this License to apply to the other\nparts of the aggregate.\n\n#### 6. Conveying Non-Source Forms.\n\n  You may convey a covered work in object code form under the terms\nof sections 4 and 5, provided that you also convey the\nmachine-readable Corresponding Source under the terms of this License,\nin one of these ways:\n\na) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by the\nCorresponding Source fixed on a durable physical medium\ncustomarily used for software interchange.\n\nb) Convey the object code in, or embodied in, a physical product\n(including a physical distribution medium), accompanied by a\nwritten offer, valid for at least three years and valid for as\nlong as you offer spare parts or customer support for that product\nmodel, to give anyone who possesses the object code either (1) a\ncopy of the Corresponding Source for all the software in the\nproduct that is covered by this License, on a durable physical\nmedium customarily used for software interchange, for a price no\nmore than your reasonable cost of physically performing this\nconveying of source, or (2) access to copy the\nCorresponding Source from a network server at no charge.\n\nc) Convey individual copies of the object code with a copy of the\nwritten offer to provide the Corresponding Source.  This\nalternative is allowed only occasionally and noncommercially, and\nonly if you received the object code with such an offer, in accord\nwith subsection 6b.\n\nd) Convey the object code by offering access from a designated\nplace (gratis or for a charge), and offer equivalent access to the\nCorresponding Source in the same way through the same place at no\nfurther charge.  You need not require recipients to copy the\nCorresponding Source along with the object code.  If the place to\ncopy the object code is a network server, the Corresponding Source\nmay be on a different server (operated by you or a third party)\nthat supports equivalent copying facilities, provided you maintain\nclear directions next to the object code saying where to find the\nCorresponding Source.  Regardless of what server hosts the\nCorresponding Source, you remain obligated to ensure that it is\navailable for as long as needed to satisfy these requirements.\n\ne) Convey the object code using peer-to-peer transmission, provided\nyou inform other peers where the object code and Corresponding\nSource of the work are being offered to the general public at no\ncharge under subsection 6d.\n\n  A separable portion of the object code, whose source code is excluded\nfrom the Corresponding Source as a System Library, need not be\nincluded in conveying the object code work.\n\n  A \"User Product\" is either (1) a \"consumer product\", which means any\ntangible personal property which is normally used for personal, family,\nor household purposes, or (2) anything designed or sold for incorporation\ninto a dwelling.  In determining whether a product is a consumer product,\ndoubtful cases shall be resolved in favor of coverage.  For a particular\nproduct received by a particular user, \"normally used\" refers to a\ntypical or common use of that class of product, regardless of the status\nof the particular user or of the way in which the particular user\nactually uses, or expects or is expected to use, the product.  A product\nis a consumer product regardless of whether the product has substantial\ncommercial, industrial or non-consumer uses, unless such uses represent\nthe only significant mode of use of the product.\n\n  \"Installation Information\" for a User Product means any methods,\nprocedures, authorization keys, or other information required to install\nand execute modified versions of a covered work in that User Product from\na modified version of its Corresponding Source.  The information must\nsuffice to ensure that the continued functioning of the modified object\ncode is in no case prevented or interfered with solely because\nmodification has been made.\n\n  If you convey an object code work under this section in, or with, or\nspecifically for use in, a User Product, and the conveying occurs as\npart of a transaction in which the right of possession and use of the\nUser Product is transferred to the recipient in perpetuity or for a\nfixed term (regardless of how the transaction is characterized), the\nCorresponding Source conveyed under this section must be accompanied\nby the Installation Information.  But this requirement does not apply\nif neither you nor any third party retains the ability to install\nmodified object code on the User Product (for example, the work has\nbeen installed in ROM).\n\n  The requirement to provide Installation Information does not include a\nrequirement to continue to provide support service, warranty, or updates\nfor a work that has been modified or installed by the recipient, or for\nthe User Product in which it has been modified or installed.  Access to a\nnetwork may be denied when the modification itself materially and\nadversely affects the operation of the network or violates the rules and\nprotocols for communication across the network.\n\n  Corresponding Source conveyed, and Installation Information provided,\nin accord with this section must be in a format that is publicly\ndocumented (and with an implementation available to the public in\nsource code form), and must require no special password or key for\nunpacking, reading or copying.\n\n#### 7. Additional Terms.\n\n  \"Additional permissions\" are terms that supplement the terms of this\nLicense by making exceptions from one or more of its conditions.\nAdditional permissions that are applicable to the entire Program shall\nbe treated as though they were included in this License, to the extent\nthat they are valid under applicable law.  If additional permissions\napply only to part of the Program, that part may be used separately\nunder those permissions, but the entire Program remains governed by\nthis License without regard to the additional permissions.\n\n  When you convey a copy of a covered work, you may at your option\nremove any additional permissions from that copy, or from any part of\nit.  (Additional permissions may be written to require their own\nremoval in certain cases when you modify the work.)  You may place\nadditional permissions on material, added by you to a covered work,\nfor which you have or can give appropriate copyright permission.\n\n  Notwithstanding any other provision of this License, for material you\nadd to a covered work, you may (if authorized by the copyright holders of\nthat material) supplement the terms of this License with terms:\n\na) Disclaiming warranty or limiting liability differently from the\nterms of sections 15 and 16 of this License; or\n\nb) Requiring preservation of specified reasonable legal notices or\nauthor attributions in that material or in the Appropriate Legal\nNotices displayed by works containing it; or\n\nc) Prohibiting misrepresentation of the origin of that material, or\nrequiring that modified versions of such material be marked in\nreasonable ways as different from the original version; or\n\nd) Limiting the use for publicity purposes of names of licensors or\nauthors of the material; or\n\ne) Declining to grant rights under trademark law for use of some\ntrade names, trademarks, or service marks; or\n\nf) Requiring indemnification of licensors and authors of that\nmaterial by anyone who conveys the material (or modified versions of\nit) with contractual assumptions of liability to the recipient, for\nany liability that these contractual assumptions directly impose on\nthose licensors and authors.\n\n  All other non-permissive additional terms are considered \"further\nrestrictions\" within the meaning of section 10.  If the Program as you\nreceived it, or any part of it, contains a notice stating that it is\ngoverned by this License along with a term that is a further\nrestriction, you may remove that term.  If a license document contains\na further restriction but permits relicensing or conveying under this\nLicense, you may add to a covered work material governed by the terms\nof that license document, provided that the further restriction does\nnot survive such relicensing or conveying.\n\n  If you add terms to a covered work in accord with this section, you\nmust place, in the relevant source files, a statement of the\nadditional terms that apply to those files, or a notice indicating\nwhere to find the applicable terms.\n\n  Additional terms, permissive or non-permissive, may be stated in the\nform of a separately written license, or stated as exceptions;\nthe above requirements apply either way.\n\n#### 8. Termination.\n\n  You may not propagate or modify a covered work except as expressly\nprovided under this License.  Any attempt otherwise to propagate or\nmodify it is void, and will automatically terminate your rights under\nthis License (including any patent licenses granted under the third\nparagraph of section 11).\n\n  However, if you cease all violation of this License, then your\nlicense from a particular copyright holder is reinstated (a)\nprovisionally, unless and until the copyright holder explicitly and\nfinally terminates your license, and (b) permanently, if the copyright\nholder fails to notify you of the violation by some reasonable means\nprior to 60 days after the cessation.\n\n  Moreover, your license from a particular copyright holder is\nreinstated permanently if the copyright holder notifies you of the\nviolation by some reasonable means, this is the first time you have\nreceived notice of violation of this License (for any work) from that\ncopyright holder, and you cure the violation prior to 30 days after\nyour receipt of the notice.\n\n  Termination of your rights under this section does not terminate the\nlicenses of parties who have received copies or rights from you under\nthis License.  If your rights have been terminated and not permanently\nreinstated, you do not qualify to receive new licenses for the same\nmaterial under section 10.\n\n#### 9. Acceptance Not Required for Having Copies.\n\n  You are not required to accept this License in order to receive or\nrun a copy of the Program.  Ancillary propagation of a covered work\noccurring solely as a consequence of using peer-to-peer transmission\nto receive a copy likewise does not require acceptance.  However,\nnothing other than this License grants you permission to propagate or\nmodify any covered work.  These actions infringe copyright if you do\nnot accept this License.  Therefore, by modifying or propagating a\ncovered work, you indicate your acceptance of this License to do so.\n\n#### 10. Automatic Licensing of Downstream Recipients.\n\n  Each time you convey a covered work, the recipient automatically\nreceives a license from the original licensors, to run, modify and\npropagate that work, subject to this License.  You are not responsible\nfor enforcing compliance by third parties with this License.\n\n  An \"entity transaction\" is a transaction transferring control of an\norganization, or substantially all assets of one, or subdividing an\norganization, or merging organizations.  If propagation of a covered\nwork results from an entity transaction, each party to that\ntransaction who receives a copy of the work also receives whatever\nlicenses to the work the party's predecessor in interest had or could\ngive under the previous paragraph, plus a right to possession of the\nCorresponding Source of the work from the predecessor in interest, if\nthe predecessor has it or can get it with reasonable efforts.\n\n  You may not impose any further restrictions on the exercise of the\nrights granted or affirmed under this License.  For example, you may\nnot impose a license fee, royalty, or other charge for exercise of\nrights granted under this License, and you may not initiate litigation\n(including a cross-claim or counterclaim in a lawsuit) alleging that\nany patent claim is infringed by making, using, selling, offering for\nsale, or importing the Program or any portion of it.\n\n#### 11. Patents.\n\n  A \"contributor\" is a copyright holder who authorizes use under this\nLicense of the Program or a work on which the Program is based.  The\nwork thus licensed is called the contributor's \"contributor version\".\n\n  A contributor's \"essential patent claims\" are all patent claims\nowned or controlled by the contributor, whether already acquired or\nhereafter acquired, that would be infringed by some manner, permitted\nby this License, of making, using, or selling its contributor version,\nbut do not include claims that would be infringed only as a\nconsequence of further modification of the contributor version.  For\npurposes of this definition, \"control\" includes the right to grant\npatent sublicenses in a manner consistent with the requirements of\nthis License.\n\n  Each contributor grants you a non-exclusive, worldwide, royalty-free\npatent license under the contributor's essential patent claims, to\nmake, use, sell, offer for sale, import and otherwise run, modify and\npropagate the contents of its contributor version.\n\n  In the following three paragraphs, a \"patent license\" is any express\nagreement or commitment, however denominated, not to enforce a patent\n(such as an express permission to practice a patent or covenant not to\nsue for patent infringement).  To \"grant\" such a patent license to a\nparty means to make such an agreement or commitment not to enforce a\npatent against the party.\n\n  If you convey a covered work, knowingly relying on a patent license,\nand the Corresponding Source of the work is not available for anyone\nto copy, free of charge and under the terms of this License, through a\npublicly available network server or other readily accessible means,\nthen you must either (1) cause the Corresponding Source to be so\navailable, or (2) arrange to deprive yourself of the benefit of the\npatent license for this particular work, or (3) arrange, in a manner\nconsistent with the requirements of this License, to extend the patent\nlicense to downstream recipients.  \"Knowingly relying\" means you have\nactual knowledge that, but for the patent license, your conveying the\ncovered work in a country, or your recipient's use of the covered work\nin a country, would infringe one or more identifiable patents in that\ncountry that you have reason to believe are valid.\n\n  If, pursuant to or in connection with a single transaction or\narrangement, you convey, or propagate by procuring conveyance of, a\ncovered work, and grant a patent license to some of the parties\nreceiving the covered work authorizing them to use, propagate, modify\nor convey a specific copy of the covered work, then the patent license\nyou grant is automatically extended to all recipients of the covered\nwork and works based on it.\n\n  A patent license is \"discriminatory\" if it does not include within\nthe scope of its coverage, prohibits the exercise of, or is\nconditioned on the non-exercise of one or more of the rights that are\nspecifically granted under this License.  You may not convey a covered\nwork if you are a party to an arrangement with a third party that is\nin the business of distributing software, under which you make payment\nto the third party based on the extent of your activity of conveying\nthe work, and under which the third party grants, to any of the\nparties who would receive the covered work from you, a discriminatory\npatent license (a) in connection with copies of the covered work\nconveyed by you (or copies made from those copies), or (b) primarily\nfor and in connection with specific products or compilations that\ncontain the covered work, unless you entered into that arrangement,\nor that patent license was granted, prior to 28 March 2007.\n\n  Nothing in this License shall be construed as excluding or limiting\nany implied license or other defenses to infringement that may\notherwise be available to you under applicable patent law.\n\n#### 12. No Surrender of Others' Freedom.\n\n  If conditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot convey a\ncovered work so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you may\nnot convey it at all.  For example, if you agree to terms that obligate you\nto collect a royalty for further conveying from those to whom you convey\nthe Program, the only way you could satisfy both those terms and this\nLicense would be to refrain entirely from conveying the Program.\n\n#### 13. Use with the GNU Affero General Public License.\n\n  Notwithstanding any other provision of this License, you have\npermission to link or combine any covered work with a work licensed\nunder version 3 of the GNU Affero General Public License into a single\ncombined work, and to convey the resulting work.  The terms of this\nLicense will continue to apply to the part which is the covered work,\nbut the special requirements of the GNU Affero General Public License,\nsection 13, concerning interaction through a network will apply to the\ncombination as such.\n\n#### 14. Revised Versions of this License.\n\n  The Free Software Foundation may publish revised and/or new versions of\nthe GNU General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\n  Each version is given a distinguishing version number.  If the\nProgram specifies that a certain numbered version of the GNU General\nPublic License \"or any later version\" applies to it, you have the\noption of following the terms and conditions either of that numbered\nversion or of any later version published by the Free Software\nFoundation.  If the Program does not specify a version number of the\nGNU General Public License, you may choose any version ever published\nby the Free Software Foundation.\n\n  If the Program specifies that a proxy can decide which future\nversions of the GNU General Public License can be used, that proxy's\npublic statement of acceptance of a version permanently authorizes you\nto choose that version for the Program.\n\n  Later license versions may give you additional or different\npermissions.  However, no additional obligations are imposed on any\nauthor or copyright holder as a result of your choosing to follow a\nlater version.\n\n#### 15. Disclaimer of Warranty.\n\n  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY\nAPPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT\nHOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY\nOF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,\nTHE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR\nPURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM\nIS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF\nALL NECESSARY SERVICING, REPAIR OR CORRECTION.\n\n#### 16. Limitation of Liability.\n\n  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS\nTHE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY\nGENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE\nUSE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF\nDATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD\nPARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),\nEVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF\nSUCH DAMAGES.\n\n#### 17. Interpretation of Sections 15 and 16.\n\n  If the disclaimer of warranty and limitation of liability provided\nabove cannot be given local legal effect according to their terms,\nreviewing courts shall apply local law that most closely approximates\nan absolute waiver of all civil liability in connection with the\nProgram, unless a warranty or assumption of liability accompanies a\ncopy of the Program in return for a fee.\n\nEND OF TERMS AND CONDITIONS\n\n---\n\n## Copyright\n\n(c) Copyright 2012-2015 RetroPie Project (See COPYRIGHT.md)\n"
  },
  {
    "path": "README.md",
    "content": "RetroPie-Setup\n==============\n\nGeneral Usage\n-------------\n\nShell 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.\n\nThis 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.\n\nTo run the RetroPie Setup Script make sure that your APT repositories are up-to-date and that Git is installed:\n\n```shell\nsudo apt-get update\nsudo apt-get dist-upgrade\nsudo apt-get install git\n```\n\nThen you can download the latest RetroPie setup script with:\n\n```shell\ncd\ngit clone --depth=1 https://github.com/RetroPie/RetroPie-Setup.git\n```\n\nThe script is executed with:\n\n```shell\ncd RetroPie-Setup\nsudo ./retropie_setup.sh\n```\n\nWhen you first run the script it may install some additional packages that are needed.\n\nBinaries and Sources\n--------------------\n\nOn 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.\n\nFor more information, visit the site at https://retropie.org.uk or the repository at https://github.com/RetroPie/RetroPie-Setup.\n\nDocs\n----\n\nYou 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).\n\n\nThanks\n------\n\nThis script just simplifies the usage of the great works of many other people that enjoy the spirit of retrogaming. Many thanks go to them!\n"
  },
  {
    "path": "platforms.cfg",
    "content": "3do_exts=\".chd .cue .iso .zip\"\n3do_fullname=\"3DO Interactive Multiplayer\"\n\nags_exts=\".exe\"\nags_fullname=\"Adventure Game Studio\"\n\namiga_exts=\".adf .adz .chd .cue .dms .hdf .hdz .ipf .lha .m3u .sh .uae .zip\"\namiga_fullname=\"Commodore Amiga\"\n\namstradcpc_exts=\".cdt .cpc .cpr .dsk .m3u .tap .zip\"\namstradcpc_fullname=\"Amstrad CPC\"\n\napple2_exts=\".po .dsk .nib\"\napple2_fullname=\"Apple II\"\n\narcade_exts=\".7z .cue .fba .iso .zip\"\narcade_fullname=\"Arcade\"\n\narcadia_exts=\".bin .zip\"\narcadia_fullname=\"Arcadia 2001\"\n\natari2600_exts=\".7z .a26 .bin .rom .zip .gz\"\natari2600_fullname=\"Atari 2600\"\n\natari5200_exts=\".7z .a52 .bin .car .zip\"\natari5200_fullname=\"Atari 5200\"\n\natari7800_exts=\".7z .a78 .bin .zip\"\natari7800_fullname=\"Atari 7800 ProSystem\"\n\natari800_exts=\".7z .atr .atr.gz .atx .bas .bin .car .cas .com .dcm .rom .xex .xfd .xfd.gz .zip\"\natari800_fullname=\"Atari 800\"\n\natarijaguar_exts=\".j64 .jag .zip\"\natarijaguar_fullname=\"Atari Jaguar\"\n\natarilynx_exts=\".7z .lnx .zip\"\natarilynx_fullname=\"Atari Lynx\"\n\natarist_exts=\".st .stx .img .m3u .rom .raw .ipf .ctr .zip\"\natarist_fullname=\"Atari ST\"\n\nc64_exts=\".cmd .crt .d64 .d71 .d80 .d81 .g64 .prg .m3u .t64 .tap .x64 .zip .vsf\"\nc64_fullname=\"Commodore 64\"\n\nchannelf_exts=\".bin .rom .zip .7z\"\nchannelf_fullname=\"Fairchild ChannelF\"\n\ncoco_exts=\".bin .cas .wav .bas .asc .dmk .jvc .os9 .dsk .vdk .rom .ccc .sna\"\ncoco_fullname=\"TRS-80 Color Computer\"\n\ncoleco_exts=\".bin .col .rom .zip\"\ncoleco_fullname=\"ColecoVision\"\ncoleco_theme=\"colecovision\"\ncoleco_platform=\"colecovision\"\n\ncrvision_exts=\".rom .zip\"\ncrvision_fullname=\"CreatiVision\"\n\ndaphne_exts=\".daphne .ogv\"\ndaphne_fullname=\"Daphne\"\n\ndragon32_exts=\".bin .cas .wav .bas .asc .dmk .jvc .os9 .dsk .vdk .rom .ccc .sna\"\ndragon32_fullname=\"Dragon 32\"\n\ndreamcast_exts=\".cdi .chd .cue .gdi .sh .zip .m3u\"\ndreamcast_fullname=\"Dreamcast\"\n\nenterprise_exts=\".img .dsk .tap .dtf .wav .bas .com .trn .128\"\nenterprise_fullname=\"Enterprise 128\"\n\nfba_exts=\".7z .cue .fba .iso .zip\"\nfba_fullname=\"Final Burn Alpha\"\nfba_platform=\"arcade\"\n\nfds_exts=\".7z .nes .fds .zip\"\nfds_fullname=\"Famicom Disk System\"\n\nfm7_exts=\".d77 .t77 .d88 .2d\"\nfm7_fullname=\"Fujitsu FM-7 Series\"\n\ngameandwatch_exts=\".mgw\"\ngameandwatch_fullname=\"Game and Watch\"\n\ngamegear_exts=\".7z .gg .bin .sms .zip\"\ngamegear_fullname=\"Sega Gamegear\"\n\ngba_exts=\".7z .gba .zip\"\ngba_fullname=\"Game Boy Advance\"\n\ngb_exts=\".7z .gb .zip\"\ngb_fullname=\"Game Boy\"\n\ngbc_exts=\".7z .gbc .zip\"\ngbc_fullname=\"Game Boy Color\"\n\ngc_exts=\".ciso .gcm .gcz .iso .rvz .m3u\"\ngc_fullname=\"Nintendo Gamecube\"\n\nintellivision_exts=\".7z .bin .int .itv .rom .zip\"\nintellivision_fullname=\"Intellivision\"\n\nlove_exts=\".love\"\nlove_fullname=\"Love\"\n\nmacintosh_exts=\".txt .dsk\"\nmacintosh_fullname=\"Apple Macintosh\"\n\nmame_exts=\".zip .7z\"\nmame_fullname=\"Multiple Arcade Machine Emulator\"\nmame_platform=\"arcade\"\nmame_theme=\"mame\"\n\nmame-advmame_exts=\".zip\"\nmame-advmame_fullname=\"Multiple Arcade Machine Emulator\"\nmame-advmame_platform=\"arcade\"\nmame-advmame_theme=\"mame\"\n\nmame-libretro_exts=\".zip\"\nmame-libretro_fullname=\"Multiple Arcade Machine Emulator\"\nmame-libretro_platform=\"arcade\"\nmame-libretro_theme=\"mame\"\n\nmame-mame4all_exts=\".zip\"\nmame-mame4all_fullname=\"Multiple Arcade Machine Emulator\"\nmame-mame4all_platform=\"arcade\"\nmame-mame4all_theme=\"mame\"\n\nmastersystem_exts=\".7z .sms .bin .zip\"\nmastersystem_fullname=\"Sega Master System\"\n\nmegadrive_exts=\".7z .smd .bin .gen .md .sg .zip\"\nmegadrive_fullname=\"Sega Mega Drive\"\nmegadrive_theme=\"megadrive\"\nmegadrive_platform=\"megadrive\"\n\nmsx_exts=\".cas .rom .mx1 .mx2 .col .dsk .zip .m3u\"\nmsx_fullname=\"MSX\"\n\nmoto_exts=\".fd .k7 .m5 .m7 .rom .sap\"\nmoto_fullname=\"Thomson MO/TO\"\n\nn64_exts=\".z64 .n64 .v64 .zip\"\nn64_fullname=\"Nintendo 64\"\n\nnds_exts=\".nds .zip\"\nnds_fullname=\"Nintendo DS\"\n\nneogeo_exts=\".7z .chd .cue .fba .iso .zip\"\nneogeo_fullname=\"Neo Geo\"\n\nnes_exts=\".7z .nes .zip\"\nnes_fullname=\"Nintendo Entertainment System\"\n\nngp_exts=\".7z .ngp .zip\"\nngp_fullname=\"Neo Geo Pocket\"\n\nngpc_exts=\".7z .ngc .zip\"\nngpc_fullname=\"Neo Geo Pocket Color\"\n\nnp2pi_exts=\".d88 .d98 .88d .98d .fdi .xdf .hdm .dup .2hd .tfd .hdi .thd .nhd .hdd\"\nnp2pi_fullname=\"NEC PC-9801\"\n\noric_exts=\".dsk .tap\"\noric_fullname=\"Oric 1\"\n\npc88_exts=\".d88 .cmt .m3u .t88\"\npc88_fullname=\"NEC PC-8801\"\n\npc98_exts=\".2hd .88d .98d .cmd .d88 .d98 .dup .fdi .fdd .hdd .hdi .hdm .nhd .thd .tfd .xdf .zip\"\npc98_fullname=\"NEC PC-9801\"\n\npc_exts=\".bat .com .conf .cue .dosz .exe .ins .ima .img .iso .m3u .m3u8 .sh .vhd .zip\"\npc_fullname=\"PC\"\n\npcengine_exts=\".7z .pce .ccd .chd .cue .zip\"\npcengine_fullname=\"PC Engine\"\npcengine_theme=\"pcengine\"\n\npcfx_exts=\".pce .ccd .cue .iso .chd\"\npcfx_fullname=\"PC-FX\"\n\npico8_exts=\".p8 .png .zip\"\npico8_fullname=\"PICO-8\"\n\npokemini_exts=\".min .zip\"\npokemini_fullname=\"Pokemon Mini\"\n\nports_exts=\".sh\"\nports_fullname=\"Ports\"\nports_platform=\"pc\"\n\nps2_exts=\".iso .img .bin .mdf .z .z2 .bz2 .dump .cso .chd .ima .gz\"\nps2_fullname=\"PlayStation 2\"\n\npsp_exts=\".chd .iso .pbp .cso\"\npsp_fullname=\"PlayStation Portable\"\n\npsx_exts=\".cue .cbn .chd .img .iso .m3u .mdf .pbp .toc .z .znx\"\npsx_fullname=\"PlayStation\"\n\nsamcoupe_exts=\".dsk .mgt .sbt .sad\"\nsamcoupe_fullname=\"SAM Coupe\"\n\nsaturn_exts=\".chd .cue .m3u .mdf .zip\"\nsaturn_fullname=\"Sega Saturn\"\n\nscummvm_exts=\".sh .svm\"\nscummvm_fullname=\"ScummVM\"\n\nsega32x_exts=\".7z .32x .smd .bin .md .zip\"\nsega32x_fullname=\"Sega 32X\"\n\nsegacd_exts=\".iso .cue .chd .m3u\"\nsegacd_fullname=\"Mega CD\"\n\nsg-1000_exts=\".7z .sg .bin .zip\"\nsg-1000_fullname=\"Sega SG-1000\"\n\nsnes_exts=\".7z .bin .bs .smc .sfc .fig .swc .mgd .zip\"\nsnes_fullname=\"Super Nintendo\"\n\nsolarus_exts=\".solarus .zip\"\nsolarus_fullname=\"Solarus Engine\"\n\nti99_exts=\".ctg\"\nti99_fullname=\"TI99\"\n\ntic80_exts=\".tic .zip\"\ntic80_fullname=\"TIC-80\"\n\ntrs-80_exts=\".dsk\"\ntrs-80_fullname=\"trs-80\"\n\nvectrex_exts=\".7z .vec .gam .bin .zip\"\nvectrex_fullname=\"Vectrex\"\n\nvideopac_exts=\".7z .bin .zip\"\nvideopac_fullname=\"Videopac\"\n\nvirtualboy_exts=\".7z .vb .zip\"\nvirtualboy_fullname=\"Virtual Boy\"\n\nwii_exts=\".ciso .gcm .gcz .iso .rvz .wad .wbfs .m3u\"\nwii_fullname=\"Nintendo Wii\"\n\nwonderswan_exts=\".7z .ws .zip\"\nwonderswan_fullname=\"Wonderswan\"\n\nwonderswancolor_exts=\".7z .wsc .zip\"\nwonderswancolor_fullname=\"Wonderswan Color\"\n\nx1_exts=\".dx1 .zip .2d .2hd .tfd .d88 .88d .hdm .xdf .dup .cmd\"\nx1_fullname=\"Sharp X1\"\n\nx68000_exts=\".dim .hdf .hdm .2hd .d88 .m3u .xdf\"\nx68000_fullname=\"X68000\"\n\nzmachine_exts=\".dat .zip .z1 .z2 .z3 .z4 .z5 .z6 .z7 .z8\"\nzmachine_fullname=\"Z-machine\"\n\nzx81_exts=\".7z .p .tzx .t81 .zip\"\nzx81_fullname=\"ZX81\"\n\nzxspectrum_exts=\".7z .sh .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip .rzx\"\nzxspectrum_fullname=\"ZX Spectrum\"\n"
  },
  {
    "path": "retropie_packages.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n__version=\"4.8.11\"\n\n[[ \"$__debug\" -eq 1 ]] && set -x\n\n# main retropie install location\nrootdir=\"/opt/retropie\"\n\n# if no user is specified\nif [[ -z \"$__user\" ]]; then\n    # get the calling user from sudo env\n    __user=\"$SUDO_USER\"\n    # if not called from sudo get the current user\n    [[ -z \"$__user\" ]] && __user=\"$(id -un)\"\nfi\n\n# check if the user exists\nif [[ -z \"$(getent passwd \"$__user\")\" ]]; then\n    echo \"User $__user does not exist.\"\n    exit 1\nfi\n\n# if no group is specified get the users primary group\nif [[ -z \"$__group\" ]]; then\n    __group=\"$(id -gn \"$__user\")\"\nfi\n\n# check if the group exists\nif [[ -z \"$(getent group \"$__group\")\" ]]; then\n    echo \"Group $__group does not exist.\"\n    exit 1\nfi\n\n# backwards compatibility\nuser=\"$__user\"\n\nhome=\"$(eval echo ~$__user)\"\ndatadir=\"$home/RetroPie\"\nbiosdir=\"$datadir/BIOS\"\nromdir=\"$datadir/roms\"\nemudir=\"$rootdir/emulators\"\nconfigdir=\"$rootdir/configs\"\n\nscriptdir=\"$(dirname \"$0\")\"\nscriptdir=\"$(cd \"$scriptdir\" && pwd)\"\n\n__logdir=\"$scriptdir/logs\"\n__tmpdir=\"$scriptdir/tmp\"\n__builddir=\"$__tmpdir/build\"\n__swapdir=\"$__tmpdir\"\n\n# check, if sudo is used\nif [[ \"$(id -u)\" -ne 0 ]]; then\n    echo \"Script must be run under sudo from the user you want to install for. Try 'sudo $0'\"\n    exit 1\nfi\n\n__backtitle=\"retropie.org.uk - RetroPie Setup. Installation folder: $rootdir for user $__user\"\n\nsource \"$scriptdir/scriptmodules/system.sh\"\nsource \"$scriptdir/scriptmodules/helpers.sh\"\nsource \"$scriptdir/scriptmodules/inifuncs.sh\"\nsource \"$scriptdir/scriptmodules/packages.sh\"\n\nsetup_env\n\nrp_registerAllModules\n\nensureFBMode 320 240\n\nrp_ret=0\nif [[ $# -gt 0 ]]; then\n    setupDirectories\n    rp_callModule \"$@\"\n    rp_ret=$?\nelse\n    rp_printUsageinfo\nfi\n\nif [[ \"${#__ERRMSGS[@]}\" -gt 0 ]]; then\n    # override return code if ERRMSGS is set - eg in the case of calling basic_install from setup\n    # we won't get the return code, as we don't handle return codes when calling non packaging functions\n    # as it would require all modules functions to handle errors differently, and make things more complicated\n    [[ \"$rp_ret\" -eq 0 ]] && rp_ret=1\n    printMsgs \"console\" \"Errors:\\n${__ERRMSGS[@]}\"\nfi\n\nif [[ \"${#__INFMSGS[@]}\" -gt 0 ]]; then\n    printMsgs \"console\" \"Info:\\n${__INFMSGS[@]}\"\nfi\n\nexit $rp_ret\n"
  },
  {
    "path": "retropie_setup.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nscriptdir=\"$(dirname \"$0\")\"\nscriptdir=\"$(cd \"$scriptdir\" && pwd)\"\n\n\"$scriptdir/retropie_packages.sh\" setup gui\n\n"
  },
  {
    "path": "scriptmodules/admin/apidocs.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"apidocs\"\nrp_module_desc=\"Generate developer documentation\"\nrp_module_section=\"\"\n\nfunction depends_apidocs() {\n    getDepends doxygen graphviz\n}\n\nfunction sources_apidocs() {\n    gitPullOrClone \"$md_build\" https://github.com/Anvil/bash-doxygen.git\n}\n\nfunction build_apidocs() {\n    local config=\"Doxyfile\"\n    rm -f \"$config\"\n    doxygen -g \"$config\" >/dev/null\n\n    iniConfig \" = \" '' \"$config\"\n\n    iniSet \"PROJECT_NAME\" \"RetroPie-Setup\"\n    iniSet \"PROJECT_NUMBER\" \"$__version\"\n\n    iniSet \"EXTENSION_MAPPING\" \"sh=C\"\n    iniSet \"QUIET\" \"YES\"\n    iniSet \"WARN_IF_DOC_ERROR\" \"NO\"\n    iniSet \"INPUT\" \"$scriptdir\"\n    iniSet \"EXCLUDE_PATTERNS\" \"*/tmp/*\"\n    iniSet \"INPUT_FILTER\" \"\\\"sed -n -f $md_build/doxygen-bash.sed -- \\\"\"\n    iniSet \"RECURSIVE\" \"YES\"\n\n    # unable to use iniSet for latest doxygen \"multi line\" FILE_PATTERNS default\n    echo \"FILE_PATTERNS = *.sh\" >>\"$config\"\n\n    doxygen \"$config\"\n}\n\nfunction install_apidocs() {\n    rsync -a --delete \"$md_build/html/\" \"$__tmpdir/apidocs/\"\n    chown -R \"$__user\":\"$__group\" \"$__tmpdir/apidocs\"\n}\n\nfunction upload_apidocs() {\n    adminRsync \"$__tmpdir/apidocs/\" \"api/\" --delete\n}\n"
  },
  {
    "path": "scriptmodules/admin/builder.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"builder\"\nrp_module_desc=\"Create binary archives for distribution\"\nrp_module_section=\"\"\n\nfunction depends_builder() {\n    getDepends rsync\n}\n\nfunction module_builder() {\n    local ids=($@)\n\n    # set log directories\n    local log_dir_ok=\"$__tmpdir/build_logs/$__os_binaries/ok/$__platform\"\n    local log_dir_fail=\"$__tmpdir/build_logs/$__os_binaries/fail/$__platform\"\n\n    # create the log directories\n    mkdir -p \"$log_dir_ok\" \"$log_dir_fail\"\n\n    local id\n    for id in \"${ids[@]}\"; do\n        printMsgs \"console\" \"Checking module $id ...\"\n        # don't build binaries for modules with flag nobin\n        # eg scraper which fails as go1.8 doesn't work under qemu\n        if hasFlag \"${__mod_info[$id/flags]}\" \"nobin\"; then\n            printMsgs \"console\" \"Module has 'nobin' flag set, so not building.\"\n            continue\n        fi\n\n        # skip modules that are not enabled for the target system\n        if [[ \"${__mod_info[$id/enabled]}\" -ne 1 ]]; then\n            printMsgs \"console\" \"Module is disabled for this platform ($__platform).\"\n            continue\n        fi\n\n        # if the module has no install_ function skip to the next module\n        if ! fnExists \"install_${id}\"; then\n            printMsgs \"console\" \"Module has no install_${id} function so cannot be pre-built.\"\n            continue\n        fi\n\n        # if there is no newer version, skip to the next module. Returns 1 when update is not required,\n        # but can also return 2, to mean \"unknown\" in which case we should do an update. Modules like sdl2\n        # will return 2 as they are handled differently, and don't use the package update mechanisms.\n        rp_hasNewerModule \"$id\" \"source\"\n        if [[ \"$?\" -eq 1 ]]; then\n            printMsgs \"console\" \"No update was found.\"\n            continue\n        else\n            printMsgs \"console\" \"Update found.\"\n        fi\n\n        # delete previous log if present\n        rm -f \"$log_dir_ok/$id.log\"\n\n        # build, install and create binary archive.\n        # initial clean in case anything was in the build folder when calling\n        local failed=0\n        local mode\n        for mode in clean depends sources build install create_bin clean remove \"depends remove\"; do\n            # don't try and create binary archives for modules with an install_bin such as sdl1/sdl2\n            if [[ \"$mode\" == \"create_bin\" ]] && fnExists \"install_bin_${id}\"; then\n                continue\n            fi\n            # call the module function, logging the output.\n            rp_callModule \"$id\" $mode 2>&1 | tee -a \"$log_dir_ok/$id.log\"\n\n            # if the module function returns an error mark as failed and continue to next module\n            if [[ ${PIPESTATUS[0]} -ne 0 ]]; then\n                failed=1\n                break\n            fi\n        done\n\n        if [[ \"$failed\" -eq 0 ]]; then\n            # if the build is successful, remove any previous fail log\n            rm -f \"$log_dir_fail/$id.log\"\n        else\n            # otherwise, the build failed or a module wasn't available so move the module output to a fail log\n            mv \"$log_dir_ok/$id.log\" \"$log_dir_fail/$id.log\"\n        fi\n    done\n    return 0\n}\n\nfunction section_builder() {\n    module_builder $(rp_getSectionIds $1) || return 1\n}\n\nfunction upload_builder() {\n    adminRsync \"$__tmpdir/archives/\" \"files/binaries/\"\n}\n\nfunction clean_archives_builder() {\n    rm -rfv \"$__tmpdir/archives\"\n}\n\nfunction chroot_build_builder() {\n    rp_callModule image depends\n    mkdir -p \"$md_build\"\n\n    # get current host ip for the distcc in the emulated chroot to connect to\n    local ip=\"$(getIPAddress)\"\n\n    local dist\n    local dists=\"$__builder_dists\"\n    [[ -z \"$dists\" ]] && return 1\n\n    local platform\n    local platforms=\"$__builder_platforms\"\n\n    for dist in $dists; do\n        [[ -z \"$platforms\" ]] && platforms=\"$(_get_info_image \"$dist\" \"platforms\")\"\n        [[ -z \"$platforms\" ]] && fatalError \"Unable to get platforms information for $dist\"\n\n        local chroot_dir=\"$md_build/$dist\"\n        local chroot_rps_dir=\"$chroot_dir/home/pi/RetroPie-Setup\"\n\n        local dist_name=\"$(_get_info_image \"$dist\" \"name\")\"\n        [[ -z \"$dist_name\" ]] && fatalError \"Unable to get name information for $dist\"\n        local archive_dir=\"tmp/archives/$dist_name\"\n\n        # set the host and chroot build_log locations\n        local chroot_build_logs=\"$chroot_rps_dir/tmp/build_logs\"\n        local host_build_logs=\"$scriptdir/tmp/build_logs\"\n\n        local distcc_hosts=\"$__builder_distcc_hosts\"\n\n        local use_ccache=\"$__builder_use_ccache\"\n\n        local makeflags=\"$__builder_makeflags\"\n        [[ -z \"$makeflags\" ]] && makeflags=\"-j$(nproc)\"\n        [[ ! -d \"$chroot_dir\" ]] && rp_callModule image create_chroot \"$dist\" \"$chroot_dir\"\n\n\n        if [[ ! -d \"$chroot_rps_dir\" ]]; then\n            gpg --export-secret-keys \"$__gpg_signing_key\" >\"$chroot_dir/retropie.key\"\n            rp_callModule image chroot \"$chroot_dir\" bash -c \"\n                sudo gpg --import /retropie.key\n                sudo rm /retropie.key\n                sudo apt-get update; sudo apt-get install -y git\n                cd\n                git clone https://github.com/RetroPie/RetroPie-Setup.git\n                \"\n            # copy existing packages from host if building in a clean chroot to avoid rebuilding everything\n            mkdir -p \"$scriptdir/$archive_dir\" \"$chroot_rps_dir/$archive_dir\"\n            rsync -av \"$scriptdir/$archive_dir/\" \"$chroot_rps_dir/$archive_dir/\"\n            # copy any previous build logs back to the chroot\n            mkdir -p \"$host_build_logs/$dist_name\" \"$chroot_build_logs/$dist_name\"\n            rsync -av --delete \"$host_build_logs/$dist_name/\" \"$chroot_build_logs/$dist_name/\"\n        else\n            rp_callModule image chroot \"$chroot_dir\" bash -c \"\n                cd ~/RetroPie-Setup\n                git checkout master\n                git pull\n                if git remote | grep -q builder; then\n                    git branch -D builder-branch\n                    git remote remove builder\n                fi\n                \"\n        fi\n\n        # if we have a __builder_repo and __builder_branch set, check out the branch and use that\n        if [[ -n \"$__builder_repo\" && \"$__builder_branch\" ]]; then\n            rp_callModule image chroot \"$chroot_dir\" bash -c \"\n                cd ~/RetroPie-Setup\n                git remote add builder $__builder_repo\n                git fetch -q builder\n                git checkout builder/$__builder_branch -b builder-branch\n                \"\n        fi\n\n        for platform in $platforms; do\n            rp_callModule image chroot \"$chroot_dir\" \\\n                sudo \\\n                __use_ccache=\"$use_ccache\" \\\n                __makeflags=\"$makeflags\" \\\n                DISTCC_HOSTS=\"$distcc_hosts\" \\\n                __platform=\"$platform\" \\\n                __has_binaries=\"$__chroot_has_binaries\" \\\n                /home/pi/RetroPie-Setup/retropie_packages.sh builder \"$@\"\n        done\n\n        rsync -av \"$chroot_rps_dir/$archive_dir/\" \"$scriptdir/$archive_dir/\"\n\n        # sync the build_logs from the chroot to the host system - note: $dist_name should be the same as $__os_binaries\n        rsync -av --delete \"$chroot_build_logs/$dist_name/\" \"$host_build_logs/$dist_name/\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/admin/crosscomp/asan_limits.diff",
    "content": "# fixes gcc/libsanitizer/asan/asan_linux.cpp:217:21: error: ‘PATH_MAX’ was not declared in this scope\n--- a/gcc/libsanitizer/asan/asan_linux.cpp\n+++ b/gcc/libsanitizer/asan/asan_linux.cpp\n@@ -31,7 +31,7 @@\n #include <sys/types.h>\n #include <dlfcn.h>\n #include <fcntl.h>\n-#include <limits.h>\n+#include <linux/limits.h>\n #include <pthread.h>\n #include <stdio.h>\n #include <unistd.h>\n"
  },
  {
    "path": "scriptmodules/admin/crosscomp/bullseye.diff",
    "content": "# see https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=49348beafe9ba150c9bd48595b3f372299bddbb0\n\ndiff --git a/math/Makefile b/math/Makefile\nindex 84a8b94c74..0a5a40430e 100644\n--- a/glibc/math/Makefile\n+++ b/glibc/math/Makefile\n@@ -644,6 +644,128 @@\n # We won't compile the `long double' code at all.  Tell the `double' code\n # to define aliases for the `FUNCl' names.\n math-CPPFLAGS += -DNO_LONG_DOUBLE\n+# GCC 10 diagnoses aliases with types conflicting with built-in\n+# functions.\n+CFLAGS-w_acos.c += -fno-builtin-acosl\n+CFLAGS-w_acosh.c += -fno-builtin-acoshl\n+CFLAGS-w_asin.c += -fno-builtin-asinl\n+CFLAGS-s_asinh.c += -fno-builtin-asinhl\n+CFLAGS-s_atan.c += -fno-builtin-atanl\n+CFLAGS-w_atan2.c += -fno-builtin-atan2l\n+CFLAGS-w_atanh.c += -fno-builtin-atanhl\n+CFLAGS-s_cabs.c += -fno-builtin-cabsl\n+CFLAGS-s_cacos.c += -fno-builtin-cacosl\n+CFLAGS-s_cacosh.c += -fno-builtin-cacoshl\n+CFLAGS-s_canonicalize.c += -fno-builtin-canonicalizel\n+CFLAGS-s_carg.c += -fno-builtin-cargl\n+CFLAGS-s_casin.c += -fno-builtin-casinl\n+CFLAGS-s_casinh.c += -fno-builtin-casinhl\n+CFLAGS-s_catan.c += -fno-builtin-catanl\n+CFLAGS-s_catanh.c += -fno-builtin-catanhl\n+CFLAGS-s_cbrt.c += -fno-builtin-cbrtl\n+CFLAGS-s_ccos.c += -fno-builtin-ccosl\n+CFLAGS-s_ccosh.c += -fno-builtin-ccoshl\n+CFLAGS-s_ceil.c += -fno-builtin-ceill\n+CFLAGS-s_cexp.c += -fno-builtin-cexpl\n+CFLAGS-s_cimag.c += -fno-builtin-cimagl\n+CFLAGS-s_clog.c += -fno-builtin-clogl\n+CFLAGS-s_clog10.c += -fno-builtin-clog10l\n+CFLAGS-s_conj.c += -fno-builtin-conjl\n+CFLAGS-s_copysign.c += -fno-builtin-copysignl\n+CFLAGS-s_cos.c += -fno-builtin-cosl\n+CFLAGS-w_cosh.c += -fno-builtin-coshl\n+CFLAGS-s_cpow.c += -fno-builtin-cpowl\n+CFLAGS-s_cproj.c += -fno-builtin-cprojl\n+CFLAGS-s_creal.c += -fno-builtin-creall\n+CFLAGS-s_csin.c += -fno-builtin-csinl\n+CFLAGS-s_csinh.c += -fno-builtin-csinhl\n+CFLAGS-s_csqrt.c += -fno-builtin-csqrtl\n+CFLAGS-s_ctan.c += -fno-builtin-ctanl\n+CFLAGS-s_ctanh.c += -fno-builtin-ctanhl\n+CFLAGS-s_dadd.c += -fno-builtin-daddl\n+CFLAGS-s_ddiv.c += -fno-builtin-ddivl\n+CFLAGS-s_dmul.c += -fno-builtin-dmull\n+CFLAGS-s_dsub.c += -fno-builtin-dsubl\n+CFLAGS-s_erf.c += -fno-builtin-erfl\n+CFLAGS-s_erfc.c += -fno-builtin-erfcl\n+CFLAGS-e_exp.c += -fno-builtin-expl\n+CFLAGS-w_exp10.c += -fno-builtin-exp10l\n+CFLAGS-e_exp2.c += -fno-builtin-exp2l\n+CFLAGS-s_expm1.c += -fno-builtin-expm1l\n+CFLAGS-s_fabs.c += -fno-builtin-fabsl\n+CFLAGS-s_fadd.c += -fno-builtin-faddl\n+CFLAGS-s_fdim.c += -fno-builtin-fdiml\n+CFLAGS-s_fdiv.c += -fno-builtin-fdivl\n+CFLAGS-s_finite.c += -fno-builtin-finitel\n+CFLAGS-s_floor.c += -fno-builtin-floorl\n+CFLAGS-s_fma.c += -fno-builtin-fmal\n+CFLAGS-s_fmax.c += -fno-builtin-fmaxl\n+CFLAGS-s_fmaxmag.c += -fno-builtin-fmaxmagl\n+CFLAGS-s_fmin.c += -fno-builtin-fminl\n+CFLAGS-s_fminmag.c += -fno-builtin-fminmagl\n+CFLAGS-w_fmod.c += -fno-builtin-fmodl\n+CFLAGS-s_fmul.c += -fno-builtin-fmull\n+CFLAGS-s_frexp.c += -fno-builtin-frexpl\n+CFLAGS-s_fromfp.c += -fno-builtin-fromfpl\n+CFLAGS-s_fromfpx.c += -fno-builtin-fromfpxl\n+CFLAGS-s_fsub.c += -fno-builtin-fsubl\n+CFLAGS-s_gamma.c += -fno-builtin-gammal\n+CFLAGS-s_getpayload.c += -fno-builtin-getpayloadl\n+CFLAGS-w_hypot.c += -fno-builtin-hypotl\n+CFLAGS-w_ilogb.c += -fno-builtin-ilogbl\n+CFLAGS-s_isinf.c += -fno-builtin-isinfl\n+CFLAGS-s_isnan.c += -fno-builtin-isnanl\n+CFLAGS-w_j0.c += -fno-builtin-j0l\n+CFLAGS-w_j1.c += -fno-builtin-j1l\n+CFLAGS-w_jn.c += -fno-builtin-jnl\n+CFLAGS-s_ldexp.c += -fno-builtin-ldexpl\n+CFLAGS-w_lgamma.c += -fno-builtin-lgammal\n+CFLAGS-w_lgamma_r.c += -fno-builtin-lgammal_r\n+CFLAGS-w_llogb.c += -fno-builtin-llogbl\n+CFLAGS-s_llrint.c += -fno-builtin-llrintl\n+CFLAGS-s_llround.c += -fno-builtin-llroundl\n+CFLAGS-e_log.c += -fno-builtin-logl\n+CFLAGS-w_log10.c += -fno-builtin-log10l\n+CFLAGS-w_log1p.c += -fno-builtin-log1pl\n+CFLAGS-e_log2.c += -fno-builtin-log2l\n+CFLAGS-s_logb.c += -fno-builtin-logbl\n+CFLAGS-s_lrint.c += -fno-builtin-lrintl\n+CFLAGS-s_lround.c += -fno-builtin-lroundl\n+CFLAGS-s_modf.c += -fno-builtin-modfl\n+CFLAGS-s_nan.c += -fno-builtin-nanl\n+CFLAGS-s_nearbyint.c += -fno-builtin-nearbyintl\n+CFLAGS-s_nextafter.c += -fno-builtin-nextafterl\n+CFLAGS-s_nextdown.c += -fno-builtin-nextdownl\n+CFLAGS-s_nexttoward.c += -fno-builtin-nexttoward -fno-builtin-nexttowardl\n+CFLAGS-s_nexttowardf.c += -fno-builtin-nexttowardf\n+CFLAGS-s_nextup.c += -fno-builtin-nextupl\n+CFLAGS-e_pow.c += -fno-builtin-powl\n+CFLAGS-w_remainder.c += -fno-builtin-remainderl -fno-builtin-dreml\n+CFLAGS-s_remquo.c += -fno-builtin-remquol\n+CFLAGS-s_rint.c += -fno-builtin-rintl\n+CFLAGS-s_round.c += -fno-builtin-roundl\n+CFLAGS-s_roundeven.c += -fno-builtin-roundevenl\n+CFLAGS-w_scalb.c += -fno-builtin-scalbl\n+CFLAGS-w_scalbln.c += -fno-builtin-scalblnl\n+CFLAGS-s_scalbn.c += -fno-builtin-scalbnl\n+CFLAGS-s_setpayload.c += -fno-builtin-setpayloadl\n+CFLAGS-s_setpayloadsig.c += -fno-builtin-setpayloadsigl\n+CFLAGS-s_significand.c += -fno-builtin-significandl\n+CFLAGS-s_sin.c += -fno-builtin-sinl\n+CFLAGS-s_sincos.c += -fno-builtin-sincosl\n+CFLAGS-w_sinh.c += -fno-builtin-sinhl\n+CFLAGS-w_sqrt.c += -fno-builtin-sqrtl\n+CFLAGS-s_tan.c += -fno-builtin-tanl\n+CFLAGS-s_tanh.c += -fno-builtin-tanhl\n+CFLAGS-w_tgamma.c += -fno-builtin-tgammal\n+CFLAGS-s_totalorder.c += -fno-builtin-totalorderl\n+CFLAGS-s_totalordermag.c += -fno-builtin-totalordermagl\n+CFLAGS-s_trunc.c += -fno-builtin-truncl\n+CFLAGS-s_ufromfp.c += -fno-builtin-ufromfpl\n+CFLAGS-s_ufromfpx.c += -fno-builtin-ufromfpxl\n+CFLAGS-s_y0.c += -fno-builtin-y0l\n+CFLAGS-s_y1.c += -fno-builtin-y1l\n+CFLAGS-s_yn.c += -fno-builtin-ynl\n endif\n \n # These files quiet sNaNs in a way that is optimized away without\n\n"
  },
  {
    "path": "scriptmodules/admin/crosscomp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"crosscomp\"\nrp_module_desc=\"Create am arm cross compiler env - based on examples from http://preshing.com/20141119/how-to-build-a-gcc-cross-compiler\"\nrp_module_help=\"Can be used via distcc to build RetroPie binaries\"\nrp_module_section=\"\"\nrp_module_flags=\"!arm\"\n\nfunction _default_dist_crosscomp() {\n    echo \"buster\"\n}\n\nfunction depends_crosscomp() {\n    getDepends distcc\n}\n\nfunction sources_crosscomp() {\n    local dist=\"$1\"\n    [[ -z \"$dist\" ]] && return\n\n    declare -A pkgs\n    case \"$dist\" in\n        stretch)\n            pkgs=(\n                [binutils]=2.28\n                [gcc]=6.4.0\n                [glibc]=2.24\n                [gmp]=6.1.2\n                [kernel]=4.9.80\n                [mpfr]=3.1.5\n                [mpc]=1.0.3\n            )\n            ;;\n        buster)\n            pkgs=(\n                [binutils]=2.31.1\n                [gcc]=8.3.0\n                [glibc]=2.28\n                [gmp]=6.1.2\n                [kernel]=4.19.50\n                [mpfr]=4.0.2\n                [mpc]=1.1.0\n            )\n            ;;\n        bullseye)\n            pkgs=(\n                [binutils]=2.35.2\n                [gcc]=10.2.0\n                [glibc]=2.31\n                [gmp]=6.2.1\n                [kernel]=5.15.61\n                [mpfr]=4.1.0\n                [mpc]=1.2.0\n            )\n            ;;\n        bookworm)\n            pkgs=(\n                [binutils]=2.40\n                [gcc]=12.2.0\n                [glibc]=2.36\n                [gmp]=6.2.1\n                [kernel]=6.1\n                [mpfr]=4.2.0\n                [mpc]=1.3.1\n            )\n            ;;\n        *)\n            md_ret_errors+=(\"Unsupported distribution $dist\")\n            return 1\n            ;;\n    esac\n\n    downloadAndExtract \"https://ftp.gnu.org/gnu/binutils/binutils-${pkgs[binutils]}.tar.gz\" binutils --strip-components 1\n\n    downloadAndExtract \"https://ftp.gnu.org/gnu/mpfr/mpfr-${pkgs[mpfr]}.tar.gz\" mpfr --strip-components 1\n    downloadAndExtract \"https://ftp.gnu.org/gnu/gmp/gmp-${pkgs[gmp]}.tar.bz2\" gmp --strip-components 1\n    downloadAndExtract \"https://ftp.gnu.org/gnu/mpc/mpc-${pkgs[mpc]}.tar.gz\" mpc --strip-components 1\n\n    downloadAndExtract \"https://ftp.gnu.org/gnu/glibc/glibc-${pkgs[glibc]}.tar.bz2\" glibc --strip-components 1\n    downloadAndExtract \"https://ftp.gnu.org/gnu/gcc/gcc-${pkgs[gcc]}/gcc-${pkgs[gcc]}.tar.gz\" gcc --strip-components 1\n\n    downloadAndExtract \"https://www.kernel.org/pub/linux/kernel/v${pkgs[kernel]:0:1}.x/linux-${pkgs[kernel]}.tar.gz\" linux --strip-components 1\n\n    local pkg\n    for pkg in gmp mpc mpfr; do\n        ln -sf \"../$pkg\" \"gcc/$pkg\"\n    done\n\n    # apply glibc patch required when compiling with GCC 10+\n    # see https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=49348beafe9ba150c9bd48595b3f372299bddbb0\n    if [[ \"$dist\" == \"bullseye\" ]]; then\n        applyPatch \"$md_data/bullseye.diff\"\n    fi\n    # fix incorrect limits.h include.\n    if compareVersions \"${pkgs[gcc]}\" ge 10; then\n        applyPatch \"$md_data/asan_limits.diff\"\n    fi\n\n}\n\nfunction build_crosscomp() {\n    local dist=\"$1\"\n    [[ -z \"$dist\" ]] && return\n\n    # remove old build directories\n    rm -rf \"$md_build/build-\"*\n\n    local params=(--with-arch=armv6 --with-fpu=vfp --with-float=hard)\n    local target=arm-linux-gnueabihf\n    local dest=\"$md_inst/$dist\"\n\n    local old_path=\"$PATH\"\n    export PATH=\"$dest/bin:$old_path\"\n\n    export ASFLAGS=\"\"\n    export CFLAGS=\"-O2\"\n    export CXXFLAGS=\"-O2\"\n\n    # binutils\n    printHeading \"Building binutils\"\n    mkdir -p build-binutils\n    cd build-binutils\n    ../binutils/configure --prefix=\"$dest\" --target=\"$target\" \"${params[@]}\"\n    make\n    make install\n    cd ..\n\n    # kernel headers\n    printHeading \"Installing kernel headers\"\n    cd linux\n    make ARCH=arm INSTALL_HDR_PATH=\"$dest/$target\" headers_install\n    cd ..\n\n    # gcc\n    printHeading \"Building gcc\"\n    mkdir -p build-gcc\n    cd build-gcc\n    ../gcc/configure --prefix=\"$dest\" --target=\"$target\" --enable-languages=c,c++ --disable-multilib --disable-werror \"${params[@]}\" \n    make all-gcc\n    make install-gcc\n    cd ..\n\n    # glibc\n    printHeading \"Building glibc\"\n    mkdir -p build-glibc\n    cd build-glibc\n    ../glibc/configure --prefix=\"$dest/$target\" --build=\"$MACHTYPE\" --host=\"$target\" --target=\"$target\" --with-headers=\"$dest/$target/include\" libc_cv_forced_unwind=yes\n    make install-bootstrap-headers=yes install-headers\n    make csu/subdir_lib\n    install csu/crt1.o csu/crti.o csu/crtn.o \"$dest/$target/lib\"\n\n    \"$target-gcc\" -nostdlib -nostartfiles -shared -x c /dev/null -o \"$dest/$target/lib/libc.so\"\n    touch \"$dest/$target/include/gnu/stubs.h\"\n    cd ..\n\n    # compiler support library\n    printHeading \"Building libgcc\"\n    cd build-gcc\n    make all-target-libgcc\n    make install-target-libgcc\n    cd ..\n\n    # standard c library\n    printHeading \"Building glibc (2)\"\n    cd build-glibc\n    make\n    make install\n    cd ..\n\n    # standard c++ library\n    printHeading \"Building libcpp\"\n    cd build-gcc\n    make all\n    make install\n    cd ..\n\n    export PATH=\"$old_path\"\n    export ASFLAGS=\"$__asflags\"\n    export CFLAGS=\"$__cflags\"\n    export CXXFLAGS=\"$__cxxflags\"\n}\n\nfunction setup_crosscomp() {\n    local dist=\"$1\"\n    [[ -z \"$dist\" ]] && dist=\"$(_default_dist_crosscomp)\"\n    \n    if rp_callModule crosscomp sources \"$dist\"; then\n        rp_callModule crosscomp build \"$dist\"\n        rp_callModule crosscomp clean\n    fi\n}\n\nfunction setup_all_crosscomp() {\n    local dist\n    for dist in stretch buster bullseye; do\n        setup_crosscomp \"$dist\"\n    done\n}\n\nfunction configure_distcc_crosscomp() {\n    local dist=\"$1\"\n    [[ -z \"$dist\" ]] && return 1\n\n    local port=\"$2\"\n    [[ -z \"$port\" ]] && return 1\n\n    local bin_dir=\"$md_inst/$dist/bin\"\n\n    # add additional symlinks for cc/gcc/c++/g++\n    local name\n    for name in cc gcc; do\n        ln -sfv \"arm-linux-gnueabihf-gcc\" \"$bin_dir/$name\"\n    done\n\n    for name in c++ g++; do\n        ln -sfv \"arm-linux-gnueabihf-g++\" \"$bin_dir/$name\"\n    done\n\n    local initd_script=\"/etc/init.d/distcc-$dist\"\n\n    # duplicate distcc init.d script\n    cp /etc/init.d/distcc \"$initd_script\"\n\n    # add dist to NAME in new init.d\n    sed -i \"s/NAME=distccd/NAME=distccd-$dist/\" \"$initd_script\"\n\n    # add custom port to new init.d\n    sed -i \"s/--daemon\\\"/--daemon --port $port\\\"/\" \"$initd_script\"\n\n    # add the $dist cross compiler bin path to new init.d\n    local replace=\"PATH=$bin_dir:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin\"\n    # if the PATH line exists, replace it (older distcc init.d script)\n    if grep -q \"PATH=\" \"$initd_script\"; then\n        sed -i \"s#^PATH=.*#$replace#\" \"$initd_script\"\n    # otherwise, insert it before the DAEMON= line (newer distcc init.d script)\n    else\n        sed -i \"/^DAEMON=.*/i $replace\" \"$initd_script\"\n    fi\n\n    # create log file\n    local log=\"/var/log/distccd-$dist.log\"\n    touch \"$log\"\n    chown distccd:nogroup \"$log\"\n\n    # restart distcc\n    systemctl daemon-reload\n    service distcc restart\n}\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-bookworm-64.ini",
    "content": "name=\"bookworm-64\"\nversion=\"12\"\nurl=\"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\"\nformat=\"xz\"\nplatforms=\"rpi3 rpi4 rpi5\"\nfile_rpi3=\"rpi3\"\ntitle_rpi3=\"Raspberry Pi 3\"\nfile_rpi4=\"rpi4\"\ntitle_rpi4=\"Raspberry Pi 4\"\nfile_rpi5=\"rpi5\"\ntitle_rpi5=\"Raspberry Pi 5\"\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-bookworm.ini",
    "content": "name=\"bookworm\"\nversion=\"12\"\nurl=\"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\"\nformat=\"xz\"\nplatforms=\"rpi1 rpi2 rpi3 rpi4 rpi5\"\nfile_rpi1=\"rpi1_zero\"\ntitle_rpi1=\"RPI 1/Zero\"\nfile_rpi2=\"rpi2\"\ntitle_rpi2=\"RPI 2\"\nfile_rpi3=\"rpi3_zero2w\"\ntitle_rpi3=\"RPI 3/Zero 2 W\"\nfile_rpi4=\"rpi4_400\"\ntitle_rpi4=\"RPI 4/400\"\nfile_rpi5=\"rpi5\"\ntitle_rpi5=\"RPI 5\"\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-bullseye.ini",
    "content": "name=\"bullseye\"\nversion=\"11\"\nurl=\"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\"\nformat=\"xz\"\nplatforms=\"rpi1 rpi2 rpi3 rpi4\"\nfile_rpi1=\"rpi1_zero\"\ntitle_rpi1=\"RPI 1/Zero\"\nfile_rpi2=\"rpi2\"\ntitle_rpi2=\"RPI 2\"\nfile_rpi3=\"rpi3_zero2w\"\ntitle_rpi3=\"RPI 3/Zero 2 W\"\nfile_rpi4=\"rpi4_400\"\ntitle_rpi4=\"RPI 4/400\"\n\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-buster.ini",
    "content": "name=\"buster\"\nversion=\"10\"\nurl=\"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\"\nformat=\"xz\"\nplatforms=\"rpi1 rpi2 rpi4\"\nfile_rpi1=\"rpi1_zero\"\ntitle_rpi1=\"RPI 1/Zero\"\nfile_rpi2=\"rpi2_3_zero2w\"\ntitle_rpi2=\"RPI 2/3/Zero 2 W\"\nfile_rpi4=\"rpi4_400\"\ntitle_rpi4=\"RPI 4/400\"\n\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-jessie.ini",
    "content": "name=\"jessie\"\nversion=\"8\"\nurl=\"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2017-07-05/2017-07-05-raspbian-jessie-lite.zip\"\nformat=\"zip\"\nplatforms=\"rpi1 rpi2\"\nfile_rpi1=\"rpi1_zero\"\ntitle_rpi1=\"RPI 1/Zero\"\nfile_rpi2=\"rpi2_3\"\ntitle_rpi2=\"RPI 2/3\"\n\n"
  },
  {
    "path": "scriptmodules/admin/image/dists/rpios-stretch.ini",
    "content": "name=\"stretch\"\nversion=\"9\"\nurl=\"https://downloads.raspberrypi.org/raspbian_lite/images/raspbian_lite-2019-04-09/2019-04-08-raspbian-stretch-lite.zip\"\nformat=\"zip\"\nplatforms=\"rpi1 rpi2\"\nfile_rpi1=\"rpi1_zero\"\ntitle_rpi1=\"RPI 1/Zero\"\nfile_rpi2=\"rpi2_3\"\ntitle_rpi2=\"RPI 2/3\"\n\n"
  },
  {
    "path": "scriptmodules/admin/image/template.json",
    "content": "        {\n            \"url\": \"https://github.com/RetroPie/RetroPie-Setup/releases/download/IMG_PATH\",\n            \"extract_size\": IMG_EXTRACT_SIZE,\n            \"extract_sha256\": \"IMG_SHA256\",\n            \"image_download_size\": IMG_DOWNLOAD_SIZE,\n            \"description\": \"Turn your Raspberry Pi into a retro-gaming machine.\",\n            \"icon\": \"https://retropie.org.uk/retropie-logo-40x40.png\",\n            \"name\": \"RetroPie IMG_VERSION (IMG_PLATFORM)\",\n            \"release_date\": \"IMG_DATE\",\n            \"website\": \"https://retropie.org.uk\"\n        }"
  },
  {
    "path": "scriptmodules/admin/image.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"image\"\nrp_module_desc=\"Create/Manage RetroPie images\"\nrp_module_section=\"\"\nrp_module_flags=\"\"\n\nfunction depends_image() {\n    local depends=(kpartx unzip binfmt-support rsync parted squashfs-tools dosfstools e2fsprogs xz-utils)\n    isPlatform \"x86\" && depends+=(qemu-user-binfmt)\n    getDepends \"${depends[@]}\"\n\n    # enable C flag in qemu-aarch64/qemu-arm binfmt_misc override to allow suid binaries in emulated chroot\n    if isPlatform \"x86\"; then\n        local platform\n        for platform in arm aarch64; do\n            local config=\"qemu-$platform.conf\"\n            local src_config=\"/usr/lib/binfmt.d/$config\"\n            local dest_config=\"/etc/binfmt.d/$config\"\n            if [[ ! -f \"$dest_config\" ]]; then\n                printMsgs \"console\" \"Adding C flag to $src_config (overriding in $dest_config)\"\n                sed \"s/$/C/\" \"/usr/lib/binfmt.d/$config\" >\"/etc/binfmt.d/$config\"\n            fi\n        done\n        systemctl restart systemd-binfmt\n    fi\n}\n\nfunction _get_info_image() {\n    local dist=\"$1\"\n    local key=\"$2\"\n    # don't use $md_data so this function can be used directly from builder.sh\n    local ini=\"${__mod_info[image/path]%/*}/image/dists/${dist}.ini\"\n\n    # if the file is found try and extract the value else echo an empty string\n    if [[ -f \"$ini\" ]]; then\n        iniConfig \"=\" \"\\\"\" \"$ini\"\n        iniGet \"$key\"\n        echo \"$ini_value\"\n    else\n        echo \"\"\n    fi\n}\n\nfunction create_chroot_image() {\n    local dist=\"$1\"\n    [[ -z \"$dist\" ]] && return 1\n\n    local chroot=\"$2\"\n    [[ -z \"$chroot\" ]] && chroot=\"$md_build/$dist\"\n\n    mkdir -p \"$md_build\"\n    pushd \"$md_build\"\n\n    mkdir -p \"$chroot\"\n\n    local url=$(_get_info_image \"$dist\" \"url\")\n    [[ -z \"$url\" ]] && fatalError \"Unable to get url information for $dist\"\n\n    local format=$(_get_info_image \"$dist\" \"format\")\n    [[ -z \"$format\" ]] && fatalError \"Unable to get format information for $dist\"\n\n    local base=\"raspbian-${dist}-lite\"\n    local image=\"${dist}.img\"\n    local dest=\"${image}.${format}\"\n    if [[ ! -f \"$image\" ]]; then\n        case \"$format\" in\n            zip)\n                download \"$url\" \"$dest\"\n                unzip -o \"$dest\"\n                mv \"$(unzip -Z -1 \"$dest\")\" \"$image\"\n                rm \"$dest\"\n                ;;\n            xz)\n                download \"$url\" \"$dest\"\n                xz -d -v \"$dest\"\n                ;;\n        esac\n    fi\n\n    # abort if there is no extracted image present\n    [[ ! -f \"$image\" ]] && return 1\n\n    # mount image\n    local partitions=($(kpartx -s -a -v \"$image\" | awk '{ print \"/dev/mapper/\"$3 }'))\n    local part_boot=\"${partitions[0]}\"\n    local part_root=\"${partitions[1]}\"\n\n    # get temporary directory\n    local tmp=\"$(mktemp -d -p \"$md_build\")\"\n\n    # mount root partition\n    mount \"$part_root\" \"$tmp\"\n\n    # get the mount location of the boot partition from etc/fstab\n    local boot_path=\"$(_get_boot_path_image \"$tmp\")\"\n\n    # create the boot partition mountpoint and mount\n    mkdir -p \"$tmp$boot_path\"\n    mount \"$part_boot\" \"$tmp$boot_path\"\n\n    printMsgs \"console\" \"Creating chroot from $image ...\"\n    rsync -aAHX --numeric-ids --delete \"$tmp/\" \"$chroot/\"\n\n    # fix up raspberry pi repos for buster image building (see buster_fix_apt_raspbiantools in raspbiantools.sh scriptmodule)\n    if [[ \"$dist\" == \"rpios-buster\" ]]; then\n        sed -i \"s/raspbian\\.raspberrypi\\.org/legacy.raspbian.org/\" \"$chroot/etc/apt/sources.list\"\n    fi\n\n    umount -l \"$tmp$boot_path\" \"$tmp\"\n    rm -rf \"$tmp\"\n\n    dmsetup remove \"${partitions[@]}\"\n    kpartx -d \"$image\"\n\n    popd\n    return 0\n}\n\nfunction _get_boot_path_image() {\n    local chroot=\"$1\"\n    # extract boot partition mount location from fstab\n    awk '$3==\"vfat\" {print $2}' \"$chroot/etc/fstab\"\n}\n\nfunction install_rp_image() {\n    local platform=\"$1\"\n    if [[ -z \"$platform\" ]]; then\n        printMsgs \"console\" \"Requires a platform (eg rpi3/rpi4)\"\n        return 1\n    fi\n\n    local dist=\"$2\"\n    if [[ -z \"$dist\" ]]; then\n        printMsgs \"Requires a distribution name (eg rpios-buster/rpios-bullseye)\"\n        return 1\n    fi\n\n    local chroot=\"$3\"\n    [[ -z \"$chroot\" ]] && chroot=\"$md_build/$dist\"\n\n    local dist_version=\"$(_get_info_image \"$dist\" \"version\")\"\n    [[ -z \"$dist_version\" ]] && fatalError \"Unable to get version information for $dist\"\n\n    # hostname to retropie\n    echo \"retropie\" >\"$chroot/etc/hostname\"\n    sed -i \"s/raspberrypi/retropie/\" \"$chroot/etc/hosts\"\n\n    local boot_path=\"$(_get_boot_path_image \"$chroot\")\"\n\n    # quieter boot / disable plymouth (as without the splash parameter it\n    # causes all boot messages to be displayed and interferes with people\n    # using tty3 to make the boot even quieter)\n    if ! grep -q consoleblank \"$chroot$boot_path/cmdline.txt\"; then\n        # extra quiet as the raspbian usr/lib/raspi-config/init_resize.sh does\n        # sed -i 's/ quiet init=.*$//' /boot/cmdline.txt so this will remove the last quiet\n        # and the init line but leave ours intact\n        sed -i \"s/quiet/quiet loglevel=3 consoleblank=0 plymouth.enable=0 quiet/\" \"$chroot/boot/cmdline.txt\"\n    fi\n\n    iniConfig \"=\" \"\" \"$chroot$boot_path/config.txt\"\n    # set default GPU mem (videocore only)\n    if [[ \"$dist_version\" -lt 11 && \"$platform\" == rpi[123] ]]; then\n        iniSet \"gpu_mem_256\" 128\n        iniSet \"gpu_mem_512\" 256\n        iniSet \"gpu_mem_1024\" 256\n    fi\n    # set overscan_scale so ES scales to overscan settings.\n    iniSet \"overscan_scale\" 1\n\n    # disable 64bit kernel on 32bit userland OSs (to disable rpi4 defaulting to 64bit kernel)\n    # 64 bit distros end in -64\n    if [[ \"$dist\" != *-64 ]]; then\n        iniSet \"arm_64bit\" 0\n    # otherwise if on 64bit switch to using the 4k page size kernel\n    else\n        iniSet \"kernel\" \"kernel8.img\"\n    fi\n\n    [[ -z \"$__chroot_repo\" ]] && __chroot_repo=\"https://github.com/RetroPie/RetroPie-Setup.git\"\n    [[ -z \"$__chroot_branch\" ]] && __chroot_branch=\"master\"\n\n    # fix up initramfs-tools installation in a chroot (can't find root partition, workaround is to use MODULES=most)\n    local config=\"$chroot/etc/initramfs-tools/initramfs.conf\"\n    if [[ -f \"$config\" ]]; then\n        sed -i \"s/MODULES=dep/MODULES=most/\" \"$config\"\n    fi\n\n    cat > \"$chroot/home/pi/install.sh\" <<_EOF_\n#!/bin/bash\ncd\nif systemctl is-enabled userconfig &>/dev/null; then\n    echo \"pi:raspberry\" | sudo chpasswd\n    sudo systemctl disable userconfig\n    sudo systemctl --quiet enable getty@tty1\nfi\nsudo apt-get update\nsudo apt-get -y install git dialog xmlstarlet joystick\ngit clone -b \"$__chroot_branch\" \"$__chroot_repo\"\ncd RetroPie-Setup\nmodules=(\n    'raspbiantools apt_upgrade'\n    'setup basic_install'\n    'bluetooth depends'\n    'raspbiantools enable_modules'\n    'autostart enable'\n    'usbromservice'\n    'samba depends'\n    'samba install_shares'\n    'splashscreen default'\n    'splashscreen enable'\n    'bashwelcometweak'\n    'xpad'\n)\nfor module in \"\\${modules[@]}\"; do\n    sudo __platform=$platform __nodialog=1 __has_binaries=$__chroot_has_binaries ./retropie_packages.sh \\$module\ndone\n\nsudo rm -rf tmp\nsudo apt-get clean\n_EOF_\n\n    # chroot and run install script\n    rp_callModule image chroot \"$chroot\" bash /home/pi/install.sh\n\n    rm \"$chroot/home/pi/install.sh\"\n\n    # restore initramfs-tools config to default\n    if [[ -f \"$config\" ]]; then\n        sed -i \"s/MODULES=most/MODULES=dep/\" \"$config\"\n    fi\n\n    # remove any ssh host keys that may have been generated during any ssh package upgrades\n    rm -f \"$chroot/etc/ssh/ssh_host\"*\n}\n\nfunction _init_chroot_image() {\n    local chroot=\"$1\"\n    [[ -z \"$chroot\" ]] && return 1\n\n    # unmount on ctrl+c\n    trap \"_trap_chroot_image '$chroot'\" INT\n\n    # mount special filesystems to chroot\n    mkdir -p \"$chroot\"{/dev/pts,/proc,/sys}\n    mount none -t devpts \"$chroot/dev/pts\"\n    mount -t proc /proc \"$chroot/proc\"\n    mount -t sysfs /sys \"$chroot/sys\"\n\n    local nameserver=\"$__nameserver\"\n    [[ -z \"$nameserver\" ]] && nameserver=\"$(nmcli device show | grep IP4.DNS | awk '{print $NF; exit}')\"\n    # so we can resolve inside the chroot\n    echo \"nameserver $nameserver\" >\"$chroot/etc/resolv.conf\"\n\n    # move /etc/ld.so.preload out of the way to avoid warnings\n    if [[ -f \"$chroot/etc/ld.so.preload\" ]]; then\n        mv \"$chroot/etc/ld.so.preload\" \"$chroot/etc/ld.so.preload.bak\"\n    fi\n}\n\nfunction _deinit_chroot_image() {\n    local chroot=\"$1\"\n    [[ -z \"$chroot\" ]] && return 1\n\n    trap \"\" INT\n\n    >\"$chroot/etc/resolv.conf\"\n\n    # restore /etc/ld.so.preload if backup present\n    if [[ -f \"$chroot/etc/ld.so.preload.bak\" ]]; then\n        mv \"$chroot/etc/ld.so.preload.bak\" \"$chroot/etc/ld.so.preload\"\n    fi\n\n    umount -l \"$chroot/proc\" \"$chroot/dev/pts\" \"$chroot/sys\"\n    trap INT\n}\n\nfunction _trap_chroot_image() {\n    _deinit_chroot_image \"$1\"\n    exit\n}\n\nfunction chroot_image() {\n    local chroot=\"$1\"\n    [[ -z \"$chroot\" ]] && return 1\n    shift\n\n    printMsgs \"console\" \"Chrooting to $chroot ...\"\n    _init_chroot_image \"$chroot\"\n    HOME=\"/home/pi\" chroot --userspec 1000:1000 \"$chroot\" \"$@\"\n    _deinit_chroot_image \"$chroot\"\n}\n\nfunction create_image() {\n    local image=\"$1\"\n    [[ -z \"$image\" ]] && return 1\n\n    local chroot=\"$2\"\n    [[ -z \"$chroot\" ]] && chroot=\"$md_build/chroot\"\n\n    local boot_size_mib=\"$3\"\n    # if not specified default the boot size partition to 512MiB\n    [[ -z \"$boot_size_mib\" ]] && boot_size_mib=512\n\n    # get size of files in MiB\n    local chroot_size_mib=$(du -s -m \"$chroot\" 2>/dev/null | cut -f1)\n    # make image size 256MiB larger than contents of chroot and boot partition\n    local image_size_mib=$((boot_size_mib + chroot_size_mib + 256))\n\n    # create image\n    printMsgs \"console\" \"Creating image $image ...\"\n    dd if=/dev/zero of=\"$image\" bs=1M count=\"$image_size_mib\"\n\n    # partition\n    printMsgs \"console\" \"partitioning $image ...\"\n    local boot_start_mib=8\n    local boot_end_mib=$((boot_start_mib + boot_size_mib))\n    parted -s \"$image\" -- \\\n        mklabel msdos \\\n        unit mib \\\n        mkpart primary fat32 $boot_start_mib $boot_end_mib \\\n        mkpart primary $boot_end_mib -1s\n\n    # format\n    printMsgs \"console\" \"Formatting $image ...\"\n\n    # change to the image folder as kpartx has problems removing the\n    # device mapper files when using a full path to the image\n    local image_path=\"${image%/*}\"\n    local image_name=\"${image##*/}\"\n    pushd \"$image_path\"\n\n    local partitions=($(kpartx -s -a -v \"$image_name\" | awk '{ print \"/dev/mapper/\"$3 }'))\n    local part_boot=\"${partitions[0]}\"\n    local part_root=\"${partitions[1]}\"\n\n    mkfs.vfat -F 32 -n bootfs \"$part_boot\"\n    # use the mke2fs config from the chroot so we create the filesystem with supported features\n    # disable huge_file & 64bit as with the Raspberry Pi OS images\n    MKE2FS_CONFIG=\"$chroot/etc/mke2fs.conf\" mkfs.ext4 -O ^huge_file,^64bit -L retropie \"$part_root\"\n\n    parted \"$image_name\" print\n\n    # disable ctrl+c\n    trap \"\" INT\n\n    # mount\n    printMsgs \"console\" \"Mounting $image_name ...\"\n\n    # get temporary directory\n    local tmp=\"$(mktemp -d -p \"$md_build\")\"\n\n    # mount root partition\n    mount \"$part_root\" \"$tmp\"\n\n    # get the mount location of the boot partition from etc/fstab\n    local boot_path=\"$(_get_boot_path_image \"$chroot\")\"\n\n    # create the boot partition mountpoint and mount\n    mkdir -p \"$tmp$boot_path\"\n    mount \"$part_boot\" \"$tmp$boot_path\"\n\n    # copy files\n    printMsgs \"console\" \"Rsyncing chroot to $image_name ...\"\n    rsync -aAHX --numeric-ids \"$chroot/\" \"$tmp/\"\n\n    # we need to fix up the UUIDS for /boot/cmdline.txt and /etc/fstab\n    local old_id=\"$(sed \"s/.*PARTUUID=\\([^-]*\\).*/\\1/\" $tmp$boot_path/cmdline.txt)\"\n    local new_id=\"$(blkid -s PARTUUID -o value \"$part_root\" | cut -c -8)\"\n    sed -i \"s/$old_id/$new_id/\" \"$tmp$boot_path/cmdline.txt\"\n    sed -i \"s/$old_id/$new_id/g\" \"$tmp/etc/fstab\"\n\n    # unmount\n    umount -l \"$tmp$boot_path\" \"$tmp\"\n    rm -rf \"$tmp\"\n\n    kpartx -d \"$image_name\"\n\n    trap INT\n}\n\n# generate berryboot squashfs from filesystem\nfunction create_bb_image() {\n    local image=\"$1\"\n    [[ -z \"$image\" ]] && return 1\n\n    local chroot=\"$2\"\n    [[ -z \"$chroot\" ]] && return 1\n\n    # replace fstab\n    echo \"proc            /proc           proc    defaults          0       0\" >\"$chroot/etc/fstab\"\n\n    # remove any earlier image\n    rm -f \"$image\"\n\n    mksquashfs \"$chroot\" \"$image\" -comp lzo -e boot -e lib/modules\n}\n\nfunction all_image() {\n    local dist=\"$1\"\n    local make_bb=\"$2\"\n    local platforms=\"$(_get_info_image \"$dist\" \"platforms\")\"\n    [[ -z \"$platforms\" ]] && fatalError \"Unable to get platforms information for $dist\"\n\n    local platform\n    printMsgs \"heading\" \"Building $platforms images based on $dist ...\"\n    for platform in $platforms; do\n        platform_image \"$platform\" \"$dist\" \"$make_bb\"\n    done\n    combine_json_image\n}\n\nfunction platform_image() {\n    local platform=\"$1\"\n    local dist=\"$2\"\n    local make_bb=\"$3\"\n    [[ -z \"$platform\" ]] && return 1\n\n    local dest=\"$__tmpdir/images\"\n    mkdir -p \"$dest\"\n\n    printMsgs \"heading\" \"Building $platform image based on $dist ...\"\n\n    rp_callModule image create_chroot \"$dist\"\n    rp_callModule image install_rp \"$platform\" \"$dist\" \"$md_build/$dist\"\n\n    local dist_name=\"$(_get_info_image \"$dist\" \"name\")\"\n    [[ -z \"$dist_name\" ]] && fatalError \"Unable to get name information for $dist\"\n\n    local dist_version=\"$(_get_info_image \"$dist\" \"version\")\"\n    [[ -z \"$dist_version\" ]] && fatalError \"Unable to get version information for $dist\"\n\n    local file_add=\"$(_get_info_image \"$dist\" \"file_${platform}\")\"\n    [[ -z \"$file_add\" ]] && fatalError \"Unable to get file_* information for $dist\"\n\n    local image_title=\"$(_get_info_image \"$dist\" \"title_${platform}\")\"\n    [[ -z \"$image_title\" ]] && fatalError \"Unable to get image_title information for $dist\"\n\n    local image_base=\"retropie-${dist_name}-${__version}-${file_add}\"\n    local image_name=\"${image_base}.img\"\n    local image_file=\"$dest/$image_name\"\n\n    local boot_size_mib=512\n    # use a 256MiB boot partition for Raspberry Pi OS lower than 12 (Bullseye and below)\n    if [[ \"$dist_version\" -lt 12 ]]; then\n        boot_size_mib=256\n    fi\n\n    rp_callModule image create \"$image_file\" \"$md_build/$dist\" $boot_size_mib\n    [[ \"$make_bb\" -eq 1 ]] && rp_callModule image create_bb \"$dest/${image_base}-berryboot.img256\"\n\n    printMsgs \"console\" \"Compressing ${image_name} ...\"\n    xz -v --compress --stdout \"$image_file\" > \"${image_file}.xz\"\n\n    printMsgs \"console\" \"Generating JSON data for rpi-imager ...\"\n    local template\n    template=\"$(<\"$md_data/template.json\")\"\n    template=\"${template/IMG_PATH/$__version\\/${image_name}.xz}\"\n    template=\"${template/IMG_EXTRACT_SIZE/$(stat -c %s $image_file)}\"\n    template=\"${template/IMG_SHA256/$(sha256sum $image_file | cut -d\" \" -f1)}\"\n    template=\"${template/IMG_DOWNLOAD_SIZE/$(stat -c %s ${image_file}.xz)}\"\n    template=\"${template/IMG_VERSION/$__version}\"\n    template=\"${template/IMG_PLATFORM/$image_title}\"\n    template=\"${template/IMG_DATE/$(date '+%Y-%m-%d')}\"\n    echo \"$template\" >\"${image_file}.json\"\n\n    rm -f \"$image_file\"\n}\n\nfunction combine_json_image() {\n    local dest=\"$__tmpdir/images\"\n    {\n        local template\n        echo -en \"{\\n    \\\"os_list\\\": [\\n\"\n        local i=0\n        while read file; do\n            [[ \"$i\" -gt 0 ]] && echo -en \",\\n\"\n            template=\"$(<$file)\"\n            echo -n \"$template\"\n            ((i++))\n        done < <(find \"$dest\" -name \"*.img.json\" | sort)\n        echo -en \"\\n    ]\\n}\\n\"\n    } >\"$dest/os_list_imagingutility.json\"\n}\n"
  },
  {
    "path": "scriptmodules/admin/joy2key/joy2key.py",
    "content": "#!/usr/bin/python3\n\n# This file is part of The RetroPie Project\n# \n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n# \n# See the LICENSE.md file at the top-level directory of this distribution and \n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nimport os, sys, struct, time, fcntl, termios, signal\nimport curses, errno, re\nfrom pyudev import Context\n\n\n#    struct js_event {\n#        __u32 time;     /* event timestamp in milliseconds */\n#        __s16 value;    /* value */\n#        __u8 type;      /* event type */\n#        __u8 number;    /* axis/button number */\n#    };\n\nJS_MIN = -32768\nJS_MAX = 32768\nJS_REP = 0.20\n\nJS_THRESH = 0.75\n\nJS_EVENT_BUTTON = 0x01\nJS_EVENT_AXIS = 0x02\nJS_EVENT_INIT = 0x80\n\nCONFIG_DIR = '/opt/retropie/configs/'\nRETROARCH_CFG = CONFIG_DIR + 'all/retroarch.cfg'\n\ndef ini_get(key, cfg_file):\n    pattern = r'[ |\\t]*' + key + r'[ |\\t]*=[ |\\t]*'\n    value_m = r'\"*([^\"\\|\\r]*)\"*'\n    value = ''\n    with open(cfg_file, 'r') as ini_file:\n        for line in ini_file:\n            if re.match(pattern, line):\n                value = re.sub(pattern + value_m + '.*\\n', r'\\1', line)\n                break\n    return value\n\ndef get_btn_num(btn, cfg):\n    num = ini_get('input_' + btn + '_btn', cfg)\n    if num: return num\n    num = ini_get('input_player1_' + btn + '_btn', cfg)\n    if num: return num\n    return ''\n\ndef sysdev_get(key, sysdev_path):\n    value = ''\n    for line in open(sysdev_path + key, 'r'):\n        value = line.rstrip('\\n')\n        break\n    return value\n\ndef get_button_codes(dev_path):\n    js_cfg_dir = CONFIG_DIR + 'all/retroarch-joypads/'\n    js_cfg = ''\n    dev_name = ''\n    dev_button_codes = list(default_button_codes)\n\n    for device in Context().list_devices(DEVNAME=dev_path):\n        sysdev_path = os.path.normpath('/sys' + device.get('DEVPATH')) + '/'\n        if not os.path.isfile(sysdev_path + 'name'):\n            sysdev_path = os.path.normpath(sysdev_path + '/../') + '/'\n        # getting joystick name\n        dev_name = sysdev_get('name', sysdev_path)\n        # getting joystick vendor ID\n        dev_vendor_id = int(sysdev_get('id/vendor', sysdev_path), 16)\n        # getting joystick product ID\n        dev_product_id = int(sysdev_get('id/product', sysdev_path), 16)\n    if not dev_name:\n        return dev_button_codes\n\n    # getting retroarch config file for joystick\n    for f in os.listdir(js_cfg_dir):\n        if f.endswith('.cfg'):\n            input_device = ini_get('input_device', js_cfg_dir + f)\n            input_vendor_id = ini_get('input_vendor_id', js_cfg_dir + f)\n            input_product_id = ini_get('input_product_id', js_cfg_dir + f)\n            if (input_device == dev_name and\n               (input_vendor_id  == '' or int(input_vendor_id)  == dev_vendor_id) and\n               (input_product_id == '' or int(input_product_id) == dev_product_id)):\n                js_cfg = js_cfg_dir + f\n                break\n    if not js_cfg:\n        js_cfg = RETROARCH_CFG\n\n    # getting configs for dpad, buttons A, B, X and Y\n    btn_map = [ 'left', 'right', 'up', 'down', 'a', 'b', 'x', 'y' ]\n    btn_num = {}\n    biggest_num = 0\n    i = 0\n    for btn in list(btn_map):\n        if i >= len(dev_button_codes):\n            break\n        try:\n            btn_num[btn] = int(get_btn_num(btn, js_cfg))\n        except ValueError:\n            btn_map.pop(i)\n            dev_button_codes.pop(i)\n            btn_num.pop(btn, None)\n            continue\n        if btn_num[btn] > biggest_num:\n            biggest_num = btn_num[btn]\n        i += 1\n\n    # building the button codes list\n    btn_codes = [''] * (biggest_num + 1)\n    i = 0\n    for btn in btn_map:\n        if i >= len(dev_button_codes):\n            break\n        btn_codes[btn_num[btn]] = dev_button_codes[i]\n        i += 1\n    try:\n        # if button A is <enter> and menu_swap_ok_cancel_buttons is true, swap buttons A and B functions\n        if (ini_get('menu_swap_ok_cancel_buttons', RETROARCH_CFG) == 'true' and\n           'a' in btn_num and 'b' in btn_num and btn_codes[btn_num['a']] == '\\n'):\n            btn_codes[btn_num['a']] = btn_codes[btn_num['b']]\n            btn_codes[btn_num['b']] = '\\n'\n    except (IOError, ValueError):\n        pass\n\n    return btn_codes\n\ndef signal_handler(signum, frame):\n    signal.signal(signal.SIGINT, signal.SIG_IGN)\n    signal.signal(signal.SIGTERM, signal.SIG_IGN)\n    if (js_fds):\n        close_fds(js_fds)\n    if (tty_fd):\n        os.close(tty_fd)\n    sys.exit(0)\n\ndef get_hex_chars(key_str):\n    if (key_str.startswith(\"0x\")):\n        out = bytes.fromhex(key_str[2:])\n    else:\n        out = curses.tigetstr(key_str)\n    return out.decode('utf-8')\n\ndef get_devices():\n    devs = []\n    if sys.argv[1] == '/dev/input/jsX':\n        for dev in os.listdir('/dev/input'):\n            if dev.startswith('js'):\n                devs.append('/dev/input/' + dev)\n    else:\n        devs.append(sys.argv[1])\n\n    return devs\n\ndef open_devices():\n    devs = get_devices()\n\n    fds = []\n    for dev in devs:\n        try:\n            fds.append(os.open(dev, os.O_RDONLY | os.O_NONBLOCK ))\n            js_button_codes[fds[-1]] = get_button_codes(dev)\n        except (OSError, ValueError):\n            pass\n\n    return devs, fds\n\ndef close_fds(fds):\n    for fd in fds:\n        os.close(fd)\n\ndef read_event(fd):\n    while True:\n        try:\n            event = os.read(fd, event_size)\n        except OSError as e:\n            if e.errno == errno.EWOULDBLOCK:\n                return None\n            return False\n\n        else:\n            return event\n\ndef process_event(event):\n\n    (js_time, js_value, js_type, js_number) = struct.unpack(event_format, event)\n\n    # ignore init events\n    if js_type & JS_EVENT_INIT:\n        return False\n\n    hex_chars = \"\"\n\n    if js_type == JS_EVENT_BUTTON:\n        if js_number < len(button_codes) and js_value == 1:\n            hex_chars = button_codes[js_number]\n\n    if js_type == JS_EVENT_AXIS and js_number <= 7:\n        if js_number % 2 == 0:\n            if js_value <= JS_MIN * JS_THRESH:\n                hex_chars = axis_codes[0]\n            if js_value >= JS_MAX * JS_THRESH:\n                hex_chars = axis_codes[1]\n        if js_number % 2 == 1:\n            if js_value <= JS_MIN * JS_THRESH:\n                hex_chars = axis_codes[2]\n            if js_value >= JS_MAX * JS_THRESH:\n                hex_chars = axis_codes[3]\n\n    if hex_chars:\n        for c in hex_chars:\n            fcntl.ioctl(tty_fd, termios.TIOCSTI, c)\n        return True\n\n    return False\n\njs_fds = []\ntty_fd = []\n\nsignal.signal(signal.SIGINT, signal_handler)\nsignal.signal(signal.SIGTERM, signal_handler)\n\n# daemonize when signal handlers are registered\nif os.fork():\n    os._exit(0)\n\njs_button_codes = {}\nbutton_codes = []\ndefault_button_codes = []\naxis_codes = []\n\ncurses.setupterm()\n\ni = 0\nfor arg in sys.argv[2:]:\n    chars = get_hex_chars(arg)\n    if i < 4:\n        axis_codes.append(chars)\n\n    default_button_codes.append(chars)\n    i += 1\n\nevent_format = 'IhBB'\nevent_size = struct.calcsize(event_format)\n\ntry:\n    tty_fd = os.open('/dev/tty', os.O_WRONLY)\nexcept IOError:\n    print('Unable to open /dev/tty', file = sys.stderr)\n    sys.exit(1)\n\nrescan_time = time.time()\nwhile True:\n    do_sleep = True\n    if not js_fds:\n        js_devs, js_fds = open_devices()\n        if js_fds:\n            i = 0\n            current = time.time()\n            js_last = [None] * len(js_fds)\n            for js in js_fds:\n                js_last[i] = current\n                i += 1\n        else:\n            time.sleep(1)\n    else:\n        i = 0\n        for fd in js_fds:\n            event = read_event(fd)\n            if event:\n                do_sleep = False\n                if time.time() - js_last[i] > JS_REP:\n                    if fd in js_button_codes:\n                        button_codes = js_button_codes[fd]\n                    else:\n                        button_codes = default_button_codes\n                    if process_event(event):\n                        js_last[i] = time.time()\n            elif event == False:\n                close_fds(js_fds)\n                js_fds = []\n                break\n            i += 1\n\n    if time.time() - rescan_time > 2:\n        rescan_time = time.time()\n        if js_devs != get_devices():\n            close_fds(js_fds)\n            js_fds = []\n\n    if do_sleep:\n        time.sleep(0.01)\n"
  },
  {
    "path": "scriptmodules/admin/joy2key/joy2key_sdl.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nThis file is part of The RetroPie Project\n\nThe RetroPie Project is the legal property of its developers, whose names are\ntoo numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n\nSee the LICENSE.md file at the top-level directory of this distribution and\nhttps://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md.\n\nCommand line joystick to keyboard translator, using SDL2 for event handling\nExample usage:\n <script> kcub1 kcuf1 kcuu1 kcud1 0x0a 0x20 0x1b 0x00 kpp knp [--debug|-d]\nSee https://pubs.opengroup.org/onlinepubs/7908799/xcurses/terminfo.html for termcap codes\nNB: not all capabilities are supported, but more can be added to the TERM_EVENTS below\n\nSDL2 event handling is based on EmulationStation's event handling, see\nhttps://github.com/RetroPie/EmulationStation/blob/62fd08c26d2f757259b7d890c98c0d7e212f6f84/es-core/src/InputManager.cpp#L205\nEmulationStation is authored by Alec \"Aloshi\" Lofquist (http://www.aloshi.com,http://www.emulationstation.org)\n\nThis script uses the PySDL2 module from https://github.com/py-sdl/py-sdl2\nThis script uses the Python-uinput module from https://github.com/tuomasjjrasanen/python-uinput\n\"\"\"\n\nimport logging\nimport sys\nimport signal\nimport re\nimport os\nimport uinput\n\nfrom argparse import ArgumentParser\nfrom ctypes import create_string_buffer, byref\nfrom configparser import ConfigParser\nfrom sdl2 import joystick, events, version, \\\n    SDL_WasInit, SDL_Init, SDL_QuitSubSystem, SDL_GetError, \\\n    SDL_INIT_JOYSTICK, version_info, \\\n    SDL_Event, SDL_PollEvent, SDL_FlushEvent, SDL_Delay, SDL_Quit, \\\n    SDL_JOYDEVICEADDED, SDL_JOYDEVICEREMOVED, SDL_QUIT, \\\n    SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP, SDL_JOYHATMOTION, SDL_JOYAXISMOTION, \\\n    SDL_GetTicks\n\nlogging.basicConfig(level=logging.INFO, format=u\"%(asctime)s %(levelname)-6s %(message)s\")\nLOG = logging.getLogger(__name__)\n\n# Switch for the HIDAPI driver usage in SDL. Disabled since RetroArch/EmulationStation don't use right now\nSDL_USE_HIDAPI = False\n\n# Joystick deadzone threshold, as used by EmulationStation (see es-core/InputManager::parseInput)\nJS_AXIS_DEADZONE = 23000\n\n# Event polling interval (ms)\nJS_POLL_DELAY = 50\n\n# Event repeat in (ms)\nJS_REPEAT_DELAY = 125\n\n# Event delay after a button is pressed (ms)\n# Set a bit larger than the default repeat delay to prevent multiple inputs being fired\nJS_INIT_DELAY = 250\n\n# Hat values defined here, they're not exported by the sdl2.joystick module\nSDL_HAT_CENTERED = 0x00\nSDL_HAT_UP = 0x01\nSDL_HAT_RIGHT = 0x02\nSDL_HAT_DOWN = 0x04\nSDL_HAT_LEFT = 0x08\nJS_HAT_VALUES = {\n    \"up\": SDL_HAT_UP,\n    \"down\": SDL_HAT_DOWN,\n    \"left\": SDL_HAT_LEFT,\n    \"right\": SDL_HAT_RIGHT\n}\n\n# Map termios capabilitu codes to Linux (uinput) event ids, for backwards compatibility\n# List of possible event IDs:\n# https://github.com/tuomasjjrasanen/python-uinput/blob/master/src/ev.py\nTERM_EVENTS = {\n    \"kcub1\": 105, # left\n    \"kcuf1\": 106, # right\n    \"kcud1\": 108, # down\n    \"kcuu1\": 103, # up\n    \"khome\": 102, # home\n    \"kbs\"  : 14,  # backspace\n    \"kend\" : 107, # end\n    \"knp\"  : 109, # page-up\n    \"kpp\"  : 104, # page-down\n    \"kent\" : 28,  # enter\n    \"kf1\"  : 59,  # F1\n    \"kf2\"  : 60,  # F2\n    \"kf3\"  : 61,  # F3\n    \"kf4\"  : 62,  # F4\n    \"kf5\"  : 63,  # F5\n    \"kf6\"  : 64,  # F6\n    \"kf7\"  : 65,  # F7\n    \"kf8\"  : 66,  # F8\n    \"kf9\"  : 67,  # F9\n    \"kf10\" : 68   # F10\n}\n\n# A charmap with 'ascii_code': 'event_id', needed to translate hex valued parameters\n# Copy the one defined in 'uinput', so we can extend it since it's missing some entries\nCHAR_MAP = { ord(x):y[1] for (x,y) in uinput._CHAR_MAP.items() }\n# add our entries to the map, so we can translate them\nCHAR_MAP[27]  = 1   # Escape \nCHAR_MAP[61]  = 13  # Equals (=)\nCHAR_MAP[43]  = 12  # Minus (-)\nCHAR_MAP[91]  = 26  # Left bracket ([)\nCHAR_MAP[93]  = 27  # Right bracket (])\nCHAR_MAP[127] = 111 # Delete\n\n# RetroPie configurations directory\nCONFIG_DIR = '/opt/retropie/configs'\n\n\nclass InputDev(object):\n    \"\"\"\n    Class representing a joystick device config.\n    Maps the inputs of the device to event names\n    name: the device's name\n    guid: the GUID, as retuned by SDL\n    hats - a dictionary of { <HatNo>: list(<HatValue>, <Event>) }\n    buttons - a dict of { <ButtonNo>: <Event> }\n    axis - a dict of { <AxisNo>: list(<AxisDirection>, <Event>) }\n    \"\"\"\n\n    def __init__(self, _name: str, _guid: str):\n        self.name = _name\n        self.guid = _guid\n        self.axis = {}\n        self.buttons = {}\n        self.hats = {}\n\n    def add_mappings(self, _axis: dict, _buttons: dict, _hats: dict):\n        self.axis, self.buttons, self.hats = _axis, _buttons, _hats\n\n    def get_btn_event(self, index: int) -> list:\n        if index in self.buttons:\n            return [self.buttons[index]]\n        else:\n            return None\n\n    def get_hat_event(self, index: int, value: int) -> list:\n        if index in self.hats:\n            return [x[1] for x in self.hats[index] if x[0] & value > 0]\n        else:\n            return None\n\n    def get_axis_event(self, index: int, value: int) -> list:\n        if index in self.axis:\n            return [x[1] for x in self.axis[index] if x[0] == value]\n        else:\n            return None\n\n    def __str__(self) -> str:\n        return str(f'{self.name}, hats: {self.hats}, buttons: {self.buttons}, axis: {self.axis}')\n\n\ndef generic_event_map(input: str, event_map: dict) -> str:\n    for k, v in event_map.items():\n        if isinstance(v, list):\n            if input in v:\n                return k\n        elif isinstance(v, str) and input == v:\n                return k\n    return input\n\n\ndef ra_event_map(input_str: str) -> str:\n    \"\"\"\n    Maps a RetroArch input option name to an event name\n    Example:\n        'input_a_btn' -> 'a'\n        'input_l_axis' -> 'pageup'\n    \"\"\"\n    ra_event_map = {\n        'up': ['l_y_minus', 'r_y_minus'],\n        'down': ['l_y_plus', 'r_y_plus'],\n        'left': ['l_x_minus', 'r_x_minus'],\n        'right': ['l_x_plus', 'r_x_plus'],\n        'pageup': 'l',\n        'pagedown': 'r'\n    }\n\n    input_norm = input_str.replace('input_', '').replace('_axis', '').replace('_btn', '')\n    return generic_event_map(input_norm, ra_event_map)\n\n\ndef ra_input_parse(key: str, value: str):\n    \"\"\"\n    For a RetroArch input option line ('key = value'), returns a triplet consisting of\n     - the type of the input (button, hat, axis)\n     - the index of the input (button number, hat number, axis number)\n     - the input value associated: 1 for buttons, axis direction (-1/1), hat value (1,2,4,8)\n    Ex:\n      - ('input_a_btn', '1') -> 'button', 1, 1\n      - ('input_left_btn, 'h0left') -> 'hat', '0', 8\n      - ('input_r_x_axis_minus, -1) -> 'axis', 1, -1\n    \"\"\"\n    try:\n        if key.endswith('btn'):\n            if value.startswith('h'):\n                input_type = 'hat'\n                hat_value = re.split(r'([0-9]+)', value)[1:]\n                # reject malformed hat values\n                if hat_value[1] not in JS_HAT_VALUES:\n                    raise ValueError('Not a valid hat value')\n                input_index, input_value = int(hat_value[0]), JS_HAT_VALUES[hat_value[1]]\n            else:\n                input_type = 'button'\n                input_index, input_value = int(value), 1\n        elif key.endswith('axis'):\n            input_type = 'axis'\n            input_index, input_value = int(value[1:]), int(f'{value[0]}1')\n        else:  # unknown input\n            return None, None, None\n\n        return input_type, input_index, input_value\n    except ValueError as e:\n        return None, None, None\n\n\ndef get_all_ra_config(def_buttons: list) -> list:\n    \"\"\"\n    Reads the RetroArch's gamepad auto-configuration folder\n    and creates a list with of the configured joystick devices as InputDev objects\n    \"\"\"\n    ra_config_list = []\n    # add a generic mapping at index 0, to be used for un-configured joysticks\n    generic_dev = InputDev(\"*\", \"*\")\n    generic_dev.add_mappings(\n        {},  # no axis\n        {0: 'b', 1: 'a', 3: 'y', 4: 'x'},  # 4 buttons\n        {0: [(1, 'up'), (8, 'left'), (4, 'down'), (2, 'right')]}  # 1 D-Pad as 'hat0'\n    )\n    ra_config_list.append(generic_dev)\n    js_cfg_dir = CONFIG_DIR + '/all/retroarch-joypads/'\n\n    config = ConfigParser(delimiters=\"=\", strict=False, interpolation=None)\n    for file in os.listdir(js_cfg_dir):\n        # skip non '.cfg' files\n        if not file.endswith('.cfg') or file.startswith('.'):\n            continue\n\n        with open(js_cfg_dir + file, 'r') as cfg_file:\n            try:\n                config.clear()\n                # ConfigParser needs a section, make up a section to appease it\n                config.read_string('[device]\\n' + cfg_file.read())\n                conf_vals = config['device']\n                dev_name = conf_vals['input_device'].strip('\"')\n\n                # translate the RetroArch inputs from the configuration file\n                axis, buttons, hats = {}, {}, {}\n                for i in conf_vals:\n                    if i.startswith('input') and (i.endswith('btn') or i.endswith('axis')):\n                        input_type, input_index, input_value = ra_input_parse(i, conf_vals[i].strip('\"'))\n\n                        # check if the input is mapped to one of the events we recognize\n                        event_name = ra_event_map(i)\n                        if event_name not in def_buttons:\n                            continue\n                        if input_type == 'button':\n                            buttons[input_index] = event_name\n                        elif input_type == 'hat':\n                            hats.setdefault(input_index, []).append((input_value, event_name))\n                        elif input_type == 'axis':\n                            axis.setdefault(input_index, []).append((input_value, event_name))\n                        else:\n                            continue\n                ra_dev_config = InputDev(dev_name, None)\n                ra_dev_config.add_mappings(axis, buttons, hats)\n                ra_config_list.append(ra_dev_config)\n            except Exception as e:\n                LOG.warning(f'Parsing error for {file}: {e}')\n                continue\n\n    return ra_config_list\n\n\ndef filter_active_events(event_queue: dict) -> list:\n    \"\"\"\n    Method to filter out the event if the event:\n     * fired once within the JS_POLL_DELAY_DEBOUNCE\n     * fired multiple times, last fire within JS_POLL_POLL_DELAY_DEFAULT\n    \"\"\"\n    current_time = SDL_GetTicks()\n    filtered_events = []\n    for e in event_queue:\n        if event_queue[e][0] is None:\n            continue\n\n        last_fire_time = event_queue[e][2]\n        repeat_count = event_queue[e][1]\n\n        if repeat_count == 0 or \\\n             (repeat_count == 1 and current_time > (last_fire_time + JS_INIT_DELAY)) or \\\n             (repeat_count > 1 and current_time > (last_fire_time + JS_REPEAT_DELAY)):\n            filtered_events.extend(event_queue[e][0])\n            event_queue[e][2] = current_time\n            event_queue[e][1] += 1\n\n    # remove any duplicate events from the list\n    return list(set(filtered_events))\n\n\"\"\"\nRemove all queued events for a device\n\"\"\"\ndef remove_events_for_device(event_queue: dict, dev_index: int):\n    return { key:value for (key,value) in event_queue.items() if not key.startswith(f\"{dev_index}_\")}\n\ndef event_loop(configs, joy_map):\n    event = SDL_Event()\n\n    # keep of dict of active joystick devices as a dict of\n    #  instance_id -> (config_id, SDL_Joystick object)\n    active_devices = {}\n\n    # keep an event queue populated with the current active inputs\n    # indexed by joystick index, input type and input index\n    # the values consist of:\n    # - the event list (as taked from the event configuration)\n    # - the number of times event was emitted (repeated)\n    # - the last time when the event was fired\n    # e.g. { event_hash -> ([event_list], repeat_no, last_fire_time) }\n    event_queue = {}\n\n    # keep track of axis previous values\n    axis_prev_values = {}\n\n    # instantiate a keyboard device with uinput to send the translated joypad inputs as keys\n    keyboard_events = [ (0x1,code) for code in joy_map.values() ]\n    LOG.debug(f'Creating uinput keyboard devices with events: {keyboard_events}')\n    kbd = uinput.Device(events=keyboard_events, name=\"Joy2Key Keyboard\")\n\n    def handle_new_input(e: SDL_Event, axis_norm_value: int = 0) -> bool:\n        \"\"\"\n        Event handling for button press/hat movement/axis movement\n        Only needed when an new input is present\n        Returns True when 'event_queue' is modified with a new event\n        \"\"\"\n        dev_index = active_devices[event.jdevice.which][0]\n        if e.type == SDL_JOYBUTTONDOWN:\n            mapped_events = configs[dev_index].get_btn_event(event.jbutton.button)\n            event_index = f'{dev_index}_btn{event.jbutton.button}'\n        elif e.type == SDL_JOYHATMOTION:\n            mapped_events = configs[dev_index].get_hat_event(event.jhat.hat, event.jhat.value)\n            event_index = f'{dev_index}_hat{event.jhat.hat}'\n        elif e.type == SDL_JOYAXISMOTION and axis_norm_value != 0:\n            mapped_events = configs[dev_index].get_axis_event(event.jaxis.axis, axis_norm_value)\n            event_index = f'{dev_index}_axis{event.jaxis.axis}'\n\n        if mapped_events is not None:\n            event_queue[event_index] = [ mapped_events, 0, SDL_GetTicks() ]\n            return True\n\n        return False\n\n    running = True\n    while running:\n        input_started = False\n\n        while SDL_PollEvent(byref(event)):\n\n            if event.type == SDL_QUIT:\n                running = False\n                break\n\n            if event.type == SDL_JOYDEVICEADDED:\n                stick = joystick.SDL_JoystickOpen(event.jdevice.which)\n                name = joystick.SDL_JoystickName(stick).decode('utf-8')\n                guid = create_string_buffer(33)\n                _SDL_JoystickGetGUIDString(joystick.SDL_JoystickGetGUID(stick), guid, 33)\n                LOG.debug(f'Joystick #{joystick.SDL_JoystickInstanceID(stick)} {name} added')\n                conf_found = False\n                # try to find a configuration for the joystick\n                for key, dev_conf in enumerate(configs):\n                    if dev_conf.name == str(name) or dev_conf.guid == guid.value.decode():\n                        # Add the matching joystick configuration to the watched list\n                        active_devices[joystick.SDL_JoystickInstanceID(stick)] = (key, stick)\n                        LOG.debug(f'Added configuration for known device {configs[key]}')\n                        conf_found = True\n                        break\n\n                # add the default configuration for unknown/un-configured joysticks\n                if not conf_found:\n                    LOG.debug(f'Un-configured device \"{str(name)}\", mapped using generic mapping')\n                    active_devices[joystick.SDL_JoystickInstanceID(stick)] = (0, stick)\n\n                # if the device has axis inputs, initialize to zero their initial position\n                if joystick.SDL_JoystickNumAxes(stick) > 0:\n                    axis_prev_values[joystick.SDL_JoystickInstanceID(stick)] = [0 for x in range(joystick.SDL_JoystickNumAxes(stick))]\n\n                # Remove any spurious axis movements reported by SDL during initialization\n                SDL_FlushEvent(SDL_JOYAXISMOTION);\n                continue\n\n            if event.jdevice.which not in active_devices:\n                continue\n            else:\n                dev_index = active_devices[event.jdevice.which][0]\n\n            if event.type == SDL_JOYDEVICEREMOVED:\n                joystick.SDL_JoystickClose(active_devices[event.jdevice.which][1])\n                if event.jdevice.which in active_devices:\n                    event_queue = remove_events_for_device(event_queue, active_devices[event.jdevice.which][0])\n                active_devices.pop(event.jdevice.which, None)\n                axis_prev_values.pop(event.jdevice.which, None)\n                LOG.debug(f'Removed joystick #{event.jdevice.which}')\n\n            if event.type == SDL_JOYBUTTONDOWN:\n                input_started = handle_new_input(event)\n\n            if event.type == SDL_JOYBUTTONUP:\n                event_queue.pop(f'{dev_index}_btn{event.jbutton.button}', None)\n\n            if event.type == SDL_JOYHATMOTION:\n                if event.jhat.value != SDL_HAT_CENTERED:\n                    input_started = handle_new_input(event)\n                else:\n                    event_queue.pop(f'{dev_index}_hat{event.jhat.hat}', None)\n\n            if event.type == SDL_JOYAXISMOTION:\n                # check if the axis value went over the deadzone threshold\n                if (abs(event.jaxis.value) > JS_AXIS_DEADZONE) \\\n                        != (abs(axis_prev_values[event.jdevice.which][event.jaxis.axis]) > JS_AXIS_DEADZONE):\n                    # normalize the axis value to the movement direction or stop the input\n                    if abs(event.jaxis.value) <= JS_AXIS_DEADZONE:\n                        event_queue.pop(f'{dev_index}_axis{event.jaxis.axis}', None)\n                    else:\n                        if event.jaxis.value < 0:\n                            axis_norm_value = -1\n                        else:\n                            axis_norm_value = 1\n                        input_started = handle_new_input(event, axis_norm_value)\n                # store the axis current values for tracking\n                axis_prev_values[event.jdevice.which][event.jaxis.axis] = event.jaxis.value\n\n        # process the current events in the queue\n        if len(event_queue):\n            emitted_events = filter_active_events(event_queue)\n            if len(emitted_events):\n                LOG.debug(f'Events to emit: {emitted_events}')\n            # send the events mapped key code(s) to the terminal\n            for k in emitted_events:\n                if k in joy_map:\n                    c = joy_map[k]\n                    LOG.debug(f'Emitting input code {c}')\n                    kbd.emit_click( (0x1,c) )\n\n        SDL_Delay(JS_POLL_DELAY)\n\n\ndef parse_arguments(args):\n    parser = ArgumentParser(\n        description='Translate joystick events to keyboard inputs')\n\n    parser.add_argument(\n        '-d', '--debug',\n        action='store_true',\n        help='print debugging messages',\n        default=False)\n    parser.add_argument(\n        'hex_chars', type=str, nargs='+',\n        metavar='0xHEX',\n        help='list of mapped character codes to translate')\n\n    args = parser.parse_args()\n    return args.debug, args.hex_chars\n\n\ndef ra_btn_swap_config():\n    \"\"\"\n    Returns the state of 'menu_swap_ok_cancel_buttons' configuration for RetroArch\n    \"\"\"\n    config = ConfigParser(delimiters=\"=\", strict=False, interpolation=None)\n    with open(CONFIG_DIR + '/all/retroarch.cfg', 'r') as cfg_file:\n        config.read_string('[device]\\n' + cfg_file.read())\n        try:\n            menu_swap = config['device']['menu_swap_ok_cancel_buttons'].strip('\"') == 'true'\n        except Exception as e:\n            menu_swap = False\n\n    return menu_swap\n\ndef get_uinput_event(key_str: str):\n    \"\"\"\n    For a Termios control string or an ASCII hex code, return the Linux scancode (integer)\n    See https://github.com/tuomasjjrasanen/python-uinput/blob/master/src/ev.py for an enumeratin of scancodes\n\n    If 'key_str' starts with '0x', it's assumed to be a hexadecimal value of an ASCII char,\n    otherwise it's presumed to be a termios control string tied to the terminal's capabilities\n    \"\"\"\n    try:\n        if key_str.startswith('/'):\n            # ignore any device name - they're not part of our assignment\n            return None\n\n        if key_str.startswith('0x'):\n            out = int(key_str,0)\n            # hex numbers are considered ASCII codes for keyboard keys\n            # we need to translate them to Linux input scancodes\n            out = CHAR_MAP[out]\n        else:\n            if (key_str in TERM_EVENTS.keys()):\n                out = TERM_EVENTS[key_str]\n            else:\n                LOG.warning(f'Unsupported termios control code \"{key_str}\", value ignored')\n                return 0\n        return out\n    except Exception as e:\n        LOG.debug(f'Cannot determine input code for \"{key_str}\", value ignored')\n        return 0\n\ndef _SDL_JoystickGetGUIDString(guid, pszGUID, cbGUID):\n    \"\"\"\n    Local method implementing https://github.com/marcusva/py-sdl2/pull/156\n    Prevents a segfault with older (<3.8) Python AND older Py-SDL2 (<0.9.7)\n    \"\"\"\n    if sys.version_info >= (3, 8, 0, 'final'):\n         joystick.SDL_JoystickGetGUIDString(guid, pszGUID, cbGUID)\n    else:\n         s = \"\"\n         for g in guid.data:\n              s += \"{:x}\".format(g >> 4)\n              s += \"{:x}\".format(g & 0x0F)\n\n         s = s.encode('utf-8')\n         pszGUID.value = s[:(cbGUID * 2)]\n\n\ndef main():\n    # install a signal handler so the script can stop safely\n    def signal_handler(signum, frame):\n        signal.signal(signal.SIGINT, signal.SIG_IGN)\n        signal.signal(signal.SIGTERM, signal.SIG_IGN)\n\n        if SDL_WasInit(SDL_INIT_JOYSTICK) == SDL_INIT_JOYSTICK:\n            SDL_QuitSubSystem(SDL_INIT_JOYSTICK)\n        SDL_Quit()\n        LOG.debug(f'{sys.argv[0]} exiting cleanly')\n        sys.exit(0)\n\n    debug_flag, hex_chars = parse_arguments(sys.argv)\n    if debug_flag:\n        LOG.setLevel(logging.DEBUG)\n\n    signal.signal(signal.SIGINT, signal_handler)\n    signal.signal(signal.SIGTERM, signal_handler)\n    # when running with no debugging, daemonize after signal handlers are registered\n    if not debug_flag:\n        if os.fork():\n            os._exit(0)\n    else:\n        LOG.debug(f'Debugging enabled, running in foreground')\n\n    mapped_chars = [get_uinput_event(code) for code in hex_chars if get_uinput_event(code) is not None]\n    def_buttons = ['left', 'right', 'up', 'down', 'a', 'b', 'x', 'y', 'pageup', 'pagedown']\n    joy_map = {}\n    # add for each button the mapped keycode, based on the arguments received\n    for i, btn in enumerate(def_buttons):\n        if i < len(mapped_chars):\n            joy_map[btn] = mapped_chars[i]\n\n    LOG.debug(f'Joy map:\\n {joy_map}')\n    menu_swap = ra_btn_swap_config()\n    # if button A is <enter> and menu_swap_ok_cancel_buttons is true, swap buttons A and B functions\n    if menu_swap \\\n            and 'a' in joy_map.keys() \\\n            and 'b' in joy_map.keys() \\\n            and joy_map['a'] == '\\n':\n        joy_map['a'] = joy_map['b']\n        joy_map['b'] = '\\n'\n\n    # tell SDL that we don't want to grab and lock the keyboard\n    os.environ['SDL_INPUT_LINUX_KEEP_KBD'] = '1'\n\n    # disable the HIDAPI joystick driver in SDL\n    if not(SDL_USE_HIDAPI):\n        os.environ['SDL_JOYSTICK_HIDAPI'] = '0'\n\n    # tell SDL to not add any signal handlers for TERM/INT\n    os.environ['SDL_NO_SIGNAL_HANDLERS'] = '1'\n\n    configs = get_all_ra_config(def_buttons)\n\n    if SDL_Init(SDL_INIT_JOYSTICK) < 0:\n        LOG.error(f'Error in SDL_Init: {SDL_GetError()}')\n        exit(2)\n\n    if LOG.isEnabledFor(logging.DEBUG):\n        sdl_ver = version.SDL_version()\n        version.SDL_GetVersion(byref(sdl_ver))\n        wrapper_version = '.'.join(str(i) for i in version_info)\n        LOG.debug(f'Using SDL Version {sdl_ver.major}.{sdl_ver.minor}.{sdl_ver.patch}, PySDL2 version {wrapper_version}')\n\n    if joystick.SDL_NumJoysticks() < 1:\n        LOG.debug(f'No available joystick devices found on startup')\n\n    event_loop(configs, joy_map)\n\n    SDL_QuitSubSystem(SDL_INIT_JOYSTICK)\n    SDL_Quit()\n    return 0\n\n\nif __name__ == \"__main__\":\n    sys.exit(main())\n"
  },
  {
    "path": "scriptmodules/admin/joy2key/osk.py",
    "content": "#!/usr/bin/env python3\n\"\"\"\nThis file is part of The RetroPie Project\nThe RetroPie Project is the legal property of its developers, whose names are\ntoo numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\nSee the LICENSE.md file at the top-level directory of this distribution and\nhttps://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md.\n\nOnScreen Keyboard console utility.\n\nAllows the user to enter a string (ASCII) and outputs the string.\nIt should be wrapped by 'joy2key' helper script,\nso that the gamepad can be used to navigate and enter the necessary characters.\n\nKeys:\n - directional keys to move around\n - Enter to select a key / press a button\n - Esc to exit the form\n\nIt uses the [URWID](https://urwid.org) Python library to show a nice console based keyboard.\n\n\nExample usage:\n <script> WindowTitle StringName [min char number]\n\nExit code can be:\n - 0 (success), the string entered by the user is written to STDERR\n - 1 (cancel/error) if the user chose cancel to exit\n\"\"\"\n\nimport sys\n\nfrom os import get_terminal_size\nfrom argparse import ArgumentParser\n\nimport urwid\nfrom urwid.widget import Text, Divider, FLOW\nfrom urwid.container import Columns, Frame, GridFlow, Overlay, Pile\nfrom urwid.decoration import AttrMap, AttrWrap, Filler, Padding\nfrom urwid.graphics import LineBox\nfrom urwid.signals import connect_signal\nfrom urwid.command_map import ACTIVATE\n\n\nASCII_BLOCK = '█'\n\n# What we consider a small screen\nSMALL_SCREEN_COLS = 43\nSMALL_SCREEN_ROWS = 22\n\n\"\"\"\nColors used in the application controls\n\"\"\"\nPALETTE = [\n    # Input box: border, text and prompt\n    ('input',      'dark gray', 'light gray'),\n    ('input text', 'black',     'light gray'),\n    ('prompt',     'dark red',  'dark cyan' ),\n\n    # Body\n    ('body',     'black',  'light gray'),\n    ('bg',       'white',  'dark blue'),\n\n    # Focused key\n    ('focus key', 'white', 'dark blue'),\n\n    # Header\n    ('header',      'light cyan', 'dark blue'),\n    ('bold header', 'dark cyan',  'dark blue'),\n\n    # Buttons\n    ('button',         'black',     'light gray'),\n    ('selected',       'white',     'dark blue' ),\n    ('label',          'dark gray', 'light gray'),\n    ('label selected', 'yellow',    'dark blue' ),\n\n    # Error dialog\n    ('error', 'dark red', 'light gray')\n]\n\n\nclass CenteredButton(urwid.WidgetWrap):\n    \"\"\"\n    Custom button class that:\n      * centers the label text\n      * allows to disable the left/righ button margins/characters\n      * disables the 'space' key handling\n    \"\"\"\n    def selectable(self):\n        return True\n\n    def sizing(self):\n        return frozenset([FLOW])\n\n    signals = [\"click\"]\n\n    def __init__(self, label, on_press=None, user_data=None, delimiters=True):\n        self._label = Text(label, align='center')\n\n        if delimiters:\n            cols = Columns(\n                [\n                    ('fixed', 1, Text(\"<\")),\n                    self._label,\n                    ('fixed', 1, Text(\">\"))\n                ],\n                dividechars=1)\n        else:\n            cols = self._label\n\n        super().__init__(cols)\n\n        if on_press:\n            connect_signal(self, 'click', on_press, user_data)\n\n    # The rest of the methods are taken from urwid.Button\n\n    def set_label(self, label):\n        self._label.set_text(label)\n\n    def get_label(self):\n        return self._label.text\n    label = property(get_label)\n\n    def keypress(self, size, key):\n        # don't activate with the 'Space' key\n        if self._command_map[key] != ACTIVATE or key == ' ':\n            return key\n\n        self._emit('click')\n\n    def mouse_event(self, size, event, button, x, y, focus):\n        return False\n\n\nclass KeyButton(CenteredButton):\n    \"\"\"\n    Custom button class to model a keyboard key\n    It has primary and secondary key values, returned based on the shift state\n    \"\"\"\n    def __init__(self, text, primary=None, secondary=None, on_press=None, user_data=None):\n        super().__init__(text, on_press, user_data, delimiters=False)\n\n        # store the primary and secondary key values\n        if primary is None:\n            self.primary_val = text\n        else:\n            self.primary_val = primary\n\n        # calculate the secondary value when the label is a letter\n        if secondary is None and len(text) == 1:\n            self.secondary_val = text.upper()\n        else:\n            self.secondary_val = secondary\n\n    def shift(self, shifted):\n        \"\"\"\n        Simulate a shift key press, changing the key's label\n        This may change the button's appearance\n        \"\"\"\n        if (shifted\n                and self.secondary_val is not None\n                and len(self.secondary_val.strip()) > 0):\n            self.set_label(self.secondary_val)\n\n        if (not shifted\n                and self.primary_val is not None\n                and len(self.primary_val.strip()) > 0):\n            self.set_label(self.primary_val)\n\n    def get_value(self, shifted):\n        if shifted and self.secondary_val:\n            return self.secondary_val\n\n        if not shifted and self.primary_val:\n            return self.primary_val\n\n\nclass WrappableColumns(Columns):\n    \"\"\"\n    Custom Columns class\n    Adds the ability to wrap-around the children (left-right) when navigating\n    \"\"\"\n    def keypress(self, size, key):\n        if self.__super.keypress(size, key):\n            if key not in ('left', 'right'):\n                return key\n\n            # we have a key, so it wasn't handled by any parent container\n            # handle 'left'/'right' ourselves for cursor wrapping\n            if key in ('left'):\n                # iterate from last widget to first\n                widgets = list(range(len(self.contents) - 1, -1, -1))\n            else:\n                # iterate from first widget to last\n                widgets = list(range(0, len(self.contents)))\n\n            # Find the 1st selectable widget and focus it\n            for i in widgets:\n                if not self.contents[i][0].selectable():\n                    continue\n\n                self.focus_position = i\n                break\n\n\nclass ViewExit(Exception):\n    pass\n\n\nclass OSK:\n    \"\"\"\n    Main class for the on-screen keyboard application\n    \"\"\"\n\n    def __init__(self, title, input_title, input_value, min_chars=8, dim=False):\n        \"\"\"\n        :param title: the string used in the application heading\n        :param input_title: the name of the input string being captured (e.g. Password)\n        :param input_value: existing string to populate the input\n        :param min_chars: minimum number of characters for a valid string (default: 8)\n        :param dim: optimize for a smaller screen (True/False)\n        \"\"\"\n        self._input_title = input_title\n        self._input_value = input_value\n        self._min_chars = min_chars\n        self.small_display = dim\n        self.def_keys = []\n        self.frame = self.setup_frame(title, input_title, input_value)\n        self.pop_up = self.setup_popup(\"Error\")\n\n        # Create the main view, overlaying the popup widget with the main view\n        view = Overlay(self.pop_up, self.frame, 'center', None, 'middle', None)\n\n        self.view = view\n\n    def setup_frame(self, title, input_title, input_value):\n        \"\"\"\n        Creates the main view, with a 3 horizontal pane container (Frame)\n        \"\"\"\n        self.keys = []  # List of keys added to the OSK\n        self._shift = False  # OSK Shift key state\n\n        # title frame (header) uses a LineBox with just the bottom line enabled\n        # if we're on a small display, use a simple Text with Padding\n        if self.small_display:\n            header = Padding(Text(title, align='center'))\n\n        else:\n            header = LineBox(Text(title),\n                             tline=None, rline=' ', lline=' ',\n                             trcorner=' ', tlcorner=' ', blcorner='', brcorner='')\n\n        header = AttrWrap(header, 'header')\n\n        # Body frame, containing the input and the OSK widget\n        input = Text([('input text', ''), ('prompt', ASCII_BLOCK)])\n        if input_value != '':\n            input.set_text([('input text', input_value), ('prompt', ASCII_BLOCK)])\n\n        self.input = input\n\n        Key = self.add_osk_key  # alias the key creation function\n        osk = Pile([\n                # 1st keyboard row\n                WrappableColumns([\n                    (1, Text(\" \")),\n                    (3, Key('`', shifted='~')),\n                    (3, Key('1', shifted='!')),\n                    (3, Key('2', shifted='@')),\n                    (3, Key('3', shifted='#')),\n                    (3, Key('4', shifted='$')),\n                    (3, Key('5', shifted='%')),\n                    (3, Key('6', shifted='^')),\n                    (3, Key('7', shifted='&')),\n                    (3, Key('8', shifted='*')),\n                    (3, Key('9', shifted='(')),\n                    (3, Key('0', shifted=')')),\n                    (3, Key('-', shifted='_')),\n                    (3, Key('=', shifted='+')),\n                    (1, Text(\" \")),\n                    ], 0),\n                Divider(),\n                # 2nd keyboard row\n                WrappableColumns([\n                    (2, Text(\" \")),\n                    (3, Key('q')),\n                    (3, Key('w')),\n                    (3, Key('e')),\n                    (3, Key('r')),\n                    (3, Key('t')),\n                    (3, Key('y')),\n                    (3, Key('u')),\n                    (3, Key('i')),\n                    (3, Key('o')),\n                    (3, Key('p')),\n                    (3, Key('[', shifted='{')),\n                    (3, Key(']', shifted='}')),\n                    (3, Key('\\\\', shifted='|')),\n                    ], 0),\n                Divider(),\n                # 3rd keyboard row\n                WrappableColumns([\n                    (3, Text(\" \")),\n                    (3, Key('a')),\n                    (3, Key('s')),\n                    (3, Key('d')),\n                    (3, Key('f')),\n                    (3, Key('g')),\n                    (3, Key('h')),\n                    (3, Key('j')),\n                    (3, Key('k')),\n                    (3, Key('l')),\n                    (3, Key(';', shifted=':')),\n                    (3, Key('\\'', shifted='\"')),\n                    ], 0),\n                Divider(),\n                # 4th keyboard row\n                WrappableColumns([\n                    (4, Text(\" \")),\n                    (3, Key('z')),\n                    (3, Key('x')),\n                    (3, Key('c')),\n                    (3, Key('v')),\n                    (3, Key('b')),\n                    (3, Key('n')),\n                    (3, Key('m')),\n                    (3, Key(',', shifted='<')),\n                    (3, Key('.', shifted='>')),\n                    (3, Key('/', shifted='?'))\n                    ], 0),\n                Divider(),\n                # 5th (last) keyboard row\n                WrappableColumns([\n                    (1, Text(\" \")),\n                    (9, Key('↑ Shift', shifted='↑ SHIFT', callback=self.shift_key_press)),\n                    (2, Text(\" \")),\n                    (15, Key('Space', value=' ', shifted=' ')),\n                    (2, Text(\" \")),\n                    (10, Key('Delete ←', callback=self.bksp_key_press)),\n                    ], 0),\n                Divider()\n              ])\n\n        if self.small_display:\n            # small displays: remove last divider line\n            osk.contents.pop(len(osk.contents) - 1)\n\n        osk = Padding(osk, 'center', 40)\n\n        # setup the text input and the buttons\n        input=AttrWrap(LineBox(input), 'input')\n        input = Padding(AttrWrap(input, 'input text'), 'center', ('relative', 80), min_width=30)\n        ok_btn = self.setup_button(\"OK\", self.button_press, exitcode=0)\n        cancel_btn = self.setup_button(\"Cancel\", self.button_press, exitcode=1)\n\n        # setup the main OSK area, depending on the screen size\n        if self.small_display:\n            body = Pile([\n                        Text(f'{input_title}', align='center'),\n                        input,\n                        Divider(),\n                        osk,\n                        Divider(),\n                        GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),\n                        Divider()\n                        ])\n        else:\n            body = Pile([\n                        Divider(), input,\n                        Divider(), osk,\n                        LineBox(\n                            GridFlow([ok_btn, cancel_btn], 10, 2, 0, 'center'),\n                            bline=None, lline=None, rline=None, tlcorner='─', trcorner='─')\n                        ])\n            body = LineBox(body, f'{input_title}')\n\n        body = AttrWrap(body, 'body')  # Style the main OSK area\n\n        # wrap and align the main OSK in the frame\n        body = Padding(body, 'center', 55, min_width=42)\n        body = Filler(body, 'middle')\n\n        body = AttrWrap(body, 'bg')  # Style the body containing the OSK\n\n        frame = Frame(body, header=header, focus_part='body')\n\n        return frame\n\n    def setup_button(self, label, callback, exitcode=None):\n        \"\"\"\n        Creates a button and applies the styling\n        \"\"\"\n        button = CenteredButton(('label', label), callback, delimiters=True)\n        button.exitcode = exitcode\n        button = AttrMap(button, {None: 'button'}, {None: 'selected', 'label': 'label selected'})\n\n        return button\n\n    def setup_popup(self, title):\n        \"\"\"\n        Overlays a dialog box on top of the working view using a Frame\n        \"\"\"\n\n        # Header\n        if self.small_display:\n            header = Padding(Text(title, align='center'))\n        else:\n            header = LineBox(Text(title),\n                             tline=None, rline=' ', lline=' ',\n                             trcorner=' ', tlcorner=' ', blcorner='', brcorner='')\n\n        header = AttrWrap(header, 'header')\n\n        # Body\n        error_text = Text(\"\", align='center')\n        # register the Text widget with the application, so we can change it\n        self._error = error_text\n\n        error_text = AttrWrap(error_text, 'error')\n        body = Pile([\n                    Divider(), error_text,\n                    Divider(),\n                    LineBox(\n                        GridFlow([self.setup_button(\"Dismiss\", self.close_popup)],\n                                 12, 2, 0, 'center'),\n                        bline=None, lline=None, rline=None, tlcorner='─', trcorner='─')\n                    ])\n\n        body = LineBox(body)\n        body = AttrWrap(body, 'body')\n\n        # on small displays let the popup fill the screen (horizontal)\n        if self.small_display:\n            body = Padding(Filler(body, 'middle'), 'center')\n        else:\n            body = Padding(Filler(body, 'middle'), 'center', ('relative', 50))\n\n        body = AttrWrap(body, 'bg')\n\n        # Main dialog widget\n        dialog = Frame(\n            body,\n            header=header,\n            focus_part='body'\n        )\n\n        return dialog\n\n    def close_popup(self, widget=None):\n        self.loop.widget = self.frame\n\n    def open_popup(self):\n        self.loop.widget = self.pop_up\n\n    def set_shifted(self, state):\n        self._shift = state\n        for b in self.keys:\n            b.shift(state)\n\n    def get_shifted(self):\n        return self._shift\n\n    # create a class property for the shifted state\n    shifted = property(get_shifted, set_shifted, \"The Shift key state\")\n\n    def set_error_text(self, message):\n        \"\"\"\n        Sets the error message displayed by 'pop_up'\n        \"\"\"\n        self._error.set_text(message)\n\n    def shift_key_press(self, key=None):\n        \"\"\"\n        Toggle the Shift key, update display of all printable keys\n        \"\"\"\n        self.shifted = not self.shifted\n\n    def button_press(self, btn):\n        txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)\n\n        # check the input string length when OK is asking to exit\n        if len(txt) < self._min_chars and btn.exitcode == 0:\n            self.set_error_text(f\"{self._input_title} must have at least {self._min_chars} characters\")\n            self.open_popup()\n            return\n\n        raise ViewExit(btn.exitcode)\n\n    def bksp_key_press(self, key=None):\n        \"\"\"\n        Handle the pressing of the erase key\n        Remove one char from the end of the text input\n        \"\"\"\n        txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)\n\n        if len(txt) > 0:\n            txt = txt[:-1]\n\n        self.input.set_text([('input text', txt), ('prompt', ASCII_BLOCK)])\n\n    def def_key_press(self, key):\n        \"\"\"\n        Default OSK key press handler, it adds the pressed key to the text input\n        \"\"\"\n        _inner = key.get_value(self.shifted)\n        if _inner is None:\n            return\n\n        # remove the final block from the input control and append the value\n        txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)\n        self.input.set_text([('input text', txt + _inner), ('prompt', ASCII_BLOCK)])\n\n        # when keyboard is shifted, toggle the shift key after a key press\n        if self.shifted:\n            self.shift_key_press()\n\n    def add_osk_key(self, key, value=None, shifted=None, callback=None):\n        \"\"\"\n        Method to create a KeyButton with the primary/secondary values and the callback handler\n        \"\"\"\n        if callback is None:\n            callback = self.def_key_press\n\n        btn = KeyButton(key, primary=value, secondary=shifted, on_press=callback)\n\n        # store the key internally, so we can shift it when needed\n        self.keys.append(btn)\n        self.def_keys.append(btn.get_value(False))\n        self.def_keys.append(btn.get_value(True))\n\n        return AttrWrap(btn, None, 'focus key')\n\n    def unhandled_key(self, key):\n        \"\"\"\n        Keyboard input handling\n        \"\"\"\n        # handle the normal key press\n        if len(key) == 1 and ord(key) in range(32, 127):\n            txt = self.input.get_text()[0].rstrip(ASCII_BLOCK)\n            self.input.set_text([('input text', txt + key), ('prompt', ASCII_BLOCK)])\n            return\n\n        if key == 'backspace':\n            self.bksp_key_press()\n\n        # handle Esccape:\n        # - close the error dialog, if in view, and return to main form\n        # - exit application if on main form\n        if str(key) in ('esc'):\n            if self.loop.widget == self.pop_up:\n                self.close_popup()\n            else:\n                raise urwid.ExitMainLoop()\n\n        # unhandled, pass it on\n        return key\n\n    def check_wpa_chars(self):\n        \"\"\"\n        Debugging method to check whether the OSK provides all valid WPA chars\n\n        All allowed WPA chars(https://en.wikipedia.org/wiki/Wi-Fi_Protected_Access#cite_note-21):\n        Each character in the passphrase must have an encoding in the range of 32 to 126 (decimal), inclusive\n        \"\"\"\n        wpa_chars = []\n        for i in range(32, 127):\n            wpa_chars.append(i)\n        print(f' All allowed WPA password characters:\\n {[chr(k) for k in wpa_chars]}')\n\n        missing = False\n        for k in wpa_chars:\n            if chr(k) not in self.def_keys:\n                print(f' {chr(k)} is not provided !')\n                missing = True\n\n        if not missing:\n            print(f'All chars are handled !')\n\n    def on_exit(self, exitcode):\n        \"\"\"\n        On exit, return an exitcode and - conditionally - the input text\n        \"\"\"\n        if exitcode != 0:\n            return exitcode, ''\n        else:\n            return exitcode, self.input.get_text()[0].rstrip(ASCII_BLOCK)\n\n    def main(self):\n        \"\"\"\n        Runs the event/display loop for our view\n        When the OK/Cancel buttons are used, 'ViewExit' will be raised,\n        otherwise assume the user has used 'Esc' to close the dialog\n        \"\"\"\n        self.loop = urwid.MainLoop(self.frame, PALETTE, unhandled_input=self.unhandled_key)\n        try:\n            self.loop.run()\n            return self.on_exit(1)\n        except ViewExit as e:\n            return self.on_exit(e.args[0])\n\n\ndef parse_arguments(args):\n    parser = ArgumentParser(description=\"Reads a string using an On Screen Keyboard\")\n\n    parser.add_argument('--backtitle', type=str, help='Window title', required=True)\n    parser.add_argument('--inputbox', type=str, help='Name of the string being captured', required=True)\n    parser.add_argument(\n        '--minchars', type=int, nargs='?',\n        help='Minimum number of characters needed (default: %(default)s)',\n        default=8)\n    parser.add_argument('input', type=str, help='Input value', default='', nargs='?')\n    args = parser.parse_args()\n    return args.backtitle, args.inputbox, args.minchars, args.input\n\n\ndef main():\n    backtitle, inputbox, minchars, value = parse_arguments(sys.argv)\n    # get the terminal size to detect small display\n    cols, rows = get_terminal_size(0)\n\n    osk = OSK(backtitle, inputbox, value, minchars, (cols < SMALL_SCREEN_COLS or rows < SMALL_SCREEN_ROWS))\n    exitcode, exitstring = osk.main()\n\n    # print the input text when returned by the application\n    if exitstring:\n        sys.stderr.write(exitstring + \"\\n\")\n\n    sys.exit(exitcode)\n\n\nif __name__ == \"__main__\":\n    main()\n"
  },
  {
    "path": "scriptmodules/admin/joy2key.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"joy2key\"\nrp_module_desc=\"Provides joystick to keyboard conversion for navigation of RetroPie dialog menus\"\nrp_module_section=\"core\"\n\nfunction _update_hook_joy2key() {\n    # make sure joy2key is always updated when updating retropie-setup\n    rp_isInstalled \"$md_id\" && rp_callModule \"$md_id\"\n}\n\nfunction depends_joy2key() {\n    local depends=(python3-urwid python3-uinput)\n    # 'python3-sdl2' might not be available\n    # it's packaged in Debian starting with version 11 (Bullseye)\n    local p_ver\n    p_ver=\"$(apt-cache madison python3-sdl2 | cut -d\" \" -f3 | head -n1)\"\n    if [[ -n \"$p_ver\" ]]; then\n        depends+=(python3-sdl2)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction install_bin_joy2key() {\n    local file\n    for file in \"joy2key.py\" \"joy2key_sdl.py\" \"osk.py\"; do\n        cp \"$md_data/$file\" \"$md_inst/\"\n        chmod +x \"$md_inst/$file\"\n        python3 -m compileall \"$md_inst/$file\"\n    done\n\n    local wrapper=\"$md_inst/joy2key\"\n    cat >\"$wrapper\" <<_EOF_\n#!/bin/bash\nmode=\"\\$1\"\n[[ -z \"\\$mode\" ]] && mode=\"start\"\nshift\n\n# allow overriding joystick device via __joy2key_dev env (by default will use /dev/input/jsX which will scan all)\ndevice=\"/dev/input/jsX\"\n[[ -n \"\\$__joy2key_dev\" ]] && device=\"\\$__joy2key_dev\"\n\nparams=(\"\\$@\")\nif [[ \"\\${#params[@]}\" -eq 0 ]]; then\n    # Default button-to-keyboard mappings:\n    # * cursor keys for axis/dpad\n    # * enter, space, esc and tab for buttons 'a', 'b', 'x' and 'y'\n    # * page up/page down for buttons 5,6 (shoulder buttons)\n    params=(kcub1 kcuf1 kcuu1 kcud1 0x0a 0x20 0x1b 0x09 kpp knp)\nfi\n\nscript=\"joy2key_sdl.py\"\ngrep --basic-regexp --quiet --no-messages '^legacy_joy2key[[:space:]]*=[[:space:]]*\"\\?1\"\\?' $configdir/all/runcommand.cfg && script=\"joy2key.py\"\n\ncase \"\\$mode\" in\n    start)\n        if pgrep -f \"\\$script\" &>/dev/null; then\n            \"\\$0\" stop\n        fi\n        \"$md_inst/\\$script\" \"\\$device\" \"\\${params[@]}\" || exit 1\n        ;;\n    stop)\n        if pid=\\$(pgrep -f \"\\$script\"); then\n            /sbin/start-stop-daemon --stop --oknodo --pid \\$pid --retry 1\n        fi\n        ;;\nesac\nexit 0\n_EOF_\n    chmod +x \"$wrapper\"\n    if ! grep -q \"uinput\" /etc/modules; then\n        addLineToFile \"uinput\" \"/etc/modules\"\n    fi\n    # add an udev rule to give 'input' group write access to `/dev/uinput`\n    echo 'KERNEL==\"uinput\", MODE=\"0660\", GROUP=\"input\"' > /etc/udev/rules.d/80-rpi-uinput.rules\n    udevadm control --reload\n\n    modprobe uinput\n\n    # make sure the install user is part of 'input' group\n    usermod -a -G input \"$__user\"\n\n    joy2keyStart\n}\n\nfunction remove_joy2key() {\n    joy2keyStop\n}\n"
  },
  {
    "path": "scriptmodules/admin/setup.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"setup\"\nrp_module_desc=\"GUI based setup for RetroPie\"\nrp_module_section=\"\"\n\nfunction _setup_gzip_log() {\n    setsid tee >(setsid gzip --stdout >\"$1\")\n}\n\nfunction rps_logInit() {\n    if [[ ! -d \"$__logdir\" ]]; then\n        if mkdir -p \"$__logdir\"; then\n            chown \"$__user\":\"$__group\" \"$__logdir\"\n        else\n            fatalError \"Couldn't make directory $__logdir\"\n        fi\n    fi\n\n    # remove all but the last 20 logs\n    find \"$__logdir\" -type f | sort | head -n -20 | xargs -d '\\n' --no-run-if-empty rm\n\n    local now=$(date +'%Y-%m-%d_%H%M%S')\n    logfilename=\"$__logdir/rps_$now.log.gz\"\n    touch \"$logfilename\"\n    chown \"$__user\":\"$__group\" \"$logfilename\"\n    time_start=$(date +\"%s\")\n}\n\nfunction rps_logStart() {\n    echo -e \"Log started at: $(date -d @$time_start)\\n\"\n    echo \"RetroPie-Setup version: $__version ($(sudo -u \"$__user\" git -C \"$scriptdir\" log -1 --pretty=format:%h))\"\n    echo \"System: $__platform ($__platform_arch) - $__os_desc - $(uname -a)\"\n}\n\nfunction rps_logEnd() {\n    time_end=$(date +\"%s\")\n    echo\n    echo \"Log ended at: $(date -d @$time_end)\"\n    date_total=$((time_end-time_start))\n    local hours=$((date_total / 60 / 60 % 24))\n    local mins=$((date_total / 60 % 60))\n    local secs=$((date_total % 60))\n    echo \"Total running time: $hours hours, $mins mins, $secs secs\"\n}\n\nfunction rps_printInfo() {\n    local log=\"$1\"\n    reset\n    if [[ ${#__ERRMSGS[@]} -gt 0 ]]; then\n        printMsgs \"dialog\" \"${__ERRMSGS[@]}\"\n        [[ -n \"$log\" ]] && printMsgs \"dialog\" \"Please see $log for more in depth information regarding the errors.\"\n    fi\n    if [[ ${#__INFMSGS[@]} -gt 0 ]]; then\n        printMsgs \"dialog\" \"${__INFMSGS[@]}\"\n    fi\n    __ERRMSGS=()\n    __INFMSGS=()\n}\n\nfunction depends_setup() {\n    # check for VERSION file - if it doesn't exist we will run the post_update script as it won't be triggered\n    # on first upgrade to 4.x\n    if [[ ! -f \"$rootdir/VERSION\" ]]; then\n        joy2keyStop\n        exec \"$scriptdir/retropie_packages.sh\" setup post_update gui_setup\n    fi\n\n    if  [[ \"$__os_debian_ver\" -le 10 ]] && isPlatform \"rpi\" && isPlatform \"mesa\" && ! isPlatform \"rpi4\"; then\n        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.\"\n    fi\n\n    if [[ \"$__os_debian_ver\" -eq 8 ]]; then\n        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).\"\n    fi\n\n    if [[ \"$__os_debian_ver\" -eq 9 ]] && [[ \"$__os_id\" == \"Raspbian\" ]]; then\n        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.\"\n    fi\n\n    # make sure user has the correct group permissions\n    if ! isPlatform \"x11\"; then\n        local group\n        for group in input video; do\n            if ! hasFlag \"$(groups $__user)\" \"$group\"; then\n                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\"\n            fi\n        done\n    fi\n\n    # set a global __setup to 1 which is used to adjust package function behaviour if called from the setup gui\n    __setup=1\n\n    # print any pending msgs - eg during module scanning which wouldn't be seen otherwise\n    rps_printInfo\n}\n\nfunction updatescript_setup()\n{\n    clear\n    chown -R \"$__user\":\"$__group\" \"$scriptdir\"\n    printHeading \"Fetching latest version of the RetroPie Setup Script.\"\n    pushd \"$scriptdir\" >/dev/null\n    if [[ ! -d \".git\" ]]; then\n        printMsgs \"dialog\" \"Cannot find directory '.git'. Please clone the RetroPie Setup script via 'git clone https://github.com/RetroPie/RetroPie-Setup.git'\"\n        popd >/dev/null\n        return 1\n    fi\n    local error\n    if ! error=$(sudo -u \"$__user\" git pull --ff-only 2>&1 >/dev/null); then\n        printMsgs \"dialog\" \"Update failed:\\n\\n$error\"\n        popd >/dev/null\n        return 1\n    fi\n    popd >/dev/null\n\n    printMsgs \"dialog\" \"Fetched the latest version of the RetroPie Setup script.\"\n    return 0\n}\n\nfunction post_update_setup() {\n    local return_func=(\"$@\")\n\n    joy2keyStart\n\n    echo \"$__version\" >\"$rootdir/VERSION\"\n\n    clear\n    local logfilename\n    rps_logInit\n    {\n        rps_logStart\n        # run _update_hook_id functions - eg to fix up modules for retropie-setup 4.x install detection\n        printHeading \"Running post update hooks\"\n        rp_updateHooks\n        rps_logEnd\n    } &> >(_setup_gzip_log \"$logfilename\")\n    rps_printInfo \"$logfilename\"\n\n    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.\"\n\n    # return to set return function\n    \"${return_func[@]}\"\n}\n\nfunction package_setup() {\n    local id=\"$1\"\n    local default=\"\"\n\n    if ! rp_isEnabled \"$id\"; then\n        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[*]}\"\n        return 1\n    fi\n\n    # associative array so we can pull out the messages later for the confirmation requester\n    declare -A option_msgs=(\n        [\"U\"]=\"\"\n        [\"B\"]=\"Install from pre-compiled binary\"\n        [\"S\"]=\"Install from source\"\n    )\n\n    while true; do\n        local options=()\n\n        local status\n\n        local has_binary=0\n        local has_net=0\n\n        isConnected && has_net=1\n\n        # for modules with nonet flag that don't need to download data, we force has_net to 1, so we get install options\n        hasFlag \"${__mod_info[$id/flags]}\" \"nonet\" && has_net=1\n\n        if [[ \"$has_net\" -eq 1 ]]; then\n            dialog --backtitle \"$__backtitle\" --infobox \"Checking for updates for $id ...\" 3 60 >/dev/tty\n            rp_hasBinary \"$id\"\n            local ret=\"$?\"\n            [[ \"$ret\" -eq 0 ]] && has_binary=1\n            [[ \"$ret\" -eq 2 ]] && has_net=0\n        fi\n\n        local is_installed=0\n\n        local pkg_origin=\"\"\n        local pkg_date=\"\"\n        if ! rp_isInstalled \"$id\"; then\n            status=\"Not installed\"\n        else\n            is_installed=1\n\n            rp_loadPackageInfo \"$id\"\n            pkg_origin=\"${__mod_info[$id/pkg_origin]}\"\n            pkg_date=\"${__mod_info[$id/pkg_date]}\"\n            [[ -n \"$pkg_date\" ]] && pkg_date=\"$(date -u -d \"$pkg_date\" 2>/dev/null)\"\n\n            status=\"Installed - via $pkg_origin\"\n\n            [[ -n \"$pkg_date\" ]] && status+=\" (built: $pkg_date)\"\n\n            if [[ \"$has_net\" -eq 1 ]]; then\n                rp_hasNewerModule \"$id\" \"$pkg_origin\"\n                local has_newer=\"$?\"\n                case \"$has_newer\" in\n                    0)\n                        status+=\"\\nUpdate is available.\"\n                        option_msgs[\"U\"]=\"Update (from $pkg_origin)\"\n                        ;;\n                    1)\n                        status+=\"\\nYou are running the latest $pkg_origin.\"\n                        option_msgs[\"U\"]=\"Re-install (from $pkg_origin)\"\n                        ;;\n                    2)\n                        if [[ \"$pkg_origin\" == \"unknown\" ]]; then\n                            if [[ \"$has_binary\" -eq 1 ]]; then\n                                pkg_origin=\"binary\"\n                            else\n                                pkg_origin=\"source\"\n                            fi\n                        fi\n                        option_msgs[\"U\"]=\"Update (from $pkg_origin)\"\n                        status+=\"\\nUpdate may be available (Unable to check for this package).\"\n                        ;;\n                    3)\n                        has_net=0\n                        ;;\n                esac\n            fi\n        fi\n\n        if [[ \"$has_net\" -eq 1 ]]; then\n            if [[ \"$is_installed\" -eq 1 ]]; then\n                options+=(U \"${option_msgs[\"U\"]}\")\n            fi\n\n            if [[ \"$pkg_origin\" != \"binary\" && \"$has_binary\" -eq 1 ]]; then\n                options+=(B \"${option_msgs[\"B\"]}\")\n            fi\n\n            if [[ \"$pkg_origin\" != \"source\" ]] && fnExists \"sources_${id}\"; then\n                options+=(S \"${option_msgs[S]}\")\n           fi\n        else\n            status+=\"\\nInstall options disabled:\\n$__NET_ERRMSG\"\n        fi\n\n        if [[ \"$is_installed\" -eq 1 ]]; then\n            if fnExists \"gui_${id}\"; then\n                options+=(C \"Configuration / Options\")\n            fi\n            options+=(X \"Remove\")\n        fi\n\n        if [[ -d \"$__builddir/$id\" ]]; then\n            options+=(Z \"Clean source folder\")\n        fi\n\n        local help=\"${__mod_info[$id/desc]}\\n\\n${__mod_info[$id/help]}\"\n        if [[ -n \"$help\" ]]; then\n            options+=(H \"Package help\")\n        fi\n\n        if [[ \"$is_installed\" -eq 1 ]]; then\n            options+=(V \"Package version information\")\n        fi\n\n        cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --default-item \"$default\" --menu \"Choose an option for $id\\n$status\" 22 76 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        local logfilename\n\n        case \"$choice\" in\n            U|B|S)\n                dialog --defaultno --yesno \"Are you sure you want to ${option_msgs[$choice]}?\" 22 76 2>&1 >/dev/tty || continue\n                local mode\n                case \"$choice\" in\n                    U) mode=\"_auto_\" ;;\n                    B) mode=\"_binary_\" ;;\n                    S) mode=\"_source_\" ;;\n                esac\n                clear\n                rps_logInit\n                {\n                    rps_logStart\n                    rp_installModule \"$id\" \"$mode\"\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            C)\n                rps_logInit\n                {\n                    rps_logStart\n                    rp_callModule \"$id\" gui\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            X)\n                local text=\"Are you sure you want to remove $id?\"\n                case \"${__mod_info[$id/section]}\" in\n                    core)\n                        text+=\"\\n\\nWARNING - core packages are needed for RetroPie to function!\"\n                        ;;\n                    depends)\n                        text+=\"\\n\\nWARNING - this package is required by other RetroPie packages - removing may cause other packages to fail.\"\n                        text+=\"\\n\\nNOTE: This will be reinstalled if missing when updating packages that require it.\"\n                        ;;\n                esac\n                dialog --defaultno --yesno \"$text\" 22 76 2>&1 >/dev/tty || continue\n                rps_logInit\n                {\n                    rps_logStart\n                    clear\n                    rp_callModule \"$id\" remove\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            H)\n                printMsgs \"dialog\" \"$help\"\n                ;;\n            V)\n                local info\n                rp_loadPackageInfo \"$id\"\n                read -r -d '' info << _EOF_\nPackage Origin: ${__mod_info[$id/pkg_origin]}\nBuild Date: ${__mod_info[$id/pkg_date]}\n\nBuilt from source via:\n\nType: ${__mod_info[$id/pkg_repo_type]}\nURL: ${__mod_info[$id/pkg_repo_url]}\nBranch: ${__mod_info[$id/pkg_repo_branch]}\nCommit: ${__mod_info[$id/pkg_repo_commit]}\nDate: ${__mod_info[$id/pkg_repo_date]}\n_EOF_\n               printMsgs \"dialog\" \"$info\"\n               ;;\n            Z)\n                rp_callModule \"$id\" clean\n                printMsgs \"dialog\" \"$__builddir/$id has been removed.\"\n                ;;\n            *)\n                break\n                ;;\n        esac\n\n    done\n}\n\nfunction section_gui_setup() {\n    local section=\"$1\"\n    local ids=()\n    case \"$section\" in\n        all|inst)\n            name=\"packages\"\n            local id\n            for id in \"${__mod_id[@]}\"; do\n                # if we are showing installed packaged, skip those that are not installed\n                [[ \"$section\" == \"inst\" ]] && ! rp_isInstalled \"$id\" && continue\n                # don't show packages from depends or modules with no section (admin)\n                ! [[ \"${__mod_info[$id/section]}\" =~ ^(depends|config|)$ ]] && ids+=(\"$id\")\n            done\n            ;;\n         *)\n            name=\"${__sections[$section]} packages\"\n            ids=($(rp_getSectionIds $section))\n            ;;\n    esac\n\n    local default=\"\"\n    local status=\"\"\n    local has_net=1\n    while true; do\n        local options=()\n        local pkgs=()\n\n        status=\"Please choose a package from below\"\n        if ! isConnected; then\n            status+=\"\\nInstall options disabled ($__NET_ERRMSG)\"\n            has_net=0\n        fi\n\n        local id\n        local num_pkgs=0\n        local info\n        local type\n        local last_type=\"\"\n        for id in \"${ids[@]}\"; do\n            local type=\"${__mod_info[$id/vendor]} - ${__mod_info[$id/type]}\"\n            # do a heading for each origin and module type\n            if [[ \"$last_type\" != \"$type\" ]]; then\n                info=\"$type\"\n                pkgs+=(\"----\" \"\\Z4$info ----\" \"Packages from $info\")\n                last_type=\"$type\"\n            fi\n            if ! rp_isEnabled \"$id\"; then\n                info=\"\\Z1$id\\Zn\"\n            else\n                if rp_isInstalled \"$id\"; then\n                    rp_loadPackageInfo \"$id\" \"pkg_origin\"\n                    local pkg_origin=\"${__mod_info[$id/pkg_origin]}\"\n\n                    info=\"$id (Installed - via $pkg_origin)\"\n                    ((num_pkgs++))\n                else\n                    info=\"$id\"\n                fi\n            fi\n            pkgs+=(\"${__mod_idx[$id]}\" \"$info\" \"$id - ${__mod_info[$id/desc]}\"$'\\n\\n'\"${__mod_info[$id/help]}\")\n        done\n\n        if [[ \"$has_net\" -eq 1 && \"$num_pkgs\" -gt 0 ]]; then\n            options+=(\n                U \"Update all installed $name\" \"This will update any installed $name. The packages will be updated by the method used previously.\"\n            )\n        fi\n\n        # allow installing an entire section except for drivers and dependencies - as it's probably a bad idea\n        if [[ \"$has_net\" -eq 1 && \"$section\" != \"driver\" && \"$section\" != \"depends\" ]]; then\n            # don't show \"Install all packages\" when we are showing only installed packages\n            if [[ \"$section\" != \"inst\" ]]; then\n                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.\")\n            fi\n            options+=(X \"Remove all installed $name\" \"X This will remove all installed $name.\")\n        fi\n\n        options+=(\"${pkgs[@]}\")\n\n        local cmd=(dialog --colors --backtitle \"$__backtitle\" --cancel-label \"Back\" --item-help --help-button --default-item \"$default\" --menu \"$status\" 22 76 16)\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        if [[ \"${choice[@]:0:4}\" == \"HELP\" ]]; then\n            # remove HELP\n            choice=\"${choice[@]:5}\"\n            # get id of menu item\n            default=\"${choice/%\\ */}\"\n            # remove id\n            choice=\"${choice#* }\"\n            printMsgs \"dialog\" \"$choice\"\n            continue\n        fi\n\n        default=\"$choice\"\n\n        local logfilename\n        case \"$choice\" in\n            U|I)\n                local mode=\"update\"\n                [[ \"$choice\" == \"I\" ]] && mode=\"install\"\n                dialog --defaultno --yesno \"Are you sure you want to $mode all installed $name?\" 22 76 2>&1 >/dev/tty || continue\n                rps_logInit\n                {\n                    rps_logStart\n                    for id in \"${ids[@]}\"; do\n                        ! rp_isEnabled \"$id\" && continue\n                        # if we are updating, skip packages that are not installed\n                        if [[ \"$mode\" == \"update\" ]]; then\n                            if rp_isInstalled \"$id\"; then\n                                rp_installModule \"$id\" \"_update_\"\n                            fi\n                        else\n                            rp_installModule \"$id\" \"_auto_\"\n                        fi\n                    done\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            X)\n                local text=\"Are you sure you want to remove all installed $name?\"\n                [[ \"$section\" == \"core\" ]] && text+=\"\\n\\nWARNING - core packages are needed for RetroPie to function!\"\n                dialog --defaultno --yesno \"$text\" 22 76 2>&1 >/dev/tty || continue\n                rps_logInit\n                {\n                    rps_logStart\n                    for id in \"${ids[@]}\"; do\n                        rp_isInstalled \"$id\" && rp_callModule \"$id\" remove\n                    done\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            ----)\n                ;;\n            *)\n                package_setup \"${__mod_id[$choice]}\"\n                ;;\n        esac\n\n    done\n}\n\nfunction config_gui_setup() {\n    local default\n    while true; do\n        local options=()\n        local id\n        for id in \"${__mod_id[@]}\"; do\n            # show all configuration modules and any installed packages with a gui function\n            if [[ \"${__mod_info[$id/section]}\" == \"config\" ]] || rp_isInstalled \"$id\" && rp_isEnabled \"$id\" && fnExists \"gui_$id\"; then\n                options+=(\"${__mod_idx[$id]}\" \"$id  - ${__mod_info[$id/desc]}\" \"${__mod_idx[$id]} ${__mod_info[$id/desc]}\")\n            fi\n        done\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --item-help --help-button --default-item \"$default\" --menu \"Choose an option\" 22 76 16)\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        if [[ \"${choice[@]:0:4}\" == \"HELP\" ]]; then\n            choice=\"${choice[@]:5}\"\n            default=\"${choice/%\\ */}\"\n            choice=\"${choice#* }\"\n            printMsgs \"dialog\" \"$choice\"\n            continue\n        fi\n\n        [[ -z \"$choice\" ]] && break\n\n        default=\"$choice\"\n        id=\"${__mod_id[$choice]}\"\n        local logfilename\n        rps_logInit\n        {\n            rps_logStart\n            if fnExists \"gui_$id\"; then\n                rp_callModule \"$id\" depends\n                rp_callModule \"$id\" gui\n            else\n                rp_callModule \"$id\" clean\n                rp_callModule \"$id\"\n            fi\n            rps_logEnd\n        } &> >(_setup_gzip_log \"$logfilename\")\n        rps_printInfo \"$logfilename\"\n    done\n}\n\nfunction update_packages_setup() {\n    clear\n    local id\n    for id in ${__mod_id[@]}; do\n        if rp_isInstalled \"$id\" && [[ \"${__mod_info[$id/section]}\" != \"depends\" ]]; then\n            rp_installModule \"$id\" \"_update_\"\n        fi\n    done\n}\n\nfunction check_connection_gui_setup() {\n    local ip=\"$(getIPAddress)\"\n    if [[ -z \"$ip\" ]]; then\n        printMsgs \"dialog\" \"Sorry, you don't seem to be connected to the internet, so installing/updating is not available.\"\n        return 1\n    fi\n    return 0\n}\n\nfunction update_packages_gui_setup() {\n    local update=\"$1\"\n    if [[ \"$update\" != \"update\" ]]; then\n        ! check_connection_gui_setup && return 1\n        dialog --defaultno --yesno \"Are you sure you want to update installed packages?\" 22 76 2>&1 >/dev/tty || return 1\n        updatescript_setup || return 1\n        # restart at post_update and then call \"update_packages_gui_setup update\" afterwards\n        joy2keyStop\n        exec \"$scriptdir/retropie_packages.sh\" setup post_update update_packages_gui_setup update\n    fi\n\n    local update_os=0\n    dialog --yesno \"Would you like to update the underlying OS packages (eg kernel etc) ?\" 22 76 2>&1 >/dev/tty && update_os=1\n\n    clear\n\n    local logfilename\n    rps_logInit\n    {\n        rps_logStart\n        if [[ \"$update_os\" -eq 1 ]]; then\n            if rp_isEnabled \"raspbiantools\"; then\n                rp_callModule raspbiantools apt_upgrade\n            else\n                aptUpdate\n                apt-get -y dist-upgrade\n            fi\n        fi\n        update_packages_setup\n        rps_logEnd\n    } &> >(_setup_gzip_log \"$logfilename\")\n\n    rps_printInfo \"$logfilename\"\n    printMsgs \"dialog\" \"Installed packages have been updated.\"\n    gui_setup\n}\n\nfunction basic_install_setup() {\n    local id\n    for id in $(rp_getSectionIds core) $(rp_getSectionIds main); do\n        rp_installModule \"$id\"\n    done\n    return 0\n}\n\nfunction packages_gui_setup() {\n    local section\n    local default\n    local options=()\n\n    for section in core main opt driver exp depends; do\n        options+=(\"$section\" \"Manage ${__sections[$section]} packages\" \"$section Choose to install/update/configure packages from the ${__sections[$section]}\")\n    done\n\n    options+=(\"----\" \"\" \"\")\n    options+=(\"inst\" \"Manage all installed packages\" \"Install/update/remove currently installed packages\")\n    options+=(\"all\" \"Manage all packages\" \"Install/update/remove packages from full list\")\n\n    local cmd\n    while true; do\n        cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --item-help --help-button --default-item \"$default\" --menu \"Choose an option\" 22 76 16)\n\n        local choice\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        if [[ \"${choice[@]:0:4}\" == \"HELP\" ]]; then\n            choice=\"${choice[@]:5}\"\n            default=\"${choice/%\\ */}\"\n            choice=\"${choice#* }\"\n            printMsgs \"dialog\" \"$choice\"\n            continue\n        fi\n        [[ \"$choice\" != \"----\" ]] && section_gui_setup \"$choice\"\n        default=\"$choice\"\n    done\n}\n\nfunction uninstall_setup()\n{\n    dialog --defaultno --yesno \"Are you sure you want to uninstall RetroPie?\" 22 76 2>&1 >/dev/tty || return 0\n    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\n    clear\n    printHeading \"Uninstalling RetroPie\"\n    for id in \"${__mod_id[@]}\"; do\n        rp_isInstalled \"$id\" && rp_callModule $id remove\n    done\n    rm -rfv \"$rootdir\"\n    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\"\n    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\n        clear\n        # remove all dependencies\n        for id in \"${__mod_id[@]}\"; do\n            rp_isInstalled \"$id\" && rp_callModule \"$id\" depends remove\n        done\n    fi\n    printMsgs \"dialog\" \"RetroPie has been uninstalled.\"\n}\n\nfunction reboot_setup()\n{\n    clear\n    reboot\n}\n\n# retropie-setup main menu\nfunction gui_setup() {\n    joy2keyStart\n    depends_setup\n    local default\n    while true; do\n        local commit=$(sudo -u \"$__user\" git -C \"$scriptdir\" log -1 --pretty=format:\"%cr (%h)\")\n\n        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)\n        options=(\n            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.\"\n\n            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.\"\n\n            P \"Manage packages\"\n            \"P Install/Remove and Configure the various components of RetroPie, including emulators, ports, and controller drivers.\"\n\n            C \"Configuration / tools\"\n            \"C Configuration and Tools. Any packages you have installed that have additional configuration options will also appear here.\"\n\n            S \"Update RetroPie-Setup script\"\n            \"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.\"\n\n            X \"Uninstall RetroPie\"\n            \"X Uninstall RetroPie completely.\"\n\n            R \"Perform reboot\"\n            \"R Reboot your machine.\"\n        )\n\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n\n        if [[ \"${choice[@]:0:4}\" == \"HELP\" ]]; then\n            choice=\"${choice[@]:5}\"\n            default=\"${choice/%\\ */}\"\n            choice=\"${choice#* }\"\n            printMsgs \"dialog\" \"$choice\"\n            continue\n        fi\n        default=\"$choice\"\n\n        case \"$choice\" in\n            I)\n                ! check_connection_gui_setup && continue\n                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\n                clear\n                local logfilename\n                rps_logInit\n                {\n                    rps_logStart\n                    basic_install_setup\n                    rps_logEnd\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            U)\n                update_packages_gui_setup\n                ;;\n            P)\n                packages_gui_setup\n                ;;\n            C)\n                config_gui_setup\n                ;;\n            S)\n                ! check_connection_gui_setup && continue\n                dialog --defaultno --yesno \"Are you sure you want to update the RetroPie-Setup script ?\" 22 76 2>&1 >/dev/tty || continue\n                if updatescript_setup; then\n                    joy2keyStop\n                    exec \"$scriptdir/retropie_packages.sh\" setup post_update gui_setup\n                fi\n                ;;\n            X)\n                local logfilename\n                rps_logInit\n                {\n                    uninstall_setup\n                } &> >(_setup_gzip_log \"$logfilename\")\n                rps_printInfo \"$logfilename\"\n                ;;\n            R)\n                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\n                reboot_setup\n                ;;\n        esac\n    done\n    joy2keyStop\n    clear\n}\n"
  },
  {
    "path": "scriptmodules/admin/stats/licences/app.css",
    "content": "body {\n\tfont-family: sans-serif;\n\tline-height: 1.25;\n}\n.center {\n\tdisplay: flex;\n\tflex-flow: column;\n\talign-items: center;\n}\nh1, body > p {\n\tmax-width: 600px;\n\ttext-align: center;\n}\n\n\ncanvas {\n\tmax-width: 500px;\n\tmargin: 1em 0;\n}\n\n\n\n#packages h3 {\n\tmargin: 0;\n\tpadding: .25em;\n\tmargin-bottom: .25em;\n}\n#packages table {\n\twidth: 100%;\n\tmax-width: 1280px;\n\tborder-collapse: collapse;\n}\n#packages thead {\n\tborder-bottom: 1px solid rgba(0,0,0,30%);\n}\n#packages td {\n\tpadding: .25em;\n}\n#packages tr td:first-child {\n\tfont-family: monospace;\n\tmin-width: 15%;\n}\n#packages tr td:last-child {\n\ttext-align: center;\n\tmin-width: 5%;\n}\n#packages thead td:nth-child(3),\n#packages tr td:nth-child(3) {\n\ttext-align: center;\n\tmin-width: 8%;\n}\n#packages tr:hover {\n\tbackground-color: #fffe;\n}\n#packages section {\n\tmargin: 2em 0;\n\tpadding: .5em;\n}\n\n\n#commit {\n\tfont-size: 90%;\n\tmargin-top: 0;\n}\n#commit code {\n\tfont-size: 110%;\n}\n\n\nfooter {\n\tfont-size: 85%;\n\twidth: 100%;\n\tmax-width: 900px;\n\ttext-align: center;\n\tmargin-top: 2em;\n\tborder-top: 1px solid #ccc;\n\tpadding: 1.5em 0;\n\tdisplay: flex;\n\tflex-flow: column;\n\talign-items: center;\n}\nfooter p {\n\tmax-width: 800px;\n\tmargin-bottom: 0;\n}\n"
  },
  {
    "path": "scriptmodules/admin/stats/licences/app.js",
    "content": "async function fetch_packages() {\n\tconst resp = await fetch('../packages.csv');\n\tconst data = await resp.text();\n\n\treturn data\n\t\t.split('\\n')\n\t\t.map(line => line.split(';'))\n\t\t.filter(fields => fields.length >= 4)\n\t\t.map(fields => ({\n\t\t\tsection: fields[0],\n\t\t\tid: fields[1],\n\t\t\tdesc: fields[2],\n\t\t\tlicence: fields[3],\n\t\t}));\n}\n\nasync function fetch_commit_info() {\n\tconst resp = await fetch('../commit.csv');\n\tconst data = await resp.text();\n\tconst fields = data.split(';');\n\treturn {\n\t\tsha: fields[0] || '',\n\t\twhen: fields[1] || '',\n\t\tbranch: fields[2] || '',\n\t};\n}\n\nfunction create_commit_info(commit) {\n\tconst date = commit.when.slice(0, 10);\n\tconst time = commit.when.slice(11, 16);\n\tconst text = `Last update: ${date} ${time}, <code>${commit.branch}</code> branch at <code>${commit.sha}</code>`;\n\tdocument.getElementById('commit').innerHTML = text;\n}\n\nfunction get_pkg_licence_name(pkg) {\n\treturn pkg.licence\n\t\t? pkg.licence.split(' ', 1)[0]\n\t\t: 'Unknown';\n}\n\nfunction get_pkg_licence_link(pkg) {\n\tif (pkg.licence) {\n\t\tconst url = pkg.licence.split(' ', 2)[1];\n\t\tif (url) {\n\t\t\tconst anchor = document.createElement('a');\n\t\t\tanchor.href = url;\n\t\t\tanchor.target = '_blank';\n\t\t\tanchor.innerText = 'link';\n\t\t\treturn anchor.outerHTML;\n\t\t}\n\t}\n\treturn null;\n}\n\nconst CATEGORIES = [\n\t'copyleft',\n\t'permissive',\n\t'nonfree',\n\t'other',\n\t'unknown',\n];\nconst CATEGORY_COLORS = {\n\tunknown: '#555',\n\tcopyleft: '#d11',\n\tpermissive: '#1d1',\n\tnonfree: '#fc0',\n\tother: '#aaa',\n};\n\nfunction categorize_licence(licence) {\n\tif (licence == 'Unknown')\n\t\treturn 'unknown';\n\n\tif (/^L?GPL/.test(licence) || /^MPL/.test(licence))\n\t\treturn 'copyleft';\n\n\tif (['ZLIB', 'MIT', 'BSD'].includes(licence))\n\t\treturn 'permissive';\n\n\tif (['PROP', 'NONCOM'].includes(licence))\n\t\treturn 'nonfree';\n\n\treturn 'other';\n}\n\nfunction create_pie(packages) {\n\tconst counts = new Map();\n\tpackages\n\t\t.map(get_pkg_licence_name)\n\t\t.map(categorize_licence)\n\t\t.forEach(lic => counts.set(lic, (counts.get(lic) || 0) + 1));\n\n\tconst categories = CATEGORIES.filter(cat => counts.has(cat));\n\tconst canvas = document.getElementById('pie');\n\tconst chart = new Chart(canvas, {\n\t\ttype: 'doughnut',\n\t\tdata: {\n\t\t\tlabels: CATEGORIES,\n\t\t\tdatasets: [{\n\t\t\t\tdata: categories.map(cat => counts.get(cat)),\n\t\t\t\tbackgroundColor: categories.map(cat => CATEGORY_COLORS[cat]),\n\t\t\t}],\n\t\t},\n\t\toptions: {\n\t\t\tlegend: {\n\t\t\t\tposition: 'bottom',\n\t\t\t},\n\t\t},\n\t});\n}\n\nfunction append_cell(parent, html) {\n\tconst cell = document.createElement('td');\n\tcell.innerHTML = html;\n\tparent.appendChild(cell);\n}\n\nfunction create_section_row(type, cell_htmls) {\n\tconst row = document.createElement(type);\n\tcell_htmls.forEach(str => append_cell(row, str))\n\treturn row;\n}\n\nfunction create_package_tables(packages) {\n\tconst pkg_licences = new Map();\n\tpackages.forEach(pkg => {\n\t\tconst licence = get_pkg_licence_name(pkg);\n\t\tconst packages = pkg_licences.get(licence) || [];\n\t\tpackages.push(pkg);\n\t\tpkg_licences.set(licence, packages);\n\t});\n\n\tconst fragment = new DocumentFragment();\n\n\tconst licence_names = [...pkg_licences.keys()].sort();\n\tlicence_names.forEach(lic => {\n\t\tconst lic_category = categorize_licence(lic);\n\t\tconst lic_color = CATEGORY_COLORS[lic_category];\n\n\t\tconst container = document.createElement('section');\n\t\tcontainer.style.backgroundColor = lic_color + '2';\n\n\t\tconst title = document.createElement('h3');\n\t\ttitle.innerText = lic;\n\t\tcontainer.appendChild(title);\n\n\t\tconst table = document.createElement('table');\n\t\tconst thead = create_section_row('thead', ['Package', 'Description', 'Section', 'Licence']);\n\t\ttable.appendChild(thead);\n\n\t\tpkg_licences\n\t\t\t.get(lic)\n\t\t\t.sort((a, b) => a.id.localeCompare(b.id))\n\t\t\t.map(pkg => [\n\t\t\t\tpkg.id,\n\t\t\t\tpkg.desc,\n\t\t\t\tpkg.section || '&mdash;',\n\t\t\t\tget_pkg_licence_link(pkg) || '&mdash;',\n\t\t\t])\n\t\t\t.map(fields => create_section_row('tr', fields))\n\t\t\t.forEach(row => table.appendChild(row));\n\n\t\tcontainer.appendChild(table);\n\t\tfragment.appendChild(container);\n\t});\n\n\tdocument.getElementById('packages').appendChild(fragment);\n}\n\nwindow.onload = async () => {\n\tconst packages = await fetch_packages();\n\tconst commit = await fetch_commit_info();\n\tcreate_pie(packages);\n\tcreate_commit_info(commit);\n\tcreate_package_tables(packages);\n};\n"
  },
  {
    "path": "scriptmodules/admin/stats/licences/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset='utf-8'>\n\t<meta name='viewport' content='width=device-width,initial-scale=1'>\n\t<meta http-equiv='x-ua-compatible' content='ie=edge'>\n\t<title>RetroPie package licences</title>\n\t<link rel='stylesheet' type='text/css' href='app.css'>\n\t<script defer type='text/javascript' src='Chart.min.js'></script>\n\t<script defer type='text/javascript' src='app.js'></script>\n</head>\n<body class='center'>\n\t<h1>RetroPie package licences</h1>\n\t<p>This page shows an up-to-date list of all RetroPie packages and the licences they use.</p>\n\t<canvas id='pie' width='550' height='400'></canvas>\n\t<p id='commit'></p>\n\t<div id='packages'></div>\n\t<footer>\n\t\t<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>\n\t\t<p>Copyright &copy; 2019 The RetroPie Project</p>\n\t</footer>\n</body>\n</html>\n"
  },
  {
    "path": "scriptmodules/admin/stats/pkgflags/app.css",
    "content": "body {\n\tfont-family: sans-serif;\n\tline-height: 1.25;\n}\n.center {\n\tdisplay: flex;\n\tflex-flow: column;\n\talign-items: center;\n}\nh1, p {\n\tmax-width: 600px;\n\ttext-align: center;\n}\n\n\n#packages table {\n\twidth: 100%;\n\tmax-width: 1280px;\n\tborder-collapse: collapse;\n}\n#packages td {\n\tpadding: .25rem;\n}\n#packages tr td.id {\n\tfont-family: monospace;\n\tmin-width: 15%;\n}\n#packages td.flag.first {\n\tborder-left: 1px solid rgba(0,0,0,30%);\n}\n#packages tr td.flag {\n\tcolor: rgba(0,0,0,50%);\n}\n#packages tr td.flag.pass {\n\tbackground-color: #dfd;\n}\n#packages tr td.flag.fail {\n\tbackground-color: #fbb;\n}\n#packages table .flag {\n\ttext-align: center;\n}\n#packages thead {\n\tvertical-align: bottom;\n\tborder-bottom: 1px solid rgba(0,0,0,30%);\n}\n#packages thead .flag {\n\twriting-mode: vertical-rl;\n\twidth: 2rem;\n\tline-height: 2rem;\n}\n#packages tr:hover {\n\tbackground-color: #eee;\n}\n#packages tr:hover td.flag.pass {\n\tbackground-color: #cfc;\n}\n#packages tr:hover td.flag.fail {\n\tbackground-color: #f99;\n}\n#packages section {\n\tposition: relative;\n\tmargin: 2em 0;\n}\n#packages section h2 {\n\tposition: absolute;\n\ttop: 0;\n}\n\n\n#devices {\n\tdisplay: flex;\n\tjustify-content: center;\n\twidth: 100%;\n\tmax-width: 1000px;\n}\n#devices ul {\n\tlist-style-type: none;\n\tpadding: 0;\n\twidth: 100%;\n\tdisplay: flex;\n\tflex-flow: column;\n}\n#devices li {\n\tdisplay: flex;\n\tmargin: .25em 0;\n}\n#devices li span {\n\twidth: 11em;\n}\n#devices li span:first-child {\n\ttext-align: right;\n}\n#devices li progress {\n\tflex-grow: 1;\n\tmargin: 0 .5em;\n\theight: auto; /* for webkit */\n}\n\n\n#commit {\n\tfont-size: 90%;\n\tmargin-top: 0;\n}\n#commit code {\n\tfont-size: 110%;\n}\n\n\nfooter {\n\tfont-size: 85%;\n\twidth: 100%;\n\tmax-width: 900px;\n\ttext-align: center;\n\tmargin-top: 2em;\n\tborder-top: 1px solid #ccc;\n\tpadding: 1.5em 0;\n}\n"
  },
  {
    "path": "scriptmodules/admin/stats/pkgflags/app.js",
    "content": "async function fetch_packages() {\n\tconst resp = await fetch('../packages.csv');\n\tconst data = await resp.text();\n\n\treturn data\n\t\t.split('\\n')\n\t\t.map(line => line.split(';'))\n\t\t.filter(fields => fields.length >= 5)\n\t\t.map(fields => ({\n\t\t\tsection: fields[0],\n\t\t\tid: fields[1],\n\t\t\tdesc: fields[2],\n\t\t\t// fields[3] is the licence\n\t\t\tflags: fields[4].split(' '),\n\t\t}));\n}\n\nasync function fetch_commit_info() {\n\tconst resp = await fetch('../commit.csv');\n\tconst data = await resp.text();\n\tconst fields = data.split(';');\n\treturn {\n\t\tsha: fields[0] || '',\n\t\twhen: fields[1] || '',\n\t\tbranch: fields[2] || '',\n\t};\n}\n\nfunction create_device_bars(packages) {\n\tconst devices = [{\n\t\t\tname: 'Raspberry Pi 0/1',\n\t\t\tflags: ['videocore', 'arm', 'armv6'],\n\t\t\thover: 'VideoCore + ARMv6',\n\t\t}, {\n\t\t\tname: 'Raspberry Pi 2',\n\t\t\tflags: ['videocore', 'arm', 'armv7'],\n\t\t\thover: 'VideoCore + ARMv7',\n\t\t},{\n\t\t\tname: 'Raspberry Pi 3',\n\t\t\tflags: ['videocore', 'arm', 'armv8'],\n\t\t\thover: 'VideoCore + ARMv8',\n\t\t}, {\n\t\t\tname: 'Raspberry Pi 4',\n\t\t\tflags: ['kms', 'arm', 'armv8'],\n\t\t\thover: 'DRM/KMS + ARMv8',\n\t\t}, {\n\t\t\tname: 'Odroid C1/XU3/XU4',\n\t\t\tflags: ['mali', 'arm', 'armv7'],\n\t\t\thover: 'Mali + ARMv7',\n\t\t}, {\n\t\t\tname: 'Odroid C2',\n\t\t\tflags: ['mali', 'aarch64'],\n\t\t\thover: 'Mali + AArch64',\n\t\t}, {\n\t\t\tname: 'Desktop Linux',\n\t\t\tflags: ['x11', 'x86'],\n\t\t\thover: 'X11 + x86',\n\t\t},\n\t];\n\n\tconst ui_holder = document.createElement('ul');\n\tdevices\n\t\t.map(device => {\n\t\t\tconst label = document.createElement('span');\n\t\t\tlabel.innerText = device.name;\n\n\t\t\tconst bar = document.createElement('progress');\n\t\t\tbar.max = packages.length;\n\t\t\tbar.value = packages\n\t\t\t\t.filter(pkg => device.flags.every(flag => !pkg.flags.includes('!' + flag)))\n\t\t\t\t.length;\n\t\t\tbar.title = `${device.hover}\\n${bar.value} / ${bar.max}`;\n\n\t\t\tconst percent = document.createElement('span');\n\t\t\tpercent.innerText = Math.round(100 * bar.value / bar.max) + '%';\n\n\t\t\tconst row = document.createElement('li');\n\t\t\trow.appendChild(label);\n\t\t\trow.appendChild(bar);\n\t\t\trow.appendChild(percent);\n\t\t\treturn row;\n\t\t})\n\t\t.forEach(row => ui_holder.appendChild(row));\n\n\tdocument.getElementById('devices').appendChild(ui_holder);\n}\n\nfunction create_commit_info(commit) {\n\tconst date = commit.when.slice(0, 10);\n\tconst time = commit.when.slice(11, 16);\n\tconst text = `Last update: ${date} ${time}, <code>${commit.branch}</code> branch at <code>${commit.sha}</code>`;\n\tdocument.getElementById('commit').innerHTML = text;\n}\n\nfunction package_enabled_for(pkg, flag) {\n\tconst video_flag_synonyms = {\n\t\t'videocore' : [ 'arm', 'rpi', 'rpi1', 'rpi2', 'rpi3', 'dispmanx', 'gles' ],\n\t\t'mali'     : [ 'arm' , 'gles' ],\n\t\t'kms'      : [ 'arm' , 'rpi', 'rpi4', 'dispmanx', 'mesa' , 'gles3' ],\n\t\t'x11'      : [ 'x86' , '64bit', 'mesa' ]\n\t};\n\n\tvar equivs = (video_flag_synonyms[flag] ? [flag].concat(video_flag_synonyms[flag]) : [flag]);\n\n\tif ( pkg.flags.includes('!all') ) {\n\t\treturn _flags_include(pkg.flags, equivs) && !_flags_exclude(pkg.flags, equivs);\n\t} else {\n\t\treturn !_flags_exclude(pkg.flags, equivs);\n\t}\n\n}\n\nfunction _flags_include(pkg_flags, flags) {\n\treturn flags.reduce( (acc, flag) => acc || pkg_flags.includes(flag), false);\n}\n\nfunction _flags_exclude(pkg_flags, flags) {\n\treturn flags.reduce( (acc, flag) => acc || pkg_flags.includes('!' + flag), false);\n}\n\nfunction append_pkg_text_cell(parent, klass, text) {\n\tconst cell = document.createElement('td');\n\tcell.innerText = text;\n\tif (Array.isArray(klass))\n\t\tklass.forEach(k => cell.classList.add(k));\n\telse\n\t\tcell.classList.add(klass);\n\tparent.appendChild(cell);\n}\n\nfunction append_pkg_flag_cell(parent, klass, is_pass) {\n\tconst cell = document.createElement('td');\n\tcell.innerText = is_pass ? '\\u2713' : '\\u2717';\n\tcell.classList.add('flag', klass, is_pass ? 'pass' : 'fail');\n\tparent.appendChild(cell);\n}\n\nfunction create_section_thead() {\n\tconst thead = document.createElement('thead');\n\tappend_pkg_text_cell(thead, 'id', 'Package');\n\tappend_pkg_text_cell(thead, 'desc', 'Description');\n\tappend_pkg_text_cell(thead, ['flag', 'video'], 'VideoCore');\n\tappend_pkg_text_cell(thead, ['flag', 'video'], 'Mali');\n\tappend_pkg_text_cell(thead, ['flag', 'video'], 'DRM/KMS');\n\tappend_pkg_text_cell(thead, ['flag', 'video'], 'X11');\n\tappend_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv6');\n\tappend_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv7');\n\tappend_pkg_text_cell(thead, ['flag', 'cpu'], 'ARMv8 (32 bit)');\n\tappend_pkg_text_cell(thead, ['flag', 'cpu'], 'AArch64');\n\tappend_pkg_text_cell(thead, ['flag', 'cpu'], 'x86');\n\tthead.querySelector('.flag.video').classList.add('first');\n\tthead.querySelector('.flag.cpu').classList.add('first');\n\treturn thead;\n}\n\nfunction create_section_row(pkg) {\n\tconst row = document.createElement('tr');\n\trow.title='Script flags: ' + pkg.flags.join(' ');\n\tappend_pkg_text_cell(row, 'id', pkg.id);\n\tappend_pkg_text_cell(row, 'desc', pkg.desc);\n\tappend_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'videocore'));\n\tappend_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'mali'));\n\tappend_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'kms'));\n\tappend_pkg_flag_cell(row, 'video', package_enabled_for(pkg, 'x11'));\n\tappend_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv6'));\n\tappend_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv7'));\n\tappend_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!arm') && !pkg.flags.includes('!armv8'));\n\tappend_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!aarch64'));\n\tappend_pkg_flag_cell(row, 'cpu', !pkg.flags.includes('!x86'));\n\trow.querySelector('.flag.video').classList.add('first');\n\trow.querySelector('.flag.cpu').classList.add('first');\n\treturn row;\n}\n\nfunction create_package_sections(packages) {\n\tconst section_ids = [\n\t\t'core',\n\t\t'main',\n\t\t'opt',\n\t\t'exp',\n\t\t'driver',\n\t\t'config',\n\t\t'',\n\t];\n\tconst section_names = {\n\t\topt: 'optional',\n\t\texp: 'experimental',\n\t\tconfig: 'configuration',\n\t\t'': 'other',\n\t};\n\tconst sections = [];\n\tsection_ids.forEach(id => sections[id] = []);\n\n\tpackages.forEach(pkg => {\n\t\tconst section = sections[pkg.section] || sections[''];\n\t\tsection.push(pkg);\n\t});\n\n\n\tconst fragment = new DocumentFragment();\n\tsection_ids\n\t\t.filter(id => sections[id])\n\t\t.forEach(id => {\n\t\t\tconst ui_container = document.createElement('section');\n\n\t\t\tconst ui_title = document.createElement('h2');\n\t\t\tui_title.innerText = section_names[id] || id;\n\t\t\tui_container.appendChild(ui_title);\n\n\t\t\tconst ui_table = document.createElement('table');\n\t\t\tui_table.appendChild(create_section_thead());\n\t\t\tsections[id]\n\t\t\t\t.sort((a, b) => a.id.localeCompare(b.id))\n\t\t\t\t.map(pkg => create_section_row(pkg))\n\t\t\t\t.forEach(row => ui_table.appendChild(row));\n\t\t\tui_container.appendChild(ui_table);\n\n\t\t\tfragment.appendChild(ui_container);\n\t\t});\n\tdocument.getElementById('packages').appendChild(fragment);\n\n\n\tdocument.querySelector('table .flag.video').classList.add('first');\n\tdocument.querySelector('table .flag.cpu').classList.add('first');\n}\n\nwindow.onload = async () => {\n\tconst packages = await fetch_packages();\n\tconst commit = await fetch_commit_info();\n\tcreate_device_bars(packages);\n\tcreate_commit_info(commit);\n\tcreate_package_sections(packages);\n};\n"
  },
  {
    "path": "scriptmodules/admin/stats/pkgflags/index.html",
    "content": "<!DOCTYPE html>\n<html>\n<head>\n\t<meta charset='utf-8'>\n\t<meta name='viewport' content='width=device-width,initial-scale=1'>\n\t<meta http-equiv='x-ua-compatible' content='ie=edge'>\n\t<title>RetroPie package flags</title>\n\t<link rel='stylesheet' type='text/css' href='app.css'>\n\t<script type='text/javascript' src='app.js' defer></script>\n</head>\n<body class='center'>\n\t<h1>RetroPie platform support</h1>\n\t<p>This page shows an up-to-date list of all RetroPie packages and the platforms (devices and flags) they support.</p>\n\t<div id='devices'></div>\n\t<p id='commit'></p>\n\t<div id='packages'></div>\n\t<footer>Copyright &copy; 2019 The RetroPie Project</footer>\n</body>\n</html>\n"
  },
  {
    "path": "scriptmodules/admin/stats.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"stats\"\nrp_module_desc=\"Generates statistics about packages\"\nrp_module_section=\"\"\n\nfunction _get_commit_data_stats() {\n    local hash=$(git -C \"$scriptdir\" log -1 --format=%h)\n    local date=$(git -C \"$scriptdir\" log -1 --format=%cd --date=iso-strict)\n    local branch=$(git -C \"$scriptdir\" rev-parse --abbrev-ref HEAD)\n    echo \"$hash;$date;$branch;\"\n}\n\nfunction _get_package_data_stats() {\n    local data=()\n    local id\n    for id in ${__mod_id[@]}; do\n        data+=(\"${__mod_info[$id/section]};$id;${__mod_info[$id/desc]};${__mod_info[$id/licence]};${__mod_info[$id/flags]};\")\n    done\n    printf \"%s\\n\" \"${data[@]}\"\n}\n\nfunction build_stats() {\n    local dest=\"$__tmpdir/stats\"\n    mkUserDir \"$dest\"\n\n    # ignore platform flags to get info for all packages\n    __ignore_flags=1\n    rp_registerAllModules\n\n    echo \"$(_get_package_data_stats)\" > \"$dest/packages.csv\"\n    echo \"$(_get_commit_data_stats)\" > \"$dest/commit.csv\"\n\n    cp -rv \"$md_data/licences\" \"$dest/\"\n    cp -rv \"$md_data/pkgflags\" \"$dest/\"\n    chown -R \"$__user\":\"$__group\" \"$dest\"\n}\n\nfunction upload_stats() {\n    adminRsync \"$__tmpdir/stats/\" \"stats/\" --delete\n}\n"
  },
  {
    "path": "scriptmodules/admin/tools.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"tools\"\nrp_module_desc=\"Various RetroPie development/administration tools\"\nrp_module_section=\"\"\n\nfunction check_repos_tools() {\n    local ids\n    if [[ -n \"$1\" ]]; then\n        ids=(\"$@\")\n    else\n        ids=(\"${__mod_id[@]}\")\n    fi\n    local id\n    local ret=0\n    for id in \"${ids[@]}\"; do\n        eval \"$(rp_moduleVars $id)\"\n        local out\n        [[ -z \"$md_repo_type\" ]] && continue\n        md_repo_branch=\"$(rp_resolveRepoParam \"$md_repo_branch\")\"\n        md_repo_commit=\"$(rp_resolveRepoParam \"$md_repo_commit\")\"\n        printMsgs \"console\" \"Checking $id repository ($md_repo_url / $md_repo_branch) ...\"\n        case \"$md_repo_type\" in\n            git|svn)\n                out=$(rp_getRemoteRepoHash \"$md_repo_type\" \"$md_repo_url\" \"$md_repo_branch\" \"$md_repo_commit\")\n                if [[ \"$?\" -ne 0 || -z \"$out\" ]]; then\n                    printMsgs \"console\" \"$id repository failed - $md_repo_url $md_repo_branch\"\n                    ret=1\n                fi\n                ;;\n           file)\n                if ! rp_getFileDate \"$md_repo_url\" >/dev/null; then\n                    printMsgs \"console\" \"$id file archive failed - $md_repo_url\"\n                    ret=1\n                fi\n                ;;\n           :*)\n                # handle checking via module function - function should return 1 if there was an error\n                local function=\"${md_repo_type:1}\"\n                if fnExists \"$function\" ; then\n                    ! \"$function\" check && ret=1\n                fi\n                ;;\n\n        esac\n    done\n    return \"$ret\"\n}\n\nfunction check_licences_tools() {\n    local ids\n    if [[ -n \"$1\" ]]; then\n        ids=(\"$@\")\n    else\n        ids=(\"${__mod_id[@]}\")\n    fi\n    local id\n    local ret=0\n    local licence\n    local url\n    for id in \"${ids[@]}\"; do\n        eval \"$(rp_moduleVars $id)\"\n        licence=($md_licence)\n        url=\"${licence[1]}\"\n        if [[ -n \"$url\" ]]; then\n            printMsgs \"console\" \"Checking $id ($md_licence) ...\"\n            if ! download \"$url\" - &>/dev/null; then\n                printMsgs \"console\" \"... $id licence URL failed ($url)\"\n                ret=1\n            fi\n        fi\n    done\n    return \"$ret\"\n}\n"
  },
  {
    "path": "scriptmodules/admin/wikidocs.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"wikidocs\"\nrp_module_desc=\"Generate mkdocs documentation from wiki\"\nrp_module_section=\"\"\n\nfunction depends_wikidocs() {\n    getDepends python3 python3-pip libyaml-dev python3-setuptools python3-wheel python3-virtualenv\n}\n\nfunction sources_wikidocs() {\n    gitPullOrClone \"$md_build\" https://github.com/RetroPie/RetroPie-Docs.git\n}\n\nfunction build_wikidocs() {\n    python3 -m venv \"$md_inst\"\n    source \"$md_inst/bin/activate\"\n    pip3 install --upgrade mkdocs-material mdx_truly_sane_lists git+https://github.com/cmitu/mkdocs-altlink-plugin\n    mkdocs build\n    deactivate\n}\n\nfunction install_wikidocs() {\n    rsync -a --delete \"$md_build/site/\" \"$__tmpdir/wikidocs/\"\n    chown -R \"$__user\":\"$__group\" \"$__tmpdir/wikidocs\"\n}\n\nfunction upload_wikidocs() {\n    adminRsync \"$__tmpdir/wikidocs/\" \"docs/\" --delete\n}\n"
  },
  {
    "path": "scriptmodules/archivefuncs.sh",
    "content": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## @file archivefuncs.sh\n## @brief RetroPie archivefuncs library\n## @copyright GPLv3\n\nreadonly arch_dir=\"/tmp/retropie-archive\"\n\n## @fn archiveExtract()\n## @param src_file Full path to archive file to extract\n## @param disk_exts Space separated list of supported disk extensions (e.g. \".d64 .t64\")\n## @brief Extracts an archive to a temporary directory\n## @details After calling this the variable arch_dir will contain the directory that was used\n## for extraction. Also the variable arch_files will contain an array of filenames that are\n## considered as game disks according to parameter disk_exts.\nfunction archiveExtract() {\n    local src_file=\"$1\"\n    local disk_exts=\"$2\"\n\n    # clean temp directory if needed\n    archiveCleanup\n    mkdir \"$arch_dir\"\n\n    local ext=\"${src_file##*.}\"\n\n    case \"${ext,,}\" in\n        zip)\n            unzip \"$src_file\" -d \"$arch_dir\"\n            ;;\n        *)\n            echo \"Unsupported archive: $src_file\"\n            return 1\n            ;;\n    esac\n\n    # build a regex portion from the passed extensions\n    local regex=\"${disk_exts// /\\\\|}\"\n\n    IFS=$'\\n' read -d '' -r -a arch_files < <(find \"$arch_dir\" -iregex \".*.\\(${regex}\\)$\" | sort)\n\n    if [[ ${#arch_files[@]} -eq 0 ]]; then\n        return 2\n    fi\n}\n\n## @fn archiveCleanup()\n## @brief Purges archive temp directory from previous calls to archiveExtract\nfunction archiveCleanup() {\n    [[ -d \"$arch_dir\" ]] && rm -rf \"$arch_dir\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/advmame/01_rpi_framebuffer.diff",
    "content": "--- 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->accel_flags = FB_ACCEL_NONE;\n-\tvar->pixclock = (unsigned)(1000000000000LL / pixelclock);\n+\tvar->pixclock = pixelclock;\n \tvar->left_margin = ht - hre;\n \tvar->right_margin = hrs - hde;\n \tvar->upper_margin = vt - vre;\n@@ -587,9 +587,8 @@\n \t\tgoto err_close;\n \t}\n \n-\tfb_state.flags = VIDEO_DRIVER_FLAGS_MODE_PALETTE8 | VIDEO_DRIVER_FLAGS_MODE_BGR15 | VIDEO_DRIVER_FLAGS_MODE_BGR16 | VIDEO_DRIVER_FLAGS_MODE_BGR24 | VIDEO_DRIVER_FLAGS_MODE_BGR32\n-\t\t| VIDEO_DRIVER_FLAGS_PROGRAMMABLE_ALL\n-\t\t| VIDEO_DRIVER_FLAGS_OUTPUT_FULLSCREEN;\n+\tfb_state.flags = VIDEO_DRIVER_FLAGS_MODE_PALETTE8 | VIDEO_DRIVER_FLAGS_MODE_BGR16 | VIDEO_DRIVER_FLAGS_MODE_BGR24 | VIDEO_DRIVER_FLAGS_MODE_BGR32\n+\t\t| VIDEO_DRIVER_FLAGS_OUTPUT_WINDOW;\n \n \tif (fb_detect() != 0) {\n \t\tgoto err_close;\n@@ -1120,14 +1119,10 @@\n {\n \tassert(fb_is_active());\n \n-\tif (crtc_is_fake(crtc)) {\n-\t\terror_nolog_set(\"Not programmable modes are not supported.\\n\");\n+\tif (!crtc_is_fake(crtc)) {\n \t\treturn -1;\n \t}\n \n-\tif (video_mode_generate_check(\"fb\", fb_flags(), 8, 2048, crtc, flags)!=0)\n-\t\treturn -1;\n-\n \tmode->crtc = *crtc;\n \tmode->index = flags & MODE_FLAGS_INDEX_MASK;\n\n--- a/advance/osd/frame.c\n+++ b/advance/osd/frame.c\n@@ -1298,9 +1299,9 @@\n \t\tbest_vclock = context->state.game_fps;\n \n \t\tvideo_init_crtc_make_fake(context, \"generate\", best_size_x, best_size_y);\n+\t\tvideo_init_crtc_make_fake(context, \"generate-double-y\", best_size_x, best_size_2y);\n+\t\tvideo_init_crtc_make_fake(context, \"generate-double-x\", best_size_2x, best_size_y);\n \t\tvideo_init_crtc_make_fake(context, \"generate-double\", best_size_2x, best_size_2y);\n-\t\tvideo_init_crtc_make_fake(context, \"generate-triple\", best_size_3x, best_size_3y);\n-\t\tvideo_init_crtc_make_fake(context, \"generate-quad\", best_size_4x, best_size_4y);\n \t} else {\n \t\tunsigned long long factor_x;\n \t\tunsigned long long factor_y;\n--- a/advance/osd/frame.c\n+++ b/advance/osd/frame.c\n@@ -2425,6 +2425,7 @@ void advance_video_mode_preinit(struct advance_video_context* context, struct ma\n \t}\n \tlog_std((\"emu:video: suggested debugger size %dx%d\\n\", option->debug_width, option->debug_height));\n \n+#if 0\n \t/* set the vector game size */\n \tif (mame_is_game_vector(option->game)) {\n \t\tunsigned mode_size_x;\n@@ -2484,6 +2485,7 @@ void advance_video_mode_preinit(struct advance_video_context* context, struct ma\n \t\toption->vector_width = 0;\n \t\toption->vector_height = 0;\n \t}\n+#endif\n }\n \n /**\n--- a/advance/osd/glue.c\n+++ b/advance/osd/glue.c\n@@ -2866,6 +2866,9 @@ adv_error mame_init(struct advance_context* context)\n \tconf_float_register_limit_default(context->cfg, \"display_gamma\", 0.5, 2.0, 1.0);\n \tconf_float_register_limit_default(context->cfg, \"display_brightness\", 0.1, 10.0, 1.0);\n \n+\tconf_int_register_default(context->cfg, \"display_width\", 640);\n+\tconf_int_register_default(context->cfg, \"display_height\", 480);\n+\n \tconf_bool_register_default(context->cfg, \"misc_cheat\", 0);\n \tconf_string_register_default(context->cfg, \"misc_languagefile\", \"english.lng\");\n \tconf_string_register_default(context->cfg, \"misc_cheatfile\", \"cheat.dat\");\n@@ -2915,6 +2918,8 @@ adv_error mame_config_load(adv_conf* cfg_context, struct mame_option* option)\n \n \toption->gamma = conf_float_get_default(cfg_context, \"display_gamma\");\n \toption->brightness = conf_float_get_default(cfg_context, \"display_brightness\");\n+\toption->vector_width = conf_int_get_default(cfg_context, \"display_width\");\n+\toption->vector_height = conf_int_get_default(cfg_context, \"display_height\");\n \n \toption->cheat_flag = conf_bool_get_default(cfg_context, \"misc_cheat\");"
  },
  {
    "path": "scriptmodules/emulators/advmame/02_fix_extern_globals_0_94.diff",
    "content": "diff --git a/src/drivers/seibuspi.c b/src/drivers/seibuspi.c\nindex 143dcc2..91187f8 100644\n--- a/src/drivers/seibuspi.c\n+++ b/src/drivers/seibuspi.c\n@@ -602,7 +602,7 @@ WRITE32_HANDLER( video_dma_length_w );\n WRITE32_HANDLER( video_dma_address_w );\n WRITE32_HANDLER( sprite_dma_start_w );\n \n-UINT32 *scroll_ram;\n+extern UINT32 *scroll_ram;\n extern int old_vidhw;\n extern int bg_size;\n data32_t *spimainram;\n"
  },
  {
    "path": "scriptmodules/emulators/advmame/02_fix_extern_globals_1_4.diff",
    "content": "From f8688cae05799a30cd5337e626a07fa9f004c0a3 Mon Sep 17 00:00:00 2001\nFrom: Andrea Mazzoleni <amadvance@gmail.com>\nDate: Fri, 23 Oct 2020 21:29:41 +0200\nSubject: [PATCH] Fix build errors due new gcc 10 default for -fno-common\n\n---\n src/drivers/cavepgm.c | 6 +++---\n 1 file changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/src/drivers/cavepgm.c b/src/drivers/cavepgm.c\nindex 38d3dae8..df6e97ab 100644\n--- a/src/drivers/cavepgm.c\n+++ b/src/drivers/cavepgm.c\n@@ -287,7 +287,7 @@ Notes:\n #include \"timer.h\"\n \n \n-UINT16 *pgm_mainram, *pgm_bg_videoram, *pgm_tx_videoram, *pgm_videoregs, *pgm_rowscrollram;\n+extern UINT16 *pgm_mainram, *pgm_bg_videoram, *pgm_tx_videoram, *pgm_videoregs, *pgm_rowscrollram;\n static UINT8 *z80_mainram;\n static UINT32 *arm7_shareram;\n static UINT32 arm7_latch;\n@@ -852,8 +852,8 @@ static void expand_32x32x5bpp(void)\n /* This function expands the sprite colour data (in the A Roms) from 3 pixels\n    in each word to a byte per pixel making it easier to use */\n \n-UINT8 *pgm_sprite_a_region;\n-size_t\tpgm_sprite_a_region_allocate;\n+extern UINT8 *pgm_sprite_a_region;\n+extern size_t\tpgm_sprite_a_region_allocate;\n \n static void expand_colourdata(void)\n {\n-- \n2.32.0\n\n"
  },
  {
    "path": "scriptmodules/emulators/advmame-0.94.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"advmame-0.94\"\nrp_module_desc=\"AdvanceMAME v0.94.0\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your AdvanceMAME roms to either $romdir/mame-advmame or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/amadvance/advancemame/master/COPYING\"\nrp_module_repo=\"file $__archive_url/advancemame-0.94.0.tar.gz\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali !kms\"\n\nfunction depends_advmame-0.94() {\n    local depends=(libsdl1.2-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_advmame-0.94() {\n    downloadAndExtract \"$md_repo_url\" \"$md_build\" --strip-components 1\n    _sources_patch_advmame-1.4\n    # Fix the global vars missing the 'external' qualifier, needed for gcc > 10\n    applyPatch \"${md_path%/*}/advmame/02_fix_extern_globals_0_94.diff\"\n}\n\nfunction build_advmame-0.94() {\n    ./configure CFLAGS=\"$CFLAGS -fsigned-char -fno-stack-protector\" LDFLAGS=\"-s -lm -Wl,--no-as-needed\" --prefix=\"$md_inst\"\n    make clean\n    make\n}\n\nfunction install_advmame-0.94() {\n    make install\n}\n\nfunction configure_advmame-0.94() {\n    # move any old configuration file\n    if [[ -f \"$md_conf_root/mame-advmame/advmame-0.94.0.rc\" ]]; then\n        mv \"$md_conf_root/mame-advmame/advmame-0.94.0.rc\" \"$md_conf_root/mame-advmame/advmame-0.94.rc\"\n    fi\n\n    # remove old emulators.cfg entries\n    delEmulator advmame-0.94.0 mame-advmame\n    delEmulator advmame-0.94.0 arcade\n\n    configure_advmame\n}\n"
  },
  {
    "path": "scriptmodules/emulators/advmame-1.4.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"advmame-1.4\"\nrp_module_desc=\"AdvanceMAME v1.4\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your AdvanceMAME roms to either $romdir/mame-advmame or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/amadvance/advancemame/master/COPYING\"\nrp_module_repo=\"file $__archive_url/advancemame-1.4.tar.gz\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali !kms\"\n\nfunction depends_advmame-1.4() {\n    local depends=(libsdl1.2-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction _sources_patch_advmame-1.4() {\n    # update internal names to separate out config files (due to incompatible options)\n    sed -i \"s/advmame\\.rc/$md_id.rc/\" advance/v/v.c advance/cfg/cfg.c\n\n    if grep -q \"ADVANCE_NAME\" advance/osd/emu.h; then\n        sed -i \"s/ADVANCE_NAME \\\"advmame\\\"/ADVANCE_NAME \\\"$md_id\\\"/\" advance/osd/emu.h\n    else\n        sed -i \"s/ADV_NAME \\\"advmame\\\"/ADV_NAME \\\"$md_id\\\"/\" advance/osd/emu.h\n    fi\n\n    if isPlatform \"rpi\"; then\n        if grep -q \"MAP_FIXED\" advance/linux/vfb.c; then\n            sed -i 's/MAP_SHARED | MAP_FIXED,/MAP_SHARED,/' advance/linux/vfb.c\n        fi\n\n        # patch advmame to use a fake generated mode with the exact dimensions for fb - avoids need for configuring monitor / clocks.\n        # the pi framebuffer doesn't use any of the framebuffer timing configs - it hardware scales from chosen dimensions to actual size\n        applyPatch \"${md_path%/*}/advmame/01_rpi_framebuffer.diff\"\n    fi\n}\n\nfunction sources_advmame-1.4() {\n    downloadAndExtract \"$md_repo_url\" \"$md_build\" --strip-components 1\n    _sources_patch_advmame-1.4 1.4\n    # Fix the global vars missing the 'external' qualifier, needed for gcc > 10\n    applyPatch \"${md_path%/*}/advmame/02_fix_extern_globals_1_4.diff\"\n}\n\nfunction build_advmame-1.4() {\n    ./configure CFLAGS=\"$CFLAGS -fsigned-char -fno-stack-protector\" LDFLAGS=\"-s -lm -Wl,--no-as-needed\" --prefix=\"$md_inst\"\n    make clean\n    make\n}\n\nfunction install_advmame-1.4() {\n    make install\n}\n\nfunction configure_advmame-1.4() {\n    configure_advmame\n}\n"
  },
  {
    "path": "scriptmodules/emulators/advmame.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"advmame\"\nrp_module_desc=\"AdvanceMAME\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your AdvanceMAME roms to either $romdir/mame-advmame or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/amadvance/advancemame/master/COPYING\"\nrp_module_repo=\"git https://github.com/amadvance/advancemame v3.10\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2 sdl1-videocore\"\n\nfunction _update_hook_advmame() {\n    # if the non split advmame is installed, make directories for 0.94 / 1.4 so they will be updated\n    # when doing update all packages\n    if [[ -d \"$md_inst/0.94.0\" ]]; then\n        mkdir -p \"$rootdir/emulators/advmame-\"{0.94,1.4}\n        printMsgs \"dialog\" \"The advmame package has now been split into the following packages.\\n\\nadvmame-0.94\\nadvmame-1.4\\nadvmame\\n\\nIf you have chosen just to update the RetroPie-Setup script, you will need to update all the advmame packages for them to work correctly.\\n\\nNote that advmame-0.94.0.rc will be renamed to advmame-0.94.rc and the config for the main advmame will be advmame.rc.\\n\\nThe advmame package will be the latest version of the software.\"\n    fi\n}\n\nfunction depends_advmame() {\n    local depends=(autoconf automake)\n    if isPlatform \"videocore\"; then\n        depends+=(libsdl1.2-dev libraspberrypi-dev)\n    else\n        depends+=(libsdl2-dev)\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_advmame() {\n    gitPullOrClone\n}\n\nfunction build_advmame() {\n    local params=()\n    if isPlatform \"videocore\"; then\n        params+=(--enable-sdl --disable-sdl2 --enable-vc)\n    else\n        params+=(--enable-sdl2 --disable-sdl --disable-vc)\n    fi\n    ./autogen.sh\n    ./configure CFLAGS=\"$CFLAGS -fno-stack-protector\" --prefix=\"$md_inst\" \"${params[@]}\"\n    make clean\n    make\n    md_ret_require=\"$md_build/advmame\"\n}\n\nfunction install_advmame() {\n    make install\n}\n\nfunction configure_advmame() {\n    mkRomDir \"arcade\"\n    mkRomDir \"arcade/advmame\"\n    mkRomDir \"mame-advmame\"\n\n    moveConfigDir \"$home/.advance\" \"$md_conf_root/mame-advmame\"\n\n    # move any old named configs (with 3.2 taking priority)\n    local ver\n    for ver in 3.1 3.2; do\n        if [[ -f \"$md_conf_root/mame-advmame/advmame-$ver.rc\" ]]; then\n            mv \"$md_conf_root/mame-advmame/advmame-$ver.rc\" \"$md_conf_root/mame-advmame/advmame.rc\"\n        fi\n\n        # remove any old emulator.cfg entries\n        delEmulator advmame-$ver mame-advmame\n        delEmulator advmame-$ver arcade\n    done\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        local mame_sub_dir\n        for mame_sub_dir in artwork diff hi inp memcard nvram sample snap sta; do\n            mkRomDir \"mame-advmame/$mame_sub_dir\"\n            ln -sf \"$romdir/mame-advmame/$mame_sub_dir\" \"$romdir/arcade/advmame\"\n            # fix for older broken symlink generation\n            rm -f \"$romdir/mame-advmame/$mame_sub_dir/$mame_sub_dir\"\n        done\n    fi\n\n    if [[ \"$md_mode\" == \"install\" && ! -f \"$md_conf_root/mame-advmame/$md_id.rc\" ]]; then\n\n        su \"$__user\" -c \"$md_inst/bin/advmame --default\"\n\n        iniConfig \" \" \"\" \"$md_conf_root/mame-advmame/$md_id.rc\"\n\n        iniSet \"misc_quiet\" \"yes\"\n        iniSet \"dir_rom\" \"$romdir/mame-advmame:$romdir/arcade\"\n        iniSet \"dir_artwork\" \"$romdir/mame-advmame/artwork\"\n        iniSet \"dir_sample\" \"$romdir/mame-advmame/samples\"\n        iniSet \"dir_diff\" \"$romdir/mame-advmame/diff\"\n        iniSet \"dir_hi\" \"$romdir/mame-advmame/hi\"\n        iniSet \"dir_image\" \"$romdir/mame-advmame\"\n        iniSet \"dir_inp\" \"$romdir/mame-advmame/inp\"\n        iniSet \"dir_memcard\" \"$romdir/mame-advmame/memcard\"\n        iniSet \"dir_nvram\" \"$romdir/mame-advmame/nvram\"\n        iniSet \"dir_snap\" \"$romdir/mame-advmame/snap\"\n        iniSet \"dir_sta\" \"$romdir/mame-advmame/nvram\"\n\n        if isPlatform \"videocore\"; then\n            iniSet \"device_video\" \"fb\"\n            iniSet \"device_video_cursor\" \"off\"\n            iniSet \"device_keyboard\" \"raw\"\n            iniSet \"device_sound\" \"alsa\"\n            iniSet \"display_vsync\" \"no\"\n            iniSet \"sound_normalize\" \"no\"\n            iniSet \"display_resizeeffect\" \"none\"\n            iniSet \"display_resize\" \"integer\"\n            iniSet \"display_magnify\" \"1\"\n        elif isPlatform \"kms\" || isPlatform \"mali\"; then\n            iniSet \"device_video\" \"sdl\"\n            # need to force keyboard device as auto will choose event driver which doesn't work with sdl\n            iniSet \"device_keyboard\" \"sdl\"\n            # default for best performance\n            iniSet \"display_magnify\" \"1\"\n            # disable threading to get rid of the crash-on-exit when using SDL, preventing config save\n            iniSet \"misc_smp\" \"no\"\n        else\n            iniSet \"device_video_output\" \"overlay\"\n            iniSet \"display_aspectx\" 16\n            iniSet \"display_aspecty\" 9\n        fi\n\n        if isPlatform \"armv6\"; then\n            iniSet \"sound_samplerate\" \"22050\"\n            iniSet \"sound_latency\" \"0.2\"\n        else\n            iniSet \"sound_samplerate\" \"44100\"\n        fi\n    fi\n\n    addEmulator 1 \"$md_id\" \"arcade\" \"$md_inst/bin/advmame %BASENAME%\"\n    addEmulator 1 \"$md_id\" \"mame-advmame\" \"$md_inst/bin/advmame %BASENAME%\"\n\n    addSystem \"arcade\"\n    addSystem \"mame-advmame\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/ags.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ags\"\nrp_module_desc=\"Adventure Game Studio - Adventure game engine\"\nrp_module_help=\"ROM Extension: .exe\\n\\nCopy your Adventure Game Studio roms to $romdir/ags/<game>/\"\nrp_module_licence=\"OTHER https://raw.githubusercontent.com/adventuregamestudio/ags/master/License.txt\"\nrp_module_repo=\"git https://github.com/adventuregamestudio/ags.git release-3.6.0\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction depends_ags() {\n    getDepends libsdl2-dev cmake pkg-config libaldmb1-dev libfreetype6-dev libtheora-dev libvorbis-dev libogg-dev liballegro4-dev\n}\n\nfunction sources_ags() {\n    gitPullOrClone\n}\n\nfunction build_ags() {\n    cmake -DCMAKE_INSTALL_PREFIX=\"$md_inst\" \\\n        -DAGS_USE_LOCAL_ALL_LIBRARIES=ON \\\n        -DAGS_USE_LOCAL_SDL2_SOUND=OFF \\\n        -DCMAKE_BUILD_TYPE=Release\n    make -C Engine clean\n    make -C Engine\n    md_ret_require=\"$md_build/ags\"\n}\n\nfunction install_ags() {\n    make -C Engine install\n    # install Eawpatches GUS patch set (see: http://liballeg.org/digmid.html)\n    download \"http://www.eglebbk.dds.nl/program/download/digmid.dat\" - | bzcat >\"$md_inst/bin/patches.dat\"\n}\n\nfunction configure_ags() {\n    local launcher=\"$md_inst/launch_ags.sh\"\n\n    moveConfigDir \"$home/.local/share/ags\" \"$md_conf_root/ags\"\n    mkRomDir \"ags\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        _create_launcher_ags \"$launcher\"\n    fi\n\n    addEmulator 1 \"$md_id\" \"ags\" \"bash '$launcher' %ROM%\" \"Adventure Game Studio\" \".exe\"\n    addSystem \"ags\"\n}\n\nfunction _create_launcher_ags() {\n    local launcher=\"$1\"\n    local binary=\"$md_inst/bin/ags\"\n    local params=(\n        \"--fullscreen\"\n        \"--gfxdriver ogl\"\n    )\n\n    cat > \"$launcher\" << _EOF_\n#! /usr/bin/env bash\n\n# ROM usually denotes \".../roms/ags/<something>.exe\" whereas the game files are\n# expected in \"<something>/\" subfolder. <something>.exe and <something>/ are\n# expected to be sibling in the $romdir/ags folder.\nROM=\\$1\nfn=\"\\${ROM##*/}\"\nsubfolder=\"\\${fn%.*}\"\npath=\"\\${ROM%/*}\"\n\n# only hint the emulator to the subfolder if it exists, because some games\n# can be run with a single AGS exe and do not require a game subfolder\nif [[ -d \"\\$path/\\$subfolder/\" ]] ; then\n    ROM=\"\\$path/\\$subfolder/\"\nfi\n\necho \"ROM parameter for AGS engine: \\$ROM\" >> /dev/shm/runcommand.log\n$binary \"${params[*]}\" \"\\$ROM\"\n_EOF_\n\n    chown \"$__user\":\"$__group\" \"$launcher\"\n    chmod u+x \"$launcher\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/amiberry/01_preserve_env.diff",
    "content": "diff --git a/Makefile b/Makefile\nindex 9747718..dcdfb2f 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -43,10 +43,10 @@ SDL_CONFIG ?= sdl2-config\n export SDL_CFLAGS := $(shell $(SDL_CONFIG) --cflags)\n export SDL_LDFLAGS := $(shell $(SDL_CONFIG) --libs)\n \n-CPPFLAGS = -MD -MT $@ -MF $(@:%.o=%.d) $(SDL_CFLAGS) -Iexternal/libguisan/include -Isrc -Isrc/osdep -Isrc/threaddep -Isrc/include -Isrc/archivers -Iexternal/floppybridge/src -Iexternal/mt32emu/src -D_FILE_OFFSET_BITS=64\n-CFLAGS=-pipe -Wno-shift-overflow -Wno-narrowing -fno-pie\n+CPPFLAGS += -MD -MT $@ -MF $(@:%.o=%.d) $(SDL_CFLAGS) -Iexternal/libguisan/include -Isrc -Isrc/osdep -Isrc/threaddep -Isrc/include -Isrc/archivers -Iexternal/floppybridge/src -Iexternal/mt32emu/src -D_FILE_OFFSET_BITS=64\n+CFLAGS += -pipe -Wno-shift-overflow -Wno-narrowing -fno-pie\n \n-LDFLAGS = $(SDL_LDFLAGS) -lSDL2_image -lSDL2_ttf -lserialport -lportmidi -lguisan -Lexternal/libguisan/lib -lmt32emu -Lexternal/mt32emu\n+LDFLAGS += $(SDL_LDFLAGS) -lSDL2_image -lSDL2_ttf -lserialport -lportmidi -lguisan -Lexternal/libguisan/lib -lmt32emu -Lexternal/mt32emu\n LDFLAGS += -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed -lpthread -lz -lpng -lrt -lFLAC -lmpg123 -ldl -lmpeg2convert -lmpeg2 -lstdc++fs -no-pie\n \n ifdef USE_OPENGL\n"
  },
  {
    "path": "scriptmodules/emulators/amiberry/02_fix_uae_config_load.diff",
    "content": "diff --git a/src/osdep/amiberry_whdbooter.cpp b/src/osdep/amiberry_whdbooter.cpp\nindex 8a03e732..939b26b8 100644\n--- a/src/osdep/amiberry_whdbooter.cpp\n+++ b/src/osdep/amiberry_whdbooter.cpp\n@@ -1180,6 +1180,7 @@ void set_booter_drives(uae_prefs* prefs, const char* filepath)\n \n void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)\n {\n+\tbool custom_config_loaded = false;\n \twrite_log(\"WHDBooter Launched\\n\");\n \n \tif (lstAvailableROMs.empty())\n@@ -1207,18 +1208,7 @@ void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)\n \tconst std::string filename_no_extension = get_game_filename(filepath);\n \twhdload_prefs.filename = filename_no_extension;\n \n-\t// LOAD GAME SPECIFICS FOR EXISTING .UAE - USE SHA1 IF AVAILABLE\n-\t//  CONFIG LOAD IF .UAE IS IN CONFIG PATH\n-\tbuild_uae_config_filename(whdload_prefs.filename);\n-\n-\t// If we have a config file, we use that first\n-\tif (std::filesystem::exists(uae_config))\n-\t{\n-\t\twrite_log(\"WHDBooter -  %s found. Loading Config for WHDLoad options.\\n\", uae_config.c_str());\n-\t\ttarget_cfgfile_load(prefs, uae_config.c_str(), CONFIG_TYPE_DEFAULT, 0);\n-\t}\n-\n-\t// setups for tmp folder.\n+\t// setup for tmp folder.\n \tstd::filesystem::create_directories(\"/tmp/amiberry/s\");\n \tstd::filesystem::create_directories(\"/tmp/amiberry/c\");\n \tstd::filesystem::create_directories(\"/tmp/amiberry/devs\");\n@@ -1234,7 +1224,6 @@ void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)\n \t// LOAD GAME SPECIFICS\n \twhd_path = whdbooter_path / \"game-data\";\n \tgame_hardware_options game_detail;\n-\n \twhd_config = whd_path / \"whdload_db.xml\";\n \n \tif (std::filesystem::exists(whd_config))\n@@ -1243,7 +1232,17 @@ void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)\n \t}\n \telse\n \t{\n-\t\twrite_log(\"WHDBooter -  Could not load whdload_db.xml - does not exist?\\n\");\n+\t\twrite_log(\"WHDBooter - Could not load whdload_db.xml - does not exist?\\n\");\n+\t}\n+\n+\t// LOAD CUSTOM CONFIG\n+\tbuild_uae_config_filename(whdload_prefs.filename);\n+\t// If we have a config file, we will load that on top of the XML settings\n+\tif (std::filesystem::exists(uae_config))\n+\t{\n+\t\twrite_log(\"WHDBooter - %s found. Loading Config for WHDLoad options.\\n\", uae_config.c_str());\n+\t\ttarget_cfgfile_load(prefs, uae_config.c_str(), CONFIG_TYPE_DEFAULT, 0);\n+\t\tcustom_config_loaded = true;\n \t}\n \n \t// If we have a slave, create a startup-sequence\n@@ -1308,7 +1307,7 @@ void whdload_auto_prefs(uae_prefs* prefs, const char* filepath)\n #endif\n \n \t// if we already loaded a .uae config, we don't need to do the below manual setup for hardware\n-\tif (std::filesystem::exists(uae_config))\n+\tif (custom_config_loaded)\n \t{\n \t\twrite_log(\"WHDBooter - %s found; ignoring WHD Quickstart setup.\\n\", uae_config.c_str());\n \t\treturn;\n"
  },
  {
    "path": "scriptmodules/emulators/amiberry/03_fix_crash_saving.diff",
    "content": "diff --git a/src/cfgfile.cpp b/src/cfgfile.cpp\nindex f96ee0d9..24bd58cb 100644\n--- a/src/cfgfile.cpp\n+++ b/src/cfgfile.cpp\n@@ -2243,7 +2243,7 @@ void cfgfile_save_options (struct zfile *f, struct uae_prefs *p, int type)\n #ifdef AMIBERRY\n \t\tstd::string mode;\n \t\tstd::string buffer;\n-\t\tdidata* did = &di_joystick[jp->id];\n+\t\tdidata* did = &di_joystick[jp->id - JSEM_JOYS];\n \n \t\t// custom options SAVING\n \t\tfor (int m = 0; m < 2; ++m)\n"
  },
  {
    "path": "scriptmodules/emulators/amiberry.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"amiberry\"\nrp_module_desc=\"Amiga emulator with JIT support (forked from uae4arm)\"\nrp_module_help=\"ROM Extension: .adf .chd .ipf .lha .zip\\n\\nCopy your Amiga games to $romdir/amiga\\n\\nCopy the required BIOS files\\nkick13.rom\\nkick20.rom\\nkick31.rom\\nto $biosdir/amiga\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/BlitterStudio/amiberry/master/LICENSE\"\nrp_module_repo=\"git https://github.com/BlitterStudio/amiberry :_get_branch_amiberry\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all arm rpi3 rpi4 rpi5 x86\"\n\nfunction _update_hook_amiberry() {\n    local rom\n    mkUserDir \"$biosdir/amiga\"\n    for rom in kick13.rom kick20.rom kick31.rom; do\n        # if we have a kickstart rom in $biosdir, move it to $biosdir/amiga and symlink the old location\n        if [[ -f \"$biosdir/$rom\" && ! -h \"$biosdir/$rom\" ]]; then\n            moveConfigFile \"$biosdir/$rom\" \"$biosdir/amiga/$rom\"\n        fi\n    done\n}\n\nfunction _get_branch_amiberry() {\n    if isPlatform \"dispmanx\"; then\n        echo \"v5.7.1\"\n    elif isPlatform \"x86\"; then\n        echo \"preview-v6.3.3\"\n    else\n        echo \"v5.7.2\"\n    fi\n}\n\nfunction _get_platform_amiberry() {\n    local platform=\"$__platform-sdl2\"\n    if isPlatform \"aarch64\" && isPlatform \"rpi\"; then\n        platform=\"$__platform-64-sdl2\"\n    elif isPlatform \"dispmanx\"; then\n        platform=\"$__platform\"\n    elif isPlatform \"odroid-xu\"; then\n        platform=\"xu4\"\n    elif isPlatform \"odroid-c1\"; then\n        platform=\"c1\"\n    elif isPlatform \"tinker\"; then\n        platform=\"tinker\"\n    elif isPlatform \"vero4k\"; then\n        platform=\"vero4k\"\n    elif isPlatform \"x86\"; then\n        platform=\"x86-64\"\n    fi\n    echo \"$platform\"\n}\n\nfunction depends_amiberry() {\n    local depends=(cmake autoconf libpng-dev libmpeg2-4-dev zlib1g-dev libmpg123-dev libflac-dev libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libserialport-dev wget libportmidi-dev)\n\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_amiberry() {\n    gitPullOrClone\n    if ! isPlatform \"x86\"; then\n        applyPatch \"$md_data/01_preserve_env.diff\"\n    fi\n    # Dispmanx is locked on v5.7.1, apply some critical fixes on top of it\n    if isPlatform \"dispmanx\"; then\n        applyPatch \"$md_data/02_fix_uae_config_load.diff\"\n        applyPatch \"$md_data/03_fix_crash_saving.diff\"\n    fi\n    # use our default optimisation level\n    sed -i \"/CFLAGS += -O3/d\" \"$md_build/Makefile\"\n}\n\nfunction build_amiberry() {\n    local platform=$(_get_platform_amiberry)\n    make clean\n    cd external/capsimg\n    ./bootstrap\n    ./configure\n    make clean\n    make\n    cp capsimg.so \"$md_build/plugins\"\n    cd \"$md_build\"\n    make PLATFORM=\"$platform\" CPUFLAGS=\"$__cpu_flags\"\n    md_ret_require=\"$md_build/amiberry\"\n}\n\nfunction install_amiberry() {\n    md_ret_files=(\n        'abr'\n        'amiberry'\n        'data'\n        'plugins'\n        'kickstarts'\n    )\n\n    cp -R \"$md_build/whdboot\" \"$md_inst/whdboot-dist\"\n}\n\nfunction configure_amiberry() {\n    addEmulator 1 \"amiberry\" \"amiga\" \"$md_inst/amiberry.sh %ROM%\"\n    addEmulator 0 \"amiberry-a500\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model A500\"\n    addEmulator 0 \"amiberry-a500plus\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model A500P\"\n    addEmulator 0 \"amiberry-a1200\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model A1200\"\n    addEmulator 0 \"amiberry-a4000\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model A4000\"\n    addEmulator 0 \"amiberry-cdtv\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model CDTV\"\n    addEmulator 0 \"amiberry-cd32\" \"amiga\" \"$md_inst/amiberry.sh %ROM% --model CD32\"\n    addSystem \"amiga\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkRomDir \"amiga\"\n\n    mkUserDir \"$md_conf_root/amiga\"\n    mkUserDir \"$md_conf_root/amiga/amiberry\"\n\n    # move config / save folders to $md_conf_root/amiga/amiberry\n    local dir\n    for dir in conf nvram savestates screenshots; do\n        moveConfigDir \"$md_inst/$dir\" \"$md_conf_root/amiga/amiberry/$dir\"\n    done\n\n    # set various media paths to the 'amiga' rom folder\n    iniConfig \"=\" \"\" \"$md_inst/conf/amiberry.conf\"\n    iniSet \"rom_path\" \"$biosdir/amiga\"\n    iniSet \"floppy_path\" \"$romdir/amiga\"\n    iniSet \"harddrive_path\" \"$romdir/amiga\"\n    iniSet \"cdrom_path\" \"$romdir/amiga\"\n    iniSet \"lha_path\" \"$romdir/amiga\"\n    chown \"$__user\":\"$__group\" \"$md_inst/conf/amiberry.conf\"\n\n    # check for cd32.nvr and move it to $md_conf_root/amiga/amiberry/nvram\n    if [[ -f \"$md_conf_root/amiga/amiberry/cd32.nvr\" ]]; then\n        mv \"$md_conf_root/amiga/amiberry/cd32.nvr\" \"$md_conf_root/amiga/amiberry/nvram/\"\n    fi\n\n    moveConfigDir \"$md_inst/kickstarts\" \"$biosdir/amiga\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/amiga\"\n\n    # symlink the retroarch config / autoconfigs for amiberry to use\n    ln -sf \"$configdir/all/retroarch/autoconfig\" \"$md_inst/controllers\"\n    ln -sf \"$configdir/all/retroarch.cfg\" \"$md_inst/conf/retroarch.cfg\"\n\n    local config_dir=\"$md_conf_root/amiga/amiberry\"\n\n    # create whdboot config area\n    moveConfigDir \"$md_inst/whdboot\" \"$config_dir/whdboot\"\n\n    # copy game-data, save-data folders, boot-data.zip and WHDLoad\n    cp -R \"$md_inst/whdboot-dist/\"{game-data,save-data,boot-data.zip,WHDLoad} \"$config_dir/whdboot/\"\n\n    chown -R \"$__user\":\"$__group\" \"$config_dir/whdboot\"\n\n    # copy shared uae4arm/amiberry launch script while setting is_amiberry=1\n    sed \"s/is_amiberry=0/is_amiberry=1/\" \"$md_data/../uae4arm/uae4arm.sh\" >\"$md_inst/amiberry.sh\"\n    chmod a+x \"$md_inst/amiberry.sh\"\n\n    local script=\"+Start Amiberry.sh\"\n    cat > \"$romdir/amiga/$script\" << _EOF_\n#!/bin/bash\n\"$md_inst/amiberry.sh\"\n_EOF_\n    chmod a+x \"$romdir/amiga/$script\"\n    chown \"$__user\":\"$__group\" \"$romdir/amiga/$script\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/atari800/01_rpi_fixes.diff",
    "content": "diff --git a/configure.ac b/configure.ac\nindex adb899f..bc9d939 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -148,7 +148,7 @@ if [[ \"$a8_target\" = \"ps2\" ]]; then\n fi\n if [[ \"$a8_target\" = \"rpi\" ]]; then\n     [[ -z \"$RPI_SDK\" ]] && RPI_SDK=\"/opt/vc\"\n-    CC=\"arm-linux-gnueabihf-gcc\"\n+    CC=\"gcc\"\n     CFLAGS=\"$CFLAGS -I${RPI_SDK}/include -I${RPI_SDK}/include/SDL -I${RPI_SDK}/include/interface/vmcs_host/linux -I${RPI_SDK}/include/interface/vcos/pthreads\"\n     LDFLAGS=\"$LDFLAGS -Wl,--unresolved-symbols=ignore-in-shared-libs -L${RPI_SDK}/lib\"\n fi\n"
  },
  {
    "path": "scriptmodules/emulators/atari800/atari800.sh",
    "content": "#!/bin/bash\n\nemulator=\"./EMULATOR\"\nrom=\"$1\"\nshift\nparams=(\"$@\")\n\npushd \"${0%/*}\" >/dev/null\n\nif [[ -z \"$rom\" ]]; then\n    \"$emulator\" \"${params[@]}\"\nelse\n    source \"../../lib/archivefuncs.sh\"\n\n    archiveExtract \"$rom\" \".a52 .atr .bas .bin .car .dcm .xex .xfd\"\n\n    # check successful extraction and if we have at least one file\n    if [[ $? == 0 ]]; then\n        rom=\"${arch_files[0]}\"\n    fi\n\n    \"$emulator\" \"$rom\" \"${params[@]}\"\n    archiveCleanup\nfi\n\npopd\n"
  },
  {
    "path": "scriptmodules/emulators/atari800.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"atari800\"\nrp_module_desc=\"Atari 8-bit/800/5200 emulator\"\nrp_module_help=\"ROM Extensions: .a52 .bas .bin .car .xex .atr .xfd .dcm .atr.gz .xfd.gz\\n\\nCopy your Atari800 games to $romdir/atari800\\n\\nCopy your Atari 5200 roms to $romdir/atari5200 You need to copy the Atari 800/5200 BIOS files (5200.ROM, ATARIBAS.ROM, ATARIOSB.ROM and ATARIXL.ROM) to the folder $biosdir and then on first launch configure it to scan that folder for roms (F1 -> Emulator Configuration -> System Rom Settings)\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/atari800/atari800/master/COPYING\"\nrp_module_repo=\"git https://github.com/atari800/atari800.git ATARI800_5_2_0\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1\"\n\nfunction depends_atari800() {\n    local depends=(libsdl1.2-dev autoconf automake zlib1g-dev libpng-dev)\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_atari800() {\n    gitPullOrClone\n    if isPlatform \"rpi\"; then\n        applyPatch \"$md_data/01_rpi_fixes.diff\"\n    fi\n}\n\nfunction build_atari800() {\n    local params=()\n    ./autogen.sh\n    isPlatform \"dispmanx\" && params+=(--target=rpi)\n    ./configure --prefix=\"$md_inst\" ${params[@]}\n    make clean\n    make\n    md_ret_require=\"$md_build/src/atari800\"\n}\n\nfunction install_atari800() {\n    cd src\n    make install\n}\n\nfunction _add_emulators_atari800() {\n    local params=()\n    local backend=\"$(getBackend \"$md_id\")\"\n    case \"$backend\" in\n        x11*)\n            # use fullscreen on x11\n            params+=(\"-fullscreen\")\n            # enable hw acceleration by default if supported\n            if isPlatform \"gl\" || isPlatform \"gles\"; then\n                params+=(\"-video-accel\")\n            fi\n            ;;\n        default|x11*)\n            # if backend is set to sdl1 default and we are on kms, we need to set fullscreen\n            # and add width/height params to be filled out by runcommand or else it won't fill the screen\n            isPlatform \"kms\" && params+=(\"-fullscreen\" \"-fs-width %XRES%\" \"-fs-height %YRES%\")\n            ;;\n    esac\n\n    local cmd=\"$md_inst/atari800.sh %ROM% ${params[*]}\"\n    addEmulator 1 \"$md_id\" \"atari800\" \"$cmd\"\n    addEmulator 1 \"$md_id-800\" \"atari800\" \"$cmd -atari\"\n    addEmulator 1 \"$md_id-800xl\" \"atari800\" \"$cmd -xl\"\n    addEmulator 1 \"$md_id-130xe\" \"atari800\" \"$cmd -xe\"\n    addEmulator 1 \"$md_id-5200\" \"atari5200\" \"$cmd -5200\"\n}\n\nfunction configure_atari800() {\n    mkRomDir \"atari800\"\n    mkRomDir \"atari5200\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkUserDir \"$md_conf_root/atari800\"\n\n        # move old config if exists to new location\n        if [[ -f \"$md_conf_root/atari800.cfg\" ]]; then\n            mv \"$md_conf_root/atari800.cfg\" \"$md_conf_root/atari800/atari800.cfg\"\n        fi\n        moveConfigFile \"$home/.atari800.cfg\" \"$md_conf_root/atari800/atari800.cfg\"\n\n        # copy launch script (used for unpacking archives)\n        sed \"s#EMULATOR#/bin/$md_id#\" \"$scriptdir/scriptmodules/$md_type/atari800/atari800.sh\" >\"$md_inst/$md_id.sh\"\n        chmod a+x \"$md_inst/$md_id.sh\"\n    fi\n\n    local params=()\n    # if we are on fkms, use the sdl1 dispmanx backend by default for good performance without using X11/opengl\n    isPlatform kms && isPlatform \"dispmanx\" && _backend_set_atari800 \"dispmanx\"\n\n    # when no dispmanx is available, but still on KMS, use 'sdl12-compat' and go through SDL2\n    isPlatform \"kms\" && ! isPlatform \"dispmanx\" _&& _backend_set_atari800 \"sdl12-compat\"\n\n    # this is split out so we can call it via _backend_set_atari800\n    _add_emulators_atari800\n    addSystem \"atari800\"\n    addSystem \"atari5200\"\n\n}\n\nfunction _backend_set_atari800() {\n    local mode=\"$1\"\n    local force=\"$2\"\n    setBackend \"$md_id\" \"$mode\" \"$force\"\n    setBackend \"$md_id-800\" \"$mode\" \"$force\"\n    setBackend \"$md_id-800xl\" \"$mode\" \"$force\"\n    setBackend \"$md_id-130xe\" \"$mode\" \"$force\"\n    setBackend \"$md_id-5200\" \"$mode\" \"$force\"\n    # call _add_emulators_atari800 again (unless called from configure_atari800) as the emulator.cfg\n    # entries differ depending on backend\n    [[ \"${FUNCNAME[1]}\" != \"configure_atari800\" ]] && _add_emulators_atari800\n}\n"
  },
  {
    "path": "scriptmodules/emulators/basilisk.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"basilisk\"\nrp_module_desc=\"Macintosh emulator\"\nrp_module_help=\"ROM Extensions: .img .rom\\n\\nCopy your Macintosh roms mac.rom and disk.img to $romdir/macintosh\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/cebix/macemu/master/BasiliskII/COPYING\"\nrp_module_repo=\"git https://github.com/cebix/macemu.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction depends_basilisk() {\n    local depends=(libsdl1.2-dev autoconf automake oss-compat)\n    isPlatform \"x11\" && depends+=(libgtk2.0-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_basilisk() {\n    gitPullOrClone\n}\n\nfunction build_basilisk() {\n    cd BasiliskII/src/Unix\n    local params=(--enable-sdl-video --enable-sdl-audio --disable-vosf --without-mon --without-esd)\n    ! isPlatform \"x86\" && params+=(--disable-jit-compiler)\n    ! isPlatform \"x11\" && params+=(--without-x --without-gtk)\n    isPlatform \"aarch64\" && params+=(--build=arm)\n    ./autogen.sh --prefix=\"$md_inst\" \"${params[@]}\"\n    make clean\n    make\n    md_ret_require=\"$md_build/BasiliskII/src/Unix/BasiliskII\"\n}\n\nfunction install_basilisk() {\n    cd \"BasiliskII/src/Unix\"\n    make install\n}\n\nfunction configure_basilisk() {\n    local params=()\n    isPlatform \"kms\" && params+=(\"--screen win/%XRES%/%YRES%\")\n\n    mkRomDir \"macintosh\"\n    touch \"$romdir/macintosh/Start.txt\"\n\n    mkUserDir \"$md_conf_root/macintosh\"\n\n    addEmulator 1 \"$md_id\" \"macintosh\" \"$md_inst/bin/BasiliskII --rom $romdir/macintosh/mac.rom --disk $romdir/macintosh/disk.img --extfs $romdir/macintosh --config $md_conf_root/macintosh/basiliskii.cfg ${params[*]}\"\n    addSystem \"macintosh\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/capricerpi.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"capricerpi\"\nrp_module_desc=\"Amstrad CPC emulator - port of Caprice32 for the RPI\"\nrp_module_help=\"ROM Extensions: .cdt .cpc .dsk\\n\\nCopy your Amstrad CPC games to $romdir/amstradcpc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/KaosOverride/CapriceRPI/master/COPYING.txt\"\nrp_module_repo=\"git https://github.com/KaosOverride/CapriceRPI.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1\"\n\nfunction depends_capricerpi() {\n    getDepends libsdl1.2-dev libsdl-image1.2-dev libsdl-ttf2.0-dev zlib1g-dev libpng-dev\n}\n\nfunction sources_capricerpi() {\n    gitPullOrClone\n    sed -i \"s/-lpng12/-lpng/\" src/makefile\n}\n\nfunction build_capricerpi() {\n    cd src\n    make clean\n\n    make RELEASE=TRUE\n    md_ret_require=\"$md_build/src/capriceRPI\"\n}\n\nfunction install_capricerpi() {\n    cp -Rv \"$md_build/\"{README*.txt,COPYING.txt} \"$md_inst/\"\n    cp -Rv \"$md_build/src/capriceRPI\" \"$md_inst/\"\n}\n\nfunction configure_capricerpi() {\n    mkRomDir \"amstradcpc\"\n\n    addEmulator 0 \"$md_id\" \"amstradcpc\" \"$md_inst/capriceRPI %ROM%\"\n    addSystem \"amstradcpc\"\n\n    [[ $mode == \"remove\" ]] && return\n    # use sdl12-compat backend on KMS\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/coolcv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"coolcv\"\nrp_module_desc=\"CoolCV Colecovision Emulator\"\nrp_module_help=\"ROM Extensions: .bin .col .rom .zip\\n\\nCopy your Colecovision roms to $romdir/coleco\"\nrp_module_licence=\"PROP\"\nrp_module_repo=\"file $__archive_url/coolcv.tar.gz\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_coolcv() {\n    getDepends libsdl2-dev\n}\n\nfunction install_bin_coolcv() {\n    downloadAndExtract \"$md_repo_url\" \"$md_inst\" --strip-components 1\n    patchVendorGraphics \"$md_inst/coolcv_pi\"\n}\n\nfunction configure_coolcv() {\n    mkRomDir \"coleco\"\n\n    moveConfigFile \"$home/coolcv_mapping.txt\" \"$md_conf_root/coleco/coolcv_mapping.txt\"\n\n    addEmulator 1 \"$md_id\" \"coleco\" \"$md_inst/coolcv_pi %ROM%\"\n    addSystem \"coleco\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/daphne/dapinput.ini",
    "content": "# Daphne cutom keyboard and joystick mapping\n#\n# Each input is mapped to 2 keyboard keys and one joystick button.\n# A joystick's first analog stick is also automatically mapped.\n#\n# The first two numbers are SDL keyboard codes (or 0 for \"none\")\n# Find keyboard codes here:\n# http://www.daphne-emu.com/mediawiki/index.php/KeyList\n#\n# The third number is the joystick button code (or 0 for \"none\")\n# Since 0 is reserved for special meaning, joystick button 0 is identified\n# as 1 here.  Button 1 is identified as 2, and so on.\n# \n# Find the button you want to map by running:\n# jstest /dev/input/js0\n\n[KEYBOARD]\nKEY_UP = 273 114 5\nKEY_DOWN = 274 102 7\nKEY_LEFT = 276 100 8\nKEY_RIGHT = 275 103 6\nKEY_BUTTON1 = 306 97 14\nKEY_BUTTON2 = 308 115 15\nKEY_BUTTON3 = 32 113 16\nKEY_START1 = 49 0 4\nKEY_START2 = 50 0 0\nKEY_COIN1 = 53 0 1\nKEY_COIN2 = 54 0 0\nKEY_SKILL1 = 304 119 0\nKEY_SKILL2 = 122 105 0\nKEY_SKILL3 = 120 107 0\nKEY_SERVICE = 57 0 0\nKEY_TEST = 283 0 0\nKEY_RESET = 284 0 0\nKEY_SCREENSHOT = 293 0 0\nKEY_QUIT = 27 113 17\nEND\n"
  },
  {
    "path": "scriptmodules/emulators/daphne.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"daphne\"\nrp_module_desc=\"Daphne - Laserdisc Emulator\"\nrp_module_help=\"ROM Extension: .daphne\\n\\nCopy your Daphne roms to $romdir/daphne\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/daphne-emu/master/COPYING\"\nrp_module_repo=\"git https://github.com/RetroPie/daphne-emu.git retropie\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !x86 !mali\"\n\nfunction depends_daphne() {\n    getDepends libsdl1.2-dev libvorbis-dev libglew-dev zlib1g-dev\n}\n\nfunction sources_daphne() {\n    gitPullOrClone\n}\n\nfunction build_daphne() {\n    local params=()\n    isPlatform \"aarch64\" && params=(--build=arm)\n    cd src/vldp2\n    ./configure \"${params[@]}\"\n    make -f Makefile.rp\n    cd ..\n    ln -sf Makefile.vars.rp Makefile.vars\n    make STATIC_VLDP=1\n    md_ret_require=\"$md_build/daphne.bin\"\n}\n\nfunction install_daphne() {\n    md_ret_files=(\n        'sound'\n        'pics'\n        'daphne.bin'\n        'COPYING'\n    )\n}\n\nfunction configure_daphne() {\n    mkRomDir \"daphne\"\n    mkRomDir \"daphne/roms\"\n\n    addEmulator 1 \"$md_id\" \"daphne\" \"$md_inst/daphne.sh %ROM%\"\n    addSystem \"daphne\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkUserDir \"$md_conf_root/daphne\"\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    if [[ ! -f \"$md_conf_root/daphne/dapinput.ini\" ]]; then\n        cp -v \"$md_data/dapinput.ini\" \"$md_conf_root/daphne/dapinput.ini\"\n    fi\n    ln -snf \"$romdir/daphne/roms\" \"$md_inst/roms\"\n    ln -sf \"$md_conf_root/$md_id/dapinput.ini\" \"$md_inst/dapinput.ini\"\n\n    cat >\"$md_inst/daphne.sh\" <<_EOF_\n#!/bin/bash\ndir=\"\\$1\"\nname=\"\\${dir##*/}\"\nname=\"\\${name%.*}\"\n\nif [[ -f \"\\$dir/\\$name.commands\" ]]; then\n    params=\\$(<\"\\$dir/\\$name.commands\")\nfi\n\n\"$md_inst/daphne.bin\" \"\\$name\" vldp -nohwaccel -framefile \"\\$dir/\\$name.txt\" -homedir \"$md_inst\" -fullscreen \\$params\n_EOF_\n    chmod +x \"$md_inst/daphne.sh\"\n\n    chown -R \"$__user\":\"$__group\" \"$md_inst\"\n    chown -R \"$__user\":\"$__group\" \"$md_conf_root/daphne/dapinput.ini\"\n\n}\n"
  },
  {
    "path": "scriptmodules/emulators/dgen.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dgen\"\nrp_module_desc=\"Megadrive/Genesis emulator DGEN\"\nrp_module_help=\"ROM Extensions: .32x .iso .cue .smd .bin .gen .md .sg .zip\\n\\nCopy your  Megadrive / Genesis roms to $romdir/megadrive\\nSega 32X roms to $romdir/sega32x\\nand SegaCD roms to $romdir/segacd\\nThe Sega CD requires the BIOS files bios_CD_U.bin, bios_CD_E.bin, and bios_CD_J.bin copied to $biosdir\"\nrp_module_licence=\"GPL2 https://sourceforge.net/p/dgen/dgen/ci/master/tree/COPYING\"\nrp_module_repo=\"file $__archive_url/dgen-sdl-1.33.tar.gz\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali !kms\"\n\nfunction depends_dgen() {\n    getDepends libsdl1.2-dev libarchive-dev\n}\n\nfunction sources_dgen() {\n    downloadAndExtract \"$md_repo_url\" \"$md_build\" --strip-components 1\n}\n\nfunction build_dgen() {\n    local params=()\n    isPlatform \"rpi\" && params+=(--disable-opengl --disable-hqx)\n    # dgen contains obsoleted arm assembler that gcc/as will not like for armv8 cpu targets\n    if isPlatform \"armv8\"; then\n        CFLAGS=\"-O2 -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard\" ./configure --prefix=\"$md_inst\"\n    else\n        ./configure --prefix=\"$md_inst\"\n    fi\n    make clean\n    make\n    md_ret_require=\"$md_build/dgen\"\n}\n\nfunction install_dgen() {\n    make install\n    cp \"sample.dgenrc\" \"$md_inst/\"\n    md_ret_require=\"$md_inst/bin/dgen\"\n}\n\nfunction configure_dgen() {\n    local system\n    for system in megadrive segacd sega32x; do\n        mkRomDir \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/bin/dgen -r $md_conf_root/megadrive/dgenrc %ROM%\"\n        addSystem \"$system\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkUserDir \"$md_conf_root/megadrive\"\n\n    # move config from previous location\n    if [[ -f \"$configdir/all/dgenrc\" ]]; then\n        mv -v \"$configdir/all/dgenrc\" \"$md_conf_root/megadrive/dgenrc\"\n    fi\n\n    if [[ ! -f \"$md_conf_root/megadrive/dgenrc\" ]]; then\n        cp \"sample.dgenrc\" \"$md_conf_root/megadrive/dgenrc\"\n        chown \"$__user\":\"$__group\" \"$md_conf_root/megadrive/dgenrc\"\n    fi\n\n    iniConfig \" = \" \"\" \"$md_conf_root/megadrive/dgenrc\"\n\n    if isPlatform \"rpi\"; then\n        iniSet \"int_width\" \"320\"\n        iniSet \"int_height\" \"240\"\n        iniSet \"bool_doublebuffer\" \"no\"\n        iniSet \"bool_screen_thread\" \"yes\"\n        iniSet \"scaling_startup\" \"none\"\n\n        # we don't have opengl (or build dgen with it)\n        iniSet \"bool_opengl\" \"no\"\n\n        # lower sample rate\n        iniSet \"int_soundrate\" \"22050\"\n\n        iniSet \"emu_z80_startup\" \"drz80\"\n        iniSet \"emu_m68k_startup\" \"cyclone\"\n    fi\n\n    iniSet \"joy_pad1_a\" \"joystick0-button0\"\n    iniSet \"joy_pad1_b\" \"joystick0-button1\"\n    iniSet \"joy_pad1_c\" \"joystick0-button2\"\n    iniSet \"joy_pad1_x\" \"joystick0-button3\"\n    iniSet \"joy_pad1_y\" \"joystick0-button4\"\n    iniSet \"joy_pad1_z\" \"joystick0-button5\"\n    iniSet \"joy_pad1_mode\" \"joystick0-button6\"\n    iniSet \"joy_pad1_start\" \"joystick0-button7\"\n\n    iniSet \"joy_pad2_a\" \"joystick1-button0\"\n    iniSet \"joy_pad2_b\" \"joystick1-button1\"\n    iniSet \"joy_pad2_c\" \"joystick1-button2\"\n    iniSet \"joy_pad2_x\" \"joystick1-button3\"\n    iniSet \"joy_pad2_y\" \"joystick1-button4\"\n    iniSet \"joy_pad2_z\" \"joystick1-button5\"\n    iniSet \"joy_pad2_mode\" \"joystick1-button6\"\n    iniSet \"joy_pad2_start\" \"joystick1-button7\"\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/dolphin.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dolphin\"\nrp_module_desc=\"Gamecube/Wii emulator Dolphin\"\nrp_module_help=\"ROM Extensions: .gcm .iso .wbfs .ciso .gcz .rvz .wad .wbfs\\n\\nCopy your Gamecube roms to $romdir/gc and Wii roms to $romdir/wii\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/dolphin-emu/dolphin/master/COPYING\"\nrp_module_repo=\"git https://github.com/dolphin-emu/dolphin.git master :_get_commit_dolphin\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all 64bit !:\\$__gcc_version:-lt:8\"\n\nfunction _get_commit_dolphin() {\n    local commit\n    local has_qt6=$(apt-cache -qq madison qt6-base-private-dev | cut -d'|' -f1)\n    # current HEAD of dolphin doesn't build without a C++20 capable compiler ..\n    [[ \"$__gcc_version\" -lt 10 ]] && commit=\"f59f1a2a\"\n    # .. and without QT6\n    [[ -z \"$has_qt6\" ]] && commit=\"b9a7f577\"\n    # support gcc 8.4.0 for Ubuntu 18.04\n    [[ \"$__gcc_version\" -lt 9  ]] && commit=\"1c0ca09e\"\n    echo \"$commit\"\n}\n\nfunction depends_dolphin() {\n    local depends=(cmake gettext pkg-config libao-dev libasound2-dev libavcodec-dev libavformat-dev libbluetooth-dev libenet-dev liblzo2-dev libminiupnpc-dev libopenal-dev libpulse-dev libreadline-dev libsfml-dev libsoil-dev libsoundtouch-dev libswscale-dev libusb-1.0-0-dev libxext-dev libxi-dev libxrandr-dev portaudio19-dev zlib1g-dev libudev-dev libevdev-dev libmbedtls-dev libcurl4-openssl-dev libegl1-mesa-dev liblzma-dev)\n    # check if qt6 is available, otherwise use qt5\n    local has_qt6=$(apt-cache -qq madison qt6-base-private-dev | cut -d'|' -f1)\n    if [[ -n \"$has_qt6\" ]]; then\n        depends+=(qt6-base-private-dev)\n        # Older Ubuntu versions provide libqt6svg6-dev instead of Debian's qt6-svg-dev\n        if [[ -n \"$__os_ubuntu_ver\" ]] && compareVersions \"$__os_ubuntu_ver\" lt 23.04; then\n            depends+=(libqt6svg6-dev)\n        else\n            depends+=(qt6-svg-dev)\n        fi\n    else\n        depends+=(qtbase5-private-dev)\n    fi\n    # on KMS use x11 to start the emulator\n    isPlatform \"kms\" && depends+=(xorg matchbox-window-manager)\n\n    # if using the latest version, add SDL2 as dependency, since it's mandatory\n    [[ \"$(_get_commit_dolphin)\" == \"\" ]] && depends+=(libsdl2-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_dolphin() {\n    gitPullOrClone\n}\n\nfunction build_dolphin() {\n    mkdir build\n    cd build\n    # use the bundled 'speexdsp' libs, distro versions before 1.2.1 trigger a 'cmake' error\n    cmake .. -DBUNDLE_SPEEX=ON -DENABLE_AUTOUPDATE=OFF -DENABLE_ANALYTICS=OFF  -DUSE_DISCORD_PRESENCE=OFF -DCMAKE_INSTALL_PREFIX=\"$md_inst\"\n    make clean\n    make\n    md_ret_require=\"$md_build/build/Binaries/dolphin-emu\"\n}\n\nfunction install_dolphin() {\n    cd build\n    make install\n}\n\nfunction configure_dolphin() {\n    mkRomDir \"gc\"\n    mkRomDir \"wii\"\n\n    local launch_prefix\n    isPlatform \"kms\" && launch_prefix=\"XINIT-WM:\"\n\n    addEmulator 0 \"$md_id\" \"gc\" \"$launch_prefix$md_inst/bin/dolphin-emu-nogui -e %ROM%\"\n    addEmulator 1 \"$md_id-gui\" \"gc\" \"$launch_prefix$md_inst/bin/dolphin-emu -b -e %ROM%\"\n    addEmulator 0 \"$md_id\" \"wii\" \"$launch_prefix$md_inst/bin/dolphin-emu-nogui -e %ROM%\"\n    addEmulator 1 \"$md_id-gui\" \"wii\" \"$launch_prefix$md_inst/bin/dolphin-emu -b -e %ROM%\"\n\n    addSystem \"gc\"\n    addSystem \"wii\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # Move the other dolphin-emu options, memory card saves etc\n    moveConfigDir \"$home/.local/share/dolphin-emu\" \"$md_conf_root/gc/local\"\n    mkUserDir \"$md_conf_root/gc/local\"\n\n    moveConfigDir \"$home/.config/dolphin-emu\" \"$md_conf_root/gc/Config\"\n    mkUserDir \"$md_conf_root/gc/Config\"\n    # preset a few options on a first installation\n    if [[ ! -f \"$md_conf_root/gc/Config/Dolphin.ini\" ]]; then\n        cat >\"$md_conf_root/gc/Config/Dolphin.ini\" <<_EOF_\n[Display]\nFullscreenDisplayRes = Auto\nFullscreen = True\nRenderToMain = True\nKeepWindowOnTop = True\n[Interface]\nConfirmStop = False\n[General]\nISOPath0 = \"$home/RetroPie/roms/gc\"\nISOPath1 = \"$home/RetroPie/roms/wii\"\nISOPaths = 2\n[Core]\nAutoDiscChange = True\n_EOF_\n    fi\n    # use the GLES(3) render path on platforms where it's available\n    if [[ ! -f \"$md_conf_root/gc/Config/GFX.ini\" ]] && isPlatform \"gles3\"; then\n        cat >\"$md_conf_root/gc/Config/GFX.ini\" <<_EOF2_\n[Settings]\nPreferGLES = True\n_EOF2_\n    fi\n\n    chown -R \"$__user\":\"$__group\" \"$md_conf_root/gc/Config\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox/01-fully-bindable-joystick.diff",
    "content": "--- 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.474081295 +0000\n@@ -69,6 +69,8 @@\n #define MAXACTIVE 16\n #define MAXBUTTON 32\n #define MAXBUTTON_CAP 16\n+#define MAXAXIS 8\n+#define MAXHAT 2\n \n class CEvent;\n class CHandlerEvent;\n@@ -634,8 +636,8 @@\n \t\tif (_dummy) return;\n \n \t\t// initialize binding lists and position data\n-\t\tpos_axis_lists=new CBindList[4];\n-\t\tneg_axis_lists=new CBindList[4];\n+\t\tpos_axis_lists=new CBindList[MAXAXIS];\n+\t\tneg_axis_lists=new CBindList[MAXAXIS];\n \t\tbutton_lists=new CBindList[MAXBUTTON];\n \t\that_lists=new CBindList[4];\n \t\tBitu i;\n@@ -644,7 +646,7 @@\n \t\t\told_button_state[i]=0;\n \t\t}\n \t\tfor(i=0;i<16;i++) old_hat_state[i]=0;\n-\t\tfor (i=0; i<4; i++) {\n+\t\tfor (i=0; i<MAXAXIS; i++) {\n \t\t\told_pos_axis_state[i]=false;\n \t\t\told_neg_axis_state[i]=false;\n \t\t}\n@@ -662,8 +664,16 @@\n \t\t}\n \n \t\taxes=SDL_JoystickNumAxes(sdl_joystick);\n-\t\tbuttons=SDL_JoystickNumButtons(sdl_joystick);\n+\t\tif (axes > MAXAXIS) axes = MAXAXIS;\n+\t\taxes_cap=emulated_axes;\n+\t\tif (axes_cap>axes) axes_cap=axes;\n+\n \t\thats=SDL_JoystickNumHats(sdl_joystick);\n+\t\tif (hats > MAXHAT) hats = MAXHAT;\n+\t\thats_cap=emulated_hats;\n+\t\tif (hats_cap>hats) hats_cap=hats;\n+\n+\t\tbuttons=SDL_JoystickNumButtons(sdl_joystick);\n \t\tbutton_wrap=buttons;\n \t\tbutton_cap=buttons;\n \t\tif (button_wrapping_enabled) {\n@@ -671,10 +681,7 @@\n \t\t\tif (buttons>MAXBUTTON_CAP) button_cap = MAXBUTTON_CAP;\n \t\t}\n \t\tif (button_wrap > MAXBUTTON) button_wrap = MAXBUTTON;\n-\t\taxes_cap=emulated_axes;\n-\t\tif (axes_cap>axes) axes_cap=axes;\n-\t\thats_cap=emulated_hats;\n-\t\tif (hats_cap>hats) hats_cap=hats;\n+\n \t\tLOG_MSG(\"Using joystick %s with %d axes, %d buttons and %d hat(s)\",SDL_JoystickName(stick),axes,buttons,hats);\n \t}\n \t~CStickBindGroup() {\n@@ -707,7 +714,7 @@\n \t\tif (event->type==SDL_JOYAXISMOTION) {\n \t\t\tif (event->jaxis.which!=stick) return 0;\n #if defined (REDUCE_JOYSTICK_POLLING)\n-\t\t\tif (event->jaxis.axis>=emulated_axes) return 0;\n+\t\t\tif (event->jaxis.axis>=axes) return 0;\n #endif\n \t\t\tif (abs(event->jaxis.value)<25000) return 0;\n \t\t\treturn CreateAxisBind(event->jaxis.axis,event->jaxis.value>0);\n@@ -799,7 +806,7 @@\n \t\t\t}\n \t\t}\n \n-\t\tfor (i=0; i<axes_cap; i++) {\n+\t\tfor (i=0; i<axes; i++) {\n \t\t\tSint16 caxis_pos=SDL_JoystickGetAxis(sdl_joystick,i);\n \t\t\t/* activate bindings for joystick position */\n \t\t\tif (caxis_pos>1) {\n@@ -831,7 +838,7 @@\n \t\t\t}\n \t\t}\n \n-\t\tfor (i=0; i<hats_cap; i++) {\n+\t\tfor (i=0; i<hats; i++) {\n \t\t\tUint8 chat_state=SDL_JoystickGetHat(sdl_joystick,i);\n \n \t\t\t/* activate binding if hat state has changed */\n@@ -857,7 +864,7 @@\n \n private:\n \tCBind * CreateAxisBind(Bitu axis,bool positive) {\n-\t\tif (axis<emulated_axes) {\n+\t\tif (axis<axes) {\n \t\t\tif (positive) return new CJAxisBind(&pos_axis_lists[axis],this,axis,positive);\n \t\t\telse return new CJAxisBind(&neg_axis_lists[axis],this,axis,positive);\n \t\t}\n@@ -896,8 +903,8 @@\n \tchar configname[10];\n \tBitu button_autofire[MAXBUTTON];\n \tbool old_button_state[MAXBUTTON];\n-\tbool old_pos_axis_state[16];\n-\tbool old_neg_axis_state[16];\n+\tbool old_pos_axis_state[MAXAXIS];\n+\tbool old_neg_axis_state[MAXAXIS];\n \tUint8 old_hat_state[16];\n \tbool is_dummy;\n };\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox-sdl2/001-sd2.0-check-remove.diff",
    "content": "diff --git a/configure.ac b/configure.ac\nindex 407d553..731d960 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -31,20 +31,6 @@ EXULT_CHECK_SDL(:,AC_MSG_ERROR([[*** SDL not found!]]))\n LIBS=\"$LIBS $SDL_LIBS\"\n CPPFLAGS=\"$CPPFLAGS $SDL_CFLAGS\"\n \n-dnl Check if SDL is 2.0.x\n-AC_MSG_CHECKING([for SDL version being 2.0.x])\n-AC_COMPILE_IFELSE([AC_LANG_SOURCE([\n-#include \"SDL.h\"\n-void blah(){\n-#if !((SDL_MAJOR_VERSION == 2) && (SDL_MINOR_VERSION == 0))\n-#error \"Only SDL 2.0 supported\"\n-#endif\n-;\n-}\n-])],AC_MSG_RESULT([yes]),[\n- AC_MSG_RESULT([no]) \n- AC_MSG_ERROR([Only libSDL 2.0.x supported])])\n-\n dnl Checks for header files.\n \n dnl Checks for typedefs, structures, and compiler characteristics.\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox-sdl2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dosbox-sdl2\"\nrp_module_desc=\"DOS emulator (enhanced DOSBox fork)\"\nrp_module_help=\"ROM Extensions: .bat .com .exe .sh .conf\\n\\nCopy your DOS games to $romdir/pc\"\nrp_module_licence=\"GPL2 https://sourceforge.net/p/dosbox/code-0/HEAD/tree/dosbox/trunk/COPYING\"\nrp_module_repo=\"git https://github.com/duganchen/dosbox.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_dosbox-sdl2() {\n    local depends=(alsa-utils libsdl2-dev libsdl2-net-dev libfluidsynth-dev fluid-soundfont-gm libglew-dev)\n    depends_dosbox \"${depends[@]}\"\n}\n\nfunction sources_dosbox-sdl2() {\n    gitPullOrClone\n    # use custom config filename & path to allow coexistence with regular dosbox\n    sed -i \"src/misc/cross.cpp\" -e 's/~\\/.dosbox/~\\/.'$md_id'/g' \\\n       -e 's/DEFAULT_CONFIG_FILE \"dosbox-\"/DEFAULT_CONFIG_FILE \"'$md_id'-\"/g'\n    # patch the SDL2 detection to remove the strict 2.0.x version check\n    applyPatch \"$md_data/001-sd2.0-check-remove.diff\"\n}\n\nfunction build_dosbox-sdl2() {\n    build_dosbox\n}\n\nfunction install_dosbox-sdl2() {\n    install_dosbox\n}\n\nfunction configure_dosbox-sdl2() {\n    configure_dosbox\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        local config_path=$(su \"$__user\" -c \"\\\"$md_inst/bin/dosbox\\\" -printconf\")\n        if [[ -f \"$config_path\" ]]; then\n            iniConfig \"=\" \"\" \"$config_path\"\n            iniSet \"fluid.driver\" \"alsa\"\n            iniSet \"fluid.soundfont\" \"/usr/share/sounds/sf2/FluidR3_GM.sf2\"\n            iniSet \"fullresolution\" \"desktop\"\n            iniSet \"fullscreen\" \"true\"\n            iniSet \"mididevice\" \"fluidsynth\"\n            iniSet \"output\" \"texture\"\n            iniDel \"usescancodes\"\n            isPlatform \"kms\" && iniSet \"vsync\" \"true\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox-staging/0.82.x-kmsdrm-fix.diff",
    "content": "# Workaround backported to 0.82.x from \n# https://github.com/dosbox-staging/dosbox-staging/pull/4589/commits/525e98ca3403ef548ba500bcf79a9e797929655c \n# \ndiff --git a/src/gui/sdlmain.cpp b/src/gui/sdlmain.cpp\nindex 04b7641..d17c2e6 100644\n--- a/src/gui/sdlmain.cpp\n+++ b/src/gui/sdlmain.cpp\n@@ -1361,6 +1361,14 @@ static SDL_Window* SetWindowMode(const RenderingBackend rendering_backend,\n \n \t\tassert(sdl.window == nullptr); // enusre we don't leak\n \t\tsdl.window = SDL_CreateWindow(\"\", pos.x, pos.y, width, height, flags);\n+\t\tif (!sdl.window) {\n+\t\t\t// Try again without sRGB. This has been a problem with KMSDRM.\n+\t\t\tSDL_GL_SetAttribute(SDL_GL_FRAMEBUFFER_SRGB_CAPABLE, 0);\n+\t\t\tsdl.window = SDL_CreateWindow(\"\", pos.x, pos.y, width, height, flags);\n+\t\t\tif (sdl.window) {\n+\t\t\t\tLOG_ERR(\"OPENGL: Failed to create an sRGB framebuffer. Falling back to non-sRGB.\");\n+\t\t\t}\n+\t\t}\n \t\tif (!sdl.window) {\n \t\t\tLOG_ERR(\"SDL: Failed to create window: %s\", SDL_GetError());\n \t\t\treturn nullptr;\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox-staging.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dosbox-staging\"\nrp_module_desc=\"modern DOS/x86 emulator focusing on ease of use\"\nrp_module_help=\"ROM Extensions: .bat .com .exe .sh .conf\\n\\nCopy your DOS games to $romdir/pc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/dosbox-staging/dosbox-staging/master/COPYING\"\nrp_module_repo=\"git https://github.com/dosbox-staging/dosbox-staging.git :_get_branch_dosbox-staging\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2\"\n\nfunction _get_branch_dosbox-staging() {\n    local branch=\"v0.82.2\"\n\n    # use 0.80.1 for VideoCore devices, 0.81 and later require OpenGL\n    if isPlatform \"videocore\"; then\n        branch=\"v0.80.1\"\n    # v0.81.2 is the last version that can build on gcc < 10\n    elif [[ \"$__gcc_version\" -lt 10 ]]; then\n        branch=\"v0.81.2\"\n    # v0.82.0 is the last version that can build on gcc < 11\n    elif [[ \"$__gcc_version\" -lt 11 ]]; then\n        branch=\"v0.82.0\"\n    fi\n\n    echo \"$branch\"\n}\n\nfunction depends_dosbox-staging() {\n    local depends\n    depends=(cmake libasound2-dev libglib2.0-dev libopusfile-dev libpng-dev libsdl2-dev libsdl2-net-dev libspeexdsp-dev meson ninja-build zlib1g-dev)\n    if [[ \"$__os_debian_ver\" -ge 11 ]]; then\n        depends+=(libslirp-dev libfluidsynth-dev)\n    else\n        # the slirp subproject requires libsdl2-image-dev to build\n        depends+=(libsdl2-image-dev)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_dosbox-staging() {\n    gitPullOrClone\n    # patch 0.81.x/0.82.x series with fix for kmsdrm\n    if [[ \"$(_get_branch_dosbox-staging)\" == v0.8[12].*  ]]; then\n        applyPatch \"$md_data/0.82.x-kmsdrm-fix.diff\"\n    fi\n    # Check if we have at least meson>=0.57, otherwise install it locally for the build\n    local meson_version=\"$(meson --version)\"\n    if compareVersions \"$meson_version\" lt 0.57; then\n        downloadAndExtract \"https://github.com/mesonbuild/meson/releases/download/0.61.5/meson-0.61.5.tar.gz\" meson --strip-components 1\n    fi\n}\n\nfunction build_dosbox-staging() {\n    local params=(-Dprefix=\"$md_inst\" -Ddatadir=\"resources\" -Dtry_static_libs=\"iir,mt32emu\")\n    # use the build local Meson installation if found\n    local meson_cmd=\"meson\"\n    [[ -f \"$md_build/meson/meson.py\" ]] && meson_cmd=\"python3 $md_build/meson/meson.py\"\n\n    # disable speexdsp simd support on armv6 devices\n    isPlatform \"armv6\" && params+=(-Dspeexdsp:simd=false)\n\n    $meson_cmd setup \"${params[@]}\" build\n    $meson_cmd compile -j${__jobs} -C build\n\n    md_ret_require=(\n        \"$md_build/build/dosbox\"\n    )\n}\n\nfunction install_dosbox-staging() {\n    ninja -C build install\n}\n\nfunction configure_dosbox-staging() {\n    configure_dosbox\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local config_dir=\"$md_conf_root/pc\"\n    chown -R \"$__user\":\"$__group\" \"$config_dir\"\n\n    local staging_output=\"texturenb\"\n    if isPlatform \"kms\"; then\n        staging_output=\"openglnb\"\n    fi\n\n    local config_path=$(su \"$__user\" -c \"\\\"$md_inst/bin/dosbox\\\" -printconf\")\n    if [[ -f \"$config_path\" ]]; then\n        iniConfig \" = \" \"\" \"$config_path\"\n        if isPlatform \"rpi\"; then\n            iniSet \"fullscreen\" \"true\"\n            iniSet \"fullresolution\" \"original\"\n            iniSet \"vsync\" \"true\"\n            iniSet \"output\" \"$staging_output\"\n            iniSet \"core\" \"dynamic\"\n            iniSet \"blocksize\" \"2048\"\n            iniSet \"prebuffer\" \"50\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/dosbox.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dosbox\"\nrp_module_desc=\"DOS emulator\"\nrp_module_help=\"ROM Extensions: .bat .com .exe .sh .conf\\n\\nCopy your DOS games to $romdir/pc\"\nrp_module_licence=\"GPL2 https://sourceforge.net/p/dosbox/code-0/HEAD/tree/dosbox/trunk/COPYING\"\nrp_module_repo=\"svn https://svn.code.sf.net/p/dosbox/code-0/dosbox/trunk - 4252\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction depends_dosbox() {\n    local depends=(alsa-utils libasound2-dev libpng-dev automake autoconf zlib1g-dev \"$@\")\n    [[ \"$md_id\" == \"dosbox\" ]] && depends+=(libsdl1.2-dev libsdl-net1.2-dev libsdl-sound1.2-dev)\n    isPlatform \"rpi\" && depends+=(timidity freepats)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_dosbox() {\n    local revision=\"$1\"\n    [[ -z \"$revision\" ]] && revision=\"4252\"\n\n    svn checkout \"$md_repo_url\" \"$md_build\" -r \"$revision\"\n    applyPatch \"$md_data/01-fully-bindable-joystick.diff\"\n}\n\nfunction build_dosbox() {\n    local params=()\n\n    ! isPlatform \"x11\" && params+=(--disable-opengl)\n    # add or override params from calling function\n    params+=(\"$@\")\n\n    ./autogen.sh\n    ./configure --prefix=\"$md_inst\" \"${params[@]}\"\n    if isPlatform \"arm\"; then\n        # enable dynamic recompilation for armv4\n        sed -i 's|/\\* #undef C_DYNREC \\*/|#define C_DYNREC 1|' config.h\n        if isPlatform \"armv6\"; then\n            sed -i 's/C_TARGETCPU.*/C_TARGETCPU ARMV4LE/g' config.h\n        else\n            sed -i 's/C_TARGETCPU.*/C_TARGETCPU ARMV7LE/g' config.h\n            sed -i 's|/\\* #undef C_UNALIGNED_MEMORY \\*/|#define C_UNALIGNED_MEMORY 1|' config.h\n        fi\n    fi\n    make clean\n    make\n    md_ret_require=\"$md_build/src/dosbox\"\n}\n\nfunction install_dosbox() {\n    make install\n    md_ret_require=\"$md_inst/bin/dosbox\"\n}\n\nfunction configure_dosbox() {\n    local def=0\n    local launcher_name=\"+Start DOSBox.sh\"\n    local needs_synth=0\n    local config_dir=\"$home/.$md_id\"\n    case \"$md_id\" in\n        dosbox-sdl2)\n            launcher_name=\"+Start DOSBox-SDL2.sh\"\n            ;;\n        dosbox)\n            def=1\n            # needs software synth for midi; limit to Pi for now\n            isPlatform \"rpi\" && needs_synth=1\n            # set dispmanx by default on rpi with fkms\n            isPlatform \"dispmanx\" && ! isPlatform \"videocore\" && setBackend \"$md_id\" \"dispmanx\"\n            ;;\n        dosbox-staging)\n            launcher_name=\"+Start DOSBox-Staging.sh\"\n            config_dir=\"$home/.config/dosbox\"\n            ;;\n        *)\n            return 1\n            ;;\n    esac\n\n    mkRomDir \"pc\"\n\n    moveConfigDir \"$config_dir\" \"$md_conf_root/pc\"\n\n    addEmulator \"$def\" \"$md_id\" \"pc\" \"bash $romdir/pc/${launcher_name// /\\\\ } %ROM%\"\n    addSystem \"pc\"\n\n    rm -f \"$romdir/pc/$launcher_name\"\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    cat > \"$romdir/pc/$launcher_name\" << _EOF_\n#!/bin/bash\n\n[[ ! -n \"\\$(aconnect -o | grep -e TiMidity -e FluidSynth)\" ]] && needs_synth=\"$needs_synth\"\n\nfunction midi_synth() {\n    [[ \"\\$needs_synth\" != \"1\" ]] && return\n\n    case \"\\$1\" in\n        \"start\")\n            timidity -Os -iAD &\n            i=0\n            until [[ -n \"\\$(aconnect -o | grep TiMidity)\" || \"\\$i\" -ge 10 ]]; do\n                sleep 1\n                ((i++))\n            done\n            ;;\n        \"stop\")\n            killall timidity\n            ;;\n        *)\n            ;;\n    esac\n}\n\nparams=(\"\\$@\")\nif [[ -z \"\\${params[0]}\" ]]; then\n    params=(-c \"@MOUNT C $romdir/pc -freesize 1024\" -c \"@C:\")\nelif [[ \"\\${params[0]}\" == *.sh ]]; then\n    midi_synth start\n    bash \"\\${params[@]}\"\n    midi_synth stop\n    exit\nelif [[ \"\\${params[0]}\" == *.conf ]]; then\n    params=(-userconf -conf \"\\${params[@]}\")\nelse\n    params+=(-exit)\nfi\n\n# fullscreen when running in X\n[[ -n \"\\$DISPLAY\" ]] && params+=(-fullscreen)\n\nmidi_synth start\n\"$md_inst/bin/dosbox\" \"\\${params[@]}\"\nmidi_synth stop\n_EOF_\n    chmod +x \"$romdir/pc/$launcher_name\"\n    chown \"$__user\":\"$__group\" \"$romdir/pc/$launcher_name\"\n\n    if [[ \"$md_id\" == \"dosbox\" || \"$md_id\" == \"dosbox-sdl2\" ]]; then\n        local config_path=$(su \"$__user\" -c \"\\\"$md_inst/bin/dosbox\\\" -printconf\")\n        if [[ -f \"$config_path\" ]]; then\n            iniConfig \" = \" \"\" \"$config_path\"\n            iniSet \"usescancodes\" \"false\"\n            iniSet \"core\" \"dynamic\"\n            iniSet \"cycles\" \"max\"\n            iniSet \"scaler\" \"none\"\n            if isPlatform \"rpi\" || [[ -n \"$(aconnect -o | grep -e TiMidity -e FluidSynth)\" ]]; then\n                iniSet \"mididevice\" \"alsa\"\n                iniSet \"midiconfig\" \"128:0\"\n            fi\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/drastic.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"drastic\"\nrp_module_desc=\"NDS emu - DraStic\"\nrp_module_help=\"ROM Extensions: .nds .zip\\n\\nCopy your Nintendo DS roms to $romdir/nds\"\nrp_module_licence=\"PROP\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2 !all arm !armv6 !mali\"\n\nfunction depends_drastic() {\n    local depends=(libasound2-dev libsdl2-dev zlib1g-dev)\n    if isPlatform \"kms\" && ! isPlatform \"x11\"; then\n        depends+=(matchbox-window-manager xorg xserver-xorg-input-all)\n    fi\n\n    getDepends ${depends[@]}\n}\n\nfunction __binary_url_drastic() {\n   echo \"$__archive_url/drastic-2.5.0.4.tar.gz\"\n}\n\nfunction install_bin_drastic() {\n    downloadAndExtract \"$(__binary_url_drastic)\" \"$md_inst\" --strip-components 1\n}\n\nfunction configure_drastic() {\n    mkRomDir \"nds\"\n\n    addEmulator 1 \"$md_id\" \"nds\" \"$md_inst/drastic.sh %ROM%\"\n    addSystem \"nds\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    isPlatform \"kms\" && ! isPlatform \"x11\" && setBackend \"$md_id\" \"x11\"\n\n    cat > \"$md_inst/drastic.sh\" << _EOF_\n#!/bin/bash\npushd \"$md_conf_root/nds/drastic\"\n$md_inst/drastic \"\\$1\"\npopd\n_EOF_\n    chmod +x \"$md_inst/drastic.sh\"\n\n    # wrong permissions on game_database.xml\n    chmod 644 \"$md_inst/game_database.xml\"\n\n    mkUserDir \"$md_conf_root/nds/drastic\"\n    mkUserDir \"$md_conf_root/nds/drastic/system\"\n\n    local file\n    for file in game_database.xml system/drastic_bios_arm7.bin system/drastic_bios_arm9.bin usrcheat.dat drastic_logo_0.raw drastic_logo_1.raw; do\n        ln -sfv \"$md_inst/$file\" \"$md_conf_root/nds/drastic/$file\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/emulators/fbzx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"fbzx\"\nrp_module_desc=\"ZXSpectrum emulator FBZX\"\nrp_module_help=\"ROM Extensions: .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip\\n\\nCopy your ZX Spectrum to $romdir/zxspectrum\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/rastersoft/fbzx/master/COPYING\"\nrp_module_repo=\"git https://github.com/rastersoft/fbzx :_get_branch_fbzx\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1\"\n\nfunction _get_branch_fbzx() {\n    local branch\n    # use older version for non x86 systems (faster)\n    ! isPlatform \"x86\" && branch=\"2.11.1\"\n    echo \"$branch\"\n}\n\nfunction depends_fbzx() {\n    getDepends libasound2-dev libsdl1.2-dev\n}\n\nfunction sources_fbzx() {\n    gitPullOrClone\n    ! isPlatform \"x86\" && sed -i 's|PREFIX2=$(PREFIX)/usr|PREFIX2=$(PREFIX)|' Makefile\n}\n\nfunction build_fbzx() {\n    make clean\n    make\n    if ! isPlatform \"x86\"; then\n        md_ret_require=\"$md_build/fbzx\"\n    else\n        md_ret_require=\"$md_build/src/fbzx\"\n    fi\n}\n\nfunction install_fbzx() {\n    if ! isPlatform \"x86\"; then\n        mkdir \"$md_inst/bin\"\n    fi\n    make install PREFIX=\"$md_inst\"\n}\n\nfunction configure_fbzx() {\n    mkRomDir \"zxspectrum\"\n\n    addEmulator 0 \"$md_id\" \"zxspectrum\" \"pushd $md_inst/share; $md_inst/bin/fbzx -fs %ROM%; popd\"\n    addSystem \"zxspectrum\"\n\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/frotz.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"frotz\"\nrp_module_desc=\"Z-Machine Interpreter for Infocom games\"\nrp_module_help=\"ROM Extensions: .dat .zip .z1 .z2 .z3 .z4 .z5 .z6 .z7 .z8\\n\\nCopy your Infocom games to $romdir/zmachine\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/DavidGriffith/frotz/master/COPYING\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _update_hook_frotz() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage frotz && mkdir -p \"$md_inst\"\n}\n\nfunction install_bin_frotz() {\n    aptInstall frotz\n}\n\nfunction remove_frotz() {\n    aptRemove frotz\n}\n\nfunction game_data_frotz() {\n    local dest=\"$romdir/zmachine\"\n    if [[ ! -f \"$dest/zork1.dat\" ]]; then\n        mkUserDir \"$dest\"\n        local temp=\"$(mktemp -d)\"\n        local file\n        for file in zork1 zork2 zork3; do\n            downloadAndExtract \"$__archive_url/$file.zip\" \"$temp\" -L\n            cp \"$temp/data/$file.dat\" \"$dest\"\n            rm -rf \"$temp\"\n        done\n        rm -rf \"$temp\"\n        chown -R \"$__user\":\"$__group\" \"$romdir/zmachine\"\n    fi\n}\n\nfunction configure_frotz() {\n    mkRomDir \"zmachine\"\n\n    # CON: to stop runcommand from redirecting stdout to log\n    addEmulator 1 \"$md_id\" \"zmachine\" \"CON:pushd $romdir/zmachine; frotz %ROM%; popd\"\n    addSystem \"zmachine\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_frotz\n}\n"
  },
  {
    "path": "scriptmodules/emulators/fs-uae/fs-uae.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrom=\"$1\"\n\nrootdir=\"/opt/retropie\"\ndatadir=\"$HOME/RetroPie\"\nromdir=\"$datadir/roms/amiga\"\nsavedir=\"$romdir\"\nbiosdir=\"$datadir/BIOS\"\nkickfile=\"$biosdir/kick13.rom\"\n\nsource \"$rootdir/lib/archivefuncs.sh\"\n\nif [[ ! -f \"$kickfile\" ]]; then\n    dialog --no-cancel --pause \"You need to copy the Amiga kickstart file (kick13.rom) to the folder $biosdir to boot the Amiga emulator.\" 22 76 15\n    exit 1\nfi\n\narchiveExtract \"$rom\" \".adf .adz .dms .ipf\"\n\n# check successful extraction and if we have at least one file\nif [[ $? == 0 ]]; then\n    rom=\"${arch_files[0]}\"\n    romdir=\"$arch_dir\"\n\n    floppy_images=()\n    for i in \"${!arch_files[@]}\"; do\n        floppy_images+=(\"--floppy_image_$i=${arch_files[$i]}\")\n    done\nfi\n\nfs-uae --floppy_drive_0=\"$rom\" \"${floppy_images[@]}\" --kickstart_file=\"$kickfile\" --floppies_dir=\"$romdir\" --save_states_dir=\"$savedir\"\narchiveCleanup\n"
  },
  {
    "path": "scriptmodules/emulators/fs-uae.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"fs-uae\"\nrp_module_desc=\"Amiga emulator - FS-UAE integrates the most accurate Amiga emulation code available from WinUAE\"\nrp_module_help=\"ROM Extension: .adf  .adz .dms .ipf .zip\\n\\nCopy your Amiga games to $romdir/amiga\\n\\nCopy a required BIOS file (e.g. kick13.rom) to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/FrodeSolheim/fs-uae/master/COPYING\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all !arm x11\"\n\nfunction depends_fs-uae() {\n    local apt_file=\"/etc/apt/sources.list.d/fsuae-stable.list\"\n    local key_file=\"/etc/apt/trusted.gpg.d/home_FrodeSolheim_stable.gpg\"\n\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        rm -f \"$apt_file\"\n        # remove old keys\n        gpg --keyring /etc/apt/trusted.gpg --batch --yes --delete-keys \"home:FrodeSolheim@build.opensuse.org\" &>/dev/null$\n        rm -f \"$key_file\"\n        return\n    fi\n\n    [[ \"$md_mode\" != \"install*\" ]] && return\n    # handle installation for Debian or Ubuntu\n    case \"$__os_id\" in\n        Debian)\n            case \"$__os_debian_ver\" in\n                11|12)\n                    name=\"Debian_${__os_debian_ver}\"\n                    ;;\n                 *)\n                    md_ret_errors+=(\"Sorry, fs-uae isn't currently available for Debian $__os_debian_ver\")\n                    return 1\n                    ;;\n            esac\n            ;;\n        Ubuntu)\n            case \"$__os_ubuntu_ver\" in\n                20.04|22.04|24.04|24.10|25.04)\n                    name=\"xUbuntu_${__os_ubuntu_ver}\"\n                    ;;\n                *)\n                     md_ret_errors+=(\"Sorry, fs-uae isn't currently available for Ubuntu $__os_ubuntu_ver\")\n                     return 1\n                     ;;\n            esac\n            ;;\n        *)\n            md_ret_errors+=(\"Sorry, fs-uae isn't currently available for your system\")\n            return 1\n            ;;\n    esac\n\n    # configure the APT repo and key\n    local repo=\"http://download.opensuse.org/repositories/home:/FrodeSolheim:/stable/$name\"\n    echo \"deb $repo/ /\" > \"$apt_file\"\n    download \"$repo/Release.key\" - | gpg --dearmor | tee \"$key_file\" >/dev/null\n}\n\nfunction install_bin_fs-uae() {\n    aptInstall fs-uae fs-uae-launcher fs-uae-arcade\n}\n\nfunction remove_fs-uae() {\n    aptRemove fs-uae fs-uae-launcher fs-uae-arcade\n}\n\nfunction configure_fs-uae() {\n    mkRomDir \"amiga\"\n\n    addEmulator 1 \"$md_id\" \"amiga\" \"CON:bash $md_inst/bin/fs-uae.sh %ROM%\"\n    addSystem \"amiga\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # copy configuring start script\n    mkdir \"$md_inst/bin\"\n    cp \"$md_data/fs-uae.sh\" \"$md_inst/bin\"\n    chmod +x \"$md_inst/bin/fs-uae.sh\"\n\n    mkUserDir \"$md_conf_root/amiga\"\n    mkUserDir \"$home/Documents/FS-UAE\"\n    mkUserDir \"$home/Documents/FS-UAE/Configurations\"\n    moveConfigDir \"$home/Documents/FS-UAE/Configurations\" \"$md_conf_root/amiga/fs-uae\"\n\n    # copy default config file\n    local config=\"$(mktemp)\"\n    iniConfig \" = \" \"\" \"$config\"\n    iniSet \"fullscreen\" \"1\"\n    iniSet \"keep_aspect\" \"1\"\n    iniSet \"zoom\" \"full\"\n    iniSet \"fsaa\" \"0\"\n    iniSet \"scanlines\" \"0\"\n    iniSet \"floppy_drive_speed\" \"100\"\n    copyDefaultConfig \"$config\" \"$md_conf_root/amiga/fs-uae/Default.fs-uae\"\n    rm \"$config\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/fuse/01_disable_cursor.diff",
    "content": "--- 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 +0000\n@@ -412,7 +412,7 @@\n     SDL_ShowCursor( SDL_DISABLE );\n     SDL_WarpMouse( 128, 128 );\n   } else {\n-    SDL_ShowCursor( SDL_ENABLE );\n+    SDL_ShowCursor( SDL_DISABLE );\n   }\n \n   fuse_emulation_unpause();\n"
  },
  {
    "path": "scriptmodules/emulators/fuse/02_sdl_fix.diff",
    "content": "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/sdl/sdldisplay.c\n@@ -249,11 +249,13 @@ uidisplay_init( int width, int height )\n     return 0;\n   }\n \n-  for( i=0; modes[i]; ++i ); /* count modes */\n-  if( settings_current.sdl_fullscreen_mode ) {\n-    if( sscanf( settings_current.sdl_fullscreen_mode, \" %dx%d\", &mw, &mh ) != 2 ) {\n-      if( sscanf( settings_current.sdl_fullscreen_mode, \" %d\", &mn ) == 1 && mn <= i ) {\n-        mw = modes[mn - 1]->w; mh = modes[mn - 1]->h;\n+  if ( ! no_modes ) {\n+    for( i=0; modes[i]; ++i ); /* count modes */\n+    if( settings_current.sdl_fullscreen_mode ) {\n+      if( sscanf( settings_current.sdl_fullscreen_mode, \" %dx%d\", &mw, &mh ) != 2 ) {\n+        if( sscanf( settings_current.sdl_fullscreen_mode, \" %d\", &mn ) == 1 && mn <= i ) {\n+          mw = modes[mn - 1]->w; mh = modes[mn - 1]->h;\n+        }\n       }\n     }\n   }\n"
  },
  {
    "path": "scriptmodules/emulators/fuse/03_gcc_10_fix.diff",
    "content": "--- 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 stack to recurse on */\n \n /* The settings used whilst playing with an options dialog box */\n-settings_info widget_options_settings;\n+extern settings_info widget_options_settings;\n \n static int widget_read_font( const char *filename )\n {\n"
  },
  {
    "path": "scriptmodules/emulators/fuse.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"fuse\"\nrp_module_desc=\"ZX Spectrum emulator Fuse\"\nrp_module_help=\"ROM Extensions: .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip\\n\\nCopy your ZX Spectrum games to $romdir/zxspectrum\"\nrp_module_licence=\"GPL2 https://sourceforge.net/p/fuse-emulator/fuse/ci/master/tree/COPYING\"\nrp_module_repo=\"file $__archive_url/fuse-1.5.7.tar.gz\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction depends_fuse() {\n    getDepends libsdl1.2-dev libpng-dev zlib1g-dev libbz2-dev libaudiofile-dev bison flex\n}\n\nfunction sources_fuse() {\n    downloadAndExtract \"$__archive_url/fuse-1.5.7.tar.gz\" \"$md_build\" --strip-components 1\n    mkdir libspectrum\n    downloadAndExtract \"$__archive_url/libspectrum-1.4.4.tar.gz\" \"$md_build/libspectrum\" --strip-components 1\n    if ! isPlatform \"x11\"; then\n        applyPatch \"$md_data/01_disable_cursor.diff\"\n    fi\n    applyPatch \"$md_data/02_sdl_fix.diff\"\n    applyPatch \"$md_data/03_gcc_10_fix.diff\"\n}\n\nfunction build_fuse() {\n    pushd libspectrum\n    ./configure --disable-shared\n    make clean\n    make\n    popd\n    ./configure --prefix=\"$md_inst\" --without-libao --without-gpm --without-gtk --without-libxml2 --with-sdl LIBSPECTRUM_CFLAGS=\"-I$md_build/libspectrum\" LIBSPECTRUM_LIBS=\"-L$md_build/libspectrum/.libs -lspectrum\"\n    make clean\n    make\n    md_ret_require=\"$md_build/fuse\"\n}\n\nfunction install_fuse() {\n    make install\n}\n\nfunction configure_fuse() {\n    mkRomDir \"zxspectrum\"\n\n    addEmulator 0 \"$md_id-48k\" \"zxspectrum\" \"$md_inst/bin/fuse --machine 48 --full-screen %ROM%\"\n    addEmulator 0 \"$md_id-128k\" \"zxspectrum\" \"$md_inst/bin/fuse --machine 128 --full-screen %ROM%\"\n    addSystem \"zxspectrum\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkUserDir \"$md_conf_root/zxspectrum\"\n    moveConfigFile \"$home/.fuserc\" \"$md_conf_root/zxspectrum/.fuserc\"\n\n    # default to dispmanx backend\n    isPlatform \"dispmanx\" && _backend_set_fuse \"dispmanx\"\n\n    # without dispmanx, but with KMS, then use sdl12-compat\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && _backend_set_fuse \"sdl12-compat\"\n\n    local script=\"$romdir/zxspectrum/+Start Fuse.sh\"\n    cat > \"$script\" << _EOF_\n#!/bin/bash\n$md_inst/bin/fuse --machine 128 --full-screen\n_EOF_\n    chown \"$__user\":\"$__group\" \"$script\"\n    chmod +x \"$script\"\n}\n\nfunction _backend_set_fuse() {\n    local mode=\"$1\"\n    local force=\"$2\"\n    setBackend \"$md_id\" \"$mode\" \"$force\"\n    setBackend \"$md_id-48k\" \"$mode\" \"$force\"\n    setBackend \"$md_id-128k\" \"$mode\" \"$force\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/gngeopi.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"gngeopi\"\nrp_module_desc=\"NeoGeo emulator GnGeoPi\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your GnGeoPi roms to $romdir/neogeo\\n\\nCopy the required BIOS file neogeo.zip BIOS to $romdir/neogeo\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/ymartel06/GnGeo-Pi/master/gngeo/COPYING\"\nrp_module_repo=\"git https://github.com/ymartel06/GnGeo-Pi.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all arm !mali !kms\"\n\nfunction depends_gngeopi() {\n    getDepends libsdl1.2-dev\n}\n\nfunction sources_gngeopi() {\n    gitPullOrClone\n}\n\nfunction build_gngeopi() {\n    cd gngeo\n    chmod +x configure\n    ./configure --disable-i386asm --prefix=\"$md_inst\"\n    make clean\n    # not safe for building in parallel\n    make -j1\n    md_ret_require=\"$md_build/gngeo/src/gngeo\"\n}\n\nfunction install_gngeopi() {\n    cd gngeo\n    make install\n    mkdir -p \"$md_inst/neogeobios\"\n}\n\nfunction configure_gngeopi() {\n    mkRomDir \"arcade\"\n    mkRomDir \"neogeo\"\n\n    # move old config to new location\n    moveConfigDir \"$home/.gngeo\" \"$md_conf_root/neogeo\"\n\n    if [[ ! -f \"$md_conf_root/neogeo/gngeorc\" ]]; then\n        # add default controls for keyboard p1/p2\n        cat > \"$md_conf_root/neogeo/gngeorc\" <<\\_EOF_\np1control A=K122,B=K120,C=K97,D=K115,START=K49,COIN=K51,UP=K273,DOWN=K274,LEFT=K276,RIGHT=K275,MENU=K27\np2control A=K108,B=K59,C=K111,D=K112,START=K50,COIN=K52,UP=K264,DOWN=K261,LEFT=K260,RIGHT=K262,MENU=K27\n_EOF_\n        chown -R \"$__user\":\"$__group\" \"$md_conf_root/neogeo/gngeorc\"\n    fi\n\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/bin/gngeo -i $romdir/neogeo -B $md_inst/neogeobios %ROM%\"\n    addEmulator 0 \"$md_id\" \"neogeo\" \"$md_inst/bin/gngeo -i $romdir/neogeo -B $md_inst/neogeobios %ROM%\"\n    addSystem \"arcade\"\n    addSystem \"neogeo\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/gpsp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"gpsp\"\nrp_module_desc=\"GameBoy Advance emulator\"\nrp_module_help=\"ROM Extensions: .gba .zip\\n\\nCopy your Game Boy Advance roms to $romdir/gba\\n\\nCopy the required BIOS file gba_bios.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/gizmo98/gpsp/master/COPYING.DOC\"\nrp_module_repo=\"git https://github.com/gizmo98/gpsp.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"noinstclean !all videocore\"\n\nfunction depends_gpsp() {\n    getDepends libsdl1.2-dev libraspberrypi-dev gcc-6\n}\n\nfunction sources_gpsp() {\n    gitPullOrClone\n}\n\nfunction build_gpsp() {\n    cd raspberrypi\n    rpSwap on 512\n    make clean\n    make CC=\"gcc-6\"\n    rpSwap off\n    md_ret_require=\"$md_build/raspberrypi/gpsp\"\n}\n\nfunction install_gpsp() {\n    md_ret_files=(\n        'COPYING.DOC'\n        'game_config.txt'\n        'readme.txt'\n        'raspberrypi/gpsp'\n    )\n}\n\nfunction configure_gpsp() {\n    mkRomDir \"gba\"\n    chown -R \"$__user\":\"$__group\" \"$md_inst\"\n\n    mkUserDir \"$md_conf_root/gba\"\n\n    # symlink the rom so so it can be installed with the other bios files\n    ln -sf \"$biosdir/gba_bios.bin\" \"$md_inst/gba_bios.bin\"\n\n    # move old config\n    moveConfigFile \"gpsp.cfg\" \"$md_conf_root/gba/gpsp.cfg\"\n\n    addEmulator 0 \"$md_id\" \"gba\" \"$md_inst/gpsp %ROM%\"\n    addSystem \"gba\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/hatari.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"hatari\"\nrp_module_desc=\"Atari emulator Hatari\"\nrp_module_help=\"ROM Extensions: .st .stx .img .rom .raw .ipf .ctr .zip\\n\\nCopy your Atari ST games to $romdir/atarist\\n\\nCopy Atari ST BIOS (tos.img) to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/hatari/hatari/master/gpl.txt\"\nrp_module_repo=\"git https://github.com/hatari/hatari v2.4.1\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_hatari() {\n    getDepends libsdl2-dev zlib1g-dev libpng-dev cmake libreadline-dev portaudio19-dev\n}\n\nfunction _sources_libcapsimage_hatari() {\n    downloadAndExtract \"$__archive_url/spsdeclib_5.1_source.zip\" \"$md_build\"\n    unzip -o capsimg_source_linux_macosx.zip\n    chmod u+x capsimg_source_linux_macosx/CAPSImg/configure\n}\n\nfunction sources_hatari() {\n    # shallow clone isn't supported via https:// on this repo\n    gitPullOrClone\n    _sources_libcapsimage_hatari\n}\n\nfunction _build_libcapsimage_hatari() {\n    # build libcapsimage\n    cd capsimg_source_linux_macosx/CAPSImg\n    ./configure --prefix=\"$md_build\"\n    make clean\n    make\n    make install\n    mkdir -p \"$md_build/src/includes/caps\"\n    cp -R \"../LibIPF/\"*.h \"$md_build/src/includes/caps/\"\n    cp \"../Core/CommonTypes.h\" \"$md_build/src/includes/caps/\"\n}\n\nfunction build_hatari() {\n    _build_libcapsimage_hatari\n\n    # build hatari\n    cd \"$md_build\"\n    rm -f CMakeCache.txt\n    # add $md_inst to library search path for loading capsimage library\n    LDFLAGS+=\"-Wl,-rpath='$md_inst'\" \\\n        cmake . \\\n        -DCMAKE_SKIP_RPATH=ON \\\n        -DCMAKE_INSTALL_PREFIX:PATH=\"$md_inst\" \\\n        -DCAPSIMAGE_INCLUDE_DIR=\"$md_build/src/includes\" \\\n        -DCAPSIMAGE_LIBRARY=\"$md_build/lib/libcapsimage.so.5.1\" \\\n        -DENABLE_SDL2:BOOL=1\n    make clean\n    make\n    md_ret_require=\"$md_build/src/hatari\"\n}\n\nfunction _install_libcapsimage_hatari() {\n    cp \"$md_build/lib/libcapsimage.so.5.1\" \"$md_inst\"\n    cd \"$md_inst\"\n    ln -sf libcapsimage.so.5.1 libcapsimage.so.5\n}\n\nfunction install_hatari() {\n    make install\n    _install_libcapsimage_hatari\n}\n\nfunction configure_hatari() {\n    mkRomDir \"atarist\"\n\n    local common_config=(\"--confirm-quit 0\" \"--statusbar 0\")\n    if ! isPlatform \"x11\"; then\n        common_config+=(\"--zoom 1\" \"-w\")\n    else\n        common_config+=(\"-f\")\n    fi\n\n    addEmulator 1 \"$md_id-fast\" \"atarist\" \"$md_inst/bin/hatari ${common_config[*]} --compatible 0 --timer-d 1 --borders 0 %ROM%\"\n    addEmulator 0 \"$md_id-fast-borders\" \"atarist\" \"$md_inst/bin/hatari ${common_config[*]} --compatible 0 --timer-d 1 --borders 1 %ROM%\"\n    addEmulator 0 \"$md_id-compatible\" \"atarist\" \"$md_inst/bin/hatari ${common_config[*]} --compatible 1 --timer-d 0 --borders 0 %ROM%\"\n    addEmulator 0 \"$md_id-compatible-borders\" \"atarist\" \"$md_inst/bin/hatari ${common_config[*]} --compatible 1 --timer-d 0 --borders 1 %ROM%\"\n    addSystem \"atarist\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # move any old configs to new location\n    moveConfigDir \"$home/.hatari\" \"$md_conf_root/atarist\"\n\n    ln -sf \"$biosdir/tos.img\" \"$md_inst/share/hatari/tos.img\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/hypseus/hypinput.ini",
    "content": "# Sample hypinput.ini\n# All key options listed\n# Hypseus uses SDL2 Keycodes\n#\n# The first two entries are SDL2 keyboard codes or names (0 for \"none\")\n#\n# Find SDL2 keyboard code information here:\n# https://github.com/DirtBagXon/hypseus-singe/blob/master/doc/keylist.txt\n#\n# Hypseus Singe supports configuration on multiple joysticks\n# First joystick is defined as 0, second joystick as 1 etc.\n#\n# IMPORTANT: Find the joystick button and axis by running:\n# jstest /dev/input/js0 || jstest /dev/input/js1\n#\n# The third number in config is a joystick button code (or 0 for \"none\")\n# Since 0 is reserved for special meaning, joystick button 0 is\n# identified as 1. Button 1 is identified as 2, and so on.\n#\n# Defining 001 (or 1) identifies first joystick(0) button 0\n# Defining 111 identifies second joystick(1) button 10\n#\n# The fourth number in config (if specified) is the joystick axis\n# configuration (or 0 for \"none\"). Since 0 is reserved for\n# special meaning, joystick axis 0 is identified as 1.\n# Axis 1 is identified as 2, and so on.\n#\n# Only the first four switches are defined (SWITCH_UP->SWITCH_RIGHT) for axis\n#\n# Defining -001 (or -1) identifies first joystick(0) axis 0 in negative direction\n# Defining +102 identifies second joystick(1) axis 1 in positive direction\n\n# KEY_BUTTON3 Turns scoreboard on/off in lair/ace\n\n#              Key1             Key2       Button    (Axis)\n[KEYBOARD]\nKEY_UP         = SDLK_UP        SDLK_r     5         -002\nKEY_DOWN       = SDLK_DOWN      SDLK_f     7         +002\nKEY_LEFT       = SDLK_LEFT      SDLK_d     8         -001\nKEY_RIGHT      = SDLK_RIGHT     SDLK_g     6         +001\nKEY_COIN1      = SDLK_5         0          1\nKEY_COIN2      = SDLK_6         0          0\nKEY_START1     = SDLK_1         0          4\nKEY_START2     = SDLK_2         0          0\nKEY_BUTTON1    = SDLK_LCTRL     SDLK_a     14\nKEY_BUTTON2    = SDLK_LALT      SDLK_s     15\nKEY_BUTTON3    = SDLK_SPACE     SDLK_d     16\nKEY_SKILL1     = SDLK_LSHIFT    SDLK_w     0\nKEY_SKILL2     = SDLK_z         SDLK_i     0\nKEY_SKILL3     = SDLK_x         SDLK_k     0\nKEY_SERVICE    = SDLK_9         0          0\nKEY_TEST       = SDLK_F2        0          0\nKEY_RESET      = SDLK_0         0          0\nKEY_SCREENSHOT = SDLK_F12       0          0\nKEY_QUIT       = SDLK_ESCAPE    SDLK_q     17\nKEY_PAUSE      = SDLK_p         0          0\nKEY_CONSOLE    = SDLK_BACKSLASH 0          0\nKEY_TILT       = SDLK_t         0          0\nEND\n"
  },
  {
    "path": "scriptmodules/emulators/hypseus/hypinput_gamepad.ini",
    "content": "# Sample hypinput.ini using SDL_GameController\n# All key options listed for use with -gamepad\n#\n# Hypseus uses SDL2 Keycodes and SDL_GameController\n# SWITCH = Key1 Key2 Pad0 (Axis Pad0) Pad1 (Axis Pad1)\n\n# Available AXIS MACROS\n#\n# AXIS_LEFT_UP\n# AXIS_LEFT_DOWN\n# AXIS_LEFT_LEFT\n# AXIS_LEFT_RIGHT\n# AXIS_RIGHT_UP\n# AXIS_RIGHT_DOWN\n# AXIS_RIGHT_LEFT\n# AXIS_RIGHT_RIGHT\n#\n# Available BUTTON MACROS\n#\n# BUTTON_A\n# BUTTON_B\n# BUTTON_X\n# BUTTON_Y\n# BUTTON_BACK\n# BUTTON_GUIDE\n# BUTTON_START\n# BUTTON_LEFTSTICK\n# BUTTON_RIGHTSTICK\n# BUTTON_LEFTSHOULDER\n# BUTTON_RIGHTSHOULDER\n# BUTTON_DPAD_UP\n# BUTTON_DPAD_DOWN\n# BUTTON_DPAD_LEFT\n# BUTTON_DPAD_RIGHT\n# AXIS_TRIGGER_LEFT\n# AXIS_TRIGGER_RIGHT\n\n\n#                Key1            Key2      Pad0 Button        (Axis Pad0)       Pad1 Button      (Axis Pad1)\n[KEYBOARD]\nKEY_UP         = SDLK_UP         0         BUTTON_DPAD_UP     AXIS_LEFT_UP      0                0\nKEY_DOWN       = SDLK_DOWN       0         BUTTON_DPAD_DOWN   AXIS_LEFT_DOWN    0                0\nKEY_LEFT       = SDLK_LEFT       0         BUTTON_DPAD_LEFT   AXIS_LEFT_LEFT    0                0\nKEY_RIGHT      = SDLK_RIGHT      0         BUTTON_DPAD_RIGHT  AXIS_LEFT_RIGHT   0                0\nKEY_COIN1      = SDLK_5          0         BUTTON_BACK        0                 0\nKEY_COIN2      = SDLK_6          0         0                  0                 BUTTON_BACK\nKEY_START1     = SDLK_1          0         BUTTON_START       0                 0\nKEY_START2     = SDLK_2          0         0                  0                 BUTTON_START\nKEY_BUTTON1    = SDLK_LCTRL      0         BUTTON_A           0                 0\nKEY_BUTTON2    = SDLK_LALT       0         BUTTON_B           0                 0\nKEY_BUTTON3    = SDLK_SPACE      0         AXIS_TRIGGER_RIGHT 0                 0\nKEY_SKILL1     = SDLK_LSHIFT     0         0                  0                 0\nKEY_SKILL2     = SDLK_z          0         0                  0                 0\nKEY_SKILL3     = SDLK_x          0         0                  0                 0\nKEY_SERVICE    = SDLK_9          0         0                  0                 0\nKEY_TEST       = SDLK_F2         SDLK_F4   0                  0                 0\nKEY_RESET      = SDLK_0          0         0                  0                 0\nKEY_SCREENSHOT = SDLK_F12        0         0                  0                 0\nKEY_QUIT       = SDLK_ESCAPE     0         0                  0                 0\nKEY_PAUSE      = SDLK_p          0         0                  0                 0\nKEY_CONSOLE    = SDLK_BACKSLASH  0         0                  0                 0\nKEY_TILT       = SDLK_t          0         0                  0                 0\nEND\n"
  },
  {
    "path": "scriptmodules/emulators/hypseus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"hypseus\"\nrp_module_desc=\"Hypseus Singe - Laserdisc Emulator\"\nrp_module_help=\"ROM Extension: .daphne\\n\\nCopy your Daphne roms to $romdir/daphne\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/DirtBagXon/hypseus-singe/master/LICENSE\"\nrp_module_repo=\"git https://github.com/DirtBagXon/hypseus-singe.git RetroPie\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_hypseus() {\n    getDepends libvorbis-dev libogg-dev zlib1g-dev libzip-dev libmpeg2-4-dev libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-mixer-dev cmake\n}\n\nfunction sources_hypseus() {\n    gitPullOrClone\n}\n\nfunction build_hypseus() {\n    rm -rf build\n    mkdir build\n    cd build\n    rpSwap on 1024\n    cmake ../src\n    make\n    rpSwap off\n    cp hypseus ../hypseus.bin\n    md_ret_require=\"hypseus\"\n}\n\nfunction install_hypseus() {\n    md_ret_files=(\n        'sound'\n        'midi'\n        'pics'\n        'fonts'\n        'hypseus.bin'\n        'LICENSE'\n    )\n}\n\nfunction configure_hypseus() {\n    mkRomDir \"daphne\"\n    mkRomDir \"daphne/roms\"\n\n    addEmulator 0 \"$md_id\" \"daphne\" \"$md_inst/hypseus.sh %ROM%\"\n    addSystem \"daphne\" \"Hypseus\" \".zlua\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkUserDir \"$md_conf_root/daphne\"\n\n    local dir\n    for dir in ram logs screenshots bezels; do\n        mkUserDir \"$md_conf_root/daphne/$dir\"\n        ln -snf \"$md_conf_root/daphne/$dir\" \"$md_inst/$dir\"\n    done\n\n    copyDefaultConfig \"$md_data/hypinput.ini\" \"$md_conf_root/daphne/hypinput.ini\"\n    copyDefaultConfig \"$md_data/hypinput_gamepad.ini\" \"$md_conf_root/daphne/hypinput_gamepad.ini\"\n\n    ln -snf \"$romdir/daphne/roms\" \"$md_inst/roms\"\n    ln -snf \"$romdir/daphne/roms\" \"$md_inst/singe\"\n\n    ln -sf \"$md_conf_root/daphne/hypinput.ini\" \"$md_inst/hypinput.ini\"\n    ln -sf \"$md_conf_root/daphne/hypinput_gamepad.ini\" \"$md_inst/hypinput_gamepad.ini\"\n\n    local common_args=\"-framefile \\\"\\$dir/\\$name.txt\\\" -homedir \\\"$md_inst\\\" -fullscreen \\$params\"\n    # prevents SDL doing an internal software conversion since 2.0.16+\n    isPlatform \"arm\" && common_args=\"-texturestream $common_args\"\n\n    cat >\"$md_inst/hypseus.sh\" <<_EOF_\n#!/bin/bash\ndir=\"\\$1\"\npath=\\$(dirname \"\\$dir\")\nname=\\$(basename \"\\${dir%.*}\")\next=\"\\${dir##*.}\"\n\nif [[ \"\\$ext\" == \"zlua\" ]]; then\n    parent=\\$(awk '{\\$1=\\$1; print}' < \"\\$1\")\n    dir=\"\\$path/\\$parent\"\n    parent=\"\\${parent##*/}\"\n    params=\"-usealt \\$name\"\nelse\n    parent=\"\\$name\"\nfi\n\nif [[ -f \"\\$dir/\\$name.commands\" ]]; then\n    params=\"\\${params:+\\$params }\\$(<\"\\$dir/\\$name.commands\")\"\nfi\n\nif [[ -f \"\\$dir/\\$parent.singe\" ]]; then\n    singerom=\"\\$dir/\\$parent.singe\"\nelif [[ -f \"\\$dir/\\$parent.zip\" ]]; then\n    singerom=\"\\$dir/\\$parent.zip\"\nfi\n\nif [[ -n \"\\$singerom\" ]]; then\n    \"$md_inst/hypseus.bin\" singe vldp -retropath -manymouse -script \"\\$singerom\" $common_args\nelse\n    \"$md_inst/hypseus.bin\" \"\\$name\" vldp $common_args\nfi\n_EOF_\n    chmod +x \"$md_inst/hypseus.sh\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/jzintv/01_rpi_hide_cursor_sdl2.patch",
    "content": "--- 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 if full screen.                                      */\r\n     /* -------------------------------------------------------------------- */\r\n     SDL_ShowCursor(\r\n+#ifndef PLAT_LINUX_RPI\r\n+        /* SDL_GetNumVideoDisplays() may return two on rpi3, thus disable   */\r\n+        /* this clause on rpi. This is not only cosmetic, it fixes the      */\r\n+        /* UI freeze (not of jzintv itself), if mouse is attached and moved.*/\r\n         SDL_GetNumVideoDisplays() == 1 &&\r\n+#endif\r\n         (act_wind_flags & SDL_WINDOW_FULLSCREEN) ? SDL_DISABLE : SDL_ENABLE);\r\n \r\n     SDL_PumpEvents();\r\n"
  },
  {
    "path": "scriptmodules/emulators/jzintv/01_rpi_pillar_boxing_black_background_sdl2.patch",
    "content": "--- 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 to clear the backdrop to our border color before copying the   */\r\n     /*  texture to the display.                                             */\r\n     /* -------------------------------------------------------------------- */\r\n-    SDL_SetRenderDrawColor(rend, bord_color.r, bord_color.g, bord_color.b, 255);\r\n+    SDL_SetRenderDrawColor(rend, 0, 0, 0, 255);\r\n     SDL_RenderClear(rend);\r\n     if (pvt->vid_enable || gfx->debug_blank)\r\n         SDL_RenderCopy(rend, text, NULL,\r\n"
  },
  {
    "path": "scriptmodules/emulators/jzintv/02_Makefile_multiarch_pkg_config.patch",
    "content": "--- a/Makefile\n+++ a/Makefile\n@@ -39,8 +39,8 @@\n GNU_READLINE ?= 1\n \n # Get SDL2 related build flags.\n-SDL2_CFLAGS := $(shell sdl2-config --cflags) -DUSE_SDL2\n-SDL2_LFLAGS := $(shell sdl2-config --static-libs || sdl2-config --libs)\n+SDL2_CFLAGS := $(shell pkg-config --cflags sdl2) -DUSE_SDL2\n+SDL2_LFLAGS := $(shell pkg-config --libs --static --keep-system-libs sdl2 || pkg-config --libs sdl2)\n \n # Override these in a .mak file. See buidlcfg/00-compiler*.txt for examples.\n #\n\n"
  },
  {
    "path": "scriptmodules/emulators/jzintv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"jzintv\"\nrp_module_desc=\"Intellivision emulator\"\nrp_module_help=\"ROM Extensions: .int .bin .rom\\n\\nCopy your Intellivision roms to $romdir/intellivision\\n\\nCopy the required BIOS files exec.bin and grom.bin to $biosdir\"\nrp_module_licence=\"GPL2 http://spatula-city.org/%7Eim14u2c/intv/\"\nrp_module_repo=\"file $__archive_url/jzintv-20200712-src.zip\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2 nodistcc\"\n\nfunction depends_jzintv() {\n    getDepends libsdl2-dev libreadline-dev\n}\n\nfunction sources_jzintv() {\n    rm -rf \"$md_build/jzintv\"\n    downloadAndExtract \"$md_repo_url\" \"$md_build\"\n    # jzintv-YYYYMMDD/ --> jzintv/\n    mv jzintv-[0-9]* jzintv\n    cd jzintv/src\n\n    if isPlatform \"rpi\" ; then\n        applyPatch \"$md_data/01_rpi_hide_cursor_sdl2.patch\"\n        applyPatch \"$md_data/01_rpi_pillar_boxing_black_background_sdl2.patch\"\n    fi\n    applyPatch \"$md_data/02_Makefile_multiarch_pkg_config.patch\"\n\n    # Add source release date information to build\n    mv buildcfg/90-svn.mak buildcfg/90-svn.mak.txt\n    echo \"SVN_REV := $(echo $md_repo_url | grep -o -P '[\\d]{8}')\" > buildcfg/90-src_releasedate.mak\n    sed -i.zip-dist \"s/SVN Revision/Releasedate/\" svn_revision.c\n\n    # aarch64 doesn't include sys/io.h - but it's not needed so we can remove\n    grep -rl \"include.*sys/io.h\" | xargs sed -i \"/include.*sys\\/io.h/d\"\n\n    # remove shipped binaries / libraries\n    rm -rf ../bin\n}\n\nfunction build_jzintv() {\n    mkdir -p jzintv/bin\n    cd jzintv/src\n\n    local extra\n    if isPlatform \"rpi\" ; then\n        extra='EXTRA=-DPLAT_LINUX_RPI'\n    fi\n\n    make clean\n    make $extra\n\n    md_ret_require=\"$md_build/jzintv/bin/jzintv\"\n}\n\nfunction install_jzintv() {\n    md_ret_files=(\n        'jzintv/bin'\n        'jzintv/doc'\n        'jzintv/src/COPYING.txt'\n        'jzintv/src/COPYRIGHT.txt'\n        $(find jzintv/Release*)\n    )\n}\n\nfunction configure_jzintv() {\n    mkRomDir \"intellivision\"\n\n    local start_script=\"$md_inst/jzintv_launcher.sh\"\n    cat > \"$start_script\" << _EOF_\n#! /usr/bin/env bash\n\n# \\$1: width of display\n# \\$2: height of display\n# \\$3: --ecs=1, optional\n# \\$4,5,6...: more optional parameters\n# last parameter: %ROM%\n\njzintv_bin=\"$md_inst/bin/jzintv\"\n\n# regular case: w>=h (rotation 90/270 not supported by jzintv)\ndisp_w=\\$1; shift\ndisp_h=\\$1; shift\n\nratio=\"4/3\"\nread intv_w intv_h < <(python3 <<PYSCRIPT\nif (\\$disp_w / \\$disp_h >= \\$ratio):\n    # left/right padding\n    intv_w=round(\\$disp_h * \\$ratio)\n    intv_h=\\$disp_h\nelse:\n    # top/bottom padding (letterboxing; e.g., on 5:4 displays)\n    intv_w=\\$disp_w\n    intv_h=round(\\$disp_w / (\\$ratio))\n\nprint(intv_w,intv_h)\nPYSCRIPT\n)\n# set --gfx-verbose instead of --quiet for verbose output\noptions=(\n    -f1 # fullscreen\n    --quiet\n#    --gfx-verbose\n    --displaysize=\"\\${intv_w}x\\${intv_h}\"\n    --rom-path=\"$biosdir\"\n    --voice=1\n)\n\necho \"Launching: \\$jzintv_bin \\${options[@]} \\$@\"\n\\$jzintv_bin \\${options[@]} \"\\$@\"\n_EOF_\n    chown $user:$user \"$start_script\"\n    chmod u+x \"$start_script\"\n\n    addEmulator 1 \"$md_id\"     \"intellivision\" \"'$start_script' %XRES% %YRES% %ROM%\"\n    addEmulator 0 \"$md_id-ecs\" \"intellivision\" \"'$start_script' %XRES% %YRES% --ecs=1 %ROM%\"\n    addSystem \"intellivision\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/linapple.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"linapple\"\nrp_module_desc=\"Apple 2 emulator LinApple\"\nrp_module_help=\"ROM Extensions: .dsk\\n\\nCopy your Apple 2 games to $romdir/apple2\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/dabonetn/linapple-pie/master/LICENSE\"\nrp_module_repo=\"git https://github.com/dabonetn/linapple-pie.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction depends_linapple() {\n    getDepends libzip-dev libsdl1.2-dev libsdl-image1.2-dev libcurl4-openssl-dev\n}\n\nfunction sources_linapple() {\n    gitPullOrClone\n}\n\nfunction build_linapple() {\n    cd src\n    make clean\n    make\n    md_ret_require=\"$md_build/linapple\"\n}\n\nfunction install_linapple() {\n    md_ret_files=(\n        'CHANGELOG'\n        'INSTALL'\n        'LICENSE'\n        'linapple'\n        'linapple.conf'\n        'Master.dsk'\n        'README'\n        'README-linapple-pie'\n    )\n}\n\nfunction configure_linapple() {\n    mkRomDir \"apple2\"\n\n    addEmulator 1 \"$md_id\" \"apple2\" \"$md_inst/linapple.sh -1 %ROM%\"\n    addSystem \"apple2\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # copy default config/disk if user doesn't have them installed\n    local file\n    for file in Master.dsk linapple.conf; do\n        copyDefaultConfig \"$file\" \"$md_conf_root/apple2/$file\"\n    done\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n\n    mkUserDir \"$md_conf_root/apple2\"\n    moveConfigDir \"$home/.linapple\" \"$md_conf_root/apple2\"\n\n    local file=\"$md_inst/linapple.sh\"\n    cat >\"$file\" << _EOF_\n#!/bin/bash\npushd \"$romdir/apple2\"\n$md_inst/linapple \"\\$@\"\npopd\n_EOF_\n    chmod +x \"$file\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/mame/lzma_armv7_crc.diff",
    "content": "diff --git a/3rdparty/lzma/C/7zCrc.c b/3rdparty/lzma/C/7zCrc.c\nindex f186324d..f39fe1c9 100644\n--- a/3rdparty/lzma/C/7zCrc.c\n+++ b/3rdparty/lzma/C/7zCrc.c\n@@ -71,7 +71,7 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U\n \n #ifdef MY_CPU_LE\n \n-#if defined(MY_CPU_ARM_OR_ARM64)\n+#if defined(MY_CPU_ARM_OR_ARM64) && 0\n \n // #pragma message(\"ARM*\")\n"
  },
  {
    "path": "scriptmodules/emulators/mame.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mame\"\nrp_module_desc=\"MAME emulator\"\nrp_module_help=\"ROM Extensions: .zip .7z\\n\\nCopy your MAME roms to either $romdir/mame or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/mamedev/mame/master/COPYING\"\nrp_module_repo=\"git https://github.com/mamedev/mame.git :_get_branch_mame\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!mali !armv6 !:\\$__gcc_version:-lt:7 nodistcc\"\n\nfunction _get_branch_mame() {\n    # starting with 0.265, GCC 10.3 or later is required for full C++17 support\n    if compareVersions \"$(gcc -dumpfullversion)\" lt 10.3.0; then\n        echo \"mame0264\"\n        return\n    fi\n    download https://api.github.com/repos/mamedev/mame/releases/latest - | grep -m 1 tag_name | cut -d\\\" -f4\n}\n\nfunction depends_mame() {\n    # Install required libraries required for compilation and running\n    # Note: libxi-dev is required as of v0.210, because of flag changes for XInput\n    local depends=(libfontconfig1-dev libsdl2-ttf-dev libflac-dev libxinerama-dev libxi-dev libpulse-dev)\n    # build the MAME debugger only on X11 (desktop) platforms\n    isPlatform \"x11\" && depends+=(qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_mame() {\n    gitPullOrClone\n    # lzma assumes hardware crc support on arm which breaks when building on armv7\n    isPlatform \"armv7\" && applyPatch \"$md_data/lzma_armv7_crc.diff\"\n}\n\nfunction build_mame() {\n    # More memory is required for 64bit platforms\n    if isPlatform \"64bit\"; then\n        rpSwap on 10240\n    else\n        rpSwap on 8192\n    fi\n\n    local params=(NOWERROR=1 ARCHOPTS=\"-U_FORTIFY_SOURCE -Wl,-s\" PYTHON_EXECUTABLE=python3 OPTIMIZE=2 USE_SYSTEM_LIB_FLAC=1)\n    isPlatform \"x11\" && params+=(USE_QTDEBUG=1) || params+=(USE_QTDEBUG=0)\n\n    # array for storing ARCHOPTS_CXX parameters\n    local arch_opts_cxx=()\n\n    # when building on ARM enable 'fsigned-char' for compiled code, fixes crashes in a few drivers\n    isPlatform \"arm\" || isPlatform \"aarch64\" && arch_opts_cxx+=(-fsigned-char)\n\n    # workaround g++-12 compiler bug/compilation issue on 32bit arm userland with aarch64 kernel on the rpi3 (cortex-a53)\n    # disabling -ftree-slp-vectorize works around the issue:\n    # {standard input}: Assembler messages:\n    # {standard input}:4045: Error: co-processor offset out of range\n    # make[2]: *** [skeleton.make:2727: obj/Release/src/mame/skeleton/scopus.o] Error 1\n    if [[ \"$__gcc_version\" -eq 12 ]] && isPlatform \"rpi3\" && isPlatform \"32bit\" && [[ \"$(uname -m)\" == \"aarch64\" ]]; then\n        arch_opts_cxx+=(-fno-tree-slp-vectorize)\n    fi\n\n    # if we have any arch opts set, add them\n    if [[ ${#arch_opts_cxx[@]} -gt 0 ]]; then\n        params+=(ARCHOPTS_CXX=\"${arch_opts_cxx[*]}\")\n    fi\n\n    # force arm on arm platform - fixes building mame on when using 32bit arm userland with aarch64 kernel\n    isPlatform \"arm\" && params+=(PLATFORM=arm)\n\n    # workaround for linker crash on bullseye (use gold linker)\n    if [[ \"$__os_debian_ver\" -eq 11 ]] && isPlatform \"arm\"; then\n        LDFLAGS+=\" -fuse-ld=gold -Wl,--long-plt\" make \"${params[@]}\"\n    else\n        QT_SELECT=5 make \"${params[@]}\"\n    fi\n\n    rpSwap off\n    md_ret_require=\"$md_build/mame\"\n}\n\nfunction install_mame() {\n    md_ret_files=(\n        'artwork'\n        'bgfx'\n        'ctrlr'\n        'docs'\n        'hash'\n        'hlsl'\n        'ini'\n        'language'\n        'mame'\n        'plugins'\n        'roms'\n        'samples'\n        'uismall.bdf'\n        'COPYING'\n    )\n}\n\nfunction configure_mame() {\n    local system=\"mame\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkRomDir \"arcade\"\n        mkRomDir \"$system\"\n\n        # Create required MAME directories underneath the ROM directory\n        local mame_sub_dir\n        for mame_sub_dir in artwork cfg comments diff inp nvram samples scores snap sta; do\n            mkRomDir \"$system/$mame_sub_dir\"\n        done\n\n        # Create a BIOS directory, where people will be able to store their BIOS files, separate from ROMs\n        mkUserDir \"$biosdir/$system\"\n\n        # Create the configuration directory for the MAME ini files\n        moveConfigDir \"$home/.mame\" \"$md_conf_root/$system\"\n\n        # Create new INI files if they do not already exist\n        # Create MAME config file\n        local temp_ini_mame=\"$(mktemp)\"\n\n        iniConfig \" \" \"\" \"$temp_ini_mame\"\n        iniSet \"rompath\"            \"$romdir/$system;$romdir/arcade;$biosdir/$system\"\n        iniSet \"hashpath\"           \"$md_inst/hash\"\n        iniSet \"samplepath\"         \"$romdir/$system/samples;$romdir/arcade/samples\"\n        iniSet \"artpath\"            \"$romdir/$system/artwork;$romdir/arcade/artwork\"\n        iniSet \"ctrlrpath\"          \"$md_inst/ctrlr\"\n        iniSet \"pluginspath\"        \"$md_inst/plugins\"\n        iniSet \"languagepath\"       \"$md_inst/language\"\n\n        iniSet \"cfg_directory\"      \"$romdir/$system/cfg\"\n        iniSet \"nvram_directory\"    \"$romdir/$system/nvram\"\n        iniSet \"input_directory\"    \"$romdir/$system/inp\"\n        iniSet \"state_directory\"    \"$romdir/$system/sta\"\n        iniSet \"snapshot_directory\" \"$romdir/$system/snap\"\n        iniSet \"diff_directory\"     \"$romdir/$system/diff\"\n        iniSet \"comment_directory\"  \"$romdir/$system/comments\"\n\n        iniSet \"skip_gameinfo\" \"1\"\n        iniSet \"plugin\" \"hiscore\"\n        iniSet \"samplerate\" \"44100\"\n\n        # Raspberry Pis show improved performance using accelerated mode which enables SDL_RENDERER_TARGETTEXTURE.\n        # On RPI4 it uses OpenGL as a renderer, while on earlier RPIs it uses OpenGLES2 as the renderer. \n        # X86 Ubuntu by default uses OpenGL as a renderer, but SDL doesn't have target texture enabled as default.\n        # Enabling accel will use target texture on X86 Ubuntu (and likely other X86 Linux platforms).\n        iniSet \"video\" \"accel\"\n\n        copyDefaultConfig \"$temp_ini_mame\" \"$md_conf_root/$system/mame.ini\"\n        rm \"$temp_ini_mame\"\n\n        # Create MAME UI config file\n        local temp_ini_ui=\"$(mktemp)\"\n        iniConfig \" \" \"\" \"$temp_ini_ui\"\n        iniSet \"scores_directory\" \"$romdir/$system/scores\"\n        copyDefaultConfig \"$temp_ini_ui\" \"$md_conf_root/$system/ui.ini\"\n        rm \"$temp_ini_ui\"\n\n        # Create MAME Plugin config file\n        local temp_ini_plugin=\"$(mktemp)\"\n        iniConfig \" \" \"\" \"$temp_ini_plugin\"\n        iniSet \"hiscore\" \"1\"\n        copyDefaultConfig \"$temp_ini_plugin\" \"$md_conf_root/$system/plugin.ini\"\n        rm \"$temp_ini_plugin\"\n\n        # Create MAME Hi Score config file\n        local temp_ini_hiscore=\"$(mktemp)\"\n        iniConfig \" \" \"\" \"$temp_ini_hiscore\"\n        iniSet \"hi_path\" \"$romdir/$system/scores\"\n        copyDefaultConfig \"$temp_ini_hiscore\" \"$md_conf_root/$system/hiscore.ini\"\n        rm \"$temp_ini_hiscore\"\n    fi\n\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/mame %BASENAME%\"\n    addEmulator 1 \"$md_id\" \"$system\" \"$md_inst/mame %BASENAME%\"\n\n    addSystem \"arcade\"\n    addSystem \"$system\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/mame4all.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mame4all\"\nrp_module_desc=\"MAME emulator MAME4All-Pi\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME4all-Pi roms to either $romdir/mame-mame4all or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/RetroPie/mame4all-pi/master/readme.txt\"\nrp_module_repo=\"git https://github.com/RetroPie/mame4all-pi.git master\"\nrp_module_section=\"opt armv6=main\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_mame4all() {\n    getDepends libasound2-dev libsdl1.2-dev libraspberrypi-dev\n}\n\nfunction sources_mame4all() {\n    gitPullOrClone\n}\n\nfunction build_mame4all() {\n    make clean\n    # drz80 contains obsoleted arm assembler that gcc/as will not like for arm8 cpu targets\n    if isPlatform \"armv8\"; then\n        CFLAGS=\"-O2 -march=armv7-a -mfpu=neon-vfpv4 -mfloat-abi=hard\" make\n    else\n        make\n    fi\n    md_ret_require=\"$md_build/mame\"\n}\n\nfunction install_mame4all() {\n    md_ret_files=(\n        'cheat.dat'\n        'clrmame.dat'\n        'folders'\n        'hiscore.dat'\n        'mame'\n        'mame.cfg.template'\n        'readme.txt'\n        'skins'\n    )\n}\n\nfunction configure_mame4all() {\n    local system=\"mame-mame4all\"\n    mkRomDir \"arcade\"\n    mkRomDir \"$system\"\n    mkRomDir \"$system/artwork\"\n    mkRomDir \"$system/samples\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkdir -p \"$md_conf_root/$system/\"{cfg,hi,inp,memcard,nvram,snap,sta}\n\n        # move old config\n        moveConfigFile \"$md_inst/mame.cfg\" \"$md_conf_root/$system/mame.cfg\"\n\n        local config=\"$(mktemp)\"\n        cp \"mame.cfg.template\" \"$config\"\n\n        iniConfig \"=\" \"\" \"$config\"\n        iniSet \"cfg\" \"$md_conf_root/$system/cfg\"\n        iniSet \"hi\" \"$md_conf_root/$system/hi\"\n        iniSet \"inp\" \"$md_conf_root/$system/inp\"\n        iniSet \"memcard\" \"$md_conf_root/$system/memcard\"\n        iniSet \"nvram\" \"$md_conf_root/$system/nvram\"\n        iniSet \"snap\" \"$md_conf_root/$system/snap\"\n        iniSet \"sta\" \"$md_conf_root/$system/sta\"\n\n        iniSet \"artwork\" \"$romdir/$system/artwork\"\n        iniSet \"samplepath\" \"$romdir/$system/samples;$romdir/arcade/samples\"\n        iniSet \"rompath\" \"$romdir/$system;$romdir/arcade\"\n\n        iniSet \"samplerate\" \"44100\"\n\n        copyDefaultConfig \"$config\" \"$md_conf_root/$system/mame.cfg\"\n        rm \"$config\"\n\n        chown -R \"$__user\":\"$__group\" \"$md_conf_root/$system\"\n    fi\n\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/mame %BASENAME%\"\n    addEmulator 1 \"$md_id\" \"$system\" \"$md_inst/mame %BASENAME%\"\n    addSystem \"arcade\"\n    addSystem \"$system\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/minivmac.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"minivmac\"\nrp_module_desc=\"Macintosh Plus Emulator\"\nrp_module_help=\"ROM Extensions: .dsk \\n\\nCopy your Macintosh Plus disks to $romdir/macintosh \\n\\n You need to copy the Macintosh bios file vMac.ROM into \"$biosdir\" and System Tools.dsk to $romdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/minivmac/minivmac/refs/heads/master/COPYING.txt\"\nrp_module_repo=\"git https://github.com/minivmac/minivmac.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_minivmac() {\n    getDepends libsdl2-dev\n}\n\nfunction sources_minivmac() {\n    gitPullOrClone\n}\n\nfunction __cpu_minivmac() {\n    if isPlatform \"64bit\"; then\n        isPlatform \"aarch64\" && echo \"a64\"\n        isPlatform \"x86\" && echo \"x64\"\n    else\n        isPlatform \"arm\" && echo \"arm\"\n        isPlatform \"x86\" && echo \"x86\"\n    fi\n}\nfunction __target_minivmac() {\n    isPlatform \"arm\" || isPlatform \"aarch64\" && echo \"larm\"\n    isPlatform \"x86\" && ! isPlatform \"64bit\" && echo \"lx86\"\n    isPlatform \"x86\" && isPlatform \"64bit\" && echo \"lx64\"\n}\n\nfunction build_minivmac() {\n    cc -o setup_t setup/tool.c\n    local em_speed=4\n    isPlatform \"armv6\" && em_speed=2\n\n    ./setup_t \\\n        -maintainer \"egon.rath@gmail.com\" \\\n        -homepage \"https://github.com/egrath\" \\\n        -t \"$(__target_minivmac)\" \\\n        -cpu \"$(__cpu_minivmac)\" \\\n        -e bgc \\\n        -hres 640 -vres 480 -depth 0 \\\n        -magnify 1 -mf 2 \\\n        -m Plus \\\n        -sound 1 \\\n        -sony-sum 1 -sony-tag 1 \\\n        -speed $em_speed -ta 2 -em-cpu 2 \\\n        -chr 0 -drc 1 -sss 4 \\\n        -fullscreen 1 \\\n        -var-fullscreen 1 \\\n        -api sd2 \\\n        > setup.sh\n\n    bash setup.sh\n    # amend the CFLAGS auto-generated by the build system\n    sed -i \"s/^mk_COptions =.*/mk_COptions = \\$(mk_COptionsCommon) $CFLAGS/\" Makefile\n    make clean\n    make\n\n    md_ret_require=\"$md_build/minivmac\"\n}\n\nfunction install_minivmac() {\n    md_ret_files=(\n        'minivmac'\n        'COPYING.txt'\n        'README.md'\n        'README.txt'\n    )\n}\n\nfunction configure_minivmac() {\n    mkRomDir \"macintosh\"\n\n    ln -sf \"$biosdir/vMac.ROM\" \"$md_inst/vMac.ROM\"\n\n    addEmulator 1 \"$md_id\" \"macintosh\" \"pushd $md_inst; $md_inst/minivmac $romdir/macintosh/System\\ Tools.dsk %ROM%; popd\"\n    addSystem \"macintosh\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/mupen64plus/0001-GLideN64-use-emplace.patch",
    "content": "diff --git a/GLideN64/src/Combiner.cpp b/GLideN64/src/Combiner.cpp\nindex f724cc0..0141f6c 100644\n--- a/GLideN64/src/Combiner.cpp\n+++ b/GLideN64/src/Combiner.cpp\n@@ -295,7 +295,7 @@ void CombinerInfo::setCombine(u64 _mux )\n \t} else {\n \t\tm_pCurrent = Combiner_Compile(key);\n \t\tm_pCurrent->update(true);\n-\t\tm_combiners[m_pCurrent->getKey()] = m_pCurrent;\n+\t\tm_combiners.emplace(m_pCurrent->getKey(), m_pCurrent);\n \t}\n \tm_bChanged = true;\n }\n"
  },
  {
    "path": "scriptmodules/emulators/mupen64plus/mupen64plus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nAUDIO_PLUGIN=\"mupen64plus-audio-sdl\"\nVIDEO_PLUGIN=\"$1\"\nROM=\"$2\"\n[[ \"$3\" != 0 ]] && RES=\"$3\"\n[[ \"$4\" -ne 0 ]] && RSP_PLUGIN=\"$4\"\nPARAMS=\"${@:5}\"\n[[ -n \"$RES\" ]] && RES=\"--resolution $RES\"\n[[ -z \"$RSP_PLUGIN\" ]] && RSP_PLUGIN=\"mupen64plus-rsp-hle\"\nWINDOW_MODE=\"--fullscreen $RES\"\n\nrootdir=\"/opt/retropie\"\nconfigdir=\"$rootdir/configs\"\nconfig=\"$configdir/n64/mupen64plus.cfg\"\ninputconfig=\"$configdir/n64/InputAutoCfg.ini\"\ndatadir=\"$HOME/RetroPie\"\nromdir=\"$datadir/roms\"\n\nsource \"$rootdir/lib/inifuncs.sh\"\n\n# arg 1: hotkey name, arg 2: device number, arg 3: retroarch auto config file\nfunction getBind() {\n    local key=\"$1\"\n    local m64p_hotkey=\"J$2\"\n    local file=\"$3\"\n\n    iniConfig \" = \" \"\" \"$file\"\n\n    # search hotkey enable button\n    local hotkey\n    local input_type\n    local i=0\n    for hotkey in input_enable_hotkey \"$key\"; do\n        for input_type in \"_btn\" \"_axis\"; do\n            iniGet \"${hotkey}${input_type}\"\n            ini_value=\"${ini_value// /}\"\n            if [[ -n \"$ini_value\" ]]; then\n                ini_value=\"${ini_value//\\\"/}\"\n                case \"$input_type\" in\n                    _axis)\n                        m64p_hotkey+=\"A${ini_value:1}${ini_value:0:1}\"\n                    ;;\n                    _btn)\n                        # if ini_value contains \"h\" it should be a hat device\n                        if [[ \"$ini_value\" == *h* ]]; then\n                            local dir=\"${ini_value:2}\"\n                            ini_value=\"${ini_value:1}\"\n                            case $dir in\n                                up)\n                                    dir=\"1\"\n                                    ;;\n                                right)\n                                    dir=\"2\"\n                                    ;;\n                                down)\n                                    dir=\"4\"\n                                    ;;\n                                left)\n                                    dir=\"8\"\n                                    ;;\n                            esac\n                            m64p_hotkey+=\"H${ini_value}V${dir}\"\n                        else\n                            [[ \"$atebitdo_hack\" -eq 1 && \"$ini_value\" -ge 11 ]] && ((ini_value-=11))\n                            m64p_hotkey+=\"B${ini_value}\"\n                        fi\n                    ;;\n                esac\n            fi\n        done\n        [[ \"$i\" -eq 0 ]] && m64p_hotkey+=\"/\"\n        ((i++))\n    done\n    echo \"$m64p_hotkey\"\n}\n\nfunction remap() {\n    local device\n    local devices\n    local device_num\n\n    # get lists of all present js device numbers and device names\n    # get device count\n    while read -r device; do\n        device_num=\"${device##*/js}\"\n        devices[$device_num]=$(</sys/class/input/js${device_num}/device/name)\n    done < <(find /dev/input -name \"js*\")\n\n    # read retroarch auto config file and use config\n    # for mupen64plus.cfg\n    local file\n    local bind\n    local hotkeys_rp=( \"input_exit_emulator\" \"input_load_state\" \"input_save_state\" )\n    local hotkeys_m64p=( \"Joy Mapping Stop\" \"Joy Mapping Load State\" \"Joy Mapping Save State\" )\n    local i\n    local j\n\n    iniConfig \" = \" \"\" \"$config\"\n    if ! grep -q \"\\[CoreEvents\\]\" \"$config\"; then\n        echo \"[CoreEvents]\" >> \"$config\"\n        echo \"Version = 1\" >> \"$config\"\n    fi\n\n    local atebitdo_hack\n    for i in {0..2}; do\n        bind=\"\"\n        for device_num in \"${!devices[@]}\"; do\n            # get name of retroarch auto config file\n            file=$(grep -lF \"\\\"${devices[$device_num]}\\\"\" \"$configdir/all/retroarch-joypads/\"*.cfg)\n            atebitdo_hack=0\n            [[ \"$file\" == *8Bitdo* ]] && getAutoConf \"8bitdo_hack\" && atebitdo_hack=1\n            if [[ -f \"$file\" ]]; then\n                if [[ -n \"$bind\" && \"$bind\" != *, ]]; then\n                    bind+=\",\"\n                fi\n                bind+=$(getBind \"${hotkeys_rp[$i]}\" \"${device_num}\" \"$file\")\n            fi\n        done\n        # write hotkey to mupen64plus.cfg\n        iniConfig \" = \" \"\\\"\" \"$config\"\n        iniSet \"${hotkeys_m64p[$i]}\" \"$bind\"\n    done\n}\n\nfunction setAudio() {\n    if tr -d '\\0' < /proc/device-tree/compatible | grep -Eq raspberrypi,[0-4]; then\n        # If a Raspberry Pi is used, try to set the right output and use audio OMX if possible\n        # check for the presence of the non-KMS audio driver\n        if aplay -l | grep -qm1 \"bcm2835 HDMI\"; then\n            # use audio OMX when the RPI has enabled the internal audio cards\n            AUDIO_PLUGIN=\"mupen64plus-audio-omx\"\n            iniConfig \" = \" \"\\\"\" \"$config\"\n            # create section if necessary\n            if ! grep -q \"\\[Audio-OMX\\]\" \"$config\"; then\n                echo \"[Audio-OMX]\" >> \"$config\"\n                echo \"Version = 1\" >> \"$config\"\n            fi\n            # try to find which audio card is default by looking at the mixer's volume control name\n            if amixer -Ddefault cget numid=1 | grep -qm1 HDMI; then\n                iniSet \"OUTPUT_PORT\" \"1\"\n            fi\n            if amixer -Ddefault cget numid=1 | grep -qm1 Headphones; then\n                iniSet \"OUTPUT_PORT\" \"0\"\n            fi\n        fi\n    fi\n}\n\nfunction testCompatibility() {\n    # fallback for glesn64 and rice plugin\n    # some roms lead to a black screen of death\n    local game\n\n    # these games need RSP-LLE\n    local blacklist=(\n        naboo\n        body\n    )\n\n    # these games do not run with gles2n64\n    local glesn64_blacklist=(\n        zelda\n        paper\n        kazooie\n        tooie\n        instinct\n        beetle\n        rogue\n        squadron\n        gauntlet\n    )\n\n    # these games do not run with rice\n    local glesn64rice_blacklist=(\n        yoshi\n        rogue\n        squadron\n        gauntlet\n        infernal\n    )\n\n    # these games have massive glitches if legacy blending is enabled\n    local GLideN64LegacyBlending_blacklist=(\n        empire\n        beetle\n        donkey\n        zelda\n        bomberman\n        infernal\n    )\n\n    local GLideN64NativeResolution_blacklist=(\n        majora\n    )\n\n    # these games have major problems with GLideN64\n    local gliden64_blacklist=(\n        zelda\n        conker\n    )\n\n    # these games crash if audio-omx is selected\n    local AudioOMX_blacklist=(\n        pokemon\n        resident\n        starcraft\n        rogue\n        squadron\n        infernal\n    )\n\n    for game in \"${blacklist[@]}\"; do\n        if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n            exit\n        fi\n    done\n\n    for game in \"${AudioOMX_blacklist[@]}\"; do\n        if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n            AUDIO_PLUGIN=\"mupen64plus-audio-sdl\"\n        fi\n    done\n\n    case \"$VIDEO_PLUGIN\" in\n        \"mupen64plus-video-GLideN64\")\n            if ! grep -q \"\\[Video-GLideN64\\]\" \"$config\"; then\n                echo \"[Video-GLideN64]\" >> \"$config\"\n            fi\n            iniConfig \" = \" \"\" \"$config\"\n            # Settings version. Don't touch it.\n            local config_version=\"20\"\n            if [[ -f \"$configdir/n64/GLideN64_config_version.ini\" ]]; then\n                config_version=$(<\"$configdir/n64/GLideN64_config_version.ini\")\n            fi\n            iniSet \"configVersion\" \"$config_version\"\n            # Set native resolution factor of 1\n            iniSet \"UseNativeResolutionFactor\" \"1\"\n            for game in \"${GLideN64NativeResolution_blacklist[@]}\"; do\n                if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n                    iniSet \"UseNativeResolutionFactor\" \"0\"\n                    break\n                fi\n            done\n            # Disable LegacyBlending if necessary\n            iniSet \"EnableLegacyBlending\" \"True\"\n            for game in \"${GLideN64LegacyBlending_blacklist[@]}\"; do\n                if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n                    iniSet \"EnableLegacyBlending\" \"False\"\n                    break\n                fi\n            done\n            for game in \"${gliden64_blacklist[@]}\"; do\n                if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n                    VIDEO_PLUGIN=\"mupen64plus-video-rice\"\n                fi\n            done\n            ;;\n        \"mupen64plus-video-n64\"|\"mupen64plus-video-rice\")\n            for game in \"${glesn64_blacklist[@]}\"; do\n                if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n                    VIDEO_PLUGIN=\"mupen64plus-video-rice\"\n                fi\n            done\n            for game in \"${glesn64rice_blacklist[@]}\"; do\n                if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n                    VIDEO_PLUGIN=\"mupen64plus-video-GLideN64\"\n                fi\n            done\n            ;;\n    esac\n\n    # fix Audio-SDL crackle\n    iniConfig \" = \" \"\\\"\" \"$config\"\n    # create section if necessary\n    if ! grep -q \"\\[Audio-SDL\\]\" \"$config\"; then\n        echo \"[Audio-SDL]\" >> \"$config\"\n        echo \"Version = 1\" >> \"$config\"\n    fi\n    iniSet \"RESAMPLE\" \"src-sinc-fastest\"\n}\n\nfunction useTexturePacks() {\n    # video-GLideN64\n    if ! grep -q \"\\[Video-GLideN64\\]\" \"$config\"; then\n        echo \"[Video-GLideN64]\" >> \"$config\"\n    fi\n    iniConfig \" = \" \"\" \"$config\"\n    # Settings version. Don't touch it.\n    local config_version=\"17\"\n    if [[ -f \"$configdir/n64/GLideN64_config_version.ini\" ]]; then\n        config_version=$(<\"$configdir/n64/GLideN64_config_version.ini\")\n    fi\n    iniSet \"configVersion\" \"$config_version\"\n    iniSet \"txHiresEnable\" \"True\"\n\n    # video-rice\n    if ! grep -q \"\\[Video-Rice\\]\" \"$config\"; then\n        echo \"[Video-Rice]\" >> \"$config\"\n    fi\n    iniSet \"LoadHiResTextures\" \"True\"\n}\n\nfunction autoset() {\n    VIDEO_PLUGIN=\"mupen64plus-video-GLideN64\"\n    RES=\"--resolution 320x240\"\n    PARAMS=\"--set Video-GLideN64[UseNativeResolutionFactor]=1\"\n\n    local game\n    # these games run fine and look better with 640x480\n    local highres=(\n        yoshi\n        worms\n        party\n        pokemon\n        bomberman\n        harvest\n        diddy\n        1080\n        starcraft\n        wipeout\n        dark\n    )\n\n    for game in \"${highres[@]}\"; do\n        if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n            RES=\"--resolution 640x480\"\n            PARAMS=\"--set Video-GLideN64[UseNativeResolutionFactor]=2\"\n            break\n        fi\n    done\n\n    # these games have no glitches and run faster with gles2n64\n    local gles2n64=(\n        wave\n        kart\n    )\n\n    for game in \"${gles2n64[@]}\"; do\n        if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n            VIDEO_PLUGIN=\"mupen64plus-video-n64\"\n            break\n        fi\n    done\n\n    # these games have no glitches or run faster with rice\n    local gles2rice=(\n        diddy\n        1080\n        conker\n        tooie\n        darkness\n    )\n\n    for game in \"${gles2rice[@]}\"; do\n        if [[ \"${ROM,,}\" == *\"$game\"* ]]; then\n            VIDEO_PLUGIN=\"mupen64plus-video-rice\"\n            break\n        fi\n    done\n}\n\nif ! grep -q \"\\[Core\\]\" \"$config\"; then\n    echo \"[Core]\" >> \"$config\"\n    echo \"Version = 1.010000\" >> \"$config\"\nfi\niniConfig \" = \" \"\\\"\" \"$config\"\n\nfunction setPath() {\n    iniSet \"ScreenshotPath\" \"$romdir/n64\"\n    iniSet \"SaveStatePath\" \"$romdir/n64\"\n    iniSet \"SaveSRAMPath\" \"$romdir/n64\"\n}\n\n\n# add default keyboard configuration if InputAutoCFG.ini is missing\nif [[ ! -f \"$inputconfig\" ]]; then\n    cat > \"$inputconfig\" << _EOF_\n; InputAutoCfg.ini for Mupen64Plus SDL Input plugin\n\n; Keyboard_START\n[Keyboard]\nplugged = True\nplugin = 2\nmouse = False\nDPad R = key(100)\nDPad L = key(97)\nDPad D = key(115)\nDPad U = key(119)\nStart = key(13)\nZ Trig = key(122)\nB Button = key(306)\nA Button = key(304)\nC Button R = key(108)\nC Button L = key(106)\nC Button D = key(107)\nC Button U = key(105)\nR Trig = key(99)\nL Trig = key(120)\nMempak switch = key(44)\nRumblepak switch = key(46)\nX Axis = key(276,275)\nY Axis = key(273,274)\n; Keyboard_END\n\n_EOF_\nfi\n\ngetAutoConf mupen64plus_savepath && setPath\ngetAutoConf mupen64plus_hotkeys && remap\ngetAutoConf mupen64plus_audio && setAudio\n[[ \"$VIDEO_PLUGIN\" == \"AUTO\" ]] && autoset\ngetAutoConf mupen64plus_compatibility_check && testCompatibility\ngetAutoConf mupen64plus_texture_packs && useTexturePacks\n\nif tr -d '\\0' < /proc/device-tree/compatible | grep -Eq raspberrypi,[0-4]; then\n    WINDOW_MODE=\"--windowed $RES\"\n    SDL_VIDEO_RPI_SCALE_MODE=1\n    # If a Raspberry Pi (<5) device is used, lower resolution to 320x240 and enable SDL dispmanx scaling mode 1\nfi\nif [[ -e /opt/vero3/lib/libMali.so  ]]; then\n    SDL_AUDIODRIVER=alsa\nfi\n\nSDL_AUDIODRIVER=${SDL_AUDIODRIVER} SDL_VIDEO_RPI_SCALE_MODE=${SDL_VIDEO_RPI_SCALE_MODE} \"$rootdir/emulators/mupen64plus/bin/mupen64plus\" --noosd $PARAMS ${WINDOW_MODE} --rsp ${RSP_PLUGIN}.so --gfx ${VIDEO_PLUGIN}.so --audio ${AUDIO_PLUGIN}.so --configdir \"$configdir/n64\" --datadir \"$configdir/n64\" \"$ROM\"\n"
  },
  {
    "path": "scriptmodules/emulators/mupen64plus/remove_fast_math.diff",
    "content": "--- a/mupen64plus-audio-sdl/projects/unix/Makefile\n+++ b/mupen64plus-audio-sdl/projects/unix/Makefile\n@@ -99,7 +99,7 @@ OBJDIR = _obj$(POSTFIX)\n # base CFLAGS, LDLIBS, and LDFLAGS\n OPTFLAGS ?= -O3 -flto\n WARNFLAGS ?= -Wall\n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fvisibility=hidden -I$(SRCDIR)\n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -fvisibility=hidden -I$(SRCDIR)\n LDFLAGS += $(SHARED)\n \n # Since we are building a shared library, we must compile with -fPIC on some architectures\n--- a/mupen64plus-input-sdl/projects/unix/Makefile\n+++ b/mupen64plus-input-sdlprojects/unix/Makefile\n@@ -96,7 +96,7 @@ OBJDIR = _obj$(POSTFIX)\n # base CFLAGS, LDLIBS, and LDFLAGS\n OPTFLAGS ?= -O3 -flto\n WARNFLAGS ?= -Wall\n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fvisibility=hidden -I$(SRCDIR) -D_GNU_SOURCE=1\n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -fvisibility=hidden -I$(SRCDIR) -D_GNU_SOURCE=1\n LDFLAGS += $(SHARED)\n LDLIBS += -lm\n \n--- a/mupen64plus-rsp-hle/projects/unix/Makefile\n+++ b/mupen64plus-rsp-hle/projects/unix/Makefile\n@@ -147,7 +147,7 @@ OBJDIR = _obj$(POSTFIX)\n # base CFLAGS, LDLIBS, and LDFLAGS\n OPTFLAGS ?= -O3 -flto\n WARNFLAGS ?= -Wall\n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fvisibility=hidden -I$(SRCDIR)\n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -fvisibility=hidden -I$(SRCDIR)\n LDFLAGS += $(SHARED)\n \n # Since we are building a shared library, we must compile with -fPIC on some architectures\n--- a/mupen64plus-ui-console/projects/unix/Makefile\n+++ b/mupen64plus-ui-console/projects/unix/Makefile\n@@ -74,7 +74,7 @@ OBJDIR = _obj$(POSTFIX)\n OPTFLAGS ?= -O3 -flto\n WARNFLAGS ?= -Wall\n \n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -I$(SRCDIR)\n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -I$(SRCDIR)\n ifeq ($(OS), MINGW)\n   CFLAGS += -lpthread\n   LDLIBS += -lpthread\n--- a/mupen64plus-video-gles2n64/projects/unix/Makefile\n+++ b/mupen64plus-video-gles2n64/projects/unix/Makefile\n@@ -132,7 +132,7 @@ endif\n # base CFLAGS, LDLIBS, and LDFLAGS\n OPTFLAGS ?= -O3 -flto\n WARNFLAGS ?= -Wall\n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fno-strict-aliasing -fvisibility=hidden -I../../src -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0     \n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -fno-strict-aliasing -fvisibility=hidden -I../../src -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0     \n CXXFLAGS += $(OPTFLAGS) -std=c++11 -fvisibility-inlines-hidden -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0    \n LDFLAGS += $(SHARED)\n \n--- a/mupen64plus-video-gles2rice/projects/unix/Makefile\n+++ b/mupen64plus-video-gles2rice/projects/unix/Makefile\n@@ -133,7 +133,7 @@ endif\n # base CFLAGS, LDLIBS, and LDFLAGS\n OPTFLAGS ?= -flto\n WARNFLAGS ?= -Wall\n-CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -ffast-math -fsingle-precision-constant -fno-strict-aliasing -fvisibility=hidden -I../../src -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0\n+CFLAGS += $(OPTFLAGS) $(WARNFLAGS) -fsingle-precision-constant -fno-strict-aliasing -fvisibility=hidden -I../../src -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0\n CXXFLAGS += -fvisibility-inlines-hidden -DSDL_VIDEO_OPENGL_ES2=1 -DSDL_VIDEO_OPENGL=0\n LDFLAGS += $(SHARED)\n \n"
  },
  {
    "path": "scriptmodules/emulators/mupen64plus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mupen64plus\"\nrp_module_desc=\"N64 emulator MUPEN64Plus\"\nrp_module_help=\"ROM Extensions: .z64 .n64 .v64\\n\\nCopy your N64 roms to $romdir/n64\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/mupen64plus/mupen64plus-core/master/LICENSES\"\nrp_module_repo=\":_pkg_info_mupen64plus\"\nrp_module_section=\"main\"\nrp_module_flags=\"sdl2 nodistcc\"\n\nfunction depends_mupen64plus() {\n    local depends=(cmake libsamplerate0-dev libspeexdsp-dev libsdl2-dev libpng-dev libfreetype6-dev fonts-freefont-ttf libboost-filesystem-dev libglu1-mesa-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"x86\" && depends+=(nasm)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n    # was a vero4k only line - I think it's not needed or can use a smaller subset of boost\n    isPlatform \"osmc\" && depends+=(libboost-all-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction _get_repos_mupen64plus() {\n    local repos=(\n        'mupen64plus mupen64plus-core master'\n        'mupen64plus mupen64plus-ui-console master'\n        'mupen64plus mupen64plus-audio-sdl master'\n        'mupen64plus mupen64plus-input-sdl master'\n        'mupen64plus mupen64plus-rsp-hle master'\n    )\n    if isPlatform \"videocore\" && isPlatform \"32bit\"; then\n        repos+=('gizmo98 mupen64plus-audio-omx master')\n    fi\n    if isPlatform \"gles\"; then\n        ! isPlatform \"rpi\" && repos+=('mupen64plus mupen64plus-video-glide64mk2 master')\n        if isPlatform \"32bit\"; then\n            repos+=('ricrpi mupen64plus-video-gles2rice pandora-backport')\n            repos+=('ricrpi mupen64plus-video-gles2n64 master')\n        fi\n    fi\n    if isPlatform \"gl\"; then\n        repos+=(\n            'mupen64plus mupen64plus-video-glide64mk2 master'\n            'mupen64plus mupen64plus-rsp-cxd4 master'\n            'mupen64plus mupen64plus-rsp-z64 master'\n        )\n    fi\n\n    local commit=\"\"\n    # GLideN64 now requires cmake 3.9 so use an older commit as a workaround for systems with older cmake (pre buster).\n    # Test using \"apt-cache madison\" as this code could be called when cmake isn't yet installed but correct version\n    # is available - eg via update check with builder module which removes dependencies after building.\n    # Multiple versions may be available, so grab the versions via cut, sort by version, take the latest from the top\n    # and pipe to xargs to strip whitespace\n    local cmake_ver=$(apt-cache madison cmake | cut -d\\| -f2 | sort --version-sort | head -1 | xargs)\n    if compareVersions \"$cmake_ver\" lt 3.9; then\n        commit=\"8a9d52b41b33d853445f0779dd2b9f5ec4ecdda8\"\n    fi\n    # avoid a GLideN64 regression introduced in 1a0621d\n    isPlatform \"gles\" && commit=\"5bbf55df8c61ab86b5e41a97906bc99ce9b00a36\"\n    repos+=(\"gonetz GLideN64 master $commit\")\n\n    local repo\n    for repo in \"${repos[@]}\"; do\n        echo \"$repo\"\n    done\n}\n\nfunction _pkg_info_mupen64plus() {\n    local mode=\"$1\"\n    local repo\n    case \"$mode\" in\n        get)\n            local hashes=()\n            local hash\n            local date\n            local newest_date\n            while read repo; do\n                repo=($repo)\n                date=$(git -C \"$md_build/${repo[1]}\" log -1 --format=%aI)\n                hash=\"$(git -C \"$md_build/${repo[1]}\" log -1 --format=%H)\"\n                hashes+=(\"$hash\")\n                if rp_dateIsNewer \"$newest_date\" \"$date\"; then\n                    newest_date=\"$date\"\n                fi\n            done < <(_get_repos_mupen64plus)\n            # store an md5sum of the various last commit hashes to be used to check for changes\n            local hash=\"$(echo \"${hashes[@]}\" | md5sum | cut -d\" \" -f1)\"\n            echo \"local pkg_repo_date=\\\"$newest_date\\\"\"\n            echo \"local pkg_repo_extra=\\\"$hash\\\"\"\n            ;;\n        newer)\n            local hashes=()\n            local hash\n            while read repo; do\n                repo=($repo)\n                # if we have any repos set to a specific git hash (eg GLideN64 then we use that) otherwise check\n                if [[ -n \"${repo[3]}\" ]]; then\n                    hash=\"${repo[3]}\"\n                else\n                    if ! hash=\"$(rp_getRemoteRepoHash git https://github.com/${repo[0]}/${repo[1]} ${repo[2]})\"; then\n                        __ERRMSGS+=(\"$hash\")\n                        return 3\n                    fi\n                fi\n                hashes+=(\"$hash\")\n            done < <(_get_repos_mupen64plus)\n            # store an md5sum of the various last commit hashes to be used to check for changes\n            local hash=\"$(echo \"${hashes[@]}\" | md5sum | cut -d\" \" -f1)\"\n            if [[ \"$hash\" != \"$pkg_repo_extra\" ]]; then\n                return 0\n            fi\n            return 1\n            ;;\n        check)\n            local ret=0\n            while read repo; do\n                repo=($repo)\n                out=$(rp_getRemoteRepoHash git https://github.com/${repo[0]}/${repo[1]} ${repo[2]})\n                if [[ -z \"$out\" ]]; then\n                    printMsgs \"console\" \"$id repository failed - https://github.com/${repo[0]}/${repo[1]} ${repo[2]}\"\n                    ret=1\n                fi\n            done < <(_get_repos_mupen64plus)\n            return \"$ret\"\n            ;;\n    esac\n}\n\nfunction sources_mupen64plus() {\n    local commit\n    local repo\n    while read repo; do\n        repo=($repo)\n        gitPullOrClone \"$md_build/${repo[1]}\" https://github.com/${repo[0]}/${repo[1]} ${repo[2]} ${repo[3]}\n    done < <(_get_repos_mupen64plus)\n\n    if isPlatform \"videocore\"; then\n        # workaround for shader cache crash issue on Raspbian stretch. See: https://github.com/gonetz/GLideN64/issues/1665\n        applyPatch \"$md_data/0001-GLideN64-use-emplace.patch\"\n    fi\n\n    if isPlatform \"armv8\"; then\n        # remove -ffast-math as it causes build errors building on cortex-a76 (rpi5)\n        applyPatch \"$md_data/remove_fast_math.diff\"\n    fi\n\n    local config_version=$(grep -oP '(?<=CONFIG_VERSION_CURRENT ).+?(?=U)' GLideN64/src/Config.h)\n    echo \"$config_version\" > \"$md_build/GLideN64_config_version.ini\"\n}\n\nfunction _params_mupen64plus() {\n    local dir=\"$1\"\n    local params=()\n\n    isPlatform \"rpi1\" && params+=(\"VFP=1\" \"VFP_HARD=1\")\n    isPlatform \"videocore\" || [[ \"$dir\" == \"mupen64plus-audio-omx\" ]] && params+=(\"VC=1\")\n    if isPlatform \"mesa\" || isPlatform \"mali\"; then\n        params+=(\"USE_GLES=1\")\n    fi\n    isPlatform \"neon\" && params+=(\"NEON=1\")\n    isPlatform \"x11\" && params+=(\"OSD=1\" \"PIE=1\")\n    isPlatform \"x86\" && params+=(\"SSE=SSE2\")\n    isPlatform \"armv6\" && params+=(\"HOST_CPU=armv6\")\n    isPlatform \"armv7\" && params+=(\"HOST_CPU=armv7\")\n    isPlatform \"armv8\" && params+=(\"HOST_CPU=armv8\")\n    isPlatform \"aarch64\" && params+=(\"HOST_CPU=aarch64\")\n    # we don't ship a Vulkan enabled front-end, so disable Vulkan in the core project\n    params+=(\"VULKAN=0\")\n    echo \"${params[@]}\"\n}\n\nfunction build_mupen64plus() {\n    rpSwap on 750\n\n    local dir\n    local params\n    for dir in *; do\n        if [[ -f \"$dir/projects/unix/Makefile\" ]]; then\n            # get make parameters\n            params=($(_params_mupen64plus $dir))\n\n            [[ \"$dir\" == \"mupen64plus-ui-console\" ]] && params+=(\"COREDIR=$md_inst/lib/\" \"PLUGINDIR=$md_inst/lib/mupen64plus/\")\n            make -C \"$dir/projects/unix\" \"${params[@]}\" clean\n            make -C \"$dir/projects/unix\" all \"${params[@]}\" OPTFLAGS=\"$CFLAGS -O3 -flto\"\n        fi\n    done\n\n    # build GLideN64\n    \"$md_build/GLideN64/src/getRevision.sh\"\n    pushd \"$md_build/GLideN64/projects/cmake\"\n\n    params=(\"-DMUPENPLUSAPI=On\" \"-DVEC4_OPT=On\" \"-DUSE_SYSTEM_LIBS=On\")\n    isPlatform \"neon\" && params+=(\"-DNEON_OPT=On\")\n    isPlatform \"mesa\" && params+=(\"-DMESA=On\" \"-DEGL=On\")\n    isPlatform \"vero4k\" && params+=(\"-DVERO4K=On\")\n    isPlatform \"armv8\" && params+=(\"-DCRC_ARMV8=On\")\n    isPlatform \"mali\" && params+=(\"-DVERO4K=On\" \"-DCRC_OPT=On\" \"-DEGL=On\")\n    isPlatform \"x86\" && params+=(\"-DCRC_OPT=On\")\n\n    cmake \"${params[@]}\" ../../src/\n    make\n    popd\n\n    rpSwap off\n    md_ret_require=(\n        'mupen64plus-ui-console/projects/unix/mupen64plus'\n        'mupen64plus-core/projects/unix/libmupen64plus.so.2.0.0'\n        'mupen64plus-audio-sdl/projects/unix/mupen64plus-audio-sdl.so'\n        'mupen64plus-input-sdl/projects/unix/mupen64plus-input-sdl.so'\n        'mupen64plus-rsp-hle/projects/unix/mupen64plus-rsp-hle.so'\n        'GLideN64/projects/cmake/plugin/Release/mupen64plus-video-GLideN64.so'\n    )\n\n    if isPlatform \"videocore\" && ! isPlatform \" 64bit\"; then\n        md_ret_require+=('mupen64plus-audio-omx/projects/unix/mupen64plus-audio-omx.so')\n    fi\n\n    if isPlatform \"gles\"; then\n        ! isPlatform \"rpi\" && md_ret_require+=('mupen64plus-video-glide64mk2/projects/unix/mupen64plus-video-glide64mk2.so')\n        if isPlatform \"32bit\"; then\n            md_ret_require+=('mupen64plus-video-gles2rice/projects/unix/mupen64plus-video-rice.so')\n            md_ret_require+=('mupen64plus-video-gles2n64/projects/unix/mupen64plus-video-n64.so')\n        fi\n    fi\n    if isPlatform \"gl\"; then\n        md_ret_require+=(\n            'mupen64plus-video-glide64mk2/projects/unix/mupen64plus-video-glide64mk2.so'\n            'mupen64plus-rsp-z64/projects/unix/mupen64plus-rsp-z64.so'\n        )\n        if isPlatform \"x86\"; then\n            md_ret_require+=('mupen64plus-rsp-cxd4/projects/unix/mupen64plus-rsp-cxd4-sse2.so')\n        else\n            md_ret_require+=('mupen64plus-rsp-cxd4/projects/unix/mupen64plus-rsp-cxd4.so')\n        fi\n    fi\n}\n\nfunction install_mupen64plus() {\n    local dir\n    local params\n    for dir in *; do\n        if [[ -f \"$dir/projects/unix/Makefile\" ]]; then\n            # get make parameters\n            params=($(_params_mupen64plus $dir))\n            # optflags is needed due to the fact the core seems to rebuild 2 files and relink during install stage most likely due to a buggy makefile\n            make -C \"$dir/projects/unix\" PREFIX=\"$md_inst\" OPTFLAGS=\"$CFLAGS -O3 -flto\" \"${params[@]}\" install\n        fi\n    done\n    cp \"$md_build/GLideN64/ini/GLideN64.custom.ini\" \"$md_inst/share/mupen64plus/\"\n    cp \"$md_build/GLideN64/projects/cmake/plugin/Release/mupen64plus-video-GLideN64.so\" \"$md_inst/lib/mupen64plus/\"\n    cp \"$md_build/GLideN64_config_version.ini\" \"$md_inst/share/mupen64plus/\"\n    # remove default InputAutoConfig.ini. inputconfigscript writes a clean file\n    rm -f \"$md_inst/share/mupen64plus/InputAutoCfg.ini\"\n}\n\nfunction configure_mupen64plus() {\n    local res\n    local resolutions=(\"320x240\" \"640x480\")\n    isPlatform \"kms\" && res=\"%XRES%x%YRES%\"\n\n    if isPlatform \"rpi\"; then\n        # kms needs to run at full screen as it doesn't benefit from our SDL scaling hint\n        if isPlatform \"mesa\"; then\n            addEmulator 0 \"${md_id}-GLideN64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM% $res 0 --set Video-GLideN64[UseNativeResolutionFactor]\\=1\"\n            addEmulator 0 \"${md_id}-GLideN64-highres\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM% $res 0 --set Video-GLideN64[UseNativeResolutionFactor]\\=2\"\n            addEmulator 0 \"${md_id}-gles2n64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-n64 %ROM%\"\n            if isPlatform \"32bit\"; then\n                addEmulator 0 \"${md_id}-gles2rice\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-rice %ROM% $res\"\n            fi\n        else\n            for res in \"${resolutions[@]}\"; do\n                local name=\"\"\n                local nativeResFactor=1\n                if [[ \"$res\" == \"640x480\" ]]; then\n                    name=\"-highres\"\n                    nativeResFactor=2\n                fi\n                addEmulator 0 \"${md_id}-GLideN64$name\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM% $res 0 --set Video-GLideN64[UseNativeResolutionFactor]\\=$nativeResFactor\"\n                addEmulator 0 \"${md_id}-gles2rice$name\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-rice %ROM% $res\"\n            done\n            addEmulator 1 \"${md_id}-auto\" \"n64\" \"$md_inst/bin/mupen64plus.sh AUTO %ROM%\"\n        fi\n        addEmulator 0 \"${md_id}-gles2n64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-n64 %ROM%\"\n    elif isPlatform \"mali\"; then\n        addEmulator 1 \"${md_id}-gles2n64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-n64 %ROM%\"\n        addEmulator 0 \"${md_id}-GLideN64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM%\"\n        addEmulator 0 \"${md_id}-glide64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-glide64mk2 %ROM%\"\n        addEmulator 0 \"${md_id}-gles2rice\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-rice %ROM%\"\n        addEmulator 0 \"${md_id}-auto\" \"n64\" \"$md_inst/bin/mupen64plus.sh AUTO %ROM%\"\n    else\n        addEmulator 0 \"${md_id}-GLideN64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM% $res\"\n        addEmulator 1 \"${md_id}-glide64\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-glide64mk2 %ROM% $res\"\n        if isPlatform \"x86\"; then\n            ! isPlatform \"kms\" && res=\"640x480\"\n            addEmulator 0 \"${md_id}-GLideN64-LLE\" \"n64\" \"$md_inst/bin/mupen64plus.sh mupen64plus-video-GLideN64 %ROM% $res mupen64plus-rsp-cxd4-sse2\"\n        fi\n    fi\n    addSystem \"n64\"\n\n    mkRomDir \"n64\"\n    moveConfigDir \"$home/.local/share/mupen64plus\" \"$md_conf_root/n64/mupen64plus\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # copy hotkey remapping start script\n    cp \"$md_data/mupen64plus.sh\" \"$md_inst/bin/\"\n    chmod +x \"$md_inst/bin/mupen64plus.sh\"\n\n    mkUserDir \"$md_conf_root/n64/\"\n\n    # Copy config files\n    cp -v \"$md_inst/share/mupen64plus/\"{*.ini,font.ttf} \"$md_conf_root/n64/\"\n    isPlatform \"rpi\" && cp -v \"$md_inst/share/mupen64plus/\"*.conf \"$md_conf_root/n64/\"\n\n    local config=\"$md_conf_root/n64/mupen64plus.cfg\"\n    local cmd=\"$md_inst/bin/mupen64plus --configdir $md_conf_root/n64 --datadir $md_conf_root/n64\"\n\n    # if the user has an existing mupen64plus config we back it up, generate a new configuration\n    # copy that to rp-dist and put the original config back again. We then make any ini changes\n    # on the rp-dist file. This preserves any user configs from modification and allows us to have\n    # a default config for reference\n    if [[ -f \"$config\" ]]; then\n        mv \"$config\" \"$config.user\"\n        su \"$__user\" -c \"$cmd\"\n        mv \"$config\" \"$config.rp-dist\"\n        mv \"$config.user\" \"$config\"\n        config+=\".rp-dist\"\n    else\n        su \"$__user\" -c \"$cmd\"\n    fi\n\n    # RPI main/GLideN64 settings\n    if isPlatform \"rpi\"; then\n        iniConfig \" = \" \"\" \"$config\"\n        # VSync is mandatory for good performance on KMS\n        if isPlatform \"kms\"; then\n            if ! grep -q \"\\[Video-General\\]\" \"$config\"; then\n                echo \"[Video-General]\" >> \"$config\"\n            fi\n            iniSet \"VerticalSync\" \"True\"\n        fi\n        # Create GlideN64 section in .cfg\n        if ! grep -q \"\\[Video-GLideN64\\]\" \"$config\"; then\n            echo \"[Video-GLideN64]\" >> \"$config\"\n        fi\n        # Settings version. Don't touch it.\n        iniSet \"configVersion\" \"29\"\n        # Bilinear filtering mode (0=N64 3point, 1=standard)\n        iniSet \"bilinearMode\" \"1\"\n        iniSet \"EnableFBEmulation\" \"True\"\n        # Use native res\n        iniSet \"UseNativeResolutionFactor\" \"1\"\n        # Enable legacy blending\n        iniSet \"EnableLegacyBlending\" \"True\"\n        # Enable Threaded GL calls\n        iniSet \"ThreadedVideo\" \"True\"\n        # Swap frame buffers On buffer update (most performant)\n        iniSet \"BufferSwapMode\" \"2\"\n        # Disable hybrid upscaling filter (needs better GPU)\n        iniSet \"EnableHybridFilter\" \"False\"\n        # Use fast but less accurate shaders. Can help with low-end GPUs.\n        iniSet \"EnableInaccurateTextureCoordinates\" \"True\"\n\n        if isPlatform \"videocore\"; then\n            # Disable gles2n64 autores feature and use dispmanx upscaling\n            iniConfig \"=\" \"\" \"$md_conf_root/n64/gles2n64.conf\"\n            iniSet \"auto resolution\" \"0\"\n\n            setAutoConf mupen64plus_audio 1\n            setAutoConf mupen64plus_compatibility_check 1\n        elif isPlatform \"mesa\"; then\n            # Create Video-Rice section in .cfg\n            if ! grep -q \"\\[Video-Rice\\]\" \"$config\"; then\n                echo \"[Video-Rice]\" >> \"$config\"\n            fi\n            # Fix flickering and black screen issues with rice video plugin\n            iniSet \"ScreenUpdateSetting\" \"7\"\n\n            setAutoConf mupen64plus_audio 0\n            setAutoConf mupen64plus_compatibility_check 0\n        fi\n    else\n        addAutoConf mupen64plus_audio 0\n        addAutoConf mupen64plus_compatibility_check 0\n    fi\n\n    addAutoConf mupen64plus_hotkeys 1\n    addAutoConf mupen64plus_texture_packs 1\n\n    chown -R \"$__user\":\"$__group\" \"$md_conf_root/n64\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/np2pi.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"np2pi\"\nrp_module_desc=\"NEC PC-9801 emulator\"\nrp_module_help=\"ROM Extensions: .d88 .d98 .88d .98d .fdi .xdf .hdm .dup .2hd .tfd .hdi .thd .nhd .hdd\\n\\nCopy your pc98 games to to $romdir/pc88\\n\\nCopy bios files 2608_bd.wav, 2608_hh.wav, 2608_rim.wav, 2608_sd.wav, 2608_tom.wav 2608_top.wav, bios.rom, FONT.ROM and sound.rom to $biosdir/pc98\"\nrp_module_repo=\"git https://github.com/eagle0wl/np2pi.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl1 !all rpi !aarch64\"\n\nfunction depends_np2pi() {\n    getDepends libsdl1.2-dev libasound2-dev libsdl-ttf2.0-dev fonts-takao-gothic\n}\n\nfunction sources_np2pi() {\n    gitPullOrClone\n}\n\nfunction build_np2pi() {\n    cd sdl\n    make -j 1 -f makefile.rpi\n    md_ret_require=\"$md_build/bin/np2\"\n}\n\nfunction install_np2pi() {\n    md_ret_files=(\n        'bin/np2'\n    )\n}\n\nfunction configure_np2pi() {\n    mkRomDir \"pc98\"\n\n    mkUserDir \"$md_conf_root/pc98\"\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    # we launch from $md_conf_root/pc98 as emulator wants to create files in\n    # the current directory (eg font.tmp).\n\n    # symlink bios files\n    mkUserDir \"$biosdir/pc98\"\n    local bios\n    for bios in 2608_bd.wav 2608_hh.wav 2608_rim.wav 2608_sd.wav 2608_tom.wav 2608_top.wav bios.rom FONT.ROM sound.rom; do\n        ln -sf \"$biosdir/pc98/$bios\" \"$md_conf_root/pc98/$bios\"\n    done\n\n    # symlink font\n    ln -sf /usr/share/fonts/truetype/takao-gothic/TakaoGothic.ttf \"$md_conf_root/pc98/default.ttf\"\n\n    addEmulator 1 \"$md_id\" \"pc98\" \"pushd $md_conf_root/pc98; $md_inst/np2 %ROM%; popd\"\n    addSystem \"pc98\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/openmsx/retropie-init.tcl",
    "content": "namespace eval retropie {\n\nproc init {} {\n    set rom_name [guess_title]\n    set config_dir [file normalize \"$::env(OPENMSX_USER_DATA)/joystick\"]\n\n    # sanitize the rom name\n    regsub -all {[:><?\\\"\\/\\\\|*]} $rom_name \"\" rom_name\n\n    # auto-configure the 1st plugged in joystick, but only if present\n    # openMSX automatically loads the plugged in joysticks in 'autoplug.tcl'\n    if {![info exists ::joystick1_config]} {\n        return\n    }\n\n    if { !($rom_name eq \"\") } {\n        if { [ file exists \"$config_dir/game/$rom_name.tcl\" ] } {\n            load_config_joystick $rom_name \"$config_dir/game/$rom_name.tcl\"\n            return\n        }\n    }\n\n    # get the 1st joystick name\n    set joy_name [machine_info pluggable joystick1]\n    # ... and sanitize it\n    regsub -all {[:><?\\\"\\/\\\\|*]} $joy_name \"\" joy_name\n    if { [file exists \"$config_dir/$joy_name.tcl\"] } {\n             load_config_joystick $joy_name \"$config_dir/$joy_name.tcl\"\n    }\n}\n\nproc load_config_joystick { conf_name conf_script } {\n    source \"$conf_script\"\n    # check for the joypad auto-configuration function\n    if { [info procs \"auto_config_joypad\"] == \"\" } {\n        return\n    }\n    auto_config_joypad\n    message \"Loaded joystick configuration for '$conf_name'\"\n}\n\n}; # namespace: retropie\n\nafter boot retropie::init\n"
  },
  {
    "path": "scriptmodules/emulators/openmsx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"openmsx\"\nrp_module_desc=\"MSX emulator OpenMSX\"\nrp_module_help=\"ROM Extensions: .cas .rom .mx1 .mx2 .col .dsk .zip\\n\\nCopy your MSX/MSX2 games to $romdir/msx\\nCopy the BIOS files to $biosdir/openmsx\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/openMSX/openMSX/master/doc/GPL.txt\"\nrp_module_repo=\"git https://github.com/openMSX/openMSX.git RELEASE_19_1 :_get_commit_openmsx\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _get_commit_openmsx() {\n    local commit\n    # latest code requires a C++ compiler with C++23 support (Debian Bullseye)\n    [[ \"$__gcc_version\" -lt 9 ]] && commit=\"127e2826\"\n    # use a commit after release 17 for older GCC versions (gcc 8.x, Debian Buster)\n    [[ \"$__gcc_version\" -lt 8 ]] && commit=\"c8d90e70\"\n    # for GCC before 7, build from an earlier commit, before C++17 support was added\n    [[ \"$__gcc_version\" -lt 7 ]] && commit=\"5ee25b62\"\n    echo \"$commit\"\n}\n\nfunction depends_openmsx() {\n    local depends=(libsdl2-dev libsdl2-ttf-dev libao-dev libogg-dev libtheora-dev libxml2-dev libvorbis-dev tcl-dev libasound2-dev libfreetype6-dev)\n    isPlatform \"x11\" && depends+=(libglew-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_openmsx() {\n    gitPullOrClone\n    sed -i \"s|INSTALL_BASE:=/opt/openMSX|INSTALL_BASE:=$md_inst|\" build/custom.mk\n    sed -i \"s|SYMLINK_FOR_BINARY:=true|SYMLINK_FOR_BINARY:=false|\" build/custom.mk\n}\n\nfunction build_openmsx() {\n    rpSwap on 2000\n    ./configure\n    make clean\n    make\n    rpSwap off\n    md_ret_require=\"$md_build/derived/openmsx\"\n}\n\nfunction install_openmsx() {\n    make install\n    mkdir -p \"$md_inst/share/systemroms/\"\n    downloadAndExtract \"$__archive_url/openmsxroms.tar.gz\" \"$md_inst/share/systemroms/\"\n}\n\nfunction configure_openmsx() {\n    mkRomDir \"msx\"\n\n    addEmulator 0 \"$md_id\" \"msx\" \"$md_inst/bin/openmsx %ROM%\"\n    addEmulator 0 \"$md_id-msx2\" \"msx\" \"$md_inst/bin/openmsx -machine 'Boosted_MSX2_EN' %ROM%\"\n    addEmulator 0 \"$md_id-msx2-plus\" \"msx\" \"$md_inst/bin/openmsx -machine 'Boosted_MSX2+_JP' %ROM%\"\n    addEmulator 0 \"$md_id-msx-turbor\" \"msx\" \"$md_inst/bin/openmsx -machine 'Panasonic_FS-A1GT' %ROM%\"\n    addSystem \"msx\"\n\n    [[ $md_mode == \"remove\" ]] && return\n\n    # Add a minimal configuration\n    local config=\"$(mktemp)\"\n    echo \"$(_default_settings_openmsx)\" > \"$config\"\n\n    mkUserDir \"$home/.openMSX/share/scripts\"\n    mkUserDir \"$home/.openMSX/share/systemroms\"\n    moveConfigDir \"$home/.openMSX\" \"$configdir/msx/openmsx\"\n    moveConfigDir \"$configdir/msx/openmsx/share/systemroms\" \"$home/RetroPie/BIOS/openmsx\"\n\n    copyDefaultConfig \"$config\" \"$home/.openMSX/share/settings.xml\"\n    rm \"$config\"\n\n    # Add an autostart script, used for joypad configuration\n    cp \"$md_data/retropie-init.tcl\" \"$home/.openMSX/share/scripts\"\n    chown -R \"$__user\":\"$__group\" \"$home/.openMSX/share/scripts\"\n}\n\nfunction _default_settings_openmsx() {\n    local header\n    local body\n    local conf_reverse\n\n    read -r -d '' header <<_EOF_\n<!DOCTYPE settings SYSTEM 'settings.dtd'>\n<settings>\n  <settings>\n    <setting id=\"default_machine\">C-BIOS_MSX</setting>\n    <setting id=\"osd_disk_path\">$romdir/msx</setting>\n    <setting id=\"osd_rom_path\">$romdir/msx</setting>\n    <setting id=\"osd_tape_path\">$romdir/msx</setting>\n    <setting id=\"osd_hdd_path\">$romdir/msx</setting>\n    <setting id=\"fullscreen\">true</setting>\n    <setting id=\"save_settings_on_exit\">false</setting>\n_EOF_\n\n    if isPlatform \"armv6\" ; then\n       IFS= read -r -d '' body <<_EOF_\n    <setting id=\"scale_factor\">1</setting>\n    <setting id=\"horizontal_stretch\">320</setting>\n    <setting id=\"resampler\">fast</setting>\n    <setting id=\"scanline\">0</setting>\n    <setting id=\"maxframeskip\">5</setting>\n_EOF_\n    fi\n\n    ! isPlatform \"x86\" && conf_reverse=\"    <setting id=\\\"auto_enable_reverse\\\">off</setting\\n\"\n    echo -e \"${header}${body}${conf_reverse}  </settings>\\n</settings>\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/oricutron.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"oricutron\"\nrp_module_desc=\"Oricutron Oric 1/Oric Atmos emulator\"\nrp_module_help=\"ROM Extensions: .dsk .tap\\n\\nCopy your Oric games to $romdir/oric\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/pete-gordon/oricutron/4c359acfb6bd36d44e6d37891d7b6453324faf7d/main.h\"\nrp_module_repo=\"git https://github.com/HerbFargus/oricutron.git extras\"\nrp_module_section=\"exp\"\n\nfunction depends_oricutron() {\n    local depends=(cmake libsdl2-dev)\n    isPlatform \"x11\" && depends+=(libgtk-3-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_oricutron() {\n    gitPullOrClone\n}\n\nfunction build_oricutron() {\n    make clean\n    if isPlatform \"rpi\" || isPlatform \"mali\"; then\n        make PLATFORM=rpi SDL_LIB=sdl2\n    else\n        make SDL_LIB=sdl2\n    fi\n    md_ret_require=\"$md_build/oricutron\"\n}\n\nfunction install_oricutron() {\n    md_ret_files=(\n        'oricutron'\n        'oricutron.cfg'\n        'roms'\n        'disks'\n        'images'\n    )\n}\n\nfunction game_data_oricutron() {\n    if [[ -d \"$md_inst/disks\" && ! -f \"$romdir/oric/barbitoric.dsk\" ]]; then\n        # copy demo disks\n        cp -v \"$md_inst/disks/\"* \"$romdir/oric/\"\n        chown -R \"$__user\":\"$__group\" \"$romdir/oric\"\n    fi\n}\n\nfunction configure_oricutron() {\n    mkRomDir \"oric\"\n\n    local machine\n    local default\n    for machine in atmos oric1 o16k telestrat pravetz; do\n        default=0\n        [[ \"$machine\" == \"atmos\" ]] && default=1\n        addEmulator \"$default\" \"$md_id-$machine\" \"oric\" \"pushd $md_inst; $md_inst/oricutron --machine $machine %ROM% --fullscreen; popd\"\n    done\n    addSystem \"oric\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_oricutron\n}\n"
  },
  {
    "path": "scriptmodules/emulators/osmose.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"osmose\"\nrp_module_desc=\"Gamegear emulator Osmose\"\nrp_module_help=\"ROM Extensions: .bin .gg .sms .zip\\nCopy your Game Gear roms to $romdir/gamegear\\n\\nMasterSystem roms to $romdir/mastersystem\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/osmose-rpi/master/license.txt\"\nrp_module_repo=\"git https://github.com/RetroPie/osmose-rpi.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali sdl1\"\n\nfunction depends_osmose() {\n    getDepends libsdl1.2-dev\n}\n\nfunction sources_osmose() {\n    gitPullOrClone\n}\n\nfunction build_osmose() {\n    make clean\n    # not safe for building in parallel\n    make -j1\n    md_ret_require=\"$md_build/osmose\"\n}\n\nfunction install_osmose() {\n    md_ret_files=(\n        'changes.txt'\n        'license.txt'\n        'osmose'\n    )\n}\n\nfunction configure_osmose() {\n    mkRomDir \"gamegear\"\n    mkRomDir \"mastersystem\"\n\n    addEmulator 0 \"$md_id\" \"gamegear\" \"$md_inst/osmose %ROM% -tv -fs\"\n    addEmulator 0 \"$md_id\" \"mastersystem\" \"$md_inst/osmose %ROM% -tv -fs\"\n    addSystem \"gamegear\"\n    addSystem \"mastersystem\"\n\n    [[ $mode == \"configure\" ]] && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/pcsx-rearmed.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pcsx-rearmed\"\nrp_module_desc=\"Playstation emulator - PCSX (arm optimised)\"\nrp_module_help=\"ROM Extensions: .bin .cue .cbn .img .iso .m3u .mdf .pbp .toc .z .znx\\n\\nCopy your PSX roms to $romdir/psx\\n\\nCopy the required BIOS file SCPH1001.BIN to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/notaz/pcsx_rearmed/master/COPYING\"\nrp_module_repo=\"git https://github.com/notaz/pcsx_rearmed.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !all videocore\"\n\nfunction depends_pcsx-rearmed() {\n    getDepends libsdl1.2-dev libasound2-dev libpng-dev libx11-dev\n}\n\nfunction sources_pcsx-rearmed() {\n    gitPullOrClone\n}\n\nfunction build_pcsx-rearmed() {\n    if isPlatform \"neon\"; then\n        ./configure --sound-drivers=alsa --enable-neon\n    else\n        ./configure --sound-drivers=alsa --disable-neon\n    fi\n    make clean\n    make\n    md_ret_require=\"$md_build/pcsx\"\n}\n\nfunction install_pcsx-rearmed() {\n    md_ret_files=(\n        'AUTHORS'\n        'COPYING'\n        'ChangeLog'\n        'ChangeLog.df'\n        'NEWS'\n        'README.md'\n        'pcsx'\n    )\n    mkdir \"$md_inst/plugins\"\n    cp \"$md_build/plugins/spunull/spunull.so\" \"$md_inst/plugins/spunull.so\"\n    cp \"$md_build/plugins/gpu_unai/gpu_unai.so\" \"$md_inst/plugins/gpu_unai.so\"\n    cp \"$md_build/plugins/gpu-gles/gpu_gles.so\" \"$md_inst/plugins/gpu_gles.so\"\n    cp \"$md_build/plugins/dfxvideo/gpu_peops.so\" \"$md_inst/plugins/gpu_peops.so\"\n}\n\nfunction configure_pcsx-rearmed() {\n    mkRomDir \"psx\"\n    mkUserDir \"$md_conf_root/psx\"\n    mkdir -p \"$md_inst/bios\"\n\n    # symlink the bios so it can be installed with the other bios files\n    ln -sf \"$biosdir/SCPH1001.BIN\" \"$md_inst/bios/SCPH1001.BIN\"\n\n    # symlink config folder\n    moveConfigDir \"$md_inst/.pcsx\" \"$md_conf_root/psx/pcsx\"\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    addEmulator 0 \"$md_id\" \"psx\" \"pushd $md_inst; ./pcsx -cdfile %ROM%; popd\"\n    addSystem \"psx\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/pcsx2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pcsx2\"\nrp_module_desc=\"PS2 emulator PCSX2\"\nrp_module_help=\"ROM Extensions: .bin .iso .img .mdf .z .z2 .bz2 .cso .chd .ima .gz\\n\\nCopy your PS2 roms to $romdir/ps2\\n\\nCopy the required BIOS file to $biosdir\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/PCSX2/pcsx2/master/COPYING.GPLv3\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all x86\"\n\nfunction _64bit_available_pcsx2() {\n    # detect if a 64bit version for pcsx2 is available in the Ubuntu PPA\n    if [[ -n \"${__os_ubuntu_ver}\" ]] && compareVersions \"${__os_ubuntu_ver}\" ge 21.04; then\n        return 0\n    fi\n\n    return 1\n}\nfunction depends_pcsx2() {\n    if isPlatform \"64bit\" && ! _64bit_available_pcsx2 ; then\n        iniConfig \" = \" '\"' \"$configdir/all/retropie.cfg\"\n        iniGet \"own_sdl2\"\n        if [[ \"$ini_value\" != \"0\" ]]; then\n            if dialog --yesno \"PCSX2 cannot be installed on a 64bit system with the RetroPie custom version of SDL2 installed due to version conflicts with the multiarch i386 version of SDL2.\\n\\nDo you want to downgrade to your OS version of SDL2 and continue to install PCSX2?\" 22 76 2>&1 >/dev/tty; then\n                chown \"$__user\":\"$__group\" \"$configdir/all/retropie.cfg\"\n                if rp_callModule sdl2 revert; then\n                    iniSet \"own_sdl2\" \"0\"\n                else\n                    md_ret_errors+=(\"Failed to install $md_desc\")\n                fi\n            else\n                md_ret_errors+=(\"$md_desc install aborted.\")\n            fi\n        fi\n    fi\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        # On Ubuntu, add the PCSX2 PPA to get the latest version\n        [[ -n \"${__os_ubuntu_ver}\" ]] && add-apt-repository -y ppa:pcsx2-team/pcsx2-daily\n        if ! _64bit_available_pcsx2 ; then\n            dpkg --add-architecture i386\n        fi\n    else\n        rm -f /etc/apt/sources.list.d/pcsx2-team-ubuntu-pcsx2-daily-*.list\n        apt-key del \"D7B4 49CF E17E 659E 5A12  EE8E DD6E EEA2 BD74 7717\" >/dev/null\n    fi\n}\n\nfunction install_bin_pcsx2() {\n    local version\n    [[ -n \"${__os_ubuntu_ver}\" ]] && version=\"-unstable\"\n\n    aptInstall \"pcsx2$version\"\n}\n\nfunction remove_pcsx2() {\n    local version\n    [[ -n \"${__os_ubuntu_ver}\" ]] && version=\"-unstable\"\n\n    aptRemove \"pcsx2$version\"\n    rp_callModule pcsx2 depends remove\n}\n\nfunction configure_pcsx2() {\n    mkRomDir \"ps2\"\n\n    # detect if the new (QT) UI is installed and add the fullscreen/windowed commands\n    if [[ -f /usr/bin/pcsx2-qt ]]; then\n        addEmulator 0 \"$md_id\" \"ps2\" \"pcsx2-qt -nofullscreen %ROM%\"\n        addEmulator 1 \"$md_id-nogui\" \"ps2\" \"pcsx2-qt -fullscreen -nogui %ROM%\"\n    else\n        local emu_path=\"/usr/games/PCSX2\"\n        [[ -f \"/usr/games/pcsx2\" ]] && emu_path=\"/usr/games/pcsx2\"\n        addEmulator 0 \"$md_id\" \"ps2\" \"$emu_path --windowed %ROM%\"\n        addEmulator 1 \"$md_id-nogui\" \"ps2\" \"$emu_path --fullscreen --nogui %ROM%\"\n    fi\n\n    addSystem \"ps2\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/pifba.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pifba\"\nrp_module_desc=\"FBA emulator PiFBA\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your FBA roms to\\n$romdir/fba or\\n$romdir/neogeo or\\n$romdir/arcade\\n\\nFor NeoGeo games the neogeo.zip BIOS is required and must be placed in the same directory as your FBA roms.\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/pifba/master/FBAcapex_src/COPYING\"\nrp_module_repo=\"git https://github.com/RetroPie/pifba.git master\"\nrp_module_section=\"opt armv6=main\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_pifba() {\n    getDepends libasound2-dev libsdl1.2-dev libraspberrypi-dev\n}\n\nfunction sources_pifba() {\n    gitPullOrClone\n}\n\nfunction build_pifba() {\n    mkdir \".obj\"\n    make clean\n    make\n    md_ret_require=\"$md_build/fba2x\"\n}\n\nfunction install_pifba() {\n    mkdir -p \"$md_inst/\"{roms,skin,preview}\n    md_ret_files=(\n        'fba2x'\n        'fba2x.cfg.template'\n        'capex.cfg.template'\n        'zipname.fba'\n        'rominfo.fba'\n        'FBACache_windows.zip'\n        'fba_029671_clrmame_dat.zip'\n    )\n}\n\nfunction configure_pifba() {\n    mkRomDir \"arcade\"\n    mkRomDir \"fba\"\n    mkRomDir \"neogeo\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkUserDir \"$md_conf_root/fba\"\n\n        local config\n        for config in fba2x.cfg capex.cfg; do\n            # move old config if it exists\n            moveConfigFile \"$md_inst/$config\" \"$md_conf_root/fba/$config\"\n            copyDefaultConfig \"$config.template\" \"$md_conf_root/fba/$config\"\n        done\n    fi\n\n    local def=0\n    isPlatform \"rpi1\" && def=1\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/fba2x %ROM%\"\n    addEmulator $def \"$md_id\" \"neogeo\" \"$md_inst/fba2x %ROM%\"\n    addEmulator $def \"$md_id\" \"fba\" \"$md_inst/fba2x %ROM%\"\n    addSystem \"arcade\"\n    addSystem \"neogeo\"\n    addSystem \"fba\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/pisnes.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pisnes\"\nrp_module_desc=\"SNES emulator PiSNES\"\nrp_module_help=\"ROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/RetroPie/pisnes/master/snes9x.h\"\nrp_module_repo=\"git https://github.com/RetroPie/pisnes.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_pisnes() {\n    getDepends libasound2-dev libsdl1.2-dev libraspberrypi-dev libjpeg-dev\n}\n\nfunction sources_pisnes() {\n    gitPullOrClone\n}\n\nfunction build_pisnes() {\n    make clean\n    make\n    md_ret_require=\"$md_build/snes9x\"\n}\n\nfunction install_pisnes() {\n    md_ret_files=(\n        'changes.txt'\n        'hardware.txt'\n        'problems.txt'\n        'readme_snes9x.txt'\n        'readme.txt'\n        'roms'\n        'skins'\n        'snes9x'\n        'snes9x.cfg.template'\n        'snes9x.gui'\n    )\n}\n\nfunction configure_pisnes() {\n    mkRomDir \"snes\"\n\n    addEmulator 0 \"$md_id\" \"snes\" \"$md_inst/snes9x %ROM%\"\n    addSystem \"snes\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    moveConfigFile \"$md_inst/snes9x.cfg\" \"$md_conf_root/snes/snes9x.cfg\"\n    copyDefaultConfig \"$md_inst/snes9x.cfg.template\" \"$md_conf_root/snes/snes9x.cfg\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/ppsspp/gles2_fix.diff",
    "content": "diff --git a/Common/GPU/OpenGL/DataFormatGL.cpp b/Common/GPU/OpenGL/DataFormatGL.cpp\nindex 425f247..ea690d8 100644\n--- a/Common/GPU/OpenGL/DataFormatGL.cpp\n+++ b/Common/GPU/OpenGL/DataFormatGL.cpp\n@@ -146,12 +146,14 @@ bool Thin3DFormatToGLFormatAndType(DataFormat fmt, GLuint &internalFormat, GLuin\n \t\talignment = 16;\n \t\tbreak;\n \n+#ifdef GL_COMPRESSED_RGBA_ASTC_4x4_KHR\n \tcase DataFormat::ASTC_4x4_UNORM_BLOCK:\n \t\tinternalFormat = GL_COMPRESSED_RGBA_ASTC_4x4_KHR;\n \t\tformat = GL_RGBA;\n \t\ttype = GL_FLOAT;\n \t\talignment = 16;\n \t\tbreak;\n+#endif\n \n \tdefault:\n \t\treturn false;\ndiff --git a/Common/GPU/OpenGL/GLFeatures.cpp b/Common/GPU/OpenGL/GLFeatures.cpp\nindex c17f1d1..fa3463e 100644\n--- a/Common/GPU/OpenGL/GLFeatures.cpp\n+++ b/Common/GPU/OpenGL/GLFeatures.cpp\n@@ -592,7 +592,9 @@ bool CheckGLExtensions() {\n \t\tfor (int i = 0; i < numCompressedFormats; i++) {\n \t\t\tswitch (compressedFormats[i]) {\n \t\t\tcase GL_COMPRESSED_RGB8_ETC2: gl_extensions.supportsETC2 = true; break;\n+#ifdef GL_COMPRESSED_RGBA_ASTC_4x4_KHR\n \t\t\tcase GL_COMPRESSED_RGBA_ASTC_4x4_KHR: gl_extensions.supportsASTC = true; break;\n+#endif\n #ifndef USING_GLES2\n \t\t\tcase GL_COMPRESSED_RGBA_S3TC_DXT5_EXT: gl_extensions.supportsBC123 = true; break;\n \t\t\tcase GL_COMPRESSED_RGBA_BPTC_UNORM: gl_extensions.supportsBC7 = true; break;\n"
  },
  {
    "path": "scriptmodules/emulators/ppsspp/sdl_ttf_fix_before_1.19.diff",
    "content": "diff --git a/Common/Render/Text/draw_text_sdl.h b/Common/Render/Text/draw_text_sdl.h\nindex 87c543a..bfd3842 100644\n--- a/Common/Render/Text/draw_text_sdl.h\n+++ b/Common/Render/Text/draw_text_sdl.h\n@@ -5,13 +5,15 @@\n #include <map>\n #include \"Common/Render/Text/draw_text.h\"\n \n+#if defined(USE_SDL2_TTF)\n+\n+#include \"SDL2/SDL.h\"\n+#include \"SDL2/SDL_ttf.h\"\n+\n #if defined(USE_SDL2_TTF_FONTCONFIG)\n #include <fontconfig/fontconfig.h>\n #endif\n \n-// SDL2_ttf's TTF_Font is a typedef of _TTF_Font.\n-struct _TTF_Font;\n-\n class TextDrawerSDL : public TextDrawer {\n public:\n \tTextDrawerSDL(Draw::DrawContext *draw);\n@@ -33,15 +35,17 @@ class TextDrawerSDL : public TextDrawer {\n \tbool FindFallbackFonts(uint32_t missingGlyph, int ptSize);\n \n \tuint32_t fontHash_;\n-\tstd::map<uint32_t, _TTF_Font *> fontMap_;\n+\tstd::map<uint32_t, TTF_Font *> fontMap_;\n \n \tstd::map<CacheKey, std::unique_ptr<TextStringEntry>> cache_;\n \tstd::map<CacheKey, std::unique_ptr<TextMeasureEntry>> sizeCache_;\n \n-\tstd::vector<_TTF_Font *> fallbackFonts_;\n+\tstd::vector<TTF_Font *> fallbackFonts_;\n \tstd::vector<std::pair<std::string, int>> fallbackFontPaths_; // path and font face index\n \n #if defined(USE_SDL2_TTF_FONTCONFIG)\n \tFcConfig *config;\n #endif\n };\n+\n+#endif\n"
  },
  {
    "path": "scriptmodules/emulators/ppsspp/tinker.armv7.cmake",
    "content": "include_directories(SYSTEM\n  /usr/local/include\n  /usr/include\n)\n\nset(ARCH_FLAGS \"-O2 -marm -march=armv7-a -mfpu=neon-vfpv4 -mtune=cortex-a17 -mfloat-abi=hard -ftree-vectorize -funsafe-math-optimizations -pipe\")\nset(CMAKE_C_FLAGS \"${CMAKE_C_FLAGS} ${ARCH_FLAGS}\"  CACHE STRING \"\" FORCE)\nset(CMAKE_CXX_FLAGS \"${CMAKE_CXX_FLAGS} ${ARCH_FLAGS}\" CACHE STRING \"\" FORCE)\nset(CMAKE_ASM_FLAGS \"${CMAKE_ASM_FLAGS} ${ARCH_FLAGS}\" CACHE STRING \"\" FORCE)\n\nset(OPENGL_LIBRARIES GLESv2)\nset(ARMV7 ON)\nset(USING_GLES2 ON)\n"
  },
  {
    "path": "scriptmodules/emulators/ppsspp-1.5.4.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ppsspp-1.5.4\"\nrp_module_desc=\"PlayStation Portable emulator PPSSPP v1.5.4\"\nrp_module_help=\"ROM Extensions: .iso .pbp .cso\\n\\nCopy your PlayStation Portable roms to $romdir/psp\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/hrydgard/ppsspp/master/LICENSE.TXT\"\nrp_module_repo=\"git https://github.com/hrydgard/ppsspp.git v1.5.4\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_ppsspp-1.5.4() {\n    depends_ppsspp\n}\n\nfunction sources_ppsspp-1.5.4() {\n    sources_ppsspp\n}\n\nfunction build_ppsspp-1.5.4() {\n    build_ppsspp\n}\n\nfunction install_ppsspp-1.5.4() {\n    install_ppsspp\n}\n\nfunction configure_ppsspp-1.5.4() {\n    configure_ppsspp\n}\n"
  },
  {
    "path": "scriptmodules/emulators/ppsspp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ppsspp\"\nrp_module_desc=\"PlayStation Portable emulator PPSSPP\"\nrp_module_help=\"ROM Extensions: .iso .pbp .cso\\n\\nCopy your PlayStation Portable roms to $romdir/psp\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/hrydgard/ppsspp/master/LICENSE.TXT\"\nrp_module_repo=\"git https://github.com/hrydgard/ppsspp.git :_get_release_ppsspp\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _get_release_ppsspp() {\n    local tagged_version=\"v1.20.1\"\n    # buster and older can't compile recent PPSSPP\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        #  the V3D Mesa driver before 21.x has issues with v1.14 and later\n        if isPlatform \"kms\" && isPlatform \"rpi\"; then\n            tagged_version=\"v1.13.2\"\n        else\n            tagged_version=\"v1.16.6\"\n        fi\n    fi\n    echo $tagged_version\n}\n\nfunction depends_ppsspp() {\n    local depends=(cmake libbrotli-dev libsnappy-dev libbz2-dev libzip-dev zlib1g-dev libzstd-dev libminiupnpc-dev)\n    [[ $md_id != \"lr-ppsspp\" ]] && depends+=(libsdl2-dev libsdl2-ttf-dev libfontconfig-dev)\n    [[ $md_id != \"lr-ppsspp\" ]] && isPlatform \"x11\" && depends+=(libx11-dev wayland-protocols libwayland-dev)\n    isPlatform \"x86\" && depends+=(nasm)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_ppsspp() {\n    gitPullOrClone \"$md_build/ppsspp\"\n    cd \"ppsspp\"\n\n    # remove the lines that trigger the ffmpeg build script functions - we will just use the variables from it\n    sed -i \"/^build_ARMv6$/,$ d\" ffmpeg/linux_arm.sh\n\n    # remove -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 as we handle this ourselves if armv7 on Raspbian\n    sed -i \"/^  -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2/d\" cmake/Toolchains/raspberry.armv7.cmake\n    # set ARCH_FLAGS to our own CXXFLAGS (which includes GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 if needed)\n    sed -i \"s/^set(ARCH_FLAGS.*/set(ARCH_FLAGS \\\"$CXXFLAGS\\\")/\" cmake/Toolchains/raspberry.armv7.cmake\n\n    # remove file(READ \"/sys/firmware/devicetree/base/compatible\" PPSSPP_PI_MODEL)\n    # as it fails when building in a chroot\n    sed -i \"/^file(READ .*/d\" cmake/Toolchains/raspberry.armv7.cmake\n\n    # ensure Pi vendor libraries are available for linking of shared library\n    sed -n -i \"p; s/^set(CMAKE_EXE_LINKER_FLAGS/set(CMAKE_SHARED_LINKER_FLAGS/p\" cmake/Toolchains/raspberry.armv?.cmake\n\n    # fix missing defines on opengles2 on v1.16.6 lr-ppsspp/ppsspp\n    # fix building with recent SDL_TTF on v1.16.6 for ppsspp\n    if [[ \"$md_id\" == \"ppsspp\" && \"$(_get_release_ppsspp)\" == \"v1.16.6\" ]]; then\n        applyPatch \"${__mod_info[ppsspp/path]%/*}/ppsspp/gles2_fix.diff\"\n        applyPatch \"${__mod_info[ppsspp/path]%/*}/ppsspp/sdl_ttf_fix_before_1.19.diff\"\n    fi\n}\n\nfunction build_ffmpeg_ppsspp() {\n    cd \"$1\"\n    local arch\n    if isPlatform \"arm\"; then\n        if isPlatform \"armv6\"; then\n            arch=\"arm\"\n        else\n            arch=\"armv7\"\n        fi\n    elif isPlatform \"x86\"; then\n        if isPlatform \"x86_64\"; then\n            arch=\"x86_64\";\n        else\n            arch=\"x86\";\n        fi\n    elif isPlatform \"aarch64\"; then\n        arch=\"aarch64\"\n    fi\n    # force to arm arch on arm - fixes building on 32bit arm userland with aarch64 kernel\n    isPlatform \"arm\" && local extra_params='--arch=arm'\n\n    local MODULES\n    local VIDEO_DECODERS\n    local AUDIO_DECODERS\n    local VIDEO_ENCODERS\n    local AUDIO_ENCODERS\n    local DEMUXERS\n    local MUXERS\n    local PARSERS\n    local GENERAL\n    local OPTS # used by older lr-ppsspp fork\n    # get the ffmpeg configure variables from the ppsspp ffmpeg distributed script\n    source linux_arm.sh\n    # linux_arm.sh has set -e which we need to switch off\n    set +e\n    ./configure $extra_params \\\n        --prefix=\"./linux/$arch\" \\\n        --extra-cflags=\"-fasm -Wno-psabi -fno-short-enums -fno-strict-aliasing -finline-limit=300\" \\\n        --disable-shared \\\n        --enable-static \\\n        --enable-zlib \\\n        --enable-pic \\\n        --disable-everything \\\n        ${MODULES} \\\n        ${VIDEO_DECODERS} \\\n        ${AUDIO_DECODERS} \\\n        ${VIDEO_ENCODERS} \\\n        ${AUDIO_ENCODERS} \\\n        ${DEMUXERS} \\\n        ${MUXERS} \\\n        ${PARSERS}\n    make clean\n    make install\n}\n\nfunction build_ppsspp() {\n    local ppsspp_binary=\"PPSSPPSDL\"\n\n    # build ffmpeg\n    build_ffmpeg_ppsspp \"$md_build/ppsspp/ffmpeg\"\n\n    # build ppsspp\n    cd \"$md_build/ppsspp\"\n    rm -fr \"build\" && mkdir \"build\"\n    cd \"build\"\n    local params=()\n    if isPlatform \"videocore\"; then\n        if isPlatform \"armv6\"; then\n            params+=(-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/raspberry.armv6.cmake -DFORCED_CPU=armv6 -DATOMIC_LIB=atomic)\n        else\n            params+=(-DCMAKE_TOOLCHAIN_FILE=cmake/Toolchains/raspberry.armv7.cmake)\n        fi\n    elif isPlatform \"mesa\"; then\n        params+=(-DUSING_GLES2=ON -DUSING_EGL=OFF)\n        # force arm target on arm platforms to fix building on arm 32bit userland with aarch64 kernel\n        if isPlatform \"arm\"; then\n            if isPlatform \"armv6\"; then\n                params+=(-DFORCED_CPU=armv6)\n            else\n                params+=(-DFORCED_CPU=armv7)\n            fi\n        fi\n    elif isPlatform \"mali\"; then\n        params+=(-DUSING_GLES2=ON -DUSING_FBDEV=ON)\n        # remove -DGL_GLEXT_PROTOTYPES on odroid-xu/tinker to avoid errors due to header prototype differences\n        params+=(-DCMAKE_C_FLAGS=\"${CFLAGS/-DGL_GLEXT_PROTOTYPES/}\")\n        params+=(-DCMAKE_CXX_FLAGS=\"${CXXFLAGS/-DGL_GLEXT_PROTOTYPES/}\")\n    elif isPlatform \"tinker\"; then\n        params+=(-DCMAKE_TOOLCHAIN_FILE=\"$md_data/tinker.armv7.cmake\")\n    fi\n    isPlatform \"vero4k\" && params+=(-DCMAKE_TOOLCHAIN_FILE=\"cmake/Toolchains/vero4k.armv8.cmake\")\n    if isPlatform \"arm\" && ! isPlatform \"vulkan\"; then\n        params+=(-DARM_NO_VULKAN=ON)\n    fi\n    if isPlatform \"vulkan\"; then\n        params+=(-DUSE_VULKAN_DISPLAY_KHR=ON)\n    fi\n    if isPlatform \"x11\"; then\n        params+=(-DUSE_WAYLAND_WSI=ON -DUSING_X11_VULKAN=ON)\n    fi\n    if [[ \"$md_id\" == \"lr-ppsspp\" ]]; then\n        params+=(-DLIBRETRO=On)\n        ppsspp_binary=\"lib/ppsspp_libretro.so\"\n    fi\n    params+=(-DUSE_SYSTEM_SNAPPY=ON -DUSE_SYSTEM_ZSTD=ON -DUSE_SYSTEM_LIBZIP=ON -DUSE_SYSTEM_LIBSDL2=ON -DUSE_SYSTEM_ZSTD=ON -DUSE_SYSTEM_MINIUPNPC=ON)\n    params+=(-DUSE_DISCORD=OFF)\n    cmake \"${params[@]}\" ..\n    make clean\n    make\n\n    md_ret_require=\"$md_build/ppsspp/build/$ppsspp_binary\"\n}\n\nfunction install_ppsspp() {\n    md_ret_files=(\n        'ppsspp/build/assets'\n        'ppsspp/build/PPSSPPSDL'\n    )\n}\n\nfunction configure_ppsspp() {\n    local extra_params=()\n    if ! isPlatform \"x11\"; then\n        extra_params+=(--fullscreen)\n    fi\n\n    mkRomDir \"psp\"\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        moveConfigDir \"$home/.config/ppsspp\" \"$md_conf_root/psp\"\n        mkUserDir \"$md_conf_root/psp/PSP\"\n        ln -snf \"$romdir/psp\" \"$md_conf_root/psp/PSP/GAME\"\n    fi\n\n    addEmulator 0 \"$md_id\" \"psp\" \"pushd $md_inst; $md_inst/PPSSPPSDL ${extra_params[*]} %ROM%; popd\"\n    addSystem \"psp\"\n\n    # if we are removing the last remaining psp emu - remove the symlink\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        if [[ -h \"$home/.config/ppsspp\" && ! -f \"$md_conf_root/psp/emulators.cfg\" ]]; then\n            rm -f \"$home/.config/ppsspp\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/px68k/001-missing-typedef.diff",
    "content": "diff --git a/win32api/peace.c b/win32api/peace.c\nindex 86989db..8a09337 100755\n--- a/win32api/peace.c\n+++ b/win32api/peace.c\n@@ -69,8 +69,8 @@ enum {\n \tHTYPE_CONSOLE,\n \tHTYPE_KEY,\n };\n-#ifdef _WIN32\n typedef unsigned int u_int;\n+#ifdef _WIN32\n #define bzero(s,d) memset(s,0,d)\n #endif\n struct internal_handle {\n"
  },
  {
    "path": "scriptmodules/emulators/px68k.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"px68k\"\nrp_module_desc=\"SHARP X68000 Emulator\"\nrp_module_help=\"You need to copy a X68000 bios file (iplrom30.dat, iplromco.dat, iplrom.dat, or iplromxv.dat), and the font file (cgrom.dat or cgrom.tmp) to $biosdir/keropi. Use F12 to access the in emulator menu.\"\nrp_module_repo=\"git https://github.com/TurtleBazooka/px68k.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_px68k() {\n    local depends=(cmake libsdl2-dev libsdl2-ttf-dev)\n    # MIDI support is through Fluidsynth, but it needs version 2 of the library\n    [[ \"$__os_debian_ver\" -gt 10 ]] && depends+=(libfluidsynth-dev timgm6mb-soundfont)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_px68k() {\n    gitPullOrClone\n    applyPatch \"$md_data/001-missing-typedef.diff\"\n}\n\nfunction build_px68k() {\n    local has_fluid\n    [[ \"$__os_debian_ver\" -gt 10 ]] && has_fluid=\"FLUID=1\"\n    make clean\n    make CDEBUGFLAGS=\"$CFLAGS -DNO_MERCURY -DSDL2\" SDL2=1 $has_fluid\n    md_ret_require=\"$md_build/px68k.sdl2\"\n}\n\nfunction install_px68k() {\n    md_ret_files=(\n        'px68k.sdl2'\n        'readme.txt'\n        'README.md'\n        'version.txt'\n    )\n}\n\nfunction configure_px68k() {\n    mkRomDir \"x68000\"\n\n    moveConfigDir \"$home/.keropi\" \"$md_conf_root/x68000\"\n    mkUserDir \"$biosdir/keropi\"\n\n    local bios\n    for bios in cgrom.dat iplrom30.dat iplromco.dat iplrom.dat iplromxv.dat; do\n        if [[ -f \"$biosdir/$bios\" ]]; then\n            mv \"$biosdir/$bios\" \"$biosdir/keropi/$bios\"\n        fi\n        ln -sf \"$biosdir/keropi/$bios\" \"$md_conf_root/x68000/$bios\"\n    done\n\n    addEmulator 1 \"$md_id\" \"x68000\" \"$md_inst/px68k.sdl2 %ROM%\"\n    addSystem \"x68000\"\n\n    [[ \"$md_mode\"  == \"remove\" ]] && return\n\n    # generate a minimal config file when no configuration is present\n    local conf=\"$md_conf_root/x68000/config\"\n    if [[ ! -f \"$conf\" ]]; then\n        echo \"[WinX68k]\" > \"$conf\"\n        echo \"StartDir=$romdir/x68000\" >> \"$conf\"\n        echo \"MenuLanguage=1\" >> \"$conf\" # anything non-zero means US\n        # when fluidsynth is enabled, add the soundfont path\n        [[ \"$__os_debian_ver\" -gt 10 ]] && echo \"SoundFontFile=/usr/share/sounds/sf2/TimGM6mb.sf2\" >> \"$conf\"\n    fi\n    chown \"$__user\":\"$__group\" \"$conf\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/quasi88/01_cmake.diff",
    "content": "diff --git a/CMakeLists.txt b/CMakeLists.txt\nindex 83c52bc..98deb4f 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -229,7 +229,7 @@ if(ENABLE_SDL)\n \tadd_definitions(-DQUASI88_SDL)\n \tfind_package(SDL2 CONFIG REQUIRED)\n \n-\tlist(APPEND SDL_LIBS SDL2::SDL2 SDL2::SDL2main)\n+\tlist(APPEND SDL_LIBS ${SDL2_LIBRARIES})\n \tlist(APPEND SDL_INCLUDES\n \t\tsrc/SDL\n \t)\n@@ -257,6 +257,7 @@ if(ENABLE_SDL)\n \t)\n \ttarget_include_directories(${PROJECT_NAME}.sdl PRIVATE ${SDL_INCLUDES})\n \ttarget_link_libraries(${PROJECT_NAME}.sdl ${COMMON_LIBS} ${SDL_LIBS})\n+\ttarget_link_libraries(${PROJECT_NAME}.sdl $<$<AND:$<CXX_COMPILER_ID:GNU>,$<VERSION_LESS:$<CXX_COMPILER_VERSION>,9.0>>:stdc++fs>)\n \n \t#### macOS needs rpath set if using a Framework\n \tif(CMAKE_SYSTEM_NAME STREQUAL \"Darwin\")\n"
  },
  {
    "path": "scriptmodules/emulators/quasi88.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"quasi88\"\nrp_module_desc=\"NEC PC-8801 emulator\"\nrp_module_help=\"ROM Extensions: .d88 .88d .cmt .t88\\n\\nCopy your pc88 games to to $romdir/pc88\\n\\nCopy bios files FONT.ROM, N88.ROM, N88KNJ1.ROM, N88KNJ2.ROM, and N88SUB.ROM to $biosdir/pc88\"\nrp_module_repo=\"git https://github.com/winterheart/quasi88.git master\"\nrp_module_licence=\"BSD https://raw.githubusercontent.com/winterheart/quasi88/master/LICENSE.txt\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_quasi88() {\n    getDepends cmake libsdl2-dev libfmt-dev libspdlog-dev\n}\n\nfunction sources_quasi88() {\n    gitPullOrClone\n    applyPatch \"$md_data/01_cmake.diff\"\n}\n\nfunction build_quasi88() {\n    rm -fr build\n    mkdir -p build && pushd build\n    cmake -DROMDIR=\"$biosdir/pc88\" -DDISKDIR=\"$romdir/pc88\" -DTAPEDIR=\"$romdir/pc88\" ..\n    make\n    popd\n}\n\nfunction install_quasi88() {\n    md_ret_files=(\n        \"build/quasi88.sdl\"\n        \"document\"\n        \"LICENSE.txt\"\n        \"README.md\"\n        \"ChangeLog.md\"\n    )\n}\n\nfunction configure_quasi88() {\n    mkRomDir \"pc88\"\n    moveConfigDir \"$home/.quasi88\" \"$md_conf_root/pc88\"\n    mkUserDir \"$biosdir/pc88\"\n\n    addEmulator 1 \"$md_id\" \"pc88\" \"$md_inst/quasi88.sdl -f6 IMAGE-NEXT1 -f7 IMAGE-NEXT2 -f8 NOWAIT -f9 ROMAJI -f10 NUMLOCK -fullscreen %ROM%\"\n    addSystem \"pc88\"\n\n    [[ \"$mode\" == \"remove\" ]] && return\n\n    # add a minimal configuration file\n    local conf=\"$md_conf_root/pc88/quasi88.ini\"\n    if [[ ! -f \"$conf\" ]]; then\ncat > \"$conf\" << EOF\n-auto_mouse\n-nostatus\n-double\n-english\n-use_joy\n-verbose 1\n-romdir \"$biosdir/pc88\"\n-diskdir \"$romdir/pc88\"\n-tapedir \"$romdir/pc88\"\nEOF\n    chown \"$__user\":\"$__group\" \"$conf\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/redream.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"redream\"\nrp_module_desc=\"Redream Dreamcast emulator\"\nrp_module_help=\"ROM Extensions: .cdi .cue .chd .gdi .iso\\n\\nCopy your Dreamcast roms to $romdir/dreamcast\"\nrp_module_licence=\"PROP\"\nrp_module_section=\"exp\"\nrp_module_flags=\"noinstclean !all gles31 aarch64 x86_64\"\n\nfunction __binary_url_redream() {\n    local platf=\"universal-raspberry\"\n    isPlatform \"x86_64\" && platf=\"x86_64\"\n    local url=\"https://redream.io/download/redream.${platf}-linux-latest.tar.gz\"\n\n    echo \"$url\"\n}\n\nfunction install_bin_redream() {\n    downloadAndExtract \"$(__binary_url_redream)\" \"$md_inst\"\n}\n\nfunction configure_redream() {\n    mkRomDir \"dreamcast\"\n\n    addEmulator 1 \"$md_id\" \"dreamcast\" \"$md_inst/redream %ROM%\"\n    addSystem \"dreamcast\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    chown -R \"$__user\":\"$__group\" \"$md_inst\"\n\n    local dest=\"$md_conf_root/dreamcast/redream\"\n    mkUserDir \"$dest\"\n\n    # symlinks configs and cache\n    moveConfigFile \"$md_inst/redream.cfg\" \"$dest/redream.cfg\"\n    moveConfigDir \"$md_inst/cache\" \"$dest/cache\"\n    moveConfigDir \"$md_inst/saves\" \"$dest/saves\"\n    moveConfigDir \"$md_inst/states\" \"$dest/states\"\n\n    # copy / symlink vmus (memory cards)\n    local i\n    for i in 0 1 2 3; do\n      moveConfigFile \"$md_inst/vmu$i.bin\" \"$dest/vmu$i.bin\"\n    done\n\n    # symlink bios files to libretro core install locations\n    mkUserDir \"$biosdir/dc\"\n    ln -sf \"$biosdir/dc/dc_boot.bin\" \"$md_inst/boot.bin\"\n    ln -sf \"$biosdir/dc/dc_flash.bin\" \"$md_inst/flash.bin\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/reicast/0001-enable-rpi4-sdl2-target.patch",
    "content": "diff --git a/shell/linux/Makefile b/shell/linux/Makefile\nindex 96c2e58..a975698 100644\n--- a/shell/linux/Makefile\n+++ b/shell/linux/Makefile\n@@ -185,9 +185,13 @@ else ifneq (,$(findstring lincpp,$(platform)))\n else ifneq (,$(findstring rpi4,$(platform)))\n \n     CFLAGS += -D TARGET_BEAGLE -D TARGET_LINUX_ARMELv7 -DARM_HARDFP -fsingle-precision-constant\n-    CFLAGS += -DGLES3\n+    ifneq (,$(findstring sdl,$(platform)))\n+        USE_SDL := 1\n+    else\n+        CFLAGS += -DGLES3\n+        USE_X11 := 1\n+    endif\n \n-    USE_X11 := 1\n     USE_GLES := 1\n \n     MFLAGS += -march=armv8-a+crc -mtune=cortex-a72 -mfpu=neon-fp-armv8 -mfloat-abi=hard\n"
  },
  {
    "path": "scriptmodules/emulators/reicast/0002-enable-vsync.patch",
    "content": "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.cpp\n@@ -272,6 +272,8 @@ void sdl_window_create()\n bool gl_init(void* wind, void* disp)\n {\n \tSDL_GL_MakeCurrent(window, glcontext);\n+\tSDL_GL_SetSwapInterval(1);\n+\n \t#ifdef GLES\n \t\treturn true;\n \t#else\n"
  },
  {
    "path": "scriptmodules/emulators/reicast/0003-fix-sdl2-sighandler-conflict.patch",
    "content": "diff --git a/core/linux-dist/main.cpp b/core/linux-dist/main.cpp\nindex aa29515..f53c871 100644\n--- a/core/linux-dist/main.cpp\n+++ b/core/linux-dist/main.cpp\n@@ -374,6 +374,9 @@ int main(int argc, wchar* argv[])\n \tprintf(\"Data dir is:   %s\\n\", get_writable_data_path(\"/\").c_str());\n \n \t#if defined(USE_SDL)\n+\t\t// bypass SDL internal signal handlers due to conflict with reicast handlers\n+\t\tSDL_SetHint(SDL_HINT_NO_SIGNAL_HANDLERS, \"1\");\n+\n \t\tif (SDL_Init(0) != 0)\n \t\t{\n \t\t\tdie(\"SDL: Initialization failed!\");\n@@ -410,6 +413,10 @@ int main(int argc, wchar* argv[])\n \t\tx11_window_destroy();\n \t#endif\n \n+\t#if defined(USE_SDL)\n+\t\tSDL_Quit();\n+\t#endif\n+\n \treturn 0;\n }\n #endif\ndiff --git a/core/linux/common.cpp b/core/linux/common.cpp\nindex 26449cb..fd73602 100644\n--- a/core/linux/common.cpp\n+++ b/core/linux/common.cpp\n@@ -1,6 +1,8 @@\n #include \"types.h\"\n #include \"cfg/cfg.h\"\n \n+extern void dc_exit();\n+\n #if HOST_OS==OS_LINUX || HOST_OS == OS_DARWIN\n #if HOST_OS == OS_DARWIN\n \t#define _XOPEN_SOURCE 1\n@@ -195,7 +197,8 @@ void common_linux_setup()\n \n \tenable_runfast();\n \tinstall_fault_handler();\n-\tsignal(SIGINT, exit);\n+\tsignal(SIGINT, dc_exit);\n+\tsignal(SIGTERM, dc_exit);\n \t\n \tsettings.profile.run_counts=0;\n \t\n"
  },
  {
    "path": "scriptmodules/emulators/reicast/reicast.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nAUDIO=\"$1\"\nROM=\"$2\"\nXRES=\"$3\"\nYRES=\"$4\"\nrootdir=\"/opt/retropie\"\nconfigdir=\"$rootdir/configs\"\nbiosdir=\"$HOME/RetroPie/BIOS/dc\"\n\nsource \"$rootdir/lib/inifuncs.sh\"\n\nif [[ ! -f \"$biosdir/dc_boot.bin\" ]]; then\n    dialog --no-cancel --pause \"You need to copy the Dreamcast BIOS files (dc_boot.bin and dc_flash.bin) to the folder $biosdir to boot the Dreamcast emulator.\" 22 76 15\n    exit 1\nfi\n\nparams=(-config config:homedir=$HOME -config x11:fullscreen=1)\n[[ -n \"$XRES\" ]] && params+=(-config x11:width=$XRES -config x11:height=$YRES)\n[[ -n \"$AUDIO\" ]] && params+=(-config audio:backend=$AUDIO -config audio:disable=0)\n[[ -n \"$ROM\" ]] && params+=(-config config:image=\"$ROM\")\nif [[ \"$AUDIO\" == \"oss\" ]]; then\n    aoss \"$rootdir/emulators/reicast/bin/reicast\" \"${params[@]}\"\nelse\n    \"$rootdir/emulators/reicast/bin/reicast\" \"${params[@]}\"\nfi\n"
  },
  {
    "path": "scriptmodules/emulators/reicast.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"reicast\"\nrp_module_desc=\"Dreamcast emulator Reicast\"\nrp_module_help=\"ROM Extensions: .cdi .gdi\\n\\nCopy your Dreamcast roms to $romdir/dreamcast\\n\\nCopy the required BIOS files dc_boot.bin and dc_flash.bin to $biosdir/dc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/reicast/reicast-emulator/master/LICENSE\"\nrp_module_repo=\"git https://github.com/reicast/reicast-emulator.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!armv6\"\n\nfunction depends_reicast() {\n    local depends=(libsdl2-dev python3-dev python3-pip alsa-oss python3-setuptools libevdev-dev libasound2-dev libudev-dev)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n    isPlatform \"vero4k\" && pip3 install wheel\n    pip3 install evdev\n}\n\nfunction sources_reicast() {\n    gitPullOrClone\n    applyPatch \"$md_data/0001-enable-rpi4-sdl2-target.patch\"\n    applyPatch \"$md_data/0002-enable-vsync.patch\"\n    applyPatch \"$md_data/0003-fix-sdl2-sighandler-conflict.patch\"\n    sed -i \"s#/usr/bin/env python#/usr/bin/env python3#\" shell/linux/tools/reicast-joyconfig.py\n}\n\nfunction _params_reicast() {\n    local platform\n    local subplatform\n    local params=()\n\n    # platform-specific params\n    if isPlatform \"rpi\" && isPlatform \"32bit\"; then\n        # platform configuration\n        if isPlatform \"rpi4\"; then\n            platform=\"rpi4\"\n        elif isPlatform \"rpi3\"; then\n            platform=\"rpi3\"\n        else\n            platform=\"rpi2\"\n        fi\n\n        # subplatform configuration\n        if isPlatform \"rpi4\"; then\n            # we need to target SDL with GLES3 disabled for KMSDRM compatibility\n            subplatform=\"-sdl\"\n        elif isPlatform \"mesa\"; then\n            subplatform=\"-mesa\"\n        fi\n\n        params+=(\"platform=${platform}${subplatform}\")\n    else\n        # generic flags\n        isPlatform \"x11\" && params+=(\"USE_X11=1\")\n        isPlatform \"kms\" || isPlatform \"gles\" && params+=(\"USE_GLES=1\")\n        isPlatform \"kms\" || isPlatform \"tinker\" && params+=(\"USE_X11=\" \"HAS_SOFTREND=\" \"USE_SDL=1\")\n    fi\n\n    echo \"${params[*]}\"\n}\n\nfunction build_reicast() {\n    cd shell/linux\n    make $(_params_reicast) clean\n    make $(_params_reicast)\n\n    md_ret_require=\"$md_build/shell/linux/reicast.elf\"\n}\n\nfunction install_reicast() {\n    cd shell/linux\n    make $(_params_reicast) PREFIX=\"$md_inst\" install\n\n    md_ret_files=(\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_reicast() {\n    local backend\n    local backends=(alsa omx oss)\n    local params=(\"%ROM%\")\n\n    # KMS reqires Xorg context & X/Y res passed.\n    if isPlatform \"kms\"; then\n        params+=(\"%XRES%\" \"%YRES%\")\n    fi\n\n    # copy hotkey remapping start script\n    cp \"$md_data/reicast.sh\" \"$md_inst/bin/\"\n    chmod +x \"$md_inst/bin/reicast.sh\"\n\n    mkRomDir \"dreamcast\"\n\n    # move any old configs to the new location\n    moveConfigDir \"$home/.reicast\" \"$md_conf_root/dreamcast/\"\n\n    # Create home VMU, cfg, and data folders. Copy dc_boot.bin and dc_flash.bin to the ~/.reicast/data/ folder.\n    mkdir -p \"$md_conf_root/dreamcast/\"{data,mappings}\n\n    # symlink bios\n    mkUserDir \"$biosdir/dc\"\n    ln -sf \"$biosdir/dc/\"{dc_boot.bin,dc_flash.bin} \"$md_conf_root/dreamcast/data\"\n\n    # copy default mappings\n    cp \"$md_inst/share/reicast/mappings/\"*.cfg \"$md_conf_root/dreamcast/mappings/\"\n\n    chown -R \"$__user\":\"$__group\" \"$md_conf_root/dreamcast\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        cat > \"$romdir/dreamcast/+Start Reicast.sh\" << _EOF_\n#!/bin/bash\n$md_inst/bin/reicast.sh\n_EOF_\n        chmod a+x \"$romdir/dreamcast/+Start Reicast.sh\"\n        chown \"$__user\":\"$__group\" \"$romdir/dreamcast/+Start Reicast.sh\"\n    else\n        rm \"$romdir/dreamcast/+Start Reicast.sh\"\n    fi\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        # possible audio backends: alsa, oss, omx\n        if isPlatform \"videocore\"; then\n            backends=(omx oss)\n        else\n            backends=(alsa)\n        fi\n    fi\n\n    # add system(s)\n    for backend in \"${backends[@]}\"; do\n        addEmulator 1 \"${md_id}-audio-${backend}\" \"dreamcast\" \"$md_inst/bin/reicast.sh $backend ${params[*]}\"\n    done\n    addSystem \"dreamcast\"\n\n    addAutoConf reicast_input 1\n}\n\nfunction input_reicast() {\n    local temp_file=\"$(mktemp)\"\n    cd \"$md_inst/bin\"\n    ./reicast-joyconfig -f \"$temp_file\" >/dev/tty\n    iniConfig \" = \" \"\" \"$temp_file\"\n    iniGet \"mapping_name\"\n    local mapping_file=\"$configdir/dreamcast/mappings/evdev_${ini_value//[:><?\\\"]/-}.cfg\"\n    mv \"$temp_file\" \"$mapping_file\"\n    chown \"$__user\":\"$__group\" \"$mapping_file\"\n}\n\nfunction gui_reicast() {\n    while true; do\n        local options=(\n            1 \"Configure input devices for Reicast\"\n        )\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        case \"$choice\" in\n            1)\n                clear\n                input_reicast\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/emulators/retroarch/mess2016_libretro.info",
    "content": "# Software Information\ndisplay_name = \"Mess (MAME 2016)\"\nauthors = \"MAMEdev\"\nsupported_extensions = \"zip|chd|7z|cmd\"\ncorename = \"MAME 2016 (0.174)\"\nlicense = \"GPLv2+\"\npermissions = \"\"\ndisplay_version = \"0.174\"\ncategories = \"Emulator\"\n\n# Hardware Information\nmanufacturer = \"Various\"\nsystemname = \"MESS (various)\"\nsystemid = \"mame\"\n\n# Libretro Features\nsupports_no_game = \"false\"\ndatabase = \"MAME 2016\"\nsavestate = \"false\"\nsavestate_features = \"null\"\ncheats = \"false\"\ninput_descriptors = \"false\"\nmemory_descriptors = \"false\"\nlibretro_saves = \"false\"\ncore_options = \"true\"\ncore_options_version = \"1.0\"\nhw_render = \"false\"\ndisk_control = \"false\"\nnotes = \"[1] MAME 2016 (0.174) supports MAME save states.|[2] MAME 2016 (0.174) supports extracted MAME cheats.|[3] The BIOS files must be inside the ROM directory.|[4] The same directory with CHD files inside must be inside the ROM directory.|[5] If desired, the ARTWORK, CHEATS, and SAMPLES directories can be|[^] inside the 'SYSTEMDIR\\mame' directory.|[6] When saving, the following directories will be created in the 'SAVEDIR\\mame'|[^] directory: STATES, NVRAM, INPUT, SNAPS, CFG, MEMCARD, and DIFF.\"\n\ndescription = \"Based on a snapshot of the MAME codebase circa 2016, 'MAME 2016' is compatible with MAME 0.174 ROM sets. MAME is the most compatible emulator in the world, and it can run almost any game from any platform (though running console games through this core requires additional steps). If your device can run the up-to-date MAME - Current core at full speed, most users will have a better experience with that core, while FBNeo is typically a better choice for speed vs accuracy, as long as it supports the game(s) in question. Otherwise, this core is notable as the most recent snapshot core with an unchanging ROM set.\"\n"
  },
  {
    "path": "scriptmodules/emulators/retroarch/mupen64plus_libretro.info",
    "content": "# Software Information\ndisplay_name = \"Nintendo - Nintendo 64 (Mupen64Plus-Legacy)\"\nauthors = \"m4xw|Hacktarux|gonetz|GLideN64 Contributors|Mupen64Plus Team\"\nsupported_extensions = \"n64|v64|z64|bin|u1\"\ncorename = \"Mupen64Plus\"\nlicense = \"GPLv2\"\npermissions = \"dynarec_optional\"\ndisplay_version = \"1.0\"\ncategories = \"Emulator\"\n\n# Hardware Information\nmanufacturer = \"Nintendo\"\nsystemname = \"Nintendo 64\"\nsystemid = \"nintendo_64\"\n\n# Libretro Features\nsupports_no_game = \"false\"\ndatabase = \"Nintendo - Nintendo 64\"\nhw_render = \"true\"\nrequired_hw_api = \"OpenGL Core >= 3.3 | OpenGL ES >= 2.0\"\nsavestate = \"true\"\nsavestate_features = \"serialized\"\ncheats = \"true\"\ninput_descriptors = \"true\"\nmemory_descriptors = \"true\"\nlibretro_saves = \"true\"\ncore_options = \"true\"\nload_subsystem = \"true\"\nneeds_fullpath = \"false\"\ndisk_control = \"false\"\nis_experimental = \"false\"\n\ndescription = \"The legacy version of the Mupen64Plus N64 emulator, ported to libretro. It uses the GLideN64 plugin as its default graphics plug, though the high-accuracy Angrylion and ParaLLEl-RDP plugins are also available. This core is no longer developed, but it's still useful for low power devices - for other platforms use the Mupen64Plus-Next core\"\n"
  },
  {
    "path": "scriptmodules/emulators/retroarch.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"retroarch\"\nrp_module_desc=\"RetroArch - frontend to the libretro emulator cores - required by all lr-* emulators\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/RetroArch/master/COPYING\"\nrp_module_repo=\"git https://github.com/retropie/RetroArch.git retropie-v1.19.0\"\nrp_module_section=\"core\"\n\nfunction depends_retroarch() {\n    local depends=(libudev-dev libxkbcommon-dev libsdl2-dev libasound2-dev libusb-1.0-0-dev)\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    isPlatform \"gles\" && ! isPlatform \"vero4k\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"mesa\" && depends+=(libx11-xcb-dev)\n    isPlatform \"mali\" && depends+=(mali-fbdev)\n    isPlatform \"x11\" && depends+=(libx11-xcb-dev libpulse-dev)\n    isPlatform \"vulkan\" && depends+=(libvulkan-dev mesa-vulkan-drivers)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc zlib1g-dev libfreetype6-dev)\n    isPlatform \"kms\" && depends+=(libgbm-dev)\n\n    if [[ \"$__os_debian_ver\" -ge 9 ]]; then\n        depends+=(libavcodec-dev libavformat-dev libavdevice-dev)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_retroarch() {\n    gitPullOrClone\n}\n\nfunction build_retroarch() {\n    local params=(--disable-sdl --enable-sdl2 --disable-oss --disable-al --disable-jack --disable-qt --enable-builtinmbedtls)\n    if ! isPlatform \"x11\"; then\n        params+=(--disable-pulse)\n        ! isPlatform \"mesa\" && params+=(--disable-x11)\n    fi\n    if [[ \"$__os_debian_ver\" -lt 9 ]]; then\n        params+=(--disable-ffmpeg)\n    fi\n    isPlatform \"gles\" && params+=(--enable-opengles)\n    if isPlatform \"gles3\"; then\n        params+=(--enable-opengles3)\n        isPlatform \"gles31\" && params+=(--enable-opengles3_1)\n        isPlatform \"gles32\" && params+=(--enable-opengles3_2)\n    fi\n    isPlatform \"videocore\" && params+=(--disable-crtswitchres)\n    isPlatform \"rpi\" && isPlatform \"mesa\" && params+=(--disable-videocore)\n    # Temporarily block dispmanx support for fkms until upstream support is fixed\n    isPlatform \"dispmanx\" && ! isPlatform \"kms\" && params+=(--enable-dispmanx --disable-opengl1)\n    isPlatform \"mali\" && params+=(--enable-mali_fbdev)\n    isPlatform \"kms\" && params+=(--enable-kms --enable-egl)\n    isPlatform \"arm\" && params+=(--enable-floathard)\n    isPlatform \"neon\" && params+=(--enable-neon)\n    isPlatform \"vulkan\" && params+=(--enable-vulkan) || params+=(--disable-vulkan)\n    ! isPlatform \"x11\" && params+=(--disable-wayland)\n    isPlatform \"vero4k\" && params+=(--enable-mali_fbdev --with-opengles_libs='-L/opt/vero3/lib')\n    ./configure --prefix=\"$md_inst\" \"${params[@]}\"\n    make clean\n    make\n    md_ret_require=\"$md_build/retroarch\"\n}\n\nfunction install_retroarch() {\n    make install\n    md_ret_files=(\n        'retroarch.cfg'\n    )\n}\n\nfunction update_shaders_retroarch() {\n    local dir=\"$configdir/all/retroarch/shaders\"\n    local branch=\"\"\n    isPlatform \"rpi\" && branch=\"rpi\"\n    # remove if not git repository for fresh checkout\n    [[ ! -d \"$dir/.git\" ]] && rm -rf \"$dir\"\n    gitPullOrClone \"$dir\" https://github.com/RetroPie/common-shaders.git \"$branch\"\n    chown -R \"$__user\":\"$__group\" \"$dir\"\n}\n\nfunction update_overlays_retroarch() {\n    local dir=\"$configdir/all/retroarch/overlay\"\n    # remove if not a git repository for fresh checkout\n    [[ ! -d \"$dir/.git\" ]] && rm -rf \"$dir\"\n    gitPullOrClone \"$dir\" https://github.com/libretro/common-overlays.git\n    chown -R \"$__user\":\"$__group\" \"$dir\"\n}\n\nfunction update_joypad_autoconfigs_retroarch() {\n    gitPullOrClone \"$md_build/autoconfigs\" https://github.com/libretro/retroarch-joypad-autoconfig.git\n    cp -a \"$md_build/autoconfigs/.\" \"$md_inst/autoconfig-presets/\"\n}\n\nfunction update_assets_retroarch() {\n    local dir=\"$configdir/all/retroarch/assets\"\n    # remove if not a git repository for fresh checkout\n    [[ ! -d \"$dir/.git\" ]] && rm -rf \"$dir\"\n    gitPullOrClone \"$dir\" https://github.com/libretro/retroarch-assets.git\n    chown -R \"$__user\":\"$__group\" \"$dir\"\n}\n\nfunction update_core_info_retroarch() {\n    local dir=\"$configdir/all/retroarch/cores\"\n    # remove if not a git repository and do a fresh checkout\n    [[ ! -d \"$dir/.git\" ]] && rm -fr \"$dir\"\n    # remove our locally generated `.info` files, just in case upstream adds them\n    [[ -d \"$dir/.git\" ]] && git -C \"$dir\" clean -q -f \"*.info\"\n    gitPullOrClone \"$dir\" https://github.com/libretro/libretro-core-info.git\n    # add our info files for cores not included in the upstream repo\n    cp --update \"$md_data\"/*.info \"$dir\"\n    chown -R \"$__user\":\"$__group\" \"$dir\"\n}\n\nfunction install_minimal_assets_retroarch() {\n    local dir=\"$configdir/all/retroarch/assets\"\n    [[ -d \"$dir/.git\" ]] && return\n    [[ ! -d \"$dir\" ]] && mkUserDir \"$dir\"\n    downloadAndExtract \"$__binary_base_url/retroarch-minimal-assets.tar.gz\" \"$dir\"\n    chown -R \"$__user\":\"$__group\" \"$dir\"\n}\n\nfunction _package_minimal_assets_retroarch() {\n    gitPullOrClone \"$md_build/assets\" https://github.com/libretro/retroarch-assets.git\n    mkdir -p \"$__tmpdir/archives\"\n    local archive=\"$__tmpdir/archives/retroarch-minimal-assets.tar.gz\"\n    rm -f \"$archive\"\n    tar cvzf \"$archive\" -C \"$md_build/assets\" ozone menu_widgets xmb/monochrome\n}\n\nfunction configure_retroarch() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    addUdevInputRules\n\n    # move / symlink the retroarch configuration\n    moveConfigDir \"$home/.config/retroarch\" \"$configdir/all/retroarch\"\n\n    # move / symlink our old retroarch-joypads folder\n    moveConfigDir \"$configdir/all/retroarch-joypads\" \"$configdir/all/retroarch/autoconfig\"\n\n    # move / symlink old assets / overlays and shader folder\n    moveConfigDir \"$md_inst/assets\" \"$configdir/all/retroarch/assets\"\n    moveConfigDir \"$md_inst/overlays\" \"$configdir/all/retroarch/overlay\"\n    moveConfigDir \"$md_inst/shader\" \"$configdir/all/retroarch/shaders\"\n\n    # install shaders by default\n    update_shaders_retroarch\n\n    # install minimal assets\n    install_minimal_assets_retroarch\n\n    # install core info files\n    update_core_info_retroarch\n\n    # install joypad autoconfig presets\n    update_joypad_autoconfigs_retroarch\n\n    local config=\"$(mktemp)\"\n\n    cp \"$md_inst/retroarch.cfg\" \"$config\"\n\n    # query ES A/B key swap configuration\n    local es_swap=\"false\"\n    getAutoConf \"es_swap_a_b\" && es_swap=\"true\"\n\n    # configure default options\n    iniConfig \" = \" '\"' \"$config\"\n    iniSet \"cache_directory\" \"/tmp/retroarch\"\n    iniSet \"system_directory\" \"$biosdir\"\n    iniSet \"config_save_on_exit\" \"false\"\n    iniSet \"video_aspect_ratio_auto\" \"true\"\n    if ! isPlatform \"x86\"; then\n        iniSet \"video_threaded\" \"true\"\n    fi\n\n    iniSet \"video_font_size\" \"24\"\n    iniSet \"core_options_path\" \"$configdir/all/retroarch-core-options.cfg\"\n    iniSet \"global_core_options\" \"true\"\n    isPlatform \"x11\" && iniSet \"video_fullscreen\" \"true\"\n    isPlatform \"mesa\" && iniSet \"video_fullscreen\" \"true\"\n\n    # set default render resolution to 640x480 for rpi1\n    if isPlatform \"videocore\" && isPlatform \"rpi1\"; then\n        iniSet \"video_fullscreen_x\" \"640\"\n        iniSet \"video_fullscreen_y\" \"480\"\n    fi\n\n    # enable hotkey (\"select\" button)\n    iniSet \"input_enable_hotkey\" \"nul\"\n    iniSet \"input_exit_emulator\" \"escape\"\n\n    # enable and configure rewind feature\n    iniSet \"rewind_enable\" \"false\"\n    iniSet \"rewind_buffer_size\" \"10\"\n    iniSet \"rewind_granularity\" \"2\"\n    iniSet \"input_rewind\" \"r\"\n\n    # enable gpu screenshots\n    iniSet \"video_gpu_screenshot\" \"true\"\n\n    # enable and configure shaders\n    iniSet \"input_shader_next\" \"m\"\n    iniSet \"input_shader_prev\" \"n\"\n\n    # configure keyboard mappings\n    iniSet \"input_player1_a\" \"x\"\n    iniSet \"input_player1_b\" \"z\"\n    iniSet \"input_player1_y\" \"a\"\n    iniSet \"input_player1_x\" \"s\"\n    iniSet \"input_player1_start\" \"enter\"\n    iniSet \"input_player1_select\" \"rshift\"\n    iniSet \"input_player1_l\" \"q\"\n    iniSet \"input_player1_r\" \"w\"\n    iniSet \"input_player1_left\" \"left\"\n    iniSet \"input_player1_right\" \"right\"\n    iniSet \"input_player1_up\" \"up\"\n    iniSet \"input_player1_down\" \"down\"\n\n    # input settings\n    iniSet \"input_autodetect_enable\" \"true\"\n    iniSet \"auto_remaps_enable\" \"true\"\n    iniSet \"input_joypad_driver\" \"udev\"\n    iniSet \"all_users_control_menu\" \"true\"\n    iniSet \"remap_save_on_exit\" \"false\"\n\n    # rgui by default\n    iniSet \"menu_driver\" \"rgui\"\n    iniSet \"rgui_aspect_ratio_lock\" \"2\"\n    iniSet \"rgui_browser_directory\" \"$romdir\"\n    iniSet \"rgui_switch_icons\" \"false\"\n    iniSet \"menu_rgui_shadows\" \"true\"\n    iniSet \"rgui_menu_color_theme\" \"29\" # Tango Dark theme\n\n    # hide online updater menu options and the restart option\n    iniSet \"menu_show_core_updater\" \"false\"\n    iniSet \"menu_show_online_updater\" \"false\"\n    iniSet \"menu_show_restart_retroarch\" \"false\"\n    # disable the search action\n    iniSet \"menu_disable_search_button\" \"true\"\n\n    # remove some rarely used entries from the quick menu\n    iniSet \"quick_menu_show_close_content\" \"false\"\n    iniSet \"quick_menu_show_add_to_favorites\" \"false\"\n    iniSet \"quick_menu_show_replay\" \"false\"\n    iniSet \"quick_menu_show_start_recording\" \"false\"\n    iniSet \"quick_menu_show_start_streaming\" \"false\"\n    iniSet \"menu_show_overlays\" \"false\"\n\n    # disable the load notification message with core and game info\n    iniSet \"menu_show_load_content_animation\" \"false\"\n    # disable core cache file\n    iniSet \"core_info_cache_enable\" \"false\"\n    # disable game runtime logging\n    iniSet \"content_runtime_log\" \"false\"\n\n    # disable unnecessary xmb menu tabs\n    iniSet \"xmb_show_add\" \"false\"\n    iniSet \"xmb_show_history\" \"false\"\n    iniSet \"xmb_show_images\" \"false\"\n    iniSet \"xmb_show_music\" \"false\"\n\n    # disable xmb menu driver icon shadows\n    iniSet \"xmb_shadows_enable\" \"false\"\n\n    # swap A/B buttons based on ES configuration\n    iniSet \"menu_swap_ok_cancel_buttons\" \"$es_swap\"\n\n    # enable menu_unified_controls by default (see below for more info)\n    iniSet \"menu_unified_controls\" \"true\"\n\n    # disable 'press twice to quit'\n    iniSet \"quit_press_twice\" \"false\"\n\n    # enable video shaders\n    iniSet \"video_shader_enable\" \"true\"\n\n    # enable overlays by default\n    iniSet \"input_overlay_enable\" \"true\"\n\n    # disable save paths under sub-folders\n    iniSet \"sort_savestates_enable\" \"false\"\n    iniSet \"sort_savefiles_enable\" \"false\"\n\n    copyDefaultConfig \"$config\" \"$configdir/all/retroarch.cfg\"\n    rm \"$config\"\n\n    # if no menu_driver is set, force RGUI, as the default has now changed to XMB.\n    _set_config_option_retroarch \"menu_driver\" \"rgui\"\n\n    # set RGUI aspect ratio to \"Integer Scaling\" to prevent stretching\n    _set_config_option_retroarch \"rgui_aspect_ratio_lock\" \"2\"\n\n    # if no menu_unified_controls is set, force it on so that keyboard player 1 can control\n    # the RGUI menu which is important for arcade sticks etc that map to keyboard inputs\n    _set_config_option_retroarch \"menu_unified_controls\" \"true\"\n\n    # disable `quit_press_twice` on existing configs\n    _set_config_option_retroarch \"quit_press_twice\" \"false\"\n\n    # enable video shaders on existing configs\n    _set_config_option_retroarch \"video_shader_enable\" \"true\"\n\n    # (compat) keep all core options in a single file\n    _set_config_option_retroarch \"global_core_options\" \"true\"\n\n    # disable the content load info popup with core and game info\n    _set_config_option_retroarch \"menu_show_load_content_animation\" \"false\"\n\n    # disable search action\n    _set_config_option_retroarch \"menu_disable_search_button\" \"true\"\n\n    # don't save input remaps by default\n    _set_config_option_retroarch \"remap_save_on_exit\" \"false\"\n\n    # enable overlays by default on upgrades\n    _set_config_option_retroarch \"input_overlay_enable\" \"true\"\n\n    # don't sort save files in sub-folders\n    _set_config_option_retroarch \"sort_savefiles_enable\" \"false\"\n    _set_config_option_retroarch \"sort_savestates_enable\" \"false\"\n\n    # remapping hack for old 8bitdo firmware\n    addAutoConf \"8bitdo_hack\" 0\n}\n\nfunction keyboard_retroarch() {\n    if [[ ! -f \"$configdir/all/retroarch.cfg\" ]]; then\n        printMsgs \"dialog\" \"No RetroArch configuration file found at $configdir/all/retroarch.cfg\"\n        return\n    fi\n    local input\n    local options\n    local i=1\n    local key=()\n    while read input; do\n        local parts=($input)\n        key+=(\"${parts[0]}\")\n        options+=(\"${parts[0]}\" $i 2 \"${parts[*]:2}\" $i 26 16 0)\n        ((i++))\n    done < <(grep \"^[[:space:]]*input_player[0-9]_[a-z]*\" \"$configdir/all/retroarch.cfg\")\n    local cmd=(dialog --backtitle \"$__backtitle\" --form \"RetroArch keyboard configuration\" 22 48 16)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        local value\n        local values\n        readarray -t values <<<\"$choice\"\n        iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n        i=0\n        for value in \"${values[@]}\"; do\n            iniSet \"${key[$i]}\" \"$value\" >/dev/null\n            ((i++))\n        done\n    fi\n}\n\nfunction hotkey_retroarch() {\n    iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose the desired hotkey behaviour.\" 22 76 16)\n    local options=(1 \"Hotkeys enabled. (default)\"\n             2 \"Press ALT to enable hotkeys.\"\n             3 \"Hotkeys disabled. Press ESCAPE to open RGUI.\")\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                iniSet \"input_enable_hotkey\" \"nul\"\n                iniSet \"input_exit_emulator\" \"escape\"\n                iniSet \"input_menu_toggle\" \"F1\"\n                ;;\n            2)\n                iniSet \"input_enable_hotkey\" \"alt\"\n                iniSet \"input_exit_emulator\" \"escape\"\n                iniSet \"input_menu_toggle\" \"F1\"\n                ;;\n            3)\n                iniSet \"input_enable_hotkey\" \"escape\"\n                iniSet \"input_exit_emulator\" \"nul\"\n                iniSet \"input_menu_toggle\" \"escape\"\n                ;;\n        esac\n    fi\n}\n\nfunction gui_retroarch() {\n    while true; do\n        local names=(shaders overlays assets)\n        local dirs=(shaders overlay assets)\n        local options=()\n        local name\n        local dir\n        local i=1\n        for name in \"${names[@]}\"; do\n            if [[ -d \"$configdir/all/retroarch/${dirs[i-1]}/.git\" ]]; then\n                options+=(\"$i\" \"Manage $name (installed)\")\n            else\n                options+=(\"$i\" \"Manage $name (not installed)\")\n            fi\n            ((i++))\n        done\n        options+=(\n            4 \"Configure keyboard for use with RetroArch\"\n            5 \"Configure keyboard hotkey behaviour for RetroArch\"\n        )\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        case \"$choice\" in\n            1|2|3)\n                name=\"${names[choice-1]}\"\n                dir=\"${dirs[choice-1]}\"\n                options=(1 \"Install/Update $name\" 2 \"Uninstall $name\" )\n                cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option for $dir\" 12 40 06)\n                choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n                case \"$choice\" in\n                    1)\n                        \"update_${name}_retroarch\"\n                        ;;\n                    2)\n                        rm -rf \"$configdir/all/retroarch/$dir\"\n                        [[ \"$dir\" == \"assets\" ]] && install_xmb_monochrome_assets_retroarch\n                        ;;\n                    *)\n                        continue\n                        ;;\n\n                esac\n                ;;\n            4)\n                keyboard_retroarch\n                ;;\n            5)\n                hotkey_retroarch\n                ;;\n            *)\n                break\n                ;;\n        esac\n\n    done\n}\n\n# adds a retroarch global config option in `$configdir/all/retroarch.cfg`, if not already set\nfunction _set_config_option_retroarch()\n{\n    local option=\"$1\"\n    local value=\"$2\"\n    iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n    iniGet \"$option\"\n    if [[ -z \"$ini_value\" ]]; then\n        iniSet \"$option\" \"$value\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/rpix86.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"rpix86\"\nrp_module_desc=\"DOS Emulator rpix86\"\nrp_module_help=\"ROM Extensions: .bat .com .exe .sh\\n\\nCopy your DOS games to $romdir/pc\"\nrp_module_licence=\"FREEWARE http://rpix86.patrickaalto.com/rdown.html\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all rpi !kms\"\n\nfunction install_bin_rpix86() {\n    downloadAndExtract \"$__archive_url/rpix86.tar.gz\" \"$md_inst\"\n    # install 4DOS.com\n    downloadAndExtract \"$__archive_url/4dos.zip\" \"$md_inst\"\n    patchVendorGraphics \"$md_inst/rpix86\"\n}\n\nfunction configure_rpix86() {\n    mkRomDir \"pc\"\n\n    rm -f \"$romdir/pc/Start rpix86.sh\" \"$romdir/pc/+Start.txt\"\n    cat > \"$romdir/pc/+Start rpix86.sh\" << _EOF_\n#!/bin/bash\nparams=(\"\\$@\")\npushd \"$md_inst\"\nif [[ \"\\${params[0]}\" == *.sh ]]; then\n    bash \"\\${params[@]}\"\nelse\n    ./rpix86 -a0 -f2 \"\\${params[@]}\"\nfi\npopd\n_EOF_\n    chmod +x \"$romdir/pc/+Start rpix86.sh\"\n    chown \"$__user\":\"$__group\" \"$romdir/pc/+Start rpix86.sh\"\n    ln -sfn \"$romdir/pc\" games\n\n    addEmulator 0 \"$md_id\" \"pc\" \"bash $romdir/pc/+Start\\ rpix86.sh %ROM%\"\n    addSystem \"pc\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/scummvm-sdl1.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"scummvm-sdl1\"\nrp_module_desc=\"ScummVM - built with legacy SDL1 support.\"\nrp_module_help=\"Copy your ScummVM games to $romdir/scummvm\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/scummvm/scummvm/master/COPYING\"\nrp_module_repo=\"git https://github.com/scummvm/scummvm.git v2026.1.0\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali !x11 !kms\"\n\nfunction depends_scummvm-sdl1() {\n    depends_scummvm\n}\n\nfunction sources_scummvm-sdl1() {\n    # sources_scummvm() expects $md_data to be ../scummvm\n    # the following only modifies $md_data for the function call\n    md_data=\"$(dirname $md_data)/scummvm\" sources_scummvm\n}\n\nfunction build_scummvm-sdl1() {\n    build_scummvm\n}\n\nfunction install_scummvm-sdl1() {\n    install_scummvm\n}\n\nfunction configure_scummvm-sdl1() {\n    # use dispmanx by default on rpi with fkms\n    isPlatform \"dispmanx\" && ! isPlatform \"videocore\" && setBackend \"$md_id\" \"dispmanx\"\n    configure_scummvm\n}\n"
  },
  {
    "path": "scriptmodules/emulators/scummvm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"scummvm\"\nrp_module_desc=\"ScummVM\"\nrp_module_help=\"Copy your ScummVM games to $romdir/scummvm\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/scummvm/scummvm/master/COPYING\"\nrp_module_repo=\"git https://github.com/scummvm/scummvm.git v2026.1.0\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_scummvm() {\n    local depends=(\n        liba52-0.7.4-dev libmpeg2-4-dev libogg-dev libvorbis-dev libenet-dev libflac-dev libgif-dev libmad0-dev libpng-dev\n        libtheora-dev libfaad-dev libfluidsynth-dev libfreetype6-dev zlib1g-dev\n        libjpeg-dev libasound2-dev libcurl4-openssl-dev libmikmod-dev libvpx-dev\n    )\n    if isPlatform \"vero4k\"; then\n        depends+=(vero3-userland-dev-osmc)\n    fi\n    if [[ \"$md_id\" == \"scummvm-sdl1\" ]]; then\n        depends+=(libsdl1.2-dev)\n    else\n        depends+=(libsdl2-dev)\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_scummvm() {\n    gitPullOrClone\n}\n\nfunction build_scummvm() {\n    rpSwap on 750\n    local params=(\n        --prefix=\"$md_inst\"\n        --enable-release --enable-vkeybd\n        --disable-debug --disable-eventrecorder --disable-sonivox\n        --disable-updates --disable-discord --disable-imgui --disable-gtk\n    )\n    isPlatform \"rpi\" && [[ \"$md_id\" == \"scummvm-sdl1\" ]] && params+=(--opengl-mode=none)\n\n    if [[ \"$md_id\" == \"scummvm-sdl1\" ]]; then\n        SDL_CONFIG=sdl-config ./configure \"${params[@]}\"\n    else\n        ./configure \"${params[@]}\"\n    fi\n    make clean\n    make\n    strip \"$md_build/scummvm\"\n    rpSwap off\n    md_ret_require=\"$md_build/scummvm\"\n}\n\nfunction install_scummvm() {\n    make install\n    mkdir -p \"$md_inst/extra\"\n    cp -v backends/vkeybd/packs/vkeybd_*.zip \"$md_inst/extra\"\n}\n\nfunction configure_scummvm() {\n    mkRomDir \"scummvm\"\n\n    local dir\n    for dir in .config .local/share; do\n        moveConfigDir \"$home/$dir/scummvm\" \"$md_conf_root/scummvm\"\n    done\n\n    # Create startup script\n    rm -f \"$romdir/scummvm/+Launch GUI.sh\"\n    local name=\"ScummVM\"\n    [[ \"$md_id\" == \"scummvm-sdl1\" ]] && name=\"ScummVM-SDL1\"\n    cat > \"$romdir/scummvm/+Start $name.sh\" << _EOF_\n#!/bin/bash\ngame=\"\\$1\"\npushd \"$romdir/scummvm\" >/dev/null\nif ! grep -qs extrapath \"\\$HOME/.config/scummvm/scummvm.ini\"; then\n    params=\"--extrapath=\"$md_inst/extra\"\"\nfi\n$md_inst/bin/scummvm --fullscreen \\$params --joystick=0 \"\\$game\"\nwhile read id desc; do\n    echo \"\\$desc\" > \"$romdir/scummvm/\\$id.svm\"\ndone < <($md_inst/bin/scummvm --list-targets | tail -n +3)\npopd >/dev/null\n_EOF_\n    chown \"$__user\":\"$__group\" \"$romdir/scummvm/+Start $name.sh\"\n    chmod u+x \"$romdir/scummvm/+Start $name.sh\"\n\n    addEmulator 1 \"$md_id\" \"scummvm\" \"bash $romdir/scummvm/+Start\\ $name.sh %BASENAME%\"\n    addSystem \"scummvm\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/sdltrs.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sdltrs\"\nrp_module_desc=\"Radio Shack TRS-80 Model I/III/4/4P emulator\"\nrp_module_help=\"ROM Extension: .dsk\\n\\nCopy your TRS-80 games to $romdir/trs-80\\n\\nCopy the required BIOS file level2.rom, level3.rom, level4.rom or level4p.rom to $biosdir\"\nrp_module_section=\"exp\"\nrp_module_licence=\"BSD https://gitlab.com/jengun/sdltrs/-/raw/master/LICENSE\"\nrp_module_repo=\"git https://gitlab.com/jengun/sdltrs.git sdl2\"\nrp_module_flags=\"\"\n\nfunction depends_sdltrs() {\n    getDepends libsdl2-dev libreadline-dev\n}\n\nfunction sources_sdltrs() {\n    gitPullOrClone\n}\n\nfunction build_sdltrs() {\n    make clean\n    ./autogen.sh\n    ./configure --prefix=\"$md_inst\"\n    make\n    md_ret_require=\"$md_build/sdl2trs\"\n}\n\nfunction install_sdltrs() {\n    md_ret_files=(\n        'sdl2trs'\n        'README.md'\n        'LICENSE'\n    )\n}\n\nfunction configure_sdltrs() {\n    local common_args\n    mkRomDir \"trs-80\"\n\n    common_args=\"-fullscreen -nomousepointer -showled\"\n    addEmulator 1 \"$md_id-model1\" \"trs-80\" \"$md_inst/sdl2trs $common_args -m1 -romfile $biosdir/level2.rom -disk0 %ROM%\"\n    addEmulator 0 \"$md_id-model3\" \"trs-80\" \"$md_inst/sdl2trs $common_args -m3 -romfile3 $biosdir/level3.rom -disk0 %ROM%\"\n    addEmulator 0 \"$md_id-model4\" \"trs-80\" \"$md_inst/sdl2trs $common_args -m4 -romfile3 $biosdir/level4.rom -disk0 %ROM%\"\n    addEmulator 0 \"$md_id-model4p\" \"trs-80\" \"$md_inst/sdl2trs $common_args -m4p -romfile4p $biosdir/level4p.rom -disk0 %ROM%\"\n    addSystem \"trs-80\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # Migrate settings from the previous version\n    if [[ -h \"$home/sdltrs.t8c\" || -f \"$home/sdltrs.t8c\" ]]; then\n       mv \"$(readlink -f \"$home/sdltrs.t8c\")\" \"$home/.sdltrs.t8c\"\n    fi\n\n    local config\n    config=\"$(mktemp)\"\n    iniConfig \"=\" \"\" \"$config\"\n    iniSet \"statedir\"   \"$romdir/trs-80\"\n    iniSet \"diskdir\"    \"$romdir/trs-80\"\n    iniSet \"cassdir\"    \"$romdir/trs-80\"\n    iniSet \"disksetdir\" \"$romdir/trs-80\"\n    iniSet \"harddir\"    \"$romdir/trs-80\"\n    copyDefaultConfig \"$config\" \"$md_conf_root/trs-80/sdltrs.t8c\"\n\n    moveConfigFile \"$home/.sdltrs.t8c\" \"$md_conf_root/trs-80/sdltrs.t8c\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/simcoupe.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"simcoupe\"\nrp_module_desc=\"SimCoupe SAM Coupe emulator\"\nrp_module_help=\"ROM Extensions: .dsk .mgt .sbt .sad\\n\\nCopy your SAM Coupe games to $romdir/samcoupe.\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/simonowen/simcoupe/master/License.txt\"\nrp_module_repo=\"git https://github.com/simonowen/simcoupe.git :_get_branch_simcoupe\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _get_branch_simcoupe() {\n    local branch=\"main\"\n    # latest simcoupe requires cmake 3.14 - on Stretch older versions throw a cmake error about CXX17\n    # dialect support but actually seem to build ok. Lock systems with older cmake to 20200711 tag,\n    # which builds ok on Raspbian Stretch, and systems with cmake 3.12 to 20210501, which builds ok on Ubuntu 18.04.\n\n    # Test using \"apt-cache madison\" as this code could be called when cmake isn't yet installed but correct version\n    # is available - eg via update check with builder module which removes dependencies after building.\n    # Multiple versions may be available, so grab the versions via cut, sort by version, take the latest from the top\n    # and pipe to xargs to strip whitespace\n    local cmake_ver=$(apt-cache madison cmake | cut -d\\| -f2 | sort --version-sort | head -1 | xargs)\n    if compareVersions \"$cmake_ver\" lt 3.8.2; then\n        branch=\"20200711\"\n    elif compareVersions \"$cmake_ver\" lt 3.14; then\n        branch=\"20210501\"\n    fi\n    echo \"$branch\"\n}\n\nfunction depends_simcoupe() {\n    getDepends cmake libsdl2-dev zlib1g-dev libbz2-dev libspectrum-dev\n}\n\nfunction sources_simcoupe() {\n    gitPullOrClone\n}\n\nfunction build_simcoupe() {\n    cmake -DCMAKE_INSTALL_PREFIX=\"$md_inst\" .\n    # force the downloaded 'SAAsound' dependency to be statically linked\n    sed -i 's/ SHARED//' _deps/saasound-src/CMakeLists.txt\n    make clean\n    make\n    md_ret_require=\"$md_build/simcoupe\"\n}\n\nfunction install_simcoupe() {\n    make install\n}\n\nfunction configure_simcoupe() {\n    mkRomDir \"samcoupe\"\n    moveConfigDir \"$home/.simcoupe\" \"$md_conf_root/$md_id\"\n\n    addEmulator 1 \"$md_id\" \"samcoupe\" \"pushd $md_inst; $md_inst/bin/simcoupe autoboot -disk1 %ROM% -fullscreen; popd\"\n    addSystem \"samcoupe\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/snes9x.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"snes9x\"\nrp_module_desc=\"SNES emulator SNES9X-RPi\"\nrp_module_help=\"ROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/RetroPie/snes9x-rpi/master/snes9x.h\"\nrp_module_repo=\"git https://github.com/RetroPie/snes9x-rpi.git retropie\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !all videocore\"\n\nfunction depends_snes9x() {\n    getDepends libsdl1.2-dev libboost-thread-dev libboost-system-dev libsdl-ttf2.0-dev libasound2-dev\n}\n\nfunction sources_snes9x() {\n    gitPullOrClone\n}\n\nfunction build_snes9x() {\n    make clean\n    make\n    md_ret_require=\"$md_build/snes9x\"\n}\n\nfunction install_snes9x() {\n    md_ret_files=(\n        'changes.txt'\n        'hardware.txt'\n        'problems.txt'\n        'readme.txt'\n        'README.md'\n        'snes9x'\n    )\n}\n\nfunction configure_snes9x() {\n    mkRomDir \"snes\"\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    addEmulator 0 \"$md_id\" \"snes\" \"$md_inst/snes9x %ROM%\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/stella.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"stella\"\nrp_module_desc=\"Atari2600 emulator STELLA\"\nrp_module_help=\"ROM Extensions: .a26 .bin .rom .zip .gz\\n\\nCopy your Atari 2600 roms to $romdir/atari2600\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/stella-emu/stella/master/License.txt\"\nrp_module_repo=\"git https://github.com/stella-emu/stella.git :_get_version_stella\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _get_version_stella() {\n    if [[ \"$__gcc_version\" -lt 11 ]]; then\n        echo \"6.7\"\n    else\n        # latest version needs C++-20 support\n        echo \"7.0\"\n    fi\n}\n\nfunction depends_stella() {\n    getDepends libsdl2-dev libpng-dev zlib1g-dev\n}\n\nfunction sources_stella() {\n    gitPullOrClone\n}\n\nfunction build_stella() {\n    ./configure --prefix=\"$md_inst\"\n    make clean\n    make\n    md_ret_require=\"$md_build/stella\"\n}\n\nfunction install_stella() {\n    make install\n}\n\nfunction configure_stella() {\n    mkRomDir \"atari2600\"\n\n    moveConfigDir \"$home/.config/stella\" \"$md_conf_root/atari2600/stella\"\n\n    addEmulator 1 \"$md_id\" \"atari2600\" \"$md_inst/bin/stella -maxres 320x240 -fullscreen 1 -tia.fsfill 1 %ROM%\"\n    addSystem \"atari2600\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/stratagus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"stratagus\"\nrp_module_desc=\"Stratagus - A strategy game engine to play Warcraft I or II, Starcraft, and some similar open-source games\"\nrp_module_help=\"Copy your Stratagus games to $romdir/stratagus\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/Wargus/stratagus/master/COPYING\"\nrp_module_repo=\"git https://github.com/Wargus/stratagus.git v2.4.3\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali !kms\"\n\nfunction depends_stratagus() {\n    getDepends cmake libsdl1.2-dev libbz2-dev libogg-dev libvorbis-dev libtheora-dev libpng-dev liblua5.1-0-dev libtolua++5.1-dev libfluidsynth-dev libmikmod-dev\n}\n\nfunction sources_stratagus() {\n    gitPullOrClone\n}\n\nfunction build_stratagus() {\n    mkdir build\n    cd build\n    cmake -DENABLE_STRIP=ON ..\n    make\n    md_ret_require=\"$md_build/build/stratagus\"\n}\n\nfunction install_stratagus() {\n    md_ret_files=(\n        'build/stratagus'\n        'COPYING'\n    )\n}\n\nfunction configure_stratagus() {\n    mkRomDir \"stratagus\"\n\n    addEmulator 0 \"$md_id\" \"stratagus\" \"$md_inst/stratagus -F -d %ROM%\"\n    addSystem \"stratagus\" \"Stratagus Strategy Engine\" \".wc1 .wc2 .sc .data\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/supermodel3.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"supermodel3\"\nrp_module_desc=\"Super Model 3 Emulator\"\nrp_module_help=\"Copy your Sega Model 3 roms to $romdir/arcade\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/DirtBagXon/model3emu-code-sinden/main/Docs/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/DirtBagXon/model3emu-code-sinden.git :_get_branch_supermodel3\"\nrp_module_section=\"exp\"\nrp_module_flags=\"all !armv6 !armv7\"\n\nfunction _get_branch_supermodel3() {\n    if isPlatform \"x86\"; then\n        echo \"main\"\n    else\n        echo \"arm\"\n    fi\n}\n\nfunction depends_supermodel3() {\n    local depends=(libsdl2-dev libsdl2-net-dev libxi-dev libglu1-mesa-dev)\n    # on KMS we need x11 to start the emulator\n    isPlatform \"kms\" && depends+=(xorg matchbox-window-manager)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_supermodel3() {\n    gitPullOrClone\n}\n\nfunction build_supermodel3() {\n    make -f Makefiles/Makefile.UNIX clean\n    make -f Makefiles/Makefile.UNIX NET_BOARD=1 VERBOSE=1 ARCH=\"\" OPT=\"$__default_cflags\"\n    md_ret_require=\"bin/supermodel\"\n}\n\nfunction install_supermodel3() {\n    md_ret_files=(\n        'bin/supermodel'\n        'Config'\n        'Docs/LICENSE.txt'\n        'Docs/README.txt'\n    )\n    isPlatform \"x86\" && md_ret_files+=(\"Assets\")\n}\n\nfunction configure_supermodel3() {\n\n    mkRomDir \"arcade\"\n    addSystem \"arcade\"\n\n    local game_args=\"-vsync\"\n    local launch_prefix=\"\"\n    # launch the emulator with an X11 backend, has better scaling and mouse/lightgun support\n    isPlatform \"kms\" && launch_prefix=\"XINIT:\"\n\n    addEmulator 0 \"$md_id\" \"arcade\" \"${launch_prefix}$md_inst/supermodel.sh %ROM% $game_args\"\n    addEmulator 0 \"$md_id-scaled\" \"arcade\" \"${launch_prefix}$md_inst/supermodel.sh %ROM% $game_args -res=%XRES%,%YRES%\"\n    if isPlatform \"x86\"; then\n        # add a legacy3d entry for less powerful PC systems\n        addEmulator 0 \"$md_id-legacy3d\" \"arcade\" \"$md_inst/supermodel.sh %ROM% -legacy3d $game_args\"\n    fi\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local conf_dir=\"$md_conf_root/arcade/supermodel3\"\n    mkUserDir \"$conf_dir\"\n    mkUserDir \"$conf_dir/NVRAM\"\n    mkUserDir \"$conf_dir/Saves\"\n    mkUserDir \"$conf_dir/Config\"\n    isPlatform \"x86\" && mkUserDir \"$conf_dir/Assets\"\n\n    # on upgrades keep the local config, but overwrite the game configs\n    ! isPlatform \"x86\" && copyDefaultConfig \"$md_inst/Config/Supermodel.ini\" \"$conf_dir/Config/Supermodel.ini\"\n    cp -f \"$md_inst/Config/Games.xml\" \"$conf_dir/Config/\"\n    isPlatform \"x86\" && cp -fr \"$md_inst/Assets\" \"$conf_dir\"\n    chown -R \"$__user\":\"$__group\" \"$conf_dir\"\n\n    cat >\"$md_inst/supermodel.sh\" <<_EOF_\n#!/usr/bin/env bash\n\ncommands=\"\\${1%.*}.commands\"\n\nif [[ -f \"\\$commands\" ]]; then\n    params=\\$(<\"\\$commands\" tr -d '\\r' | tr '\\n' ' ')\nfi\n\npushd $conf_dir\n$md_inst/supermodel \"\\$@\" \\$params\npopd\n_EOF_\n    chmod +x \"$md_inst/supermodel.sh\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/ti99sim/missing_cstring.diff",
    "content": "--- a/src/core/device-support.cpp\n+++ b/src/core/device-support.cpp\n@@ -26,6 +26,7 @@\n //\n //----------------------------------------------------------------------------\n \n+#include <cstring>\n #include <regex>\n #include \"idevice.hpp\"\n #include \"icomputer.hpp\"\n"
  },
  {
    "path": "scriptmodules/emulators/ti99sim-sdl1/missing_cstdio.diff",
    "content": "--- a/include/common.hpp\n+++ b/include/common.hpp\n@@ -30,6 +30,7 @@\n #define COMMON_HPP_\n \n #include <cstdlib>\t// For definition of size_t\n+#include <cstdio>\n \n //----------------------------------------------------------------------------\n // Determine platform & OS\n"
  },
  {
    "path": "scriptmodules/emulators/ti99sim-sdl1.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ti99sim-sdl1\"\nrp_module_desc=\"TI-99/SIM - Texas Instruments Home Computer Emulator (SDL1 version)\"\nrp_module_help=\"ROM Extension: .ctg\\n\\nCopy your TI-99 games to $romdir/ti99\\n\\nCopy the required BIOS file TI-994A.ctg (case sensitive) to $biosdir\"\nrp_module_licence=\"GPL2 http://www.mrousseau.org/programs/ti99sim/\"\nrp_module_repo=\"file $__archive_url/ti99sim-0.15.0.src.tar.gz\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction depends_ti99sim-sdl1() {\n    getDepends libsdl1.2-dev libssl-dev libboost-regex-dev\n}\n\nfunction sources_ti99sim-sdl1() {\n    downloadAndExtract \"$md_repo_url\" \"$md_build\" --strip-components 1\n    # add missing include to fix compilation on newer g++\n    applyPatch \"$md_data/missing_cstdio.diff\"\n}\n\nfunction build_ti99sim-sdl1() {\n    build_ti99sim\n}\n\nfunction install_ti99sim-sdl1() {\n    install_ti99sim\n}\n\nfunction configure_ti99sim-sdl1() {\n    mkRomDir \"ti99\"\n\n    addEmulator 0 \"$md_id\" \"ti99\" \"$md_inst/ti99sim.sh -f %ROM%\"\n    addSystem \"ti99\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    moveConfigDir \"$home/.ti99sim\" \"$md_conf_root/ti99/\"\n    ln -sf \"$biosdir/TI-994A.ctg\" \"$md_inst/TI-994A.ctg\"\n\n    local file=\"$md_inst/ti99sim.sh\"\n    cat >\"$file\" << _EOF_\n#!/bin/bash\npushd \"$md_inst\"\n./ti99sim-sdl \"\\$@\"\npopd\n_EOF_\n    chmod +x \"$file\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/ti99sim.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ti99sim\"\nrp_module_desc=\"TI-99/SIM - Texas Instruments Home Computer Emulator\"\nrp_module_help=\"ROM Extension: .ctg\\n\\nCopy your TI-99 games to $romdir/ti99\\n\\nCopy the required BIOS file TI-994A.ctg (case sensitive) to $biosdir\"\nrp_module_licence=\"GPL2 https://www.mrousseau.org/programs/ti99sim\"\nrp_module_repo=\"file $__archive_url/ti99sim-0.16.0.src.tar.gz\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!:\\$__gcc_version:-lt:8\"\n\nfunction depends_ti99sim() {\n    getDepends libsdl2-dev libssl-dev\n}\n\nfunction sources_ti99sim() {\n    downloadAndExtract \"$md_repo_url\" \"$md_build\" --strip-components 1\n    # add missing include to fix compilation on newer g++\n    applyPatch \"$md_data/missing_cstring.diff\"\n}\n\nfunction build_ti99sim() {\n    make clean\n    make\n}\n\nfunction install_ti99sim() {\n    md_ret_files=(\n        'bin/ti99sim-sdl'\n        'bin/convert-ctg'\n        'bin/catalog'\n        'bin/disk'\n        'bin/dumpgrom'\n        'bin/mkcart'\n        'bin/ti99sim-console'\n        'doc/COPYING'\n        'doc/main.css'\n        'doc/README.html'\n    )\n}\n\nfunction configure_ti99sim() {\n    mkRomDir \"ti99\"\n\n    addEmulator 1 \"$md_id\" \"ti99\" \"$md_inst/ti99sim.sh -f %ROM%\"\n    addSystem \"ti99\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    moveConfigDir \"$home/.ti99sim\" \"$md_conf_root/ti99/\"\n    ln -sf \"$biosdir/TI-994A.ctg\" \"$md_inst/TI-994A.ctg\"\n\n    local file=\"$md_inst/ti99sim.sh\"\n    cat >\"$file\" << _EOF_\n#!/bin/bash\npushd \"$md_inst\"\n./ti99sim-sdl \"\\$@\"\npopd\n_EOF_\n    chmod +x \"$file\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/uae4all/01_guichan.diff",
    "content": "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@@ -598,7 +598,8 @@ namespace gcn\n     {\n         if (mFocusHandler == NULL)\n         {\n-            throw GCN_EXCEPTION(\"No focushandler set (did you add the widget to the gui?).\");\n+            return false;\n+            //throw GCN_EXCEPTION(\"No focushandler set (isModalFocused: did you add the widget to the gui?).\");\n         }\n \n         if (getParent() != NULL)\n@@ -614,7 +615,8 @@ namespace gcn\n     {\n         if (mFocusHandler == NULL)\n         {\n-            throw GCN_EXCEPTION(\"No focushandler set (did you add the widget to the gui?).\");\n+            return false;\n+            //throw GCN_EXCEPTION(\"No focushandler set (isModalMouseInputFocused: did you add the widget to the gui?).\");\n         }\n \n         if (getParent() != NULL)\ndiff --git a/src/widgets/tabbedarea.cpp b/src/widgets/tabbedarea.cpp\nindex e07d14c..5ed9d39 100644\n--- a/src/widgets/tabbedarea.cpp\n+++ b/src/widgets/tabbedarea.cpp\n@@ -317,6 +317,10 @@ namespace gcn\n \n     void TabbedArea::logic()\n     {\n+        for (unsigned int i = 0; i < mTabs.size(); i++)\n+        {\n+                  mTabs[i].second->logic();\n+        }\n     }\n \n     void TabbedArea::adjustSize()\n"
  },
  {
    "path": "scriptmodules/emulators/uae4all.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"uae4all\"\nrp_module_desc=\"Amiga emulator UAE4All\"\nrp_module_help=\"ROM Extension: .adf\\n\\nCopy your Amiga games to $romdir/amiga\\n\\nCopy the required BIOS files\\nkick13.rom\\nkick20.rom\\nkick31.rom\\nto $biosdir/amiga\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/uae4all2/retropie/copying\"\nrp_module_repo=\"git https://github.com/RetroPie/uae4all2.git retropie\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !all videocore\"\n\nfunction depends_uae4all() {\n    getDepends libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev libsdl-gfx1.2-dev libsdl-ttf2.0-dev\n}\n\nfunction sources_uae4all() {\n    gitPullOrClone\n    mkdir guichan\n    downloadAndExtract \"$__archive_url/guichan-0.8.2.tar.gz\" \"$md_build/guichan\" --strip-components 1\n    cd guichan\n    # fix from https://github.com/sphaero/guichan\n    applyPatch \"$md_data/01_guichan.diff\"\n}\n\nfunction build_uae4all() {\n    pushd guichan\n    make clean\n    ./configure --enable-sdlimage --enable-sdl --disable-allegro --disable-opengl --disable-shared\n    make\n    popd\n    make -f Makefile.pi clean\n    if isPlatform \"neon\"; then\n        make -f Makefile.pi NEON=1 DEFS=\"-DUSE_ARMV7 -DUSE_ARMNEON\"\n    else\n        make -f Makefile.pi\n    fi\n    md_ret_require=\"$md_build/uae4all\"\n}\n\nfunction install_uae4all() {\n    unzip -o \"AndroidData/guichan26032014.zip\" -d \"$md_inst\" \"data/*\"\n    unzip -o \"AndroidData/data.zip\" -d \"$md_inst\" \"data/*\"\n    md_ret_files=(\n        'copying'\n        'uae4all'\n        'Readme.txt'\n        'AndroidData/aros20140110.zip'\n    )\n    rm -rf \"$md_inst/\"{blankdisks,roms,conf,customconf,saves}\n}\n\nfunction configure_uae4all() {\n    mkRomDir \"amiga\"\n\n    mkUserDir \"$md_conf_root/amiga\"\n    mkUserDir \"$md_conf_root/amiga/$md_id\"\n\n    # move config / save folders to $md_conf_root/amiga/$md_id\n    local dir\n    for dir in blankdisks conf customconf saves screenshots; do\n        moveConfigDir \"$md_inst/$dir\" \"$md_conf_root/amiga/$md_id/$dir\"\n    done\n\n    # symlink rom dir\n    moveConfigDir \"$md_inst/roms\" \"$romdir/amiga\"\n\n    # and kickstart dir (removing old symlinks first)\n    if [[ ! -h \"$md_inst/kickstarts\" ]]; then\n        rm -f \"$md_inst/kickstarts/\"{kick12.rom,kick13.rom,kick20.rom,kick31.rom}\n    fi\n    moveConfigDir \"$md_inst/kickstarts\" \"$biosdir/amiga\"\n\n    rm -f \"$romdir/amiga/+Start UAE4All.sh\"\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        if [[ ! -f \"$biosdir/aros-amiga-m68k-ext.bin\" ]]; then\n            # unpack aros kickstart\n            unzip -j \"aros20140110.zip\" -d \"$biosdir/amiga\"\n        fi\n\n        cat > \"$romdir/amiga/+Start UAE4All.sh\" << _EOF_\n#!/bin/bash\npushd \"$md_inst\"\n./uae4all\npopd\n_EOF_\n        chmod a+x \"$romdir/amiga/+Start UAE4All.sh\"\n        chown \"$__user\":\"$__group\" \"$romdir/amiga/+Start UAE4All.sh\"\n\n        isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n    else\n        rm -f \"$biosdir/aros-amiga-m68k\"*\n    fi\n\n    addEmulator 1 \"$md_id\" \"amiga\" \"bash $romdir/amiga/+Start\\ UAE4All.sh\"\n    addSystem \"amiga\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/uae4arm/uae4arm.sh",
    "content": "#!/bin/bash\nis_amiberry=0\n\nemulator=\"./uae4arm\"\n[[ \"$is_amiberry\" -eq 1 ]] && emulator=\"./amiberry\"\n\npushd \"${0%/*}\" >/dev/null\nsource \"../../lib/archivefuncs.sh\"\n\nparams=()\n\narg=\"$1\"\n\nif [[ \"$arg\" == *.uae ]]; then\n    config=\"$arg\"\nelse\n    rom=\"$arg\"\nfi\nshift\n\nimages=()\n\nif [[ \"$is_amiberry\" -eq 1 ]] && [[ \"$rom\" == *.lha || \"$rom\" == *.cue || \"$rom\" == *.chd ]]; then\n    params+=(--autoload \"$rom\")\nelif [[ -n \"$rom\" ]]; then\n    # check successful extraction and if we have at least one file\n    if archiveExtract \"$rom\" \".adf .adz .dms .ipf\"; then\n        for i in {0..3}; do\n            [[ -n \"${arch_files[$i]}\" ]] && images+=(-$i \"${arch_files[$i]}\")\n        done\n        name=\"${arch_files[0]}\"\n    elif [[ -n \"$rom\" ]]; then\n        name=\"$rom\"\n        # try and find the disk series\n        base=\"${name##*/}\"\n        base=\"${base%Disk*}\"\n        i=0\n        while read -r disk; do\n            images+=(-$i \"$disk\")\n            ((i++))\n            [[ \"$i\" -eq 4 ]] && break\n        done < <(find \"${rom%/*}\" -iname \"$base*\" | sort)\n        [[ \"${#images[@]}\" -eq 0 ]] && images=(-0 \"$rom\")\n    fi\n\n    rom_path=\"${rom%/*}\"\n    rom_name=\"${rom##*/}\"\n    rom_bn=\"${rom_name%.*}\"\n\n    # check for .uae files with the same base name as the adf/zip in the rom directory and conf\n    if [[ -f \"$rom_path/$rom_bn.uae\" ]]; then\n        config=\"$rom_path/$rom_bn.uae\"\n    elif [[ -f \"conf/$rom_bn.uae\" ]]; then\n        config=\"conf/$rom_bn.uae\"\n    # if no config / model parameters are included in the arguments choose a config/model automatically\n    elif [[ \"$*\" != *-config* && \"$*\" != *--model* ]]; then\n        # if amiberry choose a model for amiberry based on the rom filename\n        if [[ \"$is_amiberry\" -eq 1 ]]; then\n            model=\"A500\"\n            case \"$name\" in\n                *ECS*)\n                    model=\"A500P\"\n                    ;;\n                *AGA*)\n                    model=\"A1200\"\n                    ;;\n                *CD32*)\n                    model=\"CD32\"\n                    ;;\n                *CDTV*)\n                    model=\"CDTV\"\n                    ;;\n            esac\n            params+=(--model \"$model\")\n        else\n            # or for uae4arm choose an Amiga config based on the rom filename\n            if [[ \"$name\" =~ AGA|CD32 ]]; then\n                config=\"conf/rp-a1200.uae\"\n            else\n                config=\"conf/rp-a500.uae\"\n            fi\n        fi\n    fi\nfi\n\n# if there is a config set then use it\nif [[ -n \"$config\" ]]; then\n    if [[ \"$is_amiberry\" -eq 1 ]]; then\n        params+=(--config \"$config\")\n    else\n        params+=(-config=\"$config\")\n    fi\nfi\n\n# add any other provided arguments\nparams+=(\"$@\")\n\n# add images to parameters (needs to be after any config arguments)\nparams+=(\"${images[@]}\")\n\n# start directly into emulation if the first argument is set\n[[ -n \"$arg\" ]] && params+=(-G)\n\necho \"Launching ...\"\necho \"$emulator\" \"${params[@]}\"\n\n\"$emulator\" \"${params[@]}\"\narchiveCleanup\n\npopd\n"
  },
  {
    "path": "scriptmodules/emulators/uae4arm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"uae4arm\"\nrp_module_desc=\"Amiga emulator with JIT support\"\nrp_module_help=\"ROM Extension: .adf .ipf\\n\\nCopy your Amiga games to $romdir/amiga\\n\\nCopy the required BIOS files\\nkick13.rom\\nkick20.rom\\nkick31.rom\\nto $biosdir/amiga\"\nrp_module_licence=\"GPL2\"\nrp_module_repo=\"git https://github.com/Chips-fr/uae4arm-rpi.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all dispmanx\"\n\nfunction depends_uae4arm() {\n    getDepends libsdl1.2-dev libsdl-gfx1.2-dev libsdl-ttf2.0-dev libguichan-dev libmpg123-dev libxml2-dev libflac-dev libmpeg2-4-dev\n}\n\nfunction sources_uae4arm() {\n    gitPullOrClone\n}\n\nfunction build_uae4arm() {\n    make clean\n    if isPlatform \"rpi1\"; then\n        CXXFLAGS=\"\" make PLATFORM=rpi1\n    else\n        CXXFLAGS=\"\" make PLATFORM=rpi2\n    fi\n    md_ret_require=\"$md_build/uae4arm\"\n}\n\nfunction install_uae4arm() {\n    md_ret_files=(\n        'data'\n        'uae4arm'\n    )\n}\n\nfunction configure_uae4arm() {\n    addEmulator 1 \"uae4arm\" \"amiga\" \"$md_inst/uae4arm.sh %ROM%\"\n    addEmulator 0 \"uae4arm-a500\" \"amiga\" \"$md_inst/uae4arm.sh %ROM% -config=conf/rp-a500.uae\"\n    addEmulator 0 \"uae4arm-a1200\" \"amiga\" \"$md_inst/uae4arm.sh %ROM% -config=conf/rp-a1200.uae\"\n    addSystem \"amiga\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkRomDir \"amiga\"\n\n    mkUserDir \"$md_conf_root/amiga\"\n    mkUserDir \"$md_conf_root/amiga/uae4arm\"\n\n    # move config / save folders to $md_conf_root/amiga/uae4arm\n    local dir\n    for dir in conf savestates screenshots; do\n        moveConfigDir \"$md_inst/$dir\" \"$md_conf_root/amiga/uae4arm/$dir\"\n    done\n\n    moveConfigDir \"$md_inst/kickstarts\" \"$biosdir/amiga\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/amiga\"\n\n    local conf=\"$(mktemp)\"\n    iniConfig \"=\" \"\" \"$conf\"\n    iniSet \"config_description\" \"RetroPie A500, 68000, OCS, 512KB Chip + 512KB Slow Fast\"\n    iniSet \"chipmem_size\" \"1\"\n    iniSet \"bogomem_size\" \"2\"\n    iniSet \"chipset\" \"ocs\"\n    iniSet \"cachesize\" \"0\"\n    iniSet \"kickstart_rom_file\" \"\\$(FILE_PATH)/kick13.rom\"\n    copyDefaultConfig \"$conf\" \"$md_conf_root/amiga/uae4arm/conf/rp-a500.uae\"\n    rm \"$conf\"\n\n    conf=\"$(mktemp)\"\n    iniConfig \"=\" \"\" \"$conf\"\n    iniSet \"config_description\" \"RetroPie A1200, 68EC020, AGA, 2MB Chip\"\n    iniSet \"chipmem_size\" \"4\"\n    iniSet \"finegrain_cpu_speed\" \"1024\"\n    iniSet \"cpu_type\" \"68ec020\"\n    iniSet \"cpu_model\" \"68020\"\n    iniSet \"chipset\" \"aga\"\n    iniSet \"cachesize\" \"0\"\n    iniSet \"kickstart_rom_file\" \"\\$(FILE_PATH)/kick31.rom\"\n    copyDefaultConfig \"$conf\" \"$md_conf_root/amiga/uae4arm/conf/rp-a1200.uae\"\n    rm \"$conf\"\n\n    # copy shared uae4arm/amiberry launch script\n    cp \"$md_data/uae4arm.sh\" \"$md_inst/\"\n    chmod a+x \"$md_inst/uae4arm.sh\"\n\n    local script=\"+Start UAE4Arm.sh\"\n    cat > \"$romdir/amiga/$script\" << _EOF_\n#!/bin/bash\n\"$md_inst/uae4arm.sh\"\n_EOF_\n    chmod a+x \"$romdir/amiga/$script\"\n    chown \"$__user\":\"$__group\" \"$romdir/amiga/$script\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/vice.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"vice\"\nrp_module_desc=\"C64 emulator VICE\"\nrp_module_help=\"ROM Extensions: .crt .d64 .g64 .prg .t64 .tap .x64 .zip .vsf\\n\\nCopy your Commodore 64 games to $romdir/c64\"\nrp_module_licence=\"GPL2 http://svn.code.sf.net/p/vice-emu/code/trunk/vice/COPYING\"\nrp_module_repo=\"svn svn://svn.code.sf.net/p/vice-emu/code/tags/v3.7.1/vice - HEAD\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_vice() {\n    local depends=(libsdl2-dev libsdl2-image-dev libmpg123-dev libpng-dev zlib1g-dev libasound2-dev libvorbis-dev libflac-dev libpcap-dev automake bison flex libjpeg-dev portaudio19-dev xa65 dos2unix)\n    isPlatform \"x11\" && depends+=(libpulse-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_vice() {\n    svn checkout \"$md_repo_url\" \"$md_build\"\n}\n\nfunction build_vice() {\n    local params=(--enable-sdl2ui --without-oss --enable-ethernet --enable-x64 --disable-pdf-docs --with-fastsid)\n    ! isPlatform \"x11\" && params+=(--disable-catweasel --without-pulse)\n    ./autogen.sh\n    ./configure --prefix=\"$md_inst\" \"${params[@]}\"\n    make\n    md_ret_require=\"$md_build/src/x64\"\n}\n\nfunction install_vice() {\n    make install\n}\n\nfunction configure_vice() {\n    # get a list of supported extensions\n    local exts=\"$(getPlatformConfig c64_exts)\"\n\n    # install the vice start script\n    mkdir -p \"$md_inst/bin\"\n    cat > \"$md_inst/bin/vice.sh\" << _EOF_\n#!/bin/bash\n\nBIN=\"\\${0%/*}/\\$1\"\nROM=\"\\$2\"\nPARAMS=(\"\\${@:3}\")\n\nromdir=\"\\${ROM%/*}\"\next=\"\\${ROM##*.}\"\nsource \"$rootdir/lib/archivefuncs.sh\"\n\narchiveExtract \"\\$ROM\" \"$exts\"\n\n# check successful extraction and if we have at least one file\nif [[ \\$? == 0 ]]; then\n    ROM=\"\\${arch_files[0]}\"\n    romdir=\"\\$arch_dir\"\nfi\n\n\"\\$BIN\" -chdir \"\\$romdir\" \"\\${PARAMS[@]}\" \"\\$ROM\"\narchiveCleanup\n_EOF_\n\n    chmod +x \"$md_inst/bin/vice.sh\"\n\n    mkRomDir \"c64\"\n\n    addEmulator 1 \"$md_id-x64\" \"c64\" \"$md_inst/bin/vice.sh x64 %ROM%\"\n    addEmulator 0 \"$md_id-x64dtv\" \"c64\" \"$md_inst/bin/vice.sh x64dtv %ROM%\"\n    addEmulator 0 \"$md_id-x64sc\" \"c64\" \"$md_inst/bin/vice.sh x64sc %ROM%\"\n    addEmulator 0 \"$md_id-x128\" \"c64\" \"$md_inst/bin/vice.sh x128 %ROM%\"\n    addEmulator 0 \"$md_id-xpet\" \"c64\" \"$md_inst/bin/vice.sh xpet %ROM%\"\n    addEmulator 0 \"$md_id-xplus4\" \"c64\" \"$md_inst/bin/vice.sh xplus4 %ROM%\"\n    addEmulator 0 \"$md_id-xvic\" \"c64\" \"$md_inst/bin/vice.sh xvic %ROM%\"\n    addEmulator 0 \"$md_id-xvic-cart\" \"c64\" \"$md_inst/bin/vice.sh xvic %ROM% -cartgeneric\"\n    addSystem \"c64\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # copy configs and symlink the old and new config folders to $md_conf_root/c64/\n    moveConfigDir \"$home/.vice\" \"$md_conf_root/c64\"\n    moveConfigDir \"$home/.config/vice\" \"$md_conf_root/c64\"\n\n    local config=\"$(mktemp)\"\n    echo \"[C64]\" > \"$config\"\n    iniConfig \"=\" \"\" \"$config\"\n    if ! isPlatform \"x11\"; then\n        iniSet \"Mouse\" \"1\"\n        iniSet \"VICIIDoubleSize\" \"0\"\n        iniSet \"VICIIDoubleScan\" \"0\"\n        iniSet \"VICIIFilter\" \"0\"\n        iniSet \"VICIIVideoCache\" \"0\"\n        iniSet \"SDLWindowWidth\" \"384\"\n        iniSet \"SDLWindowHeight\" \"272\"\n    fi\n\n    if isPlatform \"arm\"; then\n        iniSet \"SidEngine\" \"0\"\n        isPlatform \"armv6\" && iniSet \"SoundSampleRate\" \"22050\"\n    fi\n\n    if isPlatform \"x11\" || isPlatform \"kms\"; then\n        iniSet \"VICIIFullscreen\" \"1\"\n    fi\n\n    copyDefaultConfig \"$config\" \"$md_conf_root/c64/sdl-vicerc\"\n    rm \"$config\"\n\n    if ! isPlatform \"x11\"; then\n        # enforce a few settings to ensure a smooth upgrade from sdl1\n        iniConfig \"=\" \"\" \"$md_conf_root/c64/sdl-vicerc\"\n        iniDel \"SDLBitdepth\"\n        iniSet \"VICIIDoubleSize\" \"0\"\n        iniSet \"VICIIDoubleScan\" \"0\"\n        iniSet \"SDLWindowWidth\" \"384\"\n        iniSet \"SDLWindowHeight\" \"272\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/emulators/xm7/01_fix_build.diff",
    "content": "diff --git a/linux-sdl/CMakeLists.txt b/linux-sdl/CMakeLists.txt\nindex e6988ff..00582e5 100644\n--- a/linux-sdl/CMakeLists.txt\n+++ b/linux-sdl/CMakeLists.txt\n@@ -41,7 +41,7 @@ else(WITH_AGAR_STATIC)\n   link_directories(${WITH_LIBAGAR_PREFIX}/lib)\n endif()\n \n-set(AGAR_DEPLIBS m jpeg png z dl uim-scm uim Xinerama)\n+set(AGAR_DEPLIBS m jpeg png z dl uim-scm uim Xinerama X11)\n \n \n find_package(Gettext)\ndiff --git a/linux-sdl/fmgen/psg.cpp b/linux-sdl/fmgen/psg.cpp\nindex f590cc9..cee80a5 100644\n--- a/linux-sdl/fmgen/psg.cpp\n+++ b/linux-sdl/fmgen/psg.cpp\n@@ -150,7 +150,7 @@ void PSG::MakeEnvelopTable()\n \t\t2,2, 2,0, 2,1, 2,3, 1,1, 1,3, 1,2, 1,0,\n \t};\n \tstatic uint8 table2[4] = {  0,  0, 31, 31 };\n-\tstatic uint8 table3[4] = {  0,  1, -1,  0 };\n+\tstatic uint8 table3[4] = {  0,  1, (uint8)-1,  0 };\n \n \tif (!enveloptable[0][0])\n \t{\ndiff --git a/linux-sdl/resource/CMakeLists.txt b/linux-sdl/resource/CMakeLists.txt\nindex deb1dfb..17053ee 100644\n--- a/linux-sdl/resource/CMakeLists.txt\n+++ b/linux-sdl/resource/CMakeLists.txt\n@@ -47,7 +47,7 @@ if(ImageMagick_convert_FOUND)\n      add_custom_target(${loop_var_target} ALL \n                      DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${loop_var_src}\n \t\t     COMMAND  ${ImageMagick_convert_EXECUTABLE}\n-\t\t     ${CMAKE_CURRENT_SOURCE_DIR}/${loop_var_src}\n+\t\t     ${CMAKE_CURRENT_SOURCE_DIR}/${loop_var_src}[0]\n \t\t     ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${loop_var_target}\n \t\t     )\n      install(FILES ${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/${loop_var_target} DESTINATION share/xm7)\n"
  },
  {
    "path": "scriptmodules/emulators/xm7.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xm7\"\nrp_module_desc=\"Fujitsu FM-7 series emulator\"\nrp_module_help=\"ROM Extensions: .d77 .t77 .d88 .2d \\n\\nCopy your FM-7 games to to $romdir/xm7\\n\\nCopy bios files DICROM.ROM, EXTSUB.ROM, FBASIC30.ROM, INITIATE.ROM, KANJI1.ROM, KANJI2.ROM, SUBSYS_A.ROM, SUBSYS_B.ROM, SUBSYSCG.ROM, SUBSYS_C.ROM, fddseek.wav, relayoff.wav and relay_on.wav to $biosdir/xm7\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/nakatamaho/XM7-for-SDL/master/Doc/mess/license.txt\"\nrp_module_repo=\"git https://github.com/nakatamaho/XM7-for-SDL.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!mali !kms\"\n\nfunction depends_xm7() {\n    getDepends cmake libjpeg-dev libsdl1.2-dev libsdl-mixer1.2-dev libtool libpng-dev libuim-dev libfreetype6-dev libfontconfig1-dev gawk fonts-takao libxinerama-dev libx11-dev imagemagick\n}\n\nfunction sources_xm7() {\n    gitPullOrClone\n    mkdir -p \"$md_build/agar\"\n    downloadAndExtract \"http://stable.hypertriton.com/agar/agar-1.5.0.tar.gz\" \"$md_build/agar\" --strip-components 1\n    # _BSD_SOURCE is deprecated and will throw an error during configure\n    sed -i \"s/_BSD_SOURCE/_DEFAULT_SOURCE/g\" \"$md_build/agar/configure\"\n    # needs libx11 to link\n    applyPatch \"$md_data/01_fix_build.diff\"\n}\n\nfunction build_xm7() {\n    cd agar\n\n    # create fake freetype-config to use pkg-config due to freetype-config being removed in recent versions\n    mkdir -p bin\n    cat > bin/freetype-config << _EOF_\n#!/bin/bash\narg=\"\\$1\"\n[[ \"\\$arg\" == \"--version\" ]] && arg=\"--modversion\"\npkg-config freetype2 \\$arg\n_EOF_\n    chmod +x \"bin/freetype-config\"\n\n    ./configure --disable-shared --prefix=\"$md_build/libagar\" --enable-freetype=\"$md_build/agar\"\n    make -j1 depend all install\n\n    cd \"$md_build\"\n    mkdir linux-sdl/build\n    cd linux-sdl/build\n    cmake -DCMAKE_CXX_FLAGS=\"-DSHAREDIR='\\\"${md_inst}/share/xm7\\\"'\" -DCMAKE_INSTALL_PREFIX:PATH=\"$md_inst\" -DCMAKE_BUILD_TYPE=Release -DUSE_OPENCL=No -DUSE_OPENGL=No -DWITH_LIBAGAR_PREFIX=\"$md_build/libagar\" -DWITH_AGAR_STATIC=yes ..\n    make\n    md_ret_require=\"$md_build/linux-sdl/build/sdl/xm7\"\n}\n\nfunction install_xm7() {\n    cd linux-sdl/build\n    make install\n}\n\nfunction configure_xm7() {\n    mkRomDir \"fm7\"\n\n    addEmulator 1 \"$md_id\" \"fm7\" \"$md_inst/bin/xm7 %ROM%\"\n    addSystem \"fm7\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    moveConfigDir \"$home/.xm7\" \"$md_conf_root/fm7\"\n\n    mkUserDir \"$biosdir/fm7\"\n\n    local bios\n    for bios in DICROM.ROM EXTSUB.ROM FBASIC30.ROM INITIATE.ROM KANJI1.ROM KANJI2.ROM SUBSYS_A.ROM SUBSYS_B.ROM SUBSYSCG.ROM SUBSYS_C.ROM fddseek.wav relayoff.wav relay_on.wav; do\n        ln -sf \"$biosdir/fm7/$bios\" \"$md_conf_root/fm7/$bios\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/emulators/xroar.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xroar\"\nrp_module_desc=\"Dragon / CoCo emulator XRoar\"\nrp_module_help=\"ROM Extensions: .bin .cas .wav .bas .asc .dmk .jvc .os9 .dsk .vdk .rom .ccc .sna\\n\\nCopy your Dragon roms to $romdir/dragon32\\n\\nCopy your CoCo games to $romdir/coco\\n\\nCopy the required BIOS files d32.rom (Dragon 32), bas13.rom (CoCo), coco3.rom/coco3p.rom (CoCo3) to $biosdir\"\nrp_module_licence=\"GPL3 http://www.6809.org.uk/xroar/\"\nrp_module_repo=\"git http://www.6809.org.uk/git/xroar.git 1.10\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_xroar() {\n    local depends=(libsdl2-dev automake libasound2-dev libsndfile1-dev texinfo zlib1g-dev)\n    isPlatform \"x11\" && depends+=(libpulse-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_xroar() {\n    gitPullOrClone \"$md_build\" \"$md_repo_url\" \"$md_repo_branch\" \"\" 0\n\n}\n\nfunction build_xroar() {\n    local params=(--without-gtk2 --without-gtkgl --without-oss)\n    if ! isPlatform \"x11\"; then\n        params+=(--without-pulse --without-x)\n    fi\n    ./autogen.sh\n    ./configure --prefix=\"$md_inst\" \"${params[@]}\"\n    make clean\n    make\n    md_ret_require=\"$md_build/src/xroar\"\n}\n\nfunction install_xroar() {\n    make install\n}\n\nfunction configure_xroar() {\n    mkRomDir \"dragon32\"\n    mkRomDir \"coco\"\n\n    mkdir -p \"$md_inst/share/xroar\"\n    ln -snf \"$biosdir\" \"$md_inst/share/xroar/roms\"\n\n    local params=()\n    ! isPlatform \"x11\" && params+=(-vo sdl -ccr simple)\n    ! isPlatform \"videocore\" && params+=(-fs)\n    isPlatform \"kms\" && params+=(-vo-vsync)\n    addEmulator 1 \"$md_id-dragon32\" \"dragon32\" \"$md_inst/bin/xroar ${params[*]} -machine dragon32 -run %ROM%\"\n    addEmulator 1 \"$md_id-cocous\" \"coco\" \"$md_inst/bin/xroar ${params[*]} -machine cocous -run %ROM%\"\n    addEmulator 0 \"$md_id-coco\" \"coco\" \"$md_inst/bin/xroar ${params[*]} -machine coco -run %ROM%\"\n    addEmulator 0 \"$md_id-coco3us\" \"coco\" \"$md_inst/bin/xroar ${params[*]} -machine coco3 -run %ROM%\"\n    addEmulator 0 \"$md_id-coco3\" \"coco\" \"$md_inst/bin/xroar ${params[*]} -machine coco3p -run %ROM%\"\n\n    addSystem \"dragon32\"\n    addSystem \"coco\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/yabasanshiro.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"yabasanshiro\"\nrp_module_desc=\"SEGA Saturn emulator Yaba Sanshiro\"\nrp_module_help=\"ROM Extensions: .cue .chd\\n\\nCopy your SEGA Saturn ios images to $romdir/saturn\"\nrp_module_licence=\"GPL2 https://github.com/devmiyax/yabause/blob/master/LICENSE\"\nrp_module_repo=\"git https://github.com/devmiyax/yabause.git pi4-1-9-0\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all rpi !videocore\"\n\nfunction depends_yabasanshiro() {\n    local depends=(cmake pkg-config protobuf-compiler libprotobuf-dev libsecret-1-dev libssl-dev libsdl2-dev libboost-all-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_yabasanshiro() {\n    gitPullOrClone\n}\n\nfunction build_yabasanshiro() {\n    local params=(-DGIT_EXECUTABLE=/usr/bin/git -DUSE_EGL=ON -DYAB_PORTS=retro_arena -DYAB_WANT_DYNAREC_DEVMIYAX=ON -DYAB_WANT_ARM7=ON -DYAB_WANT_OPENAL=OFF -DCMAKE_INSTALL_PREFIX=\"$md_inst\")\n    isPlatform \"32bit\" && params+=(-DCMAKE_SYSTEM_PROCESSOR=armv7-a)\n    isPlatform \"64bit\" && params+=(-DCMAKE_SYSTEM_PROCESSOR=aarch64)\n\n    export CFLAGS=\"$CFLAGS -D_POSIX_C_SOURCE=199309L -D__PI4__ -D__RETORO_ARENA__\"\n    export CXXFLAGS=\"$CXXFLAGS -D__PI4__ -D__RETORO_ARENA_\"\n\n    rm -fr build && mkdir -p build\n    cd build\n    cmake ../yabause/ \"${params[@]}\"\n    make\n    md_ret_require=\"$md_build/build/src/retro_arena/yabasanshiro\"\n}\n\nfunction install_yabasanshiro() {\n    cd build\n    make install\n}\n\n\nfunction configure_yabasanshiro() {\n    mkRomDir \"saturn\"\n    if [[ \"$md_mode\" == \"install\" ]]; then\n       mkUserDir \"$md_conf_root/saturn\"\n       mkUserDir \"$md_conf_root/saturn/$md_id\"\n       moveConfigFile \"$home/.$md_id\" \"$md_conf_root/saturn/$md_id\"\n    fi\n    addEmulator 1 \"$md_id\" \"saturn\" \"$md_inst/yabasanshiro -r 3 -i %ROM%\"\n    addSystem \"saturn\"\n}\n"
  },
  {
    "path": "scriptmodules/emulators/zesarux.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/petrockblog/RetroPie-Setup/master/LICENSE.md.\n#\n\nrp_module_id=\"zesarux\"\nrp_module_desc=\"ZX Spectrum emulator ZEsarUX\"\nrp_module_help=\"ROM Extensions: .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip\\n\\nCopy your ZX Spectrum games to $romdir/zxspectrum\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/chernandezba/zesarux/master/src/LICENSE\"\nrp_module_repo=\"git https://github.com/chernandezba/zesarux.git ZEsarUX-12.1\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2 sdl1-videocore\"\n\nfunction depends_zesarux() {\n    local depends=(libssl-dev libpthread-stubs0-dev libasound2-dev)\n    isPlatform \"x11\" && depends+=(libpulse-dev)\n\n    if isPlatform \"videocore\"; then\n        depends+=(libsdl1.2-dev)\n    else\n        depends+=(libsdl2-dev)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_zesarux() {\n    gitPullOrClone\n}\n\nfunction build_zesarux() {\n    local params=()\n    isPlatform \"videocore\" && params+=(--enable-raspberry)\n    ! isPlatform \"x11\" && params+=(--disable-pulse)\n    ! isPlatform \"videocore\" && params+=(--enable-sdl2)\n\n    cd src\n    ./configure --prefix \"$md_inst\" \"${params[@]}\" --enable-ssl\n    make clean\n    make\n    md_ret_require=\"$md_build/src/zesarux\"\n}\n\nfunction install_zesarux() {\n    cd src\n    make install\n}\n\n\nfunction configure_zesarux() {\n    mkRomDir \"zxspectrum\"\n    mkRomDir \"amstradcpc\"\n    mkRomDir \"samcoupe\"\n\n    mkUserDir \"$md_conf_root/zxspectrum\"\n\n    cat > \"$romdir/zxspectrum/+Start ZEsarUX.sh\" << _EOF_\n#!/bin/bash\n\"$md_inst/bin/zesarux\" \"\\$@\"\n_EOF_\n    chmod +x \"$romdir/zxspectrum/+Start ZEsarUX.sh\"\n    chown \"$__user\":\"$__group\" \"$romdir/zxspectrum/+Start ZEsarUX.sh\"\n\n    moveConfigFile \"$home/.zesaruxrc\" \"$md_conf_root/zxspectrum/.zesaruxrc\"\n\n    local ao=\"sdl\"\n    isPlatform \"x11\" && ao=\"pulse\"\n    local config=\"$(mktemp)\"\n\n    cat > \"$config\" << _EOF_\n;ZEsarUX sample configuration file\n;\n;Lines beginning with ; or # are ignored\n\n;Run zesarux with --help or --experthelp to see all the options\n--disableborder\n--disablefooter\n--vo sdl\n--ao $ao\n--hidemousepointer\n--fullscreen\n\n--smartloadpath $romdir/zxspectrum\n\n--joystickemulated Kempston\n\n;Remap Fire Event. Uncomment and amend if you wish to change the default button 3.\n;--joystickevent 3 Fire\n;Remap On-screen keyboard. Uncomment and amend if you wish to change the default button 5.\n;--joystickevent 5 Osdkeyboard\n_EOF_\n\n    copyDefaultConfig \"$config\" \"$md_conf_root/zxspectrum/.zesaruxrc\"\n    rm \"$config\"\n\n    isPlatform \"videocore\" && setBackend \"$md_id\" \"dispmanx\"\n\n    addEmulator 1 \"$md_id\" \"zxspectrum\" \"bash $romdir/zxspectrum/+Start\\ ZEsarUX.sh %ROM%\"\n    addEmulator 1 \"$md_id\" \"samcoupe\" \"bash $romdir/zxspectrum/+Start\\ ZEsarUX.sh --machine sam %ROM%\"\n    addEmulator 1 \"$md_id\" \"amstradcpc\" \"bash $romdir/zxspectrum/+Start\\ ZEsarUX.sh --machine CPC464 %ROM%\"\n    addSystem \"zxspectrum\"\n    addSystem \"samcoupe\"\n    addSystem \"amstradcpc\"\n}\n"
  },
  {
    "path": "scriptmodules/helpers.sh",
    "content": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## @file helpers.sh\n## @brief RetroPie helpers library\n## @copyright GPLv3\n\n## @fn printMsgs()\n## @param type style of display to use - dialog, console or heading\n## @param message string or array of messages to display\n## @brief Prints messages in a variety of ways.\nfunction printMsgs() {\n    local type=\"$1\"\n    shift\n    if [[ \"$__nodialog\" == \"1\" && \"$type\" == \"dialog\" ]]; then\n        type=\"console\"\n    fi\n    for msg in \"$@\"; do\n        [[ \"$type\" == \"dialog\" ]] && dialog --backtitle \"$__backtitle\" --cr-wrap --no-collapse --msgbox \"$msg\" 20 60 >/dev/tty\n        [[ \"$type\" == \"console\" ]] && echo -e \"$msg\"\n        [[ \"$type\" == \"heading\" ]] && echo -e \"\\n= = = = = = = = = = = = = = = = = = = = =\\n$msg\\n= = = = = = = = = = = = = = = = = = = = =\\n\"\n    done\n    return 0\n}\n\n## @fn printHeading()\n## @param message string or array of messages to display\n## @brief Calls PrintMsgs with \"heading\" type.\nfunction printHeading() {\n    printMsgs \"heading\" \"$@\"\n}\n\n## @fn fatalError()\n## @param message string or array of messages to display\n## @brief Calls PrintMsgs with \"heading\" type, and exits immediately.\nfunction fatalError() {\n    printHeading \"Error\"\n    echo -e \"$1\"\n    joy2keyStop\n    exit 1\n}\n\n# @fn fnExists()\n# @param name name of function to check for\n# @brief Checks if function name exists.\n# @retval 0 if the function name exists\n# @retval 1 if the function name does not exist\nfunction fnExists() {\n    declare -f \"$1\" > /dev/null\n    return $?\n}\n\nfunction ask() {\n    echo -e -n \"$@\" '[y/n] ' ; read ans\n    case \"$ans\" in\n        y*|Y*) return 0 ;;\n        *) return 1 ;;\n    esac\n}\n\n## @fn runCmd()\n## @param command command to run\n## @brief Calls command and record any non zero return codes for later printing.\n## @return whatever the command returns.\nfunction runCmd() {\n    local ret\n    \"$@\"\n    ret=$?\n    if [[ \"$ret\" -ne 0 ]]; then\n        md_ret_errors+=(\"Error running '$*' - returned $ret\")\n    fi\n    return $ret\n}\n\n## @fn hasFlag()\n## @param string string to search in\n## @param flag flag to search for\n## @brief Checks for a flag in a string (consisting of space separated flags).\n## @retval 0 if the flag was found\n## @retval 1 if the flag was not found\nfunction hasFlag() {\n    local string=\"$1\"\n    local flag=\"$2\"\n    [[ -z \"$string\" || -z \"$flag\" ]] && return 1\n\n    if [[ \"$string\" =~ (^| )$flag($| ) ]]; then\n        return 0\n    else\n        return 1\n    fi\n}\n\n## @fn isPlatform()\n## @param platform\n## @brief Test for current platform / platform flags.\nfunction isPlatform() {\n    local flag=\"$1\"\n    if hasFlag \"${__platform_flags[*]}\" \"$flag\"; then\n        return 0\n    fi\n    return 1\n}\n\n## @fn addLineToFile()\n## @param line line to add\n## @param file file to add line to\n## @brief Adds a new line of text to a file.\nfunction addLineToFile() {\n    if [[ -f \"$2\" ]]; then\n        cp -p \"$2\" \"$2.bak\"\n    else\n        sed -i --follow-symlinks '$a\\' \"$2\"\n    fi\n\n    echo \"$1\" >> \"$2\"\n}\n\n## @fn editFile()\n## @param file file to edit\n## @brief Opens an editing dialog for specified file.\nfunction editFile() {\n    local file=\"$1\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --editbox \"$file\" 22 76)\n    local choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n    [[ -n \"$choice\" ]] && echo \"$choice\" >\"$file\"\n}\n\n## @fn inputBox()\n## @param title title of dialog\n## @param text default text\n## @param minchars minimum chars to accept\n## @brief Opens an inputbox dialog and echoes resulting text. Uses the OSK if installed.\n## @details The input dialog has OK/Cancel buttons and can be cancelled by the user.\n## The dialog will enforce the minimum number of characters expected, re-prompting the user.\n## @retval 0 when the user entered the text and chose the OK button\n## @retval != 0 when the user chose the Cancel button\n\nfunction inputBox() {\n    local title=\"$1\"\n    local text=\"$2\"\n    local minchars=\"$3\"\n    [[ -z \"$minchars\" ]] && minchars=0\n    local params=(--backtitle \"$__backtitle\" --inputbox \"Enter the $title\")\n    local osk=\"$(rp_getInstallPath joy2key)/osk.py\"\n\n    if [[ -f \"$osk\" ]]; then\n        params+=(--minchars \"$minchars\")\n        text=$(python3 \"$osk\" \"${params[@]}\" \"$text\" 2>&1 >/dev/tty) || return $?\n    else\n        while true; do\n            text=$(dialog \"${params[@]}\" 10 60 \"$text\" 2>&1 >/dev/tty) || return $?\n            [[ \"${#text}\" -ge \"$minchars\" ]] && break\n            dialog --msgbox \"$title must have at least $minchars characters\" 8 60 2>&1 >/dev/tty\n        done\n    fi\n\n    echo \"$text\"\n}\n\n## @fn hasPackage()\n## @param package name of Debian package\n## @param version requested version (optional)\n## @param comparison type of comparison - defaults to `ge` (greater than or equal) if a version parameter is provided.\n## @brief Test for an installed Debian package / package version.\n## @retval 0 if the requested package / version was installed\n## @retval 1 if the requested package / version was not installed\nfunction hasPackage() {\n    local pkg=\"$1\"\n    local req_ver=\"$2\"\n    local comp=\"$3\"\n    [[ -z \"$comp\" ]] && comp=\"ge\"\n\n    local ver\n    local status\n    # extract the first line only (for cases where both amd64 & i386 versions of a package are installed)\n    local out=$(dpkg-query -W --showformat='${Status} ${Version}\\n' $1 2>/dev/null | head -n1)\n    if [[ \"$?\" -eq 0 ]]; then\n        ver=\"${out##* }\"\n        status=\"${out% *}\"\n    fi\n\n    local installed=0\n    [[ \"$status\" == *\"ok installed\" ]] && installed=1\n    # if we are not checking version\n    if [[ -z \"$req_ver\" ]]; then\n        # if the package is installed return true\n        [[ \"$installed\" -eq 1 ]] && return 0\n    else\n        # if checking version and the package is not installed we need to clear \"ver\" as it may contain\n        # the version number of a removed package and give a false positive with compareVersions.\n        # we still need to do the version check even if not installed due to the varied boolean operators\n        [[ \"$installed\" -eq 0 ]] && ver=\"\"\n\n        compareVersions \"$ver\" \"$comp\" \"$req_ver\" && return 0\n    fi\n    return 1\n}\n\n## @fn aptUpdate()\n## @brief Calls apt-get update (if it has not been called before).\nfunction aptUpdate() {\n    if [[ \"$__apt_update\" != \"1\" ]]; then\n        apt-get update --allow-releaseinfo-change\n        __apt_update=\"1\"\n    fi\n}\n\n## @fn aptInstall()\n## @param packages package / space separated list of packages to install\n## @brief Calls apt-get install with the packages provided.\nfunction aptInstall() {\n    aptUpdate\n    apt-get install -y \"$@\"\n    return $?\n}\n\n## @fn aptRemove()\n## @param packages package / space separated list of packages to install\n## @brief Calls apt-get remove with the packages provided.\nfunction aptRemove() {\n    aptUpdate\n    apt-get remove -y \"$@\"\n    return $?\n}\n\nfunction _mapPackage() {\n    local pkg=\"$1\"\n    case \"$pkg\" in\n        libraspberrypi-bin)\n            isPlatform \"osmc\" && pkg=\"rbp-userland-osmc\"\n            isPlatform \"xbian\" && pkg=\"xbian-package-firmware\"\n            ;;\n        libraspberrypi-dev)\n            isPlatform \"osmc\" && pkg=\"rbp-userland-dev-osmc\"\n            isPlatform \"xbian\" && pkg=\"xbian-package-firmware\"\n            ;;\n        mali-fbdev)\n            isPlatform \"vero4k\" && pkg=\"\"\n            ;;\n        # handle our custom package alias LINUX-HEADERS\n        LINUX-HEADERS)\n            if isPlatform \"rpi\"; then\n                if [[ \"$__os_debian_ver\" -lt 12 ]]; then\n                    pkg=\"raspberrypi-kernel-headers\"\n                else\n                    # on RaspiOS bookworm and later, kernel packages are separated by arch and model\n                    isPlatform \"rpi0\" || isPlatform \"rpi1\" && pkg=\"linux-headers-rpi-v6\"\n                    if isPlatform \"32bit\"; then\n                        isPlatform \"rpi2\" || isPlatform \"rpi3\" && pkg=\"linux-headers-rpi-v7\"\n                        isPlatform \"rpi4\" && pkg=\"linux-headers-rpi-v7l\"\n                    else\n                        isPlatform \"rpi3\" || isPlatform \"rpi4\" && pkg=\"linux-headers-rpi-v8\"\n                        isPlatform \"rpi5\" && pkg=\"linux-headers-rpi-2712\"\n                    fi\n                fi\n            elif isPlatform \"armbian\"; then\n                local branch=\"$(grep -oP \"BRANCH=\\K.*\"      /etc/armbian-release)\"\n                local family=\"$(grep -oP \"LINUXFAMILY=\\K.*\" /etc/armbian-release)\"\n                pkg=\"linux-headers-${branch}-${family}\"\n            elif [[ -z \"$__os_ubuntu_ver\" ]]; then\n                pkg=\"linux-headers-$(uname -r)\"\n            else\n                pkg=\"linux-headers-generic\"\n            fi\n            ;;\n        # map libpng-dev to libpng12-dev for Jessie\n        libpng-dev)\n            [[ \"$__os_debian_ver\" -lt 9 ]] && pkg=\"libpng12-dev\"\n            ;;\n        libsdl1.2-dev)\n            rp_isEnabled \"sdl1\" && pkg=\"RP sdl1 $pkg\"\n            ;;\n        libsdl2-dev)\n            if rp_isEnabled \"sdl2\"; then\n                # check whether to use our own sdl2 - can be disabled to resolve issues with\n                # mixing custom 64bit sdl2 and os distributed i386 version on multiarch\n                local own_sdl2=1\n                # default to off for x11 targets due to issues with dependencies with recent\n                # Ubuntu (19.04). eg libavdevice58 requiring exactly 2.0.9 sdl2.\n                isPlatform \"x11\" && own_sdl2=0\n                iniConfig \" = \" '\"' \"$configdir/all/retropie.cfg\"\n                iniGet \"own_sdl2\"\n                if [[ \"$ini_value\" == \"1\" ]]; then\n                    own_sdl2=1\n                elif [[ \"$ini_value\" == \"0\" ]]; then\n                    own_sdl2=0\n                fi\n                [[ \"$own_sdl2\" -eq 1 ]] && pkg=\"RP sdl2 $pkg\"\n            fi\n            ;;\n        libfreetype6-dev)\n            [[ \"$__os_debian_ver\" -gt 10 ]] || compareVersions \"$__os_ubuntu_ver\" gt 23.04 && pkg=\"libfreetype-dev\"\n            ;;\n        polkitd)\n            [[ \"$__os_debian_ver\" -lt 13 ]] && pkg=\"policykit-1\"\n            [[ -n \"$__os_ubuntu_ver\" ]] && compareVersions \"$__os_ubuntu_ver\" lt 24.04 && pkg=\"policykit-1\"\n            ;;\n    esac\n    echo \"$pkg\"\n}\n\n## @fn getDepends()\n## @param packages package / space separated list of packages to install\n## @brief Installs packages if they are not installed.\n## @retval 0 on success\n## @retval 1 on failure\nfunction getDepends() {\n    local own_pkgs=()\n    local apt_pkgs=()\n    local all_pkgs=()\n    local pkg\n    for pkg in \"$@\"; do\n        pkg=($(_mapPackage \"$pkg\"))\n        # manage our custom packages (pkg = \"RP module_id pkg_name\")\n        if [[ \"${pkg[0]}\" == \"RP\" ]]; then\n            # if removing, check if any version is installed and queue for removal via the custom module\n            if [[ \"$md_mode\" == \"remove\" ]]; then\n                if hasPackage \"${pkg[2]}\"; then\n                    own_pkgs+=(\"${pkg[1]}\")\n                    all_pkgs+=(\"${pkg[2]}(custom)\")\n                fi\n            else\n                # if installing check if our version is installed and queue for installing via the custom module\n                if hasPackage \"${pkg[2]}\" $(get_pkg_ver_${pkg[1]}) \"ne\"; then\n                    own_pkgs+=(\"${pkg[1]}\")\n                    all_pkgs+=(\"${pkg[2]}(custom)\")\n                fi\n            fi\n            continue\n        fi\n\n        if [[ \"$md_mode\" == \"remove\" ]]; then\n            # add package to apt_pkgs for removal if installed\n            if hasPackage \"$pkg\"; then\n                apt_pkgs+=(\"$pkg\")\n                all_pkgs+=(\"$pkg\")\n            fi\n        else\n            # add package to apt_pkgs for installation if not installed\n            if ! hasPackage \"$pkg\"; then\n                apt_pkgs+=(\"$pkg\")\n                all_pkgs+=(\"$pkg\")\n            fi\n        fi\n\n    done\n\n\n    # return if no packages required\n    [[ ${#apt_pkgs[@]} -eq 0 && ${#own_pkgs[@]} -eq 0 ]] && return\n\n    # if we are removing, then remove packages, do an autoremove to clean up additional packages and return\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        printMsgs \"console\" \"Removing dependencies: ${all_pkgs[*]}\"\n        for pkg in ${own_pkgs[@]}; do\n            rp_callModule \"$pkg\" remove\n        done\n        apt-get remove --purge -y \"${apt_pkgs[@]}\"\n        apt-get autoremove --purge -y\n        return 0\n    fi\n\n    printMsgs \"console\" \"Did not find needed dependencies: ${all_pkgs[*]}. Trying to install them now.\"\n\n    # install any custom packages\n    for pkg in ${own_pkgs[@]}; do\n       rp_callModule \"$pkg\" _auto_\n    done\n\n    aptInstall --no-install-recommends \"${apt_pkgs[@]}\"\n\n    local failed=()\n    # check the required packages again rather than return code of apt-get,\n    # as apt-get might fail for other reasons (eg other half installed packages)\n    for pkg in ${apt_pkgs[@]}; do\n        if ! hasPackage \"$pkg\"; then\n            # workaround for installing samba in a chroot (fails due to failed smbd service restart)\n            # we replace the init.d script with an empty script so the install completes\n            if [[ \"$pkg\" == \"samba\" && \"$__chroot\" -eq 1 ]]; then\n                mv /etc/init.d/smbd /etc/init.d/smbd.old\n                echo \"#!/bin/sh\" >/etc/init.d/smbd\n                chmod u+x /etc/init.d/smbd\n                apt-get -f install\n                mv /etc/init.d/smbd.old /etc/init.d/smbd\n            else\n                failed+=(\"$pkg\")\n            fi\n        fi\n    done\n\n    if [[ ${#failed[@]} -gt 0 ]]; then\n        md_ret_errors+=(\"Could not install package(s): ${failed[*]}.\")\n        return 1\n    fi\n\n    return 0\n}\n\n\n## @fn rpSwap()\n## @param command *on* to add swap if needed and *off* to remove later\n## @param memory total memory needed (swap added = memory needed - available memory)\n## @brief Adds additional swap to the system if needed.\nfunction rpSwap() {\n    local command=$1\n    local swapfile=\"$__swapdir/swap\"\n    case $command in\n        on)\n            rpSwap off\n            local needed=$2\n            local size=$((needed - __memory_avail))\n            mkdir -p \"$__swapdir/\"\n            if [[ $size -ge 0 ]]; then\n                echo \"Adding $size MB of additional swap\"\n                fallocate -l ${size}M \"$swapfile\"\n                chmod 600 \"$swapfile\"\n                mkswap \"$swapfile\"\n                swapon \"$swapfile\"\n            fi\n            ;;\n        off)\n            echo \"Removing additional swap\"\n            swapoff \"$swapfile\" 2>/dev/null\n            rm -f \"$swapfile\"\n            ;;\n    esac\n}\n\n## @fn gitPullOrClone()\n## @param dest destination directory\n## @param repo repository to clone or pull from\n## @param branch branch to clone or pull from (optional)\n## @param commit specific commit to checkout (optional - requires branch to be set)\n## @param depth depth parameter for git. (optional)\n## @brief Git clones or pulls a repository.\n## @details depth parameter will default to 1 (shallow clone) so long as __persistent_repos isn't set.\n## A depth parameter of 0 will do a full clone with all history.\nfunction gitPullOrClone() {\n    local dir=\"$1\"\n    [[ -z \"$dir\" ]] && dir=\"$md_build\"\n    local repo=\"$2\"\n    local branch=\"$3\"\n    local commit=\"$4\"\n    local depth=\"$5\"\n    # if repo is blank then use the rp_module_repo info\n    if [[ -z \"$repo\" && -n \"$md_repo_url\" ]]; then\n        repo=\"$(rp_resolveRepoParam \"$md_repo_url\")\"\n        branch=\"$(rp_resolveRepoParam \"$md_repo_branch\")\"\n        commit=\"$(rp_resolveRepoParam \"$md_repo_commit\")\"\n    fi\n    [[ -z \"$repo\" ]] && return 1\n    [[ -z \"$branch\" ]] && branch=\"master\"\n\n    # if no depth is provided default to shallow clone (depth 1)\n    [[ -z \"$depth\" ]] && depth=1\n    # if we are using persistent repos or checking out a specific commit, don't shallow clone\n    if [[ \"$__persistent_repos\" -eq 1 || -n \"$commit\" ]]; then\n        depth=0\n    fi\n\n    # record the source directory in __mod_info[ID/repo_dir] if not previously set which will be used\n    # by the packaging functions later to grab repository information\n    if [[ -z \"${__mod_info[$md_id/repo_dir]}\" ]]; then\n        __mod_info[$md_id/repo_dir]=\"$dir\"\n    fi\n\n    if [[ -d \"$dir/.git\" ]]; then\n        pushd \"$dir\" > /dev/null\n        # if we are using persistent repos, fetch the latest remote changes and clean the source so\n        # any patches can be re-applied as needed.\n        if [[ \"$__persistent_repos\" -eq 1 ]]; then\n            runCmd git fetch\n            runCmd git reset --hard\n            runCmd git clean -f -d\n        fi\n        runCmd git checkout \"$branch\"\n        # only try to pull if we are on a tracking branch\n        if [[ -n \"$(git config --get branch.$branch.merge)\" ]]; then\n            runCmd git pull --ff-only\n            runCmd git submodule update --init --recursive\n        fi\n        popd > /dev/null\n    else\n        local git=\"git clone --recursive\"\n        if [[ \"$depth\" -gt 0 ]]; then\n            git+=\" --depth $depth --shallow-submodules\"\n        fi\n        git+=\" --branch $branch\"\n        printMsgs \"console\" \"$git \\\"$repo\\\" \\\"$dir\\\"\"\n        runCmd $git \"$repo\" \"$dir\"\n    fi\n\n    if [[ -n \"$commit\" ]]; then\n        printMsgs \"console\" \"Winding back $repo->$branch to commit: #$commit\"\n        git -C \"$dir\" branch -D \"$commit\" &>/dev/null\n        runCmd git -C \"$dir\" checkout -f \"$commit\" -b \"$commit\"\n    fi\n\n    branch=$(runCmd git -C \"$dir\" rev-parse --abbrev-ref HEAD)\n    commit=$(runCmd git -C \"$dir\" rev-parse HEAD)\n    printMsgs \"console\" \"HEAD is now in branch '$branch' at commit '$commit'\"\n}\n\n# @fn setupDirectories()\n# @brief Makes sure some required retropie directories and files are created.\nfunction setupDirectories() {\n    mkdir -p \"$rootdir\"\n    mkUserDir \"$datadir\"\n    mkUserDir \"$romdir\"\n    mkUserDir \"$biosdir\"\n    mkUserDir \"$configdir\"\n    mkUserDir \"$configdir/all\"\n\n    # some home folders for configs that modules rely on\n    mkUserDir \"$home/.cache\"\n    mkUserDir \"$home/.config\"\n    mkUserDir \"$home/.local\"\n    mkUserDir \"$home/.local/share\"\n\n    # make sure we have inifuncs.sh in place and that it is up to date\n    mkdir -p \"$rootdir/lib\"\n    local helper\n    for helper in inifuncs.sh archivefuncs.sh; do\n        if [[ ! -f \"$rootdir/lib/$helper\" || \"$rootdir/lib/$helper\" -ot \"$scriptdir/scriptmodules/$helper\" ]]; then\n            cp --preserve=timestamps \"$scriptdir/scriptmodules/$helper\" \"$rootdir/lib/$helper\"\n        fi\n    done\n\n    # create template for autoconf.cfg and make sure it is owned by $__user\n    local config=\"$configdir/all/autoconf.cfg\"\n    if [[ ! -f \"$config\" ]]; then\n        echo \"# this file can be used to enable/disable retropie autoconfiguration features\" >\"$config\"\n    fi\n    chown \"$__user\":\"$__group\" \"$config\"\n}\n\n## @fn rmDirExists()\n## @param dir directory to remove\n## @brief Removes a directory and all contents if it exists.\nfunction rmDirExists() {\n    if [[ -d \"$1\" ]]; then\n        rm -rf \"$1\"\n    fi\n}\n\n## @fn mkUserDir()\n## @param dir directory to create\n## @brief Creates a directory owned by the current user.\nfunction mkUserDir() {\n    mkdir -p \"$1\"\n    chown \"$__user\":\"$__group\" \"$1\"\n}\n\n## @fn mkRomDir()\n## @param dir rom directory to create\n## @brief Creates a directory under $romdir owned by the current user.\nfunction mkRomDir() {\n    mkUserDir \"$romdir/$1\"\n    if [[ \"$1\" == \"megadrive\" ]]; then\n        if [[ ! -e \"$romdir/genesis\" ]]; then\n            pushd \"$romdir\"\n            ln -snf \"$1\" \"genesis\"\n            popd\n        fi\n    fi\n}\n\n## @fn moveConfigDir()\n## @param from source directory\n## @param to destination directory\n## @brief Moves the contents of a folder and symlinks to the new location.\nfunction moveConfigDir() {\n    local from=\"$1\"\n    local to=\"$2\"\n\n    # if we are in remove mode - remove the symlink\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        [[ -h \"$from\" ]] && rm -f \"$from\"\n        return\n    fi\n\n    mkUserDir \"$to\"\n    # move any old configs to the new location\n    if [[ -d \"$from\" && ! -h \"$from\" ]]; then\n        cp -a \"$from/.\" \"$to/\"\n        rm -rf \"$from\"\n    fi\n    ln -snf \"$to\" \"$from\"\n    # set ownership of the actual link to $__user\n    chown -h \"$__user\":\"$__group\" \"$from\"\n}\n\n## @fn moveConfigFile()\n## @param from source file\n## @param to destination file\n## @brief Moves the file and symlinks to the new location.\nfunction moveConfigFile() {\n    local from=\"$1\"\n    local to=\"$2\"\n\n    # if we are in remove mode - remove the symlink\n    if [[ \"$md_mode\" == \"remove\" && -h \"$from\" ]]; then\n        rm -f \"$from\"\n        return\n    fi\n\n    # move old file\n    if [[ -f \"$from\" && ! -h \"$from\" ]]; then\n        mv \"$from\" \"$to\"\n    fi\n    ln -sf \"$to\" \"$from\"\n    # set ownership of the actual link to $__user\n    chown -h \"$__user\":\"$__group\" \"$from\"\n}\n\n## @fn diffFiles()\n## @param file1 file to compare\n## @param file2 file to compare\n## @brief Compares two files using diff.\n## @retval 0 if the files were the same\n## @retval 1 if they were not\n## @retval >1 an error occurred\nfunction diffFiles() {\n    diff -q \"$1\" \"$2\" >/dev/null\n    return $?\n}\n\n## @fn compareVersions()\n## @param version first version to compare\n## @param operator operator to use (lt le eq ne ge gt)\n## @brief version second version to compare\n## @retval 0 if the comparison was true\n## @retval 1 if the comparison was false\nfunction compareVersions() {\n    dpkg --compare-versions \"$1\" \"$2\" \"$3\" >/dev/null\n    return $?\n}\n\n## @fn dirIsEmpty()\n## @param path path to directory\n## @param files_only set to 1 to ignore sub directories\n## @retval 0 if the directory is empty\n## @retval 1 if the directory is not empty\nfunction dirIsEmpty() {\n    if [[ \"$2\" -eq 1 ]]; then\n        [[ -z \"$(ls -lA1 \"$1\" | grep \"^-\")\" ]] && return 0\n    else\n        [[ -z \"$(ls -A \"$1\")\" ]] && return 0\n    fi\n    return 1\n}\n\n## @fn copyDefaultConfig()\n## @param from source file\n## @param to destination file\n## @brief Copies a default configuration.\n## @details Copies from the source file to the destination file if the destination\n## file doesn't exist. If the destination is the same nothing is done. If different\n## the source is copied to `$destination.rp-dist`.\nfunction copyDefaultConfig() {\n    local from=\"$1\"\n    local to=\"$2\"\n    # if the destination exists, and is different then copy the config as name.rp-dist\n    if [[ -f \"$to\" ]]; then\n        if ! diffFiles \"$from\" \"$to\"; then\n            to+=\".rp-dist\"\n            printMsgs \"console\" \"Copying new default configuration to $to\"\n            cp \"$from\" \"$to\"\n        fi\n    else\n        printMsgs \"console\" \"Copying default configuration to $to\"\n        cp \"$from\" \"$to\"\n    fi\n\n    chown \"$__user\":\"$__group\" \"$to\"\n}\n\n## @fn renameModule()\n## @param from source file\n## @param to destination file\n## @brief Renames an existing module.\n## @details Renames an existing module, moving it's install folder to the new location\n## and changing any references to it in `emulators.cfg`.\nfunction renameModule() {\n    local from=\"$1\"\n    local to=\"$2\"\n    # move from old location and update emulators.cfg\n    if [[ -d \"$rootdir/$md_type/$from\" ]]; then\n        rm -rf \"$rootdir/$md_type/$to\"\n        mv \"$rootdir/$md_type/$from\" \"$rootdir/$md_type/$to\"\n        # replace any default = \"$from\"\n        sed -i --follow-symlinks \"s/\\\"$from\\\"/\\\"$to\\\"/g\" \"$configdir\"/*/emulators.cfg\n        # replace any $from = \"cmdline\"\n        sed -i --follow-symlinks \"s/^$from\\([ =]\\)/$to\\1/g\" \"$configdir\"/*/emulators.cfg\n        # replace any paths with /$from/\n        sed -i --follow-symlinks \"s|/$from/|/$to/|g\" \"$configdir\"/*/emulators.cfg\n    fi\n}\n\n## @fn addUdevInputRules()\n## @brief Creates a udev rule to adjust input device permissions.\n## @details Creates a udev rule in `/etc/udev/rules.d/99-input.rules` to\n## make everything in `/dev/input` it writable by any user in group `input`.\nfunction addUdevInputRules() {\n    if [[ ! -f /etc/udev/rules.d/99-input.rules ]]; then\n        echo 'SUBSYSTEM==\"input\", GROUP=\"input\", MODE=\"0660\"' > /etc/udev/rules.d/99-input.rules\n    fi\n    # remove old 99-evdev.rules\n    rm -f /etc/udev/rules.d/99-evdev.rules\n}\n\n## @fn setBackend()\n## @param emulator.cfg key to configure backend for\n## @param backend name of the backend to set\n## @param force set to 1 to force the change\n## @brief Set a backend rendering driver for a module\n## @details Set a backend rendering driver for a module - can be currently default, dispmanx or x11.\n## This function will only set a backend if\n##   - It's not already configured, or\n##   - The 3rd parameter (force) is set to 1\n## The emulator.cfg key is usually the module_id but some modules add multiple emulator.cfg entries\n## which are all handled separately. A module can use a _backend_set_MODULE function hook which is called\n## from the backends module to handle calling setBackend for additional emulator.cfg entries.\n## See \"fuse\" scriptmodule for an example.\nfunction setBackend() {\n    local config=\"$configdir/all/backends.cfg\"\n    local id=\"$1\"\n    local mode=\"$2\"\n    local force=\"$3\"\n    iniConfig \"=\" \"\\\"\" \"$config\"\n    iniGet \"$id\"\n    if [[ \"$force\" -eq 1 || -z \"$ini_value\" ]]; then\n        iniSet \"$id\" \"$mode\"\n        chown \"$__user\":\"$__group\" \"$config\"\n    fi\n}\n\n## @fn getBackend()\n## @param emulator.cfg key to get backend for\n## @brief Get a backend rendering driver for a module\n## @details Get a backend rendering driver for a module\n## The function echos the result so the value can be captured using var=$(getBackend \"$module_id\")\nfunction getBackend() {\n    local config=\"$configdir/all/backends.cfg\"\n    local id=\"$1\"\n    iniConfig \" = \" '\"' \"$config\"\n    iniGet \"$id\"\n    if [[ -n \"$ini_value\" ]]; then\n        # translate old value of 1 as dispmanx for backward compatibility\n        [[ \"$ini_value\" == \"1\" ]] && ini_value=\"dispmanx\"\n     else\n        ini_value=\"default\"\n     fi\n     echo \"$ini_value\"\n}\n\n## @fn setDispmanx()\n## @param module_id name of module to add dispmanx flag for\n## @param status initial status of flag (0 or 1)\n## @brief Sets a dispmanx flag for a module. This function is deprecated.\n## @details Set a dispmanx flag for a module as to whether it should use the\n## sdl1 dispmanx backend by default or not (0 for framebuffer, 1 for dispmanx).\n## This function is deprecated and instead setBackend should be used.\nfunction setDispmanx() {\n    isPlatform \"dispmanx\" || return\n    setBackend \"$1\" \"dispmanx\"\n}\n\n## @fn iniFileEditor()\n## @param delim ini file delimiter eg. ' = '\n## @param quote ini file quoting character eg. '\"'\n## @param config ini file to edit\n## @brief Allows editing of ini files with a user friendly dialog based gui.\n## @details Some arrays need to be configured before calling this, which are\n## used to display what can be edited and the options available.\n##\n## The first array is `$ini_titles` which provides the titles for each\n## entry..\n##\n## The second array is `$ini_descs` which contains a help description for each\n## entry.\n##\n## The third array is `$ini_options` which contains multiple space separated\n## strings in each element to control how each entry should be managed.\n##\n## The `$ini_options` array is constructed as follows:\n##\n## If the first string is `_function_` then the next string should be a function\n## name that will handle that entry. The function will be called with a parameter\n## `get` or `set`. The function should return the value for get via `echo`\n## and should handle any gui functionality when called with `set`. This can be\n## used for example to build custom dialogs.\n##\n## If the first option is anything else, it is assumed to be a key name, followed\n## by a control type and a list of parameters.\n##\n## Control types are:\n##  * `_id_` map the following values to an id\n##  * `_string_` allow the value to be inputted by the user\n##  * `_file_` select from a list of files. The following values are wildcard,\n##    then file path.\n##\n## If none of the above, then the rest of the array element should be a list of\n## possible values for the key.\n##\n## Some examples for ini_options:\n##\n##     ini_options=('video_smooth true false')\n## Allow setting of the key `video_smooth` with the values of *true* or *false*\n##\n##     ini_options=('aspect_ratio_index _id_ 4:3 16:9 16:10)\n## Allow setting of the key `aspect_ratio_index` with the values 0 1 or 2 which\n## correspond to the ratios. The user is shown the ratios, but the ini configuration\n## is set to the id (4:3 = 0, 16:9 = 1, 16:10 = 2).\n##\n##     ini_options=('_function_ _video_fullscreen_configedit')\n## The function `_video_fullscreen_configedit` is called with *get* or *set*\n## to manage this entry.\n##\n##     ini_options=(\"video_shader _file_ *.*p $rootdir/emulators/retroarch/shader\")\n## The key `video_shader` will be able to be set to a list of files in\n## `$rootdir/emulators/retroarch/shader` that match the wildcard `*.*p`\n##\n## For more examples you can check out the code in supplementary/configedit.sh\nfunction iniFileEditor() {\n    local delim=\"$1\"\n    local quote=\"$2\"\n    local config=\"$3\"\n    [[ ! -f \"$config\" ]] && return\n\n    iniConfig \"$delim\" \"$quote\" \"$config\"\n    local sel\n    local value\n    local option\n    local title\n    while true; do\n        local options=()\n        local params=()\n        local values=()\n        local keys=()\n        local i=0\n\n        # generate menu from options\n        for option in \"${ini_options[@]}\"; do\n            # split into new array (globbing safe)\n            read -ra option <<<\"$option\"\n            key=\"${option[0]}\"\n            keys+=(\"$key\")\n            params+=(\"${option[*]:1}\")\n\n            # if the first parameter is _function_ we call the second parameter as a function\n            # so we can handle some options with a custom menu etc\n            if [[ \"$key\" == \"_function_\" ]]; then\n                value=\"$(${option[1]} get)\"\n            else\n                # get current value\n                iniGet \"$key\"\n                if [[ -n \"$ini_value\" ]]; then\n                    value=\"$ini_value\"\n                else\n                    value=\"unset\"\n                fi\n            fi\n\n            values+=(\"$value\")\n\n            # add the matching value to our id in _id_ lists\n            if [[ \"${option[1]}\" == \"_id_\" && \"$value\" != \"unset\" ]]; then\n                value+=\" - ${option[value+2]}\"\n            fi\n\n            # use custom title if provided\n            if [[ -n \"${ini_titles[i]}\" ]]; then\n                title=\"${ini_titles[i]}\"\n            else\n                title=\"$key\"\n            fi\n\n            options+=(\"$i\" \"$title ($value)\" \"${ini_descs[i]}\")\n\n            ((i++))\n        done\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$sel\" --item-help --help-button --menu \"Please choose the setting to modify in $config\" 22 76 16)\n        sel=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ \"${sel[@]:0:4}\" == \"HELP\" ]]; then\n            printMsgs \"dialog\" \"${sel[@]:5}\"\n            continue\n        fi\n\n        [[ -z \"$sel\" ]] && break\n\n        # if the key is _function_ we handle the option with a custom function\n        if [[ \"${keys[sel]}\" == \"_function_\" ]]; then\n            \"${params[sel]}\" set \"${values[sel]}\"\n            continue\n        fi\n\n        # process the editing of the option\n        i=0\n        options=(\"U\" \"unset\")\n        local default=\"\"\n\n        # split into new array (globbing safe)\n        read -ra params <<<\"${params[sel]}\"\n\n        local mode=\"${params[0]}\"\n\n        case \"$mode\" in\n            _string_)\n                options+=(\"E\" \"Edit (Currently ${values[sel]})\")\n                ;;\n            _file_)\n                local match=\"${params[1]}\"\n                local path=\"${params[*]:2}\"\n                local file\n                while read file; do\n                    [[ \"${values[sel]}\" == \"$file\" ]] && default=\"$i\"\n                    file=\"${file//$path\\//}\"\n                    options+=(\"$i\" \"$file\")\n                    ((i++))\n                done < <(find -L \"$path\" -type f -name \"$match\" | sort)\n                ;;\n            _id_|*)\n                [[ \"$mode\" == \"_id_\" ]] && params=(\"${params[@]:1}\")\n                for option in \"${params[@]}\"; do\n                    if [[ \"$mode\" == \"_id_\" ]]; then\n                        [[ \"${values[sel]}\" == \"$i\" ]] && default=\"$i\"\n                    else\n                        [[ \"${values[sel]}\" == \"$option\" ]] && default=\"$i\"\n                    fi\n                    options+=(\"$i\" \"$option\")\n                    ((i++))\n                done\n                ;;\n        esac\n        [[ -z \"$default\" ]] && default=\"U\"\n        # display values\n        cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Please choose the value for ${keys[sel]}\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n        # if it is a _string_ type we will open an inputbox dialog to get a manual value\n        if [[ -z \"$choice\" ]]; then\n            continue\n        elif [[ \"$choice\" == \"E\" ]]; then\n            [[ \"${values[sel]}\" == \"unset\" ]] && values[sel]=\"\"\n            cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the value for ${keys[sel]}\" 10 60 \"${values[sel]}\")\n            value=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n        elif [[ \"$choice\" == \"U\" ]]; then\n            value=\"\"\n        else\n            if [[ \"$mode\" == \"_id_\" ]]; then\n                value=\"$choice\"\n            else\n                # get the actual value from the options array\n                local index=$((choice*2+3))\n                if [[ \"$mode\" == \"_file_\" ]]; then\n                    value=\"$path/${options[index]}\"\n                else\n                    value=\"${options[index]}\"\n                fi\n            fi\n        fi\n\n        if [[ \"$choice\" == \"U\" ]]; then\n            iniUnset \"${keys[sel]}\" \"$value\"\n        else\n            iniSet \"${keys[sel]}\" \"$value\"\n        fi\n\n    done\n}\n\n## @fn setESSystem()\n## @param fullname full name of system\n## @param name short name of system\n## @param path rom path\n## @param extension file extensions to show\n## @param command command to run\n## @param platform name of platform (used by es for scraping)\n## @param theme name of theme to use\n## @brief Adds a system entry for Emulation Station (to /etc/emulationstation/es_systems.cfg).\nfunction setESSystem() {\n    local function\n    for function in $(compgen -A function _add_system_); do\n        \"$function\" \"$@\"\n    done\n}\n\n## @fn ensureSystemretroconfig()\n## @param system system to create retroarch.cfg for\n## @brief Deprecated - use defaultRAConfig\n## @details Creates a default retroarch.cfg for specified system in `$configdir/$system/retroarch.cfg`.\nfunction ensureSystemretroconfig() {\n    # don't do any config work on module removal\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # reset \"$md_conf_root\" to \"$configdir\" as defaultRAConfig handles this whereas ensureSystemretroconfig\n    # expects system to include any subdirectory in the first parameter such as \"ports/$system\".\n    local save_conf_root=\"$md_conf_root\"\n    md_conf_root=\"$configdir\"\n    defaultRAConfig \"$1\"\n    md_conf_root=\"$save_conf_root\"\n}\n\n## @fn defaultRAConfig()\n## @param system system to create retroarch.cfg for\n## @param ... optional key then value parameters to be used in the config\n## @brief Creates a default retroarch.cfg for specified system in `$md_root_dir/$system/retroarch.cfg`.\n## @details Additional default configuration values can be provided as parameters to the function - eg. \"fps_show\" \"true\"\n## as two parameters would add a default entry of fps_show = \"true\" to the default configuration.\n## This function uses $md_conf_root as a base, so there is no need to use \"ports/$system\" for libretro ports as with\n## the older ensureSystemretroconfig\nfunction defaultRAConfig() {\n    # don't do any config work on module removal\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local system=\"$1\"\n    shift\n    local defaults=(\"$@\")\n\n    local config_path=\"$md_conf_root/$system\"\n\n    [[ ! -d \"$config_path\" ]] && mkUserDir \"$config_path\"\n\n    local config=\"$(mktemp)\"\n    # add the initial comment regarding include order\n    echo -e \"# Settings made here will only override settings in the global retroarch.cfg if placed above the #include line\\n\" >\"$config\"\n\n    # add the per system default settings\n    iniConfig \" = \" '\"' \"$config\"\n    iniSet \"input_remapping_directory\" \"$config_path\"\n\n    # add any additional config key / values from function parameters\n    local key\n    local value\n    while read key value; do\n        [[ -n \"$key\" ]] && iniSet \"$key\" \"$value\"\n    done <<< \"${defaults[@]}\"\n\n    # include the main retroarch config\n    echo -e \"\\n#include \\\"$configdir/all/retroarch.cfg\\\"\" >>\"$config\"\n\n    copyDefaultConfig \"$config\" \"$config_path/retroarch.cfg\"\n    rm \"$config\"\n}\n\n## @fn setRetroArchCoreOption()\n## @param option option to set\n## @param value value to set\n## @brief Sets a retroarch core option in `$configdir/all/retroarch-core-options.cfg`.\nfunction setRetroArchCoreOption() {\n    local option=\"$1\"\n    local value=\"$2\"\n    iniConfig \" = \" \"\\\"\" \"$configdir/all/retroarch-core-options.cfg\"\n    iniGet \"$option\"\n    if [[ -z \"$ini_value\" ]]; then\n        iniSet \"$option\" \"$value\"\n    fi\n    chown \"$__user\":\"$__group\" \"$configdir/all/retroarch-core-options.cfg\"\n}\n\n## @fn setConfigRoot()\n## @param dir directory under $configdir to use\n## @brief Sets module config root `$md_conf_root` to subfolder from `$configdir`\n## @details This is used for ports that are not actually in scriptmodules/ports\n## as they would get the wrong config root otherwise.\nfunction setConfigRoot() {\n    local dir=\"$1\"\n    md_conf_root=\"$configdir\"\n    [[ -n \"$dir\" ]] && md_conf_root+=\"/$dir\"\n    mkUserDir \"$md_conf_root\"\n}\n\n## @fn loadModuleConfig()\n## @param params space separated list of key=value parameters\n## @brief Load the settings for a module.\n## @details This allows modules to quickly load some settings from an ini file.\n## It can provide a shortcut way to load a set of keys from an ini file into\n## variables.\n##\n## It requires iniConfig to be called first to specify the format and file.\n## eg.\n##\n##     iniConfig \" = \" '\"' \"$configdir/all/mymodule.cfg\"\n##     eval $(loadModuleConfig \\\n##        'some_option=1' \\\n##        'another_option=2'\n##\n## This would load the keys `some_option` and `another_option` into local\n## variables `some_option` and `another_option`. If the keys did not exist\n## in mymodule.cfg the variables would be initialised to 1 and 2.\nfunction loadModuleConfig() {\n    local options=(\"$@\")\n    local option\n    local key\n    local value\n\n    for option in \"${options[@]}\"; do\n        option=(${option/=/ })\n        key=\"${option[0]}\"\n        value=\"${option[@]:1}\"\n        iniGet \"$key\"\n        if [[ -z \"$ini_value\" ]]; then\n            iniSet \"$key\" \"$value\"\n            echo \"local $key=\\\"$value\\\"\"\n        else\n            echo \"local $key=\\\"$ini_value\\\"\"\n        fi\n    done\n}\n\n## @fn applyPatch()\n## @param patch filename of patch to apply\n## @brief Apply a patch if it has not already been applied to current folder.\n## @details This is used for applying patches against upstream code.\n## @retval 0 on success\n## @retval 1 on failure\nfunction applyPatch() {\n    local patch=\"$1\"\n    local patch_applied=\"${patch##*/}.applied\"\n\n    if [[ ! -f \"$patch_applied\" ]]; then\n        if patch -f -p1 <\"$patch\"; then\n            touch \"$patch_applied\"\n            printMsgs \"console\" \"Successfully applied patch: $patch\"\n        else\n            md_ret_errors+=(\"$md_id patch $patch failed to apply\")\n            return 1\n        fi\n    fi\n    return 0\n}\n\n## @fn runCurl()\n## @params ... commandline arguments to pass to curl\n## @brief Run curl with chosen parameters and handle curl errors\n## @details Runs curl with the provided parameters, whilst also capturing the output and extracting\n## any error message, which is stored in the global variable __NET_ERRMSG. Function returns the return\n## code provided by curl. The environment variable __curl_opts can be set to override default curl\n## parameters, eg - timeouts etc.\n## @retval curl return value\nfunction runCurl() {\n    local params=(\"$@\")\n    # add any user supplied curl opts - timeouts can be overridden as curl uses the last parameters given\n    [[ -n \"$__curl_opts\" ]] && params+=($__curl_opts)\n\n    local cmd_err\n    local ret\n\n    # get the last non zero exit status (ignoring tee)\n    set -o pipefail\n\n    # set up additional file descriptor for stdin\n    exec 3>&1\n\n    # capture stderr - while passing both stdout and stderr to terminal\n    # curl like wget outputs the progress meter to stderr, so we will extract the error line later\n    cmd_err=$(curl \"${params[@]}\" 2>&1 1>&3 | tee /dev/stderr)\n    ret=\"$?\"\n\n    # remove stdin copy\n    exec 3>&-\n\n    set +o pipefail\n\n    # if there was an error, extract it and put in __NET_ERRMSG\n    if [[ \"$ret\" -ne 0 ]]; then\n        # as we also capture the curl progress output, extract the last line which contains the error\n        __NET_ERRMSG=\"${cmd_err##*$'\\n'}\"\n    else\n        __NET_ERRMSG=\"\"\n    fi\n    return \"$ret\"\n}\n\n## @fn download()\n## @param url url of file\n## @param dest destination name (optional), use - for stdout\n## @brief Download a file\n## @details Download a file - if the dest parameter is omitted, the file will be downloaded to the current directory.\n## If the destination name is a hyphen (-), then the file will be outputted to stdout, for piping to another command\n## or retrieving the contents directly to a variable. If the destination is a folder, extract with the basename from\n## the url to the destination folder.\n## @retval 0 on success\nfunction download() {\n    local url=\"$1\"\n    local dest=\"$2\"\n    local file=\"${url##*/}\"\n\n    # if no destination, get the basename from the url\n    [[ -z \"$dest\" ]] && dest=\"${PWD}/$file\"\n\n    # if the destination is a folder, download to that with filename from url\n    [[ -d \"$dest\" ]] && dest=\"$dest/$file\"\n\n    local params=(--location)\n    if [[ \"$dest\" == \"-\" ]]; then\n        params+=(--silent --no-buffer)\n    else\n        printMsgs \"console\" \"Downloading $url to $dest ...\"\n        params+=(-o \"$dest\")\n    fi\n    params+=(--connect-timeout 10 --speed-limit 1 --speed-time 60 --fail)\n    # add the url\n    params+=(\"$url\")\n\n    local ret\n    runCurl \"${params[@]}\"\n    ret=\"$?\"\n\n    # if download failed, remove file, log error and return error code\n    if [[ \"$ret\" -ne 0 ]]; then\n        # remove dest if not set to stdout and exists\n        [[ \"$dest\" != \"-\" && -f \"$dest\" ]] && rm \"$dest\"\n        md_ret_errors+=(\"URL $url failed to download.\\n\\n$__NET_ERRMSG\")\n    fi\n    return \"$ret\"\n}\n\n## @fn downloadAndVerify()\n## @param url url of file\n## @param dest destination file (optional)\n## @brief Download a file and a corresponding .asc signature and verify the contents\n## @details Download a file and a corresponding .asc signature and verify the contents.\n## The .asc file will be downloaded to verify the file, but will be removed after downloading.\n## If the dest parameter is omitted, the file will be downloaded to the current directory\n## @retval 0 on success\nfunction downloadAndVerify() {\n    local url=\"$1\"\n    local dest=\"$2\"\n    local file=\"${url##*/}\"\n\n    # if no destination, get the basename from the url (supported by GNU basename)\n    [[ -z \"$dest\" ]] && dest=\"${PWD}/$file\"\n\n    local cmd_out\n    local ret=1\n    if download \"${url}.asc\" \"${dest}.asc\"; then\n        if download \"$url\" \"$dest\"; then\n            cmd_out=\"$(gpg --verify \"${dest}.asc\" 2>&1)\"\n            ret=\"$?\"\n            if [[ \"$ret\" -ne 0 ]]; then\n                md_ret_errors+=(\"$dest failed signature check:\\n\\n$cmd_out\")\n            fi\n        fi\n    fi\n    return \"$ret\"\n}\n\n## @fn downloadAndExtract()\n## @param url url of archive\n## @param dest destination folder for the archive\n## @param optional additional parameters to pass to the decompression tool.\n## @brief Download and extract an archive\n## @details Download and extract an archive.\n## @retval 0 on success\nfunction downloadAndExtract() {\n    local url=\"$1\"\n    local dest=\"$2\"\n    shift 2\n    local opts=(\"$@\")\n\n    local ext=\"${url##*.}\"\n    local file=\"${url##*/}\"\n\n    local temp=\"$(mktemp -d)\"\n    # download file, removing temporary folder and returning on error\n    if ! download \"$url\" \"$temp/$file\"; then\n        rm -rf \"$temp\"\n        return 1\n    fi\n\n    mkdir -p \"$dest\"\n\n    local ret\n    case \"$ext\" in\n        exe|zip)\n            runCmd unzip \"${opts[@]}\" -o \"$temp/$file\" -d \"$dest\"\n            ;;\n        *)\n            tar -xvf \"$temp/$file\" -C \"$dest\" \"${opts[@]}\"\n            ;;\n    esac\n    ret=$?\n\n    rm -rf \"$temp\"\n\n    return $ret\n}\n\n## @fn ensureFBMode()\n## @param res_x width of mode\n## @param res_y height of mode\n## @brief Add a framebuffer mode to /etc/fb.modes\n## @details Useful for adding specific resolutions used by emulators so SDL1 can\n## use them and utilise the RPI hardware scaling. Without for example a 320x240\n## mode in fb.modes many of the emulators that output to the framebuffer and\n## were not set to use the dispmanx SDL1 backend would just show in a small\n## area of the screen.\nfunction ensureFBMode() {\n    [[ ! -f /etc/fb.modes ]] && return\n    local res_x=\"$1\"\n    local res_y=\"$2\"\n    local res=\"${res_x}x${res_y}\"\n    sed -i --follow-symlinks \"/$res mode/,/endmode/d\" /etc/fb.modes\n\n    cat >> /etc/fb.modes <<_EOF_\n# added by RetroPie-Setup - $res mode for emulators\nmode \"$res\"\n    geometry $res_x $res_y $res_x $res_y 16\n    timings 0 0 0 0 0 0 0\nendmode\n_EOF_\n}\n\n## @fn joy2keyStart()\n## @param left mapping for left\n## @param right mapping for right\n## @param up mapping for up\n## @param down mapping for down\n## @param but1 mapping for button 1\n## @param but2 mapping for button 2\n## @param but3 mapping for button 3\n## @param butX mapping for button X ...\n## @brief Start joy2key process in background to map joystick presses to keyboard\n## @details Arguments are curses capability names or hex values starting with '0x'\n## see: http://pubs.opengroup.org/onlinepubs/7908799/xcurses/terminfo.html\nfunction joy2keyStart() {\n    # don't start on SSH sessions\n    # (check for bracket in output - ip/name in brackets over a SSH connection)\n    [[ \"$(who -m)\" == *\\(* ]] && return\n\n    local params=(\"$@\")\n\n    # if joy2key is installed, run it\n    if rp_isInstalled \"joy2key\"; then\n        \"$(rp_getInstallPath joy2key)/joy2key\" start \"${params[@]}\" 2>/dev/null && return 0\n    fi\n\n    return 1\n}\n\n## @fn joy2keyStop()\n## @brief Stop previously started joy2key process.\nfunction joy2keyStop() {\n    # if joy2key is installed, stop it\n    if rp_isInstalled \"joy2key\"; then\n        \"$(rp_getInstallPath joy2key)/joy2key\" stop\n    fi\n}\n\n## @fn getPlatformConfig()\n## @param key key to look up\n## @brief gets a config from a platforms.cfg ini\n## @details gets a config from a platforms.cfg ini first looking in\n## `$configdir/all/platforms.cfg` then `$scriptdir/platforms.cfg`\n## allowing users to override any parts of `$scriptdir/platforms.cfg`\nfunction getPlatformConfig() {\n    local key=\"$1\"\n    local conf\n    for conf in \"$configdir/all/platforms.cfg\" \"$scriptdir/platforms.cfg\"; do\n        [[ ! -f \"$conf\" ]] && continue\n        iniConfig \"=\" '\"' \"$conf\"\n        iniGet \"$key\"\n        [[ -n \"$ini_value\" ]] && break\n    done\n    # workaround for RetroPie platform\n    [[ \"$key\" == \"retropie_fullname\" ]] && ini_value=\"RetroPie\"\n    echo \"$ini_value\"\n}\n\n## @fn addSystem()\n## @param system system to add\n## @brief adds an emulator entry / system\n## @param fullname optional fullname for the frontend (if not present in platforms.cfg)\n## @param exts optional extensions for the frontend (if not present in platforms.cfg)\n## @details Adds a system to one of the frontend launchers\nfunction addSystem() {\n    local system=\"$1\"\n    local fullname=\"$2\"\n    local exts=($3)\n\n    local platform=\"$system\"\n    local theme=\"$system\"\n    local cmd\n    local path\n\n    # if removing and we don't have an emulators.cfg we can remove the system from the frontends\n    if [[ \"$md_mode\" == \"remove\" ]] && [[ ! -f \"$md_conf_root/$system/emulators.cfg\" ]]; then\n        delSystem \"$system\" \"$fullname\"\n        return\n    fi\n\n    # set system / platform / theme for configuration based on data in names field\n    if [[ \"$system\" == \"ports\" ]]; then\n        cmd=\"bash %ROM%\"\n        path=\"$romdir/ports\"\n    else\n        cmd=\"$rootdir/supplementary/runcommand/runcommand.sh 0 _SYS_ $system %ROM%\"\n        path=\"$romdir/$system\"\n    fi\n\n    exts+=(\"$(getPlatformConfig \"${system}_exts\")\")\n\n    local temp\n    temp=\"$(getPlatformConfig \"${system}_theme\")\"\n    if [[ -n \"$temp\" ]]; then\n        theme=\"$temp\"\n    else\n        theme=\"$system\"\n    fi\n\n    temp=\"$(getPlatformConfig \"${system}_platform\")\"\n    if [[ -n \"$temp\" ]]; then\n        platform=\"$temp\"\n    else\n        platform=\"$system\"\n    fi\n\n    temp=\"$(getPlatformConfig \"${system}_fullname\")\"\n    [[ -n \"$temp\" ]] && fullname=\"$temp\"\n\n    exts=\"${exts[*]}\"\n    # add the extensions again as uppercase\n    exts+=\" ${exts^^}\"\n\n    setESSystem \"$fullname\" \"$system\" \"$path\" \"$exts\" \"$cmd\" \"$platform\" \"$theme\"\n}\n\n## @fn delSystem()\n## @param system system to delete\n## @brief Deletes a system\n## @details deletes a system from all frontends.\nfunction delSystem() {\n    local system=\"$1\"\n    local fullname=\"$2\"\n\n    local temp\n    temp=\"$(getPlatformConfig \"${system}_fullname\")\"\n    [[ -n \"$temp\" ]] && fullname=\"$temp\"\n\n    local function\n    for function in $(compgen -A function _del_system_); do\n        \"$function\" \"$fullname\" \"$system\"\n    done\n}\n\n## @fn addPort()\n## @param id id of the module / command\n## @param port name of the port\n## @param name display name for the launch script\n## @param cmd commandline to launch\n## @param game rom/game parameter (optional)\n## @brief Adds a port to the emulationstation ports menu.\n## @details Adds an emulators.cfg entry as with addSystem but also creates a launch script in `$datadir/ports/$name.sh`.\n##\n## Can also optionally take a game parameter which can be used to create multiple launch\n## scripts for different games using the same engine - eg for quake\n##\n##     addPort \"lr-tyrquake\" \"quake\" \"Quake\" \"$emudir/retroarch/bin/retroarch -L $md_inst/tyrquake_libretro.so --config $md_conf_root/quake/retroarch.cfg %ROM%\" \"$romdir/ports/quake/id1/pak0.pak\"\n##     addPort \"lr-tyrquake\" \"quake\" \"Quake Mission Pack 2 (rogue)\" \"$emudir/retroarch/bin/retroarch -L $md_inst/tyrquake_libretro.so --config $md_conf_root/quake/retroarch.cfg %ROM%\" \"$romdir/ports/quake/id1/rogue/pak0.pak\"\n##\n## Would add an entry in $configdir/ports/quake/emulators.cfg for lr-tyrquake (setting it to default if no default set)\n## and create a launch script in $romdir/ports for each game.\nfunction addPort() {\n    local id=\"$1\"\n    local port=\"$2\"\n    local file=\"$romdir/ports/$3.sh\"\n    local cmd=\"$4\"\n    local game=\"$5\"\n\n    # move configurations from old ports location\n    if [[ -d \"$configdir/$port\" ]]; then\n        mv \"$configdir/$port\" \"$md_conf_root/\"\n    fi\n\n    # remove the emulator / port\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        delEmulator \"$id\" \"$port\"\n\n        # remove launch script if in remove mode and the ports emulators.cfg is empty\n        [[ ! -f \"$md_conf_root/$port/emulators.cfg\" ]] && rm -f \"$file\"\n\n        # if there are no more port launch scripts we can remove ports from emulation station\n        if [[ \"$(find \"$romdir/ports\" -maxdepth 1 -name \"*.sh\" | wc -l)\" -eq 0 ]]; then\n            delSystem \"ports\"\n        fi\n        return\n    fi\n\n    mkUserDir \"$romdir/ports\"\n\n    cat >\"$file\" << _EOF_\n#!/bin/bash\n\"$rootdir/supplementary/runcommand/runcommand.sh\" 0 _PORT_ \"$port\" \"$game\"\n_EOF_\n\n    chown \"$__user\":\"$__group\" \"$file\"\n    chmod +x \"$file\"\n\n    [[ -n \"$cmd\" ]] && addEmulator 1 \"$id\" \"$port\" \"$cmd\"\n    addSystem \"ports\"\n}\n\n## @fn addEmulator()\n## @param default 1 to make the emulator / command default for the system if no default already set\n## @param id unique id of the module / command\n## @param name name of the system to add the emulator to\n## @param cmd commandline to launch\n## @brief Adds a new emulator for a system.\n## @details This is the primary function for adding emulators to a system which can be\n## switched between via the runcommand launch menu \n##\n##     addEmulator 1 \"vice-x64\" \"c64\" \"$md_inst/bin/x64 %ROM%\"\n##     addEmulator 0 \"vice-xvic\" \"c64\" \"$md_inst/bin/xvic %ROM%\"\n##\n## Would add two optional emulators for the c64 - with vice-x64 being the default if no default\n## was already set. This adds entries to `$configdir/$system/emulators.cfg` with\n##\n##     id = \"cmd\"\n##     default = id\n##\n## Which are then selectable from runcommand when launching roms\n##\n## For libretro emulators, cmd needs to only contain the path to the libretro library.\n##\n## eg. for the lr-fcuemm module\n##\n##     addEmulator 1 \"$md_id\" \"nes\" \"$md_inst/fceumm_libretro.so\"\nfunction addEmulator() {\n    local default=\"$1\"\n    local id=\"$2\"\n    local system=\"$3\"\n    local cmd=\"$4\"\n\n    # check if we are removing the system\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        delEmulator \"$id\" \"$system\"\n        return\n    fi\n\n    # automatically add parameters for libretro modules\n    if [[ \"$id\" == lr-* && \"$cmd\" =~ ^\"$md_inst\"[^[:space:]]*\\.so ]]; then\n        cmd=\"$emudir/retroarch/bin/retroarch -L $cmd --config $md_conf_root/$system/retroarch.cfg %ROM%\"\n    fi\n\n    # create a config folder for the system / port\n    mkUserDir \"$md_conf_root/$system\"\n\n    # add the emulator to the $conf_dir/emulators.cfg if a commandline exists (not used for some ports)\n    if [[ -n \"$cmd\" ]]; then\n        iniConfig \" = \" '\"' \"$md_conf_root/$system/emulators.cfg\"\n        iniSet \"$id\" \"$cmd\"\n        # set a default unless there is one already set\n        iniGet \"default\"\n        if [[ -z \"$ini_value\" && \"$default\" -eq 1 ]]; then\n            iniSet \"default\" \"$id\"\n        fi\n        chown \"$__user\":\"$__group\" \"$md_conf_root/$system/emulators.cfg\"\n    fi\n}\n\n## @fn delEmulator()\n## @param id id of emulator to delete\n## @param system system to delete from\n## @brief Deletes an emulator entry / system\n## @details Delete the entry for the id from `$configdir/$system/emulators.cfg`.\n## If there are no more emulators for the system present, it will also\n## delete the system entry from the installed frontends.\nfunction delEmulator() {\n    local id=\"$1\"\n    local system=\"$2\"\n\n    local config=\"$md_conf_root/$system/emulators.cfg\"\n    # remove from apps list for system\n    if [[ -f \"$config\" && -n \"$id\" ]]; then\n        # delete emulator entry\n        iniConfig \" = \" '\"' \"$config\"\n        iniDel \"$id\"\n        # if it is the default - remove it - runcommand will prompt to select a new default\n        iniGet \"default\"\n        [[ \"$ini_value\" == \"$id\" ]] && iniDel \"default\"\n        # if we no longer have any entries in the emulators.cfg file we can remove it\n        grep -q \"=\" \"$config\" || rm -f \"$config\"\n    fi\n\n}\n\n## @fn patchVendorGraphics()\n## @param filename file to patch\n## @details replace declared dependencies of old vendor graphics libraries with new names\n## Temporary compatibility workaround for legacy software to work on new Raspberry Pi firmwares.\nfunction patchVendorGraphics() {\n    local filename=\"$1\"\n\n    # patchelf is not available on Raspbian Jessie\n    [[ \"$__os_debian_ver\" -lt 9 ]] && return\n\n    getDepends patchelf\n    printMsgs \"console\" \"Applying vendor graphics patch: $filename\"\n    patchelf --replace-needed libEGL.so libbrcmEGL.so \\\n             --replace-needed libGLES_CM.so libbrcmGLESv2.so \\\n             --replace-needed libGLESv1_CM.so libbrcmGLESv2.so \\\n             --replace-needed libGLESv2.so libbrcmGLESv2.so \\\n             --replace-needed libOpenVG.so libbrcmOpenVG.so \\\n             --replace-needed libWFC.so libbrcmWFC.so \"$filename\"\n}\n\n## @fn dkmsManager()\n## @param mode dkms operation type\n## @module_name name of dkms module\n## @module_ver version of dkms module\n## Helper function to manage DKMS modules installed by RetroPie\nfunction dkmsManager() {\n    local mode=\"$1\"\n    local module_name=\"$2\"\n    local module_ver=\"$3\"\n    local kernel=\"$(uname -r)\"\n    local ver\n\n    case \"$mode\" in\n        install)\n            if dkms status | grep -q \"^$module_name\"; then\n                dkmsManager remove \"$module_name\" \"$module_ver\"\n            fi\n            ln -sf \"$md_inst\" \"/usr/src/${module_name}-${module_ver}\"\n            dkms install --no-initrd --force -m \"$module_name\" -v \"$module_ver\" -k \"$kernel\"\n            if ! dkms status \"$module_name/$module_ver\" -k \"$kernel\" | grep -q installed; then\n                # Force building for any kernel that has source/headers\n                local k_ver\n                while read k_ver; do\n                    if [[ -d \"$(realpath /lib/modules/$k_ver/build)\" ]]; then\n                        dkms install --no-initrd --force -m \"$module_name/$module_ver\" -k \"$k_ver\"\n                    fi\n                done < <(ls -r1 /lib/modules)\n            fi\n            if ! dkms status \"$module_name/$module_ver\" | grep -q installed; then\n                md_ret_errors+=(\"Failed to install $md_id\")\n                return 1\n            fi\n            ;;\n        remove)\n            for ver in $(dkms status \"$module_name\" | awk -F'[/,:]' '{print $2}'); do\n                dkms remove -m \"$module_name\" -v \"$ver\" --all\n                rm -f \"/usr/src/${module_name}-${ver}\"\n            done\n            dkmsManager unload \"$module_name\" \"$module_ver\"\n            ;;\n        reload)\n            dkmsManager unload \"$module_name\" \"$module_ver\"\n            # No reason to load modules in chroot\n            if [[ \"$__chroot\" -eq 0 ]]; then\n                modprobe \"$module_name\"\n            fi\n            ;;\n        unload)\n            if [[ -n \"$(lsmod | grep ${module_name/-/_})\" ]]; then\n                rmmod \"$module_name\"\n            fi\n            ;;\n    esac\n}\n\n## @fn getIPAddress()\n## @param dev optional specific network device to use for address lookup\n## @brief Obtains the current externally routable source IP address of the machine\n## @details This function first tries to obtain an external IPv4 route and\n## otherwise tries an IPv6 route if the IPv4 route can not be determined.\n## If no external route can be determined, nothing will be returned.\n## This function uses Google's DNS servers as the external lookup address.\nfunction getIPAddress() {\n    local dev=\"$1\"\n    local ip_route\n\n    # first try to obtain an external IPv4 route\n    ip_route=$(ip -4 route get 8.8.8.8 ${dev:+dev $dev} 2>/dev/null)\n    if [[ -z \"$ip_route\" ]]; then\n        # if there is no IPv4 route, try to obtain an IPv6 route instead\n        ip_route=$(ip -6 route get 2001:4860:4860::8888 ${dev:+dev $dev} 2>/dev/null)\n    fi\n\n    # if an external route was found, report its source address\n    [[ -n \"$ip_route\" ]] && grep -oP \"src \\K[^\\s]+\" <<< \"$ip_route\"\n}\n\n## @fn isConnected()\n## @brief Simple check to see if there is a connection to the Internet.\n## @details Uses the getIPAddress function to check if we have a route to the Internet. Also sets\n## __NET_ERRMSG with an error message for use in packages / setup to display to the user if not.\n## @retval 0 on success\n## @retval 1 on failure\nfunction isConnected() {\n    local ip=\"$(getIPAddress)\"\n    if [[ -z \"$ip\" ]]; then\n        __NET_ERRMSG=\"Not connected to the Internet\"\n        return 1\n    fi\n    return 0\n}\n\n## @fn adminRsync()\n## @param src src folder on local system - eg \"$__tmpdir/stats/\"\n## @param dest destination folder on remote system - eg \"stats/\"\n## @param params additional rsync parameters - eg --delete\n## @brief Rsyncs data to remote host for admin modules\n## @details Used to rsync data to our server for admin modules. Default remote\n## user is retropie, host is $__binary_host and default port is 22. These can be overridden with\n## env vars __upload_user __upload_host and __upload_port\n##\n## The default parameters for rsync are \"-av --delay-updates\" - more can be added via the 3rd+ argument\nfunction adminRsync() {\n    local src=\"$1\"\n    local dest=\"$2\"\n    shift 2\n    local params=(\"$@\")\n\n    local remote_user=\"$__upload_user\"\n    [[ -z \"$remote_user\" ]] && remote_user=\"retropie\"\n    local remote_host=\"$__upload_host\"\n    [[ -z \"$remote_host\" ]] && remote_host=\"$__binary_host\"\n    local remote_port=\"$__upload_port\"\n    [[ -z \"$remote_port\" ]] && remote_port=22\n\n    rsync -av --delay-updates -e \"ssh -p $remote_port\" \"${params[@]}\" \"$src\" \"$remote_user@$remote_host:$dest\"\n}\n\n## @fn signFile()\n## @param file path to file to sign\n## @brief signs file with $__gpg_signing_key\n## @details signs file with $__gpg_signing_key creating corresponding .asc file in the same folder\nfunction signFile() {\n    local file=\"$1\"\n    local cmd_out\n    cmd_out=$(gpg --default-key \"$__gpg_signing_key\" --detach-sign --armor --yes \"$1\" 2>&1)\n    if [[ \"$?\" -ne 0 ]]; then\n        md_ret_errors+=(\"Failed to sign $1\\n\\n$cmd_out\")\n        return 1\n    fi\n    return 0\n}\n"
  },
  {
    "path": "scriptmodules/inifuncs.sh",
    "content": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## @file inifuncs.sh\n## @brief RetroPie inifuncs library\n## @copyright GPLv3\n\n# @fn fatalError()\n# @param message string or array of messages to display\n# @brief echos message, and exits immediately.\nfunction fatalError() {\n    echo -e \"$1\"\n    exit 1\n}\n\n# arg 1: delimiter, arg 2: quote, arg 3: file\n\n## @fn iniConfig()\n## @param delim ini file delimiter eg. ' = '\n## @param quote ini file quoting character eg. '\"'\n## @param config ini file to edit\n## @brief Configure an ini file for getting/setting values with `iniGet` and `iniSet`\nfunction iniConfig() {\n    __ini_cfg_delim=\"$1\"\n    __ini_cfg_quote=\"$2\"\n    __ini_cfg_file=\"$3\"\n}\n\n# arg 1: command, arg 2: key, arg 3: value, arg 4: file (optional - uses file from iniConfig if not used)\n\n# @fn iniProcess()\n# @param command `set`, `unset` or `del`\n# @param key ini key to operate on\n# @param value to set\n# @param file optional file to use another file than the one configured with iniConfig\n# @brief The main function for setting and deleting from ini files - usually\n# not called directly but via iniSet iniUnset and iniDel\nfunction iniProcess() {\n    local cmd=\"$1\"\n    local key=\"$2\"\n    local value=\"$3\"\n    local file=\"$4\"\n    [[ -z \"$file\" ]] && file=\"$__ini_cfg_file\"\n    local delim=\"$__ini_cfg_delim\"\n    local quote=\"$__ini_cfg_quote\"\n\n    [[ -z \"$file\" ]] && fatalError \"No file provided for ini/config change\"\n    [[ -z \"$key\" ]] && fatalError \"No key provided for ini/config change on $file\"\n\n    # we strip the delimiter of spaces, so we can \"fussy\" match existing entries that have the wrong spacing\n    local delim_strip=${delim// /}\n    # if the stripped delimiter is empty - such as in the case of a space, just use the delimiter instead\n    [[ -z \"$delim_strip\" ]] && delim_strip=\"$delim\"\n    local match_re=\"^[[:space:]#]*$key[[:space:]]*$delim_strip.*$\"\n\n    local match\n    if [[ -f \"$file\" ]]; then\n        match=$(grep -i \"$match_re\" \"$file\" | tail -1)\n    else\n        touch \"$file\"\n    fi\n\n    if [[ \"$cmd\" == \"del\" ]]; then\n        [[ -n \"$match\" ]] && sed -i --follow-symlinks \"\\|$(sedQuote \"$match\")|d\" \"$file\"\n        return 0\n    fi\n\n    [[ \"$cmd\" == \"unset\" ]] && key=\"# $key\"\n\n    local replace=\"$key$delim$quote$value$quote\"\n    if [[ -z \"$match\" ]]; then\n        # make sure there is a newline then add the key-value pair\n        sed -i --follow-symlinks '$a\\' \"$file\"\n        echo \"$replace\" >> \"$file\"\n    else\n        # replace existing key-value pair\n        sed -i --follow-symlinks \"s|$(sedQuote \"$match\")|$(sedQuote \"$replace\")|g\" \"$file\"\n    fi\n\n    [[ \"$file\" =~ retroarch\\.cfg$ ]] && retroarchIncludeToEnd \"$file\"\n    return 0\n}\n\n## @fn iniUnset()\n## @param key ini key to operate on\n## @param value to Unset (key will be commented out, but the value can be changed also)\n## @param file optional file to use another file than the one configured with iniConfig\n## @brief Unset (comment out) a key / value pair in an ini file.\n## @details The key does not have to exist - if it doesn't exist a new line will\n## be added - eg. `# key = \"value\"`\n##\n## This function is useful for creating example configuration entries for users\n## to manually enable later or if a configuration is to be disabled but left\n## as an example.\nfunction iniUnset() {\n    iniProcess \"unset\" \"$1\" \"$2\" \"$3\"\n}\n\n## @fn iniSet()\n## @param key ini key to operate on\n## @param value to set\n## @param file optional file to use another file than the one configured with iniConfig\n## @brief Set a key / value pair in an ini file.\n## @details If the key already exists the existing line will be changed. If not\n## a new line will be created.\nfunction iniSet() {\n    iniProcess \"set\" \"$1\" \"$2\" \"$3\"\n}\n\n## @fn iniDel()\n## @param key ini key to operate on\n## @param file optional file to use another file than the one configured with iniConfig\n## @brief Delete a key / value pair in an ini file.\nfunction iniDel() {\n    iniProcess \"del\" \"$1\" \"\" \"$2\"\n}\n\n## @fn iniGet()\n## @param key ini key to get the value of\n## @param file optional file to use another file than the one configured with iniConfig\n## @brief Get the value of a key from an ini file.\n## @details The value of the key will end up in the global ini_value variable.\nfunction iniGet() {\n    local key=\"$1\"\n    local file=\"$2\"\n    [[ -z \"$file\" ]] && file=\"$__ini_cfg_file\"\n    if [[ ! -f \"$file\" ]]; then\n        ini_value=\"\"\n        return 1\n    fi\n\n    local delim=\"$__ini_cfg_delim\"\n    local quote=\"$__ini_cfg_quote\"\n    # we strip the delimiter of spaces, so we can \"fussy\" match existing entries that have the wrong spacing\n    local delim_strip=${delim// /}\n    # if the stripped delimiter is empty - such as in the case of a space, just use the delimiter instead\n    [[ -z \"$delim_strip\" ]] && delim_strip=\"$delim\"\n\n    # create a regexp to match the value based on whether we are looking for quotes or not\n    local value_m\n    if [[ -n \"$quote\" ]]; then\n        value_m=\"$quote*\\([^$quote|\\r]*\\)$quote*\"\n    else\n        value_m=\"\\([^\\r]*\\)\"\n    fi\n\n    ini_value=\"$(sed -n \"s#^[ |\\t]*$key[ |\\t]*$delim_strip[ |\\t]*$value_m.*#\\1#p\" \"$file\" | tail -1)\"\n}\n\n# @fn retroarchIncludeToEnd()\n# @param file config file to process\n# @brief Makes sure a `retroarch.cfg` file has the `#include` line at the end.\n# @details Used in runcommand.sh and iniProcess to ensure the #include for the\n# main retroarch.cfg is always at the end of a system `retroarch.cfg`. This\n# is because when processing its config RetroArch will take the first value it\n# finds, so any overrides need to be above the `#include` line where the global\n# retroarch.cfg is included.\nfunction retroarchIncludeToEnd() {\n    local config=\"$1\"\n\n    [[ ! -f \"$config\" ]] && return\n\n    local re=\"^#include.*retroarch\\.cfg\"\n\n    # extract the include line (unless it is the last line in the file)\n    # (remove blank lines, the last line and search for an include line in remaining lines)\n    local include=$(sed '/^$/d;$d' \"$config\" | grep \"$re\")\n\n    # if matched remove it and re-add it at the end\n    if [[ -n \"$include\" ]]; then\n        sed -i --follow-symlinks \"/$re/d\" \"$config\"\n        # add newline if missing and the #include line\n        sed -i --follow-symlinks '$a\\' \"$config\"\n        echo \"$include\" >>\"$config\"\n    fi\n}\n\n# arg 1: key, arg 2: default value (optional - is 1 if not used)\nfunction addAutoConf() {\n    local key=\"$1\"\n    local default=\"$2\"\n    local file=\"$configdir/all/autoconf.cfg\"\n\n    if [[ -z \"$default\" ]]; then\n       default=\"1\"\n    fi\n\n    iniConfig \" = \" '\"' \"$file\"\n    iniGet \"$key\"\n    ini_value=\"${ini_value// /}\"\n    if [[ -z \"$ini_value\" ]]; then\n        iniSet \"$key\" \"$default\"\n        chown \"$__user\":\"$__group\" \"$file\"\n    fi\n}\n\n# arg 1: key, arg 2: value\nfunction setAutoConf() {\n    local key=\"$1\"\n    local value=\"$2\"\n    local file=\"$configdir/all/autoconf.cfg\"\n\n    iniConfig \" = \" '\"' \"$file\"\n    iniSet \"$key\" \"$value\"\n    chown \"$__user\":\"$__group\" \"$file\"\n}\n\n# arg 1: key\nfunction getAutoConf(){\n    local key=\"$1\"\n\n    iniConfig \" = \" '\"' \"$configdir/all/autoconf.cfg\"\n    iniGet \"$key\"\n\n    [[ \"$ini_value\" == \"1\" ]] && return 0\n    return 1\n}\n\n# escape special characters for sed\nfunction sedQuote() {\n    local string=\"$1\"\n    string=\"${string//\\\\/\\\\\\\\}\"\n    string=\"${string//|/\\\\|}\"\n    string=\"${string//[/\\\\[}\"\n    string=\"${string//]/\\\\]}\"\n    echo \"$string\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-81.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-81\"\nrp_module_desc=\"Sinclair ZX81 emulator - EightyOne port for libretro\"\nrp_module_help=\"ROM Extensions: .p .tzx .t81\\n\\nCopy your ZX81 roms to $romdir/zx81\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/81-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/81-libretro.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-81() {\n    gitPullOrClone\n}\n\nfunction build_lr-81() {\n    make clean\n    make\n    md_ret_require=\"$md_build/81_libretro.so\"\n}\n\nfunction install_lr-81() {\n    md_ret_files=(\n        'README.md'\n        '81_libretro.so'\n    )\n}\n\nfunction configure_lr-81() {\n    mkRomDir \"zx81\"\n    defaultRAConfig \"zx81\"\n\n    addEmulator 1 \"$md_id\" \"zx81\" \"$md_inst/81_libretro.so\"\n    addSystem \"zx81\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-atari800.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-atari800\"\nrp_module_desc=\"Atari 8-bit/800/5200 emulator - Atari800 port for libretro\"\nrp_module_help=\"ROM Extensions: .a52 .bas .bin .car .xex .atr .xfd .dcm .atr.gz .xfd.gz\\n\\nCopy your Atari800 games to $romdir/atari800\\n\\nCopy your Atari 5200 roms to $romdir/atari5200 You need to copy the Atari 800/5200 BIOS files (5200.ROM, ATARIBAS.ROM, ATARIOSB.ROM and ATARIXL.ROM) to the folder $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/libretro-atari800/master/atari800/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/libretro-atari800.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-atari800() {\n    gitPullOrClone\n}\n\nfunction build_lr-atari800() {\n    make clean\n    CFLAGS+=\" -DDEFAULT_CFG_NAME=\\\\\\\".lr-atari800.cfg\\\\\\\"\" make\n    md_ret_require=\"$md_build/atari800_libretro.so\"\n}\n\nfunction install_lr-atari800() {\n    md_ret_files=(\n        'atari800_libretro.so'\n        'atari800/COPYING'\n    )\n}\n\nfunction configure_lr-atari800() {\n    mkRomDir \"atari800\"\n    mkRomDir \"atari5200\"\n\n    defaultRAConfig \"atari800\"\n    defaultRAConfig \"atari5200\"\n\n    mkUserDir \"$md_conf_root/atari800\"\n    moveConfigFile \"$home/.lr-atari800.cfg\" \"$md_conf_root/atari800/lr-atari800.cfg\"\n\n    addEmulator 1 \"lr-atari800\" \"atari800\" \"$md_inst/atari800_libretro.so\"\n    addEmulator 1 \"lr-atari800\" \"atari5200\" \"$md_inst/atari800_libretro.so\"\n    addSystem \"atari800\"\n    addSystem \"atari5200\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-lynx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-lynx\"\nrp_module_desc=\"Atari Lynx emulator - Mednafen Lynx Port for libretro, itself a fork of Handy\"\nrp_module_help=\"ROM Extensions: .lnx .zip\\n\\nCopy your Atari Lynx roms to $romdir/atarilynx\\n\\nCopy the required BIOS file lynxboot.img to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-lynx-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-lynx-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-beetle-lynx() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-lynx() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_lynx_libretro.so\"\n}\n\nfunction install_lr-beetle-lynx() {\n    md_ret_files=(\n        'mednafen_lynx_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-lynx() {\n    mkRomDir \"atarilynx\"\n    defaultRAConfig \"atarilynx\"\n\n    addEmulator 0 \"$md_id\" \"atarilynx\" \"$md_inst/mednafen_lynx_libretro.so\"\n    addSystem \"atarilynx\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-ngp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-ngp\"\nrp_module_desc=\"Neo Geo Pocket(Color)emu - Mednafen Neo Geo Pocket core port for libretro\"\nrp_module_help=\"ROM Extensions: .ngc .ngp .zip\\n\\nCopy your Neo Geo Pocket roms to $romdir/ngp\\n\\nCopy your Neo Geo Pocket Color roms to $romdir/ngpc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-ngp-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-ngp-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction _update_hook_lr-beetle-ngp() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-mednafen-ngp\" \"lr-beetle-ngp\"\n}\n\nfunction sources_lr-beetle-ngp() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-ngp() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_ngp_libretro.so\"\n}\n\nfunction install_lr-beetle-ngp() {\n    md_ret_files=(\n        'mednafen_ngp_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-ngp() {\n    local system\n    for system in ngp ngpc; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 1 \"$md_id\" \"$system\" \"$md_inst/mednafen_ngp_libretro.so\"\n        addSystem \"$system\"\n    done\n\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-pce-fast.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-pce-fast\"\nrp_module_desc=\"PCEngine emu - Mednafen PCE Fast port for libretro\"\nrp_module_help=\"ROM Extensions: .pce .ccd .cue .zip\\n\\nCopy your PC Engine / TurboGrafx roms to $romdir/pcengine\\n\\nCopy the required BIOS file syscard3.pce to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-pce-fast-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-pce-fast-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction _update_hook_lr-beetle-pce-fast() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-mednafen-pce-fast\" \"lr-beetle-pce-fast\"\n}\n\nfunction sources_lr-beetle-pce-fast() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-pce-fast() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_pce_fast_libretro.so\"\n}\n\nfunction install_lr-beetle-pce-fast() {\n    md_ret_files=(\n        'mednafen_pce_fast_libretro.so'\n        'COPYING'\n        'README.md'\n    )\n}\n\nfunction configure_lr-beetle-pce-fast() {\n    mkRomDir \"pcengine\"\n    defaultRAConfig \"pcengine\"\n\n    addEmulator 1 \"$md_id\" \"pcengine\" \"$md_inst/mednafen_pce_fast_libretro.so\"\n    addSystem \"pcengine\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-pce.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-pce\"\nrp_module_desc=\"PC Engine/CD/SuperGrafx emulator - Mednafen PCE port for libretro\"\nrp_module_help=\"ROM Extensions: .7z .ccd .chd .cue .pce .sgx\\n\\nCopy your PC Engine roms to $romdir/pcengine\\n\\nCopy the required BIOS file syscard3.pce to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-pce-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-pce-libretro.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-beetle-pce() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-pce() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_pce_libretro.so\"\n}\n\nfunction install_lr-beetle-pce() {\n    md_ret_files=(\n        'mednafen_pce_libretro.so'\n        'COPYING'\n        'README.md'\n    )\n}\n\nfunction configure_lr-beetle-pce() {\n    mkRomDir \"pcengine\"\n    defaultRAConfig \"pcengine\"\n\n    addEmulator 1 \"$md_id\" \"pcengine\" \"$md_inst/mednafen_pce_libretro.so\"\n    addSystem \"pcengine\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # Set core options\n    setRetroArchCoreOption \"pce_aspect_ratio\" \"4:3\"\n    setRetroArchCoreOption \"pce_multitap\" \"disabled\"\n    setRetroArchCoreOption \"pce_scaling\" \"hires\"\n}\n\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-pcfx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-pcfx\"\nrp_module_desc=\"PCFX emulator - Mednafen PCFX Port for libretro\"\nrp_module_help=\"ROM Extensions: .img .iso .ccd .cue\\n\\nCopy the required BIOS file pcfx.rom to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-pcfx-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-pcfx-libretro master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-beetle-pcfx() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-pcfx() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_pcfx_libretro.so\"\n}\n\nfunction install_lr-beetle-pcfx() {\n    md_ret_files=(\n        'mednafen_pcfx_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-pcfx() {\n    mkRomDir \"pcfx\"\n    defaultRAConfig \"pcfx\"\n\n    addEmulator 1 \"$md_id\" \"pcfx\" \"$md_inst/mednafen_pcfx_libretro.so\"\n    addSystem \"pcfx\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-psx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-psx\"\nrp_module_desc=\"PlayStation emulator - Mednafen PSX Port for libretro\"\nrp_module_help=\"ROM Extensions: .bin .cue .cbn .img .iso .m3u .mdf .pbp .toc .z .znx\\n\\nCopy your PlayStation roms to $romdir/psx\\n\\nCopy the required BIOS files\\n\\nscph5500.bin and\\nscph5501.bin and\\nscph5502.bin to\\n\\n$biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-psx-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-psx-libretro.git master\"\nrp_module_section=\"opt x86=main\"\nrp_module_flags=\"!arm\"\n\nfunction depends_lr-beetle-psx() {\n    local depends=(libvulkan-dev libgl1-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-beetle-psx() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-psx() {\n    make clean\n    make HAVE_HW=1\n    md_ret_require=(\n        'mednafen_psx_hw_libretro.so'\n    )\n}\n\nfunction install_lr-beetle-psx() {\n    md_ret_files=(\n        'mednafen_psx_hw_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-psx() {\n    mkRomDir \"psx\"\n    defaultRAConfig \"psx\"\n\n    addEmulator 0 \"$md_id\" \"psx\" \"$md_inst/mednafen_psx_hw_libretro.so\"\n    addSystem \"psx\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-saturn.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-saturn\"\nrp_module_desc=\"Saturn emulator - Mednafen Saturn port for libretro\"\nrp_module_help=\"ROM Extensions: .chd .cue\\n\\nCopy your Saturn roms to $romdir/saturn\\n\\nCopy the required BIOS files sega_101.bin / mpr-17933.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-saturn-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-saturn-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-beetle-saturn() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-saturn() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_saturn_libretro.so\"\n}\n\nfunction install_lr-beetle-saturn() {\n    md_ret_files=(\n        'mednafen_saturn_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-saturn() {\n    mkRomDir \"saturn\"\n    defaultRAConfig \"saturn\"\n\n    addEmulator 1 \"$md_id\" \"saturn\" \"$md_inst/mednafen_saturn_libretro.so\"\n    addSystem \"saturn\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-supergrafx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-supergrafx\"\nrp_module_desc=\"SuperGrafx TG-16 emulator - Mednafen PCE Fast port for libretro\"\nrp_module_help=\"ROM Extensions: .pce .ccd .cue .zip\\n\\nCopy your PC Engine / TurboGrafx roms to $romdir/pcengine\\n\\nCopy the required BIOS file syscard3.pce to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-supergrafx-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-supergrafx-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-beetle-supergrafx() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-supergrafx() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_supergrafx_libretro.so\"\n}\n\nfunction install_lr-beetle-supergrafx() {\n    md_ret_files=(\n        'mednafen_supergrafx_libretro.so'\n        'COPYING'\n    )\n}\n\nfunction configure_lr-beetle-supergrafx() {\n    mkRomDir \"pcengine\"\n    defaultRAConfig \"pcengine\"\n\n    addEmulator 0 \"$md_id\" \"pcengine\" \"$md_inst/mednafen_supergrafx_libretro.so\"\n    addSystem \"pcengine\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-vb.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-vb\"\nrp_module_desc=\"Virtual Boy emulator - Mednafen VB (optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .vb .zip\\n\\nCopy your Virtual Boy roms to $romdir/virtualboy\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-vb-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-vb-libretro.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction sources_lr-beetle-vb() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-vb() {\n    local params=(NEED_STEREO_SOUND=1)\n    isPlatform \"arm\" && params+=(platform=armv FRONTEND_SUPPORTS_RGB565=1)\n    make clean\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/mednafen_vb_libretro.so\"\n}\n\nfunction install_lr-beetle-vb() {\n    md_ret_files=(\n        'mednafen_vb_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-vb() {\n    mkRomDir \"virtualboy\"\n    defaultRAConfig \"virtualboy\"\n\n    addEmulator 1 \"$md_id\" \"virtualboy\" \"$md_inst/mednafen_vb_libretro.so\"\n    addSystem \"virtualboy\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-beetle-wswan.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-beetle-wswan\"\nrp_module_desc=\"Wonderswan emu - Mednafen WonderSwan core port for libretro\"\nrp_module_help=\"ROM Extensions: .ws .wsc .zip\\n\\nCopy your Wonderswan roms to $romdir/wonderswan\\n\\nCopy your Wonderswan Color roms to $romdir/wonderswancolor\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/beetle-wswan-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/beetle-wswan-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction _update_hook_lr-beetle-wswan() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-mednafen-wswan\" \"lr-beetle-wswan\"\n}\n\nfunction sources_lr-beetle-wswan() {\n    gitPullOrClone\n}\n\nfunction build_lr-beetle-wswan() {\n    make clean\n    make\n    md_ret_require=\"$md_build/mednafen_wswan_libretro.so\"\n}\n\nfunction install_lr-beetle-wswan() {\n    md_ret_files=(\n        'mednafen_wswan_libretro.so'\n    )\n}\n\nfunction configure_lr-beetle-wswan() {\n    mkRomDir \"wonderswan\"\n    mkRomDir \"wonderswancolor\"\n    defaultRAConfig \"wonderswan\"\n    defaultRAConfig \"wonderswancolor\"\n\n    addEmulator 1 \"$md_id\" \"wonderswan\" \"$md_inst/mednafen_wswan_libretro.so\"\n    addEmulator 1 \"$md_id\" \"wonderswancolor\" \"$md_inst/mednafen_wswan_libretro.so\"\n    addSystem \"wonderswan\"\n    addSystem \"wonderswancolor\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-bennugd.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-bennugd\"\nrp_module_desc=\"BennuGD as a libretro core\"\nrp_module_help=\"ROM Extensions: .dat .dcb\\n\\nCopy your games to $romdir/bennugd\"\nrp_module_licence=\"GPL3\"\nrp_module_repo=\"git https://github.com/diekleinekuh/BennuGD_libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_lr-bennugd() {\n    getDepends cmake libssl-dev libogg-dev libvorbis-dev libmikmod-dev libpng-dev zlib1g-dev libfreetype6-dev\n}\n\n\nfunction sources_lr-bennugd() {\n    gitPullOrClone\n}\n\nfunction build_lr-bennugd() {\n    mkdir build\n    cd build\n    cmake .. -DNO_SYSTEM_DEPENDENCIES=OFF -DCMAKE_BUILD_TYPE=Release\n    cmake  --build . --clean-first -j\n    md_ret_require=\"$md_build/build/bennugd_libretro.so\"\n}\n\nfunction install_lr-bennugd() {\n    md_ret_files=(\n        'build/bennugd_libretro.so'\n    )\n}\n\nfunction configure_lr-bennugd() {\n    mkRomDir \"bennugd\"\n    defaultRAConfig \"bennugd\"\n\n    addEmulator 1 \"$md_id\" \"bennugd\" \"$md_inst/bennugd_libretro.so\"\n\n    addSystem \"bennugd\" \"BennuGD\" \".dat .dcb\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-bluemsx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-bluemsx\"\nrp_module_desc=\"MSX/MSX2/Colecovision emu - blueMSX port for libretro\"\nrp_module_help=\"ROM Extensions: .cas .rom .mx1 .mx2 .col .dsk .zip\\n\\nCopy your MSX/MSX2 games to $romdir/msx\\nCopy your Colecovision games to $romdir/coleco\\n\\nlr-bluemsx requires the BIOS files from the full standalone package of BlueMSX to be copied to '$biosdir/Machines' folder.\\nColecovision BIOS needs to be copied to '$biosdir/Machines/COL - ColecoVision\\coleco.rom'\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/blueMSX-libretro/master/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/blueMSX-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-bluemsx() {\n    gitPullOrClone\n}\n\nfunction build_lr-bluemsx() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/bluemsx_libretro.so\"\n}\n\nfunction install_lr-bluemsx() {\n    md_ret_files=(\n        'bluemsx_libretro.so'\n        'README.md'\n        'system/bluemsx/Databases'\n        'system/bluemsx/Machines'\n    )\n}\n\nfunction configure_lr-bluemsx() {\n    addEmulator 1 \"$md_id\" \"msx\" \"$md_inst/bluemsx_libretro.so\"\n    addSystem \"msx\"\n\n    addEmulator 1 \"$md_id\" \"coleco\" \"$md_inst/bluemsx_libretro.so\"\n    addSystem \"coleco\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkRomDir \"msx\"\n    defaultRAConfig \"msx\"\n\n    # force colecovision system\n    local core_config=\"$md_conf_root/coleco/retroarch-core-options.cfg\"\n    iniConfig \" = \" '\"' \"$core_config\"\n    iniSet \"bluemsx_msxtype\" \"ColecoVision\" \"$core_config\"\n    chown \"$__user\":\"$__group\" \"$core_config\"\n\n    mkRomDir \"coleco\"\n    defaultRAConfig \"coleco\" \"core_options_path\" \"$core_config\"\n\n    cp -rv \"$md_inst/\"{Databases,Machines} \"$biosdir/\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/\"{Databases,Machines}\n\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-bsnes.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-bsnes\"\nrp_module_desc=\"Super Nintendo Emulator - bsnes port for libretro (v115)\"\nrp_module_help=\"ROM Extensions: .bml .smc .sfc .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/bsnes/master/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/libretro/bsnes.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!armv6 !:\\$__gcc_version:-lt:7\"\n\nfunction sources_lr-bsnes() {\n    gitPullOrClone\n}\n\nfunction build_lr-bsnes() {\n    local params=(target=\"libretro\" build=\"release\" binary=\"library\")\n    make -C bsnes clean \"${params[@]}\"\n    make -C bsnes \"${params[@]}\"\n    md_ret_require=\"$md_build/bsnes/out/bsnes_libretro.so\"\n}\n\nfunction install_lr-bsnes() {\n    md_ret_files=(\n        'bsnes/out/bsnes_libretro.so'\n        'LICENSE.txt'\n        'GPLv3.txt'\n        'CREDITS.md'\n        'README.md'\n    )\n}\n\nfunction configure_lr-bsnes() {\n    mkRomDir \"snes\"\n    defaultRAConfig \"snes\"\n\n    addEmulator 1 \"$md_id\" \"snes\" \"$md_inst/bsnes_libretro.so\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-caprice32.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-caprice32\"\nrp_module_desc=\"Amstrad CPC emu - Caprice32 port for libretro\"\nrp_module_help=\"ROM Extensions: .cdt .cpc .dsk\\n\\nCopy your Amstrad CPC games to $romdir/amstradcpc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/libretro-cap32/master/cap32/COPYING.txt\"\nrp_module_repo=\"git https://github.com/libretro/libretro-cap32.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-caprice32() {\n    gitPullOrClone\n}\n\nfunction build_lr-caprice32() {\n    make clean\n    make\n    md_ret_require=\"$md_build/cap32_libretro.so\"\n}\n\nfunction install_lr-caprice32() {\n    md_ret_files=(\n        'cap32_libretro.so'\n    )\n}\n\nfunction configure_lr-caprice32() {\n    mkRomDir \"amstradcpc\"\n    defaultRAConfig \"amstradcpc\"\n\n    setRetroArchCoreOption \"cap32_autorun\" \"enabled\"\n    setRetroArchCoreOption \"cap32_Model\" \"6128\"\n    setRetroArchCoreOption \"cap32_Ram\" \"128\"\n    setRetroArchCoreOption \"cap32_combokey\" \"y\"\n\n    addEmulator 1 \"$md_id\" \"amstradcpc\" \"$md_inst/cap32_libretro.so\"\n    addSystem \"amstradcpc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-desmume.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-desmume\"\nrp_module_desc=\"NDS emu - DESMUME\"\nrp_module_help=\"ROM Extensions: .nds .zip\\n\\nCopy your Nintendo DS roms to $romdir/nds\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/desmume/master/desmume/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/desmume.git master\"\nrp_module_section=\"exp\"\n\nfunction _params_lr-desmume() {\n    local params=()\n    isPlatform \"arm\" && params+=(\"platform=unixarmvhardfloat\")\n    isPlatform \"aarch64\" && params+=(\"DESMUME_JIT=0\")\n    echo \"${params[@]}\"\n}\n\nfunction depends_lr-desmume() {\n    getDepends libpcap-dev libgl1-mesa-dev\n}\n\nfunction sources_lr-desmume() {\n    gitPullOrClone\n}\n\nfunction build_lr-desmume() {\n    cd desmume/src/frontend/libretro\n    make clean\n    make $(_params_lr-desmume)\n    md_ret_require=\"$md_build/desmume/src/frontend/libretro/desmume_libretro.so\"\n}\n\nfunction install_lr-desmume() {\n    md_ret_files=(\n        'desmume/src/frontend/libretro/desmume_libretro.so'\n    )\n}\n\nfunction configure_lr-desmume() {\n    mkRomDir \"nds\"\n    defaultRAConfig \"nds\"\n\n    addEmulator 0 \"$md_id\" \"nds\" \"$md_inst/desmume_libretro.so\"\n    addSystem \"nds\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-desmume2015.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-desmume2015\"\nrp_module_desc=\"NDS emu - DESMUME (2015 version)\"\nrp_module_help=\"ROM Extensions: .nds .zip\\n\\nCopy your Nintendo DS roms to $romdir/nds\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/desmume/master/desmume/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/desmume2015.git master\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-desmume2015() {\n   depends_lr-desmume\n}\n\nfunction sources_lr-desmume2015() {\n    gitPullOrClone\n}\n\nfunction build_lr-desmume2015() {\n    cd desmume\n    make clean\n    make $(_params_lr-desmume)\n    md_ret_require=\"$md_build/desmume/desmume2015_libretro.so\"\n}\n\nfunction install_lr-desmume2015() {\n    md_ret_files=(\n        'desmume/desmume2015_libretro.so'\n    )\n}\n\nfunction configure_lr-desmume2015() {\n    mkRomDir \"nds\"\n    defaultRAConfig \"nds\"\n\n    addEmulator 0 \"$md_id\" \"nds\" \"$md_inst/desmume2015_libretro.so\"\n    addSystem \"nds\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-dinothawr.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-dinothawr\"\nrp_module_desc=\"Dinothawr - standalone libretro puzzle game\"\nrp_module_help=\"Dinothawr game assets are automatically installed to $romdir/ports/dinothawr/\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/Dinothawr/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/Dinothawr.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-dinothawr() {\n    gitPullOrClone\n}\n\nfunction build_lr-dinothawr() {\n    make clean\n    # libretro-common has an issue with neon\n    if isPlatform \"neon\"; then\n        CFLAGS=\"\" make\n    else\n        make\n    fi\n    md_ret_require=\"$md_build/dinothawr_libretro.so\"\n}\n\nfunction install_lr-dinothawr() {\n    md_ret_files=(\n        'dinothawr_libretro.so'\n        'dinothawr'\n    )\n}\n\n\nfunction configure_lr-dinothawr() {\n    setConfigRoot \"ports\"\n\n    addPort \"$md_id\" \"dinothawr\" \"Dinothawr\" \"$md_inst/dinothawr_libretro.so\" \"$romdir/ports/dinothawr/dinothawr.game\"\n\n    mkRomDir \"ports/dinothawr\"\n    defaultRAConfig \"dinothawr\"\n\n    cp -Rv \"$md_inst/dinothawr\" \"$romdir/ports\"\n\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/dinothawr\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-dirksimple.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-dirksimple\"\nrp_module_desc=\"laserdisc emu - DirkSimple\"\nrp_module_help=\"ROM Extensions: .ogv .dirksimple\\n\\nCopy your laserdisc movies in Ogg Theora format to $romdir/daphne\"\nrp_module_licence=\"zlib https://raw.githubusercontent.com/icculus/DirkSimple/main/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/icculus/DirkSimple.git main\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-dirksimple() {\n    getDepends cmake\n}\n\nfunction sources_lr-dirksimple() {\n    gitPullOrClone\n}\n\nfunction build_lr-dirksimple() {\n    rm -fr build && mkdir build\n    cd build\n    cmake -DDIRKSIMPLE_LIBRETRO=ON -DDIRKSIMPLE_SDL=OFF ..\n    make dirksimple_libretro\n    md_ret_require=\"$md_build/build/dirksimple_libretro.so\"\n}\n\nfunction install_lr-dirksimple() {\n    md_ret_files=(\n        'build/dirksimple_libretro.so'\n        'data'\n        'LICENSE.txt'\n    )\n}\n\nfunction configure_lr-dirksimple() {\n    mkRomDir \"daphne\"\n    defaultRAConfig \"daphne\"\n\n    rm -rf \"$biosdir/DirkSimple\"\n    mkUserDir \"$biosdir/DirkSimple\"\n    cp -rf \"$md_inst/data\" \"$biosdir/DirkSimple/\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/DirkSimple\"\n\n    addEmulator 0 \"$md_id\" \"daphne\" \"$md_inst/dirksimple_libretro.so\"\n    addSystem \"daphne\"\n}\n\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-dolphin.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-dolphin\"\nrp_module_desc=\"Gamecube/Wii emulator - Dolphin port for libretro\"\nrp_module_help=\"ROM Extensions: .gcm .iso .wbfs .ciso .gcz\\n\\nCopy your gamecube roms to $romdir/gc and Wii roms to $romdir/wii\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/dolphin/master/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/dolphin master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all 64bit\"\n\nfunction depends_lr-dolphin() {\n    depends_dolphin\n}\n\nfunction sources_lr-dolphin() {\n    gitPullOrClone\n}\n\nfunction build_lr-dolphin() {\n    mkdir build\n    cd build\n    cmake .. -DLIBRETRO=ON -DLIBRETRO_STATIC=1\n    make clean\n    make\n    md_ret_require=\"$md_build/build/dolphin_libretro.so\"\n}\n\nfunction install_lr-dolphin() {\n    md_ret_files=(\n        'build/dolphin_libretro.so'\n    )\n}\n\nfunction configure_lr-dolphin() {\n    mkRomDir \"gc\"\n    mkRomDir \"wii\"\n\n    defaultRAConfig \"gc\"\n    defaultRAConfig \"wii\"\n\n    addEmulator 1 \"$md_id\" \"gc\" \"$md_inst/dolphin_libretro.so\"\n    addEmulator 1 \"$md_id\" \"wii\" \"$md_inst/dolphin_libretro.so\"\n\n    addSystem \"gc\"\n    addSystem \"wii\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-dosbox-pure.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-dosbox-pure\"\nrp_module_desc=\"DOS emulator\"\nrp_module_help=\"ROM Extensions: .bat .com .cue .dosz .exe .ins .ima .img .iso .m3u .m3u8 .vhd .zip\\n\\nCopy your DOS games to $ROMDIR/pc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/dosbox-pure/main/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/dosbox-pure.git main\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_lr-dosbox-pure() {\n    # lr-dosbox-pure will try and use g++ v9 on arm if the system default is v10 due to bugs\n    # see https://github.com/libretro/dosbox-pure/commit/603b1c7ae\n    isPlatform \"arm\" && [[ \"$__gcc_version\" -eq 10 ]] && getDepends g++-9\n}\n\nfunction sources_lr-dosbox-pure() {\n    gitPullOrClone\n}\n\nfunction build_lr-dosbox-pure() {\n    make clean\n    make\n    md_ret_require=\"$md_build/dosbox_pure_libretro.so\"\n}\n\nfunction install_lr-dosbox-pure() {\n    md_ret_files=(\n        'LICENSE'\n        'dosbox_pure_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-dosbox-pure() {\n    mkRomDir \"pc\"\n    defaultRAConfig \"pc\"\n\n    addEmulator 0 \"$md_id\" \"pc\" \"$md_inst/dosbox_pure_libretro.so\"\n    addSystem \"pc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-dosbox.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-dosbox\"\nrp_module_desc=\"DOS emulator\"\nrp_module_help=\"ROM Extensions: .bat .com .exe .sh\\n\\nCopy your DOS games to $ROMDIR/pc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/dosbox-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/dosbox-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction sources_lr-dosbox() {\n    gitPullOrClone\n}\n\nfunction build_lr-dosbox() {\n    local params=()\n    if isPlatform \"arm\"; then\n        if isPlatform \"armv6\"; then\n            params+=\"WITH_DYNAREC=oldarm\"\n        else\n            params+=\"WITH_DYNAREC=arm\"\n        fi\n    fi\n    make clean\n    [[ \"$__gcc_version\" -gt 10 ]] && CXXFLAGS=\"$CXXFLAGS -std=gnu++11\"\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/dosbox_libretro.so\"\n}\n\nfunction install_lr-dosbox() {\n    md_ret_files=(\n        'COPYING'\n        'dosbox_libretro.so'\n        'README'\n    )\n}\n\nfunction configure_lr-dosbox() {\n    mkRomDir \"pc\"\n    defaultRAConfig \"pc\"\n\n    addEmulator 0 \"$md_id\" \"pc\" \"$md_inst/dosbox_libretro.so\"\n    addSystem \"pc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-ep128emu.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-ep128emu\"\nrp_module_desc=\"Enterprise 128 emulator\"\nrp_module_help=\"ROM Extensions: .img .dsk .tap .dtf .wav .bas .com .trn .128\\n\\nCopy your Enterprise games to $romdir/enterprise\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/ep128emu-core/refs/heads/core/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/ep128emu-core.git core\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-ep128emu() {\n    gitPullOrClone\n}\n\nfunction build_lr-ep128emu() {\n    make clean\n    make\n    md_ret_require=\"$md_build/ep128emu_core_libretro.so\"\n}\n\nfunction install_lr-ep128emu() {\n    md_ret_files=(\n        'ep128emu_core_libretro.so'\n    )\n}\n\nfunction configure_lr-ep128emu() {\n    mkRomDir \"enterprise\"\n    ensureSystemretroconfig \"enterprise\"\n\n    addEmulator 1 \"$md_id\" \"enterprise\" \"$md_inst/ep128emu_core_libretro.so\"\n    addSystem \"enterprise\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-fbalpha2012.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-fbalpha2012\"\nrp_module_desc=\"Arcade emu - Final Burn Alpha (0.2.97.30) port for libretro\"\nrp_module_help=\"Previously called lr-fba\\n\\nROM Extension: .zip\\n\\nCopy your FBA roms to\\n$romdir/fba or\\n$romdir/neogeo or\\n$romdir/arcade\\n\\nFor NeoGeo games the neogeo.zip BIOS is required and must be placed in the same directory as your FBA roms.\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/fbalpha2012/master/docs/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/fbalpha2012.git master\"\nrp_module_section=\"opt armv6=main\"\n\nfunction _update_hook_lr-fbalpha2012() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-fba\" \"lr-fbalpha2012\"\n}\n\nfunction sources_lr-fbalpha2012() {\n    gitPullOrClone\n}\n\nfunction build_lr-fbalpha2012() {\n    cd svn-current/trunk/\n    make -f makefile.libretro clean\n    local params=()\n    isPlatform \"arm\" && params+=(\"platform=armv\")\n    make -f makefile.libretro \"${params[@]}\"\n    md_ret_require=\"$md_build/svn-current/trunk/fbalpha2012_libretro.so\"\n}\n\nfunction install_lr-fbalpha2012() {\n    md_ret_files=(\n        'svn-current/trunk/fba.chm'\n        'svn-current/trunk/fbalpha2012_libretro.so'\n        'svn-current/trunk/gamelist-gx.txt'\n        'svn-current/trunk/gamelist.txt'\n        'svn-current/trunk/whatsnew.html'\n        'svn-current/trunk/preset-example.zip'\n    )\n}\n\nfunction configure_lr-fbalpha2012() {\n    local system\n    for system in arcade fba neogeo; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/fbalpha2012_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-fbneo.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-fbneo\"\nrp_module_desc=\"Arcade emu - FinalBurn Neo (latest version) port for libretro\"\nrp_module_help=\"Previously called lr-fba-next and fbalpha\\n\\ROM Extension: .zip\\n\\nCopy your FBA roms to\\n$romdir/fba or\\n$romdir/neogeo or\\n$romdir/arcade\\n\\nFor NeoGeo games the neogeo.zip BIOS is required and must be placed in the same directory as your FBA roms.\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/FBNeo/master/src/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/FBNeo.git master\"\nrp_module_section=\"main armv6=opt\"\n\nfunction _update_hook_lr-fbneo() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-fba-next\" \"lr-fbalpha\"\n    renameModule \"lr-fbalpha\" \"lr-fbneo\"\n}\n\nfunction sources_lr-fbneo() {\n    gitPullOrClone\n}\n\nfunction build_lr-fbneo() {\n    cd src/burner/libretro\n    local params=()\n    isPlatform \"arm\" && params+=(USE_CYCLONE=1)\n    isPlatform \"neon\" && params+=(HAVE_NEON=1)\n    isPlatform \"x86\" && isPlatform \"64bit\" && params+=(USE_X64_DRC=1)\n    make clean\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/src/burner/libretro/fbneo_libretro.so\"\n}\n\nfunction install_lr-fbneo() {\n    md_ret_files=(\n        'fbahelpfilesrc/fbneo.chm'\n        'src/burner/libretro/fbneo_libretro.so'\n        'gamelist.txt'\n        'whatsnew.html'\n        'metadata'\n        'dats'\n    )\n}\n\nfunction configure_lr-fbneo() {\n    local def=1\n    isPlatform \"armv6\" && def=0\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/fbneo_libretro.so\"\n    addEmulator 0 \"$md_id-neocd\" \"arcade\" \"$md_inst/fbneo_libretro.so --subsystem neocd\"\n    addEmulator $def \"$md_id\" \"neogeo\" \"$md_inst/fbneo_libretro.so\"\n    addEmulator 0 \"$md_id-neocd\" \"neogeo\" \"$md_inst/fbneo_libretro.so --subsystem neocd\"\n    addEmulator $def \"$md_id\" \"fba\" \"$md_inst/fbneo_libretro.so\"\n    addEmulator 0 \"$md_id-neocd\" \"fba\" \"$md_inst/fbneo_libretro.so --subsystem neocd\"\n\n    addEmulator 0 \"$md_id-pce\" \"pcengine\" \"$md_inst/fbneo_libretro.so --subsystem pce\"\n    addEmulator 0 \"$md_id-sgx\" \"pcengine\" \"$md_inst/fbneo_libretro.so --subsystem sgx\"\n    addEmulator 0 \"$md_id-tg\" \"pcengine\" \"$md_inst/fbneo_libretro.so --subsystem tg\"\n    addEmulator 0 \"$md_id-gg\" \"gamegear\" \"$md_inst/fbneo_libretro.so --subsystem gg\"\n    addEmulator 0 \"$md_id-sms\" \"mastersystem\" \"$md_inst/fbneo_libretro.so --subsystem sms\"\n    addEmulator 0 \"$md_id-md\" \"megadrive\" \"$md_inst/fbneo_libretro.so --subsystem md\"\n    addEmulator 0 \"$md_id-sg1k\" \"sg-1000\" \"$md_inst/fbneo_libretro.so --subsystem sg1k\"\n    addEmulator 0 \"$md_id-cv\" \"coleco\" \"$md_inst/fbneo_libretro.so --subsystem cv\"\n    addEmulator 0 \"$md_id-msx\" \"msx\" \"$md_inst/fbneo_libretro.so --subsystem msx\"\n    addEmulator 0 \"$md_id-spec\" \"zxspectrum\" \"$md_inst/fbneo_libretro.so --subsystem spec\"\n    addEmulator 0 \"$md_id-fds\" \"fds\" \"$md_inst/fbneo_libretro.so --subsystem fds\"\n    addEmulator 0 \"$md_id-nes\" \"nes\" \"$md_inst/fbneo_libretro.so --subsystem nes\"\n    addEmulator 0 \"$md_id-ngp\" \"ngp\" \"$md_inst/fbneo_libretro.so --subsystem ngp\"\n    addEmulator 0 \"$md_id-ngpc\" \"ngpc\" \"$md_inst/fbneo_libretro.so --subsystem ngp\"\n    addEmulator 0 \"$md_id-chf\" \"channelf\" \"$md_inst/fbneo_libretro.so --subsystem chf\"\n    addEmulator 0 \"$md_id-snes\" \"snes\" \"$md_inst/fbneo_libretro.so --subsystem snes\"\n\n    local systems=(\n        \"arcade\"\n        \"neogeo\"\n        \"fba\"\n        \"pcengine\"\n        \"gamegear\"\n        \"mastersystem\"\n        \"megadrive\"\n        \"sg-1000\"\n        \"coleco\"\n        \"msx\"\n        \"zxspectrum\"\n        \"fds\"\n        \"nes\"\n        \"ngp\"\n        \"ngpc\"\n        \"channelf\"\n        \"snes\"\n    )\n\n    local system\n    for system in \"${systems[@]}\"; do\n        addSystem \"$system\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    for system in \"${systems[@]}\"; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n    done\n\n    # Create directories for all support files\n    mkUserDir \"$biosdir/fbneo\"\n    mkUserDir \"$biosdir/fbneo/blend\"\n    mkUserDir \"$biosdir/fbneo/cheats\"\n    mkUserDir \"$biosdir/fbneo/patched\"\n    mkUserDir \"$biosdir/fbneo/samples\"\n    mkUserDir \"$biosdir/fbneo/ips\"\n    mkUserDir \"$biosdir/fbneo/romdata\"\n\n    # copy hiscore.dat\n    cp \"$md_inst/metadata/hiscore.dat\" \"$biosdir/fbneo/\"\n    chown \"$__user\":\"$__group\" \"$biosdir/fbneo/hiscore.dat\"\n\n    # Set core options\n    setRetroArchCoreOption \"fbneo-diagnostic-input\" \"Hold Start\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-fceumm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-fceumm\"\nrp_module_desc=\"NES emu - FCEUmm port for libretro\"\nrp_module_help=\"ROM Extensions: .nes .zip\\n\\nCopy your NES roms to $romdir/nes\\n\\nFor the Famicom Disk System copy your roms to $romdir/fds\\n\\nFor the Famicom Disk System copy the required BIOS file disksys.rom to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/libretro-fceumm/master/Copying\"\nrp_module_repo=\"git https://github.com/libretro/libretro-fceumm.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-fceumm() {\n    gitPullOrClone\n}\n\nfunction build_lr-fceumm() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/fceumm_libretro.so\"\n}\n\nfunction install_lr-fceumm() {\n    md_ret_files=(\n        'Authors'\n        'changelog.txt'\n        'Copying'\n        'fceumm_libretro.so'\n        'whatsnew.txt'\n        'zzz_todo.txt'\n    )\n}\n\nfunction configure_lr-fceumm() {\n    mkRomDir \"nes\"\n    mkRomDir \"fds\"\n    defaultRAConfig \"nes\"\n    defaultRAConfig \"fds\"\n\n    local def=1\n    isPlatform \"armv6\" && def=0\n\n    addEmulator \"$def\" \"$md_id\" \"nes\" \"$md_inst/fceumm_libretro.so\"\n    addEmulator 0 \"$md_id\" \"fds\" \"$md_inst/fceumm_libretro.so\"\n    addSystem \"nes\"\n    addSystem \"fds\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-flycast/01_flags_fix.diff",
    "content": "diff --git a/Makefile b/Makefile\nindex 2c477b4d..92a67b62 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -44,8 +44,6 @@ LDFLAGS  :=\n LDFLAGS_END :=\n INCFLAGS :=\n LIBS     :=\n-CFLAGS   := \n-CXXFLAGS :=\n \n GIT_VERSION := \" $(shell git rev-parse --short HEAD || echo unknown)\"\n ifneq ($(GIT_VERSION),\" unknown\")\n@@ -208,6 +206,7 @@ else ifneq (,$(findstring rpi,$(platform)))\n \t\tendif\n \t\tCORE_DEFINES += -DLOW_END\n \tendif\n+\tLDFLAGS += $(CFLAGS)\n \n # Classic Platforms #####################\n # Platform affix = classic_<ISA>_<µARCH>\n@@ -894,7 +893,7 @@ else\n \telse ifneq (,$(findstring classic_arm,$(platform)))\n \t\tOPTFLAGS       := -O2\n \telse ifeq (,$(findstring classic_arm,$(platform)))\n-\t\tOPTFLAGS       := -O3\n+\t\tOPTFLAGS       := -O2\n \tendif\n \n \tCORE_DEFINES   += -DNDEBUG\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-flycast-dev.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-flycast-dev\"\nrp_module_desc=\"Multiplatform Sega Dreamcast, Naomi, Naomi 2 and Atomiswave emulator\"\nrp_module_help=\"Dreamcast ROM Extensions: .cdi .gdi .chd .m3u, Naomi/Atomiswave ROM Extension: .zip\\n\\nCopy your Dreamcast/Naomi roms to $romdir/dreamcast\\n\\nCopy the required Dreamcast BIOS files dc_boot.bin and dc_flash.bin to $biosdir/dc\\n\\nCopy the required Naomi/Atomiswave BIOS files naomi.zip/naomigd.zip and awbios.zip to $biosdir/dc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/flyinghead/flycast/master/LICENSE\"\nrp_module_repo=\"git https://github.com/flyinghead/flycast.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!armv6 !videocore !:\\$__gcc_version:-lt:9\"\n\nfunction depends_lr-flycast-dev() {\n    local depends=(zlib1g-dev libgl-dev cmake)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-flycast-dev() {\n    gitPullOrClone\n}\n\nfunction build_lr-flycast-dev() {\n    local params=(\"-DLIBRETRO=ON -DWITH_SYSTEM_ZLIB=ON -DCMAKE_BUILD_TYPE=Release\")\n\n    if isPlatform \"gles3\"; then\n            params+=(\"-DUSE_GLES=ON\")\n    elif isPlatform \"gles\"; then\n            params+=(\"-DUSE_GLES2=ON\")\n    fi\n    isPlatform \"vulkan\" && params+=(\"-DUSE_VULKAN=ON\") || params+=(\"-DUSE_VULKAN=OFF\")\n\n    rm -fr build && mkdir build\n    cd build\n    cmake \"${params[@]}\" ..\n    make\n\n    md_ret_require=\"$md_build/build/flycast_libretro.so\"\n}\n\nfunction install_lr-flycast-dev() {\n    md_ret_files=(\n        'build/flycast_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-flycast-dev() {\n    local sys\n    local def\n    for sys in \"arcade\" \"dreamcast\"; do\n        def=0\n        isPlatform \"kms\" && [[ \"$sys\" == \"dreamcast\" ]] && def=1\n        # segfaults on the rpi without redirecting stdin from </dev/null\n        addEmulator $def \"$md_id\" \"$sys\" \"$md_inst/flycast_libretro.so </dev/null\"\n        addSystem \"$sys\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    for sys in \"arcade\" \"dreamcast\"; do\n        mkRomDir \"$sys\"\n        defaultRAConfig \"$sys\"\n    done\n\n    mkUserDir \"$biosdir/dc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-flycast.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-flycast\"\nrp_module_desc=\"Dreamcast emulator - Reicast port for libretro\"\nrp_module_help=\"Previously named lr-reicast then lr-beetle-dc\\n\\nDreamcast ROM Extensions: .cdi .gdi .chd .m3u, Naomi/Atomiswave ROM Extension: .zip\\n\\nCopy your Dreamcast/Naomi roms to $romdir/dreamcast\\n\\nCopy the required Dreamcast BIOS files dc_boot.bin and dc_flash.bin to $biosdir/dc\\n\\nCopy the required Naomi/Atomiswave BIOS files naomi.zip and awbios.zip to $biosdir/dc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/flycast/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/flycast.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!armv6\"\n\nfunction depends_lr-flycast() {\n    local depends=(zlib1g-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction _update_hook_lr-flycast() {\n    renameModule \"lr-reicast\" \"lr-beetle-dc\"\n    renameModule \"lr-beetle-dc\" \"lr-flycast\"\n}\n\nfunction sources_lr-flycast() {\n    gitPullOrClone\n    # don't override our C/CXXFLAGS and set LDFLAGS to CFLAGS to avoid warnings on linking\n    applyPatch \"$md_data/01_flags_fix.diff\"\n}\n\nfunction build_lr-flycast() {\n    local params=(\"HAVE_LTCG=0\")\n    local add_flags=()\n    if isPlatform \"gles\"; then\n        if isPlatform \"videocore\"; then\n            params+=(\n                \"GLES=1\"\n                \"GL_LIB=-L/opt/vc/lib -lbrcmGLESv2\")\n            add_flags+=(\"-I/opt/vc/include -DTARGET_NO_STENCIL -DLOW_END\")\n        elif isPlatform \"vero4k\"; then\n            params+=(\"platform=AMLGXL\" \"ARCH=arm\" \"ARMV7A_FLAGS=1\")\n        else\n            params+=(\"FORCE_GLES=1\")\n        fi\n        if isPlatform \"gles3\"; then\n            params+=(\"HAVE_GL3=1\")\n        else\n            params+=(\"HAVE_GL3=0\")\n        fi\n    fi\n    isPlatform \"aarch64\" && params+=(\"WITH_DYNAREC=arm64\" \"HOST_CPU_FLAGS=-DTARGET_LINUX_ARMv8\")\n    isPlatform \"arm\" && params+=(\"WITH_DYNAREC=arm\")\n    ! isPlatform \"x86\" && params+=(\"HAVE_GENERIC_JIT=0\")\n    isPlatform \"vulkan\" && params+=(\"HAVE_VULKAN=1\") || params+=(\"HAVE_VULKAN=0\")\n    make \"${params[@]}\" clean\n    CFLAGS+=\" ${add_flags[@]}\" make \"${params[@]}\"\n    md_ret_require=\"$md_build/flycast_libretro.so\"\n}\n\nfunction install_lr-flycast() {\n    md_ret_files=(\n        'flycast_libretro.so'\n        'LICENSE'\n    )\n}\n\nfunction configure_lr-flycast() {\n    local sys\n    local systems=(dreamcast arcade)\n    local def\n    for sys in \"${systems[@]}\"; do\n        def=0\n        if isPlatform \"kms\" && [[ \"$sys\" == \"dreamcast\" ]]; then\n            def=1\n        fi\n        # segfaults on the rpi without redirecting stdin from </dev/null\n        addEmulator $def \"$md_id\" \"$sys\" \"$md_inst/flycast_libretro.so </dev/null\"\n        addSystem \"$sys\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local params=()\n    # system-specific\n    if isPlatform \"gl\"; then\n        params+=(\"video_shared_context\" \"true\")\n    fi\n\n    for sys in \"${systems[@]}\"; do\n        mkRomDir \"$sys\"\n        defaultRAConfig \"$sys\" \"${params[@]}\"\n    done\n\n    mkUserDir \"$biosdir/dc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-fmsx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-fmsx\"\nrp_module_desc=\"MSX/MSX2 emu - fMSX port for libretro\"\nrp_module_help=\"ROM Extensions: .rom .mx1 .mx2 .col .dsk .zip\\n\\nCopy the fmsx BIOS files to '$biosdir'\\n\\nCopy your MSX/MSX2 games to $romdir/msx\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/fmsx-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/fmsx-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-fmsx() {\n    gitPullOrClone\n}\n\nfunction build_lr-fmsx() {\n    make clean\n    make\n    md_ret_require=\"$md_build/fmsx_libretro.so\"\n}\n\nfunction install_lr-fmsx() {\n    md_ret_files=(\n        'fmsx_libretro.so'\n        'README.md'\n        'fMSX/ROMs/CARTS.SHA'\n    )\n}\n\nfunction configure_lr-fmsx() {\n    mkRomDir \"msx\"\n    defaultRAConfig \"msx\"\n\n    # default to MSX2+ core\n    setRetroArchCoreOption \"fmsx_mode\" \"MSX2+\"\n\n    addEmulator 0 \"$md_id\" \"msx\" \"$md_inst/fmsx_libretro.so\"\n    addSystem \"msx\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # Copy CARTS.SHA to $biosdir\n    cp \"$md_inst/CARTS.SHA\" \"$biosdir/\"\n    chown \"$__user\":\"$__group\" \"$biosdir/CARTS.SHA\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-freechaf.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-freechaf\"\nrp_module_desc=\"ChannelF emulator for libretro\"\nrp_module_help=\"ROM Extensions: .bin .rom\\n\\nCopy your ChannelF roms to $romdir/channelf\\n\\nCopy the required BIOS files sl31245.bin and sl31253.bin or sl90025.bin to $biosdir\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/FreeChaF/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/FreeChaF.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-freechaf() {\n    gitPullOrClone\n}\n\nfunction build_lr-freechaf() {\n    make clean\n    make\n    md_ret_require=\"$md_build/freechaf_libretro.so\"\n}\n\nfunction install_lr-freechaf() {\n    md_ret_files=(\n        'freechaf_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-freechaf() {\n    mkRomDir \"channelf\"\n    defaultRAConfig \"channelf\"\n\n    addEmulator 1 \"$md_id\" \"channelf\" \"$md_inst/freechaf_libretro.so\"\n    addSystem \"channelf\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-freeintv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-freeintv\"\nrp_module_desc=\"Intellivision emulator for libretro\"\nrp_module_help=\"ROM Extensions: .int .bin\\n\\nCopy your Intellivision roms to $romdir/intellivision\\n\\nCopy the required BIOS files exec.bin and grom.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/FreeIntv/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/FreeIntv.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-freeintv() {\n    gitPullOrClone\n}\n\nfunction build_lr-freeintv() {\n    make clean\n    make\n    md_ret_require=\"$md_build/freeintv_libretro.so\"\n}\n\nfunction install_lr-freeintv() {\n    md_ret_files=(\n        'freeintv_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-freeintv() {\n    mkRomDir \"intellivision\"\n    defaultRAConfig \"intellivision\"\n\n    addEmulator 1 \"$md_id\" \"intellivision\" \"$md_inst/freeintv_libretro.so\"\n    addSystem \"intellivision\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-fuse.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-fuse\"\nrp_module_desc=\"ZX Spectrum emu - Fuse port for libretro\"\nrp_module_help=\"ROM Extensions: .sna .szx .z80 .tap .tzx .gz .udi .mgt .img .trd .scl .dsk .zip\\n\\nCopy your ZX Spectrum games to $romdir/zxspectrum\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/fuse-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/fuse-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-fuse() {\n    gitPullOrClone\n}\n\nfunction build_lr-fuse() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/fuse_libretro.so\"\n}\n\nfunction install_lr-fuse() {\n    md_ret_files=(\n        'fuse_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-fuse() {\n    mkRomDir \"zxspectrum\"\n    defaultRAConfig \"zxspectrum\"\n\n    # default to 128k spectrum\n    setRetroArchCoreOption \"fuse_machine\" \"Spectrum 128K\"\n\n    addEmulator 1 \"$md_id\" \"zxspectrum\" \"$md_inst/fuse_libretro.so\"\n    addSystem \"zxspectrum\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-gambatte/default.pal",
    "content": "[General]\r\nBackground0=10140443\r\nBackground1=9087769\r\nBackground2=3105072\r\nBackground3=931599\r\nSprite%2010=10140443\r\nSprite%2011=9087769\r\nSprite%2012=3105072\r\nSprite%2013=931599\r\nSprite%2020=10140443\r\nSprite%2021=9087769\r\nSprite%2022=3105072\r\nSprite%2023=931599\r\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-gambatte.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-gambatte\"\nrp_module_desc=\"Gameboy Color emu - libgambatte port for libretro\"\nrp_module_help=\"ROM Extensions: .gb .gbc .zip\\n\\nCopy your GameBoy roms to $romdir/gb\\n\\nCopy your GameBoy Color roms to $romdir/gbc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/gambatte-libretro/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/gambatte-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-gambatte() {\n    gitPullOrClone\n}\n\nfunction build_lr-gambatte() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/gambatte_libretro.so\"\n}\n\nfunction install_lr-gambatte() {\n    md_ret_files=(\n        'COPYING'\n        'changelog'\n        'README.md'\n        'gambatte_libretro.so'\n    )\n}\n\nfunction configure_lr-gambatte() {\n    # add default green yellow palette for gameboy classic\n    mkUserDir \"$biosdir/palettes\"\n    cp \"$md_data/default.pal\" \"$biosdir/palettes/\"\n    chown \"$__user\":\"$__group\" \"$biosdir/palettes/default.pal\"\n    setRetroArchCoreOption \"gambatte_gb_colorization\" \"custom\"\n\n    mkRomDir \"gbc\"\n    mkRomDir \"gb\"\n    defaultRAConfig \"gb\"\n    defaultRAConfig \"gbc\"\n    addEmulator 1 \"$md_id\" \"gb\" \"$md_inst/gambatte_libretro.so\"\n    addEmulator 1 \"$md_id\" \"gbc\" \"$md_inst/gambatte_libretro.so\"\n    addSystem \"gb\"\n    addSystem \"gbc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-geargrafx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-geargrafx\"\nrp_module_desc=\"PC Engine/TurboGrafx-16/SuperGrafx/PCE CD-ROM² emulator\"\nrp_module_help=\"ROM Extensions: .7z .chd .cue .pce .sgx .zip\\n\\nCopy your PC Engine roms to $romdir/pcengine\\n\\nCopy the required BIOS files syscard3.pce and gexpress.pce to $biosdir\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/drhelius/Geargrafx/refs/heads/main/LICENSE\"\nrp_module_repo=\"git https://github.com/drhelius/Geargrafx.git main\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-geargrafx() {\n    gitPullOrClone\n}\n\nfunction build_lr-geargrafx() {\n    make -C platforms/libretro clean\n    make -C platforms/libretro\n    md_ret_require=\"$md_build/platforms/libretro/geargrafx_libretro.so\"\n}\n\nfunction install_lr-geargrafx() {\n    md_ret_files=(\n        'platforms/libretro/geargrafx_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-geargrafx() {\n    mkRomDir \"pcengine\"\n    defaultRAConfig \"pcengine\"\n\n    addEmulator 0 \"$md_id\" \"pcengine\" \"$md_inst/geargrafx_libretro.so\"\n    addSystem \"pcengine\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-gearsystem.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-gearsystem\"\nrp_module_desc=\"Sega 8 bit emu - Gearsystem port for libretro\"\nrp_module_help=\"ROM Extensions: .gg .sg .sms .bin .zip\\nCopy your Game Gear roms to $romdir/gamegear\\nMasterSystem roms to $romdir/mastersystem\\nSG-1000 roms to $romdir/sg-1000\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/drhelius/Gearsystem/master/LICENSE\"\nrp_module_repo=\"git https://github.com/drhelius/Gearsystem.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-gearsystem() {\n    gitPullOrClone\n}\n\nfunction build_lr-gearsystem() {\n    cd platforms/libretro\n    make clean\n    make\n    md_ret_require=\"$md_build/platforms/libretro/gearsystem_libretro.so\"\n}\n\nfunction install_lr-gearsystem() {\n    md_ret_files=(\n        'platforms/libretro/gearsystem_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-gearsystem() {\n    local system\n    for system in gamegear mastersystem sg-1000; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/gearsystem_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-genesis-plus-gx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-genesis-plus-gx\"\nrp_module_desc=\"Sega 8/16 bit emu - Genesis Plus (enhanced) port for libretro\"\nrp_module_help=\"ROM Extensions: .bin .cue .gen .gg .iso .md .sg .smd .sms .zip\\nCopy your Game Gear roms to $romdir/gamegear\\nMasterSystem roms to $romdir/mastersystem\\nMegadrive / Genesis roms to $romdir/megadrive\\nSG-1000 roms to $romdir/sg-1000\\nSegaCD roms to $romdir/segacd\\nThe Sega CD requires the BIOS files bios_CD_U.bin and bios_CD_E.bin and bios_CD_J.bin copied to $biosdir\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/Genesis-Plus-GX/master/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/libretro/Genesis-Plus-GX.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-genesis-plus-gx() {\n    gitPullOrClone\n}\n\nfunction build_lr-genesis-plus-gx() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/genesis_plus_gx_libretro.so\"\n}\n\nfunction install_lr-genesis-plus-gx() {\n    md_ret_files=(\n        'genesis_plus_gx_libretro.so'\n        'HISTORY.txt'\n        'LICENSE.txt'\n        'README.md'\n    )\n}\n\nfunction configure_lr-genesis-plus-gx() {\n    local system\n    local def\n    for system in gamegear mastersystem megadrive sg-1000 segacd; do\n        def=0\n        [[ \"$system\" == \"gamegear\" || \"$system\" == \"sg-1000\" ]] && def=1\n        # always default emulator for non armv6\n        ! isPlatform \"armv6\" && def=1\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator \"$def\" \"$md_id\" \"$system\" \"$md_inst/genesis_plus_gx_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-gpsp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-gpsp\"\nrp_module_desc=\"GBA emu - gpSP port for libretro\"\nrp_module_help=\"ROM Extensions: .gba .zip\\n\\nCopy your Game Boy Advance roms to $romdir/gba\\n\\nCopy the required BIOS file gba_bios.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/gpsp/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/gpsp.git master\"\nrp_module_section=\"opt arm=main\"\nrp_module_flags=\"\"\n\nfunction sources_lr-gpsp() {\n    gitPullOrClone\n}\n\nfunction build_lr-gpsp() {\n    rpSwap on 512\n    local params=()\n    isPlatform \"arm\" && params+=(platform=armv)\n    make \"${params[@]}\" clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/gpsp_libretro.so\"\n}\n\nfunction install_lr-gpsp() {\n    md_ret_files=(\n        'gpsp_libretro.so'\n        'COPYING'\n        'original_readme.txt'\n        'README.md'\n    )\n}\n\nfunction configure_lr-gpsp() {\n    mkRomDir \"gba\"\n    defaultRAConfig \"gba\"\n\n    local def=0\n    isPlatform \"armv6\" && def=1\n    addEmulator $def \"$md_id\" \"gba\" \"$md_inst/gpsp_libretro.so\"\n    addSystem \"gba\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-gw.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-gw\"\nrp_module_desc=\"Game and Watch simulator\"\nrp_module_help=\"ROM Extension: .mgw\\n\\nCopy your Game and Watch games to $romdir/gameandwatch\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/libretro/gw-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/gw-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-gw() {\n    gitPullOrClone\n}\n\nfunction build_lr-gw() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/gw_libretro.so\"\n}\n\nfunction install_lr-gw() {\n    md_ret_files=(\n        'gw_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-gw() {\n    mkRomDir \"gameandwatch\"\n    defaultRAConfig \"gameandwatch\"\n\n    addEmulator 1 \"$md_id\" \"gameandwatch\" \"$md_inst/gw_libretro.so\"\n    addSystem \"gameandwatch\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-handy.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-handy\"\nrp_module_desc=\"Atari Lynx emulator - Handy port for libretro\"\nrp_module_help=\"ROM Extensions: .lnx .zip\\n\\nCopy your Atari Lynx roms to $romdir/atarilynx\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/libretro/libretro-handy/master/lynx/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/libretro-handy.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-handy() {\n    gitPullOrClone\n}\n\nfunction build_lr-handy() {\n    make clean\n    make\n    md_ret_require=\"$md_build/handy_libretro.so\"\n}\n\nfunction install_lr-handy() {\n    md_ret_files=(\n        'handy_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-handy() {\n    mkRomDir \"atarilynx\"\n    defaultRAConfig \"atarilynx\"\n\n    addEmulator 1 \"$md_id\" \"atarilynx\" \"$md_inst/handy_libretro.so\"\n    addSystem \"atarilynx\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-hatari/01_libcapsimage.diff",
    "content": "diff --git a/Makefile.libretro b/Makefile.libretro\nindex 58e33e4..eb654c6 100755\n--- a/Makefile.libretro\n+++ b/Makefile.libretro\n@@ -225,7 +225,7 @@ $(TARGET): $(OBJECTS)\n ifeq ($(STATIC_LINKING_LINK),1)\r\n \t$(AR) rcs $@ $(OBJECTS) \r\n else\r\n-\t$(CC) $(CFLAGS) $(INCFLAGS) $(LDFLAGS) $(OBJECTS) -o $@ -lm $(ZLIB) $(SHARED)\r\n+\t$(CC) $(CFLAGS) $(INCFLAGS) $(LDFLAGS) $(OBJECTS) -o $@ -lm $(ZLIB) $(SHARED) $(CAPSIMG_LDFLAGS)\r\n endif\r\n \r\n %.o: %.c\r\ndiff --git a/src/floppy_ipf.c b/src/floppy_ipf.c\nindex c615b75..3626c19 100644\n--- a/src/floppy_ipf.c\n+++ b/src/floppy_ipf.c\n@@ -24,6 +24,7 @@ const char floppy_ipf_fileid[] = \"Hatari floppy_ipf.c : \" __DATE__ \" \" __TIME__;\n #include \"screen.h\"\n #include \"video.h\"\n #include \"cycles.h\"\n+#include \"inttypes.h\"\n \n #ifdef HAVE_CAPSIMAGE\n #if CAPSIMAGE_VERSION == 5\n@@ -46,7 +47,7 @@ typedef struct\n \n \tstruct CapsFdc\t\tFdc;\t\t\t\t/* Fdc state */\n \tstruct CapsDrive \tDrive[ MAX_FLOPPYDRIVES ];\t/* Physical drives */\n-\tCapsLong\t\tCapsImage[ MAX_FLOPPYDRIVES ];\t/* For the IPF disk images */\n+\tSint32\t\tCapsImage[ MAX_FLOPPYDRIVES ];\t/* For the IPF disk images */\n \n \tint\t\t\tRev_Track[ MAX_FLOPPYDRIVES ];\t/* Needed to handle CAPSSetRevolution for type II/III commands */\n \tint\t\t\tRev_Side[ MAX_FLOPPYDRIVES ];\n@@ -63,9 +64,9 @@ static IPF_STRUCT\tIPF_State;\t\t\t/* All variables related to the IPF support */\n \n \n #ifdef HAVE_CAPSIMAGE\n-static void\tIPF_CallBack_Trk ( struct CapsFdc *pc , CapsULong State );\n-static void\tIPF_CallBack_Irq ( struct CapsFdc *pc , CapsULong State );\n-static void\tIPF_CallBack_Drq ( struct CapsFdc *pc , CapsULong State );\n+static void\tIPF_CallBack_Trk ( struct CapsFdc *pc , Uint32 State );\n+static void\tIPF_CallBack_Irq ( struct CapsFdc *pc , Uint32 State );\n+static void\tIPF_CallBack_Drq ( struct CapsFdc *pc , Uint32 State );\n static void\tIPF_Drive_Update_Enable_Side ( void );\n #endif\n \n@@ -317,8 +318,8 @@ bool\tIPF_Insert ( int Drive , Uint8 *pImageBuffer , long ImageSize )\n \treturn false;\n \n #else\n-\tCapsLong\tImageId;\n-\tCapsLong\tImageType;\n+\tSint32\tImageId;\n+\tSint32\tImageType;\n \n \tImageId = CAPSAddImage();\n \tif ( ImageId < 0 )\n@@ -351,7 +352,7 @@ bool\tIPF_Insert ( int Drive , Uint8 *pImageBuffer , long ImageSize )\n \t}\n #endif\n \n-\tif ( CAPSLockImageMemory ( ImageId , pImageBuffer , (CapsULong)ImageSize , DI_LOCK_MEMREF ) == imgeOk )\n+\tif ( CAPSLockImageMemory ( ImageId , pImageBuffer , (Uint32)ImageSize , DI_LOCK_MEMREF ) == imgeOk )\n \t{\n \t\tstruct CapsImageInfo cii;\n \t\tint\t\ti;\n@@ -467,7 +468,7 @@ void IPF_Reset ( void )\n  * We need to update the track data by calling CAPSLockTrack\n  */\n #ifdef HAVE_CAPSIMAGE\n-static void\tIPF_CallBack_Trk ( struct CapsFdc *pc , CapsULong State )\n+static void\tIPF_CallBack_Trk ( struct CapsFdc *pc , Uint32 State )\n {\n \tint\tDrive = State;\t\t\t\t/* State is the drive number in that case */\n \tstruct CapsDrive *pd = pc->drive+Drive;\t\t/* Current drive where the track change occurred */\n@@ -496,7 +497,7 @@ static void\tIPF_CallBack_Trk ( struct CapsFdc *pc , CapsULong State )\n  * Callback function used when the FDC change the IRQ signal\n  */\n #ifdef HAVE_CAPSIMAGE\n-static void\tIPF_CallBack_Irq ( struct CapsFdc *pc , CapsULong State )\n+static void\tIPF_CallBack_Irq ( struct CapsFdc *pc , Uint32 State )\n {\n \tLOG_TRACE(TRACE_FDC, \"fdc ipf callback irq state=0x%x VBL=%d HBL=%d\\n\" , (int)State , nVBLs , nHBL );\n \n@@ -515,7 +516,7 @@ static void\tIPF_CallBack_Irq ( struct CapsFdc *pc , CapsULong State )\n  * -> copy the byte to/from the DMA's FIFO if it's a read or a write to the disk\n  */\n #ifdef HAVE_CAPSIMAGE\n-static void\tIPF_CallBack_Drq ( struct CapsFdc *pc , CapsULong State )\n+static void\tIPF_CallBack_Drq ( struct CapsFdc *pc , Uint32 State )\n {\n \tUint8\tByte;\n \n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-hatari.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-hatari\"\nrp_module_desc=\"Atari emulator - Hatari port for libretro\"\nrp_module_help=\"ROM Extensions: .st .stx .img .rom .raw .ipf .ctr .zip\\n\\nCopy your Atari ST games to $romdir/atarist\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/hatari/master/gpl.txt\"\nrp_module_repo=\"git https://github.com/libretro/hatari.git master\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-hatari() {\n    getDepends zlib1g-dev\n}\n\nfunction sources_lr-hatari() {\n    gitPullOrClone\n    applyPatch \"$md_data/01_libcapsimage.diff\"\n    _sources_libcapsimage_hatari\n}\n\nfunction build_lr-hatari() {\n    _build_libcapsimage_hatari\n\n    cd \"$md_build\"\n    CFLAGS+=\" -D__cdecl='' -I\\\"$md_build/src/includes/caps\\\" -DHAVE_CAPSIMAGE=1 -DCAPSIMAGE_VERSION=5\" CAPSIMG_LDFLAGS=\"-L./lib -l:libcapsimage.so.5.1\" make -f Makefile.libretro\n    md_ret_require=\"$md_build/hatari_libretro.so\"\n}\n\nfunction install_lr-hatari() {\n    _install_libcapsimage_hatari\n    md_ret_files=(\n        'hatari_libretro.so'\n        'readme.txt'\n        'gpl.txt'\n    )\n}\n\nfunction configure_lr-hatari() {\n    mkRomDir \"atarist\"\n    defaultRAConfig \"atarist\"\n\n    # move any old configs to new location\n    moveConfigDir \"$home/.hatari\" \"$md_conf_root/atarist\"\n\n    addEmulator 1 \"$md_id\" \"atarist\" \"$md_inst/hatari_libretro.so\"\n    addSystem \"atarist\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # add LD_LIBRARY_PATH='$md_inst' to start of launch command\n    iniConfig \" = \" '\"' \"$configdir/atarist/emulators.cfg\"\n    iniGet \"$md_id\"\n    iniSet \"$md_id\" \"LD_LIBRARY_PATH='$md_inst' $ini_value\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-kronos.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-kronos\"\nrp_module_desc=\"Saturn & ST-V emulator - Kronos port for libretro\"\nrp_module_help=\"ROM Extensions: .iso .cue .zip .ccd .mds\\n\\nCopy your Sega Saturn & ST-V roms to $romdir/saturn\\n\\nCopy the required BIOS file saturn_bios.bin / stvbios.zip to $biosdir/kronos\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/yabause/kronos/yabause/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/yabause.git kronos\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!arm !aarch64\"\n\nfunction sources_lr-kronos() {\n    gitPullOrClone\n}\n\nfunction build_lr-kronos() {\n    cd yabause/src/libretro\n    make clean\n    make\n    md_ret_require=\"$md_build/yabause/src/libretro/kronos_libretro.so\"\n}\n\nfunction install_lr-kronos() {\n    md_ret_files=(\n        'yabause/src/libretro/kronos_libretro.so'\n        'yabause/AUTHORS'\n        'yabause/COPYING'\n        'yabause/ChangeLog'\n        'yabause/GOALS'\n        'yabause/README'\n        'yabause/README.LIN'\n    )\n}\n\nfunction configure_lr-kronos() {\n    mkRomDir \"saturn\"\n    defaultRAConfig \"saturn\"\n\n    addEmulator 1 \"$md_id\" \"saturn\" \"$md_inst/kronos_libretro.so\"\n    addSystem \"saturn\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame\"\nrp_module_desc=\"MAME emulator - MAME (current) port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mame/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/mame.git :_get_version_lr-mame\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!:\\$__gcc_version:-lt:7\"\n\nfunction _get_version_lr-mame() {\n    if compareVersions \"$(gcc -dumpfullversion)\" lt 10.3.0; then\n        echo \"lrmame0264\"\n    fi\n}\nfunction _get_params_lr-mame() {\n    local params=(OSD=retro RETRO=1 PYTHON_EXECUTABLE=python3 NOWERROR=1 OS=linux OPTIMIZE=2 TARGETOS=linux CONFIG=libretro NO_USE_MIDI=1 NO_USE_PORTAUDIO=1 TARGET=mame)\n    isPlatform \"64bit\" && params+=(PTR64=1)\n    # force arm on arm platform - fixes building mame on when using 32bit arm userland with aarch64 kernel\n    isPlatform \"arm\" && params+=(PLATFORM=arm)\n    echo \"${params[@]}\"\n}\n\nfunction depends_lr-mame() {\n    local depends=(libasound2-dev)\n    isPlatform \"gles\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"gl\" && depends+=(libglu1-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-mame() {\n    gitPullOrClone\n}\n\nfunction build_lr-mame() {\n    if isPlatform \"64bit\"; then\n        rpSwap on 10240\n    else\n        rpSwap on 6144\n    fi\n    local params=($(_get_params_lr-mame) SUBTARGET=arcade)\n    make clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/mamearcade_libretro.so\"\n}\n\nfunction install_lr-mame() {\n    md_ret_files=(\n        'COPYING'\n        'mamearcade_libretro.so'\n        'README.md'\n        'plugins'\n    )\n}\n\nfunction configure_lr-mame() {\n    local system\n    for system in arcade mame-libretro; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mamearcade_libretro.so\"\n        addSystem \"$system\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    mkUserDir \"$biosdir/mame\"\n    mkUserDir \"$biosdir/mame/ini\"\n\n    # Create new INI files if they do not already exist\n\n    # Create mame.ini\n    local temp_ini_mame=\"$(mktemp)\"\n    iniConfig \" \" \"\" \"$temp_ini_mame\"\n    iniSet \"pluginspath\" \"$biosdir/mame/plugins\"\n    copyDefaultConfig \"$temp_ini_mame\" \"$biosdir/mame/ini/mame.ini\"\n\n    # Create plugin.ini\n    local temp_ini_plugin=\"$(mktemp)\"\n    iniConfig \" \" \"\" \"$temp_ini_plugin\"\n    iniSet \"hiscore\" \"1\"\n    copyDefaultConfig \"$temp_ini_plugin\" \"$biosdir/mame/ini/plugin.ini\"\n\n    # Copy plugins to BIOS directory\n    cp -R \"$md_inst/plugins\" \"$biosdir/mame/\"\n\n    # Set permissions\n    chown \"$__user\":\"$__group\" -R \"$biosdir/mame/\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2000.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2000\"\nrp_module_desc=\"Arcade emu - MAME 0.37b5 port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME 0.37b5 roms to either $romdir/mame-mame4all or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/mame2000-libretro/master/readme.txt\"\nrp_module_repo=\"git https://github.com/libretro/mame2000-libretro.git master\"\nrp_module_section=\"opt armv6=main\"\n\nfunction _update_hook_lr-mame2000() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-imame4all\" \"lr-mame2000\"\n}\n\nfunction sources_lr-mame2000() {\n    gitPullOrClone\n}\n\nfunction build_lr-mame2000() {\n    make clean\n    local params=()\n    isPlatform \"arm\" && params+=(\"ARM=1\" \"USE_CYCLONE=1\")\n    isPlatform \"aarch64\" && params+=(\"IS_X86=0\")\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/mame2000_libretro.so\"\n}\n\nfunction install_lr-mame2000() {\n    md_ret_files=(\n        'mame2000_libretro.so'\n        'readme.md'\n        'readme.txt'\n        'whatsnew.txt'\n    )\n}\n\nfunction configure_lr-mame2000() {\n    local system\n    for system in arcade mame-mame4all mame-libretro; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mame2000_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2003-plus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2003-plus\"\nrp_module_desc=\"Arcade emu - updated MAME 0.78 port for libretro with added game support\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/mame2003-plus-libretro/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/mame2003-plus-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction _get_dir_name_lr-mame2003-plus() {\n    echo \"mame2003-plus\"\n}\n\nfunction _get_so_name_lr-mame2003-plus() {\n    echo \"mame2003_plus\"\n}\n\nfunction sources_lr-mame2003-plus() {\n    gitPullOrClone\n}\n\nfunction build_lr-mame2003-plus() {\n    build_lr-mame2003\n}\n\nfunction install_lr-mame2003-plus() {\n    install_lr-mame2003\n}\n\nfunction configure_lr-mame2003-plus() {\n    configure_lr-mame2003\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2003.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2003\"\nrp_module_desc=\"Arcade emu - MAME 0.78 port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/mame2003-libretro/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/mame2003-libretro.git master\"\nrp_module_section=\"main armv6=opt\"\n\nfunction _get_dir_name_lr-mame2003() {\n    echo \"mame2003\"\n}\n\nfunction _get_so_name_lr-mame2003() {\n    echo \"mame2003\"\n}\n\nfunction sources_lr-mame2003() {\n    gitPullOrClone\n}\n\nfunction build_lr-mame2003() {\n    rpSwap on 750\n    make clean\n    local params=()\n    isPlatform \"arm\" && params+=(\"ARM=1\")\n    make ARCH=\"$CFLAGS\" \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/$(_get_so_name_${md_id})_libretro.so\"\n}\n\nfunction install_lr-mame2003() {\n    md_ret_files=(\n        \"$(_get_so_name_${md_id})_libretro.so\"\n        'README.md'\n        'CHANGELOG.md'\n        'metadata'\n    )\n}\n\nfunction configure_lr-mame2003() {\n    local so_name=\"$(_get_so_name_${md_id})\"\n    addEmulator 0 \"$md_id\" \"arcade\" \"$md_inst/${so_name}_libretro.so\"\n    addEmulator 1 \"$md_id\" \"mame-libretro\" \"$md_inst/${so_name}_libretro.so\"\n    addSystem \"arcade\"\n    addSystem \"mame-libretro\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local dir_name=\"$(_get_dir_name_${md_id})\"\n\n    local mame_dir\n    local mame_sub_dir\n    for mame_dir in arcade mame-libretro; do\n        mkRomDir \"$mame_dir\"\n        mkRomDir \"$mame_dir/$dir_name\"\n        defaultRAConfig \"$mame_dir\"\n\n        for mame_sub_dir in cfg ctrlr diff hi memcard nvram; do\n            mkRomDir \"$mame_dir/$dir_name/$mame_sub_dir\"\n        done\n    done\n\n    mkUserDir \"$biosdir/$dir_name\"\n    mkUserDir \"$biosdir/$dir_name/samples\"\n\n    # copy hiscore.dat and cheat.dat\n    cp \"$md_inst/metadata/\"{hiscore.dat,cheat.dat} \"$biosdir/$dir_name/\"\n    chown \"$__user\":\"$__group\" \"$biosdir/$dir_name/\"{hiscore.dat,cheat.dat}\n\n    # lr-mame2003-plus also has an artwork folder\n    if [[ \"$md_id\" == \"lr-mame2003-plus\" ]]; then\n        mkUserDir \"$biosdir/$dir_name/artwork\"\n        cp \"$md_inst/metadata/artwork/\"* \"$biosdir/$dir_name/artwork/\"\n        chown -R \"$__user\":\"$__group\" \"$biosdir/$dir_name/artwork\"\n    fi\n\n    # Set core options\n    setRetroArchCoreOption \"${dir_name}_skip_disclaimer\" \"enabled\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2010.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2010\"\nrp_module_desc=\"Arcade emu - MAME 0.139 port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/mame2010-libretro/master/docs/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/mame2010-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction depends_lr-mame2010() {\n    getDepends zlib1g-dev\n}\n\nfunction sources_lr-mame2010() {\n    gitPullOrClone\n}\n\nfunction build_lr-mame2010() {\n    rpSwap on 750\n    make clean\n    local params=()\n    ! isPlatform \"x86\" && params+=(\"VRENDER=soft\" \"FORCE_DRC_C_BACKEND=1\")\n    # ARM_ENABLED flag is only used in osinline.h for the YieldProcessor macro and is needed also for aarch64\n    if isPlatform \"arm\" || isPlatform \"aarch64\"; then\n        params+=(\"ARM_ENABLED=1\")\n    fi\n    isPlatform \"64bit\" && params+=(\"PTR64=1\")\n    make \"${params[@]}\" ARCHOPTS=\"$CFLAGS\" buildtools\n    make \"${params[@]}\" ARCHOPTS=\"$CFLAGS\"\n    rpSwap off\n    md_ret_require=\"$md_build/mame2010_libretro.so\"\n}\n\nfunction install_lr-mame2010() {\n    md_ret_files=(\n        'mame2010_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-mame2010() {\n    local system\n    for system in arcade mame-libretro; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mame2010_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2015/01-python3-irgen.diff",
    "content": "diff --git a/src/emu/cpu/m6502/m6502make.py b/src/emu/cpu/m6502/m6502make.py\nindex da29fc7..3de641d 100755\n--- a/src/emu/cpu/m6502/m6502make.py\n+++ b/src/emu/cpu/m6502/m6502make.py\n@@ -16,7 +16,7 @@ def load_opcodes(fname):\n     opcodes = []\n     logging.info(\"load_opcodes: %s\", fname)\n     try:\n-        f = open(fname, \"rU\")\n+        f = open(fname, \"r\")\n     except Exception:\n         err = sys.exc_info()[1]\n         logging.error(\"cannot read opcodes file %s [%s]\", fname, err)\n@@ -39,7 +39,7 @@ def load_disp(fname):\n     logging.info(\"load_disp: %s\", fname)\n     states = []\n     try:\n-        f = open(fname, \"rU\")\n+        f = open(fname, \"r\")\n     except Exception:\n         err = sys.exc_info()[1]\n         logging.error(\"cannot read display file %s [%s]\", fname, err)\ndiff --git a/src/emu/cpu/m6809/m6809make.py b/src/emu/cpu/m6809/m6809make.py\nindex c3d5b0f..79f6f90 100644\n--- a/src/emu/cpu/m6809/m6809make.py\n+++ b/src/emu/cpu/m6809/m6809make.py\n@@ -14,7 +14,7 @@ def load_file(fname, lines):\n \tif path != \"\":\n \t\tpath += '/'\n \ttry:\n-\t\tf = open(fname, \"rU\")\n+\t\tf = open(fname, \"r\")\n \texcept Exception:\n \t\terr = sys.exc_info()[1]\n \t\tsys.stderr.write(\"Cannot read opcodes file %s [%s]\\n\" % (fname, err))\ndiff --git a/src/emu/cpu/mcs96/mcs96make.py b/src/emu/cpu/mcs96/mcs96make.py\nindex ec5ec37..7ab806a 100644\n--- a/src/emu/cpu/mcs96/mcs96make.py\n+++ b/src/emu/cpu/mcs96/mcs96make.py\n@@ -71,7 +71,7 @@ class OpcodeList:\n         self.ea = {}\n         self.macros = {}\n         try:\n-            f = open(fname, \"rU\")\n+            f = open(fname, \"r\")\n         except Exception:\n             err = sys.exc_info()[1]\n             sys.stderr.write(\"Cannot read opcodes file %s [%s]\\n\" % (fname, err))\ndiff --git a/src/emu/cpu/tms57002/tmsmake.py b/src/emu/cpu/tms57002/tmsmake.py\nindex 6209209..78f9fe4 100755\n--- a/src/emu/cpu/tms57002/tmsmake.py\n+++ b/src/emu/cpu/tms57002/tmsmake.py\n@@ -326,7 +326,7 @@ def ins_cmp_dasm(a, b):\n def LoadLst(filename):\n     instructions = []\n     ins = None\n-    for n, line in enumerate(open(filename, \"rU\")):\n+    for n, line in enumerate(open(filename, \"r\")):\n         line = line.rstrip()\n         if not line and ins:\n             # new lines separate intructions\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2015.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2015\"\nrp_module_desc=\"Arcade emu - MAME 0.160 port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/mame2015-libretro/master/docs/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/mame2015-libretro.git master\"\nrp_module_section=\"exp\"\n\nfunction _update_hook_lr-mame2015() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-mame2014\" \"lr-mame2015\"\n}\n\nfunction sources_lr-mame2015() {\n    gitPullOrClone\n    applyPatch \"$md_data/01-python3-irgen.diff\"\n}\n\nfunction build_lr-mame2015() {\n    rpSwap on 1200\n    make clean\n    make\n    rpSwap off\n    md_ret_require=\"$md_build/mame2015_libretro.so\"\n}\n\nfunction install_lr-mame2015() {\n    md_ret_files=(\n        'mame2015_libretro.so'\n        'docs/README-original.md'\n        'docs/license.txt'\n    )\n}\n\nfunction configure_lr-mame2015() {\n    local system\n    for system in arcade mame-libretro; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mame2015_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2016/01-python3-irgen.diff",
    "content": "diff --git a/src/devices/cpu/m6502/m6502make.py b/src/devices/cpu/m6502/m6502make.py\nindex 8bcd85f8..557b1759 100755\n--- a/src/devices/cpu/m6502/m6502make.py\n+++ b/src/devices/cpu/m6502/m6502make.py\n@@ -18,7 +18,7 @@ def load_opcodes(fname):\n     opcodes = []\n     logging.info(\"load_opcodes: %s\", fname)\n     try:\n-        f = open(fname, \"rU\")\n+        f = open(fname, \"r\")\n     except Exception:\n         err = sys.exc_info()[1]\n         logging.error(\"cannot read opcodes file %s [%s]\", fname, err)\n@@ -41,7 +41,7 @@ def load_disp(fname):\n     logging.info(\"load_disp: %s\", fname)\n     states = []\n     try:\n-        f = open(fname, \"rU\")\n+        f = open(fname, \"r\")\n     except Exception:\n         err = sys.exc_info()[1]\n         logging.error(\"cannot read display file %s [%s]\", fname, err)\ndiff --git a/src/devices/cpu/m6809/m6809make.py b/src/devices/cpu/m6809/m6809make.py\nindex 8838b960..e1ea25db 100644\n--- a/src/devices/cpu/m6809/m6809make.py\n+++ b/src/devices/cpu/m6809/m6809make.py\n@@ -16,7 +16,7 @@ def load_file(fname, lines):\n \tif path != \"\":\n \t\tpath += '/'\n \ttry:\n-\t\tf = open(fname, \"rU\")\n+\t\tf = open(fname, \"r\")\n \texcept Exception:\n \t\terr = sys.exc_info()[1]\n \t\tsys.stderr.write(\"Cannot read opcodes file %s [%s]\\n\" % (fname, err))\ndiff --git a/src/devices/cpu/mcs96/mcs96make.py b/src/devices/cpu/mcs96/mcs96make.py\nindex b4844942..207208d2 100644\n--- a/src/devices/cpu/mcs96/mcs96make.py\n+++ b/src/devices/cpu/mcs96/mcs96make.py\n@@ -73,7 +73,7 @@ class OpcodeList:\n         self.ea = {}\n         self.macros = {}\n         try:\n-            f = open(fname, \"rU\")\n+            f = open(fname, \"r\")\n         except Exception:\n             err = sys.exc_info()[1]\n             sys.stderr.write(\"Cannot read opcodes file %s [%s]\\n\" % (fname, err))\ndiff --git a/src/devices/cpu/tms57002/tmsmake.py b/src/devices/cpu/tms57002/tmsmake.py\nindex e2e12b5a..942ec095 100755\n--- a/src/devices/cpu/tms57002/tmsmake.py\n+++ b/src/devices/cpu/tms57002/tmsmake.py\n@@ -323,7 +323,7 @@ class Instruction:\n def LoadLst(filename):\n     instructions = []\n     ins = None\n-    for n, line in enumerate(open(filename, \"rU\")):\n+    for n, line in enumerate(open(filename, \"r\")):\n         line = line.rstrip()\n         if not line and ins:\n             # new lines separate intructions\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mame2016.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mame2016\"\nrp_module_desc=\"MAME emulator - MAME 0.174 port for libretro\"\nrp_module_help=\"ROM Extension: .zip\\n\\nCopy your MAME roms to either $romdir/mame-libretro or\\n$romdir/arcade\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mame2016-libretro/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/mame2016-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_lr-mame2016() {\n    getDepends libasound2-dev\n}\n\nfunction sources_lr-mame2016() {\n    gitPullOrClone\n    applyPatch \"${md_path%/*}/lr-mame2016/01-python3-irgen.diff\"\n}\n\nfunction build_lr-mame2016() {\n    rpSwap on 1200\n    local params=($(_get_params_lr-mame) SUBTARGET=arcade)\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/mamearcade2016_libretro.so\"\n}\n\nfunction install_lr-mame2016() {\n    md_ret_files=(\n        'mamearcade2016_libretro.so'\n    )\n}\n\nfunction configure_lr-mame2016() {\n    local system\n    for system in arcade mame-libretro; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mamearcade2016_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mesen.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mesen\"\nrp_module_desc=\"High-accuracy NES and Famicom emulator\"\nrp_module_help=\"ROM Extensions: .nes .fds .unf .unif .zip\\n\\nCopy your NES roms to $romdir/nes\\nFamicom roms to $romdir/fds\\nCopy the recommended BIOS file disksys.rom to $biosdir\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/sourmesen/mesen/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/Mesen.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-mesen() {\n    gitPullOrClone\n}\n\nfunction build_lr-mesen() {\n    make -C Libretro clean\n    make -C Libretro\n    md_ret_require=\"$md_build/Libretro/mesen_libretro.so\"\n}\n\nfunction install_lr-mesen() {\n    md_ret_files=(\n        'Libretro/mesen_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-mesen() {\n    local system\n    for system in \"nes\" \"fds\"; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/mesen_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mess.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mess\"\nrp_module_desc=\"MESS emulator - MESS Port for libretro\"\nrp_module_help=\"see wiki for detailed explanation\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mame/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/mame.git :_get_version_lr-mame\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_lr-mess() {\n    depends_lr-mame\n}\n\nfunction sources_lr-mess() {\n    gitPullOrClone\n}\n\nfunction build_lr-mess() {\n    if isPlatform \"64bit\"; then\n        rpSwap on 10240\n    else\n        rpSwap on 6144\n    fi\n    local params=($(_get_params_lr-mame) SUBTARGET=mess)\n    make clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/mamemess_libretro.so\"\n}\n\nfunction install_lr-mess() {\n    md_ret_files=(\n        'COPYING'\n        'mamemess_libretro.so'\n        'README.md'\n        'hash'\n    )\n}\n\nfunction configure_lr-mess() {\n    local module=\"$1\"\n    [[ -z \"$module\" ]] && module=\"mamemess_libretro.so\"\n\n    local system\n    for system in nes gb coleco arcadia crvision; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/$module\"\n        addSystem \"$system\"\n    done\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    setRetroArchCoreOption \"mame_softlists_enable\" \"enabled\"\n    setRetroArchCoreOption \"mame_softlists_auto_media\" \"enabled\"\n    setRetroArchCoreOption \"mame_boot_from_cli\" \"enabled\"\n\n    mkUserDir \"$biosdir/mame\"\n    cp -rv \"$md_inst/hash\" \"$biosdir/mame/\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/mame\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mess2016.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mess2016\"\nrp_module_desc=\"MESS emulator - MESS Port for libretro\"\nrp_module_help=\"see wiki for detailed explanation\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mame2016-libretro/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/mame2016-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_lr-mess2016() {\n    depends_lr-mame2016\n}\n\nfunction sources_lr-mess2016() {\n    gitPullOrClone\n    applyPatch \"${md_path%/*}/lr-mame2016/01-python3-irgen.diff\"\n}\n\nfunction build_lr-mess2016() {\n    rpSwap on 1200\n    local params=($(_get_params_lr-mame) SUBTARGET=mess)\n    make clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/mess2016_libretro.so\"\n}\n\nfunction install_lr-mess2016() {\n    md_ret_files=(\n        'mess2016_libretro.so'\n    )\n}\n\nfunction configure_lr-mess2016() {\n    configure_lr-mess \"mess2016_libretro.so\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mgba.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mgba\"\nrp_module_desc=\"(Super) Game Boy Color/GBA emulator - MGBA (optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .gb .gbc .gba .zip\\n\\nCopy your Game Boy roms to $romdir/gb\\nGame Boy Color roms to $romdir/gbc\\nGame Boy Advance roms to $romdir/gba\\n\\nCopy the recommended BIOS files gb_bios.bin, gbc_bios.bin, sgb_bios.bin and gba_bios.bin to $biosdir\"\nrp_module_licence=\"MPL2 https://raw.githubusercontent.com/libretro/mgba/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/mgba.git master\"\nrp_module_section=\"main\"\nrp_module_flags=\"\"\n\nfunction sources_lr-mgba() {\n    gitPullOrClone\n}\n\nfunction build_lr-mgba() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/mgba_libretro.so\"\n}\n\nfunction install_lr-mgba() {\n    md_ret_files=(\n        'mgba_libretro.so'\n        'CHANGES'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-mgba() {\n    local system\n    local def\n    for system in gb gbc gba; do\n        def=0\n        [[ \"$system\" == \"gba\" ]] && ! isPlatform \"armv6\" && def=1\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator \"$def\" \"$md_id\" \"$system\" \"$md_inst/mgba_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mrboom.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mrboom\"\nrp_module_desc=\"Mr.Boom - 8 players Bomberman clone for libretro.\"\nrp_module_help=\"8 players Bomberman clone for libretro.\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/libretro/mrboom-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/mrboom-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-mrboom() {\n    gitPullOrClone\n}\n\nfunction build_lr-mrboom() {\n    rpSwap on 1000\n    make clean\n    if isPlatform \"neon\"; then\n        make HAVE_NEON=1\n    else\n        make\n    fi\n    md_ret_require=\"$md_build/mrboom_libretro.so\"\n}\n\nfunction install_lr-mrboom() {\n    md_ret_files=(\n        'mrboom_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\n\nfunction configure_lr-mrboom() {\n    setConfigRoot \"ports\"\n\n    addPort \"$md_id\" \"mrboom\" \"Mr.Boom\" \"$emudir/retroarch/bin/retroarch -L $md_inst/mrboom_libretro.so --config $md_conf_root/mrboom/retroarch.cfg\"\n\n    mkRomDir \"ports/mrboom\"\n    defaultRAConfig \"mrboom\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mupen64plus/0001-eliminate-conflicting-typedefs.patch",
    "content": "diff --git a/libretro-common/include/glsm/glsm.h b/libretro-common/include/glsm/glsm.h\nindex d422267..ecafdb2 100644\n--- a/libretro-common/include/glsm/glsm.h\n+++ b/libretro-common/include/glsm/glsm.h\n@@ -32,8 +32,8 @@\n RETRO_BEGIN_DECLS\n \n #ifdef HAVE_OPENGLES2\n-typedef GLfloat GLdouble;\n-typedef GLclampf GLclampd;\n+//typedef GLfloat GLdouble;\n+//typedef GLclampf GLclampd;\n #endif\n \n #if defined(HAVE_OPENGLES2)\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mupen64plus/0002-rpi-gles3.patch",
    "content": "--- a/Makefile\n+++ b/Makefile\n@@ -94,7 +94,11 @@ ifneq (,$(findstring unix,$(platform)))\n else ifneq (,$(findstring rpi,$(platform)))\n    TARGET := $(TARGET_NAME)_libretro.so\n    LDFLAGS += -shared -Wl,--version-script=$(LIBRETRO_DIR)/link.T -Wl,--no-undefined\n-   GLES = 1\n+   ifeq ($(FORCE_GLES3),1)\n+      GLES3 = 1\n+   else\n+      GLES = 1\n+   endif\n    ifneq (,$(findstring mesa,$(platform)))\n       GL_LIB := -lGLESv2\n    else\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mupen64plus/0003-fix-fsqrt-conflict.patch",
    "content": "diff --git a/mupen64plus-core/src/r4300/x86/assemble.h b/mupen64plus-core/src/r4300/x86/assemble.h\nindex 19edb19..0cd77aa 100644\n--- a/mupen64plus-core/src/r4300/x86/assemble.h\n+++ b/mupen64plus-core/src/r4300/x86/assemble.h\n@@ -807,7 +807,7 @@ static osal_inline void fmul_preg32_qword(int reg32)\n    put8(0x08 + reg32);\n }\n\n-static osal_inline void fsqrt(void)\n+static osal_inline void fsqrt_(void)\n {\n    put8(0xD9);\n    put8(0xFA);\ndiff --git a/mupen64plus-core/src/r4300/x86/gcop1_d.c b/mupen64plus-core/src/r4300/x86/gcop1_d.c\nindex fadcbb5..519c36e 100644\n--- a/mupen64plus-core/src/r4300/x86/gcop1_d.c\n+++ b/mupen64plus-core/src/r4300/x86/gcop1_d.c\n@@ -96,7 +96,7 @@ void gensqrt_d(void)\n    gencheck_cop1_unusable();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_double[dst->f.cf.fs]));\n    fld_preg32_qword(EAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_double[dst->f.cf.fd]));\n    fstp_preg32_qword(EAX);\n #endif\ndiff --git a/mupen64plus-core/src/r4300/x86/gcop1_s.c b/mupen64plus-core/src/r4300/x86/gcop1_s.c\nindex 699622d..96462c1 100644\n--- a/mupen64plus-core/src/r4300/x86/gcop1_s.c\n+++ b/mupen64plus-core/src/r4300/x86/gcop1_s.c\n@@ -97,7 +97,7 @@ void gensqrt_s(void)\n    gencheck_cop1_unusable();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_simple[dst->f.cf.fs]));\n    fld_preg32_dword(EAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_simple[dst->f.cf.fd]));\n    fstp_preg32_dword(EAX);\n #endif\ndiff --git a/mupen64plus-core/src/r4300/x86_64/assemble.h b/mupen64plus-core/src/r4300/x86_64/assemble.h\nindex 479843a..896233a 100644\n--- a/mupen64plus-core/src/r4300/x86_64/assemble.h\n+++ b/mupen64plus-core/src/r4300/x86_64/assemble.h\n@@ -1154,7 +1154,7 @@ static osal_inline void fmul_preg64_qword(int reg64)\n    put8(0x08 + reg64);\n }\n\n-static osal_inline void fsqrt(void)\n+static osal_inline void fsqrt_(void)\n {\n    put8(0xD9);\n    put8(0xFA);\ndiff --git a/mupen64plus-core/src/r4300/x86_64/gcop1_d.c b/mupen64plus-core/src/r4300/x86_64/gcop1_d.c\nindex af97347..4700206 100644\n--- a/mupen64plus-core/src/r4300/x86_64/gcop1_d.c\n+++ b/mupen64plus-core/src/r4300/x86_64/gcop1_d.c\n@@ -117,7 +117,7 @@ void gensqrt_d(void)\n    gencheck_cop1_unusable();\n    mov_xreg64_m64rel(RAX, (unsigned long long *)(&reg_cop1_double[dst->f.cf.fs]));\n    fld_preg64_qword(RAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_xreg64_m64rel(RAX, (unsigned long long *)(&reg_cop1_double[dst->f.cf.fd]));\n    fstp_preg64_qword(RAX);\n #endif\ndiff --git a/mupen64plus-core/src/r4300/x86_64/gcop1_s.c b/mupen64plus-core/src/r4300/x86_64/gcop1_s.c\nindex 63f4c9e..2f0c01c 100644\n--- a/mupen64plus-core/src/r4300/x86_64/gcop1_s.c\n+++ b/mupen64plus-core/src/r4300/x86_64/gcop1_s.c\n@@ -118,7 +118,7 @@ void gensqrt_s(void)\n    gencheck_cop1_unusable();\n    mov_xreg64_m64rel(RAX, (unsigned long long *)(&reg_cop1_simple[dst->f.cf.fs]));\n    fld_preg64_dword(RAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_xreg64_m64rel(RAX, (unsigned long long *)(&reg_cop1_simple[dst->f.cf.fd]));\n    fstp_preg64_dword(RAX);\n #endif\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mupen64plus-next.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mupen64plus-next\"\nrp_module_desc=\"N64 emulator - Mupen64Plus + GLideN64 for libretro (next version)\"\nrp_module_help=\"ROM Extensions: .z64 .n64 .v64\\n\\nCopy your N64 roms to $romdir/n64\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mupen64plus-libretro-nx/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/mupen64plus-libretro-nx.git develop\"\nrp_module_section=\"opt kms=main\"\nrp_module_flags=\"\"\n\nfunction depends_lr-mupen64plus-next() {\n    local depends=()\n    isPlatform \"x86\" && depends+=(nasm)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-mupen64plus-next() {\n    gitPullOrClone\n}\n\nfunction build_lr-mupen64plus-next() {\n    local params=()\n    if isPlatform \"arm\"; then\n        if isPlatform \"videocore\"; then\n            params+=(platform=\"$__platform\")\n        elif isPlatform \"mesa\"; then\n            params+=(platform=\"$__platform-mesa\")\n        elif isPlatform \"mali\"; then\n            params+=(platform=\"odroid\")\n        fi\n        if isPlatform \"neon\"; then\n            params+=(HAVE_NEON=1)\n        else\n            # force disabling HAVE_NEON on armv6 as makefile sets it for all rpi targets\n            params+=(HAVE_NEON=0)\n        fi\n    fi\n    if isPlatform \"gles3\"; then\n        params+=(FORCE_GLES3=1)\n    elif isPlatform \"gles\"; then\n        params+=(FORCE_GLES=1)\n    fi\n\n    # force ARCH=armv7 on arm platforms to fix building with 32bit arm userland on aarch64 kernel\n    isPlatform \"arm\" && params+=(ARCH=armv7l)\n\n    local add_cflags=()\n\n    # workaround for linkage_arm.S including some armv7 instructions without this\n    isPlatform \"armv6\" && add_cflags+=(-DARMv5_ONLY)\n\n    # fix building on armv8.2 (rpi5) on 32bit arm bookworm.\n    isPlatform \"armv8\" && add_cflags+=(-mfp16-format=ieee)\n\n    # use a custom core name to avoid core option name clashes with lr-mupen64plus\n    params+=(CORE_NAME=mupen64plus-next)\n    make \"${params[@]}\" clean\n\n    CFLAGS=\"$CFLAGS ${add_cflags[*]}\" make \"${params[@]}\"\n\n    md_ret_require=\"$md_build/mupen64plus_next_libretro.so\"\n}\n\nfunction install_lr-mupen64plus-next() {\n    md_ret_files=(\n        'mupen64plus_next_libretro.so'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-mupen64plus-next() {\n    mkRomDir \"n64\"\n    defaultRAConfig \"n64\"\n\n    if isPlatform \"rpi\"; then\n        # Disable hybrid upscaling filter (needs better GPU)\n        setRetroArchCoreOption \"mupen64plus-next-HybridFilter\" \"False\"\n        # Disable overscan/VI emulation (slight performance drain)\n        setRetroArchCoreOption \"mupen64plus-next-EnableOverscan\" \"Disabled\"\n        # Enable Threaded GL calls\n        setRetroArchCoreOption \"mupen64plus-next-ThreadedRenderer\" \"True\"\n    fi\n    setRetroArchCoreOption \"mupen64plus-next-EnableNativeResFactor\" \"1\"\n\n    addEmulator 1 \"$md_id\" \"n64\" \"$md_inst/mupen64plus_next_libretro.so\"\n    addSystem \"n64\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-mupen64plus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-mupen64plus\"\nrp_module_desc=\"N64 emu - Mupen64Plus + GLideN64 for libretro\"\nrp_module_help=\"ROM Extensions: .z64 .n64 .v64\\n\\nCopy your N64 roms to $romdir/n64\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/mupen64plus-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/RetroPie/mupen64plus-libretro.git master\"\nrp_module_section=\"main\"\nrp_module_flags=\"!aarch64\"\n\nfunction _update_hook_lr-mupen64plus() {\n    # retroarch renamed lr-mupen64plus to lr-parallel-n64 and\n    # lr-glupen64 to lr-mupen64plus which makes this a little tricky as an update hook\n\n    # we first need to rename lr-mupen64plus to lr-parallel-n64\n    # (if it's not the lr-glupen64 fork)\n    if [[ -d \"$md_inst\" ]] && ! grep -q \"GLideN64\" \"$md_inst/README.md\"; then\n        renameModule \"lr-mupen64plus\" \"lr-parallel-n64\"\n    fi\n    # then we can rename lr-glupen64 to lr-mupen64plus\n    renameModule \"lr-glupen64\" \"lr-mupen64plus\"\n}\n\nfunction depends_lr-mupen64plus() {\n    local depends=(flex bison libpng-dev)\n    isPlatform \"x11\" && depends+=(libglew-dev libglu1-mesa-dev)\n    isPlatform \"x86\" && depends+=(nasm)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-mupen64plus() {\n    gitPullOrClone\n\n    # mesa workaround; see: https://github.com/libretro/libretro-common/issues/98\n    if hasPackage libgles2-mesa-dev 18.2 ge; then\n        applyPatch \"$md_data/0001-eliminate-conflicting-typedefs.patch\"\n    fi\n\n    # Allows GLES3 with rpi\n    applyPatch \"$md_data/0002-rpi-gles3.patch\"\n\n    # Fix building with GCC 15\n    applyPatch \"$md_data/0003-fix-fsqrt-conflict.patch\"\n}\n\nfunction build_lr-mupen64plus() {\n    rpSwap on 750\n    local params=()\n    if isPlatform \"videocore\"; then\n        params+=(platform=\"$__platform\")\n    elif isPlatform \"mesa\"; then\n        params+=(platform=\"$__platform-mesa\")\n    elif isPlatform \"mali\"; then\n        params+=(platform=\"odroid\")\n    fi\n\n    # set these ourselves, to fix missing platforms in the Makefile (eg. rpi5)\n    isPlatform \"arm\" && params+=(WITH_DYNAREC=arm)\n    isPlatform \"neon\" && params+=(HAVE_NEON=1)\n\n    if isPlatform \"gles3\"; then\n        params+=(FORCE_GLES3=1)\n    elif isPlatform \"gles\"; then\n        params+=(FORCE_GLES=1)\n    fi\n    # for GCC 15 and up\n    CFLAGS+=\" -Wno-incompatible-pointer-types\"\n    make clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/mupen64plus_libretro.so\"\n}\n\nfunction install_lr-mupen64plus() {\n    md_ret_files=(\n        'mupen64plus_libretro.so'\n        'LICENSE'\n        'README.md'\n        'BUILDING.md'\n    )\n}\n\nfunction configure_lr-mupen64plus() {\n    mkRomDir \"n64\"\n    defaultRAConfig \"n64\"\n\n    addEmulator 0 \"$md_id\" \"n64\" \"$md_inst/mupen64plus_libretro.so\"\n    addSystem \"n64\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-neocd.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-neocd\"\nrp_module_desc=\"Neo Geo CD Emulator - rewrite of NeoCD for libretro\"\nrp_module_help=\"ROM Extension: .chd .cue\\n\\nCopy your roms to\\n$romdir/neogeo\\n\\nYou will need a minimum of two BIOS files (eg. ng-lo.rom, uni-bioscd.rom) which should be copied to $biosdir/neocd\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/neocd_libretro/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/neocd_libretro.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-neocd() {\n    gitPullOrClone\n}\n\nfunction build_lr-neocd() {\n    make clean\n    make USE_LTO=0\n    md_ret_require=\"$md_build/neocd_libretro.so\"\n}\n\nfunction install_lr-neocd() {\n    md_ret_files=(\n        'LICENSE.md'\n        'neocd_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-neocd() {\n    mkRomDir \"neogeo\"\n    defaultRAConfig \"neogeo\"\n\n    addEmulator 0 \"$md_id\" \"neogeo\" \"$md_inst/neocd_libretro.so\"\n    addSystem \"neogeo\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-nestopia.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-nestopia\"\nrp_module_desc=\"NES emu - Nestopia (enhanced) port for libretro\"\nrp_module_help=\"ROM Extensions: .nes .zip\\n\\nCopy your NES roms to $romdir/nes\\n\\nFor the Famicom Disk System copy your roms to $romdir/fds\\n\\nFor the Famicom Disk System copy the required BIOS file disksys.rom to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/nestopia/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/nestopia.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-nestopia() {\n    gitPullOrClone\n}\n\nfunction build_lr-nestopia() {\n    cd libretro\n    rpSwap on 512\n    make clean\n    make\n    rpSwap off\n    md_ret_require=\"$md_build/libretro/nestopia_libretro.so\"\n}\n\nfunction install_lr-nestopia() {\n    md_ret_files=(\n        'libretro/nestopia_libretro.so'\n        'COPYING'\n    )\n}\n\nfunction configure_lr-nestopia() {\n    mkRomDir \"nes\"\n    mkRomDir \"fds\"\n    defaultRAConfig \"nes\"\n    defaultRAConfig \"fds\"\n\n    addEmulator 0 \"$md_id\" \"nes\" \"$md_inst/nestopia_libretro.so\"\n    addEmulator 1 \"$md_id\" \"fds\" \"$md_inst/nestopia_libretro.so\"\n    addSystem \"nes\"\n    addSystem \"fds\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-np2kai.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-np2kai\"\nrp_module_desc=\"PC98 emu - Modified Neko Project II port for libretro\"\nrp_module_help=\"ROM Extensions: .d88 .d98 .88d .98d .fdi .xdf .hdm .dup .2hd .tfd .hdi .thd .nhd .hdd\\n\\nCopy your pc98 games to to $romdir/pc98\\n\\nCopy bios files 2608_bd.wav, 2608_hh.wav, 2608_rim.wav, 2608_sd.wav, 2608_tom.wav 2608_top.wav, bios.rom, FONT.ROM and sound.rom to $biosdir/np2kai\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/libretro/NP2kai/master/LICENSE\"\nrp_module_repo=\"git https://github.com/AZO234/NP2kai.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-np2kai() {\n    gitPullOrClone\n}\n\nfunction build_lr-np2kai() {\n    cd \"$md_build/sdl\"\n    make -f Makefile.libretro clean GIT_TAG=\"master\"\n    make -f Makefile.libretro GIT_TAG=\"master\"\n    md_ret_require=\"$md_build/sdl/np2kai_libretro.so\"\n}\n\nfunction install_lr-np2kai() {\n    md_ret_files=(\n        'sdl/np2kai_libretro.so'\n    )\n}\n\nfunction configure_lr-np2kai() {\n    mkRomDir \"pc98\"\n    defaultRAConfig \"pc98\"\n\n    addEmulator 1 \"$md_id\" \"pc98\" \"$md_inst/np2kai_libretro.so\"\n    addSystem \"pc98\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-nxengine.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-nxengine\"\nrp_module_desc=\"Cave Story engine clone - NxEngine port for libretro\"\nrp_module_help=\"Copy the original Cave Story game files to $romdir/ports/CaveStory so you have the file $romdir/ports/CaveStory/Doukutsu.exe present.\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/nxengine-libretro/master/nxengine/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/nxengine-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-nxengine() {\n    gitPullOrClone\n}\n\nfunction build_lr-nxengine() {\n    make clean\n    make\n    md_ret_require=\"$md_build/nxengine_libretro.so\"\n}\n\nfunction install_lr-nxengine() {\n    md_ret_files=(\n        'nxengine_libretro.so'\n    )\n}\n\nfunction configure_lr-nxengine() {\n    local script\n    setConfigRoot \"ports\"\n\n    addPort \"$md_id\" \"cavestory\" \"Cave Story\" \"$md_inst/nxengine_libretro.so\"\n    local file=\"$romdir/ports/Cave Story.sh\"\n    # custom launch script - if the data files are not found, warn the user\n    cat >\"$file\" << _EOF_\n#!/bin/bash\nif [[ ! -f \"$romdir/ports/CaveStory/Doukutsu.exe\" ]]; then\n    dialog --no-cancel --pause \"$md_help\" 22 76 15\nelse\n    \"$rootdir/supplementary/runcommand/runcommand.sh\" 0 _PORT_ cavestory \"$romdir/ports/CaveStory/Doukutsu.exe\"\nfi\n_EOF_\n    chown \"$__user\":\"$__group\" \"$file\"\n    chmod +x \"$file\"\n\n    defaultRAConfig \"cavestory\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-o2em.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-o2em\"\nrp_module_desc=\"Odyssey 2 / Videopac emu - O2EM port for libretro\"\nrp_module_help=\"ROM Extensions: .bin .zip\\n\\nCopy your Odyssey 2 / Videopac roms to $romdir/videopac\\n\\nCopy the required BIOS file o2rom.bin to $biosdir\"\nrp_module_licence=\"OTHER\"\nrp_module_repo=\"git https://github.com/libretro/libretro-o2em master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-o2em() {\n    gitPullOrClone\n}\n\nfunction build_lr-o2em() {\n    make clean\n    make\n    md_ret_require=\"$md_build/o2em_libretro.so\"\n}\n\nfunction install_lr-o2em() {\n    md_ret_files=(\n        'o2em_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-o2em() {\n    mkRomDir \"videopac\"\n    defaultRAConfig \"videopac\"\n\n    addEmulator 1 \"$md_id\" \"videopac\" \"$md_inst/o2em_libretro.so\"\n    addSystem \"videopac\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-opera.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-opera\"\nrp_module_desc=\"3DO emulator - fork of 4DO/FreeDO for libretro\"\nrp_module_help=\"ROM Extension: .cue .chd .iso .zip\\n\\nCopy your 3do roms to $romdir/3do\\n\\nCopy the required BIOS file panazf10.bin to $biosdir\"\nrp_module_licence=\"LGPL https://raw.githubusercontent.com/libretro/opera-libretro/master/libopera/opera_3do.c\"\nrp_module_repo=\"git https://github.com/libretro/opera-libretro.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-opera() {\n    gitPullOrClone\n}\n\nfunction _update_hook_lr-opera() {\n     renameModule \"lr-4do\" \"lr-opera\"\n}\n\nfunction build_lr-opera() {\n    make clean\n    make\n    md_ret_require=\"$md_build/opera_libretro.so\"\n}\n\nfunction install_lr-opera() {\n    md_ret_files=(\n        'opera_libretro.so'\n    )\n}\n\nfunction configure_lr-opera() {\n    mkRomDir \"3do\"\n    defaultRAConfig \"3do\"\n\n    addEmulator 1 \"$md_id\" \"3do\" \"$md_inst/opera_libretro.so\"\n    addSystem \"3do\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-parallel-n64/01-fix-fsqrt-conflicts.diff",
    "content": "diff --git a/mupen64plus-core/src/r4300/hacktarux_dynarec/assemble.h b/mupen64plus-core/src/r4300/hacktarux_dynarec/assemble.h\nindex 8161292..31f21b1 100644\n--- a/mupen64plus-core/src/r4300/hacktarux_dynarec/assemble.h\n+++ b/mupen64plus-core/src/r4300/hacktarux_dynarec/assemble.h\n@@ -1650,7 +1650,7 @@ static INLINE void fchs(void)\n }\n \n \n-static INLINE void fsqrt(void)\n+static INLINE void fsqrt_(void)\n {\n    put8(0xD9);\n    put8(0xFA);\ndiff --git a/mupen64plus-core/src/r4300/hacktarux_dynarec/hacktarux_dynarec.c b/mupen64plus-core/src/r4300/hacktarux_dynarec/hacktarux_dynarec.c\nindex 89fb982..4f81f9d 100644\n--- a/mupen64plus-core/src/r4300/hacktarux_dynarec/hacktarux_dynarec.c\n+++ b/mupen64plus-core/src/r4300/hacktarux_dynarec/hacktarux_dynarec.c\n@@ -6317,13 +6317,13 @@ void gensqrt_d(void)\n #ifdef __x86_64__\n    mov_xreg64_m64rel(RAX, (uint64_t *)(&reg_cop1_double[dst->f.cf.fs]));\n    fld_preg64_qword(RAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_xreg64_m64rel(RAX, (uint64_t *)(&reg_cop1_double[dst->f.cf.fd]));\n    fstp_preg64_qword(RAX);\n #else\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_double[dst->f.cf.fs]));\n    fld_preg32_qword(EAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_double[dst->f.cf.fd]));\n    fstp_preg32_qword(EAX);\n #endif\n@@ -7301,13 +7301,13 @@ void gensqrt_s(void)\n #ifdef __x86_64__\n    mov_xreg64_m64rel(RAX, (uint64_t *)(&reg_cop1_simple[dst->f.cf.fs]));\n    fld_preg64_dword(RAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_xreg64_m64rel(RAX, (uint64_t *)(&reg_cop1_simple[dst->f.cf.fd]));\n    fstp_preg64_dword(RAX);\n #else\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_simple[dst->f.cf.fs]));\n    fld_preg32_dword(EAX);\n-   fsqrt();\n+   fsqrt_();\n    mov_eax_memoffs32((unsigned int *)(&reg_cop1_simple[dst->f.cf.fd]));\n    fstp_preg32_dword(EAX);\n #endif\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-parallel-n64.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-parallel-n64\"\nrp_module_desc=\"N64 emu - Highly modified Mupen64Plus port for libretro\"\nrp_module_help=\"ROM Extensions: .z64 .n64 .v64\\n\\nCopy your N64 roms to $romdir/n64\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/parallel-n64/master/mupen64plus-core/LICENSES\"\nrp_module_repo=\"git https://github.com/RetroPie/parallel-n64.git retropie\"\nrp_module_section=\"exp x86=main\"\n\nfunction depends_lr-parallel-n64() {\n    local depends=()\n    isPlatform \"x11\" && depends+=(libgl1-mesa-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"kms\" && isPlatform \"gles\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-parallel-n64() {\n    gitPullOrClone\n    # fix building with gcc 15\n    applyPatch \"$md_data/01-fix-fsqrt-conflicts.diff\"\n}\n\nfunction build_lr-parallel-n64() {\n    rpSwap on 1000\n    local params=()\n    if isPlatform \"videocore\" || isPlatform \"odroid-c1\"; then\n        params+=(platform=\"$__platform\")\n    else\n        isPlatform \"gles\" && params+=(GLES=1 GL_LIB:=-lGLESv2)\n        if isPlatform \"arm\"; then\n            params+=(CPUFLAGS=\"-DNO_ASM -DARM -D__arm__ -DARM_ASM -D__NEON_OPT -DNOSSE -DARM_FIX\")\n            params+=(WITH_DYNAREC=arm)\n            isPlatform \"neon\" && params+=(HAVE_NEON=1)\n        elif isPlatform \"aarch64\"; then\n            params+=(CPUFLAGS=\"-DARM_FIX\")\n        fi\n    fi\n    make clean\n    make \"${params[@]}\"\n    rpSwap off\n    md_ret_require=\"$md_build/parallel_n64_libretro.so\"\n}\n\nfunction install_lr-parallel-n64() {\n    md_ret_files=(\n        'parallel_n64_libretro.so'\n        'README.md'\n        'mupen64plus-core/LICENSES'\n    )\n}\n\nfunction configure_lr-parallel-n64() {\n    mkRomDir \"n64\"\n    defaultRAConfig \"n64\"\n\n    # Set core options\n    setRetroArchCoreOption \"parallel-n64-gfxplugin\" \"auto\"\n    setRetroArchCoreOption \"parallel-n64-gfxplugin-accuracy\" \"low\"\n    setRetroArchCoreOption \"parallel-n64-screensize\" \"640x480\"\n\n    # Copy config files\n    cat > $home/RetroPie/BIOS/gles2n64rom.conf << _EOF_\n#rom specific settings\n\nrom name=SUPER MARIO 64\ntarget FPS=25\n\nrom name=Kirby64\ntarget FPS=25\n\nrom name=Banjo-Kazooie\nframebuffer enable=1\nupdate mode=4\ntarget FPS=25\n\nrom name=BANJO TOOIE\nhack banjo tooie=1\nignore offscreen rendering=1\nframebuffer enable=1\nupdate mode=4\n\nrom name=STARFOX64\nwindow width=864\nwindow height=520\ntarget FPS=27\n\nrom name=MARIOKART64\ntarget FPS=27\n\nrom name=THE LEGEND OF ZELDA\ntexture use IA=0\nhack zelda=1\ntarget FPS=17\n\nrom name=ZELDA MAJORA'S MASK\ntexture use IA=0\nhack zelda=1\nrom name=F-ZERO X\nwindow width=864\nwindow height=520\ntarget FPS=55\nrom name=WAVE RACE 64\nwindow width=864\nwindow height=520\ntarget FPS=27\nrom name=SMASH BROTHERS\nframebuffer enable=1\nwindow width=864\nwindow height=520\ntarget FPS=27\nrom name=1080 SNOWBOARDING\nupdate mode=2\ntarget FPS=27\nrom name=PAPER MARIO\nupdate mode=4\nrom name=STAR WARS EP1 RACER\nvideo force=1\nvideo width=320\nvideo height=480\nrom name=JET FORCE GEMINI\nframebuffer enable=1\nupdate mode=2\nignore offscreen rendering=1\ntarget FPS=27\nrom name=RIDGE RACER 64\nwindow width=864\nwindow height=520\nenable lighting=0\ntarget FPS=27\nrom name=Diddy Kong Racing\ntarget FPS=27\nrom name=MarioParty\nupdate mode=4\nrom name=MarioParty3\nupdate mode=4\nrom name=Beetle Adventure Rac\nwindow width=864\nwindow height=520\ntarget FPS=27\nrom name=EARTHWORM JIM 3D\nrom name=LEGORacers\nrom name=GOEMONS GREAT ADV\nwindow width=864\nwindow height=520\nrom name=Buck Bumble\nwindow width=864\nwindow height=520\nrom name=BOMBERMAN64U2\nwindow width=864\nwindow height=520\nrom name=ROCKETROBOTONWHEELS\nwindow width=864\nwindow height=520\nrom name=GOLDENEYE\nforce screen clear=1\nframebuffer enable=1\nwindow width=864\nwindow height=520\ntarget FPS=25\nrom name=Mega Man 64\nframebuffer enable=1\ntarget FPS=25\n_EOF_\n    chown \"$__user\":\"$__group\" \"$biosdir/gles2n64rom.conf\"\n\n    addEmulator 0 \"$md_id\" \"n64\" \"$md_inst/parallel_n64_libretro.so\"\n    addSystem \"n64\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-pcsx-rearmed.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-pcsx-rearmed\"\nrp_module_desc=\"Playstation emulator - PCSX (arm optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .bin .cue .cbn .img .iso .m3u .mdf .pbp .toc .z .znx\\n\\nCopy your PSX roms to $romdir/psx\\n\\nCopy the required BIOS file SCPH1001.BIN to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/pcsx_rearmed/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/pcsx_rearmed.git master\"\nrp_module_section=\"opt arm=main aarch64=main\"\n\nfunction depends_lr-pcsx-rearmed() {\n    local depends=(libpng-dev)\n    isPlatform \"x11\" && depends+=(libx11-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-pcsx-rearmed() {\n    gitPullOrClone\n}\n\nfunction build_lr-pcsx-rearmed() {\n    local params=(THREAD_RENDERING=0)\n\n    if isPlatform \"arm\"; then\n        params+=(ARCH=arm DYNAREC=ari64)\n        if isPlatform \"neon\"; then\n            params+=(HAVE_NEON=1 HAVE_NEON_ASM=1 BUILTIN_GPU=neon)\n        else\n            params+=(BUILTIN_GPU=peops)\n        fi\n    elif isPlatform \"aarch64\"; then\n        params+=(ARCH=aarch64 DYNAREC=ari64)\n    fi\n\n    make -f Makefile.libretro \"${params[@]}\" clean\n    make -f Makefile.libretro \"${params[@]}\"\n    md_ret_require=\"$md_build/pcsx_rearmed_libretro.so\"\n}\n\nfunction install_lr-pcsx-rearmed() {\n    md_ret_files=(\n        'AUTHORS'\n        'ChangeLog.df'\n        'COPYING'\n        'pcsx_rearmed_libretro.so'\n        'NEWS'\n        'README.md'\n    )\n}\n\nfunction configure_lr-pcsx-rearmed() {\n    mkRomDir \"psx\"\n    defaultRAConfig \"psx\"\n\n    addEmulator 1 \"$md_id\" \"psx\" \"$md_inst/pcsx_rearmed_libretro.so\"\n    addSystem \"psx\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-picodrive.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-picodrive\"\nrp_module_desc=\"Sega 8/16 bit emu - picodrive arm optimised libretro core\"\nrp_module_help=\"ROM Extensions: .32x .iso .cue .sms .smd .bin .gen .md .sg .zip\\n\\nCopy your Megadrive / Genesis roms to $romdir/megadrive\\nMasterSystem roms to $romdir/mastersystem\\nSega 32X roms to $romdir/sega32x and\\nSegaCD roms to $romdir/segacd\\nThe Sega CD requires the BIOS files us_scd1_9210.bin, eu_mcd1_9210.bin, jp_mcd1_9112.bin copied to $biosdir\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/picodrive/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/picodrive.git master\"\nrp_module_section=\"main\"\nrp_module_flags=\"nodistcc\"\n\nfunction sources_lr-picodrive() {\n    gitPullOrClone\n}\n\nfunction build_lr-picodrive() {\n    local params=()\n    if isPlatform \"arm\"; then\n        params+=(platform=armv ARM_ASM=1 use_fame=0 use_cyclone=1 use_sh2drc=1 use_svpdrc=1)\n        if isPlatform \"armv6\"; then\n            params+=(use_cz80=0 use_drz80=1)\n        else\n            params+=(use_cz80=1 use_drz80=0)\n        fi\n    elif isPlatform \"aarch64\"; then\n        params+=(use_sh2drc=0)\n    fi\n    make clean\n    make -f Makefile.libretro \"${params[@]}\"\n    md_ret_require=\"$md_build/picodrive_libretro.so\"\n}\n\nfunction install_lr-picodrive() {\n    md_ret_files=(\n        'AUTHORS'\n        'COPYING'\n        'picodrive_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-picodrive() {\n    local system\n    local def\n    for system in megadrive mastersystem segacd sega32x; do\n        def=0\n        # default on megadrive / mastersystem only on armv6 for performance\n        [[ \"$system\" =~ megadrive|mastersystem ]] && isPlatform \"arm6\" && def=1\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator $def \"$md_id\" \"$system\" \"$md_inst/picodrive_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-pokemini.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-pokemini\"\nrp_module_desc=\"Pokemon Mini emulator - PokeMini port for libretro\"\nrp_module_help=\"ROM Extensions: .min .zip\\n\\nCopy your Pokemon Mini roms to $romdir/pokemini\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/PokeMini/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/pokemini.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-pokemini() {\n    gitPullOrClone\n}\n\nfunction build_lr-pokemini() {\n    make clean\n    make\n    md_ret_require=\"$md_build/pokemini_libretro.so\"\n}\n\nfunction install_lr-pokemini() {\n    md_ret_files=(\n        'pokemini_libretro.so'\n    )\n}\n\nfunction configure_lr-pokemini() {\n    mkRomDir \"pokemini\"\n    defaultRAConfig \"pokemini\"\n\n    addEmulator 1 \"$md_id\" \"pokemini\" \"$md_inst/pokemini_libretro.so\"\n    addSystem \"pokemini\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-ppsspp/v13-libretro_fix.diff",
    "content": "diff --git a/Core/HLE/__sceAudio.cpp b/Core/HLE/__sceAudio.cpp\nindex 3176d26..f05ad9d 100644\n--- a/Core/HLE/__sceAudio.cpp\n+++ b/Core/HLE/__sceAudio.cpp\n@@ -82,6 +82,11 @@ static bool m_logAudio;\n static int chanQueueMaxSizeFactor;\n static int chanQueueMinSizeFactor;\n \n+// Accessor for libretro\n+int __AudioGetHostAttemptBlockSize() {\n+\treturn hostAttemptBlockSize;\n+}\n+\n static void hleAudioUpdate(u64 userdata, int cyclesLate) {\n \t// Schedule the next cycle first.  __AudioUpdate() may consume cycles.\n \tCoreTiming::ScheduleEvent(audioIntervalCycles - cyclesLate, eventAudioUpdate, 0);\ndiff --git a/Core/HLE/__sceAudio.h b/Core/HLE/__sceAudio.h\nindex ae9ca35..f26ae0d 100644\n--- a/Core/HLE/__sceAudio.h\n+++ b/Core/HLE/__sceAudio.h\n@@ -50,6 +50,8 @@ int __AudioMix(short *outstereo, int numSamples, int sampleRate);\n void __AudioGetDebugStats(char *buf, size_t bufSize);\n void __PushExternalAudio(const s32 *audio, int numSamples);  // Should not be used in-game, only at the menu!\n \n+int __AudioGetHostAttemptBlockSize();\n+\n // Audio Dumping stuff\n void __StartLogAudio(const Path &filename);\n void __StopLogAudio();\ndiff --git a/libretro/libretro.cpp b/libretro/libretro.cpp\nindex eacbca2..26f2cf6 100644\n--- a/libretro/libretro.cpp\n+++ b/libretro/libretro.cpp\n@@ -379,7 +379,7 @@ class LibretroHost : public Host\n       void InitSound() override {}\n       void UpdateSound() override\n       {\n-         extern int hostAttemptBlockSize;\n+         int hostAttemptBlockSize = __AudioGetHostAttemptBlockSize();\n          const int blockSizeMax = 512;\n          static int16_t audio[blockSizeMax * 2];\n          assert(hostAttemptBlockSize <= blockSizeMax);\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-ppsspp/v16-clamp-include.diff",
    "content": "diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp\nindex 5a2f9104f1..5eabd5e54e 100644\n--- a/libretro/libretro.cpp\n+++ b/libretro/libretro.cpp\n@@ -6,6 +6,7 @@\n #include <vector>\n #include <cstdlib>\n #include <mutex>\n+#include <algorithm>\n \n #include \"Common/CPUDetect.h\"\n #include \"Common/Log.h\"\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-ppsspp.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-ppsspp\"\nrp_module_desc=\"PlayStation Portable emu - PPSSPP port for libretro\"\nrp_module_help=\"ROM Extensions: .iso .pbp .cso\\n\\nCopy your PlayStation Portable roms to $romdir/psp\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/ppsspp/master/LICENSE.TXT\"\nrp_module_repo=\"git https://github.com/hrydgard/ppsspp.git :_get_release_ppsspp\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_lr-ppsspp() {\n    depends_ppsspp\n}\n\nfunction sources_lr-ppsspp() {\n    sources_ppsspp\n\n    # fix missing defines on opengles2 and include on v1.16.6 lr-ppsspp\n    if [[ \"$(_get_release_ppsspp)\" == \"v1.16.6\" ]]; then\n        applyPatch \"${__mod_info[ppsspp/path]%/*}/ppsspp/gles2_fix.diff\"\n        applyPatch \"$md_data/v16-clamp-include.diff\"\n    fi\n\n    # fix missing exported symbol for libretro on v1.13.2\n    if [[ \"$(_get_release_ppsspp)\" == \"v1.13.2\" ]]; then\n        applyPatch \"$md_data/v13-libretro_fix.diff\"\n    fi\n}\n\nfunction build_lr-ppsspp() {\n    build_ppsspp\n}\n\nfunction install_lr-ppsspp() {\n    md_ret_files=(\n        'ppsspp/build/lib/ppsspp_libretro.so'\n        'ppsspp/build/assets'\n    )\n}\n\nfunction configure_lr-ppsspp() {\n    mkRomDir \"psp\"\n    defaultRAConfig \"psp\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkUserDir \"$biosdir/PPSSPP\"\n        cp -Rv \"$md_inst/assets/\"* \"$biosdir/PPSSPP/\"\n        chown -R \"$__user\":\"$__group\" \"$biosdir/PPSSPP\"\n\n        # the core needs a save file directory, use the same folder as standalone 'ppsspp'\n        iniConfig \" = \" \"\" \"$configdir/psp/retroarch.cfg\"\n        iniSet \"savefile_directory\" \"$home/.config/ppsspp\"\n        moveConfigDir \"$home/.config/ppsspp\" \"$md_conf_root/psp\"\n    fi\n\n    addEmulator 1 \"$md_id\" \"psp\" \"$md_inst/ppsspp_libretro.so\"\n    addSystem \"psp\"\n\n    # if we are removing the last remaining psp emu - remove the symlink\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        if [[ -h \"$home/.config/ppsspp\" && ! -f \"$md_conf_root/psp/emulators.cfg\" ]]; then\n            rm -f \"$home/.config/ppsspp\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-prboom.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-prboom\"\nrp_module_desc=\"Doom/Doom II engine - PrBoom port for libretro\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/libretro-prboom/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/libretro-prboom.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-prboom() {\n    gitPullOrClone\n}\n\nfunction build_lr-prboom() {\n    make clean\n    make\n    md_ret_require=\"$md_build/prboom_libretro.so\"\n}\n\nfunction install_lr-prboom() {\n    md_ret_files=(\n        'prboom_libretro.so'\n        'prboom.wad'\n    )\n}\n\nfunction game_data_lr-prboom() {\n    local dest=\"$romdir/ports/doom\"\n    mkUserDir \"$dest\"\n    if [[ ! -f \"$dest/doom1.wad\" ]]; then\n        # download doom 1 shareware\n        download \"$__archive_url/doom1.wad\" \"$dest/doom1.wad\"\n    fi\n\n    if ! echo \"97bb88094a51457a8dcad98c58be22a2d0fa9a37 $romdir/ports/doom/freedoom1.wad\" | sha1sum -c &>/dev/null; then\n        # download (or update) freedoom\n        downloadAndExtract \"https://github.com/freedoom/freedoom/releases/download/v0.13.0/freedoom-0.13.0.zip\" \"$dest\" -j -LL\n    fi\n\n    mkUserDir \"$dest/addon\"\n    chown -R \"$__user\":\"$__group\" \"$dest\"\n}\n\nfunction _add_games_lr-prboom() {\n    local cmd=\"${@}\"\n    local addon=\"$romdir/ports/doom/addon\"\n\n    declare -A games=(\n        ['doom1.wad']=\"Doom\"\n        ['doom2.wad']=\"Doom II\"\n        ['doomu.wad']=\"The Ultimate Doom\"\n        ['freedoom1.wad']=\"Freedoom - Phase I\"\n        ['freedoom2.wad']=\"Freedoom - Phase II\"\n        ['tnt.wad']=\"TNT - Evilution\"\n        ['plutonia.wad']=\"The Plutonia Experiment\"\n    )\n\n    if [[ \"$md_id\" =~ \"zdoom\" ]]; then\n        games+=(\n            ['heretic.wad']=\"Heretic - Shadow of the Serpent Riders\"\n            ['hexen.wad']=\"Hexen - Beyond Heretic\"\n            ['hexdd.wad']=\"Hexen - Deathkings of the Dark Citadel\"\n            ['chex3.wad']=\"Chex Quest 3\"\n            ['strife1.wad']=\"Strife\"\n        )\n    fi\n\n    local game\n    local doswad\n    local wad\n    for game in \"${!games[@]}\"; do\n        doswad=\"$romdir/ports/doom/${game^^}\"\n        wad=\"$romdir/ports/doom/$game\"\n        if [[ -f \"$doswad\" ]]; then\n            mv \"$doswad\" \"$wad\"\n        fi\n        if [[ -f \"$wad\" ]]; then\n            addPort \"$md_id\" \"doom\" \"${games[$game]}\" \"$cmd\" \"$wad\"\n            if [[ \"$md_id\" =~ \"zdoom\" ]]; then\n                addPort \"$md_id-addon\" \"doom\" \"${games[$game]}\" \"$cmd -file ${addon}/*\" \"$wad\"\n            fi\n        fi\n    done\n}\n\nfunction add_games_lr-prboom() {\n    _add_games_lr-prboom \"$md_inst/prboom_libretro.so\"\n}\n\nfunction configure_lr-prboom() {\n    setConfigRoot \"ports\"\n\n    mkRomDir \"ports/doom\"\n    defaultRAConfig \"doom\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_lr-prboom\n\n    add_games_lr-prboom\n\n    cp prboom.wad \"$romdir/ports/doom/\"\n    chown \"$__user\":\"$__group\" \"$romdir/ports/doom/prboom.wad\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-prosystem.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-prosystem\"\nrp_module_desc=\"Atari 7800 ProSystem emu - ProSystem port for libretro\"\nrp_module_help=\"ROM Extensions: .a78 .bin .zip\\n\\nCopy your Atari 7800 roms to $romdir/atari7800\\n\\nCopy the optional BIOS file 7800 BIOS (U).rom to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/prosystem-libretro/master/License.txt\"\nrp_module_repo=\"git https://github.com/libretro/prosystem-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-prosystem() {\n    gitPullOrClone\n}\n\nfunction build_lr-prosystem() {\n    make clean\n    CXXFLAGS=\"$CXXFLAGS -fsigned-char\" make\n    md_ret_require=\"$md_build/prosystem_libretro.so\"\n}\n\nfunction install_lr-prosystem() {\n    md_ret_files=(\n        'prosystem_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-prosystem() {\n    mkRomDir \"atari7800\"\n\n    defaultRAConfig \"atari7800\"\n\n    addEmulator 1 \"$md_id\" \"atari7800\" \"$md_inst/prosystem_libretro.so\"\n    addSystem \"atari7800\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-puae.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-puae\"\nrp_module_desc=\"P-UAE Amiga emulator port for libretro\"\nrp_module_help=\"ROM Extensions: .adf .uae\\n\\nCopy your roms to $romdir/amiga and create configs as .uae\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/PUAE/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/libretro-uae.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-puae() {\n    gitPullOrClone\n}\n\nfunction build_lr-puae() {\n    make\n    md_ret_require=\"$md_build/puae_libretro.so\"\n}\n\nfunction install_lr-puae() {\n    md_ret_files=(\n        'puae_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-puae() {\n    mkRomDir \"amiga\"\n    defaultRAConfig \"amiga\"\n    addEmulator 1 \"$md_id\" \"amiga\" \"$md_inst/puae_libretro.so\"\n    addSystem \"amiga\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-puae2021.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-puae2021\"\nrp_module_desc=\"P-UAE Amiga emulator port for libretro from 2021 (v2.6.1)\"\nrp_module_help=\"ROM Extensions: .adf .uae\\n\\nCopy your roms to $romdir/amiga and create configs as .uae\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/PUAE/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/libretro-uae.git 2.6.1\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-puae2021() {\n    gitPullOrClone\n}\n\nfunction build_lr-puae2021() {\n    make\n    md_ret_require=\"$md_build/puae2021_libretro.so\"\n}\n\nfunction install_lr-puae2021() {\n    md_ret_files=(\n        'puae2021_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-puae2021() {\n    mkRomDir \"amiga\"\n    defaultRAConfig \"amiga\"\n    addEmulator 1 \"lr-puae2021\" \"amiga\" \"$md_inst/puae2021_libretro.so\"\n    addSystem \"amiga\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-px68k.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-px68k\"\nrp_module_desc=\"SHARP X68000 Emulator\"\nrp_module_help=\"You need to copy a X68000 bios file (iplrom30.dat, iplromco.dat, iplrom.dat, or iplromxv.dat), and the font file (cgrom.dat or cgrom.tmp) to $biosdir/keropi. Use F12 to access the in emulator menu.\"\nrp_module_repo=\"git https://github.com/libretro/px68k-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction sources_lr-px68k() {\n    gitPullOrClone\n}\n\nfunction build_lr-px68k() {\n    make clean\n    make\n    md_ret_require=\"$md_build/px68k_libretro.so\"\n}\n\nfunction install_lr-px68k() {\n    md_ret_files=(\n        'px68k_libretro.so'\n        'README.MD'\n        'readme.txt'\n    )\n}\n\nfunction configure_lr-px68k() {\n    mkRomDir \"x68000\"\n    defaultRAConfig \"x68000\"\n\n    mkUserDir \"$biosdir/keropi\"\n\n    addEmulator 1 \"$md_id\" \"x68000\" \"$md_inst/px68k_libretro.so\"\n    addSystem \"x68000\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-quasi88.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-quasi88\"\nrp_module_desc=\"NEC PC-8801 emu - Quasi88 port for libretro\"\nrp_module_help=\"ROM Extensions: .d88 .88d .cmt .m3u .t88\\n\\nCopy your pc88 games to to $romdir/pc88\\n\\nCopy bios files n88.rom, n88_0.rom, n88_1.rom, n88_2.rom, n88_3.rom, n88n.rom, disk.rom, n88knj1.rom, n88knj2.rom, and n88jisho.rom to $biosdir/quasi88\"\nrp_module_licence=\"BSD https://raw.githubusercontent.com/libretro/quasi88-libretro/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/quasi88-libretro.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-quasi88() {\n    gitPullOrClone\n}\n\nfunction build_lr-quasi88() {\n    make clean\n    make\n    md_ret_require=\"$md_build/quasi88_libretro.so\"\n}\n\nfunction install_lr-quasi88() {\n    md_ret_files=(\n        'README.md'\n        'quasi88_libretro.so'\n    )\n}\n\nfunction configure_lr-quasi88() {\n    mkRomDir \"pc88\"\n    defaultRAConfig \"pc88\"\n    addEmulator 1 \"$md_id\" \"pc88\" \"$md_inst/quasi88_libretro.so\"\n    addSystem \"pc88\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-quicknes.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-quicknes\"\nrp_module_desc=\"NES emulator - QuickNES Port for libretro\"\nrp_module_help=\"ROM Extensions: .nes .zip\\n\\nCopy your NES roms to $romdir/nes\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/QuickNES_Core/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/QuickNES_Core.git master\"\nrp_module_section=\"opt armv6=main\"\n\nfunction sources_lr-quicknes() {\n    gitPullOrClone\n}\n\nfunction build_lr-quicknes() {\n    make clean\n    make\n    md_ret_require=\"$md_build/quicknes_libretro.so\"\n}\n\nfunction install_lr-quicknes() {\n    md_ret_files=(\n        'quicknes_libretro.so'\n    )\n}\n\nfunction configure_lr-quicknes() {\n    mkRomDir \"nes\"\n    defaultRAConfig \"nes\"\n\n    local def=0\n    isPlatform \"armv6\" && def=1\n\n    addEmulator \"$def\" \"$md_id\" \"nes\" \"$md_inst/quicknes_libretro.so\"\n    addSystem \"nes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-retro8.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-retro8\"\nrp_module_desc=\"PICO-8 compatible engine - port of retro8 for libretro\"\nrp_module_help=\"ROM Extensions: .p8 .p8.png .zip\\n\\nCopy your roms to $romdir/pico8\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/retro8/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/retro8.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-retro8() {\n    gitPullOrClone\n}\n\nfunction build_lr-retro8() {\n    make clean\n    make\n    md_ret_require=\"$md_build/retro8_libretro.so\"\n}\n\nfunction install_lr-retro8() {\n    md_ret_files=(\n        'retro8_libretro.so'\n        'README.md'\n        'LICENSE'\n    )\n}\n\nfunction configure_lr-retro8() {\n    mkRomDir \"pico8\"\n\n    addEmulator 1 \"$md_id\" \"pico8\" \"$md_inst/retro8_libretro.so\"\n    addSystem \"pico8\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # disable retroarch built-in imageviewer so we can run .p8.png files\n    defaultRAConfig \"pico8\" \"builtin_imageviewer_enable\" \"false\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-scummvm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-scummvm\"\nrp_module_desc=\"ScummVM port for libretro\"\nrp_module_help=\"Copy your ScummVM games to $romdir/scummvm\\n\\nThe name of your game directories must be suffixed with '.svm' for direct launch in EmulationStation.\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/scummvm/master/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/scummvm.git master\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-scummvm() {\n    getDepends zip\n}\n\nfunction sources_lr-scummvm() {\n    gitPullOrClone\n}\n\nfunction build_lr-scummvm() {\n    local gl_platform=OPENGL\n    isPlatform \"gles\" && gl_platform=OPENGLES2\n    cd backends/platform/libretro\n    make clean\n    make USE_MT32EMU=1 FORCE_${gl_platform}=1\n    make datafiles\n    md_ret_require=\"$md_build/backends/platform/libretro/scummvm_libretro.so\"\n}\n\nfunction install_lr-scummvm() {\n    md_ret_files=(\n        \"backends/platform/libretro/scummvm_libretro.so\"\n        \"backends/platform/libretro/scummvm.zip\"\n        \"COPYING\"\n    )\n}\n\nfunction configure_lr-scummvm() {\n    addEmulator 0 \"$md_id\" \"scummvm\" \"$md_inst/romdir-launcher.sh %ROM%\"\n    addSystem \"scummvm\"\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # ensure rom dir and system retroconfig\n    mkRomDir \"scummvm\"\n    defaultRAConfig \"scummvm\"\n\n    # unpack the data files to system dir\n    runCmd unzip -q -o \"$md_inst/scummvm.zip\" -d \"$biosdir\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/scummvm\"\n\n    # basic initial configuration (if config file not found)\n    if [[ ! -f \"$biosdir/scummvm.ini\" ]]; then\n        echo \"[scummvm]\" > \"$biosdir/scummvm.ini\"\n        iniConfig \"=\" \"\" \"$biosdir/scummvm.ini\"\n        iniSet \"extrapath\" \"$biosdir/scummvm/extra\"\n        iniSet \"themepath\" \"$biosdir/scummvm/theme\"\n        iniSet \"soundfont\" \"$biosdir/scummvm/extra/Roland_SC-55.sf2\"\n        iniSet \"gui_theme\" \"scummremastered\"\n        iniSet \"subtitles\" \"true\"\n        iniSet \"multi_midi\" \"true\"\n        iniSet \"gm_device\" \"fluidsynth\"\n        chown \"$__user\":\"$__group\" \"$biosdir/scummvm.ini\"\n    fi\n\n    # enable speed hack core option if running in arm platform\n    isPlatform \"arm\" && setRetroArchCoreOption \"scummvm_speed_hack\" \"enabled\"\n\n    # on videocore platforms, disable the HW GL context since it leads to a crash\n    isPlatform \"videocore\" && setRetroArchCoreOption \"scummvm_video_hw_acceleration\" \"disabled\"\n\n    # create retroarch launcher for lr-scummvm with support for rom directories\n    # containing svm files inside (for direct game directory launching in ES)\n    cat > \"$md_inst/romdir-launcher.sh\" << _EOF_\n#!/usr/bin/env bash\nROM=\\$1; shift\nSVM_FILES=()\n[[ -d \\$ROM ]] && mapfile -t SVM_FILES < <(compgen -G \"\\$ROM/*.svm\")\n[[ \\${#SVM_FILES[@]} -eq 1 ]] && ROM=\\${SVM_FILES[0]}\n$emudir/retroarch/bin/retroarch \\\\\n    -L \"$md_inst/scummvm_libretro.so\" \\\\\n    --config \"$md_conf_root/scummvm/retroarch.cfg\" \\\\\n    \"\\$ROM\" \"\\$@\"\n_EOF_\n    chmod +x \"$md_inst/romdir-launcher.sh\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-smsplus-gx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-smsplus-gx\"\nrp_module_desc=\"Sega Master System & Game Gear emu - SMSPlus (enhanced) port for libretro\"\nrp_module_help=\"ROM Extensions: .gg .sms .bin .zip\\nCopy your Game Gear roms to $romdir/gamegear\\nMasterSystem roms to $romdir/mastersystem\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/smsplus-gx/master/docs/license\"\nrp_module_repo=\"git https://github.com/libretro/smsplus-gx.git master\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-smsplus-gx() {\n    gitPullOrClone\n}\n\nfunction build_lr-smsplus-gx() {\n    make -f Makefile.libretro clean\n    make -f Makefile.libretro\n    md_ret_require=\"$md_build/smsplus_libretro.so\"\n}\n\nfunction install_lr-smsplus-gx() {\n    md_ret_files=(\n        'smsplus_libretro.so'\n        'docs/license'\n        'README.md'\n    )\n}\n\nfunction configure_lr-smsplus-gx() {\n    local system\n    for system in gamegear mastersystem; do\n        mkRomDir \"$system\"\n        defaultRAConfig \"$system\"\n        addEmulator 0 \"$md_id\" \"$system\" \"$md_inst/smsplus_libretro.so\"\n        addSystem \"$system\"\n    done\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-snes9x.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-snes9x\"\nrp_module_desc=\"Super Nintendo emu - Snes9x (current) port for libretro\"\nrp_module_help=\"ROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/snes9x/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/snes9x.git master\"\nrp_module_section=\"main armv6=opt armv7=opt\"\nrp_module_flags=\"nodistcc\"\n\nfunction sources_lr-snes9x() {\n    gitPullOrClone\n}\n\nfunction build_lr-snes9x() {\n    local params=()\n    isPlatform \"arm\" && params+=(platform=\"armv\")\n\n    cd libretro\n    make \"${params[@]}\" clean\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/libretro/snes9x_libretro.so\"\n}\n\nfunction install_lr-snes9x() {\n    md_ret_files=(\n        'libretro/snes9x_libretro.so'\n        'docs'\n    )\n}\n\nfunction configure_lr-snes9x() {\n    mkRomDir \"snes\"\n    defaultRAConfig \"snes\"\n\n    local def=0\n    ! isPlatform \"armv6\" && ! isPlatform \"armv7\" && def=1\n    addEmulator $def \"$md_id\" \"snes\" \"$md_inst/snes9x_libretro.so\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-snes9x2002.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-snes9x2002\"\nrp_module_desc=\"Super Nintendo emu - ARM optimised Snes9x 1.39 port for libretro\"\nrp_module_help=\"Previously called lr-pocketsnes\\n\\nROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/snes9x2002/master/src/copyright.h\"\nrp_module_repo=\"git https://github.com/libretro/snes9x2002.git master\"\nrp_module_section=\"opt armv6=main\"\nrp_module_flags=\"!all arm\"\n\nfunction _update_hook_lr-snes9x2002() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-pocketsnes\" \"lr-snes9x2002\"\n}\n\nfunction sources_lr-snes9x2002() {\n    gitPullOrClone\n}\n\nfunction build_lr-snes9x2002() {\n    make clean\n    CFLAGS=\"$CFLAGS -Wa,-mimplicit-it=thumb\" make ARM_ASM=1\n    md_ret_require=\"$md_build/snes9x2002_libretro.so\"\n}\n\nfunction install_lr-snes9x2002() {\n    md_ret_files=(\n        'snes9x2002_libretro.so'\n        'README.txt'\n    )\n}\n\nfunction configure_lr-snes9x2002() {\n    mkRomDir \"snes\"\n    defaultRAConfig \"snes\"\n\n    local def=0\n    isPlatform \"armv6\" && def=1\n    addEmulator $def \"$md_id\" \"snes\" \"$md_inst/snes9x2002_libretro.so\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-snes9x2005.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-snes9x2005\"\nrp_module_desc=\"Super Nintendo emu - Snes9x 1.43 based port for libretro\"\nrp_module_help=\"Previously called lr-catsfc\\n\\nROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/snes9x2005/master/copyright\"\nrp_module_repo=\"git https://github.com/libretro/snes9x2005.git master\"\nrp_module_section=\"opt arm=main\"\n\nfunction _update_hook_lr-snes9x2005() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-catsfc\" \"lr-snes9x2005\"\n}\n\nfunction sources_lr-snes9x2005() {\n    gitPullOrClone\n}\n\nfunction build_lr-snes9x2005() {\n    make clean\n    make\n    md_ret_require=\"$md_build/snes9x2005_libretro.so\"\n}\n\nfunction install_lr-snes9x2005() {\n    md_ret_files=(\n        'snes9x2005_libretro.so'\n    )\n}\n\nfunction configure_lr-snes9x2005() {\n    mkRomDir \"snes\"\n    defaultRAConfig \"snes\"\n\n    addEmulator 0 \"$md_id\" \"snes\" \"$md_inst/snes9x2005_libretro.so\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-snes9x2010.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-snes9x2010\"\nrp_module_desc=\"Super Nintendo emu - Snes9x 1.52 based port for libretro\"\nrp_module_help=\"Previously called lr-snes9x-next\\n\\nROM Extensions: .bin .smc .sfc .fig .swc .mgd .zip\\n\\nCopy your SNES roms to $romdir/snes\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/libretro/snes9x2010/master/docs/snes9x-license.txt\"\nrp_module_repo=\"git https://github.com/libretro/snes9x2010.git master\"\nrp_module_section=\"opt arm=main\"\n\nfunction _update_hook_lr-snes9x2010() {\n    # move from old location and update emulators.cfg\n    renameModule \"lr-snes9x-next\" \"lr-snes9x2010\"\n}\n\nfunction sources_lr-snes9x2010() {\n    gitPullOrClone\n}\n\nfunction build_lr-snes9x2010() {\n    make -f Makefile.libretro clean\n    local platform=\"\"\n    isPlatform \"arm\" && platform+=\"armv\"\n    isPlatform \"neon\" && platform+=\"neon\"\n    if [[ -n \"$platform\" ]]; then\n        make -f Makefile.libretro platform=\"$platform\"\n    else\n        make -f Makefile.libretro\n    fi\n    md_ret_require=\"$md_build/snes9x2010_libretro.so\"\n}\n\nfunction install_lr-snes9x2010() {\n    md_ret_files=(\n        'snes9x2010_libretro.so'\n        'docs'\n    )\n}\n\nfunction configure_lr-snes9x2010() {\n    mkRomDir \"snes\"\n    defaultRAConfig \"snes\"\n\n    local def=0\n    isPlatform \"armv7\" && def=1\n    addEmulator $def \"$md_id\" \"snes\" \"$md_inst/snes9x2010_libretro.so\"\n    addSystem \"snes\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-stella.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-stella\"\nrp_module_desc=\"Atari 2600 emulator - Stella core for libretro\"\nrp_module_help=\"ROM Extensions: .a26 .bin .rom .zip .gz\\n\\nCopy your Atari 2600 roms to $romdir/atari2600\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/stella-emu/stella/master/License.txt\"\nrp_module_repo=\"git https://github.com/stella-emu/stella.git master :_get_commit_lr-stella\"\nrp_module_section=\"exp\"\n\nfunction _get_commit_lr-stella() {\n    # GCC 11 is required after 2d57f9e0\n    if [[ \"$__gcc_version\" -lt 11 ]]; then\n        echo \"2d57f9e0\"\n    fi\n}\n\nfunction sources_lr-stella() {\n    gitPullOrClone\n}\n\nfunction build_lr-stella() {\n    cd src/os/libretro\n    make clean\n    make LTO=\"\"\n    md_ret_require=\"$md_build/src/os/libretro/stella_libretro.so\"\n}\n\nfunction install_lr-stella() {\n    md_ret_files=(\n        'README.md'\n        'src/os/libretro/stella_libretro.so'\n        'License.txt'\n    )\n}\n\nfunction configure_lr-stella() {\n    mkRomDir \"atari2600\"\n    defaultRAConfig \"atari2600\"\n\n    addEmulator 0 \"$md_id\" \"atari2600\" \"$md_inst/stella_libretro.so\"\n    addSystem \"atari2600\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-stella2014.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-stella2014\"\nrp_module_desc=\"Atari 2600 emulator - Stella port for libretro\"\nrp_module_help=\"ROM Extensions: .a26 .bin .rom .zip .gz\\n\\nCopy your Atari 2600 roms to $romdir/atari2600\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/stella2014-libretro/master/stella/license.txt\"\nrp_module_repo=\"git https://github.com/libretro/stella2014-libretro.git master\"\nrp_module_section=\"main\"\n\nfunction sources_lr-stella2014() {\n    gitPullOrClone\n}\n\nfunction build_lr-stella2014() {\n    make clean\n    make\n    md_ret_require=\"$md_build/stella2014_libretro.so\"\n}\n\nfunction install_lr-stella2014() {\n    md_ret_files=(\n        'README.md'\n        'stella2014_libretro.so'\n        'stella/license.txt'\n    )\n}\n\nfunction configure_lr-stella2014() {\n    mkRomDir \"atari2600\"\n    defaultRAConfig \"atari2600\"\n\n    addEmulator 1 \"$md_id\" \"atari2600\" \"$md_inst/stella2014_libretro.so\"\n    addSystem \"atari2600\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-superflappybirds.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-superflappybirds\"\nrp_module_desc=\"Super Flappy Birds - Multiplayer Flappy Bird Clone\"\nrp_module_help=\"https://github.com/IgniparousTempest/libretro-superflappybirds/wiki\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/IgniparousTempest/libretro-superflappybirds/master/LICENSE\"\nrp_module_repo=\"git https://github.com/IgniparousTempest/libretro-superflappybirds.git master\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-superflappybirds() {\n    getDepends cmake\n}\n\nfunction sources_lr-superflappybirds() {\n    gitPullOrClone\n}\n\nfunction build_lr-superflappybirds() {\n    cmake .\n    make\n    md_ret_require=\"$md_build/superflappybirds_libretro.so\"\n}\n\nfunction install_lr-superflappybirds() {\n    md_ret_files=(\n        'superflappybirds_libretro.so'\n        'resources'\n        'LICENSE'\n        'README.md'\n    )\n}\n\nfunction configure_lr-superflappybirds() {\n    setConfigRoot \"ports\"\n\n    addPort \"$md_id\" \"superflappybirds\" \"Super Flappy Birds\" \"$md_inst/superflappybirds_libretro.so\"\n\n    defaultRAConfig \"superflappybirds\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-tgbdual.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-tgbdual\"\nrp_module_desc=\"Gameboy Color emu - TGB Dual port for libretro\"\nrp_module_help=\"ROM Extensions: .gb .gbc .zip\\n\\nCopy your GameBoy roms to $romdir/gb\\n\\nCopy your GameBoy Color roms to $romdir/gbc\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/tgbdual-libretro/master/docs/COPYING-2.0.txt\"\nrp_module_repo=\"git https://github.com/libretro/tgbdual-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-tgbdual() {\n    gitPullOrClone\n}\n\nfunction build_lr-tgbdual() {\n    make clean\n    make\n    md_ret_require=\"$md_build/tgbdual_libretro.so\"\n}\n\nfunction install_lr-tgbdual() {\n    md_ret_files=(\n        'tgbdual_libretro.so'\n    )\n}\n\nfunction configure_lr-tgbdual() {\n    mkRomDir \"gbc\"\n    mkRomDir \"gb\"\n    defaultRAConfig \"gb\"\n    defaultRAConfig \"gbc\"\n\n    # enable dual / link by default\n    setRetroArchCoreOption \"tgbdual_gblink_enable\" \"enabled\"\n\n    addEmulator 0 \"$md_id\" \"gb\" \"$md_inst/tgbdual_libretro.so\"\n    addEmulator 0 \"$md_id\" \"gbc\" \"$md_inst/tgbdual_libretro.so\"\n    addSystem \"gb\"\n    addSystem \"gbc\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-theodore.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-theodore\"\nrp_module_desc=\"Thomson MO/TO system emulator\"\nrp_module_help=\"ROM Extensions: *.fd, *.sap, *.k7, *.m5, *.m7, *.rom\\n\\nAdd your game files in $romdir/moto\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/Zlika/theodore/master/LICENSE\"\nrp_module_repo=\"git https://github.com/Zlika/theodore master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction sources_lr-theodore() {\n    gitPullOrClone\n}\n\nfunction build_lr-theodore() {\n    make clean\n    make\n    md_ret_require=\"theodore_libretro.so\"\n}\n\nfunction install_lr-theodore() {\n    md_ret_files=(\n        'theodore_libretro.so'\n        'README.md'\n        'README-FR.md'\n        'LICENSE'\n    )\n}\n\nfunction configure_lr-theodore() {\n    mkRomDir \"moto\"\n    defaultRAConfig \"moto\"\n\n    addEmulator 1 \"$md_id\" \"moto\" \"$md_inst/theodore_libretro.so\"\n    addSystem \"moto\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-tic80.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-tic80\"\nrp_module_desc=\"TIC-80 fantasy computer - port for libretro\"\nrp_module_help=\"ROM Extensions: .tic .zip\\n\\nCopy your roms to $romdir/tic80\\n\\n\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/libretro/TIC-80/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/TIC-80.git master\"\nrp_module_section=\"exp\"\n\nfunction depends_lr-tic80() {\n    getDepends cmake\n}\n\nfunction sources_lr-tic80() {\n    gitPullOrClone\n}\n\nfunction build_lr-tic80() {\n    rm -rf retropie\n    mkdir -p retropie\n    cd retropie\n    cmake -DBUILD_PLAYER=OFF -DBUILD_SOKOL=OFF -DBUILD_SDL=OFF -DBUILD_DEMO_CARTS=OFF -DBUILD_LIBRETRO=ON ../core\n    make\n    md_ret_require=\"$md_build/retropie/lib/tic80_libretro.so\"\n}\n\n\nfunction install_lr-tic80() {\n    md_ret_files=(\n        'retropie/lib/tic80_libretro.so'\n        'README.md'\n        'LICENSE'\n    )\n}\n\nfunction configure_lr-tic80() {\n    mkRomDir \"tic80\"\n    defaultRAConfig \"tic80\"\n    addEmulator 1 \"$md_id\" \"tic80\" \"$md_inst/tic80_libretro.so\"\n    addSystem \"tic80\" \"TIC-80\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-tyrquake.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-tyrquake\"\nrp_module_desc=\"Quake 1 engine - Tyrquake port for libretro\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/tyrquake/master/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/libretro/tyrquake.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-tyrquake() {\n    gitPullOrClone\n}\n\nfunction build_lr-tyrquake() {\n    make clean\n    make\n    md_ret_require=\"$md_build/tyrquake_libretro.so\"\n}\n\nfunction install_lr-tyrquake() {\n    md_ret_files=(\n        'LICENSE.txt'\n        'readme-id.txt'\n        'readme.txt'\n        'tyrquake_libretro.so'\n    )\n}\n\nfunction game_data_lr-tyrquake() {\n    if [[ ! -f \"$romdir/ports/quake/id1/pak0.pak\" ]]; then\n        getDepends lhasa\n        mkUserDir \"$romdir/ports\"\n        mkUserDir \"$romdir/ports/quake\"\n        local temp=\"$(mktemp -d)\"\n        # download / unpack / install quake shareware files\n        downloadAndExtract \"$__archive_url/quake106.zip\" \"$temp\"\n        pushd \"$temp\"\n        lhasa ef resource.1\n        cp -rf id1 \"$romdir/ports/quake/\"\n        popd\n        rm -rf \"$temp\"\n        chown -R \"$__user\":\"$__group\" \"$romdir/ports/quake\"\n        chmod 644 \"$romdir/ports/quake/id1/\"*\n    fi\n}\n\nfunction _add_games_lr-tyrquake() {\n    local cmd=\"$1\"\n    declare -A games=(\n        ['id1']=\"Quake\"\n        ['hipnotic']=\"Quake Mission Pack 1 (hipnotic)\"\n        ['rogue']=\"Quake Mission Pack 2 (rogue)\"\n        ['dopa']=\"Quake Episode 5 (dopa)\"\n    )\n    local dir\n    local pak\n    for dir in \"${!games[@]}\"; do\n        pak=\"$romdir/ports/quake/$dir/pak0.pak\"\n        if [[ -f \"$pak\" ]]; then\n            addPort \"$md_id\" \"quake\" \"${games[$dir]}\" \"$cmd\" \"$pak\"\n        fi\n    done\n}\n\nfunction add_games_lr-tyrquake() {\n    _add_games_lr-tyrquake \"$md_inst/tyrquake_libretro.so\"\n}\n\nfunction configure_lr-tyrquake() {\n    setConfigRoot \"ports\"\n    mkRomDir \"ports/quake\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_lr-tyrquake\n\n    add_games_lr-tyrquake\n\n    defaultRAConfig \"quake\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-uae4arm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-uae4arm\"\nrp_module_desc=\"Uae4arm port for libretro\"\nrp_module_help=\"ROM Extensions: .adf .uae .lha .ipf .iso\\n\\nCopy your Amigas games to $romdir/amiga.\"\nrp_module_licence=\"GPL2\"\nrp_module_repo=\"git https://github.com/Chips-fr/uae4arm-rpi.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all arm aarch64\"\n\nfunction depends_lr-uae4arm() {\n    getDepends zlib1g-dev libmpg123-dev libflac-dev\n}\n\nfunction sources_lr-uae4arm() {\n    gitPullOrClone\n}\n\nfunction build_lr-uae4arm() {\n    make -f Makefile.libretro clean\n    local params=(platform=unix)\n    isPlatform \"neon\" && params=(platform=unix-neon)\n    isPlatform \"aarch64\" && params=(platform=unix-aarch64)\n    make -f Makefile.libretro \"${params[@]}\"\n    md_ret_require=\"$md_build/uae4arm_libretro.so\"\n}\n\nfunction install_lr-uae4arm() {\n    md_ret_files=(\n        'uae4arm_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-uae4arm() {\n    mkRomDir \"amiga\"\n    defaultRAConfig \"amiga\"\n    addEmulator 1 \"$md_id\" \"amiga\" \"$md_inst/uae4arm_libretro.so\"\n    addSystem \"amiga\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-vba-next.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-vba-next\"\nrp_module_desc=\"GBA emulator - VBA-M (optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .gba .zip\\n\\nCopy your Game Boy Advance roms to $romdir/gba\\n\\nCopy the required BIOS file gba_bios.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/vba-next/master/LICENSE\"\nrp_module_repo=\"git https://github.com/libretro/vba-next.git master\"\nrp_module_section=\"main\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-vba-next() {\n    gitPullOrClone\n}\n\nfunction build_lr-vba-next() {\n    make -f Makefile.libretro clean\n    if isPlatform \"neon\"; then\n        make -f Makefile.libretro platform=armvhardfloatunix TILED_RENDERING=1 HAVE_NEON=1\n    else\n        make -f Makefile.libretro\n    fi\n    md_ret_require=\"$md_build/vba_next_libretro.so\"\n}\n\nfunction install_lr-vba-next() {\n    md_ret_files=(\n        'vba_next_libretro.so'\n    )\n}\n\nfunction configure_lr-vba-next() {\n    mkRomDir \"gba\"\n    defaultRAConfig \"gba\"\n\n    addEmulator 0 \"$md_id\" \"gba\" \"$md_inst/vba_next_libretro.so\"\n    addSystem \"gba\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-vecx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-vecx\"\nrp_module_desc=\"Vectrex emulator - vecx port for libretro\"\nrp_module_help=\"ROM Extensions: .vec .gam .bin .zip\\n\\nCopy your Vectrex roms to $romdir/vectrex\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/libretro-vecx/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/libretro/libretro-vecx.git master\"\nrp_module_section=\"main\"\n\nfunction depends_lr-vecx() {\n    local depends=()\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lr-vecx() {\n    gitPullOrClone\n}\n\nfunction build_lr-vecx() {\n    local params\n    isPlatform \"videocore\" && params+=\"platform=rpi\"\n    isPlatform \"gles\" && params+=\" HAS_GLES=1\"\n\n    make clean\n    make -f Makefile.libretro $params\n    md_ret_require=\"$md_build/vecx_libretro.so\"\n}\n\nfunction install_lr-vecx() {\n    md_ret_files=(\n        'vecx_libretro.so'\n        'bios/fast.bin'\n        'bios/skip.bin'\n        'bios/system.bin'\n    )\n}\n\nfunction configure_lr-vecx() {\n    mkRomDir \"vectrex\"\n    defaultRAConfig \"vectrex\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        # Copy bios files\n        cp -v \"$md_inst/\"{fast.bin,skip.bin,system.bin} \"$biosdir/\"\n        chown \"$__user\":\"$__group\" \"$biosdir/\"{fast.bin,skip.bin,system.bin}\n    else\n        rm -f \"$biosdir/\"{fast.bin,skip.bin,system.bin}\n    fi\n\n    addEmulator 1 \"$md_id\" \"vectrex\" \"$md_inst/vecx_libretro.so\"\n    addSystem \"vectrex\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-vice.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-vice\"\nrp_module_desc=\"C64 / C128 / PET / Plus4 / VIC20 emulator - port of VICE for libretro\"\nrp_module_help=\"ROM Extensions: .cmd .crt .d64 .d71 .d80 .d81 .g64 .m3u .prg .t64 .tap .x64 .zip .vsf\\n\\nCopy your games to $romdir/c64\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/vice-libretro/master/vice/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/vice-libretro.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction _get_targets_lr-vice() {\n    echo x64 x64dtv x64sc x128 xpet xplus4 xvic\n}\n\nfunction sources_lr-vice() {\n    gitPullOrClone\n}\n\nfunction build_lr-vice() {\n    mkdir -p \"$md_build/cores\"\n    local target\n    for target in $(_get_targets_lr-vice); do\n        make clean\n        make EMUTYPE=\"$target\"\n        cp \"$md_build/vice_${target}_libretro.so\" \"cores/\"\n        md_ret_require+=(\"$md_build/cores/vice_${target}_libretro.so\")\n    done\n}\n\nfunction install_lr-vice() {\n    md_ret_files=(\n        'vice/data'\n        'vice/COPYING'\n    )\n    local target\n    for target in $(_get_targets_lr-vice); do\n        md_ret_files+=(\"cores/vice_${target}_libretro.so\")\n    done\n}\n\nfunction configure_lr-vice() {\n    mkRomDir \"c64\"\n    defaultRAConfig \"c64\"\n\n    local target\n    local name\n    local def\n    for target in $(_get_targets_lr-vice); do\n        def=0\n        name=\"-${target}\"\n        if [[ \"$target\" == \"x64\" ]]; then\n            name=\"\"\n            def=1\n        fi\n        addEmulator \"$def\" \"$md_id${name}\" \"c64\" \"$md_inst/vice_${target}_libretro.so\"\n    done\n    \n    addSystem \"c64\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    if isPlatform \"arm\"; then\n        setRetroArchCoreOption \"vice_sid_engine\" \"FastSID\"\n        isPlatform \"armv6\" && setRetroArchCoreOption \"vice_sound_sample_rate\" \"22050\"\n    fi\n\n    cp -R \"$md_inst/data\" \"$biosdir\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir/data\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-virtualjaguar.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-virtualjaguar\"\nrp_module_desc=\"Atari Jaguar emu - Virtual Jaguar (optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .j64 .jag .zip\\n\\nCopy your Atari Jaguar roms to $romdir/atarijaguar\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/libretro/virtualjaguar-libretro/master/docs/GPLv3\"\nrp_module_repo=\"git https://github.com/libretro/virtualjaguar-libretro.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-virtualjaguar() {\n    gitPullOrClone\n}\n\nfunction build_lr-virtualjaguar() {\n    make clean\n    make\n    md_ret_require=\"$md_build/virtualjaguar_libretro.so\"\n}\n\nfunction install_lr-virtualjaguar() {\n    md_ret_files=(\n        'virtualjaguar_libretro.so'\n        'README.md'\n    )\n}\n\nfunction configure_lr-virtualjaguar() {\n    mkRomDir \"atarijaguar\"\n    defaultRAConfig \"atarijaguar\"\n\n    addEmulator 1 \"$md_id\" \"atarijaguar\" \"$md_inst/virtualjaguar_libretro.so\"\n    addSystem \"atarijaguar\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-x1.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-x1\"\nrp_module_desc=\"Sharp X1 emulator - X Millenium port for libretro\"\nrp_module_help=\"ROM Extensions: .dx1 .zip .2d .2hd .tfd .d88 .88d .hdm .xdf .dup .cmd\\n\\nCopy your X1 roms to $romdir/x1\\n\\nCopy the required BIOS files IPLROM.X1 and IPLROM.X1T to $biosdir\"\nrp_module_repo=\"git https://github.com/libretro/xmil-libretro.git master\"\nrp_module_licence=\"BSD https://raw.githubusercontent.com/libretro/xmil-libretro/master/LICENSE\"\nrp_module_section=\"exp\"\n\nfunction sources_lr-x1() {\n    gitPullOrClone\n}\n\nfunction build_lr-x1() {\n    cd libretro\n    make clean\n    make\n    md_ret_require=\"$md_build/libretro/x1_libretro.so\"\n}\n\nfunction install_lr-x1() {\n    md_ret_files=(\n        'libretro/x1_libretro.so'\n    )\n}\n\nfunction configure_lr-x1() {\n    mkRomDir \"x1\"\n    defaultRAConfig \"x1\"\n\n    addEmulator 1 \"$md_id\" \"x1\" \"$md_inst/x1_libretro.so\"\n    addSystem \"x1\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-xrick.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-xrick\"\nrp_module_desc=\"Open source implementation of Rick Dangerous - xrick ported for libretro\"\nrp_module_help=\"Install the xrick data.zip to $romdir/ports/xrick/data.zip\"\nrp_module_licence=\"GPL https://raw.githubusercontent.com/libretro/xrick-libretro/master/README\"\nrp_module_repo=\"git https://github.com/libretro/xrick-libretro.git master\"\nrp_module_section=\"opt\"\n\nfunction sources_lr-xrick() {\n    gitPullOrClone\n}\n\nfunction build_lr-xrick() {\n    make clean\n    make\n    md_ret_require=\"$md_build/xrick_libretro.so\"\n}\n\nfunction install_lr-xrick() {\n    md_ret_files=(\n        'README'\n        'README.md'\n        'xrick_libretro.so'\n    )\n}\n\nfunction configure_lr-xrick() {\n    setConfigRoot \"ports\"\n\n    addPort \"$md_id\" \"xrick\" \"XRick\" \"$md_inst/xrick_libretro.so\" \"$romdir/ports/xrick/data.zip\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    defaultRAConfig \"xrick\"\n}\n"
  },
  {
    "path": "scriptmodules/libretrocores/lr-yabause.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lr-yabause\"\nrp_module_desc=\"Sega Saturn emu - Yabause (optimised) port for libretro\"\nrp_module_help=\"ROM Extensions: .iso .bin .zip\\n\\nCopy your Sega Saturn roms to $romdir/saturn\\n\\nCopy the required BIOS file saturn_bios.bin to $biosdir\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libretro/yabause/master/yabause/COPYING\"\nrp_module_repo=\"git https://github.com/libretro/yabause.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!armv6\"\n\nfunction sources_lr-yabause() {\n    gitPullOrClone\n}\n\nfunction build_lr-yabause() {\n    local params=()\n    cd yabause/src/libretro\n    isPlatform \"neon\" && params+=(platform=armvneonhardfloat)\n    ! isPlatform \"x86\" && params+=(HAVE_SSE=0)\n    make \"${params[@]}\" clean\n    make \"${params[@]}\"\n    md_ret_require=\"$md_build/yabause/src/libretro/yabause_libretro.so\"\n}\n\nfunction install_lr-yabause() {\n    md_ret_files=(\n        'yabause/src/libretro/yabause_libretro.so'\n        'yabause/COPYING'\n        'yabause/ChangeLog'\n        'yabause/AUTHORS'\n        'yabause/README'\n    )\n}\n\nfunction configure_lr-yabause() {\n    mkRomDir \"saturn\"\n    defaultRAConfig \"saturn\"\n\n    addEmulator 1 \"$md_id\" \"saturn\" \"$md_inst/yabause_libretro.so\"\n    addSystem \"saturn\"\n}\n"
  },
  {
    "path": "scriptmodules/packages.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\ndeclare -A __sections=(\n    [core]=\"core\"\n    [main]=\"main\"\n    [opt]=\"optional\"\n    [exp]=\"experimental\"\n    [driver]=\"driver\"\n    [config]=\"configuration\"\n    [depends]=\"dependency\"\n)\n\n__NET_ERRMSG=\"\"\n\nfunction rp_listFunctions() {\n    local id\n    local desc\n    local mode\n    local func\n    local enabled\n\n    echo -e \"ID:                 Description:                                 List of available functions\"\n    echo \"-----------------------------------------------------------------------------------------------------------------------------------\"\n    for id in ${__mod_id[@]}; do\n        if rp_isEnabled \"$id\"; then\n            printf \"%-20s: %-42s :\" \"$id\" \"${__mod_info[$id/desc]}\"\n        else\n            printf \"*%-20s: %-42s : %s\\n\" \"$id\" \"${__mod_info[$id/desc]}\" \"This module is not available for your platform\"\n            continue\n        fi\n        while read mode; do\n            # skip private module functions (start with an underscore)\n            [[ \"$mode\" = _* ]] && continue\n            mode=${mode//_$id/}\n            echo -n \" $mode\"\n        done < <(compgen -A function -X \\!*_$id)\n        fnExists \"sources_${id}\" && echo -n \" clean\"\n        fnExists \"install_${id}\" || fnExists \"install_bin_${id}\" && ! fnExists \"remove_${id}\" && echo -n \" remove\"\n        echo \"\"\n    done\n    echo \"===================================================================================================================================\"\n}\n\nfunction rp_printUsageinfo() {\n    echo -e \"Usage:\\n$0 <ID>\\nThis will run the functions depends, sources, build, install, configure and clean automatically.\\n\"\n    echo -e \"Alternatively, $0 can be called as\\n$0 <ID> [function] where function is a supported module functions as listed below\\n\"\n    echo    \"Details of some common functions:\"\n    echo    \"depends:    install the dependencies for the module.\"\n    echo    \"sources:    install the sources for the module\"\n    echo    \"build:      build/compile the module\"\n    echo    \"install:    install the compiled module\"\n    echo    \"configure:  configure the installed module (es_systems.cfg / launch parameters etc)\"\n    echo    \"clean:      remove the sources/build folder for the module\"\n    echo    \"remove:     remove/uninstall the module\"\n    echo    \"help:       get additional help on the module (available for all modules)\"\n    echo -e \"\\nThis is a list of valid modules/packages and supported functions:\\n\"\n    rp_listFunctions\n}\n\nfunction rp_moduleVars() {\n    local id=\"$1\"\n\n    # create variables that can be used in modules\n    local code\n    read -d \"\" -r code <<_EOF_\n        local md_desc=\"${__mod_info[$id/desc]}\"\n        local md_help=\"${__mod_info[$id/help]}\"\n        local md_type=\"${__mod_info[$id/type]}\"\n        local md_flags=\"${__mod_info[$id/flags]}\"\n        local md_path=\"${__mod_info[$id/path]}\"\n\n        local md_licence=\"${__mod_info[$id/licence]}\"\n\n        local md_repo_type=\"${__mod_info[$id/repo_type]}\"\n        local md_repo_url=\"${__mod_info[$id/repo_url]}\"\n        local md_repo_branch=\"${__mod_info[$id/repo_branch]}\"\n        local md_repo_commit=\"${__mod_info[$id/repo_commit]}\"\n\n        local md_build=\"$__builddir/$id\"\n        local md_inst=\"$(rp_getInstallPath $id)\"\n        # get module path folder + md_id for $md_data\n        local md_data=\"${__mod_info[$id/path]%/*}/$id\"\n_EOF_\n\n    echo \"$code\"\n}\n\nfunction rp_callModule() {\n    local md_id=\"$1\"\n    local mode=\"$2\"\n    # shift the function parameters left so $@ will contain any additional parameters which we can use in modules\n    shift 2\n\n    # check if module exists\n    if ! rp_hasModule \"$md_id\"; then\n        printMsgs \"console\" \"No module '$md_id' found.\"\n        return 2\n    fi\n\n    # check if module is enabled for platform\n    if ! rp_isEnabled \"$md_id\"; then\n        printMsgs \"console\" \"Module '$md_id' is not available for your system ($__platform)\"\n        return 3\n    fi\n\n    # skip for modules 'builder' and 'setup' so that distcc settings do not propagate from them\n    if [[ \"$md_id\" != \"builder\" && \"$md_id\" != \"setup\" ]]; then\n        # if distcc is used and the module doesn't exclude it, add /usr/lib/distcc to PATH and MAKEFLAGS\n        if [[ -n \"$DISTCC_HOSTS\" ]] && ! hasFlag \"${__mod_info[$md_id/flags]}\" \"nodistcc\"; then\n            # use local variables so they are available to all child functions without changing the globals \n            local PATH=\"/usr/lib/distcc:$PATH\"\n            local MAKEFLAGS=\"$MAKEFLAGS PATH=$PATH\"\n        fi\n    fi\n\n    # parameters _auto_ _binary or _source_ (_source_ is used if no parameters are given for a module)\n    case \"$mode\" in\n        # install the module if not installed, and update if it is\n        _autoupdate_)\n            if rp_isInstalled \"$md_id\"; then\n                rp_callModule \"$md_id\" \"_update_\" || return 1\n            else\n                rp_callModule \"$md_id\" \"_auto_\" || return 1\n            fi\n            return 0\n            ;;\n        # automatic modes used by rp_installModule to choose between binary/source based on pkg info\n        _auto_|_update_)\n            # if updating and a package isn't installed, return an error\n            if [[ \"$mode\" == \"_update_\" ]] && ! rp_isInstalled \"$md_id\"; then\n                __ERRMSGS+=(\"$md_id is not installed, so can't update\")\n                return 1\n            fi\n\n            rp_loadPackageInfo \"$md_id\" \"pkg_origin\"\n            local pkg_origin=\"${__mod_info[$md_id/pkg_origin]}\"\n\n            local has_binary=0\n            local has_net=0\n\n            isConnected && has_net=1\n\n            # for modules with nonet flag that don't need to download data, we force has_net to 1\n            hasFlag \"${__mod_info[$md_id/flags]}\" \"nonet\" && has_net=1\n\n            if [[ \"$has_net\" -eq 1 ]]; then\n                rp_hasBinary \"$md_id\"\n                local ret=\"$?\"\n                [[ \"$ret\" -eq 0 ]] && has_binary=1\n                [[ \"$ret\" -eq 2 ]] && has_net=0\n            fi\n\n            # fail if we don't seem to be connected\n            if [[ \"$has_net\" -eq 0 ]]; then\n                __ERRMSGS+=(\"Can't install/update $md_id - $__NET_ERRMSG\")\n                return 1\n            fi\n\n            local do_update=0\n\n            # if we are in _update_ mode we only update if there is a newer version of the binary or source\n            if [[ \"$mode\" == \"_update_\" ]]; then\n                printMsgs \"heading\" \"Checking for updates for $md_id\"\n                rp_hasNewerModule \"$md_id\" \"$pkg_origin\"\n                [[ \"$?\" -eq 0 || \"$?\" == 2 ]] && do_update=1\n                # if rp_hasNewerModule returns 3, then there was an error and we should abort\n                [[ \"$?\" -eq 3 ]] && return 1\n            else\n                do_update=1\n            fi\n\n            if [[ \"$do_update\" -eq 1 ]]; then\n                printMsgs \"console\" \"Update is available - updating ...\"\n            else\n                printMsgs \"console\" \"No update was found.\"\n            fi\n\n            if [[ \"$do_update\" -eq 1 ]]; then\n                if [[ \"$pkg_origin\" != \"source\" && \"$has_binary\" -eq 1 ]]; then\n                    rp_callModule \"$md_id\" _binary_ || return 1\n                else\n                    rp_callModule \"$md_id\" _source_ || return 1\n                fi\n            fi\n            return 0\n            ;;\n        _binary_)\n            for mode in depends install_bin configure; do\n                rp_callModule \"$md_id\" \"$mode\" || return 1\n            done\n            return 0\n            ;;\n        # automatically build/install module from source if no _source_ or no parameters are given\n        \"\"|_source_)\n            for mode in depends sources build install configure clean; do\n                rp_callModule \"$md_id\" \"$mode\" || return 1\n            done\n            return 0\n            ;;\n    esac\n\n    # load our md_* variables\n    eval \"$(rp_moduleVars $md_id)\"\n\n    local md_mode=\"install\"\n\n    # set md_conf_root to $configdir and to $configdir/ports for ports\n    # ports in libretrocores or systems (as ES sees them) in ports will need to change it manually with setConfigRoot\n    local md_conf_root\n    if [[ \"$md_type\" == \"ports\" ]]; then\n        setConfigRoot \"ports\"\n    else\n        setConfigRoot \"\"\n    fi\n\n    case \"$mode\" in\n        # remove sources\n        clean)\n            if [[ \"$__persistent_repos\" -eq 1 ]]; then\n                if [[ -d \"$md_build/.git\" ]]; then\n                    git -C \"$md_build\" reset --hard\n                    git -C \"$md_build\" clean -f -d\n                fi\n            else\n                rmDirExists \"$md_build\"\n            fi\n            return 0\n            ;;\n        # create binary archive\n        create_bin)\n            rp_createBin || return 1\n            return 0\n            ;;\n        # echo module help to console\n        help)\n            printMsgs \"console\" \"$md_desc\\n\\n$md_help\"\n            return 0;\n            ;;\n    esac\n\n    # create function name\n    function=\"${mode}_${md_id}\"\n\n    # automatically switch to install_bin if present while install is not, and handle cases where we have\n    # fallback functions when not present in modules - currently install_bin and remove\n    if ! fnExists \"$function\"; then\n        if [[ \"$mode\" == \"install\" ]] && fnExists \"install_bin_${md_id}\"; then\n            function=\"install_bin_${md_id}\"\n            mode=\"install_bin\"\n        elif [[ \"$mode\" != \"install_bin\" && \"$mode\" != \"remove\" ]]; then\n            return 0\n        fi\n    fi\n\n    # these can be returned by a module\n    local md_ret_require=()\n    local md_ret_files=()\n    local md_ret_errors=()\n    local md_ret_info=()\n\n    local action\n    local pushed=1\n    case \"$mode\" in\n        depends)\n            if [[ \"$1\" == \"remove\" ]]; then\n                md_mode=\"remove\"\n                action=\"Removing\"\n            else\n                action=\"Installing\"\n            fi\n            action+=\" dependencies for\"\n            ;;\n        sources)\n            action=\"Getting sources for\"\n            mkdir -p \"$md_build\"\n            pushd \"$md_build\"\n            pushed=$?\n            ;;\n        build)\n            action=\"Building\"\n            pushd \"$md_build\" 2>/dev/null\n            pushed=$?\n            ;;\n        install)\n            pushd \"$md_build\" 2>/dev/null\n            pushed=$?\n            ;;\n        install_bin)\n            action=\"Installing (binary)\"\n            ;;\n        configure)\n            action=\"Configuring\"\n            pushd \"$md_inst\" 2>/dev/null\n            pushed=$?\n            ;;\n        remove)\n            action=\"Removing\"\n            ;;\n        _update_hook)\n            ;;\n        *)\n            action=\"Running action '$mode' for\"\n            ;;\n    esac\n\n    # print an action and a description\n    if [[ -n \"$action\" ]]; then\n        printHeading \"$action '$md_id' : $md_desc\"\n    fi\n\n    case \"$mode\" in\n        remove)\n            fnExists \"$function\" && \"$function\" \"$@\"\n            md_mode=\"remove\"\n            if fnExists \"configure_${md_id}\"; then\n                pushd \"$md_inst\" 2>/dev/null\n                pushed=$?\n                \"configure_${md_id}\"\n            fi\n            rm -rf \"$md_inst\"\n            rp_clearCachedInfo \"$md_id\"\n            printMsgs \"console\" \"Removed directory $md_inst\"\n            ;;\n        install)\n            action=\"Installing\"\n            # remove any previous install folder unless noinstclean flag is set\n            if ! hasFlag \"${__mod_info[$md_id/flags]}\" \"noinstclean\"; then\n                rmDirExists \"$md_inst\"\n            fi\n            mkdir -p \"$md_inst\"\n            \"$function\" \"$@\"\n            ;;\n        install_bin)\n            if fnExists \"install_bin_${md_id}\"; then\n                mkdir -p \"$md_inst\"\n                if ! \"$function\" \"$@\"; then\n                    md_ret_errors+=(\"Unable to install binary for $md_id\")\n                fi\n            else\n                if rp_hasBinary \"$md_id\"; then\n                    rp_installBin\n                else\n                    md_ret_errors+=(\"Could not find a binary for $md_id\")\n                fi\n            fi\n            ;;\n        *)\n            # call the function with parameters\n            \"$function\" \"$@\"\n            ;;\n    esac\n\n    # check if any required files are found\n    if [[ -n \"$md_ret_require\" ]]; then\n        for file in \"${md_ret_require[@]}\"; do\n            if [[ ! -e \"$file\" ]]; then\n                md_ret_errors+=(\"Could not successfully $mode $md_id - $md_desc ($file not found).\")\n                break\n            fi\n        done\n    fi\n\n    if [[ \"${#md_ret_errors}\" -eq 0 && -n \"$md_ret_files\" ]]; then\n        # check for existence and copy any files/directories returned\n        local file\n        for file in \"${md_ret_files[@]}\"; do\n            if [[ ! -e \"$md_build/$file\" ]]; then\n                md_ret_errors+=(\"Could not successfully install $md_desc ($md_build/$file not found).\")\n                break\n            fi\n            cp -Rvf \"$md_build/$file\" \"$md_inst\"\n        done\n    fi\n\n    # remove build folder if empty\n    [[ -d \"$md_build\" ]] && find \"$md_build\" -maxdepth 0 -empty -exec rmdir {} \\;\n\n    local ret=0\n    # some errors were returned.\n    if [[ \"${#md_ret_errors[@]}\" -gt 0 ]]; then\n        __ERRMSGS+=(\"${md_ret_errors[@]}\")\n        printMsgs \"console\" \"${md_ret_errors[@]}\" >&2\n        # if sources fails and we were called from the setup gui module clean sources\n        if [[ \"$mode\" == \"sources\" && \"$__setup\" -eq 1 ]]; then\n            rp_callModule \"$md_id\" clean\n        fi\n        # remove install folder if there is an error (and it is empty)\n        [[ -d \"$md_inst\" ]] && find \"$md_inst\" -maxdepth 0 -empty -exec rmdir {} \\;\n        ret=1\n    else\n        [[ \"$mode\" == \"install_bin\" ]] && rp_setPackageInfo \"$md_id\" \"binary\"\n        [[ \"$mode\" == \"install\" ]] && rp_setPackageInfo \"$md_id\" \"source\"\n        # handle the case of a few drivers that don't have an install function and set the package info at build stage\n        if ! fnExists \"install_${md_id}\" && [[ \"$mode\" == \"build\" ]]; then\n            rp_setPackageInfo \"$md_id\" \"source\"\n        fi\n    fi\n\n    # some information messages were returned\n    if [[ \"${#md_ret_info[@]}\" -gt 0 ]]; then\n        __INFMSGS+=(\"${md_ret_info[@]}\")\n    fi\n\n    [[ \"$pushed\" -eq 0 ]] && popd\n\n    return \"$ret\"\n}\n\nfunction rp_hasBinaries() {\n    [[ \"$__has_binaries\" -eq 1 ]] && return 0\n    return 1\n}\n\nfunction rp_getBinaryUrl() {\n    local id=\"$1\"\n    local url=\"\"\n    rp_hasBinaries && url=\"$__binary_url/${__mod_info[$id/type]}/$id.tar.gz\"\n    if fnExists \"install_bin_${id}\"; then\n        if fnExists \"__binary_url_${id}\"; then\n            url=\"$(__binary_url_${id})\"\n        else\n            url=\"notest\"\n        fi\n    fi\n    echo \"$url\"\n}\n\n# returns 0 if file exists, 1 if it doesn't and 2 on other error\nfunction rp_remoteFileExists() {\n    local url=\"$1\"\n    local ret\n    # runCurl will cause stderr to be copied to output so we redirect both stdout/stderr to /dev/null.\n    # any errors will have been captured by runCurl\n    runCurl --location --max-time 10 --silent --show-error --fail --head \"$url\" &>/dev/null\n    ret=\"$?\"\n    if [[ \"$ret\" -eq 0 ]]; then\n        return 0\n    elif [[ \"$ret\" -eq 22 ]]; then\n        return 1\n    else\n        return 2\n    fi\n}\n\nfunction rp_hasBinary() {\n    local id=\"$1\"\n\n    # binary blacklist for armv7 Debian/OSMC due to GCC ABI incompatibility with\n    # threaded C++ apps on Raspbian (armv6 userland)\n    if [[ \"$__os_id\" != \"Raspbian\" ]] && ! isPlatform \"armv6\"; then\n        case \"$id\" in\n            emulationstation|lzdoom|lr-dinothawr|lr-ppsspp|ppsspp)\n                return 1\n                ;;\n        esac\n    fi\n\n    local url=\"$(rp_getBinaryUrl $id)\"\n    [[ \"$url\" == \"notest\" ]] && return 0\n    [[ -z \"$url\" ]] && return 1\n\n    [[ -n \"${__mod_info[$id/has_binary]}\" ]] && return \"${__mod_info[$id/has_binary]}\"\n\n    local ret=1\n    rp_remoteFileExists \"$url\"\n    ret=\"$?\"\n\n    # if there wasn't an error, cache the result\n    [[ \"$ret\" -ne 2 ]] && __mod_info[$id/has_binary]=\"$ret\"\n    return \"$ret\"\n}\n\nfunction rp_getFileDate() {\n    local url=\"$1\"\n    [[ -z \"$url\" ]] && return 1\n\n    # get last-modified date stripping any CR in the output\n    local file_date=$(runCurl --location --silent --fail --head --no-styled-output \"$url\" | tr -d \"\\r\" | grep -ioP \"last-modified: \\K.+\")\n    # if there is a date set in last-modified header, then convert to iso-8601 format\n    if [[ -n \"$file_date\" ]]; then\n        file_date=\"$(date -Iseconds --date=\"$file_date\")\"\n        echo \"$file_date\"\n        return 0\n    fi\n    return 1\n}\n\nfunction rp_getBinaryDate() {\n    local id=\"$1\"\n    local url=\"$(rp_getBinaryUrl $id)\"\n    [[ -z \"$url\" || \"$url\" == \"notest\" ]] && return 1\n    local bin_date\n    if bin_date=\"$(rp_getFileDate \"$url\")\"; then\n        echo \"$bin_date\"\n        return 0\n    fi\n    return 1\n}\n\nfunction rp_dateIsNewer() {\n    local date_a=\"$1\"\n    local date_b=\"$2\"\n    [[ -z \"$date_a\" || -z \"$date_b\" ]] && return 0\n    if date_a=\"$(date -d \"$date_a\" +%s 2>/dev/null)\" && date_b=\"$(date -d \"$date_b\" +%s 2>/dev/null)\"; then\n        [[ \"$date_b\" -gt \"$date_a\" ]] && return 0\n    else\n        return 0\n    fi\n    return 1\n}\n\n# resolve repository parameters - any parameters with a : will get the data from the following function name\nfunction rp_resolveRepoParam() {\n    local param=\"$1\"\n    if [[ \"$param\" == :* ]]; then\n        param=\"${param:1}\"\n        if fnExists \"$param\"; then\n            echo \"$($param)\"\n            return\n        fi\n    fi\n    echo \"$param\"\n}\n\n# gets remote repository hash/revision - echos hash of remote repo and returns 0, or\n# echos an error and returns 1 on failure\nfunction rp_getRemoteRepoHash() {\n    local type=\"$1\"\n    local url=\"$2\"\n    local branch=\"$3\"\n    local commit=\"$4\"\n    local hash\n    local ret\n    local cmd=()\n    set -o pipefail\n    case \"$type\" in\n        git)\n            # when the remote repository uses an annotated git tag, the real commit is found by looking for the\n            # \"tag^{}\" reference, since the tag ref will point to the tag object itself, instead of the tagged\n            # commit. See gitrevisions(7).\n            cmd=(git ls-remote \"$url\" \"$branch\" \"$branch^{}\")\n            # grep to make sure we only return refs/heads/BRANCH and refs/tags/BRANCH in case there are additional\n            # references to the branch/tag eg refs/heads/SOMETHINGELSE/master which can be the case.\n            # we grab the last match reported by grep, as tags that also have a tag^{} reference\n            # will be displayed after.\n            hash=$(\"${cmd[@]}\" 2>/dev/null | grep -P \"\\trefs/(heads|tags)/$branch\" | tail -n1 | cut -f1)\n            ;;\n        svn)\n            cmd=(svn info -r\"$commit\" \"$url\")\n            hash=$(\"${cmd[@]}\" 2>/dev/null | grep -oP \"Last Changed Rev: \\K.*\")\n            ;;\n    esac\n    ret=\"$?\"\n    set +o pipefail\n    if [[ \"$ret\" -ne 0 ]]; then\n        echo \"${cmd[*]} failed with return code $ret - please check your network connection\"\n        return 1\n    fi\n    echo \"$hash\"\n    return 0\n}\n\n# returns 0 if a module has a newer version, 1 if it doesn't, 2 if unknown (always update), or 3 if there is an error\nfunction rp_hasNewerModule() {\n    local id=\"$1\"\n    local type=\"$2\"\n\n    [[ -n \"${__mod_info[$id/has_newer]}\" ]] && return \"${__mod_info[$id/has_newer]}\"\n\n    rp_loadPackageInfo \"$id\"\n    local pkg_origin=\"${__mod_info[$id/pkg_origin]}\"\n    local pkg_date=\"${__mod_info[$id/pkg_date]}\"\n    local pkg_repo_date=\"${__mod_info[$id/pkg_repo_date]}\"\n    local pkg_repo_commit=\"${__mod_info[$id/pkg_repo_commit]}\"\n\n    local ret=1\n    case \"$type\" in\n        binary)\n            ret=\"\"\n            if [[ -n \"$pkg_date\" ]]; then\n                local bin_date=\"$(rp_getBinaryDate $id)\"\n                if [[ -n \"$bin_date\" ]]; then\n                    rp_dateIsNewer \"$pkg_date\" \"$bin_date\"\n                    ret=\"$?\"\n                fi\n            fi\n            [[ -z \"$ret\" ]] && ret=2\n            ;;\n        source)\n            local repo_type=\"${__mod_info[$id/repo_type]}\"\n            local repo_url=\"$(rp_resolveRepoParam \"${__mod_info[$id/repo_url]}\")\"\n            case \"$repo_type\" in\n                file)\n                    if [[ -n \"$pkg_repo_date\" ]]; then\n                        local file_date=\"$(rp_getFileDate \"$repo_url\")\"\n                        rp_dateIsNewer \"$pkg_repo_date\" \"$file_date\"\n                        ret=\"$?\"\n                    fi\n                    ;;\n                git|svn)\n                    local repo_branch=\"$(rp_resolveRepoParam \"${__mod_info[$id/repo_branch]}\")\"\n                    local repo_commit=\"$(rp_resolveRepoParam \"${__mod_info[$id/repo_commit]}\")\"\n                    # if we are locked to a single commit, then we compare against the current module commit only\n                    if [[ -n \"$repo_commit\" && \"$repo_commit\" != \"HEAD\" ]]; then\n                        # if we are using git and the module has a commit hash, then adjust\n                        # the package commit length for the comparison\n                        if [[ \"$repo_type\" == \"git\" && \"${#repo_commit}\" -ge 4 ]]; then\n                            pkg_repo_commit=\"${pkg_repo_commit::${#repo_commit}}\"\n                        fi\n                        if [[ \"$pkg_repo_commit\" != \"$repo_commit\" ]]; then\n                            ret=0\n                        fi\n                    else\n                        local remote_commit\n                        if remote_commit=\"$(rp_getRemoteRepoHash \"$repo_type\" \"$repo_url\" \"$repo_branch\" \"$repo_commit\")\"; then\n                            if [[ -n \"$remote_commit\" && \"$pkg_repo_commit\" != \"$remote_commit\" ]]; then\n                                ret=0\n                            fi\n                        else\n                            __ERRMSGS+=(\"$remote_commit\")\n                            ret=3\n                        fi\n                    fi\n                    ;;\n                :*)\n                    local pkg_repo_extra=\"${__mod_info[$id/pkg_repo_extra]}\"\n                    # handle checking via module function - function should return 0 if there is a newer version\n                    local function=\"${repo_type:1}\"\n                    if fnExists \"$function\"; then\n                        \"$function\" newer\n                        ret=\"$?\"\n                    fi\n                    ;;\n                *)\n                    # fallback on forcing an update\n                    ret=2\n                    ;;\n            esac\n\n            # if we are currently not going to update - check the last commit date of the module code\n            # if it's newer than the install date of the module we force an update, in case patches or build\n            # related options have been changed\n            if [[ \"$ret\" -eq 1 && \"$__ignore_module_date\" -ne 1 ]]; then\n                local vendor=\"${__mod_info[$id/vendor]}\"\n                local repo_dir=\"$scriptdir\"\n                [[ \"$vendor\" != \"RetroPie\" ]] && repo_dir+=\"/ext/$vendor\"\n                local module_date=\"$(sudo -u \"$__user\" git -C \"$repo_dir\" log -1 --format=%cI -- \"${__mod_info[$id/path]}\")\"\n                # just in case the module is not known to git, get the file last modified date\n                [[ -z \"$module_date\" ]] && module_date=\"$(date -Iseconds -r \"${__mod_info[$id/path]}\")\"\n                if rp_dateIsNewer \"$pkg_date\" \"$module_date\"; then\n                    ret=0\n                fi\n            fi\n            ;;\n        *)\n            # for unknown or in the case of a blank pkg_origin assume there is an update\n            ret=2\n            ;;\n    esac\n\n    # cache our return value\n    __mod_info[$id/has_newer]=\"$ret\"\n\n    return \"$ret\"\n}\n\nfunction rp_getInstallPath() {\n    local id=\"$1\"\n    echo \"$rootdir/${__mod_info[$id/type]}/$id\"\n}\n\nfunction rp_installBin() {\n    rp_hasBinaries || fatalError \"There are no binary archives for platform $__platform\"\n    local archive=\"$md_id.tar.gz\";\n    local dest=\"$rootdir/$md_type\"\n\n    local cmd_out\n\n    # create temporary folder\n    local tmp=$(mktemp -d)\n\n    if downloadAndVerify \"$__binary_url/$md_type/$archive\" \"$tmp/$archive\"; then\n        mkdir -p \"$dest\"\n        rm -rf \"$dest/$md_id\"\n        if tar -xvf \"$tmp/$archive\" -C \"$dest\"; then\n            rm -rf \"$tmp\"\n            return 0\n        else\n            md_ret_errors+=(\"Archive $archive failed to unpack correctly to $dest\")\n        fi\n    fi\n\n    rm -rf \"$tmp\"\n    return 1\n}\n\nfunction rp_createBin() {\n    printHeading \"Creating binary archive for $md_desc\"\n\n    if [[ ! -d \"$md_inst\" ]]; then\n        printMsgs \"console\" \"No install directory $md_inst - no archive created\"\n        return 1\n    fi\n\n    if dirIsEmpty \"$md_inst\"; then\n        printMsgs \"console\" \"Empty install directory $md_inst - no archive created\"\n        return 1\n    fi\n\n    local archive=\"$md_id.tar.gz\"\n    local dest=\"$__tmpdir/archives/$__binary_path/$md_type\"\n    mkdir -p \"$dest\"\n    rm -f \"$dest/$archive\" \"$dest/$archive.asc\"\n    local ret=1\n    if tar cvzf \"$dest/$archive\" -C \"$rootdir/$md_type\" \"$md_id\"; then\n        if [[ -n \"$__gpg_signing_key\" ]]; then\n            if signFile \"$dest/$archive\"; then\n                chown \"$__user\":\"$__group\" \"$dest/$archive\" \"$dest/$archive.asc\"\n                ret=0\n            fi\n        else\n            ret=0\n        fi\n    fi\n    if [[ \"$ret\" -eq 0 ]]; then\n        cp \"$md_inst/retropie.pkg\" \"$dest/$md_id.pkg\"\n    else\n        rm -f \"$dest/$archive\"\n    fi\n    return \"$ret\"\n}\n\nfunction rp_hasModule() {\n    local id=\"$1\"\n    [[ -n \"${__mod_idx[$id]}\" ]] && return 0\n    return 1\n}\n\nfunction rp_installModule() {\n    local id=\"$1\"\n    local mode=\"$2\"\n    [[ -z \"$mode\" ]] && mode=\"_auto_\"\n    rp_callModule \"$id\" \"$mode\" || return 1\n    return 0\n}\n\nfunction rp_clearCachedInfo() {\n    local id=\"$1\"\n    # clear cached data\n    # set pkg_info to 0 to force a reload when needed\n    __mod_info[$id/pkg_info]=0\n    __mod_info[$id/has_binary]=\"\"\n    __mod_info[$id/has_newer]=\"\"\n}\n\n# this is run after the install_ID function for a module - which by default would be from the\n# folder set by md_build. However some modules install directly to md_inst which would mean unless\n# they change directory also to md_inst in the install stage (which is common), it's possible this\n# function could be run and not find the source. Therefore, we currently record the first directory used\n# by gitPullOrClone and record it in __mod_info to be used here - but this needs further work to handle\n# other cases.\nfunction rp_setPackageInfo() {\n    local id=\"$1\"\n    local install_path=\"$(rp_getInstallPath $id)\"\n    [[ ! -d \"$install_path\" ]] && return 1\n    local pkg=\"$install_path/retropie.pkg\"\n    local origin=\"$2\"\n\n    rp_clearCachedInfo \"$id\"\n\n    iniConfig \"=\" '\"' \"$pkg\"\n    iniSet \"pkg_origin\" \"$origin\"\n    local pkg_date\n    local pkg_repo_type\n    local pkg_repo_url\n    local pkg_repo_branch\n    local pkg_repo_commit\n    local pkg_repo_date\n    local pkg_repo_extra\n\n    if [[ \"$origin\" == \"binary\" ]]; then\n        pkg_date=\"$(rp_getBinaryDate $id)\"\n        iniSet \"pkg_date\" \"$pkg_date\"\n    else\n        pkg_date=\"$(date -Iseconds)\"\n        pkg_repo_type=\"${__mod_info[$id/repo_type]}\"\n        pkg_repo_url=\"$(rp_resolveRepoParam \"${__mod_info[$id/repo_url]}\")\"\n        pkg_repo_branch=\"$(rp_resolveRepoParam \"${__mod_info[$id/repo_branch]}\")\"\n        case \"$pkg_repo_type\" in\n            git|svn)\n                if [[ \"$pkg_repo_type\" == \"git\" ]]; then\n                    # if we have recorded a source install dir during gitPullOrClone use it, or default to md_build\n                    local repo_dir=\"${__mod_info[$id/repo_dir]}\"\n                    [[ -z \"$repo_dir\" ]] && repo_dir=\"$md_build\"\n                    # date cannot understand the default date format of git\n                    pkg_repo_date=\"$(git -C \"$repo_dir\" log -1 --format=%cI)\"\n                    pkg_repo_commit=\"$(git -C \"$repo_dir\" log -1 --format=%H)\"\n                else\n                    pkg_repo_date=\"$(svn info . | grep -oP \"Last Changed Date: \\K.*\")\"\n                    pkg_repo_date=\"$(date -Iseconds -d \"$pkg_repo_date\")\"\n                    pkg_repo_commit=\"$(svn info . | grep -oP \"Last Changed Rev: \\K.*\")\"\n                fi\n                ;;\n            file)\n                pkg_repo_date=\"$(rp_getFileDate \"$pkg_repo_url\")\"\n                ;;\n            :*)\n                # set data based on function hook - function should return code to define any pkg_* vars\n                # eg. local pkg_repo_date=\"something\"\n                local function=\"${pkg_repo_type:1}\"\n                fnExists \"$function\" && eval $(\"$function\" get)\n                ;;\n        esac\n\n        iniSet \"pkg_date\" \"$pkg_date\"\n        iniSet \"pkg_repo_type\" \"$pkg_repo_type\"\n        iniSet \"pkg_repo_url\" \"$pkg_repo_url\"\n        iniSet \"pkg_repo_branch\" \"$pkg_repo_branch\"\n        iniSet \"pkg_repo_commit\" \"$pkg_repo_commit\"\n        iniSet \"pkg_repo_date\" \"$pkg_repo_date\"\n        iniSet \"pkg_repo_extra\" \"$pkg_repo_extra\"\n    fi\n}\n\n# loads installed package information into __mod_info/pkg_* fields\n# additional parameters are optional keys to load, but the data won't be cached if this is provided\nfunction rp_loadPackageInfo() {\n    local id=\"$1\"\n\n    # if we have cached the package information already, return\n    [[ \"${__mod_info[$id/pkg_info]}\" -eq 1 ]] && return\n\n    local keys\n    local cache=1\n    if [[ -z \"$2\" ]]; then\n        keys=(\n            pkg_origin\n            pkg_date\n            pkg_repo_type\n            pkg_repo_url\n            pkg_repo_branch\n            pkg_repo_commit\n            pkg_repo_date\n            pkg_repo_extra\n        )\n    else\n        # get user supplied keys but don't cache\n        shift\n        keys=(\"$@\")\n        cache=0\n    fi\n\n    local load=0\n    local pkg_file=\"$(rp_getInstallPath $id)/retropie.pkg\"\n\n    local builder_pkg_file=\"$__tmpdir/archives/$__binary_path/${__mod_info[$id/type]}/$id.pkg\"\n    # fallback to using package info for built binaries so the binary builder code can update only changed modules\n    if [[ ! -f \"$pkg_file\" && -f \"$builder_pkg_file\" ]]; then\n        pkg_file=\"$builder_pkg_file\"\n    fi\n\n    # if the pkg file is available, we will load the data in the next loop\n    [[ -f \"$pkg_file\" ]] && load=1\n\n    local key\n    local data\n    for key in \"${keys[@]}\"; do\n        # clear any previous data we have stored, but default \"pkg_origin\" to \"unknown\"\n        data=\"\"\n        [[ \"$key\" == \"pkg_origin\" ]] && data=\"unknown\"\n        __mod_info[$id/$key]=\"$data\"\n\n        # if the package file is available and the field is set, override the default values\n        if [[ \"$load\" -eq 1 ]]; then\n            data=\"$(grep -oP \"$key=\\\"\\K[^\\\"]+\" \"$pkg_file\")\"\n            [[ -n \"$data\" ]] && __mod_info[$id/$key]=\"$data\"\n        fi\n    done\n    # if loading all data set pkg_info to 1 so we avoid loading when not needed\n    [[ \"$cache\" -eq 1 ]] && __mod_info[$id/pkg_info]=1\n}\n\nfunction rp_registerModule() {\n    local path=\"$1\"\n    local type=\"$2\"\n    local vendor=\"$3\"\n    # type is the last folder in the path as we now send a full path to rp_registerModule\n    type=\"${type##*/}\"\n    local rp_module_id=\"\"\n    local rp_module_desc=\"\"\n    local rp_module_help=\"\"\n    local rp_module_licence=\"\"\n    local rp_module_section=\"\"\n    local rp_module_flags=\"\"\n    local rp_module_repo=\"\"\n\n    local error=0\n\n    # for 3rd party modules, extract the module id and make sure it is unique\n    # as we don't want 3rd party repos overriding our built-in modules\n    if [[ \"$vendor\" != \"RetroPie\" ]]; then\n        rp_module_id=$(grep -oP \"rp_module_id=\\\"\\K([^\\\"]+)\" \"$path\")\n        if [[ -n \"${__mod_idx[$rp_module_id]}\" ]]; then\n            __INFMSGS+=(\"Module $path was skipped as $rp_module_id is already used by ${__mod_info[$rp_module_id/path]}\")\n            return\n        fi\n    fi\n\n    source \"$path\"\n\n    local var\n    for var in rp_module_id rp_module_desc; do\n        if [[ -z \"${!var}\" ]]; then\n            echo \"Module $path is missing valid $var\"\n            error=1\n        fi\n    done\n    [[ $error -eq 1 ]] && exit 1\n\n    local flags=($rp_module_flags)\n    local flag\n    local enabled=1\n\n    # flags are parsed in the order provided in the module - so the !all flag only makes sense first\n    # by default modules are enabled for all platforms\n    if [[ \"$__ignore_flags\" -ne 1 ]]; then\n        for flag in \"${flags[@]}\"; do\n            # !all excludes the module from all platforms\n            if [[ \"$flag\" == \"!all\" ]]; then\n                enabled=0\n                continue\n            fi\n            # flags without ! make the module valid for the platform\n            if isPlatform \"$flag\"; then\n                enabled=1\n                continue\n            fi\n            # flags with !flag will exclude the module for the platform\n            if [[ \"$flag\" =~ ^\\!(.+) ]] && isPlatform \"${BASH_REMATCH[1]}\"; then\n                enabled=0\n                continue\n            fi\n            # enable or disable based on a comparison in the format :\\$var:cmp:val or !:\\$var:cmp:val\n            # eg. :\\$__gcc_version:-lt:7 would be evaluated as [[ $__gcc_version -lt 7 ]]\n            # this would enable a module if the comparison was true\n            # !:\\$__gcc_version:-lt:7 would disable if the comparison was true\n\n            # match and extract the parameters\n            if [[ \"$flag\" =~ ^(\\!?):([^:]+):([^:]+):(.+)$ ]]; then\n                # enable or disable based on the first parameter (!)\n                local e=1\n                [[ ${BASH_REMATCH[1]} == \"!\" ]] && e=0\n                # evaluate the comparison\n                if eval \"[[ ${BASH_REMATCH[2]} ${BASH_REMATCH[3]} ${BASH_REMATCH[4]} ]]\"; then\n                    enabled=$e\n                fi\n                continue\n            fi\n        done\n    fi\n\n    local sections=($rp_module_section)\n    # get default section\n    rp_module_section=\"${sections[0]}\"\n\n    # loop through any additional flag=section parameters\n    local flag section\n    for section in \"${sections[@]:1}\"; do\n        section=(${section/=/ })\n        flag=\"${section[0]}\"\n        section=\"${section[1]}\"\n        isPlatform \"$flag\" && rp_module_section=\"$section\"\n    done\n\n    # create numerical index for each module id from nunber of added modules\n    __mod_idx[\"$rp_module_id\"]=\"${#__mod_id[@]}\"\n    __mod_id+=(\"$rp_module_id\")\n    __mod_info[\"$rp_module_id/enabled\"]=\"$enabled\"\n    __mod_info[\"$rp_module_id/path\"]=\"$path\"\n    __mod_info[\"$rp_module_id/vendor\"]=\"$vendor\"\n    __mod_info[\"$rp_module_id/type\"]=\"$type\"\n    __mod_info[\"$rp_module_id/desc\"]=\"$rp_module_desc\"\n    __mod_info[\"$rp_module_id/help\"]=\"$rp_module_help\"\n    __mod_info[\"$rp_module_id/licence\"]=\"$rp_module_licence\"\n    __mod_info[\"$rp_module_id/section\"]=\"$rp_module_section\"\n    __mod_info[\"$rp_module_id/flags\"]=\"$rp_module_flags\"\n\n    # split module repo into type, url, branch and commit\n    if [[ -n \"$rp_module_repo\" ]]; then\n        local repo=($rp_module_repo)\n        __mod_info[\"$rp_module_id/repo_type\"]=\"${repo[0]}\"\n        __mod_info[\"$rp_module_id/repo_url\"]=\"${repo[1]}\"\n        __mod_info[\"$rp_module_id/repo_branch\"]=\"${repo[2]}\"\n        __mod_info[\"$rp_module_id/repo_commit\"]=\"${repo[3]}\"\n    fi\n}\n\nfunction rp_registerModuleDir() {\n    local dir=\"$1\"\n    [[ ! -d \"$dir\" ]] && return 1\n    local vendor=\"$2\"\n    [[ -z \"$vendor\" ]] && return 1\n    local module\n    while read module; do\n        rp_registerModule \"$module\" \"$dir\" \"$vendor\"\n    done < <(find \"$dir\" -mindepth 1 -maxdepth 1 -type f -name \"*.sh\" | sort)\n    return 0\n}\n\nfunction rp_registerAllModules() {\n    __mod_id=()\n    declare -Ag __mod_idx=()\n    declare -Ag __mod_info=()\n\n    local dir\n    local type\n    local vendor\n    while read dir; do\n        # get parent folder\n        vendor=\"${dir%/*}\"\n        # if the folder isn't RetroPie-Setup then get the repo name which will be used for module vendor\n        if [[ \"$vendor\" != \"$scriptdir\" ]]; then\n            vendor=\"${vendor##*/}\"\n        else\n            vendor=\"RetroPie\"\n        fi\n\n        for type in emulators libretrocores ports supplementary admin; do\n            rp_registerModuleDir \"$dir/$type\" \"$vendor\"\n        done\n    done < <(find \"$scriptdir\"/scriptmodules \"$scriptdir\"/ext/*/scriptmodules -maxdepth 0 2>/dev/null)\n}\n\nfunction rp_getSectionIds() {\n    local section\n    local id\n    local ids=()\n    for id in \"${__mod_id[@]}\"; do\n        for section in \"$@\"; do\n            [[ \"${__mod_info[$id/section]}\" == \"$section\" ]] && ids+=(\"$id\")\n        done\n    done\n    echo \"${ids[@]}\"\n}\n\nfunction rp_isInstalled() {\n    local id=\"$1\"\n    local md_inst=\"$rootdir/${__mod_info[$id/type]}/$id\"\n    [[ -d \"$md_inst\" ]] && return 0\n    return 1\n}\n\nfunction rp_isEnabled() {\n    local id=\"$1\"\n    [[ \"${__mod_info[$id/enabled]}\" -eq 0 ]] && return 1\n    return 0\n}\n\nfunction rp_updateHooks() {\n    local function\n    local id\n    for function in $(compgen -A function _update_hook_); do\n        id=\"${function/_update_hook_/}\"\n        [[ -n \"$id\" && \"${__mod_info[$id/enabled]}\" -eq 1 ]] && rp_callModule \"$id\" _update_hook\n    done\n}\n"
  },
  {
    "path": "scriptmodules/ports/alephone.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"alephone\"\nrp_module_desc=\"AlephOne - Marathon Engine\"\nrp_module_help=\"To get the games running on the Raspberry Pi/Odroid, make sure to set each game to use the software renderer and disable the enhanced HUD from the Plugins menu. For Marathon 1, disable both HUDs from the Plugins menu, start a game, quit back to the title screen and enable Enhanced HUD and it will work and properly.\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/Aleph-One-Marathon/alephone/master/COPYING\"\nrp_module_repo=\"git https://github.com/Aleph-One-Marathon/alephone.git :_get_branch_alephone\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction _get_version_alephone() {\n    local version=\"20250829\"\n    # newer versions need libboost 1.69.0+\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        version=\"20250302\"\n    fi\n    echo \"$version\"\n}\n\nfunction _get_branch_alephone() {\n    echo \"release-$(_get_version_alephone)\"\n}\n\nfunction depends_alephone() {\n    local depends=(libboost-all-dev libspeexdsp-dev libzzip-dev libavcodec-dev libavformat-dev libavutil-dev libswscale-dev autoconf automake libboost-system-dev libcurl4-openssl-dev autoconf-archive libopenal-dev libsndfile1-dev libsdl2-dev libsdl2-net-dev libsdl2-image-dev libsdl2-ttf-dev libglu1-mesa-dev libgl1-mesa-dev libasio-dev) \n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_alephone() {\n    gitPullOrClone\n}\n\nfunction build_alephone() {\n    params=(--prefix=\"$md_inst\")\n    isPlatform \"arm\" && params+=(--with-boost-libdir=/usr/lib/arm-linux-gnueabihf)\n\n    autoreconf -iv\n\n    ./configure \"${params[@]}\"\n    make clean\n    make\n    md_ret_require=\"$md_build/Source_Files/alephone\"\n}\n\nfunction install_alephone() {\n    make install\n}\n\nfunction game_data_alephone() {\n    local version=\"$(_get_version_alephone)\"\n    local release_url=\"https://github.com/Aleph-One-Marathon/alephone/releases/download/release-$version\"\n\n    if [[ ! -f \"$romdir/ports/$md_id/Marathon/Shapes.shps\" ]]; then\n        downloadAndExtract \"$release_url/Marathon-$version-Data.zip\" \"$romdir/ports/$md_id\"\n    fi\n\n    if [[ ! -f \"$romdir/ports/$md_id/Marathon 2/Shapes.shpA\" ]]; then\n        downloadAndExtract \"$release_url/Marathon2-$version-Data.zip\" \"$romdir/ports/$md_id\"\n    fi\n\n    if [[ ! -f \"$romdir/ports/$md_id/Marathon Infinity/Shapes.shpA\" ]]; then\n        downloadAndExtract \"$release_url/MarathonInfinity-$version-Data.zip\" \"$romdir/ports/$md_id\"\n    fi\n\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/$md_id\"\n}\n\nfunction configure_alephone() {\n    addPort \"$md_id\" \"alephone\" \"Aleph One Engine - Marathon\" \"$md_inst/bin/alephone %ROM%\" \"$romdir/ports/$md_id/Marathon/\"\n    addPort \"$md_id\" \"alephone\" \"Aleph One Engine - Marathon 2\" \"$md_inst/bin/alephone %ROM%\" \"$romdir/ports/$md_id/Marathon 2/\"\n    addPort \"$md_id\" \"alephone\" \"Aleph One Engine - Marathon Infinity\" \"$md_inst/bin/alephone %ROM%\" \"$romdir/ports/$md_id/Marathon Infinity/\"\n\n    mkRomDir \"ports/$md_id\"\n\n    moveConfigDir \"$home/.alephone\" \"$md_conf_root/alephone\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_alephone\n}\n"
  },
  {
    "path": "scriptmodules/ports/cannonball.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"cannonball\"\nrp_module_desc=\"Cannonball - An Enhanced OutRun Engine\"\nrp_module_help=\"You need to unzip your OutRun set B from latest MAME (outrun.zip) to $romdir/ports/cannonball. They should match the file names listed in the roms.txt file found in the roms folder. You will also need to rename the epr-10381a.132 file to epr-10381b.132 before it will work.\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/djyt/cannonball/master/docs/license.txt\"\nrp_module_repo=\"git https://github.com/djyt/cannonball.git master 2b3839dd34c1b4263ec5006fdeeb1ae2689cd401\"\nrp_module_section=\"opt\"\n\nfunction depends_cannonball() {\n    local depends=(cmake libsdl2-dev libboost-dev)\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_cannonball() {\n    gitPullOrClone\n    sed -i \"s/-march=armv6 -mfpu=vfp -mfloat-abi=hard//\" \"$md_build/cmake/sdl2_rpi.cmake\" \"$md_build/cmake/sdl2gles_rpi.cmake\"\n}\n\nfunction build_cannonball() {\n    local target\n    mkdir build\n    cd build\n    if isPlatform \"videocore\"; then\n        target=\"sdl2gles_rpi\"\n    elif isPlatform \"gles\"; then\n        target=\"sdl2gles\"\n    else\n        target=\"sdl2gl\"\n    fi\n    cmake -G \"Unix Makefiles\" -DTARGET=$target ../cmake/\n    make clean\n    make\n    md_ret_require=\"$md_build/build/cannonball\"\n}\n\nfunction install_cannonball() {\n    md_ret_files=(\n        'build/cannonball'\n        'roms/roms.txt'\n    )\n\n    mkdir -p \"$md_inst/res\"\n    cp -v res/*.bin \"$md_inst/res/\"\n    cp -v res/config_sdl2.xml \"$md_inst/config.xml.def\"\n}\n\nfunction configure_cannonball() {\n    addPort \"$md_id\" \"cannonball\" \"Cannonball - OutRun Engine\" \"pushd $md_inst; $md_inst/cannonball; popd\"\n\n    mkRomDir \"ports/$md_id\"\n\n    moveConfigFile \"config.xml\" \"$md_conf_root/$md_id/config.xml\"\n    moveConfigFile \"hiscores.xml\" \"$md_conf_root/$md_id/hiscores.xml\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    copyDefaultConfig \"$md_inst/config.xml.def\" \"$md_conf_root/$md_id/config.xml\"\n\n    cp -v roms.txt \"$romdir/ports/$md_id/\"\n\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/$md_id\" \"$md_conf_root/$md_id\"\n\n    ln -snf \"$romdir/ports/$md_id\" \"$md_inst/roms\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/cdogs-sdl.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"cdogs-sdl\"\nrp_module_desc=\"C-Dogs SDL - Classic overhead run-and-gun game\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/cxong/cdogs-sdl/master/COPYING\"\nrp_module_repo=\"git https://github.com/cxong/cdogs-sdl.git 1.4.1\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_cdogs-sdl() {\n    getDepends cmake libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev\n}\n\nfunction sources_cdogs-sdl() {\n    gitPullOrClone\n}\n\nfunction build_cdogs-sdl() {\n    cmake . -DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DCDOGS_DATA_DIR=\"$md_inst/\"\n    make\n    md_ret_require=\"$md_build/src/cdogs-sdl\"\n}\n\nfunction install_cdogs-sdl() {\n    md_ret_files=(\n        'data'\n        'dogfights'\n        'graphics'\n        'missions'\n        'music'\n        'sounds'\n        'COPYING'\n        'src/cdogs-sdl'\n        'src/cdogs-sdl-editor'\n    )\n}\n\nfunction configure_cdogs-sdl() {\n    addPort \"$md_id\" \"cdogs-sdl\" \"C-Dogs SDL\" \"pushd $md_inst; $md_inst/cdogs-sdl; popd\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    moveConfigDir \"$home/.config/cdogs-sdl\" \"$md_conf_root/cdogs-sdl\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/cgenius.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"cgenius\"\nrp_module_desc=\"Commander Genius - Modern Interpreter for the Commander Keen Games (Vorticon and Galaxy Games)\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/gerstrong/Commander-Genius/master/COPYRIGHT\"\nrp_module_repo=\"git https://gitlab.com/Dringgstein/Commander-Genius.git v3.6.1\"\nrp_module_section=\"opt\"\n\nfunction depends_cgenius() {\n    getDepends cmake libcurl4-openssl-dev libvorbis-dev libogg-dev libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev zlib1g-dev\n}\n\nfunction sources_cgenius() {\n    gitPullOrClone\n}\n\nfunction build_cgenius() {\n    # gcc8 mistakenly warns on certain conversion alignments, don't promote the warnings to errors\n    sed -i 's/-Werror=cast-align//' src/CMakeLists.txt\n    rm -fr build\n    mkdir -p build && cd build\n    cmake -DBUILD_COSMOS=1 -DNOTYPESAVE=on ..\n    make\n    md_ret_require=\"$md_build/build/src/CGeniusExe\"\n}\n\nfunction install_cgenius() {\n    md_ret_files=(\n        'vfsroot'\n        'build/src/CGeniusExe'\n    )\n}\n\nfunction configure_cgenius() {\n    addPort \"$md_id\" \"cgenius\" \"Commander Genius\" \"pushd $md_inst; ./CGeniusExe; popd\"\n\n    mkRomDir \"ports/$md_id\"\n\n    moveConfigDir \"$home/.CommanderGenius\"  \"$md_conf_root/$md_id\"\n\n    [[ $md_mode == \"remove\" ]] && return\n\n    # Create a minimal config file so the Commander can find the games\n    local config=\"$(mktemp)\"\n    cat > \"$config\" << _INI_\n[FileHandling]\nEnableLogfile = false\nSearchPath1 = \\${HOME}/.CommanderGenius\nSearchPath2 = .\nSearchPath3 = $romdir/ports/$md_id\n_INI_\n    copyDefaultConfig \"$config\" \"$md_conf_root/$md_id/cgenius.cfg\"\n\n}\n"
  },
  {
    "path": "scriptmodules/ports/darkplaces-quake/01_rpi_fixes.diff",
    "content": "--- a/gl_textures.c\n+++ b/gl_textures.c\n@@ -14,6 +14,10 @@ extern LPDIRECT3DDEVICE9 vid_d3d9dev;\n #define GL_TEXTURE_3D\t\t\t\t0x806F\n #endif\n \n+#define GL_RGBA32F\t\t\t\t0x8814\n+#define GL_RGBA16F\t\t\t\t0x881A\n+#define GL_HALF_FLOAT_ARB\t\t\t0x140B\n+\n cvar_t gl_max_size = {CVAR_SAVE, \"gl_max_size\", \"2048\", \"maximum allowed texture size, can be used to reduce video memory usage, limited by hardware capabilities (typically 2048, 4096, or 8192)\"};\n cvar_t gl_max_lightmapsize = {CVAR_SAVE, \"gl_max_lightmapsize\", \"1024\", \"maximum allowed texture size for lightmap textures, use larger values to improve rendering speed, as long as there is enough video memory available (setting it too high for the hardware will cause very bad performance)\"};\n cvar_t gl_picmip = {CVAR_SAVE, \"gl_picmip\", \"0\", \"reduces resolution of textures by powers of 2, for example 1 will halve width/height, reducing texture memory usage by 75%\"};\n@@ -36,7 +40,7 @@ cvar_t gl_texturecompression_sky = {CVAR_SAVE, \"gl_texturecompression_sky\", \"0\",\n cvar_t gl_texturecompression_lightcubemaps = {CVAR_SAVE, \"gl_texturecompression_lightcubemaps\", \"1\", \"whether to compress light cubemaps (spotlights and other light projection images)\"};\n cvar_t gl_texturecompression_reflectmask = {CVAR_SAVE, \"gl_texturecompression_reflectmask\", \"1\", \"whether to compress reflection cubemap masks (mask of which areas of the texture should reflect the generic shiny cubemap)\"};\n cvar_t gl_texturecompression_sprites = {CVAR_SAVE, \"gl_texturecompression_sprites\", \"1\", \"whether to compress sprites\"};\n-cvar_t gl_nopartialtextureupdates = {CVAR_SAVE, \"gl_nopartialtextureupdates\", \"0\", \"use alternate path for dynamic lightmap updates that avoids a possibly slow code path in the driver\"};\n+cvar_t gl_nopartialtextureupdates = {CVAR_SAVE, \"gl_nopartialtextureuopdates\", \"1\", \"use alternate path for dynamic lightmap updates that avoids a possibly slow code path in the driver\"};\n cvar_t r_texture_dds_load_alphamode = {0, \"r_texture_dds_load_alphamode\", \"1\", \"0: trust DDPF_ALPHAPIXELS flag, 1: texture format and brute force search if ambiguous, 2: texture format only\"};\n cvar_t r_texture_dds_load_logfailure = {0, \"r_texture_dds_load_logfailure\", \"0\", \"log missing DDS textures to ddstexturefailures.log, 0: done log, 1: log with no optional textures (_norm, glow etc.). 2: log all\"};\n cvar_t r_texture_dds_swdecode = {0, \"r_texture_dds_swdecode\", \"0\", \"0: don't software decode DDS, 1: software decode DDS if unsupported, 2: always software decode DDS\"};\n"
  },
  {
    "path": "scriptmodules/ports/darkplaces-quake/02_makefile_fixes.diff",
    "content": "--- a/makefile.inc\n+++ b/makefile.inc\n@@ -436,8 +436,8 @@ bin-debug :\n \t$(MAKE) prepare BUILD_DIR=build-obj/debug/$(EXE)\n \t$(MAKE) -C build-obj/debug/$(EXE) $(EXE) \\\n \t\tDP_MAKE_TARGET=$(DP_MAKE_TARGET) DP_SOUND_API=$(DP_SOUND_API) \\\n-\t\tCFLAGS='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_DEBUG) $(OPTIM_DEBUG)'\\\n-\t\tLDFLAGS='$(LDFLAGS_DEBUG) $(LDFLAGS_COMMON)' LEVEL=2\n+\t\tCFLAGS+='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_DEBUG) $(OPTIM_DEBUG)'\\\n+\t\tLDFLAGS+='$(LDFLAGS_DEBUG) $(LDFLAGS_COMMON)' LEVEL=2\n \n bin-profile :\n \t$(CHECKLEVEL1)\n@@ -446,8 +446,8 @@ bin-profile :\n \t$(MAKE) prepare BUILD_DIR=build-obj/profile/$(EXE)\n \t$(MAKE) -C build-obj/profile/$(EXE) $(EXE) \\\n \t\tDP_MAKE_TARGET=$(DP_MAKE_TARGET) DP_SOUND_API=$(DP_SOUND_API) \\\n-\t\tCFLAGS='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_PROFILE) $(OPTIM_RELEASE)'\\\n-\t\tLDFLAGS='$(LDFLAGS_PROFILE) $(LDFLAGS_COMMON)' LEVEL=2\n+\t\tCFLAGS+='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_PROFILE) $(OPTIM_RELEASE)'\\\n+\t\tLDFLAGS+='$(LDFLAGS_PROFILE) $(LDFLAGS_COMMON)' LEVEL=2\n \n bin-release :\n \t$(CHECKLEVEL1)\n@@ -456,8 +456,8 @@ bin-release :\n \t$(MAKE) prepare BUILD_DIR=build-obj/release/$(EXE)\n \t$(MAKE) -C build-obj/release/$(EXE) $(EXE) \\\n \t\tDP_MAKE_TARGET=$(DP_MAKE_TARGET) DP_SOUND_API=$(DP_SOUND_API) \\\n-\t\tCFLAGS='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_RELEASE) $(OPTIM_RELEASE)'\\\n-\t\tLDFLAGS='$(LDFLAGS_RELEASE) $(LDFLAGS_COMMON)' LEVEL=2\n+\t\tCFLAGS+='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_RELEASE) $(OPTIM_RELEASE)'\\\n+\t\tLDFLAGS+='$(LDFLAGS_RELEASE) $(LDFLAGS_COMMON)' LEVEL=2\n \t$(STRIP) $(EXE)\n \n bin-release-profile :\n@@ -467,8 +467,8 @@ bin-release-profile :\n \t$(MAKE) prepare BUILD_DIR=build-obj/release-profile/$(EXE)\n \t$(MAKE) -C build-obj/release-profile/$(EXE) $(EXE) \\\n \t\tDP_MAKE_TARGET=$(DP_MAKE_TARGET) DP_SOUND_API=$(DP_SOUND_API) \\\n-\t\tCFLAGS='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_RELEASE_PROFILE) $(OPTIM_RELEASE)'\\\n-\t\tLDFLAGS='$(LDFLAGS_RELEASE) $(LDFLAGS_COMMON)' LEVEL=2\n+\t\tCFLAGS+='$(CFLAGS_COMMON) $(CFLAGS_FEATURES) $(CFLAGS_EXTRA) $(CFLAGS_RELEASE_PROFILE) $(OPTIM_RELEASE)'\\\n+\t\tLDFLAGS+='$(LDFLAGS_RELEASE) $(LDFLAGS_COMMON)' LEVEL=2\n \t$(STRIP) $(EXE)\n \n prepare :\n"
  },
  {
    "path": "scriptmodules/ports/darkplaces-quake.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"darkplaces-quake\"\nrp_module_desc=\"Quake 1 engine - Darkplaces Quake port with GLES rendering\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/xonotic/darkplaces/master/COPYING\"\nrp_module_repo=\"git https://github.com/xonotic/darkplaces.git div0-stable\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction depends_darkplaces-quake() {\n    local depends=(libsdl2-dev libjpeg-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"mesa\" && depends+=(libgles2-mesa-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_darkplaces-quake() {\n    gitPullOrClone\n    isPlatform \"rpi\" && applyPatch \"$md_data/01_rpi_fixes.diff\"\n    applyPatch \"$md_data/02_makefile_fixes.diff\"\n    # comment out problematic invariant qualifier which fails to compile with mesa gles on rpi4\n    isPlatform \"rpi4\" && sed -i 's#^\"invariant#\"//invariant#' \"$md_build/shader_glsl.h\"\n}\n\nfunction build_darkplaces-quake() {\n    local force_opengl=\"$1\"\n    # on the rpi4, we build gles first, and then force an opengl build (which is the default)\n    [[ -z \"$force_opengl\" ]] && force_opengl=0\n    local params=(OPTIM_RELEASE=\"\")\n    if isPlatform \"gles\" && [[ \"$force_opengl\" -eq 0 ]]; then\n        params+=(SDLCONFIG_UNIXCFLAGS_X11=\"-DUSE_GLES2\")\n        if isPlatform \"videocore\"; then\n            params+=(SDLCONFIG_UNIXLIBS_X11=\"-L /opt/vc/lib -lbrcmGLESv2\")\n        else\n            params+=(SDLCONFIG_UNIXLIBS_X11=\"-lGLESv2\")\n        fi\n    fi\n    make clean\n    make sdl-release \"${params[@]}\"\n    if isPlatform \"rpi4\" && [[ \"$force_opengl\" -eq 0 ]]; then\n        mv \"$md_build/darkplaces-sdl\" \"$md_build/darkplaces-sdl-gles\"\n        # revert rpi4 gles change which commented out invariant line from earlier.\n        sed -i 's#^\"//invariant#\"invariant#' \"$md_build/shader_glsl.h\"\n        # rebuild opengl version on rpi4\n        build_darkplaces-quake 1\n        md_ret_require+=(\"$md_build/darkplaces-sdl-gles\")\n    else\n        md_ret_require+=(\"$md_build/darkplaces-sdl\")\n    fi\n}\n\nfunction install_darkplaces-quake() {\n    md_ret_files=(\n        'darkplaces.txt'\n        'darkplaces-sdl'\n        'COPYING'\n    )\n    isPlatform \"rpi4\" && md_ret_files+=(\"darkplaces-sdl-gles\")\n}\n\nfunction add_games_darkplaces-quake() {\n    local params=(-basedir \"$romdir/ports/quake\" -game %QUAKEDIR%)\n    isPlatform \"kms\" && params+=(\"+vid_vsync 1\")\n    if isPlatform \"rpi4\"; then\n       addEmulator 0 \"$md_id-gles\" \"quake\" \"$md_inst/darkplaces-sdl-gles ${params[*]}\"\n    fi\n    _add_games_lr-tyrquake \"$md_inst/darkplaces-sdl ${params[*]}\"\n}\n\nfunction configure_darkplaces-quake() {\n    mkRomDir \"ports/quake\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_lr-tyrquake\n\n    add_games_darkplaces-quake\n\n    moveConfigDir \"$home/.darkplaces\" \"$md_conf_root/quake/darkplaces\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/dsda-doom.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dsda-doom\"\nrp_module_desc=\"DOOM source port based on PrBoom+, focused on speedrunning and QoL\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/kraflab/dsda-doom/master/prboom2/COPYING\"\nrp_module_repo=\"git https://github.com/kraflab/dsda-doom :_get_branch_dsda-doom\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction _get_branch_dsda-doom() {\n    local branch=\"v0.29.4\"\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        branch=\"v0.29.3\"\n    fi\n    echo \"$branch\"\n}\n\nfunction _check_fluidsynth_dsda-doom() {\n    dpkg-query -W -f '${Version}' libfluidsynth1 2>/dev/null\n}\n\nfunction depends_dsda-doom() {\n    local depends=(cmake libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libogg-dev libmad0-dev libvorbis-dev libzip-dev zlib1g-dev zipcmp zipmerge ziptool)\n    # we need Fluidsynth 2+, check whether the platform has the older libfluidsynth1\n    [[ -z \"$(_check_fluidsynth_dsda-doom)\" ]] && depends+=(libfluidsynth-dev fluidsynth libsndfile1-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_dsda-doom() {\n    gitPullOrClone\n}\n\nfunction build_dsda-doom() {\n    rm -rf release && mkdir -p release\n    cd release\n    local params=(-DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DCMAKE_BUILD_TYPE=Release -DWITH_PORTMIDI=OFF)\n    # disable fluidsynth when the v1 is found\n    [[ -n \"$(_check_fluidsynth_dsda-doom)\" ]] && params+=(-DWITH_FLUIDSYNTH=OFF)\n    cmake \"${params[@]}\" ../prboom2\n    make\n    md_ret_require=\"$md_build/release/dsda-doom\"\n}\n\nfunction install_dsda-doom() {\n    md_ret_files=(\n        'release/dsda-doom'\n        'release/dsda-doom.wad'\n        'README.md'\n        'docs'\n        'prboom2/COPYING'\n        'prboom2/AUTHORS'\n    )\n}\n\nfunction add_games_dsda-doom() {\n    local params=(\"-fullscreen\" \"-width %XRES%\" \"-height %YRES%\")\n    local launcher_prefix=\"DOOMWADDIR=$romdir/ports/doom\"\n    _add_games_lr-prboom \"$launcher_prefix $md_inst/$md_id -iwad %ROM% ${params[*]}\"\n}\n\nfunction configure_dsda-doom() {\n    mkRomDir \"ports/doom\"\n\n    moveConfigDir \"$home/.dsda-doom\" \"$md_conf_root/doom\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    game_data_lr-prboom\n    add_games_${md_id}\n}\n\n"
  },
  {
    "path": "scriptmodules/ports/dxx-rebirth.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dxx-rebirth\"\nrp_module_desc=\"DXX-Rebirth (Descent & Descent 2) source port\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/dxx-rebirth/dxx-rebirth/master/COPYING.txt\"\nrp_module_repo=\"git https://github.com/dxx-rebirth/dxx-rebirth master :_get_commit_dxx-rebirth\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction _get_commit_dxx-rebirth() {\n    local commit=\"\"\n    # last version to build on gcc 10\n    [[ \"$__gcc_version\" -le 10 ]] && commit=\"ec41384d\"\n    # last version to build on Debian Buster due to pkg-config issue with physfs\n    # newer versions also have incompatible scons changes\n    [[ \"$__os_debian_ver\" -le 10 ]] && commit=\"15bd145d\"\n    # latest code requires gcc 7+\n    [[ \"$__gcc_version\" -lt 7 ]] && commit=\"a1b3a86c\"\n    echo \"$commit\"\n}\n\nfunction depends_dxx-rebirth() {\n    local depends=(libpng-dev libphysfs-dev scons)\n    if isPlatform \"videocore\"; then\n        depends+=(libraspberrypi-dev libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev)\n    else\n        depends+=(libgl1-mesa-dev libglu1-mesa-dev libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_dxx-rebirth() {\n    gitPullOrClone\n}\n\nfunction _get_build_path_dxx-rebirth() {\n    # later versions use a build subfolder\n    [[ -d \"$md_build/build\" ]] && echo \"build\"\n}\n\nfunction build_dxx-rebirth() {\n    local params=()\n    isPlatform \"arm\" && params+=(\"words_need_alignment=1\")\n    if isPlatform \"videocore\"; then\n        params+=(\"raspberrypi=1\")\n    elif isPlatform \"mesa\"; then\n        # GLES is limited to ES 1 and blocks SDL2; GL works at fullspeed on Pi 3.\n        params+=(\"raspberrypi=mesa\" \"opengl=1\" \"opengles=0\" \"sdl2=1\")\n    else\n        params+=(\"opengl=1\" \"opengles=0\" \"sdl2=1\")\n    fi\n\n    scons -c\n    scons \"${params[@]}\" -j$__jobs\n\n    local build_path=\"$md_build/$(_get_build_path_dxx-rebirth)\"\n    md_ret_require=(\n        \"$build_path/d1x-rebirth/d1x-rebirth\"\n        \"$build_path/d2x-rebirth/d2x-rebirth\"\n    )\n}\n\nfunction install_dxx-rebirth() {\n    # Rename generic files\n    mv -f \"$md_build/d1x-rebirth/INSTALL.txt\" \"$md_build/d1x-rebirth/D1X-INSTALL.txt\"\n    mv -f \"$md_build/d1x-rebirth/RELEASE-NOTES.txt\" \"$md_build/d1x-rebirth/D1X-RELEASE-NOTES.txt\"\n    mv -f \"$md_build/d2x-rebirth/INSTALL.txt\" \"$md_build/d2x-rebirth/D2X-INSTALL.txt\"\n    mv -f \"$md_build/d2x-rebirth/RELEASE-NOTES.txt\" \"$md_build/d2x-rebirth/D2X-RELEASE-NOTES.txt\"\n\n    local build_path=\"$(_get_build_path_dxx-rebirth)\"\n\n    md_ret_files=(\n        'COPYING.txt'\n        'GPL-3.txt'\n        'd1x-rebirth/README.RPi'\n        \"$build_path/d1x-rebirth/d1x-rebirth\"\n        'd1x-rebirth/d1x.ini'\n        'd1x-rebirth/D1X-INSTALL.txt'\n        'd1x-rebirth/D1X-RELEASE-NOTES.txt'\n        \"$build_path/d2x-rebirth/d2x-rebirth\"\n        'd2x-rebirth/d2x.ini'\n        'd2x-rebirth/D2X-INSTALL.txt'\n        'd2x-rebirth/D2X-RELEASE-NOTES.txt'\n    )\n}\n\nfunction game_data_dxx-rebirth() {\n    local base_url=\"$__archive_url/descent\"\n    local D1X_SHARE_URL=\"$base_url/descent-pc-shareware.zip\"\n    local D2X_SHARE_URL=\"$base_url/descent2-pc-demo.zip\"\n    local D1X_HIGH_TEXTURE_URL=\"$base_url/d1xr-hires.dxa\"\n    local D1X_OGG_URL=\"$base_url/d1xr-sc55-music.dxa\"\n    local D2X_OGG_URL=\"$base_url/d2xr-sc55-music.dxa\"\n\n    local dest_d1=\"$romdir/ports/descent1\"\n    local dest_d2=\"$romdir/ports/descent2\"\n\n    mkUserDir \"$dest_d1\"\n    mkUserDir \"$dest_d2\"\n\n    # Download / unpack / install Descent shareware files\n    if [[ -z \"$(find \"$dest_d1\" -maxdepth 1 -iname descent.hog)\" ]]; then\n        downloadAndExtract \"$D1X_SHARE_URL\" \"$dest_d1\"\n    fi\n\n    # High Res Texture Pack\n    if [[ ! -f \"$dest_d1/d1xr-hires.dxa\" ]]; then\n        download \"$D1X_HIGH_TEXTURE_URL\" \"$dest_d1\"\n    fi\n\n    # Ogg Sound Replacement (Roland Sound Canvas SC-55 MIDI)\n    if [[ ! -f \"$dest_d1/d1xr-sc55-music.dxa\" ]]; then\n        download \"$D1X_OGG_URL\" \"$dest_d1\"\n    fi\n\n    # Download / unpack / install Descent 2 shareware files\n    if [[ -z \"$(find \"$dest_d2\" -maxdepth 1 \\( -iname D2DEMO.HOG -o -iname DESCENT2.HOG \\))\" ]]; then\n        downloadAndExtract \"$D2X_SHARE_URL\" \"$dest_d2\"\n    fi\n\n    # Ogg Sound Replacement (Roland Sound Canvas SC-55 MIDI)\n    if [[ ! -f \"$dest_d2/d2xr-sc55-music.dxa\" ]]; then\n        download \"$D2X_OGG_URL\" \"$dest_d2\"\n    fi\n\n    chown -R \"$__user\":\"$__group\" \"$dest_d1\" \"$dest_d2\"\n}\n\nfunction configure_dxx-rebirth() {\n    local config\n    local ver\n    local name=\"Descent Rebirth\"\n    for ver in 1 2; do\n        [[ \"$ver\" -eq 2 ]] && name=\"Descent 2 Rebirth\"\n        addPort \"$md_id\" \"descent${ver}\" \"$name\" \"$md_inst/d${ver}x-rebirth -hogdir $romdir/ports/descent${ver}\"\n\n        # skip folder / config work on removal\n        [[ \"$md_mode\" == \"remove\" ]] && continue\n\n        mkRomDir \"ports/descent${ver}\"\n        # copy any existing configs from ~/.d1x-rebirth and symlink the config folder to $md_conf_root/descent1/\n        moveConfigDir \"$home/.d${ver}x-rebirth\" \"$md_conf_root/descent${ver}/\"\n        if isPlatform \"kms\"; then\n            config=\"$md_conf_root/descent${ver}/descent.cfg\"\n            iniConfig \"=\" '' \"$config\"\n            iniSet \"VSync\" \"1\"\n            chown \"$__user\":\"$__group\" \"$config\"\n        fi\n    done\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_dxx-rebirth\n}\n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0001-revert-r6918.patch",
    "content": "Index: source/build/src/tilepacker.cpp\n===================================================================\n--- a/source/build/src/tilepacker.cpp\t(revision 8090)\n+++ b/source/build/src/tilepacker.cpp\t(working copy)\n@@ -33,7 +33,6 @@\n uint32_t rejectQueueHeadIndex = 0;\n uint32_t numRejected = 0;\n \n-#if 0\n static void maxheap_bubbleUp(uint32_t nodeIndex)\n {\n     while (true)\n@@ -57,7 +56,6 @@\n         nodeIndex = parentIndex;\n     }\n }\n-#endif\n \n static void maxheap_bubbleDown(uint32_t nodeIndex)\n {\n@@ -90,14 +88,6 @@\n     }\n }\n \n-static void maxheap_buildHeap()\n-{\n-    for (int i = (heapNodes-2)/2; i >= 0; --i)\n-    {\n-        maxheap_bubbleDown(i);\n-    }\n-}\n-\n static TreeNode* maxheap_pop()\n {\n     if (heapNodes == 0)\n@@ -307,6 +297,7 @@\n                         (TreeNode*) 0,\n                         {0, 0, tileWidth, tileHeight},\n                         tileUID);\n+    maxheap_bubbleUp(heapNodes-1);\n }\n \n char tilepacker_pack(uint32_t tilesheetID)\n@@ -325,8 +316,6 @@\n             rejectQueue_add(pNode);\n         }\n     }\n-\n-    maxheap_buildHeap();\n     for (TreeNode *pNode = maxheap_pop(); pNode != NULL; pNode = maxheap_pop())\n     {\n         char success = kdtree_add(tilesheetID, pNode);\n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0002-fix-skybox.patch",
    "content": "Index: source/build/src/polymost.cpp\n===================================================================\n--- a/source/build/src/polymost.cpp\t(revision 8090)\n+++ b/source/build/src/polymost.cpp\t(working copy)\n@@ -360,7 +360,7 @@\n     }\n \n     gltexfiltermode = clamp(gltexfiltermode, 0, NUMGLFILTERMODES-1);\n-    r_useindexedcolortextures = !gltexfiltermode;\n+    //r_useindexedcolortextures = !gltexfiltermode;\n \n     for (bssize_t i=0; i<=GLTEXCACHEADSIZ-1; i++)\n     {\n@@ -5437,7 +5437,7 @@\n         else if ((nextsectnum < 0) || (!(sector[nextsectnum].floorstat&1)))\n         {\n             //Parallaxing sky... hacked for Ken's mountain texture\n-            if ((usehightile && hicfindsubst(globalpicnum, globalpal, hictinting[globalpal].f & HICTINT_ALWAYSUSEART)))\n+            if (!r_useindexedcolortextures || (usehightile && hicfindsubst(globalpicnum, globalpal, hictinting[globalpal].f & HICTINT_ALWAYSUSEART)))\n                 calc_and_apply_fog_factor(sec->floorshade, sec->visibility, sec->floorpal, 0.005f);\n \n             globvis2 = globalpisibility;\n@@ -5831,7 +5831,7 @@\n         else if ((nextsectnum < 0) || (!(sector[nextsectnum].ceilingstat&1)))\n         {\n             //Parallaxing sky... hacked for Ken's mountain texture\n-            if ((usehightile && hicfindsubst(globalpicnum, globalpal, hictinting[globalpal].f & HICTINT_ALWAYSUSEART)))\n+            if (!r_useindexedcolortextures || (usehightile && hicfindsubst(globalpicnum, globalpal, hictinting[globalpal].f & HICTINT_ALWAYSUSEART)))\n                 calc_and_apply_fog_factor(sec->ceilingshade, sec->visibility, sec->ceilingpal, 0.005f);\n \n             globvis2 = globalpisibility;\n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0003-replace-gl_red.patch",
    "content": "Index: source/build/src/glsurface.cpp\n===================================================================\n--- a/source/build/src/glsurface.cpp\t(revision 8090)\n+++ b/source/build/src/glsurface.cpp\t(working copy)\n@@ -94,7 +94,7 @@\n     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);\n     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, bufferRes.x, bufferRes.y, 0, GL_RED, GL_UNSIGNED_BYTE, 0);\n+    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, bufferRes.x, bufferRes.y, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, 0);\n \n     glsurface_setPalette(curpalettefaded);\n \n@@ -227,7 +227,7 @@\n         return;\n \n     glActiveTexture(GL_TEXTURE0);\n-    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bufferRes.x, bufferRes.y, GL_RED, GL_UNSIGNED_BYTE, (void*) buffer);\n+    glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, bufferRes.x, bufferRes.y, GL_LUMINANCE, GL_UNSIGNED_BYTE, (void*) buffer);\n \n     glDrawArrays(GL_TRIANGLE_STRIP,\n                  0,\nIndex: source/build/src/polymost.cpp\n===================================================================\n--- a/source/build/src/polymost.cpp\t(revision 8090)\n+++ b/source/build/src/polymost.cpp\t(working copy)\n@@ -1874,11 +1874,11 @@\n         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);\n         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);\n \n-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, siz.y, siz.x, 0, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);\n+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, siz.y, siz.x, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (void*) tile);\n     }\n     else\n     {\n-        glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, siz.y, siz.x, GL_RED, GL_UNSIGNED_BYTE, (void*) tile);\n+        glTexSubImage2D(GL_TEXTURE_2D, 0, offset.x, offset.y, siz.y, siz.x, GL_LUMINANCE, GL_UNSIGNED_BYTE, (void*) tile);\n     }\n }\n \n@@ -1954,7 +1954,7 @@\n         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);\n         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);\n         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);\n-        glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL_RED, GL_UNSIGNED_BYTE, NULL);\n+        glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, PALSWAP_TEXTURE_SIZE, PALSWAP_TEXTURE_SIZE, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);\n     }\n \n     int32_t column = palookupnum%(PALSWAP_TEXTURE_SIZE/256);\n@@ -1965,7 +1965,7 @@\n         OSD_Printf(\"Polymost: palswaps are too large for palswap tilesheet!\\n\");\n         return;\n     }\n-    glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades+1, GL_RED, GL_UNSIGNED_BYTE, palookup[palookupnum]);\n+    glTexSubImage2D(GL_TEXTURE_2D, 0, 256*column, rowOffset, 256, numshades+1, GL_LUMINANCE, GL_UNSIGNED_BYTE, palookup[palookupnum]);\n }\n \n \nIndex: source/build/src/voxmodel.cpp\n===================================================================\n--- a/source/build/src/voxmodel.cpp\t(revision 8090)\n+++ b/source/build/src/voxmodel.cpp\t(working copy)\n@@ -60,7 +60,7 @@\n     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);\n     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);\n \n-    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, ysiz, xsiz, 0, GL_RED, GL_UNSIGNED_BYTE, (char *) pic2);\n+    glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, ysiz, xsiz, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, (char *) pic2);\n \n     Xfree(pic2);\n \n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0004-recast-function.patch",
    "content": "Index: source/duke3d/src/astub.cpp\n===================================================================\n--- a/source/duke3d/src/astub.cpp\t(revision 8090)\n+++ b/source/duke3d/src/astub.cpp\t(working copy)\n@@ -4291,7 +4291,7 @@\n     i = (i&0x4)+((i>>4)&3);\n     i = eitherSHIFT ? prev3[i] : next3[i];\n     message(\"Sector %d %s flip %d deg%s\", sectnum, typestr[search],\n-            klabs(orient[i])%360, orient[i] < 0 ? \" mirrored\":\"\");\n+            (int)klabs(orient[i])%360, orient[i] < 0 ? \" mirrored\":\"\");\n     i = (i&0x4)+((i&3)<<4);\n     *stat &= ~0x34;\n     *stat |= i;\nIndex: source/duke3d/src/player.cpp\n===================================================================\n--- a/source/duke3d/src/player.cpp\t(revision 8090)\n+++ b/source/duke3d/src/player.cpp\t(working copy)\n@@ -1666,7 +1666,7 @@\n \n     for (bssize_t i=0; i < pPlayer->numloogs; i++)\n     {\n-        int const rotAng = klabs(sintable[((loogCounter + i) << 5) & 2047]) >> 5;\n+        int const rotAng = (int)klabs(sintable[((loogCounter + i) << 5) & 2047]) >> 5;\n         int const rotZoom  = 4096 + ((loogCounter + i) << 9);\n         int const rotX     = (-fix16_to_int(g_player[screenpeek].input->q16avel) >> 1) + (sintable[((loogCounter + i) << 6) & 2047] >> 10);\n \n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0005-e1m4-shrinker-bug.patch",
    "content": "diff --git a/source/duke3d/src/actors.cpp b/source/duke3d/src/actors.cpp\nindex 9a4405b2b..21f2570a4 100644\n--- a/source/duke3d/src/actors.cpp\n+++ b/source/duke3d/src/actors.cpp\n@@ -507,25 +507,16 @@ int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uin\n \n     int returnValue;\n     int32_t diffZ;\n-    spriteheightofs(spriteNum, &diffZ, 0);\n-    int newZ = pSprite->z - diffZ;\n+    spriteheightofs(spriteNum, &diffZ, 1);\n \n-    pSprite->z -= diffZ >> 1;\n-    switch (pSprite->statnum)\n+    if (pSprite->statnum == STAT_PROJECTILE)\n+        returnValue = clipmovex(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, diffZ >> 3, diffZ >> 3, clipType, 1);\n+    else\n     {\n-        default:\n-        {\n-            returnValue = clipmove(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType);\n-            break;\n-        }\n-\n-        case STAT_PROJECTILE:\n-        {\n-            returnValue = clipmovex(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, diffZ >> 1, diffZ >> 1, clipType, 1);\n-            break;\n-        }\n+        pSprite->z -= diffZ >> 1;\n+        returnValue = clipmove(&pSprite->pos, &newSectnum, change->x << 13, change->y << 13, clipDist, ZOFFSET6, ZOFFSET6, clipType);\n+        pSprite->z += diffZ >> 1;\n     }\n-    pSprite->z += diffZ >> 1;\n \n     // Testing: For some reason the assert below this was tripping for clients\n     EDUKE32_UNUSED int16_t   dbg_ClipMoveSectnum = newSectnum;\n@@ -573,6 +564,7 @@ int32_t A_MoveSpriteClipdist(int32_t spriteNum, vec3_t const * const change, uin\n \n     Bassert(newSectnum == pSprite->sectnum);\n \n+    int newZ = pSprite->z;\n     int32_t ceilhit, florhit;\n     int const doZUpdate = change->z ? A_CheckNeedZUpdate(spriteNum, change->z, &newZ, &ceilhit, &florhit) : 0;\n \n"
  },
  {
    "path": "scriptmodules/ports/eduke32/0006-e4m4-water-bug.patch",
    "content": "diff --git a/source/build/src/clip.cpp b/source/build/src/clip.cpp\nindex 24eb02368..1a7b57bb5 100644\n--- a/source/build/src/clip.cpp\n+++ b/source/build/src/clip.cpp\n@@ -945,14 +945,22 @@ static int get_floorspr_clipyou(vec2_t const v1, vec2_t const v2, vec2_t const v\n     return clipyou;\n }\n \n-static void clipupdatesector(vec2_t const pos, int16_t * const sectnum, int const walldist)\n+static void clipupdatesector(vec2_t const pos, int16_t * const sectnum, int walldist)\n {\n     if (inside_p(pos.x, pos.y, *sectnum))\n         return;\n \n+    int16_t nsecs = min<int16_t>(getsectordist(pos, *sectnum), INT16_MAX);\n+\n+    if (nsecs > (walldist + 8))\n+    {\n+        OSD_Printf(\"%s():%d shortest distance between origin point (%d, %d) and sector %d is %d. Sector may be corrupt!\\n\",\n+                   EDUKE32_FUNCTION, __LINE__, pos.x, pos.y, *sectnum, nsecs);\n+        walldist = 0x7fff;\n+    }\n+\n     static int16_t sectlist[MAXSECTORS];\n     static uint8_t sectbitmap[(MAXSECTORS+7)>>3];\n-    int16_t        nsecs;\n \n     bfirst_search_init(sectlist, sectbitmap, &nsecs, MAXSECTORS, *sectnum);\n \n"
  },
  {
    "path": "scriptmodules/ports/eduke32.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"eduke32\"\nrp_module_desc=\"Duke3D source port\"\nrp_module_licence=\"GPL2 https://voidpoint.io/terminx/eduke32/-/raw/master/package/common/gpl-2.0.txt?inline=false\"\nrp_module_repo=\"git https://voidpoint.io/terminx/eduke32.git master dfc16b08\"\nrp_module_section=\"opt\"\n\nfunction depends_eduke32() {\n    local depends=(\n        flac libflac-dev libvorbis-dev libpng-dev libvpx-dev freepats\n        libsdl2-dev libsdl2-mixer-dev\n    )\n\n    isPlatform \"x86\" && depends+=(nasm)\n    isPlatform \"gl\" || isPlatform \"mesa\" && depends+=(libgl1-mesa-dev libglu1-mesa-dev)\n    isPlatform \"x11\" && depends+=(libgtk2.0-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_eduke32() {\n    gitPullOrClone\n\n    # r6918 causes a 20+ second delay on startup on ARM devices\n    isPlatform \"arm\" && applyPatch \"$md_data/0001-revert-r6918.patch\"\n    # r7424 gives a black skybox when r_useindexedcolortextures is 0\n    applyPatch \"$md_data/0002-fix-skybox.patch\"\n    # r6776 breaks VC4 & GLES 2.0 devices that lack GL_RED internal\n    # format support for glTexImage2D/glTexSubImage2D\n    isPlatform \"gles\" && applyPatch \"$md_data/0003-replace-gl_red.patch\"\n    # gcc 6.3.x compiler fix\n    applyPatch \"$md_data/0004-recast-function.patch\"\n    # cherry-picked commit fixing a game bug in E1M4 (shrinker ray stuck)\n    applyPatch \"$md_data/0005-e1m4-shrinker-bug.patch\"\n    # two more commits r8241 + r8247 fixing a bug in E4M4 (instant death in water)\n    applyPatch \"$md_data/0006-e4m4-water-bug.patch\"\n}\n\nfunction build_eduke32() {\n    local params=(LTO=0 SDL_TARGET=2)\n\n    [[ \"$md_id\" == \"ionfury\" ]] && params+=(FURY=1)\n    ! isPlatform \"x86\" && params+=(NOASM=1)\n    ! isPlatform \"x11\" && params+=(HAVE_GTK2=0)\n    ! isPlatform \"gl3\" && params+=(POLYMER=0)\n    ! ( isPlatform \"gl\" || isPlatform \"mesa\" ) && params+=(USE_OPENGL=0)\n    # r7242 requires >1GB memory allocation due to netcode changes.\n    isPlatform \"arm\" && params+=(NETCODE=0)\n\n    make veryclean\n    CFLAGS+=\" -DSDL_USEFOLDER\" make \"${params[@]}\"\n\n    if [[ \"$md_id\" == \"ionfury\" ]]; then\n        md_ret_require=\"$md_build/fury\"\n    else\n        md_ret_require=\"$md_build/eduke32\"\n    fi\n}\n\nfunction install_eduke32() {\n    md_ret_files=('mapster32')\n\n    if [[ \"$md_id\" == \"ionfury\" ]]; then\n        md_ret_files+=('fury')\n    else\n        md_ret_files+=('eduke32')\n    fi\n}\n\nfunction game_data_eduke32() {\n    local dest=\"$romdir/ports/duke3d\"\n    if [[ \"$md_id\" == \"eduke32\" ]]; then\n        mkUserDir \"$dest\"\n        if [[ -z \"$(find \"$dest\" -maxdepth 1 -iname duke3d.grp)\" ]]; then\n            local temp=\"$(mktemp -d)\"\n            download \"$__archive_url/3dduke13.zip\" \"$temp\"\n            unzip -L -o \"$temp/3dduke13.zip\" -d \"$temp\" dn3dsw13.shr\n            unzip -L -o \"$temp/dn3dsw13.shr\" -d \"$dest\" duke3d.grp duke.rts\n            rm -rf \"$temp\"\n            chown -R \"$__user\":\"$__group\" \"$dest\"\n        fi\n    fi\n}\n\nfunction configure_eduke32() {\n    local appname=\"eduke32\"\n    local portname=\"duke3d\"\n    if [[ \"$md_id\" == \"ionfury\" ]]; then\n        appname=\"fury\"\n        portname=\"ionfury\"\n    fi\n    local config=\"$md_conf_root/$portname/settings.cfg\"\n\n    mkRomDir \"ports/$portname\"\n    moveConfigDir \"$home/.config/$appname\" \"$md_conf_root/$portname\"\n\n    add_games_eduke32 \"$portname\" \"$md_inst/$appname\"\n\n    # remove old launch script\n    rm -f \"$romdir/ports/Duke3D Shareware.sh\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        game_data_eduke32\n\n        touch \"$config\"\n        iniConfig \" \" '\"' \"$config\"\n\n        # enforce vsync for kms targets\n        isPlatform \"kms\" && iniSet \"r_swapinterval\" \"1\"\n\n        # the VC4 & V3D drivers render menu splash colours incorrectly without this\n        isPlatform \"mesa\" && iniSet \"r_useindexedcolortextures\" \"0\"\n\n        chown -R \"$__user\":\"$__group\" \"$config\"\n    fi\n}\n\nfunction add_games_eduke32() {\n    local portname=\"$1\"\n    local binary=\"$2\"\n    local game\n    local game_args\n    local game_path\n    local game_launcher\n    local num_games=4\n\n    if [[ \"$md_id\" == \"ionfury\" ]]; then\n        num_games=0\n        local game0=('Ion Fury' '' '')\n    else\n        local game0=('Duke Nukem 3D' '' '-addon 0')\n        local game1=('Duke Nukem 3D - Duke It Out In DC' 'addons/dc' '-addon 1')\n        local game2=('Duke Nukem 3D - Nuclear Winter' 'addons/nw' '-addon 2')\n        local game3=('Duke Nukem 3D - Caribbean - Lifes A Beach' 'addons/vacation' '-addon 3')\n        local game4=('NAM' 'addons/nam' '-nam')\n    fi\n\n    for ((game=0;game<=num_games;game++)); do\n        game_launcher=\"game$game[0]\"\n        game_path=\"game$game[1]\"\n        game_args=\"game$game[2]\"\n\n        if [[ -d \"$romdir/ports/$portname/${!game_path}\" ]]; then\n           addPort \"$md_id\" \"$portname\" \"${!game_launcher}\" \"pushd $md_conf_root/$portname; ${binary}.sh %ROM%; popd\" \"-j$romdir/ports/$portname/${game0[1]} -j$romdir/ports/$portname/${!game_path} ${!game_args}\"\n        fi\n    done\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        # we need to use a dumb launcher script to strip quotes from runcommand's generated arguments\n        cat > \"${binary}.sh\" << _EOF_\n#!/bin/bash\n# HACK: force vsync for RPI Mesa driver for now\nVC4_DEBUG=always_sync $binary \\$*\n_EOF_\n\n        chmod +x \"${binary}.sh\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/ports/gemrb.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"gemrb\"\nrp_module_desc=\"gemrb - open-source implementation of Infinity Engine\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/gemrb/gemrb/master/COPYING\"\nrp_module_repo=\"git https://github.com/gemrb/gemrb.git v0.8.6\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!mali dispmanx\"\n\nfunction depends_gemrb() {\n    getDepends python2-dev libopenal-dev cmake libpng-dev libfreetype6-dev libsdl2-dev libvorbis-dev libvlc-dev libvlccore-dev\n}\n\nfunction sources_gemrb() {\n    gitPullOrClone\n}\n\nfunction build_gemrb() {\n    mkdir -p build\n    cd build\n    make clean\n    cmake .. -DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DCMAKE_BUILD_TYPE=Release -DFREETYPE_INCLUDE_DIRS=/usr/include/freetype2/ -DSDL_BACKEND=SDL2 -DUSE_SDLMIXER=OFF\n    make\n    md_ret_require=\"$md_build/build/gemrb/gemrb\"\n}\n\nfunction install_gemrb() {\n    cd build\n    make install\n}\n\nfunction configure_gemrb() {\n    mkRomDir \"ports/baldurs1\"\n    mkRomDir \"ports/baldurs2\"\n    mkRomDir \"ports/icewind1\"\n    mkRomDir \"ports/icewind2\"\n    mkRomDir \"ports/planescape\"\n    mkRomDir \"ports/cache\"\n\n    addPort \"$md_id\" \"baldursgate1\" \"Baldurs Gate 1\" \"$md_inst/bin/gemrb -C $md_conf_root/baldursgate1/GemRB.cfg\"\n    addPort \"$md_id\" \"baldursgate2\" \"Baldurs Gate 2\" \"$md_inst/bin/gemrb -C $md_conf_root/baldursgate2/GemRB.cfg\"\n    addPort \"$md_id\" \"icewind1\" \"Icewind Dale 1\" \"$md_inst/bin/gemrb -C $md_conf_root/icewind1/GemRB.cfg\"\n    addPort \"$md_id\" \"icewind2\" \"Icewind Dale 2\" \"$md_inst/bin/gemrb -C $md_conf_root/icewind2/GemRB.cfg\"\n    addPort \"$md_id\" \"planescape\" \"Planescape Torment\" \"$md_inst/bin/gemrb -C $md_conf_root/planescape/GemRB.cfg\"\n\n    #create Baldurs Gate 1 configuration\n    cat > \"$md_conf_root/baldursgate1/GemRB.cfg\" << _EOF_\nGameType=bg1\nGameName=Baldurs Gate 1\nWidth=640\nHeight=480\nBpp=32\nFullscreen=0\nTooltipDelay=500\nAudioDriver = openal\nGUIEnhancements = 15\nDrawFPS=0\nCaseSensitive=1\nGamePath=$romdir/ports/baldurs1/\nCD1=$romdir/ports/baldurs1/\nCachePath=$romdir/ports/cache/\n_EOF_\n\n    #create Baldurs Gate 2 configuration\n    cat > \"$md_conf_root/baldursgate2/GemRB.cfg\" << _EOF_\nGameType=bg2\nGameName=Baldurs Gate 2\nWidth=640\nHeight=480\nBpp=32\nFullscreen=0\nTooltipDelay=500\nAudioDriver = openal\nGUIEnhancements = 15\nDrawFPS=0\nCaseSensitive=1\nGamePath=$romdir/ports/baldurs2/\nCD1=$romdir/ports/baldurs2/data/\nCachePath=$romdir/ports/cache/\n_EOF_\n\n    #create Icewind 1 configuration\n    cat > \"$md_conf_root/icewind1/GemRB.cfg\" << _EOF_\nGameType=auto\nGameName=Icewind Dale 1\nWidth=640\nHeight=480\nBpp=32\nFullscreen=0\nTooltipDelay=500\nAudioDriver = openal\nGUIEnhancements = 15\nDrawFPS=0\nCaseSensitive=1\nGamePath=$romdir/ports/icewind1/\nCD1=$romdir/ports/icewind1/Data/\nCD2=$romdir/ports/icewind1/CD2/Data/\nCD3=$romdir/ports/icewind1/CD3/Data/\nCachePath=$romdir/ports/cache/\n_EOF_\n\n    #create Icewind2 configuration\n    cat > \"$md_conf_root/icewind2/GemRB.cfg\" << _EOF_\nGameType=iwd2\nGameName=Icewind Dale 2\nWidth=800\nHeight=600\nBpp=32\nFullscreen=0\nTooltipDelay=500\nAudioDriver = openal\nGUIEnhancements = 15\nDrawFPS=0\nCaseSensitive=1\nGamePath=$romdir/ports/icewind2/\nCD1=$romdir/ports/icewind2/data/\nCachePath=$romdir/ports/cache/\n_EOF_\n\n    #create Planescape configuration\n    cat > \"$md_conf_root/planescape/GemRB.cfg\" << _EOF_\nGameType=pst\nGameName=Planescape Torment\nWidth=640\nHeight=480\nBpp=32\nFullscreen=0\nTooltipDelay=500\nAudioDriver = openal\nGUIEnhancements = 15\nDrawFPS=0\nCaseSensitive=1\nGamePath=$romdir/ports/planescape/\nCD1=$romdir/ports/planescape/data/\nCachePath=$romdir/ports/cache/\n_EOF_\n\n    chown \"$__user\":\"$__group\" \"$md_conf_root/baldursgate1/GemRB.cfg\"\n    chown \"$__user\":\"$__group\" \"$md_conf_root/baldursgate2/GemRB.cfg\"\n    chown \"$__user\":\"$__group\" \"$md_conf_root/icewind1/GemRB.cfg\"\n    chown \"$__user\":\"$__group\" \"$md_conf_root/icewind2/GemRB.cfg\"\n    chown \"$__user\":\"$__group\" \"$md_conf_root/planescape/GemRB.cfg\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/giana.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"giana\"\nrp_module_desc=\"Giana's Return\"\nrp_module_licence=\"NONCOM https://www.gianas-return.de/?page_id=6\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_giana() {\n    getDepends libsdl1.2-dev libsdl-mixer1.2-dev libraspberrypi-dev\n}\n\nfunction install_bin_giana() {\n    downloadAndExtract \"http://www.retroguru.com/gianas-return/gianas-return-v.latest-raspberrypi.zip\" \"$md_inst\"\n    patchVendorGraphics \"$md_inst/giana_rpi\"\n}\n\nfunction configure_giana() {\n    moveConfigDir \"$home/.giana\" \"$md_conf_root/giana\"\n\n    addPort \"$md_id\" \"giana\" \"Giana's Return\" \"pushd $md_inst; $md_inst/giana_rpi; popd\"\n\n    chmod +x \"$md_inst/giana_rpi\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/gzdoom/armv8_gcc12_fix.diff",
    "content": " Fails to build with gcc 12 for armv8 on aarch64 kernel due to -ffast-math options. Enabling -fmath-errno resolves it.\n\n Fixes:\n /usr/lib/gcc/arm-linux-gnueabihf/12/include/arm_neon.h: In function ‘float16x8_t vmulq_n_f16(float16x8_t, float16_t)’:\n /usr/lib/gcc/arm-linux-gnueabihf/12/include/arm_neon.h:17784:14: error: conversion of scalar ‘float’ to vector ‘float16x8_t’ involves truncation\n 17784 |   return __a * __b;\n       |          ~~~~^~~~~\n make[2]: *** [src/CMakeFiles/zdoom.dir/build.make:685: src/CMakeFiles/zdoom.dir/common/rendering/gles/gles_renderer.cpp.o] Error 1\n\ndiff --git a/CMakeLists.txt b/CMakeLists.txt\nindex c6ba69a..b4ef587 100644\n--- a/CMakeLists.txt\n+++ b/CMakeLists.txt\n@@ -158,7 +158,7 @@ endif()\n # Fast math flags, required by some subprojects\n set( ZD_FASTMATH_FLAG \"\" )\n if( DEM_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )\n-\tset( ZD_FASTMATH_FLAG \"-ffast-math -ffp-contract=fast\" )\n+\tset( ZD_FASTMATH_FLAG \"-ffast-math -ffp-contract=fast -fmath-errno\" )\n elseif( MSVC )\n \tset( ZD_FASTMATH_FLAG \"/fp:fast\" )\n endif()\n"
  },
  {
    "path": "scriptmodules/ports/gzdoom/lzma_armv7_crc.diff",
    "content": "--- a/libraries/lzma/C/7zCrc.c\n+++ b/libraries/lzma/C/7zCrc.c\n@@ -71,7 +71,7 @@\n \n #ifdef MY_CPU_LE\n \n-#if defined(MY_CPU_ARM_OR_ARM64)\n+#if defined(MY_CPU_ARM_OR_ARM64) && 0\n \n // #pragma message(\"ARM*\")\n \n"
  },
  {
    "path": "scriptmodules/ports/gzdoom.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"gzdoom\"\nrp_module_desc=\"GZDoom is a feature centric port for all Doom engine games, based on ZDoom\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/ZDoom/gzdoom/master/LICENSE\"\nrp_module_repo=\"git https://github.com/ZDoom/gzdoom :_get_version_gzdoom\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2 !armv6\"\n\nfunction _get_version_gzdoom() {\n    # default GZDoom version\n    local gzdoom_version=\"g4.14.2\"\n\n    # 32 bit is no longer supported since g4.8.1\n    isPlatform \"32bit\" && gzdoom_version=\"g4.8.0\"\n    echo $gzdoom_version\n}\n\nfunction _get_version_zmusic_gzdoom() {\n    echo \"1.3.0\"\n}\n\nfunction depends_gzdoom() {\n    local depends=(\n        cmake libfluidsynth-dev libsdl2-dev libmpg123-dev libsndfile1-dev libbz2-dev\n        libopenal-dev libjpeg-dev libgl1-mesa-dev libasound2-dev libmpg123-dev libsndfile1-dev\n        libvpx-dev libwebp-dev pkg-config\n        zlib1g-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_gzdoom() {\n    gitPullOrClone\n    # add 'ZMusic' repo\n    cd \"$md_build\"\n    gitPullOrClone zmusic https://github.com/ZDoom/ZMusic $(_get_version_zmusic_gzdoom)\n    # workaround for Ubuntu 20.04 older vpx/wepm dev libraries\n    sed -i 's/IMPORTED_TARGET libw/IMPORTED_TARGET GLOBAL libw/' CMakeLists.txt\n    # lzma assumes hardware crc support on arm which breaks when building on armv7\n    isPlatform \"armv7\" && applyPatch \"$md_data/lzma_armv7_crc.diff\"\n    # fix build with gcc 12 for armv8 on aarch64 kernel due to -ffast-math options\n    isPlatform \"armv8\" && [[ \"$__gcc_version\" -eq 12 ]] && applyPatch \"$md_data/armv8_gcc12_fix.diff\"\n}\n\nfunction build_gzdoom() {\n    mkdir -p release\n\n    # build 'ZMusic' first\n    pushd zmusic\n    cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"$md_build/release/zmusic\" .\n    make\n    make install\n    popd\n\n    cd release\n    local params=(-DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DPK3_QUIET_ZIPDIR=ON -DCMAKE_BUILD_TYPE=Release -DDYN_OPENAL=ON -DCMAKE_PREFIX_PATH=\"$md_build/release/zmusic\")\n    ! hasFlag \"vulkan\" && params+=(-DHAVE_VULKAN=OFF)\n\n    cmake \"${params[@]}\" ..\n    make\n    md_ret_require=\"$md_build/release/$md_id\"\n}\n\nfunction install_gzdoom() {\n    md_ret_files=(\n        'release/brightmaps.pk3'\n        'release/gzdoom'\n        'release/gzdoom.pk3'\n        'release/lights.pk3'\n        'release/game_support.pk3'\n        'release/game_widescreen_gfx.pk3'\n        'release/soundfonts'\n        \"release/zmusic/lib/libzmusic.so.1\"\n        \"release/zmusic/lib/libzmusic.so.$(_get_version_zmusic_gzdoom)\"\n        'README.md'\n    )\n}\n\nfunction add_games_gzdoom() {\n    local params=(\"-fullscreen\")\n    local launcher_prefix=\"DOOMWADDIR=$romdir/ports/doom\"\n\n    # FluidSynth is too memory/CPU intensive, use OPL emulation for MIDI\n    if isPlatform \"arm\"; then\n        params+=(\"+set snd_mididevice -3\")\n    fi\n    # when using the 32bit version on GLES platforms, pre-set the renderer\n    if isPlatform \"32bit\" && hasFlag \"gles\"; then\n        params+=(\"+set vid_preferbackend 2\")\n    fi\n\n    if isPlatform \"kms\"; then\n        params+=(\"-width %XRES%\" \"-height %YRES%\")\n    fi\n\n    _add_games_lr-prboom \"$launcher_prefix $md_inst/$md_id -iwad %ROM% ${params[*]}\"\n}\n\nfunction configure_gzdoom() {\n    mkRomDir \"ports/doom\"\n\n    moveConfigDir \"$home/.config/$md_id\" \"$md_conf_root/doom\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    game_data_lr-prboom\n    add_games_${md_id}\n}\n\n"
  },
  {
    "path": "scriptmodules/ports/ionfury.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ionfury\"\nrp_module_desc=\"Ion Fury - commercial FPS game based on eduke32 source port\"\nrp_module_licence=\"GPL2 https://voidpoint.io/terminx/eduke32/-/raw/master/package/common/gpl-2.0.txt?inline=false\"\nrp_module_repo=\"git https://voidpoint.io/terminx/eduke32.git master dfc16b08\"\nrp_module_section=\"exp\"\n\nfunction depends_ionfury() {\n    depends_eduke32\n}\n\nfunction sources_ionfury() {\n    # patches are also shared with eduke32, so avoid duplication\n    md_data=\"$(dirname $md_data)/eduke32\" sources_eduke32\n}\n\nfunction build_ionfury() {\n    build_eduke32\n}\n\nfunction install_ionfury() {\n    install_eduke32\n}\n\nfunction configure_ionfury() {\n    configure_eduke32\n}\n"
  },
  {
    "path": "scriptmodules/ports/ioquake3.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ioquake3\"\nrp_module_desc=\"Quake 3 source port\"\nrp_module_licence=\"GPL2 https://github.com/ioquake/ioq3/blob/master/COPYING.txt\"\nrp_module_repo=\"git https://github.com/ioquake/ioq3 main :_get_commit_ioquake3\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!videocore\"\n\nfunction _get_commit_ioquake3() {\n    # On Buster and Bullseye we have to build using make (an old method) instead of cmake.\n    # This is because ioquake3 requires CMake 3.25 or higher which is satisfied only on Bookworm.\n    if [[ \"$__os_debian_ver\" -lt 12 ]]; then\n        # This is the latest commit before the Makefile was removed.\n        echo 7ac92951f2da597611ab4525023979df2f92047a\n    fi\n}\n\nfunction depends_ioquake3() {\n    getDepends cmake libsdl2-dev libgl1-mesa-dev\n}\n\nfunction sources_ioquake3() {\n    gitPullOrClone\n}\n\nfunction build_ioquake3() {\n    if [[ \"$__os_debian_ver\" -lt 12 ]]; then\n        make clean\n        I_ACKNOWLEDGE_THE_MAKEFILE_IS_DEPRECATED=1 make\n    else\n        cmake -S . -B build -DCMAKE_BUILD_TYPE=Release\n        cmake --build build --clean-first\n    fi\n    md_ret_require=\"$md_build/$(_release_dir)/ioquake3\"\n}\n\nfunction _release_dir() {\n    if [[ \"$__os_debian_ver\" -lt 12 ]]; then\n        # exact parsing from Makefile\n        local arch_ioquake3=\"$(uname -m | sed -e 's/i.86/x86/' | sed -e 's/^arm.*/arm/' | sed -e 's/aarch64/arm64/')\"\n        echo \"build/release-linux-${arch_ioquake3}\"\n    else\n        echo \"build/Release\"\n    fi\n}\n\nfunction install_ioquake3() {\n    md_ret_files=(\n        \"$(_release_dir)/ioq3ded\"\n        \"$(_release_dir)/ioquake3\"\n        \"$(_release_dir)/renderer_opengl1.so\"\n        \"$(_release_dir)/renderer_opengl2.so\"\n    )\n}\n\nfunction configure_ioquake3() {\n    local launcher=(\"$md_inst/ioquake3\")\n    isPlatform \"mesa\" && launcher+=(\"+set cl_renderer opengl1\")\n    isPlatform \"kms\" && launcher+=(\"+set r_mode -1\" \"+set r_customwidth %XRES%\" \"+set r_customheight %YRES%\" \"+set r_swapInterval 1\")\n\n    addPort \"$md_id\" \"quake3\" \"Quake III Arena\" \"${launcher[*]}\"\n\n    mkRomDir \"ports/quake3\"\n\n    moveConfigDir \"$md_inst/baseq3\" \"$romdir/ports/quake3\"\n    moveConfigDir \"$home/.q3a\" \"$md_conf_root/ioquake3\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_quake3\n}\n"
  },
  {
    "path": "scriptmodules/ports/jumpnbump/jumpnbump.sh",
    "content": "#!/usr/bin/env bash\nROOTDIR=\"\"\nMD_CONF_ROOT=\"\"\nROMDIR=\"\"\nMD_INST=\"\"\nDIALOG=(dialog --backtitle \"RetroPie Jump n' Bump Launcher\")\n\n# source ini functions from RetroPie\nsource \"$ROOTDIR/lib/inifuncs.sh\"\n\n# init program args\nfunction init_args() {\n    args=(-fullscreen)\n    iniConfig \" = \" \"\" \"$MD_CONF_ROOT/jumpnbump/options.cfg\"\n    iniGet \"nogore\" && [[ \"$ini_value\" -eq 1 ]] && args+=(-nogore)\n    iniGet \"noflies\" && [[ \"$ini_value\" -eq 1 ]] && args+=(-noflies)\n    iniGet \"scaleup\" && [[ \"$ini_value\" -eq 1 ]] && args+=(-scaleup)\n    iniGet \"musicnosound\" && [[ \"$ini_value\" -eq 1 ]] && args+=(-musicnosound)\n    return 0\n}\n\n# main menu\nfunction main_menu() {\n    local cmd\n    local options\n    local choice\n    while true; do\n        cmd=(\"${DIALOG[@]}\" --menu \"Main Menu\" 0 0 0)\n        options=(\n            L \"Local Game Mode\"\n            S \"Net: Start Server\"\n            C \"Net: Connect to Server\"\n            H \"Net: Help\"\n        )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty) || return\n        case \"$choice\" in\n            L) init_args && select_level_menu && return ;;\n            S) init_args && start_server_menu && select_level_menu && return ;;\n            C) init_args && connect_server_menu && select_level_menu && return ;;\n            H) netplay_help ;;\n        esac\n    done\n}\n\n# select level menu\nfunction select_level_menu() {\n    local cmd=(\"${DIALOG[@]}\" --ok-label \"Start\" --extra-button --extra-label \"Start Mirror\" --menu \"Select Level\" 16 0 16)\n    local levels=(D \"(default level)\")\n    local idx=1\n    local choice\n    local ret\n    for file in \"$ROMDIR\"/ports/jumpnbump/*.dat; do\n        levels+=(\"$idx\" \"${file##*/}\")\n        ((idx++))\n    done\n    choice=$(\"${cmd[@]}\" \"${levels[@]}\" 2>&1 >/dev/tty)\n    ret=$?\n    [[ \"$ret\" -eq 1 ]] && return 1\n    [[ \"$ret\" -eq 3 ]] && args+=(-mirror)\n    [[ \"$choice\" == \"D\" ]] && return\n    args+=(-dat \"$ROMDIR/ports/jumpnbump/${levels[$((choice * 2 + 1))]}\")\n}\n\n# start server menu\nfunction start_server_menu() {\n    local cmd=(\"${DIALOG[@]}\" --menu \"Number of players\" 0 0 0)\n    local options=(\n        1 \"One Remote + One Local\"\n        2 \"Two Remotes + One Local\"\n        3 \"Three Remotes + One Local\"\n    )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty) || return\n    args+=(-server \"$choice\")\n}\n\n# connect to server menu\nfunction connect_server_menu() {\n    local cmd=(\"${DIALOG[@]}\" --inputbox \"Please enter the address of the remote server\" 10 35)\n    choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty) || return\n    args+=(-connect \"$choice\")\n}\n\n# netplay help\nfunction netplay_help() {\n    local help\n    read -r -d \"\" help <<\"_EOF_\"\n1. On the server device, select \"Start Server\" and choose the number of additional players (1-3) to wait for.\n\n2. On each remote player device, select \"Connect to Server\" and enter the IP address of the server.\n\n3. All players (server and clients) must select the same level and mirror settings.\n_EOF_\n    \"${DIALOG[@]}\" --title \"Net Help\" --msgbox \"$help\" 16 50 2>&1 >/dev/tty\n}\n\n# start main menu\nmain_menu || exit\n\"$MD_INST\"/bin/jumpnbump \"${args[@]}\" \"$@\"\n"
  },
  {
    "path": "scriptmodules/ports/jumpnbump.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"jumpnbump\"\nrp_module_desc=\"Jump 'n Bump, play cute bunnies jumping on each other's heads - Modernization fork\"\nrp_module_help=\"Copy custom game levels (.dat) to $romdir/ports/jumpnbump\"\nrp_module_licence=\"GPL2 https://gitlab.com/LibreGames/jumpnbump/raw/master/COPYING\"\nrp_module_repo=\"git https://gitlab.com/LibreGames/jumpnbump.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_jumpnbump() {\n    getDepends libsdl2-dev libsdl2-net-dev libsdl2-mixer-dev libbz2-dev zlib1g-dev\n}\n\nfunction sources_jumpnbump() {\n    gitPullOrClone\n}\n\nfunction build_jumpnbump() {\n    make clean\n    CFLAGS=\"$CFLAGS -fsigned-char\" make PREFIX=\"$md_inst\"\n    md_ret_require=\"$md_build/jumpnbump\"\n}\n\nfunction install_jumpnbump() {\n    make PREFIX=\"$md_inst\" install\n    strip \"$md_inst\"/bin/{gobpack,jnbpack,jnbunpack,jumpnbump}\n}\n\nfunction game_data_jumpnbump() {\n    local tmpdir=\"$(mktemp -d)\"\n    local compressed\n    local uncompressed\n\n    # install extra levels from Debian's jumpnbump-levels package\n    downloadAndExtract \"https://salsa.debian.org/games-team/jumpnbump-levels/-/archive/master/jumpnbump-levels-master.tar.bz2\" \"$tmpdir\" --strip-components 1 --wildcards \"*.bz2\"\n    for compressed in \"$tmpdir\"/*.bz2; do\n        uncompressed=\"${compressed##*/}\"\n        uncompressed=\"${uncompressed%.bz2}\"\n        if [[ ! -f \"$romdir/ports/jumpnbump/$uncompressed\" ]]; then\n            bzcat \"$compressed\" > \"$romdir/ports/jumpnbump/$uncompressed\"\n            chown -R \"$__user\":\"$__group\" \"$romdir/ports/jumpnbump/$uncompressed\"\n        fi\n    done\n    rm -rf \"$tmpdir\"\n}\n\nfunction configure_jumpnbump() {\n    addPort \"$md_id\" \"jumpnbump\" \"Jump 'n Bump\" \"$md_inst/jumpnbump.sh\"\n    mkRomDir \"ports/jumpnbump\"\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # install game data\n    game_data_jumpnbump\n\n    # install launch script\n    cp \"$md_data/jumpnbump.sh\" \"$md_inst\"\n    iniConfig \"=\" '\"' \"$md_inst/jumpnbump.sh\"\n    iniSet \"ROOTDIR\" \"$rootdir\"\n    iniSet \"MD_CONF_ROOT\" \"$md_conf_root\"\n    iniSet \"ROMDIR\" \"$romdir\"\n    iniSet \"MD_INST\" \"$md_inst\"\n\n    # set default game options on first install\n    if [[ ! -f \"$md_conf_root/jumpnbump/options.cfg\" ]];  then\n        iniConfig \" = \" \"\" \"$md_conf_root/jumpnbump/options.cfg\"\n        iniSet \"nogore\" \"1\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/ports/kodi.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"kodi\"\nrp_module_desc=\"Kodi - Open source home theatre software\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/xbmc/xbmc/master/LICENSE.md\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali !osmc !xbian\"\n\nfunction _update_hook_kodi() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage kodi && mkdir -p \"$md_inst\"\n}\n\nfunction depends_kodi() {\n    # Raspberry Pi OS\n    if [[ \"$__os_id\" = \"Raspbian\" ]] && isPlatform \"rpi\"; then\n        if [[ \"$__os_debian_ver\" -le 10 ]]; then\n            if [[ \"$md_mode\" == \"install\" ]]; then\n                # remove old repository\n                rm -f /etc/apt/sources.list.d/mene.list\n                echo \"deb http://pipplware.pplware.pt/pipplware/dists/$__os_codename/main/binary/ ./\" >/etc/apt/sources.list.d/pipplware.list\n                download http://pipplware.pplware.pt/pipplware/key.asc - | apt-key add - &>/dev/null\n            else\n                rm -f /etc/apt/sources.list.d/pipplware.list\n                apt-key del 4096R/BAA567BB >/dev/null\n            fi\n        fi\n        if [[ \"$__os_debian_ver\" -gt 10 ]]; then\n            # install Kodi from the RPI repos directly\n            # make sure we're not installing Debian/Raspbian version by pinning the origin of the packages\n            local apt_pin_file=\"/etc/apt/preferences.d/01-rpie-pin-kodi\"\n            if [[ ! -f \"$apt_pin_file\" ]]; then\n                echo -e \"Package: kodi*\\nPin: release o=Raspberry Pi Foundation\\nPin-Priority: 900\" > \"$apt_pin_file\"\n            fi\n        fi\n    # ubuntu\n    elif [[ -n \"$__os_ubuntu_ver\" ]] && isPlatform \"x86\"; then\n        if [[ \"$md_mode\" == \"install\" ]]; then\n            apt-add-repository -y ppa:team-xbmc/ppa\n        else\n            apt-add-repository --remove -y ppa:team-xbmc/ppa\n        fi\n    # others\n    else\n        md_ret_errors+=(\"Sorry, but kodi is not installable for your OS/Platform via RetroPie-Setup\")\n        return 1\n    fi\n\n    # required for reboot/shutdown options. Don't try and remove if removing dependencies\n    [[ \"$md_mode\" == \"install\" ]] && getDepends polkitd\n\n    addUdevInputRules\n}\n\nfunction install_bin_kodi() {\n    # force aptInstall to get a fresh list before installing\n    __apt_update=0\n\n    # not all the kodi packages may be available depending on repository\n    # so we will check and install what's available\n    local all_pkgs=(kodi kodi-peripheral-joystick kodi-inputstream-adaptive kodi-vfs-libarchive kodi-vfs-sftp kodi-vfs-nfs)\n    compareVersions \"$__os_ubuntu_ver\" lt 22.04 && all_pkgs+=(kodi-inputstream-rtmp)\n    local avail_pkgs=()\n    local pkg\n    for pkg in \"${all_pkgs[@]}\"; do\n        # check if the package is available - we use \"madison\" rather than \"show\"\n        # as madison won't show referenced virtual packages which we don't want\n        local ret=$(apt-cache madison \"$pkg\" 2>/dev/null)\n        [[ -n \"$ret\" ]] && avail_pkgs+=(\"$pkg\")\n    done\n    aptInstall \"${avail_pkgs[@]}\"\n}\n\nfunction remove_kodi() {\n    aptRemove kodi\n    rp_callModule kodi depends remove\n}\n\nfunction configure_kodi() {\n    moveConfigDir \"$home/.kodi\" \"$md_conf_root/kodi\"\n\n    addPort \"$md_id\" \"kodi\" \"Kodi\" \"kodi-standalone\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/lincity-ng.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lincity-ng\"\nrp_module_desc=\"lincity-ng - Open Source City Building Game\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/lincity-ng/lincity-ng/master/COPYING\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction _update_hook_lincity-ng() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage lincity-ng && mkdir -p \"$md_inst\"\n}\n\nfunction depends_lincity-ng() {\n    ! isPlatform \"x11\" && getDepends xorg\n}\n\nfunction install_bin_lincity-ng() {\n    aptInstall lincity-ng\n}\n\nfunction remove_lincity-ng() {\n    aptRemove lincity-ng\n}\n\nfunction configure_lincity-ng() {\n    local binary=\"XINIT:/usr/games/lincity-ng\"\n\n    addPort \"$md_id\" \"lincity-ng\" \"LinCity-NG\" \"$binary\"\n\n    moveConfigDir \"$home/.lincity-ng\" \"$md_conf_root/lincity-ng\"\n    # fix for wrong config location\n    if [[ -d \"/lincity-ng\" ]]; then\n        cp -R /lincity-ng \"$md_conf_root/\"\n        rm -rf /lincity-ng\n        chown \"$__user\":\"$__group\" \"$md_conf_root/lincity-ng\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/ports/love-0.10.2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"love-0.10.2\"\nrp_module_desc=\"Love - 2d Game Engine v0.10.2\"\nrp_module_help=\"Copy your Love games to $romdir/love\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/love2d/love/0.10.2/license.txt\"\nrp_module_repo=\"git https://github.com/love2d/love 0.10.2\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!aarch64\"\n\nfunction depends_love-0.10.2() {\n    depends_love\n}\n\nfunction sources_love-0.10.2() {\n    gitPullOrClone\n    # libluajit-5.1-dev in buster (and also on Ubuntu 18.04+) still has\n    # LUA_VERSION_NUM defined as 501 but requires the newer luaL_Reg named struct.\n    # adjusting the compatibility code #if to check for LUA_VERSION_NUM >= 501 fixes this.\n    sed -i \"s/LUA_VERSION_NUM > 501/LUA_VERSION_NUM >= 501/\" \"$md_build/src/libraries/luasocket/libluasocket/lua.h\"\n}\n\nfunction build_love-0.10.2() {\n    build_love\n}\n\nfunction install_love-0.10.2() {\n    install_love\n}\n\nfunction game_data_love-0.10.2() {\n    game_data_love\n}\n\nfunction configure_love-0.10.2() {\n    configure_love\n}\n"
  },
  {
    "path": "scriptmodules/ports/love.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"love\"\nrp_module_desc=\"Love - 2d Game Engine\"\nrp_module_help=\"Copy your Love games to $romdir/love\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/love2d/love/master/license.txt\"\nrp_module_repo=\"git https://github.com/love2d/love 11.5\"\nrp_module_section=\"opt\"\n\nfunction depends_love() {\n    local depends=(autotools-dev automake libtool pkg-config libfreetype6-dev libluajit-5.1-dev libphysfs-dev libsdl2-dev libopenal-dev libogg-dev libtheora-dev libvorbis-dev libflac-dev libflac++-dev libmodplug-dev libmpg123-dev libmng-dev libjpeg-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_love() {\n    gitPullOrClone\n}\n\nfunction build_love() {\n    ./platform/unix/automagic\n    local params=(--prefix=\"$md_inst\")\n\n    # workaround for https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65612 on gcc 5.x+\n    if isPlatform \"x86\"; then\n        CXXFLAGS+=\" -lgcc_s -lgcc\" ./configure \"${params[@]}\"\n    else\n        ./configure \"${params[@]}\"\n    fi\n\n    make clean\n    make\n    md_ret_require=\"$md_build/src/love\"\n}\n\nfunction install_love() {\n    make install\n}\n\nfunction game_data_love() {\n    # get Mari0 1.6.2 (freeware game data)\n    if [[ ! -f \"$romdir/love/mari0.love\" ]]; then\n        downloadAndExtract \"https://github.com/Stabyourself/mari0/archive/1.6.2.tar.gz\" \"$__tmpdir/mari0\" --strip-components 1\n        pushd \"$__tmpdir/mari0\"\n        zip -qr \"$romdir/love/mari0.love\" .\n        popd\n        rm -fr \"$__tmpdir/mari0\"\n        chown \"$__user\":\"$__group\" \"$romdir/love/mari0.love\"\n    fi\n}\n\nfunction configure_love() {\n    setConfigRoot \"\"\n\n    mkRomDir \"love\"\n\n    addEmulator 1 \"$md_id\" \"love\" \"$md_inst/bin/love %ROM%\"\n    addSystem \"love\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_love\n}\n"
  },
  {
    "path": "scriptmodules/ports/lzdoom/01_remove_cmake_arm_options.diff",
    "content": "diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt\nindex 5b3e777..0bce388 100644\n--- a/src/CMakeLists.txt\n+++ b/src/CMakeLists.txt\n@@ -334,16 +334,6 @@ if( ZD_CMAKE_COMPILER_IS_GNUCXX_COMPATIBLE )\n \tset( CMAKE_C_FLAGS \"-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_C_FLAGS}\" )\n \tset( CMAKE_CXX_FLAGS \"-Wall -Wextra -Wno-unused -Wno-unused-parameter -Wno-missing-field-initializers -ffp-contract=off ${CMAKE_CXX_FLAGS}\" )\n \n-\t# ARM processors (Raspberry Pi, et al) - enable ARM NEON support.\n-\tif(${CMAKE_SYSTEM_PROCESSOR} MATCHES \"arm\")\n-\t\tset (USE_ARMV8 0 CACHE BOOL \"Use ARMv8 instructions - Raspberry Pi 3\")\n-\t\tif (USE_ARMV8)\n-\t\t\tset( CMAKE_CXX_FLAGS \"-mcpu=cortex-a53 -mfpu=neon-fp-armv8 -mtune=cortex-a53 -mhard-float -DNO_SSE ${CMAKE_CXX_FLAGS}\" )\n-\t\telse ()\n-\t\t\tset( CMAKE_CXX_FLAGS \"-mcpu=cortex-a7 -mfpu=neon-vfpv4 -mtune=cortex-a7 -mhard-float -DNO_SSE ${CMAKE_CXX_FLAGS}\" )\n-\t\tendif ()\n-\tendif ()\n-\n \tif( NOT X64 AND NOT CAN_DO_MFPMATH )\n \t\tset( CMAKE_C_FLAGS \"-DNO_SSE ${CMAKE_C_FLAGS}\" )\n \t\tset( CMAKE_CXX_FLAGS \"-DNO_SSE ${CMAKE_CXX_FLAGS}\" )\n"
  },
  {
    "path": "scriptmodules/ports/lzdoom/02_lzma_sdk_dont_force_arm_crc32.diff",
    "content": "diff --git a/libraries/lzma/C/7zCrc.c b/libraries/lzma/C/7zCrc.c\nindex f186324..f3ae7be 100644\n--- a/libraries/lzma/C/7zCrc.c\n+++ b/libraries/lzma/C/7zCrc.c\n@@ -83,12 +83,6 @@ UInt32 MY_FAST_CALL CrcUpdateT1(UInt32 v, const void *data, size_t size, const U\n     #endif\n   #elif (defined(__clang__) && (__clang_major__ >= 3)) \\\n      || (defined(__GNUC__) && (__GNUC__ > 4))\n-      #if !defined(__ARM_FEATURE_CRC32)\n-        #define __ARM_FEATURE_CRC32 1\n-          #if (!defined(__clang__) || (__clang_major__ > 3)) // fix these numbers\n-            #define ATTRIB_CRC __attribute__((__target__(\"arch=armv8-a+crc\")))\n-          #endif\n-      #endif\n       #if defined(__ARM_FEATURE_CRC32)\n         #define USE_ARM64_CRC\n         #include <arm_acle.h>\n"
  },
  {
    "path": "scriptmodules/ports/lzdoom/03_extra_includes.diff",
    "content": "diff --git a/libraries/music_common/fileio.h b/libraries/music_common/fileio.h\nindex dcea971..8affc3b 100644\n--- a/libraries/music_common/fileio.h\n+++ b/libraries/music_common/fileio.h\n@@ -27,6 +27,7 @@\n #include <string.h>\n #include <vector>\n #include <string>\n+#include <cstdint>\n \n #if defined _WIN32 && !defined _WINDOWS_\t// only define this if windows.h is not included.\n \t// I'd rather not include Windows.h for just this. This header is not supposed to pollute everything it touches.\ndiff --git a/libraries/zmusic/mididevices/music_adlmidi_mididevice.cpp b/libraries/zmusic/mididevices/music_adlmidi_mididevice.cpp\nindex 4d1f844..6c5e6b3 100644\n--- a/libraries/zmusic/mididevices/music_adlmidi_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_adlmidi_mididevice.cpp\n@@ -35,6 +35,7 @@\n // HEADER FILES ------------------------------------------------------------\n \n #include <stdlib.h>\n+#include <stdexcept>\n \n #include \"zmusic/zmusic_internal.h\"\n #include \"mididevice.h\"\ndiff --git a/libraries/zmusic/mididevices/music_fluidsynth_mididevice.cpp b/libraries/zmusic/mididevices/music_fluidsynth_mididevice.cpp\nindex 4e0edf4..7196830 100644\n--- a/libraries/zmusic/mididevices/music_fluidsynth_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_fluidsynth_mididevice.cpp\n@@ -41,6 +41,7 @@\n #include \"mididevice.h\"\n #include \"zmusic/mus2midi.h\"\n \n+#include <stdexcept>\n // FluidSynth implementation of a MIDI device -------------------------------\n \n FluidConfig fluidConfig;\ndiff --git a/libraries/zmusic/mididevices/music_opl_mididevice.cpp b/libraries/zmusic/mididevices/music_opl_mididevice.cpp\nindex 8ed7446..5e17edc 100644\n--- a/libraries/zmusic/mididevices/music_opl_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_opl_mididevice.cpp\n@@ -39,6 +39,8 @@\n #include \"mididevice.h\"\n #include \"zmusic/mus2midi.h\"\n \n+#include <stdexcept>\n+\n #ifdef HAVE_OPL\n #include \"oplsynth/opl.h\"\n #include \"oplsynth/opl_mus_player.h\"\n@@ -333,4 +335,4 @@ MIDIDevice* CreateOplMIDIDevice(const char* Args)\n {\n \tthrow std::runtime_error(\"OPL device not supported in this configuration\");\n }\n-#endif\n\\ No newline at end of file\n+#endif\ndiff --git a/libraries/zmusic/mididevices/music_opnmidi_mididevice.cpp b/libraries/zmusic/mididevices/music_opnmidi_mididevice.cpp\nindex fece81a..30447a7 100644\n--- a/libraries/zmusic/mididevices/music_opnmidi_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_opnmidi_mididevice.cpp\n@@ -37,6 +37,8 @@\n #include \"mididevice.h\"\n #include \"zmusic/zmusic_internal.h\"\n \n+#include <stdexcept>\n+\n #ifdef HAVE_OPN\n #include \"opnmidi.h\"\n \ndiff --git a/libraries/zmusic/mididevices/music_timidity_mididevice.cpp b/libraries/zmusic/mididevices/music_timidity_mididevice.cpp\nindex 2d22192..0538d3d 100644\n--- a/libraries/zmusic/mididevices/music_timidity_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_timidity_mididevice.cpp\n@@ -38,6 +38,7 @@\n #include \"mididevice.h\"\n #include \"zmusic/zmusic_internal.h\"\n \n+#include <stdexcept>\n #ifdef HAVE_GUS\n \n #include \"timidity/timidity.h\"\ndiff --git a/libraries/zmusic/mididevices/music_timiditypp_mididevice.cpp b/libraries/zmusic/mididevices/music_timiditypp_mididevice.cpp\nindex 825e80e..342d642 100644\n--- a/libraries/zmusic/mididevices/music_timiditypp_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_timiditypp_mididevice.cpp\n@@ -35,6 +35,8 @@\n #include \"mididevice.h\"\n #include \"zmusic/zmusic_internal.h\"\n \n+#include <stdexcept>\n+\n #ifdef HAVE_TIMIDITY\n \n #include \"timiditypp/timidity.h\"\n@@ -239,4 +241,4 @@ MIDIDevice* CreateTimidityPPMIDIDevice(const char* Args, int samplerate)\n {\n \tthrow std::runtime_error(\"Timidity++ device not supported in this configuration\");\n }\n-#endif\n\\ No newline at end of file\n+#endif\ndiff --git a/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp b/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp\nindex d610566..a2e1809 100644\n--- a/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_wavewriter_mididevice.cpp\n@@ -40,6 +40,7 @@\n #include \"../music_common/fileio.h\"\n #include <errno.h>\n \n+#include <stdexcept>\n // MACROS ------------------------------------------------------------------\n \n // TYPES -------------------------------------------------------------------\ndiff --git a/libraries/zmusic/mididevices/music_wildmidi_mididevice.cpp b/libraries/zmusic/mididevices/music_wildmidi_mididevice.cpp\nindex 2146830..685bbe1 100644\n--- a/libraries/zmusic/mididevices/music_wildmidi_mididevice.cpp\n+++ b/libraries/zmusic/mididevices/music_wildmidi_mididevice.cpp\n@@ -37,6 +37,7 @@\n #include \"mididevice.h\"\n #include \"zmusic/zmusic_internal.h\"\n \n+#include <stdexcept>\n #ifdef HAVE_WILDMIDI\n \n #include \"wildmidi/wildmidi_lib.h\"\n@@ -284,4 +285,4 @@ MIDIDevice* CreateWildMIDIDevice(const char* Args, int samplerate)\n {\n \tthrow std::runtime_error(\"WildMidi device not supported in this configuration\");\n }\n-#endif\n\\ No newline at end of file\n+#endif\ndiff --git a/libraries/zmusic/musicformats/music_midi.cpp b/libraries/zmusic/musicformats/music_midi.cpp\nindex 6c261f9..e693dca 100644\n--- a/libraries/zmusic/musicformats/music_midi.cpp\n+++ b/libraries/zmusic/musicformats/music_midi.cpp\n@@ -36,6 +36,7 @@\n \n #include <string>\n #include <algorithm>\n+#include <stdexcept>\n #include <assert.h>\n #include \"zmusic/zmusic_internal.h\"\n #include \"zmusic/musinfo.h\"\ndiff --git a/libraries/zmusic/streamsources/music_gme.cpp b/libraries/zmusic/streamsources/music_gme.cpp\nindex 16fdc77..4ae886e 100644\n--- a/libraries/zmusic/streamsources/music_gme.cpp\n+++ b/libraries/zmusic/streamsources/music_gme.cpp\n@@ -43,6 +43,7 @@\n #include <mutex>\n #include \"../..//libraries/music_common/fileio.h\"\n \n+#include <stdexcept>\n // MACROS ------------------------------------------------------------------\n \n // TYPES -------------------------------------------------------------------\ndiff --git a/libraries/zmusic/streamsources/music_opl.cpp b/libraries/zmusic/streamsources/music_opl.cpp\nindex 87f2723..90e5388 100644\n--- a/libraries/zmusic/streamsources/music_opl.cpp\n+++ b/libraries/zmusic/streamsources/music_opl.cpp\n@@ -37,7 +37,7 @@\n #include \"../../libraries/music_common/fileio.h\"\n #include \"zmusic/midiconfig.h\"\n \n-\n+#include <stdexcept>\n //==========================================================================\n //\n // OPL file played by a software OPL2 synth and streamed through the sound system"
  },
  {
    "path": "scriptmodules/ports/lzdoom.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"lzdoom\"\nrp_module_desc=\"lzdoom - DOOM source port (legacy version of GZDoom)\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/drfrag666/gzdoom/master/LICENSE\"\nrp_module_repo=\"git https://github.com/drfrag666/gzdoom 3.88b\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_lzdoom() {\n    local depends=(\n        libev-dev libfluidsynth-dev libgme-dev libsdl2-dev libmpg123-dev libsndfile1-dev zlib1g-dev libbz2-dev\n        timidity freepats cmake libopenal-dev libjpeg-dev libgl1-mesa-dev fluid-soundfont-gm\n    )\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_lzdoom() {\n    gitPullOrClone\n    if isPlatform \"arm\"; then\n        # patch the CMake build file to remove the ARMv8 options, we handle `gcc`'s CPU flags ourselves\n        applyPatch \"$md_data/01_remove_cmake_arm_options.diff\"\n        # patch the 21.06 version of LZMA-SDK to disable the CRC32 ARMv8 intrinsics forced for ARM CPUs\n        applyPatch \"$md_data/02_lzma_sdk_dont_force_arm_crc32.diff\"\n    fi\n    applyPatch \"$md_data/03_extra_includes.diff\"\n}\n\nfunction build_lzdoom() {\n    rm -rf release\n    mkdir -p release\n    cd release\n    local params=(-DNO_GTK=On -DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DPK3_QUIET_ZIPDIR=ON -DCMAKE_BUILD_TYPE=Release)\n    # Note: `-funsafe-math-optimizations` should be avoided, see: https://forum.zdoom.org/viewtopic.php?f=7&t=57781\n    cmake \"${params[@]}\" ..\n    make\n    md_ret_require=\"$md_build/release/$md_id\"\n}\n\nfunction install_lzdoom() {\n    md_ret_files=(\n        'release/brightmaps.pk3'\n        'release/lzdoom'\n        'release/lzdoom.pk3'\n        'release/lights.pk3'\n        'release/game_support.pk3'\n        'release/soundfonts'\n        'README.md'\n    )\n}\n\nfunction add_games_lzdoom() {\n    local params=(\"+fullscreen 1\")\n    local launcher_prefix=\"DOOMWADDIR=$romdir/ports/doom\"\n\n    if isPlatform \"mesa\" || isPlatform \"gl\"; then\n        params+=(\"+vid_renderer 1\")\n    elif isPlatform \"gles\"; then\n        params+=(\"+vid_renderer 0\")\n    fi\n\n    # FluidSynth is too memory/CPU intensive\n    if isPlatform \"arm\"; then\n        params+=(\"+snd_mididevice -3\")\n    fi\n\n    if isPlatform \"kms\"; then\n        params+=(\"+vid_vsync 1\" \"-width %XRES%\" \"-height %YRES%\")\n    fi\n\n    _add_games_lr-prboom \"$launcher_prefix $md_inst/$md_id -iwad %ROM% ${params[*]}\"\n}\n\nfunction configure_lzdoom() {\n    mkRomDir \"ports/doom\"\n\n    moveConfigDir \"$home/.config/$md_id\" \"$md_conf_root/doom\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_lr-prboom\n\n    add_games_${md_id}\n}\n"
  },
  {
    "path": "scriptmodules/ports/micropolis.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"micropolis\"\nrp_module_desc=\"Micropolis - Open Source City Building Game\"\nrp_module_licence=\"GPL https://raw.githubusercontent.com/SimHacker/micropolis/wiki/License.md\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction depends_micropolis() {\n    ! isPlatform \"x11\" getDepends xorg matchbox-window-manager\n}\n\nfunction install_bin_micropolis() {\n    aptInstall micropolis\n}\n\nfunction remove_micropolis() {\n    aptRemove micropolis\n}\n\nfunction configure_micropolis() {\n    local binary=\"/usr/games/micropolis\"\n    ! isPlatform \"x11\" && binary=\"XINIT-WMC:/usr/games/micropolis\"\n\n    addPort \"$md_id\" \"micropolis\" \"Micropolis\" \"$binary\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/minecraft.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"minecraft\"\nrp_module_desc=\"Minecraft - Pi Edition\"\nrp_module_licence=\"PROP\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_minecraft() {\n    getDepends xorg matchbox-window-manager\n}\n\nfunction install_bin_minecraft() {\n    [[ -f \"$md_inst/minecraft-pi\" ]] && rm -rf \"$md_inst/\"*\n    aptInstall minecraft-pi\n}\n\nfunction remove_minecraft() {\n    aptRemove minecraft-pi\n}\n\nfunction configure_minecraft() {\n    addPort \"$md_id\" \"minecraft\" \"Minecraft\" \"XINIT-WM:/usr/bin/minecraft-pi\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/mysticmine.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mysticmine\"\nrp_module_desc=\"Mystic Mine - Rail game for up to six players on one keyboard\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/dewitters/MysticMine/master/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/dewitters/MysticMine.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!:\\$__os_debian_ver:-gt:10\"\n\nfunction depends_mysticmine() {\n    getDepends python-pyrex python-numpy python-pygame\n}\n\nfunction sources_mysticmine() {\n    gitPullOrClone\n}\n\nfunction build_mysticmine() {\n    make\n}\n\nfunction install_mysticmine() {\n    python2 setup.py install --prefix \"$md_inst\"\n}\n\nfunction configure_mysticmine() {\n    addPort \"$md_id\" \"mysticmine\" \"MysticMine\" \"pushd $md_inst; PYTHONPATH=$PYTHONPATH:${md_inst}/lib/python2.7/site-packages ./bin/MysticMine; popd\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/openblok.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"openblok\"\nrp_module_desc=\"OpenBlok: A Block Dropping Game\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/mmatyas/openblok/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/mmatyas/openblok.git v0.8.7\"\nrp_module_section=\"exp\"\nrp_module_flags=\"\"\n\nfunction depends_openblok() {\n    getDepends cmake libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev gettext\n}\n\nfunction sources_openblok() {\n    gitPullOrClone\n}\n\nfunction build_openblok() {\n    cmake -DCMAKE_BUILD_TYPE=Release -DINSTALL_PORTABLE=ON -DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DENABLE_MP3=OFF\n    make\n    md_ret_require=\"$md_build/src/openblok\"\n}\n\nfunction install_openblok() {\n    make install/strip\n}\n\nfunction configure_openblok() {\n    moveConfigDir \"$home/.local/share/openblok\" \"$md_conf_root/openblok\"\n    addPort \"$md_id\" \"openblok\" \"OpenBlok\" \"$md_inst/openblok\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/openbor.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"openbor\"\nrp_module_desc=\"OpenBOR - Beat 'em Up Game Engine\"\nrp_module_help=\"OpenBOR games need to be extracted to function properly. Place your pak files in $romdir/ports/openbor and then run $rootdir/ports/openbor/extract.sh. When the script is done, your original pak files will be found in $romdir/ports/openbor/originals and can be deleted.\"\nrp_module_licence=\"BSD https://raw.githubusercontent.com/rofl0r/openbor/master/LICENSE\"\nrp_module_repo=\"git https://github.com/rofl0r/openbor.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl1 !mali !x11\"\n\nfunction depends_openbor() {\n    getDepends libsdl1.2-dev libsdl-gfx1.2-dev libogg-dev libvorbisidec-dev libvorbis-dev libpng-dev zlib1g-dev\n}\n\nfunction sources_openbor() {\n    gitPullOrClone\n}\n\nfunction build_openbor() {\n    local params=()\n    ! isPlatform \"x11\" && params+=(NO_GL=1)\n    make clean\n    make \"${params[@]}\"\n    cd \"$md_build/tools/borpak/\"\n    ./build-linux.sh\n    md_ret_require=\"$md_build/OpenBOR\"\n}\n\nfunction install_openbor() {\n    md_ret_files=(\n       'OpenBOR'\n       'tools/borpak/borpak'\n       'tools/unpack.sh'\n    )\n}\n\nfunction configure_openbor() {\n    addPort \"$md_id\" \"openbor\" \"OpenBOR - Beats of Rage Engine\" \"$md_inst/openbor.sh\"\n\n    mkRomDir \"ports/$md_id\"\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n\n    cat >\"$md_inst/openbor.sh\" << _EOF_\n#!/bin/bash\npushd \"$md_inst\"\n./OpenBOR \"\\$@\"\npopd\n_EOF_\n    chmod +x \"$md_inst/openbor.sh\"\n\n    cat >\"$md_inst/extract.sh\" <<_EOF_\n#!/bin/bash\nPORTDIR=\"$md_inst\"\nBORROMDIR=\"$romdir/ports/$md_id\"\nmkdir \\$BORROMDIR/original/\nmkdir \\$BORROMDIR/original/borpak/\nmv \\$BORROMDIR/*.pak \\$BORROMDIR/original/\ncp \\$PORTDIR/unpack.sh \\$BORROMDIR/original/\ncp \\$PORTDIR/borpak \\$BORROMDIR/original/borpak/\ncd \\$BORROMDIR/original/\nfor i in *.pak\ndo\n  CURRENTFILE=\\`basename \"\\$i\" .pak\\`\n  ./unpack.sh \"\\$i\"\n  mkdir \"\\$CURRENTFILE\"\n  mv data/ \"\\$CURRENTFILE\"/\n  mv \"\\$CURRENTFILE\"/ ../\ndone\n\necho \"Your games are extracted and ready to be played. Your originals are stored safely in $BORROMDIR/original/ but they won't be needed anymore. Everything within it can be deleted.\"\n_EOF_\n    chmod +x \"$md_inst/extract.sh\"\n\n    local dir\n    for dir in ScreenShots Logs Saves; do\n        mkUserDir \"$md_conf_root/$md_id/$dir\"\n        ln -snf \"$md_conf_root/$md_id/$dir\" \"$md_inst/$dir\"\n    done\n\n    ln -snf \"$romdir/ports/$md_id\" \"$md_inst/Paks\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/openpht.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"openpht\"\nrp_module_desc=\"OpenPHT is a community driven fork of Plex Home Theater\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RasPlex/OpenPHT/openpht-1.7/LICENSE.GPL\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!arm\"\n\nfunction depends_openpht() {\n    getDepends pulseaudio-utils\n    addUdevInputRules\n}\n\nfunction install_bin_openpht() {\n    local version=\"1.7.1.137-b604995c\"\n    local package=\"openpht_${version}-${__os_codename}_amd64.deb\"\n    local url=\"https://github.com/RasPlex/OpenPHT/releases/download/v$version/$package\"\n\n    local temp=\"$(mktemp -d)\"\n    download \"$url\" \"$temp/$package\"\n    if hasPackage \"apt\" \"1.1\" \"ge\"; then\n        apt install -y --allow-downgrades \"$temp/$package\"\n    else\n        # Falling back to dpkg\n        dpkg -i \"$temp/$package\"\n        apt-get -f -y install\n    fi\n    rm -rf \"$temp\"\n}\n\nfunction remove_openpht() {\n    aptRemove openpht\n}\n\nfunction configure_openpht() {\n    addPort \"openpht\" \"openpht\" \"OpenPHT\" \"pasuspender -- env AE_SINK=ALSA openpht\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/openttd.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"openttd\"\nrp_module_desc=\"Open Source Simulator Based On Transport Tycoon Deluxe\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/OpenTTD/OpenTTD/master/COPYING.md\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1 !mali\"\n\nfunction _update_hook_openttd() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage openttd && mkdir -p \"$md_inst\"\n}\n\nfunction install_bin_openttd() {\n    aptInstall openttd\n}\n\nfunction remove_openttd() {\n    aptRemove openttd\n}\n\nfunction configure_openttd() {\n    addPort \"$md_id\" \"openttd\" \"OpenTTD\" \"openttd\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    isPlatform \"dispmanx\" && setBackend \"$md_id\" \"dispmanx\"\n\n    local dir\n    for dir in .config .local/share; do\n        moveConfigDir \"$home/$dir/openttd\" \"$md_conf_root/openttd\"\n    done\n\n    moveConfigDir \"$home/.local/openttd\" \"$md_conf_root/openttd\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/opentyrian/01_fullscreen.diff",
    "content": "diff --git a/src/config.c b/src/config.c\nindex c4f4330..4c77a5d 100644\n--- a/src/config.c\n+++ b/src/config.c\n@@ -249,7 +249,7 @@ Config opentyrian_config;  // implicitly initialized\n bool load_opentyrian_config( void )\n {\n \t// defaults\n-\tfullscreen_display = -1;\n+\tfullscreen_display = 0;\n \tset_scaler_by_name(\"Scale2x\");\n \t\n \tConfig *config = &opentyrian_config;\n"
  },
  {
    "path": "scriptmodules/ports/opentyrian.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"opentyrian\"\nrp_module_desc=\"Open Tyrian - port of the DOS shoot-em-up Tyrian\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/opentyrian/opentyrian/master/COPYING\"\nrp_module_repo=\"git https://github.com/opentyrian/opentyrian.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"\"\n\nfunction depends_opentyrian() {\n    getDepends libsdl2-dev libsdl2-net-dev\n}\n\nfunction sources_opentyrian() {\n    gitPullOrClone\n    # patch to default to fullscreen\n    applyPatch \"$md_data/01_fullscreen.diff\"\n}\n\nfunction build_opentyrian() {\n    rpSwap on 512\n    make clean\n    make\n    rpSwap off\n    md_ret_require=\"$md_build/opentyrian\"\n}\n\nfunction install_opentyrian() {\n    make install prefix=\"$md_inst\"\n}\n\nfunction game_data_opentyrian() {\n    if [[ ! -d \"$romdir/ports/opentyrian/data\" ]]; then\n        cd \"$__tmpdir\"\n        # get Tyrian 2.1 (freeware game data)\n        downloadAndExtract \"$__archive_url/tyrian21.zip\" \"$romdir/ports/opentyrian/data\" -j\n        chown -R \"$__user\":\"$__group\" \"$romdir/ports/opentyrian\"\n    fi\n}\n\nfunction configure_opentyrian() {\n    addPort \"$md_id\" \"opentyrian\" \"OpenTyrian\" \"$md_inst/bin/opentyrian --data $romdir/ports/opentyrian/data\"\n\n    mkRomDir \"ports/opentyrian\"\n\n    moveConfigDir \"$home/.config/opentyrian\" \"$md_conf_root/opentyrian\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_opentyrian\n}\n"
  },
  {
    "path": "scriptmodules/ports/quake3.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"quake3\"\nrp_module_desc=\"Quake 3\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/raspberrypi/quake3/master/COPYING.txt\"\nrp_module_repo=\"git https://github.com/raspberrypi/quake3.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!all videocore\"\n\nfunction depends_quake3() {\n    getDepends libsdl1.2-dev libraspberrypi-dev\n}\n\nfunction sources_quake3() {\n    gitPullOrClone\n}\n\nfunction build_quake3() {\n    ./build_rpi_raspbian.sh\n    md_ret_require=\"$md_build/build/release-linux-arm/ioquake3.arm\"\n}\n\nfunction install_quake3() {\n    md_ret_files=(\n        'build/release-linux-arm/ioq3ded.arm'\n        'build/release-linux-arm/ioquake3.arm'\n    )\n}\n\nfunction game_data_quake3() {\n    if [[ ! -f \"$romdir/ports/quake3/pak0.pk3\" ]]; then\n        downloadAndExtract \"$__archive_url/Q3DemoPaks.zip\" \"$romdir/ports/quake3\" -j\n    fi\n    # always chown as moveConfigDir in the configure_ script would move the root owned demo files\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/quake3\"\n}\n\nfunction configure_quake3() {\n    mkRomDir \"ports/quake3\"\n    addPort \"$md_id\" \"quake3\" \"Quake III Arena\" \"LD_LIBRARY_PATH=lib $md_inst/ioquake3.arm\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    game_data_quake3\n\n    moveConfigDir \"$md_inst/baseq3\" \"$romdir/ports/quake3\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/sdlpop.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sdlpop\"\nrp_module_desc=\"SDLPoP - Port of Prince of Persia\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/NagyD/SDLPoP/master/COPYING\"\nrp_module_repo=\"git https://github.com/NagyD/SDLPoP.git master\"\nrp_module_section=\"opt\"\n\nfunction depends_sdlpop() {\n    getDepends libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev\n}\n\nfunction sources_sdlpop() {\n    gitPullOrClone\n}\n\nfunction build_sdlpop() {\n    cd src\n    make\n    md_ret_require=\"$md_build/prince\"\n}\n\nfunction install_sdlpop() {\n    md_ret_files=(\n        'prince'\n        'data'\n        'doc'\n        'COPYING'\n    )\n    cp -v \"SDLPoP.ini\" \"$md_inst/SDLPoP.ini.def\"\n    sed -i \"s/use_correct_aspect_ratio = false/use_correct_aspect_ratio = true/\" \"$md_inst/SDLPoP.ini.def\"\n}\n\nfunction configure_sdlpop() {\n    addPort \"$md_id\" \"sdlpop\" \"Prince of Persia\" \"pushd $md_inst; $md_inst/prince full; popd\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    copyDefaultConfig \"$md_inst/SDLPoP.ini.def\" \"$md_conf_root/$md_id/SDLPoP.ini\"\n    moveConfigFile \"$md_inst/SDLPoP.ini\" \"$md_conf_root/$md_id/SDLPoP.ini\"\n\n    moveConfigFile \"$md_inst/PRINCE.SAV\" \"$md_conf_root/$md_id/PRINCE.SAV\"\n    moveConfigFile \"$md_inst/QUICKSAVE.SAV\" \"$md_conf_root/$md_id/QUICKSAVE.SAV\"\n    moveConfigFile \"$md_inst/SDLPoP.cfg\" \"$md_conf_root/$md_id/SDLPoP.cfg\"\n\n    chown -R \"$__user\":\"$__group\" \"$md_conf_root/$md_id\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/smw.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"smw\"\nrp_module_desc=\"Super Mario War - A fan-made multiplayer Super Mario Bros. style deathmatch game\"\nrp_module_licence=\"GPL2 https://smwstuff.net\"\nrp_module_repo=\"git https://github.com/mmatyas/supermariowar master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_smw() {\n    getDepends cmake libsdl2-dev libsdl2-mixer-dev libsdl2-image-dev zlib1g-dev\n}\n\nfunction sources_smw() {\n    gitPullOrClone\n}\n\nfunction build_smw() {\n    local params=(-DUSE_SDL2_LIBS=ON -DSMW_INSTALL_PORTABLE=ON)\n    isPlatform \"gles2\" && params+=(-DSDL2_FORCE_GLES=ON)\n    rm -fr build\n    mkdir -p build && cd build\n    cmake .. \"${params[@]}\"\n    make smw\n    md_ret_require=\"$md_build/build/smw\"\n}\n\nfunction install_smw() {\n    md_ret_files=(\n        \"build/smw\"\n        \"data\"\n        \"docs\"\n        \"README.md\"\n        \"CREDITS\"\n    )\n}\n\nfunction configure_smw() {\n    addPort \"$md_id\" \"smw\" \"Super Mario War\" \"$md_inst/smw\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    moveConfigDir \"$home/.smw\" \"$md_conf_root/smw\"\n    # try to migrate existing settings to the new conf folder\n    if [[ -f \"$md_conf_root/smw/.smw.options.bin\" ]] ; then\n         mv \"$md_conf_root/smw/.smw.options.bin\" \"$md_conf_root/smw/options.bin\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/ports/solarus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"solarus\"\nrp_module_desc=\"Solarus - A lightweight, free and open-source game engine for Action-RPGs\"\nrp_module_help=\"Copy your Solarus quests (games) to $romdir/solarus\"\nrp_module_licence=\"GPL3 https://gitlab.com/solarus-games/solarus/-/raw/dev/license\"\nrp_module_repo=\"git https://gitlab.com/solarus-games/solarus.git :_get_branch_solarus\"\nrp_module_section=\"opt\"\n\nfunction _get_branch_solarus() {\n    local branch=\"release-2.0.1\"\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        branch=\"release-1.6.5\"\n    fi\n    echo \"$branch\"\n}\n\nfunction _options_cfg_file_solarus() {\n    echo \"$configdir/solarus/options.cfg\"\n}\n\nfunction depends_solarus() {\n    # ref: https://gitlab.com/solarus-games/solarus/blob/dev/compilation.md\n    local depends=(\n        cmake pkg-config\n        libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev\n        libopenal-dev libvorbis-dev libogg-dev\n        libmodplug-dev libphysfs-dev libglm-dev\n        libluajit-5.1-dev\n    )\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_solarus() {\n    gitPullOrClone\n}\n\nfunction build_solarus() {\n    local params=(\n        -DSOLARUS_GUI=OFF -DSOLARUS_TESTS=OFF -DSOLARUS_FILE_LOGGING=OFF\n        -DSOLARUS_LIBRARY_INSTALL_DESTINATION=\"$md_inst/lib\"\n        -DCMAKE_INSTALL_PREFIX=\"$md_inst\"\n        -DCMAKE_INSTALL_RPATH=\"$md_inst/lib\"\n        -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE\n    )\n    isPlatform \"gles\" && params+=(-DSOLARUS_GL_ES=ON)\n    rm -rf build\n    mkdir build\n    cd build\n    cmake \"${params[@]}\" ..\n    make\n    # solarus v2.x moved the executable to build/cli\n    local exe_path=\"$md_build/build\"\n    [[ -d \"$exe_path/cli\" ]] && exe_path=\"$exe_path/cli\"\n    md_ret_require=(\n        \"$exe_path/solarus-run\"\n    )\n}\n\nfunction install_solarus() {\n    cd build\n    make install/strip\n}\n\nfunction configure_solarus() {\n    setConfigRoot \"\"\n    addEmulator 1 \"$md_id\" \"solarus\" \"$md_inst/solarus.sh %ROM%\"\n    addSystem \"solarus\"\n    moveConfigDir \"$home/.solarus\" \"$configdir/solarus\"\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # ensure rom dir exists\n    mkRomDir \"solarus\"\n\n    # create launcher for Solarus that:\n    # * starts in fullscreen mode\n    # * disables mouse cursor, the JACK driver in OpenAL and the Lua console\n    # * configures the joypad deadzone and quit combo options\n    # * preloads the legacy videocore GLES2 driver (if necessary)\n    cat > \"$md_inst/solarus.sh\" << _EOF_\n#!/usr/bin/env bash\nexport ALSOFT_DRIVERS=\"-jack,\"\nARGS=(\"-fullscreen=yes\" \"-cursor-visible=no\" \"-lua-console=no\")\n[[ -f \"$(_options_cfg_file_solarus)\" ]] && source \"$(_options_cfg_file_solarus)\"\n[[ -n \"\\$JOYPAD_DEADZONE\" ]] && ARGS+=(\"-joypad-deadzone=\\$JOYPAD_DEADZONE\")\n[[ -n \"\\$QUIT_COMBO\" ]] && ARGS+=(\"-quit-combo=\\$QUIT_COMBO\")\nif $(isPlatform \"videocore\" && echo true || echo false); then\n  if [[ -f /opt/vc/lib/libbrcmGLESv2.so ]]; then\n    export LD_PRELOAD=\"/opt/vc/lib/libbrcmGLESv2.so\"\n  fi\nfi\nexec \"$md_inst\"/bin/solarus-run \"\\${ARGS[@]}\" \"\\$@\"\n_EOF_\n    chmod +x \"$md_inst/solarus.sh\"\n}\n\nfunction gui_solarus() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local joypad_deadzone\n    local quit_combo\n\n    # initialise options config file\n    iniConfig \"=\" \"\\\"\" \"$(_options_cfg_file_solarus)\"\n\n    # start the menu gui\n    default=\"D\"\n    while true; do\n        # read current options\n        iniGet \"JOYPAD_DEADZONE\" && joypad_deadzone=\"$ini_value\"\n        iniGet \"QUIT_COMBO\" && quit_combo=\"$ini_value\"\n\n        # create menu options\n        options=(\n            D \"Set joypad axis deadzone (${joypad_deadzone:-default})\"\n            Q \"Set joypad quit buttons combo (${quit_combo:-unset})\"\n        )\n\n        # show main menu\n        cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Choose an option\" 16 60 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        case \"$choice\" in\n            D)\n                cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter a joypad axis deadzone value between 0-32767, higher is less sensitive (leave BLANK to use engine default)\" 10 65)\n                choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                if [[ $? -eq 0 ]]; then\n                    if [[ -n \"$choice\" ]]; then\n                        iniSet \"JOYPAD_DEADZONE\" \"$choice\"\n                    else\n                        iniDel \"JOYPAD_DEADZONE\"\n                    fi\n                    chown \"$__user\":\"$__group\" \"$(_options_cfg_file_solarus)\"\n                fi\n                ;;\n            Q)\n                cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter joypad button numbers to use for quitting separated by '+' signs (leave BLANK to unset)\\n\\nTip: use 'jstest' to find button numbers for your joypad\" 12 65)\n                choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                if [[ $? -eq 0 ]]; then\n                    if [[ -n \"$choice\" ]]; then\n                        iniSet \"QUIT_COMBO\" \"$choice\"\n                    else\n                        iniDel \"QUIT_COMBO\"\n                    fi\n                    chown \"$__user\":\"$__group\" \"$(_options_cfg_file_solarus)\"\n                fi\n                ;;\n            *)\n                break\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/ports/splitwolf.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"splitwolf\"\nrp_module_desc=\"SplitWolf - 2-4 player split-screen Wolfenstein 3D / Spear of Destiny\"\nrp_module_help=\"Game File Extension: .wl6, .sod, .sd2, .sd3\\n\\nCopy your game files to $romdir/ports/wolf3d/\\n\\nIf you add new game files, run: sudo ~/RetroPie-Setup/retropie_packages.sh splitwolf configure\"\nrp_module_licence=\"NONCOM https://bitbucket.org/linuxwolf6/splitwolf/raw/scrubbed/license-mame.txt\"\nrp_module_repo=\"git https://bitbucket.org/linuxwolf6/splitwolf.git scrubbed\"\nrp_module_section=\"exp\"\n\nfunction depends_splitwolf() {\n    getDepends libsdl2-dev libsdl2-mixer-dev\n}\n\nfunction sources_splitwolf() {\n    gitPullOrClone\n}\n\nfunction _get_opts_splitwolf() {\n    echo 'splitwolf-wolf3d VERSION_WOLF3D_SHAREWARE=y' # shareware v1.4\n    echo 'splitwolf-wolf3d_apogee VERSION_WOLF3D_APOGEE=y' # 3d realms / apogee v1.4 full\n    echo 'splitwolf-wolf3d_full VERSION_WOLF3D=y' # gt / id / activision v1.4 full\n    echo 'splitwolf-sod VERSION_SPEAR=y' # spear of destiny\n    echo 'splitwolf-sodmp VERSION_SPEAR_MP=y' # spear of destiny mission packs\n    echo 'splitwolf-spear_demo VERSION_SPEAR_DEMO=y' # spear of destiny\n}\n\nfunction game_data_splitwolf() {\n    if [[ ! -d \"$md_inst/bin/lwmp\" ]]; then\n        # Get game assets\n        downloadAndExtract \"https://bitbucket.org/linuxwolf6/splitwolf/downloads/lwmp.zip\" \"$md_inst/bin/\"\n    fi\n}\n\nfunction add_games_splitwolf() {\n    declare -A games_wolf4sdl=(\n        ['vswap.wl1']=\"Splitwolf - Wolf 3D Demo\"\n        ['vswap.wl6']=\"Splitwolf - Wolf 3D\"\n        ['vswap.sod']=\"Splitwolf - Spear of Destiny Ep 1\"\n        ['vswap.sd2']=\"Splitwolf - Spear of Destiny Ep 2\"\n        ['vswap.sd3']=\"Splitwolf - Spear of Destiny Ep 3\"\n        ['vswap.sdm']=\"Splitwolf - Spear of Destiny Demo\"\n    )\n\n    add_ports_wolf4sdl \"$md_inst/bin/splitwolf.sh %ROM%\" \"splitwolf\"\n}\n\n\nfunction build_splitwolf() {\n    mkdir -p \"bin\"\n    local opt\n    while read -r opt; do\n        local bin=\"${opt%% *}\"\n        local defs=\"${opt#* }\"\n        make clean\n        make \"$defs\" DATADIR=\"$romdir/ports/wolf3d/\"\n        mv \"$bin\" \"bin/$bin\"\n        md_ret_require+=(\"bin/$bin\")\n    done < <(_get_opts_splitwolf)\n}\n\nfunction install_splitwolf() {\n    cp \"$md_build/gamecontrollerdb.txt\" \"$md_build/bin/\"\n    md_ret_files=('bin')\n}\n\nfunction configure_splitwolf() {\n    local game\n\n    mkRomDir \"ports/wolf3d\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        game_data_splitwolf\n        game_data_wolf4sdl\n        cat > \"$md_inst/bin/splitwolf.sh\" << _EOF_\n#!/bin/bash\n\nfunction get_md5sum() {\n    local file=\"\\$1\"\n\n    [[ -n \"\\$file\" ]] && md5sum \"\\$file\" 2>/dev/null | cut -d\" \" -f1\n}\n\nfunction launch_splitwolf() {\n    local wad_file=\"\\$1\"\n    declare -A game_checksums=(\n        ['6efa079414b817c97db779cecfb081c9']=\"splitwolf-wolf3d\"\n        ['a6d901dfb455dfac96db5e4705837cdb']=\"splitwolf-wolf3d_apogee\"\n        ['b8ff4997461bafa5ef2a94c11f9de001']=\"splitwolf-wolf3d_full\"\n        ['b1dac0a8786c7cdbb09331a4eba00652']=\"splitwolf-sod\"\n        ['25d92ac0ba012a1e9335c747eb4ab177']=\"splitwolf-sodmp --mission 2\"\n        ['94aeef7980ef640c448087f92be16d83']=\"splitwolf-sodmp --mission 3\"\n        ['35afda760bea840b547d686a930322dc']=\"splitwolf-spear_demo\"\n    )\n        if [[ \"\\${game_checksums[\\$(get_md5sum \\$wad_file)]}\" ]] 2>/dev/null; then\n            $md_inst/bin/\\${game_checksums[\\$(get_md5sum \\$wad_file)]} --splitdatadir $md_inst/bin/lwmp/ --split 2 --splitlayout 2x1\n        else\n            echo \"Error: \\$wad_file (md5: \\$(get_md5sum \\$wad_file)) is not a supported version\"\n        fi\n}\n\nlaunch_splitwolf \"\\$1\"\n_EOF_\n        chmod +x \"$md_inst/bin/splitwolf.sh\"\n    fi\n\n    add_games_splitwolf\n\n    moveConfigDir \"$home/.splitwolf\" \"$md_conf_root/splitwolf\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/srb2/001-cmake-libfind.diff",
    "content": "diff --git a/cmake/Modules/Findlibopenmpt.cmake b/cmake/Modules/Findlibopenmpt.cmake\nindex 96cc310..d509c25 100644\n--- a/cmake/Modules/Findlibopenmpt.cmake\n+++ b/cmake/Modules/Findlibopenmpt.cmake\n@@ -26,7 +26,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(libopenmpt\n     REQUIRED_VARS libopenmpt_LIBRARY libopenmpt_INCLUDE_DIR)\n \n if(libopenmpt_FOUND AND NOT TARGET openmpt)\n-\tadd_library(openmpt UNKNOWN IMPORTED)\n+\tadd_library(openmpt UNKNOWN IMPORTED GLOBAL)\n \tset_target_properties(\n \t\topenmpt\n \t\tPROPERTIES\ndiff --git a/cmake/Modules/Findminiupnpc.cmake b/cmake/Modules/Findminiupnpc.cmake\nindex f4931ad..eb12927 100644\n--- a/cmake/Modules/Findminiupnpc.cmake\n+++ b/cmake/Modules/Findminiupnpc.cmake\n@@ -26,7 +26,7 @@ FIND_PACKAGE_HANDLE_STANDARD_ARGS(miniupnpc\n     REQUIRED_VARS libminiupnpc_LIBRARY libminiupnpc_INCLUDE_DIR)\n \n if(miniupnpc_FOUND AND NOT TARGET miniupnpc)\n-\tadd_library(miniupnpc UNKNOWN IMPORTED)\n+\tadd_library(miniupnpc UNKNOWN IMPORTED GLOBAL)\n \tset_target_properties(\n \t\tminiupnpc\n \t\tPROPERTIES\n"
  },
  {
    "path": "scriptmodules/ports/srb2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"srb2\"\nrp_module_desc=\"Sonic Robo Blast 2 - 3D Sonic the Hedgehog fan-game built using a modified version of the Doom Legacy source port of Doom\"\nrp_module_licence=\"GPL2 https://git.do.srb2.org/STJr/SRB2/-/raw/next/LICENSE?ref_type=heads\"\nrp_module_repo=\"git https://git.do.srb2.org/STJr/SRB2 :_get_branch_srb2\"\nrp_module_section=\"exp\"\n\nfunction _version_srb2() {\n    echo \"2.2.15\"\n}\n\nfunction _get_branch_srb2() {\n    echo \"SRB2_release_$(_version_srb2)\"\n}\n\nfunction depends_srb2() {\n    getDepends cmake libsdl2-dev libsdl2-mixer-dev libgme-dev libpng-dev libcurl4-openssl-dev libopenmpt-dev\n}\n\nfunction sources_srb2() {\n    gitPullOrClone\n    local ver=\"$(_version_srb2)\"\n    ver=${ver//\\./}\n    downloadAndExtract \"https://github.com/STJr/SRB2/releases/download/SRB2_release_$(_version_srb2)/SRB2-v${ver}-Full.zip\" \"$md_build/assets\"\n    # patch detection for CMake < 3.18\n    if hasPackage cmake 3.18 lt; then\n        applyPatch \"$md_data/001-cmake-libfind.diff\"\n    fi\n}\n\nfunction build_srb2() {\n    rm -fr build && mkdir build\n    cd build\n\n    cmake .. -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=\"$md_inst\" -DSRB2_SDL2_EXE_NAME=srb2\n    make\n    md_ret_require=\"$md_build/build/bin/srb2\"\n}\n\nfunction install_srb2() {\n    md_ret_files=(\n        'build/bin/srb2'\n        'assets/characters.pk3'\n        'assets/srb2.pk3'\n        'assets/music.pk3'\n        'assets/zones.pk3'\n        'assets/README.txt'\n        'assets/LICENSE.txt'\n    )\n}\n\nfunction configure_srb2() {\n    addPort \"$md_id\" \"srb2\" \"Sonic Robo Blast 2\" \"pushd $md_inst; ./srb2; popd\"\n\n    moveConfigDir \"$home/.srb2\"  \"$md_conf_root/$md_id\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/steamlink.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"steamlink\"\nrp_module_desc=\"Steam Link for Raspberry Pi 3 or later\"\nrp_module_licence=\"PROP https://steamcommunity.com/app/353380/discussions/0/1743353164093954254/\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all rpi3 rpi4 rpi5\"\nrp_module_help=\"Stream games from your computer with Steam\"\n\nfunction depends_steamlink() {\n    getDepends libxkbcommon-x11-0 libinput10 libpulse0 libx11-6 libx11-xcb1 cec-utils openssl\n}\n\nfunction install_bin_steamlink() {\n    aptInstall steamlink\n}\n\nfunction remove_steamlink() {\n    aptRemove steamlink\n}\n\nfunction configure_steamlink() {\n    local sl_dir=\"$home/.local/share/SteamLink\"\n    local valve_dir=\"$home/.local/share/Valve Corporation\"\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        mkUserDir \"$sl_dir\"\n        mkUserDir \"$valve_dir\"\n        mkUserDir \"$valve_dir/SteamLink\"\n        mkUserDir \"$md_conf_root/$md_id\"\n\n        # create optional streaming_args.txt for user modification\n        touch \"$valve_dir/SteamLink/streaming_args.txt\"\n        chown \"$__user\":\"$__group\" \"$valve_dir/SteamLink/streaming_args.txt\"\n        moveConfigFile \"$valve_dir/SteamLink/streaming_args.txt\" \"$md_conf_root/$md_id/streaming_args.txt\"\n    fi\n\n    addPort \"$md_id\" \"steamlink\" \"Steam Link\" \"steamlink\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/supertux.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"supertux\"\nrp_module_desc=\"SuperTux 2d scrolling platform\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/SuperTux/supertux/master/LICENSE.txt\"\nrp_module_section=\"opt\"\nrp_module_flags=\"!mali\"\n\nfunction _update_hook_supertux() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage supertux && mkdir -p \"$md_inst\"\n}\n\nfunction install_bin_supertux() {\n    aptInstall supertux\n}\n\nfunction remove_supertux() {\n    aptRemove supertux supertux-data\n}\n\nfunction configure_supertux() {\n    addPort \"$md_id\" \"supertux\" \"SuperTux\" \"supertux2\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/tyrquake.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"tyrquake\"\nrp_module_desc=\"Quake 1 engine - TyrQuake port\"\nrp_module_licence=\"GPL2 https://disenchant.net/git/tyrquake.git/plain/gnu.txt\"\nrp_module_repo=\"git https://github.com/RetroPie/tyrquake.git master\"\nrp_module_section=\"opt\"\n\nfunction depends_tyrquake() {\n    local depends=(libsdl2-dev)\n    if isPlatform \"gl\" || isPlatform \"mesa\"; then\n        depends+=(libgl1-mesa-dev)\n    fi\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_tyrquake() {\n    gitPullOrClone\n}\n\nfunction build_tyrquake() {\n    local params=(USE_SDL=Y USE_XF86DGA=N)\n    make clean\n    make \"${params[@]}\" bin/tyr-quake bin/tyr-glquake\n    md_ret_require=(\n        \"$md_build/bin/tyr-quake\"\n        \"$md_build/bin/tyr-glquake\"\n    )\n}\n\nfunction install_tyrquake() {\n    md_ret_files=(\n        'changelog.txt'\n        'readme.txt'\n        'readme-id.txt'\n        'gnu.txt'\n        'bin'\n    )\n}\n\nfunction add_games_tyrquake() {\n    local params=(\"-basedir $romdir/ports/quake\" \"-game %QUAKEDIR%\")\n    local binary=\"$md_inst/bin/tyr-quake\"\n\n    isPlatform \"kms\" && params+=(\"-width %XRES%\" \"-height %YRES%\" \"+set vid_vsync 2\")\n    if isPlatform \"gl\" || isPlatform \"mesa\"; then\n        binary=\"$md_inst/bin/tyr-glquake\"\n    fi\n\n    _add_games_lr-tyrquake \"$binary ${params[*]}\"\n}\n\nfunction configure_tyrquake() {\n    mkRomDir \"ports/quake\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_lr-tyrquake\n\n    add_games_tyrquake\n\n    moveConfigDir \"$home/.tyrquake\" \"$md_conf_root/quake/tyrquake\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/uqm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"uqm\"\nrp_module_desc=\"The Ur-Quan Masters (Port of DOS game Star Control 2)\"\nrp_module_licence=\"GPL https://sourceforce.net/p/sc2/uqm/ci/master/tree/sc2/COPYING?format=raw\"\nrp_module_repo=\"file :_get_archive_uqm\"\nrp_module_section=\"exp\"\n\nfunction _get_ver_uqm() {\n    echo \"0.8.0\"\n}\n\nfunction _update_hook_uqm() {\n    # to show as installed in retropie-setup 4.x\n    hasPackage uqm && mkdir -p \"$md_inst\"\n}\n\nfunction _get_archive_uqm() {\n    echo \"$__archive_url/uqm-$(_get_ver_uqm)-src.tgz\"\n}\n\nfunction depends_uqm() {\n    getDepends libsdl2-dev libogg-dev libvorbis-dev libpng-dev zlib1g-dev\n}\n\nfunction sources_uqm() {\n    downloadAndExtract \"$(rp_resolveRepoParam \"$md_repo_url\")\" \"$md_build\" --strip-components 1\n    local packages=\"$md_build/content/packages\"\n    mkdir -p \"$packages\"\n    local addons=\"$md_build/content/addons\"\n    mkdir -p \"$addons\"\n    local ver=\"$(_get_ver_uqm)\"\n    download \"$__archive_url/uqm-${ver}-content.uqm\" \"$packages\"\n    download \"$__archive_url/uqm-${ver}-voice.uqm\" \"$addons\"\n    download \"$__archive_url/uqm-${ver}-3domusic.uqm\" \"$addons\"\n}\n\nfunction build_uqm() {\n    ./build.sh uqm clean\n    echo \"\\n\" | CHOICE_debug_VALUE=\"nodebug\" INPUT_install_prefix_VALUE=\"$md_inst\" ./build.sh uqm config\n    ./build.sh uqm\n    md_ret_require=\"$md_build/src/uqm\"\n}\n\nfunction install_uqm() {\n    ./build.sh uqm install\n}\n\nfunction configure_uqm() {\n    addPort \"$md_id\" \"uqm\" \"Ur-quan Masters\" \"$md_inst/bin/uqm -f\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    moveConfigDir \"$home/.uqm\" \"$md_conf_root/uqm\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/vvvvvv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"vvvvvv\"\nrp_module_desc=\"VVVVVV - 2D puzzle game by Terry Cavanagh\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/TerryCavanagh/VVVVVV/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/TerryCavanagh/VVVVVV master 39abcfa8\"\nrp_module_help=\"Copy data.zip from a purchased or Make and Play edition of VVVVVV to $romdir/ports/vvvvvv\"\nrp_module_section=\"exp\"\n\nfunction depends_vvvvvv() {\n    getDepends cmake libsdl2-dev libsdl2-mixer-dev\n}\n\nfunction sources_vvvvvv() {\n    gitPullOrClone\n    # default to fullscreen\n    sed -i \"s/fullscreen = false/fullscreen = true/\" \"$md_build/desktop_version/src/Game.cpp\"\n}\n\nfunction build_vvvvvv() {\n    cmake desktop_version\n    rpSwap on 1500\n    make clean\n    make\n    rpSwap off\n    md_ret_require=\"$md_build/VVVVVV\"\n}\n\nfunction install_vvvvvv() {\n    md_ret_files=(\n        'LICENSE.md'\n        'VVVVVV'\n    )\n}\n\nfunction configure_vvvvvv() {\n\n    addPort \"$md_id\" \"vvvvvv\" \"VVVVVV\" \"$md_inst/VVVVVV\"\n    local file=\"$romdir/ports/VVVVVV.sh\"\n    # add a check to launch script - if the data file is not found, inform user\n    cat >\"$file\" << _EOF_\n#!/bin/bash\nif [[ ! -f \"$romdir/ports/vvvvvv/data.zip\" ]]; then\n    dialog --no-cancel --pause \"The data.zip file is missing. Please ensure it is placed in $romdir/ports/vvvvvv/.\" 22 76 15\nelse\n    \"$rootdir/supplementary/runcommand/runcommand.sh\" 0 _PORT_ vvvvvv \"$md_inst/VVVVVV\"\nfi\n_EOF_\n    chown \"$__user\":\"$__group\" \"$file\"\n    chmod +x \"$file\"\n\n    [[ \"$md_mode\" != \"install\" ]] && return\n\n    moveConfigDir \"$home/.local/share/VVVVVV\" \"$md_conf_root/vvvvvv\"\n\n    mkUserDir \"$romdir/ports/$md_id\"\n    # symlink game data\n    ln -snf \"$romdir/ports/$md_id/data.zip\" \"$md_inst/data.zip\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/wolf4sdl.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"wolf4sdl\"\nrp_module_desc=\"Wolf4SDL - port of Wolfenstein 3D / Spear of Destiny engine\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/AryanWolf3D/Wolf4SDL/master/license-gpl.txt\"\nrp_module_repo=\"git https://github.com/AryanWolf3D/Wolf4SDL.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_wolf4sdl() {\n    getDepends libsdl2-dev libsdl2-mixer-dev rename\n}\n\nfunction sources_wolf4sdl() {\n    gitPullOrClone\n}\n\nfunction _get_opts_wolf4sdl() {\n    echo 'wolf4sdl-sw-v14 -DCARMACIZED -DUPLOAD' # shareware v1.4\n    echo 'wolf4sdl-3dr-v14 -DCARMACIZED' # 3d realms / apogee v1.4 full\n    echo 'wolf4sdl-gt-v14 -DCARMACIZED -DGOODTIMES' # gt / id / activision v1.4 full\n    echo 'wolf4sdl-spear -DCARMACIZED -DGOODTIMES -DSPEAR' # spear of destiny\n    echo 'wolf4sdl-spear-sw -DCARMACIZED -DSPEARDEMO -DSPEAR' # spear of destiny demo\n}\n\nfunction add_games_wolf4sdl() {\n    declare -A -g games_wolf4sdl=(\n        ['vswap.wl1']=\"Wolfenstein 3D demo\"\n        ['vswap.wl6']=\"Wolfenstein 3D\"\n        ['vswap.sd1']=\"Wolfenstein 3D - Spear of Destiny Ep 1\"\n        ['vswap.sd2']=\"Wolfenstein 3D - Spear of Destiny Ep 2\"\n        ['vswap.sd3']=\"Wolfenstein 3D - Spear of Destiny Ep 3\"\n        ['vswap.sdm']=\"Wolfenstein 3D - Spear of Destiny Demo\"\n    )\n\n    add_ports_wolf4sdl \"$md_inst/bin/wolf4sdl.sh %ROM%\" \"wolf3d\"\n}\n\nfunction add_ports_wolf4sdl() {\n    local port=\"$2\"\n    local cmd=\"$1\"\n    local game\n    local wad\n\n    for game in \"${!games_wolf4sdl[@]}\"; do\n        wad=\"$romdir/ports/wolf3d/$game\"\n        if [[ -f \"$wad\" ]]; then\n            addPort \"$md_id\" \"$port\" \"${games_wolf4sdl[$game]}\" \"$cmd\" \"$wad\"\n        fi\n    done\n}\n\nfunction build_wolf4sdl() {\n    mkdir -p \"bin\"\n    local opt\n    while read -r opt; do\n        local bin=\"${opt%% *}\"\n        local defs=\"${opt#* }\"\n        make clean\n        CFLAGS+=\" -DVERSIONALREADYCHOSEN -DGPL $defs\" make\n        mv wolf4sdl \"bin/$bin\"\n        md_ret_require+=(\"bin/$bin\")\n    done < <(_get_opts_wolf4sdl)\n}\n\nfunction install_wolf4sdl() {\n    mkdir -p \"$md_inst/share/man\"\n    cp -Rv \"$md_build/man6\" \"$md_inst/share/man/\"\n    md_ret_files=('bin')\n}\n\nfunction game_data_wolf4sdl() {\n    pushd \"$romdir/ports/wolf3d\"\n    rename 'y/A-Z/a-z/' *\n    popd\n    if [[ ! -f \"$romdir/ports/wolf3d/vswap.wl6\" && ! -f \"$romdir/ports/wolf3d/vswap.wl1\" ]]; then\n        cd \"$__tmpdir\"\n        # Get shareware game data\n        downloadAndExtract \"http://maniacsvault.net/ecwolf/files/shareware/wolf3d14.zip\" \"$romdir/ports/wolf3d\" -j -LL\n    fi\n    if [[ ! -f \"$romdir/ports/wolf3d/vswap.sdm\" && ! -f \"$romdir/ports/wolf3d/vswap.sod\" ]]; then\n        cd \"$__tmpdir\"\n        # Get shareware game data\n        downloadAndExtract \"http://maniacsvault.net/ecwolf/files/shareware/soddemo.zip\" \"$romdir/ports/wolf3d\" -j -LL\n    fi\n\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/wolf3d\"\n}\n\nfunction configure_wolf4sdl() {\n    local game\n\n    mkRomDir \"ports/wolf3d\"\n\n    # remove obsolete emulator entries\n    while read game; do\n        delEmulator \"${game%% *}\" \"wolf3d\"\n    done < <(_get_opts_wolf4sdl; echo -e \"wolf4sdl-spear2\\nwolf4sdl-spear3\")\n\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        game_data_wolf4sdl\n        cat > \"$md_inst/bin/wolf4sdl.sh\" << _EOF_\n#!/bin/bash\n\nfunction get_md5sum() {\n    local file=\"\\$1\"\n\n    [[ -n \"\\$file\" ]] && md5sum \"\\$file\" 2>/dev/null | cut -d\" \" -f1\n}\n\nfunction launch_wolf4sdl() {\n    local wad_file=\"\\$1\"\n    declare -A game_checksums=(\n        ['6efa079414b817c97db779cecfb081c9']=\"wolf4sdl-sw-v14\"\n        ['a6d901dfb455dfac96db5e4705837cdb']=\"wolf4sdl-3dr-v14\"\n        ['b8ff4997461bafa5ef2a94c11f9de001']=\"wolf4sdl-gt-v14\"\n        ['b1dac0a8786c7cdbb09331a4eba00652']=\"wolf4sdl-spear --mission 1\"\n        ['25d92ac0ba012a1e9335c747eb4ab177']=\"wolf4sdl-spear --mission 2\"\n        ['94aeef7980ef640c448087f92be16d83']=\"wolf4sdl-spear --mission 3\"\n        ['e3e87518f51414872c454b7d72a45af6']=\"wolf4sdl-spear --mission 3\"\n        ['35afda760bea840b547d686a930322dc']=\"wolf4sdl-spear-sw\"\n    )\n        if [[ \"\\${game_checksums[\\$(get_md5sum \\$wad_file)]}\" ]] 2>/dev/null; then\n            pushd \"$romdir/ports/wolf3d\"\n            $md_inst/bin/\\${game_checksums[\\$(get_md5sum \\$wad_file)]}\n            popd\n        else\n            echo \"Error: \\$wad_file (md5: \\$(get_md5sum \\$wad_file)) is not a supported version\"\n        fi\n}\n\nlaunch_wolf4sdl \"\\$1\"\n_EOF_\n        chmod +x \"$md_inst/bin/wolf4sdl.sh\"\n    fi\n\n    add_games_wolf4sdl\n\n    moveConfigDir \"$home/.wolf4sdl\" \"$md_conf_root/wolf3d\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/xrick.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xrick\"\nrp_module_desc=\"xrick - Open source implementation of Rick Dangerous\"\nrp_module_help=\"Install the xrick data.zip to $romdir/ports/xrick/data.zip\"\nrp_module_licence=\"GPL https://raw.githubusercontent.com/RetroPie/xrick/master/README\"\nrp_module_repo=\"git https://github.com/RetroPie/xrick.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"sdl1\"\n\nfunction depends_xrick() {\n    getDepends libsdl1.2-dev libsdl-mixer1.2-dev libsdl-image1.2-dev zlib1g\n}\n\nfunction sources_xrick() {\n    gitPullOrClone\n}\n\nfunction build_xrick() {\n    make clean\n    make\n    md_ret_require=\"$md_build/xrick\"\n}\n\nfunction install_xrick() {\n    md_ret_files=(\n        'README'\n        'xrick'\n    )\n}\n\nfunction configure_xrick() {\n    addPort \"$md_id\" \"xrick\" \"XRick\" \"$md_inst/xrick.sh -fullscreen\" \"$romdir/ports/xrick/data.zip\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    ln -sf \"$romdir/ports/xrick/data.zip\" \"$md_inst/data.zip\"\n    # set dispmanx by default on rpi with fkms\n    isPlatform \"dispmanx\" && ! isPlatform \"videocore\" && setBackend \"$md_id\" \"dispmanx\"\n    # on KMS and without dispmanx, use sdl12-compat\n    ! isPlatform \"dispmanx\" && isPlatform \"kms\" && setBackend \"$md_id\" \"sdl12-compat\"\n\n    local file=\"$md_inst/xrick.sh\"\n    cat >\"$file\" << _EOF_\n#!/usr/bin/env bash\npushd \"$md_inst\"\n./xrick \"\\$@\"\npopd\n_EOF_\n    chmod +x \"$file\"\n}\n"
  },
  {
    "path": "scriptmodules/ports/yquake2/hotkey_exit.diff",
    "content": "diff --git a/src/client/input/sdl2.c b/src/client/input/sdl2.c\nindex 527e3f5c..1c693749 100644\n--- a/src/client/input/sdl2.c\n+++ b/src/client/input/sdl2.c\n@@ -94,10 +94,11 @@ typedef enum\n // IN_Update() called at the beginning of a frame to the\n // actual movement functions called at a later time.\n static float mouse_x, mouse_y;\n-static unsigned char joy_escbutton = SDL_CONTROLLER_BUTTON_START;\n static int joystick_left_x, joystick_left_y, joystick_right_x, joystick_right_y;\n static qboolean mlooking;\n \n+static qboolean hotkey_back = false;\t// RetroPie Hotkey is Back instead of Guide\n+\n // The last time input events were processed.\n // Used throughout the client.\n int sys_frame_time;\n@@ -857,6 +858,7 @@ IN_Update(void)\n \tstatic qboolean left_trigger = false;\n \tstatic qboolean right_trigger = false;\n \tstatic qboolean left_stick[4] = {false, false, false, false};   // left, right, up, down virtual keys\n+\tstatic qboolean hotkey_pressed = false;\t// is Hotkey in RetroPie pressed\n \n \tstatic int consoleKeyCode = 0;\n \n@@ -1057,9 +1059,22 @@ IN_Update(void)\n \t\t\t\tqboolean down = (event.type == SDL_CONTROLLERBUTTONDOWN);\n \t\t\t\tunsigned char btn = event.cbutton.button;\n \n-\t\t\t\t// Handle Esc button first, to override its original key\n-\t\t\t\tKey_Event( (btn == joy_escbutton)? K_ESCAPE : K_JOY_FIRST_BTN + btn,\n-\t\t\t\t\tdown, true );\n+\t\t\t\tswitch (btn)\n+\t\t\t\t{\n+\t\t\t\t\tcase SDL_CONTROLLER_BUTTON_START:\n+\t\t\t\t\t\tif (hotkey_pressed && down)\n+\t\t\t\t\t\t\tCbuf_AddText(\"quit\");\n+\t\t\t\t\t\telse\n+\t\t\t\t\t\t\tKey_Event( K_ESCAPE, down, true );\n+\t\t\t\t\t\tbreak;\n+\n+\t\t\t\t\tcase SDL_CONTROLLER_BUTTON_BACK:\n+\t\t\t\t\t\tif (hotkey_back)\n+\t\t\t\t\tcase SDL_CONTROLLER_BUTTON_GUIDE:\n+\t\t\t\t\t\t\thotkey_pressed = down;\n+\t\t\t\t\tdefault:\n+\t\t\t\t\t\tKey_Event( K_JOY_FIRST_BTN + btn, down, true );\n+\t\t\t\t}\n \t\t\t\tbreak;\n \t\t\t}\n \n@@ -2524,22 +2539,6 @@ IN_Controller_Init(qboolean notify_user)\n \tSDL_Joystick *joystick = NULL;\n \tSDL_bool is_controller = SDL_FALSE;\n \n-\tcvar = Cvar_Get(\"joy_escbutton\", \"0\", CVAR_ARCHIVE);\n-\tif (cvar)\n-\t{\n-\t\tswitch ((int)cvar->value)\n-\t\t{\n-\t\t\tcase 1:\n-\t\t\t\tjoy_escbutton = SDL_CONTROLLER_BUTTON_BACK;\n-\t\t\t\tbreak;\n-\t\t\tcase 2:\n-\t\t\t\tjoy_escbutton = SDL_CONTROLLER_BUTTON_GUIDE;\n-\t\t\t\tbreak;\n-\t\t\tdefault:\n-\t\t\t\tjoy_escbutton = SDL_CONTROLLER_BUTTON_START;\n-\t\t}\n-\t}\n-\n \tcvar = Cvar_Get(\"in_initjoy\", \"1\", CVAR_NOSET);\n \tif (!cvar->value)\n \t{\n@@ -2685,6 +2684,7 @@ IN_Controller_Init(qboolean notify_user)\n \n \t\t\tshow_gamepad = true;\n \t\t\tCom_Printf(\"Enabled as Game Controller, settings:\\n%s\\n\", SDL_GameControllerMapping(controller));\n+\t\t\thotkey_back = ( !strstr(SDL_GameControllerMapping(controller), \"guide:\") );\n \n #ifndef NO_SDL_GYRO\n \n@@ -2960,6 +2960,7 @@ IN_Controller_Shutdown(qboolean notify_user)\n \tjoystick_left_x = joystick_left_y = joystick_right_x = joystick_right_y = 0;\n \tjoy_active_layout = LAYOUT_NONE;\n \tgyro_enabled = false;\n+\thotkey_back = false;\n \n #ifdef NO_SDL_GYRO\n \tif (imu_joystick)\n"
  },
  {
    "path": "scriptmodules/ports/yquake2/sdl2_joylabels.diff",
    "content": "diff --git a/src/client/cl_keyboard.c b/src/client/cl_keyboard.c\nindex 20ba3fcc..c9b24c41 100644\n--- a/src/client/cl_keyboard.c\n+++ b/src/client/cl_keyboard.c\n@@ -216,10 +216,10 @@ static char *gamepadbtns[] =\n \t// It is imperative that this list of buttons follow EXACTLY the order they\n \t// appear in QKEYS enum in keyboard.h, which in turn is the same order as\n \t// they appear in SDL_GamepadButton / SDL_GameControllerButton enum.\n-\t\"BTN_SOUTH\",\n-\t\"BTN_EAST\",\n-\t\"BTN_WEST\",\n-\t\"BTN_NORTH\",\n+\t\"BTN_A\",\n+\t\"BTN_B\",\n+\t\"BTN_X\",\n+\t\"BTN_Y\",\n \t\"BTN_BACK\",\n \t\"BTN_GUIDE\",\n \t\"BTN_START\",\n@@ -245,10 +245,10 @@ static char *gamepadbtns[] =\n \t\"TRIG_LEFT\",\n \t\"TRIG_RIGHT\",\n \t// Same with _ALT buttons ( button + 'alt modifier' pressed )\n-\t\"BTN_SOUTH_ALT\",\n-\t\"BTN_EAST_ALT\",\n-\t\"BTN_WEST_ALT\",\n-\t\"BTN_NORTH_ALT\",\n+\t\"BTN_A_ALT\",\n+\t\"BTN_B_ALT\",\n+\t\"BTN_X_ALT\",\n+\t\"BTN_Y_ALT\",\n \t\"BTN_BACK_ALT\",\n \t\"BTN_GUIDE_ALT\",\n \t\"BTN_START_ALT\",\ndiff --git a/src/client/input/sdl2.c b/src/client/input/sdl2.c\nindex 1c693749..2921a498 100644\n--- a/src/client/input/sdl2.c\n+++ b/src/client/input/sdl2.c\n@@ -2559,9 +2559,6 @@ IN_Controller_Init(qboolean notify_user)\n #ifdef SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE\n \t\tSDL_SetHint( SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE, \"1\" );\n #endif\n-#ifdef SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS\t// use button positions instead of labels, like SDL3\n-\t\tSDL_SetHint( SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS, \"0\" );\n-#endif\n \n \t\tif (SDL_Init(SDL_INIT_GAMECONTROLLER | SDL_INIT_HAPTIC) == -1)\n \t\t{\n@@ -2878,8 +2875,8 @@ IN_Init(void)\n \tjoy_forwardsensitivity = Cvar_Get(\"joy_forwardsensitivity\", \"1.0\", CVAR_ARCHIVE);\n \tjoy_sidesensitivity = Cvar_Get(\"joy_sidesensitivity\", \"1.0\", CVAR_ARCHIVE);\n \n-\tjoy_labels = Cvar_Get(\"joy_labels\", \"-1\", CVAR_ARCHIVE);\n-\tjoy_confirm = Cvar_Get(\"joy_confirm\", \"-1\", CVAR_ARCHIVE);\n+\tjoy_labels = Cvar_Get(\"joy_labels\", \"0\", CVAR_ARCHIVE);\n+\tjoy_confirm = Cvar_Get(\"joy_confirm\", \"0\", CVAR_ARCHIVE);\n \tjoy_layout = Cvar_Get(\"joy_layout\", \"0\", CVAR_ARCHIVE);\n \tjoy_left_expo = Cvar_Get(\"joy_left_expo\", \"2.0\", CVAR_ARCHIVE);\n \tjoy_left_snapaxis = Cvar_Get(\"joy_left_snapaxis\", \"0.15\", CVAR_ARCHIVE);\n"
  },
  {
    "path": "scriptmodules/ports/yquake2/yq2.cfg",
    "content": "// Default gamepad controls\nbind SHOULDR_LEFT \"+movedown\"\nbind TRIG_LEFT \"+moveup\"\nbind SHOULDR_RIGHT \"+joyaltselector\"\nbind TRIG_RIGHT \"+attack\"\n\nbind BTN_A \"+movedown\"\nbind BTN_B \"+moveup\"\nbind BTN_X \"weapprev\"\nbind BTN_Y \"weapnext\"\nbind BTN_BACK \"cmd help\"\nbind BTN_GUIDE \"+joyaltselector\"\nbind STICK_LEFT \"+gyroaction\"\nbind STICK_RIGHT \"centerview\"\nbind DP_UP \"cycleweap weapon_plasmabeam weapon_boomer weapon_chaingun weapon_etf_rifle weapon_machinegun weapon_blaster\"\nbind DP_DOWN \"cycleweap weapon_supershotgun weapon_shotgun weapon_chainfist\"\nbind DP_LEFT \"cycleweap weapon_phalanx weapon_rocketlauncher weapon_proxlauncher weapon_grenadelauncher ammo_grenades\"\nbind DP_RIGHT \"cycleweap weapon_bfg weapon_disintegrator weapon_railgun weapon_hyperblaster ammo_tesla ammo_trap\"\n\nbind BTN_X_ALT \"invdrop\"\nbind BTN_Y_ALT \"invuse\"\nbind BTN_BACK_ALT \"inven\"\nbind DP_UP_ALT \"invprev\"\nbind DP_DOWN_ALT \"invnext\"\nbind DP_LEFT_ALT \"invprev\"\nbind DP_RIGHT_ALT \"invnext\"\n\n// Gameplay options, check YQ2 documentation\nset cl_run \"1\"\nset aimfix \"1\"\nset g_machinegun_norecoil \"1\"\nset g_quick_weap \"1\"\nset g_swap_speed \"2\"\n\n// Audio options\nset s_openal \"0\"\nset ogg_ignoretrack0 \"1\"\n\n// Video options\nset vid_renderer \"soft\"\nset gl_znear \"3.2\"\nset gl1_discardfb \"1\"\nset gl1_lightmapcopies \"1\"\nset gl1_pointparameters \"0\"\nset r_mode \"-2\"\n"
  },
  {
    "path": "scriptmodules/ports/yquake2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"yquake2\"\nrp_module_desc=\"yquake2 - The Yamagi Quake II client\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/yquake2/yquake2/master/LICENSE\"\nrp_module_repo=\"git https://github.com/yquake2/yquake2.git QUAKE2_8_60\"\nrp_module_section=\"exp\"\nrp_module_flags=\"sdl2\"\n\nfunction depends_yquake2() {\n    local depends=(libgl1-mesa-dev libglu1-mesa-dev libogg-dev libopenal-dev libsdl2-dev libvorbis-dev zlib1g-dev libcurl4-openssl-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_yquake2() {\n    gitPullOrClone\n    # get the add-ons sources\n    gitPullOrClone \"$md_build/xatrix\" \"https://github.com/yquake2/xatrix\" \"XATRIX_2_16\"\n    gitPullOrClone \"$md_build/rogue\" \"https://github.com/yquake2/rogue\" \"ROGUE_2_15\"\n\n    # 1st enables Guide+Start to quit. 2nd restores buttons to SDL2 style (from SDL3).\n    applyPatch \"$md_data/hotkey_exit.diff\"\n    applyPatch \"$md_data/sdl2_joylabels.diff\"\n}\n\nfunction build_yquake2() {\n    local params=(config client game ref_soft)\n    local repo\n\n    isPlatform \"gl\" || isPlatform \"mesa\" && params+=(ref_gl1)\n    isPlatform \"gl3\" && params+=(ref_gl3)\n    isPlatform \"gles\" && [[ \"$__os_debian_ver\" -lt 12 ]] && params+=(ref_gles1)\n    isPlatform \"gles3\" && params+=(ref_gles3)\n\n    make clean\n    make ${params[@]}\n\n    # build the add-ons source\n    for repo in 'xatrix' 'rogue'; do\n        make -C \"$repo\" clean\n        make -C \"$repo\"\n        # add-ons: rename the 'release' folder so it's installed under '$repo' by the install func\n        [[ -f \"$repo/release/game.so\" ]] && mv \"$repo/release\" \"$repo/$repo\"\n    done\n    md_ret_require=\"$md_build/release/quake2\"\n}\n\nfunction install_yquake2() {\n    md_ret_files=(\n        'release/baseq2'\n        'release/quake2'\n        'release/ref_soft.so'\n        'LICENSE'\n        'README.md'\n        'xatrix/xatrix'\n        'rogue/rogue'\n    )\n\n    isPlatform \"gl\" || isPlatform \"mesa\" && md_ret_files+=('release/ref_gl1.so')\n    isPlatform \"gl3\" && md_ret_files+=('release/ref_gl3.so')\n    isPlatform \"gles\" && [[ \"$__os_debian_ver\" -lt 12 ]] && md_ret_files+=('release/ref_gles1.so')\n    isPlatform \"gles3\" && md_ret_files+=('release/ref_gles3.so')\n}\n\nfunction add_games_yquake2() {\n    local cmd=\"$1\"\n    declare -A games=(\n        ['baseq2']=\"Quake II\"\n        ['xatrix']=\"Quake II XP1 - The Reckoning\"\n        ['rogue']=\"Quake II XP2 - Ground Zero\"\n    )\n\n    local game\n    for game in \"${!games[@]}\"; do\n        if [[ -f \"$romdir/ports/quake2/$game/pak0.pak\" ]]; then\n            addPort \"$md_id\" \"quake2\" \"${games[$game]}\" \"$cmd\" \"$game\"\n        fi\n    done\n}\n\nfunction game_data_yquake2() {\n    if [[ ! -f \"$romdir/ports/quake2/baseq2/pak1.pak\" && ! -f \"$romdir/ports/quake2/baseq2/pak0.pak\" ]]; then\n        # get shareware game data\n        downloadAndExtract \"https://deponie.yamagi.org/quake2/idstuff/q2-314-demo-x86.exe\" \"$romdir/ports/quake2/baseq2\" -j -LL\n        # remove files that are likely to cause conflicts or unwanted default settings\n        local unwanted\n        for unwanted in $(find \"$romdir/ports/quake2\" -maxdepth 2 -name \"*.so\" -o -name \"*.cfg\" -o -name \"*.dll\" -o -name \"*.exe\"); do\n            rm -f \"$unwanted\"\n        done\n    fi\n\n    chown -R \"$__user\":\"$__group\" \"$romdir/ports/quake2\"\n}\n\n\nfunction configure_yquake2() {\n    local config=\"$md_conf_root/quake2/yquake2/baseq2/yq2.cfg\"\n    local renderer=\"soft\"\n\n    mkRomDir \"ports/quake2\"\n\n    moveConfigDir \"$home/.yq2\" \"$md_conf_root/quake2/yquake2\"\n    mkUserDir \"$md_conf_root/quake2/yquake2/baseq2\"\n\n    copyDefaultConfig \"$md_data/yq2.cfg\" \"$config\"\n    iniConfig \" \" '\"' \"$config\"\n\n    # Don't apply GL1 mobile optimizations to x86\n    if isPlatform \"x86\"; then\n        iniSet \"set gl1_discardfb\" \"0\"\n        iniSet \"set gl1_lightmapcopies\" \"0\"\n        iniSet \"set gl1_pointparameters\" \"1\"\n        iniSet \"set s_openal\" \"1\"\n    fi\n\n    # Select most efficient renderer as default\n    if isPlatform \"gl3\"; then\n        renderer=\"gl3\"\n    elif isPlatform \"gles3\"; then\n        renderer=\"gles3\"\n    elif isPlatform \"gles\" && [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        renderer=\"gles1\"\n        iniSet \"set gl1_pointparameters\" \"1\"\n    elif isPlatform \"gl\" || isPlatform \"mesa\"; then\n        renderer=\"gl1\"\n    fi\n\n    iniSet \"set vid_renderer\" \"$renderer\"\n\n    [[ \"$md_mode\" == \"install\" ]] && game_data_yquake2\n    add_games_yquake2 \"$md_inst/quake2 -datadir $romdir/ports/quake2 +set game %ROM%\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/attractmode.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"attractmode\"\nrp_module_desc=\"Attract Mode emulator frontend\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/mickelson/attract/master/License.txt\"\nrp_module_repo=\"git https://github.com/mickelson/attract master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!mali frontend\"\n\nfunction _get_configdir_attractmode() {\n    echo \"$configdir/all/attractmode\"\n}\n\nfunction _add_system_attractmode() {\n    local attract_dir=\"$(_get_configdir_attractmode)\"\n    [[ ! -d \"$attract_dir\" || ! -f /usr/bin/attract ]] && return 0\n\n    local fullname=\"$1\"\n    local name=\"$2\"\n    local path=\"$3\"\n    local extensions=\"$4\"\n    local command=\"$5\"\n    local platform=\"$6\"\n    local theme=\"$7\"\n\n    # replace any / characters in fullname\n    fullname=\"${fullname//\\/}\"\n\n    local config=\"$attract_dir/emulators/$fullname.cfg\"\n    iniConfig \" \" \"\" \"$config\"\n    # replace %ROM% with \"[romfilename]\" and convert to array\n    command=(${command//%ROM%/\\\"[romfilename]\\\"})\n    iniSet \"executable\" \"${command[0]}\"\n    iniSet \"args\" \"${command[*]:1}\"\n\n    iniSet \"rompath\" \"$path\"\n    iniSet \"system\" \"$fullname\"\n\n    # extensions separated by semicolon\n    extensions=\"${extensions// /;}\"\n    iniSet \"romext\" \"$extensions\"\n\n    # snap path\n    local snap=\"snap\"\n    [[ \"$name\" == \"retropie\" ]] && snap=\"icons\"\n    iniSet \"artwork flyer\" \"$path/flyer\"\n    iniSet \"artwork marquee\" \"$path/marquee\"\n    iniSet \"artwork snap\" \"$path/$snap\"\n    iniSet \"artwork wheel\" \"$path/wheel\"\n\n    chown \"$__user\":\"$__group\" \"$config\"\n\n    # if no gameslist, generate one\n    if [[ ! -f \"$attract_dir/romlists/$fullname.txt\" ]]; then\n        sudo -u \"$__user\" attract --build-romlist \"$fullname\" -o \"$fullname\"\n    fi\n\n    local config=\"$attract_dir/attract.cfg\"\n    local tab=$'\\t'\n    if [[ -f \"$config\" ]] && ! grep -q \"display$tab$fullname\" \"$config\"; then\n        cp \"$config\" \"$config.bak\"\n        cat >>\"$config\" <<_EOF_\ndisplay${tab}$fullname\n${tab}layout               Basic\n${tab}romlist              $fullname\n_EOF_\n        chown \"$__user\":\"$__group\" \"$config\"\n    fi\n}\n\nfunction _del_system_attractmode() {\n    local attract_dir=\"$(_get_configdir_attractmode)\"\n    [[ ! -d \"$attract_dir\" ]] && return 0\n\n    local fullname=\"$1\"\n    local name=\"$2\"\n\n    # Don't remove an empty system\n    [[ -z \"$fullname\" ]] && return 0\n\n    # replace any / characters in fullname\n    fullname=\"${fullname//\\/}\"\n\n    rm -rf \"$attract_dir/romlists/$fullname.txt\"\n\n    local tab=$'\\t'\n    # remove display block from \"^display$tab$fullname\" to next \"^display\" or empty line keeping the next display line\n    sed -i \"/^display$tab$fullname/,/^display\\|^$/{/^display$tab$fullname/d;/^display\\$/!d}\" \"$attract_dir/attract.cfg\"\n}\n\nfunction _add_rom_attractmode() {\n    local attract_dir=\"$(_get_configdir_attractmode)\"\n    [[ ! -d \"$attract_dir\" ]] && return 0\n\n    local system_name=\"$1\"\n    local system_fullname=\"$2\"\n    local path=\"$3\"\n    local name=\"$4\"\n    local desc=\"$5\"\n    local image=\"$6\"\n\n    local config=\"$attract_dir/romlists/$system_fullname.txt\"\n\n    # remove extension\n    path=\"${path/%.*}\"\n\n    if [[ ! -f \"$config\" ]]; then\n        echo \"#Name;Title;Emulator;CloneOf;Year;Manufacturer;Category;Players;Rotation;Control;Status;DisplayCount;DisplayType;AltRomname;AltTitle;Extra;Buttons\" >\"$config\"\n    fi\n\n    # if the entry already exists, remove it\n    if grep -q \"^$path;\" \"$config\"; then\n        sed -i \"/^$path/d\" \"$config\"\n    fi\n\n    echo \"$path;$name;$system_fullname;;;;;;;;;;;;;;\" >>\"$config\"\n    chown \"$__user\":\"$__group\" \"$config\"\n}\n\nfunction depends_attractmode() {\n    local depends=(\n        cmake fonts-freefont-ttf libflac-dev libcurl4-openssl-dev libogg-dev libvorbis-dev libopenal-dev libfreetype6-dev\n        libudev-dev libjpeg-dev libudev-dev libavutil-dev libavcodec-dev\n        libavformat-dev libavfilter-dev libswscale-dev libswresample-dev\n        libfontconfig1-dev\n    )\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n    isPlatform \"kms\" && depends+=(libegl1-mesa-dev libgl-dev libglu1-mesa-dev libdrm-dev libgbm-dev)\n    isPlatform \"x11\" && depends+=(libsfml-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_attractmode() {\n    gitPullOrClone \"$md_build/attract\"\n    isPlatform \"rpi\" && gitPullOrClone \"$md_build/sfml-pi\" \"https://github.com/mickelson/sfml-pi\"\n}\n\nfunction build_attractmode() {\n    if isPlatform \"rpi\"; then\n        local params\n        cd sfml-pi\n        isPlatform \"videocore\" && params=\"-DSFML_RPI=1 -DEGL_INCLUDE_DIR=/opt/vc/include -DEGL_LIBRARY=/opt/vc/lib/libbrcmEGL.so -DGLES_INCLUDE_DIR=/opt/vc/include -DGLES_LIBRARY=/opt/vc/lib/libbrcmGLESv2.so\"\n        isPlatform \"kms\" && params=\"-DSFML_DRM=1\"\n        cmake . -DCMAKE_INSTALL_PREFIX=\"$md_inst/sfml\" $params\n        make clean\n        make\n        cd ..\n    fi\n    cd attract\n    make clean\n    local params=(prefix=\"$md_inst\")\n    isPlatform \"videocore\" && params+=(USE_GLES=1 EXTRA_CXXFLAGS=\"$CFLAGS -I$md_build/sfml-pi/include -L$md_build/sfml-pi/lib\")\n    isPlatform \"kms\" && params+=(USE_DRM=1 EXTRA_CXXFLAGS=\"$CFLAGS -I$md_build/sfml-pi/include -L$md_build/sfml-pi/lib\")\n    isPlatform \"rpi\" && params+=(USE_MMAL=1)\n    make \"${params[@]}\"\n\n    # remove example configs\n    rm -rf \"$md_build/attract/config/emulators/\"*\n\n    md_ret_require=\"$md_build/attract/attract\"\n}\n\nfunction install_attractmode() {\n    make -C sfml-pi install\n    mkdir -p \"$md_inst\"/{bin,share,share/attract}\n    cp -v attract/attract \"$md_inst/bin/\"\n    cp -Rv attract/config/* \"$md_inst/share/attract\"\n}\n\nfunction remove_attractmode() {\n    rm -f /usr/bin/attract\n}\n\nfunction configure_attractmode() {\n    moveConfigDir \"$home/.attract\" \"$md_conf_root/all/attractmode\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local config=\"$md_conf_root/all/attractmode/attract.cfg\"\n    if [[ ! -f \"$config\" ]]; then\n        echo \"general\" >\"$config\"\n        echo -e \"\\twindow_mode          fullscreen\" >>\"$config\"\n    fi\n\n    mkUserDir \"$md_conf_root/all/attractmode/emulators\"\n    cat >/usr/bin/attract <<_EOF_\n#!/bin/bash\nMODELIST=/opt/retropie/supplementary/kmsxx/kmsprint-rp\nif [[ -z \"\\$DISPLAY\" && -f \"\\$MODELIST\" && ! \"\\$1\" =~ build-romlist ]]; then\n    MODELIST=\"\\$(\\$MODELIST 2>/dev/null)\"\n    default_mode=\"\\$(echo \"\\$MODELIST\" | grep -Em1 \"^Mode: [0-9]+ crtc\" | grep -oE [0-9]+x[0-9]+)\"\n    default_vrefresh=\"\\$(echo \"\\$MODELIST\" | grep -Em1 \"^Mode: [0-9]+ crtc\" | grep -oE [0-9]+Hz)\"\n    # Strip Hz from the refresh rate\n    default_vrefresh=\"\\${default_vrefresh%Hz}\"\n    echo \"Using default video mode: \\$default_mode @ \\$default_vrefresh\"\n\n    [[ ! -z \"\\$default_mode\" ]] && export SFML_DRM_MODE=\"\\$default_mode\"\n    [[ ! -z \"\\$default_vrefresh\" ]] && export SFML_DRM_REFRESH=\"\\$default_vrefresh\"\nfi\nLD_LIBRARY_PATH=\"$md_inst/sfml/lib\" \"$md_inst/bin/attract\" \"\\$@\"\n_EOF_\n    chmod +x \"/usr/bin/attract\"\n\n    local id\n    for id in \"${__mod_id[@]}\"; do\n        if rp_isInstalled \"$id\" && [[ -n \"${__mod_info[$id/section]}\" ]] && ! hasFlag \"${__mod_info[$id/flags]}\" \"frontend\"; then\n            rp_callModule \"$id\" configure\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/audiosettings.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"audiosettings\"\nrp_module_desc=\"Configure audio settings\"\nrp_module_section=\"config\"\nrp_module_flags=\"!all rpi\"\n\nfunction depends_audiosettings() {\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        getDepends alsa-utils\n    fi\n}\n\nfunction gui_audiosettings() {\n    # Check if the internal audio is enabled\n    if [[ `aplay -ql | grep -e bcm2835 -e vc4hdmi | wc -l` < 1 ]]; then\n        printMsgs \"dialog\" \"On-board audio disabled or not present\"\n        return\n    fi\n\n    # The list of ALSA cards/devices depends on the 'snd-bcm2385' module parameter 'enable_compat_alsa'\n    # * enable_compat_alsa: true  - single soundcard, output is routed based on the `numid` control\n    # * enable_compat_alsa: false - one soundcard per output type (HDMI/Headphones)\n    # When PulseAudio/PipeWire is enabled, try to configure it and leave ALSA alone\n    if _pa_cmd_audiosettings systemctl -q --user is-enabled {pulseaudio,pipewire-pulse}.service; then\n        _pulseaudio_audiosettings\n    elif aplay -l | grep -q \"bcm2835 ALSA\"; then\n        _bcm2835_alsa_compat_audiosettings\n    else\n        _bcm2835_alsa_internal_audiosettings\n    fi\n}\n\nfunction _reset_alsa_audiosettings() {\n    /etc/init.d/alsa-utils reset\n    alsactl store\n    rm -f \"$home/.asoundrc\" \"/etc/alsa/conf.d/99-retropie.conf\"\n    printMsgs \"dialog\" \"Audio settings reset to defaults\"\n}\n\nfunction _move_old_config_audiosettings() {\n    if [[ -f \"$home/.asoundrc\" && ! -f \"/etc/alsa/conf.d/99-retropie.conf\" ]]; then\n        if dialog --yesno \"The ALSA audio configuration for RetroPie has moved from $home/.asoundrc to /etc/alsa/conf.d/99-retropie.conf\\n\\nYou have a configuration in $home/.asoundrc - do you want to move it to the new location? If $home/.asoundrc contains your own changes you should choose 'No'.\" 20 76 2>&1 >/dev/tty; then\n            mkdir -p /etc/alsa/conf.d\n            mv \"$home/.asoundrc\" \"/etc/alsa/conf.d/\"\n        fi\n    fi\n}\n\nfunction _bcm2835_alsa_compat_audiosettings() {\n    _move_old_config_audiosettings\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Set audio output (ALSA - compat)\" 22 86 16)\n    local hdmi=\"HDMI\"\n\n    # the Pi 4/5 have 2 HDMI ports, so number them\n    (isPlatform \"rpi4\" || isPlatform \"rpi5\") && hdmi=\"HDMI 1\"\n\n    local options=(\n        1 \"Auto\"\n        2 \"Headphones - 3.5mm jack\"\n        3 \"$hdmi\"\n    )\n    # add 2nd HDMI port on the Pi 4/5\n    (isPlatform \"rpi4\" || isPlatform \"rpi5\") && options+=(4 \"HDMI 2\")\n    options+=(\n        M \"Mixer - adjust output volume\"\n        R \"Reset to default\"\n    )\n    # If PulseAudio (PipeWire) is installed, add an option to enable it\n    local sound_server=\"PulseAudio\"\n    if hasPackage \"wireplumber\"; then\n        options+=(P \"Enable PipeWire\")\n    else\n        hasPackage \"pulseaudio\" && options+=(P \"Enable PulseAudio\")\n    fi\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                amixer cset numid=3 0\n                alsactl store\n                printMsgs \"dialog\" \"Set audio output to Auto\"\n                ;;\n            2)\n                amixer cset numid=3 1\n                alsactl store\n                printMsgs \"dialog\" \"Set audio output to Headphones - 3.5mm jack\"\n                ;;\n            3)\n                amixer cset numid=3 2\n                alsactl store\n                printMsgs \"dialog\" \"Set audio output to $hdmi\"\n                ;;\n            4)\n                amixer cset numid=3 3\n                alsactl store\n                printMsgs \"dialog\" \"Set audio output to HDMI 2\"\n                ;;\n            M)\n                alsamixer >/dev/tty </dev/tty\n                alsactl store\n                ;;\n            R)\n                _reset_alsa_audiosettings\n                ;;\n            P)\n                _toggle_${sound_server,,} audiosettings \"on\"\n                printMsgs \"dialog\" \"${sound_server} enabled\"\n                ;;\n        esac\n    fi\n}\n\nfunction _bcm2835_alsa_internal_audiosettings() {\n    _move_old_config_audiosettings\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Set audio output (ALSA)\" 22 86 16)\n    local options=()\n    local card_index\n    local card_label\n\n    # Get the list of Pi internal cards\n    while read card_no card_label; do\n        options+=(\"$card_no\" \"$card_label\")\n    done < <(aplay -ql | sed -En -e '/^card/ {s/^card ([0-9]+).*\\[(bcm2835 |vc4-)([^]]*)\\].*/\\1 \\3/; s/hdmi[- ]?/HDMI /i; p}')\n    options+=(\n        M \"Mixer - adjust output volume\"\n        R \"Reset to default\"\n    )\n\n    # If PulseAudio (PipeWire) is installed, add an option to enable it\n    local sound_server=\"PulseAudio\"\n    if hasPackage \"wireplumber\"; then\n        options+=(P \"Enable PipeWire\")\n        sound_server=\"PipeWire\"\n    else\n        hasPackage \"pulseaudio\" && options+=(P \"Enable PulseAudio\")\n    fi\n\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            [0-9])\n                _asoundrc_save_audiosettings $choice ${options[$((choice*2+1))]}\n                printMsgs \"dialog\" \"Set audio output to ${options[$((choice*2+1))]}\"\n                ;;\n            M)\n                alsamixer >/dev/tty </dev/tty\n                alsactl store\n                ;;\n            R)\n                _reset_alsa_audiosettings\n                ;;\n            P)\n                _toggle_${sound_server,,}_audiosettings \"on\"\n                printMsgs \"dialog\" \"$sound_server enabled\"\n                ;;\n        esac\n    fi\n}\n\n# configure the default ALSA soundcard based on chosen card index and type\nfunction _asoundrc_save_audiosettings() {\n    [[ -z \"$1\" ]] && return\n\n    local card_index=$1\n    local card_type=$2\n    local tmpfile=\"$(mktemp)\"\n\n    if isPlatform \"kms\" && ! isPlatform \"dispmanx\" && [[ $card_type == \"HDMI\"* ]]; then\n        # when the 'vc4hdmi' driver is used instead of 'bcm2835_audio' for HDMI,\n        # the 'hdmi:vchdmi[-idx]' PCM should be used for converting to the native IEC958 codec\n        # adds a volume control since the default configured mixer doesn't work\n        # (default configuration is at /usr/share/alsa/cards/vc4-hdmi.conf)\n        local card_name=\"$(cat /proc/asound/card${card_index}/id)\"\n        cat << EOF > \"$tmpfile\"\npcm.hdmi${card_index} {\n  type asym\n  playback.pcm {\n    type plug\n    slave.pcm \"hdmi:${card_name}\"\n  }\n}\nctl.!default {\n  type hw\n  card $card_index\n}\npcm.softvolume {\n    type           softvol\n    slave.pcm      \"hdmi${card_index}\"\n    control.name  \"HDMI Playback Volume\"\n    control.card  ${card_index}\n}\n\npcm.softmute {\n    type softvol\n    slave.pcm \"softvolume\"\n    control.name \"HDMI Playback Switch\"\n    control.card ${card_index}\n    resolution 2\n}\n\npcm.!default {\n    type plug\n    slave.pcm \"softmute\"\n}\nEOF\n    else\n    cat << EOF > \"$tmpfile\"\npcm.!default {\n  type asym\n  playback.pcm {\n    type plug\n    slave.pcm \"output\"\n  }\n}\npcm.output {\n  type hw\n  card $card_index\n}\nctl.!default {\n  type hw\n  card $card_index\n}\nEOF\n    fi\n    local dest=\"/etc/alsa/conf.d/99-retropie.conf\"\n    mkdir -p /etc/alsa/conf.d\n    mv \"$tmpfile\" \"$dest\"\n    chmod 644 \"$dest\"\n}\n\nfunction _pulseaudio_audiosettings() {\n    local options=()\n    local sinks=()\n    local sink_index\n    local sink_label\n    local sound_server=\"PulseAudio\"\n\n    # Check if PulseAudio is running, otherwise 'pactl' will not work\n    if ! _pa_cmd_audiosettings pactl info >/dev/null; then\n        printMsgs \"dialog\" \"PulseAudio is present, but not running.\\nAudio settings cannot be set right now.\"\n        return\n    fi\n    while read sink_index sink_label sink_id; do\n        options+=(\"$sink_index\" \"$sink_label\")\n        sinks[$sink_index]=$sink_id\n    done < <(_pa_cmd_audiosettings pactl list sinks | \\\n            awk -F [:=#] 'BEGIN {idx=0} /Sink/ {\n                             ctl_index=$2\n                             do {getline} while($0 !~ /card.name/ && $0 !~ /Formats/);\n                             if ( $2 != \"\" ) {\n                                gsub(/\"|bcm2835[^a-zA-Z]+/, \"\", $2); # strip bcm2835 suffix on analog output\n                                gsub(/vc4[-]?/ , \"\", $2); # strip the vc4 suffix on HDMI output(s)\n                                if ( $2 ~ /hdmi/ ) $2=toupper($2)\n                                print idx,$2,ctl_index\n                                idx++\n                             }\n                         }'\n            )\n    _pa_cmd_audiosettings pactl info | grep -i pipewire >/dev/null && sound_server=\"PipeWire\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Set audio output ($sound_server)\" 22 86 16)\n    options+=(\n        M \"Mixer - adjust output volume\"\n        R \"Reset to default\"\n        P \"Disable $sound_server\"\n    )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            [0-9]*)\n                _pa_cmd_audiosettings pactl set-default-sink ${sinks[$choice]}\n                rm -f \"/etc/alsa/conf.d/99-retropie.conf\"\n\n                printMsgs \"dialog\" \"Set audio output to ${options[$((choice*2+1))]}\"\n                ;;\n            M)\n                _pa_cmd_audiosettings alsamixer >/dev/tty </dev/tty\n                alsactl store\n                ;;\n            R)\n                rm -fr \"$home/.config/pulse\"\n                /etc/init.d/alsa-utils reset\n                alsactl store\n                printMsgs \"dialog\" \"Audio settings reset to defaults\"\n                ;;\n            P)\n                _toggle_${sound_server,,}_audiosettings \"off\"\n                printMsgs \"dialog\" \"${sound_server} disabled\"\n                ;;\n        esac\n    fi\n}\n\nfunction _toggle_pulseaudio_audiosettings() {\n    local state=$1\n\n    if [[ \"$state\" == \"on\" ]]; then\n        _pa_cmd_audiosettings systemctl --user unmask pulseaudio.socket\n        _pa_cmd_audiosettings systemctl --user start  pulseaudio.service\n    fi\n\n    if [[ \"$state\" == \"off\" ]]; then\n        _pa_cmd_audiosettings systemctl --user mask pulseaudio.socket\n        _pa_cmd_audiosettings systemctl --user stop pulseaudio.service\n    fi\n}\n\nfunction _toggle_pipewire_audiosettings() {\n    local state=$1\n\n    if [[ \"$state\" == \"on\" ]]; then\n        _pa_cmd_audiosettings systemctl --user unmask {pipewire,pipewire-pulse}.{socket,service}\n        _pa_cmd_audiosettings systemctl --user start  pipewire.service pipewire-pulse.service wireplumber.service\n    fi\n\n    if [[ \"$state\" == \"off\" ]]; then\n        _pa_cmd_audiosettings systemctl --user mask {pipewire,pipewire-pulse}.{socket,service}\n        _pa_cmd_audiosettings systemctl --user stop pipewire.service pipewire-pulse.service wireplumber.service\n     fi\n}\n\n# Run PulseAudio commands as the calling user\nfunction _pa_cmd_audiosettings() {\n    [[ -n \"$@\" ]] && sudo -u \"$__user\" XDG_RUNTIME_DIR=/run/user/$SUDO_UID \"$@\" 2>/dev/null\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/autostart.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"autostart\"\nrp_module_desc=\"Auto-start EmulationStation / Pegasus / Kodi on boot\"\nrp_module_section=\"config\"\n\nfunction _update_hook_autostart() {\n    if [[ -f /etc/profile.d/10-emulationstation.sh ]]; then\n        enable_autostart\n    fi\n}\n\nfunction _autostart_script_autostart() {\n    local mode=\"$1\"\n    # delete old startup script\n    rm -f /etc/profile.d/10-emulationstation.sh\n\n    local script=\"$configdir/all/autostart.sh\"\n\n    cat >/etc/profile.d/10-retropie.sh <<_EOF_\n# launch our autostart apps (if we are on the correct tty and not in X)\nif [ \"\\`tty\\`\" = \"/dev/tty1\" ] && [ -z \"\\$DISPLAY\" ] && [ \"\\$USER\" = \"$__user\" ]; then\n    bash \"$script\"\nfi\n_EOF_\n\n    touch \"$script\"\n    # delete any previous entries for emulationstation / kodi in autostart.sh\n    sed -i '/#auto/d' \"$script\"\n    # make sure there is a newline\n    sed -i '$a\\' \"$script\"\n    case \"$mode\" in\n        kodi)\n            echo -e \"kodi-standalone #auto\\nemulationstation #auto\" >>\"$script\"\n            ;;\n        pegasus)\n            echo \"pegasus-fe #auto\" >> \"$script\"\n            ;;\n        es|*)\n            echo \"emulationstation #auto\" >>\"$script\"\n            ;;\n    esac\n    chown \"$__user\":\"$__group\" \"$script\"\n}\n\nfunction enable_autostart() {\n    local mode=\"$1\"\n\n    if isPlatform \"x11\"; then\n        mkUserDir \"$home/.config/autostart\"\n        ln -sf \"/usr/local/share/applications/retropie.desktop\" \"$home/.config/autostart/\"\n    else\n        if [[ \"$__os_id\" == \"Raspbian\" ]]; then\n            # remove any old autologin.conf - we use raspi-config now\n            rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf\n            raspi-config nonint do_boot_behaviour B2\n        elif [[ \"$(cat /proc/1/comm)\" == \"systemd\" ]]; then\n            mkdir -p /etc/systemd/system/getty@tty1.service.d/\n            cat >/etc/systemd/system/getty@tty1.service.d/autologin.conf <<_EOF_\n[Service]\nExecStart=\nExecStart=-/sbin/agetty --autologin $__user --noclear %I \\$TERM\n_EOF_\n        fi\n\n        _autostart_script_autostart \"$mode\"\n    fi\n}\n\nfunction disable_autostart() {\n    local login_type=\"$1\"\n    [[ -z \"$login_type\" ]] && login_type=\"B2\"\n    if isPlatform \"x11\"; then\n        rm \"$home/.config/autostart/retropie.desktop\"\n    else\n        if [[ \"$__os_id\" == \"Raspbian\" ]]; then\n            if [[ \"$__chroot\" -eq 1 ]]; then\n                systemctl set-default graphical.target\n                ln -fs /lib/systemd/system/getty@.service /etc/systemd/system/getty.target.wants/getty@tty1.service\n            else\n                raspi-config nonint do_boot_behaviour \"$login_type\"\n            fi\n        elif [[ \"$(cat /proc/1/comm)\" == \"systemd\" ]]; then\n            rm -f /etc/systemd/system/getty@tty1.service.d/autologin.conf\n            systemctl set-default graphical.target\n            systemctl enable lightdm.service\n        fi\n        rm -f /etc/profile.d/10-emulationstation.sh\n        rm -f /etc/profile.d/10-retropie.sh\n    fi\n}\n\nfunction remove_autostart() {\n    disable_autostart\n}\n\nfunction gui_autostart() {\n    cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose the desired boot behaviour.\" 22 76 16)\n    local has_pegasus=0\n    local has_kodi=0\n\n    command -v pegasus-fe >/dev/null && has_pegasus=1\n    command -v kodi-standalone >/dev/null && has_kodi=1\n\n    while true; do\n        if isPlatform \"x11\"; then\n            local x11_autostart\n            if [[ -f \"$home/.config/autostart/retropie.desktop\" ]]; then\n                options=(1 \"Autostart EmulationStation after login (Enabled)\")\n                x11_autostart=1\n            else\n                options=(1 \"Autostart EmulationStation after login (Disabled)\")\n                x11_autostart=0\n            fi\n        else\n            options=(\n                1 \"Start EmulationStation at boot\"\n            )\n            [[ \"$has_kodi\" -eq 1 ]] && options+=(2 \"Start Kodi at boot (exit starts EmulationStation)\")\n            [[ \"$has_pegasus\" -eq 1 ]] && options+=(3 \"Start Pegasus at boot\")\n            options+=(\n                E \"Manually edit $configdir/all/autostart.sh\"\n            )\n            if [[ \"$__os_id\" == \"Raspbian\" ]]; then\n                options+=(\n                    CL \"Boot to text console (require login)\"\n                    CA \"Boot to text console (auto login as $__user)\"\n                )\n            fi\n            options+=(DL \"Boot to desktop (require login)\")\n            if [[ \"$__os_id\" == \"Raspbian\" ]]; then\n                options+=(DA \"Boot to desktop (auto login as $__user)\")\n            fi\n        fi\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    if isPlatform \"x11\"; then\n                        if [[ \"$x11_autostart\" -eq 0 ]]; then\n                            enable_autostart\n                            printMsgs \"dialog\" \"EmulationStation is set to autostart after login.\"\n                        else\n                            disable_autostart\n                            printMsgs \"dialog\" \"Autostarting of EmulationStation is disabled.\"\n                        fi\n                        x11_autostart=$((x11_autostart ^ 1))\n                    else\n                        enable_autostart\n                        printMsgs \"dialog\" \"EmulationStation is set to launch at boot.\"\n                    fi\n                    ;;\n                2)\n                    enable_autostart kodi\n                    printMsgs \"dialog\" \"Kodi is set to launch at boot.\"\n                    ;;\n                3)\n                    enable_autostart pegasus\n                    printMsgs \"dialog\" \"Pegasus is set to launch at boot.\"\n                    ;;\n                E)\n                    editFile \"$configdir/all/autostart.sh\"\n                    ;;\n                CL)\n                    disable_autostart B1\n                    printMsgs \"dialog\" \"Booting to text console (require login).\"\n                    ;;\n                CA)\n                    disable_autostart B2\n                    printMsgs \"dialog\" \"Booting to text console (auto login as $__user).\"\n                    ;;\n                DL)\n                    disable_autostart B3\n                    printMsgs \"dialog\" \"Booting to desktop (require login).\"\n                    ;;\n                DA)\n                    disable_autostart B4\n                    printMsgs \"dialog\" \"Booting to desktop (auto login as $__user).\"\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/backends.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"backends\"\nrp_module_desc=\"Configure display/driver backends for emulators\"\nrp_module_section=\"config\"\nrp_module_flags=\"!mali !x11\"\n\nfunction _list_backends() {\n    local id=\"$1\"\n    backends=()\n\n    # skip the 'depends' packages\n    [[ ${__mod_info[$id/section]} == \"depends\" ]] && return 1\n\n    local flags=\"${__mod_info[$id/flags]}\"\n    local sdl\n    if isPlatform \"videocore\" && hasFlag \"$flags\" \"sdl1-videocore\"; then\n        sdl=\"sdl1\"\n    elif hasFlag \"$flags\" \"sdl1\" || hasFlag \"$flags\" \"dispmanx\"; then\n        sdl=\"sdl1\"\n    elif hasFlag \"$flags\" \"sdl2\"; then\n        sdl=\"sdl2\"\n    else\n        return 1\n    fi\n\n    local default\n    local sdl_name=\"${sdl^^}\"\n    if [[ \"$sdl\" == \"sdl1\" ]]; then\n        backends[\"default\"]=\"SDL1 Framebuffer driver\"\n        isPlatform \"dispmanx\" && backends[\"dispmanx\"]=\"SDL1 DispmanX driver\"\n        isPlatform \"kms\" && ! isPlatform \"dispmanx\" && backends[\"sdl12-compat\"]=\"SDL1 Compat driver\"\n    elif [[ \"$sdl\" == \"sdl2\" ]]; then\n        if isPlatform \"videocore\"; then\n            default=\"SDL2 videocore driver\"\n        elif isPlatform \"kms\"; then\n            default=\"SDL2 KMS driver\"\n        fi\n        backends[\"default\"]=\"$default\"\n    fi\n    backends[\"x11\"]=\"$sdl_name on Desktop\"\n    backends[\"x11-c\"]=\"$sdl_name on Desktop + Cursor\"\n    return 0\n}\n\nfunction _update_hook_backends() {\n    local dispmanx_cfg=\"$configdir/all/dispmanx.cfg\"\n    local backends_cfg=\"$configdir/all/backends.cfg\"\n    if [[ -f \"$dispmanx_cfg\" ]]; then\n        mv \"$dispmanx_cfg\" \"$backends_cfg\"\n    fi\n}\n\nfunction gui_backends() {\n    declare -A backends\n    local id\n    local backend\n    local default\n    local flags\n    local valid\n    while true; do\n        local options=()\n        for id in \"${__mod_id[@]}\"; do\n            valid=0\n            if rp_isInstalled \"$id\"; then\n                if _list_backends \"$id\" >/dev/null; then\n                    backend=\"$(getBackend \"$id\")\"\n                    options+=(\"$id\" \"Using ${backends[$backend]} ($backend)\")\n                fi\n            fi\n        done\n        local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Configure display/driver backends for emulators\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        default=\"$choice\"\n        gui_configure_backends \"$choice\"\n    done\n}\n\nfunction gui_configure_backends() {\n    local id=\"$1\"\n    declare -A backends\n\n    _list_backends \"$id\"\n\n    while true; do\n        local current=\"$(getBackend \"$id\")\"\n        local options=()\n        local selected\n        local backend\n        local flags\n        for backend in $(echo \"${!backends[@]}\" | xargs -n1 | sort); do\n            selected=\"\"\n            [[ \"$current\" == \"$backend\" ]] && selected=\"(Currently selected)\"\n            options+=(\"$backend\" \"${backends[$backend]} $selected\")\n        done\n        local cmd=(dialog --default-item \"$current\" --backtitle \"$__backtitle\" --menu \"Select backend for $id\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            if [[ \"$choice\" == \"x11\" ]] && ( ! hasPackage \"xorg\" || ! hasPackage \"matchbox-window-manager\" ); then\n                if dialog --defaultno --yesno \"To use the X11/Xorg backend, some additional packages are needed (xorg / matchbox-window-manager) - do you want to continue?\" 22 76 2>&1 >/dev/tty; then\n                    aptInstall xorg matchbox-window-manager\n                else\n                    continue\n                fi\n            fi\n            if [[ \"$choice\" == \"sdl12-compat\" ]] && ! rp_isInstalled \"sdl12-compat\"; then\n                rp_callModule \"sdl12-compat\" _auto_\n            fi\n            local func=\"_backend_set_$id\"\n            if fnExists \"$func\"; then\n                rp_callModule \"$id\" _backend_set \"$choice\" 1\n            else\n                setBackend \"$id\" \"$choice\" 1\n            fi\n        fi\n        break\n    done\n}\n\n\n\n"
  },
  {
    "path": "scriptmodules/supplementary/bashwelcometweak.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"bashwelcometweak\"\nrp_module_desc=\"Bash Welcome Tweak (shows additional system info on login)\"\nrp_module_section=\"config\"\n\nfunction install_bashwelcometweak() {\n    remove_bashwelcometweak\n    cat >> \"$home/.bashrc\" <<\\_EOF_\n# RETROPIE PROFILE START\n\nfunction getIPAddress() {\n    local ip_route\n    ip_route=$(ip -4 route get 8.8.8.8 2>/dev/null)\n    if [[ -z \"$ip_route\" ]]; then\n        ip_route=$(ip -6 route get 2001:4860:4860::8888 2>/dev/null)\n    fi\n    [[ -n \"$ip_route\" ]] && grep -oP \"src \\K[^\\s]+\" <<< \"$ip_route\"\n}\n\nfunction retropie_welcome() {\n    local upSeconds=\"$(/usr/bin/cut -d. -f1 /proc/uptime)\"\n    local secs=$((upSeconds%60))\n    local mins=$((upSeconds/60%60))\n    local hours=$((upSeconds/3600%24))\n    local days=$((upSeconds/86400))\n    local UPTIME=$(printf \"%d days, %02dh%02dm%02ds\" \"$days\" \"$hours\" \"$mins\" \"$secs\")\n\n    # calculate rough CPU and GPU temperatures:\n    local cpuTempC\n    local cpuTempF\n    local gpuTempC\n    local gpuTempF\n    if [[ -f \"/sys/class/thermal/thermal_zone0/temp\" ]]; then\n        cpuTempC=$(($(cat /sys/class/thermal/thermal_zone0/temp)/1000)) && cpuTempF=$((cpuTempC*9/5+32))\n    fi\n\n    if [[ -n $(command -v vcgencmd) ]]; then\n        if gpuTempC=$(vcgencmd measure_temp); then\n            gpuTempC=${gpuTempC:5:2}\n            gpuTempF=$((gpuTempC*9/5+32))\n        else\n            gpuTempC=\"\"\n        fi\n    fi\n\n    local df_out=()\n    local line\n    while read line; do\n        df_out+=(\"$line\")\n    done < <(df -h /)\n\n    local rst=\"$(tput sgr0)\"\n    local fgblk=\"${rst}$(tput setaf 0)\" # Black - Regular\n    local fgred=\"${rst}$(tput setaf 1)\" # Red\n    local fggrn=\"${rst}$(tput setaf 2)\" # Green\n    local fgylw=\"${rst}$(tput setaf 3)\" # Yellow\n    local fgblu=\"${rst}$(tput setaf 4)\" # Blue\n    local fgpur=\"${rst}$(tput setaf 5)\" # Purple\n    local fgcyn=\"${rst}$(tput setaf 6)\" # Cyan\n    local fgwht=\"${rst}$(tput setaf 7)\" # White\n\n    local bld=\"$(tput bold)\"\n    local bfgblk=\"${bld}$(tput setaf 0)\"\n    local bfgred=\"${bld}$(tput setaf 1)\"\n    local bfggrn=\"${bld}$(tput setaf 2)\"\n    local bfgylw=\"${bld}$(tput setaf 3)\"\n    local bfgblu=\"${bld}$(tput setaf 4)\"\n    local bfgpur=\"${bld}$(tput setaf 5)\"\n    local bfgcyn=\"${bld}$(tput setaf 6)\"\n    local bfgwht=\"${bld}$(tput setaf 7)\"\n\n    local logo=(\n        \"${fgred}   .***.   \"\n        \"${fgred}   ***${bfgwht}*${fgred}*   \"\n        \"${fgred}   \\`***'   \"\n        \"${bfgwht}    |*|    \"\n        \"${bfgwht}    |*|    \"\n        \"${bfgred}  ..${bfgwht}|*|${bfgred}..  \"\n        \"${bfgred}.*** ${bfgwht}*${bfgred} ***.\"\n        \"${bfgred}*******${fggrn}@@${bfgred}**\"\n        \"${fgred}\\`*${bfgred}****${bfgylw}@@${bfgred}*${fgred}*'\"\n        \"${fgred} \\`*******'${fgrst} \"\n        \"${fgred}   \\`\\\"\\\"\\\"'${fgrst}   \"\n        )\n\n    local out\n    local i\n    for i in \"${!logo[@]}\"; do\n        out+=\"  ${logo[$i]}  \"\n        case \"$i\" in\n            0)\n                out+=\"${fggrn}$(date +\"%A, %e %B %Y, %X\")\"\n                ;;\n            1)\n                out+=\"${fggrn}$(uname -srmo)\"\n                ;;\n            3)\n                out+=\"${fgylw}${df_out[0]}\"\n                ;;\n            4)\n                out+=\"${fgwht}${df_out[1]}\"\n                ;;\n            5)\n                out+=\"${fgred}Uptime.............: ${UPTIME}\"\n                ;;\n            6)\n                out+=\"${fgred}Memory.............: $(free -h | awk 'NR==2 {printf(\"%s (Free) / %s (Total)\", $4, $2)}')\"\n                ;;\n            7)\n                out+=\"${fgred}Running Processes..: $(ps ax | wc -l | tr -d \" \")\"\n                ;;\n            8)\n                out+=\"${fgred}IP Address.........: $(getIPAddress)\"\n                ;;\n            9)\n                out+=\"Temperature........: CPU: ${cpuTempC}°C/${cpuTempF}°F GPU: ${gpuTempC}°C/${gpuTempF}°F\"\n                ;;\n            10)\n                out+=\"${fgwht}The RetroPie Project, https://retropie.org.uk\"\n                ;;\n        esac\n        out+=\"${rst}\\n\"\n    done\n    echo -e \"\\n$out\"\n}\n\nretropie_welcome\n# RETROPIE PROFILE END\n_EOF_\n\n\n}\n\nfunction remove_bashwelcometweak() {\n    sed -i '/RETROPIE PROFILE START/,/RETROPIE PROFILE END/d' \"$home/.bashrc\"\n}\n\nfunction gui_bashwelcometweak() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Bash Welcome Tweak Configuration\" 22 86 16)\n    local options=(\n        1 \"Install Bash Welcome Tweak\"\n        2 \"Remove Bash Welcome Tweak\"\n    )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                rp_callModule bashwelcometweak install\n                printMsgs \"dialog\" \"Installed Bash Welcome Tweak.\"\n                ;;\n            2)\n                rp_callModule bashwelcometweak remove\n                printMsgs \"dialog\" \"Removed Bash Welcome Tweak.\"\n                ;;\n        esac\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/COPYING",
    "content": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 2, June 1991\n\n Copyright (C) 1989, 1991 Free Software Foundation, Inc.\n                       51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n Everyone is permitted to copy and distribute verbatim copies\n of this license document, but changing it is not allowed.\n\n\t\t\t    Preamble\n\n  The licenses for most software are designed to take away your\nfreedom to share and change it.  By contrast, the GNU General Public\nLicense is intended to guarantee your freedom to share and change free\nsoftware--to make sure the software is free for all its users.  This\nGeneral Public License applies to most of the Free Software\nFoundation's software and to any other program whose authors commit to\nusing it.  (Some other Free Software Foundation software is covered by\nthe GNU Library General Public License instead.)  You can apply it to\nyour programs, too.\n\n  When we speak of free software, we are referring to freedom, not\nprice.  Our General Public Licenses are designed to make sure that you\nhave the freedom to distribute copies of free software (and charge for\nthis service if you wish), that you receive source code or can get it\nif you want it, that you can change the software or use pieces of it\nin new free programs; and that you know you can do these things.\n\n  To protect your rights, we need to make restrictions that forbid\nanyone to deny you these rights or to ask you to surrender the rights.\nThese restrictions translate to certain responsibilities for you if you\ndistribute copies of the software, or if you modify it.\n\n  For example, if you distribute copies of such a program, whether\ngratis or for a fee, you must give the recipients all the rights that\nyou have.  You must make sure that they, too, receive or can get the\nsource code.  And you must show them these terms so they know their\nrights.\n\n  We protect your rights with two steps: (1) copyright the software, and\n(2) offer you this license which gives you legal permission to copy,\ndistribute and/or modify the software.\n\n  Also, for each author's protection and ours, we want to make certain\nthat everyone understands that there is no warranty for this free\nsoftware.  If the software is modified by someone else and passed on, we\nwant its recipients to know that what they have is not the original, so\nthat any problems introduced by others will not reflect on the original\nauthors' reputations.\n\n  Finally, any free program is threatened constantly by software\npatents.  We wish to avoid the danger that redistributors of a free\nprogram will individually obtain patent licenses, in effect making the\nprogram proprietary.  To prevent this, we have made it clear that any\npatent must be licensed for everyone's free use or not licensed at all.\n\n  The precise terms and conditions for copying, distribution and\nmodification follow.\n\n\t\t    GNU GENERAL PUBLIC LICENSE\n   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION\n\n  0. This License applies to any program or other work which contains\na notice placed by the copyright holder saying it may be distributed\nunder the terms of this General Public License.  The \"Program\", below,\nrefers to any such program or work, and a \"work based on the Program\"\nmeans either the Program or any derivative work under copyright law:\nthat is to say, a work containing the Program or a portion of it,\neither verbatim or with modifications and/or translated into another\nlanguage.  (Hereinafter, translation is included without limitation in\nthe term \"modification\".)  Each licensee is addressed as \"you\".\n\nActivities other than copying, distribution and modification are not\ncovered by this License; they are outside its scope.  The act of\nrunning the Program is not restricted, and the output from the Program\nis covered only if its contents constitute a work based on the\nProgram (independent of having been made by running the Program).\nWhether that is true depends on what the Program does.\n\n  1. You may copy and distribute verbatim copies of the Program's\nsource code as you receive it, in any medium, provided that you\nconspicuously and appropriately publish on each copy an appropriate\ncopyright notice and disclaimer of warranty; keep intact all the\nnotices that refer to this License and to the absence of any warranty;\nand give any other recipients of the Program a copy of this License\nalong with the Program.\n\nYou may charge a fee for the physical act of transferring a copy, and\nyou may at your option offer warranty protection in exchange for a fee.\n\n  2. You may modify your copy or copies of the Program or any portion\nof it, thus forming a work based on the Program, and copy and\ndistribute such modifications or work under the terms of Section 1\nabove, provided that you also meet all of these conditions:\n\n    a) You must cause the modified files to carry prominent notices\n    stating that you changed the files and the date of any change.\n\n    b) You must cause any work that you distribute or publish, that in\n    whole or in part contains or is derived from the Program or any\n    part thereof, to be licensed as a whole at no charge to all third\n    parties under the terms of this License.\n\n    c) If the modified program normally reads commands interactively\n    when run, you must cause it, when started running for such\n    interactive use in the most ordinary way, to print or display an\n    announcement including an appropriate copyright notice and a\n    notice that there is no warranty (or else, saying that you provide\n    a warranty) and that users may redistribute the program under\n    these conditions, and telling the user how to view a copy of this\n    License.  (Exception: if the Program itself is interactive but\n    does not normally print such an announcement, your work based on\n    the Program is not required to print an announcement.)\n\nThese requirements apply to the modified work as a whole.  If\nidentifiable sections of that work are not derived from the Program,\nand can be reasonably considered independent and separate works in\nthemselves, then this License, and its terms, do not apply to those\nsections when you distribute them as separate works.  But when you\ndistribute the same sections as part of a whole which is a work based\non the Program, the distribution of the whole must be on the terms of\nthis License, whose permissions for other licensees extend to the\nentire whole, and thus to each and every part regardless of who wrote it.\n\nThus, it is not the intent of this section to claim rights or contest\nyour rights to work written entirely by you; rather, the intent is to\nexercise the right to control the distribution of derivative or\ncollective works based on the Program.\n\nIn addition, mere aggregation of another work not based on the Program\nwith the Program (or with a work based on the Program) on a volume of\na storage or distribution medium does not bring the other work under\nthe scope of this License.\n\n  3. You may copy and distribute the Program (or a work based on it,\nunder Section 2) in object code or executable form under the terms of\nSections 1 and 2 above provided that you also do one of the following:\n\n    a) Accompany it with the complete corresponding machine-readable\n    source code, which must be distributed under the terms of Sections\n    1 and 2 above on a medium customarily used for software interchange; or,\n\n    b) Accompany it with a written offer, valid for at least three\n    years, to give any third party, for a charge no more than your\n    cost of physically performing source distribution, a complete\n    machine-readable copy of the corresponding source code, to be\n    distributed under the terms of Sections 1 and 2 above on a medium\n    customarily used for software interchange; or,\n\n    c) Accompany it with the information you received as to the offer\n    to distribute corresponding source code.  (This alternative is\n    allowed only for noncommercial distribution and only if you\n    received the program in object code or executable form with such\n    an offer, in accord with Subsection b above.)\n\nThe source code for a work means the preferred form of the work for\nmaking modifications to it.  For an executable work, complete source\ncode means all the source code for all modules it contains, plus any\nassociated interface definition files, plus the scripts used to\ncontrol compilation and installation of the executable.  However, as a\nspecial exception, the source code distributed need not include\nanything that is normally distributed (in either source or binary\nform) with the major components (compiler, kernel, and so on) of the\noperating system on which the executable runs, unless that component\nitself accompanies the executable.\n\nIf distribution of executable or object code is made by offering\naccess to copy from a designated place, then offering equivalent\naccess to copy the source code from the same place counts as\ndistribution of the source code, even though third parties are not\ncompelled to copy the source along with the object code.\n\n  4. You may not copy, modify, sublicense, or distribute the Program\nexcept as expressly provided under this License.  Any attempt\notherwise to copy, modify, sublicense or distribute the Program is\nvoid, and will automatically terminate your rights under this License.\nHowever, parties who have received copies, or rights, from you under\nthis License will not have their licenses terminated so long as such\nparties remain in full compliance.\n\n  5. You are not required to accept this License, since you have not\nsigned it.  However, nothing else grants you permission to modify or\ndistribute the Program or its derivative works.  These actions are\nprohibited by law if you do not accept this License.  Therefore, by\nmodifying or distributing the Program (or any work based on the\nProgram), you indicate your acceptance of this License to do so, and\nall its terms and conditions for copying, distributing or modifying\nthe Program or works based on it.\n\n  6. Each time you redistribute the Program (or any work based on the\nProgram), the recipient automatically receives a license from the\noriginal licensor to copy, distribute or modify the Program subject to\nthese terms and conditions.  You may not impose any further\nrestrictions on the recipients' exercise of the rights granted herein.\nYou are not responsible for enforcing compliance by third parties to\nthis License.\n\n  7. If, as a consequence of a court judgment or allegation of patent\ninfringement or for any other reason (not limited to patent issues),\nconditions are imposed on you (whether by court order, agreement or\notherwise) that contradict the conditions of this License, they do not\nexcuse you from the conditions of this License.  If you cannot\ndistribute so as to satisfy simultaneously your obligations under this\nLicense and any other pertinent obligations, then as a consequence you\nmay not distribute the Program at all.  For example, if a patent\nlicense would not permit royalty-free redistribution of the Program by\nall those who receive copies directly or indirectly through you, then\nthe only way you could satisfy both it and this License would be to\nrefrain entirely from distribution of the Program.\n\nIf any portion of this section is held invalid or unenforceable under\nany particular circumstance, the balance of the section is intended to\napply and the section as a whole is intended to apply in other\ncircumstances.\n\nIt is not the purpose of this section to induce you to infringe any\npatents or other property right claims or to contest validity of any\nsuch claims; this section has the sole purpose of protecting the\nintegrity of the free software distribution system, which is\nimplemented by public license practices.  Many people have made\ngenerous contributions to the wide range of software distributed\nthrough that system in reliance on consistent application of that\nsystem; it is up to the author/donor to decide if he or she is willing\nto distribute software through any other system and a licensee cannot\nimpose that choice.\n\nThis section is intended to make thoroughly clear what is believed to\nbe a consequence of the rest of this License.\n\n  8. If the distribution and/or use of the Program is restricted in\ncertain countries either by patents or by copyrighted interfaces, the\noriginal copyright holder who places the Program under this License\nmay add an explicit geographical distribution limitation excluding\nthose countries, so that distribution is permitted only in or among\ncountries not thus excluded.  In such case, this License incorporates\nthe limitation as if written in the body of this License.\n\n  9. The Free Software Foundation may publish revised and/or new versions\nof the General Public License from time to time.  Such new versions will\nbe similar in spirit to the present version, but may differ in detail to\naddress new problems or concerns.\n\nEach version is given a distinguishing version number.  If the Program\nspecifies a version number of this License which applies to it and \"any\nlater version\", you have the option of following the terms and conditions\neither of that version or of any later version published by the Free\nSoftware Foundation.  If the Program does not specify a version number of\nthis License, you may choose any version ever published by the Free Software\nFoundation.\n\n  10. If you wish to incorporate parts of the Program into other free\nprograms whose distribution conditions are different, write to the author\nto ask for permission.  For software which is copyrighted by the Free\nSoftware Foundation, write to the Free Software Foundation; we sometimes\nmake exceptions for this.  Our decision will be guided by the two goals\nof preserving the free status of all derivatives of our free software and\nof promoting the sharing and reuse of software generally.\n\n\t\t\t    NO WARRANTY\n\n  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\nFOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\nOTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\nPROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\nOR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\nTO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\nPROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\nREPAIR OR CORRECTION.\n\n  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\nWILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\nREDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\nINCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\nOUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\nTO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\nYOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\nPROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGES.\n\n\t\t     END OF TERMS AND CONDITIONS\n\n\t    How to Apply These Terms to Your New Programs\n\n  If you develop a new program, and you want it to be of the greatest\npossible use to the public, the best way to achieve this is to make it\nfree software which everyone can redistribute and change under these terms.\n\n  To do so, attach the following notices to the program.  It is safest\nto attach them to the start of each source file to most effectively\nconvey the exclusion of warranty; and each file should have at least\nthe \"copyright\" line and a pointer to where the full notice is found.\n\n    <one line to give the program's name and a brief idea of what it does.>\n    Copyright (C) <year>  <name of author>\n\n    This program is free software; you can redistribute it and/or modify\n    it under the terms of the GNU General Public License as published by\n    the Free Software Foundation; either version 2 of the License, or\n    (at your option) any later version.\n\n    This program is distributed in the hope that it will be useful,\n    but WITHOUT ANY WARRANTY; without even the implied warranty of\n    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n    GNU General Public License for more details.\n\n    You should have received a copy of the GNU General Public License\n    along with this program; if not, write to the Free Software\n    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA\n\n\nAlso add information on how to contact you by electronic and paper mail.\n\nIf the program is interactive, make it output a short notice like this\nwhen it starts in an interactive mode:\n\n    Gnomovision version 69, Copyright (C) year name of author\n    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.\n    This is free software, and you are welcome to redistribute it\n    under certain conditions; type `show c' for details.\n\nThe hypothetical commands `show w' and `show c' should show the appropriate\nparts of the General Public License.  Of course, the commands you use may\nbe called something other than `show w' and `show c'; they could even be\nmouse-clicks or menu items--whatever suits your program.\n\nYou should also get your employer (if you work as a programmer) or your\nschool, if any, to sign a \"copyright disclaimer\" for the program, if\nnecessary.  Here is a sample; alter the names:\n\n  Yoyodyne, Inc., hereby disclaims all copyright interest in the program\n  `Gnomovision' (which makes passes at compilers) written by James Hacker.\n\n  <signature of Ty Coon>, 1 April 1989\n  Ty Coon, President of Vice\n\nThis General Public License does not permit incorporating your program into\nproprietary programs.  If your program is a subroutine library, you may\nconsider it more useful to permit linking proprietary applications with the\nlibrary.  If this is what you want to do, use the GNU Library General\nPublic License instead of this License.\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/bluez-simple-agent",
    "content": "#!/usr/bin/python3\n\nfrom optparse import OptionParser\nimport sys\nimport dbus\nimport dbus.service\nimport dbus.mainloop.glib\nfrom gi.repository import GLib\n\nimport bluezutils\n\nBUS_NAME = 'org.bluez'\nAGENT_INTERFACE = 'org.bluez.Agent1'\nAGENT_PATH = \"/test/agent\"\n\nbus = None\ndevice_obj = None\ndev_path = None\n\ndef ask(prompt):\n\ttry:\n\t\treturn raw_input(prompt)\n\texcept:\n\t\treturn input(prompt)\n\ndef set_trusted(path):\n\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\tprops.Set(\"org.bluez.Device1\", \"Trusted\", True)\n\ndef dev_connect(path):\n\tdev = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\t\t\"org.bluez.Device1\")\n\tdev.Connect()\n\nclass Rejected(dbus.DBusException):\n\t_dbus_error_name = \"org.bluez.Error.Rejected\"\n\nclass Agent(dbus.service.Object):\n\texit_on_release = True\n\n\tdef set_exit_on_release(self, exit_on_release):\n\t\tself.exit_on_release = exit_on_release\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"\", out_signature=\"\")\n\tdef Release(self):\n\t\tprint(\"Release\")\n\t\tif self.exit_on_release:\n\t\t\tmainloop.quit()\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"os\", out_signature=\"\")\n\tdef AuthorizeService(self, device, uuid):\n\t\tprint(\"AuthorizeService (%s, %s)\" % (device, uuid))\n\t\tauthorize = ask(\"Authorize connection (yes/no): \")\n\t\tif (authorize == \"yes\"):\n\t\t\treturn\n\t\traise Rejected(\"Connection rejected by user\")\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"o\", out_signature=\"s\")\n\tdef RequestPinCode(self, device):\n\t\tprint(\"RequestPinCode (%s)\" % (device))\n\t\tset_trusted(device)\n\t\treturn ask(\"Enter PIN Code: \")\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"o\", out_signature=\"u\")\n\tdef RequestPasskey(self, device):\n\t\tprint(\"RequestPasskey (%s)\" % (device))\n\t\tset_trusted(device)\n\t\tpasskey = ask(\"Enter passkey: \")\n\t\treturn dbus.UInt32(passkey)\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"ouq\", out_signature=\"\")\n\tdef DisplayPasskey(self, device, passkey, entered):\n\t\tprint(\"DisplayPasskey (%s, %06u entered %u)\" %\n\t\t\t\t\t\t(device, passkey, entered))\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"os\", out_signature=\"\")\n\tdef DisplayPinCode(self, device, pincode):\n\t\tprint(\"DisplayPinCode (%s, %s)\" % (device, pincode))\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"ou\", out_signature=\"\")\n\tdef RequestConfirmation(self, device, passkey):\n\t\tprint(\"RequestConfirmation (%s, %06d)\" % (device, passkey))\n\t\tconfirm = ask(\"Confirm passkey (yes/no): \")\n\t\tif (confirm == \"yes\"):\n\t\t\tset_trusted(device)\n\t\t\treturn\n\t\traise Rejected(\"Passkey doesn't match\")\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"o\", out_signature=\"\")\n\tdef RequestAuthorization(self, device):\n\t\tprint(\"RequestAuthorization (%s)\" % (device))\n\t\tauth = ask(\"Authorize? (yes/no): \")\n\t\tif (auth == \"yes\"):\n\t\t\treturn\n\t\traise Rejected(\"Pairing rejected\")\n\n\t@dbus.service.method(AGENT_INTERFACE,\n\t\t\t\t\tin_signature=\"\", out_signature=\"\")\n\tdef Cancel(self):\n\t\tprint(\"Cancel\")\n\ndef pair_reply():\n\tprint(\"Device paired\")\n\tset_trusted(dev_path)\n\tdev_connect(dev_path)\n\tmainloop.quit()\n\ndef pair_error(error):\n\terr_name = error.get_dbus_name()\n\tif err_name == \"org.freedesktop.DBus.Error.NoReply\" and device_obj:\n\t\tprint(\"Timed out. Cancelling pairing\")\n\t\tdevice_obj.CancelPairing()\n\telse:\n\t\tprint(\"Creating device failed: %s\" % (error))\n\n\n\tmainloop.quit()\n\nif __name__ == '__main__':\n\tdbus.mainloop.glib.DBusGMainLoop(set_as_default=True)\n\n\tbus = dbus.SystemBus()\n\n\tcapability = \"KeyboardDisplay\"\n\n\tparser = OptionParser()\n\tparser.add_option(\"-i\", \"--adapter\", action=\"store\",\n\t\t\t\t\ttype=\"string\",\n\t\t\t\t\tdest=\"adapter_pattern\",\n\t\t\t\t\tdefault=None)\n\tparser.add_option(\"-c\", \"--capability\", action=\"store\",\n\t\t\t\t\ttype=\"string\", dest=\"capability\")\n\tparser.add_option(\"-t\", \"--timeout\", action=\"store\",\n\t\t\t\t\ttype=\"int\", dest=\"timeout\",\n\t\t\t\t\tdefault=60000)\n\t(options, args) = parser.parse_args()\n\tif options.capability:\n\t\tcapability  = options.capability\n\n\tpath = \"/test/agent\"\n\tagent = Agent(bus, path)\n\n\tmainloop = GLib.MainLoop()\n\n\tobj = bus.get_object(BUS_NAME, \"/org/bluez\");\n\tmanager = dbus.Interface(obj, \"org.bluez.AgentManager1\")\n\tmanager.RegisterAgent(path, capability)\n\n\tprint(\"Agent registered\")\n\n\t# Fix-up old style invocation (BlueZ 4)\n\tif len(args) > 0 and args[0].startswith(\"hci\"):\n\t\toptions.adapter_pattern = args[0]\n\t\tdel args[:1]\n\n\tif len(args) > 0:\n\t\tdevice = bluezutils.find_device(args[0],\n\t\t\t\t\t\toptions.adapter_pattern)\n\t\tdev_path = device.object_path\n\t\tagent.set_exit_on_release(False)\n\t\tdevice.Pair(reply_handler=pair_reply, error_handler=pair_error,\n\t\t\t\t\t\t\t\ttimeout=60000)\n\t\tdevice_obj = device\n\telse:\n\t\tmanager.RequestDefaultAgent(path)\n\n\tmainloop.run()\n\n\t#adapter.UnregisterAgent(path)\n\t#print(\"Agent unregistered\")\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/bluez-test-device",
    "content": "#!/usr/bin/python3\n\nfrom optparse import OptionParser, make_option\nimport re\nimport sys\nimport dbus\nimport dbus.mainloop.glib\nfrom gi.repository import GLib\n\nimport bluezutils\n\ndbus.mainloop.glib.DBusGMainLoop(set_as_default=True)\nbus = dbus.SystemBus()\nmainloop = GLib.MainLoop()\n\noption_list = [\n\t\tmake_option(\"-i\", \"--device\", action=\"store\",\n\t\t\t\ttype=\"string\", dest=\"dev_id\"),\n\t\t]\nparser = OptionParser(option_list=option_list)\n\n(options, args) = parser.parse_args()\n\nif (len(args) < 1):\n\tprint(\"Usage: %s <command>\" % (sys.argv[0]))\n\tprint(\"\")\n\tprint(\"  list\")\n\tprint(\"  create <address>\")\n\tprint(\"  remove <address|path>\")\n\tprint(\"  connect <address> [profile]\")\n\tprint(\"  disconnect <address> [profile]\")\n\tprint(\"  class <address>\")\n\tprint(\"  name <address>\")\n\tprint(\"  alias <address> [alias]\")\n\tprint(\"  trusted <address> [yes/no]\")\n\tprint(\"  blocked <address> [yes/no]\")\n\tsys.exit(1)\n\nif (args[0] == \"list\"):\n\tadapter = bluezutils.find_adapter(options.dev_id)\n\tadapter_path = adapter.object_path\n\n\tom = dbus.Interface(bus.get_object(\"org.bluez\", \"/\"),\n\t\t\t\t\t\"org.freedesktop.DBus.ObjectManager\")\n\tobjects = om.GetManagedObjects()\n\n\tfor path, interfaces in objects.items():\n\t\tif \"org.bluez.Device1\" not in interfaces:\n\t\t\tcontinue\n\t\tproperties = interfaces[\"org.bluez.Device1\"]\n\t\tif properties[\"Adapter\"] != adapter_path:\n\t\t\tcontinue;\n\t\tdevice_string = \"%s %s\" % (properties[\"Address\"], properties[\"Alias\"])\n\t\tprint(device_string.encode('ascii', 'ignore'))\n\n\tsys.exit(0)\n\ndef create_device_reply(device):\n\tprint(\"New device (%s)\" % device)\n\tmainloop.quit()\n\tsys.exit(0)\n\ndef create_device_error(error):\n\tprint(\"Creating device failed: %s\" % error)\n\tmainloop.quit()\n\tsys.exit(1)\n\nif (args[0] == \"create\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tadapter = bluezutils.find_adapter(options.dev_id)\n\t\tadapter.CreateDevice(args[1],\n\t\t\t\treply_handler=create_device_reply,\n\t\t\t\terror_handler=create_device_error)\n\tmainloop.run()\n\nif (args[0] == \"remove\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address or object path parameter\")\n\telse:\n\t\tmanaged_objects = bluezutils.get_managed_objects()\n\t\tadapter = bluezutils.find_adapter_in_objects(managed_objects,\n\t\t\t\t\t\t\t\toptions.dev_id)\n\t\ttry:\n\t\t\tdev = bluezutils.find_device_in_objects(managed_objects,\n\t\t\t\t\t\t\t\targs[1],\n\t\t\t\t\t\t\t\toptions.dev_id)\n\t\t\tpath = dev.object_path\n\t\texcept:\n\t\t\tpath = args[1]\n\t\tadapter.RemoveDevice(path)\n\tsys.exit(0)\n\nif (args[0] == \"connect\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tif (len(args) > 2):\n\t\t\tdevice.ConnectProfile(args[2])\n\t\telse:\n\t\t\tdevice.Connect()\n\tsys.exit(0)\n\nif (args[0] == \"disconnect\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tif (len(args) > 2):\n\t\t\tdevice.DisconnectProfile(args[2])\n\t\telse:\n\t\t\tdevice.Disconnect()\n\tsys.exit(0)\n\nif (args[0] == \"class\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tpath = device.object_path\n\t\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\t\tcls = props.Get(\"org.bluez.Device1\", \"Class\")\n\t\tprint(\"0x%06x\" % cls)\n\tsys.exit(0)\n\nif (args[0] == \"name\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tpath = device.object_path\n\t\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\t\tname = props.Get(\"org.bluez.Device1\", \"Name\")\n\t\tprint(name)\n\tsys.exit(0)\n\nif (args[0] == \"alias\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tpath = device.object_path\n\t\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\t\tif (len(args) < 3):\n\t\t\talias = props.Get(\"org.bluez.Device1\", \"Alias\")\n\t\t\tprint(alias)\n\t\telse:\n\t\t\tprops.Set(\"org.bluez.Device1\", \"Alias\", args[2])\n\tsys.exit(0)\n\nif (args[0] == \"trusted\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tpath = device.object_path\n\t\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\t\tif (len(args) < 3):\n\t\t\ttrusted = props.Get(\"org.bluez.Device1\", \"Trusted\")\n\t\t\tprint(trusted)\n\t\telse:\n\t\t\tif (args[2] == \"yes\"):\n\t\t\t\tvalue = dbus.Boolean(1)\n\t\t\telif (args[2] == \"no\"):\n\t\t\t\tvalue = dbus.Boolean(0)\n\t\t\telse:\n\t\t\t\tvalue = dbus.Boolean(args[2])\n\t\t\tprops.Set(\"org.bluez.Device1\", \"Trusted\", value)\n\tsys.exit(0)\n\nif (args[0] == \"blocked\"):\n\tif (len(args) < 2):\n\t\tprint(\"Need address parameter\")\n\telse:\n\t\tdevice = bluezutils.find_device(args[1], options.dev_id)\n\t\tpath = device.object_path\n\t\tprops = dbus.Interface(bus.get_object(\"org.bluez\", path),\n\t\t\t\t\t\"org.freedesktop.DBus.Properties\")\n\t\tif (len(args) < 3):\n\t\t\tblocked = props.Get(\"org.bluez.Device1\", \"Blocked\")\n\t\t\tprint(blocked)\n\t\telse:\n\t\t\tif (args[2] == \"yes\"):\n\t\t\t\tvalue = dbus.Boolean(1)\n\t\t\telif (args[2] == \"no\"):\n\t\t\t\tvalue = dbus.Boolean(0)\n\t\t\telse:\n\t\t\t\tvalue = dbus.Boolean(args[2])\n\t\t\tprops.Set(\"org.bluez.Device1\", \"Blocked\", value)\n\tsys.exit(0)\n\nprint(\"Unknown command\")\nsys.exit(1)\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/bluezutils.py",
    "content": "import dbus\n\nSERVICE_NAME = \"org.bluez\"\nADAPTER_INTERFACE = SERVICE_NAME + \".Adapter1\"\nDEVICE_INTERFACE = SERVICE_NAME + \".Device1\"\n\ndef get_managed_objects():\n\tbus = dbus.SystemBus()\n\tmanager = dbus.Interface(bus.get_object(\"org.bluez\", \"/\"),\n\t\t\t\t\"org.freedesktop.DBus.ObjectManager\")\n\treturn manager.GetManagedObjects()\n\ndef find_adapter(pattern=None):\n\treturn find_adapter_in_objects(get_managed_objects(), pattern)\n\ndef find_adapter_in_objects(objects, pattern=None):\n\tbus = dbus.SystemBus()\n\tfor path, ifaces in objects.items():\n\t\tadapter = ifaces.get(ADAPTER_INTERFACE)\n\t\tif adapter is None:\n\t\t\tcontinue\n\t\tif not pattern or pattern == adapter[\"Address\"] or \\\n\t\t\t\t\t\t\tpath.endswith(pattern):\n\t\t\tobj = bus.get_object(SERVICE_NAME, path)\n\t\t\treturn dbus.Interface(obj, ADAPTER_INTERFACE)\n\traise Exception(\"Bluetooth adapter not found\")\n\ndef find_device(device_address, adapter_pattern=None):\n\treturn find_device_in_objects(get_managed_objects(), device_address,\n\t\t\t\t\t\t\t\tadapter_pattern)\n\ndef find_device_in_objects(objects, device_address, adapter_pattern=None):\n\tbus = dbus.SystemBus()\n\tpath_prefix = \"\"\n\tif adapter_pattern:\n\t\tadapter = find_adapter_in_objects(objects, adapter_pattern)\n\t\tpath_prefix = adapter.object_path\n\tfor path, ifaces in objects.items():\n\t\tdevice = ifaces.get(DEVICE_INTERFACE)\n\t\tif device is None:\n\t\t\tcontinue\n\t\tif (device[\"Address\"] == device_address and\n\t\t\t\t\t\tpath.startswith(path_prefix)):\n\t\t\tobj = bus.get_object(SERVICE_NAME, path)\n\t\t\treturn dbus.Interface(obj, DEVICE_INTERFACE)\n\n\traise Exception(\"Bluetooth device not found\")\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/connect.sh",
    "content": "#!/usr/bin/env bash\nconfigdir=\"CONFIGDIR\"\n\nsource \"ROOTDIR/lib/inifuncs.sh\"\n\nmode=\"$1\"\nif [[ -z \"$mode\" ]]; then\n    iniConfig \"=\" '\"' \"$configdir/all/bluetooth.cfg\"\n    iniGet \"connect_mode\"\n    [[ -n \"$ini_value\" ]] && mode=\"$ini_value\"\nfi\n\nfunction connect() {\n    local line\n    local mac\n    local conn\n    while read line; do\n        if [[ \"$line\" =~ ^(.+)\\ \\((.+)\\)$ ]]; then\n            mac=\"${BASH_REMATCH[2]}\"\n            conn=$(bt-device -i \"$mac\" | grep \"Connected:\" | tail -c 2 2>/dev/null)\n            [[ \"$conn\" -eq 0 ]] && bt-device --connect \"$mac\" &>/dev/null\n        fi\n    done < <(bt-device --list)\n}\n\ncase \"$mode\" in\n    boot)\n        connect\n        ;;\n    background)\n        while true; do\n            connect\n            sleep 10\n        done\nesac\n\nexit 0\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth/readme.txt",
    "content": "these files are included from http://git.kernel.org/cgit/bluetooth/bluez.git/tree/test\n\n"
  },
  {
    "path": "scriptmodules/supplementary/bluetooth.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"bluetooth\"\nrp_module_desc=\"Configure Bluetooth Devices\"\nrp_module_section=\"config\"\n\nfunction _update_hook_bluetooth() {\n    # fix config location\n    [[ -f \"$configdir/bluetooth.cfg\" ]] && mv \"$configdir/bluetooth.cfg\" \"$configdir/all/bluetooth.cfg\"\n    local mode=\"$(_get_connect_mode)\"\n    # if user has set bluetooth connect mode to boot or background, make sure we\n    # have the latest dependencies and update systemd script\n    if [[ \"$mode\" != \"default\" ]]; then\n        # make sure dependencies are up to date\n        ! hasPackage \"bluez-tools\" && depends_bluetooth\n        connect_mode_set_bluetooth \"$mode\"\n    fi\n}\n\nfunction _get_connect_mode() {\n    # get bluetooth config\n    iniConfig \"=\" '\"' \"$configdir/all/bluetooth.cfg\"\n    iniGet \"connect_mode\"\n    if [[ -n \"$ini_value\" ]]; then\n        echo \"$ini_value\"\n    else\n        echo \"default\"\n    fi\n}\n\nfunction depends_bluetooth() {\n    local depends=(bluetooth python3-dbus python3-gi bluez-tools)\n    if [[ \"$__os_id\" == \"Raspbian\" ]]; then\n        depends+=(pi-bluetooth raspberrypi-sys-mods)\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction get_script_bluetooth() {\n    name=\"$1\"\n    if ! which \"$name\"; then\n        [[ \"$name\" == \"bluez-test-input\" ]] && name=\"bluez-test-device\"\n        name=\"$md_data/$name\"\n    fi\n    echo \"$name\"\n}\n\nfunction _slowecho_bluetooth() {\n    local line\n\n    IFS=$'\\n'\n    for line in $(echo -e \"${1}\"); do\n        echo -e \"$line\"\n        sleep 1\n    done\n    unset IFS\n}\n\nfunction bluez_cmd_bluetooth() {\n    # create a named pipe & fd for input for bluetoothctl\n    local fifo=\"$(mktemp -u)\"\n    mkfifo \"$fifo\"\n    exec 3<>\"$fifo\"\n    local line\n    while true; do\n        _slowecho_bluetooth \"$1\" >&3\n        # collect output for specified amount of time, then echo it\n        while read -r line; do\n            printf '%s\\n' \"$line\"\n            # (slow) reply to any optional challenges\n            if [[ -n \"$3\" && \"$line\" =~ $3 ]]; then\n                _slowecho_bluetooth \"$4\" >&3\n            fi\n        done\n        _slowecho_bluetooth \"quit\\n\" >&3\n        break\n    # read from bluetoothctl buffered line by line\n    done < <(timeout \"$2\" stdbuf -oL bluetoothctl --agent=NoInputNoOutput <&3)\n    exec 3>&-\n}\n\nfunction list_available_bluetooth() {\n    local mac\n    local name\n    local info_text=\"\\n\\nSearching ...\"\n\n    declare -A paired=()\n    declare -A found=()\n\n    # get an asc array of paired mac addresses\n    while read mac; read name; do\n        paired+=([\"$mac\"]=\"$name\")\n    done < <(list_paired_bluetooth)\n\n    # sixaxis: add USB pairing information\n    [[ -n \"$(lsmod | grep hid_sony)\" ]] && info_text=\"Searching ...\\n\\nDualShock registration: while this text is visible, unplug the controller, press the PS/SHARE button, and then replug the controller.\"\n    # sixaxis: configure workaround for PS3 when we detect one\n    if cat /proc/bus/input/devices | grep Name | grep -qE \"(Sony )?PLAY.*3\" ; then\n        _bonded_fix_bluetooth \"add\"\n        systemctl -q is-active bluetooth.service && systemctl restart bluetooth.service\n    fi\n\n    dialog --backtitle \"$__backtitle\" --infobox \"$info_text\" 7 60 >/dev/tty\n    if hasPackage bluez 5; then\n        # sixaxis: reply to authorization challenge on USB cable connect\n        while read mac; read name; do\n            found+=([\"$mac\"]=\"$name\")\n       done < <(bluez_cmd_bluetooth \"default-agent\\nscan on\" \"15\" \"Authorize service$\" \"yes\" >/dev/null; bluez_cmd_bluetooth \"devices\" \"3\" | grep \"^Device \" | cut -d\" \" -f2,3- | sed 's/ /\\n/')\n    else\n        while read; read mac; read name; do\n            found+=([\"$mac\"]=\"$name\")\n        done < <(hcitool scan --flush | tail -n +2 | sed 's/\\t/\\n/g')\n    fi\n\n    # display any found addresses that are not already paired\n    for mac in \"${!found[@]}\"; do\n        if [[ -z \"${paired[$mac]}\" ]]; then\n            echo \"$mac\"\n            echo \"${found[$mac]}\"\n        fi\n    done\n}\n\nfunction list_registered_bluetooth() {\n    local line\n    while read line; do\n        if [[ \"$line\" =~ ^(.+)\\ \\((.+)\\)$ ]]; then\n            echo ${BASH_REMATCH[2]}\n            echo ${BASH_REMATCH[1]}\n        fi\n    done < <(bt-device --list 2>/dev/null)\n}\n\nfunction _devices_grep_bluetooth() {\n    declare -A devices=()\n    local pattern=\"$1\"\n\n    local mac\n    local name\n    while read mac; read name; do\n        if bt-device --info \"$mac\" 2>/dev/null | grep -q \"$pattern\"; then\n            echo \"$mac\"\n            echo \"$name\"\n        fi\n    done < <(list_registered_bluetooth)\n}\n\nfunction list_paired_bluetooth() {\n    _devices_grep_bluetooth \"Paired: 1\"\n}\n\nfunction list_connected_bluetooth() {\n    _devices_grep_bluetooth \"Connected: 1\"\n}\n\nfunction status_bluetooth() {\n    local paired\n    local connected\n\n    local mac\n    local name\n\n    while read mac; read name; do\n        paired+=\"$mac - $name\\n\"\n    done < <(list_paired_bluetooth)\n    [[ -z \"$paired\" ]] && paired=\"There are no paired devices\"\n\n    while read mac; read name; do\n        connected+=\"$mac - $name\\n\"\n    done < <(list_connected_bluetooth)\n    [[ -z \"$connected\" ]] && connected=\"There are no connected devices\"\n\n    echo -e \"Paired Devices:\\n\\n$paired\\nConnected Devices:\\n\\n$connected\"\n}\n\nfunction remove_device_bluetooth() {\n    declare -A devices=()\n    local mac\n    local name\n\n    local options=()\n\n    # show paired devices first\n    while read mac; read name; do\n        devices+=([\"$mac\"]=\"$name\")\n        options+=(\"$mac\" \"$name\")\n    done < <(list_paired_bluetooth)\n\n    # then list all other devices known\n    while read mac; read name; do\n        if [[ -z \"${devices[$mac]}\" ]]; then\n            devices+=([\"$mac\"]=\"$name\")\n            options+=(\"$mac\" \"$name\")\n        fi\n    done < <(list_registered_bluetooth)\n\n    if [[ ${#devices[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"There are no devices to remove.\"\n    else\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please choose the bluetooth device you would like to remove\" 22 76 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && return\n\n        local out\n        out=$(bt-device --remove \"$choice\" 2>&1)\n        if [[ \"$?\" -eq 0 ]] ; then\n            printMsgs \"dialog\" \"Device ${devices[$choice]} removed\"\n            # remove Bluez workaround if it's the last PS3 device\n            if [[ \"${devices[$choice]}\" == *PLAY*3* ]]; then\n                list_paired_bluetooth | grep -qE \"(Sony )?PLAY.*3\"\n                [[ ! $? -eq 0 ]] && _bonded_fix_bluetooth \"remove\"\n            fi\n        else\n            printMsgs \"dialog\" \"Error removing device:\\n\\n$out\"\n        fi\n    fi\n}\n\nfunction pair_bluetooth() {\n    declare -A devices=()\n    local mac\n    local name\n    local options=()\n\n    while read mac; read name; do\n        devices+=([\"$mac\"]=\"$name\")\n        options+=(\"$mac\" \"$name\")\n    done < <(list_available_bluetooth)\n\n    if [[ ${#devices[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"No devices were found. Ensure device is on and try again\"\n        return\n    fi\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please choose the bluetooth device you would like to connect to\" 22 76 16)\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n\n    mac=\"$choice\"\n    name=\"${devices[$choice]}\"\n\n    if [[ \"$name\" =~ \"PLAYSTATION(R)3 Controller\" ]]; then\n        bt-device --disconnect=\"$mac\" >/dev/null\n        bt-device --set \"$mac\" Trusted 1 >/dev/null\n        if [[ \"$?\" -eq 0 ]]; then\n            printMsgs \"dialog\" \"Successfully authenticated $name ($mac).\\n\\nYou can now remove the USB cable.\"\n        else\n            printMsgs \"dialog\" \"Unable to authenticate $name ($mac).\\n\\nPlease try to pair the device again, making sure to follow the on-screen steps exactly.\"\n        fi\n        return\n    fi\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please choose the security mode - Try the first one, then second if that fails\" 22 76 16)\n    options=(\n        1 \"DisplayYesNo\"\n        2 \"KeyboardDisplay\"\n        3 \"NoInputNoOutput\"\n        4 \"DisplayOnly\"\n        5 \"KeyboardOnly\"\n    )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n\n    local mode=\"${options[choice*2-1]}\"\n\n    # create a named pipe & fd for input for bluez-simple-agent\n    local fifo=\"$(mktemp -u)\"\n    mkfifo \"$fifo\"\n    exec 3<>\"$fifo\"\n    local line\n    local pin\n    local error=\"\"\n    local skip_connect=0\n    while read -r line; do\n        case \"$line\" in\n            \"RequestPinCode\"*)\n                cmd=(dialog --nocancel --backtitle \"$__backtitle\" --menu \"Please choose a pin\" 22 76 16)\n                options=(\n                    1 \"Pin 0000\"\n                    2 \"Enter own Pin\"\n                )\n                choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n                pin=\"0000\"\n                if [[ \"$choice\" == \"2\" ]]; then\n                    pin=$(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter a pin\" 10 60 2>&1 >/dev/tty)\n                fi\n                dialog --backtitle \"$__backtitle\" --infobox \"Please enter pin $pin on your bluetooth device\" 10 60\n                echo \"$pin\" >&3\n                # read \"Enter PIN Code:\"\n                read -n 15 line\n                ;;\n            \"RequestConfirmation\"*)\n                # read \"Confirm passkey (yes/no): \"\n                echo \"yes\" >&3\n                read -n 26 line\n                skip_connect=1\n                break\n                ;;\n            \"DisplayPasskey\"*|\"DisplayPinCode\"*)\n                # extract key from end of line\n                # DisplayPasskey (/org/bluez/1284/hci0/dev_01_02_03_04_05_06, 123456)\n                [[ \"$line\" =~ ,\\ (.+)\\) ]] && pin=${BASH_REMATCH[1]}\n                dialog --backtitle \"$__backtitle\" --infobox \"Please enter pin $pin on your bluetooth device\" 10 60\n                ;;\n            \"Creating device failed\"*)\n                error=\"$line\"\n                ;;\n        esac\n    # read from bluez-simple-agent buffered line by line\n    done < <(stdbuf -oL $(get_script_bluetooth bluez-simple-agent) -c \"$mode\" hci0 \"$mac\" <&3)\n    exec 3>&-\n    rm -f \"$fifo\"\n\n    if [[ \"$skip_connect\" -eq 1 ]]; then\n        if hcitool con | grep -q \"$mac\"; then\n            printMsgs \"dialog\" \"Successfully paired and connected to $mac\"\n            return 0\n        else\n            printMsgs \"dialog\" \"Unable to connect to bluetooth device. Please try pairing with the commandline tool 'bluetoothctl'\"\n            return 1\n        fi\n    fi\n\n    if [[ -z \"$error\" ]]; then\n        error=$(bt-device --set \"$mac\" Trusted 1 2>&1)\n        if [[ \"$?\" -eq 0 ]] ; then\n            return 0\n        fi\n    fi\n\n    printMsgs \"dialog\" \"An error occurred connecting to the bluetooth device ($error)\"\n    return 1\n}\n\nfunction udev_bluetooth() {\n    declare -A devices=()\n    local mac\n    local name\n    local options=()\n    while read mac; read name; do\n        devices+=([\"$mac\"]=\"$name\")\n        options+=(\"$mac\" \"$name\")\n    done < <(list_paired_bluetooth)\n\n    if [[ ${#devices[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"There are no paired bluetooth devices.\"\n    else\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please choose the bluetooth device you would like to create a udev rule for\" 22 76 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && return\n        name=\"${devices[$choice]}\"\n        local config=\"/etc/udev/rules.d/99-bluetooth.rules\"\n        if ! grep -q \"$name\" \"$config\"; then\n            local line=\"SUBSYSTEM==\\\"input\\\", ATTRS{name}==\\\"$name\\\", MODE=\\\"0666\\\", ENV{ID_INPUT_JOYSTICK}=\\\"1\\\"\"\n            addLineToFile \"$line\" \"$config\"\n            printMsgs \"dialog\" \"Added $line to $config\\n\\nPlease reboot for the configuration to take effect.\"\n        else\n            printMsgs \"dialog\" \"An entry already exists for $name in $config\"\n        fi\n    fi\n}\n\nfunction connect_bluetooth() {\n    local mac\n    local name\n    while read mac; read name; do\n        bt-device --connect \"$mac\" 2>/dev/null\n    done < <(list_paired_bluetooth)\n}\n\nfunction connect_mode_gui_bluetooth() {\n    local mode=\"$(_get_connect_mode)\"\n    [[ -z \"$mode\" ]] && mode=\"default\"\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$mode\" --menu \"Choose a connect mode\" 22 76 16)\n\n    local options=(\n        default \"Bluetooth stack default behaviour (recommended)\"\n        boot \"Connect to devices once at boot\"\n        background \"Force connecting to devices in the background\"\n    )\n\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -n \"$choice\" ]] && connect_mode_set_bluetooth \"$choice\"\n}\n\nfunction connect_mode_set_bluetooth() {\n    local mode=\"$1\"\n    [[ -z \"$mode\" ]] && mode=\"default\"\n\n    local config=\"/etc/systemd/system/connect-bluetooth.service\"\n    case \"$mode\" in\n        boot|background)\n            mkdir -p \"$md_inst\"\n            sed -e \"s#CONFIGDIR#$configdir#\" -e \"s#ROOTDIR#$rootdir#\" \"$md_data/connect.sh\" >\"$md_inst/connect.sh\"\n            chmod a+x \"$md_inst/connect.sh\"\n            cat > \"$config\" << _EOF_\n[Unit]\nDescription=Connect Bluetooth\n\n[Service]\nType=simple\nExecStart=nice -n19 \"$md_inst/connect.sh\"\n\n[Install]\nWantedBy=multi-user.target\n_EOF_\n            systemctl enable \"$config\"\n            ;;\n        default)\n            if systemctl is-enabled connect-bluetooth 2>/dev/null | grep -q \"enabled\"; then\n               systemctl disable \"$config\"\n            fi\n            rm -f \"$config\"\n            rm -rf \"$md_inst\"\n            ;;\n    esac\n    iniConfig \"=\" '\"' \"$configdir/all/bluetooth.cfg\"\n    iniSet \"connect_mode\" \"$mode\"\n    chown \"$__user\":\"$__group\" \"$configdir/all/bluetooth.cfg\"\n}\n\nfunction gui_bluetooth() {\n    addAutoConf \"8bitdo_hack\" 0\n\n    while true; do\n        local connect_mode=\"$(_get_connect_mode)\"\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Configure Bluetooth Devices\" 22 76 16)\n        local options=(\n            P \"Pair and Connect to Bluetooth Device\"\n            X \"Remove Bluetooth Device\"\n            S \"Show Paired & Connected Bluetooth Devices\"\n            U \"Set up udev rule for Joypad (required for joypads from 8Bitdo etc)\"\n            C \"Connect now to all paired devices\"\n            M \"Configure bluetooth connect mode (currently: $connect_mode)\"\n        )\n\n        local atebitdo\n        if getAutoConf 8bitdo_hack; then\n            atebitdo=1\n            options+=(8 \"8Bitdo mapping hack (ON - old firmware)\")\n        else\n            atebitdo=0\n            options+=(8 \"8Bitdo mapping hack (OFF - new firmware)\")\n        fi\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            # temporarily restore Bluetooth stack (if needed)\n            service sixad status &>/dev/null && sixad -r\n            case \"$choice\" in\n                P)\n                    pair_bluetooth\n                    ;;\n                X)\n                    remove_device_bluetooth\n                    ;;\n                S)\n                    printMsgs \"dialog\" \"$(status_bluetooth)\"\n                    ;;\n                U)\n                    udev_bluetooth\n                    ;;\n                C)\n                    connect_bluetooth\n                    ;;\n                M)\n                    connect_mode_gui_bluetooth\n                    ;;\n                8)\n                    atebitdo=\"$((atebitdo ^ 1))\"\n                    setAutoConf \"8bitdo_hack\" \"$atebitdo\"\n                    ;;\n            esac\n        else\n            # restart sixad (if running)\n            service sixad status &>/dev/null && service sixad restart && printMsgs \"dialog\" \"NOTICE: The ps3controller driver was temporarily interrupted in order to allow compatibility with standard Bluetooth peripherals. Please re-pair your Dual Shock controller to continue (or disregard this message if currently using another controller).\"\n            break\n        fi\n    done\n}\n\nfunction _bonded_fix_bluetooth() {\n    local mode=$1\n    # exit when we don't have an op mode (install/remove) or a config file\n    [[ -z \"$mode\" ]] && return\n    [[ ! -f \"/etc/bluetooth/input.conf\" ]] && return\n\n    if [[ \"$mode\" == \"add\" ]]; then\n        # configure the workaround\n        iniConfig \"=\" '' \"/etc/bluetooth/input.conf\"\n        iniSet \"ClassicBondedOnly\" \"false\"\n    fi\n\n    if [[ \"$mode\" == \"remove\" ]]; then\n        # remove the workaround\n        iniConfig \"=\" '' \"/etc/bluetooth/input.conf\"\n        iniSet \"ClassicBondedOnly\" \"true\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/configedit.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"configedit\"\nrp_module_desc=\"Edit RetroPie/RetroArch configurations\"\nrp_module_section=\"config\"\n\nfunction _video_fullscreen_configedit() {\n    local mode=\"$1\"\n    local value=\"$2\"\n    case \"$mode\" in\n        get)\n            iniGet \"video_fullscreen_x\"\n            local res_x=\"$ini_value\"\n\n            iniGet \"video_fullscreen_y\"\n            local res_y=\"$ini_value\"\n\n            if [[ -z \"$res_x\" && -z \"$res_y\" ]]; then\n                echo \"unset\"\n            elif [[ \"$res_x\" == \"0\" && \"$res_y\" == \"0\" ]]; then\n                echo \"Video output resolution\"\n            else\n                echo \"${res_x}x${res_y}\"\n            fi\n            ;;\n        set)\n            local save=\"$1\"\n            local res=(\n                \"320x240\"\n                \"640x480\"\n                \"800x600\"\n                \"960x720\"\n                \"1280x960\"\n            )\n            local i=1\n            local item\n            local options=(U \"unset\")\n            local default\n            for item in \"${res[@]}\"; do\n                [[ \"$item\" == \"$value\" ]] && default=\"$i\"\n                options+=($i \"$item\")\n                ((i++))\n            done\n            options+=(\n                O \"Video output resolution\"\n                C \"Custom\"\n            )\n            [[ \"$value\" == \"Video output resolution\" ]] && default=\"O\"\n            [[ \"$value\" == \"unset\" ]] && default=\"U\"\n            [[ -z \"$default\" ]] && default=\"C\"\n            local cmd=(dialog --default-item \"$default\" --cancel-label \"Back\" --menu \"Choose RetroArch render resolution\" 22 76 16 )\n            local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n            [[ -z \"$choice\" ]] && return\n            local res\n            if [[ \"$choice\" == \"U\" ]]; then\n                iniUnset \"video_fullscreen_x\"\n                iniUnset \"video_fullscreen_y\"\n            elif [[ \"$choice\" == \"O\" ]]; then\n                iniSet \"video_fullscreen_x\" \"0\"\n                iniSet \"video_fullscreen_y\" \"0\"\n            else\n                if [[ \"$choice\" == \"C\" ]]; then\n                    cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --inputbox \"Please enter the render resolution as WIDTHxHEIGHT\" 10 60)\n                    res=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                    [[ -z \"$res\" || ! \"$res\" =~ ^[0-9]+x[0-9]+$ ]] && return\n                else\n                    res=\"${res[$choice-1]}\"\n                fi\n                res=(${res/x/ })\n                iniSet \"video_fullscreen_x\" \"${res[0]}\"\n                iniSet \"video_fullscreen_y\" \"${res[1]}\"\n            fi\n            ;;\n    esac\n}\n\nfunction _joypad_index_configedit() {\n    local mode=\"$1\"\n    local value=\"$2\"\n    while true; do\n\n        local players=()\n        local player\n        for player in 1 2 3 4; do\n            iniGet \"input_player${player}_joypad_index\"\n            if [[ -n \"$ini_value\" ]]; then\n                players+=(\"$ini_value\")\n            else\n                players+=(\"unset\")\n            fi\n        done\n\n        case \"$mode\" in\n            get)\n                echo \"${players[@]}\"\n                return\n                ;;\n            set)\n                local dev\n                local devs_name=()\n                local path\n                local paths=()\n\n                # get joystick device paths\n                while read -r dev; do\n                    if udevadm info --name=$dev | grep -q \"ID_INPUT_JOYSTICK=1\"; then\n                        paths+=(\"$(udevadm info --name=$dev --query=name)\")\n                    fi\n                done < <(find /dev/input -name \"js*\")\n\n                if [[ \"${#paths[@]}\" -gt 0 ]]; then\n                    # sort by path\n                    IFS=$'\\n'\n                    while read -r path; do\n                        devs_name+=(\"$(cat /sys/class/$path/device/name)\")\n                    done < <(sort <<<\"${paths[*]}\")\n                    unset IFS\n                fi\n\n                local options=()\n                local i\n                local value\n                local joypad\n                for i in 1 2 3 4; do\n                    player=\"${players[$i-1]}\"\n                    value=\"$player\"\n                    joypad=\"${devs_name[$player]}\"\n                    [[ -z \"$joypad\" ]] && joypad=\"not connected\"\n                    [[ \"$player\" != \"unset\" ]] && value+=\" ($joypad)\"\n                    options+=(\"$i\" \"$value\")\n                done\n                local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --menu \"Choose a player to adjust\" 22 76 16)\n                local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n                [[ -z \"$choice\" ]] && return\n                player=\"$choice\"\n                options=(U Unset)\n                local i=0\n                for dev in \"${devs_name[@]}\"; do\n                    options+=(\"$i\" \"$dev\")\n                    ((i++))\n                done\n                local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --menu \"Choose a Gamepad\" 22 76 16)\n                local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n                [[ -z \"$choice\" ]] && continue\n                case \"$choice\" in\n                    U)\n                        iniUnset \"input_player${player}_joypad_index\"\n                        ;;\n                    *)\n                        iniSet \"input_player${player}_joypad_index\" \"$choice\"\n                        ;;\n                esac\n                ;;\n        esac\n    done\n}\n\nfunction basic_configedit() {\n    local config=\"$1\"\n\n    local ini_options=(\n        'video_smooth true false'\n        'aspect_ratio_index _id_ 4:3 16:9 16:10 16:15 21:9 1:1 2:1 3:2 3:4 4:1 4:4 5:4 6:5 7:9 8:3 8:7 19:12 19:14 30:17 32:9 config square core custom'\n        '_function_ _video_fullscreen_configedit'\n        'video_shader_enable true false'\n        \"video_shader _file_ *.*p $rootdir/emulators/retroarch/shader\"\n        'input_auto_game_focus _id_ off on detect'\n        'input_overlay_enable true false'\n        \"input_overlay _file_ *.cfg $rootdir/emulators/retroarch/overlays\"\n        '_function_ _joypad_index_configedit'\n        'input_player1_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player2_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player3_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player4_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n    )\n\n    local ini_titles=(\n        'Video Smoothing'\n        'Aspect Ratio'\n        'Render Resolution'\n        'Video Shader Enable'\n        \"Video Shader File\"\n        'Auto Enable \"Game Focus\" Mode'\n        'Overlay Enable'\n        'Overlay File'\n        'Choose joypad order'\n        'Player 1 - use analogue stick as d-pad'\n        'Player 2 - use analogue stick as d-pad'\n        'Player 3 - use analogue stick as d-pad'\n        'Player 4 - use analogue stick as d-pad'\n    )\n\n    local ini_descs=(\n        'Smoothens picture with bilinear filtering. Should be disabled if using pixel shaders.'\n        'Aspect ratio to use (default unset - will use core aspect if video_aspect_ratio_auto is true)'\n        'Configure the resolution to render the emulator output at - for better performance on full HD displays choose a lower resolution and it will be upscaled in hardware'\n        'Load video_shader on startup. Other shaders can still be loaded later in runtime.'\n        'Video shader to use (default none)'\n        'Controls the automatic loading of \"Game Focus\" mode when starting a game.'\n        'Load input overlay on startup. Other overlays can still be loaded later in runtime.'\n        'Input overlay to use (default none)'\n        'Manual selection of joypad order'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n    )\n\n    iniFileEditor \" = \" '\"' \"$config\"\n}\n\nfunction advanced_configedit() {\n    local config=\"$1\"\n\n    local audio_opts=\"alsa alsathread sdl2\"\n    if isPlatform \"x11\"; then\n        audio_opts+=\" pulse\"\n    fi\n\n    local ini_options=(\n        'video_smooth true false'\n        'aspect_ratio_index _id_ 4:3 16:9 16:10 16:15 21:9 1:1 2:1 3:2 3:4 4:1 4:4 5:4 6:5 7:9 8:3 8:7 19:12 19:14 30:17 32:9 config square core custom'\n        'video_shader_enable true false'\n        \"video_shader _file_ *.*p $rootdir/emulators/retroarch/shader\"\n        'input_overlay_enable true false'\n        \"input_overlay _file_ *.cfg $rootdir/emulators/retroarch/overlays\"\n        \"audio_driver $audio_opts\"\n        'video_driver gl dispmanx sdl2 vg vulkan glcore gl1'\n        'menu_driver rgui xmb glui ozone'\n        'video_fullscreen_x _string_'\n        'video_fullscreen_y _string_'\n        'video_frame_delay _string_'\n        'video_threaded true false'\n        'video_force_aspect true false'\n        'video_scale_integer true false'\n        'video_aspect_ratio_auto true false'\n        'video_aspect_ratio _string_'\n        'video_allow_rotate true false'\n        'video_rotation 0 1 2 3'\n        'custom_viewport_width _string_'\n        'custom_viewport_height _string_'\n        'custom_viewport_x _string_'\n        'custom_viewport_y _string_'\n        'video_font_size _string_'\n        'fps_show true false'\n        'input_overlay_opacity _string_'\n        'input_overlay_scale _string_'\n        'input_joypad_driver udev sdl2 linuxraw hid'\n        'game_specific_options true false'\n        'input_player1_joypad_index _string_'\n        'input_player2_joypad_index _string_'\n        'input_player3_joypad_index _string_'\n        'input_player4_joypad_index _string_'\n        'input_player5_joypad_index _string_'\n        'input_player6_joypad_index _string_'\n        'input_player7_joypad_index _string_'\n        'input_player8_joypad_index _string_'\n        'input_player1_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player2_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player3_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player4_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player5_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player6_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player7_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n        'input_player8_analog_dpad_mode _id_ disabled left-stick right-stick left-stick-forced right-stick-forced'\n\n    )\n\n    local ini_descs=(\n        'Smoothens picture with bilinear filtering. Should be disabled if using pixel shaders.'\n        'Aspect ratio to use (default unset - will use core aspect if video_aspect_ratio_auto is true)'\n        'Load video_shader on startup. Other shaders can still be loaded later in runtime.'\n        'Video shader to use. Video driver gl supports *.glslp shader presets. Video drivers glcore and vulkan support *.slangp shader presets. (default none)'\n        'Load input overlay on startup. Other overlays can still be loaded later in runtime.'\n        'Input overlay to use (default none)'\n        'Audio driver to use (default is alsathread)'\n        'Video driver to use (default is gl)'\n        'Menu driver to use'\n        'Fullscreen x resolution. Resolution of 0 uses the resolution of the desktop. (defaults to 0 if unset)'\n        'Fullscreen y resolution. Resolution of 0 uses the resolution of the desktop. (defaults to 0 if unset)'\n        'Sets how many milliseconds to delay after VSync before running the core. Can reduce latency at cost of higher risk of stuttering. Maximum is 15'\n        'Use threaded video driver. Using this might improve performance at possible cost of latency and more video stuttering.'\n        'Forces rendering area to stay equal to content aspect ratio or as defined in video_aspect_ratio.'\n        'Only scales video in integer steps. The base size depends on system-reported geometry and aspect ratio. If video_force_aspect is not set, X/Y will be integer scaled independently.'\n        'If this is true and video_aspect_ratio or video_aspect_ratio_index is not set, aspect ratio is decided by libretro implementation. If this is false, 1:1 PAR will always be assumed if video_aspect_ratio or  video_aspect_ratio_index is not set.'\n        'A floating point value for video aspect ratio (width / height). If this is not set, aspect ratio is assumed to be automatic. Behavior then is defined by video_aspect_ratio_auto.'\n        'Allows libretro cores to set rotation modes. Setting this to false will honor, but ignore this request. This is useful for vertically oriented content where one manually rotates the monitor. (defaults to true)'\n        'Forces a certain rotation of the screen. The rotation is added to rotations which the libretro core sets (see video_allow_rotate). The angle is <value> * 90 degrees counter-clockwise.'\n        'Viewport resolution.'\n        'Viewport resolution.'\n        'Viewport position x.'\n        'Viewport position y.'\n        'Size of the OSD font.'\n        'Show current frames per second.'\n        'Opacity of overlay. Float value 1.000000.'\n        'Scale of overlay. Float value 1.000000.'\n        'Input joypad driver to use (default is udev)'\n        'Game specific core options in retroarch-core-options.cfg, rather than for all games via that core.'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Manual selection of joypad order'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n        'Allow analogue sticks to be used as a d-pad - 0 = disabled, 1 = left stick, 2 = right stick, 3 = left stick forced, 4 = right stick forced'\n\n    )\n\n    iniFileEditor \" = \" '\"' \"$config\"\n}\n\nfunction choose_config_configedit() {\n    local path=\"$1\"\n    local include=\"$2\"\n    local exclude=\"$3\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --menu \"Which configuration would you like to edit\" 22 76 16)\n    local configs=()\n    local options=()\n    local config\n    local i=0\n    while read config; do\n        config=${config//$path\\//}\n        configs+=(\"$config\")\n        options+=(\"$i\" \"$config\")\n        ((i++))\n    done < <(find \"$path\" -type f -regex \"$include\" ! -regex \"$exclude\" ! -regex \".*/downloaded_images/.*\" | sort)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        echo \"${configs[choice]}\"\n    fi\n}\n\nfunction basic_menu_configedit() {\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --menu \"Which platform do you want to adjust\" 22 76 16)\n        local configs=()\n        local options=()\n        local config\n        local dir\n        local desc\n        local i=0\n        while read config; do\n            configs+=(\"$config\")\n            dir=${config%/*}\n            dir=${dir//$configdir\\//}\n            if [[ \"$dir\" == \"all\" ]]; then\n                desc=\"Configure default options for all libretro emulators\"\n            else\n                desc=\"Configure additional options for $dir\"\n            fi\n            options+=(\"$i\" \"$desc\")\n            ((i++))\n        done < <(find \"$configdir\" -type f -regex \".*/retroarch.cfg\" | sort)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            basic_configedit \"${configs[choice]}\"\n        else\n            break\n        fi\n    done\n}\n\nfunction advanced_menu_configedit() {\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Back\" --menu \"Choose an option\" 22 76 16)\n        local options=(\n            1 \"Configure Libretro options\"\n            2 \"Manually edit RetroArch configurations\"\n            3 \"Manually edit global configs\"\n            4 \"Manually edit non RetroArch configurations\"\n            5 \"Manually edit all configurations\"\n        )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        local file=\"-\"\n        if [[ -n \"$choice\" ]]; then\n            local ra_exclude='.*/all/retroarch/\\(assets\\|shaders\\|thumbnails\\)/.*'\n            while [[ -n \"$file\" ]]; do\n                case \"$choice\" in\n                    1)\n                        file=$(choose_config_configedit \"$configdir\" \".*/retroarch.cfg\")\n                        advanced_configedit \"$configdir/$file\" 2\n                        ;;\n                    2)\n                        file=$(choose_config_configedit \"$configdir\" \".*/retroarch.*\" \"$ra_exclude\")\n                        editFile \"$configdir/$file\"\n                        ;;\n                    3)\n                        file=$(choose_config_configedit \"$configdir\" \".*/all/.*\" \"$ra_exclude\")\n                        editFile \"$configdir/$file\"\n                        ;;\n                    4)\n                        file=$(choose_config_configedit \"$configdir\" \".*\" \".*retroarch.*\")\n                        editFile \"$configdir/$file\"\n                        ;;\n                    5)\n                        file=$(choose_config_configedit \"$configdir\" \".*\" \"$ra_exclude\")\n                        editFile \"$configdir/$file\"\n                        ;;\n                esac\n            done\n        else\n            break\n        fi\n    done\n}\n\nfunction gui_configedit() {\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Exit\" --menu \"Choose an option\" 22 76 16)\n        local options=(\n            1 \"Configure basic libretro emulator options\"\n            2 \"Advanced Configuration\"\n        )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        local file=\"-\"\n        if [[ -n \"$choice\" ]]; then\n            case $choice in\n                1)\n                    basic_menu_configedit\n                    ;;\n                2)\n                    advanced_menu_configedit\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/consolefont.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"consolefont\"\nrp_module_desc=\"Configure default console font size/type\"\nrp_module_section=\"config\"\nrp_module_flags=\"!x11\"\n\nfunction set_consolefont() {\n    iniConfig \"=\" '\"' \"/etc/default/console-setup\"\n    iniSet \"FONTFACE\" \"$1\"\n    iniSet \"FONTSIZE\" \"$2\"\n    service console-setup restart\n    # force font configuration update if running from a pseudo-terminal\n    [[ \"$(tty | egrep '/dev/tty[1-6]')\" == \"\" ]] && setupcon -f --force\n}\n\nfunction check_consolefont() {\n    local fontface\n    local fontsize\n\n    iniConfig \"=\" '\"' \"/etc/default/console-setup\"\n    iniGet \"FONTFACE\"\n    fontface=\"$ini_value\"\n    iniGet \"FONTSIZE\"\n    fontsize=\"$ini_value\"\n    echo \"$fontface\" \"$fontsize\"\n}\n\nfunction gui_consolefont() {\n    local cmd\n    local options\n    local choice\n\n    cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose the desired console font configuration: \\n(Current configuration: $(check_consolefont))\" 22 86 16)\n    options=(\n        1 \"Large (VGA 16x32)\"\n        2 \"Large (TerminusBold 16x32)\"\n        3 \"Medium (VGA 16x28)\"\n        4 \"Medium (TerminusBold 14x28)\"\n        5 \"Small (Fixed 8x16)\"\n        6 \"Smaller (VGA 8x8)\"\n        D \"Default (Kernel font 8x16 - Restart needed)\"\n    )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                set_consolefont \"VGA\" \"16x32\"\n                ;;\n            2)\n                set_consolefont \"TerminusBold\" \"16x32\"\n                ;;\n            3)\n                set_consolefont \"VGA\" \"16x28\"\n                ;;\n            4)\n                set_consolefont \"TerminusBold\" \"14x28\"\n                ;;\n            5)\n                set_consolefont \"Fixed\" \"8x16\"\n                ;;\n            6)\n                set_consolefont \"VGA\" \"8x8\"\n                ;;\n            D)\n                set_consolefont \"\" \"\"\n                ;;\n        esac\n        if [[ \"$choice\" == \"D\" ]]; then\n            printMsgs \"dialog\" \"Default font will be used (provided by the Kernel).\\n\\nYou will need to reboot to see the change.\"\n        else\n            printMsgs \"dialog\" \"New font configuration applied: $(check_consolefont)\"\n        fi\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/controlblock.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"controlblock\"\nrp_module_desc=\"ControlBlock Driver\"\nrp_module_help=\"Please note that you need to manually enable or disable the ControlBlock Service in the Configuration section. IMPORTANT: If the service is enabled and the power switch functionality is enabled (which is the default setting) in the config file, you need to have a switch connected to the ControlBlock.\"\nrp_module_licence=\"NONCOM https://raw.githubusercontent.com/petrockblog/ControlBlockService2/master/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/petrockblog/ControlBlockService2.git master\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean !all rpi\"\n\nfunction depends_controlblock() {\n    local depends=(cmake doxygen gpiod libgpiod-dev)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_controlblock() {\n    gitPullOrClone \"$md_inst\"\n}\n\nfunction build_controlblock() {\n    cd \"$md_inst\"\n    rm -rf \"build\"\n    mkdir build\n    cd build\n    cmake ..\n    make\n    md_ret_require=\"$md_inst/build/controlblock\"\n}\n\nfunction install_controlblock() {\n    # install from there to system folders\n    cd \"$md_inst/build\"\n    make install\n}\n\nfunction gui_controlblock() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local options=(\n        1 \"Enable ControlBlock driver\"\n        2 \"Disable ControlBlock driver\"\n\n    )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                make -C \"$md_inst/build\" installservice\n                printMsgs \"dialog\" \"Enabled ControlBlock driver.\"\n                ;;\n            2)\n                make -C \"$md_inst/build\" uninstallservice\n                printMsgs \"dialog\" \"Disabled ControlBlock driver.\"\n                ;;\n        esac\n    fi\n}\n\nfunction remove_controlblock() {\n    make -C \"$md_inst/build\" uninstallservice\n    make -C \"$md_inst/build\" uninstall\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/custombluez/01_raspbian_patches.diff",
    "content": "From 480f82debde736f6511262cf1ecfa5ca02a22197 Mon Sep 17 00:00:00 2001\nFrom: Conn O'Griofa <connogriofa@gmail.com>\nDate: Sat, 17 Nov 2018 00:30:13 +0000\nSubject: [PATCH] Import Raspbian patches\n\n---\n debian/changelog                                    |  6 ++++++\n debian/libbluetooth3.symbols                        |  2 --\n .../0050-bcm43xx-Add-bcm43xx-3wire-variant.patch    | 21 +++++++++++++++++++++\n ...0052-Increase-firmware-load-timeout-to-30s.patch | 20 ++++++++++++++++++++\n .../0053-Move-43xx-firmware-to-lib-firmware.patch   | 11 +++++++++++\n debian/patches/0054-update-bluetooth.conf.patch     | 11 +++++++++++\n debian/patches/series                               |  4 ++++\n 7 files changed, 73 insertions(+), 2 deletions(-)\n create mode 100644 debian/patches/0050-bcm43xx-Add-bcm43xx-3wire-variant.patch\n create mode 100644 debian/patches/0052-Increase-firmware-load-timeout-to-30s.patch\n create mode 100644 debian/patches/0053-Move-43xx-firmware-to-lib-firmware.patch\n create mode 100644 debian/patches/0054-update-bluetooth.conf.patch\n\ndiff --git a/debian/changelog b/debian/changelog\nindex 85a875f53..7ff84df69 100644\n--- a/debian/changelog\n+++ b/debian/changelog\n@@ -1,3 +1,9 @@\n+bluez (5.50-1~rpi1) UNRELEASED; urgency=medium\n+\n+  * Import Raspbian patches.\n+\n+ -- Conn O'Griofa <connogriofa@gmail.com>  Sat, 17 Nov 2018 00:27:54 +0000\n+\n bluez (5.50-1) unstable; urgency=medium\n \n   * Update to 5.50.\ndiff --git a/debian/libbluetooth3.symbols b/debian/libbluetooth3.symbols\nindex b395a17a7..d08b15d52 100644\n--- a/debian/libbluetooth3.symbols\n+++ b/debian/libbluetooth3.symbols\n@@ -216,6 +216,4 @@ libbluetooth.so.3 libbluetooth3 #MINVER#\n  str2ba@Base 4.91\n  strtoba@Base 4.91\n sixaxis.so libbluetooth3 #MINVER#\n- __start___debug@Base 5.46\n- __stop___debug@Base 5.46\n  bluetooth_plugin_desc@Base 5.20\ndiff --git a/debian/patches/0050-bcm43xx-Add-bcm43xx-3wire-variant.patch b/debian/patches/0050-bcm43xx-Add-bcm43xx-3wire-variant.patch\nnew file mode 100644\nindex 000000000..14b2f4e17\n--- /dev/null\n+++ b/debian/patches/0050-bcm43xx-Add-bcm43xx-3wire-variant.patch\n@@ -0,0 +1,21 @@\n+From 874990be3b958bd3d5d5f61989f8d6314be3358a Mon Sep 17 00:00:00 2001\n+From: Phil Elwell <phil@raspberrypi.org>\n+Date: Tue, 16 Feb 2016 16:40:46 +0000\n+Subject: [PATCH 1/3] bcm43xx: Add bcm43xx-3wire variant\n+\n+---\n+ tools/hciattach.c | 3 +++\n+ 1 file changed, 3 insertions(+)\n+\n+--- a/tools/hciattach.c\n++++ b/tools/hciattach.c\n+@@ -1144,6 +1144,9 @@\n+ \t{ \"bcm43xx\",    0x0000, 0x0000, HCI_UART_H4,   115200, 3000000,\n+ \t\t\t\tFLOW_CTL, DISABLE_PM, NULL, bcm43xx, NULL  },\n+ \n++\t{ \"bcm43xx-3wire\",    0x0000, 0x0000, HCI_UART_3WIRE, 115200, 3000000,\n++\t\t\t\t0, DISABLE_PM, NULL, bcm43xx, NULL  },\n++\n+ \t{ \"ath3k\",    0x0000, 0x0000, HCI_UART_ATH3K, 115200, 115200,\n+ \t\t\tFLOW_CTL, DISABLE_PM, NULL, ath3k_ps, ath3k_pm  },\n+ \ndiff --git a/debian/patches/0052-Increase-firmware-load-timeout-to-30s.patch b/debian/patches/0052-Increase-firmware-load-timeout-to-30s.patch\nnew file mode 100644\nindex 000000000..df264b091\n--- /dev/null\n+++ b/debian/patches/0052-Increase-firmware-load-timeout-to-30s.patch\n@@ -0,0 +1,20 @@\n+From 74e6869ecce13b1066741ba995fc47b437c4c72f Mon Sep 17 00:00:00 2001\n+From: Phil Elwell <phil@raspberrypi.org>\n+Date: Wed, 20 Jan 2016 16:00:37 +0000\n+Subject: [PATCH 3/3] Increase firmware load timeout to 30s\n+\n+---\n+ tools/hciattach.c | 2 +-\n+ 1 file changed, 1 insertion(+), 1 deletion(-)\n+\n+--- a/tools/hciattach.c\n++++ b/tools/hciattach.c\n+@@ -1287,7 +1287,7 @@\n+ {\n+ \tstruct uart_t *u = NULL;\n+ \tint detach, printpid, raw, opt, i, n, ld, err;\n+-\tint to = 10;\n++\tint to = 30;\n+ \tint init_speed = 0;\n+ \tint send_break = 0;\n+ \tpid_t pid;\ndiff --git a/debian/patches/0053-Move-43xx-firmware-to-lib-firmware.patch b/debian/patches/0053-Move-43xx-firmware-to-lib-firmware.patch\nnew file mode 100644\nindex 000000000..61fbb7b2c\n--- /dev/null\n+++ b/debian/patches/0053-Move-43xx-firmware-to-lib-firmware.patch\n@@ -0,0 +1,11 @@\n+--- a/tools/hciattach_bcm43xx.c\n++++ b/tools/hciattach_bcm43xx.c\n+@@ -43,7 +43,7 @@\n+ #include \"hciattach.h\"\n+ \n+ #ifndef FIRMWARE_DIR\n+-#define FIRMWARE_DIR \"/etc/firmware\"\n++#define FIRMWARE_DIR \"/lib/firmware\"\n+ #endif\n+ \n+ #define FW_EXT \".hcd\"\ndiff --git a/debian/patches/0054-update-bluetooth.conf.patch b/debian/patches/0054-update-bluetooth.conf.patch\nnew file mode 100644\nindex 000000000..58b8b3808\n--- /dev/null\n+++ b/debian/patches/0054-update-bluetooth.conf.patch\n@@ -0,0 +1,11 @@\n+--- a/src/bluetooth.conf\n++++ b/src/bluetooth.conf\n+@@ -37,7 +37,7 @@\n+   </policy>\n+ \n+   <policy context=\"default\">\n+-    <deny send_destination=\"org.bluez\"/>\n++    <allow send_destination=\"org.bluez\"/>\n+   </policy>\n+ \n+ </busconfig>\ndiff --git a/debian/patches/series b/debian/patches/series\nindex d4709adf3..7598d7426 100644\n--- a/debian/patches/series\n+++ b/debian/patches/series\n@@ -9,3 +9,7 @@ org.bluez.obex.service.in.patch\n Fix-typo.patch\n shared-gatt-client-Fix-segfault-after-PIN-entry.patch\n main.conf-Add-more-details-Closes-904212.patch\n+0050-bcm43xx-Add-bcm43xx-3wire-variant.patch\n+0052-Increase-firmware-load-timeout-to-30s.patch\n+0053-Move-43xx-firmware-to-lib-firmware.patch\n+0054-update-bluetooth.conf.patch\n-- \n2.11.0\n\n"
  },
  {
    "path": "scriptmodules/supplementary/customhidsony/0001-hidsony-gasiafix.diff",
    "content": "From: Martyn Welch <martyn@welchs.me.uk>\nTo: Jiri Kosina <jikos@kernel.org>,\n\tBenjamin Tissoires <benjamin.tissoires@redhat.com>\nCc: linux-input@vger.kernel.org, linux-kernel@vger.kernel.org,\n\tMartyn Welch <martyn@welchs.me.uk>,\n\tConn O'Griofa <connogriofa@gmail.com>\nSubject: [PATCH] HID: Sony: Add support for Gasia controllers\nDate: Sun, 26 Jan 2020 19:45:13 +0000\nMessage-ID: <20200126194513.6359-1-martyn@welchs.me.uk> (raw)\n\nThere seems to be a number of subtly different firmwares for the\nPlaystation controllers made by \"Gasia Co.,Ltd\". Whilst such controllers\nare easily detectable when attached via USB that is not always the case\nvia Bluetooth. Some controllers are named \"PLAYSTATION(R)3 Controller\"\nwhere as the official Sony controllers are named\n\"Sony PLAYSTATION(R)3 Controller\", however some versions of firmware use\nthe exact name used by the official controllers. The only way I've been\nable to distinguish these versions of the controller (when connected via\nBluetooth) is that the Bluetooth Class of Device incorrectly reports the\ncontroller as a keyboard rather than a gamepad. I've so far failed to work\nout how to access this information from a HID driver.\n\nThe Gasia controllers need output reports to be configured in the same way\nas the Shanwan controllers. In order to ensure both types of Gasia firmware\nwill work, this patch adds a quirk for those devices it can detect and\nreworks `sixaxis_send_output_report()` to attempt `hid_hw_output_report()`\nshould `hid_hw_raw_request()` be known to be the wrong option (as is the\ncase with the Shanwan controllers) or fails.\n\nThis has got all the controllers I have working, with the slight\nanoyance that the Gasia controllers that don't currently get marked with\na quirk require the call to `hid_hw_raw_request()` to fail before the\ncontroller finishes initialising (which adds a significant extra delay\nbefore the controller is ready).\n\nThis patch is based on the following patch by Conn O'Griofa:\n\nhttps://github.com/RetroPie/RetroPie-Setup/pull/2263/commits/017f00f6e15f04b3272ff1abae8742dc4c47b608\n\nCc: Conn O'Griofa <connogriofa@gmail.com>\nSigned-off-by: Martyn Welch <martyn@welchs.me.uk>\n---\n drivers/hid/hid-sony.c | 31 +++++++++++++++++++++++++------\n 1 file changed, 25 insertions(+), 6 deletions(-)\n\ndiff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c\nindex 4c6ed6ef31f1..d1088a85cb59 100644\n--- a/drivers/hid/hid-sony.c\n+++ b/drivers/hid/hid-sony.c\n@@ -56,6 +56,7 @@\n #define NSG_MR5U_REMOTE_BT        BIT(14)\n #define NSG_MR7U_REMOTE_BT        BIT(15)\n #define SHANWAN_GAMEPAD           BIT(16)\n+#define GASIA_GAMEPAD             BIT(17)\n \n #define SIXAXIS_CONTROLLER (SIXAXIS_CONTROLLER_USB | SIXAXIS_CONTROLLER_BT)\n #define MOTION_CONTROLLER (MOTION_CONTROLLER_USB | MOTION_CONTROLLER_BT)\n@@ -2067,6 +2068,7 @@ static void sixaxis_send_output_report(struct sony_sc *sc)\n \tstruct sixaxis_output_report *report =\n \t\t(struct sixaxis_output_report *)sc->output_report_dmabuf;\n \tint n;\n+\tint ret = -1;\n \n \t/* Initialize the report with default values */\n \tmemcpy(report, &default_report, sizeof(struct sixaxis_output_report));\n@@ -2101,14 +2103,23 @@ static void sixaxis_send_output_report(struct sony_sc *sc)\n \t\t}\n \t}\n \n-\t/* SHANWAN controllers require output reports via intr channel */\n-\tif (sc->quirks & SHANWAN_GAMEPAD)\n-\t\thid_hw_output_report(sc->hdev, (u8 *)report,\n-\t\t\t\tsizeof(struct sixaxis_output_report));\n-\telse\n-\t\thid_hw_raw_request(sc->hdev, report->report_id, (u8 *)report,\n+\t/*\n+\t * SHANWAN & GASIA controllers require output reports via intr channel.\n+\t * Some of the Gasia controllers are basically indistinguishable from\n+\t * the official ones and thus try hid_hw_output_report() should\n+\t * hid_hw_raw_request() fail.\n+\t */\n+\tif (!(sc->quirks & (SHANWAN_GAMEPAD | GASIA_GAMEPAD)))\n+\t\tret = hid_hw_raw_request(sc->hdev, report->report_id,\n+\t\t\t\t(u8 *)report,\n \t\t\t\tsizeof(struct sixaxis_output_report),\n \t\t\t\tHID_OUTPUT_REPORT, HID_REQ_SET_REPORT);\n+\n+\tif (ret >= 0)\n+\t\treturn;\n+\n+\thid_hw_output_report(sc->hdev, (u8 *)report,\n+\t\t\tsizeof(struct sixaxis_output_report));\n }\n \n static void dualshock4_send_output_report(struct sony_sc *sc)\n@@ -2833,6 +2844,14 @@ static int sony_probe(struct hid_device *hdev, const struct hid_device_id *id)\n \tif (!strcmp(hdev->name, \"SHANWAN PS3 GamePad\"))\n \t\tquirks |= SHANWAN_GAMEPAD;\n \n+\t/*\n+\t * Some Gasia controllers are named \"PLAYSTATION(R)3 Controller\"\n+\t * where as the official Sony controllers are named\n+\t * \"Sony PLAYSTATION(R)3 Controller\".\n+\t */\n+\tif (!strcmp(hdev->name, \"PLAYSTATION(R)3 Controller\"))\n+\t\tquirks |= GASIA_GAMEPAD;\n+\n \tsc = devm_kzalloc(&hdev->dev, sizeof(*sc), GFP_KERNEL);\n \tif (sc == NULL) {\n \t\thid_err(hdev, \"can't alloc sony descriptor\\n\");\n-- \n2.20.1\n"
  },
  {
    "path": "scriptmodules/supplementary/customhidsony.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"customhidsony\"\nrp_module_desc=\"Custom hid-sony (Sony DualShock) driver with enhanced third-party controller support\"\nrp_module_help=\"Improves support for third-party (Shanwan & Gasia) DualShock 3 controllers.\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean\"\n\nfunction _version_customhidsony() {\n    echo \"0.1.3\"\n}\n\nfunction depends_customhidsony() {\n    depends_xpad\n}\n\nfunction sources_customhidsony() {\n    mkdir -p \"$md_inst/patches\"\n    pushd \"$md_inst\"\n\n    cat > \"Makefile\" << _EOF_\nobj-m := drivers/hid/hid-sony.o\n_EOF_\n\n    cat > \"dkms.conf\" << _EOF_\nPACKAGE_NAME=\"hid-sony\"\nPACKAGE_VERSION=\"$(_version_customhidsony)\"\nPRE_BUILD=\"hidsony_source.sh\"\nBUILT_MODULE_LOCATION=\"drivers/hid\"\nBUILT_MODULE_NAME=\"\\$PACKAGE_NAME\"\nDEST_MODULE_LOCATION=\"/updates/dkms\"\nAUTOINSTALL=\"yes\"\n_EOF_\n\n    cat > \"hidsony_source.sh\" << _EOF_\n#!/bin/bash\nrpi_kernel_ver=\"rpi-5.10.y\"\nmkdir -p \"drivers/hid/\" \"patches\"\ncurl -s https://raw.githubusercontent.com/raspberrypi/linux/\"\\$rpi_kernel_ver\"/drivers/hid/hid-sony.c -o \"drivers/hid/hid-sony.c\"\ncurl -s https://raw.githubusercontent.com/raspberrypi/linux/\"\\$rpi_kernel_ver\"/drivers/hid/hid-ids.h -o \"drivers/hid/hid-ids.h\"\npatch -p1 <\"patches/0001-hidsony-gasiafix.diff\"\n_EOF_\n    chmod +x \"hidsony_source.sh\"\n\n    cp \"$md_data/0001-hidsony-gasiafix.diff\" \"patches/\"\n\n    popd\n}\n\nfunction build_customhidsony() {\n    dkmsManager install hid-sony \"$(_version_customhidsony)\"\n}\n\nfunction remove_customhidsony() {\n    dkmsManager remove hid-sony \"$(_version_customhidsony)\"\n}\n\nfunction configure_customhidsony() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    dkmsManager reload hid-sony \"$(_version_customhidsony)\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/dbar4gun.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"dbar4gun\"\nrp_module_desc=\"dbar4gun is a Linux userspace driver for the wiimote with DolphinBar support.\"\nrp_module_help=\"https://github.com/lowlevel-1989/dbar4gun\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/lowlevel-1989/dbar4gun/master/LICENSE\"\nrp_module_repo=\"git https://github.com/lowlevel-1989/dbar4gun master\"\nrp_module_section=\"driver\"\n\nfunction depends_dbar4gun() {\n    getDepends python3 python3-dev python3-setuptools python3-virtualenv python3-pygame\n}\n\nfunction sources_dbar4gun() {\n    gitPullOrClone\n}\n\nfunction install_dbar4gun() {\n    python3 -m venv \"$md_inst\"\n    source \"$md_inst/bin/activate\"\n    pip3 install .\n    deactivate\n    md_ret_require=\"$md_inst/bin/dbar4gun\"\n}\n\nfunction configure_dbar4gun() {\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        return\n    fi\n\n    touch \"$configdir/all/dbar4gun.cfg\"\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n}\n\nfunction enable_dbar4gun() {\n    local config=\"/etc/systemd/system/dbar4gun.service\"\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    local dbar4gun_params=\"--width $db_width --height $db_height\"\n    dbar4gun_params=\"$dbar4gun_params --calibration $db_calibration\"\n    dbar4gun_params=\"$dbar4gun_params --setup $db_setup\"\n    dbar4gun_params=\"$dbar4gun_params --port $db_port\"\n    dbar4gun_params=\"$dbar4gun_params --smoothing-level $db_smoothing_level\"\n\n    if [[ \"$db_disable_tilt_correction\" -eq 1 ]]; then\n        dbar4gun_params=\"$dbar4gun_params --disable-tilt-correction\"\n    fi\n\n    disable_dbar4gun\n    cat > \"$config\" << _EOF_\n[Unit]\nDescription=dbar4gun\n\n[Service]\nType=simple\nExecStart=$md_inst/bin/dbar4gun start $dbar4gun_params\n\n[Install]\nWantedBy=multi-user.target\n_EOF_\n    systemctl daemon-reload\n\n    systemctl enable dbar4gun --now\n    printMsgs \"dialog\" \"dbar4gun enabled.\"\n}\n\nfunction disable_dbar4gun() {\n    systemctl disable dbar4gun --now\n}\n\nfunction remove_dbar4gun() {\n    disable_dbar4gun\n    rm -rf \"/etc/systemd/system/dbar4gun.service\"\n    systemctl daemon-reload\n}\n\nfunction _loadconfig_dbar4gun() {\n    echo \"$(loadModuleConfig \\\n        'db_width=1920' \\\n        'db_height=1080' \\\n        'db_disable_tilt_correction=0' \\\n        'db_setup=1' \\\n        'db_port=35460' \\\n        'db_calibration=2' \\\n        'db_smoothing_level=3'\n    )\"\n}\n\nfunction _menu_start_dbar4gun() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"dbar4gun service\" 22 86 16)\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    while true; do\n\n        local options=(\n            1 \"width: $db_width\"\n            2 \"height: $db_height\"\n            3 \"smoothing level: $db_smoothing_level\"\n            4 \"debug port: $db_port\"\n        )\n\n        if [[ \"$db_disable_tilt_correction\" -eq 1 ]]; then\n            options+=(5 \"enable tilt correction\")\n        else\n            options+=(5 \"disable tilt correction\")\n        fi\n\n        options+=(6 \"dbar4gun start\")\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    local cmd_in=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the width\" 10 60 \"$db_width\")\n                    db_width=$(\"${cmd_in[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"db_width\" \"$db_width\"\n                    ;;\n                2)\n                    local cmd_in=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the height\" 10 60 \"$db_height\")\n                    db_height=$(\"${cmd_in[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"db_height\" \"$db_height\"\n                    ;;\n                3)\n                    local cmd_in=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the smoothing level\" 10 60 \"$db_smoothing_level\")\n                    db_smoothing_level=$(\"${cmd_in[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"db_smoothing_level\" \"$db_smoothing_level\"\n                    ;;\n                4)\n                    local cmd_in=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the debug port\" 10 60 \"$db_port\")\n                    db_port=$(\"${cmd_in[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"db_port\" \"$db_port\"\n                    ;;\n                5)\n                    db_disable_tilt_correction=\"$((db_disable_tilt_correction ^ 1))\"\n                    iniSet \"db_disable_tilt_correction\" \"$db_disable_tilt_correction\"\n                    ;;\n                6)\n                    enable_dbar4gun\n                    break\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n\n}\n\nfunction _menu_ir_setup() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"IR Setup\" 22 86 16)\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    local options=(\n        1 \"Standard\"\n    )\n\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    iniSet \"db_setup\" \"1\"\n                    _menu_calibration_mode\n                    break\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction _menu_calibration_mode() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Calibration Mode\" 22 86 16)\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    local options=(\n        1 \"TopLeft, TopRight, BottomCenter\"\n        2 \"Center,  TopLeft\"\n        3 \"disabled\"\n    )\n\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    iniSet \"db_calibration\" \"2\"\n                    _menu_start_dbar4gun\n                    break\n                    ;;\n                2)\n                    iniSet \"db_calibration\" \"1\"\n                    _menu_start_dbar4gun\n                    break\n                    ;;\n                3)\n                    iniSet \"db_calibration\" \"0\"\n                    _menu_start_dbar4gun\n                    break\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction _menu_set_resolution() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose Resolution\" 22 86 16)\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    local options=(\n        1 \" 1080p\"\n        2 \"  720p\"\n        3 \"manual\"\n    )\n\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    iniSet \"db_width\" \"1920\"\n                    iniSet \"db_height\" \"1080\"\n                    _menu_ir_setup\n                    break\n                    ;;\n                2)\n                    iniSet \"db_width\" \"1280\"\n                    iniSet \"db_height\" \"720\"\n                    _menu_ir_setup\n                    break\n                    ;;\n                3)\n                    _menu_ir_setup\n                    break\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction gui_dbar4gun() {\n    local title=$($md_inst/bin/dbar4gun version)\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"$title\" 22 86 16)\n    local options=(\n        1 \"Enable dbar4gun\"\n        2 \"Disable dbar4gun\"\n        3 \"Debug\"\n    )\n\n    iniConfig \" = \" '\"' \"$configdir/all/dbar4gun.cfg\"\n    eval $(_loadconfig_dbar4gun)\n\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    _menu_set_resolution\n                    ;;\n                2)\n                    disable_dbar4gun\n                    ;;\n                3)\n                    $md_inst/bin/dbar4gun gui --width 640 --height 480 --port $db_port\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/docsview.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"docsview\"\nrp_module_desc=\"RetroPie-Setup Docs Viewer\"\nrp_module_section=\"config\"\n\nfunction depends_docsview() {\n    getDepends pandoc lynx\n}\n\nfunction choose_page_docsview() {\n    local path=\"$1\"\n    local include=\"$2\"\n    local exclude=\"$3\"\n    local pages=()\n    local options=()\n    local page\n    local i=0\n    while read page; do\n        page=${page//$path\\//}\n        pages+=(\"$page\")\n        options+=(\"$i\" \"$page\")\n        ((i++))\n    done < <(find \"$path\" -type f -regex \"$include\" ! -regex \"$exclude\" | sort)\n    local default\n    local file\n    while true; do\n        local cmd=(dialog --default-item \"$default\" --backtitle \"$__backtitle\" --menu \"Which page would you like to view?\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        if [[ -n \"$choice\" ]]; then\n            file=\"${pages[choice]}\"\n            joy2keyStop\n            joy2keyStart 0x00 0x00 kich1 kdch1 0x20 0x71\n            pandoc \"$dir/docs/$file\" | lynx -localhost -restrictions=all -stdin >/dev/tty\n            joy2keyStop\n            joy2keyStart\n        else\n            break\n        fi\n    done\n}\n\nfunction gui_docsview() {\n    local dir=\"$rootdir/RetroPie-Docs\"\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"RetroPie-Setup Docs Viewer\" 22 76 16)\n        local options=()\n        if [[ -d \"$dir\" ]]; then\n            options=(\n                1 \"Update RetroPie-Setup Docs\"\n                2 \"View Pages\"\n                3 \"Remove RetroPie-Setup Docs\"\n            )\n        else\n            options+=(\"1\" \"Download RetroPie-Setup Docs\")\n        fi\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    gitPullOrClone \"$dir\" \"https://github.com/RetroPie/RetroPie-Docs.git\"\n                    ;;\n                2)\n                    choose_page_docsview \"$dir/docs\" \".*.md\" \".*_.*\"\n                    ;;\n                3)\n                    if [[ -d \"$dir\" ]]; then\n                        rm -rf \"$dir\"\n                    fi\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/daphne.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction check_daphne() {\n    [[ ! -d \"$configdir/daphne/\" ]] && return 1\n    return 0\n}\n\nfunction onstart_daphne_joystick() {\n    local -r mapping_file=\"$configdir/daphne/dapinput.ini\"\n    local -r force_joy_file=\"$configdir/daphne/dapinput-forcejoy.ini\"\n    local -r force_key_file=\"$configdir/daphne/dapinput-forcekey.ini\"\n\n    if [[ ! -f \"$mapping_file\" ]]; then\n        cat > \"$mapping_file\" << _EOF_\n# Daphne custom keyboard and joystick mapping\n#\n# Each input is mapped to 2 keyboard keys and one joystick button.\n# A joystick's first analog stick is also automatically mapped.\n#\n# The first two numbers are SDL keyboard codes (or 0 for \"none\")\n# Find keyboard codes here:\n# http://www.daphne-emu.com/mediawiki/index.php/KeyList\n#\n# The third number is the joystick button code (or 0 for \"none\")\n# Since 0 is reserved for special meaning, joystick button 0 is identified\n# as 1 here.  Button 1 is identified as 2, and so on.\n#\n# Find the button you want to map by running:\n# jstest /dev/input/js0\n\n[KEYBOARD]\nKEY_UP = 273 114 5\nKEY_DOWN = 274 102 7\nKEY_LEFT = 276 100 8\nKEY_RIGHT = 275 103 6\nKEY_BUTTON1 = 306 97 14\nKEY_BUTTON2 = 308 115 15\nKEY_BUTTON3 = 32 113 16\nKEY_START1 = 49 0 4\nKEY_START2 = 50 0 0\nKEY_COIN1 = 53 0 1\nKEY_COIN2 = 54 0 0\nKEY_SKILL1 = 304 119 0\nKEY_SKILL2 = 122 105 0\nKEY_SKILL3 = 120 107 0\nKEY_SERVICE = 57 0 0\nKEY_TEST = 283 0 0\nKEY_RESET = 284 0 0\nKEY_SCREENSHOT = 293 0 0\nKEY_QUIT = 27 113 17\nEND\n_EOF_\n    fi\n\n    if [[ ! -f \"$force_joy_file\" ]]; then\n        cat > \"$force_joy_file\" << _EOF_\n# Daphne custom joystick mapping\n#\n# Any inputs defined below will map a joystick button to\n# Daphne input, regardless of remapping that occurs in emulationstation.\n#\n# Each input is mapped to 1 joystick button (or 0 for \"none\")\n#\n# Find joystick button codes by running:\n# $ jstest /dev/input/js0\n# and ADDING ONE to the button code you want.\n#\n# Example: Quit will always be js button 14\n# KEY_QUIT = 15\n#\n# (Place all entries after [KEYBOARD])\n\n[KEYBOARD]\nEND\n_EOF_\n    fi\n\n    if [[ ! -f \"$force_key_file\" ]]; then\n        cat > \"$force_key_file\" << _EOF_\n# Daphne custom keyboard mapping\n#\n# Any inputs defined below will map keyboard keys to\n# Daphne input, regardless of remapping that occurs in emulationstation.\n#\n# Each input is mapped to 2 keyboard key codes (or 0 for \"none\")\n#\n# Find keyboard codes here:\n# http://www.daphne-emu.com/mediawiki/index.php/KeyList\n#\n# Example: Quit will always be key [Esc] or [Q]\n# KEY_QUIT = 27 113\n#\n# (Place all entries after [KEYBOARD])\n\n[KEYBOARD]\nEND\n_EOF_\n    fi\n}\n\nfunction map_daphne_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local -r mapping_file=\"$configdir/daphne/dapinput.ini\"\n    local -r force_joy_file=\"$configdir/daphne/dapinput-forcejoy.ini\"\n    local -r force_key_file=\"$configdir/daphne/dapinput-forcekey.ini\"\n\n    local key\n    case \"$input_name\" in\n        up)\n            key=\"KEY_UP\"\n            ;;\n        down)\n            key=\"KEY_DOWN\"\n            ;;\n        left)\n            key=\"KEY_LEFT\"\n            ;;\n        right)\n            key=\"KEY_RIGHT\"\n            ;;\n        a)\n            key=\"KEY_BUTTON1\"\n            ;;\n        b)\n            key=\"KEY_BUTTON2\"\n            ;;\n        x)\n            key=\"KEY_BUTTON3\"\n            ;;\n        y)\n            key=\"KEY_COIN1\"\n            ;;\n        leftbottom)\n            key=\"KEY_SKILL1\"\n            ;;\n        rightbottom)\n            key=\"KEY_SKILL2\"\n            ;;\n        lefttop)\n            key=\"KEY_SKILL3\"\n            ;;\n        righttop)\n            key=\"KEY_SERVICE\"\n            ;;\n        start)\n            key=\"KEY_START1\"\n            ;;\n        select)\n            key=\"KEY_QUIT\"\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    local key_regex=\"^$key = (.*) (.*)\\$\"\n    local button_regex=\"^$key = (.*)\\$\"\n    local full_regex=\"^$key = (.*) (.*) (.*)\\$\"\n    local line\n    local key1\n    local key2\n    local button\n\n    # See if this key is specified in the override file...\n    while read -r line; do\n        if [[ \"$line\" =~ $key_regex ]]; then\n            key1=\"${BASH_REMATCH[1]}\"\n            key2=\"${BASH_REMATCH[2]}\"\n        fi\n    done < \"$force_key_file\"\n\n    # ...otherwise, use the defaults file.\n    if [[ -z \"$key1\" || -z \"$key2\" ]]; then\n        echo \"Keymap not found in $force_key_file\"\n        while read -r line; do\n            if [[ \"$line\" =~ $full_regex ]]; then\n                key1=\"${BASH_REMATCH[1]}\"\n                key2=\"${BASH_REMATCH[2]}\"\n            fi\n        done < \"$mapping_file\"\n    fi\n\n    # See if this button is specified in the override file...\n    while read -r line; do\n        if [[ \"$line\" =~ $button_regex ]]; then\n            button=\"${BASH_REMATCH[1]}\"\n        fi\n    done < \"$force_joy_file\"\n\n    # ...otherwise, use the config sent to this function.\n    if [[ -z \"$button\" ]]; then\n        while read -r line; do\n            if [[ \"$line\" =~ $key_regex ]]; then\n                button=$((input_id+1))\n            fi\n        done < \"$mapping_file\"\n    fi\n\n    # Write new button config\n    sed -i \"s/^$key = .* .* .*\\$/$key = $key1 $key2 $button/g\" \"$mapping_file\"\n}"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/emulationstation.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction onstart_emulationstation_joystick() {\n    local es_conf=\"$home/.emulationstation/es_input.cfg\"\n\n    mkdir -p \"$home/.emulationstation\"\n\n    if [[ ! -f \"$es_conf\" ]]; then\n        echo \"<inputList />\" >\"$es_conf\"\n    else\n        cp \"$es_conf\" \"$es_conf.bak\"\n    fi\n\n    # look for existing inputConfig in config by GUID\n    if [[ $(xmlstarlet sel -t -v \"count(/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"])\" \"$es_conf\") -eq 0 ]]; then\n        # if not found by GUID, look for inputConfig with deviceName only\n        if [[ $(xmlstarlet sel -t -v \"count(/inputList/inputConfig[@deviceName=\\\"$DEVICE_NAME\\\"][not(@deviceGUID)])\" \"$es_conf\") -eq 0 ]]; then\n            # insert new inputConfig entry\n            xmlstarlet ed -L -s \"/inputList\" -t elem -n newInputConfig -v \"\" \\\n                -i //newInputConfig -t attr -n \"type\" -v \"$DEVICE_TYPE\" \\\n                -i //newInputConfig -t attr -n \"deviceName\" -v \"$DEVICE_NAME\" \\\n                -i //newInputConfig -t attr -n \"deviceGUID\" -v \"$DEVICE_GUID\" \\\n                -r //newInputConfig -v inputConfig \\\n                \"$es_conf\"\n        else\n            # add deviceGUID to inputConfig\n            xmlstarlet ed -L \\\n                -i \"/inputList/inputConfig[@deviceName=\\\"$DEVICE_NAME\\\"]\" -t attr -n \"deviceGUID\" -v \"$DEVICE_GUID\" \\\n                \"$es_conf\"\n        fi\n    fi\n}\n\nfunction map_emulationstation_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local key\n    case \"$input_name\" in\n        leftbottom|leftshoulder)\n            key=\"pageup\"\n            ;;\n        rightbottom|rightshoulder)\n            key=\"pagedown\"\n            ;;\n        up|right|down|left|start|select|x|y|leftanalogup|leftanalogright|leftanalogdown|leftanalogleft|rightanalogup|rightanalogright|rightanalogdown|rightanalogleft)\n            key=\"$input_name\"\n            ;;\n        a)\n            key=\"$input_name\"\n            getAutoConf es_swap_a_b && key=\"b\"\n            ;;\n        b)\n            key=\"$input_name\"\n            getAutoConf es_swap_a_b && key=\"a\"\n            ;;\n        *)\n            return\n            ;;\n    esac\n    local es_conf=\"$home/.emulationstation/es_input.cfg\"\n\n    # add or update element\n    if [[ $(xmlstarlet sel -t -v \"count(/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"]/input[@name=\\\"$key\\\"])\" \"$es_conf\") -eq 0 ]]; then\n        xmlstarlet ed -L -s \"/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"]\" -t elem -n newinput -v \"\" \\\n            -i //newinput -t attr -n \"name\" -v \"$key\" \\\n            -i //newinput -t attr -n \"type\" -v \"$input_type\" \\\n            -i //newinput -t attr -n \"id\" -v \"$input_id\" \\\n            -i //newinput -t attr -n \"value\" -v \"$input_value\" \\\n            -r //newinput -v input \\\n            \"$es_conf\"\n    else  # if device already exists, update it\n        xmlstarlet ed -L \\\n            -u \"/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"]/input[@name=\\\"$key\\\"]/@type\" -v \"$input_type\" \\\n            -u \"/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"]/input[@name=\\\"$key\\\"]/@id\" -v \"$input_id\" \\\n            -u \"/inputList/inputConfig[@deviceGUID=\\\"$DEVICE_GUID\\\"]/input[@name=\\\"$key\\\"]/@value\" -v \"$input_value\" \\\n            \"$es_conf\"\n    fi\n}\n\nfunction onstart_emulationstation_keyboard() {\n    onstart_emulationstation_joystick \"$@\"\n}\n\nfunction map_emulationstation_keyboard() {\n    map_emulationstation_joystick \"$@\"\n}\n\nfunction onstart_emulationstation_cec() {\n    onstart_emulationstation_joystick \"$@\"\n}\n\nfunction map_emulationstation_cec() {\n    map_emulationstation_joystick \"$@\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/mupen64plus.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction onstart_mupen64plus_joystick() {\n    # write temp file header\n    echo \"; ${DEVICE_NAME}_START \" > /tmp/mp64tempconfig.cfg\n    echo \"[${DEVICE_NAME}]\" >> /tmp/mp64tempconfig.cfg\n    iniConfig \" = \" \"\" \"/tmp/mp64tempconfig.cfg\"\n    iniSet \"plugged\" \"True\"\n    iniSet \"plugin\" \"2\"\n    iniSet \"mouse\" \"False\"\n    iniSet \"AnalogDeadzone\" \"4096,4096\"\n    iniSet \"AnalogPeak\" \"32768,32768\"\n    iniSet \"Mempak switch\" \"\"\n    iniSet \"Rumblepak switch\" \"\"\n}\n\nfunction map_mupen64plus_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local keys\n    local dir\n    case \"$input_name\" in\n        up)\n            keys=(\"DPad U\")\n            dir=(\"Up\")\n            ;;\n        down)\n            keys=(\"DPad D\")\n            dir=(\"Down\")\n            ;;\n        left)\n            keys=(\"DPad L\")\n            dir=(\"Left\")\n            ;;\n        right)\n            keys=(\"DPad R\")\n            dir=(\"Right\")\n            ;;\n        b)\n            keys=(\"A Button\")\n            ;;\n        y)\n            keys=(\"B Button\")\n            ;;\n        a)\n            keys=(\"C Button D\")\n            ;;\n        x)\n            keys=(\"C Button U\")\n            ;;\n        leftbottom|leftshoulder)\n            keys=(\"L Trig\")\n            ;;\n        rightbottom|rightshoulder)\n            keys=(\"R Trig\")\n            ;;\n        lefttop|lefttrigger)\n            keys=(\"Z Trig\")\n            ;;\n        start)\n            keys=(\"Start\")\n            ;;\n        leftanalogleft)\n            keys=(\"X Axis\")\n            dir=(\"Left\")\n            ;;\n        leftanalogright)\n            keys=(\"X Axis\")\n            dir=(\"Right\")\n            ;;\n        leftanalogup)\n            keys=(\"Y Axis\")\n            dir=(\"Up\")\n            ;;\n        leftanalogdown)\n            keys=(\"Y Axis\")\n            dir=(\"Down\")\n            ;;\n        rightanalogleft)\n            keys=(\"C Button L\")\n            dir=(\"Left\")\n            ;;\n        rightanalogright)\n            keys=(\"C Button R\")\n            dir=(\"Right\")\n            ;;\n        rightanalogup)\n            keys=(\"C Button U\")\n            dir=(\"Up\")\n            ;;\n        rightanalogdown)\n            keys=(\"C Button D\")\n            dir=(\"Down\")\n            ;;\n        leftthumb)\n            keys=(\"Mempak switch\")\n            ;;\n        rightthumb)\n            keys=(\"Rumblepak switch\")\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    local key\n    local value\n    #iniConfig \" = \" \"\" \"/tmp/mp64keys.cfg\"\n    for key in \"${keys[@]}\"; do\n        # read key value. Axis takes two key/axis values.\n        iniGet \"$key\"\n        case \"$input_type\" in\n            axis)\n                # key \"X/Y Axis\" needs different button naming\n                if [[ \"$key\" == *Axis* ]]; then\n                    # if there is already a \"-\" axis add \"+\" axis value\n                    if   [[ \"$ini_value\" == *\\(* ]]; then\n                        value=\"${ini_value}${input_id}+)\"\n                    # if there is already a \"+\" axis add \"-\" axis value\n                    elif [[ \"$ini_value\" == *\\)* ]]; then\n                        value=\"axis(${input_id}-,${ini_value}\"\n                    # if there is no ini_value add \"+\" axis value\n                    elif [[ \"$input_value\" == \"1\" ]]; then\n                        value=\"${input_id}+)\"\n                    else\n                        value=\"axis(${input_id}-,\"\n                    fi\n                elif [[ \"$input_value\" == \"1\" ]]; then\n                    value=\"axis(${input_id}+) ${ini_value}\"\n                else\n                    value=\"axis(${input_id}-) ${ini_value}\"\n                fi\n                ;;\n            hat)\n                if [[ \"$key\" == *Axis* ]]; then\n                    if   [[ \"$ini_value\" == *\\(* ]]; then\n                        value=\"${ini_value}${dir})\"\n                    elif [[ \"$ini_value\" == *\\)* ]]; then\n                        value=\"hat(${input_id} ${dir} ${ini_value}\"\n                    elif [[ \"$dir\" == \"Up\" || \"$dir\" == \"Left\" ]]; then\n                        value=\"hat(${input_id} ${dir} \"\n                    elif [[ \"$dir\" == \"Right\" || \"$dir\" == \"Down\" ]]; then\n                        value=\"${dir})\"\n                    fi\n                else\n                    if [[ -n \"$dir\" ]]; then\n                        value=\"hat(${input_id} ${dir}) ${ini_value}\"\n                    fi\n                fi\n                ;;\n            *)\n                if [[ \"$key\" == *Axis* ]]; then\n                    if   [[ \"$ini_value\" == *\\(* ]]; then\n                        value=\"${ini_value}${input_id})\"\n                    elif [[ \"$ini_value\" == *\\)* ]]; then\n                        value=\"button(${input_id},${ini_value}\"\n                    elif [[ \"$dir\" == \"Up\" || \"$dir\" == \"Left\" ]]; then\n                        value=\"button(${input_id},\"\n                    elif [[ \"$dir\" == \"Right\" || \"$dir\" == \"Down\" ]]; then\n                        value=\"${input_id})\"\n                    fi\n                else\n                    value=\"button(${input_id}) ${ini_value}\"\n                fi\n                ;;\n        esac\n\n        iniSet \"$key\" \"$value\"\n    done\n}\n\nfunction onend_mupen64plus_joystick() {\n    local bind\n    local axis\n    local axis_neg\n    local axis_pos\n    for axis in \"X Axis\" \"Y Axis\"; do\n        if [[ \"$axis\" == *X* ]]; then\n            axis_neg=\"DPad L\"\n            axis_pos=\"DPad R\"\n        else\n            axis_neg=\"DPad U\"\n            axis_pos=\"DPad D\"\n        fi\n\n        # analog stick sanity check\n        # replace Axis values with DPAD values if there is no Axis\n        # device setup\n        if ! grep -q \"$axis\" /tmp/mp64tempconfig.cfg ; then\n            iniGet \"${axis_neg}\"\n            bind=${ini_value//)/,}\n            iniGet \"${axis_pos}\"\n            ini_value=${ini_value//axis(/}\n            ini_value=${ini_value//hat(/}\n            ini_value=${ini_value//button(/}\n            bind=\"${bind}${ini_value}\"\n            iniSet \"$axis\" \"$bind\"\n            iniDel \"${axis_neg}\"\n            iniDel \"${axis_pos}\"\n        fi\n    done\n\n    # If there is no Z Trig try to map the L shoulder\n    # button to it via copying over the existing L Trig\n    # value and deleting it (L Trig) after\n    if ! grep -q \"Z Trig\" /tmp/mp64tempconfig.cfg ; then\n        iniGet \"L Trig\"\n        iniSet \"Z Trig\" \"${ini_value}\"\n        iniDel \"L Trig\"\n    fi\n\n    echo \"; ${DEVICE_NAME}_END \" >> /tmp/mp64tempconfig.cfg\n    echo \"\" >> /tmp/mp64tempconfig.cfg\n\n    # abort if old device config cannot be deleted.\n    # keep original mupen64plus-input-sdl configs.\n    local file=\"$configdir/n64/InputAutoCfg.ini\"\n    if [[ -f \"$file\" ]]; then\n        # backup current config file\n        cp \"$file\" \"${file}.bak\"\n        local escaped_device_name=$(echo \"$DEVICE_NAME\" | sed 's|[]\\[^$.*/]|\\\\&|g')\n        sed -i /\"${escaped_device_name}_START\"/,/\"${escaped_device_name}_END\"/d \"$file\"\n        if grep -Fq \"$DEVICE_NAME\" \"$file\" ; then\n            rm /tmp/mp64tempconfig.cfg\n            return\n        fi\n    else\n        cat > \"$file\" << _EOF_\n; InputAutoCfg.ini for Mupen64Plus SDL Input plugin\n\n; Keyboard_START\n[Keyboard]\nplugged = True\nplugin = 2\nmouse = False\nDPad R = key(100)\nDPad L = key(97)\nDPad D = key(115)\nDPad U = key(119)\nStart = key(13)\nZ Trig = key(122)\nB Button = key(306)\nA Button = key(304)\nC Button R = key(108)\nC Button L = key(106)\nC Button D = key(107)\nC Button U = key(105)\nR Trig = key(99)\nL Trig = key(120)\nMempak switch = key(44)\nRumblepak switch = key(46)\nX Axis = key(276,275)\nY Axis = key(273,274)\n; Keyboard_END\n\n_EOF_\n    fi\n\n    # append temp device configuration to InputAutoCfg.ini\n    cat /tmp/mp64tempconfig.cfg >> \"$file\"\n    rm /tmp/mp64tempconfig.cfg\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/openmsx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction onstart_openmsx_joystick()\n{\n    truncate --size 0 /tmp/openMSXtemp.cfg\n}\n\n# Function to return the binding configuration string, when mapping to the MSX machine joystick\n# See https://openmsx.org/manual/commands.html#joystickN_config\nfunction _get_msx_bind()\n{\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n    declare -A sdl_hat_directions=([1]=\"U\" [2]=\"R\" [4]=\"D\" [8]=\"L\")\n\n    case \"$input_type\" in\n        button)\n            echo \"button${input_id}\"\n            ;;\n        axis)\n            if [[ $input_value =~ ^- ]]; then\n                echo \"-axis${input_id}\"\n            else\n                echo \"+axis${input_id}\"\n            fi\n            ;;\n        hat)\n            echo \"${sdl_hat_directions[${input_value}]}_hat${input_id}\"\n            ;;\n        *)\n            ;;\n    esac\n}\n\n# Function to return the binding configuration string, when mapping to openMSX emulator actions\n# See http://openmsx.org/manual/commands.html#bind\nfunction _get_emu_bind()\n{\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n    declare -A sdl_hat_directions=([1]=\"up\" [2]=\"right\" [4]=\"down\" [8]=\"left\")\n\n    case \"$input_type\" in\n        button)\n            echo \"button${input_id} down\"\n            ;;\n        axis)\n            if [[ $input_value =~ ^- ]]; then\n                echo \"axis${input_id} -1\"\n            else\n                echo \"+axis${input_id} +1\"\n            fi\n            ;;\n        hat)\n            echo \"hat${input_id} ${sdl_hat_directions[${input_value}]}\"\n            ;;\n        *)\n            ;;\n    esac\n}\n\nfunction map_openmsx_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local bind_msx_joystick=$(_get_msx_bind \"$1\" \"$2\" \"$3\" \"$4\")\n    local bind_msx_emulator=$(_get_emu_bind \"$1\" \"$2\" \"$3\" \"$4\")\n    local msx_key\n    local emu_key\n    local temp_conf=\"/tmp/openMSXtemp.cfg\"\n\n    case \"$input_name\" in\n        a)\n            msx_key=\"A\"\n            ;;\n        b)\n            msx_key=\"B\"\n            ;;\n        up|leftanalogup)\n            msx_key=\"UP\"\n            ;;\n        down|leftanalogdown)\n            msx_key=\"DOWN\"\n            ;;\n        left|leftanalogleft)\n            msx_key=\"LEFT\"\n            ;;\n        right|leftanalogright)\n            msx_key=\"RIGHT\"\n            ;;\n        x)\n            emu_key=\"keymatrixdown 6 0x40\" # F1\n            ;;\n        y)\n            emu_key=\"keymatrixdown 6 0x20\" # F2\n            ;;\n        lefttop|leftshoulder|pageup)\n            emu_key=\"keymatrixdown 6 0x80\" # F3\n            ;;\n        righttop|rightshoulder|pagedown)\n            emu_key=\"keymatrixdown 7 0x01\" # F4\n            ;;\n        start)\n            emu_key=\"main_menu_open\"\n            ;;\n        select)\n            emu_key=\"toggle_osd_keyboard\"\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    if [[ -n $msx_key ]]; then\n        echo \"    dict lappend joystick1_config $msx_key $bind_msx_joystick\" >> \"$temp_conf\"\n    fi\n\n    if [[ -n $emu_key ]]; then\n        # Don't try to bind a non-button input to a keyboard key, there's no 'release' event for axis/hat inputs\n        [[ $emu_key =~ ^keymatrixdown && ! $bind_msx_emulator =~ \"button\" ]] && return\n\n        echo \"    bind_default \\\"joy1 $bind_msx_emulator\\\" \\\"$emu_key\\\"\" >> \"$temp_conf\"\n        if [[ $emu_key =~ ^keymatrixdown ]]; then\n            echo \"    bind_default \\\"joy1 ${bind_msx_emulator//down/up}\\\" \\\"${emu_key//down/up}\\\"\" >>  \"$temp_conf\"\n        fi\n    fi\n\n    # Add an extra configuration for 'Start' to close the OSD menu\n    if [[ \"$input_name\" == \"start\" ]]; then\n        echo \"    bind \\\"joy1 ${bind_msx_emulator}\\\" -layer osd_menu \\\"main_menu_close\\\"\" >> \"$temp_conf\"\n    fi\n}\n\nfunction onend_openmsx_joystick() {\n    local conf\n\n    # sanitize filename\n    conf=${DEVICE_NAME//[:><?\\\"\\/\\\\|*]/}\n\n    mkdir -p \"$home/.openMSX/share/joystick/game\"\n    cat > \"$home/.openMSX/share/joystick/${conf}.tcl\" <<_EOF_\nproc auto_config_joypad { } {\n    # clear existing joypad configuration\n    global joystick1_config\n    dict for {btn binding} \\$joystick1_config { dict set joystick1_config \\$btn {} }\n\n$(sort /tmp/openMSXtemp.cfg )\n}\n_EOF_\n\n# Add a note about game overrides\ncat > \"$home/.openMSX/share/joystick/README.txt\" <<_EOF2_\nThis folder contains joypad configuration scripts, generated by EmulationStation's input configuration.\nThey are read by openMSX at start-up and loaded automatically when the corresponding joypad is plugged in.\n\nIf you wish to have a game specific joystick configuration, you can override the gamepad's configuration by:\n * copy an already existing controller '.tcl' configuration file to the 'game' subfolder.\n * edit the file and adjust the 'bind_default' commands or the 'joystick1_config' configuration.\n   See the openMSX documentation for how to use those commands:\n   - http://openmsx.org/manual/commands.html#bind\n   - https://openmsx.org/manual/commands.html#joystickN_config\n   - http://map.grauw.nl/articles/keymatrix.php\n * rename the new '.tcl' file so the name is similar to the disk/tape/rom name (i.e. 'Metal Gear.zip' will load 'Metal Gear.tcl').\n   If you are not sure which name to use, start the game, then press 'F10' and type 'guess_title', followed by Enter.\n   openMSX will print the content name, which you can then use as a filename for the override configuration file.\n   NOTE: special characters '(:?/\\*)', are automatically striped from the name so if your content file is 'ABC?.dsk',\n   then the configuration file should be 'ABC.tcl'.\n\n_EOF2_\n\n    rm /tmp/openMSXtemp.cfg\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/pifba.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction _get_config_pifba() {\n    echo \"$configdir/fba/fba2x.cfg\"\n}\n\nfunction _split_config_pifba() {\n    local cfg=\"$(_get_config_pifba)\"\n    sed -n '/\\[Keyboard\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pifba-kb.cfg\n    sed -n '/\\[Joystick\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pifba-js.cfg\n    sed -n '/\\[Graphics\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pifba-gfx.cfg\n}\n\nfunction check_pifba() {\n    [[ ! -f \"$(_get_config_pifba)\" ]] && return 1\n    return 0\n}\n\nfunction onstart_pifba_joystick() {\n    _split_config_pifba\n\n    iniConfig \"=\" \"\" /tmp/pifba-js.cfg\n}\n\nfunction onstart_pifba_keyboard() {\n    _split_config_pifba\n\n    iniConfig \"=\" \"\" /tmp/pifba-kb.cfg\n\n    sdl1_map\n}\n\nfunction map_pifba_keyboard() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local key\n    case \"$input_name\" in\n        up)\n            key=\"UP_1\"\n            ;;\n        down)\n            key=\"DOWN_1\"\n            ;;\n        left)\n            key=\"LEFT_1\"\n            ;;\n        right)\n            key=\"RIGHT_1\"\n            ;;\n        a)\n            key=\"A_1\"\n            ;;\n        b)\n            key=\"B_1\"\n            ;;\n        x)\n            key=\"X_1\"\n            ;;\n        y)\n            key=\"Y_1\"\n            ;;\n        leftbottom|leftshoulder)\n            key=\"L_1\"\n            ;;\n        rightbottom|rightshoulder)\n            key=\"R_1\"\n            ;;\n        start)\n            key=\"START_1\"\n            ;;\n        select)\n            key=\"SELECT_1\"\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    iniSet \"$key\" \"${sdl1_map[$input_id]}\"\n}\n\nfunction map_pifba_joystick() {\n    local input_name=\"$3\"\n    local input_type=\"$4\"\n    local input_id=\"$5\"\n    local input_value=\"$6\"\n\n    local key\n    case \"$input_name\" in\n        up|down)\n            key=\"JA_UD\"\n            ;;\n        left|right)\n            key=\"JA_LR\"\n            ;;\n        a)\n            key=\"A_1\"\n            ;;\n        b)\n            key=\"B_1\"\n            ;;\n        x)\n            key=\"X_1\"\n            ;;\n        y)\n            key=\"Y_1\"\n            ;;\n        leftbottom|leftshoulder)\n            key=\"L_1\"\n            ;;\n        rightbottom|rightshoulder)\n            key=\"R_1\"\n            ;;\n        start)\n            key=\"START_1\"\n            ;;\n        select)\n            key=\"SELECT_1\"\n            ;;\n        leftthumb)\n            key=\"QSAVE\"\n            ;;\n        rightthumb)\n            key=\"QLOAD\"\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    iniSet \"$key\" \"$input_id\"\n}\n\nfunction onend_pifba_joystick() {\n    local cfg=\"$configdir/fba/fba2x.cfg\"\n    cat \"/tmp/pifba-kb.cfg\" \"/tmp/pifba-js.cfg\" \"/tmp/pifba-gfx.cfg\" >\"$cfg\"\n    rm /tmp/pifba-{kb,js,gfx}.cfg\n}\n\nfunction onend_pifba_keyboard() {\n    onend_pifba_joystick\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/pisnes.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction _get_config_pisnes() {\n    echo \"$configdir/snes/snes9x.cfg\"\n}\n\nfunction _split_config_pisnes() {\n    local cfg=\"$(_get_config_pisnes)\"\n    sed -n '/\\[Keyboard\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pisnes-kb.cfg\n    sed -n '/\\[Joystick\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pisnes-js.cfg\n    sed -n '/\\[Graphics\\]/,/\\[/p' \"$cfg\" | head -n -1 >/tmp/pisnes-gfx.cfg\n}\n\nfunction check_pisnes() {\n    [[ ! -f \"$(_get_config_pisnes)\" ]] && return 1\n    return 0\n}\n\nfunction onstart_pisnes_joystick() {\n    _split_config_pisnes\n\n    iniConfig \"=\" \"\" /tmp/pisnes-js.cfg\n}\n\nfunction onstart_pisnes_keyboard() {\n    _split_config_pisnes\n\n    iniConfig \"=\" \"\" /tmp/pisnes-kb.cfg\n\n    sdl1_map\n}\n\nfunction map_pisnes_keyboard() {\n    map_pifba_keyboard \"$@\"\n}\n\nfunction map_pisnes_joystick() {\n    map_pifba_joystick \"$@\"\n}\n\nfunction onend_pisnes_joystick() {\n    local cfg=\"$configdir/snes/snes9x.cfg\"\n    cat \"/tmp/pisnes-kb.cfg\" \"/tmp/pisnes-js.cfg\" \"/tmp/pisnes-gfx.cfg\" >\"$cfg\"\n    rm /tmp/pisnes-{kb,js,gfx}.cfg\n}\n\nfunction onend_pisnes_keyboard() {\n    onend_pisnes_joystick\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/reicast.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction onstart_reicast_joystick() {\n    local file\n\n    case \"$DEVICE_NAME\" in\n        \"Xbox 360 Controller (xpad driver)\")\n            file=\"$configdir/dreamcast/mappings/controller_xpad.cfg\"\n            ;;\n        \"Xbox 360 Controller (xboxdrv userspace driver)\")\n            file=\"$configdir/dreamcast/mappings/controller_xboxdrv.cfg\"\n            ;;\n        *)\n            file=\"$configdir/dreamcast/mappings/evdev_${DEVICE_NAME//[:><?\\\"\\/\\\\|*]/-}.cfg\"\n            ;;\n    esac\n\n    # create mapping dir if necessary.\n    mkdir -p \"$configdir/dreamcast/mappings\"\n\n    # remove old config file\n    rm -f \"$file\"\n\n    # write config template\n    cat > \"$file\" << _EOF_\n[emulator]\nmapping_name =\nbtn_escape =\n\n[dreamcast]\nbtn_a =\nbtn_b =\nbtn_c =\nbtn_d =\nbtn_x =\nbtn_y =\nbtn_z =\nbtn_start =\nbtn_dpad1_left =\nbtn_dpad1_right =\nbtn_dpad1_up =\nbtn_dpad1_down =\nbtn_dpad2_left =\nbtn_dpad2_right =\nbtn_dpad2_up =\nbtn_dpad2_down =\naxis_x =\naxis_y =\naxis_trigger_left =\naxis_trigger_right =\n\n[compat]\nbtn_trigger_left =\nbtn_trigger_right =\naxis_dpad1_x =\naxis_dpad1_y =\naxis_dpad2_x =\naxis_dpad2_y =\naxis_x_inverted =\naxis_y_inverted =\naxis_trigger_left_inverted =\naxis_trigger_right_inverted =\n_EOF_\n\n    # write temp file header\n    iniConfig \" = \" \"\" \"$file\"\n    iniSet \"mapping_name\" \"$DEVICE_NAME\"\n}\n\nfunction map_reicast_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local keys\n    local dir\n    case \"$input_name\" in\n        up)\n            keys=(\"btn_dpad1_up\")\n            ;;\n        down)\n            keys=(\"btn_dpad1_down\")\n            ;;\n        left)\n            keys=(\"btn_dpad1_left\")\n            ;;\n        right)\n            keys=(\"btn_dpad1_right\")\n            ;;\n        a)\n            keys=(\"btn_b\")\n            ;;\n        b)\n            keys=(\"btn_a\")\n            ;;\n        x)\n            keys=(\"btn_y\")\n            ;;\n        y)\n            keys=(\"btn_x\")\n            ;;\n        leftbottom|leftshoulder)\n            keys=(\"btn_trigger_left\")\n            ;;\n        rightbottom|rightshoulder)\n            keys=(\"btn_trigger_right\")\n            ;;\n        lefttop|lefttrigger)\n            keys=(\"axis_trigger_left\")\n            ;;\n        righttop|righttrigger)\n            keys=(\"axis_trigger_right\")\n            ;;\n        start)\n            keys=(\"btn_start\")\n            ;;\n        select)\n            keys=(\"btn_escape\")\n            ;;\n        leftanalogleft)\n            keys=(\"axis_x\")\n            ;;\n        leftanalogright)\n            keys=(\"axis_x\")\n            ;;\n        leftanalogup)\n            keys=(\"axis_y\")\n            ;;\n        leftanalogdown)\n            keys=(\"axis_y\")\n            ;;\n        rightanalogleft)\n            keys=(\"axis_dpad1_x\")\n            ;;\n        rightanalogright)\n            keys=(\"axis_dpad1_x\")\n            ;;\n        rightanalogup)\n            keys=(\"axis_dpad1_y\")\n            ;;\n        rightanalogdown)\n            keys=(\"axis_dpad1_y\")\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    local key\n    local value\n    for key in \"${keys[@]}\"; do\n        # read key value. Axis takes two key/axis values.\n        case \"$input_type\" in\n            axis)\n                # key \"X/Y Axis\" needs different button naming\n                if [[ \"$key\" == \"btn_trigger_left\" ]] ; then\n                    iniSet \"axis_trigger_left\" \"$input_id\"\n                    iniSet \"axis_trigger_left_inverted\" \"no\"\n                elif [[ \"$key\" == \"btn_trigger_right\" ]] ; then\n                    iniSet \"axis_trigger_right\" \"$input_id\"\n                    iniSet \"axis_trigger_right_inverted\" \"no\"\n                elif [[ \"$key\" == \"btn_dpad1_up\" || \"$key\" == \"btn_dpad1_down\" ]]; then\n                    iniSet \"axis_y\" \"$input_id\"\n                    iniSet \"axis_y_inverted\" \"no\"\n                elif [[ \"$key\" == \"btn_dpad1_left\" || \"$key\" == \"btn_dpad1_right\" ]]; then\n                    iniSet \"axis_x\" \"$input_id\"\n                    iniSet \"axis_x_inverted\" \"no\"\n                elif [[ \"$key\" == *axis* ]] ; then\n                    case \"$DEVICE_NAME\" in\n                        \"Xbox 360 Controller (xpad driver)\"|\"Xbox 360 Controller (xboxdrv userspace driver)\"|\"Microsoft X-Box 360 pad\"|\"Xbox Gamepad (userspace driver)\"|\"Xbox 360 Wireless Receiver (XBOX)\"|\"Microsoft X-Box One pad\"|\"Microsoft X-Box pad (Japan)\"|\"Chinese-made Xbox Controller\")\n                            if [[ \"$input_id\" -gt 2 && \"$input_id\" -lt 5 ]]; then\n                                input_id=$(($input_id+13))\n                            fi\n                            ;;\n                    esac\n                    iniSet \"${key}\" \"$input_id\"\n                    iniSet \"${key}_inverted\" \"no\"\n                fi\n                ;;\n            hat)\n                ;;\n            *)\n                if [[ \"$key\" != *axis* ]] ; then\n                    # input_id must be recalculated: 288d = button 0\n                    input_id=$(($input_id+288))\n                    # workaround for specific controller button mismatch\n                    case \"$DEVICE_NAME\" in\n                        \"Xbox 360 Controller (xpad driver)\"|\"Xbox 360 Controller (xboxdrv userspace driver)\"|\"Microsoft X-Box 360 pad\"|\"Xbox Gamepad (userspace driver)\"|\"Xbox 360 Wireless Receiver (XBOX)\"|\"Microsoft X-Box One pad\"|\"Microsoft X-Box pad (Japan)\"|\"Chinese-made Xbox Controller\")\n                            if [[ \"$input_id\" -lt \"294\" ]]; then\n                                input_id=$(($input_id+16))\n                            else\n                                input_id=$(($input_id+20))\n                            fi\n                            ;;\n                    esac\n                    iniSet \"$key\" \"$input_id\"\n                fi\n                ;;\n        esac\n    done\n}\n\nfunction onend_reicast_joystick() {\n    local file\n\n    case \"$DEVICE_NAME\" in\n        \"Xbox 360 Controller (xpad driver)\")\n            file=\"$configdir/dreamcast/mappings/controller_xpad.cfg\"\n            ;;\n        \"Xbox 360 Controller (xboxdrv userspace driver)\")\n            file=\"$configdir/dreamcast/mappings/controller_xboxdrv.cfg\"\n            ;;\n        *)\n            file=\"$configdir/dreamcast/mappings/evdev_${DEVICE_NAME//[:><?\\\"\\/\\\\|*]/-}.cfg\"\n            ;;\n    esac\n\n    # add empty end line\n    echo \"\" >> \"$file\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/retroarch.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction onstart_retroarch_joystick() {\n    iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n    iniGet \"input_joypad_driver\"\n    local input_joypad_driver=\"$ini_value\"\n    if [[ -z \"$input_joypad_driver\" ]]; then\n        input_joypad_driver=\"udev\"\n    fi\n\n    _retroarch_select_hotkey=1\n\n    _atebitdo_hack=0\n    getAutoConf \"8bitdo_hack\" && _atebitdo_hack=1\n\n    iniConfig \" = \" \"\\\"\" \"/tmp/tempconfig.cfg\"\n    iniSet \"input_device\" \"$DEVICE_NAME\"\n    iniSet \"input_driver\" \"$input_joypad_driver\"\n    # add vendor and product ids if non-empty\n    if [[ -n \"$VENDOR_ID\" && -n \"$PRODUCT_ID\" ]]; then\n        iniSet \"input_vendor_id\" \"$VENDOR_ID\"\n        iniSet \"input_product_id\" \"$PRODUCT_ID\"\n    fi\n}\n\nfunction onstart_retroarch_keyboard() {\n    iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n\n    _retroarch_select_hotkey=1\n\n    declare -Ag retroarchkeymap\n    # SDL codes from https://wiki.libsdl.org/SDLKeycodeLookup\n    retroarchkeymap[\"1073741904\"]=\"left\"\n    retroarchkeymap[\"1073741903\"]=\"right\"\n    retroarchkeymap[\"1073741906\"]=\"up\"\n    retroarchkeymap[\"1073741905\"]=\"down\"\n    retroarchkeymap[\"13\"]=\"enter\"\n    retroarchkeymap[\"1073741912\"]=\"kp_enter\"\n    retroarchkeymap[\"9\"]=\"tab\"\n    retroarchkeymap[\"1073741897\"]=\"insert\"\n    retroarchkeymap[\"127\"]=\"del\"\n    retroarchkeymap[\"1073741901\"]=\"end\"\n    retroarchkeymap[\"1073741898\"]=\"home\"\n    retroarchkeymap[\"1073742053\"]=\"rshift\"\n    retroarchkeymap[\"1073742049\"]=\"shift\"\n    retroarchkeymap[\"1073742048\"]=\"ctrl\"\n    retroarchkeymap[\"1073742050\"]=\"alt\"\n    retroarchkeymap[\"32\"]=\"space\"\n    retroarchkeymap[\"27\"]=\"escape\"\n    retroarchkeymap[\"43\"]=\"add\"\n    retroarchkeymap[\"45\"]=\"subtract\"\n    retroarchkeymap[\"1073741911\"]=\"kp_plus\"\n    retroarchkeymap[\"1073741910\"]=\"kp_minus\"\n    retroarchkeymap[\"1073741882\"]=\"f1\"\n    retroarchkeymap[\"1073741883\"]=\"f2\"\n    retroarchkeymap[\"1073741884\"]=\"f3\"\n    retroarchkeymap[\"1073741885\"]=\"f4\"\n    retroarchkeymap[\"1073741886\"]=\"f5\"\n    retroarchkeymap[\"1073741887\"]=\"f6\"\n    retroarchkeymap[\"1073741888\"]=\"f7\"\n    retroarchkeymap[\"1073741889\"]=\"f8\"\n    retroarchkeymap[\"1073741890\"]=\"f9\"\n    retroarchkeymap[\"1073741891\"]=\"f10\"\n    retroarchkeymap[\"1073741892\"]=\"f11\"\n    retroarchkeymap[\"1073741893\"]=\"f12\"\n    retroarchkeymap[\"48\"]=\"num0\"\n    retroarchkeymap[\"49\"]=\"num1\"\n    retroarchkeymap[\"50\"]=\"num2\"\n    retroarchkeymap[\"51\"]=\"num3\"\n    retroarchkeymap[\"52\"]=\"num4\"\n    retroarchkeymap[\"53\"]=\"num5\"\n    retroarchkeymap[\"54\"]=\"num6\"\n    retroarchkeymap[\"55\"]=\"num7\"\n    retroarchkeymap[\"56\"]=\"num8\"\n    retroarchkeymap[\"57\"]=\"num9\"\n    retroarchkeymap[\"1073741899\"]=\"pageup\"\n    retroarchkeymap[\"1073741902\"]=\"pagedown\"\n    retroarchkeymap[\"1073741922\"]=\"keypad0\"\n    retroarchkeymap[\"1073741913\"]=\"keypad1\"\n    retroarchkeymap[\"1073741914\"]=\"keypad2\"\n    retroarchkeymap[\"1073741915\"]=\"keypad3\"\n    retroarchkeymap[\"1073741916\"]=\"keypad4\"\n    retroarchkeymap[\"1073741917\"]=\"keypad5\"\n    retroarchkeymap[\"1073741918\"]=\"keypad6\"\n    retroarchkeymap[\"1073741919\"]=\"keypad7\"\n    retroarchkeymap[\"1073741920\"]=\"keypad8\"\n    retroarchkeymap[\"1073741921\"]=\"keypad9\"\n    retroarchkeymap[\"46\"]=\"period\"\n    retroarchkeymap[\"1073741881\"]=\"capslock\"\n    retroarchkeymap[\"1073741907\"]=\"numlock\"\n    retroarchkeymap[\"8\"]=\"backspace\"\n    retroarchkeymap[\"42\"]=\"multiply\"\n    retroarchkeymap[\"47\"]=\"divide\"\n    retroarchkeymap[\"1073741894\"]=\"print_screen\"\n    retroarchkeymap[\"1073741895\"]=\"scroll_lock\"\n    retroarchkeymap[\"96\"]=\"backquote\"\n    retroarchkeymap[\"1073741896\"]=\"pause\"\n    retroarchkeymap[\"39\"]=\"quote\"\n    retroarchkeymap[\"44\"]=\"comma\"\n    retroarchkeymap[\"45\"]=\"minus\"\n    retroarchkeymap[\"47\"]=\"slash\"\n    retroarchkeymap[\"59\"]=\"semicolon\"\n    retroarchkeymap[\"61\"]=\"equals\"\n    retroarchkeymap[\"91\"]=\"leftbracket\"\n    retroarchkeymap[\"92\"]=\"backslash\"\n    retroarchkeymap[\"93\"]=\"rightbracket\"\n    retroarchkeymap[\"1073741923\"]=\"kp_period\"\n    retroarchkeymap[\"1073741927\"]=\"kp_equals\"\n    retroarchkeymap[\"1073742052\"]=\"rctrl\"\n    retroarchkeymap[\"1073742054\"]=\"ralt\"\n    retroarchkeymap[\"97\"]=\"a\"\n    retroarchkeymap[\"98\"]=\"b\"\n    retroarchkeymap[\"99\"]=\"c\"\n    retroarchkeymap[\"100\"]=\"d\"\n    retroarchkeymap[\"101\"]=\"e\"\n    retroarchkeymap[\"102\"]=\"f\"\n    retroarchkeymap[\"103\"]=\"g\"\n    retroarchkeymap[\"104\"]=\"h\"\n    retroarchkeymap[\"105\"]=\"i\"\n    retroarchkeymap[\"106\"]=\"j\"\n    retroarchkeymap[\"107\"]=\"k\"\n    retroarchkeymap[\"108\"]=\"l\"\n    retroarchkeymap[\"109\"]=\"m\"\n    retroarchkeymap[\"110\"]=\"n\"\n    retroarchkeymap[\"111\"]=\"o\"\n    retroarchkeymap[\"112\"]=\"p\"\n    retroarchkeymap[\"113\"]=\"q\"\n    retroarchkeymap[\"114\"]=\"r\"\n    retroarchkeymap[\"115\"]=\"s\"\n    retroarchkeymap[\"116\"]=\"t\"\n    retroarchkeymap[\"117\"]=\"u\"\n    retroarchkeymap[\"118\"]=\"v\"\n    retroarchkeymap[\"119\"]=\"w\"\n    retroarchkeymap[\"120\"]=\"x\"\n    retroarchkeymap[\"121\"]=\"y\"\n    retroarchkeymap[\"122\"]=\"z\"\n\n    # special case for disabled hotkey\n    retroarchkeymap[\"0\"]=\"nul\"\n}\n\nfunction map_retroarch_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local keys\n    case \"$input_name\" in\n        up)\n            keys=(\"input_up\")\n            ;;\n        down)\n            keys=(\"input_down\")\n            ;;\n        left)\n            keys=(\"input_left\" \"input_state_slot_decrease\")\n            ;;\n        right)\n            keys=(\"input_right\" \"input_state_slot_increase\")\n            ;;\n        a)\n            keys=(\"input_a\")\n            ;;\n        b)\n            keys=(\"input_b\" \"input_reset\")\n            ;;\n        x)\n            keys=(\"input_x\" \"input_menu_toggle\")\n            ;;\n        y)\n            keys=(\"input_y\")\n            ;;\n        leftbottom|leftshoulder)\n            keys=(\"input_l\" \"input_load_state\")\n            ;;\n        rightbottom|rightshoulder)\n            keys=(\"input_r\" \"input_save_state\")\n            ;;\n        lefttop|lefttrigger)\n            keys=(\"input_l2\")\n            ;;\n        righttop|righttrigger)\n            keys=(\"input_r2\")\n            ;;\n        leftthumb)\n            keys=(\"input_l3\")\n            ;;\n        rightthumb)\n            keys=(\"input_r3\")\n            ;;\n        start)\n            keys=(\"input_start\" \"input_exit_emulator\")\n            ;;\n        select)\n            keys=(\"input_select\")\n            ;;\n        leftanalogleft)\n            keys=(\"input_l_x_minus\")\n            ;;\n        leftanalogright)\n            keys=(\"input_l_x_plus\")\n            ;;\n        leftanalogup)\n            keys=(\"input_l_y_minus\")\n            ;;\n        leftanalogdown)\n            keys=(\"input_l_y_plus\")\n            ;;\n        rightanalogleft)\n            keys=(\"input_r_x_minus\")\n            ;;\n        rightanalogright)\n            keys=(\"input_r_x_plus\")\n            ;;\n        rightanalogup)\n            keys=(\"input_r_y_minus\")\n            ;;\n        rightanalogdown)\n            keys=(\"input_r_y_plus\")\n            ;;\n        hotkeyenable)\n            keys=(\"input_enable_hotkey\")\n            _retroarch_select_hotkey=0\n            if [[ \"$input_type\" == \"key\" && \"$input_id\" == \"0\" ]]; then\n                return\n            fi\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    local key\n    local value\n    local type\n    declare -A hat_map=([1]=\"up\" [2]=\"right\" [4]=\"down\" [8]=\"left\")\n    iniGet \"input_driver\"\n    local input_driver=\"$ini_value\"\n    local autoconfig_preset=$(grep -rwFl \"$rootdir/emulators/retroarch/autoconfig-presets/$input_driver\" -e \"$DEVICE_NAME\" | head -1)\n    for key in \"${keys[@]}\"; do\n        case \"$input_type\" in\n            hat)\n                # check if hat input value is correct\n                [[ -z ${hat_map[$input_value]} ]] && return\n                type=\"btn\"\n                value=\"h$input_id${hat_map[$input_value]}\"\n                ;;\n            axis)\n                type=\"axis\"\n                if [[ \"$input_value\" == \"1\" ]]; then\n                    value=\"+$input_id\"\n                else\n                    value=\"-$input_id\"\n                fi\n                ;;\n            *)\n                type=\"btn\"\n                value=\"$input_id\"\n\n                # workaround for mismatched controller mappings\n                if [[ \"$input_driver\" == \"udev\" ]]; then\n                    case \"$DEVICE_NAME\" in\n                        \"8Bitdo FC30\"*|\"8Bitdo NES30\"*|\"8Bitdo SFC30\"*|\"8Bitdo SNES30\"*|\"8Bitdo Zero\"*)\n                            if [[ \"$_atebitdo_hack\" -eq 1 ]]; then\n                                value=\"$((input_id+11))\"\n                            fi\n                            ;;\n                    esac\n                fi\n                ;;\n        esac\n        if [[ \"$input_name\" == \"select\" && \"$_retroarch_select_hotkey\" -eq 1 ]]; then\n            _retroarch_select_type=\"$type\"\n        fi\n        key+=\"_$type\"\n        iniSet \"$key\" \"$value\"\n\n        # set button labels from autoconfig preset (if available), when binding matches the preset\n        if [[ -f \"$autoconfig_preset\" ]]; then\n            iniGet \"$key\" \"$autoconfig_preset\"\n            if [[ \"$ini_value\" == \"$value\" ]]; then\n                key+=\"_label\"\n                iniGet \"$key\" \"$autoconfig_preset\"\n                [[ -n \"$ini_value\" ]] && iniSet \"$key\" \"$ini_value\"\n            fi\n        fi\n    done\n}\n\nfunction map_retroarch_keyboard() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n\n    local key\n    case \"$input_name\" in\n        up)\n            keys=(\"input_player1_up\")\n            ;;\n        down)\n            keys=(\"input_player1_down\")\n            ;;\n        left)\n            keys=(\"input_player1_left\" \"input_state_slot_decrease\")\n            ;;\n        right)\n            keys=(\"input_player1_right\" \"input_state_slot_increase\")\n            ;;\n        a)\n            keys=(\"input_player1_a\")\n            ;;\n        b)\n            keys=(\"input_player1_b\" \"input_reset\")\n            ;;\n        x)\n            keys=(\"input_player1_x\" \"input_menu_toggle\")\n            ;;\n        y)\n            keys=(\"input_player1_y\")\n            ;;\n        leftbottom|leftshoulder)\n            keys=(\"input_player1_l\" \"input_load_state\")\n            ;;\n        rightbottom|rightshoulder)\n            keys=(\"input_player1_r\" \"input_save_state\")\n            ;;\n        lefttop|lefttrigger)\n            keys=(\"input_player1_l2\")\n            ;;\n        righttop|righttrigger)\n            keys=(\"input_player1_r2\")\n            ;;\n        leftthumb)\n            keys=(\"input_player1_l3\")\n            ;;\n        rightthumb)\n            keys=(\"input_player1_r3\")\n            ;;\n        start)\n            keys=(\"input_player1_start\" \"input_exit_emulator\")\n            ;;\n        select)\n            keys=(\"input_player1_select\")\n            ;;\n        hotkeyenable)\n            keys=(\"input_enable_hotkey\")\n            _retroarch_select_hotkey=0\n            ;;\n        *)\n            return\n            ;;\n    esac\n\n    for key in \"${keys[@]}\"; do\n        iniSet \"$key\" \"${retroarchkeymap[$input_id]}\"\n    done\n}\n\nfunction onend_retroarch_joystick() {\n    # if $_retroarch_select_hotkey is set here, then there was no hotkeyenable button\n    # in the configuration, so we should use the select button as hotkey enable if set\n    if [[ \"$_retroarch_select_hotkey\" -eq 1 ]]; then\n        iniGet \"input_select_${_retroarch_select_type}\"\n        [[ -n \"$ini_value\" ]] && iniSet \"input_enable_hotkey_${_retroarch_select_type}\" \"$ini_value\"\n    fi\n\n    # hotkey sanity check\n    # remove hotkeys if there is no hotkey enable button\n    if ! grep -q \"input_enable_hotkey\" /tmp/tempconfig.cfg; then\n        local key\n        for key in input_state_slot_decrease input_state_slot_increase input_reset input_menu_toggle input_load_state input_save_state input_exit_emulator; do\n            sed -i \"/$key/d\" /tmp/tempconfig.cfg\n        done\n    fi\n\n    # disable any auto configs for the same device to avoid duplicates\n    local file\n    local dir=\"$configdir/all/retroarch-joypads\"\n    while read -r file; do\n        mv \"$file\" \"$file.bak\"\n    done < <(grep -Fl \"\\\"$DEVICE_NAME\\\"\" \"$dir/\"*.cfg 2>/dev/null)\n\n    # sanitise filename\n    file=\"${DEVICE_NAME//[:><?\\\"\\/\\\\|*]/}.cfg\"\n\n    if [[ -f \"$dir/$file\" ]]; then\n        mv \"$dir/$file\" \"$dir/$file.bak\"\n    fi\n    mv \"/tmp/tempconfig.cfg\" \"$dir/$file\"\n}\n\nfunction onend_retroarch_keyboard() {\n    if [[ \"$_retroarch_select_hotkey\" -eq 1 ]]; then\n        iniGet \"input_player1_select\"\n        iniSet \"input_enable_hotkey\" \"$ini_value\"\n    fi\n\n    # hotkey sanity check\n    # remove hotkeys if there is no hotkey enable button\n    iniGet \"input_enable_hotkey\"\n    if [[ -z \"$ini_value\" || \"$ini_value\" == \"nul\" ]]; then\n        iniSet \"input_state_slot_decrease\" \"\"\n        iniSet \"input_state_slot_increase\" \"\"\n        iniSet \"input_reset\" \"\"\n        iniSet \"input_menu_toggle\" \"f1\"\n        iniSet \"input_load_state\" \"\"\n        iniSet \"input_save_state\" \"\"\n        iniSet \"input_exit_emulator\" \"escape\"\n        iniSet \"input_shader_next\" \"\"\n        iniSet \"input_shader_prev\" \"\"\n        iniSet \"input_rewind\" \"\"\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/configscripts/sdl2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n# This input configuration script will create a SDL(2) GameController mapping string based on the user's choices (see [1] for the format).\n# The mapping is a comma (,) separated string of 'parameter:value' used by SDL to use the GameController.\n# SDL2 comes with it's own list of built-in mappings, defined in [2], which covers most of the well-known gamepads, but offers the ability\n# to:\n# - load additional mappings programmatically from a file using [3].\n#   This is the approach used by emulators that include an additional `gamecontrollerdb.txt` to allow extending the default SDL gamecontroller mapping database.\n# - load additional mappings from the `SDL_GAMECONTROLLERCONFIG` environment variable, which should contain newline delimited list of mappings (see [4])\n# - load additional mappings from the file pointed with `SDL_GAMECONTROLLERCONFIG_FILE` environment variable, containing newline delimited list of mapping (see [5]). Available only from SDL 2.0.22.\n#\n# The script will produce a mapping string for a configured joystick in EmulationStation, then store the result in:\n#   /opt/retropie/configs/all/sdl2_gamecontrollerdb.txt\n# This file can then be consulted by `runcommand` and the new mappings referenced via SDL2 hints.\n#\n# Notes:\n#   - this script will not replace the default/built-in SDL mappings\n#   - gamecontroller naming sanitization is not identical to SDL name mapping routines, but that doesn't affect functionality\n#\n# Ref:\n# [1] https://wiki.libsdl.org/SDL2/SDL_GameControllerAddMapping\n# [2] https://github.com/libsdl-org/SDL/blob/SDL2/src/joystick/SDL_gamecontrollerdb.h\n# [3] https://wiki.libsdl.org/SDL2/SDL_GameControllerAddMappingsFromFile\n# [4] https://wiki.libsdl.org/SDL2/SDL_HINT_GAMECONTROLLERCONFIG\n# [5] https://wiki.libsdl.org/SDL2/SDL_HINT_GAMECONTROLLERCONFIG_FILE\n\nfunction onstart_sdl2_joystick() {\n    # save the intermediary mappings into a temporary file\n    local temp_file\n    temp_file=\"$(_temp_file_sdl2)\"\n    : > \"$temp_file\"\n}\n\nfunction map_sdl2_joystick() {\n    local input_name=\"$1\"\n    local input_type=\"$2\"\n    local input_id=\"$3\"\n    local input_value=\"$4\"\n    local input_temp_map=\"$(_temp_file_sdl2)\"\n\n    # map ES input name => SDL Gamecontroller mapping label\n    declare -A input_map=(\n                      [up]=\"dpup\"\n                    [down]=\"dpdown\"\n                    [left]=\"dpleft\"\n                   [right]=\"dpright\"\n                       [a]=\"a\"\n                       [b]=\"b\"\n                       [x]=\"x\"\n                       [y]=\"y\"\n                   [start]=\"start\"\n                  [select]=\"back\"\n\n            [hotkeyenable]=\"guide\"\n\n            [leftshoulder]=\"leftshoulder\"\n             [lefttrigger]=\"lefttrigger\"\n           [rightshoulder]=\"rightshoulder\"\n            [righttrigger]=\"righttrigger\"\n\n               [leftthumb]=\"leftstick\"\n         [leftanalogright]=\"leftx\"\n          [leftanalogdown]=\"lefty\"\n\n              [rightthumb]=\"rightstick\"\n        [rightanalogright]=\"rightx\"\n         [rightanalogdown]=\"righty\"\n\n                  [pageup]=\"rightshoulder\"\n                [pagedown]=\"leftshoulder\"\n    )\n    local sdl2_mapped_input\n\n    sdl2_mapped_input=${input_map[$input_name]}\n\n    # when the SDL mapped action/input is not defined skip the mapping\n    [[ -z \"$sdl2_mapped_input\" ]] && return\n\n    case \"$input_type\" in\n       axis)\n           # add the direction for D-Pads only\n           if [[ \"$sdl2_mapped_input\" == \"dp\"* ]]; then\n               if [[ \"$input_value\" == \"-1\" ]]; then\n                   echo \"$sdl2_mapped_input:-a${input_id}\" >> \"$input_temp_map\"\n               else\n                   echo \"$sdl2_mapped_input:+a${input_id}\" >> \"$input_temp_map\"\n               fi\n            else\n                 echo \"$sdl2_mapped_input:a${input_id}\" >> \"$input_temp_map\"\n            fi\n           ;;\n       hat)\n           echo \"$sdl2_mapped_input:h${input_id}.${input_value}\" >> \"$input_temp_map\"\n           ;;\n       button)\n           echo \"$sdl2_mapped_input:b${input_id}\" >> \"$input_temp_map\"\n           ;;\n       *)\n           ;;\n     esac\n}\n\nfunction onend_sdl2_joystick() {\n    # check whether SDL2 already has a mapping for this GUID\n    if [[ \"$(_check_gamepad_sdl2)\" == \"MAPPED\" ]]; then\n        echo \"W: Device \\\"$DEVICE_NAME\\\" (guid: $DEVICE_GUID) is already known by SDL2, gamecontroller mapping was not created\"\n        return\n    fi\n\n    # gamecontroller name sanitization:\n    # - replace unexpected chars with '-'\n    # - trim blanks from the name (beginning/end)\n    # - replace ',' with space, since ',' is a delimiter in the mapping string\n    local joyname=\"$(echo ${DEVICE_NAME//[:><?\\\"\\/\\\\|*]/-} | tr -s '[:blank:]' | tr ',' ' ')\"\n    local select_value\n    local hotkey_value\n    local mapping\n    local input_temp_map\n    input_temp_map=\"$(_temp_file_sdl2)\"\n\n    # add each mapping value and save the values for Select/Back Hotkey/Guide\n    # don't add the Hotkey/Guide mapping yet\n    while read m; do\n       if [[ \"$m\" == \"guide:*\" ]]; then\n            hotkey_value=\"$m\";\n            continue;\n        fi\n\n        if [[ \"$m\" == \"back:*\" ]]; then\n            select_value=\"$m\";\n        fi\n\n        mapping+=\"$m,\"\n     done < <(sort \"$input_temp_map\")\n\n    # add the mapping for Hotkey as Guide IIF it's different than Select\n    if [[ $select_value != $hotkey_value && -n \"$hotkey_value\" ]]; then\n        mapping+=\"$hotkey_value,\"\n    fi\n    local sdl_configs=\"$configdir/all/sdl2_gamecontrollerdb.txt\"\n    mapping=\"${DEVICE_GUID},${joyname},platform:Linux,${mapping}\"\n\n    [[ -n $__debug ]] && \\\n        echo \"Mapping is $mapping\"\n\n    # update the mapping when it's present, otherwise append it to the file\n    if grep --silent --no-messages ${DEVICE_GUID} \"$sdl_configs\"; then\n        sed -i \"s/^${DEVICE_GUID}.*$/$mapping/\" \"$sdl_configs\"\n    else\n        echo \"$mapping\" >> \"$sdl_configs\"\n    fi\n    rm -f \"$input_temp_map\"\n}\n\n# function to check whether a gamepad GUID is already in SDL2's mapping list\n# we need to load SDL2's GameController subsystem and query by GUID\nfunction _check_gamepad_sdl2() {\n\ncat << EOF > \"/tmp/guid_check.py\"\nfrom sdl2 import SDL_GameControllerMappingForGUID,\\\n    SDL_Init,SDL_Quit,SDL_Error,\\\n    SDL_INIT_GAMECONTROLLER\nfrom sdl2.joystick import SDL_JoystickGetGUIDFromString\n\nif SDL_Init(SDL_INIT_GAMECONTROLLER) < 0:\n    exit(2)\n\nguid_str=b\"${DEVICE_GUID}\"\nguid = SDL_JoystickGetGUIDFromString(guid_str)\nmap = SDL_GameControllerMappingForGUID(guid)\nSDL_Quit()\n\nif map is not None:\n    exit(0)\n\nexit(1)\nEOF\n    python3 /tmp/guid_check.py 1>/dev/null 2>&1 && echo \"MAPPED\"\n    rm -f \"/tmp/guid_check.py\"\n}\n\nfunction _temp_file_sdl2() {\n    echo \"/tmp/sdl2temp.txt\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation/inputconfiguration.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## @file scriptmodules/supplementary/emulationstation/inputconfiguration.sh\n## @brief input configuration script\n## @copyright GPLv3\n## @details\n## @par global variables\n##\n## There are 5 global variables which are set to the current device being processed\n##\n## `DEVICE_TYPE` = device type is currently either joystick, keyboard or cec\n## `DEVICE_NAME` = name of the device\n## `DEVICE_GUID` = SDL2 joystick GUID of the device (-1 for keyboard, -2 for cec)\n## `VENDOR_ID`   = the USB vendor ID of the device\n## `PRODUCT_ID`  = the USB product ID of the device\n## @par Interface functions\n##\n## each input configuration module can have an optional function\n## `check_<filename without extension>`. If this function returns 1, the module is\n## skipped. This can be used to skip input configurations in some cases - eg\n## to skip configuration when an existing config file is not installed.\n##\n## There are 3 main interface functions for each of the input types (joystick/keyboard)\n##\n## function `onstart_<filename without extension>_<inputtype>()`\n## is run at the start of the input configuration\n##\n## function `onend_<filename without extension>_<inputtype>()`\n## is run at the end of the input configuration\n##\n## Returns:\n##   None\n##\n## function map_<filename without extension>_<inputtype>()\n## is run for each of the inputs - with the following arguments\n##\n## Arguments:\n## * $1 - input name is one of the following\n##  * up, down, left, right\n##  * a, b, x, y\n##  * leftshoulder, rightshoulder, lefttrigger, righttrigger\n##  * leftthumb. rightthumb\n##  * start, select\n##  * leftanalogup, leftanalogdown, leftanalogleft, leftanalogright\n##  * rightanalogup, rightanalogdown, rightanalogleft, rightanalogright\n## * $2 - input type is button, axis or hat for joysticks, key for keyboard and button for cec.\n## * $3 - button id of the input for a joystick, SDL2 keycode for a keyboard, or button id for cec.\n## * $4 - value of the joystick input or 1 for keyboard and cec.\n##\n## Returns:\n##   None\n\nfunction inputconfiguration() {\n\n    local es_conf=\"$home/.emulationstation/es_temporaryinput.cfg\"\n    declare -A mapping\n\n    # check if we have the temporary input file\n    [[ ! -f \"$es_conf\" ]] && return\n\n    local line\n    while read line; do\n        if [[ -n \"$line\" ]]; then\n            local input=($line)\n            mapping[\"${input[0]}\"]=${input[@]:1}\n        fi\n    done < <(xmlstarlet sel --text -t -m \"/inputList/inputConfig/input\"  -v \"concat(@name,' ',@type,' ',@id,' ',@value)\" -n \"$es_conf\")\n\n    local inputscriptdir=$(dirname \"$0\")\n    local inputscriptdir=$(cd \"$inputscriptdir\" && pwd)\n\n    DEVICE_TYPE=$(xmlstarlet sel --text -t -v \"/inputList/inputConfig/@type\" \"$es_conf\")\n    DEVICE_NAME=$(xmlstarlet sel --text -t -v \"/inputList/inputConfig/@deviceName\" \"$es_conf\")\n    DEVICE_GUID=$(xmlstarlet sel --text -t -v \"/inputList/inputConfig/@deviceGUID\" \"$es_conf\")\n    VENDOR_ID=$(xmlstarlet sel --text -t -v \"/inputList/inputConfig/@vendorId\" \"$es_conf\")\n    PRODUCT_ID=$(xmlstarlet sel --text -t -v \"/inputList/inputConfig/@productId\" \"$es_conf\")\n\n    echo \"Input type is '$DEVICE_TYPE'.\"\n\n    local module\n    # call all configuration modules with the\n    for module in $(find \"$inputscriptdir/configscripts/\" -maxdepth 1 -name \"*.sh\" | sort); do\n\n        source \"$module\"  # register functions from emulatorconfigs folder\n        local module_id=${module##*/}\n        local module_id=${module_id%.sh}\n\n        local funcname=\"check_${module_id}\"\n        # call check_module to check if we should run it\n        if fn_exists \"$funcname\"; then\n            \"$funcname\" || continue\n        fi\n\n        echo \"Configuring '$module_id'\"\n\n        # at the start, the onstart_module function is called.\n        funcname=\"onstart_${module_id}_${DEVICE_TYPE}\"\n        fn_exists \"$funcname\" && \"$funcname\"\n\n        local input_name\n        # loop through all buttons and use corresponding config function if it exists\n        for input_name in \"${!mapping[@]}\"; do\n            funcname=\"map_${module_id}_${DEVICE_TYPE}\"\n\n            if fn_exists \"$funcname\"; then\n                local params=(${mapping[$input_name]})\n                local input_type=${params[0]}\n                local input_id=${params[1]}\n                local input_value=${params[2]}\n\n                \"$funcname\" \"$input_name\" \"$input_type\" \"$input_id\" \"$input_value\"\n            fi\n        done\n\n        # at the end, the onend_module function is called\n        funcname=\"onend_${module_id}_${DEVICE_TYPE}\"\n        fn_exists \"$funcname\" && \"$funcname\"\n\n    done\n\n}\n\nfunction fn_exists() {\n    declare -f \"$1\" > /dev/null\n    return $?\n}\n\nfunction sdl1_map() {\n    # check if sdl1_map already exists\n    [[ -v sdl1_map[@] ]] && return\n\n    # SDL codes from https://wiki.libsdl.org/SDLKeycodeLookup mapped to /usr/include/SDL/SDL_keysym.h\n    declare -Ag sdl1_map\n    local i\n    for i in {0..127}; do\n        sdl1_map[\"$i\"]=\"$i\"\n    done\n\n    sdl1_map[\"1073741881\"]=\"301\" # SDLK SDLK_CAPSLOCK\n    sdl1_map[\"1073741882\"]=\"282\" # SDLK SDLK_F1\n    sdl1_map[\"1073741883\"]=\"283\" # SDLK SDLK_F2\n    sdl1_map[\"1073741884\"]=\"284\" # SDLK SDLK_F3\n    sdl1_map[\"1073741885\"]=\"285\" # SDLK SDLK_F4\n    sdl1_map[\"1073741886\"]=\"286\" # SDLK SDLK_F5\n    sdl1_map[\"1073741887\"]=\"287\" # SDLK SDLK_F6\n    sdl1_map[\"1073741888\"]=\"288\" # SDLK SDLK_F7\n    sdl1_map[\"1073741889\"]=\"289\" # SDLK SDLK_F8\n    sdl1_map[\"1073741890\"]=\"290\" # SDLK SDLK_F9\n    sdl1_map[\"1073741891\"]=\"291\" # SDLK SDLK_F10\n    sdl1_map[\"1073741892\"]=\"292\" # SDLK SDLK_F11\n    sdl1_map[\"1073741893\"]=\"293\" # SDLK SDLK_F12\n    sdl1_map[\"1073741894\"]=\"316\" # SDLK SDLK_PRINTSCREEN\n    sdl1_map[\"1073741895\"]=\"302\" # SDLK SDLK_SCROLLLOCK\n    sdl1_map[\"1073741896\"]=\"19\"  # SDLK SDLK_PAUSE\n    sdl1_map[\"1073741897\"]=\"277\" # SDLK SDLK_INSERT\n    sdl1_map[\"1073741898\"]=\"278\" # SDLK SDLK_HOME\n    sdl1_map[\"1073741899\"]=\"280\" # SDLK SDLK_PAGEUP\n    sdl1_map[\"1073741901\"]=\"279\" # SDLK SDLK_END\n    sdl1_map[\"1073741902\"]=\"281\" # SDLK SDLK_PAGEDOWN\n    sdl1_map[\"1073741903\"]=\"275\" # SDLK SDLK_RIGHT\n    sdl1_map[\"1073741904\"]=\"276\" # SDLK SDLK_LEFT\n    sdl1_map[\"1073741905\"]=\"274\" # SDLK SDLK_DOWN\n    sdl1_map[\"1073741906\"]=\"273\" # SDLK SDLK_UP\n    sdl1_map[\"1073741908\"]=\"267\" # SDLK SDLK_KP_DIVIDE\n    sdl1_map[\"1073741909\"]=\"268\" # SDLK SDLK_KP_MULTIPLY\n    sdl1_map[\"1073741910\"]=\"269\" # SDLK SDLK_KP_MINUS\n    sdl1_map[\"1073741911\"]=\"270\" # SDLK SDLK_KP_PLUS\n    sdl1_map[\"1073741912\"]=\"271\" # SDLK SDLK_KP_ENTER\n    sdl1_map[\"1073741913\"]=\"257\" # SDLK SDLK_KP_1\n    sdl1_map[\"1073741914\"]=\"258\" # SDLK SDLK_KP_2\n    sdl1_map[\"1073741915\"]=\"259\" # SDLK SDLK_KP_3\n    sdl1_map[\"1073741916\"]=\"260\" # SDLK SDLK_KP_4\n    sdl1_map[\"1073741917\"]=\"261\" # SDLK SDLK_KP_5\n    sdl1_map[\"1073741918\"]=\"262\" # SDLK SDLK_KP_6\n    sdl1_map[\"1073741919\"]=\"263\" # SDLK SDLK_KP_7\n    sdl1_map[\"1073741920\"]=\"264\" # SDLK SDLK_KP_8\n    sdl1_map[\"1073741921\"]=\"265\" # SDLK SDLK_KP_9\n    sdl1_map[\"1073741922\"]=\"256\" # SDLK SDLK_KP_0\n    sdl1_map[\"1073741923\"]=\"266\" # SDLK SDLK_KP_PERIOD\n    sdl1_map[\"1073741926\"]=\"320\" # SDLK SDLK_POWER\n    sdl1_map[\"1073741927\"]=\"272\" # SDLK SDLK_KP_EQUALS\n    sdl1_map[\"1073741928\"]=\"294\" # SDLK SDLK_F13\n    sdl1_map[\"1073741929\"]=\"295\" # SDLK SDLK_F14\n    sdl1_map[\"1073741930\"]=\"296\" # SDLK SDLK_F15\n    sdl1_map[\"1073741941\"]=\"315\" # SDLK SDLK_HELP\n    sdl1_map[\"1073741942\"]=\"319\" # SDLK SDLK_MENU\n    sdl1_map[\"1073741946\"]=\"322\" # SDLK SDLK_UNDO\n    sdl1_map[\"1073741978\"]=\"317\" # SDLK SDLK_SYSREQ\n    sdl1_map[\"1073742048\"]=\"306\" # SDLK SDLK_LCTRL\n    sdl1_map[\"1073742049\"]=\"304\" # SDLK SDLK_LSHIFT\n    sdl1_map[\"1073742050\"]=\"308\" # SDLK SDLK_LALT\n    sdl1_map[\"1073742051\"]=\"311\" # SDLK SDLK_LGUI\n    sdl1_map[\"1073742052\"]=\"305\" # SDLK SDLK_RCTRL\n    sdl1_map[\"1073742053\"]=\"303\" # SDLK SDLK_RSHIFT\n    sdl1_map[\"1073742054\"]=\"307\" # SDLK SDLK_RALT\n    sdl1_map[\"1073742055\"]=\"312\" # SDLK SDLK_RGUI\n    sdl1_map[\"1073742081\"]=\"313\" # SDLK SDLK_MODE\n}\n\n###### main ######\n\n__user=$(id -un)\nhome=\"$(eval echo ~$__user)\"\n\nrootdir=\"/opt/retropie\"\nconfigdir=\"$rootdir/configs\"\n\nsource \"$rootdir/lib/inifuncs.sh\"\n\ngetAutoConf \"disable\" || inputconfiguration\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation-dev.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"emulationstation-dev\"\nrp_module_desc=\"EmulationStation (latest development version) - Frontend used by RetroPie for launching emulators\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/RetroPie/EmulationStation/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/RetroPie/EmulationStation master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"frontend\"\n\nfunction _update_hook_emulationstation-dev() {\n    _update_hook_emulationstation\n}\n\nfunction depends_emulationstation-dev() {\n    depends_emulationstation\n}\n\nfunction sources_emulationstation-dev() {\n    sources_emulationstation\n}\n\nfunction build_emulationstation-dev() {\n    build_emulationstation\n}\n\nfunction install_emulationstation-dev() {\n    install_emulationstation\n}\n\nfunction configure_emulationstation-dev() {\n    rp_callModule \"emulationstation\" remove\n    configure_emulationstation\n}\n\nfunction remove_emulationstation-dev() {\n    remove_emulationstation\n}\n\nfunction gui_emulationstation-dev() {\n    gui_emulationstation\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/emulationstation.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"emulationstation\"\nrp_module_desc=\"EmulationStation - Frontend used by RetroPie for launching emulators\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/RetroPie/EmulationStation/master/LICENSE.md\"\nrp_module_repo=\"git https://github.com/RetroPie/EmulationStation :_get_branch_emulationstation\"\nrp_module_section=\"core\"\nrp_module_flags=\"frontend\"\n\nfunction _get_input_cfg_emulationstation() {\n    echo \"$configdir/all/emulationstation/es_input.cfg\"\n}\n\nfunction _update_hook_emulationstation() {\n    # make sure the input configuration scripts and launch script are always up to date\n    if rp_isInstalled \"$md_id\"; then\n        copy_inputscripts_emulationstation\n        install_launch_emulationstation\n    fi\n}\n\nfunction _sort_systems_emulationstation() {\n    local field=\"$1\"\n    cp \"/etc/emulationstation/es_systems.cfg\" \"/etc/emulationstation/es_systems.cfg.bak\"\n    xmlstarlet sel -D -I \\\n        -t -m \"/\" -e \"systemList\" \\\n        -m \"//system\" -s A:T:U \"$1\" -c \".\" \\\n        \"/etc/emulationstation/es_systems.cfg.bak\" >\"/etc/emulationstation/es_systems.cfg\"\n}\n\nfunction _add_system_emulationstation() {\n    local fullname=\"$1\"\n    local name=\"$2\"\n    local path=\"$3\"\n    local extension=\"$4\"\n    local command=\"$5\"\n    local platform=\"$6\"\n    local theme=\"$7\"\n\n    local conf=\"/etc/emulationstation/es_systems.cfg\"\n    mkdir -p \"/etc/emulationstation\"\n    if [[ ! -f \"$conf\" ]]; then\n        echo \"<systemList />\" >\"$conf\"\n    fi\n\n    cp \"$conf\" \"$conf.bak\"\n    if [[ $(xmlstarlet sel -t -v \"count(/systemList/system[name='$name'])\" \"$conf\") -eq 0 ]]; then\n        xmlstarlet ed -L -s \"/systemList\" -t elem -n \"system\" -v \"\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"name\" -v \"$name\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"fullname\" -v \"$fullname\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"path\" -v \"$path\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"extension\" -v \"$extension\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"command\" -v \"$command\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"platform\" -v \"$platform\" \\\n            -s \"/systemList/system[last()]\" -t elem -n \"theme\" -v \"$theme\" \\\n            \"$conf\"\n    else\n        xmlstarlet ed -L \\\n            -u \"/systemList/system[name='$name']/fullname\" -v \"$fullname\" \\\n            -u \"/systemList/system[name='$name']/path\" -v \"$path\" \\\n            -u \"/systemList/system[name='$name']/extension\" -v \"$extension\" \\\n            -u \"/systemList/system[name='$name']/command\" -v \"$command\" \\\n            -u \"/systemList/system[name='$name']/platform\" -v \"$platform\" \\\n            -u \"/systemList/system[name='$name']/theme\" -v \"$theme\" \\\n            \"$conf\"\n    fi\n\n    # alert the user if they have a custom es_systems.cfg which doesn't contain the system we are adding\n    local conf_local=\"$configdir/all/emulationstation/es_systems.cfg\"\n    if [[ -f \"$conf_local\" ]] && [[ \"$(xmlstarlet sel -t -v \"count(/systemList/system[name='$name'])\" \"$conf_local\")\" -eq 0 ]]; then\n        md_ret_info+=(\"You have a custom override of the EmulationStation system config in:\\n\\n$conf_local\\n\\nYou will need to copy the updated $system config from $conf to your custom config for $system to show up in EmulationStation.\")\n    fi\n\n    _sort_systems_emulationstation \"name\"\n}\n\nfunction _del_system_emulationstation() {\n    local fullname=\"$1\"\n    local name=\"$2\"\n    if [[ -f /etc/emulationstation/es_systems.cfg ]]; then\n        xmlstarlet ed -L -P -d \"/systemList/system[name='$name']\" /etc/emulationstation/es_systems.cfg\n    fi\n}\n\nfunction _add_rom_emulationstation() {\n    local system_name=\"$1\"\n    local system_fullname=\"$2\"\n    local path=\"./$3\"\n    local name=\"$4\"\n    local desc=\"$5\"\n    local image=\"$6\"\n\n    local config_dir=\"$configdir/all/emulationstation\"\n\n    mkUserDir \"$config_dir\"\n    mkUserDir \"$config_dir/gamelists\"\n    mkUserDir \"$config_dir/gamelists/$system_name\"\n    local config=\"$config_dir/gamelists/$system_name/gamelist.xml\"\n\n    if [[ ! -f \"$config\" ]]; then\n        echo \"<gameList />\" >\"$config\"\n    fi\n\n    if [[ $(xmlstarlet sel -t -v \"count(/gameList/game[path='$path'])\" \"$config\") -eq 0 ]]; then\n        xmlstarlet ed -L -s \"/gameList\" -t elem -n \"game\" -v \"\" \\\n            -s \"/gameList/game[last()]\" -t elem -n \"path\" -v \"$path\" \\\n            -s \"/gameList/game[last()]\" -t elem -n \"name\" -v \"$name\" \\\n            -s \"/gameList/game[last()]\" -t elem -n \"desc\" -v \"$desc\" \\\n            -s \"/gameList/game[last()]\" -t elem -n \"image\" -v \"$image\" \\\n            \"$config\"\n    else\n        xmlstarlet ed -L \\\n            -u \"/gameList/game[name='$name']/path\" -v \"$path\" \\\n            -u \"/gameList/game[name='$name']/name\" -v \"$name\" \\\n            -u \"/gameList/game[name='$name']/desc\" -v \"$desc\" \\\n            -u \"/gameList/game[name='$name']/image\" -v \"$image\" \\\n            \"$config\"\n    fi\n    chown \"$__user\":\"$__group\" \"$config\"\n}\n\nfunction depends_emulationstation() {\n    local depends=(\n        libfreeimage-dev libfreetype6-dev\n        libcurl4-openssl-dev libasound2-dev cmake libsdl2-dev libsm-dev\n        libvlc-dev libvlccore-dev python3-sdl2 vlc\n    )\n\n    [[ \"$__os_debian_ver\" -gt 8 ]] && depends+=(rapidjson-dev)\n    isPlatform \"x11\" && depends+=(gnome-terminal mesa-utils)\n    if isPlatform \"dispmanx\" && ! isPlatform \"osmc\"; then\n        depends+=(omxplayer)\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction _get_branch_emulationstation() {\n    if [[ -z \"$branch\" ]]; then\n        if [[ \"$__os_debian_ver\" -gt 8 ]]; then\n            branch=\"stable\"\n        else\n            branch=\"v2.7.6\"\n        fi\n    fi\n    echo \"$branch\"\n}\n\nfunction sources_emulationstation() {\n    gitPullOrClone\n}\n\nfunction build_emulationstation() {\n    local params=(-DFREETYPE_INCLUDE_DIRS=/usr/include/freetype2/)\n    if isPlatform \"rpi\"; then\n        params+=(-DRPI=On)\n        # use OpenGL on RPI/KMS for now\n        isPlatform \"mesa\" && params+=(\"-DGL=On\" \"-DUSE_GL21=On\")\n        # force GLESv1 on videocore due to performance issue with GLESv2\n        isPlatform \"videocore\" && params+=(-DUSE_GLES1=On)\n    elif isPlatform \"x11\"; then\n        if isPlatform \"gles\"; then\n            params+=(-DGLES=On)\n            local gles_ver=$(sudo -u $__user glxinfo -B | grep -oP 'Max GLES[23] profile version:\\s\\K.*')\n            compareVersions $gles_ver lt 2.0  && params+=(-DUSE_GLES1=On)\n        else\n            params+=(-DGL=On)\n            # mesa specific check of OpenGL version\n            local gl_ver=$(sudo -u $__user glxinfo -B | grep -oP 'Max compat profile version:\\s\\K.*')\n            # generic fallback check of OpenGL version\n            [[ -z \"$gl_ver\" ]] && gl_ver=$(sudo -u $__user glxinfo -B | grep -oP \"OpenGL version string: \\K[^ ]+\")\n            compareVersions $gl_ver gt 2.0 && params+=(-DUSE_GL21=On)\n        fi\n    elif isPlatform \"gles\"; then\n        params+=(-DGLES=On)\n    elif isPlatform \"gl\"; then\n        params+=(-DGL=On)\n    fi\n    if isPlatform \"dispmanx\"; then\n        params+=(-DOMX=On)\n    fi\n\n    rpSwap on 1000\n    cmake . \"${params[@]}\"\n    make clean\n    make VERBOSE=1\n    rpSwap off\n    md_ret_require=\"$md_build/emulationstation\"\n}\n\nfunction install_emulationstation() {\n    md_ret_files=(\n        'CREDITS.md'\n        'emulationstation'\n        'emulationstation.sh'\n        'GAMELISTS.md'\n        'README.md'\n        'THEMES.md'\n    )\n\n    # This folder is present only from 2.8.x, don't include it for older releases\n    if [[ \"$__os_debian_ver\" -gt 8 ]]; then\n        md_ret_files+=('resources')\n    fi\n}\n\nfunction init_input_emulationstation() {\n    local es_config=\"$(_get_input_cfg_emulationstation)\"\n\n    # if there is no ES config (or empty file) create it with initial inputList element\n    if [[ ! -s \"$es_config\" ]]; then\n        echo \"<inputList />\" >\"$es_config\"\n    fi\n\n    # add/update our inputconfiguration.sh inputAction\n    if [[ $(xmlstarlet sel -t -v \"count(/inputList/inputAction[@type='onfinish'])\" \"$es_config\") -eq 0 ]]; then\n        xmlstarlet ed -L -S \\\n            -s \"/inputList\" -t elem -n \"inputActionTMP\" -v \"\" \\\n            -s \"//inputActionTMP\" -t attr -n \"type\" -v \"onfinish\" \\\n            -s \"//inputActionTMP\" -t elem -n \"command\" -v \"$md_inst/scripts/inputconfiguration.sh\" \\\n            -r \"//inputActionTMP\" -v \"inputAction\" \"$es_config\"\n    else\n        xmlstarlet ed -L \\\n            -u \"/inputList/inputAction[@type='onfinish']/command[1]\" -v \"$md_inst/scripts/inputconfiguration.sh\" \\\n            \"$es_config\"\n    fi\n\n    chown \"$__user\":\"$__group\" \"$es_config\"\n}\n\nfunction copy_inputscripts_emulationstation() {\n    mkdir -p \"$md_inst/scripts\"\n\n    cp -r \"$scriptdir/scriptmodules/$md_type/emulationstation/\"* \"$md_inst/scripts/\"\n    chmod +x \"$md_inst/scripts/inputconfiguration.sh\"\n}\n\nfunction install_launch_emulationstation() {\n    cat > /usr/bin/emulationstation << _EOF_\n#!/bin/bash\n\nif [[ \\$(id -u) -eq 0 ]]; then\n    echo \"emulationstation should not be run as root. If you used 'sudo emulationstation' please run without sudo.\"\n    exit 1\nfi\n\n# use SDL2 wayland video driver if wayland session is detected, but...\n# Emulationstation has focus problems under Ubuntu 22.04's GNOME on Wayland session, so don't use the SDL2's Wayland driver in that combination\nif [[ \"\\$WAYLAND_DISPLAY\" == wayland* ]]; then\n    [[ \"\\$XDG_CURRENT_DESKTOP\" == *GNOME ]] || export SDL_VIDEODRIVER=wayland\nfi\n\n# save current tty/vt number for use with X so it can be launched on the correct tty\nTTY=\\$(tty)\nexport TTY=\"\\${TTY:8:1}\"\n\nclear\ntput civis\n\"$md_inst/emulationstation.sh\" \"\\$@\"\nif [[ \\$? -eq 139 ]]; then\n    dialog --cr-wrap --no-collapse --msgbox \"Emulation Station crashed!\\n\\nIf this is your first boot of RetroPie - make sure you are using the correct image for your system.\\n\\\\nCheck your rom file/folder permissions and if running on a Raspberry Pi, make sure your gpu_split is set high enough and/or switch back to using carbon theme.\\n\\nFor more help please use the RetroPie forum.\" 20 60 >/dev/tty\nfi\ntput cnorm\n_EOF_\n    chmod +x /usr/bin/emulationstation\n\n    if isPlatform \"x11\"; then\n        mkdir -p /usr/local/share/{icons,applications}\n        cp \"$scriptdir/scriptmodules/$md_type/emulationstation/retropie.svg\" \"/usr/local/share/icons/\"\n        cat > /usr/local/share/applications/retropie.desktop << _EOF_\n[Desktop Entry]\nType=Application\nExec=gnome-terminal --full-screen --hide-menubar -e emulationstation\nHidden=false\nNoDisplay=false\nX-GNOME-Autostart-enabled=true\nName[de_DE]=RetroPie\nName=rpie\nComment[de_DE]=RetroPie\nComment=retropie\nIcon=/usr/local/share/icons/retropie.svg\nCategories=Game\n_EOF_\n    fi\n}\n\nfunction clear_input_emulationstation() {\n    rm \"$(_get_input_cfg_emulationstation)\"\n    init_input_emulationstation\n}\n\nfunction remove_emulationstation() {\n    rm -f \"/usr/bin/emulationstation\"\n    if isPlatform \"x11\"; then\n        rm -rfv \"/usr/local/share/icons/retropie.svg\" \"/usr/local/share/applications/retropie.desktop\"\n    fi\n}\n\nfunction configure_emulationstation() {\n    # move the $home/emulationstation configuration dir and symlink it\n    moveConfigDir \"$home/.emulationstation\" \"$configdir/all/emulationstation\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # remove other emulation station if it's installed, so we don't end up with\n    # both packages interfering - but leave configs alone so switching is easy\n    if [[ \"$md_id\" == \"emulationstation-dev\" ]]; then\n        rmDirExists \"$rootdir/$md_type/emulationstation\"\n    else\n        rmDirExists \"$rootdir/$md_type/emulationstation-dev\"\n    fi\n\n    init_input_emulationstation\n\n    copy_inputscripts_emulationstation\n\n    install_launch_emulationstation\n\n    mkdir -p \"/etc/emulationstation\"\n\n    # ensure we have a default theme\n    rp_callModule esthemes install_theme\n\n    addAutoConf \"es_swap_a_b\" 0\n    addAutoConf \"disable\" 0\n}\n\nfunction gui_emulationstation() {\n    local es_swap=0\n    getAutoConf \"es_swap_a_b\" && es_swap=1\n\n    local disable=0\n    getAutoConf \"disable\" && disable=1\n\n    local default\n    local options\n    while true; do\n        local options=(\n            1 \"Clear/Reset Emulation Station input configuration\"\n        )\n\n        if [[ \"$disable\" -eq 0 ]]; then\n            options+=(2 \"Auto Configuration (Currently: Enabled)\")\n        else\n            options+=(2 \"Auto Configuration (Currently: Disabled)\")\n        fi\n\n        if [[ \"$es_swap\" -eq 0 ]]; then\n            options+=(3 \"Swap A/B Buttons in ES (Currently: Default)\")\n        else\n            options+=(3 \"Swap A/B Buttons in ES (Currently: Swapped)\")\n        fi\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Choose an option\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        default=\"$choice\"\n\n        case \"$choice\" in\n            1)\n                if dialog --defaultno --yesno \"Are you sure you want to reset the Emulation Station controller configuration ? This will wipe all controller configs for ES and it will prompt to reconfigure on next start\" 22 76 2>&1 >/dev/tty; then\n                    clear_input_emulationstation\n                    printMsgs \"dialog\" \"$(_get_input_cfg_emulationstation) has been reset to default values.\"\n                fi\n                ;;\n            2)\n                disable=\"$((disable ^ 1))\"\n                setAutoConf \"disable\" \"$disable\"\n                ;;\n            3)\n                es_swap=\"$((es_swap ^ 1))\"\n                setAutoConf \"es_swap_a_b\" \"$es_swap\"\n                local ra_swap=\"false\"\n                getAutoConf \"es_swap_a_b\" && ra_swap=\"true\"\n                iniSet \"menu_swap_ok_cancel_buttons\" \"$ra_swap\" \"$configdir/all/retroarch.cfg\"\n                printMsgs \"dialog\" \"You will need to reconfigure you controller in Emulation Station for the changes to take effect.\"\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/esthemes/patch-ruckage-famicom-mini.diff",
    "content": "diff -u -r famicom-mini-master/layouts/1024x768.xml famicom-mini-mod/layouts/1024x768.xml\n--- famicom-mini-master/layouts/1024x768.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1024x768.xml\t2023-11-19 20:50:59.665662200 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.573 0.5481481481481481</size>\n-\t\t\t<pos>0.38 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.630208333333333</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.39</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/1280x720.xml famicom-mini-mod/layouts/1280x720.xml\n--- famicom-mini-master/layouts/1280x720.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1280x720.xml\t2023-11-19 20:18:09.217099000 +0200\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2854166666666667 0.2185185185185185</pos>\n-\t\t\t<size>0.4291666666666667 0.5481481481481481</size>\n+\t\t\t<pos>0.2854166666666667 0.1890</pos>\n+\t\t\t<size>0.4291666666666667 0.629166666666667</size>\n \t\t\t<lineSpacing>1.3975</lineSpacing>\n \t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\ndiff -u -r famicom-mini-master/layouts/1280x960.xml famicom-mini-mod/layouts/1280x960.xml\n--- famicom-mini-master/layouts/1280x960.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1280x960.xml\t2023-11-19 20:55:57.216498200 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5725 0.5481481481481481</size>\n-\t\t\t<pos>0.3805555555555556 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.630208333333333</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/1366x768.xml famicom-mini-mod/layouts/1366x768.xml\n--- famicom-mini-master/layouts/1366x768.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1366x768.xml\t2023-11-19 20:33:51.952952100 +0200\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2854166666666667 0.2185185185185185</pos>\t\t\n-\t\t\t<size>0.4291666666666667 0.5481481481481481</size>\n+\t\t\t<pos>0.2854166666666667 0.1890</pos>\n+\t\t\t<size>0.4291666666666667 0.629166666666667</size>\n \t\t\t<lineSpacing>1.39</lineSpacing>\n \t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\ndiff -u -r famicom-mini-master/layouts/1440x1080.xml famicom-mini-mod/layouts/1440x1080.xml\n--- famicom-mini-master/layouts/1440x1080.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1440x1080.xml\t2023-11-19 20:56:45.019045900 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5722222222222222 0.5481481481481481</size>\n-\t\t\t<pos>0.3805555555555556 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.630208333333333</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.375</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/1920x1080.xml famicom-mini-mod/layouts/1920x1080.xml\n--- famicom-mini-master/layouts/1920x1080.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/1920x1080.xml\t2023-11-19 20:18:27.434632200 +0200\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2854166666666667 0.2185185185185185</pos>\t\t\n-\t\t\t<size>0.4291666666666667 0.5481481481481481</size>\n+\t\t\t<pos>0.2854166666666667 0.1890</pos>\t\t\n+\t\t\t<size>0.4291666666666667 0.629166666666667</size>\n \t\t\t<lineSpacing>1.375</lineSpacing>\n \t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\ndiff -u -r famicom-mini-master/layouts/320x240.xml famicom-mini-mod/layouts/320x240.xml\n--- famicom-mini-master/layouts/320x240.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/320x240.xml\t2023-11-19 20:53:08.112267000 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5722222222222222 0.5481481481481481</size>\n-\t\t\t<pos>0.3805555555555556 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.6302</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/640x480.xml famicom-mini-mod/layouts/640x480.xml\n--- famicom-mini-master/layouts/640x480.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/640x480.xml\t2023-11-19 20:53:09.551257200 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.575 0.5481481481481481</size>\n-\t\t\t<pos>0.378 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.6302</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/800x600.xml famicom-mini-mod/layouts/800x600.xml\n--- famicom-mini-master/layouts/800x600.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/800x600.xml\t2023-11-19 20:51:45.383240000 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5722222222222222 0.5481481481481481</size>\n-\t\t\t<pos>0.3805555555555556 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.6302</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\ndiff -u -r famicom-mini-master/layouts/ntsc.xml famicom-mini-mod/layouts/ntsc.xml\n--- famicom-mini-master/layouts/ntsc.xml\t2017-08-07 02:15:59.000000000 +0300\n+++ famicom-mini-mod/layouts/ntsc.xml\t2023-11-19 20:59:02.098705000 +0200\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5722222222222222 0.5481481481481481</size>\n-\t\t\t<pos>0.3805555555555556 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5715 0.630208333333333</size>\n+\t\t\t<pos>0.3807 0.1860</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0740740740740741</selectorHeight>\n+\t\t\t<selectorHeight>0.0795</selectorHeight>\n \t\t\t<selectorOffsetY>0</selectorOffsetY>\n \t\t\t<horizontalMargin>0.0166666666666667</horizontalMargin>\n \t\t</textlist>\n"
  },
  {
    "path": "scriptmodules/supplementary/esthemes/patch-ruckage-nes-mini.diff",
    "content": "--- nes-mini/layouts/1024x768.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/1024x768.xml\tMon Nov 20 16:04:57 2023\n@@ -10,8 +10,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.544 0.5481481481481481</size>\n-\t\t\t<pos>0.3944444444444444 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5443  0.6302</size>\n+\t\t\t<pos>0.3942 0.1890</pos>\n \t\t\t<lineSpacing>1.39</lineSpacing>\n \t\t\t<selectorHeight>0.0592592592592593</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n--- nes-mini/layouts/1280x720.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/1280x720.xml\tMon Nov 20 15:56:00 2023\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2958333333333333 0.2185185185185185</pos>\n-\t\t\t<size>0.408 0.5481481481481481</size>\n+\t\t\t<size>0.408 0.629166666666667</size>\n+\t\t\t<pos>0.2960 0.1890</pos>\n \t\t\t<lineSpacing>1.3975</lineSpacing>\n \t\t\t<selectorHeight>0.0592592592592593</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n--- nes-mini/layouts/1280x960.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/1280x960.xml\tMon Nov 20 16:03:07 2023\n@@ -10,8 +10,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5444444444444444 0.5481481481481481</size>\n-\t\t\t<pos>0.3944444444444444 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5443  0.6302</size>\n+\t\t\t<pos>0.3942 0.1890</pos>\n \t\t\t<lineSpacing>1.396</lineSpacing>\n \t\t\t<selectorHeight>0.0592592592592593</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n--- nes-mini/layouts/1366x768.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/1366x768.xml\tMon Nov 20 15:56:46 2023\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2958333333333333 0.2185185185185185</pos>\t\t\n-\t\t\t<size>0.408 0.5481481481481481</size>\n+\t\t\t<size>0.408 0.629166666666667</size>\n+\t\t\t<pos>0.2960 0.1890</pos>\n \t\t\t<lineSpacing>1.39</lineSpacing>\n \t\t\t<selectorHeight>0.0592592592592593</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n--- nes-mini/layouts/1920x1080.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/1920x1080.xml\tMon Nov 20 15:57:24 2023\n@@ -8,8 +8,8 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>0.2958333333333333 0.2185185185185185</pos>\t\t\n-\t\t\t<size>0.4083333333333333 0.5481481481481481</size>\n+\t\t\t<pos>0.2960 0.1890</pos>\n+\t\t\t<size>0.408 0.629166666666667</size>\n \t\t\t<lineSpacing>1.375</lineSpacing>\n \t\t\t<selectorHeight>0.0592592592592593</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n--- nes-mini/layouts/320x240.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/320x240.xml\tTue Nov 21 14:08:33 2023\n@@ -10,11 +10,11 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.546 0.5481481481481481</size>\n-\t\t\t<pos>0.3944444444444444 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5475 0.6310</size>\n+\t\t\t<pos>0.3935 0.1878</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.064</selectorHeight>\n-\t\t\t<selectorOffsetY>0.007</selectorOffsetY>\n+\t\t\t<selectorHeight>0.060</selectorHeight>\n+\t\t\t<selectorOffsetY>0.008</selectorOffsetY>\n \t\t</textlist>\n \t\t\n \t</view>\n--- nes-mini/layouts/640x480.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/640x480.xml\tTue Nov 21 08:39:50 2023\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.546 0.5481481481481481</size>\n-\t\t\t<pos>0.394 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5452 0.6310</size>\n+\t\t\t<pos>0.3941 0.1882</pos>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.06</selectorHeight>\n+\t\t\t<selectorHeight>0.0615</selectorHeight>\n \t\t\t<selectorOffsetY>0.007</selectorOffsetY>\n \t\t</textlist>\n \t\t\n--- nes-mini/layouts/800x600.xml\tWed May  2 15:18:27 2018\n+++ nes-mini/layouts/800x600.xml\tWed Nov 22 13:54:40 2023\n@@ -10,10 +10,10 @@\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.544 0.5481481481481481</size>\n-\t\t\t<pos>0.3944444444444444 0.2185185185185185</pos>\t\t\t\n+\t\t\t<size>0.5443 0.6302</size>\n+\t\t\t<pos>0.3954 0.1882</pos>\n \t\t\t<lineSpacing>1.4</lineSpacing>\n-\t\t\t<selectorHeight>0.06</selectorHeight>\n+\t\t\t<selectorHeight>0.0592</selectorHeight>\n \t\t\t<selectorOffsetY>0.0074074074074074</selectorOffsetY>\n \t\t</textlist>\n \t\t\n"
  },
  {
    "path": "scriptmodules/supplementary/esthemes/patch-ruckage-snes-mini.diff",
    "content": "diff --git a/layouts/1024x768.xml b/layouts/1024x768.xml\nindex 0fa2e6d..2b29a33 100644\n--- a/layouts/1024x768.xml\n+++ b/layouts/1024x768.xml\n@@ -10,12 +10,12 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5611111111111111 0.5481481481481481</size>\n-\t\t\t<pos>0.9861111111111111 0.2259259259259259</pos>\t\t\t\n+\t\t\t<size>0.5615234375 0.630208333333333</size>\n+\t\t\t<pos>0.986328125 0.1953125</pos>\t\t\t\n \t\t\t<lineSpacing>1.39</lineSpacing>\n \t\t\t<origin>1 0</origin>\n-\t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n-\t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\n+\t\t\t<selectorHeight>0.08203125</selectorHeight>\n+\t\t\t<selectorOffsetY>-0.01171875</selectorOffsetY>\n \t\t</textlist>\n \t\t\n \t</view>\ndiff --git a/layouts/1280x720.xml b/layouts/1280x720.xml\nindex f7fae91..0ad84f2 100644\n--- a/layouts/1280x720.xml\n+++ b/layouts/1280x720.xml\n@@ -8,10 +8,10 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>${listx} 0.2259259259259259</pos>\t\t\n-\t\t\t<size>${listWidth} 0.5481481481481481</size>\n+\t\t\t<pos>${listx} 0.195833333333333</pos>\t\t\n+\t\t\t<size>${listWidth} 0.629166666666667</size>\n \t\t\t<lineSpacing>1.395</lineSpacing>\n-\t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n+\t\t\t<selectorHeight>0.081944444444444</selectorHeight>\n \t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\n \t\t</textlist>\n \t\t\ndiff --git a/layouts/1280x960.xml b/layouts/1280x960.xml\nindex acb687f..dc17453 100644\n--- a/layouts/1280x960.xml\n+++ b/layouts/1280x960.xml\n@@ -10,12 +10,12 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5611111111111111 0.5481481481481481</size>\n-\t\t\t<pos>0.9861111111111111 0.2259259259259259</pos>\t\t\t\n+\t\t\t<size>0.5611111111111111 0.630208333333333</size>\n+\t\t\t<pos>0.9861111111111111 0.195833333333333</pos>\t\t\t\n \t\t\t<lineSpacing>1.4</lineSpacing>\n \t\t\t<origin>1 0</origin>\n-\t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n-\t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\n+\t\t\t<selectorHeight>0.08125</selectorHeight>\n+\t\t\t<selectorOffsetY>-0.011458333333333</selectorOffsetY>\n \t\t</textlist>\n \t\t\n \t</view>\ndiff --git a/layouts/1366x768.xml b/layouts/1366x768.xml\nindex 0c268c3..6131217 100644\n--- a/layouts/1366x768.xml\n+++ b/layouts/1366x768.xml\n@@ -8,11 +8,11 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>${listx} 0.2259259259259259</pos>\t\t\n-\t\t\t<size>${listWidth} 0.5481481481481481</size>\n+\t\t\t<pos>${listx} 0.1953125</pos>\t\t\n+\t\t\t<size>${listWidth} 0.630208333333333</size>\n \t\t\t<lineSpacing>1.39</lineSpacing>\n-\t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n-\t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\n+\t\t\t<selectorHeight>0.08203125</selectorHeight>\n+\t\t\t<selectorOffsetY>-0.01171875</selectorOffsetY>\n \t\t</textlist>\n \t\t\n \t</view>\ndiff --git a/layouts/1440x1080.xml b/layouts/1440x1080.xml\nindex 044758d..f3d6fe4 100644\n--- a/layouts/1440x1080.xml\n+++ b/layouts/1440x1080.xml\n@@ -10,8 +10,8 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5611111111111111 0.5481481481481481</size>\n-\t\t\t<pos>0.9861111111111111 0.2259259259259259</pos>\t\t\t\n+\t\t\t<size>0.5611111111111111 0.62962962962963</size>\n+\t\t\t<pos>0.9861111111111111 0.19537037037037</pos>\t\t\t\n \t\t\t<lineSpacing>1.375</lineSpacing>\n \t\t\t<origin>1 0</origin>\n \t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\ndiff --git a/layouts/1920x1080.xml b/layouts/1920x1080.xml\nindex f4c55ef..13008ed 100644\n--- a/layouts/1920x1080.xml\n+++ b/layouts/1920x1080.xml\n@@ -8,8 +8,8 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<pos>${listx} 0.2259259259259259</pos>\t\t\n-\t\t\t<size>${listWidth} 0.5481481481481481</size>\n+\t\t\t<pos>${listx} 0.19537037037037</pos>\t\t\n+\t\t\t<size>${listWidth} 0.62962962962963</size>\n \t\t\t<lineSpacing>1.375</lineSpacing>\n \t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n \t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\ndiff --git a/layouts/640x480.xml b/layouts/640x480.xml\nindex c58ca21..05f0a24 100644\n--- a/layouts/640x480.xml\n+++ b/layouts/640x480.xml\n@@ -10,11 +10,11 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5611111111111111 0.5481481481481481</size>\n-\t\t\t<pos>0.9861111111111111 0.2259259259259259</pos>\t\t\t\n+\t\t\t<size>0.5609375 0.629166666666667</size>\n+\t\t\t<pos>0.9859375 0.195833333333333</pos>\t\t\t\n \t\t\t<lineSpacing>1.395</lineSpacing>\n \t\t\t<origin>1 0</origin>\n-\t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n+\t\t\t<selectorHeight>0.08125</selectorHeight>\n \t\t\t<selectorOffsetY>-0.0111111111111111</selectorOffsetY>\n \t\t</textlist>\n \t\t\ndiff --git a/layouts/800x600.xml b/layouts/800x600.xml\nindex c58ca21..c32d8af 100644\n--- a/layouts/800x600.xml\n+++ b/layouts/800x600.xml\n@@ -10,8 +10,8 @@ author:\t\t\truckage\n     <view name=\"basic, detailed,video\">\n \n \t\t<textlist name=\"gamelist\">\n-\t\t\t<size>0.5611111111111111 0.5481481481481481</size>\n-\t\t\t<pos>0.9861111111111111 0.2259259259259259</pos>\t\t\t\n+\t\t\t<size>0.5611111111111111 0.63</size>\n+\t\t\t<pos>0.9861111111111111 0.195</pos>\t\t\t\n \t\t\t<lineSpacing>1.395</lineSpacing>\n \t\t\t<origin>1 0</origin>\n \t\t\t<selectorHeight>0.0814814814814815</selectorHeight>\n"
  },
  {
    "path": "scriptmodules/supplementary/esthemes.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"esthemes\"\nrp_module_desc=\"Install themes for Emulation Station\"\nrp_module_section=\"config\"\n\nfunction depends_esthemes() {\n    if isPlatform \"x11\"; then\n        getDepends feh\n    else\n        getDepends fbi\n    fi\n}\n\nfunction _has_pixel_pos_esthemes() {\n    local pixel_pos=0\n    # get the version of emulationstation installed so we can check whether to show\n    # themes that use the new pixel based positioning - we run as $__user as the\n    # emulationstation launch script will exit if run as root\n    local es_ver=\"$(sudo -u $__user /usr/bin/emulationstation --help | grep -oP \"Version \\K[^,]+\")\"\n    # if emulationstation is newer than 2.10, enable pixel based themes\n    compareVersions \"$es_ver\" ge \"2.10\" && pixel_pos=1\n    echo \"$pixel_pos\"\n}\n\nfunction install_theme_esthemes() {\n    local theme=\"$1\"\n    local repo=\"$2\"\n    local branch=\"$3\"\n\n    local pixel_pos=\"$(_has_pixel_pos_esthemes)\"\n\n    if [[ -z \"$repo\" ]]; then\n        repo=\"RetroPie\"\n    fi\n\n    if [[ -z \"$theme\" ]]; then\n        theme=\"carbon\"\n        repo=\"RetroPie\"\n        [[ \"$pixel_pos\" -eq 1 ]] && theme+=\"-2021\"\n    fi\n\n    local name=\"$theme\"\n\n    if [[ -z \"$branch\" ]]; then\n        # Get the name of the default branch, fallback to 'master' if not found\n        branch=$(runCmd git ls-remote --symref --exit-code \"https://github.com/$repo/es-theme-$theme.git\" HEAD | grep -oP \".*/\\K[^\\t]+\")\n        [[ -z \"$branch\" ]] && branch=\"master\"\n    else\n        name+=\"-$branch\"\n    fi\n\n    mkdir -p \"/etc/emulationstation/themes\"\n    gitPullOrClone \"/etc/emulationstation/themes/$name\" \"https://github.com/$repo/es-theme-$theme.git\" \"$branch\"\n\n    # apply any patches for themes broken due to ES fixes\n    if [[ \"$pixel_pos\" == 1 && -f \"$md_data/patch-$repo-$theme.diff\" ]]; then\n        pushd \"/etc/emulationstation/themes/$name\"\n        applyPatch \"$md_data/patch-$repo-$theme.diff\"\n        popd\n    fi\n}\n\nfunction uninstall_theme_esthemes() {\n    local theme=\"$1\"\n    if [[ -d \"/etc/emulationstation/themes/$theme\" ]]; then\n        rm -rf \"/etc/emulationstation/themes/$theme\"\n    fi\n}\n\nfunction gui_esthemes() {\n    local themes=()\n\n    local pixel_pos=\"$(_has_pixel_pos_esthemes)\"\n\n    if [[ \"$pixel_pos\" -eq 1 ]]; then\n        themes+=(\n            'RetroPie carbon-2021'\n            'RetroPie carbon-2021 centered'\n            'RetroPie carbon-2021 nometa'\n        )\n    fi\n\n    local themes+=(\n        'RetroPie carbon'\n        'RetroPie carbon-centered'\n        'RetroPie carbon-nometa'\n        'RetroPie simple'\n        'RetroPie simple-dark'\n        'RetroPie clean-look'\n        'RetroPie color-pi'\n        'RetroPie nbba'\n        'RetroPie simplified-static-canela'\n        'RetroPie turtle-pi'\n        'RetroPie zoid'\n        'ehettervik pixel'\n        'ehettervik pixel-metadata'\n        'ehettervik pixel-tft'\n        'ehettervik luminous'\n        'ehettervik minilumi'\n        'ehettervik workbench'\n        'AmadhiX eudora'\n        'AmadhiX eudora-bigshot'\n        'AmadhiX eudora-concise'\n        'Omnija simpler-turtlepi'\n        'Omnija simpler-turtlemini'\n        'Omnija metro'\n        'lilbud material'\n        'mattrixk io'\n        'mattrixk metapixel'\n        'mattrixk spare'\n        'robertybob space'\n        'robertybob simplebigart'\n        'robertybob tv'\n        'HerbFargus tronkyfran'\n        'lilbud flat'\n        'lilbud flat-dark'\n        'lilbud minimal'\n        'lilbud switch'\n        'lilbud angular'\n        'FlyingTomahawk futura-V'\n        'FlyingTomahawk futura-dark-V'\n        'G-rila fundamental'\n        'ruckage nes-mini'\n        'ruckage famicom-mini'\n        'ruckage snes-mini'\n        'anthonycaccese crt'\n        'anthonycaccese crt-centered'\n        'anthonycaccese art-book'\n        'anthonycaccese art-book-4-3'\n        'anthonycaccese art-book-pocket'\n        'anthonycaccese art-book-micro'\n        'anthonycaccese tft'\n        'anthonycaccese picade'\n        'TMNTturtleguy ComicBook'\n        'TMNTturtleguy ComicBook_4-3'\n        'TMNTturtleguy ComicBook_SE-Wheelart'\n        'TMNTturtleguy ComicBook_4-3_SE-Wheelart'\n        'ChoccyHobNob cygnus'\n        'DTEAM-1 cygnus-blue-flames'\n        'dmmarti steampunk'\n        'dmmarti hurstyblue'\n        'dmmarti maximuspie'\n        'dmmarti showcase'\n        'dmmarti kidz'\n        'dmmarti unified'\n        'dmmarti gamehat'\n        'rxbrad freeplay'\n        'rxbrad gbz35'\n        'rxbrad gbz35-dark'\n        'garaine marioblue'\n        'garaine bigwood'\n        'MrTomixf Royal_Primicia'\n        'lostless playstation'\n        'mrharias superdisplay'\n        'coinjunkie synthwave'\n        'nickearl retrowave'\n        'nickearl retrowave_4_3'\n        'pacdude minijawn'\n        'RetroHursty69 magazinemadness'\n        'RetroHursty69 stirling'\n        'RetroHursty69 boxalloyred'\n        'RetroHursty69 boxalloyblue'\n        'RetroHursty69 greenilicious'\n        'RetroHursty69 retroroid'\n        'RetroHursty69 merryxmas'\n        'RetroHursty69 cardcrazy'\n        'RetroHursty69 license2game'\n        'RetroHursty69 comiccrazy'\n        'RetroHursty69 snazzy'\n        'RetroHursty69 tributeGoT'\n        'RetroHursty69 tributeSTrek'\n        'RetroHursty69 tributeSWars'\n        'RetroHursty69 crisp'\n        'RetroHursty69 crisp_light'\n        'RetroHursty69 primo'\n        'RetroHursty69 primo_light'\n        'RetroHursty69 back2basics'\n        'RetroHursty69 retrogamenews'\n        'RetroHursty69 bluray'\n        'RetroHursty69 soda'\n        'RetroHursty69 lightswitch'\n        'RetroHursty69 darkswitch'\n        'RetroHursty69 whiteslide'\n        'RetroHursty69 graffiti'\n        'RetroHursty69 whitewood'\n        'RetroHursty69 sublime'\n        'RetroHursty69 infinity'\n        'RetroHursty69 neogeo_only'\n        'RetroHursty69 boxcity'\n        'RetroHursty69 vertical_arcade'\n        'RetroHursty69 cabsnazzy'\n        'RetroHursty69 garfieldism'\n        'RetroHursty69 halloweenspecial'\n        'RetroHursty69 heychromey'\n        'RetroHursty69 homerism'\n        'RetroHursty69 spaceinvaders'\n        'RetroHursty69 disenchantment'\n        'RetroHursty69 minions'\n        'RetroHursty69 tmnt'\n        'RetroHursty69 pacman'\n        'RetroHursty69 dragonballz'\n        'RetroHursty69 minecraft'\n        'RetroHursty69 incredibles'\n        'RetroHursty69 mario_melee'\n        'RetroHursty69 evilresident'\n        'RetroHursty69 hurstyspin'\n        'RetroHursty69 cyber'\n        'RetroHursty69 supersweet'\n        'RetroHursty69 donkeykonkey'\n        'RetroHursty69 snapback'\n        'RetroHursty69 heman'\n        'RetroHursty69 pitube'\n        'RetroHursty69 batmanburton'\n        'RetroHursty69 NegativeColor'\n        'RetroHursty69 NegativeSepia'\n        'RetroHursty69 corg'\n        'RetroHursty69 mysticorb'\n        'RetroHursty69 joysticks'\n        'RetroHursty69 orbpilot'\n        'RetroHursty69 bitfit'\n        'RetroHursty69 circuit'\n        'RetroHursty69 retroboy'\n        'RetroHursty69 retroboy2'\n        'RetroHursty69 hurstybluetake2'\n        'RetroHursty69 fabuloso'\n        'RetroHursty69 arcade1up_aspectratio54'\n        'RetroHursty69 supersweet_aspectratio54'\n        'RetroHursty69 heychromey_aspectratio54'\n        'RetroHursty69 mariobrosiii'\n        'RetroHursty69 vertical_limit_verticaltheme'\n        'RetroHursty69 CapcomColorHorizontal'\n        'RetroHursty69 CapcomColorSpin'\n        'RetroHursty69 CapcomColorVertical'\n        'RetroHursty69 bluesteel'\n        'RetroHursty69 blueprism'\n        'RetroHursty69 bluesmooth'\n        'RetroHursty69 floyd'\n        'RetroHursty69 floyd_arcade'\n        'RetroHursty69 floyd_room'\n        'RetroHursty69 Slick_Bluey'\n        'RetroHursty69 Slick_Red'\n        'RetroHursty69 ghostbusters'\n        'RetroHursty69 realghostbusters'\n        'RetroHursty69 stirlingness'\n        'RetroHursty69 marco'\n        'RetroHursty69 swatch'\n        'RetroHursty69 meshy'\n        'RetroHursty69 magazinemadness2'\n        'RetroHursty69 CosmicRise'\n        'RetroHursty69 uniflyered'\n        'RetroHursty69 gametime'\n        'RetroHursty69 CRTBlast'\n        'RetroHursty69 CRTNeonBlast'\n        'RetroHursty69 CRTCabBlast'\n        'RetroHursty69 ComicCRASHB'\n        'RetroHursty69 ComicPACMAN'\n        'RetroHursty69 ComicSONIC'\n        'RetroHursty69 ComicXMEN'\n        'RetroHursty69 ComicZELDA'\n        'RetroHursty69 synthy16x9'\n        'RetroHursty69 synthyA1UP'\n        'RetroHursty69 supersynthy16x9'\n        'RetroHursty69 supersynthyA1UP'\n        'RetroHursty69 HyperCab'\n        'RetroHursty69 NeonFantasy'\n        'RetroHursty69 ShadowClean'\n        'RetroHursty69 shine'\n        'RetroHursty69 Vinyl-Hits'\n        'RetroHursty69 ColorfulExtreme'\n        'RetroHursty69 ColorfulSupreme'\n        'RetroHursty69 CircularEssence'\n        'RetroHursty69 BoomBoxStreet'\n        'RetroHursty69 ShabangCLEAN'\n        'RetroHursty69 ShabangCRT'\n        'RetroHursty69 PopCom16x9'\n        'RetroHursty69 PopCom5x4'\n        'RetroHursty69 ToggleBobble'\n        'RetroHursty69 Sheeny'\n        'RetroHursty69 ballsy'\n        'RetroHursty69 AIGEN'\n        'RetroHursty69 AIGEN_PLUS'\n        'Saracade scv720'\n        'chicueloarcade Chicuelo'\n        'SuperMagicom nostalgic'\n        'lipebello retrorama'\n        'lipebello retrorama-turbo'\n        'lipebello strangerstuff'\n        'lipebello spaceoddity'\n        'lipebello spaceoddity-43'\n        'lipebello spaceoddity-wide'\n        'lipebello swineapple'\n        'waweedman pii-wii'\n        'waweedman Blade-360'\n        'waweedman Venom'\n        'waweedman Spider-Man'\n        'blowfinger77 locomotion'\n        'justincaseurskynet Arcade1up-5x4-Horizontal'\n        'KALEL1981 Super-Retroboy'\n        'xovox RetroCRT-240p'\n        'xovox RetroCRT-240p-Rainbow'\n        'xovox RetroCRT-240p-Vertical'\n        'arcadeforge push-a'\n        'arcadeforge push-a-v'\n        'arcadeforge pixel-heaven'\n        'arcadeforge pixel-heaven-text'\n        'arcadeforge 240p_Bubblegum'\n        'arcadeforge 240p-honey'\n        'dionmunk clean'\n        'c64-dev epicnoir'\n        'AndreaMav arcade-crt'\n        'AndreaMav arcade-crt2020'\n        'Zechariel VectorPie'\n        'KALEL1981 nes-box'\n        'KALEL1981 super-arcade1up-5x4'\n        'KALEL1981 gold-standard'\n        'Elratauru angular-artwork'\n        'cjonasw raspixel-320-240'\n        'crxone 3twenty2fourty'\n        'leochely Guilty-Gear'\n        'flpowergamesretro-rtp ffarts'\n    )\n    while true; do\n        local theme\n        local theme_dir\n        local branch\n        local name\n\n        local installed_themes=()\n        local repo\n        local options=()\n        local status=()\n        local default\n\n        local gallerydir=\"/etc/emulationstation/es-theme-gallery\"\n        if [[ -d \"$gallerydir\" ]]; then\n            status+=(\"i\")\n            options+=(G \"View or Update Theme Gallery\")\n        else\n            status+=(\"n\")\n            options+=(G \"Download Theme Gallery\")\n        fi\n\n        options+=(U \"Update all installed themes\")\n\n        local i=1\n        for theme in \"${themes[@]}\"; do\n            theme=($theme)\n            repo=\"${theme[0]}\"\n            theme=\"${theme[1]}\"\n            branch=\"${theme[2]}\"\n            name=\"$repo/$theme\"\n            theme_dir=\"$theme\"\n            if [[ -n \"$branch\" ]]; then\n                name+=\" ($branch)\"\n                theme_dir+=\"-$branch\"\n            fi\n            if [[ -d \"/etc/emulationstation/themes/$theme_dir\" ]]; then\n                status+=(\"i\")\n                options+=(\"$i\" \"Update or Uninstall $name (installed)\")\n                installed_themes+=(\"$theme $repo $branch\")\n            else\n                status+=(\"n\")\n                options+=(\"$i\" \"Install $name\")\n            fi\n            ((i++))\n        done\n        local cmd=(dialog --default-item \"$default\" --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        [[ -z \"$choice\" ]] && break\n        case \"$choice\" in\n            G)\n                if [[ \"${status[0]}\" == \"i\" ]]; then\n                    options=(1 \"View Theme Gallery\" 2 \"Update Theme Gallery\" 3 \"Remove Theme Gallery\")\n                    cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option for gallery\" 12 40 06)\n                    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n                    case \"$choice\" in\n                        1)\n                            cd \"$gallerydir\"\n                            if isPlatform \"x11\"; then\n                                feh --info \"echo %f\" --slideshow-delay 6 --fullscreen --auto-zoom --filelist images.list\n                            else\n                                fbi --timeout 6 --once --autozoom --list images.list\n                            fi\n                            ;;\n                        2)\n                            gitPullOrClone \"$gallerydir\" \"https://github.com/wetriner/es-theme-gallery\"\n                            ;;\n                        3)\n                            if [[ -d \"$gallerydir\" ]]; then\n                                rm -rf \"$gallerydir\"\n                            fi\n                            ;;\n                    esac\n                else\n                    gitPullOrClone \"$gallerydir\" \"http://github.com/wetriner/es-theme-gallery\"\n                fi\n                ;;\n            U)\n                for theme in \"${installed_themes[@]}\"; do\n                    theme=($theme)\n                    rp_callModule esthemes install_theme \"${theme[0]}\" \"${theme[1]}\" \"${theme[2]}\"\n                done\n                ;;\n            *)\n                theme=(${themes[choice-1]})\n                repo=\"${theme[0]}\"\n                theme=\"${theme[1]}\"\n                branch=\"${theme[2]}\"\n                name=\"$repo/$theme\"\n                theme_dir=\"$theme\"\n                if [[ -n \"$branch\" ]]; then\n                    name+=\" ($branch)\"\n                    theme_dir+=\"-$branch\"\n                fi\n                if [[ \"${status[choice]}\" == \"i\" ]]; then\n                    options=(1 \"Update $name\" 2 \"Uninstall $name\")\n                    cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option for theme\" 12 60 06)\n                    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n                    case \"$choice\" in\n                        1)\n                            rp_callModule esthemes install_theme \"$theme\" \"$repo\" \"$branch\"\n                            ;;\n                        2)\n                            rp_callModule esthemes uninstall_theme \"$theme_dir\"\n                            ;;\n                    esac\n                else\n                    rp_callModule esthemes install_theme \"$theme\" \"$repo\" \"$branch\"\n                fi\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/gamecondriver.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"gamecondriver\"\nrp_module_desc=\"Gamecon & Db9 drivers GPIO drivers\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/marqs85/gamecon_gpio_rpi/master/gamecon_gpio_rpi/gamecon_gpio_rpi.c\"\nrp_module_section=\"driver\"\nrp_module_flags=\"!all rpi !rpi5\"\n\nfunction depends_gamecondriver() {\n    getDepends dkms LINUX-HEADERS\n}\n\nfunction _gamecon_version() {\n    echo \"1.5\"\n}\n\nfunction _db9_version() {\n    echo \"1.3\"\n}\nfunction install_bin_gamecondriver() {\n    # install both modules\n    declare -A modules=(\n        [gamecon_gpio_rpi]=$(_gamecon_version)\n        [db9_gpio_rpi]=$(_db9_version)\n    )\n    local github_url=\"https://github.com/marqs85\"\n\n    _remove_gamecondriver_files\n\n    pushd \"$md_inst\"\n    for module_name in \"${!modules[@]}\"; do\n        local module_ver=\"${modules[$module_name]}\"\n        gitPullOrClone \"$module_name\" \"$github_url/$module_name\"\n\n        pushd \"$module_name\"\n        dkmsManager remove \"$module_name\" \n        ln -sfn \"`pwd`/$module_name\" /usr/src/\"$module_name-$module_ver\"\n        dkms install --force -m \"$module_name\" -v \"$module_ver\"\n        popd\n\n        # test if module installation is OK\n        if ! dkms status | grep -q \"^$module_name\"; then\n            md_ret_errors+=(\"$module_name driver installation FAILED\")\n        fi\n    done\n    popd\n}\n\nfunction _remove_gamecondriver_config()\n{\n    sed -i \"/gamecon_gpio_rpi/d\" /etc/modules\n    rm -f /etc/modprobe.d/gamecon.conf\n}\n\nfunction _remove_gamecondriver_files()\n{\n    dkmsManager remove gamecon_gpio_rpi\n    dkmsManager remove db9_gpio_rpi\n\n    # remove older version of the driver, installed as Debian packages\n    hasPackage gamecon-gpio-rpi-dkms && aptRemove gamecon-gpio-rpi-dkms\n    hasPackage db9-gpio-rpi-dkms && aptRemove db9-gpio-rpi-dkms\n}\n\nfunction remove_gamecondriver() {\n    _remove_gamecondriver_files\n    _remove_gamecondriver_config\n}\n\nfunction configure_gamecondriver() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    if ! grep -q \"gamecon_gpio_rpi\" /etc/modules; then\n        addLineToFile \"gamecon_gpio_rpi\" /etc/modules\n    elif grep -q \"gamecon_gpio_rpi.*map\" /etc/modules; then\n        sed -i \"s/gamecon_gpio_rpi.*/gamecon_gpio_rpi/\" /etc/modules\n    fi\n}\n\nfunction dual_snes_gamecondriver() {\n    local gpio_rev\n    case \"$(grep Revision /proc/cpuinfo | cut -d ':' -f 2 | tr -d ' \\n' | tail -c 4)\" in\n        \"0002\"|\"0003\")\n            gpio_rev=1\n            ;;\n        *)\n            gpio_rev=2\n            ;;\n    esac\n\n    if [[ \"$gpio_rev\" == 1 ]]; then\n        echo \"options gamecon_gpio_rpi map=0,1,1,0\" >/etc/modprobe.d/gamecon.conf\n    else\n        echo \"options gamecon_gpio_rpi map=0,0,1,0,0,1\" >/etc/modprobe.d/gamecon.conf\n    fi\n\n    [[ -n \"$(lsmod | grep gamecon_gpio_rpi)\" ]] && rmmod gamecon_gpio_rpi\n    modprobe gamecon_gpio_rpi\n\n    iniConfig \" = \" \"\" \"$configdir/all/retroarch.cfg\"\n\n    if dialog --yesno \"Would you like to update button mappings in $configdir/all/retroarch.cfg for 2 SNES controllers?\" 22 76 >/dev/tty; then\n        if [[ \"$GPIOREV\" == 1 ]]; then\n            iniSet \"input_player1_joypad_index\" \"0\"\n            iniSet \"input_player2_joypad_index\" \"1\"\n        else\n            iniSet \"input_player1_joypad_index\" \"1\"\n            iniSet \"input_player2_joypad_index\" \"0\"\n        fi\n\n        iniSet \"input_player1_a_btn\" \"0\"\n        iniSet \"input_player1_b_btn\" \"1\"\n        iniSet \"input_player1_x_btn\" \"2\"\n        iniSet \"input_player1_y_btn\" \"3\"\n        iniSet \"input_player1_l_btn\" \"4\"\n        iniSet \"input_player1_r_btn\" \"5\"\n        iniSet \"input_player1_start_btn\" \"7\"\n        iniSet \"input_player1_select_btn\" \"6\"\n        iniSet \"input_player1_left_axis\" \"-0\"\n        iniSet \"input_player1_up_axis\" \"-1\"\n        iniSet \"input_player1_right_axis\" \"+0\"\n        iniSet \"input_player1_down_axis\" \"+1\"\n\n        iniSet \"input_player2_a_btn\" \"0\"\n        iniSet \"input_player2_b_btn\" \"1\"\n        iniSet \"input_player2_x_btn\" \"2\"\n        iniSet \"input_player2_y_btn\" \"3\"\n        iniSet \"input_player2_l_btn\" \"4\"\n        iniSet \"input_player2_r_btn\" \"5\"\n        iniSet \"input_player2_start_btn\" \"7\"\n        iniSet \"input_player2_select_btn\" \"6\"\n        iniSet \"input_player2_left_axis\" \"-0\"\n        iniSet \"input_player2_up_axis\" \"-1\"\n        iniSet \"input_player2_right_axis\" \"+0\"\n        iniSet \"input_player2_down_axis\" \"+1\"\n    fi\n\n    dialog --clear --msgbox \"\\\n__________\\n\\\n         |          ### Board gpio revision $gpio_rev detected ###\\n\\\n    + *  |\\n\\\n    * *  |\\n\\\n    1 -  |          The driver is now set to use the following\\n\\\n    2 *  |          configuration for 2 SNES controllers:\\n\\\n    * *  |          (compatible with RetroPie GPIO adapter)\\n\\\n    * *  |\\n\\\n    * *  |          + = power\\n\\\n    * *  |          - = ground\\n\\\n    * *  |          C = clock\\n\\\n    C *  |          L = latch\\n\\\n    * *  |          1 = player1 pad\\n\\\n    L *  |          2 = player2 pad\\n\\\n    * *  |          * = unconnected\\n\\\n         |\\n\\\n         |\" 22 76 >/dev/tty\n}\n\nfunction gui_gamecondriver() {\n    local default\n\n    local options=(\n        1 \"Configure for two SNES controllers\"\n        2 \"Read Gamecon GPIO driver documentation\"\n        3 \"Read Db9 GPIO driver documentation\"\n    )\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Choose an option.\" 22 86 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    dialog --defaultno --yesno \"Gamecon driver supports RetroPie GPIO adapter board for 2 SNES controllers. Do you want to configure gamecon for 2 SNES controllers?\"  22 76 >/dev/tty || continue\n                    dual_snes_gamecondriver\n                    ;;\n                2)\n                    dialog --msgbox \"$(cat \"$md_inst/gamecon_gpio_rpi/gamecon_gpio_rpi-$(_gamecon_version)/README\")\" 22 80 >/dev/tty\n                    ;;\n                3)\n                    dialog --msgbox \"$(cat \"$md_inst/db9_gpio_rpi/db9_gpio_rpi-$(_db9_version)/README\")\" 22 80 >/dev/tty\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/golang.sh",
    "content": "# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"golang\"\nrp_module_desc=\"Golang binary install\"\nrp_module_licence=\"BSD https://golang.org/LICENSE\"\nrp_module_section=\"depends\"\nrp_module_flags=\"noinstclean\"\n\nfunction _get_goroot_golang() {\n    echo \"$rootdir/supplementary/golang\"\n}\n\nfunction install_bin_golang() {\n    local target_version=1.11.13\n    local version\n    if [[ -e \"$md_inst/bin/go\" ]]; then\n        local version=$(GOROOT=\"$md_inst\" \"$md_inst/bin/go\" version | sed 's/.*go\\(1[^ ]*\\).*/\\1/')\n    fi\n    printMsgs \"console\" \"Current Go version: $version\"\n    if compareVersions \"$version\" ge \"$target_version\" ; then\n        return 0\n    fi\n\n    rm -rf \"$md_inst\"\n    mkdir -p \"$md_inst\"\n    local arch=\"armv6l\"\n    if isPlatform \"x86\"; then\n        if isPlatform \"64bit\"; then\n            arch=\"amd64\"\n        else\n            arch=\"386\"\n        fi\n    fi\n    if isPlatform \"aarch64\"; then\n        arch=\"arm64\"\n    fi\n    printMsgs \"console\" \"Downloading go$target_version.linux-$arch.tar.gz\"\n    downloadAndExtract \"https://go.dev/dl/go${target_version}.linux-$arch.tar.gz\" \"$md_inst\" --strip-components 1 --exclude=\"go/test\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/kmsxx.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"kmsxx\"\nrp_module_desc=\"library and utilities for Linux kernel mode setting\"\nrp_module_licence=\"MPL2 https://raw.githubusercontent.com/cmitu/kmsxx/master/LICENSE\"\nrp_module_repo=\"git https://github.com/cmitu/kmsxx retropie\"\nrp_module_section=\"depends\"\nrp_module_flags=\"\"\n\nfunction depends_kmsxx() {\n    getDepends meson ninja-build libdrm-dev libfmt-dev pkg-config\n}\n\nfunction sources_kmsxx() {\n    gitPullOrClone\n}\n\nfunction build_kmsxx() {\n    rm -fr build\n    meson setup --prefix=\"$md_inst\" -Dbuildtype=release -Ddefault_library=static -Domap=disabled -Dpykms=disabled -Dkmscube=false build\n    ninja -C build\n\n    md_ret_require=\"$md_build/build/utils/kmsprint-rp\"\n}\n\nfunction install_kmsxx() {\n    md_ret_files=(\n        build/utils/kmsprint-rp\n        build/utils/kmsprint\n        build/utils/kmsview\n        build/utils/kmsblank\n        build/utils/fbtest\n    )\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/launchingimages.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"launchingimages\"\nrp_module_desc=\"Generate runcommand launching images based on emulationstation themes.\"\nrp_module_help=\"A runcommand launching image is displayed while loading a game, with this tool you can automatically create some cool images based on a chosen emulationstation theme you have on your system.\"\nrp_module_repo=\"git https://github.com/meleu/generate-launching-images.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"noinstclean\"\n\nfunction depends_launchingimages() {\n    local depends=(imagemagick librsvg2-bin)\n    if isPlatform \"x11\"; then\n        depends+=(feh)\n    else\n        depends+=(fbi)\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction install_bin_launchingimages() {\n    gitPullOrClone \"$md_inst\"\n}\n\nfunction _show_images_launchingimages() {\n    local image\n    local timeout=5\n    local is_list=0\n\n    if [[ \"$1\" = \"1\" ]]; then\n        is_list=1\n        shift\n    fi\n\n    [[ -f \"$1\" ]] || return 1\n    image=\"$1\"\n\n    if isPlatform \"x11\"; then\n        feh \\\n            --cycle-once \\\n            --hide-pointer \\\n            --fullscreen \\\n            --auto-zoom \\\n            --no-menus \\\n            --slideshow-delay $timeout \\\n            --quiet \\\n            $([[ \"$is_list\" -eq 1 ]] && echo --filelist) \\\n            \"$image\"\n    else\n        fbi \\\n            --once \\\n            --timeout \"$timeout\" \\\n            --noverbose \\\n            --autozoom \\\n            $([[ \"$is_list\" -eq 1 ]] && echo --list) \\\n            \"$image\" </dev/tty &>/dev/null\n    fi\n}\n\nfunction _dialog_menu_launchingimages() {\n    local text=\"$1\"\n    shift\n    local options=()\n    local choice\n    local opt\n    local i\n\n    [[ \"$#\" -eq 0 ]] && return 1\n\n    i=1\n    for opt in \"$@\"; do\n        options+=( \"$i\" \"$opt\" )\n        ((i++))\n    done\n    choice=$(dialog --backtitle \"$__backtitle\" --menu \"$text\" 22 86 16 \"${options[@]}\" 2>&1 >/dev/tty) || return\n    echo \"${options[choice*2-1]}\"\n}\n\nfunction _set_theme_launchingimages() {\n    _dialog_menu_launchingimages \"List of available themes\" $(\"$md_inst/generate-launching-images.sh\" --list-themes) \\\n    || echo \"$theme\"\n}\n\nfunction _set_system_launchingimages() {\n    local options=()\n    local choice\n\n    options=( all )\n    options+=( $(\"$md_inst/generate-launching-images.sh\" --list-systems) )\n    choice=$(\n        _dialog_menu_launchingimages \\\n            \"List of available systems.\\n\\nSelect the system you want to generate a launching image or \\\"all\\\" to generate for all systems.\" \\\n            \"${options[@]}\"\n    )\n    case \"$choice\" in\n        \"all\")  echo \"\" ;;\n        \"\")     echo \"$system\" ;;\n        *)      echo \"--system $choice\" ;;\n    esac\n}\n\nfunction _set_extension_launchingimages() {\n    _dialog_menu_launchingimages \"Choose the file extension of the final launching image.\" png jpg \\\n    || echo \"$extension\"\n}\n\nfunction _set_show_timeout_launchingimages() {\n    _dialog_menu_launchingimages \\\n        \"Set how long the image will be displayed before asking if you accept (in seconds)\" \\\n        1 2 3 4 5 6 7 8 9 10 \\\n    || echo \"$show_timeout\"\n}\n\nfunction _set_loading_text_launchingimages() {\n    dialog \\\n        --backtitle \"$__backtitle\" \\\n        --inputbox \"Enter the \\\"NOW LOADING\\\" text (or leave blank to no text):\" \\\n        0 70 \\\n        \"NOW LOADING\" \\\n        2>&1 >/dev/tty \\\n    || echo \"$loading_text\"\n}\n\nfunction _set_press_button_text_launchingimages() {\n    dialog \\\n        --backtitle \"$__backtitle\" \\\n        --inputbox \"Enter the \\\"PRESS A BUTTON\\\" text (or leave blank to no text):\" \\\n        0 70 \\\n        \"PRESS A BUTTON TO CONFIGURE LAUNCH OPTIONS\" \\\n        2>&1 >/dev/tty \\\n    || echo \"$press_button_text\"\n}\n\nfunction _select_color_launchingimages() {\n    _dialog_menu_launchingimages \\\n        \"Pick a color for the $1\" \\\n        white black silver gray gray10 gray25 gray50 gray75 gray90 \\\n        red orange yellow green cyan blue cyan purple pink brown\n}\n\nfunction _set_loading_text_color_launchingimages() {\n    _select_color_launchingimages \"\\\"LOADING\\\" text\" || echo \"$loading_text_color\"\n}\n\nfunction _set_press_button_text_color_launchingimages() {\n    _select_color_launchingimages \"\\\"PRESS A BUTTON\\\" text\" || echo \"$press_button_text_color\"\n}\n\nfunction _set_solid_bg_color_launchingimages() {\n    local choice\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Color to use as background\" 22 86 16)\n    local options=(\n          0 \"Disable \\\"solid background color\\\"\"\n          1 \"Use the system color defined by theme\"\n          2 \"Select a color\"\n    )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n    case \"$choice\" in\n        0)  echo\n            ;;\n        1)  echo \"--solid-bg-color\"\n            ;;\n        2)  echo \"--solid-bg-color $(_select_color_launchingimages background)\"\n            ;;\n        *)  echo \"$solid_bg_color\"\n            ;;\n    esac\n}\n\nfunction _dialog_yesno_launchingimages() {\n    dialog --backtitle \"$__backtitle\" --yesno \"$@\" 20 60 2>&1 >/dev/tty\n}\n\nfunction _set_no_ask_launchingimages() {\n    _dialog_yesno_launchingimages \"If you enable \\\"no_ask\\\" all generated images will be automatically accepted.\\n\\nDo you want to enable it?\" \\\n    && echo \"--no-ask\"\n}\n\nfunction _set_no_logo_launchingimages() {\n    _dialog_yesno_launchingimages \"If you enable \\\"no_logo\\\" the images won't have the system logo (useful for tronkyfran theme, for example).\\n\\nDo you want to enable it?\" \\\n    && echo \"--no-logo\"\n}\n\nfunction _set_logo_belt_launchingimages() {\n    _dialog_yesno_launchingimages \"If you enable \\\"logo_belt\\\" the image will have a semi-transparent white belt behind the logo.\\n\\nDo you want to enable it?\" \\\n    && echo \"--logo-belt\"\n}\n\nfunction _get_all_launchingimages() {\n    find \"$configdir\" -type f -regex \".*launching\\.\\(png\\|jpg\\)\" | sort\n}\n\nfunction _is_theme_chosen_launchingimages() {\n    if [[ -z \"$1\" ]]; then\n        printMsgs \"dialog\" \"You didn't choose a theme!\\n\\nGo to the \\\"Image generation settings\\\" and choose one.\"\n        return 1\n    fi\n}\n\nfunction _get_config_file_launchingimages() {\n    local file_list=$(find \"$md_inst\" -type f -name '*.cfg' ! -name '.current.cfg' | sort | xargs)\n    if [[ -z \"$file_list\" ]]; then\n        printMsgs \"dialog\" \"There's no config file saved.\"\n        return 1\n    fi\n    _dialog_menu_launchingimages \"Choose the file\" $file_list # XXX: no quotes surrounding $file_list is mandatory!\n    return $?\n}\n\nfunction _load_config_launchingimages() {\n    echo \"$(loadModuleConfig \\\n        'theme=' \\\n        'extension=png' \\\n        'show_timeout=5' \\\n        'loading_text=NOW LOADING' \\\n        'press_button_text=PRESS A BUTTON TO CONFIGURE LAUNCH OPTIONS' \\\n        'loading_text_color=white' \\\n        'press_button_text_color=gray50' \\\n        'no_ask=' \\\n        'no_logo=' \\\n        'solid_bg_color=' \\\n        'system=' \\\n        'logo_belt=' \\\n    )\"\n}\n\nfunction _settings_launchingimages() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --title \" SETTINGS \" --cancel-label \"Back\" --menu \"runcommand launching images generation settings.\" 22 86 16)\n    local options\n    local choice\n    local config_file\n\n    iniConfig ' = ' '\"' \"$current_cfg\"\n\n    while true; do\n        eval $(_load_config_launchingimages)\n\n        options=( \n            config_file \"$(\n               [[ \"$config_file\" == *\"$theme.cfg\" ]] && echo \"$(basename \"$config_file\")\"\n            )\"\n            theme \"$theme\"\n            system \"$(\n                if [[ -z \"$system\" ]]; then\n                    echo \"all systems in es_systems.cfg\"\n                else\n                    echo \"$system\" | cut -d' ' -f2\n                fi\n            )\"\n            extension \".$extension\"\n            loading_text \"\\\"$loading_text\\\"\"\n            press_button_text \"\\\"$press_button_text\\\"\"\n            loading_text_color \"$loading_text_color\"\n            press_button_text_color \"$press_button_text_color\"\n            show_timeout \"$( [[ -n \"$no_ask\" ]] && echo \"don't show (see no_ask)\" || echo \"$show_timeout seconds\")\"\n            no_ask \"$( [[ -n \"$no_ask\" ]] && echo true || echo false)\"\n            no_logo \"$( [[ -n \"$no_logo\" ]] && echo true || echo false)\"\n            logo_belt \"$( [[ -n \"$logo_belt\" ]] && echo true || echo false)\"\n            solid_bg_color \"$(\n                if [[ -z \"$solid_bg_color\" ]]; then\n                    echo false\n                elif [[ -z \"$(echo \"$solid_bg_color\" | cut -s -d' ' -f2)\" ]]; then\n                    echo \"get from the theme\"\n                else\n                    echo \"$solid_bg_color\" | cut -s -d' ' -f2\n                fi\n            )\"\n        )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n        [[ -z \"$choice\" ]] && break\n\n        if [[ \"$choice\" = \"config_file\" ]]; then\n            config_file=$(_manage_config_file_launchingimages)\n            continue\n        fi\n\n        iniSet \"$choice\" \"$(_set_${choice}_launchingimages)\"\n    done\n}\n\nfunction _manage_config_file_launchingimages() {\n    local choice\n    local config_file\n\n    eval $(_load_config_launchingimages)\n\n    while true; do\n        choice=$(\n            dialog --backtitle \"$__backtitle\" --title \" CONFIG FILE \" --menu \"Choose an option\" 22 86 16 \\\n                1 \"Load a file\" \\\n                2 \"Save current configs for \\\"$theme\\\"\" \\\n                3 \"Delete a config file\" \\\n                2>&1 >/dev/tty\n        )\n\n        case \"$choice\" in\n            1)  # load config\n                config_file=$(_get_config_file_launchingimages) || continue\n                cat \"$config_file\" > \"$current_cfg\"\n                echo \"$config_file\"\n                break\n                ;;\n\n            2)  # save config\n                _is_theme_chosen_launchingimages \"$theme\" || break\n                config_file=\"$md_inst/$theme.cfg\"\n                if [[ -f \"$config_file\" ]]; then\n                    _dialog_yesno_launchingimages \"\\\"$(basename \"$config_file\")\\\" exists.\\nDo you want to overwrite it?\" \\\n                    || continue\n                fi\n                cat \"$current_cfg\" > \"$config_file\"\n                printMsgs \"dialog\" \"\\\"$(basename \"$config_file\")\\\" saved!\"\n                echo \"$config_file\"\n                break\n                ;;\n\n            3)  # delete config\n                config_file=$(_get_config_file_launchingimages) || continue\n\n                _dialog_yesno_launchingimages \"Are you sure you want to delete \\\"$config_file\\\"?\" \\\n                || continue\n\n                local err_msg=$(rm -v \"$config_file\")\n                printMsgs \"dialog\" \"$err_msg\"\n                ;;\n\n            *)\n                break\n                ;;\n        esac\n    done\n}\n\nfunction _generate_launchingimages() {\n    eval $(_load_config_launchingimages)\n\n    _is_theme_chosen_launchingimages \"$theme\" || return\n    \"$md_inst/generate-launching-images.sh\" \\\n        --theme \"$theme\" \\\n        --extension \"$extension\" \\\n        --show-timeout \"$show_timeout\" \\\n        --loading-text \"$loading_text\" \\\n        --press-button-text \"$press_button_text\" \\\n        --loading-text-color \"$loading_text_color\" \\\n        --press-button-text-color \"$press_button_text_color\" \\\n        $system \\\n        $solid_bg_color \\\n        $no_ask \\\n        $no_logo \\\n        $logo_belt \\\n        2>&1 >/dev/tty\n\n    if [[ \"$?\" -ne 0 ]]; then\n        printMsgs \"dialog\" \"Unable to generate launching images. Please check the \\\"Image generation settings\\\".\"\n        return\n    fi\n\n    for file in $(_get_all_launchingimages); do\n        chown \"$__user\":\"$__group\" \"$file\"\n    done\n}\n\nfunction gui_launchingimages() {\n    local cmd=()\n    local options=()\n    local choice\n    local current_cfg=\"$md_inst/.current.cfg\"\n\n    rm -f \"$current_cfg\"\n    while true; do\n        cmd=(dialog --backtitle \"$__backtitle\" --title \" runcommand launching images generation \" --menu \"Choose an option.\" 22 86 16)\n        options=( \n            1 \"Image generation settings\"\n            2 \"Generate launching images\"\n            3 \"View slideshow of all current launching images\"\n            4 \"View a specific system's launching image\"\n        )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1) # Image generation settings\n                    _settings_launchingimages\n                    ;;\n\n                2) # Generate launching images\n                    _generate_launchingimages\n                    ;;\n\n                3) # View slideshow of all current launching images\n                    local file=$(mktemp)\n                    _get_all_launchingimages > \"$file\"\n                    if [[ -s \"$file\" ]]; then\n                        _show_images_launchingimages 1 \"$file\"\n                    else\n                        printMsgs \"dialog\" \"No launching image found.\"\n                    fi\n                    rm -f \"$file\"\n                    ;;\n\n                4) # View the launching image of a specific system\n                    while true; do\n                        local img_list=( $(_get_all_launchingimages) )\n                        if [[ \"${#img_list[@]}\" -eq 0 ]]; then\n                            printMsgs \"dialog\" \"No launching image found.\"\n                            break\n                        fi\n                        choice=$(_dialog_menu_launchingimages \"Choose the system\" \"${img_list[@]}\")\n                        [[ -z \"$choice\" ]] && break\n                        _show_images_launchingimages \"$choice\"\n                    done\n                    ;;\n\n            esac\n        else\n            break\n        fi\n    done\n    rm -f \"$current_cfg\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/mehstation.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mehstation\"\nrp_module_desc=\"mehstation emulator frontend\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/remeh/mehstation/master/LICENSE\"\nrp_module_repo=\"git https://github.com/remeh/mehstation master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"frontend nobin\"\n\nfunction _get_database_mehstation() {\n    echo \"$configdir/all/mehstation/database.db\"\n}\n\nfunction _add_system_mehstation() {\n    local db=\"$(_get_database_mehstation)\"\n    [[ ! -f \"$db\" ]] && return 0\n\n    local fullname=\"$1\"\n    local name=\"$2\"\n    local path=\"$3\"\n    local extensions=\"$4\"\n    local command=\"$5\"\n    local platform=\"$6\"\n    local theme=\"$7\"\n\n    command=\"${command//%ROM%/%exec%}\"\n    extensions=\"${extensions// /,}\"\n    NAME=\"$fullname\" COMMAND=\"$command\" DIR=\"$path\" EXTS=\"$extensions\" \"/opt/retropie/supplementary/mehstation/bin/mehtadata\" -db=\"$db\" -new-platform\n}\n\nfunction _del_system_mehstation() {\n    local db=\"$(_get_database_mehstation)\"\n    [[ ! -f \"$db\" ]] && return 0\n\n    local fullname=\"$1\"\n    local name=\"$2\"\n\n    PLATFORM_NAME=\"$fullname\" \"/opt/retropie/supplementary/mehstation/bin/mehtadata\" -db=\"$db\" -del-platform\n}\n\nfunction _add_rom_mehstation() {\n    local db=\"$(_get_database_mehstation)\"\n    [[ ! -f \"$db\" ]] && return 0\n\n    local system_name=\"$1\"\n    local system_fullname=\"$2\"\n    local path=\"$3\"\n    local name=\"$4\"\n    local desc=\"$5\"\n    local image=\"$6\"\n\n    NAME=\"$4\" FILEPATH=\"$path\" PLATFORM_NAME=\"$system_fullname\" DESCRIPTION=\"$desc\" \"/opt/retropie/supplementary/mehstation/bin/mehtadata\" -db=\"$db\" -new-exec\n\n    RESOURCE=\"$image\" FILEPATH=\"$path\" PLATFORM_NAME=\"$system_fullname\" TYPE=\"cover\" \"/opt/retropie/supplementary/mehstation/bin/mehtadata\" -db=\"$db\" -new-res\n}\n\nfunction depends_mehstation() {\n    local depends=(\n        cmake automake libfreeimage-dev libopenal-dev libpango1.0-dev\n        libsndfile1-dev libudev-dev libasound2-dev libjpeg-dev\n        libtiff5-dev libwebp-dev libsqlite3-dev libavutil-dev libavcodec-dev\n        libavformat-dev libsdl2-dev libsdl2-image-dev libsdl2-ttf-dev\n        libsdl2-image-dev sqlite3 golang\n    )\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_mehstation() {\n    gitPullOrClone\n    GOPATH=\"$md_build/mehtadata\" go get github.com/remeh/mehtadata\n}\n\nfunction build_mehstation() {\n    cd mehtadata\n    GOPATH=\"$md_build/mehtadata\" go build\n    cd ..\n\n    cmake .\n    make clean\n    make\n\n    md_ret_require=(\n        \"$md_build/mehstation\"\n        \"$md_build/mehtadata/bin/mehtadata\"\n    )\n}\n\nfunction install_mehstation() {\n    mkdir -p \"$md_inst\"/{bin,share/mehstation}\n    cp mehstation mehtadata/bin/mehtadata \"$md_inst/bin/\"\n    cp -R res \"$md_inst/share/\"\n}\n\n\nfunction configure_mehstation() {\n    # move / symlink the configuration\n    moveConfigDir \"$home/.config/mehstation\" \"$md_conf_root/all/mehstation\"\n\n    local db=\"$md_conf_root/all/mehstation/database.db\"\n\n    if [[ ! -f \"$db\" ]]; then\n        local sql\n        while read -r sql; do\n            sudo -u \"$__user\" SCHEMA=\"$sql\" \"$md_inst/bin/mehtadata\" -db=\"$db\" -init\n        done < <(find \"$md_inst/share/res\" -name \"*.sql\" | sort)\n    fi\n\n    cat >/usr/bin/mehstation <<_EOF_\n#!/bin/bash\npushd \"$md_inst/share\" >/dev/null\n\"$md_inst/bin/mehstation\" \"\\$@\"\npopd\n_EOF_\n    chmod +x \"/usr/bin/mehstation\"\n\n    local id\n    for id in \"${__mod_id[@]}\"; do\n        if rp_isInstalled \"$id\" && [[ -n \"${__mod_info[$id/section]}\" ]] && ! hasFlag \"${__mod_info[$id/flags]}\" \"frontend\"; then\n            rp_callModule \"$id\" configure\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/mesa-drm.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mesa-drm\"\nrp_module_desc=\"libdrm - userspace library for drm\"\nrp_module_licence=\"MIT https://www.mesa3d.org/license.html\"\nrp_module_repo=\"git https://github.com/RetroPie/mesa-drm runcommand_debug\"\nrp_module_section=\"depends\"\nrp_module_flags=\"\"\n\nfunction depends_mesa-drm() {\n    local depends=(meson ninja-build libgbm-dev libdrm-dev libpciaccess-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_mesa-drm() {\n    gitPullOrClone\n}\n\nfunction build_mesa-drm() {\n    local params=()\n\n    # for RPI, disable all but VC4 driver to minimize startup delay\n    isPlatform \"rpi\" && params+=(-Dintel=false -Dradeon=false \\\n                           -Damdgpu=false -Dexynos=false \\\n                           -Dnouveau=false -Dvmwgfx=false \\\n                           -Domap=false -Dfreedreno=false \\\n                           -Dtegra=false -Detnaviv=false -Dvc4=true)\n    meson builddir --prefix=\"$md_inst\" \"${params[@]}\"\n    ninja -C builddir\n\n    md_ret_require=\"$md_build/builddir/tests/modetest/modetest\"\n}\n\nfunction install_mesa-drm() {\n    md_ret_files=(\n        builddir/libkms/libkms.so*\n        builddir/tests/modetest/modetest\n    )\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/mkarcadejoystick.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mkarcadejoystick\"\nrp_module_desc=\"Raspberry Pi GPIO Joystick Driver\"\nrp_module_help=\"Installs the GPIO driver from https://github.com/cmitu/mk_arcade_joystick_rpi\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/recalbox/mk_arcade_joystick_rpi/master/LICENSE\"\nrp_module_repo=\"git https://github.com/cmitu/mk_arcade_joystick_rpi retropie\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean !all rpi !rpi5\"\n\nfunction _version_mkarcadejoystick() {\n    echo \"0.1.7\"\n}\n\nfunction depends_mkarcadejoystick() {\n    depends_gamecondriver\n}\n\nfunction sources_mkarcadejoystick() {\n    gitPullOrClone \"$md_inst\"\n    pushd \"$md_inst\"\n    sed -i \"s/\\$MKVERSION/$(_version_mkarcadejoystick)/\" \"$md_inst/dkms.conf\"\n    popd\n}\n\nfunction build_mkarcadejoystick() {\n    dkmsManager install mk_arcade_joystick_rpi \"$(_version_mkarcadejoystick)\"\n}\n\nfunction remove_mkarcadejoystick() {\n    dkmsManager remove mk_arcade_joystick_rpi\n    rm -f /etc/modprobe.d/mk_arcade_joystick_rpi.conf\n    sed -i \"/mk_arcade_joystick_rpi/d\" /etc/modules\n}\n\nfunction configure_mkarcadejoystick() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    if ! grep -q \"mk_arcade_joystick_rpi\" /etc/modules; then\n        addLineToFile \"mk_arcade_joystick_rpi\" /etc/modules\n    fi\n\n    if [[ ! -f /etc/modprobe.d/mk_arcade_joystick_rpi.conf ]]; then\n        echo \"options mk_arcade_joystick_rpi map=1\" >/etc/modprobe.d/mk_arcade_joystick_rpi.conf\n    fi\n\n    dkmsManager reload mk_arcade_joystick_rpi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/mobilegamepad.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"mobilegamepad\"\nrp_module_desc=\"Mobile Universal Gamepad for RetroPie\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/sbidolach/mobile-gamepad/master/LICENSE\"\nrp_module_repo=\"git https://github.com/sbidolach/mobile-gamepad.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"noinstclean nobin\"\n\nfunction depends_mobilegamepad() {\n    depends_virtualgamepad \"$@\"\n}\n\nfunction remove_mobilegamepad() {\n    pm2 stop app\n    pm2 delete app\n    rm -f /etc/apt/sources.list.d/nodesource.list\n}\n\nfunction sources_mobilegamepad() {\n    gitPullOrClone \"$md_inst\"\n    chown -R \"$__user\":\"$__group\" \"$md_inst\"\n}\n\nfunction install_mobilegamepad() {\n    npm install -g grunt-cli\n    npm install pm2 -g --unsafe-perm\n    cd \"$md_inst\"\n    sudo -u \"$__user\" npm install\n}\n\nfunction configure_mobilegamepad() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n    pm2 start app.sh\n    pm2 startup\n    pm2 save\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/moonlight.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"moonlight\"\nrp_module_desc=\"Moonlight Embedded - an open source gamestream client for embedded systems\"\nrp_module_help=\"ROM Extensions: .ml\\n\\nCopy your moonlight launch configurations to $romdir/steam\\n\\nDon't forget to first pair with your remote host before using moonlight. You can use the configuration menu for pairing/unpairing to/from a remote machine.\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/irtimmer/moonlight-embedded/master/LICENSE\"\nrp_module_repo=\"git https://github.com/irtimmer/moonlight-embedded.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!all arm\"\n\nfunction _scriptmodule_cfg_file_moonlight() {\n    echo \"$configdir/all/moonlight/scriptmodule.cfg\"\n}\n\nfunction _global_cfg_file_moonlight() {\n    echo \"$configdir/all/moonlight/global.conf\"\n}\n\nfunction _mangle_moonlight() {\n    local -r type=\"$1\"\n    shift\n    case \"$type\" in\n        1)  # slugify, ref: https://gist.github.com/oneohthree/f528c7ae1e701ad990e6\n            iconv -c -t ascii//TRANSLIT <<< \"$@\" |\n                sed -r s/[^a-zA-Z0-9]+/-/g |\n                sed -r s/^-+\\|-+$//g |\n                tr \"[:upper:]\" \"[:lower:]\"\n            ;;\n        2)  # windows-compatible, ref: https://stackoverflow.com/a/35352640\n            iconv -c -t ascii//TRANSLIT <<< \"$@\" |\n                sed -r s/[\\<\\>]+/\\ /g |\n                sed -r s/[\\\\/\\|]+/-/g |\n                sed -r s/[:\\*\\\"]+//g\n            ;;\n        0|*)  # no mangling, but replace invalid \"/\" with \"-\"\n            sed -r s/\\\\//-/g <<< \"$@\"\n            ;;\n    esac\n}\n\nfunction _mfmt_moonlight() {\n    case \"$1\" in\n        1)   echo \"SLUGIFY\" ;;\n        2)   echo \"WINDOWS\" ;;\n        0|*) echo \"NONE   \" ;;\n    esac\n}\n\nfunction _bfmt_moonlight() {\n    if [[ \"$1\" -eq 1 ]]; then echo \"YES\"; else echo \"NO \"; fi\n}\n\nfunction depends_moonlight() {\n    # ref: https://github.com/irtimmer/moonlight-embedded/wiki/Compilation#debian-raspbian--osmc\n    local depends=(\n        libssl-dev libopus-dev libasound2-dev libudev-dev\n        libavahi-client-dev libcurl4-openssl-dev libevdev-dev\n        libexpat1-dev libpulse-dev libenet-dev uuid-dev cmake\n    )\n\n    # for remote host autodiscovery features\n    depends+=(avahi-daemon libnss-mdns)\n\n    # platform-specific dependencies\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    isPlatform \"osmc\" && depends+=(rbp-userland-dev-osmc)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n\n    # install selected dependencies\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_moonlight() {\n    gitPullOrClone\n}\n\nfunction build_moonlight() {\n    # ref: https://github.com/irtimmer/moonlight-embedded/wiki/Compilation\n    rm -rf build\n    mkdir build\n    cd build\n    cmake ../ -DCMAKE_INSTALL_PREFIX=\"$md_inst\" \\\n        -DCMAKE_INSTALL_RPATH=\"$md_inst/lib\" \\\n        -DCMAKE_INSTALL_RPATH_USE_LINK_PATH=TRUE\n    make\n}\n\nfunction install_moonlight() {\n    cd build\n    make install\n    strip \"$md_inst/bin/moonlight\"\n}\n\nfunction configure_moonlight() {\n    addEmulator 1 \"$md_id\" \"steam\" \"$md_inst/moonlight.sh stream -config %ROM%\"\n    addSystem \"steam\" \"Steam Game Streaming\" \".ml\"\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # ensure rom dir\n    mkRomDir \"steam\"\n\n    # create and symlink user configuration directory\n    mkUserDir \"$configdir/all/moonlight\"\n    moveConfigDir \"$home/.config/moonlight\" \"$configdir/all/moonlight\"\n\n    # create a new global config file if not there already\n    if [[ ! -f \"$(_global_cfg_file_moonlight)\" ]]; then\n        cat > \"$(_global_cfg_file_moonlight)\" << \"_EOF_\"\n# global config file for moonlight\nquitappafter = true\n_EOF_\n        chown \"$__user\":\"$__group\" \"$(_global_cfg_file_moonlight)\"\n    fi\n\n    # create wrapper for moonlight with appropriate directories set\n    # note: moonlight adds /moonlight to XDG_* variables\n    cat > \"$md_inst/moonlight.sh\" << _EOF_\n#!/usr/bin/env bash\nexport XDG_DATA_DIRS=$md_inst/share\nexport XDG_CONFIG_DIR=$configdir/all\nexport XDG_CACHE_DIR=$configdir/all\n$md_inst/bin/moonlight \"\\$@\"\n_EOF_\n    chmod +x \"$md_inst/moonlight.sh\"\n}\n\nfunction get_scriptmodule_cfg_moonlight() {\n    local address\n    local overwrite=0\n    local wipe=0\n    local mangle=0\n\n    iniConfig \" = \" \"\" \"$(_scriptmodule_cfg_file_moonlight)\"\n    iniGet \"address\" && address=\"$ini_value\"\n    iniGet \"overwrite\" && overwrite=\"$ini_value\"\n    iniGet \"wipe\" && wipe=\"$ini_value\"\n    iniGet \"mangle\" && mangle=\"$ini_value\"\n\n    echo \"$address;$overwrite;$wipe;$mangle\"\n}\n\nfunction set_scriptmodule_cfg_moonlight() {\n    local -r address=\"$1\"\n    local -r overwrite=\"$2\"\n    local -r wipe=\"$3\"\n    local -r mangle=\"$4\"\n\n    [[ -z \"$overwrite\" || -z \"$wipe\" || -z \"$mangle\" ]] && return\n\n    iniConfig \" = \" \"\" \"$(_scriptmodule_cfg_file_moonlight)\"\n    if [[ -n \"$address\" ]]; then\n        iniSet \"address\" \"$address\"\n    else\n        iniDel \"address\"\n    fi\n    iniSet \"overwrite\" \"$overwrite\"\n    iniSet \"wipe\" \"$wipe\"\n    iniSet \"mangle\" \"$mangle\"\n\n    chown \"$__user\":\"$__group\" \"$(_scriptmodule_cfg_file_moonlight)\"\n}\n\nfunction get_resolution_moonlight() {\n    local width=0\n    local height=0\n    local fps=0\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    iniGet \"width\" && width=\"$ini_value\"\n    iniGet \"height\" && height=\"$ini_value\"\n    iniGet \"fps\" && fps=\"$ini_value\"\n\n    if [[ -n \"$width\" && -n \"$height\" && -n \"$fps\" ]]; then\n        echo \"$width;$height;$fps\"\n    else\n        echo \"0;0;0\"\n    fi\n}\n\nfunction get_host_moonlight() {\n    local sops=\"true\"\n    local unsupported=\"false\"\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    iniGet \"sops\" && sops=\"$ini_value\"\n    iniGet \"unsupported\" && unsupported=\"$ini_value\"\n\n    if [[ -n \"$sops\" && -n \"$unsupported\" ]]; then\n        echo \"$sops;$unsupported\"\n    else\n        echo \"true;false\"\n    fi\n}\n\nfunction set_host_moonlight() {\n    local -r sops=\"$1\"\n    local -r unsupported=\"$2\"\n\n    [[ -z \"$sops\" || -z \"$unsupported\" ]] && return\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    iniSet \"sops\" \"$sops\"\n    iniSet \"unsupported\" \"$unsupported\"\n\n    chown \"$__user\":\"$__group\" \"$(_global_cfg_file_moonlight)\"\n}\n\n\nfunction set_resolution_moonlight() {\n    local -r width=\"$1\"\n    local -r height=\"$2\"\n    local -r fps=\"$3\"\n\n    [[ -z \"$width\" || -z \"$height\" || -z \"$fps\" ]] && return\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    if [[ \"$width\" -gt 0 && \"$height\" -gt 0 && \"$fps\" -gt 0 ]]; then\n        iniSet \"width\" \"$width\"\n        iniSet \"height\" \"$height\"\n        iniSet \"fps\" \"$fps\"\n    else\n        iniDel \"width\"\n        iniDel \"height\"\n        iniDel \"fps\"\n    fi\n\n    chown \"$__user\":\"$__group\" \"$(_global_cfg_file_moonlight)\"\n}\n\nfunction get_bitrate_moonlight() {\n    local bitrate=0\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    iniGet \"bitrate\" && bitrate=\"$ini_value\"\n\n    if [[ -n \"$bitrate\" ]]; then\n        echo \"$bitrate\"\n    else\n        echo \"0\"\n    fi\n}\n\nfunction set_bitrate_moonlight() {\n    local -r bitrate=\"$1\"\n\n    [[ -z \"$bitrate\" ]] && return\n\n    iniConfig \" = \" \"\" \"$(_global_cfg_file_moonlight)\"\n    if [[ \"$bitrate\" -gt 0 ]]; then\n        iniSet \"bitrate\" \"$bitrate\"\n    else\n        iniDel \"bitrate\"\n    fi\n\n    chown \"$__user\":\"$__group\" \"$(_global_cfg_file_moonlight)\"\n}\n\nfunction exec_moonlight() {\n    trap \"trap INT; echo; return\" INT\n    sudo -u \"$__user\" \"$md_inst/moonlight.sh\" \"$@\"\n    trap INT\n}\n\nfunction pair_moonlight() {\n    exec_moonlight pair \"$@\"\n}\n\nfunction unpair_moonlight() {\n    exec_moonlight unpair \"$@\"\n}\n\nfunction list_moonlight() {\n    exec_moonlight list \"$@\"\n}\n\nfunction clear_pairing_moonlight() {\n    rm -rf \"$configdir/all/moonlight\"/{client*,key*,uniqueid.dat}\n}\n\nfunction gen_configs_moonlight() {\n    local apps=()\n    local app\n    local fname\n    local config\n\n    # read scriptmodule config\n    IFS=\";\" read -r -a config < <(get_scriptmodule_cfg_moonlight)\n\n    # wipe existing configuration files?\n    if [[ \"${config[2]}\" -eq 1 ]]; then\n        printMsgs \"console\" \"Wiping existing config files ...\"\n        rm -f \"$romdir/steam/\"*.ml\n    fi\n\n    # iterate over all apps in remote host\n    mapfile -t apps < <(list_moonlight ${config[0]:+\"${config[0]}\"} | sed -nE 's/^[0-9]+\\. //gp')\n    for app in \"${apps[@]}\"; do\n        if [[ \"$app\" == \".\" || \"$app\" == \"..\" ]]; then\n            printMsgs \"console\" \"warning: app name '$app' is not valid\"\n            continue\n        fi\n        fname=\"$(_mangle_moonlight \"${config[3]}\" \"$app\")\"  # app filename mangle\n        [[ \"${config[1]}\" -eq 0 && -f \"$romdir/steam/$fname.ml\" ]] && continue  # overwrite?\n\n        # generate config file with defaults\n        printMsgs \"console\" \"Generating config file for '$app' ...\"\n        iniConfig \" = \" \"\" \"$romdir/steam/$fname.ml\"\n        iniSet \"config\" \"$(_global_cfg_file_moonlight)\"\n        [[ -n \"${config[0]}\" ]] && iniSet \"address\" \"${config[0]}\"\n        iniSet \"app\" \"$app\"\n        chown \"$__user\":\"$__group\" \"$romdir/steam/$fname.ml\" 2>/dev/null\n    done\n}\n\nfunction apps_gui_moonlight() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local config\n\n    # read scriptmodule config\n    IFS=\";\" read -r -a config < <(get_scriptmodule_cfg_moonlight)\n\n    # start the menu gui\n    default=\"O\"\n    while true; do\n        # create menu options\n        options=(\n            O \"Overwrite existing config files: $(_bfmt_moonlight ${config[1]})\" \"Overwrite existing files in '$romdir/steam'?\"\n            W \"Wipe existing config files: $(_bfmt_moonlight ${config[2]})\" \"Delete all files in '$romdir/steam'?\"\n            S \"Config filename mangling: $(_mfmt_moonlight ${config[3]})\" \"Use original app names, slugified names or Windows-compatible names?\"\n            G \"Generate config files\" \"Start remote apps config files generation\"\n        )\n\n        # show main menu\n        cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --item-help --menu \"Remote Apps\" 13 60 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        case \"$choice\" in\n            O)\n                config[1]=$((1 - config[1]))\n                set_scriptmodule_cfg_moonlight \"${config[@]}\"\n                ;;\n            W)\n                config[2]=$((1 - config[2]))\n                set_scriptmodule_cfg_moonlight \"${config[@]}\"\n                ;;\n            S)\n                config[3]=$((config[3] + 1))\n                [[ \"${config[3]}\" -gt 2 ]] && config[3]=0\n                set_scriptmodule_cfg_moonlight \"${config[@]}\"\n                ;;\n            G)\n                gen_configs_moonlight\n                read -p \"Press ENTER to continue... \"\n                ;;\n            *)\n                break\n                ;;\n        esac\n    done\n}\n\nfunction host_gui_moonlight() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local tuple\n\n    # get current host options\n    IFS=\";\" read -r -a tuple < <(get_host_moonlight)\n    default=\"U\"\n    [[ \"${tuple[0]}\" == \"false\" && \"${tuple[1]}\" == \"false\" ]] && default=\"1\"\n    [[ \"${tuple[0]}\" == \"true\"  && \"${tuple[1]}\" == \"true\"  ]] && default=\"2\"\n    [[ \"${tuple[0]}\" == \"false\" && \"${tuple[1]}\" == \"true\"  ]] && default=\"3\"\n\n    # create menu options\n    options=(\n        U \"Unset (use default)\" \"Do not force host compatibility settings\"\n        1 \"No SOPS\" \"Don't allow GFE to modify game settings\"\n        2 \"Allow unsupported\" \"Try streaming if GFE version or options are unsupported\"\n        3 \"Open-source host compatibility\" \"Turn off SOPS and allow unsupported options (for Sunshine/Open-Stream GFE server)\"\n    )\n\n    # show main menu\n    cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --item-help --menu \"Host Compatibility Options\" 16 45 16)\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    case \"$choice\" in\n        U)\n            set_host_moonlight \"true\" \"false\"\n            ;;\n        1)\n            set_host_moonlight \"false\" \"false\"\n            ;;\n        2)\n            set_host_moonlight \"true\" \"true\"\n            ;;\n        3)\n            set_host_moonlight \"false\" \"true\"\n            ;;\n    esac\n}\n\nfunction resolution_gui_moonlight() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local resolution\n\n    # get current resolution\n    IFS=\";\" read -r -a resolution < <(get_resolution_moonlight)\n    if [[ \"${resolution[0]}\" -gt 0 && \"${resolution[1]}\" -gt 0 && \"${resolution[2]}\" -gt 0 ]]; then\n        default=\"C\"\n        [[ \"${resolution[0]}\" == 1920 && \"${resolution[1]}\" == 1080 && \"${resolution[2]}\" == 60 ]] && default=\"1\"\n        [[ \"${resolution[0]}\" == 1920 && \"${resolution[1]}\" == 1080 && \"${resolution[2]}\" == 30 ]] && default=\"2\"\n        [[ \"${resolution[0]}\" == 1280 && \"${resolution[1]}\" == 720 && \"${resolution[2]}\" == 60 ]] && default=\"3\"\n        [[ \"${resolution[0]}\" == 1280 && \"${resolution[1]}\" == 720 && \"${resolution[2]}\" == 30 ]] && default=\"4\"\n        resolution=\"${resolution[0]} x ${resolution[1]} @ ${resolution[2]} fps\"\n    else\n        default=\"U\"\n        resolution=\"(using default)\"\n    fi\n\n    # create menu options\n    options=(\n        U \"Unset (use default)\" \"Do not force a resolution setting\"\n        1 \"1080p60\" \"Set resolution to 1920 x 1080 @ 60 fps\"\n        2 \"1080p30\" \"Set resolution to 1920 x 1080 @ 30 fps\"\n        3 \"720p60\"  \"Set resolution to 1280 x 720 @ 60 fps\"\n        4 \"720p30\"  \"Set resolution to 1280 x 720 @ 30 fps\"\n        C \"Custom\"  \"Set a custom resolution\"\n    )\n\n    # show main menu\n    cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --item-help --menu \"Global Resolution\\nCurrent: $resolution\" 16 45 16)\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    case \"$choice\" in\n        U)\n            set_resolution_moonlight \"0\" \"0\" \"0\"\n            ;;\n        1)\n            set_resolution_moonlight \"1920\" \"1080\" \"60\"\n            ;;\n        2)\n            set_resolution_moonlight \"1920\" \"1080\" \"30\"\n            ;;\n        3)\n            set_resolution_moonlight \"1280\" \"720\" \"60\"\n            ;;\n        4)\n            set_resolution_moonlight \"1280\" \"720\" \"30\"\n            ;;\n        C)\n            cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter a custom resolution as WIDTH HEIGHT FPS (separated by spaces)\" 10 50)\n            choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n            if [[ $? -eq 0 ]]; then\n                IFS=\" \" read -r -a choice <<< \"$choice\"\n                set_resolution_moonlight \"${choice[0]}\" \"${choice[1]}\" \"${choice[2]}\"\n            fi\n            ;;\n    esac\n}\n\nfunction bitrate_gui_moonlight() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local bitrate\n\n    # get current bitrate\n    bitrate=$(get_bitrate_moonlight)\n    if [[ \"$bitrate\" -gt 0 ]]; then\n        default=\"C\"\n        [[ \"$bitrate\" == 20000 ]] && default=\"1\"\n        [[ \"$bitrate\" == 10000 ]] && default=\"2\"\n        [[ \"$bitrate\" == 5000 ]] && default=\"3\"\n        bitrate=\"$bitrate Kbps\"\n    else\n        default=\"U\"\n        bitrate=\"(using default)\"\n    fi\n\n    # create menu options\n    options=(\n        U \"Unset (use default)\" \"Do not force a stream bitrate setting\"\n        1 \"20000\"  \"Set stream bitrate to 20000 Kbps\"\n        2 \"10000\"  \"Set stream bitrate to 10000 Kbps\"\n        3 \"5000\"   \"Set stream bitrate to 5000 Kbps\"\n        C \"Custom\" \"Set a custom stream bitrate\"\n    )\n\n    # show main menu\n    cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --item-help --menu \"Stream Bitrate\\nCurrent: $bitrate\" 16 45 16)\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    case \"$choice\" in\n        U)\n            set_bitrate_moonlight \"0\"\n            ;;\n        1)\n            set_bitrate_moonlight \"20000\"\n            ;;\n        2)\n            set_bitrate_moonlight \"10000\"\n            ;;\n        3)\n            set_bitrate_moonlight \"5000\"\n            ;;\n        C)\n            cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter a custom stream bitrate in Kbps\" 10 50)\n            choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n            [[ $? -eq 0 ]] && set_bitrate_moonlight \"$choice\"\n            ;;\n    esac\n}\n\nfunction gui_moonlight() {\n    local options=()\n    local default\n    local cmd\n    local choice\n    local config\n\n    # read scriptmodule config\n    IFS=\";\" read -r -a config < <(get_scriptmodule_cfg_moonlight)\n\n    # start the menu gui\n    default=\"A\"\n    while true; do\n        # create menu options, if no address show \"autodiscover\"\n        options=(\n            A \"Set remote host address (${config[0]:-autodiscover})\"\n            P \"Pair to remote host\"\n            U \"Unpair from remote host\"\n            G \"Configure remote apps\"\n            R \"Configure global resolution\"\n            B \"Configure global stream bitrate\"\n            H \"Configure host compatibility\"\n            C \"Clear all pairing data\"\n        )\n\n        # show main menu\n        cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Choose an option\" 16 60 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n        case \"$choice\" in\n            A)\n                cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the address of the remote host (leave BLANK for autodiscovery of the remote host)\" 10 65)\n                choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                if [[ $? -eq 0 ]]; then\n                    config[0]=\"$choice\"\n                    set_scriptmodule_cfg_moonlight \"${config[@]}\"\n                fi\n                ;;\n            P)\n                pair_moonlight ${config[0]:+\"${config[0]}\"} </dev/tty >/dev/tty\n                read -p \"Press ENTER to continue... \"\n                ;;\n            U)\n                unpair_moonlight ${config[0]:+\"${config[0]}\"} </dev/tty >/dev/tty\n                read -p \"Press ENTER to continue... \"\n                ;;\n            G)\n                apps_gui_moonlight\n                ;;\n            R)\n                resolution_gui_moonlight\n                ;;\n            B)\n                bitrate_gui_moonlight\n                ;;\n            H)\n                host_gui_moonlight\n                ;;\n            C)\n                if dialog --defaultno --yesno \"Are you sure you want to CLEAR ALL pairing data?\" 8 40 2>&1 >/dev/tty; then\n                    if clear_pairing_moonlight; then\n                        printMsgs \"dialog\" \"All pairing data cleared.\"\n                    else\n                        printMsgs \"dialog\" \"Could not clear pairing data.\"\n                    fi\n                fi\n                ;;\n            *)\n                break\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/omxiv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"omxiv\"\nrp_module_desc=\"OpenMAX image viewer for the Raspberry Pi\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/cmitu/omxiv/master/LICENSE\"\nrp_module_repo=\"git https://github.com/retropie/omxiv.git master\"\nrp_module_section=\"depends\"\nrp_module_flags=\"!all rpi\"\n\nfunction depends_omxiv() {\n    getDepends libraspberrypi-dev libraspberrypi-doc libpng-dev libjpeg-dev\n}\n\nfunction sources_omxiv() {\n    gitPullOrClone\n}\n\nfunction build_omxiv() {\n    make clean\n    make ilclient\n    make\n    md_ret_require=\"omxiv.bin\"\n}\n\nfunction install_omxiv() {\n    make install INSTALL=\"$md_inst\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/pegasus-fe-dev.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pegasus-fe-dev\"\nrp_module_desc=\"Pegasus: A cross platform, customizable graphical frontend (lastest master)\"\nrp_module_help=\"Pegasus is a cross platform, customizable graphical frontend for launching emulators and managing your game collection.\\nThis package provides source installation on platforms not covered by the upstream project pre-built binaries (i.e. ARM 64bit, Ubuntu 22.04 or later, Debian 11 or later).\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/mmatyas/pegasus-frontend/master/LICENSE.md\"\nrp_module_section=\"exp\"\nrp_module_repo=\"git https://github.com/mmatyas/pegasus-frontend master\"\nrp_module_flags=\"!mali frontend\"\n\nfunction depends_pegasus-fe-dev() {\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        md_ret_errors+=(\"Pegasus (dev) requires Debian 11 (bullseye) or later. Please install the 'pegasus-fe' package instead.\")\n        return 1\n    fi\n\n    if [[ -n \"$__os_ubuntu_ver\" ]] && compareVersions \"$__os_ubuntu_ver\" lt 22.04; then\n        md_ret_errors+=(\"Pegasus (dev) requires Ubuntu 22.04 or later. Please install the 'pegasus-fe' package instead.\")\n        return 1\n    fi\n\n    local depends=(\n        fontconfig\n        gstreamer1.0-alsa\n        gstreamer1.0-libav\n        gstreamer1.0-plugins-good\n        libqt5multimedia5-plugins\n        libsdl2-dev\n        pkg-config\n        polkitd\n        qml-module-qtgraphicaleffects qml-module-qtmultimedia qml-module-qtqml\n        qml-module-qtqml-models2\n        qml-module-qtquick-controls qml-module-qtquick-controls2\n        qml-module-qtquick-layouts qml-module-qtquick-templates2\n        qml-module-qtquick-window2 qml-module-qtquick2\n        qml-module-qt-labs-qmlmodels qml-module-qtquick-shapes\n    )\n    # Qt build dependencies\n    depends+=(qtbase5-private-dev qtdeclarative5-dev qtmultimedia5-dev libqt5svg5-dev qttools5-dev)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_pegasus-fe-dev() {\n    gitPullOrClone\n    # on KMS, apply a patch to fix lanching games\n    isPlatform \"kms\" && applyPatch \"$md_build/etc/rpi4/kms_launch_fix.diff\"\n}\n\nfunction build_pegasus-fe-dev() {\n    rm -fr release && mkdir -p release\n    pushd release\n    qmake .. QMAKE_CXXFLAGS+=\"$__cxxflags\" QMAKE_LIBS_LIBDL=-ldl USE_SDL_GAMEPAD=1 USE_SDL_POWER=1 INSTALLDIR=\"$md_inst\"\n    make\n    md_ret_require=(\n        \"$md_build/release/src/app/pegasus-fe\"\n    )\n}\n\nfunction install_pegasus-fe-dev() {\n    make -C release install\n    _add_launcher_pegasus-fe\n}\n\nfunction remove_pegasus-fe-dev() {\n    remove_pegasus-fe\n}\n\nfunction configure_pegasus-fe-dev() {\n    configure_pegasus-fe\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/pegasus-fe.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"pegasus-fe\"\nrp_module_desc=\"Pegasus: A cross platform, customizable graphical frontend (latest pre-built release)\"\nrp_module_help=\"Pegasus is a cross platform, customizable graphical frontend for launching emulators and managing your game collection.\\nThis package installs the upstream pre-built binaries. Use this package on RaspiOS Buster or PC/x86 installations\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/mmatyas/pegasus-frontend/master/LICENSE.md\"\nrp_module_section=\"exp\"\nrp_module_flags=\"!mali frontend\"\n\nfunction depends_pegasus-fe() {\n    local depends=(\n        fontconfig\n        gstreamer1.0-alsa\n        gstreamer1.0-libav\n        gstreamer1.0-plugins-good\n        jq\n        libsdl2-dev\n        polkitd\n    )\n    # show an error on 64bit ARMs, since there are no pre-built packages for it\n    if isPlatform \"arm\" && hasFlag \"64bit\"; then\n        md_ret_errors+=(\"There are no pre-build binaries for 64bit ARM systems! Try installing Pegasus with the ${md_id}-dev package\")\n        return 1\n    fi\n    getDepends \"${depends[@]}\"\n}\n\nfunction install_bin_pegasus-fe() {\n    # get all asset urls for the latest continuous release\n    local all_assets\n    all_assets=\"$(download https://api.github.com/repos/mmatyas/pegasus-frontend/releases/tags/continuous -)\" || return\n    all_assets=\"$(echo \"${all_assets}\" | jq -r '.assets[] | .browser_download_url')\"\n\n    printMsgs \"console\" \"Available releases:\"\n    printMsgs \"console\" \"${all_assets}\"\n\n    # find out which platform's package we'll need\n    local platform\n    isPlatform \"x11\" && platform=\"x11\"\n    isPlatform \"rpi\" && platform=\"$__platform\"\n    if [[ -z \"${platform}\" ]]; then\n        md_ret_errors+=(\"Sorry, Pegasus has no pre-built binaries for this platform. Consider installing the ${md_id}-dev package or reporting this on the RetroPie forum!\")\n        return\n    fi\n\n    printMsgs \"console\" \"Package platform: ${platform}\"\n\n    # select the url for the platform\n    local asset_url\n    asset_url=\"$(echo \"${all_assets}\" | grep ${platform})\"\n\n    if [[ -z \"${asset_url}\" ]]; then\n        md_ret_errors+=(\"Looks like the latest Pegasus release is not yet available for this platform. This happens when the build is so fresh it's being uploaded right now, or when there's a technical problem on the download server. Either way, this is a temporary problem, so please try again in 1-2 minutes. If the problem persists, consider reporting it on the forum!\")\n        return\n    fi\n\n    # download and extract the package\n    printMsgs \"console\" \"Download URL: ${asset_url}\"\n    downloadAndExtract \"${asset_url}\" \"$md_inst\"\n\n    _add_launcher_pegasus-fe\n}\n\nfunction _add_launcher_pegasus-fe() {\n# create launcher script\n    cat > /usr/bin/pegasus-fe << _EOF_\n#!/bin/bash\n\nif [[ \\$(id -u) -eq 0 ]]; then\n    echo \"Pegasus should not be run as root. If you used 'sudo pegasus-fe' please run without sudo.\"\n    exit 1\nfi\n\n_EOF_\n\n# on KMS platforms, add some additional setup commands\nif isPlatform \"kms\"; then\n    cat >> /usr/bin/pegasus-fe << _EOF_\n# KMS setup\nexport QT_QPA_EGLFS_FORCE888=1  # improve gradients\nexport QT_QPA_EGLFS_KMS_ATOMIC=1  # use the atomic DRM API on Pi 4\nexport QT_QPA_PLATFORM=eglfs\nexport QT_QPA_QT_QPA_EGLFS_INTEGRATION=eglfs_kms\n\n# find the right DRI card\nfor i in \\$(find /sys/devices/platform -name \"card?\"); do\n   node=\\${i:0-1}\n   case \"\\$i\" in\n   *gpu*)  card=\\$node ;;\n  esac\ndone\n\necho Using DRI card at /dev/dri/card\\${card}\nfile=\"/tmp/pegasus_\\$\\$.eglfs.json\"\necho \"{ \\\"device\\\": \\\"/dev/dri/card\\${card}\\\" }\" > \"\\$file\"\nexport QT_QPA_EGLFS_KMS_CONFIG=\"\\$file\"\n_EOF_\nfi\n\n    cat >> /usr/bin/pegasus-fe << _EOF_\nclear\n\"$md_inst/pegasus-fe\" \"\\$@\"\n\nrm -f \"/tmp/pegasus_\\$\\$.eglfs.json\"\n_EOF_\n\n    chmod +x /usr/bin/pegasus-fe\n}\n\nfunction _update_themes_pegasus-fe() {\n    # add some themes to Pegasus\n    echo Installing themes\n    declare themes=(\n        \"mmatyas/pegasus-theme-9999999-in-1\"\n        \"mmatyas/pegasus-theme-es2-simple\"\n        \"mmatyas/pegasus-theme-flixnet\"\n        \"mmatyas/pegasus-theme-secretary\"\n    )\n    local theme\n    pushd \"$home/.config/pegasus-frontend/themes\" || return\n    for theme in ${themes[@]}; do\n        local path=${theme//\"mmatyas/pegasus-theme-\"/}\n        gitPullOrClone \"$path\" \"https://github.com/$theme\"\n    done\n    popd\n}\nfunction remove_pegasus-fe() {\n    rm -f /usr/bin/pegasus-fe\n}\n\nfunction configure_pegasus-fe() {\n    moveConfigDir \"$home/.config/pegasus-frontend\" \"$md_conf_root/all/pegasus-fe\"\n\n    # create external directories\n    mkUserDir \"$md_conf_root/all/pegasus-fe/scripts\"\n    mkUserDir \"$md_conf_root/all/pegasus-fe/themes\"\n\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    # remove the other Pegasus package if it's installed\n    if [[ \"$md_id\" == \"pegasus-fe-dev\" ]]; then\n        rmDirExists \"$rootdir/$md_type/pegasus-fe\"\n    else\n        rmDirExists \"$rootdir/$md_type/pegasus-fe-dev\"\n    fi\n    # update themes\n    _update_themes_pegasus-fe\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/powerblock.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"powerblock\"\nrp_module_desc=\"PowerBlock Driver\"\nrp_module_help=\"Please note that you need to manually enable or disable the PowerBlock Service in the Configuration section. IMPORTANT: If the service is enabled and the power switch functionality is enabled (which is the default setting) in the config file, you need to have a switch connected to the PowerBlock.\"\nrp_module_repo=\"git https://github.com/petrockblog/PowerBlock.git master\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean !all rpi\"\n\nfunction depends_powerblock() {\n    local depends=(cmake doxygen)\n    isPlatform \"videocore\" && depends+=(libraspberrypi-dev)\n\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_powerblock() {\n    if [[ -d \"$md_inst\" ]]; then\n        git -C \"$md_inst\" reset --hard  # ensure that no local changes exist\n    fi\n    gitPullOrClone \"$md_inst\"\n}\n\nfunction install_powerblock() {\n    cd \"$md_inst\"\n    bash install.sh\n}\n\nfunction remove_powerblock() {\n    cd \"$md_inst\"\n    bash uninstall.sh\n}\n\nfunction gui_powerblock() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local options=(\n        1 \"Enable PowerBlock driver\"\n        2 \"Disable PowerBlock driver\"\n\n    )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                install_powerblock\n                printMsgs \"dialog\" \"Enabled PowerBlock driver.\"\n                ;;\n            2)\n                remove_powerblock\n                printMsgs \"dialog\" \"Disabled PowerBlock driver.\"\n                ;;\n        esac\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/ps3controller.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"ps3controller\"\nrp_module_desc=\"PS3 controller driver and pair via sixad\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/sixad/master/COPYING\"\nrp_module_section=\"driver\"\n\nfunction depends_ps3controller() {\n    depends_bluetooth\n    local depends=(checkinstall libusb-dev libbluetooth-dev joystick)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_ps3controller() {\n    local branch=\"$1\"\n    [[ \"$branch\" == \"gasia-only\" ]] && branch=\"master\"\n\n    gitPullOrClone \"$md_build/sixad\" https://github.com/RetroPie/sixad.git $branch\n}\n\nfunction build_ps3controller() {\n    local branch=\"$1\"\n    local params=(\"DEVICE_SHORT_NAME=1\")\n    [[ \"$branch\" == \"gasia-only\" ]] && params+=(\"GASIA_GAMEPAD_HACKS=1\")\n\n    cd sixad\n    make clean\n    make \"${params[@]}\"\n    local bin\n    for bin in sixad-bin sixpair sixad-sixaxis sixad-remote sixad-raw sixad-3in1; do\n        md_ret_require+=(\"$md_build/sixad/bins/$bin\")\n    done\n}\n\nfunction install_ps3controller() {\n    local branch=\"$1\"\n    [[ -z \"$branch\" ]] && branch=\"ps3\"\n\n    cd sixad\n    checkinstall -y --fstrans=no\n\n    echo \"$branch\" >\"$md_inst/type.txt\"\n\n    # Disable timeouts\n    iniConfig \" = \" \"\" \"/etc/bluetooth/main.conf\"\n    iniSet \"DiscoverableTimeout\" \"0\"\n    iniSet \"PairableTimeout\" \"0\"\n}\n\nfunction remove_ps3controller() {\n    dpkg --purge sixad\n    [[ -f /usr/sbin/bluetoothd ]] && chmod 755 /usr/sbin/bluetoothd\n}\n\nfunction pair_ps3controller() {\n    local branch=\"$1\"\n    [[ -z \"$branch\" ]] && branch=\"ps3\"\n\n    if [[ ! -f \"$md_inst/type.txt\" || \"$(<\"$md_inst/type.txt\")\" != \"$branch\" ]]; then\n        local mode\n        for mode in sources build install clean; do\n            rp_callModule ps3controller $mode $branch\n        done\n        return\n    fi\n\n    printMsgs \"dialog\" \"Please connect your PS3 controller now or anytime to its USB connection, to setup Bluetooth connection. \\n\\nAfterwards disconnect your PS3 controller from its USB connection, and press the PS button to connect via Bluetooth.\"\n    # enable old behaviour. run \"sixad-helper sixpair\" \"now\" for users who do not read info text\n    sixad-helper sixpair\n}\n\nfunction gui_ps3controller() {\n    declare -A drivers\n    drivers[\"ps3\"]=\"official ps3\"\n    drivers[\"gasia\"]=\"clone support gasia\"\n    drivers[\"gasia-only\"]=\"gasia only\"\n    drivers[\"shanwan\"]=\"clone support shanwan\"\n\n    printMsgs \"dialog\" \"WARNING: The ps3controller driver partially disables the standard Bluetooth stack so that Dual Shock controllers can pair correctly. Although the Bluetooth stack is temporarily re-enabled inside Retropie's Bluetooth menu to allow compatibility with standard Bluetooth peripherals, any other software that relies on the full Bluetooth stack will not work correctly while the ps3controller driver is active.\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n    while true; do\n        local i=1\n        local options=()\n        local installed\n        local id\n        for id in ps3 gasia gasia-only shanwan; do\n            installed=\"\"\n            if [[ -f \"$md_inst/type.txt\" && \"$(<\"$md_inst/type.txt\")\" == \"$id\" ]]; then\n                options+=(\"$i\" \"Pair PS3 controller (${drivers[$id]})\")\n            else\n                options+=(\"$i\" \"Install PS3 driver (${drivers[$id]})\")\n            fi\n            ((i++))\n        done\n        options+=(\n            5 \"Remove PS3 controller configurations\"\n        )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rp_callModule \"$md_id\" pair\n                    ;;\n                2)\n                    rp_callModule \"$md_id\" pair gasia\n                    ;;\n                3)\n                    rp_callModule \"$md_id\" pair gasia-only\n                    ;;\n                4)\n                    rp_callModule \"$md_id\" pair shanwan\n                    ;;\n                5)\n                    rp_callModule \"$md_id\" remove\n                    break\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/raspbiantools.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"raspbiantools\"\nrp_module_desc=\"Raspbian related tools\"\nrp_module_section=\"config\"\nrp_module_flags=\"!all rpi\"\n\nfunction apt_upgrade_raspbiantools() {\n    # install an older kernel/firmware for stretch to resolve newer kernel issues or unhold if updating to a newer release\n    stretch_fix_raspbiantools\n\n    # on Buster, use the legacy Raspbian archive for package installation\n    buster_fix_apt_raspbiantools\n\n    # on Buster, always install the Bluez package from the RPI repos\n    buster_bluez_pin_raspbiantools\n\n    # remove our own SDL1 package for non-dispmanx/non-videocore platforms\n    if isPlatform \"rpi\" && ! isPlatform \"dispmanx\"; then\n        sdl1_replace_raspbiantools\n    fi\n\n    # on RaspiOS Trixie, disable the 'fluidsynth' user service starting automatically\n    if isPlatform \"rpi\" && [[ \"$__os_debian_ver\" -eq 13 ]]; then\n        fluidsynth_service_raspbiantools off\n    fi\n\n    aptUpdate\n    apt-get -y dist-upgrade --allow-downgrades\n}\n\nfunction lxde_raspbiantools() {\n    aptInstall --no-install-recommends xorg lxde\n    aptInstall raspberrypi-ui-mods rpi-chromium-mods gvfs\n    # On `buster`, disable PulseAudio since it messes up the audio settings\n    # remove the lxpanel plugin for PulseAudio volume, to prevent a crash due to missing PulseAudio\n    #  and install the volume lxpanel plugin that supports ALSA\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n       __toggle_pulseaudio_audiosettings \"off\"\n       aptRemove  lxplug-volumepulse\n       aptInstall lxplug-volume\n    fi\n\n    # Firefox is supported starting with Bookworm, install it along with Chromium\n    [[ \"$__os_debian_ver\" -ge 12 ]] && aptInstall --no-install-recommends firefox rpi-firefox-mods\n\n    setConfigRoot \"ports\"\n    addPort \"lxde\" \"lxde\" \"Desktop\" \"XINIT:startx\"\n    if (isPlatform \"rpi4\" || isPlatform \"rpi5\")  && [[ \"$__os_debian_ver\" -ge 12 ]]; then\n        addPort \"wayfire\" \"wayfire\" \"Desktop (Wayland)\" \"wayfire-pi\"\n    fi\n    enable_autostart\n}\n\nfunction package_cleanup_raspbiantools() {\n    # remove PulseAudio since this is slowing down the whole system significantly. Cups is also not needed\n    apt-get remove -y pulseaudio cups wolfram-engine sonic-pi\n    apt-get -y autoremove\n}\n\nfunction disable_blanker_raspbiantools() {\n    sed -i 's/BLANK_TIME=\\d*/BLANK_TIME=0/g' /etc/kbd/config\n    sed -i 's/POWERDOWN_TIME=\\d*/POWERDOWN_TIME=0/g' /etc/kbd/config\n}\n\nfunction stretch_fix_raspbiantools() {\n    # install an older kernel/firmware and hold it for stretch to resolve sony bt, composite\n    # and overscan issues, but also unhold for newer Raspbian versions to allow upgrading.\n    local ver=\"1.20190401-1\"\n    # make sure we are on a rpi and have the raspberrypi-kernel package\n    if isPlatform \"rpi\" && hasPackage raspberrypi-kernel; then\n        if [[ \"$__os_debian_ver\" -eq 9 ]]; then\n            # for Raspbian 9 (stretch) we want to install / hold the older kernel\n            install_firmware_raspbiantools \"$ver\" hold\n        elif hasPackage raspberrypi-kernel \"$ver\" eq; then\n            # if we are not running Raspbian 9 (stretch), but are running the old kernel\n            # we want to unhold it to allow kernel updates again\n            install_firmware_raspbiantools \"$ver\" unhold\n        fi\n    fi\n}\n\nfunction buster_fix_apt_raspbiantools() {\n    if isPlatform \"rpi\" && [[ \"$__os_debian_ver\" -eq 10 ]]; then\n        sed -i 's/raspbian\\.raspberrypi\\.org/legacy.raspbian.org/' /etc/apt/sources.list\n    fi\n}\n\nfunction buster_bluez_pin_raspbiantools() {\n    # pin the 'bluez' package to the RPI repos to prevent any Debian updates overwriting it\n    # use Priority 1001 to force the the installation even when the Debian package is installed\n    local pin_file=\"/etc/apt/preferences.d/01-bluez-pin\"\n    if isPlatform \"rpi\" && [[ \"$__os_debian_ver\" -eq 10 && ! -f \"$pin_file\" ]] ; then\n        cat << PIN_EOF > \"$pin_file\"\nPackage: bluez\nPin: origin archive.raspberrypi.org\nPin-Priority: 1001\nPIN_EOF\n    fi\n}\n\nfunction sdl1_replace_raspbiantools() {\n    local inst_ver=\"$(dpkg-query --show --showformat '${Version}' libsdl1.2-dev)\"\n    local sdl1_ver=\"$(get_pkg_ver_sdl1)\"\n    local repo_ver=\"$(apt-cache madison libsdl1.2-dev | head -n 1 | cut -d'|' -f 2 | tr -d '[:blank:]')\"\n    # check if the version installed is our own\n    [[ -z \"$inst_ver\" || ! \"$inst_ver\" == \"$sdl1_ver\" || -z \"$repo_ver\" ]] && return\n    printMsgs \"console\" \"Replacing RetroPie SDL1 version since it's not needed anymore\"\n    apt-get -y --allow-downgrades --allow-change-held-packages install libsdl1.2debian=$repo_ver libsdl1.2-dev=$repo_ver\n\n}\n\nfunction install_firmware_raspbiantools() {\n    local ver=\"$1\"\n    local state=\"$2\"\n    [[ -z \"$ver\" ]] && return 1\n\n    local url=\"http://archive.raspberrypi.org/debian/pool/main/r/raspberrypi-firmware\"\n\n    mkdir -p \"$md_build\"\n    pushd \"$md_build\" >/dev/null\n\n    local pkg\n    local pkgs=(raspberrypi-bootloader libraspberrypi0 libraspberrypi-doc libraspberrypi-dev libraspberrypi-bin raspberrypi-kernel-headers raspberrypi-kernel)\n    local deb\n\n    # download all packages then install later to reduce issues if interrupted or a networking issue\n    for pkg in \"${pkgs[@]}\"; do\n        if hasPackage \"$pkg\" \"$ver\" ne; then\n            deb=\"${pkg}_${ver}_armhf.deb\"\n            if ! download \"$url/$deb\"; then\n               md_ret_errors+=(\"Failed to download $deb\")\n               return 1\n            fi\n        fi\n    done\n\n    # install packages if needed\n    for pkg in \"${pkgs[@]}\"; do\n        deb=\"${pkg}_${ver}_armhf.deb\"\n        if hasPackage \"$pkg\" \"$ver\" ne && [[ -f \"$deb\" ]]; then\n            dpkg -i \"$deb\"\n            rm \"$deb\"\n        fi\n        # set package state\n        [[ -n \"$state\" ]] && apt-mark \"$state\" \"$pkg\"\n    done\n\n    popd >/dev/null\n    rm -rf \"$md_build\"\n\n    return 0\n}\n\nfunction enable_modules_raspbiantools() {\n    sed -i '/snd_bcm2835/d' /etc/modules\n\n    local modules=(uinput)\n\n    local module\n    for module in \"${modules[@]}\"; do\n        modprobe $module\n        if ! grep -q \"$module\" /etc/modules; then\n            addLineToFile \"$module\" \"/etc/modules\"\n        else\n            echo \"$module module already contained in /etc/modules\"\n        fi\n    done\n}\n\nfunction enable_zram_raspbiantools() {\n    if [[ \"$__os_id\" == \"Raspbian\" ]] || [[ \"$__os_id\" == \"Debian\" ]]; then\n        aptInstall zram-tools\n        # Use 50% of the current memory for ZRAM\n        local percent=\"50\"\n        iniConfig \"=\" \"\" \"/etc/default/zramswap\"\n        # Raspbian Buster uses keyword PERCENTAGE\n        iniSet \"PERCENTAGE\" \"$percent\"\n        # Debian Bullseye/Bookworm use keyword PERCENT\n        iniSet \"PERCENT\" \"$percent\"\n        # Use zstd compression algorithm if kernel supports it\n        [[ -f /sys/class/block/zram0/comp_algorithm ]] && [[ \"$(cat /sys/class/block/zram0/comp_algorithm)\" == *zstd* ]] && iniSet \"ALGO\" \"zstd\"\n        service zramswap stop\n        service zramswap start\n    elif [[ \"$__os_id\" == \"Ubuntu\" ]]; then\n        aptInstall zram-config\n        # Ubuntu has a automatic zram configuration\n    fi\n}\n\nfunction disable_zram_raspbiantools() {\n    if [[ \"$__os_id\" == \"Raspbian\" ]] || [[ \"$__os_id\" == \"Debian\" ]]; then\n        aptRemove zram-tools\n    elif [[ \"$__os_id\" == \"Ubuntu\" ]]; then\n        aptRemove zram-config\n    fi\n}\n\nfunction fluidsynth_service_raspbiantools() {\n    # use the 1st parameter as service state\n    local state=${1:-on}\n\n    if [[ \"$state\" == \"on\" ]]; then\n        rm \"${home}/.config/systemd/user/fluidsynth.service\"\n    fi\n\n    if [[ \"$state\" == \"off\" ]]; then\n       mkdir -p \"${home}/.config/systemd/user\"\n       ln -sf /dev/null \"${home}/.config/systemd/user/fluidsynth.service\"\n       chown -R \"$__user\":\"$__group\" \"${home}/.config/systemd/user\"\n    fi\n}\nfunction gui_raspbiantools() {\n    while true; do\n        local zram_status=\"Enable\"\n        [[ $(cat /proc/swaps) == *zram* ]] && zram_status=\"Disable\"\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n        local options=(\n            1 \"Upgrade Raspbian packages\"\n            2 \"Install Pixel desktop environment\"\n            3 \"Remove some unneeded packages (pulseaudio / cups / wolfram)\"\n            4 \"Disable screen blanker\"\n            5 \"Enable needed kernel module uinput\"\n        )\n        # exclude ZRAM config for Armbian, it is handled by `armbian-config`\n        ! isPlatform \"armbian\" && options+=(6 \"$zram_status compressed memory (ZRAM)\")\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rp_callModule \"$md_id\" apt_upgrade\n                    ;;\n                2)\n                    dialog --defaultno --yesno \"Are you sure you want to install the Pixel desktop?\" 22 76 2>&1 >/dev/tty || continue\n                    rp_callModule \"$md_id\" lxde\n                    printMsgs \"dialog\" \"Pixel desktop/LXDE is installed.\"\n                    ;;\n                3)\n                    rp_callModule \"$md_id\" package_cleanup\n                    ;;\n                4)\n                    rp_callModule \"$md_id\" disable_blanker\n                    ;;\n                5)\n                    rp_callModule \"$md_id\" enable_modules\n                    ;;\n                6)\n                    [[ \"$zram_status\" == \"Enable\" ]] && rp_callModule \"$md_id\" enable_zram || rp_callModule \"$md_id\" disable_zram\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/resetromdirs.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"resetromdirs\"\nrp_module_desc=\"Reset ownership/permissions of RetroPie/roms directory\"\nrp_module_section=\"config\"\n\nfunction gui_resetromdirs() {\n    printHeading \"Resetting $romdir ownershop/permissions\"\n    mkUserDir \"$romdir\"\n    mkUserDir \"$biosdir\"\n    chown -R \"$__user\":\"$__group\" \"$romdir\"\n    chown -R \"$__user\":\"$__group\" \"$biosdir\"\n    chmod -R ug+rwX \"$romdir\"\n    chmod -R ug+rwX \"$biosdir\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/retronetplay.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"retronetplay\"\nrp_module_desc=\"RetroNetplay\"\nrp_module_section=\"config\"\n\nfunction rps_retronet_saveconfig() {\n    local conf=\"$configdir/all/retronetplay.cfg\"\n    cat >\"$conf\"  <<_EOF_\n__netplaymode=\"$__netplaymode\"\n__netplayport=\"$__netplayport\"\n__netplayhostip=\"$__netplayhostip\"\n__netplayhostip_cfile=\"$__netplayhostip_cfile\"\n__netplaynickname=\"$__netplaynickname\"\n_EOF_\n    chown \"$__user\":\"$__group\" \"$conf\"\n    printMsgs \"dialog\" \"Configuration has been saved to $conf\"\n}\n\nfunction rps_retronet_loadconfig() {\n    if [[ -f \"$configdir/all/retronetplay.cfg\" ]]; then\n        source \"$configdir/all/retronetplay.cfg\"\n    else\n        __netplayenable=\"D\"\n        __netplaymode=\"H\"\n        __netplayport=\"55435\"\n        __netplayhostip=\"192.168.0.1\"\n        __netplayhostip_cfile=\"\"\n        __netplaynickname=\"RetroPie\"\n    fi\n}\n\nfunction rps_retronet_mode() {\n    cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please set the netplay mode.\" 22 76 16)\n    options=(1 \"Set as HOST\"\n             2 \"Set as CLIENT\" )\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n             1) __netplaymode=\"H\"\n                __netplayhostip_cfile=\"\"\n                ;;\n             2) __netplaymode=\"C\"\n                __netplayhostip_cfile=\"$__netplayhostip\"\n                ;;\n        esac\n    fi\n}\n\nfunction rps_retronet_port() {\n    choice=$(inputBox \"Port for netplay\" \"$__netplayport\" 4)\n    if [[ -n \"$choice\" ]]; then\n        __netplayport=\"$choice\"\n    fi\n}\n\nfunction rps_retronet_hostip() {\n    choice=$(inputBox \"IP Address of the host\" \"$__netplayhostip\" 8)\n    if [[ -n \"$choice\" ]]; then\n        __netplayhostip=\"$choice\"\n        if [[ $__netplaymode == \"H\" ]]; then\n            __netplayhostip_cfile=\"\"\n        else\n            __netplayhostip_cfile=\"$__netplayhostip\"\n        fi\n    fi\n}\n\nfunction rps_retronet_nickname() {\n    choice=$(inputBox \"Nickname you wish to use\" \"$__netplaynickname\" 4)\n    if [[ -n \"$choice\" ]]; then\n        __netplaynickname=\"$choice\"\n    fi\n}\n\nfunction gui_retronetplay() {\n    rps_retronet_loadconfig\n\n    local ip_int=$(ifconfig | grep -Eo 'inet (addr:)?([0-9]*\\.){3}[0-9]*' | grep -Eo '([0-9]*\\.){3}[0-9]*' | grep -v '127.0.0.1')\n    local ip_ext=$(curl -4 http://ipecho.net/plain)\n\n    while true; do\n        cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Exit\" --menu \"Configure RetroArch Netplay.\\nInternal IP: $ip_int External IP: $ip_ext\" 22 76 16)\n        options=(\n            1 \"Set mode, (H)ost or (C)lient. Currently: $__netplaymode\"\n            2 \"Set port. Currently: $__netplayport\"\n            3 \"Set host IP address (for client mode). Currently: $__netplayhostip\"\n            4 \"Set netplay nickname. Currently: '$__netplaynickname'\"\n            5 \"Save configuration\"\n        )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rps_retronet_mode\n                    ;;\n                2)\n                    rps_retronet_port\n                    ;;\n                3)\n                    rps_retronet_hostip\n                    ;;\n                4)\n                    rps_retronet_nickname\n                    ;;\n                5)\n                    rps_retronet_saveconfig\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/retropiemenu.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"retropiemenu\"\nrp_module_desc=\"RetroPie configuration menu for EmulationStation\"\nrp_module_section=\"core\"\nrp_module_flags=\"nonet\"\n\nfunction _update_hook_retropiemenu() {\n    # to show as installed when upgrading to retropie-setup 4.x\n    if ! rp_isInstalled \"$md_id\" && [[ -f \"$home/.emulationstation/gamelists/retropie/gamelist.xml\" ]]; then\n        mkdir -p \"$md_inst\"\n        # to stop older scripts removing when launching from retropie menu in ES due to not using exec or exiting after running retropie-setup from this module\n        touch \"$md_inst/.retropie\"\n    fi\n}\n\nfunction depends_retropiemenu() {\n    getDepends mc p7zip\n}\n\nfunction install_bin_retropiemenu() {\n    return\n}\n\nfunction configure_retropiemenu()\n{\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local rpdir=\"$home/RetroPie/retropiemenu\"\n    mkdir -p \"$rpdir\"\n    cp -Rv \"$md_data/icons\" \"$rpdir/\"\n    chown -R \"$__user\":\"$__group\" \"$rpdir\"\n\n    isPlatform \"rpi\" && rm -f \"$rpdir/dispmanx.rp\"\n\n    # add the gameslist / icons\n    local files=(\n        'audiosettings'\n        'bluetooth'\n        'configedit'\n        'esthemes'\n        'filemanager'\n        'raspiconfig'\n        'retroarch'\n        'retronetplay'\n        'rpsetup'\n        'runcommand'\n        'showip'\n        'splashscreen'\n        'wifi'\n    )\n\n    local names=(\n        'Audio'\n        'Bluetooth'\n        'Configuration Editor'\n        'ES Themes'\n        'File Manager'\n        'Raspi-Config'\n        'Retroarch'\n        'RetroArch Net Play'\n        'RetroPie Setup'\n        'Run Command Configuration'\n        'Show IP'\n        'Splash Screens'\n        'WiFi'\n    )\n\n    local descs=(\n        'Configure audio settings. Choose default of auto, 3.5mm jack, or HDMI. Mixer controls, and apply default settings.'\n        'Register and connect to Bluetooth devices. Unregister and remove devices, and display registered and connected devices.'\n        'Change common RetroArch options, and manually edit RetroArch configs, global configs, and non-RetroArch configs.'\n        'Install, uninstall, or update EmulationStation themes. Most themes can be previewed at https://retropie.org.uk/docs/Themes/.'\n        'Basic ASCII file manager for Linux allowing you to browse, copy, delete, and move files.'\n        'Change user password, boot options, internationalization, camera, add your Pi to Rastrack, overclock, overscan, memory split, SSH and more.'\n        'Launches the RetroArch GUI so you can change RetroArch options. Note: Changes will not be saved unless you have enabled the \"Save Configuration On Exit\" option.'\n        'Set up RetroArch Netplay options, choose host or client, port, host IP, delay frames, and your nickname.'\n        'Install RetroPie from binary or source, install experimental packages, additional drivers, edit Samba shares, custom scraper, as well as other RetroPie-related configurations.'\n        'Change what appears on the runcommand screen. Enable or disable the menu, enable or disable box art, and change CPU configuration.'\n        'Displays your current IP address, as well as other information provided by the command \"ip addr show.\"'\n        'Enable or disable the splashscreen on RetroPie boot. Choose a splashscreen, download new splashscreens, and return splashscreen to default.'\n        'Connect to or disconnect from a WiFi network and configure WiFi settings.'\n    )\n\n    # 'legacy' joy2key uses direct tty I/O and needs the extra redirection arguments\n    iniConfig \" = \" '\"' \"$configdir/all/runcommand.cfg\"\n    iniGet \"legacy_joy2key\"\n    local tty_args\n    [[ \"$ini_value\" == \"1\" ]] && tty_args=\" </dev/tty >/dev/tty\"\n    setESSystem \"RetroPie\" \"retropie\" \"$rpdir\" \".rp .sh\" \"sudo $scriptdir/retropie_packages.sh retropiemenu launch %ROM% $tty_args\" \"\" \"retropie\"\n\n    local file\n    local name\n    local desc\n    local image\n    local i\n    for i in \"${!files[@]}\"; do\n        case \"${files[i]}\" in\n            audiosettings|raspiconfig|splashscreen)\n                ! isPlatform \"rpi\" && continue\n                ;;\n            wifi)\n                [[ \"$__os_id\" != \"Raspbian\" ]] && continue\n        esac\n\n        file=\"${files[i]}\"\n        name=\"${names[i]}\"\n        desc=\"${descs[i]}\"\n        image=\"$home/RetroPie/retropiemenu/icons/${files[i]}.png\"\n\n        touch \"$rpdir/$file.rp\"\n\n        local function\n        for function in $(compgen -A function _add_rom_); do\n            \"$function\" \"retropie\" \"RetroPie\" \"$file.rp\" \"$name\" \"$desc\" \"$image\"\n        done\n    done\n}\n\nfunction remove_retropiemenu() {\n    rm -rf \"$home/RetroPie/retropiemenu\"\n    rm -rf \"$home/.emulationstation/gamelists/retropie\"\n    delSystem retropie\n}\n\nfunction launch_retropiemenu() {\n    clear\n    local command=\"$1\"\n    local basename=\"${command##*/}\"\n    local no_ext=\"${basename%.rp}\"\n    joy2keyStart\n    case \"$basename\" in\n        retroarch.rp)\n            joy2keyStop\n            cp \"$configdir/all/retroarch.cfg\" \"$configdir/all/retroarch.cfg.bak\"\n            chown \"$__user\":\"$__group\" \"$configdir/all/retroarch.cfg.bak\"\n            su \"$__user\" -c \"XDG_RUNTIME_DIR=/run/user/$SUDO_UID \\\"$emudir/retroarch/bin/retroarch\\\" --menu --config \\\"$configdir/all/retroarch.cfg\\\"\"\n            iniConfig \" = \" '\"' \"$configdir/all/retroarch.cfg\"\n            iniSet \"config_save_on_exit\" \"false\"\n            ;;\n        rpsetup.rp)\n            rp_callModule setup gui\n            ;;\n        raspiconfig.rp)\n            raspi-config\n            ;;\n        filemanager.rp)\n            mc\n            ;;\n        showip.rp)\n            local ip=\"$(getIPAddress)\"\n            printMsgs \"dialog\" \"Your IP is: ${ip:-(unknown)}\\n\\nOutput of 'ip addr show':\\n\\n$(ip addr show)\"\n            ;;\n        *.rp)\n            rp_callModule $no_ext depends\n            if fnExists gui_$no_ext; then\n                rp_callModule $no_ext gui\n            else\n                rp_callModule $no_ext configure\n            fi\n            ;;\n        *.sh)\n            cd \"$home/RetroPie/retropiemenu\"\n            sudo -u \"$__user\" bash \"$command\"\n            ;;\n    esac\n    joy2keyStop\n    clear\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/runcommand/runcommand.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n# Editor's note: You may notice \"\\c \\%\" escape sequences, these are needed\n# to avoid the initial % char to be swallowed by doxygen.\n\n## @file supplementary/runcommand/runcommand.sh\n## @brief runcommand launching script\n## @copyright GPLv3\n## @details\n## @par Usage\n##\n## `runcommand.sh VIDEO_MODE COMMAND SAVE_NAME`\n##\n## or\n##\n## `runcommand.sh VIDEO_MODE _SYS_/_PORT_ SYSTEM ROM`\n##\n## Video mode switching is supported on X11, KMS and Raspberry Pi (legacy graphics) systems\n##\n## Automatic video mode selection (all):\n##\n## * VIDEO_MODE = 0: use the current video mode\n##\n## Automatic video mode (Raspberry Pi legacy graphics):\n##\n## * VIDEO_MODE = 1: set video mode to 640x480 (4:3) or 720x480 (16:9) @60hz\n## * VIDEO_MODE = 4: set video mode to 1024x768 (4:3) or 1280x720 (16:9) @60hz\n##\n## Manual video mode selection (Raspberry Pi legacy graphics):\n##\n## * VIDEO_MODE = \"CEA-#\": set video mode to CEA mode #\n## * VIDEO_MODE = \"DMT-#\": set video mode to DMT mode #\n## * VIDEO_MODE = \"PAL/NTSC-RATIO\": set mode to SD output with RATIO of 4:3 / 16:10 or 16:9\n##\n## Manual video mode selection (KMS):\n##\n## * VIDEO_MODE = \"CRTCID-MODEID\": set video mode to CRTC connector id and mode id\n##\n## Manual video mode selection (X11):\n##\n## * VIDEO_MODE = \"OUTPUT:MODEID\": set video mode to connected output name and mode index\n##\n## @note\n## Video mode switching only happens if the monitor reports the modes as available\n## (via tvservice) and the requested mode differs from the currently active mode\n##\n## Additionally it is possible to pass in the current screen resolution\n## (selectable in the runcommand menu) to the emulator to be launched. The\n## respective variables are \\c \\%XRES% and \\c \\%YRES% which will be replaced\n## with the specific values as the placeholders \\c \\%ROM% and \\c \\%BASENAME%\n## (see below). For example it is possible to set \\c\n## --displaysize=\\%XRESx\\%YRES% in emulators.cfg` if an emulator has a command\n## line switch to set the resolution.\n##\n## If `_SYS_` or `_PORT_` is provided as the second parameter for the\n## `runcommand.sh` script, the commandline will be extracted from\n## `/opt/retropie/configs/SYSTEM/emulators.cfg` with \\c \\%ROM%, \\c \\%BASENAME%\n## being replaced with the `ROM` parameter. This is the default mode used when\n## launching in RetroPie so the user can switch emulator used as well as other\n## options from the runcommand GUI.\n##\n## If `SAVE_NAME` is included, that is used for loading and saving of video output\n## modes as well as rendering backend settings for the current `COMMAND`. If omitted,\n## the binary name is used as a key for the loading and saving. The savename is\n## also displayed in the video output menu (detailed below), so for our purposes\n## we send the emulator module id, which is somewhat descriptive yet short.\n##\n## On launch this script waits for two seconds for a key or joystick press. If\n## pressed the GUI is shown, where a user can set video modes, default emulators\n## and other options (depending what is being launched).\n\nROOTDIR=\"/opt/retropie\"\nCONFIGDIR=\"$ROOTDIR/configs\"\nLOG=\"/dev/shm/runcommand.log\"\n\nRUNCOMMAND_CONF=\"$CONFIGDIR/all/runcommand.cfg\"\nVIDEO_CONF=\"$CONFIGDIR/all/videomodes.cfg\"\nEMU_CONF=\"$CONFIGDIR/all/emulators.cfg\"\nBACKENDS_CONF=\"$CONFIGDIR/all/backends.cfg\"\nRETRONETPLAY_CONF=\"$CONFIGDIR/all/retronetplay.cfg\"\nJOY2KEY=\"$ROOTDIR/admin/joy2key/joy2key\"\nSDL2_MAPPINGS=\"$CONFIGDIR/all/sdl2_gamecontrollerdb.txt\"\n\n# modesetting tools\nTVSERVICE=\"/opt/vc/bin/tvservice\"\nKMSTOOL=\"$ROOTDIR/supplementary/kmsxx/kmsprint-rp\"\nXRANDR=\"xrandr\"\n\nsource \"$ROOTDIR/lib/inifuncs.sh\"\n\n# disable the `patsub_replacement` shell option, it breaks the string substitution when replacement contains '&'\nif shopt -s patsub_replacement 2>/dev/null; then\n    shopt -u patsub_replacement\nfi\n\nfunction get_config() {\n    declare -Ag MODE_MAP\n\n    MODE_MAP[1-CEA-4:3]=\"CEA-1\"\n    MODE_MAP[1-DMT-4:3]=\"DMT-4\"\n    MODE_MAP[1-CEA-16:9]=\"CEA-1\"\n\n    MODE_MAP[4-CEA-4:3]=\"DMT-16\"\n    MODE_MAP[4-DMT-4:3]=\"DMT-16\"\n    MODE_MAP[4-CEA-16:9]=\"CEA-4\"\n\n    if [[ -f \"$RUNCOMMAND_CONF\" ]]; then\n        iniConfig \" = \" '\"' \"$RUNCOMMAND_CONF\"\n        iniGet \"governor\"\n        GOVERNOR=\"$ini_value\"\n        iniGet \"use_art\"\n        USE_ART=\"$ini_value\"\n        iniGet \"disable_joystick\"\n        DISABLE_JOYSTICK=\"$ini_value\"\n        iniGet \"disable_menu\"\n        DISABLE_MENU=\"$ini_value\"\n        iniGet \"image_delay\"\n        IMAGE_DELAY=\"$ini_value\"\n        [[ -z \"$IMAGE_DELAY\" ]] && IMAGE_DELAY=2\n        iniGet \"legacy_joy2key\"\n        LEGACY_JOY2KEY=\"$ini_value\"\n        [[ -z \"$LEGACY_JOY2KEY\" ]] && LEGACY_JOY2KEY=0\n    fi\n\n    if [[ -n \"$DISPLAY\" ]] && $XRANDR &>/dev/null; then\n        HAS_MODESET=\"x11\"\n    # copy kms tool output to global variable to avoid multiple invocations\n    elif [[ -c /dev/dri/card0 ]] && KMS_BUFFER=\"$($KMSTOOL 2>/dev/null)\"; then\n        HAS_MODESET=\"kms\"\n    elif [[ -f \"$TVSERVICE\" ]]; then\n        HAS_MODESET=\"tvs\"\n    fi\n}\n\nfunction start_joy2key() {\n    # check if joystick support is enabled and joy2key is available\n    [[ \"$DISABLE_JOYSTICK\" -eq 1 || ! -f \"$JOY2KEY\" ]] && return\n\n    \"$JOY2KEY\" start 2>/dev/null && return 0\n}\n\nfunction stop_joy2key() {\n    # if joy2key is installed, stop it\n    [[ -f \"$JOY2KEY\" ]] && \"$JOY2KEY\" stop\n}\n\nfunction get_params() {\n    MODE_REQ=\"$1\"\n    COMMAND=\"$2\"\n\n    [[ -z \"$MODE_REQ\" || -z \"$COMMAND\" ]] && return 1\n\n    CONSOLE_OUT=0\n    # if the COMMAND is _SYS_, or _PORT_ arg 3 should be system name, and arg 4 rom/game, and we look up the configured system for that combination\n    if [[ \"$COMMAND\" == \"_SYS_\" || \"$COMMAND\" == \"_PORT_\" ]]; then\n        # if the rom is actually a special +Start System.sh script, we should launch the script directly.\n        if [[ \"$4\" =~ \\/\\+Start\\ (.+)\\.sh$ ]]; then\n            # extract emulator from the name (and lowercase it)\n            EMULATOR=${BASH_REMATCH[1],,}\n            IS_SYS=0\n            COMMAND=\"bash \\\"$4\\\"\"\n            SYSTEM=\"$3\"\n            [[ -z \"$SYSTEM\" ]] && return 1\n        else\n            IS_SYS=1\n            SYSTEM=\"$3\"\n            ROM=\"$4\"\n            ROM_BN_EXT=\"${ROM##*/}\"\n            ROM_BN=\"${ROM_BN_EXT%.*}\"\n            if [[ \"$COMMAND\" == \"_PORT_\" ]]; then\n                CONF_ROOT=\"$CONFIGDIR/ports/$SYSTEM\"\n                EMU_SYS_CONF=\"$CONF_ROOT/emulators.cfg\"\n                IS_PORT=1\n            else\n                CONF_ROOT=\"$CONFIGDIR/$SYSTEM\"\n                EMU_SYS_CONF=\"$CONF_ROOT/emulators.cfg\"\n                IS_PORT=0\n            fi\n            SYS_SAVE_ROM_OLD=\"a$(echo \"$SYSTEM$ROM\" | md5sum | cut -d\" \" -f1)\"\n            SYS_SAVE_ROM=\"$(clean_name \"${SYSTEM}_${ROM_BN}\")\"\n            [[ -z \"$SYSTEM\" ]] && return 1\n            get_sys_command\n        fi\n    else\n        IS_SYS=0\n        CONSOLE_OUT=1\n        EMULATOR=\"$3\"\n        # if we have an emulator name (such as module_id) we use that for storing/loading parameters for video mode / backend\n        # if the parameter is empty we use the name of the binary (to avoid breakage with out of date emulationstation configs)\n        [[ -z \"$EMULATOR\" ]] && EMULATOR=\"${COMMAND/% */}\"\n    fi\n\n    NETPLAY=0\n    return 0\n}\n\nfunction clean_name() {\n    local name=\"$1\"\n    name=\"${name//\\//_}\"\n    name=\"${name//[^a-zA-Z0-9_\\-]/}\"\n    echo \"$name\"\n}\n\nfunction set_save_vars() {\n    # convert emulator name / binary to a names usable as variables in our config files\n    SAVE_EMU=\"$(clean_name \"$EMULATOR\")\"\n    SAVE_ROM_OLD=r$(echo \"$COMMAND\" | md5sum | cut -d\" \" -f1)\n    if [[ \"$IS_SYS\" -eq 1 ]]; then\n        SAVE_ROM=\"${SAVE_EMU}_$(clean_name \"$ROM_BN\")\"\n    else\n        SAVE_ROM=\"$SAVE_EMU\"\n    fi\n}\n\nfunction get_all_tvs_modes() {\n    declare -Ag MODE\n    local group\n    for group in CEA DMT; do\n        while read -r line; do\n            local id=\"$(echo \"$line\" | grep -oE \"mode [0-9]*\" | cut -d\" \" -f2)\"\n            local info=\"$(echo \"$line\" | cut -d\":\" -f2-)\"\n            info=${info/ /}\n            if [[ -n \"$id\" ]]; then\n                MODE_ID+=($group-$id)\n                MODE[$group-$id]=\"$info\"\n            fi\n        done < <($TVSERVICE -m $group)\n    done\n    local aspect\n    for group in \"NTSC\" \"PAL\"; do\n        for aspect in \"4:3\" \"16:10\" \"16:9\"; do\n            MODE_ID+=($group-$aspect)\n            MODE[$group-$aspect]=\"SDTV - $group-$aspect\"\n        done\n    done\n}\n\nfunction get_all_kms_modes() {\n    declare -Ag MODE\n    default_mode=\"$(echo \"$KMS_BUFFER\" | grep -Em1 \"^Mode: [0-9]+ crtc\")\"\n    crtc=\"$(echo \"$default_mode\" | cut -d' ' -f  4)\"\n    crtc_encoder=\"$(echo \"$KMS_BUFFER\" | grep \"Encoder map:\" | awk -v crtc=\"$crtc\" '$5 == crtc { print $3 }')\"\n\n    # add default mode as fallback in case real mode cannot be mapped\n    MODE[def-def]=\"$(echo \"$default_mode\" | cut -d' ' -f5-)\"\n\n    # parse only the video modes connected to the current active crtc\n    while read -r mode_str mode_id con encoder_id info; do\n           # we only need 2nd column (mode index) and the 5+ columns (resolution info)\n           # populate resolution info into arrays (using mapped crtc encoder value)\n           MODE_ID+=($crtc-$mode_id)\n           MODE[$crtc-$mode_id]=\"$info\"\n\n           # if string matches default mode, add a special mapped entry\n           [[ \"$default_mode\" =~ \"$info\" ]] && MODE[map-map]=\"$crtc $mode_id\"\n    done < <(echo \"$KMS_BUFFER\" | grep -E \"^Mode: [0-9]+ connector $crtc_encoder\")\n}\n\nfunction get_all_x11_modes()\n{\n    declare -Ag MODE\n    local id\n    local line\n    while read -r id; do\n        # populate CONNECTOR:0xID into an array\n        MODE_ID+=($id) # output:id as in (hdmi:0x44)\n\n        read -r line\n        # array is x/y resolution @ vertical refresh rate ( details )\n        MODE[$id]=\"$line\"\n    done < <( $XRANDR --verbose | awk '\n        # defines the type of line\n        # true is the \"header\" (output and id)\n        # false is the \"description\" (Mode: and everything that begins with a space)\n        { type = /^[^ \\t]+/ }\n\n        # Exit after the first output\n        type && output {exit} # New header and output set means new output\n\n        # many outputs can be connected, but only the ones with the id are in use.\n        # output must be connected and have an (id)\n        type && / connected/ && /\\(0x[0-9a-f]+\\)/ {\n            output=$1; next\n        }\n\n        # parse mode and lines\n        # If we are in a \"description\", and output is set (output being what we want)\n        # And if $2 is an id, we are in a video mode description line\n        !type && output && $2 ~ /^\\(0x[0-9a-f]+\\)$/ {\n            # Print CRTC identifier (CONNECTOR:0xID)\n            print output \":\" substr($2,2,length($2)-2) # id\n\n            # get rid of what we printed\n            $1=\"\";$2=\"\"\n            sub(/^[ \\t]+/,\"\") # trim spaces\n\n            # save rest of the line\n            info=$0\n\n            # Save width from the 2nd line of the video mode\n            getline; width=$3\n\n            # Save height & vrefresh from the 3rd line of video mode\n            getline; height=$3; vrefresh=$NF\n\n            # Print video mode details\n            print width \"x\" height \" @ \" vrefresh \" (\" info \")\"\n        }\n    ')\n}\n\nfunction get_tvs_mode_info() {\n    local status=\"$($TVSERVICE -s)\"\n    local temp\n    local mode_info=()\n\n    # get mode type / id\n    if [[ \"$status\" =~ (PAL|NTSC) ]]; then\n        temp=($(echo \"$status\" | grep -oE \"(PAL|NTSC) (4:3|16:10|16:9)\"))\n    else\n        temp=($(echo \"$status\" | grep -oE \"(CEA|DMT) \\([0-9]+\\)\"))\n    fi\n    mode_info[0]=\"${temp[0]}\"\n    mode_info[1]=\"${temp[1]//[()]/}\"\n\n    # get mode resolution\n    temp=$(echo \"$status\" | cut -d\",\" -f2 | grep -oE \"[0-9]+x[0-9]+\")\n    temp=(${temp/x/ })\n    mode_info[2]=\"${temp[0]}\"\n    mode_info[3]=\"${temp[1]}\"\n\n    # get aspect ratio\n    temp=$(echo \"$status\" | grep -oE \"([0-9]+:[0-9]+)\")\n    mode_info[4]=\"$temp\"\n\n    # get refresh rate\n    temp=$(echo \"$status\" | grep -oE \"[0-9\\.]+Hz\" | cut -d\".\" -f1)\n    mode_info[5]=\"$temp\"\n\n    echo \"${mode_info[@]}\"\n}\n\nfunction get_kms_mode_info() {\n    local mode_id=(${1/-/ })\n    local mode_info=()\n    local status\n\n    if [[ -z \"${mode_id[*]}\" ]]; then\n        if [[ -n \"${MODE[map-map]}\" ]]; then\n            # use mapped mode directly\n            mode_id=(${MODE[map-map]})\n        else\n            # use fallback mode\n            mode_id=(def def)\n        fi\n    fi\n\n    # split resolution (1st column)\n    status=(${MODE[${mode_id[0]}-${mode_id[1]}]/x/ })\n\n    # get crtc id\n    mode_info[0]=\"${mode_id[0]}\"\n\n    # get mode id\n    mode_info[1]=\"${mode_id[1]}\"\n\n    # get mode resolution\n    mode_info[2]=\"${status[0]}\"\n    # yres may have an ending 'i'(nterlace) flag\n    mode_info[3]=\"${status[1]/i/}\"\n\n    # get aspect ratio (5th column)\n    mode_info[4]=\"${status[5]}\"\n\n    # get refresh rate (4th column, remove surrounding brackets)\n    mode_info[5]=\"${status[4]//[()]/}\"\n\n    echo \"${mode_info[@]}\"\n}\n\nfunction get_x11_mode_info() {\n    local mode_id=(${1/:/ })\n    local mode_info=()\n    local status\n\n    if [[ -z \"$mode_id\" ]]; then\n        # determine current output\n        mode_id[0]=\"$($XRANDR --verbose | awk '/ connected.*\\(0x[a-f0-9]{1,}\\)/ { print $1;exit }')\"\n        # determine current mode id & strip brackets\n        mode_id[1]=\"$($XRANDR --verbose | awk '/ connected.*\\(0x[a-f0-9]{1,}\\)/ {print;exit}' | grep -o \"(0x[a-f0-9]\\{1,\\})\")\"\n        mode_id[1]=\"$(echo ${mode_id[1]:1:-1})\"\n    fi\n\n    # mode type corresponds to the currently connected output name\n    mode_info[0]=\"${mode_id[0]}\"\n\n    # get mode id\n    mode_info[1]=\"${mode_id[1]}\"\n\n    # get status line and split resolution\n    status=(${MODE[${mode_id[0]}:${mode_id[1]}]/x/ })\n\n    # get resolution\n    mode_info[2]=\"${status[0]}\"\n    mode_info[3]=\"${status[1]}\"\n\n    # aspect ratio cannot be determined for X11\n    mode_info[4]=\"n/a\"\n\n    # get refresh rate (stripping Hz, rounded to integer)\n    mode_info[5]=\"$(LC_NUMERIC=C printf '%.0f\\n' ${status[3]::-2})\"\n\n    echo \"${mode_info[@]}\"\n}\n\nfunction default_process() {\n    local config=\"$1\"\n    local mode=\"$2\"\n    local key=\"$3\"\n    local value=\"$4\"\n\n    iniConfig \" = \" '\"' \"$config\"\n    case \"$mode\" in\n        get)\n            iniGet \"$key\"\n            echo \"$ini_value\"\n            ;;\n        set)\n            iniSet \"$key\" \"$value\"\n            ;;\n        del)\n            iniDel \"$key\"\n            ;;\n    esac\n}\n\nfunction default_mode() {\n    local mode=\"$1\"\n    local type=\"$2\"\n    local value=\"$3\"\n\n    local key\n    case \"$type\" in\n        vid_emu)\n            key=\"$SAVE_EMU\"\n            ;;\n        vid_rom_old)\n            key=\"$SAVE_ROM_OLD\"\n            ;;\n        vid_rom)\n            key=\"$SAVE_ROM\"\n            ;;\n        fb_emu)\n            key=\"${SAVE_EMU}_fb\"\n            ;;\n        fb_rom_old)\n            key=\"${SAVE_ROM_OLD}_fb\"\n            ;;\n        fb_rom)\n            key=\"${SAVE_ROM}_fb\"\n            ;;\n        render)\n            key=\"${SAVE_EMU}_render\"\n            ;;\n    esac\n    default_process \"$VIDEO_CONF\" \"$mode\" \"$key\" \"$value\"\n}\n\nfunction default_emulator() {\n    local mode=\"$1\"\n    local type=\"$2\"\n    local value=\"$3\"\n\n    local key\n    local config=\"$EMU_SYS_CONF\"\n\n    case \"$type\" in\n        emu_sys)\n            key=\"default\"\n            ;;\n        emu_cmd)\n            key=\"$EMULATOR\"\n            ;;\n        emu_rom_old)\n            key=\"$SYS_SAVE_ROM_OLD\"\n            config=\"$EMU_CONF\"\n            ;;\n        emu_rom)\n            key=\"$SYS_SAVE_ROM\"\n            config=\"$EMU_CONF\"\n            ;;\n    esac\n    default_process \"$config\" \"$mode\" \"$key\" \"$value\"\n}\n\nfunction load_mode_defaults() {\n    local separator=\"-\"\n    [[ \"$HAS_MODESET\" == \"x11\" ]] && separator=\":\"\n    local temp\n    MODE_ORIG=()\n\n    if [[ -n \"$HAS_MODESET\" ]]; then\n        # populate available modes\n        [[ -z \"$MODE_ID\" ]] && get_all_${HAS_MODESET}_modes\n\n        # get current mode / aspect ratio\n        MODE_ORIG=($(get_${HAS_MODESET}_mode_info))\n        MODE_CUR=(\"${MODE_ORIG[@]}\")\n        MODE_ORIG_ID=\"${MODE_ORIG[0]}${separator}${MODE_ORIG[1]}\"\n\n        if [[ \"$MODE_REQ\" == \"0\" ]]; then\n            MODE_REQ_ID=\"$MODE_ORIG_ID\"\n        elif [[ \"$HAS_MODESET\" == \"tvs\" ]]; then\n            # get default mode for requested mode of 1 or 4\n            if [[ \"$MODE_REQ\" =~ (1|4) ]]; then\n                # if current aspect is anything else like 5:4 / 10:9 just choose a 4:3 mode\n                local aspect=\"${MODE_ORIG[4]}\"\n                [[ \"$aspect\" =~ (4:3|16:9) ]] || aspect=\"4:3\"\n                temp=\"${MODE_REQ}-${MODE_ORIG[0]}-$aspect\"\n                MODE_REQ_ID=\"${MODE_MAP[$temp]}\"\n            else\n                MODE_REQ_ID=\"$MODE_REQ\"\n            fi\n        else\n            MODE_REQ_ID=\"$MODE_REQ\"\n        fi\n    fi\n\n    # get default fb_res (if not running on X)\n    FB_ORIG=()\n    if [[ -z \"$DISPLAY\" ]]; then\n        local status=($(fbset | tr -s '\\n'))\n        FB_ORIG[0]=\"${status[3]}\"\n        FB_ORIG[1]=\"${status[4]}\"\n        FB_ORIG[2]=\"${status[7]}\"\n    fi\n\n    # default retroarch render res to config file\n    RENDER_RES=\"config\"\n\n    local mode\n    if [[ -f \"$VIDEO_CONF\" ]]; then\n        # load default video mode for emulator / rom\n        mode=\"$(default_mode get vid_emu)\"\n        [[ -n \"$mode\" ]] && MODE_REQ_ID=\"$mode\"\n\n        # get default mode for system + rom combination\n        # try the old key first and convert to the new key if found\n        mode=\"$(default_mode get vid_rom_old)\"\n        if [[ -n \"$mode\" ]]; then\n            default_mode del vid_rom_old\n            default_mode set vid_rom \"$mode\"\n            MODE_REQ_ID=\"$mode\"\n        else\n            mode=\"$(default_mode get vid_rom)\"\n            [[ -n \"$mode\" ]] && MODE_REQ_ID=\"$mode\"\n        fi\n\n        if [[ \"$HAS_MODESET\" == \"tvs\" ]]; then\n            # load default framebuffer res for emulator / rom\n            mode=\"$(default_mode get fb_emu)\"\n            [[ -n \"$mode\" ]] && FB_NEW=\"$mode\"\n\n            # get default fb mode for system + rom combination\n            # try the old key first and convert to the new key if found\n            mode=\"$(default_mode get fb_rom_old)\"\n            if [[ -n \"$mode\" ]]; then\n                default_mode del fb_rom_old\n                default_mode set fb_rom \"$mode\"\n                FB_NEW=\"$mode\"\n            else\n                mode=\"$(default_mode get fb_rom)\"\n                [[ -n \"$mode\" ]] && FB_NEW=\"$mode\"\n            fi\n        fi\n\n        # get default retroarch render resolution for emulator\n        mode=\"$(default_mode get render)\"\n        [[ -n \"$mode\" ]] && RENDER_RES=\"$mode\"\n    fi\n}\n\nfunction main_menu() {\n    local save\n    local cmd\n    local choice\n    local default\n\n    local user_menu=0\n    [[ -d \"$CONFIGDIR/all/runcommand-menu\" && -n \"$(find \"$CONFIGDIR/all/runcommand-menu\" -maxdepth 1 -name \"*.sh\")\" ]] && user_menu=1\n\n    [[ -z \"$ROM_BN\" ]] && ROM_BN=\"game/rom\"\n    [[ -z \"$SYSTEM\" ]] && SYSTEM=\"emulator/port\"\n\n    while true; do\n\n        local options=()\n        if [[ \"$IS_SYS\" -eq 1 ]]; then\n            local emu_sys=\"$(default_emulator get emu_sys)\"\n            local emu_rom=\"$(default_emulator get emu_rom)\"\n            options+=(\n                ES \"Select default emulator for $SYSTEM ($emu_sys)\"\n                ER \"Select emulator for ROM ($emu_rom)\"\n            )\n        fi\n\n        if [[ -n \"$HAS_MODESET\" ]]; then\n            local vid_emu=\"$(default_mode get vid_emu)\"\n            local vid_rom=\"$(default_mode get vid_rom)\"\n            options+=(\n                VE \"Select video mode for $EMULATOR ($vid_emu)\"\n                VR \"Select video mode for $EMULATOR + ROM ($vid_rom)\"\n            )\n        fi\n\n        if [[ \"$EMULATOR\" == lr-* ]]; then\n            if [[ \"$HAS_MODESET\" == \"tvs\" ]]; then\n                options+=(R \"Select RetroArch render res for $EMULATOR ($RENDER_RES)\")\n            fi\n            options+=(C \"Edit custom RetroArch config for this ROM\")\n        elif [[ \"$HAS_MODESET\" == \"tvs\" ]]; then\n            local fb_emu=\"$(default_mode get fb_emu)\"\n            local fb_rom=\"$(default_mode get fb_rom)\"\n            options+=(\n                FE \"Select framebuffer res for $EMULATOR ($fb_emu)\"\n                FR \"Select framebuffer res for $EMULATOR + ROM ($fb_rom)\"\n            )\n        fi\n\n        options+=(X \"Launch\")\n\n        if [[ \"$EMULATOR\" == lr-* ]]; then\n            options+=(L \"Launch with verbose logging\")\n            options+=(Z \"Launch with netplay enabled\")\n        fi\n\n        if [[ \"$user_menu\" -eq 1 ]]; then\n            options+=(U \"User Menu\")\n        fi\n\n        options+=(Q \"Exit (without launching)\")\n\n        local temp_mode\n        if [[ -n \"$HAS_MODESET\" ]]; then\n            temp_mode=\"${MODE[$MODE_REQ_ID]}\"\n        else\n            temp_mode=\"n/a\"\n        fi\n\n        cmd=(dialog --nocancel --default-item \"$default\" --menu \"System: $SYSTEM\\nEmulator: $EMULATOR\\nVideo Mode: $temp_mode\\nROM: $ROM_BN\"  22 76 16 )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        default=\"$choice\"\n\n        case \"$choice\" in\n            ES)\n                choose_emulator \"emu_sys\" \"$emu_sys\"\n                ;;\n            ER)\n                choose_emulator \"emu_rom\" \"$emu_rom\"\n                ;;\n            VE)\n                choose_mode \"vid_emu\" \"$vid_emu\"\n                ;;\n            VR)\n                choose_mode \"vid_rom\" \"$vid_rom\"\n                ;;\n            R)\n                choose_render_res \"render\" \"$RENDER_RES\"\n                ;;\n            C)\n                touch \"$ROM.cfg\"\n                cmd=(dialog --editbox \"$ROM.cfg\" 22 76)\n                choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                [[ -n \"$choice\" ]] && echo \"$choice\" >\"$ROM.cfg\"\n                [[ ! -s \"$ROM.cfg\" ]] && rm \"$ROM.cfg\"\n                ;;\n            FE)\n                choose_mode \"fb_emu\" \"$fb_emu\"\n                ;;\n            FR)\n                choose_mode \"fb_rom\" \"$fb_rom\"\n                ;;\n            Z)\n                NETPLAY=1\n                break\n                ;;\n            X)\n                return 0\n                ;;\n            L)\n                COMMAND+=\" --verbose\"\n                VERBOSE=1\n                return 0\n                ;;\n            U)\n                user_menu\n                local ret=\"$?\"\n                [[ \"$ret\" -eq 1 ]] && return 1\n                [[ \"$ret\" -eq 2 ]] && return 0\n                ;;\n            Q)\n                return 1\n                ;;\n        esac\n    done\n    return 0\n}\n\nfunction choose_mode() {\n    local mode=\"$1\"\n    local default=\"$2\"\n\n    local key\n    local options=()\n    local mode_desc=\"\"\n\n    options=(\"X\" \"Clear / Remove\")\n    if [[ \"$mode\" == vid_* ]]; then\n        mode_desc=\"video mode for \"\n        for key in \"${MODE_ID[@]}\"; do\n            options+=(\"$key\" \"${MODE[$key]}\")\n        done\n    elif [[ \"$mode\" == fb_* ]]; then\n        mode_desc=\"framebuffer resolution for \"\n        for key in $(get_resolutions); do\n            options+=(\"$key\" \"$key\")\n        done\n    fi\n\n    if [[ \"$mode\" == *_emu ]]; then\n        mode_desc+=\"$EMULATOR\"\n    else\n        mode_desc+=\"$EMULATOR + ROM ($ROM_BN)\"\n    fi\n\n    local menu_title=\"Choose $mode_desc\\nCurrently: \"\n    if [[ -z \"$default\" ]]; then\n        menu_title+=\"(not set)\"\n    else\n        menu_title+=\"$default\"\n    fi\n\n    local cmd=(dialog --default-item \"$default\" --menu \"$menu_title\"  22 76 16 )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n\n    if [[ \"$choice\" == \"X\" ]]; then\n        default_mode del \"$mode\"\n    else\n        default_mode set \"$mode\" \"$choice\"\n    fi\n    load_mode_defaults\n}\n\nfunction choose_emulator() {\n    local mode=\"$1\"\n    local default=\"$2\"\n    local cancel=\"$3\"\n\n    local mode_desc=\"default emulator for \"\n    if [[ \"$mode\" == \"emu_sys\" ]]; then\n        mode_desc+=\"$SYSTEM\"\n    else\n        mode_desc+=\"ROM ($ROM_BN)\"\n    fi\n\n    local default_id\n\n    local options=()\n    local i=1\n    while read line; do\n        # convert key=value to array\n        local line=(${line/=/ })\n        local id=${line[0]}\n        [[ \"$id\" == \"default\" ]] && continue\n        local apps[$i]=\"$id\"\n        if [[ \"$id\" == \"$default\" ]]; then\n            default_id=\"$i\"\n        fi\n        options+=($i \"$id\")\n        ((i++))\n    done < <(sort \"$EMU_SYS_CONF\")\n    if [[ \"${#options[@]}\" -eq 0 ]]; then\n        dialog --msgbox \"No emulator options found for $SYSTEM - Do you have a valid $EMU_SYS_CONF ?\" 20 60 >/dev/tty\n        stop_joy2key\n        exit 1\n    fi\n    [[ \"$mode\" != \"emu_sys\" ]] && options=(\"X\" \"Clear / Remove\" \"${options[@]}\")\n\n    local menu_title=\"Choose $mode_desc\\nCurrently: \"\n    if [[ -z \"$default\" ]]; then\n        menu_title+=\"(not set)\"\n    else\n        menu_title+=\"$default\"\n    fi\n\n    local cmd=(dialog $cancel --default-item \"$default_id\" --menu \"$menu_title\"  22 76 16 )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n\n    if [[ \"$choice\" == \"X\" ]]; then\n        default_emulator del \"$mode\"\n    else\n        default_emulator set \"$mode\" \"${apps[$choice]}\"\n    fi\n    get_sys_command\n    set_save_vars\n    load_mode_defaults\n}\n\nfunction get_resolutions() {\n    local res=(\n        \"320x224\"\n        \"320x240\"\n        \"400x240\"\n        \"480x320\"\n        \"640x480\"\n        \"720x480\"\n        \"720x576\"\n        \"800x480\"\n        \"800x600\"\n        \"960x720\"\n        \"1024x600\"\n        \"1024x768\"\n        \"1024x800\"\n        \"1280x720\"\n        \"1280x800\"\n        \"1280x960\"\n        \"1280x1024\"\n        \"1360x768\"\n        \"1366x768\"\n        \"1920x1080\"\n    )\n    echo \"${res[@]}\"\n}\n\nfunction choose_render_res() {\n    local mode=\"$1\"\n    local default=\"$2\"\n\n    local res=($(get_resolutions))\n    local i=1\n    local item\n    local options=()\n    for item in \"${res[@]}\"; do\n        [[ \"$item\" == \"$default\" ]] && default=\"$i\"\n        options+=($i \"$item\")\n        ((i++))\n    done\n    options+=(\n        O \"Use video output resolution\"\n        C \"Use config file resolution\"\n    )\n    [[ \"$default\" == \"output\" ]] && default=\"O\"\n    [[ \"$default\" == \"config\" ]] && default=\"C\"\n    local cmd=(dialog --default-item \"$default\" --menu \"Choose RetroArch render resolution\" 22 76 16 )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n    case \"$choice\" in\n        O)\n            choice=\"output\"\n            ;;\n        C)\n            choice=\"config\"\n            ;;\n        *)\n            choice=\"${res[$choice-1]}\"\n            ;;\n    esac\n\n    default_mode set \"$mode\" \"$choice\"\n    load_mode_defaults\n}\n\nfunction user_menu() {\n    local default\n    local options=()\n    local script\n    local i=1\n    while read -r script; do\n        script=\"${script##*/}\"\n        script=\"${script%.*}\"\n        options+=($i \"$script\")\n        ((i++))\n    done < <(find \"$CONFIGDIR/all/runcommand-menu\" -type f -name \"*.sh\" | sort)\n    local default\n    local cmd\n    local choice\n    local ret\n    while true; do\n        cmd=(dialog --default-item \"$default\" --cancel-label \"Back\" --menu \"Choose option\"  22 76 16)\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && return 0\n        default=\"$choice\"\n        script=\"runcommand-menu/${options[choice*2-1]}.sh\"\n        user_script \"$script\"\n        ret=\"$?\"\n        [[ \"$ret\" -eq 1 || \"$ret\" -eq 2 ]] && return \"$ret\"\n    done\n}\n\nfunction switch_fb_res() {\n    local res=(${1/x/ })\n    local res_x=\"${res[0]}\"\n    local res_y=\"${res[1]}\"\n    local depth=\"$2\"\n    [[ -z \"$depth\" ]] && depth=\"${FB_ORIG[2]}\"\n\n    if [[ -z \"$res_x\" || -z \"$res_y\" ]]; then\n        fbset --all -depth 8\n        fbset --all -depth $depth\n    else\n        fbset --all -depth 8\n        fbset --all --geometry $res_x $res_y $res_x $res_y $depth\n    fi\n}\n\nfunction build_xinitrc() {\n    local mode=\"$1\"\n    local xinitrc=\"/dev/shm/retropie_xinitrc\"\n\n    case \"$mode\" in\n        clear)\n            rm -rf \"$xinitrc\"\n            ;;\n        build)\n            echo \"#!/bin/bash\" >\"$xinitrc\"\n\n            # do modesetting (if supported)\n            if [[ -n \"$HAS_MODESET\" ]]; then\n                cat >>\"$xinitrc\" <<_EOF_\nXRANDR_OUTPUT=\"\\$($XRANDR --verbose | grep \" connected\" | awk '{ print \\$1 }')\"\n$XRANDR --output \\$XRANDR_OUTPUT --mode ${MODE_CUR[2]}x${MODE_CUR[3]} --refresh ${MODE_CUR[5]}\necho \"Set mode ${MODE_CUR[2]}x${MODE_CUR[3]}@${MODE_CUR[5]}Hz on \\$XRANDR_OUTPUT\"\n_EOF_\n            fi\n\n            if [[ \"$XINIT_WM\" -gt 0 ]]; then\n                local params=()\n                [[ \"$XINIT_WM\" -eq 1 ]] && params+=(-use_cursor no)\n                [[ \"$XINIT_WM\" -eq 2 ]] && params+=(-use_cursor yes)\n                cat >>\"$xinitrc\" <<_EOF_\nmatchbox-window-manager ${params[@]} &\nsleep 0.5\nxset -dpms s off s noblank\n_EOF_\n            fi\n\n            # echo command line for runcommand log\n            cat >>\"$xinitrc\" <<_EOF_\necho -e \"\\nExecuting (via xinit): \"${COMMAND//\\$/\\\\\\$}\"\\n\"\n${COMMAND//\\$/\\\\\\$}\n_EOF_\n            chmod +x \"$xinitrc\"\n\n            # rewrite command to launch our xinit script (if not startx)\n            if ! [[ \"$COMMAND\" =~ ^startx ]]; then\n                COMMAND=\"xinit $xinitrc\"\n            fi\n\n            # workaround for launching xserver on correct/user owned tty\n            # see https://github.com/RetroPie/RetroPie-Setup/issues/1805\n\n            # if no TTY env var is set, try and get it - eg if launching a ports script or runcommand manually\n            if [[ -z \"$TTY\" ]]; then\n                TTY=$(tty)\n                TTY=${TTY:8:1}\n            fi\n\n            # if we managed to get the current tty then try and use it\n            if [[ -n \"$TTY\" ]]; then\n                COMMAND=\"$COMMAND -- vt$TTY -keeptty\"\n            fi\n            ;;\n    esac\n}\n\nfunction mode_switch() {\n    local command_prefix\n    local separator=\"-\"\n    # X11 uses hypens in connector names\n    [[ $HAS_MODESET == \"x11\" ]] && separator=\":\"\n    local mode_id=(${1/${separator}/ })\n\n    # if the requested mode is the same as the current mode, don't switch\n    [[ \"${mode_id[*]}\" == \"${MODE_CUR[0]} ${MODE_CUR[1]}\" ]] && return 1\n\n    if [[ \"$HAS_MODESET\" == \"kms\" ]]; then\n        # update the target resolution even though the underlying fb hasn't changed\n        MODE_CUR=($(get_${HAS_MODESET}_mode_info \"${mode_id[*]}\"))\n\n        # check the mode tuple against the list of current available CRCTID/MODEID values\n        if [[ -n ${MODE[\"${MODE_CUR[0]}-${MODE_CUR[1]}\"]} ]]; then\n            # inject the environment variables to do modesetting for SDL2 applications\n            command_prefix=\"SDL_VIDEO_KMSDRM_CRTCID=${MODE_CUR[0]} SDL_VIDEO_KMSDRM_MODEID=${MODE_CUR[1]}\"\n        fi\n        COMMAND=\"$(echo \"$command_prefix $COMMAND\" | sed -e \"s/;/; $command_prefix /g\")\"\n\n        return 0\n    elif [[ \"$HAS_MODESET\" == \"x11\" ]]; then\n        # query the target resolution\n        MODE_CUR=($(get_${HAS_MODESET}_mode_info \"${mode_id[*]}\"))\n        # set target resolution\n        $XRANDR --output \"${MODE_CUR[0]}\" --mode \"${MODE_CUR[1]}\"\n\n        [[ \"$?\" -eq 0 ]] && return 0\n    elif [[ \"$HAS_MODESET\" == \"tvs\" ]]; then\n        if [[ \"${mode_id[0]}\" == \"PAL\" ]] || [[ \"${mode_id[0]}\" == \"NTSC\" ]]; then\n            $TVSERVICE -c \"${mode_id[*]}\" >/dev/null\n        else\n            $TVSERVICE -e \"${mode_id[*]}\" >/dev/null\n        fi\n\n        # if we have switched mode, switch the framebuffer resolution also\n        if [[ \"$?\" -eq 0 ]]; then\n            sleep 1\n            clear\n            MODE_CUR=($(get_${HAS_MODESET}_mode_info))\n            [[ -z \"$FB_NEW\" ]] && FB_NEW=\"${MODE_CUR[2]}x${MODE_CUR[3]}\"\n            return 0\n        fi\n    fi\n\n    return 1\n}\n\nfunction restore_fb() {\n    sleep 1\n    switch_fb_res \"${FB_ORIG[0]}x${FB_ORIG[1]}\" \"${FB_ORIG[2]}\"\n}\n\nfunction config_backend() {\n    # if we are running under X then don't try and use a different backend\n    [[ -n \"$DISPLAY\" || \"$XINIT\" -eq 1 ]] && return\n    local name=\"$1\"\n    # if we have a backends.conf file and with an entry for the current emulator name,\n    # change the library path to load dispmanx sdl first\n    if [[ -f \"$BACKENDS_CONF\" ]]; then\n        iniConfig \" = \" '\"' \"$BACKENDS_CONF\"\n        iniGet \"$name\"\n        case \"$ini_value\" in\n            1|dispmanx)\n                if [[ \"$HAS_MODESET\" == \"kms\" ]]; then\n                    COMMAND=\"SDL_DISPMANX_WIDTH=${MODE_CUR[2]} SDL_DISPMANX_HEIGHT=${MODE_CUR[3]} $COMMAND\"\n                fi\n                COMMAND=\"SDL1_VIDEODRIVER=dispmanx $COMMAND\"\n                ;;\n            sdl12-compat)\n                COMMAND=\"LD_PRELOAD=\\\"$ROOTDIR/supplementary/sdl12-compat/libSDL-1.2.so.0\\\" $COMMAND\"\n                ;;\n            x11)\n                XINIT=1\n                XINIT_WM=1\n                ;;\n            x11-c)\n                XINIT=1\n                XINIT_WM=2\n                ;;\n        esac\n    fi\n}\n\nfunction retroarch_append_config() {\n    local conf=\"/dev/shm/retroarch.cfg\"\n    local dim\n\n    # only for retroarch emulators\n    [[ \"$EMULATOR\" != lr-* ]] && return\n\n    # make sure tmp folder exists for unpacking archives\n    mkdir -p \"/tmp/retroarch\"\n\n    rm -f \"$conf\"\n    touch \"$conf\"\n    iniConfig \" = \" '\"' \"$conf\"\n\n    # strip any suffix decimals appearing in refresh rate, just for comparison\n    if [[ -n \"$HAS_MODESET\" && \"${MODE_CUR[5]%.*}\" -gt 0 ]]; then\n        # set video_refresh_rate in our config to the same as the screen refresh\n        iniSet \"video_refresh_rate\" \"${MODE_CUR[5]}\"\n    fi\n\n    # populate with target resolution & fullscreen flag if KMS is active\n    if [[ \"$HAS_MODESET\" != \"tvs\" ]]; then\n        iniSet \"video_fullscreen\" \"true\"\n        iniSet \"video_fullscreen_x\" \"${MODE_CUR[2]}\"\n        iniSet \"video_fullscreen_y\" \"${MODE_CUR[3]}\"\n    # if our render resolution is \"config\", then we don't set anything (use the value in the retroarch.cfg)\n    elif [[ \"$RENDER_RES\" != \"config\" ]]; then\n        if [[ \"$RENDER_RES\" == \"output\" ]]; then\n            dim=(0 0)\n        else\n            dim=(${RENDER_RES/x/ })\n        fi\n        iniSet \"video_fullscreen_x\" \"${dim[0]}\"\n        iniSet \"video_fullscreen_y\" \"${dim[1]}\"\n    fi\n\n    # set `libretro_directory` to the core parent folder\n    local core_dir=$(echo \"$COMMAND\" | grep -Eo \"$ROOTDIR/libretrocores/.*libretro\\.so\" | head -n 1)\n    core_dir=$(dirname \"$core_dir\")\n    [[ -n \"$core_dir\" ]] && iniSet \"libretro_directory\" \"$core_dir\"\n\n    # if verbose logging is on, set core logging to INFO\n    [[ \"$VERBOSE\" -eq 1 ]] && iniSet \"libretro_log_level\" \"1\"\n\n    # if the ROM has a custom configuration then append that too\n    if [[ -f \"$ROM.cfg\" ]]; then\n        conf+=\"'|'\\\"$ROM.cfg\\\"\"\n    fi\n\n    # if we already have an existing appendconfig parameter, we need to add our configs to that\n    if [[ \"$COMMAND\" =~ \"--appendconfig\" ]]; then\n        COMMAND=$(echo \"$COMMAND\" | sed \"s#\\(--appendconfig *[^ $]*\\)#\\1'|'$conf#\")\n    else\n        COMMAND+=\" --appendconfig $conf\"\n    fi\n\n    # append any NETPLAY configuration\n    if [[ \"$NETPLAY\" -eq 1 ]] && [[ -f \"$RETRONETPLAY_CONF\" ]]; then\n        source \"$RETRONETPLAY_CONF\"\n        COMMAND+=\" -$__netplaymode $__netplayhostip_cfile --port $__netplayport --nick $__netplaynickname\"\n    fi\n}\n\nfunction set_governor() {\n    governor_old=()\n    # we save the previous states first, as setting any cpuX on the RPI will also set the value for the other cores\n    # which would cause us to save the wrong state for cpu1/2/3 after setting cpu0. On the RPI we could just process\n    # cpu0, but this code needs to work on other platforms that do support a \"per core\" CPU governor.\n    for cpu in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor; do\n        governor_old+=($(<$cpu))\n    done\n    for cpu in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor; do\n        echo \"$1\" | sudo tee \"$cpu\" >/dev/null\n    done\n}\n\nfunction restore_governor() {\n    local i=0\n    for cpu in /sys/devices/system/cpu/cpu[0-9]*/cpufreq/scaling_governor; do\n        echo \"${governor_old[$i]}\" | sudo tee \"$cpu\" >/dev/null\n        ((i++))\n    done\n}\n\nfunction get_sys_command() {\n    if [[ ! -f \"$EMU_SYS_CONF\" ]]; then\n        echo \"No config found for system $SYSTEM\"\n        stop_joy2key\n        exit 1\n    fi\n\n    # get system & rom specific emulator if set\n    local emulator=\"$(default_emulator get emu_sys)\"\n    if [[ -z \"$emulator\" ]]; then\n        echo \"No default emulator found for system $SYSTEM\"\n        start_joy2key\n        choose_emulator \"emu_sys\" \"\" \"--nocancel\"\n        stop_joy2key\n        get_sys_command \"$SYSTEM\" \"$ROM\"\n        return\n    fi\n    EMULATOR=\"$emulator\"\n\n    # get default emulator for system + rom combination\n    # try the old key first and convert to the new key if found\n    emulator=\"$(default_emulator get emu_rom_old)\"\n\n    if [[ -n \"$emulator\" ]]; then\n        default_emulator del emu_rom_old\n        default_emulator set emu_rom \"$emulator\"\n        EMULATOR=\"$emulator\"\n    else\n        emulator=\"$(default_emulator get emu_rom)\"\n        [[ -n \"$emulator\" ]] && EMULATOR=\"$emulator\"\n    fi\n\n    COMMAND=\"$(default_emulator get emu_cmd)\"\n\n    # replace tokens\n    COMMAND=\"${COMMAND//\\%ROM\\%/\\\"$ROM\\\"}\"\n    COMMAND=\"${COMMAND//\\%BASENAME\\%/\\\"$ROM_BN\\\"}\"\n\n    # special case to get the last 2 folders for quake games for the -game parameter\n    # remove everything up to /quake/\n    local quake_dir=\"${ROM##*/quake/}\"\n    # remove filename\n    quake_dir=\"${quake_dir%/*}\"\n    COMMAND=\"${COMMAND//\\%QUAKEDIR\\%/\\\"$quake_dir\\\"}\"\n\n    # check if COMMAND starts with a launch OPTION:\n    if [[ \"$COMMAND\" =~ ^([A-Z\\-]+?):(.*)$ ]]; then\n        # extract the command\n        COMMAND=\"${BASH_REMATCH[2]}\"\n\n        case \"${BASH_REMATCH[1]}\" in\n            # if it starts with CON: it is a console application (so we don't redirect stdout later)\n            CON)\n                CONSOLE_OUT=1\n                ;;\n            # if it starts with XINIT it is an X11 application (so we need to launch via xinit)\n            XINIT*)\n                XINIT=1\n                ;;&\n            # if it starts with XINIT-WM or XINIT-WMC (with cursor) it is an X11 application needing a window manager\n            XINIT-WM)\n                XINIT_WM=1\n                ;;\n            XINIT-WMC)\n                XINIT_WM=2\n                ;;\n        esac\n    fi\n\n}\n\nfunction show_launch() {\n    local images=()\n\n    if [[ \"$IS_SYS\" -eq 1 && \"$USE_ART\" -eq 1 ]]; then\n        # if using art look for images in paths for es art.\n        images+=(\n            \"$HOME/RetroPie/roms/$SYSTEM/images/${ROM_BN}-image\"\n            \"$HOME/.emulationstation/downloaded_images/$SYSTEM/${ROM_BN}-image\"\n            \"$HOME/.emulationstation/downloaded_media/$SYSTEM/screenshots/${ROM_BN}\"\n            \"$HOME/RetroPie/roms/$SYSTEM/media/screenshots/${ROM_BN}\"\n        )\n    fi\n\n    # look for custom launching images\n    if [[ \"$IS_SYS\" -eq 1 ]]; then\n        images+=(\n            \"$HOME/RetroPie/roms/$SYSTEM/images/${ROM_BN}-launching\"\n            \"$CONF_ROOT/launching\"\n        )\n    fi\n    [[ \"$IS_PORT\" -eq 1 ]] && images+=(\"$CONFIGDIR/ports/launching\")\n    images+=(\"$CONFIGDIR/all/launching\")\n\n    local image\n    local path\n    local ext\n    for path in \"${images[@]}\"; do\n        for ext in jpg png; do\n            if [[ -f \"$path.$ext\" ]]; then\n                image=\"$path.$ext\"\n                break 2\n            fi\n        done\n    done\n\n    if [[ -n \"$image\" ]]; then\n        # if we are running under X use feh otherwise try and use fbi\n        if [[ -n \"$DISPLAY\" ]]; then\n            feh -F -N -Z -Y -q \"$image\" & &>/dev/null\n            IMG_PID=$!\n            sleep \"$IMAGE_DELAY\"\n            # if we're not using the old Joy2Key script, we need feh to stop after the delay\n            # otherwise the menu will not be triggered due to terminal being out of focus\n            [[ \"$LEGACY_JOY2KEY\" -eq 0 && \"DISABLE_MENU\" -ne 1 ]] && kill -SIGINT \"$IMG_PID\"\n        else\n            fbi -1 -t \"$IMAGE_DELAY\" -noverbose -a \"$image\" </dev/tty &>/dev/null\n        fi\n    elif [[ \"$DISABLE_MENU\" -ne 1 && \"$USE_ART\" -ne 1 ]]; then\n        local launch_name\n        if [[ -n \"$ROM_BN\" ]]; then\n            launch_name=\"$ROM_BN ($EMULATOR)\"\n        else\n            launch_name=\"$EMULATOR\"\n        fi\n        DIALOGRC=\"$CONFIGDIR/all/runcommand-launch-dialog.cfg\" dialog --infobox \"\\nLaunching $launch_name ...\\n\\nPress a button to configure\\n\\nErrors are logged to $LOG\" 9 60\n    fi\n}\n\nfunction check_menu() {\n    local dont_launch=0\n    # check for key pressed to enter configuration\n    IFS= read -s -t 2 -N 1 key </dev/tty\n    if [[ -n \"$key\" ]]; then\n        [[ -n \"$IMG_PID\" ]] && kill -SIGINT \"$IMG_PID\"\n        tput cnorm\n        main_menu\n        dont_launch=$?\n        tput civis\n        clear\n    fi\n    return $dont_launch\n}\n\n# calls script with parameters SYSTEM, EMULATOR, ROM, and commandline\nfunction user_script() {\n    local script=\"$CONFIGDIR/all/$1\"\n    if [[ -f \"$script\" ]]; then\n        bash \"$script\" \"$SYSTEM\" \"$EMULATOR\" \"$ROM\" \"$COMMAND\" </dev/tty 2>>\"$LOG\"\n    fi\n}\n\nfunction restore_cursor_and_exit() {\n    # if we are not being run from emulationstation (get parent of parent), turn the cursor back on.\n    if [[ \"$(ps -o comm= -p $(ps -o ppid= -p $PPID))\" != \"emulationstatio\" ]]; then\n        tput cnorm\n    fi\n\n    exit 0\n}\n\nfunction launch_command() {\n    local ret\n    # escape $ to avoid variable expansion (eg roms containing $!)\n    COMMAND=\"${COMMAND//\\$/\\\\\\$}\"\n    # launch the command\n    echo -e \"Parameters: $@\\nExecuting: $COMMAND\" >>\"$LOG\"\n    if [[ \"$CONSOLE_OUT\" -eq 1 ]]; then\n        # turn cursor on\n        tput cnorm\n        eval \"$COMMAND\" </dev/tty 2>>\"$LOG\"\n        ret=$?\n        tput civis\n    else\n        eval \"$COMMAND\" </dev/tty &>>\"$LOG\"\n        ret=$?\n    fi\n    return $ret\n}\n\nfunction log_info() {\n    echo -e \"$SYSTEM\\n$EMULATOR\\n$ROM\\n$COMMAND\" >/dev/shm/runcommand.info\n}\n\nfunction runcommand() {\n    get_config\n\n    if ! get_params \"$@\"; then\n        echo \"$0 MODE COMMAND [SAVENAME]\"\n        echo \"$0 MODE _SYS_/_PORT_ SYSTEM ROM\"\n        exit 1\n    fi\n\n    # turn off cursor and clear screen\n    tput civis\n    clear\n\n    rm -f \"$LOG\"\n    log_info\n    user_script \"runcommand-onstart.sh\"\n\n    set_save_vars\n\n    load_mode_defaults\n\n    start_joy2key\n    show_launch\n\n    if [[ \"$DISABLE_MENU\" -ne 1 ]]; then\n        if ! check_menu; then\n            stop_joy2key\n            user_script \"runcommand-onend.sh\"\n            clear\n            restore_cursor_and_exit 0\n        fi\n    fi\n    stop_joy2key\n\n    mode_switch \"$MODE_REQ_ID\"\n\n    # replace X/Y resolution and refresh (useful for KMS/modesetting)\n    COMMAND=\"${COMMAND//\\%XRES\\%/${MODE_CUR[2]}}\"\n    COMMAND=\"${COMMAND//\\%YRES\\%/${MODE_CUR[3]}}\"\n    COMMAND=\"${COMMAND//\\%REFRESH\\%/${MODE_CUR[5]}}\"\n\n    # resave info after menu and resolution replacements so runcommand.info is up to date\n    log_info\n\n    [[ -n \"$FB_NEW\" ]] && switch_fb_res $FB_NEW\n\n    config_backend \"$SAVE_EMU\"\n\n    # switch to configured cpu scaling governor\n    [[ -n \"$GOVERNOR\" ]] && set_governor \"$GOVERNOR\"\n\n    retroarch_append_config\n\n    # build xinitrc and rewrite command if not already in X11 context\n    if [[ \"$XINIT\" -eq 1 && \"$HAS_MODESET\" != \"x11\" ]]; then\n        build_xinitrc build\n    fi\n\n    user_script \"runcommand-onlaunch.sh\"\n\n    # include our SDL gamecontroller mappings in the environment\n    # but check if the environment doesn't already have the SDL GameController mapping hint\n    if [[ -z $SDL_GAMECONTROLLERCONFIG && -f \"$SDL2_MAPPINGS\" ]]; then\n        export SDL_GAMECONTROLLERCONFIG=\"$(cat \"$SDL2_MAPPINGS\")\"\n    fi\n\n    local ret\n    clear\n    launch_command\n    ret=$?\n\n    [[ -n \"$IMG_PID\" ]] && kill -SIGINT \"$IMG_PID\"\n\n    clear\n\n    # remove tmp folder for unpacked archives if it exists\n    rm -rf \"/tmp/retroarch\"\n\n    # restore default cpu scaling governor\n    [[ -n \"$GOVERNOR\" ]] && restore_governor\n\n    # if we switched mode - restore preferred mode\n    mode_switch \"$MODE_ORIG_ID\"\n\n    # delete temporary xinitrc launch script\n    if [[ \"$XINIT\" -eq 1 && \"$HAS_MODESET\" != \"x11\" ]]; then\n        build_xinitrc clear\n    fi\n\n    # reset/restore framebuffer res (if it was changed)\n    [[ -n \"$FB_NEW\" ]] && restore_fb\n\n    [[ \"$EMULATOR\" == lr-* ]] && retroarchIncludeToEnd \"$CONF_ROOT/retroarch.cfg\"\n\n    user_script \"runcommand-onend.sh\"\n\n    restore_cursor_and_exit \"$ret\"\n}\n\nruncommand \"$@\"\n"
  },
  {
    "path": "scriptmodules/supplementary/runcommand.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"runcommand\"\nrp_module_desc=\"The 'runcommand' launch script - needed for launching the emulators from the frontend\"\nrp_module_section=\"core\"\nrp_module_flags=\"nonet\"\n\nfunction _update_hook_runcommand() {\n    # make sure runcommand is always updated when updating retropie-setup and\n    # install joy2key module when updating if the old joy2key is in place\n    if rp_isInstalled \"$md_id\"; then\n        [[ -f \"$md_inst/joy2key.py\" ]] && rp_callModule \"joy2key\"\n        install_bin_runcommand\n    fi\n    if hasFlag \"armv6\" && [[ \"$__os_debian_ver\" -le 12 ]]; then\n        iniConfig \" = \" '\"' \"$configdir/all/runcommand.cfg\"\n        iniSet \"legacy_joy2key\" \"1\"\n    fi\n}\n\nfunction depends_runcommand() {\n    local depends=()\n    isPlatform \"rpi\" && isPlatform \"dispmanx\" && depends+=(libraspberrypi-bin)\n    isPlatform \"rpi\" || isPlatform \"kms\" && depends+=(fbi fbset)\n    isPlatform \"x11\" && depends+=(feh)\n    getDepends \"${depends[@]}\"\n}\n\nfunction install_bin_runcommand() {\n    rm -rf \"$md_inst\"\n    mkdir -p \"$md_inst\"\n    cp \"$md_data/runcommand.sh\" \"$md_inst/\"\n    if [[ ! -f \"$configdir/all/runcommand.cfg\" ]]; then\n        mkUserDir \"$configdir/all\"\n        iniConfig \" = \" '\"' \"$configdir/all/runcommand.cfg\"\n        iniSet \"use_art\" \"0\"\n        iniSet \"disable_joystick\" \"0\"\n        iniSet \"governor\" \"\"\n        iniSet \"disable_menu\" \"0\"\n        iniSet \"image_delay\" \"2\"\n        # weaker systems should use the old Joy2Key version\n        hasFlag \"armv6\" && iniSet \"legacy_joy2key\" \"1\"\n        chown \"$__user\":\"$__group\" \"$configdir/all/runcommand.cfg\"\n    fi\n    if [[ ! -f \"$configdir/all/runcommand-launch-dialog.cfg\" ]]; then\n        dialog --create-rc \"$configdir/all/runcommand-launch-dialog.cfg\"\n        chown \"$__user\":\"$__group\" \"$configdir/all/runcommand-launch-dialog.cfg\"\n    fi\n\n    # needed for KMS modesetting (debian buster or later only)\n    if [[ \"$__os_debian_ver\" -ge 10 ]]; then\n        rp_installModule \"kmsxx\" \"_autoupdate_\"\n    fi\n\n    md_ret_require=\"$md_inst/runcommand.sh\"\n}\n\nfunction remove_runcommand() {\n    rp_callModule \"mesa-drm\" \"remove\"\n}\n\nfunction governor_runcommand() {\n    local config=\"$configdir/all/runcommand.cfg\"\n    iniConfig \" = \" '\"' \"$config\"\n    iniGet \"governor\"\n\n    local current=\"$ini_value\"\n    local default=1\n    local status=\"Default (don't change)\"\n\n    [[ -n \"$current\" ]] && status=\"$current\"\n\n    local governors\n    local governor\n    local options=(\"1\" \"Default (don't change)\")\n    local i=2\n    if [[ -f /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors ]]; then\n        for governor in $(</sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors); do\n            [[ \"$current\" == \"$governor\" ]] && default=\"$i\"\n            governors[$i]=\"$governor\"\n            options+=(\"$i\" \"Force $governor\")\n            ((i++))\n        done\n    fi\n    cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --cancel-label \"Back\" --menu \"Configure CPU Governor on command launch\\nCurrently: $status\" 22 86 16)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        governor=\"${governors[$choice]}\"\n        iniSet \"governor\" \"$governor\"\n        chown \"$__user\":\"$__group\" \"$config\"\n    fi\n}\n\nfunction gui_runcommand() {\n    local config=\"$configdir/all/runcommand.cfg\"\n    iniConfig \" = \" '\"' \"$config\"\n    chown \"$__user\":\"$__group\" \"$config\"\n\n    local cmd\n    local option\n    local default\n    while true; do\n\n        eval \"$(loadModuleConfig \\\n            'disable_menu=0' \\\n            'use_art=0' \\\n            'disable_joystick=0' \\\n            'image_delay=2' \\\n            'governor=' \\\n            'legacy_joy2key=' \\\n        )\"\n\n        [[ -z \"$governor\" ]] && governor=\"Default: don't change\"\n        [[ -z \"$legacy_joy2key\" ]] && legacy_joy2key=\"0\"\n\n        cmd=(dialog --backtitle \"$__backtitle\" --cancel-label \"Exit\" --default-item \"$default\" --menu \"Choose an option.\" 22 86 16)\n        options=()\n\n        if [[ \"$disable_menu\" -eq 0 ]]; then\n            options+=(1 \"Launch menu (currently: Enabled)\")\n        else\n            options+=(1 \"Launch menu (currently: Disabled)\")\n        fi\n\n        if [[ \"$use_art\" -eq 1 ]]; then\n            options+=(2 \"Launch menu art (currently: Enabled)\")\n        else\n            options+=(2 \"Launch menu art (currently: Disabled)\")\n        fi\n\n        if [[ \"$disable_joystick\" -eq 0 ]]; then\n            options+=(3 \"Launch menu joystick control (currently: Enabled)\")\n        else\n            options+=(3 \"Launch menu joystick control (currently: Disabled)\")\n        fi\n\n        options+=(4 \"Launch image delay in seconds (currently $image_delay)\")\n        options+=(5 \"CPU governor configuration (currently: $governor)\")\n\n        if [[ \"$legacy_joy2key\" -eq 1 ]]; then\n            options+=(6 \"Use old Joy2Key for joystick control (currently: Enabled)\")\n        else\n            options+=(6 \"Use old Joy2Key for joystick control (currently: Disabled)\")\n        fi\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        default=\"$choice\"\n        case \"$choice\" in\n            1)\n                iniSet \"disable_menu\" \"$((disable_menu ^ 1))\"\n                ;;\n            2)\n                iniSet \"use_art\" \"$((use_art ^ 1))\"\n                ;;\n            3)\n                iniSet \"disable_joystick\" \"$((disable_joystick ^ 1))\"\n                ;;\n            4)\n                cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the delay in seconds\" 10 60 \"$image_delay\")\n                choice=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                iniSet \"image_delay\" \"$choice\"\n                ;;\n            5)\n                governor_runcommand\n                ;;\n            6)\n                iniSet \"legacy_joy2key\" \"$((legacy_joy2key ^ 1))\"\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/samba.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"samba\"\nrp_module_desc=\"Configure Samba ROM Shares\"\nrp_module_section=\"config\"\n\nfunction depends_samba() {\n    DEBIAN_FRONTEND=noninteractive getDepends samba\n}\n\nfunction remove_share_samba() {\n    local name=\"$1\"\n    [[ -z \"$name\" || ! -f /etc/samba/smb.conf ]] && return\n    sed -i \"/^\\[$name\\]/,/^force user/d\" /etc/samba/smb.conf\n}\n\nfunction add_share_samba() {\n    local name=\"$1\"\n    local path=\"$2\"\n    [[ -z \"name\" || -z \"$path\" ]] && return\n    remove_share_samba \"$name\"\n    cat >>/etc/samba/smb.conf <<_EOF_\n[$1]\ncomment = $name\npath = \"$path\"\nwriteable = yes\nguest ok = yes\ncreate mask = 0644\ndirectory mask = 0755\nforce user = $__user\n_EOF_\n}\n\nfunction restart_samba() {\n    systemctl -q is-active smbd.service && systemctl -q reload-or-restart smbd.service\n}\n\nfunction install_shares_samba() {\n    cp /etc/samba/smb.conf /etc/samba/smb.conf.bak\n    add_share_samba \"roms\" \"$romdir\"\n    add_share_samba \"bios\" \"$home/RetroPie/BIOS\"\n    add_share_samba \"configs\" \"$configdir\"\n    add_share_samba \"splashscreens\" \"$datadir/splashscreens\"\n\n    # Add `wsdd` so that RetroPie is easily discovered by Windows clients\n    # Only available on Debian 12/Ubuntu 22.04 and later\n    if apt-cache -qq madison wsdd; then\n        aptInstall wsdd\n    fi\n    restart_samba\n}\n\nfunction remove_shares_samba() {\n    local name\n    for name in roms bios configs splashscreens; do\n        remove_share_samba \"$name\"\n    done\n    restart_samba\n}\n\nfunction gui_samba() {\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option\" 22 76 16)\n        local options=(\n            1 \"Install RetroPie Samba shares\"\n            2 \"Remove RetroPie Samba shares\"\n            3 \"Manually edit /etc/samba/smb.conf\"\n            4 \"Restart Samba service\"\n            5 \"Remove Samba + configuration\"\n        )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rp_callModule \"$md_id\" depends\n                    rp_callModule \"$md_id\" install_shares\n                    printMsgs \"dialog\" \"Installed and enabled shares\"\n                    ;;\n                2)\n                    rp_callModule \"$md_id\" remove_shares\n                    printMsgs \"dialog\" \"Removed shares\"\n                    ;;\n                3)\n                    editFile /etc/samba/smb.conf\n                    ;;\n                4)\n                    rp_callModule \"$md_id\" restart\n                    ;;\n                5)\n                    rp_callModule \"$md_id\" depends remove\n                    printMsgs \"dialog\" \"Removed Samba service\"\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/scraper.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"scraper\"\nrp_module_desc=\"Scraper for EmulationStation by Steven Selph\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/sselph/scraper/master/LICENSE\"\nrp_module_repo=\"git https://github.com/sselph/scraper.git master\"\nrp_module_section=\"opt\"\nrp_module_flags=\"nobin\"\n\nfunction depends_scraper() {\n    rp_callModule golang install_bin\n}\n\nfunction sources_scraper() {\n    gitPullOrClone\n}\n\nfunction build_scraper() {\n    local goroot=\"$(_get_goroot_golang)\"\n    GOROOT=\"$goroot\" \"$goroot/bin/go\" mod init github.com/sselph/scraper\n    GOROOT=\"$goroot\" \"$goroot/bin/go\" get github.com/J-Swift/thegamesdb-swagger-client-go@43ed8a0b364ed2d8521d0\n    GOROOT=\"$goroot\" \"$goroot/bin/go\" build -o scraper\n}\n\nfunction install_scraper() {\n    md_ret_files=(\n        'scraper'\n        'LICENSE'\n        'README.md'\n        'hash.csv'\n    )\n}\n\nfunction remove_scraper() {\n    rp_callModule golang remove\n}\n\nfunction get_ver_scraper() {\n    [[ -f \"$md_inst/scraper\" ]] && \"$md_inst/scraper\" -version 2>/dev/null\n}\n\nfunction latest_ver_scraper() {\n    download https://api.github.com/repos/sselph/scraper/releases/latest - | grep -m 1 tag_name | cut -d\\\" -f4\n}\n\nfunction list_systems_scraper() {\n    find -L \"$romdir\" -mindepth 1 -maxdepth 1 -not -empty -type d | sort\n}\n\nfunction scrape_scraper() {\n    local system=\"$1\"\n    [[ -z \"$system\" ]] && return\n\n    iniConfig \" = \" '\"' \"$configdir/all/scraper.cfg\"\n    eval $(_load_config_scraper)\n\n    local gamelist\n    local img_dir\n    local img_path\n    if [[ \"$use_rom_folder\" -eq 1 ]]; then\n        gamelist=\"$romdir/$system/gamelist.xml\"\n        img_dir=\"$romdir/$system/images\"\n        img_path=\"./images\"\n    else\n        gamelist=\"$home/.emulationstation/gamelists/$system/gamelist.xml\"\n        img_dir=\"$home/.emulationstation/downloaded_images/$system\"\n        img_path=\"~/.emulationstation/downloaded_images/$system\"\n    fi\n\n    local params=()\n    params+=(-image_dir \"$img_dir\")\n    params+=(-image_path \"$img_path\")\n    params+=(-video_dir \"$img_dir\")\n    params+=(-video_path \"$img_path\")\n    params+=(-marquee_dir \"$img_dir\")\n    params+=(-marquee_path \"$img_path\")\n    params+=(-output_file \"$gamelist\")\n    params+=(-rom_dir \"$romdir/$system\")\n    params+=(-workers \"4\")\n    params+=(-skip_check)\n\n    [[ \"$system\" =~ ^mame-|arcade|fba|neogeo ]] && params+=(-mame)\n\n    if [[ \"$use_thumbs\" -eq 1 ]]; then\n        params+=(-thumb_only)\n    fi\n    if [[ \"$screenshots\" -eq 1 ]]; then\n        if [[ \"$system\" =~ ^mame-|arcade|fba|neogeo ]]; then\n            params+=(-mame_img \"s,m,t\")\n        else\n            params+=(-console_img \"s,b,3b,l,f\")\n        fi\n    fi\n    if [[ \"$download_videos\" -eq 1 ]]; then\n        params+=(-download_videos)\n    fi\n    if [[ \"$download_marquees\" -eq 1 ]]; then\n        params+=(-download_marquees)\n    fi\n    if [[ -n \"$max_width\" ]]; then\n        params+=(-max_width \"$max_width\")\n    fi\n    if [[ -n \"$max_height\" ]]; then\n        params+=(-max_height \"$max_height\")\n    fi\n    if [[ \"$console_src\" -eq 0 ]]; then\n        params+=(-console_src=\"ovgdb\")\n    elif [[ \"$console_src\" -eq 1 ]]; then\n        params+=(-console_src=\"gdb\")\n    else\n        params+=(-console_src=\"ss\")\n    fi\n    if [[ \"$mame_src\" -eq 0 ]]; then\n        params+=(-mame_src=\"mamedb\")\n    elif [[ \"$mame_src\" -eq 1 ]]; then\n        params+=(-mame_src=\"ss\")\n    else\n        params+=(-mame_src=\"adb\")\n    fi\n    if [[ \"$rom_name\" -eq 1 ]]; then\n        params+=(-use_nointro_name=false)\n    elif [[ \"$rom_name\" -eq 2 ]]; then\n        params+=(-use_filename=true)\n    fi\n    if [[ \"$append_only\" -eq 1 ]]; then\n        params+=(-append)\n    fi\n\n    # trap ctrl+c and return if pressed (rather than exiting retropie-setup etc)\n    trap 'trap 2; return 1' INT\n    sudo -u \"$__user\" \"$md_inst/scraper\" ${params[@]}\n    trap 2\n}\n\nfunction scrape_all_scraper() {\n    local system\n    while read system; do\n        system=${system/$romdir\\//}\n        scrape_scraper \"$system\" \"$@\" || return 1\n    done < <(list_systems_scraper)\n}\n\nfunction scrape_chosen_scraper() {\n    local options=()\n    local system\n    local i=1\n    while read system; do\n        system=${system/$romdir\\//}\n        options+=($i \"$system\" OFF)\n        ((i++))\n    done < <(list_systems_scraper)\n\n    if [[ ${#options[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"No populated rom folders were found in $romdir.\"\n        return\n    fi\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --checklist \"Select ROM Folders\" 22 76 16)\n    local choice=($(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty))\n\n    [[ ${#choice[@]} -eq 0 ]] && return\n\n    local choice\n    for choice in \"${choice[@]}\"; do\n        choice=${options[choice*3-2]}\n        scrape_scraper \"$choice\" \"$@\"\n    done\n}\n\nfunction _load_config_scraper() {\n    echo \"$(loadModuleConfig \\\n        'use_thumbs=1' \\\n        'screenshots=0' \\\n        'max_width=400' \\\n        'max_height=400' \\\n        'console_src=1' \\\n        'mame_src=2' \\\n        'rom_name=0' \\\n        'append_only=0' \\\n        'use_rom_folder=0' \\\n        'download_videos=0' \\\n        'download_marquees=0' \\\n    )\"\n}\n\nfunction gui_scraper() {\n    if pgrep \"emulationstatio\" >/dev/null; then\n        printMsgs \"dialog\" \"This scraper must not be run while Emulation Station is running or the scraped data will be overwritten. \\n\\nPlease quit from Emulation Station, and run RetroPie-Setup from the terminal\"\n        return\n    fi\n\n    iniConfig \" = \" '\"' \"$configdir/all/scraper.cfg\"\n    eval $(_load_config_scraper)\n    chown \"$__user\":\"$__group\" \"$configdir/all/scraper.cfg\"\n\n    local default\n    while true; do\n        local ver=$(get_ver_scraper)\n        [[ -z \"$ver\" ]] && ver=\"v(Git)\"\n        local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Scraper $ver by Steven Selph\" 22 76 16)\n        local options=(\n            1 \"Scrape all systems\"\n            2 \"Scrape chosen systems\"\n        )\n\n        if [[ \"$use_thumbs\" -eq 1 ]]; then\n            options+=(3 \"Thumbnails only (Enabled)\")\n        else\n            options+=(3 \"Thumbnails only (Disabled)\")\n        fi\n\n        if [[ \"$screenshots\" -eq 1 ]]; then\n            options+=(4 \"Prefer screenshots (Enabled)\")\n        else\n            options+=(4 \"Prefer screenshots (Disabled)\")\n        fi\n\n        if [[ \"$mame_src\" -eq 0 ]]; then\n            options+=(5 \"Arcade Source (MameDB)\")\n        elif [[ \"$mame_src\" -eq 1 ]]; then\n            options+=(5 \"Arcade Source (ScreenScraper)\")\n        else\n            options+=(5 \"Arcade Source (ArcadeItalia)\")\n        fi\n\n        if [[ \"$console_src\" -eq 0 ]]; then\n            options+=(6 \"Console Source (OpenVGDB)\")\n        elif [[ \"$console_src\" -eq 1 ]]; then\n            options+=(6 \"Console Source (thegamesdb)\")\n        else\n            options+=(6 \"Console Source (ScreenScraper)\")\n        fi\n\n        if [[ \"$rom_name\" -eq 0 ]]; then\n            options+=(7 \"ROM Names (No-Intro)\")\n        elif [[ \"$rom_name\" -eq 1 ]]; then\n            options+=(7 \"ROM Names (theGamesDB)\")\n        else\n            options+=(7 \"ROM Names (Filename)\")\n        fi\n\n        if [[ \"$append_only\" -eq 1 ]]; then\n            options+=(8 \"Gamelist (Append)\")\n        else\n            options+=(8 \"Gamelist (Overwrite)\")\n        fi\n\n        if [[ \"$use_rom_folder\" -eq 1 ]]; then\n            options+=(9 \"Use rom folder for gamelist & images (Enabled)\")\n        else\n            options+=(9 \"Use rom folder for gamelist & images (Disabled)\")\n        fi\n\n        if [[ \"$download_videos\" -eq 1 ]]; then\n            options+=(V \"Download Videos (Enabled)\")\n        else\n            options+=(V \"Download Videos (Disabled)\")\n        fi\n\n        if [[ \"$download_marquees\" -eq 1 ]]; then\n            options+=(M \"Download Marquees (Enabled)\")\n        else\n            options+=(M \"Download Marquees (Disabled)\")\n        fi\n\n        options+=(W \"Max image width ($max_width)\")\n        options+=(H \"Max image height ($max_height)\")\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            default=\"$choice\"\n            case \"$choice\" in\n                1)\n                    if scrape_all_scraper; then\n                        printMsgs \"dialog\" \"ROMS have been scraped.\"\n                    else\n                        printMsgs \"dialog\" \"Scraping was aborted\"\n                    fi\n                    ;;\n                2)\n                    if scrape_chosen_scraper; then\n                        printMsgs \"dialog\" \"ROMS have been scraped.\"\n                    else\n                        printMsgs \"dialog\" \"Scraping was aborted\"\n                    fi\n                    ;;\n                3)\n                    use_thumbs=\"$((use_thumbs ^ 1))\"\n                    iniSet \"use_thumbs\" \"$use_thumbs\"\n                    ;;\n                4)\n                    screenshots=\"$((screenshots ^ 1))\"\n                    iniSet \"screenshots\" \"$screenshots\"\n                    ;;\n                5)\n                    mame_src=\"$((( mame_src + 1) % 3))\"\n                    iniSet \"mame_src\" \"$mame_src\"\n                    ;;\n                6)\n                    console_src=\"$((( console_src + 1) % 3))\"\n                    iniSet \"console_src\" \"$console_src\"\n                    ;;\n                7)\n                    rom_name=\"$((( rom_name + 1 ) % 3))\"\n                    iniSet \"rom_name\" \"$rom_name\"\n                    ;;\n                8)\n                    append_only=\"$((append_only ^ 1))\"\n                    iniSet \"append_only\" \"$append_only\"\n                    ;;\n                9)\n                    use_rom_folder=\"$((use_rom_folder ^ 1))\"\n                    iniSet \"use_rom_folder\" \"$use_rom_folder\"\n                    ;;\n                V)\n                    download_videos=\"$((download_videos ^ 1))\"\n                    iniSet \"download_videos\" \"$download_videos\"\n                    ;;\n                M)\n                    download_marquees=\"$((download_marquees ^ 1))\"\n                    iniSet \"download_marquees\" \"$download_marquees\"\n                    ;;\n                H)\n                    cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the max image height in pixels\" 10 60 \"$max_height\")\n                    max_height=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"max_height\" \"$max_height\"\n                    ;;\n                W)\n                    cmd=(dialog --backtitle \"$__backtitle\" --inputbox \"Please enter the max image width in pixels\" 10 60 \"$max_width\")\n                    max_width=$(\"${cmd[@]}\" 2>&1 >/dev/tty)\n                    iniSet \"max_width\" \"$max_width\"\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/sdl1.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sdl1\"\nrp_module_desc=\"SDL 1.2.15 with rpi fixes and dispmanx\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/libsdl-org/SDL-1.2/main/COPYING\"\nrp_module_section=\"depends\"\nrp_module_flags=\"!all dispmanx\"\n\nfunction get_pkg_ver_sdl1() {\n    local basever\n    local revision\n\n    if [[ \"$__os_debian_ver\" -eq 9 ]]; then\n        basever=\"1.2.15+dfsg1\"\n        revision=\"4\"\n    elif [[ \"$__os_debian_ver\" -ge 10 ]]; then\n        basever=\"1.2.15+dfsg2\"\n        revision=\"6\"\n    else\n        basever=\"1.2.15\"\n        revision=\"10\"\n    fi\n\n    if [[ \"$1\" == \"source\" ]]; then\n        echo \"$basever-$revision\"\n    elif [[ \"$1\" == \"base\" ]]; then\n        echo \"$basever\"\n    else\n        echo \"$basever-$(($revision + 3))rpi\"\n    fi\n}\n\nfunction _get_arch_sdl1() {\n    isPlatform \"arm\" && echo \"armhf\"\n    isPlatform \"aarch64\" && echo \"arm64\"\n}\n\nfunction depends_sdl1() {\n    getDepends debhelper dh-autoreconf devscripts libx11-dev libxext-dev libxt-dev libxv-dev x11proto-core-dev libaudiofile-dev libpulse-dev libgl1-mesa-dev libasound2-dev libcaca-dev libdirectfb-dev libglu1-mesa-dev libraspberrypi-dev\n}\n\nfunction sources_sdl1() {\n    local files=()\n    if [[ \"$__os_debian_ver\" -eq 9 ]]; then\n        files+=(libsdl1.2_$(get_pkg_ver_sdl1 base).orig.tar.xz)\n    else\n        files+=(libsdl1.2_$(get_pkg_ver_sdl1 base).orig.tar.gz)\n    fi\n    files+=(\n        libsdl1.2_$(get_pkg_ver_sdl1 source).dsc\n        libsdl1.2_$(get_pkg_ver_sdl1 source).debian.tar.xz\n    )\n    local file\n    for file in \"${files[@]}\"; do\n        download \"http://mirrordirector.raspbian.org/raspbian/pool/main/libs/libsdl1.2/$file\" \"$file\"\n    done\n    dpkg-source -x libsdl1.2_$(get_pkg_ver_sdl1 source).dsc\n\n    cd libsdl1.2-$(get_pkg_ver_sdl1 base)\n    # add fixes from https://github.com/RetroPie/sdl1/compare/master...rpi\n    download \"https://github.com/RetroPie/sdl1/compare/master...rpi.diff\" \"debian/patches/rpi.diff\"\n    echo \"rpi.diff\" >>debian/patches/series\n    # force building without tslib on Jessie (as Raspbian Jessie has tslib, but Debian Jessie doesn't and we want cross compatibility\n    sed -i \"s/--enable-video-caca/--enable-video-caca --disable-input-tslib/\" debian/rules\n    DEBEMAIL=\"Jools Wills <buzz@exotica.org.uk>\" dch -v $(get_pkg_ver_sdl1) \"Added rpi fixes and dispmanx support from https://github.com/RetroPie/sdl1/compare/master...rpi\"\n}\n\nfunction build_sdl1() {\n    cd libsdl1.2-$(get_pkg_ver_sdl1 base)\n    dpkg-buildpackage\n    local dest=\"$__tmpdir/archives/$__binary_path\"\n    mkdir -p \"$dest\"\n\n    local file\n    for file in ../*.deb; do\n        if gpg --list-secret-keys \"$__gpg_signing_key\" &>/dev/null; then\n            signFile \"$file\" || return 1\n            cp \"${file}.asc\" \"$dest/\"\n        fi\n        cp ../*.deb \"$dest/\"\n    done\n}\n\nfunction install_sdl1() {\n    local arch=\"$(_get_arch_sdl1)\"\n    # if the packages don't install completely due to missing dependencies the apt-get -y -f install will correct it\n    if ! dpkg -i libsdl1.2debian_$(get_pkg_ver_sdl1)_${arch}.deb libsdl1.2-dev_$(get_pkg_ver_sdl1)_${arch}.deb; then\n        apt-get -y -f --no-install-recommends install\n    fi\n    echo \"libsdl1.2-dev hold\" | dpkg --set-selections\n}\n\n\nfunction __binary_url_sdl1() {\n    rp_hasBinaries && echo \"$__binary_url/libsdl1.2debian_$(get_pkg_ver_sdl1)_$(_get_arch_sdl1).deb\"\n}\n\nfunction install_bin_sdl1() {\n    local arch=\"$(_get_arch_sdl1)\"\n    local tmp=\"$(mktemp -d)\"\n    pushd \"$tmp\" >/dev/null\n    local ret=1\n    if downloadAndVerify \"$__binary_url/libsdl1.2debian_$(get_pkg_ver_sdl1)_${arch}.deb\" && \\\n       downloadAndVerify \"$__binary_url/libsdl1.2-dev_$(get_pkg_ver_sdl1)_${arch}.deb\"; then\n        install_sdl1\n        ret=0\n    fi\n    popd >/dev/null\n    rm -rf \"$tmp\"\n    return \"$ret\"\n}\n\nfunction remove_sdl1() {\n    apt-get remove -y --allow-change-held-packages libsdl1.2-dev libsdl1.2debian\n    apt-get autoremove -y\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/sdl12-compat.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sdl12-compat\"\nrp_module_desc=\"SDL1.2 compatibility layer that uses SDL2 under the hood\"\nrp_module_help=\"Provides a binary and source compatible API for programs written against SDL 1.2, but it uses SDL 2.0 behind the scenes\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/libsdl-org/sdl12-compat/main/LICENSE.txt\"\nrp_module_repo=\"git https://github.com/libsdl-org/sdl12-compat :_version_sdl12-compat\"\nrp_module_section=\"depends\"\nrp_module_flags=\"!x11\"\n\nfunction _version_sdl12-compat() {\n    local ver=\"1.2.68\"\n    if [[ \"$1\" == \"short\" ]]; then\n        echo $ver\n    else\n        echo \"release-$ver\"\n    fi\n}\nfunction depend_sdl12-compat() {\n    getDepends libsdl2-dev cmake\n}\n\nfunction sources_sdl12-compat() {\n    gitPullOrClone\n}\n\nfunction build_sdl12-compat() {\n    cmake -DSDL12TESTS=OFF -DSDL12DEVEL=OFF .\n    make\n    md_ret_require=\"$md_build/libSDL-1.2.so.$(_version_sdl12-compat short)\"\n}\n\nfunction install_sdl12-compat() {\n    md_ret_files=(\n        libSDL-1.2.so.\"$(_version_sdl12-compat short)\"\n        README.md\n        LICENSE.txt\n    )\n}\n\nfunction configure_sdl12-compat() {\n    ldconfig -nN \"$md_inst\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/sdl2.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sdl2\"\nrp_module_desc=\"SDL (Simple DirectMedia Layer) v2.x\"\nrp_module_licence=\"ZLIB https://raw.githubusercontent.com/libsdl-org/SDL/main/LICENSE.txt\"\nrp_module_section=\"depends\"\nrp_module_flags=\"\"\n\nfunction get_ver_sdl2() {\n    if [[ \"$__os_debian_ver\" -ge 11 ]]; then\n        echo \"2.32.10\"\n    else\n        echo \"2.0.10\"\n    fi\n}\n\nfunction get_pkg_ver_sdl2() {\n    local ver=\"$(get_ver_sdl2)\"\n    if [[ \"$__os_debian_ver\" -ge 11 ]]; then\n        ver+=\"+1\"\n    else\n        ver+=\"+5\"\n    fi\n    isPlatform \"rpi\" && ver+=\"rpi\"\n    isPlatform \"mali\" && ver+=\"mali\"\n    echo \"$ver\"\n}\n\nfunction get_arch_sdl2() {\n    echo \"$(dpkg --print-architecture)\"\n}\n\nfunction _list_depends_sdl2() {\n    # Dependencies from the debian package control + additional dependencies for the pi (some are excluded like dpkg-dev as they are\n    # already covered by the build-essential package retropie relies on.\n    local depends=(libasound2-dev libudev-dev libibus-1.0-dev libdbus-1-dev fcitx-libs-dev libsndio-dev libsamplerate0-dev)\n    # these were removed by a PR for vero4k support (cannot test). Needed though at least for for RPI and X11\n    ! isPlatform \"vero4k\" && depends+=(libx11-dev libxcursor-dev libxext-dev libxi-dev libxinerama-dev libxkbcommon-dev libxrandr-dev libxss-dev libxt-dev libxv-dev libxxf86vm-dev libgl1-mesa-dev)\n    isPlatform \"gles\" || isPlatform \"gl\" && depends+=(libegl1-mesa-dev libgles2-mesa-dev)\n    isPlatform \"gl\" || isPlatform \"rpi\" && depends+=(libgl1-mesa-dev libglu1-mesa-dev)\n    isPlatform \"kms\" || isPlatform \"rpi\" && depends+=(libdrm-dev libgbm-dev)\n    isPlatform \"x11\" && depends+=(libpulse-dev libwayland-dev)\n\n    echo \"${depends[@]}\"\n}\n\nfunction depends_sdl2() {\n    # install additional packages that are needed, but may be unsuitable as debian package dependencies due to distribution oddities\n    local depends=(devscripts debhelper dh-autoreconf)\n\n    isPlatform \"mali\" && depends+=(mali-fbdev)\n    isPlatform \"dispmanx\" && depends+=(libraspberrypi-dev)\n    isPlatform \"vero4k\" && depends+=(vero3-userland-dev-osmc)\n\n    getDepends $(_list_depends_sdl2) \"${depends[@]}\"\n}\n\nfunction sources_sdl2() {\n    local ver=\"$(get_ver_sdl2)\"\n    local pkg_ver=\"$(get_pkg_ver_sdl2)\"\n    local branch=\"retropie-${ver}\"\n\n    gitPullOrClone \"$md_build/$pkg_ver\" https://github.com/RetroPie/SDL.git \"$branch\"\n    cd \"$pkg_ver\"\n    DEBEMAIL=\"Jools Wills <buzz@exotica.org.uk>\" dch -v \"$pkg_ver\" \"SDL $ver configured for the $__platform\"\n}\n\nfunction build_sdl2() {\n    local conf_flags=()\n    local conf_depends=( $(_list_depends_sdl2) )\n\n    cd \"$(get_pkg_ver_sdl2)\"\n\n    if isPlatform \"vero4k\"; then\n        # remove harmful (mesa) and un-needed (X11) dependencies from debian package control\n        sed -i '/^\\s*lib.*x\\|mesa/ d' ./debian/control\n        # disable vulkan and X11 video support\n        conf_flags+=(\"--disable-video-x11\")\n    fi\n    isPlatform \"vulkan\" && conf_flags+=(\"--enable-video-vulkan\") || conf_flags+=(\"--disable-video-vulkan\")\n    isPlatform \"mali\" && conf_flags+=(\"--enable-video-mali\" \"--disable-video-opengl\")\n    isPlatform \"dispmanx\" && conf_flags+=(\"--enable-video-rpi\") || conf_flags+=(\"--disable-video-rpi\")\n    isPlatform \"kms\" || isPlatform \"rpi\" && conf_flags+=(\"--enable-video-kmsdrm\")\n\n    # format debian package dependencies into comma-separated list\n    conf_depends=( \"${conf_depends[@]/%/,}\" )\n\n    sed -i 's/libgl1-mesa-dev,/libgl1-mesa-dev, '\"${conf_depends[*]}\"'/' ./debian/control\n    sed -i 's/confflags =/confflags = '\"${conf_flags[*]}\"' \\\\\\n/' ./debian/rules\n\n    if isPlatform \"rpi\" && [[ -d \"/opt/vc/include\" ]]; then\n        # move proprietary videocore headers\n        sed -i -e 's/\\\"EGL/\\\"brcmEGL/g' -e 's/\\\"GLES/\\\"brcmGLES/g' ./src/video/raspberry/SDL_rpivideo.h\n        sed -i -e 's#<EGL/eglplatform#<brcmEGL/eglplatform#g' configure\n        mv /opt/vc/include/EGL /opt/vc/include/brcmEGL\n        mv /opt/vc/include/GLES /opt/vc/include/brcmGLES\n        mv /opt/vc/include/GLES2 /opt/vc/include/brcmGLES2\n    fi\n\n    # using the videocore pkgconfig will cause unwanted linkage, so disable it!\n    PKG_CONFIG_PATH= dpkg-buildpackage -b\n\n    if isPlatform \"rpi\" && [[ -d \"/opt/vc/include\" ]]; then\n        # restore proprietary headers\n        mv /opt/vc/include/brcmEGL /opt/vc/include/EGL\n        mv /opt/vc/include/brcmGLES /opt/vc/include/GLES\n        mv /opt/vc/include/brcmGLES2 /opt/vc/include/GLES2\n    fi\n\n    md_ret_require=\"$md_build/libsdl2-dev_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb\"\n    local dest=\"$__tmpdir/archives/$__binary_path\"\n    mkdir -p \"$dest\"\n\n    local file\n    for file in ../*.deb; do\n        if gpg --list-secret-keys \"$__gpg_signing_key\" &>/dev/null; then\n            signFile \"$file\" || return 1\n            cp \"${file}.asc\" \"$dest/\"\n        fi\n        cp ../*.deb \"$dest/\"\n    done\n}\n\nfunction remove_old_sdl2() {\n    # remove our old libsdl2 packages\n    hasPackage libsdl2 && dpkg --remove libsdl2 libsdl2-dev\n}\n\nfunction install_sdl2() {\n    remove_old_sdl2\n    # if the packages don't install completely due to missing dependencies the apt-get -y -f install will correct it\n    if ! dpkg -i libsdl2-2.0-0_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb libsdl2-dev_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb; then\n        apt-get -y -f --no-install-recommends install\n    fi\n    echo \"libsdl2-dev hold\" | dpkg --set-selections\n}\n\nfunction __binary_url_sdl2() {\n    rp_hasBinaries && echo \"$__binary_url/libsdl2-dev_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb\"\n}\n\nfunction install_bin_sdl2() {\n    local tmp=\"$(mktemp -d)\"\n    pushd \"$tmp\" >/dev/null\n    local ret=1\n    if downloadAndVerify \"$__binary_url/libsdl2-dev_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb\" && \\\n       downloadAndVerify \"$__binary_url/libsdl2-2.0-0_$(get_pkg_ver_sdl2)_$(get_arch_sdl2).deb\"; then\n        install_sdl2\n        ret=0\n    fi\n    popd >/dev/null\n    rm -rf \"$tmp\"\n    return \"$ret\"\n}\n\nfunction revert_sdl2() {\n    aptUpdate\n    local packaged=\"$(apt-cache madison libsdl2-dev | cut -d\" \" -f3 | head -n1)\"\n    if ! aptInstall --allow-downgrades --allow-change-held-packages libsdl2-2.0-0=\"$packaged\" libsdl2-dev=\"$packaged\"; then\n        md_ret_errors+=(\"Failed to revert to OS packaged sdl2 versions\")\n    fi\n}\n\nfunction remove_sdl2() {\n    apt-get remove -y --allow-change-held-packages libsdl2-dev libsdl2-2.0-0\n    apt-get autoremove -y\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/sixaxis.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"sixaxis\"\nrp_module_desc=\"Helper service for official and third-party DualShock controllers (ps3controller replacement)\"\nrp_module_help=\"For Shanwan/GASIA third-party controllers, enable third-party support in the configuration options.\\n\\nTo pair controllers, use the RetroPie Bluetooth menu, choose 'Register and Connect...', then follow the on-screen instructions.\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/RetroPie/sixaxis/master/COPYING\"\nrp_module_repo=\"git https://github.com/RetroPie/sixaxis.git master\"\nrp_module_section=\"driver\"\n\nfunction depends_sixaxis() {\n    getDepends checkinstall libevdev-tools\n\n    # add special check for presence of sixaxis plugin, and restart bluetooth stack if necessary\n    if ! hasPackage \"libbluetooth3\"; then\n        getDepends libbluetooth3\n        service bluetooth restart\n    fi\n\n    rp_callModule ps3controller remove\n}\n\nfunction sources_sixaxis() {\n    gitPullOrClone\n}\n\nfunction build_sixaxis() {\n    make clean\n    make\n    md_ret_require=\"$md_build/bins/sixaxis-timeout\"\n}\n\nfunction gui_sixaxis() {\n    local sixaxis_config=\"$md_conf_root/all/sixaxis_timeout.cfg\"\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local options=(\n        1 \"Enable support for third-party controllers\"\n        2 \"Disable support for third-party controllers\"\n        3 \"Configure controller timeout\"\n    )\n    local timeout_options=(\n        0 \"No timeout\"\n        300 \"5 minutes\"\n        600 \"10 minutes\"\n        900 \"15 minutes\"\n        1200 \"20 minutes\"\n        1800 \"30 minutes\"\n    )\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rp_callModule \"customhidsony\"\n                    ;;\n                2)  rp_callModule \"customhidsony\" remove\n                    ;;\n                3)\n                    local timeout_choice=$(\"${cmd[@]}\" \"${timeout_options[@]}\" 2>&1 >/dev/tty)\n                    if [[ -n \"$timeout_choice\" ]] && [[ -f \"$sixaxis_config\" ]]; then\n                        case \"$timeout_choice\" in\n                            *)\n                                iniConfig \"=\" \"\" \"$sixaxis_config\"\n                                iniSet \"SIXAXIS_TIMEOUT\" \"$timeout_choice\"\n                                systemctl restart sixaxis@/* &>/dev/null\n                                ;;\n                        esac\n                    fi\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction install_sixaxis() {\n    checkinstall -y --fstrans=no\n}\n\nfunction configure_sixaxis() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    local sixaxis_config=\"$(mktemp)\"\n\n    echo \"# Set your preferred controller timeout in seconds (0 to disable)\" >\"$sixaxis_config\"\n    iniConfig \"=\" \"\" \"$sixaxis_config\"\n    iniSet \"SIXAXIS_TIMEOUT\" \"600\"\n    copyDefaultConfig \"$sixaxis_config\" \"$md_conf_root/all/sixaxis_timeout.cfg\"\n    rm \"$sixaxis_config\"\n}\n\nfunction remove_sixaxis() {\n    dpkg --purge sixaxis\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/skyscraper.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"skyscraper\"\nrp_module_desc=\"Scraper for EmulationStation\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/Gemba/skyscraper/master/LICENSE\"\nrp_module_repo=\"git https://github.com/Gemba/skyscraper :_get_branch_skyscraper\"\nrp_module_section=\"opt\"\n\nfunction _get_branch_skyscraper() {\n    download https://api.github.com/repos/Gemba/skyscraper/releases/latest - | grep -m 1 tag_name | cut -d\\\" -f4\n}\n\nfunction depends_skyscraper() {\n    local deps=(p7zip-full)\n    if [[ \"$__os_debian_ver\" -ge 12 ]]; then\n        deps+=(qt6-base-dev qmake6 qt6-base-dev-tools libqt6sql6-sqlite)\n    else\n        deps+=(qtbase5-dev qtchooser qt5-qmake qtbase5-dev-tools libqt5sql5-sqlite)\n    fi\n    getDepends \"${deps[@]}\"\n}\n\nfunction sources_skyscraper() {\n    gitPullOrClone\n}\n\nfunction build_skyscraper() {\n    rm --force .qmake.stash\n    if [[ \"$__os_debian_ver\" -ge 12 ]]; then\n        qmake6\n    else\n        QT_SELECT=5 qmake\n    fi\n    make\n    md_ret_require=\"$md_build/Skyscraper\"\n}\n\nfunction install_skyscraper() {\n    local config_files=($(_config_files_skyscraper))\n\n    md_ret_files=(\n        'docs'\n        'LICENSE'\n        'README.md'\n        'Skyscraper'\n        'supplementary/scraperdata/check_screenscraper_json_to_idmap.py'\n        'supplementary/scraperdata/convert_platforms_json.py'\n        'supplementary/scraperdata/deepdiff_peas_jsonfiles.py'\n        'supplementary/scraperdata/mdb2sqlite.sh'\n        'supplementary/scraperdata/peas_and_idmap_verify.py'\n        'supplementary/scraperdata/README-Skyscraper-Scripts.md'\n    )\n    local ver=$(_get_branch_skyscraper)\n    if compareVersions \"$ver\" ge \"3.19.0\"; then\n        md_ret_files+=(\n            'supplementary/scraperdata/peas-schema.json'\n            'supplementary/scraperdata/peas_validate_with_json_schema.py'\n        )\n    fi\n    md_ret_files+=(\"${config_files[@]}\")\n}\n\n\nfunction _config_files_skyscraper() {\n    local config_files=(\n        'aliasMap.csv'\n        'artwork.xml.example1'\n        'artwork.xml.example2'\n        'artwork.xml.example3'\n        'artwork.xml.example4'\n        'artwork.xml'\n        'cache/priorities.xml.example'\n        'config.ini.example'\n        'hints.xml'\n        'import'\n        'mameMap.csv'\n        'mobygames_platforms.json'\n        'peas.json'\n        'platforms_idmap.csv'\n        'resources'\n        'supplementary/bash-completion/Skyscraper.bash'\n        'screenscraper_platforms.json'\n        'tgdb_developers.json'\n        'tgdb_genres.json'\n        'tgdb_platforms.json'\n        'tgdb_publishers.json'\n    )\n    echo \"${config_files[@]}\"\n}\n\nfunction remove_skyscraper() {\n    md_ret_info+=(\"Skyscraper's cache in ~/.skyscraper/cache/ is not empty and is not removed.\")\n\n    # Remove possible per-user deployment introduced with v3.9.3\n    rm -f \"$home/.bash_completion.d/Skyscraper.bash\"\n\n    rm -f \"/etc/bash_completion.d/Skyscraper.bash\"\n    rm -f \"/usr/local/bin/Skyscraper\"\n}\n\n# Get the location of the cached resources folder. In v3+, this changed to 'cache'.\n# Note: the cache folder might be unavailable during first time installations\nfunction _cache_folder_skyscraper() {\n    if [[ -d \"$configdir/all/skyscraper/dbs\" ]]; then\n        echo \"dbs\"\n    else\n        echo \"cache\"\n    fi\n}\n\n# Purge all Skyscraper caches\nfunction _purge_skyscraper() {\n    local platform\n    local cache_folder=$(_cache_folder_skyscraper)\n\n    [[ ! -d \"$configdir/all/skyscraper/$cache_folder\" ]] && return\n\n    while read platform; do\n        # Find any sub-folders of the cache folder and clear them\n        _clear_platform_skyscraper \"$platform\"\n    done < <(find \"$configdir/all/skyscraper/$cache_folder\" -maxdepth 1 -mindepth 1 -type d -exec basename {} \\;)\n}\n\nfunction _clear_platform_skyscraper() {\n    local platform=\"$1\"\n    local mode=\"$2\"\n    local cache_folder=$(_cache_folder_skyscraper)\n\n    [[ ! -d \"$configdir/all/skyscraper/$cache_folder/$platform\" ]] && return\n\n    if [[ $mode == \"vacuum\" ]]; then\n        sudo -u \"$__user\" stdbuf -o0 $md_inst/Skyscraper --flags unattend -p \"$platform\" --cache vacuum\n    else\n        sudo -u \"$__user\" stdbuf -o0 $md_inst/Skyscraper --flags unattend -p \"$platform\" --cache purge:all\n    fi\n    sleep 5\n}\n\nfunction _purge_platform_skyscraper() {\n    local options=()\n    local cache_folder=$(_cache_folder_skyscraper)\n    local system\n\n    while read system; do\n        # If there is no 'db.xml' file underneath the folder, skip it, it means folder is empty\n        [[ ! -f \"$configdir/all/skyscraper/$cache_folder/$system/db.xml\" ]] && continue\n\n        # Get the size on disk of the system and show it in the select list\n        local size=$(du -sh  \"$configdir/all/skyscraper/$cache_folder/$system\" | cut -f1)\n        options+=(\"$system\" \"$size\" OFF)\n    done < <(find \"$configdir/all/skyscraper/$cache_folder\" -maxdepth 1 -mindepth 1 -type d -exec basename {} \\;)\n\n    # If not folders are found, show an info message instead of the selection list\n    if [[ ${#options[@]} -eq 0 ]]; then\n        printMsgs \"dialog\" \"Nothing to delete ! No cached platforms found in \\n$configdir/all/skyscraper/$cache_folder.\"\n        return\n    fi\n\n    local mode=\"$1\"\n    [[ -z \"$mode\" ]] && mode=\"purge\"\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --radiolist \"Select platform to $mode\" 20 60 12)\n    local platform=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n    # Exit if no platform chosen\n    [[ -z \"$platform\" ]] && return\n\n    _clear_platform_skyscraper \"$platform\" \"$@\"\n}\n\nfunction _get_ver_skyscraper() {\n    if [[ -f \"$md_inst/Skyscraper\" ]]; then\n        echo $(sudo -u \"$__user\" \"$md_inst/Skyscraper\" -h | grep 'Running Skyscraper' | cut -d' ' -f 3 | tr -d v 2>/dev/null)\n    fi\n}\n\nfunction _check_ver_skyscraper() {\n    ver=$(_get_ver_skyscraper)\n    if ! compareVersions \"$ver\" ge \"3.5\"; then\n        printMsgs \"dialog\" \"The version of Skyscraper you currently have installed is incompatible with options used by this script. Please update Skyscraper to the latest version to continue.\"\n        return 1\n    fi\n    return 0\n}\n\n# List any non-empty systems found in the ROM folder\nfunction _list_systems_skyscraper() {\n    find -L \"$romdir/\" -mindepth 1 -maxdepth 1 -type d -not -empty | sort -u\n}\n\nfunction configure_skyscraper() {\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        return\n    fi\n\n    # Check if this a first time install\n    local local_config\n    local_config=$(readlink -qn \"$home/.skyscraper\")\n\n    # Handle the cases where the user has an existing Skyscraper installation.\n    if [[ -d \"$home/.skyscraper\" && \"$local_config\" != \"$configdir/all/skyscraper\" ]]; then\n        # We have an existing Skyscraper installation, but not handled by this scriptmodule.\n        # Since the $HOME/.skyscraper folder will be moved, make sure the 'cache' and 'import' folders are moved separately\n        local f_size\n        local cache_folder=\"dbs\"\n        [[ -d \"$home/.skyscraper/cache\" ]] && cache_folder=\"cache\"\n\n        f_size=$(du --total -sm \"$home/.skyscraper/$cache_folder\" \"$home/.skyscraper/import\" 2>/dev/null | tail -n 1 | cut -f 1)\n        printMsgs \"console\" \"INFO: Moving the Cache and Import folders to new configuration folder (total: $f_size Mb)\"\n\n        local folder\n        for folder in $cache_folder import; do\n            mv \"$home/.skyscraper/$folder\" \"$home/.skyscraper-$folder\" &&\n                printMsgs \"console\" \"INFO: Moved $home/.skyscraper/$folder to $home/.skyscraper-$folder\"\n        done\n\n        # When having an existing installation, chances are the gamelist is generated in the ROMs folder\n        # Create a GUI config file with this setting pre-set.\n        iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n        iniSet \"use_rom_folder\" 1\n    fi\n\n    moveConfigDir \"$home/.skyscraper\" \"$configdir/all/skyscraper\"\n\n    # Move the Cache and Import folders back the new conf folder\n    for folder in $cache_folder import; do\n        if [[ -d \"$home/.skyscraper-$folder\" ]]; then\n            printMsgs \"console\" \"INFO: Moving \"$home/.skyscraper-$folder\" back to configuration folder\"\n            mv \"$home/.skyscraper-$folder\" \"$configdir/all/skyscraper/$folder\"\n        fi\n    done\n\n    _init_config_skyscraper\n    chown -R \"$__user\":\"$__group\" \"$configdir/all/skyscraper\"\n    chmod a+x \"$md_inst\"/*.py\n}\n\nfunction _init_config_skyscraper() {\n    local config_files=($(_config_files_skyscraper))\n\n    mkdir -p .pristine_cfgs\n    # assume new(er) install\n    for cf in \"${config_files[@]}\"; do\n        bn=${cf##*/} # cut off all folders\n        if [[ -e \"$md_inst/$bn\" ]]; then\n            cp -rf \"$md_inst/$bn\" \".pristine_cfgs/\"\n            rm -rf \"$md_inst/$bn\"\n        fi\n    done\n\n    local scraper_conf_dir=\"$configdir/all/skyscraper\"\n\n    # Make sure the 'artwork.xml' and other conf file(s) are present, but don't overwrite them on upgrades\n    local f_conf\n    for f_conf in artwork.xml aliasMap.csv peas.json platforms_idmap.csv; do\n        copyDefaultConfig \"$md_inst/.pristine_cfgs/$f_conf\" \"$scraper_conf_dir/$f_conf\"\n    done\n\n    # If we don't have a previous config.ini file, copy the example one\n    if [[ ! -f \"$scraper_conf_dir/config.ini\" ]]; then\n        cp \"$md_inst/.pristine_cfgs/config.ini.example\" \"$scraper_conf_dir/config.ini\"\n    fi\n\n    # Artwork example files, always overwrite\n    cp -f \"$md_inst/.pristine_cfgs/artwork.xml.example\"* \"$scraper_conf_dir\"\n\n    # Copy remaining resources, always overwrite\n    local resource_files=(\n        'hints.xml'\n        'mameMap.csv'\n        'mobygames_platforms.json'\n        'screenscraper_platforms.json'\n        'tgdb_developers.json'\n        'tgdb_genres.json'\n        'tgdb_platforms.json'\n        'tgdb_publishers.json'\n    )\n    local resource_file\n    for resource_file in \"${resource_files[@]}\"; do\n        cp -f \"$md_inst/.pristine_cfgs/$resource_file\" \"$scraper_conf_dir\"\n    done\n\n    # Copy the resource folder\n    cp -rf \"$md_inst/.pristine_cfgs/resources\" \"$scraper_conf_dir\"\n\n    # Create the import folders and add the definition template examples.\n    local folder\n    for folder in covers marquees screenshots textual videos wheels; do\n        mkUserDir \"$scraper_conf_dir/import/$folder\"\n    done\n    cp -rf \"$md_inst/.pristine_cfgs/import\" \"$scraper_conf_dir\"\n\n    # Create the cache folder and add the sample 'priorities.xml' file to it\n    mkUserDir \"$scraper_conf_dir/cache\"\n    cp -f \"$md_inst/.pristine_cfgs/priorities.xml.example\" \"$scraper_conf_dir/cache\"\n\n    # Deploy programmable completion script\n    cp -f \"$md_inst/.pristine_cfgs/Skyscraper.bash\" \"/etc/bash_completion.d/\"\n    # Ease of use but also needed for proper completion\n    ln -sf \"$md_inst/Skyscraper\" \"/usr/local/bin/Skyscraper\"\n\n    # Remove possible per-user deployment introduced with v3.9.3\n    rm -f \"$home/.bash_completion.d/Skyscraper.bash\"\n}\n\n# read scriptmodule's skyscraper.cfg and prepare the command line parameters\nfunction _get_clioptions_skyscraper() {\n    local system=$1\n    local scrape_module=$2\n\n    local params=()\n    local flags\n\n    iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n    eval $(_load_config_skyscraper)\n\n    [[ \"$system\" != \"<platform>\" ]] && system=\\\"$system\\\"\n\n    params+=(-p \"$system\")\n    flags=\"unattend,skipped,\"\n\n    [[ \"$download_videos\" -eq 1 ]] && flags+=\"videos,\"\n\n    [[ \"$cache_marquees\" -eq 0 ]] && flags+=\"nomarquees,\"\n\n    [[ \"$cache_covers\" -eq 0 ]] && flags+=\"nocovers,\"\n\n    [[ \"$cache_screenshots\" -eq 0 ]] && flags+=\"noscreenshots,\"\n\n    [[ \"$cache_wheels\" -eq 0 ]] && flags+=\"nowheels,\"\n\n    [[ \"$only_missing\" -eq 1 ]] && flags+=\"onlymissing,\"\n\n    [[ \"$rom_name\" -eq 1 ]] && flags+=\"forcefilename,\"\n\n    [[ \"$remove_brackets\" -eq 1 ]] && flags+=\"nobrackets,\"\n\n    if [[ \"$use_rom_folder\" -eq 1 ]]; then\n        params+=(-g \"$romdir/$system\")\n        params+=(-o \"$romdir/$system/media\")\n        # If we're saving to the ROM folder, then use relative paths in the gamelist\n        flags+=\"relative,\"\n    else\n        params+=(-g \"$home/.emulationstation/gamelists/$system\")\n        params+=(-o \"$home/.emulationstation/downloaded_media/$system\")\n    fi\n\n    # If 2nd parameter is unset, use the configured scraping source, otherwise scrape from cache.\n    # Scraping from cache means we can omit '-s' from the parameter list.\n    if [[ -z \"$scrape_module\" ]]; then\n        params+=(-s \"$scrape_source\")\n    fi\n\n    [[ \"$force_refresh\" -eq 1 ]] && params+=(--refresh)\n\n    # There will always be a ',' at the end of $flags, so let's remove it\n    flags=${flags::-1}\n\n    params+=(--flags \"$flags\")\n    echo \"${params[@]}\"\n}\n\n\n# Scrape one system, passed as parameter\nfunction _scrape_skyscraper() {\n    local system=\"$1\"\n    local scrape_module=\"$2\"\n\n    [[ -z \"$system\" ]] && return\n\n    local params\n    params=$(_get_clioptions_skyscraper \"$system\" \"$scrape_module\")\n    declare -a \"params_arr=($params)\"\n    # trap ctrl+c and return if pressed (rather than exiting retropie-setup etc)\n    trap 'trap 2; return 1' INT\n        sudo -u \"$__user\" stdbuf -o0 \"$md_inst/Skyscraper\" \"${params_arr[@]}\"\n        echo -e \"\\nCOMMAND LINE USED:\\n $md_inst/Skyscraper\" \"${params}\"\n        sleep 2\n    trap 2\n}\n\n# Scrape a list of systems, chosen by the user\nfunction _scrape_chosen_skyscraper() {\n    ! _check_ver_skyscraper && return 1\n\n    local options=()\n    local system\n    local i=1\n\n    while read system; do\n        system=${system/$romdir\\//}\n        options+=($i \"$system\" OFF)\n        ((i++))\n    done < <(_list_systems_skyscraper)\n\n    if [[ ${#options[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"No populated ROM folders were found in $romdir.\"\n        return\n    fi\n\n    local choices\n    local cmd=(dialog --backtitle \"$__backtitle\" --ok-label \"Start\" --cancel-label \"Back\" --checklist \" Select platforms for resource gathering\\n\\n\" 22 60 16)\n\n    choices=($(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty))\n\n    # Exit if nothing was chosen or Cancel was used\n    [[ ${#choices[@]} -eq 0 || $? -eq 1 ]] && return 1\n\n    # Confirm with the user that scraping can start\n    local cli=(\"$md_inst/Skyscraper \")\n    cli+=$(_get_clioptions_skyscraper \"<platform>\" \"\")\n\n    local sky_cmd\n    sky_cmd=$(echo \"${cli[@]}\" | sed 's/ -/ \\\\\\\\n -/g')\n\n    local msg=\"This will start the gathering process, which can take a long time if you have a large game collection.\\n\\n\"\n    msg+=\"You can interrupt this process anytime by pressing \\ZbCtrl+C\\Zn.\\n\\n\"\n    msg+=\"For each selected <platform> Skyscraper is run with these commandline options:\\n\\n$sky_cmd\"\n\n    dialog --clear --colors --yes-label \"Proceed\" --no-label \"Abort\" --yesno \"$msg\" 20 70 2>&1 >/dev/tty\n    [[ ! $? -eq 0 ]] && return 1\n\n    local choice\n\n    for choice in \"${choices[@]}\"; do\n        choice=\"${options[choice*3-2]}\"\n        _scrape_skyscraper \"$choice\" \"\"\n    done\n}\n\n# Generate gamelists for a list of systems, chosen by the user\nfunction _generate_chosen_skyscraper() {\n    ! _check_ver_skyscraper && return 1\n\n    local options=()\n    local system\n    local i=1\n\n    while read system; do\n        system=${system/$romdir\\//}\n        options+=($i \"$system\" OFF)\n        ((i++))\n    done < <(_list_systems_skyscraper)\n\n    if [[ ${#options[@]} -eq 0 ]] ; then\n        printMsgs \"dialog\" \"No populated ROM folders were found in $romdir.\"\n        return\n    fi\n\n    local choices\n    local cmd=(dialog --backtitle \"$__backtitle\" --ok-label \"Start\" --cancel-label \"Back\" --checklist \" Select platforms for gamelist(s) generation\\n\\n\" 22 60 16)\n\n    choices=($(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty))\n\n    # Exit if nothing was chosen or Cancel was used\n    [[ ${#choices[@]} -eq 0 || $? -eq 1 ]] && return 1\n\n    for choice in \"${choices[@]}\"; do\n        choice=\"${options[choice*3-2]}\"\n        _scrape_skyscraper \"$choice\" \"cache\"\n    done\n}\n\nfunction _load_config_skyscraper() {\n    echo \"$(loadModuleConfig \\\n        'rom_name=0' \\\n        'use_rom_folder=0' \\\n        'download_videos=0' \\\n        'cache_marquees=1' \\\n        'cache_covers=1' \\\n        'cache_wheels=1' \\\n        'cache_screenshots=1' \\\n        'scrape_source=screenscraper' \\\n        'remove_brackets=0' \\\n        'force_refresh=0' \\\n        'only_missing=0'\n    )\"\n}\n\n# Try to guess the most appropriate editor. On Debian derivatives, we have `sensible-editor` for that.\nfunction _open_editor_skyscraper() {\n    local editor\n\n    if [[ -n $(command -v sensible-editor) ]]; then\n        sudo -u \"$__user\" sensible-editor \"$1\" > /dev/tty < /dev/tty\n    else\n        editor=\"${EDITOR:-nano}\"\n        sudo -u \"$__user\" $editor \"$1\" > /dev/tty < /dev/tty\n    fi\n}\n\nfunction _gui_advanced_skyscraper() {\n    declare -A help_strings_adv\n\n    iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n    eval $(_load_config_skyscraper)\n\n    help_strings_adv=(\n        [E]=\"Opens the configuration file \\Zbconfig.ini\\Zn in an editor.\"\n        [F]=\"Opens the artwork definition file \\Zbartwork.xml\\Zn in an editor.\"\n        [G]=\"Opens the game alias configuration file \\ZbaliasMap.csv\\Zn in an editor.\"\n    )\n\n    while true; do\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --help-button --colors --no-collapse --default-item \"$default\" --ok-label \"Ok\" --cancel-label \"Back\" --title \"Advanced options\" --menu \"    EXPERT - edit configurations\\n\" 14 50 5)\n        local options=()\n\n        options+=(E \"Edit 'config.ini'\")\n        options+=(F \"Edit 'artwork.xml'\")\n        options+=(G \"Edit 'aliasMap.csv'\")\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 > /dev/tty)\n\n        if [[ -n \"$choice\" ]]; then\n            local default=\"$choice\"\n\n            case \"$choice\" in\n\n                E)\n                    _open_editor_skyscraper \"$configdir/all/skyscraper/config.ini\"\n                    ;;\n\n                F)\n                    _open_editor_skyscraper \"$configdir/all/skyscraper/artwork.xml\"\n                    ;;\n\n                G)\n                    _open_editor_skyscraper \"$configdir/all/skyscraper/aliasMap.csv\"\n                    ;;\n\n                HELP*)\n                    # Retain choice\n                    default=\"${choice/HELP /}\"\n                    if [[ ! -z \"${help_strings_adv[${default}]}\" ]]; then\n                    dialog --colors --no-collapse --ok-label \"Close\" --msgbox \"${help_strings_adv[${default}]}\" 22 65 >&1\n                    fi\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction gui_skyscraper() {\n    if pgrep \"emulationstatio\" >/dev/null; then\n        printMsgs \"dialog\" \"This scraper must not be run while EmulationStation is running or the scraped data will be overwritten.\\n\\nPlease quit EmulationStation and run RetroPie-Setup from the terminal:\\n\\n sudo \\$HOME/RetroPie-Setup/retropie_setup.sh\"\n        return\n    fi\n\n    iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n    eval $(_load_config_skyscraper)\n    chown \"$__user\":\"$__group\" \"$configdir/all/skyscraper.cfg\"\n\n    local -a s_source\n    local -a s_source_names\n    declare -A help_strings\n\n    s_source=(\n        [1]=screenscraper\n        [2]=arcadedb\n        [3]=thegamesdb\n        [4]=mobygames\n        [5]=openretro\n        [6]=igdb\n        [7]=worldofspectrum\n    )\n    s_source+=(\n        [10]=esgamelist\n        [11]=import\n    )\n\n    s_source_names=(\n        [1]=ScreenScraper\n        [2]=ArcadeDB\n        [3]=TheGamesDB\n        [4]=MobyGames\n        [5]=OpenRetro\n        [6]=\"Internet Game Database\"\n        [7]=\"World of Spectrum\"\n    )\n    s_source_names+=(\n        [10]=\"EmulationStation Gamelist\"\n        [11]=\"Import Folder\"\n    )\n\n    local ver\n    local lastest_ver\n\n    # Help strings for this GUI\n    help_strings=(\n        [1]=\"Gather resources and cache them for the platforms found in \\Zb$romdir\\Zn.\\nRuns the scraper to download the information and media from the selected gathering source.\"\n        [2]=\"Select the source for ROM scraping. Supported sources:\\n\\ZbONLINE\\Zn\\n * ScreenScraper (screenscraper.fr)\\n * TheGamesDB (thegamesdb.net)\\n * OpenRetro (openretro.org)\\n * ArcadeDB (adb.arcadeitalia.net)\\n * World of Spectrum (worldofspectrum.org)\\n\\ZbLOCAL\\Zn\\n * EmulationStation Gamelist (imports data from ES gamelist)\\n * Import (imports resources in the local cache)\\n\\n\\Zb\\ZrNOTE\\Zn: Some sources require a username and password for access. These can be set per source in the \\Zbconfig.ini\\Zn configuration file.\\n\\n Skyscraper parameter: \\Zb-s <source_name>\\Zn\"\n        [3]=\"Options for resource gathering and caching sub-menu.\\nClick to open it.\"\n        [4]=\"Generate EmulationStation game lists.\\nRuns the scraper to incorporate downloaded information and media from the local cache and write them to \\Zbgamelist.xml\\Zn files to be used by EmulationStation.\"\n        [5]=\"Options for EmulationStation game list generation sub-menu.\\nClick to open it and change the options.\"\n        [V]=\"Toggle the download and caching of videos.\\nThis also toggles whether the videos will be included in the resulting gamelist.\\n\\nSkyscraper option: \\Zb--flags videos\\Zn\"\n        [A]=\"Advanced options sub-menu.\"\n        [U]=\"Check for an update to Skyscraper.\"\n    )\n\n    ver=$(_get_ver_skyscraper)\n\n    while true; do\n        [[ -z \"$ver\" ]] && ver=\"v(Git)\"\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --colors --cancel-label \"Exit\" --help-button --no-collapse --cr-wrap --default-item \"$default\" --menu \"   Skyscraper: game scraper for EmulationStation ($ver)\\\\n \\\\n\" 22 60 12)\n\n        local options=(\n            \"-\" \"GATHER and cache resources\"\n        )\n\n        local source_found=0\n        local online=\"Online\"\n        local i\n\n        options+=(\n            1 \"Gather resources\"\n        )\n\n        for i in \"${!s_source[@]}\"; do\n            if [[ \"$scrape_source\" == \"${s_source[$i]}\" ]]; then\n                [[ $i -ge 10 ]] && online=\"Local\"\n                options+=(2 \"Gather source - ${s_source_names[$i]} ($online) -->\")\n                source_found=1\n            fi\n        done\n\n        if [[ $source_found -ne 1 ]]; then\n            options+=(2 \"Gather from - Screenscraper (Online) -->\")\n            scrape_source=\"screenscraper\" # default scraping source if none found\n            iniSet \"scrape_source\" \"$scrape_source\"\n        fi\n\n        options+=(3 \"Cache options and commands -->\")\n\n        options+=(\"-\" \"GAME LIST generation\")\n        options+=(4 \"Generate game list(s)\")\n        options+=(5 \"Generate options -->\")\n\n        options+=(\"-\" \"OTHER options\")\n\n        if [[ \"$download_videos\" -eq 1 ]]; then\n            options+=(V \"Download videos (Enabled)\")\n        else\n            options+=(V \"Download videos (Disabled)\")\n        fi\n\n        options+=(A \"Advanced options -->\")\n\n        options+=(U \"Check for Updates\")\n\n        # Run the GUI\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n\n        if [[ -n \"$choice\" ]]; then\n            local default=\"$choice\"\n\n            case \"$choice\" in\n\n                1)\n                    if _scrape_chosen_skyscraper; then\n                        printMsgs \"dialog\" \"ROMs information gathered.\\nDon't forget to use 'Generate Game list(s)' to add this information to EmulationStation.\"\n                    elif [[ $? -eq 2 ]]; then\n                        printMsgs \"dialog\" \"Gathering was aborted\"\n                    fi\n                    ;;\n\n                2)\n                    # Scrape source options have a separate dialog\n                    local s_options=()\n                    local i\n\n                    for i in \"${!s_source[@]}\"; do\n                        online=\"Online:\"\n                        [[ i -ge 10 ]] && online=\"Local:\"\n\n                        if [[ \"$scrape_source\" == \"${s_source[$i]}\" ]]; then\n                            s_default=\"$online ${s_source_names[$i]}\"\n                        fi\n\n                        s_options+=(\"$online ${s_source_names[$i]}\" \"\")\n                    done\n\n                    if [[ -z \"$s_default\" ]]; then\n                        s_default=\"Online: ${s_source_names[1]}\"\n                    fi\n\n                    local s_cmd=(dialog --title \"Select Scraping source\" --default-item \"$s_default\" \\\n                        --menu \"Choose one of the available scraping sources\" 18 50 9)\n\n                    # Run the Scraper source selection dialog\n                    local scrape_source_name=$(\"${s_cmd[@]}\" \"${s_options[@]}\" 2>&1 >/dev/tty)\n\n                    # If Cancel was chosen, don't do anything\n                    [[ -z \"$scrape_source_name\" ]] && continue\n\n                    # Strip the \"XYZ:\" prefix from the chosen scraper source, then compare to our list\n                    local src=$(echo \"$scrape_source_name\" | cut -d' ' -f2-)\n\n                    for i in \"${!s_source_names[@]}\"; do\n                        [[ \"${s_source_names[$i]}\" == \"$src\" ]] && scrape_source=${s_source[$i]}\n                    done\n\n                    iniSet \"scrape_source\" \"$scrape_source\"\n                    ;;\n\n                3)\n                    _gui_cache_skyscraper\n                    ;;\n\n                4)\n                    if _generate_chosen_skyscraper \"cache\"; then\n                        printMsgs \"dialog\" \"Game list(s) generated.\"\n                    elif [[ $? -eq 2 ]]; then\n                        printMsgs \"dialog\" \"Game list generation aborted\"\n                    fi\n                    ;;\n\n                5)\n                    _gui_generate_skyscraper\n                    ;;\n\n                V)\n                    download_videos=\"$((download_videos ^ 1))\"\n                    iniSet \"download_videos\" \"$download_videos\"\n                    ;;\n\n                A)\n                    _gui_advanced_skyscraper\n                    ;;\n\n                U)\n                    local latest_ver=\"$(_get_branch_skyscraper)\"\n                    # check for update\n                    if compareVersions \"$latest_ver\" gt \"$ver\" ; then\n                        printMsgs \"dialog\" \"There is a new version available. Latest released version is $latest_ver (You are running $ver).\\n\\nYou can update the package from RetroPie-Setup -> Manage Packages\"\n                    else\n                        printMsgs \"dialog\" \"You are running the latest version ($ver).\"\n                    fi\n                    ;;\n\n                HELP*)\n                    # Retain choice when the Help button is selected\n                    default=\"${choice/HELP /}\"\n                    if [[ ! -z \"${help_strings[$default]}\" ]]; then\n                        dialog --colors --no-collapse --ok-label \"Close\" --msgbox \"${help_strings[$default]}\" 22 65 >&1\n                    fi\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction _gui_cache_skyscraper() {\n    local db_size\n    local cache_folder=$(_cache_folder_skyscraper)\n    declare -A help_strings_cache\n\n    iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n    eval $(_load_config_skyscraper)\n\n    help_strings_cache=(\n        [1]=\"Toggle whether screenshots are cached locally when scraping.\\n\\nSkyscraper option: \\Zb--flags noscreenshots\\Zn\"\n        [2]=\"Toggle whether covers are cached locally when scraping.\\n\\nSkyscraper option: \\Zb--flags nocovers\\Zn\"\n        [3]=\"Toggle whether wheels are cached locally when scraping.\\n\\nSkyscraper option: \\Zb--flags nowheels\\Zn\"\n        [4]=\"Toggle whether marquees are cached locally when scraping.\\n\\nSkyscraper option: \\Zb--flags nomarquees\\Zn\"\n        [5]=\"Enable this to only scrape files that do not already have data in the Skyscraper resource cache.\\n\\nSkyscraper option: \\Zb--flags onlymissing\\Zn\"\n        [6]=\"Force the refresh of resources in the local cache when scraping.\\n\\nSkyscraper option: \\Zb--cache refresh\\Zn\"\n        [P]=\"Purge \\ZbALL\\Zn all cached resources for all platforms.\"\n        [S]=\"Purge all cached resources for a chosen platform.\\n\\nSkyscraper option: \\Zb--cache purge:all\\Zn\"\n        [V]=\"Removes all non-used cached resources for a chosen platform (vacuum).\\n\\nSkyscraper option: \\Zb--cache vacuum\\Zn\"\n    )\n\n    while true; do\n        db_size=$(du -sh \"$configdir/all/skyscraper/$cache_folder\" 2>/dev/null | cut -f 1 || echo 0m)\n        [[ -z \"$db_size\" ]] && db_size=\"0Mb\"\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --help-button --colors --no-collapse --default-item \"$default\" --ok-label \"Ok\" --cancel-label \"Back\" --title \"Cache options and commands\" --menu \"\\n               Current cache size: $db_size\\n\\n\" 21 60 12)\n\n        local options=(\"-\" \"OPTIONS for gathering and caching\")\n\n        if [[ \"$cache_screenshots\" -eq 1 ]]; then\n            options+=(1 \"Cache screenshots (Enabled)\")\n        else\n            options+=(1 \"Cache screenshots (Disabled)\")\n        fi\n\n        if [[ \"$cache_covers\" -eq 1 ]]; then\n            options+=(2 \"Cache covers (Enabled)\")\n        else\n            options+=(2 \"Cache covers (Disabled)\")\n        fi\n\n        if [[ \"$cache_wheels\" -eq 1 ]]; then\n            options+=(3 \"Cache wheels (Enabled)\")\n        else\n            options+=(3 \"Cache wheels (Disabled)\")\n        fi\n\n        if [[ \"$cache_marquees\" -eq 1 ]]; then\n            options+=(4 \"Cache marquees (Enabled)\")\n        else\n            options+=(4 \"Cache marquees (Disabled)\")\n        fi\n\n        if [[ \"$only_missing\" -eq 1 ]]; then\n            options+=(5 \"Scrape only missing (Enabled)\")\n        else\n            options+=(5 \"Scrape only missing (Disabled)\")\n        fi\n\n        if [[ \"$force_refresh\" -eq 0 ]]; then\n            options+=(6 \"Force cache refresh (Disabled)\")\n        else\n            options+=(6 \"Force cache refresh (Enabled)\")\n        fi\n\n        options+=(\"-\" \"PURGE cache commands\")\n        options+=(V \"Vacuum chosen platform\")\n        options+=(S \"Purge chosen platform\")\n        options+=(P \"Purge all platforms(!)\")\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 > /dev/tty)\n\n        if [[ -n \"$choice\" ]]; then\n            local default=\"$choice\"\n\n            case \"$choice\" in\n\n                1)\n                    cache_screenshots=\"$((cache_screenshots ^ 1))\"\n                    iniSet \"cache_screenshots\" \"$cache_screenshots\"\n                    ;;\n\n                2)\n                    cache_covers=\"$((cache_covers ^ 1))\"\n                    iniSet \"cache_covers\" \"$cache_covers\"\n                    ;;\n\n                3)\n                    cache_wheels=\"$((cache_wheels ^ 1))\"\n                    iniSet \"cache_wheels\" \"$cache_wheels\"\n                    ;;\n\n                4)\n                    cache_marquees=\"$((cache_marquees ^ 1))\"\n                    iniSet \"cache_marquees\" \"$cache_marquees\"\n                    ;;\n\n                5)\n                    only_missing=\"$((only_missing ^ 1))\"\n                    iniSet \"only_missing\" \"$only_missing\"\n                    ;;\n\n                6)\n                    force_refresh=\"$((force_refresh ^ 1))\"\n                    iniSet \"force_refresh\" \"$force_refresh\"\n                    ;;\n\n                V)\n                    _purge_platform_skyscraper \"vacuum\"\n                    ;;\n\n                S)\n                    _purge_platform_skyscraper\n                    ;;\n\n                P)\n                    dialog --clear --defaultno --colors --yesno  \"\\Z1\\ZbAre you sure ?\\Zn\\nThis will \\Zb\\ZuERASE\\Zn all locally cached scraped resources\" 8 60 2>&1 >/dev/tty\n                    if [[ $? == 0 ]]; then\n                        _purge_skyscraper\n                    fi\n                    ;;\n\n                HELP*)\n                    # Retain choice\n                    default=\"${choice/HELP /}\"\n                    if [[ ! -z \"${help_strings_cache[${default}]}\" ]]; then\n                    dialog --colors --no-collapse --ok-label \"Close\" --msgbox \"${help_strings_cache[${default}]}\" 22 65 >&1\n                    fi\n            esac\n        else\n            break\n        fi\n    done\n}\n\nfunction _gui_generate_skyscraper() {\n    declare -A help_strings_gen\n\n    iniConfig \" = \" '\"' \"$configdir/all/skyscraper.cfg\"\n    eval $(_load_config_skyscraper)\n\n    help_strings_gen=(\n        [1]=\"Game name format used in the EmulationStation game list. Available options:\\n\\n\\ZbSource name\\Zn: use the name returned by the scraper\\n\\ZbFilename\\Zn: use the filename of the ROM as game name\\n\\nSkyscraper option: \\Zb--flags forcefilename\\Z0\"\n        [2]=\"Game name option to remove/keep the text found between '()' and '[]' in the ROMs filename.\\n\\nSkyscraper option: \\Zb--flags nobrackets\\Zn\"\n        [3]=\"Choose to save the generated 'gamelist.xml' and media in the ROMs folder. Supported options:\\n\\n\\ZbEnabled\\Zn saves the 'gamelist.xml' in the ROMs folder and the media in the 'media' sub-folder.\\n\\n\\ZbDisabled\\Zn saves the 'gamelist.xml' in \\Zu\\$HOME/.emulationstation/gamelists/<system>\\Zn and the media in \\Zu\\$HOME/.emulationstation/downloaded_media\\Zn.\\n\\n\\Zb\\ZrNOTE\\Zn: changing this option will not automatically copy the 'gamelist.xml' file and the media to the new location or remove the ones in the old location. You must do this manually.\\n\\nSkyscraper parameters: \\Zb-g <gamelist>\\Zn / \\Zb-o <path>\\Zn\"\n    )\n\n    while true; do\n\n        local cmd=(dialog --backtitle \"$__backtitle\" --help-button --colors --no-collapse --default-item \"$default\" --ok-label \"Ok\" --cancel-label \"Back\" --title \"Game list generation options\" --menu \"\\n\\n\" 13 60 5)\n        local -a options\n\n        if [[ \"$rom_name\" -eq 0 ]]; then\n            options=(1 \"ROM Names (Source name)\")\n        else\n            options=(1 \"ROM Names (Filename)\")\n        fi\n\n        if [[ \"$remove_brackets\" -eq 1 ]]; then\n            options+=(2 \"Remove bracket info (Enabled)\")\n        else\n            options+=(2 \"Remove bracket info (Disabled)\")\n        fi\n\n        if [[ \"$use_rom_folder\" -eq 1 ]]; then\n            options+=(3 \"Use ROM folders for game list & media (Enabled)\")\n        else\n            options+=(3 \"Use ROM folders for game list & media (Disabled)\")\n        fi\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 > /dev/tty)\n\n        if [[ -n \"$choice\" ]]; then\n            local default=\"$choice\"\n\n            case \"$choice\" in\n\n                1)\n                    rom_name=\"$((rom_name ^ 1))\"\n                    iniSet \"rom_name\" \"$rom_name\"\n                    ;;\n\n                2)\n                    remove_brackets=\"$((remove_brackets ^ 1))\"\n                    iniSet \"remove_brackets\" \"$remove_brackets\"\n                    ;;\n\n                3)\n                    use_rom_folder=\"$((use_rom_folder ^ 1))\"\n                    iniSet \"use_rom_folder\" \"$use_rom_folder\"\n                    ;;\n\n                HELP*)\n                    # Retain choice\n                    default=\"${choice/HELP /}\"\n                    if [[ ! -z \"${help_strings_gen[${default}]}\" ]]; then\n                    dialog --colors --no-collapse --ok-label \"Close\" --msgbox \"${help_strings_gen[${default}]}\" 22 65 >&1\n                    fi\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/snesdev/001-wiringpi-static.diff",
    "content": "diff --git a/wiringPi/Makefile b/wiringPi/Makefile\nindex 88fc48e..ee5dc9f 100644\n--- a/wiringPi/Makefile\n+++ b/wiringPi/Makefile\n@@ -78,6 +78,10 @@ $(DYNAMIC):\t$(OBJ)\n \t$Q echo \"[Link (Dynamic)]\"\n \t$Q $(CC) -shared -Wl,-soname,libwiringPi.so$(WIRINGPI_SONAME_SUFFIX) -o libwiringPi.so.$(VERSION) $(OBJ) $(LIBS)\n \n+$(STATIC):\t$(OBJ)\n+\t$Q echo \"[Link (Static)]\"\n+\t$Q $(AR) -rcs $(STATIC) $(OBJ)\n+\n .c.o:\n \t$Q echo [Compile] $<\n \t$Q $(CC) -c $(CFLAGS) $< -o $@\n@@ -86,7 +90,7 @@ $(DYNAMIC):\t$(OBJ)\n .PHONY:\tclean\n clean:\n \t$Q echo \"[Clean]\"\n-\t$Q rm -f $(OBJ) $(OBJ_I2C) *~ core tags Makefile.bak libwiringPi.*\n+\t$Q rm -f $(OBJ) $(OBJ_I2C) *~ core tags Makefile.bak libwiringPi.* $(STATIC)\n \n .PHONY:\ttags\n tags:\t$(SRC)\n"
  },
  {
    "path": "scriptmodules/supplementary/snesdev.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"snesdev\"\nrp_module_desc=\"SNESDev (Driver for the RetroPie GPIO-Adapter)\"\nrp_module_section=\"driver\"\nrp_module_repo=\"git https://github.com/MonsterJoysticks/SNESDev-RPi-Wiring-Pi.git master\"\nrp_module_flags=\"noinstclean !all rpi\"\n\n# install the latest version of WiringPi\nfunction _wiringpi_snesdev() {\n    pushd \"$md_build\"\n    gitPullOrClone wiringpi https://github.com/WiringPi/WiringPi.git\n    cd wiringpi\n    applyPatch \"$md_data/001-wiringpi-static.diff\"\n    make -C wiringPi libwiringPi.a\n    popd\n}\n\nfunction depends_snesdev() {\n    getDepends libconfuse-dev\n}\n\nfunction sources_snesdev() {\n    gitPullOrClone\n}\n\nfunction build_snesdev() {\n    local wiringpi_version\n    wiringpi_version=\"$(dpkg-query -f='${Version} ${Status}' -W wiringpi 2>/dev/null | grep installed | cut -f1 -d' ')\"\n\n    CFLAGS+=\" -Wno-incompatible-pointer-types\"\n    if [[ -z \"$wiringpi_version\" ]] || compareVersions \"$wiringpi_version\" lt 3.14; then\n        # when there's no WiringPi installed or there's an old version, build a static version and use it\n        printMsgs console \"Using locally built WiringPi library\"\n        _wiringpi_snesdev\n        make LDFLAGS=\" -L\"$md_build/wiringpi/wiringPi\"\" CFLAGS=\"$CFLAGS -I\"$md_build/wiringpi/wiringPi\"\"\n    else\n        make\n    fi\n    md_ret_require=\"$md_build/src/SNESDev\"\n}\n\nfunction install_snesdev() {\n    md_ret_files=(\n        \"src/SNESDev\"\n        \"README.md\"\n        \"supplementary/snesdev.cfg\"\n    )\n}\n\nfunction configure_snesdev() {\n    if [[ \"$md_mode\" == \"install\" ]]; then\n        install -m 0755 \"$md_inst/snesdev.cfg\" \"/etc/snesdev.cfg\"\n        # remove old drivers and service\n        [[ -f \"/usr/local/bin/SNESDev\" ]] && rm -f \"/usr/local/bin/SNESDev\"\n        update-rc.d SNESDev remove\n        rm -f /etc/init.d/SNESDev\n    fi\n}\n\nfunction _systemd_install_snesdev() {\ncat > /etc/systemd/system/snesdev.service << _EOF_\n[Unit]\nDescription=Userspace SNES GPIO Driver\n\n[Service]\nExecStart=$md_inst/SNESDev\n\n[Install]\nWantedBy=multi-user.target\n_EOF_\n\n    systemctl daemon-reload\n    systemctl -q enable snesdev.service\n}\n\nfunction _systemd_uninstall_snesdev() {\n    if systemctl -q is-enabled snesdev.service 2>/dev/null; then\n        systemctl stop snesdev.service\n        systemctl -q disable snesdev.service\n    fi\n    [[ -f \"/etc/systemd/system/snesdev.service\" ]] && rm \"/etc/systemd/system/snesdev.service\"\n}\n# start SNESDev on boot and configure RetroArch input settings\nfunction enable_at_start_snesdev() {\n    local mode=\"$1\"\n    iniConfig \"=\" \"\" \"/etc/snesdev.cfg\"\n    clear\n    printHeading \"Enabling SNESDev on boot.\"\n\n    case \"$mode\" in\n        1)\n            iniSet \"button_enabled\" \"0\"\n            iniSet \"gamepad1_enabled\" \"1\"\n            iniSet \"gamepad2_enabled\" \"1\"\n            _systemd_install_snesdev\n            ;;\n        2)\n            iniSet \"button_enabled\" \"1\"\n            iniSet \"gamepad1_enabled\" \"0\"\n            iniSet \"gamepad2_enabled\" \"0\"\n            _systemd_install_snesdev\n            ;;\n        3)\n            iniSet \"button_enabled\" \"1\"\n            iniSet \"gamepad1_enabled\" \"1\"\n            iniSet \"gamepad2_enabled\" \"1\"\n            _systemd_install_snesdev\n            ;;\n        *)\n            echo \"[enable_at_start_snesdev] I do not understand what is going on here.\"\n            ;;\n    esac\n\n}\n\nfunction set_adapter_version_snesdev() {\n    local ver=\"$1\"\n    iniConfig \"=\" \"\" \"/etc/snesdev.cfg\"\n    if [[ \"$ver\" -eq 1 ]]; then\n        iniSet \"adapter_version\" \"1x\"\n    else\n        iniSet \"adapter_version\" \"2x\"\n    fi\n}\n\nfunction remove_snesdev() {\n    _systemd_uninstall_snesdev\n    # remove old versions if found\n    [[ -f \"/usr/local/bin/SNESDev\" ]] && rm -f \"/usr/local/bin/SNESDev\"\n}\n\nfunction gui_snesdev() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local options=(\n        1 \"Enable SNESDev on boot and SNESDev keyboard mapping (polling pads and button)\"\n        2 \"Enable SNESDev on boot and SNESDev keyboard mapping (polling only pads)\"\n        3 \"Enable SNESDev on boot and SNESDev keyboard mapping (polling only button)\"\n        4 \"Switch to adapter version 1.X\"\n        5 \"Switch to adapter version 2.X\"\n        D \"Disable SNESDev on boot and SNESDev keyboard mapping\"\n    )\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        case \"$choice\" in\n            1)\n                enable_at_start_snesdev 3\n                printMsgs \"dialog\" \"Enabled SNESDev on boot (polling pads and button).\"\n                ;;\n            2)\n                enable_at_start_snesdev 1\n                printMsgs \"dialog\" \"Enabled SNESDev on boot (polling only pads).\"\n                ;;\n            3)\n                enable_at_start_snesdev 2\n                printMsgs \"dialog\" \"Enabled SNESDev on boot (polling only button).\"\n                ;;\n            4)\n                set_adapter_version_snesdev 1\n                printMsgs \"dialog\" \"Switched to adapter version 1.X.\"\n                ;;\n            5)\n                set_adapter_version_snesdev 2\n                printMsgs \"dialog\" \"Switched to adapter version 2.X.\"\n                ;;\n            D)\n                _systemd_uninstall_snesdev\n                printMsgs \"dialog\" \"Disabled SNESDev on boot.\"\n                ;;\n        esac\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/splashscreen/05-splash.sh",
    "content": "PID_FILE=/dev/shm/rp-splashscreen.pid\nif [ \"`tty`\" = \"/dev/tty1\" ] && [ -z \"$DISPLAY\" ] && [ -f \"$PID_FILE\" ]; then\n    PID=`cat $PID_FILE`\n    if ps -p $PID >/dev/null; then\n        kill $PID >/dev/null 2>&1\n    fi\n    rm $PID_FILE\nfi\n"
  },
  {
    "path": "scriptmodules/supplementary/splashscreen/asplashscreen.sh",
    "content": "#!/bin/sh\n\nROOTDIR=\"\"\nDATADIR=\"\"\nREGEX_VIDEO=\"\"\nREGEX_IMAGE=\"\"\nCMD=\"vlc --intf dummy --quiet --no-video-title-show --play-and-exit\"\nCMD_OPTS=\"\"\n\n# VLC doesn't detect the connected HDMI port, defaulting to output on the 1st port\n# do the detection ourselves and pass the HDMI port as a parameter\ncase \"$CMD_OPTS\" in\n    *mmal*)\n        HDMI_PORT=\"$(tvservice -l | grep -o -P -m1 \"HDMI \\K(.*)\")\"\n        [ -n \"$HDMI_PORT\" ] && CMD_OPTS=\"$CMD_OPTS --mmal-display hdmi-$(($HDMI_PORT+1))\"\n        ;;\nesac\n\n# Load user settings\n. /opt/retropie/configs/all/splashscreen.cfg\n\ndo_start () {\n    local config=\"/etc/splashscreen.list\"\n    local line\n    local re=\"$REGEX_VIDEO\\|$REGEX_IMAGE\"\n    local cmd=\"$CMD $CMD_OPTS\"\n    case \"$RANDOMIZE\" in\n        retropie)\n            line=\"$(find \"$ROOTDIR/supplementary/splashscreen\" -type f | grep \"$re\" | shuf -n1)\"\n            ;;\n        custom)\n            line=\"$(find \"$DATADIR/splashscreens\" -type f | grep \"$re\" | shuf -n1)\"\n            ;;\n        all)\n            line=\"$(find \"$ROOTDIR/supplementary/splashscreen\" \"$DATADIR/splashscreens\" -type f | grep \"$re\" | shuf -n1)\"\n            ;;\n        list)\n            line=\"$(cat \"$config\" | shuf -n1)\"\n            ;;\n    esac\n\n    if [ \"$RANDOMIZE\" = \"disabled\" ]; then\n        local count=$(wc -l <\"$config\")\n    else\n        local count=1\n    fi\n\n    [ $count -eq 0 ] && count=1\n    [ $count -gt 12 ] && count=12\n\n    # Default duration is 12 seconds, check if configured otherwise\n    [ -z \"$DURATION\" ] && DURATION=12\n    local delay=$((DURATION/count))\n\n    cmd=\"$cmd --image-duration $delay\"\n    local pid\n    if [ \"$RANDOMIZE\" = \"disabled\" ]; then\n        tr \"\\n\" \"\\0\" <\"$config\" | xargs -0 $cmd & 2>/dev/null\n        # get cmd pid (child of xargs)\n        pid=`pgrep -P $!`\n    else\n        $cmd \"$line\" & 2>/dev/null\n        pid=$!\n    fi\n    echo \"$pid\" >/dev/shm/rp-splashscreen.pid\n\n    exit 0\n}\n\ncase \"$1\" in\n    start|\"\")\n        do_start\n        ;;\n    restart|reload|force-reload)\n        echo \"Error: argument '$1' not supported\" >&2\n        exit 3\n       ;;\n    stop)\n        # No-op\n        ;;\n    status)\n        exit 0\n        ;;\n    *)\n        echo \"Usage: asplashscreen [start|stop]\" >&2\n        exit 3\n        ;;\nesac\n"
  },
  {
    "path": "scriptmodules/supplementary/splashscreen/rp-vlc",
    "content": "Package: vlc*\nPin: origin archive.raspberrypi.org\nPin-Priority: 1001\n\nPackage: libvlc*\nPin: origin archive.raspberrypi.org\nPin-Priority: 1001\n"
  },
  {
    "path": "scriptmodules/supplementary/splashscreen.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"splashscreen\"\nrp_module_desc=\"Configure Splashscreen\"\nrp_module_section=\"main\"\nrp_module_repo=\"git https://github.com/RetroPie/retropie-splashscreens.git master\"\nrp_module_flags=\"noinstclean !all rpi !osmc !xbian\"\n\nfunction _update_hook_splashscreen() {\n    # make sure splashscreen is always up to date if updating just RetroPie-Setup\n    if rp_isInstalled \"$md_id\"; then\n        install_bin_splashscreen\n        configure_splashscreen\n    fi\n}\n\nfunction _image_exts_splashscreen() {\n    echo '\\.bmp\\|\\.jpg\\|\\.jpeg\\|\\.gif\\|\\.png\\|\\.ppm\\|\\.tiff\\|\\.webp'\n}\n\nfunction _video_exts_splashscreen() {\n    echo '\\.avi\\|\\.mov\\|\\.mp4\\|\\.mkv\\|\\.3gp\\|\\.mpg\\|\\.mp3\\|\\.wav\\|\\.m4a\\|\\.aac\\|\\.ogg\\|\\.flac'\n}\n\nfunction depends_splashscreen() {\n    # pin archive.raspberrypi.org version of VLC on buster as updated \"security\" vanilla version doesn't have mmal output\n    if [[ \"$__os_debian_ver\" -lt 11 ]]; then\n        cp \"$md_data/rp-vlc\" /etc/apt/preferences.d/\n        # try and install vlc to force downgrade\n        aptInstall --allow-downgrades vlc\n    else\n        getDepends vlc\n    fi\n}\n\nfunction install_bin_splashscreen() {\n    cat > \"/etc/systemd/system/asplashscreen.service\" << _EOF_\n[Unit]\nDescription=Show custom splashscreen\nDefaultDependencies=no\nAfter=console-setup.service\nWants=console-setup.service\nConditionPathExists=$md_inst/asplashscreen.sh\n\n[Service]\nType=oneshot\nUser=$__user\nExecStart=$md_inst/asplashscreen.sh\nRemainAfterExit=yes\n\n[Install]\nWantedBy=sysinit.target\n_EOF_\n\n    gitPullOrClone \"$md_inst\"\n\n    cp \"$md_data/asplashscreen.sh\" \"$md_inst\"\n\n    iniConfig \"=\" '\"' \"$md_inst/asplashscreen.sh\"\n\n    if [[ \"$__os_debian_ver\" -le 10 ]]; then\n        # set vlc mmal layer for Raspberry Pi OS 10 (Buster) or below.\n        iniSet \"CMD_OPTS\" \" --mmal-layer 10001\"\n        # remove 05-splash.sh if present due to previous splashscreen module installing this on rpi4 on Buster\n        rm -f /etc/profile.d/05-splash.sh\n    else\n        # install script to kill splashscreen before running autostart scripts when using kms\n        cp \"$md_data/05-splash.sh\" /etc/profile.d/\n    fi\n\n    iniSet \"ROOTDIR\" \"$rootdir\"\n    iniSet \"DATADIR\" \"$datadir\"\n    iniSet \"REGEX_IMAGE\" \"$(_image_exts_splashscreen)\"\n    iniSet \"REGEX_VIDEO\" \"$(_video_exts_splashscreen)\"\n\n    if [[ ! -f \"$configdir/all/$md_id.cfg\" ]]; then\n        iniConfig \"=\" '\"' \"$configdir/all/$md_id.cfg\"\n        iniSet \"RANDOMIZE\" \"disabled\"\n    fi\n    chown \"$__user\":\"$__group\" \"$configdir/all/$md_id.cfg\"\n\n    mkUserDir \"$datadir/splashscreens\"\n    echo \"Place your own splashscreens in here.\" >\"$datadir/splashscreens/README.txt\"\n    chown \"$__user\":\"$__group\" \"$datadir/splashscreens/README.txt\"\n}\n\nfunction enable_plymouth_splashscreen() {\n    local config=\"/boot/cmdline.txt\"\n    if [[ -f \"$config\" ]]; then\n        sed -i \"s/ *plymouth.enable=0//\" \"$config\"\n    fi\n}\n\nfunction disable_plymouth_splashscreen() {\n    local config=\"/boot/cmdline.txt\"\n    if [[ -f \"$config\" ]] && ! grep -q \"plymouth.enable\" \"$config\"; then\n        sed -i '1 s/ *$/ plymouth.enable=0/' \"$config\"\n    fi\n}\n\nfunction default_splashscreen() {\n    echo \"$md_inst/retropie-default.png\" >/etc/splashscreen.list\n}\n\nfunction enable_splashscreen() {\n    systemctl enable asplashscreen\n}\n\nfunction disable_splashscreen() {\n    systemctl disable asplashscreen\n}\n\nfunction configure_splashscreen() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    disable_plymouth_splashscreen\n    enable_splashscreen\n    [[ ! -f /etc/splashscreen.list ]] && default_splashscreen\n}\n\nfunction remove_splashscreen() {\n    enable_plymouth_splashscreen\n    disable_splashscreen\n    rm -f /etc/splashscreen.list /etc/systemd/system/asplashscreen.service\n    rm -f /etc/apt/preferences.d/rp-vlc\n    rm -f /etc/profile.d/05-splash.sh\n    systemctl daemon-reload\n}\n\nfunction choose_path_splashscreen() {\n    local options=(\n        1 \"RetroPie splashscreens\"\n        2 \"Own/Extra splashscreens (from $datadir/splashscreens)\"\n    )\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ \"$choice\" -eq 1 ]] && echo \"$md_inst\"\n    [[ \"$choice\" -eq 2 ]] && echo \"$datadir/splashscreens\"\n}\n\nfunction set_append_splashscreen() {\n    local mode=\"$1\"\n    [[ -z \"$mode\" ]] && mode=\"set\"\n    local path\n    local file\n    while true; do\n        path=\"$(choose_path_splashscreen)\"\n        [[ -z \"$path\" ]] && break\n        file=$(choose_splashscreen \"$path\")\n        if [[ -n \"$file\" ]]; then\n            if [[ \"$mode\" == \"set\" ]]; then\n                echo \"$file\" >/etc/splashscreen.list\n                printMsgs \"dialog\" \"Splashscreen set to '$file'\"\n                break\n            fi\n            if [[ \"$mode\" == \"append\" ]]; then\n                echo \"$file\" >>/etc/splashscreen.list\n                printMsgs \"dialog\" \"Splashscreen '$file' appended to /etc/splashscreen.list\"\n            fi\n        fi\n    done\n}\n\nfunction choose_splashscreen() {\n    local path=\"$1\"\n    local type=\"$2\"\n\n    local regex\n    [[ \"$type\" == \"image\" ]] && regex=$(_image_exts_splashscreen)\n    [[ \"$type\" == \"video\" ]] && regex=$(_video_exts_splashscreen)\n\n    local options=()\n    local i=0\n    while read splashdir; do\n        splashdir=${splashdir/$path\\//}\n        if echo \"$splashdir\" | grep -q \"$regex\"; then\n            options+=(\"$i\" \"$splashdir\")\n            ((i++))\n        fi\n    done < <(find \"$path\" -type f ! -regex \".*/\\..*\" ! -regex \".*LICENSE\" ! -regex \".*README.*\" ! -regex \".*\\.sh\"  ! -regex \".*\\.pkg\" | sort)\n    if [[ \"${#options[@]}\" -eq 0 ]]; then\n        printMsgs \"dialog\" \"There are no splashscreens installed in $path\"\n        return\n    fi\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose splashscreen.\" 22 76 16)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -n \"$choice\" ]] && echo \"$path/${options[choice*2+1]}\"\n}\n\nfunction randomize_splashscreen() {\n    options=(\n        0 \"Disable splashscreen randomizer\"\n        1 \"Randomize RetroPie splashscreens\"\n        2 \"Randomize own splashscreens (from $datadir/splashscreens)\"\n        3 \"Randomize all splashscreens\"\n        4 \"Randomize /etc/splashscreen.list\"\n    )\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    iniConfig \"=\" '\"' \"$configdir/all/$md_id.cfg\"\n    chown \"$__user\":\"$__group\" \"$configdir/all/$md_id.cfg\"\n\n    case \"$choice\" in\n        0)\n            iniSet \"RANDOMIZE\" \"disabled\"\n            printMsgs \"dialog\" \"Splashscreen randomizer disabled.\"\n            ;;\n        1)\n            iniSet \"RANDOMIZE\" \"retropie\"\n            printMsgs \"dialog\" \"Splashscreen randomizer enabled in directory $rootdir/supplementary/$md_id\"\n            ;;\n        2)\n            iniSet \"RANDOMIZE\" \"custom\"\n            printMsgs \"dialog\" \"Splashscreen randomizer enabled in directory $datadir/splashscreens\"\n            ;;\n        3)\n            iniSet \"RANDOMIZE\" \"all\"\n            printMsgs \"dialog\" \"Splashscreen randomizer enabled for both splashscreen directories.\"\n            ;;\n        4)\n            iniSet \"RANDOMIZE\" \"list\"\n            printMsgs \"dialog\" \"Splashscreen randomizer enabled for entries in /etc/splashscreen.list\"\n            ;;\n    esac\n}\n\nfunction preview_splashscreen() {\n    local options=(\n        1 \"View single splashscreen\"\n        2 \"View slideshow of all splashscreens\"\n        3 \"Play video splash\"\n    )\n\n    local path\n    local file\n    local splash_cmd=\"sudo -u $__user XDG_RUNTIME_DIR=/run/user/$SUDO_UID vlc --intf dummy --quiet --play-and-exit --image-duration 6\"\n    while true; do\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        path=\"$(choose_path_splashscreen)\"\n        [[ -z \"$path\" ]] && break\n        while true; do\n            case \"$choice\" in\n                1)\n                    file=$(choose_splashscreen \"$path\" \"image\")\n                    [[ -z \"$file\" ]] && break\n                    $splash_cmd \"$file\"\n                    ;;\n                2)\n                    file=$(mktemp)\n                    find \"$path\" -type f ! -regex \".*/\\..*\" ! -regex \".*LICENSE\" ! -regex \".*README.*\" ! -regex \".*\\.sh\" | sort > \"$file\"\n                    if [[ -s \"$file\" ]]; then\n                        tr \"\\n\" \"\\0\" <\"$file\" | xargs -0 $splash_cmd\n                    else\n                        printMsgs \"dialog\" \"There are no splashscreens installed in $path\"\n                    fi\n                    rm -f \"$file\"\n                    break\n                    ;;\n                3)\n                    file=$(choose_splashscreen \"$path\" \"video\")\n                    [[ -z \"$file\" ]] && break\n                    $splash_cmd \"$file\"\n                    ;;\n            esac\n        done\n    done\n}\n\nfunction download_extra_splashscreen() {\n    gitPullOrClone \"$datadir/splashscreens/retropie-extra\" https://github.com/HerbFargus/retropie-splashscreens-extra\n    chown -R \"$__user\":\"$__group\" \"$datadir/splashscreens/retropie-extra\"\n}\n\nfunction gui_splashscreen() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    while true; do\n        local enabled=0\n        [[ -n \"$(find \"/etc/systemd/system/\"*\".wants\" -type l -name \"asplashscreen.service\")\" ]] && enabled=1\n        local options=(1 \"Choose splashscreen\")\n        if [[ \"$enabled\" -eq 1 ]]; then\n            options+=(2 \"Show splashscreen on boot (currently: Enabled)\")\n            iniConfig \"=\" '\"' \"$configdir/all/$md_id.cfg\"\n            iniGet \"RANDOMIZE\"\n            options+=(3 \"Randomizer options (currently: ${ini_value^})\")\n        else\n            options+=(2 \"Show splashscreen on boot (currently: Disabled)\")\n        fi\n        options+=(\n            4 \"Use default splashscreen\"\n            5 \"Manually edit splashscreen list\"\n            6 \"Append splashscreen to list (for multiple entries)\"\n            7 \"Preview splashscreens\"\n            8 \"Update RetroPie splashscreens\"\n            9 \"Download RetroPie-Extra splashscreens\"\n        )\n\n        iniConfig \"=\" '\"' \"$configdir/all/$md_id.cfg\"\n        iniGet \"DURATION\"\n        # default splashscreen duration is 12 seconds\n        local duration=${ini_value:-12}\n\n        options+=(\n            A \"Configure image splashscreen duration ($duration sec)\"\n            )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    set_append_splashscreen set\n                    ;;\n                2)\n                    if [[ \"$enabled\" -eq 1 ]]; then\n                        disable_splashscreen\n                        printMsgs \"dialog\" \"Disabled splashscreen on boot.\"\n                    else\n                        [[ ! -f /etc/splashscreen.list ]] && rp_callModule splashscreen default\n                        enable_splashscreen\n                        printMsgs \"dialog\" \"Enabled splashscreen on boot.\"\n                    fi\n                    ;;\n                3)\n                    randomize_splashscreen\n                    ;;\n                4)\n                    iniSet \"RANDOMIZE\" \"disabled\"\n                    default_splashscreen\n                    enable_splashscreen\n                    printMsgs \"dialog\" \"Splashscreen set to RetroPie default.\"\n                    ;;\n                5)\n                    editFile /etc/splashscreen.list\n                    ;;\n                6)\n                    set_append_splashscreen append\n                    ;;\n                7)\n                    preview_splashscreen\n                    ;;\n                8)\n                    rp_callModule splashscreen install\n                    ;;\n                9)\n                    rp_callModule splashscreen download_extra\n                    printMsgs \"dialog\" \"The RetroPie-Extra splashscreens have been downloaded to $datadir/splashscreens/retropie-extra\"\n                    ;;\n                A)  \n                    duration=$(dialog --title \"Splashscreen duration\" --clear --rangebox \"Configure how many seconds the splashscreen is active\" 0 60 5 100 $duration 2>&1 >/dev/tty)\n                    if [[ -n \"$duration\" ]]; then\n                        iniSet \"DURATION\" \"${duration//[^[:digit:]]/}\"\n                    fi\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/steamcontroller.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"steamcontroller\"\nrp_module_desc=\"User-mode driver for Steam Controller\"\nrp_module_help=\"Steam Controller Driver from https://github.com/C0rn3j/sc-controller\"\nrp_module_licence=\"GPL2 https://raw.githubusercontent.com/C0rn3j/sc-controller/python3/LICENSE\"\nrp_module_repo=\"git https://github.com/C0rn3j/sc-controller.git v0.5.4\"\nrp_module_section=\"driver\"\n\nfunction _update_hook_steamcontroller() {\n    # remove the start command from the previous scriptmodule version\n    if rp_isInstalled \"$md_id\"; then\n        sed -i \"/bin\\/sc-.*.py/d\" /etc/rc.local\n    fi\n}\nfunction depends_steamcontroller() {\n    getDepends python3-virtualenv python3-dev python3-setuptools\n}\n\nfunction sources_steamcontroller() {\n    gitPullOrClone\n}\n\nfunction install_steamcontroller() {\n    # build the driver in a virtualenv created in $md_inst\n    virtualenv -p python3 \"$md_inst\"\n    source \"$md_inst/bin/activate\"\n    pip3 install libusb1 evdev ioctl_opt\n    pip3 install \"sccontroller @ file://$md_build\"\n    deactivate\n\n    # copy the default controller profiles\n    md_ret_files=(\"default_profiles\")\n}\n\nfunction enable_steamcontroller() {\n    local profile=\"$1\"\n    [[ -z \"$profile\" ]] && profile=\"XBox Controller\"\n\n    disable_steamcontroller\n    cat > /etc/systemd/system/sc-controller.service << _EOF_\n[Unit]\nDescription=Userspace Steamcontroller driver\n\n[Service]\nExecStart=\"$md_inst/bin/scc-daemon\" \"$md_inst/default_profiles/$profile.sccprofile\" debug\nExecStop=\"$md_inst/bin/scc-daemon\" stop\n\n[Install]\nWantedBy=multi-user.target\n_EOF_\n    systemctl daemon-reload\n    systemctl -q enable sc-controller.service\n    systemctl start sc-controller.service\n    printMsgs \"dialog\" \"Steamcontroller enabled and started with profile:\\n\\n$profile\"\n}\n\nfunction disable_steamcontroller() {\n    # remove start commands from /etc/rc.local\n    [[ -f \"/etc/rc.local\" ]] && sed -i \"/bin\\/scc-daemon.*start/d\" /etc/rc.local\n    if systemctl -q is-enabled sc-controller.service 2>/dev/null; then\n        systemctl stop sc-controller.service\n        systemctl -q disable sc-controller.service\n    fi\n}\n\nfunction remove_steamcontroller() {\n    disable_steamcontroller\n    rm -f /etc/udev/rules.d/99-steam-controller.rules\n    if [[ -f \"/etc/systemd/system/sc-controller.service\" ]]; then\n        rm -f \"/etc/systemd/system/sc-controller.service\"\n        systemctl daemon-reload\n    fi\n}\n\nfunction configure_steamcontroller() {\n    cat >/etc/udev/rules.d/99-steam-controller.rules <<_EOF_\n# Steam controller keyboard/mouse mode\nSUBSYSTEM==\"usb\", ATTRS{idVendor}==\"28de\", GROUP=\"input\", MODE=\"0660\"\n\n# Valve HID devices over bluetooth hidraw\nKERNEL==\"hidraw*\", KERNELS==\"*28de:*\", MODE=\"0660\", GROUP=\"input\", TAG+=\"uaccess\"\n\n# Steam controller gamepad mode\nKERNEL==\"uinput\", MODE=\"0660\", GROUP=\"input\", OPTIONS+=\"static_node=uinput\"\n_EOF_\n}\n\nfunction gui_steamcontroller() {\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    local options=(\n        1 \"Enable Steamcontroller (Xbox controller mode)\"\n        2 \"Enable Steamcontroller (Desktop mouse/keyboard mode)\"\n        3 \"Disable Steamcontroller\"\n    )\n    while true; do\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    enable_steamcontroller \"XBox Controller\"\n                    ;;\n                2)\n                    enable_steamcontroller \"Desktop\"\n                    ;;\n                3)\n                    disable_steamcontroller\n                    printMsgs \"dialog\" \"Steamcontroller service has been disabled\"\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/usbromservice/01_retropie_copyroms",
    "content": "#!/bin/bash\n# This file is part of The RetroPie Project\n# \n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n# \n# See the LICENSE.md file at the top-level directory of this distribution and \n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## config / defaults\nuser=\"USER\"\ngroup=\"GROUP\"\n\nhome=\"$(eval echo ~$user)\"\nrootdir=\"/opt/retropie\"\nretropie_path=\"$home/RetroPie\"\n\nusb_path=\"$UM_MOUNTPOINT/retropie\"\nusb_path_from_rp=\"$usb_path/configs/from_retropie\"\nusb_path_to_rp=\"$usb_path/configs/to_retropie\"\n\ndeclare -A path_mapping\n\n# mapping from usb_path_to_rp/* to retropie location\npath_mapping[\"configs\"]=\"$rootdir/configs\"\n\n## internals\nhook_name=${0##*/}\n\n## functions\nfunction log() {\n    logger -p user.$1 -t usbmount-\"$hook_name\"-[$$] -- \"$2\"\n}\n\nfunction log_cmd() {\n    local ret\n    local error\n    error=\"$(\"$@\" 2>&1 >/dev/null)\"\n    ret=$?\n    [[ \"$ret\" -ne 0 ]] && log err \"$* - returned $ret - $error\"\n}\n\n## some sanity checking\nif [[ -z \"$UM_MOUNTPOINT\" ]]; then\n    log err \"UM_MOUNTPOINT not set!\"\n    exit 0\nfi\n\nif [[ ! -d \"$UM_MOUNTPOINT\" ]]; then\n    log err \"UM_MOUNTPOINT is not a directory\"\n    exit 0\nfi\n\n# make sure we have something to sync from\nif [[ ! -d \"$usb_path\" ]]; then\n    exit 0\nfi\n\n# make folders for syncing\nmkdir -p \"$usb_path/\"{roms,BIOS} \"$usb_path_from_rp\" \"$usb_path_to_rp\"\n\n# mirror romdir structure to external drive\nlog info \"Attempting to create directory structure for ROMS in '$usb_path/roms' ...\"\n# fetch list of romdirs from current installation and mirror onto external drive\nfind \"$retropie_path/roms\" -mindepth 1 -maxdepth 1 -type d -printf \"$usb_path/roms/%f\\n\" | xargs mkdir -p 2>/dev/null || true\n\n# copy ROMs/BIOS from USB stick to local SD card\nfor dir in roms BIOS; do\n    log info \"Syncing $dir ...\"\n    log_cmd rsync -rtu --exclude '._*' --max-delete=-1 \"$usb_path/$dir\" \"$retropie_path/\"\n    chown -R \"$user\":\"$group\" \"$retropie_path/$dir\"\ndone\n\nlog info \"Syncing configs ...\"\n# copy configs to usb\nfor to in \"${!path_mapping[@]}\"; do\n    from=${path_mapping[$to]}\n    log_cmd rsync -rtu --exclude '._*' --max-delete=-1 \"$from/\" \"$usb_path_from_rp/$to/\"\ndone\n\n# copy configs from usb\nfor from in $(find \"$usb_path_to_rp/\" -mindepth 1 -maxdepth 1); do\n    # basename\n    from_bn=${from##*/}\n    to=${path_mapping[$from_bn]}\n    if [[ -n \"$to\" ]]; then\n        log_cmd rsync -rtu --exclude '._*' --max-delete=-1 \"$from/\" \"$to/\"\n        chown -R \"$user\":\"$group\" \"$to\"\n    fi\ndone\n\n# unmount USB stick\numount \"$UM_MOUNTPOINT\"\n"
  },
  {
    "path": "scriptmodules/supplementary/usbromservice/10_retropie_mount",
    "content": "#!/bin/bash\n\n# This file is part of The RetroPie Project\n#\n# The RetroPie Project is the legal property of its developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\n## config / defaults\nuser=\"USER\"\n\nhome=\"$(eval echo ~$user)\"\nretropie_path=\"$home/RetroPie\"\n\nusb_path=\"$UM_MOUNTPOINT/retropie-mount\"\n\n## internals\nhook_name=${0##*/}\n\n## functions\nfunction log() {\n    logger -p user.$1 -t usbmount-\"$hook_name\"-[$$] -- \"$2\"\n}\n\nfunction log_cmd() {\n    local ret\n    local error\n    error=\"$(\"$@\" 2>&1 >/dev/null)\"\n    ret=$?\n    [[ \"$ret\" -ne 0 ]] && log err \"$* - returned $ret - $error\"\n}\n\n## some sanity checking\nif [[ -z \"$UM_MOUNTPOINT\" ]]; then\n    log err \"UM_MOUNTPOINT not set!\"\n    exit 0\nfi\n\nif [[ ! -d \"$UM_MOUNTPOINT\" ]]; then\n    log err \"UM_MOUNTPOINT is not a directory\"\n    exit 0\nfi\n\n# check for a retropie-mount folder\nif [[ ! -d \"$usb_path\" ]]; then\n    exit 0\nfi\n\nif [[ -z \"$(ls -A \"$usb_path\")\" ]]; then\n    log info \"Copying existing $retropie_path to $usb_path ...\"\n    log_cmd rsync -rtu \"$retropie_path/\" \"$usb_path/\"\nfi\n\nlog info \"Mounting $usb_path over $retropie_path ...\"\nlog_cmd mount -o bind \"$usb_path\" \"$retropie_path\"\n"
  },
  {
    "path": "scriptmodules/supplementary/usbromservice.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"usbromservice\"\nrp_module_desc=\"USB ROM Service\"\nrp_module_section=\"opt\"\n\nfunction _get_ver_usbromservice() {\n    echo 0.0.24\n}\n\nfunction _update_hook_usbromservice() {\n    ! rp_isInstalled \"$md_id\" && return\n    [[ ! -f \"$md_inst/disabled\" ]] && install_scripts_usbromservice\n}\n\nfunction depends_usbromservice() {\n    local depends=(rsync ntfs-3g exfat-fuse)\n    if ! hasPackage usbmount $(_get_ver_usbromservice); then\n        depends+=(debhelper devscripts pmount lockfile-progs)\n        getDepends \"${depends[@]}\"\n        gitPullOrClone \"$md_build/usbmount\" https://github.com/RetroPie/usbmount.git systemd\n        cd \"$md_build/usbmount\"\n        dpkg-buildpackage\n        dpkg -i ../usbmount_*_all.deb\n        rm -f ../usbmount_*\n    fi\n}\n\nfunction install_bin_usbromservice() {\n    [[ ! -f \"$md_inst/disabled\" ]] && install_scripts_usbromservice\n    touch \"$md_inst/installed\"\n}\n\nfunction install_scripts_usbromservice() {\n    # copy our mount.d scripts over\n    local file\n    local dest\n    for file in \"$md_data/\"*; do\n        dest=\"/etc/usbmount/mount.d/${file##*/}\"\n        sed -e \"s/USER/$__user/g\" -e \"s/GROUP/$__group/g\" \"$file\" >\"$dest\"\n        chmod +x \"$dest\"\n    done\n}\n\nfunction enable_usbromservice() {\n    rm -f \"$md_inst/disabled\"\n    install_scripts_usbromservice\n}\n\nfunction disable_usbromservice() {\n    local file\n    for file in \"$md_data/\"*; do\n        file=\"/etc/usbmount/mount.d/${file##*/}\"\n        rm -f \"$file\"\n    done\n    [[ -d \"$md_inst\" ]] && touch \"$md_inst/disabled\"\n}\n\nfunction remove_usbromservice() {\n    disable_usbromservice\n    apt-get remove -y usbmount\n}\n\nfunction configure_usbromservice() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    iniConfig \"=\" '\"' /etc/usbmount/usbmount.conf\n\n    local fs\n    for fs in ntfs exfat; do\n        iniGet \"FILESYSTEMS\"\n        if [[ \"$ini_value\" != *$fs* ]]; then\n            iniSet \"FILESYSTEMS\" \"$ini_value $fs\"\n        fi\n    done\n\n    # set our mount options (usbmount has sync by default which we don't want)\n    iniSet \"MOUNTOPTIONS\" \"nodev,noexec,noatime\"\n\n    # set per filesystem mount options\n    local options=\"uid=$(id -u $__user),gid=$(id -g $__user)\"\n    local fs_options\n    local fs\n    for fs in vfat hfsplus ntfs exfat; do\n        fs_options+=(\"-fstype=${fs},${options}\")\n    done\n    iniSet \"FS_MOUNTOPTIONS\" \"${fs_options[*]}\"\n}\n\nfunction gui_usbromservice() {\n    local cmd\n    local options\n    local choice\n    while true; do\n        cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose from an option below.\" 22 86 16)\n        options=(\n            1 \"Enable USB ROM Service scripts\"\n            2 \"Disable USB ROM Service scripts\"\n        )\n        choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    rp_callModule \"$md_id\" depends\n                    rp_callModule \"$md_id\" enable\n                    printMsgs \"dialog\" \"Enabled $md_desc\"\n                    ;;\n                2)\n                    rp_callModule \"$md_id\" disable\n                    printMsgs \"dialog\" \"Disabled $md_desc\"\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/virtualgamepad.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"virtualgamepad\"\nrp_module_desc=\"Virtual Gamepad for Smartphone\"\nrp_module_licence=\"MIT https://raw.githubusercontent.com/miroof/node-virtual-gamepads/master/LICENSE\"\nrp_module_repo=\"git https://github.com/miroof/node-virtual-gamepads.git master\"\nrp_module_section=\"exp\"\nrp_module_flags=\"noinstclean nobin\"\n\nfunction depends_virtualgamepad() {\n    getDepends nodejs npm\n}\n\nfunction remove_virtualgamepad() {\n    pm2 stop main\n    pm2 delete main\n    rm -f /etc/apt/sources.list.d/nodesource.list\n}\n\nfunction sources_virtualgamepad() {\n    gitPullOrClone \"$md_inst\"\n    chown -R \"$__user\":\"$__group\" \"$md_inst\"\n}\n\nfunction install_virtualgamepad() {\n    npm install pm2 -g --unsafe-perm\n    cd \"$md_inst\"\n    sudo -u \"$__user\" npm install\n    sudo -u \"$__user\" npm install ref\n}\n\nfunction configure_virtualgamepad() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n    pm2 start main.js\n    pm2 startup\n    pm2 save\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/wifi.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"wifi\"\nrp_module_desc=\"Configure WiFi\"\nrp_module_section=\"config\"\nrp_module_flags=\"!x11\"\n\nfunction _get_interface_wifi() {\n    local iface\n    # look for the first wireless interface present\n    for iface in /sys/class/net/*; do\n        if [[ -d \"$iface/wireless\" ]]; then\n            echo \"$(basename $iface)\"\n            return 0\n        fi\n    done\n    return 1\n}\n\nfunction _get_mgmt_tool_wifi() {\n    # get the WiFi connection manager\n    if systemctl -q is-active NetworkManager.service; then\n        echo \"nm\"\n    else\n        echo \"wpasupplicant\"\n    fi\n}\nfunction _set_interface_wifi() {\n    local iface=\"$1\"\n    local state=\"$2\"\n\n    if [[ \"$state\" == \"up\" ]]; then\n        if ! ifup $iface; then\n            ip link set $iface up\n        fi\n    elif [[ \"$state\" == \"down\" ]]; then\n        if ! ifdown $iface; then\n            ip link set $iface down\n        fi\n    fi\n}\n\nfunction remove_nm_wifi() {\n    local iface=\"$1\"\n    # delete the NM connection named RetroPie-WiFi\n    nmcli connection delete RetroPie-WiFi\n    _set_interface_wifi $iface down 2>/dev/null\n}\n\nfunction remove_wpasupplicant_wifi() {\n    local iface=\"$1\"\n    sed -i '/RETROPIE CONFIG START/,/RETROPIE CONFIG END/d' \"/etc/wpa_supplicant/wpa_supplicant.conf\"\n    _set_interface_wifi $iface down 2>/dev/null\n}\n\nfunction list_wifi() {\n    local line\n    local essid\n    local type\n    local iface=\"$1\"\n\n    while read line; do\n        [[ \"$line\" =~ ^Cell && -n \"$essid\" ]] && echo -e \"$essid\\n$type\"\n        [[ \"$line\" =~ ^ESSID ]] && essid=$(echo \"$line\" | cut -d\\\" -f2)\n        [[ \"$line\" == \"Encryption key:off\" ]] && type=\"open\"\n        [[ \"$line\" == \"Encryption key:on\" ]] && type=\"wep\"\n        [[ \"$line\" =~ ^IE:.*WPA ]] && type=\"wpa\"\n    done < <(iwlist $iface scan | grep -o \"Cell .*\\|ESSID:\\\".*\\\"\\|IE: .*WPA\\|Encryption key:.*\")\n    echo -e \"$essid\\n$type\"\n}\n\nfunction connect_wifi() {\n    local iface\n    local mgmt_tool=\"wpasupplicant\"\n\n    iface=\"$(_get_interface_wifi)\"\n    if [[ -z \"$iface\" ]]; then\n        printMsgs \"dialog\" \"No wireless interfaces detected\"\n        return 1\n    fi\n    mgmt_tool=\"$(_get_mgmt_tool_wifi)\"\n\n    local essids=()\n    local essid\n    local types=()\n    local type\n    local options=()\n    i=0\n    _set_interface_wifi $iface up 2>/dev/null\n    dialog --infobox \"\\nScanning for WiFi networks...\" 5 40 > /dev/tty\n    sleep 1\n\n    while read essid; read type; do\n        essids+=(\"$essid\")\n        types+=(\"$type\")\n        options+=(\"$i\" \"$essid\")\n        ((i++))\n    done < <(list_wifi $iface)\n    options+=(\"H\" \"Hidden ESSID\")\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Please choose the WiFi network you would like to connect to\" 22 76 16)\n    choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    [[ -z \"$choice\" ]] && return\n\n    local hidden=0\n    if [[ \"$choice\" == \"H\" ]]; then\n        essid=$(inputBox \"ESSID\" \"\" 4)\n        [[ -z \"$essid\" ]] && return\n        cmd=(dialog --backtitle \"$__backtitle\" --nocancel --menu \"Please choose the WiFi type\" 12 40 6)\n        options=(\n            wpa \"WPA/WPA2\"\n            wep \"WEP\"\n            open \"Open\"\n        )\n        type=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        hidden=1\n    else\n        essid=${essids[choice]}\n        type=${types[choice]}\n    fi\n\n    if [[ \"$type\" == \"wpa\" || \"$type\" == \"wep\" ]]; then\n        local key=\"\"\n        local key_min\n        if [[ \"$type\" == \"wpa\" ]]; then\n            key_min=8\n        else\n            key_min=5\n        fi\n\n        cmd=(inputBox \"WiFi key/password\" \"\" $key_min)\n        local key_ok=0\n        while [[ $key_ok -eq 0 ]]; do\n            key=$(\"${cmd[@]}\") || return\n            key_ok=1\n        done\n    fi\n\n    create_${mgmt_tool}_config_wifi \"$type\" \"$essid\" \"$key\" \"$iface\"\n    gui_connect_wifi \"$iface\"\n}\n\nfunction create_nm_config_wifi() {\n    local type=\"$1\"\n    local essid=\"$2\"\n    local key=\"$3\"\n    local dev=\"$4\"\n    local con=\"RetroPie-WiFi\"\n\n    remove_nm_wifi\n    nmcli connection add type wifi ifname \"$dev\" ssid \"$essid\" con-name \"$con\" autoconnect yes\n    # configure security for the connection\n    case $type in\n        wpa)\n            nmcli connection modify \"$con\" \\\n                wifi-sec.key-mgmt wpa-psk  \\\n                wifi-sec.psk-flags 0       \\\n                wifi-sec.psk \"$key\"\n            ;;\n        wep)\n            nmcli connection modify \"$con\" \\\n                wifi-sec.key-mgmt none     \\\n                wifi-sec.wep-key-flags 0   \\\n                wifi-sec.wep-key-type 2    \\\n                wifi-sec.wep-key0 \"$key\"\n            ;;\n        open)\n            ;;\n    esac\n\n    [[ $hidden -eq 1 ]] && nmcli connection modify \"$con\" wifi.hidden yes\n}\n\nfunction create_wpasupplicant_config_wifi() {\n    local type=\"$1\"\n    local essid=\"$2\"\n    local key=\"$3\"\n    local dev=\"$4\"\n\n    local wpa_config\n    wpa_config+=\"\\tssid=\\\"$essid\\\"\\n\"\n    case $type in\n        wpa)\n            wpa_config+=\"\\tpsk=\\\"$key\\\"\\n\"\n            ;;\n        wep)\n            wpa_config+=\"\\tkey_mgmt=NONE\\n\"\n            wpa_config+=\"\\twep_tx_keyidx=0\\n\"\n            wpa_config+=\"\\twep_key0=$key\\n\"\n            ;;\n        open)\n            wpa_config+=\"\\tkey_mgmt=NONE\\n\"\n            ;;\n    esac\n\n    [[ $hidden -eq 1 ]] &&  wpa_config+=\"\\tscan_ssid=1\\n\"\n\n    remove_wpasupplicant_wifi\n    wpa_config=$(echo -e \"$wpa_config\")\n    cat >> \"/etc/wpa_supplicant/wpa_supplicant.conf\" <<_EOF_\n# RETROPIE CONFIG START\nnetwork={\n$wpa_config\n}\n# RETROPIE CONFIG END\n_EOF_\n}\n\nfunction gui_connect_wifi() {\n    local iface=\"$1\"\n    local mgmt_tool\n\n    mgmt_tool=\"$(_get_mgmt_tool_wifi)\"\n    _set_interface_wifi $iface down 2>/dev/null\n    _set_interface_wifi $iface up 2>/dev/null\n\n    if [[ \"$mgmt_tool\" == \"wpasupplicant\" ]]; then\n        # BEGIN workaround for dhcpcd trigger failure on Raspbian stretch\n        systemctl restart dhcpcd &>/dev/null\n        # END workaround\n    fi\n    if [[ \"$mgmt_tool\" == \"nm\" ]]; then\n        nmcli -w 0 connection up RetroPie-WiFi\n    fi\n\n    dialog --backtitle \"$__backtitle\" --infobox \"\\nConnecting ...\" 5 40 >/dev/tty\n    local id=\"\"\n    i=0\n    while [[ -z \"$id\" && $i -lt 30 ]]; do\n        sleep 1\n        id=$(iwgetid -r)\n        ((i++))\n    done\n    if [[ -z \"$id\" ]]; then\n        printMsgs \"dialog\" \"Unable to connect to network $essid\"\n        _set_interface_wifi $iface down 2>/dev/null\n    fi\n}\n\nfunction _check_country_wifi() {\n    local country\n    country=\"$(raspi-config nonint get_wifi_country)\"\n    if [[ -z \"$country\" ]]; then\n        if dialog --defaultno --yesno \"You don't currently have your WiFi country set.\\n\\nOn a Raspberry Pi 3B+ and later your WiFi will be disabled until the country is set. You can do this via raspi-config which is available from the RetroPie menu in Emulation Station. Once in raspi-config you can set your country via menu 5 (Localisation Options)\\n\\nDo you want me to launch raspi-config for you now ?\" 22 76 2>&1 >/dev/tty; then\n            raspi-config\n        fi\n    fi\n}\n\nfunction gui_wifi() {\n\n    isPlatform \"rpi\" && _check_country_wifi\n\n    local default\n    local iface\n    local mgmt_tool\n\n    iface=\"$(_get_interface_wifi)\"\n    mgmt_tool=\"$(_get_mgmt_tool_wifi)\"\n\n    while true; do\n        local ip_current=\"$(getIPAddress)\"\n        local ip_wlan=\"$(getIPAddress $iface)\"\n        local cmd=(dialog --backtitle \"$__backtitle\" --colors --cancel-label \"Exit\" --item-help --help-button --default-item \"$default\" --title \"Configure WiFi\" --menu \"Current IP: \\Zb${ip_current:-(unknown)}\\ZB\\nWireless IP: \\Zb${ip_wlan:-(unknown)}\\ZB\\nWireless ESSID: \\Zb$(iwgetid -r || echo \"none\")\\ZB\" 22 76 16)\n        local options=(\n            1 \"Connect to WiFi network\"\n            \"1 Connect to your WiFi network\"\n            2 \"Disconnect/Remove WiFi config\"\n            \"2 Disconnect and remove any WiFi configuration\"\n            3 \"Import WiFi credentials from wifikeyfile.txt\"\n            \"3 Will import the SSID (network name) and PSK (password) from the 'wifikeyfile.txt' file on the boot partition\n\nThe file should contain two lines as follows\\n\\nssid = \\\"YOUR WIFI SSID\\\"\\npsk = \\\"YOUR PASSWORD\\\"\"\n        )\n\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ \"${choice[@]:0:4}\" == \"HELP\" ]]; then\n            choice=\"${choice[@]:5}\"\n            default=\"${choice/%\\ */}\"\n            choice=\"${choice#* }\"\n            printMsgs \"dialog\" \"$choice\"\n            continue\n        fi\n        default=\"$choice\"\n\n        if [[ -n \"$choice\" ]]; then\n            case \"$choice\" in\n                1)\n                    connect_wifi $iface\n                    ;;\n                2)\n                    dialog --defaultno --yesno \"This will remove the WiFi configuration and stop the WiFi.\\n\\nAre you sure you want to continue ?\" 12 60 2>&1 >/dev/tty\n                    [[ $? -ne 0 ]] && continue\n                    remove_${mgmt_tool}_wifi $iface\n                    ;;\n                3)\n                    # check in `/boot/` (pre-bookworm) and `/boot/firmware` (bookworm and later) for the file\n                    local file=\"/boot/wifikeyfile.txt\"\n                    [[ ! -f \"$file\" ]] && file=\"/boot/firmware/wifikeyfile.txt\"\n\n                    if [[ -f \"$file\" ]]; then\n                        iniConfig \" = \" \"\\\"\" \"$file\"\n                        iniGet \"ssid\"\n                        local ssid=\"$ini_value\"\n                        iniGet \"psk\"\n                        local psk=\"$ini_value\"\n                        create_${mgmt_tool}_config_wifi \"wpa\" \"$ssid\" \"$psk\" \"$iface\"\n                        gui_connect_wifi \"$iface\"\n                    else\n                        printMsgs \"dialog\" \"File 'wifikeyfile.txt' not found on the boot partition!\"\n                    fi\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/xarcade2jstick.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xarcade2jstick\"\nrp_module_desc=\"Xarcade2Jstick\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/petrockblog/Xarcade2Jstick/master/gpl3.txt\"\nrp_module_repo=\"git https://github.com/petrockblog/Xarcade2Joystick.git master\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean\"\n\nfunction sources_xarcade2jstick() {\n    gitPullOrClone \"$md_inst\"\n}\n\nfunction build_xarcade2jstick() {\n    cd \"$md_inst\"\n    make\n}\n\nfunction install_xarcade2jstick() {\n    cd \"$md_inst\"\n    make install\n}\n\n\nfunction enable_xarcade2jstick() {\n    cd \"$md_inst\"\n    make installservice\n}\n\nfunction disable_xarcade2jstick() {\n    cd \"$md_inst\"\n    make uninstallservice\n}\n\nfunction remove_xarcade2jstick() {\n    [[ -f /lib/systemd/system/xarcade2jstick.service ]] && disable_xarcade2jstick\n    cd \"$md_inst\"\n    make uninstall\n}\n\nfunction gui_xarcade2jstick() {\n    local status\n    local options=(\n        1 \"Enable Xarcade2Jstick service.\"\n        2 \"Disable Xarcade2Jstick service.\"\n    )\n    while true; do\n        status=\"Disabled\"\n        [[ -f /lib/systemd/system/xarcade2jstick.service ]] && status=\"Enabled\"\n        local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Service is currently: $status\" 22 86 16)\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        [[ -z \"$choice\" ]] && break\n        case \"$choice\" in\n            1)\n                enable_xarcade2jstick\n                printMsgs \"dialog\" \"Enabled Xarcade2Jstick.\"\n                ;;\n            2)\n                disable_xarcade2jstick\n                printMsgs \"dialog\" \"Disabled Xarcade2Jstick service.\"\n                ;;\n        esac\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/xboxdrv.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xboxdrv\"\nrp_module_desc=\"Xbox / Xbox 360 gamepad driver\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/RetroPie/xboxdrv/stable/COPYING\"\nrp_module_repo=\"git https://github.com/RetroPie/xboxdrv.git retropie-stable\"\nrp_module_section=\"driver\"\n\nfunction def_controllers_xboxdrv() {\n    echo \"2\"\n}\n\nfunction def_deadzone_xboxdrv() {\n    echo \"4000\"\n}\n\nfunction depends_xboxdrv() {\n    getDepends libboost-dev libusb-1.0-0-dev libudev-dev libx11-dev scons pkg-config python3 x11proto-core-dev libdbus-glib-1-dev\n}\n\nfunction sources_xboxdrv() {\n    gitPullOrClone\n}\n\nfunction build_xboxdrv() {\n    python3 /usr/bin/scons\n}\n\nfunction install_xboxdrv() {\n    make install PREFIX=\"$md_inst\"\n}\n\nfunction enable_xboxdrv() {\n    local controllers=\"$1\"\n    local deadzone=\"$2\"\n\n    [[ -z \"$controllers\" ]] && controllers=\"$(def_controllers_xboxdrv)\"\n    [[ -z \"$deadzone\" ]] && deadzone=\"$(def_deadzone_xboxdrv)\"\n\n    local config=\"\\\"$md_inst/bin/xboxdrv\\\" --daemon --detach --dbus disabled --detach-kernel-driver\"\n\n    local i\n    for (( i=0; i<$controllers; i++)); do\n        [[ $i -gt 0 ]] && config+=\" --next-controller\"\n        config+=\" --id $i --led $((i+2)) --deadzone $deadzone --silent --trigger-as-button\"\n    done\n\n    # remove any previously start-up commands in /etc/rc.local\n    [[ -f /etc/rc.local ]] && sed -i \"/xboxdrv/d\" /etc/rc.local\n\n    cat > /etc/systemd/system/xboxdrv.service << _EOF_\n[Unit]\nDescription=Userspace Xbox gamepad driver and input remapper\nConditionPathExists=$md_inst/bin/xboxdrv\n\n[Service]\nType=forking\nPIDFile=/run/xboxdrv.pid\nExecStart=$config --pid-file /run/xboxdrv.pid\n\n[Install]\nWantedBy=multi-user.target\n_EOF_\n    systemctl daemon-reload\n    systemctl -q start xboxdrv\n    systemctl enable xboxdrv\n    printMsgs \"dialog\" \"xboxdrv has been enabled and started\"\n}\n\nfunction disable_xboxdrv() {\n    [[ -f /etc/rc.local ]] && sed -i \"/xboxdrv/d\" /etc/rc.local\n    systemctl -q is-enabled xboxdrv 2>/dev/null && systemctl disable xboxdrv\n    systemctl -q is-active xboxdrv 2>/dev/null && systemctl stop xboxdrv\n\n    printMsgs \"dialog\" \"xboxdrv auto-start has been disabled\"\n}\n\nfunction controllers_xboxdrv() {\n    local controllers=\"$1\"\n\n    [[ -z \"$controllers\" ]] && controllers=\"$(def_controllers_xboxdrv)\"\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$controllers\" --menu \"Select the number of controllers to enable\" 22 86 16)\n    local options=(\n        1 \"1 controller\"\n        2 \"2 controllers\"\n        3 \"3 controllers\"\n        4 \"4 controllers\"\n    )\n\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        controllers=\"$choice\"\n    fi\n\n    echo \"$controllers\"\n}\n\nfunction deadzone_xboxdrv() {\n    local deadzone=\"$1\"\n\n    [[ -z \"$deadzone\" ]] && deadzone=\"$(def_deadzone_xboxdrv)\"\n\n    local zones=()\n    local options=()\n    local i\n    local label\n    local default\n    for i in {0..12}; do\n        zones[i]=$((i*500))\n        [[ ${zones[i]} -eq $deadzone ]] && default=$i\n        label=\"0-${zones[i]}\"\n        [[ \"$i\" -eq 0 ]] && label=\"No Deadzone\"\n        options+=($i \"$label\")\n    done\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --default-item \"$default\" --menu \"Select range of your analog stick deadzone\" 22 86 16)\n\n    local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n    if [[ -n \"$choice\" ]]; then\n        deadzone=\"${zones[$choice]}\"\n    fi\n\n    echo \"$deadzone\"\n}\n\nfunction remove_xboxdrv()\n{\n    disable_xboxdrv\n\n    if [[ -f \"/etc/systemd/system/xboxdrv.service\" ]]; then\n        rm -f \"/etc/systemd/system/xboxdrv.service\"\n        systemctl daemon-reload\n    fi\n}\n\nfunction gui_xboxdrv() {\n    if [[ ! -f \"$md_inst/bin/xboxdrv\" ]]; then\n        if [[ $__has_binaries -eq 1 ]]; then\n            rp_callModule \"$md_id\" depends\n            rp_callModule \"$md_id\" install_bin\n        else\n            rp_callModule \"$md_id\"\n        fi\n    fi\n\n    local controllers=\"$(def_controllers_xboxdrv)\"\n    local deadzone=\"$(def_deadzone_xboxdrv)\"\n    local is_enabled=\"disabled\"\n    local operation=\"Enable\"\n    systemctl -q is-enabled xboxdrv && is_enabled=\"enabled\" && operation=\"Disable\"\n\n    local cmd=(dialog --backtitle \"$__backtitle\" --menu \"Choose an option.\" 22 86 16)\n    while true; do\n        local options=(\n            1 \"$operation xboxdrv (currently: $is_enabled)\"\n            2 \"Set number of controllers to enable (currently $controllers)\"\n            3 \"Set analog stick deadzone (currently $deadzone)\"\n        )\n        local choice=$(\"${cmd[@]}\" \"${options[@]}\" 2>&1 >/dev/tty)\n        if [[ -n \"$choice\" ]]; then\n\n            case \"$choice\" in\n                1)\n                    if [[ $is_enabled == \"disabled\" ]]; then\n                        enable_xboxdrv \"$controllers\" \"$deadzone\"\n                    else\n                        disable_xboxdrv\n                    fi\n                    ;;\n                2)\n                    controllers=$(controllers_xboxdrv $controllers)\n                    ;;\n                3)\n                    deadzone=$(deadzone_xboxdrv $deadzone)\n                    ;;\n            esac\n        else\n            break\n        fi\n    done\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/xpad/01_enable_leds_and_trigmapping.diff",
    "content": "--- a/xpad.c\t2018-08-22 14:49:37.237360461 +0000\n+++ b/xpad.c\t2018-08-22 14:49:37.293357132 +0000\n@@ -86,6 +86,8 @@\n \n #define XPAD_PKT_LEN 64\n \n+#define CONFIG_JOYSTICK_XPAD_LEDS 1\n+\n /*\n  * xbox d-pads should map to buttons, as is required for DDR pads\n  * but we map them to axes when possible to simplify things\n@@ -1782,12 +1784,13 @@\n \n \t\tif (dpad_to_buttons)\n \t\t\txpad->mapping |= MAP_DPAD_TO_BUTTONS;\n-\t\tif (triggers_to_buttons)\n-\t\t\txpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;\n \t\tif (sticks_to_null)\n \t\t\txpad->mapping |= MAP_STICKS_TO_NULL;\n \t}\n \n+\tif (triggers_to_buttons)\n+\t\txpad->mapping |= MAP_TRIGGERS_TO_BUTTONS;\n+\n \tif (xpad->xtype == XTYPE_XBOXONE &&\n \t    intf->cur_altsetting->desc.bInterfaceNumber != 0) {\n \t\t/*\n"
  },
  {
    "path": "scriptmodules/supplementary/xpad/02_dkms_updates_folder.diff",
    "content": "diff --git a/dkms.conf b/dkms.conf\nindex 58a1ac2..b56b148 100644\n--- a/dkms.conf\n+++ b/dkms.conf\n@@ -2,6 +2,6 @@ PACKAGE_NAME=\"xpad\"\n PACKAGE_VERSION=\"0.4\"\n MAKE[0]=\"make KVERSION=$kernelver\"\n CLEAN=\"make clean\"\n-DEST_MODULE_LOCATION[0]=\"/extra\"\n+DEST_MODULE_LOCATION[0]=\"/updates\"\n BUILT_MODULE_NAME[0]=\"xpad\"\n AUTOINSTALL=\"yes\"\n"
  },
  {
    "path": "scriptmodules/supplementary/xpad/03_xpad_add_version.diff",
    "content": "diff --git a/xpad.c b/xpad.c\nindex 43985dd..8ea2991 100644\n@@ -2497,3 +2500,4 @@ module_usb_driver(xpad_driver);\n MODULE_AUTHOR(\"Marko Friedemann <mfr@bmx-chemnitz.de>\");\n MODULE_DESCRIPTION(\"X-Box pad driver\");\n MODULE_LICENSE(\"GPL\");\n+MODULE_VERSION(\"0.4\");\n"
  },
  {
    "path": "scriptmodules/supplementary/xpad.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xpad\"\nrp_module_desc=\"Updated Xpad Linux Kernel driver\"\nrp_module_help=\"This is the latest Xpad driver from https://github.com/paroj/xpad\\n\\nThe driver has been patched to allow the triggers to map to buttons for any controller and this has been enabled by default.\\n\\nThis fixes mapping the triggers in Emulation Station.\\n\\nIf you want the previous trigger behaviour please edit /etc/modprobe.d/xpad.conf and set triggers_to_buttons=0\"\nrp_module_licence=\"GPL2 https://www.kernel.org/pub/linux/kernel/COPYING\"\nrp_module_repo=\"git https://github.com/paroj/xpad.git master\"\nrp_module_section=\"driver\"\nrp_module_flags=\"noinstclean !mali\"\n\nfunction _version_xpad() {\n    echo \"0.4\"\n}\n\nfunction depends_xpad() {\n    local depends=(dkms LINUX-HEADERS)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_xpad() {\n    rm -rf \"$md_inst\"\n    gitPullOrClone \"$md_inst\"\n    cd \"$md_inst\"\n    # LED support (as disabled currently in packaged RPI kernel) and allow forcing MAP_TRIGGERS_TO_BUTTONS\n    applyPatch \"$md_data/01_enable_leds_and_trigmapping.diff\"\n    # Tell 'dkms' to use the 'updates' kernel module folder to store the module\n    applyPatch \"$md_data/02_dkms_updates_folder.diff\"\n\n    # Force a module version, otherwise 'dkms' refuses to override the built-in module\n    if ! grep -q MODULE_VERSION xpad.c; then\n        applyPatch \"$md_data/03_xpad_add_version.diff\"\n    fi\n}\n\nfunction build_xpad() {\n    dkmsManager install xpad \"$(_version_xpad)\"\n}\n\nfunction remove_xpad() {\n    dkmsManager remove xpad \"$(_version_xpad)\"\n}\n\nfunction configure_xpad() {\n    [[ \"$md_mode\" == \"remove\" ]] && return\n\n    dkmsManager reload xpad \"$(_version_xpad)\"\n}\n"
  },
  {
    "path": "scriptmodules/supplementary/xpadneo.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nrp_module_id=\"xpadneo\"\nrp_module_desc=\"Advanced Linux driver for Xbox One wireless gamepads\"\nrp_module_licence=\"GPL3 https://raw.githubusercontent.com/atar-axis/xpadneo/master/LICENSE\"\nrp_module_repo=\"git https://github.com/atar-axis/xpadneo.git :_version_xpadneo\"\nrp_module_section=\"driver\"\nrp_module_flags=\"nobin\"\n\nfunction _version_xpadneo() {\n    local build_version=v0.10\n\n    # buster and eariler get the v0.9.x version, due to v0.10 needing a newer Linux kernel\n    [[ \"$__os_debian_ver\" -lt 11 ]] && build_version=v0.9.8\n\n    echo \"$build_version\"\n}\n\nfunction depends_xpadneo() {\n    local depends=(dkms rsync LINUX-HEADERS)\n    getDepends \"${depends[@]}\"\n}\n\nfunction sources_xpadneo() {\n    gitPullOrClone\n    rsync -a --delete \"$md_build/hid-xpadneo/\" \"$md_inst/\"\n    cp \"$md_build/VERSION\" \"$md_inst/\"\n    local version=\"$(_version_xpadneo)\"\n    sed \"s/@DO_NOT_CHANGE@/$version/g\" \"$md_inst/dkms.conf.in\" > \"$md_inst/dkms.conf\"\n}\n\nfunction build_xpadneo() {\n    dkmsManager install hid-xpadneo \"$(_version_xpadneo)\"\n}\n\nfunction remove_xpadneo() {\n    dkmsManager remove hid-xpadneo \"$(_version_xpadneo)\"\n}\n\nfunction configure_xpadneo() {\n    if [[ \"$md_mode\" == \"remove\" ]]; then\n        rm -f /etc/modprobe.d/xpadneo-rpie.conf\n        return\n    fi\n\n    dkmsManager reload hid-xpadneo \"$(_version_xpadneo)\"\n\n    # on v0.10 and later - disable shift mode key for the home/guide button\n    local num_ver=\"$(_version_xpadneo | tr -d v)\"\n    if compareVersions \"$num_ver\" ge 0.10 && [[ ! -f \"/etc/modprobe.d/xpadneo-rpie.conf\" ]]; then\n        echo \"options hid-xpadneo disable_shift_mode=1\" > /etc/modprobe.d/xpadneo-rpie.conf\n    fi\n}\n"
  },
  {
    "path": "scriptmodules/system.sh",
    "content": "#!/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 developers, whose names are\n# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.\n#\n# See the LICENSE.md file at the top-level directory of this distribution and\n# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md\n#\n\nfunction setup_env() {\n\n    __ERRMSGS=()\n    __INFMSGS=()\n\n    # if no apt-get we need to fail\n    [[ -z \"$(which apt-get)\" ]] && fatalError \"Unsupported OS - No apt-get command found\"\n\n    test_chroot\n\n    get_platform\n    get_os_version\n\n    get_retropie_depends\n\n    conf_memory_vars\n    conf_binary_vars\n    conf_build_vars\n\n    if [[ -z \"$__nodialog\" ]]; then\n        __nodialog=0\n    fi\n}\n\nfunction test_chroot() {\n    # test if we are in a chroot\n    if [[ \"$(stat -c %d:%i /)\" != \"$(stat -c %d:%i /proc/1/root/.)\" ]]; then\n        [[ -z \"$QEMU_CPU\" && -n \"$__qemu_cpu\" ]] && export QEMU_CPU=$__qemu_cpu\n        __chroot=1\n    # detect the usage of systemd-nspawn\n    elif [[ -n \"$(systemd-detect-virt)\" && \"$(systemd-detect-virt)\" == \"systemd-nspawn\" ]]; then\n        __chroot=1\n    else\n        __chroot=0\n    fi\n}\n\n\nfunction conf_memory_vars() {\n    __memory_total_kb=$(awk '/^MemTotal:/{print $2}' /proc/meminfo)\n    __memory_total=$(( __memory_total_kb / 1024 ))\n    if grep -q \"^MemAvailable:\" /proc/meminfo; then\n        __memory_avail_kb=$(awk '/^MemAvailable:/{print $2}' /proc/meminfo)\n    else\n        local mem_free=$(awk '/^MemFree:/{print $2}' /proc/meminfo)\n        local mem_cached=$(awk '/^Cached:/{print $2}' /proc/meminfo)\n        local mem_buffers=$(awk '/^Buffers:/{print $2}' /proc/meminfo)\n        __memory_avail_kb=$((mem_free + mem_cached + mem_buffers))\n    fi\n    __memory_avail=$(( __memory_avail_kb / 1024 ))\n}\n\nfunction conf_binary_vars() {\n    [[ -z \"$__has_binaries\" ]] && __has_binaries=0\n\n    # set location of binary downloads\n    __binary_host=\"files.retropie.org.uk\"\n    __binary_base_url=\"https://$__binary_host/binaries\"\n\n    __os_binaries=\"$__os_codename\"\n    # add -64 suffix for 64bit\n    isPlatform \"64bit\" && __os_binaries+=\"-64\"\n    # add platform folder (eg. rpi4)\n    __binary_path=\"$__os_binaries/$__platform\"\n\n    # add kms folder when building for kms drivers\n    isPlatform \"kms\" && __binary_path+=\"/kms\"\n    __binary_url=\"$__binary_base_url/$__binary_path\"\n\n    __archive_url=\"https://files.retropie.org.uk/archives\"\n\n    # set the gpg key used by RetroPie\n    __gpg_retropie_key=\"retropieproject@gmail.com\"\n\n    # if __gpg_signing_key is not set, set to __gpg_retropie_key\n    [[ ! -v __gpg_signing_key ]] && __gpg_signing_key=\"$__gpg_retropie_key\"\n\n    # if the RetroPie public key is not installed, install it.\n    if ! gpg --list-keys \"$__gpg_retropie_key\" &>/dev/null; then\n        gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys DC9D77FF8208FFC51D8F50CCF1B030906A3B0D31\n    fi\n}\n\nfunction conf_build_vars() {\n    __gcc_version=$(gcc -dumpversion)\n    # extract only the major version\n    # gcc -dumpversion on GCC >= 7 seems to provide the major version but the documentation\n    # suggests this depends on how it's configured\n    __gcc_version=\"${__gcc_version%%.*}\"\n\n    # calculate build concurrency based on cores and available memory\n    __jobs=1\n    local unit=512\n    isPlatform \"64bit\" && unit=$(($unit + 256))\n    if [[ \"$(nproc)\" -gt 1 ]]; then\n        local nproc=\"$(nproc)\"\n        # max one thread per unit (MB) of ram\n        local max_jobs=$(($__memory_avail / $unit))\n        if [[ \"$max_jobs\" -gt 0 ]]; then\n            if [[ \"$max_jobs\" -lt \"$nproc\" ]]; then\n                __jobs=\"$max_jobs\"\n            else\n                __jobs=\"$nproc\"\n            fi\n        fi\n    fi\n    __default_makeflags=\"-j${__jobs}\"\n\n    # set our default gcc optimisation level\n    if [[ -z \"$__opt_flags\" ]]; then\n        __opt_flags=\"$__default_opt_flags\"\n    fi\n\n    # set default cpu flags\n    [[ -z \"$__cpu_flags\" ]] && __cpu_flags=\"$__default_cpu_flags\"\n\n    # if default cxxflags is empty, use our default cflags\n    [[ -z \"$__default_cxxflags\" ]] && __default_cxxflags=\"$__default_cflags\"\n\n    # add our cpu and optimisation flags\n    __default_cflags+=\" $__cpu_flags $__opt_flags\"\n    __default_cxxflags+=\" $__cpu_flags $__opt_flags\"\n    __default_asflags+=\" $__cpu_flags\"\n\n    # if not overridden by user, configure our compiler flags\n    [[ -z \"$__cflags\" ]] && __cflags=\"$__default_cflags\"\n    [[ -z \"$__cxxflags\" ]] && __cxxflags=\"$__default_cxxflags\"\n    [[ -z \"$__asflags\" ]] && __asflags=\"$__default_asflags\"\n    [[ -z \"$__makeflags\" ]] && __makeflags=\"$__default_makeflags\"\n\n    # workaround for GCC ABI incompatibility with threaded armv7+ C++ apps built\n    # on Raspbian's armv6 userland https://github.com/raspberrypi/firmware/issues/491\n    if [[ \"$__os_id\" == \"Raspbian\" ]] && compareVersions $__gcc_version lt 5; then\n        __cxxflags+=\" -U__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2\"\n    fi\n\n    # export our compiler flags so all child processes can see them\n    export CFLAGS=\"$__cflags\"\n    export CXXFLAGS=\"$__cxxflags\"\n    export ASFLAGS=\"$__asflags\"\n    export MAKEFLAGS=\"$__makeflags\"\n\n    # if __use_ccache is set, then add ccache to PATH/MAKEFLAGS\n    if [[ \"$__use_ccache\" -eq 1 ]]; then\n        PATH=\"/usr/lib/ccache:$PATH\"\n        MAKEFLAGS+=\" PATH=$PATH\"\n    fi\n}\n\nfunction get_os_version() {\n    # make sure lsb_release is installed\n    getDepends lsb-release\n\n    # get os distributor id, description, release number and codename\n    local os\n    # armbian uses a minimal shell script replacement for lsb_release with basic\n    # parameter parsing that requires the arguments split rather than using -sidrc\n    mapfile -t os < <(lsb_release -s -i -d -r -c)\n    __os_id=\"${os[0]}\"\n    __os_desc=\"${os[1]}\"\n    __os_release=\"${os[2]}\"\n    __os_codename=\"${os[3]}\"\n\n    local error=\"\"\n    case \"$__os_id\" in\n        Raspbian|Debian|Bunsenlabs)\n            # get major version (8 instead of 8.0 etc)\n            __os_debian_ver=\"${__os_release%%.*}\"\n\n            # Debian unstable is not officially supported though\n            if [[ \"$__os_release\" == \"unstable\" ]]; then\n                __os_debian_ver=14\n            fi\n\n            # we still allow Raspbian 8 (jessie) to work (We show an popup in the setup module)\n            if [[ \"$__os_debian_ver\" -lt 8 ]]; then\n                error=\"You need Raspbian/Debian Stretch or newer\"\n            fi\n\n            # 64bit Raspberry Pi OS identifies as Debian, but functions (currently) as Raspbian\n            # we will check package sources and set to Raspbian\n            if isPlatform \"aarch64\" && apt-cache policy | grep -qE \"archive.raspberrypi.(com|org)\"; then\n                __os_id=\"Raspbian\"\n            fi\n\n            # set a platform flag for osmc\n            if grep -q \"ID=osmc\" /etc/os-release; then\n                __platform_flags+=(osmc)\n            fi\n\n            # and for xbian\n            if grep -q \"NAME=XBian\" /etc/os-release; then\n                __platform_flags+=(xbian)\n            fi\n\n            # if __has_binaries is not set, and we are on the Raspberry Pi, check if we support binaries\n            if [[ -z \"$__has_binaries\" ]] && isPlatform \"rpi\"; then\n                # we currently support 32bit binaries on Raspberry Pi OS 10 & 11 and both 32/64bit binaries on Raspberry Pi OS 12\n                if ([[ \"$__os_debian_ver\" -ge 10 && \"$__os_debian_ver\" -le 11 ]] && isPlatform \"32bit\") \\\n                    || [[ \"$__os_debian_ver\" -eq 12 ]]; then\n                    __has_binaries=1\n                fi\n            fi\n            ;;\n        Devuan)\n            if isPlatform \"rpi\"; then\n                error=\"We do not support Devuan on the Raspberry Pi. We recommend you use Raspbian to run RetroPie.\"\n            fi\n            # devuan lsb-release version numbers don't match jessie\n            case \"$__os_codename\" in\n                jessie)\n                    __os_debian_ver=\"8\"\n                    ;;\n                ascii)\n                    __os_debian_ver=\"9\"\n                    ;;\n                beowolf)\n                    __os_debian_ver=\"10\"\n                    ;;\n                ceres)\n                    __os_debian_ver=\"11\"\n                    ;;\n            esac\n            ;;\n        LinuxMint|Linuxmint)\n            if [[ \"$__os_desc\" != LMDE* ]]; then\n                if compareVersions \"$__os_release\" lt 18; then\n                    error=\"You need Linux Mint 18 or newer\"\n                elif compareVersions \"$__os_release\" lt 19; then\n                    __os_ubuntu_ver=\"16.04\"\n                    __os_debian_ver=\"8\"\n                elif compareVersions \"$__os_release\" lt 20; then\n                    __os_ubuntu_ver=\"18.04\"\n                    __os_debian_ver=\"10\"\n                elif compareVersions \"$__os_release\" lt 21; then\n                    __os_ubuntu_ver=\"20.04\"\n                    __os_debian_ver=\"10\"\n                elif compareVersions \"$__os_release\" lt 22; then\n                    __os_ubuntu_ver=\"22.04\"\n                    __os_debian_ver=\"11\"\n                else\n                    __os_ubuntu_ver=\"24.04\"\n                    __os_debian_ver=\"12\"\n                fi\n            fi\n            if [[ \"$__os_desc\" == LMDE* ]]; then\n                if compareVersions \"$__os_release\" lt 4; then\n                    error=\"You need Linux Mint Debian Edition 4 or newer\"\n                elif compareVersions \"$__os_release\" lt 5; then\n                    __os_debian_ver=\"10\"\n                elif compareVersions \"$__os_release\" lt 6; then\n                    __os_debian_ver=\"11\"\n                else\n                    __os_debian_ver=\"12\"\n                fi\n            fi\n            ;;\n        Ubuntu|[Nn]eon|Pop)\n            if compareVersions \"$__os_release\" lt 16.04; then\n                error=\"You need Ubuntu 16.04 or newer\"\n            # although ubuntu 16.04/16.10 report as being based on stretch it is before some\n            # packages were changed - we map to version 8 to avoid issues (eg libpng-dev name)\n            elif compareVersions \"$__os_release\" le 16.10; then\n                __os_debian_ver=\"8\"\n            elif compareVersions \"$__os_release\" lt 18.04; then\n                __os_debian_ver=\"9\"\n            elif compareVersions \"$__os_release\" lt 20.04; then\n                __os_debian_ver=\"10\"\n            elif compareVersions \"$__os_release\" lt 22.10; then\n                __os_debian_ver=\"11\"\n            else\n                __os_debian_ver=\"12\"\n            fi\n            __os_ubuntu_ver=\"$__os_release\"\n            ;;\n        Zorin)\n            if compareVersions \"$__os_release\" lt 14; then\n                error=\"You need Zorin OS 14 or newer\"\n            elif compareVersions \"$__os_release\" lt 14; then\n                __os_debian_ver=\"8\"\n            else\n                __os_debian_ver=\"9\"\n            fi\n            __os_ubuntu_ver=\"$__os_release\"\n            ;;\n        Deepin)\n            if compareVersions \"$__os_release\" lt 15.5; then\n                error=\"You need Deepin OS 15.5 or newer\"\n            fi\n            __os_debian_ver=\"9\"\n            ;;\n        [eE]lementary)\n            if compareVersions \"$__os_release\" lt 0.4; then\n                error=\"You need Elementary OS 0.4 or newer\"\n            elif compareVersions \"$__os_release\" eq 0.4; then\n                __os_ubuntu_ver=\"16.04\"\n                __os_debian_ver=\"8\"\n            else\n                __os_ubuntu_ver=\"18.04\"\n                __os_debian_ver=\"10\"\n            fi\n            ;;\n        Kali)\n            __os_debian_ver=\"12\"\n            ;;\n        *)\n            error=\"Unsupported OS\"\n            ;;\n    esac\n\n    [[ -n \"$error\" ]] && fatalError \"$error\\n\\n$(lsb_release -idrc)\"\n\n    # check for Armbian, which can be built on Debian/Ubuntu\n    if [[ -f /etc/armbian-release ]]; then\n        __platform_flags+=(\"armbian\")\n    fi\n\n    # configure Raspberry Pi graphics stack\n    isPlatform \"rpi\" && get_rpi_video\n}\n\nfunction get_retropie_depends() {\n    local depends=(git gpg subversion dialog curl gcc g++ build-essential unzip xmlstarlet python3-pyudev ca-certificates dirmngr)\n    # on RaspiOS, install an extra package for X11 support on Pi5\n    if isPlatform \"rpi5\" && [[ \"$__os_id\" == \"Raspbian\" ]]; then\n        depends+=(gldriver-test)\n    fi\n\n    [[ -n \"$DISTCC_HOSTS\" ]] && depends+=(distcc)\n\n    [[ \"$__use_ccache\" -eq 1 ]] && depends+=(ccache)\n\n    if ! getDepends \"${depends[@]}\"; then\n        fatalError \"Unable to install packages required by $0 - ${md_ret_errors[@]}\"\n    fi\n\n    # make sure we don't have xserver-xorg-legacy installed as it breaks launching x11 apps from ES\n    if ! isPlatform \"x11\" && hasPackage \"xserver-xorg-legacy\"; then\n        aptRemove xserver-xorg-legacy\n    fi\n}\n\nfunction get_rpi_video() {\n    local pkgconfig=\"/opt/vc/lib/pkgconfig\"\n\n    if [[ -z \"$__has_kms\" ]]; then\n        if [[ \"$__chroot\" -eq 1 ]]; then\n            # in chroot, use kms by default for rpi4 or Debian 11 (bullseye) or newer\n            if isPlatform \"rpi4\" || [[ \"$__os_debian_ver\" -ge 11 ]]; then\n                __has_kms=1\n            fi\n        else\n            # detect driver via inserted module / platform driver setup\n            [[ -d \"/sys/module/vc4\" ]] && __has_kms=1\n        fi\n    fi\n\n    if [[ \"$__has_kms\" -eq 1 ]]; then\n        __platform_flags+=(mesa kms)\n        if ! isPlatform \"aarch64\" && [[ -z \"$__has_dispmanx\" ]]; then\n            if [[ \"$__chroot\" -eq 1 ]]; then\n                # in a chroot default to fkms (supporting dispmanx) when debian is older than 11 (bullseye)\n                [[ \"$__os_debian_ver\" -lt 11 ]] && __has_dispmanx=1\n            else\n                # if running fkms driver, add dispmanx flag\n                [[ \"$(ls -A /sys/bus/platform/drivers/vc4_firmware_kms/*.firmwarekms 2>/dev/null)\" ]] && __has_dispmanx=1\n            fi\n        fi\n        [[ \"$__has_dispmanx\" -eq 1 ]] && __platform_flags+=(dispmanx)\n    else\n        __platform_flags+=(videocore)\n        if ! isPlatform \"aarch64\"; then\n            __platform_flags+=(dispmanx)\n        fi\n    fi\n\n    # delete legacy pkgconfig that conflicts with Mesa (may be installed via rpi-update)\n    # see: https://github.com/raspberrypi/userland/pull/585\n    rm -rf $pkgconfig/{egl.pc,glesv2.pc,vg.pc}\n\n    # set pkgconfig path for vendor libraries\n    export PKG_CONFIG_PATH=\"$pkgconfig\"\n}\n\nfunction get_rpi_model() {\n    # calculated based on the information from https://github.com/AndrewFromMelbourne/raspberry_pi_revision\n    # see also https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#raspberry-pi-revision-codes\n    local rev=\"0x$(sed -n '/^Revision/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo)\"\n    # if bit 23 is not set, we are on a rpi1 (bit 23 means the revision is a bitfield)\n    if [[ $((($rev >> 23) & 1)) -eq 0 ]]; then\n        __platform=\"rpi1\"\n    else\n        # if bit 23 is set, get the cpu from bits 12-15\n        local cpu=$((($rev >> 12) & 15))\n        case $cpu in\n            0)\n                __platform=\"rpi1\"\n                ;;\n            1)\n                __platform=\"rpi2\"\n                ;;\n            2)\n                __platform=\"rpi3\"\n                ;;\n            3)\n                __platform=\"rpi4\"\n                ;;\n            4)\n                __platform=\"rpi5\"\n                ;;\n        esac\n    fi\n}\nfunction get_platform() {\n    local architecture=\"$(uname --machine)\"\n    if [[ -z \"$__platform\" ]]; then\n        case \"$(sed -n '/^Hardware/s/^.*: \\(.*\\)/\\1/p' < /proc/cpuinfo)\" in\n            BCM*)\n                # RPI kernels before 2023-11-24 print a 'Hardware: BCM2835' line\n                get_rpi_model\n                ;;\n            *ODROIDC)\n                __platform=\"odroid-c1\"\n                ;;\n            *ODROID-C2)\n                __platform=\"odroid-c2\"\n                ;;\n            \"Freescale i.MX6 Quad/DualLite (Device Tree)\")\n                __platform=\"imx6\"\n                ;;\n            *ODROID-XU[34])\n                __platform=\"odroid-xu\"\n                ;;\n            \"Rockchip (Device Tree)\")\n                __platform=\"tinker\"\n                ;;\n            Vero4K|Vero4KPlus)\n                __platform=\"vero4k\"\n                ;;\n            \"Allwinner sun8i Family\")\n                __platform=\"armv7-mali\"\n                ;;\n            *)\n                # jetsons can be identified by device tree or soc0/family (depending on the L4T version used)\n                # refer to the nv.sh script in the L4T DTS for a similar implementation\n                if [[ -e \"/proc/device-tree/compatible\" ]]; then\n                    case \"$(tr -d '\\0' < /proc/device-tree/compatible)\" in\n                        *raspberrypi*)\n                            get_rpi_model\n                            ;;\n                        *odroid-xu[3|4]*)\n                            __platform=\"odroid-xu\"\n                            ;;\n                        *tegra186*)\n                            __platform=\"tegra-x2\"\n                            ;;\n                        *tegra210*)\n                            __platform=\"tegra-x1\"\n                            ;;\n                        *tegra194*)\n                            __platform=\"xavier\"\n                            ;;\n                        *rockpro64*)\n                            __platform=\"rockpro64\"\n                            ;;\n                        *imx6dl*)\n                            __platform=\"imx6\"\n                            ;;\n                        *imx6q*)\n                            __platform=\"imx6\"\n                            ;;\n                        *imx8mm*)\n                            __platform=\"imx8mm\"\n                            ;;\n                        *rk3588*)\n                            __platform=\"rk3588\"\n                            ;;\n                    esac\n                elif [[ -e \"/sys/devices/soc0/family\" ]]; then\n                    case \"$(tr -d '\\0' < /sys/devices/soc0/family)\" in\n                        *tegra30*)\n                            __platform=\"tegra-3\"\n                            ;;\n                        *tegra114*)\n                            __platform=\"tegra-4\"\n                            ;;\n                        *tegra124*)\n                            __platform=\"tegra-k1-32\"\n                            ;;\n                        *tegra132*)\n                            __platform=\"tegra-k1-64\"\n                            ;;\n                        *tegra210*)\n                            __platform=\"tegra-x1\"\n                            ;;\n                    esac\n                else\n                    __platform=\"$architecture\"\n                fi\n                ;;\n        esac\n    fi\n\n    # check if we wish to target kms for platform\n    if [[ -z \"$__has_kms\" ]]; then\n        iniConfig \" = \" '\"' \"$configdir/all/retropie.cfg\"\n        iniGet \"force_kms\"\n        [[ \"$ini_value\" == 1 ]] && __has_kms=1\n        [[ \"$ini_value\" == 0 ]] && __has_kms=0\n    fi\n\n    set_platform_defaults\n\n    # if we have a function for the platform, call it, otherwise use the default \"native\" one.\n    if fnExists \"platform_${__platform}\"; then\n        platform_${__platform}\n    else\n        platform_native\n    fi\n}\n\nfunction set_platform_defaults() {\n    __default_opt_flags=\"-O2\"\n\n    # add platform name and 32bit/64bit to platform flags\n    __platform_flags=(\"$__platform\" \"$(getconf LONG_BIT)bit\")\n    __platform_arch=$(uname -m)\n}\n\nfunction cpu_arm1176() {\n    __default_cpu_flags=\"-mcpu=arm1176jzf-s -mfpu=vfp\"\n    __platform_flags+=(arm armv6)\n    __qemu_cpu=arm1176\n}\n\nfunction cpu_armv7() {\n    local cpu=\"$1\"\n    if [[ -n \"$cpu\" ]]; then\n        __default_cpu_flags=\"-mcpu=$cpu -mfpu=neon-vfpv4\"\n    else\n        __default_cpu_flags=\"-march=armv7-a -mfpu=neon-vfpv4\"\n        cpu=\"cortex-a7\"\n    fi\n    __platform_flags+=(arm armv7 neon)\n    __qemu_cpu=\"$cpu\"\n}\n\nfunction cpu_armv8() {\n    local cpu=\"$1\"\n    __default_cpu_flags=\"-mcpu=$cpu\"\n    if isPlatform \"32bit\"; then\n        __default_cpu_flags+=\"  -mfpu=neon-fp-armv8\"\n        __platform_flags+=(arm armv8 neon)\n    else\n        __platform_flags+=(aarch64)\n    fi\n    __qemu_cpu=\"$cpu\"\n}\n\nfunction cpu_arm_state() {\n    if isPlatform \"32bit\"; then\n        __default_cpu_flags+=\" -marm\"\n    fi\n}\n\nfunction platform_conf_glext() {\n   # required for mali-fbdev headers to define GL functions\n    __default_cflags=\"-DGL_GLEXT_PROTOTYPES\"\n}\n\nfunction platform_rpi1() {\n    cpu_arm1176\n    __platform_flags+=(rpi gles)\n}\n\nfunction platform_rpi2() {\n    cpu_armv7 \"cortex-a7\"\n    __platform_flags+=(rpi gles)\n}\n\nfunction platform_rockpro64() {\n    cpu_armv8 \"cortex-a53\"\n    __platform_flags+=(gles kms)\n}\n\nfunction platform_rpi3() {\n    cpu_armv8 \"cortex-a53\"\n    __platform_flags+=(rpi gles)\n}\n\nfunction platform_rpi4() {\n    cpu_armv8 \"cortex-a72\"\n    __platform_flags+=(rpi gles gles3 gles31)\n}\n\nfunction platform_rpi5() {\n    cpu_armv8 \"cortex-a76\"\n    __platform_flags+=(rpi gles gles3 gles31)\n}\n\nfunction platform_odroid-c1() {\n    cpu_armv7 \"cortex-a5\"\n    cpu_arm_state\n    __platform_flags+=(mali gles)\n}\n\nfunction platform_odroid-c2() {\n    cpu_armv8 \"cortex-a72\"\n    cpu_arm_state\n    __platform_flags+=(mali gles)\n}\n\nfunction platform_odroid-xu() {\n    cpu_armv7 \"cortex-a7\"\n    cpu_arm_state\n    platform_conf_glext\n    __platform_flags+=(mali gles)\n}\n\nfunction platform_tegra-x1() {\n    cpu_armv8 \"cortex-a57+crypto\"\n    __platform_flags+=(x11 gl vulkan)\n}\n\nfunction platform_tegra-x2() {\n    cpu_armv8 \"cortex-a57+crypto\"\n    __platform_flags+=(x11 gl vulkan)\n}\n\nfunction platform_xavier() {\n    cpu_armv8 \"native\"\n    __platform_flags+=(x11 gl vulkan)\n}\n\nfunction platform_tegra-3() {\n    cpu_armv7 \"cortex-a9\"\n    __platform_flags+=(x11 gles vulkan)\n}\n\nfunction platform_tegra-4() {\n    cpu_armv7 \"cortex-a15\"\n    __platform_flags+=(x11 gles vulkan)\n}\n\nfunction platform_tegra-k1-32() {\n    cpu_armv7 \"cortex-a15\"\n    __platform_flags+=(x11 gl vulkan)\n}\n\nfunction platform_tegra-k1-64() {\n    cpu_armv8 \"native\"\n    __platform_flags+=(x11 gl vulkan)\n}\n\nfunction platform_tinker() {\n    cpu_armv7 \"cortex-a17\"\n    cpu_arm_state\n    platform_conf_glext\n    __platform_flags+=(kms gles)\n}\n\nfunction platform_native() {\n    __default_cpu_flags=\"-march=native\"\n    __platform_flags+=(gl vulkan)\n    if [[ \"$__has_kms\" -eq 1 ]]; then\n        __platform_flags+=(kms)\n    else\n        __platform_flags+=(x11)\n    fi\n    # add x86 platform flag for x86/x86_64 archictures.\n    [[ \"$__platform_arch\" =~ (i386|i686|x86_64) ]] && __platform_flags+=(x86)\n}\n\nfunction platform_armv7-mali() {\n    cpu_armv7\n    __platform_flags+=(mali gles)\n}\n\nfunction platform_imx6() {\n    cpu_armv7 \"cortex-a9\"\n    [[ -d /sys/class/drm/card0/device/driver/etnaviv ]] && __platform_flags+=(x11 gles mesa)\n}\n\nfunction platform_imx8mm() {\n    cpu_armv8 \"cortex-a53\"\n    __platform_flags+=(x11 gles)\n    [[ -d /sys/class/drm/card0/device/driver/etnaviv ]] && __platform_flags+=(mesa)\n}\n\nfunction platform_rk3588() {\n    cpu_armv8 \"cortex-a76.cortex-a55\"\n    __platform_flags+=(x11 gles gles3 gles32)\n}\n\nfunction platform_vero4k() {\n    cpu_armv7 \"cortex-a7\"\n    __default_cflags=\"-I/opt/vero3/include -L/opt/vero3/lib\"\n    __platform_flags+=(mali gles)\n}\n"
  }
]