5 releases (breaking)
| 0.7.0 | Apr 26, 2025 |
|---|---|
| 0.6.0 | Apr 6, 2025 |
| 0.5.0 | Mar 22, 2025 |
| 0.4.0 | Mar 20, 2025 |
| 0.1.0 | Mar 14, 2025 |
#781 in Rust patterns
378 downloads per month
2KB
FromSoftware-rs 🔩 From Software runtime rust bindings
Rust bindings to facilitate mod creation for From Software games.
Example Elden Ring mod code: render debug line
use std::time::Duration;
use eldenring::{
cs::{CSTaskImp, RendMan, WorldChrMan},
fd4::FD4TaskData,
matrix::FSVector4,
position::PositionDelta,
};
use eldenring_util::{
ez_draw::CSEzDrawExt, singleton::get_instance, system::wait_for_system_init, task::CSTaskImpExt,
};
use nalgebra_glm as glm;
#[no_mangle]
pub unsafe extern "C" fn DllMain(_hmodule: usize, reason: u32) -> bool {
// Check if we're attaching to the game
if reason == 1 {
// Kick off new thread.
std::thread::spawn(|| {
// Wait for game (current program we're injected into) to boot up.
wait_for_system_init(&Program::current(), Duration::MAX).expect("Could not await system init.");
// Retrieve games task runner.
let cs_task = get_instance::<CSTaskImp>().unwrap().unwrap();
// Register a new task with the game to happen every frame during the gameloops
// ChrIns_PostPhysics phase because all the physics calculations have ran at this
// point.
cs_task.run_recurring(
// The registered task will be our closure.
|_: &FD4TaskData| {
// Grab the debug ez draw from RendMan if it's available. Bail otherwise.
let Some(ez_draw) = get_instance::<RendMan>()
.expect("No reflection data for RendMan")
.map(|r| r.debug_ez_draw.as_ref())
else {
return;
};
// Grab the main player from WorldChrMan if it's available. Bail otherwise.
let Some(player) = get_instance::<WorldChrMan>()
.expect("No reflection data for WorldChrMan")
.map(|w| w.main_player.as_ref())
.flatten()
else {
return;
};
// Grab physics module from player.
let physics = &player.chr_ins.module_container.physics;
// Make a directional vector that points forward following the players
// rotation.
let directional_vector = {
let forward = glm::vec3(0.0, 0.0, -1.0);
glm::quat_rotate_vec3(&physics.orientation.into(), &forward)
};
// Set color for the to-be-rendered line.
ez_draw.set_color(&FSVector4(0.0, 0.0, 1.0, 1.0));
// Draw the line from the players position to a meter in front of the player.
ez_draw.draw_line(
&physics.position,
&(physics.position
+ PositionDelta(
directional_vector.x,
directional_vector.y,
directional_vector.z,
)),
);
},
eldenring::cs::CSTaskGroupIndex::ChrIns_PostPhysics,
);
});
}
// Signal that DllMain executed successfully
true
}
Result:

Project structure (crates)
crates/eldenringContains the definitions for the elden ring structures.crates/nightreignContains the definitions for the nightreign structures.crates/utilProvides helper methods for common stuff.crates/dlrfDefines a trait and exports a macro for interacting with the games reflection system.crates/dlrf/deriveDefines the derive macro for implementing the DLRF trait on types. Do not depend on this directly since the macro is reexported througheldenring-dlrf.
Credits (aside listed contributors to this repository)
- Tremwil (for the arxan code restoration disabler, vtable-rs and a few other boilerplate-y things as well as implementing the initial FD4 singleton finder for TGA that I appropriated).
- Dasaav (for libER and heaps of engine-related structures).
- Sfix (for coming up with the FD4 singleton finder approach at all).
- Yui (for some structures as well as AOBs and hinting at some logic existing in the binary).
- Vawser (and probably many more) (for hosting the param defs used with the param struct generator).
(Have you contributed to TGA in some manner and does this repository have your work in it? Reach out to @chainfailure on Discord for proper credit disclosure).
Dependencies
~185–610KB
~15K SLoC