From 5129e21902336ae8555cdcae231a15655201a249 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebasti=C3=A1n=20Aedo?= Date: Fri, 31 Dec 2021 00:40:10 -0300 Subject: [PATCH] HACK: Changed xinput injection This fixes #33 but makes it incompatible with old versions. --- Cargo.lock | 4 +-- README.md | 2 +- botw-freecam/Cargo.toml | 2 +- botw-freecam/src/globals.rs | 2 ++ botw-freecam/src/interceptor.asm | 15 ++++++++++ botw-freecam/src/lib.rs | 47 ++++++++++++++++---------------- botw-freecam/src/utils.rs | 1 + 7 files changed, 45 insertions(+), 28 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2f4bd48..480458c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -49,7 +49,7 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "botw-freecam" -version = "0.2.5" +version = "0.2.6" dependencies = [ "cc", "log", @@ -151,7 +151,7 @@ dependencies = [ [[package]] name = "memory-rs" version = "0.2.4" -source = "git+https://github.com/etra0/memory-rs#ae3c7941180acb084a66c5685588149deed1bf3b" +source = "git+https://github.com/etra0/memory-rs#de3cce682e5f6df8d4641df375c4323628e318d6" dependencies = [ "anyhow", "winapi", diff --git a/README.md b/README.md index fcf3e70..11fcae0 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This is a BOTW Freecam. Simply run it and it should work. -Tested with Cemu 1.22.2 and Breath of the Wild v1.5.0 DLC Ver.3.0 (**Support for other versions is not assured**) +Tested with Cemu 1.26.2 and Breath of the Wild v1.5.0 DLC Ver.3.0 (**Support for other versions is not assured**) **WARNING: If you close the console it'll close the game. Press HOME to close it.** diff --git a/botw-freecam/Cargo.toml b/botw-freecam/Cargo.toml index 78d3631..22c8925 100644 --- a/botw-freecam/Cargo.toml +++ b/botw-freecam/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "botw-freecam" -version = "0.2.5" +version = "0.2.6" authors = ["Sebastián Aedo "] edition = "2018" diff --git a/botw-freecam/src/globals.rs b/botw-freecam/src/globals.rs index 00b8fa5..42b8347 100644 --- a/botw-freecam/src/globals.rs +++ b/botw-freecam/src/globals.rs @@ -3,8 +3,10 @@ memory_rs::scoped_no_mangle! { g_camera_active: u8 = 0x0; g_get_camera_data: usize = 0x0; + g_xinput_override: usize = 0x0; } extern "C" { pub static asm_get_camera_data: u8; + pub static asm_override_xinput_call: u8; } diff --git a/botw-freecam/src/interceptor.asm b/botw-freecam/src/interceptor.asm index 1074e69..91b67ce 100644 --- a/botw-freecam/src/interceptor.asm +++ b/botw-freecam/src/interceptor.asm @@ -3,6 +3,9 @@ EXTERN g_get_camera_data: qword EXTERN g_camera_active: byte EXTERN g_camera_struct: qword +EXTERN dummy_xinput: qword +EXTERN g_xinput_override: qword + .code asm_get_camera_data PROC pushf @@ -27,5 +30,17 @@ asm_get_camera_data PROC jmp [g_get_camera_data] asm_get_camera_data ENDP +; HACK: We use an intermediary to replace the function pointer in rax since we +; still don't write a function trampoline because life +asm_override_xinput_call PROC + ; original code + ; mov rax, [rax+28] + ; Instead, we'll move our function pointer to rax to call that one. + lea rax, dummy_xinput + lea rdx, [rbp-19h] + mov ecx, [rdi+00000150h] + jmp [g_xinput_override] + +asm_override_xinput_call ENDP END diff --git a/botw-freecam/src/lib.rs b/botw-freecam/src/lib.rs index 2ecff40..afdb406 100644 --- a/botw-freecam/src/lib.rs +++ b/botw-freecam/src/lib.rs @@ -22,7 +22,7 @@ mod utils; use camera::*; use dolly::*; use globals::*; -use utils::{check_key_press, dummy_xinput, error_message, handle_keyboard, Input, Keys}; +use utils::{check_key_press, error_message, handle_keyboard, Input, Keys}; use std::io::{self, Write}; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, WriteColor}; @@ -135,21 +135,20 @@ fn get_camera_function() -> Result> { }) } -fn block_xinput(proc_inf: &ProcessInfo) -> Result> { +fn block_xinput(proc_inf: &ProcessInfo) -> Result> { // Find input blocker for xinput only let function_addr = proc_inf.region.scan_aob(&memory_rs::generate_aob_pattern![ - 0x41, 0xFF, 0xD0, 0x85, 0xC0, 0x74, 0x16, 0x33, 0xC9, 0xC6, 0x87, 0x58, 0x01, 0x00, 0x00, - 0x00, 0x8B, 0xC1, 0x87, 0x47, 0x14, 0x86, 0x4F, 0x18 + 0x48, 0x8B, 0x40, 0x28, 0x48, 0x8D, 0x55, 0xE7, 0x8B, 0x8F, 0x50, 0x01, 0x00, 0x00 ])? .ok_or("XInput blocker couldn't be found")?; - let rip = (function_addr - 10) as *const u8; - let jmp_offset = unsafe { rip.offset(3).cast::().read() as isize }; - let final_function_ptr = unsafe { rip.offset(jmp_offset + 7) as usize }; + // HACK: read interceptor.asm + let injection = unsafe { + Detour::new(function_addr, 14, &asm_override_xinput_call as *const _ as usize, Some(&mut g_xinput_override)) + }; - let my_function = (dummy_xinput as usize).to_ne_bytes(); - let injection = Injection::new(final_function_ptr, Vec::from(my_function)); + println!("{:x?}", unsafe { &asm_override_xinput_call as *const _ as usize }); Ok(injection) } @@ -189,24 +188,24 @@ fn patch(_lib: LPVOID) -> Result<(), Box> { ) }; - let mut nops = vec![ + let mut nops: Vec> = vec![ // Camera pos and focus writers - Injection::new(camera_struct.camera + 0x17, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x55, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0xC2, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0xD9, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x117, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x12E, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x15D, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x174, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x22A, vec![0x90; 10]), - Injection::new(camera_struct.camera + 0x22A, vec![0x90; 10]), + Box::new(Injection::new(camera_struct.camera + 0x17, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x55, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0xC2, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0xD9, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x117, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x12E, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x15D, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x174, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x22A, vec![0x90; 10])), + Box::new(Injection::new(camera_struct.camera + 0x22A, vec![0x90; 10])), // Rotation - Injection::new(camera_struct.rotation_vec1, vec![0x90; 7]), - Injection::new(camera_struct.rotation_vec1 + 0x14, vec![0x90; 7]), - Injection::new(camera_struct.rotation_vec1 + 0x28, vec![0x90; 7]), - block_xinput(&proc_inf)?, + Box::new(Injection::new(camera_struct.rotation_vec1, vec![0x90; 7])), + Box::new(Injection::new(camera_struct.rotation_vec1 + 0x14, vec![0x90; 7])), + Box::new(Injection::new(camera_struct.rotation_vec1 + 0x28, vec![0x90; 7])), + Box::new(block_xinput(&proc_inf)?), ]; cam.inject(); diff --git a/botw-freecam/src/utils.rs b/botw-freecam/src/utils.rs index 9e357a4..d8e07d4 100644 --- a/botw-freecam/src/utils.rs +++ b/botw-freecam/src/utils.rs @@ -306,6 +306,7 @@ pub fn handle_controller(input: &mut Input, func: fn(u32, &mut xinput::XINPUT_ST } } +#[no_mangle] pub unsafe extern "system" fn dummy_xinput(a: u32, b: &mut xinput::XINPUT_STATE) -> u32 { if g_camera_active != 0 { *b = std::mem::zeroed();