Skip to content

Commit

Permalink
Merge branch 'master' into pd-upscaler
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jan 31, 2024
2 parents a612b8c + 0341611 commit 2ba19c8
Show file tree
Hide file tree
Showing 8 changed files with 250 additions and 10 deletions.
86 changes: 85 additions & 1 deletion shared/sdk/Application.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ Application* Application::get() {
}

Application::Function* Application::get_functions() {
static auto functions_offset = []() -> std::optional<int32_t> {
static auto functions_offset = [this]() -> std::optional<int32_t> {
spdlog::info("Searching for Application::functions offset...");

const auto mod = utility::get_executable();
Expand Down Expand Up @@ -72,6 +72,90 @@ Application::Function* Application::get_functions() {
spdlog::info("Skipping invalid Application::functions offset: {:x}", candidate);
}

bool found_wait_rendering = false;
bool found_begin_rendering = false;
bool found_end_rendering = false;

const auto module_entry_enum = sdk::find_type_definition("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 {
const auto ptr = (Application::Function*)((uintptr_t)this + i);

if (ptr == nullptr || IsBadReadPtr(ptr, sizeof(Application::Function) * 50)) {
continue;
}

for (auto j = 0; j < 1024; ++j) try {
const auto& func = ptr[j];

if (func.description == nullptr || IsBadReadPtr(func.description, 32)) {
break;
}

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) {
break; // the first one should always be valid.
}
}
} else if (func.priority != 1) {
break; // the first one should always be valid.
}
}

if (name == "WaitRendering") {
if (module_entry_enum != nullptr) {
if (auto f = sdk::get_native_field<uint16_t>(nullptr, module_entry_enum, "WaitRendering", true); f != nullptr) {
if (*f == func.priority) {
found_wait_rendering = true;
}
}
} else {
found_wait_rendering = true;
}
} else if (name == "BeginRendering") {
if (module_entry_enum != nullptr) {
if (auto f = sdk::get_native_field<uint16_t>(nullptr, module_entry_enum, "BeginRendering", true); f != nullptr) {
if (*f == func.priority) {
found_begin_rendering = true;
}
}
} else {
found_begin_rendering = true;
}
} else if (name == "EndRendering") {
if (module_entry_enum != nullptr) {
if (auto f = sdk::get_native_field<uint16_t>(nullptr, module_entry_enum, "EndRendering", true); f != nullptr) {
if (*f == func.priority) {
found_end_rendering = true;
}
}
} else {
found_end_rendering = true;
}
}

if (found_wait_rendering && found_begin_rendering && found_end_rendering) {
spdlog::info("Application::functions offset: {:x}", i);
return i;
}
} catch (...) {
continue;
}
} catch(...) {
continue;
}


spdlog::error("Cannot find Application::functions offset.");

return std::nullopt;
Expand Down
42 changes: 42 additions & 0 deletions shared/sdk/REContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,48 @@ namespace sdk {
spdlog::info("[VM::update_pointers] s_global_context: {:x}", (uintptr_t)s_global_context);
spdlog::info("[VM::update_pointers] s_get_thread_context: {:x}", (uintptr_t)s_get_thread_context);

// Needed on TDB73/AJ. The 0x30 offset we have is not correct, so we need to find the correct one
// And the "correct" one is the first one that doesn't look like a BS pointer (crude, i know)
// so... TODO: find a better way to do this
#if TDB_VER >= 71
if (s_global_context != nullptr && *s_global_context != nullptr) {
auto static_tbl = (REStaticTbl**)((uintptr_t)*s_global_context + s_static_tbl_offset);
if (IsBadReadPtr(*static_tbl, sizeof(void*)) || ((uintptr_t)*static_tbl & (sizeof(void*) - 1)) != 0) {
spdlog::info("[VM::update_pointers] Static table offset is bad, correcting...");

// We are looking for the two arrays, the static field table, and the static field "initialized table"
// The initialized table tells whether a specific entry in the static field table has been initialized or not
// so they both should have the same size, easy to find
for (auto i = sizeof(void*); i < 0x100; i+= sizeof(void*)) {
const auto& ptr = *(REStaticTbl**)((uintptr_t)*s_global_context + (s_type_db_offset - i));

if (IsBadReadPtr(ptr, sizeof(void*)) || ((uintptr_t)ptr & (sizeof(void*) - 1)) != 0) {
continue;
}

spdlog::info("[VM::update_pointers] Examining {:x}", (uintptr_t)ptr);

const auto& potential_count = *(uint32_t*)((uintptr_t)&ptr + sizeof(void*));

if (potential_count < 2000) {
continue;
}

constexpr auto array_size = (sizeof(void*) * 2);
const auto previous_offset = s_type_db_offset - i - array_size;
const auto& previous_ptr = *(REStaticTbl**)((uintptr_t)*s_global_context + previous_offset);
const auto& previous_count = *(uint32_t*)((uintptr_t)&previous_ptr + sizeof(void*));

if (previous_count == potential_count) {
spdlog::info("[VM::update_pointers] Found static table at {:x} (offset {:x})", (uintptr_t)ptr, previous_offset);
s_static_tbl_offset = previous_offset;
break;
}
}
}
}
#endif

// Get invoke_tbl
// this SEEMS to work on RE2 and onwards, but not on RE7
// look into it later
Expand Down
22 changes: 18 additions & 4 deletions shared/sdk/RETypeDB.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ void* find_native_method(std::string_view type_name, std::string_view method_nam
}

sdk::RETypeDefinition* RETypeDB::get_type(uint32_t index) const {
index &= get_type_bitmask();

if (index >= this->numTypes) {
return nullptr;
}
Expand Down Expand Up @@ -164,6 +166,8 @@ sdk::REProperty* RETypeDB::get_property(uint32_t index) const {
}

const char* RETypeDB::get_string(uint32_t offset) const {
offset &= get_string_pool_bitmask();

if (offset >= this->numStringPool) {
return nullptr;
}
Expand All @@ -172,6 +176,8 @@ const char* RETypeDB::get_string(uint32_t offset) const {
}

uint8_t* RETypeDB::get_bytes(uint32_t offset) const {
offset &= get_byte_pool_bitmask();

if (offset >= this->numBytePool) {
return nullptr;
}
Expand Down Expand Up @@ -215,7 +221,7 @@ const char* REField::get_name() const {

#if TDB_VER >= 69
auto& impl = (*tdb->fieldsImpl)[this->impl_id];
const auto name_offset = impl.name_offset;
const auto name_offset = impl.name_offset & tdb->get_string_pool_bitmask();
#else
const auto name_offset = this->name_offset;
#endif
Expand Down Expand Up @@ -377,7 +383,7 @@ const char* REMethodDefinition::get_name() const {

#if TDB_VER >= 69
auto& impl = (*tdb->methodsImpl)[this->impl_id];
const auto name_offset = impl.name_offset;
const auto name_offset = impl.name_offset & tdb->get_string_pool_bitmask();
#else
const auto name_offset = this->name_offset;
#endif
Expand Down Expand Up @@ -951,7 +957,7 @@ std::vector<uint32_t> REMethodDefinition::get_param_typeids() const {

// Parse all params
for (auto f = 0; f < num_params; ++f) {
const auto param_index = param_ids->params[f];
const auto param_index = param_ids->params[f] & tdb->get_param_bitmask();

if (param_index >= tdb->numParams) {
break;
Expand Down Expand Up @@ -992,8 +998,16 @@ std::vector<sdk::RETypeDefinition*> REMethodDefinition::get_param_types() const
auto tdb = RETypeDB::get();
std::vector<sdk::RETypeDefinition*> out{};

static const auto system_object = tdb->find_type("System.Object");

for (auto id : typeids) {
out.push_back(tdb->get_type(id));
const auto t = tdb->get_type(id);

if (t == nullptr) {
out.push_back(system_object); // TODO: this is a hack. not sure why this happens
continue;
}
out.push_back(t);
}

return out;
Expand Down
68 changes: 68 additions & 0 deletions shared/sdk/RETypeDB.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -757,14 +757,82 @@ struct RETypeDB : public sdk::RETypeDB_ {
return numFields;
}

#if TDB_VER >= 69
uint32_t get_num_params() const {
return numParams;
}
#endif

uint32_t get_num_properties() const {
return numProperties;
}

uint32_t get_string_pool_size() const {
return numStringPool;
}

uint32_t get_byte_pool_size() const {
return numBytePool;
}

const char* get_string(uint32_t offset) const;
uint8_t* get_bytes(uint32_t offset) const;

template <typename T> T* get_data(uint32_t offset) const { return (T*)get_bytes(offset); }

uint32_t get_string_pool_bitmask() const {
static auto result = [this]() -> uint32_t {
uint32_t out{1};
while (out < get_string_pool_size()) {
out <<= 1;
}

return out - 1;
}();

return result;
}

uint32_t get_byte_pool_bitmask() const {
static auto result = [this]() -> uint32_t {
uint32_t out{1};
while (out < get_byte_pool_size()) {
out <<= 1;
}

return out - 1;
}();

return result;
}

uint32_t get_type_bitmask() const {
static auto result = [this]() -> uint32_t {
uint32_t out{1};
while (out < get_num_types()) {
out <<= 1;
}

return out - 1;
}();

return result;
}

#if TDB_VER >= 69
uint32_t get_param_bitmask() const {
static auto result = [this]() -> uint32_t {
uint32_t out{1};
while (out < get_num_params()) {
out <<= 1;
}

return out - 1;
}();

return result;
}
#endif
};
} // namespace sdk

Expand Down
3 changes: 3 additions & 0 deletions src/Main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <utility/Module.hpp>
#include <utility/Thread.hpp>

#include "mods/IntegrityCheckBypass.hpp"
#include "ExceptionHandler.hpp"
#include "REFramework.hpp"

Expand Down Expand Up @@ -81,6 +82,8 @@ void startup_thread(HMODULE reframework_module) {

BOOL APIENTRY DllMain(HANDLE handle, DWORD reason, LPVOID reserved) {
if (reason == DLL_PROCESS_ATTACH) {
IntegrityCheckBypass::setup_pristine_syscall();

CreateThread(nullptr, 0, (LPTHREAD_START_ROUTINE)startup_thread, handle, 0, nullptr);
}

Expand Down
17 changes: 14 additions & 3 deletions src/mods/IntegrityCheckBypass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,9 +516,13 @@ void IntegrityCheckBypass::remove_stack_destroyer() {
spdlog::info("[IntegrityCheckBypass]: Patched stack destroyer!");
}

// hahahah i hate this
void IntegrityCheckBypass::fix_virtual_protect() try {
spdlog::info("[IntegrityCheckBypass]: Fixing VirtualProtect...");
void IntegrityCheckBypass::setup_pristine_syscall() {
if (s_pristine_protect_virtual_memory != nullptr) {
spdlog::info("[IntegrityCheckBypass]: NtProtectVirtualMemory already setup!");
return;
}

spdlog::info("[IntegrityCheckBypass]: Copying pristine NtProtectVirtualMemory...");

auto nt_protect_virtual_memory = (NtProtectVirtualMemory_t)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtProtectVirtualMemory");
if (nt_protect_virtual_memory == nullptr) {
Expand All @@ -536,6 +540,13 @@ void IntegrityCheckBypass::fix_virtual_protect() try {
s_pristine_protect_virtual_memory = (decltype(s_pristine_protect_virtual_memory))VirtualAlloc(nullptr, 256, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
memcpy(s_pristine_protect_virtual_memory, nt_protect_virtual_memory, 256);
spdlog::info("[IntegrityCheckBypass]: Copied NtProtectVirtualMemory to 0x{:X}", (uintptr_t)s_pristine_protect_virtual_memory);
}

// hahahah i hate this
void IntegrityCheckBypass::fix_virtual_protect() try {
spdlog::info("[IntegrityCheckBypass]: Fixing VirtualProtect...");

setup_pristine_syscall(); // Called earlier in DllMain

// Now disassemble our pristine function and just remove anything that looks like its a displacement or memory reference with nops
// im doing this because im too lazy to fix up the relocations
Expand Down
2 changes: 2 additions & 0 deletions src/mods/IntegrityCheckBypass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ class IntegrityCheckBypass : public Mod {
static void immediate_patch_re8();
static void immediate_patch_re4();
static void remove_stack_destroyer();

static void setup_pristine_syscall();
static void fix_virtual_protect();

private:
Expand Down
20 changes: 18 additions & 2 deletions src/mods/vr/runtimes/OpenXR.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,28 @@ VRRuntime::Error OpenXR::update_poses() {

uint32_t view_count{};

const auto display_time = this->frame_state.predictedDisplayTime + (XrDuration)(this->frame_state.predictedDisplayPeriod * this->prediction_scale);
// Only signal that we got the first valid pose if the display time becomes a sane value
if (!this->got_first_valid_poses) {
// Seen on VDXR
if (this->frame_state.predictedDisplayTime <= this->frame_state.predictedDisplayPeriod) {
spdlog::info("[VR] Frame state predicted display time is less than predicted display period!");
return VRRuntime::Error::SUCCESS;
}

// Seen on VDXR. If for some reason the above if statement doesn't work, this will catch it.
if (this->frame_state.predictedDisplayTime == 11111111) {
spdlog::info("[VR] Frame state predicted display time is 11111111!");
return VRRuntime::Error::SUCCESS;
}
}

if (display_time <= 1000) {
if (this->frame_state.predictedDisplayTime <= 1000) {
spdlog::info("[VR] Frame state predicted display time is less than 1000!");
return VRRuntime::Error::SUCCESS;
}

const auto display_time = this->frame_state.predictedDisplayTime + (XrDuration)(this->frame_state.predictedDisplayPeriod * this->prediction_scale);

XrViewLocateInfo view_locate_info{XR_TYPE_VIEW_LOCATE_INFO};
view_locate_info.viewConfigurationType = this->view_config;
view_locate_info.displayTime = display_time;
Expand Down

0 comments on commit 2ba19c8

Please sign in to comment.