_TITLE "Any file to Base64 Data" 'Embed any file into a self-extracting .bas file
'========================================================================================================
'dataLine is the most number of bytes to convert from a 'DATA' statement when decoding
'Longer lines create slightly smaller output files. Recommended upper bound for dataLine = 252 (3 x 84)
CONST dataLine
= 192 '<---MUST be divisible by 3 !!! PRINT "Error: Maximum Data Line Length is NOT evenly divisible by 3" PRINT "Press a key to end"
'========================================================================================================
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'========================================================================================================
inFile$ = "binaryFile.ext" ' <---Change name of input file here (.zip .7z .rar .dll .bmp .png)
'========================================================================================================
outFile$ = "binaryFile_ext.bas" ' <---Change name of output file here
'========================================================================================================
'!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
'========================================================================================================
'========================================================================================================
'Change the variable 'viewPic to 1 to display an image in the distributed file.
'******************* Only set viewPic as 1 for image files used by QB64 .bmp, .png **********************
viewPic = 1
'========================================================================================================
DIM cnt
, extras
, i
, j
, numBytes
, ew
, ex
, ey
, rmdr
, temp
AS INTEGER
k
(i
- 1) = MID$("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/", i
, 1)
PRINT "The input file: "; inFile$;
" has a file length of"; fileLen;
" bytes."
GET #1, , arr
() 'Load the file into arr() <--- unsigned byte array
lastQuad = ""
'If input file length is not evenly divisible by 3 then handle one of the
'remaining possibilities. Encode b64 characters into lastQuad string.
ew
= _SHR(arr
(fileLen
- 1), 6) ex
= arr
(fileLen
- 1) AND 3 lastQuad = k(ew) + k(ex) + "=="
temp
= _SHR(arr
(fileLen
- 2), 8) + arr
(fileLen
- 1) lastQuad = k(ew) + k(ex) + k(ey) + "="
'Calc a file length that is exactly divisible by 3
newLen = fileLen - extras
'PRINT "Divisible by 3 file length ="; newLen
'Calc how many complete lines of data to generate
numBytes = (newLen \ dataLine) * dataLine
'PRINT "There are"; numBytes \ dataLine; " lines of complete data statements"
'rmdr (remainder) tells how many bytes to encode on last line of data
rmdr = newLen - numBytes
'PRINT "There are"; rmdr; " remaining data bytes on the last line of output"
'=============================================================================
'This is the crunched b64 decoder. It runs, decodes, writes decoded file to disk,
'and as an option can also display an image file
'=============================================================================
ldr = "DIM SHARED k AS LONG:k=1:READ f$,s&,t&:OPEN f$ FOR BINARY AS #9:n&=s&\t&:n&=n&-((n&*t&)<s&):FOR c&=1 TO n&:READ d$:u(d$):NEXT"
'This is optional code to display an image after decoding and writing to disk
ldr = "SLEEP 1:SCREEN _NEWIMAGE(960,720,32):_TITLE f$:img& = _LOADIMAGE(f$):_SOURCE img&:_DEST 0:_PUTIMAGE:SLEEP"
ldr = "SYSTEM"
ldr = "SUB u(d$):r$=" + q + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" + q + ":" + "s$=" + q + q + ":v%=0:L%=LEN(d$):IF RIGHT$(d$,1)=" + q + "=" + q + "THEN v%=2"
ldr = "IF RIGHT$(d$,2)=" + q + "==" + q$ + "THEN v%=1"
ldr = "IF v%>0 THEN m%=L%-5 ELSE m%=L%-1"
ldr = "FOR i%=1 TO m% STEP 4:w%=INSTR(r$,MID$(d$,i%,1))-1:x%=INSTR(r$,MID$(d$,i%+1,1))-1:y%=INSTR(r$,MID$(d$,i%+2,1))-1:z%=INSTR(r$,MID$(d$,i%+3,1))-1"
ldr = "a~%%=(w%*4)+((x% AND 48)/16):b~%%=((x% AND 15)*16)+((y% AND 60)/4):c~%%=((y% AND 3)*64)+z%:PUT #9,k,a~%%:PUT #9,k+1,b~%%:PUT #9,k+2,c~%%:k=k+3:NEXT"
ldr = "IF v%>0 THEN"
ldr = "w%=INSTR(r$,MID$(d$,L%-3,1))-1:x%=INSTR(r$,MID$(d$,i%+1,1))-1:a=(w%*4)+((x% AND 48)/16):PUT #9,k,a~%%:k=k+1"
ldr = "IF v%=2 THEN:y%=INSTR(r$,MID$(d$,L%-1,1))-1:b=((x% AND 15)*16)+((y% AND 60)/4):PUT #9,k,b~%%:k=k+1"
ldr = "END IF:END SUB"
'=============================================================================
WRITE #2, inFile$
, fileLen
, dataLine
'Write all of the complete lines of data (dataLine) to the output file
cnt = 0
'Combine 3 single bytes into a 24 bit integer
msb
= _SHL(arr
(i
+ j
), 16) msb2
= _SHL(arr
(i
+ j
+ 1), 8) lsb = arr(i + j + 2)
'store the 24 bit integers in byte3() array
byte3(cnt) = msb + msb2 + lsb
cnt = cnt + 1
enc = b64$(cnt - 1)
PRINT #2, "DATA " + q
+ enc
+ q
'Now write a partial line of data if necessary
'enc = ""
cnt = 0
msb2
= _SHL(arr
(j
+ 1), 8) lsb = arr(j + 2)
'store the 24 bit integer in the byte3() array
byte3(cnt) = msb + msb2 + lsb
cnt = cnt + 1
enc = b64$(cnt - 1)
'Add last quad of b64 encoded characters to the final data line
PRINT #2, "DATA " + q
+ enc
+ lastQuad
+ q
PRINT "The Base64 encoded file: "; outFile$;
" has been written to disk." PRINT "Size of the Base64 encoded file "; outFile$;
" is";
LOF(2);
" bytes" PRINT "Press a key to exit."
e$ = e$ + k(w%) + k(x%) + k(y%) + k(z%)
b64$ = e$