diff --git a/Cargo.toml b/Cargo.toml index c2eb1da..f10698d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,6 +17,7 @@ log = "0.4.1" serde = { version = "1.0.160", features = ["derive"]} toml = "0.7.2" broadsword = { git = "https://github.com/vswarte/broadsword.git" } +region = "3.0.2" [dependencies.windows] version = "0.48.0" diff --git a/README.md b/README.md index f75123b..75bdb6c 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ for loading DLLs. Make sure to back up your save games because if this mod loads vanilla save file first. This mod has been extensively tested with [ModEngine2](https://github.com/soulsmods/ModEngine2). And somewhat with -TechieW's Elden Mod Loader. +~~TechieW's Elden Mod Loader.~~ Do not use Elden Mod loader to load this. It will be flaky and not work at times. I will offer no support for this combination. #### How do I back up my save files? You can find your save files in the folder `%appdata%/EldenRing/`. Making a copy of that folder should suffice. diff --git a/src/lib.rs b/src/lib.rs index ce29ad6..b038ec0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ use broadsword::{dll, runtime, scanner}; #[dll::entrypoint] pub fn entry(_: usize) -> bool { + broadsword::logging::init("alt-saves.log"); file::hook(); regulation::hook(); true diff --git a/src/regulation.rs b/src/regulation.rs index 0417951..a79b067 100644 --- a/src/regulation.rs +++ b/src/regulation.rs @@ -1,39 +1,9 @@ -use std::mem::transmute; +use region::Protection; use retour::static_detour; +use std::mem::transmute; use crate::match_instruction_pattern; -static_detour! { - static REGULATIONMANAGER_CONSTRUCTOR: unsafe extern "system" fn(u64, u64) -> u64; -} - -const REGULATIONMANAGER_CONSTRUCTOR_PATTERN: &str = concat!( - // MOV qword ptr [RPS+0x8], RCX - "01001... 10001001 01001100 ..100100 00001000", - // PUSH RBX - "01010011", - // PUSH RSI - "01010110", - // PUSH RDI - "01010111", - // SUB RSP, 0x30 - "01001... 10000011 11101100 00110000", - // MOV qword ptr [RSP+0x20], -0x2 - "01001... 11000111 01000100 ..100100 00100000 11111110 11111111 11111111 11111111", - // MOV RBX, RCX - "01001... 10001011 11011001", - // LEA RAX, - "01001... 10001101 00000101 ........ ........ ........ ........", - // MOV qword ptr [RCX], RAX - "01001... 10001001 00000001", - // MOV qword ptr [RCX+0x8], RDX - "01001... 10001001 01010001 00001000", - // LEA RDI, [RCX+0x10] - "01001... 10001101 01111001 00010000", - // MOV qword ptr [RSP+0x60], RDI - "01001... 10001001 01111100 ..100100 01100000", -); - const REGBIN_CHECK_FLAG_SETTER_PATTERN: &str = concat!( // MOV RAX, qword ptr [RBX+0x8] "01001... 10001011 01000011 00001000", @@ -50,45 +20,20 @@ const REGBIN_CHECK_FLAG_SETTER_PATTERN: &str = concat!( // MOV [RegBinFlags + 1], AL "10001000 00000101 ........ ........ ........ ........", // MOV [RegBinFlags + 2], AL - "10001000 00000101 [........ ........ ........ ........]", + "[10001000 00000101 ........ ........ ........ ........]", ); pub fn hook() { - // Find the constructor's pointer - let regulationmanager_constructor = match_instruction_pattern(REGULATIONMANAGER_CONSTRUCTOR_PATTERN) - .expect("Could not find regulation manager constructor") - .location; - - // Find the regbin check flag by matching the second IBO and checking what offsets the code - // references. - let regbin_check_flag = { - let matched = match_instruction_pattern(REGBIN_CHECK_FLAG_SETTER_PATTERN) - .expect("Could not find the regbin check flag setter"); - - let capture = matched.captures.first().unwrap(); - let offset = u32::from_le_bytes(capture.bytes.as_slice().try_into().unwrap()); - - // We take the occurence location, add the offset from the bytes and add the size of the - // instruction itself (minus capture group offset in instruction) to find the - // absolute position. - capture.location + offset as usize + 4 - }; + let safety_flag_initializer_va = match_instruction_pattern(REGBIN_CHECK_FLAG_SETTER_PATTERN) + .map(|m| m.captures.first().map(|c| c.location as *mut u8)) + .flatten() + .expect("Could not find the regbin check flag setter"); unsafe { - REGULATIONMANAGER_CONSTRUCTOR - .initialize( - transmute(regulationmanager_constructor), - move |allocated_space: u64, param_2: u64| { - let result = REGULATIONMANAGER_CONSTRUCTOR.call(allocated_space, param_2); - // Overwrites the flag that seems to determine if the regulation - // bin file should be checked against a particular hash in the sl2. - *(regbin_check_flag as *mut u8) = 0x0; - - result - } - ) - .unwrap(); + region::protect(safety_flag_initializer_va, 1, Protection::READ_WRITE_EXECUTE) + .expect("Could not change memory protection for flag initializer"); - REGULATIONMANAGER_CONSTRUCTOR.enable().unwrap(); + // XOR in stead of MOV so we clear out the flag + *safety_flag_initializer_va = 0x30; } }