Discussion here
Code:
'Embed Dit '•What it does• 'This program embeds a file into your PB code as an easy alternative to, for example, a resource 'file. The technique I use here is different from Steve Hutchesson's fine program "File2asm" which 'does a similar task. The advantage is mainly that the PB code generated here is a lot smaller in 'size, so it can be eg. posted more easily at the PB site. The main drawbacks are: 1) the .EXE it 'creates is about 25% bigger than Steve's, 2) the .BAS takes longer to compile, 3) the .EXE runs very 'fast, but is just a tad slower than Steve's, and 4) there is significantly more PB code involved in 'the embed-as-PB-function/restore-original-file cycle. Therefore it could be harder to understand or 'adapt, and with complexity comes higher bug probability, but I [I]Have[/I] tested the bejeebers out of it. '•Procedure• 'The task sequence is: 1) create .BAS file with embedded file function, 2) compile that .BAS file 'as is, or use its function separately in another compiled program, 3) run the .EXE (or even .DLL) 'from that .BAS file to recreate your original binary file. The largest file this program can fully 'cycle is approx. 14MB. Zipped files work especially well and I recommend them when possible. '•Uses• 'You can reuse the function created here in the same way any PB function can be reused. It will 'possibly require a variable name/scope change or file number change to sync to your larger program. 'A few uses: Post little binaries on PB web site; embed bitmaps in your .EXE; spawn a second .EXE from 'your main .EXE; embed a .DLL; embed a video; shell out to a .PPS presentation?; lube the chassis 'of your Porsche. ;) '•Suggestion• 'I would recommend that you always run the .EXE to recreate your embedded file, then check it against 'your original file to be sure they match exactly. I've tested hundreds of various files, but there 'are quadrillions out there, and you likely wanna be safe. John Gleason, Dec. '07 #COMPILE EXE #DIM ALL #REGISTER NONE GLOBAL transTable AS STRING GLOBAL transTable2 AS STRING FUNCTION PBMAIN () AS LONG LOCAL origString, changeStr, fileName, fileName2 AS STRING LOCAL asczStr AS ASCIIZ * 240 LOCAL ii, nLoops, bChange AS LONG LOCAL scPtr AS BYTE PTR fileName = COMMAND$ 'can use "Send To" or drag-n-drop filename = LEFT$(filename, INSTR(-1, filename, "\")) & DIR$(filename) 'get long filename IF fileName = "" THEN fileName = "D:\virtualKeyboard9.zip" '<< Enter here the file you want to embed, or d-n-drop/send2 END IF fileName2 = LEFT$(fileName, INSTR(-1, filename, ".") - 1) & "_emb" & _ MID$(fileName, INSTR(-1, filename, ".") ) 'quite a unique name so file names won't collide OPEN fileName FOR BINARY [COLOR="Red"]LOCK SHARED[/COLOR] AS #2 KILL fileName & "_emb.bas" OPEN fileName & "_emb.bas" FOR BINARY AS #1 GET$ #2, LOF(#2), origString IF LEN(origString) = 0 THEN ? filename & " had a problem!",64,"Embed Dit Error" EXIT FUNCTION 'exit if file is zero length END IF changeStr= STRING$(LOF(#2), 0) CALL loadStrWithTrans !push ebx ;substitute special chars with "@" so web site & PB compiler can handle strings properly !push esi !push edi !mov esi, origString !mov eax, changeStr !mov edi, [esi-4] ;len origString !mov bChange, eax ;to get len of final changeStr--base change !mov edx, transTable vk201: !cmp edi, 0 ;are we at end of string? !je vk202 ;if yes, exit !movzx ecx, byte ptr[esi] ;get char !mov ebx, ecx ;save it for a moment !movzx ecx, byte ptr[edx+ecx] ;translate it !sub edi, 1 ;decr length so we know when we're finished !mov [esi], cl ;save it permanently !add esi, 1 ;next char !cmp ebx, 64 ;bug found, wasn't recording any "@" changes !je short vk203 !cmp ebx, ecx ;see if translation was made !je short vk201 '----------------------------------------------------------------- vk203: !mov edx, transTable2 ;substitution made, so save record of it !movzx ecx, byte ptr[edx+ebx] ;translate it to 1 thru 9 !mov [eax], cl ;save it !mov edx, transTable ;restore original transTable !add eax, 1 ;next change position !jmp short vk201 ' ; 0,9,10,13,26,34,64,160,173 are special chars as of Dec. '07 vk202: !sub eax, bChange !mov bChange, eax !pop edi !pop esi !pop ebx 'print PB code to create executable file which will, in turn, restore the original embedded file w/ a changed name. 'code created can be posted as is to PB web site. PUT$ #1, _ "'[ CODE]" & $CRLF & _ "'The function below contains the embedded file " & filename & $CRLF & _ "'Running this program will restore the file as " & filename2 & $CRLF & _ "#COMPILE EXE" & $CRLF & _ "#DIM ALL" & $CRLF & _ "#REGISTER NONE" & $CRLF & _ $CRLF & _ "GLOBAL joinOrigStr AS STRING 'GLOBAL for use anywhere" & $CRLF & _ $CRLF & _ "FUNCTION PBMAIN () AS LONG" & $CRLF & _ "LOCAL fileName AS STRING" & $CRLF & _ " fileName = """ & filename2 & """ '<< restored file name" & $CRLF & _ " CALL restoreEmbeddedFile(fileName)" & $CRLF & _ "END FUNCTION" & $CRLF & _ $CRLF & _ "FUNCTION restoreEmbeddedFile(fileName AS STRING) AS LONG" & $CRLF & _ "LOCAL changeStr, translateStr AS STRING" & $CRLF & _ "LOCAL p AS STRING PTR * 240" & $CRLF & _ "LOCAL origLen AS LONG" & $CRLF & _ $CRLF & _ " joinOrigStr = STRING$(" & FORMAT$(LEN(origString) + 240) & ", 0)" & $CRLF & _ " changeStr = STRING$(" & FORMAT$(bChange + 240) & ", 0)" & $CRLF & _ " p = STRPTR(joinOrigStr)" & $CRLF & _ " origLen = " & FORMAT$(LEN(origString)) & $CRLF nLoops = LEN(origString) \ 240 FOR ii = 0 TO nLoops - 1 PUT$ #1, "@p=" & CHR$(34) & MID$(origString, ii * 240 + 1, 240) & CHR$(34) & ":INCR p" & $CRLF NEXT asczStr = MID$(origString, nLoops * 240 + 1, 240) IF LEN(asczStr) > 0 THEN PUT$ #1, "@p=" & CHR$(34) & asczStr & CHR$(34) & $CRLF '---------------------------------------------------------------------------------------- nLoops = LEN(RTRIM$(changeStr, $NUL)) \ 240 PUT$ #1, "p = strptr(changeStr)" & $CRLF FOR ii = 0 TO nLoops - 1 PUT$ #1, "@p=" & CHR$(34) & MID$(changeStr, ii * 240 + 1, 240) & CHR$(34) & ":INCR p" & $CRLF NEXT asczStr = MID$(changeStr, nLoops * 240 + 1, 240) IF LEN(asczStr) > 0 THEN PUT$ #1, "@p=" & CHR$(34) & asczStr & CHR$(34) & $CRLF PUT$ #1, _ $CRLF & _ " translateStr = CHR$(0,9,10,13,26,34,64,160,173) 'Except for ""@""(64), these are all special chars on PowerBASIC web site." & $CRLF & _ $CRLF & _ " !mov esi, joinOrigStr ;now replace non-printable chars in origString with orig char from changeStr" & $CRLF & _ " !mov ecx, origLen ;to cut string to correct len" & $CRLF & _ " !mov edi, changeStr" & $CRLF & _ " !mov [esi-4], ecx ;now actually cut orig str to length" & $CRLF & _ " !xor eax, eax" & $CRLF & _ " !mov ebx, [esi-4] ;len origString" & $CRLF & _ " !mov edx, translateStr ;original bytes replaced with ""@"" corresponding to 1 thru 9 in changeStr" & $CRLF & _ " dpr02:" & $CRLF & _ " !cmp byte ptr[esi+eax], 64 ;is byte an ""@"" char?" & $CRLF & _ " !je short dpr01 ;yes? then replace it with orig char" & $CRLF & _ " !add eax, 1" & $CRLF & _ " !cmp eax, ebx ;are we at end of string?" & $CRLF & _ " !jb short dpr02 ;no" & $CRLF & _ " !jmp dpr03 ;yes" & $CRLF & _ " dpr01:" & $CRLF & _ " !movzx ecx, byte ptr[edi] ;char 1 thru 9" & $CRLF & _ " !sub ecx, &h31 ;turn 1 thru 9 into valid index" & $CRLF & _ " !movzx ecx, byte ptr[edx+ecx] ;cl now holds original char that was replaced by printable ""@""" & $CRLF & _ " !mov [esi+eax], cl ;restore it" & $CRLF & _ " !add eax, 1" & $CRLF & _ " !add edi, 1 ;next repl. byte" & $CRLF & _ " !jmp short dpr02" & $CRLF & _ " dpr03:" & $CRLF & _ $CRLF & _ " OPEN filename FOR BINARY AS #1" & $CRLF & _ " IF ERR <> 0 THEN ? filename & "" had a problem!"",64,""Embed Dit Error"": EXIT FUNCTION" & $CRLF & _ " IF LOF(1) > 0 THEN ? filename & "" exists already!"",64,""Embed Dit Error"": EXIT FUNCTION" & $CRLF & _ " PUT #1, , joinOrigStr" & $CRLF & _ " CLOSE" & $CRLF & _ " ? filename & "" restored successfully"",,""Embed Dit""" & $CRLF & _ "END FUNCTION'[ /CODE]" & $CRLF ? "Code file " & fileName & "_emb.bas created successfully.",,"Embed Dit" END FUNCTION FUNCTION loadStrWithTrans() AS LONG 'should PB web site (or compiler btw) change printable chars allowed, change below tables as follows: 'in TransTable, change disallowed chars to "64" 'in TransTable2, change all "64" chars you entered in TransTable to sequential series starting at "49". Eg. where CHR$(0) 'was changed to "64", TransTable2 will start at "49". Next, CHR$(9) position is "64" in TransTable, so it becomes "50" 'in table2, etc. 'Finally, change "translateStr = CHR$(0,9,10,13,26,34,64,160,173)" above to list, in order, all special chars. 'eg. CHR$(0,9,10,13,14,26,34,64,160,173,233). TransTable = CHR$(64,1,2,3,4,5,6,7,8,64,64,11,12,64,14,15,16, _ 17,18,19,20,21,22,23,24,25,64,27,28,29,30,31,32, _ 33,64,35,36,37,38,39,40,41,42,43,44,45,46,47,48, _ 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64, _ 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, _ 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96, _ 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, _ 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, _ 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144, _ 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,64 , _ 161,162,163,164,165,166,167,168,169,170,171,172,64 ,174,175,176, _ 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, _ 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208, _ 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, _ 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240, _ 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255) ' 0,9,10,13,26,34,64,160,173 << all set to 64 so "@" replaces them '-------------------------------------------------------------------------------------------- TransTable2 = CHR$(49,1,2,3,4,5,6,7,8,50,51,11,12,52,14,15,16, _ 17,18,19,20,21,22,23,24,25,53,27,28,29,30,31,32, _ 33,54,35,36,37,38,39,40,41,42,43,44,45,46,47,48, _ 49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,55, _ 65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80, _ 81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96, _ 97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112, _ 113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128, _ 129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144, _ 145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,56 , _ 161,162,163,164,165,166,167,168,169,170,171,172,57 ,174,175,176, _ 177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,192, _ 193,194,195,196,197,198,199,200,201,202,203,204,205,206,207,208, _ 209,210,211,212,213,214,215,216,217,218,219,220,221,222,223,224, _ 225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240, _ 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255) END FUNCTION