2004. december 12., vasárnap

Make Your Own Self Extractor (sfx)


Problem/Question/Abstract:

How to create an SFX (Self Extracting Executable)

Answer:

This tutorial will teach you the basics and structure of a SFX, in two parts, in theory (this file) and in practice (the project files)

STEP 1 o_o Choices [File Format]

We must take accountable what type of SFX where going to use, in this tutorial we will use the standard compression/storage standard.

Fields per Frame (File)
File Name
[Options]
  Fixed String Storage (255 Byte Standard)
    Advantages
      FAST
      EASY TO UNDERSTAND
      ZOMBIE READ (NO PROC)
    Disadvantages
      WASTED SPACE
      WASTED MEMORY
  Dynamic String Storage (1 to 256 Bytes)
    Advantages
      OPTIMAL SPACE USAGE

      LESS CHANGE OF CORRUPTION
      FASTER DOWNLOAD
      FASTER UPLOAD
    Disadvantages
      A LITTLE SLOWER
      PROCESSING READ (PROC)
Data Size [Options]
  Fixed Cardinal Storage (4 Byte Standard)
    Advantages
      FAST
      EASY TO UNDERSTAND
      ZOMBIE READ (NO PROC)
    Disadvantages
      WASTED SPACE
  Dynamic Cardinal Read (Advanced 1 - 5 Bytes)
    Advantages
      OPTIMAL SPACE USAGE
      LESS CHANCE OF CORRUPTION
      FASTER DOWNLOAD
      FASTER UPLOAD
    Disadvantages
      A LITTLE SLOWER
      PROCESSING READ (PROC)
      ADVANCED MEMORY ROUTINES  
Size Check [Options]
  Uncompressed Size (Cardinal)
    Advantages  
      FAST
      EASY
    Disadvantages
      UNSAFE
  CRC 32 (Cardinal)
    Advantages
      SAFE
      GET TO LEARN CRC32
    Disadvantages
      SLOW
      OVERKILL

You must look well into what you need and what out of the SFX to be able to choose the proper format to build, EVEN IF PEOPLE DON'T NOTICE, DO IT RIGHT!

STEP 2 o_0 Frame Format Structure Layout

Field Type Size
File Name DString 1 - 256 Bytes
Data Size Cardinal 4 Bytes
Uncompressed Size Cardinal 4 Bytes

We will introduce you step by step to the wild world of Dynamic Variables
Simple? YES
Useless? NO

Since this format doesn't have a POSITION field, we will use the old fashioned DATA HEADER approach to the SFX. This means it will be that it is meant to DUMP the files not to LOOK UP the files.

There are ways we can CONVERT this Frame Format to use in a FAT like table, but lets keep it simple (FOR NOW)

STEP 3 0_0 SFX File Format Structure

Data Type Size
SFX ID  Char 2
Frame Count Word 2
Frame Data Raw UNKNOWN
SFX Data Size Cardinal 4

SFX ID is used to detect if the executable (image file) contains valid SFX Data
Frame Count is used to tell us how many frames to process
Frame Data is the Frame Header (Structure) + Raw/Compressed File Data
SFX Data Size is NEEDED (you will see)

STEP 4 0_! How to add data to and Image File Module (EXE)

A little known fact of the all mighty image file (EXE) is that like a GOOD file format, it is that only what is specified is needed.

By that I mean that you can add what ever you want at the end and nothing will happen, no ZIP drive bursting in flames or even worse a "BLUE SCREEN" (c) Micro$oft 1991-2002

Now you see why I need the SFX Length at the END? yes its to go to the end of the READ-ONLY Image File (EXE) and read the Length, then look up the SFX ID to see if any SFX data is present on that Image File (EXE)

STEP 5 !_! Now to build an SFX module

Well this is an easy and important part of the process, make it as SMALL as POSSIBLE, yes kiddies

"YOU CAN PACK THE IMAGE FILE (EXE)"
TIP: UPX is great for SFX MODULES

Use less DELPHI libraries as possible, API is the way to go!
but since this is a intro tutorial we MUST make it simple.

Make a procedure to read and process the data,
in this case we can use it to READ, UNCOMPRESSED, WRITE the files.

FINAL STEP CODING!

How to read and write a Dynamic String

function ReadDString(Stream: TStream): string;
var

  LEN: Byte; // Length Byte

begin

  Stream.Read(LEN, 1); // Read Length (255 Max)
  SetLength(Result, LEN); // Set Delphi D-String Array Size
  Stream.Read(PChar(Result)^, LEN); // Read Data to D-String Array

end;

procedure WriteDString(Stream: TStream; const Str: string);
var

  LEN: Byte; // Length Byte

begin

  LEN := Length(Str); // Set Length Byte what Str[0] used to be
  Stream.Write(LEN, 1); // Write Length Byte (255 Max)
  Stream.Write(PChar(Str)^, LEN); // Write D-String Array Data

end;

COMMENT

Why the "PChar(Str)^" why not just use Str?
Well since the Str is a Delphi Dynamic-String Array (array of char), it stores its pointer, so if you attempt to use Str you are actually writing its pointer NOT the data, so what i do is I get the Pointer of the first Character on the array "PChar(Str)" then I release it as a VARIABLE or CONSTANT, as if it where a normal variable!.

Download

Download project files for both the SFX Maker and the SFX it self
it is your job to try to understand the code, (i re-use variables allot), the main idea is this:

CREATE NEW SFX FILE
WRITE SFX MODULE (MODULE EXE)
WRITE SFX DATA

SFX DATA
WRITE ID ('SF')
WRITE FILE COUNT
WRITE FILE
WRITE LENGTH

WRITE FILE
WRITE FILENAME
WRITE COMPRESSED LENGTH
WRITE UNCOMPRESSED LENGTH
WRITE COMPRESSED FILE DATA


Component Download: http://www.taxisairport.com/dhype/downloads/sfxtutorial.rar

Nincsenek megjegyzések:

Megjegyzés küldése