Commit Graph
31 Commits
Author SHA1 Message Date
Henrik RydgårdandClaude Opus 5 ebd2b4757f ImDebugger: prefill the assemble box with the instruction that's there
Assembling started from an empty box, so replacing an instruction meant reading
it off the screen and retyping it, and tweaking one operand meant typing the
whole thing. It now opens with the current instruction already in it, selected,
so typing replaces it and editing is just editing.

Disassembled without symbol substitution for this, unlike what the view itself
shows: a branch displayed as a function name doesn't assemble back, and the
whole point of the prefill is that it's valid input.

Selection is only applied on this path. onChar() also seeds the box - with the
character the user just typed over an instruction - and there the text is the
start of what they're writing, not something to overwrite.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 13:42:14 +02:00
Henrik RydgårdandClaude Opus 5 a0fbf32469 ImDebugger: add a filter box above the symbol list
A game with symbols loaded puts a few thousand functions in that list, and the
only way to reach one was to scroll. Typing part of a name now narrows it,
case-insensitively.

The filter produces a list of indices into the symbol cache rather than a
filtered copy of it, so selectedSymbol_ keeps meaning the same thing whether or
not a filter is active - the Edit Symbol box above the list needs it to index
the cache. Rebuilt when the filter text changes or the symbol map reloads, not
per frame, and the list clipper works off the match list so a filter that
matches everything costs no more to draw than before.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 13:42:13 +02:00
Henrik RydgårdandClaude Opus 5 d8a1808b3d ImDebugger: add "Run to here, next frame", gated on the flip count
Prototype of the frame-gated run-to-cursor idea. "Run to here" stops at the
first hit, which isn't what you want for an address hit many times per frame -
you end up stepping through the rest of the current frame to reach the state
you actually care about.

Built on machinery that was already there rather than a new stepping mode: the
one-shot breakpoint behind run-to-cursor already takes a condition (step-into
uses it to pin a step to one thread), and a hit that fails the condition leaves
it armed for the next one. So "the next frame" is just a condition that isn't
true yet - here "flipcount > <now>".

Counting presented frames rather than vblanks matters for a game that doesn't
render at the full refresh rate: at 30fps there are two vblanks per frame, so a
vblank-based condition would let you through halfway into the frame you were
trying to skip. The flip side is that the counter only advances when the
framebuffer actually changed, so if the game has stopped drawing - or is wedged
in the loop you're trying to debug - this never trips and the core keeps
running.

Both counters are exposed to the expression parser, next to
threadid/moduleid/usec/ticks, so they're usable in ordinary breakpoint
conditions and cpu.evaluate too, not just from this menu item: "flipcount" for
presented frames and "vcount" for the PSP's own vblank counter, which is what
sceDisplayGetVcount returns and is the one a game's own timing is written
against.

Verified with a headless session: across a second of emulated time flipcount
went 120 -> 172 and vcount 119 -> 172 (a game rendering every vblank, so they
track).

pspautotests 314/314, UnitTest 55/55.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 10:59:08 +02:00
Henrik RydgårdandClaude Opus 5 665cd9808a ImDebugger: bring back assembleOpcode, with an ImGui popup for the input
The disassembly view's assembler has been commented out since the ImGui
debugger was written, because it asked for the opcode with InputBox_GetString,
which is Win32-only. Replaced with a small popup built from ImGui, so it works
everywhere the ImGui debugger does.

Splitting it in two is what the popup costs: assembleOpcode() only records the
address and seed text and raises a flag, since ImGui popups have to be opened
and drawn inside the frame that owns them, and applyAssembly() does the work
when the input is submitted. The flag is consumed in PopupMenu(), next to the
existing rename-function popup, which had already established the pattern. The
new state lives in ImDisasmView.

Behaviour follows the Win32 version, including "register=expression" assigning
a register rather than assembling, and falling through to the assembler when
the left side isn't a register name. Two differences, both deliberate:

- Errors appear inside the popup instead of a modal message box, and the popup
  stays open with the text still in it, so a typo can be corrected instead of
  retyped.
- No Core_RunOnCPUThread() around the register write or the assemble. The Win32
  debugger needs it because its dialogs are pumped by the WinMain message loop,
  a genuinely different thread; UI/ImDebugger always runs on the same thread as
  Core_RunLoopUntil(), so it can touch this state directly (see AGENTS.md).

Also updated for the current APIs while it was dead: MipsAssembleOpcode() takes
an out-parameter for the error now rather than MIPSAsm::GetAssembleError(), and
expression evaluation goes through initExpression()/parseExpression().

The core has to be stepping, checked both when the popup is requested and again
on submit - the popup is modeless, so the core can be resumed while it's open.

The keyboard shortcut (A) is re-enabled along with the context menu item.
onChar(), which seeds the popup with the character typed over an instruction,
already called this and needed no change - it still has no caller of its own,
which is a separate pre-existing gap.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01GZq8ZtJmFY7bkX5FVkr3P9
2026-08-18 10:59:08 +02:00
Henrik Rydgård f5bd302694 Improve DescribeAddress, show the description of the currently selected line in disassembly 2026-08-14 14:38:33 +02:00
Henrik RydgårdandClaude Sonnet 5 b1f0112cef Debugger: Remove opcode-fusion display and fix cpu step size units
DisassemblyManager used to fuse lui+addiu/load/store into single pseudo-
instructions ("li", fused loads/stores) for display. This only applied to a
handful of opcodes, complicated DisassemblyManager, and was the root cause of
a stepping bug: Core_PerformCPUStep's Into/Over cases treated stepSize as a
byte count, while the WebSocket cpu.stepInto handler computed it as an
instruction count (needed to step over a whole fused macro in one go) - so a
plain, non-fused stepInto silently executed zero instructions.

Removed the fusion logic entirely (DisassemblyMacro, DISTYPE_MACRO) - every
disassembly line is now exactly one 4-byte instruction. With that,
"how many instructions does this line span" is always 1, so the
getInstructionSizeAt() byte-size queries in the legacy Windows and ImGui
debuggers are gone too; step requests just pass 1. Core_RequestCPUStep's
stepSize is now consistently in instructions everywhere.

Also fixes the PPSSPPHeadless build, broken since 0ed1f3e added
OpenWebDebugger() (which calls System_LaunchUrl) without a headless stub.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Hqm11k99viLfbJm2MkH4BH
2026-08-08 11:16:36 +02:00
Henrik Rydgård ff37cbe184 Minor memory safety fixes 2025-05-14 09:39:09 +02:00
Henrik Rydgård ad17ec5fc8 Minor reorganization in ImDebugger 2025-04-09 11:58:31 +02:00
Henrik Rydgård 597be1c9bc Stop pretending that DisassemblyManager isn't a singleton - it currently is. 2024-12-12 19:25:04 +01:00
Henrik Rydgård 20a17a0e8d Reorganize DebugInterface etc a bit.
KernelThreadDebugInterface no longer has a useless copy of a MIPSDebugInterface.
2024-12-12 18:54:46 +01:00
Henrik Rydgård 3844f751b3 Warning fix 2024-12-12 17:47:37 +01:00
Henrik Rydgård c85266359f More memory view work 2024-12-12 17:47:37 +01:00
Henrik Rydgård 39ffe92e0a LR->RA rename, fixes 2024-12-12 17:47:37 +01:00
Henrik Rydgård 11e858f0f1 Add input to memview. Use step counters to control updates. 2024-12-12 17:47:37 +01:00
Henrik Rydgård 20c19f96e0 More memview work 2024-12-12 17:47:37 +01:00
Henrik Rydgård 637d15434e Minor code cleanup. Add Goto LR button 2024-12-10 22:56:03 +01:00
Henrik Rydgård f665878b3c Fix crash with mismatched pushfont/popfont 2024-11-28 09:50:29 +01:00
Henrik Rydgård 47d8e292eb ImDebugger: Add basic filesystem browser. Add partial support for "save file dialogs" to System. 2024-11-25 23:03:15 +01:00
Henrik Rydgård 20c4649963 Fix step over, other stepping issues 2024-11-25 19:02:17 +01:00
Henrik Rydgård 9801f4c810 Add "Rename function" functionality. Fix some input and stepping bugs. 2024-11-25 10:18:56 +01:00
Henrik Rydgård 3cba1135d5 Add basic breakpoint editing window. Need UI refinement 2024-11-25 00:23:28 +01:00
Henrik Rydgård e31636caec Still use a fixed-width font for the disassembly (might change this) 2024-11-25 00:03:06 +01:00
Henrik Rydgård 6b11ebfb9f ImDebugger: Fix a bunch of keyboard shortcuts 2024-11-23 23:23:52 +01:00
Henrik Rydgård c5eb600044 Add search functionality to disassembler 2024-11-23 23:23:52 +01:00
Henrik Rydgård 194b2ce076 Ge Debugger: Add a framebuffer listing, along with some plumbing 2024-11-23 23:23:48 +01:00
Henrik Rydgård 68b496a868 Nemo's buildfixes 2024-11-21 15:48:17 +01:00
Henrik Rydgård 80474fd0f0 Some cosmetic fixes to the ImGui debugger 2024-11-07 20:11:23 +01:00
Henrik Rydgård 99eb0bbd64 Improve register view, fix follow PC, some cleanup 2024-11-07 11:10:16 +01:00
Henrik Rydgård 9c92978fcc ImGui debugger: assorted work 2024-11-07 11:10:16 +01:00
Henrik Rydgård 84a0293e54 Add basic register view 2024-11-07 11:10:16 +01:00
Henrik Rydgård cf6d06c56a Start work on imdbg 2024-11-07 11:10:12 +01:00