mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 21:43:55 -06:00
chore: merge the launcher evidence rule
This commit is contained in:
commit
5c1d810086
50 files changed
+2852
-475
No files matched your search
@@ -32,6 +32,13 @@ systems:
|
||||
standalone_directories:
|
||||
- "getcwd"
|
||||
- "rom_path = kickstarts"
|
||||
config_reads:
|
||||
- file: "*.uae"
|
||||
source_ref: "src/main.cpp:926-934"
|
||||
keys:
|
||||
- key: "kickstart_rom_file"
|
||||
source_ref: "src/cfgfile.cpp:6050, src/memory.cpp:1907-1916"
|
||||
|
||||
notes: |
|
||||
Amiberry 5.6.5 (src/osdep/target.h:27). Every folder it reads is below
|
||||
its start path: $EXTERNAL_FILES_DIR or $XDG_DATA_HOME when either holds a
|
||||
|
||||
@@ -43,6 +43,15 @@ standalone_directories:
|
||||
- "AMIBERRY_HOME_DIR/roms"
|
||||
- "~/Amiberry/roms"
|
||||
- "whdboot_path = whdboot"
|
||||
config_reads:
|
||||
- file: "*.uae"
|
||||
source_ref: "src/main.cpp:986-994"
|
||||
keys:
|
||||
- key: "kickstart_rom_file"
|
||||
source_ref: "src/cfgfile.cpp:6122, src/memory.cpp:1974-1983"
|
||||
- key: "$(FILE_PATH)"
|
||||
source_ref: "src/cfgfile.cpp:389"
|
||||
|
||||
notes: |
|
||||
Amiberry 7.1.1 (CMakeLists.txt:3-4). The ROM path is rom_path in
|
||||
amiberry.conf, else roms/ below the home directory: $AMIBERRY_HOME_DIR,
|
||||
|
||||
@@ -56,6 +56,49 @@ systems:
|
||||
- zx-spectrum
|
||||
- zx-spectrum-128
|
||||
|
||||
config_reads:
|
||||
- file: "settings.bml"
|
||||
source_ref: "desktop-ui/desktop-ui.cpp:9-35, 100-103, 114, desktop-ui/settings/settings.cpp:31-42, 263-286, nall/nall/path.cpp:123-142"
|
||||
keys:
|
||||
- key: "ColecoVision/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/colecovision.cpp:10-12, 42-50, mia/system/colecovision.cpp:7-9"
|
||||
- key: "MSX/Firmware/BIOS.Japan"
|
||||
source_ref: "desktop-ui/emulator/msx.cpp:16-19, 44-53"
|
||||
- key: "FamicomDiskSystem/Firmware/BIOS.Japan"
|
||||
source_ref: "desktop-ui/emulator/famicom-disk-system.cpp:17-19, 89-97"
|
||||
- key:
|
||||
- "Nintendo64DD/Firmware/BIOS.Japan"
|
||||
- "Nintendo64DD/Firmware/BIOS.US"
|
||||
- "Nintendo64DD/Firmware/BIOS.DEV"
|
||||
source_ref: "desktop-ui/emulator/nintendo-64dd.cpp:15-19, 59-73"
|
||||
condition: "the game's region"
|
||||
- key: "GameBoyAdvance/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/game-boy-advance.cpp:12-14, 55-63"
|
||||
- key:
|
||||
- "MasterSystem/Firmware/BIOS.US"
|
||||
- "MasterSystem/Firmware/BIOS.Japan"
|
||||
- "MasterSystem/Firmware/BIOS.Europe"
|
||||
source_ref: "desktop-ui/emulator/master-system.cpp:12-16, 93-107"
|
||||
condition: "the game's region"
|
||||
- key: "GameGear/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/game-gear.cpp:10-12, 30-40"
|
||||
- key:
|
||||
- "MegaCD/Firmware/BIOS.US"
|
||||
- "MegaCD/Firmware/BIOS.Japan"
|
||||
- "MegaCD/Firmware/BIOS.Europe"
|
||||
source_ref: "desktop-ui/emulator/mega-cd.cpp:15-19, 63-77"
|
||||
condition: "the disc's region"
|
||||
- key: "NeoGeoPocket/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket.cpp:10-12, 32-40"
|
||||
- key: "NeoGeoPocketColor/Firmware/BIOS.World"
|
||||
source_ref: "desktop-ui/emulator/neo-geo-pocket-color.cpp:10-12, 32-40"
|
||||
- key:
|
||||
- "PlayStation/Firmware/BIOS.US"
|
||||
- "PlayStation/Firmware/BIOS.Japan"
|
||||
- "PlayStation/Firmware/BIOS.Europe"
|
||||
source_ref: "desktop-ui/emulator/playstation.cpp:19-23, 87-101"
|
||||
condition: "the disc's region"
|
||||
|
||||
notes: |
|
||||
Multi-system emulator by Near (byuu), successor to higan/bsnes. Focuses on
|
||||
accuracy and preservation. 40 emulators registered at this pin
|
||||
|
||||
@@ -48,6 +48,25 @@ data_root:
|
||||
source_ref: "source pcsx2/Pcsx2Config.cpp:2523-2530, pcsx2/Pcsx2Config.cpp:2540-2560, pcsx2/Pcsx2Config.cpp:2567-2589"
|
||||
note: "portable.ini or portable.txt beside the binary makes its folder the root"
|
||||
|
||||
pin_build:
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/armsx2-sa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "19c83bf065ed21a19d8c46a1f578e37d2dab8efd"
|
||||
config_reads:
|
||||
- file: "PCSX2.ini"
|
||||
platforms: [rocknix]
|
||||
source_ref: "pcsx2-qt/QtHost.cpp:1307, 1325-1331, pcsx2/Pcsx2Config.cpp:2398-2491, pcsx2/VMManager.cpp:630-641"
|
||||
keys:
|
||||
- key: "[Folders] Bios"
|
||||
source_ref: "pcsx2/Pcsx2Config.cpp:2514-2524"
|
||||
condition: "[UI] SettingsVersion 1, else the ini is reset (pcsx2-qt/QtHost.cpp:1331-1342)"
|
||||
- key: "[Filenames] BIOS"
|
||||
source_ref: "pcsx2/Pcsx2Config.cpp:1879-1881, 2258-2264, pcsx2/ps2/BiosTools.cpp:258-282, 333-348, pcsx2/VMManager.cpp:1638"
|
||||
condition: "empty: the first PS2 BIOS of 4 to 8 MB found in [Folders] Bios"
|
||||
|
||||
notes: |
|
||||
PlayStation 2 emulator, a GPL-3.0 fork of PCSX2 that replaces the x86-64 only
|
||||
EE, IOP, VU and vtlb fast memory recompilers with native AArch64 ones. One tree
|
||||
|
||||
@@ -32,6 +32,32 @@ data_root:
|
||||
source_ref: "src/frontend/sdl/config.cpp:39-49"
|
||||
note: "~/.config/dsperate when XDG_CONFIG_HOME is unset. System files are read wherever the [paths] keys of the ini point."
|
||||
|
||||
config_reads:
|
||||
- file: "dsperate.ini"
|
||||
platforms: [rocknix]
|
||||
revision: "ddf2910e6d80220c6b22b4df61f0786ac9879cda"
|
||||
revision_from: "PKG_VERSION 3.0.5, the release binaries CI built from tag v3.0.5"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1065, 1155-1157, src/frontend/sdl/config.cpp:64-81"
|
||||
keys:
|
||||
- key:
|
||||
- "[paths] bios9"
|
||||
- "[paths] bios7"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1175, 1270-1274, src/core/nds.cpp:114-129"
|
||||
condition: "both present, otherwise FreeBIOS"
|
||||
- key: "[paths] firmware"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1178, 1270, src/core/nds.cpp:123, 134-135"
|
||||
- key:
|
||||
- "[paths] bios9i"
|
||||
- "[paths] bios7i"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1179-1186, 1319-1322, 1331-1334, src/core/nds_dsi.cpp:88-99"
|
||||
condition: "DSi session"
|
||||
- key: "[paths] dsi_firmware"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1176-1178, 1270"
|
||||
condition: "DSi session"
|
||||
- key: "[paths] dsi_nand"
|
||||
source_ref: "src/frontend/sdl/main.cpp:1158-1162, 1324-1326, 1337, src/core/nds_dsi.cpp:114-120"
|
||||
condition: "--dsi-mode, BootMenuDSi.nds or a .dspr.nds shortcut"
|
||||
|
||||
notes: |
|
||||
Nintendo DS emulator for ARM handhelds with a DSi mode. ROCKNIX installs the
|
||||
release tarball for its architecture and runs it with --config pointing at
|
||||
|
||||
@@ -33,6 +33,61 @@ data_root:
|
||||
source_ref: "src/core/core.cpp:137-151, src/core/core.cpp:190-215"
|
||||
note: "portable.txt or settings.ini beside the executable, or beside the AppImage, makes that folder the root"
|
||||
|
||||
pin_build:
|
||||
- platform: emuelec
|
||||
repo: "https://github.com/EmuELEC/EmuELEC"
|
||||
revision: "v4.8"
|
||||
path: "packages/sx05re/emulators/duckstation/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "fd3507c16d098fb32806c281caaefb205946da8a"
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/duckstation-sa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "0.1-10998"
|
||||
config_reads:
|
||||
- file: "settings.ini"
|
||||
platforms: [emuelec]
|
||||
source_ref: "src/frontend-common/common_host_interface.cpp:403-407, 3042-3050, 3304-3327, src/duckstation-nogui/main.cpp:62-64, 137-140, src/duckstation-nogui/nogui_host_interface.cpp:39-42"
|
||||
keys:
|
||||
- key: "[BIOS] SearchDirectory"
|
||||
source_ref: "src/core/host_interface.cpp:253-260"
|
||||
- key:
|
||||
- "[BIOS] PathNTSCU"
|
||||
- "[BIOS] PathNTSCJ"
|
||||
- "[BIOS] PathPAL"
|
||||
source_ref: "src/core/host_interface.cpp:262-375, src/core/system.cpp:817"
|
||||
condition: "the console region; an empty value scans SearchDirectory"
|
||||
- file: "settings.ini"
|
||||
platforms: [rocknix]
|
||||
revision: "9b0a4ec559ae83bfdb14685932b036ad7c1701be"
|
||||
revision_from: "PKG_VERSION 0.1-10998, the AppImage of tag v0.1-10998"
|
||||
source_ref: "src/core/core.cpp:105-223, 227-230, 232-275, src/duckstation-qt/qthost.cpp:796-800"
|
||||
keys:
|
||||
- key: "[BIOS] SearchDirectory"
|
||||
source_ref: "src/core/settings.cpp:2709-2719, 2723"
|
||||
- key:
|
||||
- "[BIOS] PathNTSCU"
|
||||
- "[BIOS] PathNTSCJ"
|
||||
- "[BIOS] PathPAL"
|
||||
source_ref: "src/core/bios.cpp:351-458, src/core/system.cpp:2923"
|
||||
condition: "the console region; an empty value scans SearchDirectory"
|
||||
- file: "settings.ini"
|
||||
platforms: [retrobat]
|
||||
revision: "5fd366809053fe287291de7a39752c4d5d5b146b"
|
||||
revision_from: "version 0.1-11752-g5fd366809 of duckstation.exe in RetroBat's stable duckstation.7z, 2026-11-10"
|
||||
source_ref: "src/core/core.cpp:131-249, 253-256, 258-301, src/duckstation-qt/qthost.cpp:803-807"
|
||||
keys:
|
||||
- key: "[BIOS] SearchDirectory"
|
||||
source_ref: "src/core/settings.cpp:2859-2869, 2873"
|
||||
- key:
|
||||
- "[BIOS] PathNTSCU"
|
||||
- "[BIOS] PathNTSCJ"
|
||||
- "[BIOS] PathPAL"
|
||||
source_ref: "src/core/bios.cpp:351-456, src/core/system.cpp:2671"
|
||||
condition: "the console region; an empty value scans SearchDirectory"
|
||||
|
||||
notes: |
|
||||
DuckStation auto-detects BIOS by MD5 hash from a flat scan of the BIOS directory.
|
||||
ref: src/core/bios.cpp:458-479 (FindBIOSImagesInDirectory, scans all files by size)
|
||||
|
||||
@@ -17,6 +17,17 @@ standalone_pools:
|
||||
"[IWADSearch.Directories] Path": ""
|
||||
"[IWADSearch.Directories] RecursivePath": ""
|
||||
|
||||
config_reads:
|
||||
- file: "gzdoom.ini"
|
||||
source_ref: "src/gameconfigfile.cpp:95-107, 942-951, src/common/platform/posix/unix/i_specialpaths.cpp:168-171"
|
||||
keys:
|
||||
- key: "[IWADSearch.Directories] Path"
|
||||
source_ref: "src/d_iwad.cpp:456-470"
|
||||
- key: "[FileSearch.Directories] Path"
|
||||
source_ref: "src/common/utility/findfile.cpp:224-260"
|
||||
- key: "[SoundfontSearch.Directories] Path"
|
||||
source_ref: "src/common/audio/music/i_soundfont.cpp:393-410"
|
||||
|
||||
notes: |
|
||||
Doom-engine source port by Christoph Oelckers. Supports Doom, Heretic,
|
||||
Hexen, Strife, Chex Quest and derived games through a unified IWAD
|
||||
|
||||
@@ -38,6 +38,45 @@ data_root:
|
||||
source_ref: "upstream src/paths.c:24-29, upstream src/paths.c:201-274"
|
||||
note: "~/.hatari is used instead when it exists and ~/.config/hatari does not. Holds hatari.cfg, hatari.nvram and auto.sav. The default tos.img is read from ../share/hatari beside the bin directory."
|
||||
|
||||
pin_build:
|
||||
- platform: emuelec
|
||||
repo: "https://github.com/EmuELEC/EmuELEC"
|
||||
revision: "v4.8"
|
||||
path: "packages/sx05re/emulators/hatarisa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "fda67f05188a925535fefc1b0ef24eb044a029d2"
|
||||
- platform: amberelec
|
||||
repo: "https://github.com/AmberELEC/AmberELEC"
|
||||
revision: "a21975bfb1a3af68f66e07a931b994b523e1e6e2"
|
||||
path: "packages/games/emulators/hatarisa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "d876db9c4b6911c059b1d9318f779f90c1c6f2d7"
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/hatarisa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "6da06056d89bb39777063388d82d065d9e2e31fd"
|
||||
config_reads:
|
||||
- file: "*.cfg"
|
||||
platforms: [emuelec]
|
||||
source_ref: "upstream src/options.c:1187-1193, upstream src/configuration.c:1088, 1149"
|
||||
keys:
|
||||
- key: "[ROM] szTosImageFileName"
|
||||
source_ref: "upstream src/configuration.c:481, upstream src/tos.c:975-986"
|
||||
- file: "*.cfg"
|
||||
platforms: [amberelec]
|
||||
source_ref: "upstream src/options.c:1283-1288, upstream src/configuration.c:1061, 1123"
|
||||
keys:
|
||||
- key: "[ROM] szTosImageFileName"
|
||||
source_ref: "upstream src/configuration.c:489, upstream src/tos.c:976-987"
|
||||
- file: "*.cfg"
|
||||
platforms: [rocknix]
|
||||
source_ref: "upstream src/options.c:1194-1199, upstream src/configuration.c:1050, 1111"
|
||||
keys:
|
||||
- key: "[ROM] szTosImageFileName"
|
||||
source_ref: "upstream src/configuration.c:480, upstream src/tos.c:975-986"
|
||||
|
||||
notes: |
|
||||
The main branch of libretro/hatari is the upstream Hatari tree at
|
||||
c453b85f, whose libretro target in src/retro carries the VFS, disk
|
||||
|
||||
@@ -24,6 +24,13 @@ systems: [sony-playstation-2]
|
||||
bios_directory: "pcsx2/bios/"
|
||||
resources_directory: "pcsx2/resources/"
|
||||
|
||||
config_reads:
|
||||
- file: "core options"
|
||||
source_ref: "libretro/main.cpp:506, 525-527"
|
||||
keys:
|
||||
- key: "pcsx2_bios"
|
||||
source_ref: "libretro/main.cpp:525-536, 2552-2560"
|
||||
|
||||
notes: |
|
||||
Hard fork of PCSX2 (pre-Qt, 1.7-dev era) ported to libretro, x86_64 only,
|
||||
with much of the emulator since rewritten in C89. The system directory of
|
||||
|
||||
@@ -43,6 +43,61 @@ systems:
|
||||
- snk-ngpc
|
||||
- sony-playstation
|
||||
|
||||
pin_build:
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/mednafen/package.mk"
|
||||
variable: PKG_URL
|
||||
value: "https://github.com/sydarn/mednafen/archive/refs/tags/1.32.1-chd.tar.gz"
|
||||
config_reads:
|
||||
- file: "mednafen.cfg"
|
||||
platforms: [rocknix]
|
||||
revision: "e46995e49cbaf1e9996a8e29cc5be16d7fe6d834"
|
||||
revision_from: "tag 1.32.1-chd of the sydarn/mednafen fork, the PKG_URL ROCKNIX builds"
|
||||
source_ref: "src/drivers/main.cpp:1469-1520, 1883-1974, 2249, 2405, src/general.cpp:277-300"
|
||||
keys:
|
||||
- key: "gba.bios"
|
||||
source_ref: "src/gba/GBA.cpp:3278, 772, 2472-2481"
|
||||
- key: "md.cdbios"
|
||||
source_ref: "src/md/system.cpp:755, 630-640, src/md/cd/cd.cpp:894-912, 971-982"
|
||||
condition: "CD content"
|
||||
- key: "nes.ggrom"
|
||||
source_ref: "src/nes/nes.cpp:455, 298-299, src/nes/cart.cpp:570-583"
|
||||
condition: "nes.gg 1"
|
||||
- key: "pce.cdbios"
|
||||
source_ref: "src/pce/pce.cpp:1103, 647-649"
|
||||
condition: "disc not detected as Games Express"
|
||||
- key: "pce.gecdbios"
|
||||
source_ref: "src/pce/pce.cpp:1104, 647-649"
|
||||
condition: "disc detected as Games Express"
|
||||
- key: "pce_fast.cdbios"
|
||||
source_ref: "src/pce_fast/pce.cpp:647, 476-487"
|
||||
- key: "pcfx.bios"
|
||||
source_ref: "src/pcfx/pcfx.cpp:1115, 606-611"
|
||||
- key:
|
||||
- "psx.bios_eu"
|
||||
- "psx.bios_jp"
|
||||
- "psx.bios_na"
|
||||
source_ref: "src/psx/psx.cpp:2373-2375, 1764-1775"
|
||||
condition: "the disc's region"
|
||||
- key:
|
||||
- "ss.bios_jp"
|
||||
- "ss.bios_na_eu"
|
||||
source_ref: "src/ss/ss.cpp:2441-2442, 1430-1439"
|
||||
condition: "not ST-V, by SMPC area"
|
||||
- key:
|
||||
- "ss.bios_stv_eu"
|
||||
- "ss.bios_stv_jp"
|
||||
- "ss.bios_stv_na"
|
||||
source_ref: "src/ss/ss.cpp:2444-2446, 1420-1439"
|
||||
condition: "ST-V cart, by area"
|
||||
- key:
|
||||
- "ss.cart.kof95_path"
|
||||
- "ss.cart.ultraman_path"
|
||||
source_ref: "src/ss/ss.cpp:2477-2478, 1811-1840, 1320-1350, 1389-1396"
|
||||
condition: "cart type KOF95 or ULTRAMAN"
|
||||
|
||||
notes: |
|
||||
Multi-system emulator by the Mednafen Team, the upstream of the beetle_* and
|
||||
mednafen_* libretro cores, which are forks of individual modules. A module is
|
||||
|
||||
@@ -28,6 +28,58 @@ data_root:
|
||||
source_ref: "upstream src/frontend/qt_sdl/main.cpp:182-184, 196-200, 206-211"
|
||||
note: "portable beside the executable when that folder exists"
|
||||
|
||||
pin_build:
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/melonds-sa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "906e9ebb27da8c6a715cd7abab4abfe8a8d29427"
|
||||
config_reads:
|
||||
- file: "melonDS.ini"
|
||||
platforms: [rocknix]
|
||||
source_ref: "upstream src/frontend/qt_sdl/main.cpp:366, upstream src/frontend/qt_sdl/Config.cpp:682-774, 777-783, 785-795, upstream src/frontend/qt_sdl/Platform.cpp:144-166, ROCKNIX projects/ROCKNIX/packages/emulators/standalone/melonds-sa/patches/001-default-config.patch:8-13, ROCKNIX projects/ROCKNIX/packages/emulators/standalone/melonds-sa/patches/003-hotkeys.patch:41-76"
|
||||
keys:
|
||||
- key: "BIOS9Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/Config.cpp:238, 240, upstream src/frontend/qt_sdl/EmuInstance.cpp:855-876, 1261-1263"
|
||||
condition: "ExternalBIOSEnable=1"
|
||||
- key: "BIOS7Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/Config.cpp:238, 241, upstream src/frontend/qt_sdl/EmuInstance.cpp:878-898, 1265-1267"
|
||||
condition: "ExternalBIOSEnable=1"
|
||||
- key: "FirmwarePath"
|
||||
source_ref: "upstream src/frontend/qt_sdl/Config.cpp:238, 242, upstream src/frontend/qt_sdl/EmuInstance.cpp:992-1016, 1269"
|
||||
condition: "ExternalBIOSEnable=1 and ConsoleType=0"
|
||||
- key: "DSiNANDPath"
|
||||
source_ref: "upstream src/frontend/qt_sdl/Config.cpp:227, 249, upstream src/frontend/qt_sdl/EmuInstance.cpp:1039-1043, 1227, 1312-1322"
|
||||
condition: "ConsoleType=1"
|
||||
- file: "melonDS.toml"
|
||||
platforms: [emudeck, retrobat]
|
||||
revision: "b86390e4428bf38ce4c1ce0e9ca446d6d25955e8"
|
||||
revision_from: "melonDS 1.1: the Flathub manifest net.kuribo64.melonDS at e5ce4504 builds it, and RetroBat's melonDS.exe names it"
|
||||
source_ref: "upstream src/frontend/qt_sdl/main.cpp:196-213, 328, upstream src/frontend/qt_sdl/Config.cpp:42, 785-799"
|
||||
keys:
|
||||
- key: "[DS] BIOS9Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:868-889, 1277"
|
||||
condition: "[Emu] ExternalBIOSEnable = true"
|
||||
- key: "[DS] BIOS7Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:891-911"
|
||||
condition: "[Emu] ExternalBIOSEnable = true"
|
||||
- key: "[DS] FirmwarePath"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:1013-1031, 1285"
|
||||
condition: "[Emu] ExternalBIOSEnable = true and ConsoleType = 0"
|
||||
- key: "[DSi] BIOS9Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:913-938, 1328-1336"
|
||||
condition: "[Emu] ConsoleType = 1"
|
||||
- key: "[DSi] BIOS7Path"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:940-965, 1328-1332"
|
||||
condition: "[Emu] ConsoleType = 1"
|
||||
- key: "[DSi] FirmwarePath"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:1013-1029, 1285"
|
||||
condition: "[Emu] ConsoleType = 1"
|
||||
- key: "[DSi] NANDPath"
|
||||
source_ref: "upstream src/frontend/qt_sdl/EmuInstance.cpp:1064-1068, 1338-1340"
|
||||
condition: "[Emu] ConsoleType = 1"
|
||||
|
||||
notes: |
|
||||
FreeBIOS fallback for DS mode (NTR), while DSi mode requires all native files.
|
||||
Libretro fork based on melonDS ~0.9.x era, validates size only.
|
||||
|
||||
@@ -24,6 +24,14 @@ cores:
|
||||
systems:
|
||||
- nintendo-gba
|
||||
|
||||
config_reads:
|
||||
- file: "/storage/.config/nanoboyadvance/config.toml"
|
||||
platforms: [rocknix]
|
||||
source_ref: "src/platform/sdl/main.cpp:293, src/platform/core/src/config.cpp:16-31"
|
||||
keys:
|
||||
- key: "[general] bios_path"
|
||||
source_ref: "src/platform/core/src/config.cpp:36, src/platform/sdl/main.cpp:177-191, src/platform/core/src/loader/bios.cpp:19-46"
|
||||
|
||||
notes: |
|
||||
Game Boy Advance emulator. ROCKNIX builds the SDL2 frontend only
|
||||
(PLATFORM_SDL2=ON, PLATFORM_QT=OFF).
|
||||
|
||||
@@ -45,6 +45,37 @@ data_root:
|
||||
source_ref: "ui/xemu-settings.cc:51-63, 73-92"
|
||||
note: "xemu.toml beside the executable makes its folder the root"
|
||||
|
||||
pin_build:
|
||||
- platform: rocknix
|
||||
repo: "https://github.com/ROCKNIX/distribution"
|
||||
revision: "20261101"
|
||||
path: "projects/ROCKNIX/packages/emulators/standalone/xemu-sa/package.mk"
|
||||
variable: PKG_VERSION
|
||||
value: "cbffb57d084c70351a596e99e32a8b73e0c5eabf"
|
||||
config_reads:
|
||||
- file: "xemu.toml"
|
||||
platforms: [rocknix]
|
||||
source_ref: "ui/xemu.c:1314-1325, ui/xemu-settings.cc:65-71, 94-104, 158-207"
|
||||
keys:
|
||||
- key: "[sys.files] bootrom_path"
|
||||
source_ref: "system/vl.c:2983-3016"
|
||||
- key: "[sys.files] flashrom_path"
|
||||
source_ref: "system/vl.c:3041-3054"
|
||||
condition: "[general] show_welcome false"
|
||||
- key: "[sys.files] eeprom_path"
|
||||
source_ref: "system/vl.c:2909-2949, 3030-3039"
|
||||
- key: "[sys.files] hdd_path"
|
||||
source_ref: "system/vl.c:3060-3074"
|
||||
- file: "xemu.toml"
|
||||
platforms: [retrobat]
|
||||
revision: "fc24584ce88f0915ad7f04775bb7712c2e3f49ee"
|
||||
revision_from: "xemu.exe 0.8.136 in RetroBat's stable xemu.7z, 2026-11-10"
|
||||
source_ref: "ui/xemu.c:1325, ui/xemu-settings.cc:51-63, 73-92, 94-104, 158-207"
|
||||
keys:
|
||||
- key: "[sys.files] flashrom_path"
|
||||
source_ref: "system/vl.c:3041-3054"
|
||||
condition: "[general] show_welcome false"
|
||||
|
||||
notes: |
|
||||
Full-system Xbox emulator built on QEMU. The libretro core is built from
|
||||
libretro's xemu-libretro tree on its libretro branch, which merges
|
||||
|
||||
@@ -29,6 +29,57 @@ standalone_pools:
|
||||
rompath: ""
|
||||
"-rompath": ""
|
||||
|
||||
config_reads:
|
||||
- file: "xroar.conf"
|
||||
source_ref: "src/xroar.c:882-909, 975-993"
|
||||
keys:
|
||||
- key: "rompath"
|
||||
source_ref: "src/xroar.c:3266, src/romlist.c:125-140"
|
||||
- key:
|
||||
- "romlist dragon"
|
||||
- "romlist d64_1"
|
||||
- "romlist d64_2"
|
||||
- "romlist d32"
|
||||
- "romlist d200e_1"
|
||||
- "romlist d200e_2"
|
||||
- "romlist dragon64"
|
||||
- "romlist dragon64_alt"
|
||||
- "romlist dragon32"
|
||||
- "romlist dragon200e"
|
||||
- "romlist dragon200e_alt"
|
||||
- "romlist dragon200e_charset"
|
||||
- "romlist dragonpro_boot"
|
||||
- "romlist dragonpro_basic"
|
||||
- "romlist coco"
|
||||
- "romlist coco_ext"
|
||||
- "romlist deluxecoco"
|
||||
- "romlist deluxecoco1"
|
||||
- "romlist deluxecoco2"
|
||||
- "romlist deluxecoco3"
|
||||
- "romlist mx1600"
|
||||
- "romlist mx1600ext"
|
||||
- "romlist coco3"
|
||||
- "romlist coco3p"
|
||||
- "romlist glenside_ide"
|
||||
- "romlist mc10"
|
||||
- "romlist alice"
|
||||
- "romlist dragondos"
|
||||
- "romlist dosplus"
|
||||
- "romlist superdos"
|
||||
- "romlist cumana"
|
||||
- "romlist dragondos_compat"
|
||||
- "romlist rsdos"
|
||||
- "romlist delta"
|
||||
- "romlist rsdos_becker"
|
||||
- "romlist mcx128"
|
||||
- "romlist mcx128_azerty"
|
||||
source_ref: "src/xroar.c:646-731, 3267, src/romlist.c:125-140"
|
||||
- file: "command line"
|
||||
source_ref: "src/xroar.c:1007"
|
||||
keys:
|
||||
- key: "-rompath"
|
||||
source_ref: "src/xroar.c:3266, src/romlist.c:125-140"
|
||||
|
||||
notes: |
|
||||
XRoar by Ciaran Anscomb emulates Dragon 32/64, Tandy CoCo 1/2/3,
|
||||
MC-10, Alice, and clones (MX-1600, CP-400, Dragon 200-E, Deluxe CoCo).
|
||||
|
||||
+24
-21
@@ -3180,6 +3180,11 @@ launchers:
|
||||
search_dir: ~/roms/bios
|
||||
passes_to: retroarch.cfg system_directory
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/retroarch/retroarch.cfg
|
||||
source_ref: "packages/sysutils/systemd/scripts/userconfig-setup:20"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "packages/games/tools/retroarch/sources/retroarch.cfg:611"
|
||||
- emulator: retrorun
|
||||
build: libretro
|
||||
@@ -3198,25 +3203,6 @@ launchers:
|
||||
fails_when_missing: false
|
||||
depends_on_option: self.emulator == 'mame'
|
||||
source_ref: "packages/amberelec/sources/scripts/runemu.py:233, 252, 255"
|
||||
- emulator: atari800
|
||||
build: libretro
|
||||
kind: fixed_name
|
||||
names:
|
||||
- ATARIOSA.ROM
|
||||
- ATARIXL.ROM
|
||||
- 5200.rom
|
||||
- 5200a.rom
|
||||
- BASIC_Rev_A.rom
|
||||
- BASIC_Rev_B.rom
|
||||
- ATARIBAS.ROM
|
||||
- ATARIOSB.ROM
|
||||
case_insensitive: false
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: atari800.cfg ROM_OS_A_PAL, ROM_OS_BB01R2, ROM_5200, ROM_5200_A, ROM_BASIC_A,
|
||||
ROM_BASIC_B, ROM_BASIC_C, ROM_400/800_CUSTOM
|
||||
fails_when_missing: false
|
||||
source_ref: "packages/games/libretro/atari800/patches/atari800-01-add-emuelec-platform.patch:27,\
|
||||
\ packages/amberelec/config/distribution/configs/atari800.cfg:3, 8, 16-22"
|
||||
- emulator: scummvm
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
@@ -3291,7 +3277,13 @@ launchers:
|
||||
passes_to: "AmigaA1200-default.uae kickstart_rom_file, $(FILE_PATH) = /storage/.config/amiberry/kickstarts/"
|
||||
fails_when_missing: false
|
||||
depends_on_option: "[ `echo $1 | egrep 'AGA|CD32' | wc -l` -eq 1 -o `echo \"$AMIBERRY_TMP_DIR\"\
|
||||
/* | egrep 'AGA|CD32' | wc -l` -eq 1 ]"
|
||||
/* | egrep 'AGA|CD32' | wc -l` -eq 1 ], content not booted with --autoload, a\
|
||||
\ WHDLoad .lha or .zip (amiberry.sh:83, 122)"
|
||||
installs:
|
||||
path: /tmp/emulation/amiberry/.amiberry_conf.uae
|
||||
source_ref: "packages/games/emulators/amiberry/scripts/amiberry.sh:59"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "packages/amberelec/sources/scripts/runemu.py:111, packages/games/emulators/amiberry/scripts/amiberry.sh:57-59,\
|
||||
\ packages/games/emulators/amiberry/config/conf/AmigaA1200-default.uae:35, 85"
|
||||
- emulator: AMIBERRY
|
||||
@@ -3305,7 +3297,13 @@ launchers:
|
||||
passes_to: "AmigaA500-default.uae kickstart_rom_file, $(FILE_PATH) = /storage/.config/amiberry/kickstarts/"
|
||||
fails_when_missing: false
|
||||
depends_on_option: "not ([ `echo $1 | egrep 'AGA|CD32' | wc -l` -eq 1 -o `echo \"\
|
||||
$AMIBERRY_TMP_DIR\"/* | egrep 'AGA|CD32' | wc -l` -eq 1 ])"
|
||||
$AMIBERRY_TMP_DIR\"/* | egrep 'AGA|CD32' | wc -l` -eq 1 ]), content not booted\
|
||||
\ with --autoload, a WHDLoad .lha or .zip (amiberry.sh:83, 122)"
|
||||
installs:
|
||||
path: /tmp/emulation/amiberry/.amiberry_conf.uae
|
||||
source_ref: "packages/games/emulators/amiberry/scripts/amiberry.sh:62"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "packages/amberelec/sources/scripts/runemu.py:111, packages/games/emulators/amiberry/scripts/amiberry.sh:60-62,\
|
||||
\ packages/games/emulators/amiberry/config/conf/AmigaA500-default.uae:35, 85"
|
||||
- emulator: HATARISA
|
||||
@@ -3317,6 +3315,11 @@ launchers:
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "Atari-ST-default.cfg [ROM] szTosImageFileName"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /tmp/hatari/.hatari-temp.cfg
|
||||
source_ref: "packages/games/emulators/hatarisa/scripts/hatari.sh:36"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "packages/amberelec/sources/scripts/runemu.py:113, packages/games/emulators/hatarisa/scripts/hatari.sh:36,\
|
||||
\ 66, packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg:200"
|
||||
- emulator: pico8
|
||||
|
||||
+105
-2
@@ -937,6 +937,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml ColecoVision/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:270, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -948,6 +954,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml MSX/Firmware/BIOS.Japan
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:278, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -959,6 +971,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml MSX2/Firmware/BIOS.Japan
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:283, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -971,6 +989,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml PCEngineCD/Firmware/BIOS.US, PCEngineCD/Firmware/BIOS.Japan
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:291-292, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -982,6 +1006,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml SuperGrafxCD/Firmware/BIOS.Japan
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:300, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -993,6 +1023,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml FamicomDiskSystem/Firmware/BIOS.Japan
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:308, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1007,6 +1043,12 @@ launchers:
|
||||
passes_to: settings.bml Nintendo64DD/Firmware/BIOS.Japan, Nintendo64DD/Firmware/BIOS.US,
|
||||
Nintendo64DD/Firmware/BIOS.DEV
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:319-321, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1018,6 +1060,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml GameBoyAdvance/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:332, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1032,6 +1080,12 @@ launchers:
|
||||
passes_to: settings.bml MasterSystem/Firmware/BIOS.US, MasterSystem/Firmware/BIOS.Japan,
|
||||
MasterSystem/Firmware/BIOS.Europe
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:340-342, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1043,6 +1097,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml GameGear/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:347, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1056,6 +1116,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml MegaCD/Firmware/BIOS.US, MegaCD/Firmware/BIOS.Japan, MegaCD/Firmware/BIOS.Europe
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:358-360, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1067,6 +1133,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml NeoGeoAES/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:368, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1078,6 +1150,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml NeoGeoPocket/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:378, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1089,6 +1167,12 @@ launchers:
|
||||
search_dir: "${biosPath}"
|
||||
passes_to: settings.bml NeoGeoPocketColor/Firmware/BIOS.World
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:383, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: ares
|
||||
@@ -1103,6 +1187,12 @@ launchers:
|
||||
passes_to: settings.bml PlayStation/Firmware/BIOS.US, PlayStation/Firmware/BIOS.Japan,
|
||||
PlayStation/Firmware/BIOS.Europe
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: "${HOME}/.var/app/dev.ares.ares/data/ares/settings.bml"
|
||||
source_ref: "functions/EmuScripts/emuDeckares.sh:26, 42, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/dev.ares.ares/data/ares/settings.bml:388-390, functions/EmuScripts/emuDeckares.sh:6,\
|
||||
\ 63-64"
|
||||
- emulator: melonds
|
||||
@@ -1121,6 +1211,12 @@ launchers:
|
||||
DSiFirmwarePath, DSiNANDPath
|
||||
fails_when_missing: false
|
||||
depends_on_option: ExternalBIOSEnable = 0 in the shipped melonDS.ini
|
||||
installs:
|
||||
path: "${HOME}/.var/app/net.kuribo64.melonDS/config/melonDS/melonDS.ini"
|
||||
source_ref: "functions/EmuScripts/emuDeckMelonDS.sh:29, 48, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "functions/EmuScripts/emuDeckMelonDS.sh:7, 62-68, 71-77, configs/net.kuribo64.melonDS/config/melonDS/melonDS.ini:77"
|
||||
- emulator: melonds
|
||||
build: standalone
|
||||
@@ -1137,8 +1233,15 @@ launchers:
|
||||
passes_to: "melonDS.toml [DS] FirmwarePath, BIOS7Path, BIOS9Path [DSi] FirmwarePath,\
|
||||
\ NANDPath, BIOS7Path, BIOS9Path"
|
||||
fails_when_missing: false
|
||||
depends_on_option: ExternalBIOSEnable = false in the shipped melonDS.toml
|
||||
source_ref: "configs/net.kuribo64.melonDS/config/melonDS/melonDS.toml:176, 181-183,\
|
||||
depends_on_option: "[DS] keys: ExternalBIOSEnable = true, false in the shipped melonDS.toml;\
|
||||
\ [DSi] keys: ConsoleType = 1, 0 in the shipped melonDS.toml"
|
||||
installs:
|
||||
path: "${HOME}/.var/app/net.kuribo64.melonDS/config/melonDS/melonDS.toml"
|
||||
source_ref: "functions/EmuScripts/emuDeckMelonDS.sh:29, 48, functions/configEmuFP.sh:11,\
|
||||
\ 15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "configs/net.kuribo64.melonDS/config/melonDS/melonDS.toml:176-178, 181-183,\
|
||||
\ 186-189, functions/EmuScripts/emuDeckMelonDS.sh:8, 32"
|
||||
- emulator: mupen64plus_next
|
||||
build: standalone
|
||||
|
||||
+138
-91
@@ -4241,96 +4241,6 @@ launchers:
|
||||
fails_when_missing: false
|
||||
depends_on_option: /storage/roms/bios/mame/ini/mame.ini absent
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame
|
||||
passes_to: mame.ini homepath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:10, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/bios
|
||||
passes_to: mame.ini rompath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:11, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/hash
|
||||
passes_to: mame.ini hashpath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:12, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/samples
|
||||
passes_to: mame.ini samplepath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:13, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/artwork
|
||||
passes_to: mame.ini artpath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:14, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/ini
|
||||
passes_to: mame.ini inipath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:16, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/cheat
|
||||
passes_to: mame.ini cheatpath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:18, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/crosshair
|
||||
passes_to: mame.ini crosshairpath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:19, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: passes_path
|
||||
names: []
|
||||
search_dir: /storage/roms/bios/mame/plugins
|
||||
passes_to: mame.ini pluginspath
|
||||
fails_when_missing: false
|
||||
depends_on_option: mame_read_config = enabled
|
||||
source_ref: "packages/sx05re/libretro/mame/config/ini/mame.ini:20, packages/sx05re/libretro/mame/config/MAME/MAME.opt:19,\
|
||||
\ packages/sx05re/emuelec/bin/emuelecRunEmu.sh:357-358, packages/sx05re/libretro/mame/scripts/mame.sh:21-23"
|
||||
- emulator: pico8
|
||||
build: standalone
|
||||
kind: moves
|
||||
@@ -4384,6 +4294,11 @@ launchers:
|
||||
passes_to: "settings.ini [BIOS] SearchDirectory (-settings), [BIOS] PathNTSCU, PathNTSCJ,\
|
||||
\ PathPAL unset"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/duckstation/settings.ini
|
||||
source_ref: "packages/sx05re/emulators/duckstation/scripts/duckstation.sh:15"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:207-209, packages/sx05re/emulators/duckstation/config/settings.ini:6-9,\
|
||||
\ packages/sx05re/emulators/duckstation/package.mk:56, packages/sx05re/emulators/duckstation/scripts/duckstation.sh:40"
|
||||
- emulator: yabasanshiroSA
|
||||
@@ -4439,6 +4354,11 @@ launchers:
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "Atari-ST-default.cfg [ROM] szTosImageFileName (--configfile)"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /tmp/hatari/.hatari-temp.cfg
|
||||
source_ref: "packages/sx05re/emulators/hatarisa/scripts/hatari.start:36"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:172-174, packages/sx05re/emulators/hatarisa/config/conf/Atari-ST-default.cfg:200,\
|
||||
\ packages/sx05re/emulators/hatarisa/package.mk:39, packages/sx05re/emulators/hatarisa/scripts/hatari.start:36,\
|
||||
\ 66, 73"
|
||||
@@ -4450,6 +4370,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_artwork
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4463,6 +4389,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/artwork
|
||||
passes_to: advmame.rc dir_artwork
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4475,6 +4407,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_diff
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4488,6 +4426,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/diff
|
||||
passes_to: advmame.rc dir_diff
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4500,6 +4444,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_hi
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4513,6 +4463,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/hi
|
||||
passes_to: advmame.rc dir_hi
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4525,6 +4481,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_image
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4538,6 +4500,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/image
|
||||
passes_to: advmame.rc dir_image
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4550,6 +4518,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_inp
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4563,6 +4537,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/inp
|
||||
passes_to: advmame.rc dir_inp
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4575,6 +4555,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_memcard
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4588,6 +4574,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/memcard
|
||||
passes_to: advmame.rc dir_memcard
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4600,6 +4592,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_nvram
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4613,6 +4611,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/nvram
|
||||
passes_to: advmame.rc dir_nvram
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4625,6 +4629,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_rom
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4638,6 +4648,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade
|
||||
passes_to: advmame.rc dir_rom
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4649,6 +4665,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/advmame/samples
|
||||
passes_to: advmame.rc dir_sample
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:80"
|
||||
@@ -4660,6 +4682,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_snap
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4673,6 +4701,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/snap
|
||||
passes_to: advmame.rc dir_snap
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4685,6 +4719,12 @@ launchers:
|
||||
passes_to: advmame.rc dir_sta
|
||||
fails_when_missing: false
|
||||
depends_on_option: system != arcade
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4698,6 +4738,12 @@ launchers:
|
||||
search_dir: /storage/roms/arcade/nvram
|
||||
passes_to: advmame.rc dir_sta
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /emuelec/configs/advmame/advmame.rc
|
||||
source_ref: "packages/sx05re/emulators/advancemame/bin/advmame.sh:17, 21"
|
||||
kept_if_present: false
|
||||
overrides:
|
||||
- "packages/sx05re/emulators/advancemame/bin/advmame.sh:27"
|
||||
source_ref: "packages/sx05re/emuelec/bin/emuelecRunEmu.sh:213-215, packages/sx05re/emulators/advancemame/config/advmame.rc_oga:1-11,\
|
||||
\ packages/sx05re/emulators/advancemame/config/advmame.rc_gf:1-11, packages/sx05re/emulators/advancemame/config/advmame.rc:4-14,\
|
||||
\ packages/sx05re/emulators/advancemame/package.mk:45-49, packages/sx05re/emulators/advancemame/bin/advmame.sh:26-27,\
|
||||
@@ -4720,7 +4766,8 @@ launchers:
|
||||
search_dir: /storage/.config/scummvm
|
||||
passes_to: /storage/roms/bios/scummvm.ini
|
||||
fails_when_missing: false
|
||||
depends_on_option: scummvm.start add
|
||||
depends_on_option: "scummvm.start add, an action no launch runs (emuelecRunEmu.sh\
|
||||
\ passes libretro, sa)"
|
||||
source_ref: "packages/sx05re/emulators/scummvmsa/bin/scummvm.start:9, 49-51, 54"
|
||||
- emulator: dolphin
|
||||
build: standalone
|
||||
|
||||
@@ -5662,9 +5662,10 @@ launchers:
|
||||
depends_on_option: "bootdisk (not (messSysName[messMode] == '' or messMode == -1)\
|
||||
\ and softList == '' and system.name == 'macintosh' and system.isOptSet('bootdisk')\
|
||||
\ and not (system.config['bootdisk'] in ['macos30', 'macos608', 'macos701', 'macos75']))"
|
||||
choices_from: "package/emulationstation/knulli-es-system/es_features.yml:11037-11043"
|
||||
source_ref: "package/system/knulli-configgen/configgen/configgen/generators/mame/mameGenerator.py:303-305,\
|
||||
\ 375-379, 384-385, package/emulationstation/knulli-es-system/es_features.yml:11037-11043"
|
||||
- emulator: mame, mess, mamevirtual, same_cdi
|
||||
\ 375-379, 384-385"
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: fixed_name
|
||||
names:
|
||||
@@ -5685,7 +5686,7 @@ launchers:
|
||||
\ in ['macos30', 'macos608', 'macos701', 'macos75'])"
|
||||
source_ref: "package/system/knulli-configgen/configgen/configgen/generators/libretro/libretroMAMEConfig.py:64,\
|
||||
\ 123, 197, 265-268, 270, 274"
|
||||
- emulator: mame, mess, mamevirtual, same_cdi
|
||||
- emulator: mame
|
||||
build: libretro
|
||||
kind: fixed_name
|
||||
names:
|
||||
@@ -5704,8 +5705,9 @@ launchers:
|
||||
\ 'plugnplay', 'vis']) and not (messSysName[messMode] == '') and not (softList\
|
||||
\ != '') and system.name == 'macintosh' and system.isOptSet('bootdisk') and not\
|
||||
\ (system.config['bootdisk'] in ['macos30', 'macos608', 'macos701', 'macos75']))"
|
||||
choices_from: "package/emulationstation/knulli-es-system/es_features.yml:3727-3733"
|
||||
source_ref: "package/system/knulli-configgen/configgen/configgen/generators/libretro/libretroMAMEConfig.py:64,\
|
||||
\ 123, 197, 265-268, 273-274, package/emulationstation/knulli-es-system/es_features.yml:3727-3733"
|
||||
\ 123, 197, 265-268, 273-274"
|
||||
- emulator: dolphin
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
|
||||
+26
-14
@@ -4259,7 +4259,8 @@ launchers:
|
||||
passes_to: "settings.ini [BIOS] PathNTSCJ = PathNTSCU = PathPAL = <value>"
|
||||
fails_when_missing: not checked by the launcher
|
||||
depends_on_option: duck_bios
|
||||
source_ref: "emulatorLauncher/Generators/Duckstation.Generator.cs:197-202, .emulationstation/es_features.cfg:12489-12497"
|
||||
choices_from: ".emulationstation/es_features.cfg:12489-12497"
|
||||
source_ref: "emulatorLauncher/Generators/Duckstation.Generator.cs:197-202"
|
||||
- emulator: eka2l1
|
||||
build: standalone
|
||||
kind: passes_path
|
||||
@@ -4599,7 +4600,8 @@ launchers:
|
||||
passes_to: "hatari.cfg [ROM] szTosImageFileName=<bios>/hatari/tos/<value>"
|
||||
fails_when_missing: ApplicationException 'Missing TOS file <tosName> in 'bios' folder.'
|
||||
depends_on_option: hatari_tos
|
||||
source_ref: "emulatorLauncher/Generators/Hatari.Generator.cs:410-415, 454, .emulationstation/es_features.cfg:13768-13774"
|
||||
choices_from: ".emulationstation/es_features.cfg:13768-13774"
|
||||
source_ref: "emulatorLauncher/Generators/Hatari.Generator.cs:410-415, 454"
|
||||
- emulator: hatari
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
@@ -4639,7 +4641,8 @@ launchers:
|
||||
passes_to: hatari_tosimage = <value>, if the file is there | default
|
||||
fails_when_missing: hatari_tosimage = default
|
||||
depends_on_option: hatari2014_tos
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3409-3417, .emulationstation/es_features.cfg:7095-7102"
|
||||
choices_from: ".emulationstation/es_features.cfg:7095-7102"
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3409-3417"
|
||||
- emulator: hatarib
|
||||
build: libretro
|
||||
kind: fixed_name
|
||||
@@ -4667,8 +4670,8 @@ launchers:
|
||||
passes_to: hatarib_tos = hatarib/<value>
|
||||
fails_when_missing: hatarib_tos = <etos1024k>, or <tos.img> when bios holds it
|
||||
depends_on_option: hatarib_tos
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3434-3435, 3457-3474,\
|
||||
\ .emulationstation/es_features.cfg:7125-7134"
|
||||
choices_from: ".emulationstation/es_features.cfg:7125-7134"
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3434-3435, 3457-3474"
|
||||
- emulator: hatarib
|
||||
build: libretro
|
||||
kind: copies
|
||||
@@ -4885,7 +4888,8 @@ launchers:
|
||||
fails_when_missing: falls back to dsi_nand.bin
|
||||
depends_on_option: melonds_console == "dsi", melonds_nandregion set, rom extension
|
||||
not ".bin"
|
||||
source_ref: "emulatorLauncher/Generators/MelonDS.Generator.cs:193-202, .emulationstation/es_features.cfg:16816-16823"
|
||||
choices_from: ".emulationstation/es_features.cfg:16816-16823"
|
||||
source_ref: "emulatorLauncher/Generators/MelonDS.Generator.cs:193-202"
|
||||
- emulator: mesen
|
||||
build: standalone
|
||||
kind: copies
|
||||
@@ -5081,7 +5085,8 @@ launchers:
|
||||
passes_to: "kronos.ini [1.0] General\\Bios = <bios>/<value>, only if the file exists"
|
||||
fails_when_missing: General\Bios not written
|
||||
depends_on_option: kronos_force_bios
|
||||
source_ref: "emulatorLauncher/Generators/Kronos.Generator.cs:162-170, .emulationstation/es_features.cfg:14519-14524"
|
||||
choices_from: ".emulationstation/es_features.cfg:14519-14524"
|
||||
source_ref: "emulatorLauncher/Generators/Kronos.Generator.cs:162-170"
|
||||
- emulator: ssf
|
||||
build: standalone
|
||||
kind: core_option
|
||||
@@ -5094,7 +5099,8 @@ launchers:
|
||||
passes_to: "SSF.ini [Peripheral] SaturnBIOS = <bios>/<value>, only if the file exists"
|
||||
fails_when_missing: SaturnBIOS not written
|
||||
depends_on_option: use_external_bios
|
||||
source_ref: "emulatorLauncher/Generators/SSF.Generator.cs:76-83, .emulationstation/es_features.cfg:20762-20767"
|
||||
choices_from: ".emulationstation/es_features.cfg:20762-20767"
|
||||
source_ref: "emulatorLauncher/Generators/SSF.Generator.cs:76-83"
|
||||
- emulator: yabasanshiro
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
@@ -5119,7 +5125,8 @@ launchers:
|
||||
\ exists"
|
||||
fails_when_missing: General\Bios not written
|
||||
depends_on_option: yabasanshiro_force_bios
|
||||
source_ref: "emulatorLauncher/Generators/Yabasanshiro.Generator.cs:123-131, .emulationstation/es_features.cfg:22724-22729"
|
||||
choices_from: ".emulationstation/es_features.cfg:22724-22729"
|
||||
source_ref: "emulatorLauncher/Generators/Yabasanshiro.Generator.cs:123-131"
|
||||
- emulator: ymir
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
@@ -5144,7 +5151,8 @@ launchers:
|
||||
\ check"
|
||||
fails_when_missing: path written without an existence check
|
||||
depends_on_option: ymir_force_bios
|
||||
source_ref: "emulatorLauncher/Generators/Ymir.Generator.cs:120-125, .emulationstation/es_features.cfg:22784-22788"
|
||||
choices_from: ".emulationstation/es_features.cfg:22784-22788"
|
||||
source_ref: "emulatorLauncher/Generators/Ymir.Generator.cs:120-125"
|
||||
- emulator: ymir
|
||||
build: standalone
|
||||
kind: passes_path
|
||||
@@ -5222,7 +5230,8 @@ launchers:
|
||||
fails_when_missing: ApplicationException 'BIOS file <pcsx2Bios> does not exist in
|
||||
'<ps2BiosFolder>'.'
|
||||
depends_on_option: lrps2_bios
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3695-3704, .emulationstation/es_features.cfg:5875-5881"
|
||||
choices_from: ".emulationstation/es_features.cfg:5875-5881"
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3695-3704"
|
||||
- emulator: pcsx2
|
||||
build: libretro
|
||||
kind: scans_dir
|
||||
@@ -5635,8 +5644,10 @@ launchers:
|
||||
search_dir: bios
|
||||
passes_to: "xemu.toml [sys.files] flashrom_path=<bios>/<value>, default Complex_4627.bin"
|
||||
fails_when_missing: path written without an existence check
|
||||
depends_on_option: xemu_flashrom
|
||||
source_ref: "emulatorLauncher/Generators/Xemu.Generator.cs:286-289, .emulationstation/es_features.cfg:22081-22085"
|
||||
depends_on_option: "xemu_flashrom, not (emulator == \"xemu-chihiro\" || system ==\
|
||||
\ \"chihiro\")"
|
||||
choices_from: ".emulationstation/es_features.cfg:22081-22085"
|
||||
source_ref: "emulatorLauncher/Generators/Xemu.Generator.cs:48, 284-289"
|
||||
- emulator: xemu
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
@@ -5752,7 +5763,8 @@ launchers:
|
||||
- coco3h
|
||||
- coco3p
|
||||
- coco3ph
|
||||
source_ref: "emulatorLauncher/Generators/Xroar.Generator.cs:76-80, .emulationstation/es_features.cfg:22650-22659"
|
||||
choices_from: ".emulationstation/es_features.cfg:22650-22659"
|
||||
source_ref: "emulatorLauncher/Generators/Xroar.Generator.cs:76-80"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: passes_path
|
||||
|
||||
+230
-82
@@ -16763,6 +16763,11 @@ launchers:
|
||||
search_dir: $roms_path/doom
|
||||
passes_to: "gzdoom.ini [IWADSearch.Directories] Path"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $gzdoom_config
|
||||
source_ref: "gzdoom/component_prepare.sh:23, 26-30"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "gzdoom/rd_assets/rd_config/gzdoom.ini:9, gzdoom/component_prepare.sh:23,\
|
||||
\ 27-28"
|
||||
- emulator: gzdoom
|
||||
@@ -16772,6 +16777,11 @@ launchers:
|
||||
search_dir: $roms_path/doom
|
||||
passes_to: "gzdoom.ini [FileSearch.Directories] Path"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $gzdoom_config
|
||||
source_ref: "gzdoom/component_prepare.sh:23, 26-30"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "gzdoom/rd_assets/rd_config/gzdoom.ini:18, gzdoom/component_prepare.sh:23,\
|
||||
\ 27-28"
|
||||
- emulator: gzdoom
|
||||
@@ -16781,6 +16791,11 @@ launchers:
|
||||
search_dir: $bios_path/gzdoom
|
||||
passes_to: "gzdoom.ini [FileSearch.Directories] Path"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $gzdoom_config
|
||||
source_ref: "gzdoom/component_prepare.sh:23, 26-30"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "gzdoom/rd_assets/rd_config/gzdoom.ini:19, gzdoom/component_prepare.sh:23,\
|
||||
\ 28"
|
||||
- emulator: gzdoom
|
||||
@@ -16790,6 +16805,11 @@ launchers:
|
||||
search_dir: $roms_path/bios/gzdoom
|
||||
passes_to: "gzdoom.ini [SoundfontSearch.Directories] Path"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $gzdoom_config
|
||||
source_ref: "gzdoom/component_prepare.sh:23, 26-30"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "gzdoom/rd_assets/rd_config/gzdoom.ini:31, gzdoom/component_prepare.sh:23,\
|
||||
\ 27-28"
|
||||
- emulator: mame
|
||||
@@ -17023,6 +17043,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: xroar.conf rompath
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:290, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17033,6 +17058,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:291, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17048,6 +17078,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist d64_1
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:292, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17062,6 +17097,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist d64_2
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:293, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17075,6 +17115,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist d32
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:294, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17087,6 +17132,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist d200e_1
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:295, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17099,6 +17149,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist d200e_2
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:296, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17115,6 +17170,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon64
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:297, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17129,6 +17189,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon64_alt
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:298, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17143,6 +17208,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon32
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:299, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17162,6 +17232,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon200e
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:300, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17179,6 +17254,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon200e_alt
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:301, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17190,6 +17270,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragon200e_charset
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:302, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17204,6 +17289,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragonpro_boot
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:303, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17222,6 +17312,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragonpro_basic
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:304, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17236,6 +17331,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:305, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17249,89 +17349,12 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco_ext
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:306, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco1
|
||||
names:
|
||||
- bas10
|
||||
- bas13
|
||||
- bas12
|
||||
- "Color Basic v1.2 (1982)(Tandy)"
|
||||
- bas11
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco1
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:307, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco1e
|
||||
names:
|
||||
- bas11
|
||||
- bas13
|
||||
- bas12
|
||||
- "Color Basic v1.2 (1982)(Tandy)"
|
||||
- bas10
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco1e
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:308, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco1e_ext
|
||||
names:
|
||||
- extbas10
|
||||
- extbas11
|
||||
- coco
|
||||
- COCO
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco1e_ext
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:309, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco2
|
||||
names:
|
||||
- bas12
|
||||
- bas13
|
||||
- "Color Basic v1.2 (1982)(Tandy)"
|
||||
- bas11
|
||||
- bas10
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco2
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:310, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco2_ext
|
||||
names:
|
||||
- extbas11
|
||||
- extbas10
|
||||
- coco
|
||||
- COCO
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco2_ext
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:311, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
slot: coco2b
|
||||
names:
|
||||
- bas13
|
||||
- bas12
|
||||
- "Color Basic v1.2 (1982)(Tandy)"
|
||||
- bas11
|
||||
- bas10
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco2b
|
||||
fails_when_missing: false
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:312, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
@@ -17342,6 +17365,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist deluxecoco
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:313, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17352,6 +17380,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist deluxecoco1
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:314, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17362,6 +17395,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist deluxecoco2
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:315, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17373,6 +17411,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist deluxecoco3
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:316, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17384,6 +17427,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist mx1600
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:317, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17394,6 +17442,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist mx1600ext
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:318, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17404,6 +17457,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco3
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:319, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17414,6 +17472,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist coco3p
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:320, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17425,6 +17488,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist glenside_ide
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:321, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17435,6 +17503,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist mc10
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:322, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17445,6 +17518,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist alice
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:323, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17460,6 +17538,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragondos
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:324, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17473,6 +17556,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dosplus
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:325, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17486,6 +17574,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist superdos
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:326, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17498,6 +17591,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist cumana
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:327, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17524,6 +17622,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist dragondos_compat
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:328, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17535,6 +17638,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist rsdos
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:329, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17550,6 +17658,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist delta
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:330, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17560,6 +17673,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist rsdos_becker
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:331, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17571,6 +17689,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist mcx128
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:332, xroar/component_prepare.sh:13-15"
|
||||
- emulator: xroar
|
||||
build: standalone
|
||||
@@ -17582,6 +17705,11 @@ launchers:
|
||||
search_dir: "$roms_path/coco:$roms_path/dragon32:$roms_path/tanodragon:$bios_path"
|
||||
passes_to: romlist mcx128_azerty
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $xroar_config
|
||||
source_ref: "xroar/component_prepare.sh:13-15"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "xroar/rd_assets/rd_config/xroar.conf:333, xroar/component_prepare.sh:13-15"
|
||||
- emulator: retroarch
|
||||
build: libretro
|
||||
@@ -17590,6 +17718,11 @@ launchers:
|
||||
- scph5500.bin
|
||||
passes_to: core option duckstation_BIOS.PathNTSCJ
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $retroarch_config_core_options
|
||||
source_ref: "retroarch/component_prepare.sh:24"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "retroarch/rd_assets/rd_config/retroarch-core-options.cfg:165, retroarch/component_prepare.sh:24"
|
||||
- emulator: retroarch
|
||||
build: libretro
|
||||
@@ -17598,6 +17731,11 @@ launchers:
|
||||
- scph5501.bin
|
||||
passes_to: core option duckstation_BIOS.PathNTSCU
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $retroarch_config_core_options
|
||||
source_ref: "retroarch/component_prepare.sh:24"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "retroarch/rd_assets/rd_config/retroarch-core-options.cfg:166, retroarch/component_prepare.sh:24"
|
||||
- emulator: retroarch
|
||||
build: libretro
|
||||
@@ -17606,6 +17744,11 @@ launchers:
|
||||
- scph5502.bin
|
||||
passes_to: core option duckstation_BIOS.PathPAL
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $retroarch_config_core_options
|
||||
source_ref: "retroarch/component_prepare.sh:24"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "retroarch/rd_assets/rd_config/retroarch-core-options.cfg:167, retroarch/component_prepare.sh:24"
|
||||
- emulator: retroarch
|
||||
build: libretro
|
||||
@@ -17614,4 +17757,9 @@ launchers:
|
||||
- scph10000.bin
|
||||
passes_to: core option pcsx2_bios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: $retroarch_config_core_options
|
||||
source_ref: "retroarch/component_prepare.sh:24"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "retroarch/rd_assets/rd_config/retroarch-core-options.cfg:515, retroarch/component_prepare.sh:24"
|
||||
+133
-19
@@ -570,6 +570,11 @@ launchers:
|
||||
passes_to: retroarch.cfg system_directory = "~/roms/bios", systemfiles_in_content_dir
|
||||
= "false"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/retroarch/retroarch.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/libretro/retroarch/sources/AMD64/retroarch.cfg:3395-3396,\
|
||||
\ projects/ROCKNIX/packages/emulators/libretro/retroarch/sources/H700/retroarch.cfg:711-712,\
|
||||
\ projects/ROCKNIX/packages/emulators/libretro/retroarch/sources/RK3326/retroarch.cfg:716-717,\
|
||||
@@ -594,7 +599,13 @@ launchers:
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "AmigaA1200-default.uae kickstart_rom_file (amiberry -f)"
|
||||
fails_when_missing: false
|
||||
depends_on_option: game name matches AGA|CD32
|
||||
depends_on_option: "game name matches AGA|CD32, content not booted with --autoload,\
|
||||
\ a WHDLoad .lha or .zip (start_amiberry.sh:90, 129)"
|
||||
installs:
|
||||
path: /tmp/emulation/amiberry/.amiberry_conf.uae
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh:64"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh:17,\
|
||||
\ 62-69, projects/ROCKNIX/packages/emulators/standalone/amiberry/config/conf/AmigaA1200-default.uae:114"
|
||||
- emulator: amiberry
|
||||
@@ -606,7 +617,13 @@ launchers:
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "AmigaA500-default.uae kickstart_rom_file (amiberry -f)"
|
||||
fails_when_missing: false
|
||||
depends_on_option: game name does not match AGA|CD32
|
||||
depends_on_option: "game name does not match AGA|CD32, content not booted with --autoload,\
|
||||
\ a WHDLoad .lha or .zip (start_amiberry.sh:90, 129)"
|
||||
installs:
|
||||
path: /tmp/emulation/amiberry/.amiberry_conf.uae
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh:67"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/amiberry/scripts/start_amiberry.sh:17,\
|
||||
\ 62-69, projects/ROCKNIX/packages/emulators/standalone/amiberry/config/conf/AmigaA500-default.uae:114"
|
||||
- emulator: amiberry
|
||||
@@ -645,6 +662,11 @@ launchers:
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "Atari-ST-default.cfg [ROM] szTosImageFileName (--configfile)"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /tmp/hatari/.hatari-temp.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/hatarisa/scripts/start_hatarisa.sh:35"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/hatarisa/config/conf/Atari-ST-default.cfg:200,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/hatarisa/scripts/start_hatarisa.sh:35,\
|
||||
\ 65"
|
||||
@@ -652,13 +674,20 @@ launchers:
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
names: []
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiBIOS9Path, DSiBIOS7Path,
|
||||
DSiFirmwarePath, DSiNANDPath left empty
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiNANDPath left empty
|
||||
fails_when_missing: false
|
||||
depends_on_option: direct_boot = 0 sets ExternalBIOSEnable=1, otherwise 0
|
||||
device: AMD64
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/AMD64/melonDS.ini:84-90,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/package.mk:60, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:41,\
|
||||
installs:
|
||||
path: /storage/.config/melonDS/melonDS.ini
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:20,\
|
||||
\ 34"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/AMD64/melonDS.ini:84-86,\
|
||||
\ 90, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/package.mk:60,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:41,\
|
||||
\ 71-73"
|
||||
- emulator: melonds
|
||||
build: standalone
|
||||
@@ -667,24 +696,28 @@ launchers:
|
||||
- bios9.bin
|
||||
- bios7.bin
|
||||
- firmware.bin
|
||||
- dsi_bios9.bin
|
||||
- dsi_bios7.bin
|
||||
- dsi_firmware.bin
|
||||
- dsi_nand.bin
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiBIOS9Path, DSiBIOS7Path,
|
||||
DSiFirmwarePath, DSiNANDPath
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiNANDPath
|
||||
fails_when_missing: false
|
||||
depends_on_option: direct_boot = 0 sets ExternalBIOSEnable=1, otherwise 0
|
||||
device: RK3399, RK3566, RK3576, RK3588, S922X, SDM845, SM4450, SM6115, SM8250, SM8550,
|
||||
SM8650, SM8750
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/InputPlumber/melonDS.ini:94-100,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3399/melonDS.ini:93-99,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3566/melonDS.ini:93-99,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3588/melonDS.ini:93-99,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/S922X/melonDS.ini:95-101,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/SM4450/melonDS.ini:90-96,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/package.mk:60, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:41,\
|
||||
installs:
|
||||
path: /storage/.config/melonDS/melonDS.ini
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:20,\
|
||||
\ 34"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/InputPlumber/melonDS.ini:94-96,\
|
||||
\ 100, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3399/melonDS.ini:93-95,\
|
||||
\ 99, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3566/melonDS.ini:93-95,\
|
||||
\ 99, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/RK3588/melonDS.ini:93-95,\
|
||||
\ 99, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/S922X/melonDS.ini:95-97,\
|
||||
\ 101, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/config/SM4450/melonDS.ini:90-92,\
|
||||
\ 96, projects/ROCKNIX/packages/emulators/standalone/melonds-sa/package.mk:60,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/melonds-sa/scripts/start_melonds.sh:41,\
|
||||
\ 71-73"
|
||||
- emulator: dsperate
|
||||
build: standalone
|
||||
@@ -701,6 +734,12 @@ launchers:
|
||||
passes_to: "dsperate.ini [paths] bios9, bios7, firmware, bios9i, bios7i, dsi_firmware,\
|
||||
\ dsi_nand (--config)"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/dsperate/dsperate.ini
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/dsperate-sa/scripts/start_dsperate.sh:19"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/dsperate-sa/config/H700/dsperate.ini:11-17,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/dsperate-sa/config/InputPlumber/dsperate.ini:11-17,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/dsperate-sa/config/RK3326/dsperate.ini:11-17,\
|
||||
@@ -716,7 +755,13 @@ launchers:
|
||||
- gba_bios.bin
|
||||
search_dir: /storage/roms/bios
|
||||
passes_to: "config.toml [general] bios_path"
|
||||
fails_when_missing: false
|
||||
fails_when_missing: true
|
||||
installs:
|
||||
path: /storage/.config/nanoboyadvance/config.toml
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/nanoboyadvance-sa/scripts/start_nanoboyadvance.sh:12"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/nanoboyadvance-sa/config/config.toml:2,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/nanoboyadvance-sa/package.mk:30"
|
||||
- emulator: xemu
|
||||
@@ -731,6 +776,13 @@ launchers:
|
||||
passes_to: "xemu.toml [sys.files] bootrom_path, flashrom_path, eeprom_path, hdd_path\
|
||||
\ (copied at each launch)"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/xemu/xemu.toml
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/xemu-sa/scripts/start_xemu.sh:15,\
|
||||
\ 19"
|
||||
kept_if_present: false
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/xemu-sa/config/AMD64/xemu.toml:28-31,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/xemu-sa/config/SM4450/xemu.toml:29-32,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/xemu-sa/config/SM8250/xemu.toml:29-32,\
|
||||
@@ -747,6 +799,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg gba.bios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 729, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -758,6 +816,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg md.cdbios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 1050, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -769,6 +833,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg nes.ggrom
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 2292, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -781,6 +851,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg pce.cdbios, pce.gecdbios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 3309, 3342, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -792,6 +868,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg pce_fast.cdbios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 4128, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -803,6 +885,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg pcfx.bios
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 4611, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -816,6 +904,12 @@ launchers:
|
||||
search_dir: /storage/roms/bios/
|
||||
passes_to: mednafen.cfg psx.bios_eu, psx.bios_jp, psx.bios_na
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 7366-7370, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: mednafen
|
||||
@@ -834,6 +928,12 @@ launchers:
|
||||
passes_to: mednafen.cfg ss.bios_jp, ss.bios_na_eu, ss.bios_stv_eu, ss.bios_stv_jp,
|
||||
ss.bios_stv_na, ss.cart.kof95_path, ss.cart.ultraman_path
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/mednafen/mednafen.cfg
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:21"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/mednafen/config/common/mednafen.template:570,\
|
||||
\ 9818-9820, 9824-9828, 9834-9836, projects/ROCKNIX/packages/emulators/standalone/mednafen/scripts/start_mednafen.sh:19-21"
|
||||
- emulator: yabasanshiro
|
||||
@@ -861,6 +961,13 @@ launchers:
|
||||
passes_to: "settings.ini [BIOS] SearchDirectory = /storage/roms/bios, [BIOS] PathNTSCU,\
|
||||
\ PathNTSCJ, PathPAL unset"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/duckstation/settings.ini
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/duckstation-sa/scripts/start_duckstation.sh:19,\
|
||||
\ 22"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/duckstation-sa/config/AMD64/settings.ini:134,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/duckstation-sa/config/H700/settings.ini:24,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/duckstation-sa/config/InputPlumber/settings.ini:29-32,\
|
||||
@@ -878,6 +985,13 @@ launchers:
|
||||
passes_to: "PCSX2.ini [Folders] Bios = /storage/roms/bios/armsx2, [Filenames] BIOS\
|
||||
\ unset"
|
||||
fails_when_missing: false
|
||||
installs:
|
||||
path: /storage/.config/ARMSX2/inis/PCSX2.ini
|
||||
source_ref: "projects/ROCKNIX/packages/sysutils/systemd/scripts/userconfig-setup:13,\
|
||||
\ projects/ROCKNIX/packages/emulators/standalone/armsx2-sa/scripts/start_armsx2.sh:11,\
|
||||
\ 16"
|
||||
kept_if_present: true
|
||||
overrides: []
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/armsx2-sa/config/S922X/ARMSX2/inis/PCSX2.ini:21,\
|
||||
\ 475, projects/ROCKNIX/packages/emulators/standalone/armsx2-sa/config/inputplumber/ARMSX2/inis/PCSX2.ini:21,\
|
||||
\ 473, projects/ROCKNIX/packages/emulators/standalone/armsx2-sa/package.mk:117-118"
|
||||
|
||||
@@ -11,15 +11,16 @@
|
||||
],
|
||||
"allOf": [
|
||||
{
|
||||
"comment": "A build reference documents why a pin is held: it never stands without the pin_frozen that says so.",
|
||||
"comment": "A build reference documents why a pin is held, or the build config_reads are read at: it never stands without the pin_frozen or the config_reads that say so.",
|
||||
"if": {
|
||||
"required": [
|
||||
"pin_build"
|
||||
]
|
||||
},
|
||||
"then": {
|
||||
"required": [
|
||||
"pin_frozen"
|
||||
"anyOf": [
|
||||
{"required": ["pin_frozen"]},
|
||||
{"required": ["config_reads"]}
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -1078,14 +1079,36 @@
|
||||
"standalone_directories": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["handle", "source_ref"],
|
||||
"properties": {
|
||||
"handle": {"type": "string", "minLength": 1},
|
||||
"source_ref": {"type": "string", "minLength": 1, "description": "Where the build reads the handle and resolves its files against it"}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "What the standalone build resolves standalone_path against, as its code names it: a directory ($XDG_DATA_HOME/flycast), a setting (Dreamcast.BiosPath), an environment variable or the function returning the directory. A platform launcher record that links or passes a folder of its BIOS tree under one of these puts the standalone files in that folder."
|
||||
},
|
||||
"standalone_pools": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"type": "string"
|
||||
"oneOf": [
|
||||
{"type": "string"},
|
||||
{
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["folder", "source_ref"],
|
||||
"properties": {
|
||||
"folder": {"type": "string"},
|
||||
"source_ref": {"type": "string", "minLength": 1, "description": "Where the build reads the setting as a search list"}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"description": "Settings the standalone build reads as a list of directories it searches one after the other, each mapped to the subfolder of the layout (relative to standalone_directories, empty for the whole of it) its directories stand for: openMSX's filepool entries are searched like share/systemroms, XRoar's rompath entries hold the ROMs themselves. A file in any entry is read, so several platform records naming entries give the first one a pack can fill."
|
||||
},
|
||||
@@ -1101,7 +1124,7 @@
|
||||
"pin_build": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"description": "The build file each platform that ships a pin_frozen build reads its revision from, so check_freshness can read it again where the platform's YAML now stands and say when the platform builds another revision.",
|
||||
"description": "The build file each platform that ships a pin_frozen build, or the build a config_reads entry is read at, reads its revision from, so check_freshness can read it again where the platform's YAML now stands and say when the platform builds another revision.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
@@ -1135,6 +1158,37 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"config_reads": {
|
||||
"type": "array",
|
||||
"description": "The configs the build loads and the keys it opens a file from, as a platform launcher record citing a config needs them: link (c) is where the file is found and loaded, link (d) where each key is read and its value opened. An entry naming platforms is read at their pin_build revision, one naming none at source_commit.",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["file", "source_ref", "keys"],
|
||||
"dependentRequired": {"revision": ["platforms", "revision_from"]},
|
||||
"properties": {
|
||||
"file": {"type": "string", "minLength": 1, "description": "The config as the code finds it: a name, a glob for any file a flag passes (*.uae), a path, the flag itself, \"command line\" or \"core options\""},
|
||||
"platforms": {"type": "array", "items": {"type": "string"}, "minItems": 1, "uniqueItems": true, "description": "Registry slugs of the platforms shipping the build these refs are read at, each with a pin_build entry unless revision names the build"},
|
||||
"revision": {"type": "string", "pattern": "^[0-9a-f]{40}$", "description": "The commit these refs are read at, for platforms installing a package no build file of theirs pins (RetroBat's stable archives, a Flathub app)"},
|
||||
"revision_from": {"type": "string", "minLength": 1, "description": "Where revision was read: the version string of the shipped binary, the Flathub manifest commit"},
|
||||
"source_ref": {"type": "string", "minLength": 1},
|
||||
"keys": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["key", "source_ref"],
|
||||
"properties": {
|
||||
"key": {"oneOf": [{"type": "string", "minLength": 1}, {"type": "array", "items": {"type": "string", "minLength": 1}, "minItems": 1}], "description": "Spelled as a launcher record's passes_to spells it: [Section] Key, or Key"},
|
||||
"source_ref": {"type": "string", "minLength": 1},
|
||||
"condition": {"type": "string", "description": "What else the read depends on"}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"pin_follows": {
|
||||
"type": "string",
|
||||
"description": "Why source_commit follows the branch tip although a single platform ships the profile: that platform builds the tip, cited by its build file. Without it or pin_frozen, a bump refuses a profile one platform ships."
|
||||
|
||||
@@ -341,6 +341,29 @@
|
||||
"type": "string",
|
||||
"description": "Devices whose shipped config this record reads, comma-separated, set only where the configs of a package differ between devices"
|
||||
},
|
||||
"installs": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["path", "source_ref"],
|
||||
"properties": {
|
||||
"path": {"type": "string", "minLength": 1, "description": "Where the config the record cites lands on the device, as the platform's code spells it"},
|
||||
"source_ref": {"type": "string", "minLength": 1, "description": "path:lines of the code that puts it there"}
|
||||
},
|
||||
"description": "How the config file a record cites reaches the emulator: link (a) of the evidence a config record carries"
|
||||
},
|
||||
"kept_if_present": {
|
||||
"type": "boolean",
|
||||
"description": "True when the install leaves a file already there in place (cp if absent, rsync --ignore-existing): the record holds on a fresh install"
|
||||
},
|
||||
"overrides": {
|
||||
"type": "array",
|
||||
"items": {"type": "string"},
|
||||
"description": "path:lines of launch code that rewrites the record's keys or replaces the installed config, empty when the launch path writes neither: link (b)"
|
||||
},
|
||||
"choices_from": {
|
||||
"type": "string",
|
||||
"description": "path:lines of the feature or option file (es_features, a core .opt) listing the values the option the record writes takes. It is never the record's evidence: source_ref cites the code writing the choice"
|
||||
},
|
||||
"source_ref": {
|
||||
"type": "string",
|
||||
"description": "path:lines in the platform's repository at the pinned revision"
|
||||
|
||||
+7
-6
@@ -3189,11 +3189,12 @@ def standalone_bindings_for(
|
||||
|
||||
``systems`` are those the entry is launched for (entry_launch_systems).
|
||||
"""
|
||||
declared = profile.get("standalone_directories") or []
|
||||
pools = profile.get("standalone_pools") or {}
|
||||
from launchers import directory_handles, pool_folders, standalone_bindings # noqa: PLC0415
|
||||
|
||||
declared = directory_handles(profile)
|
||||
pools = pool_folders(profile)
|
||||
if not declared and not pools:
|
||||
return {}
|
||||
from launchers import standalone_bindings # noqa: PLC0415
|
||||
|
||||
names = {emu_name, *(str(c) for c in profile.get("cores") or [])}
|
||||
layout = [
|
||||
@@ -3298,9 +3299,9 @@ def platform_layouts(
|
||||
|
||||
# The layout folders a search setting stands for (standalone_pools):
|
||||
# bound, the launcher passes the setting and the default is not read.
|
||||
pool_folders = {
|
||||
str(v).strip("/") for v in (profile.get("standalone_pools") or {}).values()
|
||||
} - {""}
|
||||
from launchers import pool_folders as _pool_folders # noqa: PLC0415
|
||||
|
||||
pool_folders = {v.strip("/") for v in _pool_folders(profile).values()} - {""}
|
||||
|
||||
def passed_setting(entry: dict) -> bool:
|
||||
layout = str(standalone_layout_path(entry, profile) or "")
|
||||
|
||||
@@ -56,9 +56,11 @@ from common import (
|
||||
from hashing import parse_hash_list
|
||||
from launchers import (
|
||||
LauncherLayer,
|
||||
bound_launchers,
|
||||
catalogued_model_files,
|
||||
declared_destinations,
|
||||
held_record,
|
||||
launcher_unproven,
|
||||
name_settings,
|
||||
set_by,
|
||||
setting_readers,
|
||||
@@ -1095,6 +1097,8 @@ def _settle_launcher_places(
|
||||
|
||||
# The --json key of the launcher reads category, beside the emulator keys.
|
||||
LAUNCHER_READS_KEY = "_launcher_reads_not_held"
|
||||
# The --json key of the launcher records a config file does not prove.
|
||||
LAUNCHER_UNPROVEN_KEY = "_launcher_unproven"
|
||||
|
||||
# A package record names no file: it records what a package builds.
|
||||
_NAMELESS_KINDS = frozenset({"package"})
|
||||
@@ -1238,7 +1242,9 @@ def launcher_reads_not_held(
|
||||
rows: list[dict] = []
|
||||
for platform, config in configs.items():
|
||||
by_key: dict[str, dict] = {}
|
||||
for record in config.get("launchers") or []:
|
||||
# A record resting on a config file it cannot prove reads nothing
|
||||
# yet: it is reported apart (launcher_unproven).
|
||||
for record in bound_launchers(config, profiles):
|
||||
names = launcher_file_names(record)
|
||||
if not names:
|
||||
continue
|
||||
@@ -1331,6 +1337,25 @@ def launcher_reads_not_held(
|
||||
return rows
|
||||
|
||||
|
||||
def print_launcher_unproven(rows: list[dict]) -> None:
|
||||
"""The launcher records resting on a config file the code does not prove.
|
||||
|
||||
Neither a pack, a manifest nor a severity reads them: each is listed
|
||||
with the links it lacks.
|
||||
"""
|
||||
if not rows:
|
||||
return
|
||||
platforms = sorted({r["platform"] for r in rows})
|
||||
noun = "platform" if len(platforms) == 1 else "platforms"
|
||||
print(f"\nLauncher records unproven: {len(rows)} across {len(platforms)} {noun}")
|
||||
for platform in platforms:
|
||||
print(f"\n{platform}")
|
||||
for row in (r for r in rows if r["platform"] == platform):
|
||||
print(f" [{row['index']}] {row['emulator']} {row['kind']}: {row['passes_to']}")
|
||||
for link in row["missing"]:
|
||||
print(f" missing {link}")
|
||||
|
||||
|
||||
def print_launcher_reads(rows: list[dict]) -> None:
|
||||
"""The launcher reads gap category, after the profile gaps.
|
||||
|
||||
@@ -1649,8 +1674,25 @@ def main() -> None:
|
||||
db, all_profiles, registry, emulator or "",
|
||||
)
|
||||
|
||||
unproven = [
|
||||
row for row in launcher_unproven(
|
||||
{
|
||||
name: load_platform_config(name, args.platforms_dir)
|
||||
for name in (selected or list_registered_platforms(args.platforms_dir))
|
||||
},
|
||||
all_profiles,
|
||||
)
|
||||
if not emulator or any(
|
||||
emulator in LauncherLayer._profiles_named(part, all_profiles, set(all_profiles))
|
||||
for part in row["emulator"].split(", ")
|
||||
)
|
||||
]
|
||||
|
||||
if args.json:
|
||||
print(json.dumps({**report, LAUNCHER_READS_KEY: launcher_reads}, indent=2))
|
||||
print(json.dumps(
|
||||
{**report, LAUNCHER_READS_KEY: launcher_reads, LAUNCHER_UNPROVEN_KEY: unproven},
|
||||
indent=2,
|
||||
))
|
||||
else:
|
||||
if emulator:
|
||||
scope = emulator
|
||||
@@ -1660,6 +1702,7 @@ def main() -> None:
|
||||
scope = "all emulators"
|
||||
print_report(report, scope, show_clean=bool(args.emulator))
|
||||
print_launcher_reads(launcher_reads)
|
||||
print_launcher_unproven(unproven)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
@@ -3647,13 +3647,15 @@ def _served_line(f: dict, declared_sha1: str = "") -> str:
|
||||
def _launcher_refs(config: dict) -> dict[str, list[str]]:
|
||||
"""Entry name, casefolded -> each launcher record that opens it, rendered."""
|
||||
from launchers import _names as launcher_names
|
||||
from launchers import bound_launchers
|
||||
from sitesources import launcher_ref_markdown, list_source
|
||||
|
||||
# Every scraper reads its launchers in the repository and at the revision
|
||||
# of the list it scrapes, so `source` pins each source_ref.
|
||||
# of the list it scrapes, so `source` pins each source_ref. A record a
|
||||
# config file does not prove opens nothing: it is listed apart.
|
||||
source = list_source(str(config.get("source") or ""))
|
||||
found: dict[str, list[str]] = {}
|
||||
for record in config.get("launchers") or []:
|
||||
for record in bound_launchers(config):
|
||||
if not isinstance(record, dict) or not record.get("source_ref"):
|
||||
continue
|
||||
text = (f"{_escape_tags(str(record.get('emulator', '')))} at "
|
||||
@@ -3665,6 +3667,31 @@ def _launcher_refs(config: dict) -> dict[str, list[str]]:
|
||||
return found
|
||||
|
||||
|
||||
UNPROVEN_TITLE = "Launcher records a config does not prove"
|
||||
|
||||
|
||||
def _launcher_unproven_section(config: dict) -> list[str]:
|
||||
"""The platform's launcher records resting on a config the code does not prove.
|
||||
|
||||
A config file is proof only when the code installing it and the code
|
||||
reading it are shown: these records place no file.
|
||||
"""
|
||||
from launchers import launcher_unproven
|
||||
from sitesources import launcher_ref_markdown, list_source
|
||||
|
||||
rows = launcher_unproven({str(config.get("_key") or ""): config})
|
||||
if not rows:
|
||||
return []
|
||||
source = list_source(str(config.get("source") or ""))
|
||||
body = [
|
||||
f"- {_escape_tags(row['emulator'])}, `{_escape_tags(row['passes_to'] or row['kind'])}` "
|
||||
f"at {launcher_ref_markdown(source, row['source_ref'])}: "
|
||||
f"{_escape_tags('; '.join(row['missing']))}"
|
||||
for row in rows
|
||||
]
|
||||
return ["", *markup.details("note", f"{UNPROVEN_TITLE} ({len(rows)})", body)]
|
||||
|
||||
|
||||
# The hash a row shows first, when the list does not say which it checks.
|
||||
_ROW_HASHES = ("sha1", "md5", "sha256", "crc32")
|
||||
# An untested entry whose reason is a hash the bytes do not match.
|
||||
@@ -4799,6 +4826,7 @@ def generate_platform_page(
|
||||
_render_platform_systems(by_system, config_files, emulator_files,
|
||||
(name, display), moved, config)
|
||||
)
|
||||
lines.extend(_launcher_unproven_section(config))
|
||||
|
||||
lines.extend(["", _date_line()])
|
||||
return "\n".join(lines) + "\n"
|
||||
|
||||
+314
-5
@@ -254,11 +254,318 @@ def _names(record: dict) -> list[str]:
|
||||
return names
|
||||
|
||||
|
||||
def launcher_places(config: dict) -> list[LauncherPlace]:
|
||||
# How a record's passes_to names what carries the file when it names no
|
||||
# config file: an option on the command line, or a libretro core option.
|
||||
COMMAND_LINE = "command line"
|
||||
CORE_OPTIONS = "core options"
|
||||
_TAIL_WORDS = re.compile(r"\s+(?:unset|left empty)$")
|
||||
_KEY_TOKEN = re.compile(r"^-{0,2}[\w.$()/\\]+$")
|
||||
|
||||
|
||||
def config_target(record: dict) -> tuple[str, list[str]]:
|
||||
"""The config a record writes its file to, and the keys it names there.
|
||||
|
||||
passes_to spells them as describe_keys does: "settings.ini [BIOS]
|
||||
SearchDirectory, [BIOS] PathNTSCU, PathNTSCJ unset", "command line
|
||||
-hard", "core option pcsx2_bios", "hatarib_tos = hatarib/<value>". A
|
||||
part that reads as prose ("only if the file exists") names no key. When
|
||||
passes_to names no file ("romlist coco"), the file is the one the record
|
||||
installs and the whole of passes_to is the key.
|
||||
"""
|
||||
# A parenthesis says how the file is passed, unless a config variable
|
||||
# opens it: $(FILE_PATH) is amiberry's.
|
||||
text = re.sub(r"(?<!\$)\([^()]*\)", "", str(record.get("passes_to") or "")).strip()
|
||||
head, _, rest = text.partition(" ")
|
||||
if text.startswith(COMMAND_LINE + " "):
|
||||
flag = text[len(COMMAND_LINE):].split()[0]
|
||||
return COMMAND_LINE, [flag]
|
||||
if text.startswith("core option "):
|
||||
return CORE_OPTIONS, [text[len("core option "):].split()[0]]
|
||||
if "." not in head or head.startswith("<"):
|
||||
# The file is the one the record installs, named by its path or,
|
||||
# when a variable spells the path, by the config file it cites.
|
||||
from scraper.shell_launchers import config_ref, is_feature_ref, ref_path # noqa: PLC0415
|
||||
|
||||
installed = str((record.get("installs") or {}).get("path") or "").rsplit("/", 1)[-1]
|
||||
cited = [
|
||||
ref_path(part).rsplit("/", 1)[-1]
|
||||
for part in config_ref(str(record.get("source_ref") or ""))
|
||||
if not is_feature_ref(part)
|
||||
]
|
||||
if "." in installed or (installed and not cited):
|
||||
return installed, [text]
|
||||
if installed and cited:
|
||||
return cited[0], [text]
|
||||
if record.get("build") == "libretro" and record.get("kind") == "core_option":
|
||||
return CORE_OPTIONS, [head]
|
||||
return "", []
|
||||
keys: list[str] = []
|
||||
section = ""
|
||||
for piece in re.split(r",\s*", rest):
|
||||
piece = _TAIL_WORDS.sub("", piece.strip())
|
||||
# A section opens anywhere in a piece: "BIOS9Path [DSi] FirmwarePath".
|
||||
for chunk in re.split(r"(\[[^\]]+\])", piece):
|
||||
chunk = chunk.strip()
|
||||
if not chunk:
|
||||
continue
|
||||
if chunk.startswith("[") and chunk.endswith("]"):
|
||||
section = chunk
|
||||
continue
|
||||
# "A = B = <value>" sets every key before the value.
|
||||
names = [p.strip() for p in re.split(r"\s*=\s*", chunk)]
|
||||
if len(names) > 1:
|
||||
names = names[:-1]
|
||||
for name in names:
|
||||
if not _KEY_TOKEN.match(name):
|
||||
continue
|
||||
key = f"{section} {name}" if section else name
|
||||
if key not in keys:
|
||||
keys.append(key)
|
||||
return head, keys
|
||||
|
||||
|
||||
def _read_keys(read: dict) -> dict[str, str]:
|
||||
"""Each key a config_reads entry says the build reads, to its source_ref."""
|
||||
found: dict[str, str] = {}
|
||||
for entry in read.get("keys") or []:
|
||||
spelled = entry.get("key")
|
||||
for key in spelled if isinstance(spelled, list) else [spelled]:
|
||||
if key:
|
||||
found[str(key)] = str(entry.get("source_ref") or "")
|
||||
return found
|
||||
|
||||
|
||||
def _handle_refs(profile: dict) -> dict[str, str]:
|
||||
"""The handles a profile names with the code that reads them."""
|
||||
found: dict[str, str] = {}
|
||||
for item in profile.get("standalone_directories") or []:
|
||||
if isinstance(item, dict) and item.get("source_ref"):
|
||||
handle = str(item.get("handle") or "").partition(" = ")[0]
|
||||
found[handle] = str(item["source_ref"])
|
||||
for handle, value in (profile.get("standalone_pools") or {}).items():
|
||||
if isinstance(value, dict) and value.get("source_ref"):
|
||||
found[str(handle)] = str(value["source_ref"])
|
||||
return found
|
||||
|
||||
|
||||
def directory_handles(profile: dict) -> list[str]:
|
||||
"""standalone_directories as handle strings, a {handle, source_ref} item
|
||||
by its handle."""
|
||||
return [
|
||||
str(item.get("handle") or "") if isinstance(item, dict) else str(item)
|
||||
for item in profile.get("standalone_directories") or []
|
||||
]
|
||||
|
||||
|
||||
def pool_folders(profile: dict) -> dict[str, str]:
|
||||
"""standalone_pools as handle to subfolder, a {folder, source_ref} value
|
||||
by its folder."""
|
||||
return {
|
||||
str(handle): str(value.get("folder") or "") if isinstance(value, dict) else str(value)
|
||||
for handle, value in (profile.get("standalone_pools") or {}).items()
|
||||
}
|
||||
|
||||
|
||||
def _reads_apply(read: dict, profile: dict, platform: str) -> bool:
|
||||
"""Whether a config_reads entry describes the build ``platform`` ships.
|
||||
|
||||
An entry naming platforms is read at their pin_build revision. One that
|
||||
names none is read at the profile's pin, the build of every platform
|
||||
with no pin_build of its own or one pinning the same commit.
|
||||
"""
|
||||
named = [str(p) for p in read.get("platforms") or []]
|
||||
if named:
|
||||
return platform in named
|
||||
pin = str(profile.get("source_commit") or "")
|
||||
builds = [b for b in profile.get("pin_build") or [] if b.get("platform") == platform]
|
||||
return all(pin and str(b.get("value") or "").startswith(pin[:12]) for b in builds)
|
||||
|
||||
|
||||
def _file_matches(read_file: str, file: str, record: dict) -> bool:
|
||||
"""Whether a config_reads file is the one a record writes.
|
||||
|
||||
The entry names the file as the build finds it: a name, a glob ("*.uae",
|
||||
any file the launcher passes), a path, or the flag the launcher passes
|
||||
it with (amiberry's -f).
|
||||
"""
|
||||
from fnmatch import fnmatch # noqa: PLC0415
|
||||
|
||||
spelled = read_file.rsplit("/", 1)[-1].casefold()
|
||||
if file and fnmatch(file.casefold(), spelled):
|
||||
return True
|
||||
installed = str((record.get("installs") or {}).get("path") or "").rsplit("/", 1)[-1]
|
||||
if installed and fnmatch(installed.casefold(), spelled):
|
||||
return True
|
||||
return read_file.startswith("-") and read_file in str(record.get("passes_to") or "").split()
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class ConfigEvidence:
|
||||
"""Whether a launcher record that rests on a config holds, and why not.
|
||||
|
||||
``config`` holds the parts of its source_ref that cite a config, option
|
||||
or feature file. A record citing none, and choosing among no listed
|
||||
option values, rests on code alone and holds.
|
||||
"""
|
||||
|
||||
config: tuple[str, ...]
|
||||
missing: tuple[str, ...]
|
||||
readers: tuple[str, ...] = ()
|
||||
|
||||
@property
|
||||
def proven(self) -> bool:
|
||||
return not self.missing
|
||||
|
||||
|
||||
def _named_profiles(record: dict, profiles: Mapping[str, dict], platform: str) -> list[str]:
|
||||
"""The profiles a record's emulator names, a platform's own build first."""
|
||||
found = []
|
||||
for part in (e.strip() for e in str(record.get("emulator", "")).split(",")):
|
||||
named = [
|
||||
key for key, profile in profiles.items()
|
||||
if profile.get("type") not in ("alias", "launcher")
|
||||
and (key == part or part in {str(c) for c in profile.get("cores") or []})
|
||||
]
|
||||
own = [k for k in named if platform in (profiles[k].get("built_by") or [])]
|
||||
found.extend(own or [k for k in named if not profiles[k].get("built_by")])
|
||||
return sorted(set(found))
|
||||
|
||||
|
||||
def config_evidence(
|
||||
record: dict, profiles: Mapping[str, dict], platform: str = ""
|
||||
) -> ConfigEvidence:
|
||||
"""What a record citing a config file proves, link by link.
|
||||
|
||||
A config file is proof only when the code that installs it and the code
|
||||
that reads it are shown: (a) the platform installs the file at a path
|
||||
(``installs``), (b) its launch code was read for what replaces the file
|
||||
or the key (``overrides``), (c) the emulator loads that file and (d)
|
||||
reads each key and opens the value (``config_reads`` of its profile, at
|
||||
the build the platform ships). A feature or option file only lists the
|
||||
values a menu offers: it goes in ``choices_from``, beside the code that
|
||||
writes the choice, and such a record needs (c) and (d) too.
|
||||
"""
|
||||
from scraper.shell_launchers import config_ref, is_feature_ref # noqa: PLC0415
|
||||
|
||||
cited = config_ref(str(record.get("source_ref") or ""))
|
||||
choices = str(record.get("choices_from") or "")
|
||||
if not cited and not choices:
|
||||
return ConfigEvidence((), ())
|
||||
missing: list[str] = []
|
||||
features = [part for part in cited if is_feature_ref(part)]
|
||||
if features:
|
||||
missing.append("an option list cited as source, not as choices_from")
|
||||
shipped = [part for part in cited if not is_feature_ref(part)]
|
||||
if shipped:
|
||||
installs = record.get("installs") or {}
|
||||
if not (installs.get("path") and installs.get("source_ref")):
|
||||
missing.append("installs: the code that puts the config in place")
|
||||
if "overrides" not in record:
|
||||
missing.append("overrides: the launch code read for what replaces it")
|
||||
file, keys = config_target(record)
|
||||
if not keys:
|
||||
missing.append("a key the config hands the file to")
|
||||
readers: list[str] = []
|
||||
uncovered = list(keys)
|
||||
loaded = False
|
||||
for key in _named_profiles(record, profiles, platform) or sorted(profiles):
|
||||
profile = profiles[key]
|
||||
handles = _handle_refs(profile)
|
||||
for read in profile.get("config_reads") or []:
|
||||
if not _reads_apply(read, profile, platform):
|
||||
continue
|
||||
if not _file_matches(str(read.get("file") or ""), file, record):
|
||||
continue
|
||||
loaded = True
|
||||
known = _read_keys(read)
|
||||
before = len(uncovered)
|
||||
uncovered = [k for k in uncovered if not (known.get(k) or handles.get(k))]
|
||||
if len(uncovered) < before and key not in readers:
|
||||
readers.append(key)
|
||||
if not loaded:
|
||||
missing.append(f"config_reads: an emulator that loads {file or 'the config'}")
|
||||
elif uncovered:
|
||||
missing.append("config_reads: no read of " + ", ".join(uncovered))
|
||||
return ConfigEvidence(tuple(cited or [choices]), tuple(missing), tuple(readers))
|
||||
|
||||
|
||||
_DEFAULT_PROFILES: dict[str, dict] | None = None
|
||||
|
||||
|
||||
def _profiles_or_repo(profiles: Mapping[str, dict] | None) -> Mapping[str, dict]:
|
||||
"""The profiles given, else this repository's, read once."""
|
||||
global _DEFAULT_PROFILES # noqa: PLW0603
|
||||
if profiles is not None:
|
||||
return profiles
|
||||
if _DEFAULT_PROFILES is None:
|
||||
from pathlib import Path # noqa: PLC0415
|
||||
|
||||
from common import load_emulator_profiles # noqa: PLC0415
|
||||
|
||||
_DEFAULT_PROFILES = load_emulator_profiles(
|
||||
str(Path(__file__).resolve().parent.parent / "emulators")
|
||||
)
|
||||
return _DEFAULT_PROFILES
|
||||
|
||||
|
||||
def _cites_config(record: dict) -> bool:
|
||||
from scraper.shell_launchers import config_ref # noqa: PLC0415
|
||||
|
||||
return bool(record.get("choices_from")) or bool(config_ref(str(record.get("source_ref") or "")))
|
||||
|
||||
|
||||
def bound_launchers(config: dict, profiles: Mapping[str, dict] | None = None) -> list[dict]:
|
||||
"""The launcher records a platform's packs, manifests and reports consume.
|
||||
|
||||
A record resting on a config file binds only when config_evidence holds
|
||||
for it. The repository's profiles are read only when a record cites one.
|
||||
"""
|
||||
records = [r for r in config.get("launchers") or [] if isinstance(r, dict)]
|
||||
if not any(_cites_config(r) for r in records):
|
||||
return records
|
||||
known = _profiles_or_repo(profiles)
|
||||
platform = str(config.get("_key") or "")
|
||||
return [r for r in records if config_evidence(r, known, platform).proven]
|
||||
|
||||
|
||||
def launcher_unproven(
|
||||
configs: Mapping[str, dict], profiles: Mapping[str, dict] | None = None
|
||||
) -> list[dict]:
|
||||
"""The records resting on a config file whose evidence does not hold.
|
||||
|
||||
One row per record, with the config parts it cites and each missing
|
||||
link. Reported apart: no severity, count or exit code reads it.
|
||||
"""
|
||||
rows: list[dict] = []
|
||||
for platform, config in configs.items():
|
||||
records = [r for r in config.get("launchers") or [] if isinstance(r, dict)]
|
||||
if not any(_cites_config(r) for r in records):
|
||||
continue
|
||||
known = _profiles_or_repo(profiles)
|
||||
for index, record in enumerate(records):
|
||||
evidence = config_evidence(record, known, str(config.get("_key") or platform))
|
||||
if evidence.proven:
|
||||
continue
|
||||
rows.append({
|
||||
"platform": platform,
|
||||
"index": index,
|
||||
"emulator": str(record.get("emulator", "")),
|
||||
"kind": str(record.get("kind", "")),
|
||||
"passes_to": str(record.get("passes_to") or ""),
|
||||
"source_ref": str(record.get("source_ref", "")),
|
||||
"config": list(evidence.config),
|
||||
"missing": list(evidence.missing),
|
||||
})
|
||||
return rows
|
||||
|
||||
|
||||
def launcher_places(
|
||||
config: dict, profiles: Mapping[str, dict] | None = None
|
||||
) -> list[LauncherPlace]:
|
||||
"""Every place a platform's launchers open a named file from."""
|
||||
base = str(config.get("base_destination") or "bios")
|
||||
places: list[LauncherPlace] = []
|
||||
for record in config.get("launchers") or []:
|
||||
for record in bound_launchers(config, profiles):
|
||||
kind = record.get("kind")
|
||||
if kind not in PLACE_KINDS:
|
||||
continue
|
||||
@@ -484,7 +791,9 @@ def _listed_directories(raw: str) -> list[str] | None:
|
||||
return None
|
||||
|
||||
|
||||
def handed_directories(config: dict) -> list[HandedDirectory]:
|
||||
def handed_directories(
|
||||
config: dict, profiles: Mapping[str, dict] | None = None
|
||||
) -> list[HandedDirectory]:
|
||||
"""Every whole directory a platform links or passes to a standalone build.
|
||||
|
||||
A record naming files (gpsp's gba_bios.bin) or one slot of a directory
|
||||
@@ -499,7 +808,7 @@ def handed_directories(config: dict) -> list[HandedDirectory]:
|
||||
natives = native_systems(config)
|
||||
declared = {d.lower() for d in declared_destinations(config)}
|
||||
found: list[HandedDirectory] = []
|
||||
for record in config.get("launchers") or []:
|
||||
for record in bound_launchers(config, profiles):
|
||||
if record.get("build") != "standalone" or record.get("kind") not in HANDED_KINDS:
|
||||
continue
|
||||
if record.get("names") or record.get("slot"):
|
||||
@@ -988,7 +1297,7 @@ class LauncherLayer:
|
||||
db: dict,
|
||||
declared: Iterable[str],
|
||||
) -> None:
|
||||
self.places = launcher_places(config)
|
||||
self.places = launcher_places(config, profiles)
|
||||
self.declared = set(declared)
|
||||
self.declared_folded = {d.lower() for d in self.declared}
|
||||
self.declared_names = {d.rsplit("/", 1)[-1] for d in self.declared}
|
||||
|
||||
@@ -1047,6 +1047,11 @@ class ProfileReport:
|
||||
new_files_elided: dict[str, int] = field(default_factory=dict)
|
||||
new_hashes: list[dict] | None = None
|
||||
detection_skipped: str | None = None
|
||||
# config_reads refs written for a build a platform ships, each read at
|
||||
# that build (pin_build) rather than at source_commit: {platform,
|
||||
# revision, ref, status, detail}. A status other than BUILD_OK is review
|
||||
# work.
|
||||
build_refs: list[dict] = field(default_factory=list)
|
||||
|
||||
# Skips that say the profile cannot be checked as written: a repository
|
||||
# that no longer answers, no pin to read, a death the forge contradicts.
|
||||
@@ -1070,6 +1075,7 @@ class ProfileReport:
|
||||
+ len(self.orphaned)
|
||||
+ len(self.stale_prose or ())
|
||||
+ len(self.moved_repos)
|
||||
+ sum(1 for ref in self.build_refs if ref["status"] != "BUILD_OK")
|
||||
)
|
||||
|
||||
|
||||
@@ -1603,6 +1609,81 @@ def moved_repositories(
|
||||
return moved
|
||||
|
||||
|
||||
def shipped_build_holders(profile: dict) -> dict[int, dict]:
|
||||
"""The source_ref holders of config_reads entries naming platforms, by id.
|
||||
|
||||
Such an entry describes the build those platforms ship, so its refs are
|
||||
read at their pin_build revision, never at source_commit.
|
||||
"""
|
||||
found: dict[int, dict] = {}
|
||||
for read in profile.get("config_reads") or []:
|
||||
if not isinstance(read, dict) or not read.get("platforms"):
|
||||
continue
|
||||
found[id(read)] = read
|
||||
for key in read.get("keys") or []:
|
||||
if isinstance(key, dict):
|
||||
found[id(key)] = read
|
||||
return found
|
||||
|
||||
|
||||
def build_revision(profile: dict, platform: str) -> str | None:
|
||||
"""The emulator revision a platform's pin_build entry names, None when
|
||||
its value is no revision (a URL, a package name)."""
|
||||
for build in profile.get("pin_build") or []:
|
||||
if build.get("platform") != platform:
|
||||
continue
|
||||
value = str(build.get("value") or "").strip()
|
||||
return value if value and re.fullmatch(r"[\w.+-]+", value) else None
|
||||
return None
|
||||
|
||||
|
||||
def _check_build_refs(
|
||||
profile: dict,
|
||||
deferred: list[tuple[Citation, dict]],
|
||||
views: list[RepoView],
|
||||
fetch: Callable[[upstream.Repo, str, str], list[str] | None],
|
||||
) -> list[dict]:
|
||||
"""Each deferred config_reads ref read at the build of its platforms.
|
||||
|
||||
The file must exist at that revision and every cited line lie inside
|
||||
it. The entry declares no value to anchor on, so this is the check a
|
||||
ref past the end of its file fails (BUILD_GONE), not a content match.
|
||||
"""
|
||||
results: list[dict] = []
|
||||
for citation, read in deferred:
|
||||
for platform in read.get("platforms") or []:
|
||||
revision = str(read.get("revision") or "") or build_revision(profile, str(platform))
|
||||
row = {"platform": str(platform), "revision": revision or "",
|
||||
"ref": citation.ref, "field": citation.field}
|
||||
if revision is None:
|
||||
results.append({**row, "status": "BUILD_UNREAD",
|
||||
"detail": "no pin_build revision for this platform"})
|
||||
continue
|
||||
problems: list[str] = []
|
||||
for part in split_source_ref(citation.ref):
|
||||
role, path = ref_role(part.path)
|
||||
if " " in path:
|
||||
# A project word in front (`ROCKNIX patches/x.patch:4`):
|
||||
# a file of the platform's tree, read with the record.
|
||||
continue
|
||||
lines = next(
|
||||
(found for view in views
|
||||
if (not role or view.field == role)
|
||||
and (found := fetch(view.repo, revision, path)) is not None),
|
||||
None,
|
||||
)
|
||||
if lines is None:
|
||||
problems.append(f"{part.path} absent at {revision[:12]}")
|
||||
elif (part.end or part.start or 0) > len(lines):
|
||||
problems.append(f"{part.raw} past the end ({len(lines)} lines)")
|
||||
results.append({
|
||||
**row,
|
||||
"status": "BUILD_GONE" if problems else "BUILD_OK",
|
||||
"detail": "; ".join(problems),
|
||||
})
|
||||
return results
|
||||
|
||||
|
||||
def build_report(
|
||||
name: str, profile: dict, cache_dir: str, offline: bool = False,
|
||||
text: str | None = None,
|
||||
@@ -1621,7 +1702,13 @@ def build_report(
|
||||
)
|
||||
modes = {mode for _, mode, _ in declared_repositories(profile) if mode}
|
||||
refs = []
|
||||
at_build = shipped_build_holders(profile)
|
||||
deferred: list[tuple[Citation, dict]] = []
|
||||
for citation in collect_citations(profile, text):
|
||||
if citation.kind == "ref" and id(citation.holder) in at_build:
|
||||
# Written for the build a platform ships: read at pin_build.
|
||||
deferred.append((citation, at_build[id(citation.holder)]))
|
||||
continue
|
||||
if citation.kind == "ref":
|
||||
entry = citation.entry
|
||||
display = str(entry.get("name") or "") or citation.field
|
||||
@@ -2204,6 +2291,8 @@ def build_report(
|
||||
)
|
||||
return result
|
||||
|
||||
report.build_refs = _check_build_refs(profile, deferred, views, fetch_from)
|
||||
|
||||
staged = []
|
||||
for entry_name, ref, tokens, hashes, ref_parts, citation in refs:
|
||||
flags = [self_checked(part, tokens) for part in ref_parts]
|
||||
@@ -2335,6 +2424,14 @@ def format_report(report: ProfileReport, changed_only: bool = False) -> str:
|
||||
lines.append(f" {len(report.entries)} refs: {summary}")
|
||||
for line in report.stale_prose or ():
|
||||
lines.append(f" prose under an older pin: {line}")
|
||||
for ref in report.build_refs:
|
||||
if changed_only and ref["status"] == "BUILD_OK":
|
||||
continue
|
||||
detail = f": {ref['detail']}" if ref["detail"] else ""
|
||||
lines.append(
|
||||
f" {ref['status']} at {ref['platform']} build "
|
||||
f"{ref['revision'][:12] or '-'} {ref['ref']}{detail}"
|
||||
)
|
||||
lines.append(f" {report.needs_review()} to review")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ runs the script its standalone_emulators table names (/usr/bin/<name>.sh,
|
||||
installed from the package). Those scripts, and the configs their packages
|
||||
install, say which file under /storage/roms/bios is opened: yabasanshiro.sh
|
||||
tests saturn_bios.bin and passes it with -b, Hatari's default config names
|
||||
tos.img, the atari800 core is built to read a config naming its OS ROMs.
|
||||
tos.img.
|
||||
|
||||
runemu.py is read with ast, the scripts with shell_launchers' readers. An
|
||||
extractor whose construct is gone raises instead of returning nothing.
|
||||
@@ -26,7 +26,9 @@ try:
|
||||
from .shell_launchers import (
|
||||
LauncherPatternMissing,
|
||||
Script,
|
||||
config_placement,
|
||||
describe_keys,
|
||||
evidence_fields,
|
||||
settings,
|
||||
source_ref,
|
||||
)
|
||||
@@ -35,7 +37,9 @@ except ImportError:
|
||||
from shell_launchers import ( # type: ignore[no-redef]
|
||||
LauncherPatternMissing,
|
||||
Script,
|
||||
config_placement,
|
||||
describe_keys,
|
||||
evidence_fields,
|
||||
settings,
|
||||
source_ref,
|
||||
)
|
||||
@@ -45,8 +49,8 @@ RUNEMU = "packages/amberelec/sources/scripts/runemu.py"
|
||||
RETROARCH_CFG = "packages/games/tools/retroarch/sources/retroarch.cfg"
|
||||
RETRORUN = "packages/games/tools/retrorun/retrorun.sh"
|
||||
HATARI_CONFIG = "packages/games/emulators/hatarisa/config/conf/Atari-ST-default.cfg"
|
||||
ATARI800_CONFIG = "packages/amberelec/config/distribution/configs/atari800.cfg"
|
||||
ATARI800_PATCH = "packages/games/libretro/atari800/patches/atari800-01-add-emuelec-platform.patch"
|
||||
# The first-boot copy of every package's /usr/config into /storage/.config.
|
||||
USERCONFIG = "packages/sysutils/systemd/scripts/userconfig-setup"
|
||||
AMIBERRY_PACKAGE = "packages/games/emulators/amiberry/package.mk"
|
||||
AMIBERRY_CONFIGS = "packages/games/emulators/amiberry/config/conf"
|
||||
FREEJ2ME = (
|
||||
@@ -103,16 +107,35 @@ class Runemu:
|
||||
return path, line
|
||||
|
||||
|
||||
def _evidence(
|
||||
read: Read, record: Launcher, target: str, keys: list[str],
|
||||
start: Script | None = None, source_name: str = "",
|
||||
) -> Launcher:
|
||||
"""A config record with the steps that put its file at ``target``: the
|
||||
first-boot copy of /usr/config, then the start script's own copy."""
|
||||
setup = Script(USERCONFIG, read(USERCONFIG))
|
||||
placements = [config_placement(setup, target, required=False, sources=("/usr/config/",))]
|
||||
if start is not None:
|
||||
placements.append(
|
||||
config_placement(start, target, keys, source_name=source_name, required=False)
|
||||
)
|
||||
fields = evidence_fields(placements)
|
||||
record.installs = fields["installs"]
|
||||
record.kept_if_present = fields["kept_if_present"]
|
||||
record.overrides = fields["overrides"]
|
||||
return record
|
||||
|
||||
|
||||
def retroarch(read: Read) -> list[Launcher]:
|
||||
"""system_directory of the retroarch.cfg the retroarch package installs."""
|
||||
found = [s for s in settings(read(RETROARCH_CFG)) if s.key == "system_directory"]
|
||||
if len(found) != 1:
|
||||
raise LauncherPatternMissing(RETROARCH_CFG, "one system_directory")
|
||||
return [Launcher(
|
||||
return [_evidence(read, Launcher(
|
||||
emulator="retroarch", build="libretro", kind="passes_path", names=[],
|
||||
search_dir=found[0].value, passes_to="retroarch.cfg system_directory",
|
||||
fails_when_missing=False, source_ref=source_ref([(RETROARCH_CFG, [found[0].line])]),
|
||||
)]
|
||||
), "/storage/.config/retroarch/retroarch.cfg", ["system_directory"])]
|
||||
|
||||
|
||||
def retrorun(read: Read) -> list[Launcher]:
|
||||
@@ -170,10 +193,12 @@ def hatari(read: Read, runemu: Runemu) -> list[Launcher]:
|
||||
path, table_line = runemu.script("HATARISA")
|
||||
script = Script(path, read(path))
|
||||
name = posixpath.basename(HATARI_CONFIG)
|
||||
copied, _ = script.find(rf"^\s*cp\s+\S*/{re.escape(name)}\s", f"cp of {name}")
|
||||
copied, copy = script.find(
|
||||
rf"^\s*cp\s+\S*/{re.escape(name)}\s+\"?(\$\{{?\w+\}}?)", f"cp of {name}"
|
||||
)
|
||||
passed, _ = script.find(r"\shatari\s+--configfile\s", "hatari --configfile")
|
||||
files, lines = _bios_files(HATARI_CONFIG, read(HATARI_CONFIG))
|
||||
return [Launcher(
|
||||
return [_evidence(read, Launcher(
|
||||
emulator="HATARISA", build="standalone", kind="fixed_name",
|
||||
names=[n for _k, n in files], case_insensitive=False, search_dir=BIOS,
|
||||
passes_to=describe_keys(name, tuple(k for k, _n in files)),
|
||||
@@ -181,24 +206,8 @@ def hatari(read: Read, runemu: Runemu) -> list[Launcher]:
|
||||
source_ref=source_ref([
|
||||
(RUNEMU, [table_line]), (path, [copied, passed]), (HATARI_CONFIG, lines),
|
||||
]),
|
||||
)]
|
||||
|
||||
|
||||
def atari800(read: Read) -> list[Launcher]:
|
||||
"""The ROM keys of the config the atari800 core is built to read."""
|
||||
patch = Script(ATARI800_PATCH, read(ATARI800_PATCH))
|
||||
line, found = patch.find(r'DEFAULT_CFG_NAME="\\"([^"\\]+)\\""', "DEFAULT_CFG_NAME")
|
||||
built = found.group(1)
|
||||
if not built.endswith("/" + ATARI800_CONFIG.split("/config/", 1)[1]):
|
||||
raise LauncherPatternMissing(ATARI800_PATCH, f"DEFAULT_CFG_NAME naming {ATARI800_CONFIG}")
|
||||
files, lines = _bios_files(ATARI800_CONFIG, read(ATARI800_CONFIG))
|
||||
return [Launcher(
|
||||
emulator="atari800", build="libretro", kind="fixed_name",
|
||||
names=[n for _k, n in files], case_insensitive=False, search_dir=BIOS,
|
||||
passes_to=describe_keys(posixpath.basename(ATARI800_CONFIG), tuple(k for k, _n in files)),
|
||||
fails_when_missing=False,
|
||||
source_ref=source_ref([(ATARI800_PATCH, [line]), (ATARI800_CONFIG, lines)]),
|
||||
)]
|
||||
), script.expand(copy.group(1), copied, set()),
|
||||
[f"[{s}] {k}" if s else k for (s, k), _n in files], script, name)]
|
||||
|
||||
|
||||
def yabasanshiro(read: Read, runemu: Runemu) -> list[Launcher]:
|
||||
@@ -279,6 +288,15 @@ def amiberry(read: Read, runemu: Runemu) -> list[Launcher]:
|
||||
installed = re.sub(r"^\$\{INSTALL\}", "", link.link)
|
||||
path, table_line = runemu.script("AMIBERRY")
|
||||
script = Script(path, read(path))
|
||||
# A WHDLoad archive is booted by --autoload, which builds its own setup
|
||||
# over the config: the kickstart records hold for the other content.
|
||||
autoload = [n for n, text in script.code() if re.search(r"amiberry .*--autoload", text)]
|
||||
if not autoload:
|
||||
raise script.missing("WHDLoad boot with --autoload")
|
||||
content = (
|
||||
"content not booted with --autoload, a WHDLoad .lha or .zip "
|
||||
f"({posixpath.basename(path)}:{', '.join(map(str, autoload))})"
|
||||
)
|
||||
launchers = [Launcher(
|
||||
emulator="AMIBERRY", build="standalone", kind="links", names=[],
|
||||
case_insensitive=False, search_dir=BIOS,
|
||||
@@ -314,19 +332,23 @@ def amiberry(read: Read, runemu: Runemu) -> list[Launcher]:
|
||||
else:
|
||||
test = _shell_test(script, condition_line)
|
||||
condition = test
|
||||
launchers.append(Launcher(
|
||||
target = re.search(r'"?(\$\{?\w+\}?)"?\s*$', line)
|
||||
if target is None:
|
||||
raise script.missing(f"destination of the copy at line {number}")
|
||||
launchers.append(_evidence(read, Launcher(
|
||||
emulator="AMIBERRY", build="standalone", kind="fixed_name",
|
||||
slot=copied.group(1).removesuffix("-default.uae").removeprefix("Amiga"),
|
||||
names=[found[0].value.removeprefix("$(FILE_PATH)/")], case_insensitive=False,
|
||||
search_dir=BIOS,
|
||||
passes_to=f"{copied.group(1)} kickstart_rom_file, $(FILE_PATH) = {rom_path[0].value}",
|
||||
fails_when_missing=False,
|
||||
depends_on_option=condition,
|
||||
depends_on_option=f"{condition}, {content}",
|
||||
source_ref=source_ref([
|
||||
(RUNEMU, [table_line]), (path, [condition_line, number]),
|
||||
(config, [rom_path[0].line, found[0].line]),
|
||||
]),
|
||||
))
|
||||
), script.expand(target.group(1), number, set()), ["kickstart_rom_file"],
|
||||
script, copied.group(1)))
|
||||
if len(launchers) == 1:
|
||||
raise script.missing("cp of a default .uae config")
|
||||
return launchers
|
||||
@@ -420,9 +442,13 @@ def easyrpg(read: Read) -> list[Launcher]:
|
||||
def extract_launchers(read: Read) -> list[dict[str, Any]]:
|
||||
"""Every launcher record, read through `read(repo-relative path)`."""
|
||||
runemu = Runemu(read)
|
||||
# The atari800.cfg AmberELEC ships names the OS ROMs, but the core opens
|
||||
# it only under its atari800_cfg option, off by default, and finds the
|
||||
# ROMs by a scan of the content folder (libretro-atari800 atari.c:512-516,
|
||||
# 537, libretro_core_options.h:1203): no record reads it.
|
||||
launchers = [
|
||||
*retroarch(read), *retrorun(read), *mame(runemu),
|
||||
*atari800(read), *scummvm(read), *freej2me(read), *easyrpg(read),
|
||||
*scummvm(read), *freej2me(read), *easyrpg(read),
|
||||
*amiberry(read, runemu), *hatari(read, runemu), *pico8(read, runemu),
|
||||
*piemu(read, runemu), *yabasanshiro(read, runemu),
|
||||
]
|
||||
|
||||
@@ -39,6 +39,14 @@ class Launcher:
|
||||
machines: list[str] | None = None
|
||||
# The platform systems the record is written for, none for every one.
|
||||
systems: list[str] | None = None
|
||||
# For a record citing a config: where the platform's code puts it
|
||||
# ({path, source_ref}), whether that leaves a file already there, and
|
||||
# the launch code rewriting its keys ([] when none does).
|
||||
installs: dict[str, str] | None = None
|
||||
kept_if_present: bool | None = None
|
||||
overrides: list[str] | None = None
|
||||
# The feature or option file listing the values the option written takes.
|
||||
choices_from: str | None = None
|
||||
|
||||
def entry(self) -> dict[str, Any]:
|
||||
"""The platform YAML form, in a fixed key order, unset keys left out."""
|
||||
@@ -46,7 +54,8 @@ class Launcher:
|
||||
"emulator", "systems", "build", "kind", "slot", "names", "expands",
|
||||
"case_insensitive", "search_dir", "passes_to",
|
||||
"fails_when_missing", "fails_scope", "depends_on_option",
|
||||
"device", "machines", "source_ref",
|
||||
"device", "machines", "installs", "kept_if_present", "overrides",
|
||||
"choices_from", "source_ref",
|
||||
)
|
||||
return {key: getattr(self, key) for key in order if getattr(self, key) is not None}
|
||||
|
||||
|
||||
@@ -44,6 +44,8 @@ BIOS = "${biosPath}"
|
||||
EMULATION_BIOS = "${emulationPath}/bios"
|
||||
STORAGE = "${storagePath}"
|
||||
FLATPAK_DATA = "${HOME}/.var/app/"
|
||||
# The function every EmuScript installs its Flatpak config with.
|
||||
CONFIG_EMU_FP = "functions/configEmuFP.sh"
|
||||
|
||||
# EmuScripts file names that differ from the emulator profile they set up.
|
||||
# The platform and target scrapers both read them here.
|
||||
@@ -95,6 +97,31 @@ def _is_bios(value: str) -> bool:
|
||||
return any(value == root or value.startswith(root + "/") for root in (BIOS, EMULATION_BIOS))
|
||||
|
||||
|
||||
def with_evidence(tree: RepoTree, script: Script, record: Launcher, config: str) -> Launcher:
|
||||
"""A record citing a shipped config, with the steps that install it.
|
||||
|
||||
configEmuFP rsyncs the repository's configs/<app> over the Flatpak's:
|
||||
the _init call overwrites (keeping a .bak), every other call passes
|
||||
--ignore-existing and leaves the user's file in place.
|
||||
"""
|
||||
fp = Script(CONFIG_EMU_FP, tree.read(CONFIG_EMU_FP))
|
||||
rsync_line, _ = fp.find(r"^\s*rsync .*\$emudeckBackend/configs/", "rsync of the configs")
|
||||
keep_line, _ = fp.find(r'overwrite="--ignore-existing"', "--ignore-existing")
|
||||
calls = {n for n, line in script.code() if re.match(r"\s*configEmuFP\s", line)}
|
||||
if not calls:
|
||||
raise script.missing("configEmuFP call")
|
||||
variable = script.assignment_ending("/" + config)
|
||||
if variable is None:
|
||||
raise script.missing(f"config variable for {config}")
|
||||
record.installs = {
|
||||
"path": script.expand(variable.value, variable.line, set()),
|
||||
"source_ref": source_ref([(script.path, calls), (fp.path, {keep_line, rsync_line})]),
|
||||
}
|
||||
record.kept_if_present = True
|
||||
record.overrides = []
|
||||
return record
|
||||
|
||||
|
||||
def _repo_config(script: Script, path: str) -> str:
|
||||
"""The repository copy of a Flatpak config EmuDeck installs."""
|
||||
if not path.startswith(FLATPAK_DATA):
|
||||
@@ -268,7 +295,8 @@ def ares(tree: RepoTree) -> list[Launcher]:
|
||||
raise LauncherPatternMissing(path, f"Firmware path under {old}")
|
||||
for system, found in entries.items():
|
||||
folder = posixpath.commonpath([posixpath.dirname(t) for _, t, _ in found])
|
||||
records.append(
|
||||
records.append(with_evidence(
|
||||
tree, script,
|
||||
Launcher(
|
||||
emulator="ares",
|
||||
build="standalone",
|
||||
@@ -281,16 +309,20 @@ def ares(tree: RepoTree) -> list[Launcher]:
|
||||
search_dir=folder,
|
||||
passes_to="settings.bml "
|
||||
+ ", ".join(f"{system}/Firmware/{k}" for k, _, _ in found),
|
||||
)
|
||||
)
|
||||
),
|
||||
posixpath.basename(path),
|
||||
))
|
||||
return records
|
||||
|
||||
|
||||
def melonds(tree: RepoTree) -> list[Launcher]:
|
||||
"""melonDS.ini paths set by changeLine, melonDS.toml paths shipped and rewritten by sed."""
|
||||
name = "emuDeckMelonDS.sh"
|
||||
records = setter_records(tree, name, option_key="ExternalBIOSEnable")
|
||||
script = _script(tree, name)
|
||||
records = [
|
||||
with_evidence(tree, script, record, str(record.passes_to or "").split(" ", 1)[0])
|
||||
for record in setter_records(tree, name, option_key="ExternalBIOSEnable")
|
||||
]
|
||||
# A config whose BIOS keys the setters write again keeps their values.
|
||||
set_by_setters = {file for file, _, _, value, _ in setters(script) if _is_bios(value)}
|
||||
for file, old, new, sed_lines in sed_rewrites(script, "melonDS_init"):
|
||||
@@ -306,22 +338,29 @@ def melonds(tree: RepoTree) -> list[Launcher]:
|
||||
continue
|
||||
folder = posixpath.commonpath([posixpath.dirname(t) for _, t in found])
|
||||
config = posixpath.basename(path)
|
||||
option = next((s for s in settings(tree.read(path)) if s.key == "ExternalBIOSEnable"), None)
|
||||
if option is None:
|
||||
raise LauncherPatternMissing(path, "ExternalBIOSEnable")
|
||||
shipped = {s.key: s for s in settings(tree.read(path))}
|
||||
if "ExternalBIOSEnable" not in shipped or "ConsoleType" not in shipped:
|
||||
raise LauncherPatternMissing(path, "ExternalBIOSEnable and ConsoleType")
|
||||
option, console = shipped["ExternalBIOSEnable"], shipped["ConsoleType"]
|
||||
# The DS keys are read under ExternalBIOSEnable, the DSi keys only
|
||||
# when the console is a DSi (ConsoleType 1).
|
||||
record = Launcher(
|
||||
emulator="melonds",
|
||||
build="standalone",
|
||||
kind="fixed_name",
|
||||
names=[posixpath.relpath(t, folder) for _, t in found],
|
||||
source_ref=source_ref(
|
||||
[(path, {option.line, *(s.line for s, _ in found)}), (script.path, sed_lines)]
|
||||
),
|
||||
source_ref=source_ref([
|
||||
(path, {option.line, console.line, *(s.line for s, _ in found)}),
|
||||
(script.path, sed_lines),
|
||||
]),
|
||||
search_dir=folder,
|
||||
passes_to=describe_keys(config, tuple((s.section, s.key) for s, _ in found)),
|
||||
depends_on_option=f"ExternalBIOSEnable = {option.value} in the shipped {config}",
|
||||
depends_on_option=(
|
||||
f"[DS] keys: ExternalBIOSEnable = true, {option.value} in the shipped {config}; "
|
||||
f"[DSi] keys: ConsoleType = 1, {console.value} in the shipped {config}"
|
||||
),
|
||||
)
|
||||
records.append(record)
|
||||
records.append(with_evidence(tree, script, record, config))
|
||||
if len(records) < 2:
|
||||
raise script.missing("melonDS.toml BIOS paths rewritten by sed")
|
||||
return records
|
||||
|
||||
@@ -14,7 +14,7 @@ from __future__ import annotations
|
||||
|
||||
import posixpath
|
||||
import re
|
||||
from collections.abc import Callable
|
||||
from collections.abc import Callable, Iterable
|
||||
from dataclasses import dataclass, field
|
||||
|
||||
from .configgen_launchers import Launcher
|
||||
@@ -22,6 +22,8 @@ from .rocknix_launchers import fixed_paths
|
||||
from .shell_launchers import (
|
||||
LauncherPatternMissing,
|
||||
Link,
|
||||
config_placement,
|
||||
evidence_fields,
|
||||
RepoTree,
|
||||
Script,
|
||||
describe_keys,
|
||||
@@ -104,6 +106,28 @@ class Runs:
|
||||
return (RUN_EMU, set(self.of(name).lines))
|
||||
|
||||
|
||||
def _evidence(
|
||||
record: Launcher,
|
||||
script: Script,
|
||||
target: str,
|
||||
keys: list[str],
|
||||
source_name: str = "",
|
||||
rewrites: Iterable[int] = (),
|
||||
) -> Launcher:
|
||||
"""A config record with the start script lines that put its file in place.
|
||||
|
||||
``rewrites`` are lines the extractor read as rewriting the record's
|
||||
values without naming their keys (advmame.sh's sed of /roms/mame).
|
||||
"""
|
||||
placement = config_placement(script, target, keys, source_name=source_name)
|
||||
placement.overrides |= set(rewrites)
|
||||
fields = evidence_fields([placement])
|
||||
record.installs = fields["installs"]
|
||||
record.kept_if_present = fields["kept_if_present"]
|
||||
record.overrides = fields["overrides"]
|
||||
return record
|
||||
|
||||
|
||||
def _read(tree: RepoTree, path: str) -> Script:
|
||||
return Script(path, tree.read(path))
|
||||
|
||||
@@ -317,7 +341,7 @@ def duckstation(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
name = posixpath.basename(script.path)
|
||||
lines = {found[k].line for k in (folder_key, *file_keys) if k in found}
|
||||
unset = describe_keys("", file_keys).strip()
|
||||
return [
|
||||
return [_evidence(
|
||||
Launcher(
|
||||
emulator=runs.emulator(name),
|
||||
build="standalone",
|
||||
@@ -328,8 +352,11 @@ def duckstation(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
),
|
||||
search_dir=found[folder_key].value,
|
||||
passes_to=f"settings.ini [BIOS] SearchDirectory (-settings), {unset} unset",
|
||||
)
|
||||
]
|
||||
),
|
||||
script,
|
||||
script.expand("${CONFIG_DIR}/settings.ini", run_line, set()),
|
||||
[f"[{s}] {k}" for s, k in (folder_key, *file_keys)],
|
||||
)]
|
||||
|
||||
|
||||
YABASANSHIRO_SCRIPTS = (
|
||||
@@ -473,7 +500,7 @@ def hatari(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
mk = _read(tree, f"{package}/package.mk")
|
||||
mk_line, _ = mk.find(r"cp -R \$\{PKG_DIR\}/config/\* ", "config install")
|
||||
name = posixpath.basename(script.path)
|
||||
return [
|
||||
return [_evidence(
|
||||
Launcher(
|
||||
emulator=runs.emulator(name),
|
||||
build="standalone",
|
||||
@@ -485,8 +512,12 @@ def hatari(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
),
|
||||
search_dir=value.search_dir,
|
||||
passes_to=f"{describe_keys(copy.group(1), value.keys)} (--configfile)",
|
||||
)
|
||||
]
|
||||
),
|
||||
script,
|
||||
script.expand("${" + copy.group(2) + "}", copy_line, set()),
|
||||
[f"[{s}] {k}" if s else k for s, k in value.keys],
|
||||
source_name=copy.group(1),
|
||||
)]
|
||||
|
||||
|
||||
_ADVMAME_SYSTEM = re.compile(r'^\s*if \[\[ "\$\{1\}" = "([\w-]+)" \]\]; then$')
|
||||
@@ -535,29 +566,34 @@ def advancemame(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
(script.path, {run_line, *lines}),
|
||||
])
|
||||
|
||||
found = []
|
||||
target = script.expand("${CONFIG_DIR}/advmame.rc", run_line, set())
|
||||
|
||||
def proved(record: Launcher, key: str) -> Launcher:
|
||||
return _evidence(record, script, target, [key], rewrites={sed_line})
|
||||
|
||||
records = []
|
||||
for key, folder in value:
|
||||
rewritten = folder.replace(sed.group(1), sed.group(2))
|
||||
if rewritten != folder:
|
||||
# Every system but the one the script rewrites the key for, and
|
||||
# that system with the rewritten folder.
|
||||
found.append(Launcher(
|
||||
records.append(proved(Launcher(
|
||||
emulator=runs.emulator(name), build="standalone", kind="passes_path", names=[],
|
||||
source_ref=refs(test_line, sed_line), search_dir=folder,
|
||||
passes_to=f"advmame.rc {key}",
|
||||
depends_on_option=f"system != {test.group(1)}",
|
||||
))
|
||||
found.append(Launcher(
|
||||
), key))
|
||||
records.append(proved(Launcher(
|
||||
emulator=runs.emulator(name), build="standalone", kind="passes_path", names=[],
|
||||
source_ref=refs(test_line, sed_line), search_dir=rewritten,
|
||||
passes_to=f"advmame.rc {key}", systems=[test.group(1)],
|
||||
))
|
||||
), key))
|
||||
continue
|
||||
found.append(Launcher(
|
||||
records.append(proved(Launcher(
|
||||
emulator=runs.emulator(name), build="standalone", kind="passes_path", names=[],
|
||||
source_ref=refs(), search_dir=folder, passes_to=f"advmame.rc {key}",
|
||||
))
|
||||
return found
|
||||
), key))
|
||||
return records
|
||||
|
||||
|
||||
def mame(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
@@ -594,42 +630,11 @@ def mame(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
)
|
||||
if not records:
|
||||
raise script.missing(f"copy into {BIOS_ROOT}")
|
||||
ini = next((r for r in records if r.names == ["mame*"]), None)
|
||||
if ini is None:
|
||||
raise script.missing("copy of mame.ini")
|
||||
option_path = f"{package}/config/MAME/MAME.opt"
|
||||
option = next(
|
||||
(s for s in settings(tree.read(option_path)) if s.key == "mame_read_config"), None
|
||||
)
|
||||
if option is None:
|
||||
raise LauncherPatternMissing(option_path, "mame_read_config")
|
||||
ini_path = f"{package}/config/ini/mame.ini"
|
||||
# MAME reads from the folders its *path options name and writes to its
|
||||
# *_directory ones.
|
||||
folders = [
|
||||
(s, [p for p in s.value.split(";") if _under(p)])
|
||||
for s in settings(tree.read(ini_path), separator=" ")
|
||||
if s.key.endswith("path")
|
||||
]
|
||||
folders = [(s, parts) for s, parts in folders if parts]
|
||||
if not folders:
|
||||
raise LauncherPatternMissing(ini_path, f"path under {BIOS_ROOT}")
|
||||
for setting, parts in folders:
|
||||
for part in parts:
|
||||
records.append(
|
||||
Launcher(
|
||||
emulator=emulator,
|
||||
build="libretro",
|
||||
kind="passes_path",
|
||||
names=[],
|
||||
source_ref=source_ref(
|
||||
[(ini_path, {setting.line}), (option_path, {option.line})]
|
||||
) + f", {ini.source_ref}",
|
||||
search_dir=part.rstrip("/"),
|
||||
passes_to=f"mame.ini {setting.key}",
|
||||
depends_on_option=f"mame_read_config = {option.value}",
|
||||
)
|
||||
)
|
||||
# mame.ini hands the core no folder: MAME.opt turns on
|
||||
# mame_mame_paths_enable, so the core passes no path option
|
||||
# (libretro mame src/osd/libretro/libretro-internal/retro_init.cpp:554-555),
|
||||
# and the ini MAME would read sits under a working directory no launcher
|
||||
# sets (src/emu/emuopts.cpp:49). Only the copies are the launcher's.
|
||||
return records
|
||||
|
||||
|
||||
@@ -644,6 +649,16 @@ def scummvm(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
core_line, core = script.find(r"-L /tmp/cores/(\w+)_libretro\.so", "libretro start")
|
||||
arm_line, arm = script.find(r'^\s*"(\w+)"\)', "setup arm", core_line)
|
||||
copy_line, copy = script.find(r"^\s*cp (\S+) (\S+)$", "copy into the BIOS folder", arm_line)
|
||||
launched = sorted({
|
||||
m.group(1) for _, line in runs.script.code()
|
||||
if (m := re.search(rf"\b{re.escape(name)} (\w+)", line))
|
||||
})
|
||||
if not launched:
|
||||
raise runs.script.missing(f"start of {name} with an action")
|
||||
action = f"{name} {arm.group(1)}"
|
||||
if arm.group(1) not in launched:
|
||||
# The copy runs from the setup action, never from a launch.
|
||||
action += f", an action no launch runs ({RUN_EMU.rsplit('/', 1)[-1]} passes {', '.join(launched)})"
|
||||
used = {copy_line}
|
||||
source = script.expand(copy.group(1), copy_line, used)
|
||||
target = script.expand(copy.group(2), copy_line, used)
|
||||
@@ -669,7 +684,7 @@ def scummvm(tree: RepoTree, runs: Runs) -> list[Launcher]:
|
||||
search_dir=posixpath.dirname(source),
|
||||
passes_to=target,
|
||||
fails_when_missing=False,
|
||||
depends_on_option=f"{name} {arm.group(1)}",
|
||||
depends_on_option=action,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
@@ -1001,6 +1001,14 @@ def boot_disks(
|
||||
emulator = (
|
||||
", ".join(_caller_cores(cg, spec.caller)) if spec.caller else cg.emulator(module)
|
||||
)
|
||||
if spec.caller and spec.feature[:2] == ("libretro", "cores"):
|
||||
# The option is offered for one core of the system: es_features
|
||||
# lists it under that core, the other cores the generator serves
|
||||
# never see it (KNULLI's macintosh offers mame alone).
|
||||
core = spec.feature[2]
|
||||
if core not in emulator.split(", "):
|
||||
src.fail(f"es_features offers the option for {core}, which the generator does not serve")
|
||||
emulator = core
|
||||
found = 0
|
||||
for chain in ast.walk(src.tree):
|
||||
if not (
|
||||
@@ -1054,10 +1062,10 @@ def boot_disks(
|
||||
expands={option: values}, case_insensitive=False, search_dir=cg.bios,
|
||||
passes_to=f"command line {flag}", fails_when_missing=False,
|
||||
depends_on_option=f"{option} ({' and '.join(tests)})",
|
||||
source_ref=", ".join([
|
||||
src.ref([*spans, src.span(statement), _lines(added)]),
|
||||
f"{ES_FEATURES}:{lines[0]}-{lines[1]}" if not listed else "",
|
||||
]).rstrip(", "),
|
||||
# The values the menu offers come from es_features.yml;
|
||||
# the generator writing the choice is the evidence.
|
||||
choices_from=None if listed else f"{ES_FEATURES}:{lines[0]}-{lines[1]}",
|
||||
source_ref=src.ref([*spans, src.span(statement), _lines(added)]),
|
||||
))
|
||||
if not found:
|
||||
src.fail("names no BIOS file from an option value")
|
||||
|
||||
@@ -14,6 +14,11 @@ import bisect
|
||||
import re
|
||||
from collections.abc import Callable, Iterator
|
||||
|
||||
try:
|
||||
from .shell_launchers import is_feature_ref, split_ref
|
||||
except ImportError:
|
||||
from shell_launchers import is_feature_ref, split_ref # type: ignore[no-redef]
|
||||
|
||||
GENERATORS = "emulatorLauncher/Generators"
|
||||
FEATURES = ".emulationstation/es_features.cfg"
|
||||
|
||||
@@ -1254,6 +1259,11 @@ def xemu(sources: dict[str, Source]) -> list[Record]:
|
||||
)
|
||||
|
||||
flash = src.find(r'isOptSet\("(xemu_flashrom)"\)', "xemu_flashrom")
|
||||
# The flashrom is written outside a Chihiro launch only.
|
||||
chihiro_set = src.find(r"(_chihiro) = \(([^;]+)\);", "Chihiro test")
|
||||
chihiro_guard = src.find_all(
|
||||
rf"if \(!{chihiro_set.group(1)}\)", "flashrom guard", end=flash.start()
|
||||
)[-1]
|
||||
flash_default = src.find(
|
||||
r'ini\.WriteValue\("([\w.]+)", "(flashrom_path)", "\'" \+ Path\.Combine\(flashromPath, "([^"]+)"\)',
|
||||
"flashrom default",
|
||||
@@ -1267,7 +1277,10 @@ def xemu(sources: dict[str, Source]) -> list[Record]:
|
||||
"core_option",
|
||||
_unique([flash_default.group(3), *choices]),
|
||||
source_ref(
|
||||
(src.path, [src.lines(flash.start(), flash_default.end())]),
|
||||
(src.path, [
|
||||
src.lines(chihiro_set.start(), chihiro_set.end()),
|
||||
src.lines(chihiro_guard.start(), flash_default.end()),
|
||||
]),
|
||||
(features.path, [choice_lines]),
|
||||
),
|
||||
case_insensitive=True,
|
||||
@@ -1277,7 +1290,7 @@ def xemu(sources: dict[str, Source]) -> list[Record]:
|
||||
f" default {flash_default.group(3)}"
|
||||
),
|
||||
fails_when_missing="path written without an existence check",
|
||||
depends_on_option=flash.group(1),
|
||||
depends_on_option=f"{flash.group(1)}, not ({chihiro_set.group(2)})",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -3890,4 +3903,23 @@ def extract_launchers(texts: dict[str, str]) -> list[Record]:
|
||||
if missing:
|
||||
raise LauncherPatternMissing(missing[0], "source file")
|
||||
sources = {path: Source(path, text) for path, text in texts.items()}
|
||||
return [record for extractor in EXTRACTORS for record in extractor(sources)]
|
||||
return [
|
||||
_choices_apart(record) for extractor in EXTRACTORS for record in extractor(sources)
|
||||
]
|
||||
|
||||
|
||||
def _choices_apart(record: Record) -> Record:
|
||||
"""The es_features.cfg part of a record's source_ref, moved to choices_from.
|
||||
|
||||
The feature file lists the values a menu option offers. The generator
|
||||
writing the choice is the record's evidence, never the list.
|
||||
"""
|
||||
parts = split_ref(str(record["source_ref"]))
|
||||
listed = [p for p in parts if is_feature_ref(p)]
|
||||
if not listed:
|
||||
return record
|
||||
code = [p for p in parts if not is_feature_ref(p)]
|
||||
if not code:
|
||||
raise LauncherPatternMissing(listed[0], "generator code beside the option list")
|
||||
moved = {k: v for k, v in record.items() if k != "source_ref"}
|
||||
return {**moved, "choices_from": ", ".join(listed), "source_ref": ", ".join(code)}
|
||||
@@ -35,6 +35,8 @@ PLACEHOLDER = "RETRODECKBIOSDIR"
|
||||
# gzdoom/component_prepare.sh:27 rewrites to $roms_path.
|
||||
ROMS_PLACEHOLDER = "RETRODECKROMSDIR"
|
||||
CORE_OPTIONS = "retroarch/rd_assets/rd_config/retroarch-core-options.cfg"
|
||||
# XRoar ROM lists RetroDECK's xroar.conf defines that no machine looks up.
|
||||
UNREAD_ROMLISTS = frozenset({"coco1", "coco1e", "coco1e_ext", "coco2", "coco2_ext", "coco2b"})
|
||||
# The component that runs libretro cores.
|
||||
LIBRETRO_COMPONENT = "retroarch"
|
||||
# Values of a core option that name a file rather than a setting.
|
||||
@@ -301,6 +303,19 @@ class Component:
|
||||
if copied is None:
|
||||
raise LauncherPatternMissing(f"{script.path}:{number}", f"no preset copied to {target}")
|
||||
preset = f"{self.name}/rd_assets/rd_config/{copied[1]}"
|
||||
# The reset copies the preset over the user's file, then fills its
|
||||
# placeholders: that is the install, and nothing keeps an older file.
|
||||
evidence: dict[str, Any] = {
|
||||
"installs": {
|
||||
"path": target,
|
||||
"source_ref": source_ref(
|
||||
[(script.path, copied[0])]
|
||||
+ [(script.path, line) for _v, line in substitutions.values()]
|
||||
),
|
||||
},
|
||||
"kept_if_present": False,
|
||||
"overrides": self.launch_rewrites(target),
|
||||
}
|
||||
text = self.read(preset)
|
||||
if text is None:
|
||||
raise LauncherPatternMissing(preset, "preset is missing")
|
||||
@@ -332,10 +347,10 @@ class Component:
|
||||
self.record(
|
||||
"passes_path", [], [(preset, line_no)] + applied,
|
||||
search_dir=value, passes_to=f"{self.config_name(target)} {where}",
|
||||
fails_when_missing=False,
|
||||
fails_when_missing=False, **evidence,
|
||||
)
|
||||
if key == "rompath":
|
||||
self.romlists(preset, text, value, applied)
|
||||
self.romlists(preset, text, value, applied, evidence)
|
||||
if not found:
|
||||
raise LauncherPatternMissing(preset, f"no {PLACEHOLDER} line")
|
||||
|
||||
@@ -349,10 +364,28 @@ class Component:
|
||||
found[m.group(1)] = (f"${m.group(2)}", line_no)
|
||||
return found
|
||||
|
||||
def launch_rewrites(self, target: str) -> list[str]:
|
||||
"""The sed lines of the component launcher rewriting ``target``."""
|
||||
path = f"{self.name}/component_launcher.sh"
|
||||
text = self.read(path)
|
||||
if text is None:
|
||||
return []
|
||||
return [
|
||||
source_ref([(path, number)])
|
||||
for number, line in enumerate(text.splitlines(), 1)
|
||||
if re.search(r"\bsed\b.*\s-i\b", line) and target in line
|
||||
]
|
||||
|
||||
def romlists(
|
||||
self, preset: str, text: str, rompath: str, applied: list[tuple[str, int]]
|
||||
self, preset: str, text: str, rompath: str, applied: list[tuple[str, int]],
|
||||
evidence: dict[str, Any],
|
||||
) -> None:
|
||||
"""XRoar's `romlist NAME=a,b,@other`: the names tried for each ROM, in order."""
|
||||
"""XRoar's `romlist NAME=a,b,@other`: the names tried for each ROM, in order.
|
||||
|
||||
A list no XRoar machine or cartridge looks up is no read: coco1,
|
||||
coco1e, coco1e_ext, coco2, coco2_ext and coco2b are defined by XRoar
|
||||
(src/xroar.c:663-670) and named by nothing else.
|
||||
"""
|
||||
lists: dict[str, tuple[int, list[str]]] = {}
|
||||
for line_no, line in enumerate(text.splitlines(), 1):
|
||||
found = re.match(r"^romlist\s+([\w-]+)=(.*)$", line.strip())
|
||||
@@ -375,10 +408,12 @@ class Component:
|
||||
return list(dict.fromkeys(names))
|
||||
|
||||
for name, (line_no, _items) in lists.items():
|
||||
if name in UNREAD_ROMLISTS:
|
||||
continue
|
||||
self.record(
|
||||
"names_searched", expand(name, (name,)), [(preset, line_no)] + applied,
|
||||
slot=name, search_dir=rompath, passes_to=f"romlist {name}",
|
||||
fails_when_missing=False,
|
||||
fails_when_missing=False, **evidence,
|
||||
)
|
||||
|
||||
def read_launcher(self) -> None:
|
||||
@@ -480,6 +515,7 @@ def core_options(read: Read) -> list[Launcher]:
|
||||
]
|
||||
if not copied:
|
||||
raise LauncherPatternMissing(prepare_path, "the core options preset is never copied")
|
||||
target = _words(prepare.splitlines()[copied[0] - 1].strip())[-1]
|
||||
records = []
|
||||
for line_no, line in enumerate(text.splitlines(), 1):
|
||||
found = re.match(r'^([\w.-]+)\s*=\s*"([^"]*)"$', line.strip())
|
||||
@@ -489,6 +525,8 @@ def core_options(read: Read) -> list[Launcher]:
|
||||
records.append(Launcher(
|
||||
emulator=LIBRETRO_COMPONENT, build="libretro", kind="core_option", names=[value],
|
||||
passes_to=f"core option {key}", fails_when_missing=False,
|
||||
installs={"path": target, "source_ref": source_ref([(prepare_path, copied[0])])},
|
||||
kept_if_present=False, overrides=[],
|
||||
source_ref=source_ref([(CORE_OPTIONS, line_no), (prepare_path, copied[0])]),
|
||||
))
|
||||
if not records:
|
||||
|
||||
@@ -94,6 +94,11 @@ class Launcher:
|
||||
passes_to: str | None = None
|
||||
fails_when_missing: bool | str | None = None
|
||||
depends_on_option: str | None = None
|
||||
# For a record citing a config: where the platform's code puts it, whether
|
||||
# that leaves a file already there, and the launch code rewriting it.
|
||||
installs: dict[str, str] | None = None
|
||||
kept_if_present: bool | None = None
|
||||
overrides: list[str] | None = None
|
||||
lines: list[tuple[str, int]] = field(default_factory=list, repr=False)
|
||||
|
||||
def entry(self) -> dict[str, Any]:
|
||||
@@ -101,7 +106,8 @@ class Launcher:
|
||||
order = (
|
||||
"emulator", "package", "repo", "systems", "build", "kind", "slot",
|
||||
"names", "case_insensitive", "search_dir", "passes_to",
|
||||
"fails_when_missing", "depends_on_option", "source_ref",
|
||||
"fails_when_missing", "depends_on_option", "installs", "kept_if_present",
|
||||
"overrides", "source_ref",
|
||||
)
|
||||
return {key: getattr(self, key) for key in order if getattr(self, key) is not None}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ from dataclasses import dataclass
|
||||
|
||||
try:
|
||||
from .configgen_launchers import Launcher
|
||||
from .shell_launchers import config_placement, evidence_fields
|
||||
from .shell_launchers import (
|
||||
LauncherPatternMissing,
|
||||
Link,
|
||||
@@ -30,6 +31,7 @@ try:
|
||||
)
|
||||
except ImportError:
|
||||
from configgen_launchers import Launcher
|
||||
from shell_launchers import config_placement, evidence_fields # type: ignore[no-redef]
|
||||
from shell_launchers import (
|
||||
LauncherPatternMissing,
|
||||
Link,
|
||||
@@ -46,6 +48,9 @@ DEVICES = f"{ROCKNIX}/devices"
|
||||
STANDALONE = f"{ROCKNIX}/packages/emulators/standalone"
|
||||
RETROARCH = f"{ROCKNIX}/packages/emulators/libretro/retroarch"
|
||||
BIOS_ROOT = "/storage/roms/bios"
|
||||
CONFIG_ROOT = "/storage/.config"
|
||||
# The first-boot step copying every package's /usr/config to /storage/.config.
|
||||
USERCONFIG = f"{ROCKNIX}/packages/sysutils/systemd/scripts/userconfig-setup"
|
||||
|
||||
Lines = list[tuple[str, set[int]]]
|
||||
|
||||
@@ -186,6 +191,38 @@ def bios_keys(tree: RepoTree, paths: list[str], root: str = BIOS_ROOT) -> list[t
|
||||
return keys
|
||||
|
||||
|
||||
def with_evidence(
|
||||
tree: RepoTree,
|
||||
record: Launcher,
|
||||
target: str,
|
||||
keys: list[str],
|
||||
start: Script | None = None,
|
||||
writers: tuple[str, ...] = (),
|
||||
source_name: str = "",
|
||||
) -> Launcher:
|
||||
"""A config record with the steps that put its file at ``target``.
|
||||
|
||||
The first boot copies /usr/config to /storage/.config, leaving a file
|
||||
already there. A start script can copy or generate it again, and its
|
||||
sed lines rewriting one of the record's keys are the overrides.
|
||||
"""
|
||||
setup = Script(USERCONFIG, tree.read(USERCONFIG))
|
||||
placements = [config_placement(setup, target, required=False, sources=("/usr/config/",))]
|
||||
if start is not None:
|
||||
placements.append(config_placement(
|
||||
start, target, keys, writers, source_name, required=False
|
||||
))
|
||||
fields = evidence_fields(placements)
|
||||
record.installs = fields["installs"]
|
||||
record.kept_if_present = fields["kept_if_present"]
|
||||
record.overrides = fields["overrides"]
|
||||
return record
|
||||
|
||||
|
||||
def _keys(value: FixedPaths) -> list[str]:
|
||||
return [f"[{section}] {key}" if section else key for section, key in value.keys]
|
||||
|
||||
|
||||
def config_records(
|
||||
tree: RepoTree,
|
||||
emulator: str,
|
||||
@@ -193,10 +230,17 @@ def config_records(
|
||||
file: str,
|
||||
passes_to_suffix: str = "",
|
||||
depends_on_option: str | None = None,
|
||||
target: str = "",
|
||||
start: Script | None = None,
|
||||
unread: Callable[[tuple[str, str]], bool] = lambda key: False,
|
||||
) -> list[Launcher]:
|
||||
"""fixed_name records for the bios paths of a config installed per device."""
|
||||
"""fixed_name records for the bios paths of a config installed per device.
|
||||
|
||||
``unread`` drops the keys the shipped configs leave the emulator
|
||||
reading no file from.
|
||||
"""
|
||||
configs = device_configs(tree, package, file)
|
||||
keys = bios_keys(tree, [c.path for c in configs])
|
||||
keys = [k for k in bios_keys(tree, [c.path for c in configs]) if not unread(k)]
|
||||
name = posixpath.basename(file)
|
||||
|
||||
def read(path: str, text: str) -> tuple[object, set[int]]:
|
||||
@@ -206,7 +250,8 @@ def config_records(
|
||||
for device, value, refs in per_device(tree, configs, f"{package}/package.mk", read):
|
||||
assert isinstance(value, FixedPaths)
|
||||
described = describe_keys(name, value.keys)
|
||||
records.append(
|
||||
records.append(with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator=emulator,
|
||||
build="standalone",
|
||||
@@ -219,8 +264,11 @@ def config_records(
|
||||
),
|
||||
device=device,
|
||||
depends_on_option=depends_on_option,
|
||||
)
|
||||
)
|
||||
),
|
||||
target or f"{CONFIG_ROOT}/{posixpath.basename(package)}/{name}",
|
||||
_keys(value),
|
||||
start,
|
||||
))
|
||||
return records
|
||||
|
||||
|
||||
@@ -241,7 +289,8 @@ def retroarch(tree: RepoTree) -> list[Launcher]:
|
||||
for device, value, refs in per_device(tree, configs, f"{RETROARCH}/package.mk", read):
|
||||
assert isinstance(value, tuple)
|
||||
values = dict(value)
|
||||
records.append(
|
||||
records.append(with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator="retroarch",
|
||||
build="libretro",
|
||||
@@ -251,8 +300,10 @@ def retroarch(tree: RepoTree) -> list[Launcher]:
|
||||
search_dir=values["system_directory"],
|
||||
passes_to="retroarch.cfg " + ", ".join(f'{k} = "{v}"' for k, v in value),
|
||||
device=device,
|
||||
)
|
||||
)
|
||||
),
|
||||
f"{CONFIG_ROOT}/retroarch/retroarch.cfg",
|
||||
[k for k, _ in value],
|
||||
))
|
||||
return records
|
||||
|
||||
|
||||
@@ -275,6 +326,19 @@ def amiberry(tree: RepoTree) -> list[Launcher]:
|
||||
)
|
||||
used: set[int] = {test_line, then_line, else_line, other_line, sed_line}
|
||||
root = script.expand("${" + sed.group(2) + "}", sed_line, used)
|
||||
written = re.search(r'"?(\$\{?\w+\}?)"?\s*$', script.lines[then_line - 1])
|
||||
if written is None:
|
||||
raise script.missing("destination of the config copy")
|
||||
target = script.expand(written.group(1), then_line, set())
|
||||
# A WHDLoad archive is booted by --autoload, which builds its own setup
|
||||
# (kickstart included) over the config: the record holds for floppies.
|
||||
autoload = [n for n, line in script.code() if re.search(r"amiberry .*--autoload", line)]
|
||||
if not autoload:
|
||||
raise script.missing("WHDLoad boot with --autoload")
|
||||
content = (
|
||||
"content not booted with --autoload, a WHDLoad .lha or .zip "
|
||||
f"({posixpath.basename(script.path)}:{', '.join(map(str, autoload))})"
|
||||
)
|
||||
records = []
|
||||
for config, condition in (
|
||||
(then.group(1), f"game name matches {test.group(1)}"),
|
||||
@@ -290,7 +354,8 @@ def amiberry(tree: RepoTree) -> list[Launcher]:
|
||||
raise LauncherPatternMissing(path, f"key naming a file under {sed.group(1)}")
|
||||
value, lines = fixed_paths(found, keys, path)
|
||||
slot = re.fullmatch(r"Amiga(\w+)-default\.uae", config)
|
||||
records.append(
|
||||
records.append(with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator="amiberry",
|
||||
build="standalone",
|
||||
@@ -300,9 +365,13 @@ def amiberry(tree: RepoTree) -> list[Launcher]:
|
||||
slot=slot.group(1) if slot else config,
|
||||
search_dir=value.search_dir,
|
||||
passes_to=f"{describe_keys(config, value.keys)} (amiberry -f)",
|
||||
depends_on_option=condition,
|
||||
)
|
||||
)
|
||||
depends_on_option=f"{condition}, {content}",
|
||||
),
|
||||
target,
|
||||
_keys(value),
|
||||
script,
|
||||
source_name=config,
|
||||
))
|
||||
mk = Script(f"{package}/package.mk", tree.read(f"{package}/package.mk"))
|
||||
links = mk.links(BIOS_ROOT, fixed={"INSTALL": ""})
|
||||
if not links:
|
||||
@@ -375,7 +444,11 @@ def hatari(tree: RepoTree) -> list[Launcher]:
|
||||
if not keys:
|
||||
raise LauncherPatternMissing(path, f"key naming a file under {BIOS_ROOT}")
|
||||
value, lines = fixed_paths(found, keys, path)
|
||||
return [
|
||||
copied = re.search(r'"?(\$\{?\w+\}?)"?\s*$', script.lines[copy_line - 1])
|
||||
if copied is None:
|
||||
raise script.missing("destination of the default config copy")
|
||||
return [with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator="hatari",
|
||||
build="standalone",
|
||||
@@ -384,8 +457,12 @@ def hatari(tree: RepoTree) -> list[Launcher]:
|
||||
source_ref=source_ref([(path, lines), (script.path, {copy_line, run_line})]),
|
||||
search_dir=value.search_dir,
|
||||
passes_to=f"{describe_keys(copy.group(1), value.keys)} (--configfile)",
|
||||
)
|
||||
]
|
||||
),
|
||||
script.expand(copied.group(1), copy_line, set()),
|
||||
_keys(value),
|
||||
script,
|
||||
source_name=copy.group(1),
|
||||
)]
|
||||
|
||||
|
||||
def melonds(tree: RepoTree) -> list[Launcher]:
|
||||
@@ -406,7 +483,22 @@ def melonds(tree: RepoTree) -> list[Launcher]:
|
||||
rf"^\s*{test.group(1)}=\$\(get_setting (\w+) ", f"setting read into {test.group(1)}"
|
||||
)
|
||||
condition = f"{setting.group(1)} = {test.group(2)} sets ExternalBIOSEnable=1, otherwise 0"
|
||||
records = config_records(tree, "melonds", package, "melonDS.ini", depends_on_option=condition)
|
||||
configs = [c.path for c in device_configs(tree, package, "melonDS.ini")]
|
||||
# melonDS opens the DSi BIOS and firmware keys only under
|
||||
# DSiExternalBIOSEnable, off unless a config sets it.
|
||||
dsi_external = any(
|
||||
s.key == "DSiExternalBIOSEnable" and s.value not in ("", "0")
|
||||
for path in configs for s in settings(tree.read(path))
|
||||
)
|
||||
|
||||
def unread(key: tuple[str, str]) -> bool:
|
||||
return not dsi_external and key[1] in ("DSiBIOS9Path", "DSiBIOS7Path", "DSiFirmwarePath")
|
||||
|
||||
conf_line, conf = script.find(r'^\s*CONF_DIR="([^"]+)"', "CONF_DIR")
|
||||
records = config_records(
|
||||
tree, "melonds", package, "melonDS.ini", depends_on_option=condition,
|
||||
target=f"{conf.group(1)}/melonDS.ini", start=script, unread=unread,
|
||||
)
|
||||
for record in records:
|
||||
record.source_ref += (
|
||||
f", {source_ref([(script.path, {setting_line, test_line, enable_line})])}"
|
||||
@@ -420,7 +512,10 @@ def dsperate(tree: RepoTree) -> list[Launcher]:
|
||||
f"{package}/scripts/start_dsperate.sh", tree.read(f"{package}/scripts/start_dsperate.sh")
|
||||
)
|
||||
run_line, _ = script.find(r"/usr/bin/dsperate --config ", "dsperate --config")
|
||||
records = config_records(tree, "dsperate", package, "dsperate.ini", " (--config)")
|
||||
records = config_records(
|
||||
tree, "dsperate", package, "dsperate.ini", " (--config)",
|
||||
target=script.expand("${DSPERATE_INI}", run_line, set()), start=script,
|
||||
)
|
||||
for record in records:
|
||||
record.source_ref += f", {source_ref([(script.path, {run_line})])}"
|
||||
return records
|
||||
@@ -434,7 +529,10 @@ def xemu(tree: RepoTree) -> list[Launcher]:
|
||||
copy_line, _ = script.find(
|
||||
r'cp -r "\$\{SOURCE_DIR\}/\$\{XEMU_INI\}"', "xemu.toml copy at launch"
|
||||
)
|
||||
records = config_records(tree, "xemu", package, "xemu.toml", " (copied at each launch)")
|
||||
records = config_records(
|
||||
tree, "xemu", package, "xemu.toml", " (copied at each launch)",
|
||||
target=script.expand("${CONF_DIR}/${XEMU_INI}", copy_line, set()), start=script,
|
||||
)
|
||||
for record in records:
|
||||
record.source_ref += f", {source_ref([(script.path, {copy_line})])}"
|
||||
return records
|
||||
@@ -452,7 +550,9 @@ def nanoboyadvance(tree: RepoTree) -> list[Launcher]:
|
||||
mk_line, _ = Script(mk_path, tree.read(mk_path)).find(
|
||||
r"config/config\.toml", "config.toml install"
|
||||
)
|
||||
return [
|
||||
start_path = f"{package}/scripts/start_nanoboyadvance.sh"
|
||||
return [with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator="nanoboyadvance",
|
||||
build="standalone",
|
||||
@@ -461,8 +561,14 @@ def nanoboyadvance(tree: RepoTree) -> list[Launcher]:
|
||||
source_ref=source_ref([(path, lines), (mk_path, {mk_line})]),
|
||||
search_dir=value.search_dir,
|
||||
passes_to=describe_keys("config.toml", value.keys),
|
||||
)
|
||||
]
|
||||
# NanoBoyAdvance exits when its BIOS cannot be read
|
||||
# (src/platform/sdl/main.cpp:180-185 at the build ROCKNIX ships).
|
||||
fails_when_missing=True,
|
||||
),
|
||||
f"{CONFIG_ROOT}/nanoboyadvance/config.toml",
|
||||
_keys(value),
|
||||
Script(start_path, tree.read(start_path)),
|
||||
)]
|
||||
|
||||
|
||||
def mednafen(tree: RepoTree) -> list[Launcher]:
|
||||
@@ -486,7 +592,9 @@ def mednafen(tree: RepoTree) -> list[Launcher]:
|
||||
modules: dict[str, list[Setting]] = {}
|
||||
for setting in firmware:
|
||||
modules.setdefault(setting.key.split(".", 1)[0], []).append(setting)
|
||||
return [
|
||||
home = script.expand("${MEDNAFEN_HOME}", gen_line, set())
|
||||
return [with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator="mednafen",
|
||||
build="standalone",
|
||||
@@ -501,9 +609,12 @@ def mednafen(tree: RepoTree) -> list[Launcher]:
|
||||
slot=module,
|
||||
search_dir=folder.value,
|
||||
passes_to="mednafen.cfg " + ", ".join(s.key for s in group),
|
||||
)
|
||||
for module, group in modules.items()
|
||||
]
|
||||
),
|
||||
f"{home}/mednafen.cfg",
|
||||
[s.key for s in group],
|
||||
script,
|
||||
writers=("mednafen_gen_config.sh",),
|
||||
) for module, group in modules.items()]
|
||||
|
||||
|
||||
def yabasanshiro(tree: RepoTree) -> list[Launcher]:
|
||||
@@ -549,6 +660,8 @@ def directory_records(
|
||||
file: str,
|
||||
folder_key: tuple[str, str],
|
||||
file_keys: tuple[tuple[str, str], ...],
|
||||
target: str = "",
|
||||
start: str = "",
|
||||
) -> list[Launcher]:
|
||||
"""scans_dir records: the config hands a directory and leaves the file keys empty."""
|
||||
configs = device_configs(tree, package, file)
|
||||
@@ -568,7 +681,8 @@ def directory_records(
|
||||
records = []
|
||||
for device, folder, refs in per_device(tree, configs, f"{package}/package.mk", read):
|
||||
passes = f"{name} [{folder_key[0]}] {folder_key[1]} = {folder}, {unset} unset"
|
||||
records.append(
|
||||
records.append(with_evidence(
|
||||
tree,
|
||||
Launcher(
|
||||
emulator=emulator,
|
||||
build="standalone",
|
||||
@@ -578,8 +692,11 @@ def directory_records(
|
||||
search_dir=folder,
|
||||
passes_to=passes,
|
||||
device=device,
|
||||
)
|
||||
)
|
||||
),
|
||||
target,
|
||||
[f"[{s}] {k}" for s, k in (folder_key, *file_keys)],
|
||||
Script(start, tree.read(start)) if start else None,
|
||||
))
|
||||
return records
|
||||
|
||||
|
||||
@@ -591,6 +708,8 @@ def duckstation(tree: RepoTree) -> list[Launcher]:
|
||||
"settings.ini",
|
||||
("BIOS", "SearchDirectory"),
|
||||
(("BIOS", "PathNTSCU"), ("BIOS", "PathNTSCJ"), ("BIOS", "PathPAL")),
|
||||
f"{CONFIG_ROOT}/duckstation/settings.ini",
|
||||
f"{STANDALONE}/duckstation-sa/scripts/start_duckstation.sh",
|
||||
)
|
||||
|
||||
|
||||
@@ -602,6 +721,8 @@ def armsx2(tree: RepoTree) -> list[Launcher]:
|
||||
"ARMSX2/inis/PCSX2.ini",
|
||||
("Folders", "Bios"),
|
||||
(("Filenames", "BIOS"),),
|
||||
f"{CONFIG_ROOT}/ARMSX2/inis/PCSX2.ini",
|
||||
f"{STANDALONE}/armsx2-sa/scripts/start_armsx2.sh",
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -63,6 +63,48 @@ def source_ref(parts: Iterable[tuple[str, Iterable[int]]]) -> str:
|
||||
)
|
||||
|
||||
|
||||
# The files a platform ships as configuration: an emulator reads them, the
|
||||
# platform's code never runs them. Batocera's .yml lists and an EmuELEC .opt
|
||||
# only offer the values a menu option takes.
|
||||
_CONFIG_FILE = re.compile(
|
||||
r"\.(?:ini|cfg|conf|rc|rc_\w+|opt|bml|toml|uae|template|yml|yaml)$", re.IGNORECASE
|
||||
)
|
||||
_FEATURE_FILE = re.compile(r"(?:^|/)es_features[^/]*$|\.opt$", re.IGNORECASE)
|
||||
|
||||
|
||||
def split_ref(ref: str) -> list[str]:
|
||||
"""The parts of a source_ref, each "path:lines", a bare line span
|
||||
continuing the path before it."""
|
||||
parts: list[str] = []
|
||||
for part in (p.strip() for p in ref.split(", ")):
|
||||
if not part:
|
||||
continue
|
||||
if re.fullmatch(r"\d+(?:-\d+)?", part) and parts:
|
||||
parts[-1] += f", {part}"
|
||||
else:
|
||||
parts.append(part)
|
||||
return parts
|
||||
|
||||
|
||||
def ref_path(part: str) -> str:
|
||||
return part.rsplit(":", 1)[0] if re.search(r":\d", part) else part
|
||||
|
||||
|
||||
def config_ref(ref: str) -> list[str]:
|
||||
"""The parts of a source_ref that cite a config, option or feature file.
|
||||
|
||||
Such a part proves what the file says, never that an emulator reads it:
|
||||
melonDS.ini keys are written on ROCKNIX for a build that reads them only
|
||||
when another key is set.
|
||||
"""
|
||||
return [part for part in split_ref(ref) if _CONFIG_FILE.search(ref_path(part))]
|
||||
|
||||
|
||||
def is_feature_ref(part: str) -> bool:
|
||||
"""Whether a source_ref part cites a file that lists a menu option's values."""
|
||||
return bool(_FEATURE_FILE.search(ref_path(part)))
|
||||
|
||||
|
||||
@dataclass
|
||||
class Word:
|
||||
"""A shell word: as written, and with quotes removed."""
|
||||
@@ -394,6 +436,149 @@ def _merge_links(links: list[Link]) -> list[Link]:
|
||||
return [link for link in merged if id(link) not in folded]
|
||||
|
||||
|
||||
_COPY = re.compile(r"(?:^|[\s;&|(])(cp|rsync|install|mv)\s")
|
||||
_GUARD = re.compile(r"\[\[?\s*!\s+-[fde]\s+(\S+)\s*\]")
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConfigPlacement:
|
||||
"""How a start script puts a config where the emulator reads it.
|
||||
|
||||
``install`` are the lines copying it there, ``kept_if_present`` whether
|
||||
every such copy runs only when the file (or its folder) is absent, and
|
||||
``overrides`` the sed lines rewriting one of the record's keys in it.
|
||||
"""
|
||||
|
||||
script: str
|
||||
path: str
|
||||
install: set[int]
|
||||
kept_if_present: bool
|
||||
overrides: set[int]
|
||||
|
||||
|
||||
def _bare_key(key: str) -> str:
|
||||
return key.rsplit("] ", 1)[-1].rsplit("/", 1)[-1].strip()
|
||||
|
||||
|
||||
def _guarded(script: Script, number: int, target: str) -> bool:
|
||||
"""Whether a line runs only when target, or a folder above it, is absent."""
|
||||
|
||||
def covers(found: re.Match[str], at: int) -> bool:
|
||||
guarded = script.expand(words(found.group(1))[0].text, at, set()).rstrip("/")
|
||||
return target == guarded or target.startswith(guarded + "/")
|
||||
|
||||
line = script.lines[number - 1]
|
||||
if any(covers(m, number) for m in _GUARD.finditer(line)):
|
||||
return True
|
||||
depth = 0
|
||||
for at in range(number - 1, 0, -1):
|
||||
text = script.lines[at - 1].strip()
|
||||
if re.match(r"fi\b", text):
|
||||
depth += 1
|
||||
elif re.match(r"if\b", text):
|
||||
if depth:
|
||||
depth -= 1
|
||||
continue
|
||||
return any(covers(m, at) for m in _GUARD.finditer(text))
|
||||
return False
|
||||
|
||||
|
||||
def config_placement(
|
||||
script: Script,
|
||||
target: str,
|
||||
keys: Iterable[str] = (),
|
||||
writers: Iterable[str] = (),
|
||||
source_name: str = "",
|
||||
required: bool = True,
|
||||
sources: tuple[str, ...] = (),
|
||||
) -> ConfigPlacement:
|
||||
"""The lines of a start script that install ``target`` and rewrite its keys.
|
||||
|
||||
A copy installs the target when its destination is the file or a folder
|
||||
above it. ``writers`` are other commands that write the file (ROCKNIX
|
||||
generates mednafen.cfg with mednafen_gen_config.sh). A copy guarded by
|
||||
`[ ! -f X ]` or `[ ! -d X ]` on the target or a folder above it, or made
|
||||
with cp -n or rsync --ignore-existing, leaves a file already there.
|
||||
"""
|
||||
install: set[int] = set()
|
||||
kept = True
|
||||
overrides: set[int] = set()
|
||||
bare = {_bare_key(k) for k in keys} - {""}
|
||||
writer = re.compile("|".join(re.escape(w) for w in writers)) if writers else None
|
||||
for number, line in script.code():
|
||||
if (copy := _COPY.search(line)) or (writer and writer.search(line)):
|
||||
if copy:
|
||||
args = []
|
||||
for word in words(line[copy.start(1):])[1:]:
|
||||
# The command ends at a separator or a redirection.
|
||||
if word.raw in {";", "&&", "||", "|"} or re.match(r"\d*>", word.raw):
|
||||
break
|
||||
args.append(word.text)
|
||||
operands = [a for a in args if not a.startswith("-")]
|
||||
if not operands:
|
||||
continue
|
||||
destination = script.expand(operands[-1], number, set()).rstrip("/")
|
||||
source = script.expand(operands[0], number, set()).rstrip("/")
|
||||
hits = target == destination or target.startswith(destination + "/") or (
|
||||
target.startswith(f"{destination}/{source.rsplit('/', 1)[-1]}")
|
||||
)
|
||||
# A copy of another file into the same place is another
|
||||
# record's: amiberry copies the A500 or the A1200 setup.
|
||||
named = source.rsplit("/", 1)[-1]
|
||||
if not hits or (source_name and "." in named and named != source_name):
|
||||
continue
|
||||
# A named file copied into a folder above the target is
|
||||
# another file of that folder (ARMSX2's secrets.ini).
|
||||
if (
|
||||
not source_name and "." in named and "*" not in named
|
||||
and destination != target and named != target.rsplit("/", 1)[-1]
|
||||
):
|
||||
continue
|
||||
if sources and not source.startswith(sources):
|
||||
continue
|
||||
skip = "-n" in args or "--ignore-existing" in args
|
||||
else:
|
||||
skip = False
|
||||
install.add(number)
|
||||
if not (skip or _guarded(script, number, target)):
|
||||
kept = False
|
||||
elif re.search(r"\bsed\b.*\s-i\b|\bsed -i", line) and bare:
|
||||
expanded = script.expand(line, number, set())
|
||||
if target in expanded or target.rsplit("/", 1)[-1] in expanded:
|
||||
if any(re.search(rf"\b{re.escape(k)}\b", expanded) for k in bare):
|
||||
overrides.add(number)
|
||||
if not install and required:
|
||||
raise script.missing(f"install of {target}")
|
||||
return ConfigPlacement(script.path, target, install, kept, overrides)
|
||||
|
||||
|
||||
def evidence_fields(
|
||||
placements: Iterable[ConfigPlacement],
|
||||
installed: Iterable[tuple[str, Iterable[int]]] = (),
|
||||
) -> dict:
|
||||
"""The installs, kept_if_present and overrides fields of a config record.
|
||||
|
||||
``placements`` are the steps that put the file in place, in the order
|
||||
they run (a first-boot copy, then the start script). ``installed`` are
|
||||
the build steps that put it where they copy it from (a package.mk copy
|
||||
into /usr/config).
|
||||
"""
|
||||
placements = list(placements)
|
||||
steps = [p for p in placements if p.install]
|
||||
if not steps:
|
||||
raise LauncherPatternMissing(placements[0].path if placements else "", "install")
|
||||
return {
|
||||
"installs": {
|
||||
"path": steps[-1].path,
|
||||
"source_ref": source_ref([*installed, *((p.script, p.install) for p in steps)]),
|
||||
},
|
||||
"kept_if_present": all(p.kept_if_present for p in steps),
|
||||
"overrides": [
|
||||
source_ref([(p.script, {line})]) for p in placements for line in sorted(p.overrides)
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Setting:
|
||||
section: str
|
||||
|
||||
@@ -81,7 +81,10 @@ def _validate_yaml_directory(
|
||||
continue
|
||||
out.extend(_errors(validator, data, str(path.relative_to(ROOT))))
|
||||
out.extend(_unreachable_citations(path, data))
|
||||
if schema_name == "platform.schema.json":
|
||||
out.extend(_config_records_without_evidence(path, data))
|
||||
if schema_name == "emulator.schema.json":
|
||||
out.extend(_config_reads_without_build(path, data))
|
||||
out.extend(_checks_without_values(path, data))
|
||||
out.extend(_save_dir_without_library_name(path, data))
|
||||
out.extend(_systems_outside_profile(path, data))
|
||||
@@ -102,6 +105,59 @@ _CHECK_FIELDS = {
|
||||
}
|
||||
|
||||
|
||||
def _config_records_without_evidence(path: Path, document: object) -> list[str]:
|
||||
"""A launcher record citing a config without the links its extractor reads.
|
||||
|
||||
A config file is proof only when the code installing it and the code
|
||||
reading it are shown (launchers.config_evidence). The platform's half
|
||||
is the extractor's to write: a record citing a shipped config carries
|
||||
installs and overrides, and a feature or option file is never a
|
||||
record's source, only its choices_from.
|
||||
"""
|
||||
if not isinstance(document, dict):
|
||||
return []
|
||||
from scraper.shell_launchers import config_ref, is_feature_ref # noqa: PLC0415
|
||||
|
||||
out: list[str] = []
|
||||
for index, record in enumerate(document.get("launchers") or []):
|
||||
if not isinstance(record, dict):
|
||||
continue
|
||||
cited = config_ref(str(record.get("source_ref") or ""))
|
||||
where = f"{path.relative_to(ROOT)}: launchers[{index}] ({record.get('emulator')})"
|
||||
features = [part for part in cited if is_feature_ref(part)]
|
||||
if features:
|
||||
out.append(f"{where} cites {features[0]} as source, choices_from holds it")
|
||||
if [part for part in cited if not is_feature_ref(part)] and not (
|
||||
record.get("installs") and "overrides" in record
|
||||
):
|
||||
out.append(f"{where} cites a config without installs and overrides")
|
||||
return out
|
||||
|
||||
|
||||
def _config_reads_without_build(path: Path, document: object) -> list[str]:
|
||||
"""A config_reads entry naming a platform the profile gives no pin_build.
|
||||
|
||||
Such an entry is read at the build that platform ships, and pin_build is
|
||||
where that build is named.
|
||||
"""
|
||||
if not isinstance(document, dict):
|
||||
return []
|
||||
builds = {str(b.get("platform")) for b in document.get("pin_build") or []}
|
||||
out: list[str] = []
|
||||
for index, read in enumerate(document.get("config_reads") or []):
|
||||
if not isinstance(read, dict):
|
||||
continue
|
||||
if read.get("revision"):
|
||||
continue
|
||||
for platform in read.get("platforms") or []:
|
||||
if str(platform) not in builds:
|
||||
out.append(
|
||||
f"{path.relative_to(ROOT)}: config_reads[{index}] ({read.get('file')}) "
|
||||
f"names {platform}, which has no pin_build"
|
||||
)
|
||||
return out
|
||||
|
||||
|
||||
def _systems_outside_profile(path: Path, document: object) -> list[str]:
|
||||
"""An entry's system: or systems: naming a system its profile does not list.
|
||||
|
||||
|
||||
+19
-1
@@ -100,7 +100,7 @@ from common import (
|
||||
|
||||
yaml = require_yaml()
|
||||
from exporter.candidates import BIOS, EntryCategories
|
||||
from launchers import LauncherLayer, declared_destinations, held_record
|
||||
from launchers import LauncherLayer, declared_destinations, held_record, launcher_unproven
|
||||
from cross_reference import launcher_reads_not_held
|
||||
from nativemode import (
|
||||
SIZE_AND_ANY_HASH,
|
||||
@@ -1764,6 +1764,8 @@ def verify_platform(
|
||||
"launcher_reads_not_held": launcher_reads_not_held(
|
||||
{config.get("_key", platform): config}, db, profiles, data_dir_registry
|
||||
),
|
||||
# Records a config file does not prove: listed, never consumed.
|
||||
"launcher_unproven": launcher_unproven({config.get("_key", platform): config}, profiles),
|
||||
"exclusion_notes": exclusions,
|
||||
"region_fallbacks": sorted(region_fallbacks),
|
||||
**({"left_out": left_out} if no_game_data else {}),
|
||||
@@ -2130,6 +2132,21 @@ def _print_undeclared_section(result: dict, verbose: bool) -> None:
|
||||
)
|
||||
|
||||
|
||||
def _print_launcher_unproven(result: dict, verbose: bool) -> None:
|
||||
"""Launcher records resting on a config file the code does not prove."""
|
||||
rows = result.get("launcher_unproven") or []
|
||||
if not rows:
|
||||
return
|
||||
listed = "" if verbose else " (--verbose lists them)"
|
||||
print(f" Launcher records unproven: {len(rows)}{listed}")
|
||||
if not verbose:
|
||||
return
|
||||
for row in rows:
|
||||
print(f" [{row['index']}] {row['emulator']} {row['kind']}: {row['passes_to']}")
|
||||
for link in row["missing"]:
|
||||
print(f" missing {link}")
|
||||
|
||||
|
||||
def _print_launcher_reads(result: dict, verbose: bool) -> None:
|
||||
"""Names the platform's launch code reads that the collection lacks."""
|
||||
every = result.get("launcher_reads_not_held") or []
|
||||
@@ -2220,6 +2237,7 @@ def print_platform_result(
|
||||
_print_detail_entries(result["details"], seen_details, verbose)
|
||||
_print_undeclared_section(result, verbose)
|
||||
_print_launcher_reads(result, verbose)
|
||||
_print_launcher_unproven(result, verbose)
|
||||
|
||||
# The same notes come back for every platform running these cores and
|
||||
# filled 985 of the 1114 lines of verify --all: counted, listed on ask.
|
||||
|
||||
@@ -0,0 +1,330 @@
|
||||
"""A launcher record resting on a config file binds only when its chain holds.
|
||||
|
||||
The platform's code installs the file (installs), its launch code was read
|
||||
for what replaces it (overrides), and the emulator's profile says where the
|
||||
build the platform ships loads the file and reads each key (config_reads).
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import tests # noqa: F401 offline, scratch under tmp/, the suite's own cache
|
||||
|
||||
import sys
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "scripts"))
|
||||
|
||||
import yaml # noqa: E402
|
||||
|
||||
from common import load_platform_config # noqa: E402
|
||||
from launchers import ( # noqa: E402
|
||||
bound_launchers,
|
||||
config_evidence,
|
||||
config_target,
|
||||
handed_directories,
|
||||
launcher_places,
|
||||
launcher_unproven,
|
||||
)
|
||||
from profile_sync import _check_build_refs, shipped_build_holders # noqa: E402
|
||||
from scraper.retrobat_launchers import _choices_apart # noqa: E402
|
||||
from scraper.shell_launchers import ( # noqa: E402
|
||||
LauncherPatternMissing,
|
||||
Script,
|
||||
config_placement,
|
||||
config_ref,
|
||||
is_feature_ref,
|
||||
)
|
||||
from validate_schemas import ( # noqa: E402
|
||||
_config_reads_without_build,
|
||||
_config_records_without_evidence,
|
||||
)
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def record(**fields: object) -> dict:
|
||||
"""A ROCKNIX-like DuckStation record citing its shipped settings.ini."""
|
||||
base = {
|
||||
"emulator": "duck", "build": "standalone", "kind": "scans_dir", "names": [],
|
||||
"search_dir": "/storage/roms/bios",
|
||||
"passes_to": "settings.ini [BIOS] SearchDirectory = /storage/roms/bios, [BIOS] PathPAL unset",
|
||||
"installs": {"path": "/storage/.config/duck/settings.ini", "source_ref": "setup.sh:13"},
|
||||
"overrides": [],
|
||||
"source_ref": "duck/config/settings.ini:4, duck/package.mk:33",
|
||||
}
|
||||
return {**base, **fields}
|
||||
|
||||
|
||||
def profile(**fields: object) -> dict:
|
||||
base = {
|
||||
"emulator": "Duck", "type": "standalone", "cores": ["duck"],
|
||||
"standalone_directories": ["[BIOS] SearchDirectory"],
|
||||
"config_reads": [{
|
||||
"file": "settings.ini", "source_ref": "src/core.cpp:10",
|
||||
"keys": [
|
||||
{"key": "[BIOS] SearchDirectory", "source_ref": "src/settings.cpp:20"},
|
||||
{"key": ["[BIOS] PathPAL", "[BIOS] PathNTSCU"], "source_ref": "src/bios.cpp:30"},
|
||||
],
|
||||
}],
|
||||
}
|
||||
return {**base, **fields}
|
||||
|
||||
|
||||
class ConfigRefs(unittest.TestCase):
|
||||
def test_config_option_and_feature_files_are_cited_apart(self) -> None:
|
||||
ref = "a/settings.ini:4, 6, a/start.sh:3, b/MAME.opt:19, .emulationstation/es_features.cfg:9"
|
||||
self.assertEqual(
|
||||
config_ref(ref),
|
||||
["a/settings.ini:4, 6", "b/MAME.opt:19", ".emulationstation/es_features.cfg:9"],
|
||||
)
|
||||
self.assertEqual([is_feature_ref(p) for p in config_ref(ref)], [False, True, True])
|
||||
|
||||
def test_passes_to_names_the_file_and_its_keys(self) -> None:
|
||||
cases = {
|
||||
"settings.ini [BIOS] SearchDirectory (-settings), [BIOS] PathNTSCU, PathPAL unset":
|
||||
("settings.ini", ["[BIOS] SearchDirectory", "[BIOS] PathNTSCU", "[BIOS] PathPAL"]),
|
||||
"melonDS.toml [DS] BIOS9Path [DSi] NANDPath, first file whose name holds the region":
|
||||
("melonDS.toml", ["[DS] BIOS9Path", "[DSi] NANDPath"]),
|
||||
"settings.ini [BIOS] PathNTSCJ = PathNTSCU = <value>":
|
||||
("settings.ini", ["[BIOS] PathNTSCJ", "[BIOS] PathNTSCU"]),
|
||||
"AmigaA500-default.uae kickstart_rom_file, $(FILE_PATH) = /storage/k/":
|
||||
("AmigaA500-default.uae", ["kickstart_rom_file", "$(FILE_PATH)"]),
|
||||
"command line -rompath bios/coco": ("command line", ["-rompath"]),
|
||||
"core option pcsx2_bios": ("core options", ["pcsx2_bios"]),
|
||||
}
|
||||
for passes_to, expected in cases.items():
|
||||
with self.subTest(passes_to=passes_to):
|
||||
self.assertEqual(config_target({"passes_to": passes_to}), expected)
|
||||
core = {"build": "libretro", "kind": "core_option", "passes_to": "hatarib_tos = x/<value>"}
|
||||
self.assertEqual(config_target(core), ("core options", ["hatarib_tos"]))
|
||||
|
||||
def test_a_record_naming_no_file_takes_the_config_it_installs(self) -> None:
|
||||
romlist = record(
|
||||
passes_to="romlist coco",
|
||||
installs={"path": "$xroar_config", "source_ref": "prepare.sh:13"},
|
||||
source_ref="xroar/rd_config/xroar.conf:305, xroar/prepare.sh:13",
|
||||
)
|
||||
self.assertEqual(config_target(romlist), ("xroar.conf", ["romlist coco"]))
|
||||
|
||||
|
||||
class Evidence(unittest.TestCase):
|
||||
profiles = {"duck": profile()}
|
||||
|
||||
def test_a_record_resting_on_code_holds(self) -> None:
|
||||
code = {"emulator": "duck", "kind": "fixed_name", "source_ref": "start.sh:3"}
|
||||
self.assertTrue(config_evidence(code, {}).proven)
|
||||
|
||||
def test_the_whole_chain_holds(self) -> None:
|
||||
evidence = config_evidence(record(), self.profiles, "rocknix")
|
||||
self.assertTrue(evidence.proven, evidence.missing)
|
||||
self.assertEqual(evidence.readers, ("duck",))
|
||||
|
||||
def test_each_missing_link_is_named(self) -> None:
|
||||
bare = {k: v for k, v in record().items() if k not in ("installs", "overrides")}
|
||||
missing = config_evidence(bare, self.profiles).missing
|
||||
self.assertEqual(len(missing), 2)
|
||||
self.assertTrue(missing[0].startswith("installs"))
|
||||
self.assertTrue(missing[1].startswith("overrides"))
|
||||
|
||||
def test_a_profile_that_reads_no_such_file_proves_nothing(self) -> None:
|
||||
missing = config_evidence(record(), {"duck": profile(config_reads=[])}).missing
|
||||
self.assertEqual(missing, ("config_reads: an emulator that loads settings.ini",))
|
||||
|
||||
def test_a_key_the_build_does_not_read_is_named(self) -> None:
|
||||
unread = record(passes_to="settings.ini [BIOS] PathNTSCJ")
|
||||
self.assertEqual(
|
||||
config_evidence(unread, self.profiles).missing,
|
||||
("config_reads: no read of [BIOS] PathNTSCJ",),
|
||||
)
|
||||
|
||||
def test_a_handle_with_its_code_ref_reads_the_key(self) -> None:
|
||||
handled = profile(
|
||||
config_reads=[{"file": "settings.ini", "source_ref": "src/core.cpp:10", "keys": [
|
||||
{"key": "[BIOS] PathPAL", "source_ref": "src/bios.cpp:30"}]}],
|
||||
standalone_directories=[
|
||||
{"handle": "[BIOS] SearchDirectory", "source_ref": "src/settings.cpp:20"}
|
||||
],
|
||||
)
|
||||
self.assertTrue(config_evidence(record(), {"duck": handled}).proven)
|
||||
|
||||
def test_an_option_list_is_never_the_source(self) -> None:
|
||||
listed = record(source_ref="gen.cs:3, .emulationstation/es_features.cfg:9")
|
||||
self.assertIn(
|
||||
"an option list cited as source, not as choices_from",
|
||||
config_evidence(listed, self.profiles).missing,
|
||||
)
|
||||
|
||||
def test_an_option_choice_needs_the_emulator_side_too(self) -> None:
|
||||
chosen = {
|
||||
"emulator": "duck", "kind": "core_option", "passes_to": "settings.ini [BIOS] PathPAL = <value>",
|
||||
"choices_from": "es_features.cfg:9", "source_ref": "gen.cs:3",
|
||||
}
|
||||
self.assertTrue(config_evidence(chosen, self.profiles).proven)
|
||||
self.assertFalse(config_evidence(chosen, {"duck": profile(config_reads=[])}).proven)
|
||||
|
||||
def test_reads_written_for_a_shipped_build_apply_to_its_platform_only(self) -> None:
|
||||
built = profile(
|
||||
source_commit="a" * 40,
|
||||
pin_build=[{"platform": "rocknix", "value": "b" * 40}],
|
||||
config_reads=[{**profile()["config_reads"][0], "platforms": ["rocknix"]}],
|
||||
)
|
||||
self.assertTrue(config_evidence(record(), {"duck": built}, "rocknix").proven)
|
||||
self.assertFalse(config_evidence(record(), {"duck": built}, "emuelec").proven)
|
||||
|
||||
def test_reads_at_the_pin_skip_a_platform_shipping_another_build(self) -> None:
|
||||
other = profile(source_commit="a" * 40, pin_build=[{"platform": "rocknix", "value": "b" * 40}])
|
||||
self.assertFalse(config_evidence(record(), {"duck": other}, "rocknix").proven)
|
||||
self.assertTrue(config_evidence(record(), {"duck": other}, "emuelec").proven)
|
||||
|
||||
|
||||
class Gate(unittest.TestCase):
|
||||
def config(self, *records: dict) -> dict:
|
||||
return {"_key": "rocknix", "base_destination": "bios", "launchers": list(records)}
|
||||
|
||||
def test_an_unproven_record_hands_no_directory(self) -> None:
|
||||
proven = handed_directories(self.config(record()), {"duck": profile()})
|
||||
self.assertEqual([h.folder for h in proven], [""])
|
||||
self.assertEqual(handed_directories(self.config(record()), {"duck": profile(config_reads=[])}), [])
|
||||
|
||||
def test_an_unproven_record_places_no_file(self) -> None:
|
||||
named = record(
|
||||
kind="fixed_name", names=["tos.img"], passes_to="settings.ini [BIOS] PathPAL",
|
||||
)
|
||||
self.assertEqual(len(launcher_places(self.config(named), {"duck": profile()})), 1)
|
||||
self.assertEqual(launcher_places(self.config(named), {"duck": profile(config_reads=[])}), [])
|
||||
|
||||
def test_the_unproven_are_reported_with_what_they_lack(self) -> None:
|
||||
config = self.config({"emulator": "x", "kind": "links", "source_ref": "a.sh:1"}, record())
|
||||
self.assertEqual(launcher_unproven({"rocknix": config}, {"duck": profile()}), [])
|
||||
(row,) = launcher_unproven({"rocknix": config}, {"duck": profile(config_reads=[])})
|
||||
self.assertEqual((row["platform"], row["index"], row["emulator"]), ("rocknix", 1, "duck"))
|
||||
self.assertEqual(row["config"], ["duck/config/settings.ini:4"])
|
||||
self.assertEqual(len(bound_launchers(config, {"duck": profile(config_reads=[])})), 1)
|
||||
|
||||
|
||||
class StartScripts(unittest.TestCase):
|
||||
SCRIPT = (
|
||||
'CONF_DIR="/storage/.config/duck"\n'
|
||||
'CONF_FILE="${CONF_DIR}/settings.ini"\n'
|
||||
'[ ! -d "${CONF_DIR}" ] && cp -r /usr/config/duck /storage/.config\n'
|
||||
'if [ ! -f "${CONF_FILE}" ]; then\n'
|
||||
' cp /usr/config/duck/settings.ini ${CONF_FILE}\n'
|
||||
'fi\n'
|
||||
"sed -i '/^AspectRatio/c\\\\AspectRatio = 4:3' ${CONF_FILE}\n"
|
||||
"sed -i '/^PathPAL/c\\\\PathPAL = x.bin' ${CONF_FILE}\n"
|
||||
'cp /usr/config/duck/other.ini ${CONF_DIR}/ >/dev/null 2>&1\n'
|
||||
)
|
||||
|
||||
def test_a_guarded_copy_keeps_the_file_and_a_key_rewrite_is_an_override(self) -> None:
|
||||
placement = config_placement(
|
||||
Script("start.sh", self.SCRIPT), "/storage/.config/duck/settings.ini", ["[BIOS] PathPAL"]
|
||||
)
|
||||
self.assertEqual(placement.install, {3, 5})
|
||||
self.assertTrue(placement.kept_if_present)
|
||||
self.assertEqual(placement.overrides, {8})
|
||||
|
||||
def test_a_copy_at_each_launch_replaces_the_file(self) -> None:
|
||||
script = Script("start.sh", 'cp /usr/config/duck/settings.ini /storage/.config/duck/settings.ini\n')
|
||||
self.assertFalse(config_placement(script, "/storage/.config/duck/settings.ini").kept_if_present)
|
||||
|
||||
def test_a_script_installing_nothing_raises(self) -> None:
|
||||
with self.assertRaises(LauncherPatternMissing):
|
||||
config_placement(Script("start.sh", "echo hi\n"), "/storage/.config/duck/settings.ini")
|
||||
|
||||
def test_retrobat_moves_the_option_list_to_choices_from(self) -> None:
|
||||
moved = _choices_apart({
|
||||
"emulator": "x", "passes_to": "p",
|
||||
"source_ref": "Gen.cs:3-4, .emulationstation/es_features.cfg:9-12",
|
||||
})
|
||||
self.assertEqual(moved["source_ref"], "Gen.cs:3-4")
|
||||
self.assertEqual(moved["choices_from"], ".emulationstation/es_features.cfg:9-12")
|
||||
self.assertEqual(list(moved)[-1], "source_ref")
|
||||
|
||||
|
||||
class Invariants(unittest.TestCase):
|
||||
def test_a_config_record_without_its_platform_links_is_an_error(self) -> None:
|
||||
path = REPO_ROOT / "platforms" / "x.yml"
|
||||
bare = {k: v for k, v in record().items() if k not in ("installs", "overrides")}
|
||||
listed = record(source_ref="gen.cs:3, es_features.yml:9")
|
||||
errors = _config_records_without_evidence(path, {"launchers": [record(), bare, listed]})
|
||||
self.assertEqual(len(errors), 2)
|
||||
self.assertIn("without installs and overrides", errors[0])
|
||||
self.assertIn("choices_from holds it", errors[1])
|
||||
|
||||
def test_reads_naming_a_platform_need_its_build(self) -> None:
|
||||
path = REPO_ROOT / "emulators" / "x.yml"
|
||||
reads = [{"file": "a.ini", "platforms": ["rocknix"], "source_ref": "a:1", "keys": []}]
|
||||
self.assertEqual(len(_config_reads_without_build(path, {"config_reads": reads})), 1)
|
||||
self.assertEqual(_config_reads_without_build(
|
||||
path, {"config_reads": reads, "pin_build": [{"platform": "rocknix"}]}
|
||||
), [])
|
||||
pinned = [{**reads[0], "revision": "c" * 40, "revision_from": "the exe"}]
|
||||
self.assertEqual(_config_reads_without_build(path, {"config_reads": pinned}), [])
|
||||
|
||||
|
||||
class BuildRefs(unittest.TestCase):
|
||||
def test_reads_for_a_shipped_build_are_read_at_that_build(self) -> None:
|
||||
document = {
|
||||
"pin_build": [{"platform": "rocknix", "value": "b" * 40}],
|
||||
"config_reads": [{
|
||||
"file": "a.ini", "platforms": ["rocknix"], "source_ref": "src/a.c:2",
|
||||
"keys": [{"key": "k", "source_ref": "src/a.c:9, ROCKNIX x.patch:1"}],
|
||||
}],
|
||||
}
|
||||
held = shipped_build_holders(document)
|
||||
self.assertEqual(len(held), 2)
|
||||
|
||||
class View:
|
||||
repo, field = "repo", "source"
|
||||
|
||||
class Citation:
|
||||
def __init__(self, ref: str, field: str) -> None:
|
||||
self.ref, self.field = ref, field
|
||||
|
||||
asked: list[tuple[str, str]] = []
|
||||
|
||||
def fetch(_repo: str, revision: str, path: str) -> list[str] | None:
|
||||
asked.append((revision, path))
|
||||
return ["line"] * 5 if path == "src/a.c" else None
|
||||
|
||||
rows = _check_build_refs(
|
||||
document,
|
||||
[(Citation("src/a.c:2", "c"), document["config_reads"][0]),
|
||||
(Citation("src/a.c:9, ROCKNIX x.patch:1", "k"), document["config_reads"][0])],
|
||||
[View()], fetch,
|
||||
)
|
||||
self.assertEqual([r["status"] for r in rows], ["BUILD_OK", "BUILD_GONE"])
|
||||
self.assertTrue(all(revision == "b" * 40 for revision, _ in asked))
|
||||
self.assertNotIn(("b" * 40, "ROCKNIX x.patch"), asked)
|
||||
|
||||
|
||||
class RepositoryRecords(unittest.TestCase):
|
||||
"""The placement chains the audit of 2026-11-10 found moving files."""
|
||||
|
||||
def test_the_chains_that_move_placements_still_bind(self) -> None:
|
||||
platforms = REPO_ROOT / "platforms"
|
||||
cases = (
|
||||
("rocknix", "armsx2", "/storage/roms/bios/armsx2"),
|
||||
("retrodeck", "gzdoom", "$roms_path/doom"),
|
||||
("retrodeck", "xroar", "$roms_path/coco"),
|
||||
("retrobat", "xroar", "bios/coco"),
|
||||
)
|
||||
for platform, emulator, directory in cases:
|
||||
with self.subTest(platform=platform, emulator=emulator):
|
||||
handed = handed_directories(load_platform_config(platform, str(platforms)))
|
||||
self.assertIn(
|
||||
directory, {h.directory for h in handed if h.emulator == emulator}
|
||||
)
|
||||
|
||||
def test_every_config_record_carries_its_platform_links(self) -> None:
|
||||
for path in sorted((REPO_ROOT / "platforms").glob("*.yml")):
|
||||
if path.name.startswith("_"):
|
||||
continue
|
||||
with self.subTest(platform=path.stem):
|
||||
document = yaml.safe_load(path.read_text(encoding="utf-8"))
|
||||
self.assertEqual(_config_records_without_evidence(path, document), [])
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
@@ -33,6 +33,7 @@ import verify # noqa: E402
|
||||
from common import _emulator_profiles_cache, load_emulator_profiles, load_platform_config # noqa: E402
|
||||
from cross_reference import ( # noqa: E402
|
||||
LAUNCHER_READS_KEY,
|
||||
LAUNCHER_UNPROVEN_KEY,
|
||||
launcher_file_names,
|
||||
launcher_reads_not_held,
|
||||
print_launcher_reads,
|
||||
@@ -278,7 +279,11 @@ class LauncherGapTest(unittest.TestCase):
|
||||
names = {r["name"] for r in report[LAUNCHER_READS_KEY]}
|
||||
self.assertEqual(names, {"absent.bin", "mixed.rom", "labelled.rom", "user.sf2"})
|
||||
# The emulator rows keep their own shape and counts.
|
||||
self.assertEqual(set(report) - {LAUNCHER_READS_KEY}, {"aliasemu", "missemu", "setemu"})
|
||||
self.assertEqual(
|
||||
set(report) - {LAUNCHER_READS_KEY, LAUNCHER_UNPROVEN_KEY},
|
||||
{"aliasemu", "missemu", "setemu"},
|
||||
)
|
||||
self.assertEqual(report[LAUNCHER_UNPROVEN_KEY], [])
|
||||
|
||||
def test_verify_counts_and_exit_code_are_unchanged(self) -> None:
|
||||
"""A launcher name is reported, not judged: nothing else moves."""
|
||||
|
||||
@@ -314,9 +314,9 @@ class LauncherLayerTest(unittest.TestCase):
|
||||
config = {"base_destination": "bios", "launchers": [{
|
||||
"emulator": "e", "build": "libretro", "kind": "fixed_name",
|
||||
"names": ["a.rom", "b.rom"], "search_dir": "/storage/roms/bios",
|
||||
"passes_to": "e.cfg ROM_A, ROM_B", "source_ref": "e.cfg:1",
|
||||
"passes_to": "e.cfg ROM_A, ROM_B", "source_ref": "launch.sh:1",
|
||||
}]}
|
||||
places = {p.paths[0]: p.passes_to for p in launcher_places(config)}
|
||||
places = {p.paths[0]: p.passes_to for p in launcher_places(config, {})}
|
||||
self.assertEqual(places, {"a.rom": "e.cfg ROM_A", "b.rom": "e.cfg ROM_B"})
|
||||
|
||||
def test_a_core_option_names_the_dump_of_a_model(self) -> None:
|
||||
@@ -341,12 +341,16 @@ class LauncherLayerTest(unittest.TestCase):
|
||||
"files": [{"name": "<bios>.bin", "path": "ps2/bios/<bios>.bin", "required": True,
|
||||
"min_size": 32, "max_size": 64, "validation": ["size"],
|
||||
"config_key": "emu_bios"}],
|
||||
"config_reads": [{"file": "core options", "source_ref": "core.c:1",
|
||||
"keys": [{"key": "emu_bios", "source_ref": "core.c:2"}]}],
|
||||
}
|
||||
with open(os.path.join(self.emulators_dir, "optemu.yml"), "w") as fh:
|
||||
yaml.dump(profile, fh)
|
||||
self.config["launchers"].append({
|
||||
"emulator": "retroarch", "build": "libretro", "kind": "core_option",
|
||||
"names": ["scph10000.bin"], "passes_to": "core option emu_bios",
|
||||
"installs": {"path": "retroarch-core-options.cfg", "source_ref": "prepare.sh:24"},
|
||||
"overrides": [],
|
||||
"source_ref": "core-options.cfg:515",
|
||||
})
|
||||
_emulator_profiles_cache.clear()
|
||||
|
||||
@@ -962,6 +962,17 @@ class GzdoomOnRetroDECK(unittest.TestCase):
|
||||
self.assertFalse(any(e.get("standalone_path") for e in view["files"]))
|
||||
|
||||
|
||||
def _reads_configs(profile: str) -> bool:
|
||||
"""Whether a repository profile carries config_reads."""
|
||||
path = REPO_ROOT / "emulators" / f"{profile}.yml"
|
||||
return bool((yaml.safe_load(path.read_text(encoding="utf-8")) or {}).get("config_reads"))
|
||||
|
||||
|
||||
# EmuELEC hands AdvanceMAME its folders through advmame.rc: the chain binds
|
||||
# once the profile says where the build reads them (config_reads).
|
||||
@unittest.skipUnless(
|
||||
_reads_configs("advancemame"), "advancemame.yml carries no config_reads, dir_rom is unproven"
|
||||
)
|
||||
class AdvanceMameOnEmuELEC(unittest.TestCase):
|
||||
"""advmame.rc sets dir_rom /storage/roms/mame, /storage/roms/arcade for
|
||||
the arcade system (advmame.rc:11, advmame.sh:26-30)."""
|
||||
|
||||
@@ -105,22 +105,6 @@ HATARI_CFG = text(
|
||||
"""
|
||||
)
|
||||
|
||||
ATARI800_CFG = text(
|
||||
"""
|
||||
Atari 800 Emulator, Version 3.1.0
|
||||
ROM_OS_A_NTSC=
|
||||
ROM_OS_A_PAL=/storage/roms/bios/ATARIOSA.ROM
|
||||
ROM_5200=/storage/roms/bios/5200.rom
|
||||
"""
|
||||
)
|
||||
|
||||
ATARI800_PATCH = text(
|
||||
"""
|
||||
+ LDFLAGS += -static-libgcc
|
||||
+ CFLAGS += -DDEFAULT_CFG_NAME="\\"/storage/.config/distribution/configs/atari800.cfg\\""
|
||||
"""
|
||||
)
|
||||
|
||||
AMIBERRY_MK = text(
|
||||
"""
|
||||
makeinstall_target() {
|
||||
@@ -141,6 +125,17 @@ AMIBERRY_SH = text(
|
||||
cp $AMIBERRY_CONFIG_DIR/AmigaA500-default.uae "$AMIBERRY_TMP_CONFIG"
|
||||
fi
|
||||
}
|
||||
amiberry -f "$AMIBERRY_TMP_CONFIG" --autoload "$1" >> $AMIBERRY_LOG 2>&1
|
||||
"""
|
||||
)
|
||||
|
||||
USERCONFIG = text(
|
||||
"""
|
||||
#!/bin/bash
|
||||
if [ ! -e "/storage/.configured" ]
|
||||
then
|
||||
rsync -a --ignore-existing --exclude=es_systems.cfg /usr/config/* /storage/.config/ || exit 1
|
||||
fi
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -195,8 +190,7 @@ def tree(**overrides: str) -> dict[str, str]:
|
||||
al.SCRIPTS["piemu"]: PIEMU,
|
||||
al.SCRIPTS["HATARISA"]: HATARI_SH,
|
||||
al.HATARI_CONFIG: HATARI_CFG,
|
||||
al.ATARI800_CONFIG: ATARI800_CFG,
|
||||
al.ATARI800_PATCH: ATARI800_PATCH,
|
||||
al.USERCONFIG: USERCONFIG,
|
||||
al.AMIBERRY_PACKAGE: AMIBERRY_MK,
|
||||
al.SCRIPTS["AMIBERRY"]: AMIBERRY_SH,
|
||||
f"{al.AMIBERRY_CONFIGS}/AmigaA1200-default.uae": uae("kick40068.A1200.rom"),
|
||||
@@ -218,6 +212,13 @@ class Frontends(unittest.TestCase):
|
||||
(record,) = al.retroarch(read())
|
||||
self.assertEqual(record.search_dir, "~/roms/bios")
|
||||
self.assertEqual(record.source_ref, f"{al.RETROARCH_CFG}:2")
|
||||
# The first boot copies /usr/config and leaves a file already there.
|
||||
self.assertEqual(record.installs, {
|
||||
"path": "/storage/.config/retroarch/retroarch.cfg",
|
||||
"source_ref": f"{al.USERCONFIG}:4",
|
||||
})
|
||||
self.assertIs(record.kept_if_present, True)
|
||||
self.assertEqual(record.overrides, [])
|
||||
|
||||
def test_retrorun_directory(self):
|
||||
(record,) = al.retrorun(read())
|
||||
@@ -266,6 +267,9 @@ class Standalone(unittest.TestCase):
|
||||
record.source_ref,
|
||||
f"{al.RUNEMU}:3, {al.SCRIPTS['HATARISA']}:3-4, {al.HATARI_CONFIG}:2",
|
||||
)
|
||||
# Copied over at each launch: nothing the user edits survives.
|
||||
self.assertEqual(record.installs["source_ref"], f"{al.SCRIPTS['HATARISA']}:3")
|
||||
self.assertIs(record.kept_if_present, False)
|
||||
|
||||
def test_amiberry_link_and_one_kickstart_per_config(self):
|
||||
link, a1200, a500 = al.amiberry(read(), al.Runemu(read()))
|
||||
@@ -273,7 +277,11 @@ class Standalone(unittest.TestCase):
|
||||
self.assertEqual(link.passes_to, "/usr/config/amiberry/kickstarts is a symlink to it")
|
||||
self.assertEqual((a1200.slot, a1200.names), ("A1200", ["kick40068.A1200.rom"]))
|
||||
self.assertEqual((a500.slot, a500.names), ("A500", ["kick34005.A500.rom"]))
|
||||
self.assertEqual(a500.depends_on_option, f"not ({a1200.depends_on_option})")
|
||||
self.assertTrue(a500.depends_on_option.startswith("not ("))
|
||||
# A WHDLoad boot replaces the setup the config gives.
|
||||
self.assertIn("--autoload", a1200.depends_on_option)
|
||||
self.assertEqual(a1200.installs["source_ref"], f"{al.SCRIPTS['AMIBERRY']}:5")
|
||||
self.assertEqual(a500.installs["source_ref"], f"{al.SCRIPTS['AMIBERRY']}:7")
|
||||
|
||||
def test_a_table_running_another_script_raises(self):
|
||||
broken = RUNEMU.replace("/usr/bin/yabasanshiro.sh", "/usr/bin/yaba.sh")
|
||||
@@ -287,15 +295,9 @@ class Standalone(unittest.TestCase):
|
||||
|
||||
|
||||
class Cores(unittest.TestCase):
|
||||
def test_atari800_built_to_read_the_shipped_config(self):
|
||||
(record,) = al.atari800(read())
|
||||
self.assertEqual(record.names, ["ATARIOSA.ROM", "5200.rom"])
|
||||
self.assertEqual(record.source_ref, f"{al.ATARI800_PATCH}:2, {al.ATARI800_CONFIG}:3-4")
|
||||
|
||||
def test_atari800_built_for_another_config_raises(self):
|
||||
broken = ATARI800_PATCH.replace("atari800.cfg", "other.cfg")
|
||||
with self.assertRaises(LauncherShapeError):
|
||||
al.atari800(read(**{al.ATARI800_PATCH: broken}))
|
||||
def test_atari800_config_is_no_record(self):
|
||||
# The core reads atari800.cfg only under an option that is off.
|
||||
self.assertFalse(any(r["emulator"] == "atari800" for r in al.extract_launchers(read())))
|
||||
|
||||
def test_scummvm_paths_written_under_bios(self):
|
||||
theme, extra = al.scummvm(read())
|
||||
@@ -319,7 +321,7 @@ class Cores(unittest.TestCase):
|
||||
def test_every_extractor_runs_on_the_fixture(self):
|
||||
records = al.extract_launchers(read())
|
||||
# One easyrpg runtime in the fixture, two at the pinned commit.
|
||||
self.assertEqual(len(records), 16)
|
||||
self.assertEqual(len(records), 15)
|
||||
|
||||
|
||||
class PlatformFile(unittest.TestCase):
|
||||
|
||||
@@ -40,6 +40,9 @@ ARES_SH = text(
|
||||
UserBIOSPath='/home/deck/Emulation/bios/'
|
||||
sed -i "s|$UserBIOSPath|${biosPath}\\/|g" "$ares_configFile"
|
||||
}
|
||||
ares_init(){
|
||||
configEmuFP "${ares_emuName}" "${ares_emuPath}" "true"
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -87,6 +90,9 @@ MELONDS_SH = text(
|
||||
buttonA='Joy_A='
|
||||
changeLine "$buttonA" "$buttonA""0" "${melonDS_configFile}"
|
||||
}
|
||||
melonDS_update(){
|
||||
configEmuFP "${melonDS_emuName}" "${melonDS_emuPath}"
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -103,6 +109,7 @@ MELONDS_TOML = text(
|
||||
LastROMFolder = "/run/media/mmcblk0p1/Emulation/roms/ds"
|
||||
[Emu]
|
||||
ExternalBIOSEnable = false
|
||||
ConsoleType = 0
|
||||
[DS]
|
||||
FirmwarePath = "/run/media/mmcblk0p1/Emulation/bios/firmware.bin"
|
||||
BIOS7Path = "/run/media/mmcblk0p1/Emulation/bios/bios7.bin"
|
||||
@@ -206,8 +213,23 @@ SHADPS4_SH = text(
|
||||
)
|
||||
|
||||
|
||||
CONFIG_EMU_FP = text(
|
||||
"""
|
||||
configEmuFP(){
|
||||
if [[ $overwrite == 'true' ]]; then
|
||||
overwrite="--backup --suffix=.bak"
|
||||
else
|
||||
overwrite="--ignore-existing"
|
||||
fi
|
||||
rsync -avhp --mkpath "$emudeckBackend/configs/${ID}" "$HOME/.var/app/" $overwrite
|
||||
}
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def tree(**scripts: str) -> RepoTree:
|
||||
files = {f"{S}/{name}": body for name, body in scripts.items()}
|
||||
files[el.CONFIG_EMU_FP] = CONFIG_EMU_FP
|
||||
files[f"{el.CONFIGS}/dev.ares.ares/data/ares/settings.bml"] = ARES_BML
|
||||
files[f"{el.CONFIGS}/net.kuribo64.melonDS/config/melonDS/melonDS.ini"] = MELONDS_INI
|
||||
files[f"{el.CONFIGS}/net.kuribo64.melonDS/config/melonDS/melonDS.toml"] = MELONDS_TOML
|
||||
@@ -253,8 +275,17 @@ class WrittenIntoTheConfig(unittest.TestCase):
|
||||
self.assertEqual(
|
||||
toml["passes_to"], "melonDS.toml [DS] FirmwarePath, BIOS7Path [DSi] NANDPath"
|
||||
)
|
||||
# The DS keys wait for ExternalBIOSEnable, the DSi keys for a DSi.
|
||||
self.assertEqual(
|
||||
toml["depends_on_option"], "ExternalBIOSEnable = false in the shipped melonDS.toml"
|
||||
toml["depends_on_option"],
|
||||
"[DS] keys: ExternalBIOSEnable = true, false in the shipped melonDS.toml; "
|
||||
"[DSi] keys: ConsoleType = 1, 0 in the shipped melonDS.toml",
|
||||
)
|
||||
# configEmuFP's update call passes --ignore-existing.
|
||||
self.assertIs(toml["kept_if_present"], True)
|
||||
self.assertEqual(
|
||||
toml["installs"]["path"],
|
||||
"${HOME}/.var/app/net.kuribo64.melonDS/config/melonDS/melonDS.toml",
|
||||
)
|
||||
|
||||
def test_a_config_the_setters_rewrite_keeps_their_values(self):
|
||||
|
||||
@@ -228,6 +228,9 @@ DUCKSTATION_SH = text(
|
||||
"""
|
||||
CONFIG_DIR="/emuelec/configs/duckstation"
|
||||
duckstation-nogui -fullscreen -settings "${CONFIG_DIR}/settings.ini" -- "${1}"
|
||||
if [ ! -d "${CONFIG_DIR}" ]; then
|
||||
cp -rf /usr/config/emuelec/configs/duckstation/* "${CONFIG_DIR}"
|
||||
fi
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -319,6 +322,9 @@ ADVMAME_SH = text(
|
||||
sed -i "s|/roms/arcade|/roms/mame|g" ${CONFIG_DIR}/advmame.rc
|
||||
fi
|
||||
SDL_AUDIODRIVER=alsa advmame ${ARG} -quiet
|
||||
if [ ! -d "${CONFIG_DIR}" ]; then
|
||||
cp -rf /usr/config/emuelec/configs/advmame/* "${CONFIG_DIR}/"
|
||||
fi
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -480,24 +486,12 @@ class LibretroRecords(unittest.TestCase):
|
||||
self.assertEqual(jar["passes_to"], "${HOME}/roms/bios")
|
||||
self.assertEqual(jar["depends_on_option"], "/storage/roms/bios/jdk/eeversion exists")
|
||||
|
||||
def test_mame_copies_its_own_files_and_reads_only_path_options(self):
|
||||
def test_mame_copies_its_own_files_and_hands_no_folder(self):
|
||||
# The core passes no path option and reads no mame.ini: only the
|
||||
# copies are the launcher's.
|
||||
found = records(el.mame)
|
||||
copies = [r for r in found if r["kind"] == "copies"]
|
||||
self.assertEqual([r["names"] for r in copies], [["fm*"], ["mame*"]])
|
||||
folders = [(r["passes_to"], r["search_dir"]) for r in found if r["kind"] == "passes_path"]
|
||||
self.assertEqual(
|
||||
folders,
|
||||
[
|
||||
("mame.ini rompath", "/storage/roms/bios/mame/bios"),
|
||||
("mame.ini samplepath", "/storage/roms/bios/mame/samples"),
|
||||
],
|
||||
)
|
||||
self.assertTrue(all(r["depends_on_option"] == "mame_read_config = enabled"
|
||||
for r in found if r["kind"] == "passes_path"))
|
||||
|
||||
def test_mame_without_the_read_config_option_raises(self):
|
||||
with self.assertRaises(LauncherPatternMissing):
|
||||
records(el.mame, **{f"{el.LIBRETRO}/mame/config/MAME/MAME.opt": "x = 1\n"})
|
||||
self.assertEqual([r["kind"] for r in found], ["copies", "copies"])
|
||||
self.assertEqual([r["names"] for r in found], [["fm*"], ["mame*"]])
|
||||
|
||||
|
||||
class StandaloneRecords(unittest.TestCase):
|
||||
@@ -546,6 +540,12 @@ class StandaloneRecords(unittest.TestCase):
|
||||
(record,) = records(el.duckstation)
|
||||
self.assertEqual((record["kind"], record["search_dir"]), ("scans_dir", "/storage/roms/bios"))
|
||||
|
||||
def test_duckstation_config_is_kept_when_present(self):
|
||||
(record,) = records(el.duckstation)
|
||||
self.assertEqual(record["installs"]["path"], "/emuelec/configs/duckstation/settings.ini")
|
||||
self.assertIs(record["kept_if_present"], True)
|
||||
self.assertEqual(record["overrides"], [])
|
||||
|
||||
def test_duckstation_with_a_fixed_bios_path_raises(self):
|
||||
changed = DUCKSTATION_INI.replace("PathPAL =", "PathPAL = /storage/roms/bios/scph5502.bin")
|
||||
with self.assertRaises(LauncherPatternMissing):
|
||||
@@ -631,7 +631,8 @@ class StandaloneRecords(unittest.TestCase):
|
||||
|
||||
def test_every_extractor_runs_on_the_fixtures(self):
|
||||
found = el.extract_launchers(tree())
|
||||
self.assertEqual(len(found), 28)
|
||||
# The two mame.ini folders are no longer records.
|
||||
self.assertEqual(len(found), 26)
|
||||
|
||||
|
||||
class Revision(unittest.TestCase):
|
||||
|
||||
@@ -598,10 +598,11 @@ class BootDisks(unittest.TestCase):
|
||||
self.assertEqual((hard.names, hard.passes_to), (["{bootdisk}.chd"], "command line -hard"))
|
||||
self.assertEqual(hard.expands, {"bootdisk": ["macos3", "mac755"]})
|
||||
self.assertTrue(hard.depends_on_option.startswith("bootdisk (system.name == 'macintosh'"))
|
||||
self.assertEqual(
|
||||
hard.source_ref,
|
||||
f"{G}/mame/mameGenerator.py:3-4, 9-10, {kl.ES_FEATURES}:8-10",
|
||||
)
|
||||
# The menu's values are where the choices come from, the generator
|
||||
# writing the choice is the evidence.
|
||||
self.assertEqual(hard.source_ref, f"{G}/mame/mameGenerator.py:3-4, 9-10")
|
||||
self.assertEqual(hard.choices_from, f"{kl.ES_FEATURES}:8-10")
|
||||
self.assertIsNone(floppy.choices_from)
|
||||
|
||||
def test_a_name_built_another_way_raises(self):
|
||||
broken = MAME.replace('"/userdata/bios/" + system.config["bootdisk"] + ".chd"', "disk")
|
||||
|
||||
@@ -85,13 +85,14 @@ MELONDS_SH = text(
|
||||
sed -i '/^ExternalBIOSEnable=/c\\ExternalBIOSEnable=0' /storage/.config/melonDS/melonDS.ini
|
||||
fi
|
||||
fi
|
||||
CONF_DIR="/storage/.config/melonDS"
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def melonds_tree() -> RepoTree:
|
||||
pkg = f"{SA}/melonds-sa"
|
||||
return RepoTree.from_files(
|
||||
return rocknix_tree(
|
||||
{
|
||||
**devices("AMD64", "H700", "RK3576", "S922X"),
|
||||
f"{pkg}/package.mk": MELONDS_MK,
|
||||
@@ -148,6 +149,7 @@ AMIBERRY_SH = text(
|
||||
cp -rf /usr/config/amiberry ${AMIBERRY_DIR}
|
||||
fi
|
||||
cd ${AMIBERRY_DIR}
|
||||
amiberry -f "${AMIBERRY_TMP_CONFIG}" --autoload "$1" >> ${AMIBERRY_LOG} 2>&1
|
||||
"""
|
||||
)
|
||||
|
||||
@@ -291,6 +293,22 @@ FLYCAST_SH = text(
|
||||
)
|
||||
|
||||
|
||||
USERCONFIG = text(
|
||||
"""
|
||||
#!/bin/bash
|
||||
if [ ! -e "/storage/.configured" ]
|
||||
then
|
||||
rsync -a --ignore-existing --exclude={es_features.cfg,es_systems.cfg} /usr/config/* /storage/.config/ >/var/log/configure.log 2>&1
|
||||
fi
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
def rocknix_tree(files: dict[str, str], links: dict[str, str] | None = None) -> RepoTree:
|
||||
"""A ROCKNIX tree holding the first-boot copy every config record cites."""
|
||||
return RepoTree.from_files({rl.USERCONFIG: USERCONFIG, **files}, links)
|
||||
|
||||
|
||||
def by(records: list[dict], emulator: str) -> list[dict]:
|
||||
return [r for r in records if r["emulator"] == emulator]
|
||||
|
||||
@@ -302,23 +320,26 @@ class ConfigsPerDevice(unittest.TestCase):
|
||||
empty, named = records
|
||||
self.assertEqual(empty["names"], [])
|
||||
self.assertTrue(empty["passes_to"].endswith("DSiNANDPath left empty"))
|
||||
# melonDS opens the DSi BIOS and firmware keys only under
|
||||
# DSiExternalBIOSEnable, which no shipped config sets.
|
||||
self.assertEqual(
|
||||
named["names"],
|
||||
[
|
||||
"bios9.bin",
|
||||
"bios7.bin",
|
||||
"firmware.bin",
|
||||
"dsi_bios9.bin",
|
||||
"dsi_bios7.bin",
|
||||
"dsi_firmware.bin",
|
||||
"dsi_nand.bin",
|
||||
],
|
||||
named["names"], ["bios9.bin", "bios7.bin", "firmware.bin", "dsi_nand.bin"]
|
||||
)
|
||||
self.assertEqual(named["search_dir"], "/storage/roms/bios")
|
||||
self.assertEqual(named["installs"]["path"], "/storage/.config/melonDS/melonDS.ini")
|
||||
self.assertIs(named["kept_if_present"], True)
|
||||
self.assertEqual(named["overrides"], [])
|
||||
|
||||
def test_a_config_setting_the_dsi_switch_keeps_the_dsi_keys(self):
|
||||
tree = melonds_tree()
|
||||
path = f"{SA}/melonds-sa/config/S922X/melonDS.ini"
|
||||
tree._texts[path] = tree.read(path) + "DSiExternalBIOSEnable=1\n"
|
||||
named = rl.melonds(tree)[1].entry()
|
||||
self.assertIn("dsi_bios9.bin", named["names"])
|
||||
|
||||
def test_a_linked_device_directory_reads_its_target(self):
|
||||
named = rl.melonds(melonds_tree())[1].entry()
|
||||
self.assertIn(f"{SA}/melonds-sa/config/InputPlumber/melonDS.ini:2-8", named["source_ref"])
|
||||
self.assertIn(f"{SA}/melonds-sa/config/InputPlumber/melonDS.ini:2-4, 8", named["source_ref"])
|
||||
self.assertNotIn("config/RK3576", named["source_ref"])
|
||||
|
||||
def test_the_external_bios_switch_is_the_option(self):
|
||||
@@ -330,11 +351,14 @@ class ConfigsPerDevice(unittest.TestCase):
|
||||
|
||||
def test_identical_configs_give_one_record_without_device(self):
|
||||
pkg = f"{SA}/dsperate-sa"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
**devices("H700", "RK3576", "S922X"),
|
||||
f"{pkg}/package.mk": DSPERATE_MK,
|
||||
f"{pkg}/scripts/start_dsperate.sh": '${EMUPERF} /usr/bin/dsperate --config "${DSPERATE_INI}" "${ROM}"\n',
|
||||
f"{pkg}/scripts/start_dsperate.sh": (
|
||||
'${EMUPERF} /usr/bin/dsperate --config "${DSPERATE_INI}" "${ROM}"\n'
|
||||
'DSPERATE_INI="/storage/.config/dsperate/dsperate.ini"\n'
|
||||
),
|
||||
f"{pkg}/config/H700/dsperate.ini": DSPERATE_INI,
|
||||
f"{pkg}/config/InputPlumber/dsperate.ini": DSPERATE_INI,
|
||||
f"{pkg}/config/S922X/dsperate.ini": DSPERATE_INI,
|
||||
@@ -352,10 +376,11 @@ class ConfigsPerDevice(unittest.TestCase):
|
||||
|
||||
def test_an_absent_key_and_an_empty_one_hand_over_the_same(self):
|
||||
pkg = f"{SA}/duckstation-sa"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
**devices("AMD64", "S922X"),
|
||||
f"{pkg}/package.mk": DUCKSTATION_MK,
|
||||
f"{pkg}/scripts/start_duckstation.sh": "#!/bin/bash\n",
|
||||
f"{pkg}/config/AMD64/settings.ini": "[BIOS]\nSearchDirectory = /storage/roms/bios\n",
|
||||
f"{pkg}/config/S922X/settings.ini": text(
|
||||
"""
|
||||
@@ -375,10 +400,11 @@ class ConfigsPerDevice(unittest.TestCase):
|
||||
|
||||
def test_a_bios_written_into_a_path_key_is_an_unknown_shape(self):
|
||||
pkg = f"{SA}/duckstation-sa"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
**devices("S922X"),
|
||||
f"{pkg}/package.mk": DUCKSTATION_MK,
|
||||
f"{pkg}/scripts/start_duckstation.sh": "#!/bin/bash\n",
|
||||
f"{pkg}/config/S922X/settings.ini": "[BIOS]\nSearchDirectory = /storage/roms/bios\nPathNTSCU = scph5501.bin\n",
|
||||
}
|
||||
)
|
||||
@@ -387,7 +413,7 @@ class ConfigsPerDevice(unittest.TestCase):
|
||||
|
||||
def test_a_package_without_a_device_copy_raises(self):
|
||||
pkg = f"{SA}/duckstation-sa"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
**devices("S922X"),
|
||||
f"{pkg}/package.mk": "makeinstall_target() {\n true\n}\n",
|
||||
@@ -402,7 +428,7 @@ class NamesTheConfigsFix(unittest.TestCase):
|
||||
def test_amiberry_machine_follows_the_game_name(self):
|
||||
pkg = f"{SA}/amiberry"
|
||||
uae = "amiberry.rom_path=/storage/.config/amiberry/kickstarts/\nkickstart_rom_file=@BIOS_PATH@/{}\nkickstart_ext_rom_file=\n"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
f"{pkg}/scripts/start_amiberry.sh": AMIBERRY_SH,
|
||||
f"{pkg}/package.mk": AMIBERRY_MK,
|
||||
@@ -412,9 +438,15 @@ class NamesTheConfigsFix(unittest.TestCase):
|
||||
)
|
||||
a1200, a500, link, entered, copied = (r.entry() for r in rl.amiberry(tree))
|
||||
self.assertEqual((a1200["slot"], a1200["names"]), ("A1200", ["kick40068.A1200.rom"]))
|
||||
self.assertEqual(a1200["depends_on_option"], "game name matches AGA|CD32")
|
||||
self.assertEqual(
|
||||
a1200["depends_on_option"],
|
||||
"game name matches AGA|CD32, content not booted with --autoload, "
|
||||
"a WHDLoad .lha or .zip (start_amiberry.sh:17)",
|
||||
)
|
||||
self.assertEqual(a1200["installs"]["path"], "${AMIBERRY_TMP_CONFIG}")
|
||||
self.assertIs(a1200["kept_if_present"], False)
|
||||
self.assertEqual((a500["slot"], a500["names"]), ("A500", ["kick34005.A500.rom"]))
|
||||
self.assertEqual(a500["depends_on_option"], "game name does not match AGA|CD32")
|
||||
self.assertTrue(a500["depends_on_option"].startswith("game name does not match AGA|CD32"))
|
||||
self.assertEqual(a500["search_dir"], "/storage/roms/bios")
|
||||
self.assertEqual(
|
||||
a1200["source_ref"],
|
||||
@@ -443,7 +475,7 @@ class NamesTheConfigsFix(unittest.TestCase):
|
||||
|
||||
def test_mednafen_one_record_per_module(self):
|
||||
pkg = f"{SA}/mednafen"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
f"{pkg}/config/common/mednafen.template": MEDNAFEN_TEMPLATE,
|
||||
f"{pkg}/scripts/start_mednafen.sh": MEDNAFEN_SH,
|
||||
@@ -461,7 +493,7 @@ class NamesTheConfigsFix(unittest.TestCase):
|
||||
|
||||
def test_mednafen_without_a_firmware_directory_raises(self):
|
||||
pkg = f"{SA}/mednafen"
|
||||
tree = RepoTree.from_files(
|
||||
tree = rocknix_tree(
|
||||
{
|
||||
f"{pkg}/config/common/mednafen.template": "psx.bios_eu scph5502.bin\n",
|
||||
f"{pkg}/scripts/start_mednafen.sh": MEDNAFEN_SH,
|
||||
@@ -473,7 +505,7 @@ class NamesTheConfigsFix(unittest.TestCase):
|
||||
|
||||
class SearchedNames(unittest.TestCase):
|
||||
def tree(self, script: str) -> RepoTree:
|
||||
return RepoTree.from_files({f"{SA}/yabasanshiro-sa/scripts/start_yabasanshiro.sh": script})
|
||||
return rocknix_tree({f"{SA}/yabasanshiro-sa/scripts/start_yabasanshiro.sh": script})
|
||||
|
||||
def test_yabasanshiro_tries_its_names_in_order(self):
|
||||
(record,) = [r.entry() for r in rl.yabasanshiro(self.tree(YABASANSHIRO_SH))]
|
||||
@@ -514,7 +546,7 @@ class Links(unittest.TestCase):
|
||||
|
||||
def tree(self) -> RepoTree:
|
||||
scripts = self.all_scripts()
|
||||
return RepoTree.from_files({p: scripts[e] for e, p in rl.LINK_SCRIPTS})
|
||||
return rocknix_tree({p: scripts[e] for e, p in rl.LINK_SCRIPTS})
|
||||
|
||||
def emulator(self, name: str) -> list[dict]:
|
||||
return by([r.entry() for r in rl.links(self.tree())], name)
|
||||
@@ -566,7 +598,7 @@ class Links(unittest.TestCase):
|
||||
def test_a_script_without_a_bios_link_raises(self):
|
||||
scripts = self.all_scripts()
|
||||
scripts["flycast"] = 'ln -sf "/storage/.config/flycast" "/storage/.local/share/flycast"\n'
|
||||
tree = RepoTree.from_files({p: scripts[e] for e, p in rl.LINK_SCRIPTS})
|
||||
tree = rocknix_tree({p: scripts[e] for e, p in rl.LINK_SCRIPTS})
|
||||
with self.assertRaises(LauncherPatternMissing):
|
||||
rl.links(tree)
|
||||
|
||||
@@ -603,7 +635,7 @@ class ProgramsRunOutsideTheBiosFolder(unittest.TestCase):
|
||||
PATH = f"{SA}/pico-8/scripts/start_pico8.sh"
|
||||
|
||||
def test_pico8_runs_its_binary_from_roms(self):
|
||||
(record,) = [r.entry() for r in rl.pico8(RepoTree.from_files({self.PATH: START_PICO8}))]
|
||||
(record,) = [r.entry() for r in rl.pico8(rocknix_tree({self.PATH: START_PICO8}))]
|
||||
self.assertEqual(
|
||||
(record["emulator"], record["kind"], record["names"], record["search_dir"],
|
||||
record["passes_to"]),
|
||||
@@ -615,7 +647,7 @@ class ProgramsRunOutsideTheBiosFolder(unittest.TestCase):
|
||||
def test_a_script_without_its_binary_choice_raises(self):
|
||||
broken = START_PICO8.replace('STATIC_BIN="pico8_dyn"', "STATIC_BIN=$OTHER")
|
||||
with self.assertRaises(LauncherPatternMissing):
|
||||
rl.pico8(RepoTree.from_files({self.PATH: broken}))
|
||||
rl.pico8(rocknix_tree({self.PATH: broken}))
|
||||
|
||||
|
||||
class Revision(unittest.TestCase):
|
||||
|
||||
@@ -445,6 +445,10 @@ launchers:
|
||||
| `fails_scope` | `emulator` when the failure needs every record of the emulator to come up empty |
|
||||
| `depends_on_option` | Options or conditions that decide whether the record applies |
|
||||
| `device` | Devices whose shipped config the record reads, set only where a package ships configs that differ between devices |
|
||||
| `installs` | For a record citing a config: `path` where the platform's code puts it and the `source_ref` of that code |
|
||||
| `kept_if_present` | Whether that install leaves a file already there (a copy only if absent, rsync `--ignore-existing`) |
|
||||
| `overrides` | Launch code rewriting the record's keys or replacing the config, empty when none does |
|
||||
| `choices_from` | The feature or option file listing the values the option takes (es_features, a core `.opt`), never the record's evidence |
|
||||
| `source_ref` | `path:lines` in the repository and at the revision `source` pins, which the site links |
|
||||
|
||||
Batocera's generators are read with `ast`, RetroBat's C# generators as text.
|
||||
@@ -453,18 +457,24 @@ package, so `scripts/scraper/shell_launchers.py` reads assignments, `for`
|
||||
loops, `ln -s` commands and `key = value` lines. A ROCKNIX package can ship
|
||||
one config per device: the configs are grouped by the value read, and
|
||||
`device` appears only when there is more than one group. melonDS writes its
|
||||
seven BIOS paths on every device but AMD64, where the keys are left empty:
|
||||
BIOS paths on every device but AMD64, where the keys are left empty:
|
||||
|
||||
```yaml
|
||||
- emulator: melonds
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
names: []
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiBIOS9Path,
|
||||
DSiBIOS7Path, DSiFirmwarePath, DSiNANDPath left empty
|
||||
passes_to: melonDS.ini BIOS9Path, BIOS7Path, FirmwarePath, DSiNANDPath left empty
|
||||
device: AMD64
|
||||
```
|
||||
|
||||
A config file is proof only when the code installing it and the code reading
|
||||
it are shown. A record citing a config carries `installs` and `overrides`, and
|
||||
the emulator's profile says, in `config_reads`, where the build it ships loads
|
||||
that file and reads each key. A record whose chain does not hold is listed as
|
||||
unproven by `verify.py` and `cross_reference.py`, and no pack or manifest
|
||||
places a file from it.
|
||||
|
||||
An extractor that no longer recognises the shape of the code raises: an
|
||||
empty list would read as a launcher that looks for nothing.
|
||||
|
||||
|
||||
Reference in new issue
Block a user