Yet another compressed embedded files demo

Share your advanced PureBasic knowledge/code with the community.
User avatar
Keya
Addict
Addict
Posts: 1890
Joined: Thu Jun 04, 2015 7:10 am

Yet another compressed embedded files demo

Post by Keya »

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.

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
Yay :)