Hello everyone, in this blog post I will be explaining how and why I wrote the c6502, an integrated debugging and emulation suite that I developed for the MOS 6502.
The MOS 6502 is one of the most influential microprocessors in computing history. Introduced in 1975 by MOS Technology, the 6502 was designed to be a low-cost, high-performance alternative to the more expensive processors of the time, such as Intel’s 8080 and Motorola’s 6800. What made the 6502 revolutionary was its affordability, which opened the door for hobbyists, smaller companies, and educational institutions to embrace computing at a time when prices were otherwise prohibitive.
The 6502 found its way into iconic devices like the Apple I and Apple II, the Commodore PET, and the Atari 2600, fueling the growth of personal computing and gaming in the late 1970s and early 1980s. Its simple yet powerful instruction set made it an excellent learning tool for budding engineers and programmers. Despite its simplicity, the 6502's efficiency and low transistor count allowed it to run at competitive speeds, solidifying its place in computing history. The design of the 6502 influenced later processors and remains a classic example of 8-bit microprocessor architecture.
When I started tinkering with 6502 assembly, I quickly realized there wasn’t a single tool that combined all the features I needed. Sure, there were great emulators, solid debuggers, and even some decompilers, but they were all separate. Switching between different programs disrupted the workflow, and I found myself wishing for an all-in-one tool that could handle emulation, debugging, and decompilation seamlessly. So, I created one :)
My biggest goal while writing c6502 was to make this software actually run the assembly and binary files written for mos6502. And that's what happened. For this, I used the ca65 assembler and ld65 linker provided by cc65 and created my binary files. Then I was able to use these binary files with c6502.
A real 6502 code and binary that runs assembled on c6502:
Another goal of mine was to be able to monitor the changes in memory and registers in real time. I made this possible with the c6502.
In c6502, the emulation process is designed to closely mimic the behavior of the MOS 6502 processor, step by step. Let’s take a deeper dive.
In c_reset()
the registers (A, X, Y, PC, SP) and flags are initialized. Acc, X, Y → 0; PC → 0x0000; flags cleared so the CPU starts in a clean state.
The opcode is fetched from memory at PC
and logged:
uint8_t opcode = memory->mem[cpu->reg.pc];
printf("PC: 0x%04x, Opcode: 0x%02x\n", cpu->reg.pc, opcode);
The fetched opcode is matched against the instruction table:
for (size_t i = 0; i < set_size; i++) {
if (opcode == instruction_set[i].opcode) {
instruction = &instruction_set[i];
break;
}
}
Addressing mode determines how to obtain operands (immediate/absolute/zero page/etc.). Example absolute:
uint16_t address = ((mem->mem[cpu->reg.pc + 2] << 8) | mem->mem[cpu->reg.pc + 1]);
Example LDA handler:
void lda_handler(c_cpu_t *cpu, m_memory_t *mem, uint16_t address)
{
cpu->reg.acc = mem->mem[address];
if (cpu->reg.acc == 0) {{ SET_FLAG(cpu->reg, FLAG_ZERO); }}
else {{ CLEAR_FLAG(cpu->reg, FLAG_ZERO); }}
if (cpu->reg.acc & 0x80) {{ SET_FLAG(cpu->reg, FLAG_NEGATIVE); }}
else {{ CLEAR_FLAG(cpu->reg, FLAG_NEGATIVE); }}
}
Reset → fetch → decode → address → execute, looped—mirroring the original hardware while exposing a transparent, real-time debugging view.
The GUI keeps everything in one place for emulation, debugging, and reverse engineering.
Main display area for visual output from the emulated system.
Live disassembly that follows execution and highlights the current instruction.
Real-time PC, SP, A, X, Y and flags view for quick feedback.
Inspect memory values and how instructions affect them in real time.
All critical info at a glance without switching tools—ideal for learning, debugging, and analysis.
Developing c6502 merged my love for retrocomputing with low-level programming and tool building. The result is a comprehensive suite that integrates emulation, debugging, and decompilation into a single, user-friendly tool. If you’re interested in trying it, grab it on GitHub.