Esempio n. 1
0
def command_wad_extract(parser, args):
    if not os.path.isfile(args.wad):
        parser.error("WAD file does not exist")
    if not args.output:
        args.output = os.path.splitext(args.wad)[0]
    if os.path.exists(args.output) and not os.path.isdir(args.output):
        parser.error("output is not a directory")

    if args.hashes is None:
        hashfile = default_hashfile(args.wad)
    else:
        hashfile = HashFile(args.hashes)
    wad = Wad(args.wad, hashes=hashfile.load())
    if args.unknown == 'yes':
        pass  # don't filter
    elif args.unknown == 'only':
        wad.files = [wf for wf in wad.files if wf.path is None]
    elif args.unknown == 'no':
        wad.files = [wf for wf in wad.files if wf.path is not None]

    if args.pattern:
        wad.files = [
            wf for wf in wad.files
            if any(wf.path is not None and fnmatch.fnmatchcase(wf.path, p)
                   for p in args.pattern)
        ]

    wad.guess_extensions()
    wad.extract(args.output, overwrite=not args.lazy)
Esempio n. 2
0
def command_hashes_guess(parser, args):
    hashes = load_hashes(args.hashes)

    wad_paths = []
    for path_or_component in args.wad:
        try:
            component = parse_component(args.storage, path_or_component)
        except ValueError:
            wad_paths.append(path_or_component)
            continue
        # component, get wad paths
        if isinstance(component, ProjectVersion):
            it = component.filepaths()
        elif isinstance(component, SolutionVersion):
            it = component.filepaths(langs=True)
        elif isinstance(component, PatchVersion):
            # there must be one solution
            for sv in component.solutions(latest=True):
                if sv.name == 'league_client_sln':
                    it = sv.filepaths(langs=True)
            else:
                it = []
        else:
            parser.error(f"command cannot be used on {component}")
        wad_paths.extend(
            args.storage.fspath(p) for p in it if p.endswith('.wad'))

    wads = [Wad(path) for path in wad_paths]
    unknown_hashes = set()
    for wad in wads:
        unknown_hashes |= set(wadfile.path_hash for wadfile in wad.files)
    unknown_hashes -= set(hashes)

    new_hashes = {}
    if args.search:
        for wad in wads:
            new_hashes.update(wad.guess_hashes(unknown_hashes))
    new_hashes.update(Wad.guess_hashes_from_known(hashes, unknown_hashes))

    for h, path in new_hashes.items():
        print(f"{h:016x} {path}")

    if not args.dry_run and new_hashes:
        hashes.update(new_hashes)
        save_hashes(args.hashes, hashes)
Esempio n. 3
0
def command_wad_list(parser, args):
    if not os.path.isfile(args.wad):
        parser.error("WAD file does not exist")

    hashes = load_hashes(args.hashes)
    wad = Wad(args.wad, hashes=hashes)

    wadfiles = [(wf.path or ('?.%s' % wf.ext if wf.ext else '?'), wf.path_hash)
                for wf in wad.files]
    for path, h in sorted(wadfiles):
        print(f"{h:016x} {path}")
Esempio n. 4
0
def command_wad_extract(parser, args):
    if not os.path.isfile(args.wad):
        parser.error("WAD file does not exist")
    if not args.output:
        args.output = os.path.splitext(args.wad)[0]
    if os.path.exists(args.output) and not os.path.isdir(args.output):
        parser.error("output is not a directory")

    hashes = load_hashes(args.hashes)
    wad = Wad(args.wad, hashes=hashes)
    if args.unknown == 'yes':
        pass  # don't filter
    elif args.unknown == 'only':
        wad.files = [wf for wf in wad.files if wf.path is None]
    elif args.unknown == 'no':
        wad.files = [wf for wf in wad.files if wf.path is not None]

    wad.guess_extensions()
    wad.extract(args.output)
Esempio n. 5
0
def wad_extract(filename, output=None):
    """
    WAD文件解包
    :param filename: 输入文件名
    :param output: 输出目录名
    :return:
    """
    if not output:
        output = os.path.splitext(filename)[0]
    if not os.path.exists(output):
        os.mkdir(output)
    hashfile = default_hashfile(filename)
    wad = Wad(filename, hashes=hashfile.load())
    wad.guess_extensions()
    wad.extract(output, overwrite=True)
Esempio n. 6
0
def command_hashes_guess(parser, args):
    all_methods = [
        ("grep", "search for hashes in WAD files"),
        ("numbers", "substitute numbers in basenames"),
        ("basenames", "substitute basenames"),
        ("words", "substitute known words in basenames"),
        ("ext", "substitute extensions"),
        ("regionlang", "substitute region and lang (LCU only)"),
        ("plugin", "substitute plugin name (LCU only)"),
        ("skin-num", "substitute skinNN numbers (game only)"),
        ("character", "substitute character name (game only)"),
        ("prefixes", "check basename prefixes (game only)"),
    ]
    all_method_names = [name for name, _ in all_methods]

    if args.list_methods:
        name_width = max(len(name) for name in all_method_names)
        for name, desc in all_methods:
            print(f"  {name:{name_width}}  {desc}")
        return
    elif not args.wad:
        parser.error(
            "neither \"wad\" nor \"--list-methods\" argument was found")

    if not args.methods:
        method_names = [
            name for name in all_method_names
            if name not in ("basenames", "words")
        ]
    else:
        method_names = [s.strip() for s in args.methods.split(',')]
        for name in method_names:
            if name not in all_method_names:
                parser.error(f"unknown guessing method: {name}")

    # collect WAD paths
    wads = []
    for path_or_component in args.wad:
        try:
            component = parse_storage_component(args.storage,
                                                path_or_component)
        except ValueError:
            wads.append(Wad(path_or_component))
            continue
        if component is None:
            continue
        if isinstance(component, Patch):
            elements = component.elements
        else:
            elements = [component.elements]
        for elem in elements:
            wads.extend(
                Wad(p) for p in elem.fspaths()
                if p.endswith('.wad') or p.endswith('.wad.client'))

    # guess LCU hashes
    guesser = LcuHashGuesser.from_wads(wads)
    if guesser.unknown:
        nunknown = len(guesser.unknown)
        if "grep" in method_names:
            for wad in guesser.wads:
                wad.guess_extensions()
                guesser.grep_wad(wad)
        if "numbers" in method_names:
            guesser.substitute_numbers()
        if "basenames" in method_names:
            guesser.substitute_basenames()
        if "words" in method_names:
            guesser.substitute_basename_words()
        if "ext" in method_names:
            guesser.substitute_extensions()
        if "regionlang" in method_names:
            guesser.substitute_region_lang()
        if "plugin" in method_names:
            guesser.substitute_plugin()

        nfound = nunknown - len(guesser.unknown)
        if nfound:
            print(f"found LCU hashes: {nfound}")
            if not args.dry_run:
                guesser.save()

    # guess game hashes
    guesser = GameHashGuesser.from_wads(wads)
    if guesser.unknown:
        nunknown = len(guesser.unknown)
        if "grep" in method_names:
            for wad in guesser.wads:
                wad.guess_extensions()
                guesser.grep_wad(wad)
        if "numbers" in method_names:
            guesser.substitute_numbers()
        if "basenames" in method_names:
            guesser.substitute_basenames()
        if "words" in method_names:
            guesser.substitute_basename_words()
        if "ext" in method_names:
            guesser.substitute_extensions()
        if "skin-num" in method_names:
            guesser.substitute_skin_numbers()
        if "character" in method_names:
            guesser.substitute_character()
        if "prefixes" in method_names:
            guesser.check_basename_prefixes()

        nfound = nunknown - len(guesser.unknown)
        if nfound:
            print(f"found game hashes: {nfound}")
            if not args.dry_run:
                guesser.save()