Next (Assembly Language) ⭆ |
Building an emulator means building software simulations of they key features of the system. Before we get started, lets take a look at the hardware present in the NES:
All of these are critical to the function of the system. Fortunately, we can build one piece at a time, building up the complete function of our emulation. We’ll start with the CPU. It is the “brain” of the system, and without a working CPU it is hard to see that the other components are working.
Note: Since this is the first system we’re covering, we will also provide a fair bit of background for readers less familiar with computer architecture. The goal is to provide enough background to understand how the system works.
Sometimes called the brain of the computer, a CPU or central processing unit is the main component responsible for performing calculations and running the developer’s program. The NES uses a chip developed by Ricoh, the 2A03. It looks like this :
Image By BABAX - CC BY-SA 3.0, https://commons.wikimedia.org/w/index.php?curid=1888325
A CPU can be thought of as a programmable calculator. And in fact, that is what motivated the development of the first one. A CPU has can keep track of several values, just as a calculator stores a value that is displayed. It also has a series of operations that can be applied to this value. The major advantage of a CPU that it can read and execute a program, which essentially tells it which operations to perform and with which values as inputs. We’ll see this in more detail shortly.
The NES CPU, developed by Ricoh, is very nearly compatible with the popular MOS 6502 chip. That CPU was used in several famous early computers, including the Apple® ][ and the Commodore® PET. It also made its way into several popular electronic toys including the Furby and the Tomagotchi. The main differences between the Ricoh chip and the original MOS chip are that removal of a few patented features, and the addition of sound functionality (APU) on the same chip.
For the rest of the series, I’ll use “6502” to talk strictly about the computing functionality within the Ricoh 2A03 chip.
The 6502 is an 8 bit processor, with a 16 bit address bus. But what does that mean?
Most human cultures represent numbers in base 10. The right most digit is worth 1, then each digit beyond that is worth 10 times the previous digit.
123 = 1*100 + 2*10 + 3*1
or visually:
1 2 3
100 10 1
This is almost certainly due to the fact that we have 10 fingers, and so base 10 was natural. Computers more easily represent two different possiblities, so use a base 2 numbering system. The right most digit is still worth 1, but the next is 2 then 4 then 8 and so forth.
123 (decimal to binary) :
0 1 1 1 1 0 1 1
128 64 32 16 8 4 2 1
= 1111011
Sometimes we write this with the prefix 0b to indicate that it is a binary number, ex: 0b1111011
These binary digits are also called bits. An 8 bit value can hold between 0 (0b0000000) and 255 (0b11111111).
While binary is natural for computers to represent, it takes a lot of space and is clunky for humans to work with. In practice, when talking about computer numbers, humans often use hexadecimal, which is base 16. The benefit of this is that each hex digit nicely aligns with 4 binary digits. So moving between binary and hex is fairly quick, and more dense than binary.
Since decimal only goes up to 9 in a single digit, we need more symbols to represent 10 through 15. Hexadecimal uses the latin alphabet, starting with A:
10 : A
11 : B
12 : C
13 : D
14 : E
15 : F
16 (wraps to next digit): 0x10
And notice the use of 0x to signify a hexadecimal number.
Representing value 123 now in hex:
123 (decimal) :
0x7 0xB
7 decimal 11 decimal
/-----------\ /-------\
0 1 1 1 1 0 1 1
128 64 32 16 8 4 2 1
aka 0x7b
Earlier I mentioned that the CPU has an 8 bit data bus, and a 16 bit address bus. This means that the CPU works on chunks of 8 bits at a time, so only naturally works with values between 0 and 255. 8 bits are a very common grouping so we call this a byte.
8 bits is plenty for lots of functionality. It proves to be limiting when using 8 bits for talking about memory or program locations. For this reason, the cpu has 16 bits to talk about addresses, which point to memory locations used for data or code. With each location holding an 8 bit value, this allows the CPU to talk about up to 2**16 = 65536 * 8 bits(aka bytes), or about 65 K bytes.
Whether the CPU is actually connected to this much memory is another matter, but at least it is possible for refer to it.
I mentioned memory in the previous section. But what is that? Memory is just intermediate storage for values. It is stored in an external chip. It can be thought of as a long strip of paper, with slots for many values.
When talking about locations along this strip, we refer to its position relative to the start. The first slot or address we call 0, followed by 1 and so forth.
In the NES case, each memory address holds an 8 bit value.
Memory is outside the CPU chip, and so it takes longer to read and write values there. We’ll see how the CPU works around this in the next post covering more 6502 CPU specifics.
Next (Assembly Language) ⭆ |