NES Introduction
In this project you will be creating an emulator for the Nintendo Entertainment System, or NES. Here we will briefly talk about what the NES is, and how it works.
NES
The NES is a simple game console created by Nintendo, in 1985. To play a game on the NES you insert a game cartridge. In early games, this cartridge only contained a read-only memory (ROM) chip. Later on, the cartridges also included random-access memory (RAM) and even some expansion chips for extra video or sound capabilities. Famous games like Super Mario Bros. 1, 2 and 3, The Legend of Zelda and Metroid were originally made for this console.
NES Architecture
The NES consists of four main chips.
6502
First off, there's the 6502 CPU, which you will be emulating during the project.
This CPU executes the instructions on the game cartridge. The 6502 used in the NES
is slightly special, since decimal mode is
disabled on it. NOTE: That means you do not need to implement decimal mode!
Ram
There is the RAM chip. This contains a bit of modifiable storage space. And it's not much. Only 2 Kilobytes
of ram are available. This is pretty much nothing compared to modern standards.
PPU
The PPU or the Picture Processing Unit is responsible for drawing on the screen. You can compare it to a modern-day
GPU. However, the PPU was a lot less configurable than GPUs, and could only work with 2d graphics directly from the
cartridge. We already provide you with a working PPU, so this is not something you need to emulate. However, the CPU
and PPU need to be able to communicate. This is something you will have to support.
The PPU has its own memory space. The PPU has its own ram, and parts of the cartridge called character rom (because the character data is stored there) can only be accessed by the PPU.
APU
Finally, there is the APU or the audio processing unit.
This chip is not part of the project. We haven't implemented it for you, and you don't need to implement it.
However, you can of course implement it as a bonus.
Cartridge
Both the CPU and the PPU can interact with the cartridge. A cartridge was used to physically distribute video games for the NES. The Cartridge contains two kinds of ROM, and usually some RAM.
- Character ROM, data for the PPU like sprites, backgrounds, etc.
- Program ROM, data and instructions for the CPU?
On some cartridges, the RAM was protected with a little battery. This was useful for saving game progress. Note that you don't actually have to save RAM contents after the emulator finishes. You could do this as a bonus though.
For emulators, cartridges are usually stored as .nes
files. These files contain a small
header with information about the cartridge, followed by the raw binary data of the ROM.
Mapper
The memory mapper is a chip on the cartridge, which can change the way memory is laid out. Different games may have different
mappers, and in the .nes
cartridge file format there's a number specifying which mapper
it requires.
Mappers are necessary, because the memory space of the NES is only 64Kb large. A memory space is all the places the CPU can access. The reason for this limitation is that the address of a memory location can only be 16 bits large on the NES. However, games are routinely larger than 64Kb. Super Mario Bros 3 is 384Kb large for example.
The most common mapper is the MMC1. The MMC1 can support up to 256Kb of program data. It does this by changing parts of memory on-demand. At any time, two banks of ROM are loaded into memory. One bank from 0x8000 to 0xbfff, and one from 0xc000 to 0xffff. However, there are actually up to 32 banks available. By writing to a specific memory address (this is well documented), the CPU can order the mapper to change which bank is located at one of these two locations.
NOTE: There's also the NROM mapper. This is not a mapper at all. The bank assignment cannot be changed. Therefore, it's very simple to implement and a good starting point.
Controller
Finally, there is the controller.
We will provide you with code that can process keyboard input.
You should then pass this information to the CPU in the appropriate form.
Unofficial instructions
NOTE: This is bonus. If you are not doing this bonus, this part is not necessary.
If you look at this list of all the instructions supported by the NES, you see there are holes in the table. Games are not supposed to use these opcodes. If they do, the behavior is undocumented.
However, programmers figured out that the CPU does not always crash when these opcodes are used. The following things can happen if they are used:
- The CPU jams. It halts execution and just crashes.
- Nothing happens. This is equivalent to the NOP instruction. However, sometimes these instructions are longer than the normal 1-byte NOP instruction, which can be useful sometimes.
- Something random happens. Sometimes this depends on the temperature of the CPU
- Something consistent happens. An operation is executed which is not normally supported by the CPU.
The last category is most interesting. For example, opcode 0xa3 is the LAX "instruction". It's the same as executing an LDA and LDX instruction at the same time. Some games have actually started to use these instructions.