pine_save_state
Save the current emulator state (RAM, registers, GPU, audio, timing) to a numbered slot for rollback or sharing. Overwrites the target slot without confirmation.
Instructions
PURPOSE: Trigger the emulator to save complete state (RAM, registers, GPU, audio, timing) to a numbered slot. USAGE: Rollback point before risky writes, bookmarks, repro sharing. Companion pine_load_state restores from the same slot. PINE savestates are SLOT-BASED (0-255), not file-path-based — PCSX2 picks the disk location. BEHAVIOR: DESTRUCTIVE TO TARGET SLOT: silently overwrites prior contents — no prompt, no backup, no recovery. Bound to the exact game disc and PCSX2 version; loading mismatched usually crashes the core. The call returns when PCSX2 schedules the save, NOT when the file is on disk — brief half-written window possible. Errors on no game loaded, unwritable folder, or PINE FAIL.
RETURNS: 'Save state triggered for slot N'.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| slot | Yes | Save state slot number (0-255). The PINE protocol accepts the full 0-255 range. PCSX2 slot files live in PCSX2's per-game savestate folder (typically %USERPROFILE%/Documents/PCSX2/sstates on Windows, ~/.config/PCSX2/sstates on Linux) with filenames like '<serial> (<crc>).<slot>.p2s'. Slot numbers are independent of any path. |
Implementation Reference
- src/tools.ts:412-415 (handler)The handler/case for 'pine_save_state' in the CallToolRequestSchema switch. It calls pine.saveState(slot) and returns a success message.
case "pine_save_state": { await pine.saveState(p.slot as number); return ok(`Save state triggered for slot ${p.slot}`); } - src/tools.ts:298-313 (schema)The tool definition (schema) for 'pine_save_state', including description and inputSchema with required 'slot' parameter (0-255 integer).
{ name: "pine_save_state", description: "PURPOSE: Trigger the emulator to save complete state (RAM, registers, GPU, audio, timing) to a numbered slot. " + `USAGE: Rollback point before risky writes, bookmarks, repro sharing. Companion pine_load_state restores from the same slot. PINE savestates are SLOT-BASED (0-255), not file-path-based — ${EMU_NAME} picks the disk location. ` + `BEHAVIOR: DESTRUCTIVE TO TARGET SLOT: silently overwrites prior contents — no prompt, no backup, no recovery. Bound to the exact game disc and ${EMU_NAME} version; loading mismatched usually crashes the core. The call returns when ${EMU_NAME} schedules the save, NOT when the file is on disk — brief half-written window possible. Errors on no game loaded, unwritable folder, or PINE FAIL.\n\n` + "RETURNS: 'Save state triggered for slot N'.", inputSchema: { type: "object", required: ["slot"], properties: { slot: { type: "integer", minimum: 0, maximum: 255, description: slotParamDesc(target) }, }, additionalProperties: false, }, }, - src/tools.ts:345-347 (registration)The registerTools function where tools are registered with the MCP server via setRequestHandler.
export function registerTools(server: Server, pine: PineClient, target: TargetInfo): void { const TOOLS = buildTools(target); server.setRequestHandler(ListToolsRequestSchema, async () => ({ tools: TOOLS })); - src/pine.ts:274-277 (helper)The saveState helper method on PineClient that sends the SaveState opcode (0x09) with the slot argument over the PINE protocol.
async saveState(slot: number): Promise<void> { const args = Buffer.alloc(1); args.writeUInt8(slot, 0); await this.call(Op.SaveState, args); } - src/tools.ts:45-51 (helper)The slotParamDesc helper function that generates the description for the slot parameter, used by the pine_save_state schema.
function slotParamDesc(target: TargetInfo): string { return ( `Save state slot number (0-255). The PINE protocol accepts the full 0-255 range. ` + target.savestateInfo + ` Slot numbers are independent of any path.` ); }