Mercurial > hg > dmlib
diff data2inc.c @ 407:59244a7ae37f
Move c64 utilities to the engine lib, as we benefit from a common framework.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Sat, 03 Nov 2012 02:19:51 +0200 |
parents | |
children | 9d668e48961c |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/data2inc.c Sat Nov 03 02:19:51 2012 +0200 @@ -0,0 +1,404 @@ +/* + * data2inc - Convert binary data to "C"-source or XA-compatible include file + * Programmed and designed by Matti 'ccr' Hamalainen + * (C) Copyright 2003,2009-2012 Tecnic Software productions (TNSP) + * + * Please read file 'COPYING' for information on license and distribution. + */ +#include <errno.h> +#include "dmlib.h" +#include "dmargs.h" +#include "dmmutex.h" + +#define RA_LINEBUF (16) + +enum +{ + FMT_AUTO = 0, + FMT_C, + FMT_ASM +}; + +char *optInFilename = NULL, + *optOutFilename = NULL, + *optObjName = "default_object", + *optDataType = NULL, + *optAddLine = NULL; + +int optIndentation = -1; +int optFormat = FMT_AUTO; +BOOL optHexMode = FALSE, + optQuiet = FALSE, + optExtraData = FALSE, + optFormatting = TRUE; + + +void (*writeHeader) (FILE *, char *) = NULL; +void (*writeDecl) (FILE *, size_t, char *) = NULL; +void (*writeData) (FILE *, Uint8 *, size_t) = NULL; +void (*writeFooter) (FILE *, size_t, char *) = NULL; + + +static DMOptArg optList[] = +{ + { 0, '?', "help", "Show this help", OPT_NONE }, + { 4, 'A', "format-asm", "Output in XA-compatible asm", OPT_NONE }, + { 5, 'C', "format-c", "Output in ANSI C", OPT_NONE }, + { 1, 'n', "name", "Set object name", OPT_ARGREQ }, + { 2, 't', "type", "Set datatype (unsigned char/byte)", OPT_ARGREQ }, + { 3, 'a', "add-line", "Add this line to start of file", OPT_ARGREQ }, + { 6, 'x', "hexadecimal", "Use hexadecimal output", OPT_NONE }, + { 7, 'q', "quiet", "Do not add comments", OPT_NONE }, + { 8, 'f', "no-formatting", "Disable additional output formatting", OPT_NONE }, + { 9, 'i', "indentation", "Set indentation (negative value = tab)", OPT_ARGREQ }, + { 10, 'e', "extra-data", "Add object end labels and size in asm output", OPT_NONE }, +}; + +static const int optListN = sizeof(optList) / sizeof(optList[0]); + + +void argShowHelp() +{ + dmPrintBanner(stdout, dmProgName, + "[options] [sourcefile] [destfile]"); + + dmArgsPrintHelp(stdout, optList, optListN); + + printf( + "\n" + "To convert a data file to a C structure using 'Uint8' as type:\n" + "$ data2inc -C -n variable_name -t Uint8 input.bin output.h\n" + "\n" + ); +} + + +BOOL argHandleOpt(const int optN, char *optArg, char *currArg) +{ + switch (optN) + { + case 0: + argShowHelp(); + exit(0); + break; + + case 1: + optObjName = optArg; + break; + + case 2: + optDataType = optArg; + break; + + case 3: + optAddLine = optArg; + break; + + case 4: + optFormat = FMT_ASM; + break; + case 5: + optFormat = FMT_C; + break; + case 6: + optHexMode = TRUE; + break; + case 7: + optQuiet = TRUE; + break; + case 8: + optFormatting = FALSE; + break; + + case 9: + optIndentation = atoi(optArg); + break; + + case 10: + optExtraData = TRUE; + break; + + default: + dmError("Unknown option '%s'.\n", currArg); + return FALSE; + } + + return TRUE; +} + + +BOOL argHandleFile(char * currArg) +{ + if (!optInFilename) + optInFilename = currArg; + else + if (!optOutFilename) + optOutFilename = currArg; + else + dmError("Source and destination filenames already specified, extraneous argument '%s'.\n", currArg); + + return TRUE; +} + + +/* Assembler include data output functions + */ +void writeHeader_ASM(FILE * f, char *name) +{ + if (name) + fprintf(f, "; '%s'", name); + else + fprintf(f, "; Generated"); + fprintf(f, " by %s v%s\n", + dmProgName, dmProgVersion); +} + +void writeDecl_ASM(FILE * f, size_t len, char *name) +{ + if (optExtraData) + fprintf(f, "%s_size = %u\n", name, len); + fprintf(f, "%s:\n", name); +} + +void writeData_ASM(FILE * f, Uint8 * buf, size_t len) +{ + size_t i; + + fprintf(f, "%s ", optDataType); + for (i = 0; i < len; i++) + { + if (optFormatting) + { + if (optHexMode) + fprintf(f, "$%.2x", buf[i]); + else + fprintf(f, "%3d", buf[i]); + } + else + { + if (optHexMode) + fprintf(f, "$%x", buf[i]); + else + fprintf(f, "%d", buf[i]); + } + + if (i < (len - 1)) + fprintf(f, ","); + } +} + +void writeFooter_ASM(FILE * f, size_t len, char *name) +{ + (void) len; + if (optExtraData) + fprintf(f, "%s_end: \n", name); + else + fprintf(f, "\n"); +} + + +/* ANSI-C include data output functions + */ +void writeHeader_C(FILE * f, char *name) +{ + if (name) + fprintf(f, "/* '%s' generated", name); + else + fprintf(f, "/* Generated"); + + fprintf(f, " by %s v%s\n" " */\n", + dmProgName, dmProgVersion); +} + +void writeDecl_C(FILE * f, size_t len, char *name) +{ + fprintf(f, "const %s %s[%u] = {\n", + optDataType, name, len); + + printf("extern const %s %s[%u];\n", + optDataType, name, len); +} + +void writeData_C(FILE * f, Uint8 * buf, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + { + if (optFormatting) + { + if (optHexMode) + fprintf(f, "0x%.2x", buf[i]); + else + fprintf(f, "%3d", buf[i]); + } + else + { + if (optHexMode) + fprintf(f, "0x%x", buf[i]); + else + fprintf(f, "%d", buf[i]); + } + + fprintf(f, ","); + } +} + +void writeFooter_C(FILE * f, size_t len, char *name) +{ + (void) len; + (void) name; + fprintf(f, "};\n"); +} + + +off_t dmGetFileSize(FILE *f) +{ + off_t len, pos = ftell(f); + fseeko(f, 0, SEEK_END); + len = ftell(f); + fseek(f, pos, SEEK_SET); + return len; +} + + +int main(int argc, char *argv[]) +{ + FILE *sfile = NULL, *dfile = NULL; + off_t inSize; + Uint8 inBuf[RA_LINEBUF]; + int tmpRes; + + /* Initialize */ + dmInitProg("data2inc", "Data to include converter", "0.6", NULL, NULL); + dmVerbosity = 0; + + /* Parse arguments */ + if (!dmArgsProcess(argc, argv, optList, optListN, + argHandleOpt, argHandleFile, TRUE)) + exit(1); + + /* Determine output type, if not specified */ + if (optFormat == FMT_AUTO) + { + char *dext; + + if (optOutFilename == NULL) + { + dmError("Output format not specified and no output filename given (try --help)\n"); + exit(1); + } + + /* Check filename extension */ + dext = strrchr(optOutFilename, '.'); + if (dext) + { + dext++; + if (!strcasecmp(dext, "c") || !strcasecmp(dext, "h") || + !strcasecmp(dext, "cc") || !strcasecmp(dext, "cpp") || + !strcasecmp(dext, "hpp") || !strcasecmp(dext, "c++")) + optFormat = FMT_C; + else + optFormat = FMT_ASM; + } else + optFormat = FMT_ASM; + } + + /* Set functions */ + switch (optFormat) + { + case FMT_ASM: + if (!optDataType) + optDataType = ".byte"; + + writeHeader = writeHeader_ASM; + writeDecl = writeDecl_ASM; + writeData = writeData_ASM; + writeFooter = writeFooter_ASM; + break; + + case FMT_C: + if (!optDataType) + optDataType = "unsigned char"; + + writeHeader = writeHeader_C; + writeDecl = writeDecl_C; + writeData = writeData_C; + writeFooter = writeFooter_C; + break; + + case FMT_AUTO: + default: + dmError("Internal error, FMT_AUTO at output function init.\n"); + exit(2); + } + + /* Open the files */ + if (optInFilename == NULL) + sfile = stdin; + else + if ((sfile = fopen(optInFilename, "rb")) == NULL) + { + tmpRes = errno; + dmError("Error opening input file '%s'. (%s)\n", + optInFilename, strerror(tmpRes)); + exit(3); + } + + if (optOutFilename == NULL) + dfile = stdout; + else + if ((dfile = fopen(optOutFilename, "wa")) == NULL) + { + tmpRes = errno; + dmError("Error creating output file '%s'. (%s)\n", + optOutFilename, strerror(tmpRes)); + exit(4); + } + + /* Get sourcefile size */ + inSize = dmGetFileSize(sfile); + + /* Output header */ + if (!optQuiet) + writeHeader(dfile, optOutFilename); + + if (optAddLine) + fprintf(dfile, "%s\n", optAddLine); + + /* Output declaration */ + writeDecl(dfile, inSize, optObjName); + + /* Output data */ + while (!feof(sfile)) + { + tmpRes = fread(inBuf, sizeof(Uint8), RA_LINEBUF, sfile); + if (tmpRes > 0) + { + if (optIndentation < 0) + fprintf(dfile, "\t"); + else + if (optIndentation > 0) + { + int i; + for (i = 0; i < optIndentation; i++) + fputs(" ", dfile); + } + + writeData(dfile, inBuf, tmpRes); + + fprintf(dfile, "\n"); + } + } + + + /* Output footer */ + writeFooter(dfile, inSize, optObjName); + + /* Exit */ + fclose(sfile); + fclose(dfile); + + exit(0); + return 0; +}