mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-17 11:39:33 +02:00
838 lines
38 KiB
ObjectPascal
838 lines
38 KiB
ObjectPascal
{ $Id$ }
|
|
{********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
|
|
{ }
|
|
{ System independent clone of MEMORY.PAS }
|
|
{ }
|
|
{ Interface Copyright (c) 1992 Borland International }
|
|
{ }
|
|
{ Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer }
|
|
{ ldeboer@attglobal.net - primary e-mail address }
|
|
{ ldeboer@starwon.com.au - backup e-mail address }
|
|
{ }
|
|
{****************[ THIS CODE IS FREEWARE ]*****************}
|
|
{ }
|
|
{ This sourcecode is released for the purpose to }
|
|
{ promote the pascal language on all platforms. You may }
|
|
{ redistribute it and/or modify with the following }
|
|
{ DISCLAIMER. }
|
|
{ }
|
|
{ This SOURCE CODE is distributed "AS IS" WITHOUT }
|
|
{ WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR }
|
|
{ ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED. }
|
|
{ }
|
|
{*****************[ SUPPORTED PLATFORMS ]******************}
|
|
{ 16 and 32 Bit compilers }
|
|
{ DOS - Turbo Pascal 7.0 + (16 Bit) }
|
|
{ DPMI - Turbo Pascal 7.0 + (16 Bit) }
|
|
{ - FPC 0.9912+ (GO32V2) (32 Bit) }
|
|
{ WINDOWS - Turbo Pascal 7.0 + (16 Bit) }
|
|
{ - Delphi 1.0+ (16 Bit) }
|
|
{ WIN95/NT - Delphi 2.0+ (32 Bit) }
|
|
{ - Virtual Pascal 2.0+ (32 Bit) }
|
|
{ - Speedsoft Sybil 2.0+ (32 Bit) }
|
|
{ - FPC 0.9912+ (32 Bit) }
|
|
{ OS2 - Virtual Pascal 1.0+ (32 Bit) }
|
|
{ }
|
|
{******************[ REVISION HISTORY ]********************}
|
|
{ Version Date Fix }
|
|
{ ------- --------- --------------------------------- }
|
|
{ 1.00 19 feb 96 Initial DOS/DPMI code released. }
|
|
{ 1.10 18 Jul 97 Windows conversion added. }
|
|
{ 1.20 29 Aug 97 Platform.inc sort added. }
|
|
{ 1.30 05 May 98 Virtual pascal 2.0 code added. }
|
|
{ 1.40 01 Oct 99 Complete multiplatform rewrite }
|
|
{ 1.41 03 Nov 99 FPC Windows support added }
|
|
{**********************************************************}
|
|
|
|
UNIT Memory;
|
|
|
|
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
|
|
INTERFACE
|
|
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
|
|
|
|
{====Include file to sort compiler platform out =====================}
|
|
{$I Platform.inc}
|
|
{====================================================================}
|
|
|
|
{==== Compiler directives ===========================================}
|
|
|
|
{$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
|
|
{$F+} { Force far calls }
|
|
{$A+} { Word Align Data }
|
|
{$B-} { Allow short circuit boolean evaluations }
|
|
{$O+} { This unit may be overlaid }
|
|
{$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
|
|
{$P-} { Normal string variables }
|
|
{$N-} { No 80x87 code generation }
|
|
{$E+} { Emulation is on }
|
|
{$ENDIF}
|
|
|
|
{$X+} { Extended syntax is ok }
|
|
{$R-} { Disable range checking }
|
|
{$S-} { Disable Stack Checking }
|
|
{$I-} { Disable IO Checking }
|
|
{$Q-} { Disable Overflow Checking }
|
|
{$V-} { Turn off strict VAR strings }
|
|
{====================================================================}
|
|
|
|
USES FVCommon;
|
|
|
|
{***************************************************************************}
|
|
{ INTERFACE ROUTINES }
|
|
{***************************************************************************}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ MEMORY ACCESS ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{-MemAlloc-----------------------------------------------------------
|
|
Allocates the requested size of memory if this takes memory free below
|
|
the safety pool then a nil pointer is returned.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
FUNCTION MemAlloc (Size: Word): Pointer;
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ MEMORY MANAGER SYSTEM CONTROL ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{-LowMemory----------------------------------------------------------
|
|
Returns if the free memory left is below the safety pool value.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
FUNCTION LowMemory: Boolean;
|
|
|
|
{-InitMemory---------------------------------------------------------
|
|
Initializes the memory and safety pool manager. This should be called
|
|
prior to using any of the memory manager routines.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE InitMemory;
|
|
|
|
{-DoneMemory---------------------------------------------------------
|
|
Closes the memory and safety pool manager. This should be called after
|
|
using the memory manager routines so as to clean up.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE DoneMemory;
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ CACHE MEMORY ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{-NewCache-----------------------------------------------------------
|
|
Create a new cache of given size in pointer P failure will return nil.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE NewCache (Var P: Pointer; Size: Word);
|
|
|
|
{-DisposeCache-------------------------------------------------------
|
|
Dispose of a cache buffer given by pointer P.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE DisposeCache (P: Pointer);
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ BUFFER MEMORY ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{-GetBufferSize------------------------------------------------------
|
|
Returns the size of memory buffer given by pointer P.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
FUNCTION GetBufferSize (P: Pointer): Word;
|
|
|
|
{-SetBufferSize------------------------------------------------------
|
|
Change the size of buffer given by pointer P to the size requested.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
FUNCTION SetBufferSize (P: Pointer; Size: Word): Boolean;
|
|
|
|
{-DisposeBuffer------------------------------------------------------
|
|
Dispose of buffer given by pointer P.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE DisposeBuffer (P: Pointer);
|
|
|
|
{-NewBuffer----------------------------------------------------------
|
|
Create a new buffer of given size in ptr P failure will return nil.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ DOS MEMORY CONTROL ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{-InitDosMem---------------------------------------------------------
|
|
Initialize memory manager routine for a shell to launch a DOS window.
|
|
Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE InitDosMem;
|
|
|
|
{-DoneDosMem---------------------------------------------------------
|
|
Finished shell to a DOS window so reset memory manager again.
|
|
Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
|
|
01Oct99 LdB
|
|
---------------------------------------------------------------------}
|
|
PROCEDURE DoneDosMem;
|
|
|
|
{***************************************************************************}
|
|
{ PUBLIC INITIALIZED VARIABLES }
|
|
{***************************************************************************}
|
|
CONST
|
|
LowMemSize : Word = 4096 DIV 16; { 4K }
|
|
SafetyPoolSize: Word = 8192; { Safety pool size }
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
MaxHeapSize : Word = 655360 DIV 16; { 640K }
|
|
MaxBufMem : Word = 65536 DIV 16; { 64K }
|
|
{$ENDIF}
|
|
|
|
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
|
|
IMPLEMENTATION
|
|
{<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
|
|
{$IFDEF OS_WINDOWS} { WIN/NT CODE }
|
|
{$IFDEF PPC_FPC} { FPC WINDOWS COMPILER }
|
|
USES Windows; { Standard unit }
|
|
{$ELSE} { OTHER COMPILERS }
|
|
USES WinProcs, WinTypes; { Standard units }
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
{$IFDEF OS_OS2} { OS2 CODE }
|
|
USES Os2Base; { Standard unit }
|
|
{$ENDIF}
|
|
|
|
{***************************************************************************}
|
|
{ PRIVATE RECORD TYPE DEFINITIONS }
|
|
{***************************************************************************}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ TBuffer RECORD DEFINITION }
|
|
{---------------------------------------------------------------------------}
|
|
TYPE
|
|
PBuffer = ^TBuffer; { Buffer pointer }
|
|
TBuffer = PACKED RECORD
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
Size : Word; { Buffer size }
|
|
Master: ^Word; { Master buffer }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
Next: PBuffer; { Next buffer }
|
|
Size: Word; { Buffer size }
|
|
Data: RECORD END; { Buffer data }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ POINTER TYPE CONVERSION RECORDS }
|
|
{---------------------------------------------------------------------------}
|
|
TYPE
|
|
PtrRec = PACKED RECORD
|
|
Ofs, Seg: Word; { Pointer to words }
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ TCache RECORD DEFINITION }
|
|
{---------------------------------------------------------------------------}
|
|
TYPE
|
|
PCache = ^TCache; { Cache pointer }
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
TCache = PACKED RECORD
|
|
Size : Word; { Cache size }
|
|
Master: ^Pointer; { Master cache }
|
|
Data : RECORD END; { Cache data }
|
|
END;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
TCache = PACKED RECORD
|
|
Next : PCache; { Next cache }
|
|
Master: ^Pointer; { Master cache }
|
|
Size : Word; { Size of cache }
|
|
Data : RECORD END; { Cache data }
|
|
End;
|
|
{$ENDIF}
|
|
|
|
{***************************************************************************}
|
|
{ INITIALIZED PRIVATE VARIABLES }
|
|
{***************************************************************************}
|
|
CONST
|
|
DisablePool: Boolean = False; { Disable safety pool }
|
|
SafetyPool : Pointer = Nil; { Safety pool memory }
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
HeapResult: Integer = 0; { Heap result }
|
|
BufHeapPtr: Word = 0; { Heap position }
|
|
BufHeapEnd: Word = 0; { Heap end }
|
|
CachePtr : Pointer = Nil; { Cache list }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
CacheList : PCache = Nil; { Cache list }
|
|
BufferList: PBuffer = Nil; { Buffer list }
|
|
{$ENDIF}
|
|
|
|
{***************************************************************************}
|
|
{ PRIVATE UNIT ROUTINES }
|
|
{***************************************************************************}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ PRIVATE UNIT ROUTINES - REAL MODE DOS PLATFORMS }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
{---------------------------------------------------------------------------}
|
|
{ GetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION GetBufSize (P: PBuffer): Word; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
BEGIN
|
|
GetBufSize := (P^.Size + 15) SHR 4 + 1; { Buffer paragraphs }
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ FreeCacheMem -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE FreeCacheMem; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
BEGIN
|
|
While (CachePtr <> HeapEnd) Do
|
|
DisposeCache(CachePtr); { Release blocks }
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ SetMemTop -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE SetMemTop (MemTop: Pointer); ASSEMBLER;
|
|
ASM
|
|
MOV BX, MemTop.Word[0]; { Top of memory }
|
|
ADD BX, 15;
|
|
MOV CL, 4;
|
|
SHR BX, CL; { Size in paragraphs }
|
|
ADD BX, MemTop.Word[2];
|
|
MOV AX, PrefixSeg; { Add prefix seg }
|
|
SUB BX, AX;
|
|
MOV ES, AX;
|
|
MOV AH, 4AH;
|
|
INT 21H; { Call to DOS }
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ MoveSeg -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE MoveSeg (Source, Dest, Size: Word); NEAR; ASSEMBLER;
|
|
ASM
|
|
PUSH DS; { Save register }
|
|
MOV AX, Source;
|
|
MOV DX, Dest; { Destination }
|
|
MOV BX, Size;
|
|
CMP AX, DX; { Does Source=Dest? }
|
|
JB @@3;
|
|
CLD; { Go forward }
|
|
@@1:
|
|
MOV CX, 0FFFH;
|
|
CMP CX, BX;
|
|
JB @@2;
|
|
MOV CX, BX;
|
|
@@2:
|
|
MOV DS, AX;
|
|
MOV ES, DX;
|
|
ADD AX, CX;
|
|
ADD DX, CX;
|
|
SUB BX, CX;
|
|
SHL CX, 3; { Mult x8 }
|
|
XOR SI, SI;
|
|
XOR DI, DI;
|
|
REP MOVSW;
|
|
OR BX, BX;
|
|
JNE @@1;
|
|
JMP @@6;
|
|
@@3: { Source=Dest }
|
|
ADD AX, BX; { Hold register }
|
|
ADD DX, BX; { Must go backwards }
|
|
STD;
|
|
@@4:
|
|
MOV CX, 0FFFH;
|
|
CMP CX, BX;
|
|
JB @@5;
|
|
MOV CX, BX;
|
|
@@5:
|
|
SUB AX, CX;
|
|
SUB DX, CX;
|
|
SUB BX, CX;
|
|
MOV DS, AX;
|
|
MOV ES, DX;
|
|
SHL CX, 3; { Mult x8 }
|
|
MOV SI, CX;
|
|
DEC SI;
|
|
SHL SI, 1;
|
|
MOV DI, SI;
|
|
REP MOVSW; { Move data }
|
|
OR BX, BX;
|
|
JNE @@4;
|
|
@@6:
|
|
POP DS; { Recover register }
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ SetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE SetBufSize (P: PBuffer; NewSize: Word); {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
VAR CurSize: Word;
|
|
BEGIN
|
|
CurSize := GetBufSize(P); { Current size }
|
|
MoveSeg(PtrRec(P).Seg + CurSize, PtrRec(P).Seg+
|
|
NewSize, BufHeapPtr - PtrRec(P).Seg - CurSize); { Move data }
|
|
Inc(BufHeapPtr, NewSize - CurSize); { Adjust heap space }
|
|
Inc(PtrRec(P).Seg, NewSize); { Adjust pointer }
|
|
While PtrRec(P).Seg < BufHeapPtr Do Begin
|
|
Inc(P^.Master^, NewSize - CurSize); { Adjust master }
|
|
Inc(PtrRec(P).Seg, (P^.Size + 15) SHR 4 + 1); { Adjust paragraphs }
|
|
End;
|
|
END;
|
|
{$ENDIF}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ PRIVATE UNIT ROUTINES - DPMI/WIN/NT/OS2 PLATFORMS }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{$IFNDEF PROC_REAL} { DPMI/WIN/NT/OS2 CODE }
|
|
{---------------------------------------------------------------------------}
|
|
{ FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION FreeCache: Boolean; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
BEGIN
|
|
FreeCache := False; { Preset fail }
|
|
If (CacheList <> Nil) Then Begin
|
|
DisposeCache(CacheList^.Next^.Master^); { Dispose cache }
|
|
FreeCache := True; { Return success }
|
|
End;
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION FreeSafetyPool: Boolean; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
BEGIN
|
|
FreeSafetyPool := False; { Preset fail }
|
|
If (SafetyPool <> Nil) Then Begin { Pool exists }
|
|
FreeMem(SafetyPool, SafetyPoolSize); { Release memory }
|
|
SafetyPool := Nil; { Clear pointer }
|
|
FreeSafetyPool := True; { Return true }
|
|
End;
|
|
END;
|
|
{$ENDIF}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ PRIVATE UNIT ROUTINES - ALL PLATFORMS }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ HeapNotify -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION HeapNotify (Size: Word): Integer; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
ASSEMBLER;
|
|
ASM
|
|
CMP Size, 0; { Check for zero size }
|
|
JNE @@3; { Exit if size = zero }
|
|
@@1:
|
|
MOV AX, CachePtr.Word[2];
|
|
CMP AX, HeapPtr.Word[2]; { Compare segments }
|
|
JA @@3;
|
|
JB @@2;
|
|
MOV AX, CachePtr.Word[0];
|
|
CMP AX, HeapPtr.Word[0]; { Compare offsets }
|
|
JAE @@3;
|
|
@@2:
|
|
XOR AX, AX; { Clear register }
|
|
PUSH AX; { Push zero }
|
|
PUSH AX; { Push zero }
|
|
CALL DisposeCache; { Dispose cache }
|
|
JMP @@1;
|
|
@@3:
|
|
MOV AX, HeapResult; { Return result }
|
|
END;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 }
|
|
BEGIN
|
|
If FreeCache Then HeapNotify := 2 Else { Release cache }
|
|
If DisablePool Then HeapNotify := 1 Else { Safetypool disabled }
|
|
If FreeSafetyPool Then HeapNotify := 2 Else { Free safety pool }
|
|
HeapNotify := 0; { Return success }
|
|
END;
|
|
{$ENDIF}
|
|
|
|
|
|
{***************************************************************************}
|
|
{ INTERFACE ROUTINES }
|
|
{***************************************************************************}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ MEMORY ACCESS ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ MemAlloc -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION MemAlloc (Size: Word): Pointer;
|
|
VAR P: Pointer;
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
HeapResult := 1; { Stop error calls }
|
|
GetMem(P, Size); { Get memory }
|
|
HeapResult := 0; { Reset error calls }
|
|
If (P <> Nil) AND LowMemory Then Begin { Low memory }
|
|
FreeMem(P, Size); { Release memory }
|
|
P := Nil; { Clear pointer }
|
|
End;
|
|
MemAlloc := P; { Return result }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 }
|
|
DisablePool := True; { Disable safety }
|
|
GetMem(P, Size); { Allocate memory }
|
|
DisablePool := False; { Enable safety }
|
|
MemAlloc := P; { Return result }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ MEMORY MANAGER SYSTEM CONTROL ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ LowMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Checked 29Jun98 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION LowMemory: Boolean;
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
ASSEMBLER;
|
|
ASM
|
|
MOV AX, HeapEnd.Word[2]; { Get heap end }
|
|
SUB AX, HeapPtr.Word[2];
|
|
SUB AX, LowMemSize; { Subtract size }
|
|
SBB AX, AX;
|
|
NEG AX; { Return result }
|
|
END;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
BEGIN
|
|
LowMemory := False; { Preset false }
|
|
If (SafetyPool = Nil) Then Begin { Not initialized }
|
|
SafetyPool := MemAlloc(SafetyPoolSize); { Allocate safety pool }
|
|
If (SafetyPool = Nil) Then LowMemory := True; { Return if low memory }
|
|
End;
|
|
END;
|
|
{$ENDIF}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ InitMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE InitMemory;
|
|
{$IFDEF PROC_REAL} VAR HeapSize: Word; {$ENDIF}
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
HeapError := @HeapNotify; { Point to error proc }
|
|
If (BufHeapPtr = 0) Then Begin
|
|
HeapSize := PtrRec(HeapEnd).Seg
|
|
- PtrRec(HeapOrg).Seg; { Calculate size }
|
|
If (HeapSize > MaxHeapSize) Then
|
|
HeapSize := MaxHeapSize; { Restrict max size }
|
|
BufHeapEnd := PtrRec(HeapEnd).Seg; { Set heap end }
|
|
PtrRec(HeapEnd).Seg := PtrRec(HeapOrg).Seg
|
|
+ HeapSize; { Add heapsize }
|
|
BufHeapPtr := PtrRec(HeapEnd).Seg; { Set heap pointer }
|
|
End;
|
|
CachePtr := HeapEnd; { Cache starts at end }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
{$IFNDEF PPC_FPC}
|
|
HeapError := @HeapNotify; { Set heap error proc }
|
|
{$ENDIF}
|
|
SafetyPoolSize := LowMemSize * 16; { Fix safety pool size }
|
|
LowMemory; { Check for low memory }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ DoneMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE DoneMemory;
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAl MODE DOS CODE }
|
|
FreeCacheMem; { Release cache memory }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 }
|
|
While FreeCache Do; { Free cache memory }
|
|
FreeSafetyPool; { Release safety pool }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ CACHE MEMORY ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ NewCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE NewCache (Var P: Pointer; Size: Word);
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
ASSEMBLER;
|
|
ASM
|
|
LES DI, P; { Addres of var P }
|
|
MOV AX, Size;
|
|
ADD AX, (TYPE TCache)+15; { Add offset }
|
|
MOV CL, 4;
|
|
SHR AX, CL;
|
|
MOV DX, CachePtr.Word[2]; { Reteive cache ptr }
|
|
SUB DX, AX;
|
|
JC @@1;
|
|
CMP DX, HeapPtr.Word[2]; { Heap ptr end }
|
|
JBE @@1;
|
|
MOV CX, HeapEnd.Word[2];
|
|
SUB CX, DX;
|
|
CMP CX, MaxBufMem; { Compare to maximum }
|
|
JA @@1;
|
|
MOV CachePtr.Word[2], DX; { Exchange ptr }
|
|
PUSH DS;
|
|
MOV DS, DX;
|
|
XOR SI, SI;
|
|
MOV DS:[SI].TCache.Size, AX; { Get cache size }
|
|
MOV DS:[SI].TCache.Master.Word[0], DI;
|
|
MOV DS:[SI].TCache.Master.Word[2], ES; { Get master ptr }
|
|
POP DS;
|
|
MOV AX, OFFSET TCache.Data;
|
|
JMP @@2;
|
|
@@1:
|
|
XOR AX, AX;
|
|
CWD; { Make double word }
|
|
@@2:
|
|
CLD;
|
|
STOSW; { Write low word }
|
|
XCHG AX, DX;
|
|
STOSW; { Write high word }
|
|
END;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
VAR Cache: PCache;
|
|
BEGIN
|
|
Inc(Size, SizeOf(TCache)); { Add cache size }
|
|
If (MaxAvail >= Size) Then GetMem(Cache, Size) { Allocate memory }
|
|
Else Cache := Nil; { Not enough memory }
|
|
If (Cache <> Nil) Then Begin { Cache is valid }
|
|
If (CacheList = Nil) Then Cache^.Next := Cache
|
|
Else Begin
|
|
Cache^.Next := CacheList^.Next; { Insert in list }
|
|
CacheList^.Next := Cache; { Complete link }
|
|
End;
|
|
CacheList := Cache; { Hold cache ptr }
|
|
Cache^.Size := Size; { Hold cache size }
|
|
Cache^.Master := @P; { Hold master ptr }
|
|
Inc(PtrRec(Cache).Ofs, SizeOf(TCache)); { Set cache offset }
|
|
End;
|
|
P := Cache; { Return pointer }
|
|
END;
|
|
{$ENDIF}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ DisposeCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE DisposeCache (P: Pointer);
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
ASSEMBLER;
|
|
ASM
|
|
MOV AX, CachePtr.Word[2]; { Cache high word }
|
|
XOR BX, BX;
|
|
XOR CX, CX;
|
|
MOV DX, P.Word[2]; { P high word }
|
|
@@1:
|
|
MOV ES, AX;
|
|
CMP AX, DX; { Check for match }
|
|
JE @@2;
|
|
ADD AX, ES:[BX].TCache.Size; { Move to next cache }
|
|
CMP AX, HeapEnd.Word[2];
|
|
JE @@2; { Are we at heap end }
|
|
PUSH ES;
|
|
INC CX; { No so try next }
|
|
JMP @@1;
|
|
@@2:
|
|
PUSH ES;
|
|
LES DI, ES:[BX].TCache.Master; { Pointe to master }
|
|
XOR AX, AX;
|
|
CLD;
|
|
STOSW; { Clear master ptr }
|
|
STOSW;
|
|
POP ES;
|
|
MOV AX, ES:[BX].TCache.Size; { Next cache }
|
|
JCXZ @@4;
|
|
@@3:
|
|
POP DX;
|
|
PUSH DS;
|
|
PUSH CX; { Hold registers }
|
|
MOV DS, DX;
|
|
ADD DX, AX;
|
|
MOV ES, DX;
|
|
MOV SI, DS:[BX].TCache.Size; { Get cache size }
|
|
MOV CL, 3;
|
|
SHL SI, CL; { Multiply x8 }
|
|
MOV CX, SI;
|
|
SHL SI, 1;
|
|
DEC SI; { Adjust position }
|
|
DEC SI;
|
|
MOV DI, SI;
|
|
STD;
|
|
REP MOVSW; { Move cache memory }
|
|
LDS SI, ES:[BX].TCache.Master;
|
|
MOV DS:[SI].Word[2], ES; { Store new master }
|
|
POP CX;
|
|
POP DS; { Recover registers }
|
|
LOOP @@3;
|
|
@@4:
|
|
ADD CachePtr.Word[2], AX; { Add offset }
|
|
END;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
VAR Cache, C: PCache;
|
|
BEGIN
|
|
PtrRec(Cache).Ofs := PtrRec(P).Ofs-SizeOf(TCache); { Previous cache }
|
|
PtrRec(Cache).Seg := PtrRec(P).Seg; { Segment }
|
|
C := CacheList; { Start at 1st cache }
|
|
While (C^.Next <> Cache) AND (C^.Next <> CacheList)
|
|
Do C := C^.Next; { Find previous }
|
|
If (C^.Next = Cache) Then Begin { Cache found }
|
|
If (C = Cache) Then CacheList := Nil Else Begin { Only cache in list }
|
|
If CacheList = Cache Then CacheList := C; { First in list }
|
|
C^.Next := Cache^.Next; { Remove from list }
|
|
End;
|
|
Cache^.Master^ := Nil; { Clear master }
|
|
FreeMem(Cache, Cache^.Size); { Release memory }
|
|
End;
|
|
END;
|
|
{$ENDIF}
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ BUFFER MEMORY ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ GetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION GetBufferSize (P: Pointer): Word;
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { DOS CODE }
|
|
Dec(PtrRec(P).Seg); { Segment prior }
|
|
GetBufferSize := PBuffer(P)^.Size; { Size of this buffer }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
If (P <> Nil) Then Begin { Check pointer }
|
|
Dec(PtrRec(P).Ofs,SizeOf(TBuffer)); { Correct to buffer }
|
|
GetBufferSize := PBuffer(P)^.Size; { Return buffer size }
|
|
End Else GetBufferSize := 0; { Invalid pointer }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ SetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
FUNCTION SetBufferSize (P: Pointer; Size: Word): Boolean;
|
|
VAR NewSize: Word;
|
|
BEGIN
|
|
SetBufferSize := False; { Preset failure }
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
Dec(PtrRec(P).Seg); { Prior segment }
|
|
NewSize := (Size + 15) SHR 4 + 1; { Paragraph size }
|
|
If (BufHeapPtr+NewSize-GetBufSize(P)<=BufHeapEnd) { Check enough heap }
|
|
Then Begin
|
|
SetBufSize(P, NewSize); { Set the buffer size }
|
|
PBuffer(P)^.Size := Size; { Set the size }
|
|
SetBufferSize := True; { Return success }
|
|
End;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
SetBufferSize := False; { No block resizing }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ DisposeBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE DisposeBuffer (P: Pointer);
|
|
{$IFNDEF PROC_REAL} VAR Buffer,PrevBuf: PBuffer; {$ENDIF}
|
|
BEGIN
|
|
If (P <> Nil) Then Begin
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
Dec(PtrRec(P).Seg); { Prior segement }
|
|
SetBufSize(P, 0); { Release memory }
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
Dec(PtrRec(P).Ofs, SizeOf(TBuffer)); { Actual buffer pointer }
|
|
Buffer := BufferList; { Start on first }
|
|
PrevBuf := Nil; { Preset prevbuf to nil }
|
|
While (Buffer <> Nil) AND (P <> Buffer) Do Begin { Search for buffer }
|
|
PrevBuf := Buffer; { Hold last buffer }
|
|
Buffer := Buffer^.Next; { Move to next buffer }
|
|
End;
|
|
If (Buffer <> Nil) Then Begin { Buffer was found }
|
|
If (PrevBuf = Nil) Then { We were first on list }
|
|
BufferList := Buffer^.Next Else { Set bufferlist entry }
|
|
PrevBuf^.Next := Buffer^.Next; { Remove us from chain }
|
|
FreeMem(Buffer, Buffer^.Size); { Release buffer }
|
|
End;
|
|
{$ENDIF}
|
|
End;
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ NewBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
|
|
VAR BufSize: Word; Buffer: PBuffer;
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
BufSize := (Size + 15) SHR 4 + 1; { Paragraphs to alloc }
|
|
If (BufHeapPtr+BufSize > BufHeapEnd) Then P := Nil { Exceeeds heap }
|
|
Else Begin
|
|
Buffer := Ptr(BufHeapPtr, 0); { Current position }
|
|
Buffer^.Size := Size; { Set size }
|
|
Buffer^.Master := @PtrRec(P).Seg; { Set master }
|
|
P := Ptr(BufHeapPtr + 1, 0); { Position ptr }
|
|
Inc(BufHeapPtr, BufSize); { Allow space on heap }
|
|
End;
|
|
{$ELSE} { DPMI/WIN/NT/OS2 CODE }
|
|
BufSize := Size + SizeOf(TBuffer); { Size to allocate }
|
|
Buffer := MemAlloc(BufSize); { Allocate the memory }
|
|
If (Buffer <> Nil) Then Begin
|
|
Buffer^.Next := BufferList; { First part of chain }
|
|
BufferList := Buffer; { Complete the chain }
|
|
Buffer^.Size := BufSize; { Hold the buffer size }
|
|
Inc(PtrRec(Buffer).Ofs, SizeOf(TBuffer)); { Buffer to data area }
|
|
End;
|
|
P := Buffer; { Return the buffer ptr }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
{ DOS MEMORY CONTROL ROUTINES }
|
|
{+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ InitDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE InitDosMem;
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAl MODE DOS CODE }
|
|
SetMemTop(Ptr(BufHeapEnd, 0)); { Move heap to empty }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
{---------------------------------------------------------------------------}
|
|
{ DoneDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
|
|
{---------------------------------------------------------------------------}
|
|
PROCEDURE DoneDosMem;
|
|
{$IFDEF PROC_REAL} VAR MemTop: Pointer; {$ENDIF}
|
|
BEGIN
|
|
{$IFDEF PROC_REAL} { REAL MODE DOS CODE }
|
|
MemTop := Ptr(BufHeapPtr, 0); { Top of memory }
|
|
If (BufHeapPtr = PtrRec(HeapEnd).Seg) Then Begin { Is memory empty }
|
|
FreeCacheMem; { Release memory }
|
|
MemTop := HeapPtr; { Set pointer }
|
|
End;
|
|
SetMemTop(MemTop); { Release memory }
|
|
{$ENDIF}
|
|
END;
|
|
|
|
END.
|
|
|
|
{
|
|
$Log$
|
|
Revision 1.6 2002-09-09 08:04:06 pierre
|
|
* remove all warnings about far
|
|
|
|
Revision 1.5 2002/09/07 15:06:37 peter
|
|
* old logs removed and tabs fixed
|
|
|
|
}
|