mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-13 13:33:52 -06:00
feat: read pico-8 launchers of rocknix, retrobat
ROCKNIX's start_pico8.sh runs pico8_64 or pico8_dyn from /storage/roms/pico-8 and RetroBat's Pico8 generator runs pico8.exe from its pico8 emulator folder. Both are recorded as exec records, read from the scripts at the revisions the platform files pin.
This commit is contained in:
1 parent
6a9700489d
commit
b5ee4ab09e
7 files changed
+216
No files matched your search
@@ -4953,6 +4953,16 @@ launchers:
|
||||
fails_when_missing: ApplicationException 'No valid PS2 BIOS file found in '<ps2BiosFolder>'.'
|
||||
depends_on_option: lrps2_bios unset
|
||||
source_ref: "emulatorLauncher/Generators/LibRetro.CoreOptions.cs:3662-3683, 3708-3713"
|
||||
- emulator: pico8
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
names:
|
||||
- pico8.exe
|
||||
case_insensitive: true
|
||||
search_dir: "<AppConfig.GetFullPath(\"pico8\")>"
|
||||
passes_to: exec
|
||||
fails_when_missing: returns no process when the binary is absent
|
||||
source_ref: "emulatorLauncher/Generators/Pico8.Generator.cs:14-18, 56-57"
|
||||
- emulator: bizhawk
|
||||
build: standalone
|
||||
kind: names_searched
|
||||
|
||||
@@ -736,6 +736,19 @@ launchers:
|
||||
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"
|
||||
- emulator: pico-8
|
||||
build: standalone
|
||||
kind: fixed_name
|
||||
names:
|
||||
- pico8_64
|
||||
- pico8_dyn
|
||||
search_dir: /storage/roms/pico-8
|
||||
passes_to: exec
|
||||
fails_when_missing: false
|
||||
depends_on_option: "HW_ARCH aarch64 runs pico8_64, any other pico8_dyn, from /storage/roms/pico-8/${HW_ARCH}\
|
||||
\ when that folder exists"
|
||||
source_ref: "projects/ROCKNIX/packages/emulators/standalone/pico-8/scripts/start_pico8.sh:8-15,\
|
||||
\ 35-40, 48"
|
||||
- emulator: flycast
|
||||
build: standalone
|
||||
kind: passes_path
|
||||
|
||||
@@ -51,6 +51,7 @@ SOURCE_FILES = (
|
||||
f"{GENERATORS}/OpenMSX.Generator.cs",
|
||||
f"{GENERATORS}/PSXMame.Generator.cs",
|
||||
f"{GENERATORS}/Pcsx2.Generator.cs",
|
||||
f"{GENERATORS}/Pico8.Generator.cs",
|
||||
f"{GENERATORS}/PortsLauncher.Configuration.cs",
|
||||
f"{GENERATORS}/Project64.Generator.cs",
|
||||
f"{GENERATORS}/Raine.Generator.cs",
|
||||
@@ -2968,6 +2969,44 @@ def xroar(sources: dict[str, Source]) -> list[Record]:
|
||||
return _covered(src, records)
|
||||
|
||||
|
||||
def pico8(sources: dict[str, Source]) -> list[Record]:
|
||||
"""The PICO-8 binary the generator runs, from an emulator folder.
|
||||
|
||||
AppConfig.GetFullPath names a folder of the RetroBat install
|
||||
(emulatorLauncher.cfg, else emulators/<key>): the binary is never
|
||||
looked up in the BIOS tree.
|
||||
"""
|
||||
src = sources[f"{GENERATORS}/Pico8.Generator.cs"]
|
||||
folder = src.find(r'string path = AppConfig\.GetFullPath\("(\w+)"\);', "pico8 folder")
|
||||
exe = src.find(
|
||||
r'string exe = Path\.Combine\(path, "([^"]+)"\);', "binary path", folder.end()
|
||||
)
|
||||
check = src.find(r"if \(!File\.Exists\(exe\)\)\s*return null;", "binary check", exe.end())
|
||||
run = src.find(r"FileName = exe,\s*WorkingDirectory = path,", "binary run", check.end())
|
||||
return [
|
||||
_record(
|
||||
"pico8",
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[exe.group(1)],
|
||||
source_ref(
|
||||
(
|
||||
src.path,
|
||||
[
|
||||
src.lines(folder.start(), folder.end()),
|
||||
src.lines(exe.start(), check.end()),
|
||||
src.lines(run.start(), run.end()),
|
||||
],
|
||||
)
|
||||
),
|
||||
case_insensitive=True,
|
||||
search_dir=f"<AppConfig.GetFullPath(\"{folder.group(1)}\")>",
|
||||
passes_to="exec",
|
||||
fails_when_missing="returns no process when the binary is absent",
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
def snes9x(sources: dict[str, Source]) -> list[Record]:
|
||||
src = sources[f"{GENERATORS}/Snes9x.Generator.cs"]
|
||||
entry = src.find(rf'\{{ "([^"]+)", (Path\.Combine\({_BIOS_ROOT}\)) \}}', "bios folder entry")
|
||||
@@ -3236,6 +3275,7 @@ EXTRACTORS: tuple[Callable[[dict[str, Source]], list[Record]], ...] = (
|
||||
option_paths,
|
||||
pcsx2,
|
||||
pcsx2_libretro,
|
||||
pico8,
|
||||
psx_cascades,
|
||||
psxmame,
|
||||
raine,
|
||||
|
||||
@@ -575,6 +575,47 @@ def armsx2(tree: RepoTree) -> list[Launcher]:
|
||||
|
||||
|
||||
# Start scripts whose ln -s commands put a BIOS path where the emulator reads.
|
||||
def pico8(tree: RepoTree) -> list[Launcher]:
|
||||
"""The PICO-8 binary start_pico8.sh executes, outside /storage/roms/bios.
|
||||
|
||||
The script picks the binary by HW_ARCH, pico8_64 on aarch64 and
|
||||
pico8_dyn on any other, and runs it from GAME_DIR, or from
|
||||
GAME_DIR/${HW_ARCH} when that folder exists.
|
||||
"""
|
||||
path = f"{STANDALONE}/pico-8/scripts/start_pico8.sh"
|
||||
script = Script(path, tree.read(path))
|
||||
game_line, game = script.find(r'^\s*GAME_DIR="([^"$]+)"', "GAME_DIR assignment")
|
||||
case_line, _ = script.find(r"^\s*case \$\{HW_ARCH\} in", "case on HW_ARCH")
|
||||
arch_line, arch = script.find(r"^\s*(\w+)\)", "HW_ARCH branch", case_line + 1)
|
||||
first_line, first = script.find(r'STATIC_BIN="([^"$]+)"', "binary of the first branch", arch_line)
|
||||
other_line, _ = script.find(r"^\s*\*\)", "default HW_ARCH branch", first_line)
|
||||
rest_line, rest = script.find(r'STATIC_BIN="([^"$]+)"', "binary of the default branch", other_line)
|
||||
sub_line, _ = script.find(
|
||||
r'if \[ -d "\$\{GAME_DIR\}/\$\{HW_ARCH\}" \]', "per-architecture launch folder"
|
||||
)
|
||||
end_line, _ = script.find(r"^\s*fi\b", "end of the launch folder test", sub_line)
|
||||
run_line, _ = script.find(r"^\s*\$\{LAUNCH_DIR\}/\$\{STATIC_BIN\} ", "binary run")
|
||||
return [
|
||||
Launcher(
|
||||
emulator="pico-8",
|
||||
build="standalone",
|
||||
kind="fixed_name",
|
||||
names=[first.group(1), rest.group(1)],
|
||||
source_ref=source_ref([(path, {
|
||||
game_line, case_line, arch_line, first_line, other_line, rest_line,
|
||||
*range(sub_line, end_line + 1), run_line,
|
||||
})]),
|
||||
search_dir=game.group(1).rstrip("/"),
|
||||
passes_to="exec",
|
||||
fails_when_missing=False,
|
||||
depends_on_option=(
|
||||
f"HW_ARCH {arch.group(1)} runs {first.group(1)}, any other {rest.group(1)}, "
|
||||
f"from {game.group(1).rstrip('/')}/${{HW_ARCH}} when that folder exists"
|
||||
),
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
LINK_SCRIPTS = (
|
||||
("drastic", f"{STANDALONE}/drastic-sa/scripts/start_drastic.sh"),
|
||||
("dolphin", f"{STANDALONE}/dolphin-sa/scripts/start_dolphin_gc.sh"),
|
||||
@@ -679,6 +720,7 @@ EXTRACTORS: tuple[Callable[[RepoTree], list[Launcher]], ...] = (
|
||||
yabasanshiro,
|
||||
duckstation,
|
||||
armsx2,
|
||||
pico8,
|
||||
patched_directories,
|
||||
links,
|
||||
)
|
||||
|
||||
@@ -1141,6 +1141,36 @@ class FolderArguments(unittest.TestCase):
|
||||
)
|
||||
|
||||
|
||||
PICO8 = """
|
||||
public override System.Diagnostics.ProcessStartInfo Generate(string system, string emulator, string core, string rom, string playersControllers, ScreenResolution resolution)
|
||||
{
|
||||
string path = AppConfig.GetFullPath("pico8");
|
||||
|
||||
string exe = Path.Combine(path, "pico8.exe");
|
||||
if (!File.Exists(exe))
|
||||
return null;
|
||||
|
||||
return new ProcessStartInfo()
|
||||
{
|
||||
FileName = exe,
|
||||
WorkingDirectory = path,
|
||||
Arguments = args,
|
||||
};
|
||||
}
|
||||
"""
|
||||
|
||||
|
||||
class ProgramsRunFromEmulatorFolders(unittest.TestCase):
|
||||
def test_pico8_runs_its_binary_from_its_emulator_folder(self):
|
||||
(record,) = rl.pico8(_sources(**{f"{G}/Pico8.Generator.cs": PICO8}))
|
||||
self.assertEqual(
|
||||
(record["emulator"], record["kind"], record["names"], record["search_dir"],
|
||||
record["passes_to"], record["source_ref"]),
|
||||
("pico8", "fixed_name", ["pico8.exe"], '<AppConfig.GetFullPath("pico8")>', "exec",
|
||||
f"{G}/Pico8.Generator.cs:3-7, 11-12"),
|
||||
)
|
||||
|
||||
|
||||
class EveryBiosReferenceIsRead(unittest.TestCase):
|
||||
def test_unread_reference_stops_the_scrape(self):
|
||||
extra = EKA2L1 + (
|
||||
|
||||
@@ -293,6 +293,28 @@ DRASTIC = module("drastic", """
|
||||
""", 36)
|
||||
|
||||
|
||||
UAE4ALL = module("uae4all", """
|
||||
function configure_uae4all() {
|
||||
mkRomDir "amiga"
|
||||
|
||||
moveConfigDir "$md_inst/kickstarts" "$biosdir/amiga"
|
||||
|
||||
rm -f "$romdir/amiga/+Start UAE4All.sh"
|
||||
if [[ "$md_mode" == "install" ]]; then
|
||||
cat > "$romdir/amiga/+Start UAE4All.sh" << _EOF_
|
||||
#!/bin/bash
|
||||
pushd "$md_inst"
|
||||
./uae4all
|
||||
popd
|
||||
_EOF_
|
||||
fi
|
||||
|
||||
addEmulator 1 "$md_id" "amiga" "bash $romdir/amiga/+Start\\ UAE4All.sh"
|
||||
addSystem "amiga"
|
||||
}
|
||||
""", 60)
|
||||
|
||||
|
||||
class WorkingDirectory(unittest.TestCase):
|
||||
def test_drastic_reads_below_the_folder_its_script_enters(self):
|
||||
found = records({f"{EMULATORS}/drastic.sh": DRASTIC}, "drastic")
|
||||
@@ -306,6 +328,18 @@ class WorkingDirectory(unittest.TestCase):
|
||||
)],
|
||||
)
|
||||
|
||||
def test_uae4all_runs_from_its_install_directory(self):
|
||||
found = records({f"{EMULATORS}/uae4all.sh": UAE4ALL}, "uae4all")
|
||||
entered = [r for r in found if r["kind"] == "passes_path"]
|
||||
self.assertEqual(
|
||||
[(r["search_dir"], r["passes_to"], r["source_ref"]) for r in entered],
|
||||
[(
|
||||
"$md_inst",
|
||||
"working directory of $romdir/amiga/+Start UAE4All.sh",
|
||||
f"{EMULATORS}/uae4all.sh:69",
|
||||
)],
|
||||
)
|
||||
|
||||
def test_a_launch_script_that_no_longer_enters_a_folder_raises(self):
|
||||
files = {f"{EMULATORS}/drastic.sh": DRASTIC.replace('pushd "', 'echo "')}
|
||||
with self.assertRaises(rl.LauncherPatternMissing):
|
||||
|
||||
@@ -551,6 +551,53 @@ class Links(unittest.TestCase):
|
||||
rl.links(tree)
|
||||
|
||||
|
||||
START_PICO8 = text(
|
||||
"""
|
||||
#!/bin/bash
|
||||
. /etc/profile
|
||||
|
||||
GAME_DIR="/storage/roms/pico-8/"
|
||||
|
||||
case ${HW_ARCH} in
|
||||
aarch64)
|
||||
STATIC_BIN="pico8_64"
|
||||
;;
|
||||
*)
|
||||
STATIC_BIN="pico8_dyn"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -d "${GAME_DIR}/${HW_ARCH}" ]
|
||||
then
|
||||
LAUNCH_DIR="${GAME_DIR}/${HW_ARCH}"
|
||||
else
|
||||
LAUNCH_DIR="${GAME_DIR}"
|
||||
fi
|
||||
|
||||
${LAUNCH_DIR}/${STATIC_BIN} -home -root_path ${GAME_DIR} -joystick 0 ${OPTIONS} "${CART}"
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
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}))]
|
||||
self.assertEqual(
|
||||
(record["emulator"], record["kind"], record["names"], record["search_dir"],
|
||||
record["passes_to"]),
|
||||
("pico-8", "fixed_name", ["pico8_64", "pico8_dyn"], "/storage/roms/pico-8", "exec"),
|
||||
)
|
||||
self.assertIn("HW_ARCH aarch64 runs pico8_64", record["depends_on_option"])
|
||||
self.assertEqual(record["source_ref"], f"{self.PATH}:4-11, 15-22")
|
||||
|
||||
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}))
|
||||
|
||||
|
||||
class Revision(unittest.TestCase):
|
||||
def test_the_revision_is_the_one_the_bios_list_is_read_at(self):
|
||||
url = (
|
||||
|
||||
Reference in new issue
Block a user