
PROGRAM BinToInclude; (* Version 1.0, 12.10.96 *)

(*

   Author: Dirk "Rob!" Schwarzmann, (w) September 1996, Germany

   E-Mail: rob@rbg.informatik.th-darmstadt.de

   WWW   : http://www.student.informatik.th-darmstadt.de/~rob/


   About this small piece of code:

   This program reads any type of file and writes it back as a include
   file  (text type for TurboPascal) where every byte read is written as
   its value. So, if a .com file is read and byte #x is an @, BinToInclude
   will write the number 64 for it.

   In addition, it creates a header so that you can use the new data
   file directly as an include file in your own programs. The binary file
   is stored as an array of byte and you can write it back to disc by using
   the small procedure shown below.

   What's it all good for?

   You can hold binary files of _any_ type in your own program and do not
   have to take care that an external data (or program) file is truly there.
   If it does not exist, you simple write it! No panic, if a user has
   accidently deleted a file or a file is corrupted!

   Using this program:

   You have to specify at least one command line parameter giving the file
   you like to read. If no second parameter (the target file name) is given,
   BinToInclude will create an .INC file with the path and name similar to
   the source file. Otherwise the given name is used.
   Note that BinToInclude does very little error checking! It does not
   assure that the source file exists nor does it prevent you from over-
   writing existing include files! But because this program is only a small
   quick-hacked utility for programmers, I guess this not very important.
   If you include a file in your program, keep in mind that you may get
   problems if you include files bigger than 64k!

   There a some constants you can only change in this source code;

    - COMPRESSED is a boolean flag and toggles the writing of data between
      the well-to-read format:
        001, 020, 234, 089, ...
      and the space-saving format:
        1, 20, 234, 89, ...
      If you want to save even the blanks between comma and numbers, get
      your editor, mark the whole area and do a search + replace. It's
      that simple! It would have taken much more effort to do this here.

    - ArrayFormat
      Specify the number of rows the array definition should use. 65 - 70
      rows are a good choice to keep a good readability.

    - Ext2_Str
      Here you can change the default data file suffix - but I think there
      is no need to do so.

   To write the data back in a file, you only need this small routine:

     PROCEDURE WriteArrayToFile(TargetName:FILE OF BYTE);

     VAR
       i : LONGINT;

     BEGIN
       Assign(TargetFile,TargetName);
       Rewrite(TargetFile);
       FOR i := 1 TO BinFileSize DO
         Write(TargetFile,BinFile[i]);
       Close(TargetFile);
     END;

   That's all!

   For any suggestions, please feel free to email me!

 *)

USES DOS;

CONST
  Compressed : BOOLEAN = FALSE; (* False: 010, 009, 255, ...
                                   True: 10, 9, 255,...
                                   If you want to have 10,9,255 you can
                                   remove the blanks with search +
replace
                                   in your editor! *)

  ArrayFormat : BYTE = 65; (* The width of the array definition area
                              (number of rows) *)

  Ext2_Str : ExtStr = '.INC'; (* The default suffix for the file to write *)

  (* These lines are the header of the written include-file. After the
     variable "BinFileSize =" the program will insert the file length
     (=array length) and after the last header line the data will  follow. *)

  IncHeader1 : STRING = 'CONST';
  IncHeader2 : STRING = '  BinFileSize = ';
  IncHeader3 : STRING = '  BinFile : ARRAY[1..BinFileSize] OF BYTE = (';

VAR (* main.BinToInclude *)
  SourceFile : FILE OF BYTE;
  TargetFile : TEXT;
  SourceName : STRING[128];
  TargetName : STRING[128];
  SourceByte : BYTE;
  TgtByteStr : STRING[5];
  TargetStr : STRING[80];
  Dir_Str : DirStr;
  Name_Str : NameStr;
  Ext_Str : ExtStr;

BEGIN (* main.BinToInclude *)
  (* The case statement is only to parse the command line: *)
  CASE ParamCount OF
    1: BEGIN
      FSplit(FExpand(ParamStr(1)),Dir_Str,Name_Str,Ext_Str);
      SourceName := Dir_Str + Name_Str + Ext_Str;
      TargetName := Dir_Str + Name_Str + Ext2_Str;
    END; (* case ParamCount of 1 *)
    2: BEGIN
      FSplit(FExpand(ParamStr(1)),Dir_Str,Name_Str,Ext_Str);
      SourceName := Dir_Str + Name_Str + Ext_Str;
      FSplit(FExpand(ParamStr(2)),Dir_Str,Name_Str,Ext_Str);
      TargetName := Dir_Str + Name_Str + Ext_Str;
    END; (* case ParamCount of 2 *)
  ELSE (* case ParamCount *)
    WriteLn('Please specify at least one Parameter as the source file.');
    Write('If the optional second one is not given, <Source file>.INC is');
    WriteLn(' assumed.');
    Halt(1);
  END; (* case ParamCount *)

  Assign(SourceFile,SourceName);
  Reset(SourceFile);
  Assign(TargetFile,TargetName);
  Rewrite(TargetFile);
  WriteLn(TargetFile,IncHeader1);
  WriteLn(TargetFile,IncHeader2,FileSize(SourceFile),';');
  WriteLn(TargetFile,IncHeader3);
  TargetStr := '    '; (* Set the left margin *)
  Inc(ArrayFormat,2); (* This needs an explanation: because of the 4 blanks
                         on the left margin, we should add 4 to ArrayFormat.
                         But as every number will be followed by a comma
                         and a blank, we have to decrease it by 2. -> add 2 *)
  WHILE NOT EoF(SourceFile) DO BEGIN
    Read(SourceFile,SourceByte);
    Str(Ord(SourceByte),TgtByteStr);
    IF NOT Compressed THEN
      TgtByteStr := Copy('00',1,3-Length(TgtByteStr)) + TgtByteStr;
    IF (Length(TargetStr) + Length(TgtByteStr) > ArrayFormat) THEN BEGIN
      WriteLn(TargetFile,TargetStr); (* Flush the string *)
      TargetStr := '    ';
    END;
    TargetStr := TargetStr + TgtByteStr + ', ';
  END; (* while not EoF(SourceFile) *)
  (* Flush the buffer string but don't write the last comma: *)
  Write(TargetFile,Copy(TargetStr,1,Length(TargetStr)-2));
  WriteLn(TargetFile,');'); (* Close the array definition with the ")"
  *)
  Close(TargetFile);
  Close(SourceFile);
END. (* main.BinToInclude *)

