Click here to Skip to main content
13,195,821 members (55,014 online)
Click here to Skip to main content
Add your own
alternative version


100 bookmarked
Posted 21 Jul 2009

My Nes - Nes Emulator

, 19 Dec 2009
Rate this:
Please Sign up or sign in to vote.
My Nes is a portable Open Source NES/FAMICOM emulator written in C#.



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

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 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" ......


My Nes includes three projects:

  1. The launcher called "My NES", it just the main EXE for the program and it initialize the main window form.
  2. 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.
  3. 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;
.......//methods for addrissing modes, opcodes ...
//the cycles are done here in the "while" loop
//don't forget that the Thread will handle it.
public void RunProcessor()
   previousPC = pc_register;
   while (!_NesEmu.isQuitting) 
    currentOpcode = _NesEmu.ReadMemory8(pc_register);//get the next opcode from the memory
    switch (currentOpcode) //do the opcode
     case (0x00): OpcodeBRK(); break; 
     case (0x01): OpcodeORA(); break; 
     case (0x05): OpcodeORA(); break;
    if (tick_count >= _NesEmu.Ticks_Per_Scanline) 
    //if the cpu done the required cycles for the scanline
    //and this depending on NTSC or PAL.
     if (_NesEmu.myPPU.RenderNextScanline()) //tell the picture unit to render the scanline
       //do the interrupt routine.
       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"

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 //IMapper is the interface !!
   Mappers Map;//Mappers is the general class for bank switching 
   //and the engine depends on Mappers class for accessing any mapper.
   //It includes a field called "CurrentMapper" and it will hold this 
   //mapper when the cart is mapper 2.
   public Mapper2(Mappers Maps) 
   { Map = Maps; } 
   //When the system ask to write into cart (and rom is read only you know)
   //it asks to tell the mapper something . 
   public void Write(ushort address, byte data) 
     if ((address >= 0x8000) && (address <= 0xFFFF)) 
      Map.Switch16kPrgRom(data * 4, 0); //this means :
      //attach the prg bank # (data * 4) in the cart into the
      //address 0x8000 in the main memory.
   //At the reset or start of the system, it calls this method
   //to setup the mapper.
   public void SetUpMapperDefaults() 
      //last prg rom into address 0xC000.
      Map.Switch16kPrgRom((Map.mapperCartridge.prg_rom_pages - 1) * 4, 1);
   //some mappers needs to tick in each scanline and the system calls this method
   //every scanline even that mapper (like this) doesn't have a ticker.
   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)
   //Clean up the line from before 
   //Remember everything done on the offscreenBuffer array which holds
   //the 256 * 240 pixels in 16-bit color format.
   if ((uint)nameTables[0x1f00] > 63) 
    for (i = 0; i < 256; i++) 
    { offscreenBuffer[(currentScanline * 256) + i] = 0; sprite0Buffer[i] = 0; } 
    for (i = 0; i < 256; i++) 
    { offscreenBuffer[(currentScanline * 256) + i] = (
        short)Nes_Palette[(uint)nameTables[0x1f00]]; sprite0Buffer[i] = 0; } }
  //We are in visible territory, so render to our offscreen buffer 
  if (spritesVisible) 
  if (backgroundVisible) 
  if (spritesVisible) 
  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; } }
  //The mapper timer !! 
  if (backgroundVisible || spritesVisible) 
  //The moment of truth, render the buffer into the screen !!
  if (currentScanline == 240) { myVideo.CurrentDrawer.RenderFrame(offscreenBuffer); }
  //Render the sound ...
  if (currentScanline == Scanlinesperframe) 
  { if (myEngine.SoundEnabled) { myEngine.myAPU.Render(myEngine.my6502.total_cycles);..... }
  //Are we about to NMI on vblank? 
  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);//used to check the validate of the rom
  if (rom.validRom)
   if (rom.SupportedMapper()) 
    _Nes = new NesEmulator(panel1, statusStrip1);
    _Nes.CurrentSystem = MainCore.Settings.NesRegion;
    //Launch ... 
    myThreadCreator = new ThreadStart(_Nes.DoFrame); 
    gameThread = new Thread(myThreadCreator); 
    gameThread.Priority = ThreadPriority.Highest; 

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;//The drawer
Control _Surface;//the drawing surface like "panel" control.
//These 4 values changed depending on NTSC, PAL and DrawSize.
int Screen_X = 0; 
int Screen_Y = 0; 
int Screen_W = 0;//width 
int Screen_H = 0;//height
Bitmap bmp = new Bitmap(256, 240);
public unsafe void RenderFrame(short[] ScreenBuffer) 
  if (Surface != null & !_IsRendering & _CanRender) 
   _IsRendering = true; 
   //Render the bitmap 
   BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, 256, _ScanLines),
       ImageLockMode.WriteOnly, PixelFormat.Format16bppRgb565); 
   short* numPtr = (short*)bmpData.Scan0;//using the pointer is the best way to make it fast. 
   for (int i = _FirstLinesTCut; i < ScreenBuffer.Length - _FirstLinesTCut; i++) 
     //ScreenBuffer is an array of 16-bit color format so we don't have to convert it
     //so that saves speed.
     numPtr[i - _FirstLinesTCut] = ScreenBuffer[i];
   //Draw it !! 
   GR.DrawImage(bmp, Screen_X, Screen_Y, Screen_W, Screen_H);
   //Draw the text if we have to 
   if (TextApperance > 0) 
   GR.DrawString(TextToRender, new System.Drawing.Font("Tohama", 16, FontStyle.Bold), 
   new SolidBrush(Color.White), new PointF(30, Surface.Height - 50)); 
   _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.


This article, along with any associated source code and files, is licensed under The GNU General Public License (GPLv3)


About the Author

Ala Hadid
Software Developer
Germany Germany
Programming and software development is my life Smile | :)

You may also be interested in...

Comments and Discussions

SuggestionVideo Tutorials Serie about NES emulation Pin
Luca D'Amico4-Nov-13 13:55
memberLuca D'Amico4-Nov-13 13:55 
Questionwelcome to: Pin
kuif8sa9s9-Aug-12 14:54
memberkuif8sa9s9-Aug-12 14:54 
GeneralMy vote of 5 Pin
Member 89327415-May-12 8:44
memberMember 89327415-May-12 8:44 
Generalممتاز يعطيك العافية Pin
Mazen el Senih14-Mar-12 9:08
memberMazen el Senih14-Mar-12 9:08 
GeneralRe: ممتاز يعطيك العافية Pin
Ala Hadid22-Mar-12 9:20
memberAla Hadid22-Mar-12 9:20 
QuestionMy NES doesn't work on any computer I own Pin
Mifdongs24-Nov-11 18:25
memberMifdongs24-Nov-11 18:25 
AnswerRe: My NES doesn't work on any computer I own Pin
Ala Hadid26-Nov-11 22:22
memberAla Hadid26-Nov-11 22:22 
AnswerRe: My NES doesn't work on any computer I own Pin
sgraves10-Jan-12 16:51
membersgraves10-Jan-12 16:51 
GeneralRe: My NES doesn't work on any computer I own Pin
Ala Hadid11-Jan-12 11:16
memberAla Hadid11-Jan-12 11:16 
NewsVersion 2.3 is out !! Pin
Ala Hadid29-Mar-11 11:49
memberAla Hadid29-Mar-11 11:49 
Generalاعجبني Pin
TheDevelopper12-Feb-11 23:28
memberTheDevelopper12-Feb-11 23:28 
GeneralRe: اعجبني Pin
Ala Hadid13-Feb-11 1:31
memberAla Hadid13-Feb-11 1:31 
NewsNew version Pin
Ala Hadid14-Jan-10 22:19
memberAla Hadid14-Jan-10 22:19 
GeneralNew ver released Pin
Ala Hadid7-Nov-09 23:09
memberAla Hadid7-Nov-09 23:09 
NewsVer released !! Pin
Ala Hadid30-Oct-09 0:41
memberAla Hadid30-Oct-09 0:41 
NewsNew Release Ver Pin
Ala Hadid17-Oct-09 14:12
memberAla Hadid17-Oct-09 14:12 
GeneralRe: New Release Ver Pin
maxim galayko29-Oct-09 8:23
membermaxim galayko29-Oct-09 8:23 
AnswerRe: New Release Ver Pin
Ala Hadid29-Oct-09 23:39
memberAla Hadid29-Oct-09 23:39 
GeneralRe: New Release Ver Pin
maxim galayko31-Oct-09 11:27
membermaxim galayko31-Oct-09 11:27 
AnswerRe: New Release Ver Pin
Ala Hadid5-Nov-09 6:17
memberAla Hadid5-Nov-09 6:17 
GeneralNDS Pin
Norm .net7-Oct-09 23:38
groupNorm .net7-Oct-09 23:38 
GeneralRe: NDS Pin
Ala Hadid8-Oct-09 4:25
memberAla Hadid8-Oct-09 4:25 
GeneralROMS Pin
GabPsy18-Aug-09 6:56
memberGabPsy18-Aug-09 6:56 
AnswerRe: ROMS [modified] Pin
Ala Hadid21-Aug-09 6:04
memberAla Hadid21-Aug-09 6:04 
GeneralRe: ROMS Pin
The_Mega_ZZTer7-Oct-09 16:09
memberThe_Mega_ZZTer7-Oct-09 16:09 
GeneralRe: ROMS [modified] Pin
Ala Hadid8-Oct-09 4:23
memberAla Hadid8-Oct-09 4:23 
QuestionHow about don't use 'unsafe' ? Pin
Member 8454483-Aug-09 2:28
memberMember 8454483-Aug-09 2:28 
AnswerRe: How about don't use 'unsafe' ? [modified] Pin
Ala Hadid3-Aug-09 22:58
memberAla Hadid3-Aug-09 22:58 
GeneralRe: How about don't use 'unsafe' ? Pin
Member 8454485-Aug-09 1:52
memberMember 8454485-Aug-09 1:52 
GeneralRe: How about don't use 'unsafe' ? Pin
Ala Hadid21-Aug-09 6:09
memberAla Hadid21-Aug-09 6:09 
GeneralExcelent Pin
Atanas Palavrov28-Jul-09 10:22
memberAtanas Palavrov28-Jul-09 10:22 
GeneralRe: Excelent Pin
Ala Hadid28-Jul-09 11:02
memberAla Hadid28-Jul-09 11:02 
QuestionGreat work. Pin
Aybe28-Jul-09 9:55
memberAybe28-Jul-09 9:55 
AnswerRe: Great work. Pin
Ala Hadid28-Jul-09 10:10
memberAla Hadid28-Jul-09 10:10 
GeneralRe: Great work. Pin
Aybe28-Jul-09 12:50
memberAybe28-Jul-09 12:50 
GeneralLooks Promising, But... Pin
Reelix27-Jul-09 20:17
memberReelix27-Jul-09 20:17 
GeneralRe: Looks Promising, But... Pin
Ala Hadid27-Jul-09 22:16
memberAla Hadid27-Jul-09 22:16 
GeneralRe: Looks Promising, But... Pin
Reelix28-Jul-09 0:35
memberReelix28-Jul-09 0:35 
AnswerRe: Looks Promising, But... Pin
Ala Hadid28-Jul-09 3:41
memberAla Hadid28-Jul-09 3:41 
GeneralRe: Looks Promising, But... Pin
Reelix28-Jul-09 3:44
memberReelix28-Jul-09 3:44 
GeneralRe: Looks Promising, But... Pin
Ala Hadid28-Jul-09 9:12
memberAla Hadid28-Jul-09 9:12 
GeneralRe: Looks Promising, But... Pin
The_Mega_ZZTer7-Oct-09 16:11
memberThe_Mega_ZZTer7-Oct-09 16:11 
GeneralWPF and Surface Pin
stumpyfr27-Jul-09 2:10
memberstumpyfr27-Jul-09 2:10 
GeneralRe: WPF and Surface Pin
Ala Hadid27-Jul-09 6:01
memberAla Hadid27-Jul-09 6:01 
GeneralRe: WPF and Surface Pin
The_Mega_ZZTer7-Oct-09 16:18
memberThe_Mega_ZZTer7-Oct-09 16:18 
AnswerRe: WPF and Surface Pin
Ala Hadid27-Jul-09 6:26
memberAla Hadid27-Jul-09 6:26 
GeneralRe: WPF and Surface Pin
stumpyfr27-Jul-09 12:29
memberstumpyfr27-Jul-09 12:29 
GeneralRe: WPF and Surface Pin
Ala Hadid27-Jul-09 22:21
memberAla Hadid27-Jul-09 22:21 
QuestionSo you're finished working on the project? Pin
x24325-Jul-09 19:47
memberx24325-Jul-09 19:47 
AnswerRe: So you're finished working on the project? Pin
Ala Hadid26-Jul-09 10:00
memberAla Hadid26-Jul-09 10:00 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.171019.1 | Last Updated 19 Dec 2009
Article Copyright 2009 by Ala Hadid
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid