Docs menu · C interface+

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

    Reference · SDK 1.2.0

    The C interface

    Everything the port hands a native mod: openrac_mod.h. A mod is built against this header alone. Each item says which interface version added it; check api->api_minor before you use something newer than your manifest's api

    The interface

    NameValueWhat it is
    OPENRAC_MOD_API_MAJOR1
    OPENRAC_MOD_API_MINOR2 1.2: the keyboard and mouse (input, take_input, capture_mouse)
    OPENRAC_MOD_TARGET_MINOROPENRAC_MOD_API_MINOR The interface a mod is built for, what its openrac_mod_query reports:
    More its manifest's "api" minor, which the SDK's openrac_add_mod passes in, else this header's. A mod for 1.1 built with a newer SDK thus still loads on a port of 1.1 (and uses nothing newer without checking api->api_minor).
    OPENRAC_MOD_EXPORT__declspec(dllexport) or __attribute__((visibility("default")))

    openrac_gaddr

    Type
    Declaration
    typedef uint32_t openrac_gaddr;
    A game address: an offset into game memory (the console's address).
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
    static void pad_process_report(openrac_gaddr pad, openrac_gaddr report, int32_t size) {
        ++s_reports;
        s_pad_original(pad, report, size);
    }

    openrac_mod

    Type
    Declaration
    typedef struct openrac_mod openrac_mod;
    The port's handle for one loaded mod, passed back to the functions that are the mod's own (its log lines, its settings, its hooks).
    +Examples (2)
    From the guide “Native mods in C”
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    
    OPENRAC_MOD_DEFINE("my-mod", "0.1.0")   /* openrac_mod_query: the interface version, the id */
    
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "this mod is for Ratchet & Clank");
            return 1;                          /* not loaded; the reason is shown */
        }
        api->log(mod, OPENRAC_LOG_INFO, "hello");
        return 0;                              /* loaded */
    }
    From sdk/examples/frame-counter/src/frame_counter.c
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    NameValueWhat it is
    OPENRAC_LOG_DEBUG0 Log levels for openrac_api.log.
    OPENRAC_LOG_INFO1
    OPENRAC_LOG_WARN2
    OPENRAC_LOG_ERROR3
    OPENRAC_HOOK_OK0 openrac_api.hook's results.
    OPENRAC_HOOK_UNKNOWN(-1) this port has no hook point of that name (on this disc)
    OPENRAC_HOOK_SIGNATURE(-2) the hook point's signature is another
    OPENRAC_HOOK_TOO_LATE(-3) hooks are taken in openrac_mod_load only

    struct openrac_mod_info

    What openrac_mod_query tells the port before it loads the mod.
    MemberWhat it is
    uint32_t sizesizeof(openrac_mod_info), set by the port
    uint32_t api_majorOPENRAC_MOD_API_MAJOR as the mod was built
    uint32_t api_minorOPENRAC_MOD_API_MINOR as the mod was built
    const char* idthe manifest's id: the port checks they agree
    const char* versionthe mod's version, as its manifest's
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
        if (OPENRAC_RAC1_HOOK(api, mod, Pad_ProcessReport, pad_process_report, &s_pad_original) != OPENRAC_HOOK_OK) {
            api->fail(mod, "this OpenRAC has no Pad_ProcessReport hook point");
            return 1;
        }
        api->on_frame(mod, on_frame, NULL);
        char line[96];
        snprintf(line, sizeof line, "counting on %s/%s, a line every %lld ticks", api->game, api->version,
                 (long long)s_every);
        api->log(mod, OPENRAC_LOG_INFO, line);
        return 0;
    }
    NameValueWhat it is
    OPENRAC_KEY_COUNT512 1.2: the keyboard and mouse. A key is its USB HID usage, the same on every layout and system (openrac/keys.h names them: "KeyW", "Space", "ShiftLeft").
    OPENRAC_KEY_HELD1u openrac_input.keys[k]: the key is down
    OPENRAC_KEY_PRESSED2u it went down since the last tick (a tap shorter than a tick too)
    OPENRAC_MOUSE_LEFT1u openrac_input.mouse_held and mouse_pressed's bits.
    OPENRAC_MOUSE_MIDDLE2u
    OPENRAC_MOUSE_RIGHT4u
    OPENRAC_MOUSE_BACK8u the side button nearer the wrist (X1)
    OPENRAC_MOUSE_FORWARD16u the other side button (X2)
    OPENRAC_INPUT_KEYBOARD1u the port's own keyboard table stops driving pad 0
    OPENRAC_INPUT_MOUSE2u the mod uses the mouse in play (reserved: the port has no mouse use of its own in play)

    struct openrac_input

    The keyboard and mouse as the port read them for the tick about to run: taken once a tick, after the window's events and before the game reads its pads (so before the tick's pad reports).
    MemberWhat it is
    uint32_t sizesizeof(openrac_input) as the port was built: a newer port's is larger
    uint32_t tickcounts the ticks: a new value, a new state
    uint8_t keys[OPENRAC_KEY_COUNT]by HID usage: OPENRAC_KEY_HELD | OPENRAC_KEY_PRESSED
    uint32_t mouse_heldOPENRAC_MOUSE_* down now
    uint32_t mouse_pressedOPENRAC_MOUSE_* that went down since the last tick
    float mouse_dxthe mouse's motion since the last tick, in the system's pixels;
    float mouse_dyraw (no pointer acceleration) while captured; y grows downward
    float wheel_xthe wheel since the last tick, in notches: x > 0 to the right,
    float wheel_yy > 0 away from the player (up), whatever the system's scroll direction
    uint8_t focusedthe game's window has the keyboard; while not, nothing is held
    uint8_t capturedthe cursor is captured: hidden, kept in the window, motion relative
    uint8_t overlaythe port's own overlay or menu has the input now (F3): leave it
    uint8_t reserved(as above)
    +Example (1)
    From the guide “Native mods in C”
    static void pad(void* user, int port, uint8_t* report, int size) {
        const openrac_input* in = s_api->input();      /* this tick's keys and mouse */
        if (port == 0 && openrac_bind_held(in, s_jump)) {
            report[1] &= (uint8_t)~0x40;               /* Cross held (bit 14: a clear bit is held) */
        }
        /* in->mouse_dx, mouse_dy: the motion since the last tick; wheel_x, wheel_y in notches */
    }

    openrac_frame_fn

    Callback type
    Declaration
    typedef void (*openrac_frame_fn)(void* user);

    openrac_pad_fn

    Callback type
    Declaration
    typedef void (*openrac_pad_fn)(void* user, int port, uint8_t* report, int size);
    A pad report as the console's pad library hands it to the game (its bytes, size of them), which the callback may change before the game reads it. port is the controller's port, 0 or 1.
    What the port offers a mod. Filled by the port; valid for the life of the program.

    game

    Value
    Field
    const char* game;
    "rac1": the game's id (games/<game>/game.json)
    +Examples (2)
    From the guide “Native mods in C”
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    
    OPENRAC_MOD_DEFINE("my-mod", "0.1.0")   /* openrac_mod_query: the interface version, the id */
    
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "this mod is for Ratchet & Clank");
            return 1;                          /* not loaded; the reason is shown */
        }
        api->log(mod, OPENRAC_LOG_INFO, "hello");
        return 0;                              /* loaded */
    }
    From sdk/examples/frame-counter/src/frame_counter.c
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        s_api = api;
        s_mod = mod;
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "frame-counter is for Ratchet & Clank (rac1)");
            return 1;
        }
        s_every = api->setting_int(mod, "every");
        if (s_every <= 0) {
            s_every = 600;

    version

    Value
    Field
    const char* version;
    "pal", "ntsc": the disc's version
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
        if (OPENRAC_RAC1_HOOK(api, mod, Pad_ProcessReport, pad_process_report, &s_pad_original) != OPENRAC_HOOK_OK) {
            api->fail(mod, "this OpenRAC has no Pad_ProcessReport hook point");
            return 1;
        }
        api->on_frame(mod, on_frame, NULL);
        char line[96];
        snprintf(line, sizeof line, "counting on %s/%s, a line every %lld ticks", api->game, api->version,
                 (long long)s_every);
        api->log(mod, OPENRAC_LOG_INFO, line);
        return 0;
    }

    openrac_version

    Value
    Field
    const char* openrac_version;
    OpenRAC's version, "0.9.0"

    platform

    Value
    Field
    const char* platform;
    "macos-arm64", "linux-x86_64", "windows-x86_64", ...

    memory

    Value
    Field
    uint8_t* memory;
    The base of game memory: game address a is memory + a. Fixed for the life of the program.
    +Example (1)
    From sdk/template/src/mod.cpp
    // Once a game tick: read or change game memory through mod.memory().
    mod.on_frame([] {});

    log()

    Signature
    void log(openrac_mod* mod, int level, const char* text);
    
    // how a call looks
    api->log(mod, level, text);
    A line in the session's log, after the mod's id.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • level (int)
    • text (const char*)
    +Examples (2)
    From the guide “Native mods in C”
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    
    OPENRAC_MOD_DEFINE("my-mod", "0.1.0")   /* openrac_mod_query: the interface version, the id */
    
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "this mod is for Ratchet & Clank");
            return 1;                          /* not loaded; the reason is shown */
        }
        api->log(mod, OPENRAC_LOG_INFO, "hello");
        return 0;                              /* loaded */
    }
    From sdk/examples/frame-counter/src/frame_counter.c
        if (++s_ticks % (uint64_t)s_every != 0) {
            return;
        }
        char line[128];
        snprintf(line, sizeof line, "%llu ticks, %llu pad reports, level %d", (unsigned long long)s_ticks,
                 (unsigned long long)s_reports, s_api->loaded_level());
        s_api->log(s_mod, s_verbose ? OPENRAC_LOG_INFO : OPENRAC_LOG_DEBUG, line);
    }

    fail()

    Signature
    void fail(openrac_mod* mod, const char* reason);
    
    // how a call looks
    api->fail(mod, reason);
    During openrac_mod_load: why the mod refuses to load (status.json and the launcher show it).

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • reason (const char*)
    +Examples (2)
    From the guide “Native mods in C”
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    
    OPENRAC_MOD_DEFINE("my-mod", "0.1.0")   /* openrac_mod_query: the interface version, the id */
    
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "this mod is for Ratchet & Clank");
            return 1;                          /* not loaded; the reason is shown */
        }
        api->log(mod, OPENRAC_LOG_INFO, "hello");
        return 0;                              /* loaded */
    }
    From the guide “Native mods in C”
    static openrac_rac1_Hero_SetPlanarVelocity s_original;
    
    static void my_velocity(float angle) {
        s_original(angle);   /* the game's own, or the mod before yours */
    }
    
    /* in openrac_mod_load: */
    if (OPENRAC_RAC1_HOOK(api, mod, Hero_SetPlanarVelocity, my_velocity, &s_original) != OPENRAC_HOOK_OK) {
        api->fail(mod, "no Hero_SetPlanarVelocity in this OpenRAC");
        return 1;
    }

    setting_bool(), setting_int(), setting_float(), setting_string()

    Signature
    int setting_bool(openrac_mod* mod, const char* key);
    int64_t setting_int(openrac_mod* mod, const char* key);
    double setting_float(openrac_mod* mod, const char* key);
    const char* setting_string(openrac_mod* mod, const char* key);
    The mod's settings (its manifest's "settings"; the values the launcher wrote). A key the manifest does not declare, or of another type, gives 0, 0.0 or "". The string stays valid.
    +Examples (2)
    From sdk/examples/frame-counter/src/frame_counter.c
        return 1;
    }
    s_every = api->setting_int(mod, "every");
    if (s_every <= 0) {
        s_every = 600;
    }
    s_verbose = api->setting_bool(mod, "verbose");
    if (OPENRAC_RAC1_HOOK(api, mod, Pad_ProcessReport, pad_process_report, &s_pad_original) != OPENRAC_HOOK_OK) {
        api->fail(mod, "this OpenRAC has no Pad_ProcessReport hook point");
        return 1;
    }
    api->on_frame(mod, on_frame, NULL);
    char line[96];
    From sdk/examples/frame-counter/src/frame_counter.c
    s_api = api;
    s_mod = mod;
    if (strcmp(api->game, "rac1") != 0) {
        api->fail(mod, "frame-counter is for Ratchet & Clank (rac1)");
        return 1;
    }
    s_every = api->setting_int(mod, "every");
    if (s_every <= 0) {
        s_every = 600;
    }
    s_verbose = api->setting_bool(mod, "verbose");
    if (OPENRAC_RAC1_HOOK(api, mod, Pad_ProcessReport, pad_process_report, &s_pad_original) != OPENRAC_HOOK_OK) {
        api->fail(mod, "this OpenRAC has no Pad_ProcessReport hook point");

    hook()

    Only while loading
    Signature
    int hook(
        openrac_mod* mod,
        const char* name,
        const char* signature,
        void* replacement,
        void** original
    );
    
    // how a call looks
    int result = api->hook(mod, name, signature, replacement, original);
    Takes the hook point name (games/<game>.h: its name and signature) for replacement, a function of the hook point's signature. *original is set to what the replacement goes on to: the game's own function, or the replacement of a mod loaded earlier. So the mod loaded last runs first. Only during openrac_mod_load.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • name (const char*)
    • signature (const char*)
    • replacement (void*)
    • original (void**)

    Returns

    int
    +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 ...
    });

    on_frame()

    Only while loading
    Signature
    int on_frame(openrac_mod* mod, openrac_frame_fn fn, void* user);
    
    // how a call looks
    int result = api->on_frame(mod, fn, user);
    fn(user) after each game tick, in load order. Only during openrac_mod_load.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • fn (openrac_frame_fn)
    • user (void*)

    Returns

    int
    +Examples (2)
    From the guide “Native mods in C”
    static void tick(void* user) { /* after each game tick */ }
    static void pad(void* user, int port, uint8_t* report, int size) { /* change report[] */ }
    
    api->on_frame(mod, tick, NULL);
    api->on_pad(mod, pad, NULL);
    From sdk/examples/frame-counter/src/frame_counter.c
        }
        s_verbose = api->setting_bool(mod, "verbose");
        if (OPENRAC_RAC1_HOOK(api, mod, Pad_ProcessReport, pad_process_report, &s_pad_original) != OPENRAC_HOOK_OK) {
            api->fail(mod, "this OpenRAC has no Pad_ProcessReport hook point");
            return 1;
        }
        api->on_frame(mod, on_frame, NULL);
        char line[96];
        snprintf(line, sizeof line, "counting on %s/%s, a line every %lld ticks", api->game, api->version,
                 (long long)s_every);
        api->log(mod, OPENRAC_LOG_INFO, line);
        return 0;
    }

    on_pad()

    Only while loading
    Signature
    int on_pad(openrac_mod* mod, openrac_pad_fn fn, void* user);
    
    // how a call looks
    int result = api->on_pad(mod, fn, user);
    fn(user, port, report, size) for each pad report, before the game reads it, in load order. Only during openrac_mod_load.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • fn (openrac_pad_fn)
    • user (void*)

    Returns

    int
    +Example (1)
    From the guide “Native mods in C”
    static void tick(void* user) { /* after each game tick */ }
    static void pad(void* user, int port, uint8_t* report, int size) { /* change report[] */ }
    
    api->on_frame(mod, tick, NULL);
    api->on_pad(mod, pad, NULL);

    function()

    Signature
    void* function(const char* name);
    
    // how a call looks
    void* result = api->function(name);
    A game function by its name in this disc's build ("func_001F9F90" on PAL, "FUN_001f9dc8" on NTSC-U), as a host function to call with its signature; null when there is none.

    Parameters

    • name (const char*)

    Returns

    void*

    function_at()

    Signature
    void* function_at(openrac_gaddr address);
    
    // how a call looks
    void* result = api->function_at(address);
    The function at a code address, in the level loaded now (a function pointer the game keeps); null when there is none.

    Parameters

    • address (openrac_gaddr)

    Returns

    void*

    relocate_data(), relocate_level_data()

    Signature
    openrac_gaddr relocate_data(openrac_gaddr address);
    openrac_gaddr relocate_level_data(int level, openrac_gaddr address);
    A global's address for the code loaded now: one of the executable's (guest.h, OPENRAC_DATA), or of level level's program (OPENRAC_LDATA). Ask each time: a level moves its globals.

    loaded_level()

    Signature
    int loaded_level();
    
    // how a call looks
    int result = api->loaded_level();
    The level whose program is loaded, -1 for none (the executable's).

    Returns

    int
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
        (void)user;
        if (++s_ticks % (uint64_t)s_every != 0) {
            return;
        }
        char line[128];
        snprintf(line, sizeof line, "%llu ticks, %llu pad reports, level %d", (unsigned long long)s_ticks,
                 (unsigned long long)s_reports, s_api->loaded_level());
        s_api->log(s_mod, s_verbose ? OPENRAC_LOG_INFO : OPENRAC_LOG_DEBUG, line);
    }

    stack_push(), stack_pop()

    Signature
    openrac_gaddr stack_push(uint32_t size, openrac_gaddr* saved);
    void stack_pop(openrac_gaddr saved);
    Room on the game's stack for a call that takes the address of a local: stack_push gives size bytes (aligned to 16) and keeps the stack as it was in *saved; stack_pop(saved) gives them back. Pushes and pops pair, innermost first.

    input()

    Signature
    const openrac_input* input();
    
    // how a call looks
    const openrac_input* result = api->input();
    The keyboard and mouse for the tick about to run (openrac_input). Never null: without a window (a test, a server) nothing is held and nothing moves. Valid until the next tick.

    Returns

    const openrac_input*
    +Example (1)
    From the guide “Native mods in C”
    static void pad(void* user, int port, uint8_t* report, int size) {
        const openrac_input* in = s_api->input();      /* this tick's keys and mouse */
        if (port == 0 && openrac_bind_held(in, s_jump)) {
            report[1] &= (uint8_t)~0x40;               /* Cross held (bit 14: a clear bit is held) */
        }
        /* in->mouse_dx, mouse_dy: the motion since the last tick; wheel_x, wheel_y in notches */
    }

    take_input()

    Signature
    int take_input(openrac_mod* mod, uint32_t devices);
    
    // how a call looks
    int result = api->take_input(mod, devices);
    Takes devices (OPENRAC_INPUT_*) from the port:
    More with OPENRAC_INPUT_KEYBOARD the port's own keyboard table (WASD, Space, ...) no longer presses pad 0's buttons, and the mod presses them through on_pad instead. A gamepad goes on as before; the port's window keys (F3, F11) stay the port's. 0, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • devices (uint32_t)

    Returns

    int
    +Example (1)
    From the guide “Native mods in C”
    /* in openrac_mod_load: */
    s_jump = openrac_bind_from_name(api->setting_string(mod, "jump"));  /* one bind; split a pair at ',' */
    api->take_input(mod, OPENRAC_INPUT_KEYBOARD);  /* the port's own WASD table stops */
    api->capture_mouse(mod, 1);                     /* hidden cursor, relative motion */

    capture_mouse()

    Signature
    void capture_mouse(openrac_mod* mod, int capture);
    
    // how a call looks
    api->capture_mouse(mod, capture);
    Asks for the cursor captured (1: hidden, held in the window, motion relative, as a game's mouse look wants it) or let go (0).
    More Any time; the latest asking of any mod counts. The port lets it go anyway while the window is not focused or its overlay is open, and takes it back when the reason is gone and the mod still asks.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • capture (int)
    +Example (1)
    From the guide “Native mods in C”
    /* in openrac_mod_load: */
    s_jump = openrac_bind_from_name(api->setting_string(mod, "jump"));  /* one bind; split a pair at ',' */
    api->take_input(mod, OPENRAC_INPUT_KEYBOARD);  /* the port's own WASD table stops */
    api->capture_mouse(mod, 1);                     /* hidden cursor, relative motion */

    openrac_mod_query_fn

    Callback type
    Declaration
    typedef void (*openrac_mod_query_fn)(openrac_mod_info* info);
    The entry points a mod exports.

    openrac_mod_load_fn

    Callback type
    Declaration
    typedef int (*openrac_mod_load_fn)(const openrac_api* api, openrac_mod* mod);
    NameValueWhat it is
    OPENRAC_MOD_QUERY"openrac_mod_query"
    OPENRAC_MOD_LOAD"openrac_mod_load"
    OPENRAC_MOD_UNLOAD"openrac_mod_unload"

    OPENRAC_G()

    Macro
    Declaration
    #define OPENRAC_G(api, a) ((void*)((api)->memory + (openrac_gaddr)(a)))
    Helpers for a mod: a game address's bytes, and a typed value there.

    OPENRAC_GREF()

    Macro
    Declaration
    #define OPENRAC_GREF(api, T, a) (*(T*)OPENRAC_G(api, a))

    OPENRAC_MOD_DEFINE()

    Macro
    Declaration
    #define OPENRAC_MOD_DEFINE(mod_id, mod_version) ...
    The usual openrac_mod_query: OPENRAC_MOD_DEFINE("lock-strafe", "1.0.0").
    +Examples (2)
    From the guide “Native mods in C”
    #include "openrac/openrac_mod.h"
    #include "openrac/games/rac1.h"
    
    OPENRAC_MOD_DEFINE("my-mod", "0.1.0")   /* openrac_mod_query: the interface version, the id */
    
    OPENRAC_MOD_EXPORT int openrac_mod_load(const openrac_api* api, openrac_mod* mod) {
        if (strcmp(api->game, "rac1") != 0) {
            api->fail(mod, "this mod is for Ratchet & Clank");
            return 1;                          /* not loaded; the reason is shown */
        }
        api->log(mod, OPENRAC_LOG_INFO, "hello");
        return 0;                              /* loaded */
    }
    From sdk/examples/frame-counter/src/frame_counter.c
    OPENRAC_MOD_DEFINE("frame-counter", "1.0.0")

    Generated from sdk/include/openrac/openrac_mod.h at sdk-v1.2.0. Edit this page or report a problem.