Thinking with Banks
By now we are going to assume that you are familiar with concepts like tiles, palettes, and nametables as the basic concepts for working with NES spec artwork. Some of those concepts will be covered again in this document to give perspective on how graphics are loaded into memory when a game is being played. Once we move beyond those basic concepts, we need to start looking at how banks are stored, what things are being loaded into memory, and how much can be loaded in.
Understanding these concepts and how to use them effectively is crucial in designing some artwork for the NES that is not only great looking but able to harness the technical aspects of the console. A firm grasp on what banks are and how they are used is essential for taking a game the looks like it came out at the beginning of the NES life cycle and instead of making it look like one from the end of it. This post will also cover some techniques that can be used to make the game do different things depending on when certain scan lines are being rendered. This enables some really nice effects.
Basics of Pages and Banks
All Mega Cat NES titles are made using the MMC3 mapper. MMC3 is extremely versatile, has a lot of space for graphics and programming compared to other mappers, and has some nice features that allow artists to create pretty stunning images. There are two levels of graphics storage that I will be talking about: Pages and Banks.
Mega Cat titles are able to store 256k of graphics data on them. That ends up equating to 64 pages of graphics. Each page is made up of 256 8x8 tiles. At any given moment, the NES itself can store two pages of graphics in memory. One page is dedicated to sprite objects, and the other is dedicated to background graphics. The NES doesn’t have enough memory to be able to display more than that on a single screen. This is where banks come into play.
These are the pages that are loaded into memory during gameplay in Little Medusa. The sprite page is loaded on the left side, and the backgrounds are on the right.
MMC3 has two sets of banks that it will have loaded into memory. It has a set of four 1K banks and two 2K banks. We tend to use names “quarter banks” and “half banks” due to the amount of space that they take up on a page. Each set of banks can be assigned to either the sprite objects or backgrounds. An example would be a game that uses quarter banks for the sprites and half banks for the backgrounds. That would mean that the sprite object page would be split into four equal sections of 64 tiles, and the backgrounds would be split into two halves of 128 tiles.
In Little Medusa, half banks were chosen for the sprites due to there not being a large diversity of enemy types on screen at the same time.
Quarter banks were then used for the Background elements due to our need for a large number of global background elements such as the power-ups and puzzle elements.
The real strengths of storing graphics as swappable banks can be seen in how they are used. By having graphics stored in banks global elements like the player sprite only have to be stored in the ROM once, and the game can always call for the correct bank. However, the greatest advantage comes with bank swapping. By using bank swapping you can have a larger range of tiles that the game can load up on the fly.
In our example of a game with quarter banks for our sprite, the player character can take up a single bank. If we use bank swapping though, we can dedicate multiple banks to different player actions. When the player does a certain action in the game, the player character’s bank would then be swapped with the correct one while the animation plays, returning to its original state after the animation is complete. This can be done in order to have a larger range of animations for any sprite (just keep in mind that the entire bank is being swapped out, so if anything else on screen is sharing those graphics they will also have their tiles replaced by the ones from the new bank).
This is the standard bank for Little Medusa’s player character that is used while idling and moving.
This bank is loaded whenever the player fires their attack off. The Player Character’s eyes glow and their stance changes. In order to have the space for both states a new bank was created and is swapped to at the appropriate time.
Bank swapping is also used to animate backgrounds. If a background element is placed in the same location in multiple different banks, the banks can be quickly swapped in a cycle to make an animation. The best practice for doing this involves keeping all of your animated elements on the same bank together in order to save space. Using bank swapping to animate backgrounds can lead to some really impressive effects as well.
The out of bounds areas in Little Medusa are all animated. This effect was achieved by having their tiles (in this case the water) shared in different banks, and animations were made on each bank. Then the game would repeatedly swap through those banks to make it move.
Bank Swapping as a Raster Effect
The MMC3 mapper is capable of creating splits in the screen whenever a specified scan line is being rendered. In order to understand what I mean, think about how an old CRT television works. Those types of televisions would render an image as a series of horizontal lines called scan lines. It would start at the top of the screen and render one line at a time. The NES is capable of setting flags based off of which scan line is being rendered, and then use those flags to achieve different effects. The most commonly used case of this is having a stationary background based HUD on the screen. This concept can be used multiple times to achieve multi-layered scrolling effects by adjusting the scroll speed of the background at specified scan lines.
Another very useful application of this is the ability to swap a bank of background graphics when a specified scan line is loading. Common applications of this effect are seen in games with a lot of cutscenes and in-game HUDs. If a game has cut scenes with text in them, generally the backgrounds banks are swapped on the scanline after the images, and they are swapped with the banks the contain the game’s font. That way the scenes have access to a full page of graphics without having to share with the text. In games that use two-way scrolling, or have a hard limit of two screens in height in the case of four-way scrolling, this can be used to load the in-game hud separately from the rest of the backgrounds graphics allowing for more space for both.
In this scene, a screen split is made on the scan line where the text box starts. The graphics for the top part of the screen are loaded into memory first, and once the split is reached the game loads the text box and font on top of the already rendered image’s graphics eliminating the need for both to be stored on the same page.
Interesting uses for Bank Swapping and Scan-line rendering
Concepts like bank swapping and using scan line rendering to your advantage can lead to some impressive effects. Bank swapping with the background can be used to add an extra sense of depth to a scene, by creating the illusion of an extra parallax layer in a scene. This is achieved by creating a small tileable element to be used as the objects in the furthest background.
You should never really do anything bigger than 32px in height for this. For our example, let’s assume that it is 32px. That element would be copied in the same spot across 32 banks and shifted horizontally by a single pixel. By the time you get to the last bank, it will be one pixel away from looping back to its original position. That element can then be animated relative to how the screen is scrolling, making it look like it is on a different layer than other background elements. This can be done to cheat the fact that the NES only has a single background layer, and make it look like there are background elements that are in front of other ones.
Aside from doing splits for parallax scrolling and bank swapping, scan-line rendering can allow for some interesting effects as well. Seeing how scroll speeds and direction can be altered per scan-line, it can be used to make a smooth wavy motion on a background object to simulate being underwater, or flickering fire. This trick is pretty hard on the NES’ CPU though, so it is usually utilized during cutscenes or transitions.
Looking at Other Games
Being able to efficiently use banks is not an easy thing to figure out on your own. Being able to deconstruct your work into 8x8 tiles that can be stored in a useful way can be a big task without some good examples. Luckily the emulator FCEUX has a way for you to look at what graphics are being loaded into a game at any time.
Once you have loaded up the game you want to look at, click on Debug -> PPU Viewer. This will open up a window that will show you what graphics and palettes are loaded up in real-time. You can use this to see what banks are being loaded, and when bank switches occur.
It splits the pages up into sprites and background so that you can see exactly what is in memory pretty easily. If you are having a hard time figuring out what you are looking at, right-clicking on either side will allow you to cycle through the currently loaded palettes.
Another option for looking at how the graphics are stored in a ROM is to open it up in YY-CHR. While YY-CHR is limited in terms of image editing ability, it is extremely useful for opening up any ROM and looking at how the graphics are being stored inside of it.
Once you open a ROM in YY-CHR you are immediately taken to the first page of graphics data. There are some gibberish tiles before and after the graphics usually, but that is because it is opening the entire ROM including all the non-graphics related data. Generally, if you are wondering how someone made some kind of graphic fit into a game on the NES, looking at the ROM in here is a great way to get a quick peek.
Want more NES graphic techniques? Learn about sprite layering here!