1+ {
2+ MIT License
3+
4+ Copyright (c) 2022 Viacheslav Komenda
5+
6+ Permission is hereby granted, free of charge, to any person obtaining a copy
7+ of this software and associated documentation files (the "Software"), to deal
8+ in the Software without restriction, including without limitation the rights
9+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+ copies of the Software, and to permit persons to whom the Software is
11+ furnished to do so, subject to the following conditions:
12+
13+ The above copyright notice and this permission notice shall be included in all
14+ copies or substantial portions of the Software.
15+
16+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+ SOFTWARE.
23+ }
24+ { $A+,I-,S-,R-,D-,L-,Q-,F-,G-,O-,B-}
25+ UNIT SysMem;
26+
27+ INTERFACE
28+
29+ CONST
30+
31+ EXTMEM_BLOCK_SIZE = 16 * 1024 ;
32+
33+ FUNCTION sysmem_avail : BOOLEAN;
34+ FUNCTION sysmem_alloc (blk_count : WORD) : POINTER;
35+ FUNCTION sysmem_put (h : POINTER; blk_num : WORD; VAR blk) : BOOLEAN;
36+ FUNCTION sysmem_get (h : POINTER; blk_num : WORD; VAR blk) : BOOLEAN;
37+ PROCEDURE sysmem_free (h : POINTER);
38+
39+ IMPLEMENTATION
40+
41+ USES SysEms, SysXms;
42+
43+ TYPE
44+
45+ DWORD = LONGINT;
46+
47+ TMEMTYPE = (MT_NONE, MT_EMS, MT_XMS);
48+
49+ PSYSMEM_REC = ^TSYSMEM_REC;
50+ TSYSMEM_REC = RECORD
51+ ems_h : WORD;
52+ xms_h : WORD;
53+ size : WORD;
54+ END ;
55+
56+ VAR
57+
58+ ems_installed : BOOLEAN;
59+ ems_window : PCHAR;
60+ ems_winnum : WORD;
61+ ems_windows : ARRAY [0 ..3 ] OF WORD;
62+ xms_installed : BOOLEAN;
63+ memtype : TMEMTYPE;
64+
65+ FUNCTION ems_alloc (VAR he : TSYSMEM_REC; blk_count : WORD) : BOOLEAN;
66+ BEGIN
67+ he.ems_h := sysems.ems_malloc(blk_count);
68+ ems_alloc := he.ems_h <> 0 ;
69+ END ;
70+
71+ FUNCTION xms_alloc (VAR he : TSYSMEM_REC; blk_count : WORD) : BOOLEAN;
72+ BEGIN
73+ he.xms_h := sysxms.xms_malloc(blk_count);
74+ xms_alloc := he.xms_h <> 0 ;
75+ END ;
76+
77+ FUNCTION ems_get_win (h : WORD) : WORD;
78+ VAR i : WORD;
79+ BEGIN
80+ i := 0 ;
81+ WHILE i < 4 DO BEGIN
82+ IF ems_windows[i] = h THEN BEGIN
83+ BREAK;
84+ END ;
85+ Inc(i);
86+ END ;
87+ IF i = 4 THEN BEGIN
88+ i := ems_winnum;
89+ ems_windows[i] := h;
90+ ems_winnum := (ems_winnum + 1 ) AND 3 ;
91+ END ;
92+ ems_get_win := i;
93+ END ;
94+
95+ FUNCTION ems_get (VAR he : TSYSMEM_REC; blk_num : WORD; VAR blk) : BOOLEAN;
96+ VAR r : BOOLEAN;
97+ win : WORD;
98+ BEGIN
99+ r := FALSE;
100+ win := ems_get_win(he.ems_h);
101+ IF sysems.ems_map(he.ems_h, blk_num, win) = EMS_STATUS_OK THEN BEGIN
102+ Move(ems_window[win SHL 14 ], blk, EMS_PAGE_SIZE);
103+ sysems.ems_map(he.ems_h, EMS_PAGE_UNMAP, win);
104+ r := TRUE;
105+ END ;
106+ ems_get := r;
107+ END ;
108+
109+ FUNCTION xms_get (VAR he : TSYSMEM_REC; blk_num : WORD; VAR blk) : BOOLEAN;
110+ BEGIN
111+ xms_copy(he.xms_h, blk_num, blk, XMS2DOS);
112+ xms_get := TRUE;
113+ END ;
114+
115+ FUNCTION ems_put (VAR he : TSYSMEM_REC; blk_num : WORD; VAR blk) : BOOLEAN;
116+ VAR r : BOOLEAN;
117+ win : WORD;
118+ BEGIN
119+ r := FALSE;
120+ win := ems_get_win(he.ems_h);
121+ IF sysems.ems_map(he.ems_h, blk_num, win) = EMS_STATUS_OK THEN BEGIN
122+ Move(blk, ems_window[win SHL 14 ], EMS_PAGE_SIZE);
123+ sysems.ems_map(he.ems_h, EMS_PAGE_UNMAP, win);
124+ r := TRUE;
125+ END ;
126+ ems_put := r;
127+ END ;
128+
129+ FUNCTION xms_put (VAR he : TSYSMEM_REC; blk_num : WORD; VAR blk) : BOOLEAN;
130+ BEGIN
131+ xms_copy(he.xms_h, blk_num, blk, DOS2XMS);
132+ xms_put := TRUE;
133+ END ;
134+
135+ PROCEDURE ems_free (VAR he : TSYSMEM_REC);
136+ VAR i : INTEGER;
137+ BEGIN
138+ IF he.ems_h <> 0 THEN BEGIN
139+ FOR i := 0 TO 3 DO BEGIN
140+ IF ems_windows[i] = he.ems_h THEN BEGIN
141+ ems_windows[i] := 0 ;
142+ END ;
143+ END ;
144+ sysems.ems_free(he.ems_h);
145+ END ;
146+ END ;
147+
148+ PROCEDURE xms_free (VAR he : TSYSMEM_REC);
149+ BEGIN
150+ IF he.xms_h <> 0 THEN sysxms.xms_free(he.xms_h);
151+ END ;
152+
153+ FUNCTION sysmem_avail : BOOLEAN;
154+ BEGIN
155+ sysmem_avail := memtype IN [MT_EMS, MT_XMS];
156+ END ;
157+
158+ FUNCTION sysmem_alloc (blk_count : WORD):POINTER;
159+ VAR he : Psysmem_REC;
160+ r : BOOLEAN;
161+ BEGIN
162+ he := NIL ;
163+ IF memtype <> MT_NONE THEN BEGIN
164+ GetMem(he, SizeOf(Tsysmem_REC));
165+ IF he <> NIL THEN BEGIN
166+ FillChar(he^, SizeOf(Tsysmem_REC), #0 );
167+ IF memtype = MT_EMS THEN r := sysmem.ems_alloc(he^, blk_count)
168+ ELSE IF memtype = MT_XMS THEN r := sysmem.xms_alloc(he^, blk_count)
169+ ELSE r := FALSE;
170+ IF r THEN he^.size := blk_count ELSE BEGIN
171+ FreeMem(he, SizeOf(Tsysmem_REC));
172+ he := NIL ;
173+ END ;
174+ END ;
175+ END ;
176+ sysmem_alloc := he;
177+ END ;
178+
179+ FUNCTION sysmem_get (h : POINTER; blk_num:WORD; VAR blk) : BOOLEAN;
180+ BEGIN
181+ IF h = NIL THEN sysmem_get := FALSE
182+ ELSE IF blk_num >= Psysmem_REC(h)^.size THEN sysmem_get := FALSE
183+ ELSE IF memtype = MT_XMS THEN sysmem_get := xms_get(PSYSMEM_REC(h)^, blk_num, blk)
184+ ELSE IF memtype = MT_EMS THEN sysmem_get := ems_get(PSYSMEM_REC(h)^, blk_num, blk)
185+ ELSE sysmem_get := FALSE;
186+ END ;
187+
188+ FUNCTION sysmem_put (h : POINTER; blk_num : WORD; VAR blk) : BOOLEAN;
189+ BEGIN
190+ IF h = NIL THEN sysmem_put := FALSE
191+ ELSE IF blk_num >= Psysmem_REC(h)^.size THEN sysmem_put := FALSE
192+ ELSE IF memtype = MT_XMS THEN sysmem_put := xms_put(PSYSMEM_REC(h)^, blk_num, blk)
193+ ELSE IF memtype = MT_EMS THEN sysmem_put := ems_put(PSYSMEM_REC(h)^, blk_num, blk)
194+ ELSE sysmem_put := FALSE;
195+ END ;
196+
197+ PROCEDURE sysmem_free (h : POINTER);
198+ BEGIN
199+ IF h = NIL THEN EXIT
200+ ELSE IF memtype = MT_XMS THEN xms_free(PSYSMEM_REC(h)^)
201+ ELSE IF memtype = MT_EMS THEN ems_free(PSYSMEM_REC(h)^);
202+ FreeMem(h, SizeOf(TSYSMEM_REC));
203+ END ;
204+
205+ BEGIN
206+ ems_installed := FALSE;
207+ xms_installed := FALSE;
208+ ems_window := NIL ;
209+ FillChar(ems_windows, SizeOf(ems_windows), #0 );
210+ memtype := MT_NONE;
211+
212+ xms_installed := xms_check_driver;
213+ IF ems_check_driver THEN IF ems_get_status = EMS_STATUS_OK THEN BEGIN
214+ ems_installed := TRUE;
215+ ems_window := ems_get_window;
216+ ems_winnum := 0 ;
217+ END ;
218+
219+ IF xms_installed THEN memtype := MT_XMS
220+ ELSE IF ems_installed THEN memtype := MT_EMS;
221+ END .
0 commit comments