Skip to content

Commit

Permalink
Merge pull request #359 from expired6978/master
Browse files Browse the repository at this point in the history
More type support, more dumps, more accessible functions
  • Loading branch information
Yamashi authored Jan 3, 2021
2 parents 5294aa3 + 314f81b commit b6e5462
Show file tree
Hide file tree
Showing 6 changed files with 343 additions and 19 deletions.
4 changes: 3 additions & 1 deletion src/reverse/Converter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "Converter.h"

#include "BasicTypes.h"
#include "Enum.h"
#include "LuaRED.h"

auto s_metaVisitor = [](auto... args) {
Expand All @@ -24,7 +25,8 @@ auto s_metaVisitor = [](auto... args) {
LuaRED<EulerAngles, "EulerAngles">(),
LuaRED<ItemID, "gameItemID">(),
LuaRED<TweakDBID, "TweakDBID">(),
LuaRED<CName, "CName">()
LuaRED<CName, "CName">(),
LuaRED<Enum, "Enum">()
);

size_t Converter::Size(RED4ext::IRTTIType* apRtti)
Expand Down
139 changes: 139 additions & 0 deletions src/reverse/Enum.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
#include <stdafx.h>

#include "Enum.h"

Enum::Enum(const RED4ext::CStackType& stackType)
{
Get(stackType);
}

Enum::Enum(const std::string& typeName, const std::string& value)
{
auto* pType = static_cast<RED4ext::CEnum*>(RED4ext::CRTTISystem::Get()->GetEnum(RED4ext::FNV1a(typeName.c_str())));
if (pType)
{
m_type = pType;
SetValueByName(value);
}
}

Enum::Enum(const std::string& typeName, uint32_t value)
{
auto* pType = static_cast<RED4ext::CEnum*>(RED4ext::CRTTISystem::Get()->GetEnum(RED4ext::FNV1a(typeName.c_str())));
if (pType)
{
m_type = pType;
SetValueSafe(static_cast<uint32_t>(value));
}
}


Enum::Enum(const RED4ext::CEnum* pType, const std::string& value)
: m_type(pType)
{
SetValueByName(value);
}


Enum::Enum(const RED4ext::CEnum* pType, uint32_t value)
: m_type(pType)
{
SetValueSafe(static_cast<uint32_t>(value));
}

void Enum::SetValueSafe(uint64_t value)
{
for (auto i = 0; i < m_type->valueList.size; ++i)
{
if (m_type->valueList[i] == value)
{
m_value = value;
break;
}
}
}

void Enum::Get(const RED4ext::CStackType& stackType)
{
m_type = static_cast<RED4ext::CEnum*>(stackType.type);
switch (stackType.type->GetSize())
{
case sizeof(uint8_t) :
m_value = *static_cast<uint8_t*>(stackType.value);
break;
case sizeof(uint16_t):
m_value = *static_cast<uint16_t*>(stackType.value);
break;
case sizeof(uint32_t):
m_value = *static_cast<uint32_t*>(stackType.value);
break;
case sizeof(uint64_t):
m_value = *static_cast<uint64_t*>(stackType.value);
break;
}
}

void Enum::Set(RED4ext::CStackType& stackType, TiltedPhoques::Allocator* apAllocator)
{
stackType.type = const_cast<RED4ext::CEnum*>(m_type); // Sad cast
switch (m_type->GetSize())
{
case sizeof(uint8_t):
stackType.value = apAllocator->New<uint8_t>(static_cast<uint8_t>(m_value));
break;
case sizeof(uint16_t):
stackType.value = apAllocator->New<uint16_t>(static_cast<uint16_t>(m_value));
break;
case sizeof(uint32_t):
stackType.value = apAllocator->New<uint32_t>(static_cast<uint32_t>(m_value));
break;
case sizeof(uint64_t):
stackType.value = apAllocator->New<uint64_t>(static_cast<uint64_t>(m_value));
break;
}
}


std::string Enum::GetValueName() const
{
for (auto i = 0; i < m_type->valueList.size; ++i)
{
if (m_type->valueList[i] == m_value)
{
return RED4ext::CName(m_type->hashList[i]).ToString();
}
}

return "";
}


void Enum::SetValueByName(const std::string& value)
{
for (auto i = 0; i < m_type->hashList.size; ++i)
{
if (m_type->hashList[i] == RED4ext::FNV1a(value.c_str()))
{
m_value = m_type->valueList[i];
break;
}
}
}

std::string Enum::ToString() const
{
if (m_type)
{
RED4ext::CName name;
m_type->GetName(name);
return name.ToString() + std::string(" : ") + GetValueName() + std::string(" (") + std::to_string(m_value) + std::string(")");
}

return "Invalid enum";
}

const RED4ext::CEnum* Enum::GetType() const
{
return m_type;
}

106 changes: 106 additions & 0 deletions src/reverse/Enum.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
#pragma once

#include "LuaRED.h"

struct Enum
{
Enum(const RED4ext::CEnum*, const std::string& value);
Enum(const RED4ext::CEnum*, uint32_t value);
Enum(const RED4ext::CStackType& stackType);
Enum(const std::string& typeName, const std::string& value);
Enum(const std::string& typeName, uint32_t value);

void Get(const RED4ext::CStackType& stackType);
void Set(RED4ext::CStackType& stackType, TiltedPhoques::Allocator* apAllocator);

// Returns the enum value by name
std::string GetValueName() const;

// Sets value by name in the enum list
void SetValueByName(const std::string& value);

// Sets by value verified against enum list
void SetValueSafe(uint64_t value);

std::string ToString() const;

const RED4ext::CEnum* GetType() const;

protected:
const RED4ext::CEnum* m_type{ nullptr };
uint64_t m_value{ 0 };
};

template<>
struct LuaRED<Enum, "Enum">
{
sol::object ToLua(RED4ext::CStackType& aResult, sol::state_view aLua)
{
return make_object(aLua, Enum(aResult));
}

RED4ext::CStackType ToRED(sol::object aObject, RED4ext::IRTTIType* apRtti, TiltedPhoques::Allocator* apAllocator)
{
RED4ext::CStackType result;
if (aObject.is<Enum>())
{
auto* pEnum = aObject.as<Enum*>();
if (pEnum->GetType() == apRtti)
{
pEnum->Set(result, apAllocator);
}
else // The enum type we were passed isn't the same
{
result.type = apRtti;
result.value = nullptr;
}
}
else if (aObject.get_type() == sol::type::number) // Enum from number cast
{
auto* enumType = static_cast<RED4ext::CEnum*>(apRtti);
if (aObject != sol::nil)
{
Enum en(enumType, aObject.as<uint32_t>());
en.Set(result, apAllocator);
}
}
else if (aObject.get_type() == sol::type::string) // Enum from string cast
{
auto* enumType = static_cast<RED4ext::CEnum*>(apRtti);
if (aObject != sol::nil)
{
sol::state_view v(aObject.lua_state());
std::string str = v["tostring"](aObject);
Enum en(enumType, str);
en.Set(result, apAllocator);
}
}
else
{
// Probably not going to like this but ok
result.type = apRtti;
result.value = nullptr;
}

return result;
}

size_t Size() const noexcept
{
return m_pRtti ? m_pRtti->GetSize() : 0;
}

bool Is(RED4ext::IRTTIType* apRtti) const
{
if (apRtti->GetType() == RED4ext::ERTTIType::Enum)
{
m_pRtti = apRtti;
return true;
}

return false;
}

private:
mutable RED4ext::IRTTIType* m_pRtti{ nullptr };
};
63 changes: 48 additions & 15 deletions src/reverse/Type.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <stdafx.h>
#include <spdlog/fmt/fmt.h>

#include "Type.h"

Expand All @@ -14,6 +15,11 @@ std::string Type::Descriptor::ToString() const
{
result += "\t\t" + function + ",\n";
}
result += "},\n\tstaticFunctions: {\n";
for (auto& function : staticFunctions)
{
result += "\t\t" + function + ",\n";
}
result += "},\nproperties: {\n";
for (auto& property : properties)
{
Expand Down Expand Up @@ -57,8 +63,21 @@ sol::protected_function Type::InternalIndex(const std::string& acName)
auto* pFunc = m_pType->GetFunction(RED4ext::FNV1a(acName.c_str()));
if(!pFunc)
{
Overlay::Get().Log("Function '" + acName + "' not found in system '" + GetName() + "'.");
return sol::nil;
// Search the function table if it isn't found, the above function only searches by ShortName so overloads are not found
for (uint32_t i = 0; i < m_pType->funcs.size; ++i)
{
if (m_pType->funcs.entries[i]->name.hash == RED4ext::FNV1a(acName.c_str()))
{
pFunc = static_cast<RED4ext::CClassFunction*>(m_pType->funcs.entries[i]);
break;
}
}

if (!pFunc)
{
Overlay::Get().Log("Function '" + acName + "' not found in system '" + GetName() + "'.");
return sol::nil;
}
}

auto obj = make_object(m_lua, [pFunc, name = acName](Type* apType, sol::variadic_args args, sol::this_environment env, sol::this_state L)
Expand Down Expand Up @@ -98,21 +117,35 @@ Type::Descriptor Type::Dump() const
{
descriptor.name = m_pType->name.ToString();

for (auto i = 0u; i < m_pType->funcs.size; ++i)
RED4ext::CClass* type = m_pType;
while (type)
{
auto* pFunc = m_pType->funcs[i];
std::string funcName = pFunc->name.ToString();
descriptor.functions.push_back(funcName);
}
std::string name = type->name.ToString();
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);
}

for (auto i = 0u; i < m_pType->props.size; ++i)
{
auto* pProperty = m_pType->props[i];
RED4ext::CName name;
pProperty->type->GetName(name);

std::string propName = std::string(pProperty->name.ToString()) + " : " + name.ToString();
descriptor.properties.push_back(propName);
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);
}

for (auto i = 0u; i < type->props.size; ++i)
{
auto* pProperty = type->props[i];
RED4ext::CName name;
pProperty->type->GetName(name);

std::string propName = std::string(pProperty->name.ToString()) + " : " + name.ToString();
descriptor.properties.push_back(propName);
}

type = type->parent && type->parent->GetType() == RED4ext::ERTTIType::Class ? type->parent : nullptr;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/reverse/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ struct Type
{
std::string name{"Unknown"};
std::vector<std::string> functions;
std::vector<std::string> staticFunctions;
std::vector<std::string> properties;

std::string ToString() const;
Expand All @@ -22,7 +23,6 @@ struct Type
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);

protected:

virtual RED4ext::IScriptable* GetHandle() { return nullptr; }

RED4ext::CClass* m_pType{ nullptr };
Expand All @@ -33,3 +33,4 @@ struct Type
sol::state_view m_lua;
std::unordered_map<std::string, sol::object> m_properties;
};

Loading

0 comments on commit b6e5462

Please sign in to comment.