[Back to EXEC SWAG index] [Back to Main SWAG index] [Original]
{
>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 blocks<SizeOf(exehdr) then
begin
Writeln('File read error!');
Halt(1);
end;
exesize := dirfile.size; { the total file size of exe+data }
with exehdr do
begin
imgsize := FPages; {exe img size div 512 bytes, +1 if Lpage>0}
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<mod^.datasize then { make sure we got all the data }
begin
Writeln('File read error!');
FreeMem(mod^.data, mod^.datasize);
Dispose(mod);
ReadBlockFromMOD := NIL;
EXIT;
end;
ReadBlockFromMOD := mod;
end;
{
This will read in the .MOD from the "back" of the .exe 64k-8
bytes at a time. As written, you manually have to pass a block
number to the "read" function.
A couple of caveats - doing it as written is error-prone. Using
this code "barebones" in a finished application is not advisable,
but it does demonstrate the concept and gives you a starting
point. THIS CODE HAS NOT BEEN TESTED! If you have problems with
it, let me know and I'll help you out.
After you have digest the code, ask some more questions and we
can discuss streams and OOP techniques to do this in a less
dangerous manner.
}
[Back to EXEC SWAG index] [Back to Main SWAG index] [Original]