mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-11-01 07:33:45 -06:00
chore: merge origin/main into the campaign work
This commit is contained in:
commit
5f3c836db9
26 files changed
+223
-135
No files matched your search
@@ -62,10 +62,13 @@ permissions:
|
||||
pull-requests: write
|
||||
|
||||
concurrency:
|
||||
# A push series collapses to the tip: what has to stay verified is the head
|
||||
# of main, not every commit that passed under it.
|
||||
# A run on main finishes before the next starts: with three sessions pushing
|
||||
# every 25 minutes and a 40-minute suite, cancelling left main with no
|
||||
# finished run at all. GitHub keeps one pending run per group and replaces
|
||||
# it with each newer push, so main gets a finished run and then its tip,
|
||||
# never a growing queue. A pull request still collapses to its latest push.
|
||||
group: validate-${{ github.event.pull_request.number || github.ref }}
|
||||
cancel-in-progress: true
|
||||
cancel-in-progress: ${{ github.event_name == 'pull_request' }}
|
||||
|
||||
jobs:
|
||||
validate-bios:
|
||||
|
||||
BIN
Binary file not shown.
Binary file not shown.
+30
-30
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schema_version": 1,
|
||||
"generated_at": "2026-10-26T22:11:28Z",
|
||||
"generated_at": "2026-10-27T10:27:58Z",
|
||||
"total_files": 19916,
|
||||
"total_size": 16892318346,
|
||||
"bios_dir": "bios",
|
||||
@@ -196896,15 +196896,15 @@
|
||||
"crc32": "f2dde5c7",
|
||||
"adler32": "4a48e7f1"
|
||||
},
|
||||
"f7171b2a8f1c464696771941225c32d636b59349": {
|
||||
"path": "bios/Sega/Saturn/.variants/mpeg_card.bin.821af2bd",
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652": {
|
||||
"path": "bios/Sega/Saturn/.variants/mpeg_card.bin.b3841bb9",
|
||||
"name": "mpeg_card.bin",
|
||||
"size": 524288,
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"md5": "821af2bdf04d9016a4149245f3bed058",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"crc32": "9688c629",
|
||||
"adler32": "e395666e"
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"md5": "b3841bb91201eee6c0db229b2c66d54c",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"crc32": "192e52c2",
|
||||
"adler32": "512b434c"
|
||||
},
|
||||
"bb6459da484864226616c5d45b779d4b1644c527": {
|
||||
"path": "bios/Sega/Saturn/.variants/mpeg_card.bin.b60e8866",
|
||||
@@ -197077,15 +197077,15 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652": {
|
||||
"f7171b2a8f1c464696771941225c32d636b59349": {
|
||||
"path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"name": "mpeg_card.bin",
|
||||
"size": 524288,
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"md5": "b3841bb91201eee6c0db229b2c66d54c",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"crc32": "192e52c2",
|
||||
"adler32": "512b434c"
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"md5": "821af2bdf04d9016a4149245f3bed058",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"crc32": "9688c629",
|
||||
"adler32": "e395666e"
|
||||
},
|
||||
"8a22710e09ce75f39625894366cafe503ed1942d": {
|
||||
"path": "bios/Sega/Saturn/mpr-18100.bin",
|
||||
@@ -223787,7 +223787,7 @@
|
||||
"0306c0e408d6682dd2d86324bd4ac661": "8c031bf9908fd0142fdd10a9cdd79389f8a3f2fc",
|
||||
"3fee63d472f171e42220549768b6040a": "eaac576b8b5e79e7df5e3efd70275b220ff70d78",
|
||||
"80179c493258d4ebbfc1091910bbbcd9": "567f82a31d5f93676120d699869b3ca64995e167",
|
||||
"821af2bdf04d9016a4149245f3bed058": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"b3841bb91201eee6c0db229b2c66d54c": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"b60e88665fe63a49ce2629e8a3a01e4c": "bb6459da484864226616c5d45b779d4b1644c527",
|
||||
"b74508128abcc2aea6e449e90044740f": "286f2c75b1a5bb9d7df23db9f0a381e61b1ac76c",
|
||||
"ee821d3f07b4af6168876bc64673e6cb": "40f284e79f205728b72c7d7c0cf0bae0ade38f76",
|
||||
@@ -223803,7 +223803,7 @@
|
||||
"2eaec1ef88f3596c2cb56190a49dfe25": "b3c20fbe57cd2eb595e9edac86817e5948dccae4",
|
||||
"1f4ccf420e2189207bf018f2f5369c44": "f4f6c2aac68c352814d396ae41f81f54ad228e68",
|
||||
"3ea3202e2634cb47cb90f3a05c015010": "49d8493008fa715ca0c94d99817a5439d6f2c796",
|
||||
"b3841bb91201eee6c0db229b2c66d54c": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"821af2bdf04d9016a4149245f3bed058": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"cb2cebc1b6e573b7c44523d037edcd45": "8a22710e09ce75f39625894366cafe503ed1942d",
|
||||
"7c8a9c44c1d5ce607ccfc0794ec4f1b4": "b9645d265644d201dbccc39aaf4bfa60cebe7ead",
|
||||
"74570fed4d44b2682b560c8cd44b8b6a": "7b23b53d62de0f29a23e423d0fe751dfb469c2fa",
|
||||
@@ -273528,12 +273528,12 @@
|
||||
"mpeg_card.bin": [
|
||||
"eaac576b8b5e79e7df5e3efd70275b220ff70d78",
|
||||
"567f82a31d5f93676120d699869b3ca64995e167",
|
||||
"f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"bb6459da484864226616c5d45b779d4b1644c527",
|
||||
"286f2c75b1a5bb9d7df23db9f0a381e61b1ac76c",
|
||||
"40f284e79f205728b72c7d7c0cf0bae0ade38f76",
|
||||
"88aa35e48e655540e87ebeae10220413a8feee81",
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
],
|
||||
"SAT_1.00-(U+E).bin": [
|
||||
"faa8ea183a6d7bbe5d4e03bb1332519800d3fbc3"
|
||||
@@ -301577,7 +301577,7 @@
|
||||
"6abfefea": "8c031bf9908fd0142fdd10a9cdd79389f8a3f2fc",
|
||||
"ef9d13ef": "eaac576b8b5e79e7df5e3efd70275b220ff70d78",
|
||||
"f2dde5c7": "567f82a31d5f93676120d699869b3ca64995e167",
|
||||
"9688c629": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"192e52c2": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"afe194aa": "bb6459da484864226616c5d45b779d4b1644c527",
|
||||
"badf129d": "286f2c75b1a5bb9d7df23db9f0a381e61b1ac76c",
|
||||
"f9ca3180": "40f284e79f205728b72c7d7c0cf0bae0ade38f76",
|
||||
@@ -301593,7 +301593,7 @@
|
||||
"3681d3b0": "b3c20fbe57cd2eb595e9edac86817e5948dccae4",
|
||||
"1c8b9f38": "f4f6c2aac68c352814d396ae41f81f54ad228e68",
|
||||
"721e1b60": "49d8493008fa715ca0c94d99817a5439d6f2c796",
|
||||
"192e52c2": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"9688c629": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"3408dbf4": "8a22710e09ce75f39625894366cafe503ed1942d",
|
||||
"1057fc63": "b9645d265644d201dbccc39aaf4bfa60cebe7ead",
|
||||
"b3c63c25": "7b23b53d62de0f29a23e423d0fe751dfb469c2fa",
|
||||
@@ -321495,7 +321495,7 @@
|
||||
"37561c4444bec52ae1aae31de5579f1856d5b23002ee083ade42f9ed13c8616f": "8c031bf9908fd0142fdd10a9cdd79389f8a3f2fc",
|
||||
"5818c2d614d35d7620800ef82b9dc8b17cc4605cc4fbc5250e490101b3901174": "eaac576b8b5e79e7df5e3efd70275b220ff70d78",
|
||||
"227790140028f27d8bdf69e9fe390681b89909082ec935084b193221f087c876": "567f82a31d5f93676120d699869b3ca64995e167",
|
||||
"395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"7227c28b604efa812586426d8a5edc829750b5ff92096301fc75ab2fe67bc1b8": "bb6459da484864226616c5d45b779d4b1644c527",
|
||||
"095db77077f306a2b83b7d0d448a68b4b5e60f0de8c94530e35d1f1b2da78e1e": "286f2c75b1a5bb9d7df23db9f0a381e61b1ac76c",
|
||||
"43c2fac85f2dcfad0d9699ca3b3003a7dd42ec6a2ca11132e2e20ea29bfdec95": "40f284e79f205728b72c7d7c0cf0bae0ade38f76",
|
||||
@@ -321511,7 +321511,7 @@
|
||||
"2dfb3618b5b612bb49abbf0d1d8d53016908bb81aa8c92515f0836203e0b7f1c": "b3c20fbe57cd2eb595e9edac86817e5948dccae4",
|
||||
"c488cd91cbf35392047faf7fcaf9faeb96d72fc9c8f5a5039d82eca59573dcc0": "f4f6c2aac68c352814d396ae41f81f54ad228e68",
|
||||
"feb733e0a1578eb8a6ff9c7f32b0b7319336bcf98f461a5f608e73159f672f4e": "49d8493008fa715ca0c94d99817a5439d6f2c796",
|
||||
"d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"1d964171c979f87ca120d77fdb0d98063bb75bfa219bb180aeb650c528ce054e": "8a22710e09ce75f39625894366cafe503ed1942d",
|
||||
"76982109ed433d512413044d7c5bc869f6d97e2826f5ac10cc7418fb3fff1ab3": "b9645d265644d201dbccc39aaf4bfa60cebe7ead",
|
||||
"cc1e1b7f88f1c6e6fc35994bae2c2292e06fdae258c79eb26a1f1391e72914a8": "7b23b53d62de0f29a23e423d0fe751dfb469c2fa",
|
||||
@@ -563858,14 +563858,14 @@
|
||||
".variants/mpeg_card.bin.80179c49": [
|
||||
"567f82a31d5f93676120d699869b3ca64995e167"
|
||||
],
|
||||
"Sega/Saturn/.variants/mpeg_card.bin.821af2bd": [
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
"Sega/Saturn/.variants/mpeg_card.bin.b3841bb9": [
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
],
|
||||
"Saturn/.variants/mpeg_card.bin.821af2bd": [
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
"Saturn/.variants/mpeg_card.bin.b3841bb9": [
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
],
|
||||
".variants/mpeg_card.bin.821af2bd": [
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
".variants/mpeg_card.bin.b3841bb9": [
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
],
|
||||
"Sega/Saturn/.variants/mpeg_card.bin.b60e8866": [
|
||||
"bb6459da484864226616c5d45b779d4b1644c527"
|
||||
@@ -563985,10 +563985,10 @@
|
||||
"49d8493008fa715ca0c94d99817a5439d6f2c796"
|
||||
],
|
||||
"Sega/Saturn/mpeg_card.bin": [
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
],
|
||||
"Saturn/mpeg_card.bin": [
|
||||
"2f5ebd434f6d5b82e93d03e5626007bd5380f652"
|
||||
"f7171b2a8f1c464696771941225c32d636b59349"
|
||||
],
|
||||
"Sega/Saturn/mpr-18100.bin": [
|
||||
"8a22710e09ce75f39625894366cafe503ed1942d"
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
||||
$defaultInstallSha256 = "b3363820bb97bec559287f72d9712281e22307387fa752b663f6f7af023a0e33"
|
||||
$defaultInstallSha256 = "cc940a96dea46fb43d3940a13fddb4c9f1c02b8d81d1c810bcbddd5120143ce4"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+16
-5
@@ -4468,15 +4468,19 @@ def _check_holder(holder: Path) -> os.stat_result:
|
||||
|
||||
A link would send them wherever it points. On a system with user ids, a
|
||||
folder another user owns was not made by this user's runs, and its owner
|
||||
could read or swap what is moved in. Returns what was checked, so the
|
||||
caller can confirm the same folder is still there once it has written
|
||||
into it.
|
||||
could read or swap what is moved in. A storage that keeps no owner per
|
||||
file gives every file one owner: Android's shared storage shows a folder
|
||||
Termux has just made as another user's, as does a FAT card. A holder
|
||||
owned like the folder it sits in is that storage's owner, not someone
|
||||
else's folder. Returns what was checked, so the caller can confirm the
|
||||
same folder is still there once it has written into it.
|
||||
"""
|
||||
info = os.lstat(holder)
|
||||
if not stat.S_ISDIR(info.st_mode):
|
||||
raise OSError(errno.ELOOP, f"{holder} is a link or not a folder")
|
||||
getuid = getattr(os, "getuid", None)
|
||||
if getuid is not None and info.st_uid != getuid():
|
||||
if (getuid is not None and info.st_uid != getuid()
|
||||
and info.st_uid != os.lstat(holder.parent).st_uid):
|
||||
raise OSError(errno.EPERM, f"{holder} belongs to another user")
|
||||
return info
|
||||
|
||||
@@ -5497,6 +5501,12 @@ def _report_outcome(
|
||||
"(or delete them), then run again.")
|
||||
if any(isinstance(reason, NetworkReason) for _dest, reason in failures or []):
|
||||
advice.append(NETWORK_FAILURE_ADVICE)
|
||||
if any(str(reason).startswith(NOT_KEPT) for _dest, reason in failures or []):
|
||||
# The same run fails the same way: "retry only those" sent a phone
|
||||
# user round the loop with nothing changed.
|
||||
advice.append(" The files in place were left as they were, as no backup folder could "
|
||||
"be made for them. Move them out of the folder, then run again to "
|
||||
"install the new ones.")
|
||||
paths = paths + [folder for folder in elsewhere if folder not in paths]
|
||||
|
||||
if offline:
|
||||
@@ -5554,7 +5564,8 @@ def _report_outcome(
|
||||
print(f"Location: {_locations(paths)}")
|
||||
for line in kept + advice:
|
||||
print(line)
|
||||
print("Run the same command again to retry only those.")
|
||||
if not all(str(reason).startswith(NOT_KEPT) for _dest, reason in failures or []):
|
||||
print("Run the same command again to retry only those.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"\nDone. {_plural(downloaded, 'file')} installed, "
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ esac
|
||||
TEMP_INSTALLER=""
|
||||
TEMP_DIRECTORY=""
|
||||
DEFAULT_INSTALL_URL="https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
||||
DEFAULT_INSTALL_SHA256="b3363820bb97bec559287f72d9712281e22307387fa752b663f6f7af023a0e33"
|
||||
DEFAULT_INSTALL_SHA256="cc940a96dea46fb43d3940a13fddb4c9f1c02b8d81d1c810bcbddd5120143ce4"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "batocera",
|
||||
"display_name": "Batocera",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -179639,8 +179639,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "emudeck",
|
||||
"display_name": "EmuDeck",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -69437,8 +69437,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "emuelec",
|
||||
"display_name": "EmuELEC",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "",
|
||||
"detect": [
|
||||
{
|
||||
@@ -46931,8 +46931,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "bios/mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
"platform": "knulli",
|
||||
"display_name": "KNULLI",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -111758,8 +111758,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
+3
-3
@@ -6,7 +6,7 @@
|
||||
"platform": "lakka",
|
||||
"display_name": "Lakka",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "system",
|
||||
"detect": [
|
||||
{
|
||||
@@ -84627,8 +84627,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -27,8 +27,8 @@
|
||||
{
|
||||
"dest": "roms/ports/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 734772,
|
||||
"sha256": "b3363820bb97bec559287f72d9712281e22307387fa752b663f6f7af023a0e33",
|
||||
"size": 735645,
|
||||
"sha256": "cc940a96dea46fb43d3940a13fddb4c9f1c02b8d81d1c810bcbddd5120143ce4",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -71,8 +71,8 @@
|
||||
"muos": {
|
||||
"archive": {
|
||||
"dest": "ARCHIVE/RetroBIOS.muxapp",
|
||||
"size": 787321,
|
||||
"sha256": "45366e0a225d8143f7b359fd04cd6b341a21f43057b7d5a41ad8f734f765f142"
|
||||
"size": 788194,
|
||||
"sha256": "3a9bc441d4178cc15833dc8a3f28877370b4075a05131d209208186247756cc7"
|
||||
},
|
||||
"members": [
|
||||
{
|
||||
@@ -92,8 +92,8 @@
|
||||
{
|
||||
"name": "RetroBIOS/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 734772,
|
||||
"sha256": "b3363820bb97bec559287f72d9712281e22307387fa752b663f6f7af023a0e33",
|
||||
"size": 735645,
|
||||
"sha256": "cc940a96dea46fb43d3940a13fddb4c9f1c02b8d81d1c810bcbddd5120143ce4",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
@@ -166,8 +166,8 @@
|
||||
{
|
||||
"dest": ".config/modules/retrobios/install.py",
|
||||
"repo_path": "install.py",
|
||||
"size": 734772,
|
||||
"sha256": "b3363820bb97bec559287f72d9712281e22307387fa752b663f6f7af023a0e33",
|
||||
"size": 735645,
|
||||
"sha256": "cc940a96dea46fb43d3940a13fddb4c9f1c02b8d81d1c810bcbddd5120143ce4",
|
||||
"executable": false
|
||||
},
|
||||
{
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "recalbox",
|
||||
"display_name": "Recalbox",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -38837,8 +38837,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "retroarch",
|
||||
"display_name": "RetroArch",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "system",
|
||||
"detect": [
|
||||
{
|
||||
@@ -85540,8 +85540,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "retrobat",
|
||||
"display_name": "RetroBat",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -46377,8 +46377,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "retrodeck",
|
||||
"display_name": "RetroDECK",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "",
|
||||
"detect": [
|
||||
{
|
||||
@@ -118462,8 +118462,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "bios/mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "retropie",
|
||||
"display_name": "RetroPie",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "BIOS",
|
||||
"detect": [
|
||||
{
|
||||
@@ -90887,8 +90887,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"platform": "rocknix",
|
||||
"display_name": "ROCKNIX",
|
||||
"version": "1.0",
|
||||
"generated": "2026-10-26T22:11:28Z",
|
||||
"generated": "2026-10-27T10:27:58Z",
|
||||
"base_destination": "bios",
|
||||
"detect": [
|
||||
{
|
||||
@@ -55411,8 +55411,8 @@
|
||||
},
|
||||
{
|
||||
"dest": "mpeg_card.bin",
|
||||
"sha1": "2f5ebd434f6d5b82e93d03e5626007bd5380f652",
|
||||
"sha256": "d4bac489d59bf9bfd05fab4f647df66a087f0fd0bbb9f0a8b3c55cdcf51048de",
|
||||
"sha1": "f7171b2a8f1c464696771941225c32d636b59349",
|
||||
"sha256": "395835dba2a3356909de9dca7f03212e9deb747062c4c75448ab55c27f294429",
|
||||
"size": 524288,
|
||||
"repo_path": "bios/Sega/Saturn/mpeg_card.bin",
|
||||
"cores": [
|
||||
|
||||
@@ -4,3 +4,4 @@
|
||||
{"check":{"claim":"The mpeg_card.bin image Beetle Saturn loads changes what the Saturn BIOS shows and does for a Video CD.","method":"Saturn BIOS v1.01 (Japan), region forced to Japan, Video CD Card option enabled, automatic RTC left on and the host clock running (no libfaketime), to test whether runs repeat, the authored Video CD inserted. 3000 frames; Saturn A (libretro B) held 15 frames from frame 1300, which is Play on the BIOS CD player, and Start 15 frames from frame 1900. Repeated with each mpeg_card.bin image, with no file, with 512 KiB of zeros and with a 1-byte file; every other input is identical. Each variant runs twice in fresh processes.","observable":"video_sha1","result":{"groups":[{"value":"bde95c486614dc797ba5a939fb738d947b479fa8","variants":["mpeg_card.bin"]},{"value":"5a14993408a486a4c55341ca7284f89e148dfc18","variants":["mpeg_card.bin.3fee63d4"]},{"value":"7e3d403552c31c494beb9847262bf86cf266c3fa","variants":["mpeg_card.bin.80179c49"]},{"value":"b639d8c3130638876b398c66f463b98f535a2497","variants":["mpeg_card.bin.821af2bd"]},{"value":"5dd8db90027d8ef7670c0805751b8973920195a9","variants":["mpeg_card.bin.b60e8866"]},{"value":"fabe749bf34c09de4c26d4328e2744876488a18e","variants":["mpeg_card.bin.b7450812"]},{"value":"ef9d0fab7815222344d7d669bd0dbc6e0d811174","variants":["mpeg_card.bin.ee821d3f"]},{"value":"164f2e824cc15672226bebc07998f40d5e3422ce","variants":["mpeg_card.bin.ef9de845"]},{"value":"1c920f21c6fc3d402fa45a7a5fb4d302a82d4898","variants":["mpeg_card.bin-absent"]},{"value":"2a6d6e171b0bafe5b60ec41a37db4322ff2b12e8","variants":["zeros_512k.bin"]},{"value":"2d5be7af25846153e20081a8b12b614ff348c4b9","variants":["one_byte.bin"]}],"statement":"video_sha1 is not settled in 11 of 11 variants (mpeg_card.bin, mpeg_card.bin.3fee63d4, mpeg_card.bin.80179c49, mpeg_card.bin.821af2bd, mpeg_card.bin.b60e8866, mpeg_card.bin.b7450812, mpeg_card.bin.ee821d3f, mpeg_card.bin.ef9de845, mpeg_card.bin-absent, zeros_512k.bin, one_byte.bin): no comparison is drawn","status":"inconclusive"},"variable":"mpeg_card.bin"},"core":{"build_command":"make -j8","commit":"2ce77e20a956dc9a67b8d3d527f477b984310feb","compiler":["GCC: (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0"],"file":"mednafen_saturn_libretro.so","library_name":"Beetle Saturn","library_version":"v1.32.1","repo":"https://github.com/libretro/beetle-saturn-libretro","sha256":"6e9a44698a2eee492e8d7eff67f2bd5634f52de8cc1af7885f334c3f29fcf2bd"},"emulator":"beetle_saturn","flags":["mpeg_card.bin: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.3fee63d4: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.80179c49: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.821af2bd: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.b60e8866: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.b7450812: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.ee821d3f: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin.ef9de845: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","mpeg_card.bin-absent: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","zeros_512k.bin: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1","one_byte.bin: repetition 1 disagrees with repetition 0 on frame_hashes, frame_sha1, state_sha1, video_sha1"],"frontend":{"commit":"8b12685c1652732828c146336a14a5fc265fffd3","script":"scripts/core_probe.py","script_modified":false,"script_sha256":"a95ab54a8d8f9ecc5dc2a55fd0ab93ffc66fe6466e2d89eea56a1a95c17d858b"},"host":{"cpu_count":12,"cpu_model":"13th Gen Intel(R) Core(TM) i9-13900K","kernel":"6.18.54.1-microsoft-standard-WSL2","load_after":[1.77,2.58,4.32],"load_before":[1.81,3.2,4.89],"machine":"x86_64","max_load":6.0,"os":"Linux-6.18.54.1-microsoft-standard-WSL2-x86_64-with-glibc2.39","python":"3.12.3"},"id":"2026-10-27-bf3d8283b265","inputs":{"content":{"label":"authored Video CD: Big Buck Bunny 60 s, NTSC VCD 2.0 (identity.json beside the image)","sha1":"150cfb81d3c844f0721f2864073a33e326492d46","size":172,"tracks":[{"file":"bbb_vcd.bin","sha1":"e7952e60928dba7f3ceb6c3316894f96ad24e175","size":12169248}]},"env":{},"frame_hash_every":150,"frames":3000,"joypad_ports":2,"observables":["frame_sha1","video_sha1","audio_sha1","state_sha1","state:MPEG.AuthState","state:MPEG.Present","frame_hashes"],"options":{"beetle_saturn_mpeg_card":"enabled","beetle_saturn_region":"Japan"},"presses":[{"button":0,"frame":1300,"length":15},{"button":3,"frame":1900,"length":15}],"repetitions":2,"warmup":0},"kind":"check","migrated_from_version":1,"recorLine truncated
|
||||
{"check":{"claim":"The mpeg_card.bin image Beetle Saturn loads decides whether Lunar - Silver Star Story MPEG (T-27904G) detects the Video CD Card and plays its movies.","method":"Saturn BIOS v1.01 (Japan), Video CD Card option enabled, region auto-detected from the disc (Japan), host clock frozen at 2000-01-01 00:00:00 by libfaketime 0.9.10 so runs are deterministic. 4800 frames; Start held 15 frames at frames 2400, 3000, 3600 and 4200. Repeated with each mpeg_card.bin image, with no file, with 512 KiB of zeros and with a 1-byte file; every other input is identical. Each variant runs twice in fresh processes.","observable":"video_sha1","result":{"groups":[{"value":"e248465e55f8edbdfb16a8ca6588817ffa9d8064","variants":["mpeg_card.bin","mpeg_card.bin.3fee63d4","mpeg_card.bin.80179c49","mpeg_card.bin.821af2bd","mpeg_card.bin.b60e8866","mpeg_card.bin.b7450812","mpeg_card.bin.ee821d3f","mpeg_card.bin.ef9de845","mpeg_card.bin-absent","zeros_512k.bin","one_byte.bin"]}],"statement":"video_sha1 is identical across all 11 variants","status":"same"},"variable":"mpeg_card.bin"},"core":{"build_command":"make -j8","commit":"2ce77e20a956dc9a67b8d3d527f477b984310feb","compiler":["GCC: (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0"],"file":"mednafen_saturn_libretro.so","library_name":"Beetle Saturn","library_version":"v1.32.1","repo":"https://github.com/libretro/beetle-saturn-libretro","sha256":"6e9a44698a2eee492e8d7eff67f2bd5634f52de8cc1af7885f334c3f29fcf2bd"},"emulator":"beetle_saturn","flags":[],"frontend":{"commit":"8b12685c1652732828c146336a14a5fc265fffd3","script":"scripts/core_probe.py","script_modified":false,"script_sha256":"a95ab54a8d8f9ecc5dc2a55fd0ab93ffc66fe6466e2d89eea56a1a95c17d858b"},"host":{"cpu_count":12,"cpu_model":"13th Gen Intel(R) Core(TM) i9-13900K","kernel":"6.18.54.1-microsoft-standard-WSL2","load_after":[3.16,2.62,3.83],"load_before":[1.77,2.58,4.32],"machine":"x86_64","max_load":6.0,"os":"Linux-6.18.54.1-microsoft-standard-WSL2-x86_64-with-glibc2.39","python":"3.12.3"},"id":"2026-10-27-5d8f0b375830","inputs":{"content":{"label":"Redump: Lunar - Silver Star Story Complete (Japan), T-27904G V1.00 (cue sha1 7a609a9b579de648197ccfb5ab7bf4b3beb07d95)","sha1":"7a609a9b579de648197ccfb5ab7bf4b3beb07d95","size":554,"tracks":[{"file":"Lunar - Silver Star Story Complete (Japan) (Track 1).bin","sha1":"b6d71e1c96211af46d83278eccf7d6827a57d004","size":83710032},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 2).bin","sha1":"c2406d2953cec7f9fe5826aa71c7359c2baeb3a7","size":491934912},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 3).bin","sha1":"71c3bcfc22038d0f25126b34f703aa464259cfb5","size":25867296},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 4).bin","sha1":"b9c73d3890cd699cb1718131c2f7f04897a14d65","size":1872192}]},"env":{"FAKETIME":"2000-01-01 00:00:00","FAKETIME_DONT_FAKE_MONOTONIC":"1","LD_PRELOAD":"libfaketime.so.1 sha256:7ac8a1cdff1b627548de11513fddedd75014f5b041e9ae9054a634bb04aa7982"},"frame_hash_every":300,"frames":4800,"joypad_ports":2,"observables":["frame_sha1","video_sha1","audio_sha1","state_sha1","state:MPEG.AuthState","state:MPEG.Present","frame_hashes"],"options":{"beetle_saturn_mpeg_card":"enabled"},"presses":[{"button":3,"frame":2400,"length":15},{"button":3,"frame":3000,"length":15},{"button":3,"frame":3600,"length":15},{"button":3,"frame":4200,"length":15}],"repetitions":2,"warmup":0},"kind":"check","migrated_from_version":1,"record_version":3,"recorded_at":"2026-10-27T05:26:27+00:00","subject":"mpeg-card-lunar","supersedes":null,"variants":[{"flags":[],"label":"mpeg_card.bin","repetitions":[{"env_unanswered":{"11":1,"13":1,"28":1,"35":3,"37":1,"40":4799,"45":4,"46":1,"47":4800,"51":1,"55":2,"57":1,"8":1,"87":1},"files_opened":[{"path":"sega_101.bin","sha1_after":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720","sha1_staged":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720"},{"path":"mpeg_card.bin","sha1_after":"2f5ebd434f6d5b82e93d03e5626007bd5380f652","sha1_staged":"2f5ebd434f6d5b82e93d03e5626007bd5380f652"}],"files_probed_absent":[],"fps":366.16169342725783,"fps_nominal":59.82650314089141,"frames":4800,"input_pressed":120,"input_queries":249600,"last_frame_size":[330,224],"library_name":"Beetle Saturn","library_version":"v1.32.1","loaded":true,"logs":[{"frame":0,"level":"info","text":"Loading \"<content>/Lunar - Silver Star Story Complete (Japan).cue\""},{"frame":0,"level":"debug","text":"Disc 1"},{"frame":0,"level":"debug","text":"- Track 1, LBA: 0 DATA"},{"frame":0,"level":"debug","text":"- Track 2, LBA: 35891 DATA"},{"frame":0,"level":"debug","text":"- Track 3, LBA: 244897 AUDIO"},{"frame":0,"level":"debug","text":"- Track 4, LBA: 255894 AUDIO"},{"frame":0,"level":"debug","text":"Leadout: 256541"},{"frame":0,"level":"info","text":"Calculating game ID (1 discs)"},{"frame":0,"level":"info","text":"Game ID is: T-27904G"},{"frame":0,"level":"info","text":"This is a Saturn disc."},{"frame":0,"level":"info","text":"Disc Region: \"Japan\""},{"frame":0,"level":"inLine truncated
|
||||
{"check":{"claim":"The mpeg_card.bin image Beetle Saturn loads decides whether Lunar - Silver Star Story MPEG (T-27904G) detects the Video CD Card and plays its movies.","method":"Experimental build, not what users run: AUTH_DEVICE and GET_AUTH read the device type from CR2. Saturn BIOS v1.01 (Japan), Video CD Card option enabled, region auto-detected from the disc (Japan), host clock frozen at 2000-01-01 00:00:00 by libfaketime 0.9.10 so runs are deterministic. 4800 frames; Start held 15 frames at frames 2400, 3000, 3600 and 4200. Repeated with each mpeg_card.bin image, with no file, with 512 KiB of zeros and with a 1-byte file; every other input is identical. Each variant runs twice in fresh processes.","observable":"video_sha1","result":{"groups":[{"value":"f7db10347ce2081c188f83fbe5640131b4f2ceb5","variants":["mpeg_card.bin","mpeg_card.bin.3fee63d4","mpeg_card.bin.80179c49","mpeg_card.bin.821af2bd","mpeg_card.bin.b60e8866","mpeg_card.bin.b7450812","mpeg_card.bin.ee821d3f","mpeg_card.bin.ef9de845","zeros_512k.bin","one_byte.bin"]},{"value":"d60fcae489df0c317cca4e95f6f57c323be20ee4","variants":["mpeg_card.bin-absent"]}],"statement":"video_sha1 takes 2 distinct values across 11 variants","status":"differs"},"variable":"mpeg_card.bin"},"core":{"build_command":"make -j8 after editing mednafen/ss/cdb.c: AUTH_DEVICE and GET_AUTH read CTR.CD[1] instead of CTR.CD[2], plus a command trace","commit":"2ce77e20a956dc9a67b8d3d527f477b984310feb","compiler":["GCC: (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0"],"file":"mednafen_saturn_libretro.so","library_name":"Beetle Saturn","library_version":"v1.32.1","repo":"https://github.com/libretro/beetle-saturn-libretro","sha256":"fc9c33c697ddcde7547f2315f6ff91231f2ecfa24280c884a0185b880ffc2dfb"},"emulator":"beetle_saturn","flags":[],"frontend":{"commit":"8b12685c1652732828c146336a14a5fc265fffd3","script":"scripts/core_probe.py","script_modified":false,"script_sha256":"a95ab54a8d8f9ecc5dc2a55fd0ab93ffc66fe6466e2d89eea56a1a95c17d858b"},"host":{"cpu_count":12,"cpu_model":"13th Gen Intel(R) Core(TM) i9-13900K","kernel":"6.18.54.1-microsoft-standard-WSL2","load_after":[3.24,2.85,3.56],"load_before":[3.16,2.62,3.83],"machine":"x86_64","max_load":6.0,"os":"Linux-6.18.54.1-microsoft-standard-WSL2-x86_64-with-glibc2.39","python":"3.12.3"},"id":"2026-10-27-f532e5006714","inputs":{"content":{"label":"Redump: Lunar - Silver Star Story Complete (Japan), T-27904G V1.00 (cue sha1 7a609a9b579de648197ccfb5ab7bf4b3beb07d95)","sha1":"7a609a9b579de648197ccfb5ab7bf4b3beb07d95","size":554,"tracks":[{"file":"Lunar - Silver Star Story Complete (Japan) (Track 1).bin","sha1":"b6d71e1c96211af46d83278eccf7d6827a57d004","size":83710032},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 2).bin","sha1":"c2406d2953cec7f9fe5826aa71c7359c2baeb3a7","size":491934912},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 3).bin","sha1":"71c3bcfc22038d0f25126b34f703aa464259cfb5","size":25867296},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 4).bin","sha1":"b9c73d3890cd699cb1718131c2f7f04897a14d65","size":1872192}]},"env":{"FAKETIME":"2000-01-01 00:00:00","FAKETIME_DONT_FAKE_MONOTONIC":"1","LD_PRELOAD":"libfaketime.so.1 sha256:7ac8a1cdff1b627548de11513fddedd75014f5b041e9ae9054a634bb04aa7982"},"frame_hash_every":300,"frames":4800,"joypad_ports":2,"observables":["frame_sha1","video_sha1","audio_sha1","state_sha1","state:MPEG.AuthState","state:MPEG.Present","frame_hashes"],"options":{"beetle_saturn_mpeg_card":"enabled"},"presses":[{"button":3,"frame":2400,"length":15},{"button":3,"frame":3000,"length":15},{"button":3,"frame":3600,"length":15},{"button":3,"frame":4200,"length":15}],"repetitions":2,"warmup":0},"kind":"check","migrated_from_version":1,"record_version":3,"recorded_at":"2026-10-27T05:31:33+00:00","subject":"mpeg-card-lunar-cr2-build","supersedes":null,"variants":[{"flags":[],"label":"mpeg_card.bin","repetitions":[{"env_unanswered":{"11":1,"13":1,"28":1,"35":3,"37":1,"40":4799,"45":4,"46":1,"47":4800,"51":1,"55":2,"57":1,"8":1,"87":1},"files_opened":[{"path":"sega_101.bin","sha1_after":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720","sha1_staged":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720"},{"path":"mpeg_card.bin","sha1_after":"2f5ebd434f6d5b82e93d03e5626007bd5380f652","sha1_staged":"2f5ebd434f6d5b82e93d03e5626007bd5380f652"}],"files_probed_absent":[],"fps":363.57766936404164,"fps_nominal":59.82650314089141,"frames":4800,"input_pressed":120,"input_queries":249600,"last_frame_size":[330,224],"library_name":"Beetle Saturn","library_version":"v1.32.1","loaded":true,"logs":[{"frame":0,"level":"info","text":"Loading \"<content>/Lunar - Silver Star Story Complete (Japan).cue\""},{"frame":0,"level":"debug","text":"Disc 1"},{"frame":0,"level":"debug","text":"- Track 1, LBA: 0 DATA"},{"frame":0,"level":"debug","text":"- Track 2, LBA: 35891 DATA"},{"frame":0,"level":"debug","text":"- Track 3, LBA: 244897 AUDIO"},{"frame":0,"level":"debug","text":"- Track 4, LBA: 255894 AUDIO"},{"frame":0,"level"Line truncated
|
||||
{"check":{"claim":"With COMMAND_AUTH_DEVICE and COMMAND_GET_AUTH reading CR2, Beetle Saturn authenticates the Video CD Card that Lunar - Silver Star Story MPEG asks for.","method":"Same protocol as the issue 85 records: BIOS v1.01 Japan, card option enabled, clock frozen, 4800 frames, Start at 2400/3000/3600/4200. Core 2ce77e2 plus the two-line CR2 patch. Variants: HSS-0119, MK-80310, no file.","observable":"state:MPEG.AuthState","result":{"groups":[{"value":"02","variants":["mpeg_card.bin","mpeg_card.bin.b3841bb9"]},{"value":"00","variants":["mpeg_card.bin-absent"]}],"statement":"state:MPEG.AuthState takes 2 distinct values across 3 variants. Other flags, in 3 variants, are listed with them","status":"differs"},"variable":"mpeg_card.bin"},"core":{"build_command":"make -j10, with the CR2 patch to mednafen/ss/cdb.c (COMMAND_AUTH_DEVICE, COMMAND_GET_AUTH read CTR.CD[1])","commit":"2ce77e20a956dc9a67b8d3d527f477b984310feb","compiler":["GCC: (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0"],"file":"mednafen_saturn_libretro.so","library_name":"Beetle Saturn","library_version":"v1.32.1","repo":"https://github.com/libretro/beetle-saturn-libretro","sha256":"24d9fb7a8d99613819c9cdb00843e5e0b24914805a5eb8d01707e94a1b29fd24"},"emulator":"beetle_saturn","flags":["mpeg_card.bin: repetition 1 disagrees with repetition 0 on state_sha1","mpeg_card.bin.b3841bb9: repetition 1 disagrees with repetition 0 on state_sha1","mpeg_card.bin-absent: repetition 1 disagrees with repetition 0 on state_sha1"],"frontend":{"commit":"51d383b4226ef20c4cb0628142a5f81098ee79a2","script":"scripts/core_probe.py","script_modified":false,"script_sha256":"a3ff7cbb207ab3141124b25ba0793fbcd4b58fdbf77bd5e252c202a0aabdf738"},"host":{"cpu_count":12,"cpu_model":"13th Gen Intel(R) Core(TM) i9-13900K","kernel":"6.18.54.1-microsoft-standard-WSL2","load_after":[1.64,6.12,5.18],"load_before":[1.23,7.44,5.48],"machine":"x86_64","max_load":3.0,"os":"Linux-6.18.54.1-microsoft-standard-WSL2-x86_64-with-glibc2.39","python":"3.12.3"},"id":"2026-10-27-fb0468d3593d","inputs":{"content":{"label":"Redump: Lunar - Silver Star Story Complete (Japan), T-27904G V1.00","sha1":"7a609a9b579de648197ccfb5ab7bf4b3beb07d95","size":554,"tracks":[{"file":"Lunar - Silver Star Story Complete (Japan) (Track 1).bin","sha1":"b6d71e1c96211af46d83278eccf7d6827a57d004","size":83710032},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 2).bin","sha1":"c2406d2953cec7f9fe5826aa71c7359c2baeb3a7","size":491934912},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 3).bin","sha1":"71c3bcfc22038d0f25126b34f703aa464259cfb5","size":25867296},{"file":"Lunar - Silver Star Story Complete (Japan) (Track 4).bin","sha1":"b9c73d3890cd699cb1718131c2f7f04897a14d65","size":1872192}]},"env":{"FAKETIME":"2000-01-01 00:00:00","FAKETIME_DONT_FAKE_MONOTONIC":"1","LD_PRELOAD":"libfaketime.so.1"},"frame_hash_every":0,"frames":4800,"joypad_ports":2,"observables":["frame_sha1","video_sha1","audio_sha1","state_sha1","state:MPEG.AuthState"],"options":{"beetle_saturn_mpeg_card":"enabled"},"presses":[{"button":3,"frame":2400,"length":15},{"button":3,"frame":3000,"length":15},{"button":3,"frame":3600,"length":15},{"button":3,"frame":4200,"length":15}],"repetitions":2,"warmup":0},"kind":"check","record_version":3,"recorded_at":"2026-10-27T10:43:35+00:00","subject":"with-command-auth-device-and-command-get-9a211715","supersedes":null,"variants":[{"flags":["repetition 1 disagrees with repetition 0 on state_sha1"],"label":"mpeg_card.bin","repetitions":[{"env_unanswered":{"11":1,"13":1,"28":1,"35":3,"37":1,"40":4799,"45":4,"46":1,"47":4800,"51":1,"55":2,"57":1,"8":1,"87":1},"files_opened":[{"path":"sega_101.bin","sha1_after":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720","sha1_staged":"df94c5b4d47eb3cc404d88b33a8fda237eaf4720"},{"path":"mpeg_card.bin","sha1_after":"f7171b2a8f1c464696771941225c32d636b59349","sha1_staged":"f7171b2a8f1c464696771941225c32d636b59349"}],"files_probed_absent":[],"fps":354.4078198234303,"fps_nominal":59.82650314089141,"frames":4800,"input_pressed":120,"input_queries":249600,"last_frame_size":[330,224],"library_name":"Beetle Saturn","library_version":"v1.32.1","loaded":true,"logs":[{"frame":0,"level":"info","text":"Loading \"<content>/Lunar - Silver Star Story Complete (Japan).cue\""},{"frame":0,"level":"debug","text":"Disc 1"},{"frame":0,"level":"debug","text":"- Track 1, LBA: 0 DATA"},{"frame":0,"level":"debug","text":"- Track 2, LBA: 35891 DATA"},{"frame":0,"level":"debug","text":"- Track 3, LBA: 244897 AUDIO"},{"frame":0,"level":"debug","text":"- Track 4, LBA: 255894 AUDIO"},{"frame":0,"level":"debug","text":"Leadout: 256541"},{"frame":0,"level":"info","text":"Calculating game ID (1 discs)"},{"frame":0,"level":"info","text":"Game ID is: T-27904G"},{"frame":0,"level":"info","text":"This is a Saturn disc."},{"frame":0,"level":"info","text":"Disc Region: \"Japan\""},{"frame":0,"level":"info","text":"CPU Cache Emulation Mode: Data only"},{"frame":0,"level":"info","text":"Region: 0x1."},{"framLine truncated
|
||||
+4
-28
@@ -43,7 +43,6 @@ import shlex
|
||||
import shutil
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
import time
|
||||
from collections.abc import Callable, Iterator, Sequence
|
||||
from dataclasses import dataclass, field
|
||||
@@ -74,7 +73,6 @@ SEGFAULT_CODES = (139, -11)
|
||||
HOST_MISREAD_MARKERS = ("SystemError", "unknown opcode")
|
||||
VOLATILE_KEYS = frozenset({"generated_at", "generated", "imported_at"})
|
||||
|
||||
SUBJECT_TYPES = re.compile(r"^(feat|refactor|chore|docs|fix): [a-z0-9]")
|
||||
CI_RED = frozenset({"failure", "timed_out", "startup_failure"})
|
||||
CI_GREEN = frozenset({"success", "skipped", "neutral"})
|
||||
|
||||
@@ -189,33 +187,11 @@ class Context:
|
||||
|
||||
|
||||
def check_subject(subject: str, body: str = "") -> list[str]:
|
||||
"""What the repository's commit-msg hook would refuse in this message.
|
||||
"""What the repository's commit rules refuse in this message, checked
|
||||
when the job list loads instead of two hours into the job."""
|
||||
from commit_rules import problems # noqa: PLC0415
|
||||
|
||||
The hook holds the vocabulary rules, so they live in one place: a job
|
||||
list is checked against it when it loads, not two hours into the job.
|
||||
Without a hook (another clone) only the shape is checked.
|
||||
"""
|
||||
problems = []
|
||||
if len(subject) > 50:
|
||||
problems.append(f"subject is {len(subject)} characters, 50 at most")
|
||||
if not SUBJECT_TYPES.match(subject):
|
||||
problems.append("subject must read 'type: description'")
|
||||
if re.search(r"^co-authored-by", body, re.IGNORECASE | re.MULTILINE):
|
||||
problems.append("no Co-Authored-By trailer")
|
||||
hook = subprocess.run(["git", "rev-parse", "--git-path", "hooks/commit-msg"],
|
||||
capture_output=True, text=True, cwd=REPO_ROOT, check=False).stdout.strip()
|
||||
hook_path = (REPO_ROOT / hook) if hook else None
|
||||
if hook_path and hook_path.is_file() and os.access(hook_path, os.X_OK):
|
||||
with tempfile.NamedTemporaryFile("w", suffix=".msg", delete=False) as message:
|
||||
message.write(f"{subject}\n\n{body}\n" if body else f"{subject}\n")
|
||||
try:
|
||||
refused = subprocess.run([str(hook_path), message.name], capture_output=True,
|
||||
text=True, check=False)
|
||||
finally:
|
||||
os.unlink(message.name)
|
||||
if refused.returncode:
|
||||
problems.append((refused.stderr or refused.stdout).strip() or "refused by commit-msg")
|
||||
return problems
|
||||
return problems(f"{subject}\n\n{body}" if body else subject)
|
||||
|
||||
|
||||
def _step(raw: object, where: str) -> Step:
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
"""Commit message rules of this repository, in one place.
|
||||
|
||||
The local commit-msg hook calls this file, and autorun checks every job's
|
||||
subject with it when the job list loads. Kept in the tree, the rules hold in
|
||||
any clone and in CI: a copy in the hook alone left the runner checking only
|
||||
the shape there.
|
||||
|
||||
Usage as a hook: python scripts/commit_rules.py MESSAGE_FILE
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
MAX_SUBJECT = 50
|
||||
SUBJECT_TYPES = re.compile(r"^(feat|refactor|chore|docs|fix): [a-z0-9]")
|
||||
REFUSED_WORDS = re.compile(
|
||||
r"\b(bug|regression|revert|dead code|broken|wrong|hack|workaround|"
|
||||
r"comprehensive|implement)",
|
||||
re.IGNORECASE,
|
||||
)
|
||||
CO_AUTHOR = re.compile(r"^co-authored-by", re.IGNORECASE | re.MULTILINE)
|
||||
|
||||
|
||||
def problems(message: str) -> list[str]:
|
||||
"""What this repository refuses in a commit message, first line first."""
|
||||
found = []
|
||||
subject = message.split("\n", 1)[0]
|
||||
if len(subject) > MAX_SUBJECT:
|
||||
found.append(f"subject is {len(subject)} characters, {MAX_SUBJECT} at most: {subject}")
|
||||
if not SUBJECT_TYPES.match(subject):
|
||||
found.append("subject must read 'type: description' (feat, refactor, chore, docs, fix)")
|
||||
text = "\n".join(line for line in message.splitlines() if not line.startswith("#"))
|
||||
if REFUSED_WORDS.search(text):
|
||||
found.append("the message uses a word this repository's history does not carry")
|
||||
if CO_AUTHOR.search(message):
|
||||
found.append("no Co-Authored-By trailer here")
|
||||
return found
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
if len(argv) != 2:
|
||||
print("usage: commit_rules.py MESSAGE_FILE", file=sys.stderr)
|
||||
return 2
|
||||
found = problems(Path(argv[1]).read_text(encoding="utf-8", errors="replace"))
|
||||
for problem in found:
|
||||
print(f"commit-msg: {problem}", file=sys.stderr)
|
||||
return 1 if found else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
+22
-20
@@ -888,28 +888,30 @@ class BiosIntegrity(Scratch):
|
||||
return str(self.tmp / "database.json")
|
||||
|
||||
|
||||
class SubjectsFollowTheRepositoryHook(unittest.TestCase):
|
||||
"""The vocabulary rules live in the commit-msg hook alone: a copy in the
|
||||
runner put the very words the history refuses into a tracked file."""
|
||||
class SubjectsFollowTheRepositoryRules(unittest.TestCase):
|
||||
"""The commit rules live in scripts/commit_rules.py, which the local hook
|
||||
calls: a copy in the hook alone let CI check only the shape."""
|
||||
|
||||
def test_a_refusal_comes_from_the_hook(self):
|
||||
def test_the_runner_reads_the_tracked_rules(self):
|
||||
import commit_rules # noqa: PLC0415
|
||||
|
||||
for subject in ("chore: fix the broken manifests", "update things", "chore: " + "a" * 60):
|
||||
with self.subTest(subject=subject):
|
||||
self.assertEqual(ar.check_subject(subject), commit_rules.problems(subject))
|
||||
self.assertTrue(ar.check_subject(subject))
|
||||
self.assertEqual(ar.check_subject("chore: tidy the cache"), [])
|
||||
|
||||
def test_the_rules_run_as_a_hook(self):
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
hook = Path(tmp) / "commit-msg"
|
||||
hook.write_text('#!/bin/sh\ngrep -q forbiddenword "$1" && echo refused && exit 1\nexit 0\n')
|
||||
hook.chmod(0o755)
|
||||
real = subprocess.run
|
||||
def fake(argv, *args, **kwargs):
|
||||
if argv[:3] == ["git", "rev-parse", "--git-path"]:
|
||||
return subprocess.CompletedProcess(argv, 0, stdout=str(hook) + "\n", stderr="")
|
||||
return real(argv, *args, **kwargs)
|
||||
with unittest.mock.patch.object(ar.subprocess, "run", side_effect=fake):
|
||||
self.assertEqual(ar.check_subject("chore: tidy the cache"), [])
|
||||
self.assertEqual(ar.check_subject("chore: add forbiddenword"), ["refused"])
|
||||
|
||||
def test_the_shape_is_checked_without_a_hook(self):
|
||||
problems = ar.check_subject("not a subject that follows the type rule at all, too long")
|
||||
self.assertTrue(any("50 at most" in p for p in problems))
|
||||
self.assertTrue(any("type: description" in p for p in problems))
|
||||
message = Path(tmp) / "MSG"
|
||||
script = REPO_ROOT / "scripts" / "commit_rules.py"
|
||||
for text, code in (("fix: keep the cache\n", 0), ("fix: a broken cache\n", 1),
|
||||
("fix: keep it\n\nCo-Authored-By: x\n", 1)):
|
||||
message.write_text(text)
|
||||
done = subprocess.run([sys.executable, str(script), str(message)],
|
||||
capture_output=True, text=True, check=False)
|
||||
with self.subTest(text=text):
|
||||
self.assertEqual(done.returncode, code, done.stderr)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
+30
-5
@@ -9,6 +9,7 @@ import importlib.util
|
||||
import io
|
||||
import json
|
||||
import os
|
||||
import stat
|
||||
import shlex
|
||||
import re
|
||||
import shutil
|
||||
@@ -5737,11 +5738,35 @@ class AFileYouHadIsKept(unittest.TestCase):
|
||||
|
||||
@unittest.skipUnless(hasattr(os, "getuid"), "user ids are POSIX")
|
||||
def test_a_holder_another_user_owns_is_refused(self):
|
||||
(self.home / install.BACKUP_DIR).mkdir()
|
||||
with self.assertRaises(OSError):
|
||||
with unittest.mock.patch.object(install.os, "getuid", return_value=os.getuid() + 1):
|
||||
install._check_holder(self.home / install.BACKUP_DIR)
|
||||
install._check_holder(self.home / install.BACKUP_DIR)
|
||||
holder = self.home / install.BACKUP_DIR
|
||||
holder.mkdir()
|
||||
real = os.lstat
|
||||
|
||||
def planted(path, *args, **kwargs):
|
||||
info = real(path, *args, **kwargs)
|
||||
if Path(path) != holder:
|
||||
return info
|
||||
fields = list(info)
|
||||
fields[stat.ST_UID] = info.st_uid + 2
|
||||
return os.stat_result(fields)
|
||||
|
||||
with self.assertRaises(OSError), \
|
||||
unittest.mock.patch.object(install.os, "lstat", side_effect=planted):
|
||||
install._check_holder(holder)
|
||||
install._check_holder(holder)
|
||||
|
||||
@unittest.skipUnless(hasattr(os, "getuid"), "user ids are POSIX")
|
||||
def test_a_storage_with_one_owner_for_every_file_takes_the_holder(self):
|
||||
# Android's shared storage, seen from Termux on Android 17: a folder
|
||||
# the run has just made is shown as another user's, like every other
|
||||
# file there. Refusing it left 25 files unreplaced on a real phone.
|
||||
holder = self.home / install.BACKUP_DIR
|
||||
holder.mkdir()
|
||||
with unittest.mock.patch.object(install.os, "getuid", return_value=os.getuid() + 1):
|
||||
install._check_holder(holder)
|
||||
(self.bios / "x.bin").write_bytes(self.OLD)
|
||||
self.assertTrue(self._download("x.bin")[1])
|
||||
self.assertEqual((self._run_folder() / "system" / "x.bin").read_bytes(), self.OLD)
|
||||
|
||||
def test_restore_refuses_a_folder_the_installer_did_not_write(self):
|
||||
planted = self.home / install.BACKUP_DIR / "20260101-000000"
|
||||
|
||||
@@ -337,6 +337,21 @@ class ProgressOutput(unittest.TestCase):
|
||||
self.assertIn("failed: x.bin (HTTP 404)", out)
|
||||
self.assertIn("2.0 KB downloaded in 0:02", out)
|
||||
|
||||
def test_files_not_set_aside_get_a_remedy_not_a_retry(self):
|
||||
# A real Android run: 25 files whose backup folder was refused, told
|
||||
# to run again, which refuses them the same way.
|
||||
reason = f"{install.NOT_KEPT} (/sdcard/RetroArch/retrobios-backup belongs to another user)"
|
||||
buf = io.StringIO()
|
||||
with contextlib.redirect_stdout(buf), self.assertRaises(SystemExit) as end:
|
||||
install._report_outcome(
|
||||
[Path("/b")], 3, 0, 2, 0, False,
|
||||
failures=[("a.zip", reason), ("b.zip", reason)],
|
||||
)
|
||||
out = buf.getvalue()
|
||||
self.assertEqual(end.exception.code, 1)
|
||||
self.assertIn("The files in place were left as they were", out)
|
||||
self.assertNotIn("retry only those", out)
|
||||
|
||||
|
||||
class CommandLine(unittest.TestCase):
|
||||
def test_a_dry_run_writes_nothing(self):
|
||||
|
||||
@@ -168,7 +168,8 @@ class NoMarketingVocabulary(unittest.TestCase):
|
||||
def test_no_tracked_text_uses_them(self):
|
||||
offenders = []
|
||||
for path in _tracked():
|
||||
if path.name == "test_prose_style.py":
|
||||
# This file and the commit rules have to name the words they refuse.
|
||||
if path.name in {"test_prose_style.py", "commit_rules.py"}:
|
||||
continue
|
||||
text = path.read_text(encoding="utf-8", errors="replace")
|
||||
for number, line in enumerate(text.splitlines(), 1):
|
||||
|
||||
Reference in new issue
Block a user