From f242ce69ee99ee863bc71369e93360846019f497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?L=C3=A9o=20Lam?= Date: Mon, 9 Nov 2020 13:53:18 +0100 Subject: [PATCH] ksys/gdt: Add more flag utilities --- src/KingSystem/GameData/gdtFlagUtils.h | 159 +++++++++++++++++++++++++ src/KingSystem/GameData/gdtManager.h | 79 +++++++++++- tools/generate_gdt_common_flags.py | 115 ++++++++++++++---- 3 files changed, 327 insertions(+), 26 deletions(-) diff --git a/src/KingSystem/GameData/gdtFlagUtils.h b/src/KingSystem/GameData/gdtFlagUtils.h index 8d73a470..3e1573df 100644 --- a/src/KingSystem/GameData/gdtFlagUtils.h +++ b/src/KingSystem/GameData/gdtFlagUtils.h @@ -14,4 +14,163 @@ inline bool getBool(FlagHandle handle, bool debug = false) { return value; } +inline s32 getS32(FlagHandle handle, bool debug = false) { + s32 value{}; + + auto* mgr = Manager::instance(); + if (mgr) + mgr->getS32(handle, &value, debug); + + return value; +} + +inline f32 getF32(FlagHandle handle, bool debug = false) { + f32 value{}; + + auto* mgr = Manager::instance(); + if (mgr) + mgr->getF32(handle, &value, debug); + + return value; +} + +inline void getStr(FlagHandle handle, const char** value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr(handle, value, debug); +} + +inline void getStr64(FlagHandle handle, const char** value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr64(handle, value, debug); +} + +inline void getStr256(FlagHandle handle, const char** value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr256(handle, value, debug); +} + +inline void getVec2f(FlagHandle handle, sead::Vector2f* value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec2f(handle, value, debug); +} + +inline void getVec3f(FlagHandle handle, sead::Vector3f* value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec3f(handle, value, debug); +} + +inline void getVec4f(FlagHandle handle, sead::Vector4f* value, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec4f(handle, value, debug); +} + +inline bool getBool(FlagHandle handle, s32 idx, bool debug = false) { + bool value{}; + + auto* mgr = Manager::instance(); + if (mgr) + mgr->getBool(handle, &value, idx, debug); + + return value; +} + +inline s32 getS32(FlagHandle handle, s32 idx, bool debug = false) { + s32 value{}; + + auto* mgr = Manager::instance(); + if (mgr) + mgr->getS32(handle, &value, idx, debug); + + return value; +} + +inline f32 getF32(FlagHandle handle, s32 idx, bool debug = false) { + f32 value{}; + + auto* mgr = Manager::instance(); + if (mgr) + mgr->getF32(handle, &value, idx, debug); + + return value; +} + +inline void getStr(FlagHandle handle, const char** value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr(handle, value, idx, debug); +} + +inline void getStr64(FlagHandle handle, const char** value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr64(handle, value, idx, debug); +} + +inline void getStr256(FlagHandle handle, const char** value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getStr256(handle, value, idx, debug); +} + +inline void getVec2f(FlagHandle handle, sead::Vector2f* value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec2f(handle, value, idx, debug); +} + +inline void getVec3f(FlagHandle handle, sead::Vector3f* value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec3f(handle, value, idx, debug); +} + +inline void getVec4f(FlagHandle handle, sead::Vector4f* value, s32 idx, bool debug = false) { + auto* mgr = Manager::instance(); + if (mgr) + mgr->getVec4f(handle, value, idx, debug); +} + +#define GDT_SET_FLAG_(NAME, T) \ + inline void NAME(T value, FlagHandle handle, bool debug = false) { \ + auto* mgr = Manager::instance(); \ + if (mgr) \ + mgr->NAME(value, handle, debug); \ + } \ + inline void NAME(T value, FlagHandle handle, s32 sub_idx, bool debug = false) { \ + auto* mgr = Manager::instance(); \ + if (mgr) \ + mgr->NAME(value, handle, debug, sub_idx); \ + } + +#define GDT_SET_FLAG_STR_(NAME, T) \ + inline void NAME(T value, FlagHandle handle, bool debug = false) { \ + auto* mgr = Manager::instance(); \ + if (mgr) \ + mgr->NAME(value.cstr(), handle, debug); \ + } \ + inline void NAME(T value, FlagHandle handle, s32 sub_idx, bool debug = false) { \ + auto* mgr = Manager::instance(); \ + if (mgr) \ + mgr->NAME(value.cstr(), handle, debug, sub_idx); \ + } + +GDT_SET_FLAG_(setBool, bool) +GDT_SET_FLAG_(setS32, s32) +GDT_SET_FLAG_(setF32, f32) +GDT_SET_FLAG_STR_(setStr, const sead::SafeString&) +GDT_SET_FLAG_STR_(setStr64, const sead::SafeString&) +GDT_SET_FLAG_STR_(setStr256, const sead::SafeString&) +GDT_SET_FLAG_(setVec2f, const sead::Vector2f&) +GDT_SET_FLAG_(setVec3f, const sead::Vector3f&) +GDT_SET_FLAG_(setVec4f, const sead::Vector4f&) + +#undef GDT_SET_FLAG_ +#undef GDT_SET_FLAG_STR_ + } // namespace ksys::gdt diff --git a/src/KingSystem/GameData/gdtManager.h b/src/KingSystem/GameData/gdtManager.h index 093f4f9c..fb3a489a 100644 --- a/src/KingSystem/GameData/gdtManager.h +++ b/src/KingSystem/GameData/gdtManager.h @@ -215,6 +215,12 @@ public: ref.get().NAME(value, idx); \ return true; \ }); \ + } \ + void NAME(FlagHandle handle, T* value, s32 sub_idx, bool debug = false) { \ + unwrapHandle(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ + ref.get().NAME(value, idx, sub_idx); \ + return true; \ + }); \ } GDT_GET_(getBool, bool) @@ -230,6 +236,7 @@ public: #undef GDT_GET_ #define GDT_SET_(NAME, T) \ + /* Setters (by handle) */ \ KSYS_ALWAYS_INLINE bool NAME(T value, FlagHandle handle, bool debug, bool force) { \ if (mBitFlags.isOn(BitFlag::_40000)) \ return false; \ @@ -242,7 +249,25 @@ public: bool NAME##NoCheckForce(T value, FlagHandle handle) { \ return NAME(value, handle, true, true); \ } \ - \ + /* Setters for arrays (by handle) */ \ + KSYS_ALWAYS_INLINE bool NAME(T value, FlagHandle handle, bool debug, bool force, \ + s32 sub_idx) { \ + if (mBitFlags.isOn(BitFlag::_40000)) \ + return false; \ + return unwrapHandle(handle, debug, [&](u32 idx, TriggerParamRef& ref) { \ + return ref.get().NAME(value, idx, sub_idx, force); \ + }); \ + } \ + bool NAME(T value, FlagHandle handle, s32 sub_idx) { \ + return NAME(value, handle, false, false, sub_idx); \ + } \ + bool NAME##NoCheck(T value, FlagHandle handle, s32 sub_idx) { \ + return NAME(value, handle, true, false, sub_idx); \ + } \ + bool NAME##NoCheckForce(T value, FlagHandle handle, s32 sub_idx) { \ + return NAME(value, handle, true, true, sub_idx); \ + } \ + /* Setters (by name) */ \ KSYS_ALWAYS_INLINE bool NAME(T value, const sead::SafeString& name, bool debug, bool force) { \ if (mBitFlags.isOn(BitFlag::_40000)) \ return false; \ @@ -257,6 +282,58 @@ public: } \ [[gnu::noinline]] bool NAME##NoCheckForce(T value, const sead::SafeString& name) { \ return NAME(value, name, true, true); \ + } \ + /* Setters for arrays (by name) */ \ + KSYS_ALWAYS_INLINE bool NAME(T value, const sead::SafeString& name, bool debug, bool force, \ + s32 sub_idx) { \ + if (mBitFlags.isOn(BitFlag::_40000)) \ + return false; \ + auto& ref = debug ? getParamBypassPerm() : getParam(); \ + return ref.get().NAME(value, name, sub_idx, force); \ + } \ + [[gnu::noinline]] bool NAME(T value, const sead::SafeString& name, s32 sub_idx) { \ + return NAME(value, name, false, false, sub_idx); \ + } \ + [[gnu::noinline]] bool NAME##NoCheck(T value, const sead::SafeString& name, s32 sub_idx) { \ + return NAME(value, name, true, false, sub_idx); \ + } \ + [[gnu::noinline]] bool NAME##NoCheckForce(T value, const sead::SafeString& name, \ + s32 sub_idx) { \ + return NAME(value, name, true, true, sub_idx); \ + } \ + \ + bool NAME(T value, FlagHandle handle, bool debug) { \ + if (debug) { \ + setBool(true, "IsChangedByDebug"); \ + mBitFlags.set(BitFlag::_800); \ + return NAME##NoCheckForce(value, handle); \ + } \ + return NAME(value, handle); \ + } \ + bool NAME(T value, const sead::SafeString& name, bool debug) { \ + if (debug) { \ + setBool(true, "IsChangedByDebug"); \ + mBitFlags.set(BitFlag::_800); \ + return NAME##NoCheckForce(value, name); \ + } \ + return NAME(value, name); \ + } \ + \ + bool NAME(T value, FlagHandle handle, bool debug, s32 sub_idx) { \ + if (debug) { \ + setBool(true, "IsChangedByDebug"); \ + mBitFlags.set(BitFlag::_800); \ + return NAME##NoCheckForce(value, handle, sub_idx); \ + } \ + return NAME(value, handle, sub_idx); \ + } \ + bool NAME(T value, const sead::SafeString& name, bool debug, s32 sub_idx) { \ + if (debug) { \ + setBool(true, "IsChangedByDebug"); \ + mBitFlags.set(BitFlag::_800); \ + return NAME##NoCheckForce(value, name, sub_idx); \ + } \ + return NAME(value, name, sub_idx); \ } GDT_SET_(setBool, bool) diff --git a/tools/generate_gdt_common_flags.py b/tools/generate_gdt_common_flags.py index 10432328..0adcc2ba 100755 --- a/tools/generate_gdt_common_flags.py +++ b/tools/generate_gdt_common_flags.py @@ -6,6 +6,58 @@ import typing as tp import oead +class FlagTypeInfo(tp.NamedTuple): + def get_getter_fn_name(self) -> str: + return self.getter_fn_name + + def get_handle_getter_fn_name(self) -> str: + s = self.getter_fn_name + if self.is_value_array(): + s += "Array" + s += "Handle" + return s + + def get_setter_fn_name(self) -> str: + return "s" + self.getter_fn_name[1:] + + def is_value_inline(self) -> bool: + return self.arg_type in ("bool", "s32", "f32") + + def is_value_array(self) -> bool: + return self.arg_type.endswith("_array_data") + + def get_setter_arg_type(self) -> str: + if self.arg_type == "const char*": + return "sead::SafeString" + return self.arg_type + + getter_fn_name: str + arg_type: str + + +flag_type_info = { + "bool_data": FlagTypeInfo("getBool", "bool"), + "s32_data": FlagTypeInfo("getS32", "s32"), + "f32_data": FlagTypeInfo("getF32", "f32"), + "string_data": FlagTypeInfo("getStr", "char const*"), + "string64_data": FlagTypeInfo("getStr64", "char const*"), + "string256_data": FlagTypeInfo("getStr256", "char const*"), + "vector2f_data": FlagTypeInfo("getVec2f", "sead::Vector2f"), + "vector3f_data": FlagTypeInfo("getVec3f", "sead::Vector3f"), + "vector4f_data": FlagTypeInfo("getVec4f", "sead::Vector4f"), + + "bool_array_data": FlagTypeInfo("getBool", "bool"), + "s32_array_data": FlagTypeInfo("getS32", "s32"), + "f32_array_data": FlagTypeInfo("getF32", "f32"), + "string_array_data": FlagTypeInfo("getStr", "char const*"), + "string64_array_data": FlagTypeInfo("getStr64", "char const*"), + "string256_array_data": FlagTypeInfo("getStr256", "char const*"), + "vector2f_array_data": FlagTypeInfo("getVec2f", "sead::Vector2f"), + "vector3f_array_data": FlagTypeInfo("getVec3f", "sead::Vector3f"), + "vector4f_array_data": FlagTypeInfo("getVec4f", "sead::Vector4f"), +} + + def add_development_remnant_flags(flags: tp.Dict[str, str]): _flags = { "AoC_DragonFireChallengeRing_Advent": "bool_data", @@ -116,7 +168,42 @@ 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 +""") + + with (src_gdt / "gdtCommonFlagsUtils.h").open("w") as f: + f.write("""\ +#pragma once + +// DO NOT EDIT. This file is automatically generated. + +#include "KingSystem/GameData/gdtCommonFlags.h" +#include "KingSystem/GameData/gdtFlagUtils.h" + +namespace ksys::gdt { + +// clang-format off + +""") + for i, name in enumerate(exe_flag_list): + info = flag_type_info[flag_types[name]] + if info.is_value_inline(): + f.write( + f"inline {info.arg_type} getFlag_{name}(bool debug = false) {{ return {info.get_getter_fn_name()}(flag_{name}(), debug); }}\n") + else: + f.write( + f"inline void getFlag_{name}({info.arg_type}* value, bool debug = false) {{ {info.get_getter_fn_name()}(flag_{name}(), value, debug); }}\n") + + for i, name in enumerate(exe_flag_list): + info = flag_type_info[flag_types[name]] + f.write( + f"inline void setFlag_{name}({info.get_setter_arg_type()} const& value, bool debug = false) {{ " + f"{info.get_setter_fn_name()}(value, flag_{name}(), debug); }}\n") f.write("""\ @@ -126,29 +213,6 @@ void initCommonFlags(); """) # 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. @@ -180,7 +244,8 @@ void initCommonFlags_() { """) for flag_name in exe_flag_list: - f.write(f" flag_{flag_name}() = mgr->{fn_names[flag_types[flag_name]]}(\"{flag_name}\");\n") + info = flag_type_info[flag_types[flag_name]] + f.write(f" flag_{flag_name}() = mgr->{info.get_handle_getter_fn_name()}(\"{flag_name}\");\n") f.write("""\