mirror of https://github.com/zeldaret/botw.git
ksys/gdt: Add common flags
This commit is contained in:
parent
f2a8d32f29
commit
d87fefe1fb
|
@ -52351,7 +52351,8 @@
|
|||
0x00000071008bf838,nullsub_2643,4,
|
||||
0x00000071008bf83c,sub_71008BF83C,8,
|
||||
0x00000071008bf844,sub_71008BF844,92,
|
||||
0x00000071008bf8a0,initGlobalGameDataFlagIndexes,148764,
|
||||
0x00000071008bf8a0,_ZN4ksys3gdt11CommonFlags4initEv,4,_ZN4ksys3gdt15initCommonFlagsEv
|
||||
0x00000071008bf8a4,initGlobalGameDataFlagIndexes,148760,_ZN4ksys3gdt16initCommonFlags_Ev
|
||||
0x00000071008e3dbc,sub_71008E3DBC,12,
|
||||
0x00000071008e3dc8,getStrBowPorchStockNum,12,
|
||||
0x00000071008e3dd4,getStrCaptionPictSize,12,
|
||||
|
|
Can't render this file because it is too large.
|
|
@ -1,7 +1,10 @@
|
|||
target_sources(uking PRIVATE
|
||||
gdtCommonFlags.cpp
|
||||
gdtCommonFlags.h
|
||||
gdtFlag.cpp
|
||||
gdtFlag.h
|
||||
gdtFlagProxy.h
|
||||
gdtFlagUtils.h
|
||||
gdtManager.cpp
|
||||
gdtManager.h
|
||||
gdtSaveMgr.cpp
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,5 @@
|
|||
#pragma once
|
||||
|
||||
#include "KingSystem/GameData/gdtManager.h"
|
||||
|
||||
namespace ksys::gdt {} // namespace ksys::gdt
|
|
@ -22,6 +22,8 @@ namespace ksys::gdt {
|
|||
|
||||
enum class FlagHandle : u32 {};
|
||||
|
||||
constexpr FlagHandle InvalidHandle = FlagHandle(-1);
|
||||
|
||||
class TriggerParamRef {
|
||||
public:
|
||||
TriggerParamRef(TriggerParam** param_1, TriggerParam** param, bool check_permissions,
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env python3
|
||||
import argparse
|
||||
from pathlib import Path
|
||||
import typing as tp
|
||||
|
||||
import oead
|
||||
|
||||
|
||||
def add_development_remnant_flags(flags: tp.Dict[str, str]):
|
||||
_flags = {
|
||||
"AoC_DragonFireChallengeRing_Advent": "bool_data",
|
||||
"AoC_RandomSpawnTreasure_Contents": "string64_data",
|
||||
"AoC_RandomSpawnTreasure_IsRandomized": "bool_data",
|
||||
"AoC_TestProg_Imoto_Flag_00": "bool_data",
|
||||
"AoC_TestProg_Imoto_TagCount_00": "s32_data",
|
||||
"AocTestEx_Omosako_IsPastWorld": "bool_data",
|
||||
"AocTestEx_Omosako_ReturnToMainField_Position": "vector3f_data",
|
||||
"AocTestEx_Omosako_ReturnToMainField_Rotation": "f32_data",
|
||||
"AocTestEx_Omosako_SandOfTime_Num": "s32_data",
|
||||
"AocTestEx_Omosako_SandOfTime_Rate": "f32_data",
|
||||
"Location_DarkDungeon01": "s32_data",
|
||||
"Location_DarkDungeon02": "s32_data",
|
||||
"Location_DarkDungeon03": "s32_data",
|
||||
"Location_DarkDungeon04": "s32_data",
|
||||
"SpurGear_revolve_01": "bool_data",
|
||||
"SpurGear_revolve_02": "bool_data",
|
||||
}
|
||||
flags.update(_flags)
|
||||
|
||||
|
||||
def load_flag_types(root: Path) -> tp.Dict[str, str]:
|
||||
flag_types: tp.Dict[str, str] = dict()
|
||||
add_development_remnant_flags(flag_types)
|
||||
|
||||
gdt_dir = root / "GameData"
|
||||
for path in gdt_dir.glob("Flag/*.yml"):
|
||||
flag_list = oead.byml.from_text(path.read_text(encoding="utf-8"))
|
||||
keys = list(flag_list.keys())
|
||||
assert len(keys) == 1
|
||||
flag_type = keys[0]
|
||||
for flag in flag_list[flag_type]:
|
||||
flag_types[flag["DataName"]] = flag_type
|
||||
|
||||
return flag_types
|
||||
|
||||
|
||||
def write_struct_chunk(f: tp.TextIO, flags: tp.Collection[str], i: int) -> None:
|
||||
f.write(f"""\
|
||||
struct CommonFlags{i} {{
|
||||
""")
|
||||
for name in flags:
|
||||
f.write(f" FlagHandle flag_{name} = InvalidHandle;\n")
|
||||
f.write(f"""\
|
||||
u32 _pad = 0;
|
||||
}};
|
||||
|
||||
[[gnu::visibility("hidden")]] extern CommonFlags{i} sCommonFlags{i};
|
||||
""")
|
||||
|
||||
|
||||
FLAGS_PER_CHUNK = 1023
|
||||
|
||||
|
||||
def chunk_flag_iterator(flags: tp.Iterator[str]):
|
||||
while True:
|
||||
chunk = []
|
||||
for i in range(FLAGS_PER_CHUNK):
|
||||
try:
|
||||
chunk.append(next(flags))
|
||||
except StopIteration:
|
||||
break
|
||||
|
||||
if not chunk:
|
||||
return
|
||||
|
||||
yield chunk
|
||||
|
||||
|
||||
def main() -> None:
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument("root", help="Path to the root of the GameROM source")
|
||||
parser.add_argument("exe_flag_list", help="Path to a file containing a list of flags")
|
||||
args = parser.parse_args()
|
||||
|
||||
src_root = Path(__file__).parent.parent
|
||||
src_gdt = src_root / "src" / "KingSystem" / "GameData"
|
||||
root = Path(args.root)
|
||||
exe_flag_list = Path(args.exe_flag_list).read_text().splitlines()
|
||||
flag_types = load_flag_types(root)
|
||||
|
||||
with (src_gdt / "gdtCommonFlags.h").open("w") as f:
|
||||
f.write("""\
|
||||
#pragma once
|
||||
|
||||
// DO NOT EDIT. This file is automatically generated.
|
||||
|
||||
#include "KingSystem/GameData/gdtManager.h"
|
||||
|
||||
namespace ksys::gdt {
|
||||
|
||||
// clang-format off
|
||||
|
||||
namespace detail {
|
||||
|
||||
""")
|
||||
for i, chunk in enumerate(chunk_flag_iterator(iter(exe_flag_list))):
|
||||
write_struct_chunk(f, chunk, i)
|
||||
f.write("\n")
|
||||
f.write("""\
|
||||
} // namespace detail
|
||||
|
||||
void initCommonFlags();
|
||||
|
||||
""")
|
||||
|
||||
for i, name in enumerate(exe_flag_list):
|
||||
chunk_idx: int = i // FLAGS_PER_CHUNK
|
||||
f.write(f"inline FlagHandle& flag_{name}() {{ return detail::sCommonFlags{chunk_idx}.flag_{name}; }}\n")
|
||||
pass
|
||||
|
||||
f.write("""\
|
||||
|
||||
// clang-format on
|
||||
|
||||
} // namespace ksys::gdt
|
||||
""")
|
||||
|
||||
# Generate the implementation.
|
||||
|
||||
fn_names = {
|
||||
"bool_data": "getBoolHandle",
|
||||
"s32_data": "getS32Handle",
|
||||
"f32_data": "getF32Handle",
|
||||
"string_data": "getStrHandle",
|
||||
"string64_data": "getStr64Handle",
|
||||
"string256_data": "getStr256Handle",
|
||||
"vector2f_data": "getVec2fHandle",
|
||||
"vector3f_data": "getVec3fHandle",
|
||||
"vector4f_data": "getVec4fHandle",
|
||||
|
||||
"bool_array_data": "getBoolArrayHandle",
|
||||
"s32_array_data": "getS32ArrayHandle",
|
||||
"f32_array_data": "getF32ArrayHandle",
|
||||
"string_array_data": "getStrArrayHandle",
|
||||
"string64_array_data": "getStr64ArrayHandle",
|
||||
"string256_array_data": "getStr256ArrayHandle",
|
||||
"vector2f_array_data": "getVec2fArrayHandle",
|
||||
"vector3f_array_data": "getVec3fArrayHandle",
|
||||
"vector4f_array_data": "getVec4fArrayHandle",
|
||||
}
|
||||
|
||||
with (src_gdt / "gdtCommonFlags.cpp").open("w") as f:
|
||||
f.write("""\
|
||||
// DO NOT EDIT. This file is automatically generated.
|
||||
|
||||
#include "KingSystem/GameData/gdtCommonFlags.h"
|
||||
|
||||
namespace ksys::gdt {
|
||||
|
||||
namespace detail {
|
||||
|
||||
""")
|
||||
for i in range(len(exe_flag_list) // FLAGS_PER_CHUNK + 1):
|
||||
f.write(f"CommonFlags{i} sCommonFlags{i};\n")
|
||||
f.write("""
|
||||
} // namespace detail
|
||||
|
||||
void initCommonFlags_();
|
||||
|
||||
void initCommonFlags() {
|
||||
initCommonFlags_();
|
||||
}
|
||||
|
||||
void initCommonFlags_() {
|
||||
auto* mgr = Manager::instance();
|
||||
if (!mgr)
|
||||
return;
|
||||
|
||||
// clang-format off
|
||||
|
||||
""")
|
||||
for flag_name in exe_flag_list:
|
||||
f.write(f" flag_{flag_name}() = mgr->{fn_names[flag_types[flag_name]]}(\"{flag_name}\");\n")
|
||||
|
||||
f.write("""\
|
||||
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
} // namespace ksys::gdt
|
||||
""")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
|
@ -0,0 +1,31 @@
|
|||
# This script needs to be compatible with Python 2.7 as it is executed in IDA.
|
||||
|
||||
import idaapi
|
||||
import idautils
|
||||
import idc
|
||||
import os
|
||||
|
||||
# only valid in 1.5.0
|
||||
LOAD_SAVEDATA_FUNCTION_START = 0x71008BF8A0
|
||||
LOAD_SAVEDATA_FUNCTION_END = 0x71008E3DB8
|
||||
CRC32_FUNCTION_EA = 0x7100B2170C
|
||||
SAVEDATA_STRUCT = 0x710246F9E0
|
||||
|
||||
with open(os.path.dirname(os.path.realpath(__file__)) + "/../build/gdt_common_flags.txt", "w") as file:
|
||||
struct_offset = 0
|
||||
for ref in idautils.CodeRefsTo(idc.GetFunctionAttr(CRC32_FUNCTION_EA, idc.FUNCATTR_START), 1):
|
||||
if not (LOAD_SAVEDATA_FUNCTION_START < ref < LOAD_SAVEDATA_FUNCTION_END):
|
||||
continue
|
||||
|
||||
string_xref = idaapi.get_arg_addrs(ref)[0]
|
||||
iterator = idautils.XrefsFrom(string_xref, 0)
|
||||
next(iterator)
|
||||
string_addr = next(iterator).to
|
||||
string = idc.GetString(string_addr)
|
||||
|
||||
# For some reason the struct includes dummy members that should be skipped.
|
||||
if idaapi.get_dword(SAVEDATA_STRUCT + struct_offset) == 0:
|
||||
struct_offset += 4
|
||||
|
||||
file.write("%s\n" % string)
|
||||
struct_offset += 4
|
Loading…
Reference in New Issue