Tech News
← Back to articles

C64: Putting Sprite Multiplexing to Work

read original related products more articles

Last week’s article summarized the sprite system on the Commodore 64. I’ve done this for quite a few other platforms at this point, and I’ve usually followed up with a short project that makes heavy use of sprites and often reuses them over the course of each frame. To date, this project has always been my “shooting gallery Rosetta Stone” project. However, for the C64, I have unfinished sprite-related business with an entirely different Rosetta Stone project:

When last I left the C64 Lights-Out project, I’d used a set of static sprites to add rivets and drop shadows to the game board. At the time, I left it at that and did not attempt to completely close the gap with the NES display. In particular, the buttons on the board are flat, and on the NES and PICO-8, they both had drop shadows of their own and animated being pressed when they were selected. We used all eight of the VIC-II chip’s sprites to produce the shadows we have above; we’d need 33 to do what we want properly.

As of last week, that isn’t going to stop us anymore. We need 33 sprites at once, and 33 sprites at once we shall have. Animating the button presses also will take us into slightly unknown territory, too; on the NES and PICO-8 the buttons were blank, but the buttons have labels here on the C64 and we will need to animate those too.

Designing Our New Display

Our previous display uses all 8 sprites to produce the rivets and shadows: one sprite for each corner, and then two expanded sprites each for the left and bottom sides. We now wish to add new sprites to represent drop shadows for each of the puzzle cells. Those cells are each squares 3 characters to a side (so, a 24×24 pixel region), but thanks to the bezels around each button, the shadow itself only needs to be 19 pixels tall. That fits neatly into our 24×21 sprite space.

With five cells per row, we’ll need to dedicate five sprites to the cells’ drop shadows. We will reuse those cells in each subsequent row, and if a shadow needs to go missing (because the corresponding button is depressed), we will simply disable that sprite on that row via the $D015 register. Two sprites will suffice for the corner sprites; the top corners may be similarly re-used for the bottom ones. That leaves one sprite spare, and it seems like it would be most conveniently used for the rest of the left-side shadow.

That leaves the bottom shadow. For that, we’ll need to re-use two of the sprites we’d previously been using for cell shadows. This will impose the tightest timing requirements upon us of anything in the design. Because we are altering the sprite graphics, the magnification, and the X coordinate, we cannot reconfigure the sprite registers until after we have finished rendering the last cell, and we’ll only have a few scanlines of space to do that work. As we’ll see once we get into the nuts and bolts, we’ll normally have dozens.

With sprite usage sorted out, we may now move on to defining the new graphics. We have two new graphical elements to define: the cells’ drop shadows (which fit in one sprite pattern) and alternate graphics for a puzzle cell when it’s being pushed down (which consumes 8 ideally consecutive character codes).

We have plenty of memory for both of these, but we do hit another inconvenience when we define the new characters; we’re using the Extended Color Mode for both the game board and the status window, and we cannot get 8 characters together for our new button graphic without overwriting some of the punctuation that we need in the status line. That’s not really a problem for us, though, because we can just turn off Extended Color Mode for the status line and get 256 characters back. In fact, as long as we’re doing that, we really might as well just switch back to the system font and get mixed-case text while we’re at it:

Going back to the system font like this also makes our final graphics challenge trivial. The character set that we are using for the game board only uses letters as part of the labels, and it uses each letter at most once. We may animate the letters during the button press simply by redefining the character in place.

... continue reading