Building an NES Emulator in C: Part 1 – Emulating the 6502 CPU
Over the course of a few posts, I will be constructing an NES emulator that will allow you to play NES ROMs. Today’s post is the first in this series, where I will be walking through the process of emulating the CPU the NES used, the MOS 6502. STRUCTURE The 6502 has 6 primary registers we need to emulate in our program. The A register is the accumulator, which is 1 byte long The X register is an index register, which is also 1 byte long The Y register is another index register, also 1 byte long The Program Counter is 2 bytes long, allowing for accessing 65536 memory locations The Stack Pointer is 1 byte long, allowing a 256 byte stack The P register is a status register that is 1 byte long, containing the CPU status flags Below is the struct I used for the 6502 typedef struct { uint8_t A ; uint8_t X ; uint8_t Y ; uint16_t pc ; uint8_t S ; uint8_t P ; } cpu_6502 ; MEMORY The 6502 can read up to 64kb of memory thanks to the 2 byte long program counter. For my implementation, the memory is just a simple uint8_t array declared like so: uint8_t memory[65536] = {0}; This just implements an array of 65536 bytes that we will load programs into, that the CPU will then step through. However, we need to have a function that is able to decode the commands. OPCODES An opcode (operation code) is a number that represents an instruction for the CPU. The 6502 has 56 distinct (useful) opcodes I will be emulating today. A full list of the opcodes can be found in this handy little table. Since there are so many opcodes, I will not go through them all. The full code can be found in my GitHub repo here: https://github.com/benjaminavachon/6502-emulator Here we can discuss a few of the operations so you can get a feel for what they do. The first one we will discuss is very simple. It is LDA; it simply loads the piece of data after the opcode stored in memory into the A register and increments the program counter to the next memory address. A simple example of this would be: LDA 0x05 This i