After playing around with compressed loading screens and compressed application images, I ended up with a monstrosity of a build scheme.
It's no wonder most people don't bother with the compression..
On the left side of the graph you can see an example of a relatively complex project with couple C and couple assembly files being first compiled with their appropriate compilers and then linked, resulting in an intel hex (ihx) file. This file is typically converted to binary and then run through some .tap making utility, and we're done. Well, done-ish. But if we want a loading screen, and want both the loading screen and the application image to be compressed, things get a bit hairier.
First, you'll notice that we're compiling the hypothetical "unpack.asm" twice. This is because they're not position independent, and will have to run from different offsets. The compiled decompressors and then binarified and copy /b:d to a combined binary file which can then be tapified. On the loading screen side things are slightly more complicated because we need a specific bootstrap written in spectrum BASIC and the compressed loading screen image itself, but eventually we get a tap file from that branch as well. These tap files can be joined with another copy /b command to get the final tap file.
What the graph doesn't include is that since you pretty much always end up with compressed files of different sizes, you also end up with different loading offsets, which may mean patching the compiled binaries, or recompiling the boot-up assembly after manual changes. And you also need to care about all the offsets you want to load things into, and have to update build scripts and whatnot whenever these change.
Or you can do something a little fishy.
Introducing Mackarel, the one-stop solution for neat zx spectrum releases. Mackarel converts ihx files, generates the needed basic, generates loading screens if need be, compresses, patches binaries, and generates the final tap file in one swell swoop.
There's a couple different compression algorithms to pick from, but the defaults are picked so that you don't really have to care about it. If your compile chain doesn't generate ihx files, you can also feed binaries to Mackarel, but then you have to give the start address of the binary too.
On a more technical side, the compressed loading screen and combined basic bootstrap works pretty much the same way as described in my earlier post about compressed loading images, except that everything is self-contained within Mackarel and you don't need to call any compressors, etc. yourself. If no loading screen is provided, Mackarel will generate a simple one for you which typically takes, along with its decompressor, about 250 bytes.
The application image itself is compressed and loaded to the end of the memory space. Upon launching, the bootloader first copies itself to video memory, and also sets stack to point there. Running from video memory, it decompresses the application image to the desired start address, restores stack and hops to the beginning of the image. Assuming the application doesn't do anything wonky, it's clean to exit back to basic if you really want to.
As before, all of the code is available on github.