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)
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)
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}")
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)
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)
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()