home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / PROG / PASCAL / EXTEND32.ZIP / SHRINK.PAS < prev   
Encoding:
Pascal/Delphi Source File  |  1989-09-15  |  4.0 KB  |  114 lines

  1. unit Shrink;
  2.  
  3. { This unit allows you to allocate memory from the DOS memory pool rather than
  4.   from the Turbo Pascal heap.  It also provides a procedure for shrinking the
  5.   current program to free up DOS memory.
  6.  
  7.   Scott Bussinger
  8.   Professional Practice Systems
  9.   110 South 131st Street
  10.   Tacoma, WA  98444
  11.   (206)531-8944
  12.   Compuserve [72247,2671] }
  13.  
  14. { ** Revision History **
  15.   1 SHRINK.PAS 15-Sep-89,`SCOTT' Initial version of SHRINK unit
  16.   ** Revision History ** }
  17.  
  18. interface
  19.  
  20. procedure DosNew(var P: pointer;
  21.                      Bytes: word);
  22.   { Get a pointer to a chunk of memory from DOS.  Returns NIL if
  23.     sufficient DOS memory is not available. }
  24.  
  25. procedure DosDispose(var P: pointer);
  26.   { Return an allocated chunk of memory to DOS.  Only call this function
  27.     with pointers allocated with DosNew or DosNewShrink. }
  28.  
  29. procedure DosNewShrink(var P: pointer;
  30.                            Bytes: word);
  31.   { Get a pointer to a chunk of memory from DOS, shrinking current program
  32.     to gain DOS memory if necessary.  Returns NIL if sufficient DOS memory
  33.     is not available and there is insufficient free space in the heap to
  34.     allow program to be shrunk to accomodate the request. }
  35.  
  36. implementation
  37.  
  38. uses Dos;
  39.  
  40. const DosOverhead = 1;                           { Extra number of paragraphs that DOS requires in overhead for MCB chain }
  41.  
  42. function Linear(P: pointer): longint;
  43.   { Return the pointer as a linear longint value }
  44.   begin
  45.   Linear := (longint(seg(P^)) shl 4) + ofs(P^)
  46.   end;
  47.  
  48. procedure DosNew(var P: pointer;
  49.                      Bytes: word);
  50.   { Get a pointer to a chunk of memory from DOS.  Returns NIL if
  51.     sufficient DOS memory is not available. }
  52.   var SegsToAllocate: word;
  53.       Regs: Registers;
  54.   begin
  55.   SegsToAllocate := (Bytes+15) shr 4;            { DOS allocates memory in paragraph sized pieces only }
  56.   with Regs do
  57.     begin
  58.     AH := $48;
  59.     BX := SegsToAllocate;
  60.     MsDos(Regs);
  61.     if odd(Flags)
  62.      then
  63.       P := nil                                   { No memory available }
  64.      else
  65.       P := ptr(AX,$0000)                         { Return pointer to memory block }
  66.     end
  67.   end;
  68.  
  69. procedure DosDispose(var P: pointer);
  70.   { Return an allocated chunk of memory to DOS.  Only call this function
  71.     with pointers allocated with DosNew or DosNewShrink. }
  72.   var Regs: Registers;
  73.   begin
  74.   with Regs do
  75.     begin
  76.     AH := $49;
  77.     ES := seg(P^);
  78.     MsDos(Regs)
  79.     end
  80.   end;
  81.  
  82. procedure DosNewShrink(var P: pointer;
  83.                            Bytes: word);
  84.   { Get a pointer to a chunk of memory from DOS, shrinking current program
  85.     to gain DOS memory if necessary.  Returns NIL if sufficient DOS memory
  86.     is not available and there is insufficient free space in the heap to
  87.     allow program to be shrunk to accomodate the request. }
  88.   var BytesToAllocate: word;
  89.       OldFreePtr: pointer;
  90.       Regs: Registers;
  91.   begin
  92.   BytesToAllocate := (((Bytes+15) shr 4) + DosOverhead) shl 4;
  93.   DosNew(P,Bytes);                               { Try to get memory the easy way first }
  94.   if (P=nil) and
  95.      (((ofs(FreePtr^)=0) and (Linear(FreePtr)+$10000-Linear(HeapPtr)>=BytesToAllocate)) or
  96.       ((ofs(FreePtr^)<>0) and (Linear(FreePtr)-Linear(HeapPtr)>=BytesToAllocate))) then
  97.     begin                                        { The easy method didn't work but there is sufficient space in the heap }
  98.     OldFreePtr := FreePtr;
  99.     dec(longint(FreePtr),longint(BytesToAllocate) shl 12); { Decrement the segment of the pointer to the free list }
  100.     if ofs(OldFreePtr^) <> 0 then                { If free list is empty, then there's nothing to move }
  101.       move(OldFreePtr^,FreePtr^,$10000-ofs(OldFreePtr^)); { Otherwise, move the free list down in memory }
  102.     with Regs do
  103.       begin
  104.       AH := $4A;
  105.       BX := seg(OldFreePtr^) + $1000 - prefixseg - (BytesToAllocate shr 4);
  106.       ES := prefixseg;
  107.       MsDos(Regs)
  108.       end;
  109.     DosNew(P,Bytes)                              { Try the DOS allocation one more time }
  110.     end
  111.   end;
  112.  
  113. end.
  114.