fix: place Dolphin's User folder a platform sets

Dolphin reads its User folder at $XDG_DATA_HOME/dolphin-emu, else
~/.local/share/dolphin-emu (Source/Core/UICommon/UICommon.cpp:449-477).
The profile names both, so a launcher handing that folder places the
layout:

- EmuELEC starts Dolphin with XDG_DATA_HOME=/storage/roms/dolphin
  (dolphinSA/scripts/dolphin.sh:28): its 30 files move from the BIOS
  root to dolphin/dolphin-emu/ of the install tree.
- RetroDECK links User/Triforce to bios/Triforce
  (dolphin/component_prepare.sh:30, 49), where its list already puts
  segaboot.gcm. The rest of the User folder sits in the Flatpak's data
  directory and is named as read outside the BIOS folder.

An entry only the standalone build reads, path and no standalone_path,
now takes that path as its layout path (Load/Firmware/rtl_bt/), and
the pass copying a name the platform declares elsewhere reaches an
unprefixed path: gba_bios.bin lands in dolphin/dolphin-emu/GBA/.
This commit is contained in:
Abdessamad Derraz committed 2026-11-10 12:21:05 +01:00
1 parent 74ef0a37d5
commit 2fc3df50c6
4 files changed
+39 -4

No files matched your search

+3
View File
@@ -23,6 +23,9 @@ cores:
- "dolphin-qt-gc"
- "dolphin-qt-wii"
systems: [nintendo-gamecube, nintendo-wii, sega-triforce]
standalone_directories:
- "$XDG_DATA_HOME/dolphin-emu"
- "~/.local/share/dolphin-emu"
data_root:
android:
path: "Android/data/org.dolphinemu.dolphinemu/files"
+4 -2
View File
@@ -2985,12 +2985,14 @@ def standalone_layout_path(entry: dict, profile: dict) -> str | None:
``standalone_path`` when the entry has one. A profile with no libretro
build has one layout, so its ``path`` is that layout: UAE4All2 reads
kickstarts/kick13.rom below its working directory.
kickstarts/kick13.rom below its working directory. So does an entry only
the standalone build reads (``mode: standalone``), whose destination is
its ``path``: Dolphin's Load/Firmware/rtl_bt/ under its User directory.
"""
own = entry.get("standalone_path")
if own:
return own
if "libretro" in str(profile.get("type", "")):
if "libretro" in str(profile.get("type", "")) and entry.get("mode") != "standalone":
return None
return entry.get("path") or None
+9 -2
View File
@@ -1399,7 +1399,7 @@ def _collect_emulator_extras(
# covered elsewhere belongs to another program's file.
# Nor is one placed outside the BIOS tree by the layout.
if (fname not in covered_names or f.get("unsourceable") or f.get("unplaced")
or f.get("root") in OUTER_ROOTS or f.get("unprefixed")):
or f.get("root") in OUTER_ROOTS):
continue
# Installed with the emulator or by the platform's package,
# as the first pass already decided for the same entry.
@@ -1429,7 +1429,12 @@ def _collect_emulator_extras(
# of the directory core files go to, which the platform may not
# declare (Recalbox has its System Cards under pcenginecd/ only,
# geargrafx reads them from the root).
full_dest = prefixed_destination(dest, extras_prefix)
# A path of the install tree outside the BIOS folder keeps no
# prefix: EmuELEC's dolphin/dolphin-emu/GBA/gba_bios.bin.
full_dest = (
sanitize_pack_path(dest) if f.get("unprefixed")
else prefixed_destination(dest, extras_prefix)
)
if full_dest in seen_dests and full_dest not in taken:
continue
if full_dest in taken and full_dest not in seen and fname not in platform_names:
@@ -1475,6 +1480,8 @@ def _collect_emulator_extras(
extra["contents"] = f["contents"]
if f.get("system_dir"):
extra["system_dir"] = f["system_dir"]
if f.get("unprefixed"):
extra["unprefixed"] = True
extra["claim_order"] = (2, 0, emu_name)
if _take(extra, full_dest, seen_dests, taken):
extras.append(extra)
+23
View File
@@ -784,5 +784,28 @@ class CemuOnRetroDECK(unittest.TestCase):
self.assertEqual(otp.get("unplaced"), "outside_bios_folder")
class DolphinUserDirectory(unittest.TestCase):
"""EmuELEC runs Dolphin with XDG_DATA_HOME=/storage/roms/dolphin (dolphin.sh:28),
RetroDECK links $XDG_DATA_HOME/dolphin-emu/Triforce to bios/Triforce
(dolphin/component_prepare.sh:30, 49)."""
def test_emuelec_installs_the_user_directory_below_its_roms(self) -> None:
view = standalone_view("dolphin", "emuelec")
placed = {e["name"]: e["standalone_path"] for e in view["files"] if e.get("layout_path")}
self.assertEqual(placed["segaboot.gcm"], "dolphin/dolphin-emu/Triforce/segaboot.gcm")
# A standalone-only entry's path is its place in the User directory.
self.assertEqual(
placed["rtl8723a_fw.bin"], "dolphin/dolphin-emu/Load/Firmware/rtl_bt/rtl8723a_fw.bin"
)
self.assertTrue(all(e.get("unprefixed") for e in view["files"] if e.get("layout_path")))
def test_retrodeck_places_triforce_alone(self) -> None:
view = standalone_view("dolphin", "retrodeck")
placed = {e["name"]: e["standalone_path"] for e in view["files"] if e.get("layout_path")}
self.assertEqual(placed, {"segaboot.gcm": "Triforce/segaboot.gcm"})
(ipl, *_) = [e for e in view["files"] if e["name"] == "IPL.bin"]
self.assertEqual(ipl.get("unplaced"), "outside_bios_folder")
if __name__ == "__main__":
unittest.main()