Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/LiveSplit/livesplit-core/llms.txt

Use this file to discover all available pages before exploring further.

Enable auto-splitting in Cargo features: livesplit-core = { version = "0.13.0", features = ["auto-splitting"] }
Auto splitting allows a WebAssembly module to read a game’s process memory and automatically call timer controls — start, split, reset — without any input from the runner. The module runs inside a sandboxed WebAssembly environment managed by livesplit-core’s auto splitting runtime.
Auto splitters are separate .wasm files, not Rust code compiled into your main application. You compile the auto splitter independently and load it at runtime.

Requirements for an Auto Splitter Module

The WebAssembly module must satisfy two requirements:
  1. Export an update function with the following signature. The runtime calls it periodically (120 Hz by default, adjustable via runtime_set_tick_rate):
#[unsafe(no_mangle)]
pub extern "C" fn update() {}
  1. Export a memory export — the standard linear memory export from a WebAssembly module.
The auto splitter can change the tick rate at any time by calling runtime_set_tick_rate(ticks_per_second).

API Exposed to Auto Splitters (env module)

The runtime exposes the following functions to auto splitter modules in the env import namespace.

Timer State

#[repr(transparent)]
pub struct TimerState(u32);

impl TimerState {
    /// The timer is not running.
    pub const NOT_RUNNING: Self = Self(0);
    /// The timer is running.
    pub const RUNNING: Self = Self(1);
    /// The timer started but got paused (separate from game time pausing).
    pub const PAUSED: Self = Self(2);
    /// The timer has ended, but hasn't been reset yet.
    pub const ENDED: Self = Self(3);
}

Timer Control

FunctionDescription
timer_get_state() -> TimerStateReturns the current state of the timer.
timer_current_split_index() -> i64Returns the index of the current split, or -1 if no attempt is in progress.
timer_segment_splitted(idx: u64) -> i32Returns 1 if the segment was split, 0 if skipped, or -1 if idx is at or beyond the current split.
timer_start()Starts the timer.
timer_split()Splits the current segment.
timer_skip_split()Skips the current split.
timer_undo_split()Undoes the previous split.
timer_reset()Resets the timer.
timer_set_game_time(secs: i64, nanos: i32)Sets the game time directly.
timer_pause_game_time()Pauses the automatic flow of game time (does not pause the timer itself).
timer_resume_game_time()Resumes the automatic flow of game time.
timer_set_variable(key_ptr, key_len, value_ptr, value_len)Sets a custom key-value variable for visualization.

Process Attachment

FunctionDescription
process_attach(name_ptr, name_len) -> Option<AttachedProcess>Attaches to a process by name. If multiple processes match, the most recently started one is used.
process_attach_by_pid(pid: ProcessId) -> Option<AttachedProcess>Attaches to a process by its process ID.
process_detach(process: AttachedProcess)Detaches from a process.
process_is_open(process: AttachedProcess) -> boolReturns false if the process has exited; you should detach and stop using it.
process_list_by_name(name_ptr, name_len, list_ptr, list_len_ptr) -> boolFills a buffer with process IDs for processes matching the given name.

Memory Reading

FunctionDescription
process_read(process, address, buf_ptr, buf_len) -> boolReads arbitrary bytes from a process address into a buffer.
process_get_module_address(process, name_ptr, name_len) -> Option<NonZeroAddress>Gets the base address of a named module.
process_get_module_size(process, name_ptr, name_len) -> Option<NonZeroU64>Gets the size of a named module in memory.
process_get_module_path(process, name_ptr, name_len, buf_ptr, buf_len_ptr) -> boolStores the WASI-mapped path of a module (e.g. C:\foo.exe/mnt/c/foo.exe).
process_get_path(process, buf_ptr, buf_len_ptr) -> boolStores the WASI-mapped path of the process executable.
process_get_memory_range_count(process) -> Option<NonZeroU64>Returns the number of memory ranges in the process.
process_get_memory_range_address(process, idx) -> Option<NonZeroAddress>Gets the start address of a memory range by index.
process_get_memory_range_size(process, idx) -> Option<NonZeroU64>Gets the size of a memory range by index.
process_get_memory_range_flags(process, idx) -> Option<MemoryRangeFlags>Gets the flags of a memory range (readable, writable, executable, has path).

Runtime Utilities

FunctionDescription
runtime_set_tick_rate(ticks_per_second: f64)Changes how many times per second update() is called. Default is 120.
runtime_print_message(text_ptr, text_len)Prints a debug log message.
runtime_get_os(buf_ptr, buf_len_ptr) -> boolStores the OS name (e.g. windows, linux, macos).
runtime_get_arch(buf_ptr, buf_len_ptr) -> boolStores the CPU architecture (e.g. x86_64, aarch64).

User Settings

Auto splitters can expose settings that users can modify at runtime.
FunctionDescription
user_settings_add_bool(key_ptr, key_len, description_ptr, description_len, default_value) -> boolAdds a boolean setting. Returns the current value (user override or default).
user_settings_add_title(key_ptr, key_len, description_ptr, description_len, heading_level)Adds a section title to group settings visually.
user_settings_add_choice(key_ptr, key_len, description_ptr, description_len, default_option_key_ptr, default_option_key_len)Adds a choice (enum) setting.
user_settings_add_choice_option(key_ptr, key_len, option_key_ptr, option_key_len, option_description_ptr, option_description_len) -> boolAdds an option to a choice setting. Returns true if this option is currently selected.
user_settings_add_file_select(key_ptr, key_len, description_ptr, description_len)Adds a file-select setting; the stored value is a WASI-mapped path.
user_settings_set_tooltip(key_ptr, key_len, tooltip_ptr, tooltip_len)Attaches an explanatory tooltip to a setting.
Settings are backed by a settings map — a key-value store that persists across restarts. The map can be loaded, modified, and stored back:
FunctionDescription
settings_map_new() -> SettingsMapCreates a new empty settings map.
settings_map_load() -> SettingsMapLoads a copy of the current global settings map.
settings_map_store(map: SettingsMap)Overwrites the global settings map with a copy of map.
settings_map_store_if_unchanged(old_map, new_map) -> boolAtomically stores the new map only if the global map still matches old_map.
settings_map_get(map, key_ptr, key_len) -> Option<SettingValue>Retrieves a value by key.
settings_map_insert(map, key_ptr, key_len, value)Inserts or overwrites a key.

WASI Support

In addition to the env API, the runtime provides WASI 0.1 support:
  • stderr — available for logging (line-buffered).
  • File system — the host file system is exposed read-only under /mnt. Windows paths like C:\foo\bar.exe are mapped to /mnt/c/foo/bar.exe.
  • stdout/stdin — unbound; currently no-ops.
  • No environment variables, command-line arguments, networking, or threading.
  • Time and random numbers are available.

Loading an Auto Splitter (Rust)

use livesplit_core::auto_splitting::Runtime;
use std::path::PathBuf;

// Runtime<T> is generic over any T: CommandSink + TimerQuery + Send.
// In most applications, T is livesplit_core::SharedTimer.
let runtime: Runtime<_> = Runtime::new();

// Load a WASM auto splitter, passing the timer it should control.
runtime
    .load(PathBuf::from("my_game.wasm"), shared_timer)
    .expect("Failed to load auto splitter");

// Later, unload it (safe to call even if nothing is loaded).
runtime.unload().expect("Failed to unload auto splitter");
Runtime::new() starts two background threads: one that drives the update() loop and one watchdog that monitors for hangs.

Loading an Auto Splitter via the C API

// Create the runtime (does not load an auto splitter yet).
AutoSplittingRuntime *runtime = AutoSplittingRuntime_new();

// Load a WASM file. Returns true on success.
bool ok = AutoSplittingRuntime_load(runtime, "my_game.wasm", shared_timer);

// Unload the current auto splitter. Returns true on success.
AutoSplittingRuntime_unload(runtime);

// Free the runtime when done.
AutoSplittingRuntime_drop(runtime);

Watchdog and Error Handling

A dedicated watchdog thread monitors the runtime. If the auto splitter’s update() function does not return within 5 seconds, the watchdog logs an error and sends an interrupt to the WebAssembly instance. If the auto splitter traps (panics or hits an unreachable), it is automatically unloaded and the runtime returns to an idle state waiting for a new module to be loaded.

Managing Settings at Runtime

// Read the current settings map (returns None if no auto splitter is loaded).
if let Some(map) = runtime.settings_map() {
    // Display widgets to the user.
    if let Some(widgets) = runtime.settings_widgets() {
        for widget in widgets.iter() {
            // widget.key, widget.description, widget.kind, etc.
        }
    }

    // Apply user changes and store back, handling concurrent updates.
    let new_map = map.clone(); // modify as needed
    runtime.set_settings_map_if_unchanged(&map, new_map);
}

Build docs developers (and LLMs) love