{XMSEXAM.PAS / EXAMPLE FOR FADE XMS ROUTINES}
{WRITING BY THE KING IN 01/02/96            }
Uses Crt;

Type
{This is a struct for move block via XMS to Conventional Memory}
{Or Conventional Memory To XMS}

    XmsMoveStruct = Record
        Length  : LongInt;   {The LENGTH of the block in BYTES}
        SHandle : Word;      {Source Handle}
        SOffset : Longint;   {Source Offset}
        DHandle : Word;      {Destinaton Handle}
        DOffset : Longint;   {Destinaton Offset}
    End;
Var
    XMove : XmsMoveStruct;   {An Xms Move Stuct , for moving}
    Xms_Address : LongInt;   {The Address to the software interrupt}
    Handle : Word;           {Handle for allocate memory}

{-----------------------------------------------}
{       Checking If XMS Program Installed       }
{-----------------------------------------------}

Function XMSInstalled:Boolean;
var
    Installed : Boolean;
Begin
Asm
    Mov ax,4300h    {Function Ax=4300, Int 2Fh , Checking XMS INSTALLED}
    Int 2fh
    Cmp al,80h      {If Al=80h mean that XMS found.}
    je @found
    Mov Installed,0 {Else Installed = False}
    Jmp @Exit       {Exit}
@Found:
    Mov Installed,1 {In Case XMS INSTALLED , Installed = True}
@Exit:
End;
    XmsInstalled := Installed;  {Return to function result}
End;

{-----------------------------------------------}
{     Get the XMS software intterupt handle.    }
{-----------------------------------------------}

Procedure Get_XMS_Address;
Begin
    Asm
        Mov Ax,4310h     {Function Ax=4310h , Int 2Fh , Get Handle Of Xms}
        Int 2fh          {Interrupt.}
        Mov Word Ptr [Xms_Address+2],Es  {Moving to The Hi Word Of Handle
                                          The Hi Word of the Interrupt.}
        mov word ptr [Xms_Address],Bx    {Moving to The Low Word Of Handle
                                          The Low Word of the Interrupt.}
    End;
End;

{-----------------------------------------------}
{            Allocate Memory to handle.         }
{-----------------------------------------------}
Function AllocateMemory(Var Handle : Word;AllocK:Word) : Boolean;Assembler;
asm
    mov ah,09h            {Function Ah=09 , Allocate Memory}
    Mov Dx,AllocK         {Dx=the size to allocate in KB}
    Call Xms_Address      {Calling the interrupt}
    Les Di,Handle         {[Es:Di] = Handle}
    Mov [Es:Di],Dx        {[Es:Di] = Allocated Handle}
End;

{-----------------------------------------------}
{            Free Memory From handle.           }
{-----------------------------------------------}

Function FreeMemory(Handle : Word):Boolean;assembler;
asm
    Mov Ah,0Ah        {Function Ah=0Ah , Free Memory}
    Mov Dx,Handle     {Dx=Handle}
    Call Xms_Address  {Calling Intterupt}
end;

{-----------------------------------------------}
{    Reallocated Memory Without losing data     }
{-----------------------------------------------}

Function ReAllocMemory(Handle:Word;NewSize:Word):Boolean;Assembler;
Asm
    Mov Ah,0Fh        {Function Ah=0Fh , Reallocate memory}
    Mov Bx,NewSize    {Bx = New Size}
    Mov Dx,Handle     {Dx = Handle}
    Call Xms_Address  {Calling Interrupt}
End;


{-----------------------------------------------}
{ Moving Memory Form Convertional memory To XMS }
{-----------------------------------------------}

Function   RealToXms(Size:LongInt;Source:LongInt;DHandle:Word) : Boolean;
Var
    Ok : Boolean;
Begin
    {Building Struct}
    XMove.Length  := Size;
    XMove.Shandle := 0;
    XMove.SOffset := Source;
    XMove.Dhandle := Dhandle;
    XMove.DOffset := 0;
    Asm
        Mov Ah,0Bh       {Function Ah=0Bh , Moving Memory}
        Lea SI,XMove     {[Ds:Si] = XMove}
        Call Xms_Address {Calling Interrupt}
        Mov Ok,Al
    End;
    RealToXms := Ok;
End;

{-----------------------------------------------}
{ Moving Memory Form XMS To Convertional memory }
{-----------------------------------------------}

Function   XmsToReal(Size:LongInt;SHandle:Word;Dest:LongInt) : Boolean;
Var
    Ok : Boolean;
Begin
    XMove.Length  := Size;
    XMove.Shandle := SHandle;
    XMove.SOffset := 0;
    XMove.Dhandle := 0;
    XMove.DOffset := Dest;
    Asm
        Mov Ah,0Bh             {Function Ah=0Bh , Moving Memory}
        Lea SI,XMove           {[Ds:Si] = XMove}
        Call Xms_Address       {Calling Interrupt}
        Mov Ok,Al
    End;
    XmsToReal := Ok;
End;

{---------------------------------------------}
{           Return Free XMS Memory            }
{---------------------------------------------}

Function FreeMem : Word;Assembler;
Asm
    Mov Ah,8h            {Ah = 08h , Return Free Memory}
    Call Xms_address     {Calling Interrupt}
End;

Begin
    If XMSINSTALLED Then
    Begin
        Writeln('XMS Found.');
        Get_XMS_Address;
        Writeln('Total free memory = ',FreeMem,'Kb');
        Writeln;
        Writeln('Press Enter to try to Move the screen memory to XMS');
        Readln;

        If Not AllocateMemory(Handle,8) Then
        Begin
            Writeln('Cant Allocate 8k of memory in XMS');
            Halt;
        End;
        If Not RealToXms(8000,LongInt(Ptr($0b800,0)),Handle) Then
        Begin
            Writeln('Cant Move From Convertsional memory to XMS.');
            Halt;
        End;
        ClrScr;
        Writeln('Memory Moved Successfull..');
        Writeln('Press Enter To Restore the memory screen from XMS');
        Readln;
        If Not XmsToReal(8000,Handle,LongInt(Ptr($0b800,0))) Then
        Begin
            Writeln('Cant Move From XMS To Convertsiomal memory.');
            Halt;
        End;
        If Not FreeMemory(Handle) Then
        Begin
            Writeln('Cant Free Memory...');
            Halt;
        End;
        Gotoxy(1,24);
        Writeln('Well everything is ok ! :) Press enter to return.');
        readln;

    End
    Else
        Writeln('XMS Not Found.');
End.
#include "kmagunit.c"

virtualscreen