Skip to content

Commit

Permalink
HACK: Changed xinput injection
Browse files Browse the repository at this point in the history
This fixes #33 but makes it incompatible with old versions.
  • Loading branch information
etra0 committed Dec 31, 2021
1 parent 1fcf4c4 commit 5129e21
Show file tree
Hide file tree
Showing 7 changed files with 45 additions and 28 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.**

Expand Down
2 changes: 1 addition & 1 deletion botw-freecam/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "botw-freecam"
version = "0.2.5"
version = "0.2.6"
authors = ["Sebastián Aedo <sebastian.aedo@sansano.usm.cl>"]
edition = "2018"

Expand Down
2 changes: 2 additions & 0 deletions botw-freecam/src/globals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
15 changes: 15 additions & 0 deletions botw-freecam/src/interceptor.asm
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
47 changes: 23 additions & 24 deletions botw-freecam/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -135,21 +135,20 @@ fn get_camera_function() -> Result<CameraOffsets, Box<dyn std::error::Error>> {
})
}

fn block_xinput(proc_inf: &ProcessInfo) -> Result<Injection, Box<dyn std::error::Error>> {
fn block_xinput(proc_inf: &ProcessInfo) -> Result<Detour, Box<dyn std::error::Error>> {
// 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::<u32>().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)
}
Expand Down Expand Up @@ -189,24 +188,24 @@ fn patch(_lib: LPVOID) -> Result<(), Box<dyn std::error::Error>> {
)
};

let mut nops = vec![
let mut nops: Vec<Box<dyn Inject>> = 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();
Expand Down
1 change: 1 addition & 0 deletions botw-freecam/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down

0 comments on commit 5129e21

Please sign in to comment.