210. Cpu verification

verify the completed CPU instruction slice.

Lesson 210 of 356 · tests/chapter_01_cpu/test_210_CPU_VERIFICATION.py

In this step, integrate existing `emulator/cpu/cpu.py::CPU.reset/CPU.step, emulator/cpu/opcodes.py::OPCODE_TABLE, instruction symbols lda, ldx, ldy, sta, stx, sty, adc, sbc, inc, dec, and_a, or_a, or_e, bit, cmp, beq, bne, pha, pla, php, plp, asl_a, lsr_a, rol_a, ror_a, tax, txa, tay, tya, txs, tsx, inx, dex, iny, dey, jsr, rts, clc, sec, cld, sed, clv, cli, sei, and nop in emulator/cpu/instructions.py, plus emulator/bus/cpu_bus.py::CpuBus.read/write and emulator/memory/fake_rom.py::FakeROM.read/write`.

The complete transition is test support, added to `tests/helpers.py`::

from emulator.memory.fake_rom import FakeROM

def make_cpu_with_rom():
    rom = FakeROM()
    bus = CpuBus(program_rom=rom)
    return CPU(bus), bus, rom

def write_reset_vector(rom, addr: int):
    rom.write(0x7FFC, addr & 0xFF)
    rom.write(0x7FFD, (addr >> 8) & 0xFF)

def load_program(rom, start_addr: int, program: list[int]):
    for offset, byte in enumerate(program):
        rom.write((start_addr - 0x8000) + offset, byte)

Why this step exists

Although this validation adds no production implementation, short byte programs expose integration defects hidden by direct operation tests. Invariants include sequential PC ownership by CPU.step, balanced stack round trips, branch targets relative to post-operand PC, preservation of unrelated flags, and RAM writes at the addressed locations. The misconception is that passing isolated instruction tests proves dispatch, PC, stack, and flag interactions also compose correctly.

Out of scope: the trace formatter is step 211. The iNES reader, cartridge/NROM mapping, PPU, VBlank, and NMI belong to later steps and must not be anticipated here.

Run this lesson

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