Exomizer
Exomizer is a file compression utility which is designed so that files can be compressed quickly and efficiently on a PC and decompressed on 8-bit machines, such as the Amstrad CPC, where memory and processing power are much more limited. Across the 8-bit programming scene, it is generally regarded as the most efficient compressor that is currently available.
Tutorial
Installing Exomizer
Firstly, download Exomizer from the home page; the link is at the bottom of this article.
For Windows:
Unzip the ZIP file to a folder of your choice (e.g. C:\exomizer). The Windows binaries are located in the win32\ subfolder. For ease of use, copy the exomizer.exe file in this subfolder to the main folder (i.e. C:\exomizer).
This tutorial also assumes that ManageDsk (a Windows utility for manipulating DSK files) is installed on your PC.
For Linux:
You need to download the zip, extract it and build it from source. You will gnu C installed.
unzip exomizer202.zip cd exomizer202/src make
When you are done you will have b2membuf, exobasic, exomizer and exoraw in the same directory as the source.
Compression
For this example, the game code for Mirrorsoft's classic game Boulder Dash will be used as the file to decompress. Its start address is &200, its length is &7520 bytes (29,984 bytes in decimal), its execution address is &1F52, and the file name is BOULDER.BIN.
Start ManageDsk, and select the DSK file that BOULDER.BIN is saved on. Export BOULDER.BIN to the Exomizer folder. You must ensure that you export it without an AMSDOS header.
Now open a command prompt and go to the Exomizer folder by typing:
cd C:\exomizer
Then type the following command to compress BOULDER.BIN and save the compressed file as BOULDERC.BIN:
exomizer raw boulder.bin -o boulderc.bin
This produces the following output:
Crunching infile "boulder.bin" to outfile "boulderc.bin". Phase 1: Instrumenting file ----------------------------- Length of indata: 29984 bytes. [building.directed.acyclic.graph.building.directed.acyclic.graph.] Instrumenting file, done. Phase 2: Calculating encoding ----------------------------- pass 1: optimizing .. [finding.cheapest.path.finding.cheapest.path.finding.cheapest.pat] size 88005.0 bits ~11001 bytes pass 2: optimizing .. [finding.cheapest.path.finding.cheapest.path.finding.cheapest.pat] size 87512.0 bits ~10939 bytes pass 3: optimizing .. [finding.cheapest.path.finding.cheapest.path.finding.cheapest.pat] size 87512.0 bits ~10939 bytes Calculating encoding, done. Phase 3: Generating output file ------------------------------ Encoding: 11222454573A2071,1012,1100233355666788,1232234457819AAD Length of crunched data: 10968 bytes. Literal sequences are not used and the safety offset is 2.
This information shows that Exomizer has managed to compress BOULDER.BIN from 29,984 bytes to just 10,968 bytes (&2AD8 in hexadecimal) - around 37% of its original size! The safety offset refers to the minimum number of bytes that must separate the final byte of the compressed file and the final byte of the decompressed data - more about this below.
Decompression
Now that the file has been compressed, use ManageDsk to import BOULDERC.BIN back to a DSK file. You must ensure that you import it as a binary file, and not an ASCII file, as ManageDsk will need to add an AMSDOS header. The program will ask for the start address and entry point of the file.
Remember the safety offset that was mentioned earlier? The game code starts at &200 and is &7520 bytes long, so the final byte is located at address &200 + &7520 - 1 = &771F. As the safety offset for BOULDERC.BIN is 2 bytes, this means that the final byte of this file can be located at any address from &771F + 2 = &7721 or above. This means that the lowest start address that the file can be loaded to is &7721 - &2AD8 + 1 = &4C4A (or 0x4C4A), so enter this value as the start address. The entry point should be left at 0x0000.
The Z80 assembler source code for decompressing files is located in the rawdecrs\z80\ subfolder, and the file name is deexo.asm. The decompression routine is 198 bytes long, and it also requires a buffer of 156 bytes. The buffer is labelled exo_mapbasebits
, and it is located immediately after the decompression routine, but you can alter it (by adding the line exo_mapbasebits equ &xxxx
) so that it is located anywhere in memory - as long as it doesn't overwrite the compressed file or the decompressed data! Assemble the decompression routine to a suitable address in memory using an assembler of your choice (e.g. Pasmo or WinAPE's built-in assembler); again, ensure that it doesn't overwrite the compressed file or the decompressed data. The code supplied with Exomizer may need to be edited to suit the syntax of your assembler.
Now you will need to add some code to load BOULDERC.BIN into memory and decompress it. Add the following code before the decompression routine:
load_file: ld hl,filename ;HL = file name address ld de,&4c4a ;DE = start address to load file to ld b,12 ;B = length of file name call &bc77 ;Open the file header ex de,hl ;Now HL = start address push hl ;Store it call &bc83 ;Load the file call &bc7a ;Close the file decompress_file: pop hl ;HL = start address of compressed file ld de,&0200 ;DE = start address of decompressed data call deexo ;Decompress the data start_game: jp &1f52 ;Start the game filename: db "BOULDERC.BIN" ;Name of file containing compressed data
Finally, run this code, and if you have done everything correctly, you should see the Boulder Dash title screen!
Bugs
Exomizer can sometimes fail to decompress files correctly for no apparent reason, causing the CPC to crash. Unfortunately there is no known way to overcome this problem, other than to use a different compressor.
[31-August-2017] The above claim is questionable. The *only* times I've ever encountered such Exomizer crashes were due to errors on my part (for example, an incorrect data type for an array in C). In my experience, Exomizer itself has never caused any problems.