Yet another compressed embedded files demo
Posted: Wed Sep 02, 2015 11:26 pm
Yet another simple compressed embedded files demo. I was interested in this method as it's multi-OS unlike Windows PE resources.
Im using PB's built-in BriefLZ packer, it only adds 10kb to the size of 32bit exe. There are other algorithms with better compression, faster decompression, and even smaller codec, but that can wait another day
First we need to compress the files, I simply make a ".blz" packed copy of each file. For this demo i use two text files for the purpose of showing use of multiple files, but they're read as binary data suitable for images etc.
We embed them in the data section of our executable and decompress when we need them. The unpacked size is stored as the 3rd Long in the BriefLZ-packed data, how handy! so we can simply read that to know how much memory to allocate, and also give that to UncompressMemory() as recommended by the docs so it has a buffer safety limit
Yay 
Im using PB's built-in BriefLZ packer, it only adds 10kb to the size of 32bit exe. There are other algorithms with better compression, faster decompression, and even smaller codec, but that can wait another day

First we need to compress the files, I simply make a ".blz" packed copy of each file. For this demo i use two text files for the purpose of showing use of multiple files, but they're read as binary data suitable for images etc.
Code: Select all
UseBriefLZPacker()
Procedure BriefLZPackFile(sFileToPack.s) ;packs sFileToPack to sFileToPack+".blz"
Protected hPack.i, Size1.q, Size2.q
hFile.i = ReadFile(#PB_Any, sFileToPack)
If hFile
Size1 = Lof(hFile)
*pMem = AllocateMemory(Size1)
ReadData(hFile, *pMem, Size1)
CloseFile(hFile)
*pPackmem = AllocateMemory(Size1)
Size2 = CompressMemory(*pMem, Size1, *pPackmem, Size1)
If Size2 = 0
MessageRequester("Error", "CompressMemory failed")
Else
MessageRequester("Success","Packed from " + Str(Size1) + " to " + Str(Size2) + " = " + StrF((Size2 / Size1) * 100,3) + "%")
DeleteFile(sFileToPack+".blz")
hFile = CreateFile(#PB_Any, sFileToPack+".blz")
If hFile = 0
MessageRequester("Error", "Couldnt open archive to save data into")
Else
WriteData(hFile, *pPackMem, Size2)
CloseFile(hFile)
EndIf
EndIf
Else
MessageRequester("Error", "Couldnt read file")
EndIf
EndProcedure
BriefLZPackFile("c:\temp\Include1.txt")
BriefLZPackFile("c:\temp\Include2.txt")
We embed them in the data section of our executable and decompress when we need them. The unpacked size is stored as the 3rd Long in the BriefLZ-packed data, how handy! so we can simply read that to know how much memory to allocate, and also give that to UncompressMemory() as recommended by the docs so it has a buffer safety limit

Code: Select all
EnableExplicit
UseBriefLZPacker()
Procedure.i UnpackBriefLZ(BincludeStart, BincludeEnd, *pMem.integer)
Protected unpsize.l
If BincludeStart = 0 Or BincludeEnd = 0: ProcedureReturn 0: EndIf
unpsize = PeekL(BincludeStart+8) ;unpacked size is stored in the packed header
*pMem\i = AllocateMemory(unpsize)
unpsize = UncompressMemory(BincludeStart, BincludeEnd-BincludeStart, *pMem\i, unpsize, #PB_PackerPlugin_BriefLZ)
If unpsize = 0: FreeMemory(*pMem\i): EndIf
ProcedureReturn unpsize
EndProcedure
Define unpacked.i, *pMem
unpacked = UnpackBriefLZ(?Binclude1, ?Binclude1End, @*pMem)
If unpacked <> 0: MessageRequester("Unpacked " + Str(unpacked) + " bytes", PeekS(*pMem, unpacked)): EndIf
If *pMem <> 0: FreeMemory(*pMem): *pMem = 0: EndIf
unpacked = UnpackBriefLZ(?Binclude2, ?Binclude2End, @*pMem)
If unpacked <> 0: MessageRequester("Unpacked " + Str(unpacked) + " bytes", PeekS(*pMem, unpacked)): EndIf
If *pMem <> 0: FreeMemory(*pMem): *pMem = 0: EndIf
End
DataSection
Binclude1:
IncludeBinary "c:\temp\Include1.txt.blz"
Binclude1End:
Binclude2:
IncludeBinary "c:\temp\Include2.txt.blz"
Binclude2End:
EndDataSection
