Skip to main content
Glama
AstralVoidZ
by AstralVoidZ

ppsspp_breakpoint

Control PPSSPP debugging: set, remove, update, list CPU breakpoints and memory watchpoints; block until a hit or trace the hit with registers and backtrace then resume.

Instructions

PURPOSE: Manage breakpoints AND consume their hits — set/remove/update/list CPU execution breakpoints and memory watchpoints, strict-wait for a hit, or one-call arm-hit-capture-resume tracing.

USAGE: session_id optional when exactly one session is active; management actions as below; action='wait' blocks until any breakpoint is hit (set/mem_set first; lock-free; breakpoint stays armed); action='trace' arms a temporary MEMORY breakpoint at address, waits, captures pc/registers/backtrace, always removes it and resumes (defaults to read access; narrow with read/write/size). For EXECUTION breakpoints use action='set' + 'wait'.

ROUTING: persistent breakpoint management -> here; one-shot strict-wait -> action='wait'; armed hit-capture -> action='trace'. BEHAVIOR: MUTATING. trace arms/removes and set/mem_* manage state; Reliable hits need CPUCore=2 (IR Interpreter). mem_remove resolves the watchpoint's real size via mem_list first (address+size matching); mem_update merges existing read/write/change unconditionally (PPSSPP zero-omits omitted bools). CPU set/remove return no data — the tool follows with a list for verification. wait/trace are lock-free during the wait itself (concurrent reads keep working); do NOT submit step/pause/resume during a wait. CONDITION SEMANTICS: PPSSPP's IR mode ignores register conditions, so any condition is enforced MCP-side — the breakpoint is armed unconditionally and each hit's expression is evaluated with cpu.evaluate; a falsy hit is auto-resumed (not surfaced) and counted in filtered_hits.

RETURNS: stats → {mode:"stats", window_s, total_hits, by_pc: [{pc, count, first_seen, last_seen}]} (fixed ~30s sampling window — no shorter-window option, probe_changes?: [{probe, old, new, ts}], note}; management actions → {action, address, enabled, breakpoints[]}; wait → {hit, already_paused, timeout_s, pc, reason, related_address, ticks, condition, condition_filtered, filtered_hits, storm_break}; trace → {hit, already_paused, address, access, timeout_s, hits: [{pc, related_address, reason, ticks, mem_hits?, registers?, backtrace?}], bp_removed, resumed, note}.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
logNoLog flag (update / mem_set / mem_update only; None = don't change). For mem_set, defaults to False when None.
readNoTrigger on read access (mem_set only; None defaults to True). For mem_update, passing read triggers a merge query — omit to leave read unchanged.
sizeNoMemory breakpoint watch size in bytes (mem_set / mem_remove / mem_update; default 4). Fixed-width watches use 1/2/4; larger sizes are passed through to PPSSPP as a range watch. NOTE: PPSSPP matches a memory watchpoint by the exact address+size pair (BreakpointSubscriber.cpp) -- the size is part of the match key, not just bookkeeping. mem_remove therefore resolves the real size via mem_list first, because removing with the caller's size alone silently fails when it differs (e.g. a 16-byte watch removed with the default 4).
writeNoTrigger on write access (mem_set only; None defaults to True). For mem_update, passing write triggers a merge query — omit to leave write unchanged.
actionYesBreakpoint operation. Valid values: Consumption actions (lifecycle orchestration): - 'wait': STRICT-WAIT — block until any breakpoint is hit (arm nothing; set/mem_set first). Lock-free: concurrent reads keep working. The breakpoint stays armed. - 'stats': HIT-FREQUENCY — count breakpoint hits by pc over a time window; optionally samples probe value changes via state_observer. Read-only. - 'trace': HIT-SNAPSHOT-RESUME — arm a temporary MEMORY breakpoint at `address`, wait for the hit, capture pc/registers/backtrace, ALWAYS remove it, then resume (defaults to read access; narrow with read/write/size). For EXECUTION breakpoints use action='set' + 'wait' instead. CPU breakpoint actions: - 'set': add a CPU execution breakpoint (requires address; enabled? defaults to True; condition? optional — enforced MCP-side (falsy hits auto-resumed, counted in filtered_hits), NOT sent to PPSSPP). - 'remove': delete a CPU breakpoint by address. - 'list': list all current CPU breakpoints. - 'update': update a CPU breakpoint's enabled/log/condition/log_format (requires address; all other params optional; condition='' clears it). Memory breakpoint actions: - 'mem_set': add a memory access breakpoint (requires address; size?/read?/write?/enabled?/log?/condition?/log_format?). - 'mem_remove': delete a memory breakpoint by address. Delete semantics are STRICT: removing a non-existent memcheck is an ERROR (unlike ppsspp_state_observer action=clear, which is idempotent-ok). - 'mem_list': list all current memory breakpoints. - 'mem_update': update a memory breakpoint's enabled/log/condition/log_format (requires address).
addressNoRequired for set / remove / update / mem_set / mem_remove / mem_update. Breakpoint address, as a hex string (e.g. '0x08804000'). Not used by list / mem_list. The schema default of '0x0' exists for legacy callers -- do NOT rely on it when the action is one of the above.0x0
enabledNoBreakpoint enable flag. For action='set' / 'mem_set', defaults to True when None. For action='update' / 'mem_update', None means 'don't change'. Ignored for remove / list actions.
conditionNoBreak condition expression (set / update / mem_set / mem_update; None = don't send). Enforced MCP-side: PPSSPP's IR mode silently ignores register conditions, so the breakpoint is armed UNCONDITIONALLY and falsy hits are auto-resumed and counted in filtered_hits.
timeout_sNoWait budget in seconds (wait / trace only; default 30, clamped to [0.5, 300]). On timeout: hit=false — NOT an error — so callers can poll.
log_formatNoLog format string (update / mem_set / mem_update only; None = don't change).
session_idNoActive session ID; omit to auto-resolve when exactly one session is active.
want_backtraceNoInclude the HLE backtrace in the hit (trace only; CPU is paused at the hit, so the trace is valid).
want_registersNoInclude the full CPU register dump in the hit (trace only).

Output Schema

TableJSON Schema
NameRequiredDescriptionDefault
pcNo
hitNo
hitsNo
modeNo
noteNo
by_pcNo
ticksNo
accessNo
actionNo'set' / 'remove' / 'list' / 'update' / 'mem_set' / 'mem_remove' / 'mem_list' / 'mem_update'.
reasonNo
addressNo
enabledNoEnabled flag (set / mem_set / update / mem_update only).
resumedNo
mem_hitsNo
window_sNo
conditionNo
timeout_sNo
bp_removedNo
total_hitsNo
breakpointsNoBreakpoint list (list / mem_list only).
storm_breakNo
filtered_hitsNo
probe_changesNo
already_pausedNo
related_addressNo
condition_filteredNo

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed8 schema fields changedv0.1.7
    • changedInput schema / properties / action / description
      Previous value: -"Breakpoint operation. Valid values:\nConsumption actions (lifecycle orchestration):\n- 'wait': STRICT-WAIT — block until any breakpoint is hit \n(arm nothing; set/mem_set first). Lock-free: concurrent \nreads keep working. The breakpoint stays armed.\n- 'stats': HIT-FREQUENCY — count breakpoint hits by pc \nover a time window; optionally samples probe value \nchanges via state_observer. Read-only.\n- 'trace': HIT-SNAPSHOT-RESUME — arm a temporary \nMEMORY breakpoint at `address`, wait for the hit, \ncapture pc/registers/backtrace, ALWAYS remove it, then \nresume (defaults to read access; narrow with \nread/write/size). For EXECUTION breakpoints use \naction='set' + 'wait' instead.\nCPU breakpoint actions:\n- 'set': add a CPU execution breakpoint (requires address; enabled? defaults to True; condition? optional — enforced MCP-side (falsy hits auto-resumed, counted in filtered_hits), NOT sent to PPSSPP).\n- 'remove': delete a CPU breakpoint by address.\n- 'list': list all current CPU breakpoints.\n- 'update': update a CPU breakpoint's enabled/log/condition/log_format (requires address; all other params optional; condition='' clears it).\nMemory breakpoint actions:\n- 'mem_set': add a memory access breakpoint (requires address; size?/read?/write?/enabled?/log?/condition?/log_format?).\n- 'mem_remove': delete a memory breakpoint by address. Delete semantics are STRICT: removing a non-existent memcheck is an ERROR (unlike ppsspp_state_observer action=clear, which is idempotent-ok — F-5 contract, 2026-09-08).\n- 'mem_list': list all current memory breakpoints.\n- 'mem_update': update a memory breakpoint's enabled/log/condition/log_format (requires address)."New value: +"Breakpoint operation. Valid values:\nConsumption actions (lifecycle orchestration):\n- 'wait': STRICT-WAIT — block until any breakpoint is hit \n(arm nothing; set/mem_set first). Lock-free: concurrent \nreads keep working. The breakpoint stays armed.\n- 'stats': HIT-FREQUENCY — count breakpoint hits by pc \nover a time window; optionally samples probe value \nchanges via state_observer. Read-only.\n- 'trace': HIT-SNAPSHOT-RESUME — arm a temporary \nMEMORY breakpoint at `address`, wait for the hit, \ncapture pc/registers/backtrace, ALWAYS remove it, then \nresume (defaults to read access; narrow with \nread/write/size). For EXECUTION breakpoints use \naction='set' + 'wait' instead.\nCPU breakpoint actions:\n- 'set': add a CPU execution breakpoint (requires address; enabled? defaults to True; condition? optional — enforced MCP-side (falsy hits auto-resumed, counted in filtered_hits), NOT sent to PPSSPP).\n- 'remove': delete a CPU breakpoint by address.\n- 'list': list all current CPU breakpoints.\n- 'update': update a CPU breakpoint's enabled/log/condition/log_format (requires address; all other params optional; condition='' clears it).\nMemory breakpoint actions:\n- 'mem_set': add a memory access breakpoint (requires address; size?/read?/write?/enabled?/log?/condition?/log_format?).\n- 'mem_remove': delete a memory breakpoint by address. Delete semantics are STRICT: removing a non-existent memcheck is an ERROR (unlike ppsspp_state_observer action=clear, which is idempotent-ok).\n- 'mem_list': list all current memory breakpoints.\n- 'mem_update': update a memory breakpoint's enabled/log/condition/log_format (requires address)."
    • changedInput schema / properties / address / description
      Previous value: -"Breakpoint address, as a hex string (e.g. '0x08804000'). Required for set / remove / update / mem_set / mem_remove / mem_update; ignored for list / mem_list."New value: +"Required for set / remove / update / mem_set / mem_remove / mem_update. Breakpoint address, as a hex string (e.g. '0x08804000'). Not used by list / mem_list. The schema default of '0x0' exists for legacy callers -- do NOT rely on it when the action is one of the above."
    • addedInput schema / properties / session_id / anyOf
      Added value: +[
      +  {
      +    "type": "string"
      +  },
      +  {
      +    "type": "null"
      +  }
      +]
    • addedInput schema / properties / session_id / default
      Added value: +null
    • changedInput schema / properties / session_id / description
      Previous value: -"Active session ID."New value: +"Active session ID; omit to auto-resolve when exactly one session is active."
    • removedInput schema / properties / session_id / type
      Removed value: -"string"
    • changedInput schema / properties / size / description
      Previous value: -"Memory breakpoint watch size in bytes (mem_set / mem_remove / mem_update; default 4). Fixed-width watches use 1/2/4; larger sizes are passed through to PPSSPP as a range watch. NOTE (verified): mem_remove matches by ADDRESS only — a wrong or omitted size still removes the breakpoint at that address, so keep the size you set for bookkeeping, not for matching."New value: +"Memory breakpoint watch size in bytes (mem_set / mem_remove / mem_update; default 4). Fixed-width watches use 1/2/4; larger sizes are passed through to PPSSPP as a range watch. NOTE: PPSSPP matches a memory watchpoint by the exact address+size pair (BreakpointSubscriber.cpp) -- the size is part of the match key, not just bookkeeping. mem_remove therefore resolves the real size via mem_list first, because removing with the caller's size alone silently fails when it differs (e.g. a 16-byte watch removed with the default 4)."
    • changedInput schema / required
      Previous value: -[
      -  "session_id",
      -  "action"
      -]New value: +[
      +  "action"
      +]
  2. Changed31 schema fields changedv0.1.6
    • changedInput schema / properties / action / description
      Previous value: -"Breakpoint operation. Valid values:\nCPU breakpoint actions:\n- 'set': add a CPU execution breakpoint (requires address; enabled? defaults to True; condition? optional).\n- 'remove': delete a CPU breakpoint by address.\n- 'list': list all current CPU breakpoints.\n- 'update': update a CPU breakpoint's enabled/log/condition/log_format (requires address; all other params optional).\nMemory breakpoint actions:\n- 'mem_set': add a memory access breakpoint (requires address; size?/read?/write?/enabled?/log?/condition?/log_format?).\n- 'mem_remove': delete a memory breakpoint by address. Delete semantics are STRICT: removing a non-existent memcheck is an ERROR (unlike ppsspp_state_observer action=clear, which is idempotent-ok — F-5 contract, 2026-09-08).\n- 'mem_list': list all current memory breakpoints.\n- 'mem_update': update a memory breakpoint's enabled/log/condition/log_format (requires address)."New value: +"Breakpoint operation. Valid values:\nConsumption actions (lifecycle orchestration):\n- 'wait': STRICT-WAIT — block until any breakpoint is hit \n(arm nothing; set/mem_set first). Lock-free: concurrent \nreads keep working. The breakpoint stays armed.\n- 'stats': HIT-FREQUENCY — count breakpoint hits by pc \nover a time window; optionally samples probe value \nchanges via state_observer. Read-only.\n- 'trace': HIT-SNAPSHOT-RESUME — arm a temporary \nMEMORY breakpoint at `address`, wait for the hit, \ncapture pc/registers/backtrace, ALWAYS remove it, then \nresume (defaults to read access; narrow with \nread/write/size). For EXECUTION breakpoints use \naction='set' + 'wait' instead.\nCPU breakpoint actions:\n- 'set': add a CPU execution breakpoint (requires address; enabled? defaults to True; condition? optional — enforced MCP-side (falsy hits auto-resumed, counted in filtered_hits), NOT sent to PPSSPP).\n- 'remove': delete a CPU breakpoint by address.\n- 'list': list all current CPU breakpoints.\n- 'update': update a CPU breakpoint's enabled/log/condition/log_format (requires address; all other params optional; condition='' clears it).\nMemory breakpoint actions:\n- 'mem_set': add a memory access breakpoint (requires address; size?/read?/write?/enabled?/log?/condition?/log_format?).\n- 'mem_remove': delete a memory breakpoint by address. Delete semantics are STRICT: removing a non-existent memcheck is an ERROR (unlike ppsspp_state_observer action=clear, which is idempotent-ok — F-5 contract, 2026-09-08).\n- 'mem_list': list all current memory breakpoints.\n- 'mem_update': update a memory breakpoint's enabled/log/condition/log_format (requires address)."
    • changedInput schema / properties / action / enum
      Previous value: -[
      -  "set",
      -  "remove",
      -  "list",
      -  "update",
      -  "mem_set",
      -  "mem_remove",
      -  "mem_list",
      -  "mem_update"
      -]New value: +[
      +  "wait",
      +  "trace",
      +  "stats",
      +  "set",
      +  "remove",
      +  "list",
      +  "update",
      +  "mem_set",
      +  "mem_remove",
      +  "mem_list",
      +  "mem_update"
      +]
    • changedInput schema / properties / condition / description
      Previous value: -"Break condition expression (set / update / mem_set / mem_update; None = don't send)."New value: +"Break condition expression (set / update / mem_set / mem_update; None = don't send). Enforced MCP-side: PPSSPP's IR mode silently ignores register conditions, so the breakpoint is armed UNCONDITIONALLY and falsy hits are auto-resumed and counted in filtered_hits."
    • changedInput schema / properties / size / description
      Previous value: -"Memory breakpoint watch size in bytes (mem_set / mem_remove / mem_update; default 4). Fixed-width watches use 1/2/4; larger sizes are passed through to PPSSPP as a range watch. PPSSPP matches memory breakpoints by address+size pair, so remove/update must pass the exact size recorded at set time."New value: +"Memory breakpoint watch size in bytes (mem_set / mem_remove / mem_update; default 4). Fixed-width watches use 1/2/4; larger sizes are passed through to PPSSPP as a range watch. NOTE (verified): mem_remove matches by ADDRESS only — a wrong or omitted size still removes the breakpoint at that address, so keep the size you set for bookkeeping, not for matching."
    • addedInput schema / properties / timeout_s
      Added value: +{
      +  "default": 30,
      +  "description": "Wait budget in seconds (wait / trace only; default 30, clamped to [0.5, 300]). On timeout: hit=false — NOT an error — so callers can poll.",
      +  "title": "Timeout S",
      +  "type": "number"
      +}
    • addedInput schema / properties / want_backtrace
      Added value: +{
      +  "default": false,
      +  "description": "Include the HLE backtrace in the hit (trace only; CPU is paused at the hit, so the trace is valid).",
      +  "title": "Want Backtrace",
      +  "type": "boolean"
      +}
    • addedInput schema / properties / want_registers
      Added value: +{
      +  "default": false,
      +  "description": "Include the full CPU register dump in the hit (trace only).",
      +  "title": "Want Registers",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / access
      Added value: +{
      +  "title": "Access",
      +  "type": "string"
      +}
    • removedOutput schema / properties / address / description
      Removed value: -"Breakpoint address, hex string (e.g. '0x08804000'); '0x00000000' for list / mem_list."
    • addedOutput schema / properties / already_paused
      Added value: +{
      +  "title": "Already Paused",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / bp_removed
      Added value: +{
      +  "title": "Bp Removed",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / by_pc
      Added value: +{
      +  "items": {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  "title": "By Pc",
      +  "type": "array"
      +}
    • addedOutput schema / properties / condition
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Condition"
      +}
    • addedOutput schema / properties / condition_filtered
      Added value: +{
      +  "title": "Condition Filtered",
      +  "type": "integer"
      +}
    • addedOutput schema / properties / filtered_hits
      Added value: +{
      +  "title": "Filtered Hits",
      +  "type": "integer"
      +}
    • addedOutput schema / properties / hit
      Added value: +{
      +  "title": "Hit",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / hits
      Added value: +{
      +  "items": {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  "title": "Hits",
      +  "type": "array"
      +}
    • addedOutput schema / properties / mem_hits
      Added value: +{
      +  "items": {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  "title": "Mem Hits",
      +  "type": "array"
      +}
    • addedOutput schema / properties / mode
      Added value: +{
      +  "title": "Mode",
      +  "type": "string"
      +}
    • addedOutput schema / properties / note
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Note"
      +}
    • addedOutput schema / properties / pc
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Pc"
      +}
    • addedOutput schema / properties / probe_changes
      Added value: +{
      +  "items": {
      +    "additionalProperties": true,
      +    "type": "object"
      +  },
      +  "title": "Probe Changes",
      +  "type": "array"
      +}
    • addedOutput schema / properties / reason
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Reason"
      +}
    • addedOutput schema / properties / related_address
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "string"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Related Address"
      +}
    • addedOutput schema / properties / resumed
      Added value: +{
      +  "title": "Resumed",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / storm_break
      Added value: +{
      +  "title": "Storm Break",
      +  "type": "boolean"
      +}
    • addedOutput schema / properties / ticks
      Added value: +{
      +  "anyOf": [
      +    {
      +      "type": "integer"
      +    },
      +    {
      +      "type": "null"
      +    }
      +  ],
      +  "title": "Ticks"
      +}
    • addedOutput schema / properties / timeout_s
      Added value: +{
      +  "title": "Timeout S",
      +  "type": "number"
      +}
    • addedOutput schema / properties / total_hits
      Added value: +{
      +  "title": "Total Hits",
      +  "type": "integer"
      +}
    • addedOutput schema / properties / window_s
      Added value: +{
      +  "title": "Window S",
      +  "type": "number"
      +}
    • removedOutput schema / required
      Removed value: -[
      -  "action",
      -  "address",
      -  "enabled",
      -  "breakpoints"
      -]
  3. First observedv0.1.0

TDQS

A4.6/5.0
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Beyond the annotations, it discloses that the tool is mutating, that trace arms and always removes a temporary memory breakpoint and resumes, that reliable hits need CPUCore=2, that mem_remove resolves the real size via mem_list, that mem_update merges omitted booleans, that CPU set/remove return no data and are followed by a list, and that wait/trace remain lock-free. These are material behavioral traits not captured by the structured fields.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long, but it is front-loaded with PURPOSE and organized into USAGE, ROUTING, BEHAVIOR, and RETURNS sections. The length is defensible for an 11-action tool, though some material repeats the schema or output schema.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the 11 actions, 13 parameters, annotations, and output schema, the description is complete. It covers action semantics, mutation behavior, condition filtering, timeout behavior, return-shape expectations, and important edge cases such as strict mem_remove and PPSSPP IR condition handling.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already documents all 13 parameters in detail. The description adds cross-action routing and some caveats, but most parameter-specific meaning is redundant with the schema, so the baseline of 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb-and-resource statement: it manages CPU execution breakpoints and memory watchpoints and consumes their hits. It distinguishes management, wait, trace, and stats actions, and routes execution breakpoints to set + wait, so an agent can identify what this tool does without opening the schema.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It explicitly states when to use each action: persistent management, one-shot strict-wait via action='wait', and armed hit-capture via action='trace'. It also says when to use set + wait for execution breakpoints and warns against submitting step/pause/resume during a wait, giving clear alternatives and exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.