fix: a shared tail is proof only in the own tree

PCSX2x6 reads bin/resources/GameIndex.yaml, an arcade database keyed by NM gameid. The shortened tail resources/GameIndex.yaml matched four files, and the resolver set aside the three in other emulators' trees before measuring ambiguity, so PCSX2's console database passed for path proof and shipped in the PCSX2x6 pack. Ambiguity is now read before that filtering. A tail indexed from an identical copy is kept even when the database records the other copy's path.

PCSX2x6's GameIndex.yaml and RedumpDatabase.yaml are collected from its repository at the pinned 583f0e90 (git blobs ed8232e3 and 8669b3af).
This commit is contained in:
Abdessamad Derraz committed 2026-10-19 23:14:24 +02:00
1 parent 843f0ddc0e
commit adaa1eba87
5 files changed
+70965 -4

No files matched your search

@@ -0,0 +1,412 @@
NM00001:
name: Ridge Racer V - Arcade Battle
region: System246
bootprog: START
media: CD
input: driving
clampModes:
vuClampMode: 2
gsHWFixes:
alignSprite: 1
textureInsideRT: 1
halfPixelOffset: 2
roundSprite: 1
gpuPaletteConversion: 2
cpuSpriteRenderBW: 1
cpuSpriteRenderLevel: 1
NM00002:
name: Bloody Roar 3
region: System246
bootprog: BDRGAME
media: CD
input: button
NM00003:
name: Vampire Night
region: System246
bootprog: VPNGAME
media: CD
input: lightgun
NM10003:
name: Technic Beat
region: System246
bootprog: VPNGAME
media: DVD
input: button
NM00004:
name: Tekken 4
region: System246
bootprog: TK4LOAD
media: DVD
input: button
gsHWFixes:
alignSprite: 1
NM00005:
name: Wangan Midnight R
region: System246
bootprog: AL3LOAD
media: CD
input: driving
NM00006:
name: Smash Court Pro Tournament
region: System246
bootprog: SCPTLOAD
media: CD
input: button
NM00007:
name: Soul Calibur II
region: System246
bootprog: SCSLOAD
media: DVD
input: button
clampModes:
vuClampMode: 2 # Respawn issues, Fixes SPS, avoids teleporting characters.
gameFixes:
- EETimingHack # Fixes bad colours on character select when in Progressive Scan.
- SoftwareRendererFMVHack # Horizontal bottom line in FMV.
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
nativeScaling: 2 # Fixes misaligned bloom
NM00008:
name: Wangan Midnight
region: System246
bootprog: WGNLOAD
media: CD
input: driving
NM00009:
name: Netchuu! Pro Baseball 2002
region: System246
bootprog: NPBLOAD
media: CD
input: button
NM00010:
name: Battle Gear 3
region: System246
bootprog: BGRLOAD
media: HDD
input: driving
clampModes:
eeClampMode: 3
vuClampMode: 3
NM00011:
name: Pride GP 2003
region: System246
bootprog: FGTLOAD
media: DVD
input: button
NM00012:
name: Time Crisis 3
region: System246
bootprog: TC3LOAD
media: DVD
input: lightgun
NM00013:
name: Mobile Suit Gundam Zeta - A.E.U.G. vs. Titans
region: System246
bootprog: GDMLOAD
media: DVD
input: button
NM00014:
name: Dragon Chronicle - Legendary Master Ark
region: System246
bootprog: DGNLOAD
media: CD
input: touchscreen
NM00015:
name: Battle Gear 3 Tuned
region: System246
bootprog: BGTLOAD
media: HDD
input: driving
clampModes:
eeClampMode: 3
vuClampMode: 3
NM00016:
name: Zoids Infinity
region: System246
bootprog: ZOILOAD
media: HDD
input: twinstick
NM00017:
name: Mobile Suit Gundam Zeta - A.E.U.G. vs. Titans DX
region: System246
bootprog: GDXLOAD
media: DVD
input: button
NM00018:
name: Capcom Fighting Jam
region: System246
bootprog: FJMLOAD
media: DVD
input: button
NM00019:
name: Tekken 5
region: System256
bootprog: TK5LOAD
media: DVD
input: button
clampModes:
eeClampMode: 2 # Fixes camera and stops constant coin noises on Pirates Cove.
gsHWFixes:
recommendedBlendingLevel: 3 # Improves effect rendering on various levels.
halfPixelOffset: 2 # Align post.
alignSprite: 1 # Fixes vertical lines.
nativeScaling: 1 # Fixes depth of field effect.
textureInsideRT: 1 # Fixes heat haze half screen problem.
cpuSpriteRenderBW: 1
getSkipCount: "GSC_NamcoGames"
bilinearDirtyUpscale: 1 # Fixed the issue where a sphere would appear as a cube when backlit.
autoFlush: 1
NM00020:
name: Dragon Chronicle Online - Great Sky Battle
region: System246
bootprog: DCOLOAD
media: CD
input: touchscreen
NM00021:
name: Cobra - The Arcade
region: System256
bootprog: CBRLOAD
media: HDD
input: lightgun
NM00022:
name: The IDOLM@STER
region: System256
bootprog: IDLLOAD
media: HDD
input: touchscreen
NM00023:
name: Taiko Drum Master 7
region: System256
bootprog: TA7LOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00024:
name: Mobile Suit Gundam SEED - Federation vs. Z.A.F.T.
region: System246
bootprog: SEDLOAD
media: DVD
input: button
NM00025:
name: Zoids Infinity - EX
region: System246
bootprog: ZO2LOAD
media: HDD
input: twinstick
NM00026:
name: Tekken 5 - Dark Resurrection
region: System256
bootprog: T55LOAD
media: DVD
input: button
clampModes:
eeClampMode: 2 # Fixes camera and stops constant coin noises on Pirates Cove.
gsHWFixes:
recommendedBlendingLevel: 3 # Improves effect rendering on various levels.
halfPixelOffset: 2 # Align post.
alignSprite: 1 # Fixes vertical lines.
nativeScaling: 1 # Fixes depth of field effect.
textureInsideRT: 1 # Fixes heat haze half screen problem.
cpuSpriteRenderBW: 1
getSkipCount: "GSC_NamcoGames"
bilinearDirtyUpscale: 1 # Fixes the issue where a sphere would appear as a cube when backlit.
autoFlush: 1
NM00027:
name: Super Dragon Ball Z
region: System256
bootprog: DBALOAD
media: DVD
input: button
NM00028:
name: Druaga Online - The Story of Aon
region: System256
bootprog: DRULOAD
media: DVD
input: touchscreen
NM00029:
name: Kinnikuman Muscle Grand Prix
region: System256
bootprog: KINLOAD
media: DVD
input: button
NM00030:
name: Mobile Suit Gundam Quiz Warrior
region: System246
bootprog: GQZLOAD
media: DVD
input: button
NM00031:
name: Soul Calibur III - Arcade Edition
region: System246
bootprog: SC3LOAD
media: DVD
input: button
clampModes:
vuClampMode: 2 # Respawn issues, Fixes SPS, avoids teleporting characters.
gameFixes:
- EETimingHack # Fixes bad colours on character select when in Progressive Scan.
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
nativeScaling: 2 # Fixes misaligned bloom.
NM00032:
name: Time Crisis 4
region: System SUPER256
bootprog: TC4LOAD
media: HDD
input: lightgun
NM00033:
name: Taiko Drum Master 8
region: System256
bootprog: TA8LOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00034:
name: Mobile Suit Gundam SEED Destiny - Federation vs. Z.A.F.T. II
region: System246
bootprog: SE2LOAD
media: DVD
input: button
NM00035:
name: The Battle of YuYu Hakusho - Deathmatch! Dark Martial Arts Association
region: System256
bootprog: YUULOAD
media: DVD
input: button
NM00036:
name: Whole Brain Training With Everybody
region: System256
bootprog: NTRLOAD
media: DVD
input: touchscreen
NM00037:
name: Quiz & Variety Suku Suku Inufuku 2 - More Suku Suku
region: System246
bootprog: DR2LOAD
media: CD
input: button
NM00038:
name: Taiko Drum Master 9
region: System256
bootprog: TA9LOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00039:
name: MotoGP
region: System256
bootprog: MGPLOAD
media: HDD
input: driving
NM00040:
name: Kinnikuman Muscle Grand Prix 2
region: System246
bootprog: KI2LOAD
media: DVD
input: button
NM00041:
name: Taiko Drum Master 10
region: System256
bootprog: T10LOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00042:
name: Sengoku Basara X
region: System246
bootprog: BASLOAD
media: DVD
input: button
NM00043:
name: Mobile Suit Gundam - Gundam vs. Gundam
region: System256
bootprog: GDNLOAD
media: DVD
input: button
NM00044:
name: Taiko Drum Master 11
region: System256
bootprog: T11LOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00045:
name: Taiko Drum Master 11 Asian Edition Taiwan
region: System256
bootprog: TEALOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1
NM00046:
name: Taiko Drum Master 11 - Asian Edition
region: System256
bootprog: TEBLOAD
media: DVD
input: drum
gsHWFixes:
alignSprite: 1
NM00047:
name: Ace Driver 3 - Final Turn
region: System256
bootprog: NRALOAD
media: HDD
input: driving
NM00048:
name: Fate - Unlimited Codes
region: System246
bootprog: FTELOAD
media: HDD
input: button
NM00051:
name: Taiko Drum Master 12
region: System256
bootprog: T12LOAD
media: HDD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00052:
name: Mobile Suit Gundam - Gundam vs. Gundam NEXT
region: System256
bootprog: GNXLOAD
media: HDD
input: button
NM00053:
name: Taiko Drum Master 12 - Asian Edition Taiwan
region: System256
bootprog: TECLOAD
media: HDD
input: drum
gsHWFixes:
alignSprite: 1
NM00054:
name: Taiko Drum Master 12 - Asian Edition
region: System256
bootprog: TEDLOAD
media: HDD
input: drum
gsHWFixes:
alignSprite: 1
NM00056:
name: Taiko Drum Master 13
region: System256
bootprog: T13LOAD
media: HDD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
NM00057:
name: Taiko Drum Master 14
region: System256
bootprog: T14LOAD
media: HDD
input: drum
gsHWFixes:
alignSprite: 1 # Fixes vertical lines.
File diff suppressed because it is too large. Load diff
+36 -3
View File
@@ -1,8 +1,8 @@
{
"schema_version": 1,
"generated_at": "2026-10-18T18:08:38Z",
"total_files": 19081,
"total_size": 17568664571,
"generated_at": "2026-10-19T21:13:16Z",
"total_files": 19082,
"total_size": 17568673502,
"bios_dir": "bios",
"files": {
"738c7f5fd0c8b57ee2e87ae7a97bf8e21a821d07": {
@@ -142534,6 +142534,16 @@
"crc32": "0e016ecf",
"adler32": "be32f95f"
},
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364": {
"path": "bios/Other/pcsx2x6/bin/resources/GameIndex.yaml",
"name": "GameIndex.yaml",
"size": 8931,
"sha1": "b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"md5": "bb279005ee28d778f59d2476938b5983",
"sha256": "6e80e18cecc1c2f1016e0ddc0835a9d17f255c2934edb50d16dea94e899b140b",
"crc32": "dd157af0",
"adler32": "4780cc9d"
},
"b624812e3aa0ef2f75847f47907296e1f370cecd": {
"path": "bios/Other/pcsx2x6/game_controller_db.txt",
"name": "game_controller_db.txt",
@@ -210005,6 +210015,7 @@
"9d4c94e260e14a114e79d7618bcc4331": "0572593b67aad6bb1639afba4f303f221261246f",
"5f30d9c6cabc2d121bd1c22df016e7a5": "579d3b402f27189ccb4965082e8e5de097513a81",
"7844c637dc246ec5f0e760ea33475073": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
"bb279005ee28d778f59d2476938b5983": "b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"37ce488ec574ba351c2dcf90a13d8fed": "b624812e3aa0ef2f75847f47907296e1f370cecd",
"18756952572508cb0948b3a884128a0f": "3061cf7af25793a655a1ff5a509385f3620f3eb3",
"b73761d82a77f73006145848a00c515b": "0c8c9706abc0116f08b66d11a69da6aa9ef7e6bf",
@@ -248336,6 +248347,7 @@
"997fdfb1c1873c1a43972b2984ac0da61fd47b14",
"fca26d4f7c1fe0abf6534b470da2ee5ad461eba5",
"58fb1f8ea6cf2d526904349640453e682fe388a1",
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"7efb2ed721cf0c0f0677324e09be311a8337e793",
"57369df9ca82a460e596cea7835c5a0797dee668",
"b22389650f6c0a1e276b48213fed8a9c1c6476ce",
@@ -286002,6 +286014,7 @@
"b4308300": "0572593b67aad6bb1639afba4f303f221261246f",
"ef4efa89": "579d3b402f27189ccb4965082e8e5de097513a81",
"0e016ecf": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
"dd157af0": "b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"eef26072": "b624812e3aa0ef2f75847f47907296e1f370cecd",
"611423b6": "3061cf7af25793a655a1ff5a509385f3620f3eb3",
"43f15403": "0c8c9706abc0116f08b66d11a69da6aa9ef7e6bf",
@@ -305085,6 +305098,7 @@
"1c85b8f1d13b37ab157b6f4b256c687c83a12c0dc5fe7f13fb562ed73c3aec45": "0572593b67aad6bb1639afba4f303f221261246f",
"cac33fe9739f97e1fcb7af00494ebfb83d5bbc200cc065f32012fc16f0b5fbdc": "579d3b402f27189ccb4965082e8e5de097513a81",
"f68a569f71fc090cec61bc5f699d0553dca7c5d012166709e74fc6c72568fdc2": "2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2",
"6e80e18cecc1c2f1016e0ddc0835a9d17f255c2934edb50d16dea94e899b140b": "b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"49f94f7bc9fc605cbf60457937429e3c8499e515d8164b7dd7cd0345844fc86a": "b624812e3aa0ef2f75847f47907296e1f370cecd",
"ae7b7855e115a5966d8b1b3f80f254ccc117ec86f9965e202ee2940453837280": "3061cf7af25793a655a1ff5a509385f3620f3eb3",
"af19d135d3a935b3ebfbd80320716ffe1202052c5f68dc2c5f1abc57005ac605": "0c8c9706abc0116f08b66d11a69da6aa9ef7e6bf",
@@ -471535,6 +471549,7 @@
"71fc274cbe27f382afb0324024ebdc6f59aa666d",
"72bfdf91fa11a86e2810a7c167cdcf11e20418a8",
"2d9878fdd70979ecf6dd0da7652efd3797c26039",
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364",
"40ecf6138c99a0aba775ef93240b295025a45500"
],
"Other/altirra/.variants/810-archiver.rom.8080d51e": [
@@ -480461,6 +480476,15 @@
"tandy/tandy1t1.020": [
"2f5ac8921b7cba56b02122ef772f5f11bbf6d8a2"
],
"Other/pcsx2x6/bin/resources/GameIndex.yaml": [
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364"
],
"pcsx2x6/bin/resources/GameIndex.yaml": [
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364"
],
"bin/resources/GameIndex.yaml": [
"b1e1fd4c082c0d8c11e2b5ecc8119fc280323364"
],
"Other/pcsx2x6/game_controller_db.txt": [
"b624812e3aa0ef2f75847f47907296e1f370cecd"
],
@@ -565979,6 +566003,15 @@
"flags/PAL-M.png": [
"c78cd2ff8c2f363043a753b663af8855ee3b02f5"
],
"Other/pcsx2x6/bin/resources/RedumpDatabase.yaml": [
"dceb4536fba7fb89452864fc512a4d071a19eae0"
],
"pcsx2x6/bin/resources/RedumpDatabase.yaml": [
"dceb4536fba7fb89452864fc512a4d071a19eae0"
],
"bin/resources/RedumpDatabase.yaml": [
"dceb4536fba7fb89452864fc512a4d071a19eae0"
],
"Other/skyline/tzdata/zoneinfo/Africa/Asmara": [
"4650b524081009959e8487ed97c07a331c13fd2d"
],
+26 -1
View File
@@ -897,6 +897,14 @@ def _foreign_tree(path: str, owners: set[str]) -> bool:
return not (owners & _affinity_tokens(parts[2]))
def _own_tree(path: str, owners: set[str]) -> bool:
"""Whether a path lives in the bios/Other/<emulator>/ tree of the asker."""
parts = path.split("/")
if not owners or len(parts) < 4 or parts[0] != "bios" or parts[1] != "Other":
return False
return bool(owners & _affinity_tokens(parts[2]))
def _rank_tail_candidates(
candidates: list[str], start: int, tail: str, files_db: dict, owners: set[str],
asker: frozenset[str] = frozenset(),
@@ -921,9 +929,14 @@ def _rank_tail_candidates(
# pins on every desktop target. A platform's own declaration has no
# asker, and the tree whose path is its destination still answers it.
if start or asker:
# The database keeps one path per content. When that path does not
# end with the tail, the tail was indexed from an identical copy
# elsewhere, and the recorded path says nothing about whose tree it
# sits in: PCSX2x6's RedumpDatabase.yaml has EmuCoreX's bytes.
candidates = [
h for h in candidates
if not _foreign_tree(path_of(h), owners if start else set(asker))
if not path_of(h).endswith("/" + tail)
or not _foreign_tree(path_of(h), owners if start else set(asker))
]
if len(candidates) < 2:
return candidates
@@ -1304,6 +1317,18 @@ def resolve_local_file(
by_path_suffix.get(tail, []), start, tail, files_db, owners,
frozenset(_owner_tokens(file_entry)),
)
raw = by_path_suffix.get(tail, [])
if start and len(raw) > 1:
# Ambiguity is read before the foreign trees are set aside:
# PCSX2x6's bin/resources/GameIndex.yaml met four copies
# under resources/GameIndex.yaml, three in other emulators'
# trees, and the fourth (PCSX2's console database, not
# PCSX2x6's arcade one) passed for proof. Only the asker's own
# tree still answers a tail several files share.
candidates = [
h for h in candidates
if _own_tree(files_db.get(h, {}).get("path", ""), owners)
]
if start and len(candidates) > 1:
continue
# The index names the file this destination designates. Not on
+59
View File
@@ -192,5 +192,64 @@ class TestSizeGateOnTheNameStep(unittest.TestCase):
self.assertIsNotNone(path)
class TestForeignTreesAndSharedTails(unittest.TestCase):
"""PCSX2x6's arcade GameIndex.yaml met four copies under a shortened
tail: three in other emulators' trees and PCSX2's console database. The
three were set aside first, the fourth then looked unique and passed for
path proof."""
@classmethod
def setUpClass(cls):
cls.root = Path(tempfile.mkdtemp(prefix="foreign-"))
cls.previous = os.getcwd()
stored = {
"1" * 40: "bios/Other/aethersx2/resources/GameIndex.yaml",
"2" * 40: "bios/Other/armsx2/resources/GameIndex.yaml",
"3" * 40: "bios/Other/emucorex/resources/GameIndex.yaml",
"4" * 40: "bios/Sony/PlayStation 2/resources/GameIndex.yaml",
"5" * 40: "bios/Other/emucorex/resources/RedumpDatabase.yaml",
}
# Same bytes as emucorex's copy: the database keeps one path for it.
duplicate = ("5" * 40, "bios/Other/x6/bin/resources/RedumpDatabase.yaml")
files, by_name, by_suffix = {}, {}, {}
for sha1, rel in [*stored.items(), duplicate]:
target = cls.root / rel
target.parent.mkdir(parents=True, exist_ok=True)
target.write_bytes(sha1[:4].encode())
name = rel.rsplit("/", 1)[-1]
if sha1 not in files:
files[sha1] = {"path": rel, "name": name, "md5": "", "size": 4,
"crc32": "", "sha1": sha1}
by_name.setdefault(name, []).append(sha1)
for suffix in _path_suffixes(rel):
if sha1 not in by_suffix.setdefault(suffix, []):
by_suffix[suffix].append(sha1)
cls.db = {
"files": files,
"indexes": {"by_md5": {}, "by_name": by_name, "by_crc32": {},
"by_path_suffix": by_suffix},
}
os.chdir(cls.root)
@classmethod
def tearDownClass(cls):
os.chdir(cls.previous)
shutil.rmtree(cls.root, ignore_errors=True)
def test_a_shared_shortened_tail_proves_nothing(self):
_path, status = resolve_local_file(
{"name": "GameIndex.yaml", "source_profile": "x6"}, self.db,
dest_hint="bin/resources/GameIndex.yaml",
)
self.assertNotEqual(status, "path_exact")
def test_a_tail_indexed_from_a_duplicate_is_the_askers(self):
path, status = resolve_local_file(
{"name": "RedumpDatabase.yaml", "source_profile": "x6"}, self.db,
dest_hint="bin/resources/RedumpDatabase.yaml",
)
self.assertEqual((status, path), ("path_exact", "bios/Other/emucorex/resources/RedumpDatabase.yaml"))
if __name__ == "__main__":
unittest.main()