Docs menu · C interface+

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

    Reference · SDK 1.7.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

    Versions

    NameValueWhat it is
    OPENRAC_MOD_API_MAJOR1 The interface's major version. Changes when anything in the table changes or goes.
    OPENRAC_MOD_API_MINOR7 The interface's minor version, which this header describes. It grows when something is added at the end of the table.
    Show what each version added (7)
    • 1.1script mods (the table is unchanged)
    • 1.2the keyboard and mouse
    • 1.3the pointer over the game's picture (openrac_input.pointer_*)
    • 1.4the graphics context, extra views of the game and a Vulkan device made with the mod (a VR headset, docs/views.md)
    • 1.5entries in the game's front-end menu with a page of the mod's own
    • 1.6the tick-boundary callback and warm in-session snapshot calls
    • 1.7pages of the game's own menus (its frames, list, text, prompt and sounds) and items of the title's main menu
    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")))Since 1.0 Marks an entry point of the mod's library as exported, whatever the build's default visibility.

    Basic types and constants

    openrac_gaddr

    Since 1.0Type
    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

    Since 1.0Type
    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). Opaque; valid from openrac_mod_load until the program ends.
    +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
     * counts. It changes nothing in the game.
     *
     * How it works: OPENRAC_MOD_DEFINE writes openrac_mod_query; openrac_mod_load keeps the table and
     * the handle in file-level variables (the port calls the mod's functions on the game's thread, one
     * at a time, so no lock is needed), takes the hook point and the callback, and logs a line;
     * openrac_mod_unload logs the totals at exit. Written in C, so the whole mod is plain C99 against
     * openrac_mod.h and games/rac1.h.
     */
    #include <stdio.h>
    #include <string.h>
    NameValueWhat it is
    OPENRAC_LOG_DEBUG0Since 1.0 The levels of openrac_api.log, from the most to the least talkative.
    OPENRAC_LOG_INFO1
    OPENRAC_LOG_WARN2
    OPENRAC_LOG_ERROR3
    OPENRAC_HOOK_OK0Since 1.0 The results of openrac_api.hook.
    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 than the one asked for.
    OPENRAC_HOOK_TOO_LATE(-3) Hooks are taken in openrac_mod_load only.
    OPENRAC_HOOK_TAKEN(-4)Since 1.4 Another mod has it already: the views (on_views) and the Vulkan device (setup_vulkan) are one mod's each.

    Reporting to the port

    struct openrac_mod_info

    Since 1.0
    What openrac_mod_query tells the port before it loads the mod. The port sets size; the mod sets the rest (OPENRAC_MOD_DEFINE does).
    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_TARGET_MINOR as the mod was built.
    const char* idThe manifest's id: the port checks they agree. Static storage in the mod.
    const char* versionThe mod's version, as its manifest's. Static storage in the mod.
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
    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);

    The keyboard and mouse

    Since 1.2
    NameValueWhat it is
    OPENRAC_KEY_COUNT512Since 1.2 The number of entries of openrac_input.keys. A key is its USB HID usage, the same on every layout and system (openrac/keys.h names them: "KeyW", "Space", "ShiftLeft").
    OPENRAC_KEY_HELD1uSince 1.2 The key is down: a bit of an openrac_input.keys[k] entry.
    OPENRAC_KEY_PRESSED2uSince 1.2 The key went down since the last tick (a tap shorter than a tick too): a bit of an openrac_input.keys[k] entry.
    OPENRAC_MOUSE_LEFT1uSince 1.2 The bits of openrac_input.mouse_held and mouse_pressed.
    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_KEYBOARD1uSince 1.2 A device of openrac_api.take_input: the port's own keyboard table stops driving pad 0.
    OPENRAC_INPUT_MOUSE2uSince 1.2 A device of openrac_api.take_input: the mod uses the mouse in play. Reserved: the port has no mouse use of its own in play.

    struct openrac_input

    Since 1.2
    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). Read it through openrac_api.input; it is the port's, and valid until the next tick.
    Since 1.2; the fields from pointer_x on are 1.3's, and exist only when size reaches them.
    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_heldThe OPENRAC_MOUSE_* buttons down now.
    uint32_t mouse_pressedThe OPENRAC_MOUSE_* buttons that went down since the last tick.
    float mouse_dxThe mouse's motion since the last tick, in the system's pixels: raw (no pointer acceleration) while captured; y grows downward.
    float mouse_dy(as above)
    float wheel_xThe wheel since the last tick, in notches: x > 0 to the right, y > 0 away from the player (up), whatever the system's scroll direction.
    float wheel_y(as above)
    uint8_t focused1 when the game's window has the keyboard; while not, nothing is held.
    uint8_t captured1 when the cursor is captured: hidden, kept in the window, motion relative.
    uint8_t overlay1 when the port's own overlay or menu has the input now (F3): leave it alone.
    uint8_t reservedPadding; zero.
    float pointer_xSince 1.3 (check size first): where the cursor is over the game's 4:3 picture, 0..1 across and down (outside it below 0 or above 1), as the game's 2D screen of 512 by 416 pixels has it:
    More x * 512, y * 416 is the game's pixel. Meaningful while the cursor is not captured.
    float pointer_y(as above)
    uint8_t pointer_insideSince 1.3: 1 when the cursor is over the picture, in the focused window.
    uint8_t reserved2[3]Padding; zero.
    +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 */
    }

    The graphics context

    Since 1.4
    NameValueWhat it is
    OPENRAC_GRAPHICS_NONE0 No window yet, or none at all (a test, a server).
    OPENRAC_GRAPHICS_OPENGL1 The desktop's OpenGL 4.1 core profile.
    OPENRAC_GRAPHICS_OPENGL_ES2 OpenGL ES 3.2 (Android, or OPENRAC_GL_API=es).
    OPENRAC_GRAPHICS_VULKAN3 The port's Vulkan renderer (OPENRAC_GL_API=vulkan).

    struct openrac_graphics

    Since 1.4
    What the port draws with, for a mod that hands the game's pictures to another API (OpenXR).
    More Read it through openrac_api.graphics; it is the port's, and valid while the window is open. Vulkan handles are given as pointers (VkInstance, VkPhysicalDevice, VkDevice and VkQueue are dispatchable handles), so that this header needs no Vulkan header.
    MemberWhat it is
    uint32_t sizesizeof(openrac_graphics) as the port was built: a newer port's is larger.
    uint32_t backendAn OPENRAC_GRAPHICS_* value.
    void *(*gl_proc)(const char *name)OpenGL and OpenGL ES: the context's functions by name (SDL_GL_GetProcAddress); null for Vulkan and without a window. The context is current on the game's thread.
    void *vk_instanceVulkan: the backend's instance, physical device, device and graphics queue, its family and its index in the family, and the vkGetInstanceProcAddr they were made with;
    More null and 0 otherwise. While a mod has views (on_views) the port submits to the queue on the game's thread only, so a mod's own use of it there (OpenXR's xrEndFrame) needs no lock.
    void *vk_physical_device(as above)
    void *vk_device(as above)
    void *vk_queue(as above)
    uint32_t vk_queue_family(as above)
    uint32_t vk_queue_index(as above)
    void *vk_get_instance_proc_addr(as above)

    Views of the game

    Since 1.4
    NameValueWhat it is
    OPENRAC_VIEW_MAX4Since 1.4 The most views a frame draws (openrac_view_source.begin's max).
    OPENRAC_VIEW_FULL0 The game's whole picture: the world, with the 2D (HUD, text, menus, fades) over it at the game's 4:3 shape in its middle.
    OPENRAC_VIEW_WORLD1 The world alone, without the 2D.
    OPENRAC_VIEW_2D2 The 2D alone, over transparent black (alpha 0 where nothing is drawn): for a panel. Give it the game's 4:3 shape; the eye pose and field of view are not used.

    struct openrac_view

    Since 1.4
    One view the port draws in a frame besides the window's: an eye of a headset, a panel. The mod fills the members up to image_layout in openrac_view_source.begin; the port sets the ones after as it draws.
    MemberWhat it is
    uint32_t kindAn OPENRAC_VIEW_* value.
    int32_t widthThe picture's size in pixels, each from 1 to 8192.
    int32_t height(as above)
    float position[3]The eye relative to the game's camera, in the camera's view space (OpenXR's and OpenGL's: X right, Y up, looking down -Z), in the game's units:
    More a position, and an orientation as a quaternion x, y, z, w. The identity (0 0 0, 0 0 0 1) is the game's own camera; an all-zero orientation counts as the identity.
    float orientation[4](as above)
    float angle_leftThe field of view as OpenXR's XrFovf gives it:
    More the angles of its left, right, top and bottom edges from straight ahead, in radians (left and down negative). All zero: the game's own vertical one, at the view's shape.
    float angle_right(as above)
    float angle_up(as above)
    float angle_down(as above)
    uint32_t textureWhere the picture goes, in the backend's own terms (openrac_api.graphics), copied as its bytes with no conversion of colour (an sRGB image gets the game's picture as it is shown):
    More - OpenGL: texture, a GL_TEXTURE_2D of the port's context, RGBA8 or SRGB8_ALPHA8, at least width by height (an OpenXR swapchain image); - Vulkan: image, a VkImage of the port's device, VK_FORMAT_R8G8B8A8_UNORM or _SRGB, exactly width by height, usable as a transfer destination, which the port finds in image_layout (a VkImageLayout) and leaves in it. Zero and null: the picture is drawn only into the port's own texture (picture).
    void *image(as above)
    uint32_t image_layout(as above)
    uint32_t drawnSet by the port: 1 when this frame drew the view anew;
    More 0 when it showed the last frame's picture again (a frame the port draws no world in, as the pause menu's repeated frames), and then that picture is copied again.
    uint32_t pictureSet by the port: its own GL texture holding the view (with OpenGL), until the next frame.
    uint32_t reserved[3]Padding; zero.

    struct openrac_view_source

    Since 1.4
    The functions a mod gives on_views. The port copies the structure; user is passed back to each. Every function is called on the game's thread, with the graphics context current.
    MemberWhat it is
    uint32_t sizesizeof(openrac_view_source) as the mod was built.
    void *user(as above)
    int (*begin)(void *user, openrac_view *views, int max)Called in each frame the port draws the game's scene (each refresh, between the game's ticks too), after the window's picture is recorded:
    More fills views[0] to views[n - 1] (n at most max) and returns n; 0 draws none this frame. The place for OpenXR's xrWaitFrame, xrBeginFrame, xrLocateViews and xrAcquireSwapchainImage. Frames that show a movie or a still picture instead of the scene do not call it.
    void (*end)(void *user, const openrac_view *views, int count)Called once the frame that drew them is submitted to the GPU (after the window's picture is shown), with the views begin gave and what the port set in them:
    More the place for xrReleaseSwapchainImage and xrEndFrame. Called after every begin, even one that returned 0 or a frame that drew nothing.
    void (*closing)(void *user)Called once before the graphics context goes (the window closes): let go of everything made with it (OpenXR's session and swapchains). Optional.

    struct openrac_vulkan_setup

    Since 1.4
    What a mod gives setup_vulkan so that the port's Vulkan device is one the mod can share (OpenXR's XR_KHR_vulkan_enable2: xrCreateVulkanInstanceKHR, xrGetVulkanGraphicsDevice2KHR, xrCreateVulkanDeviceKHR).
    More The port copies the structure; user is passed back to each. The functions are called when the window opens, after openrac_mod_load, on the game's thread: the mod's manifest says "vulkan_device": true so that it loads before the window. Pointers stand for the Vulkan types named, and int32_t for VkResult.
    MemberWhat it is
    uint32_t sizesizeof(openrac_vulkan_setup) as the mod was built.
    void *user(as above)
    int32_t (*create_instance)(void *user, void *get_instance_proc_addr, const void *create_info, void **instance)Makes the instance from create_info (a const VkInstanceCreateInfo*, the port's: the extensions and the API version it needs) in place of vkCreateInstance, through get_instance_proc_addr (a PFN_vkGetInstanceProcAddr), and sets *instance.
    More Returns a VkResult; anything but VK_SUCCESS (0) and the port draws with OpenGL instead. Optional.
    void *(*physical_device)(void *user, void *instance)Returns the VkPhysicalDevice to draw on, of instance; null lets the port choose. The port refuses a device it cannot draw with (and draws with OpenGL instead). Optional.
    int32_t (*create_device)(void *user, void *get_instance_proc_addr, void *physical_device, const void *create_info, void **device)Makes the device from create_info (a const VkDeviceCreateInfo*, the port's) on physical_device in place of vkCreateDevice, and sets *device. Returns a VkResult, as create_instance. Optional.

    Menu pages

    Since 1.5
    NameValueWhat it is
    OPENRAC_MENU_ENTRIES_MAX4Since 1.5 The most entries the mods together add to the front-end menu (openrac_api.menu_entry).
    OPENRAC_MENU_WIDTH512Since 1.5 A menu page's own pixels: the game's 2D picture, 512 across and 448 down, (0, 0) its top left, shown stretched over the whole window.
    OPENRAC_MENU_HEIGHT448
    OPENRAC_MENU_CHAR_WIDTH6Since 1.5 A character of openrac_api.menu_text at size 1:
    More 6 pixels across (a 5 by 7 glyph and a column between), 8 down; at size n each is n times that. Letters are drawn as capitals; a character the font lacks is a blank.
    OPENRAC_MENU_CHAR_HEIGHT8

    OPENRAC_RGBA()

    Since 1.5Macro
    Declaration
    #define OPENRAC_RGBA(r, g, b, a)     (((uint32_t)(r) << 24) | ((uint32_t)(g) << 16) | ((uint32_t)(b) << 8) | (uint32_t)(a))
    A colour of a menu page's drawing, 0xRRGGBBAA: alpha 255 covers what is under, 0 leaves it.
    NameValueWhat it is
    OPENRAC_PAD_SELECT0x0001uSince 1.5 The pad's buttons in openrac_menu_frame.held and .pressed: pad 0's (the keyboard's keys the port maps to it included), one bit each, set while down.
    OPENRAC_PAD_L30x0002u
    OPENRAC_PAD_R30x0004u
    OPENRAC_PAD_START0x0008u
    OPENRAC_PAD_UP0x0010u
    OPENRAC_PAD_RIGHT0x0020u
    OPENRAC_PAD_DOWN0x0040u
    OPENRAC_PAD_LEFT0x0080u
    OPENRAC_PAD_L20x0100u
    OPENRAC_PAD_R20x0200u
    OPENRAC_PAD_L10x0400u
    OPENRAC_PAD_R10x0800u
    OPENRAC_PAD_TRIANGLE0x1000u
    OPENRAC_PAD_CIRCLE0x2000u
    OPENRAC_PAD_CROSS0x4000u
    OPENRAC_PAD_SQUARE0x8000u

    struct openrac_menu_frame

    Since 1.5
    What a menu page's callback is given each frame it is open. The port's; valid during the call.
    MemberWhat it is
    uint32_t sizesizeof(openrac_menu_frame) as the port was built: a newer port's is larger.
    uint32_t heldThe OPENRAC_PAD_* buttons down now.
    uint32_t pressedThe OPENRAC_PAD_* buttons that went down since the last call.
    uint32_t opened1 on the first call after the page opened, 0 after.
    NameValueWhat it is
    OPENRAC_MENU_STAY0Since 1.5 What a menu page's callback returns: the page stays open, or closes and the game's menu it was opened from comes back (as the game's own back button does).
    OPENRAC_MENU_CLOSE1

    openrac_menu_fn

    Since 1.5Callback type
    Declaration
    typedef int (*openrac_menu_fn)(void* user, const openrac_menu_frame* frame);
    A mod's menu page (openrac_api.menu_entry):
    More called once a frame while the page is open, on the game's thread, with the user pointer the mod gave. It draws the page with menu_rect and menu_text (the page starts each frame black) and returns OPENRAC_MENU_STAY or OPENRAC_MENU_CLOSE. While the page is open the game sees no button of pad 0.

    Pages of the game's own menus

    New 1.7
    A page here is drawn by the game's own front end:
    More its frames, its title, its list in its font, its footer of hints, its sounds. The mod says what is on it (openrac_api.ui_set) and hears what the player does (openrac_ui_fn). Ratchet & Clank: a page opened from an item of the title's main menu (openrac_api.ui_main_item) has the Options page's frames; a page opened from that one has the Language page's, a level down, and opening another from there takes its place. Up and Down move the cursor (over the items the cursor can take), Cross chooses, Left and Right step a choice, Triangle goes back a level. A game whose front end the port does not know shows none.
    NameValueWhat it is
    OPENRAC_UI_PAGES_MAX16New 1.7 The most pages the mods together make, items a page lists, footer lines, choices an item steps through, and characters a text keeps (longer ones are cut).
    OPENRAC_UI_ITEMS_MAX12
    OPENRAC_UI_CHOICES_MAX64
    OPENRAC_UI_TEXT_MAX47
    OPENRAC_UI_MAIN_ITEMS_MAX2New 1.7 The most items the mods together add to the main menu (openrac_api.ui_main_item): Ratchet & Clank's has room for two rows below its own three.
    OPENRAC_UI_NEW_GAME"new_game"New 1.7 The main menu's own items, for openrac_api.ui_main_item's after.
    OPENRAC_UI_LOAD_GAME"load_game"
    OPENRAC_UI_OPTIONS"options"
    OPENRAC_UI_CROSS"\x10"New 1.7 The pad's buttons as the game's font draws them, for a text: OPENRAC_UI_CROSS " Join".
    OPENRAC_UI_CIRCLE"\x11"
    OPENRAC_UI_TRIANGLE"\x12"
    OPENRAC_UI_SQUARE"\x13"
    OPENRAC_UI_BUTTON0u A line Cross chooses: OPENRAC_UI_CHOOSE.
    OPENRAC_UI_CHOICE1u A line with a value among choices: Left and Right step it back and on, Cross on (around the ends), each an OPENRAC_UI_CHANGE. Shown as the label and the value.
    OPENRAC_UI_TEXT2u A line of text (a status, a name): the cursor passes over it.
    OPENRAC_UI_DISABLED0x1u Drawn dim, as the game's locked entries; choosing it plays the game's refusal, and no event.
    OPENRAC_UI_OWN_BACK0x1u Triangle comes to the mod as OPENRAC_UI_BACK instead of going back: the mod goes back itself (openrac_api.ui_open with OPENRAC_UI_GO_BACK), for one that asks first.

    struct openrac_ui_item

    New 1.7
    One item of a page (openrac_ui_content.items). The mod's; read during openrac_api.ui_set.
    MemberWhat it is
    uint32_t kindOPENRAC_UI_BUTTON, OPENRAC_UI_CHOICE or OPENRAC_UI_TEXT.
    uint32_t flagsOPENRAC_UI_DISABLED, or 0.
    const char* labelWhat the line says (UTF-8: ASCII and the game's accented letters; the OPENRAC_UI_CROSS ... glyphs).
    const char* const* choicesOPENRAC_UI_CHOICE: the values (choice_count of them, up to OPENRAC_UI_CHOICES_MAX) and the one shown. Unused otherwise.
    uint32_t choice_count(as above)
    uint32_t choice(as above)

    struct openrac_ui_content

    New 1.7
    What a page shows (openrac_api.ui_set). The mod's; read during the call.
    MemberWhat it is
    uint32_t sizesizeof(openrac_ui_content) as the mod was built.
    const char* titleThe title, in the page's title frame.
    const openrac_ui_item* itemsThe list, item_count items (up to OPENRAC_UI_ITEMS_MAX).
    uint32_t item_count(as above)
    const char* const* footerThe footer's lines (up to OPENRAC_UI_FOOTER_MAX); none: the game's own hints (Select, Exit, in the game's language).
    uint32_t footer_count(as above)
    NameValueWhat it is
    OPENRAC_UI_SHOW0u The page came on the screen (from the main menu, ui_open, or back from a page under it).
    OPENRAC_UI_FRAME1u Each tick the page is on the screen, after the tick's other events.
    OPENRAC_UI_CHOOSE2u Cross on a button that is not disabled: item.
    OPENRAC_UI_CHANGE3u A choice stepped: item, value its new choice.
    OPENRAC_UI_BACK4u Triangle on a page made with OPENRAC_UI_OWN_BACK.
    OPENRAC_UI_ANSWER5u The question of ui_confirm answered: value 1 for yes (Cross), 0 for no (Triangle, or the page left), tag the one the mod gave.
    OPENRAC_UI_HIDE6u The page left the screen.

    struct openrac_ui_event

    New 1.7
    An event of a page (openrac_ui_fn). The port's; valid during the call.
    MemberWhat it is
    uint32_t sizesizeof(openrac_ui_event) as the port was built: a newer port's is larger.
    uint32_t kindOPENRAC_UI_SHOW ... OPENRAC_UI_HIDE.
    int32_t itemThe item it is about (CHOOSE, CHANGE), else -1.
    int32_t valueCHANGE: the new choice; ANSWER: 1 yes, 0 no; else 0.
    uint32_t tagANSWER: the question's tag; else 0.
    int32_t cursorThe item under the cursor.

    openrac_ui_fn

    New 1.7Callback type
    Declaration
    typedef void (*openrac_ui_fn)(void* user, int page, const openrac_ui_event* event);
    A mod's page (openrac_api.ui_page): called on the game's thread with the user pointer the mod gave, the page's id and each event. The calls of the table work from here (ui_set, ui_open, ...); what they ask for happens after the call.
    NameValueWhat it is
    OPENRAC_UI_GO_BACK(-1)New 1.7 openrac_api.ui_open's page that goes back a level, as Triangle does.
    OPENRAC_UI_SOUND_SELECT0New 1.7 The game's menu sounds (openrac_api.ui_sound). The port plays the cursor's, a choice's and a refusal's itself.
    OPENRAC_UI_SOUND_CURSOR1
    OPENRAC_UI_SOUND_DENIED2
    OPENRAC_UI_SOUND_OPEN3
    OPENRAC_UI_SOUND_PAGE4

    Callbacks

    openrac_frame_fn

    Since 1.0Callback type
    Declaration
    typedef void (*openrac_frame_fn)(void* user);
    A function the port calls after each game tick (openrac_api.on_frame), with the user pointer the mod gave.

    openrac_tick_boundary_fn

    Since 1.6Callback type
    Declaration
    typedef void (*openrac_tick_boundary_fn)(void* user, uint32_t tick);
    Called after the game's vertical-blank handlers have run. Snapshot operations are only accepted from this callback, at the port's tick boundary.

    openrac_pad_fn

    Since 1.0Callback type
    Declaration
    typedef void (*openrac_pad_fn)(void* user, int port, uint8_t* report, int size);
    A function the port calls for each pad report (openrac_api.on_pad), with the user pointer the mod gave. report is the 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.

    The table the port offers

    What the port offers a mod. Filled by the port; valid for the life of the program. Every function is called on the game's thread. Members from "1.2" on are at the end: a mod built for 1.1 never sees them, and one built for 1.2 loads on a 1.2 port or newer.

    size

    Since 1.0Value
    Field
    uint32_t size;
    sizeof(openrac_api) as the port was built: a newer port's is larger.

    api_major, api_minor

    Since 1.0Value
    Field
    uint16_t api_major;
    uint16_t api_minor;
    The port's interface version: at least what the mod was built for, else it is not loaded.

    game

    Since 1.0Value
    Field
    const char* game;
    The game's id, "rac1" (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
    /* The hook point and the memory it reads are Ratchet & Clank's: refuse any other game. */
    if (strcmp(api->game, "rac1") != 0) {
        api->fail(mod, "frame-counter is for Ratchet & Clank (rac1)");
        return 1;
    }

    version

    Since 1.0Value
    Field
    const char* version;
    The disc's version, "pal" or "ntsc".
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
    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);

    openrac_version

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

    platform

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

    memory

    Since 1.0Value
    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()

    Since 1.0
    Signature
    void log(openrac_mod* mod, int level, const char* text);
    
    // how a call looks
    api->log(mod, level, text);
    Writes a line to the session's log, after the mod's id. level is an OPENRAC_LOG_* value.

    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
            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()

    Since 1.0Only while loading
    Signature
    void fail(openrac_mod* mod, const char* reason);
    
    // how a call looks
    api->fail(mod, reason);
    Says why the mod refuses to load (status.json and the launcher show it). Only during openrac_mod_load, which then returns non-zero.

    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()

    Since 1.0
    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);
    Read 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 "". A string stays valid for the life of the program.
    +Examples (2)
    From sdk/examples/frame-counter/src/frame_counter.c
    s_verbose = api->setting_bool(mod, "verbose");
    From sdk/examples/frame-counter/src/frame_counter.c
    s_every = api->setting_int(mod, "every");

    hook()

    Since 1.0Only 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, which signature spells.
    More Sets *original 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

    Returns OPENRAC_HOOK_OK or one of the other OPENRAC_HOOK_* results.
    +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()

    Since 1.0Only 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);
    Calls 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

    Returns 0, or non-zero when refused (after openrac_mod_load).
    +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
    api->on_frame(mod, on_frame, NULL);

    on_pad()

    Since 1.0Only 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);
    Calls 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

    Returns 0, or non-zero when refused (after openrac_mod_load).
    +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()

    Since 1.0
    Signature
    void* function(const char* name);
    
    // how a call looks
    void* result = api->function(name);

    Parameters

    • name (const char*)

    Returns

    Returns 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.

    function_at()

    Since 1.0
    Signature
    void* function_at(openrac_gaddr address);
    
    // how a call looks
    void* result = api->function_at(address);

    Parameters

    • address (openrac_gaddr)

    Returns

    Returns the function at a code address, in the level loaded now (a function pointer the game keeps); null when there is none.

    relocate_data(), relocate_level_data()

    Since 1.0
    Signature
    openrac_gaddr relocate_data(openrac_gaddr address);
    openrac_gaddr relocate_level_data(int level, openrac_gaddr address);
    Ask each time: a level moves its globals.

    Returns

    Return 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).

    loaded_level()

    Since 1.0
    Signature
    int loaded_level();
    
    // how a call looks
    int result = api->loaded_level();

    Returns

    Returns the level whose program is loaded, -1 for none (the executable's).
    +Example (1)
    From sdk/examples/frame-counter/src/frame_counter.c
        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()

    Since 1.0
    Signature
    openrac_gaddr stack_push(uint32_t size, openrac_gaddr* saved);
    
    // how a call looks
    openrac_gaddr result = api->stack_push(size, saved);
    Pair each push with a stack_pop, innermost first.

    Parameters

    • size (uint32_t)
    • saved (openrac_gaddr*)

    Returns

    Gives size bytes (aligned to 16) of room on the game's stack for a call that takes the address of a local, and keeps the stack as it was in *saved. Returns the room's address.

    stack_pop()

    Since 1.0
    Signature
    void stack_pop(openrac_gaddr saved);
    
    // how a call looks
    api->stack_pop(saved);

    Parameters

    • saved (openrac_gaddr)

    Returns

    Gives back what the matching stack_push took: saved is what it stored.

    input()

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

    Returns

    Returns the keyboard and mouse for the tick about to run.
    +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()

    Since 1.2
    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: 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.

    Parameters

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

    Returns

    Returns 0, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.
    +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()

    Since 1.2
    Signature
    void capture_mouse(openrac_mod* mod, int capture);
    
    // how a call looks
    api->capture_mouse(mod, capture);
    Asks for the cursor captured (capture 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 */

    on_views()

    Since 1.4
    Signature
    int on_views(openrac_mod* mod, const openrac_view_source* source);
    
    // how a call looks
    int result = api->on_views(mod, source);
    Asks the port to draw views of the game besides the window's picture each frame, through source (openrac_view_source), with OpenGL and Vulkan. While a mod has views, the Vulkan renderer draws on the game's thread.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • source (const openrac_view_source*)

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN when another mod has them, OPENRAC_HOOK_UNKNOWN for a source without begin or end, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    setup_vulkan()

    Since 1.4
    Signature
    int setup_vulkan(openrac_mod* mod, const openrac_vulkan_setup* setup);
    
    // how a call looks
    int result = api->setup_vulkan(mod, setup);
    Has the port make its Vulkan device through setup (openrac_vulkan_setup) when the window opens, so that the mod can share it. Without Vulkan (OpenGL, a build without it) nothing is called.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • setup (const openrac_vulkan_setup*)

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN when another mod has it, OPENRAC_HOOK_UNKNOWN for a setup too small, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    menu_entry()

    Since 1.5
    Signature
    int menu_entry(
        openrac_mod* mod,
        const char* label,
        openrac_menu_fn fn,
        void* user
    );
    
    // how a call looks
    int result = api->menu_entry(mod, label, fn, user);
    Adds an entry named label (ASCII, up to 31 characters) to the game's front-end menu, which opens a page of the mod's own:
    More fn(user, frame) each frame it is open (openrac_menu_fn). Ratchet & Clank has it in the title's Options list, after the port's own entries (Video, and Planets with developer tools). A game whose front end the port does not know shows none.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_UNKNOWN for no label or fn or past OPENRAC_MENU_ENTRIES_MAX, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    menu_rect()

    Since 1.5
    Signature
    void menu_rect(
        openrac_mod* mod,
        int x,
        int y,
        int width,
        int height,
        uint32_t rgba
    );
    
    // how a call looks
    api->menu_rect(mod, x, y, width, height, rgba);
    Fills the rectangle of width by height pixels whose top left is (x, y) on the menu page (OPENRAC_MENU_WIDTH by OPENRAC_MENU_HEIGHT) with rgba (OPENRAC_RGBA), blended by its alpha; what is outside the page is left out. Only during the mod's own menu callback; ignored otherwise.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • x (int)
    • y (int)
    • width (int)
    • height (int)
    • rgba (uint32_t)

    menu_text()

    Since 1.5
    Signature
    void menu_text(
        openrac_mod* mod,
        int x,
        int y,
        int size,
        uint32_t rgba,
        const char* text
    );
    
    // how a call looks
    api->menu_text(mod, x, y, size, rgba, text);
    Writes text (ASCII; a newline starts a line below) on the menu page with its first character's top left at (x, y), each character OPENRAC_MENU_CHAR_WIDTH by OPENRAC_MENU_CHAR_HEIGHT times size (1 to 8), in rgba. Only during the mod's own menu callback; ignored otherwise.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • x (int)
    • y (int)
    • size (int)
    • rgba (uint32_t)
    • text (const char*)

    on_tick_boundary()

    Since 1.6
    Signature
    int on_tick_boundary(
        openrac_mod* mod,
        openrac_tick_boundary_fn fn,
        void* user
    );
    
    // how a call looks
    int result = api->on_tick_boundary(mod, fn, user);
    Calls fn(user, tick) after the game's vertical-blank handlers have run, the port's tick boundary, the only place the savestate calls below are accepted (openrac_tick_boundary_fn).

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_TOO_LATE for no fn or after openrac_mod_load.

    savestate_size()

    Since 1.6
    Signature
    size_t savestate_size();
    
    // how a call looks
    size_t result = api->savestate_size();
    The byte size of this port build's warm, same-process snapshot; 0 where the running game has none (Ratchet & Clank PAL and NTSC have one).

    Returns

    size_t

    savestate_save()

    Since 1.6
    Signature
    int savestate_save(void* out, size_t size);
    
    // how a call looks
    int result = api->savestate_save(out, size);
    Captures a snapshot into out, size being savestate_size(). Only inside on_tick_boundary; returns 0 on success. The bytes are private to this process and build, not for a cold restore or another version.

    Parameters

    • out (void*)
    • size (size_t)

    Returns

    int

    savestate_load()

    Since 1.6
    Signature
    int savestate_load(const void* data, size_t size);
    
    // how a call looks
    int result = api->savestate_load(data, size);
    Restores a snapshot savestate_save made, under the same constraints; returns 0 on success. It may refuse when the runtime allocated new guest statics or strings since the snapshot, because translated call sites cache those addresses in process memory.

    Parameters

    • data (const void*)
    • size (size_t)

    Returns

    int

    ui_page()

    New 1.7
    Signature
    int ui_page(openrac_mod* mod, uint32_t flags, openrac_ui_fn fn, void* user);
    
    // how a call looks
    int result = api->ui_page(mod, flags, fn, user);
    Makes a page of the game's own menus (OPENRAC_UI_OWN_BACK or 0 in flags), with nothing on it yet (ui_set), whose events go to fn(user, page, event) (openrac_ui_fn).

    Parameters

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

    Returns

    Returns the page's id (0 or more), OPENRAC_HOOK_UNKNOWN for no fn or past OPENRAC_UI_PAGES_MAX, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    ui_main_item()

    New 1.7
    Signature
    int ui_main_item(
        openrac_mod* mod,
        const char* after,
        const char* label,
        int page
    );
    
    // how a call looks
    int result = api->ui_main_item(mod, after, label, page);
    Adds an item named label to the title's main menu, after its own item after (OPENRAC_UI_NEW_GAME, OPENRAC_UI_LOAD_GAME, OPENRAC_UI_OPTIONS), which opens the mod's page. Two after the same item go in the order they were added.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • after (const char*)
    • label (const char*)
    • page (int)

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_UNKNOWN for an unknown after, no label, a page that is not the mod's, or past OPENRAC_UI_MAIN_ITEMS_MAX, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    ui_set()

    New 1.7
    Signature
    int ui_set(openrac_mod* mod, int page, const openrac_ui_content* content);
    
    // how a call looks
    int result = api->ui_set(mod, page, content);
    Puts content on the mod's page (openrac_ui_content), in place of what it had: shown at once if the page is on the screen. Any time. The cursor stays on its item (on the last when there are fewer, and off a TEXT).

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • page (int)
    • content (const openrac_ui_content*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a page that is not the mod's or no content.

    ui_open()

    New 1.7
    Signature
    int ui_open(openrac_mod* mod, int page);
    
    // how a call looks
    int result = api->ui_open(mod, page);
    While one of the mod's pages is on the screen: shows its page, a level under a page the main menu opened or in place of one under it; a page that is on a level above goes back to it. OPENRAC_UI_GO_BACK goes back a level, as Triangle does.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN when none of the mod's pages is on the screen or the page is not the mod's.

    ui_confirm()

    New 1.7
    Signature
    int ui_confirm(
        openrac_mod* mod,
        int page,
        const char* question,
        uint32_t tag
    );
    
    // how a call looks
    int result = api->ui_confirm(mod, page, question, tag);
    While the mod's page is on the screen: asks question with the game's prompt box in place of the list, the footer saying Cross is yes and Triangle no; the answer is an OPENRAC_UI_ANSWER with tag.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • page (int)
    • question (const char*)
    • tag (uint32_t)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN when the page is not on the screen or another question is open.

    ui_cursor()

    New 1.7
    Signature
    int ui_cursor(openrac_mod* mod, int page, int item);
    
    // how a call looks
    int result = api->ui_cursor(mod, page, item);

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • page (int)
    • item (int)

    Returns

    Returns the item under the cursor of the mod's page (-1 for a page that is not the mod's), after moving it to item when that is 0 or more and an item the cursor takes.

    ui_sound()

    New 1.7
    Signature
    int ui_sound(openrac_mod* mod, int sound);
    
    // how a call looks
    int result = api->ui_sound(mod, sound);
    Plays one of the game's menu sounds (OPENRAC_UI_SOUND_*) while one of the mod's pages is on the screen.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN otherwise.

    The entry points a mod exports

    openrac_mod_query_fn

    Since 1.0Callback type
    Declaration
    typedef void (*openrac_mod_query_fn)(openrac_mod_info* info);
    Tells the port which interface the mod was built for: sets info's api_major, api_minor, id and version. Called before the mod is loaded. Required; OPENRAC_MOD_DEFINE writes it.

    openrac_mod_load_fn

    Since 1.0Callback type
    Declaration
    typedef int (*openrac_mod_load_fn)(const openrac_api* api, openrac_mod* mod);
    Loads the mod: takes its hook points and callbacks from api, and keeps mod for the calls that are its own. Returns 0 to load, non-zero to refuse (after openrac_api.fail gave the reason). Required.

    openrac_mod_unload_fn

    Since 1.0Callback type
    Declaration
    typedef void (*openrac_mod_unload_fn)(void);
    Lets go of what the mod holds, when the program ends. Optional.
    NameValueWhat it is
    OPENRAC_MOD_QUERY"openrac_mod_query"Since 1.0 The names the entry points are exported under, for the port's lookup.
    OPENRAC_MOD_LOAD"openrac_mod_load"
    OPENRAC_MOD_UNLOAD"openrac_mod_unload"

    Helpers for a mod

    OPENRAC_G()

    Since 1.0Macro
    Declaration
    #define OPENRAC_G(api, a) ((void*)((api)->memory + (openrac_gaddr)(a)))
    The host pointer to a game address's bytes. api is the openrac_api, a a game address.

    OPENRAC_GREF()

    Since 1.0Macro
    Declaration
    #define OPENRAC_GREF(api, T, a) (*(T*)OPENRAC_G(api, a))
    A typed value at a game address, as an lvalue: OPENRAC_GREF(api, int32_t, a) = 5. The address must be aligned for T.

    OPENRAC_MOD_DEFINE()

    Since 1.0Macro
    Declaration
    #define OPENRAC_MOD_DEFINE(mod_id, mod_version) ...
    Writes the usual openrac_mod_query: OPENRAC_MOD_DEFINE("lock-strafe", "1.0.0"). mod_id and mod_version are string literals, the manifest's.
    +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
     *
     * An example mod that uses each part of the interface (sdk/README.md): it refuses a game it is not
     * for, reads a bool and an int setting, counts the game's ticks with on_frame, and takes a hook
     * point, counting the calls and going on to what it replaced. Every `every` ticks it logs both
     * counts. It changes nothing in the game.
     *
     * How it works: OPENRAC_MOD_DEFINE writes openrac_mod_query; openrac_mod_load keeps the table and
     * the handle in file-level variables (the port calls the mod's functions on the game's thread, one
     * at a time, so no lock is needed), takes the hook point and the callback, and logs a line;
     * openrac_mod_unload logs the totals at exit. Written in C, so the whole mod is plain C99 against
     * openrac_mod.h and games/rac1.h.
     */
    #include <stdio.h>

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