Author Topic: Embedding files in programs (FileToDATA convertor) by RhoSigma  (Read 4838 times)

0 Members and 1 Guest are viewing this topic.

Offline Junior Librarian

  • Moderator
  • Newbie
  • Posts: 19
Embedding files in programs (FileToDATA convertor) by RhoSigma
« on: October 31, 2021, 06:06:52 am »
Embedding files in programs (FileToDATA convertor)

Author: @RhoSigma
Source: qb64.org Forum
URL: https://www.qb64.org/forum/index.php?topic=790.0
Version: October 04 2021


Description:
These two programs I use a lot.  These goodies got an complete overhaul and are now using the LZW packer/unpacker, which I've released. So this is a good opportunity to make it available again for everybody.  MakeDATA.bas Create a DATA block out of the given file, so you can embed it in your program and write it back when needed.  The DATAs are written into a .bm file.   MakeCARR.bas will do the whole thing in an array on C/C++ level, rather then in DATAs on the QB64 level. Although it's handling is a bit more tricky, as you get not only a .bm file, but also a .h file, and both must match (ie. the DECLARE LIBRARY path in the .bm must point to the .h), this approach has several advantages.

Both of the following tools require the 'lzwpacker.bm' file.


The .bm file is to be found in the author's Libraries Collection https://www.qb64.org/forum/index.php?topic=809

Source Code MakeDATA.bas:
Code: QB64: [Select]
  1.     '+---------------+---------------------------------------------------+
  2.     '| ###### ###### |     .--. .         .-.                            |
  3.     '| ##  ## ##   # |     |   )|        (   ) o                         |
  4.     '| ##  ##  ##    |     |--' |--. .-.  `-.  .  .-...--.--. .-.        |
  5.     '| ######   ##   |     |  \ |  |(   )(   ) | (   ||  |  |(   )       |
  6.     '| ##      ##    |     '   `'  `-`-'  `-'-' `-`-`|'  '  `-`-'`-      |
  7.     '| ##     ##   # |                            ._.'                   |
  8.     '| ##     ###### |  Sources & Documents placed in the Public Domain. |
  9.     '+---------------+---------------------------------------------------+
  10.     '|                                                                   |
  11.     '| === MakeDATA.bas ===                                              |
  12.     '|                                                                   |
  13.     '| == Create a DATA block out of the given file, so you can embed it |
  14.     '| == in your program and write it back when needed.                 |
  15.     '|                                                                   |
  16.     '| == The DATAs are written into a .bm file together with a ready to |
  17.     '| == use write back FUNCTION. You just $INCLUDE this .bm file into  |
  18.     '| == your program and call the write back FUNCTION somewhere.       |
  19.     '|                                                                   |
  20.     '| == This program needs the 'lzwpacker.bm' file available from the  |
  21.     '| == Libraries Collection here:                                     |
  22.     '| ==      https://www.qb64.org/forum/index.php?topic=809            |
  23.     '| == as it will try to pack the given file to keep the DATA block   |
  24.     '| == as small as possible. If compression is successful, then your  |
  25.     '| == program also must $INCLUDE 'lzwpacker.bm' to be able to unpack |
  26.     '| == the file data again for write back. MakeDATA.bas is printing   |
  27.     '| == a reminder message in such a case.                             |
  28.     '|                                                                   |
  29.     '+-------------------------------------------------------------------+
  30.     '| Done by RhoSigma, R.Heyder, provided AS IS, use at your own risk. |
  31.     '| Find me in the QB64 Forum or mail to support&rhosigma-cw.net for  |
  32.     '| any questions or suggestions. Thanx for your interest in my work. |
  33.     '+-------------------------------------------------------------------+
  34.      
  35.     '--- if you wish, set any default paths, end with a backslash ---
  36.     srcPath$ = "" 'source path
  37.     tarPath$ = "" 'target path
  38.     '-----
  39.     IF srcPath$ <> "" THEN
  40.         COLOR 15: PRINT "Default source path: ": COLOR 7: PRINT srcPath$: PRINT
  41.     END IF
  42.     IF tarPath$ <> "" THEN
  43.         COLOR 15: PRINT "Default target path: ": COLOR 7: PRINT tarPath$: PRINT
  44.     END IF
  45.      
  46.     '--- collect inputs (relative paths allowed, based on default paths) ---
  47.     source:
  48.     LINE INPUT "Source Filename: "; src$ 'any file you want to put into DATAs
  49.     IF src$ = "" GOTO source
  50.     target:
  51.     LINE INPUT "Target Basename: "; tar$ 'write stuff into this file (.bm is added)
  52.     IF tar$ = "" GOTO target
  53.     '-----
  54.     ON ERROR GOTO abort
  55.     OPEN "I", #1, srcPath$ + src$: CLOSE #1 'file exist check
  56.     OPEN "O", #2, tarPath$ + tar$ + ".bm": CLOSE #2 'path exist check
  57.     ON ERROR GOTO 0
  58.      
  59.     '--- separate source filename part ---
  60.     FOR po% = LEN(src$) TO 1 STEP -1
  61.         IF MID$(src$, po%, 1) = "\" OR MID$(src$, po%, 1) = "/" THEN
  62.             srcName$ = MID$(src$, po% + 1)
  63.             EXIT FOR
  64.         ELSEIF po% = 1 THEN
  65.             srcName$ = src$
  66.         END IF
  67.     NEXT po%
  68.     '--- separate target filename part ---
  69.     FOR po% = LEN(tar$) TO 1 STEP -1
  70.         IF MID$(tar$, po%, 1) = "\" OR MID$(tar$, po%, 1) = "/" THEN
  71.             tarName$ = MID$(tar$, po% + 1)
  72.             EXIT FOR
  73.         ELSEIF po% = 1 THEN
  74.             tarName$ = tar$
  75.         END IF
  76.     NEXT po%
  77.     MID$(tarName$, 1, 1) = UCASE$(MID$(tarName$, 1, 1)) 'capitalize 1st letter
  78.      
  79.     '--- init ---
  80.     OPEN "B", #1, srcPath$ + src$
  81.     filedata$ = SPACE$(LOF(1))
  82.     GET #1, , filedata$
  83.     CLOSE #1
  84.     rawdata$ = LzwPack$(filedata$, 20)
  85.     IF rawdata$ <> "" THEN
  86.         OPEN "O", #1, tarPath$ + tar$ + ".lzw"
  87.         CLOSE #1
  88.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  89.         PUT #1, , rawdata$
  90.         CLOSE #1
  91.         packed% = -1
  92.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  93.     ELSE
  94.         packed% = 0
  95.         OPEN "B", #1, srcPath$ + src$
  96.     END IF
  97.     fl& = LOF(1)
  98.     cntL& = INT(fl& / 32)
  99.     cntB& = (fl& - (cntL& * 32))
  100.      
  101.     '--- .bm include file ---
  102.     OPEN "O", #2, tarPath$ + tar$ + ".bm"
  103.     PRINT #2, "'============================================================"
  104.     PRINT #2, "'=== This file was created with MakeDATA.bas by RhoSigma, ==="
  105.     PRINT #2, "'=== you must $INCLUDE this at the end of your program.   ==="
  106.     IF packed% THEN
  107.         PRINT #2, "'=== ---------------------------------------------------- ==="
  108.         PRINT #2, "'=== If your program is NOT a GuiTools based application, ==="
  109.         PRINT #2, "'=== then it must also $INCLUDE: 'lzwpacker.bm' available ==="
  110.         PRINT #2, "'=== from the Libraries Collection here:                  ==="
  111.         PRINT #2, "'===    https://www.qb64.org/forum/index.php?topic=809    ==="
  112.     END IF
  113.     PRINT #2, "'============================================================"
  114.     PRINT #2, ""
  115.     '--- writeback function ---
  116.     PRINT #2, "'"; STRING$(LEN(tarName$) + 18, "-")
  117.     PRINT #2, "'--- Write"; tarName$; "Data$ ---"
  118.     PRINT #2, "'"; STRING$(LEN(tarName$) + 18, "-")
  119.     PRINT #2, "' This function will write the DATAs you've created with MakeDATA.bas"
  120.     PRINT #2, "' back to disk and so it rebuilds the original file."
  121.     PRINT #2, "'"
  122.     PRINT #2, "' After the writeback call, only use the returned realFile$ to access the"
  123.     PRINT #2, "' written file. It's your given path, but with an maybe altered filename"
  124.     PRINT #2, "' (number added) in order to avoid the overwriting of an already existing"
  125.     PRINT #2, "' file with the same name in the given location."
  126.     PRINT #2, "'----------"
  127.     PRINT #2, "' SYNTAX:"
  128.     PRINT #2, "'   realFile$ = Write"; tarName$; "Data$ (wantFile$)"
  129.     PRINT #2, "'----------"
  130.     PRINT #2, "' INPUTS:"
  131.     PRINT #2, "'   --- wantFile$ ---"
  132.     PRINT #2, "'    The filename you would like to write the DATAs to, can contain"
  133.     PRINT #2, "'    a full or relative path."
  134.     PRINT #2, "'----------"
  135.     PRINT #2, "' RESULT:"
  136.     PRINT #2, "'   --- realFile$ ---"
  137.     PRINT #2, "'    - On success this is the path and filename finally used after all"
  138.     PRINT #2, "'      applied checks, use only this returned filename to access the"
  139.     PRINT #2, "'      written file."
  140.     PRINT #2, "'    - On failure this function will panic with the appropriate runtime"
  141.     PRINT #2, "'      error code which you may trap and handle as needed with your own"
  142.     PRINT #2, "'      ON ERROR GOTO... handler."
  143.     PRINT #2, "'---------------------------------------------------------------------"
  144.     PRINT #2, "FUNCTION Write"; tarName$; "Data$ (file$)"
  145.     PRINT #2, "'--- option _explicit requirements ---"
  146.     PRINT #2, "DIM po%, body$, ext$, num%, numL&, numB&, rawdata$, stroffs&, i&, dat&, ff%";
  147.     IF packed% THEN PRINT #2, ", filedata$": ELSE PRINT #2, ""
  148.     PRINT #2, "'--- separate filename body & extension ---"
  149.     PRINT #2, "FOR po% = LEN(file$) TO 1 STEP -1"
  150.     PRINT #2, "    IF MID$(file$, po%, 1) = "; CHR$(34); "."; CHR$(34); " THEN"
  151.     PRINT #2, "        body$ = LEFT$(file$, po% - 1)"
  152.     PRINT #2, "        ext$ = MID$(file$, po%)"
  153.     PRINT #2, "        EXIT FOR"
  154.     PRINT #2, "    ELSEIF MID$(file$, po%, 1) = "; CHR$(34); "\"; CHR$(34); " OR MID$(file$, po%, 1) = "; CHR$(34); "/"; CHR$(34); " OR po% = 1 THEN"
  155.     PRINT #2, "        body$ = file$"
  156.     PRINT #2, "        ext$ = "; CHR$(34); CHR$(34)
  157.     PRINT #2, "        EXIT FOR"
  158.     PRINT #2, "    END IF"
  159.     PRINT #2, "NEXT po%"
  160.     PRINT #2, "'--- avoid overwriting of existing files ---"
  161.     PRINT #2, "num% = 1"
  162.     PRINT #2, "WHILE _FILEEXISTS(file$)"
  163.     PRINT #2, "    file$ = body$ + "; CHR$(34); "("; CHR$(34); " + LTRIM$(STR$(num%)) + "; CHR$(34); ")"; CHR$(34); " + ext$"
  164.     PRINT #2, "    num% = num% + 1"
  165.     PRINT #2, "WEND"
  166.     PRINT #2, "'--- write DATAs ---"
  167.     PRINT #2, "RESTORE "; tarName$
  168.     PRINT #2, "READ numL&, numB&"
  169.     PRINT #2, "rawdata$ = SPACE$((numL& * 4) + numB&)"
  170.     PRINT #2, "stroffs& = 1"
  171.     PRINT #2, "FOR i& = 1 TO numL&"
  172.     PRINT #2, "    READ dat&"
  173.     PRINT #2, "    MID$(rawdata$, stroffs&, 4) = MKL$(dat&)"
  174.     PRINT #2, "    stroffs& = stroffs& + 4"
  175.     PRINT #2, "NEXT i&"
  176.     PRINT #2, "IF numB& > 0 THEN"
  177.     PRINT #2, "    FOR i& = 1 TO numB&"
  178.     PRINT #2, "        READ dat&"
  179.     PRINT #2, "        MID$(rawdata$, stroffs&, 1) = CHR$(dat&)"
  180.     PRINT #2, "        stroffs& = stroffs& + 1"
  181.     PRINT #2, "    NEXT i&"
  182.     PRINT #2, "END IF"
  183.     PRINT #2, "ff% = FREEFILE"
  184.     PRINT #2, "OPEN file$ FOR OUTPUT AS ff%"
  185.     IF packed% THEN
  186.         PRINT #2, "CLOSE ff%"
  187.         PRINT #2, "filedata$ = LzwUnpack$(rawdata$)"
  188.         PRINT #2, "OPEN file$ FOR BINARY AS ff%"
  189.         PRINT #2, "PUT #ff%, , filedata$"
  190.     ELSE
  191.         PRINT #2, "PRINT #ff%, rawdata$;"
  192.     END IF
  193.     PRINT #2, "CLOSE ff%"
  194.     PRINT #2, "'--- set result ---"
  195.     PRINT #2, "Write"; tarName$; "Data$ = file$"
  196.     PRINT #2, "EXIT FUNCTION"
  197.     PRINT #2, ""
  198.     PRINT #2, "'--- DATAs representing the contents of file "; srcName$
  199.     PRINT #2, "'---------------------------------------------------------------------"
  200.     PRINT #2, tarName$; ":"
  201.     '--- read LONGs ---
  202.     PRINT #2, "DATA "; LTRIM$(STR$(cntL& * 8)); ","; LTRIM$(STR$(cntB&))
  203.     tmpI$ = SPACE$(32)
  204.     FOR z& = 1 TO cntL&
  205.         GET #1, , tmpI$: offI% = 1
  206.         tmpO$ = "DATA " + STRING$(87, ","): offO% = 6
  207.         DO
  208.             tmpL& = CVL(MID$(tmpI$, offI%, 4)): offI% = offI% + 4
  209.             MID$(tmpO$, offO%, 10) = "&H" + RIGHT$("00000000" + HEX$(tmpL&), 8)
  210.             offO% = offO% + 11
  211.         LOOP UNTIL offO% > 92
  212.         PRINT #2, tmpO$
  213.     NEXT z&
  214.     '--- read remaining BYTEs ---
  215.     IF cntB& > 0 THEN
  216.         PRINT #2, "DATA ";
  217.         FOR x% = 1 TO cntB&
  218.             GET #1, , tmpB%%
  219.             PRINT #2, "&H" + RIGHT$("00" + HEX$(tmpB%%), 2);
  220.             IF x% <> 16 THEN
  221.                 IF x% <> cntB& THEN PRINT #2, ",";
  222.             ELSE
  223.                 IF x% <> cntB& THEN
  224.                     PRINT #2, ""
  225.                     PRINT #2, "DATA ";
  226.                 END IF
  227.             END IF
  228.         NEXT x%
  229.         PRINT #2, ""
  230.     END IF
  231.     PRINT #2, "END FUNCTION"
  232.     PRINT #2, ""
  233.     '--- ending ---
  234.     CLOSE #2
  235.     CLOSE #1
  236.      
  237.     '--- finish message ---
  238.     COLOR 10: PRINT: PRINT "file successfully processed..."
  239.     COLOR 9: PRINT: PRINT "You must $INCLUDE the created file (target name + .bm extension) at"
  240.     PRINT "the end of your program and call the function 'Write"; tarName$; "Data$(...)'"
  241.     PRINT "in an appropriate place to write the file back to disk."
  242.     IF packed% THEN
  243.         COLOR 12: PRINT: PRINT "Your program must also $INCLUDE 'lzwpacker.bm' available from"
  244.         PRINT "the Libraries Collection here:"
  245.         PRINT "     https://www.qb64.org/forum/index.php?topic=809"
  246.         PRINT "to be able to write back the just processed file."
  247.         KILL tarPath$ + tar$ + ".lzw"
  248.     END IF
  249.     done:
  250.     COLOR 7
  251.     END
  252.     '--- error handler ---
  253.     abort:
  254.     COLOR 12: PRINT: PRINT "something is wrong with path/file access, check your inputs and try again..."
  255.     RESUME done
  256.      
  257.     '$INCLUDE: 'QB64Library\LZW-Compress\lzwpacker.bm'
  258.      
  259.      
  260.  


Source Code MakeCARR.bas:
Code: QB64: [Select]
  1.     '+---------------+---------------------------------------------------+
  2.     '| ###### ###### |     .--. .         .-.                            |
  3.     '| ##  ## ##   # |     |   )|        (   ) o                         |
  4.     '| ##  ##  ##    |     |--' |--. .-.  `-.  .  .-...--.--. .-.        |
  5.     '| ######   ##   |     |  \ |  |(   )(   ) | (   ||  |  |(   )       |
  6.     '| ##      ##    |     '   `'  `-`-'  `-'-' `-`-`|'  '  `-`-'`-      |
  7.     '| ##     ##   # |                            ._.'                   |
  8.     '| ##     ###### |  Sources & Documents placed in the Public Domain. |
  9.     '+---------------+---------------------------------------------------+
  10.     '|                                                                   |
  11.     '| === MakeCARR.bas ===                                              |
  12.     '|                                                                   |
  13.     '| == Create a C/C++ array out of the given file, so you can embed   |
  14.     '| == it in your program and write it back when needed.              |
  15.     '|                                                                   |
  16.     '| == Two files are created, the .h file, which contains the array(s)|
  17.     '| == and some functions, and a respective .bm file which needs to   |
  18.     '| == be $INCLUDEd with your program and does provide the FUNCTION   |
  19.     '| == to write back the array(s) into any file. All used functions   |
  20.     '| == are standard library calls, no API calls are involved, so the  |
  21.     '| == writeback should work on all QB64 supported platforms.         |
  22.     '|                                                                   |
  23.     '| == Make sure to adjust the path for the .h file for your personal |
  24.     '| == needs in the created .bm files (DECLARE LIBRARY), if required. |
  25.     '| == You may specify default paths right below this header.         |
  26.     '|                                                                   |
  27.     '| == This program needs the 'lzwpacker.bm' file available from the  |
  28.     '| == Libraries Collection here:                                     |
  29.     '| ==      https://www.qb64.org/forum/index.php?topic=809            |
  30.     '| == as it will try to pack the given file to keep the array(s) as  |
  31.     '| == small as possible. If compression is successful, then your     |
  32.     '| == program also must $INCLUDE 'lzwpacker.bm' to be able to unpack |
  33.     '| == the file data again for write back. MakeCARR.bas is printing   |
  34.     '| == a reminder message in such a case.                             |
  35.     '|                                                                   |
  36.     '+-------------------------------------------------------------------+
  37.     '| Done by RhoSigma, R.Heyder, provided AS IS, use at your own risk. |
  38.     '| Find me in the QB64 Forum or mail to support&rhosigma-cw.net for  |
  39.     '| any questions or suggestions. Thanx for your interest in my work. |
  40.     '+-------------------------------------------------------------------+
  41.      
  42.     '--- if you wish, set any default paths, end with a backslash ---
  43.     srcPath$ = "" 'source path
  44.     tarPath$ = "" 'target path
  45.     '-----
  46.     IF srcPath$ <> "" THEN
  47.         COLOR 15: PRINT "Default source path: ": COLOR 7: PRINT srcPath$: PRINT
  48.     END IF
  49.     IF tarPath$ <> "" THEN
  50.         COLOR 15: PRINT "Default target path: ": COLOR 7: PRINT tarPath$: PRINT
  51.     END IF
  52.      
  53.     '--- collect inputs (relative paths allowed, based on default paths) ---
  54.     source:
  55.     LINE INPUT "Source Filename: "; src$ 'any file you want to put into a C/C++ array
  56.     IF src$ = "" GOTO source
  57.     target:
  58.     LINE INPUT "Target Basename: "; tar$ 'write stuff into this file(s) (.h/.bm is added)
  59.     IF tar$ = "" GOTO target
  60.     '-----
  61.     ON ERROR GOTO abort
  62.     OPEN "I", #1, srcPath$ + src$: CLOSE #1 'file exist check
  63.     OPEN "O", #2, tarPath$ + tar$ + ".bm": CLOSE #2 'path exist check
  64.     ON ERROR GOTO 0
  65.      
  66.     '--- separate source filename part ---
  67.     FOR po% = LEN(src$) TO 1 STEP -1
  68.         IF MID$(src$, po%, 1) = "\" OR MID$(src$, po%, 1) = "/" THEN
  69.             srcName$ = MID$(src$, po% + 1)
  70.             EXIT FOR
  71.         ELSEIF po% = 1 THEN
  72.             srcName$ = src$
  73.         END IF
  74.     NEXT po%
  75.     '--- separate target filename part ---
  76.     FOR po% = LEN(tar$) TO 1 STEP -1
  77.         IF MID$(tar$, po%, 1) = "\" OR MID$(tar$, po%, 1) = "/" THEN
  78.             tarName$ = MID$(tar$, po% + 1)
  79.             EXIT FOR
  80.         ELSEIF po% = 1 THEN
  81.             tarName$ = tar$
  82.         END IF
  83.     NEXT po%
  84.     MID$(tarName$, 1, 1) = UCASE$(MID$(tarName$, 1, 1)) 'capitalize 1st letter
  85.      
  86.     '---------------------------------------------------------------------
  87.     ' Depending on the source file's size, one or more array(s) are
  88.     ' created. This is because some C/C++ compilers seem to have problems
  89.     ' with arrays with more than 65535 elements. This does not affect the
  90.     ' write back, as the write function will take this behavior into account.
  91.     '---------------------------------------------------------------------
  92.      
  93.     '--- init ---
  94.     OPEN "B", #1, srcPath$ + src$
  95.     filedata$ = SPACE$(LOF(1))
  96.     GET #1, , filedata$
  97.     CLOSE #1
  98.     rawdata$ = LzwPack$(filedata$, 20)
  99.     IF rawdata$ <> "" THEN
  100.         OPEN "O", #1, tarPath$ + tar$ + ".lzw"
  101.         CLOSE #1
  102.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  103.         PUT #1, , rawdata$
  104.         CLOSE #1
  105.         packed% = -1
  106.         OPEN "B", #1, tarPath$ + tar$ + ".lzw"
  107.     ELSE
  108.         packed% = 0
  109.         OPEN "B", #1, srcPath$ + src$
  110.     END IF
  111.     fl& = LOF(1)
  112.     cntL& = INT(fl& / 32)
  113.     cntV& = INT(cntL& / 8180)
  114.     cntB& = (fl& - (cntL& * 32))
  115.      
  116.     '--- .h include file ---
  117.     OPEN "O", #2, tarPath$ + tar$ + ".h"
  118.     PRINT #2, "// ============================================================"
  119.     PRINT #2, "// === This file was created with MakeCARR.bas by RhoSigma, ==="
  120.     PRINT #2, "// === use it in conjunction with its respective .bm file.  ==="
  121.     PRINT #2, "// ============================================================"
  122.     PRINT #2, ""
  123.     PRINT #2, "// --- Array(s) representing the contents of file "; srcName$
  124.     PRINT #2, "// ---------------------------------------------------------------------"
  125.     '--- read LONGs ---
  126.     tmpI$ = SPACE$(32)
  127.     FOR vc& = 0 TO cntV&
  128.         IF vc& = cntV& THEN numL& = (cntL& MOD 8180): ELSE numL& = 8180
  129.         PRINT #2, "static const unsigned int32 "; tarName$; "L"; LTRIM$(STR$(vc&)); "[] = {"
  130.         PRINT #2, "    "; LTRIM$(STR$(numL& * 8)); ","
  131.         FOR z& = 1 TO numL&
  132.             GET #1, , tmpI$: offI% = 1
  133.             tmpO$ = "    " + STRING$(88, ","): offO% = 5
  134.             DO
  135.                 tmpL& = CVL(MID$(tmpI$, offI%, 4)): offI% = offI% + 4
  136.                 MID$(tmpO$, offO%, 10) = "0x" + RIGHT$("00000000" + HEX$(tmpL&), 8)
  137.                 offO% = offO% + 11
  138.             LOOP UNTIL offO% > 92
  139.             IF z& < numL& THEN PRINT #2, tmpO$: ELSE PRINT #2, LEFT$(tmpO$, 91)
  140.         NEXT z&
  141.         PRINT #2, "};"
  142.         PRINT #2, ""
  143.     NEXT vc&
  144.     '--- read remaining BYTEs ---
  145.     IF cntB& > 0 THEN
  146.         PRINT #2, "static const unsigned int8 "; tarName$; "B[] = {"
  147.         PRINT #2, "    "; LTRIM$(STR$(cntB&)); ","
  148.         PRINT #2, "    ";
  149.         FOR x% = 1 TO cntB&
  150.             GET #1, , tmpB%%
  151.             PRINT #2, "0x" + RIGHT$("00" + HEX$(tmpB%%), 2);
  152.             IF x% <> 16 THEN
  153.                 IF x% <> cntB& THEN PRINT #2, ",";
  154.             ELSE
  155.                 IF x% <> cntB& THEN
  156.                     PRINT #2, ","
  157.                     PRINT #2, "    ";
  158.                 END IF
  159.             END IF
  160.         NEXT x%
  161.         PRINT #2, ""
  162.         PRINT #2, "};"
  163.         PRINT #2, ""
  164.     END IF
  165.     '--- some functions ---
  166.     PRINT #2, "// --- Saved full qualified output path and filename, so we've no troubles"
  167.     PRINT #2, "// --- when cleaning up, even if the current working folder was changed"
  168.     PRINT #2, "// --- during program runtime."
  169.     PRINT #2, "// ---------------------------------------------------------------------"
  170.     PRINT #2, "char "; tarName$; "Name[8192]; // it's a safe size for any current OS"
  171.     PRINT #2, ""
  172.     PRINT #2, "// --- Cleanup function to delete the written file, called by the atexit()"
  173.     PRINT #2, "// --- handler at program termination time, if requested by user."
  174.     PRINT #2, "// ---------------------------------------------------------------------"
  175.     PRINT #2, "void Kill"; tarName$; "Data(void)"
  176.     PRINT #2, "{"
  177.     PRINT #2, "    remove("; tarName$; "Name);"
  178.     PRINT #2, "}"
  179.     PRINT #2, ""
  180.     PRINT #2, "// --- Function to write the array(s) back into a file, will return the"
  181.     PRINT #2, "// --- full qualified output path and filename on success, otherwise an"
  182.     PRINT #2, "// --- empty string is returned (access/write errors, file truncated)."
  183.     PRINT #2, "// ---------------------------------------------------------------------"
  184.     PRINT #2, "const char *Write"; tarName$; "Data(const char *FileName, int16 AutoClean)"
  185.     PRINT #2, "{"
  186.     PRINT #2, "    FILE *han = NULL; // file handle"
  187.     PRINT #2, "    int32 num = NULL; // written elements"
  188.     PRINT #2, ""
  189.     PRINT #2, "    #ifdef QB64_WINDOWS"
  190.     PRINT #2, "    if (!_fullpath("; tarName$; "Name, FileName, 8192)) return "; CHR$(34); CHR$(34); ";"
  191.     PRINT #2, "    #else"
  192.     PRINT #2, "    if (!realpath(FileName, "; tarName$; "Name)) return "; CHR$(34); CHR$(34); ";"
  193.     PRINT #2, "    #endif"
  194.     PRINT #2, ""
  195.     PRINT #2, "    if (!(han = fopen("; tarName$; "Name, "; CHR$(34); "wb"; CHR$(34); "))) return "; CHR$(34); CHR$(34); ";"
  196.     PRINT #2, "    if (AutoClean) atexit(Kill"; tarName$; "Data);"
  197.     PRINT #2, ""
  198.     FOR vc& = 0 TO cntV&
  199.         PRINT #2, "    num = fwrite(&"; tarName$; "L"; LTRIM$(STR$(vc&)); "[1], 4, "; tarName$; "L"; LTRIM$(STR$(vc&)); "[0], han);"
  200.         PRINT #2, "    if (num != "; tarName$; "L"; LTRIM$(STR$(vc&)); "[0]) {fclose(han); return "; CHR$(34); CHR$(34); ";}"
  201.         PRINT #2, ""
  202.     NEXT vc&
  203.     IF cntB& > 0 THEN
  204.         PRINT #2, "    num = fwrite(&"; tarName$; "B[1], 1, "; tarName$; "B[0], han);"
  205.         PRINT #2, "    if (num != "; tarName$; "B[0]) {fclose(han); return "; CHR$(34); CHR$(34); ";}"
  206.         PRINT #2, ""
  207.     END IF
  208.     PRINT #2, "    fclose(han);"
  209.     PRINT #2, "    return "; tarName$; "Name;"
  210.     PRINT #2, "}"
  211.     PRINT #2, ""
  212.     '--- ending ---
  213.     CLOSE #2
  214.     CLOSE #1
  215.      
  216.     '--- .bm include file ---
  217.     OPEN "O", #2, tarPath$ + tar$ + ".bm"
  218.     PRINT #2, "'============================================================"
  219.     PRINT #2, "'=== This file was created with MakeCARR.bas by RhoSigma, ==="
  220.     PRINT #2, "'=== you must $INCLUDE this at the end of your program.   ==="
  221.     IF packed% THEN
  222.         PRINT #2, "'=== ---------------------------------------------------- ==="
  223.         PRINT #2, "'=== If your program is NOT a GuiTools based application, ==="
  224.         PRINT #2, "'=== then it must also $INCLUDE: 'lzwpacker.bm' available ==="
  225.         PRINT #2, "'=== from the Libraries Collection here:                  ==="
  226.         PRINT #2, "'===    https://www.qb64.org/forum/index.php?topic=809    ==="
  227.     END IF
  228.     PRINT #2, "'============================================================"
  229.     PRINT #2, ""
  230.     PRINT #2, "'-----------------"
  231.     PRINT #2, "'--- Important ---"
  232.     PRINT #2, "'-----------------"
  233.     PRINT #2, "' If you need to move around this .bm file and its respective .h file"
  234.     PRINT #2, "' to fit in your project, then make sure the path in the DECLARE LIBRARY"
  235.     PRINT #2, "' statement below does match the actual .h file location. It's best to"
  236.     PRINT #2, "' specify a relative path assuming your QB64 installation folder as root."
  237.     PRINT #2, "'---------------------------------------------------------------------"
  238.     PRINT #2, ""
  239.     '--- writeback function ---
  240.     PRINT #2, "'"; STRING$(LEN(tarName$) + 19, "-")
  241.     PRINT #2, "'--- Write"; tarName$; "Array$ ---"
  242.     PRINT #2, "'"; STRING$(LEN(tarName$) + 19, "-")
  243.     PRINT #2, "' This function will write the array(s) you've created with MakeCARR.bas"
  244.     PRINT #2, "' back to disk and so it rebuilds the original file."
  245.     PRINT #2, "'"
  246.     PRINT #2, "' After the writeback call, only use the returned realFile$ to access the"
  247.     PRINT #2, "' written file. It's the full qualified absolute path and filename, which"
  248.     PRINT #2, "' is made by expanding your maybe given relative path and an maybe altered"
  249.     PRINT #2, "' filename (number added) in order to avoid the overwriting of an already"
  250.     PRINT #2, "' existing file with the same name in the given location. By this means"
  251.     PRINT #2, "' you'll always have safe access to the file, no matter how your current"
  252.     PRINT #2, "' working folder changes during runtime."
  253.     PRINT #2, "'"
  254.     PRINT #2, "' If you wish, the written file can automatically be deleted for you when"
  255.     PRINT #2, "' your program will end, so you don't need to do the cleanup yourself."
  256.     PRINT #2, "'----------"
  257.     PRINT #2, "' SYNTAX:"
  258.     PRINT #2, "'   realFile$ = Write"; tarName$; "Array$ (wantFile$, autoDel%)"
  259.     PRINT #2, "'----------"
  260.     PRINT #2, "' INPUTS:"
  261.     PRINT #2, "'   --- wantFile$ ---"
  262.     PRINT #2, "'    The filename you would like to write the array(s) to, can contain"
  263.     PRINT #2, "'    a full or relative path."
  264.     PRINT #2, "'   --- autoDel% ---"
  265.     PRINT #2, "'    Shows whether you want the auto cleanup (see description above) at"
  266.     PRINT #2, "'    the program end or not (-1 = delete file, 0 = don't delete file)."
  267.     PRINT #2, "'----------"
  268.     PRINT #2, "' RESULT:"
  269.     PRINT #2, "'   --- realFile$ ---"
  270.     PRINT #2, "'    - On success this is the full qualified path and filename finally"
  271.     PRINT #2, "'      used after all applied checks, use only this returned filename"
  272.     PRINT #2, "'      to access the written file."
  273.     PRINT #2, "'    - On failure (write/access) this will be an empty string, so you"
  274.     PRINT #2, "'      should check for this before trying to access/open the file."
  275.     PRINT #2, "'---------------------------------------------------------------------"
  276.     PRINT #2, "FUNCTION Write"; tarName$; "Array$ (file$, clean%)"
  277.     PRINT #2, "'--- declare C/C++ function ---"
  278.     PRINT #2, "DECLARE LIBRARY "; CHR$(34); tarPath$; tar$; CHR$(34); " 'Do not add .h here !!"
  279.     PRINT #2, "    FUNCTION Write"; tarName$; "Data$ (FileName$, BYVAL AutoClean%)"
  280.     PRINT #2, "END DECLARE"
  281.     PRINT #2, "'--- option _explicit requirements ---"
  282.     PRINT #2, "DIM po%, body$, ext$, num%";
  283.     IF packed% THEN PRINT #2, ", real$, ff%, rawdata$, filedata$": ELSE PRINT #2, ""
  284.     PRINT #2, "'--- separate filename body & extension ---"
  285.     PRINT #2, "FOR po% = LEN(file$) TO 1 STEP -1"
  286.     PRINT #2, "    IF MID$(file$, po%, 1) = "; CHR$(34); "."; CHR$(34); " THEN"
  287.     PRINT #2, "        body$ = LEFT$(file$, po% - 1)"
  288.     PRINT #2, "        ext$ = MID$(file$, po%)"
  289.     PRINT #2, "        EXIT FOR"
  290.     PRINT #2, "    ELSEIF MID$(file$, po%, 1) = "; CHR$(34); "\"; CHR$(34); " OR MID$(file$, po%, 1) = "; CHR$(34); "/"; CHR$(34); " OR po% = 1 THEN"
  291.     PRINT #2, "        body$ = file$"
  292.     PRINT #2, "        ext$ = "; CHR$(34); CHR$(34)
  293.     PRINT #2, "        EXIT FOR"
  294.     PRINT #2, "    END IF"
  295.     PRINT #2, "NEXT po%"
  296.     PRINT #2, "'--- avoid overwriting of existing files ---"
  297.     PRINT #2, "num% = 1"
  298.     PRINT #2, "WHILE _FILEEXISTS(file$)"
  299.     PRINT #2, "    file$ = body$ + "; CHR$(34); "("; CHR$(34); " + LTRIM$(STR$(num%)) + "; CHR$(34); ")"; CHR$(34); " + ext$"
  300.     PRINT #2, "    num% = num% + 1"
  301.     PRINT #2, "WEND"
  302.     PRINT #2, "'--- write array & set result ---"
  303.     IF NOT packed% THEN
  304.         PRINT #2, "Write"; tarName$; "Array$ = Write"; tarName$; "Data$(file$ + CHR$(0), clean%)"
  305.     ELSE
  306.         PRINT #2, "real$ = Write"; tarName$; "Data$(file$ + CHR$(0), clean%)"
  307.         PRINT #2, "IF real$ <> "; CHR$(34); CHR$(34); " THEN"
  308.         PRINT #2, "    ff% = FREEFILE"
  309.         PRINT #2, "    OPEN real$ FOR BINARY AS ff%"
  310.         PRINT #2, "    rawdata$ = SPACE$(LOF(ff%))"
  311.         PRINT #2, "    GET #ff%, , rawdata$"
  312.         PRINT #2, "    filedata$ = LzwUnpack$(rawdata$)"
  313.         PRINT #2, "    PUT #ff%, 1, filedata$"
  314.         PRINT #2, "    CLOSE ff%"
  315.         PRINT #2, "END IF"
  316.         PRINT #2, "Write"; tarName$; "Array$ = real$"
  317.     END IF
  318.     PRINT #2, "END FUNCTION"
  319.     PRINT #2, ""
  320.     '--- ending ---
  321.     CLOSE #2
  322.      
  323.     '--- finish message ---
  324.     COLOR 10: PRINT: PRINT "file successfully processed..."
  325.     COLOR 9: PRINT: PRINT "You must $INCLUDE the created file (target name + .bm extension) at"
  326.     PRINT "the end of your program and call the function 'Write"; tarName$; "Array$(...)'"
  327.     PRINT "in an appropriate place to write the file back to disk."
  328.     IF packed% THEN
  329.         COLOR 12: PRINT: PRINT "Your program must also $INCLUDE 'lzwpacker.bm' available from"
  330.         PRINT "the Libraries Collection here:"
  331.         PRINT "     https://www.qb64.org/forum/index.php?topic=809"
  332.         PRINT "to be able to write back the just processed file."
  333.         KILL tarPath$ + tar$ + ".lzw"
  334.     END IF
  335.     done:
  336.     COLOR 7
  337.     END
  338.     '--- error handler ---
  339.     abort:
  340.     COLOR 12: PRINT: PRINT "something is wrong with path/file access, check your inputs and try again..."
  341.     RESUME done
  342.      
  343.     '$INCLUDE: 'QB64Library\LZW-Compress\lzwpacker.bm'
  344.      
  345.      
  346.  

                                                                                                                                         (162 downloads previously)
« Last Edit: October 31, 2021, 06:37:01 am by Junior Librarian »