Save states
C8B_API has no save-state functions. Save states are a plugin_call convention: the Lua functions plugin.saveState() and friends call reserved ids of your plugin. Implement these ids to support save states.
Contents
Reserved call ids
| Lua | Calls your plugin with | Your plugin returns |
|---|---|---|
plugin.saveState() → string or nil |
call(20), then call(22) |
20: size in bytes (> 0) of a state you wrote to your own buffer; 22: the address of that buffer |
plugin.loadState(s) → boolean |
call(21, ptr, len) |
0 = success |
plugin.fullSaveState() → string or nil |
call(30), then call(32) |
as 20/22, for the full state |
plugin.fullLoadState(s) → boolean |
call(31, ptr, len) |
0 = success |
The compact state (20/21/22) is meant for netplay synchronisation; the full state (30/31/32) is a complete snapshot.
Do not use ids 20, 21, 22, 30, 31 or 32 for anything else. If your plugin does not support save states, return -1 for these ids, and do not call the save-state functions from Lua for that plugin.
On the console the functions return nil or false when no plugin is ready.
Buffer lifetime
- Saving: Lua copies your buffer into a string during
call(22)/call(32). The buffer only needs to stay valid until that call returns. - Loading:
ptrpoints into the Lua string and is valid only duringcall(21)/call(31). Copy what you need.
Example
static uint8_t s_state[64 * 1024];
static int64_t s_state_size;
int64_t plugin_call(uint8_t id, const int64_t* args, uint8_t argc) {
switch (id) {
case 20: s_state_size = write_state(s_state, sizeof s_state); return s_state_size;
case 22: return (int64_t)(intptr_t)s_state;
case 21: return read_state((const void*)(intptr_t)args[0], (size_t)args[1]) ? 0 : -1;
default: return -1;
}
}
local snapshot = plugin.saveState()
-- ...
if snapshot then plugin.loadState(snapshot) end
Game save files (saved games, battery RAM) are ordinary files written with file_open, file_write, file_rename and file_mkdir, not save states.