97 lines
3.0 KiB
C
97 lines
3.0 KiB
C
#include "sim_api.h"
|
|
|
|
#include <string.h>
|
|
|
|
typedef struct {
|
|
uint32_t created;
|
|
uint32_t loaded;
|
|
uint64_t tick;
|
|
uint32_t pending_event;
|
|
} sim_state;
|
|
|
|
static sim_state state;
|
|
|
|
#ifndef SIM_CHECKPOINT_BUILD_ID
|
|
#define SIM_CHECKPOINT_BUILD_ID "unversioned"
|
|
#endif
|
|
const char *sim_checkpoint_build_id(void) { return SIM_CHECKPOINT_BUILD_ID; }
|
|
|
|
uint32_t sim_core_checkpoint_size(void) { return sizeof(state); }
|
|
int32_t sim_core_checkpoint_export(uint8_t *output, uint32_t capacity) {
|
|
if (output == NULL || capacity != sizeof(state)) return SIM_ERR_INVALID_ARGUMENT;
|
|
memcpy(output, &state, sizeof(state)); return SIM_OK;
|
|
}
|
|
int32_t sim_core_checkpoint_restore(const uint8_t *input, uint32_t length) {
|
|
if (input == NULL || length != sizeof(state)) return SIM_ERR_INVALID_ARGUMENT;
|
|
const sim_state *saved = (const sim_state *)input;
|
|
if (saved->created > 1 || saved->loaded > 1 || saved->pending_event > 1) return SIM_ERR_INVALID_ARGUMENT;
|
|
memcpy(&state, saved, sizeof(state)); return SIM_OK;
|
|
}
|
|
|
|
static int valid_buffer(const uint8_t *data, uint32_t len) {
|
|
return len == 0 || data != NULL;
|
|
}
|
|
|
|
int32_t sim_create(const uint8_t *config, uint32_t config_len) {
|
|
if (!valid_buffer(config, config_len)) return SIM_ERR_INVALID_ARGUMENT;
|
|
memset(&state, 0, sizeof(state));
|
|
state.created = 1;
|
|
state.pending_event = 1;
|
|
return SIM_OK;
|
|
}
|
|
|
|
int32_t sim_load_workspace(const char *root_path) {
|
|
if (!state.created) return SIM_ERR_NOT_CREATED;
|
|
if (root_path == NULL || root_path[0] == '\0') return SIM_ERR_INVALID_ARGUMENT;
|
|
state.loaded = 1;
|
|
state.pending_event = 1;
|
|
return SIM_OK;
|
|
}
|
|
|
|
int32_t sim_command(const uint8_t *command, uint32_t command_len) {
|
|
if (!state.created || !state.loaded) return SIM_ERR_INVALID_STATE;
|
|
if (!valid_buffer(command, command_len) || command_len == 0) return SIM_ERR_INVALID_ARGUMENT;
|
|
state.pending_event = 1;
|
|
return SIM_OK;
|
|
}
|
|
|
|
int32_t sim_step(uint32_t cycles) {
|
|
if (!state.created || !state.loaded) return SIM_ERR_INVALID_STATE;
|
|
state.tick += cycles;
|
|
state.pending_event = 1;
|
|
return SIM_OK;
|
|
}
|
|
|
|
uint32_t sim_read_snapshot(uint8_t *out, uint32_t capacity) {
|
|
const uint32_t size = (uint32_t)sizeof(state.tick);
|
|
if (out == NULL || capacity < size) return size;
|
|
memcpy(out, &state.tick, size);
|
|
return size;
|
|
}
|
|
|
|
uint32_t sim_read_event(uint8_t *out, uint32_t capacity) {
|
|
const uint32_t size = 1;
|
|
if (!state.pending_event) return 0;
|
|
if (out == NULL || capacity < size) return size;
|
|
out[0] = 1;
|
|
state.pending_event = 0;
|
|
return size;
|
|
}
|
|
|
|
int32_t sim_export_state(uint8_t *out, uint32_t capacity) {
|
|
const uint32_t size = (uint32_t)sizeof(state);
|
|
if (out == NULL || capacity < size) return SIM_ERR_BUFFER_TOO_SMALL;
|
|
memcpy(out, &state, size);
|
|
return (int32_t)size;
|
|
}
|
|
|
|
int32_t sim_import_state(const uint8_t *data, uint32_t len) {
|
|
if (data == NULL || len != sizeof(state)) return SIM_ERR_INVALID_ARGUMENT;
|
|
memcpy(&state, data, sizeof(state));
|
|
return SIM_OK;
|
|
}
|
|
|
|
void sim_destroy(void) {
|
|
memset(&state, 0, sizeof(state));
|
|
}
|