This is a creation in Article, where the information may have evolved or changed. This article by Bole Online-jackalhu translation, Toolate School Draft. without permission, no reprint!
English Source: Fogleman. Welcome to join the translation team.
Family computer (FC) is a home game console issued by Nintendo (Nintendo). The Japanese version of the FC fuselage with red and white mainly, so in the Chinese circle there are "red and white Machine" commonly known, Europe and the United States version of FC in Europe and the United States is called Nintendo Entertainment System (NES).
Recently I have written an FC emulator. Making such a simulator is primarily out of interest and in order to learn how FC works. In this process I learned a lot of interesting knowledge, so I wrote this article to share with you what I have learned. Since there are a lot of related documents, I'm just going to tell you some interesting features here. Please note that the next step will be some technical content.
Figure 1 My simulator can record the screen as a GIF. This is the picture of "King Kong" (Donkey Kong) I am playing.
Cpu
FC uses MOS 6502 (clocked at 1.79MHz) as its CPU. 6502 is a 8-bit microprocessor that was born in 1975 (40 years ago). At that time the chip was very popular, not only for FC, but also widely used in Atari 2600 & 800, Apple I & II, Commodore 64, VIC-20, BBC micro and other machines. In fact, until today the 6502 revision (65C02) is still in production.
6502 registers are relatively small, only registers A, X, and Y, and they are private registers. However, its instructions have multiple addressing modes. This includes an addressing pattern called a "0 page" (Zero page) that gives developers access to the first 256 words in memory ($0000~ $00ff). The 6502 opcode consumes less program memory and takes a shorter CPU cycle time to execute. In this sense, developers can think of 256 storage units on page 0 as 256 registers.
There are no multiplication and division instructions in 6502, and of course there are no floating-point arithmetic instructions. Although there is a BCD code mode, but in the FC version of 6502, it may be due to the patent problem this mode is disabled.
binary-coded decimal, or BCD, mainland China called BCD code or two-decimal code, is a decimal number encoding form. Under this encoding, each decimal number is stored in a single string of binary bits. Usually 4 binary numbers represent 1 decimal digits.
6502 also has a piece of 256 bytes of stack space without overflow detection.
6502 has 151 instructions (theoretically 256 instructions). The remaining 105 are illegal or undocumented instructions, most of which cause the processor to crash. But some of them may happen to have some sort of effect, so most of these instructions will also have a name corresponding to their role.
6502 there is at least one known hardware flaw, such as a flaw in an indirect jump instruction that JMP
does not work when the operand of the instruction is an address of the form $xxFF. Because when 2 bytes of data are read from such an address, the instruction cannot add a low-byte FF plus 1 (FF-a 00) to a high byte. For example, when 2 bytes of data are read from $10FF, the data in the $10FF and $1000 is actually read, not the data in $10ff and $1100.
Memory mapping
6502 has a 16-bit address space and an addressable capacity of up to KB. But FC actually has only 2 KB of RAM (Internal RAM), and the corresponding address range is $0000~$0799. The remaining address space is used to access PPU, APU, game cards, and input devices.
6502 Some address bus pins are not routed, so a large chunk of memory space is actually mapped to the previous space. For example, $1000~$17ff in RAM is mapped to $0000~$07ff, which means writing data to $1000 is equivalent to writing data to $0000.
Figure 2 "IT S dangerous to GO alone! Take this. " (game dialogue in The Legend of Zelda)
PPU (graphics processing device)
PPU generates video output for FC. Unlike CPUs, the PPU chip is custom-made for FC and operates 3 times times more frequently than the CPU. The PPU outputs 1 pixels per cycle during rendering.
PPU can render the background layer in the game and up to 64 sprites (sprites). Sprites can consist of 8 x 8 or 8 x 16 pixels. In the background, you can scroll both horizontally (x-axis) and in Vertical (Y-axis) direction. And PPU also supports a scrolling mode called fine tuning (Fine), which scrolls only 1 pixels at a time. This scrolling mode was a great technology in that year.
The background and sprites are made up of 8 x 8 pixel graphic blocks (tiles), and the graphics block is defined in the pattern Table in the game card ROM. The graphics block in the pattern Table specifies only the last 2 bits of the color it uses, and the remaining 2 bits are from Attribute Table. Nametable Specifies the position of the drawing block on the background. In short, it all seemed more complex than today's standards, so I had to explain to the collaborators that "this is not a simple bitmap."
The resolution of the background is x 30 = 960 pixels and consists of 8 x 8 pixel graphics blocks. Background scrolling is achieved by rendering an additional 30-pixel background with an offset from each background. If you scroll the background along the X and Y axes at the same time, you can have up to 4 backgrounds visible. However, FC supports only 2 backgrounds, so different mirroring modes (mirroring mode) are often used in the game to achieve horizontal or vertical mirroring.
The PPU contains a 256-byte OAM (Object Attribute memory) for storing properties of all 64 sprites. Attributes include the X and Y coordinates of the sprite, the corresponding drawing block number, and a set of flag bits. In this set of flags, 2 bits are used to specify the color of the sprite, and whether the sprite is allowed to be displayed in front of the background layer or after, or not, to allow the flag to flip the sprite in both horizontal and/or vertical directions. FC supports DMA replication, which can be used to quickly populate 256 bytes from a CPU addressable memory (usually $0200–$02ff) to the entire OAM. Direct access like this is about 3 times times faster than a manual byte-by-bit copy.
Although the PPU supports 64 cartoon graphics, only 8 sprites can be displayed on a scan line. When there are too many sprites on a scan line, the PPU overflow (Overflow) flag bit will be set, and the program can handle it accordingly. This is why the sprite flashes when there are a lot of sprites in the screen. Additionally, because of a hardware flaw, the overflow flag bit may sometimes not work correctly.
Many games use a technique called mid-frame, so that PPU can do one thing on the screen and do another in the other part. This technique is often used for split-screen scrolling or to refresh the number of bars. This requires a precise time perfectly and a detailed understanding of the CPU cycles required for each instruction. Implementing a feature like this will make it more difficult to write a simulator.
PPU has a primitive form of collision detection mechanism. If the 1th (numbered 0) sprite intersects the background, a flag bit will be set to indicate that "Sprite 0 has collided." This collision occurs only once per frame.
FC has a built-in 54-color palette that the game can only use in this color. These colors are not RGB colors and basically only output specific chroma (Chroma) and luminance (luminance) signals to the TV.
Figure 3 FC Palette.
APU (Audio processor)
The APU supports 5 channels, including 2 square channels, 1 triangular channels, 1 noise channels and an incremental modulation channel (DMC).
The game program needs to write data to the specified registers (mapped to memory) to drive these channels to make sounds.
The square Wave channel supports control of frequency and value, as well as frequency sweep (Frequency Sweep) and volume envelope (Volume Envelope).
The noise channel can generate pseudo-random noise using the linear feedback shift (Linear Feedback shift) register.
The Delta Modulation channel (DMC) can play a sample of the sound in memory. For example, in Super Mario 3, the percussion sound of the metal drums and "Ninja Turtle 3" in the Voice of "Cowabunga" use DMC.
Figure 4 Playing balloon games
Memory Mapper
The address space reserved for the game card is limited, the program memory of the game card is limited to 8 KB, and the role memory (Character memories) is limited. To break through this limitation, a memory mapper (Mapper) has been invented.
The memory mapper is a hardware in the game card that has the ability to switch the storage space (Bank switching) to introduce new program or role memory into the addressable memory space. Programs can control the switch of the storage space by writing data to a specific address to the memory mapper.
Different game cards implement different storage space switching schemes, so there will be more than 10 different memory mappers. Now that the simulator is simulating FC hardware, it must be able to emulate the memory mapper of the game card. Nonetheless, 90% of FC games are actually used in one of the six most common memory mapper types.
Rom File
A ROM file with the. nes extension contains one or more program memory bank and role memory bank in the game card. In addition, a simple head is used to illustrate which Mapper and video mirroring modes are used in the game, and whether there is RAM with battery backup power.
End
Learning FC was very interesting, and people at that time were able to use such a limited amount of hardware to complete such a game console I left a deep impression. Next I want to start writing a 8-bit style game.
I wrote my simulator in Go language, processed the video with OpenGL and GLFW, and Portaudio processed the audio. The simulator code is on GitHub, and you're welcome to download: Https://github.com/fogleman/nes
Figure 5 My favorite: Super Mario 3
Learn More
- NES documentation (PDF)
- NES Reference Guide (Wiki)
- 6502 CPU Reference
About the Author: Jackalhu
Love programming, focus on design patterns, and strive to improve the quality of software development. Sina Weibo: @Jackal-hu