Pure-C# 6502 emulator
KullGames.RetroCore
A real, from-scratch MOS 6502 (NMOS) CPU core - pure C#, single-stepped through hand-assembled machine code.
This page is a static render of the console app's real captured output. The CPU is not
reimplemented for the web - it is reused directly from the library leaf
OnlyCSharp/1.8/ComputerEngineering.Processors.M6502 (Nmos6502 : M6502Core), the
full 256-entry NMOS opcode table running against an injected IMemoryBus8. The app supplies
only a flat 64 KiB RAM bus; every register transition, flag update, and branch below comes straight out
of the real emulator.
The program (hand-assembled at $0600)
$0600: A2 00 LDX #$00 ; X = 0 $0602: 86 10 STX $10 ; loop: mem[$10] = X $0604: E8 INX ; X++ $0605: E0 0A CPX #$0A ; compare X to 10 $0607: D0 F9 BNE $0602 ; if X != 10, branch back (offset -7 = 0xF9) $0609: 00 BRK
The reset vector ($FFFC/$FFFD) points at $0600, so the CPU boots straight into it.
Real captured output
KullGames.RetroCore -- a real MOS 6502 (NMOS) core, OnlyCSharp/1.8 ComputerEngineering.Processors.M6502 Program: count X from 0 to 9, storing X into zero-page $0010 every pass, then BRK. #1 PC=$0602 A=$00 X=$00 Y=$00 P=$26 #2 PC=$0604 A=$00 X=$00 Y=$00 P=$26 #3 PC=$0605 A=$00 X=$01 Y=$00 P=$24 #4 PC=$0607 A=$00 X=$01 Y=$00 P=$A4 #5 PC=$0602 A=$00 X=$01 Y=$00 P=$A4 #6 PC=$0604 A=$00 X=$01 Y=$00 P=$A4 #7 PC=$0605 A=$00 X=$02 Y=$00 P=$24 #8 PC=$0607 A=$00 X=$02 Y=$00 P=$A4 #9 PC=$0602 A=$00 X=$02 Y=$00 P=$A4 #10 PC=$0604 A=$00 X=$02 Y=$00 P=$A4 #11 PC=$0605 A=$00 X=$03 Y=$00 P=$24 #12 PC=$0607 A=$00 X=$03 Y=$00 P=$A4 #13 PC=$0602 A=$00 X=$03 Y=$00 P=$A4 #14 PC=$0604 A=$00 X=$03 Y=$00 P=$A4 #15 PC=$0605 A=$00 X=$04 Y=$00 P=$24 #16 PC=$0607 A=$00 X=$04 Y=$00 P=$A4 #17 PC=$0602 A=$00 X=$04 Y=$00 P=$A4 #18 PC=$0604 A=$00 X=$04 Y=$00 P=$A4 #19 PC=$0605 A=$00 X=$05 Y=$00 P=$24 #20 PC=$0607 A=$00 X=$05 Y=$00 P=$A4 #21 PC=$0602 A=$00 X=$05 Y=$00 P=$A4 #22 PC=$0604 A=$00 X=$05 Y=$00 P=$A4 #23 PC=$0605 A=$00 X=$06 Y=$00 P=$24 #24 PC=$0607 A=$00 X=$06 Y=$00 P=$A4 #25 PC=$0602 A=$00 X=$06 Y=$00 P=$A4 #26 PC=$0604 A=$00 X=$06 Y=$00 P=$A4 #27 PC=$0605 A=$00 X=$07 Y=$00 P=$24 #28 PC=$0607 A=$00 X=$07 Y=$00 P=$A4 #29 PC=$0602 A=$00 X=$07 Y=$00 P=$A4 #30 PC=$0604 A=$00 X=$07 Y=$00 P=$A4 #31 PC=$0605 A=$00 X=$08 Y=$00 P=$24 #32 PC=$0607 A=$00 X=$08 Y=$00 P=$A4 #33 PC=$0602 A=$00 X=$08 Y=$00 P=$A4 #34 PC=$0604 A=$00 X=$08 Y=$00 P=$A4 #35 PC=$0605 A=$00 X=$09 Y=$00 P=$24 #36 PC=$0607 A=$00 X=$09 Y=$00 P=$A4 #37 PC=$0602 A=$00 X=$09 Y=$00 P=$A4 #38 PC=$0604 A=$00 X=$09 Y=$00 P=$A4 #39 PC=$0605 A=$00 X=$0A Y=$00 P=$24 #40 PC=$0607 A=$00 X=$0A Y=$00 P=$27 #41 PC=$0609 A=$00 X=$0A Y=$00 P=$27 #42 PC=$0000 A=$00 X=$0A Y=$00 P=$27 Final value at $0010: 9 (0x09) Summary: 42 instructions retired, final X register = 10 (0x0A)
The real result: 9, not 10
STX $10 runs before
INX each pass, so the ten stores write 0,1,2,...,9 - the byte left at $0010 is
9 (0x09), while X counts one step further to
10 (0x0A) to satisfy the CPX #$0A exit test.
Step #42 executes BRK, which (this demo wires no BRK/IRQ vector at $FFFE/$FFFF) faithfully
jumps PC to $0000 - real 6502 semantics, not a harness bug.