SkoolKit

Spectrum game disassembly toolkit

Macros v. Python

SkoolKit 8.5 has been released. To get a copy, please head over to the download page, the Python Package Index, the Ubuntu PPA, or the Fedora copr repo.

As if the #PLOT macro (new in 8.3) weren’t enough, this release introduces the second and third new image macros to the 8.x series: #COPY and #OVER. The first of these (#COPY) enables you to copy all or part of an existing frame into a new frame, and change the scale, mask type and cropping specification (if desired) in the process. The second (#OVER) enables you to superimpose one frame (let’s call it the foreground) over another (the background, if you will), using the foreground’s mask or some other custom scheme for combining the graphic bytes and attributes of each frame.

So what do #COPY and #OVER make possible that was either very difficult or impossible before? One example is composing complex gameplay images consisting of sprites drawn on a background without having to write a SkoolKit extension module first. (Not that I’d want to discourage anyone from writing Python, but I understand that it’s not everyone’s bag.) Construct one big frame of the entire gameplay background, and one frame for each sprite in the game. Then use #COPY to copy the desired portion of that background to a new frame, and #OVER to sprinkle sprites onto that new frame. Finally, use the good old #UDGARRAY* macro to create an image file from the result. Bingo, as the saying goes.

Now, while you’re doing that, you might consider using the new #DEF macro to define custom macros that will simplify some of the repeated #COPYing and #OVERing. Why the new #DEF instead of the old #DEFINE? Well, #DEF has a more natural syntax and can create macros with optional integer and string parameters. And you can name the parameters to boot. In short, #DEF is what #DEFINE should have been from the start. For example, whereas you might define a #MAX macro using #DEFINE like this:

#DEFINE2(MAX,#IF({0}>{1})({0},{1}))

the same can be accomplished using #DEF like this:

#DEF(#MAX(a,b) #IF($a>$b)($a,$b))

If you’re not sold on #DEF yet by this particular example, think about how you’d define a new macro that has 10 arguments instead of just two. Then perhaps you’ll find that keeping track of them all by name instead of their position in a list is quite a bit easier and makes the macro definition much more readable.

At this point you’re probably sick of hearing about macros, so let’s talk about sna2skool.py instead. This workhorse of the SkoolKit suite now has the ability to disassemble an instruction that crosses the 64K boundary (i.e. has one of its bytes at address 65535 and the next one at address 0). Just set the new Wrap configuration parameter to 1, and off you go. Should be a boon to those of you who particularly enjoy disassembling custom interrupt routines.

While all that is perhaps the most interesting new stuff in 8.5, it is by no means everything. For details on the rest, I recommend consulting the changelog. There you will find details on such things as how to change the default snapshot disassembly start address (traditionally 16384), and how to add to the list of instructions that SkoolKit regards as identifying entry points (traditionally just calls, jumps and RSTs). After that, grab a copy of 8.5 and see just how complex an image you can compose without resorting to Python.

Groups and loops

SkoolKit 8.4 has been released. To get a copy, please head over to the download page, the Python Package Index, the Ubuntu PPA, or the Fedora copr repo.

Perhaps the most noteworthy change in this release is that the image writer component is now pluggable. So, for example, if you’re sick of the PNG files that SkoolKit currently creates and would rather produce ASCII art instead, or embed base64-encoded image data in your HTML documents, or perhaps even do something as perverse as revive the ability to write GIF files, then you now have that option. Go for it.

In the ref file department, there’s a completely new section on the scene - in fact, the first new section to be introduced since 4.0: [EntryGroups]. Here you can define groups of entries, surprisingly enough. To what end? Well, once a group has been defined, the entries belonging to it can be given custom titles and page headers in the HTML output - such as ‘Sprite buffer’ or ‘Character variables’ - instead of the boring stock ones (‘Data’, ‘Routines’ etc.).

Over in the snapshot analysis arena, snapinfo.py has acquired the Peek and Word configuration parameters for controlling the format of each line of the output of the --peek and --word options. So, for example, if you wanted to produce a series of POKE commands for a range of addresses, you can now do something like this:

$ snapinfo.py -p 30000-30010 -I 'Peek=POKE {address},{value}' game.z80

Shifting to the control file domain, instruction comments are now repeated when they appear in a loop (as defined by the L control directive). Full disclosure: this is not actually a new feature, but a bug fix. Instruction comments were repeated in control file loops back when loops were introduced in SkoolKit 4.2, but that stopped happening in 7.2, and I didn’t notice until quite recently. Oops.

With that damning admission out of the way, I will now point you to the changelog for details of all the other new stuff that I haven’t mentioned here (such as the ability to spread @expand directive values over multiple lines, and the ability to initialise the system variables in a snapshot when using tap2sna.py). Once you’re done there, please do grab a copy of 8.4 and perhaps start thinking about what obscure image format you’d like to add support for.

Old skool, new bugs

Over the past few months I’ve been working not on SkoolKit, but on a brand new disassembly: Skool Daze! Not the Spectrum version of the game, of course (because there would be nothing new about that), but the Commodore 64 version of the game, which was released some time in 1985, after the original Spectrum version.

The main reasons for going through this exercise were twofold. First, I wanted to give sk6502 (the SkoolKit components for 6502 disassembly) a workout by reverse engineering a game from scratch, and see where improvements for supporting 6502-based machines could be made. Secondly, I was curious how well and how faithfully one of my favourite games of all time had been ported from my favourite 8-bit platform of all time to a platform I’d never used before.

On that second point, I can report that the investigation was rather interesting. For one thing, I had to read up on how sound and sprites work on the Commodore 64 in order to understand how the game uses them. (This explains why the annotations for the sound-producing and sprite-animating code in the game are somewhat dry, for which I apologise.) For another thing, in many instances there is a one-to-one relationship between routines and data blocks in the Commodore 64 version and corresponding routines and data blocks in the Spectrum version, which I have pointed out where I noticed them.

The Commodore 64 version also has its own unique bugs and trivia, some of which suggest that the port was made from an earlier cut of the game code than was used for the Spectrum version (because they could easily have been in the Spectrum version too, but apparently were fixed before release).

Anyway, do take a look and see for yourself, and if you spot any errors in the disassembly (or my very recently acquired and very incomplete understanding of the Commodore 64), please let me know. And with that, time to get working on some changes to sk6502 and SkoolKit that were inspired by this experiment.