Ouch my eye!

Do not look at LASER with remaining eye!


Show me the money

Okay well maybe not the money, but the palette. As we left off in my last post, we have been looking for the palette to be able to correctly render the 256 colour images from the game. While we did find a chunk of it, a few small bits remained elusive. In one of our Email exchanges about our mutual progress on various parts of reverse engineering F15-SE2 Neuviemeporte suggested I look into the slideshow “demo” for the F-15 Desert Storm Scenario pack for the palette. It’s a great idea, and this post is in response to that.

Down the rabbit hole we go…

So what is F15STORM? F15STORM is an executable file that was distributed by MicroProse that was a slideshow “demo” for the F-15 Desert Storm Scenario Pack which adds additional missions onto F-15 Strike Eagle II. The slideshow shows a number of screen captures form the game. From The quote above, looks like the base program is something called “MPS Show” which must be an in-house developed slideshow program, and it appears to contain 30 images. One challenge is that the entire demo, including images, is contained in a single EXE file. As a result getting at the images, and palettes, is going to take a little reverse-engineering. So in the words of the illustrious Dave Jones of EEVblog, “Don’t turn it on… take it apart!


First steps

-rw-rw-r--  557147 18 May  1990 F15STORM.EXE
Info for 'F15STORM.EXE' File is 557147 bytes
Signature: 'MZ' - MSDOS Executable
EXE reported size: 12272 bytes [2ff0]
IP: 00b8
checksum: 0000

First thing to do is take a look in the hex editor to see if this is a compressed file, and if we can see any data that would suggest being the images.

Well this is a good sign that the file isn’t compressed. The top part seems to be just the actual executable, this is then followed by a long block of 0x00 before finally being broken at around 61A0 well past the file size as stated by the EXE header. Not sure the purpose of all the null data, but it appears that some sort of data file has been appended onto the end. So perhaps the null data is required for the attached executable to be able to find it? not sure, but it doesn’t really matter, we can see from the hex view the data we’re interested in looks start somewhere after 61A0.

From what we can see it looks like we have some text, and what appears to be palette data. Continuing to scan we see this pattern repeating on a regular basis, but far too soon to contain the image data. These appear to be informational records about the slides themselves.

Looks like the first bit of text is perhaps the filename, followed by a description. Going from filename to filename as landmarks, the blocks all appear to be 835 bytes long. Plenty large to hold a full 256 colour palette so this is really looking good for being able to extract a palette. After all these informational records we see what looks to be the start of some image data at around C380 (this is around where I would have expected the next info record to be).

The image data doesn’t appear to be in the PIC format we’ve been reverse-engineering. Perhaps it’s raw uncompressed image data. Though it doesn’t really matter, if the palette data we’re looking for is contained in the info records. Next we need to establish the actual extent of the records, and see if we can determine where the palette sits in all of it.


Finding the record extents

Going back to the first non-zero byte in the data I noticed something.

The very first byte is 0x1E or 30 in decimal, and we have 30 slides, this looks like it could be the number of slides in the show. Then I noticed something peculiar before each of the strings before the text.

The strings appear to be length prefixed. Looking at the other records seems to confirm this. This suggests that MPS Show was written in Pascal though I did not see any compiler, runtime, or linker information in any of the data segments, so it must have been scrubbed out. This information isn’t likely to help us much here, only that any strings will be length prefixed. Next looking at the beginning of the following record we see.

This indicates to me that the record boundary happens between the length prefix for the filename string, and the byte before. As that allows the record count byte to sit outside the record. That means the first record spans from 61A9 to 64EB for a total of 835 bytes, which we had previously established as the length. Now lets calculate the total length for the records 835 * 30 = 25,050 Bytes Add that to the start of our first record 0x61A9 + 25, 050 = 0xC383 which should be the start of our image data. Looking at the data we can see that does indeed appear to be the case.


Establishing the record layout.

We’ve already established that the strings are Pascal style strings with a length prefix. For the time being we will assume that the first strings allotted space ends just before the 2nd. That means that the first string takes up 10 bytes, including the length. Now looking back at the record we can see that the first non-zero byte after the text occurs 26 bytes later. For now we will assume that this is where the 2nd string ends.

Then we can see the next 2 bytes form 0xC383, which if you remember this is where we calculated the image data to begin. The two bytes after that are 0x0000, and the fact that this file is way over 64K in size, I’m going to assume that this next value is the image offset, and is stored as a 32bit value forming 0x0000c383

This is a pretty good start, and with that we can read in the records, and make sure that what we have is good so far. This gives us a record that looks like the following. As the data is not 32-bit aligned, the record will need to be PACKED the method for declaring that is compiler, and even version dependant. I’m showing what needs to be done for the version of GCC I am using, and may need to be different for you (highlighted). Also as we are ending the record with a variable length array, so that we can access those bytes if we want. We will need to be sure to not use sizeof(info_t) when we use fread(), instead we want to tell fread() that our length is 835 bytes. Also, while GCC does have a non-portable way of specifying a Pascal type string, I’m not willing to go that far with the non-portable bits of code here, so instead I’m going to do it manually. (there is no portable way around packing, but there is a portable way around a Pascal string)

#pragma pack(push,1)
typedef struct {
    uint8_t name_len;
    char    name[9];
    uint8_t desc_len;
    char    desc[25];
    uint32_t img_offset;
    uint8_t unknown[];
} info_t;
#pragma pack(pop)

So to read in the records and print them we can do something like the following. Note the careful handling of the strings in the printf() to ensure we only print as many characters as the string says it contains. (ignore the lack of any other error checking, this is just rough test code)

    FILE *fp = fopen("F15STORM.EXE", "rb");
    fseek(fp, 0x61a8, SEEK_SET); // seek to the start of data we found

    uint num_slides = fgetc(fp); // get the number of slides
    printf("Number of slides: %d\n", num_slides);

    info_t *tinfo = (info_t *)calloc(1,835);

    for(uint i=0; i<num_slides; i++) {
        fread((void *)&tinfo, 835, 1, fp);

        printf("%2d: %9.*s - %-25.*s ofs:%06x\n", i, 
            tinfo[i].name_len, tinfo[i].name, 
            tinfo[i].desc_len, tinfo[i].desc, 
            tinfo[i].img_offset);
    }

And when we run it we get the following:

Number of slides: 30
 0:   MPSLABS - MPS Labs                  ofs:00c383
 1:     MENU1 - Menu 1                    ofs:00da7d
 2:     MENU2 - Menu 2                    ofs:01598f
 3:     MENU3 - Menu 3                    ofs:01d5e5
 4:  CARRIERN - carrier nice              ofs:025cd9
 5:  REARCARR - rear carrier view         ofs:026035
 6:   TAKEOFF - Take off                  ofs:0267ad
 7:  CLIMBOUT - climb out view            ofs:02af09
 8:  LEFTVIEW - left view                 ofs:02b325
 9:  PIOLTBAC - piolt back                ofs:02e2c5
10:  RIGHTVIE - right view                ofs:03195b
11:  PLANESHO - plane shoy down           ofs:03454f
12:  CLIMBVIE - climb view                ofs:03959f
13:  CLIMBLOC - climb lock on             ofs:039aaf
14:  BETTERCL - better climb lock on      ofs:03e9db
15:  PLANECLI - plane climb explosion     ofs:04361f
16:  15CLIMBI - 15 climbing outside view  ofs:0483d7
17:  BIOWEACP - bio wea cp                ofs:048999
18:     BIOCP - bio cp                    ofs:04e0ef
19:  BIOCLOSE - bio close cp              ofs:053a41
20:  EXPLOSIO - explosion                 ofs:0590f7
21:  REAROUTS - Rear outside f view       ofs:0593ef
22:  PETREFCP - pet ref cp                ofs:0599f9
23:  GREATREF - great ref close mis loc   ofs:05f68d
24:  GREATCLO - great closer lock on      ofs:064985
25:  AIRBASEV - air base view             ofs:069e07
26:  NICEAIRB - nice air base view        ofs:06ff15
27:  PILOTVIE - pilot view                ofs:07528d
28:  CARRIERL - carrier landing           ofs:0792df
29:  BEBRIEFI - bebriefing                ofs:07deb5
file position at 00c383

Well that worked swimmingly, all the data appears to have read in correctly, and we ended in the right place at the start of the image data. And with the length of the description on slide 16, I think our initial length guess was correct. With the data we can now calculate the image length, by subtracting the start of the first image from the start of the second. Then we can look to see if this length value is encoded anywhere in the first record. 0xDA7D - 0xC383 = 0x16FA.

Once again we can see it in the record, so we can assume that this field is the image data length, and I’m going to assume this is a 32 bit value again. Another thing we can establish here is that the images must be compressed, otherwise for 320×200 they lengths would need to all be 64,000 (0xFA00). While we can actually see oxFA00 in the capture here, it does not show up again in the next slides data. Now curiously the image length does not immediately follow the image offset. We have another 16 bits of data 0x0013 (19 decimal) in there, and scanning through the records, all of them have this value at that location. Perhaps this pertains to the graphics mode to display in (mode13h for 256 colours). Or perhaps this is defining how the image data is encoded. I think we can proceed without this knowledge for now, as it remains constant, we just need to account for its presence. I’ll call it “mode” in our record. Let’s add the new fields to the record, and print out the values as well. As a sanity check I’ll also print the calculated image data length, by subtracting the image offset, from the image offset of the next image.

Number of slides: 30
 0:   MPSLABS - MPS Labs                  ofs:00c383 len:5882   mode:13h [calc len: 5882  ]
 1:     MENU1 - Menu 1                    ofs:00da7d len:201359122 mode:13h [calc len: 32530 ]
 2:     MENU2 - Menu 2                    ofs:01598f len:31830  mode:13h [calc len: 31830 ]
 3:     MENU3 - Menu 3                    ofs:01d5e5 len:34548  mode:13h [calc len: 34548 ]
 4:  CARRIERN - carrier nice              ofs:025cd9 len:860    mode:13h [calc len: 860   ]
 5:  REARCARR - rear carrier view         ofs:026035 len:151193464 mode:13h [calc len: 1912  ]
 6:   TAKEOFF - Take off                  ofs:0267ad len:235816796 mode:13h [calc len: 18268 ]
 7:  CLIMBOUT - climb out view            ofs:02af09 len:1052   mode:13h [calc len: 1052  ]
 8:  LEFTVIEW - left view                 ofs:02b325 len:12192  mode:13h [calc len: 12192 ]
 9:  PIOLTBAC - piolt back                ofs:02e2c5 len:13974  mode:13h [calc len: 13974 ]
10:  RIGHTVIE - right view                ofs:03195b len:11252  mode:13h [calc len: 11252 ]
11:  PLANESHO - plane shoy down           ofs:03454f len:20560  mode:13h [calc len: 20560 ]
12:  CLIMBVIE - climb view                ofs:03959f len:1296   mode:13h [calc len: 1296  ]
13:  CLIMBLOC - climb lock on             ofs:039aaf len:20268  mode:13h [calc len: 20268 ]
14:  BETTERCL - better climb lock on      ofs:03e9db len:19524  mode:13h [calc len: 19524 ]
15:  PLANECLI - plane climb explosion     ofs:04361f len:19896  mode:13h [calc len: 19896 ]
16:  15CLIMBI - 15 climbing outside view  ofs:0483d7 len:1474   mode:13h [calc len: 1474  ]
17:  BIOWEACP - bio wea cp                ofs:048999 len:22358  mode:13h [calc len: 22358 ]
18:     BIOCP - bio cp                    ofs:04e0ef len:22866  mode:13h [calc len: 22866 ]
19:  BIOCLOSE - bio close cp              ofs:053a41 len:22198  mode:13h [calc len: 22198 ]
20:  EXPLOSIO - explosion                 ofs:0590f7 len:760    mode:13h [calc len: 760   ]
21:  REAROUTS - Rear outside f view       ofs:0593ef len:1546   mode:13h [calc len: 1546  ]
22:  PETREFCP - pet ref cp                ofs:0599f9 len:23700  mode:13h [calc len: 23700 ]
23:  GREATREF - great ref close mis loc   ofs:05f68d len:21240  mode:13h [calc len: 21240 ]
24:  GREATCLO - great closer lock on      ofs:064985 len:21634  mode:13h [calc len: 21634 ]
25:  AIRBASEV - air base view             ofs:069e07 len:24846  mode:13h [calc len: 24846 ]
26:  NICEAIRB - nice air base view        ofs:06ff15 len:184570744 mode:13h [calc len: 21368 ]
27:  PILOTVIE - pilot view                ofs:07528d len:16466  mode:13h [calc len: 16466 ]
28:  CARRIERL - carrier landing           ofs:0792df len:19414  mode:13h [calc len: 19414 ]
29:  BEBRIEFI - bebriefing                ofs:07deb5 len:41382  mode:13h [calc len: 41382 ]
end of info data at 00c383

Well that’s certainly not right, let’s try again, with the length field set to 16 bits.

Number of slides: 30
 0:   MPSLABS - MPS Labs                  ofs:00c383 len:5882   mode:13h [calc len: 5882  ]
 1:     MENU1 - Menu 1                    ofs:00da7d len:32530  mode:13h [calc len: 32530 ]
 2:     MENU2 - Menu 2                    ofs:01598f len:31830  mode:13h [calc len: 31830 ]
 3:     MENU3 - Menu 3                    ofs:01d5e5 len:34548  mode:13h [calc len: 34548 ]
 4:  CARRIERN - carrier nice              ofs:025cd9 len:860    mode:13h [calc len: 860   ]
 5:  REARCARR - rear carrier view         ofs:026035 len:1912   mode:13h [calc len: 1912  ]
 6:   TAKEOFF - Take off                  ofs:0267ad len:18268  mode:13h [calc len: 18268 ]
 7:  CLIMBOUT - climb out view            ofs:02af09 len:1052   mode:13h [calc len: 1052  ]
 8:  LEFTVIEW - left view                 ofs:02b325 len:12192  mode:13h [calc len: 12192 ]
 9:  PIOLTBAC - piolt back                ofs:02e2c5 len:13974  mode:13h [calc len: 13974 ]
10:  RIGHTVIE - right view                ofs:03195b len:11252  mode:13h [calc len: 11252 ]
11:  PLANESHO - plane shoy down           ofs:03454f len:20560  mode:13h [calc len: 20560 ]
12:  CLIMBVIE - climb view                ofs:03959f len:1296   mode:13h [calc len: 1296  ]
13:  CLIMBLOC - climb lock on             ofs:039aaf len:20268  mode:13h [calc len: 20268 ]
14:  BETTERCL - better climb lock on      ofs:03e9db len:19524  mode:13h [calc len: 19524 ]
15:  PLANECLI - plane climb explosion     ofs:04361f len:19896  mode:13h [calc len: 19896 ]
16:  15CLIMBI - 15 climbing outside view  ofs:0483d7 len:1474   mode:13h [calc len: 1474  ]
17:  BIOWEACP - bio wea cp                ofs:048999 len:22358  mode:13h [calc len: 22358 ]
18:     BIOCP - bio cp                    ofs:04e0ef len:22866  mode:13h [calc len: 22866 ]
19:  BIOCLOSE - bio close cp              ofs:053a41 len:22198  mode:13h [calc len: 22198 ]
20:  EXPLOSIO - explosion                 ofs:0590f7 len:760    mode:13h [calc len: 760   ]
21:  REAROUTS - Rear outside f view       ofs:0593ef len:1546   mode:13h [calc len: 1546  ]
22:  PETREFCP - pet ref cp                ofs:0599f9 len:23700  mode:13h [calc len: 23700 ]
23:  GREATREF - great ref close mis loc   ofs:05f68d len:21240  mode:13h [calc len: 21240 ]
24:  GREATCLO - great closer lock on      ofs:064985 len:21634  mode:13h [calc len: 21634 ]
25:  AIRBASEV - air base view             ofs:069e07 len:24846  mode:13h [calc len: 24846 ]
26:  NICEAIRB - nice air base view        ofs:06ff15 len:21368  mode:13h [calc len: 21368 ]
27:  PILOTVIE - pilot view                ofs:07528d len:16466  mode:13h [calc len: 16466 ]
28:  CARRIERL - carrier landing           ofs:0792df len:19414  mode:13h [calc len: 19414 ]
29:  BEBRIEFI - bebriefing                ofs:07deb5 len:41382  mode:13h [calc len: 41382 ]
end of info data at 00c383

Much better, so it looks like the length field is actually only 16 bits. At this point we’re getting really close to where the palette data looks to begin. If these images are raw screen captures, then the palette should be “normal” meaning that the first 16 entries should be the usual CGA/EGA values. Let’s look at what those values should be and then see if we can line that up with what we see in the datastream.

  {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a},
  {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
  {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f},
  {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},

And sure enough we can see that the first 16 entries do appear.

That leaves us with 32 bits of unknown data after the length and before the palette. Lets store those 32bits as a single value and print the hex to see what is going on with them.

Number of slides: 30
 0:   MPSLABS - MPS Labs                  ofs:00c383 len:5882   mode:13h [00000000]
 1:     MENU1 - Menu 1                    ofs:00da7d len:32530  mode:13h [00000c00]
 2:     MENU2 - Menu 2                    ofs:01598f len:31830  mode:13h [00000000]
 3:     MENU3 - Menu 3                    ofs:01d5e5 len:34548  mode:13h [00000000]
 4:  CARRIERN - carrier nice              ofs:025cd9 len:860    mode:13h [00000000]
 5:  REARCARR - rear carrier view         ofs:026035 len:1912   mode:13h [0b0b0903]
 6:   TAKEOFF - Take off                  ofs:0267ad len:18268  mode:13h [0e0e0e0e]
 7:  CLIMBOUT - climb out view            ofs:02af09 len:1052   mode:13h [00000000]
 8:  LEFTVIEW - left view                 ofs:02b325 len:12192  mode:13h [00000000]
 9:  PIOLTBAC - piolt back                ofs:02e2c5 len:13974  mode:13h [00000000]
10:  RIGHTVIE - right view                ofs:03195b len:11252  mode:13h [00000000]
11:  PLANESHO - plane shoy down           ofs:03454f len:20560  mode:13h [00000000]
12:  CLIMBVIE - climb view                ofs:03959f len:1296   mode:13h [00000000]
13:  CLIMBLOC - climb lock on             ofs:039aaf len:20268  mode:13h [000d0000]
14:  BETTERCL - better climb lock on      ofs:03e9db len:19524  mode:13h [00000000]
15:  PLANECLI - plane climb explosion     ofs:04361f len:19896  mode:13h [00000000]
16:  15CLIMBI - 15 climbing outside view  ofs:0483d7 len:1474   mode:13h [00000000]
17:  BIOWEACP - bio wea cp                ofs:048999 len:22358  mode:13h [00000000]
18:     BIOCP - bio cp                    ofs:04e0ef len:22866  mode:13h [00000000]
19:  BIOCLOSE - bio close cp              ofs:053a41 len:22198  mode:13h [00000000]
20:  EXPLOSIO - explosion                 ofs:0590f7 len:760    mode:13h [00000000]
21:  REAROUTS - Rear outside f view       ofs:0593ef len:1546   mode:13h [00000000]
22:  PETREFCP - pet ref cp                ofs:0599f9 len:23700  mode:13h [00000000]
23:  GREATREF - great ref close mis loc   ofs:05f68d len:21240  mode:13h [00000000]
24:  GREATCLO - great closer lock on      ofs:064985 len:21634  mode:13h [00000000]
25:  AIRBASEV - air base view             ofs:069e07 len:24846  mode:13h [00000000]
26:  NICEAIRB - nice air base view        ofs:06ff15 len:21368  mode:13h [0b0b0b00]
27:  PILOTVIE - pilot view                ofs:07528d len:16466  mode:13h [00000000]
28:  CARRIERL - carrier landing           ofs:0792df len:19414  mode:13h [00000000]
29:  BEBRIEFI - bebriefing                ofs:07deb5 len:41382  mode:13h [00000000]
end of info data at 00c383

Seems to be predominantly 0x00000000, and most of the ones that are not seem to almost look like palette data. I wonder if this isn’t just some uninitialized data. Hopefully we can ignore this for now. I think next is to add in an array of 256 RGB triplets to our structure, after the unknown32 bits. And dump them out as PAL files.

After scanning through all 30 generated palettes, the data all looks to be reasonable. I’m thinking we want to dump the images and see if we can render them, to validate the palettes. I think we have enough of the structure at this point that we can ignore the 19 bytes that remain after the palette data. So let’s add some code to Extract the palette, and the image data as-is. Then we can take a closer look at the image data and see if we can figure it out. If all these images expand out to 320×200 (64,000 bytes), some of those images have very impressive compression ratios. “CARRIERN” has a compressed size of only 860 bytes, “EXPLOSIO” is even smaller at 760 bytes!


The image data

After extracting all the data, we are left with 30 PAL files each 768 bytes containing what should be the image palette data. We also have 30 MPS files containing the 30 compressed images. Now we need to examine the image data to see if we can determine the encoding.

The first thing I noticed is that the data appears to follow a very regular pattern. Despite noticing the pattern, the obvious fact that this is the most basic form of RLE encoding eluded me for longer than I care to admit. With that said, this is indeed very basic RLE encoding, where every entry is 16 bits, the first 8 bits are the count, and the 2nd 8 bits are the value. So all that’s left is to code it up, and render an image.

    uint src_pos = 0;
    uint dst_pos = 0;
    while(src_pos < src_len) {
        uint8_t count = src[src_pos++];
        uint8_t pix = src[src_pos++];

        for(uint i=0; i<count; i++) {
            dst[dst_pos++] = pix;
        }
    }

And that is pretty much it. Lets decompress the image data, and render it using the associated extracted palette.

MPSLABS – Pulled from MPS Show data

Looks like we have it. Let’s take a look at some of the other ones. I’m particularily intersted in the images that were very small once compressed, here they are.

CARRIERN – Pulled from MPS Show data
EXPLOSIO – Pulled from MPS Show data

That is amazing 760 bytes expanding to 64,000, if only we could get that kind of compression with everything. Finally the candidate image for where we will pull the pallete from for our PIC renderings

BETTERCL – Pulled from MPS Show data

And that’s pretty much it. I may come back to this to try and figure out the other bits, and possibly write an encoder/repacker so that we can make our own slideshows, but for now we have more than we need to wrap up on the PIC rendering.


Now that we have a palette, lets see how our PIC files render with it.

Everything looks as it should now, though I’ll be honest, I liked the olive green on the screens better, it gave it more of a phosphor feel, not that you ever see it in game.

There I fixed it 😉

This is the final of the backlogged posts on my efforts with the PIC file format. I largely paused my efforts on the decoding effort to document everything I had done to this point, and in some cases recreating the steps I had taken in order to generate the imagery at some of the mid-steps, but overall is pretty accurate to my progress. Next steps at this point will be to write a PIC88 encoder, and that is where I think we will pick up next time.

By Thread



7 responses to “Show me the money”

  1. Wow, about 5 times a year, each year, I have searched for info on the microprose .PIC format of this era, without luck. And suddenly, here you are! Absolutely fantastic!! On the behalf of all MicroProse friends, I beg you – please make this happen! I have been for a long time trying to find some way to improve the art assets of the 80s/early 90s era MPS sims. I am currently working on Fleet Defender upgrades (https://youtu.be/tiHuEP_2HtY?si=Rr5Oz-RVUUjZUSjC), and have been able to modify others in the audio department, other quality improvements, etc. Your posts here have been super exciting reads, and I cannot wait for more! Thanks for doing this CanadianAvenger!!

    1. Glad you’re enjoying it, and that you might be able to make use of my efforts. Had to take a look as I don’t have Fleet Defender, but based on its release date I’m going to guess you’re dealing with the PIC91 variant which is already pretty well documented (See the darklands.txt file mentioned in one of my first posts). Having said that I will be delving into the newer variants very soon. For now I’m concentrating on the PIC88 variant, which really serves as the core for all the variants that come after. Stay tuned 😉

      1. Indeed, same as the darklands iirc! In fact, Joel McIntyre did make a decoder/encoder for that specific format, which I use to work with Fleet Defender. Luckily most assets are in the accessible PCX format, especially textures and such. Anyhow, super excited for this development! I hope too that we are able sometime to change the art in Red Storm Rising to that of the amiga version. Those assets seems to be integrated into the executables. 🙂

      2. Glad to hear you’re enjoying the ride. I am aware of Joel’s code, and some other code out there as well (most seem to point back to Joel), but have purposely not looked at any of it yet. I wanted to figure this out as much as I could on my own, without the influence of other code. I may in a future post look at some of the code that is out there.

        The code I’m producing may, or may not apply to other platforms. I’m focused on the PC/DOS based games, though would not be surprised to learn they used the format on other platforms as well.

        If the images are integrated into the executable that will be more work, and would need to be done on a program by program basis, unless it’s a mechanism like they did with the MPS Show demo here, then a more generalized mechanism may be possible.

      3. That is a good approach 🙂

  2. There’s another Microprose / Sid Meier game called Covert Action using PIC (and even PAN for animations).

    Here’s a repository with PIC decoder and some modding tool: https://github.com/jarikomppa/covert_action

    1. Thanks for the tip, we actually cover off on Covert Action, and many other titles in this later post. And discuss, and fully decode the variant with it in this post. The format used with Covert Action is a variation on the original format we’ve been dealing with at this stage in my series. In reality only the header is different, the rest of the encoding is exactly the same so I will be able to decode and encode it with what I’ve already created.

Leave a comment