mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-14 05:53:47 -06:00
fix: record what RetroBat writes for xemu and Cxbx
The xemu generator writes eeprom.bin and xbox_hdd.qcow2 into saves/<system> from its own resources and passes both in xemu.toml, copies chihiro_eeprom.bin between saves/chihiro and the emulator folder, and points the Chihiro snapshot store at saves/chihiro. The Cxbx generator runs each build from its emulator folder (chihiro, chihiro-ds, cxbx-reloaded, else cxbx-r), where it writes settings.ini, writes EEPROM.bin into cxbx-reloaded for an Xbox, and mounts an .iso with its own xbox-iso-vfs.exe after checking the Dokan 2 runtime. Nine records, read at emulatorLauncher ca486005. A program the launcher runs from its own folder is no launcher read left to collect. xemu-chihiro lists the two files it generates, chihiro_eeprom.bin and chihiro_snapshots.qcow2, as unsourceable.
This commit is contained in:
1 parent
9c46f7471d
commit
7f38954041
6 files changed
+563
-1
No files matched your search
@@ -26,6 +26,7 @@ SOURCE_FILES = (
|
||||
f"{GENERATORS}/Bizhawk.Generator.cs",
|
||||
f"{GENERATORS}/Blastem.Generator.cs",
|
||||
f"{GENERATORS}/Citron.Generator.cs",
|
||||
f"{GENERATORS}/Cxbx.Generator.cs",
|
||||
f"{GENERATORS}/Demul.Generator.cs",
|
||||
f"{GENERATORS}/Desmume.Generator.cs",
|
||||
f"{GENERATORS}/Dolphin.Generator.cs",
|
||||
@@ -1358,6 +1359,287 @@ def xemu(sources: dict[str, Source]) -> list[Record]:
|
||||
return records
|
||||
|
||||
|
||||
def xemu_saves(sources: dict[str, Source]) -> list[Record]:
|
||||
"""The files the xemu generator keeps below the saves folder.
|
||||
|
||||
An Xbox gets eeprom.bin and xbox_hdd.qcow2 in saves/<system>, written
|
||||
from the launcher's own resources when absent, and their paths in
|
||||
xemu.toml. A Chihiro keeps chihiro_eeprom.bin there, copied into the
|
||||
emulator folder before the run and back after it, and its snapshot
|
||||
store.
|
||||
"""
|
||||
src = sources[f"{GENERATORS}/Xemu.Generator.cs"]
|
||||
chihiro = src.find(r'(_chihiro) = \(emulator == "([\w-]+)" \|\| system == "(\w+)"\);', "Chihiro switch")
|
||||
chihiro_when = f'emulator == "{chihiro.group(2)}" or system == "{chihiro.group(3)}"'
|
||||
saves = src.find(
|
||||
r'if \(!string\.IsNullOrEmpty\(AppConfig\["saves"\]\) && Directory\.Exists\(AppConfig\.GetFullPath\("saves"\)\)\)'
|
||||
r'\s*\{\s*string savePath = Path\.Combine\(AppConfig\.GetFullPath\("saves"\), system\);',
|
||||
"Xbox save folder",
|
||||
)
|
||||
eeprom = src.find(
|
||||
r'if \(!File\.Exists\(Path\.Combine\(savePath, "([^"]+)"\)\)\)\s*\{[^{}]*?'
|
||||
r'File\.WriteAllBytes\(Path\.Combine\(savePath, "\1"\), Properties\.Resources\.(\w+)\);\s*\}',
|
||||
"EEPROM written from resources",
|
||||
saves.end(),
|
||||
)
|
||||
hdd = src.find(
|
||||
r'if \(!File\.Exists\(Path\.Combine\(savePath, "([^"]+)"\)\)\)\s*\{[^{}]*?'
|
||||
r'File\.WriteAllBytes\(zipFile, Properties\.Resources\.(\w+)\);[^{}]*?Zip\.Extract\(zipFile, savePath\);[^{}]*?\}',
|
||||
"hard disk image written from resources",
|
||||
eeprom.end(),
|
||||
)
|
||||
eeprom_key = src.find(
|
||||
r'ini\.WriteValue\("([\w.]+)", "(eeprom_path)", "\'" \+ eepromPath', "eeprom_path write"
|
||||
)
|
||||
hdd_key = src.find(r'ini\.WriteValue\("([\w.]+)", "(hdd_path)", "\'" \+ hddPath', "hdd_path write")
|
||||
records = [
|
||||
_record(
|
||||
"xemu",
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[eeprom.group(1), hdd.group(1)],
|
||||
source_ref(
|
||||
(
|
||||
src.path,
|
||||
[
|
||||
src.lines(chihiro.start(), chihiro.end()),
|
||||
src.lines(saves.start(), hdd.end()),
|
||||
src.lines(eeprom_key.start(), eeprom_key.end()),
|
||||
src.lines(hdd_key.start(), hdd_key.end()),
|
||||
],
|
||||
)
|
||||
),
|
||||
case_insensitive=True,
|
||||
search_dir="saves/<system>",
|
||||
passes_to=(
|
||||
f"xemu.toml [{eeprom_key.group(1)}] {eeprom_key.group(2)}, {hdd_key.group(2)};"
|
||||
f" written from the launcher's {eeprom.group(2)} and {hdd.group(2)} resources"
|
||||
" when absent, the disk image unzipped"
|
||||
),
|
||||
fails_when_missing="never missing: the launcher writes both",
|
||||
depends_on_option=_joined("the saves folder is set and exists", f"not ({chihiro_when})"),
|
||||
)
|
||||
]
|
||||
|
||||
setup = src.find(r"private void SetupChihiroEeprom\(string path\)", "SetupChihiroEeprom")
|
||||
body = src.block_at(setup.end())
|
||||
folder = src.find(
|
||||
r'string savePath = Path\.Combine\(AppConfig\.GetFullPath\("saves"\), "(\w+)"\);',
|
||||
"Chihiro save folder",
|
||||
body[0],
|
||||
body[1],
|
||||
)
|
||||
pair = src.find(
|
||||
r'_chihiroEeprom = Path\.Combine\(path, "([^"]+)"\);\s*'
|
||||
r'_chihiroEepromSave = Path\.Combine\(savePath, "\1"\);',
|
||||
"Chihiro EEPROM pair",
|
||||
folder.end(),
|
||||
body[1],
|
||||
)
|
||||
save = src.find(r"private void SaveChihiroEeprom\(\)", "SaveChihiroEeprom")
|
||||
save_body = src.block_at(save.end())
|
||||
records.append(
|
||||
_record(
|
||||
"xemu, xemu-chihiro",
|
||||
"standalone",
|
||||
"copies",
|
||||
[pair.group(1)],
|
||||
source_ref(
|
||||
(
|
||||
src.path,
|
||||
[
|
||||
src.lines(chihiro.start(), chihiro.end()),
|
||||
src.statement_span(body),
|
||||
src.statement_span(save_body),
|
||||
],
|
||||
)
|
||||
),
|
||||
case_insensitive=True,
|
||||
search_dir=f"saves/{folder.group(1)}",
|
||||
passes_to=(
|
||||
f"<emulator>/{pair.group(1)}, restored when the saved copy is newer or the"
|
||||
" emulator folder holds none, copied back after the run"
|
||||
),
|
||||
fails_when_missing=False,
|
||||
depends_on_option=chihiro_when,
|
||||
)
|
||||
)
|
||||
|
||||
store = src.find(
|
||||
r'string savePath = Path\.Combine\(AppConfig\.GetFullPath\("saves"\), "(\w+)"\);\s*'
|
||||
r'if \(!Directory\.Exists\(savePath\)\) try \{ Directory\.CreateDirectory\(savePath\); \} catch \{ \}\s*'
|
||||
r'if \(Directory\.Exists\(savePath\)\)\s*'
|
||||
r'ini\.WriteValue\("([\w.]+)", "(\w+)", "\'" \+ Path\.Combine\(savePath, "([^"]+)"\)',
|
||||
"Chihiro snapshot store",
|
||||
)
|
||||
records.append(
|
||||
_record(
|
||||
"xemu, xemu-chihiro",
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[store.group(4)],
|
||||
source_ref((src.path, [src.lines(chihiro.start(), chihiro.end()),
|
||||
src.lines(store.start(), store.end())])),
|
||||
case_insensitive=True,
|
||||
search_dir=f"saves/{store.group(1)}",
|
||||
passes_to=f"xemu.toml [{store.group(2)}] {store.group(3)}, created by the emulator",
|
||||
fails_when_missing=False,
|
||||
depends_on_option=chihiro_when,
|
||||
)
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
# What the Cxbx generator hands each build: the data folder is the one its
|
||||
# settings.ini sits in (Cxbx-Reloaded Settings::FindSettingsLocation), which
|
||||
# the launcher writes beside the binary.
|
||||
CXBX_DATA_FOLDER = "Settings::GetDataLocation"
|
||||
|
||||
|
||||
def cxbx(sources: dict[str, Source]) -> list[Record]:
|
||||
"""The folder each Cxbx build runs from, and the EEPROM written there.
|
||||
|
||||
The generator picks the emulator folder by core or emulator name, opens
|
||||
settings.ini in it, and for an Xbox writes EEPROM.bin into the
|
||||
cxbx-reloaded folder from its own resource when absent.
|
||||
"""
|
||||
src = sources[f"{GENERATORS}/Cxbx.Generator.cs"]
|
||||
named = src.find_all(
|
||||
r'(?:else )?if \(\(core != null && core == "([\w-]+)"\) \|\| '
|
||||
r'\(emulator != null && emulator == "\1"\)\)\s*\{\s*path = AppConfig\.GetFullPath\("([\w-]+)"\);',
|
||||
"emulator folder by name",
|
||||
)
|
||||
fallbacks = src.find_all(
|
||||
r'if \(string\.IsNullOrEmpty\(path\)\)\s*path = AppConfig\.GetFullPath\("([\w-]+)"\);',
|
||||
"default emulator folder",
|
||||
)
|
||||
settings = src.find(
|
||||
r'IniFile\.FromFile\(Path\.Combine\(path, "(settings\.ini)"\)', "settings.ini beside the binary"
|
||||
)
|
||||
settings_span = src.lines(settings.start(), settings.end())
|
||||
passes_to = (
|
||||
f"{CXBX_DATA_FOLDER}, the folder holding {settings.group(1)},"
|
||||
" which the launcher writes beside the binary"
|
||||
)
|
||||
records = []
|
||||
for match in named:
|
||||
records.append(
|
||||
_record(
|
||||
match.group(1),
|
||||
"standalone",
|
||||
"passes_path",
|
||||
[],
|
||||
source_ref((src.path, [src.lines(match.start(), match.end()), settings_span])),
|
||||
search_dir=f'<AppConfig.GetFullPath("{match.group(2)}")>',
|
||||
passes_to=passes_to,
|
||||
fails_when_missing=False,
|
||||
)
|
||||
)
|
||||
first, *rest = fallbacks
|
||||
others = "neither core nor emulator is " + " or ".join(f'"{m.group(1)}"' for m in named)
|
||||
records.append(
|
||||
_record(
|
||||
first.group(1),
|
||||
"standalone",
|
||||
"passes_path",
|
||||
[],
|
||||
source_ref(
|
||||
(
|
||||
src.path,
|
||||
[src.lines(first.start(), first.end()),
|
||||
*(src.lines(m.start(), m.end()) for m in rest), settings_span],
|
||||
)
|
||||
),
|
||||
search_dir=f'<AppConfig.GetFullPath("{first.group(1)}")>',
|
||||
passes_to=passes_to,
|
||||
fails_when_missing=False,
|
||||
depends_on_option=_joined(
|
||||
others,
|
||||
*(f'<AppConfig.GetFullPath("{m.group(1)}")> when "{first.group(1)}" is not set'
|
||||
for m in rest),
|
||||
),
|
||||
)
|
||||
)
|
||||
records.extend(_cxbx_mount(src, [*(m.group(1) for m in named), first.group(1)]))
|
||||
eeprom = src.find(
|
||||
r'if \(system == "(\w+)"\)\s*\{\s*string (\w+) = Path\.Combine\(AppConfig\.GetFullPath\("([\w-]+)"\), "([^"]+)"\);'
|
||||
r'\s*if \(!File\.Exists\(\2\)\)\s*File\.WriteAllBytes\(\2, Properties\.Resources\.(\w+)\);'
|
||||
r'\s*WriteXboxEEPROM\(\2\);\s*\}',
|
||||
"EEPROM written from resources",
|
||||
)
|
||||
records.append(
|
||||
_record(
|
||||
eeprom.group(3),
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[eeprom.group(4)],
|
||||
source_ref((src.path, [src.lines(eeprom.start(), eeprom.end())])),
|
||||
case_insensitive=True,
|
||||
search_dir=f'<AppConfig.GetFullPath("{eeprom.group(3)}")>',
|
||||
passes_to=(
|
||||
f"written from the launcher's {eeprom.group(5)} resource when absent,"
|
||||
" then its language set: the emulator reads it from its data folder"
|
||||
),
|
||||
fails_when_missing="never missing: the launcher writes it",
|
||||
depends_on_option=f'system == "{eeprom.group(1)}"',
|
||||
)
|
||||
)
|
||||
return records
|
||||
|
||||
|
||||
def _cxbx_mount(src: Source, emulators: list[str]) -> list[Record]:
|
||||
"""What the generator needs to mount an .iso before Cxbx opens it: its
|
||||
own xbox-iso-vfs.exe, run from the launcher's folder, and the Dokan 2
|
||||
runtime installed on the system."""
|
||||
iso = src.find(
|
||||
r'if \(Path\.GetExtension\(rom\)\.ToLowerInvariant\(\) != "(\.\w+)"\)\s*return rom;',
|
||||
"mount for disc images only",
|
||||
)
|
||||
vfs = src.find(
|
||||
r'string (\w+) = Path\.Combine\(Path\.GetDirectoryName\(typeof\(\w+\)\.Assembly\.Location\), "([^"]+)"\);'
|
||||
r'\s*if \(!File\.Exists\(\1\)\)\s*throw new ApplicationException\("([^"]+)"\);',
|
||||
"mount tool beside the launcher",
|
||||
iso.end(),
|
||||
)
|
||||
dokan = src.find(
|
||||
r'string (\w+) = Environment\.GetEnvironmentVariable\("(\w+)"\);.*?'
|
||||
r'\1 = Path\.Combine\(\1, "([^"]+)"\);\s*if \(!File\.Exists\(\1\)\)\s*\{[^{}]*?'
|
||||
r'throw new ApplicationException\("([^"]+)"\);\s*\}',
|
||||
"Dokan runtime check",
|
||||
vfs.end(),
|
||||
flags=re.S,
|
||||
)
|
||||
iso_span = src.lines(iso.start(), iso.end())
|
||||
when = f'rom extension "{iso.group(1)}"'
|
||||
emulator = ", ".join(emulators)
|
||||
return [
|
||||
_record(
|
||||
emulator,
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[vfs.group(2)],
|
||||
source_ref((src.path, [iso_span, src.lines(vfs.start(), vfs.end())])),
|
||||
case_insensitive=True,
|
||||
search_dir="<emulatorLauncher folder>",
|
||||
passes_to="exec",
|
||||
fails_when_missing=vfs.group(3),
|
||||
depends_on_option=when,
|
||||
),
|
||||
_record(
|
||||
emulator,
|
||||
"standalone",
|
||||
"fixed_name",
|
||||
[dokan.group(3)],
|
||||
source_ref((src.path, [iso_span, src.lines(dokan.start(), dokan.end())])),
|
||||
case_insensitive=True,
|
||||
search_dir=f"%{dokan.group(2)}%",
|
||||
passes_to=f"nothing passed: checked before {vfs.group(2)} mounts the image",
|
||||
fails_when_missing=dokan.group(4),
|
||||
depends_on_option=when,
|
||||
),
|
||||
]
|
||||
|
||||
|
||||
def openmsx(sources: dict[str, Source]) -> list[Record]:
|
||||
src = sources[f"{GENERATORS}/OpenMSX.Generator.cs"]
|
||||
table = src.find(
|
||||
@@ -3521,6 +3803,7 @@ EXTRACTORS: tuple[Callable[[dict[str, Source]], list[Record]], ...] = (
|
||||
blastem,
|
||||
bsyndrome,
|
||||
capsimg,
|
||||
cxbx,
|
||||
demul,
|
||||
desmume,
|
||||
dolphin,
|
||||
@@ -3551,6 +3834,7 @@ EXTRACTORS: tuple[Callable[[dict[str, Source]], list[Record]], ...] = (
|
||||
value_folders,
|
||||
winuae,
|
||||
xemu,
|
||||
xemu_saves,
|
||||
xm6pro,
|
||||
xroar,
|
||||
)
|
||||
|
||||
Reference in new issue
Block a user