Commit Graph
8 Commits
Author SHA1 Message Date
Henrik Rydgård 9b9083d3e5 Fix for headless port problem by Claude 2026-08-16 23:09:12 +02:00
Henrik RydgårdandClaude Sonnet 5 a502b55fea Debugger: add memory.disasm compact mode and memory.searchDisasm findAll
Two real gaps hit repeatedly while investigating the VSH boot path (see
docs/VSHBootInvestigation.md):

- memory.disasm's response is the full per-field JSON (type, address,
  addressSize, encoding, macroEncoding, backgroundColor, name, params,
  symbol, function, dataSymbol, breakpoint, isCurrentPC, branch,
  relevantData, conditionMet, dataAccess - ~15 fields per line). Reading
  disassembly by hand meant writing a throwaway script each time to reduce
  this down to "ADDR: name params" - and at least once, a bug in one of
  those scripts produced misleading output that wasn't caught immediately.
  Added compact=true: returns "lines" as an array of plain strings
  ("M AAAAAAAA  [symbol: ]name params", M = '>' for current PC, '*'/'o'
  for an enabled/disabled breakpoint) instead, computed once correctly
  here instead of ad hoc every time.

- memory.searchDisasm already existed but only ever returned the first
  match - genuinely limiting for "find every caller of this address"
  call-graph-style queries, which came up directly while trying to trace
  which function builds VSH's GE display list. Added findAll=true: scans
  the whole range and returns every match in a new "addresses" array
  (capped at 1000), instead of stopping at the first. Default behavior
  (address: first match or null) is unchanged for existing callers.

Verified live via PPSSPPHeadless + wsdbg: compact mode against a real
demo ELF's entry point produces clean, correctly-marked text lines;
findAll=true against the same range found all 11 jal instructions instead
of just the first. UnitTest.exe all: 49/49 passed.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-14 11:04:32 +02:00
Henrik RydgårdandClaude Sonnet 5 db2d248b4a Rename GPRBreakpoint/gprBreakpoint to RegBreakpoint/regBreakpoint
The struct and its API only handle GPR indices today, but the naming
should stay general since this is expected to grow to cover other
register files too (e.g. FPU registers like $f10). Pure rename - no
behavior change:

- Core/Debugger/Breakpoints.{h,cpp}: RegBreakpoint struct, all
  BreakpointManager Add/Remove/Change/Get/Exec/Has/Find*RegBreakpoint*
  methods, regBreakpoints_/regBreakpointMask_ members.
- Core/Core.{h,cpp}: BreakReason::RegBreakpoint, "cpu.regBreakpoint"
  break-reason string.
- Core/Debugger/WebSocket/BreakpointSubscriber.{h,cpp}: WebSocket
  events cpu.gprBreakpoint.* -> cpu.regBreakpoint.*, matching
  Add/Update/Remove/List handlers and params struct.
- Core/MIPS/MIPSTables.cpp: local variable names in the interpreter's
  per-instruction breakpoint check.
- docs/WebSocketDebugger.md updated to match.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-13 16:09:51 +02:00
Henrik RydgårdandClaude Sonnet 5 75174af77b Add GPR write breakpoints (break when a register is written, anywhere)
New debugging primitive: break whenever any instruction writes to a
given general-purpose register (0-31), regardless of which address
executes the write. Requested for continuing the reboot.bin trace,
where the actual blocker is "what sets $s3 to this bad value", not
"what happens at a specific address" - existing address/memory
breakpoints can't express that directly.

- GPRBreakpoint (Core/Debugger/Breakpoints.h) mirrors the existing
  BreakPoint/MemCheck shape (result/condition/logFormat/hit count),
  keyed by register index instead of address/range.
- BreakpointManager keeps a u32 bitmask (bit i = register i has an
  active breakpoint) alongside the GPRBreakpoint vector, so the
  interpreter loop can test "would this write trip anything" with a
  single shift+and against a value already cached in a local.
- RunUntilDowncountZeroWithChecks (Core/MIPS/MIPSTables.cpp) computes
  the about-to-be-written register from the current instruction's
  OUT_RT/OUT_RD/OUT_RA flags (GetGPRWriteTarget()) and checks it
  against the mask, same convention as the existing memcheck handling
  right above it (checked before the instruction executes, bails via
  CORE_STEPPING_CPU without running it if tripped).
- New BreakReason::GPRBreakpoint ("cpu.gprBreakpoint") for Core_Break.
- WebSocket API: cpu.gprBreakpoint.add/update/remove/list, accepting
  either a 0-31 'register' index or a case-insensitive 'name' (e.g.
  "s3"), documented in docs/WebSocketDebugger.md.

Interpreter-only for now, deliberately.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-13 11:35:29 +02:00
Henrik Rydgård 3eee14b02b Clean up the AI-generated documentation manually, AGENTS.md updates 2026-07-27 10:55:54 +02:00
Henrik RydgårdandClaude Opus 5 333ae20092 Update docs for the unified --debugger=PORT flag
Reflect the CmdLine.cpp unification and the headless net::Init() fix in
docs/WebSocketDebugger.md and AGENTS.md - previously these described the
app-only boolean --debugger flag and flagged headless as unreliable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-26 21:52:48 +02:00
Henrik RydgårdandClaude Opus 5 074c8ac523 Add memory.search and hle.data.* to the WebSocket debugger
Reverse-engineering workflows need to (1) find where an unknown value lives
in memory and (2) label what's found, neither of which the debugger API
could do before:

- memory.search (MemorySubscriber.cpp): Cheat-Engine-style scan of a memory
  range for a u8/u16/u32/float value, or a byte pattern with an optional
  wildcard mask.
- hle.data.list/add/remove/rename (HLESubscriber.cpp): manage ST_DATA
  symbols (structs, tables, buffers), mirroring the existing hle.func.*
  commands for functions. Needed a new SymbolMap::RemoveData, since only
  RemoveFunction existed - added following the same pattern.

Verified live against a running PPSSPP instance (game.status, cpu.stepping,
memory.search in u32/bytes/masked-bytes modes, and the full
add/list/rename/remove data-symbol lifecycle) via Tools/wsdbg.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-26 21:17:09 +02:00
Henrik RydgårdandClaude Opus 5 2fa8efad2b Document the WebSocket debugger interface
Add docs/WebSocketDebugger.md covering the transport, message protocol,
broadcast/request event catalog, how to enable it, LAN discovery, and how
the bundled JS web debugger (assets/debugger submodule) connects to it.
Point AGENTS.md at it so future sessions know it exists.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XDNwPPuidmNxQGRJxBuRL6
2026-07-26 21:01:28 +02:00