diff --git a/.gitignore b/.gitignore
index 2ef23aa1c..6645841f5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,6 +1,7 @@
# Object files
*.o
*.lo
+*.mo
*.slo
# Shared libraries
diff --git a/ANDROID-DEV.md b/ANDROID-DEV.md
index 5dfdb1719..3723c3656 100644
--- a/ANDROID-DEV.md
+++ b/ANDROID-DEV.md
@@ -182,6 +182,8 @@ Apart from this it works as you'd expect, ES-DE will start automatically when re
If the operating system runs out of memory when a game is running it will kill ES-DE even if it's set as home app. If this happens ES-DE will reload whenever you return from the game or if you press the home button. This is simply how Android works.
+Also be aware that the version check that runs on app startup may not be able to complete successfully when ES-DE is set as the home app, as the device may not have network connectivity enabled yet just after rebooting.
+
It's generally a very good idea to import your native Android apps into ES-DE prior to setting it as the home app, this way you can easily access things like the Settings app. Note however that even if you somehow lock yourself out of the system by setting ES-DE as the home app and not having any native apps added you can still always access the Settings app via the Android notification shade. On most devices you access this by swiping down from the top of the screen. After swiping down, just select the cogwheel icon to start the Settings app. From there you can change the home app to something else than ES-DE, should you need to.
## Known ES-DE problems
@@ -332,6 +334,20 @@ After installing the emulator, open it and go to the settings tab, then choose "
http://www.arts-union.ru/node/23
+### J2ME Loader
+
+This emulator can be installed from the Play store or the F-Droid store, or it can be downloaded from their GitHub site.
+
+https://play.google.com/store/apps/details?id=ru.playsoftware.j2meloader \
+https://f-droid.org/en/packages/ru.playsoftware.j2meloader \
+https://github.com/nikita36078/J2ME-Loader/releases
+
+### JL-Mod
+
+This emulator can be downloaded from their GitHub site.
+
+https://github.com/woesss/JL-Mod/releases
+
### Lime3DS
This emulator which is forked from Citra can be downloaded from their GitHub site.
@@ -347,6 +363,14 @@ Note that for MAME4droid 2024 there's an exception when it comes to setting up t
https://play.google.com/store/apps/details?id=com.seleuco.mame4d2024 \
https://play.google.com/store/apps/details?id=com.seleuco.mame4droid
+Be aware that MAME4droid 2024 requires specific input configuration for some systems. For instance to navigate the mouse cursor when using touch input you'll need to got into the _Settings_ menu, then _Input_, then _Touch controller_ and change _Mode_ to _Analog Stick_.
+
+If using a physical controller for mouse input (via the thumbstick) then you will need to map the mouse buttons to physical controller buttons. You do this via the MAME input settings. Bring up the MAME menu by pressing both thumbsticks, or by pressing the _Start_ and _Coin_ buttons on the touch overlay. Go into _Input Settings_ then _Input Assignments (this system)_ where you can assign physical buttons to the mouse buttons.
+
+For some systems you will need to explictly set the _Start_ and _Select_ buttons in the same fashion as when configuring the mouse buttons. Otherwise you'll not be able to start any games.
+
+There are a few more things that you may need to configure for some systems, but that's beyond the scope of this document and should be covered by the MAME emulator documentation.
+
### MasterGear
This emulator can be installed from the Play store as a paid app.
@@ -387,6 +411,12 @@ Nesoid is not available on the Play store but it can be installed from the F-Dro
https://f-droid.org/en/packages/com.androidemu.nes \
https://github.com/proninyaroslav/nesoid/releases
+### NooDS
+
+Although NooDS is available via the Play store that version does not allow game launching from ES-DE. To get that to work instead use the version from their GitHub site. Also note that this emulator does not support launching of zipped game files.
+
+https://github.com/Hydr8gon/NooDS/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).
@@ -484,6 +514,17 @@ This PlayStation Vita emulator can be downloaded from their GitHub site. Refer t
https://github.com/Vita3K/Vita3K-Android/releases
+### Winlator
+
+In order to use Winlator to run Windows games you need to use a specific fork named _Winlator Cmod_ as mainline [Winlator](https://winlator.com/) does not offer frontend support. The Cmod fork can be downloaded from their GitHub page:\
+https://github.com/coffincolors/winlator
+
+There are two variants of the fork, Glibc and PRoot, both of which come with some pros and cons with regards to compatibility and performance. The Glibc variant is the default emulator in ES-DE, so to use PRoot instead you'll need to select its alternative emulator entry.
+
+In addition to the official repository there are multiple Winlator builds floating around the Internet, but these have not been extensively tested with ES-DE.
+
+It's beyond the scope of this document to describe how to install games in Winlator, but once it's done and you've created a shortcut to your game from inside the container you can export it via the _Export for Frontend_ option in the Winlator user interface. This will generate a .desktop file that you can place in the `ROMs/pcarcade`, `ROMs/type-x` or `ROMs/windows` folder and launch from ES-DE. You can alternatively set the _Frontend Export Path_ setting from inside the Winlator Settings screen to avoid the manual step of moving the .desktop file.
+
### Yaba Sanshiro 2
This emulator can be installed from the Play store. Note that only the paid Pro version supports game launching from ES-DE. Also note that .bin/.cue files can't be launched for the time being, only .chd files seem to work. This needs to be fixed in the emulator so nothing can be done in ES-DE to work around that limitation.
@@ -504,6 +545,7 @@ This is clearly not a complete list of Android devices, but rather those we know
| Anbernic | RG505 | 12 | Yes | None | Limited RAM capacity for this device makes it unsuitable for demanding themes and large game collections |
| Anbernic | RG556 | 13 | Yes | None | |
| Anbernic | RG ARC | 12 | Yes | None | LineageOS |
+| Anbernic | RG Cube | 13 | Yes | None | |
| AYANEO | Pocket Air | 12 | Yes | None | |
| AYANEO | Pocket S | 13 | Yes | None | |
| Ayn | Odin (Base/Pro) | 10 | Yes | None | |
@@ -528,7 +570,7 @@ This is clearly not a complete list of Android devices, but rather those we know
| Huawei | MatePad 11 (2021) | 13 | Yes | None | |
| Infinix | Zero 30 5G | 13 | Yes | None | |
| Kinhank | G1 | 11 | No | Unable to install | Possibly 32-bit operating system? |
-| Kinhank | Super Console X5 Pro | 12 (TV) | No | Fails at configurator/onboarding | Seems to run a custom 64-bit Android TV OS |
+| Kinhank | Super Console X5 Pro | 12 (TV) | No | None | Custom 64-bit Android TV OS |
| Lenovo | Legion Y700 (2022) | 12 | Yes | None | |
| Lenovo | Legion Y700 (2023) | 13 | Yes | None | |
| Lenovo | Xiaoxin Pad Pro 2021 | 11 | Yes | None | |
@@ -553,6 +595,9 @@ This is clearly not a complete list of Android devices, but rather those we know
| OnePlus | Open | 14 | Yes | None | |
| Oppo | A15 | 10 | Yes | None | |
| Oppo | Find X5 Pro | 14 | Yes | None | |
+| Oppo | Reno5 | 12 | Yes | None | |
+| Raspberry | Pi 4/400 | 13, 14 | Yes | None | Low-power GPU so ES-DE may run a bit sluggish |
+| Raspberry | Pi 5 | 15 | Yes | None | Very poor GPU performance, runs at almost double speed in Raspberry Pi OS so likely a driver issue |
| Razer | Edge | 13 | Yes | None | |
| Realme | GT2 | 12 | Yes | None | |
| Retroid | Pocket 2+ | 11 | Yes | None | |
@@ -615,10 +660,10 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| 3do | 3DO Interactive Multiplayer | Opera | Real3DOPlayer **(Standalone)** | Yes | |
| adam | Coleco Adam | MAME4droid 2024 [Diskette] **(Standalone)** | MAME4droid 2024 [Tape] **(Standalone)**, MAME4droid 2024 [Cartridge] **(Standalone)**, MAME4droid 2024 [Software list] **(Standalone)**, ColEm **(Standalone)** | Yes for MAME4droid 2024 | |
| 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 | |
+| amiga | Commodore Amiga | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga1200 | Commodore Amiga 1200 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga600 | Commodore Amiga 600 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amigacd32 | Commodore Amiga CD32 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
| amstradcpc | Amstrad CPC | Caprice32 | CrocoDS, MAME4droid 2024 **(Standalone)** | Yes for MAME4droid 2024 | Single archive or disk file |
| android | Google Android | _Placeholder_ | | | |
| androidapps | Android Apps | _Native apps_ | | No | |
@@ -628,9 +673,9 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| arcade | Arcade | MAME - Current | MAME 2010, MAME 2003-Plus, MAME 2003, MAME 2000, MAME4droid 2024 **(Standalone)**, MAME4droid **(Standalone)**, NEO.emu **(Standalone)**, FinalBurn Neo, FB Alpha 2012, Geolith, Flycast, Flycast **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
| arcadia | Emerson Arcadia 2001 | DroidArcadia **(Standalone**) | MAME4droid 2024 **(Standalone)** | No | Single archive or ROM file |
| archimedes | Acorn Archimedes | MAME4droid 2024 [Model A440/1] **(Standalone)** | MAME4droid 2024 [Model A3000] **(Standalone)**, MAME4droid 2024 [Model A310] **(Standalone)**, MAME4droid 2024 [Model A540] **(Standalone)** | Yes | |
-| arduboy | Arduboy Miniature Game System | Arduous | | No | Single archive or .hex file |
+| arduboy | Arduboy Miniature Game System | Arduous | Ardens | No | Single archive or .hex file |
| astrocde | Bally Astrocade | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
-| atari2600 | Atari 2600 | Stella | Stella 2014, 2600.emu **(Standalone)** | No | Single archive or ROM file |
+| atari2600 | Atari 2600 | Stella | Stella 2014, Stella 2023, 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 | MAME4droid 2024 **(Standalone)** | Yes | Single archive or ROM file |
| atari800 | Atari 800 | Atari800 | | Yes | |
@@ -657,8 +702,8 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| daphne | Daphne Arcade LaserDisc Emulator | MAME4droid 2024 **(Standalone)** | DirkSimple | Depends | See the specific _LaserDisc Games_ section in the user guide |
| desktop | Desktop Applications | _Placeholder_ | | | |
| doom | Doom | PrBoom | | No | |
-| dos | DOS (PC) | DOSBox-Pure | DOSBox-Core, DOSBox-SVN | No | |
-| dragon32 | Dragon Data Dragon 32 | _Placeholder_ | | | |
+| dos | DOS (PC) | DOSBox-Pure | DOSBox-Core, DOSBox-SVN, VirtualXT | No | See the specific _DOS / PC_ section in the user guide |
+| dragon32 | Dragon Data Dragon 32 | MAME4droid 2024 Dragon 32 [Tape] **(Standalone)** | MAME4droid 2024 Dragon 32 [Cartridge] **(Standalone)**, MAME4droid 2024 Dragon 64 [Tape] **(Standalone)**, MAME4droid 2024 Dragon 64 [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
| dreamcast | Sega Dreamcast | Flycast | Flycast **(Standalone)**, 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 | MAME4droid 2024 [Tape] **(Standalone)** | MAME4droid 2024 [Diskette DFS] **(Standalone)**, MAME4droid 2024 [Diskette ADFS] **(Standalone)** | Yes | Single archive, or single tape or diskette image file |
@@ -677,14 +722,14 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| gamecom | Tiger Electronics Game.com | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
| gamegear | Sega Game Gear | Genesis Plus GX | Genesis Plus GX Wide, Gearsystem, SMS Plus GX, PicoDrive, MasterGear **(Standalone)** | No | Single archive or ROM file |
| gb | Nintendo Game Boy | Gambatte | SameBoy, Gearboy, TGB Dual, DoubleCherryGB, Mesen-S, bsnes, mGBA, VBA-M, GBC.emu **(Standalone)**, My OldBoy! **(Standalone**), Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
-| gba | Nintendo Game Boy Advance | mGBA | VBA-M, VBA Next, gpSP, GBA.emu **(Standalone)**, My Boy! **(Standalone)**, Pizza Boy GBA **(Standalone)** | No | Single archive or ROM file |
+| gba | Nintendo Game Boy Advance | mGBA | VBA-M, VBA Next, gpSP, GBA.emu **(Standalone)**, My Boy! **(Standalone)**, NooDS **(Standalone)**, Pizza Boy GBA **(Standalone)** | No | Single archive or ROM file |
| gbc | Nintendo Game Boy Color | Gambatte | SameBoy, Gearboy, TGB Dual, DoubleCherryGB, Mesen-S, bsnes, mGBA, VBA-M, GBC.emu **(Standalone)**, My OldBoy! **(Standalone**), Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
| gc | Nintendo GameCube | Dolphin | Dolphin **(Standalone)**, Dolphin MMJR **(Standalone)**, Dolphin MMJR2 **(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, PicoDrive, MD.emu **(Standalone)** | No | Single archive or ROM file |
| gmaster | Hartung Game Master | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
| gx4000 | Amstrad GX4000 | Caprice32 | CrocoDS, MAME4droid 2024 **(Standalone)** | No | Single archive or ROM file |
| intellivision | Mattel Electronics Intellivision | FreeIntv | MAME4droid 2024 **(Standalone)** | Yes | Single archive or ROM file |
-| j2me | Java 2 Micro Edition (J2ME) | SquirrelJME | | No | Single .jar file |
+| j2me | Java 2 Micro Edition (J2ME) | J2ME Loader **(Standalone)** | JL-Mod **(Standalone)**, SquirrelJME | No | Single .jar file |
| kodi | Kodi Home Theatre Software | _Placeholder_ | | | |
| laserdisc | LaserDisc Games | MAME4droid 2024 **(Standalone)** | DirkSimple | Depends | See the specific _LaserDisc Games_ section in the user guide |
| lcdgames | LCD Handheld Games | Multi (MESS) | MAME4droid 2024 Local Artwork **(Standalone)**, MAME4droid 2024 **(Standalone)**, Handheld Electronic (GW) | No | See the specific _LCD handheld games_ section in the user guide |
@@ -716,7 +761,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| n3ds | Nintendo 3DS | Citra | Citra **(Standalone)**, Citra Canary **(Standalone)**, Citra MMJ **(Standalone)**, Lime3DS **(Standalone)**, Panda3DS **(Standalone)** | No | Single ROM file |
| n64 | Nintendo 64 | Mupen64Plus-Next | M64Plus FZ **(Standalone)**, Mupen64Plus AE **(Standalone)**, ParaLLEl N64 | No | Single archive or ROM file |
| n64dd | Nintendo 64DD | Mupen64Plus-Next | M64Plus FZ **(Standalone)**, Mupen64Plus AE **(Standalone)**, ParaLLEl N64 | Yes | |
-| nds | Nintendo DS | melonDS DS | melonDS, melonDS **(Standalone)**, melonDS Nightly **(Standalone)**, DeSmuME, DeSmuME 2015, DraStic **(Standalone)** | No | Single archive or ROM file |
+| nds | Nintendo DS | melonDS DS | melonDS, melonDS **(Standalone)**, melonDS Nightly **(Standalone)**, DeSmuME, DeSmuME 2015, DraStic **(Standalone)**, NooDS **(Standalone)** | No | Single archive or ROM file |
| neogeo | SNK Neo Geo | FinalBurn Neo | Geolith, NEO.emu **(Standalone)**, MAME4droid 2024 **(Standalone)**, MAME4droid **(Standalone)** | Yes | See the specific _Arcade and Neo Geo_ section in the user guide |
| neogeocd | SNK Neo Geo CD | NeoCD | FinalBurn Neo, MAME4droid 2024 **(Standalone)** | Yes | .chd (NeoCD and MAME4droid 2024 only) or .cue file |
| neogeocdjp | SNK Neo Geo CD [Japan] | NeoCD | FinalBurn Neo, MAME4droid 2024 **(Standalone)** | Yes | .chd (NeoCD and MAME4droid 2024 only) or .cue file |
@@ -728,10 +773,10 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| openbor | OpenBOR Game Engine | OpenBOR **(Standalone)** | | No | See the specific _OpenBOR_ section in the User guide |
| oric | Tangerine Computer Systems Oric | MAME4droid 2024 **(Standalone)** | | Yes | See the specific _Tangerine Computer Systems Oric_ section in the user guide |
| palm | Palm OS | Mu | | | |
-| pc | IBM PC | DOSBox-Pure | DOSBox-Core, DOSBox-SVN | No | |
+| pc | IBM PC | DOSBox-Pure | DOSBox-Core, DOSBox-SVN, VirtualXT | No | See the specific _DOS / PC_ section in the user guide |
| pc88 | NEC PC-8800 Series | QUASI88 | | Yes | |
| pc98 | NEC PC-9800 Series | Neko Project II Kai | Neko Project II | | |
-| pcarcade | PC Arcade Systems | _Placeholder_ | | | | |
+| pcarcade | PC Arcade Systems | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| pcengine | NEC PC Engine | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | No | Single archive or ROM file |
| pcenginecd | NEC PC Engine CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | Yes | |
| pcfx | NEC PC-FX | Beetle PC-FX | | Yes | |
@@ -772,7 +817,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| supracan | Funtech Super A'Can | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file. You need a supracan.zip archive that contains a valid internal_68k.bin file and an empty file named umc6650.bin |
| switch | Nintendo Switch | Skyline **(Standalone)** | | Yes | |
| symbian | Symbian | EKA2L1 **(Standalone)** | | Yes | See the specific _Symbian and Nokia N-Gage_ section in the User guide |
-| tanodragon | Tano Dragon | _Placeholder_ | | | |
+| tanodragon | Tano Dragon | MAME4droid 2024 [Tape] **(Standalone)** | MAME4droid 2024 [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
| tg16 | NEC TurboGrafx-16 | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | No | Single archive or ROM file |
| tg-cd | NEC TurboGrafx-CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | Yes | |
| ti99 | Texas Instruments TI-99 | MAME4droid 2024 **(Standalone)** | | Yes | See the specific _Texas Instruments TI-99_ section in the user guide |
@@ -780,7 +825,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| to8 | Thomson TO8 | Theodore | | | |
| triforce | Namco-Sega-Nintendo Triforce | _Placeholder_ | | | |
| trs-80 | Tandy TRS-80 | _Placeholder_ | | | |
-| type-x | Taito Type X | _Placeholder_ | | | |
+| type-x | Taito Type X | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| uzebox | Uzebox Open Source Console | Uzem | | | |
| vectrex | GCE Vectrex | vecx | MAME4droid 2024 **(Standalone)** | Yes for MAME4droid 2024 | Single archive or ROM file |
| vic20 | Commodore VIC-20 | VICE xvic | | No | Single archive or tape, cartridge or diskette image file |
@@ -791,7 +836,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| wasm4 | WASM-4 Fantasy Console | WASM-4 | | No | Single .wasm file |
| wii | Nintendo Wii | Dolphin | Dolphin **(Standalone)**, Dolphin MMJR **(Standalone)**, Dolphin MMJR2 **(Standalone)** | No | |
| wiiu | Nintendo Wii U | _Placeholder_ | | | |
-| windows | Microsoft Windows | _Placeholder_ | | | |
+| windows | Microsoft Windows | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| 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 |
@@ -801,6 +846,6 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| xbox | Microsoft Xbox | _Placeholder_ | | | |
| xbox360 | Microsoft Xbox 360 | _Placeholder_ | | | |
| zmachine | Infocom Z-machine | MojoZork | | No | |
-| zx81 | Sinclair ZX81 | EightyOne | | | |
+| zx81 | Sinclair ZX81 | EightyOne | | No | |
| zxnext | Sinclair ZX Spectrum Next | _Placeholder_ | | | |
| zxspectrum | Sinclair ZX Spectrum | Fuse | Speccy **(Standalone)** | No | Single archive or ROM file |
diff --git a/ANDROID.md b/ANDROID.md
index 61e3b1244..42b4428ed 100644
--- a/ANDROID.md
+++ b/ANDROID.md
@@ -182,6 +182,8 @@ Apart from this it works as you'd expect, ES-DE will start automatically when re
If the operating system runs out of memory when a game is running it will kill ES-DE even if it's set as home app. If this happens ES-DE will reload whenever you return from the game or if you press the home button. This is simply how Android works.
+Also be aware that the version check that runs on app startup may not be able to complete successfully when ES-DE is set as the home app, as the device may not have network connectivity enabled yet just after rebooting.
+
It's generally a very good idea to import your native Android apps into ES-DE prior to setting it as the home app, this way you can easily access things like the Settings app. Note however that even if you somehow lock yourself out of the system by setting ES-DE as the home app and not having any native apps added you can still always access the Settings app via the Android notification shade. On most devices you access this by swiping down from the top of the screen. After swiping down, just select the cogwheel icon to start the Settings app. From there you can change the home app to something else than ES-DE, should you need to.
## Known ES-DE problems
@@ -332,6 +334,20 @@ After installing the emulator, open it and go to the settings tab, then choose "
http://www.arts-union.ru/node/23
+### J2ME Loader
+
+This emulator can be installed from the Play store or the F-Droid store, or it can be downloaded from their GitHub site.
+
+https://play.google.com/store/apps/details?id=ru.playsoftware.j2meloader \
+https://f-droid.org/en/packages/ru.playsoftware.j2meloader \
+https://github.com/nikita36078/J2ME-Loader/releases
+
+### JL-Mod
+
+This emulator can be downloaded from their GitHub site.
+
+https://github.com/woesss/JL-Mod/releases
+
### Lime3DS
This emulator which is forked from Citra can be downloaded from their GitHub site.
@@ -347,6 +363,14 @@ Note that for MAME4droid 2024 there's an exception when it comes to setting up t
https://play.google.com/store/apps/details?id=com.seleuco.mame4d2024 \
https://play.google.com/store/apps/details?id=com.seleuco.mame4droid
+Be aware that MAME4droid 2024 requires specific input configuration for some systems. For instance to navigate the mouse cursor when using touch input you'll need to got into the _Settings_ menu, then _Input_, then _Touch controller_ and change _Mode_ to _Analog Stick_.
+
+If using a physical controller for mouse input (via the thumbstick) then you will need to map the mouse buttons to physical controller buttons. You do this via the MAME input settings. Bring up the MAME menu by pressing both thumbsticks, or by pressing the _Start_ and _Coin_ buttons on the touch overlay. Go into _Input Settings_ then _Input Assignments (this system)_ where you can assign physical buttons to the mouse buttons.
+
+For some systems you will need to explictly set the _Start_ and _Select_ buttons in the same fashion as when configuring the mouse buttons. Otherwise you'll not be able to start any games.
+
+There are a few more things that you may need to configure for some systems, but that's beyond the scope of this document and should be covered by the MAME emulator documentation.
+
### MasterGear
This emulator can be installed from the Play store as a paid app.
@@ -387,6 +411,12 @@ Nesoid is not available on the Play store but it can be installed from the F-Dro
https://f-droid.org/en/packages/com.androidemu.nes \
https://github.com/proninyaroslav/nesoid/releases
+### NooDS
+
+Although NooDS is available via the Play store that version does not allow game launching from ES-DE. To get that to work instead use the version from their GitHub site. Also note that this emulator does not support launching of zipped game files.
+
+https://github.com/Hydr8gon/NooDS/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.md#openbor).
@@ -484,6 +514,17 @@ This PlayStation Vita emulator can be downloaded from their GitHub site. Refer t
https://github.com/Vita3K/Vita3K-Android/releases
+### Winlator
+
+In order to use Winlator to run Windows games you need to use a specific fork named _Winlator Cmod_ as mainline [Winlator](https://winlator.com/) does not offer frontend support. The Cmod fork can be downloaded from their GitHub page:\
+https://github.com/coffincolors/winlator
+
+There are two variants of the fork, Glibc and PRoot, both of which come with some pros and cons with regards to compatibility and performance. The Glibc variant is the default emulator in ES-DE, so to use PRoot instead you'll need to select its alternative emulator entry.
+
+In addition to the official repository there are multiple Winlator builds floating around the Internet, but these have not been extensively tested with ES-DE.
+
+It's beyond the scope of this document to describe how to install games in Winlator, but once it's done and you've created a shortcut to your game from inside the container you can export it via the _Export for Frontend_ option in the Winlator user interface. This will generate a .desktop file that you can place in the `ROMs/pcarcade`, `ROMs/type-x` or `ROMs/windows` folder and launch from ES-DE. You can alternatively set the _Frontend Export Path_ setting from inside the Winlator Settings screen to avoid the manual step of moving the .desktop file.
+
### Yaba Sanshiro 2
This emulator can be installed from the Play store. Note that only the paid Pro version supports game launching from ES-DE. Also note that .bin/.cue files can't be launched for the time being, only .chd files seem to work. This needs to be fixed in the emulator so nothing can be done in ES-DE to work around that limitation.
@@ -504,6 +545,7 @@ This is clearly not a complete list of Android devices, but rather those we know
| Anbernic | RG505 | 12 | Yes | None | Limited RAM capacity for this device makes it unsuitable for demanding themes and large game collections |
| Anbernic | RG556 | 13 | Yes | None | |
| Anbernic | RG ARC | 12 | Yes | None | LineageOS |
+| Anbernic | RG Cube | 13 | Yes | None | |
| AYANEO | Pocket Air | 12 | Yes | None | |
| AYANEO | Pocket S | 13 | Yes | None | |
| Ayn | Odin (Base/Pro) | 10 | Yes | None | |
@@ -528,7 +570,7 @@ This is clearly not a complete list of Android devices, but rather those we know
| Huawei | MatePad 11 (2021) | 13 | Yes | None | |
| Infinix | Zero 30 5G | 13 | Yes | None | |
| Kinhank | G1 | 11 | No | Unable to install | Possibly 32-bit operating system? |
-| Kinhank | Super Console X5 Pro | 12 (TV) | No | Fails at configurator/onboarding | Seems to run a custom 64-bit Android TV OS |
+| Kinhank | Super Console X5 Pro | 12 (TV) | No | None | Custom 64-bit Android TV OS |
| Lenovo | Legion Y700 (2022) | 12 | Yes | None | |
| Lenovo | Legion Y700 (2023) | 13 | Yes | None | |
| Lenovo | Xiaoxin Pad Pro 2021 | 11 | Yes | None | |
@@ -553,6 +595,9 @@ This is clearly not a complete list of Android devices, but rather those we know
| OnePlus | Open | 14 | Yes | None | |
| Oppo | A15 | 10 | Yes | None | |
| Oppo | Find X5 Pro | 14 | Yes | None | |
+| Oppo | Reno5 | 12 | Yes | None | |
+| Raspberry | Pi 4/400 | 13, 14 | Yes | None | Low-power GPU so ES-DE may run a bit sluggish |
+| Raspberry | Pi 5 | 15 | Yes | None | Very poor GPU performance, runs at almost double speed in Raspberry Pi OS so likely a driver issue |
| Razer | Edge | 13 | Yes | None | |
| Realme | GT2 | 12 | Yes | None | |
| Retroid | Pocket 2+ | 11 | Yes | None | |
@@ -615,10 +660,10 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| 3do | 3DO Interactive Multiplayer | Opera | Real3DOPlayer **(Standalone)** | Yes | |
| adam | Coleco Adam | MAME4droid 2024 [Diskette] **(Standalone)** | MAME4droid 2024 [Tape] **(Standalone)**, MAME4droid 2024 [Cartridge] **(Standalone)**, MAME4droid 2024 [Software list] **(Standalone)**, ColEm **(Standalone)** | Yes for MAME4droid 2024 | |
| 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 | |
+| amiga | Commodore Amiga | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga1200 | Commodore Amiga 1200 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga600 | Commodore Amiga 600 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amigacd32 | Commodore Amiga CD32 | PUAE | PUAE 2021 | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
| amstradcpc | Amstrad CPC | Caprice32 | CrocoDS, MAME4droid 2024 **(Standalone)** | Yes for MAME4droid 2024 | Single archive or disk file |
| android | Google Android | _Placeholder_ | | | |
| androidapps | Android Apps | _Native apps_ | | No | |
@@ -628,9 +673,9 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| arcade | Arcade | MAME - Current | MAME 2010, MAME 2003-Plus, MAME 2003, MAME 2000, MAME4droid 2024 **(Standalone)**, MAME4droid **(Standalone)**, NEO.emu **(Standalone)**, FinalBurn Neo, FB Alpha 2012, Geolith, Flycast, Flycast **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
| arcadia | Emerson Arcadia 2001 | DroidArcadia **(Standalone**) | MAME4droid 2024 **(Standalone)** | No | Single archive or ROM file |
| archimedes | Acorn Archimedes | MAME4droid 2024 [Model A440/1] **(Standalone)** | MAME4droid 2024 [Model A3000] **(Standalone)**, MAME4droid 2024 [Model A310] **(Standalone)**, MAME4droid 2024 [Model A540] **(Standalone)** | Yes | |
-| arduboy | Arduboy Miniature Game System | Arduous | | No | Single archive or .hex file |
+| arduboy | Arduboy Miniature Game System | Arduous | Ardens | No | Single archive or .hex file |
| astrocde | Bally Astrocade | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
-| atari2600 | Atari 2600 | Stella | Stella 2014, 2600.emu **(Standalone)** | No | Single archive or ROM file |
+| atari2600 | Atari 2600 | Stella | Stella 2014, Stella 2023, 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 | MAME4droid 2024 **(Standalone)** | Yes | Single archive or ROM file |
| atari800 | Atari 800 | Atari800 | | Yes | |
@@ -657,8 +702,8 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| daphne | Daphne Arcade LaserDisc Emulator | MAME4droid 2024 **(Standalone)** | DirkSimple | Depends | See the specific _LaserDisc Games_ section in the user guide |
| desktop | Desktop Applications | _Placeholder_ | | | |
| doom | Doom | PrBoom | | No | |
-| dos | DOS (PC) | DOSBox-Pure | DOSBox-Core, DOSBox-SVN | No | |
-| dragon32 | Dragon Data Dragon 32 | _Placeholder_ | | | |
+| dos | DOS (PC) | DOSBox-Pure | DOSBox-Core, DOSBox-SVN, VirtualXT | No | See the specific _DOS / PC_ section in the user guide |
+| dragon32 | Dragon Data Dragon 32 | MAME4droid 2024 Dragon 32 [Tape] **(Standalone)** | MAME4droid 2024 Dragon 32 [Cartridge] **(Standalone)**, MAME4droid 2024 Dragon 64 [Tape] **(Standalone)**, MAME4droid 2024 Dragon 64 [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
| dreamcast | Sega Dreamcast | Flycast | Flycast **(Standalone)**, 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 | MAME4droid 2024 [Tape] **(Standalone)** | MAME4droid 2024 [Diskette DFS] **(Standalone)**, MAME4droid 2024 [Diskette ADFS] **(Standalone)** | Yes | Single archive, or single tape or diskette image file |
@@ -677,14 +722,14 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| gamecom | Tiger Electronics Game.com | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
| gamegear | Sega Game Gear | Genesis Plus GX | Genesis Plus GX Wide, Gearsystem, SMS Plus GX, PicoDrive, MasterGear **(Standalone)** | No | Single archive or ROM file |
| gb | Nintendo Game Boy | Gambatte | SameBoy, Gearboy, TGB Dual, DoubleCherryGB, Mesen-S, bsnes, mGBA, VBA-M, GBC.emu **(Standalone)**, My OldBoy! **(Standalone**), Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
-| gba | Nintendo Game Boy Advance | mGBA | VBA-M, VBA Next, gpSP, GBA.emu **(Standalone)**, My Boy! **(Standalone)**, Pizza Boy GBA **(Standalone)** | No | Single archive or ROM file |
+| gba | Nintendo Game Boy Advance | mGBA | VBA-M, VBA Next, gpSP, GBA.emu **(Standalone)**, My Boy! **(Standalone)**, NooDS **(Standalone)**, Pizza Boy GBA **(Standalone)** | No | Single archive or ROM file |
| gbc | Nintendo Game Boy Color | Gambatte | SameBoy, Gearboy, TGB Dual, DoubleCherryGB, Mesen-S, bsnes, mGBA, VBA-M, GBC.emu **(Standalone)**, My OldBoy! **(Standalone**), Pizza Boy GBC **(Standalone)** | No | Single archive or ROM file |
| gc | Nintendo GameCube | Dolphin | Dolphin **(Standalone)**, Dolphin MMJR **(Standalone)**, Dolphin MMJR2 **(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, PicoDrive, MD.emu **(Standalone)** | No | Single archive or ROM file |
| gmaster | Hartung Game Master | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file |
| gx4000 | Amstrad GX4000 | Caprice32 | CrocoDS, MAME4droid 2024 **(Standalone)** | No | Single archive or ROM file |
| intellivision | Mattel Electronics Intellivision | FreeIntv | MAME4droid 2024 **(Standalone)** | Yes | Single archive or ROM file |
-| j2me | Java 2 Micro Edition (J2ME) | SquirrelJME | | No | Single .jar file |
+| j2me | Java 2 Micro Edition (J2ME) | J2ME Loader **(Standalone)** | JL-Mod **(Standalone)**, SquirrelJME | No | Single .jar file |
| kodi | Kodi Home Theatre Software | _Placeholder_ | | | |
| laserdisc | LaserDisc Games | MAME4droid 2024 **(Standalone)** | DirkSimple | Depends | See the specific _LaserDisc Games_ section in the user guide |
| lcdgames | LCD Handheld Games | Multi (MESS) | MAME4droid 2024 Local Artwork **(Standalone)**, MAME4droid 2024 **(Standalone)**, Handheld Electronic (GW) | No | See the specific _LCD handheld games_ section in the user guide |
@@ -716,7 +761,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| n3ds | Nintendo 3DS | Citra | Citra **(Standalone)**, Citra Canary **(Standalone)**, Citra MMJ **(Standalone)**, Lime3DS **(Standalone)**, Panda3DS **(Standalone)** | No | Single ROM file |
| n64 | Nintendo 64 | Mupen64Plus-Next | M64Plus FZ **(Standalone)**, Mupen64Plus AE **(Standalone)**, ParaLLEl N64 | No | Single archive or ROM file |
| n64dd | Nintendo 64DD | Mupen64Plus-Next | M64Plus FZ **(Standalone)**, Mupen64Plus AE **(Standalone)**, ParaLLEl N64 | Yes | |
-| nds | Nintendo DS | melonDS DS | melonDS, melonDS **(Standalone)**, melonDS Nightly **(Standalone)**, DeSmuME, DeSmuME 2015, DraStic **(Standalone)** | No | Single archive or ROM file |
+| nds | Nintendo DS | melonDS DS | melonDS, melonDS **(Standalone)**, melonDS Nightly **(Standalone)**, DeSmuME, DeSmuME 2015, DraStic **(Standalone)**, NooDS **(Standalone)** | No | Single archive or ROM file |
| neogeo | SNK Neo Geo | FinalBurn Neo | Geolith, NEO.emu **(Standalone)**, MAME4droid 2024 **(Standalone)**, MAME4droid **(Standalone)** | Yes | See the specific _Arcade and Neo Geo_ section in the user guide |
| neogeocd | SNK Neo Geo CD | NeoCD | FinalBurn Neo, MAME4droid 2024 **(Standalone)** | Yes | .chd (NeoCD and MAME4droid 2024 only) or .cue file |
| neogeocdjp | SNK Neo Geo CD [Japan] | NeoCD | FinalBurn Neo, MAME4droid 2024 **(Standalone)** | Yes | .chd (NeoCD and MAME4droid 2024 only) or .cue file |
@@ -728,10 +773,10 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| openbor | OpenBOR Game Engine | OpenBOR **(Standalone)** | | No | See the specific _OpenBOR_ section in the User guide |
| oric | Tangerine Computer Systems Oric | MAME4droid 2024 **(Standalone)** | | Yes | See the specific _Tangerine Computer Systems Oric_ section in the user guide |
| palm | Palm OS | Mu | | | |
-| pc | IBM PC | DOSBox-Pure | DOSBox-Core, DOSBox-SVN | No | |
+| pc | IBM PC | DOSBox-Pure | DOSBox-Core, DOSBox-SVN, VirtualXT | No | See the specific _DOS / PC_ section in the user guide |
| pc88 | NEC PC-8800 Series | QUASI88 | | Yes | |
| pc98 | NEC PC-9800 Series | Neko Project II Kai | Neko Project II | | |
-| pcarcade | PC Arcade Systems | _Placeholder_ | | | | |
+| pcarcade | PC Arcade Systems | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| pcengine | NEC PC Engine | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | No | Single archive or ROM file |
| pcenginecd | NEC PC Engine CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | Yes | |
| pcfx | NEC PC-FX | Beetle PC-FX | | Yes | |
@@ -772,7 +817,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| supracan | Funtech Super A'Can | MAME4droid 2024 **(Standalone)** | | Yes | Single archive or ROM file. You need a supracan.zip archive that contains a valid internal_68k.bin file and an empty file named umc6650.bin |
| switch | Nintendo Switch | Skyline **(Standalone)** | | Yes | |
| symbian | Symbian | EKA2L1 **(Standalone)** | | Yes | See the specific _Symbian and Nokia N-Gage_ section in the User guide |
-| tanodragon | Tano Dragon | _Placeholder_ | | | |
+| tanodragon | Tano Dragon | MAME4droid 2024 [Tape] **(Standalone)** | MAME4droid 2024 [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
| tg16 | NEC TurboGrafx-16 | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | No | Single archive or ROM file |
| tg-cd | NEC TurboGrafx-CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, PCE.emu **(Standalone)** | Yes | |
| ti99 | Texas Instruments TI-99 | MAME4droid 2024 **(Standalone)** | | Yes | See the specific _Texas Instruments TI-99_ section in the user guide |
@@ -780,7 +825,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| to8 | Thomson TO8 | Theodore | | | |
| triforce | Namco-Sega-Nintendo Triforce | _Placeholder_ | | | |
| trs-80 | Tandy TRS-80 | _Placeholder_ | | | |
-| type-x | Taito Type X | _Placeholder_ | | | |
+| type-x | Taito Type X | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| uzebox | Uzebox Open Source Console | Uzem | | | |
| vectrex | GCE Vectrex | vecx | MAME4droid 2024 **(Standalone)** | Yes for MAME4droid 2024 | Single archive or ROM file |
| vic20 | Commodore VIC-20 | VICE xvic | | No | Single archive or tape, cartridge or diskette image file |
@@ -791,7 +836,7 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| wasm4 | WASM-4 Fantasy Console | WASM-4 | | No | Single .wasm file |
| wii | Nintendo Wii | Dolphin | Dolphin **(Standalone)**, Dolphin MMJR **(Standalone)**, Dolphin MMJR2 **(Standalone)** | No | |
| wiiu | Nintendo Wii U | _Placeholder_ | | | |
-| windows | Microsoft Windows | _Placeholder_ | | | |
+| windows | Microsoft Windows | Winlator Cmod Glibc **(Standalone)** | Winlator Cmod PRoot **(Standalone)** | No | See the _Winlator_ section elsewhere in this document |
| 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 |
@@ -801,6 +846,6 @@ The **@** symbol indicates that the emulator is _deprecated_ and will be removed
| xbox | Microsoft Xbox | _Placeholder_ | | | |
| xbox360 | Microsoft Xbox 360 | _Placeholder_ | | | |
| zmachine | Infocom Z-machine | MojoZork | | No | |
-| zx81 | Sinclair ZX81 | EightyOne | | | |
+| zx81 | Sinclair ZX81 | EightyOne | | No | |
| zxnext | Sinclair ZX Spectrum Next | _Placeholder_ | | | |
| zxspectrum | Sinclair ZX Spectrum | Fuse | Speccy **(Standalone)** | No | Single archive or ROM file |
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dca8abef1..f02e44590 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,124 @@
# ES-DE Frontend - Changelog
+## Version 3.1.1 (in development)
+
+**Release date:** TBD
+
+### Release overview
+
+3.1 maintenance release.
+
+### Detailed list of changes
+
+* Added translations for German (de_DE)
+* Added translations for Korean (ko_KR)
+* Decreased the memory footprint under some circumstances by completely freeing up video player resources after finishing view transitions
+* Added the Nanum Square Neo Korean font
+
+### Bug fixes
+
+* Attempting to view media for a game that had no downloaded media paused the playback of all static theme videos
+* Newly entered ScreenScraper username and password values were positioned incorrectly vertically in the account settings menu
+
+## Version 3.1.0 / 3.1.0-32
+
+**Release date:** 2024-09-13
+
+### Release overview
+
+This release brings full localization support and includes translations to ten new languages. More specifically these are Spanish (Spain), French, Italian, Polish, Portuguese (Brazil), Romanian, Russian, Swedish, Japanese and Simplified Chinese. More languages will follow in future releases.
+
+As part of the localization work there have been substantial changes made to the application, for instance to the text rendering which has been improved with proper text shaping using the HarfBuzz library. Case mappings and boundary analysis are now also performed by the ICU library rather than using inaccurate built-in functions as was previously the case.
+
+As for other notable improvements, entering the wrong ScreenScraper credentials will now display an error popup during scraping, specific subdirectories inside the system folders can be excluded from getting loaded, and the starting time for the screensaver has been greatly reduced on devices with poor disk I/O performance, such as Android. A number of new systems have also been enabled on Android, which brings game system support for this platform one step closer to being on par with the desktop ports.
+
+And talking of ports, this release also brings experimental support for the Haiku operating system.
+
+See the full list below for all changes and bug fixes.
+
+### Detailed list of changes
+
+* Added localization support
+* Added text shaping support using the HarfBuzz library
+* Replaced all built-in Unicode case conversion logic and lookup tables with facilities from the ICU library
+* Added translations for English (United Kingdom) (en_GB)
+* Added translations for Spanish (Spain) (es_ES)
+* Added translations for French (fr_FR)
+* Added translations for Italian (it_IT)
+* Added translations for Polish (pl_PL)
+* Added translations for Portuguese (Brazil) (pt_BR)
+* Added translations for Romanian (ro_RO)
+* Added translations for Russian (ru_RU)
+* Added translations for Swedish (sv_SE)
+* Added translations for Japanese (ja_JP)
+* Added translations for Simplified Chinese (zh_CN)
+* Dramatically reduced the start time for the video and slideshow screensavers on devices with poor disk I/O performance (like Android)
+* Added support for skipping game system subdirectories scanning on startup (by using noload.txt files)
+* Added an error popup if incorrect credentials (username and password) are used when scraping using ScreenScraper
+* Added a "Dark and red" menu color scheme to improve perceived contrast on low-contrast displays
+* (Android) Added support for the PC Arcade Systems (pcarcade) game system using the Winlator emulator
+* (Android) Added support for the Taito Type X (type-x) game system using the Winlator emulator
+* (Android) Added support for the Microsoft Windows (windows) game system using the Winlator emulator
+* (Android) Added support for the Dragon Data Dragon 32 (dragon32) game system
+* (Android) Added support for the Tano Dragon (tanodragon) game system
+* (Android) Added a new default find rule entry for Flycast as its application ID has been changed
+* (Android) Changed the find rule for Ruffle to make game launching work again after a code change in the emulator
+* (Android) Changed ePSXe to use %ROM% instead of %ROMSAF% as the latter caused game launching to fail on some devices
+* (Android) Added J2ME Loader standalone as the default emulator for the j2me system
+* (Android) Added JL-Mod standalone as an alternative emulator for the j2me system
+* (Android) Added support for launching individual games directly with EKA2L1 for the symbian system
+* Added jgenesis as an alternative emulator for the famicom, gamegear, gb, gbc, genesis, mastersystem and megacd systems on Linux and Windows
+* Added jgenesis as an alternative emulator for the megacdjp, megadrive, megadrivejp, nes, segacd, sfc, snes and snesna systems on Linux and Windows
+* Added NooDS standalone as an alternative emulator for the gba and nds systems on Android, Linux and Windows
+* Added izapple2 standalone as an alternative emulator for the apple2 system on Linux and Windows
+* Added MAME standalone as the default emulator for the dragon32 and tanodragon systems on Linux, macOS and Windows
+* Added the .7z and .zip file extensions to the dragon32 and tanodragon systems
+* Added the Stella 2023 RetroArch core as an alternative emulator for the atari2600 system
+* Added the VirtualXT RetroArch core as an alternative emulator for the dos and pc systems
+* Added the .img file extension to the dos and pc systems
+* Added the Ardens RetroArch core as an alternative emulator for the arduboy system
+* Added the .arduboy file extension to the arduboy system
+* Added support for the new Lime3DS binary names on Linux, macOS and Windows
+* (Windows) Added "Shortcut" as an alternative emulator for the switch system
+* (Windows) Added the .lnk file extension to the switch system
+* (Linux) Added a systempath find rule for the ppsspp binary name for the PPSSPP emulator
+* (Linux) Added a systempath find rule for the ryujinx binary name for the Ryujinx emulator
+* (Android) Added support for using the %BASENAME% variable with the %EXTRA% and %EXTRAARRAY% variables
+* Text within parantheses is no longer stripped out from the game name popup when adding or removing games from custom collections
+* Renamed the "Menu opening effect" setting in the UI settings menu to "Menu opening animation"
+* (linear-es-de) Added translations for all supported languages
+* (modern-es-de) Added translations for all supported languages
+* (slate-es-de) Added partial translations for all supported languages
+* Added a "backgroundMargins" property to the datetime element
+* Added a "backgroundCornerRadius" property to the datetime element
+* Added a check for whether a text element has a width defined when the container property is set
+* Added support for including theme files from within the colorScheme and fontSize tag pairs
+* Game files with only an extension and no filename will now get skipped on application startup
+* StringUtil::toCapitalized() will now capitalize text more accurately by using ICU boundary analysis
+* Removed some obsolete code from DateTimeEditComponent
+* Added the libintl library as a dependency
+* Added the HarfBuzz library as a dependency
+* Added the ICU library as a dependency
+* Refactored large parts of the text and font code
+* Added experimental support for the Haiku operating system
+* Added some improvements for building and running on FreeBSD
+* Removed support for NetBSD and OpenBSD
+* Updated SDL to 2.30.7 on Android, Windows, macOS and the Linux AppImage builds
+* Added some extra compiler checking options when building with AddressSanitizer or UndefinedBehaviorSanitizer
+* Updated the MAME index files to include ROMs up to MAME version 0.269
+* Bundled the July 2024 release of the Mozilla TLS/SSL certificates
+
+### Bug fixes
+
+* When returning from a game the helpsystem was sometimes using the dimmed theme properties
+* The StringUtil::toCapitalized() function didn't correctly capitalize multi-byte Unicode characters
+* (Windows) Video textures were sometimes not sized and aligned correctly horizontally
+* The theme engine game count text was capitalized by default instead of being set as lowercase
+* Text elements defined as gamecount using the systemdata property could not scroll horizontally
+* (linear-es-de) The system logo and carousel icon for saturnjp was incorrectly showing the western variant
+* (modern-es-de) The carousel icon for saturnjp was incorrectly showing the western variant
+* There was a typo where the 32:9 aspect ratio was referred to as 32:0
+
## Version 3.0.3 / 3.0.3-26
**Release date:** 2024-06-14
diff --git a/CMake/Packages/FindHarfBuzz.cmake b/CMake/Packages/FindHarfBuzz.cmake
new file mode 100644
index 000000000..b481fa415
--- /dev/null
+++ b/CMake/Packages/FindHarfBuzz.cmake
@@ -0,0 +1,203 @@
+# Copyright (c) 2012, Intel Corporation
+# Copyright (c) 2019 Sony Interactive Entertainment Inc.
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are met:
+#
+# * Redistributions of source code must retain the above copyright notice, this
+# list of conditions and the following disclaimer.
+# * Redistributions in binary form must reproduce the above copyright notice,
+# this list of conditions and the following disclaimer in the documentation
+# and/or other materials provided with the distribution.
+# * Neither the name of Intel Corporation nor the names of its contributors may
+# be used to endorse or promote products derived from this software without
+# specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+# POSSIBILITY OF SUCH DAMAGE.
+#
+# Try to find Harfbuzz include and library directories.
+#
+# After successful discovery, this will set for inclusion where needed:
+# HarfBuzz_INCLUDE_DIRS - containg the HarfBuzz headers
+# HarfBuzz_LIBRARIES - containg the HarfBuzz library
+
+#[=======================================================================[.rst:
+FindHarfBuzz
+--------------
+
+Find HarfBuzz headers and libraries.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+``HarfBuzz::HarfBuzz``
+ The HarfBuzz library, if found.
+
+``HarfBuzz::ICU``
+ The HarfBuzz ICU library, if found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This will define the following variables in your project:
+
+``HarfBuzz_FOUND``
+ true if (the requested version of) HarfBuzz is available.
+``HarfBuzz_VERSION``
+ the version of HarfBuzz.
+``HarfBuzz_LIBRARIES``
+ the libraries to link against to use HarfBuzz.
+``HarfBuzz_INCLUDE_DIRS``
+ where to find the HarfBuzz headers.
+``HarfBuzz_COMPILE_OPTIONS``
+ this should be passed to target_compile_options(), if the
+ target is not used for linking
+
+#]=======================================================================]
+
+find_package(PkgConfig QUIET)
+pkg_check_modules(PC_HARFBUZZ QUIET harfbuzz)
+set(HarfBuzz_COMPILE_OPTIONS ${PC_HARFBUZZ_CFLAGS_OTHER})
+set(HarfBuzz_VERSION ${PC_HARFBUZZ_CFLAGS_VERSION})
+
+find_path(HarfBuzz_INCLUDE_DIR
+ NAMES hb.h
+ HINTS ${PC_HARFBUZZ_INCLUDEDIR} ${PC_HARFBUZZ_INCLUDE_DIRS}
+ PATH_SUFFIXES harfbuzz
+)
+
+find_library(HarfBuzz_LIBRARY
+ NAMES ${HarfBuzz_NAMES} harfbuzz
+ HINTS ${PC_HARFBUZZ_LIBDIR} ${PC_HARFBUZZ_LIBRARY_DIRS}
+)
+
+if (HarfBuzz_INCLUDE_DIR AND NOT HarfBuzz_VERSION)
+ if (EXISTS "${HarfBuzz_INCLUDE_DIR}/hb-version.h")
+ file(READ "${HarfBuzz_INCLUDE_DIR}/hb-version.h" _harfbuzz_version_content)
+
+ string(REGEX MATCH "#define +HB_VERSION_STRING +\"([0-9]+\\.[0-9]+\\.[0-9]+)\"" _dummy "${_harfbuzz_version_content}")
+ set(HarfBuzz_VERSION "${CMAKE_MATCH_1}")
+ endif ()
+endif ()
+
+if ("${HarfBuzz_FIND_VERSION}" VERSION_GREATER "${HarfBuzz_VERSION}")
+ if (HarfBuzz_FIND_REQUIRED)
+ message(FATAL_ERROR
+ "Required version (" ${HarfBuzz_FIND_VERSION} ")"
+ " is higher than found version (" ${HarfBuzz_VERSION} ")")
+ else ()
+ message(WARNING
+ "Required version (" ${HarfBuzz_FIND_VERSION} ")"
+ " is higher than found version (" ${HarfBuzz_VERSION} ")")
+ unset(HarfBuzz_VERSION)
+ unset(HarfBuzz_INCLUDE_DIRS)
+ unset(HarfBuzz_LIBRARIES)
+ return ()
+ endif ()
+endif ()
+
+# Find components
+if (HarfBuzz_INCLUDE_DIR AND HarfBuzz_LIBRARY)
+ set(_HarfBuzz_REQUIRED_LIBS_FOUND ON)
+ set(HarfBuzz_LIBS_FOUND "HarfBuzz (required): ${HarfBuzz_LIBRARY}")
+else ()
+ set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
+ set(HarfBuzz_LIBS_NOT_FOUND "HarfBuzz (required)")
+endif ()
+
+if (NOT CMAKE_VERSION VERSION_LESS 3.3)
+ if ("ICU" IN_LIST HarfBuzz_FIND_COMPONENTS)
+ pkg_check_modules(PC_HARFBUZZ_ICU QUIET harfbuzz-icu)
+ set(HarfBuzz_ICU_COMPILE_OPTIONS ${PC_HARFBUZZ_ICU_CFLAGS_OTHER})
+
+ find_path(HarfBuzz_ICU_INCLUDE_DIR
+ NAMES hb-icu.h
+ HINTS ${PC_HARFBUZZ_ICU_INCLUDEDIR} ${PC_HARFBUZZ_ICU_INCLUDE_DIRS}
+ PATH_SUFFIXES harfbuzz
+ )
+
+ find_library(HarfBuzz_ICU_LIBRARY
+ NAMES ${HarfBuzz_ICU_NAMES} harfbuzz-icu
+ HINTS ${PC_HARFBUZZ_ICU_LIBDIR} ${PC_HARFBUZZ_ICU_LIBRARY_DIRS}
+ )
+
+ if (HarfBuzz_ICU_LIBRARY)
+ if (HarfBuzz_FIND_REQUIRED_ICU)
+ list(APPEND HarfBuzz_LIBS_FOUND "ICU (required): ${HarfBuzz_ICU_LIBRARY}")
+ else ()
+ list(APPEND HarfBuzz_LIBS_FOUND "ICU (optional): ${HarfBuzz_ICU_LIBRARY}")
+ endif ()
+ else ()
+ if (HarfBuzz_FIND_REQUIRED_ICU)
+ set(_HarfBuzz_REQUIRED_LIBS_FOUND OFF)
+ list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (required)")
+ else ()
+ list(APPEND HarfBuzz_LIBS_NOT_FOUND "ICU (optional)")
+ endif ()
+ endif ()
+ endif ()
+endif ()
+
+if (NOT HarfBuzz_FIND_QUIETLY)
+ if (HarfBuzz_LIBS_FOUND)
+ message(STATUS "Found the following HarfBuzz libraries:")
+ foreach (found ${HarfBuzz_LIBS_FOUND})
+ message(STATUS " ${found}")
+ endforeach ()
+ endif ()
+ if (HarfBuzz_LIBS_NOT_FOUND)
+ message(STATUS "The following HarfBuzz libraries were not found:")
+ foreach (found ${HarfBuzz_LIBS_NOT_FOUND})
+ message(STATUS " ${found}")
+ endforeach ()
+ endif ()
+endif ()
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(HarfBuzz
+ FOUND_VAR HarfBuzz_FOUND
+ REQUIRED_VARS HarfBuzz_INCLUDE_DIR HarfBuzz_LIBRARY _HarfBuzz_REQUIRED_LIBS_FOUND
+ VERSION_VAR HarfBuzz_VERSION
+)
+
+if (NOT CMAKE_VERSION VERSION_LESS 3.1)
+ if (HarfBuzz_LIBRARY AND NOT TARGET HarfBuzz::HarfBuzz)
+ add_library(HarfBuzz::HarfBuzz UNKNOWN IMPORTED GLOBAL)
+ set_target_properties(HarfBuzz::HarfBuzz PROPERTIES
+ IMPORTED_LOCATION "${HarfBuzz_LIBRARY}"
+ INTERFACE_COMPILE_OPTIONS "${HarfBuzz_COMPILE_OPTIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_INCLUDE_DIR}"
+ )
+ endif ()
+
+ if (HarfBuzz_ICU_LIBRARY AND NOT TARGET HarfBuzz::ICU)
+ add_library(HarfBuzz::ICU UNKNOWN IMPORTED GLOBAL)
+ set_target_properties(HarfBuzz::ICU PROPERTIES
+ IMPORTED_LOCATION "${HarfBuzz_ICU_LIBRARY}"
+ INTERFACE_COMPILE_OPTIONS "${HarfBuzz_ICU_COMPILE_OPTIONS}"
+ INTERFACE_INCLUDE_DIRECTORIES "${HarfBuzz_ICU_INCLUDE_DIR}"
+ )
+ endif ()
+endif ()
+
+mark_as_advanced(
+ HarfBuzz_INCLUDE_DIR
+ HarfBuzz_ICU_INCLUDE_DIR
+ HarfBuzz_LIBRARY
+ HarfBuzz_ICU_LIBRARY
+)
+
+if (HarfBuzz_FOUND)
+ set(HarfBuzz_LIBRARIES ${HarfBuzz_LIBRARY} ${HarfBuzz_ICU_LIBRARY})
+ set(HarfBuzz_INCLUDE_DIRS ${HarfBuzz_INCLUDE_DIR} ${HarfBuzz_ICU_INCLUDE_DIR})
+endif ()
diff --git a/CMake/Packages/FindICU.cmake b/CMake/Packages/FindICU.cmake
new file mode 100644
index 000000000..59dd891af
--- /dev/null
+++ b/CMake/Packages/FindICU.cmake
@@ -0,0 +1,690 @@
+# This module can find the International Components for Unicode (ICU) libraries
+#
+# Requirements:
+# - CMake >= 2.8.3 (for new version of find_package_handle_standard_args)
+#
+# The following variables will be defined for your use:
+# - ICU_FOUND : were all of your specified components found?
+# - ICU_INCLUDE_DIRS : ICU include directory
+# - ICU_LIBRARIES : ICU libraries
+# - ICU_VERSION : complete version of ICU (x.y.z)
+# - ICU_VERSION_MAJOR : major version of ICU
+# - ICU_VERSION_MINOR : minor version of ICU
+# - ICU_VERSION_PATCH : patch version of ICU
+# - ICU__FOUND : were found? (FALSE for non specified component if it is not a dependency)
+#
+# For windows or non standard installation, define ICU_ROOT_DIR variable to point to the root installation of ICU. Two ways:
+# - run cmake with -DICU_ROOT_DIR=
+# - define an environment variable with the same name before running cmake
+# With cmake-gui, before pressing "Configure":
+# 1) Press "Add Entry" button
+# 2) Add a new entry defined as:
+# - Name: ICU_ROOT_DIR
+# - Type: choose PATH in the selection list
+# - Press "..." button and select the root installation of ICU
+#
+# Example Usage:
+#
+# 1. Copy this file in the root of your project source directory
+# 2. Then, tell CMake to search this non-standard module in your project directory by adding to your CMakeLists.txt:
+# set(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR})
+# 3. Finally call find_package() once, here are some examples to pick from
+#
+# Require ICU 4.4 or later
+# find_package(ICU 4.4 REQUIRED)
+#
+# if(ICU_FOUND)
+# add_executable(myapp myapp.c)
+# include_directories(${ICU_INCLUDE_DIRS})
+# target_link_libraries(myapp ${ICU_LIBRARIES})
+# # with CMake >= 3.0.0, the last two lines can be replaced by the following
+# target_link_libraries(myapp ICU::ICU)
+# endif(ICU_FOUND)
+
+########## ##########
+
+find_package(PkgConfig QUIET)
+
+########## Private ##########
+if(NOT DEFINED ICU_PUBLIC_VAR_NS)
+ set(ICU_PUBLIC_VAR_NS "ICU") # Prefix for all ICU relative public variables
+endif(NOT DEFINED ICU_PUBLIC_VAR_NS)
+if(NOT DEFINED ICU_PRIVATE_VAR_NS)
+ set(ICU_PRIVATE_VAR_NS "_${ICU_PUBLIC_VAR_NS}") # Prefix for all ICU relative internal variables
+endif(NOT DEFINED ICU_PRIVATE_VAR_NS)
+if(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+ set(PC_ICU_PRIVATE_VAR_NS "_PC${ICU_PRIVATE_VAR_NS}") # Prefix for all pkg-config relative internal variables
+endif(NOT DEFINED PC_ICU_PRIVATE_VAR_NS)
+
+set(${ICU_PRIVATE_VAR_NS}_HINTS )
+#
+# for future removal
+if(DEFINED ENV{ICU_ROOT})
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS "$ENV{ICU_ROOT}")
+ message(AUTHOR_WARNING "ENV{ICU_ROOT} is deprecated in favor of ENV{ICU_ROOT_DIR}")
+endif(DEFINED ENV{ICU_ROOT})
+if (DEFINED ICU_ROOT)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS "${ICU_ROOT}")
+ message(AUTHOR_WARNING "ICU_ROOT is deprecated in favor of ICU_ROOT_DIR")
+endif(DEFINED ICU_ROOT)
+#
+if(DEFINED ENV{ICU_ROOT_DIR})
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS "$ENV{ICU_ROOT_DIR}")
+endif(DEFINED ENV{ICU_ROOT_DIR})
+if (DEFINED ICU_ROOT_DIR)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS "${ICU_ROOT_DIR}")
+endif(DEFINED ICU_ROOT_DIR)
+
+set(${ICU_PRIVATE_VAR_NS}_COMPONENTS )
+# ...
+macro(_icu_declare_component _NAME)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_COMPONENTS ${_NAME})
+ set("${ICU_PRIVATE_VAR_NS}_COMPONENTS_${_NAME}" ${ARGN})
+endmacro(_icu_declare_component)
+
+_icu_declare_component(data icudata)
+_icu_declare_component(uc icuuc) # Common and Data libraries
+_icu_declare_component(i18n icui18n icuin) # Internationalization library
+_icu_declare_component(io icuio ustdio) # Stream and I/O Library
+_icu_declare_component(le icule) # Layout library
+_icu_declare_component(lx iculx) # Paragraph Layout library
+
+########## Public ##########
+set(${ICU_PUBLIC_VAR_NS}_FOUND FALSE)
+set(${ICU_PUBLIC_VAR_NS}_LIBRARIES )
+set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS )
+set(${ICU_PUBLIC_VAR_NS}_C_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS "")
+set(${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS "")
+
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" FALSE) # may be done in the _icu_declare_component macro
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Check components
+if(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS) # uc required at least
+ set(${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+else(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS uc)
+ list(REMOVE_DUPLICATES ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ if(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ message(FATAL_ERROR "Unknown ICU component: ${${ICU_PRIVATE_VAR_NS}_COMPONENT}")
+ endif(NOT DEFINED ${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT})
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(NOT ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS)
+
+# if pkg-config is available check components dependencies and append `pkg-config icu- --variable=prefix` to hints
+if(PKG_CONFIG_FOUND)
+ set(${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_DUP})
+ pkg_check_modules(${PC_ICU_PRIVATE_VAR_NS} "icu-${${ICU_PRIVATE_VAR_NS}_COMPONENT}" QUIET)
+
+ if(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS ${${PC_ICU_PRIVATE_VAR_NS}_PREFIX})
+ foreach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARIES})
+ string(REGEX REPLACE "^icu" "" ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY ${${PC_ICU_PRIVATE_VAR_NS}_LIBRARY})
+ if(NOT ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY STREQUAL "data")
+ list(FIND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY} ${ICU_PRIVATE_VAR_NS}_COMPONENT_INDEX)
+ if(${ICU_PRIVATE_VAR_NS}_COMPONENT_INDEX EQUAL -1)
+ message(WARNING "Missing component dependency: ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY}. Add it to your find_package(ICU) line as COMPONENTS to fix this warning.")
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS ${${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY})
+ endif(${ICU_PRIVATE_VAR_NS}_COMPONENT_INDEX EQUAL -1)
+ endif(NOT ${PC_ICU_PRIVATE_VAR_NS}_STRIPPED_LIBRARY STREQUAL "data")
+ endforeach(${PC_ICU_PRIVATE_VAR_NS}_LIBRARY)
+ endif(${PC_ICU_PRIVATE_VAR_NS}_FOUND)
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+endif(PKG_CONFIG_FOUND)
+# list(APPEND ${ICU_PRIVATE_VAR_NS}_HINTS ENV ICU_ROOT_DIR)
+# message("${ICU_PRIVATE_VAR_NS}_HINTS = ${${ICU_PRIVATE_VAR_NS}_HINTS}")
+
+# Includes
+find_path(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR
+ NAMES unicode/utypes.h utypes.h
+ HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS}
+ PATH_SUFFIXES "include"
+ DOC "Include directories for ICU"
+)
+
+if(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR)
+ ########## ##########
+ if(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/uvernum.h") # ICU >= 4.4
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/uvernum.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/uversion.h") # ICU [2;4.4[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/uversion.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/utypes.h") # ICU [1.4;2[
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/unicode/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ elseif(EXISTS "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/utypes.h") # ICU 1.3
+ file(READ "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}/utypes.h" ${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS)
+ else()
+ message(FATAL_ERROR "ICU version header not found")
+ endif()
+
+ if(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *ICU_VERSION *\"([0-9]+)\".*") # ICU 1.3
+ # [1.3;1.4[ as #define ICU_VERSION "3" (no patch version, ie all 1.3.X versions will be detected as 1.3.0)
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR "1")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MINOR "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_PATCH "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION_MAJOR_NUM *([0-9]+).*")
+ #
+ # Since version 4.9.1, ICU release version numbering was totaly changed, see:
+ # - http://site.icu-project.org/download/49
+ # - http://userguide.icu-project.org/design#TOC-Version-Numbers-in-ICU
+ #
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_MINOR_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_VERSION_MINOR "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ string(REGEX REPLACE ".*# *define *U_ICU_VERSION_PATCHLEVEL_NUM *([0-9]+).*" "\\1" ${ICU_PUBLIC_VAR_NS}_VERSION_PATCH "${${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS}")
+ elseif(${ICU_PRIVATE_VAR_NS}_VERSION_HEADER_CONTENTS MATCHES ".*# *define *U_ICU_VERSION *\"(([0-9]+)(\\.[0-9]+)*)\".*") # ICU [1.4;1.8[
+ # [1.4;1.8[ as #define U_ICU_VERSION "1.4.1.2" but it seems that some 1.4.[12](?:\.\d)? have releasing error and appears as 1.4.0
+ set(${ICU_PRIVATE_VAR_NS}_FULL_VERSION "${CMAKE_MATCH_1}") # copy CMAKE_MATCH_1, no longer valid on the following if
+ if(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)$")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_PATCH "0")
+ elseif(${ICU_PRIVATE_VAR_NS}_FULL_VERSION MATCHES "^([0-9]+)\\.([0-9]+)\\.([0-9]+)")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR "${CMAKE_MATCH_1}")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_MINOR "${CMAKE_MATCH_2}")
+ set(${ICU_PUBLIC_VAR_NS}_VERSION_PATCH "${CMAKE_MATCH_3}")
+ endif()
+ else()
+ message(FATAL_ERROR "failed to detect ICU version")
+ endif()
+ set(${ICU_PUBLIC_VAR_NS}_VERSION "${${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR}.${${ICU_PUBLIC_VAR_NS}_VERSION_MINOR}.${${ICU_PUBLIC_VAR_NS}_VERSION_PATCH}")
+ ########## ##########
+endif(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR)
+
+# Check libraries
+if(MSVC)
+ include(SelectLibraryConfigurations)
+endif(MSVC)
+foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ if(MSVC)
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES )
+ set(${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES )
+ foreach(${ICU_PRIVATE_VAR_NS}_BASE_NAME ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}})
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}d")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR}${${ICU_PUBLIC_VAR_NS}_VERSION_MINOR}")
+ list(APPEND ${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES "${${ICU_PRIVATE_VAR_NS}_BASE_NAME}${${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR}${${ICU_PUBLIC_VAR_NS}_VERSION_MINOR}d")
+ endforeach(${ICU_PRIVATE_VAR_NS}_BASE_NAME)
+
+ find_library(
+ ${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_RELEASE
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_RELEASE_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS}
+ DOC "Release library for ICU ${${ICU_PRIVATE_VAR_NS}_COMPONENT} component"
+ )
+ find_library(
+ ${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_DEBUG
+ NAMES ${${ICU_PRIVATE_VAR_NS}_POSSIBLE_DEBUG_NAMES}
+ HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS}
+ DOC "Debug library for ICU ${${ICU_PRIVATE_VAR_NS}_COMPONENT} component"
+ )
+
+ select_library_configurations("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}")
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARY ${${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY})
+ else(MSVC)
+ find_library(
+ ${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY
+ NAMES ${${ICU_PRIVATE_VAR_NS}_COMPONENTS_${${ICU_PRIVATE_VAR_NS}_COMPONENT}}
+ PATHS ${${ICU_PRIVATE_VAR_NS}_HINTS}
+ DOC "Library for ICU ${${ICU_PRIVATE_VAR_NS}_COMPONENT} component"
+ )
+
+ if(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY)
+ set("${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_FOUND" TRUE)
+ list(APPEND ${ICU_PUBLIC_VAR_NS}_LIBRARY ${${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY})
+ endif(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY)
+ endif(MSVC)
+endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+# Try to find out compiler flags
+find_program(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE icu-config HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS})
+if(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_C_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cxxflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CXX_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+ execute_process(COMMAND ${${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE} --cppflags-dynamic OUTPUT_VARIABLE ${ICU_PUBLIC_VAR_NS}_CPP_SHARED_FLAGS OUTPUT_STRIP_TRAILING_WHITESPACE)
+endif(${ICU_PUBLIC_VAR_NS}_CONFIG_EXECUTABLE)
+
+# Check find_package arguments
+include(FindPackageHandleStandardArgs)
+if(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(
+ ${ICU_PUBLIC_VAR_NS}
+ REQUIRED_VARS ${ICU_PUBLIC_VAR_NS}_LIBRARY ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR
+ VERSION_VAR ${ICU_PUBLIC_VAR_NS}_VERSION
+ )
+else(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+ find_package_handle_standard_args(${ICU_PUBLIC_VAR_NS} "Could NOT find ICU" ${ICU_PUBLIC_VAR_NS}_LIBRARY ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR)
+endif(${ICU_PUBLIC_VAR_NS}_FIND_REQUIRED AND NOT ${ICU_PUBLIC_VAR_NS}_FIND_QUIETLY)
+
+if(${ICU_PUBLIC_VAR_NS}_FOUND)
+ #
+ # for compatibility with previous versions, alias old ICU_(MAJOR|MINOR|PATCH)_VERSION to ICU_VERSION_$1
+ set(${ICU_PUBLIC_VAR_NS}_MAJOR_VERSION ${${ICU_PUBLIC_VAR_NS}_VERSION_MAJOR})
+ set(${ICU_PUBLIC_VAR_NS}_MINOR_VERSION ${${ICU_PUBLIC_VAR_NS}_VERSION_MINOR})
+ set(${ICU_PUBLIC_VAR_NS}_PATCH_VERSION ${${ICU_PUBLIC_VAR_NS}_VERSION_PATCH})
+ #
+ set(${ICU_PUBLIC_VAR_NS}_LIBRARIES ${${ICU_PUBLIC_VAR_NS}_LIBRARY})
+ set(${ICU_PUBLIC_VAR_NS}_INCLUDE_DIRS ${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR})
+
+ if(NOT CMAKE_VERSION VERSION_LESS "3.0.0")
+ if(NOT TARGET ICU::ICU)
+ add_library(ICU::ICU INTERFACE IMPORTED)
+ endif(NOT TARGET ICU::ICU)
+ set_target_properties(ICU::ICU PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}")
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PUBLIC_VAR_NS}_FIND_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ add_library("ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" UNKNOWN IMPORTED)
+ if(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_RELEASE)
+ set_property(TARGET "ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
+ set_target_properties("ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" PROPERTIES IMPORTED_LOCATION_RELEASE "${${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_RELEASE}")
+ endif(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_RELEASE)
+ if(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_DEBUG)
+ set_property(TARGET "ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
+ set_target_properties("ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" PROPERTIES IMPORTED_LOCATION_DEBUG "${${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_DEBUG}")
+ endif(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY_DEBUG)
+ if(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY)
+ set_target_properties("ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" PROPERTIES IMPORTED_LOCATION "${${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY}")
+ endif(${ICU_PUBLIC_VAR_NS}_${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_LIBRARY)
+ set_property(TARGET ICU::ICU APPEND PROPERTY INTERFACE_LINK_LIBRARIES "ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}")
+# set_target_properties("ICU::${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}" PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR}")
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+ endif(NOT CMAKE_VERSION VERSION_LESS "3.0.0")
+endif(${ICU_PUBLIC_VAR_NS}_FOUND)
+
+mark_as_advanced(
+ ${ICU_PUBLIC_VAR_NS}_INCLUDE_DIR
+ ${ICU_PUBLIC_VAR_NS}_LIBRARY
+)
+
+########## ##########
+
+########## ##########
+
+########## Private ##########
+function(_icu_extract_locale_from_rb _BUNDLE_SOURCE _RETURN_VAR_NAME)
+ file(READ "${_BUNDLE_SOURCE}" _BUNDLE_CONTENTS)
+ string(REGEX REPLACE "//[^\n]*\n" "" _BUNDLE_CONTENTS_WITHOUT_COMMENTS ${_BUNDLE_CONTENTS})
+ string(REGEX REPLACE "[ \t\n]" "" _BUNDLE_CONTENTS_WITHOUT_COMMENTS_AND_SPACES ${_BUNDLE_CONTENTS_WITHOUT_COMMENTS})
+ string(REGEX MATCH "^([a-zA-Z_-]+)(:table)?{" LOCALE_FOUND ${_BUNDLE_CONTENTS_WITHOUT_COMMENTS_AND_SPACES})
+ set("${_RETURN_VAR_NAME}" "${CMAKE_MATCH_1}" PARENT_SCOPE)
+endfunction(_icu_extract_locale_from_rb)
+
+########## Public ##########
+
+#
+# Prototype:
+# icu_generate_resource_bundle([NAME ] [PACKAGE] [DESTINATION ] [FILES ])
+#
+# Common arguments:
+# - NAME : name of output package and to create dummy targets
+# - FILES ... : list of resource bundles sources
+# - DEPENDS ... : required to package as library (shared or static), a list of cmake parent targets to link to
+# Note: only (PREVIOUSLY DECLARED) add_executable and add_library as dependencies
+# - DESTINATION : optional, directory where to install final binary file(s)
+# - FORMAT : optional, one of none (ICU4C binary format, default), java (plain java) or xliff (XML), see below
+#
+# Arguments depending on FORMAT:
+# - none (default):
+# * PACKAGE : if present, package all resource bundles together. Default is to stop after building individual *.res files
+# * TYPE : one of :
+# + common or archive (default) : archive all ressource bundles into a single .dat file
+# + library or dll : assemble all ressource bundles into a separate and loadable library (.dll/.so)
+# + static : integrate all ressource bundles to targets designed by DEPENDS parameter (as a static library)
+# * NO_SHARED_FLAGS : only with TYPE in ['library', 'dll', 'static'], do not append ICU_C(XX)_SHARED_FLAGS to targets given as DEPENDS argument
+# - JAVA:
+# * BUNDLE : required, prefix for generated classnames
+# - XLIFF:
+# (none)
+#
+
+#
+# For an archive, the idea is to generate the following dependencies:
+#
+# root.txt => root.res \
+# |
+# en.txt => en.res |
+# | => pkglist.txt => application.dat
+# fr.txt => fr.res |
+# |
+# and so on /
+#
+# Lengend: 'A => B' means B depends on A
+#
+# Steps (correspond to arrows):
+# 1) genrb (from .txt to .res)
+# 2) generate a file text (pkglist.txt) with all .res files to put together
+# 3) build final archive (from *.res/pkglist.txt to .dat)
+#
+
+function(icu_generate_resource_bundle)
+
+ ##### #####
+ find_program(${ICU_PUBLIC_VAR_NS}_GENRB_EXECUTABLE genrb HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS})
+ find_program(${ICU_PUBLIC_VAR_NS}_PKGDATA_EXECUTABLE pkgdata HINTS ${${ICU_PRIVATE_VAR_NS}_HINTS})
+
+ if(NOT ${ICU_PUBLIC_VAR_NS}_GENRB_EXECUTABLE)
+ message(FATAL_ERROR "genrb not found")
+ endif(NOT ${ICU_PUBLIC_VAR_NS}_GENRB_EXECUTABLE)
+ if(NOT ${ICU_PUBLIC_VAR_NS}_PKGDATA_EXECUTABLE)
+ message(FATAL_ERROR "pkgdata not found")
+ endif(NOT ${ICU_PUBLIC_VAR_NS}_PKGDATA_EXECUTABLE)
+ ##### #####
+
+ ##### #####
+ set(TARGET_SEPARATOR "+")
+ set(__FUNCTION__ "icu_generate_resource_bundle")
+ set(PACKAGE_TARGET_PREFIX "ICU${TARGET_SEPARATOR}PKG")
+ set(RESOURCE_TARGET_PREFIX "ICU${TARGET_SEPARATOR}RB")
+ ##### #####
+
+ ##### #####
+ # filename extension of built resource bundle (without dot)
+ set(BUNDLES__SUFFIX "res")
+ set(BUNDLES_JAVA_SUFFIX "java")
+ set(BUNDLES_XLIFF_SUFFIX "xlf")
+ # alias: none (default) = common = archive ; dll = library ; static
+ set(PKGDATA__ALIAS "")
+ set(PKGDATA_COMMON_ALIAS "")
+ set(PKGDATA_ARCHIVE_ALIAS "")
+ set(PKGDATA_DLL_ALIAS "LIBRARY")
+ set(PKGDATA_LIBRARY_ALIAS "LIBRARY")
+ set(PKGDATA_STATIC_ALIAS "STATIC")
+ # filename prefix of built package
+ set(PKGDATA__PREFIX "")
+ set(PKGDATA_LIBRARY_PREFIX "${CMAKE_SHARED_LIBRARY_PREFIX}")
+ set(PKGDATA_STATIC_PREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
+ # filename extension of built package (with dot)
+ set(PKGDATA__SUFFIX ".dat")
+ set(PKGDATA_LIBRARY_SUFFIX "${CMAKE_SHARED_LIBRARY_SUFFIX}")
+ set(PKGDATA_STATIC_SUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
+ # pkgdata option mode specific
+ set(PKGDATA__OPTIONS "-m" "common")
+ set(PKGDATA_STATIC_OPTIONS "-m" "static")
+ set(PKGDATA_LIBRARY_OPTIONS "-m" "library")
+ # cmake library type for output package
+ set(PKGDATA_LIBRARY__TYPE "")
+ set(PKGDATA_LIBRARY_STATIC_TYPE STATIC)
+ set(PKGDATA_LIBRARY_LIBRARY_TYPE SHARED)
+ ##### #####
+
+ include(CMakeParseArguments)
+ cmake_parse_arguments(
+ PARSED_ARGS # output variable name
+ # options (true/false) (default value: false)
+ "PACKAGE;NO_SHARED_FLAGS"
+ # univalued parameters (default value: "")
+ "NAME;DESTINATION;TYPE;FORMAT;BUNDLE"
+ # multivalued parameters (default value: "")
+ "FILES;DEPENDS"
+ ${ARGN}
+ )
+
+ # assert(${PARSED_ARGS_NAME} != "")
+ if(NOT PARSED_ARGS_NAME)
+ message(FATAL_ERROR "${__FUNCTION__}(): no name given, NAME parameter missing")
+ endif(NOT PARSED_ARGS_NAME)
+
+ # assert(length(PARSED_ARGS_FILES) > 0)
+ list(LENGTH PARSED_ARGS_FILES PARSED_ARGS_FILES_LEN)
+ if(PARSED_ARGS_FILES_LEN LESS 1)
+ message(FATAL_ERROR "${__FUNCTION__}() expects at least 1 resource bundle as FILES argument, 0 given")
+ endif(PARSED_ARGS_FILES_LEN LESS 1)
+
+ string(TOUPPER "${PARSED_ARGS_FORMAT}" UPPER_FORMAT)
+ # assert(${UPPER_FORMAT} in ['', 'java', 'xlif'])
+ if(NOT DEFINED BUNDLES_${UPPER_FORMAT}_SUFFIX)
+ message(FATAL_ERROR "${__FUNCTION__}(): unknown FORMAT '${PARSED_ARGS_FORMAT}'")
+ endif(NOT DEFINED BUNDLES_${UPPER_FORMAT}_SUFFIX)
+
+ if(UPPER_FORMAT STREQUAL "JAVA")
+ # assert(${PARSED_ARGS_BUNDLE} != "")
+ if(NOT PARSED_ARGS_BUNDLE)
+ message(FATAL_ERROR "${__FUNCTION__}(): java bundle name expected, BUNDLE parameter missing")
+ endif(NOT PARSED_ARGS_BUNDLE)
+ endif(UPPER_FORMAT STREQUAL "JAVA")
+
+ if(PARSED_ARGS_PACKAGE)
+ # assert(${PARSED_ARGS_FORMAT} == "")
+ if(PARSED_ARGS_FORMAT)
+ message(FATAL_ERROR "${__FUNCTION__}(): packaging is only supported for binary format, not xlif neither java outputs")
+ endif(PARSED_ARGS_FORMAT)
+
+ string(TOUPPER "${PARSED_ARGS_TYPE}" UPPER_MODE)
+ # assert(${UPPER_MODE} in ['', 'common', 'archive', 'dll', library'])
+ if(NOT DEFINED PKGDATA_${UPPER_MODE}_ALIAS)
+ message(FATAL_ERROR "${__FUNCTION__}(): unknown TYPE '${PARSED_ARGS_TYPE}'")
+ else(NOT DEFINED PKGDATA_${UPPER_MODE}_ALIAS)
+ set(TYPE "${PKGDATA_${UPPER_MODE}_ALIAS}")
+ endif(NOT DEFINED PKGDATA_${UPPER_MODE}_ALIAS)
+
+ # Package name: strip file extension if present
+ get_filename_component(PACKAGE_NAME_WE ${PARSED_ARGS_NAME} NAME_WE)
+ # Target name to build package
+ set(PACKAGE_TARGET_NAME "${PACKAGE_TARGET_PREFIX}${TARGET_SEPARATOR}${PACKAGE_NAME_WE}")
+ # Target name to build intermediate list file
+ set(PACKAGE_LIST_TARGET_NAME "${PACKAGE_TARGET_NAME}${TARGET_SEPARATOR}PKGLIST")
+ # Directory (absolute) to set as "current directory" for genrb (does not include package directory, -p)
+ # We make our "cook" there to prevent any conflict
+ if(DEFINED CMAKE_PLATFORM_ROOT_BIN) # CMake < 2.8.10
+ set(RESOURCE_GENRB_CHDIR_DIR "${CMAKE_PLATFORM_ROOT_BIN}/${PACKAGE_TARGET_NAME}.dir/")
+ else(DEFINED CMAKE_PLATFORM_ROOT_BIN) # CMake >= 2.8.10
+ set(RESOURCE_GENRB_CHDIR_DIR "${CMAKE_PLATFORM_INFO_DIR}/${PACKAGE_TARGET_NAME}.dir/")
+ endif(DEFINED CMAKE_PLATFORM_ROOT_BIN)
+ # Directory (absolute) where resource bundles are built: concatenation of RESOURCE_GENRB_CHDIR_DIR and package name
+ set(RESOURCE_OUTPUT_DIR "${RESOURCE_GENRB_CHDIR_DIR}/${PACKAGE_NAME_WE}/")
+ # Output (relative) path for built package
+ if(MSVC AND TYPE STREQUAL PKGDATA_LIBRARY_ALIAS)
+ set(PACKAGE_OUTPUT_PATH "${RESOURCE_GENRB_CHDIR_DIR}/${PACKAGE_NAME_WE}/${PKGDATA_${TYPE}_PREFIX}${PACKAGE_NAME_WE}${PKGDATA_${TYPE}_SUFFIX}")
+ else(MSVC AND TYPE STREQUAL PKGDATA_LIBRARY_ALIAS)
+ set(PACKAGE_OUTPUT_PATH "${RESOURCE_GENRB_CHDIR_DIR}/${PKGDATA_${TYPE}_PREFIX}${PACKAGE_NAME_WE}${PKGDATA_${TYPE}_SUFFIX}")
+ endif(MSVC AND TYPE STREQUAL PKGDATA_LIBRARY_ALIAS)
+ # Output (absolute) path for the list file
+ set(PACKAGE_LIST_OUTPUT_PATH "${RESOURCE_GENRB_CHDIR_DIR}/pkglist.txt")
+
+ file(MAKE_DIRECTORY "${RESOURCE_OUTPUT_DIR}")
+ else(PARSED_ARGS_PACKAGE)
+ set(RESOURCE_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/")
+# set(RESOURCE_GENRB_CHDIR_DIR "UNUSED")
+ endif(PARSED_ARGS_PACKAGE)
+
+ set(TARGET_RESOURCES )
+ set(COMPILED_RESOURCES_PATH )
+ set(COMPILED_RESOURCES_BASENAME )
+ foreach(RESOURCE_SOURCE ${PARSED_ARGS_FILES})
+ _icu_extract_locale_from_rb(${RESOURCE_SOURCE} RESOURCE_NAME_WE)
+ get_filename_component(SOURCE_BASENAME ${RESOURCE_SOURCE} NAME)
+ get_filename_component(ABSOLUTE_SOURCE ${RESOURCE_SOURCE} ABSOLUTE)
+
+ if(UPPER_FORMAT STREQUAL "XLIFF")
+ if(RESOURCE_NAME_WE STREQUAL "root")
+ set(XLIFF_LANGUAGE "en")
+ else(RESOURCE_NAME_WE STREQUAL "root")
+ string(REGEX REPLACE "[^a-z].*$" "" XLIFF_LANGUAGE "${RESOURCE_NAME_WE}")
+ endif(RESOURCE_NAME_WE STREQUAL "root")
+ endif(UPPER_FORMAT STREQUAL "XLIFF")
+
+ ##### #####
+ set(RESOURCE_TARGET_NAME "${RESOURCE_TARGET_PREFIX}${TARGET_SEPARATOR}${PARSED_ARGS_NAME}${TARGET_SEPARATOR}${RESOURCE_NAME_WE}")
+
+ set(RESOURCE_OUTPUT__PATH "${RESOURCE_NAME_WE}.res")
+ if(RESOURCE_NAME_WE STREQUAL "root")
+ set(RESOURCE_OUTPUT_JAVA_PATH "${PARSED_ARGS_BUNDLE}.java")
+ else(RESOURCE_NAME_WE STREQUAL "root")
+ set(RESOURCE_OUTPUT_JAVA_PATH "${PARSED_ARGS_BUNDLE}_${RESOURCE_NAME_WE}.java")
+ endif(RESOURCE_NAME_WE STREQUAL "root")
+ set(RESOURCE_OUTPUT_XLIFF_PATH "${RESOURCE_NAME_WE}.xlf")
+
+ set(GENRB__OPTIONS "")
+ set(GENRB_JAVA_OPTIONS "-j" "-b" "${PARSED_ARGS_BUNDLE}")
+ set(GENRB_XLIFF_OPTIONS "-x" "-l" "${XLIFF_LANGUAGE}")
+ ##### #####
+
+ # build .txt from .res
+ if(PARSED_ARGS_PACKAGE)
+ add_custom_command(
+ OUTPUT "${RESOURCE_OUTPUT_DIR}${RESOURCE_OUTPUT_${UPPER_FORMAT}_PATH}"
+ COMMAND ${CMAKE_COMMAND} -E chdir ${RESOURCE_GENRB_CHDIR_DIR} ${${ICU_PUBLIC_VAR_NS}_GENRB_EXECUTABLE} ${GENRB_${UPPER_FORMAT}_OPTIONS} -d ${PACKAGE_NAME_WE} ${ABSOLUTE_SOURCE}
+ DEPENDS ${RESOURCE_SOURCE}
+ )
+ else(PARSED_ARGS_PACKAGE)
+ add_custom_command(
+ OUTPUT "${RESOURCE_OUTPUT_DIR}${RESOURCE_OUTPUT_${UPPER_FORMAT}_PATH}"
+ COMMAND ${${ICU_PUBLIC_VAR_NS}_GENRB_EXECUTABLE} ${GENRB_${UPPER_FORMAT}_OPTIONS} -d ${RESOURCE_OUTPUT_DIR} ${ABSOLUTE_SOURCE}
+ DEPENDS ${RESOURCE_SOURCE}
+ )
+ endif(PARSED_ARGS_PACKAGE)
+ # dummy target (ICU+RB++) for each locale to build the .res file from its .txt by the add_custom_command above
+ add_custom_target(
+ "${RESOURCE_TARGET_NAME}" ALL
+ COMMENT ""
+ DEPENDS "${RESOURCE_OUTPUT_DIR}${RESOURCE_OUTPUT_${UPPER_FORMAT}_PATH}"
+ SOURCES ${RESOURCE_SOURCE}
+ )
+
+ if(PARSED_ARGS_DESTINATION AND NOT PARSED_ARGS_PACKAGE)
+ install(FILES "${RESOURCE_OUTPUT_DIR}${RESOURCE_OUTPUT_${UPPER_FORMAT}_PATH}" DESTINATION ${PARSED_ARGS_DESTINATION} PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+ endif(PARSED_ARGS_DESTINATION AND NOT PARSED_ARGS_PACKAGE)
+
+ list(APPEND TARGET_RESOURCES "${RESOURCE_TARGET_NAME}")
+ list(APPEND COMPILED_RESOURCES_PATH "${RESOURCE_OUTPUT_DIR}${RESOURCE_OUTPUT_${UPPER_FORMAT}_PATH}")
+ list(APPEND COMPILED_RESOURCES_BASENAME "${RESOURCE_NAME_WE}.${BUNDLES_${UPPER_FORMAT}_SUFFIX}")
+ endforeach(RESOURCE_SOURCE)
+ # convert semicolon separated list to a space separated list
+ # NOTE: if the pkglist.txt file starts (or ends?) with a whitespace, pkgdata add an undefined symbol (named _) for it
+ string(REPLACE ";" " " COMPILED_RESOURCES_BASENAME "${COMPILED_RESOURCES_BASENAME}")
+
+ if(PARSED_ARGS_PACKAGE)
+ # create a text file (pkglist.txt) with the list of the *.res to package together
+ add_custom_command(
+ OUTPUT "${PACKAGE_LIST_OUTPUT_PATH}"
+ COMMAND ${CMAKE_COMMAND} -E echo "${COMPILED_RESOURCES_BASENAME}" > "${PACKAGE_LIST_OUTPUT_PATH}"
+ DEPENDS ${COMPILED_RESOURCES_PATH}
+ )
+ # run pkgdata from pkglist.txt
+ add_custom_command(
+ OUTPUT "${PACKAGE_OUTPUT_PATH}"
+ COMMAND ${CMAKE_COMMAND} -E chdir ${RESOURCE_GENRB_CHDIR_DIR} ${${ICU_PUBLIC_VAR_NS}_PKGDATA_EXECUTABLE} -F ${PKGDATA_${TYPE}_OPTIONS} -s ${PACKAGE_NAME_WE} -p ${PACKAGE_NAME_WE} ${PACKAGE_LIST_OUTPUT_PATH}
+ DEPENDS "${PACKAGE_LIST_OUTPUT_PATH}"
+ VERBATIM
+ )
+ if(PKGDATA_LIBRARY_${TYPE}_TYPE)
+ # assert(${PARSED_ARGS_DEPENDS} != "")
+ if(NOT PARSED_ARGS_DEPENDS)
+ message(FATAL_ERROR "${__FUNCTION__}(): static and library mode imply a list of targets to link to, DEPENDS parameter missing")
+ endif(NOT PARSED_ARGS_DEPENDS)
+ add_library(${PACKAGE_TARGET_NAME} ${PKGDATA_LIBRARY_${TYPE}_TYPE} IMPORTED)
+ if(MSVC)
+ string(REGEX REPLACE "${PKGDATA_LIBRARY_SUFFIX}\$" "${CMAKE_IMPORT_LIBRARY_SUFFIX}" PACKAGE_OUTPUT_LIB "${PACKAGE_OUTPUT_PATH}")
+ set_target_properties(${PACKAGE_TARGET_NAME} PROPERTIES IMPORTED_LOCATION ${PACKAGE_OUTPUT_PATH} IMPORTED_IMPLIB ${PACKAGE_OUTPUT_LIB})
+ else(MSVC)
+ set_target_properties(${PACKAGE_TARGET_NAME} PROPERTIES IMPORTED_LOCATION ${PACKAGE_OUTPUT_PATH})
+ endif(MSVC)
+ foreach(DEPENDENCY ${PARSED_ARGS_DEPENDS})
+ target_link_libraries(${DEPENDENCY} ${PACKAGE_TARGET_NAME})
+ if(NOT PARSED_ARGS_NO_SHARED_FLAGS)
+ get_property(ENABLED_LANGUAGES GLOBAL PROPERTY ENABLED_LANGUAGES)
+ list(LENGTH "${ENABLED_LANGUAGES}" ENABLED_LANGUAGES_LENGTH)
+ if(ENABLED_LANGUAGES_LENGTH GREATER 1)
+ message(WARNING "Project has more than one language enabled, skip automatic shared flags appending")
+ else(ENABLED_LANGUAGES_LENGTH GREATER 1)
+ set_property(TARGET "${DEPENDENCY}" APPEND PROPERTY COMPILE_FLAGS "${${ICU_PUBLIC_VAR_NS}_${ENABLED_LANGUAGES}_SHARED_FLAGS}")
+ endif(ENABLED_LANGUAGES_LENGTH GREATER 1)
+ endif(NOT PARSED_ARGS_NO_SHARED_FLAGS)
+ endforeach(DEPENDENCY)
+ # http://www.mail-archive.com/cmake-commits@cmake.org/msg01135.html
+ set(PACKAGE_INTERMEDIATE_TARGET_NAME "${PACKAGE_TARGET_NAME}${TARGET_SEPARATOR}DUMMY")
+ # dummy intermediate target (ICU+PKG++DUMMY) to link the package to the produced library by running pkgdata (see add_custom_command above)
+ add_custom_target(
+ ${PACKAGE_INTERMEDIATE_TARGET_NAME}
+ COMMENT ""
+ DEPENDS "${PACKAGE_OUTPUT_PATH}"
+ )
+ add_dependencies("${PACKAGE_TARGET_NAME}" "${PACKAGE_INTERMEDIATE_TARGET_NAME}")
+ else(PKGDATA_LIBRARY_${TYPE}_TYPE)
+ # dummy target (ICU+PKG+) to run pkgdata (see add_custom_command above)
+ add_custom_target(
+ "${PACKAGE_TARGET_NAME}" ALL
+ COMMENT ""
+ DEPENDS "${PACKAGE_OUTPUT_PATH}"
+ )
+ endif(PKGDATA_LIBRARY_${TYPE}_TYPE)
+ # dummy target (ICU+PKG++PKGLIST) to build the file pkglist.txt
+ add_custom_target(
+ "${PACKAGE_LIST_TARGET_NAME}" ALL
+ COMMENT ""
+ DEPENDS "${PACKAGE_LIST_OUTPUT_PATH}"
+ )
+ # package => pkglist.txt
+ add_dependencies("${PACKAGE_TARGET_NAME}" "${PACKAGE_LIST_TARGET_NAME}")
+ # pkglist.txt => *.res
+ add_dependencies("${PACKAGE_LIST_TARGET_NAME}" ${TARGET_RESOURCES})
+
+ if(PARSED_ARGS_DESTINATION)
+ install(FILES "${PACKAGE_OUTPUT_PATH}" DESTINATION ${PARSED_ARGS_DESTINATION} PERMISSIONS OWNER_READ GROUP_READ WORLD_READ)
+ endif(PARSED_ARGS_DESTINATION)
+ endif(PARSED_ARGS_PACKAGE)
+
+endfunction(icu_generate_resource_bundle)
+
+########## ##########
+
+########## ##########
+
+if(${ICU_PUBLIC_VAR_NS}_DEBUG)
+
+ function(icudebug _VARNAME)
+ if(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ${${ICU_PUBLIC_VAR_NS}_${_VARNAME}}")
+ else(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ message("${ICU_PUBLIC_VAR_NS}_${_VARNAME} = ")
+ endif(DEFINED ${ICU_PUBLIC_VAR_NS}_${_VARNAME})
+ endfunction(icudebug)
+
+ # IN (args)
+ icudebug("FIND_COMPONENTS")
+ icudebug("FIND_REQUIRED")
+ icudebug("FIND_QUIETLY")
+ icudebug("FIND_VERSION")
+
+ # OUT
+ # Found
+ icudebug("FOUND")
+ # Flags
+ icudebug("C_FLAGS")
+ icudebug("CPP_FLAGS")
+ icudebug("CXX_FLAGS")
+ icudebug("C_SHARED_FLAGS")
+ icudebug("CPP_SHARED_FLAGS")
+ icudebug("CXX_SHARED_FLAGS")
+ # Linking
+ icudebug("INCLUDE_DIRS")
+ icudebug("LIBRARIES")
+ # Version
+ icudebug("VERSION_MAJOR")
+ icudebug("VERSION_MINOR")
+ icudebug("VERSION_PATCH")
+ icudebug("VERSION")
+ # _(FOUND|LIBRARY)
+ set(${ICU_PRIVATE_VAR_NS}_COMPONENT_VARIABLES "FOUND" "LIBRARY" "LIBRARY_RELEASE" "LIBRARY_DEBUG")
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT ${${ICU_PRIVATE_VAR_NS}_COMPONENTS})
+ string(TOUPPER "${${ICU_PRIVATE_VAR_NS}_COMPONENT}" ${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT)
+ foreach(${ICU_PRIVATE_VAR_NS}_COMPONENT_VARIABLE ${${ICU_PRIVATE_VAR_NS}_COMPONENT_VARIABLES})
+ icudebug("${${ICU_PRIVATE_VAR_NS}_UPPER_COMPONENT}_${${ICU_PRIVATE_VAR_NS}_COMPONENT_VARIABLE}")
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT_VARIABLE)
+ endforeach(${ICU_PRIVATE_VAR_NS}_COMPONENT)
+
+endif(${ICU_PUBLIC_VAR_NS}_DEBUG)
+
+########## ##########
diff --git a/CMake/Packages/FindIntl.cmake b/CMake/Packages/FindIntl.cmake
new file mode 100644
index 000000000..7640397de
--- /dev/null
+++ b/CMake/Packages/FindIntl.cmake
@@ -0,0 +1,60 @@
+# Distributed under the OSI-approved BSD 3-Clause License. See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindIntl
+--------
+
+Find the Gettext libintl headers and libraries.
+
+This module reports information about the Gettext libintl
+installation in several variables. General variables::
+
+ Intl_FOUND - true if the libintl headers and libraries were found
+ Intl_INCLUDE_DIRS - the directory containing the libintl headers
+ Intl_LIBRARIES - libintl libraries to be linked
+
+The following cache variables may also be set::
+
+ Intl_INCLUDE_DIR - the directory containing the libintl headers
+ Intl_LIBRARY - the libintl library (if any)
+
+.. note::
+ On some platforms, such as Linux with GNU libc, the gettext
+ functions are present in the C standard library and libintl
+ is not required. ``Intl_LIBRARIES`` will be empty in this
+ case.
+
+.. note::
+ If you wish to use the Gettext tools (``msgmerge``,
+ ``msgfmt``, etc.), use :module:`FindGettext`.
+#]=======================================================================]
+
+
+# Written by Roger Leigh
+
+# Find include directory
+find_path(Intl_INCLUDE_DIR
+ NAMES "libintl.h"
+ DOC "libintl include directory")
+mark_as_advanced(Intl_INCLUDE_DIR)
+
+# Find all Intl libraries
+find_library(Intl_LIBRARY "intl"
+ DOC "libintl libraries (if not in the C library)")
+mark_as_advanced(Intl_LIBRARY)
+
+include(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(Intl
+ FOUND_VAR Intl_FOUND
+ REQUIRED_VARS Intl_INCLUDE_DIR
+ FAIL_MESSAGE "Failed to find Gettext libintl")
+
+if(Intl_FOUND)
+ set(Intl_INCLUDE_DIRS "${Intl_INCLUDE_DIR}")
+ if(Intl_LIBRARY)
+ set(Intl_LIBRARIES "${Intl_LIBRARY}")
+ else()
+ unset(Intl_LIBRARIES)
+ endif()
+endif()
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 4fc6fd6c3..7151a1bde 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,7 +19,7 @@ endif()
project(es-de)
# Application version, update this when making a new release.
-set(ES_VERSION 3.0.3)
+set(ES_VERSION 3.1.1-alpha)
# 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)
@@ -35,6 +35,7 @@ list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/CMake/Utils
option(GL "Set to ON if targeting Desktop OpenGL" ON)
option(GLES "Set to ON if targeting OpenGL ES" OFF)
option(APPLICATION_UPDATER "Set to OFF to build without the application updater" ON)
+option(COMPILE_LOCALIZATIONS "Set to OFF to skip compilation of localization message catalogs" ON)
option(APPIMAGE_BUILD "Set to ON when building as an AppImage" OFF)
option(AUR_BUILD "Set to ON when building for the AUR" OFF)
option(FLATPAK_BUILD "Set to ON when building as a Flatpak" OFF)
@@ -136,6 +137,9 @@ elseif(NOT EMSCRIPTEN AND NOT ANDROID)
find_package(FFmpeg REQUIRED)
find_package(FreeImage REQUIRED)
find_package(Freetype REQUIRED)
+ find_package(HarfBuzz REQUIRED)
+ find_package(ICU REQUIRED)
+ find_package(Intl REQUIRED)
find_package(Libgit2 REQUIRED)
find_package(Pugixml REQUIRED)
find_package(SDL2 REQUIRED)
@@ -213,7 +217,8 @@ else()
endif()
endif()
-if(APPLE AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
+# Silence some annoying warnings caused by invalid characters in some FreeImage source comments.
+if(CMAKE_CXX_COMPILER_ID MATCHES Clang AND CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 15.0.0)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-invalid-utf8")
endif()
@@ -269,6 +274,11 @@ if(UBSAN)
endif()
endif()
+if(ASAN OR UBSAN)
+ # Add some extra checks when building with AddressSanitizer or UndefinedBehaviorSanitizer.
+ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_GLIBCXX_ASSERTIONS -D_FORTIFY_SOURCE=3")
+endif()
+
# The following removes half of the ranlib warnings on macOS regarding no symbols for files
# that are #ifdef'ed away. There must be a way to remove the other half as well?
if(APPLE)
@@ -284,6 +294,7 @@ endif()
if(ANDROID)
set(BUNDLED_CERTS ON)
+ set(COMPILE_LOCALIZATIONS OFF)
add_compile_definitions(ANDROID_VERSION_CODE=${ANDROID_VERSION_CODE})
add_compile_definitions(ANDROID_APPLICATION_ID="org.es_de.frontend")
endif()
@@ -359,19 +370,15 @@ if(VIDEO_HW_DECODING)
endif()
if(DEINIT_ON_LAUNCH)
- if(CMAKE_SYSTEM_NAME MATCHES Linux)
+ if(CMAKE_SYSTEM_NAME MATCHES Linux OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)
add_compile_definitions(DEINIT_ON_LAUNCH)
message("-- Building with deinitialization on game launch")
else()
- message(FATAL_ERROR "-- Deinitialization on game launch can only be used on Linux")
+ message(FATAL_ERROR "-- Deinitialization on game launch can only be used on Linux and FreeBSD")
endif()
endif()
-if(AUR_BUILD OR FLATPAK_BUILD OR RETRODECK OR RPI)
- set(APPLICATION_UPDATER OFF)
-endif()
-
-if(CMAKE_SYSTEM_NAME MATCHES FreeBSD OR CMAKE_SYSTEM_NAME MATCHES NetBSD OR CMAKE_SYSTEM_NAME MATCHES OpenBSD)
+if(AUR_BUILD OR FLATPAK_BUILD OR RETRODECK OR RPI OR HAIKU OR CMAKE_SYSTEM_NAME MATCHES FreeBSD)
set(APPLICATION_UPDATER OFF)
endif()
@@ -424,13 +431,11 @@ add_compile_definitions(GLM_FORCE_CXX17)
add_compile_definitions(GLM_FORCE_XYZW_ONLY)
# 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 and /usr/local on FreeBSD.
if(NOT WIN32 AND NOT APPLE AND NOT ANDROID)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
if(CMAKE_SYSTEM_NAME MATCHES Linux)
set(CMAKE_INSTALL_PREFIX /usr CACHE INTERNAL CMAKE_INSTALL_PREFIX)
- elseif(CMAKE_SYSTEM_NAME MATCHES NetBSD)
- set(CMAKE_INSTALL_PREFIX /usr/pkg CACHE INTERNAL CMAKE_INSTALL_PREFIX)
else()
set(CMAKE_INSTALL_PREFIX /usr/local CACHE INTERNAL CMAKE_INSTALL_PREFIX)
endif()
@@ -463,7 +468,10 @@ if(APPLE)
${CMAKE_CURRENT_SOURCE_DIR}/external/FFmpeg
${CMAKE_CURRENT_SOURCE_DIR}/external/freeimage/FreeImage/Source
${CMAKE_CURRENT_SOURCE_DIR}/external/freetype/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/gettext/gettext-runtime/intl
${CMAKE_CURRENT_SOURCE_DIR}/external/libgit2/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/harfbuzz/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/icu/icu4c/source/common
${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL)
elseif(WIN32)
@@ -473,6 +481,9 @@ elseif(WIN32)
${CMAKE_CURRENT_SOURCE_DIR}/external/ffmpeg/include
${CMAKE_CURRENT_SOURCE_DIR}/external/FreeImage/Dist/x64
${CMAKE_CURRENT_SOURCE_DIR}/external/freetype/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/gettext/include
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/harfbuzz/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/icu/icu4c/source/common
${CMAKE_CURRENT_SOURCE_DIR}/external/libgit2/include
${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL2)
@@ -489,6 +500,9 @@ elseif(ANDROID)
${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/gettext/gettext-runtime/intl
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/harfbuzz/src
+ ${CMAKE_CURRENT_SOURCE_DIR}/external/icu/icu4c/source/common
${CMAKE_CURRENT_SOURCE_DIR}/external/libgit2/include
${CMAKE_CURRENT_SOURCE_DIR}/external/pugixml/src
${CMAKE_CURRENT_SOURCE_DIR}/external/SDL_Android)
@@ -498,6 +512,8 @@ else()
${FreeImage_INCLUDE_DIRS}
${FREETYPE_INCLUDE_DIRS}
${GIT2_INCLUDE_PATH}
+ ${HarfBuzz_INCLUDE_DIRS}
+ ${ICU_INCLUDE_DIRS}
${PUGIXML_INCLUDE_DIRS}
${SDL2_INCLUDE_DIR})
endif()
@@ -534,6 +550,11 @@ if(APPLE)
${PROJECT_SOURCE_DIR}/libfreeimage.a
${PROJECT_SOURCE_DIR}/libfreetype.6.dylib
${PROJECT_SOURCE_DIR}/libgit2.1.7.dylib
+ ${PROJECT_SOURCE_DIR}/libharfbuzz.dylib
+ ${PROJECT_SOURCE_DIR}/libicudata.75.dylib
+ ${PROJECT_SOURCE_DIR}/libicui18n.75.dylib
+ ${PROJECT_SOURCE_DIR}/libicuuc.75.dylib
+ ${PROJECT_SOURCE_DIR}/libintl.8.dylib
${PROJECT_SOURCE_DIR}/libpugixml.a
${PROJECT_SOURCE_DIR}/libSDL2-2.0.0.dylib)
elseif(WIN32)
@@ -546,7 +567,12 @@ elseif(WIN32)
${PROJECT_SOURCE_DIR}/FreeImage.lib
${PROJECT_SOURCE_DIR}/git2.lib
${PROJECT_SOURCE_DIR}/glew32.lib
+ ${PROJECT_SOURCE_DIR}/harfbuzz.lib
+ ${PROJECT_SOURCE_DIR}/icudt.lib
+ ${PROJECT_SOURCE_DIR}/icuin.lib
+ ${PROJECT_SOURCE_DIR}/icuuc.lib
${PROJECT_SOURCE_DIR}/libcurl-x64.lib
+ ${PROJECT_SOURCE_DIR}/libintl-8.lib
${PROJECT_SOURCE_DIR}/freetype.lib
${PROJECT_SOURCE_DIR}/lunasvg.lib
${PROJECT_SOURCE_DIR}/pugixml.lib
@@ -569,6 +595,11 @@ elseif(ANDROID)
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libfreeimage.so
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libfreetype.so
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libgit2.so
+ ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libharfbuzz.so
+ ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libicudata.a
+ ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libicui18n.a
+ ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libicuuc.a
+ ${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libintl.so
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libjpeg.so
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libpoppler.so
${PROJECT_SOURCE_DIR}/android/libs/${ANDROID_CPU_ARCH}/libpugixml.a
@@ -613,8 +644,15 @@ else()
${FreeImage_LIBRARIES}
${FREETYPE_LIBRARIES}
${GIT2_LIBRARY}
+ ${HarfBuzz_LIBRARIES}
+ ${ICU_LIBRARIES}
${PUGIXML_LIBRARIES}
${SDL2_LIBRARY})
+ if(Intl_LIBRARY)
+ # On Unix systems where the gettext functions are not part of the C standard library
+ # we need to explicitly link with the libintl library.
+ set(COMMON_LIBRARIES ${COMMON_LIBRARIES} ${Intl_LIBRARY})
+ endif()
endif()
if(NOT WIN32)
@@ -673,15 +711,23 @@ set(dir ${CMAKE_CURRENT_SOURCE_DIR})
set(EXECUTABLE_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
set(LIBRARY_OUTPUT_PATH ${dir} CACHE PATH "Build directory" FORCE)
-# Add each component.
+if(COMPILE_LOCALIZATIONS)
+ add_subdirectory(locale)
+endif()
+
add_subdirectory(es-pdf-converter)
add_subdirectory(external)
add_subdirectory(es-core)
add_subdirectory(es-app)
# 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.
add_dependencies(lunasvg es-pdf-convert)
+if(COMPILE_LOCALIZATIONS)
+ add_dependencies(es-pdf-convert localization)
+endif()
+
add_dependencies(es-core rlottie)
+
+# Set lottie2gif to not be built.
set_target_properties(lottie2gif PROPERTIES EXCLUDE_FROM_ALL 1 EXCLUDE_FROM_DEFAULT_BUILD 1)
diff --git a/CREDITS.md b/CREDITS.md
index 308799b5e..4eec32ced 100644
--- a/CREDITS.md
+++ b/CREDITS.md
@@ -15,6 +15,37 @@ Alec Lofquist
Nils Bonenberger
+# Translations
+
+**English (United Kingdom)** \
+Weestuarty \
+**German** \
+Thorsten \
+Pest \
+**Spanish (Spain)** \
+Dani (stshunz) \
+**French** \
+Fredy27 (neuromancer974) \
+**Italian** \
+Viler \
+**Polish** \
+kycho \
+**Portuguese (Brazil)** \
+MrVictorFull \
+**Romanian** \
+SilverGreen93 \
+**Russian** \
+Lulzee \
+**Swedish** \
+Leon Styhre \
+**Japanese** \
+冰棍 \
+**Korean** \
+wakeboxer \
+**Simplified Chinese** \
+邻家小熊 \
+冰棍
+
# Licenses
Please find the individual license files inside the [licenses](https://gitlab.com/es-de/emulationstation-de/-/tree/master/licenses) directory. There is also additional license information in the headers of most source files.
@@ -42,9 +73,18 @@ http://glew.sourceforge.net
GLM \
https://github.com/g-truc/glm
+HarfBuzz \
+https://harfbuzz.github.io
+
+ICU \
+https://icu.unicode.org
+
libgit2 \
https://libgit2.org
+libintl (gettext) \
+https://www.gnu.org/software/gettext
+
libvpx \
https://github.com/webmproject/libvpx
@@ -109,10 +149,10 @@ https://fontawesome.com
GNU FreeFont (FreeMono) \
https://www.gnu.org/software/freefont
-Nanum font \
-https://hangeul.naver.com
+Nanum Square Neo font \
+https://campaign.naver.com/nanumsquare_neo
-Noto Emoji \
+Noto Emoji font \
https://fonts.google.com/noto/specimen/Noto+Emoji
Ubuntu font \
diff --git a/FAQ-ANDROID.md b/FAQ-ANDROID.md
index bd4cfc298..84155cc79 100644
--- a/FAQ-ANDROID.md
+++ b/FAQ-ANDROID.md
@@ -8,11 +8,11 @@ Yes it's the exact same application, with only some minor differences. This mean
## Why is it named ES-DE as in "Desktop Edition" if this is a release for a mobile operating system?
-First it's branding, it would be very confusing to have different names for the same application when it's available cross-platform. Second, the _Desktop Edition_ part is now a legacy, nowadays instead think of the D as standing for _Deck, Droid_ or _Desktop_. The _EmulationStation Desktop Edition_ subtitle used on the splash screen is only temporary during a transition period, it will be removed.
+First it's branding, it would be very confusing to have different names for the same application when it's available cross-platform. Second, the _Desktop Edition_ part is now basically legacy. Actually the entire _EmulationStation Desktop Edition_ subtitle used on the splash screen is only temporary during a transition period and it will be removed at some point. The official name of the project is already ES-DE Frontend or ES-DE for short.
## Is it available for free, and is it open source?
-The Android release specifically is not free, it's a paid app available for purchase through [Patreon](https://www.patreon.com/es_de) or the [Samsung Galaxy Store](https://galaxystore.samsung.com/detail/org.es_de.frontend.galaxy). And although approximately 99% of the app is open source there are some portions of the code that is closed source.
+The Android release specifically is not free, it's a paid app available for purchase through [Patreon](https://www.patreon.com/es_de), the [Samsung Galaxy Store](https://galaxystore.samsung.com/detail/org.es_de.frontend.galaxy) and [Huawei AppGallery](https://appgallery.huawei.com/#/app/C111315115). And although the majority of the code is open source there is some Android-specific code that is copyrighted and closed source.
## I bought ES-DE on Patreon, how do I get access to future releases?
@@ -20,11 +20,15 @@ When a new release is available you will be sent a download link to the email ad
## Can I use ES-DE on more than a single Android device or do I need to buy it multiple times?
-You only need to buy it once, and then you can use it on all your devices. There are no subscriptions or additional costs, you just buy it once. With that said we do appreciate if you want to support the project by keeping your paid Patreon subscription.
+You only need to buy the Patreon release once, and then you can use it on all your devices. There are no subscriptions or additional costs, you just buy it once. With that said we do appreciate if you want to support the project by keeping your paid Patreon subscription. The Samsung Galaxy Store and Huawei AppGallery releases may not be available on all your devices, but that is not an ES-DE restriction but rather governed by the availability of these app stores on your different Android devices.
## ES-DE doesn't work on my device, can I get a refund?
-Although the overwhelming majority of people have successfully got ES-DE to run on their devices (assuming they are fulfilling the basic requirements of 64-bit Android 10 or later) there are some devices that have been problematic. Unfortunately Android is not really a standardized operating system and hardware manufacturers are sometimes applying custom patches and such which may prevent ES-DE from working correctly. We will refund everyone up to one month from the purchase date if they are unable to get ES-DE to run on their device, just send a DM on Patreon and we will issue a refund as soon as possible.
+Although the overwhelming majority of people have successfully got ES-DE to run on their devices (assuming they are fulfilling the basic requirements of 64-bit Android 10 or later) there are some devices that have been problematic. Unfortunately Android is not really a standardized operating system and hardware manufacturers are sometimes applying custom patches and such which may prevent ES-DE from working correctly. We will refund anyone that bought ES-DE on Patreon within one month from the purchase date if they are unable to get ES-DE to run on their device. Just send a DM on Patreon and we will issue a refund as soon as possible. We are however unfortunately not able to refund purchases on the Samsung Galaxy Store and Huawei AppGallery. But make sure to read the next question below as your device may be compatible after all.
+
+## ES-DE hangs at the onboarding configurator, is the app not compatible with my device?
+
+There are some Android developer options that break ES-DE (and probably many other apps too) so make sure to never change such settings unless you know exactly what you are doing. For instance the option _Don't keep activities_ will make the configurator hang so that you'll never be able to get past the onboarding step.
## I received an update email to my Gmail account but the APK download link doesn't seem to work?
@@ -42,7 +46,7 @@ The second reason is that the APK is corrupt or not complete. When we make relea
## Can I set ES-DE as my home app/launcher?
-Yes, as of version 3.0.3 there is experimental support for setting ES-DE as the home app. Read the _Running ES-DE as the Android home app_ section of the [Android documentation](ANDROID.md#running-es-de-as-the-android-home-app) for more information about this functionality. There are currently some minor glitches like sometimes needing to start ES-DE twice after switching between regular mode and home app mode, but apart from that it should hopefully work fine.
+Yes, read the _Running ES-DE as the Android home app_ section of the [Android documentation](ANDROID.md#running-es-de-as-the-android-home-app) for more information about this functionality.
## Can I launch Android apps and games from inside ES-DE?
@@ -68,7 +72,9 @@ Yes but this is not recommended. It's tedious to setup and not how ES-DE is inte
RetroArch on Android is very unforgiving, if you haven't installed the necessary core or BIOS files it's a high chance that you just see a black screen and it will hang there, possibly until you kill it. And due to the security model in Android it's not possible for ES-DE to check if a core is actually installed prior to attempting to launch RetroArch (on Linux, macOS and Windows a popup is shown if the core file is missing and the game is never actually launched in this case). Also make sure that the core you have installed in RetroArch is the one you actually use in ES-DE. You can select between different cores and emulators for most systems using the _Alternative emulators_ interface in the _Other settings_ menu.
-Also note that the RetroArch release on the Google Play store is not working correctly on some devices, it can be used on its own but game launching fails from ES-DE. These issues have been resolved by a number of people by instead switching to the release from the [RetroArch](https://retroarch.com) website.
+Another reason for the black screen is if you have multiple users configured on your device and attempt to run RetroArch from a non-primary user while having your ROMs on internal storage. At the time of writing RetroArch does not support external game launching for any other user than the primary user as it can't parse paths such as /storage/emulated/10/.
+
+Also note that the RetroArch release on the Google Play store is not working correctly on most devices. It can be used on its own but game launching fails from ES-DE. These issues are resolved by using a current release from the [RetroArch](https://retroarch.com) website.
## When I launch a game using a standalone emulator, why does it say the game file could not be opened?
@@ -92,11 +98,19 @@ No Android may stop applications that are not currently focused if it needs to r
## ES-DE takes a very long time to start, is there a way to improve this?
-Unfortunately disk I/O performance on Android leaves a lot to be desired compared to desktop operating systems. Google has prioritized other things over performance which leads to disk speed being poor overall on this operating system. The main offender is the choice of FAT filesystems such as exFAT for external storage which offer very poor performance for some file operations on which ES-DE relies heavily. Generally speaking a small to medium ROM collection can normally be placed on a FAT-formatted device such as an SD card but the ES-DE directory and more importantly the _downloaded_media_ directory should always be placed on internal storage. For large game collections ES-DE could turn borderline unusable if the ES-DE directory is placed on an SD card or USB memory stick. It's also possible to enable the _Only show games from gamelist.xml files_ option in the _Other settings_ menu to skip checking for game files on startup, but this has multiple implications such as what's displayed inside ES-DE not necessarily reflecting reality any longer. And obviously you'll need gamelist.xml entries for all games you want to show up inside ES-DE. So this option is really a last resort and is generally only recommended for testing purposes. In summary huge game collections are discouraged on Android due to limitations in the operating system itself. Setting up a collection of tens of thousands of games is for sure achievable with ES-DE on Linux, macOS or Windows but it's not really feasible on Android.
+Unfortunately disk I/O performance on Android is not on par with desktop operating systems. Google has prioritized other things over performance which leads to disk speed being poor overall on this operating system. The main issue is the choice of FAT filesystems such as exFAT for external storage which offer very poor performance for some file operations on which ES-DE relies heavily. The SAF/MediaStore layer also adds a lot of overhead. Generally speaking a small to medium ROM collection can be placed on a FAT-formatted device such as an SD card, but it's recommended to place the ES-DE directory and more importantly the _downloaded_media_ directory on internal storage. For large game collections ES-DE could turn borderline unusable if the _downloaded_media_ directory is placed on an SD card or on a USB memory stick. This seems to be quite device-dependent though and on some devices performance is still acceptable, so you'll need to test it.
-## On game launch RetroArch runs an old game instead of the one I just selected, how do I prevent this?
+One possible improvement to startup times is to enable the _Only show games from gamelist.xml files_ option in the _Other settings_ menu to skip checking for game files on startup, but this has multiple implications such as what's displayed inside ES-DE not necessarily reflecting reality any longer. And obviously you'll need gamelist.xml entries for all games you want to show up inside ES-DE. So this option is really a last resort and is generally only recommended for testing purposes.
-There is a video on the official ES-DE YouTube channel on how to configure RetroArch correctly so that it quits completely when you're exiting a game:\
+Another option that could speed up startup times under some circumstances is disabling the _Enable theme variant triggers_ setting in the _UI settings_ menu. But whether this has a tangible effect depends on the theme used and to what extent there is scraped media available for your game systems.
+
+Finally, if you keep directories containing texture packs and similar inside your game system folders then these can slow down the startup considerably. To exclude scanning of any such directory you can place a file named `noload.txt` inside the folder and it will get completely skipped on startup.
+
+In summary huge game collections are discouraged on Android due to limitations in the operating system itself. Setting up a collection of tens of thousands of games is for sure achievable with ES-DE on Linux, macOS or Windows but it's not really feasible on Android.
+
+## On game launch the emulator runs an old game instead of the one I just selected, how do I prevent this?
+
+You need to exit the game every time you stop playing, by doing this everything will work correctly. Pressing the home button or manually navigating back to ES-DE without exiting the game is equivalent to pressing "Alt+tab" on a desktop operating system, i.e. the game will still run. The difference from desktop operating systems is that Android pauses the game if you switch away from its window so it may seem like it has closed down, although it actually hasn't. While the procedure to fully exit a game differs between emulators there's a video on the official ES-DE YouTube channel on how to configure RetroArch correctly so that it quits completely when you're exiting a game:\
https://www.youtube.com/watch?v=k5WWacfIn6Y
## What type of Android devices are supported
diff --git a/FAQ.md b/FAQ.md
index 2db2d8edc..e52c70c6a 100644
--- a/FAQ.md
+++ b/FAQ.md
@@ -6,11 +6,11 @@ As of the 3.0.0 release the official name for the project and application is ES-
## Is this software available for free, and is it open source?
-ES-DE is available for free on Windows, macOS and Linux and it's released under the MIT open source license. For Android it's a paid app available via [Patreon](https://www.patreon.com/es_de) and this port is partially closed source.
+ES-DE is available for free on Windows, macOS and Linux and it's released under the MIT open source license. For Android it's a paid app available via [Patreon](https://www.patreon.com/es_de), the [Samsung Galaxy Store](https://galaxystore.samsung.com/detail/org.es_de.frontend.galaxy) and [Huawei AppGallery](https://appgallery.huawei.com/#/app/C111315115) and this port is partially closed source.
## Which operating systems are supported?
-ES-DE runs on Windows, macOS and multiple Linux distributions including Ubuntu, Fedora, Arch, Manjaro, SteamOS etc.
+ES-DE is officially supported on Android, Windows, macOS and multiple Linux distributions including Ubuntu, Fedora, Arch, Manjaro, SteamOS etc. It's also semiofficially supported on some secondary platforms like FreeBSD, the Raspberry Pi and Haiku although these ports may not always be up to date and you may have to build ES-DE yourself.
## What is the relationship between ES-DE and RetroDECK?
@@ -28,6 +28,10 @@ See the _Supported game systems_ section at the bottom of the [User guide](USERG
Menus in ES-DE are not lists but grids, sometimes there is only a list but sometimes there are buttons beneath the list. Enabling the up and down buttons to wrap around would therefore not work consistently as it would sometimes jump to the last row of the list and sometimes to a button, requiring a different number of button presses depending on the menu layout. This type of contextual navigation feels very weird in practice, especially when you have to press the up button twice to get to the bottom of a list. The solution is instead to use the shoulder buttons (which will jump six rows), or the trigger buttons (which will jump to the first and last row). These buttons work consistently throughout the application and avoid the strange side effects just mentioned.
+## I'm using SteamOS and my language settings are not reflected in ES-DE, how can I get language auto-detection to work?
+
+SteamOS does not setup the environment correctly in game mode so it's not possible for ES-DE to detect your configured language. As such you need to manually select your language inside ES-DE using the _Application Language_ option in the _UI Settings_ menu.
+
## 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 ~/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.
diff --git a/HAIKU.md b/HAIKU.md
new file mode 100644
index 000000000..742bf70dc
--- /dev/null
+++ b/HAIKU.md
@@ -0,0 +1,319 @@
+# ES-DE Frontend - Haiku documentation
+
+Note that support for Haiku is currently experimental as the operating system itself is experimental.
+
+There are currently no pre-built packages available so you'll need to build ES-DE yourself. Detailed instructions are available in the _Building on Haiku_ section of the [INSTALL-DEV.md](INSTALL-DEV.md#building-on-haiku) document.
+
+Table of contents:
+
+[[_TOC_]]
+
+## Known ES-DE problems
+
+* Key repeat doesn't work in text editing fields (but it works elsewhere in the application)
+
+* There is no 3D acceleration as the operating system does not support that
+
+## Emulator problems
+
+In contrast with all other platforms which ES-DE runs on, on Haiku emulators which are not working correctly are still included in the configuration. This is done with the belief that things will improve in the future as the operating system matures.
+
+### Atari800
+
+Can't run compressed game files such as those with the .zip extension, and does not seem to be able to correctly emulate any games even if they are uncompressed? (The emulator starts but the games don't.)
+
+### Beetle Lynx
+
+Games don't start, just displays a black screen.
+
+### Beetle PSX HW
+
+Crashes on game start.
+
+### blueMSX
+
+Can't run compressed game files such as those with the .zip extension.
+
+### bsnes
+
+Can't run compressed game files such as those with the .zip extension.
+
+### Caprice32
+
+Can't run compressed game files such as those with the .zip extension.
+
+### DeSmuME
+
+Can't run compressed game files such as those with the .zip extension.
+
+### DOSBox-X (Standalone)
+
+Games can only be launched if ES-DE has been started from the command line, i.e. from a _Terminal_ window. And when existing a game the OS screen resolution is sometimes not reset back to its previous state meaning it has to be manually set to the correct resolution using the operating system's _Screen_ utility.
+
+### EasyRPG
+
+Crashes on game start.
+
+### Flycast
+
+Too slow to be usable in practice, probably due to lack of 3D acceleration.
+
+### fMSX
+
+Can't run compressed game files such as those with the .zip extension.
+
+### FreeIntv
+
+Can't run compressed game files such as those with the .zip extension.
+
+### FS-UAE (Standalone)
+
+This emulator does not seem to accept command-line arguments, meaning games can't be launched from ES-DE.
+
+### Genesis Plus GX Wide
+
+Can't run compressed game files such as those with the .zip extension (it works fine in Genesis Plus GX).
+
+### gpSP
+
+Can't run compressed game files such as those with the .zip extension.
+
+### Hatari
+
+Can't run compressed game files such as those with the .zip extension, and IPF files are not supported.
+
+### MAME (Standalone)
+
+When existing a game the OS screen resolution is sometimes not reset back to its previous state meaning it has to be manually set to the correct resolution using the operating system's _Screen_ utility.
+
+### melonDS
+
+Crashes on game start.
+
+### melonDS (Standalone)
+
+Crashes on game start if attempting to launch a zipped game file.
+
+### Mupen64Plus-Next
+
+Crashes on game start.
+
+### PCSX ReARMed
+
+Games don't run, emulator instantly exits.
+
+### PUAE
+
+Crashes on game start.
+
+### ScummVM (Standalone)
+
+Games can only be launched if ES-DE has been started from the command line, i.e. from a _Terminal_ window.
+
+### Stella
+
+Crashes on game start (Stella 2014 works fine).
+
+### ZEsarUX
+
+Crashes on game start.
+
+## Supported game systems
+
+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 | | Yes | |
+| adam | Coleco Adam | MAME [Diskette] **(Standalone)** | MAME [Tape] **(Standalone)**, MAME [Cartridge] **(Standalone)**, MAME [Software list] **(Standalone)** | Yes | |
+| ags | Adventure Game Studio Game Engine | _Placeholder_ | | | |
+| amiga | Commodore Amiga | PUAE | FS-UAE **(Standalone)** | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga1200 | Commodore Amiga 1200 | PUAE | FS-UAE **(Standalone)** | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amiga600 | Commodore Amiga 600 | PUAE | FS-UAE **(Standalone)** | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amigacd32 | Commodore Amiga CD32 | PUAE | FS-UAE **(Standalone)** | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| amstradcpc | Amstrad CPC | Caprice32 | MAME **(Standalone)** | Yes for MAME | Single archive or disk file |
+| android | Google Android | _Placeholder_ | | | |
+| androidapps | Android Apps | _Placeholder_ | | | |
+| androidgames | Android Games | _Placeholder_ | | | |
+| apple2 | Apple II | Mednafen **(Standalone)** | MAME **(Standalone)** | Yes | See the specific _Apple II_ section in the user guide |
+| apple2gs | Apple IIGS | MAME **(Standalone)** | | Yes | See the specific _Apple IIGS_ section in the user guide |
+| arcade | Arcade | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)**, Geolith, Flycast, _Script_ | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| arcadia | Emerson Arcadia 2001 | MAME **(Standalone)** | | No | Single archive or ROM file |
+| archimedes | Acorn Archimedes | MAME [Model A440/1] **(Standalone)** | MAME [Model A3000] **(Standalone)**, MAME [Model A310] **(Standalone)**, MAME [Model A540] **(Standalone)** | Yes | |
+| arduboy | Arduboy Miniature Game System | _Placeholder_ | | | |
+| astrocde | Bally Astrocade | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| atari2600 | Atari 2600 | Stella | Stella 2014 | No | Single archive or ROM file |
+| atari5200 | Atari 5200 | Atari800 | | Yes | Single archive or ROM file |
+| atari7800 | Atari 7800 ProSystem | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| atari800 | Atari 800 | Atari800 | | Yes | |
+| atarijaguar | Atari Jaguar | Virtual Jaguar | MAME **(Standalone)** | Yes for MAME | See the specific _Atari Jaguar and Atari Jaguar CD_ section in the user guide |
+| atarijaguarcd | Atari Jaguar CD | _Placeholder_ | | | |
+| atarilynx | Atari Lynx | Handy | Beetle Lynx, Mednafen **(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 | | Yes | Single archive file |
+| bbcmicro | Acorn Computers BBC Micro | MAME **(Standalone)** | | Yes | Single archive or diskette image file |
+| c64 | Commodore 64 | VICE x64sc Accurate | VICE x64 Fast, VICE x64 SuperCPU, VICE x128 | No | Single archive or image file for tape, cartridge or single-diskette games, .m3u playlist for multi-diskette games |
+| cdimono1 | Philips CD-i | MAME **(Standalone)** | | Yes | |
+| cdtv | Commodore CDTV | PUAE | FS-UAE **(Standalone)** | Yes | See the specific _Commodore Amiga and CDTV_ section in the user guide |
+| chailove | ChaiLove Game Engine | _Placeholder_ | | | |
+| channelf | Fairchild Channel F | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| coco | Tandy Color Computer | MAME [Cartridge] **(Standalone)** | MAME [Tape] **(Standalone)** | Yes | See the specific _Tandy Color Computer_ section in the user guide |
+| colecovision | Coleco ColecoVision | blueMSX | Gearcoleco | Yes | Single archive or ROM file |
+| consolearcade | Console Arcade Systems | MAME **(Standalone)** | Flycast, Mednafen [Sega Saturn] **(Standalone)**, _Script_ | Depends | See the specific _Console Arcade Systems_ section in the user guide |
+| cps | Capcom Play System | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| cps1 | Capcom Play System I | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| cps2 | Capcom Play System II | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| cps3 | Capcom Play System III | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)** | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| crvision | VTech CreatiVision | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| daphne | Daphne Arcade LaserDisc Emulator | MAME **(Standalone)** | | Depends | See the specific _LaserDisc Games_ section in the user guide |
+| desktop | Desktop Applications | _Suspend ES-DE_ | _Keep ES-DE running_ | No | See the specific _Ports and desktop applications_ section in the user guide |
+| doom | Doom | _Script_ | | No | |
+| dos | DOS (PC) | DOSBox-Pure | DOSBox, DOSBox-X **(Standalone)** | No | See the specific _DOS / PC_ section in the user guide |
+| dragon32 | Dragon Data Dragon 32 | MAME Dragon 32 [Tape] **(Standalone)** | MAME Dragon 32 [Cartridge] **(Standalone)**, MAME Dragon 64 [Tape] **(Standalone)**, MAME Dragon 64 [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
+| dreamcast | Sega Dreamcast | Flycast | | No | In separate folder interpreted as a file, with .m3u playlist if multi-disc game |
+| easyrpg | EasyRPG Game Engine | EasyRPG | | No | See the specific _EasyRPG Game Engine_ section in the user guide |
+| electron | Acorn Electron | MAME [Tape] **(Standalone)** | MAME [Diskette DFS] **(Standalone)**, MAME [Diskette ADFS] **(Standalone)** | Yes | Single archive, or single tape or diskette image file |
+| emulators | Emulators | _Suspend ES-DE_ | _Keep ES-DE running_ | No | See the specific _Ports and desktop applications_ section in the user guide |
+| epic | Epic Games Store | _Placeholder_ | | | |
+| famicom | Nintendo Family Computer | Mesen | Nestopia UE, FCEUmm, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| fba | FinalBurn Alpha | _Placeholder_ | | | |
+| fbneo | FinalBurn Neo | FinalBurn Neo | FinalBurn Neo **(Standalone)** | Yes | See the specific _Arcade and Neo Geo_ section in the user guide |
+| fds | Nintendo Famicom Disk System | Mesen | Nestopia UE, FCEUmm, Mednafen **(Standalone)** | Yes | Single archive or ROM file |
+| flash | Adobe Flash | _Placeholder_ | | | |
+| fm7 | Fujitsu FM-7 | MAME [FM-7 Diskette] **(Standalone)** | MAME [FM-7 Tape] **(Standalone)**, MAME [FM-7 Software list] **(Standalone)**, MAME [FM77AV Diskette] **(Standalone)**, MAME [FM77AV Tape] **(Standalone)**, MAME [FM77AV Software list] **(Standalone)** | Yes | For tape files you need to manually start the cassette player from the MAME menu after the "load" command, as well as entering the "run" command after loading is complete |
+| fmtowns | Fujitsu FM Towns | MAME **(Standalone)** | | Yes | See the specific _Fujitsu FM Towns_ section in the user guide |
+| fpinball | Future Pinball | _Placeholder_ | | | |
+| gamate | Bit Corporation Gamate | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| gameandwatch | Nintendo Game and Watch | MAME Local Artwork **(Standalone)** | MAME **(Standalone)**, Handheld Electronic (GW) | No | See the specific _LCD handheld games_ section in the user guide |
+| gamecom | Tiger Electronics Game.com | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| gamegear | Sega Game Gear | Genesis Plus GX | Genesis Plus GX Wide, Gearsystem, PicoDrive, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| gb | Nintendo Game Boy | Gambatte | SameBoy, Gearboy, mGBA, mGBA **(Standalone)**, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| gba | Nintendo Game Boy Advance | mGBA | mGBA **(Standalone)**, VBA Next, gpSP, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| gbc | Nintendo Game Boy Color | Gambatte | SameBoy, Gearboy, mGBA, mGBA **(Standalone)**, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| gc | Nintendo GameCube | _Placeholder_ | | | |
+| genesis | Sega Genesis | Genesis Plus GX | Genesis Plus GX Wide, PicoDrive, BlastEm, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| gmaster | Hartung Game Master | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| gx4000 | Amstrad GX4000 | Caprice32 | MAME **(Standalone)** | No | Single archive or ROM file |
+| intellivision | Mattel Electronics Intellivision | FreeIntv | MAME **(Standalone)** | Yes | Single archive or ROM file |
+| j2me | Java 2 Micro Edition (J2ME) | _Placeholder_ | | | |
+| kodi | Kodi Home Theatre Software | _Placeholder_ | | | |
+| laserdisc | LaserDisc Games | MAME **(Standalone)** | | Depends | See the specific _LaserDisc Games_ section in the user guide |
+| lcdgames | LCD Handheld Games | MAME Local Artwork **(Standalone)** | MAME **(Standalone)**, Handheld Electronic (GW) | No | See the specific _LCD handheld games_ section in the user guide |
+| lowresnx | LowRes NX Fantasy Console | _Placeholder_ | | | |
+| lutris | Lutris Open Gaming Platform | _Placeholder_ | | | |
+| lutro | Lutro Game Engine | _Placeholder_ | | | |
+| macintosh | Apple Macintosh | MAME Mac SE Bootable **(Standalone)** | MAME Mac SE Boot Disk **(Standalone)**, MAME Mac Plus Bootable **(Standalone)**, MAME Mac Plus Boot Disk **(Standalone)** | Yes | See the specific _Apple Macintosh_ section in the user guide |
+| mame | Multiple Arcade Machine Emulator | MAME 2003-Plus | MAME **(Standalone)**, FinalBurn Neo, FinalBurn Neo **(Standalone)**, Geolith, Flycast, _Script_ | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| mame-advmame | AdvanceMAME | AdvanceMAME **(Standalone)** | | Depends | See the specific _Arcade and Neo Geo_ section in the user guide |
+| mastersystem | Sega Master System | Genesis Plus GX | Genesis Plus GX Wide, Gearsystem, PicoDrive, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| megacd | Sega Mega-CD | Genesis Plus GX | Genesis Plus GX Wide, PicoDrive | Yes | |
+| megacdjp | Sega Mega-CD [Japan] | Genesis Plus GX | Genesis Plus GX Wide, PicoDrive | Yes | |
+| megadrive | Sega Mega Drive | Genesis Plus GX | Genesis Plus GX Wide, PicoDrive, BlastEm, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| megadrivejp | Sega Mega Drive [Japan] | Genesis Plus GX | Genesis Plus GX Wide, PicoDrive, BlastEm, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| megaduck | Creatronic Mega Duck | _Placeholder_ | | | |
+| mess | Multi Emulator Super System | _Placeholder_ | | | |
+| model2 | Sega Model 2 | _Placeholder_ | | | |
+| model2 | Sega Model 2 | MAME **(Standalone)** | | Yes | See the specific _Arcade and Neo Geo_ section in the user guide |
+| model3 | Sega Model 3 | _Placeholder_ | | | |
+| moto | Thomson MO/TO Series | _Placeholder_ | | | |
+| msx | MSX | blueMSX | fMSX | Yes | |
+| msx1 | MSX1 | blueMSX | fMSX | Yes | |
+| msx2 | MSX2 | blueMSX | fMSX | Yes | |
+| msxturbor | MSX Turbo R | blueMSX | | Yes | |
+| mugen | M.U.G.E.N Game Engine | _Placeholder_ | | | |
+| multivision | Othello Multivision | Gearsystem | | No | Single archive or ROM file |
+| n3ds | Nintendo 3DS | _Placeholder_ | | | |
+| n64 | Nintendo 64 | Mupen64Plus-Next | Mupen64Plus **(Standalone)**, ParaLLEl N64 | No | Single archive or ROM file |
+| n64dd | Nintendo 64DD | ParaLLEl N64 | Mupen64Plus-Next | Yes | See the specific _Nintendo 64DD_ section in the user guide |
+| naomi | Sega NAOMI | Flycast | | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
+| naomi2 | Sega NAOMI 2 | Flycast | | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
+| naomigd | Sega NAOMI GD-ROM | Flycast | | Yes | Single archive file + .chd file in subdirectory if GD-ROM game |
+| nds | Nintendo DS | melonDS | melonDS **(Standalone)**, DeSmuME | No | Single archive or ROM file |
+| neogeo | SNK Neo Geo | FinalBurn Neo | FinalBurn Neo **(Standalone)**, Geolith, MAME **(Standalone)** | Yes | See the specific _Arcade and Neo Geo_ section in the user guide |
+| neogeocd | SNK Neo Geo CD | NeoCD | FinalBurn Neo, FinalBurn Neo **(Standalone)**, MAME **(Standalone)** | Yes | .chd (NeoCD and MAME only) or .cue file |
+| neogeocdjp | SNK Neo Geo CD [Japan] | NeoCD | FinalBurn Neo, FinalBurn Neo **(Standalone)**, MAME **(Standalone)** | Yes | .chd (NeoCD and MAME only) or .cue file |
+| nes | Nintendo Entertainment System | Mesen | Mesen | Nestopia UE, FCEUmm, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| ngage | Nokia N-Gage | _Placeholder_ | | | |
+| ngp | SNK Neo Geo Pocket | Beetle NeoPop | Mednafen **(Standalone)** | No | Single archive or ROM file |
+| ngpc | SNK Neo Geo Pocket Color | Beetle NeoPop | Mednafen **(Standalone)** | No | Single archive or ROM file |
+| odyssey2 | Magnavox Odyssey 2 | O2EM | MAME **(Standalone)** | Yes | Single archive or ROM file |
+| openbor | OpenBOR Game Engine | _Placeholder_ | | | |
+| oric | Tangerine Computer Systems Oric | MAME **(Standalone)** | | Yes | See the specific _Tangerine Computer Systems Oric_ section in the user guide |
+| palm | Palm OS | _Placeholder_ | | | |
+| pc | IBM PC | DOSBox-Pure | DOSBox, DOSBox-X **(Standalone)** | No | See the specific _DOS / PC_ section in the user guide |
+| pc88 | NEC PC-8800 Series | _Placeholder_ | | | |
+| pc98 | NEC PC-9800 Series | Neko Project II | | | |
+| pcarcade | PC Arcade Systems | _Script_ | | No | |
+| pcengine | NEC PC Engine | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| pcenginecd | NEC PC Engine CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, Mednafen **(Standalone)** | Yes | |
+| pcfx | NEC PC-FX | Beetle PC-FX | Mednafen **(Standalone)** | Yes | |
+| pico8 | PICO-8 Fantasy Console | _Placeholder_ | | | |
+| 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 | _Placeholder_ | | | |
+| ports | Ports | _Script_ | OpenLara (Tomb Raider) | No | See the specific _Ports and desktop applications_ section in the user guide |
+| ps2 | Sony PlayStation 2 | _Placeholder_ | | | |
+| ps3 | Sony PlayStation 3 | _Placeholder_ | | | |
+| ps4 | Sony PlayStation 4 | _Placeholder_ | | | |
+| psp | Sony PlayStation Portable | PPSSPP **(Standalone)** | | No | Single disc image file |
+| psvita | Sony PlayStation Vita | _Placeholder_ | | | |
+| psx | Sony PlayStation | Beetle PSX | Beetle PSX HW, PCSX ReARMed, Mednafen **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
+| pv1000 | Casio PV-1000 | MAME **(Standalone)** | | No | Single archive or ROM file |
+| quake | Quake | TyrQuake | _Script_ | No | |
+| samcoupe | MGT SAM Coupé | _Placeholder_ | | | |
+| satellaview | Nintendo Satellaview | Snes9x - Current | bsnes | | |
+| saturn | Sega Saturn | Beetle Saturn | Yabause, Mednafen **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
+| saturnjp | Sega Saturn [Japan] | Beetle Saturn | Yabause, Mednafen **(Standalone)** | Yes | .chd file for single-disc games, .m3u playlist for multi-disc games |
+| scummvm | ScummVM Game Engine | ScummVM | ScummVM **(Standalone)** | No | See the specific _ScummVM_ section in the user guide |
+| scv | Epoch Super Cassette Vision | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| 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, PicoDrive | Yes | |
+| sfc | Nintendo SFC (Super Famicom) | Snes9x - Current | bsnes, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| sg-1000 | Sega SG-1000 | Genesis Plus GX | Genesis Plus GX Wide, Gearsystem, blueMSX | No | Single archive or ROM file |
+| sgb | Nintendo Super Game Boy | SameBoy | mGBA, mGBA **(Standalone)** | | Single archive or ROM file |
+| snes | Nintendo SNES (Super Nintendo) | Snes9x - Current | Snes9x - Current | bsnes, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| snesna | Nintendo SNES (Super Nintendo) [North America] | Snes9x - Current | Snes9x - Current | bsnes, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| solarus | Solarus Game Engine | Solarus **(Standalone)** | | No | Single .solarus game file |
+| spectravideo | Spectravideo | blueMSX | | | |
+| steam | Valve Steam | _Placeholder_ | | | |
+| stv | Sega Titan Video Game System | MAME **(Standalone)** | Mednafen **(Standalone)** | Yes | Single archive file |
+| sufami | Bandai SuFami Turbo | Snes9x - Current | bsnes | | |
+| supergrafx | NEC SuperGrafx | Beetle SuperGrafx | Beetle PCE, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| supervision | Watara Supervision | _Placeholder_ | | | |
+| supracan | Funtech Super A'Can | MAME **(Standalone)** | | Yes | Single archive or ROM file. You need a supracan.zip archive that contains a valid internal_68k.bin file and an empty file named umc6650.bin |
+| switch | Nintendo Switch | _Placeholder_ | | | |
+| symbian | Symbian | _Placeholder_ | | | |
+| tanodragon | Tano Dragon | MAME [Tape] **(Standalone)** | MAME [Cartridge] **(Standalone)** | Yes | See the specific _Dragon 32 and Tano Dragon_ section in the user guide |
+| tg16 | NEC TurboGrafx-16 | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, Mednafen **(Standalone)** | No | Single archive or ROM file |
+| tg-cd | NEC TurboGrafx-CD | Beetle PCE | Beetle PCE FAST, Beetle SuperGrafx, Mednafen **(Standalone)** | Yes | |
+| ti99 | Texas Instruments TI-99 | MAME **(Standalone)** | | Yes | See the specific _Texas Instruments TI-99_ section in the user guide |
+| tic80 | TIC-80 Fantasy Computer | _Placeholder_ | | | |
+| to8 | Thomson TO8 | _Placeholder_ | | | |
+| triforce | Namco-Sega-Nintendo Triforce | _Placeholder_ | | | |
+| trs-80 | Tandy TRS-80 | _Placeholder_ | | | |
+| type-x | Taito Type X | _Placeholder_ | | | |
+| uzebox | Uzebox Open Source Console | _Placeholder_ | | | |
+| vectrex | GCE Vectrex | vecx | MAME **(Standalone)** | Yes for MAME | 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 | MAME **(Standalone)** | Yes | Single archive or ROM file |
+| virtualboy | Nintendo Virtual Boy | Beetle VB | Mednafen **(Standalone)** | No | |
+| vpinball | Visual Pinball | _Placeholder_ | | | |
+| vsmile | VTech V.Smile | MAME **(Standalone)** | | Yes | Single archive or ROM file |
+| wasm4 | WASM-4 Fantasy Console | _Placeholder_ | | | |
+| wii | Nintendo Wii | _Placeholder_ | | | |
+| wiiu | Nintendo Wii U | _Placeholder_ | | | |
+| windows | Microsoft Windows | _Placeholder_ | | | |
+| windows3x | Microsoft Windows 3.x | DOSBox-X **(Standalone)** | DOSBox-Pure, _Script (Suspend ES-DE)_, _Script (Keep ES-DE running)_ | No | See the specific _Microsoft Windows 3.x and 9x_ section in the user guide |
+| windows9x | Microsoft Windows 9x | DOSBox-X **(Standalone)** | DOSBox-Pure, _Script (Suspend ES-DE)_, _Script (Keep ES-DE running)_ | No | See the specific _Microsoft Windows 3.x and 9x_ section in the user guide |
+| wonderswan | Bandai WonderSwan | Beetle Cygne | Mednafen **(Standalone)** | No | Single archive or ROM file |
+| wonderswancolor | Bandai WonderSwan Color | Beetle Cygne | Mednafen **(Standalone)** | No | Single archive or ROM file |
+| x1 | Sharp X1 | MAME [Diskette] **(Standalone)** | MAME [Tape] **(Standalone)** | Yes | Single archive or diskette/tape file |
+| x68000 | Sharp X68000 | MAME **(Standalone)** | | Yes | |
+| xbox | Microsoft Xbox | _Placeholder_ | | | |
+| xbox360 | Microsoft Xbox 360 | _Placeholder_ | | | |
+| zmachine | Infocom Z-machine | _Placeholder_ | | | |
+| zx81 | Sinclair ZX81 | EightyOne | | No | |
+| zxnext | Sinclair ZX Spectrum Next | ZEsarUX **(Standalone)** | | No | In separate folder interpreted as a file |
+| zxspectrum | Sinclair ZX Spectrum | Fuse | Fuse **(Standalone)** | No | Single archive or ROM file |
diff --git a/INSTALL-DEV.md b/INSTALL-DEV.md
index 50b049edb..ea014ad40 100644
--- a/INSTALL-DEV.md
+++ b/INSTALL-DEV.md
@@ -25,7 +25,7 @@ There are some dependencies that need to be fulfilled in order to build ES-DE. T
All of the required packages can be installed with apt-get:
```
-sudo apt-get install build-essential clang-format git cmake libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-openssl-dev libpugixml-dev libasound2-dev libgl1-mesa-dev libpoppler-cpp-dev
+sudo apt-get install build-essential clang-format git cmake gettext libharfbuzz-dev libicu-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-openssl-dev libpugixml-dev libasound2-dev libgl1-mesa-dev libpoppler-cpp-dev
```
**Fedora**
@@ -40,7 +40,7 @@ https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -
Then you can use dnf to install all the required packages:
```
-sudo dnf install gcc-c++ clang-tools-extra cmake libasan rpm-build SDL2-devel ffmpeg-devel freeimage-devel freetype-devel libgit2-devel curl-devel pugixml-devel alsa-lib-devel mesa-libGL-devel poppler-cpp-devel
+sudo dnf install gcc-c++ clang-tools-extra cmake gettext harfbuzz-devel libicu-devel libasan rpm-build SDL2-devel ffmpeg-devel freeimage-devel freetype-devel libgit2-devel curl-devel pugixml-devel alsa-lib-devel mesa-libGL-devel poppler-cpp-devel
```
**Manjaro**
@@ -48,14 +48,14 @@ sudo dnf install gcc-c++ clang-tools-extra cmake libasan rpm-build SDL2-devel ff
Use pacman to install all the required packages:
```
-sudo pacman -S gcc clang make cmake pkgconf sdl2 ffmpeg freeimage freetype2 libgit2 pugixml poppler
+sudo pacman -S gcc clang make cmake gettext harfbuzz icu pkgconf sdl2 ffmpeg freeimage freetype2 libgit2 pugixml poppler
```
**Raspberry Pi OS**
All of the required packages can be installed with apt-get:
```
-sudo apt-get install clang-format cmake libraspberrypi-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-gnutls-dev libpugixml-dev libpoppler-cpp-dev
+sudo apt-get install clang-format cmake gettext libharfbuzz-dev libicu-dev libraspberrypi-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-gnutls-dev libpugixml-dev libpoppler-cpp-dev
```
For a 64-bit build it's very important that you include libraspberrypi-dev because if this package is not installed then the file /usr/include/bcm_host.h is not present on the filesystem. This leads to CMake not detecting that it's indeed a Raspberry Pi and it will attempt to make a regular Linux build instead.
@@ -75,44 +75,21 @@ Only the OpenGL ES 3.0 renderer works on Raspberry Pi and it's enabled by defaul
Use pkg to install the dependencies:
```
-pkg install llvm-devel git pkgconf cmake sdl2 ffmpeg freeimage libgit2 pugixml poppler
+pkg install llvm-devel git pkgconf cmake gettext harfbuzz icu sdl2 ffmpeg freeimage libgit2 pugixml poppler
```
Clang/LLVM and curl should already be included in the base OS installation.
-**NetBSD**
-
-Use pkgin to install the dependencies:
+Note that there is a strange issue specifically on FreeBSD 14.1 where the rlottie library refuses to build. This can be resolved by the following workaround:
```
-pkgin install clang git cmake pkgconf SDL2 ffmpeg4 freeimage libgit2 pugixml poppler-cpp
+echo > external/rlottie/format
```
-NetBSD ships with GCC by default, and although you should be able to use Clang/LLVM, it's probably easier to just stick to the default compiler environment. The reason why the clang package needs to be installed is to get clang-format onto the system.
-
-**OpenBSD**
-
-Use pkg_add to install the dependencies:
-```
-pkg_add clang-tools-extra cmake pkgconf sdl2 ffmpeg freeimage libgit2 poppler
-```
-
-In the same manner as for FreeBSD, Clang/LLVM and curl should already be installed by default.
-
-The pugixml library does exist in the package collection but somehow this version is not properly detected by CMake, so you need to compile this manually as well:
-
-```
-git clone https://github.com/zeux/pugixml.git
-cd pugixml
-git checkout v1.10
-cmake .
-make
-make install
-```
+It's not clear yet whether this is a compiler bug or some other issue.
**Cloning and compiling ES-DE**
To clone the source repository, run the following:
-
```
git clone https://gitlab.com/es-de/emulationstation-de.git
```
@@ -133,7 +110,7 @@ cmake -DAPPLICATION_UPDATER=off .
make
```
-Note that the application updater is always disabled when building for the AUR, RetroDECK, Raspberry Pi or BSD Unix.
+Note that the application updater is always disabled when building for the AUR, RetroDECK, Raspberry Pi or FreeBSD.
On Linux specifically you can build with the DEINIT_ON_LAUNCH option which will deinit the renderer, application window and audio when an emulator is launched. This makes it possible to use ES-DE with KMS/direct framebuffer access to for example make ES-DE a drop-in replacement for RetroPie EmulationStation:
```
@@ -188,6 +165,11 @@ It could also be a good idea to use the `TSAN_suppressions` file included in the
TSAN_OPTIONS="suppressions=tools/TSAN_suppressions" ./es-de --debug --resolution 2560 1440
```
+On some Linux distributions you need to modify the _vm.mmap_rnd_bits_ kernel runtime parameter or you'll see an error message such as _FATAL: ThreadSanitizer: unexpected memory mapping 0x58bd90d75000-0x58bd90dbe000_ when attempting to start ES-DE. Setting the parameter to 28 should make ThreadSanitizer work correctly. The following is how it's done on Ubuntu:
+```
+sudo sysctl vm.mmap_rnd_bits=28
+```
+
To enable UndefinedBehaviorSanitizer which helps with identifying bugs that may otherwise be hard to find, build with the UBSAN option:
```
cmake -DCMAKE_BUILD_TYPE=Debug -UBSAN=on .
@@ -269,7 +251,7 @@ make -j8
This renderer is generally only needed on the Raspberry Pi and the desktop OpenGL renderer should otherwise be used.
-By default ES-DE will install under /usr on Linux, /usr/pkg on NetBSD and /usr/local on FreeBSD and OpenBSD although this can be changed by setting the `CMAKE_INSTALL_PREFIX` variable.
+By default ES-DE will install under /usr on Linux and /usr/local on FreeBSD although this can be changed by setting the `CMAKE_INSTALL_PREFIX` variable.
The following example will build the application for installtion under /opt:
@@ -437,6 +419,54 @@ This is similar to the regular AppImage but does not build with the BUNDLED_CERT
Both _appimagetool_ and _linuxdeploy_ are required for the build process but they will be downloaded automatically by the script if they don't exist. So to force an update to the latest build tools, delete these two AppImages prior to running the build script.
+## Building on Haiku
+
+It's recommended to run R1/beta5 as the nightly Haiku builds can be quite unstable.
+
+If running Haiku in KVM/Qemu, make sure to use SATA storage intead of VirtIO storage as you may otherwise experience stability issues and filesystem corruption.
+
+**Local build**
+
+Use pkgman to install the required dependencies:
+```
+pkgman install cmake gettext curl_devel harfbuzz_devel freeimage_devel pugixml_devel libsdl2_devel libgit2_devel freetype_devel ffmpeg6_devel poppler24_devel
+```
+
+To clone the ES-DE source repository, run the following:
+```
+git clone https://gitlab.com/es-de/emulationstation-de.git
+```
+You can then go ahead and build the application:
+```
+cd emulationstation-de
+cmake .
+make -j8
+```
+
+Change the -j flag to whatever amount of parallel threads you want to use for the compilation.
+
+**HaikuPorts package build**
+
+Run the following to build the .hpkg package:
+
+```
+cd ~
+git clone https://github.com/haikuports/haikuports.git --depth=50
+mkdir haikuports/games-emulation/es-de
+pkgman install haikuporter
+cp /boot/system/settings/haikuports.conf ~/config/settings/
+cd emulationstation-de
+cp es-app/assets/es_de-3.1.0.recipe ~/haikuports/games-emulation/es-de
+haikuporter -S --no-source-packages --get-dependencies -j8 es_de
+```
+
+The first time you run haikuporter it will take a while as dependencies for all ports will get updated before the ES-DE build process starts.
+
+Following this you can install the package into the running system:
+```
+cp ~/haikuports/packages/es_de-3.1.0-1-x86_64.hpkg /boot/system/packages
+```
+
## Building on macOS
ES-DE for macOS is built using Clang/LLVM which is the default compiler for this operating system. It's pretty straightforward to build software on this OS. The main problem is that there is no native package manager, but as there are several third party package managers available, this can be partly compensated for. The use of one of them, [Homebrew](https://brew.sh), is detailed below.
@@ -650,29 +680,23 @@ CPack: - package: /Users/myusername/emulationstation-de/ES-DE_3.0.0-arm64.dmg ge
Only the Microsoft Visual C++ (MSVC) compiler is supported on Windows. Although MinGW/GCC produces higher quality code with ES-DE running around 10% to 25% faster it's unfortunately not sustainable to use it. There are multiple technical issues with third party libraries like severe threading issues with FFmpeg and some libraries like Poppler not being readily available.
-**MSVC setup**
-
Install Git for Windows: \
-[https://gitforwindows.org](https://gitforwindows.org)
+https://gitforwindows.org
Download the Visual Studio Build Tools (choose Visual Studio Community edition): \
-[https://visualstudio.microsoft.com/downloads](https://visualstudio.microsoft.com/downloads)
+https://visualstudio.microsoft.com/downloads
-During installation, choose the Desktop development with C++ workload with the following options (version details may differ):
+During installation, choose the Desktop development with C++ workload with the following options:
```
MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
-Windows 10 SDK
Just-In-Time debugger
-C++ AddressSanitizer
-```
-
-If you will only use MSVC and not MinGW, then also add this option:
-```
C++ CMake tools for Windows
+C++ AddressSanitizer
+Windows 10 SDK (10.0.20348.0)
```
-If not installing the CMake version supplied by Microsoft, you need to make sure that you have a recent version on your machine or CMake will not be able to detect MSVC correctly.
+The Windows SDK version is important, it has to be this precise version or some dependencies may not build correctly.
It's strongly recommended to also install Jom, which is a drop-in replacement for nmake that offers support for building in parallel using multiple CPU cores:\
https://wiki.qt.io/Jom
@@ -688,7 +712,7 @@ It's important to choose the x64-specific shell and not the x86 variant, as ES-D
**Other preparations**
In order to get clang-format onto the system you need to download and install Clang/LLVM: \
-[https://releases.llvm.org](https://releases.llvm.org)
+https://releases.llvm.org
Just run the installer and make sure to select the option _Add LLVM to the system PATH for current user_.
@@ -768,7 +792,7 @@ On Windows the certificates supplied with the operating system will not be utili
**Running with OpenGL software rendering**
-If you are running Windows in a virtualized environment such as QEMU-KVM that does not support HW accelerated OpenGL, you can install the Mesa3D for Windows library, which can be downloaded at [https://fdossena.com/?p=mesa/index.frag](https://fdossena.com/?p=mesa/index.frag).
+If you are running Windows in a virtualized environment such as QEMU-KVM that does not support HW accelerated OpenGL, you can install the Mesa3D for Windows library, which can be downloaded at https://fdossena.com/?p=mesa/index.frag
You simply extract the opengl32.dll file into the ES-DE directory and this will enable the llvmpipe renderer. The performance will be terrible of course, but everything should work and it should be good enough for test building on Windows without having to reboot your computer to a native Windows installation. (Note that you may need to copy opengl32.dll to your RetroArch installation directory as well to get the emulators to work somehow correctly.)
@@ -778,7 +802,7 @@ Obviously this library is only intended for development and will not be shipped
To create an NSIS installer (Nullsoft Scriptable Install System) you need to first install the NSIS creation tool:
-[https://nsis.sourceforge.io/Download](https://nsis.sourceforge.io/Download)
+https://nsis.sourceforge.io/Download
Simply install the application using its installer.
@@ -921,9 +945,9 @@ Of course you would like to get the code formatted according to the clang-format
There are some files shipped with ES-DE that need to be pulled from external resources, the first one being the CA certificate bundle to get TLS/SSL support working on Windows.
-The CA certificates shipped with ES-DE come directly from the curl project but they're originally supplied by the Mozilla foundation. See [https://wiki.mozilla.org/CA](https://wiki.mozilla.org/CA) for more information about this certificate bundle.
+The CA certificates shipped with ES-DE come directly from the curl project but they're originally supplied by the Mozilla foundation. See https://wiki.mozilla.org/CA for more information about this certificate bundle.
-The latest version can be downloaded from [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html)
+The latest version can be downloaded from https://curl.se/docs/caextract.html
After downloading the file, rename it from `cacert.pem` to `curl-ca-bundle.crt` and move it to the certificates directory i.e.:
@@ -935,7 +959,7 @@ emulationstation-de/resources/certificates/curl-ca-bundle.crt
ES-DE automatically identifies and excludes MAME BIOS and device files, as well as translating the short MAME ROM names to their full game names. This is done using information from the MAME driver file shipped with the official MAME distribution. The file needs to be converted to an internal format used by ES-DE as the original file is huge and most of the information is not required.
-To get hold of the driver file, go to [https://www.mamedev.org/release.php](https://www.mamedev.org/release.php) and select the Windows version, but only download the driver information in XML format and not MAME itself. This file will be named something like `mame0226lx.zip` and unzipping it will give you a filename such as `mame0226.xml`.
+To get hold of the driver file, go to https://www.mamedev.org/release.php and select the Windows version, but only download the driver information in XML format and not MAME itself. This file will be named something like `mame0226lx.zip` and unzipping it will give you a filename such as `mame0226.xml`.
Move the XML driver file to the resources/MAME directory and then convert it to the ES-DE internal files:
@@ -1762,9 +1786,9 @@ The es_systems.xml file on Android utilizes variables heavily to implement the _
There are two main ways to pass options to emulators, using _extras_ or using the _data_ URI. There can only be a single data URI but there can be an arbitrary amount of extras. To understand more about the way this works, you can read about the _putExtra()_ and and _setData()_ functions here:\
https://developer.android.com/reference/android/content/Intent
-`%EXTRA_` - This passes an _extra_ which contains any additional information that the emulator may support. This is provided as a key/value pair where you define the key name following the literal %EXTRA_ string and terminate it with a % sign and then assign the value using an equal sign. For example %EXTRA_LIBRETRO%=puae_libretro_android.so will pass the extra named _LIBRETRO_ with its value set to _puae_libretro_android.so_. You can pass an unlimited number of extras and you can also use various ROM variables in combination with this as described below. It's also possible to use the `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRA_` variable definition, which will expand to the the directory of the game file, the ROM directory and the path to the game file respectively.
+`%EXTRA_` - This passes an _extra_ which contains any additional information that the emulator may support. This is provided as a key/value pair where you define the key name following the literal %EXTRA_ string and terminate it with a % sign and then assign the value using an equal sign. For example %EXTRA_LIBRETRO%=puae_libretro_android.so will pass the extra named _LIBRETRO_ with its value set to _puae_libretro_android.so_. You can pass an unlimited number of extras and you can also use various ROM variables in combination with this as described below. It's also possible to use the `%BASENAME%`, `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRA_` variable definition, which will expand to the basename of the game file, the directory of the game file, the ROM directory and the path to the game file respectively.
-`%EXTRAARRAY_` - Defines an array of comma-separated string values following the key name. Only literal strings are supported, so this can't be used in combination with any ROM variables. As commas are used as separator characters, you'll need to escape any comma signs that you want to include in the actual value. For example %EXTRAARRAY_Parameters%=pone,p\\,two,pthree will pass the extra named _Parameters_ with the three separate array entries _pone_, _p,two_ and _pthree_. It's also possible to use the `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRAARRAY_` variable definition, which will expand to the the directory of the game file, the ROM directory and the path to the game file respectively.
+`%EXTRAARRAY_` - Defines an array of comma-separated string values following the key name. Only literal strings and special variables are supported, so this can't be used in combination with any ROM variables. As commas are used as separator characters, you'll need to escape any comma signs that you want to include in the actual value. For example %EXTRAARRAY_Parameters%=pone,p\\,two,pthree will pass the extra named _Parameters_ with the three separate array entries _pone_, _p,two_ and _pthree_. It's also possible to use the `%BASENAME%`, `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRAARRAY_` variable definition, which will expand to the basename of the game file, the directory of the game file, the ROM directory and the path to the game file respectively.
`%EXTRABOOL_` - Sets an extra with a boolean value, i.e. true/1 or false/0.
@@ -2136,7 +2160,7 @@ Just make sure to not place the portable installation on a network share that us
There are numerous locations throughout ES-DE where custom scripts can be executed if the option to do so has been enabled in the settings. You'll find the option _Enable custom event scripts_ on the Main menu under _Other settings_. By default this setting is deactivated so make sure to enable it to use this feature.
-The approach is quite straightforward, ES-DE will look for any files inside a script directory that corresponds to the event that is triggered and will then attempt to execute all these files (regardless of their file extensions). If you want to have the scripts executed in a certain order you can name them accordingly as they will be sorted and executed in lexicographic order. The sorting is case-sensitive on Unix/Linux and case-insensitive on macOS and Windows. ES-DE will wait for each script to finish its execution before moving on to the next one, so the application will suspend briefly when whatever the script is doing is executing. If you want to avoid this you can setup a wrapper script that executes another script outside the ES-DE scripts directory as a background process. Refer to your operating system documentation on how to accomplish this.
+The approach is quite straightforward, ES-DE will look for any files inside a script directory that corresponds to the event that is triggered and will then attempt to execute all these files (regardless of their file extensions). If you want to have the scripts executed in a certain order you can name them accordingly as they will be sorted and executed in lexicographic order. The sorting is case-sensitive on Linux and Android and case-insensitive on macOS and Windows. ES-DE will wait for each script to finish its execution before moving on to the next one, so the application will suspend briefly when whatever the script is doing is executing. If you want to avoid this you can setup a wrapper script that executes another script outside the ES-DE scripts directory as a background process. Refer to your operating system documentation on how to accomplish this.
On Windows it's also possible to place .lnk shortcut files in the event directories to have these executed in the same manner as a script. Note that while PowerShell scripts can't be executed directly they can be run via either a .lnk shortcut file or a .bat wrapper script where you explicitly call powershell.exe with the -command flag. Just be aware that by default the execution of PowerShell scripts is disabled on Windows. Further details about PowerShell is beyond the scope of this document.
@@ -2163,11 +2187,11 @@ We'll go through two examples:
* Creating a log file that will record the start and end time for each game we play, letting us see how much time we spend on retro-gaming
* Changing the system resolution when launching and returning from a game in order to run the emulator at a lower resolution than ES-DE
-The following examples are for Unix systems, but it works the same way on macOS and Windows (although .bat batch files are used on Windows instead of shell scripts and any spaces in the parameters are not escaped as is the case on Unix and macOS).
+The following examples are for Linux systems, but it works the same way on Android, macOS and Windows (although .bat batch files are used on Windows instead of shell scripts and any spaces in the parameters are not escaped as is the case on Linux, Android and macOS).
As can be seen in the table above, the events executed when a game starts and ends are named _game-start_ and _game-end_
-So let's create the folders for these events in the scripts directory. The location is `~/ES-DE/scripts`
+So let's create the folders for these events inside the application data directory, or more specifically in `~/ES-DE/scripts`
**Game log**
diff --git a/INSTALL.md b/INSTALL.md
index bc0b2c1de..640ba9adb 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -23,7 +23,7 @@ There are some dependencies that need to be fulfilled in order to build ES-DE. T
All of the required packages can be installed with apt-get:
```
-sudo apt-get install build-essential clang-format git cmake libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-openssl-dev libpugixml-dev libasound2-dev libgl1-mesa-dev libpoppler-cpp-dev
+sudo apt-get install build-essential clang-format git cmake gettext libharfbuzz-dev libicu-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-openssl-dev libpugixml-dev libasound2-dev libgl1-mesa-dev libpoppler-cpp-dev
```
**Fedora**
@@ -38,7 +38,7 @@ https://download1.rpmfusion.org/nonfree/fedora/rpmfusion-nonfree-release-$(rpm -
Then you can use dnf to install all the required packages:
```
-sudo dnf install gcc-c++ clang-tools-extra cmake libasan rpm-build SDL2-devel ffmpeg-devel freeimage-devel freetype-devel libgit2-devel curl-devel pugixml-devel alsa-lib-devel mesa-libGL-devel poppler-cpp-devel
+sudo dnf install gcc-c++ clang-tools-extra cmake gettext harfbuzz-devel libicu-devel libasan rpm-build SDL2-devel ffmpeg-devel freeimage-devel freetype-devel libgit2-devel curl-devel pugixml-devel alsa-lib-devel mesa-libGL-devel poppler-cpp-devel
```
**Manjaro**
@@ -46,14 +46,14 @@ sudo dnf install gcc-c++ clang-tools-extra cmake libasan rpm-build SDL2-devel ff
Use pacman to install all the required packages:
```
-sudo pacman -S gcc clang make cmake pkgconf sdl2 ffmpeg freeimage freetype2 libgit2 pugixml poppler
+sudo pacman -S gcc clang make cmake gettext harfbuzz icu pkgconf sdl2 ffmpeg freeimage freetype2 libgit2 pugixml poppler
```
**Raspberry Pi OS**
All of the required packages can be installed with apt-get:
```
-sudo apt-get install clang-format cmake libraspberrypi-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-gnutls-dev libpugixml-dev libpoppler-cpp-dev
+sudo apt-get install clang-format cmake gettext libharfbuzz-dev libicu-dev libraspberrypi-dev libsdl2-dev libavcodec-dev libavfilter-dev libavformat-dev libavutil-dev libfreeimage-dev libfreetype6-dev libgit2-dev libcurl4-gnutls-dev libpugixml-dev libpoppler-cpp-dev
```
For a 64-bit build it's very important that you include libraspberrypi-dev because if this package is not installed then the file /usr/include/bcm_host.h is not present on the filesystem. This leads to CMake not detecting that it's indeed a Raspberry Pi and it will attempt to make a regular Linux build instead.
@@ -73,44 +73,21 @@ Only the OpenGL ES 3.0 renderer works on Raspberry Pi and it's enabled by defaul
Use pkg to install the dependencies:
```
-pkg install llvm-devel git pkgconf cmake sdl2 ffmpeg freeimage libgit2 pugixml poppler
+pkg install llvm-devel git pkgconf cmake gettext harfbuzz icu sdl2 ffmpeg freeimage libgit2 pugixml poppler
```
Clang/LLVM and curl should already be included in the base OS installation.
-**NetBSD**
-
-Use pkgin to install the dependencies:
+Note that there is a strange issue specifically on FreeBSD 14.1 where the rlottie library refuses to build. This can be resolved by the following workaround:
```
-pkgin install clang git cmake pkgconf SDL2 ffmpeg4 freeimage libgit2 pugixml poppler-cpp
+echo > external/rlottie/format
```
-NetBSD ships with GCC by default, and although you should be able to use Clang/LLVM, it's probably easier to just stick to the default compiler environment. The reason why the clang package needs to be installed is to get clang-format onto the system.
-
-**OpenBSD**
-
-Use pkg_add to install the dependencies:
-```
-pkg_add clang-tools-extra cmake pkgconf sdl2 ffmpeg freeimage libgit2 poppler
-```
-
-In the same manner as for FreeBSD, Clang/LLVM and curl should already be installed by default.
-
-The pugixml library does exist in the package collection but somehow this version is not properly detected by CMake, so you need to compile this manually as well:
-
-```
-git clone https://github.com/zeux/pugixml.git
-cd pugixml
-git checkout v1.10
-cmake .
-make
-make install
-```
+It's not clear yet whether this is a compiler bug or some other issue.
**Cloning and compiling ES-DE**
To clone the source repository, run the following:
-
```
git clone https://gitlab.com/es-de/emulationstation-de.git
```
@@ -131,7 +108,7 @@ cmake -DAPPLICATION_UPDATER=off .
make
```
-Note that the application updater is always disabled when building for the AUR, RetroDECK, Raspberry Pi or BSD Unix.
+Note that the application updater is always disabled when building for the AUR, RetroDECK, Raspberry Pi or FreeBSD.
On Linux specifically you can build with the DEINIT_ON_LAUNCH option which will deinit the renderer, application window and audio when an emulator is launched. This makes it possible to use ES-DE with KMS/direct framebuffer access to for example make ES-DE a drop-in replacement for RetroPie EmulationStation:
```
@@ -186,6 +163,11 @@ It could also be a good idea to use the `TSAN_suppressions` file included in the
TSAN_OPTIONS="suppressions=tools/TSAN_suppressions" ./es-de --debug --resolution 2560 1440
```
+On some Linux distributions you need to modify the _vm.mmap_rnd_bits_ kernel runtime parameter or you'll see an error message such as _FATAL: ThreadSanitizer: unexpected memory mapping 0x58bd90d75000-0x58bd90dbe000_ when attempting to start ES-DE. Setting the parameter to 28 should make ThreadSanitizer work correctly. The following is how it's done on Ubuntu:
+```
+sudo sysctl vm.mmap_rnd_bits=28
+```
+
To enable UndefinedBehaviorSanitizer which helps with identifying bugs that may otherwise be hard to find, build with the UBSAN option:
```
cmake -DCMAKE_BUILD_TYPE=Debug -UBSAN=on .
@@ -267,7 +249,7 @@ make -j8
This renderer is generally only needed on the Raspberry Pi and the desktop OpenGL renderer should otherwise be used.
-By default ES-DE will install under /usr on Linux, /usr/pkg on NetBSD and /usr/local on FreeBSD and OpenBSD although this can be changed by setting the `CMAKE_INSTALL_PREFIX` variable.
+By default ES-DE will install under /usr on Linux and /usr/local on FreeBSD although this can be changed by setting the `CMAKE_INSTALL_PREFIX` variable.
The following example will build the application for installtion under /opt:
@@ -435,6 +417,54 @@ This is similar to the regular AppImage but does not build with the BUNDLED_CERT
Both _appimagetool_ and _linuxdeploy_ are required for the build process but they will be downloaded automatically by the script if they don't exist. So to force an update to the latest build tools, delete these two AppImages prior to running the build script.
+## Building on Haiku
+
+It's recommended to run R1/beta5 as the nightly Haiku builds can be quite unstable.
+
+If running Haiku in KVM/Qemu, make sure to use SATA storage intead of VirtIO storage as you may otherwise experience stability issues and filesystem corruption.
+
+**Local build**
+
+Use pkgman to install the required dependencies:
+```
+pkgman install cmake gettext curl_devel harfbuzz_devel freeimage_devel pugixml_devel libsdl2_devel libgit2_devel freetype_devel ffmpeg6_devel poppler24_devel
+```
+
+To clone the ES-DE source repository, run the following:
+```
+git clone https://gitlab.com/es-de/emulationstation-de.git
+```
+You can then go ahead and build the application:
+```
+cd emulationstation-de
+cmake .
+make -j8
+```
+
+Change the -j flag to whatever amount of parallel threads you want to use for the compilation.
+
+**HaikuPorts package build**
+
+Run the following to build the .hpkg package:
+
+```
+cd ~
+git clone https://github.com/haikuports/haikuports.git --depth=50
+mkdir haikuports/games-emulation/es-de
+pkgman install haikuporter
+cp /boot/system/settings/haikuports.conf ~/config/settings/
+cd emulationstation-de
+cp es-app/assets/es_de-3.1.0.recipe ~/haikuports/games-emulation/es-de
+haikuporter -S --no-source-packages --get-dependencies -j8 es_de
+```
+
+The first time you run haikuporter it will take a while as dependencies for all ports will get updated before the ES-DE build process starts.
+
+Following this you can install the package into the running system:
+```
+cp ~/haikuports/packages/es_de-3.1.0-1-x86_64.hpkg /boot/system/packages
+```
+
## Building on macOS
ES-DE for macOS is built using Clang/LLVM which is the default compiler for this operating system. It's pretty straightforward to build software on this OS. The main problem is that there is no native package manager, but as there are several third party package managers available, this can be partly compensated for. The use of one of them, [Homebrew](https://brew.sh), is detailed below.
@@ -648,29 +678,23 @@ CPack: - package: /Users/myusername/emulationstation-de/ES-DE_3.0.0-arm64.dmg ge
Only the Microsoft Visual C++ (MSVC) compiler is supported on Windows. Although MinGW/GCC produces higher quality code with ES-DE running around 10% to 25% faster it's unfortunately not sustainable to use it. There are multiple technical issues with third party libraries like severe threading issues with FFmpeg and some libraries like Poppler not being readily available.
-**MSVC setup**
-
Install Git for Windows: \
-[https://gitforwindows.org](https://gitforwindows.org)
+https://gitforwindows.org
Download the Visual Studio Build Tools (choose Visual Studio Community edition): \
-[https://visualstudio.microsoft.com/downloads](https://visualstudio.microsoft.com/downloads)
+https://visualstudio.microsoft.com/downloads
-During installation, choose the Desktop development with C++ workload with the following options (version details may differ):
+During installation, choose the Desktop development with C++ workload with the following options:
```
MSVC v143 - VS 2022 C++ x64/x86 build tools (Latest)
-Windows 10 SDK
Just-In-Time debugger
-C++ AddressSanitizer
-```
-
-If you will only use MSVC and not MinGW, then also add this option:
-```
C++ CMake tools for Windows
+C++ AddressSanitizer
+Windows 10 SDK (10.0.20348.0)
```
-If not installing the CMake version supplied by Microsoft, you need to make sure that you have a recent version on your machine or CMake will not be able to detect MSVC correctly.
+The Windows SDK version is important, it has to be this precise version or some dependencies may not build correctly.
It's strongly recommended to also install Jom, which is a drop-in replacement for nmake that offers support for building in parallel using multiple CPU cores:\
https://wiki.qt.io/Jom
@@ -686,7 +710,7 @@ It's important to choose the x64-specific shell and not the x86 variant, as ES-D
**Other preparations**
In order to get clang-format onto the system you need to download and install Clang/LLVM: \
-[https://releases.llvm.org](https://releases.llvm.org)
+https://releases.llvm.org
Just run the installer and make sure to select the option _Add LLVM to the system PATH for current user_.
@@ -766,7 +790,7 @@ On Windows the certificates supplied with the operating system will not be utili
**Running with OpenGL software rendering**
-If you are running Windows in a virtualized environment such as QEMU-KVM that does not support HW accelerated OpenGL, you can install the Mesa3D for Windows library, which can be downloaded at [https://fdossena.com/?p=mesa/index.frag](https://fdossena.com/?p=mesa/index.frag).
+If you are running Windows in a virtualized environment such as QEMU-KVM that does not support HW accelerated OpenGL, you can install the Mesa3D for Windows library, which can be downloaded at https://fdossena.com/?p=mesa/index.frag
You simply extract the opengl32.dll file into the ES-DE directory and this will enable the llvmpipe renderer. The performance will be terrible of course, but everything should work and it should be good enough for test building on Windows without having to reboot your computer to a native Windows installation. (Note that you may need to copy opengl32.dll to your RetroArch installation directory as well to get the emulators to work somehow correctly.)
@@ -776,7 +800,7 @@ Obviously this library is only intended for development and will not be shipped
To create an NSIS installer (Nullsoft Scriptable Install System) you need to first install the NSIS creation tool:
-[https://nsis.sourceforge.io/Download](https://nsis.sourceforge.io/Download)
+https://nsis.sourceforge.io/Download
Simply install the application using its installer.
@@ -919,9 +943,9 @@ Of course you would like to get the code formatted according to the clang-format
There are some files shipped with ES-DE that need to be pulled from external resources, the first one being the CA certificate bundle to get TLS/SSL support working on Windows.
-The CA certificates shipped with ES-DE come directly from the curl project but they're originally supplied by the Mozilla foundation. See [https://wiki.mozilla.org/CA](https://wiki.mozilla.org/CA) for more information about this certificate bundle.
+The CA certificates shipped with ES-DE come directly from the curl project but they're originally supplied by the Mozilla foundation. See https://wiki.mozilla.org/CA for more information about this certificate bundle.
-The latest version can be downloaded from [https://curl.se/docs/caextract.html](https://curl.se/docs/caextract.html)
+The latest version can be downloaded from https://curl.se/docs/caextract.html
After downloading the file, rename it from `cacert.pem` to `curl-ca-bundle.crt` and move it to the certificates directory i.e.:
@@ -933,7 +957,7 @@ emulationstation-de/resources/certificates/curl-ca-bundle.crt
ES-DE automatically identifies and excludes MAME BIOS and device files, as well as translating the short MAME ROM names to their full game names. This is done using information from the MAME driver file shipped with the official MAME distribution. The file needs to be converted to an internal format used by ES-DE as the original file is huge and most of the information is not required.
-To get hold of the driver file, go to [https://www.mamedev.org/release.php](https://www.mamedev.org/release.php) and select the Windows version, but only download the driver information in XML format and not MAME itself. This file will be named something like `mame0226lx.zip` and unzipping it will give you a filename such as `mame0226.xml`.
+To get hold of the driver file, go to https://www.mamedev.org/release.php and select the Windows version, but only download the driver information in XML format and not MAME itself. This file will be named something like `mame0226lx.zip` and unzipping it will give you a filename such as `mame0226.xml`.
Move the XML driver file to the resources/MAME directory and then convert it to the ES-DE internal files:
@@ -1760,9 +1784,9 @@ The es_systems.xml file on Android utilizes variables heavily to implement the _
There are two main ways to pass options to emulators, using _extras_ or using the _data_ URI. There can only be a single data URI but there can be an arbitrary amount of extras. To understand more about the way this works, you can read about the _putExtra()_ and and _setData()_ functions here:\
https://developer.android.com/reference/android/content/Intent
-`%EXTRA_` - This passes an _extra_ which contains any additional information that the emulator may support. This is provided as a key/value pair where you define the key name following the literal %EXTRA_ string and terminate it with a % sign and then assign the value using an equal sign. For example %EXTRA_LIBRETRO%=puae_libretro_android.so will pass the extra named _LIBRETRO_ with its value set to _puae_libretro_android.so_. You can pass an unlimited number of extras and you can also use various ROM variables in combination with this as described below. It's also possible to use the `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRA_` variable definition, which will expand to the the directory of the game file, the ROM directory and the path to the game file respectively.
+`%EXTRA_` - This passes an _extra_ which contains any additional information that the emulator may support. This is provided as a key/value pair where you define the key name following the literal %EXTRA_ string and terminate it with a % sign and then assign the value using an equal sign. For example %EXTRA_LIBRETRO%=puae_libretro_android.so will pass the extra named _LIBRETRO_ with its value set to _puae_libretro_android.so_. You can pass an unlimited number of extras and you can also use various ROM variables in combination with this as described below. It's also possible to use the `%BASENAME%`, `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRA_` variable definition, which will expand to the basename of the game file, the directory of the game file, the ROM directory and the path to the game file respectively.
-`%EXTRAARRAY_` - Defines an array of comma-separated string values following the key name. Only literal strings are supported, so this can't be used in combination with any ROM variables. As commas are used as separator characters, you'll need to escape any comma signs that you want to include in the actual value. For example %EXTRAARRAY_Parameters%=pone,p\\,two,pthree will pass the extra named _Parameters_ with the three separate array entries _pone_, _p,two_ and _pthree_. It's also possible to use the `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRAARRAY_` variable definition, which will expand to the the directory of the game file, the ROM directory and the path to the game file respectively.
+`%EXTRAARRAY_` - Defines an array of comma-separated string values following the key name. Only literal strings and special variables are supported, so this can't be used in combination with any ROM variables. As commas are used as separator characters, you'll need to escape any comma signs that you want to include in the actual value. For example %EXTRAARRAY_Parameters%=pone,p\\,two,pthree will pass the extra named _Parameters_ with the three separate array entries _pone_, _p,two_ and _pthree_. It's also possible to use the `%BASENAME%`, `%GAMEDIRRAW%`, `%ROMPATHRAW%` and `%ROMRAW%` variables inside an `%EXTRAARRAY_` variable definition, which will expand to the basename of the game file, the directory of the game file, the ROM directory and the path to the game file respectively.
`%EXTRABOOL_` - Sets an extra with a boolean value, i.e. true/1 or false/0.
@@ -2134,7 +2158,7 @@ Just make sure to not place the portable installation on a network share that us
There are numerous locations throughout ES-DE where custom scripts can be executed if the option to do so has been enabled in the settings. You'll find the option _Enable custom event scripts_ on the Main menu under _Other settings_. By default this setting is deactivated so make sure to enable it to use this feature.
-The approach is quite straightforward, ES-DE will look for any files inside a script directory that corresponds to the event that is triggered and will then attempt to execute all these files (regardless of their file extensions). If you want to have the scripts executed in a certain order you can name them accordingly as they will be sorted and executed in lexicographic order. The sorting is case-sensitive on Unix/Linux and case-insensitive on macOS and Windows. ES-DE will wait for each script to finish its execution before moving on to the next one, so the application will suspend briefly when whatever the script is doing is executing. If you want to avoid this you can setup a wrapper script that executes another script outside the ES-DE scripts directory as a background process. Refer to your operating system documentation on how to accomplish this.
+The approach is quite straightforward, ES-DE will look for any files inside a script directory that corresponds to the event that is triggered and will then attempt to execute all these files (regardless of their file extensions). If you want to have the scripts executed in a certain order you can name them accordingly as they will be sorted and executed in lexicographic order. The sorting is case-sensitive on Linux and Android and case-insensitive on macOS and Windows. ES-DE will wait for each script to finish its execution before moving on to the next one, so the application will suspend briefly when whatever the script is doing is executing. If you want to avoid this you can setup a wrapper script that executes another script outside the ES-DE scripts directory as a background process. Refer to your operating system documentation on how to accomplish this.
On Windows it's also possible to place .lnk shortcut files in the event directories to have these executed in the same manner as a script. Note that while PowerShell scripts can't be executed directly they can be run via either a .lnk shortcut file or a .bat wrapper script where you explicitly call powershell.exe with the -command flag. Just be aware that by default the execution of PowerShell scripts is disabled on Windows. Further details about PowerShell is beyond the scope of this document.
@@ -2161,11 +2185,11 @@ We'll go through two examples:
* Creating a log file that will record the start and end time for each game we play, letting us see how much time we spend on retro-gaming
* Changing the system resolution when launching and returning from a game in order to run the emulator at a lower resolution than ES-DE
-The following examples are for Unix systems, but it works the same way on macOS and Windows (although .bat batch files are used on Windows instead of shell scripts and any spaces in the parameters are not escaped as is the case on Unix and macOS).
+The following examples are for Linux systems, but it works the same way on Android, macOS and Windows (although .bat batch files are used on Windows instead of shell scripts and any spaces in the parameters are not escaped as is the case on Linux, Android and macOS).
As can be seen in the table above, the events executed when a game starts and ends are named _game-start_ and _game-end_
-So let's create the folders for these events in the scripts directory. The location is `~/ES-DE/scripts`
+So let's create the folders for these events inside the application data directory, or more specifically in `~/ES-DE/scripts`
**Game log**
diff --git a/LICENSE b/LICENSE
index 84a609b0d..9e807c8d5 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,3 +1,4 @@
+Copyright (c) 2024 Northwestern Software AB
Copyright (c) 2020-2024 Leon Styhre
Copyright (c) 2014 Alec Lofquist
diff --git a/README.md b/README.md
index 9a57ccce5..c540b3c96 100644
--- a/README.md
+++ b/README.md
@@ -2,7 +2,7 @@
ES-DE (EmulationStation Desktop Edition) is a frontend for browsing and launching games from your multi-platform collection.
-It's officially supported on Linux, macOS, Windows and Android but can also be used on BSD Unix and the Raspberry Pi if you build it yourself from source code.
+It's officially supported on Linux, macOS, Windows and Android but can also be used on Haiku and the Raspberry Pi if you build it yourself from source code. There is also an ES-DE package in the FreeBSD ports collection.
Website:\
https://es-de.org
@@ -27,11 +27,13 @@ https://gitlab.com/es-de/themes/themes-list
## Download
-Visit https://es-de.org to download the latest ES-DE release or go to the [package registry](https://gitlab.com/es-de/emulationstation-de/-/packages) where you can also find most previous releases.
+Visit https://es-de.org to download the latest ES-DE release or go to the [package registry](https://gitlab.com/es-de/emulationstation-de/-/packages) where you can also find a number of previous releases.
-The Android port of ES-DE is a paid app, which you can get on [Patreon](https://www.patreon.com/es_de) or on the [Samsung Galaxy Store](https://galaxystore.samsung.com/detail/org.es_de.frontend.galaxy).
+The Android port of ES-DE is a paid app, which you can get on [Patreon](https://www.patreon.com/es_de), the [Samsung Galaxy Store](https://galaxystore.samsung.com/detail/org.es_de.frontend.galaxy) and [Huawei AppGallery](https://appgallery.huawei.com/#/app/C111315115).
-If you're using a Raspberry Pi or if you run FreeBSD, NetBSD or OpenBSD then you need to compile from source code as no prebuilt packages are provided for these platforms. A detailed build guide is available in [INSTALL.md](INSTALL.md).
+If you're using a Raspberry Pi or if you run Haiku, then you need to compile from source code as no prebuilt packages are provided for these platforms. A detailed build guide is available in [INSTALL.md](INSTALL.md).
+
+If your run FreeBSD then ES-DE is available as an [official port](https://www.freshports.org/emulators/es-de).
## Additional information
diff --git a/ROADMAP.md b/ROADMAP.md
index e37644476..957c20275 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -10,7 +10,6 @@ A more detailed breakdown can be found on the [Kanban](https://gitlab.com/es-de/
* Bulk metadata editor
* Background music
* Controller button mappings from inside ES-DE (similar to pad2key in Batocera)
-* Localization/multi-language support
* Auto-import tools for Android apps, Steam, Lutris etc.
**User interface**
diff --git a/THEMES-DEV.md b/THEMES-DEV.md
index 5287536f0..c410130c7 100644
--- a/THEMES-DEV.md
+++ b/THEMES-DEV.md
@@ -97,14 +97,14 @@ themes/
The ES-DE theme functionality makes it easy for users to install different themes and to choose between them from the _UI Settings_ menu.
There are two places that ES-DE can load themes from:
-* `[HOME]/.emulationstation/themes/`
+* `[HOME]/ES-DE/themes/`
* `[INSTALLATION PATH]/themes/`
An installation path could be something like this:
```
-/usr/share/emulationstation/themes/slate-es-de/
-/Applications/EmulationStation Desktop Edition.app/Contents/Resources/themes/
-C:\Program Files\EmulationStation-DE\themes\
+/usr/share/es-de/themes/
+/Applications/ES-DE.app/Contents/Resources/themes/
+C:\Program Files\ES-DE\themes\
```
If a theme with the same name exists in both locations, the one in the home directory will be loaded and the other one will be skipped.
@@ -145,7 +145,7 @@ As for more specific changes, the following are the most important ones compared
* The helpsystem `textColorDimmed` and `iconColorDimmed` properties (which apply when opening a menu) were always defined under the system view configuration which meant these properties could not be separately set for the gamelist views. Now these properties work as expected with the possibility to configure separate values for the system and gamelist views
* When right-aligning the helpsystem using an X origin value of 1, the element is now aligned correctly to the defined position instead of being offset by the entrySpacing width (in RetroPie ES the offset was instead the hardcoded element entry padding)
* Correct theme structure is enforced more strictly than before, and deviations will generate error log messages and make the theme loading fail
-* Many additional elements and properties have been added, refer to the [Reference](THEMES-DEV.md#reference) section for more information
+* Many additional elements and properties have been added, refer to the reference section for more information
Attempting to use any of the legacy logic in the new theme structure will make the theme loading fail, for example adding the _extra="true"_ attribute to any element.
@@ -298,8 +298,7 @@ This is the element structure:
```
-Finally _properties_ control how a particular element looks and behaves, for example its position, size, image path, animation controls etc. The property type determines what kinds of values you can use. You can read about each type below in the
-[Reference](THEMES-DEV.md#reference) section. Properties are defined like this:
+Finally _properties_ control how a particular element looks and behaves, for example its position, size, image path, animation controls etc. The property type determines what kinds of values you can use. You can read about each type below in the reference section. Properties are defined like this:
```xml
valueHere
@@ -381,12 +380,12 @@ If you are writing a theme it's recommended to enable the _Debug mode_ setting f
Here's an example of launching ES-DE in debug mode at a limited resolution, which will make it run in a window:
```
-emulationstation --debug --resolution 1280 720
+es-de --debug --resolution 1280 720
```
Enforcement of a correct theme configuration is quite strict, and most errors will abort the theme loading, leading to an unthemed system. In each such situation the log output will be very clear of what happened, for instance:
```
-Jan 28 17:17:30 Error: ThemeData::parseElement(): "/home/myusername/.emulationstation/themes/mytheme-es-de/theme.xml": Property "origin" for element "image" has no value defined (system "collections", theme "custom-collections")
+Jan 28 17:17:30 Error: ThemeData::parseElement(): "/home/myusername/ES-DE/themes/mytheme-es-de/theme.xml": Property "origin" for element "image" has no value defined (system "collections", theme "custom-collections")
```
Note that an unthemed system means precisely that, the specific system where the error occured will be unthemed but not necessarily the entire theme. The latter can still happen if the error is global such as a missing variable used by all XML files or an error in a file included by all XML files. The approach is to only untheme relevant sections of the theme to be able to pinpoint precisely where the problem lies.
@@ -396,7 +395,7 @@ Sanitization for valid data format and structure is done in this manner, but ver
Jan 28 17:25:27 Warn: BadgeComponent: Invalid theme configuration, property "horizontalAlignment" for element "gamelistBadges" defined as "leftr"
```
-Note however that warnings are not printed for all invalid properties as that would lead to an excessive amount of logging code. This is especially true for numeric values which are commonly just clamped to the allowable range without notifying the theme author. So make sure to check the [Reference](THEMES-DEV.md#reference) section of this document for valid values for each property.
+Note however that warnings are not printed for all invalid properties as that would lead to an excessive amount of logging code. This is especially true for numeric values which are commonly just clamped to the allowable range without notifying the theme author. So make sure to check the reference section of this document for valid values for each property.
For more serious issues where it does not make sense to assign a default value or auto-adjust the configuration, an error log entry is generated and the element will in most instances not get rendered at all. Here's such an example where the imageType property for a video element was accidentally set to _covr_ instead of _cover_:
@@ -407,12 +406,12 @@ Jan 28 17:29:11 Error: VideoComponent: Invalid theme configuration, property "i
Error handling for missing files is handled a bit differently depending on whether the paths have been defined explicitly or via a variable. For explicitly defined paths a warning will be logged for element properties and an error will be triggered for include files. Here's an example of the latter case:
```
-Jan 28 17:32:29 Error: ThemeData::parseIncludes(): "/home/myusername/.emulationstation/themes/mytheme-es-de/theme.xml" -> "./colors_dark.xml" not found (resolved to "/home/myusername/.emulationstation/themes/mytheme-es-de/colors_dark.xml")
+Jan 28 17:32:29 Error: ThemeData::parseIncludes(): "/home/myusername/ES-DE/themes/mytheme-es-de/theme.xml" -> "./colors_dark.xml" not found (resolved to "/home/myusername/ES-DE/themes/mytheme-es-de/colors_dark.xml")
```
However, if a variable has been used to define the include file, only a debug message will be generated if the file is not found:
```
-Jan 28 17:34:03 Debug: ThemeData::parseIncludes(): "/home/myusername/.emulationstation/themes/mytheme-es-de/theme.xml": Couldn't find file "./${system.theme}/colors.xml" which resolves to "/home/myusername/.emulationstation/themes/mytheme-es-de/amiga/colors.xml"
+Jan 28 17:34:03 Debug: ThemeData::parseIncludes(): "/home/myusername/ES-DE/themes/mytheme-es-de/theme.xml": Couldn't find file "./${system.theme}/colors.xml" which resolves to "/home/myusername/ES-DE/themes/mytheme-es-de/amiga/colors.xml"
```
It works essentially the same way for element path properties as for include files. This distinction between explicit values and variables makes it possible to create a theme configuration where both include files and files for fonts, images, videos etc. will be used if found, and if not found a fallback configuration can still be applied so the system will be themed.
@@ -742,6 +741,204 @@ Here's an example configuration:
```
+## Languages
+
+Multilingual support works very similarly to color schemes and font sizes in that it's a variable-based configuration. Due to this you can set any arbitrary property values you want for a certain language, such as different texts or different images and so on. The supported languages for use in themes are the same as for the overall application.
+
+Note that the word _language_ is not technically the correct term as it's rather _locales_ that are used within ES-DE. For instance the en_US and en_GB locales are both for the English language but rather variations for different countries (United States and United Kingdom). Still, as the term _language_ is colloquially used to describe locales in many applications and operating systems this is also used in ES-DE even if it's not entirely correct. The term _language_ is as such also used throughout this document.
+
+While it's possible to use the theme engine language support to set language-specific date formats this is generally discouraged as it's better to use the ISO 8601 (YYYY-MM-DD) standard instead. This is an international standard that makes sense to use in all countries in the world.
+
+The following languages are supported:
+
+| Language | English name | Native name |
+| :------------ | :----------------------- | :----------------------- |
+| en_US | English (United States) | English (United States) |
+| en_GB | English (United Kingdom) | English (United Kingdom) |
+| de_DE | German | Deutsch |
+| es_ES | Spanish (Spain) | Español (España) |
+| fr_FR | French | Français |
+| it_IT | Italian | Italiano |
+| pl_PL | Polish | Polski |
+| pt_BR | Portuguese (Brazil) | Português (Brasil) |
+| ro_RO | Romanian | Română |
+| ru_RU | Russian | Русский |
+| sv_SE | Swedish | Svenska |
+| ja_JP | Japanese | 日本語 |
+| ko_KR | Korean | 한국어 |
+| zh_CN | Simplified Chinese | 简体中文 |
+
+Note that the native name is what is shown inside the _UI Settings_ menu for the _Theme Language_ and _Application Language_ settings.
+
+You can find more information about locales/languages here:\
+https://simplelocalize.io/data/locales
+
+The languages a theme supports need to be declared in the `capabilities.xml` file using `` tag pairs, such as the following example:
+
+```xml
+
+
+ My theme
+
+ en_US
+ es_ES
+ pt_PR
+ sv_SE
+ zh_CN
+
+
+```
+
+Although language support is optional for a theme, if you have declared at least one language then you have to include support for en_US as well. Attempting to skip an entry for this language will output an error message and the language configuration will not get loaded. The reason for this is that en_US is the default language for the ES-DE application so all themes have to support it, either implicitly (by not having any multilingual support) or explicitly by declaring it and providing localization for it.
+
+It's also possible to provide label translations for variants, color schemes and transitions, as displayed in the _UI Settings_ menu. This is done using the `language` attribute for these `label` entries, as in this example `capabilities.xml` file:
+
+```xml
+
+ My theme
+
+ en_US
+ sv_SE
+
+
+
+
+
+
+
+
+
+ true
+
+ noMedia
+ miximage, screenshot, cover, video
+ noGameMedia
+
+
+
+
+
+
+ true
+ instant
+ slide
+ instant
+ slide
+ slide
+ slide
+
+
+```
+
+Leaving out the `language` property will make ES-DE set the language to en_US.
+
+The actual language-specific values in the theme configuration are defined using variables, like the following example:
+
+```xml
+
+
+
+ logo.svg
+ Developer
+ Publisher
+
+
+
+
+ logo-sv-se.svg
+ Utvecklare
+ Utgivare
+
+
+
+
+
+ 0.38 0.1781
+ 0.158 0.12
+ ./assets/${langLogo}
+
+
+ 0.88 0.511
+ 0.165 0.03
+ ${langLabelDeveloper}
+
+
+ 0.88 0.5935
+ 0.165 0.03
+ ${langLabelPublisher}
+
+
+
+```
+
+It could also be a good idea to include the translations from a separate file:
+```xml
+
+ ./languages.xml
+
+
+
+ 0.38 0.1781
+ 0.158 0.12
+ ./assets/${langLogo}
+
+
+ 0.88 0.511
+ 0.165 0.03
+ ${langLabelDeveloper}
+
+
+ 0.88 0.5935
+ 0.165 0.03
+ ${langLabelPublisher}
+
+
+
+```
+
+Including separate files per language is also supported but it's probably not a good idea as it will add a lot of unnecessary files to the theme:
+```xml
+
+
+ ./lang-en-us.xml
+
+
+ ./lang-sv-se.xml
+
+
+
+
+ 0.38 0.1781
+ 0.158 0.12
+ ./assets/${langLogo}
+
+
+ 0.88 0.511
+ 0.165 0.03
+ ${langLabelDeveloper}
+
+
+ 0.88 0.5935
+ 0.165 0.03
+ ${langLabelPublisher}
+
+
+
+```
+
+Note the naming convention when using localized versions of files such as images. These should include the locale/language in their name and they should be in lowercase characters, using only dashes as separators. For the default language the locale could be omitted from the filename (as language-specific images and similar will likely be exceptions with most files rather shared across all locales). Here are some examples:
+
+```
+logo.svg
+logo-fr-fr.svg
+logo-pt-br.svg
+logo-sv-se.svg
+auto-allgames.webp
+auto-allgames-fr-fr.webp
+auto-allgames-pt-br.webp
+auto-allgames-sv-se.webp
+```
+
## 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.
@@ -900,9 +1097,9 @@ Finally it's possible to apply theme-defined transition profiles on a per-varian
## capabilities.xml
-Variants, variant triggers, color schemes, aspect ratios and transition animation profiles need to be declared before they can be used inside the actual theme configuration files and that is done in the `capabilities.xml` file. This file needs to be located in the root of the theme directory, for example:
+Variants, variant triggers, color schemes, font sizes, languages, aspect ratios and transition animation profiles need to be declared before they can be used inside the actual theme configuration files and that is done in the `capabilities.xml` file. This file needs to be located in the root of the theme directory, for example:
```
-~/.emulationstation/themes/mytheme-es-de/capabilities.xml
+~/ES-DE/themes/mytheme-es-de/capabilities.xml
```
The capabilities.xml file is mandatory and if it doesn't exist ES-DE will not attempt to load the theme.
@@ -914,19 +1111,29 @@ The structure of the file is simple, as can be seen in this example:
My theme
+ en_US
+ sv_SE
+
16:94:34:3_vertical
+ medium
+ large
+
-
+
+
-
+
+
+
+
instantslideinstant
@@ -934,7 +1141,8 @@ The structure of the file is simple, as can be seen in this example:
-
+
+
truenoMedia
@@ -944,7 +1152,8 @@ The structure of the file is simple, as can be seen in this example:
-
+
+
truenoMedia
@@ -959,7 +1168,8 @@ The structure of the file is simple, as can be seen in this example:
```
-The file format is hopefully mostly self-explanatory; this example provides three aspect ratios, two color schemes, one transition animation profile and three variants, one of which is a variant trigger override. The `