{**************************************************************************
*   EMS - unit of EMS functions                                           *
*   Copyright (c) 1991,1993 Kim Kokkonen, TurboPower Software.            *
*   May be freely distributed and used but not sold except by permission. *
*                                                                         *
*   Version 3.0 9/24/91                                                   *
*     first release                                                       *
*   Version 3.1 11/4/91                                                   *
*     no change                                                           *
*   Version 3.2 11/22/91                                                  *
*     no change                                                           *
*   Version 3.3 1/8/92                                                    *
*     no change                                                           *
*   Version 3.4 2/14/92                                                   *
*     no change                                                           *
*   Version 3.5 10/18/93                                                  *
*     add RestorePageMap function                                         *
*     change FreeEms to return a Byte status code                         *
***************************************************************************}

{$R-,S-,I-,V-,B-,F-,A-,E-,N-,G-,X-}

unit Ems;
  {-EMS functions needed for MAPMEM, MARKNET, RELNET}

interface

const
  MaxHandles = 255;
  EmsDevice : string[8] = 'EMMXXXX0';
type
  HandlePageRecord =
  record
    Handle : Word;
    NumPages : Word;
  end;
  PageArray = array[1..MaxHandles] of HandlePageRecord;
  PageArrayPtr = ^PageArray;

function EmsPresent : Boolean;
  {-Return true if EMS memory manager is present}

function EmsPagesAvailable : LongInt;
  {-Return Total pages in high word, Available pages in low word}

function EmsHandles(var PageMap : PageArray) : Word;
  {-Return number of handles allocated and page map}

function EmsVersion : Byte;
  {-Return EMM version number}

procedure GetHandleName(Handle : Word; var Name : String);
  {-Return name of EMS block, if any}

function FreeEms(Handle : Word) : Byte;
  {-Deallocate EMS handle}

function RestorePageMap(Handle : Word) : Byte;
  {-Restore page map}

  {=========================================================================}

implementation

  function EMSpresent : Boolean; assembler;
    {-Return true if EMS memory manager is present}
  asm
    mov ax,$3567
    int $21
    mov ax,es
    or ax,bx            {is int $67 nil?}
    jz @AbsentNoClose
    cmp byte ptr es:[bx],$CF  {does int $67 point to iret?}
    je @AbsentNoClose
    mov dx,offset EmsDevice+1
    mov ax,$3D02
    int $21             {can we open EMM device?}
    mov bx,ax
    jc @AbsentNoClose
    mov ax,$4400
    int $21             {can we get its device properties?}
    jc @Absent
    and dx,$80          {does bit 7 = 1?}
    jz @Absent
    mov ax,$4407
    int $21             {device ready for output?}
    jc @Absent
    or al,al
    jz @Absent
    push bx
    mov ah,$30
    int $21
    pop bx
    xchg ah,al
    cmp ax,$030A
    jb @Present
    mov ax,$440A
    int $21             {local device?}
    jc @Present
    and dx,$8000
    jnz @Absent
@Present:
    mov ah,$3E           {close handle}
    int $21
    mov al,1
    jmp @Done
@Absent:
    mov ah,$3E           {close handle}
    int $21
@AbsentNoClose:
    xor ax,ax
@Done:
  end;

  function EmsPagesAvailable : LongInt; assembler;
    {-Return Total pages in high word, Available pages in low word}
  asm
    mov ah, $42
    int $67
    or ah,ah
    jnz @error
    mov ax,bx     {available pages now in ax}
    jmp @done
@error:
    xor ax,ax
    mov dx,ax
@done:
  end;

  function EmsHandles(var PageMap : PageArray) : Word; assembler;
    {-Return number of handles allocated and page map}
  asm
    mov ah,$4D
    les di,PageMap
    xor bx,bx
    int $67
    or ah,ah
    mov ax,bx
    jz @done
    xor ax,ax
@done:
  end;

  function EmsVersion : Byte; assembler;
    {-Return EMM version number}
  asm
    mov ah,$46
    int $67
    or ah,ah
    jz @Done
    xor al,al
@Done:
  end;

  procedure GetHandleName(Handle : Word; var Name : String); assembler;
    {-Return name of EMS block, if any}
  asm
    mov dx,Handle
    les di,Name
    mov si,di         {save offset}
    inc di            {point past length byte}
    mov ax,$5300
    int $67
    mov al,0          {assume zero length}
    or ah,ah
    jnz @Done
    mov cx,8
    xor al,al
    cld               {scan for null terminator}
    repne scasb
    mov al,8          {assume all 8 chars significant}
    jne @Done
    sub al,cl
    dec al
@Done:
    mov es:[si],al    {store length byte}
  end;

  function FreeEms(Handle : Word) : Byte; assembler;
    {-Deallocate EMS handle}
  asm
    mov ah,$45
    mov dx,Handle
    int $67
    mov al,ah
  end;

  function RestorePageMap(Handle : Word) : Byte; assembler;
    {-Restore page map}
  asm
    mov ah,$48
    mov dx,HAndle
    int $67
    mov al,ah
  end;

end.
