]> 4ch.mooo.com Git - 16.git/blob - 16/EMS.BAS
p16 screen design notes added to design.txt
[16.git] / 16 / EMS.BAS
1 ' Using EMS in QuickBASIC: Part 1 of 3\r
2 ' Source Code\r
3 '\r
4 ' By Jon Petrosky (Plasma)\r
5 ' www.phatcode.net\r
6 '\r
7 ' [Remember to start QB with the /L switch to enable interrupts]\r
8 \r
9 DEFINT A-Z\r
10 '$DYNAMIC\r
11 '$INCLUDE: 'QB.BI'\r
12 \r
13 DIM SHARED Regs AS RegTypeX\r
14 DIM SHARED EMS.Error            'Holds the error code of the last operation\r
15 \r
16 DECLARE FUNCTION EMS.ErrorMsg$ ()\r
17 DECLARE FUNCTION EMS.Init ()\r
18 DECLARE FUNCTION EMS.Version$ ()\r
19 DECLARE FUNCTION EMS.PageFrame ()\r
20 DECLARE FUNCTION EMS.FreeHandles ()\r
21 DECLARE FUNCTION EMS.FreePages ()\r
22 DECLARE FUNCTION EMS.TotalPages ()\r
23 DECLARE FUNCTION EMS.AllocPages (NumPages)\r
24 DECLARE SUB EMS.DeallocPages (Handle)\r
25 DECLARE SUB EMS.MapPage (Physical, Logical, Handle)\r
26 DECLARE SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
27 DECLARE SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)\r
28 DECLARE SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)\r
29 \r
30 CLS\r
31 \r
32 IF NOT EMS.Init THEN\r
33   PRINT "No EMM detected."\r
34   END\r
35 END IF\r
36 \r
37 COLOR 14, 1\r
38 PRINT SPACE$(22); "Using EMS in QuickBasic: Part 1 of 3"; SPACE$(22)\r
39 COLOR 15, 0\r
40 PRINT STRING$(31, 196); " EMS Information "; STRING$(32, 196)\r
41 COLOR 7\r
42 PRINT "EMM Version: "; EMS.Version$\r
43 \r
44 IF EMS.Version$ < "4.0" THEN\r
45   PRINT\r
46   PRINT "EMM 4.0 or later must be present to use some of the EMS functions."\r
47   END\r
48 END IF\r
49 \r
50 PRINT "Page frame at: "; HEX$(EMS.PageFrame); "h"\r
51 PRINT "Free handles:"; EMS.FreeHandles\r
52 \r
53 IF EMS.FreeHandles = 0 THEN\r
54   PRINT\r
55   PRINT "You need at least one free handle to run this demo."\r
56   END\r
57 END IF\r
58 \r
59 PRINT "Total EMS:"; EMS.TotalPages; "pages /"; EMS.TotalPages * 16&; "KB /"; EMS.TotalPages \ 64; "MB"\r
60 PRINT "Free EMS:"; EMS.FreePages; "pages /"; EMS.FreePages * 16&; "KB /"; EMS.FreePages \ 64; "MB"\r
61 \r
62 IF EMS.FreePages < 64 THEN\r
63   PRINT\r
64   PRINT "You need at least 64 pages (1 MB) free EMS to run this demo."\r
65   END\r
66 END IF\r
67 \r
68 PRINT\r
69 COLOR 15, 0\r
70 PRINT STRING$(31, 196); " Allocation Test "; STRING$(32, 196)\r
71 COLOR 7\r
72 PRINT "Allocating 64 pages (1 MB) of EMS...";\r
73 \r
74 Handle = EMS.AllocPages(64)\r
75 IF EMS.Error THEN\r
76   PRINT "error!"\r
77   PRINT EMS.ErrorMsg$\r
78   END\r
79 ELSE\r
80   PRINT "ok!"\r
81 END IF\r
82 \r
83 PRINT "Pages allocated to handle"; Handle\r
84 PRINT\r
85 COLOR 15, 0\r
86 PRINT STRING$(30, 196); " Page Map/Copy Test "; STRING$(30, 196)\r
87 COLOR 7\r
88 PRINT "Mapping logical page 0 to physical page 0...";\r
89 \r
90 EMS.MapPage 0, 0, Handle\r
91 IF EMS.Error THEN\r
92   PRINT "error!"\r
93   PRINT EMS.ErrorMsg$\r
94   END\r
95 ELSE\r
96   PRINT "ok!"\r
97 END IF\r
98 \r
99 PRINT "Mapping logical pages 0-3 to physical pages 0-3...";\r
100 \r
101 EMS.MapXPages 0, 0, 4, Handle\r
102 IF EMS.Error THEN\r
103   PRINT "error!"\r
104   PRINT EMS.ErrorMsg$\r
105   END\r
106 ELSE\r
107   PRINT "ok!"\r
108 END IF\r
109 \r
110 PRINT "Copying logical pages 0-31 to logical pages 32-63...";\r
111 \r
112 EMS.CopyMem 512288, Handle, 0, 0, Handle, 32, 0\r
113 IF EMS.Error THEN\r
114   PRINT "error!"\r
115   PRINT EMS.ErrorMsg$\r
116   END\r
117 ELSE\r
118   PRINT "ok!"\r
119 END IF\r
120 \r
121 PRINT "Exchanging logical pages 0-31 with logical pages 32-63...";\r
122 \r
123 EMS.ExchMem 512288, Handle, 0, 0, Handle, 32, 0\r
124 IF EMS.Error THEN\r
125   PRINT "error!"\r
126   PRINT EMS.ErrorMsg$\r
127   END\r
128 ELSE\r
129   PRINT "ok!"\r
130 END IF\r
131 \r
132 PRINT\r
133 COLOR 15, 0\r
134 PRINT STRING$(22, 196); " 10-Second Speed Test (Please Wait) "; STRING$(22, 196)\r
135 COLOR 7\r
136 \r
137 Mapped& = 0\r
138 StartTime! = TIMER\r
139 DO UNTIL StartTime! + 5 <= TIMER\r
140   EMS.MapXPages 0, 0, 4, Handle\r
141   Mapped& = Mapped& + 4\r
142 LOOP\r
143 \r
144 Copied& = 0\r
145 StartTime! = TIMER\r
146 DO UNTIL StartTime! + 5 <= TIMER\r
147   EMS.CopyMem 512288, Handle, 0, 0, Handle, 32, 0\r
148   Copied& = Copied& + 1\r
149 LOOP\r
150 \r
151 PRINT "Pages Mapped/Sec:"; Mapped& \ 5\r
152 PRINT "Bytes copied/Sec:"; (Copied& * 512288) \ 5\r
153 PRINT\r
154 COLOR 15, 0\r
155 PRINT STRING$(30, 196); " Deallocation Test "; STRING$(31, 196)\r
156 COLOR 7\r
157 PRINT "Deallocating 64 pages...";\r
158 \r
159 EMS.DeallocPages (Handle)\r
160 IF EMS.Error THEN\r
161   PRINT "error!"\r
162   PRINT EMS.ErrorMsg$\r
163   END\r
164 ELSE\r
165   PRINT "ok!";\r
166 END IF\r
167 \r
168 KeyPress$ = INPUT$(1)\r
169 CLS\r
170 END\r
171 \r
172 FUNCTION EMS.AllocPages (NumPages)\r
173 \r
174   'Allocates the number of pages in [NumPages] and\r
175   'returns the EMS handle the memory is allocated to.\r
176 \r
177   Regs.ax = &H4300                           'Allocate [NumPages] pages of EMS\r
178   Regs.bx = NumPages\r
179   InterruptX &H67, Regs, Regs\r
180   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
181 \r
182   EMS.AllocPages = Regs.dx                   'Return the handle\r
183 \r
184 END FUNCTION\r
185 \r
186 SUB EMS.CopyMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)\r
187 \r
188   'Copies memory from EMS or base memory to EMS or base memory, where:\r
189   '\r
190   'Length&    = Length of memory to copy in bytes\r
191   'SrcHandle  = EMS handle of source memory (use 0 if source is base memory)\r
192   'SrcSegment = Segment of source memory (or page number if source is EMS)\r
193   'SrcOffset  = Offset of source memory\r
194   'DstHandle  = EMS handle of destination memory (use 0 if destination is base memory)\r
195   'DstSegment = Segment of destination memory (or page number if destination is EMS)\r
196   'DstOffset  = Offset of destination memory\r
197 \r
198   'Determine the source and destination memory types by checking the handles\r
199   IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1)\r
200   IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1)\r
201 \r
202   'Create a buffer containing the copy information\r
203   CopyInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment)\r
204 \r
205   Regs.ax = &H5700                           'Copy the memory region\r
206   Regs.ds = VARSEG(CopyInfo$)                'described in the buffer\r
207   Regs.si = SADD(CopyInfo$)\r
208   InterruptX &H67, Regs, Regs\r
209   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
210 \r
211 END SUB\r
212 \r
213 SUB EMS.DeallocPages (Handle)\r
214 \r
215   'Deallocates the EMS pages allocated the EMS handle [Handle].\r
216   'You MUST remember to call the sub before your program ends\r
217   'if you allocate any memory!\r
218 \r
219   Regs.ax = &H4500                           'Release the pages allocated to [Handle]\r
220   Regs.dx = Handle\r
221   InterruptX &H67, Regs, Regs\r
222   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
223 \r
224 END SUB\r
225 \r
226 FUNCTION EMS.ErrorMsg$\r
227 \r
228   'Returns a text string describing the error code in EMS.Error.\r
229 \r
230   SELECT CASE EMS.Error\r
231     CASE &H0: Msg$ = "successful"\r
232     CASE &H80: Msg$ = "internal error"\r
233     CASE &H81: Msg$ = "hardware malfunction"\r
234     CASE &H82: Msg$ = "busy -- retry later"\r
235     CASE &H83: Msg$ = "invalid handle"\r
236     CASE &H84: Msg$ = "undefined function requested by application"\r
237     CASE &H85: Msg$ = "no more handles available"\r
238     CASE &H86: Msg$ = "error in save or restore of mapping context"\r
239     CASE &H87: Msg$ = "insufficient memory pages in system"\r
240     CASE &H88: Msg$ = "insufficient memory pages available"\r
241     CASE &H89: Msg$ = "zero pages requested"\r
242     CASE &H8A: Msg$ = "invalid logical page number encountered"\r
243     CASE &H8B: Msg$ = "invalid physical page number encountered"\r
244     CASE &H8C: Msg$ = "page-mapping hardware state save area is full"\r
245     CASE &H8D: Msg$ = "save of mapping context failed"\r
246     CASE &H8E: Msg$ = "restore of mapping context failed"\r
247     CASE &H8F: Msg$ = "undefined subfunction"\r
248     CASE &H90: Msg$ = "undefined attribute type"\r
249     CASE &H91: Msg$ = "feature not supported"\r
250     CASE &H92: Msg$ = "successful, but a portion of the source region has been overwritten"\r
251     CASE &H93: Msg$ = "length of source or destination region exceeds length of region allocated to either source or destination handle"\r
252     CASE &H94: Msg$ = "conventional and expanded memory regions overlap"\r
253     CASE &H95: Msg$ = "offset within logical page exceeds size of logical page"\r
254     CASE &H96: Msg$ = "region length exceeds 1 MB"\r
255     CASE &H97: Msg$ = "source and destination EMS regions have same handle and overlap"\r
256     CASE &H98: Msg$ = "memory source or destination type undefined"\r
257     CASE &H9A: Msg$ = "specified alternate map register or DMA register set not supported"\r
258     CASE &H9B: Msg$ = "all alternate map register or DMA register sets currently allocated"\r
259     CASE &H9C: Msg$ = "alternate map register or DMA register sets not supported"\r
260     CASE &H9D: Msg$ = "undefined or unallocated alternate map register or DMA register set"\r
261     CASE &H9E: Msg$ = "dedicated DMA channels not supported"\r
262     CASE &H9F: Msg$ = "specified dedicated DMA channel not supported"\r
263     CASE &HA0: Msg$ = "no such handle name"\r
264     CASE &HA1: Msg$ = "a handle found had no name, or duplicate handle name"\r
265     CASE &HA2: Msg$ = "attempted to wrap around 1M conventional address space"\r
266     CASE &HA3: Msg$ = "source array corrupted"\r
267     CASE &HA4: Msg$ = "operating system denied access"\r
268     CASE ELSE: Msg$ = HEX$(EMS.Error) '"undefined error"\r
269   END SELECT\r
270 \r
271   EMS.ErrorMsg$ = Msg$\r
272 \r
273 END FUNCTION\r
274 \r
275 SUB EMS.ExchMem (Length&, SrcHandle, SrcSegment, SrcOffset, DstHandle, DstSegment, DstOffset)\r
276 \r
277   'Exhanges memory from EMS or base memory to EMS or base memory, where:\r
278   '\r
279   'Length&    = Length of memory to exchange in bytes\r
280   'SrcHandle  = EMS handle of source memory (use 0 if source is base memory)\r
281   'SrcSegment = Segment of source memory (or page number if source is EMS)\r
282   'SrcOffset  = Offset of source memory\r
283   'DstHandle  = EMS handle of destination memory (use 0 if destination is base memory)\r
284   'DstSegment = Segment of destination memory (or page number if destination is EMS)\r
285   'DstOffset  = Offset of destination memory\r
286 \r
287   'Determine the source and destination memory types by checking the handles\r
288   IF SrcHandle = 0 THEN SrcType$ = CHR$(0) ELSE SrcType$ = CHR$(1)\r
289   IF DstHandle = 0 THEN DstType$ = CHR$(0) ELSE DstType$ = CHR$(1)\r
290 \r
291   'Create a buffer containing the copy information\r
292   ExchInfo$ = MKL$(Length&) + SrcType$ + MKI$(SrcHandle) + MKI$(SrcOffset) + MKI$(SrcSegment) + DstType$ + MKI$(DstHandle) + MKI$(DstOffset) + MKI$(DstSegment)\r
293 \r
294   Regs.ax = &H5701                           'Exchange the memory region\r
295   Regs.ds = VARSEG(ExchInfo$)                'described in the buffer\r
296   Regs.si = SADD(ExchInfo$)\r
297   InterruptX &H67, Regs, Regs\r
298   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
299 \r
300 END SUB\r
301 \r
302 FUNCTION EMS.FreeHandles\r
303 \r
304   'Returns the number of free (available) EMS handles.\r
305 \r
306   Regs.ax = &H4B00                             'Get the # of handles in use\r
307   InterruptX &H67, Regs, Regs\r
308   UsedHandles = Regs.bx\r
309 \r
310   Regs.ax = &H5402                             'Get the total # of handles\r
311   InterruptX &H67, Regs, Regs\r
312   EMS.Error = (Regs.ax AND &HFF00&) \ &H100    'Store the status code\r
313   TotalHandles = Regs.bx\r
314 \r
315   EMS.FreeHandles = TotalHandles - UsedHandles 'Subtract to get the # of free handles\r
316 \r
317 END FUNCTION\r
318 \r
319 FUNCTION EMS.FreePages\r
320 \r
321   'Returns the number of free (available) EMS pages\r
322   '(Multiply by 16 to get the amount free EMS in KB.)\r
323 \r
324   Regs.ax = &H4200                           'Get the # of free pages\r
325   InterruptX &H67, Regs, Regs\r
326   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
327   EMS.FreePages = Regs.bx\r
328 \r
329 END FUNCTION\r
330 \r
331 FUNCTION EMS.Init\r
332 \r
333   'Returns true (-1) if an EMM is installed\r
334   'or false (0) if an EMM is not installed.\r
335 \r
336   Regs.ax = &H3567                        'Get the interrupt vector for int 67h\r
337   InterruptX &H21, Regs, Regs\r
338   DEF SEG = Regs.es                       'Point to the interrupt segment\r
339   FOR x = 10 TO 17                        'Store the 8 bytes at ES:0A in EMM$\r
340     EMM$ = EMM$ + CHR$(PEEK(x))\r
341   NEXT\r
342   IF EMM$ <> "EMMXXXX0" THEN\r
343     EMS.Init = 0              'EMM not installed\r
344   ELSE\r
345     EMS.Init = -1             'EMM installed\r
346   END IF\r
347 \r
348 END FUNCTION\r
349 \r
350 SUB EMS.MapPage (Physical, Logical, Handle)\r
351 \r
352   'Maps the logical EMS page [Logical] (allocated to the handle [Handle])\r
353   'to the physical page [Physical] in the EMS page frame.\r
354 \r
355   Regs.ax = &H4400 + Physical                'Map the logical page [Logical]\r
356   Regs.bx = Logical                          'to the physical page [Physical]\r
357   Regs.dx = Handle\r
358   InterruptX &H67, Regs, Regs\r
359   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
360 \r
361 END SUB\r
362 \r
363 SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
364 \r
365   'Maps up to 4 logical EMS pages to physical pages in the page frame, where:\r
366   '\r
367   'PhysicalStart = Physical page first logical page is mapped to\r
368   'LogicalStart  = First logical page to map\r
369   'NumPages      = Number of pages to map (1 to 4)\r
370   'Handle        = EMS handle logical pages are allocated to\r
371 \r
372   'Create a buffer containing the page information\r
373   FOR x = 0 TO NumPages - 1\r
374     MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)\r
375   NEXT\r
376 \r
377   Regs.ax = &H5000                           'Map the pages in the buffer\r
378   Regs.cx = NumPages                         'to the pageframe\r
379   Regs.dx = Handle\r
380   Regs.ds = VARSEG(MapInfo$)\r
381   Regs.si = SADD(MapInfo$)\r
382   InterruptX &H67, Regs, Regs\r
383   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
384 \r
385 END SUB\r
386 \r
387 FUNCTION EMS.PageFrame\r
388 \r
389   'Returns the segment of the EMS page frame\r
390 \r
391   Regs.ax = &H4100                           'Get the segment of the page frame\r
392   InterruptX &H67, Regs, Regs\r
393   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Save the status code\r
394   EMS.PageFrame = Regs.bx\r
395 \r
396 END FUNCTION\r
397 \r
398 FUNCTION EMS.TotalPages\r
399 \r
400   'Returns the total number of EMS pages\r
401   '(Multiply by 16 to get the total amount of EMS in KB.)\r
402 \r
403   Regs.ax = &H4200                           'Get the # of total pages\r
404   InterruptX &H67, Regs, Regs\r
405   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Store the status code\r
406   EMS.TotalPages = Regs.dx\r
407 \r
408 END FUNCTION\r
409 \r
410 FUNCTION EMS.Version$\r
411 \r
412   'Returns a string containing the EMM version.\r
413   '(Must be "4.0" or greater to use our routines.)\r
414 \r
415   Regs.ax = &H4600                           'Get the EMM version\r
416   InterruptX &H67, Regs, Regs\r
417   EMS.Error = (Regs.ax AND &HFF00&) \ &H100  'Save the status code\r
418 \r
419   Version = Regs.ax AND &HFF                 'Split the version number into\r
420   Major = (Version AND &HF0) \ &H10          'its major and minor counterparts\r
421   Minor = Version AND &HF\r
422   EMS.Version$ = LTRIM$(STR$(Major)) + "." + LTRIM$(STR$(Minor))\r
423 \r
424 END FUNCTION\r
425 \r