[Back to MEMORY SWAG index]  [Back to Main SWAG index]  [Original]

{
    Here is the UMB_Heap unit i found in a copy of PC Magazine a while back..
This code works on my 486DX/2 66mhz with 4meg ram...    so it should (i hope)
run on yourz too....    All you need to do to use this is just call
Extend_Heap in your program someplace to get the extra heap memory, and
GetBlockSizes if you wish to know how large the UMB blocks are that were
allocated...


}

Unit
  UMB_Heap;

Interface

Const
  Max_Blocks      = 4;

Type
  UMBDataType = Array[1..Max_Blocks] Of Word;

Procedure Extend_Heap;
Procedure GetBlockSizes(Var US : UMBDataType);

Implementation

Type
  PFreeRec        = ^TFreeRec;
  TFreeRec        = Record
    Next          : PFreeRec;
    Size          : Pointer;
  End;

Var
  Block_Segments  : UMBDataType;
  Block_Sizes     : UMBDataType;
  SaveExitProc    : Pointer;

Function UMB_Driver_Present : Boolean;

Var
  Flag            : Boolean;

Begin
  Flag := False;
  Asm
    Mov   AX, $4300
    Int   $2F
    CMP   AL, $80
    JNE   @Done
    Inc   [Flag]
  @Done:
  End;
  UMB_Driver_Present := Flag;
End;

Procedure Allocate_UMB;

Var
  I,
  Save_Strategy,
  Block_Segment,
  Block_Size      : Word;

Begin
  For I := 1 To Max_Blocks Do
    Begin
      Block_Segments[I] := 0;
      Block_Sizes[I] := 0;
    End;
  Asm
    Mov   AX, $5801
    Mov   BX, $0FFFF
    Int   $21
    Mov   AX, $5803
    Mov   BX, $0001
    Int   $21
  End;
  For I := 1 To Max_Blocks Do
    Begin
      Block_Segment := 0;
      Block_Size := 0;
      Asm
        Mov   AX, $4800
        Mov   BX, $0FFFF
        Int   $21
        CMP   BX, 0
        JE    @Fail
        Mov   AX, $4800
        Int   $21
        JC    @Fail
        Mov   [Block_Segment], AX
        Mov   [Block_Size], BX
      @Fail:
      End;
      Block_Segments[I] := Block_Segment;
      Block_Sizes[I] := Block_Size;
    End;
End;

Procedure Release_UMB; Far;

Var
  I,
  Segment : Word;

Begin
  ExitProc := SaveExitProc;
  Asm
    Mov   AX, $5803
    Mov   BX, $0000
    Int   $21
  End;
  For I := 1 To Max_Blocks Do
    Begin
      Segment := Block_Segments[I];
      If (Segment > 0) Then
        Asm
          Mov   AX, $4901
          Mov   BX, [Segment]
          Mov   ES, BX
          Int   $21
        End;
    End;
End;

Function Pointer_To_LongInt(p : Pointer) : LongInt;

Type
  PtrRec          = Record
    Lo, Hi        : Word;
  End;

Begin
  Pointer_To_LongInt := LongInt(PtrRec(P).Hi * 16 + PtrRec(P).Lo);
End;

Procedure Extend_Heap;

Var
  I               : Word;
  Temp            : PFreeRec;

Begin
  If UMB_Driver_Present then
    Begin
      Allocate_UMB;
      Temp := HeapPtr;
      I := 1;
      While ((Block_Sizes[I] > 0) And
             (I <= Max_Blocks)) Do
        Begin
          Temp^.Next := Ptr(Block_Segments[I], 0);
          Temp       := Temp^.Next;
          Temp^.Next := HeapPtr;
          Move(Block_Sizes[I], Temp^.Size, SizeOf(Word));
          Temp^.Size := Pointer(LongInt(Temp^.Size) SHL 16);
          Inc(I);
        End;
      If (Block_Sizes[1] > 0) then
        FreeList := Ptr(Block_Segments[1], 0);
    End;
End;

Procedure GetBlockSizes(Var US : UMBDataType);

Begin
  US := Block_Sizes;
End;

Begin
  FillChar(Block_Sizes, SizeOf(Block_Sizes), 0);
  SaveExitProc := ExitProc;
  ExitProc := @Release_UMB;
End.

[Back to MEMORY SWAG index]  [Back to Main SWAG index]  [Original]