[Scummvm-git-logs] scummvm master -> 2e9862863c1245eadeebc370a9602fea76319c28

sev- noreply at scummvm.org
Wed Apr 24 22:28:47 UTC 2024


This automated email contains information about 7 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
90ab5bfa5a DEVTOOLS: DUMPERCOMPANION: support iso9660 and hybrid disk images
11279cd07a DEVTOOLS: DUMPERCOMPANION: support Joliet, Rock Ridge and UDF extensions
4aa571b95f DEVTOOLS: DUMPERCOMPANION: support puny encoding, japanese and dry run for iso9660
37b9bbb32f DEVTOOLS: COMPANION: Add autodetection of file system and extensions if unspecified
7e4da992ca DEVTOOLS: COMPANION: Add probe parser and --silent flag in ISO parser
15efeac016 DEVTOOLS: COMPANION: Add enums for file systems and extensions
2e9862863c DEVTOOLS: COMPANION: Add version checker pycdlib module


Commit: 90ab5bfa5aeec7ee3ed2c837e55ce0aa0ce0d3a9
    https://github.com/scummvm/scummvm/commit/90ab5bfa5aeec7ee3ed2c837e55ce0aa0ce0d3a9
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: DUMPERCOMPANION: support iso9660 and hybrid disk images

Add parsers to handle iso9660 and hybrid disk images

Add functions for extracting iso9660 and hybrid disk images

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index c85db87cd48..c37e911dc3c 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -7,7 +7,7 @@
 # See https://wiki.scummvm.org/index.php?title=HOWTO-Dump_Macintosh_Media for
 # the full documentation
 #
-# prerequisites: pip3 install machfs
+# prerequisites: pip3 install machfs pycdlib
 #
 # Development information:
 # This file contains tests. They can be run with:
@@ -31,6 +31,7 @@ from struct import pack, unpack
 from typing import Any
 
 import machfs
+import pycdlib
 
 
 # fmt: off
@@ -289,7 +290,7 @@ def encode_string(args: argparse.Namespace) -> int:
     return 0
 
 
-def extract_volume(args: argparse.Namespace) -> int:
+def extract_volume_hfs(args: argparse.Namespace) -> int:
     """Extract an HFS volume"""
     source_volume: Path = args.src
     loglevel: str = args.log
@@ -340,6 +341,62 @@ def extract_volume(args: argparse.Namespace) -> int:
             extract_partition(args, vol)
 
 
+def extract_volume_iso(args: argparse.Namespace):
+    """Extract an ISO volume"""
+    source_volume = args.src
+    loglevel: str = args.log
+
+    numeric_level = getattr(logging, loglevel.upper(), None)
+    if not isinstance(numeric_level, int):
+        raise ValueError("Invalid log level: %s" % loglevel)
+    logging.basicConfig(format="%(levelname)s: %(message)s", level=numeric_level)
+
+    logging.info(f"Loading {source_volume} ...")
+
+    iso = pycdlib.PyCdlib()
+    iso.open(source_volume)
+
+    output_dir = str(args.dir)
+
+    for dirname, dirlist, filelist in iso.walk(iso_path='/'):
+        pwd = output_dir + dirname
+        for dir in dirlist:
+            joined_path = os.path.join(pwd, dir)
+            os.makedirs(joined_path, exist_ok=True)
+        for file in filelist:
+            filename = file.split(';')[0]
+            if dirname != '/':
+                iso_file_path = dirname + '/' + file
+            else:
+                iso_file_path = dirname + file
+            with open(os.path.join(pwd, filename), 'wb') as f:
+                iso.get_file_from_iso_fp(outfp=f, iso_path=iso_file_path)
+
+    iso.close()
+
+
+def extract_volume_hybrid(args: argparse.Namespace):
+    source_volume = args.src
+    loglevel: str = args.log
+
+    numeric_level = getattr(logging, loglevel.upper(), None)
+    if not isinstance(numeric_level, int):
+        raise ValueError("Invalid log level: %s" % loglevel)
+    logging.basicConfig(format="%(levelname)s: %(message)s", level=numeric_level)
+
+    logging.info(f"Loading {source_volume} ...")
+
+    if not args.macdump and not args.iso9660dump:
+        logging.error("Please provide at least one dump for the hybrid drive")
+        return
+    if args.macdump:
+        args.dir = args.macdump
+        extract_volume_hfs(args)
+    if args.iso9660dump:
+        args.dir = args.iso9660dump
+        extract_volume_iso(args)
+
+
 def extract_partition(args: argparse.Namespace, vol) -> int:
     destination_dir: Path = args.dir
     japanese: bool = args.japanese
@@ -731,35 +788,81 @@ def generate_parser() -> argparse.ArgumentParser:
     """
     parser = argparse.ArgumentParser()
     subparsers = parser.add_subparsers()
-    parser_iso = subparsers.add_parser("iso", help="Dump HFS ISOs")
+    parser_hfs = subparsers.add_parser("hfs", help="Dump HFS ISOs")
 
-    parser_iso.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
-    parser_iso.add_argument(
+    parser_hfs.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
+    parser_hfs.add_argument(
         "--nopunycode", action="store_true", help="never encode pathnames into punycode"
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "--japanese", action="store_true", help="read MacJapanese HFS"
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "--dryrun", action="store_true", help="do not write any files"
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "--log", metavar="LEVEL", help="set logging level", default="INFO"
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "--forcemacbinary",
         action="store_true",
         help="always encode using MacBinary, even for files with no resource fork",
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "--addmacbinaryext",
         action="store_true",
         help="add .bin extension when using MacBinary",
     )
-    parser_iso.add_argument(
+    parser_hfs.add_argument(
         "dir", metavar="OUTPUT", type=Path, help="Destination folder"
     )
-    parser_iso.set_defaults(func=extract_volume)
+    parser_hfs.set_defaults(func=extract_volume_hfs)
+
+    parser_iso9660 = subparsers.add_parser(
+        "iso9660", help="Dump ISO9660 ISOs"
+    )
+    parser_iso9660.add_argument(
+        "--log", metavar="LEVEL", help="set logging level", default="INFO"
+    )
+    parser_iso9660.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
+    parser_iso9660.add_argument(
+        "dir", metavar="OUTPUT", type=Path, help="Destination folder"
+    )
+    parser_iso9660.set_defaults(func=extract_volume_iso)
+
+    parser_hybrid = subparsers.add_parser(
+        "hybrid", help="Dump Hybrid ISOs"
+    )
+    parser_hybrid.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
+    parser_hybrid.add_argument(
+        "--nopunycode", action="store_true", help="never encode pathnames into punycode"
+    )
+    parser_hybrid.add_argument(
+        "--japanese", action="store_true", help="read MacJapanese HFS"
+    )
+    parser_hybrid.add_argument(
+        "--dryrun", action="store_true", help="do not write any files"
+    )
+    parser_hybrid.add_argument(
+        "--log", metavar="LEVEL", help="set logging level", default="INFO"
+    )
+    parser_hybrid.add_argument(
+        "--forcemacbinary",
+        action="store_true",
+        help="always encode using MacBinary, even for files with no resource fork",
+    )
+    parser_hybrid.add_argument(
+        "--addmacbinaryext",
+        action="store_true",
+        help="add .bin extension when using MacBinary",
+    )
+    parser_hybrid.add_argument(
+        "--macdump", metavar="OUTPUT", type=Path, help="Destination Folder for HFS Dump"
+    )
+    parser_hybrid.add_argument(
+        "--iso9660dump", metavar="OUTPUT", type=Path, help="Destination Folder for ISO9660 Dump"
+    )
+    parser_hybrid.set_defaults(func=extract_volume_hybrid)
 
     parser_dir = subparsers.add_parser(
         "dir", help="Punyencode all files and dirs in place"


Commit: 11279cd07a916129dc45edc437f723b88889e7e0
    https://github.com/scummvm/scummvm/commit/11279cd07a916129dc45edc437f723b88889e7e0
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: DUMPERCOMPANION: support Joliet, Rock Ridge and UDF extensions

Add '--extension' argument to handle different iso9660 extensions

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index c37e911dc3c..9bd495811f5 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -358,19 +358,28 @@ def extract_volume_iso(args: argparse.Namespace):
 
     output_dir = str(args.dir)
 
-    for dirname, dirlist, filelist in iso.walk(iso_path='/'):
+    if not args.extension:
+        path_type = 'iso_path'
+    elif args.extension == 'joliet':
+        path_type = 'joliet_path'
+    elif args.extension == 'rr':
+        path_type = 'rr_type'
+    else:
+        path_type = 'udf_path'
+
+    arg = {path_type: '/'}
+
+    for dirname, dirlist, filelist in iso.walk(**arg):
         pwd = output_dir + dirname
         for dir in dirlist:
             joined_path = os.path.join(pwd, dir)
             os.makedirs(joined_path, exist_ok=True)
         for file in filelist:
             filename = file.split(';')[0]
-            if dirname != '/':
-                iso_file_path = dirname + '/' + file
-            else:
-                iso_file_path = dirname + file
+            iso_file_path = os.path.join(dirname, filename)
             with open(os.path.join(pwd, filename), 'wb') as f:
-                iso.get_file_from_iso_fp(outfp=f, iso_path=iso_file_path)
+                arg[path_type] = iso_file_path
+                iso.get_file_from_iso_fp(outfp=f, **arg)
 
     iso.close()
 
@@ -824,6 +833,7 @@ def generate_parser() -> argparse.ArgumentParser:
     parser_iso9660.add_argument(
         "--log", metavar="LEVEL", help="set logging level", default="INFO"
     )
+    parser_iso9660.add_argument("--extension", choices=['joliet', 'rr', 'udf'], metavar="EXTENSION", help="Use if the iso9660 has an extension")
     parser_iso9660.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
     parser_iso9660.add_argument(
         "dir", metavar="OUTPUT", type=Path, help="Destination folder"


Commit: 4aa571b95f2f4f55744ca6cbe320ca33774421d6
    https://github.com/scummvm/scummvm/commit/4aa571b95f2f4f55744ca6cbe320ca33774421d6
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: DUMPERCOMPANION: support puny encoding, japanese and dry run for iso9660

Add optional arguments '--japanese', '--no-punyencode' and '--dryrun' for dealing with 'shift_jis' encoded filenames, disregarding puny encoding and dry running the script respectively

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index 9bd495811f5..484bdfc1c84 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -345,6 +345,9 @@ def extract_volume_iso(args: argparse.Namespace):
     """Extract an ISO volume"""
     source_volume = args.src
     loglevel: str = args.log
+    dopunycode: bool = not args.nopunycode
+    dryrun: bool = args.dryrun
+    japanese: bool = args.japanese
 
     numeric_level = getattr(logging, loglevel.upper(), None)
     if not isinstance(numeric_level, int):
@@ -363,24 +366,35 @@ def extract_volume_iso(args: argparse.Namespace):
     elif args.extension == 'joliet':
         path_type = 'joliet_path'
     elif args.extension == 'rr':
-        path_type = 'rr_type'
+        path_type = 'rr_path'
     else:
         path_type = 'udf_path'
 
     arg = {path_type: '/'}
 
+    if japanese:
+        arg['encoding'] = 'shift_jis'
+
     for dirname, dirlist, filelist in iso.walk(**arg):
         pwd = output_dir + dirname
         for dir in dirlist:
             joined_path = os.path.join(pwd, dir)
-            os.makedirs(joined_path, exist_ok=True)
+            if not dryrun:
+                os.makedirs(joined_path, exist_ok=True)
+            else:
+                print(joined_path)
+
+        if dryrun:
+            continue
+
         for file in filelist:
             filename = file.split(';')[0]
             iso_file_path = os.path.join(dirname, filename)
             with open(os.path.join(pwd, filename), 'wb') as f:
                 arg[path_type] = iso_file_path
                 iso.get_file_from_iso_fp(outfp=f, **arg)
-
+    if dopunycode:
+        punyencode_dir(Path(output_dir))
     iso.close()
 
 
@@ -834,6 +848,15 @@ def generate_parser() -> argparse.ArgumentParser:
         "--log", metavar="LEVEL", help="set logging level", default="INFO"
     )
     parser_iso9660.add_argument("--extension", choices=['joliet', 'rr', 'udf'], metavar="EXTENSION", help="Use if the iso9660 has an extension")
+    parser_iso9660.add_argument(
+        "--nopunycode", action="store_true", help="never encode pathnames into punycode"
+    )
+    parser_iso9660.add_argument(
+        "--dryrun", action="store_true", help="do not write any files"
+    )
+    parser_iso9660.add_argument(
+        "--japanese", action="store_true", help="read MacJapanese HFS"
+    )
     parser_iso9660.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
     parser_iso9660.add_argument(
         "dir", metavar="OUTPUT", type=Path, help="Destination folder"


Commit: 37b9bbb32f3435490dccd28938a13927ca06303f
    https://github.com/scummvm/scummvm/commit/37b9bbb32f3435490dccd28938a13927ca06303f
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: COMPANION: Add autodetection of file system and extensions if unspecified

Add functions which detect the file system (which was provided on discord thanks to eintei) and extensions if not specified by the user; combine iso9660, hfs and hybrid parsers into one common iso parser

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index 484bdfc1c84..d8c56e7dcb6 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -18,6 +18,7 @@
 from __future__ import annotations
 
 import argparse
+import copy
 import logging
 import os
 import sys
@@ -290,6 +291,82 @@ def encode_string(args: argparse.Namespace) -> int:
     return 0
 
 
+def check_extension(args):
+    args_copy = copy.copy(args)
+    args_copy.dryrun = True
+    extensions = ['joliet', 'rr', 'udf']
+    args_copy.dir = args.dir.joinpath('test')
+    args_copy.fs = 'iso9660'
+    args.silent = True
+    for extension in extensions:
+        args_copy.extension = extension
+        try:
+            extract_volume_iso(args_copy)
+        except Exception as e:
+            pass
+        else:
+            return extension
+
+
+def check_fs(iso):
+    APPLE_PM_SIGNATURE = b"PM\x00\x00"
+    SECTOR_SIZE = 512
+
+    disk_formats = []
+    f = open(iso, "rb")
+
+    # ISO Primary Volume Descriptor
+    f.seek(64 * SECTOR_SIZE)
+    if f.read(6) == b"\x01CD001":
+        # print('Found ISO PVD')
+        disk_formats.append("iso9660")
+
+    f.seek(0)
+    mac_1 = f.read(4)
+    f.seek(1 * SECTOR_SIZE)
+    mac_2 = f.read(4)
+    f.seek(2 * SECTOR_SIZE)
+    mac_3 = f.read(2)
+    if mac_2 == APPLE_PM_SIGNATURE:
+        partition_num = 1
+        while True:
+            num_partitions, partition_start, partition_size = unpack(">III", f.read(12))
+            f.seek(32, 1)
+            partition_type = f.read(32).decode("mac-roman").split("\x00")[0]
+            if partition_type == "Apple_HFS":
+                disk_formats.append("hfs")
+                break
+            # Check if there are more partitions
+            if partition_num <= num_partitions:
+                # Move onto the next partition
+                partition_num += 1
+                f.seek(partition_num * SECTOR_SIZE + 4)
+    # Bootable Mac-only disc
+    elif mac_1 == b"LK\x60\x00" and mac_3 == b"BD":
+        disk_formats.append("hfs")
+
+    if len(disk_formats) > 1:
+        return 'hybrid'
+    else:
+        return disk_formats[0]
+
+
+def extract_iso(args: argparse.Namespace):
+    if not args.fs:
+        args.fs = check_fs(args.src)
+        print('Detected filesystem:', args.fs)
+    if (args.fs == 'hybrid' or args.fs == 'iso9660') and not args.extension:
+        args.extension = check_extension(args)
+        print('Detected extension:', args.extension)
+
+    if args.fs == 'iso9660':
+        extract_volume_iso(args)
+    elif args.fs == 'hfs':
+        extract_volume_hfs(args)
+    else:
+        extract_volume_hybrid(args)
+
+
 def extract_volume_hfs(args: argparse.Namespace) -> int:
     """Extract an HFS volume"""
     source_volume: Path = args.src
@@ -381,7 +458,7 @@ def extract_volume_iso(args: argparse.Namespace):
             joined_path = os.path.join(pwd, dir)
             if not dryrun:
                 os.makedirs(joined_path, exist_ok=True)
-            else:
+            elif not args.silent:
                 print(joined_path)
 
         if dryrun:
@@ -389,7 +466,7 @@ def extract_volume_iso(args: argparse.Namespace):
 
         for file in filelist:
             filename = file.split(';')[0]
-            iso_file_path = os.path.join(dirname, filename)
+            iso_file_path = os.path.join(dirname, file)
             with open(os.path.join(pwd, filename), 'wb') as f:
                 arg[path_type] = iso_file_path
                 iso.get_file_from_iso_fp(outfp=f, **arg)
@@ -409,15 +486,13 @@ def extract_volume_hybrid(args: argparse.Namespace):
 
     logging.info(f"Loading {source_volume} ...")
 
-    if not args.macdump and not args.iso9660dump:
-        logging.error("Please provide at least one dump for the hybrid drive")
-        return
-    if args.macdump:
-        args.dir = args.macdump
-        extract_volume_hfs(args)
-    if args.iso9660dump:
-        args.dir = args.iso9660dump
-        extract_volume_iso(args)
+    main_dir = args.dir
+
+    args.dir = main_dir.joinpath('hfs')
+    extract_volume_hfs(args)
+
+    args.dir = main_dir.joinpath('iso9660')
+    extract_volume_iso(args)
 
 
 def extract_partition(args: argparse.Namespace, vol) -> int:
@@ -811,91 +886,39 @@ def generate_parser() -> argparse.ArgumentParser:
     """
     parser = argparse.ArgumentParser()
     subparsers = parser.add_subparsers()
-    parser_hfs = subparsers.add_parser("hfs", help="Dump HFS ISOs")
+    parser_iso = subparsers.add_parser("iso", help="Dump HFS ISOs")
 
-    parser_hfs.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
-    parser_hfs.add_argument(
+    parser_iso.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
+    parser_iso.add_argument(
         "--nopunycode", action="store_true", help="never encode pathnames into punycode"
     )
-    parser_hfs.add_argument(
+    parser_iso.add_argument(
         "--japanese", action="store_true", help="read MacJapanese HFS"
     )
-    parser_hfs.add_argument(
+    parser_iso.add_argument(
         "--dryrun", action="store_true", help="do not write any files"
     )
-    parser_hfs.add_argument(
+    parser_iso.add_argument(
         "--log", metavar="LEVEL", help="set logging level", default="INFO"
     )
-    parser_hfs.add_argument(
+    parser_iso.add_argument(
         "--forcemacbinary",
         action="store_true",
         help="always encode using MacBinary, even for files with no resource fork",
     )
-    parser_hfs.add_argument(
+    parser_iso.add_argument(
         "--addmacbinaryext",
         action="store_true",
         help="add .bin extension when using MacBinary",
     )
-    parser_hfs.add_argument(
-        "dir", metavar="OUTPUT", type=Path, help="Destination folder"
-    )
-    parser_hfs.set_defaults(func=extract_volume_hfs)
-
-    parser_iso9660 = subparsers.add_parser(
-        "iso9660", help="Dump ISO9660 ISOs"
-    )
-    parser_iso9660.add_argument(
-        "--log", metavar="LEVEL", help="set logging level", default="INFO"
-    )
-    parser_iso9660.add_argument("--extension", choices=['joliet', 'rr', 'udf'], metavar="EXTENSION", help="Use if the iso9660 has an extension")
-    parser_iso9660.add_argument(
-        "--nopunycode", action="store_true", help="never encode pathnames into punycode"
-    )
-    parser_iso9660.add_argument(
-        "--dryrun", action="store_true", help="do not write any files"
-    )
-    parser_iso9660.add_argument(
-        "--japanese", action="store_true", help="read MacJapanese HFS"
-    )
-    parser_iso9660.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
-    parser_iso9660.add_argument(
+    parser_iso.add_argument("--extension", choices=['joliet', 'rr', 'udf'], metavar="EXTENSION",
+                            help="Use if the iso9660 has an extension")
+    parser_iso.add_argument("--fs", choices=['iso9660', 'hfs', 'hybrid'], metavar="FILE_SYSTEM",
+                            help="Specify the file system of the ISO")
+    parser_iso.add_argument(
         "dir", metavar="OUTPUT", type=Path, help="Destination folder"
     )
-    parser_iso9660.set_defaults(func=extract_volume_iso)
-
-    parser_hybrid = subparsers.add_parser(
-        "hybrid", help="Dump Hybrid ISOs"
-    )
-    parser_hybrid.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
-    parser_hybrid.add_argument(
-        "--nopunycode", action="store_true", help="never encode pathnames into punycode"
-    )
-    parser_hybrid.add_argument(
-        "--japanese", action="store_true", help="read MacJapanese HFS"
-    )
-    parser_hybrid.add_argument(
-        "--dryrun", action="store_true", help="do not write any files"
-    )
-    parser_hybrid.add_argument(
-        "--log", metavar="LEVEL", help="set logging level", default="INFO"
-    )
-    parser_hybrid.add_argument(
-        "--forcemacbinary",
-        action="store_true",
-        help="always encode using MacBinary, even for files with no resource fork",
-    )
-    parser_hybrid.add_argument(
-        "--addmacbinaryext",
-        action="store_true",
-        help="add .bin extension when using MacBinary",
-    )
-    parser_hybrid.add_argument(
-        "--macdump", metavar="OUTPUT", type=Path, help="Destination Folder for HFS Dump"
-    )
-    parser_hybrid.add_argument(
-        "--iso9660dump", metavar="OUTPUT", type=Path, help="Destination Folder for ISO9660 Dump"
-    )
-    parser_hybrid.set_defaults(func=extract_volume_hybrid)
+    parser_iso.set_defaults(func=extract_iso)
 
     parser_dir = subparsers.add_parser(
         "dir", help="Punyencode all files and dirs in place"


Commit: 7e4da992ca250d766a853a7ef46078420341a42c
    https://github.com/scummvm/scummvm/commit/7e4da992ca250d766a853a7ef46078420341a42c
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: COMPANION: Add probe parser and --silent flag in ISO parser

Add new parser probe which detects the file system, extension and presence of japanese of a provided ISO; Add a silent flag that disables all print and log messages

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index d8c56e7dcb6..54a82996ed5 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -291,13 +291,53 @@ def encode_string(args: argparse.Namespace) -> int:
     return 0
 
 
+def probe_iso(args):
+    fs = check_fs(args.src)
+    print('Detected file system:', fs)
+    args.fs = fs
+    args.dryrun = True
+    args.dir = Path('testing')
+    args.silent = True
+    args.forcemacbinary = False
+    args.addmacbinaryext = False
+    args.log = 'INFO'
+    args.nopunycode = False
+    args.japanese = False
+    if fs == 'hybrid' or fs == 'iso9660':
+        args.extension = check_extension(args)
+        print('Detected extension:', args.extension)
+    print('Japanese detected:', check_japanese(args))
+
+
+def check_japanese(args):
+    args.japanese = False
+    if args.fs == 'hybrid':
+        fn = extract_volume_hybrid
+    elif args.fs == 'iso9660':
+        fn = extract_volume_iso
+    else:
+        fn = extract_volume_hfs
+    try:
+        fn(args)
+    except Exception as e:
+        args.japanese = True
+        try:
+            fn(args)
+        except Exception as e:
+            raise Exception('Could not determine japanese')
+        else:
+            return True
+    else:
+        return False
+
+
 def check_extension(args):
     args_copy = copy.copy(args)
     args_copy.dryrun = True
     extensions = ['joliet', 'rr', 'udf']
     args_copy.dir = args.dir.joinpath('test')
     args_copy.fs = 'iso9660'
-    args.silent = True
+    args_copy.silent = True
     for extension in extensions:
         args_copy.extension = extension
         try:
@@ -371,13 +411,15 @@ def extract_volume_hfs(args: argparse.Namespace) -> int:
     """Extract an HFS volume"""
     source_volume: Path = args.src
     loglevel: str = args.log
+    silent: bool = args.silent
 
     numeric_level = getattr(logging, loglevel.upper(), None)
     if not isinstance(numeric_level, int):
         raise ValueError("Invalid log level: %s" % loglevel)
     logging.basicConfig(format="%(levelname)s: %(message)s", level=numeric_level)
 
-    logging.info(f"Loading {source_volume} ...")
+    if not silent:
+        logging.info(f"Loading {source_volume} ...")
     vol = machfs.Volume()
     partitions = []
     with source_volume.open(mode="rb") as f:
@@ -425,13 +467,15 @@ def extract_volume_iso(args: argparse.Namespace):
     dopunycode: bool = not args.nopunycode
     dryrun: bool = args.dryrun
     japanese: bool = args.japanese
+    silent: bool = args.silent
 
     numeric_level = getattr(logging, loglevel.upper(), None)
     if not isinstance(numeric_level, int):
         raise ValueError("Invalid log level: %s" % loglevel)
     logging.basicConfig(format="%(levelname)s: %(message)s", level=numeric_level)
 
-    logging.info(f"Loading {source_volume} ...")
+    if not silent:
+        logging.info(f"Loading {source_volume} ...")
 
     iso = pycdlib.PyCdlib()
     iso.open(source_volume)
@@ -458,7 +502,7 @@ def extract_volume_iso(args: argparse.Namespace):
             joined_path = os.path.join(pwd, dir)
             if not dryrun:
                 os.makedirs(joined_path, exist_ok=True)
-            elif not args.silent:
+            elif not silent:
                 print(joined_path)
 
         if dryrun:
@@ -478,21 +522,25 @@ def extract_volume_iso(args: argparse.Namespace):
 def extract_volume_hybrid(args: argparse.Namespace):
     source_volume = args.src
     loglevel: str = args.log
+    silent: bool = args.silent
 
     numeric_level = getattr(logging, loglevel.upper(), None)
     if not isinstance(numeric_level, int):
         raise ValueError("Invalid log level: %s" % loglevel)
     logging.basicConfig(format="%(levelname)s: %(message)s", level=numeric_level)
 
-    logging.info(f"Loading {source_volume} ...")
+    if not silent:
+        logging.info(f"Loading {source_volume} ...")
 
     main_dir = args.dir
 
-    args.dir = main_dir.joinpath('hfs')
-    extract_volume_hfs(args)
+    args_copy = copy.copy(args)
+
+    args_copy.dir = main_dir.joinpath('hfs')
+    extract_volume_hfs(args_copy)
 
-    args.dir = main_dir.joinpath('iso9660')
-    extract_volume_iso(args)
+    args_copy.dir = main_dir.joinpath('iso9660')
+    extract_volume_iso(args_copy)
 
 
 def extract_partition(args: argparse.Namespace, vol) -> int:
@@ -502,6 +550,7 @@ def extract_partition(args: argparse.Namespace, vol) -> int:
     dopunycode: bool = not args.nopunycode
     force_macbinary: bool = args.forcemacbinary
     add_macbinary_ext: bool = args.addmacbinaryext
+    silent: bool = args.silent
 
     if not dryrun:
         destination_dir.mkdir(parents=True, exist_ok=True)
@@ -529,14 +578,14 @@ def extract_partition(args: argparse.Namespace, vol) -> int:
 
             upath /= el
 
-        if might_be_jp and not might_be_jp_warned:
+        if might_be_jp and not might_be_jp_warned and not silent:
             logging.warning(
                 "Possible Mac-Japanese string detected, did you mean to use --japanese?"
             )
             might_be_jp_warned = True
 
         if dryrun:
-            if not isinstance(obj, machfs.Folder):
+            if not isinstance(obj, machfs.Folder) and not silent:
                 print(upath)
             continue
 
@@ -547,7 +596,7 @@ def extract_partition(args: argparse.Namespace, vol) -> int:
             folders.append((upath, obj.mddate - 2082844800))
             continue
 
-        print(upath)
+        # print(upath)
         if obj.data and not obj.rsrc and not force_macbinary:
             upath.write_bytes(obj.data)
 
@@ -906,6 +955,11 @@ def generate_parser() -> argparse.ArgumentParser:
         action="store_true",
         help="always encode using MacBinary, even for files with no resource fork",
     )
+    parser_iso.add_argument(
+        "--silent",
+        action="store_true",
+        help="do not print anything"
+    )
     parser_iso.add_argument(
         "--addmacbinaryext",
         action="store_true",
@@ -926,6 +980,10 @@ def generate_parser() -> argparse.ArgumentParser:
     parser_dir.add_argument("directory", metavar="directory ", type=Path, help="Path")
     parser_dir.set_defaults(func=punyencode_arg)
 
+    parser_probe = subparsers.add_parser("probe", help="Detect file system and extension of the given ISO")
+    parser_probe.add_argument("src", metavar="INPUT", type=Path, help="Disk image")
+    parser_probe.set_defaults(func=probe_iso)
+
     parser_str = subparsers.add_parser(
         "str", help="Convert strings or standard in to or from punycode"
     )


Commit: 15efeac0160983e562318c93b5f4ddeaf43eb5e8
    https://github.com/scummvm/scummvm/commit/15efeac0160983e562318c93b5f4ddeaf43eb5e8
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: COMPANION: Add enums for file systems and extensions

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index 54a82996ed5..cdc37375289 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -16,6 +16,7 @@
 # Code is formatted with `black`
 
 from __future__ import annotations
+from enum import Enum
 
 import argparse
 import copy
@@ -86,6 +87,19 @@ decode_map = {
 # fmt: on
 
 
+class FileSystem(Enum):
+    hybrid = 'hybrid'
+    hfs = 'hfs'
+    iso9660 = 'iso9660'
+
+
+class Extension(Enum):
+    none = None
+    joliet = 'joliet'
+    rr = 'rr'
+    udf = 'udf'
+
+
 def decode_macjapanese(text: bytes) -> str:
     """
     Decode MacJapanese
@@ -291,9 +305,9 @@ def encode_string(args: argparse.Namespace) -> int:
     return 0
 
 
-def probe_iso(args):
+def probe_iso(args: argparse.Namespace):
     fs = check_fs(args.src)
-    print('Detected file system:', fs)
+    print('Detected file system:', fs.value)
     args.fs = fs
     args.dryrun = True
     args.dir = Path('testing')
@@ -303,17 +317,17 @@ def probe_iso(args):
     args.log = 'INFO'
     args.nopunycode = False
     args.japanese = False
-    if fs == 'hybrid' or fs == 'iso9660':
+    if fs in [FileSystem.hybrid, FileSystem.iso9660]:
         args.extension = check_extension(args)
-        print('Detected extension:', args.extension)
+        print('Detected extension:', args.extension.value)
     print('Japanese detected:', check_japanese(args))
 
 
-def check_japanese(args):
+def check_japanese(args: argparse.Namespace):
     args.japanese = False
-    if args.fs == 'hybrid':
+    if args.fs == FileSystem.hybrid:
         fn = extract_volume_hybrid
-    elif args.fs == 'iso9660':
+    elif args.fs == FileSystem.iso9660:
         fn = extract_volume_iso
     else:
         fn = extract_volume_hfs
@@ -331,14 +345,13 @@ def check_japanese(args):
         return False
 
 
-def check_extension(args):
+def check_extension(args: argparse.Namespace):
     args_copy = copy.copy(args)
     args_copy.dryrun = True
-    extensions = ['joliet', 'rr', 'udf']
     args_copy.dir = args.dir.joinpath('test')
-    args_copy.fs = 'iso9660'
+    args_copy.fs = FileSystem.iso9660
     args_copy.silent = True
-    for extension in extensions:
+    for extension in Extension:
         args_copy.extension = extension
         try:
             extract_volume_iso(args_copy)
@@ -346,6 +359,7 @@ def check_extension(args):
             pass
         else:
             return extension
+    return Extension.none
 
 
 def check_fs(iso):
@@ -359,7 +373,7 @@ def check_fs(iso):
     f.seek(64 * SECTOR_SIZE)
     if f.read(6) == b"\x01CD001":
         # print('Found ISO PVD')
-        disk_formats.append("iso9660")
+        disk_formats.append(FileSystem.iso9660)
 
     f.seek(0)
     mac_1 = f.read(4)
@@ -374,7 +388,7 @@ def check_fs(iso):
             f.seek(32, 1)
             partition_type = f.read(32).decode("mac-roman").split("\x00")[0]
             if partition_type == "Apple_HFS":
-                disk_formats.append("hfs")
+                disk_formats.append(FileSystem.hfs)
                 break
             # Check if there are more partitions
             if partition_num <= num_partitions:
@@ -383,25 +397,28 @@ def check_fs(iso):
                 f.seek(partition_num * SECTOR_SIZE + 4)
     # Bootable Mac-only disc
     elif mac_1 == b"LK\x60\x00" and mac_3 == b"BD":
-        disk_formats.append("hfs")
+        disk_formats.append(FileSystem.hfs)
 
     if len(disk_formats) > 1:
-        return 'hybrid'
-    else:
-        return disk_formats[0]
+        return FileSystem.hybrid
+    return disk_formats[0]
 
 
 def extract_iso(args: argparse.Namespace):
     if not args.fs:
         args.fs = check_fs(args.src)
-        print('Detected filesystem:', args.fs)
-    if (args.fs == 'hybrid' or args.fs == 'iso9660') and not args.extension:
+        print('Detected filesystem:', args.fs.value)
+    else:
+        args.fs = FileSystem(args.fs)
+    if args.fs in [FileSystem.hybrid, FileSystem.iso9660] and not args.extension:
         args.extension = check_extension(args)
-        print('Detected extension:', args.extension)
+        print('Detected extension:', args.extension.value)
+    elif args.extension:
+        args.extension = Extension(args.extension)
 
-    if args.fs == 'iso9660':
+    if args.fs == FileSystem.iso9660:
         extract_volume_iso(args)
-    elif args.fs == 'hfs':
+    elif args.fs == FileSystem.hfs:
         extract_volume_hfs(args)
     else:
         extract_volume_hybrid(args)
@@ -482,11 +499,11 @@ def extract_volume_iso(args: argparse.Namespace):
 
     output_dir = str(args.dir)
 
-    if not args.extension:
+    if not args.extension or args.extension == Extension.none:
         path_type = 'iso_path'
-    elif args.extension == 'joliet':
+    elif args.extension == Extension.joliet:
         path_type = 'joliet_path'
-    elif args.extension == 'rr':
+    elif args.extension == Extension.rr:
         path_type = 'rr_path'
     else:
         path_type = 'udf_path'
@@ -596,7 +613,9 @@ def extract_partition(args: argparse.Namespace, vol) -> int:
             folders.append((upath, obj.mddate - 2082844800))
             continue
 
-        # print(upath)
+        if not silent:
+            print(upath)
+
         if obj.data and not obj.rsrc and not force_macbinary:
             upath.write_bytes(obj.data)
 


Commit: 2e9862863c1245eadeebc370a9602fea76319c28
    https://github.com/scummvm/scummvm/commit/2e9862863c1245eadeebc370a9602fea76319c28
Author: Darkhood148 (ujjwal.sharma9999999 at gmail.com)
Date: 2024-04-25T00:28:42+02:00

Commit Message:
DEVTOOLS: COMPANION: Add version checker pycdlib module

The pycdlib module does not implement the encoding parameter that is required for decoding Japanese filenames. A PR has been made to acknowledge this issue: https://github.com/clalancette/pycdlib/pull/124 . For the time, the PR is not merged, we need a temporary pycdlib version checker. Once the pycdlib PR has been merged, this commit can be removed

Changed paths:
    devtools/dumper-companion.py


diff --git a/devtools/dumper-companion.py b/devtools/dumper-companion.py
index cdc37375289..347b4493cf9 100755
--- a/devtools/dumper-companion.py
+++ b/devtools/dumper-companion.py
@@ -943,6 +943,26 @@ def create_macfonts(args: argparse.Namespace) -> int:
     return 0
 
 
+def search_encoding_parameter(s: str) -> bool:
+    l = -1
+    u = -1
+    for i, line in enumerate(s.split('\n')):
+        if line.strip() == 'Parameters:':
+            l = i + 1
+        if line.strip() == 'Yields:':
+            u = i
+            break
+    parameters = [i.split('-')[0].strip() for i in s.split('\n')[l:u]]
+    return 'encoding' in parameters
+
+
+def check_pycdlib_version() -> bool:
+    iso_test = pycdlib.PyCdlib()
+    doc_walk = iso_test.walk.__doc__
+    doc_get_file_from_iso_fp = iso_test.get_file_from_iso_fp.__doc__
+    return search_encoding_parameter(doc_walk) and search_encoding_parameter(doc_get_file_from_iso_fp)
+
+
 def generate_parser() -> argparse.ArgumentParser:
     """
     Generate the parser
@@ -1060,6 +1080,8 @@ def generate_parser() -> argparse.ArgumentParser:
 
 
 if __name__ == "__main__":
+    if not check_pycdlib_version():
+        print('WARNING: Old version of pycdlib detected. Parsing of Japanese filenames in ISO9660 may not work')
     parser = generate_parser()
     args = parser.parse_args()
     try:




More information about the Scummvm-git-logs mailing list