Need a unique gift idea?
A Pastebin account makes a great Christmas gift
SHARE
TWEET

bin2h v0.1

8bitbubsy Oct 18th, 2018 (edited) 35 Never
Upgrade to PRO!
ENDING IN00days00hours00mins00secs
 
  1. #ifdef _WIN32
  2. #define WIN32_LEAN_AND_MEAN
  3. #include <windows.h>
  4. #include <shlwapi.h>
  5. #endif
  6. #include <stdio.h>
  7. #include <string.h> /* stricmp() */
  8. #include <stdlib.h> /* atoi()    */
  9. #include <ctype.h>  /* toupper() */
  10. #include <stdint.h>
  11. #include <stdbool.h>
  12.  
  13. #define CLAMP(x, low, high) (((x) > (high)) ? (high) : (((x) < (low)) ? (low) : (x)))
  14.  
  15. #define IO_BUF_SIZE        4096
  16. #define MAX_NAME_LEN       64
  17. #define DATA_NAME          "hdata" /* this has to be a legal C variable name */
  18. #define BYTES_PER_LINE     24
  19. #define MAX_MEGABYTES_IN   4
  20. #define MIN_BYTES_PER_LINE 1
  21. #define MAX_BYTES_PER_LINE 64
  22.  
  23. static char fileNameOut[MAX_NAME_LEN + 8], dataType[32];
  24. static char dataName[MAX_NAME_LEN + 1], dataNameUpper[MAX_NAME_LEN + 1];
  25. static bool useConstFlag = true, addZeroFlag = false;
  26. static size_t fileSize, bytesPerLine = BYTES_PER_LINE, dataNameLen;
  27.  
  28. #ifdef _WIN32
  29. static void setDirToExecutablePath(void);
  30. #endif
  31.  
  32. static void setNewDataName(const char *name);
  33. static bool handleArguments(int argc, char *argv[]);
  34. static bool compareFileNames(const char *path1, const char *path2);
  35. static bool setAndTestFileSize(FILE *f);
  36. static bool writeHeader(FILE *f);
  37.  
  38. int main(int argc, char *argv[])
  39. {
  40.     const char hex2ch[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
  41.     uint8_t byte, readBuffer[IO_BUF_SIZE], writeBuffer[IO_BUF_SIZE * 6]; /* don't mess with the sizes here */
  42.     size_t i, lineEntry, readLength, writeLength, bytesWritten;
  43.     FILE *fIn, *fOut;
  44.  
  45. #ifdef _WIN32 /* path is not set to cwd in XP (with VS2017 runtime) for some reason */
  46.     setDirToExecutablePath();
  47. #endif
  48.  
  49.     strcpy(dataType, "uint8_t");
  50.     setNewDataName(DATA_NAME);
  51.  
  52.     printf("bin2h v0.1 - by 8bitbubsy 2018 - Converts a binary to a C include file\n");
  53.     printf("======================================================================\n");
  54.  
  55.     /* handle input arguments */
  56.     if (!handleArguments(argc, argv))
  57.         return (-1);
  58.  
  59.     /* test if the output file is the same as the input file (illegal) */
  60.     if (compareFileNames(argv[1], fileNameOut))
  61.     {
  62.         printf("Error: Output file can't be the same as input file!\n");
  63.         return (1);
  64.     }
  65.  
  66.     /* open input file */
  67.     fIn = fopen(argv[1], "rb");
  68.     if (fIn == NULL)
  69.     {
  70.         printf("Error: Could not open input file for reading!\n");
  71.         return (1);
  72.     }
  73.  
  74.     /* get filesize and test if it's 0 or too high */
  75.     if (!setAndTestFileSize(fIn))
  76.     {
  77.         fclose(fIn);
  78.         return (1);
  79.     }
  80.  
  81.     /* open output file */
  82.     fOut = fopen(fileNameOut, "w");
  83.     if (fOut == NULL)
  84.     {
  85.         fclose(fIn);
  86.  
  87.         printf("Error: Could not open data.h for writing!\n");
  88.         return (1);
  89.     }
  90.  
  91.     /* write .h header */
  92.     if (!writeHeader(fOut))
  93.         goto IOError;
  94.  
  95.     /* write main data */
  96.  
  97.     printf("Reading/writing from/to files...\n");
  98.  
  99.     bytesWritten = 0;
  100.     while (!feof(fIn))
  101.     {
  102.         readLength = fread(readBuffer, 1, IO_BUF_SIZE, fIn);
  103.  
  104.         writeLength = 0;
  105.         for (i = 0; i < readLength; ++i)
  106.         {
  107.             lineEntry = bytesWritten % bytesPerLine;
  108.  
  109.             /* put tab if we're at the start of a line */
  110.             if (lineEntry == 0)
  111.                 writeBuffer[writeLength++] = '\t';
  112.  
  113.             /* write table entry */
  114.  
  115.             byte = readBuffer[i];
  116.             if (bytesWritten == (fileSize - 1))
  117.             {
  118.                 /* last byte in table */
  119.  
  120.                 if (addZeroFlag) /* fileSize is increased by one if addZeroFlag = true */
  121.                 {
  122.                     writeBuffer[writeLength++] = '\0';
  123.                 }
  124.                 else
  125.                 {
  126.                     /* "0xXX" */
  127.                     writeBuffer[writeLength++] = '0';
  128.                     writeBuffer[writeLength++] = 'x';
  129.                     writeBuffer[writeLength++] = hex2ch[byte >> 4];
  130.                     writeBuffer[writeLength++] = hex2ch[byte & 15];
  131.                 }
  132.             }
  133.             else
  134.             {
  135.                 /* "0xXX," */
  136.                 writeBuffer[writeLength++] = '0';
  137.                 writeBuffer[writeLength++] = 'x';
  138.                 writeBuffer[writeLength++] = hex2ch[byte >> 4];
  139.                 writeBuffer[writeLength++] = hex2ch[byte & 15];
  140.                 writeBuffer[writeLength++] = ',';
  141.             }
  142.  
  143.             /* put linefeed if we're at the end of a line (or at the last byte entry) */
  144.             if ((lineEntry == (bytesPerLine - 1)) || (bytesWritten == (fileSize - 1)))
  145.                 writeBuffer[writeLength++] = '\n';
  146.  
  147.             bytesWritten++;
  148.         }
  149.  
  150.         if (fwrite(writeBuffer, 1, writeLength, fOut) != writeLength)
  151.             goto IOError;
  152.     }
  153.  
  154.     if (bytesWritten != fileSize)
  155.         goto IOError;
  156.  
  157.     /* write .h footer */
  158.     if (fprintf(fOut, "};\n")     < 0) goto IOError;
  159.     if (fprintf(fOut, "\n")       < 0) goto IOError;
  160.     if (fprintf(fOut, "#endif\n") < 0) goto IOError;
  161.  
  162.     fclose(fOut);
  163.     fclose(fIn);
  164.  
  165.     printf("%d bytes sucessfully written to \"%s\".\n", fileSize, fileNameOut);
  166.     return (0);
  167.  
  168. IOError:
  169.     fclose(fOut);
  170.     fclose(fIn);
  171.  
  172.     printf("Error: General I/O fault during reading/writing!\n");
  173.     return (1);
  174. }
  175.  
  176. #ifdef _WIN32
  177. static void setDirToExecutablePath(void)
  178. {
  179.     char path[MAX_PATH];
  180.  
  181.     GetModuleFileName(GetModuleHandle(NULL), path, MAX_PATH);
  182.     PathRemoveFileSpec(path);
  183.     SetCurrentDirectory(path);
  184.  
  185.     /* we don't care if this fails or not, so no error checking for now */
  186. }
  187. #endif
  188.  
  189. static bool dataNameIsValid(const char *s, size_t len)
  190. {
  191.     bool charIsValid;
  192.     size_t i;
  193.  
  194.     for (i = 0; i < len; ++i)
  195.     {
  196.         if ((i == 0) && ((s[i] >= '0') && (s[i] <= '9')))
  197.             return (false); /* a C variable can't start with a digit */
  198.  
  199.         charIsValid = ((s[i] >= '0') && (s[i] <= '9')) ||
  200.                       ((s[i] >= 'a') && (s[i] <= 'z')) ||
  201.                       ((s[i] >= 'A') && (s[i] <= 'Z'));
  202.  
  203.         if (!charIsValid)
  204.             return (false);
  205.     }
  206.  
  207.     return (true);
  208. }
  209.  
  210. static void setNewDataName(const char *name)
  211. {
  212.     size_t i;
  213.  
  214.     strncpy(dataName, name, sizeof (dataName) - 1);
  215.     dataNameLen = strlen(dataName);
  216.     sprintf(fileNameOut, "%s.h", dataName);
  217.  
  218.     /* maker upper case version of dataName */
  219.     for (i = 0; i < dataNameLen; ++i)
  220.         dataNameUpper[i] = (char)(toupper(dataName[i]));
  221.     dataNameUpper[i] = '\0';
  222.  
  223.     /* test if dataName is valid for use in a C header */
  224.     if (!dataNameIsValid(dataName, dataNameLen))
  225.     {
  226.         strcpy(dataName, DATA_NAME);
  227.         printf("Warning: Data name was illegal and was set to default (%s).\n", DATA_NAME);
  228.     }
  229. }
  230.  
  231. static bool handleArguments(int argc, char *argv[])
  232. {
  233.     int32_t i;
  234.  
  235.     if (argc < 2)
  236.     {
  237.         printf("Usage: bin2h <binary> [options]\n");
  238.         printf("\n");
  239.         printf("Options:\n");
  240.         printf(" --no-const   Don't declare data as const\n");
  241.         printf(" --signed     Declare data as signed instead of unsigned\n");
  242.         printf(" --terminate  Insert a zero after the data (also increases length constant by 1)\n");
  243.         printf(" -n <name>    Set data name (max %d chars, a-zA-Z0-9_, default = %s)\n", MAX_NAME_LEN, DATA_NAME);
  244.         printf(" -b <num>     Set amount of bytes per line in data table (%d..%d, default = %d)\n",
  245.             MIN_BYTES_PER_LINE, MAX_BYTES_PER_LINE, BYTES_PER_LINE);
  246.  
  247.         return (false);
  248.     }
  249.     else
  250.     {
  251.         for (i = 0; i < argc; ++i)
  252.         {
  253.             if (_stricmp(argv[i], "--no-const") == 0)
  254.             {
  255.                 useConstFlag = false;
  256.             }
  257.             if (_stricmp(argv[i], "--terminate") == 0)
  258.             {
  259.                 addZeroFlag = true;
  260.             }
  261.             if (_stricmp(argv[i], "--signed") == 0)
  262.             {
  263.                 strcpy(dataType, "int8_t");
  264.             }
  265.             else if (_stricmp(argv[i], "-n") == 0)
  266.             {
  267.                 if (i < (argc - 1))
  268.                     setNewDataName(argv[i + 1]);
  269.             }
  270.             else if (_stricmp(argv[i], "-b") == 0)
  271.             {
  272.                 if (i < (argc - 1))
  273.                     bytesPerLine = CLAMP(atoi(argv[i + 1]), MIN_BYTES_PER_LINE, MAX_BYTES_PER_LINE);
  274.             }
  275.         }
  276.     }
  277.  
  278.     return (true);
  279. }
  280.  
  281. /* compares two filenames (mixed full path or not, case insensitive) */
  282. static bool compareFileNames(const char *path1, const char *path2)
  283. {
  284.     char sep;
  285.     const char *p1, *p2;
  286.     size_t i, l1, l2;
  287.  
  288.     if ((path1 == NULL) || (path2 == NULL))
  289.        return (false); /* error */
  290.  
  291. #ifdef _WIN32
  292.    sep = '\\';
  293. #else
  294.    sep = '/';
  295. #endif
  296.  
  297.     /* set pointers to first occurrences of separator in paths */
  298.     p1 = strrchr(path1, sep);
  299.     p2 = strrchr(path2, sep);
  300.  
  301.     if (p1 == NULL)
  302.     {
  303.         /* separator not found, point to start of path */
  304.         p1 = path1;
  305.         l1 = strlen(p1);
  306.     }
  307.     else
  308.     {
  309.         /* separator found, increase pointer by 1 if we have room */
  310.         l1 = strlen(p1);
  311.         if (l1 > 0)
  312.         {
  313.             p1++;
  314.             l1--;
  315.         }
  316.     }
  317.  
  318.     if (p2 == NULL)
  319.     {
  320.         /* separator not found, point to start of path */
  321.         p2 = path2;
  322.         l2 = strlen(p2);
  323.     }
  324.     else
  325.     {
  326.         /* separator found, increase pointer by 1 if we have room */
  327.         l2 = strlen(p2);
  328.         if (l2 > 0)
  329.         {
  330.             p2++;
  331.             l2--;
  332.         }
  333.     }
  334.  
  335.     if (l1 != l2)
  336.         return (false); /* definitely not the same */
  337.  
  338.     /* compare strings */
  339.     for (i = 0; i < l1; ++i)
  340.     {
  341.         if (tolower(p1[i]) != tolower(p2[i]))
  342.             return (false); /* not the same */
  343.     }
  344.  
  345.     return (true); /* both filenames are the same */
  346. }
  347.  
  348. static bool setAndTestFileSize(FILE *f)
  349. {
  350.     fseek(f, 0, SEEK_END);
  351.     fileSize = ftell(f);
  352.     rewind(f);
  353.  
  354.     if (fileSize == 0)
  355.     {
  356.         printf("Error: Input file is empty!\n");
  357.         return (false);
  358.     }
  359.  
  360.     if (fileSize > (MAX_MEGABYTES_IN * (1024UL * 1024UL)))
  361.     {
  362.         printf("Error: The input filesize is over %dMB. This program is meant for small files!\n", MAX_MEGABYTES_IN);
  363.         return (false);
  364.     }
  365.  
  366.     if (addZeroFlag)
  367.         fileSize++; /* make room for zero */
  368.  
  369.     return (true);
  370. }
  371.  
  372. static bool writeHeader(FILE *f)
  373. {
  374.     if (fprintf(f, "#ifndef __%s_H\n", dataNameUpper)                 < 0) return (false);
  375.     if (fprintf(f, "#define __%s_H\n", dataNameUpper)                 < 0) return (false);
  376.     if (fprintf(f, "\n")                                              < 0) return (false);
  377.     if (fprintf(f, "#include <stdint.h>\n")                           < 0) return (false);
  378.     if (fprintf(f, "\n")                                              < 0) return (false);
  379.     if (fprintf(f, "#define %s_LENGTH %d\n", dataNameUpper, fileSize) < 0) return (false);
  380.     if (fprintf(f, "\n")                                              < 0) return (false);
  381.  
  382.     if (useConstFlag)
  383.     {
  384.         if (fprintf(f, "const %s %s[%s_LENGTH] =\n", dataType, dataName, dataNameUpper) < 0)
  385.             return (false);
  386.     }
  387.     else
  388.     {
  389.         if (fprintf(f, "%s %s[%s_LENGTH] =\n", dataType, dataName, dataNameUpper) < 0)
  390.             return (false);
  391.     }
  392.  
  393.     if (fprintf(f, "{\n") < 0)
  394.         return (false);
  395.  
  396.     return (true);
  397. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top