XMS Memory Manager

Unit: XMS

Extended memory (XMS) access via HIMEM.SYS (1992, KIV without Co).

Types

type
  EMMstruct = record
    Size: LongInt;    { Transfer size in bytes }
    SOH: Word;        { Source handle (0=conventional memory) }
    SOO: LongInt;     { Source offset }
    DSH: Word;        { Destination handle (0=conventional memory) }
    DSO: LongInt;     { Destination offset }
  end;

Globals

var
  XMSerror: Byte;   { Last error code }

Functions

Detection

function XMSinstalled: Boolean;

Memory Allocation

procedure GetXMSmem(var Total, Block: Word);
function AllocXMS(KB: Word): Word;               { Returns handle }
function ReallocXMS(Handle: Word; KB: Word): Boolean;
procedure FreeXMS(Handle: Word);

Transfer

procedure MoveXMS(var EMM: EMMstruct);
procedure Mem2Xms(var Buf; Count: Word; Handle: Word; Offset: LongInt);
procedure Xms2Mem(Handle: Word; Offset: LongInt; var Buf; Count: Word);

Locking

function LockBlock(Handle: Word; var Address: LongInt): Boolean;
function UnlockBlock(Handle: Word): Boolean;

Info

procedure GetXMShandleInfo(Handle: Word; var LockCount, FreeHandles, Size: Word);
function XMSerrorMSG(Error: Byte): string;

HMA

function RequestHMA(Mem: Word): Boolean;
procedure ReleaseHMA;

Example (Sound Bank)

uses XMS, SBDSP;

var
  Handle: Word;
  Buffer: array[0..16383] of Byte;
begin
  if not XMSinstalled then
  begin
    WriteLn('HIMEM.SYS not loaded!');
    Exit;
  end;

  { Allocate 64KB XMS }
  Handle := AllocXMS(64);
  if Handle = 0 then
  begin
    WriteLn('XMS allocation failed: ', XMSerrorMSG(XMSerror));
    Exit;
  end;

  { Upload sound data }
  Mem2Xms(Buffer, SizeOf(Buffer), Handle, 0);

  { Download to DMA buffer }
  Xms2Mem(Handle, 0, Buffer, SizeOf(Buffer));

  { Free XMS memory }
  FreeXMS(Handle);
end;

Critical: Handle=0 Convention

When Handle=0 in EMMstruct, offset is pointer (Seg:Ofs), NOT linear address:

var
  EMM: EMMstruct;
  Buf: array[0..1023] of Byte;
begin
  EMM.Size := 1024;
  EMM.SOH := 0;                          { Source = conventional memory }
  EMM.SOO := LongInt(@Buf);              { Pointer (Seg:Ofs) }
  EMM.DSH := XMSHandle;                  { Dest = XMS memory }
  EMM.DSO := 0;                          { Linear offset }
  MoveXMS(EMM);
end;

Error Codes

Code

Message

0x80

Not implemented

0x81

VDISK detected

0x82

A20 error

0xA0

All memory allocated

0xA1

All handles allocated

0xA2

Invalid handle

0xA3

Source handle invalid

0xA4

Source offset invalid

0xA5

Destination handle invalid

0xA6

Destination offset invalid

0xA7

Length invalid

0xAB

Block locked

0xAC

Block locked

Requirements

  • HIMEM.SYS in CONFIG.SYS:

    DEVICE=C:\DOS\HIMEM.SYS
    

Notes

  • Used by SNDBANK for large sound buffers

  • Max 286/386 extended memory (above 1MB)

  • Handles DMA 64KB boundary crossing automatically in SNDBANK

  • GetXMSmem returns total and largest block in KB