QB64 Phoenix Edition
Adding multiple files to the EXE - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: QB64 Rising (https://qb64phoenix.com/forum/forumdisplay.php?fid=1)
+--- Forum: Prolific Programmers (https://qb64phoenix.com/forum/forumdisplay.php?fid=26)
+---- Forum: Petr (https://qb64phoenix.com/forum/forumdisplay.php?fid=52)
+---- Thread: Adding multiple files to the EXE (/showthread.php?tid=1533)



Adding multiple files to the EXE - Petr - 03-06-2023

To add more files to EXE you will need the programs listed in this thread, but first also the PMF2 compressor program which is in the previous thread:  https://qb64phoenix.com/forum/showthread.php?tid=1532&pid=14125#pid14125

Be careful what you do, I always recommend COPYING the program to another folder and putting the files there. I've tried it all and it's a working procedure. The described procedure assumes that you have already created a PMF2 file that contains all the files you need to include in the EXE file.


STEP 1:

Code: (Select All)
'STEP 1: Your EXE file is named Step1 (for example, but EXE file name must be the same as second parameter for ExtractExe!)
'        Copy to this EXE ExtractEse, and all need sources for PMF2 extractor as in this example
'        DO NOT RUN IT, MAKE EXE FILE ONLY and then goto step 2 in example 2 for completing this operation.


Type Header '                        Header 1
    ID As String * 4 '               file format signature PMF2
    Files_Total As Long '            how much files container contains
End Type

Type File_List '                     Header 2
    FileNameLEN As _Unsigned _Byte 'Lenght for file name (example: Untitled.bas = file name lenght = 12)
    Compress As _Unsigned _Byte '   Compression. 0 = not used, 1 = used (_INFLATE$)
    Offset As Long '                Area in file (offset) where start this file data
    BlockSize As Long '             Byte size (how much bytes is used for this file in PMF2 container, size after compression if used)
End Type




Dim Shared PMF2H As Header
ReDim Shared PMF2FL(0) As File_List 'each added file has its own index in this field

Const Show = -1
Const Unpack_All = 0



ExtractExe "archive.pmf2", "Step1.exe" 'get PMF2 from EXE
_Delay 1 'is need!
UnPack_PMF2 "archive.pmf2", Unpack_All ' get files from PMF2

'your program is here


End


Sub ExtractExe (OutputFile As String, ThisExeFile As String)
    Dim As Long ExeSize
    TEF = FreeFile
    Open ThisExeFile For Binary As #TEF
    Get #TEF, LOF(TEF) - 3, ExeSize
    '  Print "Original EXE size: "; ExeSize
    If ExeSize < 0 Then Print "Invalid record.": End
    OutputFileBinary$ = Space$(LOF(TEF) - ExeSize - 4)
    Get #TEF, ExeSize + 1, OutputFileBinary$
    Close #TEF
    '    Print "V RAM je "; Len(OutputFileBinary$); "bytes"
    Open OutputFile For Binary As #TEF
    Put #TEF, , OutputFileBinary$
    OutputFileBinary$ = ""
    Close #TEF
End Sub

Sub UnPack_PMF2 (ArchiveName As String, METHOD As _Byte)
    'method: -1 = show files in PMF2 file
    '         0 = UnPack all files from PMF2 file
    '       > 0 = Unpack file writed in this position in PMF2 file (-1) - use record number printed in Show mode

    If _FileExists(ArchiveName) Then
        FF = FreeFile
        Open ArchiveName For Binary As FF
        Get FF, , PMF2H '                                       read head 1

        If PMF2H.ID = "PMF2" Then
            If PMF2H.Files_Total > -1 Then
                ReDim As File_List PMF2FL(PMF2H.Files_Total)
                Get FF, , PMF2FL() '                            read head 2
                ReDim As String Names(PMF2H.Files_Total)

                For ReadFileNames = 0 To PMF2H.Files_Total '    read files names in file
                    N$ = Space$(PMF2FL(ReadFileNames).FileNameLEN)
                    Get FF, , N$
                    Names(ReadFileNames) = N$
                    N$ = ""
                Next

                Select Case METHOD '                                                                                 This is information block (Show)
                    Case -1
                        Print "Pos. File name      Compressed          Size in PMF2 file [bytes]"
                        Print "-----------------------------------------------------------------"
                        For ReadContent = 0 To PMF2H.Files_Total
                            F_Name$ = Names(ReadContent)
                            If Len(F_Name$) > 15 Then F_Name$ = Mid$(F_Name$, 1, 12) + "..."
                            If PMF2FL(ReadContent).Compress Then F_Compress$ = "Yes" Else F_Compress$ = "No"
                            F_Size& = PMF2FL(ReadContent).BlockSize

                            ddd = Len(LTrim$(Str$(ReadContent)))
                            Print LTrim$(Str$(ReadContent + 1)) + "."; Spc(4 - ddd); F_Name$; Spc(18 - Len(F_Name$) + ddd); F_Compress$; Spc(12); F_Size&
                            If ReadContent Mod 18 = 0 And ReadContent > 0 Then
                                Print "Press any key for next..."
                                Sleep
                                Cls
                                Print "Pos. File name      Compressed          Size in PMF2 file [bytes]"
                                Print "-----------------------------------------------------------------"
                            End If
                        Next
                    Case 0 '                                        extract it
                        For UnPack = 0 To PMF2H.Files_Total
                            If _FileExists(Names(UnPack)) Then 'add automaticaly parentheses and number, if file exists
                                u = 0
                                Do Until _FileExists(Names(UnPack)) = 0
                                    Dot = InStr(1, Names(UnPack), ".") - 1
                                    Test$ = Mid$(Names(UnPack), 1, Dot) + "(" + _Trim$(Str$(u) + ")") + Right$(Names(UnPack), PMF2FL(UnPack).FileNameLEN - Dot)
                                    If _FileExists(Test$) = 0 Then Names(UnPack) = Test$
                                    Test$ = ""
                                    u = u + 1
                                Loop
                            End If
                            EF = FreeFile
                            Open Names(UnPack) For Binary As EF
                            N$ = Space$(PMF2FL(UnPack).BlockSize)
                            Get FF, , N$
                            If PMF2FL(UnPack).Compress Then Rec$ = _Inflate$(N$) Else Rec$ = N$
                            Put EF, , Rec$
                            N$ = ""
                            Rec$ = ""
                            Close EF
                        Next UnPack
                    Case Is > 0 '                   unpack just one concrete file
                        Fi = METHOD - 1
                        If Fi > UBound(Names) Then Print "Invalid record add as parameter for Unpack_PMF2 SUB!": Sleep 3: End
                        If _FileExists(Names(Fi)) Then 'add automaticaly parentheses and number, if file exists
                            u = 0
                            Do Until _FileExists(Names(Fi)) = 0
                                Dot = InStr(1, Names(Fi), ".") - 1
                                Test$ = Mid$(Names(Fi), 1, Dot) + "(" + _Trim$(Str$(u) + ")") + Right$(Names(Fi), PMF2FL(Fi).FileNameLEN - Dot)
                                If _FileExists(Test$) = 0 Then Names(Fi) = Test$
                                Test$ = ""
                                u = u + 1
                            Loop
                        End If

                        EF = FreeFile
                        Open Names(Fi) For Binary As EF
                        N$ = Space$(PMF2FL(Fi).BlockSize)
                        Seek FF, PMF2FL(Fi).Offset
                        Get FF, , N$
                        If PMF2FL(Fi).Compress Then Rec$ = _Inflate$(N$) Else Rec$ = N$
                        Put EF, , Rec$
                        N$ = ""
                        Rec$ = ""
                        Close EF
                End Select
            Else
                Print "Invalid record: Number of files in PMF2 file: "; PMF2H.Files_Total: Sleep 3: End
            End If
        Else
            Print "Invalid PMF2 file format. ": Sleep 3: End
        End If
    Else
        Print "PMF2 file: "; ArchiveName$; " not exists. Can not continue.": Sleep 3: End
    End If
End Sub

Place to your program PMF2 headers and source code as in this example. COMPILE IT, DO NOT RUN IT! We need EXE file named Step1.exe, this program is named as Step1.bas it is very important for correct function!

Then, when EXE file is done, we can add files to EXE - Step 2:

Code: (Select All)
'STEP 2: USE PMF2 archiver for compress more files to PMF2 and then insert it to EXE file.

AddToExe "pmf2test2023.pmf2", "step1.exe"
End

Sub AddToExe (File As String, ExeFile As String)
    Dim As Long FileSize
    If _FileExists(ExeFile) Then
        If _FileExists(File) Then
            Af = FreeFile
            Open File For Binary As #Af
            FileBin$ = Space$(LOF(Af))
            Get #Af, , FileBin$
            Close #Af
            Af = FreeFile
            Open ExeFile For Binary As #Af
            FileSize = LOF(Af)
            Seek #Af, LOF(Af) + 1
            Put #Af, , FileBin$
            Put #Af, , FileSize
            Close #Af
            FileBin$ = ""
        Else Print "Sorry, file "; File; "not exists"
        End If
    Else Print "Sorry, file "; ExeFile; "not exists."
    End If
End Sub

Program insert archive file pmf2test2023.pmf2 to file test1.exe  

If you do all correct, after running program Step1.exe all files from PMF2 are extracted to harddrive.

If there is interest, I am willing to modify the output of PMF2 so that the files are not saved to the hard disk, but to the computer's memory.

But then of course you have to have your own solution for working with these yours files.