memory.pas 39 KB

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