SkoolKit

Spectrum game disassembly toolkit

Keeping it SMPL

#FOR1,100($n,I will not...)

SkoolKit 5.1 has been released. Even though it goes without saying, I will say that copies of 5.1 are available from the download page (as usual), the Python Package Index (as usual), and the Ubuntu PPA (as usual).

Before we embark on a tour of the new features in this release, allow me to divulge a small piece of previously unrevealed history. Back in January 2012 - between 2.4 and 2.4.1 in SkoolKit time, if that’s how you prefer to measure dates - I added an item to my SkoolKit TODO list about making it possible to define a new skool macro in terms of existing skool macros without writing any Python code. At the time, it was just an idea that I hadn’t really fleshed out. And it stayed that way until fairly recently - between 5.0 and 5.1 in SkoolKit time, as it happens - when I finally decided on a scheme that would bring the idea to fruition.

Enter 5.1 with the @replace directive, the ability to evaluate arithmetic expressions in macro parameters, and seven new skool macros: #(), #EVAL, #FOR, #FOREACH, #IF, #MAP and #PEEK. Together they constitute the Skool Macro Programming Language - SMPL (pronounced ‘simple’, I’ve just decided) for short. With them you can effectively define new macros that are shorthand for complex forms or combinations of the classic skool macros, or that fill in gaps in their capabilities.

For example, let’s look at the good old #UDG macro. It’s fine as far as it goes, but one thing it has lacked all these years is the ability to specify an address from which to collect the desired attribute byte; instead we’ve had to hard code the attribute value into the #UDG macro’s parameter string. Now, though, with the advent of the #PEEK macro, that has changed. Suppose the game we’re disassembling arranges tiles in groups of nine bytes: the attribute byte first, followed by the eight graphic bytes. Then we could create an image of the tile at 30000 like this:

#UDG(30001,#PEEK30000)

Which is nice, but perhaps not a great improvement over hard coding the attribute value. Now suppose that we want to create images of the tiles at 30009, 30018 and so on:

#UDG(30001,#PEEK30000)
#UDG(30010,#PEEK30009)
#UDG(30019,#PEEK30018)
...

This is getting tiresome. However, the nascent SMPL programmer within you should be noticing a pattern to these macros; they are all of the form:

#UDG(addr+1,#PEEKaddr)

where addr is the address of the tile’s attribute byte. Having identified the pattern, we can now embody it in a @replace directive, which replaces one regular expression with another:

@replace=/#udg\i/#UDG(\1+1,#PEEK\1)

With this directive in place, we can now create images of the tiles with the appropriate attribute values thus:

#udg30000
#udg30009
#udg30018
...

Which, I hope you will agree, is actually starting to look somewhat handy. But still, typing out all these #udg macros is a pain when there are 20 of them (say). So let’s use a #FOR loop instead to cut down on the typing:

#FOR30000,30171,9||n|#UDG(n+1,#PEEKn)||

If you’re still not convinced of the merits of SMPL, try this control file snippet on a snapshot of Hungry Horace:

@ 28663 replace=/#maze\i/#UDGARRAY#(32#FOR(\1,\1+767)||n|;#tile||)
@ 28663 replace=/#tile/(31735+8*#PEEKn),#MAP(#PEEKn)(61,2:60,3:56)
b 28663 Maze layouts
N 28663 #maze28663(maze2)
N 29431 #maze29431(maze1)
N 30199 #maze30199(maze3)
N 30967 #maze30967(maze4)
i 31815

Now take a look at the data block at 28663, with its correctly coloured images of the mazes in the game, each one composed of 32x24 tiles. All without a single line of custom Python code in a SkoolKit extension module.

Well, I’ve done my best to showcase SMPL in this brief introduction. The rest is now up to you.

For details of the other (boring by comparison) changes in 5.1, see the changelog. But after that, go forth and define new macros.

Take Five

@assemble=1

SkoolKit 5.0 has been released. As dedicated followers of this website have no doubt already guessed, copies of 5.0 are available from the ever-present download page, the Python Package Index, and the Ubuntu PPA.

As even the not-so-dedicated followers among you might have noticed, 5.0 both looks and smells like a major new version, and there is little point in pretending that it isn’t. Not to put too fine a point on it, there are some changes that make SkoolKit 5.0 incompatible with some skool files and control files that work with SkoolKit 4.5 and earlier versions, which is why this new version isn’t simply 4.6. For example: the ‘D’ directive can no longer be used to define a mid-block comment - you must use the ‘N’ directive instead. Also: an ASM directive can no longer be declared by starting a line with ‘; @’ - you must use the ‘@’ directive in a control file, and omit the semicolon and space in a skool file. See the documentation on migrating from SkoolKit 4 for a comprehensive list of the compatibility-breaking changes, and for information on the skoolkit4to5.py utility, which might ease some of the pain of switching to SkoolKit 5.

But a major new version should be about more than just a bunch of backwards incompatibilities, and I’m glad to say that 5.0 is no exception to this rule. First of all, there are two new commands: skool2bin.py and tapinfo.py. As the name implies, skool2bin.py converts a skool file into a binary (raw memory) file, bypassing the need to create an ASM file with skool2asm.py first and then assemble it. Let’s be clear up front, though: skool2bin.py is not an assembler. At least, it’s not a fully fledged assembler, in that it knows nothing about labels or any kind of assembler directive besides DEFB, DEFM, DEFS and DEFW. As for tapinfo.py, this new utility displays information about the blocks in a TAP or TZX file. It will be most useful for determining the block numbers to use when creating a snapshot from a tape file with tap2sna.py.

Second of all, SkoolKit 5.0 says goodbye to XHTML 1.0 and hello to HTML5. Yes, the output of skool2html.py has left the 20th century behind and belatedly come crashing into the 21st. To be specific, the stock full-page HTML templates have been converted from XHTML 1.0 Strict to HTML5. And to drive the point home, they also sport <footer> elements, instead of the generic <div> elements of the bygone era.

Third of all, there is the new @assemble directive, which controls whether assembly language instructions are converted into byte values for the purpose of populating the memory snapshot. In previous versions of SkoolKit, only DEFB, DEFM, DEFS and DEFW statements were converted into byte values, but now we have the ability to convert regular instructions as well. Does your skool file contain any data definition entries (‘d’ blocks) whose only purpose is to provide the byte values for a block of code? Time to consider using the @assemble directive instead, and save some space into the bargain.

That’s about it for the main new features; see the changelog for further details. I hope you can all pluck up the courage to upgrade to SkoolKit 5.0 - if not today, then some time soon. And be sure to report any bugs you find, or backwards incompatibilities I have not (yet) documented!

Unlock the speed

BUG OFF YOU BIG WALLY

SkoolKit 4.5 has been released. Fresh copies are available for collection, as usual, from the download page, the Python Package Index, and the Ubuntu PPA.

But enough inane banter. What of the new features? Well, tap2sna.py has seen its first update since it was introduced in SkoolKit 3.5. Back then it could only read TZX block types 0x10 (standard speed data) and 0x11 (turbo speed data), but this set has been expanded by one (that’s 50%) to include block type 0x14 (pure data). In addition, tap2sna.py can now load the first and last bytes of a tape block (which are usually, but not always, the flag and parity bytes), and also modify memory with XOR and ADD operations. In case you’re struggling to see the point of all this, one word: Speedlock. Speedlock TZX files typically have the bulk of their data encoded in pure data blocks that have no flag or parity bytes and are scrambled by XOR and ADD operations. If the point is still not clear, come back to it later and try again with fresh eyes.

Elsewhere in the arena of SkoolKit commands, bin2tap.py has picked up a couple of new abilities. First, the --clear option, which creates a BASIC loader that has a CLEAR command, and otherwise leaves the stack pointer alone. This option enables you create a TAP file for a program that will run and then return to BASIC without crashing. Second, bin2tap.py can now convert not only a raw memory file, but also a SNA, SZX or Z80 snapshot into a TAP file. Just use the --org option to specify the origin address, and the new --end option to specify the end address of the section of memory to dump onto the tape.

Speaking of origins and ends, skool2asm.py, skool2ctl.py and skool2sft.py now sport --start and --end options for specifying how much of the input skool file to convert to ASM, CTL or SFT format. And the --start and --end options of sna2skool.py now also take effect when used in conjunction with the --ctl or --sft option to read a control file or skool file template. In short, we all now have the power to tell SkoolKit where to start and where to stop, and it will obey.

Which brings us to the end of this brief review of 4.5. As always, a more detailed list of changes can be found in the changelog. After that, if you’re convinced that 4.5 is worth the upgrade, go get a copy and descramble yourself some Speedlock tapes.