Project / 01
6502 Microprocessor Emulator
I completed and tested an unfinished standalone MOS 6502 CPU core in C++, building on the original CPU branch. My contribution focuses on finishing the processor execution path, correcting CPU behaviour, and making the implementation verifiable through instruction-level tests.
Architecture / Request path
How the pieces connect.
- 01Fetch opcode
- 02Decode
- 03Resolve address
- 04Execute
- 05Update CPU state
Interactive / Safe CPU lab
Step through the completed core.
This bounded browser adapter follows the same register, memory, opcode, flag, and cycle model as my completed C++ core. The default bytes are the repository’s example: LDA #$05, ADC #$03, and STA $0200.
Preparing CPU…
Bounded64 program bytes · 64 instructions · fixed 64 KB memory · writes limited to $0200–$02FF · unsupported opcodes halt safely
- A
- $00
- X
- $00
- Y
- $00
- SP
- $FD
- PC
- $8000
- Status
- $24
- Cycles
- 7
- [$0200]
- $00
No instructions executed yet.
01 / Problem
Why I built it
The original CPU branch provided an educational 6502 foundation, but the standalone processor was unfinished. I took that branch into my fork to complete the execution path, correct behavioural issues, and turn it into a buildable, testable CPU project.
02 / Design
System shape
I preserved the original project’s separation between the CPU, bus, RAM, opcode table, addressing modes, and instruction operations. My changes connect those pieces into a working execution loop, add reset and interrupt behaviour, correct addressing and flag bugs, and keep the fork intentionally scoped to the standalone MOS 6502 rather than NES graphics, audio, or cartridge hardware.
03 / Implementation
What the code actually does
- 01
Fixed the existing build and 64 KB memory-size problems, then connected the CPU and bus correctly
- 02
Completed the instruction execution path through the 256-entry opcode table and addressing modes
- 03
Implemented reset, IRQ, NMI, BRK, RTI, missing ADC, SBC and NOP behaviour
- 04
Corrected signed branches, zero-page wrapping, status flags, register operations, and cycle penalties
- 05
Added packed-BCD arithmetic, a runnable machine-code example, and 13 instruction-level CPU tests
04 / Decisions
Engineering choices
Preserve the original architecture
I extended the base repo’s CPU structure instead of replacing it, keeping its learning path and original authorship visible.
Prove behaviour with tests
Instruction-level tests cover reset, memory boundaries, arithmetic, flags, BCD mode, branches, subroutines, stack behaviour, transfers, BRK and RTI.
Keep the scope honest
The fork implements the standalone processor only. It intentionally does not claim cartridge loading, PPU, audio, or other NES hardware.
Concrete outcomes
- 01
- 13 CPU tests passing
- 02
- C++17 clean build
- 03
- $08 stored at $0200
Observed while building
- Completing an existing codebase requires first understanding and preserving its original design decisions.
- Small mistakes in flags, signed branches, or program-counter movement surface many instructions later.
- Tests made it possible to separate my completion work from assumptions about what the original branch already handled.
Next iteration