Docs menu · C++ layer+

    You are reading the docs of SDK 1.2.1, an older release. See the latest (1.11.0).

    Reference · SDK 1.2.1

    The C++ layer

    A header-only C++17 layer over the C interface: openrac/mod.hpp. It is compiled into your mod; the game still sees only the C table
    +About this header
    The C++ layer of the mod interface (docs/port/MODS.md, section 11): header-only, C++17, compiled into the mod and never into the port. Everything here goes through openrac_mod.h's table, which stays the boundary; no exception crosses it.
    C++
    #include "openrac/mod.hpp"
    #include "openrac/games/rac1.hpp"
    C++
    static void load(openrac::Mod& mod) {
        if (mod.game() != "rac1") throw openrac::Error("this mod is for Ratchet & Clank");
        const bool trace = mod.setting<bool>("trace");
        mod.hook<openrac::rac1::Hero_TurnToHeading>(
            [](auto original, int32_t m, float accel, float damping, float limit) {
                original(m, accel, damping, limit);   // the game's own, or a mod's loaded earlier
            });
        mod.on_frame([] { /* once a game tick */ });
    }
    OPENRAC_MOD_CPP("my-mod", "0.1.0", load)
    One library is one mod: the layer keeps one openrac::Mod per library, and each hook point's callable in a static of its own (a load takes a hook point once; a later load of the same library starts afresh).
    More An exception out of the load function becomes the mod's refusal (fail() with its message); one out of a hook or a callback is logged with the mod's id, and a hook then calls its original, so the game goes on (a hook that threw after calling the original has it called twice: do not throw there).

    openrac::Error

    What load and the layer throw: its message is the mod's refusal, or the log's line.

    openrac::Memory

    Game memory: typed reads and writes at game addresses. Reads and writes copy (any alignment); ref() gives an lvalue where the address is aligned for T.

    read()

    Declaration
    template <class T> T read(gaddr address) const;

    write()

    Declaration
    template <class T> void write(gaddr address, const T& value) const;

    ref()

    Declaration
    template <class T> T& ref(gaddr address) const;

    pointer()

    Declaration
    void* pointer(gaddr address) const;

    base()

    Declaration
    std::uint8_t* base() const;

    openrac::Input

    The keyboard and mouse for the tick about to run (interface 1.2, openrac_input): a view of the port's state, renewed each tick.

    raw()

    Declaration
    const openrac_input& raw() const;

    held()

    Declaration
    bool held(int bind) const;
    A bind (a key's HID usage, OPENRAC_BIND_*): held now; went down since the last tick.

    pressed()

    Declaration
    bool pressed(int bind) const;

    tick()

    Declaration
    std::uint32_t tick() const;

    openrac::Original

    C++
    template <class R, class... A>

    R()

    Declaration
    using fn = R (*)(A...);

    get()

    Declaration
    fn get() const;

    openrac::Mod

    The mod as the port loaded it: the table, the handle, and what the mod takes of the game.

    api()

    Declaration
    const openrac_api& api() const;

    handle()

    Declaration
    openrac_mod* handle() const;

    game()

    Declaration
    std::string_view game() const;
    +Examples (2)
    From the guide “Native mods in C++”
    static void load(openrac::Mod& mod) {
        if (mod.game() != "rac1") throw openrac::Error("this mod is for Ratchet & Clank");
    From sdk/template/src/mod.cpp
    void load(openrac::Mod& mod) {
        if (mod.game() != "rac1") {
            throw openrac::Error("this mod is for Ratchet & Clank");
        }
        const bool extra = mod.setting<bool>("enabled_extra");

    version()

    Declaration
    std::string_view version() const;

    platform()

    Declaration
    std::string_view platform() const;

    api_major()

    Declaration
    unsigned api_major() const;
    The port's interface version: at least what the mod was built for, else it is not loaded.

    log()

    Declaration
    void log(LogLevel level, const std::string& text) const;

    debug()

    Declaration
    void debug(const std::string& text) const;

    info()

    Declaration
    void info(const std::string& text) const;
    +Examples (2)
    From the guide “Native mods in C++”
    mod.hook<openrac::rac1::Hero_TurnToHeading>(
        [trace, &mod](auto original, int32_t m, float accel, float damping, float limit) {
            if (trace) mod.info("turning");
            original(m, accel, damping, limit);
        });
    From sdk/template/src/mod.cpp
        mod.info(extra ? "loaded, with the extra" : "loaded");
    }

    warn()

    Declaration
    void warn(const std::string& text) const;

    error()

    Declaration
    void error(const std::string& text) const;

    fail()

    Declaration
    void fail(const std::string& reason) const;
    During load: why the mod refuses (throwing an openrac::Error from load does the same).

    setting()

    Declaration
    template <class T> T setting(const char* key) const;
    A setting of the manifest's, as T: bool for "bool"; an integer type for "int"; float or double for "float"; std::string for "choice" and "string".
    +Examples (2)
    From the guide “Native mods in C++”
    const bool trace = mod.setting<bool>("trace");
    From sdk/template/src/mod.cpp
    void load(openrac::Mod& mod) {
        if (mod.game() != "rac1") {
            throw openrac::Error("this mod is for Ratchet & Clank");
        }
        const bool extra = mod.setting<bool>("enabled_extra");

    hook()

    Declaration
    template <class HookPoint, class F> void hook(F&& callable);
    Takes the hook point (a type of openrac/games/<game>.hpp) for callable, called as callable(original, args...). Throws openrac::Error when the port has no such hook point, a different signature, or the mod already took it. Only during load.
    +Examples (2)
    From the guide “Native mods in C++”
    mod.hook<openrac::rac1::Hero_TurnToHeading>(
        [trace, &mod](auto original, int32_t m, float accel, float damping, float limit) {
            if (trace) mod.info("turning");
            original(m, accel, damping, limit);
        });
    From sdk/template/src/mod.cpp
    // A hook: the lambda gets the way on (the game's function, or a mod's loaded earlier) first,
    // then the hook point's arguments. An exception thrown here is logged, and the original runs.
    mod.hook<openrac::rac1::Hero_SetPlanarVelocity>([](auto original, float angle) {
        // ... before the game's own ...
        original(angle);
        // ... after it ...
    });

    original()

    Declaration
    template <class HookPoint> typename HookPoint::fn original() const;
    What a hook point this mod took goes on to (as the callable's original), for calling it from elsewhere in the mod (another hook, a callback); nullptr before the hook is taken.

    on_frame()

    Declaration
    template <class F> void on_frame(F&& callable);
    callable() after each game tick, in load order. Only during load.
    +Examples (2)
    From the guide “Native mods in C++”
        mod.on_frame([] { /* after each game tick */ });
    }
    From sdk/template/src/mod.cpp
    // Once a game tick: read or change game memory through mod.memory().
    mod.on_frame([] {});

    on_pad()

    Declaration
    template <class F> void on_pad(F&& callable);
    callable(port, report, size) for each pad report, before the game reads it. Only during load.

    function()

    Declaration
    template <class Fn> Fn function(const char* name) const;
    A game function by its name in this disc's build, as Fn (a function pointer type); nullptr when there is none. required_function throws instead.

    required_function()

    Declaration
    template <class Fn> Fn required_function(const char* name) const;

    function_at()

    Declaration
    template <class Fn> Fn function_at(gaddr address) const;
    The function at a code address of the level loaded now, as Fn; nullptr when there is none.

    has_input()

    Declaration
    bool has_input() const;
    Interface 1.2: the keyboard and mouse. has_input() says whether the port offers them (a mod built for 1.2 is loaded only by a port that does).

    input()

    Declaration
    Input input() const;
    The state for the tick about to run.

    take_input()

    Declaration
    void take_input(std::uint32_t devices);
    Takes the keyboard (OPENRAC_INPUT_KEYBOARD) and or the mouse from the port's own use of them in play: the mod presses pad 0's buttons through on_pad. Only during load.

    capture_mouse()

    Declaration
    void capture_mouse(bool capture) const;
    Asks for the cursor captured (hidden, motion relative) or let go; any time.

    memory()

    Declaration
    Memory memory() const;
    +Example (1)
    From sdk/template/src/mod.cpp
    // Once a game tick: read or change game memory through mod.memory().
    mod.on_frame([] {});

    relocate()

    Declaration
    gaddr relocate(gaddr address) const;

    relocate_level()

    Declaration
    gaddr relocate_level(int level, gaddr address) const;

    openrac::StackFrame

    Room on the game's stack for a call that takes the address of a local, given back when it goes.

    Macros

    OPENRAC_MOD_CPP(mod_id, mod_version, load_fn)

    The two entry points of a C++ mod: openrac_mod_query (the id and version, as its manifest's) and openrac_mod_load, which calls load_fn(openrac::Mod&). A throw out of load_fn refuses the load with its message.
    +Example (1)
    From the guide “Native mods in C++”
    OPENRAC_MOD_CPP("my-mod", "0.1.0", load)

    Generated from sdk/include/openrac/mod.hpp at sdk-v1.2.1. Edit this page or report a problem.