123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875 |
- {********[ 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 }
- { [email protected] - primary e-mail address }
- { [email protected] - 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;
- {====Include file to sort compiler platform out =====================}
- {$I Platform.inc}
- {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
- INTERFACE
- {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
- {====================================================================}
- {==== 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 (var 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 }
- {$IFDEF PPC_FPC}
- USES DosCalls; { Standard unit }
- {$ELSE}
- USES Os2Base; { Standard unit }
- {$ENDIF}
- {$ENDIF}
- {***************************************************************************}
- { PRIVATE RECORD TYPE DEFINITIONS }
- {***************************************************************************}
- {---------------------------------------------------------------------------}
- { TBuffer RECORD DEFINITION }
- {---------------------------------------------------------------------------}
- TYPE
- PBuffer = ^TBuffer; { Buffer pointer }
- TBuffer =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- PACKED
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- 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 =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- PACKED
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- RECORD
- Ofs, Seg: Word; { Pointer to words }
- END;
- {---------------------------------------------------------------------------}
- { TCache RECORD DEFINITION }
- {---------------------------------------------------------------------------}
- TYPE
- PCache = ^TCache; { Cache pointer }
- {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
- TCache =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- PACKED
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- RECORD
- Size : Word; { Cache size }
- Master: ^Pointer; { Master cache }
- Data : RECORD END; { Cache data }
- END;
- {$ELSE} { DPMI/WIN/NT/OS2 CODE }
- TCache =
- {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
- PACKED
- {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
- 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 }
- {$ifdef fpc}
- Inc(Pointer(Cache), SizeOf(TCache)); { Set cache offset }
- {$else fpc}
- Inc(PtrRec(Cache).Ofs, SizeOf(TCache)); { Set cache offset }
- {$endif fpc}
- 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
- {$ifdef fpc}
- Cache:=pointer(p)-SizeOf(TCache);
- {$else fpc}
- PtrRec(Cache).Ofs := PtrRec(P).Ofs-SizeOf(TCache); { Previous cache }
- PtrRec(Cache).Seg := PtrRec(P).Seg; { Segment }
- {$endif fpc}
- 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 { Check pointer }
- Begin
- {$ifdef fpc}
- Dec(Pointer(P),SizeOf(TBuffer)); { Correct to buffer }
- {$else fpc}
- Dec(PtrRec(P).Ofs,SizeOf(TBuffer)); { Correct to buffer }
- {$endif fpc}
- 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 (var 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 }
- {$ifdef fpc}
- Dec(Pointer(P),SizeOf(TBuffer)); { Correct to buffer }
- SetBufferSize := ReAllocMem(P, Size + SizeOf(TBuffer)) <> nil;
- if SetBufferSize then
- TBuffer(P^).Size := Size + SizeOf(TBuffer);
- Inc(Pointer(P), SizeOf(TBuffer)); { Correct to buffer }
- {$endif fpc}
- {$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 }
- {$ifdef fpc}
- Dec(Pointer(P), SizeOf(TBuffer)); { Actual buffer pointer }
- {$else fpc}
- Dec(PtrRec(P).Ofs, SizeOf(TBuffer)); { Actual buffer pointer }
- {$endif fpc}
- 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 }
- {$ifdef fpc}
- Inc(Pointer(Buffer), SizeOf(TBuffer)); { Buffer to data area }
- {$else fpc}
- Inc(PtrRec(Buffer).Ofs, SizeOf(TBuffer)); { Buffer to data area }
- {$endif fpc}
- 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.
|