MNEMOcompress
Released on issue 68 of Fred disk magazine, spring 1996.
Updated 24/2/98 to v2.01 (bugfix)
"Excellent" - Stefan Drissen
Programmed by Andrew Collier. This compressor is intended mainly for
screens, but can be used to compress any code, provided that the
compressed and uncompressed code can be in memory simultaneously. The
algorithm uses Huffman encoding and Run-length compression. The compressor
is fully integrated into Basic, and there is an on-screen progress
indicator during the compression of memory areas. Multiple screens can be
grouped into blocks automatically.
Instructions
Technical info in italics
Compatability note
This program directly calls some ROM routines, and has been tested
with ROM version 3.0. If your sam has a clone ROM or a later version then
the program should function correctly.If not then a crash may be caused; a
warning message will be displayed when the program is installed.
Installing the compressor code
Load the code at the start of any page (>0); ie at an address which
is a multiple of 16384, 32768 or higher; and execute once.
Eg. LOAD "MNEMOcomp" CODE 81920 : CALL 81920
Providing that sufficient memory is available, code will be
installed into the system heap and the highest available free page. This
page number is USR's return value, which is also included on-screen in the
installation message. It is, if necessary, possible to force installation
into a specified page: eg CALL 81920,28
A new token is now valid: COMPRESS (You may type COMP. as
shorthand) This is used as part of a command or function.
Compressing a screen
The code always compresses the currently displayed
screen and palette. When you compress the first screen, you must always supply
an address at which the result is to be stored. eg COMP. SCREEN AT 98304
The screen will turn black, there will be a little flickering, and several
seconds later the picture will reappear. The function COMPRESS LENGTH will give
the length of this screen.
To compress a second screen, to be viewed immediately after the first, do not
specify an address. Simply type instead: COMP. SCREEN
The function COMPRESS LENGTH always gives the total length
of all screens which have been compressed together (It is reset when a new
destination start address is given.) Memory restiction is the only limit to
the number of
screens which may be compressed in a block. When all screens have been
compressed,save the code.
eg SAVE "screenblok" code 98304, COMP. LENGTH
Uncompressing a screen
Files may be decompressed either from the COMPRESSing
program, or from the seperate MNEMexpand file.
It is necessary to CALL the code which has been installed :-
address = 16384*(page+1)
where page is the number given when the code was installed. To decompress the first (or only) screen in a block, CALL address,data_addr. To decompress subsequent screens, CALL address. Note that although VMPR (which controls screen mode) is changed temporarily, BASIC will not always respond to any changes. Particularly if the command is entered from the editor line, a decompression should be followed by a pause.
This highly space-optimised program fits snugly into two disk sectors, and is the only file which necessarily needs to be included with compressed data. It can be loaded at the start of any page (>0) and uses 8K of that page. Screens and screen blocks are decompressed with the command:
CALL address,data_addr
If a block contains only one screen then this screen is decompressed and displayed, and control returns immediately to basic. If, on the other hand, a block contains many screens then all the screens are decompressed and displayed in order, with a pause between each for the user to press a key. Two screens are used, so one screen may be viewed while the other is being decompressed.
Compressing an area of memory
It generally must be arranged that the original data, the compressor and the compressed code are in memory seperately at the same time. (This is unlikely to be a problem unless the file is very large, in which case another compressor may be a better solution. See algorithm notes, below.)
The command takes the form:
COMPRESS start_addr TO end_addr AT destination_addr
The start and end values are inclusive. During compression, the screen is switched off to increase clock speed. However, at the bottom of the screen, some indicators are made visible. Compression takes place in three stages.
When this is complete, COMPRESS LENGTH again gives the number of bytes used in the compressed file. The file can be decompressed from either the Compressor or MNEMexpand code, with:
CALL address,data_addr,destination_addr
A Note on Compression Algorithms
Every data compression technique has its own strengths and weaknesses. The huffman algorithm optimises frequently occurring bytes by giving them codes less than eight bits long. This program is recommended mainly for use with with screens, and has beaten its known competitors for space in the vast majority of tested images. The algorithm works at the cost of speed - treating a file as a sequence of bits is far more difficult thanas a sequence of bytes; it can be somewhat slower than for example, Rumsoft's Imploder, which optimises commonly occurring sequences of bytes. One of that program's biggest advantages is that the original data needn't be kept intact throughout decompression, and thus it is able to handle much larger files than my program.
Decompression speed is an important factor to consider when choosing a compression system to use. The MNEMexpand file keeps interrupts enabled, so that screens which use palette line may be viewed properly. The compressor program does not, and is therefore able to use the stack pointer during decompression, resulting in a 50% increase in speed. The imploder is a little faster and sometimes more efficient, but my program has the advantage that I have included decompression source code - an adventurous coder might like to include some intro effects to help pass the time while the main demo decompresses... Remember that various algorithms will have different levels of success on different files, so trial and error with various systems is possibly the only way to ensure greatest efficiency.