mirror of
https://github.com/Abdess/retroarch_system.git
synced 2026-10-23 20:29:06 -05:00
chore: merge audit fixes (region)
# Conflicts: # install.ps1 # install.sh
This commit is contained in:
commit
43c6df58ee
10 files changed
+128
-24
No files matched your search
@@ -80,10 +80,10 @@ files:
|
||||
|
||||
- name: bios_CD_E.bin
|
||||
system: sega-megacd
|
||||
region: [europe]
|
||||
region: [europe, oceania]
|
||||
required: true
|
||||
mode: libretro
|
||||
note: "Mega CD BIOS for discs whose region resolves to E (segacd.c:1587-1588). Same load rules as bios_CD_U.bin."
|
||||
note: "Mega CD BIOS for discs whose region resolves to E (segacd.c:1587-1588). The header code E, or bit 8 of a hex code, is the only PAL value the code reads, so Australian discs take this branch too (romdb.c:176-215). Same load rules as bios_CD_U.bin."
|
||||
source_ref: "source libblastem.c:502, source segacd.c:1573-1615"
|
||||
|
||||
- name: bios_CD_J.bin
|
||||
|
||||
@@ -71,11 +71,11 @@ files:
|
||||
- name: eu_mcd1_9210.bin
|
||||
aliases: [bios_CD_E.bin]
|
||||
system: sega-megacd
|
||||
region: [europe]
|
||||
region: [europe, oceania]
|
||||
required: true
|
||||
description: "Mega CD (Europe) boot ROM"
|
||||
note: "Opened from SCDEURBIOS for the European region, same 128 KB read and same lock when it is missing, with the EUR message."
|
||||
source_ref: "Fusion.exe 0x44b68a (default path), 0x478979-0x4789d6 (open, message, fread 0x20000)"
|
||||
note: "Opened from SCDEURBIOS for the European region, same 128 KB read and same lock when it is missing, with the EUR message. With country autodetect on (the default), the disc's security byte at 0x20B picks the region: 0x7A USA, 0xA1 JAP, 0x64 EUR. EUR is the only branch that sets the PAL version bits (0xC0) and 50 Hz, so Australian discs take it too."
|
||||
source_ref: "Fusion.exe 0x44b68a (default path), 0x478979-0x4789d6 (open, message, fread 0x20000), 0x44756b-0x44758a and 0x44cfc0-0x44cfe3 (security byte), 0x478963-0x478970 (PAL branch)"
|
||||
|
||||
- name: 32X_G_BIOS.bin
|
||||
system: sega-32x
|
||||
@@ -110,11 +110,10 @@ files:
|
||||
|
||||
- name: bios_U.sms
|
||||
system: sega-mastersystem
|
||||
region: [north-america]
|
||||
required: false
|
||||
description: "Master System (USA) boot ROM"
|
||||
note: "Read from SMSUSABIOS, up to 512 KB, for the USA region unless SMSBIOSDisable is set. A missing file leaves the cartridge to start directly. No file name is fixed by the code."
|
||||
source_ref: "Fusion.exe 0x47d541-0x47d5b9"
|
||||
note: "Read from SMSUSABIOS, up to 512 KB, for the USA region unless SMSBIOSDisable is set. A missing file leaves the cartridge to start directly. No file name is fixed by the code. The header nibble at 0x7FFF tells Japan from export only: an export cart gets USA or EUR from the CountryOrder setting (USA by default), or from a CRC32 list held in the executable."
|
||||
source_ref: "Fusion.exe 0x47d541-0x47d5b9, 0x45c173-0x45c1f4 (header nibble, CountryOrder), 0x47ce20-0x47ced1 (CRC32 list)"
|
||||
|
||||
- name: bios_J.sms
|
||||
system: sega-mastersystem
|
||||
@@ -126,11 +125,10 @@ files:
|
||||
|
||||
- name: bios_E.sms
|
||||
system: sega-mastersystem
|
||||
region: [europe]
|
||||
required: false
|
||||
description: "Master System (Europe) boot ROM"
|
||||
note: "Read from SMSEURBIOS for the European region, same rules as the USA image."
|
||||
source_ref: "Fusion.exe 0x47d60c-0x47d659"
|
||||
note: "Read from SMSEURBIOS for the European region, same rules as the USA image. EUR comes from the CountryOrder setting or the CRC32 list, never from the header."
|
||||
source_ref: "Fusion.exe 0x47d60c-0x47d659, 0x45c1a4-0x45c1f4 (CountryOrder), 0x47cea1-0x47ced1 (CRC32 list)"
|
||||
|
||||
- name: bios.gg
|
||||
system: sega-gamegear
|
||||
|
||||
@@ -36,13 +36,13 @@ files:
|
||||
|
||||
- name: "scph5501.bin"
|
||||
description: "SCPH-5501 (v3.0 11-18-96 A)"
|
||||
region: [north-america]
|
||||
region: [north-america, latin-america]
|
||||
size: 524288
|
||||
required: false
|
||||
hle_fallback: true
|
||||
validation: [size]
|
||||
source_ref: "source frontend/libretro.c:3864-3867 (listed_bios[1])"
|
||||
note: "Preferred US BIOS, searched first by exact filename."
|
||||
note: "Preferred US BIOS, searched first by exact filename. The US slot is the detector's default: a disc takes it for both America licence strings and for any licence that is neither \"Inc.\" (JP) nor \"Euro pe\" (EU), and content without a disc boots it too (libpcsxcore/misc.c:422-453, frontend/libretro.c:2167-2171)."
|
||||
|
||||
# -- Region: Europe (PSX_REGION_EU = 2) --
|
||||
|
||||
@@ -70,7 +70,7 @@ files:
|
||||
|
||||
- name: "scph101.bin"
|
||||
description: "SCPH-101 (v4.4 03-24-00 A) - PSone US"
|
||||
region: [north-america]
|
||||
region: [north-america, latin-america]
|
||||
size: 524288
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -80,7 +80,7 @@ files:
|
||||
|
||||
- name: "scph7001.bin"
|
||||
description: "SCPH-7001 (v4.1 12-16-97 A)"
|
||||
region: [north-america]
|
||||
region: [north-america, latin-america]
|
||||
size: 524288
|
||||
required: false
|
||||
hle_fallback: true
|
||||
@@ -89,7 +89,7 @@ files:
|
||||
|
||||
- name: "scph1001.bin"
|
||||
description: "SCPH-1001 (v2.2 12-04-95 A)"
|
||||
region: [north-america]
|
||||
region: [north-america, latin-america]
|
||||
size: 524288
|
||||
required: false
|
||||
hle_fallback: true
|
||||
|
||||
+1
-1
@@ -12,7 +12,7 @@
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
$defaultInstallUrl = "https://raw.githubusercontent.com/Abdess/retrobios/main/install.py"
|
||||
$defaultInstallSha256 = "376edf794195d74f21e598854b5f3e90fb1955513835264bc9326ad4d2acf9c9"
|
||||
$defaultInstallSha256 = "496e5a3aaf817301c40f45f184b97fc5607147184195d827a46b92c28fd3d2b0"
|
||||
$maximumInstallerBytes = 2MB
|
||||
$installerExit = 0
|
||||
$installer = if ($PSScriptRoot) { Join-Path $PSScriptRoot "install.py" } else { $null }
|
||||
|
||||
+11
-1
@@ -138,6 +138,10 @@ REGION_ALIASES: dict[str, str] = {
|
||||
"auto": WORLD_REGION,
|
||||
"gb": "uk",
|
||||
}
|
||||
AREA_TERRITORIES: dict[str, frozenset] = {
|
||||
"asia-ntsc": frozenset({"taiwan"}),
|
||||
"asia-pal": frozenset({"china"}),
|
||||
}
|
||||
_REGION_PARENT = {
|
||||
member: parent for parent, members in REGION_TREE.items() for member in members
|
||||
}
|
||||
@@ -2209,7 +2213,13 @@ def canonical_region(raw: str) -> str:
|
||||
|
||||
|
||||
def _region_comparable(a: str, b: str) -> bool:
|
||||
return a == b or _REGION_PARENT.get(a) == b or _REGION_PARENT.get(b) == a
|
||||
return (
|
||||
a == b
|
||||
or _REGION_PARENT.get(a) == b
|
||||
or _REGION_PARENT.get(b) == a
|
||||
or a in AREA_TERRITORIES.get(b, ())
|
||||
or b in AREA_TERRITORIES.get(a, ())
|
||||
)
|
||||
|
||||
|
||||
def _region_rank(file_regions: set[str], requested: list[str]) -> int:
|
||||
|
||||
+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="376edf794195d74f21e598854b5f3e90fb1955513835264bc9326ad4d2acf9c9"
|
||||
DEFAULT_INSTALL_SHA256="496e5a3aaf817301c40f45f184b97fc5607147184195d827a46b92c28fd3d2b0"
|
||||
MAX_INSTALLER_BYTES=2097152
|
||||
|
||||
cleanup() {
|
||||
|
||||
+20
-2
@@ -47,6 +47,17 @@ REGION_TREE: dict[str, frozenset[str]] = {
|
||||
"oceania": frozenset({"australia", "new-zealand"}),
|
||||
}
|
||||
|
||||
# Hardware areas that fuse territory and signal standard, with the territories
|
||||
# the code serves through them. Mednafen's Saturn SMPC area 0x2 is "For TAIWAN
|
||||
# and PHILIPINES" and its area option offers it as "Taiwan", area 0xA as
|
||||
# "China" (mednafen/ss/ss.cpp:1119, 2363-2364 in the mednafen_stv port).
|
||||
# kronos tags the ST-V BIOS epr-19854.ic8 taiwan and mednafen_stv tags it
|
||||
# asia-ntsc: a request in either spelling has to reach the other.
|
||||
AREA_TERRITORIES: dict[str, frozenset[str]] = {
|
||||
"asia-ntsc": frozenset({"taiwan"}),
|
||||
"asia-pal": frozenset({"china"}),
|
||||
}
|
||||
|
||||
_PARENT: dict[str, str] = {
|
||||
member: parent for parent, members in REGION_TREE.items() for member in members
|
||||
}
|
||||
@@ -96,8 +107,15 @@ def _canonical(raw: str) -> str:
|
||||
|
||||
|
||||
def comparable(a: str, b: str) -> bool:
|
||||
"""True when two regions are equal or in a parent/child relation."""
|
||||
return a == b or _PARENT.get(a) == b or _PARENT.get(b) == a
|
||||
"""True when two regions are equal, parent and child, or an area and a
|
||||
territory it serves."""
|
||||
return (
|
||||
a == b
|
||||
or _PARENT.get(a) == b
|
||||
or _PARENT.get(b) == a
|
||||
or a in AREA_TERRITORIES.get(b, ())
|
||||
or b in AREA_TERRITORIES.get(a, ())
|
||||
)
|
||||
|
||||
|
||||
def normalize_declared(raw: str | list | None) -> set[str]:
|
||||
|
||||
@@ -40,6 +40,7 @@ class OneRegionVocabulary(unittest.TestCase):
|
||||
|
||||
def test_the_copy_matches(self):
|
||||
self.assertEqual(install.REGION_TREE, dict(region.REGION_TREE))
|
||||
self.assertEqual(install.AREA_TERRITORIES, dict(region.AREA_TERRITORIES))
|
||||
self.assertEqual(install.REGION_ALIASES, region.ALIASES)
|
||||
self.assertEqual(install.WORLD_REGION, region.WORLD)
|
||||
self.assertEqual(install.REGIONS, region.REGIONS)
|
||||
@@ -49,7 +50,8 @@ class TheRegionRuleIsTheBuilders(unittest.TestCase):
|
||||
"""Random groups, both implementations, one answer."""
|
||||
|
||||
POOL = ["north-america", "europe", "japan", "uk", "canada", "brazil",
|
||||
"south-korea", "world", "asia", "oceania"]
|
||||
"south-korea", "world", "asia", "oceania", "taiwan", "asia-ntsc",
|
||||
"china", "asia-pal"]
|
||||
|
||||
def _case(self, rng: random.Random):
|
||||
groups: dict[str, list[tuple[str, str]]] = {}
|
||||
@@ -79,7 +81,8 @@ class TheRegionRuleIsTheBuilders(unittest.TestCase):
|
||||
if not entry["regions"]:
|
||||
del entry["regions"], entry["region_groups"]
|
||||
entry.pop("priority", None)
|
||||
requested = rng.sample(["north-america", "europe", "japan", "uk", "canada"],
|
||||
requested = rng.sample(["north-america", "europe", "japan", "uk", "canada",
|
||||
"taiwan", "asia-ntsc", "china", "asia-pal"],
|
||||
rng.randint(1, 3))
|
||||
return groups, index, list(entries.values()), requested
|
||||
|
||||
|
||||
@@ -58,6 +58,17 @@ class TestComparable(unittest.TestCase):
|
||||
def test_saturn_fused_slug_is_under_asia(self):
|
||||
self.assertTrue(region.comparable("asia", "asia-ntsc"))
|
||||
|
||||
def test_an_area_matches_the_territory_it_serves(self):
|
||||
"""kronos tags the ST-V BIOS epr-19854.ic8 taiwan, mednafen_stv tags
|
||||
it asia-ntsc, the SMPC area Mednafen names for Taiwan."""
|
||||
self.assertTrue(region.comparable("taiwan", "asia-ntsc"))
|
||||
self.assertTrue(region.comparable("asia-ntsc", "taiwan"))
|
||||
self.assertTrue(region.comparable("china", "asia-pal"))
|
||||
|
||||
def test_an_area_does_not_match_other_territories(self):
|
||||
self.assertFalse(region.comparable("japan", "asia-ntsc"))
|
||||
self.assertFalse(region.comparable("taiwan", "asia-pal"))
|
||||
|
||||
|
||||
class TestNormalizeDeclared(unittest.TestCase):
|
||||
def test_none_is_empty(self):
|
||||
@@ -889,6 +900,13 @@ class RegionalRequestsKeepWhatTheCodeLoads(unittest.TestCase):
|
||||
("ace-dl", ["france"], "private/firmware/Amstrad_s4.cpr"),
|
||||
("duckstation", ["brazil"], "scph5501.bin"),
|
||||
("duckstation", ["south-korea"], "scph5500.bin"),
|
||||
("mednafen_stv", ["taiwan", "north-america"], "epr-19854.ic8"),
|
||||
("kronos", ["asia-ntsc", "north-america"], "epr-19854.ic8"),
|
||||
("beetle_saturn", ["taiwan", "north-america"], "sega_101.bin"),
|
||||
("pcsx_rearmed", ["brazil", "japan"], "scph5501.bin"),
|
||||
("pcsx_rearmed", ["brazil", "japan"], "scph1001.bin"),
|
||||
("blastem", ["australia", "north-america"], "bios_CD_E.bin"),
|
||||
("kega-fusion", ["australia", "north-america"], "eu_mcd1_9210.bin"),
|
||||
)
|
||||
|
||||
def test_each_request_keeps_its_file(self):
|
||||
@@ -1094,6 +1112,60 @@ class MegaCdAmericasIsOneCode(unittest.TestCase):
|
||||
self.assertEqual(narrow, [])
|
||||
|
||||
|
||||
class MegaCdEuropeServesOceania(unittest.TestCase):
|
||||
"""A Mega CD disc carries one PAL code for Europe and Australia, so every
|
||||
emulator picking the European BIOS by that code picks it for an
|
||||
Australian disc too. blastem and kega-fusion tagged it europe alone, and a
|
||||
--region au,us pack dropped the BIOS those discs boot with."""
|
||||
|
||||
def test_a_european_mega_cd_bios_includes_oceania(self):
|
||||
import yaml
|
||||
|
||||
root = Path(__file__).resolve().parents[1]
|
||||
narrow = []
|
||||
for path in sorted((root / "emulators").glob("*.yml")):
|
||||
profile = yaml.safe_load(path.read_text(encoding="utf-8")) or {}
|
||||
for entry in profile.get("files") or []:
|
||||
system = str(entry.get("system", ""))
|
||||
regions = entry.get("region") or []
|
||||
if system in ("sega-megacd", "mega-cd") and "europe" in regions \
|
||||
and "oceania" not in regions:
|
||||
narrow.append(f"{path.stem}: {entry.get('name')}")
|
||||
self.assertEqual(narrow, [])
|
||||
|
||||
|
||||
class PcsxRearmedUsSlotIsTheDefault(unittest.TestCase):
|
||||
"""CheckCdrom sets PSX_REGION_US before reading the licence and only
|
||||
"Inc." or "Euro pe" move it (libpcsxcore/misc.c:422-453): a disc of any
|
||||
other market boots the US slot."""
|
||||
|
||||
def test_every_us_slot_bios_includes_latin_america(self):
|
||||
from common import load_emulator_profiles
|
||||
|
||||
tagged = [
|
||||
f for f in load_emulator_profiles("emulators")["pcsx_rearmed"]["files"]
|
||||
if "north-america" in (f.get("region") or [])
|
||||
]
|
||||
self.assertEqual(len(tagged), 4)
|
||||
for entry in tagged:
|
||||
with self.subTest(name=entry["name"]):
|
||||
self.assertIn("latin-america", entry["region"])
|
||||
|
||||
|
||||
class FusionSmsExportBiosFollowsTheSetting(unittest.TestCase):
|
||||
"""Kega Fusion tells a Japanese Master System cart from an export one by
|
||||
the header, then picks USA or EUR from its CountryOrder setting or a CRC32
|
||||
list. Neither export BIOS is chosen for a territory the cart names."""
|
||||
|
||||
def test_the_export_bioses_are_unregioned(self):
|
||||
from common import load_emulator_profiles
|
||||
|
||||
files = {f["name"]: f for f in load_emulator_profiles("emulators")["kega-fusion"]["files"]}
|
||||
for name in ("bios_U.sms", "bios_E.sms"):
|
||||
with self.subTest(name=name):
|
||||
self.assertNotIn("region", files[name])
|
||||
|
||||
|
||||
class NoMarketStopsAtAustralia(unittest.TestCase):
|
||||
"""simple64 tagged its PAL PIF [europe, australia]. New Zealand is not
|
||||
under australia, so --region new-zealand kept only the NTSC PIF, though
|
||||
|
||||
+4
-1
@@ -186,7 +186,10 @@ What does not, and why each trap is easy to fall into:
|
||||
`env.Loader.ReqSpec == "PAL"`, a video specification, and the Atari 2600 has
|
||||
no region lock. There is no signal field: drop `region:` rather than map it.
|
||||
The exception is hardware that fuses both axes in one register, such as the
|
||||
Saturn SMPC area codes behind `asia-ntsc` and `asia-pal`.
|
||||
Saturn SMPC area codes behind `asia-ntsc` and `asia-pal`. Mednafen names
|
||||
them for Taiwan and China, so a `--region taiwan` request reaches an
|
||||
`asia-ntsc` file and a `--region china` request an `asia-pal` one, and the
|
||||
other way round (`AREA_TERRITORIES` in `scripts/region.py`).
|
||||
- **A single-region system.** When every file of a system shares one region,
|
||||
the pack filter keeps them all anyway, so annotating adds nothing.
|
||||
- **A language without a territory.** Arabic MSX variants, CJK fonts. The
|
||||
|
||||
Reference in new issue
Block a user