Skip to content

Commit

Permalink
SDK: More robust way of finding FSceneView constructor
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Jun 21, 2023
1 parent 4349881 commit a7e465e
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 26 deletions.
81 changes: 56 additions & 25 deletions shared/sdk/FSceneView.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#include <unordered_set>
#include <cstdint>

#include <spdlog/spdlog.h>
Expand Down Expand Up @@ -44,53 +45,83 @@ std::optional<uintptr_t> FSceneView::get_constructor_address() {

SPDLOG_INFO("[FSceneView] Found string references for FSceneView constructor");

// We need to find the function that contains both of these strings
std::vector<uintptr_t> instanced_string_refs{};
std::vector<uintptr_t> translucent_string_refs{};
//const auto instanced_string_refs = utility::scan_displacement_references(module, *instanced_string);
//const auto translucent_string_refs = utility::scan_displacement_references(module, *translucent_string);

for (const auto& instanced_string : instanced_strings) {
const auto instanced_string_refs_ = utility::scan_displacement_references(module, instanced_string);

instanced_string_refs.insert(instanced_string_refs.end(), instanced_string_refs_.begin(), instanced_string_refs_.end());
}

for (const auto& translucent_string : translucent_strings) {
SPDLOG_INFO("[FSceneView] Found r.TranslucentSortPolicy string at 0x{:x}", translucent_string);

const auto translucent_string_refs_ = utility::scan_displacement_references(module, translucent_string);

translucent_string_refs.insert(translucent_string_refs.end(), translucent_string_refs_.begin(), translucent_string_refs_.end());
}

if (instanced_string_refs.empty() || translucent_string_refs.empty()) {
if (translucent_string_refs.empty()) {
SPDLOG_ERROR("[FSceneView] Failed to find references for FSceneView constructor");
return std::nullopt;
}

std::vector<uintptr_t> instanced_functions{};
// For use with a fallback method
std::vector<uintptr_t> translucent_functions{};

for (const auto& translucent_ref : translucent_string_refs) {
SPDLOG_INFO("[FSceneView] Found r.TranslucentSortPolicy reference at 0x{:x}", translucent_ref);

for (const auto& instanced_ref : instanced_string_refs) {
const auto instanced_func = utility::find_function_start_with_call(instanced_ref);
const auto translucent_func = utility::find_function_start_with_call(translucent_ref);

if (!instanced_func) {
if (!translucent_func) {
continue;
}

instanced_functions.push_back(*instanced_func);
translucent_functions.push_back(*translucent_func);
}

for (const auto& translucent_ref : translucent_string_refs) {
const auto translucent_func = utility::find_function_start_with_call(translucent_ref);
// previously we naively checked if the vr.InstancedStereo string ref was
// in the same function as one of the r.TranslucentSortPolicy string refs
// however, at some point, UE decided to
// move the vr.InstancedStereo string ref inside of its own function
// however, this function is still called from the constructor
// so we can exhaustively disassemble all code paths from the r.TranslucentSortPolicy string refs
// until we find a reference to the vr.InstancedStereo string along the way
// this is kind of a scorched earth method, but it works
SPDLOG_INFO("[FSceneView] Exhaustively searching for FSceneView constructor");

if (!translucent_func) {
continue;
}
std::unordered_set<uintptr_t> seen_ips{};

for (const auto& translucent_function : translucent_functions) {
SPDLOG_INFO("[FSceneView] Exhaustively searching for references to vr.InstancedStereo in 0x{:x}", translucent_function);

bool is_correct_function = false;

for (const auto& instanced_func : instanced_functions) {
if (instanced_func == *translucent_func) {
SPDLOG_INFO("[FSceneView] Found FSceneView constructor at 0x{:x}", instanced_func);
return instanced_func;
utility::exhaustive_decode((uint8_t*)translucent_function, 1000, [&](INSTRUX& ix, uintptr_t ip) -> utility::ExhaustionResult {
if (seen_ips.contains(ip) || is_correct_function) {
return utility::ExhaustionResult::BREAK;
}

seen_ips.insert(ip);

// Looking for something like "lea rdx, "vr.InstancedStereo""
// but we will assume it can be any kind of instruction that references the string
const auto displacement = utility::resolve_displacement(ip);

if (!displacement) {
return utility::ExhaustionResult::CONTINUE;
}

// Check if the displacement is any of the vr.InstancedStereo strings
for (const auto& instanced_string : instanced_strings) {
if (*displacement == instanced_string) {
SPDLOG_INFO("[FSceneView] Found correct displacement at 0x{:x}", ip);
is_correct_function = true;
return utility::ExhaustionResult::BREAK;
}
}

return utility::ExhaustionResult::CONTINUE;
});

if (is_correct_function) {
SPDLOG_INFO("[FSceneView] Found FSceneView constructor at 0x{:x}", translucent_function);
return translucent_function;
}
}

Expand Down
1 change: 0 additions & 1 deletion src/mods/vr/FFakeStereoRenderingHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2484,7 +2484,6 @@ constexpr auto INIT_OPTION_SCENE_STATE_INTERFACE_OFFSET = 0xB8;
constexpr auto INIT_OPTIONS_PROJECTION_MATRIX_OFFSET = 0x50;
constexpr auto INIT_OPTIONS_STEREO_PASS_OFFSET = 0x108;

constexpr auto test = offsetof(sdk::FSceneViewInitOptions, scene_view_state);
// FSceneView constructor hook
sdk::FSceneView* FFakeStereoRenderingHook::sceneview_constructor(sdk::FSceneView* view, sdk::FSceneViewInitOptions* init_options, void* a3, void* a4) {
SPDLOG_INFO_ONCE("Called FSceneView constructor for the first time");
Expand Down

0 comments on commit a7e465e

Please sign in to comment.