mirror of
https://github.com/IntQuant/noita_entangled_worlds.git
synced 2025-10-19 07:03:16 +00:00
Grab addresses of globals.
This commit is contained in:
parent
f47a91150e
commit
f1a0bbf07f
4 changed files with 90 additions and 1 deletions
16
ewext/Cargo.lock
generated
16
ewext/Cargo.lock
generated
|
@ -43,6 +43,7 @@ name = "ewext"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"iced-x86",
|
||||
"libloading",
|
||||
]
|
||||
|
||||
|
@ -52,6 +53,21 @@ version = "0.31.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
||||
|
||||
[[package]]
|
||||
name = "iced-x86"
|
||||
version = "1.21.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7c447cff8c7f384a7d4f741cfcff32f75f3ad02b406432e8d6c878d56b1edf6b"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "lazy_static"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.162"
|
||||
|
|
|
@ -14,3 +14,4 @@ strip = true
|
|||
[dependencies]
|
||||
libloading = "0.8.5"
|
||||
backtrace = "0.3.74"
|
||||
iced-x86 = "1.21.0"
|
||||
|
|
27
ewext/src/addr_grabber.rs
Normal file
27
ewext/src/addr_grabber.rs
Normal file
|
@ -0,0 +1,27 @@
|
|||
use std::{os::raw::c_void, ptr};
|
||||
|
||||
use iced_x86::{Decoder, DecoderOptions, Mnemonic};
|
||||
|
||||
pub(crate) unsafe fn grab_addr_from_instruction(
|
||||
func: *const c_void,
|
||||
offset: isize,
|
||||
expected_mnemonic: Mnemonic,
|
||||
) -> *mut c_void {
|
||||
let instruction_addr = func.wrapping_offset(offset);
|
||||
// We don't really have an idea of how many bytes the instruction takes, so just take *enough* bytes for most cases.
|
||||
let instruction_bytes = ptr::read_unaligned(instruction_addr.cast::<[u8; 16]>());
|
||||
let mut decoder = Decoder::with_ip(
|
||||
32,
|
||||
&instruction_bytes,
|
||||
instruction_addr as u64,
|
||||
DecoderOptions::NONE,
|
||||
);
|
||||
let instruction = decoder.decode();
|
||||
|
||||
if instruction.mnemonic() != expected_mnemonic {
|
||||
println!("Encountered unexpected mnemonic: {}", instruction);
|
||||
}
|
||||
assert_eq!(instruction.mnemonic(), expected_mnemonic);
|
||||
|
||||
instruction.memory_displacement32() as *mut c_void
|
||||
}
|
|
@ -4,13 +4,16 @@ use std::{
|
|||
sync::LazyLock,
|
||||
};
|
||||
|
||||
use lua_bindings::{lua_State, Lua51};
|
||||
use iced_x86::Mnemonic;
|
||||
use lua_bindings::{lua_State, Lua51, LUA_GLOBALSINDEX};
|
||||
use noita::{NoitaPixelRun, ParticleWorldState};
|
||||
|
||||
mod lua_bindings;
|
||||
|
||||
mod noita;
|
||||
|
||||
mod addr_grabber;
|
||||
|
||||
static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
|
||||
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
|
||||
Lua51::from_library(lib).expect("library to be lua")
|
||||
|
@ -20,9 +23,15 @@ thread_local! {
|
|||
static STATE: LazyCell<RefCell<ExtState>> = LazyCell::new(|| ExtState::default().into());
|
||||
}
|
||||
|
||||
struct GrabbedGlobals {
|
||||
game_global: *const c_void,
|
||||
world_state_entity: *const c_void,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct ExtState {
|
||||
particle_world_state: Option<ParticleWorldState>,
|
||||
globals: Option<GrabbedGlobals>,
|
||||
}
|
||||
|
||||
// const EWEXT: [(&'static str, Function); 1] = [("testfn", None)];
|
||||
|
@ -61,6 +70,40 @@ unsafe extern "C" fn encode_area(lua: *mut lua_State) -> c_int {
|
|||
1
|
||||
}
|
||||
|
||||
unsafe fn grab_addrs(lua: *mut lua_State) {
|
||||
LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetWorldStateEntity".as_ptr());
|
||||
let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void;
|
||||
let world_state_entity =
|
||||
addr_grabber::grab_addr_from_instruction(base, 0x007aa7ce - 0x007aa540, Mnemonic::Mov);
|
||||
println!(
|
||||
"World state entity addr: 0x{:x}",
|
||||
world_state_entity as usize
|
||||
);
|
||||
// Pop the last element.
|
||||
LUA.lua_settop(lua, -2);
|
||||
|
||||
LUA.lua_getfield(lua, LUA_GLOBALSINDEX, c"GameGetFrameNum".as_ptr());
|
||||
let base = LUA.lua_tocfunction(lua, -1).unwrap() as *const c_void;
|
||||
let load_game_global =
|
||||
addr_grabber::grab_addr_from_instruction(base, 0x007bf3c9 - 0x007bf140, Mnemonic::Call); // CALL load_game_global
|
||||
println!("Load game global addr: 0x{:x}", load_game_global as usize);
|
||||
let game_global = addr_grabber::grab_addr_from_instruction(
|
||||
load_game_global,
|
||||
0x00439c17 - 0x00439bb0,
|
||||
Mnemonic::Mov,
|
||||
);
|
||||
println!("Game global addr: 0x{:x}", game_global as usize);
|
||||
// Pop the last element.
|
||||
LUA.lua_settop(lua, -2);
|
||||
|
||||
STATE.with(|state| {
|
||||
state.borrow_mut().globals = Some(GrabbedGlobals {
|
||||
game_global,
|
||||
world_state_entity,
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/// # Safety
|
||||
///
|
||||
/// Only gets called by lua when loading a module.
|
||||
|
@ -68,6 +111,8 @@ unsafe extern "C" fn encode_area(lua: *mut lua_State) -> c_int {
|
|||
pub unsafe extern "C" fn luaopen_ewext0(lua: *mut lua_State) -> c_int {
|
||||
println!("Initializing ewext");
|
||||
unsafe {
|
||||
grab_addrs(lua);
|
||||
|
||||
LUA.lua_createtable(lua, 0, 0);
|
||||
|
||||
LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue