memory.pas 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900
  1. {********[ SOURCE FILE OF GRAPHICAL FREE VISION ]**********}
  2. { }
  3. { System independent clone of MEMORY.PAS }
  4. { }
  5. { Interface Copyright (c) 1992 Borland International }
  6. { }
  7. { Copyright (c) 1996, 1997, 1998, 1999 by Leon de Boer }
  8. { [email protected] - primary e-mail address }
  9. { [email protected] - backup e-mail address }
  10. { }
  11. {****************[ THIS CODE IS FREEWARE ]*****************}
  12. { }
  13. { This sourcecode is released for the purpose to }
  14. { promote the pascal language on all platforms. You may }
  15. { redistribute it and/or modify with the following }
  16. { DISCLAIMER. }
  17. { }
  18. { This SOURCE CODE is distributed "AS IS" WITHOUT }
  19. { WARRANTIES AS TO PERFORMANCE OF MERCHANTABILITY OR }
  20. { ANY OTHER WARRANTIES WHETHER EXPRESSED OR IMPLIED. }
  21. { }
  22. {*****************[ SUPPORTED PLATFORMS ]******************}
  23. { 16 and 32 Bit compilers }
  24. { DOS - Turbo Pascal 7.0 + (16 Bit) }
  25. { DPMI - Turbo Pascal 7.0 + (16 Bit) }
  26. { - FPC 0.9912+ (GO32V2) (32 Bit) }
  27. { WINDOWS - Turbo Pascal 7.0 + (16 Bit) }
  28. { - Delphi 1.0+ (16 Bit) }
  29. { WIN95/NT - Delphi 2.0+ (32 Bit) }
  30. { - Virtual Pascal 2.0+ (32 Bit) }
  31. { - Speedsoft Sybil 2.0+ (32 Bit) }
  32. { - FPC 0.9912+ (32 Bit) }
  33. { OS2 - Virtual Pascal 1.0+ (32 Bit) }
  34. { }
  35. {******************[ REVISION HISTORY ]********************}
  36. { Version Date Fix }
  37. { ------- --------- --------------------------------- }
  38. { 1.00 19 feb 96 Initial DOS/DPMI code released. }
  39. { 1.10 18 Jul 97 Windows conversion added. }
  40. { 1.20 29 Aug 97 Platform.inc sort added. }
  41. { 1.30 05 May 98 Virtual pascal 2.0 code added. }
  42. { 1.40 01 Oct 99 Complete multiplatform rewrite }
  43. { 1.41 03 Nov 99 FPC Windows support added }
  44. {**********************************************************}
  45. {$IFNDEF FPC_DOTTEDUNITS}
  46. UNIT Memory;
  47. {$ENDIF FPC_DOTTEDUNITS}
  48. {====Include file to sort compiler platform out =====================}
  49. {$I platform.inc}
  50. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  51. INTERFACE
  52. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  53. {====================================================================}
  54. {==== Compiler directives ===========================================}
  55. {$IFNDEF PPC_FPC}{ FPC doesn't support these switches }
  56. {$F+} { Force far calls }
  57. {$A+} { Word Align Data }
  58. {$B-} { Allow short circuit boolean evaluations }
  59. {$O+} { This unit may be overlaid }
  60. {$G+} { 286 Code optimization - if you're on an 8088 get a real computer }
  61. {$P-} { Normal string variables }
  62. {$N-} { No 80x87 code generation }
  63. {$E+} { Emulation is on }
  64. {$ENDIF}
  65. {$X+} { Extended syntax is ok }
  66. {$R-} { Disable range checking }
  67. {$S-} { Disable Stack Checking }
  68. {$I-} { Disable IO Checking }
  69. {$Q-} { Disable Overflow Checking }
  70. {$V-} { Turn off strict VAR strings }
  71. {====================================================================}
  72. {$IFDEF FPC_DOTTEDUNITS}
  73. USES FreeVision.Fvcommon;
  74. {$ELSE FPC_DOTTEDUNITS}
  75. USES FVCommon;
  76. {$ENDIF FPC_DOTTEDUNITS}
  77. {***************************************************************************}
  78. { INTERFACE ROUTINES }
  79. {***************************************************************************}
  80. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  81. { MEMORY ACCESS ROUTINES }
  82. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  83. {-MemAlloc-----------------------------------------------------------
  84. Allocates the requested size of memory if this takes memory free below
  85. the safety pool then a nil pointer is returned.
  86. 01Oct99 LdB
  87. ---------------------------------------------------------------------}
  88. FUNCTION MemAlloc (Size: Word): Pointer;
  89. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  90. { MEMORY MANAGER SYSTEM CONTROL ROUTINES }
  91. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  92. {-LowMemory----------------------------------------------------------
  93. Returns if the free memory left is below the safety pool value.
  94. 01Oct99 LdB
  95. ---------------------------------------------------------------------}
  96. FUNCTION LowMemory: Boolean;
  97. {-InitMemory---------------------------------------------------------
  98. Initializes the memory and safety pool manager. This should be called
  99. prior to using any of the memory manager routines.
  100. 01Oct99 LdB
  101. ---------------------------------------------------------------------}
  102. PROCEDURE InitMemory;
  103. {-DoneMemory---------------------------------------------------------
  104. Closes the memory and safety pool manager. This should be called after
  105. using the memory manager routines so as to clean up.
  106. 01Oct99 LdB
  107. ---------------------------------------------------------------------}
  108. PROCEDURE DoneMemory;
  109. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  110. { CACHE MEMORY ROUTINES }
  111. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  112. {-NewCache-----------------------------------------------------------
  113. Create a new cache of given size in pointer P failure will return nil.
  114. 01Oct99 LdB
  115. ---------------------------------------------------------------------}
  116. PROCEDURE NewCache (Var P: Pointer; Size: Word);
  117. {-DisposeCache-------------------------------------------------------
  118. Dispose of a cache buffer given by pointer P.
  119. 01Oct99 LdB
  120. ---------------------------------------------------------------------}
  121. PROCEDURE DisposeCache (P: Pointer);
  122. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  123. { BUFFER MEMORY ROUTINES }
  124. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  125. {-GetBufferSize------------------------------------------------------
  126. Returns the size of memory buffer given by pointer P.
  127. 01Oct99 LdB
  128. ---------------------------------------------------------------------}
  129. FUNCTION GetBufferSize (P: Pointer): Word;
  130. {-SetBufferSize------------------------------------------------------
  131. Change the size of buffer given by pointer P to the size requested.
  132. 01Oct99 LdB
  133. ---------------------------------------------------------------------}
  134. FUNCTION SetBufferSize (var P: Pointer; Size: Word): Boolean;
  135. {-DisposeBuffer------------------------------------------------------
  136. Dispose of buffer given by pointer P.
  137. 01Oct99 LdB
  138. ---------------------------------------------------------------------}
  139. PROCEDURE DisposeBuffer (P: Pointer);
  140. {-NewBuffer----------------------------------------------------------
  141. Create a new buffer of given size in ptr P failure will return nil.
  142. 01Oct99 LdB
  143. ---------------------------------------------------------------------}
  144. PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
  145. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  146. { DOS MEMORY CONTROL ROUTINES }
  147. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  148. {-InitDosMem---------------------------------------------------------
  149. Initialize memory manager routine for a shell to launch a DOS window.
  150. Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
  151. 01Oct99 LdB
  152. ---------------------------------------------------------------------}
  153. PROCEDURE InitDosMem;
  154. {-DoneDosMem---------------------------------------------------------
  155. Finished shell to a DOS window so reset memory manager again.
  156. Interface for compatability only under DPMI/WIN/NT/OS2 platforms.
  157. 01Oct99 LdB
  158. ---------------------------------------------------------------------}
  159. PROCEDURE DoneDosMem;
  160. {***************************************************************************}
  161. { PUBLIC INITIALIZED VARIABLES }
  162. {***************************************************************************}
  163. CONST
  164. LowMemSize : Word = 4096 DIV 16; { 4K }
  165. SafetyPoolSize: Word = 8192; { Safety pool size }
  166. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  167. MaxHeapSize : Word = 655360 DIV 16; { 640K }
  168. MaxBufMem : Word = 65536 DIV 16; { 64K }
  169. {$ENDIF}
  170. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  171. IMPLEMENTATION
  172. {<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>}
  173. {$IFDEF FPC_DOTTEDUNITS}
  174. {$IFDEF OS_WINDOWS} { WIN/NT CODE }
  175. {$IFDEF PPC_FPC} { FPC WinApi.Windows COMPILER }
  176. USES WinApi.Windows; { Standard unit }
  177. {$ELSE} { OTHER COMPILERS }
  178. USES WinApi.WinProcs, WinApi.WinTypes; { Standard units }
  179. {$ENDIF}
  180. {$ENDIF}
  181. {$IFDEF OS_OS2} { OS2 CODE }
  182. {$IFDEF PPC_FPC}
  183. USES OS2Api.doscalls; { Standard unit }
  184. {$ELSE}
  185. USES Os2Base; { Standard unit }
  186. {$ENDIF}
  187. {$ENDIF}
  188. {$ELSE FPC_DOTTEDUNITS}
  189. {$IFDEF OS_WINDOWS} { WIN/NT CODE }
  190. {$IFDEF PPC_FPC} { FPC WINDOWS COMPILER }
  191. USES Windows; { Standard unit }
  192. {$ELSE} { OTHER COMPILERS }
  193. USES WinProcs, WinTypes; { Standard units }
  194. {$ENDIF}
  195. {$ENDIF}
  196. {$IFDEF OS_OS2} { OS2 CODE }
  197. {$IFDEF PPC_FPC}
  198. USES DosCalls; { Standard unit }
  199. {$ELSE}
  200. USES Os2Base; { Standard unit }
  201. {$ENDIF}
  202. {$ENDIF}
  203. {$ENDIF FPC_DOTTEDUNITS}
  204. {***************************************************************************}
  205. { PRIVATE RECORD TYPE DEFINITIONS }
  206. {***************************************************************************}
  207. {---------------------------------------------------------------------------}
  208. { TBuffer RECORD DEFINITION }
  209. {---------------------------------------------------------------------------}
  210. TYPE
  211. PBuffer = ^TBuffer; { Buffer pointer }
  212. TBuffer =
  213. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  214. PACKED
  215. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  216. RECORD
  217. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  218. Size : Word; { Buffer size }
  219. Master: ^Word; { Master buffer }
  220. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  221. Next: PBuffer; { Next buffer }
  222. Size: Word; { Buffer size }
  223. Data: RECORD END; { Buffer data }
  224. {$ENDIF}
  225. END;
  226. {---------------------------------------------------------------------------}
  227. { POINTER TYPE CONVERSION RECORDS }
  228. {---------------------------------------------------------------------------}
  229. TYPE
  230. PtrRec =
  231. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  232. PACKED
  233. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  234. RECORD
  235. Ofs, Seg: Word; { Pointer to words }
  236. END;
  237. {---------------------------------------------------------------------------}
  238. { TCache RECORD DEFINITION }
  239. {---------------------------------------------------------------------------}
  240. TYPE
  241. PCache = ^TCache; { Cache pointer }
  242. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  243. TCache =
  244. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  245. PACKED
  246. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  247. RECORD
  248. Size : Word; { Cache size }
  249. Master: ^Pointer; { Master cache }
  250. Data : RECORD END; { Cache data }
  251. END;
  252. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  253. TCache =
  254. {$ifndef FPC_REQUIRES_PROPER_ALIGNMENT}
  255. PACKED
  256. {$endif FPC_REQUIRES_PROPER_ALIGNMENT}
  257. RECORD
  258. Next : PCache; { Next cache }
  259. Master: ^Pointer; { Master cache }
  260. Size : Word; { Size of cache }
  261. Data : RECORD END; { Cache data }
  262. End;
  263. {$ENDIF}
  264. {***************************************************************************}
  265. { INITIALIZED PRIVATE VARIABLES }
  266. {***************************************************************************}
  267. CONST
  268. DisablePool: Boolean = False; { Disable safety pool }
  269. SafetyPool : Pointer = Nil; { Safety pool memory }
  270. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  271. HeapResult: SmallInt = 0; { Heap result }
  272. BufHeapPtr: Word = 0; { Heap position }
  273. BufHeapEnd: Word = 0; { Heap end }
  274. CachePtr : Pointer = Nil; { Cache list }
  275. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  276. CacheList : PCache = Nil; { Cache list }
  277. BufferList: PBuffer = Nil; { Buffer list }
  278. {$ENDIF}
  279. {***************************************************************************}
  280. { PRIVATE UNIT ROUTINES }
  281. {***************************************************************************}
  282. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  283. { PRIVATE UNIT ROUTINES - REAL MODE DOS PLATFORMS }
  284. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  285. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  286. {---------------------------------------------------------------------------}
  287. { GetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
  288. {---------------------------------------------------------------------------}
  289. FUNCTION GetBufSize (P: PBuffer): Word; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  290. BEGIN
  291. GetBufSize := (P^.Size + 15) SHR 4 + 1; { Buffer paragraphs }
  292. END;
  293. {---------------------------------------------------------------------------}
  294. { FreeCacheMem -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
  295. {---------------------------------------------------------------------------}
  296. PROCEDURE FreeCacheMem; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  297. BEGIN
  298. While (CachePtr <> HeapEnd) Do
  299. DisposeCache(CachePtr); { Release blocks }
  300. END;
  301. {---------------------------------------------------------------------------}
  302. { SetMemTop -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
  303. {---------------------------------------------------------------------------}
  304. PROCEDURE SetMemTop (MemTop: Pointer); ASSEMBLER;
  305. ASM
  306. MOV BX, MemTop.Word[0]; { Top of memory }
  307. ADD BX, 15;
  308. MOV CL, 4;
  309. SHR BX, CL; { Size in paragraphs }
  310. ADD BX, MemTop.Word[2];
  311. MOV AX, PrefixSeg; { Add prefix seg }
  312. SUB BX, AX;
  313. MOV ES, AX;
  314. MOV AH, 4AH;
  315. INT 21H; { Call to DOS }
  316. END;
  317. {---------------------------------------------------------------------------}
  318. { MoveSeg -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
  319. {---------------------------------------------------------------------------}
  320. PROCEDURE MoveSeg (Source, Dest, Size: Word); NEAR; ASSEMBLER;
  321. ASM
  322. PUSH DS; { Save register }
  323. MOV AX, Source;
  324. MOV DX, Dest; { Destination }
  325. MOV BX, Size;
  326. CMP AX, DX; { Does Source=Dest? }
  327. JB @@3;
  328. CLD; { Go forward }
  329. @@1:
  330. MOV CX, 0FFFH;
  331. CMP CX, BX;
  332. JB @@2;
  333. MOV CX, BX;
  334. @@2:
  335. MOV DS, AX;
  336. MOV ES, DX;
  337. ADD AX, CX;
  338. ADD DX, CX;
  339. SUB BX, CX;
  340. SHL CX, 3; { Mult x8 }
  341. XOR SI, SI;
  342. XOR DI, DI;
  343. REP MOVSW;
  344. OR BX, BX;
  345. JNE @@1;
  346. JMP @@6;
  347. @@3: { Source=Dest }
  348. ADD AX, BX; { Hold register }
  349. ADD DX, BX; { Must go backwards }
  350. STD;
  351. @@4:
  352. MOV CX, 0FFFH;
  353. CMP CX, BX;
  354. JB @@5;
  355. MOV CX, BX;
  356. @@5:
  357. SUB AX, CX;
  358. SUB DX, CX;
  359. SUB BX, CX;
  360. MOV DS, AX;
  361. MOV ES, DX;
  362. SHL CX, 3; { Mult x8 }
  363. MOV SI, CX;
  364. DEC SI;
  365. SHL SI, 1;
  366. MOV DI, SI;
  367. REP MOVSW; { Move data }
  368. OR BX, BX;
  369. JNE @@4;
  370. @@6:
  371. POP DS; { Recover register }
  372. END;
  373. {---------------------------------------------------------------------------}
  374. { SetBufSize -> Platforms DOS REAL MODE - Updated 01Oct99 LdB }
  375. {---------------------------------------------------------------------------}
  376. PROCEDURE SetBufSize (P: PBuffer; NewSize: Word); {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  377. VAR CurSize: Word;
  378. BEGIN
  379. CurSize := GetBufSize(P); { Current size }
  380. MoveSeg(PtrRec(P).Seg + CurSize, PtrRec(P).Seg+
  381. NewSize, BufHeapPtr - PtrRec(P).Seg - CurSize); { Move data }
  382. Inc(BufHeapPtr, NewSize - CurSize); { Adjust heap space }
  383. Inc(PtrRec(P).Seg, NewSize); { Adjust pointer }
  384. While PtrRec(P).Seg < BufHeapPtr Do Begin
  385. Inc(P^.Master^, NewSize - CurSize); { Adjust master }
  386. Inc(PtrRec(P).Seg, (P^.Size + 15) SHR 4 + 1); { Adjust paragraphs }
  387. End;
  388. END;
  389. {$ENDIF}
  390. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  391. { PRIVATE UNIT ROUTINES - DPMI/WIN/NT/OS2 PLATFORMS }
  392. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  393. {$IFNDEF PROC_REAL} { DPMI/WIN/NT/OS2 CODE }
  394. {---------------------------------------------------------------------------}
  395. { FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  396. {---------------------------------------------------------------------------}
  397. FUNCTION FreeCache: Boolean; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  398. BEGIN
  399. FreeCache := False; { Preset fail }
  400. If (CacheList <> Nil) Then Begin
  401. DisposeCache(CacheList^.Next^.Master^); { Dispose cache }
  402. FreeCache := True; { Return success }
  403. End;
  404. END;
  405. {---------------------------------------------------------------------------}
  406. { FreeCache -> Platforms DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  407. {---------------------------------------------------------------------------}
  408. FUNCTION FreeSafetyPool: Boolean; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  409. BEGIN
  410. FreeSafetyPool := False; { Preset fail }
  411. If (SafetyPool <> Nil) Then Begin { Pool exists }
  412. FreeMem(SafetyPool, SafetyPoolSize); { Release memory }
  413. SafetyPool := Nil; { Clear pointer }
  414. FreeSafetyPool := True; { Return true }
  415. End;
  416. END;
  417. {$ENDIF}
  418. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  419. { PRIVATE UNIT ROUTINES - ALL PLATFORMS }
  420. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  421. {---------------------------------------------------------------------------}
  422. { HeapNotify -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  423. {---------------------------------------------------------------------------}
  424. FUNCTION HeapNotify (Size: Word): SmallInt; {$IFNDEF PPC_FPC}FAR;{$ENDIF}
  425. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  426. ASSEMBLER;
  427. ASM
  428. CMP Size, 0; { Check for zero size }
  429. JNE @@3; { Exit if size = zero }
  430. @@1:
  431. MOV AX, CachePtr.Word[2];
  432. CMP AX, HeapPtr.Word[2]; { Compare segments }
  433. JA @@3;
  434. JB @@2;
  435. MOV AX, CachePtr.Word[0];
  436. CMP AX, HeapPtr.Word[0]; { Compare offsets }
  437. JAE @@3;
  438. @@2:
  439. XOR AX, AX; { Clear register }
  440. PUSH AX; { Push zero }
  441. PUSH AX; { Push zero }
  442. CALL DisposeCache; { Dispose cache }
  443. JMP @@1;
  444. @@3:
  445. MOV AX, HeapResult; { Return result }
  446. END;
  447. {$ELSE} { DPMI/WIN/NT/OS2 }
  448. BEGIN
  449. If FreeCache Then HeapNotify := 2 Else { Release cache }
  450. If DisablePool Then HeapNotify := 1 Else { Safetypool disabled }
  451. If FreeSafetyPool Then HeapNotify := 2 Else { Free safety pool }
  452. HeapNotify := 0; { Return success }
  453. END;
  454. {$ENDIF}
  455. {***************************************************************************}
  456. { INTERFACE ROUTINES }
  457. {***************************************************************************}
  458. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  459. { MEMORY ACCESS ROUTINES }
  460. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  461. {---------------------------------------------------------------------------}
  462. { MemAlloc -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  463. {---------------------------------------------------------------------------}
  464. FUNCTION MemAlloc (Size: Word): Pointer;
  465. VAR P: Pointer;
  466. BEGIN
  467. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  468. HeapResult := 1; { Stop error calls }
  469. GetMem(P, Size); { Get memory }
  470. HeapResult := 0; { Reset error calls }
  471. If (P <> Nil) AND LowMemory Then Begin { Low memory }
  472. FreeMem(P, Size); { Release memory }
  473. P := Nil; { Clear pointer }
  474. End;
  475. MemAlloc := P; { Return result }
  476. {$ELSE} { DPMI/WIN/NT/OS2 }
  477. DisablePool := True; { Disable safety }
  478. GetMem(P, Size); { Allocate memory }
  479. DisablePool := False; { Enable safety }
  480. MemAlloc := P; { Return result }
  481. {$ENDIF}
  482. END;
  483. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  484. { MEMORY MANAGER SYSTEM CONTROL ROUTINES }
  485. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  486. {---------------------------------------------------------------------------}
  487. { LowMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Checked 29Jun98 LdB }
  488. {---------------------------------------------------------------------------}
  489. FUNCTION LowMemory: Boolean;
  490. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  491. ASSEMBLER;
  492. ASM
  493. MOV AX, HeapEnd.Word[2]; { Get heap end }
  494. SUB AX, HeapPtr.Word[2];
  495. SUB AX, LowMemSize; { Subtract size }
  496. SBB AX, AX;
  497. NEG AX; { Return result }
  498. END;
  499. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  500. BEGIN
  501. LowMemory := False; { Preset false }
  502. If (SafetyPool = Nil) Then Begin { Not initialized }
  503. SafetyPool := MemAlloc(SafetyPoolSize); { Allocate safety pool }
  504. If (SafetyPool = Nil) Then LowMemory := True; { Return if low memory }
  505. End;
  506. END;
  507. {$ENDIF}
  508. {---------------------------------------------------------------------------}
  509. { InitMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  510. {---------------------------------------------------------------------------}
  511. PROCEDURE InitMemory;
  512. {$IFDEF PROC_REAL} VAR HeapSize: Word; {$ENDIF}
  513. BEGIN
  514. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  515. HeapError := @HeapNotify; { Point to error proc }
  516. If (BufHeapPtr = 0) Then Begin
  517. HeapSize := PtrRec(HeapEnd).Seg
  518. - PtrRec(HeapOrg).Seg; { Calculate size }
  519. If (HeapSize > MaxHeapSize) Then
  520. HeapSize := MaxHeapSize; { Restrict max size }
  521. BufHeapEnd := PtrRec(HeapEnd).Seg; { Set heap end }
  522. PtrRec(HeapEnd).Seg := PtrRec(HeapOrg).Seg
  523. + HeapSize; { Add heapsize }
  524. BufHeapPtr := PtrRec(HeapEnd).Seg; { Set heap pointer }
  525. End;
  526. CachePtr := HeapEnd; { Cache starts at end }
  527. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  528. {$IFNDEF PPC_FPC}
  529. HeapError := @HeapNotify; { Set heap error proc }
  530. {$ENDIF}
  531. SafetyPoolSize := LowMemSize * 16; { Fix safety pool size }
  532. LowMemory; { Check for low memory }
  533. {$ENDIF}
  534. END;
  535. {---------------------------------------------------------------------------}
  536. { DoneMemory -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  537. {---------------------------------------------------------------------------}
  538. PROCEDURE DoneMemory;
  539. BEGIN
  540. {$IFDEF PROC_REAL} { REAl MODE DOS CODE }
  541. FreeCacheMem; { Release cache memory }
  542. {$ELSE} { DPMI/WIN/NT/OS2 }
  543. While FreeCache Do; { Free cache memory }
  544. FreeSafetyPool; { Release safety pool }
  545. {$ENDIF}
  546. END;
  547. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  548. { CACHE MEMORY ROUTINES }
  549. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  550. {---------------------------------------------------------------------------}
  551. { NewCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  552. {---------------------------------------------------------------------------}
  553. PROCEDURE NewCache (Var P: Pointer; Size: Word);
  554. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  555. ASSEMBLER;
  556. ASM
  557. LES DI, P; { Addres of var P }
  558. MOV AX, Size;
  559. ADD AX, (TYPE TCache)+15; { Add offset }
  560. MOV CL, 4;
  561. SHR AX, CL;
  562. MOV DX, CachePtr.Word[2]; { Reteive cache ptr }
  563. SUB DX, AX;
  564. JC @@1;
  565. CMP DX, HeapPtr.Word[2]; { Heap ptr end }
  566. JBE @@1;
  567. MOV CX, HeapEnd.Word[2];
  568. SUB CX, DX;
  569. CMP CX, MaxBufMem; { Compare to maximum }
  570. JA @@1;
  571. MOV CachePtr.Word[2], DX; { Exchange ptr }
  572. PUSH DS;
  573. MOV DS, DX;
  574. XOR SI, SI;
  575. MOV DS:[SI].TCache.Size, AX; { Get cache size }
  576. MOV DS:[SI].TCache.Master.Word[0], DI;
  577. MOV DS:[SI].TCache.Master.Word[2], ES; { Get master ptr }
  578. POP DS;
  579. MOV AX, OFFSET TCache.Data;
  580. JMP @@2;
  581. @@1:
  582. XOR AX, AX;
  583. CWD; { Make double word }
  584. @@2:
  585. CLD;
  586. STOSW; { Write low word }
  587. XCHG AX, DX;
  588. STOSW; { Write high word }
  589. END;
  590. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  591. VAR Cache: PCache;
  592. BEGIN
  593. Inc(Size, SizeOf(TCache)); { Add cache size }
  594. If (MaxAvail >= Size) Then GetMem(Cache, Size) { Allocate memory }
  595. Else Cache := Nil; { Not enough memory }
  596. If (Cache <> Nil) Then Begin { Cache is valid }
  597. If (CacheList = Nil) Then Cache^.Next := Cache
  598. Else Begin
  599. Cache^.Next := CacheList^.Next; { Insert in list }
  600. CacheList^.Next := Cache; { Complete link }
  601. End;
  602. CacheList := Cache; { Hold cache ptr }
  603. Cache^.Size := Size; { Hold cache size }
  604. Cache^.Master := @P; { Hold master ptr }
  605. {$ifdef fpc}
  606. Inc(Pointer(Cache), SizeOf(TCache)); { Set cache offset }
  607. {$else fpc}
  608. Inc(PtrRec(Cache).Ofs, SizeOf(TCache)); { Set cache offset }
  609. {$endif fpc}
  610. End;
  611. P := Cache; { Return pointer }
  612. END;
  613. {$ENDIF}
  614. {---------------------------------------------------------------------------}
  615. { DisposeCache -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  616. {---------------------------------------------------------------------------}
  617. PROCEDURE DisposeCache (P: Pointer);
  618. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  619. ASSEMBLER;
  620. ASM
  621. MOV AX, CachePtr.Word[2]; { Cache high word }
  622. XOR BX, BX;
  623. XOR CX, CX;
  624. MOV DX, P.Word[2]; { P high word }
  625. @@1:
  626. MOV ES, AX;
  627. CMP AX, DX; { Check for match }
  628. JE @@2;
  629. ADD AX, ES:[BX].TCache.Size; { Move to next cache }
  630. CMP AX, HeapEnd.Word[2];
  631. JE @@2; { Are we at heap end }
  632. PUSH ES;
  633. INC CX; { No so try next }
  634. JMP @@1;
  635. @@2:
  636. PUSH ES;
  637. LES DI, ES:[BX].TCache.Master; { Pointe to master }
  638. XOR AX, AX;
  639. CLD;
  640. STOSW; { Clear master ptr }
  641. STOSW;
  642. POP ES;
  643. MOV AX, ES:[BX].TCache.Size; { Next cache }
  644. JCXZ @@4;
  645. @@3:
  646. POP DX;
  647. PUSH DS;
  648. PUSH CX; { Hold registers }
  649. MOV DS, DX;
  650. ADD DX, AX;
  651. MOV ES, DX;
  652. MOV SI, DS:[BX].TCache.Size; { Get cache size }
  653. MOV CL, 3;
  654. SHL SI, CL; { Multiply x8 }
  655. MOV CX, SI;
  656. SHL SI, 1;
  657. DEC SI; { Adjust position }
  658. DEC SI;
  659. MOV DI, SI;
  660. STD;
  661. REP MOVSW; { Move cache memory }
  662. LDS SI, ES:[BX].TCache.Master;
  663. MOV DS:[SI].Word[2], ES; { Store new master }
  664. POP CX;
  665. POP DS; { Recover registers }
  666. LOOP @@3;
  667. @@4:
  668. ADD CachePtr.Word[2], AX; { Add offset }
  669. END;
  670. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  671. VAR Cache, C: PCache;
  672. BEGIN
  673. {$ifdef fpc}
  674. Cache:=pointer(p)-SizeOf(TCache);
  675. {$else fpc}
  676. PtrRec(Cache).Ofs := PtrRec(P).Ofs-SizeOf(TCache); { Previous cache }
  677. PtrRec(Cache).Seg := PtrRec(P).Seg; { Segment }
  678. {$endif fpc}
  679. C := CacheList; { Start at 1st cache }
  680. While (C^.Next <> Cache) AND (C^.Next <> CacheList)
  681. Do C := C^.Next; { Find previous }
  682. If (C^.Next = Cache) Then Begin { Cache found }
  683. If (C = Cache) Then CacheList := Nil Else Begin { Only cache in list }
  684. If CacheList = Cache Then CacheList := C; { First in list }
  685. C^.Next := Cache^.Next; { Remove from list }
  686. End;
  687. Cache^.Master^ := Nil; { Clear master }
  688. FreeMem(Cache, Cache^.Size); { Release memory }
  689. End;
  690. END;
  691. {$ENDIF}
  692. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  693. { BUFFER MEMORY ROUTINES }
  694. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  695. {---------------------------------------------------------------------------}
  696. { GetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  697. {---------------------------------------------------------------------------}
  698. FUNCTION GetBufferSize (P: Pointer): Word;
  699. BEGIN
  700. {$IFDEF PROC_REAL} { DOS CODE }
  701. Dec(PtrRec(P).Seg); { Segment prior }
  702. GetBufferSize := PBuffer(P)^.Size; { Size of this buffer }
  703. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  704. If (P <> Nil) Then { Check pointer }
  705. Begin
  706. {$ifdef fpc}
  707. Dec(Pointer(P),SizeOf(TBuffer)); { Correct to buffer }
  708. {$else fpc}
  709. Dec(PtrRec(P).Ofs,SizeOf(TBuffer)); { Correct to buffer }
  710. {$endif fpc}
  711. GetBufferSize := PBuffer(P)^.Size; { Return buffer size }
  712. End
  713. Else
  714. GetBufferSize := 0; { Invalid pointer }
  715. {$ENDIF}
  716. END;
  717. {---------------------------------------------------------------------------}
  718. { SetBufferSize -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  719. {---------------------------------------------------------------------------}
  720. FUNCTION SetBufferSize (var P: Pointer; Size: Word): Boolean;
  721. VAR NewSize: Word;
  722. BEGIN
  723. SetBufferSize := False; { Preset failure }
  724. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  725. Dec(PtrRec(P).Seg); { Prior segment }
  726. NewSize := (Size + 15) SHR 4 + 1; { Paragraph size }
  727. If (BufHeapPtr+NewSize-GetBufSize(P)<=BufHeapEnd) { Check enough heap }
  728. Then Begin
  729. SetBufSize(P, NewSize); { Set the buffer size }
  730. PBuffer(P)^.Size := Size; { Set the size }
  731. SetBufferSize := True; { Return success }
  732. End;
  733. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  734. {$ifdef fpc}
  735. Dec(Pointer(P),SizeOf(TBuffer)); { Correct to buffer }
  736. SetBufferSize := ReAllocMem(P, Size + SizeOf(TBuffer)) <> nil;
  737. if SetBufferSize then
  738. TBuffer(P^).Size := Size + SizeOf(TBuffer);
  739. Inc(Pointer(P), SizeOf(TBuffer)); { Correct to buffer }
  740. {$endif fpc}
  741. {$ENDIF}
  742. END;
  743. {---------------------------------------------------------------------------}
  744. { DisposeBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  745. {---------------------------------------------------------------------------}
  746. PROCEDURE DisposeBuffer (P: Pointer);
  747. {$IFNDEF PROC_REAL} VAR Buffer,PrevBuf: PBuffer; {$ENDIF}
  748. BEGIN
  749. If (P <> Nil) Then Begin
  750. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  751. Dec(PtrRec(P).Seg); { Prior segement }
  752. SetBufSize(P, 0); { Release memory }
  753. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  754. {$ifdef fpc}
  755. Dec(Pointer(P), SizeOf(TBuffer)); { Actual buffer pointer }
  756. {$else fpc}
  757. Dec(PtrRec(P).Ofs, SizeOf(TBuffer)); { Actual buffer pointer }
  758. {$endif fpc}
  759. Buffer := BufferList; { Start on first }
  760. PrevBuf := Nil; { Preset prevbuf to nil }
  761. While (Buffer <> Nil) AND (P <> Buffer) Do Begin { Search for buffer }
  762. PrevBuf := Buffer; { Hold last buffer }
  763. Buffer := Buffer^.Next; { Move to next buffer }
  764. End;
  765. If (Buffer <> Nil) Then Begin { Buffer was found }
  766. If (PrevBuf = Nil) Then { We were first on list }
  767. BufferList := Buffer^.Next Else { Set bufferlist entry }
  768. PrevBuf^.Next := Buffer^.Next; { Remove us from chain }
  769. FreeMem(Buffer, Buffer^.Size); { Release buffer }
  770. End;
  771. {$ENDIF}
  772. End;
  773. END;
  774. {---------------------------------------------------------------------------}
  775. { NewBuffer -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  776. {---------------------------------------------------------------------------}
  777. PROCEDURE NewBuffer (Var P: Pointer; Size: Word);
  778. VAR BufSize: Word; Buffer: PBuffer;
  779. BEGIN
  780. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  781. BufSize := (Size + 15) SHR 4 + 1; { Paragraphs to alloc }
  782. If (BufHeapPtr+BufSize > BufHeapEnd) Then P := Nil { Exceeeds heap }
  783. Else Begin
  784. Buffer := Ptr(BufHeapPtr, 0); { Current position }
  785. Buffer^.Size := Size; { Set size }
  786. Buffer^.Master := @PtrRec(P).Seg; { Set master }
  787. P := Ptr(BufHeapPtr + 1, 0); { Position ptr }
  788. Inc(BufHeapPtr, BufSize); { Allow space on heap }
  789. End;
  790. {$ELSE} { DPMI/WIN/NT/OS2 CODE }
  791. BufSize := Size + SizeOf(TBuffer); { Size to allocate }
  792. Buffer := MemAlloc(BufSize); { Allocate the memory }
  793. If (Buffer <> Nil) Then Begin
  794. Buffer^.Next := BufferList; { First part of chain }
  795. BufferList := Buffer; { Complete the chain }
  796. Buffer^.Size := BufSize; { Hold the buffer size }
  797. {$ifdef fpc}
  798. Inc(Pointer(Buffer), SizeOf(TBuffer)); { Buffer to data area }
  799. {$else fpc}
  800. Inc(PtrRec(Buffer).Ofs, SizeOf(TBuffer)); { Buffer to data area }
  801. {$endif fpc}
  802. End;
  803. P := Buffer; { Return the buffer ptr }
  804. {$ENDIF}
  805. END;
  806. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  807. { DOS MEMORY CONTROL ROUTINES }
  808. {+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++}
  809. {---------------------------------------------------------------------------}
  810. { InitDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  811. {---------------------------------------------------------------------------}
  812. PROCEDURE InitDosMem;
  813. BEGIN
  814. {$IFDEF PROC_REAL} { REAl MODE DOS CODE }
  815. SetMemTop(Ptr(BufHeapEnd, 0)); { Move heap to empty }
  816. {$ENDIF}
  817. END;
  818. {---------------------------------------------------------------------------}
  819. { DoneDosMem -> Platforms DOS/DPMI/WIN/NT/OS2 - Updated 01Oct99 LdB }
  820. {---------------------------------------------------------------------------}
  821. PROCEDURE DoneDosMem;
  822. {$IFDEF PROC_REAL} VAR MemTop: Pointer; {$ENDIF}
  823. BEGIN
  824. {$IFDEF PROC_REAL} { REAL MODE DOS CODE }
  825. MemTop := Ptr(BufHeapPtr, 0); { Top of memory }
  826. If (BufHeapPtr = PtrRec(HeapEnd).Seg) Then Begin { Is memory empty }
  827. FreeCacheMem; { Release memory }
  828. MemTop := HeapPtr; { Set pointer }
  829. End;
  830. SetMemTop(MemTop); { Release memory }
  831. {$ENDIF}
  832. END;
  833. END.