Docs menu · C interface+

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

    Reference · SDK 1.10.1

    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_MINOR10 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 (10)
    • 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
    • 1.8play (multiplayer's calls): the game's phase and level, the hero's pose, figures that look like the hero, a game started or a level travelled to from code, and the player's saves
    • 1.9the world: the level's mobys listed, driven by a mod, posed, killed and made, a gate around each moby's update with the hero standing in for another player, hits watched and posted, eyes that keep mobys running, and the bolts
    • 1.10optional top-level desktop menu entries for mods
    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

    Since 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_MAX16Since 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_MAX2Since 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_PAUSE_ITEMS_MAX2Since 1.9 The most items the mods together add to the pause menu's Options page (openrac_api.ui_pause_item).
    OPENRAC_UI_NEW_GAME"new_game"Since 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"Since 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; the cursor passes over it, and 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

    Since 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

    Since 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

    Since 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

    Since 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)Since 1.7 openrac_api.ui_open's page that goes back a level, as Triangle does.
    OPENRAC_UI_SOUND_SELECT0Since 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

    Play: multiplayer's calls

    Since 1.8
    What a mod that plays the game with others needs of it:
    More what the game is doing (its phase and level), the hero's pose to send, figures to show the others with (mobys that look like the hero, driven by the mod: they never run the hero's logic, collide with nothing and are no target), a new game or a save started from code and a level travelled to, and the player's saves. Ratchet & Clank has them (PAL and NTSC-U); another game answers that it has none (OPENRAC_PLAY_NONE, OPENRAC_HOOK_UNKNOWN).
    NameValueWhat it is
    OPENRAC_PLAY_NONE0 The port knows nothing of this game's play: the play calls do nothing.
    OPENRAC_PLAY_FRONT_END1 The title and its menus: a game can be started (openrac_api.play_start).
    OPENRAC_PLAY_LOADING2 Between two programs: a level loading, the flight between planets.
    OPENRAC_PLAY_PLAYING3 A level, the player in control: a level can be travelled to (openrac_api.play_travel).
    OPENRAC_PLAY_SCENE4 A level, a scene playing: a cutscene, a movie, a slideshow, the ship's landing or take-off.
    OPENRAC_PLAY_MENU5 A level, a menu over it: paused, a vendor, a dialog.

    struct openrac_play_status

    Since 1.8
    What the game is doing (openrac_api.play_status). The port's; filled by the call.
    MemberWhat it is
    uint32_t sizesizeof(openrac_play_status), set by the mod before the call.
    int32_t phaseOPENRAC_PLAY_NONE ... OPENRAC_PLAY_MENU.
    int32_t levelThe level played (the game's own number), or the one loading; -1 for none (the front end).
    int32_t levelsHow many levels the game has (0 .. levels - 1).
    uint32_t loadsCounts the level programs loaded since the start: a new value, a new level (or the same one loaded again), whose figures are gone.
    NameValueWhat it is
    OPENRAC_POSE_BLENDING0x1u The animation is blending into seq from another: frame is where it arrives.

    struct openrac_pose

    Since 1.8
    A pose of the hero, or of a figure (openrac_api.hero_pose, figure_pose). Units are the game's.
    MemberWhat it is
    uint32_t sizesizeof(openrac_pose), set by the mod.
    int32_t levelThe level the pose is in.
    float position[3]Where the body is drawn, its rotation (radians, the game's axes: z the yaw) and its scale.
    float rotation[3](as above)
    float scale(as above)
    float velocity[3]How fast it moves, in game units a second.
    int32_t stateThe hero's state (the game's own ids), its health, and the item it holds (-1 none).
    int32_t health(as above)
    int32_t item(as above)
    uint32_t seqThe animation: the sequence of the hero's class, the key it is at, the key after, how far from one to the other (0 to 1), and its speed (1 normal, 0 held). OPENRAC_POSE_* flags.
    uint32_t frame(as above)
    uint32_t next_frame(as above)
    float anim_time(as above)
    float anim_speed(as above)
    uint32_t flags(as above)

    The world: the level's mobys

    Since 1.9
    For a mod that shares the world between games:
    More one game runs it (its enemies, crates, doors, platforms), the others drive their copies from it. A moby is named by its slot (its index in the level's moby array, this game's own) and, when the level placed it, by its key (its record in the level's file: the same moby has the same key in every game that loads the level, whatever was killed before). A driven moby's own update no longer runs (its animation still plays and its collision follows it): the mod poses it. The gate (on_moby_update) is asked around each update the game runs; before one, the mod may have the hero stand in elsewhere for it (another player: the enemy then sees, chases and hits that player's figure). Hits the game posts are told to a mod (on_moby_hit), which may take them back, and a mod posts its own (moby_hit).
    NameValueWhat it is
    OPENRAC_MOBY_UPDATES0x1u It has an update of its own (the game runs it near the camera).
    OPENRAC_MOBY_DRIVEN0x2u A mod drives it (moby_drive): its update does not run.
    OPENRAC_MOBY_PLACED0x4u The level placed it: it has a key.
    OPENRAC_MOBY_CREATURE0x8u Its class is a creature (an enemy, a person).
    OPENRAC_MOBY_DEAD0x10u A placed moby the game deleted (killed, broken, picked up): it stays dead for the level load, listed so a mod learns of the death from the game itself, never from a moby left out.
    OPENRAC_MOBY_SCENE0x20u An actor of the in-level scene playing (scene_playing): the game made it for the scene and deletes it when the scene ends. Each game playing the scene has its own.
    OPENRAC_MOBY_HIDDEN0x40u Hidden: drawn by nothing however near, as the game hides one (its update did, or moby_hide), or faded out (alpha 0).
    OPENRAC_MOBY_DRAWN0x80u Drawn in the last frame (in view, within its draw distance, not hidden).

    struct openrac_moby

    Since 1.9
    A moby of the level (moby_list), or the pose a mod gives one (moby_pose, moby_spawn: position, rotation, scale and the animation are read).
    MemberWhat it is
    uint32_t sizesizeof(openrac_moby), set by the mod.
    int32_t slotIts slot in this game, its key (-1 for one the level did not place), its class.
    int32_t key(as above)
    int32_t oclass(as above)
    uint32_t flagsOPENRAC_MOBY_* flags, and its state (the game's own byte, below 0x80 while it lives).
    uint32_t state(as above)
    float position[3]As openrac_pose's.
    float rotation[3](as above)
    float scale(as above)
    uint32_t seq(as above)
    uint32_t frame(as above)
    uint32_t next_frame(as above)
    float anim_time(as above)
    float anim_speed(as above)

    struct openrac_moby_deletion

    Since 1.9
    How the game deleted a moby of the level (moby_deletion).
    MemberWhat it is
    uint32_t sizesizeof(openrac_moby_deletion), set by the mod.
    int32_t byThe slot and class of the moby whose update deleted it (itself, or another: a spawner, a manager), -1 for none (the game's own code outside any moby's update: a level's script, a scene ending, the hero's items).
    int32_t by_class(as above)
    int32_t by_mod1 when a mod deleted it (moby_kill).
    int32_t oclassIts class then.
    uint32_t loadsThe level load it happened in (as openrac_play_status' loads).
    NameValueWhat it is
    OPENRAC_MOBY_RUN_NONE(-1) Not looked at: no moby there, a dead one, or one the game never runs (mode bit 2).
    OPENRAC_MOBY_RUN_FAR0 Left out: farther than its update distance from the camera and from every eye (play_eyes).
    OPENRAC_MOBY_RUN_DRAWN1 Run: drawn in the last frame, its update distance always (255), within it of the camera, within it of an eye, or as a member of a group another member of which was run.
    OPENRAC_MOBY_RUN_ALWAYS2
    OPENRAC_MOBY_RUN_NEAR3
    OPENRAC_MOBY_RUN_EYE4
    OPENRAC_MOBY_RUN_GROUP5
    OPENRAC_RUN_MENU_NONE0 No menu update in this level load yet.
    OPENRAC_RUN_MENU_HELD1 A menu updated with the world held (play_overlay_pause off).
    OPENRAC_RUN_MENU_FIRST2 The pause menu's first tick: the level's camera saved, the world run with it.
    OPENRAC_RUN_MENU_LEVEL_CAMERA3 The pause menu: the level's camera saved on its first tick put up for the world's run.
    OPENRAC_RUN_MENU_OWN_CAMERA4 The pause menu, with no level camera saved in this level load: the menu's camera stays up.
    OPENRAC_RUN_MENU_FREEZE5 A freeze dialog: the world run with the camera up (no swap).

    struct openrac_moby_run

    Since 1.9
    How the game ran the level's mobys in the last tick, and the moby in a slot (moby_run): for a mod that reports why a moby stopped or left.
    MemberWhat it is
    uint32_t sizesizeof(openrac_moby_run), set by the mod.
    uint32_t runsRun lists built of the level's mobys in this level load, and the camera the last one measured the update distances from.
    float camera[3](as above)
    uint32_t menu_ticksThe menu updates seen in this level load (the pause menu's, a freeze dialog's), what the last did (OPENRAC_RUN_MENU_*), and the level's camera the pause menu puts up for the world.
    int32_t menu(as above)
    float level_camera[3](as above)
    int32_t level_modeThe level's own game mode (Ratchet & Clank: 0 play, 3 paused, 4 a dialog, 5 a vendor...), and which moby context is current (0 the level's, 1 the pause menu's own).
    int32_t context(as above)
    int32_t update_distThe moby in slot (-1 or none: OPENRAC_MOBY_RUN_NONE and zeros):
    More its update distance (255: always), its draw distance, whether it was drawn in the last frame, how the last run list treated it (OPENRAC_MOBY_RUN_*), and its distance from that run list's camera.
    int32_t draw_dist(as above)
    int32_t drawn(as above)
    int32_t ran(as above)
    float distance(as above)
    NameValueWhat it is
    OPENRAC_MOBY_BEFORE0Since 1.9 The gate's moments (openrac_moby_update_fn).
    OPENRAC_MOBY_AFTER1

    openrac_moby_update_fn

    Since 1.9Callback type
    Declaration
    typedef int (*openrac_moby_update_fn)(void* user, int slot, int phase);
    The gate (openrac_api.on_moby_update): called with the user pointer the mod gave, before and after the update of the moby in slot (not for one a mod drives). Before it, returns 1 to skip the update (then no call after), 0 to run it.

    struct openrac_hit

    Since 1.9
    A hit (openrac_api.on_moby_hit, moby_hit): to the moby in victim, from attacker (-1 none), of the game's weapon or attack mask, damage, at position moving at velocity.
    MemberWhat it is
    uint32_t sizesizeof(openrac_hit), set by whoever fills it.
    int32_t victim(as above)
    int32_t attacker(as above)
    uint32_t mask(as above)
    float damage(as above)
    float position[3](as above)
    float velocity[3](as above)

    openrac_hit_fn

    Since 1.9Callback type
    Declaration
    typedef int (*openrac_hit_fn)(void* user, const openrac_hit* hit);
    Told a hit the game posted (openrac_api.on_moby_hit); returns 1 to take it back (the victim never reads it), 0 to leave it.
    NameValueWhat it is
    OPENRAC_EYES_MAX8Since 1.9 The most eyes (openrac_api.play_eyes).
    OPENRAC_FIGURES_MAX8Since 1.8 The most figures the mods together have at once (openrac_api.figure_create).
    OPENRAC_HELD_MAX8Since 1.9 The pieces the hero wears and holds (openrac_api.hero_held, figure_held):
    More the item in his hand (Ratchet & Clank: the wrench, or the weapon or gadget equipped), and the others the game draws on him (boots, helmet, the pack or Clank on his back).
    OPENRAC_HELD_HIDDEN0x1u Not drawn now (the game hides it).
    OPENRAC_HELD_BLENDING0x2u Its animation is blending into seq, as OPENRAC_POSE_BLENDING.
    OPENRAC_HELD_LOOSE0x4u Off the body (a thrown wrench): at position and rotation, not on its joint.

    struct openrac_held_piece

    Since 1.9
    One piece: the game's slot it is worn in and which of the slot's mobys it is (0 or 1), the item and the class of its moby, the body's joint it follows, OPENRAC_HELD_* flags, where it is (only read for a loose piece), and its own animation (as openrac_pose's: a swing, a shot).
    MemberWhat it is
    int32_t slot
    int32_t part(as above)
    int32_t item(as above)
    int32_t oclass(as above)
    int32_t joint(as above)
    uint32_t flags(as above)
    float position[3](as above)
    float rotation[3](as above)
    uint32_t seq(as above)
    uint32_t frame(as above)
    uint32_t next_frame(as above)
    float anim_time(as above)
    float anim_speed(as above)

    struct openrac_held

    Since 1.9
    What a body wears and holds: count pieces.
    MemberWhat it is
    uint32_t sizesizeof(openrac_held), set by the mod.
    int32_t count(as above)
    openrac_held_piece pieces[OPENRAC_HELD_MAX](as above)

    struct openrac_shot

    Since 1.9
    A shot the hero fired (openrac_api.hero_shots), or one a figure fires (figure_shot):
    More the weapon (the game's item id), where it starts, its velocity (game units a tick, as the game keeps it; for a shot the game aims by angles, its direction) and the game's own aim angles (Ratchet & Clank's Blaster: the heading's yaw and pitch, then the shot's first yaw and pitch).
    MemberWhat it is
    uint32_t sizesizeof(openrac_shot), set by whoever fills it.
    int32_t item(as above)
    float position[3](as above)
    float velocity[3](as above)
    float aim[4](as above)
    NameValueWhat it is
    OPENRAC_SHOTS_MAX16Since 1.9 The most shots kept for hero_shots between two calls.

    struct openrac_save_info

    Since 1.8
    A save of the player's (openrac_api.save_slot), read from the game's own save file on the memory card.
    MemberWhat it is
    uint32_t sizesizeof(openrac_save_info), set by the mod before the call.
    int32_t levelThe level it continues in, its bolts, its gold bolts and its time played in seconds.
    int32_t bolts(as above)
    int32_t gold_bolts(as above)
    int32_t seconds(as above)

    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.

    struct openrac_developer_menu_item

    New 1.10
    One entry in a mod's top-level desktop menu. group is an optional submenu label; action is a nonzero mod-defined id.
    MemberWhat it is
    const char* label
    const char* shortcut(as above)
    uint32_t action(as above)
    const char* group(as above)

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

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

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

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

    Since 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:
    More 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. Since 1.9 also while the title's main menu itself is on the screen: shows the page one of the mod's main-menu items opens (openrac_api.ui_main_item), as choosing the item does, so a mod brings the player back to its page after a game it ended.

    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 (nor the main menu, for an item's page) is on the screen or the page is not the mod's.

    ui_confirm()

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

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

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

    play_status()

    Since 1.8
    Signature
    int play_status(openrac_play_status* out);
    
    // how a call looks
    int result = api->play_status(out);
    Fills out (its size set) with what the game is doing: its phase (OPENRAC_PLAY_*), its level.

    Parameters

    • out (openrac_play_status*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a game the port knows no play of (phase OPENRAC_PLAY_NONE).

    level_name()

    Since 1.8
    Signature
    const char* level_name(int level);
    
    // how a call looks
    const char* result = api->level_name(level);
    The name of the game's level level ("Veldin"), or null for none.

    Parameters

    • level (int)

    Returns

    const char*

    figure_create()

    Since 1.8
    Signature
    int figure_create(openrac_mod* mod);
    
    // how a call looks
    int result = api->figure_create(mod);
    Makes a figure in the level: a moby that looks like the hero, in his pose, drawn but never running his logic, colliding with nothing and targeted by nothing, until figure_remove or the level goes (a new play_status.loads).

    Parameters

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

    Returns

    Returns its id (0 or more), or OPENRAC_HOOK_UNKNOWN outside a level, past OPENRAC_FIGURES_MAX, or when the level has no room for a moby.

    figure_pose()

    Since 1.8
    Signature
    int figure_pose(openrac_mod* mod, int id, const openrac_pose* pose);
    
    // how a call looks
    int result = api->figure_pose(mod, id, pose);
    Puts the mod's figure id in pose: where it is, its rotation and scale, and its animation (a new seq blends into it; the figure animates by itself, at anim_speed nudged faster or slower to keep to the pose's key and anim_time, and is put on the key only when more than a few keys away).
    More Each tick the mod wants it to move.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • id (int)
    • pose (const openrac_pose*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a figure that is not the mod's or is gone with its level (then the mod makes another).

    play_start()

    Since 1.8
    Signature
    int play_start(openrac_mod* mod, int level, const void* save, size_t size);
    
    // how a call looks
    int result = api->play_start(mod, level, save, size);
    From the front end (phase OPENRAC_PLAY_FRONT_END):
    More starts a game, after this frame, as the title's New Game and Load Game do: with save null a new game in level (0 the first); otherwise the size bytes of save (a save as save_read or save_capture give it), which continue in its own level, or in level when that is 0 or more. Nothing is written to the memory card.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • level (int)
    • save (const void*)
    • size (size_t)

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN while a start or travel asked before is still to happen, or OPENRAC_HOOK_UNKNOWN outside the front end, for a level the game has not, or a save it does not take.

    play_travel()

    Since 1.8
    Signature
    int play_travel(openrac_mod* mod, int level);
    
    // how a call looks
    int result = api->play_travel(mod, level);
    In a level with the player in control (phase OPENRAC_PLAY_PLAYING), and since 1.9 also in its scenes and menus (OPENRAC_PLAY_SCENE, OPENRAC_PLAY_MENU: a cutscene, the pause menu, a vendor):
    More leaves it for level, after this frame, as the ship's travel does (the flight between planets, then the level); -1 goes back to the title, as the pause menu's Quit Game does (since 1.9).

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN while a start or travel is still to happen, or OPENRAC_HOOK_UNKNOWN otherwise.

    save_capture()

    Since 1.8
    Signature
    size_t save_capture(void* out, size_t size);
    
    // how a call looks
    size_t result = api->save_capture(out, size);
    The game's progress now, as a save (the memory card's save file's bytes): written to out when size is large enough.

    Parameters

    • out (void*)
    • size (size_t)

    Returns

    Returns its size in bytes (call with a null out to ask), or 0 when there is none (no game started).

    save_slot()

    Since 1.8
    Signature
    int save_slot(int slot, openrac_save_info* out);
    
    // how a call looks
    int result = api->save_slot(slot, out);
    Fills out (its size set) with what the memory card's save slot holds.

    Parameters

    • slot (int)
    • out (openrac_save_info*)

    Returns

    Returns 1 for a save, 0 for an empty slot (or one the game would not load), -1 past the game's last slot.

    save_read()

    Since 1.8
    Signature
    size_t save_read(int slot, void* out, size_t size);
    
    // how a call looks
    size_t result = api->save_read(slot, out, size);
    The bytes of the memory card's save slot, for play_start: written to out when size is large enough.

    Parameters

    • slot (int)
    • out (void*)
    • size (size_t)

    Returns

    Returns their size, or 0 for no save there.

    moby_list()

    Since 1.9
    Signature
    int moby_list(openrac_moby* out, int max);
    
    // how a call looks
    int result = api->moby_list(out, max);
    Fills out with the level's live mobys and its placed ones deleted (OPENRAC_MOBY_DEAD), at most max of them (each one's size set by the port), in slot order, whatever menu is up.

    Parameters

    • out (openrac_moby*)
    • max (int)

    Returns

    Returns how many there are (more than max: the rest left out); 0 outside a level.

    Constants it uses

    moby_slot()

    Since 1.9
    Signature
    int moby_slot(int key);
    
    // how a call looks
    int result = api->moby_slot(key);

    Parameters

    • key (int)

    Returns

    Returns the slot of the placed moby key, or -1 for none (killed, or no such record).

    moby_drive()

    Since 1.9
    Signature
    int moby_drive(openrac_mod* mod, int slot, int on);
    
    // how a call looks
    int result = api->moby_drive(mod, slot, on);
    Drives the moby in slot (on 1: its update no longer runs, the mod poses it) or lets it go (0). A drive ends with its level.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for no moby there, or OPENRAC_HOOK_TAKEN when another mod drives it.

    moby_pose()

    Since 1.9
    Signature
    int moby_pose(openrac_mod* mod, int slot, const openrac_moby* pose);
    
    // how a call looks
    int result = api->moby_pose(mod, slot, pose);
    Puts the moby in slot in the pose pose gives (its position, rotation, scale when above 0, and animation, as figure_pose does).

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • slot (int)
    • pose (const openrac_moby*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for no moby there.

    moby_kill()

    Since 1.9
    Signature
    int moby_kill(openrac_mod* mod, int slot);
    
    // how a call looks
    int result = api->moby_kill(mod, slot);
    Deletes the moby in slot as the game deletes one (a placed one stays dead until its level loads again).

    Parameters

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

    moby_spawn()

    Since 1.9
    Signature
    int moby_spawn(openrac_mod* mod, int oclass, const openrac_moby* pose);
    
    // how a call looks
    int result = api->moby_spawn(mod, oclass, pose);
    Makes a moby of class oclass (one the level has) in pose, driven by the mod.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • oclass (int)
    • pose (const openrac_moby*)

    Returns

    Returns its slot, or OPENRAC_HOOK_UNKNOWN (no level, no room, a class the level has not).

    Results and errors

    figure_slot()

    Since 1.9
    Signature
    int figure_slot(openrac_mod* mod, int id);
    
    // how a call looks
    int result = api->figure_slot(mod, id);

    Parameters

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

    Returns

    Returns the slot of the mod's figure id (figure_create), or of the hero's moby with -1; -1 for none.

    on_moby_update()

    Since 1.9
    Signature
    int on_moby_update(openrac_mod* mod, openrac_moby_update_fn fn, void* user);
    
    // how a call looks
    int result = api->on_moby_update(mod, fn, user);
    Calls fn(user, slot, phase) around each moby's update (openrac_moby_update_fn). One mod's.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN when another mod has it, or OPENRAC_HOOK_TOO_LATE after openrac_mod_load.

    hero_stand_in()

    Since 1.9
    Signature
    int hero_stand_in(openrac_mod* mod, const float[3] position, int figure);
    
    // how a call looks
    int result = api->hero_stand_in(mod, position, figure);
    Only in the gate's call before an update: for that update the hero is at position, and his moby is the mod's figure figure (-1: his own), as another player would be there; put back after it.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • position (const float[3])
    • figure (int)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN outside that call.

    on_moby_hit()

    Since 1.9
    Signature
    int on_moby_hit(openrac_mod* mod, openrac_hit_fn fn, void* user);
    
    // how a call looks
    int result = api->on_moby_hit(mod, fn, user);
    Calls fn(user, &hit) for each hit the game posts (openrac_hit_fn). One mod's.

    Parameters

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

    Returns

    Returns as on_moby_update.

    moby_hit()

    Since 1.9
    Signature
    int moby_hit(openrac_mod* mod, const openrac_hit* hit);
    
    // how a call looks
    int result = api->moby_hit(mod, hit);
    Posts hit to its victim as the game posts one (the victim's update reads it: an enemy takes the damage, the hero is hurt), not told to on_moby_hit.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for no victim there.

    play_eyes()

    Since 1.9
    Signature
    int play_eyes(openrac_mod* mod, const float* xyz, int count);
    
    // how a call looks
    int result = api->play_eyes(mod, xyz, count);
    Sets up to OPENRAC_EYES_MAX points (x, y, z each) besides the camera: the mobys within their update distance of one run too (the world near other players). count 0 clears them.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • xyz (const float*)
    • count (int)

    Returns

    bolts()

    Since 1.9
    Signature
    int bolts(int add);
    
    // how a call looks
    int result = api->bolts(add);
    Adds add to the player's bolts (0: none) and returns them.

    Parameters

    • add (int)

    Returns

    int

    play_overlay_pause()

    Since 1.9
    Signature
    int play_overlay_pause(openrac_mod* mod, int on);
    
    // how a call looks
    int result = api->play_overlay_pause(mod, on);
    While on (1), the level's mobys keep being updated under the game's pause menu and its freeze dialogs, in the level's own mobys (the hero and the picture stay as the menu left them): a game that plays with others never stops their world for a menu. 0: as the game does.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a game without it.

    moby_slot_of()

    Since 1.9
    Signature
    int moby_slot_of(openrac_gaddr moby);
    
    // how a call looks
    int result = api->moby_slot_of(moby);

    Parameters

    • moby (openrac_gaddr)

    Returns

    Returns the slot of the moby at game address moby (a hook point's argument), -1 for none.

    play_skip()

    Since 1.9
    Signature
    int play_skip(openrac_mod* mod);
    
    // how a call looks
    int result = api->play_skip(mod);
    Skips the scene playing (a cutscene, the ship's landing or take-off, the flight between planets) the way the game's own skip does, as Start does with the port's "Skip cutscenes": for the next ticks, until the scene is over. For a party whose scenes end together.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a game the port has no skip of.

    figure_held()

    Since 1.9
    Signature
    int figure_held(openrac_mod* mod, int id, const openrac_held* held);
    
    // how a call looks
    int result = api->figure_held(mod, id, held);
    Has the mod's figure id wear and hold held:
    More each piece a moby of its class on the figure's joint (a loose one where it says), animated as it says, made when the level has its class loaded or can load it beside the hero's own (a piece it cannot have is left out, the hand's falling back to the wrench), taken off when left out of a later call, with the figure or with its level. Call it each tick the figure is posed.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • id (int)
    • held (const openrac_held*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a figure that is not the mod's or is gone.

    hero_shots()

    Since 1.9
    Signature
    int hero_shots(openrac_shot* out, int max);
    
    // how a call looks
    int result = api->hero_shots(out, max);
    The shots the hero fired since the last call (any mod's), oldest first: at most max into out (each one's size set by the port), at most OPENRAC_SHOTS_MAX kept between calls.

    Parameters

    • out (openrac_shot*)
    • max (int)

    Returns

    Returns how many were written.

    Constants it uses

    figure_shot()

    Since 1.9
    Signature
    int figure_shot(openrac_mod* mod, int id, const openrac_shot* shot);
    
    // how a call looks
    int result = api->figure_shot(mod, id, shot);
    Has the mod's figure id fire shot as the hero would: the game's own projectile and its effects, owned by the figure, hitting and breaking nothing in this game (the shooter's game tells what it hit).

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • id (int)
    • shot (const openrac_shot*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for a figure that is not the mod's, or a weapon the port cannot fire for a figure.

    play_notice()

    Since 1.9
    Signature
    int play_notice(openrac_mod* mod, const char* text);
    
    // how a call looks
    int result = api->play_notice(mod, text);
    Shows text (one line, UTF-8) at the top of the game's picture until the mod shows another or clears it (null or ""): what the game's own words cannot say, such as a party waiting for its players.

    Parameters

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

    Returns

    Results and errors

    ui_pause_item()

    Since 1.9
    Signature
    int ui_pause_item(openrac_mod* mod, const char* label, int page);
    
    // how a call looks
    int result = api->ui_pause_item(mod, label, page);
    Adds an item named label to the Options page of the pause menu in a level, after the game's own items (and the port's Video), which opens the mod's page (ui_page).
    More Ratchet & Clank: the page is a copy of the game's Camera options page, its title the page's and its list a row per item, the label on the left and a choice's value on the right, a few rows at a time; the game's cursor, sounds and Triangle (back to Options, but for OPENRAC_UI_OWN_BACK and while a question is open, which Triangle answers no); a question (ui_confirm) is the title with two rows, Yes and No; the footer is the game's. ui_open swaps another of the mod's pages into its place, ui_cursor only reads the cursor and ui_sound plays nothing there. Two go in the order they were added.

    Parameters

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

    Returns

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

    scene_playing()

    Since 1.9
    Signature
    int scene_playing(int* frame);
    
    // how a call looks
    int result = api->scene_playing(frame);
    The in-level scene playing now: a cutscene of the level's own, which the game starts from the level's mobys (a person spoken to, a place reached, a level's opening) or play_scene started; not a movie, a slideshow, the ship's landing and take-off, or a scene the pause menu plays again for its player.

    Parameters

    • frame (int*)

    Returns

    Returns its number in the level (the game's own, the same in every game of that level), or -1 with none playing; frame (when not null) gets how many of the scene's frames have played.

    play_scene()

    Since 1.9
    Signature
    int play_scene(openrac_mod* mod, int scene);
    
    // how a call looks
    int result = api->play_scene(mod, scene);
    Starts the level's scene scene (scene_playing's number) as the game's own trigger does, from its start:
    More its actors made, its camera, sound and music, the hero held until it ends (or is skipped: play_skip). It starts at the end of a tick with the player in control in the level (OPENRAC_PLAY_PLAYING, the hero alive); asked before that (a menu up, another scene playing), the request waits, until it starts, the level is left or loaded again, or another call replaces it (-1 drops it). For a party whose games play the same scenes.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN outside a level, or for a game the port starts no scenes of.

    moby_hide()

    Since 1.9
    Signature
    int moby_hide(openrac_mod* mod, int slot, int hidden);
    
    // how a call looks
    int result = api->moby_hide(mod, slot, hidden);
    Hides the moby in slot from drawing (hidden 1), as the game hides one, or shows it again (0); the game's own update may change it again (one a mod drives keeps it). Listed with OPENRAC_MOBY_HIDDEN while hidden.

    Parameters

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

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for no moby there.

    moby_deletion()

    Since 1.9
    Signature
    int moby_deletion(int slot, openrac_moby_deletion* out);
    
    // how a call looks
    int result = api->moby_deletion(slot, out);
    Fills out (its size set by the mod) with the last deletion the game made of the moby in slot in this level load: whose update did it, or a mod. For a mod that wants to know why a moby left the level (a spawned one's slot is used again: ask on the tick it went).

    Parameters

    • slot (int)
    • out (openrac_moby_deletion*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN for none seen (none, or it left the level some other way).

    moby_run()

    Since 1.9
    Signature
    int moby_run(int slot, openrac_moby_run* out);
    
    // how a call looks
    int result = api->moby_run(slot, out);
    Fills out (its size set by the mod) with how the game ran the level's mobys in the last tick (the run list's camera, what the last menu update did) and the moby in slot (-1: none) in it (openrac_moby_run).

    Parameters

    • slot (int)
    • out (openrac_moby_run*)

    Returns

    Returns OPENRAC_HOOK_OK, or OPENRAC_HOOK_UNKNOWN outside a level or for a game without it.

    developer_menu()

    New 1.10
    Signature
    int developer_menu(
        openrac_mod* mod,
        const char* title,
        const openrac_developer_menu_item* items,
        uint32_t item_count
    );
    
    // how a call looks
    int result = api->developer_menu(mod, title, items, item_count);
    Adds a top-level menu beside View, Graphics, Sound and Developer to the in-window desktop menu bar.
    More title, item labels, shortcuts and groups are copied. Selections are queued for the mod and retrieved from its tick-boundary callback; this never calls mod code from UI drawing. Items may be placed in groups (submenus), and use nonzero mod-defined action ids.

    Parameters

    • mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.
    • title (const char*)
    • items (const openrac_developer_menu_item*)
    • item_count (uint32_t)

    Returns

    Returns OPENRAC_HOOK_OK, OPENRAC_HOOK_TAKEN for a duplicate title or action, OPENRAC_HOOK_UNKNOWN for invalid items, or OPENRAC_HOOK_TOO_LATE unless called during openrac_mod_load.

    take_developer_menu_action()

    New 1.10
    Signature
    uint32_t take_developer_menu_action(openrac_mod* mod);
    
    // how a call looks
    uint32_t result = api->take_developer_menu_action(mod);
    Only from its on_tick_boundary callback.

    Parameters

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

    Returns

    Returns and removes the next queued action for this mod, or 0 if none.

    developer_menu_set_label()

    New 1.10
    Signature
    int developer_menu_set_label(
        openrac_mod* mod,
        uint32_t action,
        const char* label
    );
    
    // how a call looks
    int result = api->developer_menu_set_label(mod, action, label);
    Changes a registered item's label, copying label. Only from this mod's tick-boundary callback.

    Parameters

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

    Returns

    int

    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.10.1. Edit this page or report a problem.