SkoolKit

Spectrum game disassembly toolkit

Cramping one's style sheet

SkoolKit 10.2 has been released. To get a copy, please head over to the download page, the Python Package Index, or GitHub.

Over the years, SkoolKit has built up a comprehensive automated test suite, growing from 54 tests for version 1.1 up to 4950 tests for this latest version. Their main purpose is, of course, to ensure that I don’t accidentally break things that used to work - or, to put it another way, to ensure that the “happy paths” continue to be happy. But what about the sad, dejected, or downright depressed paths - by which I mean error conditions? Perhaps SkoolKit has historically not been particularly strong on that point, so recently I have concentrated quite a bit on what happens when things go wrong. To cut a long story short, this version of SkoolKit is slightly less likely than all of its predecessors to produce a confusing Python stack trace when an error occurs, and is correspondingly slightly more likely to produce a somewhat helpful error message explaining what went wrong. Fingers crossed, anyway.

Another area where SkoolKit has historically been quite weak is web design. The default HTML templates and CSS rules are functional, but that’s about all that can be said for them. In particular, one aspect of web design that has been conspicuous by its absence from those templates and that CSS is responsiveness. True, SkoolKit itself is older than the concept of responsive web design - but not by much. Anyway, things have improved a little in this release. The next time you go looking for a SkoolKit disassembly on your phone, then so long as it’s using the stock templates and CSS from 10.2 (or some theme derived from them), the fonts should be legible without having to zoom, and the amount of horizontal scrolling required should have drastically reduced. Fingers crossed (again), anyway.

In keeping with the theme of “little things that should have been done ages ago”, the rest of the new features in this release fall mainly in the category of what might be called “housekeeping”. For example, rzxplay.py now reads configuration from skoolkit.ini (alongside all the other commands for which a central configuration file makes sense and were already enjoying that feature). So if you’re sick of the screen popping up every time you run the command, add Screen=0 to the [rzxplay] section of skoolkit.ini and you need never supply the --no-screen option again. But if you like the screen, never fear: there are also configuration parameters for setting its default scale (ScreenScale) and frame rate (ScreenFps). And for those more interested in tracing code execution, the format of the trace log can now be configured via the TraceHeader, TraceLine and TraceOperand parameters (as they already could be for trace.py).

Other such changes to be aware of include the addition of the --analyse option to tapinfo.py. This provides exactly the same information on a tape’s tones and pulses as the --tape-analysis option of tap2sna.py has done since version 8.10, but at least now it’s accomplished by the command you’d expect it to be accomplished by. Also, the --map option of trace.py now updates an existing file instead of replacing it - which makes it behave exactly as the --map option of rzxplay.py has always behaved, and much more useful for building a code execution map over multiple runs.

For a full list of all the new features and fixes since 10.1, I recommend consulting the changelog. And after that, go ahead an create an animated PNG of your favourite game character that contains more than 255 frames - just because you can now.

Blurring the border lines

SkoolKit 10.1 has been released. To get a copy, please head over to the download page, the Python Package Index, or GitHub.

Back in SkoolKit 9.2, the upstart new command was rzxplay.py with its ability to play RZX files (hence the name). It also had the ability to display a (borderless) screen, so you could sit back and watch the action as the command mapped out the executable code in whatever game you were reverse-engineering. Soon after that release, trace.py kept bugging me for its own screen-drawing capability, which I added (still borderlessly) in 9.4. Then, in 10.0, I added a border area to the screen displayed by rzxplay.py and trace.py. It could only display one colour at any given time, but despite that limitation, it caught the attention of tap2sna.py. That command then started bugging me for its own screen-drawing capability, but with support for multiple colours in the border area - think ‘loading stripes’ - or else. All of which is a roundabout way of bringing us to the current release, with tapsna.py boasting a new --screen option, and all three commands in this story now enjoying a border that can display multiple colours simultaneously all day, every day, and twice on Sundays.

However, though it might be fun to watch the previously headless tap2sna.py show off the speed of its phantom typist, or slowly draw a loading screen (or a little more quickly draw a loading screen, if the ScreenFps configuration parameter is set to 0), I can tell you from experience that the appeal soon wears off. I imagine the --screen option will come in most useful for troubleshooting tricky tapes that refuse to load - no longer will such troubleshooting have to be done ‘blind’, as it were. That said, the visual reassurance that tap2sna.py really is simulating a real tape loading on a real Spectrum (and not just cheating while you’re not looking) is somewhat comforting.

In other screen-related news, rzxplay.py now has a --cmio option, which simulates memory and I/O contention and the MEMPTR register. How is that screen-related, you ask? Well, some games employ border effects whose timing relies on memory and I/O contention: Aquaplane is a good example. So now you can use rzxplay.py to watch the RZX of that game as nature intended. The --cmio option will also come in handy for playing an RZX file whose execution path depends on accurate emulation of the MEMPTR register. I’m not aware of any such RZX files at the moment, however - at least, none that correctly play to completion in a modern emulator.

So much for the visual improvements in SkoolKit 10.1. What about the audio improvements? Well, after AY audio support was added in 10.0, it only makes sense that trace.py and the #AUDIO macro should gain the ability to tweak that AY simulation experience via the --volume option and vol parameter for setting the volume; the --ay-mode option and aymode parameter for setting the AY stereo mode (to ABC, ACB or MONO); and the --ay-res option and ayres parameter for setting the AY sampling resolution (in T-states). The default AY sampling resolution of 622 T-states - equivalent to 5700Hz on a 128K Spectrum - should be good enough for capturing most AY speech and other sound effects, but if you ever find it lacking, now there’s a way to adjust it.

Finally, speaking of the screen and AY audio - as I have been - I should also mention that the ‘Screen’ (to give it its official name) and the AY audio writer are now pluggable components. So if you don’t like the way SkoolKit draws pixels or rips AY audio, you can bloody well write your own components and plug them in via the component API. More power to you.

Finally finally, for even more details on what’s new in 10.1, visit the changelog. After that, get a copy of 10.1 and use the --screen option of tap2sna.py (along with the acceleration-disabling, real-time-matching -c fast-load=0 and -c cmio=1 options) to watch Skool Daze take over four minutes to load, just like the good old days.

Offering a few MEMPTRs

SkoolKit 10.0 has been released. To get a copy, please head over to the download page, the Python Package Index, or GitHub.

Before we get into the meat of what’s new in 10.0, a word of warning. As is often the case with an N.0 release, there are some compatibility-breaking changes, which you can read about in the migration guide. In particular, the #UDGARRAY* macro is no more, the syntax of the #AUDIO macro has had a complete overhaul, and the #CALL, #FONT, #LINK and #UDGARRAY macros no longer support the syntax that was deprecated in 9.x. But never fear - in keeping with tradition, there is a migration script (skoolkit9to10.py) to help you get your skool files, control files and ref files ready for 10.0.

When support for simulating code execution on a 128K Spectrum was added back in SkoolKit 9.1, you might have been forgiven for thinking that it would also gain the ability to convert AY audio into a WAV file. However, you would have thought wrong. A couple of years later, though - which, as the saying goes, is better than never - SkoolKit 10.0 steps in to provide that missing functionality. So, for example, you could capture the AY speech at the beginning of Robocop with:

$ tap2sna.py -c machine=128 "Robocop - Side A.tzx" robocop.z80
$ trace.py --ay --stop 39978 robocop.z80 robocop.wav

Of course, the #AUDIO macro can now capture AY audio as well by setting its brand new ay parameter to 1. And for those cases where you want to capture both AY and beeper audio at the same time, you can use the --ay and --beeper options of trace.py, or set the ay and bpr parameters of the #AUDIO macro to 1.

In other simulator-related news, fans of MEMPTR (or WZ, as the case may be) can rejoice in the fact that 10.0 brings full support for this often overlooked internal register pair. It is simulated whenever memory and I/O contention are enabled, i.e. when the --cmio option of trace.py is specified, and when the cmio parameter of the #AUDIO, #SIM or #TSTATES macro is set to 1. In addition, snapinfo.py now shows the value of MEMPTR in SZX snapshots, and bin2sna.py, snapmod.py, tap2sna.py and trace.py can all set the value of MEMPTR. tap2sna.py and trace.py can also log the value of MEMPTR via the r[memptr] replacement field. So what does all of this mean in practice? Well, you could, for example, now use trace.py to play MEMPTR Snake properly. The possibilities are truly endless.

Speaking of using trace.py to play games, that experience - still not recommended, by the way - should be slightly less awful in 10.0 thanks to the border area now being included in the display. It won’t show multi-colour border effects (at least not yet), but the effect of entering ‘BORDER 0’, for example, being distinguishable from nothing counts as progress in my book. Obviously rzxplay.py benefits from this new feature as well.

Remember the comment generator introduced in SkoolKit 9.5? No need to apologise if you don’t. Anyway, it has been updated to handle some keyboard-reading instructions a little more intelligently. Specifically, the comment for ‘IN r,(C)’ immediately after ‘LD BC,$XXFE’, along with the comment for ‘IN A,($FE)’ immediately after ‘LD A,$XX’, now indicates the half-row of the keyboard being read when eaxctly one bit of XX is reset. Which should make it easier to spot that all-important keyboard-reading code in a freshly made skool file.

And that’s about it for the main new features in this release. For details of the non-main new features, visit the changelog. After that, get a copy of 10.0 and test your mental MEMPTR-tracing skills against trace.py running on your favourite game.