So here's my thoughts on how to handle compression. My
player can handle it just fine, using ScummVM as a guide, but I've always been afraid of doing the reverse...
We have the following commands:
- 0xC0 - top two bits set: clear out the top two bits. If zero, end this line. If not, skip that many bytes on the current line.
- 0x80 - only the top bit set: clear out the top two bits. If zero, copy raw bytes to finish the rest of the line. If not, copy that many raw bytes.
- Something that I can't quite express like that: a 16-bit value, small part is the command, large part the count.
- 2: Skip bytes.
- 3: Copy raw bytes.
- 6: Copy entire lines.
- 7: Skip entire lines.
Okay, so here's my theory on how to produce compressed SEQ frame data:
First, crop out the frame as before.
Obviously.
Second, if this is not the first frame, compare each run of pixels with the previous frame's and keep track of them in Run objects. Say you find one different pixel, you instantiate a new CopyRun with its Start set to the current column and Length set to 1, and add it to currentLine. Continue looking, and the next pixel is also different, so you increase currentRun.Length. Then you find a pixel that's the same as the previous frame's, so you start a SkipRun and do pretty much the same as before until you find the end of the current line. Continue with the next line until done. You should now have a series of Runs that cover the entire (cropped) frame:
currentFrameRunLines = [
[ CopyRun(0, 10), SkipRun(10, 12) ... ] //lengths total should equal frame width
[ SkipRun(0, 2), CopyRun(2, 8) ... ]
... //line total should equal frame height
]If this -was- the first frame, just store it fully raw as we do now.
Third, run through each line to emit the actual compressed frame data. Pick between 8-bit and 16-bit blocks where appropriate. If a run happens to reach the end of a line, emit the bytes to skip to the end. If a run spans the entire frame width, check if there's more such runs after and emit a "copy/skip entire lines" command.
I would personally build it up, as it were, doing only 8-bit commands at first and adding 16-bit support after. It seems safer.