Skip to content

retro_cpu_jump reports success before a paused C64 program counter change is applied #126

Description

@c64cryptoboy

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

  1. Stop the C64 at BASIC's keyboard-idle loop $E5CD with a normal CPU breakpoint.

  2. Confirm that machine state reports isPaused: true and CPU status reports pc: $E5CD.

  3. While it remains paused, call:

    {"platform":"c64","address":828}

    (828 is $033C.)

  4. Observe that retro_cpu_jump returns:

    {"status":"jumped","address":828}
  5. Observe that retro_cpu_status reports PC $033C.

  6. Without resuming the emulator, call retro_step_instruction.

  7. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions