Firelink is a C++ project for building DLLs that hook into running Windows applications and provide pointer and memory manipulation features (like Cheat Engine). This project is intended for educational or modding purposes and should not be used to cheat in online games or other malicious activities.
Of course, the real value of Firelink is the BaseHook subclasses that target FromSoftware games. Currently, only
Dark Souls: Remastered (FirelinkDSR) and Elden Ring (FirelinkER) are supported. These hook subclasses,
like similar projects by @JKAnderson (TKGP) and myself in C# and Python, automatically expose known valuable memory
addresses in the running game application (a la Cheat Engine). You can create a simple native DLL that creates a hook
when the DLL is loaded by searching for the game process, or by assuming that the DLL is being loaded into the game
process as a plugin (e.g. via dinput8.dll sideloading).
- FirelinkCore: Core utilities and memory manipulation functions, centered around
ManagedProcess. - FirelinkDSR: Extensions and hooks specific to Dark Souls: Remastered, centered around
DSRHook. - FirelinkER: Extensions and hooks specific to Elden Ring, centered around
ERHook.- Bonus: includes a complete C++ implementation of the
MSBformat, which e.g. reads Stormveil Castle in ~100 ms.
- Bonus: includes a complete C++ implementation of the
These libraries are Windows only (64-bit), as they are currently only designed to support (64-bit) FromSoftware games on Steam. Linux (and Steam Deck) support may come in the (very distant) future.
Before building the project, ensure you have the following tools installed:
- CMake: Version 3.20 or higher.
- Ninja (optional): For faster builds.
- MinGW (for GCC/Clang on Windows) or Visual Studio Build Tools.
- Git: For cloning the repository.
Follow these steps to build the project:
git clone https://github.com/Grimrukh/Firelink.git
cd Firelinkor via SSH:
git clone git@github.com/Grimrukh/Firelink.git
cd FirelinkUsing Ninja:
cmake -S . -B build -G "Ninja" -DCMAKE_BUILD_TYPE=ReleaseOr using your installed version of Visual Studio (e.g. 2022):
cmake -S . -B build -G "Visual Studio 17 2022" -A x64cmake --build build --config ReleaseIf your project includes tests, you can run them using ctest. First, ensure that tests are enabled in the CMake configuration:
cmake -S . -B build -G "Ninja" -DENABLE_TESTING=ONThen build and run the tests:
cmake --build build --config Release
ctest --test-dir build --output-on-failureOnce built, the DLLs will be located in the build directory. To use them, copy them to the directory of your own C++
application that links against FirelinkCore (and optionally FirelinkDSR) and use the public include headers to
gain access to classes such as Firelink::BaseHook and FirelinkDSR::DSRHook.
Here's a simple example loop that prints the player's health in Dark Souls: Remastered. See other projects, such as DSREquipmentSwap, for more complex examples.
#include <FirelinkDSRHook/DSRHook.h>
#include <atomic>
#include <format>
#include <iostream>
#include <thread>
void PrintHealthEverySecond()
{
using namespace Firelink;
using namespace FirelinkDSR;
// We need an atomic flag to pass to `WaitForProcess` to stop the search if needed.
// It's not used in this example, but the caller could pass it in and set it to `true` in another thread to
// stop the search or our main loop below.
std::atomic<bool> stopFlag = false;
// Do initial DSR process search. We are the sole owner of the found `ManagedProcess`.
auto newProcess = ManagedProcess::WaitForProcess(
DSR_PROCESS_NAME,
10000, // 10 second timeout
500, // 500 ms search interval (enumerating all Windows processes is expensive)
stopFlag);
// Check if we found the process (as opposed to timing out).
if (!newProcess)
{
std::cout << "WARNING: Failed to find DSR process.\n";
return;
}
// We create a `DSRHook` and transfer ownership of the `ManagedProcess` to it.
auto dsrHook = std::make_unique<DSRHook>(std::move(newProcess));
// Main loop. We can reuse the same atomic stop flag.
while (!stopFlag.load())
{
// Get the player's current and max health.
std::pair<int, int> currentAndMaxHealth = dsrHook->GetPlayerHp();
// Print health.
std::string msg = std::format("Player health: {} / {}\n", currentAndMaxHealth.first, currentAndMaxHealth.second);
std::cout << msg;
// Sleep for a second.
std::this_thread::sleep_for(std::chrono::milliseconds(1000));
}
// Exited loop.
std::cout << "Stopped printing player health.\n";
}The project includes a GitHub Actions workflow to automatically build and test the project on every commit. The MSB file for Stormveil Castle in Elden Ring is included for testing the MSB format.
- Pushes to the
mainbranch. - Pull requests targeting
main.
You can view the CI status in the Actions tab of the GitHub repository.
This project is licensed under the MIT License. See the LICENSE file for details.
Contributions are welcome! To contribute:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Submit a pull request with a detailed description of your changes.
If you encounter any issues, please open an issue on the GitHub repository.
Happy hooking!