Friday, September 20, 2013

Learning NES

This month's Mini-Ludum Dare has a theme of Low Level. The idea being that the game created should be created in a language like C so that the developer can learn something about how computers work. I figure the learning part is the key to this challenge so developing a game in C/C++ wouldn't really teach me anything. Then I thought about creating a game for a platform I haven't worked with before. This immediately got me thinking about the NES. I like 6502 assembly language so figured it would be a fun challenge.

The last few days I have spent my evenings researching the NES. There is a surprisingly large amount of info on it, most of it poor. I suppose this is not too big of a surprise considering that the big N didn't want anybody programming their platform without their blessing so most information was the result of  hobbyists digging into the system on their own and learning how it worked by disassembling existing games. There are some really good tutorials and tools available, but a lot of the stuff is old DOS tools. I ended up finding NESAsm for my 6502 assembler and YY-Chr for editing the 2-bit tile-based graphics.

I have put together a simple skeleton (a title-screen and gamepad controlled spite screen) that I will use as my starting code for this weekend. the link is http://blazinggames.com/gamejams/minild45/miniLD45.php and while it is far from the best assembly code I have written, it isn't too bad for first-project code.

The sad thing is that I was expecting it to be programmed more like the C64. With that you simply had a range of memory that the graphics unit used so simply wrote to that ram like it was regular memory. On the NES, the PPU's (Picture Processing Unit) memory is separate so you have a small number of addresses that you use to communicate with it. You set the address of PPU memory you want to write to by writing to a register with the hi then the lo (which is strange as the 6502 is lo-hi for addressing) then write or read from another register which increments the address that you are looking at.  The way colors are selected is also over-complicated. You have 4 palettes of 4 colors that are chosen from 64 colors. Sprites have another 4 sets of 4 palettes but each of the 64 sprites have their own choice of colors. For background tiles, 2x2 blocks share the same palette. This isn't overly convoluted, so to make things more confusing the attribute byte for selecting the palette is grouped in 2x2 blocks of the 2x2 tile blocks (which probably explains why mario seemed to be broken into 4x4 chunks of tiles).

The gamepads for me were the strangest thing. They have 8 buttons so you would assume you simply read a gamepad port and get back a byte with each bit being the state of a button. Nope. You first have to strobe an address to get the gamepad to start transmitting bits. You then have to read each of the 8 bits separately.

Even if I don't finish my game, I have certainly learned a lot from this challenge so consider it a success. If nothing else, it reminded me of how different similar-looking things can be.

1 comment:

puzzud said...

I've dabbled with programming most of the classic 6502 systems. They all have their own oddities, but you are right, the NES can seem overly complicated. The C64 has the smallest learning curve.

I ended up going hardcore and learning to code around the MMC5 memory mapper. For a couple different reasons, good documentation was hard to find on it--it can be hard to code around; it forces you to write to drawing queues. But, the big payoff is that your background graphics can be colored per 8x8 pixel character graphic, instead of per 4 8x8 characters... more so like a C64.

If you are interested, check out my Google project called puzl6502.