Merge remote-tracking branch 'upstream/stable-3.0' into update/3.0

This commit is contained in:
XargonWan 2024-02-19 15:32:54 +01:00
commit 119cc001a2
1183 changed files with 40169 additions and 5150 deletions

View file

@ -1,10 +1,9 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# EmulationStation Desktop Edition # ES-DE
# .clang-format # .clang-format
# #
# Style configuration file for automatic C++ code formatting using clang-format. # Style configuration file for automatic C++ and Java code formatting using clang-format.
# This file requires at least clang-format version 11.0.
# #
--- ---
@ -141,3 +140,17 @@ TabWidth: 8
UseCRLF: false UseCRLF: false
UseTab: Never UseTab: Never
... ...
---
Language: Java
BraceWrapping:
AfterClass: true
AfterFunction: true
BeforeCatch: true
BeforeElse: true
IndentBraces: false
BreakBeforeBraces: Custom
ColumnLimit: 100
IndentWidth: 4
TabWidth: 8
UseCRLF: false
UseTab: Never

42
.gitignore vendored
View file

@ -18,27 +18,33 @@
*.d *.d
# Compiled executable # Compiled executable
emulationstation /es-de
EmulationStation /ES-DE
EmulationStation.exe /ES-DE.exe
es-pdf-convert /es-pdf-convert
es-pdf-convert.exe /es-pdf-converter/es-pdf-convert.exe
# Emscripten build # Emscripten build
emulationstation.data es-de.data
emulationstation.html es-de.html
emulationstation.js es-de.js
emulationstation.wasm es-de.wasm
emulationstation.worker.js es-de.worker.js
/index.html /index.html
/ROMs /ROMs
# Android
/android
/logback.log
es-core/src/InputOverlay.*
es-core/src/utils/PlatformUtilAndroid.*
# AppImage # AppImage
AppDir AppDir
*.AppImage *.AppImage
# Core dumps # Core dumps
emulationstation.core es-de.core
# Profiling data # Profiling data
callgrind.out.* callgrind.out.*
@ -60,21 +66,21 @@ CMakeFiles
cmake_install.cmake cmake_install.cmake
Makefile Makefile
install_manifest.txt install_manifest.txt
EmulationStation.exe.manifest ES-DE.exe.manifest
# CPack # CPack
_CPack_Packages _CPack_Packages
emulationstation-de*.deb es-de*.deb
emulationstation-de*.rpm es-de*.rpm
EmulationStation-DE*.dmg ES-DE*.dmg
EmulationStation-DE*.exe ES-DE*.exe
# macOS # macOS
.DS_Store .DS_Store
# MSVC # MSVC
EmulationStation.ilk ES-DE.ilk
EmulationStation.pdb ES-DE.pdb
es-pdf-convert.ilk es-pdf-convert.ilk
es-pdf-convert.pdb es-pdf-convert.pdb
lunasvg.exp lunasvg.exp

532
ANDROID.md Normal file
View file

@ -0,0 +1,532 @@
# ES-DE (EmulationStation Desktop Edition) v3.0 (development version) - Android documentation
This document contains information specific to the Android release, for more general ES-DE documentation refer to the [User guide](USERGUIDE-DEV.md).
Table of contents:
[[_TOC_]]
## First startup and onboarding
When you first start ES-DE you will be greeted by a welcome screen, this is part of the _configurator_, the ES-DE onboarding interface. The configurator is easy to use and will guide you through the necessary setup steps.
As a first step you need to give ES-DE the required storage access permission or it will not be able to function. Just enable the setting and the configurator will proceed to the next step. Next you will need to define a application data directory where your settings, scraped media, custom collections and so on will be stored. By default this will be placed in the _ES-DE_ directory in the root of your device's internal storage, and this directory will be created for you automatically.
After this step you need to select a ROMs directory where your game files will be stored, by default this will be named _ROMs_ and will be located in the root of you device's internal storage. You can however choose to place this on an SD card if you want to, just change the path using the Android file selector GUI. If you do change the path to the SD card you will however need to manually create the ROMs directory as well as to delete the empty directory that was created for you in the built-in storage.
The next step is optional, and it's whether to create the game systems directory structure inside your ROMs folder. Performing this will also create _systeminfo.txt_ files in each system directory. These files contain information about the system such as what file extensions and emulators that are supported. They are not mandatory for the app to function, they are only there for your convenience. In general it's recommended to create the system directories, although you could remove the ones you don't need afterwards for a slightly faster app startup speed.
This is basically the onboarding process, and ES-DE should now start up. Just be aware that you need to place at least one game with a supported file extension in the ROMs directory tree or ES-DE will only show an information dialog about missing games.
Also note that ES-DE does not install any emulators, you need to install those separately. There is more information about that topic later in this document.
If you need to re-run the configurator for some reason then the easiest way is to go into the Android Apps setting screen and revoke the storage access permissions under _Special app access_. This will make the configurator run automatically next time you start ES-DE. Another way to force it to start is to clear the app's storage under _Storage & cache_ but this is normally not recommended as it also deletes all themes you have downloaded using the theme downloader. A third option would be to rename either the ES-DE or ROMs directory as this will also trigger the configurator on next app startup.
## Touch input overlay
By default the touch input overlay will be enabled which makes it possible to use ES-DE without a controller or physical keyboard by overlaying virtual buttons on top of the ES-DE interface. If you are using a device which has a built-in controller you may however want to disable this feature. That is done via the _Enable touch overlay_ option in the _Input device settings_ menu on the main menu. Just be aware that disabling this option on a device where you have no other input method than touch will lock you out of the application.
If you accidentally disable the touch overlay you can force the configurator to run as explained in the previous section above, this will always reset the touch overlay setting. Another option would of course be to temporarily plug in a controller or keyboard to enable the setting via its menu entry. A third option would be to manually edit the es_settings.xml file in the ES-DE application data directory. The setting you are after is named _InputTouchOverlay_ which should be changed from _false_ to _true_.
Apart from this there are numerous options for the touch overlay, like the ability to change its size, opacity and fade-out time. Setting the fade-out to zero will make it permanently visible. See the [User guide](USERGUIDE-DEV.md) for a complete reference of all app settings and features.
## Retention of files and data
Almost all files saved and used by ES-DE are kept in the shared storage on either the device's built-in storage or on the SD card. This means that uninstalling the ES-DE app will not remove any of that data. The only thing that will be deleted are themes that have been downloaded using the built-in theme downloader, as it's not possible to store these in the ES-DE application data directory for technical reasons.
## Emulation on Android in general
There are some challenges with emulation on Android. Some emulators on the Google Play store have not been updated for a long time, or like in the case with RetroArch they are crippled to comply with Google's rules and policies. And some emulators are not available on the Play store at all. For these reasons you will need to sideload some manually downloaded APKs for a good emulation setup. There is a section later in this document describing the best place to get hold of each supported emulator.
Thankfully sideloading emulators is not very difficult to do, the exact producedure for how to install APKs manually is not covered here but there are many resources available online on how to accomplish this.
There is also the [F-Droid](https://f-droid.org/) app store as an alternative to Google Play, and this service contains a couple of emulators that are not present on the Play store, or that are present there but haven't been updated for a very long time.
A number of emulators support the [FileProvider](https://developer.android.com/reference/androidx/core/content/FileProvider) API which makes it possible for ES-DE to temporarily provide storage access to the game ROMs on launch. This means that no access permission needs to be setup in the emulator upfront. For those emulators which do not support the FileProvider API, you will generally need to manually provide scoped storage access to each game system directory. Note that it's not supported to give access to the root of the entire ROM directory for emulators that use scoped storage, it has to be for the specific system. For instance `/storage/emulated/0/ROMs/n64` rather than `/storage/emulated/0/ROMs`.
Some emulators like RetroArch are still using an older storage access method and for those emulators this is not something you need to consider.
The following emulators are configured for FileProvider access:
* 2600.emu
* C64.emu
* GBA.emu
* GBC.emu
* Lynx.emu
* MD.emu
* MAME4droid 2024
* MAME4droid
* NES.emu
* NGP.emu
* PCE.emu
* Play!
* Ruffle
* Saturn.emu
* Swan.emu
* Yuzu
Some of these emulators still require BIOS files, so not all of them will be completely free from manual configuration.
The following emulators have partial FileProvider access support but are currently not configured for that in ES-DE:
* Dolphin (the FileProvider interface is broken on some devices)
* M64Plus FZ (the FileProvider interface doesn't work reliably and game launching randomly fails when using it)
* PPSSPP (the FileProvider interface doesn't work with .chd files specifically)
## Issues with the Ayn Odin 2
There are two serious issues that seem to be specific to the Ayn Odin 2, although it remains to be seen whether the problem exists also on other devices.
The first problem is that some emulators refuse to run games that you place inside directories that contain dots in their names. This is quite problematic as the [directories interpreted as files](USERGUIDE.md#directories-interpreted-as-files) functionality depends on the ability to add file extensions to directory names.
This has been observed with M64Plus FZ, Play!, Saturn.emu, FPse and FPseNG and it's working fine with RetroArch, NetherSX2, ePSXe, DuckStation and Yuzu. Note however that this is not a complete list as not all emulators have been tested for this problem.
If you run into this issue you can use the _folder link_ functionality as an alternative to the _directories interpreted as files_ functionality. How to use folder links is described in the [User guide](USERGUIDE.md).
The second problem is that a number of emulators can't be launched from ES-DE at all. When attempting to run such an emulator an error popup with the game name followed by "ERROR CODE -1" is displayed. The affected emulators are ColEm, fMSX, iNES, MasterGear, My Boy!, My OldBoy!, Redream and Speccy.
The following devices have been tested and do **not** experience either of these two problems:
* Ayn Odin Lite (Android 11)
* Retroid Pocket 4 Pro (Android 13)
* Google Pixel 4a (Android 13)
* Google Pixel Tablet (Android 14)
There are also some issues with sound quality on the Odin 2, such as large fluctuations in volume where some sounds are quite loud and some are quite silent. There are also some strange aliasing effects when playing samples rapidly.
## Known ES-DE problems
In addition to the issues specific to the Ayn Odin 2 there are a couple of other problems that will hopefully be resolved in the near future:
* Poor performance/low frame rate after startup on some devices, which seems to happen randomly and is usually resolved by itself within 10 to 30 seconds.
* The Android soft keyboard causes rendering issues when navigating using a controller or physical keyboard, as such the ES-DE built-in keyboard is enabled by default for the time being. For testing purposes the Android soft keyboard can be enabled via the _Enable virtual keyboard_ option in the _UI settings_ menu. If only using touch input the issue is not present. This problem is believed to be caused by a bug in the SDL library so it probably needs to be resolved there.
## Emulator installation and setup
Below are specific instructions and considerations for all supported emulators.
### RetroArch
The RetroArch release in the Play Store is not very good and is therefore not recommended. To get access to all cores make sure to instead manually download and install the 64-bit/aarch64 APK from their website.
https://retroarch.com/
Or you could alternatively install their release on the F-Droid store.
https://f-droid.org/en/packages/com.retroarch
Be aware that you need to manually install every core you want to use from inside the RetroArch user interface, and you also need to install all necessary BIOS files. The Android release of RetroArch is pretty unforgiving and will usually just present a black screen on game launch if the core file or the BIOS file is missing, and it will hang there until Android realizes the app is not responding and displays a popup where you can choose to kill the process.
### AetherSX2 / NetherSX2
Although the emulator entry is named AetherSX2 the recommended release of this emulator is actually the NetherSX2 patched version as the AetherSX2 release on the Google Play store doesn't work correctly and probably can't be used with ES-DE at all. You'll need to search for this APK online, the filename you'll want is `15210-v1.5-4248-noads.apk`
If you prefer to apply the NetherSX2 patch yourself (i.e. build the APK) then you can find all relevant information here:
https://github.com/Trixarian/NetherSX2-patch
### Citra
The version of Citra on the Google Play store is very old and barely works. Instead download either the Canary or Nightly builds from the Citra website or use the Citra MMJ fork:
https://citra-emu.org/download \
https://github.com/weihuoya/citra/releases
### ColEm
This emulator can be installed from the Play store. There is a paid version as well named ColEm Deluxe (ColEm+ ColecoVision Emulator is the store listing name).
Although this emulator supports both the Adam and ColecoVision systems it can unfortunately not do both interchangeably. In order to play Adam games you need to go into the Emulation settings in ColEm and tick the _Coleco Adam_ box. And likewise you'll need to untick it any time you want to play a ColecoVision game. This is true for launching games from ES-DE as well as starting them from inside the emulator GUI.
https://play.google.com/store/apps/details?id=com.fms.colem \
https://play.google.com/store/apps/details?id=com.fms.colem.deluxe
### Dolphin
The Play store version is somehow up to date and could be used, otherwise the F-Droid store version is up to date, or you could download the latest release directly from their website.
https://play.google.com/store/apps/details?id=org.dolphinemu.dolphinemu \
https://f-droid.org/en/packages/org.dolphinemu.dolphinemu \
https://dolphin-emu.org/download/
In the past there were multiple unofficial ports, but these are not really recommended any longer as most of them don't seem to have been updated in a long time and are likely to have been surpassed by the official Dolphin release.
### DraStic
This emulator can be installed from the Play store as a paid app. Note that it does not support launching of zipped game files.
https://play.google.com/store/apps/details?id=com.dsemu.drastic
### DuckStation
The Play store version of this emulator is getting frequent updates and is therefore recommended.
https://play.google.com/store/apps/details?id=com.github.stenzek.duckstation
### EKA2L1
This emulator can be downloaded from their GitHub site.
https://github.com/EKA2L1/EKA2L1/releases
There does not seem to be a way to launch individual EKA2L1 games from a frontend application on Android, instead ES-DE will simply launch the EKA2L1 user interface and you'll have to manually start your game from there.
### ePSXe
This emulator can be installed from the Play store as a paid app.
https://play.google.com/store/apps/details?id=com.epsxe.ePSXe
### EX Plus Alpha emulators
These set of emulators also known as the "Robert Broglia" emulators consist of 2600.emu, C64.emu, GBA.emu, GBC.emu, Lynx.emu, NEO.emu, NES.emu, NGP.emu, MD.emu, MSX.emu, PCE.emu, Snes9x EX+, Saturn.emu and Swan.emu
You can install them via Google Play (as paid apps) or download them from their GitHub automatic build system.
https://play.google.com/store/apps/developer?id=Robert+Broglia \
https://github.com/Rakashazi/emu-ex-plus-alpha/actions
There are also some BIOS files and similar that are needed to run these emulators, and which can be downloaded from their website.
https://www.explusalpha.com/
### Fake-08
This RetroArch core is a good port of the official PICO-8 game engine which does not exist on Android. It's not shipped with RetroArch by default though so you need to manaully install it. After download you'll need to place it inside's RetroArch's downloads directory and then install it from the RetroArch app. Details on how to accomplish this can be found on the Internet. Fake-08 can be downloaded from their GitHub site.
https://github.com/jtothebell/fake-08/releases
### Flycast
Flycast is not available on the Play store or the F-Droid store, but it can be downloaded from their GitHub site.
https://github.com/flyinghead/flycast/releases
### fMSX
This emulator can be installed from the Play store. There is a paid version as well named fMSX Deluxe (fMSX+ MSX/MSX2 Emulator is the store listing name).
https://play.google.com/store/apps/details?id=com.fms.fmsx \
https://play.google.com/store/apps/details?id=com.fms.fmsx.deluxe
### FPseNG and FPse
These emulators can be installed from the Play store as a paid apps. FPseNG is the more modern version so it's probably best to go for that. Note that these emulators do not support .chd files.
https://play.google.com/store/apps/details?id=com.emulator.fpse64 \
https://play.google.com/store/apps/details?id=com.emulator.fpse
### iNES
This emulator can be installed from the Play store.
https://play.google.com/store/apps/details?id=com.fms.ines.free
### MAME4droid 2024 and MAME4droid
These emulators can be installed from the Play store. It's strongly recommended to go for the _MAME4droid 2024_ version as this is updated with a frequent MAME release while the older _MAME4droid_ is using an ancient MAME release.
https://play.google.com/store/apps/details?id=com.seleuco.mame4d2024 \
https://play.google.com/store/apps/details?id=com.seleuco.mame4droid
### MasterGear
This emulator can be installed from the Play store as a paid app.
https://play.google.com/store/apps/details?id=com.fms.mg
### melonDS
This emulator can be installed from the Play store but it's quite buggy. Every time you add a new game to the ROM directory you need to start the emulator and manually refresh the game list or you won't be able to launch the game from ES-DE. Filenames containing parentheses also don't work and need to be renamed or they can't be launched from ES-DE. The same is probably true for a number of additional characters.
https://play.google.com/store/apps/details?id=me.magnum.melonds
### M64Plus FZ
This emulator can be installed from the Play store. The Pro version is recommended to avoid annoying ads.
https://play.google.com/store/apps/details?id=org.mupen64plusae.v3.fzurita.pro \
https://play.google.com/store/apps/details?id=org.mupen64plusae.v3.fzurita
### My Boy! and My OldBoy!
These emulators can be installed from the Play store as paid apps. There are also free/Lite versions availble for these emulators but they have not been updated in years and don't run on modern devices. As such they are not supported by ES-DE.
https://play.google.com/store/apps/details?id=com.fastemulator.gba \
https://play.google.com/store/apps/details?id=com.fastemulator.gbc
### Nesoid
Nesoid is not available on the Play store but it can be installed from the F-Droid store, or it can be downloaded from their GitHub site.
https://f-droid.org/en/packages/com.androidemu.nes \
https://github.com/proninyaroslav/nesoid/releases
### OpenBOR
Although OpenBOR is working fine on Android it's not possible to properly integrate it with a frontend, you'll instead need to install your game PAKs into the `/sdcard/OpenBOR/Paks` directory and create dummy .openbor files for your games in `ROMs/openbor` and after launching a game from ES-DE you need to manually start it from inside the OpenBOR GUI. There are more detailed setup instructions in the _OpenBOR_ section of the [User guide](USERGUIDE-DEV.md#openbor).
You can download OpenBOR from their GitHub site, the version named _OpenBOR v3.0 Build 6391_ has for example been proven to work well.
https://github.com/DCurrent/openbor/releases
### Pizza Boy GBA and Pizza Boy GBC
The Pizza Boy GBA and Pizza Boy GBC emulators can be installed from the Play store. There are Basic (free) versions and Pro (paid) versions available.
As of writing this, the Basic version of the GBA emulator does not seem to be able to launch games from ES-DE, but the Pro version is working fine. Both the Basic and Pro versions of the GBC emulator are working correctly.
https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboygba \
https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboygbapro \
https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboy \
https://play.google.com/store/apps/details?id=it.dbtecno.pizzaboypro
### Play!
This PlayStation 2 emulator can be downloaded from their website.
https://www.purei.org/downloads.php
### PPSSPP
The Play store version of this emulator is getting frequent updates and is therefore recommended. There is a paid Gold version as well which is functionally identical to the free version.
https://play.google.com/store/apps/details?id=org.ppsspp.ppsspp \
https://play.google.com/store/apps/details?id=org.ppsspp.ppssppgold
### Ruffle
This emulator can be downloaded from their GitHub site.
https://github.com/torokati44/ruffle-android/releases
### Real3DOPlayer
This 3DO Interactive Multiplayer emulator can be downloaded from their website.
http://www.arts-union.ru/node/23
### Redream
This emulator can be installed for free from the Play store and can later be upgraded to the Premium version from inside the application.
https://play.google.com/store/apps/details?id=io.recompiled.redream
### Speccy
This emulator can be installed from the Play store. There is a paid version as well named Speccy Deluxe (Speccy+ ZX Spectrum Emulator is the store listing name).
Although this emulator supports both the Sinclar ZX Spectrum and MGT SAM Coupé systems it can unfortunately not do both interchangeably. In order to play SAM Coupé games you need to go into the Emulation settings in Speccy and select _Sam Coupe_ from the _Computer Model_ selection screen. And likewise you'll need to change it back any time you want to play a ZX Spectrum game. This is true for launching games from ES-DE as well as starting them from inside the emulator GUI.
https://play.google.com/store/apps/details?id=com.fms.speccy \
https://play.google.com/store/apps/details?id=com.fms.speccy.deluxe
### Vita3K
This PlayStation Vita emulator can be downloaded from their GitHub site. Refer to the User guide for detailed game setup instructions.
https://github.com/Vita3K/Vita3K-Android/releases
### Yuzu
The Play store version of this emulator is getting frequent updates and is therefore recommended. There's an Early Access version as well which is also recommended.
https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu \
https://play.google.com/store/apps/details?id=org.yuzu.yuzu_emu.ea
## Supported game systems
All emulators are RetroArch cores unless marked as **(Standalone)**
The **@** symbol indicates that the emulator is _deprecated_ and will be removed in a future ES-DE release.
| System name | Full name | Default emulator | Alternative emulators | Needs BIOS | Recommended game setup |
| :-------------------- | :--------------------------------------------- | :-------------------------------- | :-------------------------------- | :----------- | :----------------------------------- |
| 3do | 3DO Interactive Multiplayer | Opera | Real3DOPlayer **(Standalone)** | Yes | |
| adam | Coleco Adam | ColEm **(Standalone)** | | No | |
| ags | Adventure Game Studio Game Engine | _Placeholder_ | | | |
| amiga | Commodore Amiga | PUAE | PUAE 2021 | Yes | |
| amiga1200 | Commodore Amiga 1200 | PUAE | PUAE 2021 | Yes | |
| amiga600 | Commodore Amiga 600 | PUAE | PUAE 2021 | Yes | |
| amigacd32 | Commodore Amiga CD32 | PUAE | PUAE 2021 | Yes | |
| amstradcpc | Amstrad CPC | Caprice32 | CrocoDS | No | Single archive or disk file |
| android | Google Android | _Placeholder_ | | | |
| apple2 | Apple II | _Placeholder_ | | | |
| apple2gs | Apple IIGS | _Placeholder_ | | | |
| arcade | Arcade | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>NEO.emu **(Standalone)**,<br>FinalBurn Neo,<br>FB Alpha 2012,<br>Flycast,<br>Flycast **(Standalone)** | Depends | |
| arcadia | Emerson Arcadia 2001 | _Placeholder_ | | | |
| archimedes | Acorn Archimedes | _Placeholder_ | | | |
| arduboy | Arduboy Miniature Game System | Arduous | | No | Single archive or .hex file |
| astrocde | Bally Astrocade | _Placeholder_ | | | |
| atari2600 | Atari 2600 | Stella | Stella 2014,<br>2600.emu **(Standalone)** | No | Single archive or ROM file |
| atari5200 | Atari 5200 | a5200 | Atari800 | Yes | Single archive or ROM file |
| atari7800 | Atari 7800 ProSystem | ProSystem | | Yes | Single archive or ROM file |
| atari800 | Atari 800 | Atari800 | | Yes | |
| atarijaguar | Atari Jaguar | Virtual Jaguar | | No | |
| atarijaguarcd | Atari Jaguar CD | _Placeholder_ | | | |
| atarilynx | Atari Lynx | Handy | Beetle Lynx,<br>Lynx.emu **(Standalone)** | No | Single archive or ROM file |
| atarist | Atari ST [also STE and Falcon] | Hatari | | Yes | Single archive or image file for single-diskette games, .m3u playlist for multi-diskette games |
| atarixe | Atari XE | Atari800 | | Yes | |
| atomiswave | Sammy Corporation Atomiswave | Flycast | Flycast **(Standalone)** | Depends | Single archive file |
| bbcmicro | Acorn Computers BBC Micro | _Placeholder_ | | | |
| c64 | Commodore 64 | VICE x64sc Accurate | VICE x64 Fast,<br>VICE x64 SuperCPU,<br>VICE x128,<br>C64.emu **(Standalone)** | No | Single archive or image file for tape, cartridge or single-diskette games, .m3u playlist for multi-diskette games |
| cdimono1 | Philips CD-i | SAME CDi | | Yes | Single .bin/.cue pair |
| cdtv | Commodore CDTV | PUAE | PUAE 2021 | Yes | |
| chailove | ChaiLove Game Engine | ChaiLove | | | |
| channelf | Fairchild Channel F | FreeChaF | | Yes | Single archive or ROM file |
| coco | Tandy Color Computer | _Placeholder_ | | | |
| colecovision | Coleco ColecoVision | blueMSX | Gearcoleco,<br>MSX.emu **(Standalone)**,<br>ColEm **(Standalone)** | Yes | Single archive or ROM file |
| consolearcade | Console Arcade Systems | _Placeholder_ | | | |
| cps | Capcom Play System | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>FinalBurn Neo,<br>FB Alpha 2012,<br>FB Alpha 2012 CPS-1,<br>FB Alpha 2012 CPS-2,<br>FB Alpha 2012 CPS-3 | Depends | |
| cps1 | Capcom Play System I | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>FinalBurn Neo,<br>FB Alpha 2012,<br>FB Alpha 2012 CPS-1 | Depends | |
| cps2 | Capcom Play System II | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>FB Alpha 2012,<br>FB Alpha 2012 CPS-2 | Depends | |
| cps3 | Capcom Play System III | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>FB Alpha 2012,<br>FB Alpha 2012 CPS-3 | Depends | |
| crvision | VTech CreatiVision | _Placeholder_ | | | |
| daphne | Daphne Arcade LaserDisc Emulator | DirkSimple | | No | |
| desktop | Desktop Applications | _Placeholder_ | | | |
| doom | Doom | PrBoom | | No | |
| dos | DOS (PC) | DOSBox-Pure | DOSBox-Core,<br>DOSBox-SVN | No | |
| dragon32 | Dragon Data Dragon 32 | _Placeholder_ | | | |
| dreamcast | Sega Dreamcast | Flycast | Flycast **(Standalone)**,<br>Redream **(Standalone)** | No | In separate folder interpreted as a file, with .m3u playlist if multi-disc game |
| easyrpg | EasyRPG Game Engine | EasyRPG | | No | |
| electron | Acorn Electron | _Placeholder_ | | | |
| emulators | Emulators | _Placeholder_ | | | |
| epic | Epic Games Store | _Placeholder_ | | | |
| famicom | Nintendo Family Computer | Mesen | Nestopia UE,<br>FCEUmm,<br>QuickNES,<br>NES.emu **(Standalone)**,<br>iNES **(Standalone)**,<br>Nesoid **(Standalone)** | No | Single archive or ROM file |
| fba | FinalBurn Alpha | FB Alpha 2012 | FB Alpha 2012 Neo Geo,<br>FB Alpha 2012 CPS-1,<br>FB Alpha 2012 CPS-2,<br>FB Alpha 2012 CPS-3 | Yes | |
| fbneo | FinalBurn Neo | FinalBurn Neo | | Yes | |
| fds | Nintendo Famicom Disk System | Mesen | Nestopia UE,<br>FCEUmm,<br>NES.emu **(Standalone)**,<br>iNES **(Standalone)**,<br>Nesoid **(Standalone)** | Yes | Single archive or ROM file |
| flash | Adobe Flash | Ruffle **(Standalone)** | | No | Single .swf file |
| fm7 | Fujitsu FM-7 | _Placeholder_ | | | |
| fmtowns | Fujitsu FM Towns | _Placeholder_ | | | |
| fpinball | Future Pinball | _Placeholder_ | | | |
| gamate | Bit Corporation Gamate | _Placeholder_ | | | |
| gameandwatch | Nintendo Game and Watch | Multi (MESS) | MAME4droid 2024 **(Standalone)**,<br>Handheld Electronic (GW) | No | Single archive or ROM file |
| gamecom | Tiger Electronics Game.com | _Placeholder_ | | | |
| gamegear | Sega Game Gear | Genesis Plus GX | Genesis Plus GX Wide,<br>Gearsystem,<br>SMS Plus GX,<br>PicoDrive,<br>MasterGear **(Standalone)** | No | Single archive or ROM file |
| gb | Nintendo Game Boy | Gambatte | SameBoy,<br>Gearboy,<br>TGB Dual,<br>DoubleCherryGB,<br>Mesen-S,<br>bsnes,<br>mGBA,<br>VBA-M,<br>GBC.emu **(Standalone)**,<br>My OldBoy! **(Standalone**),<br>Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
| gba | Nintendo Game Boy Advance | mGBA | VBA-M,<br>VBA Next,<br>gpSP,<br>GBA.emu **(Standalone)**,<br>My Boy! **(Standalone)**,<br>Pizza Boy GBA **(Standalone)** | No | Single archive or ROM file |
| gbc | Nintendo Game Boy Color | Gambatte | SameBoy,<br>Gearboy,<br>TGB Dual,<br>DoubleCherryGB,<br>Mesen-S,<br>bsnes,<br>mGBA,<br>VBA-M,<br>GBC.emu **(Standalone)**,<br>My OldBoy! **(Standalone**),<br>Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
| gc | Nintendo GameCube | Dolphin | Dolphin **(Standalone)** | No | Disc image file for single-disc games, .m3u playlist for multi-disc games |
| genesis | Sega Genesis | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | No | Single archive or ROM file |
| gmaster | Hartung Game Master | _Placeholder_ | | | |
| gx4000 | Amstrad GX4000 | Caprice32 | CrocoDS | No | Single archive or ROM file |
| intellivision | Mattel Electronics Intellivision | FreeIntv | | Yes | Single archive or ROM file |
| j2me | Java 2 Micro Edition (J2ME) | SquirrelJME | | No | Single .jar file |
| kodi | Kodi Home Theatre Software | _Placeholder_ | | | |
| laserdisc | LaserDisc Games | DirkSimple | | No | |
| lcdgames | LCD Handheld Games | Multi (MESS) | MAME4droid 2024 **(Standalone)**,<br>Handheld Electronic (GW) | No | Single archive or ROM file |
| lowresnx | LowRes NX Fantasy Console | LowRes NX | | No | Single ROM file |
| lutris | Lutris Open Gaming Platform | _Placeholder_ | | | |
| lutro | Lutro Game Engine | Lutro | | | |
| macintosh | Apple Macintosh | _Placeholder_ | | | |
| mame | Multiple Arcade Machine Emulator | MAME - Current | MAME 2010,<br>MAME 2003-Plus,<br>MAME 2000,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)**,<br>NEO.emu **(Standalone)**,<br>FinalBurn Neo,<br>FB Alpha 2012,<br>Flycast,<br>Flycast **(Standalone)** | Depends | |
| mame-advmame | AdvanceMAME | _Placeholder_ | | | |
| mastersystem | Sega Master System | Genesis Plus GX | Genesis Plus GX Wide,<br>SMS Plus GX,<br>Gearsystem,<br>PicoDrive,<br>MD.emu **(Standalone)**,<br>MasterGear **(Standalone)** | No | Single archive or ROM file |
| megacd | Sega Mega-CD | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | Yes | |
| megacdjp | Sega Mega-CD [Japan] | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | Yes | |
| megadrive | Sega Mega Drive | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | No | Single archive or ROM file |
| megadrivejp | Sega Mega Drive [Japan] | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | No | Single archive or ROM file |
| megaduck | Creatronic Mega Duck | SameDuck | | No | Single archive or ROM file |
| mess | Multi Emulator Super System | Multi (MESS) | | | |
| model2 | Sega Model 2 | MAME - Current | | Yes | |
| model3 | Sega Model 3 | _Placeholder_ | | | |
| moto | Thomson MO/TO Series | Theodore | | | |
| msx | MSX | blueMSX | fMSX,<br>fMSX **(Standalone)**,<br>MSX.emu **(Standalone)** | Yes except for fMSX standalone | |
| msx1 | MSX1 | blueMSX | fMSX,<br>fMSX **(Standalone)**,<br>MSX.emu **(Standalone)** | Yes except for fMSX standalone | |
| msx2 | MSX2 | blueMSX | fMSX,<br>fMSX **(Standalone)**,<br>MSX.emu **(Standalone)** | Yes except for fMSX standalone | |
| msxturbor | MSX Turbo R | blueMSX | fMSX,<br>MSX.emu **(Standalone)** | Yes | |
| mugen | M.U.G.E.N Game Engine | _Placeholder_ | | Yes | |
| multivision | Othello Multivision | Gearsystem | MasterGear **(Standalone)** | No | Single archive or ROM file |
| naomi | Sega NAOMI | Flycast | Flycast **(Standalone)** | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
| naomi2 | Sega NAOMI 2 | Flycast | Flycast **(Standalone)** | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
| naomigd | Sega NAOMI GD-ROM | Flycast | Flycast **(Standalone)** | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
| n3ds | Nintendo 3DS | Citra | Citra **(Standalone)** [Play store version or Nightly],<br>Citra Canary **(Standalone)**,<br>Citra MMJ **(Standalone)** | No | Single ROM file |
| n64 | Nintendo 64 | Mupen64Plus-Next | M64Plus FZ **(Standalone)**,<br>ParaLLEl N64 | No | Single archive or ROM file |
| n64dd | Nintendo 64DD | Mupen64Plus-Next | M64Plus FZ **(Standalone)**,<br>ParaLLEl N64 | Yes | |
| nds | Nintendo DS | melonDS DS | melonDS **(Standalone)**,<br>DeSmuME,<br>DeSmuME 2015,<br>DraStic **(Standalone)** | No | Single archive or ROM file |
| neogeo | SNK Neo Geo | FinalBurn Neo | NEO.emu **(Standalone)**,<br>MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)** | Yes | Single archive or ROM file |
| neogeocd | SNK Neo Geo CD | NeoCD | FinalBurn Neo | Yes | |
| neogeocdjp | SNK Neo Geo CD [Japan] | NeoCD | FinalBurn Neo | Yes | |
| nes | Nintendo Entertainment System | Mesen | Nestopia UE,<br>FCEUmm,<br>QuickNES,<br>NES.emu **(Standalone)**,<br>iNES **(Standalone)**,<br>Nesoid **(Standalone)** | No | Single archive or ROM file |
| ngage | Nokia N-Gage | EKA2L1 **(Standalone)** | | Yes | See the specific _Symbian and Nokia N-Gage_ section in the User guide |
| ngp | SNK Neo Geo Pocket | Beetle NeoPop | RACE,<br>NGP.emu **(Standalone)** | No | Single archive or ROM file |
| ngpc | SNK Neo Geo Pocket Color | Beetle NeoPop | RACE,<br>NGP.emu **(Standalone)** | No | Single archive or ROM file |
| odyssey2 | Magnavox Odyssey 2 | O2EM | | Yes | Single archive or ROM file |
| openbor | OpenBOR Game Engine | OpenBOR **(Standalone)** | | No | See the specific _OpenBOR_ section in the User guide |
| oric | Tangerine Computer Systems Oric | _Placeholder_ | | | |
| palm | Palm OS | Mu | | | |
| pc | IBM PC | DOSBox-Pure | DOSBox-Core,<br>DOSBox-SVN | No | |
| pc88 | NEC PC-8800 Series | QUASI88 | | Yes | |
| pc98 | NEC PC-9800 Series | Neko Project II Kai | Neko Project II | | |
| pcarcade | PC Arcade Systems | _Placeholder_ | | | | |
| pcengine | NEC PC Engine | Beetle PCE | Beetle PCE FAST,<br>PCE.emu **(Standalone)** | No | Single archive or ROM file |
| pcenginecd | NEC PC Engine CD | Beetle PCE | Beetle PCE FAST,<br>PCE.emu **(Standalone)** | Yes | |
| pcfx | NEC PC-FX | Beetle PC-FX | | Yes | |
| pico8 | PICO-8 Fantasy Console | Fake-08 | Retro8 | No | See the specific _PICO-8_ section in the User guide |
| plus4 | Commodore Plus/4 | VICE xplus4 | | No | Single archive or image file for tape, cartridge or single-diskette games, .m3u playlist for multi-diskette games |
| pokemini | Nintendo Pokémon Mini | PokeMini | | No | |
| ports | Ports | ECWolf (Wolfenstein 3D) | NXEngine (Cave Story),<br>OpenLara (Tomb Raider),<br>Super Bros War | Yes for ECWolf | |
| ps2 | Sony PlayStation 2 | AetherSX2 **(Standalone)** | Play! **(Standalone)** | Yes for AetherSX2 | |
| ps3 | Sony PlayStation 3 | _Placeholder_ | | | |
| ps4 | Sony PlayStation 4 | _Placeholder_ | | | |
| psp | Sony PlayStation Portable | PPSSPP | PPSSPP **(Standalone)** | No | Single disc image file |
| psvita | Sony PlayStation Vita | Vita3K **(Standalone)** | | Yes | See the specific _Sony PlayStation Vita_ section in the User guide |
| psx | Sony PlayStation | Beetle PSX | Beetle PSX HW,<br>PCSX ReARMed,<br>SwanStation,<br>DuckStation **(Standalone)**,<br>ePSXe **(Standalone)**,<br>FPseNG **(Standalone)**,<br>FPse **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
| pv1000 | Casio PV-1000 | _Placeholder_ | | | |
| quake | Quake | TyrQuake | vitaQuake 2,<br>vitaQuake 2 [Rogue],<br>vitaQuake 2 [Xatrix],<br>vitaQuake 2 [Zaero] | No | |
| samcoupe | MGT SAM Coupé | Speccy **(Standalone)** | | No | Single archive or ROM file |
| satellaview | Nintendo Satellaview | Snes9x - Current | Snes9x 2010,<br>Snes9x EX+ **(Standalone)**,<br>bsnes,<br>bsnes-hd,<br>bsnes-mercury Accuracy,<br>Mesen-S | | |
| saturn | Sega Saturn | Beetle Saturn | YabaSanshiro,<br>Yabause,<br>Saturn.emu **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
| saturnjp | Sega Saturn [Japan] | Beetle Saturn | YabaSanshiro,<br>Yabause,<br>Saturn.emu **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
| scummvm | ScummVM Game Engine | ScummVM | | No | |
| scv | Epoch Super Cassette Vision | _Placeholder_ | | | |
| sega32x | Sega Mega Drive 32X | PicoDrive | | No | Single archive or ROM file |
| sega32xjp | Sega Super 32X [Japan] | PicoDrive | | No | Single archive or ROM file |
| sega32xna | Sega Genesis 32X [North America] | PicoDrive | | No | Single archive or ROM file |
| segacd | Sega CD | Genesis Plus GX | Genesis Plus GX Wide,<br>PicoDrive,<br>MD.emu **(Standalone)** | Yes | |
| sfc | Nintendo SFC (Super Famicom) | Snes9x - Current | Snes9x 2010,<br>Snes9x EX+ **(Standalone)**,<br>bsnes,<br>bsnes-hd,<br>bsnes-mercury Accuracy,<br>Beetle Supafaust,<br>Mesen-S | No | Single archive or ROM file |
| sg-1000 | Sega SG-1000 | Genesis Plus GX | Genesis Plus GX Wide,<br>Gearsystem,<br>blueMSX,<br>MasterGear **(Standalone)** | No | Single archive or ROM file |
| sgb | Nintendo Super Game Boy | Mesen-S | SameBoy,<br>mGBA | | Single archive or ROM file |
| snes | Nintendo SNES (Super Nintendo) | Snes9x - Current | Snes9x 2010,<br>Snes9x EX+ **(Standalone)**,<br>bsnes,<br>bsnes-hd,<br>bsnes-mercury Accuracy,<br>Beetle Supafaust,<br>Mesen-S | No | Single archive or ROM file |
| snesna | Nintendo SNES (Super Nintendo) [North America] | Snes9x - Current | Snes9x 2010,<br>Snes9x EX+ **(Standalone)**,<br>bsnes,<br>bsnes-hd,<br>bsnes-mercury Accuracy,<br>Beetle Supafaust,<br>Mesen-S | No | Single archive or ROM file |
| solarus | Solarus Game Engine | _Placeholder_ | | | |
| spectravideo | Spectravideo | blueMSX | | | |
| steam | Valve Steam | _Placeholder_ | | | |
| stv | Sega Titan Video Game System | MAME - Current | MAME4droid 2024 **(Standalone)**,<br>MAME4droid **(Standalone)** | Yes | Single archive file |
| sufami | Bandai SuFami Turbo | Snes9x - Current | Snes9x 2010,<br>Snes9x EX+ **(Standalone)**,<br>bsnes,<br>bsnes-hd,<br>bsnes-mercury Accuracy | | |
| supergrafx | NEC SuperGrafx | Beetle SuperGrafx | Beetle PCE,<br>PCE.emu **(Standalone)** | No | Single archive or ROM file |
| supervision | Watara Supervision | Potator | | No | Single archive or ROM file |
| supracan | Funtech Super A'Can | _Placeholder_ | | | |
| switch | Nintendo Switch | Yuzu **(Standalone)** | | Yes | |
| symbian | Symbian | EKA2L1 **(Standalone)** | | Yes | See the specific _Symbian and Nokia N-Gage_ section in the User guide |
| tanodragon | Tano Dragon | _Placeholder_ | | | |
| tg16 | NEC TurboGrafx-16 | Beetle PCE | Beetle PCE FAST,<br>PCE.emu **(Standalone)** | No | Single archive or ROM file |
| tg-cd | NEC TurboGrafx-CD | Beetle PCE | Beetle PCE FAST,<br>PCE.emu **(Standalone)** | Yes | |
| ti99 | Texas Instruments TI-99 | _Placeholder_ | | | |
| tic80 | TIC-80 Fantasy Computer | TIC-80 | | No | Single .tic file |
| to8 | Thomson TO8 | Theodore | | | |
| triforce | Namco-Sega-Nintendo Triforce | _Placeholder_ | | | |
| trs-80 | Tandy TRS-80 | _Placeholder_ | | | |
| type-x | Taito Type X | _Placeholder_ | | | |
| uzebox | Uzebox Open Source Console | Uzem | | | |
| vectrex | GCE Vectrex | vecx | | No | Single archive or ROM file |
| vic20 | Commodore VIC-20 | VICE xvic | | No | Single archive or tape, cartridge or diskette image file |
| videopac | Philips Videopac G7000 | O2EM | | Yes | Single archive or ROM file |
| virtualboy | Nintendo Virtual Boy | Beetle VB | | No | |
| vpinball | Visual Pinball | _Placeholder_ | | | |
| vsmile | VTech V.Smile | _Placeholder_ | | | |
| wasm4 | WASM-4 Fantasy Console | WASM-4 | | No | Single .wasm file |
| wii | Nintendo Wii | Dolphin | Dolphin **(Standalone)** | No | |
| wiiu | Nintendo Wii U | _Placeholder_ | | | |
| windows | Microsoft Windows | _Placeholder_ | | | |
| windows3x | Microsoft Windows 3.x | DOSBox-Pure | | No | |
| windows9x | Microsoft Windows 9x | DOSBox-Pure | | No | |
| wonderswan | Bandai WonderSwan | Beetle Cygne | Swan.emu **(Standalone)** | No | Single archive or ROM file |
| wonderswancolor | Bandai WonderSwan Color | Beetle Cygne | Swan.emu **(Standalone)** | No | Single archive or ROM file |
| x1 | Sharp X1 | X Millennium | | No | Single archive or diskette/tape file |
| x68000 | Sharp X68000 | PX68k | | Yes | |
| xbox | Microsoft Xbox | _Placeholder_ | | | |
| xbox360 | Microsoft Xbox 360 | _Placeholder_ | | | |
| zmachine | Infocom Z-machine | _Placeholder_ | | | |
| zx81 | Sinclair ZX81 | EightyOne | | | |
| zxnext | Sinclair ZX Spectrum Next | _Placeholder_ | | | |
| zxspectrum | Sinclair ZX Spectrum | Fuse | Speccy **(Standalone)** | No | Single archive or ROM file |

View file

@ -1,4 +1,84 @@
# EmulationStation Desktop Edition (ES-DE) - Changelog # ES-DE (EmulationStation Desktop Edition) - Changelog
## Version 3.0.0
**Release date:** 2024-02-17
### Release overview
The 3.0 release rebrands the application from EmulationStation Desktop Edition to simply ES-DE. And as part of this the application data directory has changed from .emulationstation to ES-DE and its internal structure has been improved. There is also a new default theme named Linear that is bundled with the application.
Support for configurable font sizes has also been added, so assuming the theme supports it, it's now possible to select between these sizes from the _UI settings_ menu.
A number of minor improvements and bug fixes are also part of this release.
### Detailed list of changes
* Renamed the application from EmulationStation Desktop Edition to ES-DE
* Renamed the application data directory from .emulationstation to ES-DE
* Updated the splash screen to reflect the new application name
* Added a new default theme named "Linear"
* Split the es_find_rules.xml and es_systems.xml files for Linux and BSD Unix into separate directories
* Added support for defining font sizes from the theme configuration and selecting these from the UI settings menu
* Added the theme font sizes count to the theme downloader interface
* Added support for medium and large font sizes to the Slate and Modern themes
* Added an option to the Input device settings menu to swap the A/B and X/Y buttons
* Added support for .webp, .svg and unanimated .gif files to the slideshow screensaver when using a custom image directory
* Changed the default slideshow custom image directory from slideshow/custom_images to screensavers/custom_slideshow
* Changed the custom slideshow image directory setting from ScreensaverSlideshowImageDir to ScreensaverSlideshowCustomDir
* The HTTP error code will now be shown on scraper errors instead of the "File is smaller than 350 bytes" message
* Removed the ScraperHaltOnInvalidMedia option and corresponding menu entry as it has been superseded by the HTTP error code logic
* Added a ScraperIgnoreHTTP404Errors option that can be manually set in es_settings.xml to ignore 404 errors (i.e. resource not found)
* Added Mednafen standalone as an alternative emulator for the gb, gba, gbc and supergrafx systems
* Added Mesen standalone as an alternative emulator for the gamegear, mastersystem and multivision systems on Linux, Unix and Windows
* Added Mesen standalone as an alternative emulator for the sg-1000 and supergrafx systems on Linux, Unix and Windows
* Set Mesen standalone to specifically run in Super Game Boy mode for the sgb system on Linux, Unix and Windows
* Added the DoubleCherryGB RetroArch core as an alternative emulator for the gb and gbc systems on Linux, Unix and Windows
* Added the MAME - Current RetroArch core as the default emulator for the gameandwatch and lcdgames systems
* Added the melonDS DS RetroArch core as the default emulator for the nds system
* (Linux) Added support for the AppImage release of Vita3K
* (Linux) Added support for the Flatpak release of puNES
* Added the .zso file extension to the ps2 system
* Added the .zar file extension to the xbox360 system on Linux and Windows
* Added the .pk3 and .ipk3 file extensions to the doom system on Linux, Unix and Windows
* Added the .dirksimple file extension to the daphne and laserdisc systems
* (Unix) Removed the -Minimized flag from the Visual Pinball launch command
* (Windows) Updated the find rules for Visual Pinball to match the actual filenames of the official releases
* (Windows) Added the %RUNINBACKGROUND% variable for the epic system
* When scraping using ScreenScraper, the wheel and wheel-hd media types are now considered equivalent
* Added conversion of an additional HTML character code when scraping using ScreenScraper
* Added a "renderDuringTransitions" property to the image element
* Added a "selectorWidth" property to the textlist element
* Added a "hideIfZero" property to the rating element
* Putting the computer to sleep while a video is playing will no longer result in a massive fast-forward on resume
* Combining video pillarboxes with rounded corners will no longer round corners for the actual video frame (except for extreme values)
* Made the text element "defaultValue" property usable with the metadata types systemName, systemFullname, sourceSystemName and sourceSystemFullname
* Replaced the default d-pad helpsystem images to make them more legible when using smaller screen sizes
* Placeholder entries in es_systems.xml are now skipped by default when creating the system directories and systeminfo.txt files
* Added a CreatePlaceholderSystemDirectories option that can be manually set in es_settings.xml to still create placeholder directories
* Changed the ScreenScraper URL from https://www.screenscraper.fr/api2 to https://api.screenscraper.fr/api2
* Added support for more extreme vertical resolutions than previously allowed
* Added support for the 19.5:9, 20:9 and 1:1 display aspect ratios
* If any legacy theme configuration is encountered the error messages now simply state that the config is unsupported
* (Windows) Removed support for building the application using MinGW
* The relevant SDL error message is now printed to the log if a controller could not be added
* Added rendering workarounds for some mobile GPUs which do not support all OpenGL operations when using the BGRA pixel format
* Added the UTF8-CPP library as a dependency
* Updated SDL to 2.30.0 on Windows, macOS and the Linux AppImage builds
* Bundled the December 2023 release of the Mozilla TLS/SSL certificates
### Bug fixes
* Attempting to create the system directories with invalid entries in es_systems.xml could crash the application
* Sometimes controllers were not added correctly when there was a mix of supported and unsupported devices present
* The last grid row would sometimes not render correctly if fractionalRows was set to true
* Stationary image elements could sometimes glitch out during carousel navigation
* Videos were sometimes positioned incorrectly if combining pillarboxes with rounded corners while using an origin value higher than 0.5
* An extra space character was appended to text elements when setting the systemdata property to gamecountGames or gamecountGamesNoText
* Theme loading debug output would sometimes print incorrect paths when the configuration included files using variables
* Font textures were sometimes updated with empty glyhps which generated OpenGL errors on some mobile GPUs
* The custom collection editing popup did not show the correct button name if the controller type was a PlayStation variant
* The UI mode confirmation dialog did not show the correct button descriptions if the controller type was PlayStation 1/2/3
## Version 2.2.1 ## Version 2.2.1
@ -18,6 +98,8 @@ Some improvements were also made to the systems sorting functionality.
* The Orphaned data cleanup utility will now skip any system where a flatten.txt file is present * The Orphaned data cleanup utility will now skip any system where a flatten.txt file is present
* Changed a number of error messages in the Orphaned data cleanup utility from uppercase to lowercase * Changed a number of error messages in the Orphaned data cleanup utility from uppercase to lowercase
* The application release number is now tracked on startup instead of the application version * The application release number is now tracked on startup instead of the application version
* (macOS) Reclassified the application as a non-game to disable Game Mode on macOS 14 Sonoma
* (macOS) Added support for the Visual Pinball (vpinball) game system
* (slate-es-de) Added console graphics for the adam system * (slate-es-de) Added console graphics for the adam system
* Changed the systems sorting platform from "Peripheral" to "Console" for the fds, megacd, megacdjp, n64dd, pcenginecd and satellaview systems * Changed the systems sorting platform from "Peripheral" to "Console" for the fds, megacd, megacdjp, n64dd, pcenginecd and satellaview systems
* Changed the systems sorting platform from "Peripheral" to "Console" for the sega32x, sega32xjp, sega32xna, segacd, sgb, sufami and tg-cd systems * Changed the systems sorting platform from "Peripheral" to "Console" for the sega32x, sega32xjp, sega32xna, segacd, sgb, sufami and tg-cd systems

View file

@ -0,0 +1,32 @@
# FindOpenGLES
# ------------
# Finds the OpenGLES3 library
#
# This will define the following variables::
#
# OPENGLES3_FOUND - system has OpenGLES
# OPENGLES3_INCLUDE_DIRS - the OpenGLES include directory
# OPENGLES3_LIBRARIES - the OpenGLES libraries
if(NOT HINT_GLES_LIBNAME)
set(HINT_GLES_LIBNAME GLESv3)
endif()
find_path(OPENGLES3_INCLUDE_DIR GLES3/gl3.h
PATHS "${CMAKE_FIND_ROOT_PATH}/usr/include"
HINTS ${HINT_GLES_INCDIR}
)
find_library(OPENGLES3_gl_LIBRARY
NAMES ${HINT_GLES_LIBNAME}
HINTS ${HINT_GLES_LIBDIR}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(OpenGLES3 REQUIRED_VARS OPENGLES3_gl_LIBRARY OPENGLES3_INCLUDE_DIR)
if(OPENGLES3_FOUND)
set(OPENGLES3_LIBRARIES ${OPENGLES3_gl_LIBRARY})
set(OPENGLES3_INCLUDE_DIRS ${OPENGLES3_INCLUDE_DIR})
mark_as_advanced(OPENGLES3_INCLUDE_DIR OPENGLES3_gl_LIBRARY)
endif()

View file

@ -1,6 +1,6 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# EmulationStation Desktop Edition # ES-DE
# CMakeLists.txt # CMakeLists.txt
# #
# Main CMake configuration file. # Main CMake configuration file.
@ -11,15 +11,15 @@
cmake_minimum_required(VERSION 3.13) cmake_minimum_required(VERSION 3.13)
if(APPLE) if(APPLE)
# Set this to the minimum supported macOS version, and also update # Set this to the minimum supported macOS version, and also update
# es-app/assets/EmulationStation-DE_Info.plist accordingly. # es-app/assets/ES-DE_Info.plist accordingly.
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "macOS deployment target") set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "macOS deployment target")
# This optional variable is used for code signing the DMG installer. # This optional variable is used for code signing the DMG installer.
set(MACOS_CODESIGN_IDENTITY "" CACHE STRING "macOS code signing certificate identity") set(MACOS_CODESIGN_IDENTITY "" CACHE STRING "macOS code signing certificate identity")
endif() endif()
project(emulationstation-de) project(es-de)
# Application version, update this when making a new release. # Application version, update this when making a new release.
set(ES_VERSION 2.2.1) set(ES_VERSION 3.0.0)
# Set this to ON to show verbose compiler output (e.g. compiler flags, include directories etc.) # Set this to ON to show verbose compiler output (e.g. compiler flags, include directories etc.)
set(CMAKE_VERBOSE_MAKEFILE OFF CACHE BOOL "Show verbose compiler output" FORCE) set(CMAKE_VERBOSE_MAKEFILE OFF CACHE BOOL "Show verbose compiler output" FORCE)
@ -114,6 +114,8 @@ set_property(CACHE GLSYSTEM PROPERTY STRINGS "Desktop OpenGL" "Embedded OpenGL")
if(GLSYSTEM MATCHES "Desktop OpenGL") if(GLSYSTEM MATCHES "Desktop OpenGL")
set(OpenGL_GL_PREFERENCE GLVND) set(OpenGL_GL_PREFERENCE GLVND)
find_package(OpenGL REQUIRED) find_package(OpenGL REQUIRED)
elseif(ANDROID)
find_package(OpenGLES3 REQUIRED)
elseif(GLES AND NOT EMSCRIPTEN) elseif(GLES AND NOT EMSCRIPTEN)
find_package(OpenGLES2 REQUIRED) find_package(OpenGLES2 REQUIRED)
endif() endif()
@ -125,11 +127,10 @@ if(APPLE)
endif() endif()
find_package(CURL REQUIRED) find_package(CURL REQUIRED)
elseif(WIN32) elseif(WIN32)
if(NOT EXISTS ${PROJECT_SOURCE_DIR}/external/pugixml/libpugixml.dll AND # MinGW if(NOT EXISTS ${PROJECT_SOURCE_DIR}/external/pugixml/pugixml.dll)
NOT EXISTS ${PROJECT_SOURCE_DIR}/external/pugixml/pugixml.dll) # MSVC
message(FATAL_ERROR "-- You need to build the dependencies in ./external first") message(FATAL_ERROR "-- You need to build the dependencies in ./external first")
endif() endif()
elseif(NOT EMSCRIPTEN) elseif(NOT EMSCRIPTEN AND NOT ANDROID)
find_package(CURL REQUIRED) find_package(CURL REQUIRED)
find_package(FFmpeg REQUIRED) find_package(FFmpeg REQUIRED)
find_package(FreeImage REQUIRED) find_package(FreeImage REQUIRED)
@ -155,19 +156,16 @@ endif()
if(CMAKE_CXX_COMPILER_ID MATCHES Clang) if(CMAKE_CXX_COMPILER_ID MATCHES Clang)
message("-- Compiler is Clang/LLVM") message("-- Compiler is Clang/LLVM")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0.0)
message(SEND_ERROR "You need at least Clang 5.0.0 to compile EmulationStation-DE") message(SEND_ERROR "You need at least Clang 5.0.0 to compile ES-DE")
endif() endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES GNU) elseif(CMAKE_CXX_COMPILER_ID MATCHES GNU)
message("-- Compiler is GNU/GCC") message("-- Compiler is GNU/GCC")
if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1) if(CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.1)
message(SEND_ERROR "You need at least GCC 7.1 to compile EmulationStation-DE") message(SEND_ERROR "You need at least GCC 7.1 to compile ES-DE")
endif()
if(WIN32)
set(CMAKE_CXX_FLAGS "-mwindows ${CMAKE_CXX_FLAGS}")
endif() endif()
elseif(CMAKE_CXX_COMPILER_ID MATCHES MSVC) elseif(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
message("-- Compiler is MSVC") message("-- Compiler is MSVC")
# If using the MSVC compiler on Windows, disable the built-in min() and max() macros. # Disable the built-in min() and max() macros.
add_compile_definitions(NOMINMAX) add_compile_definitions(NOMINMAX)
endif() endif()
@ -218,12 +216,17 @@ if(APPLE AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-utf8") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-utf8")
endif() endif()
if(ANDROID)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -llog")
endif()
if(EMSCRIPTEN) if(EMSCRIPTEN)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_SDL=2 -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -s USE_SDL=2 -pthread")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s INITIAL_MEMORY=33554432 -s ALLOW_MEMORY_GROWTH=1 -s WASM=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=1 -s USE_SDL=2 \ set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s INITIAL_MEMORY=33554432 -s ALLOW_MEMORY_GROWTH=1 -s WASM=1 -s ASSERTIONS=1 -s EXIT_RUNTIME=1 -s USE_SDL=2 \
-pthread -s PTHREAD_POOL_SIZE=4 -s DEMANGLE_SUPPORT=1 -s USE_WEBGL2=1 -s FULL_ES3=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ASYNCIFY \ -pthread -s PTHREAD_POOL_SIZE=4 -s DEMANGLE_SUPPORT=1 -s USE_WEBGL2=1 -s FULL_ES3=1 -s ERROR_ON_UNDEFINED_SYMBOLS=1 -s ASYNCIFY \
--preload-file ${PROJECT_SOURCE_DIR}/resources@/home/web_user/.emulationstation/resources/ \ --preload-file ${PROJECT_SOURCE_DIR}/resources@/home/web_user/ES-DE/resources/ \
--preload-file ${PROJECT_SOURCE_DIR}/themes/slate-es-de@/home/web_user/.emulationstation/themes/slate-es-de/ \ --preload-file ${PROJECT_SOURCE_DIR}/themes/slate-es-de@/home/web_user/ES-DE/themes/slate-es-de/ \
--preload-file ${PROJECT_SOURCE_DIR}/ROMs@/home/web_user/ROMs/") --preload-file ${PROJECT_SOURCE_DIR}/ROMs@/home/web_user/ROMs/")
endif() endif()
@ -278,6 +281,16 @@ if(APPLE)
endif() endif()
endif() endif()
if(ANDROID)
set(BUNDLED_CERTS ON)
if(ANDROID_LITE_RELEASE)
add_compile_definitions(ANDROID_APPLICATION_ID="org.es_de.frontend.lite")
add_compile_definitions(ANDROID_LITE_RELEASE)
else()
add_compile_definitions(ANDROID_APPLICATION_ID="org.es_de.frontend")
endif()
endif()
if(WIN32) if(WIN32)
set(BUNDLED_CERTS ON) set(BUNDLED_CERTS ON)
add_compile_definitions(UNICODE) add_compile_definitions(UNICODE)
@ -348,7 +361,7 @@ if(VIDEO_HW_DECODING)
message("-- Building with FFmpeg HW decoding") message("-- Building with FFmpeg HW decoding")
endif() endif()
if(AUR_BUILD OR FLATPAK_BUILD OR RETRODECK OR RPI) if(AUR_BUILD OR FLATPAK_BUILD OR RETRODECK OR RPI OR ANDROID)
set(APPLICATION_UPDATER OFF) set(APPLICATION_UPDATER OFF)
endif() endif()
@ -379,6 +392,23 @@ if(APPLE)
endif() endif()
endif() endif()
if(ANDROID)
if(ANDROID_ABI MATCHES arm64-v8a)
message("-- Building for Android arm64-v8a on API level ${ANDROID_PLATFORM}")
set(ANDROID_CPU_ARCH arm64-v8a)
elseif(ANDROID_ABI MATCHES x86_64)
message("-- Building for Android x86_64 on API level ${ANDROID_PLATFORM}")
set(ANDROID_CPU_ARCH x86_64)
else()
message(FATAL_ERROR "-- Unsupported Android ABI: " ${ANDROID_ABI})
endif()
if(ANDROID_LITE_RELEASE)
message("-- Building Lite release")
else()
message("-- Building full release")
endif()
endif()
# Affects the application updater and is used for displaying version info in the main menu. # Affects the application updater and is used for displaying version info in the main menu.
if(ES_VERSION MATCHES alpha OR ES_VERSION MATCHES beta OR ES_VERSION MATCHES dev) if(ES_VERSION MATCHES alpha OR ES_VERSION MATCHES beta OR ES_VERSION MATCHES dev)
add_compile_definitions(IS_PRERELEASE) add_compile_definitions(IS_PRERELEASE)
@ -390,7 +420,7 @@ add_compile_definitions(GLM_FORCE_XYZW_ONLY)
# For Unix systems, assign the installation prefix. If it's not explicitly set, # For Unix systems, assign the installation prefix. If it's not explicitly set,
# we use /usr on Linux, /usr/pkg on NetBSD and /usr/local on FreeBSD and OpenBSD. # we use /usr on Linux, /usr/pkg on NetBSD and /usr/local on FreeBSD and OpenBSD.
if(NOT WIN32 AND NOT APPLE) if(NOT WIN32 AND NOT APPLE AND NOT ANDROID)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT) if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
if(CMAKE_SYSTEM_NAME MATCHES Linux) if(CMAKE_SYSTEM_NAME MATCHES Linux)
set(CMAKE_INSTALL_PREFIX /usr CACHE INTERNAL CMAKE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX /usr CACHE INTERNAL CMAKE_INSTALL_PREFIX)
@ -419,7 +449,9 @@ set(COMMON_INCLUDE_DIRS ${CURL_INCLUDE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/external/lunasvg/include ${CMAKE_CURRENT_SOURCE_DIR}/external/lunasvg/include
${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson/include ${CMAKE_CURRENT_SOURCE_DIR}/external/rapidjson/include
${CMAKE_CURRENT_SOURCE_DIR}/external/rlottie/inc ${CMAKE_CURRENT_SOURCE_DIR}/external/rlottie/inc
${CMAKE_CURRENT_SOURCE_DIR}/es-core/src) ${CMAKE_CURRENT_SOURCE_DIR}/external/utfcpp/source
${CMAKE_CURRENT_SOURCE_DIR}/es-core/src
${CMAKE_CURRENT_SOURCE_DIR}/es-pdf-converter/src)
if(APPLE) if(APPLE)
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS} set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS}
@ -446,6 +478,15 @@ elseif(EMSCRIPTEN)
${CMAKE_CURRENT_SOURCE_DIR}/external/FreeImage-CMake/FreeImage/Source ${CMAKE_CURRENT_SOURCE_DIR}/external/FreeImage-CMake/FreeImage/Source
${CMAKE_CURRENT_SOURCE_DIR}/external/freetype/include ${CMAKE_CURRENT_SOURCE_DIR}/external/freetype/include
${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src) ${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src)
elseif(ANDROID)
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS}
${CMAKE_CURRENT_SOURCE_DIR}/external/curl/include
${CMAKE_CURRENT_SOURCE_DIR}/external/ffmpeg-kit/src/ffmpeg
${CMAKE_CURRENT_SOURCE_DIR}/external/freeimage/FreeImage/Source
${CMAKE_CURRENT_SOURCE_DIR}/external/freetype/include
${CMAKE_CURRENT_SOURCE_DIR}/external/libgit2/include
${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL_Android)
else() else()
set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS} set(COMMON_INCLUDE_DIRS ${COMMON_INCLUDE_DIRS}
${FFMPEG_INCLUDE_DIRS} ${FFMPEG_INCLUDE_DIRS}
@ -491,44 +532,43 @@ if(APPLE)
${PROJECT_SOURCE_DIR}/libpugixml.a ${PROJECT_SOURCE_DIR}/libpugixml.a
${PROJECT_SOURCE_DIR}/libSDL2-2.0.0.dylib) ${PROJECT_SOURCE_DIR}/libSDL2-2.0.0.dylib)
elseif(WIN32) elseif(WIN32)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) set(COMMON_LIBRARIES ${PROJECT_SOURCE_DIR}/avcodec.lib
set(COMMON_LIBRARIES ${PROJECT_SOURCE_DIR}/avcodec.lib ${PROJECT_SOURCE_DIR}/avfilter.lib
${PROJECT_SOURCE_DIR}/avfilter.lib ${PROJECT_SOURCE_DIR}/avformat.lib
${PROJECT_SOURCE_DIR}/avformat.lib ${PROJECT_SOURCE_DIR}/avutil.lib
${PROJECT_SOURCE_DIR}/avutil.lib ${PROJECT_SOURCE_DIR}/swresample.lib
${PROJECT_SOURCE_DIR}/swresample.lib ${PROJECT_SOURCE_DIR}/swscale.lib
${PROJECT_SOURCE_DIR}/swscale.lib ${PROJECT_SOURCE_DIR}/FreeImage.lib
${PROJECT_SOURCE_DIR}/FreeImage.lib ${PROJECT_SOURCE_DIR}/git2.lib
${PROJECT_SOURCE_DIR}/git2.lib ${PROJECT_SOURCE_DIR}/glew32.lib
${PROJECT_SOURCE_DIR}/glew32.lib ${PROJECT_SOURCE_DIR}/libcurl-x64.lib
${PROJECT_SOURCE_DIR}/libcurl-x64.lib ${PROJECT_SOURCE_DIR}/freetype.lib
${PROJECT_SOURCE_DIR}/freetype.lib ${PROJECT_SOURCE_DIR}/lunasvg.lib
${PROJECT_SOURCE_DIR}/lunasvg.lib ${PROJECT_SOURCE_DIR}/pugixml.lib
${PROJECT_SOURCE_DIR}/pugixml.lib ${PROJECT_SOURCE_DIR}/rlottie.lib
${PROJECT_SOURCE_DIR}/rlottie.lib ${PROJECT_SOURCE_DIR}/SDL2main.lib
${PROJECT_SOURCE_DIR}/SDL2main.lib ${PROJECT_SOURCE_DIR}/SDL2.lib
${PROJECT_SOURCE_DIR}/SDL2.lib Winmm.dll)
Winmm.dll) elseif(ANDROID)
else() set(COMMON_LIBRARIES ${COMMON_LIBRARIES}
set(COMMON_LIBRARIES ${PROJECT_SOURCE_DIR}/avcodec-60.dll # FFmpeg libraries.
${PROJECT_SOURCE_DIR}/avfilter-9.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libavcodec.so
${PROJECT_SOURCE_DIR}/avformat-60.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libavfilter.so
${PROJECT_SOURCE_DIR}/avutil-58.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libavformat.so
${PROJECT_SOURCE_DIR}/swresample-4.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libavutil.so
${PROJECT_SOURCE_DIR}/swscale-7.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libswresample.so
${PROJECT_SOURCE_DIR}/FreeImage.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libswscale.so
${PROJECT_SOURCE_DIR}/libgit2.dll # Other dependencies.
${PROJECT_SOURCE_DIR}/glew32.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libcurl.so
${PROJECT_SOURCE_DIR}/libcurl-x64.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libcrypto.so
${PROJECT_SOURCE_DIR}/libfreetype.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libfreeimage.so
${PROJECT_SOURCE_DIR}/liblunasvg.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libfreetype.so
${PROJECT_SOURCE_DIR}/libpugixml.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libgit2.so
${PROJECT_SOURCE_DIR}/libSDL2main.a ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libjpeg.so
${PROJECT_SOURCE_DIR}/librlottie.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libpoppler.so
${PROJECT_SOURCE_DIR}/SDL2.dll ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libpugixml.a
mingw32 ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libSDL2.so
Winmm.dll) ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libssl.so)
endif()
elseif(EMSCRIPTEN) elseif(EMSCRIPTEN)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} set(COMMON_LIBRARIES ${COMMON_LIBRARIES}
# FFmpeg core libraries. # FFmpeg core libraries.
@ -573,16 +613,25 @@ else()
endif() endif()
if(NOT WIN32) if(NOT WIN32)
# SVG rendering library LunaSVG. # SVG rendering library LunaSVG and Lottie animation library rlottie.
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/liblunasvg.a) if(ANDROID)
# Lottie animation library rlottie. if(ANDROID_LITE_RELEASE)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/librlottie.a) set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/android_lite_${ANDROID_ABI}/liblunasvg.a)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/android_lite_${ANDROID_ABI}/librlottie.a)
else()
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/android_${ANDROID_ABI}/liblunasvg.a)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/android_${ANDROID_ABI}/librlottie.a)
endif()
else()
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/liblunasvg.a)
set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${PROJECT_SOURCE_DIR}/librlottie.a)
endif()
endif() endif()
if(APPLE) if(APPLE)
# See es-app/CMakeLists.txt for an explation for why an extra "Resources" directory # See es-app/CMakeLists.txt for an explation for why an extra "Resources" directory
# has been added to the install prefix. # has been added to the install prefix.
set(CMAKE_INSTALL_PREFIX "/Applications/EmulationStation Desktop Edition.app/Contents/Resources") set(CMAKE_INSTALL_PREFIX "/Applications/ES-DE.app/Contents/Resources")
# Set the same rpath links for the install executable as for the build executable. # Set the same rpath links for the install executable as for the build executable.
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
@ -611,6 +660,8 @@ endif()
# OpenGL. # OpenGL.
if(GLSYSTEM MATCHES "Desktop OpenGL") if(GLSYSTEM MATCHES "Desktop OpenGL")
list(APPEND COMMON_LIBRARIES ${OPENGL_LIBRARIES}) list(APPEND COMMON_LIBRARIES ${OPENGL_LIBRARIES})
elseif(GLES AND ANDROID)
list(APPEND COMMON_LIBRARIES ${OPENGLES3_LIBRARIES})
elseif(GLES) elseif(GLES)
list(APPEND COMMON_LIBRARIES ${OPENGLES2_LIBRARIES}) list(APPEND COMMON_LIBRARIES ${OPENGLES2_LIBRARIES})
endif() endif()
@ -631,5 +682,6 @@ add_subdirectory(es-app)
# Make sure that es-pdf-convert is built first, and then that rlottie is built before es-core. # Make sure that es-pdf-convert is built first, and then that rlottie is built before es-core.
# Also set lottie2gif to not be built. # Also set lottie2gif to not be built.
add_dependencies(lunasvg es-pdf-convert) add_dependencies(lunasvg es-pdf-convert)
add_dependencies(es-core rlottie) add_dependencies(es-core rlottie)
set_target_properties(lottie2gif PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1) set_target_properties(lottie2gif PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)

View file

@ -1,4 +1,4 @@
# EmulationStation Desktop Edition (ES-DE) - Contributing # ES-DE (EmulationStation Desktop Edition) - Contributing
### Help needed ### Help needed

View file

@ -1,11 +1,10 @@
# EmulationStation Desktop Edition (ES-DE) - Credits # ES-DE (EmulationStation Desktop Edition) - Credits
# Programming # Programming
**Desktop Edition**\ **ES-DE**\
Leon Styhre \ Leon Styhre \
Sophia Hadash \ Sophia Hadash
Joseph Geumlek
**RetroPie fork**\ **RetroPie fork**\
RetroPie community RetroPie community
@ -74,6 +73,9 @@ https://github.com/Samsung/rlottie
SDL \ SDL \
https://www.libsdl.org https://www.libsdl.org
UTF8-CPP \
https://github.com/nemtrif/utfcpp
Vorbis \ Vorbis \
https://gitlab.xiph.org/xiph/vorbis https://gitlab.xiph.org/xiph/vorbis

40
FAQ.md
View file

@ -1,20 +1,16 @@
# EmulationStation Desktop Edition (ES-DE) - Frequently Asked Questions # ES-DE (EmulationStation Desktop Edition) - Frequently Asked Questions
## What is this project and how is it related to other EmulationStation forks? ## What's the correct name for the application? ES-DE, EmulationStation etc?
This project started in 2020 as a fork of RetroPie EmulationStation and it has been in very active development ever since. Large parts of the application have been rewritten and much functionality has been added, so overall it's a quite different application by now. As of the 3.0.0 release the official name for the project and application is ES-DE or sometimes ES-DE Frontend. This stands for EmulationStation Desktop Edition as the project originated from the RetroPie fork of EmulationStation in 2020, and was originally intended for desktop computers. However the application has now changed so much that it would just cause confusion to keep the EmulationStation name. During a transition period EmulationStation Desktop Edition will be included as a subtitle on the splash screen and mentioned in some documentation entries, but long term this will be dropped entirely. The red version of the EmulationStation logo will however remain as it's part of the application legacy.
## What's the correct name? EmulationStation, ES-DE, Emulation Station, EmuStation etc?
The correct name is EmulationStation Desktop Edition, which is for practical reasons often shortened to EmulationStation-DE or more commonly ES-DE. It's not spelled Emulation Station (i.e. two separate words) in the same manner as you don't write Sony Play Station or Nintendo Game Cube.
## Is this software available for free, and is it open source? ## Is this software available for free, and is it open source?
ES-DE is available for free. Voluntary donations to support the project are however very welcome. The application is released under the MIT open source license with the source code readily available to anyone via the project's [GitLab site](https://gitlab.com/es-de/emulationstation-de). ES-DE is available for free on Windows, macOS and Linux and it's released under the MIT open source license.
## Which operating systems are supported? ## Which operating systems are supported?
ES-DE runs on Windows, macOS and BSD Unix as well as on multiple Linux distributions including Ubuntu, Fedora, Arch, Manjaro, SteamOS etc. ES-DE runs on Windows, macOS and multiple Linux distributions including Ubuntu, Fedora, Arch, Manjaro, SteamOS etc.
## What is the relationship between ES-DE and RetroDECK? ## What is the relationship between ES-DE and RetroDECK?
@ -22,7 +18,7 @@ ES-DE and [RetroDECK](http://retrodeck.net) are completely separate projects, bu
## What is the relationship between ES-DE and EmuDeck? ## What is the relationship between ES-DE and EmuDeck?
[EmuDeck](http://www.emudeck.com) is an installer that installs ES-DE and a number of emulators. There is no relationship between the two projects apart from this, and it's generally not recommended to use EmuDeck as this will lead to a non-standard installation. There are few tangible benefits to using EmuDeck over a manual installation apart from some convenience for the initial setup. Instead it's recommended to setup your emulators manually which will allow you to configure everything exactly to your liking. That is also a fun and interesting experience. EmuDeck is an installer that installs ES-DE and a number of emulators. There is no relationship between the two projects apart from this, and it's not recommended to use EmuDeck as this will lead to a non-standard installation and can cause a lot of other issues as well. Instead it's recommended to setup your emulators manually which will allow you to configure everything exactly to your liking.
## What game systems/platforms and emulators are supported by ES-DE? ## What game systems/platforms and emulators are supported by ES-DE?
@ -34,7 +30,7 @@ Menus in ES-DE are not lists but grids, sometimes there is only a list but somet
## Can I change the system sorting to not sort by full system names? ## Can I change the system sorting to not sort by full system names?
Yes the systems sorting configuration file can be selected via the _Systems sorting_ option in the _UI Settings_ menu. There are four such files bundled with ES-DE to sort by _"Release year", "Manufacturer, release year", "Hardware type, release year"_ and _"Manufacturer, hardware type, release year"_. If you don't want to use any of the bundled files then you can create your own custom sorting file and place it into the ~/.emulationstation/custom_systems/ directory. More details about this setup can be found in the _es_systems_sorting.xml_ section of the [Building and advanced configuration](INSTALL.md#es_systems_sortingxml) document. Yes the systems sorting configuration file can be selected via the _Systems sorting_ option in the _UI Settings_ menu. There are four such files bundled with ES-DE to sort by _"Release year", "Manufacturer, release year", "Hardware type, release year"_ and _"Manufacturer, hardware type, release year"_. If you don't want to use any of the bundled files then you can create your own custom sorting file and place it into the ~/ES-DE/custom_systems/ directory. More details about this setup can be found in the _es_systems_sorting.xml_ section of the [Building and advanced configuration](INSTALL.md#es_systems_sortingxml) document.
## I'm missing some systems like SNES MSU-1 and WiiWare, could those get added to ES-DE? ## I'm missing some systems like SNES MSU-1 and WiiWare, could those get added to ES-DE?
@ -46,7 +42,7 @@ ES-DE comes preconfigured with support for many alternative emulators, see the [
## I'm on Windows and ES-DE can't find my emulators, what is wrong? ## I'm on Windows and ES-DE can't find my emulators, what is wrong?
On Windows ES-DE is shipped as a portable installation and as a regular installer. If you're using the portable installation you need to drop your emulators inside the Emulators directory. Make sure to read the README.txt file directly in the EmulationStation-DE folder for more details. For the regular installer many emulators do not provide a method to inform ES-DE where they are installed, so you will need to add their installation directories to the Path environment variable in Windows. It's strongly recommended to read the _Specific notes for Windows_ section of the [User guide](USERGUIDE.md#specific-notes-for-windows) before attempting to setup and use ES-DE on Windows. On Windows ES-DE is shipped as a portable installation and as a regular installer. If you're using the portable installation you need to drop your emulators inside the Emulators directory. Make sure to read the README.txt file directly in the ES-DE folder for more details. For the regular installer many emulators do not provide a method to inform ES-DE where they are installed, so you will need to add their installation directories to the Path environment variable in Windows. It's strongly recommended to read the _Specific notes for Windows_ section of the [User guide](USERGUIDE.md#specific-notes-for-windows) before attempting to setup and use ES-DE on Windows.
## I'm on Windows and ES-DE refuses to start, is the application broken? ## I'm on Windows and ES-DE refuses to start, is the application broken?
@ -54,7 +50,7 @@ You're probably missing the OpenGL drivers required to run ES-DE. Try to downloa
## I'm on Windows and there is only a black screen shown on startup or when launching a game, is there a way to fix this? ## I'm on Windows and there is only a black screen shown on startup or when launching a game, is there a way to fix this?
This behavior has been observed for some specific AMD GPUs in the past. In some instances there is only a black screen on startup and in some instances the application starts and runs correctly but launching a game only shows a black screen. The issue is seemingly caused by GPU driver bugs and it only affects Windows as Linux works fine with the same hardware. The workaround is to make ES-DE run in windowed mode. You accomplish this by using the --resolution flag and setting the width to one pixel wider than your screen resolution. So if for instance running at a 1280x800 display resolution, run ES-DE such as this: `EmulationStation.exe --resolution 1281 800` This behavior has been observed for some specific AMD GPUs in the past. In some instances there is only a black screen on startup and in some instances the application starts and runs correctly but launching a game only shows a black screen. The issue is seemingly caused by GPU driver bugs and it only affects Windows as Linux works fine with the same hardware. The workaround is to make ES-DE run in windowed mode. You accomplish this by using the --resolution flag and setting the width to one pixel wider than your screen resolution. So if for instance running at a 1280x800 display resolution, run ES-DE such as this: `ES-DE.exe --resolution 1281 800`
## The emulators don't seem to be properly configured? ## The emulators don't seem to be properly configured?
@ -84,13 +80,9 @@ See the question above for a possible solution. Another approach would be to hid
No, by default games are not removed from the gamelists when they are hidden and are instead only marked with a much lower opacity. You need to disable the setting _Show hidden games_ from the _Other Settings_ menu to make them disappear entirely. The reason this option is not disabled by default is that new users could very easily make a mistake by hiding some files accidentally without realizing it, only to have the entries being immediately removed from the gamelist view. It's also good practice to hide all your games with this option enabled and verify that it's all correct before going ahead and disabling it. No, by default games are not removed from the gamelists when they are hidden and are instead only marked with a much lower opacity. You need to disable the setting _Show hidden games_ from the _Other Settings_ menu to make them disappear entirely. The reason this option is not disabled by default is that new users could very easily make a mistake by hiding some files accidentally without realizing it, only to have the entries being immediately removed from the gamelist view. It's also good practice to hide all your games with this option enabled and verify that it's all correct before going ahead and disabling it.
## I'm using Linux or macOS and I can't find the .emulationstation directory, where is it located?
The .emulationstation directory is normally located in your home directory, but on these Unix-based operating systems files and directories starting with a dot are hidden by default. So you need to enable hidden files and directories in your file manager. On macOS this is done in Finder using the Shift + Command + . (a dot) keyboard combination. On Linux it depends on which file manager you're using, but in KDE's Dolphin it's accomplished by using the Alt + . (a dot) keyboard combination or via the corresponding entry in the hamburger menu.
## I can't find a ROM directory setting in the user interface, so how do I relocate my games? ## I can't find a ROM directory setting in the user interface, so how do I relocate my games?
There is no need for such a setting as ES-DE will not start unless it finds at least one game. So you simply need to move your ROM directory to its new location using your operating system's file manager or terminal and then the next time you start ES-DE you will be shown a dialog where you can enter the new directory. Optionally you can manually change the ROMDirectory setting in ~/.emulationstation/es_settings.xml There is no need for such a setting as ES-DE will not start unless it finds at least one game. So you simply need to move your ROM directory to its new location using your operating system's file manager or terminal and then the next time you start ES-DE you will be shown a dialog where you can enter the new directory. Optionally you can manually change the ROMDirectory setting in ~/ES-DE/es_settings.xml
## What are miximages precisely and why don't they get updated when I change my miximage settings? ## What are miximages precisely and why don't they get updated when I change my miximage settings?
@ -98,7 +90,7 @@ As the name implies these are images, and more specifically they are generated b
## Is there a way to customize existing systems, and/or to add more systems than those shipped by default? ## Is there a way to customize existing systems, and/or to add more systems than those shipped by default?
Yes it's possible to both customize existing systems that are part of the bundled configuration as well as to add more systems than those shipped with ES-DE. Almost nothing is hardcoded in the application so there is a huge flexibility when it comes to such configuration. How this is done is covered in the _Game system customizations_ section of the [User guide](USERGUIDE.md#game-system-customizations). Just make sure to never modify the es_systems.xml and es_find_rules.xml files included in the application installation directory as these will be overwritten when upgrading ES-DE in the future. Always place your customizations in ~/.emulationstation/custom_systems/ as is also described in the user guide. Yes it's possible to both customize existing systems that are part of the bundled configuration as well as to add more systems than those shipped with ES-DE. Almost nothing is hardcoded in the application so there is a huge flexibility when it comes to such configuration. How this is done is covered in the _Game system customizations_ section of the [User guide](USERGUIDE.md#game-system-customizations). Just make sure to never modify the es_systems.xml and es_find_rules.xml files included in the application installation directory as these will be overwritten when upgrading ES-DE in the future. Always place your customizations in ~/ES-DE/custom_systems/ as is also described in the user guide.
## Can I use the Steam release of RetroArch? ## Can I use the Steam release of RetroArch?
@ -110,7 +102,7 @@ You would normally use the built-in theme downloader to install additional theme
## I added some EmulationStation themes manually but they don't seem to show up inside ES-DE? ## I added some EmulationStation themes manually but they don't seem to show up inside ES-DE?
Only themes made specifically for ES-DE can be used. If you want to use a theme from Batocera, Recalbox, RetroBat, RetroPie etc. then it first needs to be ported to the ES-DE theme engine. If you place a non-supported theme in the ~/.emulationtation/themes/ directory then this will be ignored on startup, meaning it will not be selectable from the _UI Settings_ menu. EmulationStation themes are not supported by ES-DE. If you want to use a theme from Batocera, Recalbox, RetroBat, RetroPie etc. then it first needs to be ported to the ES-DE theme engine. If you place a non-supported theme in the ES-DE/themes/ directory then this will be ignored on startup, meaning it will not be selectable from the _UI Settings_ menu.
## I used to be a Batocera/Recalbox user and ES-DE can't seem to find some of my games? ## I used to be a Batocera/Recalbox user and ES-DE can't seem to find some of my games?
@ -122,15 +114,11 @@ There is a built-in application updater that works with the Linux AppImage relea
## I can't find any game media links in the gamelist.xml files, where is this data stored? ## I can't find any game media links in the gamelist.xml files, where is this data stored?
ES-DE works differently compared to all other EmulationStation forks when it comes to handling of game media. There are no links in the gamelist.xml files, instead media files are matched against the ROM/game file names which makes for a much simpler, faster and completely portable setup. Migrating game media from other EmulationStation forks (and potentially from other frontends as well) can be accomplished quite easily. See the next question below for more information. Make sure to also read the _Migrating from other EmulationStation forks_ section of the [User guide](USERGUIDE.md#migrating-from-other-emulationstation-forks) to avoid data loss if running ES-DE with existing data from another EmulationStation fork. ES-DE works differently compared to EmulationStation when it comes to handling of game media. There are no links in the gamelist.xml files, instead media files are matched against the ROM/game file names which makes for a much simpler, faster and completely portable setup. Migrating game media from EmulationStation (and potentially from other frontends as well) can be accomplished quite easily. Make sure to also read the _Migrating from EmulationStation_ section of the [User guide](USERGUIDE.md#migrating-from-emulationstation) to avoid data loss if running ES-DE with existing data from EmulationStation.
## It seems like gamelist.xml files in the ROM directory tree are not getting loaded? ## It seems like gamelist.xml files in the ROM directory tree are not getting loaded?
These files are not loaded by default as of ES-DE 2.0.0, only files placed in .emulationstation/gamelists/ are processed. If you insist on retaining the old logic of also looking for gamelist.xml files in the ROM directory tree then you can enable the LegacyGamelistFileLocation setting in es_settings.xml as explained in the _Settings not configurable via the GUI_ section of the [Building and advanced configuration](INSTALL.md#settings-not-configurable-via-the-gui) document. These files are not loaded by default, only files placed in ES-DE/gamelists/ are processed. If you insist on also looking for gamelist.xml files in the ROM directory tree then you can enable the LegacyGamelistFileLocation setting in es_settings.xml as explained in the _Settings not configurable via the GUI_ section of the [Building and advanced configuration](INSTALL.md#settings-not-configurable-via-the-gui) document.
## Why do I sometimes get error messages when scraping stating that files are less than 350 bytes in size?
This issue can occur occassionally as the ScreenScraper servers sometimes return invalid responses, in this case simply pressing the _RETRY_ button often works. But there is also a ScreenScraper bug where their cache could include entries that no longer exist. When a media file is removed from the ScreenScraper database, the cached link to that file is retained for some time and will be returned as a valid media file URL to ES-DE. However, when attempting to scrape such a file, it will only contain the text string _NOMEDIA_ which will trigger this error in ES-DE. The cache bug only affects the multi-scraper API call, so a workaround is to manually scrape such games using the single-game scraper (reachable via the metadata editor). The invalid cache entries seem to disappear within 24 hours so waiting for a while and rescraping should also resolve the problem. The issue has been reported to the ScreenScraper team but it's unclear if and when it will be resolved.
## Can I use an external scraper application instead of the built-in scraper? ## Can I use an external scraper application instead of the built-in scraper?

File diff suppressed because it is too large Load diff

1150
INSTALL.md

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
Copyright (c) 2020-2023 Leon Styhre Copyright (c) 2020-2024 Leon Styhre
Copyright (c) 2014 Alec Lofquist Copyright (c) 2014 Alec Lofquist
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy

View file

@ -1,4 +1,4 @@
# EmulationStation Desktop Edition (ES-DE) # ES-DE (EmulationStation Desktop Edition)
EmulationStation Desktop Edition is a frontend for browsing and launching games from your multi-platform game collection. EmulationStation Desktop Edition is a frontend for browsing and launching games from your multi-platform game collection.

View file

@ -1,4 +1,4 @@
# EmulationStation Desktop Edition (ES-DE) - Feature roadmap # ES-DE (EmulationStation Desktop Edition) - Feature roadmap
ES-DE is developed using an agile methodology so which features to include per release is reviewed and adjusted continuously. As such this document is basically a list of the main features that are planned to be added eventually. ES-DE is developed using an agile methodology so which features to include per release is reviewed and adjusted continuously. As such this document is basically a list of the main features that are planned to be added eventually.

View file

@ -1,8 +1,8 @@
# EmulationStation Desktop Edition (ES-DE) v2.2 (development version) - Themes # ES-DE (EmulationStation Desktop Edition) v3.0 (development version) - Themes
**Note:** This document is only relevant for the current ES-DE development version, if you would like to see the documentation for the latest stable release, refer to [THEMES.md](THEMES.md) instead. **Note:** This document is only relevant for the current ES-DE development version, if you would like to see the documentation for the latest stable release, refer to [THEMES.md](THEMES.md) instead.
If creating themes specifically for ES-DE, please add `-es-de` to the repository/directory name, as in `slate-es-de`. Themes made for ES-DE are not compatible with any other EmulationStation forks (and vice versa) and the -es-de extension makes it clear that it's an ES-DE theme. The actual theme name as defined using the `themeName` tag in capabilities.xml does of course not need to include the `-es-de` extension as that's the actual theme name that will be displayed when selecting themes from the _UI Settings_ menu. For example slate-es-de will be listed simply as _Slate_ in this menu. If creating themes for ES-DE, please add `-es-de` to the repository/directory name to clearly indicate that it's a theme for this frontend. Two examples would be `linear-es-de` and `modern-es-de`. The actual theme name as defined using the `themeName` tag in capabilities.xml does of course not need to include the `-es-de` extension as that's the actual theme name that will be displayed when selecting themes from the _UI Settings_ menu. For example linear-es-de will be listed simply as _Linear_ in this menu.
Before your start, make sure to download the _Theme engine examples_ theme that contains a number of example variants for things like vertical and horizontal carousels, wheel carousels, system view text lists, grids etc: Before your start, make sure to download the _Theme engine examples_ theme that contains a number of example variants for things like vertical and horizontal carousels, wheel carousels, system view text lists, grids etc:
@ -18,7 +18,7 @@ https://github.com/lilbud/es-de-theme-stuff
To test whether your theme includes support for all ES-DE systems, download one of the following archives which contain ROM directory trees fully populated with dummy files: To test whether your theme includes support for all ES-DE systems, download one of the following archives which contain ROM directory trees fully populated with dummy files:
[ROMs_ALL_Unix.zip](tools/system-dirs-dummy-files/ROMs_ALL_Unix.zip)\ [ROMs_ALL_Linux.zip](tools/system-dirs-dummy-files/ROMs_ALL_Linux.zip)\
[ROMs_ALL_macOS.zip](tools/system-dirs-dummy-files/ROMs_ALL_macOS.zip)\ [ROMs_ALL_macOS.zip](tools/system-dirs-dummy-files/ROMs_ALL_macOS.zip)\
[ROMs_ALL_Windows.zip](tools/system-dirs-dummy-files/ROMs_ALL_Windows.zip) [ROMs_ALL_Windows.zip](tools/system-dirs-dummy-files/ROMs_ALL_Windows.zip)
@ -158,17 +158,19 @@ Note that the legacy theme engine had quite inaccurate text sizing and font rend
* The defined line spacing was not always applied for automatically sized text elements * The defined line spacing was not always applied for automatically sized text elements
* Font sizes were rounded to integers, leading to imprecise text sizing across different resolutions (the rounding was also done incorrectly) * Font sizes were rounded to integers, leading to imprecise text sizing across different resolutions (the rounding was also done incorrectly)
## System metadata and logo repositories ## Theme assets repositories
There are two useful repositories hosted by the ES-DE project that provide system metadata and system logotypes. This greatly simplifies the work of adding support for all systems that ES-DE supports. There are several useful repositories hosted by the ES-DE project that provide system metadata and system graphics files. Using these greatly simplifies the work of adding support for all ES-DE systems to your theme.
**Metadata** Make sure to regularly check for updates in these repositories as corrections, improvements and additions of new systems are made continuously.
### Metadata
The metadata repository provides descriptions, release dates, per-system color palettes etc. and it can be found here: The metadata repository provides descriptions, release dates, per-system color palettes etc. and it can be found here:
https://gitlab.com/es-de/themes/system-metadata https://gitlab.com/es-de/themes/system-metadata
By adding this to your theme, either via manually downloading and including it, or by adding it as a Git subtree, you'll be able to access its defined variables. Make sure to regularly check for updates as corrections and additions of new systems are done continuously. Also check the README.md file in the repository for more details on how to actually use the variables. By adding this to your theme, either via manually downloading and including it, or by adding it as a Git subtree, you'll be able to access its defined variables. Check the README.md file in the repository for details on how to actually use the variables.
Here's how to add this repository as a subtree inside your theme's Git repository: Here's how to add this repository as a subtree inside your theme's Git repository:
``` ```
@ -183,9 +185,47 @@ git subtree pull --prefix=system-metadata --squash system-metadata master
The directory name can be changed to whatever you like using the --prefix flag. The directory name can be changed to whatever you like using the --prefix flag.
**Logos** ### Controller outline graphics
Likewise there's a repository of system logotypes that can also be added and used in the same fashion as the metadata. It can be found here: This repository provides controller graphics files for each system in an outline style and it can be found here:
https://gitlab.com/es-de/themes/system-controllers-outline
Here's how to add this repository as a subtree inside your theme's Git repository:
```
git remote add system-controllers-outline https://gitlab.com/es-de/themes/system-controllers-outline.git
git subtree add --prefix=system-controllers-outline --squash system-controllers-outline master
```
To later pull in repository updates you'll run the following:
```
git subtree pull --prefix=system-controllers-outline --squash system-controllers-outline master
```
The directory name can be changed to whatever you like using the --prefix flag.
### Mini system graphics
This repository provides graphics files for each system in a "mini" style and it can be found here:
https://gitlab.com/es-de/themes/system-graphics-mini
Here's how to add this repository as a subtree inside your theme's Git repository:
```
git remote add system-graphics-mini https://gitlab.com/es-de/themes/system-graphics-mini.git
git subtree add --prefix=system-graphics-mini --squash system-graphics-mini master
```
To later pull in repository updates you'll run the following:
```
git subtree pull --prefix=system-graphics-mini --squash system-graphics-mini master
```
The directory name can be changed to whatever you like using the --prefix flag.
### Logos
This repository provides logos for each system in color and white (the latter for use with color shifting) and it can be found here:
https://gitlab.com/es-de/themes/system-logos https://gitlab.com/es-de/themes/system-logos
@ -202,11 +242,13 @@ git subtree pull --prefix=system-logos --squash system-logos master
The directory name can be changed to whatever you like using the --prefix flag. The directory name can be changed to whatever you like using the --prefix flag.
**Adding remotes** ### Adding remotes
Note that the remotes are only setup for your local repository, so if you clone a theme you'll need to manually add the system-metadata and/or system-logos remotes to be able to pull to these subtrees. That means you'll need to run the following commands on a freshly cloned theme repository: Note that the remotes are only setup for your local repository, so if you clone a theme you'll need to manually add the repository remotes to be able to pull from these subtrees. That means you'll need to run one or more of the following commands on a freshly cloned theme repository:
``` ```
git remote add system-metadata https://gitlab.com/es-de/themes/system-metadata.git git remote add system-metadata https://gitlab.com/es-de/themes/system-metadata.git
git remote add system-controllers-outline https://gitlab.com/es-de/themes/system-controllers-outline.git
git remote add system-graphics-mini https://gitlab.com/es-de/themes/system-graphics-mini.git
git remote add system-logos https://gitlab.com/es-de/themes/system-logos.git git remote add system-logos https://gitlab.com/es-de/themes/system-logos.git
``` ```
After doing this you'll be able to pull repository updates as described above. After doing this you'll be able to pull repository updates as described above.
@ -611,6 +653,95 @@ Here's an example configuration:
</theme> </theme>
``` ```
## Font sizes
The optional font sizes functionality makes it possible to use a set of predefined size options and connect these to theme variables that can be used to apply different text sizes and related design changes. The font sizes declared for the theme can be selected via the _Theme font size_ setting in the _UI Settings_ menu.
To understand the basics on how to use variables, make sure to read the _Theme variables_ section elsewhere in this document.
To use the font size entries you first need to declare them using `<fontSize>` tag pairs in the `capabilities.xml` file. The following sizes are available:
| capabilities.xml name | UI Settings label |
| :-------------------- | :--------------- |
| medium | medium |
| large | large |
| small | small |
| x-large | extra large |
| x-small | extra small |
The options will always be listed in the above order in the _UI Settings_ menu.
Here's an example of a theme that implements three of these sizes:
```xml
<!-- Theme capabilities for mytheme-es-de -->
<themeCapabilities>
<themeName>My theme</themeName>
<fontSize>medium</fontSize>
<fontSize>small</fontSize>
<fontSize>x-small</fontSize>
</themeCapabilities>
```
In the theme configuration you'll also use a `<fontSize>` tag pair combined with a `<variable>` tag pair to define the variables you want to apply per font size.
These `<fontSize>` tag pairs can be placed directly inside the `<theme>` tags, inside the `<variants>` tags or inside the `<aspectRatio>` tags.
The mandatory name attribute is used to specificy which font size to use, and multiple values can be specified at the same time by separating them by commas or by whitespace characters (tabs, spaces or line breaks).
Here's an example configuration:
```xml
<theme>
<fontSize name="medium">
<variables>
<gameCounterFontSize>0.025</gameCounterFontSize>
<gameCounterPos>0.5 0.6437</gameCounterPos>
<gameNameFontSize>0.022</gameNameFontSize>
<publisherFontSize>0.016</publisherFontSize>
</variables>
</fontSize>
<fontSize name="small">
<variables>
<gameCounterFontSize>0.015</gameCounterFontSize>
<gameCounterPos>0.45 0.6437</gameCounterPos>
<gameNameFontSize>0.013</gameNameFontSize>
</variables>
</fontSize>
<fontSize name="x-small">
<variables>
<gameCounterFontSize>0.008</gameCounterFontSize>
<gameCounterPos>0.4 0.6437</gameCounterPos>
<gameNameFontSize>0.006</gameNameFontSize>
</variables>
<fontSize name="small, x-small">
<variables>
<publisherFontSize>0.011</publisherFontSize>
</variables>
</fontSize>
<view name="system">
<text name="gameCounter">
<pos>${gameCounterPos}</pos>
<size>1 0.056</size>
<fontSize>${gameCounterFontSize}</fontSize>
</text>
<view name="gamelist">
<text name="gameName">
<pos>0.2 0.3412</pos>
<size>0.2 0.040</size>
<fontSize>${gameNameFontSize}</fontSize>
</text>
<text name="publisher">
<pos>0.33 0.3412</pos>
<size>0.18 0.040</size>
<fontSize>${publisherFontSize}</fontSize>
</text>
</view>
</theme>
```
## Aspect ratios ## Aspect ratios
The aspect ratio support works almost identically to the variants and color schemes with the main difference that the available aspect ratios are hardcoded into ES-DE. The theme can still decide which of the aspect ratios to support (or none at all in which case the theme aspect ratio is left undefined) but it can't create entirely new aspect ratio entries. The aspect ratio support works almost identically to the variants and color schemes with the main difference that the available aspect ratios are hardcoded into ES-DE. The theme can still decide which of the aspect ratios to support (or none at all in which case the theme aspect ratio is left undefined) but it can't create entirely new aspect ratio entries.
@ -836,15 +967,18 @@ The variant, color scheme and transitions names as well as their labels can be s
Unlike the types just mentioned, aspectRatio entries can not be set to arbitrary values, instead they have to use a value from the _horizontal name_ or _vertical name_ columns in the following table: Unlike the types just mentioned, aspectRatio entries can not be set to arbitrary values, instead they have to use a value from the _horizontal name_ or _vertical name_ columns in the following table:
| Horizontal name | Vertical name | Common resolutions | | Horizontal name | Vertical name | Common resolutions |
| :--------------- | :------------- | :--------------------------------------------- | | :--------------- | :-------------- | :--------------------------------------------- |
| 16:9 | 16:9_vertical | 1280x720, 1920x1080, 2560x1440, 3840x2160 | | 16:9 | 16:9_vertical | 1280x720, 1920x1080, 2560x1440, 3840x2160 |
| 16:10 | 16:10_vertical | 1280x800, 1440x900, 1920x1200 | | 16:10 | 16:10_vertical | 1280x800, 1440x900, 1920x1200 |
| 3:2 | 3:2_vertical | 2160x1440 | | 3:2 | 3:2_vertical | 2160x1440 |
| 4:3 | 4:3_vertical | 320x240, 640x480, 800x600, 1024x768, 1600x1200 | | 4:3 | 4:3_vertical | 320x240, 640x480, 800x600, 1024x768, 1600x1200 |
| 5:4 | 5:4_vertical | 1280x1024 | | 5:4 | 5:4_vertical | 1280x1024 |
| 21:9 | 21:9_vertical | 2560x1080, 3840x1600, 5120x2160 | | 19.5:9 | 19.5:9_vertical | 2340x1080, 2532x1170 |
| 32:9 | 32:9_vertical | 3840x1080, 5120x1440 | | 20:9 | 20:9_vertical | 2400x1080, 1600x720 |
| 21:9 | 21:9_vertical | 2560x1080, 3840x1600, 5120x2160 |
| 32:9 | 32:9_vertical | 3840x1080, 5120x1440 |
| 1:1 | 1:1 | Any square resolution |
The 21:9 and 32:9 aspect ratios are approximate as monitors of slightly different ratios are collectively marketed using these numbers. The 21:9 and 32:9 aspect ratios are approximate as monitors of slightly different ratios are collectively marketed using these numbers.
@ -1287,10 +1421,11 @@ It's important to understand how the theme configuration files are parsed in ord
1) Transitions 1) Transitions
2) Variables 2) Variables
3) Color schemes 3) Color schemes
4) Included files 4) Font sizes
5) "General" (non-variant) configuration 5) Included files
6) Variants 6) "General" (non-variant) configuration
7) Aspect ratios 7) Variants
8) Aspect ratios
When including a file using the `<include>` tag (i.e. step 4 above) then all steps listed above are executed for that included file prior to continuing to the next line after the `<include>` tag. When including a file using the `<include>` tag (i.e. step 4 above) then all steps listed above are executed for that included file prior to continuing to the next line after the `<include>` tag.
@ -1299,7 +1434,7 @@ For any given step, the configuration is parsed in the exact order that it's def
## Property data types ## Property data types
* NORMALIZED_PAIR - two decimal values delimited by a space, for example `0.25 0.5` * NORMALIZED_PAIR - two decimal values delimited by a space, for example `0.25 0.5`
* PATH - path to a resource. If the first character is a tilde (`~`) then it will be expanded to the user's home directory (`$HOME` for Unix and macOS and `%HOMEPATH%` for Windows) unless overridden using the --home command line option. If the first character is a dot (`.`) then the resource will be searched for relative to the location of the theme file, for example `./myfont.ttf` or `./../core/fonts/myfont.ttf` * PATH - path to a resource. If the first character is a tilde (`~`) then it will be expanded to the user's home directory (`$HOME` for Linux, BSD Unix and macOS and `%HOMEPATH%` for Windows) unless overridden using the --home command line option. If the first character is a dot (`.`) then the resource will be searched for relative to the location of the theme file, for example `./myfont.ttf` or `./../core/fonts/myfont.ttf`
* BOOLEAN - `true`/`1` or `false`/`0` * BOOLEAN - `true`/`1` or `false`/`0`
* COLOR - a hexadecimal RGB or RGBA color value consisting of 6 or 8 digits. If a 6 digit value is used then the alpha channel will be set to `FF` (completely opaque) * COLOR - a hexadecimal RGB or RGBA color value consisting of 6 or 8 digits. If a 6 digit value is used then the alpha channel will be set to `FF` (completely opaque)
* UNSIGNED_INTEGER - an unsigned integer value * UNSIGNED_INTEGER - an unsigned integer value
@ -1872,6 +2007,10 @@ Properties:
- Where on the element `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the textlist exactly in the middle of the screen. If the position and size attributes are themeable, origin is implied. - Where on the element `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the textlist exactly in the middle of the screen. If the position and size attributes are themeable, origin is implied.
- Minimum value per axis is `0` and maximum value per axis is `1` - Minimum value per axis is `0` and maximum value per axis is `1`
- Default is `0 0` - Default is `0 0`
* `selectorWidth` - type: FLOAT
- Width of the selector bar. If an image has been defined using `selectorImagePath` then setting this property to zero will retain the aspect ratio for that image.
- Minimum value is `0` and maximum value is `1`
- Default is the equivalent value as the width of the overall element.
* `selectorHeight` - type: FLOAT * `selectorHeight` - type: FLOAT
- Height of the selector bar. This is expanded downwards so you'll probably want to adjust its position using `selectorVerticalOffset` if making use of this property. - Height of the selector bar. This is expanded downwards so you'll probably want to adjust its position using `selectorVerticalOffset` if making use of this property.
- Minimum value is `0` and maximum value is `1` - Minimum value is `0` and maximum value is `1`
@ -2033,6 +2172,10 @@ Properties:
- `always` - Set element as stationary during all transitions. - `always` - Set element as stationary during all transitions.
- `never` - Don't set element as stationary during any transitions. - `never` - Don't set element as stationary during any transitions.
- Default is `never` - Default is `never`
* `renderDuringTransitions` - type: BOOLEAN
- This special property which is only usable for slide transitions between the system and gamelist views makes it possible to for example have a background image stay seamlessly in place when transitioning, or being able to use semi-transparent stationary elements without having them render on top of each other during transitions. For this to work correctly only define `stationary` for one view and set `renderDuringTransitions` to false for the corresponding element in the other view. This way the element from the former view will keep rendering until the slide animation has been completed, after which the latter view will "take over" by rendering the element normally.
- This property can only be used if slide transitions are used, and only when moving from the system view to the gamelist view, or vice versa.
- Default is `true`
* `flipHorizontal` - type: BOOLEAN * `flipHorizontal` - type: BOOLEAN
- Flips the image texture horizontally. - Flips the image texture horizontally.
- Default is `false` - Default is `false`
@ -2603,7 +2746,7 @@ Properties:
- `sourceSystemName` - The source short system name of the game. For regular systems this value will be identical to `systemName` but for collections it will show the actual system that the game is located in instead of the collection system name. - `sourceSystemName` - The source short system name of the game. For regular systems this value will be identical to `systemName` but for collections it will show the actual system that the game is located in instead of the collection system name.
- `sourceSystemFullname` - The source full system name of the game. For regular systems this value will be identical to `systemFullname` but for collections it will show the actual system that the game is located in instead of the collection system name. - `sourceSystemFullname` - The source full system name of the game. For regular systems this value will be identical to `systemFullname` but for collections it will show the actual system that the game is located in instead of the collection system name.
* `defaultValue` - type: STRING * `defaultValue` - type: STRING
- This property makes it possible to override the default "unknown" text that is displayed if `metadata` has been set to `developer`, `publisher`, `genre` or `players` and there is no metadata available for the defined type. Any string can be used but you can't set it to a blank value. If you don't want to display anything when there is no metadata available, then set this property to `:space:` in which case a blankspace will be used. This property has no effect on the metadata editor where "unknown" will still be shown for blank values. - This property makes it possible to override the default "unknown" text that is displayed if `metadata` has been set to `developer`, `publisher`, `genre` or `players` and there is no metadata available for the defined type. Any string can be used but you can't set it to a blank value. If you don't want to display anything when there is no metadata available, then set this property to `:space:` in which case a blankspace will be used. This property has no effect on the metadata editor where "unknown" will still be shown for blank values. A secondary use for this property is to set a default value if `metadata` has been set to `systemName`, `systemFullname`, `sourceSystemName` or `sourceSystemFullname` in which case the value will be used if the metadata value is blank. This is useful for defining a specific string at the root of the custom collections system.
* `systemNameSuffix` - type: BOOLEAN * `systemNameSuffix` - type: BOOLEAN
- Whether to add the system name in square brackets after the game name when inside a collection system (automatic as well as custom collections). If `metadata` has been set to `description` then this property will only apply when inside the root of the grouped custom collections system where a summary of available games for the currently selected collection is displayed. - Whether to add the system name in square brackets after the game name when inside a collection system (automatic as well as custom collections). If `metadata` has been set to `description` then this property will only apply when inside the root of the grouped custom collections system where a summary of available games for the currently selected collection is displayed.
- Default is `true` - Default is `true`
@ -2884,6 +3027,9 @@ Properties:
- `always` - Set element as stationary during all transitions. - `always` - Set element as stationary during all transitions.
- `never` - Don't set element as stationary during any transitions. - `never` - Don't set element as stationary during any transitions.
- Default is `never` - Default is `never`
* `hideIfZero` - type: BOOLEAN
- If set to true then the element will not get rendered if the rating value is zero.
- Default is `false`
* `gameselector` - type: STRING * `gameselector` - type: STRING
- If more than one gameselector element has been defined, this property makes it possible to state which one to use. If multiple gameselector elements have been defined and this property is missing then the first entry will be chosen and a warning message will be logged. If only a single gameselector has been defined, this property is ignored. The value of this property must match the `name` attribute value of the gameselector element. This property is only needed for the `system` view. - If more than one gameselector element has been defined, this property makes it possible to state which one to use. If multiple gameselector elements have been defined and this property is missing then the first entry will be chosen and a warning message will be logged. If only a single gameselector has been defined, this property is ignored. The value of this property must match the `name` attribute value of the gameselector element. This property is only needed for the `system` view.
* `gameselectorEntry` - type: UNSIGNED_INTEGER * `gameselectorEntry` - type: UNSIGNED_INTEGER
@ -2946,7 +3092,7 @@ Properties:
#### helpsystem #### helpsystem
The helpsystem is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Note that this element does not have a zIndex value, instead it's always rendered on top of all other elements. The helpsystem is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Note that this element does not have a zIndex value, instead it's always rendered on top of all other elements. It also has to have its name attribute set to `help` or the configuration will not get loaded.
It's possible to set this element as right-aligned or center-aligned using a combination of the `pos` and `origin` properties. For example `<pos>1 1</pos>` and `<origin>1 1</origin>` will place it in the lower right corner of the screen. It's possible to set this element as right-aligned or center-aligned using a combination of the `pos` and `origin` properties. For example `<pos>1 1</pos>` and `<origin>1 1</origin>` will place it in the lower right corner of the screen.

200
THEMES.md
View file

@ -1,6 +1,6 @@
# EmulationStation Desktop Edition (ES-DE) v2.2 - Themes # ES-DE (EmulationStation Desktop Edition) v3.0 - Themes
If creating themes specifically for ES-DE, please add `-es-de` to the repository/directory name, as in `slate-es-de`. Themes made for ES-DE are not compatible with any other EmulationStation forks (and vice versa) and the -es-de extension makes it clear that it's an ES-DE theme. The actual theme name as defined using the `themeName` tag in capabilities.xml does of course not need to include the `-es-de` extension as that's the actual theme name that will be displayed when selecting themes from the _UI Settings_ menu. For example slate-es-de will be listed simply as _Slate_ in this menu. If creating themes for ES-DE, please add `-es-de` to the repository/directory name to clearly indicate that it's a theme for this frontend. Two examples would be `linear-es-de` and `modern-es-de`. The actual theme name as defined using the `themeName` tag in capabilities.xml does of course not need to include the `-es-de` extension as that's the actual theme name that will be displayed when selecting themes from the _UI Settings_ menu. For example linear-es-de will be listed simply as _Linear_ in this menu.
Before your start, make sure to download the _Theme engine examples_ theme that contains a number of example variants for things like vertical and horizontal carousels, wheel carousels, system view text lists, grids etc: Before your start, make sure to download the _Theme engine examples_ theme that contains a number of example variants for things like vertical and horizontal carousels, wheel carousels, system view text lists, grids etc:
@ -16,7 +16,7 @@ https://github.com/lilbud/es-de-theme-stuff
To test whether your theme includes support for all ES-DE systems, download one of the following archives which contain ROM directory trees fully populated with dummy files: To test whether your theme includes support for all ES-DE systems, download one of the following archives which contain ROM directory trees fully populated with dummy files:
[ROMs_ALL_Unix.zip](tools/system-dirs-dummy-files/ROMs_ALL_Unix.zip)\ [ROMs_ALL_Linux.zip](tools/system-dirs-dummy-files/ROMs_ALL_Linux.zip)\
[ROMs_ALL_macOS.zip](tools/system-dirs-dummy-files/ROMs_ALL_macOS.zip)\ [ROMs_ALL_macOS.zip](tools/system-dirs-dummy-files/ROMs_ALL_macOS.zip)\
[ROMs_ALL_Windows.zip](tools/system-dirs-dummy-files/ROMs_ALL_Windows.zip) [ROMs_ALL_Windows.zip](tools/system-dirs-dummy-files/ROMs_ALL_Windows.zip)
@ -156,17 +156,19 @@ Note that the legacy theme engine had quite inaccurate text sizing and font rend
* The defined line spacing was not always applied for automatically sized text elements * The defined line spacing was not always applied for automatically sized text elements
* Font sizes were rounded to integers, leading to imprecise text sizing across different resolutions (the rounding was also done incorrectly) * Font sizes were rounded to integers, leading to imprecise text sizing across different resolutions (the rounding was also done incorrectly)
## System metadata and logo repositories ## Theme assets repositories
There are two useful repositories hosted by the ES-DE project that provide system metadata and system logotypes. This greatly simplifies the work of adding support for all systems that ES-DE supports. There are several useful repositories hosted by the ES-DE project that provide system metadata and system graphics files. Using these greatly simplifies the work of adding support for all ES-DE systems to your theme.
**Metadata** Make sure to regularly check for updates in these repositories as corrections, improvements and additions of new systems are made continuously.
### Metadata
The metadata repository provides descriptions, release dates, per-system color palettes etc. and it can be found here: The metadata repository provides descriptions, release dates, per-system color palettes etc. and it can be found here:
https://gitlab.com/es-de/themes/system-metadata https://gitlab.com/es-de/themes/system-metadata
By adding this to your theme, either via manually downloading and including it, or by adding it as a Git subtree, you'll be able to access its defined variables. Make sure to regularly check for updates as corrections and additions of new systems are done continuously. Also check the README.md file in the repository for more details on how to actually use the variables. By adding this to your theme, either via manually downloading and including it, or by adding it as a Git subtree, you'll be able to access its defined variables. Check the README.md file in the repository for details on how to actually use the variables.
Here's how to add this repository as a subtree inside your theme's Git repository: Here's how to add this repository as a subtree inside your theme's Git repository:
``` ```
@ -181,9 +183,47 @@ git subtree pull --prefix=system-metadata --squash system-metadata master
The directory name can be changed to whatever you like using the --prefix flag. The directory name can be changed to whatever you like using the --prefix flag.
**Logos** ### Controller outline graphics
Likewise there's a repository of system logotypes that can also be added and used in the same fashion as the metadata. It can be found here: This repository provides controller graphics files for each system in an outline style and it can be found here:
https://gitlab.com/es-de/themes/system-controllers-outline
Here's how to add this repository as a subtree inside your theme's Git repository:
```
git remote add system-controllers-outline https://gitlab.com/es-de/themes/system-controllers-outline.git
git subtree add --prefix=system-controllers-outline --squash system-controllers-outline master
```
To later pull in repository updates you'll run the following:
```
git subtree pull --prefix=system-controllers-outline --squash system-controllers-outline master
```
The directory name can be changed to whatever you like using the --prefix flag.
### Mini system graphics
This repository provides graphics files for each system in a "mini" style and it can be found here:
https://gitlab.com/es-de/themes/system-graphics-mini
Here's how to add this repository as a subtree inside your theme's Git repository:
```
git remote add system-graphics-mini https://gitlab.com/es-de/themes/system-graphics-mini.git
git subtree add --prefix=system-graphics-mini --squash system-graphics-mini master
```
To later pull in repository updates you'll run the following:
```
git subtree pull --prefix=system-graphics-mini --squash system-graphics-mini master
```
The directory name can be changed to whatever you like using the --prefix flag.
### Logos
This repository provides logos for each system in color and white (the latter for use with color shifting) and it can be found here:
https://gitlab.com/es-de/themes/system-logos https://gitlab.com/es-de/themes/system-logos
@ -200,11 +240,13 @@ git subtree pull --prefix=system-logos --squash system-logos master
The directory name can be changed to whatever you like using the --prefix flag. The directory name can be changed to whatever you like using the --prefix flag.
**Adding remotes** ### Adding remotes
Note that the remotes are only setup for your local repository, so if you clone a theme you'll need to manually add the system-metadata and/or system-logos remotes to be able to pull to these subtrees. That means you'll need to run the following commands on a freshly cloned theme repository: Note that the remotes are only setup for your local repository, so if you clone a theme you'll need to manually add the repository remotes to be able to pull from these subtrees. That means you'll need to run one or more of the following commands on a freshly cloned theme repository:
``` ```
git remote add system-metadata https://gitlab.com/es-de/themes/system-metadata.git git remote add system-metadata https://gitlab.com/es-de/themes/system-metadata.git
git remote add system-controllers-outline https://gitlab.com/es-de/themes/system-controllers-outline.git
git remote add system-graphics-mini https://gitlab.com/es-de/themes/system-graphics-mini.git
git remote add system-logos https://gitlab.com/es-de/themes/system-logos.git git remote add system-logos https://gitlab.com/es-de/themes/system-logos.git
``` ```
After doing this you'll be able to pull repository updates as described above. After doing this you'll be able to pull repository updates as described above.
@ -609,6 +651,95 @@ Here's an example configuration:
</theme> </theme>
``` ```
## Font sizes
The optional font sizes functionality makes it possible to use a set of predefined size options and connect these to theme variables that can be used to apply different text sizes and related design changes. The font sizes declared for the theme can be selected via the _Theme font size_ setting in the _UI Settings_ menu.
To understand the basics on how to use variables, make sure to read the _Theme variables_ section elsewhere in this document.
To use the font size entries you first need to declare them using `<fontSize>` tag pairs in the `capabilities.xml` file. The following sizes are available:
| capabilities.xml name | UI Settings label |
| :-------------------- | :--------------- |
| medium | medium |
| large | large |
| small | small |
| x-large | extra large |
| x-small | extra small |
The options will always be listed in the above order in the _UI Settings_ menu.
Here's an example of a theme that implements three of these sizes:
```xml
<!-- Theme capabilities for mytheme-es-de -->
<themeCapabilities>
<themeName>My theme</themeName>
<fontSize>medium</fontSize>
<fontSize>small</fontSize>
<fontSize>x-small</fontSize>
</themeCapabilities>
```
In the theme configuration you'll also use a `<fontSize>` tag pair combined with a `<variable>` tag pair to define the variables you want to apply per font size.
These `<fontSize>` tag pairs can be placed directly inside the `<theme>` tags, inside the `<variants>` tags or inside the `<aspectRatio>` tags.
The mandatory name attribute is used to specificy which font size to use, and multiple values can be specified at the same time by separating them by commas or by whitespace characters (tabs, spaces or line breaks).
Here's an example configuration:
```xml
<theme>
<fontSize name="medium">
<variables>
<gameCounterFontSize>0.025</gameCounterFontSize>
<gameCounterPos>0.5 0.6437</gameCounterPos>
<gameNameFontSize>0.022</gameNameFontSize>
<publisherFontSize>0.016</publisherFontSize>
</variables>
</fontSize>
<fontSize name="small">
<variables>
<gameCounterFontSize>0.015</gameCounterFontSize>
<gameCounterPos>0.45 0.6437</gameCounterPos>
<gameNameFontSize>0.013</gameNameFontSize>
</variables>
</fontSize>
<fontSize name="x-small">
<variables>
<gameCounterFontSize>0.008</gameCounterFontSize>
<gameCounterPos>0.4 0.6437</gameCounterPos>
<gameNameFontSize>0.006</gameNameFontSize>
</variables>
<fontSize name="small, x-small">
<variables>
<publisherFontSize>0.011</publisherFontSize>
</variables>
</fontSize>
<view name="system">
<text name="gameCounter">
<pos>${gameCounterPos}</pos>
<size>1 0.056</size>
<fontSize>${gameCounterFontSize}</fontSize>
</text>
<view name="gamelist">
<text name="gameName">
<pos>0.2 0.3412</pos>
<size>0.2 0.040</size>
<fontSize>${gameNameFontSize}</fontSize>
</text>
<text name="publisher">
<pos>0.33 0.3412</pos>
<size>0.18 0.040</size>
<fontSize>${publisherFontSize}</fontSize>
</text>
</view>
</theme>
```
## Aspect ratios ## Aspect ratios
The aspect ratio support works almost identically to the variants and color schemes with the main difference that the available aspect ratios are hardcoded into ES-DE. The theme can still decide which of the aspect ratios to support (or none at all in which case the theme aspect ratio is left undefined) but it can't create entirely new aspect ratio entries. The aspect ratio support works almost identically to the variants and color schemes with the main difference that the available aspect ratios are hardcoded into ES-DE. The theme can still decide which of the aspect ratios to support (or none at all in which case the theme aspect ratio is left undefined) but it can't create entirely new aspect ratio entries.
@ -834,15 +965,18 @@ The variant, color scheme and transitions names as well as their labels can be s
Unlike the types just mentioned, aspectRatio entries can not be set to arbitrary values, instead they have to use a value from the _horizontal name_ or _vertical name_ columns in the following table: Unlike the types just mentioned, aspectRatio entries can not be set to arbitrary values, instead they have to use a value from the _horizontal name_ or _vertical name_ columns in the following table:
| Horizontal name | Vertical name | Common resolutions | | Horizontal name | Vertical name | Common resolutions |
| :--------------- | :------------- | :--------------------------------------------- | | :--------------- | :-------------- | :--------------------------------------------- |
| 16:9 | 16:9_vertical | 1280x720, 1920x1080, 2560x1440, 3840x2160 | | 16:9 | 16:9_vertical | 1280x720, 1920x1080, 2560x1440, 3840x2160 |
| 16:10 | 16:10_vertical | 1280x800, 1440x900, 1920x1200 | | 16:10 | 16:10_vertical | 1280x800, 1440x900, 1920x1200 |
| 3:2 | 3:2_vertical | 2160x1440 | | 3:2 | 3:2_vertical | 2160x1440 |
| 4:3 | 4:3_vertical | 320x240, 640x480, 800x600, 1024x768, 1600x1200 | | 4:3 | 4:3_vertical | 320x240, 640x480, 800x600, 1024x768, 1600x1200 |
| 5:4 | 5:4_vertical | 1280x1024 | | 5:4 | 5:4_vertical | 1280x1024 |
| 21:9 | 21:9_vertical | 2560x1080, 3840x1600, 5120x2160 | | 19.5:9 | 19.5:9_vertical | 2340x1080, 2532x1170 |
| 32:9 | 32:9_vertical | 3840x1080, 5120x1440 | | 20:9 | 20:9_vertical | 2400x1080, 1600x720 |
| 21:9 | 21:9_vertical | 2560x1080, 3840x1600, 5120x2160 |
| 32:9 | 32:9_vertical | 3840x1080, 5120x1440 |
| 1:1 | 1:1 | Any square resolution |
The 21:9 and 32:9 aspect ratios are approximate as monitors of slightly different ratios are collectively marketed using these numbers. The 21:9 and 32:9 aspect ratios are approximate as monitors of slightly different ratios are collectively marketed using these numbers.
@ -1285,10 +1419,11 @@ It's important to understand how the theme configuration files are parsed in ord
1) Transitions 1) Transitions
2) Variables 2) Variables
3) Color schemes 3) Color schemes
4) Included files 4) Font sizes
5) "General" (non-variant) configuration 5) Included files
6) Variants 6) "General" (non-variant) configuration
7) Aspect ratios 7) Variants
8) Aspect ratios
When including a file using the `<include>` tag (i.e. step 4 above) then all steps listed above are executed for that included file prior to continuing to the next line after the `<include>` tag. When including a file using the `<include>` tag (i.e. step 4 above) then all steps listed above are executed for that included file prior to continuing to the next line after the `<include>` tag.
@ -1297,7 +1432,7 @@ For any given step, the configuration is parsed in the exact order that it's def
## Property data types ## Property data types
* NORMALIZED_PAIR - two decimal values delimited by a space, for example `0.25 0.5` * NORMALIZED_PAIR - two decimal values delimited by a space, for example `0.25 0.5`
* PATH - path to a resource. If the first character is a tilde (`~`) then it will be expanded to the user's home directory (`$HOME` for Unix and macOS and `%HOMEPATH%` for Windows) unless overridden using the --home command line option. If the first character is a dot (`.`) then the resource will be searched for relative to the location of the theme file, for example `./myfont.ttf` or `./../core/fonts/myfont.ttf` * PATH - path to a resource. If the first character is a tilde (`~`) then it will be expanded to the user's home directory (`$HOME` for Linux, BSD Unix and macOS and `%HOMEPATH%` for Windows) unless overridden using the --home command line option. If the first character is a dot (`.`) then the resource will be searched for relative to the location of the theme file, for example `./myfont.ttf` or `./../core/fonts/myfont.ttf`
* BOOLEAN - `true`/`1` or `false`/`0` * BOOLEAN - `true`/`1` or `false`/`0`
* COLOR - a hexadecimal RGB or RGBA color value consisting of 6 or 8 digits. If a 6 digit value is used then the alpha channel will be set to `FF` (completely opaque) * COLOR - a hexadecimal RGB or RGBA color value consisting of 6 or 8 digits. If a 6 digit value is used then the alpha channel will be set to `FF` (completely opaque)
* UNSIGNED_INTEGER - an unsigned integer value * UNSIGNED_INTEGER - an unsigned integer value
@ -1870,6 +2005,10 @@ Properties:
- Where on the element `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the textlist exactly in the middle of the screen. If the position and size attributes are themeable, origin is implied. - Where on the element `pos` refers to. For example, an origin of `0.5 0.5` and a `pos` of `0.5 0.5` would place the textlist exactly in the middle of the screen. If the position and size attributes are themeable, origin is implied.
- Minimum value per axis is `0` and maximum value per axis is `1` - Minimum value per axis is `0` and maximum value per axis is `1`
- Default is `0 0` - Default is `0 0`
* `selectorWidth` - type: FLOAT
- Width of the selector bar. If an image has been defined using `selectorImagePath` then setting this property to zero will retain the aspect ratio for that image.
- Minimum value is `0` and maximum value is `1`
- Default is the equivalent value as the width of the overall element.
* `selectorHeight` - type: FLOAT * `selectorHeight` - type: FLOAT
- Height of the selector bar. This is expanded downwards so you'll probably want to adjust its position using `selectorVerticalOffset` if making use of this property. - Height of the selector bar. This is expanded downwards so you'll probably want to adjust its position using `selectorVerticalOffset` if making use of this property.
- Minimum value is `0` and maximum value is `1` - Minimum value is `0` and maximum value is `1`
@ -2031,6 +2170,10 @@ Properties:
- `always` - Set element as stationary during all transitions. - `always` - Set element as stationary during all transitions.
- `never` - Don't set element as stationary during any transitions. - `never` - Don't set element as stationary during any transitions.
- Default is `never` - Default is `never`
* `renderDuringTransitions` - type: BOOLEAN
- This special property which is only usable for slide transitions between the system and gamelist views makes it possible to for example have a background image stay seamlessly in place when transitioning, or being able to use semi-transparent stationary elements without having them render on top of each other during transitions. For this to work correctly only define `stationary` for one view and set `renderDuringTransitions` to false for the corresponding element in the other view. This way the element from the former view will keep rendering until the slide animation has been completed, after which the latter view will "take over" by rendering the element normally.
- This property can only be used if slide transitions are used, and only when moving from the system view to the gamelist view, or vice versa.
- Default is `true`
* `flipHorizontal` - type: BOOLEAN * `flipHorizontal` - type: BOOLEAN
- Flips the image texture horizontally. - Flips the image texture horizontally.
- Default is `false` - Default is `false`
@ -2601,7 +2744,7 @@ Properties:
- `sourceSystemName` - The source short system name of the game. For regular systems this value will be identical to `systemName` but for collections it will show the actual system that the game is located in instead of the collection system name. - `sourceSystemName` - The source short system name of the game. For regular systems this value will be identical to `systemName` but for collections it will show the actual system that the game is located in instead of the collection system name.
- `sourceSystemFullname` - The source full system name of the game. For regular systems this value will be identical to `systemFullname` but for collections it will show the actual system that the game is located in instead of the collection system name. - `sourceSystemFullname` - The source full system name of the game. For regular systems this value will be identical to `systemFullname` but for collections it will show the actual system that the game is located in instead of the collection system name.
* `defaultValue` - type: STRING * `defaultValue` - type: STRING
- This property makes it possible to override the default "unknown" text that is displayed if `metadata` has been set to `developer`, `publisher`, `genre` or `players` and there is no metadata available for the defined type. Any string can be used but you can't set it to a blank value. If you don't want to display anything when there is no metadata available, then set this property to `:space:` in which case a blankspace will be used. This property has no effect on the metadata editor where "unknown" will still be shown for blank values. - This property makes it possible to override the default "unknown" text that is displayed if `metadata` has been set to `developer`, `publisher`, `genre` or `players` and there is no metadata available for the defined type. Any string can be used but you can't set it to a blank value. If you don't want to display anything when there is no metadata available, then set this property to `:space:` in which case a blankspace will be used. This property has no effect on the metadata editor where "unknown" will still be shown for blank values. A secondary use for this property is to set a default value if `metadata` has been set to `systemName`, `systemFullname`, `sourceSystemName` or `sourceSystemFullname` in which case the value will be used if the metadata value is blank. This is useful for defining a specific string at the root of the custom collections system.
* `systemNameSuffix` - type: BOOLEAN * `systemNameSuffix` - type: BOOLEAN
- Whether to add the system name in square brackets after the game name when inside a collection system (automatic as well as custom collections). If `metadata` has been set to `description` then this property will only apply when inside the root of the grouped custom collections system where a summary of available games for the currently selected collection is displayed. - Whether to add the system name in square brackets after the game name when inside a collection system (automatic as well as custom collections). If `metadata` has been set to `description` then this property will only apply when inside the root of the grouped custom collections system where a summary of available games for the currently selected collection is displayed.
- Default is `true` - Default is `true`
@ -2882,6 +3025,9 @@ Properties:
- `always` - Set element as stationary during all transitions. - `always` - Set element as stationary during all transitions.
- `never` - Don't set element as stationary during any transitions. - `never` - Don't set element as stationary during any transitions.
- Default is `never` - Default is `never`
* `hideIfZero` - type: BOOLEAN
- If set to true then the element will not get rendered if the rating value is zero.
- Default is `false`
* `gameselector` - type: STRING * `gameselector` - type: STRING
- If more than one gameselector element has been defined, this property makes it possible to state which one to use. If multiple gameselector elements have been defined and this property is missing then the first entry will be chosen and a warning message will be logged. If only a single gameselector has been defined, this property is ignored. The value of this property must match the `name` attribute value of the gameselector element. This property is only needed for the `system` view. - If more than one gameselector element has been defined, this property makes it possible to state which one to use. If multiple gameselector elements have been defined and this property is missing then the first entry will be chosen and a warning message will be logged. If only a single gameselector has been defined, this property is ignored. The value of this property must match the `name` attribute value of the gameselector element. This property is only needed for the `system` view.
* `gameselectorEntry` - type: UNSIGNED_INTEGER * `gameselectorEntry` - type: UNSIGNED_INTEGER
@ -2944,7 +3090,7 @@ Properties:
#### helpsystem #### helpsystem
The helpsystem is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Note that this element does not have a zIndex value, instead it's always rendered on top of all other elements. The helpsystem is a special element that displays a context-sensitive list of actions the user can take at any time. You should try and keep the position constant throughout every screen. Note that this element does not have a zIndex value, instead it's always rendered on top of all other elements. It also has to have its name attribute set to `help` or the configuration will not get loaded.
It's possible to set this element as right-aligned or center-aligned using a combination of the `pos` and `origin` properties. For example `<pos>1 1</pos>` and `<origin>1 1</origin>` will place it in the lower right corner of the screen. It's possible to set this element as right-aligned or center-aligned using a combination of the `pos` and `origin` properties. For example `<pos>1 1</pos>` and `<origin>1 1</origin>` will place it in the lower right corner of the screen.

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,18 +1,18 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# EmulationStation Desktop Edition # ES-DE
# CMakeLists.txt (es-app) # CMakeLists.txt (es-app)
# #
# CMake configuration for es-app # CMake configuration for es-app
# Also contains the application packaging configuration. # Also contains the application packaging configuration.
# #
project(emulationstation-de) project(es-de)
set(ES_HEADERS set(ES_HEADERS
${CMAKE_CURRENT_SOURCE_DIR}/src/ApplicationUpdater.h ${CMAKE_CURRENT_SOURCE_DIR}/src/ApplicationUpdater.h
${CMAKE_CURRENT_SOURCE_DIR}/src/ApplicationVersion.h
${CMAKE_CURRENT_SOURCE_DIR}/src/CollectionSystemsManager.h ${CMAKE_CURRENT_SOURCE_DIR}/src/CollectionSystemsManager.h
${CMAKE_CURRENT_SOURCE_DIR}/src/EmulationStation.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FileData.h ${CMAKE_CURRENT_SOURCE_DIR}/src/FileData.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.h ${CMAKE_CURRENT_SOURCE_DIR}/src/FileFilterIndex.h
${CMAKE_CURRENT_SOURCE_DIR}/src/FileSorts.h ${CMAKE_CURRENT_SOURCE_DIR}/src/FileSorts.h
@ -112,7 +112,7 @@ set(ES_SOURCES
) )
if(WIN32) if(WIN32)
LIST(APPEND ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation.rc) LIST(APPEND ES_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE.rc)
endif() endif()
#--------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------
@ -121,149 +121,79 @@ endif()
# Define target. # Define target.
if(APPLE) if(APPLE)
include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_executable(EmulationStation ${ES_SOURCES} ${ES_HEADERS}) add_executable(ES-DE ${ES_SOURCES} ${ES_HEADERS})
target_link_libraries(EmulationStation ${COMMON_LIBRARIES} es-core) target_link_libraries(ES-DE ${COMMON_LIBRARIES} es-core)
set_target_properties(EmulationStation PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) set_target_properties(ES-DE PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0) if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
target_link_options(EmulationStation PRIVATE LINKER:-no_warn_duplicate_libraries) target_link_options(ES-DE PRIVATE LINKER:-no_warn_duplicate_libraries)
endif() endif()
elseif(WIN32) elseif(WIN32)
include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_executable(EmulationStation WIN32 ${ES_SOURCES} ${ES_HEADERS}) add_executable(ES-DE WIN32 ${ES_SOURCES} ${ES_HEADERS})
target_link_libraries(EmulationStation ${COMMON_LIBRARIES} es-core) target_link_libraries(ES-DE ${COMMON_LIBRARIES} es-core)
set_target_properties(EmulationStation PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) set_target_properties(ES-DE PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
elseif(ANDROID)
include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_library(main MODULE ${ES_SOURCES} ${ES_HEADERS})
target_link_libraries(main PRIVATE ${COMMON_LIBRARIES} ${CMAKE_DL_LIBS} es-core es-pdf-convert)
else() else()
include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src) include_directories(${COMMON_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/src)
add_executable(emulationstation ${ES_SOURCES} ${ES_HEADERS}) add_executable(es-de ${ES_SOURCES} ${ES_HEADERS})
target_link_libraries(emulationstation ${COMMON_LIBRARIES} ${CMAKE_DL_LIBS} es-core) target_link_libraries(es-de ${COMMON_LIBRARIES} ${CMAKE_DL_LIBS} es-core)
set_target_properties(emulationstation PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE) set_target_properties(es-de PROPERTIES INSTALL_RPATH_USE_LINK_PATH TRUE)
endif() endif()
# Setup for installation and package generation. # Setup for installation and package generation.
if(WIN32) if(WIN32)
install(TARGETS EmulationStation RUNTIME DESTINATION .) install(TARGETS ES-DE RUNTIME DESTINATION .)
install(TARGETS es-pdf-convert RUNTIME DESTINATION es-pdf-converter) install(TARGETS es-pdf-convert RUNTIME DESTINATION es-pdf-converter)
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC) set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .)
set(CMAKE_INSTALL_SYSTEM_RUNTIME_DESTINATION .) if(CMAKE_BUILD_TYPE MATCHES Debug)
if(CMAKE_BUILD_TYPE MATCHES Debug) set(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE)
set(CMAKE_INSTALL_DEBUG_LIBRARIES TRUE)
endif()
install(FILES ../avcodec-60.dll
../avfilter-9.dll
../avformat-60.dll
../avutil-58.dll
../postproc-57.dll
../swresample-4.dll
../swscale-7.dll
../FreeImage.dll
../freetype.dll
../git2.dll
../glew32.dll
../libcrypto-1_1-x64.dll
../libcurl-x64.dll
../libssl-1_1-x64.dll
../lunasvg.dll
../pugixml.dll
../rlottie.dll
../SDL2.dll
../vcomp140.dll
DESTINATION .)
install(FILES ../es-pdf-converter/charset.dll
../es-pdf-converter/deflate.dll
../es-pdf-converter/freetype.dll
../es-pdf-converter/iconv.dll
../es-pdf-converter/jpeg8.dll
../es-pdf-converter/lcms2.dll
../es-pdf-converter/Lerc.dll
../es-pdf-converter/libcrypto-3-x64.dll
../es-pdf-converter/libcurl.dll
../es-pdf-converter/liblzma.dll
../es-pdf-converter/libpng16.dll
../es-pdf-converter/libssh2.dll
../es-pdf-converter/openjp2.dll
../es-pdf-converter/poppler.dll
../es-pdf-converter/poppler-cpp.dll
../es-pdf-converter/tiff.dll
../es-pdf-converter/zlib.dll
../es-pdf-converter/zstd.dll
DESTINATION es-pdf-converter)
else()
install(FILES ../avcodec-60.dll
../avfilter-9.dll
../avformat-60.dll
../avutil-58.dll
../postproc-57.dll
../swresample-4.dll
../swscale-7.dll
../FreeImage.dll
../glew32.dll
../libcrypto-1_1-x64.dll
../libcurl-x64.dll
../libfreetype.dll
../libgit2.dll
../liblunasvg.dll
../libpugixml.dll
../librlottie.dll
../libssl-1_1-x64.dll
../SDL2.dll
../vcomp140.dll
DESTINATION .)
install(FILES ../es-pdf-converter/libbrotlicommon.dll
../es-pdf-converter/libbrotlidec.dll
../es-pdf-converter/libbz2-1.dll
../es-pdf-converter/libcairo-2.dll
../es-pdf-converter/libcrypto-3-x64.dll
../es-pdf-converter/libcurl-4.dll
../es-pdf-converter/libdeflate.dll
../es-pdf-converter/libexpat-1.dll
../es-pdf-converter/libffi-8.dll
../es-pdf-converter/libfontconfig-1.dll
../es-pdf-converter/libfreetype-6.dll
../es-pdf-converter/libgcc_s_seh-1.dll
../es-pdf-converter/libgio-2.0-0.dll
../es-pdf-converter/libglib-2.0-0.dll
../es-pdf-converter/libgmodule-2.0-0.dll
../es-pdf-converter/libgobject-2.0-0.dll
../es-pdf-converter/libgraphite2.dll
../es-pdf-converter/libharfbuzz-0.dll
../es-pdf-converter/libiconv-2.dll
../es-pdf-converter/libidn2-0.dll
../es-pdf-converter/libintl-8.dll
../es-pdf-converter/libjbig-0.dll
../es-pdf-converter/libjpeg-8.dll
../es-pdf-converter/liblcms2-2.dll
../es-pdf-converter/libLerc.dll
../es-pdf-converter/liblzma-5.dll
../es-pdf-converter/libnghttp2-14.dll
../es-pdf-converter/libnspr4.dll
../es-pdf-converter/libopenjp2-7.dll
../es-pdf-converter/libpcre2-8-0.dll
../es-pdf-converter/libpixman-1-0.dll
../es-pdf-converter/libplc4.dll
../es-pdf-converter/libplds4.dll
../es-pdf-converter/libpng16-16.dll
../es-pdf-converter/libpoppler-129.dll
../es-pdf-converter/libpoppler-cpp-0.dll
../es-pdf-converter/libpoppler-glib-8.dll
../es-pdf-converter/libpsl-5.dll
../es-pdf-converter/libsharpyuv-0.dll
../es-pdf-converter/libssh2-1.dll
../es-pdf-converter/libssl-3-x64.dll
../es-pdf-converter/libstdc++-6.dll
../es-pdf-converter/libtiff-6.dll
../es-pdf-converter/libunistring-5.dll
../es-pdf-converter/libwebp-7.dll
../es-pdf-converter/libwinpthread-1.dll
../es-pdf-converter/libzstd.dll
../es-pdf-converter/nss3.dll
../es-pdf-converter/nssutil3.dll
../es-pdf-converter/smime3.dll
../es-pdf-converter/zlib1.dll
DESTINATION es-pdf-converter)
endif() endif()
install(FILES ../avcodec-60.dll
../avfilter-9.dll
../avformat-60.dll
../avutil-58.dll
../postproc-57.dll
../swresample-4.dll
../swscale-7.dll
../FreeImage.dll
../freetype.dll
../git2.dll
../glew32.dll
../libcrypto-1_1-x64.dll
../libcurl-x64.dll
../libssl-1_1-x64.dll
../lunasvg.dll
../pugixml.dll
../rlottie.dll
../SDL2.dll
../vcomp140.dll
DESTINATION .)
install(FILES ../es-pdf-converter/charset.dll
../es-pdf-converter/deflate.dll
../es-pdf-converter/freetype.dll
../es-pdf-converter/iconv.dll
../es-pdf-converter/jpeg8.dll
../es-pdf-converter/lcms2.dll
../es-pdf-converter/Lerc.dll
../es-pdf-converter/libcrypto-3-x64.dll
../es-pdf-converter/libcurl.dll
../es-pdf-converter/liblzma.dll
../es-pdf-converter/libpng16.dll
../es-pdf-converter/libssh2.dll
../es-pdf-converter/openjp2.dll
../es-pdf-converter/poppler.dll
../es-pdf-converter/poppler-cpp.dll
../es-pdf-converter/tiff.dll
../es-pdf-converter/zlib.dll
../es-pdf-converter/zstd.dll
DESTINATION es-pdf-converter)
install(FILES ../LICENSE DESTINATION .) install(FILES ../LICENSE DESTINATION .)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION .) install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION .)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/linear-es-de DESTINATION themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de DESTINATION themes) install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de DESTINATION themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de DESTINATION themes) install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de DESTINATION themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources DESTINATION .) install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources DESTINATION .)
@ -274,10 +204,10 @@ elseif(APPLE)
# So an extra 'Resources' directory was added to the CMAKE_INSTALL_PREFIX variable as well # So an extra 'Resources' directory was added to the CMAKE_INSTALL_PREFIX variable as well
# to compensate for this. It's a bad solution to the problem and there must surely be a # to compensate for this. It's a bad solution to the problem and there must surely be a
# better way to fix this. # better way to fix this.
install(TARGETS EmulationStation RUNTIME DESTINATION ../MacOS) install(TARGETS ES-DE RUNTIME DESTINATION ../MacOS)
install(TARGETS es-pdf-convert RUNTIME DESTINATION ../MacOS) install(TARGETS es-pdf-convert RUNTIME DESTINATION ../MacOS)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE.icns DESTINATION ../Resources) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE.icns DESTINATION ../Resources)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_Info.plist DESTINATION .. RENAME Info.plist) install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE_Info.plist DESTINATION .. RENAME Info.plist)
set(APPLE_DYLIB_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE set(APPLE_DYLIB_PERMISSIONS OWNER_WRITE OWNER_READ OWNER_EXECUTE
GROUP_READ GROUP_EXECUTE GROUP_READ GROUP_EXECUTE
@ -322,37 +252,40 @@ elseif(APPLE)
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ../Resources) install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ../Resources)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources DESTINATION ../Resources) install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources DESTINATION ../Resources)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/linear-es-de DESTINATION ../Resources/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de DESTINATION ../Resources/themes) install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de DESTINATION ../Resources/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de DESTINATION ../Resources/themes) install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de DESTINATION ../Resources/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION ../Resources) install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses DESTINATION ../Resources)
else() elseif(NOT ANDROID)
install(TARGETS emulationstation RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS es-de RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
install(TARGETS es-pdf-convert RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin) install(TARGETS es-pdf-convert RUNTIME DESTINATION ${CMAKE_INSTALL_PREFIX}/bin)
if(CMAKE_SYSTEM_NAME MATCHES Linux) if(CMAKE_SYSTEM_NAME MATCHES Linux)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/emulationstation.6.gz install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/es-de.6.gz
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man6) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/man/man6)
else() else()
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/emulationstation.6.gz install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/es-de.6.gz
DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man6) DESTINATION ${CMAKE_INSTALL_PREFIX}/man/man6)
endif() endif()
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE install(FILES ${CMAKE_SOURCE_DIR}/LICENSE
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/emulationstation) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.emulationstation-de.desktop install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.frontend.desktop
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/applications)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.emulationstation-de.svg install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.frontend.svg
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/pixmaps)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.emulationstation-de.svg install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.frontend.svg
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/icons/hicolor/scalable/apps)
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.emulationstation-de.appdata.xml install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/assets/org.es_de.frontend.appdata.xml
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/metainfo)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses install(DIRECTORY ${CMAKE_SOURCE_DIR}/licenses
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/emulationstation) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/linear-es-de
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/modern-es-de
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/emulationstation/themes) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de install(DIRECTORY ${CMAKE_SOURCE_DIR}/themes/slate-es-de
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/emulationstation/themes) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de/themes)
install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources install(DIRECTORY ${CMAKE_SOURCE_DIR}/resources
DESTINATION ${CMAKE_INSTALL_PREFIX}/share/emulationstation) DESTINATION ${CMAKE_INSTALL_PREFIX}/share/es-de)
endif() endif()
include(InstallRequiredSystemLibraries) include(InstallRequiredSystemLibraries)
@ -360,17 +293,17 @@ include(InstallRequiredSystemLibraries)
#--------------------------------------------------------------------------------------------------- #---------------------------------------------------------------------------------------------------
# General CPack settings. # General CPack settings.
set(CPACK_PACKAGE_NAME emulationstation-de) set(CPACK_PACKAGE_NAME es-de)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Emulator frontend") set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Emulator frontend")
set(CPACK_PACKAGE_DESCRIPTION "EmulationStation Desktop Edition (ES-DE) is a frontend for browsing and launching games from your multi-platform game collection.") set(CPACK_PACKAGE_DESCRIPTION "ES-DE (EmulationStation Desktop Edition) is a frontend for browsing and launching games from your multi-platform game collection.")
set(CPACK_PACKAGE_VERSION ${ES_VERSION}) set(CPACK_PACKAGE_VERSION ${ES_VERSION})
if(APPLE) if(APPLE)
# Shorter line length license file to be able to fit inside the drag-and-drop installer window without introducing extra line breaks. # Shorter line length license file to be able to fit inside the drag-and-drop installer window without introducing extra line breaks.
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_LICENSE_macOS) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE_LICENSE_macOS)
elseif(WIN32) elseif(WIN32)
# The installer window looks a bit different on Windows so a specific file for this OS is required. # The installer window looks a bit different on Windows so a specific file for this OS is required.
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_LICENSE_Windows) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE_LICENSE_Windows)
else() else()
set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE) set(CPACK_RESOURCE_FILE_LICENSE ${CMAKE_SOURCE_DIR}/LICENSE)
endif() endif()
@ -386,40 +319,40 @@ endif()
# Settings per operating system and generator type. # Settings per operating system and generator type.
if(APPLE) if(APPLE)
set(CPACK_GENERATOR Bundle) set(CPACK_GENERATOR Bundle)
set(CPACK_PACKAGE_FILE_NAME EmulationStation-DE-${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}) set(CPACK_PACKAGE_FILE_NAME ES-DE_${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE})
set(CPACK_DMG_VOLUME_NAME "EmulationStation Desktop Edition ${CPACK_PACKAGE_VERSION}") set(CPACK_DMG_VOLUME_NAME "ES-DE ${CPACK_PACKAGE_VERSION}")
set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE.icns) set(CPACK_PACKAGE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE.icns)
set(CPACK_DMG_DS_STORE ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_DS_Store) set(CPACK_DMG_DS_STORE ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE_DS_Store)
set(CPACK_BUNDLE_NAME "EmulationStation Desktop Edition") set(CPACK_BUNDLE_NAME "ES-DE")
set(CPACK_BUNDLE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE.icns) set(CPACK_BUNDLE_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE.icns)
set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation-DE_Info.plist) set(CPACK_BUNDLE_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE_Info.plist)
if(MACOS_CODESIGN_IDENTITY) if(MACOS_CODESIGN_IDENTITY)
set(CPACK_BUNDLE_APPLE_CERT_APP "Developer ID Application: ${MACOS_CODESIGN_IDENTITY}") set(CPACK_BUNDLE_APPLE_CERT_APP "Developer ID Application: ${MACOS_CODESIGN_IDENTITY}")
set(CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER "--deep --force --options runtime") set(CPACK_BUNDLE_APPLE_CODESIGN_PARAMETER "--deep --force --options runtime")
endif() endif()
elseif(WIN32) elseif(WIN32)
set(CPACK_GENERATOR NSIS) set(CPACK_GENERATOR NSIS)
set(CPACK_PACKAGE_FILE_NAME EmulationStation-DE-${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}) set(CPACK_PACKAGE_FILE_NAME ES-DE_${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE})
set(CPACK_PACKAGE_INSTALL_DIRECTORY EmulationStation-DE) set(CPACK_PACKAGE_INSTALL_DIRECTORY ES-DE)
set(CPACK_PACKAGE_EXECUTABLES EmulationStation EmulationStation) set(CPACK_PACKAGE_EXECUTABLES ES-DE ES-DE)
set(CPACK_NSIS_INSTALL_ROOT ${PROGRAMFILES64}) set(CPACK_NSIS_INSTALL_ROOT ${PROGRAMFILES64})
set(CPACK_NSIS_EXECUTABLES_DIRECTORY .) set(CPACK_NSIS_EXECUTABLES_DIRECTORY .)
set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/EmulationStation.ico) set(CPACK_NSIS_MUI_ICON ${CMAKE_CURRENT_SOURCE_DIR}/assets/ES-DE.ico)
set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON) set(CPACK_NSIS_ENABLE_UNINSTALL_BEFORE_INSTALL ON)
set(CPACK_NSIS_DISPLAY_NAME "EmulationStation Desktop Edition ${CPACK_PACKAGE_VERSION}") set(CPACK_NSIS_DISPLAY_NAME "ES-DE ${CPACK_PACKAGE_VERSION}")
set(CPACK_NSIS_PACKAGE_NAME "EmulationStation Desktop Edition") set(CPACK_NSIS_PACKAGE_NAME "ES-DE")
set(CPACK_NSIS_INSTALLED_ICON_NAME EmulationStation.exe) set(CPACK_NSIS_INSTALLED_ICON_NAME ES-DE.exe)
set(CPACK_NSIS_WELCOME_TITLE "EmulationStation Desktop Edition Installer") set(CPACK_NSIS_WELCOME_TITLE "ES-DE Installer")
set(CPACK_NSIS_FINISH_TITLE "EmulationStation Desktop Edition Installation Completed") set(CPACK_NSIS_FINISH_TITLE "ES-DE Installation Completed")
set(CPACK_NSIS_MANIFEST_DPI_AWARE ON) set(CPACK_NSIS_MANIFEST_DPI_AWARE ON)
set(CPACK_NSIS_MENU_LINKS "https://es-de.org" "ES-DE Website" "https://es-de.org" "Please Donate") set(CPACK_NSIS_MENU_LINKS "https://es-de.org" "ES-DE Website")
else() else()
set(CPACK_PACKAGE_INSTALL_DIRECTORY emulationstation_${CMAKE_PACKAGE_VERSION}) set(CPACK_PACKAGE_INSTALL_DIRECTORY es-de_${CMAKE_PACKAGE_VERSION})
set(CPACK_PACKAGE_EXECUTABLES emulationstation emulationstation) set(CPACK_PACKAGE_EXECUTABLES es-de es-de)
if(LINUX_CPACK_GENERATOR MATCHES DEB) if(LINUX_CPACK_GENERATOR MATCHES DEB)
set(CPACK_GENERATOR DEB) set(CPACK_GENERATOR DEB)
endif() endif()
set(CPACK_DEBIAN_FILE_NAME emulationstation-de-${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}.deb) set(CPACK_DEBIAN_FILE_NAME es-de_${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}.deb)
set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Leon Styhre <info@es-de.org>") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "Leon Styhre <info@es-de.org>")
set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://es-de.org) set(CPACK_DEBIAN_PACKAGE_HOMEPAGE https://es-de.org)
set(CPACK_DEBIAN_PACKAGE_SECTION games) set(CPACK_DEBIAN_PACKAGE_SECTION games)
@ -428,7 +361,7 @@ else()
if(LINUX_CPACK_GENERATOR MATCHES RPM) if(LINUX_CPACK_GENERATOR MATCHES RPM)
set(CPACK_GENERATOR RPM) set(CPACK_GENERATOR RPM)
endif() endif()
set(CPACK_RPM_FILE_NAME emulationstation-de-${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}.rpm) set(CPACK_RPM_FILE_NAME es-de_${CPACK_PACKAGE_VERSION}-${CPU_ARCHITECTURE}.rpm)
set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION}) set(CPACK_RPM_PACKAGE_DESCRIPTION ${CPACK_PACKAGE_DESCRIPTION})
set(CPACK_RPM_PACKAGE_LICENSE MIT) set(CPACK_RPM_PACKAGE_LICENSE MIT)
list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_PREFIX}) list(APPEND CPACK_RPM_EXCLUDE_FROM_AUTO_FILELIST_ADDITION ${CMAKE_INSTALL_PREFIX})

View file

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 291 KiB

View file

@ -1,4 +1,4 @@
#include "EmulationStation.h" #include "ApplicationVersion.h"
#include "windows.h" #include "windows.h"
@ -21,13 +21,13 @@ BEGIN
BEGIN BEGIN
VALUE "Comments", "\0" VALUE "Comments", "\0"
VALUE "CompanyName", "es-de.org\0" VALUE "CompanyName", "es-de.org\0"
VALUE "FileDescription", "EmulationStation\0" VALUE "FileDescription", "ES-DE\0"
VALUE "FileVersion", RESOURCE_VERSION_STRING VALUE "FileVersion", RESOURCE_VERSION_STRING
VALUE "InternalName", "emulationstation.exe\0" VALUE "InternalName", "ES-DE.exe\0"
VALUE "LegalCopyright", "Copyright (c) 2020-2023 Leon Styhre\0" VALUE "LegalCopyright", "Copyright (c) 2020-2024 Leon Styhre\0"
VALUE "LegalTrademarks", "\0" VALUE "LegalTrademarks", "\0"
VALUE "OriginalFilename", "emulationstation.exe\0" VALUE "OriginalFilename", "ES-DE.exe\0"
VALUE "ProductName", "EmulationStation\0" VALUE "ProductName", "ES-DE\0"
VALUE "ProductVersion", PROGRAM_VERSION_STRING VALUE "ProductVersion", PROGRAM_VERSION_STRING
END END
END END
@ -37,4 +37,4 @@ BEGIN
END END
END END
IDI_ES_LOGO ICON DISCARDABLE "EmulationStation.ico" IDI_ES_LOGO ICON DISCARDABLE "ES-DE.ico"

View file

@ -3,31 +3,31 @@
<plist version="1.0"> <plist version="1.0">
<dict> <dict>
<key>CFBundleIdentifier</key> <key>CFBundleIdentifier</key>
<string>org.es-de.EmulationStation</string> <string>3.0.0</string>
<key>CFBundleDevelopmentRegion</key> <key>CFBundleDevelopmentRegion</key>
<string>English</string> <string>English</string>
<key>CFBundleDisplayName</key> <key>CFBundleDisplayName</key>
<string>EmulationStation Desktop Edition</string> <string>ES-DE</string>
<key>CFBundleExecutable</key> <key>CFBundleExecutable</key>
<string>EmulationStation</string> <string>ES-DE</string>
<key>CFBundleGetInfoString</key> <key>CFBundleGetInfoString</key>
<string>EmulationStation Desktop Edition 2.2.1</string> <string>ES-DE 3.0.0</string>
<key>CFBundleIconFile</key> <key>CFBundleIconFile</key>
<string>EmulationStation-DE.icns</string> <string>ES-DE.icns</string>
<key>CFBundleName</key> <key>CFBundleName</key>
<string>EmulationStation Desktop Edition</string> <string>ES-DE</string>
<key>CFBundlePackageType</key> <key>CFBundlePackageType</key>
<string>APPL</string> <string>APPL</string>
<key>CFBundleSignature</key> <key>CFBundleSignature</key>
<string>ESDE</string> <string>ESDE</string>
<key>CFBundleShortVersionString</key> <key>CFBundleShortVersionString</key>
<string>2.2.1</string> <string>3.0.0-alpha</string>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>2.2.1</string> <string>3.0.0-alpha</string>
<key>CFBundleInfoDictionaryVersion</key> <key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string> <string>6.0</string>
<key>LSApplicationCategoryType</key> <key>LSApplicationCategoryType</key>
<string>public.app-category.games</string> <string>public.app-category.education</string>
<key>LSMinimumSystemVersion</key> <key>LSMinimumSystemVersion</key>
<string>10.15.0</string> <string>10.15.0</string>
<key>LSUIPresentationMode</key> <key>LSUIPresentationMode</key>
@ -37,9 +37,9 @@
<key>NSPrincipalClass</key> <key>NSPrincipalClass</key>
<string>NSApplication</string> <string>NSApplication</string>
<key>NSMainNibFile</key> <key>NSMainNibFile</key>
<string>EmulationStation</string> <string>ES-DE</string>
<key>NSHumanReadableCopyright</key> <key>NSHumanReadableCopyright</key>
<string>Copyright (c) 2020-2023 Leon Styhre <string>Copyright (c) 2020-2024 Leon Styhre
Copyright (c) 2014 Alec Lofquist Copyright (c) 2014 Alec Lofquist
Licensed under the MIT license</string> Licensed under the MIT license</string>
</dict> </dict>

View file

@ -1,4 +1,4 @@
Copyright (c) 2020-2023 Leon Styhre Copyright (c) 2020-2024 Leon Styhre
Copyright (c) 2014 Alec Lofquist Copyright (c) 2014 Alec Lofquist
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy

View file

@ -1,6 +1,6 @@
Copyright (c) 2020-2023 Leon Styhre Copyright (c) 2020-2024 Leon Styhre
Copyright (c) 2014 Alec Lofquist Copyright (c) 2014 Alec Lofquist
Permission is hereby granted, free of charge, to any person Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without files (the "Software"), to deal in the Software without
@ -9,10 +9,10 @@ copy, modify, merge, publish, distribute, sublicense, and/or
sell copies of the Software, and to permit persons to whom sell copies of the Software, and to permit persons to whom
the Software is furnished to do so, subject to the following the Software is furnished to do so, subject to the following
conditions: conditions:
The above copyright notice and this permission notice shall be The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software. included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A

View file

@ -1 +1 @@
Place manually downloaded or modified themes into .emulationstation\themes\ and not into this directory Place manually downloaded or modified themes into ES-DE\ES-DE\themes\ and not into this directory

View file

@ -1,11 +1,10 @@
EmulationStation Desktop Edition (ES-DE) - Portable installation on Windows ES-DE (EmulationStation Desktop Edition) - Portable installation on Windows
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
ES-DE release: ES-DE release:
2.2.1 3.0.0
The latest version can be downloaded from https://es-de.org The latest version can be downloaded from https://es-de.org
Please also consider donating to the project, links for that can be found on the ES-DE website just mentioned.
Instructions: Instructions:
@ -15,18 +14,18 @@ New installation:
1) The ROMs_ALL directory contains all the systems that ES-DE supports, but to decrease application startup time only copy the folders you need to the ROMs directory 1) The ROMs_ALL directory contains all the systems that ES-DE supports, but to decrease application startup time only copy the folders you need to the ROMs directory
2) Place your games into their respective folders in the ROMs directory tree 2) Place your games into their respective folders in the ROMs directory tree
3) Place your emulators inside the Emulators directory 3) Place your emulators inside the Emulators directory
4) Start ES-DE using EmulationStation.exe and enjoy some retrogaming! 4) Start ES-DE using ES-DE.exe and enjoy some retrogaming!
Upgrading from an older release: Upgrading from an older release:
1) Rename your old EmulationStation-DE directory, for example to EmulationStation-DE_OLD 1) Rename your old ES-DE directory, for example to ES-DE_OLD
2) Move your games from EmulationStation-DE_OLD\ROMs\ to EmulationStation-DE\ROMs\ 2) Move your games from ES-DE_OLD\ROMs\ to ES-DE\ROMs\
3) Move your emulators from EmulationStation-DE_OLD\Emulators\ to EmulationStation-DE\Emulators\ 3) Move your emulators from ES-DE_OLD\Emulators\ to ES-DE\Emulators\
4) Move the contents of EmulationStation-DE_OLD\.emulationstation\ to EmulationStation-DE\.emulationstation\ 4) Move the contents of ES-DE_OLD\ES-DE\ to ES-DE\ES-DE\
This last step includes your settings, custom collections, custom systems, scraped/downloaded media, gamelist.xml files, scripts and themes This last step includes your settings, custom collections, custom systems, scraped/downloaded media, gamelist.xml files, scripts and themes
5) Update your themes using the theme downloader to get support for all the latest systems and features 5) Update your themes using the theme downloader to get support for all the latest systems and features
In case of issues, check .emulationstation\es_log.txt for clues as to what went wrong. In case of issues, check ES-DE\es_log.txt for clues as to what went wrong.
Enabling the "Debug mode" setting in the "Other settings" menu or starting EmulationStation.exe with the --debug flag will provide additional details. Enabling the "Debug mode" setting in the "Other settings" menu or starting ES-DE.exe with the --debug flag will provide additional details.
Refer to the FAQ and user guide for more detailed instructions and documentation: Refer to the FAQ and user guide for more detailed instructions and documentation:
https://gitlab.com/es-de/emulationstation-de/-/blob/master/FAQ.md https://gitlab.com/es-de/emulationstation-de/-/blob/master/FAQ.md
@ -128,7 +127,8 @@ Emulators\VICE\xplus4.exe
Emulators\VICE\bin\xplus4.exe Emulators\VICE\bin\xplus4.exe
Emulators\VICE\xvic.exe Emulators\VICE\xvic.exe
Emulators\VICE\bin\xvic.exe Emulators\VICE\bin\xvic.exe
Emulators\Visual Pinball\VPinballX.exe Emulators\VPinballX\VPinballX_GL64.exe
Emulators\VPinballX\VPinballX64.exe
Emulators\Vita3K\Vita3K.exe Emulators\Vita3K\Vita3K.exe
Emulators\xemu\xemu.exe Emulators\xemu\xemu.exe
Emulators\xenia\xenia.exe Emulators\xenia\xenia.exe

Binary file not shown.

BIN
es-app/assets/es-de.6.gz Normal file

Binary file not shown.

View file

@ -1,13 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application"> <component type="desktop-application">
<id>org.es_de.emulationstation-de</id> <id>org.es_de.frontend</id>
<name>EmulationStation Desktop Edition</name> <name>ES-DE</name>
<summary>Emulator frontend</summary> <summary>Emulator frontend</summary>
<description> <description>
<p>EmulationStation Desktop Edition (ES-DE) is a frontend for browsing and <p>ES-DE (EmulationStation Desktop Edition) is a frontend for browsing and
launching games from your multi-platform game collection.</p> launching games from your multi-platform game collection.</p>
</description> </description>
<launchable type="desktop-id">org.es_de.emulationstation-de.desktop</launchable> <launchable type="desktop-id">org.es_de.frontend.desktop</launchable>
<categories> <categories>
<category>Game</category> <category>Game</category>
<category>Emulator</category> <category>Emulator</category>
@ -38,6 +38,9 @@
</screenshot> </screenshot>
</screenshots> </screenshots>
<releases> <releases>
<release version="3.0.0" date="2024-02-17">
<url>https://gitlab.com/es-de/emulationstation-de/-/releases</url>
</release>
<release version="2.2.1" date="2023-11-12"> <release version="2.2.1" date="2023-11-12">
<url>https://gitlab.com/es-de/emulationstation-de/-/releases</url> <url>https://gitlab.com/es-de/emulationstation-de/-/releases</url>
</release> </release>

View file

@ -1,12 +1,12 @@
[Desktop Entry] [Desktop Entry]
Version=1.0 Version=1.0
Exec=emulationstation Exec=es-de
Icon=org.es_de.emulationstation-de Icon=org.es_de.frontend
Terminal=false Terminal=false
Type=Application Type=Application
StartupNotify=true StartupNotify=true
Hidden=false Hidden=false
Categories=Game;Emulator; Categories=Game;Emulator;
Name=EmulationStation Desktop Edition Name=ES-DE
GenericName=Emulator Frontend GenericName=Emulator Frontend
Keywords=emulator;emulation;front-end;frontend; Keywords=emulator;emulation;front-end;frontend;

View file

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 9.1 KiB

View file

@ -1,16 +1,16 @@
# SPDX-License-Identifier: MIT # SPDX-License-Identifier: MIT
# #
# EmulationStation Desktop Edition # ES-DE
# org.es_de.emulationstation-de.yml # org.es_de.frontend.yml
# #
# Flatpak manifest file for use with flatpak-builder. # Flatpak manifest file for use with flatpak-builder.
# #
app-id: org.es_de.emulationstation-de app-id: org.es_de.frontend-de
sdk: org.freedesktop.Sdk sdk: org.freedesktop.Sdk
runtime: org.freedesktop.Platform runtime: org.freedesktop.Platform
runtime-version: '21.08' runtime-version: '21.08'
command: emulationstation command: es-de
finish-args: finish-args:
- --share=ipc - --share=ipc
- --socket=x11 - --socket=x11
@ -74,7 +74,7 @@ modules:
url: https://github.com/zeux/pugixml/releases/download/v1.11.4/pugixml-1.11.4.tar.gz url: https://github.com/zeux/pugixml/releases/download/v1.11.4/pugixml-1.11.4.tar.gz
sha256: 8ddf57b65fb860416979a3f0640c2ad45ddddbbafa82508ef0a0af3ce7061716 sha256: 8ddf57b65fb860416979a3f0640c2ad45ddddbbafa82508ef0a0af3ce7061716
- name: emulationstation - name: es-de
buildsystem: cmake-ninja buildsystem: cmake-ninja
config-opts: config-opts:
- -DFLATPAK_BUILD=on - -DFLATPAK_BUILD=on

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// ApplicationUpdater.cpp // ApplicationUpdater.cpp
// //
// Checks for application updates. // Checks for application updates.
@ -9,7 +9,7 @@
#include "ApplicationUpdater.h" #include "ApplicationUpdater.h"
#include "EmulationStation.h" #include "ApplicationVersion.h"
#include "Log.h" #include "Log.h"
#include "Settings.h" #include "Settings.h"
#include "resources/ResourceManager.h" #include "resources/ResourceManager.h"
@ -211,8 +211,8 @@ void ApplicationUpdater::parseFile()
#if (LOCAL_TESTING_FILE) #if (LOCAL_TESTING_FILE)
LOG(LogWarning) << "ApplicationUpdater: Using local \"latest_release.json\" testing file"; LOG(LogWarning) << "ApplicationUpdater: Using local \"latest_release.json\" testing file";
const std::string localReleaseFile {Utils::FileSystem::getHomePath() + const std::string localReleaseFile {Utils::FileSystem::getAppDataDirectory() +
"/.emulationstation/latest_release.json"}; "/latest_release.json"};
if (!Utils::FileSystem::exists(localReleaseFile)) if (!Utils::FileSystem::exists(localReleaseFile))
throw std::runtime_error("Local testing file not found"); throw std::runtime_error("Local testing file not found");

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// ApplicationUpdater.h // ApplicationUpdater.h
// //
// Checks for application updates. // Checks for application updates.

View file

@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
//
// ES-DE
// ApplicationVersion.h
//
#ifndef ES_APP_APPLICATION_VERSION_H
#define ES_APP_APPLICATION_VERSION_H
// These numbers and strings need to be manually updated for a new version.
// Do this version number update as the very last commit for the new release version.
// clang-format off
#define PROGRAM_VERSION_MAJOR 3
#define PROGRAM_VERSION_MINOR 0
#define PROGRAM_VERSION_MAINTENANCE 0
#define PROGRAM_RELEASE_NUMBER 41
// clang-format on
#define PROGRAM_VERSION_STRING "3.0.0"
#define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__
#define RESOURCE_VERSION_STRING "3,0,0\0"
#define RESOURCE_VERSION PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_MAINTENANCE
#endif // ES_APP_APPLICATION_VERSION_H

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// CollectionSystemsManager.cpp // CollectionSystemsManager.cpp
// //
// Manages collections of the following two types: // Manages collections of the following two types:
@ -634,8 +634,31 @@ void CollectionSystemsManager::setEditMode(const std::string& collectionName, bo
mEditingCollectionSystemData = sysData; mEditingCollectionSystemData = sysData;
if (showPopup) { if (showPopup) {
const std::string controllerType {
Settings::getInstance()->getString("InputControllerType")};
std::string editButton;
if (controllerType == "ps123" || controllerType == "ps4" || controllerType == "ps5") {
#if defined(_MSC_VER) // MSVC compiler.
if (Settings::getInstance()->getBool("InputSwapButtons"))
editButton = Utils::String::wideStringToString(L"\uF04D"); // Square.
else
editButton = Utils::String::wideStringToString(L"\uF0D8"); // Triangle.
#else
if (Settings::getInstance()->getBool("InputSwapButtons"))
editButton = "\uF04D"; // Square.
else
editButton = "\uF0D8"; // Triangle.
#endif
}
else {
if (Settings::getInstance()->getBool("InputSwapButtons"))
editButton = "'X'";
else
editButton = "'Y'";
}
mWindow->queueInfoPopup("EDITING '" + Utils::String::toUpper(collectionName) + mWindow->queueInfoPopup("EDITING '" + Utils::String::toUpper(collectionName) +
"' COLLECTION, ADD/REMOVE GAMES WITH 'Y'", "' COLLECTION, ADD/REMOVE GAMES WITH " + editButton,
10000); 10000);
} }
} }
@ -1437,7 +1460,7 @@ std::vector<std::string> CollectionSystemsManager::getSystemsFromConfig()
std::vector<std::string> configPaths {SystemData::getConfigPath()}; std::vector<std::string> configPaths {SystemData::getConfigPath()};
// Here we don't honor the <loadExclusive> tag which may be present in the custom es_systems.xml // Here we don't honor the <loadExclusive> tag which may be present in the custom es_systems.xml
// file under ~/.emulationstation/custom_systems as we really want to include all the themes // file under <application data>/custom_systems as we really want to include all the themes
// supported by ES-DE. Otherwise a user may accidentally create a custom collection that // supported by ES-DE. Otherwise a user may accidentally create a custom collection that
// corresponds to a supported theme. // corresponds to a supported theme.
for (auto path : configPaths) { for (auto path : configPaths) {
@ -1625,6 +1648,6 @@ std::string CollectionSystemsManager::getCustomCollectionConfigPath(
std::string CollectionSystemsManager::getCollectionsFolder() std::string CollectionSystemsManager::getCollectionsFolder()
{ {
return Utils::FileSystem::getGenericPath(Utils::FileSystem::getHomePath() + return Utils::FileSystem::getGenericPath(Utils::FileSystem::getAppDataDirectory() +
"/.emulationstation/collections"); "/collections");
} }

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// CollectionSystemsManager.h // CollectionSystemsManager.h
// //
// Manages collections of the following two types: // Manages collections of the following two types:

View file

@ -1,26 +0,0 @@
// SPDX-License-Identifier: MIT
//
// EmulationStation.h
//
// Version and build information.
//
#ifndef ES_APP_EMULATION_STATION_H
#define ES_APP_EMULATION_STATION_H
// These numbers and strings need to be manually updated for a new version.
// Do this version number update as the very last commit for the new release version.
// clang-format off
#define PROGRAM_VERSION_MAJOR 2
#define PROGRAM_VERSION_MINOR 2
#define PROGRAM_VERSION_MAINTENANCE 1
#define PROGRAM_RELEASE_NUMBER 40
// clang-format on
#define PROGRAM_VERSION_STRING "2.2.1"
#define PROGRAM_BUILT_STRING __DATE__ " - " __TIME__
#define RESOURCE_VERSION_STRING "2,2,1\0"
#define RESOURCE_VERSION PROGRAM_VERSION_MAJOR, PROGRAM_VERSION_MINOR, PROGRAM_VERSION_MAINTENANCE
#endif // ES_APP_EMULATION_STATION_H

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileData.cpp // FileData.cpp
// //
// Provides game file data structures and functions to access and sort this information. // Provides game file data structures and functions to access and sort this information.
@ -25,6 +25,10 @@
#include "views/GamelistView.h" #include "views/GamelistView.h"
#include "views/ViewController.h" #include "views/ViewController.h"
#if defined(__ANDROID__)
#include "utils/PlatformUtilAndroid.h"
#endif
#include <assert.h> #include <assert.h>
#include <regex> #include <regex>
@ -148,6 +152,10 @@ const std::vector<FileData*> FileData::getChildrenRecursive() const
const std::string FileData::getROMDirectory() const std::string FileData::getROMDirectory()
{ {
#if defined(__ANDROID__)
return AndroidVariables::sROMDirectory;
#endif
const std::string& romDirSetting {Settings::getInstance()->getString("ROMDirectory")}; const std::string& romDirSetting {Settings::getInstance()->getString("ROMDirectory")};
std::string romDirPath; std::string romDirPath;
@ -180,8 +188,8 @@ const std::string FileData::getMediaDirectory()
const std::string& mediaDirSetting {Settings::getInstance()->getString("MediaDirectory")}; const std::string& mediaDirSetting {Settings::getInstance()->getString("MediaDirectory")};
std::string mediaDirPath; std::string mediaDirPath;
if (mediaDirSetting == "") { if (mediaDirSetting.empty()) {
mediaDirPath = Utils::FileSystem::getHomePath() + "/.emulationstation/downloaded_media/"; mediaDirPath = Utils::FileSystem::getAppDataDirectory() + "/downloaded_media/";
} }
else { else {
mediaDirPath = mediaDirSetting; mediaDirPath = mediaDirSetting;
@ -202,7 +210,6 @@ const std::string FileData::getMediaDirectory()
const std::string FileData::getMediafilePath(const std::string& subdirectory) const const std::string FileData::getMediafilePath(const std::string& subdirectory) const
{ {
const std::vector<std::string> extList {".png", ".jpg"};
std::string subFolders; std::string subFolders;
// Extract possible subfolders from the path. // Extract possible subfolders from the path.
@ -214,8 +221,8 @@ const std::string FileData::getMediafilePath(const std::string& subdirectory) co
subFolders + "/" + getDisplayName()}; subFolders + "/" + getDisplayName()};
// Look for an image file in the media directory. // Look for an image file in the media directory.
for (size_t i {0}; i < extList.size(); ++i) { for (auto& extension : sImageExtensions) {
std::string mediaPath {tempPath + extList[i]}; const std::string mediaPath {tempPath + extension};
if (Utils::FileSystem::exists(mediaPath)) if (Utils::FileSystem::exists(mediaPath))
return mediaPath; return mediaPath;
} }
@ -307,7 +314,6 @@ const std::string FileData::getCustomImagePath() const
const std::string FileData::getVideoPath() const const std::string FileData::getVideoPath() const
{ {
const std::vector<std::string> extList {".avi", ".mkv", ".mov", ".mp4", ".wmv"};
std::string subFolders; std::string subFolders;
// Extract possible subfolders from the path. // Extract possible subfolders from the path.
@ -319,8 +325,8 @@ const std::string FileData::getVideoPath() const
getDisplayName()}; getDisplayName()};
// Look for media in the media directory. // Look for media in the media directory.
for (size_t i {0}; i < extList.size(); ++i) { for (auto& extension : sVideoExtensions) {
std::string mediaPath {tempPath + extList[i]}; const std::string mediaPath {tempPath + extension};
if (Utils::FileSystem::exists(mediaPath)) if (Utils::FileSystem::exists(mediaPath))
return mediaPath; return mediaPath;
} }
@ -872,8 +878,13 @@ void FileData::launchGame()
} }
} }
else { else {
LOG(LogDebug) << "FileData::launchGame(): Using default emulator \"" if (!mEnvData->mLaunchCommands.front().second.empty()) {
<< mEnvData->mLaunchCommands.front().second << "\""; LOG(LogDebug) << "FileData::launchGame(): Using default emulator \""
<< mEnvData->mLaunchCommands.front().second << "\"";
}
else {
LOG(LogDebug) << "FileData::launchGame(): Using default emulator";
}
} }
if (command.empty()) if (command.empty())
@ -882,6 +893,7 @@ void FileData::launchGame()
std::string commandRaw {command}; std::string commandRaw {command};
std::string romPath {Utils::FileSystem::getEscapedPath(mPath)}; std::string romPath {Utils::FileSystem::getEscapedPath(mPath)};
std::string baseName {Utils::FileSystem::getStem(mPath)}; std::string baseName {Utils::FileSystem::getStem(mPath)};
std::string romRaw {Utils::FileSystem::getPreferredPath(mPath)};
// For the special case where a directory has a supported file extension and is therefore // For the special case where a directory has a supported file extension and is therefore
// interpreted as a file, check if there is a matching filename inside the directory. // interpreted as a file, check if there is a matching filename inside the directory.
@ -890,7 +902,11 @@ void FileData::launchGame()
for (std::string& file : Utils::FileSystem::getDirContent(mPath)) { for (std::string& file : Utils::FileSystem::getDirContent(mPath)) {
if (Utils::FileSystem::getFileName(file) == Utils::FileSystem::getFileName(mPath) && if (Utils::FileSystem::getFileName(file) == Utils::FileSystem::getFileName(mPath) &&
(Utils::FileSystem::isRegularFile(file) || Utils::FileSystem::isSymlink(file))) { (Utils::FileSystem::isRegularFile(file) || Utils::FileSystem::isSymlink(file))) {
#if defined(__ANDROID__)
romRaw = file;
#else
romPath = Utils::FileSystem::getEscapedPath(file); romPath = Utils::FileSystem::getEscapedPath(file);
#endif
baseName = baseName.substr(0, baseName.find(".")); baseName = baseName.substr(0, baseName.find("."));
break; break;
} }
@ -898,8 +914,13 @@ void FileData::launchGame()
} }
const std::string fileName {baseName + Utils::FileSystem::getExtension(romPath)}; const std::string fileName {baseName + Utils::FileSystem::getExtension(romPath)};
const std::string romRaw {Utils::FileSystem::getPreferredPath(mPath)};
const std::string esPath {Utils::FileSystem::getExePath()}; const std::string esPath {Utils::FileSystem::getExePath()};
#if defined(__ANDROID__)
// On Android we always run in the background, although the logic is a bit different
// as we don't need to wake up the application manually.
bool runInBackground {true};
#else
bool runInBackground {false}; bool runInBackground {false};
// In addition to the global RunInBackground setting it's possible to define this flag // In addition to the global RunInBackground setting it's possible to define this flag
@ -918,6 +939,7 @@ void FileData::launchGame()
// The global setting always applies. // The global setting always applies.
if (Settings::getInstance()->getBool("RunInBackground")) if (Settings::getInstance()->getBool("RunInBackground"))
runInBackground = true; runInBackground = true;
#endif
#if !defined(_WIN64) #if !defined(_WIN64)
// Whether to parse .desktop files on Unix or open apps or alias files on macOS. // Whether to parse .desktop files on Unix or open apps or alias files on macOS.
@ -947,6 +969,19 @@ void FileData::launchGame()
bool foundCoreFile {false}; bool foundCoreFile {false};
std::vector<std::string> emulatorCorePaths; std::vector<std::string> emulatorCorePaths;
#if defined(__ANDROID__)
std::string androidPackage;
std::string androidActivity;
std::string androidAction;
std::string androidCategory;
std::string androidMimeType;
std::string androidData;
std::map<std::string, std::string> androidExtrasString;
std::map<std::string, std::string> androidExtrasStringArray;
std::map<std::string, std::string> androidExtrasBool;
std::vector<std::string> androidActivityFlags;
#endif
#if defined(_WIN64) #if defined(_WIN64)
bool hideWindow {false}; bool hideWindow {false};
@ -997,30 +1032,27 @@ void FileData::launchGame()
// Expand home path if ~ is used. // Expand home path if ~ is used.
command = Utils::FileSystem::expandHomePath(command); command = Utils::FileSystem::expandHomePath(command);
std::string preCommandPath;
// Check for any pre-command entry, and if it exists then expand it using the find rules. // Check for any pre-command entry, and if it exists then expand it using the find rules.
if (command.find("%PRECOMMAND_") != std::string::npos) { if (command.find("%PRECOMMAND_") != std::string::npos) {
preCommandPath = findEmulatorPath(command, true); const std::pair<std::string, FileData::findEmulatorResult> preCommand {
findEmulator(command, true)};
// Show an error message if there was no matching emulator entry in es_find_rules.xml. // Show an error message if there was no matching emulator entry in es_find_rules.xml.
if (preCommandPath.substr(0, 18) == "NO EMULATOR RULE: ") { if (preCommand.second == FileData::findEmulatorResult::NO_RULES) {
const std::string& preCommandEntry {
preCommandPath.substr(18, preCommandPath.size() - 18)};
LOG(LogError) LOG(LogError)
<< "Couldn't launch game, either there is no emulator entry for pre-command \"" << "Couldn't launch game, either there is no emulator entry for pre-command \""
<< preCommandEntry << "\" in es_find_rules.xml or there are no rules defined"; << preCommand.first << "\" in es_find_rules.xml or there are no rules defined";
LOG(LogError) << "Raw emulator launch command:"; LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw; LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: MISSING PRE-COMMAND FIND RULES CONFIGURATION FOR '" + window->queueInfoPopup("ERROR: MISSING PRE-COMMAND FIND RULES CONFIGURATION FOR '" +
preCommandEntry + "'", preCommand.first + "'",
6000); 6000);
window->setAllowTextScrolling(true); window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true); window->setAllowFileAnimation(true);
return; return;
} }
else if (preCommandPath.empty()) { else if (preCommand.first.empty()) {
LOG(LogError) << "Couldn't launch game, pre-command binary not found"; LOG(LogError) << "Couldn't launch game, pre-command not found";
LOG(LogError) << "Raw emulator launch command:"; LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw; LOG(LogError) << commandRaw;
@ -1047,30 +1079,30 @@ void FileData::launchGame()
return; return;
} }
else { else {
LOG(LogDebug) << "FileData::launchGame(): Pre-command binary set to \"" LOG(LogDebug) << "FileData::launchGame(): Pre-command set to \"" << preCommand.first
<< preCommandPath << "\""; << "\"";
} }
} }
// Check that the emulator binary actually exists, and if so, get its path. // Check that the emulator actually exists, and if so, get its path.
const std::string& binaryPath {findEmulatorPath(command, false)}; const std::pair<std::string, FileData::findEmulatorResult> emulator {
findEmulator(command, false)};
// Show an error message if there was no matching emulator entry in es_find_rules.xml. // Show an error message if there was no matching emulator entry in es_find_rules.xml.
if (binaryPath.substr(0, 18) == "NO EMULATOR RULE: ") { if (emulator.second == FileData::findEmulatorResult::NO_RULES) {
const std::string& emulatorEntry {binaryPath.substr(18, binaryPath.size() - 18)};
LOG(LogError) << "Couldn't launch game, either there is no emulator entry for \"" LOG(LogError) << "Couldn't launch game, either there is no emulator entry for \""
<< emulatorEntry << "\" in es_find_rules.xml or there are no rules defined"; << emulator.first << "\" in es_find_rules.xml or there are no rules defined";
LOG(LogError) << "Raw emulator launch command:"; LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw; LOG(LogError) << commandRaw;
window->queueInfoPopup( window->queueInfoPopup(
"ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulatorEntry + "'", 6000); "ERROR: MISSING EMULATOR FIND RULES CONFIGURATION FOR '" + emulator.first + "'", 6000);
window->setAllowTextScrolling(true); window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true); window->setAllowFileAnimation(true);
return; return;
} }
else if (binaryPath.empty()) { else if (emulator.second == FileData::findEmulatorResult::NOT_FOUND) {
LOG(LogError) << "Couldn't launch game, emulator binary not found"; LOG(LogError) << "Couldn't launch game, emulator not found";
LOG(LogError) << "Raw emulator launch command:"; LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw; LOG(LogError) << commandRaw;
@ -1098,15 +1130,29 @@ void FileData::launchGame()
} }
#if defined(_WIN64) #if defined(_WIN64)
else { else {
std::string binaryLogPath {Utils::String::replace( std::string emulatorLogPath {Utils::String::replace(
Utils::String::replace(binaryPath, "%ESPATH%", esPath), "/", "\\")}; Utils::String::replace(emulator.first, "%ESPATH%", esPath), "/", "\\")};
if (binaryLogPath.front() != '\"' && binaryLogPath.back() != '\"') if (emulatorLogPath.front() != '\"' && emulatorLogPath.back() != '\"')
binaryLogPath = "\"" + binaryLogPath + "\""; emulatorLogPath = "\"" + emulatorLogPath + "\"";
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to " << binaryLogPath; LOG(LogDebug) << "FileData::launchGame(): Emulator set to " << emulatorLogPath;
#else #else
#if defined(__ANDROID__)
else if (emulator.second == FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE) {
androidPackage = emulator.first;
size_t separatorPos {androidPackage.find('/')};
if (separatorPos != std::string::npos) {
androidActivity = androidPackage.substr(separatorPos + 1);
androidPackage = androidPackage.substr(0, separatorPos);
}
LOG(LogDebug) << "FileData::launchGame(): Found emulator package \"" << androidPackage
<< "\"";
}
#endif
else if (!isShortcut) { else if (!isShortcut) {
LOG(LogDebug) << "FileData::launchGame(): Emulator binary set to \"" LOG(LogDebug) << "FileData::launchGame(): Emulator set to \""
<< Utils::String::replace(binaryPath, "%ESPATH%", esPath) << "\""; << Utils::String::replace(emulator.first, "%ESPATH%", esPath) << "\"";
#endif #endif
} }
@ -1127,11 +1173,12 @@ void FileData::launchGame()
if (spacePos != std::string::npos) { if (spacePos != std::string::npos) {
coreRaw = command.substr(emuPathPos, spacePos - emuPathPos); coreRaw = command.substr(emuPathPos, spacePos - emuPathPos);
#if defined(_WIN64) #if defined(_WIN64)
coreFile = Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", "")) + coreFile =
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9); Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")) +
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
coreFile = Utils::String::replace(coreFile, "/", "\\"); coreFile = Utils::String::replace(coreFile, "/", "\\");
#else #else
coreFile = Utils::FileSystem::getParent(binaryPath) + coreFile = Utils::FileSystem::getParent(emulator.first) +
command.substr(emuPathPos + 9, spacePos - emuPathPos - 9); command.substr(emuPathPos + 9, spacePos - emuPathPos - 9);
#endif #endif
if (hasQuotationMark) { if (hasQuotationMark) {
@ -1192,7 +1239,7 @@ void FileData::launchGame()
// the emulator core using the rules defined in es_find_rules.xml. // the emulator core using the rules defined in es_find_rules.xml.
for (std::string& path : emulatorCorePaths) { for (std::string& path : emulatorCorePaths) {
// The position of the %CORE_ variable could have changed as there may have been an // The position of the %CORE_ variable could have changed as there may have been an
// %EMULATOR_ variable that was substituted for the actual emulator binary. // %EMULATOR_ variable that was substituted for the actual emulator.
coreEntryPos = command.find("%CORE_"); coreEntryPos = command.find("%CORE_");
coreFilePos = command.find("%", coreEntryPos + 6); coreFilePos = command.find("%", coreEntryPos + 6);
@ -1218,10 +1265,11 @@ void FileData::launchGame()
#if defined(_WIN64) #if defined(_WIN64)
coreFile = coreFile.replace( coreFile = coreFile.replace(
stringPos, 9, stringPos, 9,
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", ""))); Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
coreFile = Utils::String::replace(coreFile, "/", "\\"); coreFile = Utils::String::replace(coreFile, "/", "\\");
#else #else
coreFile = coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(binaryPath)); coreFile =
coreFile.replace(stringPos, 9, Utils::FileSystem::getParent(emulator.first));
#endif #endif
} }
@ -1325,7 +1373,7 @@ void FileData::launchGame()
#if defined(_WIN64) #if defined(_WIN64)
startDirectory = Utils::String::replace( startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%", startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\"", ""))); Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\"", "")));
startDirectory = Utils::String::replace( startDirectory = Utils::String::replace(
startDirectory, "%GAMEDIR%", startDirectory, "%GAMEDIR%",
@ -1336,7 +1384,7 @@ void FileData::launchGame()
#else #else
startDirectory = Utils::String::replace( startDirectory = Utils::String::replace(
startDirectory, "%EMUDIR%", startDirectory, "%EMUDIR%",
Utils::FileSystem::getParent(Utils::String::replace(binaryPath, "\\", ""))); Utils::FileSystem::getParent(Utils::String::replace(emulator.first, "\\", "")));
startDirectory = Utils::String::replace( startDirectory = Utils::String::replace(
startDirectory, "%GAMEDIR%", startDirectory, "%GAMEDIR%",
@ -1500,7 +1548,7 @@ void FileData::launchGame()
if (Utils::FileSystem::exists(Utils::String::replace(romPath, "\\", ""))) { if (Utils::FileSystem::exists(Utils::String::replace(romPath, "\\", ""))) {
LOG(LogInfo) << "Opening app or alias file \"" LOG(LogInfo) << "Opening app or alias file \""
<< Utils::String::replace(romPath, "\\", "") << "\""; << Utils::String::replace(romPath, "\\", "") << "\"";
command = Utils::String::replace(command, binaryPath, "open -W -a"); command = Utils::String::replace(command, emulator.first, "open -W -a");
} }
else { else {
LOG(LogError) << "App or alias file \"" << romPath LOG(LogError) << "App or alias file \"" << romPath
@ -1551,7 +1599,7 @@ void FileData::launchGame()
} }
romPath = Utils::String::replace(romPath, "%%", "%"); romPath = Utils::String::replace(romPath, "%%", "%");
romPath = Utils::String::trim(romPath); romPath = Utils::String::trim(romPath);
command = Utils::String::replace(command, binaryPath, ""); command = Utils::String::replace(command, emulator.first, "");
execEntry = true; execEntry = true;
break; break;
} }
@ -1576,6 +1624,7 @@ void FileData::launchGame()
#endif #endif
#endif #endif
#if !defined(__ANDROID__)
// Replace the remaining variables with their actual values. // Replace the remaining variables with their actual values.
command = Utils::String::replace(command, "%ROM%", romPath); command = Utils::String::replace(command, "%ROM%", romPath);
command = Utils::String::replace(command, "%BASENAME%", baseName); command = Utils::String::replace(command, "%BASENAME%", baseName);
@ -1583,12 +1632,142 @@ void FileData::launchGame()
command = Utils::String::replace(command, "%ROMRAW%", romRaw); command = Utils::String::replace(command, "%ROMRAW%", romRaw);
command = Utils::String::replace(command, "%ROMPATH%", command = Utils::String::replace(command, "%ROMPATH%",
Utils::FileSystem::getEscapedPath(getROMDirectory())); Utils::FileSystem::getEscapedPath(getROMDirectory()));
#else
command = Utils::String::replace(command, "%ANDROIDPACKAGE%", androidPackage);
const std::vector<std::string> androidVariabels {
"%ACTION%=", "%CATEGORY%=", "%MIMETYPE%=", "%DATA%="};
for (std::string variable : androidVariabels) {
size_t dataPos {command.find(variable)};
if (dataPos != std::string::npos) {
bool invalidEntry {false};
bool isQuoted {(command.length() > dataPos + variable.length() &&
command[dataPos + variable.length()] == '\"')};
std::string value;
if (isQuoted) {
const size_t closeQuotePos {command.find("\"", dataPos + variable.length() + 1)};
if (closeQuotePos != std::string::npos)
value = command.substr(dataPos + variable.length() + 1,
closeQuotePos - (dataPos + variable.length() + 1));
else
invalidEntry = true;
}
else {
const size_t spacePos {command.find(" ", dataPos)};
if (spacePos != std::string::npos)
value = command.substr(dataPos + variable.length(),
spacePos - (dataPos + variable.length()));
else
value = command.substr(dataPos + variable.length(),
command.size() - dataPos + variable.length());
}
if (invalidEntry) {
LOG(LogError) << "Invalid entry in systems configuration file es_systems.xml";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE", 6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
if (variable == "%ACTION%=")
androidAction = value;
else if (variable == "%DATA%=")
androidData = value;
else if (variable == "%CATEGORY%=")
androidCategory = value;
else if (variable == "%MIMETYPE%=")
androidMimeType = value;
}
}
std::vector<std::string> extraVariabels {"%EXTRA_", "%EXTRAARRAY_", "%EXTRABOOL_"};
for (std::string variable : extraVariabels) {
size_t extraPos {command.find(variable)};
while (extraPos != std::string::npos) {
if (extraPos != std::string::npos) {
bool invalidEntry {false};
bool isQuoted {false};
std::string extraName;
std::string extraValue;
size_t equalPos {command.find("=", extraPos)};
if (equalPos == std::string::npos)
invalidEntry = true;
if (!invalidEntry && extraPos + variable.length() + 1 >= command.size())
invalidEntry = true;
if (!invalidEntry) {
if (command.length() > equalPos && command[equalPos + 1] == '\"')
isQuoted = true;
extraName = command.substr(extraPos + variable.length(),
equalPos - (extraPos + variable.length() + 1));
if (isQuoted) {
const size_t closeQuotePos {command.find("\"", equalPos + 2)};
if (closeQuotePos != std::string::npos)
extraValue =
command.substr(equalPos + 2, closeQuotePos - (equalPos + 2));
else
invalidEntry = true;
}
else {
const size_t spacePos {command.find(" ", extraPos)};
if (spacePos != std::string::npos)
extraValue = command.substr(equalPos + 1, spacePos - (equalPos + 1));
else
extraValue = command.substr(equalPos + 1, command.size() - equalPos);
}
if (invalidEntry) {
LOG(LogError)
<< "Invalid entry in systems configuration file es_systems.xml";
LOG(LogError) << "Raw emulator launch command:";
LOG(LogError) << commandRaw;
window->queueInfoPopup("ERROR: INVALID ENTRY IN SYSTEMS CONFIGURATION FILE",
6000);
window->setAllowTextScrolling(true);
window->setAllowFileAnimation(true);
return;
}
if (extraName != "" && extraValue != "") {
if (variable == "%EXTRA_")
androidExtrasString[extraName] = extraValue;
else if (variable == "%EXTRAARRAY_")
androidExtrasStringArray[extraName] = extraValue;
else if (variable == "%EXTRABOOL_")
androidExtrasBool[extraName] = extraValue;
}
}
}
extraPos = command.find(variable, extraPos + 1);
}
}
if (command.find("%ACTIVITY_CLEAR_TASK%") != std::string::npos)
androidActivityFlags.emplace_back("%ACTIVITY_CLEAR_TASK%");
if (command.find("%ACTIVITY_CLEAR_TOP%") != std::string::npos)
androidActivityFlags.emplace_back("%ACTIVITY_CLEAR_TOP%");
if (command.find("%ACTIVITY_NO_HISTORY%") != std::string::npos)
androidActivityFlags.emplace_back("%ACTIVITY_NO_HISTORY%");
#endif
#if defined(_WIN64) #if defined(_WIN64)
command = Utils::String::replace( command = Utils::String::replace(
command, "%ESPATH%", Utils::String::replace(Utils::FileSystem::getExePath(), "/", "\\")); command, "%ESPATH%", Utils::String::replace(Utils::FileSystem::getExePath(), "/", "\\"));
command = Utils::String::replace(command, "%EMUDIR%", command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent( Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\"", "")))); Utils::String::replace(emulator.first, "\"", ""))));
command = Utils::String::replace(command, "%GAMEDIR%", command = Utils::String::replace(command, "%GAMEDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent( Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(romPath, "\"", "")))); Utils::String::replace(romPath, "\"", ""))));
@ -1600,7 +1779,7 @@ void FileData::launchGame()
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath()); command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
command = Utils::String::replace(command, "%EMUDIR%", command = Utils::String::replace(command, "%EMUDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent( Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(binaryPath, "\\", "")))); Utils::String::replace(emulator.first, "\\", ""))));
command = Utils::String::replace(command, "%GAMEDIR%", command = Utils::String::replace(command, "%GAMEDIR%",
Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent( Utils::FileSystem::getEscapedPath(Utils::FileSystem::getParent(
Utils::String::replace(romPath, "\\", "")))); Utils::String::replace(romPath, "\\", ""))));
@ -1625,8 +1804,40 @@ void FileData::launchGame()
LOG(LogDebug) << "Raw emulator launch command:"; LOG(LogDebug) << "Raw emulator launch command:";
LOG(LogDebug) << commandRaw; LOG(LogDebug) << commandRaw;
#if defined(__ANDROID__)
LOG(LogInfo) << "Expanded emulator launch arguments:";
LOG(LogInfo) << "Package: " << androidPackage;
if (androidActivity != "") {
LOG(LogInfo) << "Activity: " << androidActivity;
}
if (androidAction != "") {
LOG(LogInfo) << "Action: " << androidAction;
}
if (androidCategory != "") {
LOG(LogInfo) << "Category: " << androidCategory;
}
if (androidMimeType != "") {
LOG(LogInfo) << "MIME type: " << androidMimeType;
}
if (androidData != "") {
LOG(LogInfo) << "Data: " << androidData;
}
for (auto& extra : androidExtrasString) {
LOG(LogInfo) << "Extra name: " << extra.first;
LOG(LogInfo) << "Extra value: " << extra.second;
}
for (auto& extra : androidExtrasStringArray) {
LOG(LogInfo) << "Extra array name: " << extra.first;
LOG(LogInfo) << "Extra array value: " << extra.second;
}
for (auto& extra : androidExtrasBool) {
LOG(LogInfo) << "Extra bool name: " << extra.first;
LOG(LogInfo) << "Extra bool value: " << extra.second;
}
#else
LOG(LogInfo) << "Expanded emulator launch command:"; LOG(LogInfo) << "Expanded emulator launch command:";
LOG(LogInfo) << command; LOG(LogInfo) << command;
#endif
#if defined(FLATPAK_BUILD) #if defined(FLATPAK_BUILD)
// Break out of the sandbox. // Break out of the sandbox.
@ -1645,12 +1856,17 @@ void FileData::launchGame()
returnValue = Utils::Platform::launchGameWindows( returnValue = Utils::Platform::launchGameWindows(
Utils::String::stringToWideString(command), Utils::String::stringToWideString(command),
Utils::String::stringToWideString(startDirectory), runInBackground, hideWindow); Utils::String::stringToWideString(startDirectory), runInBackground, hideWindow);
#elif defined(__ANDROID__)
returnValue = Utils::Platform::Android::launchGame(
androidPackage, androidActivity, androidAction, androidCategory, androidMimeType,
androidData, romRaw, androidExtrasString, androidExtrasStringArray, androidExtrasBool,
androidActivityFlags);
#else #else
returnValue = Utils::Platform::launchGameUnix(command, startDirectory, runInBackground); returnValue = Utils::Platform::launchGameUnix(command, startDirectory, runInBackground);
#endif #endif
// Notify the user in case of a failed game launch using a popup window. // Notify the user in case of a failed game launch using a popup window.
if (returnValue != 0) { if (returnValue != 0) {
LOG(LogWarning) << "...launch terminated with nonzero return value " << returnValue; LOG(LogWarning) << "Launch terminated with nonzero return value " << returnValue;
window->queueInfoPopup("ERROR LAUNCHING GAME '" + window->queueInfoPopup("ERROR LAUNCHING GAME '" +
Utils::String::toUpper(metadata.get("name")) + "' (ERROR CODE " + Utils::String::toUpper(metadata.get("name")) + "' (ERROR CODE " +
@ -1692,8 +1908,7 @@ void FileData::launchGame()
getSourceFileData()->getSystem()->getFullName()); getSourceFileData()->getSystem()->getFullName());
} }
else { else {
std::vector<std::string>& gameEndParams { std::vector<std::string>& gameEndParams {window->getGameEndEventParams()};
ViewController::getInstance()->getGameEndEventParams()};
gameEndParams.emplace_back("game-end"); gameEndParams.emplace_back("game-end");
gameEndParams.emplace_back(romPath); gameEndParams.emplace_back(romPath);
gameEndParams.emplace_back(getSourceFileData()->metadata.get("name")); gameEndParams.emplace_back(getSourceFileData()->metadata.get("name"));
@ -1737,23 +1952,27 @@ void FileData::launchGame()
gameToUpdate->mSystem->onMetaDataSavePoint(); gameToUpdate->mSystem->onMetaDataSavePoint();
} }
const std::string FileData::findEmulatorPath(std::string& command, const bool preCommand) const std::pair<std::string, FileData::findEmulatorResult> FileData::findEmulator(
std::string& command, const bool preCommand)
{ {
// Extract the emulator executable from the launch command string. There are two ways // Extract the emulator executable from the launch command string. There are two ways
// that the emulator can be defined in es_systems.xml, either using the find rules in // that the emulator can be defined in es_systems.xml, either using the find rules in
// es_find_rules.xml or via the explicit emulator binary name. In the former case, we // es_find_rules.xml or via the explicit emulator name. In the former case, we
// need to process any configured systempath and staticpath rules (and for Windows also // need to process any configured systempath and staticpath rules (and for Windows also
// winregistrypath and winregistryvalue rules), and in the latter case we simply search // winregistrypath and winregistryvalue rules), and in the latter case we simply search
// for the emulator binary in the system path. // for the emulator in the system path.
std::string emuExecutable; std::string emuExecutable;
std::string exePath; std::string exePath;
// Method 1, emulator binary is defined using find rules: // Method 1, emulator is defined using find rules:
#if defined(_WIN64) #if defined(_WIN64)
std::vector<std::string> emulatorWinRegistryPaths; std::vector<std::string> emulatorWinRegistryPaths;
std::vector<std::string> emulatorWinRegistryValues; std::vector<std::string> emulatorWinRegistryValues;
#endif
#if defined(__ANDROID__)
std::vector<std::string> emulatorAndroidPackages;
#endif #endif
std::vector<std::string> emulatorSystemPaths; std::vector<std::string> emulatorSystemPaths;
std::vector<std::string> emulatorStaticPaths; std::vector<std::string> emulatorStaticPaths;
@ -1782,6 +2001,10 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryPaths; SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryPaths;
emulatorWinRegistryValues = emulatorWinRegistryValues =
SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryValues; SystemData::sFindRules.get()->mEmulators[emulatorEntry].winRegistryValues;
#endif
#if defined(__ANDROID__)
emulatorAndroidPackages =
SystemData::sFindRules.get()->mEmulators[emulatorEntry].androidPackages;
#endif #endif
emulatorSystemPaths = SystemData::sFindRules.get()->mEmulators[emulatorEntry].systemPaths; emulatorSystemPaths = SystemData::sFindRules.get()->mEmulators[emulatorEntry].systemPaths;
@ -1793,10 +2016,13 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
if (emulatorEntry != "" && emulatorWinRegistryPaths.empty() && if (emulatorEntry != "" && emulatorWinRegistryPaths.empty() &&
emulatorWinRegistryValues.empty() && emulatorSystemPaths.empty() && emulatorWinRegistryValues.empty() && emulatorSystemPaths.empty() &&
emulatorStaticPaths.empty()) emulatorStaticPaths.empty())
#elif defined(__ANDROID__)
if (emulatorEntry != "" && emulatorAndroidPackages.empty() && emulatorSystemPaths.empty() &&
emulatorStaticPaths.empty())
#else #else
if (emulatorEntry != "" && emulatorSystemPaths.empty() && emulatorStaticPaths.empty()) if (emulatorEntry != "" && emulatorSystemPaths.empty() && emulatorStaticPaths.empty())
#endif #endif
return "NO EMULATOR RULE: " + emulatorEntry; return std::make_pair(emulatorEntry, FileData::findEmulatorResult::NO_RULES);
#if defined(_WIN64) #if defined(_WIN64)
for (std::string& path : emulatorWinRegistryPaths) { for (std::string& path : emulatorWinRegistryPaths) {
@ -1834,19 +2060,19 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
continue; continue;
} }
// That a value was found does not guarantee that the emulator binary actually exists, // That a value was found does not guarantee that the emulator actually exists, so
// so check for that as well. // check for that as well.
if (pathStatus == ERROR_SUCCESS) { if (pathStatus == ERROR_SUCCESS) {
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(registryPath)) || if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(registryPath)) ||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(registryPath))) { Utils::FileSystem::isSymlink(Utils::String::wideStringToString(registryPath))) {
LOG(LogDebug) << "FileData::findEmulatorPath(): " LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary") << (preCommand ? "Pre-command" : "Emulator")
<< " found via winregistrypath rule"; << " found via winregistrypath rule";
exePath = Utils::FileSystem::getEscapedPath( exePath = Utils::FileSystem::getEscapedPath(
Utils::String::wideStringToString(registryPath)); Utils::String::wideStringToString(registryPath));
command.replace(startPos, endPos - startPos + 1, exePath); command.replace(startPos, endPos - startPos + 1, exePath);
RegCloseKey(registryKey); RegCloseKey(registryKey);
return exePath; return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
} }
RegCloseKey(registryKey); RegCloseKey(registryKey);
@ -1906,25 +2132,47 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
if (!appendString.empty()) if (!appendString.empty())
path.append(Utils::String::stringToWideString(appendString)); path.append(Utils::String::stringToWideString(appendString));
// That a value was found does not guarantee that the emulator binary actually exists, // That a value was found does not guarantee that the emulator actually exists,
// so check for that as well. // so check for that as well.
if (pathStatus == ERROR_SUCCESS) { if (pathStatus == ERROR_SUCCESS) {
if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(path)) || if (Utils::FileSystem::isRegularFile(Utils::String::wideStringToString(path)) ||
Utils::FileSystem::isSymlink(Utils::String::wideStringToString(path))) { Utils::FileSystem::isSymlink(Utils::String::wideStringToString(path))) {
LOG(LogDebug) << "FileData::findEmulatorPath(): " LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary") << (preCommand ? "Pre-command" : "Emulator")
<< " found via winregistryvalue rule"; << " found via winregistryvalue rule";
exePath = exePath =
Utils::FileSystem::getEscapedPath(Utils::String::wideStringToString(path)); Utils::FileSystem::getEscapedPath(Utils::String::wideStringToString(path));
command.replace(startPos, endPos - startPos + 1, exePath); command.replace(startPos, endPos - startPos + 1, exePath);
RegCloseKey(registryKey); RegCloseKey(registryKey);
return exePath; return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
} }
RegCloseKey(registryKey); RegCloseKey(registryKey);
} }
#endif #endif
#if defined(__ANDROID__)
for (std::string& androidpackage : emulatorAndroidPackages) {
// If a forward slash character is present in the androidpackage entry it means an explicit
// Intent activity should be used rather than the default one. The checkEmulatorInstalled()
// Java function will check for the activity as well and if it's not found it flags the
// overall emulator entry as not found.
std::string packageName {androidpackage};
std::string activity;
size_t separatorPos {packageName.find('/')};
if (separatorPos != std::string::npos) {
activity = packageName.substr(separatorPos + 1);
packageName = packageName.substr(0, separatorPos);
}
if (Utils::Platform::Android::checkEmulatorInstalled(packageName, activity)) {
return std::make_pair(androidpackage,
FileData::findEmulatorResult::FOUND_ANDROID_PACKAGE);
}
}
#endif
for (std::string& path : emulatorSystemPaths) { for (std::string& path : emulatorSystemPaths) {
#if defined(_WIN64) #if defined(_WIN64)
std::wstring pathWide {Utils::String::stringToWideString(path)}; std::wstring pathWide {Utils::String::stringToWideString(path)};
@ -1945,30 +2193,30 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
} }
} }
if (exePath != "") { if (exePath != "") {
LOG(LogDebug) << "FileData::findEmulatorPath(): " LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary") << (preCommand ? "Pre-command" : "Emulator")
<< " found via systempath rule"; << " found via systempath rule";
exePath += "\\" + path; exePath += "\\" + path;
exePath = Utils::FileSystem::getEscapedPath(exePath); exePath = Utils::FileSystem::getEscapedPath(exePath);
command.replace(startPos, endPos - startPos + 1, exePath); command.replace(startPos, endPos - startPos + 1, exePath);
return exePath; return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
#else #else
exePath = Utils::FileSystem::getPathToBinary(path); exePath = Utils::FileSystem::getPathToBinary(path);
if (exePath != "") { if (exePath != "") {
LOG(LogDebug) << "FileData::findEmulatorPath(): " LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary") << (preCommand ? "Pre-command" : "Emulator")
<< " found via systempath rule"; << " found via systempath rule";
exePath += "/" + path; exePath += "/" + path;
command.replace(startPos, endPos - startPos + 1, exePath); command.replace(startPos, endPos - startPos + 1, exePath);
return exePath; return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
#endif #endif
} }
for (std::string& path : emulatorStaticPaths) { for (std::string& path : emulatorStaticPaths) {
// If a pipe character is present in the staticpath entry it means we should substitute // If a pipe character is present in the staticpath entry it means we should substitute
// the emulator binary with whatever is defined after the pipe character. // the emulator with whatever is defined after the pipe character.
std::string replaceCommand; std::string replaceCommand;
const size_t pipePos {path.find('|')}; const size_t pipePos {path.find('|')};
@ -1998,23 +2246,23 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
} }
if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) { if (Utils::FileSystem::isRegularFile(path) || Utils::FileSystem::isSymlink(path)) {
LOG(LogDebug) << "FileData::findEmulatorPath(): " LOG(LogDebug) << "FileData::findEmulator(): "
<< (preCommand ? "Pre-command binary" : "Emulator binary") << (preCommand ? "Pre-command" : "Emulator")
<< " found via staticpath rule"; << " found via staticpath rule";
if (replaceCommand == "") { if (replaceCommand == "") {
exePath = Utils::FileSystem::getEscapedPath(path); exePath = Utils::FileSystem::getEscapedPath(path);
} }
else { else {
LOG(LogDebug) << "FileData::findEmulatorPath(): Replacing emulator binary in " LOG(LogDebug) << "FileData::findEmulator(): Replacing emulator in "
"staticpath rule with explicitly defined command"; "staticpath rule with explicitly defined command";
exePath = replaceCommand; exePath = replaceCommand;
} }
command.replace(startPos, endPos - startPos + 1, exePath); command.replace(startPos, endPos - startPos + 1, exePath);
return exePath; return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
} }
// Method 2, exact emulator binary name: // Method 2, exact emulator name:
// If %ESPATH% is used, then expand it to the binary directory of ES-DE. // If %ESPATH% is used, then expand it to the binary directory of ES-DE.
command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath()); command = Utils::String::replace(command, "%ESPATH%", Utils::FileSystem::getExePath());
@ -2052,7 +2300,7 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
exePath = Utils::String::wideStringToString(pathBuffer.data()); exePath = Utils::String::wideStringToString(pathBuffer.data());
} }
#else #elif !defined(__ANDROID__)
if (Utils::FileSystem::isRegularFile(emuExecutable) || if (Utils::FileSystem::isRegularFile(emuExecutable) ||
Utils::FileSystem::isSymlink(emuExecutable)) { Utils::FileSystem::isSymlink(emuExecutable)) {
exePath = Utils::FileSystem::getEscapedPath(emuExecutable); exePath = Utils::FileSystem::getEscapedPath(emuExecutable);
@ -2065,7 +2313,10 @@ const std::string FileData::findEmulatorPath(std::string& command, const bool pr
} }
#endif #endif
return exePath; if (exePath.empty())
return std::make_pair("", FileData::findEmulatorResult::NOT_FOUND);
else
return std::make_pair(exePath, FileData::findEmulatorResult::FOUND_FILE);
} }
CollectionFileData::CollectionFileData(FileData* file, SystemData* system) CollectionFileData::CollectionFileData(FileData* file, SystemData* system)

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileData.h // FileData.h
// //
// Provides game file data structures and functions to access and sort this information. // Provides game file data structures and functions to access and sort this information.
@ -40,11 +40,7 @@ public:
const std::string& getName() { return metadata.get("name"); } const std::string& getName() { return metadata.get("name"); }
const std::string& getSortName(); const std::string& getSortName();
// Returns our best guess at the "real" name for this file. // Returns our best guess at the "real" name for this file.
std::string getDisplayName() const std::string getDisplayName() const { return Utils::FileSystem::getStem(mPath); }
{
const std::string& stem {Utils::FileSystem::getStem(mPath)};
return stem;
}
std::string getCleanName() const std::string getCleanName() const
{ {
return Utils::String::removeParenthesis(this->getDisplayName()); return Utils::String::removeParenthesis(this->getDisplayName());
@ -112,8 +108,8 @@ public:
bool excludeRecursively, bool excludeRecursively,
bool respectExclusions) const; bool respectExclusions) const;
void addChild(FileData* file); // Error if mType != FOLDER void addChild(FileData* file);
void removeChild(FileData* file); // Error if mType != FOLDER void removeChild(FileData* file);
virtual std::string getKey() { return getFileName(); } virtual std::string getKey() { return getFileName(); }
const bool isArcadeAsset() const; const bool isArcadeAsset() const;
@ -123,8 +119,16 @@ public:
virtual FileData* getSourceFileData() { return this; } virtual FileData* getSourceFileData() { return this; }
const std::string& getSystemName() const { return mSystemName; } const std::string& getSystemName() const { return mSystemName; }
enum class findEmulatorResult {
FOUND_FILE,
FOUND_ANDROID_PACKAGE,
NOT_FOUND,
NO_RULES
};
void launchGame(); void launchGame();
const std::string findEmulatorPath(std::string& command, const bool preCommand); const std::pair<std::string, FileData::findEmulatorResult> findEmulator(std::string& command,
const bool preCommand);
using ComparisonFunction = bool(const FileData* a, const FileData* b); using ComparisonFunction = bool(const FileData* a, const FileData* b);
struct SortType { struct SortType {
@ -167,6 +171,9 @@ private:
std::vector<FileData*> mChildrenLastPlayed; std::vector<FileData*> mChildrenLastPlayed;
std::vector<FileData*> mChildrenMostPlayed; std::vector<FileData*> mChildrenMostPlayed;
std::function<void()> mUpdateListCallback; std::function<void()> mUpdateListCallback;
static inline std::vector<std::string> sImageExtensions {".png", ".jpg"};
static inline std::vector<std::string> sVideoExtensions {".mp4", ".mkv", ".avi",
".mp4", ".wmv", ".mov"};
// The pair includes all games, and favorite games. // The pair includes all games, and favorite games.
std::pair<unsigned int, unsigned int> mGameCount; std::pair<unsigned int, unsigned int> mGameCount;
bool mOnlyFolders; bool mOnlyFolders;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileFilterIndex.cpp // FileFilterIndex.cpp
// //
// Gamelist filters. // Gamelist filters.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileFilterIndex.h // FileFilterIndex.h
// //
// Gamelist filters. // Gamelist filters.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileSorts.cpp // FileSorts.cpp
// //
// Gamelist sorting functions. // Gamelist sorting functions.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// FileSorts.h // FileSorts.h
// //
// Gamelist sorting functions. // Gamelist sorting functions.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GamelistFileParser.cpp // GamelistFileParser.cpp
// //
// Parses and updates the gamelist.xml files. // Parses and updates the gamelist.xml files.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GamelistFileParser.h // GamelistFileParser.h
// //
// Parses and updates the gamelist.xml files. // Parses and updates the gamelist.xml files.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MediaViewer.cpp // MediaViewer.cpp
// //
// Fullscreen game media viewer. // Fullscreen game media viewer.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MediaViewer.h // MediaViewer.h
// //
// Fullscreen game media viewer. // Fullscreen game media viewer.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MetaData.cpp // MetaData.cpp
// //
// Static data for default metadata values as well as functions // Static data for default metadata values as well as functions

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MetaData.h // MetaData.h
// //
// Static data for default metadata values as well as functions // Static data for default metadata values as well as functions

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MiximageGenerator.cpp // MiximageGenerator.cpp
// //
// Generates miximages from screenshots, marquees, 3D boxes/covers and physical media images. // Generates miximages from screenshots, marquees, 3D boxes/covers and physical media images.
@ -895,6 +895,17 @@ std::string MiximageGenerator::getSavePath() const
if (!Utils::FileSystem::exists(path)) if (!Utils::FileSystem::exists(path))
Utils::FileSystem::createDirectory(path); Utils::FileSystem::createDirectory(path);
#if defined(__ANDROID__)
if (!Utils::FileSystem::exists(path + ".nomedia")) {
LOG(LogInfo) << "Creating \"no media\" file \"" << path + ".nomedia"
<< "\"...";
Utils::FileSystem::createEmptyFile(path + ".nomedia");
if (!Utils::FileSystem::exists(path + ".nomedia")) {
LOG(LogWarning) << "Couldn't create file, permission problems?";
}
}
#endif
path += mGame->getSystemName() + "/miximages" + subFolders + "/"; path += mGame->getSystemName() + "/miximages" + subFolders + "/";
if (!Utils::FileSystem::exists(path)) if (!Utils::FileSystem::exists(path))

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// MiximageGenerator.h // MiximageGenerator.h
// //
// Generates miximages from screenshots, marquees, 3D boxes/covers and physical media images. // Generates miximages from screenshots, marquees, 3D boxes/covers and physical media images.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// PDFViewer.cpp // PDFViewer.cpp
// //
// Parses and renders pages using the Poppler library via the external es-pdf-convert binary. // Parses and renders pages using the Poppler library via the external es-pdf-convert binary.
@ -20,6 +20,10 @@
#include <windows.h> #include <windows.h>
#endif #endif
#if defined(__ANDROID__)
#include "ConvertPDF.h"
#endif
#define DEBUG_PDF_CONVERSION false #define DEBUG_PDF_CONVERSION false
#define KEY_REPEAT_START_DELAY 600 #define KEY_REPEAT_START_DELAY 600
@ -51,6 +55,7 @@ bool PDFViewer::startPDFViewer(FileData* game)
{ {
ViewController::getInstance()->pauseViewVideos(); ViewController::getInstance()->pauseViewVideos();
#if !defined(__ANDROID__)
#if defined(_WIN64) #if defined(_WIN64)
const std::string convertBinary {"/es-pdf-converter/es-pdf-convert.exe"}; const std::string convertBinary {"/es-pdf-converter/es-pdf-convert.exe"};
#else #else
@ -67,6 +72,7 @@ bool PDFViewer::startPDFViewer(FileData* game)
ViewController::getInstance()->startViewVideos(); ViewController::getInstance()->startViewVideos();
return false; return false;
} }
#endif // !__ANDROID__
mGame = game; mGame = game;
mManualPath = mGame->getManualPath(); mManualPath = mGame->getManualPath();
@ -298,6 +304,9 @@ bool PDFViewer::getDocumentInfo()
// Close process and thread handles. // Close process and thread handles.
CloseHandle(pi.hProcess); CloseHandle(pi.hProcess);
CloseHandle(pi.hThread); CloseHandle(pi.hThread);
#elif defined(__ANDROID__)
if (ConvertPDF::processFile(mManualPath, "-fileinfo", 0, 0, 0, commandOutput) == -1)
return false;
#else #else
FILE* commandPipe; FILE* commandPipe;
std::array<char, 512> buffer {}; std::array<char, 512> buffer {};
@ -439,6 +448,13 @@ void PDFViewer::convertPage(int pageNum)
CloseHandle(childStdoutRead); CloseHandle(childStdoutRead);
WaitForSingleObject(pi.hThread, INFINITE); WaitForSingleObject(pi.hThread, INFINITE);
WaitForSingleObject(pi.hProcess, INFINITE); WaitForSingleObject(pi.hProcess, INFINITE);
#elif (__ANDROID__)
ConvertPDF::processFile(mManualPath, "-convert", pageNum,
static_cast<int>(mPages[pageNum].width),
static_cast<int>(mPages[pageNum].height), imageData);
mPages[pageNum].imageData.insert(mPages[pageNum].imageData.end(),
std::make_move_iterator(imageData.begin()),
std::make_move_iterator(imageData.end()));
#else #else
FILE* commandPipe; FILE* commandPipe;
std::array<char, 512> buffer {}; std::array<char, 512> buffer {};
@ -461,6 +477,8 @@ void PDFViewer::convertPage(int pageNum)
#if defined(_WIN64) #if defined(_WIN64)
if (!processReturnValue || (static_cast<int>(imageDataSize) < if (!processReturnValue || (static_cast<int>(imageDataSize) <
mPages[pageNum].width * mPages[pageNum].height * 4)) { mPages[pageNum].width * mPages[pageNum].height * 4)) {
#elif defined(__ANDROID__)
if (static_cast<int>(imageDataSize) < mPages[pageNum].width * mPages[pageNum].height * 4) {
#else #else
if (returnValue != 0 || (static_cast<int>(imageDataSize) < if (returnValue != 0 || (static_cast<int>(imageDataSize) <
mPages[pageNum].width * mPages[pageNum].height * 4)) { mPages[pageNum].width * mPages[pageNum].height * 4)) {

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// PDFViewer.h // PDFViewer.h
// //
// Parses and renders pages using the Poppler library via the external es-pdf-convert binary. // Parses and renders pages using the Poppler library via the external es-pdf-convert binary.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// PlatformId.cpp // PlatformId.cpp
// //
// Index of all supported systems/platforms. // Index of all supported systems/platforms.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// PlatformId.h // PlatformId.h
// //
// Index of all supported systems/platforms. // Index of all supported systems/platforms.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// Screensaver.cpp // Screensaver.cpp
// //
// Screensaver, supporting the following types: // Screensaver, supporting the following types:
@ -464,8 +464,11 @@ void Screensaver::generateVideoList()
void Screensaver::generateCustomImageList() void Screensaver::generateCustomImageList()
{ {
std::string imageDir = Utils::FileSystem::expandHomePath( std::string imageDir {Utils::FileSystem::expandHomePath(
Settings::getInstance()->getString("ScreensaverSlideshowImageDir")); Settings::getInstance()->getString("ScreensaverSlideshowCustomDir"))};
if (imageDir.empty())
imageDir = Utils::FileSystem::getAppDataDirectory() + "/screensavers/custom_slideshow";
// This makes it possible to set the custom image directory relative to the ES-DE binary // This makes it possible to set the custom image directory relative to the ES-DE binary
// directory or the ROM directory. // directory or the ROM directory.
@ -473,19 +476,23 @@ void Screensaver::generateCustomImageList()
imageDir = Utils::String::replace(imageDir, "%ROMPATH%", FileData::getROMDirectory()); imageDir = Utils::String::replace(imageDir, "%ROMPATH%", FileData::getROMDirectory());
if (imageDir != "" && Utils::FileSystem::isDirectory(imageDir)) { if (imageDir != "" && Utils::FileSystem::isDirectory(imageDir)) {
std::string imageFilter {".jpg, .JPG, .png, .PNG"}; const std::vector<std::string> extList {".jpg", ".JPG", ".png", ".PNG", ".gif",
Utils::FileSystem::StringList dirContent = Utils::FileSystem::getDirContent( ".GIF", ".webp", ".WEBP", ".svg", ".SVG"};
imageDir, Settings::getInstance()->getBool("ScreensaverSlideshowRecurse"));
Utils::FileSystem::StringList dirContent {Utils::FileSystem::getDirContent(
imageDir, Settings::getInstance()->getBool("ScreensaverSlideshowRecurse"))};
for (auto it = dirContent.begin(); it != dirContent.end(); ++it) { for (auto it = dirContent.begin(); it != dirContent.end(); ++it) {
if (Utils::FileSystem::isRegularFile(*it)) { if (Utils::FileSystem::isRegularFile(*it)) {
if (imageFilter.find(Utils::FileSystem::getExtension(*it)) != std::string::npos) if (std::find(extList.cbegin(), extList.cend(),
Utils::FileSystem::getExtension(*it)) != extList.cend())
mImageCustomFiles.push_back(*it); mImageCustomFiles.push_back(*it);
} }
} }
} }
else { else {
LOG(LogWarning) << "Custom screensaver image directory '" << imageDir << "' does not exist"; LOG(LogWarning) << "Custom screensaver image directory \"" << imageDir
<< "\" does not exist";
} }
mCustomFilesInventory.insert(mCustomFilesInventory.begin(), mImageCustomFiles.begin(), mCustomFilesInventory.insert(mCustomFilesInventory.begin(), mImageCustomFiles.begin(),

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// Screensaver.h // Screensaver.h
// //
// Screensaver, supporting the following types: // Screensaver, supporting the following types:

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// SystemData.cpp // SystemData.cpp
// //
// Provides data structures for the game systems and populates and indexes them based // Provides data structures for the game systems and populates and indexes them based
@ -42,15 +42,20 @@ FindRules::FindRules()
void FindRules::loadFindRules() void FindRules::loadFindRules()
{ {
std::vector<std::string> paths; std::vector<std::string> paths;
std::string filePath {Utils::FileSystem::getHomePath() + "/.emulationstation/custom_systems" + std::string filePath {Utils::FileSystem::getAppDataDirectory() +
"/es_find_rules.xml"}; "/custom_systems/es_find_rules.xml"};
if (Utils::FileSystem::exists(filePath)) { if (Utils::FileSystem::exists(filePath)) {
paths.emplace_back(filePath); paths.emplace_back(filePath);
LOG(LogInfo) << "Found custom find rules configuration file"; LOG(LogInfo) << "Found custom find rules configuration file";
} }
#if defined(_WIN64) #if defined(__ANDROID__)
filePath = ResourceManager::getInstance().getResourcePath(":/systems/android/es_find_rules.xml",
false);
#elif defined(__linux__)
filePath =
ResourceManager::getInstance().getResourcePath(":/systems/linux/es_find_rules.xml", false);
#elif defined(_WIN64)
filePath = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_find_rules.xml", filePath = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_find_rules.xml",
false); false);
#elif defined(__APPLE__) #elif defined(__APPLE__)
@ -61,12 +66,12 @@ void FindRules::loadFindRules()
ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml", false); ResourceManager::getInstance().getResourcePath(":/systems/unix/es_find_rules.xml", false);
#endif #endif
if (filePath == "" && paths.empty()) { if (filePath.empty() && paths.empty()) {
LOG(LogWarning) << "No find rules configuration file found"; LOG(LogWarning) << "No find rules configuration file found";
return; return;
} }
if (filePath != "") if (!filePath.empty())
paths.emplace_back(filePath); paths.emplace_back(filePath);
for (auto& path : paths) { for (auto& path : paths) {
@ -84,7 +89,6 @@ void FindRules::loadFindRules()
#else #else
const pugi::xml_parse_result& res {doc.load_file(path.c_str())}; const pugi::xml_parse_result& res {doc.load_file(path.c_str())};
#endif #endif
if (!res) { if (!res) {
LOG(LogError) << "Couldn't parse es_find_rules.xml: " << res.description(); LOG(LogError) << "Couldn't parse es_find_rules.xml: " << res.description();
continue; continue;
@ -126,6 +130,9 @@ void FindRules::loadFindRules()
#if defined(_WIN64) #if defined(_WIN64)
if (ruleType != "winregistrypath" && ruleType != "winregistryvalue" && if (ruleType != "winregistrypath" && ruleType != "winregistryvalue" &&
ruleType != "systempath" && ruleType != "staticpath") { ruleType != "systempath" && ruleType != "staticpath") {
#elif defined(__ANDROID__)
if (ruleType != "androidpackage" && ruleType != "systempath" &&
ruleType != "staticpath") {
#else #else
if (ruleType != "systempath" && ruleType != "staticpath") { if (ruleType != "systempath" && ruleType != "staticpath") {
#endif #endif
@ -145,6 +152,9 @@ void FindRules::loadFindRules()
emulatorRules.winRegistryPaths.emplace_back(entryValue); emulatorRules.winRegistryPaths.emplace_back(entryValue);
else if (ruleType == "winregistryvalue") else if (ruleType == "winregistryvalue")
emulatorRules.winRegistryValues.emplace_back(entryValue); emulatorRules.winRegistryValues.emplace_back(entryValue);
#elif defined(__ANDROID__)
else if (ruleType == "androidpackage")
emulatorRules.androidPackages.emplace_back(entryValue);
#endif #endif
} }
} }
@ -154,6 +164,8 @@ void FindRules::loadFindRules()
#if defined(_WIN64) #if defined(_WIN64)
emulatorRules.winRegistryPaths.clear(); emulatorRules.winRegistryPaths.clear();
emulatorRules.winRegistryValues.clear(); emulatorRules.winRegistryValues.clear();
#elif defined(__ANDROID__)
emulatorRules.androidPackages.clear();
#endif #endif
} }
@ -838,9 +850,8 @@ bool SystemData::loadConfig()
void SystemData::loadSortingConfig() void SystemData::loadSortingConfig()
{ {
const std::string sortSetting {Settings::getInstance()->getString("SystemsSorting")}; const std::string sortSetting {Settings::getInstance()->getString("SystemsSorting")};
const std::string customFilePath {Utils::FileSystem::getHomePath() + const std::string customFilePath {Utils::FileSystem::getAppDataDirectory() +
"/.emulationstation/custom_systems" + "/custom_systems/es_systems_sorting.xml"};
"/es_systems_sorting.xml"};
const bool customFileExists {Utils::FileSystem::exists(customFilePath)}; const bool customFileExists {Utils::FileSystem::exists(customFilePath)};
std::string path; std::string path;
@ -875,7 +886,7 @@ void SystemData::loadSortingConfig()
path = customFilePath; path = customFilePath;
} }
if (path == "") { if (path.empty()) {
LOG(LogDebug) << "No systems sorting file loaded"; LOG(LogDebug) << "No systems sorting file loaded";
return; return;
} }
@ -947,8 +958,8 @@ std::vector<std::string> SystemData::getConfigPath()
{ {
std::vector<std::string> paths; std::vector<std::string> paths;
const std::string& customSystemsDirectory {Utils::FileSystem::getHomePath() + const std::string customSystemsDirectory {Utils::FileSystem::getAppDataDirectory() +
"/.emulationstation/custom_systems"}; "/custom_systems"};
if (!Utils::FileSystem::exists(customSystemsDirectory)) { if (!Utils::FileSystem::exists(customSystemsDirectory)) {
LOG(LogInfo) << "Creating custom systems directory \"" << customSystemsDirectory << "\"..."; LOG(LogInfo) << "Creating custom systems directory \"" << customSystemsDirectory << "\"...";
@ -965,7 +976,11 @@ std::vector<std::string> SystemData::getConfigPath()
paths.emplace_back(path); paths.emplace_back(path);
} }
#if defined(_WIN64) #if defined(__ANDROID__)
path = ResourceManager::getInstance().getResourcePath(":/systems/android/es_systems.xml", true);
#elif defined(__linux__)
path = ResourceManager::getInstance().getResourcePath(":/systems/linux/es_systems.xml", true);
#elif defined(_WIN64)
path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true); path = ResourceManager::getInstance().getResourcePath(":/systems/windows/es_systems.xml", true);
#elif defined(__APPLE__) #elif defined(__APPLE__)
path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true); path = ResourceManager::getInstance().getResourcePath(":/systems/macos/es_systems.xml", true);
@ -1107,6 +1122,31 @@ bool SystemData::createSystemDirectories()
return (std::isspace(character) || character == ','); return (std::isspace(character) || character == ',');
}) != platform.cend()}; }) != platform.cend()};
if (name.empty()) {
LOG(LogError)
<< "A system in the es_systems.xml file has no name defined, skipping entry";
continue;
}
else if (fullname.empty() || path.empty() || extensions.empty() || commands.empty()) {
LOG(LogError) << "System \"" << name
<< "\" is missing the fullname, path, "
"extension, or command tag, skipping entry";
continue;
}
if (commands.size() == 1 &&
Utils::String::toLower(commands.front()).find("placeholder") != std::string::npos) {
if (Settings::getInstance()->getBool("CreatePlaceholderSystemDirectories")) {
LOG(LogInfo) << "System \"" << name
<< "\" is a placeholder but creating directory anyway as "
"CreatePlaceholderSystemDirectories is set to true";
}
else {
LOG(LogInfo) << "System \"" << name << "\" is a placeholder, skipping entry";
continue;
}
}
themeFolder = system.child("theme").text().as_string(name.c_str()); themeFolder = system.child("theme").text().as_string(name.c_str());
// Check that the %ROMPATH% variable is actually used for the path element. // Check that the %ROMPATH% variable is actually used for the path element.
@ -1188,7 +1228,10 @@ bool SystemData::createSystemDirectories()
} }
systemInfoFile << "Platform" << (multiplePlatforms ? "s" : "") systemInfoFile << "Platform" << (multiplePlatforms ? "s" : "")
<< " (for scraping):" << std::endl; << " (for scraping):" << std::endl;
systemInfoFile << platform << std::endl << std::endl; if (platform.empty())
systemInfoFile << "None defined" << std::endl << std::endl;
else
systemInfoFile << platform << std::endl << std::endl;
systemInfoFile << "Theme folder:" << std::endl; systemInfoFile << "Theme folder:" << std::endl;
systemInfoFile << themeFolder << std::endl; systemInfoFile << themeFolder << std::endl;
systemInfoFile.close(); systemInfoFile.close();
@ -1296,8 +1339,8 @@ SystemData* SystemData::getPrev() const
std::string SystemData::getGamelistPath(bool forWrite) const std::string SystemData::getGamelistPath(bool forWrite) const
{ {
std::string filePath {mRootFolder->getPath() + "/gamelist.xml"}; std::string filePath {mRootFolder->getPath() + "/gamelist.xml"};
const std::string gamelistPath {Utils::FileSystem::getHomePath() + const std::string gamelistPath {Utils::FileSystem::getAppDataDirectory() + "/gamelists/" +
"/.emulationstation/gamelists/" + mName}; mName};
if (Utils::FileSystem::exists(filePath)) { if (Utils::FileSystem::exists(filePath)) {
if (Settings::getInstance()->getBool("LegacyGamelistFileLocation")) { if (Settings::getInstance()->getBool("LegacyGamelistFileLocation")) {
@ -1307,8 +1350,7 @@ std::string SystemData::getGamelistPath(bool forWrite) const
#if defined(_WIN64) #if defined(_WIN64)
LOG(LogWarning) << "Found a gamelist.xml file in \"" LOG(LogWarning) << "Found a gamelist.xml file in \""
<< Utils::String::replace(mRootFolder->getPath(), "/", "\\") << Utils::String::replace(mRootFolder->getPath(), "/", "\\")
<< "\\\" which will not get loaded, move it to \"" << "\\\" which will not get loaded, move it to \"" << gamelistPath
<< Utils::String::replace(gamelistPath, "/", "\\")
<< "\\\" or otherwise delete it"; << "\\\" or otherwise delete it";
#else #else
LOG(LogWarning) << "Found a gamelist.xml file in \"" << mRootFolder->getPath() LOG(LogWarning) << "Found a gamelist.xml file in \"" << mRootFolder->getPath()

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// SystemData.h // SystemData.h
// //
// Provides data structures for the game systems and populates and indexes them based // Provides data structures for the game systems and populates and indexes them based
@ -44,6 +44,8 @@ private:
#if defined(_WIN64) #if defined(_WIN64)
std::vector<std::string> winRegistryPaths; std::vector<std::string> winRegistryPaths;
std::vector<std::string> winRegistryValues; std::vector<std::string> winRegistryValues;
#elif defined(__ANDROID__)
std::vector<std::string> androidPackages;
#endif #endif
std::vector<std::string> systemPaths; std::vector<std::string> systemPaths;
std::vector<std::string> staticPaths; std::vector<std::string> staticPaths;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// UIModeController.cpp // UIModeController.cpp
// //
// Handling of application user interface modes (full, kiosk and kid). // Handling of application user interface modes (full, kiosk and kid).
@ -127,13 +127,13 @@ std::string UIModeController::getFormattedPassKeyStr()
std::string symbolX; std::string symbolX;
std::string symbolY; std::string symbolY;
if (controllerType == "snes") { if (Settings::getInstance()->getBool("InputSwapButtons") || controllerType == "snes") {
symbolA = "B"; symbolA = "B";
symbolB = "A"; symbolB = "A";
symbolX = "Y"; symbolX = "Y";
symbolY = "X"; symbolY = "X";
} }
else if (controllerType == "ps4" || controllerType == "ps5") { else if (controllerType == "ps123" || controllerType == "ps4" || controllerType == "ps5") {
#if defined(_MSC_VER) // MSVC compiler. #if defined(_MSC_VER) // MSVC compiler.
// These symbols are far from perfect but you can at least understand what // These symbols are far from perfect but you can at least understand what
// they are supposed to depict. // they are supposed to depict.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// UIModeController.h // UIModeController.h
// //
// Handling of application user interface modes (full, kiosk and kid). // Handling of application user interface modes (full, kiosk and kid).

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// VolumeControl.cpp // VolumeControl.cpp
// //
// Controls system audio volume. // Controls system audio volume.
@ -15,14 +15,14 @@
#include <cmath> #include <cmath>
#endif #endif
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
std::string VolumeControl::mixerName = "Master"; std::string VolumeControl::mixerName = "Master";
std::string VolumeControl::mixerCard = "default"; std::string VolumeControl::mixerCard = "default";
#endif #endif
VolumeControl::VolumeControl() VolumeControl::VolumeControl()
// clang-format off // clang-format off
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
: mixerIndex {0} : mixerIndex {0}
, mixerHandle {nullptr} , mixerHandle {nullptr}
, mixerElem {nullptr} , mixerElem {nullptr}
@ -39,7 +39,7 @@ VolumeControl::VolumeControl()
VolumeControl::~VolumeControl() VolumeControl::~VolumeControl()
{ {
deinit(); deinit();
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
snd_config_update_free_global(); snd_config_update_free_global();
#endif #endif
} }
@ -48,7 +48,7 @@ void VolumeControl::init()
{ {
// Initialize audio mixer interface. // Initialize audio mixer interface.
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
// Try to open mixer device. // Try to open mixer device.
if (mixerHandle == nullptr) { if (mixerHandle == nullptr) {
snd_mixer_selem_id_alloca(&mixerSelemId); snd_mixer_selem_id_alloca(&mixerSelemId);
@ -139,7 +139,7 @@ void VolumeControl::deinit()
{ {
// Deinitialize audio mixer interface. // Deinitialize audio mixer interface.
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
if (mixerHandle != nullptr) { if (mixerHandle != nullptr) {
snd_mixer_detach(mixerHandle, mixerCard.c_str()); snd_mixer_detach(mixerHandle, mixerCard.c_str());
snd_mixer_free(mixerHandle); snd_mixer_free(mixerHandle);
@ -160,7 +160,7 @@ int VolumeControl::getVolume() const
{ {
int volume = 0; int volume = 0;
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
if (mixerElem != nullptr) { if (mixerElem != nullptr) {
// Get volume range. // Get volume range.
long minVolume; long minVolume;
@ -204,7 +204,7 @@ void VolumeControl::setVolume(int volume)
{ {
volume = glm::clamp(volume, 0, 100); volume = glm::clamp(volume, 0, 100);
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
if (mixerElem != nullptr) { if (mixerElem != nullptr) {
// Get volume range. // Get volume range.
long minVolume; long minVolume;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// VolumeControl.h // VolumeControl.h
// //
// Controls system audio volume. // Controls system audio volume.
@ -11,7 +11,7 @@
#include <memory> #include <memory>
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
#include <alsa/asoundlib.h> #include <alsa/asoundlib.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
@ -33,7 +33,7 @@ public:
int getVolume() const; int getVolume() const;
void setVolume(int volume); void setVolume(int volume);
#if defined(__linux__) #if defined(__linux__) && !defined(__ANDROID__)
static std::string mixerName; static std::string mixerName;
static std::string mixerCard; static std::string mixerCard;
int mixerIndex; int mixerIndex;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiAlternativeEmulators.cpp // GuiAlternativeEmulators.cpp
// //
// User interface to select between alternative emulators per system // User interface to select between alternative emulators per system

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiAlternativeEmulators.h // GuiAlternativeEmulators.h
// //
// User interface to select between alternative emulators per system // User interface to select between alternative emulators per system

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiApplicationUpdater.cpp // GuiApplicationUpdater.cpp
// //
// Installs application updates. // Installs application updates.
@ -9,7 +9,7 @@
#include "guis/GuiApplicationUpdater.h" #include "guis/GuiApplicationUpdater.h"
#include "EmulationStation.h" #include "ApplicationVersion.h"
#include "guis/GuiTextEditKeyboardPopup.h" #include "guis/GuiTextEditKeyboardPopup.h"
#include "guis/GuiTextEditPopup.h" #include "guis/GuiTextEditPopup.h"
#include "utils/PlatformUtil.h" #include "utils/PlatformUtil.h"

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiApplicationUpdater.h // GuiApplicationUpdater.h
// //
// Installs application updates. // Installs application updates.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiCollectionSystemsOptions.cpp // GuiCollectionSystemsOptions.cpp
// //
// User interface for the game collection settings. // User interface for the game collection settings.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiCollectionSystemsOptions.h // GuiCollectionSystemsOptions.h
// //
// User interface for the game collection settings. // User interface for the game collection settings.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiGamelistFilter.cpp // GuiGamelistFilter.cpp
// //
// User interface for the gamelist filters. // User interface for the gamelist filters.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiGamelistFilter.h // GuiGamelistFilter.h
// //
// User interface for the gamelist filters. // User interface for the gamelist filters.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiGamelistOptions.cpp // GuiGamelistOptions.cpp
// //
// Gamelist options menu for the 'Jump to...' quick selector, // Gamelist options menu for the 'Jump to...' quick selector,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiGamelistOptions.h // GuiGamelistOptions.h
// //
// Gamelist options menu for the 'Jump to...' quick selector, // Gamelist options menu for the 'Jump to...' quick selector,

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiLaunchScreen.cpp // GuiLaunchScreen.cpp
// //
// Screen shown when launching a game. // Screen shown when launching a game.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiLaunchScreen.h // GuiLaunchScreen.h
// //
// Screen shown when launching a game. // Screen shown when launching a game.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMediaViewerOptions.cpp // GuiMediaViewerOptions.cpp
// //
// User interface for the media viewer options. // User interface for the media viewer options.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMediaViewerOptions.h // GuiMediaViewerOptions.h
// //
// User interface for the media viewer options. // User interface for the media viewer options.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMenu.cpp // GuiMenu.cpp
// //
// Main menu. // Main menu.
@ -14,8 +14,8 @@
#include <winsock2.h> #include <winsock2.h>
#endif #endif
#include "ApplicationVersion.h"
#include "CollectionSystemsManager.h" #include "CollectionSystemsManager.h"
#include "EmulationStation.h"
#include "FileFilterIndex.h" #include "FileFilterIndex.h"
#include "FileSorts.h" #include "FileSorts.h"
#include "Scripting.h" #include "Scripting.h"
@ -38,6 +38,10 @@
#include "guis/GuiThemeDownloader.h" #include "guis/GuiThemeDownloader.h"
#include "utils/PlatformUtil.h" #include "utils/PlatformUtil.h"
#if defined(__ANDROID__)
#include "InputOverlay.h"
#endif
#include <SDL2/SDL_events.h> #include <SDL2/SDL_events.h>
#include <algorithm> #include <algorithm>
@ -164,12 +168,12 @@ void GuiMenu::openUIOptions()
Scripting::fireEvent("theme-changed", theme->getSelected(), Scripting::fireEvent("theme-changed", theme->getSelected(),
Settings::getInstance()->getString("Theme")); Settings::getInstance()->getString("Theme"));
// Handle the situation where the previously selected theme has been deleted // Handle the situation where the previously selected theme has been deleted
// using the theme downloader. In this case attempt to fall back to slate-es-de // using the theme downloader. In this case attempt to fall back to linear-es-de
// and if this theme doesn't exist then select the first available one. // and if this theme doesn't exist then select the first available one.
auto themes = ThemeData::getThemes(); auto themes = ThemeData::getThemes();
if (themes.find(theme->getSelected()) == themes.end()) { if (themes.find(theme->getSelected()) == themes.end()) {
if (themes.find("slate-es-de") != themes.end()) if (themes.find("linear-es-de") != themes.end())
Settings::getInstance()->setString("Theme", "slate-es-de"); Settings::getInstance()->setString("Theme", "linear-es-de");
else else
Settings::getInstance()->setString("Theme", themes.begin()->first); Settings::getInstance()->setString("Theme", themes.begin()->first);
} }
@ -288,6 +292,47 @@ void GuiMenu::openUIOptions()
themeColorSchemesFunc(Settings::getInstance()->getString("Theme"), themeColorSchemesFunc(Settings::getInstance()->getString("Theme"),
Settings::getInstance()->getString("ThemeColorScheme")); Settings::getInstance()->getString("ThemeColorScheme"));
// Theme font sizes.
auto themeFontSize = std::make_shared<OptionListComponent<std::string>>(
getHelpStyle(), "THEME FONT SIZE", false);
s->addWithLabel("THEME FONT SIZE", themeFontSize);
s->addSaveFunc([themeFontSize, s] {
if (themeFontSize->getSelected() != Settings::getInstance()->getString("ThemeFontSize")) {
Settings::getInstance()->setString("ThemeFontSize", themeFontSize->getSelected());
s->setNeedsSaving();
s->setNeedsReloading();
s->setInvalidateCachedBackground();
}
});
auto themeFontSizeFunc = [=](const std::string& selectedTheme,
const std::string& selectedFontSize) {
std::map<std::string, ThemeData::Theme, ThemeData::StringComparator>::const_iterator
currentSet {themes.find(selectedTheme)};
if (currentSet == themes.cend())
return;
// We need to recreate the OptionListComponent entries.
themeFontSize->clearEntries();
if (currentSet->second.capabilities.fontSizes.size() > 0) {
for (auto& fontSize : currentSet->second.capabilities.fontSizes)
themeFontSize->add(ThemeData::getFontSizeLabel(fontSize), fontSize,
fontSize == selectedFontSize);
if (themeFontSize->getSelectedObjects().size() == 0)
themeFontSize->selectEntry(0);
}
else {
themeFontSize->add("None defined", "none", true);
themeFontSize->setEnabled(false);
themeFontSize->setOpacity(DISABLED_OPACITY);
themeFontSize->getParent()
->getChild(themeFontSize->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
}
};
themeFontSizeFunc(Settings::getInstance()->getString("Theme"),
Settings::getInstance()->getString("ThemeFontSize"));
// Theme aspect ratios. // Theme aspect ratios.
auto themeAspectRatio = std::make_shared<OptionListComponent<std::string>>( auto themeAspectRatio = std::make_shared<OptionListComponent<std::string>>(
getHelpStyle(), "THEME ASPECT RATIO", false); getHelpStyle(), "THEME ASPECT RATIO", false);
@ -845,6 +890,12 @@ void GuiMenu::openUIOptions()
Settings::getInstance()->setBool("VirtualKeyboard", virtualKeyboard->getState()); Settings::getInstance()->setBool("VirtualKeyboard", virtualKeyboard->getState());
s->setNeedsSaving(); s->setNeedsSaving();
s->setInvalidateCachedBackground(); s->setInvalidateCachedBackground();
#if defined(__ANDROID__)
if (Settings::getInstance()->getBool("VirtualKeyboard"))
SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "0");
else
SDL_SetHint(SDL_HINT_ENABLE_SCREEN_KEYBOARD, "1");
#endif
} }
}); });
@ -891,6 +942,7 @@ void GuiMenu::openUIOptions()
if (!firstRun) { if (!firstRun) {
themeVariantsFunc(themeName, themeVariant->getSelected()); themeVariantsFunc(themeName, themeVariant->getSelected());
themeColorSchemesFunc(themeName, themeColorScheme->getSelected()); themeColorSchemesFunc(themeName, themeColorScheme->getSelected());
themeFontSizeFunc(themeName, themeFontSize->getSelected());
themeAspectRatiosFunc(themeName, themeAspectRatio->getSelected()); themeAspectRatiosFunc(themeName, themeAspectRatio->getSelected());
themeTransitionsFunc(themeName, themeTransitions->getSelected()); themeTransitionsFunc(themeName, themeTransitions->getSelected());
} }
@ -927,6 +979,20 @@ void GuiMenu::openUIOptions()
->getChild(themeColorScheme->getChildIndex() - 1) ->getChild(themeColorScheme->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY); ->setOpacity(DISABLED_OPACITY);
} }
if (selectedTheme->second.capabilities.fontSizes.size() > 0) {
themeFontSize->setEnabled(true);
themeFontSize->setOpacity(1.0f);
themeFontSize->getParent()
->getChild(themeFontSize->getChildIndex() - 1)
->setOpacity(1.0f);
}
else {
themeFontSize->setEnabled(false);
themeFontSize->setOpacity(DISABLED_OPACITY);
themeFontSize->getParent()
->getChild(themeFontSize->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
}
if (selectedTheme->second.capabilities.aspectRatios.size() > 0) { if (selectedTheme->second.capabilities.aspectRatios.size() > 0) {
themeAspectRatio->setEnabled(true); themeAspectRatio->setEnabled(true);
themeAspectRatio->setOpacity(1.0f); themeAspectRatio->setOpacity(1.0f);
@ -954,9 +1020,9 @@ void GuiMenu::openSoundOptions()
{ {
auto s = new GuiSettings("SOUND SETTINGS"); auto s = new GuiSettings("SOUND SETTINGS");
// TODO: Hide the volume slider on macOS and BSD Unix until the volume control logic has been // TODO: Implement system volume support for macOS and Android.
// implemented for these operating systems. #if !defined(__APPLE__) && !defined(__ANDROID__) && !defined(__FreeBSD__) && \
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined(__NetBSD__) !defined(__OpenBSD__) && !defined(__NetBSD__)
// System volume. // System volume.
// The reason to create the VolumeControl object every time instead of making it a singleton // The reason to create the VolumeControl object every time instead of making it a singleton
// is that this is the easiest way to detect new default audio devices or changes to the // is that this is the easiest way to detect new default audio devices or changes to the
@ -1090,6 +1156,166 @@ void GuiMenu::openInputDeviceOptions()
} }
}); });
#if defined(__ANDROID__)
// Touch overlay size.
auto touchOverlaySize = std::make_shared<OptionListComponent<std::string>>(
getHelpStyle(), "TOUCH OVERLAY SIZE", false);
std::string selectedOverlaySize {Settings::getInstance()->getString("InputTouchOverlaySize")};
touchOverlaySize->add("MEDIUM", "medium", selectedOverlaySize == "medium");
touchOverlaySize->add("LARGE", "large", selectedOverlaySize == "large");
touchOverlaySize->add("SMALL", "small", selectedOverlaySize == "small");
touchOverlaySize->add("EXTRA SMALL", "x-small", selectedOverlaySize == "x-small");
// If there are no objects returned, then there must be a manually modified entry in the
// configuration file. Simply set the overlay size to "medium" in this case.
if (touchOverlaySize->getSelectedObjects().size() == 0)
touchOverlaySize->selectEntry(0);
s->addWithLabel("TOUCH OVERLAY SIZE", touchOverlaySize);
s->addSaveFunc([touchOverlaySize, s] {
if (touchOverlaySize->getSelected() !=
Settings::getInstance()->getString("InputTouchOverlaySize")) {
Settings::getInstance()->setString("InputTouchOverlaySize",
touchOverlaySize->getSelected());
s->setNeedsSaving();
InputOverlay::getInstance().createButtons();
}
});
// Touch overlay opacity.
auto touchOverlayOpacity = std::make_shared<OptionListComponent<std::string>>(
getHelpStyle(), "TOUCH OVERLAY OPACITY", false);
std::string selectedOverlayOpacity {
Settings::getInstance()->getString("InputTouchOverlayOpacity")};
touchOverlayOpacity->add("NORMAL", "normal", selectedOverlayOpacity == "normal");
touchOverlayOpacity->add("LOW", "low", selectedOverlayOpacity == "low");
touchOverlayOpacity->add("VERY LOW", "verylow", selectedOverlayOpacity == "verylow");
// If there are no objects returned, then there must be a manually modified entry in the
// configuration file. Simply set the overlay opacity to "normal" in this case.
if (touchOverlayOpacity->getSelectedObjects().size() == 0)
touchOverlayOpacity->selectEntry(0);
s->addWithLabel("TOUCH OVERLAY OPACITY", touchOverlayOpacity);
s->addSaveFunc([touchOverlayOpacity, s] {
if (touchOverlayOpacity->getSelected() !=
Settings::getInstance()->getString("InputTouchOverlayOpacity")) {
Settings::getInstance()->setString("InputTouchOverlayOpacity",
touchOverlayOpacity->getSelected());
s->setNeedsSaving();
InputOverlay::getInstance().createButtons();
}
});
// Touch overlay fade-out timer.
auto touchOverlayFadeTime = std::make_shared<SliderComponent>(0.0f, 20.0f, 1.0f, "s");
touchOverlayFadeTime->setValue(
static_cast<float>(Settings::getInstance()->getInt("InputTouchOverlayFadeTime")));
s->addWithLabel("TOUCH OVERLAY FADE-OUT TIME", touchOverlayFadeTime);
s->addSaveFunc([touchOverlayFadeTime, s] {
if (touchOverlayFadeTime->getValue() !=
static_cast<float>(Settings::getInstance()->getInt("InputTouchOverlayFadeTime"))) {
Settings::getInstance()->setInt("InputTouchOverlayFadeTime",
static_cast<int>(touchOverlayFadeTime->getValue()));
InputOverlay::getInstance().resetFadeTimer();
s->setNeedsSaving();
}
});
// Whether to enable the touch overlay.
auto inputTouchOverlay = std::make_shared<SwitchComponent>();
inputTouchOverlay->setState(Settings::getInstance()->getBool("InputTouchOverlay"));
s->addWithLabel("ENABLE TOUCH OVERLAY", inputTouchOverlay);
s->addSaveFunc([inputTouchOverlay, s] {
if (Settings::getInstance()->getBool("InputTouchOverlay") !=
inputTouchOverlay->getState()) {
Settings::getInstance()->setBool("InputTouchOverlay", inputTouchOverlay->getState());
if (Settings::getInstance()->getBool("InputTouchOverlay"))
InputOverlay::getInstance().createButtons();
else
InputOverlay::getInstance().clearButtons();
s->setNeedsSaving();
}
});
if (!Settings::getInstance()->getBool("InputTouchOverlay")) {
touchOverlaySize->setEnabled(false);
touchOverlaySize->setOpacity(DISABLED_OPACITY);
touchOverlaySize->getParent()
->getChild(touchOverlaySize->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
touchOverlayOpacity->setEnabled(false);
touchOverlayOpacity->setOpacity(DISABLED_OPACITY);
touchOverlayOpacity->getParent()
->getChild(touchOverlayOpacity->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
touchOverlayFadeTime->setEnabled(false);
touchOverlayFadeTime->setOpacity(DISABLED_OPACITY);
touchOverlayFadeTime->getParent()
->getChild(touchOverlayFadeTime->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
}
auto inputTouchOverlayCallback = [this, inputTouchOverlay, touchOverlaySize,
touchOverlayOpacity, touchOverlayFadeTime]() {
if (!inputTouchOverlay->getState()) {
const std::string message {
"DON'T DISABLE THE TOUCH OVERLAY UNLESS YOU ARE USING A CONTROLLER OR YOU WILL "
"LOCK YOURSELF OUT OF THE APP. IF THIS HAPPENS YOU WILL NEED TO TEMPORARILY "
"PLUG IN A CONTROLLER OR A KEYBOARD TO ENABLE THIS SETTING AGAIN, OR YOU "
"COULD CLEAR THE ES-DE STORAGE IN THE ANDROID APP SETTINGS TO FORCE THE "
"CONFIGURATOR TO RUN ON NEXT STARTUP"};
Window* window {mWindow};
window->pushGui(
new GuiMsgBox(getHelpStyle(), message, "OK", nullptr, "", nullptr, "", nullptr,
nullptr, true, true,
(mRenderer->getIsVerticalOrientation() ?
0.84f :
0.54f * (1.778f / mRenderer->getScreenAspectRatio()))));
}
if (touchOverlaySize->getEnabled()) {
touchOverlaySize->setEnabled(false);
touchOverlaySize->setOpacity(DISABLED_OPACITY);
touchOverlaySize->getParent()
->getChild(touchOverlaySize->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
touchOverlayOpacity->setEnabled(false);
touchOverlayOpacity->setOpacity(DISABLED_OPACITY);
touchOverlayOpacity->getParent()
->getChild(touchOverlayOpacity->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
touchOverlayFadeTime->setEnabled(false);
touchOverlayFadeTime->setOpacity(DISABLED_OPACITY);
touchOverlayFadeTime->getParent()
->getChild(touchOverlayFadeTime->getChildIndex() - 1)
->setOpacity(DISABLED_OPACITY);
}
else {
touchOverlaySize->setEnabled(true);
touchOverlaySize->setOpacity(1.0f);
touchOverlaySize->getParent()
->getChild(touchOverlaySize->getChildIndex() - 1)
->setOpacity(1.0f);
touchOverlayOpacity->setEnabled(true);
touchOverlayOpacity->setOpacity(1.0f);
touchOverlayOpacity->getParent()
->getChild(touchOverlayOpacity->getChildIndex() - 1)
->setOpacity(1.0f);
touchOverlayFadeTime->setEnabled(true);
touchOverlayFadeTime->setOpacity(1.0f);
touchOverlayFadeTime->getParent()
->getChild(touchOverlayFadeTime->getChildIndex() - 1)
->setOpacity(1.0f);
}
};
inputTouchOverlay->setCallback(inputTouchOverlayCallback);
#endif
// Whether to only accept input from the first controller. // Whether to only accept input from the first controller.
auto inputOnlyFirstController = std::make_shared<SwitchComponent>(); auto inputOnlyFirstController = std::make_shared<SwitchComponent>();
inputOnlyFirstController->setState( inputOnlyFirstController->setState(
@ -1104,6 +1330,17 @@ void GuiMenu::openInputDeviceOptions()
} }
}); });
// Whether to swap the A/B and X/Y buttons.
auto inputSwapButtons = std::make_shared<SwitchComponent>();
inputSwapButtons->setState(Settings::getInstance()->getBool("InputSwapButtons"));
s->addWithLabel("SWAP THE A/B AND X/Y BUTTONS", inputSwapButtons);
s->addSaveFunc([inputSwapButtons, s] {
if (Settings::getInstance()->getBool("InputSwapButtons") != inputSwapButtons->getState()) {
Settings::getInstance()->setBool("InputSwapButtons", inputSwapButtons->getState());
s->setNeedsSaving();
}
});
// Whether to ignore keyboard input (except the quit shortcut). // Whether to ignore keyboard input (except the quit shortcut).
auto inputIgnoreKeyboard = std::make_shared<SwitchComponent>(); auto inputIgnoreKeyboard = std::make_shared<SwitchComponent>();
inputIgnoreKeyboard->setState(Settings::getInstance()->getBool("InputIgnoreKeyboard")); inputIgnoreKeyboard->setState(Settings::getInstance()->getBool("InputIgnoreKeyboard"));
@ -1185,7 +1422,8 @@ void GuiMenu::openOtherOptions()
rowMediaDir.addElement(bracketMediaDirectory, false); rowMediaDir.addElement(bracketMediaDirectory, false);
std::string titleMediaDir {"ENTER GAME MEDIA DIRECTORY"}; std::string titleMediaDir {"ENTER GAME MEDIA DIRECTORY"};
std::string mediaDirectoryStaticText {"Default directory:"}; std::string mediaDirectoryStaticText {"Default directory:"};
std::string defaultDirectoryText {"~/.emulationstation/downloaded_media/"}; std::string defaultDirectoryText {Utils::FileSystem::getAppDataDirectory() +
"/downloaded_media"};
std::string initValueMediaDir {Settings::getInstance()->getString("MediaDirectory")}; std::string initValueMediaDir {Settings::getInstance()->getString("MediaDirectory")};
bool multiLineMediaDir {false}; bool multiLineMediaDir {false};
auto updateValMediaDir = [this](const std::string& newVal) { auto updateValMediaDir = [this](const std::string& newVal) {
@ -1417,6 +1655,7 @@ void GuiMenu::openOtherOptions()
}); });
#endif #endif
#if !defined(__ANDROID__)
// Run ES in the background when a game has been launched. // Run ES in the background when a game has been launched.
auto runInBackground = std::make_shared<SwitchComponent>(); auto runInBackground = std::make_shared<SwitchComponent>();
runInBackground->setState(Settings::getInstance()->getBool("RunInBackground")); runInBackground->setState(Settings::getInstance()->getBool("RunInBackground"));
@ -1427,6 +1666,7 @@ void GuiMenu::openOtherOptions()
s->setNeedsSaving(); s->setNeedsSaving();
} }
}); });
#endif
#if defined(VIDEO_HW_DECODING) #if defined(VIDEO_HW_DECODING)
// Whether to enable hardware decoding for the FFmpeg video player. // Whether to enable hardware decoding for the FFmpeg video player.
@ -1538,7 +1778,7 @@ void GuiMenu::openOtherOptions()
} }
}); });
#if defined(__unix__) #if defined(__unix__) && !defined(__ANDROID__)
// Whether to disable desktop composition. // Whether to disable desktop composition.
auto disableComposition = std::make_shared<SwitchComponent>(); auto disableComposition = std::make_shared<SwitchComponent>();
disableComposition->setState(Settings::getInstance()->getBool("DisableComposition")); disableComposition->setState(Settings::getInstance()->getBool("DisableComposition"));
@ -1612,7 +1852,7 @@ void GuiMenu::openOtherOptions()
// macOS requires root privileges to reboot and power off so it doesn't make much // macOS requires root privileges to reboot and power off so it doesn't make much
// sense to enable this setting and menu entry for that operating system. // sense to enable this setting and menu entry for that operating system.
#if !defined(__APPLE__) #if !defined(__APPLE__) && !defined(__ANDROID__)
// Whether to show the quit menu with the options to reboot and shutdown the computer. // Whether to show the quit menu with the options to reboot and shutdown the computer.
auto showQuitMenu = std::make_shared<SwitchComponent>(); auto showQuitMenu = std::make_shared<SwitchComponent>();
showQuitMenu->setState(Settings::getInstance()->getBool("ShowQuitMenu")); showQuitMenu->setState(Settings::getInstance()->getBool("ShowQuitMenu"));
@ -1661,12 +1901,23 @@ void GuiMenu::openUtilities()
ComponentListRow row; ComponentListRow row;
#if defined(ANDROID_LITE_RELEASE)
auto orphanedDataCleanup =
std::make_shared<TextComponent>("ORPHANED DATA CLEANUP (FULL VERSION ONLY)",
Font::get(FONT_SIZE_MEDIUM), mMenuColorPrimary);
orphanedDataCleanup->setOpacity(DISABLED_OPACITY);
row.addElement(orphanedDataCleanup, true);
auto orphanedDataCleanupArrow = mMenu.makeArrow();
orphanedDataCleanupArrow->setOpacity(DISABLED_OPACITY);
row.addElement(orphanedDataCleanupArrow, false);
#else
row.addElement(std::make_shared<TextComponent>("ORPHANED DATA CLEANUP", row.addElement(std::make_shared<TextComponent>("ORPHANED DATA CLEANUP",
Font::get(FONT_SIZE_MEDIUM), mMenuColorPrimary), Font::get(FONT_SIZE_MEDIUM), mMenuColorPrimary),
true); true);
row.addElement(mMenu.makeArrow(), false); row.addElement(mMenu.makeArrow(), false);
row.makeAcceptInputHandler(std::bind( row.makeAcceptInputHandler(std::bind(
[this] { mWindow->pushGui(new GuiOrphanedDataCleanup([&]() { close(true); })); })); [this] { mWindow->pushGui(new GuiOrphanedDataCleanup([&]() { close(true); })); }));
#endif
s->addRow(row); s->addRow(row);
row.elements.clear(); row.elements.clear();
@ -1764,7 +2015,11 @@ void GuiMenu::openUtilities()
void GuiMenu::openQuitMenu() void GuiMenu::openQuitMenu()
{ {
#if defined(__APPLE__) || defined(__ANDROID__)
if (true) {
#else
if (!Settings::getInstance()->getBool("ShowQuitMenu")) { if (!Settings::getInstance()->getBool("ShowQuitMenu")) {
#endif
mWindow->pushGui(new GuiMsgBox( mWindow->pushGui(new GuiMsgBox(
this->getHelpStyle(), "REALLY QUIT?", "YES", this->getHelpStyle(), "REALLY QUIT?", "YES",
[this] { [this] {
@ -1790,8 +2045,8 @@ void GuiMenu::openQuitMenu()
}, },
"NO", nullptr)); "NO", nullptr));
}); });
auto quitText = std::make_shared<TextComponent>( auto quitText = std::make_shared<TextComponent>("QUIT RETRODECK", Font::get(FONT_SIZE_MEDIUM),
"QUIT RETRODECK", Font::get(FONT_SIZE_MEDIUM), mMenuColorPrimary); mMenuColorPrimary);
quitText->setSelectable(true); quitText->setSelectable(true);
row.addElement(quitText, true); row.addElement(quitText, true);
s->addRow(row); s->addRow(row);
@ -1840,11 +2095,17 @@ void GuiMenu::addVersionInfo()
mVersion.setFont(Font::get(FONT_SIZE_SMALL)); mVersion.setFont(Font::get(FONT_SIZE_SMALL));
mVersion.setColor(mMenuColorTertiary); mVersion.setColor(mMenuColorTertiary);
#if defined(ANDROID_LITE_RELEASE)
const std::string applicationName {"ES-DE LITE"};
#else
const std::string applicationName {"ES-DE"};
#endif
#if defined(IS_PRERELEASE) #if defined(IS_PRERELEASE)
mVersion.setText("EMULATIONSTATION-DE V" + Utils::String::toUpper(PROGRAM_VERSION_STRING) + mVersion.setText(applicationName + " V" + Utils::String::toUpper(PROGRAM_VERSION_STRING) +
" (Built " + __DATE__ + ")"); " (Built " + __DATE__ + ")");
#else #else
mVersion.setText("EMULATIONSTATION-DE V" + Utils::String::toUpper(PROGRAM_VERSION_STRING)); mVersion.setText(applicationName + " V" + Utils::String::toUpper(PROGRAM_VERSION_STRING));
#endif #endif
mVersion.setHorizontalAlignment(ALIGN_CENTER); mVersion.setHorizontalAlignment(ALIGN_CENTER);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMenu.h // GuiMenu.h
// //
// Main menu. // Main menu.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMetaDataEd.cpp // GuiMetaDataEd.cpp
// //
// Game metadata edit user interface. // Game metadata edit user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiMetaDataEd.h // GuiMetaDataEd.h
// //
// Game metadata edit user interface. // Game metadata edit user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiOfflineGenerator.cpp // GuiOfflineGenerator.cpp
// //
// User interface for the miximage offline generator. // User interface for the miximage offline generator.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiOfflineGenerator.h // GuiOfflineGenerator.h
// //
// User interface for the miximage offline generator. // User interface for the miximage offline generator.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE Frontend
// GuiOrphanedDataCleanup.cpp // GuiOrphanedDataCleanup.cpp
// //
// Removes orphaned game media, gamelist.xml entries and custom collections entries. // Removes orphaned game media, gamelist.xml entries and custom collections entries.
@ -39,7 +39,7 @@ GuiOrphanedDataCleanup::GuiOrphanedDataCleanup(std::function<void()> reloadCallb
addChild(&mBackground); addChild(&mBackground);
addChild(&mGrid); addChild(&mGrid);
#if defined(_WIN64) || defined(__APPLE__) #if defined(_WIN64) || defined(__APPLE__) || defined(__ANDROID__)
// Although macOS may have filesystem case-sensitivity enabled it's rare and in worst case // Although macOS may have filesystem case-sensitivity enabled it's rare and in worst case
// this will just leave some extra media files on the filesystem. // this will just leave some extra media files on the filesystem.
mCaseSensitiveFilesystem = false; mCaseSensitiveFilesystem = false;

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE Frontend
// GuiOrphanedDataCleanup.h // GuiOrphanedDataCleanup.h
// //
// Removes orphaned game media, gamelist.xml entries and custom collections entries. // Removes orphaned game media, gamelist.xml entries and custom collections entries.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperMenu.cpp // GuiScraperMenu.cpp
// //
// Game media scraper, including settings as well as the scraping start button. // Game media scraper, including settings as well as the scraping start button.
@ -950,20 +950,6 @@ void GuiScraperMenu::openOtherOptions()
} }
}); });
// Halt scraping on invalid media files.
auto scraperHaltOnInvalidMedia = std::make_shared<SwitchComponent>();
scraperHaltOnInvalidMedia->setState(
Settings::getInstance()->getBool("ScraperHaltOnInvalidMedia"));
s->addWithLabel("HALT ON INVALID MEDIA FILES", scraperHaltOnInvalidMedia);
s->addSaveFunc([scraperHaltOnInvalidMedia, s] {
if (scraperHaltOnInvalidMedia->getState() !=
Settings::getInstance()->getBool("ScraperHaltOnInvalidMedia")) {
Settings::getInstance()->setBool("ScraperHaltOnInvalidMedia",
scraperHaltOnInvalidMedia->getState());
s->setNeedsSaving();
}
});
// Search using file hashes for non-interactive mode. // Search using file hashes for non-interactive mode.
auto scraperSearchFileHash = std::make_shared<SwitchComponent>(); auto scraperSearchFileHash = std::make_shared<SwitchComponent>();
scraperSearchFileHash->setState(Settings::getInstance()->getBool("ScraperSearchFileHash")); scraperSearchFileHash->setState(Settings::getInstance()->getBool("ScraperSearchFileHash"));

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperMenu.h // GuiScraperMenu.h
// //
// Game media scraper, including settings as well as the scraping start button. // Game media scraper, including settings as well as the scraping start button.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperMulti.cpp // GuiScraperMulti.cpp
// //
// Multiple game scraping user interface. // Multiple game scraping user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperMulti.h // GuiScraperMulti.h
// //
// Multiple game scraping user interface. // Multiple game scraping user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperSearch.cpp // GuiScraperSearch.cpp
// //
// User interface for the scraper where the user is able to see an overview // User interface for the scraper where the user is able to see an overview

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperSearch.h // GuiScraperSearch.h
// //
// User interface for the scraper where the user is able to see an overview // User interface for the scraper where the user is able to see an overview

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperSingle.cpp // GuiScraperSingle.cpp
// //
// Single game scraping user interface. // Single game scraping user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScraperSingle.h // GuiScraperSingle.h
// //
// Single game scraping user interface. // Single game scraping user interface.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScreensaverOptions.cpp // GuiScreensaverOptions.cpp
// //
// User interface for the screensaver options. // User interface for the screensaver options.
@ -15,6 +15,8 @@
#include "components/SliderComponent.h" #include "components/SliderComponent.h"
#include "components/SwitchComponent.h" #include "components/SwitchComponent.h"
#include "guis/GuiMsgBox.h" #include "guis/GuiMsgBox.h"
#include "guis/GuiTextEditKeyboardPopup.h"
#include "guis/GuiTextEditPopup.h"
GuiScreensaverOptions::GuiScreensaverOptions(const std::string& title) GuiScreensaverOptions::GuiScreensaverOptions(const std::string& title)
: GuiSettings {title} : GuiSettings {title}
@ -196,20 +198,45 @@ void GuiScreensaverOptions::openSlideshowScreensaverOptions()
}); });
// Custom image directory. // Custom image directory.
auto screensaverSlideshowImageDir = std::make_shared<TextComponent>( ComponentListRow rowCustomImageDir;
"", Font::get(FONT_SIZE_SMALL), mMenuColorPrimary, ALIGN_RIGHT); auto ScreensaverSlideshowCustomDir = std::make_shared<TextComponent>(
s->addEditableTextComponent( "CUSTOM IMAGE DIRECTORY", Font::get(FONT_SIZE_MEDIUM), mMenuColorPrimary);
"CUSTOM IMAGE DIRECTORY", screensaverSlideshowImageDir, auto bracketCustomImageDir = std::make_shared<ImageComponent>();
Settings::getInstance()->getString("ScreensaverSlideshowImageDir"), bracketCustomImageDir->setResize(
Settings::getInstance()->getDefaultString("ScreensaverSlideshowImageDir")); glm::vec2 {0.0f, Font::get(FONT_SIZE_MEDIUM)->getLetterHeight()});
s->addSaveFunc([screensaverSlideshowImageDir, s] { bracketCustomImageDir->setImage(":/graphics/arrow.svg");
if (screensaverSlideshowImageDir->getValue() != bracketCustomImageDir->setColorShift(mMenuColorPrimary);
Settings::getInstance()->getString("ScreensaverSlideshowImageDir")) { rowCustomImageDir.addElement(ScreensaverSlideshowCustomDir, true);
Settings::getInstance()->setString("ScreensaverSlideshowImageDir", rowCustomImageDir.addElement(bracketCustomImageDir, false);
screensaverSlideshowImageDir->getValue()); const std::string titleCustomImageDir {"CUSTOM IMAGE DIRECTORY"};
s->setNeedsSaving(); const std::string defaultImageDirStaticText {"Default directory:"};
const std::string defaultImageDirText {Utils::FileSystem::getAppDataDirectory() +
"/screensavers/custom_slideshow"};
const std::string initValueMediaDir {
Settings::getInstance()->getString("ScreensaverSlideshowCustomDir")};
auto updateValMediaDir = [s](const std::string& newVal) {
Settings::getInstance()->setString("ScreensaverSlideshowCustomDir", newVal);
s->setNeedsSaving();
};
rowCustomImageDir.makeAcceptInputHandler([this, s, titleCustomImageDir,
defaultImageDirStaticText, defaultImageDirText,
initValueMediaDir, updateValMediaDir] {
if (Settings::getInstance()->getBool("VirtualKeyboard")) {
mWindow->pushGui(new GuiTextEditKeyboardPopup(
getHelpStyle(), s->getMenu().getPosition().y, titleCustomImageDir,
Settings::getInstance()->getString("ScreensaverSlideshowCustomDir"),
updateValMediaDir, false, "SAVE", "SAVE CHANGES?", defaultImageDirStaticText,
defaultImageDirText, "load default directory"));
}
else {
mWindow->pushGui(new GuiTextEditPopup(
getHelpStyle(), titleCustomImageDir,
Settings::getInstance()->getString("ScreensaverSlideshowCustomDir"),
updateValMediaDir, false, "SAVE", "SAVE CHANGES?", defaultImageDirStaticText,
defaultImageDirText, "load default directory"));
} }
}); });
s->addRow(rowCustomImageDir);
s->setSize(mSize); s->setSize(mSize);
mWindow->pushGui(s); mWindow->pushGui(s);

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiScreensaverOptions.h // GuiScreensaverOptions.h
// //
// User interface for the screensaver options. // User interface for the screensaver options.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiSettings.cpp // GuiSettings.cpp
// //
// User interface template for a settings GUI. // User interface template for a settings GUI.

View file

@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
// //
// EmulationStation Desktop Edition // ES-DE
// GuiSettings.h // GuiSettings.h
// //
// User interface template for a settings GUI. // User interface template for a settings GUI.

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