/* * 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 "iff.h" #include #define MODE_V1 0x01 #define MODE_V2 0x02 extern char *tabstr(), *ltos(); union { 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; long 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 = xopen(av[j], "r", 8192); if (fi == NULL) { puts ("could not open file"); exit(1); } endpos = xseek(fi, 0, 1); xseek(fi, 0, -1); iffdecode(fi, 0, endpos); xclose(fi); if (checkbreak()) puts ("*BREAK*"); } iffdecode(fi, tab, endpos) { long chunk[2]; long curpos, bytes, curend; long data; char ok; char count = 0; for (;;) { curpos = xseek(fi, 0, 0); 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); } xread(fi, chunk, 8); 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); } 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: xread(fi, &data, 4); curpos += 4; bytes -= 4; printf ("TYPE %s\n", ltos(data)); if (checkbreak()) break; iffdecode(fi, tab + 4, curend); if (checkbreak()) break; 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; } xseek(fi, curend, -1); if (checkbreak()) break; } } decode_sub(fi, tab, name, bytes) { int i, j; tab += 4; switch (name) { case ILBM_BMHD: cs(sizeof(U.bmhd), bytes); xread(fi, &U.bmhd, sizeof(U.bmhd)); printf ("%s width= %-4ld\n", tabstr(tab), U.bmhd.w); printf ("%sheight= %-4ld\n", tabstr(tab), U.bmhd.h); printf ("%splanes= %-4ld\n", tabstr(tab), U.bmhd.planes); printf ("%s x= %-4ld\n", tabstr(tab), U.bmhd.x); printf ("%s y= %-4ld\n", tabstr(tab), U.bmhd.y); printf ("%s mask= x%-2lx\n",tabstr(tab), U.bmhd.masking); printf ("%s comp= x%-2lx\n",tabstr(tab), U.bmhd.compression); printf ("%stcolor= %-2ld\n", tabstr(tab), U.bmhd.transparent_color); printf ("%sxaspct= %-2ld\n", tabstr(tab), U.bmhd.xaspect); printf ("%syaspct= %-2ld\n", tabstr(tab), U.bmhd.yaspect); printf ("%s pagew= %-4ld\n", tabstr(tab), U.bmhd.pagewidth); printf ("%s pageh= %-4ld\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; } xread(fi, &U.cmap, bytes); j = bytes/3; for (i = 0; i < j; ++i) { printf ("%scolor %2ld %2lx %2lx %2lx\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: xread(fi, &U.camg, sizeof(U.camg)); i = U.camg.vpmodes; printf ("%sVP MODES = %8lx (", 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: case ILBM_BODY: break; } } hexdump(fi, curpos, bytes, tab) { long pos; UBYTE ch; pos = 0; xseek(fi, curpos, -1); while (bytes) { xread(fi, &ch, 1); if ((pos & 15) == 0) { if (checkbreak()) break; printf("\n%s%5lx ", tabstr(tab+4), pos); } printf ("%2lx ", ch); ++pos; --bytes; } puts(""); } cs(shouldbe, actual) { if (shouldbe != actual) printf ("Expected %ld bytes, got %ld\n", shouldbe, actual); } char * tabstr(tab) { static char space[128]; static int lasttab; static int init = 1; if (init) { bset(space + 1, 127, ' '); 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); }