Contributor: LARRY HADLEY             

{
>Hmmm.... how about this.... I want to put a 75k MOD file into the EXE...
>I've heard that you use pointers and appending the MOD to end of your
>compiled program and stuff like that... I'm not too sure how to go about
>it.

In short, the easiest way is to append to to your .EXE file. The
following code will search the current .exe for data appended to
the end of the .exe file.
}

Uses
  DOS;

TYPE              { .exe file header }
  EXEH = RECORD
    id,            { .exe signature }
    Lpage,         { .exe file size mod 512 bytes; < 512 bytes }
    Fpages,        { .exe file size div 512 bytes; + 1 if Lpage > 0 }
    relocitems,    { number of relocation table items }
    size,          { .exe header size in 16-byte paragraphs }
    minalloc,      { min heap required in additional to .exe image }
    maxalloc,      { extra heap desired beyond that required
                     to hold .exe's image }
    ss,            { displacement of stack segment }
    sp,            { initial SP register value }
    chk_sum,       { complemented checksum }
    ip,            { initial IP register value }
    cs,            { displacement of code segment }
    ofs_rtbl,      { offset to first relocation item }
    ovr_num : word; { overlay numbers }
  END;

CONST
  MAX_BLOCK_SIZE = 65528; {maximum allowable size of data block in
                            TP}
TYPE
  pdata = ^data_array;
  data_array = array[0..MAX_BLOCK_SIZE] of byte;

  pMODblock = ^MODblock;
  MODblock = RECORD
    data     :pdata;
    datasize :word;
  end;

VAR
  exefile : file;
  exehdr  : exeh;
  blocks  : word;

  exesize,
  imgsize : longint;

  path    : dirstr;
  name    : namestr;
  ext     : extstr;
  EXEName : pathstr;
  n       : byte;

  dirfile : searchrec;

  M       : pMODblock;

{Determines the exe filename, opens the file for read-only, and
 determines the actual .exe code image size by reading the
 standard .exe header that is in front of every .exe file. The .MOD
 data will be in the file *after* the end of the code image.}
Procedure ReadHdr;

  {this "finds" your exe filename}
  Function CalcEXEName : string;
  var
    Dir  : DirStr;
    Name : NameStr;
    Ext  : ExtStr;
  begin
    if Lo(DosVersion) >= 3 then
      EXEName := ParamStr(0)
    else
      EXEName := FSearch('progname.EXE', GetEnv('PATH'));
                         {  ^^^^^^^^ } { change this to intended EXE name }
    FSplit(EXEName, Dir, Name, Ext);
    CalcEXEName := Name;
  end;

begin
  Name := CalcEXEName;

  findfirst(EXEName, anyfile, dirfile);
  while (doserror=0) do
  BEGIN
    Assign(exefile, EXEName);
    Reset(exefile, 1);         { reset for 1 byte records }
    BlockRead(exefile, exehdr, SizeOf(exehdr), blocks);
    if blocks0}
      if LPage > 0 then
        dec(imgsize);
      imgsize := (imgsize*512) + LPage; {final image size}
    end;
  END;
end;

{ this function reads the 64k-8 byte sized block, numbered
  "blocknum" from the end of the file exefile (already opened in
  ReadHdr proc above), allocates a new pMODblock structure and
  passes it back to the caller. "blocknum" is 0-based - ie, data
  offset starts at 0. If the remaining data is less than 64k, the
  data record will be sized to the remaining data.}
Function ReadBlockFromMOD(blocknum):pMODblock;
var
  filepos : longint;
  mod     : pMODblock;
begin
  filepos := imgsize + (blocknum*MAX_BLOCK_SIZE);
  if filepos > exesize then {block position asked for exceeds filesize}
  begin
    ReadBlockFromMOD := NIL; { return error signal }
    EXIT;                    {...and return}
  end;
  New(mod);

  if (filepos+MAX_BLOCK_SIZE>exesize) then
    mod^.datasize := exesize-filepos
        { data left in this block is less than 64k }
  else
    mod^.datasize := MAX_BLOCK_SIZE;
        { data block is a full 64k }
  GetMem(mod^.data, mod^.datasize); {get the memory for the data buffer}

  Seek(exefile, filepos); { position dos's filepointer to beginning of block}
  BlockRead(exefile, mod^.data^, mod^.datasize, blocks);

  if blocks