memory.pas 39 KB

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