Developing a NES Emulator Part 1 : Overview

Ozan Armağan
8 min readJan 20, 2022

Nintendo Entertainment System, short for NES, is one of the greatest legends of the 80s and 90s.

Nintendo Entertainment System (NES)

This console, which remained on the market between 1985 and 2003 and sold 61 million units all over the world, continued its existence for many years through its very similar clones called “FamiClone” after 2003.

In this series of articles, I have prepared a guide for you on how to develop an emulator where you can play the games of this famous and legendary console.

Before going into the details of the console, let’s talk about what an emulator is.

An emulator is a software that emulates another computer environment in hardware or software, in any computer environment. The purpose of emulators is to simulate software to hardware and to run various data that can normally only work on its own system in other environments.

(Wikipedia)

So what we’re going to do is; this will consist of imitating all the hardware of the console, the architecture that connects the hardware, and the general operation of the console. Of course, since we will emulate a physical hardware in software in a virtual environment, we will have to go around some processes by following different methods at some points, and in some cases, we will be able to handle the necessary processes more easily because we are not dependent on physical conditions.

Development Environment

Now, after first introducing our console -even though I don’t think it’s really necessary since it’s quite famous- and after defining what the emulator is, I would like to talk about the development environment that I will use in this series of articles before I take a look at the structure of our console.

First of all, since we will emulate a physical hardware, we have to consider performance and efficiency when choosing the programming language we will develop, as every emulator basically does, although the NES actually has a relatively primitive structure today. That’s why I chose to develop in C++.

In addition, we need to use a library to reflect the images we have obtained to the screen via the video card, to deliver the sound waves we will obtain virtually to the sound card and output them, and finally to take the inputs from the keyboard to control our console. The SDL (Simple DirectMedia Layer) library, which has been developed here for about 24 years and works regardless of platform (Windows, Linux, Mac OS), is quite sufficient and will make our work much easier.

Structure of SDL Layers

However, I would like to point out that the choices I make here are my personal preferences, and you can develop using any programming language and library you want, as long as you stick to the general architecture and algorithms while following this series of articles.

NES Architecture Overview

When we look at the hardware, since the analog TV systems around the world are divided into 2 different standards, NTSC (National Television Standards Committee) and PAL (Phase Alternating Line), there are actually 2 different versions of both the console and the cartridges of all the games of the console.

NTSC vs. PAL

Of these two standards, NTSC is used in the North American continent, a part of the South American continent and a part of the Far East; PAL is the system used in the rest of the world.

Worldwide PAL vs NTSC Map (Vuze Wiki)

These two standard differences have caused NES to have two separate versions, and these two versions have different hardware. Although there are many factors that create this difference, the most important difference for developing emulators is the refresh rate difference between the two standards.

NES NTSC vs. PAL Differences Table (NESDev Wiki)

NES consoles with the NTSC standard offer a refresh rate of 60hz (60 frames per second), while those with the PAL standard offer a refresh rate of 50hz (50 frames per second).

In addition, as seen in the table above, this difference also affects many features such as CPU cycle required per frame, VBlank period (we will see this frequently in the following sections), which are important for the emulator.

While we are developing, we will use the NTSC version of the console both because it offers a more fluid experience due to the higher refresh rate and because it is similar to the refresh rate standards of the monitors we use today, and all the sections we will process from here on will proceed in accordance with this standard.

Processor : MOS6502

Before moving on to the processor that NES uses, to give general information about processors and their tasks in computer organization,

A processor is an integrated circuit composed of chips, which forms the basic processing unit of the computer, interprets and executes given commands in a way that can perform certain logic and mathematical operations electronically.(Oxford)

In other words, the processor forms the basis of the computer and performs the necessary mathematical and logical operations. While doing these, it works in a loop that we call Fetch — Decode — Execute. While working in this loop, it first reads the data at the address indicated by the Program Counter in the memory (Fetch phase), interprets the next operation from this data (Decode phase), and finally takes the necessary data from the register or memory and puts it into action (Execute phase).

When we look at the MOS6502 processor, which gives the processing power to the NES, it is a very famous processor used not only in the NES, but also in many other computers and game consoles of the Apple I, Apple II, Commodore64 era.

Today, when we look at it, the MOS6502 is a processor that is relatively easy to emulate both with 8-bit registers and with its opcodes.

MOS6502 has the capacity to interpret 256 different opcodes, but it uses only 151 of this capacity, so it actually has only 151 opcodes officially, since it is 8 bits. 155 options are actually “Illegal Opcodes” and they can also be used, but NES does not support them. Within the supported 151 opcodes, 56 different operations are included with different addressing modes (which we will cover more often in the future).

NES Instruction Set Table (masswerk.at Source and Detailed Information)

Bus, Mapper and Cartridge

The processor performs all its communication with the main system via a bridge we call Bus, all read and write requests sent by the processor to this structure are performed by the Bus and/or forwarded to the appropriate sections in the system.

One of the most important parts that the bus communicates with the CPU is the cartridge we mentioned before. Cartridge is the section that holds all game related graphics (CHR ROM) and program information translated into machine code (PRG ROM). In short, the data we read from the game file is loaded into this component. However, this situation creates a problem in terms of the system; Since the program counter of the processor is 16 bits, the memory range that the processor can see is ²¹⁶ hence 64 KB, and only 32 KB of this 64 KB is reserved for the data in the Cartridge, but especially advanced games hold much more data than this number.

In order to solve this problem, chips called Mapper are placed in the Cartridge, which can interpret the data coming over the bus according to the status of the system and the Cartridge and send different data to the request coming to the same address at different times. The main problem here from the emulator’s point of view is that there are many different Mappers, almost every game and every Cartridge has its own Mapper. To solve this problem, we will use the most important OOP principles, inheritance and polymorphism.

Picture Processing Unit : 2C02

Contrary to what we normally expect from computers, the most powerful hardware inside the NES is hidden in the image processing unit, not the processor.

Being a unit ahead of its time, the 2C02 not only runs at 3 times faster clock speed than the processor (ie, the image processing unit performs 3 cycles while the processor performs 1 cycle) and often performs more than one complex operation per cycle.

The chip, which contains 8 different registers, actually controls different states in each bit of these 8 registers, so the registers of 2C02 are at bit level, at the same time, it directly pulls data from the processor memory at certain time intervals with DMA (Direct Memory Access) and interprets this data during the rendering process.

It can also initiate an interrupt to the processor with NMI (Non-Maskable Interrupt) if necessary at the end of each frame.

Due to its complex structure, we will touch on all the details about the image processing unit when we come to the relevant section.

NES 2C02 PPU Die Shot (visual6502.org)

Audio Processing Unit : 2A03

NES’s sound processing unit provides the output by combining the data from 5 separate channels in one channel, thanks to a Mixer. The Sound Processing Unit is actually a part of the processor and runs at the same clock speed as the processor, but in our emulator we will treat it as if it were a completely independent part.

The frequency of the sound waves produced by the sound processing unit is 44100Hz, so if we consider that there are 60 frames per second, it must produce 44100/60, that is, 735 samples in each frame.

Each of the 5 different channels inside the sound unit are:

  1. Pulse Square Wave Channel
  2. Pulse Square Wave Channel
  3. Triangle Wave Channel
  4. Noise Wave Channel
  5. Delta Modulation Channel

Structure Combining All Components: System

We almost need a software motherboard to connect all the components we have examined above, and for this we will connect all the parts together using the component (class) we call System or NES.

Flowchart showing the entire architecture of the emulator (NOTE: Although DMA is actually a PPU operation, here we make it easy for the System to manage the DMA)

Conclusion

Thus, with this article, we have mentioned both the detailed features of the NES and emulators in general to introduce our NES emulator. You may have had a lot of questions and/or question marks after this article, but we will clarify all the parts with the following articles.

Thank you for reading and accompanying,

Ozan Armağan

--

--