Introduction
Famicom (Family Computer) is a Nintendo® Entertainment System. It was the world’s most widely used videogames console during the 1980s. From its initial release in 1983 until it was discontinued in 1995, the console brought gaming into more homes than ever before and paved the way for the videogame industry as it stands today.
For more information about the Nintendo® Entertainment System, please visit http://nesdev.parodius.com.
Emulation is the process of simulating hardware to enable the software developed for it to be used on an otherwise incompatible system.
My Nes is an emulator for this system. At this time, it covers the popular games and it closed to cover over than 1000 games.
My Nes is completely portable, which means that you can port it into another platform or system like Xbox. Although it uses windows codes in some places for drawing and rendering sound but not the main NES engine.
This article should cover what you need to understand this project, also My Nes can be found at http://sourceforge.net/projects/mynes/ for developing, downloading what's new ...
But before you start reading this article or looking at the code, I recommended that you get a good knowledge about the real NES hardware and the other stuff.
And sorry if I'll abasing you when I say that you should get a knowledge about the "byte" and how to get a "bit" from the "byte" and what is the "short" ......
Background
My Nes includes three projects:
- The launcher called "My NES", it just the main EXE for the program and it initialize the main window form.
- The Core which includes the Windows forms and the classes for its like settings. I decided to add the windows forms in this library so that it will be lonesome from the NES engine. When you want to port into another platform or system, you should take care of this first.
- The NES project: it's a DLL library includes the classes that work together to emulate the NES system. these classes are completely lonesome with windows (exapt drawing, input handling and sound rendering).
The purpos of My Nes project is to use the engine (3rd project) to emulate the NES.
How does My Nes engine emulate?
Central Processing Unit (CPU)
The NES uses the NMOS processor based on the 6502, the 2A03, The chip differed from a standard 6502 in that it had the ability to handle sound, but in this engine i made the sound work done at APU class.
However, like any system, CPU is the heart and it controls everything using the registers.
The 6502 has five 8-bit registers and one 16-bit register. In each system cycle, the cpu fetch the instruction from the memory to execute, and the execution decides what's gonna happen at the next cycle and what's every part of the system has to do.
So 6502 emulation done at CPU6502.cs class, just take a look :
public byte a_register;
public byte x_index_register;
public byte y_index_register;
public byte sp_register;
public ushort pc_register;
public byte carry_flag;
public byte zero_flag;
.......
public void RunProcessor()
{
previousPC = pc_register;
while (!_NesEmu.isQuitting)
{
currentOpcode = _NesEmu.ReadMemory8(pc_register); switch (currentOpcode) {
case (0x00): OpcodeBRK(); break;
case (0x01): OpcodeORA(); break;
case (0x05): OpcodeORA(); break;
........
}
if (tick_count >= _NesEmu.Ticks_Per_Scanline)
{
if (_NesEmu.myPPU.RenderNextScanline()) {
Push16(pc_register);
PushStatus();
pc_register = _NesEmu.ReadMemory16(0xFFFA);
}
tick_count = tick_count - _NesEmu.Ticks_Per_Scanline;
}
}
}
The Memory
All the memory is located at the NesEmulator.cs class, and the CPU access the memory using ReadMemory8, WriteMemory8 and ReadMemory16 methods.
Also NesEmulator.cs class handles everything about the ROM (cart memory) including the access of mappers. Mappers are the most important stuff in the memory, 'cause the access of the cart is depending on the mapper. In the real NES cart, the mapper comes inside of it. But the INES format does not has the ability to handle a mapper, so we have to write each mapper (256 one) inside the emulator.

"This figure taken from http://nesdev.parodius.com/NESDoc.pdf"
There's no buses in the emulator, you know, just the read and write methods.
Take a look at the mapper # 2 code:
internal class Mapper2 : IMapper {
Mappers Map; public Mapper2(Mappers Maps)
{ Map = Maps; }
public void Write(ushort address, byte data)
{
if ((address >= 0x8000) && (address <= 0xFFFF))
{
Map.Switch16kPrgRom(data * 4, 0); }
}
public void SetUpMapperDefaults()
{
Map.Switch16kPrgRom((Map.mapperCartridge.prg_rom_pages - 1) * 4, 1);
Map.Switch8kChrRom(0);
}
public void TickTimer() { }
}
Picture Processing Unit (PPU)
The NES has the 2C02 processor to serve as PPU. This processor handles the graphics and the CPU access the PPU via memory addresses 0x2000 to 0x4020 and this area of memory called I/O registers.
Also in My Nes engine, the PPU emulation done at class called PPU, and it render each scanline like the follow:
public bool RenderNextScanline()
{
int i;
if (currentScanline < 240)
{
if ((uint)nameTables[0x1f00] > 63)
{
for (i = 0; i < 256; i++)
{ offscreenBuffer[(currentScanline * 256) + i] = 0; sprite0Buffer[i] = 0; }
}
else
{
for (i = 0; i < 256; i++)
{ offscreenBuffer[(currentScanline * 256) + i] = (
short)Nes_Palette[(uint)nameTables[0x1f00]]; sprite0Buffer[i] = 0; } }
if (spritesVisible)
RenderSprites(0x20);
if (backgroundVisible)
RenderBackground();
if (spritesVisible)
RenderSprites(0);
if (!noBackgroundClipping)
{ for (i = 0; i < 8; i++)
offscreenBuffer[(currentScanline * 256) + i] = 0;
}
if (sprite0Hit == 0)
{ for (i = 0; i < 256; i++) { if (sprite0Buffer[i] > 4) sprite0Hit = 1; } }
if (backgroundVisible || spritesVisible)
myEngine.myMapper.TickTimer();
}
if (currentScanline == 240) { myVideo.CurrentDrawer.RenderFrame(offscreenBuffer); }
currentScanline++;
if (currentScanline == Scanlinesperframe)
{ if (myEngine.SoundEnabled) { myEngine.myAPU.Render(myEngine.my6502.total_cycles);..... }
if ((currentScanline == ScanlinesOfVBLANK) && (executeNMIonVBlank))
{ return true; }
else { return false; }
}
Audio Processing Unit (APU)
The APU.cs renders the sound of the NES, and I will not write any thing about the APU because I'm still confused about this part of the NES and I really include it in the engine hoping someone help me on it. However, take a look at the source.
Cool but, how does it work?
The RunProcessor() method at the CPU loops to execute, and as I say before, this execution may tells every part what to do. Also the I/O registers is the most important area in the memory, so when the CPU access this area (Read or Write), the other parts do their job depending on the values of the registers. For example, a write anto address 0x2000 will change the sprite size (8x8 or 8x16), background address .... in the PPU.
Stop that method "RunProcessor()" and the system will stop. Run it and the system will run -_-
How to use the engine?
The main window (in the Core) uses the engine like this :
NesEmulator _Nes;
Thread gameThread;
ThreadStart myThreadCreator;
public void OpenRom(string FileName)
{
CartHeaderReader rom = new CartHeaderReader(FileName); if (rom.validRom)
{
if (rom.SupportedMapper())
{
_Nes.QuitEngine();
_Nes = new NesEmulator(panel1, statusStrip1);
_Nes.InitializeEngine();
_Nes.LoadCart(rom.FilePath);
_Nes.CurrentSystem = MainCore.Settings.NesRegion;
......
myThreadCreator = new ThreadStart(_Nes.DoFrame);
gameThread = new Thread(myThreadCreator);
gameThread.Priority = ThreadPriority.Highest;
gameThread.Start();
}
}
}
I think that's easy :)
Rendering the Video
I written 2 GDI renderer class for video, and it directly renders the offscreenBuffer from the PPU.
I used to draw it into a Bitmap image first then draw it into a Control which will be the screen surface and that to make TakeScreenShot() done easily.
Graphics GR;Control _Surface;int Screen_X = 0;
int Screen_Y = 0;
int Screen_W = 0;int Screen_H = 0;Bitmap bmp = new Bitmap(256, 240);
public unsafe void RenderFrame(short[] ScreenBuffer)
{
if (Surface != null & !_IsRendering & _CanRender)
{
_IsRendering = true;
BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 256, _ScanLines),
ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb565);
short* numPtr = (short*)bmpData.Scan0; for (int i = _FirstLinesTCut; i < ScreenBuffer.Length - _FirstLinesTCut; i++)
{
numPtr[i - _FirstLinesTCut] = ScreenBuffer[i];
}
bmp.UnlockBits(bmpData);
GR.DrawImage(bmp, Screen_X, Screen_Y, Screen_W, Screen_H);
if (TextApperance > 0)
{
GR.DrawString(TextToRender, new System.Drawing.Font("Tohama", 16, FontStyle.Bold),
new SolidBrush(Color.White), new PointF(30, Surface.Height - 50));
TextApperance--;
}
_IsRendering = false;
}
}
That code taken from Vid_GDI_16Bit class and using it makes My Nes runs at 80 ~ 100 fps (after enabling the Speed Throttling).
Point Of Interest
Playing the NES is realy cool but emulating the NES in your hands, that's a different story !!
My Nes can be the start point of your emulator for the NES or any system , all have the same principles.
Also My Nes is closing to be a REAL emulator, it's cool to play using it since it covers the most nice NES games which can be playable perfectly.
Start programming at 2008, my first successful project was AHD Subtitles Maker "ahd-subtitles-maker.webnode.com".
I'm studying Physics in Hims university.
Programming is my favorite hobby that fill my empty times.