From c1220d13c352897d83aeaea1895ec2440451727f Mon Sep 17 00:00:00 2001 From: Danilo Reyes Date: Wed, 3 Dec 2025 23:37:06 -0600 Subject: [PATCH] Add multi-disc game detection and handling in ROM processing --- main.py | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/main.py b/main.py index 862006a..e60273d 100644 --- a/main.py +++ b/main.py @@ -119,6 +119,73 @@ def get_language_count(rom: Dict) -> int: return len(languages) if languages else 0 +def _matches_disc_pattern(text: str, patterns: List[str]) -> bool: + """Check if text matches any disc pattern.""" + return any(re.search(pattern, text.lower()) for pattern in patterns) + + +def _check_tags_for_disc(tags: List) -> bool: + """Check if tags contain disc indicators.""" + tag_patterns = [ + r"disc\s*\d+", + r"disk\s*\d+", + r"cd\s*\d+", + r"dvd\s*\d+", + r"part\s*\d+", + r"disc\s*[a-z]", + r"disk\s*[a-z]", + ] + return any( + _matches_disc_pattern(str(tag), tag_patterns) + for tag in filter(None, tags) + ) + + +def _check_name_for_disc(name: str) -> bool: + """Check if name contains disc indicators.""" + name_patterns = [ + r"\(disc\s*\d+\)", + r"\(disk\s*\d+\)", + r"\[disc\s*\d+\]", + r"\[disk\s*\d+\]", + r"disc\s*\d+", + r"disk\s*\d+", + r"\(cd\s*\d+\)", + r"\(dvd\s*\d+\)", + r"part\s*\d+", + ] + return bool(name) and _matches_disc_pattern(str(name), name_patterns) + + +def _check_filename_for_disc(fs_name: str) -> bool: + """Check if filename contains disc indicators.""" + filename_patterns = [ + r"disc\s*\d+", + r"disk\s*\d+", + r"cd\s*\d+", + r"dvd\s*\d+", + r"\(disc\s*\d+\)", + r"\(disk\s*\d+\)", + r"\[disc\s*\d+\]", + r"\[disk\s*\d+\]", + ] + return bool(fs_name) and _matches_disc_pattern(str(fs_name), filename_patterns) + + +def is_multi_disc_game(rom: Dict) -> bool: + """Check if ROM is part of a multi-disc game by scanning tags and name.""" + return ( + _check_tags_for_disc(rom.get("tags", [])) + or _check_name_for_disc(rom.get("name", "")) + or _check_filename_for_disc(rom.get("fs_name", "")) + ) + + +def has_multi_disc_roms(group: List[Dict]) -> bool: + """Check if a group contains any multi-disc game ROMs.""" + return any(map(is_multi_disc_game, group)) + + def get_metadata_score(rom: Dict) -> int: """Calculate a score based on metadata completeness.""" score_map = { @@ -255,6 +322,16 @@ def process_group( if group_ids & processed_ids: return [] + # Skip deletion if this group contains multi-disc games + if has_multi_disc_roms(group): + print(f"Group: {group_name}") + print(" ⚠️ SKIPPED: Contains multi-disc game ROMs (all discs are needed)") + for rom in group: + score = rom_preference_score(rom) + print_rom_info(rom, score, " Keeping: ") + print() + return [] + scored_roms = score_roms(group) best_rom, delete_roms = select_best_rom(scored_roms)