Several posts back we looked at some other MicroProse titles and discovered that the PIC file format has evolved over the years with various titles. In this post we’re going to look at a few more titles that I found to have PIC files and see where they fit into the mix. Then we will hopefully be able to write some quick code to be able to identify what type of PIC file we’re looking at. This is a first stage to opening the newer variants up to our encoder/decoder.
Note from the future: This is an ongoing effort, and as such certain details are incorrect, and will change over time as more titles using the format are discovered. With that said please note that the designations used here for the variants does change in the future, as newer dates of earliest use become uncovered.Both the PIC90 and PIC91 formats will be discovered to occur a year earlier than they do here, making them PIC89 and PIC90 respectively.
(As of Jun 21 2024)
In my continuing effort to document use of the PIC file format by MicroProse and its evolution over the years, I’ve identified three more titles that appear to include PIC files. With hope, and some tools, I can enlist the help of others to scan their collections of MicroProse games for PIC files and identify the titles and what version they are using, as well as identifying any potentially new formats. the thee new titles I’ve identified are:
- F-14 Fleet Defender – 1994
- Railroad Tycoon – 1990
- Railroad Tycoon Deluxe – 1993
Just as before, I’m going to go through and discuss them in chronological order here.
Railroad Tycoon (Feb 1990)
Railroad Tycoon appears to use the same PIC90 format as Silent Service 2. This format is still the first evolution of the PIC format we’ve seen from the PIC88 version we’ve been working with. Given the asset dates of Feb 1990, they predate those of SS2, and are likely the first released use of this variant of the PIC file.

Railroad Tycoon Deluxe (Jun 1993)

Carrying on the tradition of its predecessor, Railroad Tycoon Deluxe (RRDX) introduces us to another variant of the PIC file that we have not seen before. This version seems to be closer to the PIC90 format than the PIC91 format that superseded it. Without the dates of the assets, I would have placed this version between the two. RRDX is largely a re-release of the original, with improved graphics, so perhaps that’s why this version seems to be a step from PIC90 rather than PIC91. This could be a solid hypothesis, if we don’t see the format used anywhere else. In keeping with out naming format, we will call this format PIC93.
Looking at the binary of one of the files, we can see that the 2-byte signature that was present in the PIC90 version, has been replaced with a 4 byte signature containing “H8”. Not sure of the significance of this value, as this is the only example I’ve seen so far. The signature is followed by 16 bit width and height values for the image. After the image dimensions I presume is the beginning of the image datastream, though the encoding is unclear. The “format identifier” byte that specified the max bit width for the LZW compression has vanished, and the encoding itself does not appear to be LZW at least not initially. More effort is going to be required to decode this version. This version also seems to go back to being a homogeneous file format containing only image data, and not the palette like we see with PIC91, though it is possible other blocks will emerge after decompressing/decoding.
File: LABS.PIC [6644 bytes]
Offset x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF Decoded Text
0000000x: 00 48 38 00 80 02 90 01 00 00 0A 0F 0F 05 00 0A · H 8 · · · · · · · · · · · · ·
0000001x: 00 00 0A 0A 0A 00 00 08 08 08 0A 05 00 0A 0A 0A · · · · · · · · · · · · · · · ·
0000002x: 05 05 05 05 05 0F 05 0F 05 00 0C 0F 0F 05 05 0F · · · · · · · · · · · · · · · ·
0000003x: 0E 0B 00 00 00 0F 0F 0F 48 09 55 55 00 FF F8 FC · · · · · · · · H · U U · · · ·
0280 = 640
0190 = 400
F-14 Fleet Defender (Feb 1994)
F-14 Fleet Defender (F14) goes back to using the PIC91 format which we have seen before with several titles. This seems to support the theory that the PIC93 format was a quick fix solely for the purpose of RRDX, and why it seems to fit between PIC90 and PIC91 from an evolution standpoint. Though both are a sample of one, so can’t say anything conclusively yet.

Coding the identities
Note from the future: Just a reminder that both the PIC90 and PIC91 formats will be discovered to occur a year earlier than they do here, making them PIC89 and PIC90 respectively. So the designations used here are incorrect. (As of Jun 21 2024)
So far we’ve been identifying the variants in a rather manual process of visual inspection with a hex editor. It’s time to try and teach the computer to do that for us. To do that we will write a quick program to read in the first few bytes of a given file (arbitrarily chose 16 here, which should be more than enough), and then try to determine the format through a sequence of tests, going from most-specific to least specific. Which as luck would have it is mostly the reverse chronological progress of the PIC file format. Starting with PIC93 and ending with PIC88.
We start by reading in the “header” bytes into our buffer hbuf
int nr = fread(hbuf, 1, 16, fp); // read up-to 16 bytes
fseek(fp,0,SEEK_SET); // return to the start of the file
if(0==nr) {
printf("Empty File\n"); // file too small to analyze
fclose(fp);
return -1;
}
Identifying PIC93
The PIC93 format seems to begin with 00 H 8 00 while it is quite possible these values bytes have meaning and could change, so far all the examples I’ve looked at begin like this. We will use this signature to identify the type. Along with identifying the types, we will print out whatever image information we can gather, this will help in our encode/decode implementations later. The signature is followed by 2 16 bit values that are the width and height of the image respectively. What follows after that is unknown at this point, but this should be enough to identify the type.
// PIC93: [00 "H8" 00][width16][height16][data...]
if((0==hbuf[0]) && ('H'==hbuf[1]) && ('8'==hbuf[2]) && (0==hbuf[3])) {
uint16_t *width = (uint16_t *)(hbuf+4);
uint16_t *height = (uint16_t *)(hbuf+6);
uint8_t fmt = abs((int8_t)(hbuf[8]));
printf("PIC93: Image: %dx%d\n", *width, *height);
return 93;
}
Identifying PIC91
PIC91 is a little less specific, as we don’t have a direct signature to look at. Instead we know that one of the chunk/block identifiers will appear first. So far we have identified via our own testing and what was documented in the infamous darklands.txt document that the known blocks are ‘M0‘, ‘X0‘, ‘X1‘, and ‘E0‘, and they can appear in any order. So we will use this fact to write a simple filter that will catch any of these. This one will be one of our most involved as we need to then skip down through the file looking at each block identifier to see what blocks the file contains, and printing the details we know about it.
Note that for ‘E0‘ I am assuming a grey-scale mapping palette as that makes the most sense, but is so far remains an untested theory. Another assumption I’m making here, is that the “Alt Image” data block ‘X1‘ as described in the darklands file format document is actually our packed pixel arrangement that we see with PIC88. It appears that the sign of the format identifier is not used in later versions to signal the packing.
typedef struct {
char block_id[2];
uint16_t len; // length of the block
} pic_block_t;
typedef struct {
uint16_t width;
uint16_t height;
uint8_t format_identifier;
} pic_image_hdr_t;
// PIC91: [block_id][length16][id specific data...]
if((('M'==hbuf[0]) || ('X'==hbuf[0]) || ('E'==hbuf[0])) &&
(('0'==hbuf[1]) || ('1'==hbuf[1]))) {
printf("PIC91:\n");
// print out sections:
do {
pic_block_t block_hdr;
nr = fread(&block_hdr, sizeof(pic_block_t), 1, fp);
if(nr > 0) {
// E0 block (greymap): [id][length16][start8][end8][data...]
// assumed use for this block, untested
if(0 == strncmp("E0", block_hdr.block_id, 2)) {
uint8_t start_idx = fgetc(fp);
uint8_t end_idx = fgetc(fp);
printf("\tGrey Map: Start: %d End %d (Len: %d)\n",
start_idx, end_idx, block_hdr.len);
block_hdr.len-=2;
// M0 block (palette): [id][length16][start8][end8][data...]
} else if(0 == strncmp("M0", block_hdr.block_id, 2)) {
uint8_t start_idx = fgetc(fp);
uint8_t end_idx = fgetc(fp);
printf("\tPalette: Start: %d End %d (Len: %d)\n",
start_idx, end_idx, block_hdr.len);
block_hdr.len-=2;
// X0 block (image): [id][length16][width16][height16][format8][data...]
} else if(0 == strncmp("X0", block_hdr.block_id, 2)) {
pic_image_hdr_t img_hdr;
nr = fread(&img_hdr, sizeof(pic_image_hdr_t), 1, fp);
printf("\tImage: %dx%d 0x%02x: max-bits: %d (Len: %d)\n",
img_hdr.width, img_hdr.height,
img_hdr.format_identifier, img_hdr.format_identifier,
block_hdr.len);
block_hdr.len-=sizeof(pic_image_hdr_t);
// X1 block (packed image): [id][length16][width16][height16][format8][data...]
} else if(0 == strncmp("X1", block_hdr.block_id, 2)) {
pic_image_hdr_t img_hdr;
nr = fread(&img_hdr, sizeof(pic_image_hdr_t), 1, fp);
printf("\tImage: %dx%d Packed 0x%02x: max-bits: %d (Len: %d)\n",
img_hdr.width, img_hdr.height,
img_hdr.format_identifier, img_hdr.format_identifier,
block_hdr.len);
block_hdr.len-=sizeof(pic_image_hdr_t);
// unknown block: [id][length16][data...]
} else {
printf("\tUnknown: %2.2s (Len: %d)\n",
block_hdr.block_id, block_hdr.len);
}
fseek(fp, block_hdr.len, SEEK_CUR); // skip ahead to the next block
}
} while(!feof(fp));
fclose(fp);
return 91;
}
Identifying PIC90
PIC90 is starting to get a bit more difficult, as we don’t have much to go on really, just fractions of bytes. To complicate things, we have seen at least 2 different values appear in the first two bytes, and if we’re not careful we could misidentify PIC88 files as PIC90. So we will constrain the range to exclude PIC88 values for the first byte. While we know that the PIC loader will accept a wide range of values for the format byte, only a small subset is practical, and pf that we have really only ever seen 11 (0b/f5) being used. The two values for PIC90 I have seen are 6 and 7, so I’m going to start by limiting PIC91 to be values less than 9, to avoid conflict with the range for PIC88. With that said, the pattern appears to be zero in the upper nibble of the first byte, and the second byte having a value of zero. One other note, the format byte with PIC90 always seems to be a positive value. I think that the packed/unpacked signalling is now done via the “Type” value (6 & 7)
// PIC90: [0T 00][width16][height16][format8][data...]
if((0==(hbuf[0] & 0xf0)) && (0 == hbuf[1]) && (9 > hbuf[0])) {
uint16_t *width = (uint16_t *)(hbuf+2);
uint16_t *height = (uint16_t *)(hbuf+4);
printf("PIC90: Type: %02x Image: %dx%d 0x%02x: max-bits: %d\n",
hbuf[0], *width, *height, hbuf[6], hbuf[6]);
return 90;
}
Identifying PIC88
PIC88 gives us the least to work with… only a single byte! And even worse is that that byte seems to have a very wide range of allowable values. However as discovered in testing, values below 9 are unacceptably slow, and practically speaking the upper limit would be 12-14 bits. So far we have only ever seen a value of 11 used. Of course we can’t forget that the byte appears to be treated as a signed value, with positive values meaning packed pixels, and negative values meaning unpacked pixels. So with that said, We will constrain PIC88 to be the absolute value of the first byte ranging from 9-15.
// PIC88: [format8][data...]
uint8_t fmt = abs((int8_t)(hbuf[0]));
if((8 < fmt) && (fmt < 16)) {
printf("PIC88: 0x%02x: max-bits: %d, %spacked\n",
hbuf[0], fmt, (hbuf[0]>127)?"un":"");
return 88;
}
And that is pretty much it. Let’s add a catch-all at the end and dump those 16 bytes we read so we can analyze if any unknowns that come up.
// Unknown format, print a hex dump of what we have for later analysis
printf("PIC??: ");
for(int i = 0; i<16; i++) {
if(i < nr) {
printf("%02x ", hbuf[i]);
} else {
printf(" ");
}
}
for(int i = 0; i<nr; i++) {
uint8_t ch = hbuf[i];
if((isprint(ch)) && (ch < 128)) {
printf(" %c", ch);
} else {
printf(" %lc", 0x00b7);
}
}
printf("\n");
Now I did things in a pretty ugly way here. But this is only for testing. For a final implementation I would likely create structures for each “header” type, and then create a union of them. This will allow for a much cleaner bit of code. With that said, let’s build it and give it a go with some known samples.
Debugging the identities
I guess it was too much to ask for this to work first try lol. I was pretty sure the LABS.PIC90 was pulled from RRT, which should be PIC90. (I was hoping to have a version of LABS.PIC for all 4, unfortunately none of the 91 titles I’ve identified so far have one)
% picinfo LABS.PIC88
Analyzing: 'LABS.PIC88': PIC88: 0x0b: max-bits: 11, Packed
% picinfo LABS.PIC90
Analyzing: 'LABS.PIC90': PIC88: 0x0f: max-bits: 15, Packed
% picinfo LABS.PIC93
Analyzing: 'LABS.PIC93': PIC93: Image: 640x400
% picinfo CITYPIX2.PIC91
Analyzing: 'CITYPIX2.PIC91': PIC91:
Grey Map: Start: 0 End 255 (Len: 258)
Palette: Start: 0 End 255 (Len: 770)
Image: 320x200 0x0b: max-bits: 11 (Len: 13553)
Let’s take a look at the PIC90 file and see why it’s showing up as a PIC88. Something is off, as it has the format byte as 0f, which would be very unusual.
File: LABS.PIC90 [2263 bytes]
Offset x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF Decoded Text
0000000x: 0F 00 40 01 C8 00 00 11 02 03 10 11 12 33 33 11 · · @ · · · · · · · · · · 3 3 ·
0000001x: 22 23 30 31 22 33 0B 00 20 99 00 84 08 D2 94 80 " # 0 1 " 3 · · · · · · · · ·
0000002x: 4C 00 05 94 A2 10 52 C2 85 0D 1F 42 62 88 B0 21 L · · · · · R · · · · B b · · !
0000003x: 45 87 16 23 66 AC 08 91 E3 44 8D 1D 31 86 94 78 E · · # f · · · · D · · 1 · · x
0140 = 320
00C8 = 200
This clearly looks to be a PIC90 file, but has a new type value we hadn’t noticed before. Time to make a few changes to our PIC90 detector to account for this. Adding to the mystery here is the encoding does not appear to be LZW, or at lest not based on 8 bit input symbols starting at 0006. I smell a new adventure coming on here, though whatever it is, it seems to have been short-lived as we never see this odd encoding again in PIC files anyway, as far as I’m aware, though possibly the same as what we see in PIC93. (I have a suspicion of what it might be based on the time) That adventure will have to wait, the goal right now is just identifying the files. Stay on target… Stay. on. target.
// PIC90: [0T 00][width16][height16]([format8])[data...]
// so far catalogued 6 and 7 and F for T, (6, 7 seem to have format byte, F does not)
if((0==(hbuf[0] & 0xf0)) && (0 == hbuf[1]) && ((9 > hbuf[0]) || (hbuf[0] > 14))) {
uint16_t *width = (uint16_t *)(hbuf+2);
uint16_t *height = (uint16_t *)(hbuf+4);
printf("PIC90: Type: %1x Image: %dx%d", hbuf[0], *width, *height);
if((0x06 == hbuf[0]) || (0x07 == hbuf[0])) {
printf(" 0x%02x: max-bits: %d", hbuf[6], hbuf[6]);
} else {
printf(" (Unknown Subtype)");
}
printf("\n");
return 90;
}
Here I’ve updated out PIC90 detection code to account for the new 0F type. And added in the format decoding for 06 and 07 though I don’t know which one is packed yet (assuming that is the distinction – though likely). We should probably update PIC88 to remove 15 bits as the max width, as it is highly unlikely we will ever see it, but doesn’t hurt to leave it in for now. Now that we have the ability to encode files, we will properly be able to explore the limits later. Let’s try our updated identifier code.
% picinfo LABS.PIC88
Analyzing: 'LABS.PIC88': PIC88: 0x0b: max-bits: 11, Packed
% picinfo LABS.PIC90
Analyzing: 'LABS.PIC90': PIC90: Type: f Image: 320x200 (Unknown Subtype)
% picinfo LABS.PIC93
Analyzing: 'LABS.PIC93': PIC93: Image: 640x400
% picinfo CITYPIX2.PIC
Analyzing: 'CITYPIX2.PIC': PIC91:
Grey Map: Start: 0 End 255 (Len: 258)
Palette: Start: 0 End 255 (Len: 770)
Image: 320x200 0x0b: max-bits: 11 (Len: 13553)
Well that is looking much better now. Though as we’ve learned from past experience, a sample size of one is not enough. Let’s run the code against some directories to see what we get. But for that we will need to do something similar to what we did when validating our decoder and encoder. We need a script to find the files, and then call our identifier code for each file found.
#!/bin/sh
find "$(pwd)/${1}" -name "*.PIC" -maxdepth 5 -type f -not -path '*/\.*' -exec ./picinfo {} \;
find "$(pwd)/${1}" -name "*.SPR" -maxdepth 5 -type f -not -path '*/\.*' -exec ./picinfo {} \;
With that done, let’s give it a go. As some of these can have a lot of files, I’ll truncate to the first 10.
F-15 Strike Eagle II (PIC88)
Analyzing: 'F15SE2/DEATH.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/COCKPIT.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/HISCORE.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/RIGHT.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/MEDAL.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/PROMO.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/256RIGHT.PIC': PIC88: 0xf5: max-bits: 11, unpacked
Analyzing: 'F15SE2/TITLE16.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/WALL.PIC': PIC88: 0x0b: max-bits: 11, packed
Analyzing: 'F15SE2/LEFT.PIC': PIC88: 0x0b: max-bits: 11, packed
Things look as we expect for F15, which we are pretty familiar with at this point. Most importantly, none of the files have been mistakenly picked up as a PIC90, which is what I was most worried about. (I checked the other PIC88 titles, and they all detect correctly)
Railroad Tycoon (PIC90)
Analyzing: 'RAILS/PAGE1.PIC': PIC90: Type: f Image: 320x200 (Unknown Subtype)
Analyzing: 'RAILS/STATION.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'RAILS/PAGE0.PIC': PIC90: Type: f Image: 320x200 (Unknown Subtype)
Analyzing: 'RAILS/ELOCOS.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'RAILS/PAGE2.PIC': PIC90: Type: f Image: 320x200 (Unknown Subtype)
Analyzing: 'RAILS/CLOCOSM.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'RAILS/CSPRITES.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'RAILS/PAGE3.PIC': PIC90: Type: f Image: 320x200 (Unknown Subtype)
Analyzing: 'RAILS/PAGE7.PIC': PIC90: Type: f Image: 320x200 (Unknown Subtype)
Analyzing: 'RAILS/ESPCGA.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Things look as we expect for F15, which we are pretty familiar with at this point. We don’t see any Type 6 here, so let’s look at our other PIC90 title.
Silent Service II (PIC90)
Analyzing: 'SS2/CON12_41.PIC': PIC90: Type: 6 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/CON02_43.PIC': PIC90: Type: 6 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/MICRO.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/CON11_44.PIC': PIC90: Type: 6 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/CON01_44.PIC': PIC90: Type: 6 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/SS-ADS.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/LABS.PIC': PIC90: Type: 7 Image: 320x200 0x0b: max-bits: 11
Analyzing: 'SS2/CON05_42.PIC': PIC90: Type: 6 Image: 320x200 0x0b: max-bits: 11
Perfect! Also looks like that odd sub-type is used by RRT only (at least for now).
F-14 Fleet Defender (PIC91)
Analyzing: 'F14/JOYPIC.PIC': PIC91:
Palette: Start: 0 End 255 (Len: 770)
Image: 320x200 0x0b: max-bits: 11 (Len: 12630)
Analyzing: 'F14/SP5EX2.PIC': PIC91:
Palette: Start: 0 End 255 (Len: 770)
Image: 320x200 0x0b: max-bits: 11 (Len: 12162)
Analyzing: 'F14/PL2DY1.PIC': PIC91:
Palette: Start: 0 End 94 (Len: 288)
Image: 0x0 0x0b: max-bits: 11 (Len: 7)
Analyzing: 'F14/RIOSTR.PIC': PIC91:
Palette: Start: 0 End 94 (Len: 288)
Image: 320x200 0x0b: max-bits: 11 (Len: 14606)
Analyzing: 'F14/PL0DY1.PIC': PIC91:
Palette: Start: 0 End 255 (Len: 770)
Image: 0x0 0x0b: max-bits: 11 (Len: 7)
Analyzing: 'F14/CPFBL1.PIC': PIC91:
Palette: Start: 0 End 94 (Len: 288)
Image: 320x200 0x0b: max-bits: 11 (Len: 9018)
Analyzing: 'F14/PL5NT1.PIC': PIC91:
Palette: Start: 0 End 94 (Len: 288)
Image: 0x0 0x0b: max-bits: 11 (Len: 7)
Analyzing: 'F14/GM-LOAD.PIC': PIC91:
Palette: Start: 0 End 255 (Len: 770)
Image: 320x200 0x0b: max-bits: 11 (Len: 41458)
Analyzing: 'F14/CPFTP1.PIC': PIC91:
Palette: Start: 0 End 94 (Len: 288)
Image: 320x200 0x0b: max-bits: 11 (Len: 13181)
Analyzing: 'F14/PL0DY2.PIC': PIC91:
Palette: Start: 0 End 255 (Len: 770)
Image: 0x0 0x0b: max-bits: 11 (Len: 7)
Looks to be detecting correctly here. Interesting though is the files with 0x0 sized images. Will need to double check some of these, perhaps they are just used for the palette that’s in them.
File: PL2DY1.PIC [303 bytes]
Offset x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF Decoded Text
0000000x: 4D 30 20 01 00 5E 00 00 00 09 08 0A 22 00 00 22 M 0 · · ^ · · · · · · " · · "
0000001x: 00 00 15 00 00 15 00 00 36 10 10 30 30 32 20 20 · · · · · · · · 6 · · 0 0 2
0000002x: 20 1D 1D 1F 0C 0B 0D 00 00 31 00 21 3F 34 34 34 · · · · · · · · 1 · ! ? 4 4 4
0000003x: 29 21 0A 3F 3F 3F 3F 00 00 21 00 00 0B 00 00 32 ) ! · ? ? ? ? · · ! · · · · · 2
0000004x: 27 00 24 1C 00 1C 14 03 08 07 07 04 04 04 03 03 ' · $ · · · · · · · · · · · · ·
0000005x: 03 1E 1D 23 19 19 1E 15 15 1A 11 12 16 0F 0F 13 · · · # · · · · · · · · · · · ·
0000006x: 0C 0C 0F 09 08 0A 2C 2C 2E 25 24 26 1A 19 1B 17 · · · · · · , , . % $ & · · · ·
0000007x: 16 18 14 13 15 10 0F 11 0E 0D 0F 0C 0B 0D 0A 09 · · · · · · · · · · · · · · · ·
0000008x: 0B 09 08 0A 07 06 08 06 05 07 04 03 04 01 01 01 · · · · · · · · · · · · · · · ·
0000009x: 1A 1A 1A 11 11 11 0E 0E 0E 0B 0B 0B 07 07 07 03 · · · · · · · · · · · · · · · ·
000000Ax: 03 03 00 00 00 25 25 25 1E 1E 1E 17 17 17 13 13 · · · · · % % % · · · · · · · ·
000000Bx: 13 0B 0B 0B 08 08 08 08 0A 08 0F 0F 0F 0D 0D 0D · · · · · · · · · · · · · · · ·
000000Cx: 3F 00 00 21 00 00 3F 3F 30 3F 3D 2D 3F 3C 2A 3F ? · · ! · · ? ? 0 ? = - ? < * ?
000000Dx: 39 27 3F 37 24 3F 34 22 3F 31 1F 3F 2D 1C 3F 29 9 ' ? 7 $ ? 4 " ? 1 · ? - · ? )
000000Ex: 19 3F 24 16 3F 1F 14 3F 19 11 3F 14 0E 3F 0D 0B · ? $ · ? · · ? · · ? · · ? · ·
000000Fx: 3F 08 0A 3F 06 0C 28 00 00 19 00 00 00 0F 00 00 ? · · ? · · ( · · · · · · · · ·
0000010x: 13 00 00 17 00 00 1B 00 00 1F 00 00 22 00 00 26 · · · · · · · · · · · · " · · &
0000011x: 00 00 2A 00 00 2E 00 00 32 00 3C 00 3F 3F 00 3F · · * · · . · · 2 · < · ? ? · ?
0000012x: 3F 00 3F FF 58 30 07 00 00 00 00 00 0B FF 00 ? · ? · X 0 · · · · · · · · ·
58 30 - Block ID "X0"
0007 - Block Length
0000 - Width
0000 - Height
0B - Format identifier
FF 00 - LZW Datastream
Well that pretty much confirms that the image is actually set as 0x0. Interestingly it does appear there is a single code written to the LZW stream, which is padded out to 16 bits. The 9 bit code is for the byte FF which is likely the result of encoding EOF as a 8 bit char. (EOF has a value of -1).
Railroad Tycoon Deluxe (PIC93)
Analyzing: 'RAILSDX/TYCOON1.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/BOND1.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/DIFFSL.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/TYCOON0.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/TYCOON2.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/BOND2.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/TYCOON3.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/TYCOON7.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/TYCOON6.PIC': PIC93: Image: 640x400
Analyzing: 'RAILSDX/SPRITES.PIC': PIC93: Image: 640x400
No surprises here, this version is pretty identifiable, and we don’t know much about it yet.
I think this is a good place to wrap things up for this post. Seems the MicroProse PIC format still has a few more secrets to reveal. I had planned for the next post to be about reading and writing the newer variants, but looks like we’re not quite ready to do that just yet. So next post we will dive back into discovering and decoding these new encodings we’ve discovered.
This post is part of a series of posts surrounding my reverse engineering efforts of the PIC file format that MicroProse used with their games. Specifically F-15 Strike Eagle II (Though I plan to trace the format through other titles to see if and how it changes). To read my other posts on this topic you can use this link to my archive page for the PIC File Format which will contain all my posts to date on the subject.
Leave a reply to andreas86x Cancel reply