home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DP Tool Club 26
/
CD_ASCQ_26_1295.iso
/
voxrom
/
textes
/
repwin08
/
annexes
/
squirrel
/
mem2
/
memory.pas
next >
Wrap
Pascal/Delphi Source File
|
1995-10-01
|
35KB
|
1,194 lines
Unit memory;
INTERFACE
{================== EMS ====================================================}
Var Ems_Ver : word;
Ems_Seg : word;
Function Ems_Err (n : byte) : string;
Function Ems_Map (handle, logik : word; Physik : byte) : byte;
Function Ems_SaveMap (handle : word) : byte;
Function Ems_RestoreMap (handle : word) : byte;
Function Ems_Alloc (var handle : word; nbpages : word) : byte;
Function Ems_UnAlloc (handle : word) : byte;
Function Ems_GetTotalPages : word;
Function Ems_GetFreePages : word;
Function Ems_GetNbPages (handle : word) : word;
Function Ems_GetNbHandles : word;
Function Ems_GetHandles (var handles) : byte;
Function Ems_State : byte;
Function IsEms : boolean;
{================== XMS/HMA/UMB ============================================}
Var Xms_Ver : word;
Xms_Rev : word; { Révision interne }
Xms_Proc : procedure;
Xms_Errflag : byte;
Type ExMM = record { si un handle = 0 alors mémoire conventionelle }
size : longint; { Taille à déplacer }
src_handle : word; { Handle Source }
src_offset : longint; { Offset de début du bloc source }
cib_handle : word; { Handle Cible }
cib_offset : longint; { Offset de début du bloc cible }
end;
Function isXms : boolean;
Function Xms_Err (n : byte) : string;
Function Xms_ok : boolean;
Function Xms_GetHMA : boolean;
Function Xms_ReleaseHMA : boolean;
Function Xms_A20unlock : boolean;
Function Xms_A20lock : boolean;
Function Xms_A20localunlock : boolean;
Function Xms_A20locallock : boolean;
Function Xms_A20unlocked : boolean;
Function Xms_MaxAvail : word;
Function Xms_MemAvail : word;
Function Xms_Alloc (var handle : word; nbko : word) : boolean;
Function Xms_UnAlloc (handle : word) : boolean;
Function Xms_move (var e : ExMM) : boolean;
Function Xms_Lock (handle : word) : boolean;
Function Xms_UnLock (handle : word) : boolean;
Function Xms_NbLocked (handle : word) : byte; { Nombre de verrouillages }
Function Xms_GetEMBsize (handle : word) : word; { Taille en ko }
Function Xms_SetEMBsize (handle, NewSizeInko : word) : boolean;
Function Xms_UMBAlloc (size : word) : word; { Retourne l'adresse }
Function Xms_UMBMaxAvail : word; { taille du + gd bloc }
Function Xms_UMBunAlloc (segm : word) : boolean;
{================== Mémoire DOS/MCBs =======================================}
Type mcb = record
id : char; { M = à suivre, Z = dernier }
pspseg : word; { Adresse du psp père du bloc }
size : word; { Taille du block mémoire }
unused : array[1..3] of byte; { Pas touche ! }
name : array[1..8] of char; { DOS 4.x + seulement }
end;
ddhptr = ^ddh;
ddh = record
next : ddhptr;
attr : word; { attributs }
strategiePROC : word;
interruptPROC : word;
name : array[1..8] of char;
end;
psp = record
int20h : word;
endseg : word;
reserved1 : byte;
int21h : word;
int22h : word;
int23h : word;
int24h : word;
reserved2 : array[1..22] of byte;
envBlock : word; { adresse de segment de l'environnement }
reserved3 : array[1..46] of byte;
fcb1 : array[1..16] of byte;
fcb2 : array[1..20] of byte;
command : string[127];
end;
Function xm_FreeMem (var P: Pointer) : byte;
Function xm_GetMem (var P: Pointer; Size: longint) : byte;
Function xm_SetMem (var P: Pointer; Size: longint) : byte;
Function xm_MaxAvail : longint;
Function xm_GetSize (P: Pointer) : longint;
Function xm_useUMB (use : boolean) : boolean;
Function xm_isUMB : boolean;
Function xm_SetStrategy (strategy : word) : boolean;
Function xm_GetStrategy : byte;
Function GetDIB : pointer;
{==================== Fonctions systèmes ===================================}
Const Seg0000 : word = 0;
Const xm_ok = 0;
xm_mcb_failure = 7;
xm_no_more_mem = 8;
xm_not_mcb = 9;
Procedure SetIntVec (IntNo: word; Vector: Pointer);
Procedure GetIntVec (IntNo: word; var Vector: Pointer);
Procedure SetInDos;
Function GetInDos : byte;
Procedure SetPsp (s : word);
Function GetPsp : word;
Function ExePath : string;
Procedure Move (Var Source, Dest; Count: Word);
Procedure Xchg (Var Source, Dest; Count: Word);
Procedure FillChar (Var X; Count: Word; value: byte);
Procedure FillWord (Var X; Count: Word; value: word);
Procedure FillLong (Var X; Count: Word; value: longint);
Function DosVersion : word;
Function PHexa (n : pointer) : string;
Function Hexa (n : word) : string;
IMPLEMENTATION
{██████████████████████████████████████████████████████████████████████
╔════════════════════════════════════════════════════════════════════╗
║ Fonctions systèmes utilisées plus loin (pour certaines) ║
╚════════════════════════════════════════════════════════════════════╝
██████████████████████████████████████████████████████████████████████}
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie la valeur hexa d'un pointeur ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ La chaine de sortie est au format SSSS:OOOO ║
╚═════════════════════════════════════════════════════════════════════════╝}
const hex : array[0..15] of char = '0123456789ABCDEF';
Function PHexa (n : pointer) : string;
var i : byte;
s : string[9];
begin
s[0] := #8;
for i := 1 to 8 do begin
s[9-i] := hex[longint(n) AND 15];
longint(n) := longint(n) shr 4;
end;
insert (':', s, 5);
Phexa := s;
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie la correspondance hexa d'un nombre ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ La chaine de la sortie est ajusté au nombre de chiffres du nombre. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function Hexa (n : word) : string;
var i : byte;
s : string[8];
begin
s := '';
for i := 1 to 4 do begin
s := hex[n AND 15] + s;
n := n shr 4;
end;
hexa := s;
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie la version du Système d'exploitation ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Au format binaire, l'octet fort contient la version majeure et le ║
║ faible la version mineure ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function DosVersion : word;
assembler; asm
mov ah, 30h
int 21h
xchg al, ah
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Echange deux parties de mémoires ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ A la difference de Move, Xchg intervertit les données sources et cible. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure Xchg (Var Source, Dest; Count : Word);
assembler; asm { Pas de 32 bits ici, gain de temps insignifiant }
push ds
mov cx, count
les di, Dest
lds si, Source
shr cx, 1
@:mov ax, es:[di] { cible --> buffer }
movsw { source --> cible }
mov ds:[si-2], ax { cible --> source }
loop @
jnc @fin
mov al, es:[di]
movsb
mov ds:[si-1], al
@fin:
pop ds
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Copie une partie de mémoire sur une autre ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Move est identique à system.move, mais bien plus rapide, car en 32bits. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure Move (Var Source, Dest; Count : Word);
assembler; asm
push ds
cmp test8086, 1
mov cx, count
les di, Dest
lds si, Source
ja @32
@16: { 8086 & 286 }
shr cx, 1
rep movsw
rcl cx, 1
rep movsb
jmp @fin
@32: { 386 & 486 }
mov bx, cx
shr cx, 2
{ rep movsd } db $F3,$66,$A5
mov cx, bx
and cx, 3
rep movsb
@fin:
pop ds
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Remplit une zone mémoire de n octets identiques ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ FillChar fonctionne comme system.fillchar, mais est optimisée en 32bits ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure FillChar (Var X; Count : Word; value : byte);
assembler; asm
les di, X
mov cx, count
mov al, value
cmp test8086, 1
ja @32
@16:
mov ah, al
shr cx, 1
rep stosw
rcl cx, 1
rep stosb
jmp @fin
@32:
mov ah, al
push ax
push ax
{ pop eax } db $66,$58
mov bx, cx
and cx, 3
rep stosb
mov cx, bx
shr cx, 2
{ rep stosd } db $F3,$66,$AB
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Remplit une zone mémoire de n words identiques ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Comme FillChar, mais l'unité de base est ici le word. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure FillWord (Var X; Count : Word; value : word);
assembler; asm
les di, X
mov cx, count
mov ax, value
cmp test8086, 1
ja @32
@16:
rep stosw
jmp @fin
@32:
push ax
push ax
{ pop eax } db $66,$58
shr cx, 1
{ rep stosd } db $F3,$66,$AB
rcl cx, 1
rep stosw
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Remplit une zone mémoire avec n dwords identiques ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Comme FillChar et FillWord, FillLong remplit, mais avec des longint. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure FillLong (Var X; Count : Word; value : longint);
assembler; asm
les di, X
mov cx, count
mov ax, word ptr value
mov dx, word ptr value +2
cmp test8086, 1
ja @32
@16: mov es:[di+0], ax
mov es:[di+2], dx
add di, 4
loop @16
jmp @fin
@32:
push dx
push ax
{ pop eax } db $66,$58
{ rep stosd } db $F3,$66,$AB
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie le répertoire où est le programme .exe tournant ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ La fonction ne fait la recherche qu'une fois, lors de son 1° appel ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function ExePath : string;
Const Path : string = '';
Var i : byte;
Begin
IF Path = '' then begin
Path := paramstr(0);
for i := ord(Path[0]) downto 1 do
if Path[i] = '\' then begin
Path := copy(Path, 1, i-1);
if path[0] = #2 then path := path + '\';
break;
end;
end;
ExePath := Path;
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Charge l'adresse du flag indos ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Vous pouvez ensuite accéder à Indos via Getindos ║
╚═════════════════════════════════════════════════════════════════════════╝}
Var indos : ^byte;
Procedure SetInDos;
assembler; asm
mov ah, 34h
int 21h
mov indos.0.word, bx
mov indos.2.word, es
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Lit le flag indos ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Si indos contient la valeur >0, alors Le dos est actif ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function GetInDos : byte;
assembler; asm
les bx, indos
mov al, es:[bx]
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Fixe un vecteur d'interruption ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Fonctionne comme dos.setintvec ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure SetIntVec (IntNo : word; Vector: Pointer);
assembler; asm
pushf
push ds
mov es, Seg0000
mov di, IntNo
shl di, 2
{ N'utilise pas le dos, donc 10 * + rapide }
cli
lds si, vector
mov es:[di+2], ds
mov es:[di+0], si
pop ds
popf
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Prend connaissance d'un vecteur d'interruption ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Fonctionne comme dos.getintvec ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure GetIntVec (IntNo : word; var Vector: Pointer);
assembler; asm
push ds
les di, vector
mov ds, Seg0000
mov si, IntNo
shl si, 2
movsw
movsw
pop ds
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Fixe le psp actif ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ s est le segment (word) indiquant le début du programme (cseg) ║
╚═════════════════════════════════════════════════════════════════════════╝}
Procedure SetPsp (s : word);
assembler; asm
mov ah, 50h
mov bx, s
int 21h
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Lit le segment de psp actif ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function GetPsp : word;
assembler; asm
mov ah, 51h
int 21h
mov ax, bx
end;
{██████████████████████████████████████████████████████████████████████
╔════════════════════════════════════════════════════════════════════╗
║ Fonctions d'accès à la mémoire DOS dont UMBs ║
╚════════════════════════════════════════════════════════════════════╝
██████████████████████████████████████████████████████████████████████}
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Get dos information Bloc ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function GetDIB : pointer;
assembler; asm
mov ah, 52h
int 21h
mov dx, es
mov ax, bx
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Détermine si les UMBs sont inclus dans la gestion mémoire ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ use = true alors les UMBs sont gérés ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_useUMB (use : boolean) : boolean;
assembler; asm
mov ax, 5803h
mov bx, word ptr use
int 21h
mov ax, -1
adc ax, 0
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie TRUE si les UMBs sont inclus dans la mémoire ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_isUMB : boolean;
assembler; asm
mov ax, 5802h
int 21h
and ax, not 1
xor ax, 1
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Choisis la stratégie d'allocation mémoire ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ 1 = Premier bloc convenable ║
║ 2 = Meilleur bloc convenable ║
║ 3 = Dernier bloc convenable ║
║ Avec le DOS 5 : Bit 7 (+128) donne la priorité aux UMBs ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_SetStrategy (strategy : word) : boolean;
assembler; asm
mov ax, 5801h
mov bx, strategy
int 21h
mov ax, -1
adc ax, 0 { ajoute la carry }
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Obtient la stratégie actuelle ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_GetStrategy : byte;
assembler; asm
mov ax, 5800h
int 21h { renvoie la stratégie dans ax }
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie la taille occupée par une zone mémoire externe ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ La taille est en octets. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_GetSize (P: Pointer) : longint;
assembler; asm
les bx, p { obtenir l'adresse du block mémoire }
mov bx, es
cmp bx, 0 { NIL ? }
jne @ok
mov ax, 0 { oui, }
mov dx, 0 { Renvoyer 0 }
jmp @fin
@ok:
dec bx { mcb = block mémoire - 1 }
mov es, bx
mov ax, es:mcb.size { Renvoyer la taille }
mov bx, 16 { multipliée par 16 }
mul bx { dans dx:ax }
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Renvoie la taille de la mémoire externe disponible ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Le nombre renvoyé est en octets et indique la taille DU PLUS GRAND ║
║ BLOC disponible ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_MaxAvail : longint;
assembler; asm
mov ah, 48h { Allouer }
mov bx, $FFFF { toute la mémoire }
int 21h { Impossible, d'où erreur }
mov ax, 16 { Renvoie le nb de para libres ds bx }
mul bx { Qu'il suffit de * par 16 }
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Change la taille d'une zone mémoire externe ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Utilise les mcbs. La taille à fournir est en octets et est arrondie au ║
║ 16 octets supérieurs (paragraphe). ║
║ Le maximum adressable est fonction de la taille maximum disponible ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_SetMem (var P: Pointer; Size: longint) : byte;
assembler; asm
mov ah, 4Ah { Modifier une taille }
les bx, p { Pointer sur la zone à modifier }
mov bx, size.word.0 { poids faible }
shr bx, 4 { diviser par 16 }
mov dx, size.word.2 { poids fort }
and dl, 1111b { ne garder que le nibble extra low }
shl dl, 4 { le déplacer sur le nibble high }
or bh, dl { qu'on additione au poids faible }
test size.byte, 15 { Vérifier si size mod 16 = 0 }
jz @resize { oui, on économise 16 octets }
inc bx { non, on pêche par excès }
@resize:
int 21h { Maintenant, au dos de jouer ! }
jc @fin { erreur, al = 7, 8 ou 9 }
mov al, xm_ok { aucune erreur }
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Alloue un bloc mémoire externe ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ Utilise les mcbs. La taille à fournir est en octets et est arrondie au ║
║ 16 octets supérieurs (paragraphe). ║
║ Le maximum adressable est fonction de la taille maximum disponible ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_GetMem (var P: Pointer; Size: longint) : byte;
assembler; asm
mov ah, 48h { Créer un block }
mov bx, size.word.0 { poids faible }
shr bx, 4 { diviser par 16 }
mov dx, size.word.2 { poids fort }
and dl, 1111b { ne garder que le nibble extra low }
shl dl, 4 { le déplacer sur le nibble high }
or bh, dl { qu'on additione au poids faible }
test size.byte, 15 { Vérifier si size mod 16 = 0 }
jz @alloc { oui, on économise 16 octets }
inc bx { non, on pêche par excès }
@alloc:
int 21h { Maintenant, au dos de jouer ! }
jc @fin { erreur, al = 7, 8 ou 9 }
les di, p { Pointeur sur la zone crée }
mov es:di.word.0, 0 { offset toujours = à 0 }
mov es:di.word.2, ax { segment }
mov al, xm_ok { aucune erreur }
@fin:
end;
{╔═════════════╤═══════════════════════════════════════════════════════════╗
║ Unit memory │ Désaloue une zone mémoire externe dos ║
║─────────────┴───────────────────────────────────────────────────────────╢
║ P identifie un MCB qui contient les informations nécessaires (taille, ║
║ voisins...) au déchargement du bloc. ║
╚═════════════════════════════════════════════════════════════════════════╝}
Function xm_FreeMem (var P: Pointer) : byte;
assembler; asm
mov ah, 49h { Retirer un block de la mémoire }
les bx, p { Pointer sur le pointeur }
les bx, es:[bx] { qui pointe sur la zone à retirer }
int 21h { Maintenant, au dos de jouer ! }
xor ax, ax { Reseter le pointeur }
les bx, p
mov es:bx.2, ax
mov es:bx.0, ax { = NIL }
jc @fin { erreur, al = 7, ou 9 }
mov al, xm_ok { aucune erreur }
@fin:
end;
{██████████████████████████████████████████████████████████████████████
╔════════════════════════════════════════════════════════════════════╗
║ Fonctions proposées par HIMEM.SYS : ║
║ HMA, UMB et XMS ║
╚════════════════════════════════════════════════════════════════════╝
██████████████████████████████████████████████████████████████████████}
Function Xms_ok : boolean;
assembler; asm
mov al, Xms_errflag
mov Xms_Errflag, 0
end;
Procedure NoXmsDriver; far;
Assembler; asm
mov ax, 3 { Mode texte 80x25 }
int 10h { Réafficher le mode 3 }
mov ah, 9 { Fonction DOS 9h : }
push cs { Afficher une chaine }
pop ds { Chaine dans le segment }
mov dx, offset @err { de code, offset @info }
int 21h { Afficher l'erreur }
mov ax, 4C80h { Code de retour 128 }
int 21h { Terminer le programme }
@err:DB 'Erreur : Driver XMS non initialisé.',13,10,'$'
END;
Function isXms : boolean;
assembler; asm
mov ax, 4300h
int 2fh { Vérifit la présence d'un EMM }
cmp al, 80h
jne @noXMS
mov ax, 4310h
int 2fh { Obtient l'adresse d'appel }
mov word ptr [Xms_Proc+0], bx
mov word ptr [Xms_Proc+2], es
mov ah, 0
call Xms_Proc { Puis le numéro de version }
mov Xms_Ver, ax
mov Xms_Rev, bx
{ dans cl : état HMA (1=libre, 0=occupée) }
cmp ah, 3
jb @BadVer { Version < 3 non ok }
mov al, true { Renvoie true }
mov Xms_ErrFlag, 0
ret
@noXMS:
mov Xms_Ver, 0
mov Xms_Rev, 0
@Badver:
mov word ptr [Xms_Proc+0], offset NoXmsDriver
mov word ptr [Xms_Proc+2], seg NoXmsDriver
mov al, false
mov Xms_ErrFlag, 1
end;
Function Xms_GetHMA : boolean;
assembler; asm
mov ah, 1
mov dx, 0FFFFh
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_ReleaseHMA : boolean;
assembler; asm
mov ah, 2
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_A20unlock : boolean;
assembler; asm
mov ah, 3
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_A20lock : boolean;
assembler; asm
mov ah, 4
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_A20localunlock : boolean;
assembler; asm
mov ah, 5
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_A20locallock : boolean;
assembler; asm
mov ah, 6
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_A20unlocked : boolean; { 1 = unlock, 0 = lock }
assembler; asm
mov ah, 7
call Xms_proc
end;
Function Xms_MaxAvail : word; { l'unité est le Ko }
assembler; asm
mov ah, 8
call Xms_proc
{ renvoie dans ax le block, dans dx la mém }
end;
Function Xms_MemAvail : word; { l'unité est le Ko }
assembler; asm
mov ah, 8
call Xms_proc
mov ax, dx
end;
Function Xms_Alloc (var handle : word; nbko : word) : boolean;
assembler; asm
mov ah, 9
mov dx, nbko
call xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
les di, handle
mov es:[di], dx
end;
Function Xms_UnAlloc (handle : word) : boolean;
assembler; asm
mov ah, 10
mov dx, handle
call xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_Move (var e : ExMM) : boolean;
assembler; asm
push ds { sauver le segment de données car il est utilisé ! }
mov ah, 11
lds si, e
call xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
pop ds
end;
Function Xms_Lock (handle : word) : boolean;
assembler; asm
mov ah, 12
mov dx, handle
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
{ retourne l'adresse linéaire 32bits de l'emb en mémoire dans
dx:bx }
end;
Function Xms_UnLock (handle : word) : boolean;
assembler; asm
mov ah, 13
mov dx, handle
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_NbLocked (handle : word) : byte; { Nombre de verrouillages }
assembler; asm
mov ah, 14
mov dx, handle
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
jmp @ret
@fin:
mov al, bh
@ret:
end;
Function Xms_GetEMBsize (handle : word) : word; { Taille en ko }
assembler; asm
mov ah, 14
mov dx, handle
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
mov ax, 0
jmp @ret
@fin:
mov ax, dx
@ret:
end;
Function Xms_SetEMBsize (handle, NewSizeInko : word) : boolean;
assembler; asm
mov ah, 15
mov bx, NewSizeinKo
mov dx, handle
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
@fin:
end;
Function Xms_UMBAlloc (size : word) : word; { Retourne l'adresse }
assembler; asm { size en paragraphes }
mov ah, 10h
mov dx, size
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
mov ax, 0
jmp @ret
@fin:
mov ax, bx
@ret:
end;
Function Xms_UMBMaxAvail : word; { taille du + gd bloc }
assembler; asm
mov ah, 10h
mov dx, 0FFFFh
call Xms_proc
mov ax, dx
end;
Function Xms_UMBunAlloc (segm : word) : boolean;
assembler; asm
mov ah, 11h
mov dx, segm
call Xms_proc
cmp al, 1
je @fin
mov Xms_Errflag, bl
mov ax, 0
@fin:
end;
Function Xms_Err (n : byte) : string;
CONST errs : array[1..29] of pchar = (
#$00'Opération réussie',
#$01'gestionnaire XMS non installé',
#$80'Fonction spécifiée non connue',
#$81'Conflit avec un RamDisque',
#$82'Erreur sur l''addresse de ligne A20',
#$8E'Erreur génerale du driver XMS',
#$8F'Erreur système, impossible à éliminer',
#$90'HMA non trouvée',
#$91'HMA déjà occupée',
#$92'Seuil d''allocation trop bas',
#$93'HMA non allouée',
#$94'La ligne A20 est encore en fonction',
#$A0'Plus de mémoire étendue disponible',
#$A1'Tous les Handles XMS sont occupés',
#$A2'Accès à une zone [Handle] indéfinie',
#$A3'Erreur de l''handle source',
#$A4'Erreur de l''offset source',
#$A5'Erreur de l''handle cible',
#$A6'Erreur de l''offset cible',
#$A7'Déplacement - longueur incorrecte',
#$A8'Déplacement - Superposition interdite',
#$A9'Erreur de parité',
#$AA'UMB non verrouillé',
#$AB'UMB encore vérouillé',
#$AC'UMB - Débordement de verrouillage',
#$AD'UMB non verrouillable',
#$B0'UMB plus petit disponible',
#$B1'Plus d''UMB Disponible',
#$B2'Adresse de segment d''UMB incorrecte' );
VAR i, j : word;
st : string;
BEGIN
st := 'Erreur inconnue';
for i := 1 to 29 do
if ord(errs[i][0]) = n then begin
for j := 1 to 255 do
if errs[i][j] = #0 then break;
move (errs[i][0], st, j);
st[0] := chr(j-1);
break;
end;
Xms_Err := st;
END;
{██████████████████████████████████████████████████████████████████████
╔════════════════════════════════════════════════════════════════════╗
║ Fonctions de gestion de l'EMS ║
║ Contient l'ensemble des services proposés par l'EMM 3.0 ║
╚════════════════════════════════════════════════════════════════════╝
██████████████████████████████████████████████████████████████████████}
Function Ems_State : byte;
assembler; asm
mov ah, 40h
int 67h
mov al, ah
end;
Function Ems_Err (n : byte) : string;
CONST errs : array[1..17] of pchar = (
#$00'Opération réussie',
#$80'Erreur Interne, EMM détruit',
#$81'Electronique EMS défaillante',
#$82'EMM occupé',
#$83'Handle incorrect',
#$84'Fonction non reconnue',
#$85'Plus d''handle disponibles',
#$86'Erreur de concordance de pages',
#$87'Dépassement de pages',
#$88'Mémoire insufisante',
#$89'Impossible d''allouer 0 page',
#$8A'Numéro de page logique non valable',
#$8B'Numéro de page physique non valable',
#$8C'Cellule d''allocation saturée',
#$8D'Handle déjà sauvegardé',
#$8E'Handle non sauvegardé',
#$8F'Sous-fonction non reconnue' );
VAR i, j : word;
st : string;
BEGIN
st := 'Erreur inconnue';
for i := 1 to 28 do
if ord(errs[i][0]) = n then begin
for j := 1 to 255 do
if errs[i][j] = #0 then break;
move (errs[i][0], st, j);
st[0] := chr(j-1);
break;
end;
Ems_Err := st;
END;
Function Ems_Map (handle, logik : word; Physik : byte) : byte;
assembler; asm
mov dx, handle
mov bx, Logik
mov al, physik
mov ah, 44h
int 67h
mov al, ah
end;
Function Ems_SaveMap (handle : word) : byte;
assembler; asm
mov ah, 47h
mov dx, handle
int 67h
mov al, ah
END;
Function Ems_RestoreMap (handle : word) : byte;
assembler; asm
mov ah, 48h
mov dx, handle
int 67h
mov al, ah
end;
Function Ems_Alloc (var handle : word; nbpages : word) : byte;
assembler; asm
mov ah, 43h
mov bx, nbpages
int 67h
les di, handle
mov es:[di], dx
mov al, ah
end;
Function Ems_GetHandles (var handles) : byte;
assembler; asm
mov ah, 4Dh
les di, handles
int 67h
mov al, ah
end;
Function Ems_UnAlloc (handle : word) : byte;
assembler; asm
mov ah, 45h
mov dx, handle
int 67h
mov al, ah
end;
Function Ems_GetNbHandles : word;
assembler; asm
mov ah, 4Bh
int 67h
cmp ah, 0
jne @fin
mov ax, bx
@fin:
mov ax, 0 { 0 indique une erreur }
end;
Function Ems_GetNbPages (handle : word) : word;
assembler; asm
mov ah, 4Ch
mov dx, handle
int 67h
cmp ah, 0
jne @fin
mov ax, bx
@fin:
mov ax, 0 { 0 indique une erreur }
end;
Function Ems_GetTotalPages : word;
assembler; asm
mov ah, 42h
int 67h
cmp ah, 0
jne @fin
mov ax, dx
ret
@fin:
mov ax, 0 { 0 indique une erreur }
end;
Function Ems_GetFreePages : word;
assembler; asm
mov ah, 42h
int 67h
cmp ah, 0
jne @fin
mov ax, bx
ret
@fin:
mov ax, 0 { 0 indique une erreur }
end;
Function IsEms : boolean;
Function Ems_GetSeg : boolean;
assembler; asm
mov ah, 41h
int 67h
cmp ah, 0
jne @fin
mov ems_seg, bx
mov al, true
jmp @ret
@fin:
mov Ems_Seg, 0A000h { un segment innofensif }
mov al, false
@ret:
end;
Function Ems_Version : boolean;
assembler; asm
mov ah, 46h
int 67h
cmp ah, 0
jne @fin
mov bx, ax
and bx, 15
shr al, 4
mov cl, 10
mul cl
add ax, bx
mov Ems_Ver, ax
mov al, true
jmp @ret
@fin:
mov al, false
mov Ems_Ver, 0
@ret:
end;
Type EmmName = array[1..8] of char;
Var emm : ^emmname;
BEGIN
GetIntVec ($67, pointer(emm));
word(emm) := 10;
IsEms := false;
{$B-}
if emm^ = 'EMMXXXX0' then
IsEms := Ems_GetSeg and Ems_Version and (Ems_Ver >= 30);
{$B+}
END;
end.