Ouch my eye!

Do not look at LASER with remaining eye!


A new sub in the barn

Well looks like the break from the PIC file format didn’t last long. My last post we were wrapping up with the decoding of the MicroProse CAT file format when we stumbled upon what appears to be a previously unseen sub-type of the PIC89 variant of the PIC file format. I had actually suspected that this sub-type might exist, back when we were exploring the PIC89 variant (then referred to as PIC90 for reasons covered here), but had no assets to support that theory until now. Lets dig in and see what this mystery sub-type holds for us.

I always suspected that Type F had an unpacked cousin in the form of Type E, ever since we discovered it. It just made sense as every other form we’ve seen supported both packed and unpacked, why should it be any different here? It turns out we had it all along, it was just hiding, buried inside a CAT archive where we couldn’t see it. Makes me wonder what other secrets lie inside those CAT files. So far all of our PIC variants (with the exception of possibly PIC93) have supported 2 different pixel encodings, and that includes PIC89 and its sub-types… well except for Type F, which seemed to lack a counterpart for the other pixel encoding.

Just to recap a bit here. The PIC89 variant of the MicroProse PIC file format appears to have several sub-types (or at least that’s how I’m referring to them as) The sub-types define how the rest of the image and additional meta-data are encoded. Just like the PIC88 and PIC90 variants, two different pixel encodings are supported, unpacked and packed. With PIC89 this was true also, at least for sub-types 6 & 7. Type F seemed to stand out, as it had no twin (Type-E) for unpacked data. Now we’ve found a Type E file, and it’s time to see if it fits the pattern of being a twin to Type F, but with unpacked pixels, or is it something completely different.


We already know the bulk of the structure for any PIC89 sub-type, they all share a common 6 byte header that includes the 16 bit type identifier, 16 bit width, and 16 bit height.

typedef struct {
    uint16_t type;    // 16 bit type value
    uint16_t width;   // image width
    uint16_t height;  // image height
} pic89_hdr_t;

Anything after that is specific to the sub-type. With types 6 & 7 what follows is basically just the LZW compressed image data prefixed with the max bits value. With Type F there is an additional 16 byte CGA Mapping table that precedes image data in the same form as the other types.

typedef struct {
    uint8_t max_bits;      // max bit width for LZW codeword
    uint8_t lzdata[];      // LZW compressed datastream
} pic89_t6t7_t;

typedef struct {
    uint8_t cga_remap[16]; // CGA remap/dither table
    uint8_t max_bits;      // max bit width for LZW codeword
    uint8_t lzdata[];      // LZW compressed datastream
} pic89_tf_t;

I suspect Type E to take the same from as Type F. If so, this is probably going to be a short post.


A first look at Type E

File: EBOOT/SS_TITLE.PIC  [3367 bytes]
Offset    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF  Decoded Text
0000000x: 0E 00 40 01 C8 00 00 11 02 03 10 11 33 13 20 33  · · @ · · · · · · · · · 3 ·   3
0000001x: 22 11 30 31 32 33 0B 00 20 FD 0B 38 50 20 C1 83  " · 0 1 2 3 · ·   · · 8 P   · ·
0000002x: 06 13 16 5C 88 90 A1 C2 86 08 CF 05 48 00 A9 41  · · · \ · · · · · · · · H · · A
0000003x: 00 00 13 21 11 08 48 80 22 05 00 00 3C 06 84 40  · · · ! · · H · " · · · < · · @

0E 00: 0x000E (14) Type 'E'
40 01: 0x0140 (320) Width
C8 00: 0x00C8 (200) Height

Well it certainly starts off like a proper PIC89 type file, and the sub-type code is most definitely indicating a sub-type of 0x000E, so our PIC identifying program wasn’t confused and showing us an incorrect id. What follows is not the typical 0x0b we see prefixed before the image data, so this is not like types 6 & 7, not that we expected it to. Let’s look at the next bit.

File: EBOOT/SS_TITLE.PIC  [3367 bytes]
Offset    x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF  Decoded Text
0000000x: 0E 00 40 01 C8 00 00 11 02 03 10 11 33 13 20 33  · · @ · · · · · · · · · 3 ·   3
0000001x: 22 11 30 31 32 33 0B 00 20 FD 0B 38 50 20 C1 83  " · 0 1 2 3 · ·   · · 8 P   · ·
0000002x: 06 13 16 5C 88 90 A1 C2 86 08 CF 05 48 00 A9 41  · · · \ · · · · · · · · H · · A
0000003x: 00 00 13 21 11 08 48 80 22 05 00 00 3C 06 84 40  · · · ! · · H · " · · · < · · @

We can see that there are 16 bytes of data that occur before we see a 0x0b so this definitely appears to fit the same pattern as Type F. The nature of the 16 bytes certainly also seems fit the pattern of being a CGA dither/remap. Nibbles limited in range 0-3, often repeated but sometimes alternating with another value. Finally we see our 0x0B which is the typical value of 11 for the maximum LZW code-width that we have seen for pretty much all the PIC files so far compressed by MicroProse. Next thing to do is to check the image data, and the best way to do that is to render it.


Rendering the Type E file

While I suspect an unpacked image, I’ll render it both ways for comparison here. To do that I need to remove all the PIC89 header before the 0x0B this effectively makes it a PIC88 file. Then I can render it wit the values of 0x0b for packed and then again with 0xF5 for unpacked.

SS_TITLE.PIC (Type E – Packed)
SS_TITLE.PIC (Type E – Unpacked)

Well that makes it pretty clear that this is indeed unpacked data as we have suspected. Not too surprised, everything follows a logical arrangement here. And for completeness, this is how the file renders in CGA mode, using the CGA mapping.

SS_TITLE.PNG (Type E – CGA Mapping)

That pretty much does it for this one, not much else to say here. We’ve added to our list of sub-types so we have a more complete list of possible PIC variants, and sub-types. The next stop for the PIC journey will be to make proper readers and writers for each of the variants, instead of relaying on manual manipulation to convert it to work with our existing PIC88 renderer. That will then bring me one step closer to having something I can release in terms of code. The aim is to have a set of command-line tools capable of converting to/from PIC and some modern format, likely PNG. As well as preserve meta-data like the CGA mapping tables here, or the palette and EGA mapping tables we see in the PIC90 format. This should help facilitate modding of the graphics assets for those that are so-inclined. I plan to eventually take on the larger task of writing a graphical app for working with the images, but that is a longer term project and goal.

By Thread



One response to “A new sub in the barn”

  1. Great work as always!

Leave a reply to andreas86x Cancel reply