Decoding the Reunion .PIC file format. Thu Aug 9 14:41:52 CEST 2007 The files all start with SpidyGfx@. They vary widely in size, so they're compressed somehow. Since this is old-school, RLE is probable. In the INTRO dir, there are PRESENTS.PIC and GAMEBY.PIC. When the game runs, it says "PRESENTS" and "GAME BY" in big fancy letters. We take a screenshot of this. These files happen to be very small compared to the others, and they're filled with 00 FF 00 FF 00 FF (presents) and 01 FF 01 FF 01 FF (gameby) at beginning and end, with some squiggles in the middle. Since the gameby/presents titles are on a black background, they probably a bit (we don't know how much) of filler on the sides. Zooming in on the screenshots, on top of the P there is a serif that goes 20-38-20 in hex colour values. The first thing after the FF 00 FF 00 part in the file is 1E 1B 1E, and then some more FF00. Then there is a string of 1F 1E 1C 1D 1E 1F. This happens to correspond with six pixels on the same line on top of the last S in presents. The bytes between these little landmarks are FF 00 FF 00 DA 00. There are 304 black pixels between them. presumably FF is a count and 00 is the colour (black or transparent). FF+FF+DA is 728. Since 1E 1B 1E appears as three bytes, there is probably some value for when it's counted as run. But it's not simply high bit set. In the start, there are 5 FF00s followed by a C500, repeated over and over. This is perhaps the full line length (which might be 640). Before the P serif, there are 156 pixels, and the pixels are FF00 CF00. So we have/hope that 5*FF + C5 = 640, and FF+CF = 156. CF-C5 is 10, so 5*FF + C5 = 640 FF + C5 + 10 = 156 FF=123.5 Crap. The image width is probably not 640 then. We'll try to find some smaller intervals. Like between the P and R. Hey now, there's suddenly a C2 popping up in the row of 1[0-F] bytes. And it corresponds to a 2 byte stretch of the same value. (FF-C0)*4 + (C5-C0) = 320. Hehey, now we're getting somewhere. 320d is 140h. In the start of this particular file, there's 40 01. The next bytes are C8 00. So 320x200. We write an app to try this out. ------- #include unsigned char* buf; unsigned char tmp[100]; int w, h; int pos; int bytepos; int main() { int count, val, i; bytepos=0; read(0, tmp, 8); bytepos+=8; if(strncmp(tmp, "SpidyGfx", 8) != 0) { fprintf(stderr, "Bad header\n"); return 1; } if(read(0, tmp, 4)!=4) { fprintf(stderr, "Bad read\n"); return 2; } bytepos+=4; w=tmp[0]+tmp[1]*256; h=tmp[2]+tmp[3]*256; fprintf(stderr, "Dimensions: %d x %d\n", w, h); buf=calloc(w*h,1); pos=0; while(pos unsigned char* buf; unsigned char tmp[100]; unsigned long int pal[256]; int w, h; int pos; int bytepos; int main() { int count, val, i; bytepos=0; read(0, tmp, 8); bytepos+=8; if(strncmp(tmp, "SpidyGfx", 8) != 0) { fprintf(stderr, "Bad header\n"); return 1; } if(read(0, tmp, 4)!=4) { fprintf(stderr, "Bad read\n"); return 2; } bytepos+=4; w=tmp[0]+tmp[1]*256; h=tmp[2]+tmp[3]*256; fprintf(stderr, "Dimensions: %d x %d\n", w, h); buf=calloc(w*h,1); pos=0; while(pos>16)&0xFF; tmp[1] = (pal[buf[pos]]>> 8)&0xFF; tmp[2] = (pal[buf[pos]]>> 0)&0xFF; i=write(1, tmp, 3); if(i!=3) { perror("Writing buffer"); return 6; } pos++; } return 0; } ------------------------------ Wooo, it works great! That was easy. Thu Aug 9 16:20:38 CEST 2007