#timer #wasm-module #speedrun #livesplit #auto-splitting

livesplit-auto-splitting

livesplit-auto-splitting是一个库,提供运行可以控制速度跑计时器的自动分割器运行时。这些自动分割器以WebAssembly模块的形式提供。

1个不稳定版本

0.1.0 2022年12月28日

#691 in WebAssembly


livesplit-core中使用

Apache-2.0/MIT

38KB
600

LiveSplit livesplit-auto-splitting

livesplit-auto-splitting是一个库,提供运行可以控制速度跑计时器的自动分割器运行时。这些自动分割器以WebAssembly模块的形式提供。

自动分割器的需求

自动分割器必须提供一个具有以下签名的update函数

#[no_mangle]
pub extern "C" fn update() {}

此函数由运行时以配置的滴答速率定期调用。默认滴答速率为120 Hz,但可以由自动分割器更改。

此外,WebAssembly模块应导出一个名为memory的内存。

暴露给自动分割器的API

以下函数通过模块env提供给自动分割器

#[repr(transparent)]
pub struct Address(pub u64);

#[repr(transparent)]
pub struct NonZeroAddress(pub NonZeroU64);

#[repr(transparent)]
pub struct ProcessId(NonZeroU64);

#[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. This is separate from the game
    /// time being paused. Game time may even always be paused.
    pub const PAUSED: Self = Self(2);
    /// The timer has ended, but didn't get reset yet.
    pub const ENDED: Self = Self(3);
}

extern "C" {
    /// Gets the state that the timer currently is in.
    pub fn timer_get_state() -> TimerState;

    /// Starts the timer.
    pub fn timer_start();
    /// Splits the current segment.
    pub fn timer_split();
    /// Resets the timer.
    pub fn timer_reset();
    /// Sets a custom key value pair. This may be arbitrary information that
    /// the auto splitter wants to provide for visualization.
    pub fn timer_set_variable(
        key_ptr: *const u8,
        key_len: usize,
        value_ptr: *const u8,
        value_len: usize,
    );

    /// Sets the game time.
    pub fn timer_set_game_time(secs: i64, nanos: i32);
    /// Pauses the game time. This does not pause the timer, only the
    /// automatic flow of time for the game time.
    pub fn timer_pause_game_time();
    /// Resumes the game time. This does not resume the timer, only the
    /// automatic flow of time for the game time.
    pub fn timer_resume_game_time();

    /// Attaches to a process based on its name.
    pub fn process_attach(name_ptr: *const u8, name_len: usize) -> Option<ProcessId>;
    /// Detaches from a process.
    pub fn process_detach(process: ProcessId);
    /// Checks whether is a process is still open. You should detach from a
    /// process and stop using it if this returns `false`.
    pub fn process_is_open(process: ProcessId) -> bool;
    /// Reads memory from a process at the address given. This will write
    /// the memory to the buffer given. Returns `false` if this fails.
    pub fn process_read(
        process: ProcessId,
        address: Address,
        buf_ptr: *mut u8,
        buf_len: usize,
    ) -> bool;
    /// Gets the address of a module in a process.
    pub fn process_get_module_address(
        process: ProcessId,
        name_ptr: *const u8,
        name_len: usize,
    ) -> Option<NonZeroAddress>;
    /// Gets the size of a module in a process.
    pub fn process_get_module_size(
        process: ProcessId,
        name_ptr: *const u8,
        name_len: usize,
    ) -> Option<NonZeroU64>;

    /// Sets the tick rate of the runtime. This influences the amount of
    /// times the `update` function is called per second.
    pub fn runtime_set_tick_rate(ticks_per_second: f64);
    /// Prints a log message for debugging purposes.
    pub fn runtime_print_message(text_ptr: *const u8, text_len: usize);

    /// Adds a new setting that the user can modify. This will return either
    /// the specified default value or the value that the user has set.
    pub fn user_settings_add_bool(
        key_ptr: *const u8,
        key_len: usize,
        description_ptr: *const u8,
        description_len: usize,
        default_value: bool,
    ) -> bool;
}

在运行时API的基础上,还提供了不稳定的WASI支持,通过unstable功能。

依赖项

~25–41MB
~684K SLoC