Spectrum Pac-Man

I think I’ve got Pac-Man back out of my system for now, with the new(ish) Spectrum port and updated SAM version.

The Spectrum version turned out to be much bigger than expected, in terms of both conversion effort and community reception. I’d only planned to do a quick conversion of the graphics to monochrome, and spend an evening or two rewriting the graphics routines for the display change. It did start that way, but snowballed from there.

The early work was done using pyz80+SimCoupe, with a mode 1 screen matching what the Spectrum would use. Once I got the basic tile drawing working (still only to 8-pixel boundaries), I switched to Pasmo+Fuse to check the AY sound mapping, and ensure the rest of the game was running correctly. I kept a video of this first playable version, which still lacked sprites.

The tile support includes the flashing power pills, which the arcade version animates by changing the cell attribute colour. The SAM version flashes a spare palette entry, used only for the power pill graphics. Unfortunately, the Spectrum couldn’t use attribute blocks without affecting the sprites passing over them, so the only option was to flash the display data directly.

Adding the sprites was more trouble than expected due to lack of free memory. The SAM version has 102 sprites, but at least 24 of the coloured ghost sprites weren’t needed, since they all looked the same in the Spectrum version. The remaining 78 sprites still required a whopping 21K to be stored fully pre-shifted. On top of that the 256 background tiles in 4 possible shift positions required an additional 10K. Ouch.

To save space I halved the resolution of the frequency-to-AY sound look-up table, and stored only the even sprite shift positions; the odd positions could be made up from those at draw time. Even that extra drawing work was too much at times, causing dropped frames if too many sprites were at odd positions, as they often were in one of the main vertical tunnels.

I really needed the full set of pre-shifted graphics, so I looked for savings in the graphics themselves. The tile set included a number of gaps, which could be filled by relocating other tiles. As with the sprites, the duplicate coloured ghosts (used for the attract screen) could also be removed. The fruit tiles weren’t needed either, since I used the sprite versions to simplify drawing of the relocated fruit to the right of the maze. On the sprites side, I eliminated duplicate segments from the large Pac-Man character, as used for the first intermission sequence. The savings worked, with a little space to spare.

Having all the ghosts look the same was a problem, as each has its own behaviour, and telling them apart is an important part of gameplay. I considered having a symbol stamped on each, but felt that would spoil the appearance. I chose to single out just the red ghost (the most dangerous) with a small mouth, so you could tell him apart from the others. It might even make it look a bit more menacing too!

At that point it was good enough for the first release. I got plenty of feedback and feature requests, one of which was colour support. However, the maze isn’t aligned to Spectrum attribute blocks, as that would require extensive changes to the graphics tile set and/or the ROM (thanks to Andrew Owen for looking into this). I still thought it was worth trying colour, if only to prove how bad it would look. Except it didn’t.

Colour support was added to the sprite save/restore/draw code, with a look-up table mapping sprite number to a single Spectrum attribute value. As a bonus, the lives and fruit indicators to the side of the maze were also in colour, as they were drawn using the sprite code. Unfortunately, the extra work to add colour pushed us back into the danger zone, causing frames to be dropped in some cases (mostly when the fruit sprite was visible). I released a video showing colour support in action, but took care to mask the speed problem by my choice of route through the maze. The video was a hit, so I needed to fix the running speed, fast!

The biggest time saving was a relatively simple one; rather than save and restore the previous attribute blocks for each sprite, I just needed to paint the old location with the current screen attribute. This, combined with other tweaks to the save/restore code was enough, and the colour version was ready for all. At this point it was still an assemble-time option to pick between mono and colour, but the next release added run-time switching, using a sprinkling of self-modifying code.

More recently, some of the Spectrum enhancements have found their way back to the SAM version, just in time for its 8th anniversary update. The save/restore/draw/clip code is more efficient, reducing the risk of frame overrun in later levels when the game speeds up. Adding the ROMs to the disk image is much easier, and the game startup is faster due to skipped memory check. It also adds joystick support, and our old favourite the Q/A/O/P key mappings.

Barring bugs, I’ll probably not return to this project for a while. That might even give time to look into the feasibility of Mr. Do!