Docs menu · C++ layer+

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

    Reference · SDK 1.5.0

    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):
    More 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. The header is laid out as: the includes, the error and log types, game memory, binds and the input state, the hook machinery (detail), the Mod itself, the stack frame, and last the macro that writes a mod's entry points. Each item says which interface version added it; the layer itself needs only the table of the interface the mod was built for.
    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

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

    openrac::Memory

    Since 1.0
    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. A view: it owns nothing, and the memory it views lasts for the life of the program.

    Memory (constructor)

    Declaration
    explicit Memory(std::uint8_t* base);
    Views the memory that begins at base (openrac_api.memory).

    read()

    Declaration
    template <class T> T read(gaddr address) const;
    Returns the T at address, copied out; T is a plain value (trivially copyable).

    write()

    Declaration
    template <class T> void write(gaddr address, const T& value) const;
    Copies value to address; T is a plain value (trivially copyable). It does not mark anything the game caches: a value the game keeps elsewhere is the mod's to update.

    ref()

    Declaration
    template <class T> T& ref(gaddr address) const;
    Returns the T at address as an lvalue. The address must be aligned for T, and the reference must not be kept across a level load (the level's program moves its globals).

    pointer()

    Declaration
    void* pointer(gaddr address) const;
    Returns the host pointer to address.

    base()

    Declaration
    std::uint8_t* base() const;
    Returns the host pointer to game address 0.

    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. Cheap to copy; do not keep it past the tick it was read in.

    Input (constructor)

    Declaration
    explicit Input(const openrac_input* state);
    Views the port's state (openrac_api.input()'s result).

    raw()

    Declaration
    const openrac_input& raw() const;
    Returns the C state, for what the accessors do not cover.

    held()

    Declaration
    bool held(int bind) const;
    Returns whether a bind (a key's HID usage, OPENRAC_BIND_*) is held now.

    pressed()

    Declaration
    bool pressed(int bind) const;
    Returns whether a bind went down since the last tick.

    mouse_dx()

    Declaration
    float mouse_dx() const;
    Return the mouse's motion since the last tick, in the system's pixels (raw while captured).

    wheel_x()

    Declaration
    float wheel_x() const;
    Return the wheel's turn since the last tick, in notches (x > 0 right, y > 0 up).

    focused()

    Declaration
    bool focused() const;
    Return whether the game's window has the keyboard, whether the cursor is captured, and whether the port's own overlay has the input now (leave it alone then).

    tick()

    Declaration
    std::uint32_t tick() const;
    Returns the tick counter: a new value is a new state.

    has_pointer()

    Since 1.3
    Declaration
    bool has_pointer() const;
    Since 1.3: returns whether the port's state reaches the pointer fields. False on a 1.2 port, whose pointer_x(), pointer_y() and pointer_inside() then give 0, 0 and false.

    pointer_x()

    Since 1.3
    Declaration
    float pointer_x() const;
    Since 1.3: return where the cursor is over the game's picture, 0..1 across and down (pointer_x() * 512, pointer_y() * 416 is the game's 2D pixel), and whether it is over it.

    openrac::MenuFrame

    New 1.5
    What a menu page's callback is given each frame (openrac_menu_frame): pad 0's buttons, by the OPENRAC_PAD_* bits. A view of the port's state, valid during the call.

    MenuFrame (constructor)

    Declaration
    explicit MenuFrame(const openrac_menu_frame& frame);
    Wraps the port's state frame.

    held()

    Declaration
    bool held(std::uint32_t buttons) const;
    Return whether any of buttons is down now, or went down since the last frame.

    pressed()

    Declaration
    bool pressed(std::uint32_t buttons) const;

    opened()

    Declaration
    bool opened() const;
    Returns whether this is the first frame since the page opened.

    raw()

    Declaration
    const openrac_menu_frame& raw() const;
    Returns the port's state as it is.

    openrac::MenuPage

    New 1.5
    Draws a mod's menu page during its callback: rectangles and text on a page of OPENRAC_MENU_WIDTH by OPENRAC_MENU_HEIGHT pixels, which starts each frame black.

    MenuPage (constructor)

    Declaration
    MenuPage(const openrac_api* api, openrac_mod* handle);
    Draws through api for the mod handle.

    rect()

    Declaration
    void rect(int x, int y, int w, int h, std::uint32_t rgba) const;
    Fills w by h pixels from (x, y), the top left, with rgba (OPENRAC_RGBA), blended.

    text()

    Declaration
    void text(int x, int y, int size, std::uint32_t rgba, const std::string& text) const;
    Writes text (ASCII) from (x, y), its top left, at size (1 to 8) in rgba.

    text_centred()

    Declaration
    void text_centred(int y, int size, std::uint32_t rgba, const std::string& text) const;
    Writes text centred across the page, its top at y.

    text_width()

    Declaration
    static int text_width(std::string_view text, int size);
    Returns how wide text is at size, in pixels: its longest line's characters, without the last one's spacing column.

    openrac::Original

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

    R()

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

    Original (constructor)

    Declaration
    explicit Original(fn f);
    Wraps the function f that the replacement goes on to.

    operator()()

    Declaration
    R operator()(A... args) const;
    Calls the original with args, as the game would have called the hook point.

    get()

    Declaration
    fn get() const;
    Returns the original as a plain function pointer.

    openrac::Mod

    Since 1.0
    ---------------------------------------------------------------------------------------------- The mod ---------------------------------------------------------------------------------------------- The mod as the port loaded it:
    More the table, the handle, and what the mod takes of the game. One per library, made by OPENRAC_MOD_CPP at load; the game's thread is the only one that uses it. Not copyable: the port holds pointers into the callbacks it keeps.

    Mod (constructor)

    Declaration
    Mod(const openrac_api* api, openrac_mod* handle);
    Wraps the port's table and this mod's handle, as openrac_mod_load received them.

    api()

    Declaration
    const openrac_api& api() const;
    Returns the C table, for what the layer does not wrap.

    handle()

    Declaration
    openrac_mod* handle() const;
    Returns the port's handle for this mod, the first argument of the table's own functions.

    game()

    Declaration
    std::string_view game() const;
    Return where the mod runs: the game's id ("rac1"), the disc's version ("pal", "ntsc"), the platform ("macos-arm64", ...) and OpenRAC's version. Valid for the life of the program.
    +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) {
        // Refuse here rather than misbehave later: a mod written for one game reads its memory and
        // takes its hook points, which another game does not have.
        if (mod.game() != "rac1") {
            throw openrac::Error("this mod is for Ratchet & Clank");
        }

    version()

    Declaration
    std::string_view version() const;

    platform()

    Declaration
    std::string_view platform() const;

    api_major()

    Declaration
    unsigned api_major() const;
    Return the port's interface version: at least what the mod was built for, else it is not loaded. Check api_minor() before using anything newer than the minor the mod was built for.

    log()

    Declaration
    void log(LogLevel level, const std::string& text) const;
    Writes text to the session's log at level, after the mod's id.

    debug()

    Declaration
    void debug(const std::string& text) const;
    Write text to the log at the level the name says.

    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;
    Says why the mod refuses to load, for status.json and the launcher. Only during load; throwing an openrac::Error from load does the same.

    setting()

    Declaration
    template <class T> T setting(const char* key) const;
    Returns 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". A key the manifest does not declare, or of another type, gives 0, 0.0, false or "".
    +Examples (2)
    From the guide “Native mods in C++”
    const bool trace = mod.setting<bool>("trace");
    From sdk/template/src/mod.cpp
    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;
    Returns 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);
    Calls callable() after each game tick, in load order. Throws openrac::Error when refused. 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);
    Calls callable(port, report, size) for each pad report, before the game reads it: the callable may change the report's bytes. Throws openrac::Error when refused. Only during load.

    function()

    Declaration
    template <class Fn> Fn function(const char* name) const;
    Returns 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 openrac::Error 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;
    Returns the function at a code address of the level loaded now, as Fn; nullptr when there is none.

    has_input()

    Since 1.2
    Declaration
    bool has_input() const;
    Since 1.2: returns whether the port offers the keyboard and mouse (input(), take_input(), capture_mouse()): a mod built for 1.2 is loaded only by a port that does, so a mod that wants to run on 1.1 checks this first.

    input()

    Since 1.2
    Declaration
    Input input() const;
    Since 1.2: returns the keyboard and mouse for the tick about to run.

    take_input()

    Since 1.2
    Declaration
    void take_input(std::uint32_t devices);
    Since 1.2: 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. Throws openrac::Error when refused. Only during load.

    capture_mouse()

    Since 1.2
    Declaration
    void capture_mouse(bool capture) const;
    Since 1.2: asks for the cursor captured (hidden, motion relative) or let go. The port may let it go anyway (window not focused, overlay open). Any time.

    has_views()

    Since 1.4
    Declaration
    bool has_views() const;
    Since 1.4: returns whether the port offers the graphics context, views and the Vulkan device (graphics(), on_views(), setup_vulkan()): a mod that wants to run on 1.3 checks this first.

    graphics()

    Since 1.4
    Declaration
    const openrac_graphics &graphics() const;
    Since 1.4: returns what the port draws with (openrac_graphics); its backend is OPENRAC_GRAPHICS_NONE before the window opens.

    on_views()

    Since 1.4
    Declaration
    void on_views(const openrac_view_source &source);
    Since 1.4: has the port draw the views source asks for each frame (openrac_view_source, sdk/docs/views.md). Throws openrac::Error when refused. Only during load.

    setup_vulkan()

    Since 1.4
    Declaration
    void setup_vulkan(const openrac_vulkan_setup &setup);
    Since 1.4: has the port make its Vulkan device through setup (openrac_vulkan_setup); the manifest says "vulkan_device": true. Throws openrac::Error when refused. Only during load.

    has_menu()

    New 1.5
    Declaration
    bool has_menu() const;
    Since 1.5: returns whether the port offers menu entries and pages (menu_entry()): a mod that wants to run on 1.4 checks this first.

    menu_entry()

    New 1.5
    Declaration
    template <class F> void menu_entry(const char* label, F&& callable);
    Since 1.5: adds an entry named label to the game's front-end menu that opens a page drawn by callable(page, frame) each frame, which returns true to close it (MenuCallable). Throws openrac::Error when refused. Only during load.

    memory()

    Declaration
    Memory memory() const;
    Returns a view of game memory.
    +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;
    Return a global's address for the code loaded now: the executable's (relocate) or level level's program's (relocate_level). Ask each time, because a level moves its globals.

    relocate_level()

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

    loaded_level()

    Declaration
    int loaded_level() const;
    Returns the level whose program is loaded, -1 for none (the executable's).

    openrac::StackFrame

    Since 1.0
    Room on the game's stack for a call that takes the address of a local, given back when it goes. Not copyable; frames nest and must end innermost first, which scopes do.

    StackFrame (constructor)

    Declaration
    StackFrame(const Mod& mod, std::uint32_t size);
    Pushes size bytes (aligned to 16) on the game's stack through mod's table.

    ~StackFrame()

    Declaration
    ~StackFrame();
    Pops what the constructor pushed.

    address()

    Declaration
    gaddr address() const;
    Returns the game address of the room.

    Macros

    OPENRAC_MOD_CPP(mod_id, mod_version, load_fn)

    Since 1.0
    Writes 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. mod_id and mod_version are string literals.
    +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.5.0. Edit this page or report a problem.