Recently I found a tad more time to work on my C64 game, Cab Hustle. There is also a new video on my YouTube channel showing some of the changes (you can watch it at the bottom of this post). Let’s take a look at where things stand and what is new since my last post about the game.

Map Changes

First of all, the map has been extended from 9 rooms (arranged in a 3×3 pattern) to 36 rooms (in a 6×6 pattern). With the map compression packing one room into around 300 bytes, there is space for plenty more, but with the latest addition of new rooms there is already lots to explore.

To bring a bit more variety into the game and to make the visuals more interesting, there are new areas in the new map. The original area from the last version with its stone cellar look is still part of the game, and the game still starts there. On top of that, there are now an industrial-looking area with steel beams, an area with grassy hills, and an area with scarce tunnels that are connecting places. All these graphics fit nicely into the 256 characters that the machine offers for tile-based graphics.

Another map-related change is the status display. Previously, there were two rectangles at the bottom left and right that showed information. They were strictly speaking part of the map, i.e. flying into them would destroy the player’s ship. Now, the last two rows of characters are reserved for the status display, outside of the map area. This approach has two advantages. First, it makes designing the map easier since those two fixed obstacles in each room are no longer a constraint. Second, now each room is 40×23 characters large (instead of the full screen, 40×25). That saves some additional bytes of memory per room.

To implement the status bar, I am setting a raster interrupt for the bottom of the screen. The idea is to switch off the player sprite in the interrupt handler once the room graphics have been drawn by the raster beam. See my post on raster bars for a discussion of some related techniques. Not only would it look wrong to have the player sprite overlap the status bar, but it would also trigger a hardware collision detection interrupt, which the game utilizes to determine if the player hit any obstacles.

My initial thought was to just turn off the sprite in the VIC-II’s “sprite enabled” register, $d015. That sounds simple enough: ask the VIC to trigger an interrupt at the last raster line used for the room, switch off the player sprite, done. However, that turns out to not work. The VIC chip will stubbornly continue to draw the sprite. My second thought was to move the sprite to a different position on the screen. That can be done, for example, using the register at d001, which controls the y-coordinate of Sprite 0. That also does not work: once the VIC started to draw the sprite, it will continue to do so.

After scouting through some forums I finally came across the solution: one needs to update the sprite pointer instead. The sprite pointer is used by the VIC to find the memory location of the pixel data for the sprite to be drawn. Interestingly, sprite pointers are not implemented as registers—they live in memory in the free space at the end of Screen RAM. Evidently there’s a memory access on each raster line that contains a sprite to fetch first a pointer to the pixel data and then the data pointed to. That was a surprise considering that the values of the aforementioned registers would have been available already as internal signals to the circuitry without having to fetch any additional data from memory, a slow operation. Christian Bauer has documented all the details of the inner workings of the VIC-II, including the precise cycles in each raster line when what memory access happens.

There are some other things I could do during the raster interrupt such as switching to a different character set (giving me 256 different tiles for the status bar than the ones for the rooms) or changing global colors (three of the four colors per tile are globally set). But for now I am keeping it simple and straightforward.

Title Screen

Initially, I planned to have a multicolor bitmap graphic for the title screen. There are some different trade-offs in this mode compared to multicolor character mode, which I discussed in my last post about the game. Instead, I ended up reusing tile graphics from the map to create the title screen (with some bespoke tiles for the “Cab Hustle” logo). That is not only a lot quicker and makes it easier to change text in the future, it also is already supported by the code that drives the game map. Plus, the title screen compresses down to just 260 bytes.

Music

In addition to nicer graphics, the title screen now also has music. I opted for a simple upbeat tune in C major to give the game a happy vibe, and the result sounds more agreeable than the noise I created for my Slither game.

I’ve started creating the song using DefleMask but ran into a number of problems integrating it. Since then, I switched to GoatTracker. GoatTracker has a significantly steeper learning curve with its minimalistic UI, but once you get a hang of it, it provides a lot more control. The exported SID files are small and use resources very sparingly. In addition, GoatTracker has a feature to also use its playroutine for sound effects. That sounds quite handy, but for now I am not making use of that feature.

GoatTracker
DefleMask


The State of Affairs

The game is close to being done, but there are a few rough edges left. First of all, it is not well-balanced. The time bonuses and score rewards for delivery of passengers need to be a set empirically and with more care.

Second, the title song sounds as intended on the newer 8580 SID chip. On the older 6581 SID, some instruments are muffled or drowned out. That’ll require some investigation—possibly some oscillator waveform combinations that work fine on the 8580 cause problems on the 6581.

Third, the game does not work on NTSC machines at all, it works only on PAL machines. The title music plays (at a higher speed as expected since the playroutine is now called 60 times per second instead of 50 times), but the “Press Fire” text no longer flashes, and pressing fire does not start the game. Since there is less time per frame (1/60th of a second rather than 1/50th), I may potentially run out of raster time (the flashing of the text isn’t implemented particularly efficiently). This, too, will require some investigation.

There are some other minor nuisances. Landing closely to a passenger can cause in rare cases the ship to “ride up” the passenger. That is caused by code that moves the ship out of platform tiles if there is a collision with a platform while landing.

And lastly, there is still the delay when switching between rooms that I mentioned in the last post. The small lag is due to room data being uncompressed and copied. It is especially noticeable when briefly thrusting while leaving the room. The thrusting sound stays on for a tad longer while data is moved and before the code can check again if the player is still pushing the joystick button.

And that’s where things are standing as of now. If you want to take a look yourself, below is the latest video about the game. Leave me a comment and let me know what you think.