211. Cpu trace formatter

add `emulator/debug/cpu_trace.py::format_cpu_trace`.

Lesson 211 of 356 · tests/chapter_01_cpu/test_211_cpu_trace_formatter.py

Why this step exists

In this step, add a formatter that provides observability before ROM-log comparison without coupling debugging to CPU execution. Its line reports the next PC/opcode and the A, X, Y, P, and S register values before execution:

8000 A9 A:00 X:00 Y:00 P:04 S:FD

Suggested implementation

from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from emulator.cpu.cpu import CPU


def format_cpu_trace(cpu: CPU):
    opcode = cpu.bus.read(cpu.pc)
    return f"{cpu.pc:04X} {opcode:02X} A:{cpu.a:02X} X:{cpu.x:02X} Y:{cpu.y:02X} P:{cpu.p:02X} S:{cpu.s:02X}"

Invariants: formatting performs one non-advancing bus read, returns uppercase fixed-width hexadecimal fields, and leaves PC, registers, and flags unchanged. Do not use CPU.fetch_byte() or call CPU.step(); both confuse observation with execution, and fetch_byte() advances PC. Out of scope: ROM and cartridge support belong to later numbered steps.

Run this lesson

uv run pytest tests/chapter_01_cpu/test_211_cpu_trace_formatter.py -v