diff --git a/src/lib.rs b/src/lib.rs index cac375e..abd44c1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ use imgui::*; use memory_rs::internal::process_info::ProcessInfo; use tweaks::editor_camera_speed::EditorCameraSpeedTweak; use tweaks::editor_placement::EditorPlacementTweak; +use tweaks::loading::LoadingTweak; use tweaks::map_lag::MapLagTweak; use tweaks::Tweak; use windows::Win32::Foundation::HINSTANCE; @@ -68,6 +69,7 @@ impl MainHud { this.add_tweak(MapLagTweak::new(&process.region)); this.add_tweak(EditorCameraSpeedTweak::new(&process.region)); this.add_tweak(EditorPlacementTweak::new(&process.region)); + this.add_tweak(LoadingTweak::new(&process.region)); }, Err(err) => this.errors.push(err), } diff --git a/src/main.rs b/src/main.rs index 692e157..3ace8cd 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,3 @@ -use std::path::{Path, PathBuf}; - use hudhook::inject::Process; fn main() { diff --git a/src/tweaks/loading.rs b/src/tweaks/loading.rs new file mode 100644 index 0000000..875ecf1 --- /dev/null +++ b/src/tweaks/loading.rs @@ -0,0 +1,143 @@ +use std::arch::asm; + +use anyhow::{anyhow, Context}; +use memory_rs::{generate_aob_pattern, internal::{injections::{Inject, Injection}, memory_region::MemoryRegion}}; + +use super::{MemoryRegionExt, Tweak}; + +const VANILLA_FAST_MENU_FADE: bool = false; +const DEFAULT_FAST_MENU_FADE: bool = true; + +const VANILLA_SKIP_LOAD_FINISH: bool = false; +const DEFAULT_SKIP_LOAD_FINISH: bool = true; + +pub struct LoadingTweak { + fast_menu_fade: bool, + fast_menu_fade_injection: Injection, + skip_load_finish: bool, + skip_load_finish_injection: Injection, +} + +impl LoadingTweak { + pub fn new(region: &MemoryRegion) -> anyhow::Result { + // --- main menu fading + + // ``` + // ... // some junk because I need more space to inject + // menu_state.fade_cur++; + // ``` + let memory_pattern = generate_aob_pattern![ + 0x49, 0x8B, 0xD4, // MOV RDX,R12 + 0xff, 0x90, 0xf0, 0x00, 0x00, 0x00, // CALL qword ptr [RAX + 0xf0] + 0x41, 0xff, 0x86, 0x80, 0xdb, 0x0b, 0x00 // INC dword ptr [R14 + 0xbdb80] + ]; + + let menu_fade_addr = { + region.scan_aob_single(&memory_pattern) + .context(anyhow!("Error finding menu fade addr"))? + }; + + // CALL custom_fade + let mut inject = vec![0xff, 0x15, 0x02, 0x00, 0x00, 0x00, 0xeb, 0x08]; + inject.extend_from_slice(&(custom_fade as usize).to_le_bytes()); + // pad with NOP + inject.resize(memory_pattern.size, 0x90); + + let mut menu_fade_injection = Injection::new(menu_fade_addr, inject); + + if DEFAULT_FAST_MENU_FADE { + menu_fade_injection.inject(); + } + + // --- skip loading wheel finish animation + + // `&& (visual_progress == 1.0)` + let memory_pattern = generate_aob_pattern![ + 0x0f, 0x2e, 0xc6, // UCOMISS XMM0,XMM6 + 0x7a, 0x41, // JP +41 + 0x75, 0x3f // JNZ +3f + ]; + + let skip_load_finish_addr = { + region.scan_aob_single(&memory_pattern) + .context(anyhow!("Error finding skip load finish addr"))? + }; + + let mut skip_load_finish_injection = Injection::new(skip_load_finish_addr + memory_pattern.size - 2, vec![0x90, 0x90]); + + if DEFAULT_SKIP_LOAD_FINISH { + skip_load_finish_injection.inject(); + } + + Ok(Self { + fast_menu_fade: DEFAULT_FAST_MENU_FADE, + fast_menu_fade_injection: menu_fade_injection, + skip_load_finish: DEFAULT_SKIP_LOAD_FINISH, + skip_load_finish_injection, + }) + } + + fn set_fast_menu_fade(&mut self, enabled: bool) { + self.fast_menu_fade = !enabled; + + if self.fast_menu_fade { + self.fast_menu_fade_injection.inject(); + } else { + self.fast_menu_fade_injection.remove_injection(); + } + } + + fn set_skip_load_finish(&mut self, enabled: bool) { + self.skip_load_finish = !enabled; + + if self.skip_load_finish { + self.skip_load_finish_injection.inject(); + } else { + self.skip_load_finish_injection.remove_injection(); + } + } +} + +impl Tweak for LoadingTweak { + fn uninit(&mut self) -> anyhow::Result<()> { + Ok(()) + } + + fn render(&mut self, ui: &hudhook::imgui::Ui) { + if ui.checkbox("Fast Main Menu Fade", &mut self.fast_menu_fade) { + self.set_fast_menu_fade(!self.fast_menu_fade); + } + if ui.is_item_hovered() { + ui.tooltip_text(format!("Speeds up the main menu loading fade\n(default: {DEFAULT_FAST_MENU_FADE}, vanilla: {VANILLA_FAST_MENU_FADE})")); + } + + if ui.checkbox("Skip Loading Finish Animation", &mut self.skip_load_finish) { + self.set_skip_load_finish(!self.skip_load_finish); + } + if ui.is_item_hovered() { + ui.tooltip_text(format!("Skips the animation of the progress bar going to 100%\n(default: {DEFAULT_SKIP_LOAD_FINISH}, vanilla: {VANILLA_SKIP_LOAD_FINISH})")); + } + } + + fn reset_to_default(&mut self) { + self.set_fast_menu_fade(DEFAULT_FAST_MENU_FADE); + self.set_skip_load_finish(DEFAULT_SKIP_LOAD_FINISH); + } + + fn reset_to_vanilla(&mut self) { + self.set_fast_menu_fade(VANILLA_FAST_MENU_FADE); + self.set_skip_load_finish(VANILLA_SKIP_LOAD_FINISH); + } +} + +#[no_mangle] +extern "stdcall" fn custom_fade() { + unsafe { + asm!( + "mov rdx,r12", // original code + "call [rax + 0xf0]", // original code + "add dword ptr [r14 + 0xbdb80],15", // inc by 15 instead of 1 + options(nostack), + ); + } +} \ No newline at end of file diff --git a/src/tweaks/mod.rs b/src/tweaks/mod.rs index 911729f..647b64d 100644 --- a/src/tweaks/mod.rs +++ b/src/tweaks/mod.rs @@ -4,6 +4,7 @@ use memory_rs::internal::memory_region::MemoryRegion; pub mod map_lag; pub mod editor_camera_speed; pub mod editor_placement; +pub mod loading; pub trait Tweak { fn uninit(&mut self) -> anyhow::Result<()>;