Skip to content

Commit

Permalink
Initial fixes for Monster Hunter Wilds
Browse files Browse the repository at this point in the history
+ReClass_Internal_MHWILDS.hpp

add_ref/release fixes, get_runtime_type fix

Fix
  • Loading branch information
praydog committed Oct 31, 2024
1 parent 8dbfc71 commit 131d3c8
Show file tree
Hide file tree
Showing 18 changed files with 5,425 additions and 21 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build-pr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
target: [RE2, RE2_TDB66, RE3, RE3_TDB67, RE4, RE7, RE7_TDB49, RE8, DMC5, MHRISE, SF6, DD2]
target: [RE2, RE2_TDB66, RE3, RE3_TDB67, RE4, RE7, RE7_TDB49, RE8, DMC5, MHRISE, SF6, DD2, MHWILDS]
steps:
- name: Checkout
uses: actions/checkout@v3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/dev-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ jobs:
runs-on: windows-latest
strategy:
matrix:
target: [RE2, RE2_TDB66, RE3, RE3_TDB67, RE4, RE7, RE7_TDB49, RE8, DMC5, MHRISE, SF6, DD2]
target: [RE2, RE2_TDB66, RE3, RE3_TDB67, RE4, RE7, RE7_TDB49, RE8, DMC5, MHRISE, SF6, DD2, MHWILDS]
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11
Expand Down
1,041 changes: 1,041 additions & 0 deletions CMakeLists.txt

Large diffs are not rendered by default.

10 changes: 10 additions & 0 deletions cmake.toml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ REF_BUILD_DMC5_SDK = false
REF_BUILD_MHRISE_SDK = false
REF_BUILD_SF6_SDK = false
REF_BUILD_DD2_SDK = false
REF_BUILD_MHWILDS_SDK = false
REF_BUILD_FRAMEWORK = { value = true, comment = "Enable building the full REFramework" }
REF_BUILD_DEPENDENCIES = { value = true, comment = "Enable building dependencies" }

Expand All @@ -64,6 +65,7 @@ build-dmc5-sdk = "REF_BUILD_DMC5_SDK OR REF_BUILD_FRAMEWORK"
build-mhrise-sdk = "REF_BUILD_MHRISE_SDK OR REF_BUILD_FRAMEWORK"
build-sf6-sdk = "REF_BUILD_SF6_SDK OR REF_BUILD_FRAMEWORK"
build-dd2-sdk = "REF_BUILD_DD2_SDK OR REF_BUILD_FRAMEWORK"
build-mhwilds-sdk = "REF_BUILD_MHWILDS_SDK OR REF_BUILD_FRAMEWORK"
build-framework-dependencies = "REF_BUILD_DEPENDENCIES AND CMAKE_SIZEOF_VOID_P EQUAL 8"

[fetch-content.asmjit]
Expand Down Expand Up @@ -351,6 +353,14 @@ condition = "build-dd2-sdk"
[target.DD2]
type = "game"

[target.MHWILDSSDK]
type = "sdk"
compile-definitions = ["MHWILDS", "REENGINE_PACKED", "REENGINE_AT"]
condition = "build-mhwilds-sdk"

[target.MHWILDS]
type = "game"

[template.plugin]
type = "shared"
include-directories = ["include/"]
Expand Down
9 changes: 8 additions & 1 deletion shared/sdk/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,10 @@ Application::Function* Application::get_functions() {

const auto module_entry_enum = sdk::find_type_definition("via.ModuleEntry");

if (module_entry_enum == nullptr) {
spdlog::error("Cannot find via.ModuleEntry");
}

// screw that lets just bruteforce through the Application object looking for huge
// list of valid pointers within the current module
for (auto i = 0x100; i < 0x1000; i += sizeof(void*)) try {
Expand All @@ -131,14 +135,17 @@ Application::Function* Application::get_functions() {
if (j == 0 && func.entry == nullptr || IsBadReadPtr(func.entry, sizeof(void*))) {
break; // the first one should always be valid.
}

const auto name = std::string_view{func.description};

if (j == 0) {
if (module_entry_enum != nullptr) {
if (auto f = sdk::get_native_field<uint16_t>(nullptr, module_entry_enum, name, true); f != nullptr) {
if (*f != func.priority) {
spdlog::error("{} priority mismatch: {} != {}", name.data(), *f, func.priority);
break; // the first one should always be valid.
} else{
spdlog::info("{} priority match: {} == {}", name.data(), *f, func.priority);
}
}
} else if (func.priority != 1) {
Expand Down
17 changes: 17 additions & 0 deletions shared/sdk/Application.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,37 @@
#include <cstdint>
#include <string_view>

#include "TDBVer.hpp"

namespace sdk {
struct RETypeDefinition;

struct Application {
struct Function {
void* entry; // 0
void (*func)(void* entry); // 0x8

#if TDB_VER < 74
void* unk; // 0x10
#endif

const char* description; // 0x18
uint16_t priority; // 0x20 (via.ModuleEntry enum)
uint16_t type; // 0x22

#if TDB_VER >= 74
uint8_t pad[0xC8 - 0x1C];
#else
uint8_t pad[0xD0 - 0x24];
#endif
};

#if TDB_VER >= 74
static_assert(sizeof(Function) == 0xC8, "Function has wrong size");
#elif TDB_VER < 74
static_assert(sizeof(Function) == 0xD0, "Function has wrong size");
#endif

static RETypeDefinition* get_type();
static Application* get();

Expand Down
10 changes: 6 additions & 4 deletions shared/sdk/REManagedObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,11 @@ void resolve_add_ref() {
return;
}

constexpr std::array<std::string_view, 3> possible_patterns{
constexpr std::array<std::string_view, 4> possible_patterns{
"40 ? 48 83 EC ? 8B 41 ? 48 8B ? 85 C0 0F ? ? ? ? ? 0F ? ? 0E", // RE2+
"40 ? 48 83 EC ? 8B 41 ? 48 8B ? 85 C0 0F ? ? ? ? ? 80 ? 0E 00", // TDB73+/DD2+
"48 89 ? ? ? 57 48 83 EC ? 0F ? ? 0E" // RE7 TDB49
"48 89 ? ? ? 57 48 83 EC ? 0F ? ? 0E", // RE7 TDB49
"41 57 41 56 41 55 41 54 56 57 55 53 48 83 EC ? 48 89 CE 8B 41 08 85 C0", // MHWILDS+ (or unoptimized compiler builds?)
};

spdlog::info("[REManagedObject] Finding add_ref function...");
Expand All @@ -53,9 +54,10 @@ void resolve_release() {
// because we need to make sure we don't resolve release to the same function.
resolve_add_ref();

constexpr std::array<std::string_view, 2> possible_patterns{
constexpr std::array<std::string_view, 3> possible_patterns{
"40 53 48 83 EC ? 8B 41 08 48 8B D9 85 C0 0F", // RE2+
"40 53 48 83 EC ? 8B 41 08 48 8B D9 48 83 C1 08 85 C0 78" // RE7
"40 53 48 83 EC ? 8B 41 08 48 8B D9 48 83 C1 08 85 C0 78", // RE7
"41 57 41 56 41 55 41 54 56 57 55 53 48 83 EC ? 48 8B 05 ? ? ? ? 48 31 E0 48 89 44 24 30 8B 41 08", // MHWILDS+ (or unoptimized compiler builds?)
};

spdlog::info("[REManagedObject] Finding release function...");
Expand Down
166 changes: 165 additions & 1 deletion shared/sdk/RETypeDB.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,157 @@ T* create_instance(std::string_view type_name, bool simplify = false);
#include "REGlobals.hpp"

namespace sdk {
namespace tdb74 {
struct REMethodDefinition;
struct REMethodImpl;
struct REField;
struct REFieldImpl;
struct REProperty;
struct RETypeImpl;
struct REPropertyImpl;
struct REParameterDef;

struct TDB {
uint32_t magic;
uint32_t version;
uint32_t numTypes;
uint32_t typesStartOfGenericsProbably; // I think this is the index of the start of the generics list in the types array (or start of something else)

uint32_t unk_int_tdb74;

uint32_t numMethods;
uint32_t numFields;
uint32_t numTypeImpl;
uint32_t numFieldImpl;
uint32_t numMethodImpl;
uint32_t numPropertyImpl;
uint32_t numProperties;
uint32_t numEvents;

uint32_t numParams;
uint32_t numAttributes;
int32_t numInitData;
uint32_t numAttributes2;
uint32_t numInternStrings;
uint32_t numModules;
int32_t devEntry;
int32_t appEntry;
uint32_t numStringPool;
uint32_t numBytePool;

uint32_t padding;

//
void* modules;
sdk::RETypeDefinition (*types)[93788];
sdk::RETypeImpl (*typesImpl)[256];
sdk::REMethodDefinition (*methods)[703558];
sdk::REMethodImpl (*methodsImpl)[56756];
sdk::REField (*fields)[1];
sdk::REFieldImpl (*fieldsImpl)[1];
sdk::REProperty (*properties)[256];
sdk::REPropertyImpl (*propertiesImpl)[1];
void* events;
sdk::REParameterDef (*params)[10000];
class ::REAttributeDef (*attributes)[2000];
int32_t (*initData)[19890];
void* unk;
int32_t (*attributes2)[256];
char (*stringPool)[1];
uint8_t (*bytePool)[256];
int32_t (*internStrings)[14154];
};

#pragma pack(push, 4)
struct REParameterDef {
uint16_t attributes_id;
uint16_t init_data_index;
uint32_t name_offset : 30;
uint32_t modifier : 2;
uint32_t type_id : TYPE_INDEX_BITS;
uint32_t flags : (32 - TYPE_INDEX_BITS);
};

struct REMethodDefinition {
uint32_t declaring_typeid : TYPE_INDEX_BITS;
uint32_t params_lo : 13;
uint32_t impl_id : 19;
uint32_t params_hi : 13;
int32_t encoded_offset;
};
static_assert(sizeof(REMethodDefinition) == 0xC);

struct REMethodImpl {
uint16_t attributes_id;
int16_t vtable_index;
uint16_t flags;
uint16_t impl_flags;
uint32_t name_offset;
};

struct RETypeImpl {
int32_t name_offset; // 0x0
int32_t namespace_offset; // 0x4
int32_t field_size; // 0x8
int32_t static_field_size; // 0xc
uint64_t unk_pad : 33; // 0x10
uint64_t num_member_fields : 24; // 0x10
uint64_t unk_pad_2 : 7; // 0x10
uint16_t num_member_methods; // 0x18
int16_t num_native_vtable; // 0x1a
int16_t interface_id; // 0x1c
char pad_1e[0x12];
};
#if TDB_VER >= 71
static_assert(sizeof(RETypeImpl) == 0x30);
static_assert(offsetof(RETypeImpl, num_member_methods) == 0x18);
#endif

struct REProperty {
uint64_t impl_id : 20;
uint64_t getter : 22;
uint64_t setter : 22;
};

struct REPropertyImpl {
uint16_t flags;
uint16_t attributes_id;
int32_t name_offset;
};
#pragma pack(pop)

struct ParamList {
uint16_t numParams; //0x0000
uint16_t invokeID; //0x0002
uint32_t returnType; //0x0004
uint32_t params[1]; //0x0008
};

struct REField {
uint64_t declaring_typeid : TYPE_INDEX_BITS;
uint64_t impl_id : TYPE_INDEX_BITS;
uint64_t field_typeid : TYPE_INDEX_BITS;
uint64_t init_data_hi : 6;
uint64_t rest2 : 1;
};

struct REFieldImpl {
uint16_t attributes_id;
uint16_t unk : 1;
uint16_t flags : 15;
uint32_t offset : 26;
uint32_t init_data_lo : 6;
uint32_t name_offset : 28;
uint32_t init_data_mid : 4;
};

struct GenericListData {
uint32_t definition_typeid : TYPE_INDEX_BITS;
uint32_t num : (32 - TYPE_INDEX_BITS);
uint32_t types[1];
};
}

namespace tdb73 {
struct REMethodDefinition;
struct REMethodImpl;
Expand Down Expand Up @@ -820,7 +971,20 @@ struct TDB {
#pragma pack(pop)
}

#if TDB_VER >= 73
#if TDB_VER >= 74
struct RETypeDB_ : public sdk::tdb74::TDB {};

struct REMethodDefinition_ : public sdk::tdb74::REMethodDefinition {};
struct REMethodImpl : public sdk::tdb74::REMethodImpl {};
using REField_ = sdk::tdb74::REField;
struct REFieldImpl : public sdk::tdb74::REFieldImpl {};
struct RETypeImpl : public sdk::tdb74::RETypeImpl {};
struct REPropertyImpl : public sdk::tdb74::REPropertyImpl {};
struct REProperty : public sdk::tdb74::REProperty {};
struct REParameterDef : public sdk::tdb74::REParameterDef {};
struct GenericListData : public sdk::tdb74::GenericListData {};
using ParamList = sdk::tdb74::ParamList;
#elif TDB_VER >= 73
struct RETypeDB_ : public sdk::tdb73::TDB {};

struct REMethodDefinition_ : public sdk::tdb73::REMethodDefinition {};
Expand Down
19 changes: 19 additions & 0 deletions shared/sdk/RETypeDefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -934,6 +934,25 @@ ::REManagedObject* RETypeDefinition::get_runtime_type() const {
static auto get_assemblies_func = appdomain_type->get_method("GetAssemblies");
static auto get_assembly_type_func = assembly_type->get_method("GetType(System.String)");

if (get_assembly_type_func == nullptr) {
// Past TDB 74, we have to do this because
// a lot of the assembly stuff seems to be stripped?
if (auto fn = this->get_method("GetType()"); fn != nullptr) {
struct TypeDefinitionHolder {
const sdk::RETypeDefinition* t{nullptr};
} holder;

struct FakeObject {
const TypeDefinitionHolder* holder{nullptr};
} fake_obj;

fake_obj.holder = &holder;
holder.t = this;

return fn->call<::REManagedObject*>(sdk::get_thread_context(), &fake_obj);
}
}

auto context = sdk::get_thread_context();
auto current_domain = get_current_domain_func->call<REManagedObject*>(context, nullptr);

Expand Down
Loading

0 comments on commit 131d3c8

Please sign in to comment.