unit Mem;

{$F+,S-}

interface

procedure InitMem;
procedure SaveEms;
procedure RestoreEms;
procedure SaveMem;
procedure RestoreMem;
function  AllocMem(Size: Word; UseEms: Boolean): Word;

const

  WindowHeapSize: Word = 32 * 1024 div 16;
  EditorHeapSize: Word = 28 * 1024 div 16;
  OverlayHeapSize: Word = 112 * 1024 div 16;

  EditorHeapOrg: Word = 0;

  MemPtr: Word = 0;
  MemTop: Word = 0;
  SaveMemPtr: Word = 0;

  EmsPtr: Word = 0;
  EmsTop: Word = 0;
  SaveEmsPtr: Word = 0;
  EmsInUse: Boolean = True;
  EmsVersion: Byte = 0;
  EmsHandle: Word = 0;

implementation

uses Objects;

var
  SaveExit: Pointer;

procedure DoneEms; assembler;
asm
        MOV     DX,EmsHandle
        MOV     AH,45H
        INT     67H
        LES     AX,SaveExit
        MOV     ExitProc.Word[0],AX
        MOV     ExitProc.Word[2],ES
end;

procedure InitEms; near; assembler;
const
  EmsDeviceLen = 8;
  EmsDeviceStr: array [1..EmsDeviceLen] of Char = 'EMMXXXX0';
asm
        CMP     EmsInUse,0
        JE      @@1
        MOV     AX,3567H
        INT     21H
        MOV     CX,EmsDeviceLen
        MOV     SI,OFFSET EmsDeviceStr
        MOV     DI,0AH
        CLD
        REPE    CMPSB
        JNE     @@1
        MOV     BX,3
        MOV     AH,43H
        INT     67H
        OR      AH,AH
        JNZ     @@1
        MOV     EmsHandle,DX
        MOV     AH,41H
        INT     67H
        ADD     BX,400H
        MOV     EmsPtr,BX
        ADD     BX,0C00H
        MOV     EmsTop,BX
        MOV     AH,46H
        INT     67H
        MOV     EmsVersion,AL
        LES     AX,ExitProc
        MOV     SaveExit.Word[0],AX
        MOV     SaveExit.Word[2],ES
        MOV     ExitProc.Word[0],OFFSET DoneEms
        MOV     ExitProc.Word[2],CS
@@1:
end;

procedure InitMem;
begin
  InitEms;
  MemPtr := OvrHeapOrg;
  MemTop := PtrRec(HeapEnd).Seg;
  PtrRec(HeapOrg).Seg := AllocMem(WindowHeapSize, False);
  PtrRec(HeapEnd).Seg := MemPtr;
  Release(HeapOrg);
  EditorHeapOrg := AllocMem(EditorHeapSize, True);
  OvrHeapOrg := AllocMem(OverlayHeapSize, False);
  OvrHeapPtr := OvrHeapOrg;
  OvrHeapEnd := MemPtr;
end;

procedure SaveEms; assembler;
asm
        MOV     DX,EmsHandle
        OR      DX,DX
        JZ      @@2
        MOV     AH,47H
        INT     67H
        XOR     BX,BX
@@1:    MOV     AH,44H
        MOV     AL,BL
        INC     AX
        INT     67H
        INC     BX
        CMP     BL,3
        JNE     @@1
        MOV     AX,-1
        MOV     EmsCurHandle,AX
        MOV     EmsCurPage,AX
@@2:
end;

procedure RestoreEms; assembler;
asm
        MOV     DX,EmsHandle
        OR      DX,DX
        JZ      @@1
        MOV     AH,48H
        INT     67H
@@1:
end;

procedure SaveMem; assembler;
asm
        CALL    SaveEms
        MOV     AX,MemPtr
        MOV     SaveMemPtr,AX
        MOV     AX,EmsPtr
        MOV     SaveEmsPtr,AX
end;

procedure RestoreMem; assembler;
asm
        MOV     AX,SaveMemPtr
        MOV     MemPtr,AX
        MOV     AX,SaveEmsPtr
        MOV     EmsPtr,AX
        CALL    RestoreEms
end;

function AllocMem(Size: Word; UseEms: Boolean): Word; assembler;
asm
        CMP     UseEms,0
        JE      @@1
        MOV     AX,EmsPtr
        MOV     DX,Size
        ADD     DX,AX
        JC      @@1
        CMP     DX,EmsTop
        JA      @@1
        MOV     EmsPtr,DX
        JMP     @@2
@@1:    MOV     AX,MemPtr
        MOV     DX,Size
        ADD     MemPtr,DX
@@2:
end;

end.
