[IMPORTANT: This post contains spoilers about the NES game I made. If you have one of the copies of this game and don't want to be spoiled, I advise you to leave.]
So around the middle of December, the idea popped into my head to make an NES game from scratch as a Christmas present to the Tymkrs and to make a second copy as a gift for the annual White Elephant gift exchange event for the hackerspace the Tymkrs hosts, "The Rabbit Hole". As a celebration of that hackerspace, I decided to base this project on The Rabbit Hole name and logo.
[All versions of this project are individually numbered and the one shown in this blog post is my personal copy.]
This project was developed using 6502 Assembly and was my first experience using 6502 Assembly, so it was a fun learning experience. The 6502 microprocessor and variations of the 6502 were used in a lot of devices around the 70s, 80s, and even into the 90s, which included the NES, SNES, Commodore 64, Apple II, Atari 2600, and Tamagotchi, so I can use what I learned with this project to create things for other devices besides the NES.
The label on the front shows "🠅+Start", which if pressed at the starting screen, turns the color palette to a monochrome green to try and emulate the "P1" phosphor monitors from back in the day.
Without going too into detail about how graphics worked, I could have 2 tilesets loaded at once along with 4 color palettes with 4 colors each for each tileset. All color palettes have 3 uniquely set colors and a shared background color. Only one of these tilesets can be set for background tiles and the other would be set for sprite tiles. Tiles can be either 8x8 pixels or 8x16 pixels, but for simplicity's sake, I decided to stick with 8x8 pixels. I'm just going to completely skip over setting background tiles on the screen because rules involved for how background tiles are grouped together is complicated and warrants a separate blog post.
Notice how all of the tiles use at most 4 colors. That's because I can change the color palette of a tile to use in this project by specifying which palette I want. This makes color changing animations like for the "?" blocks in Super Mario Bros. easier to create and is the reason why stronger versions of enemies in The Legend of Zelda were just recolored sprites of other enemies.
Because I decided not to use any sprites at all, I only needed 1 of the tilesets, so I put a message in the other tileset, which you can see in the image above.
I cheated a bit with this by using 2 tools, the music making program FamiTracker and the NES audio engine Famitone. These tools allowed me to create sound effects and music that I could include into the assembly file of this project along with simple methods for controlling that audio from the assembly file. Below is the simple song I created in FamiTracker for the project.
NTSC is the video standard that was used for North America, PAL for Europe. There are a few differences between NTSC and PAL for the NES.
First of all, NTSC systems tend to cut off about the top and bottom 8 pixels, which means I could make this project hide an entire tile row of information on the top and bottom of the screen when played on an NTSC system, but have that information show when playing on a PAL system.
Another difference is that NTSC NES games are 60 frames per second while PAL NES games are 50 frames per second, so if a game that is meant for NTSC is played on a PAL NES, it will play at 5/6 the normal speed and PAL NES games playing on an NTSC NES will play at 6/5 the normal speed.
It is in fact possible for an NES game to figure out if it is being played on an NTSC or PAL NES by counting clock cycles, so I had this project figure that out so it can keep timing correct on both an NTSC and PAL NES automatically.
The result of playing this project on a PAL system is shown below.
Fun Fact: The frame rate difference of PAL and NTSC is the reason why Sonic The Hedgehog on the Sega Mega Drive for the PAL region sounded and played slow, because the game was built with NTSC in mind, so that game played at 5/6 speed.
A flaw of the NES Zapper has always been that it requires a CRT monitor for the light gun functionality to work. The trigger works as an input though, as the trigger has either been pulled or it has not been pulled, so I felt like there was no excuse not to include the NES Zapper as a user input for this project.
Fun Fact: The game "Wild Gunman" never actually checked to see if the zapper was pointed at the TV. It would only rely on whether the trigger was pulled or not.
On the normal official NES controller, the arrow pads are all one button that tilts like a seesaw, preventing the player from only pressing opposite directions together at the same time, like Left and Right. I was able to use this to get the player to take their controller apart to continue.
Turns out there is nothing stopping the developer of an NES game from not resetting the internal memory of the NES when the reset button is pressed. It is also possible to count how many times the player pressed the reset button since last powering the NES on and to figure out if a player pressed reset at a specific time. The reset button plays a part in this project because at one point, the game freezes and expects the player to press the reset button in order to continue.
While the project does count how many times the player presses the reset button, it didn't end up using that information for anything, so I'm hoping to explore the idea of using the reset button as an integral user input in the future.
I ended up getting the circuit board for this project from Second Dimension, who has been really awesome in making sure I had everything I needed on time. I also ended up using 2 EPROMs, one for the graphics and one for the programming logic, and a region free CIC chip which allows this game to be played on an NTSC or PAL system. The EPROMs have a little window to allow UV light to get in to delete the data off of the EPROMs, so I decided to put important information on some labels to cover those UV light windows.
Now for my favorite part of the project. As you can see with some of the previous pictures, there are 3 secret codes. These secret codes is used by a device called a Game Genie that actually lets you modify the data of up to 3 different memory locations for an NES game. With this ability in mind, I was able to make this project require a Game Genie and the 3 specific 8 letter long secret Game Genie codes in order to get to the ending.
A few more ideas that I either didn't implement or didn't end up having time to implement with hopefully go into future NES cartridge projects.
Use the Reset Button More
Like I mentioned earlier in the post, this project ended up counting how many times a user resets but doesn't actually use that information. Games are also able to figure out at what point in gameplay a user resets. The reset button and the power it allows the developer to have can be used for some interesting interaction akin to the style of "The Stanley Parable" and was the idea I had in my head when I started this project, although I quickly realized the scope would be a bit too ambitious for a project I wanted to finish programming in about 2 days.
NES Game That Is Also a ZIP Folder
It should theoretically be possible to inject a ZIP folder into an NES game so that it will be both an NES rom and a ZIP folder at the same time. This should also work even if the NES rom data is burned onto EPROMS and the rom is turned into an actual NES cartridge, so ripping data from the EPROMS and turning that data into an NES rom will maintain that ZIP folder data. I'll test that out soon and if it is successful, I'll try to submit it to PoC||GTFO.
Create Custom Cartridges
One of my favorite things about many of the older cartridge games was that as long as you were not breaking the rules of the system the cartridge was playing on, you could pretty much let the hardware on the cartridge do whatever you want it to do. This opens up a host of possibilities for gameplay and interactivity.
Exploit the Top Loader NES 2 (Model NES-101)
The CIC chip on NES cartridges are used to communicate to a lockout chip in the NES. While the original NES design had that lockout chip, the Top Loader NES did not have that lockout chip. Because of this, on a Top Loader NES, if you pull a game out while the power is on and put in a new game and reset the system, the NES will retain the memory from the first game when the second game is restarted. This could easily be used in order to require 2 cartridges to beat a challenge. As far as I know, this "feature" isn't included in any of the popular NES emulators, so it could be used to get a player to play the game on actual hardware.
Get More Creative With the Game Genie
The Game Genie is limited to modifying the data of up to 3 locations in memory, but that is enough to open up a lot of strange development ideas. It is possible with only 3 game genie codes to tell the game to jump to a specific point in memory and start running that code. This means it's possible to develop a game that needs to be hacked in order to beat.