openrac_gaddr
Since 1.0Typetypedef uint32_t openrac_gaddr;+Example (1)
static void pad_process_report(openrac_gaddr pad, openrac_gaddr report, int32_t size) {
++s_reports;
s_pad_original(pad, report, size);
}Reference · SDK 1.11.0
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| Name | Value | What it is |
|---|---|---|
| OPENRAC_MOD_API_MAJOR | 1 | The interface's major version. Changes when anything in the table changes or goes. |
| OPENRAC_MOD_API_MINOR | 11 | 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 (11)Hide
|
| OPENRAC_MOD_TARGET_MINOR | OPENRAC_MOD_API_MINOR | The interface a mod is built for, what its openrac_mod_query reports:Moreits 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. |
typedef uint32_t openrac_gaddr;static void pad_process_report(openrac_gaddr pad, openrac_gaddr report, int32_t size) {
++s_reports;
s_pad_original(pad, report, size);
}typedef struct openrac_mod openrac_mod;#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 */
} * 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>| Name | Value | What it is |
|---|---|---|
| OPENRAC_LOG_DEBUG | 0 | Since 1.0 The levels of openrac_api.log, from the most to the least talkative. |
| OPENRAC_LOG_INFO | 1 | |
| OPENRAC_LOG_WARN | 2 | |
| OPENRAC_LOG_ERROR | 3 | |
| OPENRAC_HOOK_OK | 0 | Since 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. |
size; the mod sets the rest (OPENRAC_MOD_DEFINE does).| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_mod_info), set by the port. |
| uint32_t api_major | OPENRAC_MOD_API_MAJOR as the mod was built. |
| uint32_t api_minor | OPENRAC_MOD_TARGET_MINOR as the mod was built. |
| const char* id | The manifest's id: the port checks they agree. Static storage in the mod. |
| const char* version | The mod's version, as its manifest's. Static storage in the mod. |
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);| Name | Value | What it is |
|---|---|---|
| OPENRAC_KEY_COUNT | 512 | Since 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_HELD | 1u | Since 1.2 The key is down: a bit of an openrac_input.keys[k] entry. |
| OPENRAC_KEY_PRESSED | 2u | Since 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_LEFT | 1u | Since 1.2 The bits of openrac_input.mouse_held and mouse_pressed. |
| OPENRAC_MOUSE_MIDDLE | 2u | |
| OPENRAC_MOUSE_RIGHT | 4u | |
| OPENRAC_MOUSE_BACK | 8u | The side button nearer the wrist (X1). |
| OPENRAC_MOUSE_FORWARD | 16u | The other side button (X2). |
| OPENRAC_INPUT_KEYBOARD | 1u | Since 1.2 A device of openrac_api.take_input: the port's own keyboard table stops driving pad 0. |
| OPENRAC_INPUT_MOUSE | 2u | Since 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. |
pointer_x on are 1.3's, and exist only when size reaches them.| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_input) as the port was built: a newer port's is larger. |
| uint32_t tick | Counts 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_held | The OPENRAC_MOUSE_* buttons down now. |
| uint32_t mouse_pressed | The OPENRAC_MOUSE_* buttons that went down since the last tick. |
| float mouse_dx | The 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_x | The 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 focused | 1 when the game's window has the keyboard; while not, nothing is held. |
| uint8_t captured | 1 when the cursor is captured: hidden, kept in the window, motion relative. |
| uint8_t overlay | 1 when the port's own overlay or menu has the input now (F3): leave it alone. |
| uint8_t reserved | Padding; zero. |
| float pointer_x | Since 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:Morex * 512, y * 416 is the game's pixel. Meaningful while the cursor is not captured. |
| float pointer_y | (as above) |
| uint8_t pointer_inside | Since 1.3: 1 when the cursor is over the picture, in the focused window. |
| uint8_t reserved2[3] | Padding; zero. |
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 */
}| Name | Value | What it is |
|---|---|---|
| OPENRAC_GRAPHICS_NONE | 0 | No window yet, or none at all (a test, a server). |
| OPENRAC_GRAPHICS_OPENGL | 1 | The desktop's OpenGL 4.1 core profile. |
| OPENRAC_GRAPHICS_OPENGL_ES | 2 | OpenGL ES 3.2 (Android, or OPENRAC_GL_API=es). |
| OPENRAC_GRAPHICS_VULKAN | 3 | The port's Vulkan renderer (OPENRAC_GL_API=vulkan). |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_graphics) as the port was built: a newer port's is larger. |
| uint32_t backend | An 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_instance | Vulkan: 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;Morenull 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) |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_VIEW_MAX | 4 | Since 1.4 The most views a frame draws (openrac_view_source.begin's max). |
| OPENRAC_VIEW_FULL | 0 | 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_WORLD | 1 | The world alone, without the 2D. |
| OPENRAC_VIEW_2D | 2 | 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. |
image_layout in openrac_view_source.begin; the port sets the ones after as it draws.| Member | What it is |
|---|---|
| uint32_t kind | An OPENRAC_VIEW_* value. |
| int32_t width | The 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:Morea 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_left | The field of view as OpenXR's XrFovf gives it:Morethe 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 texture | Where 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 drawn | Set by the port: 1 when this frame drew the view anew;More0 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 picture | Set by the port: its own GL texture holding the view (with OpenGL), until the next frame. |
| uint32_t reserved[3] | Padding; zero. |
user is passed back to each. Every function is called on the game's thread, with the graphics context current.| Member | What it is |
|---|---|
| uint32_t size | sizeof(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:Morefills views[0] to views[n - 1] (n at mostmax) 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:Morethe place for xrReleaseSwapchainImage and xrEndFrame. Called after everybegin, 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. |
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.| Member | What it is |
|---|---|
| uint32_t size | sizeof(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.MoreReturns 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. |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_PLAY_NONE | 0 | The port knows nothing of this game's play: the play calls do nothing. |
| OPENRAC_PLAY_FRONT_END | 1 | The title and its menus: a game can be started (openrac_api.play_start). |
| OPENRAC_PLAY_LOADING | 2 | Between two programs: a level loading, the flight between planets. |
| OPENRAC_PLAY_PLAYING | 3 | A level, the player in control: a level can be travelled to (openrac_api.play_travel). |
| OPENRAC_PLAY_SCENE | 4 | A level, a scene playing: a cutscene, a movie, a slideshow, the ship's landing or take-off. |
| OPENRAC_PLAY_MENU | 5 | A level, a menu over it: paused, a vendor, a dialog. |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_play_status), set by the mod before the call. |
| int32_t phase | OPENRAC_PLAY_NONE ... OPENRAC_PLAY_MENU. |
| int32_t level | The level played (the game's own number), or the one loading; -1 for none (the front end). |
| int32_t levels | How many levels the game has (0 .. levels - 1). |
| uint32_t loads | Counts the level programs loaded since the start: a new value, a new level (or the same one loaded again), whose figures are gone. |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_POSE_BLENDING | 0x1u | The animation is blending into seq from another: frame is where it arrives. |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_pose), set by the mod. |
| int32_t level | The 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 state | The 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 seq | The 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) |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_MOBY_UPDATES | 0x1u | It has an update of its own (the game runs it near the camera). |
| OPENRAC_MOBY_DRIVEN | 0x2u | A mod drives it (moby_drive): its update does not run. |
| OPENRAC_MOBY_PLACED | 0x4u | The level placed it: it has a key. |
| OPENRAC_MOBY_CREATURE | 0x8u | Its class is a creature (an enemy, a person). |
| OPENRAC_MOBY_DEAD | 0x10u | 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_SCENE | 0x20u | 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_HIDDEN | 0x40u | Hidden: drawn by nothing however near, as the game hides one (its update did, or moby_hide), or faded out (alpha 0). |
| OPENRAC_MOBY_DRAWN | 0x80u | Drawn in the last frame (in view, within its draw distance, not hidden). |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_moby), set by the mod. |
| int32_t slot | Its 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 flags | OPENRAC_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) |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_moby_deletion), set by the mod. |
| int32_t by | The 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_mod | 1 when a mod deleted it (moby_kill). |
| int32_t oclass | Its class then. |
| uint32_t loads | The level load it happened in (as openrac_play_status' loads). |
| Name | Value | What 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_FAR | 0 | Left out: farther than its update distance from the camera and from every eye (play_eyes). |
| OPENRAC_MOBY_RUN_DRAWN | 1 | 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_ALWAYS | 2 | |
| OPENRAC_MOBY_RUN_NEAR | 3 | |
| OPENRAC_MOBY_RUN_EYE | 4 | |
| OPENRAC_MOBY_RUN_GROUP | 5 | |
| OPENRAC_RUN_MENU_NONE | 0 | No menu update in this level load yet. |
| OPENRAC_RUN_MENU_HELD | 1 | A menu updated with the world held (play_overlay_pause off). |
| OPENRAC_RUN_MENU_FIRST | 2 | The pause menu's first tick: the level's camera saved, the world run with it. |
| OPENRAC_RUN_MENU_LEVEL_CAMERA | 3 | The pause menu: the level's camera saved on its first tick put up for the world's run. |
| OPENRAC_RUN_MENU_OWN_CAMERA | 4 | The pause menu, with no level camera saved in this level load: the menu's camera stays up. |
| OPENRAC_RUN_MENU_FREEZE | 5 | A freeze dialog: the world run with the camera up (no swap). |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_moby_run), set by the mod. |
| uint32_t runs | Run 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_ticks | The 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_mode | The 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_dist | The moby in slot (-1 or none: OPENRAC_MOBY_RUN_NONE and zeros):Moreits 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) |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_MOBY_BEFORE | 0 | Since 1.9 The gate's moments (openrac_moby_update_fn). |
| OPENRAC_MOBY_AFTER | 1 |
typedef int (*openrac_moby_update_fn)(void* user, int slot, int phase);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.victim, from attacker (-1 none), of the game's weapon or attack mask, damage, at position moving at velocity.| Member | What it is |
|---|---|
| uint32_t size | sizeof(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) |
typedef int (*openrac_hit_fn)(void* user, const openrac_hit* hit);| Name | Value | What it is |
|---|---|---|
| OPENRAC_EYES_MAX | 8 | Since 1.9 The most eyes (openrac_api.play_eyes). |
| OPENRAC_FIGURES_MAX | 8 | Since 1.8 The most figures the mods together have at once (openrac_api.figure_create). |
| OPENRAC_HELD_MAX | 8 | Since 1.9 The pieces the hero wears and holds (openrac_api.hero_held, figure_held):Morethe 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_HIDDEN | 0x1u | Not drawn now (the game hides it). |
| OPENRAC_HELD_BLENDING | 0x2u | Its animation is blending into seq, as OPENRAC_POSE_BLENDING. |
| OPENRAC_HELD_LOOSE | 0x4u | Off the body (a thrown wrench): at position and rotation, not on its joint. |
| Member | What 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) |
count pieces.| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_held), set by the mod. |
| int32_t count | (as above) |
| openrac_held_piece pieces[OPENRAC_HELD_MAX] | (as above) |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(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) |
| Name | Value | What it is |
|---|---|---|
| OPENRAC_SHOTS_MAX | 16 | Since 1.9 The most shots kept for hero_shots between two calls. |
| Member | What it is |
|---|---|
| uint32_t size | sizeof(openrac_save_info), set by the mod before the call. |
| int32_t level | The 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) |
typedef void (*openrac_frame_fn)(void* user);user pointer the mod gave.typedef void (*openrac_tick_boundary_fn)(void* user, uint32_t tick);group is an optional submenu label; action is a nonzero mod-defined id.| Member | What it is |
|---|---|
| const char* label | |
| const char* shortcut | (as above) |
| uint32_t action | (as above) |
| const char* group | (as above) |
typedef void (*openrac_pad_fn)(void* user, int port, uint8_t* report, int size);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.uint32_t size;uint16_t api_major;
uint16_t api_minor;const char* game;#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 */
}/* 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;
}const char* version;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);const char* openrac_version;const char* platform;uint8_t* memory;// Once a game tick: read or change game memory through mod.memory().
mod.on_frame([] {});void log(openrac_mod* mod, int level, const char* text);
// how a call looks
api->log(mod, level, text);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*)Constants it uses
#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 */
} 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);
}void fail(openrac_mod* mod, const char* reason);
// how a call looks
api->fail(mod, reason);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.reason (const char*)#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 */
}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;
}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);s_verbose = api->setting_bool(mod, "verbose");s_every = api->setting_int(mod, "every");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);name (games/<game>.h: its name and signature) for replacement, a function of the hook point's signature, which signature spells.*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
Results and errors
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);
});// 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 ...
});int on_frame(openrac_mod* mod, openrac_frame_fn fn, void* user);
// how a call looks
int result = api->on_frame(mod, fn, user);fn(user) after each game tick, in load order. Only during openrac_mod_load.Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.fn (openrac_frame_fn)user (void*)Returns
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);api->on_frame(mod, on_frame, NULL);int on_pad(openrac_mod* mod, openrac_pad_fn fn, void* user);
// how a call looks
int result = api->on_pad(mod, fn, user);fn(user, port, report, size) for each pad report, before the game reads it, in load order. Only during openrac_mod_load.Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.fn (openrac_pad_fn)user (void*)Returns
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);void* function(const char* name);
// how a call looks
void* result = api->function(name);Parameters
name (const char*)Returns
void* function_at(openrac_gaddr address);
// how a call looks
void* result = api->function_at(address);Parameters
address (openrac_gaddr)Returns
openrac_gaddr relocate_data(openrac_gaddr address);
openrac_gaddr relocate_level_data(int level, openrac_gaddr address);Returns
level's program (OPENRAC_LDATA).int loaded_level();
// how a call looks
int result = api->loaded_level();Returns
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);
}openrac_gaddr stack_push(uint32_t size, openrac_gaddr* saved);
// how a call looks
openrac_gaddr result = api->stack_push(size, saved);Parameters
size (uint32_t)saved (openrac_gaddr*)Returns
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.void stack_pop(openrac_gaddr saved);
// how a call looks
api->stack_pop(saved);Parameters
saved (openrac_gaddr)Returns
saved is what it stored.const openrac_input* input();
// how a call looks
const openrac_input* result = api->input();Returns
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 */
}int take_input(openrac_mod* mod, uint32_t devices);
// how a call looks
int result = api->take_input(mod, devices);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
Results and errors
/* 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 */void capture_mouse(openrac_mod* mod, int capture);
// how a call looks
api->capture_mouse(mod, capture);capture 1: hidden, held in the window, motion relative, as a game's mouse look wants it) or let go (0).Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.capture (int)/* 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 */const openrac_graphics * graphics();
// how a call looks
const openrac_graphics * result = api->graphics();Returns
Constants it uses
int on_views(openrac_mod* mod, const openrac_view_source* source);
// how a call looks
int result = api->on_views(mod, source);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
int setup_vulkan(openrac_mod* mod, const openrac_vulkan_setup* setup);
// how a call looks
int result = api->setup_vulkan(mod, setup);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
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);label (ASCII, up to 31 characters) to the game's front-end menu, which opens a page of the mod's own: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
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);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)Constants it uses
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);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*)Constants it uses
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);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
Results and errors
size_t savestate_size();
// how a call looks
size_t result = api->savestate_size();Returns
size_tint savestate_save(void* out, size_t size);
// how a call looks
int result = api->savestate_save(out, size);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
intint savestate_load(const void* data, size_t size);
// how a call looks
int result = api->savestate_load(data, size);Parameters
data (const void*)size (size_t)Returns
intint 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);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
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);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
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.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);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
Results and errors
int ui_open(openrac_mod* mod, int page);
// how a call looks
int result = api->ui_open(mod, page);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
Results and errors
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);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
Results and errors
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
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.int ui_sound(openrac_mod* mod, int sound);
// how a call looks
int result = api->ui_sound(mod, sound);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.sound (int)Returns
int play_status(openrac_play_status* out);
// how a call looks
int result = api->play_status(out);out (its size set) with what the game is doing: its phase (OPENRAC_PLAY_*), its level.Parameters
out (openrac_play_status*)Returns
const char* level_name(int level);
// how a call looks
const char* result = api->level_name(level);level ("Veldin"), or null for none.Parameters
level (int)Returns
const char*int hero_pose(openrac_pose* out);
// how a call looks
int result = api->hero_pose(out);out (its size set) with the hero's pose as it is drawn now.Parameters
out (openrac_pose*)Returns
Results and errors
int figure_create(openrac_mod* mod);
// how a call looks
int result = api->figure_create(mod);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.Returns
Results and errors
int figure_pose(openrac_mod* mod, int id, const openrac_pose* pose);
// how a call looks
int result = api->figure_pose(mod, id, pose);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).Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.id (int)pose (const openrac_pose*)Returns
Results and errors
int figure_remove(openrac_mod* mod, int id);
// how a call looks
int result = api->figure_remove(mod, id);id out of the level.Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.id (int)Returns
Results and errors
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);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
int play_travel(openrac_mod* mod, int level);
// how a call looks
int result = api->play_travel(mod, level);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
size_t save_capture(void* out, size_t size);
// how a call looks
size_t result = api->save_capture(out, size);out when size is large enough.Parameters
out (void*)size (size_t)Returns
out to ask), or 0 when there is none (no game started).int save_slot(int slot, openrac_save_info* out);
// how a call looks
int result = api->save_slot(slot, out);out (its size set) with what the memory card's save slot holds.Parameters
slot (int)out (openrac_save_info*)Returns
size_t save_read(int slot, void* out, size_t size);
// how a call looks
size_t result = api->save_read(slot, out, size);slot, for play_start: written to out when size is large enough.Parameters
slot (int)out (void*)size (size_t)Returns
int moby_list(openrac_moby* out, int max);
// how a call looks
int result = api->moby_list(out, max);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
max: the rest left out); 0 outside a level.Constants it uses
int moby_slot(int key);
// how a call looks
int result = api->moby_slot(key);Parameters
key (int)Returns
key, or -1 for none (killed, or no such record).int moby_drive(openrac_mod* mod, int slot, int on);
// how a call looks
int result = api->moby_drive(mod, slot, on);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
Results and errors
int moby_pose(openrac_mod* mod, int slot, const openrac_moby* pose);
// how a call looks
int result = api->moby_pose(mod, slot, pose);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
Results and errors
int moby_kill(openrac_mod* mod, int slot);
// how a call looks
int result = api->moby_kill(mod, slot);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)Returns
Results and errors
int moby_spawn(openrac_mod* mod, int oclass, const openrac_moby* pose);
// how a call looks
int result = api->moby_spawn(mod, oclass, pose);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
Results and errors
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
id (figure_create), or of the hero's moby with -1; -1 for none.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);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
Results and errors
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);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
Results and errors
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);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
int moby_hit(openrac_mod* mod, const openrac_hit* hit);
// how a call looks
int result = api->moby_hit(mod, hit);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
Results and errors
int play_eyes(openrac_mod* mod, const float* xyz, int count);
// how a call looks
int result = api->play_eyes(mod, xyz, count);count 0 clears them.Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.xyz (const float*)count (int)Returns
Results and errors
int bolts(int add);
// how a call looks
int result = api->bolts(add);add to the player's bolts (0: none) and returns them.Parameters
add (int)Returns
intint play_overlay_pause(openrac_mod* mod, int on);
// how a call looks
int result = api->play_overlay_pause(mod, on);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
Results and errors
int moby_slot_of(openrac_gaddr moby);
// how a call looks
int result = api->moby_slot_of(moby);Parameters
moby (openrac_gaddr)Returns
moby (a hook point's argument), -1 for none.int play_skip(openrac_mod* mod);
// how a call looks
int result = api->play_skip(mod);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.Returns
Results and errors
int hero_held(openrac_held* out);
// how a call looks
int result = api->hero_held(out);out (its size set) with what the hero wears and holds now (openrac_held), the pieces in the game's slot order.Parameters
out (openrac_held*)Returns
Results and errors
int figure_held(openrac_mod* mod, int id, const openrac_held* held);
// how a call looks
int result = api->figure_held(mod, id, held);id wear and hold held:Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.id (int)held (const openrac_held*)Returns
Results and errors
int hero_shots(openrac_shot* out, int max);
// how a call looks
int result = api->hero_shots(out, max);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
Constants it uses
int figure_shot(openrac_mod* mod, int id, const openrac_shot* shot);
// how a call looks
int result = api->figure_shot(mod, id, shot);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
Results and errors
int play_notice(openrac_mod* mod, const char* text);
// how a call looks
int result = api->play_notice(mod, text);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
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);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).Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.label (const char*)page (int)Returns
int scene_playing(int* frame);
// how a call looks
int result = api->scene_playing(frame);Parameters
frame (int*)Returns
frame (when not null) gets how many of the scene's frames have played.int play_scene(openrac_mod* mod, int scene);
// how a call looks
int result = api->play_scene(mod, scene);scene (scene_playing's number) as the game's own trigger does, from its start:Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.scene (int)Returns
Results and errors
int moby_hide(openrac_mod* mod, int slot, int hidden);
// how a call looks
int result = api->moby_hide(mod, slot, hidden);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
Results and errors
int moby_deletion(int slot, openrac_moby_deletion* out);
// how a call looks
int result = api->moby_deletion(slot, out);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
Results and errors
int camera_position(float[3] out);
// how a call looks
int result = api->camera_position(out);out: the level's, also under a pause menu whose own camera is no place in the level.Parameters
out (float[3])Returns
Results and errors
int moby_run(int slot, openrac_moby_run* out);
// how a call looks
int result = api->moby_run(slot, out);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
Results and errors
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);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
uint32_t take_developer_menu_action(openrac_mod* mod);
// how a call looks
uint32_t result = api->take_developer_menu_action(mod);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.Returns
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);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
intconst char* data_dir(openrac_mod* mod);
// how a call looks
const char* result = api->data_dir(mod);Parameters
mod (openrac_mod*): your mod's handle, as openrac_mod_load got it.Returns
const char*int save_slot_current();
// how a call looks
int result = api->save_slot_current();Returns
inttypedef void (*openrac_mod_query_fn)(openrac_mod_info* info);info's api_major, api_minor, id and version. Called before the mod is loaded. Required; OPENRAC_MOD_DEFINE writes it.typedef int (*openrac_mod_load_fn)(const openrac_api* api, openrac_mod* mod);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.typedef void (*openrac_mod_unload_fn)(void);| Name | Value | What 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" |
#define OPENRAC_G(api, a) ((void*)((api)->memory + (openrac_gaddr)(a)))#define OPENRAC_GREF(api, T, a) (*(T*)OPENRAC_G(api, a))T.#define OPENRAC_MOD_DEFINE(mod_id, mod_version) ...mod_id and mod_version are string literals, the manifest's.#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 */
} *
* 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.11.0. Edit this page or report a problem.