Warning: these may be some long articles
If you’re unfamiliar with how emulators work, aside from that they let you play videogames on your computer, the basic explanation is that the software you’re using is a code version of the original concept. Instead of the NES hardware reading and acting on the instructions contained in the ROM code on the cartridge, a program handles the CPU instructions, creates its own RAM, and maps graphical output instructions to visual output on your screen. This is incredibly complex, and hard to get the hang of, but it’s also a lot of fun, and provides some interesting problems to solve.
For instance, the NES hardware is a little idiosyncratic, and often restrictive in what it allowed programmers to be able to do. As a result, NES game programmers learned to exploit aspects of the hardware in very interesting ways, relying on the exact hardware implementation’s quirks to produce the result. This could mean that a “perfect” emulator that runs each component exactly may not run games properly.
Let’s take a look at the NES hardware. The NESdev wiki has been an amazing resource so far, and it’s a great place to start from. In these really early stages, gathering an idea of the hardware to be implemented and a rough sketch of how things fit together would be useful.
The goal of the first phase was to get a rough outline of the code and get a few instructions working. In order to do this a few things need completing:
- Basic CPU emulation What flags and registers does the CPU use? How does it calculate clock cycles for synchronization?
- Memory Mapping How do different parts of hardware map to addresses in memory? (this is the primary way that the CPU communicates with other hardware parts)
- Basic ROM Loading. Where is the executable data stored in the data from the cartridge?
- Ability to debug instructions Let’s be real, I have no clue what I’m doing with a lot of this, I’m going to need something to check against when I get stuck.
The NES CPU core is based on the 6502 processor and runs at approximately 1.79 MHz. Reading this PDF helped immensely. The 6502 has the following registers:
- A Accumulator Register
- X, Y Index Registers
- SP Stack Pointer
- P Program Counter
- S Status Flag
At its most simplest, a CPU is only really doing a few simple things. We fetch a byte from memory, decode the opcode, and take some action based on it. And then we do it again. And again. Until we have a reason not to. The CPU is where I’m going to start, and in the next post I’ll talk a bit about how that’s implemented.