static void showstats(void) { fputs("memory allocation tracing statistics\n", stdout); fputs("------------------------------------\n", stdout); fprintf(stdout, "allocated: %lu (", stats.acount); printsize(stats.atotal); fprintf(stdout, ")\nfreed: %lu (", stats.fcount); printsize(stats.ftotal); fprintf(stdout, ")\nunfreed: %lu (", stats.acount - stats.fcount); printsize(stats.atotal - stats.ftotal); fprintf(stdout, ")\npeak: %lu (", stats.pcount); printsize(stats.ptotal); fprintf(stdout, ")\nreserved: %lu (", stats.rcount); printsize(stats.rtotal); fprintf(stdout, ")\ninternal: %lu (", stats.icount); printsize(stats.itotal); fprintf(stdout, ")\ntotal: %lu (", stats.rcount + stats.icount); printsize(stats.rtotal + stats.itotal); fputs(")\n\n", stdout); fputs("smallest size: ", stdout); printsize(stats.lsize); fputs("\nlargest size: ", stdout); printsize(stats.usize); fputs("\naverage size: ", stdout); printsize(rounddivide(stats.atotal, stats.acount)); fputc('\n', stdout); }
void lib_debug_check(void) { #ifdef LIB_DEBUG unsigned int index, count; unsigned int leakbytes; count = 0; leakbytes = 0; for (index = 0; index < LIB_DEBUG_SIZE; index++) { if (lib_debug_address[index] != NULL) { count++; #ifdef LIB_DEBUG_PINPOINT printf("%s:%d: ", lib_debug_filename[index], lib_debug_line[index]); #endif printf("Warning: Memory block allocated here was not free'd (Memory leak with size 0x%x at %p).", lib_debug_size[index], lib_debug_address[index]); #ifdef LIB_DEBUG_CALLER printf("(called from %p)", lib_debug_caller[index]); #endif printf("\n"); leakbytes += lib_debug_size[index]; #if LIB_DEBUG_GUARD > 0 lib_debug_guard_remove((char *)lib_debug_address[index]); #endif } } printf("Total memory leaks: %d Bytes leaked: 0x%x\n", count, leakbytes); printf("max. total memory that was allocated: 0x%x bytes. (", lib_debug_max_total); printsize(lib_debug_max_total); printf(")\n"); #ifdef LIB_DEBUG_PINPOINT printf("\nTop %d largest allocated blocks:\n", LIB_DEBUG_TOPMAX); for (index = 0; index < LIB_DEBUG_TOPMAX; index++) { if (lib_debug_top_size[index]) { printf("%8x bytes (", lib_debug_top_size[index]); printsize(lib_debug_top_size[index]); printf(") allocated at %s:%d\n", lib_debug_top_filename[index], lib_debug_top_line[index]); } } #endif #endif }
static void df(char *s, int always) { struct statfs st; if (statfs(s, &st) < 0) { fprintf(stderr, "%s: %s\n", s, strerror(errno)); ok = EXIT_FAILURE; } else { if (st.f_blocks == 0 && !always) return; printf("%-20s ", s); printsize((long long)st.f_blocks * (long long)st.f_bsize); printf(" "); printsize((long long)(st.f_blocks - (long long)st.f_bfree) * st.f_bsize); printf(" "); printsize((long long)st.f_bfree * (long long)st.f_bsize); printf(" %d\n", (int) st.f_bsize); } }
void plong(FTSENT *p) { char tmp[NAME_BUFSZ]; FTSENT_PRT *prt=(FTSENT_PRT*)p->fts_pointer; int length=prt->s_name; if (f_inodenum) printf("%*lld ", prt->s_inode, (LL)p->fts_statp->st_ino); if (f_dispblock) { LL b=p->fts_statp->st_blocks; b/=block_size_factor; printf("%*lld ", prt->s_block, b); } printmodestr(p); printf("%*hd ", prt->s_link, (short)p->fts_statp->st_nlink); if (f_numric) { printf("%*d ", prt->s_uid, (int)p->fts_statp->st_uid); printf("%*d ", prt->s_gid, (int)p->fts_statp->st_gid); } else { if (printuname(p, prt->s_uname)==-1) printf("%*d ", prt->s_uid, (int)p->fts_statp->st_uid); if (printgname(p, prt->s_gname)==-1) printf("%*d ", prt->s_gid, (int)p->fts_statp->st_gid); } printsize(p); if (f_sortbyacc) printtime(p->fts_statp->st_atime); else if (f_sortbychg) printtime(p->fts_statp->st_ctime); else printtime(p->fts_statp->st_mtime); if (f_displgd) { sprintf(tmp, "%s%c", p->fts_name, type(p)); length++; } else sprintf(tmp, "%s", p->fts_name); printstr(tmp, length); if (S_ISLNK(p->fts_statp->st_mode)) { int l; char buf[NAME_BUFSZ], path[NAME_BUFSZ]; if (p->fts_level==0) sprintf(path, "%s", p->fts_name); else sprintf(path, "%s/%s", p->fts_parent->fts_accpath, p->fts_name); if ((l=readlink(path, buf, sizeof(path)))==-1) warn("%s", p->fts_path); buf[l]='\0'; printf(" -> "); printstr(buf, prt->s_name); } }
void printlong(DISPLAY *dp) { struct stat *sp; FTSENT *p; NAMES *np; char buf[20]; if (dp->list->fts_level != FTS_ROOTLEVEL && (f_longform || f_size)) (void)printf("total %llu\n", howmany(dp->btotal, blocksize)); for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; sp = p->fts_statp; if (f_inode) (void)printf("%*llu ", dp->s_inode, (unsigned long long)sp->st_ino); if (f_size) (void)printf("%*lld ", dp->s_block, howmany((long long)sp->st_blocks, blocksize)); (void)strmode(sp->st_mode, buf); np = p->fts_pointer; (void)printf("%s %*u ", buf, dp->s_nlink, sp->st_nlink); if (!f_grouponly) (void)printf("%-*s ", dp->s_user, np->user); (void)printf("%-*s ", dp->s_group, np->group); if (f_flags) (void)printf("%-*s ", dp->s_flags, np->flags); if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) (void)printf("%3d, %3d ", major(sp->st_rdev), minor(sp->st_rdev)); else if (dp->bcfile) (void)printf("%*s%*lld ", 8 - dp->s_size, "", dp->s_size, (long long)sp->st_size); else printsize(dp->s_size, sp->st_size); if (f_accesstime) printtime(sp->st_atime); else if (f_statustime) printtime(sp->st_ctime); else printtime(sp->st_mtime); (void)mbsprint(p->fts_name, 1); if (f_type || (f_typedir && S_ISDIR(sp->st_mode))) (void)printtype(sp->st_mode); if (S_ISLNK(sp->st_mode)) printlink(p); (void)putchar('\n'); } }
void do_directory(const u8* base, u32 offset, u32 size, const char* path, const char* name, int mode) { printsize(size, size); printf("%s", name); // Check if we are actually unpacking if (path[0]=='-') { return; } // Make the local directory if (mkdir(path, mode) == -1) { perror(path); return; } }
void do_symlink(const u8 * base, u32 offset, u32 size, const char *path, const char *name, int mode) { // Allocate the uncompressed string u8 link_contents[size + 1]; // do uncompression uncompress_data(base, base + offset, size, link_contents); link_contents[size] = 0; printsize(size, compressed_size(base, base + offset, size)); printf("%s -> %s", name, link_contents); // Check if we are actually unpacking if (path[0] == '-') { return; } // Make local copy if (symlink((const char *)link_contents, path) == -1) { perror(path); exit(1); } }
void printlong(const DISPLAY *dp) { struct stat *sp; FTSENT *p; NAMES *np; char buf[20]; #ifdef COLORLS int color_printed = 0; #endif if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && (f_longform || f_size)) { xo_emit("{L:total} {:total-blocks/%lu}\n", howmany(dp->btotal, blocksize)); } xo_open_list("entry"); for (p = dp->list; p; p = p->fts_link) { char *name, *type; if (IS_NOPRINT(p)) continue; xo_open_instance("entry"); sp = p->fts_statp; name = getname(p->fts_name); if (name) xo_emit("{ke:name/%hs}", name); if (f_inode) xo_emit("{t:inode/%*ju} ", dp->s_inode, (uintmax_t)sp->st_ino); if (f_size) xo_emit("{t:blocks/%*jd} ", dp->s_block, howmany(sp->st_blocks, blocksize)); strmode(sp->st_mode, buf); aclmode(buf, p); np = p->fts_pointer; xo_attr("value", "%03o", (int) sp->st_mode & ALLPERMS); if (f_numericonly) { xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {td:user/%-*s}{e:user/%ju} {td:group/%-*s}{e:group/%ju} ", buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, dp->s_user, np->user, sp->st_uid, dp->s_group, np->group, sp->st_gid); } else { xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} {t:user/%-*s} {t:group/%-*s} ", buf, (int) sp->st_mode & ALLPERMS, dp->s_nlink, sp->st_nlink, dp->s_user, np->user, dp->s_group, np->group); } if (S_ISBLK(sp->st_mode)) asprintf(&type, "block"); if (S_ISCHR(sp->st_mode)) asprintf(&type, "character"); if (S_ISDIR(sp->st_mode)) asprintf(&type, "directory"); if (S_ISFIFO(sp->st_mode)) asprintf(&type, "fifo"); if (S_ISLNK(sp->st_mode)) asprintf(&type, "symlink"); if (S_ISREG(sp->st_mode)) asprintf(&type, "regular"); if (S_ISSOCK(sp->st_mode)) asprintf(&type, "socket"); if (S_ISWHT(sp->st_mode)) asprintf(&type, "whiteout"); xo_emit("{e:type/%s}", type); free(type); if (f_flags) xo_emit("{:flags/%-*s} ", dp->s_flags, np->flags); if (f_label) xo_emit("{t:label/%-*s} ", dp->s_label, np->label); if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) printdev(dp->s_size, sp->st_rdev); else printsize("size", dp->s_size, sp->st_size); if (f_accesstime) printtime("access-time", sp->st_atime); else if (f_birthtime) printtime("birth-time", sp->st_birthtime); else if (f_statustime) printtime("change-time", sp->st_ctime); else printtime("modify-time", sp->st_mtime); #ifdef COLORLS if (f_color) color_printed = colortype(sp->st_mode); #endif if (name) { xo_emit("{dk:name/%hs}", name); free(name); } #ifdef COLORLS if (f_color && color_printed) endcolor(0); #endif if (f_type) (void)printtype(sp->st_mode); if (S_ISLNK(sp->st_mode)) printlink(p); xo_close_instance("entry"); xo_emit("\n"); } xo_close_list("entry"); }
void printlong(const DISPLAY *dp) { struct stat *sp; FTSENT *p; NAMES *np; char buf[20]; #ifdef COLORLS int color_printed = 0; #endif if ((dp->list == NULL || dp->list->fts_level != FTS_ROOTLEVEL) && (f_longform || f_size)) { (void)printf("total %lu\n", howmany(dp->btotal, blocksize)); } for (p = dp->list; p; p = p->fts_link) { if (IS_NOPRINT(p)) continue; sp = p->fts_statp; if (f_inode) (void)printf("%*lu ", dp->s_inode, (u_long)sp->st_ino); if (f_size) (void)printf("%*jd ", dp->s_block, howmany(sp->st_blocks, blocksize)); strmode(sp->st_mode, buf); aclmode(buf, p); np = p->fts_pointer; (void)printf("%s %*u %-*s %-*s ", buf, dp->s_nlink, sp->st_nlink, dp->s_user, np->user, dp->s_group, np->group); if (f_flags) (void)printf("%-*s ", dp->s_flags, np->flags); if (f_label) (void)printf("%-*s ", dp->s_label, np->label); if (S_ISCHR(sp->st_mode) || S_ISBLK(sp->st_mode)) printdev(dp->s_size, sp->st_rdev); else printsize(dp->s_size, sp->st_size); if (f_accesstime) printtime(sp->st_atime); else if (f_birthtime) printtime(sp->st_birthtime); else if (f_statustime) printtime(sp->st_ctime); else printtime(sp->st_mtime); #ifdef COLORLS if (f_color) color_printed = colortype(sp->st_mode); #endif (void)printname(p->fts_name); #ifdef COLORLS if (f_color && color_printed) endcolor(0); #endif if (f_type) (void)printtype(sp->st_mode); if (S_ISLNK(sp->st_mode)) printlink(p); (void)putchar('\n'); } }
int showinfo (int fd) { int i,err,n; struct mtd_info_user mtd; static struct region_info_user region[1024]; err = getmeminfo (fd,&mtd); if (err < 0) { perror ("MEMGETINFO"); return (1); } err = getregions (fd,region,&n); if (err < 0) { perror ("MEMGETREGIONCOUNT"); return (1); } printf ("mtd.type = "); switch (mtd.type) { case MTD_ABSENT: printf ("MTD_ABSENT"); break; case MTD_RAM: printf ("MTD_RAM"); break; case MTD_ROM: printf ("MTD_ROM"); break; case MTD_NORFLASH: printf ("MTD_NORFLASH"); break; case MTD_NANDFLASH: printf ("MTD_NANDFLASH"); break; case MTD_PEROM: printf ("MTD_PEROM"); break; case MTD_OTHER: printf ("MTD_OTHER"); break; case MTD_UNKNOWN: printf ("MTD_UNKNOWN"); break; default: printf ("(unknown type - new MTD API maybe?)"); } printf ("\nmtd.flags = "); if (mtd.flags == MTD_CAP_ROM) printf ("MTD_CAP_ROM"); else if (mtd.flags == MTD_CAP_RAM) printf ("MTD_CAP_RAM"); else if (mtd.flags == MTD_CAP_NORFLASH) printf ("MTD_CAP_NORFLASH"); else if (mtd.flags == MTD_CAP_NANDFLASH) printf ("MTD_CAP_NANDFLASH"); else if (mtd.flags == MTD_WRITEABLE) printf ("MTD_WRITEABLE"); else { int i,first = 1; static struct { const char *name; int value; } flags[] = { { "MTD_CLEAR_BITS", MTD_CLEAR_BITS }, { "MTD_SET_BITS", MTD_SET_BITS }, { "MTD_ERASEABLE", MTD_ERASEABLE }, { "MTD_WRITEB_WRITEABLE", MTD_WRITEB_WRITEABLE }, { "MTD_VOLATILE", MTD_VOLATILE }, { "MTD_XIP", MTD_XIP }, { "MTD_OOB", MTD_OOB }, { "MTD_ECC", MTD_ECC }, { NULL, -1 } }; for (i = 0; flags[i].name != NULL; i++) if (mtd.flags & flags[i].value) { if (first) { printf (flags[i].name); first = 0; } else printf (" | %s",flags[i].name); } } printf ("\nmtd.size = "); printsize (mtd.size); printf ("\nmtd.erasesize = "); printsize (mtd.erasesize); printf ("\nmtd.oobblock = "); printsize (mtd.oobblock); printf ("\nmtd.oobsize = "); printsize (mtd.oobsize); printf ("\nmtd.ecctype = "); switch (mtd.ecctype) { case MTD_ECC_NONE: printf ("MTD_ECC_NONE"); break; case MTD_ECC_RS_DiskOnChip: printf ("MTD_ECC_RS_DiskOnChip"); break; case MTD_ECC_SW: printf ("MTD_ECC_SW"); break; default: printf ("(unknown ECC type - new MTD API maybe?)"); } printf ("\n" "regions = %d\n" "\n", n); for (i = 0; i < n; i++) { printf ("region[%d].offset = 0x%.8x\n" "region[%d].erasesize = ", i,region[i].offset,i); printsize (region[i].erasesize); printf ("\nregion[%d].numblocks = %d\n" "region[%d].regionindex = %d\n", i,region[i].numblocks, i,region[i].regionindex); } return (0); }
void lib_debug_check(void) { #ifdef LIB_DEBUG unsigned int index, count; unsigned int leakbytes; #ifdef LIB_DEBUG_CALLER char **btstring; int btidx, spc; #endif count = 0; leakbytes = 0; lib_debug_leaklist_num = 0; for (index = 0; index < LIB_DEBUG_SIZE; index++) { if (lib_debug_address[index] != NULL) { count++; #ifdef LIB_DEBUG_PINPOINT lib_debug_leaklist_add(index); #else printf("Warning: Memory block allocated here was not free'd (Memory leak with size 0x%x at %p).", lib_debug_size[index], lib_debug_address[index]); printf("\n"); #endif leakbytes += lib_debug_size[index]; #if LIB_DEBUG_GUARD > 0 lib_debug_guard_remove((char *)lib_debug_address[index]); #endif } } #ifdef LIB_DEBUG_PINPOINT printf("\n"); for (index = 0; index < lib_debug_leaklist_num; index++) { printf("%s:%d: Warning: Memory block(s) allocated here was not free'd (Memory leak with size 0x%x at %p).", lib_debug_leaklist_filename[index], lib_debug_leaklist_line[index], lib_debug_leaklist_size[index], lib_debug_leaklist_address[index]); #ifdef LIB_DEBUG_CALLER printf("\ncallstack:\n"); btstring = backtrace_symbols(lib_debug_leaklist_bt_caller[index], lib_debug_leaklist_bt_numcaller[index]); if (btstring == NULL) { printf(" lookup failed\n"); } else { for (btidx = 1; btidx < lib_debug_leaklist_bt_numcaller[index]; btidx++) { printf(" "); for (spc = 0; spc < btidx; spc++) { printf(" "); } printf("%s\n", btstring[btidx]); } } free(btstring); #endif printf("\n"); } #endif printf("\nTotal memory leaks: %d", count); #ifdef LIB_DEBUG_PINPOINT printf(" in %d lines", lib_debug_leaklist_num); #endif printf(". Total bytes leaked: 0x%x (", leakbytes); printsize(leakbytes); printf(").\n\nmax. total memory that was allocated: 0x%x bytes. (", lib_debug_max_total); printsize(lib_debug_max_total); printf(")\n"); #ifdef LIB_DEBUG_PINPOINT printf("\nTop %d largest allocated blocks:\n", LIB_DEBUG_TOPMAX); for (index = 0; index < LIB_DEBUG_TOPMAX; index++) { if (lib_debug_top_size[index]) { printf("%8x bytes (", lib_debug_top_size[index]); printsize(lib_debug_top_size[index]); printf(") allocated at %s:%d\n", lib_debug_top_filename[index], lib_debug_top_line[index]); } } #endif #endif }
void do_file(const u8* base, u32 offset, u32 size, const char* path, const char* name, int mode) { int fd; u8* file_data; const u8* srcdata; // Allow for uncompressed XIP executable if (mode & S_ISVTX) { // It seems that the offset may not necessarily be page // aligned. This is silly because mkcramfs wastes // the alignment space, whereas it might be used if it wasn't // bogusly in our file extent. // // blksize must be a power of 2 for the following to work, but it seems // quite likely. srcdata=(const u8*)(((u32)(base+offset)+blksize-1) & ~(blksize-1)); printsize(size, srcdata+size-(base+offset)); printf("%s", name); } else { printsize(size, compressed_size(base, base+offset, size) ); printf("%s", name); } // Check if we are actually unpacking if (path[0]=='-') { return; } // Make local copy fd=open(path, O_CREAT|O_TRUNC|O_RDWR, mode); if (fd == -1) { perror("create"); return; }; if (ftruncate(fd, size) == -1) { perror("ftruncate"); close(fd); return; } file_data = mmap(0, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (file_data == MAP_FAILED) { perror("mmap"); close(fd); return; } // Allow for uncompressed XIP executable if (mode & S_ISVTX) { memcpy(file_data, srcdata, size); } else { if(uncompress_data(base, base+offset, size, file_data) == -1) { printf("failed to decompress data\n"); } } munmap(file_data, size); close(fd); }
int showinfo (int fd) { int i,err,n; struct mtd_info_user mtd; static struct region_info_user region[1024]; err = getmeminfo (fd,&mtd); if (err < 0) { perror ("MEMGETINFO"); return (1); } err = getregions (fd,region,&n); if (err < 0) { perror ("MEMGETREGIONCOUNT"); return (1); } printf ("mtd.type = "); switch (mtd.type) { case MTD_ABSENT: printf ("MTD_ABSENT"); break; case MTD_RAM: printf ("MTD_RAM"); break; case MTD_ROM: printf ("MTD_ROM"); break; case MTD_NORFLASH: printf ("MTD_NORFLASH"); break; case MTD_NANDFLASH: printf ("MTD_NANDFLASH"); break; case MTD_DATAFLASH: printf ("MTD_DATAFLASH"); break; case MTD_UBIVOLUME: printf ("MTD_UBIVOLUME"); default: printf ("(unknown type - new MTD API maybe?)"); } printf ("\nmtd.flags = "); if (mtd.flags == MTD_CAP_ROM) printf ("MTD_CAP_ROM"); else if (mtd.flags == MTD_CAP_RAM) printf ("MTD_CAP_RAM"); else if (mtd.flags == MTD_CAP_NORFLASH) printf ("MTD_CAP_NORFLASH"); else if (mtd.flags == MTD_CAP_NANDFLASH) printf ("MTD_CAP_NANDFLASH"); else if (mtd.flags == MTD_WRITEABLE) printf ("MTD_WRITEABLE"); else { int first = 1; static struct { const char *name; int value; } flags[] = { { "MTD_WRITEABLE", MTD_WRITEABLE }, { "MTD_BIT_WRITEABLE", MTD_BIT_WRITEABLE }, { "MTD_NO_ERASE", MTD_NO_ERASE }, { "MTD_STUPID_LOCK", MTD_STUPID_LOCK }, { NULL, -1 } }; for (i = 0; flags[i].name != NULL; i++) if (mtd.flags & flags[i].value) { if (first) { printf (flags[i].name); first = 0; } else printf (" | %s",flags[i].name); } } printf ("\nmtd.size = "); printsize (mtd.size); printf ("\nmtd.erasesize = "); printsize (mtd.erasesize); printf ("\nmtd.writesize = "); printsize (mtd.writesize); printf ("\nmtd.oobsize = "); printsize (mtd.oobsize); printf ("\n" "regions = %d\n" "\n", n); for (i = 0; i < n; i++) { printf ("region[%d].offset = 0x%.8x\n" "region[%d].erasesize = ", i,region[i].offset,i); printsize (region[i].erasesize); printf ("\nregion[%d].numblocks = %d\n" "region[%d].regionindex = %d\n", i,region[i].numblocks, i,region[i].regionindex); } return (0); }
int main(int argc, char *argv[]){ unsigned c; int slash; FILE * hFile; int overwrite = 0; char *InFile, *OutFile = NULL, *FileName, *OutDir = NULL; size_t FileSize; struct MD5Context md5c; unsigned char digest[16]; uint8_t * IFFData; IFFFile * IFFFileInfo; IFFChunk * ChunkData; if(argc == 1 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")){ printf("Usage: iff2html [-f] infile (outfile)\n" "Produce an HTML webpage describing an EA IFF file.\n" "Use -f to force overwriting without confirmation.\n" "If outfile is unspecified, file.iff will output to file.html.\n" "\n" "Report bugs to <*****@*****.**>.\n" "iff2html is maintained by the Niotso project.\n" "Home page: <http://www.niotso.org/>\n"); return 0; } if(argc >= 4 && !strcmp(argv[1], "-f")){ overwrite++; InFile = argv[2]; OutFile = argv[3]; }else if(argc == 3){ if(!strcmp(argv[1], "-f")){ overwrite++; InFile = argv[2]; }else{ InFile = argv[1]; OutFile = argv[2]; } }else InFile = argv[1]; if(OutFile == NULL){ unsigned length = strlen(InFile); OutFile = malloc(max(length+2, 6)); strcpy(OutFile, InFile); strcpy(max(OutFile+length-4, OutFile), ".html"); } for(c=0, slash=-1; OutFile[c]; c++) if(OutFile[c] == '/' || OutFile[c] == '\\') slash = c; if(slash >= 0){ OutDir = malloc(slash+2); memcpy(OutDir, OutFile, slash+1); OutDir[slash+1] = 0x00; }else OutDir = ""; for(c=0, slash=-1; InFile[c]; c++) if(InFile[c] == '/' || InFile[c] == '\\') slash = c; FileName = InFile + slash + 1; /**** ** Open the file and read in entire contents to memory */ hFile = fopen(InFile, "rb"); if(hFile == NULL){ printf("%sThe specified input file does not exist or could not be opened for reading.", "iff2html: error: "); return -1; } fseek(hFile, 0, SEEK_END); FileSize = ftell(hFile); if(FileSize < 64){ printf("%sNot a valid IFF file.", "iff2html: error: "); return -1; } fseek(hFile, 0, SEEK_SET); IFFData = malloc(FileSize); if(IFFData == NULL){ printf("%sMemory for this file could not be allocated.", "iff2html: error: "); return -1; } if(!fread(IFFData, FileSize, 1, hFile)){ printf("%sThe input file could not be read.", "iff2html: error: "); return -1; } fclose(hFile); /**** ** Load header information */ IFFFileInfo = iff_create(); if(IFFFileInfo == NULL){ printf("%sMemory for this file could not be allocated.", "iff2html: error: "); return -1; } if(!iff_read_header(IFFFileInfo, IFFData, FileSize)){ printf("%sNot a valid IFF file.", "iff2html: error: "); return -1; } /**** ** Load entry information */ if(!iff_enumerate_chunks(IFFFileInfo, IFFData+64, FileSize-64)){ printf("%sChunk data is corrupt.", "iff2html: error: "); return -1; } /* Calculate the MD5, and then we can free the IFF data because we're done with it */ MD5Init(&md5c); MD5Update(&md5c, IFFData, FileSize); MD5Final(digest, &md5c); free(IFFData); for(c = 0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++) iff_parse_chunk(ChunkData, ChunkData->Data); /**** ** Open the output file and write the header */ if(!overwrite){ hFile = fopen(OutFile, "rb"); if(hFile != NULL){ /* File exists */ char c; fclose(hFile); printf("File \"%s\" exists.\nContinue anyway? (y/n) ", OutFile); c = getchar(); if(c != 'y' && c != 'Y'){ printf("\nAborted."); return -1; } } } hFile = fopen(OutFile, "wb"); if(hFile == NULL){ printf("%sThe output file could not be opened for writing.", "iff2html: error: "); return -1; } /**** ** We're splitting fprintf by line to guarantee compatibility; ** even C99 compilers are only required to support 4096 byte strings in printf()-related functions */ fprintf(hFile, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\n"); fprintf(hFile, "<html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\" dir=\"ltr\">\n"); fprintf(hFile, "<head>\n"); fprintf(hFile, "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\" />\n"); fprintf(hFile, "<meta http-equiv=\"Content-Style-Type\" content=\"text/css; charset=iso-8859-1\" />\n"); fprintf(hFile, "<meta http-equiv=\"Content-Language\" content=\"en\" />\n"); fprintf(hFile, "<meta name=\"description\" content=\"%s (iff2html)\" />\n", FileName); fprintf(hFile, "<meta name=\"generator\" content=\"iff2html\" />\n"); fprintf(hFile, "<title>%s (iff2html)</title>\n", FileName); fprintf(hFile, "<style type=\"text/css\" media=\"all\">\n"); fprintf(hFile, "html, body {\n"); fprintf(hFile, " background: #fff;\n"); fprintf(hFile, " color: #000;\n"); fprintf(hFile, " font-family: sans-serif;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, "a:link, a:visited, a:hover, a:active { color: #00f; }\n"); fprintf(hFile, "a:link, a:visited { text-decoration: none; }\n"); fprintf(hFile, "a:hover, a:active { text-decoration: underline; }\n"); fprintf(hFile, "\n"); fprintf(hFile, "#attributes {\n"); fprintf(hFile, " border-left: 2px solid #888; padding-left: 4px; margin-bottom: 1em;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, "#toc {\n"); fprintf(hFile, " display: table-cell;\n"); fprintf(hFile, " margin-top: 1em;\n"); fprintf(hFile, " background: #eee; border: 1px solid #bbb;\n"); fprintf(hFile, " padding: .25em;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "#toc div {\n"); fprintf(hFile, " border-bottom: 1px solid #aaa;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "#toc ul {\n"); fprintf(hFile, " list-style-type: none;\n"); fprintf(hFile, " padding: 0;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "ul ul {\n"); fprintf(hFile, " padding: 2em;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, "h2 {\n"); fprintf(hFile, " border-bottom: 1px solid #888;\n"); fprintf(hFile, " margin: 2em 0 0.25em 0;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "h2 a {\n"); fprintf(hFile, " font-size: 9pt;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, "table {\n"); fprintf(hFile, " border: 1px #aaa solid;\n"); fprintf(hFile, " border-collapse: collapse;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "th, td {\n"); fprintf(hFile, " border: 1px #aaa solid;\n"); fprintf(hFile, " padding: 0.2em;\n"); fprintf(hFile, " white-space: pre-wrap;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, ".center {\n"); fprintf(hFile, " margin: auto auto;\n"); fprintf(hFile, "}\n"); fprintf(hFile, ".centerall * {\n"); fprintf(hFile, " text-align: center;\n"); fprintf(hFile, " vertical-align: middle;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, ".palette td, .palette th {\n"); fprintf(hFile, " border: none;\n"); fprintf(hFile, " width: 16px;\n"); fprintf(hFile, " height: 16px;\n"); fprintf(hFile, " font-size: 12px;\n"); fprintf(hFile, " line-height: 16px;\n"); fprintf(hFile, "}\n"); fprintf(hFile, ".palette td[title] {\n"); fprintf(hFile, " border: 1px solid #000;\n"); fprintf(hFile, " cursor: help;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "\n"); fprintf(hFile, "#footer {\n"); fprintf(hFile, " margin-top: 2em;\n"); fprintf(hFile, " padding-bottom: 0.5em;\n"); fprintf(hFile, " text-align: center;\n"); fprintf(hFile, "}\n"); fprintf(hFile, "</style>\n"); fprintf(hFile, "</head>\n"); fprintf(hFile, "<body>\n"); fprintf(hFile, "<h1>%s</h1>\n", FileName); fprintf(hFile, "<div id=\"attributes\">\n"); fprintf(hFile, "<div>"); for(c=0; c<16; c++) fprintf(hFile, "%.2x", digest[c]); fprintf(hFile, " (md5), "); printsize(hFile, FileSize); fprintf(hFile, "</div>\n"); fprintf(hFile, "<div>Dumped by iff2html.</div></div>\n"); fprintf(hFile, "\n"); fprintf(hFile, "<div id=\"toc\"><div><b>Contents</b> – %u chunks</div>\n", IFFFileInfo->ChunkCount); fprintf(hFile, "<ul>\n"); for(c=1, ChunkData = IFFFileInfo->Chunks; c <= IFFFileInfo->ChunkCount; c++, ChunkData++) fprintf(hFile, "<li><a href=\"#chunk%u_%.4x\">%u [%s] (%.4X)%s%s</a></li>\n", c, ChunkData->ChunkID, c, ChunkData->Type, ChunkData->ChunkID, (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label); fprintf(hFile, "</ul>\n"); fprintf(hFile, "</div>\n"); fprintf(hFile, "\n"); for(c=0, ChunkData = IFFFileInfo->Chunks; c < IFFFileInfo->ChunkCount; c++, ChunkData++){ fprintf(hFile, "<h2 id=\"chunk%u_%.4x\">%u [%s] (%.4X)%s%s <a href=\"#chunk%u_%.4x\">(Jump)</a></h2>\n", c+1, ChunkData->ChunkID, c+1, ChunkData->Type, ChunkData->ChunkID, (ChunkData->Label[0] != 0x00) ? " – " : "", ChunkData->Label, c+1, ChunkData->ChunkID); fprintf(hFile, "<div>\n"); if(ChunkData->FormattedData == NULL){ int success = 0; /* The iff library does not parse BMP_ or FBMP chunks */ if(!strcmp(ChunkData->Type, "BMP_") || !strcmp(ChunkData->Type, "FBMP")){ int bmp = !strcmp(ChunkData->Type, "BMP_"); size_t Width, Height; char filename[32]; sprintf(filename, "%s%s_%u_%.4x.png", OutDir, bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID); if(WritePNG(filename, ChunkData, 0, NULL, &Width, &Height)){ fprintf(hFile, "<table class=\"center centerall\">\n"); fprintf(hFile, "<tr><th>Image</th></tr>\n"); fprintf(hFile, "<tr><td><img src=\"%s_%u_%.4x.png\" width=\"%u\" height=\"%u\" alt=\"\" /></td></tr>\n", bmp ? "bmp" : "fbmp", c+1, ChunkData->ChunkID, (unsigned) Width, (unsigned) Height); fprintf(hFile, "</table>\n"); success++; } } if(!success) fprintf(hFile, "The contents of this chunk could not be parsed.\n"); }else if(!strcmp(ChunkData->Type, "STR#") || !strcmp(ChunkData->Type, "CTSS") || !strcmp(ChunkData->Type, "FAMs") || !strcmp(ChunkData->Type, "TTAs") || !strcmp(ChunkData->Type, "CST") ){ /**** ** STR# parsing */ IFFString * StringData = ChunkData->FormattedData; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Format:</td><td>"); switch(StringData->Format){ case 0: fprintf(hFile, "<tt>00 00</tt> (0)"); break; case -1: fprintf(hFile, "<tt>FF FF</tt> (−1)"); break; case -2: fprintf(hFile, "<tt>FE FF</tt> (−2)"); break; case -3: fprintf(hFile, "<tt>FD FF</tt> (−3)"); break; case -4: fprintf(hFile, "<tt>FC FF</tt> (−4)"); break; default: fprintf(hFile, "Unrecognized"); break; } fprintf(hFile, "</td></tr>\n"); fprintf(hFile, "</table>\n"); if(StringData->Format >= -4 && StringData->Format <= 0){ unsigned LanguageSet; const char * LanguageStrings[] = { "English (US)", "English (International)", "French", "German", "Italian", "Spanish", "Dutch", "Danish", "Swedish", "Norwegian", "Finnish", "Hebrew", "Russian", "Portuguese", "Japanese", "Polish", "Simplified Chinese", "Traditional Chinese", "Thai", "Korean" }; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th>Language</th><th colspan=\"3\">String pairs</th></tr>\n"); for(LanguageSet=0; LanguageSet<20; LanguageSet++){ IFFStringPair * Pair; unsigned PairIndex; if(StringData->LanguageSets[LanguageSet].PairCount == 0) continue; fprintf(hFile, "<tr><td rowspan=\"%u\">%s</td>\n", StringData->LanguageSets[LanguageSet].PairCount, LanguageStrings[LanguageSet]); for(PairIndex=1, Pair = StringData->LanguageSets[LanguageSet].Pairs; PairIndex <= StringData->LanguageSets[LanguageSet].PairCount; PairIndex++, Pair++){ if(PairIndex != 1) fprintf(hFile, "<tr>"); fprintf(hFile, "<td>%u</td><td>%s</td><td>%s</td></tr>\n", PairIndex, (Pair->Key) != NULL ? Pair->Key : "", (Pair->Value) != NULL ? Pair->Value : ""); } } fprintf(hFile, "</table>\n"); } }else if(!strcmp(ChunkData->Type, "CATS")){ /**** ** Regular string pair */ IFFStringPair * Pair = ChunkData->FormattedData; fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th>Key</th><th>Value</th></tr>\n"); fprintf(hFile, "<tr><td>%s</td><td>%s</td></tr>\n", (Pair->Key) != NULL ? Pair->Key : "", (Pair->Value) != NULL ? Pair->Value : ""); fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "FWAV") || !strcmp(ChunkData->Type, "GLOB")){ /**** ** Regular string */ fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th>String</th></tr>\n"); fprintf(hFile, "<tr><td>%s</td></tr>\n", ChunkData->FormattedData ? (char*) ChunkData->FormattedData : ""); fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "BCON")){ /**** ** BCON parsing */ IFF_BCON * BCONData = ChunkData->FormattedData; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Flags:</td><td><tt>%02X</tt> (%u)</td></tr>\n", BCONData->Flags, BCONData->Flags); fprintf(hFile, "</table>\n"); if(BCONData->ConstantCount > 0){ unsigned i; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Constant Value</th></tr>\n"); for(i=0; i<BCONData->ConstantCount; i++) fprintf(hFile, "<tr><td>%u</td><td>%u</td></tr>\n", i+1, BCONData->Constants[i]); fprintf(hFile, "</table>\n"); } }else if(!strcmp(ChunkData->Type, "FCNS")){ /**** ** FCNS parsing */ IFFConstantList * List = ChunkData->FormattedData; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", List->Version); fprintf(hFile, "</table>\n"); if(List->ConstantCount > 0){ IFFConstant * Constant; unsigned i; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Name</th><th>Value</th><th>Description</th></tr>\n"); for(i=0, Constant=List->Constants; i<List->ConstantCount; i++, Constant++) fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%g</td><td>%s</td></tr>\n", i+1, Constant->Name ? Constant->Name : "", Constant->Value, Constant->Description ? Constant->Description : ""); fprintf(hFile, "</table>\n"); } }else if(!strcmp(ChunkData->Type, "TMPL")){ /**** ** TMPL parsing */ IFFTemplate * Template = ChunkData->FormattedData; IFFTemplateField * Field; unsigned i; fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Name</th><th>Type</th>\n"); for(i=0, Field=Template->Fields; i<Template->FieldCount; i++, Field++) fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%s</td></tr>\n", i+1, Field->Name ? Field->Name : "", Field->Type ? Field->Type : ""); fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "TRCN")){ /**** ** TRCN parsing */ IFFRangeSet * RangeSet = ChunkData->FormattedData; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", RangeSet->Version); fprintf(hFile, "</table>\n"); if(RangeSet->RangeCount > 0){ unsigned i; IFFRangeEntry * Range; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">In use</th><th>Default value</th><th>Name</th>" "<th>Comment</th><th>Range is enforced</th><th>Minimum</th><th>Maximum</th></tr>\n"); for(i=0, Range=RangeSet->Ranges; i<RangeSet->RangeCount; i++, Range++) fprintf(hFile, "<tr><td>%u</td><td>%s</td><td>%u</td><td>%s</td><td>%s</td><td>%s</td><td>%u</td><td>%u</td></tr>\n", i+1, Range->IsUsed ? "Yes" : "No", Range->DefaultValue, Range->Name ? Range->Name : "", Range->Comment ? Range->Comment : "", Range->Enforced ? "Yes" : "No", Range->RangeMin, Range->RangeMax); fprintf(hFile, "</table>\n"); } }else if(!strcmp(ChunkData->Type, "PALT")){ /**** ** PALT parsing */ IFFPalette * Palette = ChunkData->FormattedData; uint8_t * Data = Palette->Data; unsigned i, j; fprintf(hFile, "<table class=\"center palette\" border=\"0\">\n"); fprintf(hFile, "<tr><th></th>"); for(i=0; i<16; i++) fprintf(hFile, "<th>%X</th>", i); fprintf(hFile, "</tr>\n"); for(i=0; i<16; i++){ fprintf(hFile, "<tr><th>%X</th>", i); for(j=0; j<16; j++){ if(i*16 + j < Palette->ColorCount){ unsigned red = *(Data++); unsigned green = *(Data++); unsigned blue = *(Data++); fprintf(hFile, "\n<td style=\"background:#%.2x%.2x%.2x\" title=\"%u: #%.2x%.2x%.2x\"></td>", red, green, blue, i*16 + j, red, green, blue); }else fprintf(hFile, "\n<td></td>"); } fprintf(hFile, "</tr>\n"); } fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "SPR#") || !strcmp(ChunkData->Type, "SPR2")){ /**** ** SPR# and SPR2 parsing */ int spr1 = !strcmp(ChunkData->Type, "SPR#"); IFFSpriteList * SpriteList = ChunkData->FormattedData; IFFChunk * Palette = NULL; IFFPalette BlankPalette; IFFPalette * PaletteData; unsigned i; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", SpriteList->Version); fprintf(hFile, "<tr><td>Palette ID:</td><td>%.4X</td></tr>\n", SpriteList->PaletteID); fprintf(hFile, "</table>\n"); if(SpriteList->PaletteID < 0xFFFF){ Palette = iff_find_chunk(IFFFileInfo, "PALT", SpriteList->PaletteID); if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", ChunkData->ChunkID); if(!Palette || !Palette->FormattedData) Palette = iff_find_chunk(IFFFileInfo, "PALT", -1); } if(!Palette || !Palette->FormattedData){ memset(&BlankPalette, 0, sizeof(IFFPalette)); BlankPalette.Version = 1; BlankPalette.ColorCount = 256; PaletteData = &BlankPalette; }else PaletteData = Palette->FormattedData; fprintf(hFile, "<table class=\"center centerall\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Sprite</th>"); if(!spr1) fprintf(hFile, "<th>Z-Buffer</th>"); fprintf(hFile, "</tr>\n"); for(i=0; i<SpriteList->SpriteCount; i++){ IFFSprite * Sprite = &SpriteList->Sprites[i]; char filename[32]; sprintf(filename, "%s%s_%u_%.4x_%u.png", OutDir, spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1); fprintf(hFile, "<tr><td>%u</td><td", i+1); if(Sprite->IndexData && iff_depalette(Sprite, PaletteData)){ WritePNG(filename, NULL, 0, Sprite, NULL, NULL); fprintf(hFile, "><img src=\"%s_%u_%.4x_%u.png\" width=\"%u\" height=\"%u\" alt=\"\" />", spr1 ? "spr1" : "spr2", c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height); if(!spr1){ sprintf(filename, "%sspr2_%u_%.4x_%u_z.png", OutDir, c+1, ChunkData->ChunkID, i+1); if(Sprite->ZBuffer){ WritePNG(filename, NULL, 1, Sprite, NULL, NULL); fprintf(hFile, "</td><td><img src=\"spr2_%u_%.4x_%u_z.png\" width=\"%u\" height=\"%u\" alt=\"\" />", c+1, ChunkData->ChunkID, i+1, Sprite->Width, Sprite->Height); }else fprintf(hFile, "None provided"); } }else fprintf(hFile, Sprite->InvalidDimensions ? "%sBlank sprite" : "%sThis sprite cannot be displayed.", !spr1 ? " colspan=\"2\">" : ">"); fprintf(hFile, "</td></tr>\n"); } fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "DGRP")){ /**** ** DGRP parsing */ IFFDrawGroup * Group = ChunkData->FormattedData; IFFDrawAngle * Angle; IFFSpriteInfo * Sprite; unsigned i,j; const char * Zooms[] = {"Far", "Middle", "Close"}; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Group->Version); fprintf(hFile, "</table>\n"); fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th>Direction</th><th>Zoom</th><th colspan=\"6\">Sprite</th></tr>\n"); for(i=0, Angle=Group->DrawAngles; i<12; i++, Angle++){ const char * Direction = (Angle->Direction == IFFDIRECTION_NORTHEAST) ? "North east" : (Angle->Direction == IFFDIRECTION_SOUTHEAST) ? "South east" : (Angle->Direction == IFFDIRECTION_NORTHWEST) ? "North west" : "South west"; if(Angle->SpriteCount){ fprintf(hFile, "<tr><td rowspan=\"%u\">%s</td><td rowspan=\"%u\">%s</td>" "<th>#</th><th>Type</th><th>Chunk ID</th><th>Sprite index</th>" "<th>Flags</th><th>Sprite offset</th><th>Object offset</th></tr>\n", 1+Angle->SpriteCount, Direction, 1+Angle->SpriteCount, Zooms[Angle->Zoom-1]); for(j=0, Sprite = Angle->SpriteInfo; j<Angle->SpriteCount; j++, Sprite++) fprintf(hFile, "<tr><td>%u</td><td>%u</td><td>%.4X</td><td>%u</td><td>%u</td>" "<td>(%+d,%+d)</td><td>(%+g,%+g,%+g)</td></tr>", j+1, Sprite->Type, Sprite->ChunkID, Sprite->SpriteIndex, Sprite->Flags, Sprite->SpriteX, Sprite->SpriteY, Sprite->ObjectX, Sprite->ObjectY, Sprite->ObjectZ); }else{ fprintf(hFile, "<tr><td>%s</td><td>%s</td><td>None specified</td></tr>", Direction, Zooms[Angle->Zoom-1]); } } fprintf(hFile, "</table>\n"); }else if(!strcmp(ChunkData->Type, "BHAV")){ /**** ** BHAV parsing */ IFFBehavior * Behavior = ChunkData->FormattedData; IFFInstruction * Instruction; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Behavior->Version); fprintf(hFile, "<tr><td>Type:</td><td>%u</td></tr>\n", Behavior->Type); fprintf(hFile, "<tr><td>Arguments:</td><td>%u</td></tr>\n", Behavior->ArgumentCount); fprintf(hFile, "<tr><td>Locals:</td><td>%u</td></tr>\n", Behavior->LocalCount); fprintf(hFile, "<tr><td>Flags:</td><td>%.4X</td></tr>\n", Behavior->Flags); fprintf(hFile, "</table>\n"); if(Behavior->InstructionCount > 0){ unsigned i; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Opcode</th><th>T-Dest</th><th>F-Dest</th><th>Operand data</th></tr>\n"); for(i=0, Instruction = Behavior->Instructions; i<Behavior->InstructionCount; i++, Instruction++) fprintf(hFile, "<tr><td>%u</td><td><tt>%.4X</tt></td><td>%u</td><td>%u</td>" "<td><tt>%.2X %.2X %.2X %.2X %.2X %.2X %.2X %.2X</tt></td></tr>\n", i, Instruction->Opcode, Instruction->TDest, Instruction->FDest, Instruction->Operands[0], Instruction->Operands[1], Instruction->Operands[2], Instruction->Operands[3], Instruction->Operands[4], Instruction->Operands[5], Instruction->Operands[6], Instruction->Operands[7]); fprintf(hFile, "</table>\n"); } }else if(!strcmp(ChunkData->Type, "OBJf")){ /**** ** OBJf parsing */ IFFFunctionTable * Table = ChunkData->FormattedData; fprintf(hFile, "<table>\n"); fprintf(hFile, "<tr><td>Version:</td><td>%u</td></tr>\n", Table->Version); fprintf(hFile, "</table>\n"); if(Table->FunctionCount > 0){ unsigned i; fprintf(hFile, "<br />\n"); fprintf(hFile, "<table class=\"center\">\n"); fprintf(hFile, "<tr><th colspan=\"2\">Condition function</th><th>Action function</th></tr>\n"); for(i=0; i<Table->FunctionCount; i++) fprintf(hFile, "<tr><td>%u</td><td>%.4X</td><td>%.4X</td></tr>\n", i+1, Table->Functions[i].ConditionID, Table->Functions[i].ActionID); fprintf(hFile, "</table>\n"); } }else{ fprintf(hFile, "The contents of this chunk cannot be shown on this page.\n"); } fprintf(hFile, "</div>\n\n"); } iff_delete(IFFFileInfo); fprintf(hFile, "<div id=\"footer\">This page was generated by the use of <a href=\"http://www.niotso.org/\">iff2html</a>.\n"); fprintf(hFile, "The content of this page may be subject to copyright by the author(s) of the original iff file.</div>\n"); fprintf(hFile, "</body>\n"); fprintf(hFile, "</html>"); fclose(hFile); printf("Wrote contents to '%s'.\n", OutFile); return 0; }