User:Remark/Icon2ppm.c

< User:Remark
Revision as of 22:35, 27 April 2009 by Remark (talk | contribs) (Oops.)
 // DSi icon2ppm - #dsidev
 // written by remark
 // thanks to loopy_, bLASTY
 
 // Copyright 2007,2008  Segher Boessenkool  <segher@kernel.crashing.org>
 // Licensed under the terms of the GNU GPL, version 2
 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt
 
 #include <stdio.h>
 #include <unistd.h>
 typedef unsigned long u32;
 typedef unsigned short u16;
 typedef unsigned char u8;
 
 u16 be16(const u8 *p)
 {
   return (p[0] << 8) | p[1];
 }
 u32 be32(const u8 *p)
 {
   return (p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3];
 }
 
 #define BNR_VER 0x0301
 #define FLAG_FLIPV 0x80
 #define FLAG_FLIPH 0x40
 typedef struct {
   u16 version;
   u16 crcs[4];
   u8 padding[0x16]; 
   u8 bitmap[0x200];
   u16 palette[0x10];
   u8 title_jap[0x100];
   u8 title_eng[0x100];
   u8 title_fr[0x100];
   u8 title_ger[0x100];
   u8 title_ita[0x100];
   u8 title_spa[0x100];
   u8 title_unk[0x100]; 
   u8 title_unk2[0x100];
   u8 padding2[0x800];
   u8 bitmaps[8][0x200];
   u16 palettes[8][0x10];
   u16 sequence[0x40];
 } bannerstruct;
 
 int flength(FILE *f)
 {
   int pos,end;
   pos = ftell (f);
   fseek (f, 0, SEEK_END);
   end = ftell (f);
   fseek (f, pos, SEEK_SET);
   return end;
 }
 
 void do_bitmap(u8* bitmap, u16* palette, char* fname)
 {
   FILE *fp = fopen(fname, "wb");
   if (fp == NULL)
   {
     fprintf(stderr, "file cannot be opened: %s\n", fname);
     exit(1);
   }
   fprintf(fp, "P6 %d %d 255\n", 32, 32);
   
   // fix 8x8 tiling
   u8 tilebuf[0x204];
   int x,y,z;
   for(x=0; x<4; x++)
   {
     for(y=0; y<8; y++)
     {
       for(z=0; z<8; z++)
       {
         memcpy(tilebuf+(x*128)+(16*y)+(4*z),
           bitmap+(x*128)+(32*z)+(4*y), 4);
       }
     }
   }
   
   // convert to rgb888
   int i,j;
   u8 pixeldata[32*32][3];
   for(i=0; i<0x200; i++)
   {
     u8 off = tilebuf[i];
     int offs[2];
     offs[0] = off&0x0F;
     offs[1] = (off&0xF0)>>4;
     
     u16 colors[2];
     colors[0] = *(palette+offs[0]);
     colors[1] = *(palette+offs[1]);
     
     for(j=0; j<2; j++)
     {
       u8 r = (colors[j]      ) & 0x1f;
       u8 g = (colors[j] >>  5) & 0x1f;
       u8 b = (colors[j] >> 10) & 0x1f;
       pixeldata[i*2+j][0] = (r << 3);
       pixeldata[i*2+j][1] = (g << 3);
       pixeldata[i*2+j][2] = (b << 3);
     }
   }
   
   if(fwrite(pixeldata, sizeof(pixeldata), 1, fp)Ā != 1)
   {
     fprintf(stderr, "writing output-file failed\n");
     exit(1);
   }
   fclose(fp);
 }
 
 int main(int argc, char* argv[])
 {
   if(argcĀ != 2)
   {
     fprintf(stderr, "usage: %s <icon.bin>\n", argv[0]);
     exit(0);
   }
   
   FILE* fp = fopen(argv[1], "rb");
   if(fp == NULL)
   {
     fprintf(stderr, "input file not found\n");
     exit(1);
   }
   
   int f_len = flength(fp);
   char* f_buf = malloc(f_len);
   if(f_buf == NULL)
   {
     fprintf(stderr, "not enough memory\n");
     exit(1);
   }
   if(fread(f_buf, f_len, 1, fp)Ā != 1)
   {
     fprintf(stderr, "file read failure\n");
     exit(1);
   }
   
   char dirname[256];
   snprintf(dirname, sizeof(dirname), "%s.out", argv[1]);
   mkdir(dirname, 0777);
   chdir(dirname);
   
   bannerstruct* bnr = (bannerstruct*) f_buf;
   // check magic
   if(be16((u8*)&bnr->version)Ā != BNR_VER)
   {
     fprintf(stderr, "invalid banner icon (magic mismatch)\n");
     exit(1);
   }
   
   // extract default bitmap
   do_bitmap(bnr->bitmap, bnr->palette, "default.ppm");
   
   // loop through all sequences
   u16* pseq = bnr->sequence;
   u16 seq, i;
   for(i=0; (seq = be16((u8*) pseq+i))Ā != 0; i++)
   {
     // masking out 
     int bid = (seq&0x7);
     int pid = (seq&0x38)>>3;
     
     // write to logfile
     char fname[256];
     snprintf(fname, sizeof(fname), "seq#%d.txt", i);
     
     FILE* flog = fopen(fname, "w+");
     if(flog == NULL)
     {
       fprintf(stderr, "log-file couldn't be created\n");
       exit(1);
     }
     
     fprintf(flog, "durationĀ : %d frames\n", (seq&0xFF00)>>8);
     fprintf(flog, "bitmap   : #%d\n", bid);
     fprintf(flog, "palette  : #%d\n", pid);
     fclose(flog);
     
     // todo: flipz!
     if((seq & FLAG_FLIPV) = FLAG_FLIPV)
       fprintf(stderr, "warning: vertical flip ignored on sequence #%d\n", i);
     if((seq & FLAG_FLIPH) = FLAG_FLIPH)
       fprintf(stderr, "warning: horizontal flip ignored on sequence #%d\n", i);
     
     // change extension to .ppm
     char* dot_pos = strchr(fname, '.');
     strcpy(dot_pos, ".ppm");
     
     // extract bitmap to file
     do_bitmap(bnr->bitmaps[bid], bnr->palettes[pid], fname);
   }
   
   fclose(fp);
   free(f_buf);
   
   return 0;
 }