Skip to content

Commit

Permalink
fix cvars offsets again and move register into new
Browse files Browse the repository at this point in the history
  • Loading branch information
catornot committed Jan 20, 2024
1 parent 6a68347 commit 209a8b4
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/bindings/cvar/convar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ pub mod root {
fMin: f32,
bMax: bool,
fMax: f32,
pCallback: *mut ::std::os::raw::c_void,
pCallback: FnChangeCallback_t,
);
extern "C" {
#[link_name = "\u{1}?conVarRegister@@3P6AXPEAVConVar@@PEBD1H1_NM2MPEAX@ZEA"]
Expand Down
96 changes: 40 additions & 56 deletions src/high/convars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,17 @@
//! return;
//! };
//!
//! let mut convar = ConVarStruct::try_new().unwrap(); // creates the convar struct
//! let register_info = ConVarRegister { // struct containing info the convar ( there is a lot of stuff )
//! callback: Some(cool_convar_change_callback),
//! ..ConVarRegister::mandatory(
//! "cool_convar",
//! "cool_convar",
//! "cool_default",
//! 0,
//! "cool_convar",
//! "this is a cool convar",
//! )
//! };
//!
//! convar.register(register_info).unwrap(); // register the convar
//!
//! let convar = ConVarStruct::try_new(&register_info).unwrap(); // create and register the convar
//! _ = COOLCONVAR.set(convar);
//! }
//!
//! // to access your convar, you will have to save them into a static or in the plugin struct
Expand Down Expand Up @@ -185,43 +184,13 @@ pub struct ConVarStruct {
}

impl ConVarStruct {
/// Creates an unregistered convar
///
/// Would only fail if something goes wrong with northstar
pub fn try_new() -> Option<Self> {
get_engine_data().map(move |engine| unsafe { Self::new(engine) })
}

unsafe fn new(engine: &EngineData) -> Self {
let convar_classes = &engine.convar;
unsafe {
let convar = SOURCE_ALLOC.alloc(Layout::new::<ConVar>()) as *mut ConVar;

addr_of_mut!((*convar).m_ConCommandBase.m_pConCommandBaseVTable)
.write(convar_classes.convar_vtable);

addr_of_mut!((*convar).m_ConCommandBase.s_pConCommandBases)
.write(convar_classes.iconvar_vtable);

#[allow(clippy::crosspointer_transmute)] // its what c++ this->convar_malloc is
(convar_classes.convar_malloc)(mem::transmute(addr_of_mut!((*convar).m_pMalloc)), 0, 0);
// Allocate new memory for ConVar.

Self {
inner: &mut *convar, // no way this is invalid
}
}
}

/// registers a convar from [`ConVarRegister`]
/// creates and registers a convar from [`ConVarRegister`]
///
/// this functions leaks the strings since convars live for the lifetime of the game :)
///
/// # Example
/// ```no_run
/// # use rrplug::prelude::*;
///
/// let mut convar = ConVarStruct::try_new().unwrap(); // creates the convar struct
/// let register_info = ConVarRegister { // struct containing info the convar ( there is a lot of stuff )
/// ..ConVarRegister::mandatory(
/// "a_convar",
Expand All @@ -231,27 +200,38 @@ impl ConVarStruct {
/// )
/// };
///
/// convar.register(register_info).unwrap(); // register the convar
/// let convar = ConVarStruct::try_new(&register_info).unwrap(); // create and register the convar
/// ```
pub fn register(&mut self, register_info: ConVarRegister) -> Result<(), RegisterError> {
let engine_data = get_engine_data().ok_or(RegisterError::NoneFunction)?;

self.private_register(register_info, engine_data)
pub fn try_new(register_info: &ConVarRegister) -> Result<Self, RegisterError> {
get_engine_data()
.map(move |engine| unsafe { Self::internal_try_new(engine, register_info) })
.unwrap_or_else(|| Err(RegisterError::NoneFunction))
}

pub(crate) fn private_register(
&mut self,
register_info: ConVarRegister,
#[inline]
unsafe fn internal_try_new(
engine_data: &EngineData,
) -> Result<(), RegisterError> {
log::info!("Registering ConVar {}", register_info.name);
register_info: &ConVarRegister,
) -> Result<Self, RegisterError> {
let convar_classes = engine_data.convar;
let convar = unsafe {
let convar = SOURCE_ALLOC.alloc(Layout::new::<ConVar>()) as *mut ConVar;

addr_of_mut!((*convar).m_ConCommandBase.m_pConCommandBaseVTable)
.write(convar_classes.convar_vtable);

addr_of_mut!((*convar).m_ConCommandBase.s_pConCommandBases)
.write(convar_classes.iconvar_vtable);

#[allow(clippy::crosspointer_transmute)] // its what c++ this->convar_malloc is
(convar_classes.convar_malloc)(mem::transmute(addr_of_mut!((*convar).m_pMalloc)), 0, 0); // Allocate new memory for ConVar.

convar
};

debug_assert!(!register_info.name.is_empty());

// the following stuff may still leak memory
// has to be investigated
// I think its safe
// since it should live until process termination so the os would clean it
// TODO: could be optimized to not allocated a cstring

let name = try_cstring(&register_info.name)?.into_bytes_with_nul();
let name_ptr =
Expand Down Expand Up @@ -285,8 +265,8 @@ impl ConVarStruct {
};

unsafe {
(engine_data.convar.convar_register)(
self.inner,
(convar_classes.convar_register)(
convar,
name_ptr as *const i8,
default_value_ptr as *const i8,
register_info.flags,
Expand All @@ -295,13 +275,17 @@ impl ConVarStruct {
register_info.fmin,
register_info.bmax,
register_info.fmax,
mem::transmute(register_info.callback),
register_info.callback,
)
}
Ok(())

log::info!("Registering ConVar {}", register_info.name);

Ok(Self {
inner: unsafe { &mut *convar }, // no way this is invalid
})
}

///
pub fn find_convar_by_name(name: &str) -> Option<Self> {
let name = try_cstring(name).ok()?;

Expand Down
10 changes: 7 additions & 3 deletions src/high/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,12 @@ impl EngineData {
) -> Result<(), RegisterError> {
use super::convars::{ConVarRegister, ConVarStruct};

let mut convar = ConVarStruct::try_new().ok_or(RegisterError::NoneResult)?;
let register_info = ConVarRegister::new(name, default_value, flags, help_string);
convar.private_register(register_info, self)
ConVarStruct::try_new(&ConVarRegister::new(
name,
default_value,
flags,
help_string,
))
.map(|_| ())
}
}
2 changes: 1 addition & 1 deletion src/mid/convars.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use super::utils::try_cstring;

offset_functions! {
CVAR_GLOBALS + CvarGlobals for WhichDll::Engine => {
convar_vtable = *mut c_void where offset(0x415C20);
convar_vtable = *mut c_void where offset(0x67FD28);
convar_register = ConVarRegisterType where offset(0x417230);
iconvar_vtable = *mut ConCommandBase where offset(0x67FD28);
convar_malloc = ConVarMallocType where offset(0x415C20);
Expand Down

0 comments on commit 209a8b4

Please sign in to comment.