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