diff --git a/crates/livesplit-auto-splitting/src/lib.rs b/crates/livesplit-auto-splitting/src/lib.rs index e6e0144c..f8386065 100644 --- a/crates/livesplit-auto-splitting/src/lib.rs +++ b/crates/livesplit-auto-splitting/src/lib.rs @@ -100,6 +100,12 @@ //! name_ptr: *const u8, //! name_len: usize, //! ) -> Option; +//! /// Gets the size of a module in a process. +//! pub fn process_get_module_size( +//! process: ProcessId, +//! name_ptr: *const u8, +//! name_len: usize, +//! ) -> Option; //! //! /// Sets the tick rate of the runtime. This influences the amount of //! /// times the `update` function is called per second. diff --git a/crates/livesplit-auto-splitting/src/process.rs b/crates/livesplit-auto-splitting/src/process.rs index f6ce6252..607c50df 100644 --- a/crates/livesplit-auto-splitting/src/process.rs +++ b/crates/livesplit-auto-splitting/src/process.rs @@ -90,6 +90,26 @@ impl Process { .map(|m| m.start() as u64) } + pub fn module_size(&mut self, module: &str) -> Result { + let now = Instant::now(); + if now - self.last_check >= Duration::from_secs(1) { + self.modules = match proc_maps::get_process_maps(self.pid) { + Ok(m) => m, + Err(source) => { + self.modules.clear(); + return Err(ModuleError::ListModules { source }); + } + }; + self.last_check = now; + } + Ok(self + .modules + .iter() + .filter(|m| m.filename().map_or(false, |f| f.ends_with(module))) + .map(|m| m.size() as u64) + .sum()) + } + pub fn read_mem(&self, address: Address, buf: &mut [u8]) -> io::Result<()> { self.handle.copy_address(address as usize, buf) } diff --git a/crates/livesplit-auto-splitting/src/runtime.rs b/crates/livesplit-auto-splitting/src/runtime.rs index e67e3eae..af3e3f3b 100644 --- a/crates/livesplit-auto-splitting/src/runtime.rs +++ b/crates/livesplit-auto-splitting/src/runtime.rs @@ -380,6 +380,21 @@ fn bind_interface(linker: &mut Linker>) -> Result<(), Creat .context(LinkFunction { name: "process_get_module_address", })? + .func_wrap("env", "process_get_module_size", { + |mut caller: Caller<'_, Context>, process: u64, ptr: u32, len: u32| { + let (memory, context) = memory_and_context(&mut caller); + let module_name = read_str(memory, ptr, len)?; + Ok(context + .processes + .get_mut(ProcessKey::from(KeyData::from_ffi(process as u64))) + .ok_or_else(|| Trap::new(format!("Invalid process handle: {process}")))? + .module_size(module_name) + .unwrap_or_default()) + } + }) + .context(LinkFunction { + name: "process_get_module_size", + })? .func_wrap("env", "process_read", { |mut caller: Caller<'_, Context>, process: u64, diff --git a/src/auto_splitting/mod.rs b/src/auto_splitting/mod.rs index fbb02ad0..e58f7f11 100644 --- a/src/auto_splitting/mod.rs +++ b/src/auto_splitting/mod.rs @@ -100,6 +100,12 @@ //! name_ptr: *const u8, //! name_len: usize, //! ) -> Option; +//! /// Gets the size of a module in a process. +//! pub fn process_get_module_size( +//! process: ProcessId, +//! name_ptr: *const u8, +//! name_len: usize, +//! ) -> Option; //! //! /// Sets the tick rate of the runtime. This influences the amount of //! /// times the `update` function is called per second.