Page 1 of 1

NES Game Programming Part 1 Introduction to writing NES games.

#1 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 781
  • View blog
  • Posts: 7,604
  • Joined: 05-May 05

Post icon  Posted 27 January 2010 - 10:52 PM

*
POPULAR

NES Game Programming Part 1
a series by WolfCoder (January 2010)

Welcome! I think it would be fun to write a series of tutorials on console game programming. No, not those old text games, I'm talking about home entertainment consoles such as the NES or GameBoy Advance. While this series will work with the classic Nintendo Entertainment System most of the time, I'll include some sections about the PC or other consoles. All you need to follow along is some basic knowledge of C, but you might have to get your hands a bit dirty with ASM on some platforms if you need even more performance. I'll organize the things I assume you know how to do beforehand so you can get yourself ready.

- Get yourself refreshed/learned in C. I suggest the K&R book which is practically the bible of C programmers.
- You just need notepad to edit program code, but you can open these files one-by-one in Microsoft Visual Studio to get the syntax highlighting and all. There's also the Programmer's Notepad which is neat when working with toolchains like we will use.
- We will be working with pictures. Nothing more than simple image preparation and pixel-art, so you don't need Adobe Photoshop. Try the GIMP or Paint.net out if you want a free option, but I strongly urge you to NOT use MS Paint.
- I might not even cover it, but a good way to play back tracked music files (like MIDI) is to convert it to an easy-to-read format like the Triton XM. MODPlug Tracker is a great program to convert from MIDI to XM or something else. MOD files are like a cross between a WAVE and MIDI. Anyway, don't worry about music too much as it's pretty complicated and I'm afraid it might overwhelm most of my readers.

Introduction to the NES

Posted Image
Classic

Do I really have to introduce you to the most revolutionary console ever made? It's one of the consoles that defined the way consoles should be made today. The cartridges were well made, the controllers could be swapped, there were simple hookups for video and power, the console itself was very sturdy, and it had an impressive set of hardware (for the 80s). There was also a gigantic library of NES games you could literally fill a library with! Don't believe me? Just watch this video. Say what you want about Nintendo now, but they really nailed the market with their wonderful gray box.

If you want to hear someone talk about the NES and the games, you should watch the Angry Video Game Nerd (who used to be just the Angry Nintendo Nerd). His videos make a wonderful companion to this series of tutorials as he does his angry comedy routine to explain everything wrong with NES games and what not to do when making a video game. However, I'm here to tell you about what is inside the NES.

The NES has a modified version of the 6502 CPU which was also inside the Commodore 64 and Atari (to name a few). It's clocked at ~1.78Mhz and, of course, is 8-bit. It also has this weird video card known as the PPU (Picture Processing Unit). The unit supports a background and 64 particle sprites (8x8 or 8x16 pixels), four background and four sprite palettes, a 64-color master NTSC palette, and... That's about it. The screen is 256 and 240 pixels big but the top and bottom is cut off a bit because the NTSC standard is smaller. As for the sound, you have two square waves, a triangle wave, a noise wave and some other primitive sound channels. Oh yeah, and you have two controller ports. I'm not going to get into all the exotic and Japanese hardware you'll find as we're going to make standard games.

The 6502

Posted Image
Something like this thing, right here

The 6502 is a primitive processor. I mean primitive! It doesn't do very much and you have to 'stitch' together several instructions to handle numbers bigger than 8 bits wide. It's a general rule of thumb to stick to addition, subtraction, logical operations, and bit shifts on 8 bit numbers wherever and whenever you can. The other features of the C programming language can really start to slow it down.

The Compiler

Posted Image
Pretty simple

Now, for the important part. The compiler we are going to work with is known as the CC65. It contains libraries to develop applications for many devices that implement the 6502 including the NES. You can download the latest version from here. You will also need the NES libraries which is in a different download from the compiler itself.

Now, let's set up our compiler environment. You should have these two files downloaded (if you are using Windows) and ready to extract:

Posted Image
Downloads folder

First, extract the compiler itself into a directory, and then the nes libraries into that same directory. It's very important to extract the compiler first and then the NES libraries last. You should get something like this:

Posted Image
Installed directory

Now go into the folder labeled "bin" and you will see this:

Posted Image

Make careful note of this current directory. We are going to make it so that the environment variables point to this directory. It really depends on your operating system, but the end result will allow us to type cl65 from the terminal from any current directory. In Vista, right click on computer, then advanced settings, click on the Advanced tab and click the Environment Variables. Modify the "Path" variable and add the path to these .exe files with a ; at the end. If you run cmd and type cc65 and it tells you there are no input files, you did this step correctly. If not, you should look up how to change Environment Variables for your version of Windows. If you want to use the not-so-clever-and-messy approach, just copy these into the system32 folder under C:\WINDOWS\. This option can be messy and dangerous though, I highly recommend the variable option.

Posted Image
What you should see in the console

The Libraries

Alright, I know this is annoying and it might take a little fiddling to get the compiler running from the command line, but bear with me. We will have our "Hello, world!" program up and running in no time~ OK, you will want to make some basic folder (I did C:\NES\) and copy the lib and the include folders there from the cc65 installation directory you made earlier. You'll have a folder that is like this:

Posted Image
Full view of my window

You can see the path I used. I suggest you use the same path because that is the path I will use when compiling all the programs found in this tutorial.

Programming

Whew... We're finally ready to write our "Hello, world!" test program, are you still with me? You sure? Alright, in that case, make a folder where you will put the program code in. There are many details with getting text displayed on the screen including the actual pictures of the font and everything, but thankfully every game made with cc65 has the Commodore 64 default graphics set in two banks of VROM so you can draw text right from the start. VROM is the part of the program that has some picture data in it. Write the following program and save it as a .c file in the folder you just made.

/*
	Hello, NES!
	writes "Hello, NES!" to the screen

	written by WolfCoder (2010)
*/

/* Includes */
#include <nes.h>

/* Writes the string to the screen */
/* Note how the NES hardware itself automatically moves the position we write to the screen */
void write_string(char *str)
{
	/* Position the cursor */
	/* We only need to do this once */
	/* This is actually 2 cells down since the first 8 pixels from the top of the screen is hidden */
	*((unsigned char*)0x2006) = 0x20;
	*((unsigned char*)0x2006) = 0x41;
	/* Write the string */
	while(*str)
	{
		/* Write a letter */
		/* The compiler put a set of graphics that match ASCII */
		*((unsigned char*)0x2007) = *str;
		/* Advance pointer that reads from the string */
		str++;
	}
}

/* Program entry */
int main()
{
	/* We have to wait for VBLANK or we can't even use the PPU */
	waitvblank(); /* This is found in nes.h */

	/* This is a really strange way to set colors, don't you think? */
	/* First, we need to set the background color */
	*((unsigned char*)0x2006) = 0x3F;
	*((unsigned char*)0x2006) = 0x00;
	*((unsigned char*)0x2007) = 1;
	/* Then, we need to set the text color */
	*((unsigned char*)0x2006) = 0x3F;
	*((unsigned char*)0x2006) = 0x03;
	*((unsigned char*)0x2007) = 0x30;

	/* We must write our message to the screen */
	write_string("Hello, NES!");

	/* Set the screen position */
	/* First value written sets the X offset and the second is the Y offset */
	*((unsigned char*)0x2005) = 0x00;
	*((unsigned char*)0x2005) = 0x00;

	/* Enable the screen */
	/* By default, the screen and sprites were off */
	*((unsigned char*)0x2001) = 8;

	/* Wait */
	/* The compiler seems to loop the main function over and over, so we need to hold it here */
	while(1);
	
	return 0;
}



Now in order to compile this, let's write a batch file. Batch files are ugly, but I don't have a red hat distro of Linux and I don't want to install some RPM installer on my Linux machine to install the Linux version of CC65... OK, OK, in any case, I assume you're at least familiar with windows. The batch file you need to write is really easy, actually. Take a look:

@echo off
cl65 -L C:\NES\lib -t nes -I C:\NES\include *.c -o hello.nes
pause



There you go. That's it. The other two lines are there just to make it clean and for the window to remain open in case of errors/warnings. Unlike countless tutorials I have seen, I will actually explain this entire command to you.

-L [path] : This loads the .lib library files from the directory given. This is where nes.lib is found and we copied them in an earlier step to C:\NES\lib.
-t nes : Now that we referenced those libraries, this command tells the compiler we are making a NES game. It links the nes.lib and does all the necessary things.
-I [path] : This adds a path to look for the .h we include. That include folder we copied earlier has the nes.h file with a whopping two functions! It's important to have a good "Wait for the VBlank" function, so there's no complaints here.
*.c : Easy, this means to compile every file ending in .c.
-o hello.nes : This is the name of the output file.

The above file ends with a .bat extension. These run like programs. Have it right next to your .c files and double click on it to do the magic. Nothing but the press any key prompt should show up if the compiler has no problems. Out comes the .nes file! Wasn't that easy? Well... Not always. If you are having problems with this, I strongly urge you to look up how Windows Batch files work. I mean it, nothing is worse than trying to make NES games when you're trying to wrestle with the file system on Windows.

Run Program

Alright, so go ahead and run the program you just wrote. Wait, you don't know how? Well, you can test play these programs with an emulator of course. FCEUX is the perfect emulator for the game developer. It has a disassembler, PPU viewer, Name Table viewer and other functions. Don't go asking me for ROMs now, we're here to make games, not play them. Although... I suggest you play some of your favorites on the NES. If you have the original hardware, nothing beats it. If it doesn't work, then go find the ROMs yourself. Don't worry, if you want to stay legal, just get images of games you physically own. The emulators themselves are legal, they were not written with knowledge that wasn't already available and do not contain any BIOS code or anything from an actual NES. The NES actually has a fun history with knockoffs and tricks 3rd parties did to make games for it, it's a good read on your own if you're interested in this stuff.

Right now, go ahead and open the .nes file and the following should happen:

Posted Image
Classic test program output

Interesting. I'm sure you have a half a dozen questions about the program as it looks really, really weird if you've never written a first-order program that runs straight on hardware.

The program is mostly spacing and comments to make it easier to see. Here's a step-by-step explanation of the hello world program up there:

First, you don't need command line arguments to a NES game, obviously. We just have a main function that returns an int and even that is a little excessive.

In order to get anything to happen, we must write values directly to the memory. You can see this by all the casting of numbers into pointers, and then using them. In a normal program on a PC, this usually causes tons of problems and makes your program crash due to memory protection and all that.

Before we mess with anything that has to do with the video, we must wait until the NES is in something called the VBlank period. This is when you can modify the PPU and update the picture to be drawn for the next frame. When you are done, you then process the logic for the next frame while the screen is being drawn by the hardware. You need to be very quick about setting the PPU before the VBlank ends and the system begins drawing things as it locks you out of the PPU.

The PPU has its own memory, so we first have to write two values to tell the NES where we want to write data, and then write the data. We write the blue color of the background to the first color, which makes blue the background color for everything. Then, we write white for the text color.

Next, there is a helper function to write the contents of ASCII strings to the screen. Thankfully, the default text font is aligned with ASCII in the video memory.

After we put the text on the screen, we have to position the screen so that the text is in the place we expect it to be.

Since we are done, we then turn on the image so that it will be drawn in the coming picture.

The program then gets stuck in the while loop and does nothing, otherwise the program would repeat itself over and over, messing things up.

Conclusion

There is much you still don't know about NES programming, and I will explain it in depth for every subject we cover. In the mean time, try looking up information about the 6502, the NES hardware specs, and any other information you could use and try things out. Also, focus on your favorite NES games and try to think of how they did things in the game. Pay close attention to things such as little 8x8 pixel tiles, the colors used, and how different games behave. We're going to have ourselves lots of homebrew fun later, so stay tuned~

Is This A Good Question/Topic? 8
  • +

Replies To: NES Game Programming Part 1

#2 born2c0de  Icon User is offline

  • printf("I'm a %XR",195936478);
  • member icon

Reputation: 180
  • View blog
  • Posts: 4,667
  • Joined: 26-November 04

Posted 31 January 2010 - 09:59 AM

Awesome! I'm looking forward to reading the next one.
Was This Post Helpful? 0
  • +
  • -

#3 ts230  Icon User is offline

  • D.I.C Head

Reputation: 11
  • View blog
  • Posts: 225
  • Joined: 11-July 09

Posted 31 January 2010 - 10:58 AM

What about all of us Mac users? I really want to do this...
Was This Post Helpful? 0
  • +
  • -

#4 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 781
  • View blog
  • Posts: 7,604
  • Joined: 05-May 05

Posted 31 January 2010 - 12:09 PM

You'll have to bug the CC65 author about that.
Was This Post Helpful? 0
  • +
  • -

#5 ts230  Icon User is offline

  • D.I.C Head

Reputation: 11
  • View blog
  • Posts: 225
  • Joined: 11-July 09

Posted 31 January 2010 - 12:15 PM

View PostWolfCoder, on 31 Jan, 2010 - 11:09 AM, said:

You'll have to bug the CC65 author about that.

OK.
Was This Post Helpful? 0
  • +
  • -

#6 Nykc  Icon User is offline

  • Gentleman of Leisure
  • member icon

Reputation: 725
  • View blog
  • Posts: 8,638
  • Joined: 14-September 07

Posted 31 January 2010 - 12:28 PM

Nice start. I think these tutorials might be the nudge I need in the right direction.
Was This Post Helpful? 0
  • +
  • -

#7 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 781
  • View blog
  • Posts: 7,604
  • Joined: 05-May 05

Posted 31 January 2010 - 01:14 PM

Don't worry, the GBA series I'm writing side-by-side has mac versions of devkitPro I think... Not sure.
Was This Post Helpful? 0
  • +
  • -

#8 neptunusmaris  Icon User is offline

  • New D.I.C Head

Reputation: -18
  • View blog
  • Posts: 42
  • Joined: 31-July 09

Posted 01 February 2010 - 02:04 PM

View PostWolfCoder, on 31 Jan, 2010 - 12:14 PM, said:

Don't worry, the GBA series I'm writing side-by-side has mac versions of devkitPro I think... Not sure.


What about Linux huh?
Was This Post Helpful? 0
  • +
  • -

#9 WolfCoder  Icon User is offline

  • Isn't a volcano just an angry hill?
  • member icon


Reputation: 781
  • View blog
  • Posts: 7,604
  • Joined: 05-May 05

Posted 01 February 2010 - 05:54 PM

Of course it has Linux. It's a modified version of GCC!
Was This Post Helpful? 0
  • +
  • -

#10 nathanpc  Icon User is offline

  • SCIENCE!
  • member icon

Reputation: 112
  • View blog
  • Posts: 1,171
  • Joined: 31-July 09

Posted 30 March 2010 - 07:09 PM

I'm a NES developer, but I develop using 6502 Assembly Language, that is alot more used and flexible than C(for this platform at least).

The best tutorial on the internet to learn is Nerdy Nights(from bunnyboy). ;)
Was This Post Helpful? 0
  • +
  • -

#11 he-Shiny  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 08-May 10

Posted 08 May 2010 - 12:49 PM

Thanks for this, I've been looking for some way to code NES or SNES games without resorting to straight up Assembly (since I seem to have horrible luck with my assembly coding). I'm looking forward to future tutorials on this.
Was This Post Helpful? 0
  • +
  • -

#12 Guest_matt*


Reputation:

Posted 15 May 2010 - 06:24 PM

Mac users, just install the port of cc65, works a treat :)

http://cc65.darwinports.com/
Was This Post Helpful? 1

#13 Guest_Voyager2*


Reputation:

Posted 30 July 2010 - 06:01 AM

I'm having a problem, i created a .c file(a renamed txt file) and pasted in your code(after deleting the line numbers) and compiled using the .bat file, it compiled fine and created a .o file!
So I renamed it .nes and loaded it into Nesten(my emulator) but it didn't even load...
Can someone pleas help with this?
Was This Post Helpful? 0

#14 Guest_Voyager2*


Reputation:

Posted 30 July 2010 - 06:11 AM

Recompiled and i got a .nes file that outputed "!"
I thing i'm doing it wrong...
Was This Post Helpful? 0

#15 vaidesjunior  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 1
  • Joined: 16-January 13

Posted 16 January 2013 - 05:19 AM

Hi! This is a very nice post, but where's the part II?
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1