I got it in my head the other day to start writing a NES emulator, as I didn’t really have a current home project on my plate. I’ve dabbled in virtual machines before, having tried to build an implementation of the DCPU computer, but I only got so far with that one since there wasn’t really anything to run. The NES, though, has no end of documentation and people still releasing code for it.
Why am I doing this?
I wanted to have a look at something a little older and maybe a bit easier to implement as an emulator. The NES was a console that was on its way out in favour of the SNES when I was a young child, but my friend had one and we’d still play it a lot, namely Kirby and Smash TV.
First steps
My first step was to read a bunch of documentation and watch a few videos. I stumbled upon One Lone Coder’s YouTube series, and was impressed by his way of explaining things. His repo is on Github, and a lot of my code is a direct port to golang from his work.
I’ve also been trying to work a lot out myself by reading the NESdev wiki, which has a huge wealth of resources about how everything works under the hood.
The basic architecture looks as such
Where the CPU is an 8 bit MOS technology 6502 (with a few extensions) and the PPU a custom chip by Ricoh.
These components communicate over a bus, where each component has its own address range that it will listen to for read and write requests.
With this basic understanding, I started implementing it.
Implementation
To be honest, this is taking me a little longer to implement than I thought it would. I currently have a CPU that can run programs and a cartridge loader. I think I was a little too optimistic, but hey, I’ve learned a huge amount about virtual machines and hardware level implementations by undertaking this.
I’ve been quite surprised with how clever the system in places, having come into
software construction in an era where resources are less of a concern, seeing
all the little tricks to increase the amount of addressable memory available
blew my mind a little. Took a little getting used to, loading in two values
for my addresses, but it’s become second nature to type in uint16
or uint8
depending on where in the code the variable is being used.
My next two steps will be to implement a couple of mappers, which take read and write instructions and map them to various values, and to hopefully be able to pull the image data out of the cartridge.
I think my biggest problem is going to be the graphics, I’ve been trying to wrap my head around the scanlines and such, but it’s a bit of a world away from what I normally code. I’m having fun and learning, though, which is the whole reason I’m doing this to begin with. Hopefully I get it to a point where I’m happy to mark the repo as public on github.