From 51697acc6c80af6fb3796dd524fbabbfb17ca03e Mon Sep 17 00:00:00 2001 From: chendo Date: Fri, 1 Jan 2021 15:07:51 +1100 Subject: [PATCH 1/3] Improve Dump() by including param name/types to functions, as well as return types for properties --- src/reverse/Type.cpp | 47 ++++++++++++++++++++++++++++++++++++++++---- src/reverse/Type.h | 1 + 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/reverse/Type.cpp b/src/reverse/Type.cpp index 493bf6fa..88e910d8 100644 --- a/src/reverse/Type.cpp +++ b/src/reverse/Type.cpp @@ -90,6 +90,41 @@ std::string Type::GetName() const return ""; } +std::string Type::FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const +{ + std::stringstream ret; + + // name2 seems to be a cleaner representation of the name + // for example, name would be "DisableFootstepAudio;Bool", and name2 is just"DisableFootstepAudio" + std::string funcName2 = pFunc->name2.ToString(); + + ret << funcName2 << "("; + + RED4ext::CName name; + for (auto i = 0u; i < pFunc->params.size; ++i) + { + auto* param = pFunc->params[i]; + ret << param->name.ToString() << ": "; + param->type->GetName(name); + ret << name.ToString(); + if (i < pFunc->params.size - 1) { + ret << ", "; + } + } + + ret << ")"; + + const bool hasReturnType = (pFunc->returnType) != nullptr && (pFunc->returnType->type) != nullptr; + + if (hasReturnType) + { + pFunc->returnType->type->GetName(name); + ret << ": " << name.ToString(); + } + + return ret.str(); +} + Type::Descriptor Type::Dump() const { Descriptor descriptor; @@ -101,18 +136,22 @@ Type::Descriptor Type::Dump() const for (auto i = 0u; i < m_pType->funcs.size; ++i) { auto* pFunc = m_pType->funcs[i]; - std::string funcName = pFunc->name.ToString(); - descriptor.functions.push_back(funcName); + std::string funcDescriptor = FunctionDescriptor(pFunc); + descriptor.functions.push_back(funcDescriptor); } for (auto i = 0u; i < m_pType->props.size; ++i) { auto* pProperty = m_pType->props[i]; + RED4ext::CName name; pProperty->type->GetName(name); + + std::stringstream ret; + + ret << pProperty->name.ToString() << ": " << name.ToString(); - std::string propName = std::string(pProperty->name.ToString()) + " : " + name.ToString(); - descriptor.properties.push_back(propName); + descriptor.properties.push_back(ret.str()); } } diff --git a/src/reverse/Type.h b/src/reverse/Type.h index dfd7fe1f..d7461a99 100644 --- a/src/reverse/Type.h +++ b/src/reverse/Type.h @@ -18,6 +18,7 @@ struct Type sol::protected_function InternalIndex(const std::string& acName); std::string GetName() const; Descriptor Dump() const; + std::string FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const; sol::object Execute(RED4ext::CClassFunction* apFunc, const std::string& acName, sol::variadic_args args, sol::this_environment env, sol::this_state L, std::string& aReturnMessage); From 5e33946a3a0b973f54441d81ae467c5fd4f2e172 Mon Sep 17 00:00:00 2001 From: chendo Date: Sun, 3 Jan 2021 17:17:52 +1100 Subject: [PATCH 2/3] Move out params to return type, and allow Dump to take a second optional boolean to get hashes --- src/reverse/Type.cpp | 87 ++++++++++++++++++++++++++++++------- src/reverse/Type.h | 4 +- src/scripting/Scripting.cpp | 8 ++-- 3 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/reverse/Type.cpp b/src/reverse/Type.cpp index 6804b22a..00aff5f9 100644 --- a/src/reverse/Type.cpp +++ b/src/reverse/Type.cpp @@ -109,9 +109,12 @@ std::string Type::GetName() const return ""; } -std::string Type::FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const +std::string Type::FunctionDescriptor(RED4ext::CBaseFunction* pFunc, bool withHashes) const { std::stringstream ret; + RED4ext::CName typeName; + std::vector params; + bool hasOutParams = false; // name2 seems to be a cleaner representation of the name // for example, name would be "DisableFootstepAudio;Bool", and name2 is just"DisableFootstepAudio" @@ -119,14 +122,26 @@ std::string Type::FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const ret << funcName2 << "("; - RED4ext::CName name; for (auto i = 0u; i < pFunc->params.size; ++i) { auto* param = pFunc->params[i]; - ret << param->name.ToString() << ": "; - param->type->GetName(name); - ret << name.ToString(); - if (i < pFunc->params.size - 1) { + + if ((param->unk28 & 0x200) != 0) + { + // 'out' param, for returning additional data + // we hide these here so we can display them in the return types + hasOutParams = true; + continue; + } + param->type->GetName(typeName); + params.push_back(param->name.ToString() + std::string(": ") + typeName.ToString()); + } + + for (auto i = 0u; i < params.size(); ++i) + { + ret << params[i]; + if (i < params.size() - 1) + { ret << ", "; } } @@ -135,16 +150,59 @@ std::string Type::FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const const bool hasReturnType = (pFunc->returnType) != nullptr && (pFunc->returnType->type) != nullptr; + params.clear(); + if (hasReturnType) { - pFunc->returnType->type->GetName(name); - ret << ": " << name.ToString(); + pFunc->returnType->type->GetName(typeName); + params.push_back(typeName.ToString()); + } + + if (hasOutParams) + { + for (auto i = 0u; i < pFunc->params.size; ++i) + { + auto* param = pFunc->params[i]; + + if ((param->unk28 & 0x200) == 0) + { + // ignone non-out params cause we've dealt with them above + continue; + } + + param->type->GetName(typeName); + params.push_back(param->name.ToString() + std::string(": ") + typeName.ToString()); + } + + } + + if (params.size() > 0) + { + ret << " => ("; + + for (auto i = 0; i < params.size(); ++i) + { + ret << params[i]; + if (i < params.size() - 1) + { + ret << ", "; + } + } + + ret << ")"; + } + + + if (withHashes) + { + std::string funcHashes = "Hash:(" + fmt::format("{:016x}", pFunc->name.hash) + ") / ShortName:(" + pFunc->name2.ToString() + ") Hash:(" + fmt::format("{:016x}", pFunc->name2.hash) + ")"; + ret << " # " << funcHashes; } return ret.str(); } -Type::Descriptor Type::Dump() const +Type::Descriptor Type::Dump(bool withHashes) const { Descriptor descriptor; @@ -159,15 +217,15 @@ Type::Descriptor Type::Dump() const for (auto i = 0u; i < type->funcs.size; ++i) { auto* pFunc = type->funcs[i]; - std::string funcName = "Owner:(" + name + ") Hash:" + pFunc->name.ToString() + " Hash:( " + fmt::format("{:016x}", pFunc->name.hash) + ") / ShortName:(" + pFunc->name2.ToString() + ") Hash:( " + fmt::format("{:016x}", pFunc->name2.hash) + ")"; - descriptor.functions.push_back(funcName); + std::string funcDesc = FunctionDescriptor(pFunc, withHashes); + descriptor.functions.push_back(funcDesc); } for (auto i = 0u; i < type->staticFuncs.size; ++i) { auto* pFunc = type->staticFuncs[i]; - std::string funcName = "Owner:(" + name + ") Hash:" + pFunc->name.ToString() + " Hash:( " + fmt::format("{:016x}", pFunc->name.hash) + ") / ShortName:(" + pFunc->name2.ToString() + ") Hash:( " + fmt::format("{:016x}", pFunc->name2.hash) + ")"; - descriptor.staticFunctions.push_back(funcName); + std::string funcDesc = FunctionDescriptor(pFunc, withHashes); + descriptor.staticFunctions.push_back(funcDesc); } for (auto i = 0u; i < type->props.size; ++i) @@ -176,8 +234,7 @@ Type::Descriptor Type::Dump() const RED4ext::CName name; pProperty->type->GetName(name); - std::string propName = std::string(pProperty->name.ToString()) + " : " + name.ToString(); - descriptor.properties.push_back(propName); + descriptor.properties.push_back(pProperty->name.ToString() + std::string(": ") + name.ToString()); } type = type->parent && type->parent->GetType() == RED4ext::ERTTIType::Class ? type->parent : nullptr; diff --git a/src/reverse/Type.h b/src/reverse/Type.h index be06fdbb..9a9440eb 100644 --- a/src/reverse/Type.h +++ b/src/reverse/Type.h @@ -18,8 +18,8 @@ struct Type sol::object NewIndex(const std::string& acName, sol::object aParam); sol::protected_function InternalIndex(const std::string& acName); std::string GetName() const; - Descriptor Dump() const; - std::string FunctionDescriptor(RED4ext::CBaseFunction* pFunc) const; + Descriptor Dump(bool withHashes) const; + std::string FunctionDescriptor(RED4ext::CBaseFunction* pFunc, bool withHashes) const; sol::object Execute(RED4ext::CClassFunction* apFunc, const std::string& acName, sol::variadic_args args, sol::this_environment env, sol::this_state L, std::string& aReturnMessage); diff --git a/src/scripting/Scripting.cpp b/src/scripting/Scripting.cpp index 52506fd4..ec17e493 100644 --- a/src/scripting/Scripting.cpp +++ b/src/scripting/Scripting.cpp @@ -418,12 +418,12 @@ void Scripting::Initialize() return this->GetSingletonHandle(acName); }; - m_lua["Dump"] = [this](Type* apType) + m_lua["Dump"] = [this](Type* apType, bool detailed) { - return apType != nullptr ? apType->Dump() : Type::Descriptor{}; + return apType != nullptr ? apType->Dump(detailed) : Type::Descriptor{}; }; - m_lua["DumpType"] = [this](const std::string& acName) + m_lua["DumpType"] = [this](const std::string& acName, bool detailed) { auto* pRtti = RED4ext::CRTTISystem::Get(); auto* pType = pRtti->GetClass(RED4ext::FNV1a(acName.c_str())); @@ -431,7 +431,7 @@ void Scripting::Initialize() return Type::Descriptor(); Type type(m_lua, pType); - return type.Dump(); + return type.Dump(detailed); }; m_lua["print"] = [](sol::variadic_args args, sol::this_environment env, sol::this_state L) From 775066bf436b1d0342fa9bb873972948a62fb8cd Mon Sep 17 00:00:00 2001 From: chendo Date: Sun, 3 Jan 2021 17:22:05 +1100 Subject: [PATCH 3/3] Fix identing of output --- src/reverse/Type.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reverse/Type.cpp b/src/reverse/Type.cpp index 00aff5f9..815eecfe 100644 --- a/src/reverse/Type.cpp +++ b/src/reverse/Type.cpp @@ -15,12 +15,12 @@ std::string Type::Descriptor::ToString() const { result += "\t\t" + function + ",\n"; } - result += "},\n\tstaticFunctions: {\n"; + result += "\t},\n\tstaticFunctions: {\n"; for (auto& function : staticFunctions) { result += "\t\t" + function + ",\n"; } - result += "},\nproperties: {\n"; + result += "\t},\n\tproperties: {\n"; for (auto& property : properties) { result += "\t\t" + property + ",\n";