thomblog

Tom 'voxel' Purnell's notes

Deathloop 256 NES/Famicom STG shooter

Alakajam 20

This weekend was the 20th tri-annual 48 hour Alakajam gamejam. Participants suggest themes, the community takes a vote, and the theme most (dis)liked by all is revealed at the start of the 48 hours. Games are written from scratch and submitted before the time is up - developers working alone for the solo category or in arbitrary sized teams for the team category. My entry (which you can play here) is a NES game.

NES Famicom

Released in 1983 in Japan, and other countries soon after, Nintendo’s ‘Family Computer’ or ‘Entertainment System’ is a limited machine with 2KB of work RAM, 2KB of video RAM, 54 colours, and a 6502 family processor clocked at a stately 1.79MHz, probably about 1 thousandth the speed of the device you’re using to read this. It’s awesome. I have an ongoing game project for this console, with a plan to produce a small run of physical cartridges - which means I’ve deliberately targeting the minimum spec for a game cartridge to keep cost and difficulty of hardware development to a minimum. But commercial releases for the console were not always so constrained - it’s possible to add special chips that allow for extra memory, super graphics capabilities and much more - all within the game cartridge. So for this gamejam I decided to give myself the luxury of Nintendo’s top of the line mapper - the extra control chip on the cart - and use the ‘MMC5’. Most notably, this chip lets the cart exceed the normal 8KB of stored graphics by many, many times.

Vertical scrolling

The NES can scroll the screen in any direction - but that moves the entire screen as a single chunk, as shown here in another of my NES jam games, Windstorm Reef. My interest for this jam was creating a vertical parallax effect, scrolling the screen vertically, but at different speeds to give an illusion of depth. While it’s possible to dynamically change the vertical scroll of screen regions in realtime, it’s very difficult to do accurately, especially if you have gameplay happening simultaneously and using the CPU’s very limited time.

So instead of ‘actually’ scrolling the screen, I leveraged the MMC5’s ability to access large amounts of graphical memory and drew versions of the background in each state of being scrolled.

Tiles viewed in NEXXT graphics editor

Here are four ‘frames’ of the background, stored in a 4KB ‘page’ of CHR (CHaRacter) memory. Overall the vertical scrolling effect uses 64 frames, with each of the frames contains all of the graphics needed to make a frame of the background image when repeated:

A NES nametable using the background tiles

The NES ‘thinks’ that it’s drawing the same background every frame and has no concept that any ‘scrolling’ is happening. Instead, the MMC5 mapper chip is instructed to page a section of video memory. When the graphics ‘PPU’ processor is ready to draw the pixels for the background, it looks up the correct values to draw by first checking the ‘nametable’ to get a tile index, and then grabs the pixels for that tile from character ROM. This lookup happens via the MMC5, which I’ve programmed to ‘point’ to a different window of the background tile library each frame.

We can examine what the console ‘sees’ in video RAM in realtime using the Mesen emulator’s Tile Viewer debug tool:

By rapidly flicking through the different pages of character rom, the background tiles appear to animate. Putting it all together, the end result is pretty good:

I also tried to implement a small amount of horizontal perspective, but I’m unhappy with how it turned out. Not smooth enough and too subtle an effect. You can see this for yourself if you play the game and move left and right. This was a real time waster in the jam, I nudged the pixels by hand for 7 perspective angles, for a total of 448 frames. I didn’t expect it to take more than half an hour so didn’t really consider an automated solution. If I revisit this type of effect, scripting as much of the process as possible will be my first step.

Gameplay

A scrolling background does not a game make. The theme for the jam was ‘In a loop’, so my entry is a ‘shoot em up’ or ‘STG’ (ShooTing Game) where the play is stuck in a series of loops. Usually in STGs a viable strategy is to shoot a few enemies and dodge the rest. In this game, you must defeat every enemy that appears onscreen to progress. Missing one or more enemies causes the loop to repeat - and being destroyed by an enemy causes the player to ‘loop down’ to the previous loop. It’s a simple mechanic and works well enough, but in the current implementation severely lacks variety. There’s only a single enemy type and only eight different enemy attack patterns. In order to allow for a gradual increase in difficulty, the enemies do not even fire at the player until more than halfway through the game’s 8 loop waves. But once they do, the difficulty climbs quite rapidly.

Firin mah’ lazer

Firing the laser in Deathloop 256

I’m a big fan of ‘special attacks’ in this genre of games. Choosing when to use your special weapon can add a lot of tactical depth to what might otherwise be a very shallow game. Time limited, my special laser is very overpowered and suffers some bugs, but I’m happy with how it looks. Unfortunately, when the lazer stretches the full screen height, it consumes all of the limited number of sprites the console is able to draw to the screen, but when it works correctly, it looks cool!

Assembly

I wrote this game using only assembly, the lowest level human readable representation of machine code. I really enjoy working at the bare metal level and giving the machine direct instructions, rather than writing in a higher level language and hoping the compiler produces something close enough to what I want. It’s not the fastest way to develop a game, but I’ve done a few NES assembly jam entries now and am pretty happy with how much I’m able to achieve in a short timespan. I could have produced a more fully featured game using a high level language - but would it have run on a console from 1983?

Conclusion

You can play Deathloop-256 in your browser or download it for use in an emulator here. It’s simple but quick to try out, and I hope you at least enjoy the cool scrolling background - I do :D.