How to start developing games for NES?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

monobogdan
Posts: 24
Joined: Thu Mar 23, 2017 11:23 am

How to start developing games for NES?

Post by monobogdan »

Just read about NES architecture and it's... not unusually for me.
So, i want start developing games for NES, but don't know starting point.
I have C, C++ skills, have some experience in x86 asm.
So, from what i should start learning coding for NES?
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: How to start developing games for NES?

Post by DRW »

I myself started with the Nerdy Nights tutorial for general knowledge and low level stuff.
http://nintendoage.com/forum/messagevie ... eadid=7155

Be careful: Some information is wrong or poorly explained. You basically never get your program to work if you just follow the instructions. You also always have to download the source code file to notice that it contains a good bunch of stuff that wasn't explained in the actual tutorial at all.

When I was able to do that stuff, I switched to cc65 and converted my program to that assembler.
Then I programmed most of the game logic using C, only using Assembler for hardware-specific stuff, general purpose functions and time-critical things.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How to start developing games for NES?

Post by Pokun »

Nerdy Nights is where I started too. With all it's flaws, it's still the best NES development tutorial out there for beginners.
It should teach you everything you need to know to make your first NES program and some basics. Then you can learn the rest from this forum and the Nesdev wiki.

I prefer programming in assembly. I eventually switched assembler from NESASM to the more popular ASM6.
User avatar
tokumaru
Posts: 12427
Joined: Sat Feb 12, 2005 9:43 pm
Location: Rio de Janeiro - Brazil

Re: How to start developing games for NES?

Post by tokumaru »

I find it easier to code for the NES in assembly because you have full control of everything that goes on, while using C means relying on some hidden library code you won't understand unless you know assembly anyway, and you often have to tailor your C code in not necessarily intuitive ways in order to produce ASM code that's not slow or buggy, so you end up not only having to learn how ASM works, but you also have to study a whole lot about the C->ASM process and the pre-made libraries if you expect to make anything beyond trivial.

But I guess there are beginner guides for both C and ASM, so maybe you should try both out and see what works best for you.
Pokun wrote:I eventually switched assembler from NESASM to the more popular ASM6.
I don't think that ASM6 is more popular than NESASM... It certainly is less restrictive than NESASM, so it gets recommended a lot as an alternative when people run into the pitfalls of NESASM, since both are equally easy to use. There's one really important thing that ASM6 lacks though, which's the ability to get bank numbers from labels (NESASM does it with severe limitations, ca65 does it better). I guess it shouldn't be hard to add a "bank" directive that would cause labels to inherit whatever value was last set, and a function to read that value back, but I can't follow ASM6's source for shit.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: How to start developing games for NES?

Post by DRW »

tokumaru wrote:and you often have to tailor your C code in not necessarily intuitive ways in order to produce ASM code that's not slow or buggy, so you end up not only having to learn how ASM works, but you also have to study a whole lot about the C->ASM process and the pre-made libraries if you expect to make anything beyond trivial.
That's nonsense. Yes, there are a few things to keep in mind, like using global variables instead of locals or parameters or creating an array of a struct as a struct with arrays. But it's not like your C code would look totally outlandish in the end.
I programmed a whole jump'n'run and my code still looks pretty clean and C-like.

Writing C can still be a ton easier than writing Assembly directly.

If you can program Assembly well enough, that's of course always better.

But someone who can write fluently in C, but only very slowly in Assembly:
Don't tell those people that the adjustments that you have to make in the C code to make it efficient enough for NES programming are such a huge disadvantage and such a code uglyfier that they're better off writing Assembly directly. Because that's simply not true.
Don't tell people that they can only either program clean Assembly code or butt-ugly, unintuitive, unreadable C code that's so shitty and energy-taking that they have less trouble using Assembly right away. Because this is clearly nonsense.

For someone who is good in C, but slow in Assembly, C is still a huge help for NES programming. And no, not only for "Pong" or "Space Invaders". It has been proven several times that you can make a real game for the NES by using mostly C:
http://www.youtube.com/watch?v=Eee0yurkIW4

Even if you need to use Assembly for the really time-critical stuff or for understanding what's going on under the hood: There's still a difference whether you force yourself to write an UpdateSprite or ProcessNmi function in Assembly or if you have to code the whole game logic and simply eveything in Assembly.

In the following, I will present you my movement function for the most basic opponent of my game. Please tell me:
Is the function so ugly and un-C-like and tailored in unintuitive ways that you would usually never use in C, so that I would have been better off writing it in Assembly directly? Or is this pretty much regular C for the most part, so that somebody who knows C but can program in Assembly only very slowly really has an advantage in using C?

Let's see if my function will convince a C coder to switch to Assembly because he considers the code to be such an abomination that he sees no use in programming C on the NES and prefers to become a master in Assembly programming instead because he considers this the easier way.

Code: Select all

/* The most basic opponent who
   just walks left and right. */
void __fastcall__ MoveGoon(void)
{
	/* If the Goon is stunned, */
	if (Npcs.IsStunned[IndexChr])
	{
		/* we decrement the stunned counter.
		   The Goon cannot escape from the stun.
		   The counter is just there to make
		   the vibrating movement in "Level.c". */
		--Chrs.StunnedCounter[IndexChr];

		/* If he's stunned,
		   nothing else is done. */
		return;
	}

	/* Often used array variables are put
	   into temporary variables because
	   accessing them is smaller and faster. */
	MoveGoonX = Chrs.X[IndexChr];
	MoveGoonFramesForNextWalkingAnimation =
		Npcs.GoonFramesForNextWalkingAnimation[IndexChr];

	/* If it is declared that
	   the Goon leaves the screen,
	   then nothing can stop him. */
	if (Npcs.GoonMovesOutOfScreen[IndexChr])
		MoveGoonX -= GoonMovementPixelsLeft;
	/* Movement to the right and
	   to the left are done differently.
	   We first check for right. */
	else if (Chrs.Direction[IndexChr] == DirectionRight)
	{
		/* We calculate the new position
		   of the right border side.
		   We use CharacterFullBorderRight
		   because the Goon's drawn size is
		   bigger than his bounding boxes. */
		MoveGoonNewPositionRight =
			  MoveGoonX
			+ (CharacterFullBorderRight + GoonMovementPixelsRight);

		/* If the new position is outside the screen or over a gap, */
		if (MoveGoonNewPositionRight > 255
		 || GetOnScreenLevelDataValue(MoveGoonNewPositionRight) == 0)
		{
			/* then we change the direction. */
			Chrs.Direction[IndexChr] = DirectionLeft;

			/* We reset the frames for the next
			   walking animation since left and
			   right have different values. */
			MoveGoonFramesForNextWalkingAnimation =
				GoonFramesPerWalkingAnimationLeft;

			/* And we immediately let the Goon
			   walk the new distance. */
			MoveGoonX -= GoonMovementPixelsLeft;
		}
		/* If the Goon doesn't reach
		   a border, we just let him
		   continue walking. */
		else
			MoveGoonX += GoonMovementPixelsRight;
	}
	/* Movement to the left. */
	else
	{
		/* We check the new left border position. */
		MoveGoonNewPositionLeft =
			  MoveGoonX
			+ (CharacterFullBorderLeft - GoonMovementPixelsLeft);

		/* And we check for a position a bit
		   to the right of the Goon.
		   This way we check whether the room
		   where movement is possible for
		   him has become very small.
		   That room is exactly 2/3
		   of CharacterWidth. */
		MoveGoonNewPositionRight =
			  MoveGoonX
			+ (CharacterFullBorderLeft + 3 * CharacterWidth / 2);

		/* If that certain right position is not a gap
		   and the Goon's new left position would be
		   either outside the screen or be a gap, */
		if (GetOnScreenLevelDataValue(MoveGoonNewPositionRight) != 0
		 && (MoveGoonNewPositionLeft < 0
		  || GetOnScreenLevelDataValue(MoveGoonNewPositionLeft) == 0))
		{
			/* then we switch the Goon's direction. */
			Chrs.Direction[IndexChr] = DirectionRight;

			/* Just like in the code above,
			   the walking animation frames
			   are reset. */
			MoveGoonFramesForNextWalkingAnimation =
				GoonFramesPerWalkingAnimationRight;

			/* And the Goon is moved. */
			MoveGoonX += GoonMovementPixelsRight;
		}
		else
		{
			/* If the Goon's new left position
			   would be outside the screen
			   and that specific right position
			   is a gap, i.e. if the room
			   where the Goon can move
			   has become very small, */
			if (MoveGoonNewPositionLeft < 0
			 && GetOnScreenLevelDataValue(MoveGoonNewPositionRight) == 0)
			{
				/* then leaving the screen is a given. */
				Npcs.GoonMovesOutOfScreen[IndexChr] = true;
			}

			/* The movement is done. */
			MoveGoonX -= GoonMovementPixelsLeft;
		}
	}

	/* The movement animation is done.
	   If the frame counter is at zero, */
	if (--MoveGoonFramesForNextWalkingAnimation == 0)
	{
		/* we get the next animation
		   phase from the array
		   and apply it to the meta sprite. */
		Chrs.MetaSprite[IndexChr] =
			GoonWalkingMetaSprites
			[
				Npcs.GoonWalkingIndex[IndexChr] =
					(Npcs.GoonWalkingIndex[IndexChr] + 1) & BitMask(GoonWalkingMetaSprites)
			];

		/* And we reset the counter,
		   depending on the direction. */
		MoveGoonFramesForNextWalkingAnimation =
			Chrs.Direction[IndexChr] == DirectionRight
				? GoonFramesPerWalkingAnimationRight
				: GoonFramesPerWalkingAnimationLeft;
	}

	/* The temporary variables
	   are put back into their
	   original arrays. */
	Chrs.X[IndexChr] = MoveGoonX;
	Npcs.GoonFramesForNextWalkingAnimation[IndexChr] =
		MoveGoonFramesForNextWalkingAnimation;
}
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
dougeff
Posts: 3079
Joined: Fri May 08, 2015 7:17 pm

Re: How to start developing games for NES?

Post by dougeff »

I think first thing is to understand what a valid NES ROM looks like. Early games (super mario bros) look like this...

16 byte header (look up iNES)
32768 bytes of program code (0x8000)
8192 bytes of graphics (0x2000)

the program code will load into the CPU at address 0x8000 and run through 0xffff. The last 6 bytes are pointers to system interrupts, and RESET (the start of the program). (look up vectors)

the RAM runs from 0 to 0x7ff. 0x100 to 0x1ff is the hardware stack.

Use a tile editor program (like YY-CHR or Tile Editor Pro) to make the graphics.

Use an assembler (nesasm, asm6, or ca65) to assemble the ASM code and make a .nes file. You would write the code in something like notepad or notepad++.

The most basic lesson would be constructing a valid .nes file, where an emulator loads it correctly, and it actually runs code. Get an emulator with a good set of debugging tools. I use FCEUX (and apologize to all the people making new emulators). The important tools are a hex editor, where you can see all the RAM values...PPU viewer, where you can see the graphics...and debugger, where you can freeze the execution of the program and step through the code.

There are like 1000 tiny but important things you need to learn to get anything to work right...for example, you can't (shouldn't) transfer data to the PPU while rendering is on (register 0x2001, sprite enable (s), background enable (b)).

Then you can learn what the NMI interupt is, what the V-blank is, where the palette is, how to write to the screen, how to put sprites on the screen, how to set up a stable loop, how music works, etc.

You write to the screen (registers 0x2006 and 2007) by sending data to PPU addresses 0x2000 - 0x23ff (nametable #0).

You have to set the scroll (registers 0x2005) (and write to 0x2000, to make sure correct nametable is selected), after writing to 2006/2007. Then turn rendering on.

Good luck. Ask any questions here.

(edits made)
nesdoug.com -- blog/tutorial on programming for the NES
Sour
Posts: 891
Joined: Sun Feb 07, 2016 6:16 pm

Re: How to start developing games for NES?

Post by Sour »

dougeff wrote:I use FCEUX (and apologize to all the people making new emulators)
I am greatly offended by the fact you're using what you're familiar with!
Jokes aside, if there is any reason you prefer FCEUX as your debugger (other than it being what you're familiar with), I'm always looking for feedback :)
na_th_an
Posts: 558
Joined: Mon May 27, 2013 9:40 am

Re: How to start developing games for NES?

Post by na_th_an »

If you can code fluently in C, take that route first. Check neslib, it's user friendly and will help getting your first stuff going quickly. Then you can start getting more hardcore. You'll eventually end up learing assembly, modifying neslib or getting rid of it, and replacing portions in your game with assembly equivalents.

Anyway, my only suggestion is that you have fun.
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How to start developing games for NES?

Post by Pokun »

You use C only to improve development speed for the cost of performance, not because you don't want to bother learning assembly neither as a stepping stone to learning assembly. You need to learn assembly anyway, so I suggest starting with Nerdy Nights and learn the basics of assembly and the NES hardware. Then you can choose if you want to go the C route like DRW did, or the pure assembly route like I did.

tokumaru wrote: I don't think that ASM6 is more popular than NESASM... It certainly is less restrictive than NESASM, so it gets recommended a lot as an alternative when people run into the pitfalls of NESASM, since both are equally easy to use.
My impressions is that ASM6 and CA65 are the two most popular assemblers on this forum, but maybe that's only among the regulars.
User avatar
DRW
Posts: 2225
Joined: Sat Sep 07, 2013 2:59 pm

Re: How to start developing games for NES?

Post by DRW »

Pokun wrote:You use C only to improve development speed for the cost of performance, not because you don't want to bother learning assembly neither as a stepping stone to learning assembly. You need to learn assembly anyway, so I suggest starting with Nerdy Nights and learn the basics of assembly and the NES hardware.
That's right. You should always start with Assembly first, so that you know what the NES does. And so that you are capable of writing single Assembly functions here and there, even if the majority of your code is still in C.
Once you're able to render a background and move a sprite in Assembly, you can start adding C to your code.

C is merely a help to make it easier for you, not to avoid the low level stuff completely. But it's still a huge help because it frees you from the burden of having to painstakingly write every single function (like game physics etc.) in low level processor code.

For example in my case, I'm totally capable of reading and writing Assembly code.
My problem is just that it takes much, much longer for me to write a function in Assembly and I have to concentrate much more if I try to read such a function and play out in my head what it does.
So, my sprite rendering function (the function that puts the hardware sprites on screen) is still written in Assembly to make it as tight as possible. But a game-specific, character-specific movement function (how a character reacts when he moves agains a wall etc.), that's done in C.
My game "City Trouble":
Gameplay video: https://youtu.be/Eee0yurkIW4
Download (ROM, manual, artworks): http://www.denny-r-walter.de/city.html
User avatar
FrankenGraphics
Formerly WheelInventor
Posts: 2064
Joined: Thu Apr 14, 2016 2:55 am
Location: Gothenburg, Sweden
Contact:

Re: How to start developing games for NES?

Post by FrankenGraphics »

A perspective from someone who's never taken a single cs class: Assembly language in itself isn't hard to learn (besides a few 6502 specific quirks). The NES hardware - especially the PPU and the APU -, on the other hand, is. And one'd need to learn that part regardless of writing C or ASM.

One thing i do find difficult with assembly is reading code and immediately understanding what it does. A function in a higher language can often be self-explanatory because it does what it says in a few lines. Assembly language can take quite a bunch of lines to disclose what it really does besides pushing bits and nibbles and bytes here and there. This makes commenting even more important, imo.
hackfresh
Posts: 101
Joined: Sun May 03, 2015 8:19 pm

Re: How to start developing games for NES?

Post by hackfresh »

Macros, descriptive function names, and good comments make things insanely more readable


Image
na_th_an
Posts: 558
Joined: Mon May 27, 2013 9:40 am

Re: How to start developing games for NES?

Post by na_th_an »

Well, I cheated 'cause I'm a computer engineer and know how computers work and had to learn assembly for several architectures during my studies. That surely helps. Not 6502 (or Z80) though. Anyways, 6502 assembly is probably the most human friendly, human readable, and human writeable of them all (save for maybe 68K). I just think that starting by writing a game in assembly is too harsh for a newcomer, at least it was for me. I enjoy making games and getting results. If I had taken the hard path I wouldn't have finished any.

My first NES game was Sir Ababol. Learning the NES specifics was hard enough for me, so I didn't want to add more difficulty to the mix, that's why I chose to code it in C + neslib. The game was short, easy and inefficient, but at least I managed to finish it.

Now I've reached a point where I can read and write 6502 assembly. I can modify and expand the core library I still use (neslib) or rewrite parts of my games in assembly. In the meantime, I've produced a number of games which have kept me happy.

Besides, I *really* enjoy the act of trying and produce the most efficient C code, learning how to make the compiler behave, and stuff like that. I guess everybody's motivation is different :)
Pokun
Posts: 2681
Joined: Tue May 28, 2013 5:49 am
Location: Hokkaido, Japan

Re: How to start developing games for NES?

Post by Pokun »

Yeah programming the NES is harsh, you have to be prepared that there is a lot you need to learn. Both 6502 and the NES hardware (although there is no need to focus on the parts not currently needed). But he said he has experience in C/C++ and x86 assembly (which is more than I had when I started with NES), so I think he should be totally fine if he spends some time on it.

You don't have to make a game right away though. I played around a lot with the hardware making various more or less useless apps. But when making a game it isn't that different from doing it in for example C. The game programming logic is the same. Game programming was also something I had to learn though (and is still learning) as I had no experience with programming graphical games before I started with NES programming.
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: How to start developing games for NES?

Post by tepples »

Sour wrote:
dougeff wrote:I use FCEUX (and apologize to all the people making new emulators)
I am greatly offended by the fact you're using what you're familiar with!
Jokes aside, if there is any reason you prefer FCEUX as your debugger (other than it being what you're familiar with), I'm always looking for feedback :)
FCEUX is familiar.

When I started seriously[1] developing for NES in the fourth quarter of 2008, the big choices were FCEUX and Nintendulator. I had to pick, and Nintendulator had two drawbacks.

First, FCEUX came in two editions, both of which worked for me. The non-debugging was natively ported to GNU/Linux using SDL. And the debugging version worked in Wine, an environment for running Windows programs on x86 operating systems not made by Microsoft. Nintendulator at the time had serious problems with the input configuration dialog on non-Microsoft operating systems (allegedly fixed a year ago). In any case, FCEUX developers felt responsive to my reports of bugs that appear only in Wine, as opposed to developers of some other popular in the NES scene.[2] Often, it revealed reliance on undefined or unspecified behavior of a Win32 API call.

Second, FCEUX runs fine even on old or mobile-spec hardware. For seven and a half years, I used a Linux netbook as my primary PC for NESdev, and things like Nintendulator and bsnes-plus couldn't hold anywhere near 60 fps. I'm no longer using that laptop since its third rechargeable battery stopped holding a charge, and I don't want to try buying a fourth battery for an over seven-year-old PC.

I'll have to try Mesen sometime.


[1]I started back in the late 1990s, when NESticle, loopyNES, and NESten were hot $#!+. Only once I bought a PowerPak did I become truly serious about the NES.

[2] HertzDevil of 0CC-FamiTracker has passed the buck for Wine compatibility to the Wine developers, who have accepted the issue as Bug 40416. But Wine is distributed in a manner that it can take up to three years for improvements to trickle down to users.
Post Reply