コード例 #1
0
ファイル: util.py プロジェクト: NiceneNerd/botw_actor_tool
def make_new_savedata(store: FlagStore, big_endian: bool,
                      orig_files: list) -> bytes:
    svwriter = oead.SarcWriter(
        endian=oead.Endianness.Big if big_endian else oead.Endianness.Little)
    svdata_array = store.flags_to_svdata_Array()
    num_files = ceil(len(svdata_array) / 8192)
    for idx in range(num_files):
        start = idx * 8192
        end = (idx + 1) * 8192
        if end > len(svdata_array):
            end = len(svdata_array)
        svwriter.files[f"/saveformat_{idx}.bgsvdata"] = oead.byml.to_binary(
            oead.byml.Hash({
                "file_list":
                oead.byml.Array([
                    {
                        "IsCommon": False,
                        "IsCommonAtSameAccount": False,
                        "IsSaveSecureCode": True,
                        "file_name": "game_data.sav",
                    },
                    oead.byml.Array(svdata_array[start:end]),
                ]),
                "save_info":
                oead.byml.Array([{
                    "directory_num": oead.S32(num_files + 2),
                    "is_build_machine": True,
                    "revision": oead.S32(18203),
                }]),
            }),
            big_endian,
        )
    svwriter.files[f"/saveformat_{num_files}.bgsvdata"] = orig_files[0]
    svwriter.files[f"/saveformat_{num_files+1}.bgsvdata"] = orig_files[1]
    return svwriter.write()[1]
コード例 #2
0
def generate_actor_info(pack: ActorPack, has_far: bool,
                        old_info: oead.byml.Hash) -> oead.byml.Hash:
    entry = old_info
    entry["name"] = pack.get_name()
    entry["isHasFar"] = has_far

    profile = pack.get_link("ProfileUser")
    if not pack.get_link("SlinkUser") == "Dummy":
        entry["bugMask"] = oead.S32(
            2)  # TODO: Find what sets the first bit of bugMask

    if entry["sortKey"].v > 0:
        entry["sortKey"] = oead.S32(entry["sortKey"].v + 1)

    actorlink = pack.get_actorlink()
    for key, value in get_actorlink_entries(actorlink).items():
        if key in KEYS_BY_PROFILE[profile]:
            entry[key] = value
    tags = get_actorlink_tags(actorlink)
    if tags:
        entry["tags"] = tags

    funcs = {
        "ChemicalUser": get_chemical_entries,
        "DropTableUser": get_droptable_entries,
        "GParamUser": get_gparamlist_entries,
        "LifeConditionUser": get_lifecondition_entries,
        "ModelUser": get_modellist_entries,
        "PhysicsUser": get_physics_entries,
        "RecipeUser": get_recipe_entries,
    }

    for link, func in funcs.items():
        yaml = pack.get_link_data(link)
        if not yaml == "":
            for key, value in func(
                    oead.aamp.ParameterIO.from_text(yaml)).items():
                entry[key] = value

    keys_to_pop: list = []
    for key in entry.keys():
        if not key in KEYS_BY_PROFILE[profile]:
            keys_to_pop.append(key)
    for key in keys_to_pop:
        del entry[key]
    del keys_to_pop

    return entry
コード例 #3
0
ファイル: data.py プロジェクト: arkhamsaiyan/BCML
def get_modded_savedata_entries(savedata: oead.Sarc) -> {}:
    ref_savedata = get_stock_savedata().get_files()
    ref_hashes = {
        int(item["HashValue"])
        for file in sorted(ref_savedata, key=lambda f: f.name)[0:-2]
        for item in oead.byml.from_binary(file.data)["file_list"][1]
    }
    new_entries = oead.byml.Array()
    mod_hashes = set()
    for file in sorted(
            savedata.get_files(),
            key=lambda f: f.name,
    )[0:-2]:
        entries = oead.byml.from_binary(file.data)["file_list"][1]
        mod_hashes |= {int(item["HashValue"]) for item in entries}
        new_entries.extend({
            item
            for item in entries if int(item["HashValue"]) not in ref_hashes
        })
    del ref_savedata
    return oead.byml.Hash({
        "add":
        new_entries,
        "del":
        oead.byml.Array(
            {oead.S32(item)
             for item in ref_hashes if item not in mod_hashes}),
    })
コード例 #4
0
def get_modded_savedata_entries(savedata: oead.Sarc) -> Hash:
    ref_savedata = get_stock_savedata().get_files()
    ref_hashes = {
        int(item["HashValue"])
        for file in sorted(ref_savedata, key=lambda f: f.name)[0:-2]
        for item in oead.byml.from_binary(file.data)["file_list"][1]
    }
    new_entries = oead.byml.Array()
    mod_hashes = set()
    for file in savedata.get_files():
        data = oead.byml.from_binary(file.data)
        if data["file_list"][0]["file_name"] != "game_data.sav":
            continue
        entries = data["file_list"][1]
        mod_hashes |= {int(item["HashValue"]) for item in entries}
        new_entries.extend(
            [item for item in entries if int(item["HashValue"]) not in ref_hashes]
        )
    del ref_savedata
    return Hash(
        {
            "add": new_entries,
            "del": oead.byml.Array(
                oead.S32(item)
                for item in {item for item in ref_hashes if item not in mod_hashes}
            ),
        }
    )
コード例 #5
0
 def __init__(self,
              def_name: str,
              type: str,
              name: str = "",
              group: str = ""):
     super().__init__()
     defs = util.get_ai_defs()
     key = ("AIs" if type == "ai" else
            "Actions" if type == "action" else "Behaviors"
            if type == "behavior" else "Querys" if type == "query" else "")
     if def_name in defs[key]:
         ai_def = defs[key][def_name]
         self.lists = {}
         self.objects = {crc32(b"Def"): ParameterObject()}
         self.objects["Def"].params["ClassName"] = Parameter(
             oead.FixedSafeString32(def_name))
         self.objects["Def"].params["Name"] = Parameter(name)
         self.objects["Def"].params["GroupName"] = Parameter(group)
         if "childs" in ai_def:
             self.objects["ChildIdx"] = ParameterObject()
             for child in ai_def["childs"]:
                 self.objects["ChildIdx"].params[child] = Parameter(
                     oead.S32(-1))
         if "StaticInstParams" in ai_def:
             self.objects["SInst"] = ParameterObject()
             for sinst in ai_def["StaticInstParams"]:
                 if "Value" in sinst:
                     val = sinst["Value"]
                 else:
                     val = _param_type_map[sinst["Type"]]()
                 self.objects["SInst"].params[sinst["Name"]] = Parameter(
                     val)
     else:
         raise ValueError(f"{def_name} is not a valid AI")
コード例 #6
0
ファイル: actors.py プロジェクト: arkhamsaiyan/BCML
    def perform_merge(self):
        actor_path = (util.get_master_modpack_dir() / util.get_content_path() /
                      "Actor" / "ActorInfo.product.sbyml")
        print("Loading modded actor info...")
        modded_actors = self.consolidate_diffs(self.get_all_diffs())
        if not modded_actors:
            print("No actor info merging necessary.")
            if actor_path.exists():
                actor_path.unlink()
            return

        print("Loading unmodded actor info...")
        actorinfo = get_stock_actorinfo()
        stock_actors = {
            crc32(actor["name"].encode("utf8")): actor
            for actor in actorinfo["Actors"]
        }

        print("Merging changes...")
        new_hashes = set()
        for actor_hash, actor_info in modded_actors.items():
            if isinstance(actor_hash, str):
                actor_hash = int(actor_hash)
            if actor_hash in stock_actors:
                util.dict_merge(stock_actors[actor_hash],
                                actor_info,
                                overwrite_lists=True)
            else:
                actorinfo["Actors"].append(actor_info)
                new_hashes.add(actor_hash)

        print("Sorting new actor info...")
        actorinfo["Hashes"] = oead.byml.Array([
            oead.S32(x) if x < 2147483648 else oead.U32(x)
            for x in sorted(new_hashes | set(stock_actors.keys()))
        ])
        try:
            actorinfo["Actors"] = sorted(
                actorinfo["Actors"],
                key=lambda x: crc32(x["name"].encode("utf-8")))
        except KeyError as err:
            if str(err) == "":
                raise RuntimeError(
                    "Your actor info mods could not be merged. "
                    "This usually indicates a corrupt game dump.") from err
            else:
                raise

        print("Saving new actor info...")
        actor_path.parent.mkdir(parents=True, exist_ok=True)
        actor_path.write_bytes(
            util.compress(
                oead.byml.to_binary(actorinfo,
                                    big_endian=util.get_settings("wiiu"))))
        print("Actor info merged successfully")
コード例 #7
0
def get_actorlink_tags(
        data: oead.aamp.ParameterIO) -> Union[oead.byml.Hash, None]:
    d: Union[oead.byml.Hash, None] = None
    if "Tags" in data.objects:
        d = oead.byml.Hash()
        for _, val in data.objects["Tags"].params.items():
            taghash = zlib.crc32(val.v.encode("utf-8"))
            tagval = oead.U32(taghash) if taghash > 2147483647 else oead.S32(
                taghash)
            taghex = f"tag{padhex(hex(taghash))[2:]}"
            d[taghex] = tagval
    return d
コード例 #8
0
def get_chemical_entries(data: oead.aamp.ParameterIO) -> dict:
    d: dict = {}
    if "chemical_root" in data.lists:
        cr = data.lists["chemical_root"]
        if "chemical_body" in cr.lists:
            cb = cr.lists["chemical_body"]
            if "rigid_c_00" in cb.objects:
                rc = cb.objects["rigid_c_00"]
                if "attribute" in rc.params:
                    if rc.params["attribute"].v == 650:
                        if not "Chemical" in d:
                            d["Chemical"] = oead.byml.Hash()
                        d["Chemical"]["Capaciter"] = oead.S32(1)
            if "shape_00" in cb.objects:
                s0 = cb.objects["shape_00"]
                if "name" in s0.params:
                    if s0.params["name"].v == "WeaponFire":
                        if not "Chemical" in d:
                            d["Chemical"] = oead.byml.Hash()
                        d["Chemical"]["Burnable"] = oead.S32(1)
    return d
コード例 #9
0
def _build_actorinfo(params: BuildParams):
    actors = []
    for actor_file in (params.out / params.content / "Actor" / "ActorInfo").glob(
        "*.info"
    ):
        actors.append(oead.byml.from_binary(actor_file.read_bytes()))
        actor_file.unlink()
    hashes = oead.byml.Array(
        [
            oead.S32(crc) if crc < 2147483648 else oead.U32(crc)
            for crc in sorted({crc32(a["name"].encode("utf8")) for a in actors})
        ]
    )
    actors.sort(key=lambda actor: crc32(actor["name"].encode("utf8")))
    actor_info = oead.byml.Hash({"Actors": oead.byml.Array(actors), "Hashes": hashes})
    info_path = params.out / params.content / "Actor" / "ActorInfo.product.sbyml"
    info_path.parent.mkdir(exist_ok=True, parents=True)
    info_path.write_bytes(
        compress(oead.byml.to_binary(actor_info, big_endian=params.be))
    )
コード例 #10
0
ファイル: builder.py プロジェクト: biD3V/Hyrule-Builder
def _build_actorinfo(params: BuildParams):
    actors = []
    for actor_file in (params.mod / params.content / 'Actor' /
                       'ActorInfo').glob('*.info.yml'):
        actors.append(
            oead.byml.from_text(actor_file.read_text(encoding='utf-8')))
    hashes = oead.byml.Array([
        oead.S32(crc) if crc < 2147483648 else oead.U32(crc)
        for crc in sorted({crc32(a['name'].encode('utf8'))
                           for a in actors})
    ])
    actors.sort(key=lambda actor: crc32(actor['name'].encode('utf8')))
    actor_info = oead.byml.Hash({
        'Actors': oead.byml.Array(actors),
        'Hashes': hashes
    })
    info_path = params.out / params.content / 'Actor' / 'ActorInfo.product.sbyml'
    info_path.parent.mkdir(exist_ok=True, parents=True)
    info_path.write_bytes(
        compress(oead.byml.to_binary(actor_info, big_endian=params.be)))
コード例 #11
0
def dictParamsToByml(dictIn):
    subDict = {}
    dictOut = {}
#    print(dictIn)
    for key in dictIn.keys():
        keyVal = dictIn.get(key)
        if isinstance(keyVal, int):
            dictOut.update({key: oead.S32(keyVal)})
        elif isinstance(keyVal, dict):
            subDict.update({key: keyVal})
            dictOut.update({key: dictParamsToByml(subDict)})
        elif isinstance(keyVal, str):
            dictOut.update({key: keyVal})
        elif isinstance(keyVal, float):
            dictOut.update({key: oead.F32(keyVal)})
        elif keyVal == None:
            dictOut.update({key: 'none'})
        else:
            print('error?')
            dictOut.update({key: keyVal})
#    print(dictOut)
    return(((dict(dictOut))))
コード例 #12
0
ファイル: actorinfo.py プロジェクト: krenyy/botw_tools
def convert_hash(x: int) -> Union[oead.S32, oead.U32]:
    return oead.U32(x) if x > 0x80000000 else oead.S32(x)
コード例 #13
0
def armor_iter(armor, actorinfo, actors):
    armor.base = get_def_item(armor.base, actors)
    old_hash = create_hash(armor.base)
    new_hash = create_hash(armor.name)

    loc = 0
    for x in actorinfo['Hashes']:
        if int(new_hash) < int(x):
            break
        loc += 1

    old_loc = get_arr_index(actorinfo["Hashes"], old_hash)
    actorinfo["Hashes"].insert(loc, new_hash)
    # new_loc = get_arr_index(actorinfo["Hashes"], new_hash)
    new_entry = dict(actorinfo["Actors"][old_loc])
    new_entry["name"] = armor.name
    new_entry = dict(actorinfo["Actors"][old_loc])
    new_entry["name"] = armor.name

    if armor.elink: new_entry["elink"] = armor.elink

    if armor.slink: new_entry["slink"] = armor.slink
    if armor.armorStarNum:
        new_entry["armorStarNum"] = oead.S32(armor.armorStarNum)
    if armor.armorNextRankName:
        new_entry["armorNextRankName"] = armor.armorNextRankName
    if armor.itemUseIconActorName:
        new_entry["itemUseIconActorName"] = armor.itemUseIconActorName

    if armor.defence:
        new_entry["armorDefenceAddLevel"] = oead.S32(int(armor.defence))
    if armor.effect_lv:
        new_entry["armorEffectEffectLevel"] = oead.S32(int(armor.effect_lv))
    if armor.effect: new_entry["armorEffectEffectType"] = armor.effect
    elif armor.effect == 'None':
        new_entry["armorEffectEffectLevel"] = oead.S32(0)
    if armor.profile: new_entry["profile"] = armor.profile
    if armor.series: new_entry["seriesArmorSeriesType"] = armor.series

    if armor.bfres: new_entry["bfres"] = armor.bfres
    else: new_entry["bfres"] = armor.bfres_folder

    if armor.mainmodel: new_entry["mainModel"] = armor.mainmodel
    else: new_entry["mainModel"] = armor.name

    #if "bfres" in new_entry: new_entry["bfres"] = armor.bfres_folder
    #if "mainModel" in new_entry: new_entry["mainModel"] = armor.name
    new_entry["sortKey"] = S32(int(new_entry["sortKey"]) + 1)
    #new_entry["armorNextRankName"] = ''

    if armor.item1 and armor.item1_n:
        new_entry["normal0ItemName01"] = armor.item1
        new_entry["normal0ItemNum01"] = oead.S32(int(armor.item1_n))
    else:
        new_entry["normal0ItemName01"] = 'Item_Enemy_26'
        new_entry["normal0ItemNum01"] = oead.S32(1)

    if armor.item1 and armor.item1_n and armor.item2 and armor.item2_n:
        new_entry["normal0ItemName02"] = armor.item2
        new_entry["normal0ItemNum02"] = oead.S32(int(armor.item2_n))
    else:
        new_entry["normal0ItemName02"] = 'Item_Enemy_00'
        new_entry["normal0ItemNum02"] = oead.S32(1)

    if armor.item1 and armor.item1_n and armor.item2 and armor.item2_n and armor.item3 and armor.item3_n:
        new_entry["normal0ItemName03"] = armor.item3
        new_entry["normal0ItemNum03"] = oead.S32(int(armor.item3_n))
    else:
        new_entry["normal0ItemName03"] = 'Item_Enemy_28'
        new_entry["normal0ItemNum03"] = oead.S32(1)
    new_entry["normal0StuffNum"] = oead.S32(1)
    if armor.price:
        new_entry["itemBuyingPrice"] = oead.S32(int(armor.price))
        new_entry["itemCreatingPrice"] = oead.S32(int(armor.price))

    actorinfo["Actors"].insert(loc, new_entry)
    del new_entry

    return actorinfo
コード例 #14
0
def weapon_iter(weapon, actorinfo, actors):
    weapon.base = get_def_item(weapon.base, actors)
    old_hash = create_hash(weapon.base)

    new_hash = create_hash(weapon.name)

    loc = 0
    for x in actorinfo['Hashes']:
        if int(new_hash) < int(x):
            break
        loc += 1

    old_loc = get_arr_index(actorinfo["Hashes"], old_hash)
    actorinfo["Hashes"].insert(loc, new_hash)
    #new_loc = get_arr_index(actorinfo["Hashes"], new_hash)
    new_entry = dict(actorinfo["Actors"][old_loc])
    new_entry["name"] = weapon.name

    if weapon.profile == 'WeaponShield':
        if weapon.attack:
            new_entry["weaponCommonGuardPower"] = oead.S32(int(weapon.attack))
    else:
        if weapon.attack:
            new_entry["attackPower"] = oead.S32(int(weapon.attack))

    if weapon.elink: new_entry["elink"] = weapon.elink
    if weapon.slink: new_entry["slink"] = weapon.slink
    if weapon.dur: new_entry["generalLife"] = oead.S32(int(weapon.dur))
    new_entry["bfres"] = weapon.name
    new_entry["mainModel"] = weapon.name
    new_entry["sortKey"] = S32(int(new_entry["sortKey"]) + 1)

    if weapon.item1 and weapon.item1_n:
        new_entry["normal0ItemName01"] = weapon.item1
        new_entry["normal0ItemNum01"] = oead.S32(int(weapon.item1_n))
    else:
        new_entry["normal0ItemName01"] = 'Item_Enemy_26'
        new_entry["normal0ItemNum01"] = oead.S32(1)

    if weapon.item1 and weapon.item1_n and weapon.item2 and weapon.item2_n:
        new_entry["normal0ItemName02"] = weapon.item2
        new_entry["normal0ItemNum02"] = oead.S32(int(weapon.item2_n))
    else:
        new_entry["normal0ItemName02"] = 'Item_Enemy_00'
        new_entry["normal0ItemNum02"] = oead.S32(1)

    if weapon.item1 and weapon.item1_n and weapon.item2 and weapon.item2_n and weapon.item3 and weapon.item3_n:
        new_entry["normal0ItemName03"] = weapon.item3
        new_entry["normal0ItemNum03"] = oead.S32(int(weapon.item3_n))
    else:
        new_entry["normal0ItemName03"] = 'Item_Enemy_28'
        new_entry["normal0ItemNum03"] = oead.S32(1)

    new_entry["normal0StuffNum"] = oead.S32(1)
    if weapon.price:
        new_entry["itemBuyingPrice"] = oead.S32(int(weapon.price))
        new_entry["itemCreatingPrice"] = oead.S32(int(weapon.price))

    actorinfo["Actors"].insert(loc, new_entry)
    del new_entry
    return actorinfo
コード例 #15
0
ファイル: actor.py プロジェクト: NiceneNerd/botw_actor_tool
    def save(self, root_dir: str, be: bool) -> None:
        if self._resident:
            titlebg_path = Path(f"{root_dir}/Pack/TitleBG.pack")
            actor_dir = f"Actor/Pack/{self._pack.get_name()}.sbactorpack"
            if not titlebg_path.exists():
                titlebg_path.parent.mkdir(parents=True, exist_ok=True)
                shutil.copy(util.find_file(Path("Pack/TitleBG.pack")),
                            titlebg_path)
            yaz0_bytes = oead.yaz0.compress(self._pack.get_bytes(be))
            util.inject_bytes_into_sarc(titlebg_path, actor_dir, yaz0_bytes)
        else:
            actor_path = Path(
                f"{root_dir}/Actor/Pack/{self._pack.get_name()}.sbactorpack")
            yaz0_bytes = oead.yaz0.compress(self._pack.get_bytes(be))
            if not actor_path.exists():
                actor_path.parent.mkdir(parents=True, exist_ok=True)
                actor_path.touch()
            actor_path.write_bytes(yaz0_bytes)

        hash = crc32(self._pack.get_name().encode("utf-8"))
        info = self.get_info()

        if self._has_far:
            actor_path = Path(
                f"{root_dir}/Actor/Pack/{self._far_pack.get_name()}.sbactorpack"
            )
            yaz0_bytes = oead.yaz0.compress(self._far_pack.get_bytes(be))
            if not actor_path.exists():
                actor_path.touch()
            actor_path.write_bytes(yaz0_bytes)

            far_hash = crc32(self._far_pack.get_name().encode("utf-8"))
            far_info = self.get_far_info()

        actorinfo_path = Path(f"{root_dir}/Actor/ActorInfo.product.sbyml")
        actorinfo_load_path = actorinfo_path
        if not actorinfo_load_path.exists():
            actorinfo_load_path.touch()
            actorinfo_load_path = Path(
                util.find_file(Path("Actor/ActorInfo.product.sbyml")))
        actorinfo = oead.byml.from_binary(
            oead.yaz0.decompress(actorinfo_load_path.read_bytes()))

        hashes = [int(h) for h in actorinfo["Hashes"]]
        try:
            hash_index = hashes.index(hash)
        except ValueError:
            hashes.append(hash)
            hashes.sort()
            hash_index = hashes.index(hash)
            actorinfo["Actors"].insert(hash_index, oead.byml.Hash())
        if self._has_far:
            try:
                far_hash_index = hashes.index(far_hash)
            except ValueError:
                hashes.append(far_hash)
                hashes.sort()
                far_hash_index = hashes.index(far_hash)
                actorinfo["Actors"].insert(far_hash_index, oead.byml.Hash())
        actorinfo["Hashes"] = oead.byml.Array(
            [oead.U32(h) if h > 2147483647 else oead.S32(h) for h in hashes])

        actorinfo["Actors"][hash_index] = info
        if self._has_far:
            actorinfo["Actors"][far_hash_index] = far_info

        actorinfo_path.write_bytes(
            oead.yaz0.compress(oead.byml.to_binary(actorinfo, be)))

        self._texts.write(root_dir, be)

        bootup_path = Path(f"{root_dir}/Pack/Bootup.pack")
        if not bootup_path.exists():
            bootup_path.parent.mkdir(parents=True, exist_ok=True)
            shutil.copy(util.find_file(Path("Pack/Bootup.pack")), bootup_path)

        gamedata_sarc = util.get_gamedata_sarc(bootup_path)
        for bgdata_name, bgdata_hash in map(util.unpack_oead_file,
                                            gamedata_sarc.get_files()):
            self._flags.add_flags_from_Hash(bgdata_name, bgdata_hash, False)

        files_to_write: list = []
        files_to_write.append("GameData/gamedata.ssarc")
        files_to_write.append("GameData/savedataformat.ssarc")
        orig_files = util.get_last_two_savedata_files(bootup_path)
        datas_to_write: list = []
        datas_to_write.append(
            oead.yaz0.compress(util.make_new_gamedata(self._flags, be)))
        datas_to_write.append(
            oead.yaz0.compress(
                util.make_new_savedata(self._flags, be, orig_files)))
        util.inject_files_into_bootup(bootup_path, files_to_write,
                                      datas_to_write)
コード例 #16
0
ファイル: data.py プロジェクト: arkhamsaiyan/BCML
    def perform_merge(self):
        force = self._options.get("force", False)
        slog_path = util.get_master_modpack_dir() / "logs" / "savedata.log"

        new_entries = self.consolidate_diffs(self.get_all_diffs())
        if not new_entries:
            print("No savedata merging necessary.")
            if slog_path.exists():
                slog_path.unlink()
            if (util.get_master_modpack_dir() / "logs" /
                    "savedata.sarc").exists():
                (util.get_master_modpack_dir() / "logs" /
                 "savedata.sarc").unlink()
            return
        if slog_path.exists() and not force:
            with slog_path.open("r") as l_file:
                if xxhash.xxh64_hexdigest(str(new_entries)) == l_file.read():
                    print("No savedata merging necessary.")
                    return

        savedata = get_stock_savedata()
        save_files = sorted(savedata.get_files(), key=lambda f: f.name)[0:-2]

        print("Merging changes...")
        merged_entries = oead.byml.Array(
            sorted(
                {
                    entry["HashValue"].v: entry
                    for entry in [
                        *[
                            e for file in save_files for e in
                            oead.byml.from_binary(file.data)["file_list"][1]
                        ],
                        *new_entries["add"],
                    ] if entry not in new_entries["del"]
                }.values(),
                key=itemgetter("HashValue"),
            ))
        print("Creating and injecting new savedataformat.sarc...")
        new_savedata = oead.SarcWriter(
            endian=oead.Endianness.Big if util.get_settings("wiiu") else oead.
            Endianness.Little)
        num_files = ceil(len(merged_entries) / 8192)
        for i in range(num_files):
            end_pos = (i + 1) * 8192
            if end_pos > len(merged_entries):
                end_pos = len(merged_entries)
            data = oead.byml.to_binary(
                oead.byml.Hash({
                    "file_list":
                    oead.byml.Array([
                        {
                            "IsCommon": False,
                            "IsCommonAtSameAccount": False,
                            "IsSaveSecureCode": True,
                            "file_name": "game_data.sav",
                        },
                        oead.byml.Array(merged_entries[i * 8192:end_pos]),
                    ]),
                    "save_info":
                    oead.byml.Array([{
                        "directory_num": oead.S32(8),
                        "is_build_machine": True,
                        "revision": oead.S32(18203),
                    }]),
                }),
                big_endian=util.get_settings("wiiu"),
            )
            new_savedata.files[f"/saveformat_{i}.bgsvdata"] = data

        new_savedata.files[f"/saveformat_{num_files}.bgsvdata"] = oead.Bytes(
            savedata.get_file("/saveformat_6.bgsvdata").data)
        new_savedata.files[
            f"/saveformat_{num_files + 1}.bgsvdata"] = oead.Bytes(
                savedata.get_file("/saveformat_7.bgsvdata").data)

        del savedata
        new_save_bytes = new_savedata.write()[1]
        del new_savedata
        util.inject_file_into_sarc(
            "GameData/savedataformat.ssarc",
            util.compress(new_save_bytes),
            "Pack/Bootup.pack",
            create_sarc=True,
        )
        (util.get_master_modpack_dir() / "logs").mkdir(parents=True,
                                                       exist_ok=True)
        ((util.get_master_modpack_dir() / "logs" /
          "savedata.sarc").write_bytes(new_save_bytes))

        print("Updating RSTB...")
        rstable.set_size(
            "GameData/savedataformat.sarc",
            rstable.calculate_size("GameData/savedataformat.sarc",
                                   new_save_bytes),
        )
        del new_save_bytes

        slog_path.parent.mkdir(parents=True, exist_ok=True)
        with slog_path.open("w", encoding="utf-8") as l_file:
            l_file.write(xxhash.xxh64_hexdigest(str(new_entries)))
コード例 #17
0
def main():
#   Cli Arguments Setup
    progDesc = "A program for bulk replacing and deleting parameters and actors in BotW BYML map files."

    parser = argparse.ArgumentParser(description=progDesc)
    subParser = parser.add_subparsers(description='Sub-Commands required to use the functions of BMPM', dest='subParserType')
    parser.add_argument('fileIn', type=str, help="File to open and read data from.", default=None)
#    parser.add_argument('--version', '-v', dest='version', help='Displays the current version of BMPM being run.', required=False)
    parser.add_argument('--noCompression', '-nc', action='store_true', help='Add this if you would prefer the program to not compress the output file with yaz0.')
    parser.add_argument('--bigEndian', '-be', action='store_true', dest='endian', help='Outputs the files in a big endian format', required=False, default=False)

    editParser = subParser.add_parser('edit', help='edit')
    editParser.add_argument('termToSearch', type=str, help='Term to look through the file and find.')
    editParser.add_argument('--value', '-v', type=str, metavar='value', dest='value', help='Value to match with params found in file.', required=False, default=None)
    editParser.add_argument('replacementTerm', help='Value to replace the original termToSearch value with.')
    editParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1'], help='A value of 0 meaning an integer or 1 meaning a string to set the replacement term as. (defaults to zero)', required=False, default=0)

    remParser = subParser.add_parser('delete', help='Remove an actor or actors from the map file(s) based on either name or hashID')
    remParser.add_argument('ActorToDelete', help='The actor name or HashID you would like removed from the map file.')
    remParser.add_argument('--fragment', '-f', dest='subStr', action='store_true', help='Whether or not the inputted search term is a prefix to search for or not.', required=False)
    remParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1', 'hash', 'name'], help='Type of string that was inputted for actor removal(0 maps to hash and 1 to actor name, will default to actor name.)', required=False, default=1)

    convParser = subParser.add_parser('convert', help='Converts one actor to another based off of a template.')
    convParser.add_argument('--type', '-t', metavar='value', dest='type', choices=['0', '1', 'hash', 'name'], help='Type of string that was inputted for actor removal(0 maps to hash and 1 to actor name, will default to actor name.)', required=False, default=1)
    convParser.add_argument('--fragment', '-f', dest='subStr', action='store_true', help='Whether or not the inputted search term is a prefix to search for or not.', required=False)
    convParser.add_argument('actorConvertFrom', help='The actor name or hashID you would like to be converted.')
    convParser.add_argument('actorConvertTo', type=str, help='Actor to convert to.')

    endSwap = subParser.add_parser('swap', help='A function to detect and quickly convert the endianness of map files.')

    genParser = subParser.add_parser('genDB', help='Generate the database of actors necessary for using the replace actor function. Only needs to be run once.')


#   Global Variables
    args = parser.parse_args()
    if (args.fileIn != None):
        fileToOpen = pathlib.Path(args.fileIn)
        fileToOpen = fileToOpen
        if fileToOpen.is_file():
            fileObj = fileToOpen
            fileName = str(fileObj).split('.')[0]
            fileExt = ('.' + str(fileObj).split('.')[-1])
        else:
            print('Directory entered, beginning recursive processes.')


    if (args.subParserType == 'edit'):
        termToSearch = args.termToSearch
        replaceTerm = args.replacementTerm
        replacementParamType = None
        if (int(args.type) == 0):
            replacementParamType = oead.S32(value=int(replaceTerm))
        elif (int(args.type) == 1):
            replacementParamType = str(replaceTerm)



        if fileToOpen.is_dir():
            fileList = util.checkDir(fileToOpen)
            for fileToOpen in fileList:
                fileName = str(fileToOpen).split('.')[0]
                fileExt = ('.' + str(fileToOpen).split('.')[-1])

                if (args.value != None):
                    valToSearch = args.value
                    functions.replaceSpfxParam(fileToOpen, fileName, fileExt, termToSearch, valToSearch, replacementParamType, args)
                else:
                    functions.replaceParam(fileToOpen, fileName, fileExt, termToSearch, replacementParamType, args)
        else:
            if (args.value != None):
                valToSearch = args.value
                functions.replaceSpfxParam(fileToOpen, fileName, fileExt, termToSearch, valToSearch, replacementParamType, args)
            else:
                functions.replaceParam(fileToOpen, fileName, fileExt, termToSearch, replacementParamType, args)

    elif (args.subParserType == 'delete'):
        actorToDel = args.ActorToDelete
        nameHash = args.type
        if fileToOpen.is_dir():
            fileList = util.checkDir(fileToOpen)
            for fileToOpen in fileList:
                fileName = str(fileToOpen).split('.')[0]
                fileExt = ('.' + str(fileToOpen).split('.')[-1])
                functions.removeActor(fileToOpen, fileName, fileExt, actorToDel, nameHash, args)
        else:
            functions.removeActor(fileToOpen, fileName, fileExt, actorToDel, nameHash, args)

    elif (args.subParserType == 'convert'):
        actorToConv = args.actorConvertFrom
        actorConvTo = args.actorConvertTo
        nameHash = args.type 
        if fileToOpen.is_dir():
            fileList = util.checkDir(fileToOpen)
            for fileToOpen in fileList:
                fileName = str(fileToOpen).split('.')[0]
                fileExt = ('.' + str(fileToOpen).split('.')[-1])
                functions.replaceActor(fileToOpen, fileName, fileExt, nameHash, actorToConv, actorConvTo, args)
        else:
            functions.replaceActor(fileToOpen, fileName, fileExt, nameHash, actorToConv, actorConvTo, args)

    elif(args.subParserType == 'genDB'):
        if (input('This may take a while, are you sure you would like to continue? (y/n)').lower().startswith('y')):
            functions.genActorDatabase(fileToOpen)
        else:
            print('Cancelling operation.')
    
#    elif(args.subParserType == 'version'):
#        print(f"BMPM-{str(version)}")
    elif(args.subParserType == 'swap'):
            if fileToOpen.is_dir():
                fileList = util.checkDir(fileToOpen)
                for fileToOpen in fileList:
                    fileName = str(fileToOpen).split('.')[0]
                    fileExt = ('.' + str(fileToOpen).split('.')[-1])
                    functions.swapEnd(fileToOpen, fileName, fileExt, args)
            else:
                functions.swapEnd(fileToOpen, fileName, fileExt, args)
    else:
        print(f'The option {str(args.subParserType)} could not be found.')
コード例 #18
0
def create_hash(x):
    result = zlib.crc32(bytes(x.encode()))
    if result < 2147483647:
        return oead.S32(result)
    else:
        return oead.U32(result)