{
> Protected mode has the WinAPI unit that lets you deal with
> huge memory blocks and other stuff. That is what is needed.

> In real mode all you can do is:

Here's some stuff from a huge memory block unit I'm working on.  It isn't fully
debugged yet, but I think these parts work.  However, use at your own risk.
There are a few routines called which I don't include; you should be able to
figure those ones out, or pull them out of a standard library.  "LH" is a
record with fields L and H for pulling the low and high words out of a pointer
or longint.

 { This part works in both real and protected mode. }

 procedure IncPtr(var p:pointer;count:word);
 { Increments pointer }
 begin
   inc(LH(p).L,count);
   if LH(p).L < count then
     inc(LH(p).H,SelectorInc);
 end;

 procedure DecPtr(var p:pointer;count:word);
 { decrements pointer }
 begin
   if count > LH(p).L then
     dec(LH(p).H,SelectorInc);
   dec(LH(p).L,Count);
 end;

 procedure IncPtrLong(var p:pointer;count:longint);
 { Increments pointer; assumes count > 0 }
 begin
   inc(LH(p).H,SelectorInc*LH(count).H);
   inc(LH(p).L,LH(Count).L);
   if LH(p).L < LH(count).L then
     inc(LH(p).H,SelectorInc);
 end;

 procedure DecPtrLong(var p:pointer;count:longint);
 { Decrements pointer; assumes count > 0 }
 begin
   if LH(count).L > LH(p).L then
     dec(LH(p).H,SelectorInc);
   dec(LH(p).L,LH(Count).L);
   dec(LH(p).H,SelectorInc*LH(Count).H);
 end;
 { The next section is for real mode only }

{$ifndef dpmi}

 type
   PFreeRec = ^TFreeRec;
   TFreeRec = record
     next: PFreeRec;
     size: Pointer;
   end;

 procedure GetMemHuge(var p:HugePtr;size:Longint);
 const
   blocksize = $FFF0;
 var
   prev,free : PFreeRec;
   save,temp : pointer;
   block : word;
 begin
   { Handle the easy cases first }
   if size > maxavail then
     p := nil
   else if size < 65521 then
     getmem(p,size)
   else
   begin
 {$ifndef ver60}
    {$ifndef ver70}
     The code below is extremely version specific to the TP 6/7 heap manager!!
    {$endif}
 {$endif}
     { Find the block that has enough space }
     prev := PFreeRec(@freeList);
     free := prev^.next;
     while (free <> heapptr) and (PtrToLong(free^.size) < size) do
     begin
       prev := free;
       free := prev^.next;
     end;

     { Now free points to a region with enough space; make it the first one and
       multiple allocations will be contiguous. }

     save := freelist;
     freelist := free;
     { In TP 6, this works; check against other heap managers }
     while size > 0 do
     begin
       block := minlong(blocksize,size);
       dec(size,block);
       getmem(temp,block);
     end;

     { We've got what we want now; just sort things out and restore the
       free list to normal }

     p := free;
     if prev^.next <> freelist then
     begin
       prev^.next := freelist;
       freelist := save;
     end;
   end;
 end;

 procedure FreeMemHuge(var p:HugePtr;size : longint);
 const
   blocksize = $FFF0;
 var
   block : word;
 begin
   while size > 0 do
   begin
     block := minlong(blocksize,size);
     dec(size,block);
     freemem(p,block);
     IncPtr(p,block);
     p := Normalized(p);
   end;
 end;

{ The next section is the protected mode part }

 {$else}

 Procedure GetMemHuge(var p : HugePtr; Size: LongInt);
 begin
   if Size < 65521 then
     GetMem(p,size)
   else
     p := GlobalAllocPtr(gmem_moveable,Size);
 end;

 Procedure FreeMemHuge(var p : HugePtr; Size: Longint);
 var
   h : THandle;
 begin
   if Size < 65521 then
     Freemem(p,size)
   else
     h := GlobalFreePtr(p);
 end;

