*SVPIC, *LDPIC compressed screen saving and loading =================================================== v2.10 - 23-Dec-2017 *LDPIC and *SVPIC are commands to load and save compressed screen images, including the palette information. They work on BBC and Master and with shadow screens on the Master, Aries-B32 and Watford shadow screen systems. The original code for them was published in the October 1986 issue of Acorn User, issue number 51. The original code was broken and failed on many systems, and was rewritten as v2.00 by J.G.Harston. The latest version has been extended to transparently support 12-bit palettes. An old version of LDPIC will load a new version LDPIC file and will ignore any extensions. A new version of LDPIC will load an old version LDPIC file without any extensions. *LDPIC ------------- Loads in a compressed screen picture saved with *SVPIC with its palette information. If a shadow screen mode is selected, then any mode change will also be a shadow mode. On a B+ non-shadow modes are forced. Shadow screen cannot be supported on the B+ as the hardware only allows the VDU driver code between &C000 and &DFFF to access the shadow screen memory. *SVPIC ------------ Saves a screen picture, and attempts to compress it. Makes several passes through the data to find the smallest possible output file, so can take up to about 2 minutes to complete. It is theoretically possible for a very complex picture to result in a file larger than a simple *SAVE would create. Technical details ----------------- The file data is a bit stream that is read from bit 7 of each byte in the file into bit 7 of the receiving data byte, so data bytes in the file are reversed compared to their value. The file contains several blocks, each of which starts aligned to a byte boundary: Offset Size Name Description ------------------------------------------------------------------------- 0000 1 byte DATAW Data width - number of bits in DATA entries. 0001 1 byte MODE Screen mode. 0002 8 bytes PALETTE Palette entries, 16 values of 4-bit FBGR colours. Colour 15 is first, colour 0 is last. 000A 1 byte STEP Step-1 between bytes loaded to the image memory. 000B 1 byte COUNTW Count width - number of bits in COUNT entries. 000C ... DATA Image Data xxxx 24 bytes PAL12 Optional 12-bit palette data, 16 sets of three 4-bit {red, green, blue} colour values. Colour 15 is first, colour 0 is last. yyyy 1 byte len ... NAUX If len>0: optional nULA control data { repeat: zzzz 1 byte len ... extra If len>0: extra information blocks } If the 12-bit palette data is present it can be followed by any number of blocks of "len, { len x byte }" sequences. The first of these sequences is control data to write to the nULA auxilary control data. For example, the sequence {1, &11} programs the nULA to use logical colour mapping. The palette entries at PALETTE map logical colour numbers to physical colour numbers. The palette entries at PAL12 by default then map those physical colour numbers to 12-bit analogue colour values. So, if colour 2 is mapped to physical colour 4 (blue) in PALETTE, entry 4 in PAL12 maps that to a 12-bit colour value. If the NAUX control data includes the &11 control byte, that switches to using logical colour mapping. Then, the logical colour numbers are mapped directly to 12-bit analogue colour values in PAL12. In the above example, if colour 2 is mapped to an analogue colour value in entry 2 in PAL12. In all cases, PALETTE must contain a set of 4-bit physical colour numbers so the image is viewable on systems with only 4-bit colour hardware. The file can terminate at any point and the load must terminate cleanly at that point. For instance, a file could contain just the data for the top half of the screen, and omit the bottom half of the screen. If the file terminates early there cannot be any subsequent blocks. Each block (header, image data, palette, extensions) is byte aligned, so other than the compressed image data they can be simply read as byte values and the bits reversed. The file contents are optimised to be read efficiently. An inefficiency is that to read and update the PAL12 and subsequent entries, the whole file has to be scanned through to find where the end of the image data is. As a bit stream the file contents looks like the following, with bit 7 of each file byte being the first read and becoming bit 0 of the resulting value. Header bit stream ~~~~~~~~~~~~~~~~~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |w w w w 0 0 0 0|m m m 0 0 0 0 m| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ DATAW MODE +-+-+-+-+-+-+-+-+-+-+-+-+-+...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |r g b f|r g b f|r g b f|r ... f|r g b f|r g b f|r g b f|r g b f|r g b f| +-+-+-+-+-+-+-+-+-+-+-+-+-+...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 15 14 13 4 3 2 1 0 palette entries +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |s s s s 0 0 0 0|c c c c 0 0 0 0| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ STEP COUNTW Data bit stream ~~~~~~~~~~~~~~~ +-+-....-+ +-+-...-+-....-+ Multiple sets of: |0| DATA | or |1|COUNT| DATA | until end of screen or +-+-....-+ +-+-...-+-....-+ end of file 12-bit palette bit stream ~~~~~~~~~~~~~~~~~~~~~~~~~ +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... |r r r r|g g g g|b b b b|r r r r|g g g g|b b b b|r g b f|.... +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+... \--------15---------/ \--------14---------/ ...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ....|b b b b|r r r r|g g g g|b b b b|r r r r|g g g g|b b b b| ...+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ \---------1---------/ \---------0---------/ Extended palette control block bit stream ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ |n n n n n n n n| n sets of |d d d d d d d d| +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ The data bytes are written to the nULA auxilary control register. This allows logical colour mapping, border colours, and non-standard geometries to be included in the file. Remember, the bit stream is reversed compared to the actual byte values. See nULA documentation for more details. Typical values would be: &0n - select 3-bit RGB border colour &11 - use logical 12-bit palette mapping Decompression code ------------------ The following pseudocode describes how to decompress the image data. read data: finished = FALSE address = screenstart + STEP -1 loop read one bit if bit=0 { DATA=read number of bits set by DATAW store in current address update address } else { COUNT=read number of bits set by COUNTW DATA=read number of bits set by DATAW store this DATA byte COUNT number of times update address } until finished update address: address = address +1 if address>&7FFF { STEP = STEP -1 if STEP<0 { finished = TRUE } else { address = screenstart + STEP -1 } Example data ------------ 0 1 2 3 4 5 6 7 8 9 A B C D E F 000000 10 80 0C 82 0C 82 0C 82 0C 82 80 E0 FF AA FF AA | | | | | | | | | | | | | | DATAW=8 --+ | | | | | | | | | | | | | MODE 1 ------+ | | | | | | | | | | | | Palette ---------0 3 1 4 0 3 1 4 0 3 1 4 0 3 1 4 | | | +---1,COUNT=127,DATA=&55 STEP=1 ------------------------------------------+ | +-----------1,COUNT=127,DATA=&55 COUNTW=7 ----------------------------------------------+