Exemplo n.º 1
0
def main() -> None:
    parser = argparse.ArgumentParser(description="Tool for converting CookData in LoZ:BotW")
    parser.add_argument(
        "file", help="Filename to be converted (accepts wildcards for converting multiple files)",
    )
    parser.add_argument("output", help="Output type: bas or yml")
    parser.add_argument(
        "-n", "--names", help="Output with human-readable names", action="store_true"
    )
    parser.add_argument(
        "-d", "--digits", help="Output with machine-readable values", action="store_true"
    )

    args = parser.parse_args()

    if not args.names and not args.digits:
        raise RuntimeError("-n or -d must be specified!")
    if args.names and args.digits:
        raise RuntimeError("Only one of -n and -d must be specified!")

    output_str: str = str.lower(args.output)
    output_yaml: bool = True if output_str == "yml" or output_str == "yaml" else False
    output_aamp: bool = True if output_str == "bas" or output_str == "aamp" else False
    if not output_yaml and not output_aamp:
        raise RuntimeError("Output type must be one of: 'yml', 'yaml', 'bas', or 'aamp'")

    folder = Path(args.file).parent.resolve()
    filename = Path(args.file).name

    for file in folder.glob(filename):
        ext: str = file.suffix
        pio: ParameterIO = ParameterIO()
        if ext == ".bas":
            pio = ParameterIO.from_binary(file.read_bytes())
        elif ext == ".yml":
            pio = ParameterIO.from_text(file.read_text())

        try:
            if args.names:
                convert.to_names(pio)
            else:
                convert.to_numbers(pio)
        except:
            output_type: str = "names" if args.names else "numbers"
            print(f"{file.name} already had {output_type}! Skipping...")
            continue

        new_file: Path = Path()
        if output_yaml:
            new_file = file.with_suffix(".yml")
            to_write = ParameterIO.to_text(pio)
            new_file.write_text(to_write)
        else:
            new_file = file.with_suffix(".bas")
            to_write = ParameterIO.to_binary(pio)
            new_file.write_bytes(to_write)
Exemplo n.º 2
0
def nested_patch(pack: oead.Sarc, nest: dict) -> Tuple[oead.SarcWriter, dict]:
    new_sarc: oead.SarcWriter = oead.SarcWriter.from_sarc(pack)
    failures: dict = {}

    for file, stuff in nest.items():
        file_bytes = pack.get_file(file).data
        yazd = file_bytes[0:4] == b"Yaz0"
        file_bytes = util.decompress(file_bytes) if yazd else file_bytes

        if isinstance(stuff, dict):
            sub_sarc = oead.Sarc(file_bytes)
            new_sub_sarc, sub_failures = nested_patch(sub_sarc, stuff)
            for failure in sub_failures:
                failure[file + "//" + failure] = sub_failures[failure]
            del sub_sarc
            new_bytes = bytes(new_sub_sarc.write()[1])
            new_sarc.files[file] = new_bytes if not yazd else util.compress(
                new_bytes)

        elif isinstance(stuff, ParameterList):
            try:
                if file_bytes[0:4] == b"AAMP":
                    aamp_contents = ParameterIO.from_binary(file_bytes)
                    try:
                        file_ext = os.path.splitext(file)[1]
                        aamp_contents = shop_merge(
                            aamp_contents,
                            file_ext.replace(".", ""),
                            stuff.lists["Additions"],
                            stuff.lists["Removals"],
                        )
                        aamp_bytes = ParameterIO.to_binary(aamp_contents)
                    except:  # pylint: disable=bare-except
                        raise RuntimeError(
                            f"AAMP file {file} could be merged.")
                    del aamp_contents
                    new_bytes = aamp_bytes if not yazd else util.compress(
                        aamp_bytes)
                    cache_merged_shop(file, new_bytes)
                else:
                    raise ValueError(
                        "Wait, what the heck, this isn't an AAMP file?!")
            except ValueError:
                new_bytes = pack.get_file(file).data
                print(f"Deep merging {file} failed. No changes were made.")

            new_sarc.files[file] = oead.Bytes(new_bytes)
    return new_sarc, failures
Exemplo n.º 3
0
def threaded_merge(item) -> Tuple[str, dict]:
    """Deep merges an individual file, suitable for multiprocessing"""
    file, stuff = item
    failures = {}

    try:
        base_file = util.get_game_file(file,
                                       file.startswith(util.get_dlc_path()))
    except FileNotFoundError:
        return "", {}
    if (util.get_master_modpack_dir() / file).exists():
        base_file = util.get_master_modpack_dir() / file
    file_ext = os.path.splitext(file)[1]
    if file_ext in util.SARC_EXTS and (util.get_master_modpack_dir() /
                                       file).exists():
        base_file = util.get_master_modpack_dir() / file
    file_bytes = base_file.read_bytes()
    yazd = file_bytes[0:4] == b"Yaz0"
    file_bytes = file_bytes if not yazd else util.decompress(file_bytes)
    magic = file_bytes[0:4]

    if magic == b"SARC":
        new_sarc, sub_failures = nested_patch(oead.Sarc(file_bytes), stuff)
        del file_bytes
        new_bytes = bytes(new_sarc.write()[1])
        for failure, contents in sub_failures.items():
            print(f"Some patches to {failure} failed to apply.")
            failures[failure] = contents
    elif magic == b"AAMP":
        try:
            aamp_contents = ParameterIO.from_binary(file_bytes)
            try:
                aamp_contents = shop_merge(
                    aamp_contents,
                    file_ext.replace(".", ""),
                    stuff.lists["Additions"],
                    stuff.lists["Removals"],
                )
                aamp_bytes = ParameterIO.to_binary(aamp_contents)
            except:  # pylint: disable=bare-except
                raise RuntimeError(f"AAMP file {file} could be merged.")
            del aamp_contents
            new_bytes = aamp_bytes if not yazd else util.compress(aamp_bytes)
        except ValueError:
            new_bytes = file_bytes
            del file_bytes
            print(f"Deep merging file {file} failed. No changes were made.")
    else:
        raise ValueError(f"{file} is not a SARC or AAMP file.")

    new_bytes = new_bytes if not yazd else util.compress(new_bytes)
    output_file = util.get_master_modpack_dir() / file
    if base_file == output_file:
        output_file.unlink()
    output_file.parent.mkdir(parents=True, exist_ok=True)
    output_file.write_bytes(new_bytes)
    del new_bytes
    if magic == b"SARC":
        util.vprint(f"Finished patching files inside {file}")
    else:
        util.vprint(f"Finished patching {file}")
    return util.get_canon_name(file), failures