File: common\memory.c
1 #include <string.h>
2 #include <limits.h>
3 #include <malloc.h>
4
5 #if (!defined(XFRACT) && !defined(WINFRACT))
6 #include <io.h>
7 #endif
8
9 #ifndef USE_VARARGS
10 #include <stdarg.h>
11 #else
12 #include <varargs.h> 13 #endif
14
15 #include <ctype.h>
16
17 #include "port.h"
18 #include "prototyp.h"
19
20
21 /* Memory allocation routines. */
22
23 #if 1
24 /* For extra seg memory: */
25 #define EXTRA_RESERVE 4096L /* amount of extra mem we will leave avail. */
26 /* For far memory: */
27 #define FAR_RESERVE 8192L /* amount of far mem we will leave avail. */
28 /* For expanded memory: */
29 #define EXPWRITELEN 16384L /* max # bytes transferred to/from expanded mem at once */
30 /* For extended memory: */
31 #define XMMWRITELEN 8192L /* max # bytes transferred to/from extended mem at once */
32 /* For disk memory: */
33 #define DISKWRITELEN 2048L /* max # bytes transferred to/from disk mem at once */
34
35 BYTE far *charbuf = NULL;
36 int numEXThandles;
37 long ext_xfer_size;
38 U16 start_avail_extra = 0;
39 #endif
40
41 #define MAXHANDLES 256 /* arbitrary #, suitably big */
42 char memfile[] = "handle.$$$";
43 int numTOTALhandles;
44
45 #if (!defined(XFRACT) && !defined(WINFRACT))
46 char memstr[6][9] = {"nowhere", "extraseg", "far", "expanded",
47 "extended", "disk"};
48 #endif
49
50 #if (defined(XFRACT) || defined(WINFRACT))
51 char memstr[3][9] = {{"nowhere"}, {"far"}, {"disk"}}; 52 #endif
53
54 struct nowhere {
55 enum stored_at_values stored_at; /* first 2 entries must be the same */
56 long size; /* for each of these data structures */
57 };
58
59 struct farmem {
60 enum stored_at_values stored_at;
61 long size;
62 BYTE far *farmemory;
63 };
64
65 struct disk {
66 enum stored_at_values stored_at;
67 long size;
68 FILE *file;
69 };
70
71 #if (!defined(XFRACT) && !defined(WINFRACT))
72 struct extra {
73 enum stored_at_values stored_at;
74 long size;
75 BYTE far *extramemory;
76 };
77
78 struct expanded {
79 enum stored_at_values stored_at;
80 long size;
81 int oldexppage;
82 int mempages;
83 int emmhandle;
84 BYTE far *expmemory;
85 };
86
87 struct extended {
88 enum stored_at_values stored_at;
89 long size;
90 int mempages;
91 int xmmhandle;
92 };
93 #endif
94
95 union mem {
96 struct nowhere Nowhere;
97 struct farmem Farmem;
98 struct disk Disk;
99 #if (!defined(XFRACT) && !defined(WINFRACT))
100 struct extra Extra;
101 struct expanded Expanded;
102 struct extended Extended;
103 #endif
104 };
105
106 union mem far handletable[MAXHANDLES];
107
108 /* Routines in this module */
109 #ifndef XFRACT
110 U32 GetDiskSpace(void);
111 static void _fastcall near exp_seek(U16 handle, int page); /* expanded mem seek */
112 #endif
113 static int _fastcall near CheckDiskSpace(long howmuch);
114 static int check_for_mem(int stored_at, long howmuch);
115 static U16 next_handle(void);
116 static int CheckBounds (long start, long length, U16 handle);
117 static void WhichDiskError(int);
118 static void DisplayError(int stored_at, long howmuch);
119
120 /* Routines in this module, visible to outside routines */
121
122 void DisplayMemory (void);
123 void DisplayHandle (U16 handle);
124 int MemoryType (U16 handle);
125 void InitMemory (void);
126 void ExitCheck (void);
127 U16 MemoryAlloc(U16 size, long count, int stored_at);
128 void MemoryRelease(U16 handle);
129 int MoveToMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle);
130 int MoveFromMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle);
131 int SetMemory(int value,U16 size,long count,long offset,U16 handle);
132
133 /* Memory handling support routines */
134
135 #ifndef XFRACT
136 U32 GetDiskSpace(void)
137 {
138 /* Returns the number of bytes available on the current disk drive. */
139 U32 available = 0;
140 union REGS regs;
141
142 regs.h.ah = 0x36; /* Function 36, Get Disk Free Space */
143 regs.h.dl = 0; /* Check the default drive */
144 intdos(®s, ®s);
145 if (regs.x.ax != 0xFFFF) /* Drive is valid */
146 available = (U32)regs.x.ax * regs.x.bx * regs.x.cx;
147 return (available);
148 }
149 #endif
150
151 static int _fastcall near CheckDiskSpace(long howmuch)
152 {
153 int EnoughSpace = FALSE;
154 #ifndef XFRACT
155 U32 available;
156
157 available = GetDiskSpace();
158 if (available > (U32)howmuch)
159 EnoughSpace = TRUE;
160 #endif
161 #ifdef XFRACT
164 #endif
165 return(EnoughSpace);
166 }
167
168 static void WhichDiskError(int I_O)
169 { /* Set I_O == 1 after a file create, I_O == 2 after a file set value */
170 /* Set I_O == 3 after a file write, I_O == 4 after a file read */
171 #if (!defined(XFRACT) && !defined(WINFRACT))
172 char buf[MSGLEN];
173 char nmsg[MSGLEN];
174 static FCODE fmsg1[] = {"Disk file creation error"};
175 static FCODE fmsg2[] = {"Disk file set error"};
176 static FCODE fmsg3[] = {"Disk file write error"};
177 static FCODE fmsg4[] = {"Disk file read error"};
178
179 /* The following and the associated sprintf eat up 432 bytes of near memory.
180 Only marginally useful for debugging purposes.
181 static FCODE fmsg1[] = {"Create file error %d: %s"};
182 static FCODE fmsg2[] = {"Set file error %d: %s"};
183 static FCODE fmsg3[] = {"Write file error %d: %s"};
184 static FCODE fmsg4[] = {"Read file error %d: %s"};
185 */
186 switch (I_O) {
187 default:
188 case 1:
189 far_strcpy(nmsg,fmsg1);
190 break;
191 case 2:
192 far_strcpy(nmsg,fmsg2);
193 break;
194 case 3:
195 far_strcpy(nmsg,fmsg3);
196 break;
197 case 4:
198 far_strcpy(nmsg,fmsg4);
199 break;
200 }
201 sprintf(buf,nmsg);
202 /*
203 sprintf(buf,nmsg,errno,strerror(errno));
204 */
205 if (debugflag == 10000)
206 if(stopmsg(6,(char far *)buf) == -1)
207 goodbye(); /* bailout if ESC */
208 #endif
209 }
210
211 #if (!defined(XFRACT) && !defined(WINFRACT))
212 static void _fastcall near exp_seek(U16 handle, int page) /* expanded mem seek */
213 {
214 static U16 lasthandle = 0;
215 if (page != handletable[handle].Expanded.oldexppage || page == 0 ||
216 lasthandle != handle) {
217 /* time to get a new page? */
218 handletable[handle].Expanded.oldexppage = page;
219 lasthandle = handle;
220 emmgetpage(page, handletable[handle].Expanded.emmhandle);
221 }
222 }
223 #endif
224
225 int MemoryType (U16 handle)
226 {
227 return (handletable[handle].Nowhere.stored_at);
228 }
229
230 static void DisplayError(int stored_at, long howmuch)
231 {
232 /* This routine is used to display an error message when the requested */
233 /* memory type cannot be allocated due to insufficient memory, AND there */
234 /* is also insufficient disk space to use as memory. */
235
236 char buf[MSGLEN*2];
237 char nmsg[MSGLEN*2];
238 static FCODE fmsg[] = {"Allocating %ld Bytes of %s memory failed.\nAlternate disk space is also insufficient. Goodbye"};
239 far_strcpy(nmsg,fmsg);
240 sprintf(buf,nmsg,howmuch,memstr[stored_at]);
241 stopmsg(0,(char far *)buf);
242 }
243
244 static int check_for_mem(int stored_at, long howmuch)
245 {
246 /* This function returns an adjusted stored_at value. */
247 /* This is where the memory requested can be allocated. */
248
249 #if (!defined(XFRACT) && !defined(WINFRACT))
250 long usedmem, totalmem;
251 long longtmp;
252 int counter;
253 #endif
254 long maxmem;
255 BYTE far *temp;
256 int use_this_type;
257
258 use_this_type = NOWHERE;
259 maxmem = (long)USHRT_MAX; /* limit EXTRA and FARMEM to 64K */
260 /* limit EXPANDED and EXTENDED to 64K blocks */
261
262 if (debugflag == 420)
263 stored_at = DISK;
264 if (debugflag == 422)
265 stored_at = EXTENDED;
266
267 switch (stored_at)
268 {
269 #if (!defined(XFRACT) && !defined(WINFRACT))
270 case EXTRA: /* check_for_mem */
271 usedmem = 0L;
272 for(counter = 0; counter < MAXHANDLES; counter++)
273 if (handletable[counter].Nowhere.stored_at == EXTRA)
274 usedmem += handletable[counter].Extra.size;
275 if ((maxmem - usedmem) > howmuch) {
276 use_this_type = EXTRA;
277 break;
278 }
279 /* failed, fall through and try far memory */
280 #endif
281
282 case FARMEM: /* check_for_mem */
283 if (maxmem > howmuch) {
284 temp = (BYTE far *)farmemalloc(howmuch + FAR_RESERVE);
285 if (temp != NULL) { /* minimum free space + requested amount */
286 farmemfree(temp);
287 use_this_type = FARMEM;
288 break;
289 }
290 }
291
292 #if (!defined(XFRACT) && !defined(WINFRACT))
293 /* Failed, fall through and try expanded memory */
294 case EXPANDED: /* check_for_mem */
295 totalmem = (howmuch + 16383) >> 14; /* # of 16 KB blocks */
296 if ((totalmem < (long)USHRT_MAX) && (emmquery() != NULL)) {
297 maxmem = emmgetfree(); /* reuse maxmem, so may not be good below */
298 if (maxmem > totalmem) {
299 use_this_type = EXPANDED;
300 break;
301 }
302 }
303 /* Failed, fall through and try extended memory */
304
305 case EXTENDED: /* check_for_mem */
306 longtmp = (howmuch + 1023) >> 10; /* # of 1 KB blocks */
307 if (longtmp <= 0)
308 longtmp = 1;
309 if (xmmquery() != 0)
310 if ((longtmp < (long)USHRT_MAX) && ((long)xmmfree() > longtmp)) {
311 use_this_type = EXTENDED;
312 break;
313 }
314 /* failed, fall through and try disk memory */
315 #endif
316
317 case DISK: /* check_for_mem */
318 default: /* just in case a nonsense number gets used */
319 if (CheckDiskSpace(howmuch)) {
320 use_this_type = DISK;
321 break;
322 }
323 /* failed, fall through, no memory available */
324
325 case NOWHERE: /* check_for_mem */
326 use_this_type = NOWHERE;
327 break;
328
329 } /* end of switch */
330
331 return(use_this_type);
332 }
333
334 static U16 next_handle()
335 {
336 U16 counter = 1; /* don't use handle 0 */
337
338 while(handletable[counter].Nowhere.stored_at != NOWHERE &&
339 counter < MAXHANDLES)
340 counter++;
341 return (counter);
342 }
343
344 static int CheckBounds (long start, long length, U16 handle)
345 {
346 if(handletable[handle].Nowhere.size - start - length < 0)
347 {
348 static FCODE msg[] = {"Memory reference out of bounds."};
349 stopmsg(20,msg);
350 DisplayHandle(handle);
351 return (1);
352 }
353 if(length > (long)USHRT_MAX)
354 {
355 static FCODE msg[] = {"Tried to move > 65,535 bytes."};
356 stopmsg(20,msg);
357 DisplayHandle(handle);
358 return (1);
359 }
360 if(handletable[handle].Nowhere.stored_at == DISK &&
361 (stackavail() <= DISKWRITELEN) )
362 {
363 static FCODE msg[] = {"Stack space insufficient for disk memory."};
364 stopmsg(20,msg);
365 DisplayHandle(handle);
366 return (1);
367 }
368 if(length <= 0)
369 {
370 static FCODE msg[] = {"Zero or negative length."};
371 stopmsg(20,msg);
372 DisplayHandle(handle);
373 return (1);
374 }
375 if(start < 0)
376 {
377 static FCODE msg[] = {"Negative offset."};
378 stopmsg(20,msg);
379 DisplayHandle(handle);
380 return (1);
381 }
382 return (0);
383 }
384
385 void DisplayMemory (void)
386 {
387 #if (!defined(XFRACT) && !defined(WINFRACT))
388 long tmpfar;
389 U32 tmpdisk;
390 char buf[MSGLEN];
391 char nmsg[MSGLEN];
392 /* #ifdef XFRACT static FCODE fmsg[] = {"far=%ld, disk=%lu"}; */
393 static FCODE fmsg[] = {"extra=%ld, far=%ld, expanded=%ld,\nextended=%ld, disk=%lu"};
394 long tmpextra, tmpexp, tmpext;
395
396 tmpextra = USHRT_MAX - start_avail_extra;
397 if (emmquery() != NULL)
398 tmpexp = (long)emmgetfree() * 16L * 1024L;
399 else
400 tmpexp = 0;
401 if (xmmquery() != 0)
402 tmpext = (long)xmmfree() * 1024L;
403 else
404 tmpext = 0;
405 tmpdisk = GetDiskSpace(); /* fix this for XFRACT ????? */
406
407 tmpfar = fr_farfree();
408 far_strcpy(nmsg,fmsg);
409 sprintf(buf,nmsg,tmpextra,tmpfar,tmpexp,tmpext,tmpdisk);
410 stopmsg(20,(char far *)buf);
411 #endif
412 }
413
414 void DisplayHandle (U16 handle)
415 {
416 char buf[MSGLEN];
417 char nmsg[MSGLEN];
418 static FCODE fmsg[] = {"Handle %u, type %s, size %li"};
419
420 far_strcpy(nmsg,fmsg);
421 sprintf(buf,nmsg,handle,memstr[handletable[handle].Nowhere.stored_at],
422 handletable[handle].Nowhere.size);
423 if(stopmsg(6,(char far *)buf) == -1)
424 goodbye(); /* bailout if ESC, it's messy, but should work */
425 }
426
427 void InitMemory (void)
428 {
429 int counter;
430 #if (!defined(XFRACT) && !defined(WINFRACT))
431 long longtmp;
432 #endif
433
434 numTOTALhandles = 0;
435 for (counter = 0; counter < MAXHANDLES; counter++) {
436 handletable[counter].Nowhere.stored_at = NOWHERE;
437 handletable[counter].Nowhere.size = 0;
438 }
439 #if (!defined(XFRACT) && !defined(WINFRACT))
440 numEXThandles = 0;
441 longtmp = fr_farfree();
442 ext_xfer_size = XMMWRITELEN; /* 8192 */
443 if (longtmp < (long)XMMWRITELEN * 8)
444 ext_xfer_size = XMMWRITELEN / 2; /* 4096 */
445 if (longtmp < (long)XMMWRITELEN)
446 ext_xfer_size = XMMWRITELEN / 8; /* 1024, won't work, try anyway */
447 #endif
448 }
449
450 void ExitCheck (void)
451 {
452 U16 i;
453 if(/*charbuf != NULL ||*/ numEXThandles != 0 || numTOTALhandles != 0) {
454 static FCODE msg[] = {"Error - not all memory released, I'll get it."};
455 stopmsg(0,msg);
456 for (i = 1; i < MAXHANDLES; i++)
457 if (handletable[i].Nowhere.stored_at != NOWHERE) {
458 char buf[MSGLEN];
459 char nmsg[MSGLEN];
460 static FCODE fmsg[] = {"Memory type %s still allocated. Handle = %i."};
461 far_strcpy(nmsg,fmsg);
462 sprintf(buf,nmsg,memstr[handletable[i].Nowhere.stored_at],i);
463 stopmsg(0,(char far *)buf);
464 MemoryRelease(i);
465 }
466 }
467 }
468
469 /* * * * * */
470 /* Memory handling routines */
471
472 U16 MemoryAlloc(U16 size, long count, int stored_at)
473 {
474 /* Returns handle number if successful, 0 or NULL if failure */
475 U16 handle = 0;
476 int success, use_this_type;
477 long toallocate;
478
479 #if (!defined(XFRACT) && !defined(WINFRACT))
480 BYTE far *temp;
481 long longtmp;
482 int mempages = 0;
483 struct XMM_Move MoveStruct;
484 #endif
485
486 success = FALSE;
487 toallocate = count * size;
488 if (toallocate <= 0) /* we failed, can't allocate > 2,147,483,647 */
489 return((U16)success); /* or it wraps around to negative */
490
491 /* check structure for requested memory type (add em up) to see if
492 sufficient amount is available to grant request */
493
494 use_this_type = check_for_mem(stored_at, toallocate);
495 if (use_this_type == NOWHERE) {
496 DisplayError(stored_at, toallocate);
497 goodbye();
498 }
499
500 /* get next available handle */
501
502 handle = next_handle();
503
504 if (handle >= MAXHANDLES || handle <= 0) {
505 DisplayHandle(handle);
506 return((U16)success);
507 /* Oops, do something about this! ????? */
508 }
509
510 /* attempt to allocate requested memory type */
511 switch (use_this_type)
512 {
513 default:
514 case NOWHERE: /* MemoryAlloc */
515 use_this_type = NOWHERE; /* in case nonsense value is passed */
516 break;
517
518 #if (!defined(XFRACT) && !defined(WINFRACT))
519 case EXTRA: /* MemoryAlloc */
520 handletable[handle].Extra.size = toallocate;
521 handletable[handle].Extra.stored_at = EXTRA;
522 handletable[handle].Extra.extramemory = (BYTE far *)MK_FP(extraseg,start_avail_extra);
523 start_avail_extra += (U16)toallocate;
524 numTOTALhandles++;
525 success = TRUE;
526 break;
527 #endif
528
529 case FARMEM: /* MemoryAlloc */
530 /* Availability of far memory checked in check_for_mem() */
531 handletable[handle].Farmem.farmemory = (BYTE far *)farmemalloc(toallocate);
532 handletable[handle].Farmem.size = toallocate;
533 handletable[handle].Farmem.stored_at = FARMEM;
534 numTOTALhandles++;
535 success = TRUE;
536 break;
537
538 #if (!defined(XFRACT) && !defined(WINFRACT))
539 case EXPANDED: /* MemoryAlloc */
540 mempages = (int)((toallocate + 16383) >> 14);
541 if (emmquery() != NULL) {
542 handletable[handle].Expanded.mempages = mempages;
543 handletable[handle].Expanded.expmemory = emmquery();
544 if ((handletable[handle].Expanded.emmhandle = emmallocate(mempages)) != 0) {
545 handletable[handle].Expanded.oldexppage = 0;
546 handletable[handle].Expanded.size = toallocate;
547 handletable[handle].Expanded.stored_at = EXPANDED;
548 numTOTALhandles++;
549 success = TRUE;
550 break;
551 }
552 }
553
554 case EXTENDED: /* MemoryAlloc */
555 /* This is ugly! Need far memory to use extended memory. */
556 if (charbuf == NULL) { /* first time through, allocate buffer */
557 temp = (BYTE far *)farmemalloc((long)ext_xfer_size + FAR_RESERVE);
558 if (temp != NULL) /* minimum free space + requested amount */
559 {
560 farmemfree(temp);
561 charbuf = (BYTE far *)farmemalloc((long)ext_xfer_size);
562 }
563 else
564 goto dodisk;
565 }
566 if (toallocate < ext_xfer_size)
567 longtmp = (ext_xfer_size + 1023) >> 10;
568 else
569 longtmp = (toallocate + 1023) >> 10;
570 if (xmmquery() != 0
571 && (handletable[handle].Extended.xmmhandle = xmmallocate((U16)(longtmp))) != 0)
572 {
573 longtmp /= (ext_xfer_size >> 10);
574 handletable[handle].Extended.mempages = (int)longtmp;
575 far_memset(charbuf, 0, (int)ext_xfer_size); /* zero the buffer */
576 MoveStruct.SourceHandle = 0; /* Source is in conventional memory */
577 MoveStruct.SourceOffset = (U32)charbuf;
578 MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle;
579 MoveStruct.DestOffset = 0;
580 MoveStruct.Length = (long)ext_xfer_size;
581 while (--longtmp >= 0) {
582 if ((success = xmmmoveextended(&MoveStruct)) == 0) break;
583 MoveStruct.DestOffset += ext_xfer_size;
584 }
585 if (success) {
586 /* put in structure */
587 success = TRUE;
588 handletable[handle].Extended.size = toallocate;
589 handletable[handle].Extended.stored_at = EXTENDED;
590 numTOTALhandles++;
591 numEXThandles++;
592 break;
593 }
594 xmmdeallocate(handletable[handle].Extended.xmmhandle); /* Clear the memory */
595 handletable[handle].Extended.xmmhandle = 0; /* Signal same */
596 }
597 /* need to fall through and use disk memory, or will crash fractint */
598 dodisk:
599 #endif
600 case DISK: /* MemoryAlloc */
601 memfile[9] = (char)(handle % 10 + (int)'0');
602 memfile[8] = (char)((handle % 100) / 10 + (int)'0');
603 memfile[7] = (char)((handle % 1000) / 100 + (int)'0');
604 if (disktarga)
605 handletable[handle].Disk.file = dir_fopen(workdir,light_name, "a+b");
606 else
607 handletable[handle].Disk.file = dir_fopen(tempdir,memfile, "w+b");
608 rewind(handletable[handle].Disk.file);
609 if (fseek(handletable[handle].Disk.file,toallocate,SEEK_SET) != 0)
610 handletable[handle].Disk.file = NULL;
611 if (handletable[handle].Disk.file == NULL) {
612 handletable[handle].Disk.stored_at = NOWHERE;
613 use_this_type = NOWHERE;
614 WhichDiskError(1);
615 DisplayMemory();
616 buzzer(3);
617 break;
618 }
619 numTOTALhandles++;
620 success = TRUE;
621 fclose(handletable[handle].Disk.file); /* so clusters aren't lost if we crash while running */
622 if (disktarga)
623 handletable[handle].Disk.file = dir_fopen(workdir,light_name, "r+b");
624 else
625 handletable[handle].Disk.file = dir_fopen(tempdir,memfile,"r+b"); /* reopen */
626 rewind(handletable[handle].Disk.file);
627 handletable[handle].Disk.size = toallocate;
628 handletable[handle].Disk.stored_at = DISK;
629 use_this_type = DISK;
630 break;
631 } /* end of switch */
632
633 if (stored_at != use_this_type && debugflag == 10000) {
634 char buf[MSGLEN];
635 char nmsg[MSGLEN];
636 static FCODE fmsg[] = {"Asked for %s, allocated %lu bytes of %s, handle = %u."};
637 far_strcpy(nmsg,fmsg);
638 sprintf(buf,nmsg,memstr[stored_at],toallocate,memstr[use_this_type],handle);
639 stopmsg(20,(char far *)buf);
640 DisplayMemory();
641 }
642
643 if (success)
644 return (handle);
645 else /* return 0 if failure */
646 return 0;
647 }
648
649 void MemoryRelease(U16 handle)
650 {
651 switch(handletable[handle].Nowhere.stored_at)
652 {
653 case NOWHERE: /* MemoryRelease */
654 break;
655
656 #if (!defined(XFRACT) && !defined(WINFRACT))
657 case EXTRA: /* MemoryRelease */
658 /* Deallocate in the reverse order of allocation. */
659 start_avail_extra -= (U16)handletable[handle].Extra.size;
660 handletable[handle].Extra.size = 0;
661 handletable[handle].Extra.stored_at = NOWHERE;
662 handletable[handle].Extra.extramemory = NULL;
663 numTOTALhandles--;
664 break;
665 #endif
666
667 case FARMEM: /* MemoryRelease */
668 farmemfree(handletable[handle].Farmem.farmemory);
669 handletable[handle].Farmem.farmemory = NULL;
670 handletable[handle].Farmem.size = 0;
671 handletable[handle].Farmem.stored_at = NOWHERE;
672 numTOTALhandles--;
673 break;
674
675 #if (!defined(XFRACT) && !defined(WINFRACT))
676 case EXPANDED: /* MemoryRelease */
677 emmdeallocate(handletable[handle].Expanded.emmhandle);
678 handletable[handle].Expanded.emmhandle = 0;
679 handletable[handle].Expanded.size = 0;
680 handletable[handle].Expanded.stored_at = NOWHERE;
681 numTOTALhandles--;
682 break;
683
684 case EXTENDED: /* MemoryRelease */
685 /* far memory allocated for this must be released */
686 numEXThandles--;
687 xmmdeallocate(handletable[handle].Extended.xmmhandle);
688 if (numEXThandles == 0) {
689 farmemfree(charbuf);
690 charbuf = NULL;
691 }
692 handletable[handle].Extended.xmmhandle = 0;
693 handletable[handle].Extended.size = 0;
694 handletable[handle].Extended.stored_at = NOWHERE;
695 numTOTALhandles--;
696 break;
697 #endif
698
699 case DISK: /* MemoryRelease */
700 memfile[9] = (char)(handle % 10 + (int)'0');
701 memfile[8] = (char)((handle % 100) / 10 + (int)'0');
702 memfile[7] = (char)((handle % 1000) / 100 + (int)'0');
703 fclose(handletable[handle].Disk.file);
704 dir_remove(tempdir,memfile);
705 handletable[handle].Disk.file = NULL;
706 handletable[handle].Disk.size = 0;
707 handletable[handle].Disk.stored_at = NOWHERE;
708 numTOTALhandles--;
709 break;
710 } /* end of switch */
711 }
712
713 int MoveToMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle)
714 { /* buffer is a pointer to local memory */
715 /* Always start moving from the beginning of buffer */
716 /* offset is the number of units from the start of the allocated "Memory" */
717 /* to start moving the contents of buffer to */
718 /* size is the size of the unit, count is the number of units to move */
719 /* Returns TRUE if successful, FALSE if failure */
720 #if (!defined(XFRACT) && !defined(WINFRACT))
721 int currpage;
722 long tmplength;
723 struct XMM_Move MoveStruct;
724 #endif
725 BYTE diskbuf[DISKWRITELEN];
726 long start; /* offset to first location to move to */
727 long tomove; /* number of bytes to move */
728 U16 numwritten, i;
729 int success;
730
731 success = FALSE;
732 start = (long)offset * size;
733 tomove = (long)count * size;
734 if (debugflag == 10000)
735 if (CheckBounds(start, tomove, handle))
736 return(success); /* out of bounds, don't do it */
737
738 switch(handletable[handle].Nowhere.stored_at)
739 {
740 case NOWHERE: /* MoveToMemory */
741 DisplayHandle(handle);
742 break;
743
744 #if (!defined(XFRACT) && !defined(WINFRACT))
745 case EXTRA: /* MoveToMemory */
746 far_memcpy(handletable[handle].Extra.extramemory+start, buffer, (U16)tomove);
747 success = TRUE; /* No way to gauge success or failure */
748 break;
749 #endif
750
751 case FARMEM: /* MoveToMemory */
752 for(i=0;i<size;i++) {
753 far_memcpy(handletable[handle].Farmem.farmemory+start, buffer, (U16)count);
754 start += count;
755 buffer += count;
756 }
757 success = TRUE; /* No way to gauge success or failure */
758 break;
759
760 #if (!defined(XFRACT) && !defined(WINFRACT))
761 case EXPANDED: /* MoveToMemory */
762 currpage = (int)(start / EXPWRITELEN);
763 exp_seek(handle, currpage);
764 /* Not on a page boundary, move data up to next page boundary */
765 tmplength = (currpage + 1) * EXPWRITELEN - start;
766 start -= (currpage * EXPWRITELEN);
767 if (tmplength > tomove)
768 tmplength = tomove;
769 far_memcpy(handletable[handle].Expanded.expmemory+start, buffer, (U16)tmplength);
770 buffer += tmplength;
771 tomove -= tmplength;
772 /* At a page boundary, move until less than a page left */
773 while (tomove >= EXPWRITELEN)
774 {
775 currpage++;
776 exp_seek(handle, currpage);
777 far_memcpy(handletable[handle].Expanded.expmemory, buffer, (U16)EXPWRITELEN);
778 buffer += EXPWRITELEN;
779 tomove -= EXPWRITELEN;
780 }
781 /* Less than a page left, move it */
782 if (tomove > 0) /* still some left */
783 {
784 currpage++;
785 exp_seek(handle, currpage);
786 far_memcpy(handletable[handle].Expanded.expmemory, buffer, (U16)tomove);
787 }
788 exp_seek(handle, 0); /* flush the last page out of the page frame */
789 success = TRUE; /* No way to gauge success or failure */
790 break;
791
792 case EXTENDED: /* MoveToMemory */
793 MoveStruct.Length = ext_xfer_size;
794 MoveStruct.SourceHandle = 0; /* Source is conventional memory */
795 MoveStruct.SourceOffset = (U32)charbuf;
796 MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle;
797 MoveStruct.DestOffset = (U32)start;
798 while (tomove > ext_xfer_size)
799 {
800 far_memcpy(charbuf,buffer,(int)ext_xfer_size);
801 xmmmoveextended(&MoveStruct);
802 start += ext_xfer_size;
803 tomove -= ext_xfer_size;
804 buffer += ext_xfer_size;
805 MoveStruct.DestOffset = (U32)(start);
806 }
807 far_memcpy(charbuf,buffer,(U16)tomove);
808 MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */
809 success = xmmmoveextended(&MoveStruct);
810 break;
811 #endif
812
813 case DISK: /* MoveToMemory */
814 rewind(handletable[handle].Disk.file);
815 fseek(handletable[handle].Disk.file,start,SEEK_SET);
816 while (tomove > DISKWRITELEN)
817 {
818 far_memcpy(diskbuf,buffer,(U16)DISKWRITELEN);
819 numwritten = (U16)write1(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file);
820 if (numwritten != 1) {
821 WhichDiskError(3);
822 goto diskerror;
823 }
824 tomove -= DISKWRITELEN;
825 buffer += DISKWRITELEN;
826 }
827 far_memcpy(diskbuf,buffer,(U16)tomove);
828 numwritten = (U16)write1(diskbuf,(U16)tomove,1,handletable[handle].Disk.file);
829 if (numwritten != 1) {
830 WhichDiskError(3);
831 break;
832 }
833 success = TRUE;
834 diskerror:
835 break;
836 } /* end of switch */
837 if (!success && debugflag == 10000)
838 DisplayHandle(handle);
839 return (success);
840 }
841
842 int MoveFromMemory(BYTE far *buffer,U16 size,long count,long offset,U16 handle)
843 { /* buffer points is the location to move the data to */
844 /* offset is the number of units from the beginning of buffer to start moving */
845 /* size is the size of the unit, count is the number of units to move */
846 /* Returns TRUE if successful, FALSE if failure */
847 #if (!defined(XFRACT) && !defined(WINFRACT))
848 int currpage;
849 long tmplength;
850 struct XMM_Move MoveStruct;
851 #endif
852 BYTE diskbuf[DISKWRITELEN];
853 long start; /* first location to move */
854 long tomove; /* number of bytes to move */
855 U16 numread, i;
856 int success;
857
858 success = FALSE;
859 start = (long)offset * size;
860 tomove = (long)count * size;
861 if (debugflag == 10000)
862 if (CheckBounds(start, tomove, handle))
863 return(success); /* out of bounds, don't do it */
864
865 switch(handletable[handle].Nowhere.stored_at)
866 {
867 case NOWHERE: /* MoveFromMemory */
868 DisplayHandle(handle);
869 break;
870
871 #if (!defined(XFRACT) && !defined(WINFRACT))
872 case EXTRA: /* MoveFromMemory */
873 far_memcpy(buffer, handletable[handle].Extra.extramemory+start, (U16)tomove);
874 success = TRUE; /* No way to gauge success or failure */
875 break;
876 #endif
877
878 case FARMEM: /* MoveFromMemory */
879 for(i=0;i<size;i++) {
880 far_memcpy(buffer, handletable[handle].Farmem.farmemory+start, (U16)count);
881 start += count;
882 buffer += count;
883 }
884 success = TRUE; /* No way to gauge success or failure */
885 break;
886
887 #if (!defined(XFRACT) && !defined(WINFRACT))
888 case EXPANDED: /* MoveFromMemory */
889 currpage = (int)(start / EXPWRITELEN);
890 exp_seek(handle, currpage);
891 /* Not on a page boundary, move data up to next page boundary */
892 tmplength = (currpage + 1) * EXPWRITELEN - start;
893 start -= (currpage * EXPWRITELEN);
894 if (tmplength > tomove)
895 tmplength = tomove;
896 far_memcpy(buffer, handletable[handle].Expanded.expmemory+start, (U16)tmplength);
897 buffer += tmplength;
898 tomove -= tmplength;
899 /* At a page boundary, move until less than a page left */
900 while (tomove >= EXPWRITELEN)
901 {
902 currpage++;
903 exp_seek(handle, currpage);
904 far_memcpy(buffer, handletable[handle].Expanded.expmemory, (U16)EXPWRITELEN);
905 buffer += EXPWRITELEN;
906 tomove -= EXPWRITELEN;
907 }
908 /* Less than a page left, move it */
909 if (tomove > 0) /* still some left */
910 {
911 currpage++;
912 exp_seek(handle, currpage);
913 far_memcpy(buffer, handletable[handle].Expanded.expmemory, (U16)tomove);
914 }
915 exp_seek(handle, 0); /* flush the last page out of the page frame */
916 success = TRUE; /* No way to gauge success or failure */
917 break;
918
919 case EXTENDED: /* MoveFromMemory */
920 MoveStruct.Length = ext_xfer_size;
921 MoveStruct.SourceHandle = handletable[handle].Extended.xmmhandle;
922 MoveStruct.SourceOffset = (U32)start;
923 MoveStruct.DestHandle = 0; /* Destination is conventional memory */
924 MoveStruct.DestOffset = (U32)charbuf;
925 while (tomove > ext_xfer_size)
926 {
927 xmmmoveextended(&MoveStruct);
928 far_memcpy(buffer,charbuf,(int)ext_xfer_size);
929 buffer += ext_xfer_size;
930 tomove -= ext_xfer_size;
931 start += ext_xfer_size;
932 MoveStruct.SourceOffset = (U32)start;
933 }
934 MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */
935 success = xmmmoveextended(&MoveStruct);
936 far_memcpy(buffer,charbuf,(U16)tomove);
937 break;
938 #endif
939
940 case DISK: /* MoveFromMemory */
941 rewind(handletable[handle].Disk.file);
942 fseek(handletable[handle].Disk.file,start,SEEK_SET);
943 while (tomove > DISKWRITELEN)
944 {
945 numread = (U16)fread(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file);
946 if (numread != 1 && !feof(handletable[handle].Disk.file)) {
947 WhichDiskError(4);
948 goto diskerror;
949 }
950 far_memcpy(buffer,diskbuf,(U16)DISKWRITELEN);
951 tomove -= DISKWRITELEN;
952 buffer += DISKWRITELEN;
953 }
954 numread = (U16)fread(diskbuf,(U16)tomove,1,handletable[handle].Disk.file);
955 if (numread != 1 && !feof(handletable[handle].Disk.file)) {
956 WhichDiskError(4);
957 break;
958 }
959 far_memcpy(buffer,diskbuf,(U16)tomove);
960 success = TRUE;
961 diskerror:
962 break;
963 } /* end of switch */
964 if (!success && debugflag == 10000)
965 DisplayHandle(handle);
966 return (success);
967 }
968
969 int SetMemory(int value,U16 size,long count,long offset,U16 handle)
970 { /* value is the value to set memory to */
971 /* offset is the number of units from the start of allocated memory */
972 /* size is the size of the unit, count is the number of units to set */
973 /* Returns TRUE if successful, FALSE if failure */
974 #if (!defined(XFRACT) && !defined(WINFRACT))
975 int currpage;
976 long tmplength;
977 struct XMM_Move MoveStruct;
978 #endif
979 BYTE diskbuf[DISKWRITELEN];
980 long start; /* first location to set */
981 long tomove; /* number of bytes to set */
982 U16 numwritten, i;
983 int success;
984
985 success = FALSE;
986 start = (long)offset * size;
987 tomove = (long)count * size;
988 if (debugflag == 10000)
989 if (CheckBounds(start, tomove, handle))
990 return(success); /* out of bounds, don't do it */
991
992 switch(handletable[handle].Nowhere.stored_at)
993 {
994 case NOWHERE: /* SetMemory */
995 DisplayHandle(handle);
996 break;
997
998 #if (!defined(XFRACT) && !defined(WINFRACT))
999 case EXTRA: /* SetMemory */
1000 far_memset(handletable[handle].Extra.extramemory+start, value, (U16)tomove);
1001 success = TRUE; /* No way to gauge success or failure */
1002 break;
1003 #endif
1004
1005 case FARMEM: /* SetMemory */
1006 for(i=0;i<size;i++) {
1007 far_memset(handletable[handle].Farmem.farmemory+start, value, (U16)count);
1008 start += count;
1009 }
1010 success = TRUE; /* No way to gauge success or failure */
1011 break;
1012
1013 #if (!defined(XFRACT) && !defined(WINFRACT))
1014 case EXPANDED: /* SetMemory */
1015 currpage = (int)(start / EXPWRITELEN);
1016 exp_seek(handle, currpage);
1017 /* Not on a page boundary, move data up to next page boundary */
1018 tmplength = (currpage + 1) * EXPWRITELEN - start;
1019 start -= (currpage * EXPWRITELEN);
1020 if (tmplength > tomove)
1021 tmplength = tomove;
1022 far_memset(handletable[handle].Expanded.expmemory+start, value, (U16)tmplength);
1023 tomove -= tmplength;
1024 /* At a page boundary, move until less than a page left */
1025 while (tomove >= EXPWRITELEN)
1026 {
1027 currpage++;
1028 exp_seek(handle, currpage);
1029 far_memcpy(handletable[handle].Expanded.expmemory, &value, (U16)EXPWRITELEN);
1030 tomove -= EXPWRITELEN;
1031 }
1032 /* Less than a page left, move it */
1033 if (tomove > 0) /* still some left */
1034 {
1035 currpage++;
1036 exp_seek(handle, currpage);
1037 far_memcpy(handletable[handle].Expanded.expmemory, &value, (U16)tomove);
1038 }
1039 exp_seek(handle, 0); /* flush the last page out of the page frame */
1040 success = TRUE; /* No way to gauge success or failure */
1041 break;
1042
1043 case EXTENDED: /* SetMemory */
1044 MoveStruct.Length = ext_xfer_size;
1045 MoveStruct.SourceHandle = 0; /* Source is conventional memory */
1046 MoveStruct.SourceOffset = (U32)charbuf;
1047 MoveStruct.DestHandle = handletable[handle].Extended.xmmhandle;
1048 MoveStruct.DestOffset = (U32)start;
1049 far_memset(charbuf, value, (int)ext_xfer_size);
1050 while (tomove > ext_xfer_size)
1051 {
1052 xmmmoveextended(&MoveStruct);
1053 start += ext_xfer_size;
1054 tomove -= ext_xfer_size;
1055 MoveStruct.DestOffset = (U32)(start);
1056 }
1057 MoveStruct.Length = (tomove % 2) ? tomove + 1 : tomove; /* must be even */
1058 success = xmmmoveextended(&MoveStruct);
1059 break;
1060 #endif
1061
1062 case DISK: /* SetMemory */
1063 far_memset(diskbuf, value, (U16)DISKWRITELEN);
1064 rewind(handletable[handle].Disk.file);
1065 fseek(handletable[handle].Disk.file,start,SEEK_SET);
1066 while (tomove > DISKWRITELEN)
1067 {
1068 numwritten = (U16)write1(diskbuf,(U16)DISKWRITELEN,1,handletable[handle].Disk.file);
1069 if (numwritten != 1) {
1070 WhichDiskError(2);
1071 goto diskerror;
1072 }
1073 tomove -= DISKWRITELEN;
1074 }
1075 numwritten = (U16)write1(diskbuf,(U16)tomove,1,handletable[handle].Disk.file);
1076 if (numwritten != 1) {
1077 WhichDiskError(2);
1078 break;
1079 }
1080 success = TRUE;
1081 diskerror:
1082 break;
1083 } /* end of switch */
1084 if (!success && debugflag == 10000)
1085 DisplayHandle(handle);
1086 return (success);
1087 }
1088
1089