
/*
 * DECODE IFF formatted files    V1.00
 *
 *	COMPILE W/ASTARTUP.OBJ and MY.LIB
 *
 * iffdump [-vV] file
 *
 * -v    :  display a little more information (only for forms and types
 *          the program knows about)
 * -V    :  display additional hex dump of all sections
 *
 *
 * NOTE:  The '-v' flag could use *a lot* of expansion... Since I haven't
 *        got the latest IFF documentation.
 *
 *
 * NOTE:  This program does almost no format checking (e.g. PROP's only
 *        within LIST's, etc...), it is meant to display the format of
 *        valid IFF files.
 */

#include "iffdump.h"
#include <graphics/view.h>
#include "stdio.h"
#include "functions.h"

#define MODE_V1   0x01
#define MODE_V2   0x02

extern char *tabstr(), *ltos();

union {
   X_ANHD anhd;
   X_BMHD bmhd;
   X_CMAP cmap[64];
   X_GRAB grab;
   X_DEST dest;
   X_SPRT sprt;
   X_CAMG camg;
   X_CRNG crng;
} U;

int Modes;

main(ac, av)
char *av[];
{
   int i, j;
   char *str;
   FILE *fi;
   long endpos;

   for (j = 0, i = 1; i < ac; ++i) {
      str = av[i];
      if (*str == '-') {
         while (*++str) {
            switch(*str) {
            case 'v':
               Modes |= MODE_V1;
               break;
            case 'V':
               Modes |= MODE_V2;
               break;
            default:
               printf ("'%lc' bad option\n", *str);
            }
         }
      } else {
         if (j) {
            puts("May specify only one file");
            exit(1);
         }
         j = i;
      }
   }
   if (j == 0) {
      puts ("IFFDUMP [-vV] file");
      puts ("(c)1986 Matthew Dillon.  Public Domain V1.00");
      puts ("");
      puts ("-v   show detail on things the prog. knows about");
      puts ("-V   show hex dump");
      exit(1);
   }
   fi = fopen(av[j],"r");
   if (fi == NULL) {
      puts ("could not open file");
      exit(1L);
   }
   fseek(fi, 0L, 2);
   endpos = ftell(fi);
   fseek(fi, 0L, 0);
#if 0
printf("file end: %ld\n",endpos);
#endif
   iffdecode(fi, 0L, endpos);
   fclose(fi);
}


iffdecode(fi, tab, endpos)
FILE *fi;
long tab;
long endpos;
{
   long chunk[2];
   long curpos, bytes, curend;
   long data;
   char ok;
   char count = 0;

#if 0
printf("call iffdecode: %ld %ld\n",tab,endpos);
#endif
   for (;;) {
      curpos = ftell(fi);
#if 0
printf("curpos: %ld\n",curpos);
#endif
      if (curpos == endpos)
         return(1);
      if (count++ && tab == 0) {
         puts ("Warning: Garbage after IFF-EOF");
         return (0);
      }
      if (curpos + 8 > endpos) {
         puts ("Error: Premature End Of File in header");
         return(0);
      }
      fread(chunk,1,8,fi);
      curpos += 8;
      bytes = chunk[1];
      curend = curpos + bytes;
      printf ("%sCHUNK %s (%8ld)", tabstr(tab), ltos(chunk[0]), bytes);
      if (curend > endpos) {
         puts ("\nError: Premature End Of File within chunk");
         return(0);
      }
#if 0
printf("chunk: %lx\n",chunk[0]);
#endif
      ok = 0;
      switch(chunk[0]) {
      case IFF_FILLER:
         printf ("A filler chunk\n");
         if (Modes & MODE_V2)
            hexdump(fi, curpos, bytes, tab);
         break;
      case IFF_FORM:
      case IFF_LIST:
      case IFF_CAT:
      case IFF_PROP:
         fread(&data,1, 4,fi);
         curpos += 4;
         bytes  -= 4;
         printf ("TYPE %s\n", ltos(data));
         iffdecode(fi, tab + 4, curend);
         break;
      default:
         ok = 1;
         break;
      }
      if (ok) {
         puts ("");
         if (Modes & MODE_V1)
            decode_sub(fi, tab, chunk[0], bytes);
         if (Modes & MODE_V2)
            hexdump(fi, curpos, bytes, tab);
      }
      if (curend & 1) {
         printf ("%s(Filler Byte)\n", tabstr(tab));
         ++curend;
      }
      fseek(fi, curend, 0);
   }
}



decode_sub(fi, tab, name, bytes)
FILE *fi;
long tab,bytes,name;
{
   int i, j;

   tab += 4;
   switch (name) {
   case ILBM_ANHD:
      cs((long)sizeof(U.anhd), bytes);
      fread(&U.anhd,1, sizeof(U.anhd),fi);
      printf ("%s    op= %-4d\n", tabstr(tab), U.anhd.operation);
      printf ("%s  mask= %-2x\n", tabstr(tab), U.anhd.mask);
      printf ("%s width= %-4d\n", tabstr(tab), U.anhd.w);
      printf ("%sheight= %-4d\n", tabstr(tab), U.anhd.h);
      printf ("%s     x= %-4d\n", tabstr(tab), U.anhd.x);
      printf ("%s     y= %-4d\n", tabstr(tab), U.anhd.y);
      printf ("%sabstim= %-4ld\n", tabstr(tab), U.anhd.abstime);
      printf ("%sreltim= %-4ld\n", tabstr(tab), U.anhd.reltime);
      printf ("%sintrlv= %-4d\n", tabstr(tab), U.anhd.interleave);
      break;
   case ILBM_BMHD:
      cs((long)sizeof(U.bmhd), bytes);
      fread(&U.bmhd,1, sizeof(U.bmhd),fi);
      printf ("%s width= %-4d\n", tabstr(tab), U.bmhd.w);
      printf ("%sheight= %-4d\n", tabstr(tab), U.bmhd.h);
      printf ("%splanes= %-4d\n", tabstr(tab), U.bmhd.planes);
      printf ("%s     x= %-4d\n", tabstr(tab), U.bmhd.x);
      printf ("%s     y= %-4d\n", tabstr(tab), U.bmhd.y);
      printf ("%s  mask= x%-2x\n",tabstr(tab), U.bmhd.masking);
      printf ("%s  comp= x%-2x\n",tabstr(tab), U.bmhd.compression);
      printf ("%stcolor= %-2d\n", tabstr(tab), U.bmhd.transparent_color);
      printf ("%sxaspct= %-2d\n", tabstr(tab), U.bmhd.xaspect);
      printf ("%syaspct= %-2d\n", tabstr(tab), U.bmhd.yaspect);
      printf ("%s pagew= %-4d\n", tabstr(tab), U.bmhd.pagewidth);
      printf ("%s pageh= %-4d\n", tabstr(tab), U.bmhd.pageheight);
      break;
   case ILBM_CMAP:
      if (bytes % 3) {
         puts ("Expected multiples of 3 bytes for colormap");
         break;
      }
      if (bytes > 32*3) {
         puts ("Color map is larger than 32 entries");
         break;
      }
      fread(&U.cmap,1,(int)bytes,fi);
      j = bytes/3;
      for (i = 0; i < j; ++i) {
         printf ("%scolor %2d   %2x %2x %2x\n",
            tabstr(tab), i, U.cmap[i][0], U.cmap[i][1], U.cmap[i][2]);
      }
      break;
   case ILBM_GRAB:
   case ILBM_DEST:
   case ILBM_SPRT:
      puts ("");
      break;
   case ILBM_CAMG:
      fread(&U.camg,1, sizeof(U.camg),fi);
      i = U.camg.vpmodes;
      printf ("%sVP MODES = %8x (", tabstr(tab), i);
      if (i & HIRES)
         printf("HIRES ");
      if (i & SPRITES)
         printf("SPRITES ");
      if (i & VP_HIDE)
         printf("VP_HIDE ");
      if (i & HAM)
         printf ("HAM ");
      if (i & DUALPF)
         printf ("DUALPF ");
      if (i & GENLOCK_AUDIO)
         printf ("GENLOCK_AUDIO ");
      if (i & EXTRA_HALFBRITE)
         printf ("EXTRA_HALFBRITE ");
      if (i & PFBA)
         printf ("PFBA ");
      if (i & LACE)
         printf ("LACE ");
      if (i & GENLOCK_VIDEO)
         printf ("GENLOCK_VIDEO ");
      puts (")");
      break;
   case ILBM_CRNG:
      cs((long)sizeof(U.crng), bytes);
      fread(&U.crng,1, sizeof(U.crng),fi);
      printf ("%s count= %-4d\n", tabstr(tab), U.crng.count);
      printf ("%s  rate= %-4d\n", tabstr(tab), U.crng.rate);
      printf ("%s flags= %-4d\n", tabstr(tab), U.crng.flags);
      printf ("%s   low= %-4d\n", tabstr(tab), U.crng.low);
      printf ("%s  high= %-4d\n", tabstr(tab), U.crng.high);
      break;
   case ILBM_BODY:
      break;
   }
}



hexdump(fi, curpos, bytes, tab)
FILE *fi;
long curpos,bytes,tab;
{
   long pos;
   UBYTE ch;

   pos = 0;
   fseek(fi, curpos, 0);
   while (bytes) {
      fread( &ch,1, 1,fi);
      if ((pos & 15) == 0) {
         printf("\n%s%5lx     ", tabstr(tab+4), pos);
      }
      printf ("%2x ", ch);
      ++pos;
      --bytes;
   }
   puts("");
}



cs(shouldbe, actual)
long shouldbe,actual;
{
   if (shouldbe != actual)
      printf ("Expected %ld bytes, got %ld\n", shouldbe, actual);
}


char *
tabstr(tab)
long tab;
{
   static char space[128];
   static int lasttab = 0;
   static int init = 1;

   if (init) {
      for (init=1;init<128;init++) space[init] = ' ';
      init = 0;
   }
   if (tab != lasttab) {
      space[lasttab] = ' ';
      space[lasttab = tab] = '\0';
   }
   return (space);
}

char *
ltos(data)
unsigned long data;
{
   static char buf[5];

   buf[0] = (data >> 24) & 0xFF;
   buf[1] = (data >> 16) & 0xFF;
   buf[2] = (data >> 8 ) & 0xFF;
   buf[3] = data & 0xFF;
   return(buf);
}


