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"
|
version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
|
"iced-x86",
|
||||||
"libloading",
|
"libloading",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -52,6 +53,21 @@ version = "0.31.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
|
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]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.162"
|
version = "0.2.162"
|
||||||
|
|
|
@ -14,3 +14,4 @@ strip = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libloading = "0.8.5"
|
libloading = "0.8.5"
|
||||||
backtrace = "0.3.74"
|
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,
|
sync::LazyLock,
|
||||||
};
|
};
|
||||||
|
|
||||||
use lua_bindings::{lua_State, Lua51};
|
use iced_x86::Mnemonic;
|
||||||
|
use lua_bindings::{lua_State, Lua51, LUA_GLOBALSINDEX};
|
||||||
use noita::{NoitaPixelRun, ParticleWorldState};
|
use noita::{NoitaPixelRun, ParticleWorldState};
|
||||||
|
|
||||||
mod lua_bindings;
|
mod lua_bindings;
|
||||||
|
|
||||||
mod noita;
|
mod noita;
|
||||||
|
|
||||||
|
mod addr_grabber;
|
||||||
|
|
||||||
static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
|
static LUA: LazyLock<Lua51> = LazyLock::new(|| unsafe {
|
||||||
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
|
let lib = libloading::Library::new("./lua51.dll").expect("library to exist");
|
||||||
Lua51::from_library(lib).expect("library to be lua")
|
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());
|
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)]
|
#[derive(Default)]
|
||||||
struct ExtState {
|
struct ExtState {
|
||||||
particle_world_state: Option<ParticleWorldState>,
|
particle_world_state: Option<ParticleWorldState>,
|
||||||
|
globals: Option<GrabbedGlobals>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// const EWEXT: [(&'static str, Function); 1] = [("testfn", None)];
|
// 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
|
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
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// Only gets called by lua when loading a module.
|
/// 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 {
|
pub unsafe extern "C" fn luaopen_ewext0(lua: *mut lua_State) -> c_int {
|
||||||
println!("Initializing ewext");
|
println!("Initializing ewext");
|
||||||
unsafe {
|
unsafe {
|
||||||
|
grab_addrs(lua);
|
||||||
|
|
||||||
LUA.lua_createtable(lua, 0, 0);
|
LUA.lua_createtable(lua, 0, 0);
|
||||||
|
|
||||||
LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0);
|
LUA.lua_pushcclosure(lua, Some(init_particle_world_state), 0);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue