[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]
{This unit is a kit to EMS functions.}
Unit EMSLib;
{ Copyright (c) 1994 by Andrew Eigus FidoNet: 2:5100/33 }
{ LIM EMS Interface V1.01 for Turbo Pascal version 7.0 }
(*
Material used:
Interrupt List V1.02 (WindowBook) (c) 1984-90 Box Company, Inc.
Tech Help V4.50
*)
{$X+} { Enable extended syntax }
{$G+} { Enable 286 instructions }
interface
const
PageSize = 16384; { EMS Page size: 16384 bytes }
{ LIM EMS 3+ function numbers }
EGetPageFrame = $41;
EGetPageCount = $42;
EAllocPages = $43;
EMapPages = $44;
EReleasePages = $45;
EGetVersion = $46;
{ LIM EMS functions result codes }
emsrOk = $00; { Function successful }
emsrNotInitd = $01; { EMS not installed }
emsrIntrnlError = $80; { Internal error }
emsrHardwareMalf = $81; { Hardware malfunction }
emsrBadHandle = $83; { Invalid handle }
emsrBadFunction = $84; { Undefined function requested }
emsrNoMoreHandles = $85; { No more handles available }
emsrMapContError = $86; { Error in save or restore of mapping context }
emsrMorePagesPhys = $87; { More pages requested than physically exist }
emsrMorePagesCurr = $88; { More pages requested than currently available }
emsrZeroPages = $89; { Zero pages requested }
emsrBadPageLogNum = $8A; { Invalid page logical number }
emsrBadPagePhyNum = $8B; { Invalid page physical number }
function EMS_Setup : boolean;
function EMS_GetVersion(var Version : byte) : byte;
function EMS_GetMemAvail(var FreeMem : word) : byte;
function EMS_AllocEMB(var Handle, PageSeg : word; Pages : word) : byte;
function EMS_FreeEMB(Handle : word) : byte;
function EMS_MapPages(Handle, LogicalPage : word; PhysicalPage : byte) : byte;
function EMS_GetErrorMsg(ErrorCode : byte) : string;
implementation
const
DOS = $21; { DOS interrupt number }
EMS = $67; { EMS interrupt number }
var
EMSInitd : boolean;
Function EMS_Setup; assembler;
{ EMM Installation check }
const DeviceDriver : PChar = 'EMMXXXX0';
Asm
MOV EMSInitd,False
PUSH DS
MOV AX,3D02h { DOS function to open the device as file }
LDS DX,DeviceDriver
INT DOS
POP DS
JC @@1
PUSH AX { store device handle to close the file afterwards }
MOV AX,4407h { DOS function to test device status }
INT DOS
MOV EMSInitd,AL
POP BX
MOV AH,3Eh { close the file using it's handle in BX }
INT DOS
@@1:
MOV AL,EMSInitd
End; { EMS_Setup }
Function EMS_GetVersion; assembler;
{ Get Expanded Memory Manager version number }
Asm
MOV AL,emsrNotInitd
CMP EMSInitd,False { If library not initialized by EMS_Setup }
JE @@1 { then exit }
MOV AH,EGetVersion { Get EMS version }
INT EMS
LES DI,Version
MOV [ES:DI],AL { Store version number }
MOV AL,AH { Store result byte }
@@1:
End; { EMS_GetVersion }
Function EMS_GetMemAvail; assembler;
{ Returns free memory in FreeMem parameter }
Asm
MOV AL,emsrNotInitd
CMP EMSInitd,False
JE @@1
MOV AH,EGetPageCount
INT EMS
SHL BX,4 { Got in pages, convert to K-bytes }
LES DI,FreeMem
MOV [ES:DI],BX { Store memory available in K-Bytes }
MOV AL,AH { Store result byte }
@@1:
End; { EMS_GetMemAvail }
Function EMS_AllocEMB; assembler;
{ Allocates specified number of 16 K-byte pages and returns handle number in
Handle parameter. Page frame segment address stored in PageSeg. To access
data, use the following function:
DataPtr := Ptr(PageSeg, PhysicalPageNumber * PageSize) }
Asm
MOV AL,emsrNotInitd
CMP EMSInitd,False
JE @@2
MOV AH,EGetPageFrame
INT EMS
CMP AH,0
JNE @@1
LES DI,PageSeg { Store page frame segment }
MOV [ES:DI],BX
MOV BX,Pages
MOV AH,EAllocPages
INT EMS
LES DI,Handle
MOV [ES:DI],DX { Store handle number }
@@1:
MOV AL,AH { Return result code }
@@2:
End; { EMS_AllocEMB }
Function EMS_FreeEMB; assembler;
{ Deallocates (releases) allocated expanded memory }
Asm
MOV AL,emsrNotInitd
CMP EMSInitd,False
JE @@1
MOV AH,EReleasePages
MOV DX,Handle
INT EMS
MOV AL,AH { Return result code }
@@1:
End; { EMS_FreeEMB }
Function EMS_MapPages; assembler;
{ Maps a logical page number at physical page number }
Asm
MOV AL,emsrNotInitd
CMP EMSInitd,False
JE @@1
MOV AH,EMapPages
MOV DX,Handle
MOV BX,LogicalPage
MOV AL,PhysicalPage
INT EMS
MOV AL,AH
@@1:
End; { EMS_MapPages }
Function EMS_GetErrorMsg;
{ Get an error message according to ErrorCode }
Begin
case ErrorCode of
emsrNotInitd: EMS_GetErrorMsg := 'EMM not initialized';
emsrIntrnlError: EMS_GetErrorMsg := 'Internal error';
emsrHardwareMalf: EMS_GetErrorMsg := 'Hardware malfunction';
emsrBadHandle: EMS_GetErrorMsg := 'Invalid block handle';
emsrBadFunction: EMS_GetErrorMsg := 'Function not implemented';
emsrNoMoreHandles: EMS_GetErrorMsg := 'No more handles available';
emsrMapContError: EMS_GetErrorMsg := 'Error in save or restore of ' +
'mapping context';
emsrMorePagesPhys: EMS_GetErrorMsg := 'More pages requested than ' +
'physically exist';
emsrMorePagesCurr: EMS_GetErrorMsg := 'More pages requested than ' +
'currently available';
emsrZeroPages: EMS_GetErrorMsg := 'Zero pages requested';
emsrBadPageLogNum: EMS_GetErrorMsg := 'Invalid page logical number';
emsrBadPagePhyNum: EMS_GetErrorMsg := 'Invalid page physical number';
else EMS_GetErrorMsg := 'Unknown error'
end
End; { EMS_GetErrorMsg }
Begin
EMSInitd := False
End. { EMSLib }
{ -------------------------- DEMO --------------------------------- }
Program EMSLibDemo;
{ Copyright (c) 1994 by Andrew Eigus FidoNet: 2:5100/33 }
{ LIM EMS Interface V1.01 for Turbo Pascal version 7.0 demonstration program }
(*
Tested on IBM 486 SX 33Mhz with 4MB RAM with the following configuration:
HIMEM.SYS (MS-DOS 6.2 XMS memory manager)
EMM386.EXE (MS-DOS 6.2 EMS memory manager)
If any bugs occur in your system while running this demo,
please inform me:
AndRew's BBS Phone: 003-712-559777 (Riga, Latvia) 24h 2400bps
Voice Phone: 003-712-553218
FidoNet: 2:5100/33
E-Mail: aeigus@fgate.castle.riga.lv
*)
{$X+}{$R-} { Enable extended syntax }
uses EMSLib;
type TMsg = array[1..13] of Char;
const
Message1 : TMsg = 'First string ';
Message2 : TMsg = 'Second string';
var
Version : byte;
FreeMemory, Handle, SegAddr, I : word;
P : pointer;
Function Hex(Num : longint; Places : byte) : string;
const HexTab : array[0..15] of Char = '0123456789ABCDEF';
var
HS : string[8];
Digit : byte;
Begin
HS[0] := Chr(Places);
for Digit := Places downto 1 do
begin
HS[Digit] := HexTab[Num and $0000000F];
Num := Num shr 4
end;
Hex := HS
End; { Hex }
Function Check(Result : byte; Func : string) : byte;
Begin
if Result <> emsrOk then
WriteLn(Func, ' returned ',
Hex(Result, 2), 'h (', Result, '): ', EMS_GetErrorMsg(Result));
Check := Result
End; { Check }
Procedure PrintFreeMemory;
Begin
WriteLn;
if Check(EMS_GetMemAvail(FreeMemory), 'EMS_GetMemAvail') = emsrOk then
WriteLn('EMS memory available: ', FreeMemory, ' KB');
WriteLn
End; { PrintFreeMemory }
Begin
WriteLn('LIM EMS Library V1.01 Demonstration program by Andrew Eigus'#10);
if EMS_Setup then
begin
if Check(EMS_GetVersion(Version), 'EMS_GetVersion') = emsrOk then
WriteLn('EMS driver version ',
Version shr 4, '.', Version shr 8, ' detected');
PrintFreeMemory;
if FreeMemory = 0 then Halt(8);
if Check(EMS_AllocEMB(Handle, SegAddr, 1), 'EMS_AllocEMB') = emsrOk then
begin
WriteLn('Message1: ', Message1);
WriteLn('Message2: ', Message2);
WriteLn('16 KB (one page) of EMS allocated. Linear address: ',
Hex(SegAddr, 8), 'h');
PrintFreeMemory;
WriteLn('Transferring Message1 to EMS...');
for I := 0 to SizeOf(TMsg) - 1 do
EMS_MapPages(Handle, I, 0);
P := Ptr(SegAddr, 0);
Move(Message1, P^, SizeOf(TMsg));
WriteLn('Transferring Message1 from EMS to Message2...');
Move(P^, Message2, SizeOf(TMsg));
WriteLn('Message1: ', Message1);
WriteLn('Message2: ', Message2);
if Check(EMS_FreeEMB(Handle), 'EMS_FreeEMB') = emsrOk then
begin
WriteLn('Memory deallocated (released). ');
PrintFreeMemory
end
end
end else
WriteLn('EMM386 manager not installed.');
End.
[Back to MEMORY SWAG index] [Back to Main SWAG index] [Original]