Skip to content

Instantly share code, notes, and snippets.

@Ryan-rsm-McKenzie
Created February 25, 2020 06:04
Show Gist options
  • Save Ryan-rsm-McKenzie/ff2a8745a98abb0ecc51a5e07de5a13a to your computer and use it in GitHub Desktop.
Save Ryan-rsm-McKenzie/ff2a8745a98abb0ecc51a5e07de5a13a to your computer and use it in GitHub Desktop.
rtti dump
void DumpRTTI()
{
std::vector<std::pair<std::string, std::uint64_t>> results;
REL::VTable typeInfo(".?AVtype_info@@");
auto baseAddr = REL::Module::BaseAddr();
auto data = REL::Module::GetSection(REL::Module::ID::kData);
auto beg = data.BasePtr<std::uintptr_t>();
auto end = reinterpret_cast<std::uintptr_t*>(data.BaseAddr() + data.Size());
for (auto iter = beg; iter < end; ++iter) {
if (*iter == typeInfo.GetAddress()) {
auto typeDescriptor = reinterpret_cast<RE::RTTI::TypeDescriptor*>(iter);
try {
auto id = REL::IDDatabase::OffsetToID(reinterpret_cast<std::uintptr_t>(iter) - baseAddr);
results.push_back(std::make_pair(DecodeName(typeDescriptor), id));
} catch ([[maybe_unused]] std::exception& e) {
_ERROR("%s", DecodeName(typeDescriptor).c_str());
continue;
}
}
}
std::ofstream file("output.txt");
std::sort(results.begin(), results.end());
for (auto& result : results) {
file << "static constexpr REL::ID " << result.first << "(static_cast<std::uint64_t>(" << result.second << "));\n";
}
}
void DumpNiRTTI()
{
constexpr REL::Offset<std::uintptr_t> SEEDS[] = { // 1_5_97
0x03012388, // NiObject
0x03013748, // NiCullingProcess
0x02F07CD8, // BSFaceGenMorphData
0x02F0D428, // BSTempEffect
0x0302F330, // bhkPositionConstraintMotor
0x0302F340, // bhkVelocityConstraintMotor
0x0302F350, // bhkSpringDamperConstraintMotor
};
std::unordered_set<std::uintptr_t> results;
for (std::size_t i = 0; i < std::extent_v<decltype(SEEDS)>; ++i) {
results.insert(SEEDS[i].GetAddress());
}
auto baseAddr = REL::Module::BaseAddr();
auto data = REL::Module::GetSection(REL::Module::ID::kData);
auto beg = data.BasePtr<std::uintptr_t>();
auto end = reinterpret_cast<std::uintptr_t*>(data.BaseAddr() + data.Size());
bool found;
do {
found = false;
for (auto iter = beg; iter < end; ++iter) {
if (results.find(*iter) != results.end()) {
auto ins = results.insert(reinterpret_cast<std::uintptr_t>(iter - 1));
if (!found) {
found = ins.second;
}
}
}
} while (found);
using value_type = std::pair<std::string, std::uint64_t>;
std::vector<value_type> toPrint;
for (auto& result : results) {
auto rtti = reinterpret_cast<RE::NiRTTI*>(result);
std::string name = "NiRTTI_";
name += rtti->GetName();
try {
auto id = REL::IDDatabase::OffsetToID(result - baseAddr);
toPrint.push_back(std::make_pair(std::move(name), id));
} catch ([[maybe_unused]] std::exception& e) {
_ERROR("%s", rtti->GetName());
}
}
auto comp = [](const value_type& a_lhs, const value_type& a_rhs) -> bool
{
return a_lhs.first < a_rhs.first;
};
std::sort(toPrint.begin(), toPrint.end(), comp);
std::ifstream input("input.txt");
std::string line;
while (std::getline(input, line) && !line.empty()) {
auto elem = value_type(std::move(line), 0);
auto exists = std::binary_search(toPrint.begin(), toPrint.end(), elem, comp);
if (!exists) {
_ERROR("Failed to find %s", elem.first.c_str());
}
}
std::ofstream output("output.txt");
for (auto& elem : toPrint) {
output << "static constexpr REL::ID " << elem.first << "(static_cast<std::uint64_t>(" << elem.second << "));\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment