Bridge schema reference#
ABI version 0.9. All structs are little-endian and naturally aligned, with every padding byte declared.
Constants#
| Name |
Value |
Meaning |
bridge_magic |
0x42464249 |
'IBFB' read as a little-endian u32 |
directory_magic |
0x44464249 |
'IBFD' read as a little-endian u32 |
max_clients |
8 |
Client table rows, and client blocks |
max_instances |
16 |
Hosts the directory lists at once |
max_regions |
8 |
Rows in a layout table |
ring_slots |
8 |
Snapshot ring slots |
ring_slot_size |
32768 |
Bytes per ring slot, its header included |
client_block_size |
0x10000 |
Bytes per client block |
log_ring_capacity |
0x10000 |
Bytes of entries in the host log ring |
log_queue_capacity |
16384 |
Bytes of entries in a client's log queue |
client_name_len |
32 |
Bytes in a client name, including the terminating NUL |
version_len |
32 |
Bytes in a host version string, including the terminating NUL |
log_source_max |
32 |
Bytes of a log entry's source |
log_text_max |
968 |
Bytes of a log entry's text; longer messages are split |
no_pad |
255 |
No virtual pad bound; in pad_owner, a bot pad nobody owns |
pad_not_bot |
254 |
In pad_owner: the slot is not a bot pad (input.bot_pads), so no client can bind it |
command_line_max |
1024 |
Bytes of a command line a client may send, its terminating NUL included |
bot_block_size |
0x49000 |
Bytes per bot block: a client's draw lists, parameters and stats (ABI 0.5) |
draw_buffers |
3 |
Draw lists per client: the client's, the shared one and the host's (a triple buffer) |
draw_max_commands |
2048 |
Commands in one draw list; more are dropped and the list marked overflow |
draw_payload_max |
16384 |
Bytes of one draw list's payload: points, text and heatmap cells |
max_params |
32 |
Parameters a client may declare |
param_name_len |
32 |
Bytes in a parameter name, including the terminating NUL |
param_help_len |
96 |
Bytes in a parameter's help text, including the terminating NUL |
param_options_len |
88 |
Bytes of an enum parameter's options, separated by '|', including the terminating NUL |
max_stats |
64 |
Stats a client may publish |
stat_name_len |
24 |
Bytes in a stat name, including the terminating NUL |
stat_text_len |
24 |
Bytes in a text stat, including the terminating NUL |
max_players |
4 |
Player slots, and virtual pads |
max_ships |
16 |
Ship capacity of a snapshot |
max_projectiles |
128 |
Projectile capacity of a snapshot |
max_pickups |
64 |
Pickup capacity of a snapshot |
max_events |
32 |
Event ring capacity |
board_max_dim |
64 |
Largest supported board width or height, in tiles |
board_max_tiles |
4096 |
board_max_dim squared |
max_extras |
64 |
Custom probe entries per snapshot |
extras_blob_max |
16384 |
Bytes of custom probe data per snapshot |
extra_name_len |
24 |
Bytes in a probe name, including the terminating NUL |
snapshot_magic |
0x53464249 |
'IBFS' read as a little-endian u32 |
no_player |
255 |
Empty player slot, or unknown owner |
max_pickup_spawns |
16 |
Pickup spawn points a snapshot lists (ABI 0.6) |
max_spawn_markers |
16 |
Arcade spawn markers a snapshot lists (ABI 0.9) |
rec_magic |
0x52464249 |
'IBFR' read as a little-endian u32: a recording's first bytes |
rec_chunk_magic |
0x43464249 |
'IBFC': a chunk header |
rec_footer_magic |
0x58464249 |
'IBFX': the footer |
rec_trailer_magic |
0x45464249 |
'IBFE': the trailer, the file's last 16 bytes |
rec_format |
1 |
The .ibfrec layout version |
rec_chunk_ticks |
300 |
Tick records per chunk (5 s at 60 Hz) |
Enums#
bridge_region (enum, u32)#
Rows of the bridge header's layout table
| Name |
Value |
Meaning |
header |
0 |
|
snapshot_ring |
1 |
|
client_blocks |
2 |
|
log_ring |
3 |
|
bot_blocks |
4 |
One bot block per client row: its draw lists, parameters and stats (ABI 0.5) |
bot_region (enum, u32)#
Rows of a bot block's layout table
| Name |
Value |
Meaning |
draw |
0 |
A draw_header, then draw_buffers draw lists (design 8.4) |
params |
1 |
A params_header, then max_params param_def, then max_params param_value (design 8.6) |
stats |
2 |
A stats_header, then max_stats stat_entry (design 8.6) |
draw_list_flags (flags, u32)#
| Name |
Value |
Meaning |
overflow |
0x1 |
Commands or payload did not fit and were dropped |
param_kind (enum, u8)#
What a parameter's control is (design 8.6)
| Name |
Value |
Meaning |
bool |
0 |
A checkbox: value 0 or 1 |
int |
1 |
A whole number between min and max |
float |
2 |
A number between min and max |
enum |
3 |
One of the options: value is its index |
button |
4 |
A button: value counts the presses |
color |
5 |
A colour: value is its RGBA as a u32 (R in the low byte) |
stat_kind (enum, u8)#
| Name |
Value |
Meaning |
number |
0 |
|
text |
1 |
|
stat_flags (flags, u8)#
| Name |
Value |
Meaning |
plot |
0x1 |
Keep a sparkline of the last 300 values |
client_region (enum, u32)#
Rows of a client block's layout table
| Name |
Value |
Meaning |
log_queue |
0 |
The client's log entries, for the host to drain |
pad_input |
1 |
The client's virtual pad: one pad_input record, which the host reads on each XInput poll |
mailbox |
2 |
Command requests from the client and their results from the host |
command_status (enum, u32)#
How the host answered a command request
| Name |
Value |
Meaning |
none |
0 |
Not answered yet |
ok |
1 |
The command ran and succeeded |
failed |
2 |
The command ran and failed, or there is no such command |
refused |
3 |
The host takes no commands, or the request was malformed |
control_stick (enum, u8)#
The stick that moves a ship (design 7.7)
| Name |
Value |
Meaning |
left_stick |
0 |
|
right_stick |
1 |
|
dpad |
2 |
|
run_mode (enum, u8)#
Whether the game waits for its bots (design 4.5; ABI 0.7)
| Name |
Value |
Meaning |
realtime |
0 |
The game never waits: each poll reads the newest input |
lockstep |
1 |
After each tick the host waits until every bot pad answers it, up to lockstep_timeout_ms |
sim_state (enum, u8)#
Whether the game's steps run (design 4.5; ABI 0.7)
| Name |
Value |
Meaning |
running |
0 |
|
paused |
1 |
sim.pause: the steps are skipped, the game still draws; sim.step lets some through |
client_state (enum, u32)#
A client table row's state (design 6.5)
| Name |
Value |
Meaning |
free |
0 |
|
claimed |
1 |
A client won the row and is filling it in |
active |
2 |
|
closing |
3 |
The client said goodbye; the host frees the row |
client_caps (flags, u32)#
What a client takes part in
| Name |
Value |
Meaning |
ticks |
0x1 |
Set my tick event after each publish |
tool |
0x2 |
A tool (the CLI), not a bot: not counted among the bots |
remote |
0x4 |
Set by the host's TCP proxy for a client over TCP (design 6.6): the files its commands write stay in ibf\remote (ABI 0.8) |
host_state (enum, u32)#
| Name |
Value |
Meaning |
starting |
0 |
|
running |
1 |
|
exiting |
2 |
The game is closing; clients should disconnect |
instance_state (enum, u32)#
A directory row's state
| Name |
Value |
Meaning |
free |
0 |
|
claimed |
1 |
A host won the row and is filling it in |
live |
2 |
|
log_entry_kind (enum, u8)#
| Name |
Value |
Meaning |
record |
0 |
|
padding |
1 |
Fills the ring to its end; the next entry starts at offset 0 |
draw_op (enum, u8)#
| Name |
Value |
Meaning |
line |
0 |
|
polyline |
1 |
|
rect |
2 |
|
rect_fill |
3 |
|
circle |
4 |
|
circle_fill |
5 |
|
text |
6 |
|
arrow |
7 |
|
tile_fill |
8 |
|
tile_outline |
9 |
|
heatmap |
10 |
|
draw_space (enum, u8)#
| Name |
Value |
Meaning |
world |
0 |
Tiles, origin at the board centre, +Y up |
tile |
1 |
Integer tile coordinates |
screen |
2 |
Back-buffer pixels |
screen_norm |
3 |
0..1 across the back buffer |
draw_layer (enum, u8)#
| Name |
Value |
Meaning |
below_panels |
0 |
|
above_panels |
1 |
|
draw_flags (flags, u8)#
| Name |
Value |
Meaning |
antialias |
0x1 |
|
fade |
0x2 |
Fade out over the list's time to live |
closed |
0x4 |
polyline: join the last point to the first (ABI 0.5) |
centered |
0x8 |
text: centred on its point instead of hanging from it (ABI 0.5) |
heatmap_palette (enum, u8)#
How a heatmap's values become colours (ABI 0.5)
| Name |
Value |
Meaning |
tint |
0 |
The command's colour, its alpha scaled by the value |
inferno |
1 |
Black through red and orange to yellow |
viridis |
2 |
Purple through teal to yellow |
coolwarm |
3 |
Blue through white to red: 128 is white |
greys |
4 |
Black to white |
heatmap_flags (flags, u8)#
| Name |
Value |
Meaning |
zero_clear |
0x1 |
A value of 0 draws nothing |
log_level (enum, u8)#
Log severity, lowest first
| Name |
Value |
Meaning |
trace |
0 |
|
debug |
1 |
|
info |
2 |
|
warn |
3 |
|
error |
4 |
|
XINPUT_GAMEPAD_* button bits
| Name |
Value |
Meaning |
dpad_up |
0x1 |
|
dpad_down |
0x2 |
|
dpad_left |
0x4 |
|
dpad_right |
0x8 |
|
start |
0x10 |
|
back |
0x20 |
|
left_thumb |
0x40 |
|
right_thumb |
0x80 |
|
left_shoulder |
0x100 |
|
right_shoulder |
0x200 |
|
a |
0x1000 |
|
b |
0x2000 |
|
x |
0x4000 |
|
y |
0x8000 |
|
| Name |
Value |
Meaning |
connected |
0x1 |
Set on every write; a record without it reads neutral (bot pads stay connected: design 7.8) |
rec_record_kind (enum, u8)#
| Name |
Value |
Meaning |
keyframe |
1 |
The snapshot as published |
delta |
2 |
The snapshot XORed with the record before it |
rec_pad_source (enum, u8)#
Who answered a pad's last poll
| Name |
Value |
Meaning |
none |
0 |
Not polled yet, or not connected |
bot |
1 |
A bridge client's pad record |
script |
2 |
The host: pad.* commands, or the Navigator |
real |
3 |
A real controller passed through |
phase (enum, u8)#
Game phase, mapped from the menu ID by the profile
| Name |
Value |
Meaning |
unknown |
0 |
|
boot |
1 |
Splash screens and loading |
menu |
2 |
|
lobby |
3 |
|
get_ready |
4 |
|
go |
5 |
|
playing |
6 |
|
dead |
7 |
The local player is dead but the round continues |
round_over |
8 |
|
game_over |
9 |
|
color (enum, u8)#
Ship or tile colour
| Name |
Value |
Meaning |
white |
0 |
|
black |
1 |
|
unknown |
255 |
|
tile (enum, u8)#
Board tile state
| Name |
Value |
Meaning |
white |
0 |
Walkable by black ships |
black |
1 |
Walkable by white ships |
none |
255 |
No tile: outside the playfield, or a hole in the map |
dir (enum, u8)#
One of the four shot directions
| Name |
Value |
Meaning |
none |
0 |
|
up |
1 |
|
down |
2 |
|
left |
3 |
|
right |
4 |
|
projectile_kind (enum, u8)#
| Name |
Value |
Meaning |
normal |
0 |
|
fast |
1 |
Red shot from a pickup |
unknown |
255 |
|
pickup_kind (enum, u8)#
| Name |
Value |
Meaning |
fast_shots |
0 |
Grants red shots; amount says how many |
block_eat |
1 |
Square power-up: 4 s of breaking the cells the ship runs into, and of x1.5 speed |
unknown |
255 |
|
shield |
2 |
Shield power-up: 10 s in which a hit breaks the shield instead of the ship (ABI 0.6) |
game_type (enum, u8)#
Which game is running (ABI 0.6)
| Name |
Value |
Meaning |
none |
0 |
No game yet: the menus at start-up (after a game they keep its type, with no map) |
versus |
1 |
|
arcade |
2 |
|
unknown |
255 |
|
round_state (enum, u8)#
Where the round is (ABI 0.6)
| Name |
Value |
Meaning |
none |
0 |
Not started: get ready, or no game |
playing |
1 |
|
decided |
2 |
A team won (or, in arcade, the last life went); the round is ending |
unknown |
255 |
|
spawn_state (enum, u8)#
A pickup spawn point's state (ABI 0.6)
| Name |
Value |
Meaning |
due |
0 |
Spawns on the next step |
out |
1 |
Its pickup is on the board |
waiting |
2 |
Spawns in time_left seconds |
enemy_kind (enum, u8)#
What an arcade enemy does (ABI 0.9)
| Name |
Value |
Meaning |
unknown |
0 |
|
smash |
1 |
Breaks the cells it runs into |
shoot |
2 |
Fires at the players |
smash_shoot |
3 |
Both |
event_kind (enum, u16)#
Events derived by diffing consecutive ticks (design section 5.5)
| Name |
Value |
Meaning |
none |
0 |
Unused ring slot |
menu_changed |
1 |
a = old menu ID, b = new menu ID |
match_started |
2 |
|
round_started |
3 |
a = round number |
round_ended |
4 |
a = winner player ID or -1 |
match_ended |
5 |
a = winner player ID, or -1 for no winner (a tie, or a match abandoned for a menu) |
ship_spawned |
6 |
|
ship_died |
7 |
|
shot_fired |
8 |
a = dir, b = 1 if fast |
pickup_spawned |
9 |
a = pickup_kind, b = amount |
pickup_taken |
10 |
a = pickup_kind, b = amount |
score_changed |
11 |
a = old score, b = new score |
invalid_reason (enum, u16)#
Why the latest tick produced no valid snapshot
| Name |
Value |
Meaning |
none |
0 |
|
no_profile |
1 |
No profile matches the game executable |
root_unreadable |
2 |
|
path_fault |
3 |
A pointer path hit an unreadable or implausible pointer |
list_invalid |
4 |
An entity list header failed its checks |
board_out_of_range |
5 |
|
count_out_of_range |
6 |
|
non_finite_value |
7 |
|
read_fault |
8 |
An access violation was caught while reading |
torn_read |
9 |
Memory changed under the build; the retry did not help |
profile_error |
10 |
A profile loaded but a required path is unresolved |
state_disabled |
11 |
The state module is disabled |
tick_source (enum, u8)#
Which hook built the snapshot (design section 4.5)
| Name |
Value |
Meaning |
present |
0 |
The Present fallback: one tick per frame |
sim_step |
1 |
The game's simulation step |
snapshot_flags (flags, u32)#
| Name |
Value |
Meaning |
valid |
0x1 |
|
in_match |
0x2 |
|
truncated |
0x4 |
A capacity was exceeded; the tail was dropped |
lockstep |
0x8 |
|
sim_paused |
0x10 |
|
overlay_focused |
0x20 |
The overlay's console is open and takes the user's typing |
stale |
0x40 |
The body is from an earlier tick; only the header is new |
ship_flags (flags, u16)#
| Name |
Value |
Meaning |
shield |
0x1 |
|
block_eat |
0x2 |
|
charging |
0x4 |
|
moving |
0x8 |
|
ship_valid (flags, u32)#
| Name |
Value |
Meaning |
pos |
0x1 |
|
vel |
0x2 |
|
last_shot_pos |
0x4 |
|
reload_progress |
0x8 |
|
reload_time |
0x10 |
|
time_alive |
0x20 |
|
time_since_shot |
0x40 |
|
score |
0x80 |
|
multiplier |
0x100 |
|
flags |
0x200 |
|
player_id |
0x400 |
|
color |
0x800 |
|
ammo |
0x1000 |
|
max_ammo |
0x2000 |
|
fast_ammo |
0x4000 |
|
charge_dir |
0x8000 |
|
Element type of a custom probe
| Name |
Value |
Meaning |
raw |
0 |
|
u8 |
1 |
|
i8 |
2 |
|
u16 |
3 |
|
i16 |
4 |
|
u32 |
5 |
|
i32 |
6 |
|
u64 |
7 |
|
i64 |
8 |
|
f32 |
9 |
|
f64 |
10 |
|
Structs#
region_entry (8 bytes, align 4)#
One row of a layout table; size 0 means the region is absent
| Offset |
Field |
Type |
Meaning |
0x0000 |
offset |
u32 |
From the start of the bridge, or of the client block |
0x0004 |
size |
u32 |
|
client_entry (128 bytes, align 8)#
One row of the client table. The client claims it by compare-and-swap from free; the host frees it.
| Offset |
Field |
Type |
Meaning |
0x0000 |
state |
client_state |
|
0x0004 |
generation |
u32 |
Bumped by each claim: a client that no longer finds its own generation was disconnected |
0x0008 |
pid |
u32 |
|
0x000C |
caps |
client_caps |
|
0x0010 |
heartbeat_ns |
u64 |
Host clock; the client writes it at least every 100 ms, and one older than 1 s counts as hung |
0x0018 |
connected_ns |
u64 |
Host clock at the claim |
0x0020 |
pad |
u8 |
The virtual pad this client bound, or no_pad; the host goes by pad_owner |
0x0021 |
_pad33 |
u8[3] |
|
0x0024 |
waiting |
u32 |
1 while the client sleeps on its tick event: the host sets the event only then |
0x0028 |
name |
char[client_name_len] |
|
0x0048 |
_reserved |
u8[56] |
|
controls (16 bytes, align 2)#
The pad input for each game action (design 7.7): what the SDKs turn actions into, and what the Navigator presses
| Offset |
Field |
Type |
Meaning |
0x0000 |
move |
control_stick |
|
0x0001 |
min_press_ticks |
u8 |
Hold a tap for at least this many ticks (input.min_press_ticks) |
0x0002 |
shoot_up |
pad_buttons |
|
0x0004 |
shoot_down |
pad_buttons |
|
0x0006 |
shoot_left |
pad_buttons |
|
0x0008 |
shoot_right |
pad_buttons |
|
0x000A |
pause |
pad_buttons |
|
0x000C |
confirm |
pad_buttons |
Menu confirm |
0x000E |
back |
pad_buttons |
Menu back |
The first bytes of the bridge. Written by the host, except the client table rows and the commands' event.
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
bridge_magic |
0x0004 |
abi_major |
u16 |
|
0x0006 |
abi_minor |
u16 |
|
0x0008 |
header_size |
u32 |
sizeof(bridge_header) as the host built it |
0x000C |
total_size |
u32 |
Bytes in the whole bridge |
0x0010 |
host_pid |
u32 |
|
0x0014 |
host_generation |
u32 |
Changes when the host reloads; the old host's clients find their rows freed and connect again |
0x0018 |
host_state |
host_state |
|
0x001C |
region_count |
u32 |
|
0x0020 |
host_version |
char[version_len] |
|
0x0040 |
regions |
region_entry[max_regions] |
Indexed by bridge_region |
0x0080 |
clock_mono_ns |
u64 |
A host clock reading (QueryPerformanceCounter in ns)... |
0x0088 |
clock_unix_ns |
i64 |
...and the Unix time then: unix = clock_unix_ns + (t - clock_mono_ns) |
0x0090 |
ring_slots |
u32 |
|
0x0094 |
ring_slot_size |
u32 |
|
0x0098 |
max_clients |
u32 |
|
0x009C |
client_block_size |
u32 |
|
0x00A0 |
client_entry_size |
u32 |
|
0x00A4 |
pad_owner |
u8[max_players] |
Per pad: the client row that owns it, no_pad for a free bot pad, or pad_not_bot. Clients bind by compare-and-swap of the four bytes as one u32 |
0x00A8 |
_pad168 |
u8[24] |
|
0x00C0 |
snapshot_seq |
u64 |
Snapshots published; the newest is in slot (snapshot_seq - 1) % ring_slots. On its own cache line |
0x00C8 |
_pad200 |
u8[56] |
|
0x0100 |
clients |
client_entry[max_clients] |
|
0x0500 |
controls |
controls |
The pad input for each game action, from ibf.toml's [controls] (ABI 0.4) |
0x0510 |
run_mode |
run_mode |
ABI 0.7: in lockstep the host waits for each tick's answers, and a client sets the input event after writing its pad |
0x0511 |
sim_state |
sim_state |
ABI 0.7: running, or paused by sim.pause |
0x0512 |
_pad1298 |
u8[2] |
|
0x0514 |
lockstep_timeout_ms |
u32 |
ABI 0.7: how long the host waits for a tick's answers in lockstep |
The start of a client's draw region. The lists follow it, buffer_size bytes apart
| Offset |
Field |
Type |
Meaning |
0x0000 |
state |
u32 |
Bits 0-1: the shared list's index; bit 2: it is fresh (a list waits for the host). Swapped whole by both sides |
0x0004 |
buffers |
u32 |
Host: draw_buffers |
0x0008 |
buffer_size |
u32 |
Host: bytes from one list's header to the next's |
0x000C |
max_commands |
u32 |
Host: commands a list holds |
0x0010 |
max_payload |
u32 |
Host: payload bytes a list holds |
0x0014 |
published |
u32 |
Client: lists published |
0x0018 |
_pad24 |
u8[40] |
|
One draw list: this header, max_commands draw_cmd, then max_payload bytes of payload
| Offset |
Field |
Type |
Meaning |
0x0000 |
seq |
u32 |
Client: the list's number |
0x0004 |
count |
u32 |
Commands in the list |
0x0008 |
payload_len |
u32 |
Bytes of payload in use |
0x000C |
ttl_ms |
u32 |
Shown until replaced or this long after the host takes it; 0 means 500 |
0x0010 |
flags |
draw_list_flags |
|
0x0014 |
dropped |
u32 |
Commands dropped because the list was full |
0x0018 |
for_tick |
u64 |
The tick the list was drawn for |
0x0020 |
_pad32 |
u8[32] |
|
The start of a client's parameters: the client's definitions, then the host's values
| Offset |
Field |
Type |
Meaning |
0x0000 |
defs_seq |
u32 |
Client: odd while it writes the definitions |
0x0004 |
def_count |
u32 |
Client: definitions in use |
0x0008 |
values_seq |
u32 |
Host: odd while it writes the values |
0x000C |
changes |
u32 |
Host: bumped with every change of a value |
0x0010 |
max_params |
u32 |
Host: definitions the area holds |
0x0014 |
_pad20 |
u8[44] |
|
param_def (256 bytes, align 8)#
One parameter a client declares (design 8.6). The host shows it as a control in the Bots panel
| Offset |
Field |
Type |
Meaning |
0x0000 |
name |
char[param_name_len] |
|
0x0020 |
kind |
param_kind |
|
0x0021 |
option_count |
u8 |
enum: options in options |
0x0022 |
_pad34 |
u8[6] |
|
0x0028 |
default_value |
f64 |
|
0x0030 |
min |
f64 |
int and float |
0x0038 |
max |
f64 |
|
0x0040 |
step |
f64 |
int and float: the control's step; 0 for none |
0x0048 |
help |
char[param_help_len] |
|
0x00A8 |
options |
char[param_options_len] |
enum: the options' names, separated by '|' |
param_value (16 bytes, align 8)#
One parameter's value, written by the host
| Offset |
Field |
Type |
Meaning |
0x0000 |
value |
f64 |
|
0x0008 |
changes |
u32 |
Bumped by every change, so a button's presses and a set to the same value count |
0x000C |
_pad12 |
u8[4] |
|
The start of a client's stats. The client writes both halves: the stats under seq, and its tick facts, which ibf_client keeps
| Offset |
Field |
Type |
Meaning |
0x0000 |
seq |
u32 |
Client: odd while it writes the stats |
0x0004 |
count |
u32 |
Client: stats in use |
0x0008 |
max_stats |
u32 |
Host: entries the area holds |
0x000C |
_pad12 |
u8[4] |
|
0x0010 |
ticks |
u64 |
Client: snapshots it waited for and got |
0x0018 |
skipped |
u64 |
Client: publications it missed (latest wins) |
0x0020 |
wake_p50_us |
f32 |
Client: publish-to-wake over its last ticks, median |
0x0024 |
wake_p99_us |
f32 |
|
0x0028 |
_pad40 |
u8[24] |
|
stat_entry (64 bytes, align 8)#
One stat: a number or a short text
| Offset |
Field |
Type |
Meaning |
0x0000 |
name |
char[stat_name_len] |
|
0x0018 |
kind |
stat_kind |
|
0x0019 |
flags |
stat_flags |
|
0x001A |
_pad26 |
u8[6] |
|
0x0020 |
value |
f64 |
number |
0x0028 |
text |
char[stat_text_len] |
text |
A client's command mailbox: one request at a time. The request text follows the header, then the response text
| Offset |
Field |
Type |
Meaning |
0x0000 |
request_seq |
u32 |
Client: bumped (release) after each request's text and length are written |
0x0004 |
request_len |
u32 |
Client: bytes of the request, at most request_capacity - 1 |
0x0008 |
response_seq |
u32 |
Host: the request_seq answered, stored (release) after the rest |
0x000C |
status |
command_status |
Host |
0x0010 |
response_len |
u32 |
Host: bytes of the result in the response area |
0x0014 |
response_total |
u32 |
Host: bytes of the whole result; more than response_len when it was cut |
0x0018 |
request_capacity |
u32 |
Host: bytes of the request area |
0x001C |
response_capacity |
u32 |
Host: bytes of the response area, which follows the request area |
0x0020 |
_pad32 |
u8[32] |
|
The start of a snapshot ring slot; the snapshot and its extras follow it
| Offset |
Field |
Type |
Meaning |
0x0000 |
seq |
u32 |
Odd while the host writes the slot |
0x0004 |
size |
u32 |
Payload bytes: the snapshot, then its extras |
0x0008 |
publish_seq |
u64 |
The snapshot_seq this slot was published as |
0x0010 |
tick |
u64 |
|
0x0018 |
publish_ns |
u64 |
Host clock when the payload was complete |
0x0020 |
_pad32 |
u8[32] |
|
log_entry (40 bytes, align 8)#
One log entry in the host log ring or a client's log queue; the source, then the text, follow it
| Offset |
Field |
Type |
Meaning |
0x0000 |
size |
u16 |
Bytes of the entry with its source and text, a multiple of 8 |
0x0002 |
kind |
log_entry_kind |
|
0x0003 |
level |
log_level |
|
0x0004 |
source_len |
u8 |
|
0x0005 |
_pad5 |
u8 |
|
0x0006 |
text_len |
u16 |
|
0x0008 |
thread |
u32 |
|
0x000C |
_pad12 |
u8[4] |
|
0x0010 |
seq |
u64 |
Entries written before this one |
0x0018 |
time_ns |
u64 |
Host clock |
0x0020 |
tick |
u64 |
|
The host log ring: one writer (the host's log drain), any number of readers, oldest overwritten
| Offset |
Field |
Type |
Meaning |
0x0000 |
write_pos |
u64 |
Bytes ever written; the next entry starts at write_pos % capacity |
0x0008 |
tail_pos |
u64 |
The oldest whole entry; a reader behind it was lapped |
0x0010 |
capacity |
u32 |
|
0x0014 |
_pad20 |
u8[4] |
|
0x0018 |
entries |
u64 |
Entries written |
0x0020 |
_pad32 |
u8[32] |
|
A client's log queue: the client writes, the host reads. Full means the entry is dropped and counted
| Offset |
Field |
Type |
Meaning |
0x0000 |
write_pos |
u64 |
Client: bytes ever written |
0x0008 |
dropped |
u64 |
Client: entries that did not fit |
0x0010 |
capacity |
u32 |
|
0x0014 |
_pad20 |
u8[12] |
|
0x0020 |
read_pos |
u64 |
Host: bytes consumed |
0x0028 |
_pad40 |
u8[24] |
|
The start of a client block; the host writes it
| Offset |
Field |
Type |
Meaning |
0x0000 |
size |
u32 |
|
0x0004 |
region_count |
u32 |
|
0x0008 |
regions |
region_entry[max_regions] |
Indexed by client_region |
directory_entry (64 bytes, align 8)#
One running host in the directory
| Offset |
Field |
Type |
Meaning |
0x0000 |
state |
instance_state |
|
0x0004 |
pid |
u32 |
|
0x0008 |
process_time |
u64 |
The host process's creation time (FILETIME): tells a reused PID apart, and orders instances |
0x0010 |
abi_major |
u16 |
|
0x0012 |
abi_minor |
u16 |
|
0x0014 |
_pad20 |
u8[4] |
|
0x0018 |
host_version |
char[version_len] |
|
0x0038 |
_pad56 |
u8[8] |
|
Local\ibf.directory: the hosts running in this logon session
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
directory_magic |
0x0004 |
entry_count |
u32 |
|
0x0008 |
entry_size |
u32 |
|
0x000C |
_pad12 |
u8[52] |
|
0x0040 |
entries |
directory_entry[max_instances] |
|
The start of a heatmap's payload; width x height u8 values follow, row by row from the bottom row (ABI 0.5)
| Offset |
Field |
Type |
Meaning |
0x0000 |
palette |
heatmap_palette |
|
0x0001 |
flags |
heatmap_flags |
|
0x0002 |
_pad2 |
u8[6] |
|
draw_cmd (36 bytes, align 4)#
One drawing (design 8.4). By op, in the command's space:
line, arrow: from (a, b) to (c, d), thickness pixels wide.
polyline: the payload's points (vec2 each); flags.closed joins the ends.
rect, rect_fill: the corners (a, b) and (c, d).
circle, circle_fill: centre (a, b), radius c (screen_norm: a fraction of the height).
text: the payload's UTF-8 hanging from (a, b), or centred on it (flags.centered); c is the size in pixels, 0 for the overlay's.
tile_fill, tile_outline: tile (a, b), c x d tiles (0 counts as 1), whatever the space.
heatmap: c x d cells from tile (a, b), the lower-left; the payload is a heatmap_header, then the cells. The colour's alpha is the opacity.
| Offset |
Field |
Type |
Meaning |
0x0000 |
op |
draw_op |
|
0x0001 |
space |
draw_space |
|
0x0002 |
layer |
draw_layer |
|
0x0003 |
flags |
draw_flags |
|
0x0004 |
color |
u32 |
RGBA, byte order R, G, B, A (ImGui IM_COL32) |
0x0008 |
thickness |
f32 |
Pixels |
0x000C |
a |
f32 |
|
0x0010 |
b |
f32 |
|
0x0014 |
c |
f32 |
|
0x0018 |
d |
f32 |
|
0x001C |
payload_off |
u32 |
Points, UTF-8 text or heatmap cells in the list's payload area |
0x0020 |
payload_len |
u16 |
|
0x0022 |
_pad34 |
u8[2] |
|
vec2 (8 bytes, align 4)#
2-D vector in world units (tiles): origin at the board centre, +Y up
| Offset |
Field |
Type |
Meaning |
0x0000 |
x |
f32 |
|
0x0004 |
y |
f32 |
|
One virtual pad. Written under a seqlock: seq is odd while the client writes. A record whose seq stays the same for input.timeout_ms reads neutral
| Offset |
Field |
Type |
Meaning |
0x0000 |
seq |
u32 |
|
0x0004 |
flags |
pad_input_flags |
|
0x0008 |
for_tick |
u64 |
The tick of the snapshot this input answers; the host counts the lag, and lockstep (M6) waits for it |
0x0010 |
lx |
i16 |
-32768..32767, +Y up |
0x0012 |
ly |
i16 |
|
0x0014 |
rx |
i16 |
|
0x0016 |
ry |
i16 |
|
0x0018 |
buttons |
pad_buttons |
|
0x001A |
lt |
u8 |
|
0x001B |
rt |
u8 |
|
0x001C |
_pad28 |
u8[4] |
|
rec_pad (24 bytes, align 8)#
One pad as the game last polled it before a tick
| Offset |
Field |
Type |
Meaning |
0x0000 |
for_tick |
u64 |
The tick a bot's record answered; 0 when no bot answered the poll |
0x0008 |
lx |
i16 |
|
0x000A |
ly |
i16 |
|
0x000C |
rx |
i16 |
|
0x000E |
ry |
i16 |
|
0x0010 |
buttons |
pad_buttons |
|
0x0012 |
lt |
u8 |
|
0x0013 |
rt |
u8 |
|
0x0014 |
source |
rec_pad_source |
|
0x0015 |
owner |
u8 |
A bot pad's owner (its client row), or no_pad |
0x0016 |
_pad22 |
u8[2] |
|
One tick record; the snapshot and its extras follow it
| Offset |
Field |
Type |
Meaning |
0x0000 |
size |
u32 |
Bytes of the record: this header and data_size |
0x0004 |
data_size |
u32 |
Bytes of the snapshot and its extras |
0x0008 |
kind |
rec_record_kind |
|
0x0009 |
_pad9 |
u8[7] |
|
0x0010 |
tick |
u64 |
|
0x0018 |
frame |
u64 |
|
0x0020 |
host_time_ns |
u64 |
The host clock when the tick was published |
0x0028 |
pads |
rec_pad[max_players] |
What the game last polled from each pad before this tick |
The first 512 bytes of a recording
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
rec_magic |
0x0004 |
format |
u16 |
rec_format |
0x0006 |
header_size |
u16 |
sizeof(rec_file_header) |
0x0008 |
schema_major |
u16 |
The snapshot's ABI |
0x000A |
schema_minor |
u16 |
|
0x000C |
snapshot_size |
u32 |
sizeof(snapshot) for the host that recorded |
0x0010 |
chunk_ticks |
u32 |
rec_chunk_ticks |
0x0014 |
host_pid |
u32 |
|
0x0018 |
start_unix_ns |
i64 |
When recording started |
0x0020 |
start_mono_ns |
u64 |
The host clock then |
0x0028 |
controls |
controls |
The pad input each game action mapped to |
0x0038 |
run_mode |
run_mode |
When recording started |
0x0039 |
bot_pads |
u8 |
Bit n: pad n was a bot pad |
0x003A |
_pad58 |
u8[2] |
|
0x003C |
lockstep_timeout_ms |
u32 |
|
0x0040 |
host_version |
char[version_len] |
|
0x0060 |
profile_name |
char[64] |
|
0x00A0 |
exe_sha256 |
char[80] |
The game executable's SHA-256 in hex |
0x00F0 |
note |
char[256] |
Free text: what was recorded |
0x01F0 |
_pad496 |
u8[16] |
|
One chunk: its zlib stream follows
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
rec_chunk_magic |
0x0004 |
stored_size |
u32 |
Bytes of the zlib stream |
0x0008 |
raw_size |
u32 |
Bytes of tick records it inflates to |
0x000C |
tick_count |
u32 |
|
0x0010 |
first_tick |
u64 |
|
0x0018 |
last_tick |
u64 |
|
rec_chunk_entry (24 bytes, align 8)#
The footer's index of a chunk
| Offset |
Field |
Type |
Meaning |
0x0000 |
offset |
u64 |
Of its rec_chunk_header, from the file's start |
0x0008 |
first_tick |
u64 |
|
0x0010 |
last_tick |
u64 |
|
rec_mark (16 bytes, align 8)#
A match or round boundary, from the snapshots' events
| Offset |
Field |
Type |
Meaning |
0x0000 |
tick |
u64 |
|
0x0008 |
kind |
event_kind |
match_started, round_started, round_ended or match_ended |
0x000A |
_pad10 |
u8[2] |
|
0x000C |
a |
i32 |
The event's a: the round number, or the winner |
The footer: chunk_count rec_chunk_entry and mark_count rec_mark follow it
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
rec_footer_magic |
0x0004 |
chunk_count |
u32 |
|
0x0008 |
mark_count |
u32 |
|
0x000C |
dropped |
u32 |
Ticks the recorder could not keep up with |
0x0010 |
ticks |
u64 |
Tick records in the file |
0x0018 |
first_tick |
u64 |
|
0x0020 |
last_tick |
u64 |
|
0x0028 |
end_unix_ns |
i64 |
When recording stopped |
rec_trailer (16 bytes, align 8)#
A recording's last 16 bytes
| Offset |
Field |
Type |
Meaning |
0x0000 |
footer_offset |
u64 |
Of the rec_footer, from the file's start |
0x0008 |
_pad8 |
u8[4] |
|
0x000C |
magic |
u32 |
rec_trailer_magic |
| Offset |
Field |
Type |
Meaning |
0x0000 |
magic |
u32 |
snapshot_magic |
0x0004 |
schema_major |
u16 |
|
0x0006 |
schema_minor |
u16 |
|
0x0008 |
size |
u32 |
Bytes in this snapshot, including extras |
0x000C |
flags |
snapshot_flags |
|
0x0010 |
frame |
u64 |
Present calls since start-up |
0x0018 |
tick |
u64 |
Simulation steps since start-up (equals frame in fallback mode) |
0x0020 |
host_time_ns |
u64 |
Monotonic host clock |
0x0028 |
game_time |
f32 |
Round time in seconds: counts during play, from 0 at each round start |
0x002C |
invalid_reason |
invalid_reason |
|
0x002E |
tick_source |
tick_source |
Which hook built the snapshot |
0x002F |
_pad47 |
u8 |
|
game (24 bytes, align 4)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
menu_id |
i32 |
Raw menu ID |
0x0004 |
menu_depth |
i32 |
|
0x0008 |
menu_item |
i32 |
Highlighted item; top item is 0 |
0x000C |
arcade_score |
i32 |
The arcade score (the screen's counts up to it) |
0x0010 |
lives |
i16 |
Lives left (arcade), the ship in play included: the squares on screen are lives - players |
0x0012 |
phase |
phase |
|
0x0013 |
paused |
u8 |
|
0x0014 |
focused |
u8 |
The game believes its window has focus |
0x0015 |
player_count |
u8 |
|
0x0016 |
_pad22 |
u8[2] |
|
board (4100 bytes, align 2)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
width |
u16 |
|
0x0002 |
height |
u16 |
|
0x0004 |
tiles |
tile[board_max_tiles] |
Row-major, index y * width + x, row 0 at the bottom |
ship (64 bytes, align 4)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
pos |
vec2 |
|
0x0008 |
vel |
vec2 |
Direction of movement: a unit vector while moving, zero when still (Inversus 1.2.0 keeps no speed) |
0x0010 |
last_shot_pos |
vec2 |
|
0x0018 |
reload_progress |
f32 |
|
0x001C |
reload_time |
f32 |
|
0x0020 |
time_alive |
f32 |
|
0x0024 |
time_since_shot |
f32 |
The charge timer: from 0 when a charge starts and when a shot fires, so it counts a held button |
0x0028 |
score |
i32 |
Versus: round wins of the ship's team |
0x002C |
multiplier |
i32 |
Already de-obfuscated |
0x0030 |
valid |
ship_valid |
One bit per field the profile marks confirmed |
0x0034 |
flags |
ship_flags |
|
0x0036 |
player_id |
u8 |
Player index 0-3 (Inversus 1.2.0 stores one bit per player), or no_player for an arcade enemy |
0x0037 |
color |
color |
|
0x0038 |
alive |
u8 |
|
0x0039 |
ammo |
u8 |
|
0x003A |
max_ammo |
u8 |
|
0x003B |
fast_ammo |
u8 |
Red shots held |
0x003C |
charge_dir |
dir |
|
0x003D |
_pad61 |
u8[3] |
|
projectile (24 bytes, align 4)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
pos |
vec2 |
|
0x0008 |
speed |
f32 |
|
0x000C |
time_alive |
f32 |
Seconds since it spawned |
0x0010 |
kind_raw |
i32 |
The game's own type value |
0x0014 |
dir |
dir |
|
0x0015 |
kind |
projectile_kind |
|
0x0016 |
owner |
u8 |
Player ID, or no_player when unknown |
0x0017 |
_pad23 |
u8 |
|
pickup (16 bytes, align 4)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
pos |
vec2 |
|
0x0008 |
time_alive |
f32 |
|
0x000C |
kind |
pickup_kind |
|
0x000D |
amount |
u8 |
|
0x000E |
_pad14 |
u8[2] |
|
event (24 bytes, align 8)#
| Offset |
Field |
Type |
Meaning |
0x0000 |
tick |
u64 |
Tick the event was detected on |
0x0008 |
a |
i32 |
|
0x000C |
b |
i32 |
|
0x0010 |
kind |
event_kind |
|
0x0012 |
player |
u8 |
Player ID, or no_player |
0x0013 |
_pad19 |
u8[5] |
|
match (20 bytes, align 4)#
The running match and its map (ABI 0.6)
| Offset |
Field |
Type |
Meaning |
0x0000 |
map_scale |
f32 |
The map's zoom: pixels per tile = ceil(round(available pixels x map_scale) / tiles) on the limiting axis |
0x0004 |
focus_hash |
u32 |
FNV-1a hash of the focused menu button's name (ResumeButton, RetryButton, ...); 0 when none |
0x0008 |
game_type |
game_type |
|
0x0009 |
map_set |
u8 |
0 tutorial, 1 arcade one player, 2 arcade two players, 3 versus 1v1, 4 versus 2v2; 255 none |
0x000A |
map_index |
u8 |
The map's index in its set (the map select's item); 255 none |
0x000B |
wrap |
u8 |
1 when ships and shots cross the board's edges to the other side |
0x000C |
wrap_shift_x |
i8 |
Columns a crossing of the top edge moves left by (of the bottom edge, right) |
0x000D |
wrap_shift_y |
i8 |
Rows a crossing of the right edge moves down by (of the left edge, up) |
0x000E |
rounds_to_win |
u8 |
Versus: round wins that take the match |
0x000F |
round_state |
round_state |
|
0x0010 |
round_winner |
u8 |
The team that won the round once round_state is decided; no_player otherwise |
0x0011 |
teams |
u8 |
Teams in the game: 2 in versus |
0x0012 |
pickup_spawn_count |
u8 |
Entries used in pickup_spawns |
0x0013 |
_pad19 |
u8 |
|
pickup_spawn (16 bytes, align 4)#
One of the map's pickup spawn points and its timer (ABI 0.6)
| Offset |
Field |
Type |
Meaning |
0x0000 |
pos |
vec2 |
The spawn cell's centre |
0x0008 |
time_left |
f32 |
Seconds until it spawns while waiting; 0 otherwise |
0x000C |
state |
spawn_state |
|
0x000D |
_pad13 |
u8[3] |
|
spawn_marker (16 bytes, align 4)#
Arcade: where an enemy is about to appear, marked on the board before it does (ABI 0.9)
| Offset |
Field |
Type |
Meaning |
0x0000 |
pos |
vec2 |
The marked cell's centre |
0x0008 |
time_left |
f32 |
Seconds until the enemy appears (the marker shows for 1.5 s) |
0x000C |
kind |
enemy_kind |
|
0x000D |
_pad13 |
u8[3] |
|
ship_ext (28 bytes, align 4)#
More of each ship, parallel to ships (ABI 0.6)
| Offset |
Field |
Type |
Meaning |
0x0000 |
velocity |
vec2 |
Tiles per second |
0x0008 |
block_eat_time |
f32 |
Seconds of block-eat left (arcade enemies keep it for good) |
0x000C |
speed_boost_time |
f32 |
Seconds of x1.5 speed left |
0x0010 |
shield_time |
f32 |
Seconds of shield left |
0x0014 |
points |
i16 |
Points for killing it (arcade enemies) |
0x0016 |
team |
u8 |
0 or 1: the team; a team walks on the cells of its own index (team 0 is black and walks on white) |
0x0017 |
parry_dir |
dir |
The direction of a charge started within 0.3 s: a shot coming the other way is absorbed |
0x0018 |
dying |
u8 |
1 once hit, while it explodes |
0x0019 |
_pad25 |
u8[3] |
|
projectile_ext (8 bytes, align 4)#
More of each projectile, parallel to projectiles (ABI 0.6)
| Offset |
Field |
Type |
Meaning |
0x0000 |
distance |
f32 |
Tiles flown since it spawned (a shot dies after 100) |
0x0004 |
team |
u8 |
The shooter's team: ships of the other team die in its tile |
0x0005 |
_pad5 |
u8[3] |
|
snapshot (12104 bytes, align 8)#
Fixed part of a snapshot. When extras_size > 0, an extras_header follows at extras_offset.
| Offset |
Field |
Type |
Meaning |
0x0000 |
header |
snapshot_header |
|
0x0030 |
game |
game |
|
0x0048 |
event_total |
u64 |
Events detected since start-up; event i is at events[i % max_events] |
0x0050 |
ship_count |
u8 |
|
0x0051 |
pickup_count |
u8 |
|
0x0052 |
projectile_count |
u16 |
|
0x0054 |
players |
u8[max_players] |
Index into ships per player slot, or no_player |
0x0058 |
extras_offset |
u32 |
From the start of the snapshot; 0 when there are no extras |
0x005C |
extras_size |
u32 |
|
0x0060 |
board |
board |
|
0x1064 |
ships |
ship[max_ships] |
|
0x1464 |
projectiles |
projectile[max_projectiles] |
|
0x2064 |
pickups |
pickup[max_pickups] |
|
0x2464 |
_pad9316 |
u8[4] |
|
0x2468 |
events |
event[max_events] |
|
0x2768 |
match |
match |
ABI 0.6: read it when header.schema_minor >= 6 |
0x277C |
pickup_spawns |
pickup_spawn[max_pickup_spawns] |
ABI 0.6 |
0x287C |
ships_ext |
ship_ext[max_ships] |
ABI 0.6: ships_ext[i] goes with ships[i] |
0x2A3C |
projectiles_ext |
projectile_ext[max_projectiles] |
ABI 0.6: projectiles_ext[i] goes with projectiles[i] |
0x2E3C |
_pad11836 |
u8[4] |
|
0x2E40 |
spawn_markers |
spawn_marker[max_spawn_markers] |
ABI 0.9: read them when header.schema_minor >= 9 |
0x2F40 |
spawn_marker_count |
u8 |
ABI 0.9: entries used in spawn_markers |
0x2F41 |
_pad12097 |
u8[7] |
|
One custom probe (design section 5.6)
| Offset |
Field |
Type |
Meaning |
0x0000 |
name |
char[extra_name_len] |
|
0x0018 |
offset |
u32 |
From the start of the extras blob |
0x001C |
size |
u32 |
Bytes |
0x0020 |
type |
extra_type |
|
0x0022 |
count |
u16 |
Elements: 1 per object, or one per entity for per-entity probes |
| Offset |
Field |
Type |
Meaning |
0x0000 |
entry_count |
u16 |
|
0x0002 |
_pad2 |
u8[2] |
|
0x0004 |
blob_size |
u32 |
|
0x0008 |
entries |
extra_entry[max_extras] |
|