Spooter
2018: An NESASM Experiment
Aug 08, 2018
Fresh out of the Nerdy Nights Pong tutorial, I had vowed never to write any assembly for the NES ever again.
As you can guess, that didn’t happen.
Background
While on vacation visiting my grandparents, I found out about a game jam called Floppy Jam. The gimmick of the jam was that all entries must theoretically fit on the 1.44MB alloted to a floppy disk, hence the name of the jam. Naturally, this meant that most orthodox game engines would not meet the cut as they create too much overhead.
This also meant that I was down to only a few options if I chose to participate:
- Finally learn OpenGL and pray that I can write something in C/C++
- Hack a thing together with various JS libraries and a canvas
- Go back to NESASM hell
I might also mention at this point that my grandparents have limited access to the Internet, and being on vacation, I wanted to see sights, not screens. So, with a few cached NESDev wiki pages and the 6502 instruction manual in hand, I jumped back into the fray of writing really bad assembly code.
Process
For the longest time, I had dreamed of making an even shittier version of Hong Kong 97, a bootleg SNES game starring Jackie Chan vs China. While this was the impetus for the project, Spooter very quickly morphed into a traditional space shooter.
Starting off, I copied the Pong basecode I had written following Nerdy Nights last year, leaving a lot of the hardware shenanigans intact while deleting just enough Pong functionality for the assembly to still compile and run. After fiddling a little bit more with the code, I managed to get a space ship sprite to load and went from there.
One of the greatest hurdles in designing Spooter was controlling groups of objects (lasers, aliens, explosions). Initially, I thought this could be done naively by hardcoding the functionality of every object individually. However, as I started adding functionality for the aliens, this readily became infeasable. As you might expect, since every alien needed to be checked against every laser, I would be re-writing upwards of 12 blocks of code. This kinda ticked me off. I had avoided anything too complicated before this, but now I braced myself for the inevitable and wrote what may be called in the most primitive sense, a “nested for-loop”. After somehow successfully doing that, I started to get into the groove of things and began navigating and building a jungle of jumps, loops, and register juggling, even working in a system of activating and deactivating groups of objects with a bitmask where the bits in a byte would dictate active members of a group (so a bitmask of 00001001 would mean that the 4th and 1st object were active).
By far, the largest time sink with NESASM was fixing bugs. Often this was a slip-up like forgetting to load newly-added sprites or writing to the wrong area of memory. Other times, bugs were a result of inexperience with writing for the system such as not knowing to turn off NMI before loading a new BG.
A few of these many endless gripes include:
- Labels that would occasionally get out of range. This was solved by hacking sections of code out and putting them into subroutines which worked somehow…
- More than enough bugs arose simply from bad math in hex and writing to the wrong addresses
- Nine-out-of-ten, a bug somehow got fixed by clearing/setting the carry bit
- For the longest time, I thought I was bit-shifting right when I was really going left
- The score is an 8-bit value and, as such, will overflow once the player gets a score of 256. This will remain a feature that I now dub, “Spaceship Reincarnation”
- The game over screen is made of BG tiles and flickers since the only working method I have of writing to the background is turning off NMI, writing to an address, and turning it back on…
Here is the finished game. The final product ended up being a relatively simple shoot ‘em up where enemy floppies would float down, get shot, and respawn ad infinitum.
After Thoughts
Several goals remain unaccomplished for this project.
For one, I had wanted to add music and sound-effects into the game but lack of experience with the APU and time made this a hard endeavor. Another early dream was also to parallel the boss of Hong Kong 97 with a large boss made of BG tiles. This was also not possible due to a lack of experience.
The box art was also drawn up in MSPaint in the literal hour immediately after the game’s completion and leaves much to be desired.
Here it is in all its glory.