Describe the bug
retro_cpu_jump reports a paused C64 jump as complete even though the underlying 6510 PC change is still deferred. This prevents debugger automation from safely chaining a jump with retro_step_instruction or injected-code cleanup: the next step can execute at the old PC, causing operations to run in the wrong order and produce misleading timeouts.
While the C64 is in Retro Debugger's normal debugger-paused state, retro_cpu_jump returns {"status":"jumped"} and retro_cpu_status shows the requested address. However, a subsequent retro_step_instruction executes the instruction at the pre-jump PC.
To Reproduce
-
Stop the C64 at BASIC's keyboard-idle loop $E5CD with a normal CPU breakpoint.
-
Confirm that machine state reports isPaused: true and CPU status reports pc: $E5CD.
-
While it remains paused, call:
{"platform":"c64","address":828}
(828 is $033C.)
-
Observe that retro_cpu_jump returns:
{"status":"jumped","address":828}
-
Observe that retro_cpu_status reports PC $033C.
-
Without resuming the emulator, call retro_step_instruction.
-
Observe that CPU status now reports PC $E5CF.
$E5CD contains the two-byte instruction LDA $C6, so reaching $E5CF shows that the step executed at the old PC. If the requested target, $033C, contains a single-byte instruction (for example, PHP), then a jump applied before stepping would instead stop at $033D.
This report concerns reassignment of the program counter while the machine is debugger-paused, both before the jump request and after the single step. It does not assert the same problem while the emulator is free-running: in ordinary sequential MCP use, VICE should process the deferred trap far sooner than a client can make its next MCP request.
Expected behavior
A jump requested while paused should have an unambiguous completion contract. retro_cpu_jump should not report success until the requested PC change has committed, so that a subsequent step executes at the requested target. The implementation may apply the PC change directly or allow VICE to process its trap and wait for confirmation before returning, while preserving the caller's paused state.
If waiting for commitment is not feasible, the tool should report that the jump is queued rather than applied and provide a reliable way to observe when it commits.
Actual behavior
retro_cpu_jump returns "status":"jumped".
- CPU status can show the requested target before the underlying 6510 PC changes.
- A single-step executes the instruction at the old PC.
- While the emulator is free-running, VICE should process the deferred PC change well before the next ordinary MCP request. The paused single-step workflow prevents that processing, and clients currently need indirect synchronization, such as a separate target breakpoint.
Source context
In the cloned source, CDebugInterfaceVice::MakeJmpC64() calls c64d_set_c64_pc() while paused. That path appears to update debugger-facing PC state and defer assignment to maincpu_regs.pc through interrupt_maincpu_trigger_trap().
The MCP retro_cpu_jump handler then returns:
{"status":"jumped","address":...}
without distinguishing a queued request from a committed PC change. The deferred-trap mechanism is the apparent cause; the stepping behavior above is the observed evidence.
Suggested fix
Could either apply paused jumps before reporting success, or expose the deferred state explicitly. For example, before the trap commits:
{
"status":"queued",
"requestedPc":828,
"applied":false
}
CPU status could also expose the committed and pending values separately, for example:
{
"pc":58829,
"pendingPc":828
}
Once committed, pendingPc could be absent or null, and the result could report applied: true.
Regression test
Pause at a known instruction, request a jump, perform one instruction step, and verify that the stepped instruction is at the requested target. If jumps intentionally remain deferred while paused, test that the tool reports the queued state rather than successful completion.
Describe the bug
retro_cpu_jumpreports a paused C64 jump as complete even though the underlying 6510 PC change is still deferred. This prevents debugger automation from safely chaining a jump withretro_step_instructionor injected-code cleanup: the next step can execute at the old PC, causing operations to run in the wrong order and produce misleading timeouts.While the C64 is in Retro Debugger's normal debugger-paused state,
retro_cpu_jumpreturns{"status":"jumped"}andretro_cpu_statusshows the requested address. However, a subsequentretro_step_instructionexecutes the instruction at the pre-jump PC.To Reproduce
Stop the C64 at BASIC's keyboard-idle loop
$E5CDwith a normal CPU breakpoint.Confirm that machine state reports
isPaused: trueand CPU status reportspc: $E5CD.While it remains paused, call:
{"platform":"c64","address":828}(
828is$033C.)Observe that
retro_cpu_jumpreturns:{"status":"jumped","address":828}Observe that
retro_cpu_statusreports PC$033C.Without resuming the emulator, call
retro_step_instruction.Observe that CPU status now reports PC
$E5CF.$E5CDcontains the two-byte instructionLDA $C6, so reaching$E5CFshows that the step executed at the old PC. If the requested target,$033C, contains a single-byte instruction (for example,PHP), then a jump applied before stepping would instead stop at$033D.This report concerns reassignment of the program counter while the machine is debugger-paused, both before the jump request and after the single step. It does not assert the same problem while the emulator is free-running: in ordinary sequential MCP use, VICE should process the deferred trap far sooner than a client can make its next MCP request.
Expected behavior
A jump requested while paused should have an unambiguous completion contract.
retro_cpu_jumpshould not report success until the requested PC change has committed, so that a subsequent step executes at the requested target. The implementation may apply the PC change directly or allow VICE to process its trap and wait for confirmation before returning, while preserving the caller's paused state.If waiting for commitment is not feasible, the tool should report that the jump is queued rather than applied and provide a reliable way to observe when it commits.
Actual behavior
retro_cpu_jumpreturns"status":"jumped".Source context
In the cloned source,
CDebugInterfaceVice::MakeJmpC64()callsc64d_set_c64_pc()while paused. That path appears to update debugger-facing PC state and defer assignment tomaincpu_regs.pcthroughinterrupt_maincpu_trigger_trap().The MCP
retro_cpu_jumphandler then returns:{"status":"jumped","address":...}without distinguishing a queued request from a committed PC change. The deferred-trap mechanism is the apparent cause; the stepping behavior above is the observed evidence.
Suggested fix
Could either apply paused jumps before reporting success, or expose the deferred state explicitly. For example, before the trap commits:
{ "status":"queued", "requestedPc":828, "applied":false }CPU status could also expose the committed and pending values separately, for example:
{ "pc":58829, "pendingPc":828 }Once committed,
pendingPccould be absent ornull, and the result could reportapplied: true.Regression test
Pause at a known instruction, request a jump, perform one instruction step, and verify that the stepped instruction is at the requested target. If jumps intentionally remain deferred while paused, test that the tool reports the queued state rather than successful completion.