This is an old animation format on Acorn computers made by Ace Computing. It exists in several flavours.
There is bare Ace film that has barely any header (mostly just data size, title, some offsets) and chunks which start and end with the chunk size (so that you can seek backwards in the file). Then there’s chunked Ace film where all that data is wrapped into ACEF
chunk with some other chunks following it (like RATE
, FULL
or PALE
—the last one is for palette).
Presumably at offset 32 of raw data there is a compression method: 0, 1 or 2 (last one added in EuclidX). 0 means uncompressed data, 1 means LZW and 2 means unpacked data XORed with the previous frame.
Let’s take a closer look at method 1. It looks like a more or less conventional LZW. If the second byte of the stream is zero, the stream contains 16-bit little-endian LZW indices, otherwise it is variable-length LZW with initial index length being 9 bits (and value equal to 256) and growing up (the decoders don’t check upper limit but I suspect it should be around 16 bits). It also uses value 256 to signal the stream end and there are no other reserved values.
Apparently for convenience it decodes indices, stores them in the dictionary (it’s the property of LZW that each new index involves adding a new dictionary entry) and then decodes them backwards. After all, LZW dictionary entries are essentially stored in reverse so either you have to decode an entry, reverse and output it—or you can decode reverse string and output it at the end. This decoder chose the latter implementation (not that you can do it in any other way).
Unfortunately I’ve not managed to reconstruct data properly because of the implementation subtle details but I’m pretty sure anybody knowing how LZW works and willing to spend a bit of time fiddling with the format can come with a working decoder. As for me, it’s not interesting enough to spend more time on it. There are still several more ARMovie codecs to support and other formats to look at.